Merge branch 'master' into debounce_refactor
# Conflicts: # tmk_core/common/keyboard.c
This commit is contained in:
commit
2bb2977c13
3425 changed files with 216380 additions and 20651 deletions
56
tmk_core/arm_atsam.mk
Normal file
56
tmk_core/arm_atsam.mk
Normal file
|
@ -0,0 +1,56 @@
|
|||
# Hey Emacs, this is a -*- makefile -*-
|
||||
##############################################################################
|
||||
# Compiler settings
|
||||
#
|
||||
CC = arm-none-eabi-gcc
|
||||
OBJCOPY = arm-none-eabi-objcopy
|
||||
OBJDUMP = arm-none-eabi-objdump
|
||||
SIZE = arm-none-eabi-size
|
||||
AR = arm-none-eabi-ar rcs
|
||||
NM = arm-none-eabi-nm
|
||||
HEX = $(OBJCOPY) -O $(FORMAT) -R .eeprom -R .fuse -R .lock -R .signature
|
||||
EEP = $(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O $(FORMAT)
|
||||
BIN =
|
||||
|
||||
COMMON_VPATH += $(LIB_PATH)/arm_atsam/packs/atmel/SAMD51_DFP/1.0.70/include
|
||||
COMMON_VPATH += $(LIB_PATH)/arm_atsam/packs/arm/cmsis/5.0.1/CMSIS/Include
|
||||
|
||||
COMPILEFLAGS += -funsigned-char
|
||||
COMPILEFLAGS += -funsigned-bitfields
|
||||
COMPILEFLAGS += -ffunction-sections
|
||||
COMPILEFLAGS += -fshort-enums
|
||||
COMPILEFLAGS += -fno-inline-small-functions
|
||||
COMPILEFLAGS += -fno-strict-aliasing
|
||||
COMPILEFLAGS += -mfloat-abi=hard
|
||||
COMPILEFLAGS += -mfpu=fpv4-sp-d16
|
||||
COMPILEFLAGS += -mthumb
|
||||
|
||||
#ALLOW_WARNINGS = yes
|
||||
|
||||
CFLAGS += $(COMPILEFLAGS)
|
||||
|
||||
CPPFLAGS += $(COMPILEFLAGS)
|
||||
CPPFLAGS += -fno-exceptions -std=c++11
|
||||
|
||||
LDFLAGS +=-Wl,--gc-sections
|
||||
LDFLAGS += -Wl,-Map="%OUT%%PROJ_NAME%.map"
|
||||
LDFLAGS += -Wl,--start-group
|
||||
LDFLAGS += -Wl,--end-group
|
||||
LDFLAGS += --specs=rdimon.specs
|
||||
LDFLAGS += -T$(LIB_PATH)/arm_atsam/packs/atmel/SAMD51_DFP/1.0.70/gcc/gcc/samd51j18a_flash.ld
|
||||
|
||||
OPT_DEFS += -DPROTOCOL_ARM_ATSAM
|
||||
|
||||
MCUFLAGS = -mcpu=$(MCU)
|
||||
MCUFLAGS += -D__$(ARM_ATSAM)__
|
||||
|
||||
# List any extra directories to look for libraries here.
|
||||
# Each directory must be seperated by a space.
|
||||
# Use forward slashes for directory separators.
|
||||
# For a directory that has spaces, enclose it in quotes.
|
||||
EXTRALIBDIRS =
|
||||
|
||||
# Convert hex to bin.
|
||||
bin: $(BUILD_DIR)/$(TARGET).hex
|
||||
$(OBJCOPY) -Iihex -Obinary $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin
|
||||
$(COPY) $(BUILD_DIR)/$(TARGET).bin $(TARGET).bin;
|
|
@ -169,7 +169,38 @@ dfu-ee: $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).eep
|
|||
fi
|
||||
$(DFU_PROGRAMMER) $(MCU) reset
|
||||
|
||||
avrdude: $(BUILD_DIR)/$(TARGET).hex check-size cpfirmware
|
||||
dfu-split-left: $(BUILD_DIR)/$(TARGET).hex cpfirmware check-size
|
||||
until $(DFU_PROGRAMMER) $(MCU) get bootloader-version; do\
|
||||
echo "Error: Bootloader not found. Trying again in 5s." ;\
|
||||
sleep 5 ;\
|
||||
done
|
||||
if $(DFU_PROGRAMMER) --version 2>&1 | $(GREP) -q 0.7 ; then\
|
||||
$(DFU_PROGRAMMER) $(MCU) erase --force;\
|
||||
$(DFU_PROGRAMMER) $(MCU) flash --eeprom $(QUANTUM_PATH)/split_common/eeprom-lefthand.eep;\
|
||||
else\
|
||||
$(DFU_PROGRAMMER) $(MCU) erase;\
|
||||
$(DFU_PROGRAMMER) $(MCU) flash-eeprom $(QUANTUM_PATH)/split_common/eeprom-lefthand.eep;\
|
||||
fi
|
||||
$(DFU_PROGRAMMER) $(MCU) flash $(BUILD_DIR)/$(TARGET).hex
|
||||
$(DFU_PROGRAMMER) $(MCU) reset
|
||||
|
||||
dfu-split-right: $(BUILD_DIR)/$(TARGET).hex cpfirmware check-size
|
||||
until $(DFU_PROGRAMMER) $(MCU) get bootloader-version; do\
|
||||
echo "Error: Bootloader not found. Trying again in 5s." ;\
|
||||
sleep 5 ;\
|
||||
done
|
||||
if $(DFU_PROGRAMMER) --version 2>&1 | $(GREP) -q 0.7 ; then\
|
||||
$(DFU_PROGRAMMER) $(MCU) erase --force;\
|
||||
$(DFU_PROGRAMMER) $(MCU) flash --eeprom $(QUANTUM_PATH)/split_common/eeprom-righthand.eep;\
|
||||
else\
|
||||
$(DFU_PROGRAMMER) $(MCU) erase;\
|
||||
$(DFU_PROGRAMMER) $(MCU) flash-eeprom $(QUANTUM_PATH)/split_common/eeprom-rightand.eep;\
|
||||
fi
|
||||
$(DFU_PROGRAMMER) $(MCU) flash $(BUILD_DIR)/$(TARGET).hex
|
||||
$(DFU_PROGRAMMER) $(MCU) reset
|
||||
|
||||
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 AVRDUDE, AVRDUDESS, or XLoader.'; \
|
||||
else \
|
||||
|
@ -191,6 +222,15 @@ avrdude: $(BUILD_DIR)/$(TARGET).hex check-size cpfirmware
|
|||
sleep 1; \
|
||||
avrdude -p $(MCU) -c avr109 -P $$USB -U flash:w:$(BUILD_DIR)/$(TARGET).hex; \
|
||||
fi
|
||||
endef
|
||||
|
||||
avrdude: $(BUILD_DIR)/$(TARGET).hex check-size cpfirmware
|
||||
$(call EXEC_AVRDUDE)
|
||||
|
||||
avrdude-loop: $(BUILD_DIR)/$(TARGET).hex check-size cpfirmware
|
||||
while true; do \
|
||||
$(call EXEC_AVRDUDE) ; \
|
||||
done
|
||||
|
||||
# Convert hex to bin.
|
||||
bin: $(BUILD_DIR)/$(TARGET).hex
|
||||
|
@ -253,12 +293,12 @@ extcoff: $(BUILD_DIR)/$(TARGET).elf
|
|||
bootloader:
|
||||
make -C lib/lufa/Bootloaders/DFU/ clean
|
||||
printf "#ifndef QMK_KEYBOARD\n#define QMK_KEYBOARD\n\n" > lib/lufa/Bootloaders/DFU/Keyboard.h
|
||||
printf "%s\n" "`$(GREP) "MANUFACTURER" $(ALL_CONFIGS) -h | tail -1`" >> lib/lufa/Bootloaders/DFU/Keyboard.h
|
||||
printf "%s Bootloader\n" "`$(GREP) "PRODUCT" $(ALL_CONFIGS) -h | tail -1`" >> lib/lufa/Bootloaders/DFU/Keyboard.h
|
||||
printf "%s\n" "`$(GREP) "QMK_ESC_OUTPUT" $(ALL_CONFIGS) -h | tail -1`" >> lib/lufa/Bootloaders/DFU/Keyboard.h
|
||||
printf "%s\n" "`$(GREP) "QMK_ESC_INPUT" $(ALL_CONFIGS) -h | tail -1`" >> lib/lufa/Bootloaders/DFU/Keyboard.h
|
||||
printf "%s\n" "`$(GREP) "QMK_LED" $(ALL_CONFIGS) -h | tail -1`" >> lib/lufa/Bootloaders/DFU/Keyboard.h
|
||||
printf "%s\n" "`$(GREP) "QMK_SPEAKER" $(ALL_CONFIGS) -h | tail -1`" >> lib/lufa/Bootloaders/DFU/Keyboard.h
|
||||
printf "%s\n" "`$(GREP) "MANUFACTURER\s" $(ALL_CONFIGS) -h | tail -1`" >> lib/lufa/Bootloaders/DFU/Keyboard.h
|
||||
printf "%s Bootloader\n" "`$(GREP) "PRODUCT\s" $(ALL_CONFIGS) -h | tail -1 | tr -d '\r'`" >> lib/lufa/Bootloaders/DFU/Keyboard.h
|
||||
printf "%s\n" "`$(GREP) "QMK_ESC_OUTPUT\s" $(ALL_CONFIGS) -h | tail -1`" >> lib/lufa/Bootloaders/DFU/Keyboard.h
|
||||
printf "%s\n" "`$(GREP) "QMK_ESC_INPUT\s" $(ALL_CONFIGS) -h | tail -1`" >> lib/lufa/Bootloaders/DFU/Keyboard.h
|
||||
printf "%s\n" "`$(GREP) "QMK_LED\s" $(ALL_CONFIGS) -h | tail -1`" >> lib/lufa/Bootloaders/DFU/Keyboard.h
|
||||
printf "%s\n" "`$(GREP) "QMK_SPEAKER\s" $(ALL_CONFIGS) -h | tail -1`" >> lib/lufa/Bootloaders/DFU/Keyboard.h
|
||||
printf "\n#endif" >> lib/lufa/Bootloaders/DFU/Keyboard.h
|
||||
make -C lib/lufa/Bootloaders/DFU/
|
||||
printf "BootloaderDFU.hex copied to $(TARGET)_bootloader.hex\n"
|
||||
|
@ -269,4 +309,3 @@ production: $(BUILD_DIR)/$(TARGET).hex bootloader cpfirmware
|
|||
@cat $(TARGET)_bootloader.hex >> $(TARGET)_production.hex
|
||||
echo "File sizes:"
|
||||
$(SIZE) $(TARGET).hex $(TARGET)_bootloader.hex $(TARGET)_production.hex
|
||||
|
||||
|
|
|
@ -198,10 +198,13 @@ ifneq ("$(SERIAL)","")
|
|||
DFU_ARGS += -S $(SERIAL)
|
||||
endif
|
||||
|
||||
ST_LINK_ARGS ?=
|
||||
|
||||
# List any extra directories to look for libraries here.
|
||||
EXTRALIBDIRS = $(RULESPATH)/ld
|
||||
|
||||
DFU_UTIL ?= dfu-util
|
||||
ST_LINK_CLI ?= st-link_cli
|
||||
|
||||
# Generate a .qmk for the QMK-FF
|
||||
qmk: $(BUILD_DIR)/$(TARGET).bin
|
||||
|
@ -230,5 +233,26 @@ qmk: $(BUILD_DIR)/$(TARGET).bin
|
|||
dfu-util: $(BUILD_DIR)/$(TARGET).bin cpfirmware sizeafter
|
||||
$(DFU_UTIL) $(DFU_ARGS) -D $(BUILD_DIR)/$(TARGET).bin
|
||||
|
||||
|
||||
ifneq ($(strip $(TIME_DELAY)),)
|
||||
TIME_DELAY = $(strip $(TIME_DELAY))
|
||||
else
|
||||
TIME_DELAY = 10
|
||||
endif
|
||||
dfu-util-wait: $(BUILD_DIR)/$(TARGET).bin cpfirmware sizeafter
|
||||
echo "Preparing to flash firmware. Please enter bootloader now..." ;\
|
||||
COUNTDOWN=$(TIME_DELAY) ;\
|
||||
while [[ $$COUNTDOWN -ge 1 ]] ; do \
|
||||
echo "Flashing in $$COUNTDOWN ..."; \
|
||||
sleep 1 ;\
|
||||
((COUNTDOWN = COUNTDOWN - 1)) ; \
|
||||
done; \
|
||||
echo "Flashing $(TARGET).bin" ;\
|
||||
sleep 1 ;\
|
||||
$(DFU_UTIL) $(DFU_ARGS) -D $(BUILD_DIR)/$(TARGET).bin
|
||||
|
||||
st-link-cli: $(BUILD_DIR)/$(TARGET).hex sizeafter
|
||||
$(ST_LINK_CLI) $(ST_LINK_ARGS) -q -c SWD -p $(BUILD_DIR)/$(TARGET).hex -Rst
|
||||
|
||||
bin: $(BUILD_DIR)/$(TARGET).bin sizeafter
|
||||
$(COPY) $(BUILD_DIR)/$(TARGET).bin $(TARGET).bin;
|
||||
|
|
|
@ -4,6 +4,8 @@ ifeq ($(PLATFORM),AVR)
|
|||
PLATFORM_COMMON_DIR = $(COMMON_DIR)/avr
|
||||
else ifeq ($(PLATFORM),CHIBIOS)
|
||||
PLATFORM_COMMON_DIR = $(COMMON_DIR)/chibios
|
||||
else ifeq ($(PLATFORM),ARM_ATSAM)
|
||||
PLATFORM_COMMON_DIR = $(COMMON_DIR)/arm_atsam
|
||||
else
|
||||
PLATFORM_COMMON_DIR = $(COMMON_DIR)/test
|
||||
endif
|
||||
|
@ -31,12 +33,31 @@ endif
|
|||
|
||||
ifeq ($(PLATFORM),CHIBIOS)
|
||||
TMK_COMMON_SRC += $(PLATFORM_COMMON_DIR)/printf.c
|
||||
TMK_COMMON_SRC += $(PLATFORM_COMMON_DIR)/eeprom.c
|
||||
ifeq ($(MCU_SERIES), STM32F3xx)
|
||||
TMK_COMMON_SRC += $(PLATFORM_COMMON_DIR)/eeprom_stm32.c
|
||||
TMK_COMMON_SRC += $(PLATFORM_COMMON_DIR)/flash_stm32.c
|
||||
TMK_COMMON_DEFS += -DEEPROM_EMU_STM32F303xC
|
||||
TMK_COMMON_DEFS += -DSTM32_EEPROM_ENABLE
|
||||
else ifeq ($(MCU_SERIES), STM32F1xx)
|
||||
TMK_COMMON_SRC += $(PLATFORM_COMMON_DIR)/eeprom_stm32.c
|
||||
TMK_COMMON_SRC += $(PLATFORM_COMMON_DIR)/flash_stm32.c
|
||||
TMK_COMMON_DEFS += -DEEPROM_EMU_STM32F103xB
|
||||
TMK_COMMON_DEFS += -DSTM32_EEPROM_ENABLE
|
||||
else
|
||||
TMK_COMMON_SRC += $(PLATFORM_COMMON_DIR)/eeprom_teensy.c
|
||||
endif
|
||||
ifeq ($(strip $(AUTO_SHIFT_ENABLE)), yes)
|
||||
TMK_COMMON_SRC += $(CHIBIOS)/os/various/syscalls.c
|
||||
else ifeq ($(strip $(TERMINAL_ENABLE)), yes)
|
||||
TMK_COMMON_SRC += $(CHIBIOS)/os/various/syscalls.c
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM),ARM_ATSAM)
|
||||
TMK_COMMON_SRC += $(PLATFORM_COMMON_DIR)/printf.c
|
||||
TMK_COMMON_SRC += $(PLATFORM_COMMON_DIR)/eeprom.c
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM),TEST)
|
||||
TMK_COMMON_SRC += $(PLATFORM_COMMON_DIR)/eeprom.c
|
||||
endif
|
||||
|
@ -57,22 +78,50 @@ else # default algorithm
|
|||
endif
|
||||
|
||||
# Option modules
|
||||
ifeq ($(strip $(BOOTMAGIC_ENABLE)), yes)
|
||||
BOOTMAGIC_ENABLE ?= no
|
||||
VALID_MAGIC_TYPES := yes full lite
|
||||
ifneq ($(strip $(BOOTMAGIC_ENABLE)), no)
|
||||
ifeq ($(filter $(BOOTMAGIC_ENABLE),$(VALID_MAGIC_TYPES)),)
|
||||
$(error BOOTMAGIC_ENABLE="$(BOOTMAGIC_ENABLE)" is not a valid type of magic)
|
||||
endif
|
||||
ifeq ($(strip $(BOOTMAGIC_ENABLE)), lite)
|
||||
TMK_COMMON_DEFS += -DBOOTMAGIC_LITE
|
||||
TMK_COMMON_DEFS += -DMAGIC_ENABLE
|
||||
TMK_COMMON_SRC += $(COMMON_DIR)/magic.c
|
||||
else
|
||||
TMK_COMMON_DEFS += -DBOOTMAGIC_ENABLE
|
||||
TMK_COMMON_SRC += $(COMMON_DIR)/bootmagic.c
|
||||
endif
|
||||
else
|
||||
TMK_COMMON_DEFS += -DMAGIC_ENABLE
|
||||
TMK_COMMON_SRC += $(COMMON_DIR)/magic.c
|
||||
endif
|
||||
|
||||
SHARED_EP_ENABLE = no
|
||||
MOUSE_SHARED_EP ?= yes
|
||||
ifeq ($(strip $(KEYBOARD_SHARED_EP)), yes)
|
||||
TMK_COMMON_DEFS += -DKEYBOARD_SHARED_EP
|
||||
SHARED_EP_ENABLE = yes
|
||||
# With the current usb_descriptor.c code,
|
||||
# you can't share kbd without sharing mouse;
|
||||
# that would be a very unexpected use case anyway
|
||||
MOUSE_SHARED_EP = yes
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(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
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(EXTRAKEY_ENABLE)), yes)
|
||||
TMK_COMMON_DEFS += -DEXTRAKEY_ENABLE
|
||||
SHARED_EP_ENABLE = yes
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(RAW_ENABLE)), yes)
|
||||
|
@ -93,6 +142,7 @@ endif
|
|||
|
||||
ifeq ($(strip $(NKRO_ENABLE)), yes)
|
||||
TMK_COMMON_DEFS += -DNKRO_ENABLE
|
||||
SHARED_EP_ENABLE = yes
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(USB_6KRO_ENABLE)), yes)
|
||||
|
@ -164,6 +214,10 @@ ifeq ($(strip $(KEYMAP_SECTION_ENABLE)), yes)
|
|||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(SHARED_EP_ENABLE)), yes)
|
||||
TMK_COMMON_DEFS += -DSHARED_EP_ENABLE
|
||||
endif
|
||||
|
||||
# Bootloader address
|
||||
ifdef STM32_BOOTLOADER_ADDRESS
|
||||
TMK_COMMON_DEFS += -DSTM32_BOOTLOADER_ADDRESS=$(STM32_BOOTLOADER_ADDRESS)
|
||||
|
|
|
@ -120,7 +120,7 @@ void process_hand_swap(keyevent_t *event) {
|
|||
}
|
||||
#endif
|
||||
|
||||
#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
|
||||
#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE)
|
||||
bool disable_action_cache = false;
|
||||
|
||||
void process_record_nocache(keyrecord_t *record)
|
||||
|
@ -773,6 +773,13 @@ void register_code(uint8_t code)
|
|||
else if IS_CONSUMER(code) {
|
||||
host_consumer_send(KEYCODE2CONSUMER(code));
|
||||
}
|
||||
|
||||
#ifdef MOUSEKEY_ENABLE
|
||||
else if IS_MOUSEKEY(code) {
|
||||
mousekey_on(code);
|
||||
mousekey_send();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/** \brief Utilities for actions. (FIXME: Needs better description)
|
||||
|
@ -832,6 +839,24 @@ void unregister_code(uint8_t code)
|
|||
else if IS_CONSUMER(code) {
|
||||
host_consumer_send(0);
|
||||
}
|
||||
#ifdef MOUSEKEY_ENABLE
|
||||
else if IS_MOUSEKEY(code) {
|
||||
mousekey_off(code);
|
||||
mousekey_send();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/** \brief Utilities for actions. (FIXME: Needs better description)
|
||||
*
|
||||
* FIXME: Needs documentation.
|
||||
*/
|
||||
void tap_code(uint8_t code) {
|
||||
register_code(code);
|
||||
#if TAP_CODE_DELAY > 0
|
||||
wait_ms(TAP_CODE_DELAY);
|
||||
#endif
|
||||
unregister_code(code);
|
||||
}
|
||||
|
||||
/** \brief Utilities for actions. (FIXME: Needs better description)
|
||||
|
@ -873,10 +898,19 @@ void clear_keyboard(void)
|
|||
* FIXME: Needs documentation.
|
||||
*/
|
||||
void clear_keyboard_but_mods(void)
|
||||
{
|
||||
clear_keys();
|
||||
clear_keyboard_but_mods_and_keys();
|
||||
}
|
||||
|
||||
/** \brief Utilities for actions. (FIXME: Needs better description)
|
||||
*
|
||||
* FIXME: Needs documentation.
|
||||
*/
|
||||
void clear_keyboard_but_mods_and_keys()
|
||||
{
|
||||
clear_weak_mods();
|
||||
clear_macro_mods();
|
||||
clear_keys();
|
||||
send_keyboard_report();
|
||||
#ifdef MOUSEKEY_ENABLE
|
||||
mousekey_clear();
|
||||
|
|
|
@ -62,7 +62,7 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt);
|
|||
bool process_record_quantum(keyrecord_t *record);
|
||||
|
||||
/* Utilities for actions. */
|
||||
#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
|
||||
#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE)
|
||||
extern bool disable_action_cache;
|
||||
#endif
|
||||
|
||||
|
@ -88,11 +88,13 @@ void process_record(keyrecord_t *record);
|
|||
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 register_mods(uint8_t mods);
|
||||
void unregister_mods(uint8_t mods);
|
||||
//void set_mods(uint8_t mods);
|
||||
void clear_keyboard(void);
|
||||
void clear_keyboard_but_mods(void);
|
||||
void clear_keyboard_but_mods_and_keys(void);
|
||||
void layer_switch(uint8_t new_layer);
|
||||
bool is_tap_key(keypos_t key);
|
||||
|
||||
|
|
|
@ -15,13 +15,22 @@
|
|||
*/
|
||||
uint32_t default_layer_state = 0;
|
||||
|
||||
/** \brief Default Layer State Set At user Level
|
||||
*
|
||||
* FIXME: Needs docs
|
||||
*/
|
||||
__attribute__((weak))
|
||||
uint32_t default_layer_state_set_user(uint32_t state) {
|
||||
return state;
|
||||
}
|
||||
|
||||
/** \brief Default Layer State Set At Keyboard Level
|
||||
*
|
||||
* FIXME: Needs docs
|
||||
*/
|
||||
__attribute__((weak))
|
||||
uint32_t default_layer_state_set_kb(uint32_t state) {
|
||||
return state;
|
||||
return default_layer_state_set_user(state);
|
||||
}
|
||||
|
||||
/** \brief Default Layer State Set
|
||||
|
@ -35,7 +44,11 @@ static void default_layer_state_set(uint32_t state)
|
|||
default_layer_debug(); debug(" to ");
|
||||
default_layer_state = state;
|
||||
default_layer_debug(); debug("\n");
|
||||
#ifdef STRICT_LAYER_RELEASE
|
||||
clear_keyboard_but_mods(); // To avoid stuck keys
|
||||
#else
|
||||
clear_keyboard_but_mods_and_keys(); // Don't reset held keys
|
||||
#endif
|
||||
}
|
||||
|
||||
/** \brief Default Layer Print
|
||||
|
@ -118,7 +131,11 @@ void layer_state_set(uint32_t state)
|
|||
layer_debug(); dprint(" to ");
|
||||
layer_state = state;
|
||||
layer_debug(); dprintln();
|
||||
#ifdef STRICT_LAYER_RELEASE
|
||||
clear_keyboard_but_mods(); // To avoid stuck keys
|
||||
#else
|
||||
clear_keyboard_but_mods_and_keys(); // Don't reset held keys
|
||||
#endif
|
||||
}
|
||||
|
||||
/** \brief Layer clear
|
||||
|
@ -219,7 +236,7 @@ void layer_debug(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
|
||||
#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE)
|
||||
uint8_t source_layers_cache[(MATRIX_ROWS * MATRIX_COLS + 7) / 8][MAX_LAYER_BITS] = {{0}};
|
||||
|
||||
void update_source_layers_cache(keypos_t key, uint8_t layer)
|
||||
|
@ -263,7 +280,7 @@ uint8_t read_source_layers_cache(keypos_t key)
|
|||
*/
|
||||
action_t store_or_get_action(bool pressed, keypos_t key)
|
||||
{
|
||||
#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
|
||||
#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE)
|
||||
if (disable_action_cache) {
|
||||
return layer_switch_get_action(key);
|
||||
}
|
||||
|
|
|
@ -31,6 +31,8 @@ void default_layer_set(uint32_t state);
|
|||
|
||||
__attribute__((weak))
|
||||
uint32_t default_layer_state_set_kb(uint32_t state);
|
||||
__attribute__((weak))
|
||||
uint32_t default_layer_state_set_user(uint32_t state);
|
||||
|
||||
#ifndef NO_ACTION_LAYER
|
||||
/* bitwise operation */
|
||||
|
@ -80,15 +82,13 @@ void layer_xor(uint32_t state);
|
|||
#define layer_or(state)
|
||||
#define layer_and(state)
|
||||
#define layer_xor(state)
|
||||
|
||||
__attribute__((weak))
|
||||
uint32_t layer_state_set_user(uint32_t state);
|
||||
__attribute__((weak))
|
||||
uint32_t layer_state_set_kb(uint32_t state);
|
||||
#endif
|
||||
|
||||
uint32_t layer_state_set_user(uint32_t state);
|
||||
uint32_t layer_state_set_kb(uint32_t state);
|
||||
|
||||
/* pressed actions cache */
|
||||
#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
|
||||
#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE)
|
||||
/* The number of bits needed to represent the layer number: log2(32). */
|
||||
#define MAX_LAYER_BITS 5
|
||||
void update_source_layers_cache(keypos_t key, uint8_t layer);
|
||||
|
|
51
tmk_core/common/arm_atsam/bootloader.c
Normal file
51
tmk_core/common/arm_atsam/bootloader.c
Normal file
|
@ -0,0 +1,51 @@
|
|||
/* Copyright 2017 Fred Sundvik
|
||||
*
|
||||
* 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 "bootloader.h"
|
||||
#include "samd51j18a.h"
|
||||
#include "md_bootloader.h"
|
||||
|
||||
//Set watchdog timer to reset. Directs the bootloader to stay in programming mode.
|
||||
void bootloader_jump(void) {
|
||||
#ifdef KEYBOARD_massdrop_ctrl
|
||||
//CTRL keyboards released with bootloader version below must use RAM method. Otherwise use WDT method.
|
||||
uint8_t ver_ram_method[] = "v2.18Jun 22 2018 17:28:08"; //The version to match (NULL terminated by compiler)
|
||||
uint8_t *ver_check = ver_ram_method; //Pointer to version match string for traversal
|
||||
uint8_t *ver_rom = (uint8_t *)0x21A0; //Pointer to address in ROM where this specific bootloader version would exist
|
||||
|
||||
while (*ver_check && *ver_rom == *ver_check) { //While there are check version characters to match and bootloader's version matches check's version
|
||||
ver_check++; //Move check version pointer to next character
|
||||
ver_rom++; //Move ROM version pointer to next character
|
||||
}
|
||||
|
||||
if (!*ver_check) { //If check version pointer is NULL, all characters have matched
|
||||
*MAGIC_ADDR = BOOTLOADER_MAGIC; //Set magic number into RAM
|
||||
NVIC_SystemReset(); //Perform system reset
|
||||
while (1) {} //Won't get here
|
||||
}
|
||||
#endif
|
||||
|
||||
WDT->CTRLA.bit.ENABLE = 0;
|
||||
while (WDT->SYNCBUSY.bit.ENABLE) {}
|
||||
while (WDT->CTRLA.bit.ENABLE) {}
|
||||
WDT->CONFIG.bit.WINDOW = 0;
|
||||
WDT->CONFIG.bit.PER = 0;
|
||||
WDT->EWCTRL.bit.EWOFFSET = 0;
|
||||
WDT->CTRLA.bit.ENABLE = 1;
|
||||
while (WDT->SYNCBUSY.bit.ENABLE) {}
|
||||
while (!WDT->CTRLA.bit.ENABLE) {}
|
||||
while (1) {} //Wait on timeout
|
||||
}
|
98
tmk_core/common/arm_atsam/eeprom.c
Normal file
98
tmk_core/common/arm_atsam/eeprom.c
Normal file
|
@ -0,0 +1,98 @@
|
|||
/* Copyright 2017 Fred Sundvik
|
||||
*
|
||||
* 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 "eeprom.h"
|
||||
|
||||
#define EEPROM_SIZE 32
|
||||
|
||||
static uint8_t buffer[EEPROM_SIZE];
|
||||
|
||||
uint8_t eeprom_read_byte(const uint8_t *addr) {
|
||||
uintptr_t offset = (uintptr_t)addr;
|
||||
return buffer[offset];
|
||||
}
|
||||
|
||||
void eeprom_write_byte(uint8_t *addr, uint8_t value) {
|
||||
uintptr_t offset = (uintptr_t)addr;
|
||||
buffer[offset] = value;
|
||||
}
|
||||
|
||||
uint16_t eeprom_read_word(const uint16_t *addr) {
|
||||
const uint8_t *p = (const uint8_t *)addr;
|
||||
return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8);
|
||||
}
|
||||
|
||||
uint32_t eeprom_read_dword(const uint32_t *addr) {
|
||||
const uint8_t *p = (const uint8_t *)addr;
|
||||
return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8)
|
||||
| (eeprom_read_byte(p+2) << 16) | (eeprom_read_byte(p+3) << 24);
|
||||
}
|
||||
|
||||
void eeprom_read_block(void *buf, const void *addr, uint32_t len) {
|
||||
const uint8_t *p = (const uint8_t *)addr;
|
||||
uint8_t *dest = (uint8_t *)buf;
|
||||
while (len--) {
|
||||
*dest++ = eeprom_read_byte(p++);
|
||||
}
|
||||
}
|
||||
|
||||
void eeprom_write_word(uint16_t *addr, uint16_t value) {
|
||||
uint8_t *p = (uint8_t *)addr;
|
||||
eeprom_write_byte(p++, value);
|
||||
eeprom_write_byte(p, value >> 8);
|
||||
}
|
||||
|
||||
void eeprom_write_dword(uint32_t *addr, uint32_t value) {
|
||||
uint8_t *p = (uint8_t *)addr;
|
||||
eeprom_write_byte(p++, value);
|
||||
eeprom_write_byte(p++, value >> 8);
|
||||
eeprom_write_byte(p++, value >> 16);
|
||||
eeprom_write_byte(p, value >> 24);
|
||||
}
|
||||
|
||||
void eeprom_write_block(const void *buf, void *addr, uint32_t len) {
|
||||
uint8_t *p = (uint8_t *)addr;
|
||||
const uint8_t *src = (const uint8_t *)buf;
|
||||
while (len--) {
|
||||
eeprom_write_byte(p++, *src++);
|
||||
}
|
||||
}
|
||||
|
||||
void eeprom_update_byte(uint8_t *addr, uint8_t value) {
|
||||
eeprom_write_byte(addr, value);
|
||||
}
|
||||
|
||||
void eeprom_update_word(uint16_t *addr, uint16_t value) {
|
||||
uint8_t *p = (uint8_t *)addr;
|
||||
eeprom_write_byte(p++, value);
|
||||
eeprom_write_byte(p, value >> 8);
|
||||
}
|
||||
|
||||
void eeprom_update_dword(uint32_t *addr, uint32_t value) {
|
||||
uint8_t *p = (uint8_t *)addr;
|
||||
eeprom_write_byte(p++, value);
|
||||
eeprom_write_byte(p++, value >> 8);
|
||||
eeprom_write_byte(p++, value >> 16);
|
||||
eeprom_write_byte(p, value >> 24);
|
||||
}
|
||||
|
||||
void eeprom_update_block(const void *buf, void *addr, uint32_t len) {
|
||||
uint8_t *p = (uint8_t *)addr;
|
||||
const uint8_t *src = (const uint8_t *)buf;
|
||||
while (len--) {
|
||||
eeprom_write_byte(p++, *src++);
|
||||
}
|
||||
}
|
66
tmk_core/common/arm_atsam/printf.c
Normal file
66
tmk_core/common/arm_atsam/printf.c
Normal file
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
Copyright 2018 Massdrop Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef CONSOLE_ENABLE
|
||||
|
||||
#include "samd51j18a.h"
|
||||
#include "arm_atsam_protocol.h"
|
||||
#include "printf.h"
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
void console_printf(char *fmt, ...) {
|
||||
while (udi_hid_con_b_report_trans_ongoing) {} //Wait for any previous transfers to complete
|
||||
|
||||
static char console_printbuf[CONSOLE_PRINTBUF_SIZE]; //Print and send buffer
|
||||
va_list va;
|
||||
int result;
|
||||
|
||||
va_start(va, fmt);
|
||||
result = vsnprintf(console_printbuf, CONSOLE_PRINTBUF_SIZE, fmt, va);
|
||||
va_end(va);
|
||||
|
||||
uint32_t irqflags;
|
||||
char *pconbuf = console_printbuf; //Pointer to start send from
|
||||
int send_out = CONSOLE_EPSIZE; //Bytes to send per transfer
|
||||
|
||||
while (result > 0) { //While not error and bytes remain
|
||||
while (udi_hid_con_b_report_trans_ongoing) {} //Wait for any previous transfers to complete
|
||||
|
||||
irqflags = __get_PRIMASK();
|
||||
__disable_irq();
|
||||
__DMB();
|
||||
|
||||
if (result < CONSOLE_EPSIZE) { //If remaining bytes are less than console epsize
|
||||
memset(udi_hid_con_report, 0, CONSOLE_EPSIZE); //Clear the buffer
|
||||
send_out = result; //Send remaining size
|
||||
}
|
||||
|
||||
memcpy(udi_hid_con_report, pconbuf, send_out); //Copy data into the send buffer
|
||||
|
||||
udi_hid_con_b_report_valid = 1; //Set report valid
|
||||
udi_hid_con_send_report(); //Send report
|
||||
|
||||
__DMB();
|
||||
__set_PRIMASK(irqflags);
|
||||
|
||||
result -= send_out; //Decrement result by bytes sent
|
||||
pconbuf += send_out; //Increment buffer point by bytes sent
|
||||
}
|
||||
}
|
||||
|
||||
#endif //CONSOLE_ENABLE
|
11
tmk_core/common/arm_atsam/printf.h
Normal file
11
tmk_core/common/arm_atsam/printf.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#ifndef _PRINTF_H_
|
||||
#define _PRINTF_H_
|
||||
|
||||
#define CONSOLE_PRINTBUF_SIZE 512
|
||||
|
||||
void console_printf(char *fmt, ...);
|
||||
|
||||
#define __xprintf console_printf
|
||||
|
||||
#endif //_PRINTF_H_
|
||||
|
85
tmk_core/common/arm_atsam/suspend.c
Normal file
85
tmk_core/common/arm_atsam/suspend.c
Normal file
|
@ -0,0 +1,85 @@
|
|||
#include "matrix.h"
|
||||
#include "i2c_master.h"
|
||||
#include "led_matrix.h"
|
||||
#include "suspend.h"
|
||||
|
||||
/** \brief Suspend idle
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
void suspend_idle(uint8_t time) {
|
||||
/* Note: Not used anywhere currently */
|
||||
}
|
||||
|
||||
/** \brief Run user level Power down
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
__attribute__ ((weak))
|
||||
void suspend_power_down_user (void) {
|
||||
|
||||
}
|
||||
|
||||
/** \brief Run keyboard level Power down
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
__attribute__ ((weak))
|
||||
void suspend_power_down_kb(void) {
|
||||
suspend_power_down_user();
|
||||
}
|
||||
|
||||
/** \brief Suspend power down
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
void suspend_power_down(void)
|
||||
{
|
||||
I2C3733_Control_Set(0); //Disable LED driver
|
||||
|
||||
suspend_power_down_kb();
|
||||
}
|
||||
|
||||
__attribute__ ((weak)) void matrix_power_up(void) {}
|
||||
__attribute__ ((weak)) void matrix_power_down(void) {}
|
||||
bool suspend_wakeup_condition(void) {
|
||||
matrix_power_up();
|
||||
matrix_scan();
|
||||
matrix_power_down();
|
||||
for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
|
||||
if (matrix_get_row(r)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** \brief run user level code immediately after wakeup
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
__attribute__ ((weak))
|
||||
void suspend_wakeup_init_user(void) {
|
||||
|
||||
}
|
||||
|
||||
/** \brief run keyboard level code immediately after wakeup
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
__attribute__ ((weak))
|
||||
void suspend_wakeup_init_kb(void) {
|
||||
suspend_wakeup_init_user();
|
||||
}
|
||||
|
||||
/** \brief run immediately after wakeup
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
void suspend_wakeup_init(void) {
|
||||
/* If LEDs are set to enabled, enable the hardware */
|
||||
if (led_enabled) {
|
||||
I2C3733_Control_Set(1);
|
||||
}
|
||||
|
||||
suspend_wakeup_init_kb();
|
||||
}
|
||||
|
59
tmk_core/common/arm_atsam/timer.c
Normal file
59
tmk_core/common/arm_atsam/timer.c
Normal file
|
@ -0,0 +1,59 @@
|
|||
#include "samd51j18a.h"
|
||||
#include "timer.h"
|
||||
#include "tmk_core/protocol/arm_atsam/clks.h"
|
||||
|
||||
void set_time(uint64_t tset)
|
||||
{
|
||||
ms_clk = tset;
|
||||
}
|
||||
|
||||
void timer_init(void)
|
||||
{
|
||||
ms_clk = 0;
|
||||
}
|
||||
|
||||
uint16_t timer_read(void)
|
||||
{
|
||||
return (uint16_t)ms_clk;
|
||||
}
|
||||
|
||||
uint32_t timer_read32(void)
|
||||
{
|
||||
return (uint32_t)ms_clk;
|
||||
}
|
||||
|
||||
uint64_t timer_read64(void)
|
||||
{
|
||||
return ms_clk;
|
||||
}
|
||||
|
||||
uint16_t timer_elapsed(uint16_t tlast)
|
||||
{
|
||||
return TIMER_DIFF_16(timer_read(), tlast);
|
||||
}
|
||||
|
||||
uint32_t timer_elapsed32(uint32_t tlast)
|
||||
{
|
||||
return TIMER_DIFF_32(timer_read32(), tlast);
|
||||
}
|
||||
|
||||
uint32_t timer_elapsed64(uint32_t tlast)
|
||||
{
|
||||
uint64_t tnow = timer_read64();
|
||||
return (tnow >= tlast ? tnow - tlast : UINT64_MAX - tlast + tnow);
|
||||
}
|
||||
|
||||
void timer_clear(void)
|
||||
{
|
||||
ms_clk = 0;
|
||||
}
|
||||
|
||||
void wait_ms(uint64_t msec)
|
||||
{
|
||||
CLK_delay_ms(msec);
|
||||
}
|
||||
|
||||
void wait_us(uint16_t usec)
|
||||
{
|
||||
CLK_delay_us(usec);
|
||||
}
|
|
@ -10,6 +10,7 @@
|
|||
#include "timer.h"
|
||||
#include "led.h"
|
||||
#include "host.h"
|
||||
#include "rgblight_reconfig.h"
|
||||
|
||||
#ifdef PROTOCOL_LUFA
|
||||
#include "lufa.h"
|
||||
|
@ -55,6 +56,24 @@ void suspend_idle(uint8_t time)
|
|||
sleep_disable();
|
||||
}
|
||||
|
||||
|
||||
// TODO: This needs some cleanup
|
||||
|
||||
/** \brief Run keyboard level Power down
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
__attribute__ ((weak))
|
||||
void suspend_power_down_user (void) { }
|
||||
/** \brief Run keyboard level Power down
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
__attribute__ ((weak))
|
||||
void suspend_power_down_kb(void) {
|
||||
suspend_power_down_user();
|
||||
}
|
||||
|
||||
#ifndef NO_SUSPEND_POWER_DOWN
|
||||
/** \brief Power down MCU with watchdog timer
|
||||
*
|
||||
|
@ -72,21 +91,6 @@ void suspend_idle(uint8_t time)
|
|||
*/
|
||||
static uint8_t wdt_timeout = 0;
|
||||
|
||||
/** \brief Run keyboard level Power down
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
__attribute__ ((weak))
|
||||
void suspend_power_down_user (void) { }
|
||||
/** \brief Run keyboard level Power down
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
__attribute__ ((weak))
|
||||
void suspend_power_down_kb(void) {
|
||||
suspend_power_down_user();
|
||||
}
|
||||
|
||||
/** \brief Power down
|
||||
*
|
||||
* FIXME: needs doc
|
||||
|
@ -143,6 +147,8 @@ static void power_down(uint8_t wdto)
|
|||
*/
|
||||
void suspend_power_down(void)
|
||||
{
|
||||
suspend_power_down_kb();
|
||||
|
||||
#ifndef NO_SUSPEND_POWER_DOWN
|
||||
power_down(WDTO_15MS);
|
||||
#endif
|
||||
|
@ -189,12 +195,15 @@ void suspend_wakeup_init(void)
|
|||
#endif
|
||||
led_set(host_keyboard_leds());
|
||||
#if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE)
|
||||
#ifdef BOOTLOADER_TEENSY
|
||||
wait_ms(10);
|
||||
#endif
|
||||
rgblight_enable_noeeprom();
|
||||
#ifdef RGBLIGHT_ANIMATIONS
|
||||
rgblight_timer_enable();
|
||||
#endif
|
||||
#endif
|
||||
suspend_wakeup_init_kb();
|
||||
suspend_wakeup_init_kb();
|
||||
}
|
||||
|
||||
#ifndef NO_SUSPEND_POWER_DOWN
|
||||
|
|
|
@ -76,12 +76,51 @@ void backlight_decrease(void)
|
|||
*/
|
||||
void backlight_toggle(void)
|
||||
{
|
||||
backlight_config.enable ^= 1;
|
||||
if (backlight_config.raw == 1) // enabled but level = 0
|
||||
backlight_config.level = 1;
|
||||
eeconfig_update_backlight(backlight_config.raw);
|
||||
dprintf("backlight toggle: %u\n", backlight_config.enable);
|
||||
backlight_set(backlight_config.enable ? backlight_config.level : 0);
|
||||
bool enabled = backlight_config.enable;
|
||||
dprintf("backlight toggle: %u\n", enabled);
|
||||
if (enabled)
|
||||
backlight_disable();
|
||||
else
|
||||
backlight_enable();
|
||||
}
|
||||
|
||||
/** \brief Enable backlight
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
void backlight_enable(void)
|
||||
{
|
||||
if (backlight_config.enable) return; // do nothing if backlight is already on
|
||||
|
||||
backlight_config.enable = true;
|
||||
if (backlight_config.raw == 1) // enabled but level == 0
|
||||
backlight_config.level = 1;
|
||||
eeconfig_update_backlight(backlight_config.raw);
|
||||
dprintf("backlight enable\n");
|
||||
backlight_set(backlight_config.level);
|
||||
}
|
||||
|
||||
/** /brief Disable backlight
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
void backlight_disable(void)
|
||||
{
|
||||
if (!backlight_config.enable) return; // do nothing if backlight is already off
|
||||
|
||||
backlight_config.enable = false;
|
||||
eeconfig_update_backlight(backlight_config.raw);
|
||||
dprintf("backlight disable\n");
|
||||
backlight_set(0);
|
||||
}
|
||||
|
||||
/** /brief Get the backlight status
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
bool is_backlight_enabled(void)
|
||||
{
|
||||
return backlight_config.enable;
|
||||
}
|
||||
|
||||
/** \brief Backlight step through levels
|
||||
|
|
|
@ -15,8 +15,7 @@ You should have received a copy of the GNU General Public License
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef BACKLIGHT_H
|
||||
#define BACKLIGHT_H
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
@ -33,9 +32,11 @@ void backlight_init(void);
|
|||
void backlight_increase(void);
|
||||
void backlight_decrease(void);
|
||||
void backlight_toggle(void);
|
||||
void backlight_enable(void);
|
||||
void backlight_disable(void);
|
||||
bool is_backlight_enabled(void);
|
||||
void backlight_step(void);
|
||||
void backlight_set(uint8_t level);
|
||||
void backlight_level(uint8_t level);
|
||||
uint8_t get_backlight_level(void);
|
||||
|
||||
#endif
|
||||
|
|
673
tmk_core/common/chibios/eeprom_stm32.c
Executable file
673
tmk_core/common/chibios/eeprom_stm32.c
Executable file
|
@ -0,0 +1,673 @@
|
|||
/*
|
||||
* This software is experimental and a work in progress.
|
||||
* Under no circumstances should these files be used in relation to any critical system(s).
|
||||
* Use of these files is at your own risk.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This files are free to use from https://github.com/rogerclarkmelbourne/Arduino_STM32 and
|
||||
* https://github.com/leaflabs/libmaple
|
||||
*
|
||||
* Modifications for QMK and STM32F303 by Yiancar
|
||||
*/
|
||||
|
||||
#include "eeprom_stm32.h"
|
||||
|
||||
FLASH_Status EE_ErasePage(uint32_t);
|
||||
|
||||
uint16_t EE_CheckPage(uint32_t, uint16_t);
|
||||
uint16_t EE_CheckErasePage(uint32_t, uint16_t);
|
||||
uint16_t EE_Format(void);
|
||||
uint32_t EE_FindValidPage(void);
|
||||
uint16_t EE_GetVariablesCount(uint32_t, uint16_t);
|
||||
uint16_t EE_PageTransfer(uint32_t, uint32_t, uint16_t);
|
||||
uint16_t EE_VerifyPageFullWriteVariable(uint16_t, uint16_t);
|
||||
|
||||
uint32_t PageBase0 = EEPROM_PAGE0_BASE;
|
||||
uint32_t PageBase1 = EEPROM_PAGE1_BASE;
|
||||
uint32_t PageSize = EEPROM_PAGE_SIZE;
|
||||
uint16_t Status = EEPROM_NOT_INIT;
|
||||
|
||||
// See http://www.st.com/web/en/resource/technical/document/application_note/CD00165693.pdf
|
||||
|
||||
/**
|
||||
* @brief Check page for blank
|
||||
* @param page base address
|
||||
* @retval Success or error
|
||||
* EEPROM_BAD_FLASH: page not empty after erase
|
||||
* EEPROM_OK: page blank
|
||||
*/
|
||||
uint16_t EE_CheckPage(uint32_t pageBase, uint16_t status)
|
||||
{
|
||||
uint32_t pageEnd = pageBase + (uint32_t)PageSize;
|
||||
|
||||
// Page Status not EEPROM_ERASED and not a "state"
|
||||
if ((*(__IO uint16_t*)pageBase) != EEPROM_ERASED && (*(__IO uint16_t*)pageBase) != status)
|
||||
return EEPROM_BAD_FLASH;
|
||||
for(pageBase += 4; pageBase < pageEnd; pageBase += 4)
|
||||
if ((*(__IO uint32_t*)pageBase) != 0xFFFFFFFF) // Verify if slot is empty
|
||||
return EEPROM_BAD_FLASH;
|
||||
return EEPROM_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Erase page with increment erase counter (page + 2)
|
||||
* @param page base address
|
||||
* @retval Success or error
|
||||
* FLASH_COMPLETE: success erase
|
||||
* - Flash error code: on write Flash error
|
||||
*/
|
||||
FLASH_Status EE_ErasePage(uint32_t pageBase)
|
||||
{
|
||||
FLASH_Status FlashStatus;
|
||||
uint16_t data = (*(__IO uint16_t*)(pageBase));
|
||||
if ((data == EEPROM_ERASED) || (data == EEPROM_VALID_PAGE) || (data == EEPROM_RECEIVE_DATA))
|
||||
data = (*(__IO uint16_t*)(pageBase + 2)) + 1;
|
||||
else
|
||||
data = 0;
|
||||
|
||||
FlashStatus = FLASH_ErasePage(pageBase);
|
||||
if (FlashStatus == FLASH_COMPLETE)
|
||||
FlashStatus = FLASH_ProgramHalfWord(pageBase + 2, data);
|
||||
|
||||
return FlashStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check page for blank and erase it
|
||||
* @param page base address
|
||||
* @retval Success or error
|
||||
* - Flash error code: on write Flash error
|
||||
* - EEPROM_BAD_FLASH: page not empty after erase
|
||||
* - EEPROM_OK: page blank
|
||||
*/
|
||||
uint16_t EE_CheckErasePage(uint32_t pageBase, uint16_t status)
|
||||
{
|
||||
uint16_t FlashStatus;
|
||||
if (EE_CheckPage(pageBase, status) != EEPROM_OK)
|
||||
{
|
||||
FlashStatus = EE_ErasePage(pageBase);
|
||||
if (FlashStatus != FLASH_COMPLETE)
|
||||
return FlashStatus;
|
||||
return EE_CheckPage(pageBase, status);
|
||||
}
|
||||
return EEPROM_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Find valid Page for write or read operation
|
||||
* @param Page0: Page0 base address
|
||||
* Page1: Page1 base address
|
||||
* @retval Valid page address (PAGE0 or PAGE1) or NULL in case of no valid page was found
|
||||
*/
|
||||
uint32_t EE_FindValidPage(void)
|
||||
{
|
||||
uint16_t status0 = (*(__IO uint16_t*)PageBase0); // Get Page0 actual status
|
||||
uint16_t status1 = (*(__IO uint16_t*)PageBase1); // Get Page1 actual status
|
||||
|
||||
if (status0 == EEPROM_VALID_PAGE && status1 == EEPROM_ERASED)
|
||||
return PageBase0;
|
||||
if (status1 == EEPROM_VALID_PAGE && status0 == EEPROM_ERASED)
|
||||
return PageBase1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculate unique variables in EEPROM
|
||||
* @param start: address of first slot to check (page + 4)
|
||||
* @param end: page end address
|
||||
* @param address: 16 bit virtual address of the variable to excluse (or 0XFFFF)
|
||||
* @retval count of variables
|
||||
*/
|
||||
uint16_t EE_GetVariablesCount(uint32_t pageBase, uint16_t skipAddress)
|
||||
{
|
||||
uint16_t varAddress, nextAddress;
|
||||
uint32_t idx;
|
||||
uint32_t pageEnd = pageBase + (uint32_t)PageSize;
|
||||
uint16_t count = 0;
|
||||
|
||||
for (pageBase += 6; pageBase < pageEnd; pageBase += 4)
|
||||
{
|
||||
varAddress = (*(__IO uint16_t*)pageBase);
|
||||
if (varAddress == 0xFFFF || varAddress == skipAddress)
|
||||
continue;
|
||||
|
||||
count++;
|
||||
for(idx = pageBase + 4; idx < pageEnd; idx += 4)
|
||||
{
|
||||
nextAddress = (*(__IO uint16_t*)idx);
|
||||
if (nextAddress == varAddress)
|
||||
{
|
||||
count--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transfers last updated variables data from the full Page to an empty one.
|
||||
* @param newPage: new page base address
|
||||
* @param oldPage: old page base address
|
||||
* @param SkipAddress: 16 bit virtual address of the variable (or 0xFFFF)
|
||||
* @retval Success or error status:
|
||||
* - FLASH_COMPLETE: on success
|
||||
* - EEPROM_OUT_SIZE: if valid new page is full
|
||||
* - Flash error code: on write Flash error
|
||||
*/
|
||||
uint16_t EE_PageTransfer(uint32_t newPage, uint32_t oldPage, uint16_t SkipAddress)
|
||||
{
|
||||
uint32_t oldEnd, newEnd;
|
||||
uint32_t oldIdx, newIdx, idx;
|
||||
uint16_t address, data, found;
|
||||
FLASH_Status FlashStatus;
|
||||
|
||||
// Transfer process: transfer variables from old to the new active page
|
||||
newEnd = newPage + ((uint32_t)PageSize);
|
||||
|
||||
// Find first free element in new page
|
||||
for (newIdx = newPage + 4; newIdx < newEnd; newIdx += 4)
|
||||
if ((*(__IO uint32_t*)newIdx) == 0xFFFFFFFF) // Verify if element
|
||||
break; // contents are 0xFFFFFFFF
|
||||
if (newIdx >= newEnd)
|
||||
return EEPROM_OUT_SIZE;
|
||||
|
||||
oldEnd = oldPage + 4;
|
||||
oldIdx = oldPage + (uint32_t)(PageSize - 2);
|
||||
|
||||
for (; oldIdx > oldEnd; oldIdx -= 4)
|
||||
{
|
||||
address = *(__IO uint16_t*)oldIdx;
|
||||
if (address == 0xFFFF || address == SkipAddress)
|
||||
continue; // it's means that power off after write data
|
||||
|
||||
found = 0;
|
||||
for (idx = newPage + 6; idx < newIdx; idx += 4)
|
||||
if ((*(__IO uint16_t*)(idx)) == address)
|
||||
{
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (found)
|
||||
continue;
|
||||
|
||||
if (newIdx < newEnd)
|
||||
{
|
||||
data = (*(__IO uint16_t*)(oldIdx - 2));
|
||||
|
||||
FlashStatus = FLASH_ProgramHalfWord(newIdx, data);
|
||||
if (FlashStatus != FLASH_COMPLETE)
|
||||
return FlashStatus;
|
||||
|
||||
FlashStatus = FLASH_ProgramHalfWord(newIdx + 2, address);
|
||||
if (FlashStatus != FLASH_COMPLETE)
|
||||
return FlashStatus;
|
||||
|
||||
newIdx += 4;
|
||||
}
|
||||
else
|
||||
return EEPROM_OUT_SIZE;
|
||||
}
|
||||
|
||||
// Erase the old Page: Set old Page status to EEPROM_EEPROM_ERASED status
|
||||
data = EE_CheckErasePage(oldPage, EEPROM_ERASED);
|
||||
if (data != EEPROM_OK)
|
||||
return data;
|
||||
|
||||
// Set new Page status
|
||||
FlashStatus = FLASH_ProgramHalfWord(newPage, EEPROM_VALID_PAGE);
|
||||
if (FlashStatus != FLASH_COMPLETE)
|
||||
return FlashStatus;
|
||||
|
||||
return EEPROM_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Verify if active page is full and Writes variable in EEPROM.
|
||||
* @param Address: 16 bit virtual address of the variable
|
||||
* @param Data: 16 bit data to be written as variable value
|
||||
* @retval Success or error status:
|
||||
* - FLASH_COMPLETE: on success
|
||||
* - EEPROM_PAGE_FULL: if valid page is full (need page transfer)
|
||||
* - EEPROM_NO_VALID_PAGE: if no valid page was found
|
||||
* - EEPROM_OUT_SIZE: if EEPROM size exceeded
|
||||
* - Flash error code: on write Flash error
|
||||
*/
|
||||
uint16_t EE_VerifyPageFullWriteVariable(uint16_t Address, uint16_t Data)
|
||||
{
|
||||
FLASH_Status FlashStatus;
|
||||
uint32_t idx, pageBase, pageEnd, newPage;
|
||||
uint16_t count;
|
||||
|
||||
// Get valid Page for write operation
|
||||
pageBase = EE_FindValidPage();
|
||||
if (pageBase == 0)
|
||||
return EEPROM_NO_VALID_PAGE;
|
||||
|
||||
// Get the valid Page end Address
|
||||
pageEnd = pageBase + PageSize; // Set end of page
|
||||
|
||||
for (idx = pageEnd - 2; idx > pageBase; idx -= 4)
|
||||
{
|
||||
if ((*(__IO uint16_t*)idx) == Address) // Find last value for address
|
||||
{
|
||||
count = (*(__IO uint16_t*)(idx - 2)); // Read last data
|
||||
if (count == Data)
|
||||
return EEPROM_OK;
|
||||
if (count == 0xFFFF)
|
||||
{
|
||||
FlashStatus = FLASH_ProgramHalfWord(idx - 2, Data); // Set variable data
|
||||
if (FlashStatus == FLASH_COMPLETE)
|
||||
return EEPROM_OK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check each active page address starting from begining
|
||||
for (idx = pageBase + 4; idx < pageEnd; idx += 4)
|
||||
if ((*(__IO uint32_t*)idx) == 0xFFFFFFFF) // Verify if element
|
||||
{ // contents are 0xFFFFFFFF
|
||||
FlashStatus = FLASH_ProgramHalfWord(idx, Data); // Set variable data
|
||||
if (FlashStatus != FLASH_COMPLETE)
|
||||
return FlashStatus;
|
||||
FlashStatus = FLASH_ProgramHalfWord(idx + 2, Address); // Set variable virtual address
|
||||
if (FlashStatus != FLASH_COMPLETE)
|
||||
return FlashStatus;
|
||||
return EEPROM_OK;
|
||||
}
|
||||
|
||||
// Empty slot not found, need page transfer
|
||||
// Calculate unique variables in page
|
||||
count = EE_GetVariablesCount(pageBase, Address) + 1;
|
||||
if (count >= (PageSize / 4 - 1))
|
||||
return EEPROM_OUT_SIZE;
|
||||
|
||||
if (pageBase == PageBase1)
|
||||
newPage = PageBase0; // New page address where variable will be moved to
|
||||
else
|
||||
newPage = PageBase1;
|
||||
|
||||
// Set the new Page status to RECEIVE_DATA status
|
||||
FlashStatus = FLASH_ProgramHalfWord(newPage, EEPROM_RECEIVE_DATA);
|
||||
if (FlashStatus != FLASH_COMPLETE)
|
||||
return FlashStatus;
|
||||
|
||||
// Write the variable passed as parameter in the new active page
|
||||
FlashStatus = FLASH_ProgramHalfWord(newPage + 4, Data);
|
||||
if (FlashStatus != FLASH_COMPLETE)
|
||||
return FlashStatus;
|
||||
|
||||
FlashStatus = FLASH_ProgramHalfWord(newPage + 6, Address);
|
||||
if (FlashStatus != FLASH_COMPLETE)
|
||||
return FlashStatus;
|
||||
|
||||
return EE_PageTransfer(newPage, pageBase, Address);
|
||||
}
|
||||
|
||||
/*EEPROMClass::EEPROMClass(void)
|
||||
{
|
||||
PageBase0 = EEPROM_PAGE0_BASE;
|
||||
PageBase1 = EEPROM_PAGE1_BASE;
|
||||
PageSize = EEPROM_PAGE_SIZE;
|
||||
Status = EEPROM_NOT_INIT;
|
||||
}*/
|
||||
/*
|
||||
uint16_t EEPROM_init(uint32_t pageBase0, uint32_t pageBase1, uint32_t pageSize)
|
||||
{
|
||||
PageBase0 = pageBase0;
|
||||
PageBase1 = pageBase1;
|
||||
PageSize = pageSize;
|
||||
return EEPROM_init();
|
||||
}*/
|
||||
|
||||
uint16_t EEPROM_init(void)
|
||||
{
|
||||
uint16_t status0 = 6, status1 = 6;
|
||||
FLASH_Status FlashStatus;
|
||||
|
||||
FLASH_Unlock();
|
||||
Status = EEPROM_NO_VALID_PAGE;
|
||||
|
||||
status0 = (*(__IO uint16_t *)PageBase0);
|
||||
status1 = (*(__IO uint16_t *)PageBase1);
|
||||
|
||||
switch (status0)
|
||||
{
|
||||
/*
|
||||
Page0 Page1
|
||||
----- -----
|
||||
EEPROM_ERASED EEPROM_VALID_PAGE Page1 valid, Page0 erased
|
||||
EEPROM_RECEIVE_DATA Page1 need set to valid, Page0 erased
|
||||
EEPROM_ERASED make EE_Format
|
||||
any Error: EEPROM_NO_VALID_PAGE
|
||||
*/
|
||||
case EEPROM_ERASED:
|
||||
if (status1 == EEPROM_VALID_PAGE) // Page0 erased, Page1 valid
|
||||
Status = EE_CheckErasePage(PageBase0, EEPROM_ERASED);
|
||||
else if (status1 == EEPROM_RECEIVE_DATA) // Page0 erased, Page1 receive
|
||||
{
|
||||
FlashStatus = FLASH_ProgramHalfWord(PageBase1, EEPROM_VALID_PAGE);
|
||||
if (FlashStatus != FLASH_COMPLETE)
|
||||
Status = FlashStatus;
|
||||
else
|
||||
Status = EE_CheckErasePage(PageBase0, EEPROM_ERASED);
|
||||
}
|
||||
else if (status1 == EEPROM_ERASED) // Both in erased state so format EEPROM
|
||||
Status = EEPROM_format();
|
||||
break;
|
||||
/*
|
||||
Page0 Page1
|
||||
----- -----
|
||||
EEPROM_RECEIVE_DATA EEPROM_VALID_PAGE Transfer Page1 to Page0
|
||||
EEPROM_ERASED Page0 need set to valid, Page1 erased
|
||||
any EEPROM_NO_VALID_PAGE
|
||||
*/
|
||||
case EEPROM_RECEIVE_DATA:
|
||||
if (status1 == EEPROM_VALID_PAGE) // Page0 receive, Page1 valid
|
||||
Status = EE_PageTransfer(PageBase0, PageBase1, 0xFFFF);
|
||||
else if (status1 == EEPROM_ERASED) // Page0 receive, Page1 erased
|
||||
{
|
||||
Status = EE_CheckErasePage(PageBase1, EEPROM_ERASED);
|
||||
if (Status == EEPROM_OK)
|
||||
{
|
||||
FlashStatus = FLASH_ProgramHalfWord(PageBase0, EEPROM_VALID_PAGE);
|
||||
if (FlashStatus != FLASH_COMPLETE)
|
||||
Status = FlashStatus;
|
||||
else
|
||||
Status = EEPROM_OK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
/*
|
||||
Page0 Page1
|
||||
----- -----
|
||||
EEPROM_VALID_PAGE EEPROM_VALID_PAGE Error: EEPROM_NO_VALID_PAGE
|
||||
EEPROM_RECEIVE_DATA Transfer Page0 to Page1
|
||||
any Page0 valid, Page1 erased
|
||||
*/
|
||||
case EEPROM_VALID_PAGE:
|
||||
if (status1 == EEPROM_VALID_PAGE) // Both pages valid
|
||||
Status = EEPROM_NO_VALID_PAGE;
|
||||
else if (status1 == EEPROM_RECEIVE_DATA)
|
||||
Status = EE_PageTransfer(PageBase1, PageBase0, 0xFFFF);
|
||||
else
|
||||
Status = EE_CheckErasePage(PageBase1, EEPROM_ERASED);
|
||||
break;
|
||||
/*
|
||||
Page0 Page1
|
||||
----- -----
|
||||
any EEPROM_VALID_PAGE Page1 valid, Page0 erased
|
||||
EEPROM_RECEIVE_DATA Page1 valid, Page0 erased
|
||||
any EEPROM_NO_VALID_PAGE
|
||||
*/
|
||||
default:
|
||||
if (status1 == EEPROM_VALID_PAGE)
|
||||
Status = EE_CheckErasePage(PageBase0, EEPROM_ERASED); // Check/Erase Page0
|
||||
else if (status1 == EEPROM_RECEIVE_DATA)
|
||||
{
|
||||
FlashStatus = FLASH_ProgramHalfWord(PageBase1, EEPROM_VALID_PAGE);
|
||||
if (FlashStatus != FLASH_COMPLETE)
|
||||
Status = FlashStatus;
|
||||
else
|
||||
Status = EE_CheckErasePage(PageBase0, EEPROM_ERASED);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Erases PAGE0 and PAGE1 and writes EEPROM_VALID_PAGE / 0 header to PAGE0
|
||||
* @param PAGE0 and PAGE1 base addresses
|
||||
* @retval Status of the last operation (Flash write or erase) done during EEPROM formating
|
||||
*/
|
||||
uint16_t EEPROM_format(void)
|
||||
{
|
||||
uint16_t status;
|
||||
FLASH_Status FlashStatus;
|
||||
|
||||
FLASH_Unlock();
|
||||
|
||||
// Erase Page0
|
||||
status = EE_CheckErasePage(PageBase0, EEPROM_VALID_PAGE);
|
||||
if (status != EEPROM_OK)
|
||||
return status;
|
||||
if ((*(__IO uint16_t*)PageBase0) == EEPROM_ERASED)
|
||||
{
|
||||
// Set Page0 as valid page: Write VALID_PAGE at Page0 base address
|
||||
FlashStatus = FLASH_ProgramHalfWord(PageBase0, EEPROM_VALID_PAGE);
|
||||
if (FlashStatus != FLASH_COMPLETE)
|
||||
return FlashStatus;
|
||||
}
|
||||
// Erase Page1
|
||||
return EE_CheckErasePage(PageBase1, EEPROM_ERASED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the erase counter for current page
|
||||
* @param Data: Global variable contains the read variable value
|
||||
* @retval Success or error status:
|
||||
* - EEPROM_OK: if erases counter return.
|
||||
* - EEPROM_NO_VALID_PAGE: if no valid page was found.
|
||||
*/
|
||||
uint16_t EEPROM_erases(uint16_t *Erases)
|
||||
{
|
||||
uint32_t pageBase;
|
||||
if (Status != EEPROM_OK)
|
||||
if (EEPROM_init() != EEPROM_OK)
|
||||
return Status;
|
||||
|
||||
// Get active Page for read operation
|
||||
pageBase = EE_FindValidPage();
|
||||
if (pageBase == 0)
|
||||
return EEPROM_NO_VALID_PAGE;
|
||||
|
||||
*Erases = (*(__IO uint16_t*)pageBase+2);
|
||||
return EEPROM_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the last stored variable data, if found,
|
||||
* which correspond to the passed virtual address
|
||||
* @param Address: Variable virtual address
|
||||
* @retval Data for variable or EEPROM_DEFAULT_DATA, if any errors
|
||||
*/
|
||||
/*
|
||||
uint16_t EEPROM_read (uint16_t Address)
|
||||
{
|
||||
uint16_t data;
|
||||
EEPROM_read(Address, &data);
|
||||
return data;
|
||||
}*/
|
||||
|
||||
/**
|
||||
* @brief Returns the last stored variable data, if found,
|
||||
* which correspond to the passed virtual address
|
||||
* @param Address: Variable virtual address
|
||||
* @param Data: Pointer to data variable
|
||||
* @retval Success or error status:
|
||||
* - EEPROM_OK: if variable was found
|
||||
* - EEPROM_BAD_ADDRESS: if the variable was not found
|
||||
* - EEPROM_NO_VALID_PAGE: if no valid page was found.
|
||||
*/
|
||||
uint16_t EEPROM_read(uint16_t Address, uint16_t *Data)
|
||||
{
|
||||
uint32_t pageBase, pageEnd;
|
||||
|
||||
// Set default data (empty EEPROM)
|
||||
*Data = EEPROM_DEFAULT_DATA;
|
||||
|
||||
if (Status == EEPROM_NOT_INIT)
|
||||
if (EEPROM_init() != EEPROM_OK)
|
||||
return Status;
|
||||
|
||||
// Get active Page for read operation
|
||||
pageBase = EE_FindValidPage();
|
||||
if (pageBase == 0)
|
||||
return EEPROM_NO_VALID_PAGE;
|
||||
|
||||
// Get the valid Page end Address
|
||||
pageEnd = pageBase + ((uint32_t)(PageSize - 2));
|
||||
|
||||
// Check each active page address starting from end
|
||||
for (pageBase += 6; pageEnd >= pageBase; pageEnd -= 4)
|
||||
if ((*(__IO uint16_t*)pageEnd) == Address) // Compare the read address with the virtual address
|
||||
{
|
||||
*Data = (*(__IO uint16_t*)(pageEnd - 2)); // Get content of Address-2 which is variable value
|
||||
return EEPROM_OK;
|
||||
}
|
||||
|
||||
// Return ReadStatus value: (0: variable exist, 1: variable doesn't exist)
|
||||
return EEPROM_BAD_ADDRESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes/upadtes variable data in EEPROM.
|
||||
* @param VirtAddress: Variable virtual address
|
||||
* @param Data: 16 bit data to be written
|
||||
* @retval Success or error status:
|
||||
* - FLASH_COMPLETE: on success
|
||||
* - EEPROM_BAD_ADDRESS: if address = 0xFFFF
|
||||
* - EEPROM_PAGE_FULL: if valid page is full
|
||||
* - EEPROM_NO_VALID_PAGE: if no valid page was found
|
||||
* - EEPROM_OUT_SIZE: if no empty EEPROM variables
|
||||
* - Flash error code: on write Flash error
|
||||
*/
|
||||
uint16_t EEPROM_write(uint16_t Address, uint16_t Data)
|
||||
{
|
||||
if (Status == EEPROM_NOT_INIT)
|
||||
if (EEPROM_init() != EEPROM_OK)
|
||||
return Status;
|
||||
|
||||
if (Address == 0xFFFF)
|
||||
return EEPROM_BAD_ADDRESS;
|
||||
|
||||
// Write the variable virtual address and value in the EEPROM
|
||||
uint16_t status = EE_VerifyPageFullWriteVariable(Address, Data);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes/upadtes variable data in EEPROM.
|
||||
The value is written only if differs from the one already saved at the same address.
|
||||
* @param VirtAddress: Variable virtual address
|
||||
* @param Data: 16 bit data to be written
|
||||
* @retval Success or error status:
|
||||
* - EEPROM_SAME_VALUE: If new Data matches existing EEPROM Data
|
||||
* - FLASH_COMPLETE: on success
|
||||
* - EEPROM_BAD_ADDRESS: if address = 0xFFFF
|
||||
* - EEPROM_PAGE_FULL: if valid page is full
|
||||
* - EEPROM_NO_VALID_PAGE: if no valid page was found
|
||||
* - EEPROM_OUT_SIZE: if no empty EEPROM variables
|
||||
* - Flash error code: on write Flash error
|
||||
*/
|
||||
uint16_t EEPROM_update(uint16_t Address, uint16_t Data)
|
||||
{
|
||||
uint16_t temp;
|
||||
EEPROM_read(Address, &temp);
|
||||
if (temp == Data)
|
||||
return EEPROM_SAME_VALUE;
|
||||
else
|
||||
return EEPROM_write(Address, Data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return number of variable
|
||||
* @retval Number of variables
|
||||
*/
|
||||
uint16_t EEPROM_count(uint16_t *Count)
|
||||
{
|
||||
if (Status == EEPROM_NOT_INIT)
|
||||
if (EEPROM_init() != EEPROM_OK)
|
||||
return Status;
|
||||
|
||||
// Get valid Page for write operation
|
||||
uint32_t pageBase = EE_FindValidPage();
|
||||
if (pageBase == 0)
|
||||
return EEPROM_NO_VALID_PAGE; // No valid page, return max. numbers
|
||||
|
||||
*Count = EE_GetVariablesCount(pageBase, 0xFFFF);
|
||||
return EEPROM_OK;
|
||||
}
|
||||
|
||||
uint16_t EEPROM_maxcount(void)
|
||||
{
|
||||
return ((PageSize / 4)-1);
|
||||
}
|
||||
|
||||
|
||||
uint8_t eeprom_read_byte (const uint8_t *Address)
|
||||
{
|
||||
const uint16_t p = (const uint32_t) Address;
|
||||
uint16_t temp;
|
||||
EEPROM_read(p, &temp);
|
||||
return (uint8_t) temp;
|
||||
}
|
||||
|
||||
void eeprom_write_byte (uint8_t *Address, uint8_t Value)
|
||||
{
|
||||
uint16_t p = (uint32_t) Address;
|
||||
EEPROM_write(p, (uint16_t) Value);
|
||||
}
|
||||
|
||||
void eeprom_update_byte (uint8_t *Address, uint8_t Value)
|
||||
{
|
||||
uint16_t p = (uint32_t) Address;
|
||||
EEPROM_update(p, (uint16_t) Value);
|
||||
}
|
||||
|
||||
uint16_t eeprom_read_word (const uint16_t *Address)
|
||||
{
|
||||
const uint16_t p = (const uint32_t) Address;
|
||||
uint16_t temp;
|
||||
EEPROM_read(p, &temp);
|
||||
return temp;
|
||||
}
|
||||
|
||||
void eeprom_write_word (uint16_t *Address, uint16_t Value)
|
||||
{
|
||||
uint16_t p = (uint32_t) Address;
|
||||
EEPROM_write(p, Value);
|
||||
}
|
||||
|
||||
void eeprom_update_word (uint16_t *Address, uint16_t Value)
|
||||
{
|
||||
uint16_t p = (uint32_t) Address;
|
||||
EEPROM_update(p, Value);
|
||||
}
|
||||
|
||||
uint32_t eeprom_read_dword (const uint32_t *Address)
|
||||
{
|
||||
const uint16_t p = (const uint32_t) Address;
|
||||
uint16_t temp1, temp2;
|
||||
EEPROM_read(p, &temp1);
|
||||
EEPROM_read(p + 1, &temp2);
|
||||
return temp1 | (temp2 << 16);
|
||||
}
|
||||
|
||||
void eeprom_write_dword (uint32_t *Address, uint32_t Value)
|
||||
{
|
||||
uint16_t temp = (uint16_t) Value;
|
||||
uint16_t p = (uint32_t) Address;
|
||||
EEPROM_write(p, temp);
|
||||
temp = (uint16_t) (Value >> 16);
|
||||
EEPROM_write(p + 1, temp);
|
||||
}
|
||||
|
||||
void eeprom_update_dword (uint32_t *Address, uint32_t Value)
|
||||
{
|
||||
uint16_t temp = (uint16_t) Value;
|
||||
uint16_t p = (uint32_t) Address;
|
||||
EEPROM_update(p, temp);
|
||||
temp = (uint16_t) (Value >> 16);
|
||||
EEPROM_update(p + 1, temp);
|
||||
}
|
95
tmk_core/common/chibios/eeprom_stm32.h
Executable file
95
tmk_core/common/chibios/eeprom_stm32.h
Executable file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* This software is experimental and a work in progress.
|
||||
* Under no circumstances should these files be used in relation to any critical system(s).
|
||||
* Use of these files is at your own risk.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This files are free to use from https://github.com/rogerclarkmelbourne/Arduino_STM32 and
|
||||
* https://github.com/leaflabs/libmaple
|
||||
*
|
||||
* Modifications for QMK and STM32F303 by Yiancar
|
||||
*/
|
||||
|
||||
// This file must be modified if the MCU is not defined below.
|
||||
// This library also assumes that the pages are not used by the firmware.
|
||||
|
||||
#ifndef __EEPROM_H
|
||||
#define __EEPROM_H
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
#include "flash_stm32.h"
|
||||
|
||||
// HACK ALERT. This definition may not match your processor
|
||||
// To Do. Work out correct value for EEPROM_PAGE_SIZE on the STM32F103CT6 etc
|
||||
#if defined(EEPROM_EMU_STM32F303xC)
|
||||
#define MCU_STM32F303CC
|
||||
#elif defined(EEPROM_EMU_STM32F103xB)
|
||||
#define MCU_STM32F103RB
|
||||
#else
|
||||
#error "not implemented."
|
||||
#endif
|
||||
|
||||
#ifndef EEPROM_PAGE_SIZE
|
||||
#if defined (MCU_STM32F103RB)
|
||||
#define EEPROM_PAGE_SIZE (uint16_t)0x400 /* Page size = 1KByte */
|
||||
#elif defined (MCU_STM32F103ZE) || defined (MCU_STM32F103RE) || defined (MCU_STM32F103RD) || defined (MCU_STM32F303CC)
|
||||
#define EEPROM_PAGE_SIZE (uint16_t)0x800 /* Page size = 2KByte */
|
||||
#else
|
||||
#error "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef EEPROM_START_ADDRESS
|
||||
#if defined (MCU_STM32F103RB)
|
||||
#define EEPROM_START_ADDRESS ((uint32_t)(0x8000000 + 128 * 1024 - 2 * EEPROM_PAGE_SIZE))
|
||||
#elif defined (MCU_STM32F103ZE) || defined (MCU_STM32F103RE)
|
||||
#define EEPROM_START_ADDRESS ((uint32_t)(0x8000000 + 512 * 1024 - 2 * EEPROM_PAGE_SIZE))
|
||||
#elif defined (MCU_STM32F103RD)
|
||||
#define EEPROM_START_ADDRESS ((uint32_t)(0x8000000 + 384 * 1024 - 2 * EEPROM_PAGE_SIZE))
|
||||
#elif defined (MCU_STM32F303CC)
|
||||
#define EEPROM_START_ADDRESS ((uint32_t)(0x8000000 + 256 * 1024 - 2 * EEPROM_PAGE_SIZE))
|
||||
#else
|
||||
#error "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Pages 0 and 1 base and end addresses */
|
||||
#define EEPROM_PAGE0_BASE ((uint32_t)(EEPROM_START_ADDRESS + 0x000))
|
||||
#define EEPROM_PAGE1_BASE ((uint32_t)(EEPROM_START_ADDRESS + EEPROM_PAGE_SIZE))
|
||||
|
||||
/* Page status definitions */
|
||||
#define EEPROM_ERASED ((uint16_t)0xFFFF) /* PAGE is empty */
|
||||
#define EEPROM_RECEIVE_DATA ((uint16_t)0xEEEE) /* PAGE is marked to receive data */
|
||||
#define EEPROM_VALID_PAGE ((uint16_t)0x0000) /* PAGE containing valid data */
|
||||
|
||||
/* Page full define */
|
||||
enum uint16_t
|
||||
{
|
||||
EEPROM_OK = ((uint16_t)0x0000),
|
||||
EEPROM_OUT_SIZE = ((uint16_t)0x0081),
|
||||
EEPROM_BAD_ADDRESS = ((uint16_t)0x0082),
|
||||
EEPROM_BAD_FLASH = ((uint16_t)0x0083),
|
||||
EEPROM_NOT_INIT = ((uint16_t)0x0084),
|
||||
EEPROM_SAME_VALUE = ((uint16_t)0x0085),
|
||||
EEPROM_NO_VALID_PAGE = ((uint16_t)0x00AB)
|
||||
};
|
||||
|
||||
#define EEPROM_DEFAULT_DATA 0xFFFF
|
||||
|
||||
uint16_t EEPROM_init(void);
|
||||
uint16_t EEPROM_format(void);
|
||||
uint16_t EEPROM_erases(uint16_t *);
|
||||
uint16_t EEPROM_read (uint16_t address, uint16_t *data);
|
||||
uint16_t EEPROM_write(uint16_t address, uint16_t data);
|
||||
uint16_t EEPROM_update(uint16_t address, uint16_t data);
|
||||
uint16_t EEPROM_count(uint16_t *);
|
||||
uint16_t EEPROM_maxcount(void);
|
||||
|
||||
#endif /* __EEPROM_H */
|
188
tmk_core/common/chibios/flash_stm32.c
Executable file
188
tmk_core/common/chibios/flash_stm32.c
Executable file
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
* This software is experimental and a work in progress.
|
||||
* Under no circumstances should these files be used in relation to any critical system(s).
|
||||
* Use of these files is at your own risk.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This files are free to use from https://github.com/rogerclarkmelbourne/Arduino_STM32 and
|
||||
* https://github.com/leaflabs/libmaple
|
||||
*
|
||||
* Modifications for QMK and STM32F303 by Yiancar
|
||||
*/
|
||||
|
||||
#if defined(EEPROM_EMU_STM32F303xC)
|
||||
#define STM32F303xC
|
||||
#include "stm32f3xx.h"
|
||||
#elif defined(EEPROM_EMU_STM32F103xB)
|
||||
#define STM32F103xB
|
||||
#include "stm32f1xx.h"
|
||||
#else
|
||||
#error "not implemented."
|
||||
#endif
|
||||
|
||||
#include "flash_stm32.h"
|
||||
|
||||
#if defined(EEPROM_EMU_STM32F103xB)
|
||||
#define FLASH_SR_WRPERR FLASH_SR_WRPRTERR
|
||||
#endif
|
||||
|
||||
/* Delay definition */
|
||||
#define EraseTimeout ((uint32_t)0x00000FFF)
|
||||
#define ProgramTimeout ((uint32_t)0x0000001F)
|
||||
|
||||
#define ASSERT(exp) (void)((0))
|
||||
|
||||
/**
|
||||
* @brief Inserts a time delay.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void delay(void)
|
||||
{
|
||||
__IO uint32_t i = 0;
|
||||
for(i = 0xFF; i != 0; i--) { }
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the FLASH Status.
|
||||
* @param None
|
||||
* @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG,
|
||||
* FLASH_ERROR_WRP or FLASH_COMPLETE
|
||||
*/
|
||||
FLASH_Status FLASH_GetStatus(void)
|
||||
{
|
||||
if ((FLASH->SR & FLASH_SR_BSY) == FLASH_SR_BSY)
|
||||
return FLASH_BUSY;
|
||||
|
||||
if ((FLASH->SR & FLASH_SR_PGERR) != 0)
|
||||
return FLASH_ERROR_PG;
|
||||
|
||||
if ((FLASH->SR & FLASH_SR_WRPERR) != 0 )
|
||||
return FLASH_ERROR_WRP;
|
||||
|
||||
if ((FLASH->SR & FLASH_OBR_OPTERR) != 0 )
|
||||
return FLASH_ERROR_OPT;
|
||||
|
||||
return FLASH_COMPLETE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Waits for a Flash operation to complete or a TIMEOUT to occur.
|
||||
* @param Timeout: FLASH progamming Timeout
|
||||
* @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
|
||||
* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
|
||||
*/
|
||||
FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout)
|
||||
{
|
||||
FLASH_Status status;
|
||||
|
||||
/* Check for the Flash Status */
|
||||
status = FLASH_GetStatus();
|
||||
/* Wait for a Flash operation to complete or a TIMEOUT to occur */
|
||||
while ((status == FLASH_BUSY) && (Timeout != 0x00))
|
||||
{
|
||||
delay();
|
||||
status = FLASH_GetStatus();
|
||||
Timeout--;
|
||||
}
|
||||
if (Timeout == 0)
|
||||
status = FLASH_TIMEOUT;
|
||||
/* Return the operation status */
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Erases a specified FLASH page.
|
||||
* @param Page_Address: The page address to be erased.
|
||||
* @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG,
|
||||
* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
|
||||
*/
|
||||
FLASH_Status FLASH_ErasePage(uint32_t Page_Address)
|
||||
{
|
||||
FLASH_Status status = FLASH_COMPLETE;
|
||||
/* Check the parameters */
|
||||
ASSERT(IS_FLASH_ADDRESS(Page_Address));
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation(EraseTimeout);
|
||||
|
||||
if(status == FLASH_COMPLETE)
|
||||
{
|
||||
/* if the previous operation is completed, proceed to erase the page */
|
||||
FLASH->CR |= FLASH_CR_PER;
|
||||
FLASH->AR = Page_Address;
|
||||
FLASH->CR |= FLASH_CR_STRT;
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation(EraseTimeout);
|
||||
if(status != FLASH_TIMEOUT)
|
||||
{
|
||||
/* if the erase operation is completed, disable the PER Bit */
|
||||
FLASH->CR &= ~FLASH_CR_PER;
|
||||
}
|
||||
FLASH->SR = (FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR);
|
||||
}
|
||||
/* Return the Erase Status */
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Programs a half word at a specified address.
|
||||
* @param Address: specifies the address to be programmed.
|
||||
* @param Data: specifies the data to be programmed.
|
||||
* @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
|
||||
* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
|
||||
*/
|
||||
FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data)
|
||||
{
|
||||
FLASH_Status status = FLASH_BAD_ADDRESS;
|
||||
|
||||
if (IS_FLASH_ADDRESS(Address))
|
||||
{
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation(ProgramTimeout);
|
||||
if(status == FLASH_COMPLETE)
|
||||
{
|
||||
/* if the previous operation is completed, proceed to program the new data */
|
||||
FLASH->CR |= FLASH_CR_PG;
|
||||
*(__IO uint16_t*)Address = Data;
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation(ProgramTimeout);
|
||||
if(status != FLASH_TIMEOUT)
|
||||
{
|
||||
/* if the program operation is completed, disable the PG Bit */
|
||||
FLASH->CR &= ~FLASH_CR_PG;
|
||||
}
|
||||
FLASH->SR = (FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR);
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unlocks the FLASH Program Erase Controller.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void FLASH_Unlock(void)
|
||||
{
|
||||
/* Authorize the FPEC Access */
|
||||
FLASH->KEYR = FLASH_KEY1;
|
||||
FLASH->KEYR = FLASH_KEY2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Locks the FLASH Program Erase Controller.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void FLASH_Lock(void)
|
||||
{
|
||||
/* Set the Lock Bit to lock the FPEC and the FCR */
|
||||
FLASH->CR |= FLASH_CR_LOCK;
|
||||
}
|
53
tmk_core/common/chibios/flash_stm32.h
Executable file
53
tmk_core/common/chibios/flash_stm32.h
Executable file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* This software is experimental and a work in progress.
|
||||
* Under no circumstances should these files be used in relation to any critical system(s).
|
||||
* Use of these files is at your own risk.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This files are free to use from https://github.com/rogerclarkmelbourne/Arduino_STM32 and
|
||||
* https://github.com/leaflabs/libmaple
|
||||
*
|
||||
* Modifications for QMK and STM32F303 by Yiancar
|
||||
*/
|
||||
|
||||
#ifndef __FLASH_STM32_H
|
||||
#define __FLASH_STM32_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
FLASH_BUSY = 1,
|
||||
FLASH_ERROR_PG,
|
||||
FLASH_ERROR_WRP,
|
||||
FLASH_ERROR_OPT,
|
||||
FLASH_COMPLETE,
|
||||
FLASH_TIMEOUT,
|
||||
FLASH_BAD_ADDRESS
|
||||
} FLASH_Status;
|
||||
|
||||
#define IS_FLASH_ADDRESS(ADDRESS) (((ADDRESS) >= 0x08000000) && ((ADDRESS) < 0x0807FFFF))
|
||||
|
||||
FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout);
|
||||
FLASH_Status FLASH_ErasePage(uint32_t Page_Address);
|
||||
FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data);
|
||||
|
||||
void FLASH_Unlock(void);
|
||||
void FLASH_Lock(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __FLASH_STM32_H */
|
|
@ -181,7 +181,11 @@ static void print_version(void)
|
|||
print("VID: " STR(VENDOR_ID) "(" STR(MANUFACTURER) ") "
|
||||
"PID: " STR(PRODUCT_ID) "(" STR(PRODUCT) ") "
|
||||
"VER: " STR(DEVICE_VER) "\n");
|
||||
#ifdef SKIP_VERSION
|
||||
print("BUILD: (" __DATE__ ")\n");
|
||||
#else
|
||||
print("BUILD: " STR(QMK_VERSION) " (" __TIME__ " " __DATE__ ")\n");
|
||||
#endif
|
||||
|
||||
/* build options */
|
||||
print("OPTIONS:"
|
||||
|
|
|
@ -15,8 +15,7 @@ You should have received a copy of the GNU General Public License
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef COMMAND_H
|
||||
#define COMMAND
|
||||
#pragma once
|
||||
|
||||
/* FIXME: Add doxygen comments for the behavioral defines in here. */
|
||||
|
||||
|
@ -155,5 +154,3 @@ bool command_proc(uint8_t code);
|
|||
|
||||
#define XMAGIC_KC(key) KC_##key
|
||||
#define MAGIC_KC(key) XMAGIC_KC(key)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -3,29 +3,59 @@
|
|||
#include "eeprom.h"
|
||||
#include "eeconfig.h"
|
||||
|
||||
#ifdef STM32_EEPROM_ENABLE
|
||||
#include "hal.h"
|
||||
#include "eeprom_stm32.h"
|
||||
#endif
|
||||
|
||||
extern uint32_t default_layer_state;
|
||||
/** \brief eeconfig enable
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
__attribute__ ((weak))
|
||||
void eeconfig_init_user(void) {
|
||||
// Reset user EEPROM value to blank, rather than to a set value
|
||||
eeconfig_update_user(0);
|
||||
}
|
||||
|
||||
__attribute__ ((weak))
|
||||
void eeconfig_init_kb(void) {
|
||||
// Reset Keyboard EEPROM value to blank, rather than to a set value
|
||||
eeconfig_update_kb(0);
|
||||
|
||||
eeconfig_init_user();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
void eeconfig_init_quantum(void) {
|
||||
#ifdef STM32_EEPROM_ENABLE
|
||||
EEPROM_format();
|
||||
#endif
|
||||
eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER);
|
||||
eeprom_update_byte(EECONFIG_DEBUG, 0);
|
||||
eeprom_update_byte(EECONFIG_DEFAULT_LAYER, 0);
|
||||
default_layer_state = 0;
|
||||
eeprom_update_byte(EECONFIG_KEYMAP, 0);
|
||||
eeprom_update_byte(EECONFIG_MOUSEKEY_ACCEL, 0);
|
||||
eeprom_update_byte(EECONFIG_BACKLIGHT, 0);
|
||||
eeprom_update_byte(EECONFIG_AUDIO, 0xFF); // On by default
|
||||
eeprom_update_dword(EECONFIG_RGBLIGHT, 0);
|
||||
eeprom_update_byte(EECONFIG_STENOMODE, 0);
|
||||
|
||||
eeconfig_init_kb();
|
||||
}
|
||||
|
||||
/** \brief eeconfig initialization
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
void eeconfig_init(void)
|
||||
{
|
||||
eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER);
|
||||
eeprom_update_byte(EECONFIG_DEBUG, 0);
|
||||
eeprom_update_byte(EECONFIG_DEFAULT_LAYER, 0);
|
||||
eeprom_update_byte(EECONFIG_KEYMAP, 0);
|
||||
eeprom_update_byte(EECONFIG_MOUSEKEY_ACCEL, 0);
|
||||
#ifdef BACKLIGHT_ENABLE
|
||||
eeprom_update_byte(EECONFIG_BACKLIGHT, 0);
|
||||
#endif
|
||||
#ifdef AUDIO_ENABLE
|
||||
eeprom_update_byte(EECONFIG_AUDIO, 0xFF); // On by default
|
||||
#endif
|
||||
#if defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE)
|
||||
eeprom_update_dword(EECONFIG_RGBLIGHT, 0);
|
||||
#endif
|
||||
#ifdef STENO_ENABLE
|
||||
eeprom_update_byte(EECONFIG_STENOMODE, 0);
|
||||
#endif
|
||||
void eeconfig_init(void) {
|
||||
|
||||
eeconfig_init_quantum();
|
||||
}
|
||||
|
||||
/** \brief eeconfig enable
|
||||
|
@ -43,7 +73,10 @@ void eeconfig_enable(void)
|
|||
*/
|
||||
void eeconfig_disable(void)
|
||||
{
|
||||
eeprom_update_word(EECONFIG_MAGIC, 0xFFFF);
|
||||
#ifdef STM32_EEPROM_ENABLE
|
||||
EEPROM_format();
|
||||
#endif
|
||||
eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER_OFF);
|
||||
}
|
||||
|
||||
/** \brief eeconfig is enabled
|
||||
|
@ -55,6 +88,15 @@ bool eeconfig_is_enabled(void)
|
|||
return (eeprom_read_word(EECONFIG_MAGIC) == EECONFIG_MAGIC_NUMBER);
|
||||
}
|
||||
|
||||
/** \brief eeconfig is disabled
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
bool eeconfig_is_disabled(void)
|
||||
{
|
||||
return (eeprom_read_word(EECONFIG_MAGIC) == EECONFIG_MAGIC_NUMBER_OFF);
|
||||
}
|
||||
|
||||
/** \brief eeconfig read debug
|
||||
*
|
||||
* FIXME: needs doc
|
||||
|
@ -88,7 +130,6 @@ uint8_t eeconfig_read_keymap(void) { return eeprom_read_byte(EECONFIG_KEYMA
|
|||
*/
|
||||
void eeconfig_update_keymap(uint8_t val) { eeprom_update_byte(EECONFIG_KEYMAP, val); }
|
||||
|
||||
#ifdef BACKLIGHT_ENABLE
|
||||
/** \brief eeconfig read backlight
|
||||
*
|
||||
* FIXME: needs doc
|
||||
|
@ -99,9 +140,8 @@ uint8_t eeconfig_read_backlight(void) { return eeprom_read_byte(EECONFIG_BA
|
|||
* FIXME: needs doc
|
||||
*/
|
||||
void eeconfig_update_backlight(uint8_t val) { eeprom_update_byte(EECONFIG_BACKLIGHT, val); }
|
||||
#endif
|
||||
|
||||
#ifdef AUDIO_ENABLE
|
||||
|
||||
/** \brief eeconfig read audio
|
||||
*
|
||||
* FIXME: needs doc
|
||||
|
@ -112,4 +152,28 @@ uint8_t eeconfig_read_audio(void) { return eeprom_read_byte(EECONFIG_AUDIO)
|
|||
* FIXME: needs doc
|
||||
*/
|
||||
void eeconfig_update_audio(uint8_t val) { eeprom_update_byte(EECONFIG_AUDIO, val); }
|
||||
#endif
|
||||
|
||||
|
||||
/** \brief eeconfig read kb
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
uint32_t eeconfig_read_kb(void) { return eeprom_read_dword(EECONFIG_KEYBOARD); }
|
||||
/** \brief eeconfig update kb
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
|
||||
void eeconfig_update_kb(uint32_t val) { eeprom_update_dword(EECONFIG_KEYBOARD, val); }
|
||||
/** \brief eeconfig read user
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
uint32_t eeconfig_read_user(void) { return eeprom_read_dword(EECONFIG_USER); }
|
||||
/** \brief eeconfig update user
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
void eeconfig_update_user(uint32_t val) { eeprom_update_dword(EECONFIG_USER, val); }
|
||||
|
||||
|
||||
|
|
|
@ -23,21 +23,42 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
|
||||
#define EECONFIG_MAGIC_NUMBER (uint16_t)0xFEED
|
||||
#define EECONFIG_MAGIC_NUMBER_OFF (uint16_t)0xFFFF
|
||||
|
||||
/* eeprom parameteter address */
|
||||
#if !defined(STM32_EEPROM_ENABLE)
|
||||
#define EECONFIG_MAGIC (uint16_t *)0
|
||||
#define EECONFIG_DEBUG (uint8_t *)2
|
||||
#define EECONFIG_DEFAULT_LAYER (uint8_t *)3
|
||||
#define EECONFIG_KEYMAP (uint8_t *)4
|
||||
#define EECONFIG_MOUSEKEY_ACCEL (uint8_t *)5
|
||||
#define EECONFIG_BACKLIGHT (uint8_t *)6
|
||||
#define EECONFIG_AUDIO (uint8_t *)7
|
||||
#define EECONFIG_DEBUG (uint8_t *)2
|
||||
#define EECONFIG_DEFAULT_LAYER (uint8_t *)3
|
||||
#define EECONFIG_KEYMAP (uint8_t *)4
|
||||
#define EECONFIG_MOUSEKEY_ACCEL (uint8_t *)5
|
||||
#define EECONFIG_BACKLIGHT (uint8_t *)6
|
||||
#define EECONFIG_AUDIO (uint8_t *)7
|
||||
#define EECONFIG_RGBLIGHT (uint32_t *)8
|
||||
#define EECONFIG_UNICODEMODE (uint8_t *)12
|
||||
#define EECONFIG_STENOMODE (uint8_t *)13
|
||||
// EEHANDS for two handed boards
|
||||
#define EECONFIG_HANDEDNESS (uint8_t *)14
|
||||
#define EECONFIG_HANDEDNESS (uint8_t *)14
|
||||
#define EECONFIG_KEYBOARD (uint32_t *)15
|
||||
#define EECONFIG_USER (uint32_t *)19
|
||||
|
||||
#else
|
||||
/* STM32F3 uses 16byte block. Reconfigure memory map */
|
||||
#define EECONFIG_MAGIC (uint16_t *)0
|
||||
#define EECONFIG_DEBUG (uint8_t *)1
|
||||
#define EECONFIG_DEFAULT_LAYER (uint8_t *)2
|
||||
#define EECONFIG_KEYMAP (uint8_t *)3
|
||||
#define EECONFIG_MOUSEKEY_ACCEL (uint8_t *)4
|
||||
#define EECONFIG_BACKLIGHT (uint8_t *)5
|
||||
#define EECONFIG_AUDIO (uint8_t *)6
|
||||
#define EECONFIG_RGBLIGHT (uint32_t *)7
|
||||
#define EECONFIG_UNICODEMODE (uint8_t *)9
|
||||
#define EECONFIG_STENOMODE (uint8_t *)10
|
||||
// EEHANDS for two handed boards
|
||||
#define EECONFIG_HANDEDNESS (uint8_t *)11
|
||||
#define EECONFIG_KEYBOARD (uint32_t *)12
|
||||
#define EECONFIG_USER (uint32_t *)14
|
||||
#endif
|
||||
|
||||
/* debug bit */
|
||||
#define EECONFIG_DEBUG_ENABLE (1<<0)
|
||||
|
@ -57,8 +78,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
|
||||
bool eeconfig_is_enabled(void);
|
||||
bool eeconfig_is_disabled(void);
|
||||
|
||||
void eeconfig_init(void);
|
||||
void eeconfig_init_quantum(void);
|
||||
void eeconfig_init_kb(void);
|
||||
void eeconfig_init_user(void);
|
||||
|
||||
void eeconfig_enable(void);
|
||||
|
||||
|
@ -83,4 +108,9 @@ uint8_t eeconfig_read_audio(void);
|
|||
void eeconfig_update_audio(uint8_t val);
|
||||
#endif
|
||||
|
||||
uint32_t eeconfig_read_kb(void);
|
||||
void eeconfig_update_kb(uint32_t val);
|
||||
uint32_t eeconfig_read_user(void);
|
||||
void eeconfig_update_user(uint32_t val);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -22,6 +22,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include "util.h"
|
||||
#include "debug.h"
|
||||
|
||||
#ifdef NKRO_ENABLE
|
||||
#include "keycode_config.h"
|
||||
extern keymap_config_t keymap_config;
|
||||
#endif
|
||||
|
||||
static host_driver_t *driver;
|
||||
static uint16_t last_system_report = 0;
|
||||
static uint16_t last_consumer_report = 0;
|
||||
|
@ -46,6 +51,20 @@ uint8_t host_keyboard_leds(void)
|
|||
void host_keyboard_send(report_keyboard_t *report)
|
||||
{
|
||||
if (!driver) return;
|
||||
#if defined(NKRO_ENABLE) && defined(NKRO_SHARED_EP)
|
||||
if (keyboard_protocol && keymap_config.nkro) {
|
||||
/* The callers of this function assume that report->mods is where mods go in.
|
||||
* But report->nkro.mods can be at a different offset if core keyboard does not have a report ID.
|
||||
*/
|
||||
report->nkro.mods = report->mods;
|
||||
report->nkro.report_id = REPORT_ID_NKRO;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
#ifdef KEYBOARD_SHARED_EP
|
||||
report->report_id = REPORT_ID_KEYBOARD;
|
||||
#endif
|
||||
}
|
||||
(*driver->send_keyboard)(report);
|
||||
|
||||
if (debug_keyboard) {
|
||||
|
@ -60,6 +79,9 @@ void host_keyboard_send(report_keyboard_t *report)
|
|||
void host_mouse_send(report_mouse_t *report)
|
||||
{
|
||||
if (!driver) return;
|
||||
#ifdef MOUSE_SHARED_EP
|
||||
report->report_id = REPORT_ID_MOUSE;
|
||||
#endif
|
||||
(*driver->send_mouse)(report);
|
||||
}
|
||||
|
||||
|
|
|
@ -73,6 +73,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#ifdef HD44780_ENABLE
|
||||
# include "hd44780.h"
|
||||
#endif
|
||||
#ifdef QWIIC_ENABLE
|
||||
# include "qwiic.h"
|
||||
#endif
|
||||
|
||||
#ifdef MATRIX_HAS_GHOST
|
||||
extern const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS];
|
||||
|
@ -121,6 +124,14 @@ static inline bool has_ghost_in_row(uint8_t row, matrix_row_t rowdata)
|
|||
|
||||
#endif
|
||||
|
||||
void disable_jtag(void) {
|
||||
// To use PORTF disable JTAG with writing JTD bit twice within four cycles.
|
||||
#if (defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega32U4__))
|
||||
MCUCR |= _BV(JTD);
|
||||
MCUCR |= _BV(JTD);
|
||||
#endif
|
||||
}
|
||||
|
||||
/** \brief matrix_setup
|
||||
*
|
||||
* FIXME: needs doc
|
||||
|
@ -134,6 +145,7 @@ void matrix_setup(void) {
|
|||
* FIXME: needs doc
|
||||
*/
|
||||
void keyboard_setup(void) {
|
||||
disable_jtag();
|
||||
matrix_setup();
|
||||
}
|
||||
|
||||
|
@ -152,13 +164,11 @@ bool is_keyboard_master(void) {
|
|||
*/
|
||||
void keyboard_init(void) {
|
||||
timer_init();
|
||||
// To use PORTF disable JTAG with writing JTD bit twice within four cycles.
|
||||
#if (defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega32U4__))
|
||||
MCUCR |= _BV(JTD);
|
||||
MCUCR |= _BV(JTD);
|
||||
#endif
|
||||
matrix_init();
|
||||
matrix_debounce_init();
|
||||
#ifdef QWIIC_ENABLE
|
||||
qwiic_init();
|
||||
#endif
|
||||
#ifdef PS2_MOUSE_ENABLE
|
||||
ps2_mouse_init();
|
||||
#endif
|
||||
|
@ -256,6 +266,10 @@ void keyboard_task(void)
|
|||
|
||||
MATRIX_LOOP_END:
|
||||
|
||||
#ifdef QWIIC_ENABLE
|
||||
qwiic_task();
|
||||
#endif
|
||||
|
||||
#ifdef MOUSEKEY_ENABLE
|
||||
// mousekey repeat & acceleration
|
||||
mousekey_task();
|
||||
|
|
|
@ -57,6 +57,8 @@ static inline bool IS_RELEASED(keyevent_t event) { return (!IS_NOEVENT(event) &&
|
|||
.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. */
|
||||
|
|
|
@ -33,7 +33,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
#define IS_SPECIAL(code) ((0xA5 <= (code) && (code) <= 0xDF) || (0xE8 <= (code) && (code) <= 0xFF))
|
||||
#define IS_SYSTEM(code) (KC_PWR <= (code) && (code) <= KC_WAKE)
|
||||
#define IS_CONSUMER(code) (KC_MUTE <= (code) && (code) <= KC_MRWD)
|
||||
#define IS_CONSUMER(code) (KC_MUTE <= (code) && (code) <= KC_BRID)
|
||||
|
||||
#define IS_FN(code) (KC_FN0 <= (code) && (code) <= KC_FN31)
|
||||
|
||||
|
@ -140,6 +140,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#define KC_LWIN KC_LGUI
|
||||
#define KC_RCTL KC_RCTRL
|
||||
#define KC_RSFT KC_RSHIFT
|
||||
#define KC_ALGR KC_RALT
|
||||
#define KC_RCMD KC_RGUI
|
||||
#define KC_RWIN KC_RGUI
|
||||
|
||||
|
@ -170,6 +171,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#define KC_WFAV KC_WWW_FAVORITES
|
||||
#define KC_MFFD KC_MEDIA_FAST_FORWARD
|
||||
#define KC_MRWD KC_MEDIA_REWIND
|
||||
#define KC_BRIU KC_BRIGHTNESS_UP
|
||||
#define KC_BRID KC_BRIGHTNESS_DOWN
|
||||
|
||||
/* Mouse Keys */
|
||||
#define KC_MS_U KC_MS_UP
|
||||
|
@ -457,6 +460,8 @@ enum internal_special_keycodes {
|
|||
KC_WWW_FAVORITES,
|
||||
KC_MEDIA_FAST_FORWARD,
|
||||
KC_MEDIA_REWIND,
|
||||
KC_BRIGHTNESS_UP,
|
||||
KC_BRIGHTNESS_DOWN,
|
||||
|
||||
/* Fn keys */
|
||||
KC_FN0 = 0xC0,
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#include <stdbool.h>
|
||||
#include "util.h"
|
||||
|
||||
#if defined(PROTOCOL_CHIBIOS)
|
||||
#if defined(PROTOCOL_CHIBIOS) || defined(PROTOCOL_ARM_ATSAM)
|
||||
#define PSTR(x) x
|
||||
#endif
|
||||
|
||||
|
@ -60,7 +60,7 @@
|
|||
# define println(s) xputs(PSTR(s "\r\n"))
|
||||
# define uprint(s) print(s)
|
||||
# define uprintln(s) println(s)
|
||||
# define uprintf(fmt, ...) xprintf(fmt, ...)
|
||||
# define uprintf(fmt, ...) xprintf(fmt, ##__VA_ARGS__)
|
||||
|
||||
# endif /* USER_PRINT / NORMAL PRINT */
|
||||
|
||||
|
@ -73,7 +73,9 @@ void print_set_sendchar(int8_t (*print_sendchar_func)(uint8_t));
|
|||
|
||||
#elif defined(PROTOCOL_CHIBIOS) /* PROTOCOL_CHIBIOS */
|
||||
|
||||
#ifndef TERMINAL_ENABLE
|
||||
# include "chibios/printf.h"
|
||||
#endif
|
||||
|
||||
# ifdef USER_PRINT /* USER_PRINT */
|
||||
|
||||
|
@ -99,6 +101,34 @@ void print_set_sendchar(int8_t (*print_sendchar_func)(uint8_t));
|
|||
|
||||
# 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 */
|
||||
|
||||
#elif defined(__arm__) /* __arm__ */
|
||||
|
||||
# include "mbed/xprintf.h"
|
||||
|
@ -111,26 +141,26 @@ void print_set_sendchar(int8_t (*print_sendchar_func)(uint8_t));
|
|||
# define xprintf(fmt, ...)
|
||||
|
||||
// Create user print defines
|
||||
# define uprintf(fmt, ...) __xprintf(fmt, ...)
|
||||
# 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, ...)
|
||||
# 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, ...)
|
||||
# define uprintf(fmt, ...) xprintf(fmt, ##__VA_ARGS__)
|
||||
|
||||
# endif /* USER_PRINT / NORMAL PRINT */
|
||||
|
||||
/* TODO: to select output destinations: UART/USBSerial */
|
||||
# define print_set_sendchar(func)
|
||||
|
||||
#endif /* __AVR__ / PROTOCOL_CHIBIOS / __arm__ */
|
||||
#endif /* __AVR__ / PROTOCOL_CHIBIOS / PROTOCOL_ARM_ATSAM / __arm__ */
|
||||
|
||||
// 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
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "keycode_config.h"
|
||||
#include "debug.h"
|
||||
#include "util.h"
|
||||
#include <string.h>
|
||||
|
||||
/** \brief has_anykey
|
||||
*
|
||||
|
@ -27,8 +28,16 @@
|
|||
uint8_t has_anykey(report_keyboard_t* keyboard_report)
|
||||
{
|
||||
uint8_t cnt = 0;
|
||||
for (uint8_t i = 1; i < KEYBOARD_REPORT_SIZE; i++) {
|
||||
if (keyboard_report->raw[i])
|
||||
uint8_t *p = keyboard_report->keys;
|
||||
uint8_t lp = sizeof(keyboard_report->keys);
|
||||
#ifdef NKRO_ENABLE
|
||||
if (keyboard_protocol && keymap_config.nkro) {
|
||||
p = keyboard_report->nkro.bits;
|
||||
lp = sizeof(keyboard_report->nkro.bits);
|
||||
}
|
||||
#endif
|
||||
while (lp--) {
|
||||
if (*p++)
|
||||
cnt++;
|
||||
}
|
||||
return cnt;
|
||||
|
@ -237,7 +246,11 @@ void del_key_from_report(report_keyboard_t* keyboard_report, uint8_t key)
|
|||
void clear_keys_from_report(report_keyboard_t* keyboard_report)
|
||||
{
|
||||
// not clear mods
|
||||
for (int8_t i = 1; i < KEYBOARD_REPORT_SIZE; i++) {
|
||||
keyboard_report->raw[i] = 0;
|
||||
#ifdef NKRO_ENABLE
|
||||
if (keyboard_protocol && keymap_config.nkro) {
|
||||
memset(keyboard_report->nkro.bits, 0, sizeof(keyboard_report->nkro.bits));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
memset(keyboard_report->keys, 0, sizeof(keyboard_report->keys));
|
||||
}
|
||||
|
|
|
@ -23,9 +23,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
|
||||
/* report id */
|
||||
#define REPORT_ID_MOUSE 1
|
||||
#define REPORT_ID_SYSTEM 2
|
||||
#define REPORT_ID_CONSUMER 3
|
||||
#define REPORT_ID_KEYBOARD 1
|
||||
#define REPORT_ID_MOUSE 2
|
||||
#define REPORT_ID_SYSTEM 3
|
||||
#define REPORT_ID_CONSUMER 4
|
||||
#define REPORT_ID_NKRO 5
|
||||
|
||||
/* mouse buttons */
|
||||
#define MOUSE_BTN1 (1<<0)
|
||||
|
@ -36,6 +38,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
/* Consumer Page(0x0C)
|
||||
* following are supported by Windows: http://msdn.microsoft.com/en-us/windows/hardware/gg463372.aspx
|
||||
* see also https://docs.microsoft.com/en-us/windows-hardware/drivers/hid/display-brightness-control
|
||||
*/
|
||||
#define AUDIO_MUTE 0x00E2
|
||||
#define AUDIO_VOL_UP 0x00E9
|
||||
|
@ -45,6 +48,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#define TRANSPORT_STOP 0x00B7
|
||||
#define TRANSPORT_STOP_EJECT 0x00CC
|
||||
#define TRANSPORT_PLAY_PAUSE 0x00CD
|
||||
#define BRIGHTNESSUP 0x006F
|
||||
#define BRIGHTNESSDOWN 0x0070
|
||||
/* application launch */
|
||||
#define AL_CC_CONFIG 0x0183
|
||||
#define AL_EMAIL 0x018A
|
||||
|
@ -72,27 +77,35 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#define SYSTEM_WAKE_UP 0x0083
|
||||
|
||||
|
||||
#define NKRO_SHARED_EP
|
||||
/* key report size(NKRO or boot mode) */
|
||||
#if defined(NKRO_ENABLE)
|
||||
#if defined(PROTOCOL_PJRC)
|
||||
#include "usb.h"
|
||||
#define KEYBOARD_REPORT_SIZE KBD2_SIZE
|
||||
#define KEYBOARD_REPORT_KEYS (KBD2_SIZE - 2)
|
||||
#define KEYBOARD_REPORT_BITS (KBD2_SIZE - 1)
|
||||
#elif defined(PROTOCOL_LUFA) || defined(PROTOCOL_CHIBIOS)
|
||||
#if defined(PROTOCOL_LUFA) || defined(PROTOCOL_CHIBIOS)
|
||||
#include "protocol/usb_descriptor.h"
|
||||
#define KEYBOARD_REPORT_SIZE NKRO_EPSIZE
|
||||
#define KEYBOARD_REPORT_KEYS (NKRO_EPSIZE - 2)
|
||||
#define KEYBOARD_REPORT_BITS (SHARED_EPSIZE - 2)
|
||||
#elif defined(PROTOCOL_ARM_ATSAM)
|
||||
#include "protocol/arm_atsam/usb/udi_device_epsize.h"
|
||||
#define KEYBOARD_REPORT_BITS (NKRO_EPSIZE - 1)
|
||||
#undef NKRO_SHARED_EP
|
||||
#undef MOUSE_SHARED_EP
|
||||
#else
|
||||
#error "NKRO not supported with this protocol"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef KEYBOARD_SHARED_EP
|
||||
# define KEYBOARD_REPORT_SIZE 9
|
||||
#else
|
||||
# define KEYBOARD_REPORT_SIZE 8
|
||||
# define KEYBOARD_REPORT_KEYS 6
|
||||
#endif
|
||||
|
||||
#define KEYBOARD_REPORT_KEYS 6
|
||||
|
||||
/* VUSB hardcodes keyboard and mouse+extrakey only */
|
||||
#if defined(PROTOCOL_VUSB)
|
||||
#undef KEYBOARD_SHARED_EP
|
||||
#undef MOUSE_SHARED_EP
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -121,12 +134,18 @@ extern "C" {
|
|||
typedef union {
|
||||
uint8_t raw[KEYBOARD_REPORT_SIZE];
|
||||
struct {
|
||||
#ifdef KEYBOARD_SHARED_EP
|
||||
uint8_t report_id;
|
||||
#endif
|
||||
uint8_t mods;
|
||||
uint8_t reserved;
|
||||
uint8_t keys[KEYBOARD_REPORT_KEYS];
|
||||
};
|
||||
#ifdef NKRO_ENABLE
|
||||
struct {
|
||||
struct nkro_report {
|
||||
#ifdef NKRO_SHARED_EP
|
||||
uint8_t report_id;
|
||||
#endif
|
||||
uint8_t mods;
|
||||
uint8_t bits[KEYBOARD_REPORT_BITS];
|
||||
} nkro;
|
||||
|
@ -134,6 +153,9 @@ typedef union {
|
|||
} __attribute__ ((packed)) report_keyboard_t;
|
||||
|
||||
typedef struct {
|
||||
#ifdef MOUSE_SHARED_EP
|
||||
uint8_t report_id;
|
||||
#endif
|
||||
uint8_t buttons;
|
||||
int8_t x;
|
||||
int8_t y;
|
||||
|
@ -170,7 +192,9 @@ typedef struct {
|
|||
(key == KC_WWW_FORWARD ? AC_FORWARD : \
|
||||
(key == KC_WWW_STOP ? AC_STOP : \
|
||||
(key == KC_WWW_REFRESH ? AC_REFRESH : \
|
||||
(key == KC_WWW_FAVORITES ? AC_BOOKMARKS : 0)))))))))))))))))))))
|
||||
(key == KC_BRIGHTNESS_UP ? BRIGHTNESSUP : \
|
||||
(key == KC_BRIGHTNESS_DOWN ? BRIGHTNESSDOWN : \
|
||||
(key == KC_WWW_FAVORITES ? AC_BOOKMARKS : 0)))))))))))))))))))))))
|
||||
|
||||
uint8_t has_anykey(report_keyboard_t* keyboard_report);
|
||||
uint8_t get_first_key(report_keyboard_t* keyboard_report);
|
||||
|
|
|
@ -50,5 +50,10 @@ ifdef ADB_MOUSE_ENABLE
|
|||
OPT_DEFS += -DADB_MOUSE_ENABLE -DMOUSE_ENABLE
|
||||
endif
|
||||
|
||||
ifdef XT_ENABLE
|
||||
SRC += $(PROTOCOL_DIR)/xt_interrupt.c
|
||||
OPT_DEFS += -DXT_ENABLE
|
||||
endif
|
||||
|
||||
# Search Path
|
||||
VPATH += $(TMK_DIR)/protocol
|
||||
|
|
25
tmk_core/protocol/arm_atsam.mk
Normal file
25
tmk_core/protocol/arm_atsam.mk
Normal file
|
@ -0,0 +1,25 @@
|
|||
ARM_ATSAM_DIR = protocol/arm_atsam
|
||||
|
||||
SRC += $(ARM_ATSAM_DIR)/adc.c
|
||||
SRC += $(ARM_ATSAM_DIR)/clks.c
|
||||
SRC += $(ARM_ATSAM_DIR)/d51_util.c
|
||||
SRC += $(ARM_ATSAM_DIR)/i2c_master.c
|
||||
SRC += $(ARM_ATSAM_DIR)/led_matrix.c
|
||||
SRC += $(ARM_ATSAM_DIR)/main_arm_atsam.c
|
||||
SRC += $(ARM_ATSAM_DIR)/spi.c
|
||||
SRC += $(ARM_ATSAM_DIR)/startup.c
|
||||
|
||||
SRC += $(ARM_ATSAM_DIR)/usb/main_usb.c
|
||||
SRC += $(ARM_ATSAM_DIR)/usb/udc.c
|
||||
SRC += $(ARM_ATSAM_DIR)/usb/udi_cdc.c
|
||||
SRC += $(ARM_ATSAM_DIR)/usb/udi_hid.c
|
||||
SRC += $(ARM_ATSAM_DIR)/usb/udi_hid_kbd.c
|
||||
SRC += $(ARM_ATSAM_DIR)/usb/udi_hid_kbd_desc.c
|
||||
SRC += $(ARM_ATSAM_DIR)/usb/ui.c
|
||||
SRC += $(ARM_ATSAM_DIR)/usb/usb2422.c
|
||||
SRC += $(ARM_ATSAM_DIR)/usb/usb.c
|
||||
SRC += $(ARM_ATSAM_DIR)/usb/usb_device_udd.c
|
||||
SRC += $(ARM_ATSAM_DIR)/usb/usb_util.c
|
||||
|
||||
# Search Path
|
||||
VPATH += $(TMK_DIR)/$(ARM_ATSAM_DIR)
|
99
tmk_core/protocol/arm_atsam/adc.c
Normal file
99
tmk_core/protocol/arm_atsam/adc.c
Normal file
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
Copyright 2018 Massdrop Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "arm_atsam_protocol.h"
|
||||
|
||||
uint16_t v_5v;
|
||||
uint16_t v_5v_avg;
|
||||
uint16_t v_con_1;
|
||||
uint16_t v_con_2;
|
||||
uint16_t v_con_1_boot;
|
||||
uint16_t v_con_2_boot;
|
||||
|
||||
void ADC0_clock_init(void)
|
||||
{
|
||||
DBGC(DC_ADC0_CLOCK_INIT_BEGIN);
|
||||
|
||||
MCLK->APBDMASK.bit.ADC0_ = 1; //ADC0 Clock Enable
|
||||
|
||||
GCLK->PCHCTRL[ADC0_GCLK_ID].bit.GEN = GEN_OSC0; //Select generator clock
|
||||
GCLK->PCHCTRL[ADC0_GCLK_ID].bit.CHEN = 1; //Enable peripheral clock
|
||||
|
||||
DBGC(DC_ADC0_CLOCK_INIT_COMPLETE);
|
||||
}
|
||||
|
||||
void ADC0_init(void)
|
||||
{
|
||||
DBGC(DC_ADC0_INIT_BEGIN);
|
||||
|
||||
//MCU
|
||||
PORT->Group[1].DIRCLR.reg = 1 << 0; //PB00 as input 5V
|
||||
PORT->Group[1].DIRCLR.reg = 1 << 1; //PB01 as input CON2
|
||||
PORT->Group[1].DIRCLR.reg = 1 << 2; //PB02 as input CON1
|
||||
PORT->Group[1].PMUX[0].bit.PMUXE = 1; //PB00 mux select B ADC 5V
|
||||
PORT->Group[1].PMUX[0].bit.PMUXO = 1; //PB01 mux select B ADC CON2
|
||||
PORT->Group[1].PMUX[1].bit.PMUXE = 1; //PB02 mux select B ADC CON1
|
||||
PORT->Group[1].PINCFG[0].bit.PMUXEN = 1; //PB01 mux ADC Enable 5V
|
||||
PORT->Group[1].PINCFG[1].bit.PMUXEN = 1; //PB01 mux ADC Enable CON2
|
||||
PORT->Group[1].PINCFG[2].bit.PMUXEN = 1; //PB02 mux ADC Enable CON1
|
||||
|
||||
//ADC
|
||||
ADC0->CTRLA.bit.SWRST = 1;
|
||||
while (ADC0->SYNCBUSY.bit.SWRST) { DBGC(DC_ADC0_SWRST_SYNCING_1); }
|
||||
while (ADC0->CTRLA.bit.SWRST) { DBGC(DC_ADC0_SWRST_SYNCING_2); }
|
||||
|
||||
//Clock divide
|
||||
ADC0->CTRLA.bit.PRESCALER = ADC_CTRLA_PRESCALER_DIV2_Val;
|
||||
|
||||
//Averaging
|
||||
ADC0->AVGCTRL.bit.SAMPLENUM = ADC_AVGCTRL_SAMPLENUM_4_Val;
|
||||
while (ADC0->SYNCBUSY.bit.AVGCTRL) { DBGC(DC_ADC0_AVGCTRL_SYNCING_1); }
|
||||
if (ADC0->AVGCTRL.bit.SAMPLENUM == ADC_AVGCTRL_SAMPLENUM_1_Val) ADC0->AVGCTRL.bit.ADJRES = 0;
|
||||
else if (ADC0->AVGCTRL.bit.SAMPLENUM == ADC_AVGCTRL_SAMPLENUM_2_Val) ADC0->AVGCTRL.bit.ADJRES = 1;
|
||||
else if (ADC0->AVGCTRL.bit.SAMPLENUM == ADC_AVGCTRL_SAMPLENUM_4_Val) ADC0->AVGCTRL.bit.ADJRES = 2;
|
||||
else if (ADC0->AVGCTRL.bit.SAMPLENUM == ADC_AVGCTRL_SAMPLENUM_8_Val) ADC0->AVGCTRL.bit.ADJRES = 3;
|
||||
else ADC0->AVGCTRL.bit.ADJRES = 4;
|
||||
while (ADC0->SYNCBUSY.bit.AVGCTRL) { DBGC(DC_ADC0_AVGCTRL_SYNCING_2); }
|
||||
|
||||
//Settling
|
||||
ADC0->SAMPCTRL.bit.SAMPLEN = 45; //Sampling Time Length: 1-63, 1 ADC CLK per
|
||||
while (ADC0->SYNCBUSY.bit.SAMPCTRL) { DBGC(DC_ADC0_SAMPCTRL_SYNCING_1); }
|
||||
|
||||
//Load factory calibration data
|
||||
ADC0->CALIB.bit.BIASCOMP = (ADC0_FUSES_BIASCOMP_ADDR >> ADC0_FUSES_BIASCOMP_Pos) & ADC0_FUSES_BIASCOMP_Msk;
|
||||
ADC0->CALIB.bit.BIASR2R = (ADC0_FUSES_BIASR2R_ADDR >> ADC0_FUSES_BIASR2R_Pos) & ADC0_FUSES_BIASR2R_Msk;
|
||||
ADC0->CALIB.bit.BIASREFBUF = (ADC0_FUSES_BIASREFBUF_ADDR >> ADC0_FUSES_BIASREFBUF_Pos) & ADC0_FUSES_BIASREFBUF_Msk;
|
||||
|
||||
//Enable
|
||||
ADC0->CTRLA.bit.ENABLE = 1;
|
||||
while (ADC0->SYNCBUSY.bit.ENABLE) { DBGC(DC_ADC0_ENABLE_SYNCING_1); }
|
||||
|
||||
DBGC(DC_ADC0_INIT_COMPLETE);
|
||||
}
|
||||
|
||||
uint16_t adc_get(uint8_t muxpos)
|
||||
{
|
||||
ADC0->INPUTCTRL.bit.MUXPOS = muxpos;
|
||||
while (ADC0->SYNCBUSY.bit.INPUTCTRL) {}
|
||||
|
||||
ADC0->SWTRIG.bit.START = 1;
|
||||
while (ADC0->SYNCBUSY.bit.SWTRIG) {}
|
||||
while (!ADC0->INTFLAG.bit.RESRDY) {}
|
||||
|
||||
return ADC0->RESULT.reg;
|
||||
}
|
||||
|
37
tmk_core/protocol/arm_atsam/adc.h
Normal file
37
tmk_core/protocol/arm_atsam/adc.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
Copyright 2018 Massdrop Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _ADC_H_
|
||||
#define _ADC_H_
|
||||
|
||||
#define ADC_5V_START_LEVEL 2365
|
||||
|
||||
#define ADC_5V ADC_INPUTCTRL_MUXPOS_AIN12_Val
|
||||
#define ADC_CON1 ADC_INPUTCTRL_MUXPOS_AIN14_Val
|
||||
#define ADC_CON2 ADC_INPUTCTRL_MUXPOS_AIN13_Val
|
||||
|
||||
extern uint16_t v_5v;
|
||||
extern uint16_t v_5v_avg;
|
||||
extern uint16_t v_con_1;
|
||||
extern uint16_t v_con_2;
|
||||
extern uint16_t v_con_1_boot;
|
||||
extern uint16_t v_con_2_boot;
|
||||
|
||||
void ADC0_clock_init(void);
|
||||
void ADC0_init(void);
|
||||
|
||||
#endif //_ADC_H_
|
44
tmk_core/protocol/arm_atsam/arm_atsam_protocol.h
Normal file
44
tmk_core/protocol/arm_atsam/arm_atsam_protocol.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
Copyright 2018 Massdrop Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _ARM_ATSAM_PROTOCOL_H_
|
||||
#define _ARM_ATSAM_PROTOCOL_H_
|
||||
|
||||
#include "samd51j18a.h"
|
||||
#include "md_bootloader.h"
|
||||
|
||||
#include "d51_util.h"
|
||||
#include "clks.h"
|
||||
#include "adc.h"
|
||||
#include "i2c_master.h"
|
||||
#include "spi.h"
|
||||
|
||||
#include "./usb/usb2422.h"
|
||||
|
||||
#ifndef MD_BOOTLOADER
|
||||
|
||||
#include "main_arm_atsam.h"
|
||||
#include "led_matrix.h"
|
||||
#include "issi3733_driver.h"
|
||||
#include "./usb/compiler.h"
|
||||
#include "./usb/udc.h"
|
||||
#include "./usb/udi_cdc.h"
|
||||
|
||||
#endif //MD_BOOTLOADER
|
||||
|
||||
#endif //_ARM_ATSAM_PROTOCOL_H_
|
||||
|
439
tmk_core/protocol/arm_atsam/clks.c
Normal file
439
tmk_core/protocol/arm_atsam/clks.c
Normal file
|
@ -0,0 +1,439 @@
|
|||
/*
|
||||
Copyright 2018 Massdrop Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "arm_atsam_protocol.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
volatile clk_t system_clks;
|
||||
volatile uint64_t ms_clk;
|
||||
|
||||
volatile uint8_t us_delay_done;
|
||||
|
||||
const uint32_t sercom_apbbase[] = {(uint32_t)SERCOM0,(uint32_t)SERCOM1,(uint32_t)SERCOM2,(uint32_t)SERCOM3,(uint32_t)SERCOM4,(uint32_t)SERCOM5};
|
||||
const uint8_t sercom_pchan[] = {7, 8, 23, 24, 34, 35};
|
||||
|
||||
#define USE_DPLL_IND 0
|
||||
#define USE_DPLL_DEF GCLK_SOURCE_DPLL0
|
||||
|
||||
void CLK_oscctrl_init(void)
|
||||
{
|
||||
Oscctrl *posctrl = OSCCTRL;
|
||||
Gclk *pgclk = GCLK;
|
||||
|
||||
DBGC(DC_CLK_OSC_INIT_BEGIN);
|
||||
|
||||
//default setup on por
|
||||
system_clks.freq_dfll = FREQ_DFLL_DEFAULT;
|
||||
system_clks.freq_gclk[0] = system_clks.freq_dfll;
|
||||
|
||||
//configure and startup 16MHz xosc0
|
||||
posctrl->XOSCCTRL[0].bit.ENABLE = 0;
|
||||
posctrl->XOSCCTRL[0].bit.STARTUP = 0xD;
|
||||
posctrl->XOSCCTRL[0].bit.ENALC = 1;
|
||||
posctrl->XOSCCTRL[0].bit.IMULT = 5;
|
||||
posctrl->XOSCCTRL[0].bit.IPTAT = 3;
|
||||
posctrl->XOSCCTRL[0].bit.ONDEMAND = 0;
|
||||
posctrl->XOSCCTRL[0].bit.XTALEN = 1;
|
||||
posctrl->XOSCCTRL[0].bit.ENABLE = 1;
|
||||
while (posctrl->STATUS.bit.XOSCRDY0 == 0) { DBGC(DC_CLK_OSC_INIT_XOSC0_SYNC); }
|
||||
system_clks.freq_xosc0 = FREQ_XOSC0;
|
||||
|
||||
//configure and startup DPLL
|
||||
posctrl->Dpll[USE_DPLL_IND].DPLLCTRLA.bit.ENABLE = 0;
|
||||
while (posctrl->Dpll[USE_DPLL_IND].DPLLSYNCBUSY.bit.ENABLE) { DBGC(DC_CLK_OSC_INIT_DPLL_SYNC_DISABLE); }
|
||||
posctrl->Dpll[USE_DPLL_IND].DPLLCTRLB.bit.REFCLK = 2; //select XOSC0 (16MHz)
|
||||
posctrl->Dpll[USE_DPLL_IND].DPLLCTRLB.bit.DIV = 7; //16 MHz / (2 * (7 + 1)) = 1 MHz
|
||||
posctrl->Dpll[USE_DPLL_IND].DPLLRATIO.bit.LDR = PLL_RATIO; //1 MHz * (PLL_RATIO(47) + 1) = 48MHz
|
||||
while (posctrl->Dpll[USE_DPLL_IND].DPLLSYNCBUSY.bit.DPLLRATIO) { DBGC(DC_CLK_OSC_INIT_DPLL_SYNC_RATIO); }
|
||||
posctrl->Dpll[USE_DPLL_IND].DPLLCTRLA.bit.ONDEMAND = 0;
|
||||
posctrl->Dpll[USE_DPLL_IND].DPLLCTRLA.bit.ENABLE = 1;
|
||||
while (posctrl->Dpll[USE_DPLL_IND].DPLLSYNCBUSY.bit.ENABLE) { DBGC(DC_CLK_OSC_INIT_DPLL_SYNC_ENABLE); }
|
||||
while (posctrl->Dpll[USE_DPLL_IND].DPLLSTATUS.bit.LOCK == 0) { DBGC(DC_CLK_OSC_INIT_DPLL_WAIT_LOCK); }
|
||||
while (posctrl->Dpll[USE_DPLL_IND].DPLLSTATUS.bit.CLKRDY == 0) { DBGC(DC_CLK_OSC_INIT_DPLL_WAIT_CLKRDY); }
|
||||
system_clks.freq_dpll[0] = (system_clks.freq_xosc0 / 2 / (posctrl->Dpll[USE_DPLL_IND].DPLLCTRLB.bit.DIV + 1)) * (posctrl->Dpll[USE_DPLL_IND].DPLLRATIO.bit.LDR + 1);
|
||||
|
||||
//change gclk0 to DPLL
|
||||
pgclk->GENCTRL[GEN_DPLL0].bit.SRC = USE_DPLL_DEF;
|
||||
while (pgclk->SYNCBUSY.bit.GENCTRL0) { DBGC(DC_CLK_OSC_INIT_GCLK_SYNC_GENCTRL0); }
|
||||
|
||||
system_clks.freq_gclk[0] = system_clks.freq_dpll[0];
|
||||
|
||||
DBGC(DC_CLK_OSC_INIT_COMPLETE);
|
||||
}
|
||||
|
||||
//configure for 1MHz (1 usec timebase)
|
||||
//call CLK_set_gclk_freq(GEN_TC45, FREQ_TC45_DEFAULT);
|
||||
uint32_t CLK_set_gclk_freq(uint8_t gclkn, uint32_t freq)
|
||||
{
|
||||
Gclk *pgclk = GCLK;
|
||||
|
||||
DBGC(DC_CLK_SET_GCLK_FREQ_BEGIN);
|
||||
|
||||
while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_SET_GCLK_FREQ_SYNC_1); }
|
||||
pgclk->GENCTRL[gclkn].bit.SRC = USE_DPLL_DEF;
|
||||
while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_SET_GCLK_FREQ_SYNC_2); }
|
||||
pgclk->GENCTRL[gclkn].bit.DIV = (uint8_t)(system_clks.freq_dpll[0] / freq);
|
||||
while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_SET_GCLK_FREQ_SYNC_3); }
|
||||
pgclk->GENCTRL[gclkn].bit.DIVSEL = 0;
|
||||
while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_SET_GCLK_FREQ_SYNC_4); }
|
||||
pgclk->GENCTRL[gclkn].bit.GENEN = 1;
|
||||
while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_SET_GCLK_FREQ_SYNC_5); }
|
||||
system_clks.freq_gclk[gclkn] = system_clks.freq_dpll[0] / pgclk->GENCTRL[gclkn].bit.DIV;
|
||||
|
||||
DBGC(DC_CLK_SET_GCLK_FREQ_COMPLETE);
|
||||
|
||||
return system_clks.freq_gclk[gclkn];
|
||||
}
|
||||
|
||||
void CLK_init_osc(void)
|
||||
{
|
||||
uint8_t gclkn = GEN_OSC0;
|
||||
Gclk *pgclk = GCLK;
|
||||
|
||||
DBGC(DC_CLK_INIT_OSC_BEGIN);
|
||||
|
||||
while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_INIT_OSC_SYNC_1); }
|
||||
pgclk->GENCTRL[gclkn].bit.SRC = GCLK_SOURCE_XOSC0;
|
||||
while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_INIT_OSC_SYNC_2); }
|
||||
pgclk->GENCTRL[gclkn].bit.DIV = 1;
|
||||
while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_INIT_OSC_SYNC_3); }
|
||||
pgclk->GENCTRL[gclkn].bit.DIVSEL = 0;
|
||||
while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_INIT_OSC_SYNC_4); }
|
||||
pgclk->GENCTRL[gclkn].bit.GENEN = 1;
|
||||
while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_INIT_OSC_SYNC_5); }
|
||||
system_clks.freq_gclk[gclkn] = system_clks.freq_xosc0;
|
||||
|
||||
DBGC(DC_CLK_INIT_OSC_COMPLETE);
|
||||
}
|
||||
|
||||
void CLK_reset_time(void)
|
||||
{
|
||||
Tc *ptc4 = TC4;
|
||||
Tc *ptc0 = TC0;
|
||||
|
||||
ms_clk = 0;
|
||||
|
||||
DBGC(DC_CLK_RESET_TIME_BEGIN);
|
||||
|
||||
//stop counters
|
||||
ptc4->COUNT16.CTRLA.bit.ENABLE = 0;
|
||||
while (ptc4->COUNT16.SYNCBUSY.bit.ENABLE) {}
|
||||
ptc0->COUNT32.CTRLA.bit.ENABLE = 0;
|
||||
while (ptc0->COUNT32.SYNCBUSY.bit.ENABLE) {}
|
||||
//zero counters
|
||||
ptc4->COUNT16.COUNT.reg = 0;
|
||||
while (ptc4->COUNT16.SYNCBUSY.bit.COUNT) {}
|
||||
ptc0->COUNT32.COUNT.reg = 0;
|
||||
while (ptc0->COUNT32.SYNCBUSY.bit.COUNT) {}
|
||||
//start counters
|
||||
ptc0->COUNT32.CTRLA.bit.ENABLE = 1;
|
||||
while (ptc0->COUNT32.SYNCBUSY.bit.ENABLE) {}
|
||||
ptc4->COUNT16.CTRLA.bit.ENABLE = 1;
|
||||
while (ptc4->COUNT16.SYNCBUSY.bit.ENABLE) {}
|
||||
|
||||
DBGC(DC_CLK_RESET_TIME_COMPLETE);
|
||||
}
|
||||
|
||||
void TC4_Handler()
|
||||
{
|
||||
if (TC4->COUNT16.INTFLAG.bit.MC0)
|
||||
{
|
||||
TC4->COUNT16.INTFLAG.reg = TC_INTENCLR_MC0;
|
||||
ms_clk++;
|
||||
}
|
||||
}
|
||||
|
||||
void TC5_Handler()
|
||||
{
|
||||
if (TC5->COUNT16.INTFLAG.bit.MC0)
|
||||
{
|
||||
TC5->COUNT16.INTFLAG.reg = TC_INTENCLR_MC0;
|
||||
us_delay_done = 1;
|
||||
TC5->COUNT16.CTRLA.bit.ENABLE = 0;
|
||||
while (TC5->COUNT16.SYNCBUSY.bit.ENABLE) {}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t CLK_enable_timebase(void)
|
||||
{
|
||||
Gclk *pgclk = GCLK;
|
||||
Mclk *pmclk = MCLK;
|
||||
Tc *ptc4 = TC4;
|
||||
Tc *ptc5 = TC5;
|
||||
Tc *ptc0 = TC0;
|
||||
Evsys *pevsys = EVSYS;
|
||||
|
||||
DBGC(DC_CLK_ENABLE_TIMEBASE_BEGIN);
|
||||
|
||||
//gclk2 highspeed time base
|
||||
CLK_set_gclk_freq(GEN_TC45, FREQ_TC45_DEFAULT);
|
||||
CLK_init_osc();
|
||||
|
||||
//unmask TC4, sourcegclk2 to TC4
|
||||
pmclk->APBCMASK.bit.TC4_ = 1;
|
||||
pgclk->PCHCTRL[TC4_GCLK_ID].bit.GEN = GEN_TC45;
|
||||
pgclk->PCHCTRL[TC4_GCLK_ID].bit.CHEN = 1;
|
||||
|
||||
//unmask TC5 sourcegclk2 to TC5
|
||||
pmclk->APBCMASK.bit.TC5_ = 1;
|
||||
pgclk->PCHCTRL[TC5_GCLK_ID].bit.GEN = GEN_TC45;
|
||||
pgclk->PCHCTRL[TC5_GCLK_ID].bit.CHEN = 1;
|
||||
|
||||
//configure TC4
|
||||
DBGC(DC_CLK_ENABLE_TIMEBASE_TC4_BEGIN);
|
||||
ptc4->COUNT16.CTRLA.bit.ENABLE = 0;
|
||||
while (ptc4->COUNT16.SYNCBUSY.bit.ENABLE) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC4_SYNC_DISABLE); }
|
||||
ptc4->COUNT16.CTRLA.bit.SWRST = 1;
|
||||
while (ptc4->COUNT16.SYNCBUSY.bit.SWRST) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC4_SYNC_SWRST_1); }
|
||||
while (ptc4->COUNT16.CTRLA.bit.SWRST) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC4_SYNC_SWRST_2); }
|
||||
|
||||
//CTRLA defaults
|
||||
//CTRLB as default, counting up
|
||||
ptc4->COUNT16.CTRLBCLR.reg = 5;
|
||||
while (ptc4->COUNT16.SYNCBUSY.bit.CTRLB) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC4_SYNC_CLTRB); }
|
||||
ptc4->COUNT16.CC[0].reg = 999;
|
||||
while (ptc4->COUNT16.SYNCBUSY.bit.CC0) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC4_SYNC_CC0); }
|
||||
//ptc4->COUNT16.DBGCTRL.bit.DBGRUN = 1;
|
||||
|
||||
//wave mode
|
||||
ptc4->COUNT16.WAVE.bit.WAVEGEN = 1; //MFRQ match frequency mode, toggle each CC match
|
||||
//generate event for next stage
|
||||
ptc4->COUNT16.EVCTRL.bit.MCEO0 = 1;
|
||||
|
||||
NVIC_EnableIRQ(TC4_IRQn);
|
||||
ptc4->COUNT16.INTENSET.bit.MC0 = 1;
|
||||
|
||||
DBGC(DC_CLK_ENABLE_TIMEBASE_TC4_COMPLETE);
|
||||
|
||||
//configure TC5
|
||||
DBGC(DC_CLK_ENABLE_TIMEBASE_TC5_BEGIN);
|
||||
ptc5->COUNT16.CTRLA.bit.ENABLE = 0;
|
||||
while (ptc5->COUNT16.SYNCBUSY.bit.ENABLE) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC5_SYNC_DISABLE); }
|
||||
ptc5->COUNT16.CTRLA.bit.SWRST = 1;
|
||||
while (ptc5->COUNT16.SYNCBUSY.bit.SWRST) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC5_SYNC_SWRST_1); }
|
||||
while (ptc5->COUNT16.CTRLA.bit.SWRST) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC5_SYNC_SWRST_2); }
|
||||
|
||||
//CTRLA defaults
|
||||
//CTRLB as default, counting up
|
||||
ptc5->COUNT16.CTRLBCLR.reg = 5;
|
||||
while (ptc5->COUNT16.SYNCBUSY.bit.CTRLB) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC5_SYNC_CLTRB); }
|
||||
//ptc5->COUNT16.DBGCTRL.bit.DBGRUN = 1;
|
||||
|
||||
//wave mode
|
||||
ptc5->COUNT16.WAVE.bit.WAVEGEN = 1; //MFRQ match frequency mode, toggle each CC match
|
||||
//generate event for next stage
|
||||
ptc5->COUNT16.EVCTRL.bit.MCEO0 = 1;
|
||||
|
||||
NVIC_EnableIRQ(TC5_IRQn);
|
||||
ptc5->COUNT16.INTENSET.bit.MC0 = 1;
|
||||
|
||||
DBGC(DC_CLK_ENABLE_TIMEBASE_TC5_COMPLETE);
|
||||
|
||||
//unmask TC0,1, sourcegclk2 to TC0,1
|
||||
pmclk->APBAMASK.bit.TC0_ = 1;
|
||||
pgclk->PCHCTRL[TC0_GCLK_ID].bit.GEN = GEN_TC45;
|
||||
pgclk->PCHCTRL[TC0_GCLK_ID].bit.CHEN = 1;
|
||||
|
||||
pmclk->APBAMASK.bit.TC1_ = 1;
|
||||
pgclk->PCHCTRL[TC1_GCLK_ID].bit.GEN = GEN_TC45;
|
||||
pgclk->PCHCTRL[TC1_GCLK_ID].bit.CHEN = 1;
|
||||
|
||||
//configure TC0
|
||||
DBGC(DC_CLK_ENABLE_TIMEBASE_TC0_BEGIN);
|
||||
ptc0->COUNT32.CTRLA.bit.ENABLE = 0;
|
||||
while (ptc0->COUNT32.SYNCBUSY.bit.ENABLE) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC0_SYNC_DISABLE); }
|
||||
ptc0->COUNT32.CTRLA.bit.SWRST = 1;
|
||||
while (ptc0->COUNT32.SYNCBUSY.bit.SWRST) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC0_SYNC_SWRST_1); }
|
||||
while (ptc0->COUNT32.CTRLA.bit.SWRST) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC0_SYNC_SWRST_2); }
|
||||
//CTRLA as default
|
||||
ptc0->COUNT32.CTRLA.bit.MODE = 2; //32 bit mode
|
||||
ptc0->COUNT32.EVCTRL.bit.TCEI = 1; //enable incoming events
|
||||
ptc0->COUNT32.EVCTRL.bit.EVACT = 2 ; //count events
|
||||
|
||||
DBGC(DC_CLK_ENABLE_TIMEBASE_TC0_COMPLETE);
|
||||
|
||||
DBGC(DC_CLK_ENABLE_TIMEBASE_EVSYS_BEGIN);
|
||||
|
||||
//configure event system
|
||||
pmclk->APBBMASK.bit.EVSYS_ = 1;
|
||||
pgclk->PCHCTRL[EVSYS_GCLK_ID_0].bit.GEN = GEN_TC45;
|
||||
pgclk->PCHCTRL[EVSYS_GCLK_ID_0].bit.CHEN = 1;
|
||||
pevsys->USER[44].reg = EVSYS_ID_USER_PORT_EV_0; //TC0 will get event channel 0
|
||||
pevsys->Channel[0].CHANNEL.bit.EDGSEL = EVSYS_CHANNEL_EDGSEL_RISING_EDGE_Val; //Rising edge
|
||||
pevsys->Channel[0].CHANNEL.bit.PATH = EVSYS_CHANNEL_PATH_SYNCHRONOUS_Val; //Synchronous
|
||||
pevsys->Channel[0].CHANNEL.bit.EVGEN = EVSYS_ID_GEN_TC4_MCX_0; //TC4 MC0
|
||||
|
||||
DBGC(DC_CLK_ENABLE_TIMEBASE_EVSYS_COMPLETE);
|
||||
|
||||
CLK_reset_time();
|
||||
|
||||
ADC0_clock_init();
|
||||
|
||||
DBGC(DC_CLK_ENABLE_TIMEBASE_COMPLETE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t CLK_get_ms(void)
|
||||
{
|
||||
return ms_clk;
|
||||
}
|
||||
|
||||
void CLK_delay_us(uint16_t usec)
|
||||
{
|
||||
us_delay_done = 0;
|
||||
|
||||
if (TC5->COUNT16.CTRLA.bit.ENABLE)
|
||||
{
|
||||
TC5->COUNT16.CTRLA.bit.ENABLE = 0;
|
||||
while (TC5->COUNT16.SYNCBUSY.bit.ENABLE) {}
|
||||
}
|
||||
|
||||
if (usec < 10) usec = 0;
|
||||
else usec -= 10;
|
||||
|
||||
TC5->COUNT16.CC[0].reg = usec;
|
||||
while (TC5->COUNT16.SYNCBUSY.bit.CC0) {}
|
||||
|
||||
TC5->COUNT16.CTRLA.bit.ENABLE = 1;
|
||||
while (TC5->COUNT16.SYNCBUSY.bit.ENABLE) {}
|
||||
|
||||
while (!us_delay_done) {}
|
||||
}
|
||||
|
||||
void CLK_delay_ms(uint64_t msec)
|
||||
{
|
||||
msec += CLK_get_ms();
|
||||
while (msec > CLK_get_ms()) {}
|
||||
}
|
||||
|
||||
void clk_enable_sercom_apbmask(int sercomn)
|
||||
{
|
||||
Mclk *pmclk = MCLK;
|
||||
switch (sercomn)
|
||||
{
|
||||
case 0:
|
||||
pmclk->APBAMASK.bit.SERCOM0_ = 1;
|
||||
break;
|
||||
case 1:
|
||||
pmclk->APBAMASK.bit.SERCOM1_ = 1;
|
||||
break;
|
||||
case 2:
|
||||
pmclk->APBBMASK.bit.SERCOM2_ = 1;
|
||||
break;
|
||||
case 3:
|
||||
pmclk->APBBMASK.bit.SERCOM3_ = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//call CLK_oscctrl_init first
|
||||
//call CLK_set_spi_freq(CHAN_SERCOM_SPI, FREQ_SPI_DEFAULT);
|
||||
uint32_t CLK_set_spi_freq(uint8_t sercomn, uint32_t freq)
|
||||
{
|
||||
DBGC(DC_CLK_SET_SPI_FREQ_BEGIN);
|
||||
|
||||
Gclk *pgclk = GCLK;
|
||||
Sercom *psercom = (Sercom *)sercom_apbbase[sercomn];
|
||||
clk_enable_sercom_apbmask(sercomn);
|
||||
|
||||
//all gclk0 for now
|
||||
pgclk->PCHCTRL[sercom_pchan[sercomn]].bit.GEN = 0;
|
||||
pgclk->PCHCTRL[sercom_pchan[sercomn]].bit.CHEN = 1;
|
||||
|
||||
psercom->I2CM.CTRLA.bit.SWRST = 1;
|
||||
while (psercom->I2CM.SYNCBUSY.bit.SWRST) {}
|
||||
while (psercom->I2CM.CTRLA.bit.SWRST) {}
|
||||
|
||||
psercom->SPI.BAUD.reg = (uint8_t) (system_clks.freq_gclk[0]/2/freq-1);
|
||||
system_clks.freq_spi = system_clks.freq_gclk[0]/2/(psercom->SPI.BAUD.reg+1);
|
||||
system_clks.freq_sercom[sercomn] = system_clks.freq_spi;
|
||||
|
||||
DBGC(DC_CLK_SET_SPI_FREQ_COMPLETE);
|
||||
|
||||
return system_clks.freq_spi;
|
||||
}
|
||||
|
||||
//call CLK_oscctrl_init first
|
||||
//call CLK_set_i2c0_freq(CHAN_SERCOM_I2C0, FREQ_I2C0_DEFAULT);
|
||||
uint32_t CLK_set_i2c0_freq(uint8_t sercomn, uint32_t freq)
|
||||
{
|
||||
DBGC(DC_CLK_SET_I2C0_FREQ_BEGIN);
|
||||
|
||||
Gclk *pgclk = GCLK;
|
||||
Sercom *psercom = (Sercom *)sercom_apbbase[sercomn];
|
||||
clk_enable_sercom_apbmask(sercomn);
|
||||
|
||||
//all gclk0 for now
|
||||
pgclk->PCHCTRL[sercom_pchan[sercomn]].bit.GEN = 0;
|
||||
pgclk->PCHCTRL[sercom_pchan[sercomn]].bit.CHEN = 1;
|
||||
|
||||
psercom->I2CM.CTRLA.bit.SWRST = 1;
|
||||
while (psercom->I2CM.SYNCBUSY.bit.SWRST) {}
|
||||
while (psercom->I2CM.CTRLA.bit.SWRST) {}
|
||||
|
||||
psercom->I2CM.BAUD.bit.BAUD = (uint8_t) (system_clks.freq_gclk[0]/2/freq-1);
|
||||
system_clks.freq_i2c0 = system_clks.freq_gclk[0]/2/(psercom->I2CM.BAUD.bit.BAUD+1);
|
||||
system_clks.freq_sercom[sercomn] = system_clks.freq_i2c0;
|
||||
|
||||
DBGC(DC_CLK_SET_I2C0_FREQ_COMPLETE);
|
||||
|
||||
return system_clks.freq_i2c0;
|
||||
}
|
||||
|
||||
//call CLK_oscctrl_init first
|
||||
//call CLK_set_i2c1_freq(CHAN_SERCOM_I2C1, FREQ_I2C1_DEFAULT);
|
||||
uint32_t CLK_set_i2c1_freq(uint8_t sercomn, uint32_t freq)
|
||||
{
|
||||
DBGC(DC_CLK_SET_I2C1_FREQ_BEGIN);
|
||||
|
||||
Gclk *pgclk = GCLK;
|
||||
Sercom *psercom = (Sercom *)sercom_apbbase[sercomn];
|
||||
clk_enable_sercom_apbmask(sercomn);
|
||||
|
||||
//all gclk0 for now
|
||||
pgclk->PCHCTRL[sercom_pchan[sercomn]].bit.GEN = 0;
|
||||
pgclk->PCHCTRL[sercom_pchan[sercomn]].bit.CHEN = 1;
|
||||
|
||||
psercom->I2CM.CTRLA.bit.SWRST = 1;
|
||||
while (psercom->I2CM.SYNCBUSY.bit.SWRST) {}
|
||||
while (psercom->I2CM.CTRLA.bit.SWRST) {}
|
||||
|
||||
psercom->I2CM.BAUD.bit.BAUD = (uint8_t) (system_clks.freq_gclk[0]/2/freq-10);
|
||||
system_clks.freq_i2c1 = system_clks.freq_gclk[0]/2/(psercom->I2CM.BAUD.bit.BAUD+10);
|
||||
system_clks.freq_sercom[sercomn] = system_clks.freq_i2c1;
|
||||
|
||||
DBGC(DC_CLK_SET_I2C1_FREQ_COMPLETE);
|
||||
|
||||
return system_clks.freq_i2c1;
|
||||
}
|
||||
|
||||
void CLK_init(void)
|
||||
{
|
||||
DBGC(DC_CLK_INIT_BEGIN);
|
||||
|
||||
memset((void *)&system_clks,0,sizeof(system_clks));
|
||||
|
||||
CLK_oscctrl_init();
|
||||
CLK_enable_timebase();
|
||||
|
||||
DBGC(DC_CLK_INIT_COMPLETE);
|
||||
}
|
||||
|
90
tmk_core/protocol/arm_atsam/clks.h
Normal file
90
tmk_core/protocol/arm_atsam/clks.h
Normal file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
Copyright 2018 Massdrop Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _CLKS_H_
|
||||
#define _CLKS_H_
|
||||
|
||||
#ifndef MD_BOOTLOADER
|
||||
|
||||
//From keyboard
|
||||
#include "config_led.h"
|
||||
#include "config.h"
|
||||
|
||||
#endif //MD_BOOTLOADER
|
||||
|
||||
#define PLL_RATIO 47 //mcu frequency ((X+1)MHz)
|
||||
#define FREQ_DFLL_DEFAULT 48000000 //DFLL frequency / usb clock
|
||||
#define FREQ_SPI_DEFAULT 1000000 //spi to 595 shift regs
|
||||
#define FREQ_I2C0_DEFAULT 100000 //i2c to hub
|
||||
#define FREQ_I2C1_DEFAULT I2C_HZ //i2c to LED drivers
|
||||
#define FREQ_TC45_DEFAULT 1000000 //1 usec resolution
|
||||
|
||||
//I2C1 Set ~Result PWM Time (2x Drivers)
|
||||
// 1000000 1090000
|
||||
// 900000 1000000 3.82ms
|
||||
// 800000 860000
|
||||
// 700000 750000
|
||||
// 600000 630000
|
||||
// 580000 615000 6.08ms
|
||||
// 500000 522000
|
||||
|
||||
#define FREQ_XOSC0 16000000
|
||||
|
||||
#define CHAN_SERCOM_SPI 2 //shift regs
|
||||
#define CHAN_SERCOM_I2C0 0 //hub
|
||||
#define CHAN_SERCOM_I2C1 1 //led drivers
|
||||
#define CHAN_SERCOM_UART 3 //debug util
|
||||
|
||||
//Generator clock channels
|
||||
#define GEN_DPLL0 0
|
||||
#define GEN_OSC0 1
|
||||
#define GEN_TC45 2
|
||||
|
||||
#define SERCOM_COUNT 5
|
||||
#define GCLK_COUNT 12
|
||||
|
||||
typedef struct clk_s {
|
||||
uint32_t freq_dfll;
|
||||
uint32_t freq_dpll[2];
|
||||
uint32_t freq_sercom[SERCOM_COUNT];
|
||||
uint32_t freq_gclk[GCLK_COUNT];
|
||||
uint32_t freq_xosc0;
|
||||
uint32_t freq_spi;
|
||||
uint32_t freq_i2c0;
|
||||
uint32_t freq_i2c1;
|
||||
uint32_t freq_uart;
|
||||
uint32_t freq_adc0;
|
||||
} clk_t;
|
||||
|
||||
extern volatile clk_t system_clks;
|
||||
extern volatile uint64_t ms_clk;
|
||||
|
||||
void CLK_oscctrl_init(void);
|
||||
void CLK_reset_time(void);
|
||||
uint32_t CLK_set_gclk_freq(uint8_t gclkn, uint32_t freq);
|
||||
uint32_t CLK_enable_timebase(void);
|
||||
uint32_t CLK_get_ms(void);
|
||||
uint64_t CLK_get_us(void);
|
||||
void CLK_delay_us(uint16_t usec);
|
||||
void CLK_delay_ms(uint64_t msec);
|
||||
|
||||
uint32_t CLK_set_spi_freq(uint8_t sercomn, uint32_t freq);
|
||||
uint32_t CLK_set_i2c0_freq(uint8_t sercomn, uint32_t freq);
|
||||
uint32_t CLK_set_i2c1_freq(uint8_t sercomn, uint32_t freq);
|
||||
void CLK_init(void);
|
||||
|
||||
#endif // _CLKS_H_
|
227
tmk_core/protocol/arm_atsam/d51_util.c
Normal file
227
tmk_core/protocol/arm_atsam/d51_util.c
Normal file
|
@ -0,0 +1,227 @@
|
|||
#include "d51_util.h"
|
||||
|
||||
static volatile uint32_t w;
|
||||
|
||||
//Display unsigned 32-bit number by port toggling DBG_1 (to view on a scope)
|
||||
//Read as follows: 1230 = | | | | | | || (note zero is fast double toggle)
|
||||
#define DBG_PAUSE 5
|
||||
void dbg_print(uint32_t x)
|
||||
{
|
||||
int8_t t;
|
||||
uint32_t n;
|
||||
uint32_t p, p2;
|
||||
|
||||
if (x < 10) t = 0;
|
||||
else if (x < 100) t = 1;
|
||||
else if (x < 1000) t = 2;
|
||||
else if (x < 10000) t = 3;
|
||||
else if (x < 100000) t = 4;
|
||||
else if (x < 1000000) t = 5;
|
||||
else if (x < 10000000) t = 6;
|
||||
else if (x < 100000000) t = 7;
|
||||
else if (x < 1000000000) t = 8;
|
||||
else t = 9;
|
||||
|
||||
while (t >= 0)
|
||||
{
|
||||
p2 = t;
|
||||
p = 1;
|
||||
while (p2--) p *= 10;
|
||||
n = x / p;
|
||||
x -= n * p;
|
||||
if (!n)
|
||||
{
|
||||
DBG_1_ON;
|
||||
DBG_1_OFF;
|
||||
DBG_1_ON;
|
||||
DBG_1_OFF;
|
||||
n--;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (n > 0)
|
||||
{
|
||||
DBG_1_ON;
|
||||
DBG_1_OFF;
|
||||
n--;
|
||||
}
|
||||
}
|
||||
|
||||
t--;
|
||||
}
|
||||
|
||||
for (w = DBG_PAUSE; w; w--); //Long pause after number is complete
|
||||
}
|
||||
|
||||
//Display unsigned 32-bit number through debug led
|
||||
//Read as follows: 1230 = [*] [* *] [* * *] [**] (note zero is fast double flash)
|
||||
#define DLED_ONTIME 1000000
|
||||
#define DLED_PAUSE 1500000
|
||||
void dled_print(uint32_t x, uint8_t long_pause)
|
||||
{
|
||||
int8_t t;
|
||||
uint32_t n;
|
||||
uint32_t p, p2;
|
||||
|
||||
if (x < 10) t = 0;
|
||||
else if (x < 100) t = 1;
|
||||
else if (x < 1000) t = 2;
|
||||
else if (x < 10000) t = 3;
|
||||
else if (x < 100000) t = 4;
|
||||
else if (x < 1000000) t = 5;
|
||||
else if (x < 10000000) t = 6;
|
||||
else if (x < 100000000) t = 7;
|
||||
else if (x < 1000000000) t = 8;
|
||||
else t = 9;
|
||||
|
||||
while (t >= 0)
|
||||
{
|
||||
p2 = t;
|
||||
p = 1;
|
||||
while (p2--) p *= 10;
|
||||
n = x / p;
|
||||
x -= n * p;
|
||||
if (!n)
|
||||
{
|
||||
DBG_LED_ON;
|
||||
for (w = DLED_ONTIME / 4; w; w--);
|
||||
DBG_LED_OFF;
|
||||
for (w = DLED_ONTIME / 4; w; w--);
|
||||
DBG_LED_ON;
|
||||
for (w = DLED_ONTIME / 4; w; w--);
|
||||
DBG_LED_OFF;
|
||||
for (w = DLED_ONTIME / 4; w; w--);
|
||||
n--;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (n > 0)
|
||||
{
|
||||
DBG_LED_ON;
|
||||
for (w = DLED_ONTIME; w; w--);
|
||||
DBG_LED_OFF;
|
||||
for (w = DLED_ONTIME / 2; w; w--);
|
||||
n--;
|
||||
}
|
||||
}
|
||||
|
||||
for (w = DLED_PAUSE; w; w--);
|
||||
t--;
|
||||
}
|
||||
|
||||
if (long_pause)
|
||||
{
|
||||
for (w = DLED_PAUSE * 4; w; w--);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_BOOT_TRACING_ENABLE
|
||||
|
||||
volatile uint32_t debug_code;
|
||||
|
||||
//These macros are for compile time substitution
|
||||
#define DEBUG_BOOT_TRACING_EXTINTn (DEBUG_BOOT_TRACING_PIN % _U_(0x10))
|
||||
#define DEBUG_BOOT_TRACING_EXTINTb (_U_(0x1) << DEBUG_BOOT_TRACING_EXTINTn)
|
||||
#define DEBUG_BOOT_TRACING_CONFIG_INDn (DEBUG_BOOT_TRACING_EXTINTn / _U_(0x8))
|
||||
#define DEBUG_BOOT_TRACING_CONFIG_SENSEn (DEBUG_BOOT_TRACING_EXTINTn % _U_(0x8))
|
||||
#define DEBUG_BOOT_TRACING_CONFIG_SENSEb (DEBUG_BOOT_TRACING_CONFIG_SENSEn * _U_(0x4))
|
||||
#define DEBUG_BOOT_TRACING_IRQn (EIC_0_IRQn + DEBUG_BOOT_TRACING_EXTINTn)
|
||||
|
||||
//These macros perform PORT+PIN definition translation to IRQn in the preprocessor
|
||||
#define PORTPIN_TO_IRQn_EXPAND(def) def
|
||||
#define PORTPIN_TO_IRQn_DEF(def) PORTPIN_TO_IRQn_EXPAND(def)
|
||||
#if DEBUG_BOOT_TRACING_PIN < 10
|
||||
#define PORTPIN_TO_IRQn_TODEF(port, pin) PORTPIN_TO_IRQn_DEF(PIN_ ## port ## 0 ## pin ## A_EIC_EXTINT_NUM)
|
||||
#else
|
||||
#define PORTPIN_TO_IRQn_TODEF(port, pin) PORTPIN_TO_IRQn_DEF(PIN_ ## port ## pin ## A_EIC_EXTINT_NUM)
|
||||
#endif
|
||||
#define PORTPIN_TO_IRQn(port, pin) PORTPIN_TO_IRQn_TODEF(port, pin)
|
||||
|
||||
//These macros perform function name output in the preprocessor
|
||||
#define DEBUG_BOOT_TRACING_HANDLER_CONCAT(irq) void EIC_ ## irq ## _Handler(void)
|
||||
#define DEBUG_BOOT_TRACING_HANDLER(irq) DEBUG_BOOT_TRACING_HANDLER_CONCAT(irq)
|
||||
|
||||
//To generate the function name of the IRQ handler catching boot tracing,
|
||||
// certain macros must be undefined, so save their current values to macro stack
|
||||
#pragma push_macro("PA")
|
||||
#pragma push_macro("PB")
|
||||
#pragma push_macro("_L_")
|
||||
|
||||
//Undefine / redefine pushed macros
|
||||
#undef PA
|
||||
#undef PB
|
||||
#undef _L_
|
||||
#define _L_(x) x
|
||||
|
||||
//Perform the work and output
|
||||
//Ex: PORT PB, PIN 31 = void EIC_15_Handler(void)
|
||||
DEBUG_BOOT_TRACING_HANDLER(PORTPIN_TO_IRQn(DEBUG_BOOT_TRACING_PORT, DEBUG_BOOT_TRACING_PIN))
|
||||
|
||||
//Restore macros
|
||||
#pragma pop_macro("PA")
|
||||
#pragma pop_macro("PB")
|
||||
#pragma pop_macro("_L_")
|
||||
{
|
||||
//This is only for non-functional keyboard troubleshooting and should be disabled after boot
|
||||
//Intention is to lock up the keyboard here with repeating debug led code
|
||||
while (1)
|
||||
{
|
||||
dled_print(debug_code, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void debug_code_init(void)
|
||||
{
|
||||
DBGC(DC_UNSET);
|
||||
|
||||
//Configure Ports for EIC
|
||||
PORT->Group[DEBUG_BOOT_TRACING_PORT].DIRCLR.reg = 1 << DEBUG_BOOT_TRACING_PIN; //Input
|
||||
PORT->Group[DEBUG_BOOT_TRACING_PORT].OUTSET.reg = 1 << DEBUG_BOOT_TRACING_PIN; //High
|
||||
PORT->Group[DEBUG_BOOT_TRACING_PORT].PINCFG[DEBUG_BOOT_TRACING_PIN].bit.INEN = 1; //Input Enable
|
||||
PORT->Group[DEBUG_BOOT_TRACING_PORT].PINCFG[DEBUG_BOOT_TRACING_PIN].bit.PULLEN = 1; //Pull Enable
|
||||
PORT->Group[DEBUG_BOOT_TRACING_PORT].PINCFG[DEBUG_BOOT_TRACING_PIN].bit.PMUXEN = 1; //Mux Enable
|
||||
PORT->Group[DEBUG_BOOT_TRACING_PORT].PMUX[DEBUG_BOOT_TRACING_PIN / 2].bit.PMUXO = 0; //Mux A
|
||||
|
||||
//Enable CLK_EIC_APB
|
||||
MCLK->APBAMASK.bit.EIC_ = 1;
|
||||
|
||||
//Configure EIC
|
||||
EIC->CTRLA.bit.SWRST = 1;
|
||||
while (EIC->SYNCBUSY.bit.SWRST) {}
|
||||
EIC->ASYNCH.reg = DEBUG_BOOT_TRACING_EXTINTb;
|
||||
EIC->INTENSET.reg = DEBUG_BOOT_TRACING_EXTINTb;
|
||||
EIC->CONFIG[DEBUG_BOOT_TRACING_CONFIG_INDn].reg |= (EIC_CONFIG_SENSE0_FALL_Val << DEBUG_BOOT_TRACING_CONFIG_SENSEb);
|
||||
EIC->CTRLA.bit.ENABLE = 1;
|
||||
while (EIC->SYNCBUSY.bit.ENABLE) {}
|
||||
|
||||
//Enable EIC IRQ
|
||||
NVIC_EnableIRQ(DEBUG_BOOT_TRACING_IRQn);
|
||||
}
|
||||
|
||||
void debug_code_disable(void)
|
||||
{
|
||||
//Disable EIC IRQ
|
||||
NVIC_DisableIRQ(DEBUG_BOOT_TRACING_IRQn);
|
||||
|
||||
//Disable EIC
|
||||
EIC->CTRLA.bit.ENABLE = 0;
|
||||
while (EIC->SYNCBUSY.bit.ENABLE) {}
|
||||
|
||||
//Default port configuration
|
||||
PORT->Group[DEBUG_BOOT_TRACING_PORT].DIRCLR.reg = 1 << DEBUG_BOOT_TRACING_PIN; //Input
|
||||
PORT->Group[DEBUG_BOOT_TRACING_PORT].OUTCLR.reg = 1 << DEBUG_BOOT_TRACING_PIN; //Low
|
||||
PORT->Group[DEBUG_BOOT_TRACING_PORT].PINCFG[DEBUG_BOOT_TRACING_PIN].bit.INEN = 0; //Input Disable
|
||||
PORT->Group[DEBUG_BOOT_TRACING_PORT].PINCFG[DEBUG_BOOT_TRACING_PIN].bit.PULLEN = 0; //Pull Disable
|
||||
PORT->Group[DEBUG_BOOT_TRACING_PORT].PINCFG[DEBUG_BOOT_TRACING_PIN].bit.PMUXEN = 0; //Mux Disable
|
||||
PORT->Group[DEBUG_BOOT_TRACING_PORT].PMUX[DEBUG_BOOT_TRACING_PIN / 2].bit.PMUXO = 0; //Mux A
|
||||
|
||||
//Disable CLK_EIC_APB
|
||||
MCLK->APBAMASK.bit.EIC_ = 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void debug_code_init(void) {}
|
||||
void debug_code_disable(void) {}
|
||||
|
||||
#endif //DEBUG_BOOT_TRACING_ENABLE
|
223
tmk_core/protocol/arm_atsam/d51_util.h
Normal file
223
tmk_core/protocol/arm_atsam/d51_util.h
Normal file
|
@ -0,0 +1,223 @@
|
|||
/*
|
||||
Copyright 2018 Massdrop Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _D51_UTIL_H_
|
||||
#define _D51_UTIL_H_
|
||||
|
||||
#include "samd51j18a.h"
|
||||
|
||||
/* Debug LED */
|
||||
#if DEBUG_LED_ENABLE == 1
|
||||
#define DBG_LED_ENA PORT->Group[DEBUG_LED_PORT].DIRSET.reg = (1 << DEBUG_LED_PIN)
|
||||
#define DBG_LED_DIS PORT->Group[DEBUG_LED_PORT].DIRCLR.reg = (1 << DEBUG_LED_PIN)
|
||||
#define DBG_LED_ON PORT->Group[DEBUG_LED_PORT].OUTSET.reg = (1 << DEBUG_LED_PIN)
|
||||
#define DBG_LED_OFF PORT->Group[DEBUG_LED_PORT].OUTCLR.reg = (1 << DEBUG_LED_PIN)
|
||||
#else
|
||||
#define DBG_LED_ENA
|
||||
#define DBG_LED_DIS
|
||||
#define DBG_LED_ON
|
||||
#define DBG_LED_OFF
|
||||
#endif
|
||||
|
||||
/* Debug Port 1 */
|
||||
#if DEBUG_PORT1_ENABLE == 1
|
||||
#define DBG_1_ENA PORT->Group[DEBUG_PORT1_PORT].DIRSET.reg = (1 << DEBUG_PORT1_PIN)
|
||||
#define DBG_1_DIS PORT->Group[DEBUG_PORT1_PORT].DIRCLR.reg = (1 << DEBUG_PORT1_PIN)
|
||||
#define DBG_1_ON PORT->Group[DEBUG_PORT1_PORT].OUTSET.reg = (1 << DEBUG_PORT1_PIN)
|
||||
#define DBG_1_OFF PORT->Group[DEBUG_PORT1_PORT].OUTCLR.reg = (1 << DEBUG_PORT1_PIN)
|
||||
#else
|
||||
#define DBG_1_ENA
|
||||
#define DBG_1_DIS
|
||||
#define DBG_1_ON
|
||||
#define DBG_1_OFF
|
||||
#endif
|
||||
|
||||
/* Debug Port 2 */
|
||||
#if DEBUG_PORT2_ENABLE == 1
|
||||
#define DBG_2_ENA PORT->Group[DEBUG_PORT2_PORT].DIRSET.reg = (1 << DEBUG_PORT2_PIN)
|
||||
#define DBG_2_DIS PORT->Group[DEBUG_PORT2_PORT].DIRCLR.reg = (1 << DEBUG_PORT2_PIN)
|
||||
#define DBG_2_ON PORT->Group[DEBUG_PORT2_PORT].OUTSET.reg = (1 << DEBUG_PORT2_PIN)
|
||||
#define DBG_2_OFF PORT->Group[DEBUG_PORT2_PORT].OUTCLR.reg = (1 << DEBUG_PORT2_PIN)
|
||||
#else
|
||||
#define DBG_2_ENA
|
||||
#define DBG_2_DIS
|
||||
#define DBG_2_ON
|
||||
#define DBG_2_OFF
|
||||
#endif
|
||||
|
||||
/* Debug Port 3 */
|
||||
#if DEBUG_PORT3_ENABLE == 1
|
||||
#define DBG_3_ENA PORT->Group[DEBUG_PORT3_PORT].DIRSET.reg = (1 << DEBUG_PORT3_PIN)
|
||||
#define DBG_3_DIS PORT->Group[DEBUG_PORT3_PORT].DIRCLR.reg = (1 << DEBUG_PORT3_PIN)
|
||||
#define DBG_3_ON PORT->Group[DEBUG_PORT3_PORT].OUTSET.reg = (1 << DEBUG_PORT3_PIN)
|
||||
#define DBG_3_OFF PORT->Group[DEBUG_PORT3_PORT].OUTCLR.reg = (1 << DEBUG_PORT3_PIN)
|
||||
#else
|
||||
#define DBG_3_ENA
|
||||
#define DBG_3_DIS
|
||||
#define DBG_3_ON
|
||||
#define DBG_3_OFF
|
||||
#endif
|
||||
|
||||
void dbg_print(uint32_t x);
|
||||
void dled_print(uint32_t x, uint8_t long_pause);
|
||||
|
||||
void debug_code_init(void);
|
||||
void debug_code_disable(void);
|
||||
|
||||
#ifdef DEBUG_BOOT_TRACING_ENABLE
|
||||
|
||||
#define DBGC(n) debug_code = n
|
||||
|
||||
extern volatile uint32_t debug_code;
|
||||
|
||||
enum debug_code_list {
|
||||
DC_UNSET = 0,
|
||||
DC_CLK_INIT_BEGIN,
|
||||
DC_CLK_INIT_COMPLETE,
|
||||
DC_CLK_SET_I2C1_FREQ_BEGIN,
|
||||
DC_CLK_SET_I2C1_FREQ_COMPLETE,
|
||||
DC_CLK_SET_I2C0_FREQ_BEGIN,
|
||||
DC_CLK_SET_I2C0_FREQ_COMPLETE,
|
||||
DC_CLK_SET_SPI_FREQ_BEGIN,
|
||||
DC_CLK_SET_SPI_FREQ_COMPLETE,
|
||||
DC_CLK_ENABLE_TIMEBASE_BEGIN,
|
||||
DC_CLK_ENABLE_TIMEBASE_SYNC_ENABLE,
|
||||
DC_CLK_ENABLE_TIMEBASE_SYNC_SWRST_1,
|
||||
DC_CLK_ENABLE_TIMEBASE_SYNC_SWRST_2,
|
||||
DC_CLK_ENABLE_TIMEBASE_TC4_BEGIN,
|
||||
DC_CLK_ENABLE_TIMEBASE_TC4_SYNC_DISABLE,
|
||||
DC_CLK_ENABLE_TIMEBASE_TC4_SYNC_SWRST_1,
|
||||
DC_CLK_ENABLE_TIMEBASE_TC4_SYNC_SWRST_2,
|
||||
DC_CLK_ENABLE_TIMEBASE_TC4_SYNC_CLTRB,
|
||||
DC_CLK_ENABLE_TIMEBASE_TC4_SYNC_CC0,
|
||||
DC_CLK_ENABLE_TIMEBASE_TC4_COMPLETE,
|
||||
DC_CLK_ENABLE_TIMEBASE_TC5_BEGIN,
|
||||
DC_CLK_ENABLE_TIMEBASE_TC5_SYNC_DISABLE,
|
||||
DC_CLK_ENABLE_TIMEBASE_TC5_SYNC_SWRST_1,
|
||||
DC_CLK_ENABLE_TIMEBASE_TC5_SYNC_SWRST_2,
|
||||
DC_CLK_ENABLE_TIMEBASE_TC5_SYNC_CLTRB,
|
||||
DC_CLK_ENABLE_TIMEBASE_TC5_COMPLETE,
|
||||
DC_CLK_ENABLE_TIMEBASE_TC0_BEGIN,
|
||||
DC_CLK_ENABLE_TIMEBASE_TC0_SYNC_DISABLE,
|
||||
DC_CLK_ENABLE_TIMEBASE_TC0_SYNC_SWRST_1,
|
||||
DC_CLK_ENABLE_TIMEBASE_TC0_SYNC_SWRST_2,
|
||||
DC_CLK_ENABLE_TIMEBASE_TC0_COMPLETE,
|
||||
DC_CLK_ENABLE_TIMEBASE_EVSYS_BEGIN,
|
||||
DC_CLK_ENABLE_TIMEBASE_EVSYS_COMPLETE,
|
||||
DC_CLK_ENABLE_TIMEBASE_COMPLETE,
|
||||
DC_CLK_SET_GCLK_FREQ_BEGIN,
|
||||
DC_CLK_SET_GCLK_FREQ_SYNC_1,
|
||||
DC_CLK_SET_GCLK_FREQ_SYNC_2,
|
||||
DC_CLK_SET_GCLK_FREQ_SYNC_3,
|
||||
DC_CLK_SET_GCLK_FREQ_SYNC_4,
|
||||
DC_CLK_SET_GCLK_FREQ_SYNC_5,
|
||||
DC_CLK_SET_GCLK_FREQ_COMPLETE,
|
||||
DC_CLK_INIT_OSC_BEGIN,
|
||||
DC_CLK_INIT_OSC_SYNC_1,
|
||||
DC_CLK_INIT_OSC_SYNC_2,
|
||||
DC_CLK_INIT_OSC_SYNC_3,
|
||||
DC_CLK_INIT_OSC_SYNC_4,
|
||||
DC_CLK_INIT_OSC_SYNC_5,
|
||||
DC_CLK_INIT_OSC_COMPLETE,
|
||||
DC_CLK_RESET_TIME_BEGIN,
|
||||
DC_CLK_RESET_TIME_COMPLETE,
|
||||
DC_CLK_OSC_INIT_BEGIN,
|
||||
DC_CLK_OSC_INIT_XOSC0_SYNC,
|
||||
DC_CLK_OSC_INIT_DPLL_SYNC_DISABLE,
|
||||
DC_CLK_OSC_INIT_DPLL_SYNC_RATIO,
|
||||
DC_CLK_OSC_INIT_DPLL_SYNC_ENABLE,
|
||||
DC_CLK_OSC_INIT_DPLL_WAIT_LOCK,
|
||||
DC_CLK_OSC_INIT_DPLL_WAIT_CLKRDY,
|
||||
DC_CLK_OSC_INIT_GCLK_SYNC_GENCTRL0,
|
||||
DC_CLK_OSC_INIT_COMPLETE,
|
||||
DC_SPI_INIT_BEGIN,
|
||||
DC_SPI_WRITE_DRE,
|
||||
DC_SPI_WRITE_TXC_1,
|
||||
DC_SPI_WRITE_TXC_2,
|
||||
DC_SPI_SYNC_ENABLING,
|
||||
DC_SPI_INIT_COMPLETE,
|
||||
DC_PORT_DETECT_INIT_BEGIN,
|
||||
DC_PORT_DETECT_INIT_FAILED,
|
||||
DC_PORT_DETECT_INIT_COMPLETE,
|
||||
DC_USB_RESET_BEGIN,
|
||||
DC_USB_RESET_COMPLETE,
|
||||
DC_USB_SET_HOST_BY_VOLTAGE_BEGIN,
|
||||
DC_USB_SET_HOST_5V_LOW_WAITING,
|
||||
DC_USB_SET_HOST_BY_VOLTAGE_COMPLETE,
|
||||
DC_USB_CONFIGURE_BEGIN,
|
||||
DC_USB_CONFIGURE_GET_SERIAL,
|
||||
DC_USB_CONFIGURE_COMPLETE,
|
||||
DC_USB_WRITE2422_BLOCK_BEGIN,
|
||||
DC_USB_WRITE2422_BLOCK_SYNC_SYSOP,
|
||||
DC_USB_WRITE2422_BLOCK_COMPLETE,
|
||||
DC_ADC0_CLOCK_INIT_BEGIN,
|
||||
DC_ADC0_CLOCK_INIT_COMPLETE,
|
||||
DC_ADC0_INIT_BEGIN,
|
||||
DC_ADC0_SWRST_SYNCING_1,
|
||||
DC_ADC0_SWRST_SYNCING_2,
|
||||
DC_ADC0_AVGCTRL_SYNCING_1,
|
||||
DC_ADC0_AVGCTRL_SYNCING_2,
|
||||
DC_ADC0_SAMPCTRL_SYNCING_1,
|
||||
DC_ADC0_ENABLE_SYNCING_1,
|
||||
DC_ADC0_INIT_COMPLETE,
|
||||
DC_I2C0_INIT_BEGIN,
|
||||
DC_I2C0_INIT_SYNC_ENABLING,
|
||||
DC_I2C0_INIT_SYNC_SYSOP,
|
||||
DC_I2C0_INIT_WAIT_IDLE,
|
||||
DC_I2C0_INIT_COMPLETE,
|
||||
DC_I2C1_INIT_BEGIN,
|
||||
DC_I2C1_INIT_SYNC_ENABLING,
|
||||
DC_I2C1_INIT_SYNC_SYSOP,
|
||||
DC_I2C1_INIT_WAIT_IDLE,
|
||||
DC_I2C1_INIT_COMPLETE,
|
||||
DC_I2C3733_INIT_CONTROL_BEGIN,
|
||||
DC_I2C3733_INIT_CONTROL_COMPLETE,
|
||||
DC_I2C3733_INIT_DRIVERS_BEGIN,
|
||||
DC_I2C3733_INIT_DRIVERS_COMPLETE,
|
||||
DC_I2C_DMAC_LED_INIT_BEGIN,
|
||||
DC_I2C_DMAC_LED_INIT_COMPLETE,
|
||||
DC_I2C3733_CONTROL_SET_BEGIN,
|
||||
DC_I2C3733_CONTROL_SET_COMPLETE,
|
||||
DC_LED_MATRIX_INIT_BEGIN,
|
||||
DC_LED_MATRIX_INIT_COMPLETE,
|
||||
DC_USB2422_INIT_BEGIN,
|
||||
DC_USB2422_INIT_WAIT_5V_LOW,
|
||||
DC_USB2422_INIT_OSC_SYNC_DISABLING,
|
||||
DC_USB2422_INIT_OSC_SYNC_DFLLCTRLB_1,
|
||||
DC_USB2422_INIT_OSC_SYNC_DFLLCTRLB_2,
|
||||
DC_USB2422_INIT_OSC_SYNC_DFLLCTRLB_3,
|
||||
DC_USB2422_INIT_OSC_SYNC_DFLLCTRLB_4,
|
||||
DC_USB2422_INIT_OSC_SYNC_DFLLMUL,
|
||||
DC_USB2422_INIT_OSC_SYNC_ENABLING,
|
||||
DC_USB2422_INIT_USB_SYNC_SWRST,
|
||||
DC_USB2422_INIT_USB_WAIT_SWRST,
|
||||
DC_USB2422_INIT_USB_SYNC_ENABLING,
|
||||
DC_USB2422_INIT_COMPLETE,
|
||||
DC_MAIN_UDC_START_BEGIN,
|
||||
DC_MAIN_UDC_START_COMPLETE,
|
||||
DC_MAIN_CDC_INIT_BEGIN,
|
||||
DC_MAIN_CDC_INIT_COMPLETE,
|
||||
/* Never change the order of error codes! Only add codes to end! */
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#define DBGC(n) {}
|
||||
|
||||
#endif //DEBUG_BOOT_TRACING_ENABLE
|
||||
|
||||
#endif //_D51_UTIL_H_
|
586
tmk_core/protocol/arm_atsam/i2c_master.c
Normal file
586
tmk_core/protocol/arm_atsam/i2c_master.c
Normal file
|
@ -0,0 +1,586 @@
|
|||
/*
|
||||
Copyright 2018 Massdrop Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "arm_atsam_protocol.h"
|
||||
|
||||
#ifndef MD_BOOTLOADER
|
||||
|
||||
#include <string.h>
|
||||
|
||||
//From keyboard
|
||||
#include "config.h"
|
||||
#include "config_led.h"
|
||||
#include "matrix.h"
|
||||
|
||||
#define I2C_LED_USE_DMA 1 //Set 1 to use background DMA transfers for leds, Set 0 to use inline software transfers
|
||||
|
||||
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
|
||||
static uint8_t i2c_led_q_full; //Queue full counter for reset
|
||||
|
||||
static uint8_t dma_sendbuf[I2C_DMA_MAX_SEND]; //Data being written to I2C
|
||||
|
||||
volatile uint8_t i2c_led_q_running;
|
||||
|
||||
#endif //MD_BOOTLOADER
|
||||
|
||||
void i2c0_init(void)
|
||||
{
|
||||
DBGC(DC_I2C0_INIT_BEGIN);
|
||||
|
||||
CLK_set_i2c0_freq(CHAN_SERCOM_I2C0, FREQ_I2C0_DEFAULT);
|
||||
|
||||
//MCU
|
||||
PORT->Group[0].PMUX[4].bit.PMUXE = 2;
|
||||
PORT->Group[0].PMUX[4].bit.PMUXO = 2;
|
||||
PORT->Group[0].PINCFG[8].bit.PMUXEN = 1;
|
||||
PORT->Group[0].PINCFG[9].bit.PMUXEN = 1;
|
||||
|
||||
//I2C
|
||||
//Note: SW Reset handled in CLK_set_i2c0_freq clks.c
|
||||
|
||||
SERCOM0->I2CM.CTRLA.bit.MODE = 5; //Set master mode
|
||||
|
||||
SERCOM0->I2CM.CTRLA.bit.SPEED = 0; //Set to 1 for Fast-mode Plus (FM+) up to 1 MHz
|
||||
SERCOM0->I2CM.CTRLA.bit.RUNSTDBY = 1; //Enabled
|
||||
|
||||
SERCOM0->I2CM.CTRLA.bit.ENABLE = 1; //Enable the device
|
||||
while (SERCOM0->I2CM.SYNCBUSY.bit.ENABLE) { DBGC(DC_I2C0_INIT_SYNC_ENABLING); } //Wait for SYNCBUSY.ENABLE to clear
|
||||
|
||||
SERCOM0->I2CM.STATUS.bit.BUSSTATE = 1; //Force into IDLE state
|
||||
while (SERCOM0->I2CM.SYNCBUSY.bit.SYSOP) { DBGC(DC_I2C0_INIT_SYNC_SYSOP); }
|
||||
while (SERCOM0->I2CM.STATUS.bit.BUSSTATE != 1) { DBGC(DC_I2C0_INIT_WAIT_IDLE); } //Wait while not idle
|
||||
|
||||
DBGC(DC_I2C0_INIT_COMPLETE);
|
||||
}
|
||||
|
||||
uint8_t i2c0_start(uint8_t address)
|
||||
{
|
||||
SERCOM0->I2CM.ADDR.bit.ADDR = address;
|
||||
while (SERCOM0->I2CM.SYNCBUSY.bit.SYSOP) {}
|
||||
while (SERCOM0->I2CM.INTFLAG.bit.MB == 0) {}
|
||||
while (SERCOM0->I2CM.STATUS.bit.RXNACK) {}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t i2c0_transmit(uint8_t address, uint8_t *data, uint16_t length, uint16_t timeout)
|
||||
{
|
||||
if (!length) return 0;
|
||||
|
||||
i2c0_start(address);
|
||||
|
||||
while (length)
|
||||
{
|
||||
SERCOM0->I2CM.DATA.bit.DATA = *data;
|
||||
while (SERCOM0->I2CM.INTFLAG.bit.MB == 0) {}
|
||||
while (SERCOM0->I2CM.STATUS.bit.RXNACK) {}
|
||||
|
||||
data++;
|
||||
length--;
|
||||
}
|
||||
|
||||
i2c0_stop();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void i2c0_stop(void)
|
||||
{
|
||||
if (SERCOM0->I2CM.STATUS.bit.CLKHOLD || SERCOM0->I2CM.INTFLAG.bit.MB == 1 || SERCOM0->I2CM.STATUS.bit.BUSSTATE != 1)
|
||||
{
|
||||
SERCOM0->I2CM.CTRLB.bit.CMD = 3;
|
||||
while (SERCOM0->I2CM.SYNCBUSY.bit.SYSOP);
|
||||
while (SERCOM0->I2CM.STATUS.bit.CLKHOLD);
|
||||
while (SERCOM0->I2CM.INTFLAG.bit.MB);
|
||||
while (SERCOM0->I2CM.STATUS.bit.BUSSTATE != 1);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef MD_BOOTLOADER
|
||||
void i2c1_init(void)
|
||||
{
|
||||
DBGC(DC_I2C1_INIT_BEGIN);
|
||||
|
||||
CLK_set_i2c1_freq(CHAN_SERCOM_I2C1, FREQ_I2C1_DEFAULT);
|
||||
|
||||
/* MCU */
|
||||
PORT->Group[0].PMUX[8].bit.PMUXE = 2;
|
||||
PORT->Group[0].PMUX[8].bit.PMUXO = 2;
|
||||
PORT->Group[0].PINCFG[16].bit.PMUXEN = 1;
|
||||
PORT->Group[0].PINCFG[17].bit.PMUXEN = 1;
|
||||
|
||||
/* I2C */
|
||||
//Note: SW Reset handled in CLK_set_i2c1_freq clks.c
|
||||
|
||||
SERCOM1->I2CM.CTRLA.bit.MODE = 5; //MODE: Set master mode (No sync)
|
||||
SERCOM1->I2CM.CTRLA.bit.SPEED = 1; //SPEED: Fm+ up to 1MHz (No sync)
|
||||
SERCOM1->I2CM.CTRLA.bit.RUNSTDBY = 1; //RUNSTBY: Enabled (No sync)
|
||||
|
||||
SERCOM1->I2CM.CTRLB.bit.SMEN = 1; //SMEN: Smart mode enabled (For DMA)(No sync)
|
||||
|
||||
NVIC_EnableIRQ(SERCOM1_0_IRQn);
|
||||
SERCOM1->I2CM.INTENSET.bit.ERROR = 1;
|
||||
|
||||
SERCOM1->I2CM.CTRLA.bit.ENABLE = 1; //ENABLE: Enable the device (sync SYNCBUSY.ENABLE)
|
||||
while (SERCOM1->I2CM.SYNCBUSY.bit.ENABLE) { DBGC(DC_I2C1_INIT_SYNC_ENABLING); } //Wait for SYNCBUSY.ENABLE to clear
|
||||
|
||||
SERCOM1->I2CM.STATUS.bit.BUSSTATE = 1; //BUSSTATE: Force into IDLE state (sync SYNCBUSY.SYSOP)
|
||||
while (SERCOM1->I2CM.SYNCBUSY.bit.SYSOP) { DBGC(DC_I2C1_INIT_SYNC_SYSOP); }
|
||||
while (SERCOM1->I2CM.STATUS.bit.BUSSTATE != 1) { DBGC(DC_I2C1_INIT_WAIT_IDLE); } //Wait while not idle
|
||||
|
||||
DBGC(DC_I2C1_INIT_COMPLETE);
|
||||
}
|
||||
|
||||
uint8_t i2c1_start(uint8_t address)
|
||||
{
|
||||
SERCOM1->I2CM.ADDR.bit.ADDR = address;
|
||||
while (SERCOM1->I2CM.SYNCBUSY.bit.SYSOP) {}
|
||||
while (SERCOM1->I2CM.INTFLAG.bit.MB == 0) {}
|
||||
while (SERCOM1->I2CM.STATUS.bit.RXNACK) {}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t i2c1_transmit(uint8_t address, uint8_t *data, uint16_t length, uint16_t timeout)
|
||||
{
|
||||
if (!length) return 0;
|
||||
|
||||
i2c1_start(address);
|
||||
|
||||
while (length)
|
||||
{
|
||||
SERCOM1->I2CM.DATA.bit.DATA = *data;
|
||||
while (SERCOM1->I2CM.INTFLAG.bit.MB == 0) {}
|
||||
while (SERCOM1->I2CM.STATUS.bit.RXNACK) {}
|
||||
|
||||
data++;
|
||||
length--;
|
||||
}
|
||||
|
||||
i2c1_stop();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void i2c1_stop(void)
|
||||
{
|
||||
if (SERCOM1->I2CM.STATUS.bit.CLKHOLD || SERCOM1->I2CM.INTFLAG.bit.MB == 1 || SERCOM1->I2CM.STATUS.bit.BUSSTATE != 1)
|
||||
{
|
||||
SERCOM1->I2CM.CTRLB.bit.CMD = 3;
|
||||
while (SERCOM1->I2CM.SYNCBUSY.bit.SYSOP);
|
||||
while (SERCOM1->I2CM.STATUS.bit.CLKHOLD);
|
||||
while (SERCOM1->I2CM.INTFLAG.bit.MB);
|
||||
while (SERCOM1->I2CM.STATUS.bit.BUSSTATE != 1);
|
||||
}
|
||||
}
|
||||
|
||||
void i2c_led_send_CRWL(uint8_t drvid)
|
||||
{
|
||||
uint8_t i2cdata[] = { ISSI3733_CMDRWL, ISSI3733_CMDRWL_WRITE_ENABLE_ONCE };
|
||||
i2c1_transmit(issidrv[drvid].addr, i2cdata, sizeof(i2cdata), 0);
|
||||
}
|
||||
|
||||
void i2c_led_select_page(uint8_t drvid, uint8_t pageno)
|
||||
{
|
||||
uint8_t i2cdata[] = { ISSI3733_CMDR, pageno };
|
||||
i2c1_transmit(issidrv[drvid].addr, i2cdata, sizeof(i2cdata), 0);
|
||||
}
|
||||
|
||||
void i2c_led_send_GCR(uint8_t drvid)
|
||||
{
|
||||
uint8_t i2cdata[] = { ISSI3733_GCCR, 0x00 };
|
||||
|
||||
if (gcr_actual > LED_GCR_MAX) gcr_actual = LED_GCR_MAX;
|
||||
i2cdata[1] = gcr_actual;
|
||||
|
||||
i2c1_transmit(issidrv[drvid].addr, i2cdata, sizeof(i2cdata), 0);
|
||||
}
|
||||
|
||||
void i2c_led_send_onoff(uint8_t drvid)
|
||||
{
|
||||
#if I2C_LED_USE_DMA != 1
|
||||
if (!i2c_led_q_running)
|
||||
{
|
||||
#endif
|
||||
i2c_led_send_CRWL(drvid);
|
||||
i2c_led_select_page(drvid, 0);
|
||||
#if I2C_LED_USE_DMA != 1
|
||||
}
|
||||
#endif
|
||||
|
||||
*issidrv[drvid].onoff = 0; //Force start location offset to zero
|
||||
i2c1_transmit(issidrv[drvid].addr, issidrv[drvid].onoff, ISSI3733_PG0_BYTES, 0);
|
||||
}
|
||||
|
||||
void i2c_led_send_mode_op_gcr(uint8_t drvid, uint8_t mode, uint8_t operation)
|
||||
{
|
||||
uint8_t i2cdata[] = { ISSI3733_CR, mode | operation, gcr_actual};
|
||||
i2c1_transmit(issidrv[drvid].addr, i2cdata, sizeof(i2cdata), 0);
|
||||
}
|
||||
|
||||
void i2c_led_send_pur_pdr(uint8_t drvid, uint8_t pur, uint8_t pdr)
|
||||
{
|
||||
uint8_t i2cdata[] = { ISSI3733_SWYR_PUR, pur, pdr };
|
||||
|
||||
i2c1_transmit(issidrv[drvid].addr, i2cdata, sizeof(i2cdata), 0);
|
||||
}
|
||||
|
||||
void i2c_led_send_pwm(uint8_t drvid)
|
||||
{
|
||||
#if I2C_LED_USE_DMA != 1
|
||||
if (!i2c_led_q_running)
|
||||
{
|
||||
#endif
|
||||
i2c_led_send_CRWL(drvid);
|
||||
i2c_led_select_page(drvid, 0);
|
||||
#if I2C_LED_USE_DMA != 1
|
||||
}
|
||||
#endif
|
||||
|
||||
*issidrv[drvid].pwm = 0; //Force start location offset to zero
|
||||
i2c1_transmit(issidrv[drvid].addr, issidrv[drvid].pwm, ISSI3733_PG1_BYTES, 0);
|
||||
}
|
||||
|
||||
uint8_t I2C3733_Init_Control(void)
|
||||
{
|
||||
DBGC(DC_I2C3733_INIT_CONTROL_BEGIN);
|
||||
|
||||
//Hardware state shutdown on boot
|
||||
//USB state machine will enable driver when communication is ready
|
||||
I2C3733_Control_Set(0);
|
||||
|
||||
CLK_delay_ms(1);
|
||||
|
||||
sr_exp_data.bit.IRST = 0;
|
||||
SR_EXP_WriteData();
|
||||
|
||||
CLK_delay_ms(1);
|
||||
|
||||
DBGC(DC_I2C3733_INIT_CONTROL_COMPLETE);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t I2C3733_Init_Drivers(void)
|
||||
{
|
||||
DBGC(DC_I2C3733_INIT_DRIVERS_BEGIN);
|
||||
|
||||
gcr_actual = ISSI3733_GCR_DEFAULT;
|
||||
gcr_actual_last = gcr_actual;
|
||||
|
||||
if (gcr_actual > LED_GCR_MAX) gcr_actual = LED_GCR_MAX;
|
||||
gcr_desired = gcr_actual;
|
||||
|
||||
//Set up master device
|
||||
i2c_led_send_CRWL(0);
|
||||
i2c_led_select_page(0, 3);
|
||||
i2c_led_send_mode_op_gcr(0, 0, ISSI3733_CR_SSD_NORMAL); //No SYNC due to brightness mismatch with second driver
|
||||
|
||||
//Set up slave device
|
||||
i2c_led_send_CRWL(1);
|
||||
i2c_led_select_page(1, 3);
|
||||
i2c_led_send_mode_op_gcr(1, 0, ISSI3733_CR_SSD_NORMAL); //No SYNC due to brightness mismatch with first driver and slight flicker at rgb values 1,2
|
||||
|
||||
i2c_led_send_CRWL(0);
|
||||
i2c_led_select_page(0, 3);
|
||||
i2c_led_send_pur_pdr(0, ISSI3733_SWYR_PUR_8000, ISSI3733_CSXR_PDR_8000);
|
||||
|
||||
i2c_led_send_CRWL(1);
|
||||
i2c_led_select_page(1, 3);
|
||||
i2c_led_send_pur_pdr(1, ISSI3733_SWYR_PUR_8000, ISSI3733_CSXR_PDR_8000);
|
||||
|
||||
DBGC(DC_I2C3733_INIT_DRIVERS_COMPLETE);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void I2C_DMAC_LED_Init(void)
|
||||
{
|
||||
Dmac *dmac = DMAC;
|
||||
|
||||
DBGC(DC_I2C_DMAC_LED_INIT_BEGIN);
|
||||
|
||||
//Disable device
|
||||
dmac->CTRL.bit.DMAENABLE = 0; //Disable DMAC
|
||||
while (dmac->CTRL.bit.DMAENABLE) {} //Wait for disabled state in case of ongoing transfers
|
||||
dmac->CTRL.bit.SWRST = 1; //Software Reset DMAC
|
||||
while (dmac->CTRL.bit.SWRST) {} //Wait for software reset to complete
|
||||
|
||||
//Configure device
|
||||
dmac->BASEADDR.reg = (uint32_t)&dmac_desc; //Set descriptor base address
|
||||
dmac->WRBADDR.reg = (uint32_t)&dmac_desc_wb; //Set descriptor write back address
|
||||
dmac->CTRL.reg |= 0x0f00; //Handle all priorities (LVL0-3)
|
||||
|
||||
//Disable channel
|
||||
dmac->Channel[0].CHCTRLA.bit.ENABLE = 0; //Disable the channel
|
||||
while (dmac->Channel[0].CHCTRLA.bit.ENABLE) {} //Wait for disabled state in case of ongoing transfers
|
||||
dmac->Channel[0].CHCTRLA.bit.SWRST = 1; //Software Reset the channel
|
||||
while (dmac->Channel[0].CHCTRLA.bit.SWRST) {} //Wait for software reset to complete
|
||||
|
||||
//Configure channel
|
||||
dmac->Channel[0].CHCTRLA.bit.THRESHOLD = 0; //1BEAT
|
||||
dmac->Channel[0].CHCTRLA.bit.BURSTLEN = 0; //SINGLE
|
||||
dmac->Channel[0].CHCTRLA.bit.TRIGACT = 2; //BURST
|
||||
dmac->Channel[0].CHCTRLA.bit.TRIGSRC = SERCOM1_DMAC_ID_TX; //Trigger source
|
||||
dmac->Channel[0].CHCTRLA.bit.RUNSTDBY = 1; //Run in standby
|
||||
|
||||
NVIC_EnableIRQ(DMAC_0_IRQn);
|
||||
dmac->Channel[0].CHINTENSET.bit.TCMPL = 1;
|
||||
dmac->Channel[0].CHINTENSET.bit.TERR = 1;
|
||||
|
||||
//Enable device
|
||||
dmac->CTRL.bit.DMAENABLE = 1; //Enable DMAC
|
||||
while (dmac->CTRL.bit.DMAENABLE == 0) {} //Wait for enable state
|
||||
|
||||
DBGC(DC_I2C_DMAC_LED_INIT_COMPLETE);
|
||||
}
|
||||
|
||||
//state = 1 enable
|
||||
//state = 0 disable
|
||||
void I2C3733_Control_Set(uint8_t state)
|
||||
{
|
||||
DBGC(DC_I2C3733_CONTROL_SET_BEGIN);
|
||||
|
||||
sr_exp_data.bit.SDB_N = (state == 1 ? 1 : 0);
|
||||
SR_EXP_WriteData();
|
||||
|
||||
DBGC(DC_I2C3733_CONTROL_SET_COMPLETE);
|
||||
}
|
||||
|
||||
void i2c_led_desc_defaults(void)
|
||||
{
|
||||
dmac_desc.BTCTRL.bit.STEPSIZE = 0; //SRCINC used in favor for auto 1 inc
|
||||
dmac_desc.BTCTRL.bit.STEPSEL = 0; //SRCINC used in favor for auto 1 inc
|
||||
dmac_desc.BTCTRL.bit.DSTINC = 0; //The Destination Address Increment is disabled
|
||||
dmac_desc.BTCTRL.bit.SRCINC = 1; //The Source Address Increment is enabled (Inc by 1)
|
||||
dmac_desc.BTCTRL.bit.BEATSIZE = 0; //8-bit bus transfer
|
||||
dmac_desc.BTCTRL.bit.BLOCKACT = 0; //Channel will be disabled if it is the last block transfer in the transaction
|
||||
dmac_desc.BTCTRL.bit.EVOSEL = 0; //Event generation disabled
|
||||
dmac_desc.BTCTRL.bit.VALID = 1; //Set dmac valid
|
||||
}
|
||||
|
||||
void i2c_led_prepare_send_dma(uint8_t *data, uint8_t len)
|
||||
{
|
||||
i2c_led_desc_defaults();
|
||||
|
||||
dmac_desc.BTCNT.reg = len;
|
||||
dmac_desc.SRCADDR.reg = (uint32_t)data + len;
|
||||
dmac_desc.DSTADDR.reg = (uint32_t)&SERCOM1->I2CM.DATA.reg;
|
||||
dmac_desc.DESCADDR.reg = 0;
|
||||
}
|
||||
|
||||
void i2c_led_begin_dma(uint8_t drvid)
|
||||
{
|
||||
DMAC->Channel[0].CHCTRLA.bit.ENABLE = 1; //Enable the channel
|
||||
|
||||
SERCOM1->I2CM.ADDR.reg = (dmac_desc.BTCNT.reg << 16) | 0x2000 | issidrv[drvid].addr; //Begin transfer
|
||||
}
|
||||
|
||||
void i2c_led_send_CRWL_dma(uint8_t drvid)
|
||||
{
|
||||
*(dma_sendbuf+0) = ISSI3733_CMDRWL;
|
||||
*(dma_sendbuf+1) = ISSI3733_CMDRWL_WRITE_ENABLE_ONCE;
|
||||
i2c_led_prepare_send_dma(dma_sendbuf, 2);
|
||||
|
||||
i2c_led_begin_dma(drvid);
|
||||
}
|
||||
|
||||
void i2c_led_select_page_dma(uint8_t drvid, uint8_t pageno)
|
||||
{
|
||||
*(dma_sendbuf+0) = ISSI3733_CMDR;
|
||||
*(dma_sendbuf+1) = pageno;
|
||||
i2c_led_prepare_send_dma(dma_sendbuf, 2);
|
||||
|
||||
i2c_led_begin_dma(drvid);
|
||||
}
|
||||
|
||||
void i2c_led_send_GCR_dma(uint8_t drvid)
|
||||
{
|
||||
*(dma_sendbuf+0) = ISSI3733_GCCR;
|
||||
*(dma_sendbuf+1) = gcr_actual;
|
||||
i2c_led_prepare_send_dma(dma_sendbuf, 2);
|
||||
|
||||
i2c_led_begin_dma(drvid);
|
||||
}
|
||||
|
||||
void i2c_led_send_pwm_dma(uint8_t drvid)
|
||||
{
|
||||
//Note: This copies the CURRENT pwm buffer, which may be getting modified
|
||||
memcpy(dma_sendbuf, issidrv[drvid].pwm, ISSI3733_PG1_BYTES);
|
||||
*dma_sendbuf = 0; //Force start location offset to zero
|
||||
i2c_led_prepare_send_dma(dma_sendbuf, ISSI3733_PG1_BYTES);
|
||||
|
||||
i2c_led_begin_dma(drvid);
|
||||
}
|
||||
|
||||
void i2c_led_send_onoff_dma(uint8_t drvid)
|
||||
{
|
||||
//Note: This copies the CURRENT onoff buffer, which may be getting modified
|
||||
memcpy(dma_sendbuf, issidrv[drvid].onoff, ISSI3733_PG0_BYTES);
|
||||
*dma_sendbuf = 0; //Force start location offset to zero
|
||||
i2c_led_prepare_send_dma(dma_sendbuf, ISSI3733_PG0_BYTES);
|
||||
|
||||
i2c_led_begin_dma(drvid);
|
||||
}
|
||||
|
||||
void i2c_led_q_init(void)
|
||||
{
|
||||
memset(i2c_led_q, 0, I2C_Q_SIZE);
|
||||
i2c_led_q_s = 0;
|
||||
i2c_led_q_e = 0;
|
||||
i2c_led_q_running = 0;
|
||||
i2c_led_q_full = 0;
|
||||
}
|
||||
|
||||
uint8_t i2c_led_q_isempty(void)
|
||||
{
|
||||
return i2c_led_q_s == i2c_led_q_e;
|
||||
}
|
||||
|
||||
uint8_t i2c_led_q_size(void)
|
||||
{
|
||||
return (i2c_led_q_e - i2c_led_q_s) % I2C_Q_SIZE;
|
||||
}
|
||||
|
||||
uint8_t i2c_led_q_available(void)
|
||||
{
|
||||
return I2C_Q_SIZE - i2c_led_q_size() - 1; //Never allow end to meet start
|
||||
}
|
||||
|
||||
void i2c_led_q_add(uint8_t cmd)
|
||||
{
|
||||
//WARNING: Always request room before adding commands!
|
||||
|
||||
//Assign command
|
||||
i2c_led_q[i2c_led_q_e] = cmd;
|
||||
|
||||
i2c_led_q_e = (i2c_led_q_e + 1) % I2C_Q_SIZE; //Move end up one or wrap
|
||||
}
|
||||
|
||||
void i2c_led_q_s_advance(void)
|
||||
{
|
||||
i2c_led_q_s = (i2c_led_q_s + 1) % I2C_Q_SIZE; //Move start up one or wrap
|
||||
}
|
||||
|
||||
//Always request room before adding commands
|
||||
//PS: In case the queue somehow gets filled, it will reset if it can not clear up
|
||||
//PS: Could only get this to happen through unrealistic timings to overload the I2C bus
|
||||
uint8_t i2c_led_q_request_room(uint8_t request_size)
|
||||
{
|
||||
if (request_size > i2c_led_q_available())
|
||||
{
|
||||
i2c_led_q_full++;
|
||||
|
||||
if (i2c_led_q_full >= 100) //Give the queue a chance to clear up
|
||||
{
|
||||
DBG_LED_ON;
|
||||
I2C_DMAC_LED_Init();
|
||||
i2c_led_q_init();
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
i2c_led_q_full = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t i2c_led_q_run(void)
|
||||
{
|
||||
if (i2c_led_q_isempty())
|
||||
{
|
||||
i2c_led_q_running = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (i2c_led_q_running) return 1;
|
||||
|
||||
i2c_led_q_running = 1;
|
||||
|
||||
#if I2C_LED_USE_DMA != 1
|
||||
while (!i2c_led_q_isempty())
|
||||
{
|
||||
#endif
|
||||
//run command
|
||||
if (i2c_led_q[i2c_led_q_s] == I2C_Q_CRWL)
|
||||
{
|
||||
i2c_led_q_s_advance();
|
||||
uint8_t drvid = i2c_led_q[i2c_led_q_s];
|
||||
#if I2C_LED_USE_DMA == 1
|
||||
i2c_led_send_CRWL_dma(drvid);
|
||||
#else
|
||||
i2c_led_send_CRWL(drvid);
|
||||
#endif
|
||||
}
|
||||
else if (i2c_led_q[i2c_led_q_s] == I2C_Q_PAGE_SELECT)
|
||||
{
|
||||
i2c_led_q_s_advance();
|
||||
uint8_t drvid = i2c_led_q[i2c_led_q_s];
|
||||
i2c_led_q_s_advance();
|
||||
uint8_t page = i2c_led_q[i2c_led_q_s];
|
||||
#if I2C_LED_USE_DMA == 1
|
||||
i2c_led_select_page_dma(drvid, page);
|
||||
#else
|
||||
i2c_led_select_page(drvid, page);
|
||||
#endif
|
||||
}
|
||||
else if (i2c_led_q[i2c_led_q_s] == I2C_Q_PWM)
|
||||
{
|
||||
i2c_led_q_s_advance();
|
||||
uint8_t drvid = i2c_led_q[i2c_led_q_s];
|
||||
#if I2C_LED_USE_DMA == 1
|
||||
i2c_led_send_pwm_dma(drvid);
|
||||
#else
|
||||
i2c_led_send_pwm(drvid);
|
||||
#endif
|
||||
}
|
||||
else if (i2c_led_q[i2c_led_q_s] == I2C_Q_GCR)
|
||||
{
|
||||
i2c_led_q_s_advance();
|
||||
uint8_t drvid = i2c_led_q[i2c_led_q_s];
|
||||
#if I2C_LED_USE_DMA == 1
|
||||
i2c_led_send_GCR_dma(drvid);
|
||||
#else
|
||||
i2c_led_send_GCR(drvid);
|
||||
#endif
|
||||
}
|
||||
else if (i2c_led_q[i2c_led_q_s] == I2C_Q_ONOFF)
|
||||
{
|
||||
i2c_led_q_s_advance();
|
||||
uint8_t drvid = i2c_led_q[i2c_led_q_s];
|
||||
#if I2C_LED_USE_DMA == 1
|
||||
i2c_led_send_onoff_dma(drvid);
|
||||
#else
|
||||
i2c_led_send_onoff(drvid);
|
||||
#endif
|
||||
}
|
||||
|
||||
i2c_led_q_s_advance(); //Advance last run command or if the command byte was not serviced
|
||||
|
||||
#if I2C_LED_USE_DMA != 1
|
||||
}
|
||||
|
||||
i2c_led_q_running = 0;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif //MD_BOOTLOADER
|
108
tmk_core/protocol/arm_atsam/i2c_master.h
Normal file
108
tmk_core/protocol/arm_atsam/i2c_master.h
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
Copyright 2018 Massdrop Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _I2C_MASTER_H_
|
||||
#define _I2C_MASTER_H_
|
||||
|
||||
#ifndef MD_BOOTLOADER
|
||||
|
||||
#include "samd51j18a.h"
|
||||
#include "issi3733_driver.h"
|
||||
#include "config.h"
|
||||
|
||||
__attribute__((__aligned__(16)))
|
||||
DmacDescriptor dmac_desc;
|
||||
__attribute__((__aligned__(16)))
|
||||
DmacDescriptor dmac_desc_wb;
|
||||
|
||||
uint8_t I2C3733_Init_Control(void);
|
||||
uint8_t I2C3733_Init_Drivers(void);
|
||||
void I2C3733_Control_Set(uint8_t state);
|
||||
void I2C_DMAC_LED_Init(void);
|
||||
|
||||
#define I2C_Q_SIZE 100
|
||||
|
||||
#define I2C_Q_NA 100
|
||||
#define I2C_Q_CRWL 101
|
||||
#define I2C_Q_PAGE_SELECT 102
|
||||
#define I2C_Q_PWM 103
|
||||
#define I2C_Q_GCR 104
|
||||
#define I2C_Q_ONOFF 105
|
||||
|
||||
#define I2C_DMA_MAX_SEND 255
|
||||
|
||||
extern volatile uint8_t i2c_led_q_running;
|
||||
|
||||
#define I2C_LED_Q_PWM(a) { \
|
||||
if (i2c_led_q_request_room(7)) \
|
||||
{ \
|
||||
i2c_led_q_add(I2C_Q_CRWL); \
|
||||
i2c_led_q_add(a); \
|
||||
i2c_led_q_add(I2C_Q_PAGE_SELECT); \
|
||||
i2c_led_q_add(a); \
|
||||
i2c_led_q_add(ISSI3733_PG_PWM); \
|
||||
i2c_led_q_add(I2C_Q_PWM); \
|
||||
i2c_led_q_add(a); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define I2C_LED_Q_GCR(a) { \
|
||||
if (i2c_led_q_request_room(7)) \
|
||||
{ \
|
||||
i2c_led_q_add(I2C_Q_CRWL); \
|
||||
i2c_led_q_add(a); \
|
||||
i2c_led_q_add(I2C_Q_PAGE_SELECT); \
|
||||
i2c_led_q_add(a); \
|
||||
i2c_led_q_add(ISSI3733_PG_FN); \
|
||||
i2c_led_q_add(I2C_Q_GCR); \
|
||||
i2c_led_q_add(a); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define I2C_LED_Q_ONOFF(a) { \
|
||||
if (i2c_led_q_request_room(7)) \
|
||||
{ \
|
||||
i2c_led_q_add(I2C_Q_CRWL); \
|
||||
i2c_led_q_add(a); \
|
||||
i2c_led_q_add(I2C_Q_PAGE_SELECT); \
|
||||
i2c_led_q_add(a); \
|
||||
i2c_led_q_add(ISSI3733_PG_ONOFF); \
|
||||
i2c_led_q_add(I2C_Q_ONOFF); \
|
||||
i2c_led_q_add(a); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
void i2c_led_q_init(void);
|
||||
void i2c_led_q_add(uint8_t cmd);
|
||||
void i2c_led_q_s_advance(void);
|
||||
uint8_t i2c_led_q_size(void);
|
||||
uint8_t i2c_led_q_request_room(uint8_t request_size);
|
||||
uint8_t i2c_led_q_run(void);
|
||||
|
||||
void i2c1_init(void);
|
||||
uint8_t i2c1_transmit(uint8_t address, uint8_t *data, uint16_t length, uint16_t timeout);
|
||||
void i2c1_stop(void);
|
||||
|
||||
#endif //MD_BOOTLOADER
|
||||
|
||||
void i2c0_init(void);
|
||||
uint8_t i2c0_transmit(uint8_t address, uint8_t *data, uint16_t length, uint16_t timeout);
|
||||
void i2c0_stop(void);
|
||||
|
||||
#endif // _I2C_MASTER_H_
|
||||
|
201
tmk_core/protocol/arm_atsam/issi3733_driver.h
Normal file
201
tmk_core/protocol/arm_atsam/issi3733_driver.h
Normal file
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
Copyright 2018 Massdrop Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _ISSI3733_DRIVER_H_
|
||||
#define _ISSI3733_DRIVER_H_
|
||||
|
||||
//ISII3733 Registers
|
||||
|
||||
#define ISSI3733_CMDR 0xFD //Command Register (Write Only)
|
||||
|
||||
#define ISSI3733_CMDRWL 0xFE //Command Register Write Lock (Read/Write)
|
||||
#define ISSI3733_CMDRWL_WRITE_DISABLE 0x00 //Lock register
|
||||
#define ISSI3733_CMDRWL_WRITE_ENABLE_ONCE 0xC5 //Enable one write to register then reset to locked
|
||||
|
||||
#define ISSI3733_IMR 0xF0 //Interrupt Mask Register (Write Only)
|
||||
#define ISSI3733_IMR_IAC_ON 0x08 //Auto Clear Interrupt Bit - Interrupt auto clear when INTB stay low exceeds 8ms
|
||||
#define ISSI3733_IMR_IAB_ON 0x04 //Auto Breath Interrupt Bit - Enable auto breath loop finish interrupt
|
||||
#define ISSI3733_IMR_IS_ON 0x02 //Dot Short Interrupt Bit - Enable dot short interrupt
|
||||
#define ISSI3733_IMR_IO_ON 0x01 //Dot Open Interrupt Bit - Enable dot open interrupt
|
||||
|
||||
#define ISSI3733_ISR 0xF1 //Interrupt Status Register (Read Only)
|
||||
#define ISSI3733_ISR_ABM3_FINISH 0x10 //Auto Breath Mode 3 Finish Bit - ABM3 finished
|
||||
#define ISSI3733_ISR_ABM2_FINISH 0x08 //Auto Breath Mode 2 Finish Bit - ABM2 finished
|
||||
#define ISSI3733_ISR_ABM1_FINISH 0x04 //Auto Breath Mode 1 Finish Bit - ABM1 finished
|
||||
#define ISSI3733_ISR_SB 0x02 //Short Bit - Shorted
|
||||
#define ISSI3733_ISR_OB 0x01 //Open Bit - Opened
|
||||
|
||||
#define ISSI3733_PG0 0x00 //LED Control Register
|
||||
#define ISSI3733_PG1 0x01 //PWM Register
|
||||
#define ISSI3733_PG2 0x02 //Auto Breath Mode Register
|
||||
#define ISSI3733_PG3 0x03 //Function Register
|
||||
|
||||
#define ISSI3733_PG_ONOFF ISSI3733_PG0
|
||||
#define ISSI3733_PG_OR ISSI3733_PG0
|
||||
#define ISSI3733_PG_SR ISSI3733_PG0
|
||||
#define ISSI3733_PG_PWM ISSI3733_PG1
|
||||
#define ISSI3733_PG_ABM ISSI3733_PG2
|
||||
#define ISSI3733_PG_FN ISSI3733_PG3
|
||||
|
||||
#define ISSI3733_CR 0x00 //Configuration Register
|
||||
|
||||
//PG3: Configuration Register: Synchronize Configuration
|
||||
#define ISSI3733_CR_SYNC_MASTER 0x40 //Master
|
||||
#define ISSI3733_CR_SYNC_SLAVE 0x80 //Slave
|
||||
#define ISSI3733_CR_SYNC_HIGH_IMP 0xC0 //High Impedance
|
||||
|
||||
//PG3: Configuration Register: Open/Short Detection Enable Bit
|
||||
//#define ISSI3733_CR_OSD_DISABLE 0x00 //Disable open/short detection
|
||||
#define ISSI3733_CR_OSD_ENABLE 0x04 //Enable open/short detection
|
||||
|
||||
//PG3: Configuration Register: Auto Breath Enable
|
||||
//#define ISSI3733_CR_B_EN_PWM 0x00 //PWM Mode Enable
|
||||
#define ISSI3733_CR_B_EN_AUTO 0x02 //Auto Breath Mode Enable
|
||||
|
||||
//PG3: Configuration Register: Software Shutdown Control
|
||||
//#define ISSI3733_CR_SSD_SHUTDOWN 0x00 //Software shutdown
|
||||
#define ISSI3733_CR_SSD_NORMAL 0x01 //Normal operation
|
||||
|
||||
#define ISSI3733_GCCR 0x01 //Global Current Control Register
|
||||
|
||||
//1 Byte, Iout = (GCC / 256) * (840 / Rext)
|
||||
//TODO: Give user define for Rext
|
||||
|
||||
//PG3: Auto Breath Control Register 1
|
||||
#define ISSI3733_ABCR1_ABM1 0x02 //Auto Breath Control Register 1 of ABM-1
|
||||
#define ISSI3733_ABCR1_ABM2 0x06 //Auto Breath Control Register 1 of ABM-2
|
||||
#define ISSI3733_ABCR1_ABM3 0x0A //Auto Breath Control Register 1 of ABM-3
|
||||
|
||||
//Rise time
|
||||
#define ISSI3733_ABCR1_T1_0021 0x00 //0.21s
|
||||
#define ISSI3733_ABCR1_T1_0042 0x20 //0.42s
|
||||
#define ISSI3733_ABCR1_T1_0084 0x40 //0.84s
|
||||
#define ISSI3733_ABCR1_T1_0168 0x60 //1.68s
|
||||
#define ISSI3733_ABCR1_T1_0336 0x80 //3.36s
|
||||
#define ISSI3733_ABCR1_T1_0672 0xA0 //6.72s
|
||||
#define ISSI3733_ABCR1_T1_1344 0xC0 //13.44s
|
||||
#define ISSI3733_ABCR1_T1_2688 0xE0 //26.88s
|
||||
|
||||
//Max value time
|
||||
#define ISSI3733_ABCR1_T2_0000 0x00 //0s
|
||||
#define ISSI3733_ABCR1_T2_0021 0x02 //0.21s
|
||||
#define ISSI3733_ABCR1_T2_0042 0x04 //0.42s
|
||||
#define ISSI3733_ABCR1_T2_0084 0x06 //0.84s
|
||||
#define ISSI3733_ABCR1_T2_0168 0x08 //1.68s
|
||||
#define ISSI3733_ABCR1_T2_0336 0x0A //3.36s
|
||||
#define ISSI3733_ABCR1_T2_0672 0x0C //6.72s
|
||||
#define ISSI3733_ABCR1_T2_1344 0x0E //13.44s
|
||||
#define ISSI3733_ABCR1_T2_2688 0x10 //26.88s
|
||||
|
||||
//PG3: Auto Breath Control Register 2
|
||||
#define ISSI3733_ABCR2_ABM1 0x03 //Auto Breath Control Register 2 of ABM-1
|
||||
#define ISSI3733_ABCR2_ABM2 0x07 //Auto Breath Control Register 2 of ABM-2
|
||||
#define ISSI3733_ABCR2_ABM3 0x0B //Auto Breath Control Register 2 of ABM-3
|
||||
|
||||
//Fall time
|
||||
#define ISSI3733_ABCR2_T3_0021 0x00 //0.21s
|
||||
#define ISSI3733_ABCR2_T3_0042 0x20 //0.42s
|
||||
#define ISSI3733_ABCR2_T3_0084 0x40 //0.84s
|
||||
#define ISSI3733_ABCR2_T3_0168 0x60 //1.68s
|
||||
#define ISSI3733_ABCR2_T3_0336 0x80 //3.36s
|
||||
#define ISSI3733_ABCR2_T3_0672 0xA0 //6.72s
|
||||
#define ISSI3733_ABCR2_T3_1344 0xC0 //13.44s
|
||||
#define ISSI3733_ABCR2_T3_2688 0xE0 //26.88s
|
||||
|
||||
//Min value time
|
||||
#define ISSI3733_ABCR2_T4_0000 0x00 //0s
|
||||
#define ISSI3733_ABCR2_T4_0021 0x02 //0.21s
|
||||
#define ISSI3733_ABCR2_T4_0042 0x04 //0.42s
|
||||
#define ISSI3733_ABCR2_T4_0084 0x06 //0.84s
|
||||
#define ISSI3733_ABCR2_T4_0168 0x08 //1.68s
|
||||
#define ISSI3733_ABCR2_T4_0336 0x0A //3.36s
|
||||
#define ISSI3733_ABCR2_T4_0672 0x0C //6.72s
|
||||
#define ISSI3733_ABCR2_T4_1344 0x0E //13.44s
|
||||
#define ISSI3733_ABCR2_T4_2688 0x10 //26.88s
|
||||
#define ISSI3733_ABCR2_T4_5376 0x12 //53.76s
|
||||
#define ISSI3733_ABCR2_T4_10752 0x14 //107.52s
|
||||
|
||||
//PG3: Auto Breath Control Register 3
|
||||
#define ISSI3733_ABCR3_ABM1 0x04 //Auto Breath Control Register 3 of ABM-1
|
||||
#define ISSI3733_ABCR3_ABM2 0x08 //Auto Breath Control Register 3 of ABM-2
|
||||
#define ISSI3733_ABCR3_ABM3 0x0C //Auto Breath Control Register 3 of ABM-3
|
||||
|
||||
#define ISSI3733_ABCR3_LTA_LOOP_ENDLESS 0x00
|
||||
#define ISSI3733_ABCR3_LTA_LOOP_1 0x01
|
||||
#define ISSI3733_ABCR3_LTA_LOOP_2 0x02
|
||||
#define ISSI3733_ABCR3_LTA_LOOP_3 0x03
|
||||
#define ISSI3733_ABCR3_LTA_LOOP_4 0x04
|
||||
#define ISSI3733_ABCR3_LTA_LOOP_5 0x05
|
||||
#define ISSI3733_ABCR3_LTA_LOOP_6 0x06
|
||||
#define ISSI3733_ABCR3_LTA_LOOP_7 0x07
|
||||
#define ISSI3733_ABCR3_LTA_LOOP_8 0x08
|
||||
#define ISSI3733_ABCR3_LTA_LOOP_9 0x09
|
||||
#define ISSI3733_ABCR3_LTA_LOOP_10 0x0A
|
||||
#define ISSI3733_ABCR3_LTA_LOOP_11 0x0B
|
||||
#define ISSI3733_ABCR3_LTA_LOOP_12 0x0C
|
||||
#define ISSI3733_ABCR3_LTA_LOOP_13 0x0D
|
||||
#define ISSI3733_ABCR3_LTA_LOOP_14 0x0E
|
||||
#define ISSI3733_ABCR3_LTA_LOOP_15 0x0F
|
||||
|
||||
//Loop Begin
|
||||
#define ISSI3733_ABCR3_LB_T1 0x00
|
||||
#define ISSI3733_ABCR3_LB_T2 0x10
|
||||
#define ISSI3733_ABCR3_LB_T3 0x20
|
||||
#define ISSI3733_ABCR3_LB_T4 0x30
|
||||
|
||||
//Loop End
|
||||
#define ISSI3733_ABCR3_LE_T3 0x00 //End at Off state
|
||||
#define ISSI3733_ABCR3_LE_T1 0x40 //End at On State
|
||||
|
||||
//PG3: Auto Breath Control Register 4
|
||||
#define ISSI3733_ABCR4_ABM1 0x05 //Auto Breath Control Register 4 of ABM-1
|
||||
#define ISSI3733_ABCR4_ABM2 0x09 //Auto Breath Control Register 4 of ABM-2
|
||||
#define ISSI3733_ABCR4_ABM3 0x0D //Auto Breath Control Register 4 of ABM-3
|
||||
|
||||
#define ISSI3733_ABCR4_LTB_LOOP_ENDLESS 0x00
|
||||
//Or 8bit loop times
|
||||
|
||||
//PG3: Time Update Register
|
||||
#define ISSI3733_TUR 0x0E
|
||||
#define ISSI3733_TUR_UPDATE 0x00 //Write to update 02h~0Dh time registers after configuring
|
||||
|
||||
//PG3: SWy Pull-Up Resistor Selection Register
|
||||
#define ISSI3733_SWYR_PUR 0x0F
|
||||
#define ISSI3733_SWYR_PUR_NONE 0x00 //No pull-up resistor
|
||||
#define ISSI3733_SWYR_PUR_500 0x01 //0.5k Ohm
|
||||
#define ISSI3733_SWYR_PUR_1000 0x02 //1.0k Ohm
|
||||
#define ISSI3733_SWYR_PUR_2000 0x03 //2.0k Ohm
|
||||
#define ISSI3733_SWYR_PUR_4000 0x04 //4.0k Ohm
|
||||
#define ISSI3733_SWYR_PUR_8000 0x05 //8.0k Ohm
|
||||
#define ISSI3733_SWYR_PUR_16000 0x06 //16k Ohm
|
||||
#define ISSI3733_SWYR_PUR_32000 0x07 //32k Ohm
|
||||
|
||||
//PG3: CSx Pull-Down Resistor Selection Register
|
||||
#define ISSI3733_CSXR_PDR 0x10
|
||||
#define ISSI3733_CSXR_PDR_NONE 0x00 //No pull-down resistor
|
||||
#define ISSI3733_CSXR_PDR_500 0x01 //0.5k Ohm
|
||||
#define ISSI3733_CSXR_PDR_1000 0x02 //1.0k Ohm
|
||||
#define ISSI3733_CSXR_PDR_2000 0x03 //2.0k Ohm
|
||||
#define ISSI3733_CSXR_PDR_4000 0x04 //4.0k Ohm
|
||||
#define ISSI3733_CSXR_PDR_8000 0x05 //8.0k Ohm
|
||||
#define ISSI3733_CSXR_PDR_16000 0x06 //16k Ohm
|
||||
#define ISSI3733_CSXR_PDR_32000 0x07 //32k Ohm
|
||||
|
||||
//PG3: Reset Register
|
||||
#define ISSI3733_RR 0x11 //Read to reset all registers to default values
|
||||
|
||||
#endif //_ISSI3733_DRIVER_H_
|
528
tmk_core/protocol/arm_atsam/led_matrix.c
Normal file
528
tmk_core/protocol/arm_atsam/led_matrix.c
Normal file
|
@ -0,0 +1,528 @@
|
|||
/*
|
||||
Copyright 2018 Massdrop Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "arm_atsam_protocol.h"
|
||||
#include "tmk_core/common/led.h"
|
||||
#include <string.h>
|
||||
|
||||
void SERCOM1_0_Handler( void )
|
||||
{
|
||||
if (SERCOM1->I2CM.INTFLAG.bit.ERROR)
|
||||
{
|
||||
SERCOM1->I2CM.INTFLAG.reg = SERCOM_I2CM_INTENCLR_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
void DMAC_0_Handler( void )
|
||||
{
|
||||
if (DMAC->Channel[0].CHINTFLAG.bit.TCMPL)
|
||||
{
|
||||
DMAC->Channel[0].CHINTFLAG.reg = DMAC_CHINTENCLR_TCMPL;
|
||||
|
||||
i2c1_stop();
|
||||
|
||||
i2c_led_q_running = 0;
|
||||
|
||||
i2c_led_q_run();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (DMAC->Channel[0].CHINTFLAG.bit.TERR)
|
||||
{
|
||||
DMAC->Channel[0].CHINTFLAG.reg = DMAC_CHINTENCLR_TERR;
|
||||
}
|
||||
}
|
||||
|
||||
issi3733_driver_t issidrv[ISSI3733_DRIVER_COUNT];
|
||||
|
||||
issi3733_led_t led_map[ISSI3733_LED_COUNT+1] = ISSI3733_LED_MAP;
|
||||
issi3733_led_t *lede = led_map + ISSI3733_LED_COUNT; //End pointer of mapping
|
||||
|
||||
uint8_t gcr_desired;
|
||||
uint8_t gcr_breathe;
|
||||
uint8_t gcr_use;
|
||||
uint8_t gcr_actual;
|
||||
uint8_t gcr_actual_last;
|
||||
|
||||
#define ACT_GCR_NONE 0
|
||||
#define ACT_GCR_INC 1
|
||||
#define ACT_GCR_DEC 2
|
||||
|
||||
#define LED_GCR_STEP_AUTO 2
|
||||
|
||||
static uint8_t gcr_min_counter;
|
||||
static uint8_t v_5v_cat_hit;
|
||||
|
||||
//WARNING: Automatic GCR is in place to prevent USB shutdown and LED driver overloading
|
||||
void gcr_compute(void)
|
||||
{
|
||||
uint8_t action = ACT_GCR_NONE;
|
||||
|
||||
if (led_animation_breathing)
|
||||
gcr_use = gcr_breathe;
|
||||
else
|
||||
gcr_use = gcr_desired;
|
||||
|
||||
//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)
|
||||
{
|
||||
I2C3733_Control_Set(0);
|
||||
//CDC_print("USB: WARNING: 5V catastrophic level reached! Disabling LED drivers!\r\n"); //Blocking print is bad here!
|
||||
v_5v_cat_hit = 20; //~100ms recover
|
||||
gcr_actual = 0; //Minimize GCR
|
||||
usb_gcr_auto = 1; //Force auto mode enabled
|
||||
return;
|
||||
}
|
||||
else if (v_5v_cat_hit > 1)
|
||||
{
|
||||
v_5v_cat_hit--;
|
||||
return;
|
||||
}
|
||||
else if (v_5v_cat_hit == 1)
|
||||
{
|
||||
I2C3733_Control_Set(1);
|
||||
CDC_print("USB: WARNING: Re-enabling LED drivers\r\n");
|
||||
v_5v_cat_hit = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (usb_gcr_auto)
|
||||
{
|
||||
if (v_5v_avg < V5_LOW) action = ACT_GCR_DEC;
|
||||
else if (v_5v_avg > V5_HIGH && gcr_actual < gcr_use) action = ACT_GCR_INC;
|
||||
else if (gcr_actual > gcr_use) action = ACT_GCR_DEC;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gcr_actual < gcr_use) action = ACT_GCR_INC;
|
||||
else if (gcr_actual > gcr_use) action = ACT_GCR_DEC;
|
||||
}
|
||||
|
||||
if (action == ACT_GCR_NONE)
|
||||
{
|
||||
gcr_min_counter = 0;
|
||||
}
|
||||
else if (action == ACT_GCR_INC)
|
||||
{
|
||||
if (LED_GCR_STEP_AUTO > LED_GCR_MAX - gcr_actual) gcr_actual = LED_GCR_MAX; //Obey max and prevent wrapping
|
||||
else gcr_actual += LED_GCR_STEP_AUTO;
|
||||
gcr_min_counter = 0;
|
||||
}
|
||||
else if (action == ACT_GCR_DEC)
|
||||
{
|
||||
if (LED_GCR_STEP_AUTO > gcr_actual) //Prevent wrapping
|
||||
{
|
||||
gcr_actual = 0;
|
||||
//At this point, power can no longer be cut from the LED drivers, so focus on cutting out extra port if active
|
||||
if (usb_extra_state != USB_EXTRA_STATE_DISABLED_UNTIL_REPLUG) //If not in a wait for replug state
|
||||
{
|
||||
if (usb_extra_state == USB_EXTRA_STATE_ENABLED) //If extra usb is enabled
|
||||
{
|
||||
gcr_min_counter++;
|
||||
if (gcr_min_counter > 200) //5ms per check = 1s delay
|
||||
{
|
||||
USB_ExtraSetState(USB_EXTRA_STATE_DISABLED_UNTIL_REPLUG);
|
||||
usb_extra_manual = 0; //Force disable manual mode of extra port
|
||||
if (usb_extra_manual) CDC_print("USB: Disabling extra port until replug and manual mode toggle!\r\n");
|
||||
else CDC_print("USB: Disabling extra port until replug!\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Power successfully cut back from LED drivers
|
||||
gcr_actual -= LED_GCR_STEP_AUTO;
|
||||
gcr_min_counter = 0;
|
||||
|
||||
//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)
|
||||
{
|
||||
gcr_breathe = gcr_actual;
|
||||
//PS: At this point, setting breathing to exhale makes a noticebly shorter cycle
|
||||
// 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
led_disp_t disp;
|
||||
|
||||
void issi3733_prepare_arrays(void)
|
||||
{
|
||||
memset(issidrv,0,sizeof(issi3733_driver_t) * ISSI3733_DRIVER_COUNT);
|
||||
|
||||
int i;
|
||||
uint8_t addrs[ISSI3733_DRIVER_COUNT] = ISSI3773_DRIVER_ADDRESSES;
|
||||
|
||||
for (i=0;i<ISSI3733_DRIVER_COUNT;i++)
|
||||
{
|
||||
issidrv[i].addr = addrs[i];
|
||||
}
|
||||
|
||||
issi3733_led_t *cur = led_map;
|
||||
|
||||
while (cur < lede)
|
||||
{
|
||||
//BYTE: 1 + (SW-1)*16 + (CS-1)
|
||||
cur->rgb.g = issidrv[cur->adr.drv-1].pwm + 1 + ((cur->adr.swg-1)*16 + (cur->adr.cs-1));
|
||||
cur->rgb.r = issidrv[cur->adr.drv-1].pwm + 1 + ((cur->adr.swr-1)*16 + (cur->adr.cs-1));
|
||||
cur->rgb.b = issidrv[cur->adr.drv-1].pwm + 1 + ((cur->adr.swb-1)*16 + (cur->adr.cs-1));
|
||||
|
||||
//BYTE: 1 + (SW-1)*2 + (CS-1)/8
|
||||
//BIT: (CS-1)%8
|
||||
*(issidrv[cur->adr.drv-1].onoff + 1 + (cur->adr.swg-1)*2+(cur->adr.cs-1)/8) |= (1<<((cur->adr.cs-1)%8));
|
||||
*(issidrv[cur->adr.drv-1].onoff + 1 + (cur->adr.swr-1)*2+(cur->adr.cs-1)/8) |= (1<<((cur->adr.cs-1)%8));
|
||||
*(issidrv[cur->adr.drv-1].onoff + 1 + (cur->adr.swb-1)*2+(cur->adr.cs-1)/8) |= (1<<((cur->adr.cs-1)%8));
|
||||
|
||||
cur++;
|
||||
}
|
||||
}
|
||||
|
||||
void disp_calc_extents(void)
|
||||
{
|
||||
issi3733_led_t *cur = led_map;
|
||||
|
||||
disp.left = 1e10;
|
||||
disp.right = -1e10;
|
||||
disp.top = -1e10;
|
||||
disp.bottom = 1e10;
|
||||
|
||||
while (cur < lede)
|
||||
{
|
||||
if (cur->x < disp.left) disp.left = cur->x;
|
||||
if (cur->x > disp.right) disp.right = cur->x;
|
||||
if (cur->y < disp.bottom) disp.bottom = cur->y;
|
||||
if (cur->y > disp.top) disp.top = cur->y;
|
||||
|
||||
cur++;
|
||||
}
|
||||
|
||||
disp.width = disp.right - disp.left;
|
||||
disp.height = disp.top - disp.bottom;
|
||||
}
|
||||
|
||||
void disp_pixel_setup(void)
|
||||
{
|
||||
issi3733_led_t *cur = led_map;
|
||||
|
||||
while (cur < lede)
|
||||
{
|
||||
cur->px = (cur->x - disp.left) / disp.width * 100;
|
||||
cur->py = (cur->y - disp.bottom) / disp.height * 100;
|
||||
*cur->rgb.r = 0;
|
||||
*cur->rgb.g = 0;
|
||||
*cur->rgb.b = 0;
|
||||
|
||||
cur++;
|
||||
}
|
||||
}
|
||||
|
||||
void led_matrix_prepare(void)
|
||||
{
|
||||
disp_calc_extents();
|
||||
disp_pixel_setup();
|
||||
}
|
||||
|
||||
uint8_t led_enabled;
|
||||
float led_animation_speed;
|
||||
uint8_t led_animation_direction;
|
||||
uint8_t led_animation_orientation;
|
||||
uint8_t led_animation_breathing;
|
||||
uint8_t led_animation_breathe_cur;
|
||||
uint8_t breathe_step;
|
||||
uint8_t breathe_dir;
|
||||
uint64_t led_next_run;
|
||||
|
||||
uint8_t led_animation_id;
|
||||
uint8_t led_lighting_mode;
|
||||
|
||||
issi3733_led_t *led_cur;
|
||||
uint8_t led_per_run = 15;
|
||||
float breathe_mult;
|
||||
|
||||
__attribute__ ((weak))
|
||||
void led_matrix_run(void)
|
||||
{
|
||||
float ro;
|
||||
float go;
|
||||
float bo;
|
||||
float po;
|
||||
uint8_t led_this_run = 0;
|
||||
led_setup_t *f = (led_setup_t*)led_setups[led_animation_id];
|
||||
|
||||
if (led_cur == 0) //Denotes start of new processing cycle in the case of chunked processing
|
||||
{
|
||||
led_cur = led_map;
|
||||
|
||||
disp.frame += 1;
|
||||
|
||||
breathe_mult = 1;
|
||||
|
||||
if (led_animation_breathing)
|
||||
{
|
||||
led_animation_breathe_cur += breathe_step * breathe_dir;
|
||||
|
||||
if (led_animation_breathe_cur >= BREATHE_MAX_STEP)
|
||||
breathe_dir = -1;
|
||||
else if (led_animation_breathe_cur <= BREATHE_MIN_STEP)
|
||||
breathe_dir = 1;
|
||||
|
||||
//Brightness curve created for 256 steps, 0 - ~98%
|
||||
breathe_mult = 0.000015 * led_animation_breathe_cur * led_animation_breathe_cur;
|
||||
if (breathe_mult > 1) breathe_mult = 1;
|
||||
else if (breathe_mult < 0) breathe_mult = 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t fcur = 0;
|
||||
uint8_t fmax = 0;
|
||||
|
||||
//Frames setup
|
||||
while (f[fcur].end != 1)
|
||||
{
|
||||
fcur++; //Count frames
|
||||
}
|
||||
|
||||
fmax = fcur; //Store total frames count
|
||||
|
||||
while (led_cur < lede && led_this_run < led_per_run)
|
||||
{
|
||||
ro = 0;
|
||||
go = 0;
|
||||
bo = 0;
|
||||
|
||||
if (led_lighting_mode == LED_MODE_KEYS_ONLY && led_cur->scan == 255)
|
||||
{
|
||||
//Do not act on this LED
|
||||
}
|
||||
else if (led_lighting_mode == LED_MODE_NON_KEYS_ONLY && led_cur->scan != 255)
|
||||
{
|
||||
//Do not act on this LED
|
||||
}
|
||||
else if (led_lighting_mode == LED_MODE_INDICATORS_ONLY)
|
||||
{
|
||||
//Do not act on this LED (Only show indicators)
|
||||
}
|
||||
else
|
||||
{
|
||||
//Act on LED
|
||||
for (fcur = 0; fcur < fmax; fcur++)
|
||||
{
|
||||
|
||||
if (led_animation_orientation)
|
||||
{
|
||||
po = led_cur->py;
|
||||
}
|
||||
else
|
||||
{
|
||||
po = led_cur->px;
|
||||
}
|
||||
|
||||
float pomod;
|
||||
pomod = (float)(disp.frame % (uint32_t)(1000.0f / led_animation_speed)) / 10.0f * led_animation_speed;
|
||||
|
||||
//Add in any moving effects
|
||||
if ((!led_animation_direction && f[fcur].ef & EF_SCR_R) || (led_animation_direction && (f[fcur].ef & EF_SCR_L)))
|
||||
{
|
||||
pomod *= 100.0f;
|
||||
pomod = (uint32_t)pomod % 10000;
|
||||
pomod /= 100.0f;
|
||||
|
||||
po -= pomod;
|
||||
|
||||
if (po > 100) po -= 100;
|
||||
else if (po < 0) po += 100;
|
||||
}
|
||||
else if ((!led_animation_direction && f[fcur].ef & EF_SCR_L) || (led_animation_direction && (f[fcur].ef & EF_SCR_R)))
|
||||
{
|
||||
pomod *= 100.0f;
|
||||
pomod = (uint32_t)pomod % 10000;
|
||||
pomod /= 100.0f;
|
||||
po += pomod;
|
||||
|
||||
if (po > 100) po -= 100;
|
||||
else if (po < 0) po += 100;
|
||||
}
|
||||
|
||||
//Check if LED's po is in current frame
|
||||
if (po < f[fcur].hs) continue;
|
||||
if (po > f[fcur].he) continue;
|
||||
//note: < 0 or > 100 continue
|
||||
|
||||
//Calculate the po within the start-stop percentage for color blending
|
||||
po = (po - f[fcur].hs) / (f[fcur].he - f[fcur].hs);
|
||||
|
||||
//Add in any color effects
|
||||
if (f[fcur].ef & EF_OVER)
|
||||
{
|
||||
ro = (po * (f[fcur].re - f[fcur].rs)) + f[fcur].rs;// + 0.5;
|
||||
go = (po * (f[fcur].ge - f[fcur].gs)) + f[fcur].gs;// + 0.5;
|
||||
bo = (po * (f[fcur].be - f[fcur].bs)) + f[fcur].bs;// + 0.5;
|
||||
}
|
||||
else if (f[fcur].ef & EF_SUBTRACT)
|
||||
{
|
||||
ro -= (po * (f[fcur].re - f[fcur].rs)) + f[fcur].rs;// + 0.5;
|
||||
go -= (po * (f[fcur].ge - f[fcur].gs)) + f[fcur].gs;// + 0.5;
|
||||
bo -= (po * (f[fcur].be - f[fcur].bs)) + f[fcur].bs;// + 0.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
ro += (po * (f[fcur].re - f[fcur].rs)) + f[fcur].rs;// + 0.5;
|
||||
go += (po * (f[fcur].ge - f[fcur].gs)) + f[fcur].gs;// + 0.5;
|
||||
bo += (po * (f[fcur].be - f[fcur].bs)) + f[fcur].bs;// + 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Clamp values 0-255
|
||||
if (ro > 255) ro = 255; else if (ro < 0) ro = 0;
|
||||
if (go > 255) go = 255; else if (go < 0) go = 0;
|
||||
if (bo > 255) bo = 255; else if (bo < 0) bo = 0;
|
||||
|
||||
if (led_animation_breathing)
|
||||
{
|
||||
ro *= breathe_mult;
|
||||
go *= breathe_mult;
|
||||
bo *= breathe_mult;
|
||||
}
|
||||
|
||||
*led_cur->rgb.r = (uint8_t)ro;
|
||||
*led_cur->rgb.g = (uint8_t)go;
|
||||
*led_cur->rgb.b = (uint8_t)bo;
|
||||
|
||||
#ifdef USB_LED_INDICATOR_ENABLE
|
||||
if (keyboard_leds())
|
||||
{
|
||||
uint8_t kbled = keyboard_leds();
|
||||
if (
|
||||
#if USB_LED_NUM_LOCK_SCANCODE != 255
|
||||
(led_cur->scan == USB_LED_NUM_LOCK_SCANCODE && kbled & (1<<USB_LED_NUM_LOCK)) ||
|
||||
#endif //NUM LOCK
|
||||
#if USB_LED_CAPS_LOCK_SCANCODE != 255
|
||||
(led_cur->scan == USB_LED_CAPS_LOCK_SCANCODE && kbled & (1<<USB_LED_CAPS_LOCK)) ||
|
||||
#endif //CAPS LOCK
|
||||
#if USB_LED_SCROLL_LOCK_SCANCODE != 255
|
||||
(led_cur->scan == USB_LED_SCROLL_LOCK_SCANCODE && kbled & (1<<USB_LED_SCROLL_LOCK)) ||
|
||||
#endif //SCROLL LOCK
|
||||
#if USB_LED_COMPOSE_SCANCODE != 255
|
||||
(led_cur->scan == USB_LED_COMPOSE_SCANCODE && kbled & (1<<USB_LED_COMPOSE)) ||
|
||||
#endif //COMPOSE
|
||||
#if USB_LED_KANA_SCANCODE != 255
|
||||
(led_cur->scan == USB_LED_KANA_SCANCODE && kbled & (1<<USB_LED_KANA)) ||
|
||||
#endif //KANA
|
||||
(0))
|
||||
{
|
||||
if (*led_cur->rgb.r > 127) *led_cur->rgb.r = 0;
|
||||
else *led_cur->rgb.r = 255;
|
||||
if (*led_cur->rgb.g > 127) *led_cur->rgb.g = 0;
|
||||
else *led_cur->rgb.g = 255;
|
||||
if (*led_cur->rgb.b > 127) *led_cur->rgb.b = 0;
|
||||
else *led_cur->rgb.b = 255;
|
||||
}
|
||||
}
|
||||
#endif //USB_LED_INDICATOR_ENABLE
|
||||
|
||||
led_cur++;
|
||||
led_this_run++;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t led_matrix_init(void)
|
||||
{
|
||||
DBGC(DC_LED_MATRIX_INIT_BEGIN);
|
||||
|
||||
issi3733_prepare_arrays();
|
||||
|
||||
led_matrix_prepare();
|
||||
|
||||
disp.frame = 0;
|
||||
led_next_run = 0;
|
||||
|
||||
led_enabled = 1;
|
||||
led_animation_id = 0;
|
||||
led_lighting_mode = LED_MODE_NORMAL;
|
||||
led_animation_speed = 4.0f;
|
||||
led_animation_direction = 0;
|
||||
led_animation_orientation = 0;
|
||||
led_animation_breathing = 0;
|
||||
led_animation_breathe_cur = BREATHE_MIN_STEP;
|
||||
breathe_step = 1;
|
||||
breathe_dir = 1;
|
||||
|
||||
gcr_min_counter = 0;
|
||||
v_5v_cat_hit = 0;
|
||||
|
||||
//Run led matrix code once for initial LED coloring
|
||||
led_cur = 0;
|
||||
rgb_matrix_init_user();
|
||||
led_matrix_run();
|
||||
|
||||
DBGC(DC_LED_MATRIX_INIT_COMPLETE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__ ((weak))
|
||||
void rgb_matrix_init_user(void) {
|
||||
|
||||
}
|
||||
|
||||
#define LED_UPDATE_RATE 10 //ms
|
||||
|
||||
//led data processing can take time, so process data in chunks to free up the processor
|
||||
//this is done through led_cur and lede
|
||||
void led_matrix_task(void)
|
||||
{
|
||||
if (led_enabled)
|
||||
{
|
||||
//If an update may run and frame processing has completed
|
||||
if (CLK_get_ms() >= led_next_run && led_cur == lede)
|
||||
{
|
||||
uint8_t drvid;
|
||||
|
||||
led_next_run = CLK_get_ms() + LED_UPDATE_RATE; //Set next frame update time
|
||||
|
||||
//NOTE: GCR does not need to be timed with LED processing, but there is really no harm
|
||||
if (gcr_actual != gcr_actual_last)
|
||||
{
|
||||
for (drvid=0;drvid<ISSI3733_DRIVER_COUNT;drvid++)
|
||||
I2C_LED_Q_GCR(drvid); //Queue data
|
||||
gcr_actual_last = gcr_actual;
|
||||
}
|
||||
|
||||
for (drvid=0;drvid<ISSI3733_DRIVER_COUNT;drvid++)
|
||||
I2C_LED_Q_PWM(drvid); //Queue data
|
||||
|
||||
i2c_led_q_run();
|
||||
|
||||
led_cur = 0; //Signal next frame calculations may begin
|
||||
}
|
||||
}
|
||||
|
||||
//Process more data if not finished
|
||||
if (led_cur != lede)
|
||||
{
|
||||
//DBG_1_OFF; //debug profiling
|
||||
led_matrix_run();
|
||||
//DBG_1_ON; //debug profiling
|
||||
}
|
||||
}
|
||||
|
144
tmk_core/protocol/arm_atsam/led_matrix.h
Normal file
144
tmk_core/protocol/arm_atsam/led_matrix.h
Normal file
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
Copyright 2018 Massdrop Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _LED_MATRIX_H_
|
||||
#define _LED_MATRIX_H_
|
||||
|
||||
//From keyboard
|
||||
#include "config_led.h"
|
||||
|
||||
//CS1-CS16 Current Source "Col"
|
||||
#define ISSI3733_CS_COUNT 16
|
||||
|
||||
//SW1-SW12 Switch "Row"
|
||||
#define ISSI3733_SW_COUNT 12
|
||||
|
||||
#define ISSI3733_LED_RGB_COUNT ISSI3733_CS_COUNT * ISSI3733_SW_COUNT
|
||||
#define ISSI3733_PG0_BYTES ISSI3733_LED_RGB_COUNT / 8 + 1 //+1 for first byte being memory start offset for I2C transfer
|
||||
#define ISSI3733_PG1_BYTES ISSI3733_LED_RGB_COUNT + 1 //+1 for first byte being memory start offset for I2C transfer
|
||||
#define ISSI3733_PG2_BYTES ISSI3733_LED_RGB_COUNT + 1 //+1 for first byte being memory start offset for I2C transfer
|
||||
#define ISSI3733_PG3_BYTES 18 + 1 //+1 for first byte being memory start offset for I2C transfer
|
||||
|
||||
#define ISSI3733_PG_ONOFF_BYTES ISSI3733_PG0_BYTES
|
||||
#define ISSI3733_PG_OR_BYTES ISSI3733_PG0_BYTES
|
||||
#define ISSI3733_PG_SR_BYTES ISSI3733_PG0_BYTES
|
||||
#define ISSI3733_PG_PWM_BYTES ISSI3733_PG1_BYTES
|
||||
#define ISSI3733_PG_ABM_BYTES ISSI3733_PG2_BYTES
|
||||
#define ISSI3733_PG_FN_BYTES ISSI3733_PG3_BYTES
|
||||
|
||||
typedef struct issi3733_driver_s {
|
||||
uint8_t addr; //Address of the driver according to wiring "ISSI3733: Table 1 Slave Address"
|
||||
uint8_t onoff[ISSI3733_PG_ONOFF_BYTES]; //PG0 - LED Control Register - LED On/Off Register
|
||||
uint8_t open[ISSI3733_PG_OR_BYTES]; //PG0 - LED Control Register - LED Open Register
|
||||
uint8_t shrt[ISSI3733_PG_SR_BYTES]; //PG0 - LED Control Register - LED Short Register
|
||||
uint8_t pwm[ISSI3733_PG_PWM_BYTES]; //PG1 - PWM Register
|
||||
uint8_t abm[ISSI3733_PG_ABM_BYTES]; //PG2 - Auto Breath Mode Register
|
||||
uint8_t conf[ISSI3733_PG_FN_BYTES]; //PG3 - Function Register
|
||||
} issi3733_driver_t;
|
||||
|
||||
typedef struct issi3733_rgb_s {
|
||||
uint8_t *r; //Direct access into PWM data
|
||||
uint8_t *g; //Direct access into PWM data
|
||||
uint8_t *b; //Direct access into PWM data
|
||||
} issi3733_rgb_t;
|
||||
|
||||
typedef struct issi3733_rgb_adr_s {
|
||||
uint8_t drv; //Driver from given list
|
||||
uint8_t cs; //CS
|
||||
uint8_t swr; //SW Red
|
||||
uint8_t swg; //SW Green
|
||||
uint8_t swb; //SW Blue
|
||||
} issi3733_rgb_adr_t;
|
||||
|
||||
typedef struct issi3733_led_s {
|
||||
uint8_t id; //According to PCB ref
|
||||
issi3733_rgb_t rgb; //PWM settings of R G B
|
||||
issi3733_rgb_adr_t adr; //Hardware addresses
|
||||
float x; //Physical position X
|
||||
float y; //Physical position Y
|
||||
float px; //Physical position X in percent
|
||||
float py; //Physical position Y in percent
|
||||
uint8_t scan; //Key scan code from wiring (set 0xFF if no key)
|
||||
} issi3733_led_t;
|
||||
|
||||
typedef struct led_disp_s {
|
||||
uint64_t frame;
|
||||
float left;
|
||||
float right;
|
||||
float top;
|
||||
float bottom;
|
||||
float width;
|
||||
float height;
|
||||
} led_disp_t;
|
||||
|
||||
uint8_t led_matrix_init(void);
|
||||
void rgb_matrix_init_user(void);
|
||||
|
||||
#define LED_MODE_NORMAL 0 //Must be 0
|
||||
#define LED_MODE_KEYS_ONLY 1
|
||||
#define LED_MODE_NON_KEYS_ONLY 2
|
||||
#define LED_MODE_INDICATORS_ONLY 3
|
||||
#define LED_MODE_MAX_INDEX LED_MODE_INDICATORS_ONLY //Must be highest value
|
||||
|
||||
#define EF_NONE 0x00000000 //No effect
|
||||
#define EF_OVER 0x00000001 //Overwrite any previous color information with new
|
||||
#define EF_SCR_L 0x00000002 //Scroll left
|
||||
#define EF_SCR_R 0x00000004 //Scroll right
|
||||
#define EF_SUBTRACT 0x00000008 //Subtract color values
|
||||
|
||||
typedef struct led_setup_s {
|
||||
float hs; //Band begin at percent
|
||||
float he; //Band end at percent
|
||||
uint8_t rs; //Red start value
|
||||
uint8_t re; //Red end value
|
||||
uint8_t gs; //Green start value
|
||||
uint8_t ge; //Green end value
|
||||
uint8_t bs; //Blue start value
|
||||
uint8_t be; //Blue end value
|
||||
uint32_t ef; //Animation and color effects
|
||||
uint8_t end; //Set to signal end of the setup
|
||||
} led_setup_t;
|
||||
|
||||
extern issi3733_driver_t issidrv[ISSI3733_DRIVER_COUNT];
|
||||
|
||||
extern uint8_t gcr_desired;
|
||||
extern uint8_t gcr_breathe;
|
||||
extern uint8_t gcr_actual;
|
||||
extern uint8_t gcr_actual_last;
|
||||
|
||||
extern uint8_t led_animation_id;
|
||||
extern uint8_t led_enabled;
|
||||
extern float led_animation_speed;
|
||||
extern uint8_t led_lighting_mode;
|
||||
extern uint8_t led_animation_direction;
|
||||
extern uint8_t led_animation_orientation;
|
||||
extern uint8_t led_animation_breathing;
|
||||
extern uint8_t led_animation_breathe_cur;
|
||||
extern uint8_t breathe_dir;
|
||||
extern const uint8_t led_setups_count;
|
||||
|
||||
extern void *led_setups[];
|
||||
|
||||
extern issi3733_led_t *led_cur;
|
||||
extern issi3733_led_t *lede;
|
||||
|
||||
void led_matrix_run(void);
|
||||
void led_matrix_task(void);
|
||||
|
||||
void gcr_compute(void);
|
||||
|
||||
#endif //_LED_MATRIX_H_
|
340
tmk_core/protocol/arm_atsam/main_arm_atsam.c
Normal file
340
tmk_core/protocol/arm_atsam/main_arm_atsam.c
Normal file
|
@ -0,0 +1,340 @@
|
|||
/*
|
||||
Copyright 2018 Massdrop Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "samd51j18a.h"
|
||||
#include "tmk_core/common/keyboard.h"
|
||||
|
||||
#include "report.h"
|
||||
#include "host.h"
|
||||
#include "host_driver.h"
|
||||
#include "keycode_config.h"
|
||||
#include <string.h>
|
||||
#include "quantum.h"
|
||||
|
||||
//From protocol directory
|
||||
#include "arm_atsam_protocol.h"
|
||||
|
||||
//From keyboard's directory
|
||||
#include "config_led.h"
|
||||
|
||||
uint8_t g_usb_state = USB_FSMSTATUS_FSMSTATE_OFF_Val; //Saved USB state from hardware value to detect changes
|
||||
|
||||
void main_subtasks(void);
|
||||
uint8_t keyboard_leds(void);
|
||||
void send_keyboard(report_keyboard_t *report);
|
||||
void send_mouse(report_mouse_t *report);
|
||||
void send_system(uint16_t data);
|
||||
void send_consumer(uint16_t data);
|
||||
|
||||
host_driver_t arm_atsam_driver = {
|
||||
keyboard_leds,
|
||||
send_keyboard,
|
||||
send_mouse,
|
||||
send_system,
|
||||
send_consumer
|
||||
};
|
||||
|
||||
uint8_t led_states;
|
||||
|
||||
uint8_t keyboard_leds(void)
|
||||
{
|
||||
#ifdef NKRO_ENABLE
|
||||
if (keymap_config.nkro)
|
||||
return udi_hid_nkro_report_set;
|
||||
else
|
||||
#endif //NKRO_ENABLE
|
||||
return udi_hid_kbd_report_set;
|
||||
}
|
||||
|
||||
void send_keyboard(report_keyboard_t *report)
|
||||
{
|
||||
uint32_t irqflags;
|
||||
|
||||
#ifdef NKRO_ENABLE
|
||||
if (!keymap_config.nkro)
|
||||
{
|
||||
#endif //NKRO_ENABLE
|
||||
while (udi_hid_kbd_b_report_trans_ongoing) { main_subtasks(); } //Run other tasks while waiting for USB to be free
|
||||
|
||||
irqflags = __get_PRIMASK();
|
||||
__disable_irq();
|
||||
__DMB();
|
||||
|
||||
memcpy(udi_hid_kbd_report, report->raw, UDI_HID_KBD_REPORT_SIZE);
|
||||
udi_hid_kbd_b_report_valid = 1;
|
||||
udi_hid_kbd_send_report();
|
||||
|
||||
__DMB();
|
||||
__set_PRIMASK(irqflags);
|
||||
#ifdef NKRO_ENABLE
|
||||
}
|
||||
else
|
||||
{
|
||||
while (udi_hid_nkro_b_report_trans_ongoing) { main_subtasks(); } //Run other tasks while waiting for USB to be free
|
||||
|
||||
irqflags = __get_PRIMASK();
|
||||
__disable_irq();
|
||||
__DMB();
|
||||
|
||||
memcpy(udi_hid_nkro_report, report->raw, UDI_HID_NKRO_REPORT_SIZE);
|
||||
udi_hid_nkro_b_report_valid = 1;
|
||||
udi_hid_nkro_send_report();
|
||||
|
||||
__DMB();
|
||||
__set_PRIMASK(irqflags);
|
||||
}
|
||||
#endif //NKRO_ENABLE
|
||||
}
|
||||
|
||||
void send_mouse(report_mouse_t *report)
|
||||
{
|
||||
#ifdef MOUSEKEY_ENABLE
|
||||
uint32_t irqflags;
|
||||
|
||||
irqflags = __get_PRIMASK();
|
||||
__disable_irq();
|
||||
__DMB();
|
||||
|
||||
memcpy(udi_hid_mou_report, report, UDI_HID_MOU_REPORT_SIZE);
|
||||
udi_hid_mou_b_report_valid = 1;
|
||||
udi_hid_mou_send_report();
|
||||
|
||||
__DMB();
|
||||
__set_PRIMASK(irqflags);
|
||||
#endif //MOUSEKEY_ENABLE
|
||||
}
|
||||
|
||||
void send_system(uint16_t data)
|
||||
{
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
uint32_t irqflags;
|
||||
|
||||
irqflags = __get_PRIMASK();
|
||||
__disable_irq();
|
||||
__DMB();
|
||||
|
||||
udi_hid_exk_report.desc.report_id = REPORT_ID_SYSTEM;
|
||||
if (data != 0) data = data - SYSTEM_POWER_DOWN + 1;
|
||||
udi_hid_exk_report.desc.report_data = data;
|
||||
udi_hid_exk_b_report_valid = 1;
|
||||
udi_hid_exk_send_report();
|
||||
|
||||
__DMB();
|
||||
__set_PRIMASK(irqflags);
|
||||
#endif //EXTRAKEY_ENABLE
|
||||
}
|
||||
|
||||
void send_consumer(uint16_t data)
|
||||
{
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
uint32_t irqflags;
|
||||
|
||||
irqflags = __get_PRIMASK();
|
||||
__disable_irq();
|
||||
__DMB();
|
||||
|
||||
udi_hid_exk_report.desc.report_id = REPORT_ID_CONSUMER;
|
||||
udi_hid_exk_report.desc.report_data = data;
|
||||
udi_hid_exk_b_report_valid = 1;
|
||||
udi_hid_exk_send_report();
|
||||
|
||||
__DMB();
|
||||
__set_PRIMASK(irqflags);
|
||||
#endif //EXTRAKEY_ENABLE
|
||||
}
|
||||
|
||||
void main_subtask_usb_state(void)
|
||||
{
|
||||
static uint32_t fsmstate_on_delay = 0; //Delay timer to be sure USB is actually operating before bringing up hardware
|
||||
uint8_t fsmstate_now = USB->DEVICE.FSMSTATUS.reg; //Current state from hardware register
|
||||
|
||||
if (fsmstate_now == USB_FSMSTATUS_FSMSTATE_SUSPEND_Val) //If USB SUSPENDED
|
||||
{
|
||||
fsmstate_on_delay = 0; //Clear ON delay timer
|
||||
|
||||
if (g_usb_state != USB_FSMSTATUS_FSMSTATE_SUSPEND_Val) //If previously not SUSPENDED
|
||||
{
|
||||
suspend_power_down(); //Run suspend routine
|
||||
g_usb_state = fsmstate_now; //Save current USB state
|
||||
}
|
||||
}
|
||||
else if (fsmstate_now == USB_FSMSTATUS_FSMSTATE_SLEEP_Val) //Else if USB SLEEPING
|
||||
{
|
||||
fsmstate_on_delay = 0; //Clear ON delay timer
|
||||
|
||||
if (g_usb_state != USB_FSMSTATUS_FSMSTATE_SLEEP_Val) //If previously not SLEEPING
|
||||
{
|
||||
suspend_power_down(); //Run suspend routine
|
||||
g_usb_state = fsmstate_now; //Save current USB state
|
||||
}
|
||||
}
|
||||
else if (fsmstate_now == USB_FSMSTATUS_FSMSTATE_ON_Val) //Else if USB ON
|
||||
{
|
||||
if (g_usb_state != USB_FSMSTATUS_FSMSTATE_ON_Val) //If previously not ON
|
||||
{
|
||||
if (fsmstate_on_delay == 0) //If ON delay timer is cleared
|
||||
{
|
||||
fsmstate_on_delay = CLK_get_ms() + 250; //Set ON delay timer
|
||||
}
|
||||
else if (CLK_get_ms() > fsmstate_on_delay) //Else if ON delay timer is active and timed out
|
||||
{
|
||||
suspend_wakeup_init(); //Run wakeup routine
|
||||
g_usb_state = fsmstate_now; //Save current USB state
|
||||
}
|
||||
}
|
||||
}
|
||||
else //Else if USB is in a state not being tracked
|
||||
{
|
||||
fsmstate_on_delay = 0; //Clear ON delay timer
|
||||
}
|
||||
}
|
||||
|
||||
void main_subtask_led(void)
|
||||
{
|
||||
if (g_usb_state != USB_FSMSTATUS_FSMSTATE_ON_Val) return; //Only run LED tasks if USB is operating
|
||||
|
||||
led_matrix_task();
|
||||
}
|
||||
|
||||
void main_subtask_power_check(void)
|
||||
{
|
||||
static uint64_t next_5v_checkup = 0;
|
||||
|
||||
if (CLK_get_ms() > next_5v_checkup)
|
||||
{
|
||||
next_5v_checkup = CLK_get_ms() + 5;
|
||||
|
||||
v_5v = adc_get(ADC_5V);
|
||||
v_5v_avg = 0.9 * v_5v_avg + 0.1 * v_5v;
|
||||
|
||||
gcr_compute();
|
||||
}
|
||||
}
|
||||
|
||||
void main_subtask_usb_extra_device(void)
|
||||
{
|
||||
static uint64_t next_usb_checkup = 0;
|
||||
|
||||
if (CLK_get_ms() > next_usb_checkup)
|
||||
{
|
||||
next_usb_checkup = CLK_get_ms() + 10;
|
||||
|
||||
USB_HandleExtraDevice();
|
||||
}
|
||||
}
|
||||
|
||||
void main_subtasks(void)
|
||||
{
|
||||
main_subtask_usb_state();
|
||||
main_subtask_led();
|
||||
main_subtask_power_check();
|
||||
main_subtask_usb_extra_device();
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
DBG_LED_ENA;
|
||||
DBG_1_ENA;
|
||||
DBG_1_OFF;
|
||||
DBG_2_ENA;
|
||||
DBG_2_OFF;
|
||||
DBG_3_ENA;
|
||||
DBG_3_OFF;
|
||||
|
||||
debug_code_init();
|
||||
|
||||
CLK_init();
|
||||
|
||||
ADC0_init();
|
||||
|
||||
SR_EXP_Init();
|
||||
|
||||
i2c1_init();
|
||||
|
||||
matrix_init();
|
||||
|
||||
USB2422_init();
|
||||
|
||||
DBGC(DC_MAIN_UDC_START_BEGIN);
|
||||
udc_start();
|
||||
DBGC(DC_MAIN_UDC_START_COMPLETE);
|
||||
|
||||
DBGC(DC_MAIN_CDC_INIT_BEGIN);
|
||||
CDC_init();
|
||||
DBGC(DC_MAIN_CDC_INIT_COMPLETE);
|
||||
|
||||
while (USB2422_Port_Detect_Init() == 0) {}
|
||||
|
||||
DBG_LED_OFF;
|
||||
|
||||
led_matrix_init();
|
||||
|
||||
while (I2C3733_Init_Control() != 1) {}
|
||||
while (I2C3733_Init_Drivers() != 1) {}
|
||||
|
||||
I2C_DMAC_LED_Init();
|
||||
|
||||
i2c_led_q_init();
|
||||
|
||||
for (uint8_t drvid = 0; drvid < ISSI3733_DRIVER_COUNT; drvid++)
|
||||
I2C_LED_Q_ONOFF(drvid); //Queue data
|
||||
|
||||
keyboard_setup();
|
||||
|
||||
keyboard_init();
|
||||
|
||||
host_set_driver(&arm_atsam_driver);
|
||||
|
||||
#ifdef CONSOLE_ENABLE
|
||||
uint64_t next_print = 0;
|
||||
#endif //CONSOLE_ENABLE
|
||||
|
||||
v_5v_avg = adc_get(ADC_5V);
|
||||
|
||||
debug_code_disable();
|
||||
|
||||
while (1)
|
||||
{
|
||||
main_subtasks(); //Note these tasks will also be run while waiting for USB keyboard polling intervals
|
||||
|
||||
if (g_usb_state == USB_FSMSTATUS_FSMSTATE_SUSPEND_Val || g_usb_state == USB_FSMSTATUS_FSMSTATE_SLEEP_Val)
|
||||
{
|
||||
if (suspend_wakeup_condition())
|
||||
{
|
||||
udc_remotewakeup(); //Send remote wakeup signal
|
||||
wait_ms(50);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
keyboard_task();
|
||||
|
||||
#ifdef CONSOLE_ENABLE
|
||||
if (CLK_get_ms() > next_print)
|
||||
{
|
||||
next_print = CLK_get_ms() + 250;
|
||||
//Add any debug information here that you want to see very often
|
||||
//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
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
23
tmk_core/protocol/arm_atsam/main_arm_atsam.h
Normal file
23
tmk_core/protocol/arm_atsam/main_arm_atsam.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
Copyright 2018 Massdrop Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _MAIN_ARM_ATSAM_H_
|
||||
#define _MAIN_ARM_ATSAM_H_
|
||||
|
||||
uint8_t keyboard_leds(void);
|
||||
|
||||
#endif //_MAIN_ARM_ATSAM_H_
|
25
tmk_core/protocol/arm_atsam/md_bootloader.h
Normal file
25
tmk_core/protocol/arm_atsam/md_bootloader.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
#ifndef _MD_BOOTLOADER_H_
|
||||
#define _MD_BOOTLOADER_H_
|
||||
|
||||
extern uint32_t _srom;
|
||||
extern uint32_t _lrom;
|
||||
extern uint32_t _erom;
|
||||
|
||||
#define BOOTLOADER_SERIAL_MAX_SIZE 20 //DO NOT MODIFY!
|
||||
|
||||
#ifdef KEYBOARD_massdrop_ctrl
|
||||
//WARNING: These are only for CTRL bootloader release "v2.18Jun 22 2018 17:28:08" for bootloader_jump support
|
||||
extern uint32_t _eram;
|
||||
#define BOOTLOADER_MAGIC 0x3B9ACA00
|
||||
#define MAGIC_ADDR (uint32_t *)(&_eram - 4)
|
||||
#endif
|
||||
|
||||
#ifdef MD_BOOTLOADER
|
||||
|
||||
#define MCU_HZ 48000000
|
||||
#define I2C_HZ 0 //Not used
|
||||
|
||||
#endif //MD_BOOTLOADER
|
||||
|
||||
#endif //_MD_BOOTLOADER_H_
|
||||
|
87
tmk_core/protocol/arm_atsam/spi.c
Normal file
87
tmk_core/protocol/arm_atsam/spi.c
Normal file
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
Copyright 2018 Massdrop Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "arm_atsam_protocol.h"
|
||||
|
||||
sr_exp_t sr_exp_data;
|
||||
|
||||
void SR_EXP_WriteData(void)
|
||||
{
|
||||
SR_EXP_RCLK_LO;
|
||||
|
||||
while (!(SR_EXP_SERCOM->SPI.INTFLAG.bit.DRE)) { DBGC(DC_SPI_WRITE_DRE); }
|
||||
|
||||
SR_EXP_SERCOM->SPI.DATA.bit.DATA = sr_exp_data.reg & 0xFF; //Shift in bits 7-0
|
||||
while (!(SR_EXP_SERCOM->SPI.INTFLAG.bit.TXC)) { DBGC(DC_SPI_WRITE_TXC_1); }
|
||||
|
||||
SR_EXP_SERCOM->SPI.DATA.bit.DATA = (sr_exp_data.reg >> 8) & 0xFF; //Shift in bits 15-8
|
||||
while (!(SR_EXP_SERCOM->SPI.INTFLAG.bit.TXC)) { DBGC(DC_SPI_WRITE_TXC_2); }
|
||||
|
||||
SR_EXP_RCLK_HI;
|
||||
}
|
||||
|
||||
void SR_EXP_Init(void)
|
||||
{
|
||||
DBGC(DC_SPI_INIT_BEGIN);
|
||||
|
||||
CLK_set_spi_freq(CHAN_SERCOM_SPI, FREQ_SPI_DEFAULT);
|
||||
|
||||
//Set up MCU Shift Register pins
|
||||
PORT->Group[SR_EXP_RCLK_PORT].DIRSET.reg = (1 << SR_EXP_RCLK_PIN);
|
||||
PORT->Group[SR_EXP_OE_N_PORT].DIRSET.reg = (1 << SR_EXP_OE_N_PIN);
|
||||
|
||||
//Set up MCU SPI pins
|
||||
PORT->Group[SR_EXP_DATAOUT_PORT].PMUX[SR_EXP_DATAOUT_PIN / 2].bit.SR_EXP_DATAOUT_MUX_SEL = SR_EXP_DATAOUT_MUX; //MUX select for sercom
|
||||
PORT->Group[SR_EXP_SCLK_PORT].PMUX[SR_EXP_SCLK_PIN / 2].bit.SR_EXP_SCLK_MUX_SEL = SR_EXP_SCLK_MUX; //MUX select for sercom
|
||||
PORT->Group[SR_EXP_DATAOUT_PORT].PINCFG[SR_EXP_DATAOUT_PIN].bit.PMUXEN = 1; //MUX Enable
|
||||
PORT->Group[SR_EXP_SCLK_PORT].PINCFG[SR_EXP_SCLK_PIN].bit.PMUXEN = 1; //MUX Enable
|
||||
|
||||
//Initialize Shift Register
|
||||
SR_EXP_OE_N_DIS;
|
||||
SR_EXP_RCLK_HI;
|
||||
|
||||
SR_EXP_SERCOM->SPI.CTRLA.bit.DORD = 1; //Data Order - LSB is transferred first
|
||||
SR_EXP_SERCOM->SPI.CTRLA.bit.CPOL = 1; //Clock Polarity - SCK high when idle. Leading edge of cycle is falling. Trailing rising.
|
||||
SR_EXP_SERCOM->SPI.CTRLA.bit.CPHA = 1; //Clock Phase - Leading Edge Falling, change, Trailing Edge - Rising, sample
|
||||
SR_EXP_SERCOM->SPI.CTRLA.bit.DIPO = 3; //Data In Pinout - SERCOM PAD[3] is used as data input (Configure away from DOPO. Not using input.)
|
||||
SR_EXP_SERCOM->SPI.CTRLA.bit.DOPO = 0; //Data Output PAD[0], Serial Clock PAD[1]
|
||||
SR_EXP_SERCOM->SPI.CTRLA.bit.MODE = 3; //Operating Mode - Master operation
|
||||
|
||||
SR_EXP_SERCOM->SPI.CTRLA.bit.ENABLE = 1; //Enable - Peripheral is enabled or being enabled
|
||||
while (SR_EXP_SERCOM->SPI.SYNCBUSY.bit.ENABLE) { DBGC(DC_SPI_SYNC_ENABLING); }
|
||||
|
||||
sr_exp_data.reg = 0;
|
||||
sr_exp_data.bit.HUB_CONNECT = 0;
|
||||
sr_exp_data.bit.HUB_RESET_N = 0;
|
||||
sr_exp_data.bit.S_UP = 0;
|
||||
sr_exp_data.bit.E_UP_N = 1;
|
||||
sr_exp_data.bit.S_DN1 = 1;
|
||||
sr_exp_data.bit.E_DN1_N = 1;
|
||||
sr_exp_data.bit.E_VBUS_1 = 0;
|
||||
sr_exp_data.bit.E_VBUS_2 = 0;
|
||||
sr_exp_data.bit.SRC_1 = 1;
|
||||
sr_exp_data.bit.SRC_2 = 1;
|
||||
sr_exp_data.bit.IRST = 1;
|
||||
sr_exp_data.bit.SDB_N = 0;
|
||||
SR_EXP_WriteData();
|
||||
|
||||
//Enable Shift Register output
|
||||
SR_EXP_OE_N_ENA;
|
||||
|
||||
DBGC(DC_SPI_INIT_COMPLETE);
|
||||
}
|
||||
|
70
tmk_core/protocol/arm_atsam/spi.h
Normal file
70
tmk_core/protocol/arm_atsam/spi.h
Normal file
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
Copyright 2018 Massdrop Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _SPI_H_
|
||||
#define _SPI_H_
|
||||
|
||||
/* Macros for Shift Register control */
|
||||
#define SR_EXP_RCLK_LO PORT->Group[SR_EXP_RCLK_PORT].OUTCLR.reg = (1 << SR_EXP_RCLK_PIN)
|
||||
#define SR_EXP_RCLK_HI PORT->Group[SR_EXP_RCLK_PORT].OUTSET.reg = (1 << SR_EXP_RCLK_PIN)
|
||||
#define SR_EXP_OE_N_ENA PORT->Group[SR_EXP_OE_N_PORT].OUTCLR.reg = (1 << SR_EXP_OE_N_PIN)
|
||||
#define SR_EXP_OE_N_DIS PORT->Group[SR_EXP_OE_N_PORT].OUTSET.reg = (1 << SR_EXP_OE_N_PIN)
|
||||
|
||||
/* Determine bits to set for mux selection */
|
||||
#if SR_EXP_DATAOUT_PIN % 2 == 0
|
||||
#define SR_EXP_DATAOUT_MUX_SEL PMUXE
|
||||
#else
|
||||
#define SR_EXP_DATAOUT_MUX_SEL PMUXO
|
||||
#endif
|
||||
|
||||
/* Determine bits to set for mux selection */
|
||||
#if SR_EXP_SCLK_PIN % 2 == 0
|
||||
#define SR_EXP_SCLK_MUX_SEL PMUXE
|
||||
#else
|
||||
#define SR_EXP_SCLK_MUX_SEL PMUXO
|
||||
#endif
|
||||
|
||||
/* Data structure to define Shift Register output expander hardware */
|
||||
/* This structure gets shifted into registers LSB first */
|
||||
typedef union {
|
||||
struct {
|
||||
uint16_t RSVD4:1; /*!< bit: 0 */
|
||||
uint16_t RSVD3:1; /*!< bit: 1 */
|
||||
uint16_t RSVD2:1; /*!< bit: 2 */
|
||||
uint16_t RSVD1:1; /*!< bit: 3 */
|
||||
uint16_t SDB_N:1; /*!< bit: 4 SHUTDOWN THE CHIP WHEN 0, RUN WHEN 1 */
|
||||
uint16_t IRST:1; /*!< bit: 5 RESET THE IS3733 I2C WHEN 1, RUN WHEN 0 */
|
||||
uint16_t SRC_2:1; /*!< bit: 6 ADVERTISE A SOURCE TO USBC-2 CC */
|
||||
uint16_t SRC_1:1; /*!< bit: 7 ADVERTISE A SOURCE TO USBC-1 CC */
|
||||
uint16_t E_VBUS_2:1; /*!< bit: 8 ENABLE 5V OUT TO USBC-2 WHEN 1 */
|
||||
uint16_t E_VBUS_1:1; /*!< bit: 9 ENABLE 5V OUT TO USBC-1 WHEN 1 */
|
||||
uint16_t E_DN1_N:1; /*!< bit: 10 ENABLE DN1 1:2 MUX WHEN 0 */
|
||||
uint16_t S_DN1:1; /*!< bit: 11 SELECT DN1 PATH 0:USBC-1, 1:USBC-2 */
|
||||
uint16_t E_UP_N:1; /*!< bit: 12 ENABLE SUP 1:2 MUX WHEN 0 */
|
||||
uint16_t S_UP:1; /*!< bit: 13 SELECT UP PATH 0:USBC-1, 1:USBC-2 */
|
||||
uint16_t HUB_RESET_N:1; /*!< bit: 14 RESET USB HUB WHEN 0, RUN WHEN 1 */
|
||||
uint16_t HUB_CONNECT:1; /*!< bit: 15 SIGNAL VBUS CONNECT TO USB HUB WHEN 1 */
|
||||
} bit; /*!< Structure used for bit access */
|
||||
uint16_t reg; /*!< Type used for register access */
|
||||
} sr_exp_t;
|
||||
|
||||
extern sr_exp_t sr_exp_data;
|
||||
|
||||
void SR_EXP_WriteData(void);
|
||||
void SR_EXP_Init(void);
|
||||
|
||||
#endif //_SPI_H_
|
559
tmk_core/protocol/arm_atsam/startup.c
Normal file
559
tmk_core/protocol/arm_atsam/startup.c
Normal file
|
@ -0,0 +1,559 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief gcc starttup file for SAMD51
|
||||
*
|
||||
* Copyright (c) 2017 Microchip Technology Inc.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the Licence at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
|
||||
#include "samd51.h"
|
||||
#include "md_bootloader.h"
|
||||
|
||||
/* Initialize segments */
|
||||
extern uint32_t _sfixed;
|
||||
extern uint32_t _efixed;
|
||||
extern uint32_t _etext;
|
||||
extern uint32_t _srelocate;
|
||||
extern uint32_t _erelocate;
|
||||
extern uint32_t _szero;
|
||||
extern uint32_t _ezero;
|
||||
extern uint32_t _sstack;
|
||||
extern uint32_t _estack;
|
||||
|
||||
/** \cond DOXYGEN_SHOULD_SKIP_THIS */
|
||||
int main(void);
|
||||
/** \endcond */
|
||||
|
||||
void __libc_init_array(void);
|
||||
|
||||
/* Default empty handler */
|
||||
void Dummy_Handler(void);
|
||||
|
||||
/* Cortex-M4 core handlers */
|
||||
void NMI_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
void HardFault_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
void MemManage_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
void BusFault_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
void UsageFault_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
void SVC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
void DebugMon_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
void PendSV_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
void SysTick_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
|
||||
/* Peripherals handlers */
|
||||
void PM_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
void MCLK_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
void OSCCTRL_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* OSCCTRL_XOSCFAIL_0, OSCCTRL_XOSCRDY_0 */
|
||||
void OSCCTRL_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* OSCCTRL_XOSCFAIL_1, OSCCTRL_XOSCRDY_1 */
|
||||
void OSCCTRL_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* OSCCTRL_DFLLLOCKC, OSCCTRL_DFLLLOCKF, OSCCTRL_DFLLOOB, OSCCTRL_DFLLRCS, OSCCTRL_DFLLRDY */
|
||||
void OSCCTRL_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* OSCCTRL_DPLLLCKF_0, OSCCTRL_DPLLLCKR_0, OSCCTRL_DPLLLDRTO_0, OSCCTRL_DPLLLTO_0 */
|
||||
void OSCCTRL_4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* OSCCTRL_DPLLLCKF_1, OSCCTRL_DPLLLCKR_1, OSCCTRL_DPLLLDRTO_1, OSCCTRL_DPLLLTO_1 */
|
||||
void OSC32KCTRL_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
void SUPC_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SUPC_B12SRDY, SUPC_B33SRDY, SUPC_BOD12RDY, SUPC_BOD33RDY, SUPC_VCORERDY, SUPC_VREGRDY */
|
||||
void SUPC_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SUPC_BOD12DET, SUPC_BOD33DET */
|
||||
void WDT_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
void RTC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
void EIC_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_0 */
|
||||
void EIC_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_1 */
|
||||
void EIC_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_2 */
|
||||
void EIC_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_3 */
|
||||
void EIC_4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_4 */
|
||||
void EIC_5_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_5 */
|
||||
void EIC_6_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_6 */
|
||||
void EIC_7_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_7 */
|
||||
void EIC_8_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_8 */
|
||||
void EIC_9_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_9 */
|
||||
void EIC_10_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_10 */
|
||||
void EIC_11_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_11 */
|
||||
void EIC_12_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_12 */
|
||||
void EIC_13_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_13 */
|
||||
void EIC_14_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_14 */
|
||||
void EIC_15_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_15 */
|
||||
void FREQM_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
void NVMCTRL_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* NVMCTRL_0, NVMCTRL_1, NVMCTRL_2, NVMCTRL_3, NVMCTRL_4, NVMCTRL_5, NVMCTRL_6, NVMCTRL_7 */
|
||||
void NVMCTRL_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* NVMCTRL_10, NVMCTRL_8, NVMCTRL_9 */
|
||||
void DMAC_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DMAC_SUSP_0, DMAC_TCMPL_0, DMAC_TERR_0 */
|
||||
void DMAC_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DMAC_SUSP_1, DMAC_TCMPL_1, DMAC_TERR_1 */
|
||||
void DMAC_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DMAC_SUSP_2, DMAC_TCMPL_2, DMAC_TERR_2 */
|
||||
void DMAC_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DMAC_SUSP_3, DMAC_TCMPL_3, DMAC_TERR_3 */
|
||||
void DMAC_4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DMAC_SUSP_10, DMAC_SUSP_11, DMAC_SUSP_12, DMAC_SUSP_13, DMAC_SUSP_14, DMAC_SUSP_15, DMAC_SUSP_16, DMAC_SUSP_17, DMAC_SUSP_18, DMAC_SUSP_19, DMAC_SUSP_20, DMAC_SUSP_21, DMAC_SUSP_22, DMAC_SUSP_23, DMAC_SUSP_24, DMAC_SUSP_25, DMAC_SUSP_26, DMAC_SUSP_27, DMAC_SUSP_28, DMAC_SUSP_29, DMAC_SUSP_30, DMAC_SUSP_31, DMAC_SUSP_4, DMAC_SUSP_5, DMAC_SUSP_6, DMAC_SUSP_7, DMAC_SUSP_8, DMAC_SUSP_9, DMAC_TCMPL_10, DMAC_TCMPL_11, DMAC_TCMPL_12, DMAC_TCMPL_13, DMAC_TCMPL_14, DMAC_TCMPL_15, DMAC_TCMPL_16, DMAC_TCMPL_17, DMAC_TCMPL_18, DMAC_TCMPL_19, DMAC_TCMPL_20, DMAC_TCMPL_21, DMAC_TCMPL_22, DMAC_TCMPL_23, DMAC_TCMPL_24, DMAC_TCMPL_25, DMAC_TCMPL_26, DMAC_TCMPL_27, DMAC_TCMPL_28, DMAC_TCMPL_29, DMAC_TCMPL_30, DMAC_TCMPL_31, DMAC_TCMPL_4, DMAC_TCMPL_5, DMAC_TCMPL_6, DMAC_TCMPL_7, DMAC_TCMPL_8, DMAC_TCMPL_9, DMAC_TERR_10, DMAC_TERR_11, DMAC_TERR_12, DMAC_TERR_13, DMAC_TERR_14, DMAC_TERR_15, DMAC_TERR_16, DMAC_TERR_17, DMAC_TERR_18, DMAC_TERR_19, DMAC_TERR_20, DMAC_TERR_21, DMAC_TERR_22, DMAC_TERR_23, DMAC_TERR_24, DMAC_TERR_25, DMAC_TERR_26, DMAC_TERR_27, DMAC_TERR_28, DMAC_TERR_29, DMAC_TERR_30, DMAC_TERR_31, DMAC_TERR_4, DMAC_TERR_5, DMAC_TERR_6, DMAC_TERR_7, DMAC_TERR_8, DMAC_TERR_9 */
|
||||
void EVSYS_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EVSYS_EVD_0, EVSYS_OVR_0 */
|
||||
void EVSYS_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EVSYS_EVD_1, EVSYS_OVR_1 */
|
||||
void EVSYS_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EVSYS_EVD_2, EVSYS_OVR_2 */
|
||||
void EVSYS_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EVSYS_EVD_3, EVSYS_OVR_3 */
|
||||
void EVSYS_4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EVSYS_EVD_10, EVSYS_EVD_11, EVSYS_EVD_4, EVSYS_EVD_5, EVSYS_EVD_6, EVSYS_EVD_7, EVSYS_EVD_8, EVSYS_EVD_9, EVSYS_OVR_10, EVSYS_OVR_11, EVSYS_OVR_4, EVSYS_OVR_5, EVSYS_OVR_6, EVSYS_OVR_7, EVSYS_OVR_8, EVSYS_OVR_9 */
|
||||
void PAC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
void TAL_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TAL_BRK */
|
||||
void TAL_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TAL_IPS_0, TAL_IPS_1 */
|
||||
void RAMECC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
void SERCOM0_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM0_0 */
|
||||
void SERCOM0_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM0_1 */
|
||||
void SERCOM0_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM0_2 */
|
||||
void SERCOM0_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM0_3, SERCOM0_4, SERCOM0_5, SERCOM0_6 */
|
||||
void SERCOM1_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM1_0 */
|
||||
void SERCOM1_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM1_1 */
|
||||
void SERCOM1_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM1_2 */
|
||||
void SERCOM1_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM1_3, SERCOM1_4, SERCOM1_5, SERCOM1_6 */
|
||||
void SERCOM2_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM2_0 */
|
||||
void SERCOM2_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM2_1 */
|
||||
void SERCOM2_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM2_2 */
|
||||
void SERCOM2_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM2_3, SERCOM2_4, SERCOM2_5, SERCOM2_6 */
|
||||
void SERCOM3_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM3_0 */
|
||||
void SERCOM3_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM3_1 */
|
||||
void SERCOM3_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM3_2 */
|
||||
void SERCOM3_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM3_3, SERCOM3_4, SERCOM3_5, SERCOM3_6 */
|
||||
#ifdef ID_SERCOM4
|
||||
void SERCOM4_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM4_0 */
|
||||
void SERCOM4_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM4_1 */
|
||||
void SERCOM4_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM4_2 */
|
||||
void SERCOM4_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM4_3, SERCOM4_4, SERCOM4_5, SERCOM4_6 */
|
||||
#endif
|
||||
#ifdef ID_SERCOM5
|
||||
void SERCOM5_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM5_0 */
|
||||
void SERCOM5_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM5_1 */
|
||||
void SERCOM5_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM5_2 */
|
||||
void SERCOM5_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM5_3, SERCOM5_4, SERCOM5_5, SERCOM5_6 */
|
||||
#endif
|
||||
#ifdef ID_SERCOM6
|
||||
void SERCOM6_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM6_0 */
|
||||
void SERCOM6_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM6_1 */
|
||||
void SERCOM6_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM6_2 */
|
||||
void SERCOM6_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM6_3, SERCOM6_4, SERCOM6_5, SERCOM6_6 */
|
||||
#endif
|
||||
#ifdef ID_SERCOM7
|
||||
void SERCOM7_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM7_0 */
|
||||
void SERCOM7_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM7_1 */
|
||||
void SERCOM7_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM7_2 */
|
||||
void SERCOM7_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM7_3, SERCOM7_4, SERCOM7_5, SERCOM7_6 */
|
||||
#endif
|
||||
#ifdef ID_CAN0
|
||||
void CAN0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
#endif
|
||||
#ifdef ID_CAN1
|
||||
void CAN1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
#endif
|
||||
#ifdef ID_USB
|
||||
void USB_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* USB_EORSM_DNRSM, USB_EORST_RST, USB_LPMSUSP_DDISC, USB_LPM_DCONN, USB_MSOF, USB_RAMACER, USB_RXSTP_TXSTP_0, USB_RXSTP_TXSTP_1, USB_RXSTP_TXSTP_2, USB_RXSTP_TXSTP_3, USB_RXSTP_TXSTP_4, USB_RXSTP_TXSTP_5, USB_RXSTP_TXSTP_6, USB_RXSTP_TXSTP_7, USB_STALL0_STALL_0, USB_STALL0_STALL_1, USB_STALL0_STALL_2, USB_STALL0_STALL_3, USB_STALL0_STALL_4, USB_STALL0_STALL_5, USB_STALL0_STALL_6, USB_STALL0_STALL_7, USB_STALL1_0, USB_STALL1_1, USB_STALL1_2, USB_STALL1_3, USB_STALL1_4, USB_STALL1_5, USB_STALL1_6, USB_STALL1_7, USB_SUSPEND, USB_TRFAIL0_TRFAIL_0, USB_TRFAIL0_TRFAIL_1, USB_TRFAIL0_TRFAIL_2, USB_TRFAIL0_TRFAIL_3, USB_TRFAIL0_TRFAIL_4, USB_TRFAIL0_TRFAIL_5, USB_TRFAIL0_TRFAIL_6, USB_TRFAIL0_TRFAIL_7, USB_TRFAIL1_PERR_0, USB_TRFAIL1_PERR_1, USB_TRFAIL1_PERR_2, USB_TRFAIL1_PERR_3, USB_TRFAIL1_PERR_4, USB_TRFAIL1_PERR_5, USB_TRFAIL1_PERR_6, USB_TRFAIL1_PERR_7, USB_UPRSM, USB_WAKEUP */
|
||||
void USB_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* USB_SOF_HSOF */
|
||||
void USB_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* USB_TRCPT0_0, USB_TRCPT0_1, USB_TRCPT0_2, USB_TRCPT0_3, USB_TRCPT0_4, USB_TRCPT0_5, USB_TRCPT0_6, USB_TRCPT0_7 */
|
||||
void USB_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* USB_TRCPT1_0, USB_TRCPT1_1, USB_TRCPT1_2, USB_TRCPT1_3, USB_TRCPT1_4, USB_TRCPT1_5, USB_TRCPT1_6, USB_TRCPT1_7 */
|
||||
#endif
|
||||
#ifdef ID_GMAC
|
||||
void GMAC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
#endif
|
||||
void TCC0_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC0_CNT_A, TCC0_DFS_A, TCC0_ERR_A, TCC0_FAULT0_A, TCC0_FAULT1_A, TCC0_FAULTA_A, TCC0_FAULTB_A, TCC0_OVF, TCC0_TRG, TCC0_UFS_A */
|
||||
void TCC0_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC0_MC_0 */
|
||||
void TCC0_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC0_MC_1 */
|
||||
void TCC0_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC0_MC_2 */
|
||||
void TCC0_4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC0_MC_3 */
|
||||
void TCC0_5_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC0_MC_4 */
|
||||
void TCC0_6_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC0_MC_5 */
|
||||
void TCC1_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC1_CNT_A, TCC1_DFS_A, TCC1_ERR_A, TCC1_FAULT0_A, TCC1_FAULT1_A, TCC1_FAULTA_A, TCC1_FAULTB_A, TCC1_OVF, TCC1_TRG, TCC1_UFS_A */
|
||||
void TCC1_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC1_MC_0 */
|
||||
void TCC1_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC1_MC_1 */
|
||||
void TCC1_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC1_MC_2 */
|
||||
void TCC1_4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC1_MC_3 */
|
||||
void TCC2_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC2_CNT_A, TCC2_DFS_A, TCC2_ERR_A, TCC2_FAULT0_A, TCC2_FAULT1_A, TCC2_FAULTA_A, TCC2_FAULTB_A, TCC2_OVF, TCC2_TRG, TCC2_UFS_A */
|
||||
void TCC2_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC2_MC_0 */
|
||||
void TCC2_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC2_MC_1 */
|
||||
void TCC2_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC2_MC_2 */
|
||||
#ifdef ID_TCC3
|
||||
void TCC3_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC3_CNT_A, TCC3_DFS_A, TCC3_ERR_A, TCC3_FAULT0_A, TCC3_FAULT1_A, TCC3_FAULTA_A, TCC3_FAULTB_A, TCC3_OVF, TCC3_TRG, TCC3_UFS_A */
|
||||
void TCC3_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC3_MC_0 */
|
||||
void TCC3_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC3_MC_1 */
|
||||
#endif
|
||||
#ifdef ID_TCC4
|
||||
void TCC4_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC4_CNT_A, TCC4_DFS_A, TCC4_ERR_A, TCC4_FAULT0_A, TCC4_FAULT1_A, TCC4_FAULTA_A, TCC4_FAULTB_A, TCC4_OVF, TCC4_TRG, TCC4_UFS_A */
|
||||
void TCC4_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC4_MC_0 */
|
||||
void TCC4_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC4_MC_1 */
|
||||
#endif
|
||||
void TC0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
void TC1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
void TC2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
void TC3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
#ifdef ID_TC4
|
||||
void TC4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
#endif
|
||||
#ifdef ID_TC5
|
||||
void TC5_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
#endif
|
||||
#ifdef ID_TC6
|
||||
void TC6_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
#endif
|
||||
#ifdef ID_TC7
|
||||
void TC7_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
#endif
|
||||
void PDEC_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* PDEC_DIR_A, PDEC_ERR_A, PDEC_OVF, PDEC_VLC_A */
|
||||
void PDEC_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* PDEC_MC_0 */
|
||||
void PDEC_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* PDEC_MC_1 */
|
||||
void ADC0_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* ADC0_OVERRUN, ADC0_WINMON */
|
||||
void ADC0_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* ADC0_RESRDY */
|
||||
void ADC1_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* ADC1_OVERRUN, ADC1_WINMON */
|
||||
void ADC1_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* ADC1_RESRDY */
|
||||
void AC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
void DAC_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DAC_OVERRUN_A_0, DAC_OVERRUN_A_1, DAC_UNDERRUN_A_0, DAC_UNDERRUN_A_1 */
|
||||
void DAC_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DAC_EMPTY_0 */
|
||||
void DAC_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DAC_EMPTY_1 */
|
||||
void DAC_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DAC_RESRDY_0 */
|
||||
void DAC_4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DAC_RESRDY_1 */
|
||||
#ifdef ID_I2S
|
||||
void I2S_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
#endif
|
||||
void PCC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
void AES_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
void TRNG_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
#ifdef ID_ICM
|
||||
void ICM_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
#endif
|
||||
#ifdef ID_PUKCC
|
||||
void PUKCC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
#endif
|
||||
void QSPI_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
#ifdef ID_SDHC0
|
||||
void SDHC0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
#endif
|
||||
#ifdef ID_SDHC1
|
||||
void SDHC1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
|
||||
#endif
|
||||
|
||||
/* Exception Table */
|
||||
__attribute__ ((section(".vectors")))
|
||||
const DeviceVectors exception_table = {
|
||||
|
||||
/* Configure Initial Stack Pointer, using linker-generated symbols */
|
||||
.pvStack = (void*) (&_estack),
|
||||
|
||||
.pfnReset_Handler = (void*) Reset_Handler,
|
||||
.pfnNMI_Handler = (void*) NMI_Handler,
|
||||
.pfnHardFault_Handler = (void*) HardFault_Handler,
|
||||
.pfnMemManage_Handler = (void*) MemManage_Handler,
|
||||
.pfnBusFault_Handler = (void*) BusFault_Handler,
|
||||
.pfnUsageFault_Handler = (void*) UsageFault_Handler,
|
||||
.pvReservedM9 = (void*) (0UL), /* Reserved */
|
||||
.pvReservedM8 = (void*) (0UL), /* Reserved */
|
||||
.pvReservedM7 = (void*) (0UL), /* Reserved */
|
||||
.pvReservedM6 = (void*) (0UL), /* Reserved */
|
||||
.pfnSVC_Handler = (void*) SVC_Handler,
|
||||
.pfnDebugMon_Handler = (void*) DebugMon_Handler,
|
||||
.pvReservedM3 = (void*) (0UL), /* Reserved */
|
||||
.pfnPendSV_Handler = (void*) PendSV_Handler,
|
||||
.pfnSysTick_Handler = (void*) SysTick_Handler,
|
||||
|
||||
/* Configurable interrupts */
|
||||
.pfnPM_Handler = (void*) PM_Handler, /* 0 Power Manager */
|
||||
.pfnMCLK_Handler = (void*) MCLK_Handler, /* 1 Main Clock */
|
||||
.pfnOSCCTRL_0_Handler = (void*) OSCCTRL_0_Handler, /* 2 OSCCTRL_XOSCFAIL_0, OSCCTRL_XOSCRDY_0 */
|
||||
.pfnOSCCTRL_1_Handler = (void*) OSCCTRL_1_Handler, /* 3 OSCCTRL_XOSCFAIL_1, OSCCTRL_XOSCRDY_1 */
|
||||
.pfnOSCCTRL_2_Handler = (void*) OSCCTRL_2_Handler, /* 4 OSCCTRL_DFLLLOCKC, OSCCTRL_DFLLLOCKF, OSCCTRL_DFLLOOB, OSCCTRL_DFLLRCS, OSCCTRL_DFLLRDY */
|
||||
.pfnOSCCTRL_3_Handler = (void*) OSCCTRL_3_Handler, /* 5 OSCCTRL_DPLLLCKF_0, OSCCTRL_DPLLLCKR_0, OSCCTRL_DPLLLDRTO_0, OSCCTRL_DPLLLTO_0 */
|
||||
.pfnOSCCTRL_4_Handler = (void*) OSCCTRL_4_Handler, /* 6 OSCCTRL_DPLLLCKF_1, OSCCTRL_DPLLLCKR_1, OSCCTRL_DPLLLDRTO_1, OSCCTRL_DPLLLTO_1 */
|
||||
.pfnOSC32KCTRL_Handler = (void*) OSC32KCTRL_Handler, /* 7 32kHz Oscillators Control */
|
||||
.pfnSUPC_0_Handler = (void*) SUPC_0_Handler, /* 8 SUPC_B12SRDY, SUPC_B33SRDY, SUPC_BOD12RDY, SUPC_BOD33RDY, SUPC_VCORERDY, SUPC_VREGRDY */
|
||||
.pfnSUPC_1_Handler = (void*) SUPC_1_Handler, /* 9 SUPC_BOD12DET, SUPC_BOD33DET */
|
||||
.pfnWDT_Handler = (void*) WDT_Handler, /* 10 Watchdog Timer */
|
||||
.pfnRTC_Handler = (void*) RTC_Handler, /* 11 Real-Time Counter */
|
||||
.pfnEIC_0_Handler = (void*) EIC_0_Handler, /* 12 EIC_EXTINT_0 */
|
||||
.pfnEIC_1_Handler = (void*) EIC_1_Handler, /* 13 EIC_EXTINT_1 */
|
||||
.pfnEIC_2_Handler = (void*) EIC_2_Handler, /* 14 EIC_EXTINT_2 */
|
||||
.pfnEIC_3_Handler = (void*) EIC_3_Handler, /* 15 EIC_EXTINT_3 */
|
||||
.pfnEIC_4_Handler = (void*) EIC_4_Handler, /* 16 EIC_EXTINT_4 */
|
||||
.pfnEIC_5_Handler = (void*) EIC_5_Handler, /* 17 EIC_EXTINT_5 */
|
||||
.pfnEIC_6_Handler = (void*) EIC_6_Handler, /* 18 EIC_EXTINT_6 */
|
||||
.pfnEIC_7_Handler = (void*) EIC_7_Handler, /* 19 EIC_EXTINT_7 */
|
||||
.pfnEIC_8_Handler = (void*) EIC_8_Handler, /* 20 EIC_EXTINT_8 */
|
||||
.pfnEIC_9_Handler = (void*) EIC_9_Handler, /* 21 EIC_EXTINT_9 */
|
||||
.pfnEIC_10_Handler = (void*) EIC_10_Handler, /* 22 EIC_EXTINT_10 */
|
||||
.pfnEIC_11_Handler = (void*) EIC_11_Handler, /* 23 EIC_EXTINT_11 */
|
||||
.pfnEIC_12_Handler = (void*) EIC_12_Handler, /* 24 EIC_EXTINT_12 */
|
||||
.pfnEIC_13_Handler = (void*) EIC_13_Handler, /* 25 EIC_EXTINT_13 */
|
||||
.pfnEIC_14_Handler = (void*) EIC_14_Handler, /* 26 EIC_EXTINT_14 */
|
||||
.pfnEIC_15_Handler = (void*) EIC_15_Handler, /* 27 EIC_EXTINT_15 */
|
||||
.pfnFREQM_Handler = (void*) FREQM_Handler, /* 28 Frequency Meter */
|
||||
.pfnNVMCTRL_0_Handler = (void*) NVMCTRL_0_Handler, /* 29 NVMCTRL_0, NVMCTRL_1, NVMCTRL_2, NVMCTRL_3, NVMCTRL_4, NVMCTRL_5, NVMCTRL_6, NVMCTRL_7 */
|
||||
.pfnNVMCTRL_1_Handler = (void*) NVMCTRL_1_Handler, /* 30 NVMCTRL_10, NVMCTRL_8, NVMCTRL_9 */
|
||||
.pfnDMAC_0_Handler = (void*) DMAC_0_Handler, /* 31 DMAC_SUSP_0, DMAC_TCMPL_0, DMAC_TERR_0 */
|
||||
.pfnDMAC_1_Handler = (void*) DMAC_1_Handler, /* 32 DMAC_SUSP_1, DMAC_TCMPL_1, DMAC_TERR_1 */
|
||||
.pfnDMAC_2_Handler = (void*) DMAC_2_Handler, /* 33 DMAC_SUSP_2, DMAC_TCMPL_2, DMAC_TERR_2 */
|
||||
.pfnDMAC_3_Handler = (void*) DMAC_3_Handler, /* 34 DMAC_SUSP_3, DMAC_TCMPL_3, DMAC_TERR_3 */
|
||||
.pfnDMAC_4_Handler = (void*) DMAC_4_Handler, /* 35 DMAC_SUSP_10, DMAC_SUSP_11, DMAC_SUSP_12, DMAC_SUSP_13, DMAC_SUSP_14, DMAC_SUSP_15, DMAC_SUSP_16, DMAC_SUSP_17, DMAC_SUSP_18, DMAC_SUSP_19, DMAC_SUSP_20, DMAC_SUSP_21, DMAC_SUSP_22, DMAC_SUSP_23, DMAC_SUSP_24, DMAC_SUSP_25, DMAC_SUSP_26, DMAC_SUSP_27, DMAC_SUSP_28, DMAC_SUSP_29, DMAC_SUSP_30, DMAC_SUSP_31, DMAC_SUSP_4, DMAC_SUSP_5, DMAC_SUSP_6, DMAC_SUSP_7, DMAC_SUSP_8, DMAC_SUSP_9, DMAC_TCMPL_10, DMAC_TCMPL_11, DMAC_TCMPL_12, DMAC_TCMPL_13, DMAC_TCMPL_14, DMAC_TCMPL_15, DMAC_TCMPL_16, DMAC_TCMPL_17, DMAC_TCMPL_18, DMAC_TCMPL_19, DMAC_TCMPL_20, DMAC_TCMPL_21, DMAC_TCMPL_22, DMAC_TCMPL_23, DMAC_TCMPL_24, DMAC_TCMPL_25, DMAC_TCMPL_26, DMAC_TCMPL_27, DMAC_TCMPL_28, DMAC_TCMPL_29, DMAC_TCMPL_30, DMAC_TCMPL_31, DMAC_TCMPL_4, DMAC_TCMPL_5, DMAC_TCMPL_6, DMAC_TCMPL_7, DMAC_TCMPL_8, DMAC_TCMPL_9, DMAC_TERR_10, DMAC_TERR_11, DMAC_TERR_12, DMAC_TERR_13, DMAC_TERR_14, DMAC_TERR_15, DMAC_TERR_16, DMAC_TERR_17, DMAC_TERR_18, DMAC_TERR_19, DMAC_TERR_20, DMAC_TERR_21, DMAC_TERR_22, DMAC_TERR_23, DMAC_TERR_24, DMAC_TERR_25, DMAC_TERR_26, DMAC_TERR_27, DMAC_TERR_28, DMAC_TERR_29, DMAC_TERR_30, DMAC_TERR_31, DMAC_TERR_4, DMAC_TERR_5, DMAC_TERR_6, DMAC_TERR_7, DMAC_TERR_8, DMAC_TERR_9 */
|
||||
.pfnEVSYS_0_Handler = (void*) EVSYS_0_Handler, /* 36 EVSYS_EVD_0, EVSYS_OVR_0 */
|
||||
.pfnEVSYS_1_Handler = (void*) EVSYS_1_Handler, /* 37 EVSYS_EVD_1, EVSYS_OVR_1 */
|
||||
.pfnEVSYS_2_Handler = (void*) EVSYS_2_Handler, /* 38 EVSYS_EVD_2, EVSYS_OVR_2 */
|
||||
.pfnEVSYS_3_Handler = (void*) EVSYS_3_Handler, /* 39 EVSYS_EVD_3, EVSYS_OVR_3 */
|
||||
.pfnEVSYS_4_Handler = (void*) EVSYS_4_Handler, /* 40 EVSYS_EVD_10, EVSYS_EVD_11, EVSYS_EVD_4, EVSYS_EVD_5, EVSYS_EVD_6, EVSYS_EVD_7, EVSYS_EVD_8, EVSYS_EVD_9, EVSYS_OVR_10, EVSYS_OVR_11, EVSYS_OVR_4, EVSYS_OVR_5, EVSYS_OVR_6, EVSYS_OVR_7, EVSYS_OVR_8, EVSYS_OVR_9 */
|
||||
.pfnPAC_Handler = (void*) PAC_Handler, /* 41 Peripheral Access Controller */
|
||||
.pfnTAL_0_Handler = (void*) TAL_0_Handler, /* 42 TAL_BRK */
|
||||
.pfnTAL_1_Handler = (void*) TAL_1_Handler, /* 43 TAL_IPS_0, TAL_IPS_1 */
|
||||
.pvReserved44 = (void*) (0UL), /* 44 Reserved */
|
||||
.pfnRAMECC_Handler = (void*) RAMECC_Handler, /* 45 RAM ECC */
|
||||
.pfnSERCOM0_0_Handler = (void*) SERCOM0_0_Handler, /* 46 SERCOM0_0 */
|
||||
.pfnSERCOM0_1_Handler = (void*) SERCOM0_1_Handler, /* 47 SERCOM0_1 */
|
||||
.pfnSERCOM0_2_Handler = (void*) SERCOM0_2_Handler, /* 48 SERCOM0_2 */
|
||||
.pfnSERCOM0_3_Handler = (void*) SERCOM0_3_Handler, /* 49 SERCOM0_3, SERCOM0_4, SERCOM0_5, SERCOM0_6 */
|
||||
.pfnSERCOM1_0_Handler = (void*) SERCOM1_0_Handler, /* 50 SERCOM1_0 */
|
||||
.pfnSERCOM1_1_Handler = (void*) SERCOM1_1_Handler, /* 51 SERCOM1_1 */
|
||||
.pfnSERCOM1_2_Handler = (void*) SERCOM1_2_Handler, /* 52 SERCOM1_2 */
|
||||
.pfnSERCOM1_3_Handler = (void*) SERCOM1_3_Handler, /* 53 SERCOM1_3, SERCOM1_4, SERCOM1_5, SERCOM1_6 */
|
||||
.pfnSERCOM2_0_Handler = (void*) SERCOM2_0_Handler, /* 54 SERCOM2_0 */
|
||||
.pfnSERCOM2_1_Handler = (void*) SERCOM2_1_Handler, /* 55 SERCOM2_1 */
|
||||
.pfnSERCOM2_2_Handler = (void*) SERCOM2_2_Handler, /* 56 SERCOM2_2 */
|
||||
.pfnSERCOM2_3_Handler = (void*) SERCOM2_3_Handler, /* 57 SERCOM2_3, SERCOM2_4, SERCOM2_5, SERCOM2_6 */
|
||||
.pfnSERCOM3_0_Handler = (void*) SERCOM3_0_Handler, /* 58 SERCOM3_0 */
|
||||
.pfnSERCOM3_1_Handler = (void*) SERCOM3_1_Handler, /* 59 SERCOM3_1 */
|
||||
.pfnSERCOM3_2_Handler = (void*) SERCOM3_2_Handler, /* 60 SERCOM3_2 */
|
||||
.pfnSERCOM3_3_Handler = (void*) SERCOM3_3_Handler, /* 61 SERCOM3_3, SERCOM3_4, SERCOM3_5, SERCOM3_6 */
|
||||
#ifdef ID_SERCOM4
|
||||
.pfnSERCOM4_0_Handler = (void*) SERCOM4_0_Handler, /* 62 SERCOM4_0 */
|
||||
.pfnSERCOM4_1_Handler = (void*) SERCOM4_1_Handler, /* 63 SERCOM4_1 */
|
||||
.pfnSERCOM4_2_Handler = (void*) SERCOM4_2_Handler, /* 64 SERCOM4_2 */
|
||||
.pfnSERCOM4_3_Handler = (void*) SERCOM4_3_Handler, /* 65 SERCOM4_3, SERCOM4_4, SERCOM4_5, SERCOM4_6 */
|
||||
#else
|
||||
.pvReserved62 = (void*) (0UL), /* 62 Reserved */
|
||||
.pvReserved63 = (void*) (0UL), /* 63 Reserved */
|
||||
.pvReserved64 = (void*) (0UL), /* 64 Reserved */
|
||||
.pvReserved65 = (void*) (0UL), /* 65 Reserved */
|
||||
#endif
|
||||
#ifdef ID_SERCOM5
|
||||
.pfnSERCOM5_0_Handler = (void*) SERCOM5_0_Handler, /* 66 SERCOM5_0 */
|
||||
.pfnSERCOM5_1_Handler = (void*) SERCOM5_1_Handler, /* 67 SERCOM5_1 */
|
||||
.pfnSERCOM5_2_Handler = (void*) SERCOM5_2_Handler, /* 68 SERCOM5_2 */
|
||||
.pfnSERCOM5_3_Handler = (void*) SERCOM5_3_Handler, /* 69 SERCOM5_3, SERCOM5_4, SERCOM5_5, SERCOM5_6 */
|
||||
#else
|
||||
.pvReserved66 = (void*) (0UL), /* 66 Reserved */
|
||||
.pvReserved67 = (void*) (0UL), /* 67 Reserved */
|
||||
.pvReserved68 = (void*) (0UL), /* 68 Reserved */
|
||||
.pvReserved69 = (void*) (0UL), /* 69 Reserved */
|
||||
#endif
|
||||
#ifdef ID_SERCOM6
|
||||
.pfnSERCOM6_0_Handler = (void*) SERCOM6_0_Handler, /* 70 SERCOM6_0 */
|
||||
.pfnSERCOM6_1_Handler = (void*) SERCOM6_1_Handler, /* 71 SERCOM6_1 */
|
||||
.pfnSERCOM6_2_Handler = (void*) SERCOM6_2_Handler, /* 72 SERCOM6_2 */
|
||||
.pfnSERCOM6_3_Handler = (void*) SERCOM6_3_Handler, /* 73 SERCOM6_3, SERCOM6_4, SERCOM6_5, SERCOM6_6 */
|
||||
#else
|
||||
.pvReserved70 = (void*) (0UL), /* 70 Reserved */
|
||||
.pvReserved71 = (void*) (0UL), /* 71 Reserved */
|
||||
.pvReserved72 = (void*) (0UL), /* 72 Reserved */
|
||||
.pvReserved73 = (void*) (0UL), /* 73 Reserved */
|
||||
#endif
|
||||
#ifdef ID_SERCOM7
|
||||
.pfnSERCOM7_0_Handler = (void*) SERCOM7_0_Handler, /* 74 SERCOM7_0 */
|
||||
.pfnSERCOM7_1_Handler = (void*) SERCOM7_1_Handler, /* 75 SERCOM7_1 */
|
||||
.pfnSERCOM7_2_Handler = (void*) SERCOM7_2_Handler, /* 76 SERCOM7_2 */
|
||||
.pfnSERCOM7_3_Handler = (void*) SERCOM7_3_Handler, /* 77 SERCOM7_3, SERCOM7_4, SERCOM7_5, SERCOM7_6 */
|
||||
#else
|
||||
.pvReserved74 = (void*) (0UL), /* 74 Reserved */
|
||||
.pvReserved75 = (void*) (0UL), /* 75 Reserved */
|
||||
.pvReserved76 = (void*) (0UL), /* 76 Reserved */
|
||||
.pvReserved77 = (void*) (0UL), /* 77 Reserved */
|
||||
#endif
|
||||
#ifdef ID_CAN0
|
||||
.pfnCAN0_Handler = (void*) CAN0_Handler, /* 78 Control Area Network 0 */
|
||||
#else
|
||||
.pvReserved78 = (void*) (0UL), /* 78 Reserved */
|
||||
#endif
|
||||
#ifdef ID_CAN1
|
||||
.pfnCAN1_Handler = (void*) CAN1_Handler, /* 79 Control Area Network 1 */
|
||||
#else
|
||||
.pvReserved79 = (void*) (0UL), /* 79 Reserved */
|
||||
#endif
|
||||
#ifdef ID_USB
|
||||
.pfnUSB_0_Handler = (void*) USB_0_Handler, /* 80 USB_EORSM_DNRSM, USB_EORST_RST, USB_LPMSUSP_DDISC, USB_LPM_DCONN, USB_MSOF, USB_RAMACER, USB_RXSTP_TXSTP_0, USB_RXSTP_TXSTP_1, USB_RXSTP_TXSTP_2, USB_RXSTP_TXSTP_3, USB_RXSTP_TXSTP_4, USB_RXSTP_TXSTP_5, USB_RXSTP_TXSTP_6, USB_RXSTP_TXSTP_7, USB_STALL0_STALL_0, USB_STALL0_STALL_1, USB_STALL0_STALL_2, USB_STALL0_STALL_3, USB_STALL0_STALL_4, USB_STALL0_STALL_5, USB_STALL0_STALL_6, USB_STALL0_STALL_7, USB_STALL1_0, USB_STALL1_1, USB_STALL1_2, USB_STALL1_3, USB_STALL1_4, USB_STALL1_5, USB_STALL1_6, USB_STALL1_7, USB_SUSPEND, USB_TRFAIL0_TRFAIL_0, USB_TRFAIL0_TRFAIL_1, USB_TRFAIL0_TRFAIL_2, USB_TRFAIL0_TRFAIL_3, USB_TRFAIL0_TRFAIL_4, USB_TRFAIL0_TRFAIL_5, USB_TRFAIL0_TRFAIL_6, USB_TRFAIL0_TRFAIL_7, USB_TRFAIL1_PERR_0, USB_TRFAIL1_PERR_1, USB_TRFAIL1_PERR_2, USB_TRFAIL1_PERR_3, USB_TRFAIL1_PERR_4, USB_TRFAIL1_PERR_5, USB_TRFAIL1_PERR_6, USB_TRFAIL1_PERR_7, USB_UPRSM, USB_WAKEUP */
|
||||
.pfnUSB_1_Handler = (void*) USB_1_Handler, /* 81 USB_SOF_HSOF */
|
||||
.pfnUSB_2_Handler = (void*) USB_2_Handler, /* 82 USB_TRCPT0_0, USB_TRCPT0_1, USB_TRCPT0_2, USB_TRCPT0_3, USB_TRCPT0_4, USB_TRCPT0_5, USB_TRCPT0_6, USB_TRCPT0_7 */
|
||||
.pfnUSB_3_Handler = (void*) USB_3_Handler, /* 83 USB_TRCPT1_0, USB_TRCPT1_1, USB_TRCPT1_2, USB_TRCPT1_3, USB_TRCPT1_4, USB_TRCPT1_5, USB_TRCPT1_6, USB_TRCPT1_7 */
|
||||
#else
|
||||
.pvReserved80 = (void*) (0UL), /* 80 Reserved */
|
||||
.pvReserved81 = (void*) (0UL), /* 81 Reserved */
|
||||
.pvReserved82 = (void*) (0UL), /* 82 Reserved */
|
||||
.pvReserved83 = (void*) (0UL), /* 83 Reserved */
|
||||
#endif
|
||||
#ifdef ID_GMAC
|
||||
.pfnGMAC_Handler = (void*) GMAC_Handler, /* 84 Ethernet MAC */
|
||||
#else
|
||||
.pvReserved84 = (void*) (0UL), /* 84 Reserved */
|
||||
#endif
|
||||
.pfnTCC0_0_Handler = (void*) TCC0_0_Handler, /* 85 TCC0_CNT_A, TCC0_DFS_A, TCC0_ERR_A, TCC0_FAULT0_A, TCC0_FAULT1_A, TCC0_FAULTA_A, TCC0_FAULTB_A, TCC0_OVF, TCC0_TRG, TCC0_UFS_A */
|
||||
.pfnTCC0_1_Handler = (void*) TCC0_1_Handler, /* 86 TCC0_MC_0 */
|
||||
.pfnTCC0_2_Handler = (void*) TCC0_2_Handler, /* 87 TCC0_MC_1 */
|
||||
.pfnTCC0_3_Handler = (void*) TCC0_3_Handler, /* 88 TCC0_MC_2 */
|
||||
.pfnTCC0_4_Handler = (void*) TCC0_4_Handler, /* 89 TCC0_MC_3 */
|
||||
.pfnTCC0_5_Handler = (void*) TCC0_5_Handler, /* 90 TCC0_MC_4 */
|
||||
.pfnTCC0_6_Handler = (void*) TCC0_6_Handler, /* 91 TCC0_MC_5 */
|
||||
.pfnTCC1_0_Handler = (void*) TCC1_0_Handler, /* 92 TCC1_CNT_A, TCC1_DFS_A, TCC1_ERR_A, TCC1_FAULT0_A, TCC1_FAULT1_A, TCC1_FAULTA_A, TCC1_FAULTB_A, TCC1_OVF, TCC1_TRG, TCC1_UFS_A */
|
||||
.pfnTCC1_1_Handler = (void*) TCC1_1_Handler, /* 93 TCC1_MC_0 */
|
||||
.pfnTCC1_2_Handler = (void*) TCC1_2_Handler, /* 94 TCC1_MC_1 */
|
||||
.pfnTCC1_3_Handler = (void*) TCC1_3_Handler, /* 95 TCC1_MC_2 */
|
||||
.pfnTCC1_4_Handler = (void*) TCC1_4_Handler, /* 96 TCC1_MC_3 */
|
||||
.pfnTCC2_0_Handler = (void*) TCC2_0_Handler, /* 97 TCC2_CNT_A, TCC2_DFS_A, TCC2_ERR_A, TCC2_FAULT0_A, TCC2_FAULT1_A, TCC2_FAULTA_A, TCC2_FAULTB_A, TCC2_OVF, TCC2_TRG, TCC2_UFS_A */
|
||||
.pfnTCC2_1_Handler = (void*) TCC2_1_Handler, /* 98 TCC2_MC_0 */
|
||||
.pfnTCC2_2_Handler = (void*) TCC2_2_Handler, /* 99 TCC2_MC_1 */
|
||||
.pfnTCC2_3_Handler = (void*) TCC2_3_Handler, /* 100 TCC2_MC_2 */
|
||||
#ifdef ID_TCC3
|
||||
.pfnTCC3_0_Handler = (void*) TCC3_0_Handler, /* 101 TCC3_CNT_A, TCC3_DFS_A, TCC3_ERR_A, TCC3_FAULT0_A, TCC3_FAULT1_A, TCC3_FAULTA_A, TCC3_FAULTB_A, TCC3_OVF, TCC3_TRG, TCC3_UFS_A */
|
||||
.pfnTCC3_1_Handler = (void*) TCC3_1_Handler, /* 102 TCC3_MC_0 */
|
||||
.pfnTCC3_2_Handler = (void*) TCC3_2_Handler, /* 103 TCC3_MC_1 */
|
||||
#else
|
||||
.pvReserved101 = (void*) (0UL), /* 101 Reserved */
|
||||
.pvReserved102 = (void*) (0UL), /* 102 Reserved */
|
||||
.pvReserved103 = (void*) (0UL), /* 103 Reserved */
|
||||
#endif
|
||||
#ifdef ID_TCC4
|
||||
.pfnTCC4_0_Handler = (void*) TCC4_0_Handler, /* 104 TCC4_CNT_A, TCC4_DFS_A, TCC4_ERR_A, TCC4_FAULT0_A, TCC4_FAULT1_A, TCC4_FAULTA_A, TCC4_FAULTB_A, TCC4_OVF, TCC4_TRG, TCC4_UFS_A */
|
||||
.pfnTCC4_1_Handler = (void*) TCC4_1_Handler, /* 105 TCC4_MC_0 */
|
||||
.pfnTCC4_2_Handler = (void*) TCC4_2_Handler, /* 106 TCC4_MC_1 */
|
||||
#else
|
||||
.pvReserved104 = (void*) (0UL), /* 104 Reserved */
|
||||
.pvReserved105 = (void*) (0UL), /* 105 Reserved */
|
||||
.pvReserved106 = (void*) (0UL), /* 106 Reserved */
|
||||
#endif
|
||||
.pfnTC0_Handler = (void*) TC0_Handler, /* 107 Basic Timer Counter 0 */
|
||||
.pfnTC1_Handler = (void*) TC1_Handler, /* 108 Basic Timer Counter 1 */
|
||||
.pfnTC2_Handler = (void*) TC2_Handler, /* 109 Basic Timer Counter 2 */
|
||||
.pfnTC3_Handler = (void*) TC3_Handler, /* 110 Basic Timer Counter 3 */
|
||||
#ifdef ID_TC4
|
||||
.pfnTC4_Handler = (void*) TC4_Handler, /* 111 Basic Timer Counter 4 */
|
||||
#else
|
||||
.pvReserved111 = (void*) (0UL), /* 111 Reserved */
|
||||
#endif
|
||||
#ifdef ID_TC5
|
||||
.pfnTC5_Handler = (void*) TC5_Handler, /* 112 Basic Timer Counter 5 */
|
||||
#else
|
||||
.pvReserved112 = (void*) (0UL), /* 112 Reserved */
|
||||
#endif
|
||||
#ifdef ID_TC6
|
||||
.pfnTC6_Handler = (void*) TC6_Handler, /* 113 Basic Timer Counter 6 */
|
||||
#else
|
||||
.pvReserved113 = (void*) (0UL), /* 113 Reserved */
|
||||
#endif
|
||||
#ifdef ID_TC7
|
||||
.pfnTC7_Handler = (void*) TC7_Handler, /* 114 Basic Timer Counter 7 */
|
||||
#else
|
||||
.pvReserved114 = (void*) (0UL), /* 114 Reserved */
|
||||
#endif
|
||||
.pfnPDEC_0_Handler = (void*) PDEC_0_Handler, /* 115 PDEC_DIR_A, PDEC_ERR_A, PDEC_OVF, PDEC_VLC_A */
|
||||
.pfnPDEC_1_Handler = (void*) PDEC_1_Handler, /* 116 PDEC_MC_0 */
|
||||
.pfnPDEC_2_Handler = (void*) PDEC_2_Handler, /* 117 PDEC_MC_1 */
|
||||
.pfnADC0_0_Handler = (void*) ADC0_0_Handler, /* 118 ADC0_OVERRUN, ADC0_WINMON */
|
||||
.pfnADC0_1_Handler = (void*) ADC0_1_Handler, /* 119 ADC0_RESRDY */
|
||||
.pfnADC1_0_Handler = (void*) ADC1_0_Handler, /* 120 ADC1_OVERRUN, ADC1_WINMON */
|
||||
.pfnADC1_1_Handler = (void*) ADC1_1_Handler, /* 121 ADC1_RESRDY */
|
||||
.pfnAC_Handler = (void*) AC_Handler, /* 122 Analog Comparators */
|
||||
.pfnDAC_0_Handler = (void*) DAC_0_Handler, /* 123 DAC_OVERRUN_A_0, DAC_OVERRUN_A_1, DAC_UNDERRUN_A_0, DAC_UNDERRUN_A_1 */
|
||||
.pfnDAC_1_Handler = (void*) DAC_1_Handler, /* 124 DAC_EMPTY_0 */
|
||||
.pfnDAC_2_Handler = (void*) DAC_2_Handler, /* 125 DAC_EMPTY_1 */
|
||||
.pfnDAC_3_Handler = (void*) DAC_3_Handler, /* 126 DAC_RESRDY_0 */
|
||||
.pfnDAC_4_Handler = (void*) DAC_4_Handler, /* 127 DAC_RESRDY_1 */
|
||||
#ifdef ID_I2S
|
||||
.pfnI2S_Handler = (void*) I2S_Handler, /* 128 Inter-IC Sound Interface */
|
||||
#else
|
||||
.pvReserved128 = (void*) (0UL), /* 128 Reserved */
|
||||
#endif
|
||||
.pfnPCC_Handler = (void*) PCC_Handler, /* 129 Parallel Capture Controller */
|
||||
.pfnAES_Handler = (void*) AES_Handler, /* 130 Advanced Encryption Standard */
|
||||
.pfnTRNG_Handler = (void*) TRNG_Handler, /* 131 True Random Generator */
|
||||
#ifdef ID_ICM
|
||||
.pfnICM_Handler = (void*) ICM_Handler, /* 132 Integrity Check Monitor */
|
||||
#else
|
||||
.pvReserved132 = (void*) (0UL), /* 132 Reserved */
|
||||
#endif
|
||||
#ifdef ID_PUKCC
|
||||
.pfnPUKCC_Handler = (void*) PUKCC_Handler, /* 133 PUblic-Key Cryptography Controller */
|
||||
#else
|
||||
.pvReserved133 = (void*) (0UL), /* 133 Reserved */
|
||||
#endif
|
||||
.pfnQSPI_Handler = (void*) QSPI_Handler, /* 134 Quad SPI interface */
|
||||
#ifdef ID_SDHC0
|
||||
.pfnSDHC0_Handler = (void*) SDHC0_Handler, /* 135 SD/MMC Host Controller 0 */
|
||||
#else
|
||||
.pvReserved135 = (void*) (0UL), /* 135 Reserved */
|
||||
#endif
|
||||
#ifdef ID_SDHC1
|
||||
.pfnSDHC1_Handler = (void*) SDHC1_Handler /* 136 SD/MMC Host Controller 1 */
|
||||
#else
|
||||
.pvReserved136 = (void*) (0UL) /* 136 Reserved */
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief This is the code that gets called on processor reset.
|
||||
* To initialize the device, and call the main() routine.
|
||||
*/
|
||||
void Reset_Handler(void)
|
||||
{
|
||||
#ifdef KEYBOARD_massdrop_ctrl
|
||||
/* WARNING: This is only for CTRL bootloader release "v2.18Jun 22 2018 17:28:08" for bootloader_jump support */
|
||||
if (*MAGIC_ADDR == BOOTLOADER_MAGIC) {
|
||||
/* At this point, the bootloader's memory is initialized properly, so undo the jump to here, then jump back */
|
||||
*MAGIC_ADDR = 0x00000000; /* Change value to prevent potential bootloader entrance loop */
|
||||
__set_MSP(0x20008818); /* MSP according to bootloader */
|
||||
SCB->VTOR = 0x00000000; /* Vector table back to bootloader's */
|
||||
asm("bx %0"::"r"(0x00001267)); /* Jump past bootloader RCAUSE check using THUMB */
|
||||
}
|
||||
#endif
|
||||
uint32_t *pSrc, *pDest;
|
||||
|
||||
/* Initialize the relocate segment */
|
||||
pSrc = &_etext;
|
||||
pDest = &_srelocate;
|
||||
|
||||
if (pSrc != pDest) {
|
||||
for (; pDest < &_erelocate;) {
|
||||
*pDest++ = *pSrc++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear the zero segment */
|
||||
for (pDest = &_szero; pDest < &_ezero;) {
|
||||
*pDest++ = 0;
|
||||
}
|
||||
|
||||
/* Set the vector table base address */
|
||||
pSrc = (uint32_t *) & _sfixed;
|
||||
SCB->VTOR = ((uint32_t) pSrc & SCB_VTOR_TBLOFF_Msk);
|
||||
|
||||
#if __FPU_USED
|
||||
/* Enable FPU */
|
||||
SCB->CPACR |= (0xFu << 20);
|
||||
__DSB();
|
||||
__ISB();
|
||||
#endif
|
||||
|
||||
/* Initialize the C library */
|
||||
__libc_init_array();
|
||||
|
||||
/* Branch to main function */
|
||||
main();
|
||||
|
||||
/* Infinite loop */
|
||||
while (1);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Default interrupt handler for unused IRQs.
|
||||
*/
|
||||
void Dummy_Handler(void)
|
||||
{
|
||||
while (1) {
|
||||
}
|
||||
}
|
1177
tmk_core/protocol/arm_atsam/usb/compiler.h
Normal file
1177
tmk_core/protocol/arm_atsam/usb/compiler.h
Normal file
File diff suppressed because it is too large
Load diff
168
tmk_core/protocol/arm_atsam/usb/conf_usb.h
Normal file
168
tmk_core/protocol/arm_atsam/usb/conf_usb.h
Normal file
|
@ -0,0 +1,168 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief USB configuration file
|
||||
*
|
||||
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
|
||||
#ifndef _CONF_USB_H_
|
||||
#define _CONF_USB_H_
|
||||
|
||||
#include "compiler.h"
|
||||
#include "udi_device_conf.h"
|
||||
|
||||
#define UDI_CDC_DEFAULT_RATE 115200
|
||||
#define UDI_CDC_DEFAULT_STOPBITS CDC_STOP_BITS_1
|
||||
#define UDI_CDC_DEFAULT_PARITY CDC_PAR_NONE
|
||||
#define UDI_CDC_DEFAULT_DATABITS 8
|
||||
|
||||
//! Device definition (mandatory)
|
||||
#define USB_DEVICE_VENDOR_ID VENDOR_ID
|
||||
#define USB_DEVICE_PRODUCT_ID PRODUCT_ID
|
||||
#define USB_DEVICE_VERSION DEVICE_VER
|
||||
#define USB_DEVICE_POWER 500 // Consumption on Vbus line (mA)
|
||||
#define USB_DEVICE_ATTR (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_BUS_POWERED)
|
||||
// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_BUS_POWERED)
|
||||
// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_SELF_POWERED)
|
||||
// (USB_CONFIG_ATTR_SELF_POWERED)
|
||||
// (USB_CONFIG_ATTR_BUS_POWERED)
|
||||
|
||||
//! USB Device string definitions (Optional)
|
||||
#define USB_DEVICE_MANUFACTURE_NAME MANUFACTURER
|
||||
#define USB_DEVICE_PRODUCT_NAME PRODUCT
|
||||
#define USB_DEVICE_SERIAL_NAME SERIAL_NUM
|
||||
|
||||
//Comment out USB_DEVICE_SERIAL_USE_BOOTLOADER_SERIAL to prevent ROM lookup of factory programmed serial number
|
||||
#define USB_DEVICE_SERIAL_USE_BOOTLOADER_SERIAL
|
||||
|
||||
/**
|
||||
* Device speeds support
|
||||
* @{
|
||||
*/
|
||||
//! To define a Low speed device
|
||||
//#define USB_DEVICE_LOW_SPEED
|
||||
|
||||
//! To authorize the High speed
|
||||
#if (UC3A3||UC3A4)
|
||||
//#define USB_DEVICE_HS_SUPPORT
|
||||
#elif (SAM3XA||SAM3U)
|
||||
//#define USB_DEVICE_HS_SUPPORT
|
||||
#endif
|
||||
//@}
|
||||
|
||||
/**
|
||||
* USB Device Callbacks definitions (Optional)
|
||||
* @{
|
||||
*/
|
||||
#define UDC_VBUS_EVENT(b_vbus_high)
|
||||
#define UDC_SOF_EVENT() main_sof_action()
|
||||
#define UDC_SUSPEND_EVENT() main_suspend_action()
|
||||
#define UDC_RESUME_EVENT() main_resume_action()
|
||||
//! Mandatory when USB_DEVICE_ATTR authorizes remote wakeup feature
|
||||
#define UDC_REMOTEWAKEUP_ENABLE() main_remotewakeup_enable()
|
||||
#define UDC_REMOTEWAKEUP_DISABLE() main_remotewakeup_disable()
|
||||
//! When a extra string descriptor must be supported
|
||||
//! other than manufacturer, product and serial string
|
||||
// #define UDC_GET_EXTRA_STRING()
|
||||
//@}
|
||||
|
||||
//@}
|
||||
|
||||
|
||||
/**
|
||||
* USB Interface Configuration
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* Configuration of HID Keyboard interface
|
||||
* @{
|
||||
*/
|
||||
//! Interface callback definition
|
||||
#ifdef KBD
|
||||
#define UDI_HID_KBD_ENABLE_EXT() main_kbd_enable()
|
||||
#define UDI_HID_KBD_DISABLE_EXT() main_kbd_disable()
|
||||
//#define UDI_HID_KBD_CHANGE_LED(value) ui_kbd_led(value)
|
||||
#endif
|
||||
|
||||
#ifdef NKRO
|
||||
#define UDI_HID_NKRO_ENABLE_EXT() main_nkro_enable()
|
||||
#define UDI_HID_NKRO_DISABLE_EXT() main_nkro_disable()
|
||||
//#define UDI_HID_NKRO_CHANGE_LED(value) ui_kbd_led(value)
|
||||
#endif
|
||||
|
||||
#ifdef EXK
|
||||
#define UDI_HID_EXK_ENABLE_EXT() main_exk_enable()
|
||||
#define UDI_HID_EXK_DISABLE_EXT() main_exk_disable()
|
||||
#endif
|
||||
|
||||
#ifdef CON
|
||||
#define UDI_HID_CON_ENABLE_EXT() main_con_enable()
|
||||
#define UDI_HID_CON_DISABLE_EXT() main_con_disable()
|
||||
#endif
|
||||
|
||||
#ifdef MOU
|
||||
#define UDI_HID_MOU_ENABLE_EXT() main_mou_enable()
|
||||
#define UDI_HID_MOU_DISABLE_EXT() main_mou_disable()
|
||||
#endif
|
||||
|
||||
#ifdef RAW
|
||||
#define UDI_HID_RAW_ENABLE_EXT() main_raw_enable()
|
||||
#define UDI_HID_RAW_DISABLE_EXT() main_raw_disable()
|
||||
#endif
|
||||
|
||||
|
||||
//@}
|
||||
//@}
|
||||
|
||||
|
||||
/**
|
||||
* USB Device Driver Configuration
|
||||
* @{
|
||||
*/
|
||||
//@}
|
||||
|
||||
//! The includes of classes and other headers must be done at the end of this file to avoid compile error
|
||||
#include "udi_hid_kbd_conf.h"
|
||||
#include "usb_main.h"
|
||||
#include "ui.h"
|
||||
|
||||
#endif // _CONF_USB_H_
|
132
tmk_core/protocol/arm_atsam/usb/main_usb.c
Normal file
132
tmk_core/protocol/arm_atsam/usb/main_usb.c
Normal file
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
Copyright 2018 Massdrop Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "samd51j18a.h"
|
||||
#include "conf_usb.h"
|
||||
#include "udd.h"
|
||||
|
||||
uint8_t keyboard_protocol = 1;
|
||||
|
||||
void main_suspend_action(void)
|
||||
{
|
||||
ui_powerdown();
|
||||
}
|
||||
|
||||
void main_resume_action(void)
|
||||
{
|
||||
ui_wakeup();
|
||||
}
|
||||
|
||||
void main_sof_action(void)
|
||||
{
|
||||
ui_process(udd_get_frame_number());
|
||||
}
|
||||
|
||||
void main_remotewakeup_enable(void)
|
||||
{
|
||||
ui_wakeup_enable();
|
||||
}
|
||||
|
||||
void main_remotewakeup_disable(void)
|
||||
{
|
||||
ui_wakeup_disable();
|
||||
}
|
||||
|
||||
#ifdef KBD
|
||||
volatile bool main_b_kbd_enable = false;
|
||||
bool main_kbd_enable(void)
|
||||
{
|
||||
main_b_kbd_enable = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void main_kbd_disable(void)
|
||||
{
|
||||
main_b_kbd_enable = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef NKRO
|
||||
volatile bool main_b_nkro_enable = false;
|
||||
bool main_nkro_enable(void)
|
||||
{
|
||||
main_b_nkro_enable = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void main_nkro_disable(void)
|
||||
{
|
||||
main_b_nkro_enable = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef EXK
|
||||
volatile bool main_b_exk_enable = false;
|
||||
bool main_exk_enable(void)
|
||||
{
|
||||
main_b_exk_enable = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void main_exk_disable(void)
|
||||
{
|
||||
main_b_exk_enable = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CON
|
||||
volatile bool main_b_con_enable = false;
|
||||
bool main_con_enable(void)
|
||||
{
|
||||
main_b_con_enable = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void main_con_disable(void)
|
||||
{
|
||||
main_b_con_enable = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MOU
|
||||
volatile bool main_b_mou_enable = false;
|
||||
bool main_mou_enable(void)
|
||||
{
|
||||
main_b_mou_enable = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void main_mou_disable(void)
|
||||
{
|
||||
main_b_mou_enable = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef RAW
|
||||
volatile bool main_b_raw_enable = false;
|
||||
bool main_raw_enable(void)
|
||||
{
|
||||
main_b_raw_enable = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void main_raw_disable(void)
|
||||
{
|
||||
main_b_raw_enable = false;
|
||||
}
|
||||
#endif
|
||||
|
158
tmk_core/protocol/arm_atsam/usb/status_codes.h
Normal file
158
tmk_core/protocol/arm_atsam/usb/status_codes.h
Normal file
|
@ -0,0 +1,158 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Status code definitions.
|
||||
*
|
||||
* This file defines various status codes returned by functions,
|
||||
* indicating success or failure as well as what kind of failure.
|
||||
*
|
||||
* Copyright (C) 2012-2015 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
|
||||
#ifndef STATUS_CODES_H_INCLUDED
|
||||
#define STATUS_CODES_H_INCLUDED
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* \defgroup group_sam0_utils_status_codes Status Codes
|
||||
*
|
||||
* \ingroup group_sam0_utils
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Mask to retrieve the error category of a status code. */
|
||||
#define STATUS_CATEGORY_MASK 0xF0
|
||||
|
||||
/** Mask to retrieve the error code within the category of a status code. */
|
||||
#define STATUS_ERROR_MASK 0x0F
|
||||
|
||||
/** Status code error categories. */
|
||||
enum status_categories {
|
||||
STATUS_CATEGORY_OK = 0x00,
|
||||
STATUS_CATEGORY_COMMON = 0x10,
|
||||
STATUS_CATEGORY_ANALOG = 0x30,
|
||||
STATUS_CATEGORY_COM = 0x40,
|
||||
STATUS_CATEGORY_IO = 0x50,
|
||||
};
|
||||
|
||||
/**
|
||||
* Status code that may be returned by shell commands and protocol
|
||||
* implementations.
|
||||
*
|
||||
* \note Any change to these status codes and the corresponding
|
||||
* message strings is strictly forbidden. New codes can be added,
|
||||
* however, but make sure that any message string tables are updated
|
||||
* at the same time.
|
||||
*/
|
||||
enum status_code {
|
||||
STATUS_OK = STATUS_CATEGORY_OK | 0x00,
|
||||
STATUS_VALID_DATA = STATUS_CATEGORY_OK | 0x01,
|
||||
STATUS_NO_CHANGE = STATUS_CATEGORY_OK | 0x02,
|
||||
STATUS_ABORTED = STATUS_CATEGORY_OK | 0x04,
|
||||
STATUS_BUSY = STATUS_CATEGORY_OK | 0x05,
|
||||
STATUS_SUSPEND = STATUS_CATEGORY_OK | 0x06,
|
||||
|
||||
STATUS_ERR_IO = STATUS_CATEGORY_COMMON | 0x00,
|
||||
STATUS_ERR_REQ_FLUSHED = STATUS_CATEGORY_COMMON | 0x01,
|
||||
STATUS_ERR_TIMEOUT = STATUS_CATEGORY_COMMON | 0x02,
|
||||
STATUS_ERR_BAD_DATA = STATUS_CATEGORY_COMMON | 0x03,
|
||||
STATUS_ERR_NOT_FOUND = STATUS_CATEGORY_COMMON | 0x04,
|
||||
STATUS_ERR_UNSUPPORTED_DEV = STATUS_CATEGORY_COMMON | 0x05,
|
||||
STATUS_ERR_NO_MEMORY = STATUS_CATEGORY_COMMON | 0x06,
|
||||
STATUS_ERR_INVALID_ARG = STATUS_CATEGORY_COMMON | 0x07,
|
||||
STATUS_ERR_BAD_ADDRESS = STATUS_CATEGORY_COMMON | 0x08,
|
||||
STATUS_ERR_BAD_FORMAT = STATUS_CATEGORY_COMMON | 0x0A,
|
||||
STATUS_ERR_BAD_FRQ = STATUS_CATEGORY_COMMON | 0x0B,
|
||||
STATUS_ERR_DENIED = STATUS_CATEGORY_COMMON | 0x0c,
|
||||
STATUS_ERR_ALREADY_INITIALIZED = STATUS_CATEGORY_COMMON | 0x0d,
|
||||
STATUS_ERR_OVERFLOW = STATUS_CATEGORY_COMMON | 0x0e,
|
||||
STATUS_ERR_NOT_INITIALIZED = STATUS_CATEGORY_COMMON | 0x0f,
|
||||
|
||||
STATUS_ERR_SAMPLERATE_UNAVAILABLE = STATUS_CATEGORY_ANALOG | 0x00,
|
||||
STATUS_ERR_RESOLUTION_UNAVAILABLE = STATUS_CATEGORY_ANALOG | 0x01,
|
||||
|
||||
STATUS_ERR_BAUDRATE_UNAVAILABLE = STATUS_CATEGORY_COM | 0x00,
|
||||
STATUS_ERR_PACKET_COLLISION = STATUS_CATEGORY_COM | 0x01,
|
||||
STATUS_ERR_PROTOCOL = STATUS_CATEGORY_COM | 0x02,
|
||||
|
||||
STATUS_ERR_PIN_MUX_INVALID = STATUS_CATEGORY_IO | 0x00,
|
||||
};
|
||||
typedef enum status_code status_code_genare_t;
|
||||
|
||||
/**
|
||||
Status codes used by MAC stack.
|
||||
*/
|
||||
enum status_code_wireless {
|
||||
//STATUS_OK = 0, //!< Success
|
||||
ERR_IO_ERROR = -1, //!< I/O error
|
||||
ERR_FLUSHED = -2, //!< Request flushed from queue
|
||||
ERR_TIMEOUT = -3, //!< Operation timed out
|
||||
ERR_BAD_DATA = -4, //!< Data integrity check failed
|
||||
ERR_PROTOCOL = -5, //!< Protocol error
|
||||
ERR_UNSUPPORTED_DEV = -6, //!< Unsupported device
|
||||
ERR_NO_MEMORY = -7, //!< Insufficient memory
|
||||
ERR_INVALID_ARG = -8, //!< Invalid argument
|
||||
ERR_BAD_ADDRESS = -9, //!< Bad address
|
||||
ERR_BUSY = -10, //!< Resource is busy
|
||||
ERR_BAD_FORMAT = -11, //!< Data format not recognized
|
||||
ERR_NO_TIMER = -12, //!< No timer available
|
||||
ERR_TIMER_ALREADY_RUNNING = -13, //!< Timer already running
|
||||
ERR_TIMER_NOT_RUNNING = -14, //!< Timer not running
|
||||
|
||||
/**
|
||||
* \brief Operation in progress
|
||||
*
|
||||
* This status code is for driver-internal use when an operation
|
||||
* is currently being performed.
|
||||
*
|
||||
* \note Drivers should never return this status code to any
|
||||
* callers. It is strictly for internal use.
|
||||
*/
|
||||
OPERATION_IN_PROGRESS = -128,
|
||||
};
|
||||
|
||||
typedef enum status_code_wireless status_code_t;
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* STATUS_CODES_H_INCLUDED */
|
1164
tmk_core/protocol/arm_atsam/usb/udc.c
Normal file
1164
tmk_core/protocol/arm_atsam/usb/udc.c
Normal file
File diff suppressed because it is too large
Load diff
260
tmk_core/protocol/arm_atsam/usb/udc.h
Normal file
260
tmk_core/protocol/arm_atsam/usb/udc.h
Normal file
|
@ -0,0 +1,260 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Interface of the USB Device Controller (UDC)
|
||||
*
|
||||
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
|
||||
#ifndef _UDC_H_
|
||||
#define _UDC_H_
|
||||
|
||||
#include "conf_usb.h"
|
||||
#include "usb_protocol.h"
|
||||
#include "udc_desc.h"
|
||||
#include "udd.h"
|
||||
|
||||
#if USB_DEVICE_VENDOR_ID == 0
|
||||
# error USB_DEVICE_VENDOR_ID cannot be equal to 0
|
||||
#endif
|
||||
|
||||
#if USB_DEVICE_PRODUCT_ID == 0
|
||||
# error USB_DEVICE_PRODUCT_ID cannot be equal to 0
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \ingroup usb_device_group
|
||||
* \defgroup udc_group USB Device Controller (UDC)
|
||||
*
|
||||
* The UDC provides a high-level abstraction of the usb device.
|
||||
* You can use these functions to control the main device state
|
||||
* (start/attach/wakeup).
|
||||
*
|
||||
* \section USB_DEVICE_CONF USB Device Custom configuration
|
||||
* The following USB Device configuration must be included in the conf_usb.h
|
||||
* file of the application.
|
||||
*
|
||||
* USB_DEVICE_VENDOR_ID (Word)<br>
|
||||
* Vendor ID provided by USB org (ATMEL 0x03EB).
|
||||
*
|
||||
* USB_DEVICE_PRODUCT_ID (Word)<br>
|
||||
* Product ID (Referenced in usb_atmel.h).
|
||||
*
|
||||
* USB_DEVICE_MAJOR_VERSION (Byte)<br>
|
||||
* Major version of the device
|
||||
*
|
||||
* USB_DEVICE_MINOR_VERSION (Byte)<br>
|
||||
* Minor version of the device
|
||||
*
|
||||
* USB_DEVICE_MANUFACTURE_NAME (string)<br>
|
||||
* ASCII name for the manufacture
|
||||
*
|
||||
* USB_DEVICE_PRODUCT_NAME (string)<br>
|
||||
* ASCII name for the product
|
||||
*
|
||||
* USB_DEVICE_SERIAL_NAME (string)<br>
|
||||
* ASCII name to enable and set a serial number
|
||||
*
|
||||
* USB_DEVICE_POWER (Numeric)<br>
|
||||
* (unit mA) Maximum device power
|
||||
*
|
||||
* USB_DEVICE_ATTR (Byte)<br>
|
||||
* USB attributes available:
|
||||
* - USB_CONFIG_ATTR_SELF_POWERED
|
||||
* - USB_CONFIG_ATTR_REMOTE_WAKEUP
|
||||
* Note: if remote wake enabled then defines remotewakeup callbacks,
|
||||
* see Table 5-2. External API from UDC - Callback
|
||||
*
|
||||
* USB_DEVICE_LOW_SPEED (Only defined)<br>
|
||||
* Force the USB Device to run in low speed
|
||||
*
|
||||
* USB_DEVICE_HS_SUPPORT (Only defined)<br>
|
||||
* Authorize the USB Device to run in high speed
|
||||
*
|
||||
* USB_DEVICE_MAX_EP (Byte)<br>
|
||||
* Define the maximum endpoint number used by the USB Device.<br>
|
||||
* This one is already defined in UDI default configuration.
|
||||
* Ex:
|
||||
* - When endpoint control 0x00, endpoint 0x01 and
|
||||
* endpoint 0x82 is used then USB_DEVICE_MAX_EP=2
|
||||
* - When only endpoint control 0x00 is used then USB_DEVICE_MAX_EP=0
|
||||
* - When endpoint 0x01 and endpoint 0x81 is used then USB_DEVICE_MAX_EP=1<br>
|
||||
* (configuration not possible on USBB interface)
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Authorizes the VBUS event
|
||||
*
|
||||
* \return true, if the VBUS monitoring is possible.
|
||||
*
|
||||
* \section udc_vbus_monitoring VBus monitoring used cases
|
||||
*
|
||||
* The VBus monitoring is used only for USB SELF Power application.
|
||||
*
|
||||
* - By default the USB device is automatically attached when Vbus is high
|
||||
* or when USB is start for devices without internal Vbus monitoring.
|
||||
* conf_usb.h file does not contains define USB_DEVICE_ATTACH_AUTO_DISABLE.
|
||||
* \code //#define USB_DEVICE_ATTACH_AUTO_DISABLE \endcode
|
||||
*
|
||||
* - Add custom VBUS monitoring. conf_usb.h file contains define
|
||||
* USB_DEVICE_ATTACH_AUTO_DISABLE:
|
||||
* \code #define USB_DEVICE_ATTACH_AUTO_DISABLE \endcode
|
||||
* User C file contains:
|
||||
* \code
|
||||
// Authorize VBUS monitoring
|
||||
if (!udc_include_vbus_monitoring()) {
|
||||
// Implement custom VBUS monitoring via GPIO or other
|
||||
}
|
||||
Event_VBUS_present() // VBUS interrupt or GPIO interrupt or other
|
||||
{
|
||||
// Attach USB Device
|
||||
udc_attach();
|
||||
}
|
||||
\endcode
|
||||
*
|
||||
* - Case of battery charging. conf_usb.h file contains define
|
||||
* USB_DEVICE_ATTACH_AUTO_DISABLE:
|
||||
* \code #define USB_DEVICE_ATTACH_AUTO_DISABLE \endcode
|
||||
* User C file contains:
|
||||
* \code
|
||||
Event VBUS present() // VBUS interrupt or GPIO interrupt or ..
|
||||
{
|
||||
// Authorize battery charging, but wait key press to start USB.
|
||||
}
|
||||
Event Key press()
|
||||
{
|
||||
// Stop batteries charging
|
||||
// Start USB
|
||||
udc_attach();
|
||||
}
|
||||
\endcode
|
||||
*/
|
||||
static inline bool udc_include_vbus_monitoring(void)
|
||||
{
|
||||
return udd_include_vbus_monitoring();
|
||||
}
|
||||
|
||||
/*! \brief Start the USB Device stack
|
||||
*/
|
||||
void udc_start(void);
|
||||
|
||||
/*! \brief Stop the USB Device stack
|
||||
*/
|
||||
void udc_stop(void);
|
||||
|
||||
/**
|
||||
* \brief Attach device to the bus when possible
|
||||
*
|
||||
* \warning If a VBus control is included in driver,
|
||||
* then it will attach device when an acceptable Vbus
|
||||
* level from the host is detected.
|
||||
*/
|
||||
static inline void udc_attach(void)
|
||||
{
|
||||
udd_attach();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Detaches the device from the bus
|
||||
*
|
||||
* The driver must remove pull-up on USB line D- or D+.
|
||||
*/
|
||||
static inline void udc_detach(void)
|
||||
{
|
||||
udd_detach();
|
||||
}
|
||||
|
||||
/*! \brief The USB driver sends a resume signal called \e "Upstream Resume"
|
||||
* This is authorized only when the remote wakeup feature is enabled by host.
|
||||
*/
|
||||
inline void udc_remotewakeup(void)
|
||||
{
|
||||
udd_send_remotewakeup();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns a pointer on the current interface descriptor
|
||||
*
|
||||
* \return pointer on the current interface descriptor.
|
||||
*/
|
||||
usb_iface_desc_t UDC_DESC_STORAGE *udc_get_interface_desc(void);
|
||||
|
||||
//@}
|
||||
|
||||
/**
|
||||
* \ingroup usb_group
|
||||
* \defgroup usb_device_group USB Stack Device
|
||||
*
|
||||
* This module includes USB Stack Device implementation.
|
||||
* The stack is divided in three parts:
|
||||
* - USB Device Controller (UDC) provides USB chapter 9 compliance
|
||||
* - USB Device Interface (UDI) provides USB Class compliance
|
||||
* - USB Device Driver (UDD) provides USB Driver for each Atmel MCU
|
||||
|
||||
* Many USB Device applications can be implemented on Atmel MCU.
|
||||
* Atmel provides many application notes for different applications:
|
||||
* - AVR4900, provides general information about Device Stack
|
||||
* - AVR4901, explains how to create a new class
|
||||
* - AVR4902, explains how to create a composite device
|
||||
* - AVR49xx, all device classes provided in ASF have an application note
|
||||
*
|
||||
* A basic USB knowledge is required to understand the USB Device
|
||||
* Class application notes (HID,MS,CDC,PHDC,...).
|
||||
* Then, to create an USB device with
|
||||
* only one class provided by ASF, refer directly to the application note
|
||||
* corresponding to this USB class. The USB Device application note for
|
||||
* New Class and Composite is dedicated to advanced USB users.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
//! @}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _UDC_H_
|
135
tmk_core/protocol/arm_atsam/usb/udc_desc.h
Normal file
135
tmk_core/protocol/arm_atsam/usb/udc_desc.h
Normal file
|
@ -0,0 +1,135 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Common API for USB Device Interface
|
||||
*
|
||||
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
|
||||
#ifndef _UDC_DESC_H_
|
||||
#define _UDC_DESC_H_
|
||||
|
||||
#include "conf_usb.h"
|
||||
#include "usb_protocol.h"
|
||||
#include "udi.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \ingroup udc_group
|
||||
* \defgroup udc_desc_group USB Device Descriptor
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Defines the memory's location of USB descriptors
|
||||
*
|
||||
* By default the Descriptor is stored in RAM
|
||||
* (UDC_DESC_STORAGE is defined empty).
|
||||
*
|
||||
* If you have need to free RAM space,
|
||||
* it is possible to put descriptor in flash in following case:
|
||||
* - USB driver authorize flash transfer (USBB on UC3 and USB on Mega)
|
||||
* - USB Device is not high speed (UDC no need to change USB descriptors)
|
||||
*
|
||||
* For UC3 application used "const".
|
||||
*
|
||||
* For Mega application used "code".
|
||||
*/
|
||||
#define UDC_DESC_STORAGE
|
||||
// Descriptor storage in internal RAM
|
||||
#if (defined UDC_DATA_USE_HRAM_SUPPORT)
|
||||
#if defined(__GNUC__)
|
||||
#define UDC_DATA(x) COMPILER_WORD_ALIGNED __attribute__((__section__(".data_hram0")))
|
||||
#define UDC_BSS(x) COMPILER_ALIGNED(x) __attribute__((__section__(".bss_hram0")))
|
||||
#elif defined(__ICCAVR32__)
|
||||
#define UDC_DATA(x) COMPILER_ALIGNED(x) __data32
|
||||
#define UDC_BSS(x) COMPILER_ALIGNED(x) __data32
|
||||
#endif
|
||||
#else
|
||||
#define UDC_DATA(x) COMPILER_ALIGNED(x)
|
||||
#define UDC_BSS(x) COMPILER_ALIGNED(x)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* \brief Configuration descriptor and UDI link for one USB speed
|
||||
*/
|
||||
typedef struct {
|
||||
//! USB configuration descriptor
|
||||
usb_conf_desc_t UDC_DESC_STORAGE *desc;
|
||||
//! Array of UDI API pointer
|
||||
udi_api_t UDC_DESC_STORAGE *UDC_DESC_STORAGE * udi_apis;
|
||||
} udc_config_speed_t;
|
||||
|
||||
|
||||
/**
|
||||
* \brief All information about the USB Device
|
||||
*/
|
||||
typedef struct {
|
||||
//! USB device descriptor for low or full speed
|
||||
usb_dev_desc_t UDC_DESC_STORAGE *confdev_lsfs;
|
||||
//! USB configuration descriptor and UDI API pointers for low or full speed
|
||||
udc_config_speed_t UDC_DESC_STORAGE *conf_lsfs;
|
||||
#ifdef USB_DEVICE_HS_SUPPORT
|
||||
//! USB device descriptor for high speed
|
||||
usb_dev_desc_t UDC_DESC_STORAGE *confdev_hs;
|
||||
//! USB device qualifier, only use in high speed mode
|
||||
usb_dev_qual_desc_t UDC_DESC_STORAGE *qualifier;
|
||||
//! USB configuration descriptor and UDI API pointers for high speed
|
||||
udc_config_speed_t UDC_DESC_STORAGE *conf_hs;
|
||||
#endif
|
||||
usb_dev_bos_desc_t UDC_DESC_STORAGE *conf_bos;
|
||||
} udc_config_t;
|
||||
|
||||
//! Global variables of USB Device Descriptor and UDI links
|
||||
extern UDC_DESC_STORAGE udc_config_t udc_config;
|
||||
|
||||
//@}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // _UDC_DESC_H_
|
396
tmk_core/protocol/arm_atsam/usb/udd.h
Normal file
396
tmk_core/protocol/arm_atsam/usb/udd.h
Normal file
|
@ -0,0 +1,396 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Common API for USB Device Drivers (UDD)
|
||||
*
|
||||
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
|
||||
#ifndef _UDD_H_
|
||||
#define _UDD_H_
|
||||
|
||||
#include "usb_protocol.h"
|
||||
#include "udc_desc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \ingroup usb_device_group
|
||||
* \defgroup udd_group USB Device Driver (UDD)
|
||||
*
|
||||
* The UDD driver provides a low-level abstraction of the device
|
||||
* controller hardware. Most events coming from the hardware such as
|
||||
* interrupts, which may cause the UDD to call into the UDC and UDI.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
//! \brief Endpoint identifier
|
||||
typedef uint8_t udd_ep_id_t;
|
||||
|
||||
//! \brief Endpoint transfer status
|
||||
//! Returned in parameters of callback register via udd_ep_run routine.
|
||||
typedef enum {
|
||||
UDD_EP_TRANSFER_OK = 0,
|
||||
UDD_EP_TRANSFER_ABORT = 1,
|
||||
} udd_ep_status_t;
|
||||
|
||||
/**
|
||||
* \brief Global variable to give and record information of the setup request management
|
||||
*
|
||||
* This global variable allows to decode and response a setup request.
|
||||
* It can be updated by udc_process_setup() from UDC or *setup() from UDIs.
|
||||
*/
|
||||
typedef struct {
|
||||
//! Data received in USB SETUP packet
|
||||
//! Note: The swap of "req.wValues" from uin16_t to le16_t is done by UDD.
|
||||
usb_setup_req_t req;
|
||||
|
||||
//! Point to buffer to send or fill with data following SETUP packet
|
||||
//! This buffer must be word align for DATA IN phase (use prefix COMPILER_WORD_ALIGNED for buffer)
|
||||
uint8_t *payload;
|
||||
|
||||
//! Size of buffer to send or fill, and content the number of byte transfered
|
||||
uint16_t payload_size;
|
||||
|
||||
//! Callback called after reception of ZLP from setup request
|
||||
void (*callback) (void);
|
||||
|
||||
//! Callback called when the buffer given (.payload) is full or empty.
|
||||
//! This one return false to abort data transfer, or true with a new buffer in .payload.
|
||||
bool(*over_under_run) (void);
|
||||
} udd_ctrl_request_t;
|
||||
extern udd_ctrl_request_t udd_g_ctrlreq;
|
||||
|
||||
//! Return true if the setup request \a udd_g_ctrlreq indicates IN data transfer
|
||||
#define Udd_setup_is_in() \
|
||||
(USB_REQ_DIR_IN == (udd_g_ctrlreq.req.bmRequestType & USB_REQ_DIR_MASK))
|
||||
|
||||
//! Return true if the setup request \a udd_g_ctrlreq indicates OUT data transfer
|
||||
#define Udd_setup_is_out() \
|
||||
(USB_REQ_DIR_OUT == (udd_g_ctrlreq.req.bmRequestType & USB_REQ_DIR_MASK))
|
||||
|
||||
//! Return the type of the SETUP request \a udd_g_ctrlreq. \see usb_reqtype.
|
||||
#define Udd_setup_type() \
|
||||
(udd_g_ctrlreq.req.bmRequestType & USB_REQ_TYPE_MASK)
|
||||
|
||||
//! Return the recipient of the SETUP request \a udd_g_ctrlreq. \see usb_recipient
|
||||
#define Udd_setup_recipient() \
|
||||
(udd_g_ctrlreq.req.bmRequestType & USB_REQ_RECIP_MASK)
|
||||
|
||||
/**
|
||||
* \brief End of halt callback function type.
|
||||
* Registered by routine udd_ep_wait_stall_clear()
|
||||
* Callback called when endpoint stall is cleared.
|
||||
*/
|
||||
typedef void (*udd_callback_halt_cleared_t) (void);
|
||||
|
||||
/**
|
||||
* \brief End of transfer callback function type.
|
||||
* Registered by routine udd_ep_run()
|
||||
* Callback called by USB interrupt after data transfer or abort (reset,...).
|
||||
*
|
||||
* \param status UDD_EP_TRANSFER_OK, if transfer is complete
|
||||
* \param status UDD_EP_TRANSFER_ABORT, if transfer is aborted
|
||||
* \param n number of data transfered
|
||||
*/
|
||||
typedef void (*udd_callback_trans_t) (udd_ep_status_t status,
|
||||
iram_size_t nb_transfered, udd_ep_id_t ep);
|
||||
|
||||
/**
|
||||
* \brief Authorizes the VBUS event
|
||||
*
|
||||
* \return true, if the VBUS monitoring is possible.
|
||||
*/
|
||||
bool udd_include_vbus_monitoring(void);
|
||||
|
||||
/**
|
||||
* \brief Enables the USB Device mode
|
||||
*/
|
||||
void udd_enable(void);
|
||||
|
||||
/**
|
||||
* \brief Disables the USB Device mode
|
||||
*/
|
||||
void udd_disable(void);
|
||||
|
||||
/**
|
||||
* \brief Attach device to the bus when possible
|
||||
*
|
||||
* \warning If a VBus control is included in driver,
|
||||
* then it will attach device when an acceptable Vbus
|
||||
* level from the host is detected.
|
||||
*/
|
||||
void udd_attach(void);
|
||||
|
||||
/**
|
||||
* \brief Detaches the device from the bus
|
||||
*
|
||||
* The driver must remove pull-up on USB line D- or D+.
|
||||
*/
|
||||
void udd_detach(void);
|
||||
|
||||
/**
|
||||
* \brief Test whether the USB Device Controller is running at high
|
||||
* speed or not.
|
||||
*
|
||||
* \return \c true if the Device is running at high speed mode, otherwise \c false.
|
||||
*/
|
||||
bool udd_is_high_speed(void);
|
||||
|
||||
/**
|
||||
* \brief Changes the USB address of device
|
||||
*
|
||||
* \param address New USB address
|
||||
*/
|
||||
void udd_set_address(uint8_t address);
|
||||
|
||||
/**
|
||||
* \brief Returns the USB address of device
|
||||
*
|
||||
* \return USB address
|
||||
*/
|
||||
uint8_t udd_getaddress(void);
|
||||
|
||||
/**
|
||||
* \brief Returns the current start of frame number
|
||||
*
|
||||
* \return current start of frame number.
|
||||
*/
|
||||
uint16_t udd_get_frame_number(void);
|
||||
|
||||
/**
|
||||
* \brief Returns the current micro start of frame number
|
||||
*
|
||||
* \return current micro start of frame number required in high speed mode.
|
||||
*/
|
||||
uint16_t udd_get_micro_frame_number(void);
|
||||
|
||||
/*! \brief The USB driver sends a resume signal called Upstream Resume
|
||||
*/
|
||||
void udd_send_remotewakeup(void);
|
||||
|
||||
/**
|
||||
* \brief Load setup payload
|
||||
*
|
||||
* \param payload Pointer on payload
|
||||
* \param payload_size Size of payload
|
||||
*/
|
||||
void udd_set_setup_payload( uint8_t *payload, uint16_t payload_size );
|
||||
|
||||
|
||||
/**
|
||||
* \name Endpoint Management
|
||||
*
|
||||
* The following functions allow drivers to create and remove
|
||||
* endpoints, as well as set, clear and query their "halted" and
|
||||
* "wedged" states.
|
||||
*/
|
||||
//@{
|
||||
|
||||
#if (USB_DEVICE_MAX_EP != 0)
|
||||
|
||||
/**
|
||||
* \brief Configures and enables an endpoint
|
||||
*
|
||||
* \param ep Endpoint number including direction (USB_EP_DIR_IN/USB_EP_DIR_OUT).
|
||||
* \param bmAttributes Attributes of endpoint declared in the descriptor.
|
||||
* \param MaxEndpointSize Endpoint maximum size
|
||||
*
|
||||
* \return \c 1 if the endpoint is enabled, otherwise \c 0.
|
||||
*/
|
||||
bool udd_ep_alloc(udd_ep_id_t ep, uint8_t bmAttributes,
|
||||
uint16_t MaxEndpointSize);
|
||||
|
||||
/**
|
||||
* \brief Disables an endpoint
|
||||
*
|
||||
* \param ep Endpoint number including direction (USB_EP_DIR_IN/USB_EP_DIR_OUT).
|
||||
*/
|
||||
void udd_ep_free(udd_ep_id_t ep);
|
||||
|
||||
/**
|
||||
* \brief Check if the endpoint \a ep is halted.
|
||||
*
|
||||
* \param ep The ID of the endpoint to check.
|
||||
*
|
||||
* \return \c 1 if \a ep is halted, otherwise \c 0.
|
||||
*/
|
||||
bool udd_ep_is_halted(udd_ep_id_t ep);
|
||||
|
||||
/**
|
||||
* \brief Set the halted state of the endpoint \a ep
|
||||
*
|
||||
* After calling this function, any transaction on \a ep will result
|
||||
* in a STALL handshake being sent. Any pending transactions will be
|
||||
* performed first, however.
|
||||
*
|
||||
* \param ep The ID of the endpoint to be halted
|
||||
*
|
||||
* \return \c 1 if \a ep is halted, otherwise \c 0.
|
||||
*/
|
||||
bool udd_ep_set_halt(udd_ep_id_t ep);
|
||||
|
||||
/**
|
||||
* \brief Clear the halted state of the endpoint \a ep
|
||||
*
|
||||
* After calling this function, any transaction on \a ep will
|
||||
* be handled normally, i.e. a STALL handshake will not be sent, and
|
||||
* the data toggle sequence will start at DATA0.
|
||||
*
|
||||
* \param ep The ID of the endpoint to be un-halted
|
||||
*
|
||||
* \return \c 1 if function was successfully done, otherwise \c 0.
|
||||
*/
|
||||
bool udd_ep_clear_halt(udd_ep_id_t ep);
|
||||
|
||||
/**
|
||||
* \brief Registers a callback to call when endpoint halt is cleared
|
||||
*
|
||||
* \param ep The ID of the endpoint to use
|
||||
* \param callback NULL or function to call when endpoint halt is cleared
|
||||
*
|
||||
* \warning if the endpoint is not halted then the \a callback is called immediately.
|
||||
*
|
||||
* \return \c 1 if the register is accepted, otherwise \c 0.
|
||||
*/
|
||||
bool udd_ep_wait_stall_clear(udd_ep_id_t ep,
|
||||
udd_callback_halt_cleared_t callback);
|
||||
|
||||
/**
|
||||
* \brief Allows to receive or send data on an endpoint
|
||||
*
|
||||
* The driver uses a specific DMA USB to transfer data
|
||||
* from internal RAM to endpoint, if this one is available.
|
||||
* When the transfer is finished or aborted (stall, reset, ...), the \a callback is called.
|
||||
* The \a callback returns the transfer status and eventually the number of byte transfered.
|
||||
* Note: The control endpoint is not authorized.
|
||||
*
|
||||
* \param ep The ID of the endpoint to use
|
||||
* \param b_shortpacket Enabled automatic short packet
|
||||
* \param buf Buffer on Internal RAM to send or fill.
|
||||
* It must be align, then use COMPILER_WORD_ALIGNED.
|
||||
* \param buf_size Buffer size to send or fill
|
||||
* \param callback NULL or function to call at the end of transfer
|
||||
*
|
||||
* \warning About \a b_shortpacket, for IN endpoint it means that a short packet
|
||||
* (or a Zero Length Packet) will be sent to the USB line to properly close the usb
|
||||
* transfer at the end of the data transfer.
|
||||
* For Bulk and Interrupt OUT endpoint, it will automatically stop the transfer
|
||||
* at the end of the data transfer (received short packet).
|
||||
*
|
||||
* \return \c 1 if function was successfully done, otherwise \c 0.
|
||||
*/
|
||||
bool udd_ep_run(udd_ep_id_t ep, bool b_shortpacket,
|
||||
uint8_t *buf, iram_size_t buf_size,
|
||||
udd_callback_trans_t callback);
|
||||
/**
|
||||
* \brief Aborts transfer on going on endpoint
|
||||
*
|
||||
* If a transfer is on going, then it is stopped and
|
||||
* the callback registered is called to signal the end of transfer.
|
||||
* Note: The control endpoint is not authorized.
|
||||
*
|
||||
* \param ep Endpoint to abort
|
||||
*/
|
||||
void udd_ep_abort(udd_ep_id_t ep);
|
||||
|
||||
#endif
|
||||
|
||||
//@}
|
||||
|
||||
|
||||
/**
|
||||
* \name High speed test mode management
|
||||
*
|
||||
* The following functions allow the device to jump to a specific test mode required in high speed mode.
|
||||
*/
|
||||
//@{
|
||||
void udd_test_mode_j(void);
|
||||
void udd_test_mode_k(void);
|
||||
void udd_test_mode_se0_nak(void);
|
||||
void udd_test_mode_packet(void);
|
||||
//@}
|
||||
|
||||
|
||||
/**
|
||||
* \name UDC callbacks to provide for UDD
|
||||
*
|
||||
* The following callbacks are used by UDD.
|
||||
*/
|
||||
//@{
|
||||
|
||||
/**
|
||||
* \brief Decodes and manages a setup request
|
||||
*
|
||||
* The driver call it when a SETUP packet is received.
|
||||
* The \c udd_g_ctrlreq contains the data of SETUP packet.
|
||||
* If this callback accepts the setup request then it must
|
||||
* return \c 1 and eventually update \c udd_g_ctrlreq to send or receive data.
|
||||
*
|
||||
* \return \c 1 if the request is accepted, otherwise \c 0.
|
||||
*/
|
||||
extern bool udc_process_setup(void);
|
||||
|
||||
/**
|
||||
* \brief Reset the UDC
|
||||
*
|
||||
* The UDC must reset all configuration.
|
||||
*/
|
||||
extern void udc_reset(void);
|
||||
|
||||
/**
|
||||
* \brief To signal that a SOF is occurred
|
||||
*
|
||||
* The UDC must send the signal to all UDIs enabled
|
||||
*/
|
||||
extern void udc_sof_notify(void);
|
||||
|
||||
//@}
|
||||
|
||||
//@}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // _UDD_H_
|
133
tmk_core/protocol/arm_atsam/usb/udi.h
Normal file
133
tmk_core/protocol/arm_atsam/usb/udi.h
Normal file
|
@ -0,0 +1,133 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Common API for USB Device Interface
|
||||
*
|
||||
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
|
||||
#ifndef _UDI_H_
|
||||
#define _UDI_H_
|
||||
|
||||
#include "conf_usb.h"
|
||||
#include "usb_protocol.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \ingroup usb_device_group
|
||||
* \defgroup udi_group USB Device Interface (UDI)
|
||||
* The UDI provides a common API for all classes,
|
||||
* and this is used by UDC for the main control of USB Device interface.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief UDI API.
|
||||
*
|
||||
* The callbacks within this structure are called only by
|
||||
* USB Device Controller (UDC)
|
||||
*
|
||||
* The udc_get_interface_desc() can be use by UDI to know the interface descriptor
|
||||
* selected by UDC.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* \brief Enable the interface.
|
||||
*
|
||||
* This function is called when the host selects a configuration
|
||||
* to which this interface belongs through a Set Configuration
|
||||
* request, and when the host selects an alternate setting of
|
||||
* this interface through a Set Interface request.
|
||||
*
|
||||
* \return \c 1 if function was successfully done, otherwise \c 0.
|
||||
*/
|
||||
bool(*enable) (void);
|
||||
|
||||
/**
|
||||
* \brief Disable the interface.
|
||||
*
|
||||
* This function is called when this interface is currently
|
||||
* active, and
|
||||
* - the host selects any configuration through a Set
|
||||
* Configuration request, or
|
||||
* - the host issues a USB reset, or
|
||||
* - the device is detached from the host (i.e. Vbus is no
|
||||
* longer present)
|
||||
*/
|
||||
void (*disable) (void);
|
||||
|
||||
/**
|
||||
* \brief Handle a control request directed at an interface.
|
||||
*
|
||||
* This function is called when this interface is currently
|
||||
* active and the host sends a SETUP request
|
||||
* with this interface as the recipient.
|
||||
*
|
||||
* Use udd_g_ctrlreq to decode and response to SETUP request.
|
||||
*
|
||||
* \return \c 1 if this interface supports the SETUP request, otherwise \c 0.
|
||||
*/
|
||||
bool(*setup) (void);
|
||||
|
||||
/**
|
||||
* \brief Returns the current setting of the selected interface.
|
||||
*
|
||||
* This function is called when UDC when know alternate setting of selected interface.
|
||||
*
|
||||
* \return alternate setting of selected interface
|
||||
*/
|
||||
uint8_t(*getsetting) (void);
|
||||
|
||||
/**
|
||||
* \brief To signal that a SOF is occurred
|
||||
*/
|
||||
void(*sof_notify) (void);
|
||||
} udi_api_t;
|
||||
|
||||
//@}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // _UDI_H_
|
1380
tmk_core/protocol/arm_atsam/usb/udi_cdc.c
Normal file
1380
tmk_core/protocol/arm_atsam/usb/udi_cdc.c
Normal file
File diff suppressed because it is too large
Load diff
376
tmk_core/protocol/arm_atsam/usb/udi_cdc.h
Normal file
376
tmk_core/protocol/arm_atsam/usb/udi_cdc.h
Normal file
|
@ -0,0 +1,376 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief USB Device Communication Device Class (CDC) interface definitions.
|
||||
*
|
||||
* Copyright (c) 2009-2016 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
|
||||
#ifndef _UDI_CDC_H_
|
||||
#define _UDI_CDC_H_
|
||||
|
||||
#ifdef CDC
|
||||
|
||||
#include "conf_usb.h"
|
||||
#include "usb_protocol.h"
|
||||
#include "usb_protocol_cdc.h"
|
||||
#include "udd.h"
|
||||
#include "udc_desc.h"
|
||||
#include "udi.h"
|
||||
|
||||
// Check the number of port
|
||||
#ifndef UDI_CDC_PORT_NB
|
||||
# define UDI_CDC_PORT_NB 1
|
||||
#endif
|
||||
#if (UDI_CDC_PORT_NB > 1)
|
||||
# error UDI_CDC_PORT_NB must be at most 1
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \addtogroup udi_cdc_group_udc
|
||||
* @{
|
||||
*/
|
||||
|
||||
//! Global structure which contains standard UDI API for UDC
|
||||
extern UDC_DESC_STORAGE udi_api_t udi_api_cdc_comm;
|
||||
extern UDC_DESC_STORAGE udi_api_t udi_api_cdc_data;
|
||||
//@}
|
||||
|
||||
//#define CDC_ACM_SIZE 64 see usb_protocol_cdc.h
|
||||
//#define CDC_RX_SIZE 64
|
||||
|
||||
//! CDC communication endpoints size for all speeds
|
||||
#define UDI_CDC_COMM_EP_SIZE CDC_ACM_SIZE
|
||||
//! CDC data endpoints size for FS speed (8B, 16B, 32B, 64B)
|
||||
#define UDI_CDC_DATA_EPS_FS_SIZE CDC_RX_SIZE
|
||||
|
||||
//@}
|
||||
|
||||
/**
|
||||
* \ingroup udi_group
|
||||
* \defgroup udi_cdc_group USB Device Interface (UDI) for Communication Class Device (CDC)
|
||||
*
|
||||
* Common APIs used by high level application to use this USB class.
|
||||
*
|
||||
* These routines are used to transfer and control data
|
||||
* to/from USB CDC endpoint.
|
||||
*
|
||||
* See \ref udi_cdc_quickstart.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \name Interface for application with single CDC interface support
|
||||
*/
|
||||
//@{
|
||||
|
||||
/**
|
||||
* \brief Notify a state change of DCD signal
|
||||
*
|
||||
* \param b_set DCD is enabled if true, else disabled
|
||||
*/
|
||||
void udi_cdc_ctrl_signal_dcd(bool b_set);
|
||||
|
||||
/**
|
||||
* \brief Notify a state change of DSR signal
|
||||
*
|
||||
* \param b_set DSR is enabled if true, else disabled
|
||||
*/
|
||||
void udi_cdc_ctrl_signal_dsr(bool b_set);
|
||||
|
||||
/**
|
||||
* \brief Notify a framing error
|
||||
*/
|
||||
void udi_cdc_signal_framing_error(void);
|
||||
|
||||
/**
|
||||
* \brief Notify a parity error
|
||||
*/
|
||||
void udi_cdc_signal_parity_error(void);
|
||||
|
||||
/**
|
||||
* \brief Notify a overrun
|
||||
*/
|
||||
void udi_cdc_signal_overrun(void);
|
||||
|
||||
/**
|
||||
* \brief Gets the number of byte received
|
||||
*
|
||||
* \return the number of data available
|
||||
*/
|
||||
iram_size_t udi_cdc_get_nb_received_data(void);
|
||||
|
||||
/**
|
||||
* \brief This function checks if a character has been received on the CDC line
|
||||
*
|
||||
* \return \c 1 if a byte is ready to be read.
|
||||
*/
|
||||
bool udi_cdc_is_rx_ready(void);
|
||||
|
||||
/**
|
||||
* \brief Waits and gets a value on CDC line
|
||||
*
|
||||
* \return value read on CDC line
|
||||
*/
|
||||
int udi_cdc_getc(void);
|
||||
|
||||
/**
|
||||
* \brief Reads a RAM buffer on CDC line
|
||||
*
|
||||
* \param buf Values read
|
||||
* \param size Number of value read
|
||||
*
|
||||
* \return the number of data remaining
|
||||
*/
|
||||
iram_size_t udi_cdc_read_buf(void* buf, iram_size_t size);
|
||||
|
||||
/**
|
||||
* \brief Non polling reads of a up to 'size' data from CDC line
|
||||
*
|
||||
* \param port Communication port number to manage
|
||||
* \param buf Buffer where to store read data
|
||||
* \param size Maximum number of data to read (size of buffer)
|
||||
*
|
||||
* \return the number of data effectively read
|
||||
*/
|
||||
iram_size_t udi_cdc_read_no_polling(void* buf, iram_size_t size);
|
||||
|
||||
/**
|
||||
* \brief Gets the number of free byte in TX buffer
|
||||
*
|
||||
* \return the number of free byte in TX buffer
|
||||
*/
|
||||
iram_size_t udi_cdc_get_free_tx_buffer(void);
|
||||
|
||||
/**
|
||||
* \brief This function checks if a new character sent is possible
|
||||
* The type int is used to support scanf redirection from compiler LIB.
|
||||
*
|
||||
* \return \c 1 if a new character can be sent
|
||||
*/
|
||||
bool udi_cdc_is_tx_ready(void);
|
||||
|
||||
/**
|
||||
* \brief Puts a byte on CDC line
|
||||
* The type int is used to support printf redirection from compiler LIB.
|
||||
*
|
||||
* \param value Value to put
|
||||
*
|
||||
* \return \c 1 if function was successfully done, otherwise \c 0.
|
||||
*/
|
||||
int udi_cdc_putc(int value);
|
||||
|
||||
/**
|
||||
* \brief Writes a RAM buffer on CDC line
|
||||
*
|
||||
* \param buf Values to write
|
||||
* \param size Number of value to write
|
||||
*
|
||||
* \return the number of data remaining
|
||||
*/
|
||||
iram_size_t udi_cdc_write_buf(const void* buf, iram_size_t size);
|
||||
//@}
|
||||
|
||||
/**
|
||||
* \name Interface for application with multi CDC interfaces support
|
||||
*/
|
||||
//@{
|
||||
|
||||
/**
|
||||
* \brief Notify a state change of DCD signal
|
||||
*
|
||||
* \param port Communication port number to manage
|
||||
* \param b_set DCD is enabled if true, else disabled
|
||||
*/
|
||||
void udi_cdc_multi_ctrl_signal_dcd(uint8_t port, bool b_set);
|
||||
|
||||
/**
|
||||
* \brief Notify a state change of DSR signal
|
||||
*
|
||||
* \param port Communication port number to manage
|
||||
* \param b_set DSR is enabled if true, else disabled
|
||||
*/
|
||||
void udi_cdc_multi_ctrl_signal_dsr(uint8_t port, bool b_set);
|
||||
|
||||
/**
|
||||
* \brief Notify a framing error
|
||||
*
|
||||
* \param port Communication port number to manage
|
||||
*/
|
||||
void udi_cdc_multi_signal_framing_error(uint8_t port);
|
||||
|
||||
/**
|
||||
* \brief Notify a parity error
|
||||
*
|
||||
* \param port Communication port number to manage
|
||||
*/
|
||||
void udi_cdc_multi_signal_parity_error(uint8_t port);
|
||||
|
||||
/**
|
||||
* \brief Notify a overrun
|
||||
*
|
||||
* \param port Communication port number to manage
|
||||
*/
|
||||
void udi_cdc_multi_signal_overrun(uint8_t port);
|
||||
|
||||
/**
|
||||
* \brief Gets the number of byte received
|
||||
*
|
||||
* \param port Communication port number to manage
|
||||
*
|
||||
* \return the number of data available
|
||||
*/
|
||||
iram_size_t udi_cdc_multi_get_nb_received_data(uint8_t port);
|
||||
|
||||
/**
|
||||
* \brief This function checks if a character has been received on the CDC line
|
||||
*
|
||||
* \param port Communication port number to manage
|
||||
*
|
||||
* \return \c 1 if a byte is ready to be read.
|
||||
*/
|
||||
bool udi_cdc_multi_is_rx_ready(uint8_t port);
|
||||
|
||||
/**
|
||||
* \brief Waits and gets a value on CDC line
|
||||
*
|
||||
* \param port Communication port number to manage
|
||||
*
|
||||
* \return value read on CDC line
|
||||
*/
|
||||
int udi_cdc_multi_getc(uint8_t port);
|
||||
|
||||
/**
|
||||
* \brief Reads a RAM buffer on CDC line
|
||||
*
|
||||
* \param port Communication port number to manage
|
||||
* \param buf Values read
|
||||
* \param size Number of values read
|
||||
*
|
||||
* \return the number of data remaining
|
||||
*/
|
||||
iram_size_t udi_cdc_multi_read_buf(uint8_t port, void* buf, iram_size_t size);
|
||||
|
||||
/**
|
||||
* \brief Gets the number of free byte in TX buffer
|
||||
*
|
||||
* \param port Communication port number to manage
|
||||
*
|
||||
* \return the number of free byte in TX buffer
|
||||
*/
|
||||
iram_size_t udi_cdc_multi_get_free_tx_buffer(uint8_t port);
|
||||
|
||||
/**
|
||||
* \brief This function checks if a new character sent is possible
|
||||
* The type int is used to support scanf redirection from compiler LIB.
|
||||
*
|
||||
* \param port Communication port number to manage
|
||||
*
|
||||
* \return \c 1 if a new character can be sent
|
||||
*/
|
||||
bool udi_cdc_multi_is_tx_ready(uint8_t port);
|
||||
|
||||
/**
|
||||
* \brief Puts a byte on CDC line
|
||||
* The type int is used to support printf redirection from compiler LIB.
|
||||
*
|
||||
* \param port Communication port number to manage
|
||||
* \param value Value to put
|
||||
*
|
||||
* \return \c 1 if function was successfully done, otherwise \c 0.
|
||||
*/
|
||||
int udi_cdc_multi_putc(uint8_t port, int value);
|
||||
|
||||
/**
|
||||
* \brief Writes a RAM buffer on CDC line
|
||||
*
|
||||
* \param port Communication port number to manage
|
||||
* \param buf Values to write
|
||||
* \param size Number of value to write
|
||||
*
|
||||
* \return the number of data remaining
|
||||
*/
|
||||
iram_size_t udi_cdc_multi_write_buf(uint8_t port, const void* buf, iram_size_t size);
|
||||
//@}
|
||||
|
||||
#define CDC_PRINTBUF_SIZE 256
|
||||
extern char printbuf[CDC_PRINTBUF_SIZE];
|
||||
|
||||
#define CDC_INBUF_SIZE 256
|
||||
|
||||
typedef struct {
|
||||
uint32_t count;
|
||||
uint32_t lastcount;
|
||||
char buf[CDC_INBUF_SIZE];
|
||||
} inbuf_t;
|
||||
|
||||
#else //CDC
|
||||
|
||||
// keep these to accommodate calls if remaining
|
||||
#define CDC_PRINTBUF_SIZE 1
|
||||
extern char printbuf[CDC_PRINTBUF_SIZE];
|
||||
|
||||
#define CDC_INBUF_SIZE 1
|
||||
|
||||
typedef struct {
|
||||
uint32_t count;
|
||||
uint32_t lastcount;
|
||||
char buf[CDC_INBUF_SIZE];
|
||||
} inbuf_t;
|
||||
|
||||
extern inbuf_t inbuf;
|
||||
|
||||
#endif //CDC
|
||||
|
||||
uint32_t CDC_print(char *printbuf);
|
||||
int CDC_printf(const char *_Format, ...);
|
||||
uint32_t CDC_input(void);
|
||||
void CDC_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _UDI_CDC_H_
|
72
tmk_core/protocol/arm_atsam/usb/udi_cdc_conf.h
Normal file
72
tmk_core/protocol/arm_atsam/usb/udi_cdc_conf.h
Normal file
|
@ -0,0 +1,72 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Default CDC configuration for a USB Device with a single interface
|
||||
*
|
||||
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
|
||||
#ifndef _UDI_CDC_CONF_H_
|
||||
#define _UDI_CDC_CONF_H_
|
||||
|
||||
#include "usb_protocol_cdc.h"
|
||||
#include "conf_usb.h"
|
||||
#include "udi_device_conf.h"
|
||||
|
||||
#ifndef UDI_CDC_PORT_NB
|
||||
#define UDI_CDC_PORT_NB 1
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define UDI_CDC_DATA_EP_IN_0 ((CDC_TX_ENDPOINT) | (USB_EP_DIR_IN)) //TX
|
||||
#define UDI_CDC_DATA_EP_OUT_0 ((CDC_RX_ENDPOINT) | (USB_EP_DIR_OUT)) // RX
|
||||
#define UDI_CDC_COMM_EP_0 ((CDC_ACM_ENDPOINT) | (USB_EP_DIR_IN)) // Notify endpoint
|
||||
|
||||
#define UDI_CDC_COMM_IFACE_NUMBER_0 (CDC_STATUS_INTERFACE)
|
||||
#define UDI_CDC_DATA_IFACE_NUMBER_0 (CDC_DATA_INTERFACE)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // _UDI_CDC_CONF_H_
|
781
tmk_core/protocol/arm_atsam/usb/udi_device_conf.h
Normal file
781
tmk_core/protocol/arm_atsam/usb/udi_device_conf.h
Normal file
|
@ -0,0 +1,781 @@
|
|||
/*
|
||||
Copyright 2018 Massdrop Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _UDI_DEVICE_CONF_H_
|
||||
#define _UDI_DEVICE_CONF_H_
|
||||
|
||||
#include "udi_device_epsize.h"
|
||||
#include "usb_protocol.h"
|
||||
#include "compiler.h"
|
||||
#include "usb_protocol_hid.h"
|
||||
|
||||
#define DEVICE_CLASS 0
|
||||
#define DEVICE_SUBCLASS 0
|
||||
#define DEVICE_PROTOCOL 0
|
||||
|
||||
#define KBD
|
||||
|
||||
//#define MOUSE_ENABLE //rules.mk
|
||||
#ifdef MOUSE_ENABLE
|
||||
#define MOU
|
||||
#endif
|
||||
|
||||
//#define EXTRAKEY_ENABLE //rules.mk
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
#define EXK
|
||||
#endif
|
||||
|
||||
//#define RAW_ENABLE //rules.mk
|
||||
#ifdef RAW_ENABLE
|
||||
#define RAW
|
||||
#endif
|
||||
|
||||
//#define CONSOLE_ENABLE //rules.mk
|
||||
#ifdef CONSOLE_ENABLE
|
||||
#define CON
|
||||
#endif
|
||||
|
||||
//#define NKRO_ENABLE //rules.mk
|
||||
#ifdef NKRO_ENABLE
|
||||
#define NKRO
|
||||
#endif
|
||||
|
||||
//#define MIDI_ENABLE //deferred implementation
|
||||
//#ifdef MIDI_ENABLE
|
||||
//#define MIDI
|
||||
//#endif
|
||||
|
||||
//#define VIRTSER_ENABLE //rules.mk
|
||||
#ifdef VIRTSER_ENABLE
|
||||
#define CDC
|
||||
//because CDC uses IAD (interface association descriptor
|
||||
//per USB Interface Association Descriptor Device Class Code and Use Model 7/23/2003 Rev 1.0)
|
||||
#undef DEVICE_CLASS
|
||||
#define DEVICE_CLASS 0xEF
|
||||
#undef DEVICE_SUBCLASS
|
||||
#define DEVICE_SUBCLASS 0x02
|
||||
#undef DEVICE_PROTOCOL
|
||||
#define DEVICE_PROTOCOL 0x01
|
||||
#endif
|
||||
|
||||
/* number of interfaces */
|
||||
#define NEXT_INTERFACE_0 0
|
||||
|
||||
#ifdef KBD
|
||||
#define KEYBOARD_INTERFACE NEXT_INTERFACE_0
|
||||
#define NEXT_INTERFACE_1 (KEYBOARD_INTERFACE + 1)
|
||||
#define UDI_HID_KBD_IFACE_NUMBER KEYBOARD_INTERFACE
|
||||
#else
|
||||
#define NEXT_INTERFACE_1 NEXT_INTERFACE_0
|
||||
#endif
|
||||
|
||||
// It is important that the Raw HID interface is at a constant
|
||||
// interface number, to support Linux/OSX platforms and chrome.hid
|
||||
// If Raw HID is enabled, let it be always 1.
|
||||
#ifdef RAW
|
||||
#define RAW_INTERFACE NEXT_INTERFACE_1
|
||||
#define NEXT_INTERFACE_2 (RAW_INTERFACE + 1)
|
||||
#else
|
||||
#define NEXT_INTERFACE_2 NEXT_INTERFACE_1
|
||||
#endif
|
||||
|
||||
#ifdef MOU
|
||||
#define MOUSE_INTERFACE NEXT_INTERFACE_2
|
||||
#define UDI_HID_MOU_IFACE_NUMBER MOUSE_INTERFACE
|
||||
#define NEXT_INTERFACE_3 (MOUSE_INTERFACE + 1)
|
||||
#else
|
||||
#define NEXT_INTERFACE_3 NEXT_INTERFACE_2
|
||||
#endif
|
||||
|
||||
#ifdef EXK
|
||||
#define EXTRAKEY_INTERFACE NEXT_INTERFACE_3
|
||||
#define NEXT_INTERFACE_4 (EXTRAKEY_INTERFACE + 1)
|
||||
#define UDI_HID_EXK_IFACE_NUMBER EXTRAKEY_INTERFACE
|
||||
#else
|
||||
#define NEXT_INTERFACE_4 NEXT_INTERFACE_3
|
||||
#endif
|
||||
|
||||
#ifdef CON
|
||||
#define CON_INTERFACE NEXT_INTERFACE_4
|
||||
#define NEXT_INTERFACE_5 (CON_INTERFACE + 1)
|
||||
#define UDI_HID_CON_IFACE_NUMBER CON_INTERFACE
|
||||
#else
|
||||
#define NEXT_INTERFACE_5 NEXT_INTERFACE_4
|
||||
#endif
|
||||
|
||||
#ifdef NKRO
|
||||
#define NKRO_INTERFACE NEXT_INTERFACE_5
|
||||
#define NEXT_INTERFACE_6 (NKRO_INTERFACE + 1)
|
||||
#define UDI_HID_NKRO_IFACE_NUMBER NKRO_INTERFACE
|
||||
#else
|
||||
#define NEXT_INTERFACE_6 NEXT_INTERFACE_5
|
||||
#endif
|
||||
|
||||
#ifdef MIDI
|
||||
#define AC_INTERFACE NEXT_INTERFACE_6
|
||||
#define AS_INTERFACE (AC_INTERFACE + 1)
|
||||
#define NEXT_INTERFACE_7 (AS_INTERFACE + 1)
|
||||
#else
|
||||
#define NEXT_INTERFACE_7 NEXT_INTERFACE_6
|
||||
#endif
|
||||
|
||||
#ifdef CDC
|
||||
#define CCI_INTERFACE NEXT_INTERFACE_7
|
||||
#define CDI_INTERFACE (CCI_INTERFACE + 1)
|
||||
#define NEXT_INTERFACE_8 (CDI_INTERFACE + 1)
|
||||
#define CDC_STATUS_INTERFACE CCI_INTERFACE
|
||||
#define CDC_DATA_INTERFACE CDI_INTERFACE
|
||||
#else
|
||||
#define NEXT_INTERFACE_8 NEXT_INTERFACE_7
|
||||
#endif
|
||||
|
||||
/* nubmer of interfaces */
|
||||
#define TOTAL_INTERFACES NEXT_INTERFACE_8
|
||||
#define USB_DEVICE_NB_INTERFACE TOTAL_INTERFACES
|
||||
|
||||
|
||||
// **********************************************************************
|
||||
// Endopoint number and size
|
||||
// **********************************************************************
|
||||
#define USB_DEVICE_EP_CTRL_SIZE 8
|
||||
|
||||
#define NEXT_IN_EPNUM_0 1
|
||||
#define NEXT_OUT_EPNUM_0 1
|
||||
|
||||
#ifdef KBD
|
||||
#define KEYBOARD_IN_EPNUM NEXT_IN_EPNUM_0
|
||||
#define UDI_HID_KBD_EP_IN KEYBOARD_IN_EPNUM
|
||||
#define NEXT_IN_EPNUM_1 (KEYBOARD_IN_EPNUM + 1)
|
||||
#define UDI_HID_KBD_EP_SIZE KEYBOARD_EPSIZE
|
||||
#define KBD_POLLING_INTERVAL 10
|
||||
#ifndef UDI_HID_KBD_STRING_ID
|
||||
#define UDI_HID_KBD_STRING_ID 0
|
||||
#endif
|
||||
#else
|
||||
#define NEXT_IN_EPNUM_1 NEXT_IN_EPNUM_0
|
||||
#endif
|
||||
|
||||
#ifdef MOU
|
||||
#define MOUSE_IN_EPNUM NEXT_IN_EPNUM_1
|
||||
#define NEXT_IN_EPNUM_2 (MOUSE_IN_EPNUM + 1)
|
||||
#define UDI_HID_MOU_EP_IN MOUSE_IN_EPNUM
|
||||
#define UDI_HID_MOU_EP_SIZE MOUSE_EPSIZE
|
||||
#define MOU_POLLING_INTERVAL 10
|
||||
#ifndef UDI_HID_MOU_STRING_ID
|
||||
#define UDI_HID_MOU_STRING_ID 0
|
||||
#endif
|
||||
#else
|
||||
#define NEXT_IN_EPNUM_2 NEXT_IN_EPNUM_1
|
||||
#endif
|
||||
|
||||
#ifdef EXK
|
||||
#define EXTRAKEY_IN_EPNUM NEXT_IN_EPNUM_2
|
||||
#define UDI_HID_EXK_EP_IN EXTRAKEY_IN_EPNUM
|
||||
#define NEXT_IN_EPNUM_3 (EXTRAKEY_IN_EPNUM + 1)
|
||||
#define UDI_HID_EXK_EP_SIZE EXTRAKEY_EPSIZE
|
||||
#define EXTRAKEY_POLLING_INTERVAL 10
|
||||
#ifndef UDI_HID_EXK_STRING_ID
|
||||
#define UDI_HID_EXK_STRING_ID 0
|
||||
#endif
|
||||
#else
|
||||
#define NEXT_IN_EPNUM_3 NEXT_IN_EPNUM_2
|
||||
#endif
|
||||
|
||||
#ifdef RAW
|
||||
#define RAW_IN_EPNUM NEXT_IN_EPNUM_3
|
||||
#define UDI_HID_RAW_EP_IN RAW_IN_EPNUM
|
||||
#define NEXT_IN_EPNUM_4 (RAW_IN_EPNUM + 1)
|
||||
#define RAW_OUT_EPNUM NEXT_OUT_EPNUM_0
|
||||
#define UDI_HID_RAW_EP_OUT RAW_OUT_EPNUM
|
||||
#define NEXT_OUT_EPNUM_1 (RAW_OUT_EPNUM + 1)
|
||||
#define RAW_POLLING_INTERVAL 1
|
||||
#ifndef UDI_HID_RAW_STRING_ID
|
||||
#define UDI_HID_RAW_STRING_ID 0
|
||||
#endif
|
||||
#else
|
||||
#define NEXT_IN_EPNUM_4 NEXT_IN_EPNUM_3
|
||||
#define NEXT_OUT_EPNUM_1 NEXT_OUT_EPNUM_0
|
||||
#endif
|
||||
|
||||
#ifdef CON
|
||||
#define CON_IN_EPNUM NEXT_IN_EPNUM_4
|
||||
#define UDI_HID_CON_EP_IN CON_IN_EPNUM
|
||||
#define NEXT_IN_EPNUM_5 (CON_IN_EPNUM + 1)
|
||||
#define CON_OUT_EPNUM NEXT_OUT_EPNUM_1
|
||||
#define UDI_HID_CON_EP_OUT CON_OUT_EPNUM
|
||||
#define NEXT_OUT_EPNUM_2 (CON_OUT_EPNUM + 1)
|
||||
#define CON_POLLING_INTERVAL 1
|
||||
#ifndef UDI_HID_CON_STRING_ID
|
||||
#define UDI_HID_CON_STRING_ID 0
|
||||
#endif
|
||||
#else
|
||||
#define NEXT_IN_EPNUM_5 NEXT_IN_EPNUM_4
|
||||
#define NEXT_OUT_EPNUM_2 NEXT_OUT_EPNUM_1
|
||||
#endif
|
||||
|
||||
#ifdef NKRO
|
||||
#define NKRO_IN_EPNUM NEXT_IN_EPNUM_5
|
||||
#define UDI_HID_NKRO_EP_IN NKRO_IN_EPNUM
|
||||
#define NEXT_IN_EPNUM_6 (NKRO_IN_EPNUM + 1)
|
||||
#define UDI_HID_NKRO_EP_SIZE NKRO_EPSIZE
|
||||
#define NKRO_POLLING_INTERVAL 1
|
||||
#ifndef UDI_HID_NKRO_STRING_ID
|
||||
#define UDI_HID_NKRO_STRING_ID 0
|
||||
#endif
|
||||
#else
|
||||
#define NEXT_IN_EPNUM_6 NEXT_IN_EPNUM_5
|
||||
#endif
|
||||
|
||||
#ifdef MIDI
|
||||
#define MIDI_STREAM_IN_EPNUM NEXT_IN_EPNUM_6
|
||||
#define NEXT_IN_EPNUM_7 (MIDI_STREAM_IN_EPNUM + 1)
|
||||
#define MIDI_STREAM_OUT_EPNUM NEXT_OUT_EPNUM_2
|
||||
#define NEXT_OUT_EPNUM_3 (MIDI_STREAM_OUT_EPNUM + 1)
|
||||
#define MIDI_POLLING_INTERVAL 5
|
||||
#else
|
||||
#define NEXT_IN_EPNUM_7 NEXT_IN_EPNUM_6
|
||||
#define NEXT_OUT_EPNUM_3 NEXT_OUT_EPNUM_2
|
||||
#endif
|
||||
|
||||
#ifdef CDC
|
||||
#define CDC_NOTIFICATION_EPNUM NEXT_IN_EPNUM_7
|
||||
#define CDC_ACM_ENDPOINT CDC_NOTIFICATION_EPNUM
|
||||
#define CDC_TX_ENDPOINT (CDC_NOTIFICATION_EPNUM + 1)
|
||||
#define NEXT_IN_EPNUM_8 (CDC_TX_ENDPOINT + 1)
|
||||
|
||||
#define CDC_OUT_EPNUM NEXT_OUT_EPNUM_3
|
||||
#define CDC_RX_ENDPOINT CDC_OUT_EPNUM
|
||||
#define NEXT_OUT_EPNUM_4 (CDC_OUT_EPNUM + 1)
|
||||
|
||||
#define CDC_ACM_SIZE CDC_NOTIFICATION_EPSIZE
|
||||
#define CDC_RX_SIZE CDC_EPSIZE //KFSMOD was 64
|
||||
#define CDC_TX_SIZE CDC_RX_SIZE
|
||||
#define CDC_ACM_POLLING_INTERVAL 255
|
||||
#define CDC_EP_INTERVAL_STATUS CDC_ACM_POLLING_INTERVAL
|
||||
#define CDC_DATA_POLLING_INTERVAL 5
|
||||
#define CDC_EP_INTERVAL_DATA CDC_DATA_POLLING_INTERVAL
|
||||
#define CDC_STATUS_NAME L"Virtual Serial Port - Status"
|
||||
#define CDC_DATA_NAME L"Virtual Serial Port - Data"
|
||||
#else
|
||||
#define NEXT_IN_EPNUM_8 NEXT_IN_EPNUM_7
|
||||
#define NEXT_OUT_EPNUM_4 NEXT_OUT_EPNUM_3
|
||||
#endif
|
||||
|
||||
#define TOTAL_OUT_EP NEXT_OUT_EPNUM_4
|
||||
#define TOTAL_IN_EP NEXT_IN_EPNUM_8
|
||||
#define USB_DEVICE_MAX_EP (max(NEXT_OUT_EPNUM_4, NEXT_IN_EPNUM_8))
|
||||
|
||||
#if USB_DEVICE_MAX_EP > 8
|
||||
#error "There are not enough available endpoints to support all functions. Remove some in the rules.mk file.(MOUSEKEY, EXTRAKEY, CONSOLE, NKRO, MIDI, VIRTSER)"
|
||||
#endif
|
||||
|
||||
|
||||
// **********************************************************************
|
||||
// KBD Descriptor structure and content
|
||||
// **********************************************************************
|
||||
#ifdef KBD
|
||||
|
||||
COMPILER_PACK_SET(1)
|
||||
|
||||
typedef struct {
|
||||
usb_iface_desc_t iface;
|
||||
usb_hid_descriptor_t hid;
|
||||
usb_ep_desc_t ep;
|
||||
} udi_hid_kbd_desc_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t array[59];
|
||||
} udi_hid_kbd_report_desc_t;
|
||||
|
||||
#define UDI_HID_KBD_DESC {\
|
||||
.iface.bLength = sizeof(usb_iface_desc_t),\
|
||||
.iface.bDescriptorType = USB_DT_INTERFACE,\
|
||||
.iface.bInterfaceNumber = UDI_HID_KBD_IFACE_NUMBER,\
|
||||
.iface.bAlternateSetting = 0,\
|
||||
.iface.bNumEndpoints = 1,\
|
||||
.iface.bInterfaceClass = HID_CLASS,\
|
||||
.iface.bInterfaceSubClass = HID_SUB_CLASS_BOOT,\
|
||||
.iface.bInterfaceProtocol = HID_PROTOCOL_KEYBOARD,\
|
||||
.iface.iInterface = UDI_HID_KBD_STRING_ID,\
|
||||
.hid.bLength = sizeof(usb_hid_descriptor_t),\
|
||||
.hid.bDescriptorType = USB_DT_HID,\
|
||||
.hid.bcdHID = LE16(USB_HID_BDC_V1_11),\
|
||||
.hid.bCountryCode = USB_HID_NO_COUNTRY_CODE,\
|
||||
.hid.bNumDescriptors = USB_HID_NUM_DESC,\
|
||||
.hid.bRDescriptorType = USB_DT_HID_REPORT,\
|
||||
.hid.wDescriptorLength = LE16(sizeof(udi_hid_kbd_report_desc_t)),\
|
||||
.ep.bLength = sizeof(usb_ep_desc_t),\
|
||||
.ep.bDescriptorType = USB_DT_ENDPOINT,\
|
||||
.ep.bEndpointAddress = UDI_HID_KBD_EP_IN | USB_EP_DIR_IN,\
|
||||
.ep.bmAttributes = USB_EP_TYPE_INTERRUPT,\
|
||||
.ep.wMaxPacketSize = LE16(UDI_HID_KBD_EP_SIZE),\
|
||||
.ep.bInterval = KBD_POLLING_INTERVAL,\
|
||||
}
|
||||
|
||||
//set report buffer (from host)
|
||||
extern uint8_t udi_hid_kbd_report_set;
|
||||
|
||||
//report buffer (to host)
|
||||
#define UDI_HID_KBD_REPORT_SIZE 8
|
||||
extern uint8_t udi_hid_kbd_report[UDI_HID_KBD_REPORT_SIZE];
|
||||
|
||||
COMPILER_PACK_RESET()
|
||||
|
||||
#endif //KBD
|
||||
|
||||
// **********************************************************************
|
||||
// EXK Descriptor structure and content
|
||||
// **********************************************************************
|
||||
#ifdef EXK
|
||||
|
||||
COMPILER_PACK_SET(1)
|
||||
|
||||
typedef struct {
|
||||
usb_iface_desc_t iface;
|
||||
usb_hid_descriptor_t hid;
|
||||
usb_ep_desc_t ep;
|
||||
} udi_hid_exk_desc_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t array[54];
|
||||
} udi_hid_exk_report_desc_t;
|
||||
|
||||
#define UDI_HID_EXK_DESC {\
|
||||
.iface.bLength = sizeof(usb_iface_desc_t),\
|
||||
.iface.bDescriptorType = USB_DT_INTERFACE,\
|
||||
.iface.bInterfaceNumber = UDI_HID_EXK_IFACE_NUMBER,\
|
||||
.iface.bAlternateSetting = 0,\
|
||||
.iface.bNumEndpoints = 1,\
|
||||
.iface.bInterfaceClass = HID_CLASS,\
|
||||
.iface.bInterfaceSubClass = HID_SUB_CLASS_BOOT,\
|
||||
.iface.bInterfaceProtocol = HID_PROTOCOL_GENERIC,\
|
||||
.iface.iInterface = UDI_HID_EXK_STRING_ID,\
|
||||
.hid.bLength = sizeof(usb_hid_descriptor_t),\
|
||||
.hid.bDescriptorType = USB_DT_HID,\
|
||||
.hid.bcdHID = LE16(USB_HID_BDC_V1_11),\
|
||||
.hid.bCountryCode = USB_HID_NO_COUNTRY_CODE,\
|
||||
.hid.bNumDescriptors = USB_HID_NUM_DESC,\
|
||||
.hid.bRDescriptorType = USB_DT_HID_REPORT,\
|
||||
.hid.wDescriptorLength = LE16(sizeof(udi_hid_exk_report_desc_t)),\
|
||||
.ep.bLength = sizeof(usb_ep_desc_t),\
|
||||
.ep.bDescriptorType = USB_DT_ENDPOINT,\
|
||||
.ep.bEndpointAddress = UDI_HID_EXK_EP_IN | USB_EP_DIR_IN,\
|
||||
.ep.bmAttributes = USB_EP_TYPE_INTERRUPT,\
|
||||
.ep.wMaxPacketSize = LE16(UDI_HID_EXK_EP_SIZE),\
|
||||
.ep.bInterval = EXTRAKEY_POLLING_INTERVAL,\
|
||||
}
|
||||
|
||||
//set report buffer (from host)
|
||||
extern uint8_t udi_hid_exk_report_set;
|
||||
|
||||
//report buffer
|
||||
#define UDI_HID_EXK_REPORT_SIZE 3
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t report_id;
|
||||
uint16_t report_data;
|
||||
} desc;
|
||||
uint8_t raw[UDI_HID_EXK_REPORT_SIZE];
|
||||
} udi_hid_exk_report_t;
|
||||
|
||||
extern udi_hid_exk_report_t udi_hid_exk_report;
|
||||
|
||||
COMPILER_PACK_RESET()
|
||||
|
||||
#endif //EXK
|
||||
|
||||
// **********************************************************************
|
||||
// NKRO Descriptor structure and content
|
||||
// **********************************************************************
|
||||
#ifdef NKRO
|
||||
|
||||
COMPILER_PACK_SET(1)
|
||||
|
||||
typedef struct {
|
||||
usb_iface_desc_t iface;
|
||||
usb_hid_descriptor_t hid;
|
||||
usb_ep_desc_t ep;
|
||||
} udi_hid_nkro_desc_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t array[57];
|
||||
} udi_hid_nkro_report_desc_t;
|
||||
|
||||
#define UDI_HID_NKRO_DESC {\
|
||||
.iface.bLength = sizeof(usb_iface_desc_t),\
|
||||
.iface.bDescriptorType = USB_DT_INTERFACE,\
|
||||
.iface.bInterfaceNumber = UDI_HID_NKRO_IFACE_NUMBER,\
|
||||
.iface.bAlternateSetting = 0,\
|
||||
.iface.bNumEndpoints = 1,\
|
||||
.iface.bInterfaceClass = HID_CLASS,\
|
||||
.iface.bInterfaceSubClass = HID_SUB_CLASS_NOBOOT,\
|
||||
.iface.bInterfaceProtocol = HID_PROTOCOL_KEYBOARD,\
|
||||
.iface.iInterface = UDI_HID_NKRO_STRING_ID,\
|
||||
.hid.bLength = sizeof(usb_hid_descriptor_t),\
|
||||
.hid.bDescriptorType = USB_DT_HID,\
|
||||
.hid.bcdHID = LE16(USB_HID_BDC_V1_11),\
|
||||
.hid.bCountryCode = USB_HID_NO_COUNTRY_CODE,\
|
||||
.hid.bNumDescriptors = USB_HID_NUM_DESC,\
|
||||
.hid.bRDescriptorType = USB_DT_HID_REPORT,\
|
||||
.hid.wDescriptorLength = LE16(sizeof(udi_hid_nkro_report_desc_t)),\
|
||||
.ep.bLength = sizeof(usb_ep_desc_t),\
|
||||
.ep.bDescriptorType = USB_DT_ENDPOINT,\
|
||||
.ep.bEndpointAddress = UDI_HID_NKRO_EP_IN | USB_EP_DIR_IN,\
|
||||
.ep.bmAttributes = USB_EP_TYPE_INTERRUPT,\
|
||||
.ep.wMaxPacketSize = LE16(UDI_HID_NKRO_EP_SIZE),\
|
||||
.ep.bInterval = NKRO_POLLING_INTERVAL,\
|
||||
}
|
||||
|
||||
//set report buffer
|
||||
extern uint8_t udi_hid_nkro_report_set;
|
||||
|
||||
//report buffer
|
||||
#define UDI_HID_NKRO_REPORT_SIZE 32
|
||||
extern uint8_t udi_hid_nkro_report[UDI_HID_NKRO_REPORT_SIZE];
|
||||
|
||||
COMPILER_PACK_RESET()
|
||||
|
||||
#endif //NKRO
|
||||
|
||||
// **********************************************************************
|
||||
// MOU Descriptor structure and content
|
||||
// **********************************************************************
|
||||
#ifdef MOU
|
||||
|
||||
COMPILER_PACK_SET(1)
|
||||
|
||||
typedef struct {
|
||||
usb_iface_desc_t iface;
|
||||
usb_hid_descriptor_t hid;
|
||||
usb_ep_desc_t ep;
|
||||
} udi_hid_mou_desc_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t array[77];//MOU PDS
|
||||
} udi_hid_mou_report_desc_t;
|
||||
|
||||
#define UDI_HID_MOU_DESC {\
|
||||
.iface.bLength = sizeof(usb_iface_desc_t),\
|
||||
.iface.bDescriptorType = USB_DT_INTERFACE,\
|
||||
.iface.bInterfaceNumber = MOUSE_INTERFACE,\
|
||||
.iface.bAlternateSetting = 0,\
|
||||
.iface.bNumEndpoints = 1,\
|
||||
.iface.bInterfaceClass = HID_CLASS,\
|
||||
.iface.bInterfaceSubClass = HID_SUB_CLASS_BOOT,\
|
||||
.iface.bInterfaceProtocol = HID_PROTOCOL_MOUSE,\
|
||||
.iface.iInterface = UDI_HID_MOU_STRING_ID,\
|
||||
.hid.bLength = sizeof(usb_hid_descriptor_t),\
|
||||
.hid.bDescriptorType = USB_DT_HID,\
|
||||
.hid.bcdHID = LE16(USB_HID_BDC_V1_11),\
|
||||
.hid.bCountryCode = USB_HID_NO_COUNTRY_CODE,\
|
||||
.hid.bNumDescriptors = USB_HID_NUM_DESC,\
|
||||
.hid.bRDescriptorType = USB_DT_HID_REPORT,\
|
||||
.hid.wDescriptorLength = LE16(sizeof(udi_hid_mou_report_desc_t)),\
|
||||
.ep.bLength = sizeof(usb_ep_desc_t),\
|
||||
.ep.bDescriptorType = USB_DT_ENDPOINT,\
|
||||
.ep.bEndpointAddress = UDI_HID_MOU_EP_IN | USB_EP_DIR_IN,\
|
||||
.ep.bmAttributes = USB_EP_TYPE_INTERRUPT,\
|
||||
.ep.wMaxPacketSize = LE16(UDI_HID_MOU_EP_SIZE),\
|
||||
.ep.bInterval = MOU_POLLING_INTERVAL,\
|
||||
}
|
||||
|
||||
//no set report buffer
|
||||
|
||||
//report buffer
|
||||
#define UDI_HID_MOU_REPORT_SIZE 5 //MOU PDS
|
||||
extern uint8_t udi_hid_mou_report[UDI_HID_MOU_REPORT_SIZE];
|
||||
|
||||
COMPILER_PACK_RESET()
|
||||
|
||||
#endif //MOU
|
||||
|
||||
// **********************************************************************
|
||||
// RAW Descriptor structure and content
|
||||
// **********************************************************************
|
||||
#ifdef RAW
|
||||
|
||||
COMPILER_PACK_SET(1)
|
||||
|
||||
typedef struct {
|
||||
usb_iface_desc_t iface;
|
||||
usb_hid_descriptor_t hid;
|
||||
usb_ep_desc_t ep_out;
|
||||
usb_ep_desc_t ep_in;
|
||||
} udi_hid_raw_desc_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t array[27];
|
||||
} udi_hid_raw_report_desc_t;
|
||||
|
||||
#define UDI_HID_RAW_DESC {\
|
||||
.iface.bLength = sizeof(usb_iface_desc_t),\
|
||||
.iface.bDescriptorType = USB_DT_INTERFACE,\
|
||||
.iface.bInterfaceNumber = RAW_INTERFACE,\
|
||||
.iface.bAlternateSetting = 0,\
|
||||
.iface.bNumEndpoints = 2,\
|
||||
.iface.bInterfaceClass = HID_CLASS,\
|
||||
.iface.bInterfaceSubClass = HID_SUB_CLASS_NOBOOT,\
|
||||
.iface.bInterfaceProtocol = HID_SUB_CLASS_NOBOOT,\
|
||||
.iface.iInterface = UDI_HID_RAW_STRING_ID,\
|
||||
.hid.bLength = sizeof(usb_hid_descriptor_t),\
|
||||
.hid.bDescriptorType = USB_DT_HID,\
|
||||
.hid.bcdHID = LE16(USB_HID_BDC_V1_11),\
|
||||
.hid.bCountryCode = USB_HID_NO_COUNTRY_CODE,\
|
||||
.hid.bNumDescriptors = USB_HID_NUM_DESC,\
|
||||
.hid.bRDescriptorType = USB_DT_HID_REPORT,\
|
||||
.hid.wDescriptorLength = LE16(sizeof(udi_hid_raw_report_desc_t)),\
|
||||
.ep_out.bLength = sizeof(usb_ep_desc_t),\
|
||||
.ep_out.bDescriptorType = USB_DT_ENDPOINT,\
|
||||
.ep_out.bEndpointAddress = UDI_HID_RAW_EP_OUT | USB_EP_DIR_OUT,\
|
||||
.ep_out.bmAttributes = USB_EP_TYPE_INTERRUPT,\
|
||||
.ep_out.wMaxPacketSize = LE16(RAW_EPSIZE),\
|
||||
.ep_out.bInterval = RAW_POLLING_INTERVAL,\
|
||||
.ep_in.bLength = sizeof(usb_ep_desc_t),\
|
||||
.ep_in.bDescriptorType = USB_DT_ENDPOINT,\
|
||||
.ep_in.bEndpointAddress = UDI_HID_RAW_EP_IN | USB_EP_DIR_IN,\
|
||||
.ep_in.bmAttributes = USB_EP_TYPE_INTERRUPT,\
|
||||
.ep_in.wMaxPacketSize = LE16(RAW_EPSIZE),\
|
||||
.ep_in.bInterval = RAW_POLLING_INTERVAL,\
|
||||
}
|
||||
|
||||
#define UDI_HID_RAW_REPORT_SIZE RAW_EPSIZE
|
||||
|
||||
extern uint8_t udi_hid_raw_report_set[UDI_HID_RAW_REPORT_SIZE];
|
||||
|
||||
//report buffer
|
||||
extern uint8_t udi_hid_raw_report[UDI_HID_RAW_REPORT_SIZE];
|
||||
|
||||
COMPILER_PACK_RESET()
|
||||
|
||||
#endif //RAW
|
||||
|
||||
// **********************************************************************
|
||||
// CON Descriptor structure and content
|
||||
// **********************************************************************
|
||||
#ifdef CON
|
||||
|
||||
COMPILER_PACK_SET(1)
|
||||
|
||||
typedef struct {
|
||||
usb_iface_desc_t iface;
|
||||
usb_hid_descriptor_t hid;
|
||||
usb_ep_desc_t ep_out;
|
||||
usb_ep_desc_t ep_in;
|
||||
} udi_hid_con_desc_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t array[34];
|
||||
} udi_hid_con_report_desc_t;
|
||||
|
||||
#define UDI_HID_CON_DESC {\
|
||||
.iface.bLength = sizeof(usb_iface_desc_t),\
|
||||
.iface.bDescriptorType = USB_DT_INTERFACE,\
|
||||
.iface.bInterfaceNumber = UDI_HID_CON_IFACE_NUMBER,\
|
||||
.iface.bAlternateSetting = 0,\
|
||||
.iface.bNumEndpoints = 2,\
|
||||
.iface.bInterfaceClass = HID_CLASS,\
|
||||
.iface.bInterfaceSubClass = HID_SUB_CLASS_NOBOOT,\
|
||||
.iface.bInterfaceProtocol = HID_SUB_CLASS_NOBOOT,\
|
||||
.iface.iInterface = UDI_HID_CON_STRING_ID,\
|
||||
.hid.bLength = sizeof(usb_hid_descriptor_t),\
|
||||
.hid.bDescriptorType = USB_DT_HID,\
|
||||
.hid.bcdHID = LE16(USB_HID_BDC_V1_11),\
|
||||
.hid.bCountryCode = USB_HID_NO_COUNTRY_CODE,\
|
||||
.hid.bNumDescriptors = USB_HID_NUM_DESC,\
|
||||
.hid.bRDescriptorType = USB_DT_HID_REPORT,\
|
||||
.hid.wDescriptorLength = LE16(sizeof(udi_hid_con_report_desc_t)),\
|
||||
.ep_out.bLength = sizeof(usb_ep_desc_t),\
|
||||
.ep_out.bDescriptorType = USB_DT_ENDPOINT,\
|
||||
.ep_out.bEndpointAddress = UDI_HID_CON_EP_OUT | USB_EP_DIR_OUT,\
|
||||
.ep_out.bmAttributes = USB_EP_TYPE_INTERRUPT,\
|
||||
.ep_out.wMaxPacketSize = LE16(CONSOLE_EPSIZE),\
|
||||
.ep_out.bInterval = CON_POLLING_INTERVAL,\
|
||||
.ep_in.bLength = sizeof(usb_ep_desc_t),\
|
||||
.ep_in.bDescriptorType = USB_DT_ENDPOINT,\
|
||||
.ep_in.bEndpointAddress = UDI_HID_CON_EP_IN | USB_EP_DIR_IN,\
|
||||
.ep_in.bmAttributes = USB_EP_TYPE_INTERRUPT,\
|
||||
.ep_in.wMaxPacketSize = LE16(CONSOLE_EPSIZE),\
|
||||
.ep_in.bInterval = CON_POLLING_INTERVAL,\
|
||||
}
|
||||
|
||||
#define UDI_HID_CON_REPORT_SIZE CONSOLE_EPSIZE
|
||||
|
||||
extern uint8_t udi_hid_con_report_set[UDI_HID_CON_REPORT_SIZE];
|
||||
|
||||
//report buffer
|
||||
extern uint8_t udi_hid_con_report[UDI_HID_CON_REPORT_SIZE];
|
||||
|
||||
COMPILER_PACK_RESET()
|
||||
|
||||
#endif //CON
|
||||
|
||||
// **********************************************************************
|
||||
// CDC Descriptor structure and content
|
||||
// **********************************************************************
|
||||
#ifdef CDC
|
||||
|
||||
COMPILER_PACK_SET(1)
|
||||
|
||||
typedef struct {
|
||||
uint8_t bFunctionLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDescriptorSubtype;
|
||||
le16_t bcdCDC;
|
||||
} usb_cdc_hdr_desc_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t bFunctionLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDescriptorSubtype;
|
||||
uint8_t bmCapabilities;
|
||||
uint8_t bDataInterface;
|
||||
} usb_cdc_call_mgmt_desc_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t bFunctionLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDescriptorSubtype;
|
||||
uint8_t bmCapabilities;
|
||||
} usb_cdc_acm_desc_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t bFunctionLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDescriptorSubtype;
|
||||
uint8_t bMasterInterface;
|
||||
uint8_t bSlaveInterface0;
|
||||
} usb_cdc_union_desc_t;
|
||||
|
||||
typedef struct {
|
||||
usb_association_desc_t iaface;
|
||||
usb_iface_desc_t iface_c;
|
||||
usb_cdc_hdr_desc_t fd;
|
||||
usb_cdc_call_mgmt_desc_t mfd;
|
||||
usb_cdc_acm_desc_t acmd;
|
||||
usb_cdc_union_desc_t ufd;
|
||||
usb_ep_desc_t ep_c;
|
||||
usb_iface_desc_t iface_d;
|
||||
usb_ep_desc_t ep_tx;
|
||||
usb_ep_desc_t ep_rx;
|
||||
} udi_cdc_desc_t;
|
||||
|
||||
#define CDC_DESCRIPTOR {\
|
||||
.iaface.bLength = sizeof(usb_association_desc_t),\
|
||||
.iaface.bDescriptorType = USB_DT_IAD,\
|
||||
.iaface.bFirstInterface = CDC_STATUS_INTERFACE,\
|
||||
.iaface.bInterfaceCount = 2,\
|
||||
.iaface.bFunctionClass = CDC_CLASS_DEVICE,\
|
||||
.iaface.bFunctionSubClass = CDC_SUBCLASS_ACM,\
|
||||
.iaface.bFunctionProtocol = CDC_PROTOCOL_V25TER,\
|
||||
.iaface.iFunction = 0,\
|
||||
.iface_c.bLength = sizeof(usb_iface_desc_t),\
|
||||
.iface_c.bDescriptorType = USB_DT_INTERFACE,\
|
||||
.iface_c.bInterfaceNumber = CDC_STATUS_INTERFACE,\
|
||||
.iface_c.bAlternateSetting = 0,\
|
||||
.iface_c.bNumEndpoints = 1,\
|
||||
.iface_c.bInterfaceClass = 0x02,\
|
||||
.iface_c.bInterfaceSubClass = 0x02,\
|
||||
.iface_c.bInterfaceProtocol = CDC_PROTOCOL_V25TER,\
|
||||
.iface_c.iInterface = 0,\
|
||||
.fd.bFunctionLength = sizeof(usb_cdc_hdr_desc_t),\
|
||||
.fd.bDescriptorType = CDC_CS_INTERFACE,\
|
||||
.fd.bDescriptorSubtype = CDC_SCS_HEADER,\
|
||||
.fd.bcdCDC = 0x0110,\
|
||||
.mfd.bFunctionLength = sizeof(usb_cdc_call_mgmt_desc_t),\
|
||||
.mfd.bDescriptorType = CDC_CS_INTERFACE,\
|
||||
.mfd.bDescriptorSubtype = CDC_SCS_CALL_MGMT,\
|
||||
.mfd.bmCapabilities = CDC_CALL_MGMT_SUPPORTED,\
|
||||
.mfd.bDataInterface = CDC_DATA_INTERFACE,\
|
||||
.acmd.bFunctionLength = sizeof(usb_cdc_acm_desc_t),\
|
||||
.acmd.bDescriptorType = CDC_CS_INTERFACE,\
|
||||
.acmd.bDescriptorSubtype = CDC_SCS_ACM,\
|
||||
.acmd.bmCapabilities = CDC_ACM_SUPPORT_LINE_REQUESTS,\
|
||||
.ufd.bFunctionLength = sizeof(usb_cdc_union_desc_t),\
|
||||
.ufd.bDescriptorType = CDC_CS_INTERFACE,\
|
||||
.ufd.bDescriptorSubtype = CDC_SCS_UNION,\
|
||||
.ufd.bMasterInterface = CDC_STATUS_INTERFACE,\
|
||||
.ufd.bSlaveInterface0 = CDC_DATA_INTERFACE,\
|
||||
.ep_c.bLength = sizeof(usb_ep_desc_t),\
|
||||
.ep_c.bDescriptorType = USB_DT_ENDPOINT,\
|
||||
.ep_c.bEndpointAddress = CDC_ACM_ENDPOINT | USB_EP_DIR_IN,\
|
||||
.ep_c.bmAttributes = USB_EP_TYPE_INTERRUPT,\
|
||||
.ep_c.wMaxPacketSize = LE16(CDC_ACM_SIZE),\
|
||||
.ep_c.bInterval = CDC_EP_INTERVAL_STATUS,\
|
||||
.iface_d.bLength = sizeof(usb_iface_desc_t),\
|
||||
.iface_d.bDescriptorType = USB_DT_INTERFACE,\
|
||||
.iface_d.bInterfaceNumber = CDC_DATA_INTERFACE,\
|
||||
.iface_d.bAlternateSetting = 0,\
|
||||
.iface_d.bNumEndpoints = 2,\
|
||||
.iface_d.bInterfaceClass = CDC_CLASS_DATA,\
|
||||
.iface_d.bInterfaceSubClass = 0,\
|
||||
.iface_d.bInterfaceProtocol = 0,\
|
||||
.iface_d.iInterface = 0,\
|
||||
.ep_rx.bLength = sizeof(usb_ep_desc_t),\
|
||||
.ep_rx.bDescriptorType = USB_DT_ENDPOINT,\
|
||||
.ep_rx.bEndpointAddress = CDC_RX_ENDPOINT | USB_EP_DIR_OUT,\
|
||||
.ep_rx.bmAttributes = USB_EP_TYPE_BULK,\
|
||||
.ep_rx.wMaxPacketSize = LE16(CDC_RX_SIZE),\
|
||||
.ep_rx.bInterval = CDC_EP_INTERVAL_DATA,\
|
||||
.ep_tx.bLength = sizeof(usb_ep_desc_t),\
|
||||
.ep_tx.bDescriptorType = USB_DT_ENDPOINT,\
|
||||
.ep_tx.bEndpointAddress = CDC_TX_ENDPOINT | USB_EP_DIR_IN,\
|
||||
.ep_tx.bmAttributes = USB_EP_TYPE_BULK,\
|
||||
.ep_tx.wMaxPacketSize = LE16(CDC_TX_SIZE),\
|
||||
.ep_tx.bInterval = CDC_EP_INTERVAL_DATA,\
|
||||
}
|
||||
|
||||
COMPILER_PACK_RESET()
|
||||
|
||||
#endif //CDC
|
||||
|
||||
// **********************************************************************
|
||||
// CONFIGURATION Descriptor structure and content
|
||||
// **********************************************************************
|
||||
COMPILER_PACK_SET(1)
|
||||
|
||||
typedef struct {
|
||||
usb_conf_desc_t conf;
|
||||
#ifdef KBD
|
||||
udi_hid_kbd_desc_t hid_kbd;
|
||||
#endif
|
||||
#ifdef MOU
|
||||
udi_hid_mou_desc_t hid_mou;
|
||||
#endif
|
||||
#ifdef EXK
|
||||
udi_hid_exk_desc_t hid_exk;
|
||||
#endif
|
||||
#ifdef RAW
|
||||
udi_hid_raw_desc_t hid_raw;
|
||||
#endif
|
||||
#ifdef CON
|
||||
udi_hid_con_desc_t hid_con;
|
||||
#endif
|
||||
#ifdef NKRO
|
||||
udi_hid_nkro_desc_t hid_nkro;
|
||||
#endif
|
||||
#ifdef MIDI
|
||||
udi_hid_midi_desc_t hid_midi;
|
||||
#endif
|
||||
#ifdef CDC
|
||||
udi_cdc_desc_t cdc_serial;
|
||||
#endif
|
||||
} udc_desc_t;
|
||||
|
||||
COMPILER_PACK_RESET()
|
||||
|
||||
#endif //_UDI_DEVICE_CONF_H_
|
32
tmk_core/protocol/arm_atsam/usb/udi_device_epsize.h
Normal file
32
tmk_core/protocol/arm_atsam/usb/udi_device_epsize.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
Copyright 2018 Massdrop Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _UDI_DEVICE_EPSIZE_H_
|
||||
#define _UDI_DEVICE_EPSIZE_H_
|
||||
|
||||
#define KEYBOARD_EPSIZE 8
|
||||
#define MOUSE_EPSIZE 8
|
||||
#define EXTRAKEY_EPSIZE 8
|
||||
#define RAW_EPSIZE 64
|
||||
#define CONSOLE_EPSIZE 32
|
||||
#define NKRO_EPSIZE 32
|
||||
#define MIDI_STREAM_EPSIZE 64
|
||||
#define CDC_NOTIFICATION_EPSIZE 8
|
||||
#define CDC_EPSIZE 16
|
||||
|
||||
#endif //_UDI_DEVICE_EPSIZE_H_
|
||||
|
162
tmk_core/protocol/arm_atsam/usb/udi_hid.c
Normal file
162
tmk_core/protocol/arm_atsam/usb/udi_hid.c
Normal file
|
@ -0,0 +1,162 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief USB Device Human Interface Device (HID) interface.
|
||||
*
|
||||
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
|
||||
#include "conf_usb.h"
|
||||
#include "usb_protocol.h"
|
||||
#include "udd.h"
|
||||
#include "udc.h"
|
||||
#include "udi_hid.h"
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup udi_hid_group
|
||||
* \defgroup udi_hid_group_internal Implementation of HID common library
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Send the specific descriptors requested by SETUP request
|
||||
*
|
||||
* \retval true if the descriptor is supported
|
||||
*/
|
||||
static bool udi_hid_reqstdifaceget_descriptor(uint8_t *report_desc);
|
||||
|
||||
bool udi_hid_setup( uint8_t *rate, uint8_t *protocol, uint8_t *report_desc, bool (*setup_report)(void) )
|
||||
{
|
||||
if (Udd_setup_is_in()) {
|
||||
// Requests Interface GET
|
||||
if (Udd_setup_type() == USB_REQ_TYPE_STANDARD) {
|
||||
// Requests Standard Interface Get
|
||||
switch (udd_g_ctrlreq.req.bRequest) {
|
||||
|
||||
case USB_REQ_GET_DESCRIPTOR:
|
||||
return udi_hid_reqstdifaceget_descriptor(report_desc);
|
||||
}
|
||||
}
|
||||
if (Udd_setup_type() == USB_REQ_TYPE_CLASS) {
|
||||
// Requests Class Interface Get
|
||||
switch (udd_g_ctrlreq.req.bRequest) {
|
||||
|
||||
case USB_REQ_HID_GET_REPORT:
|
||||
return setup_report();
|
||||
|
||||
case USB_REQ_HID_GET_IDLE:
|
||||
udd_g_ctrlreq.payload = rate;
|
||||
udd_g_ctrlreq.payload_size = 1;
|
||||
return true;
|
||||
|
||||
case USB_REQ_HID_GET_PROTOCOL:
|
||||
udd_g_ctrlreq.payload = protocol;
|
||||
udd_g_ctrlreq.payload_size = 1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Udd_setup_is_out()) {
|
||||
// Requests Interface SET
|
||||
if (Udd_setup_type() == USB_REQ_TYPE_CLASS) {
|
||||
// Requests Class Interface Set
|
||||
switch (udd_g_ctrlreq.req.bRequest) {
|
||||
|
||||
case USB_REQ_HID_SET_REPORT:
|
||||
return setup_report();
|
||||
|
||||
case USB_REQ_HID_SET_IDLE:
|
||||
*rate = udd_g_ctrlreq.req.wValue >> 8;
|
||||
return true;
|
||||
|
||||
case USB_REQ_HID_SET_PROTOCOL:
|
||||
if (0 != udd_g_ctrlreq.req.wLength)
|
||||
return false;
|
||||
*protocol = udd_g_ctrlreq.req.wValue;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false; // Request not supported
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
//------- Internal routines
|
||||
|
||||
static bool udi_hid_reqstdifaceget_descriptor(uint8_t *report_desc)
|
||||
{
|
||||
usb_hid_descriptor_t UDC_DESC_STORAGE *ptr_hid_desc;
|
||||
|
||||
// Get the USB descriptor which is located after the interface descriptor
|
||||
// This descriptor must be the HID descriptor
|
||||
ptr_hid_desc = (usb_hid_descriptor_t UDC_DESC_STORAGE *) ((uint8_t *)
|
||||
udc_get_interface_desc() + sizeof(usb_iface_desc_t));
|
||||
if (USB_DT_HID != ptr_hid_desc->bDescriptorType)
|
||||
return false;
|
||||
|
||||
// The SETUP request can ask for:
|
||||
// - an USB_DT_HID descriptor
|
||||
// - or USB_DT_HID_REPORT descriptor
|
||||
// - or USB_DT_HID_PHYSICAL descriptor
|
||||
if (USB_DT_HID == (uint8_t) (udd_g_ctrlreq.req.wValue >> 8)) {
|
||||
// USB_DT_HID descriptor requested then send it
|
||||
udd_g_ctrlreq.payload = (uint8_t *) ptr_hid_desc;
|
||||
udd_g_ctrlreq.payload_size =
|
||||
min(udd_g_ctrlreq.req.wLength,
|
||||
ptr_hid_desc->bLength);
|
||||
return true;
|
||||
}
|
||||
// The HID_X descriptor requested must correspond to report type
|
||||
// included in the HID descriptor
|
||||
if (ptr_hid_desc->bRDescriptorType ==
|
||||
(uint8_t) (udd_g_ctrlreq.req.wValue >> 8)) {
|
||||
// Send HID Report descriptor given by high level
|
||||
udd_g_ctrlreq.payload = report_desc;
|
||||
udd_g_ctrlreq.payload_size =
|
||||
min(udd_g_ctrlreq.req.wLength,
|
||||
le16_to_cpu(ptr_hid_desc->wDescriptorLength));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//@}
|
85
tmk_core/protocol/arm_atsam/usb/udi_hid.h
Normal file
85
tmk_core/protocol/arm_atsam/usb/udi_hid.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief USB Device Human Interface Device (HID) interface definitions.
|
||||
*
|
||||
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
|
||||
#ifndef _UDI_HID_H_
|
||||
#define _UDI_HID_H_
|
||||
|
||||
#include "conf_usb.h"
|
||||
#include "usb_protocol.h"
|
||||
#include "usb_protocol_hid.h"
|
||||
#include "udd.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \ingroup udi_group
|
||||
* \defgroup udi_hid_group USB Device Interface (UDI) for Human Interface Device (HID)
|
||||
*
|
||||
* Common library for all Human Interface Device (HID) implementation.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Decode HID setup request
|
||||
*
|
||||
* \param rate Pointer on rate of current HID interface
|
||||
* \param protocol Pointer on protocol of current HID interface
|
||||
* \param report_desc Pointer on report descriptor of current HID interface
|
||||
* \param set_report Pointer on set_report callback of current HID interface
|
||||
*
|
||||
* \return \c 1 if function was successfully done, otherwise \c 0.
|
||||
*/
|
||||
bool udi_hid_setup( uint8_t *rate, uint8_t *protocol, uint8_t *report_desc, bool (*setup_report)(void) );
|
||||
|
||||
//@}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // _UDI_HID_H_
|
992
tmk_core/protocol/arm_atsam/usb/udi_hid_kbd.c
Normal file
992
tmk_core/protocol/arm_atsam/usb/udi_hid_kbd.c
Normal file
|
@ -0,0 +1,992 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief USB Device Human Interface Device (HID) keyboard interface.
|
||||
*
|
||||
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
|
||||
#include "samd51j18a.h"
|
||||
#include "d51_util.h"
|
||||
#include "conf_usb.h"
|
||||
#include "usb_protocol.h"
|
||||
#include "udd.h"
|
||||
#include "udc.h"
|
||||
#include "udi_device_conf.h"
|
||||
#include "udi_hid.h"
|
||||
#include "udi_hid_kbd.h"
|
||||
#include <string.h>
|
||||
#include "report.h"
|
||||
|
||||
//***************************************************************************
|
||||
// KBD
|
||||
//***************************************************************************
|
||||
#ifdef KBD
|
||||
|
||||
bool udi_hid_kbd_enable(void);
|
||||
void udi_hid_kbd_disable(void);
|
||||
bool udi_hid_kbd_setup(void);
|
||||
uint8_t udi_hid_kbd_getsetting(void);
|
||||
|
||||
UDC_DESC_STORAGE udi_api_t udi_api_hid_kbd = {
|
||||
.enable = (bool(*)(void))udi_hid_kbd_enable,
|
||||
.disable = (void (*)(void))udi_hid_kbd_disable,
|
||||
.setup = (bool(*)(void))udi_hid_kbd_setup,
|
||||
.getsetting = (uint8_t(*)(void))udi_hid_kbd_getsetting,
|
||||
.sof_notify = NULL,
|
||||
};
|
||||
|
||||
COMPILER_WORD_ALIGNED
|
||||
static uint8_t udi_hid_kbd_rate;
|
||||
|
||||
COMPILER_WORD_ALIGNED
|
||||
static uint8_t udi_hid_kbd_protocol;
|
||||
|
||||
COMPILER_WORD_ALIGNED
|
||||
uint8_t udi_hid_kbd_report_set;
|
||||
|
||||
bool udi_hid_kbd_b_report_valid;
|
||||
|
||||
COMPILER_WORD_ALIGNED
|
||||
uint8_t udi_hid_kbd_report[UDI_HID_KBD_REPORT_SIZE];
|
||||
|
||||
volatile bool udi_hid_kbd_b_report_trans_ongoing;
|
||||
|
||||
COMPILER_WORD_ALIGNED
|
||||
static uint8_t udi_hid_kbd_report_trans[UDI_HID_KBD_REPORT_SIZE];
|
||||
|
||||
COMPILER_WORD_ALIGNED
|
||||
UDC_DESC_STORAGE udi_hid_kbd_report_desc_t udi_hid_kbd_report_desc = {
|
||||
{
|
||||
0x05, 0x01, // Usage Page (Generic Desktop)
|
||||
0x09, 0x06, // Usage (Keyboard)
|
||||
0xA1, 0x01, // Collection (Application)
|
||||
0x05, 0x07, // Usage Page (Keyboard)
|
||||
0x19, 0xE0, // Usage Minimum (224)
|
||||
0x29, 0xE7, // Usage Maximum (231)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x25, 0x01, // Logical Maximum (1)
|
||||
0x75, 0x01, // Report Size (1)
|
||||
0x95, 0x08, // Report Count (8)
|
||||
0x81, 0x02, // Input (Data, Variable, Absolute)
|
||||
0x81, 0x01, // Input (Constant)
|
||||
0x19, 0x00, // Usage Minimum (0)
|
||||
0x29, 0x65, // Usage Maximum (101)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x25, 0x65, // Logical Maximum (101)
|
||||
0x75, 0x08, // Report Size (8)
|
||||
0x95, 0x06, // Report Count (6)
|
||||
0x81, 0x00, // Input (Data, Array)
|
||||
0x05, 0x08, // Usage Page (LED)
|
||||
0x19, 0x01, // Usage Minimum (1)
|
||||
0x29, 0x05, // Usage Maximum (5)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x25, 0x01, // Logical Maximum (1)
|
||||
0x75, 0x01, // Report Size (1)
|
||||
0x95, 0x05, // Report Count (5)
|
||||
0x91, 0x02, // Output (Data, Variable, Absolute)
|
||||
0x95, 0x03, // Report Count (3)
|
||||
0x91, 0x01, // Output (Constant)
|
||||
0xC0 // End Collection
|
||||
}
|
||||
};
|
||||
|
||||
static bool udi_hid_kbd_setreport(void);
|
||||
|
||||
static void udi_hid_kbd_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep);
|
||||
|
||||
static void udi_hid_kbd_setreport_valid(void);
|
||||
|
||||
bool udi_hid_kbd_enable(void)
|
||||
{
|
||||
// Initialize internal values
|
||||
udi_hid_kbd_rate = 0;
|
||||
udi_hid_kbd_protocol = 0;
|
||||
udi_hid_kbd_b_report_trans_ongoing = false;
|
||||
memset(udi_hid_kbd_report, 0, UDI_HID_KBD_REPORT_SIZE);
|
||||
udi_hid_kbd_b_report_valid = false;
|
||||
return UDI_HID_KBD_ENABLE_EXT();
|
||||
}
|
||||
|
||||
void udi_hid_kbd_disable(void)
|
||||
{
|
||||
UDI_HID_KBD_DISABLE_EXT();
|
||||
}
|
||||
|
||||
bool udi_hid_kbd_setup(void)
|
||||
{
|
||||
return udi_hid_setup(&udi_hid_kbd_rate,
|
||||
&udi_hid_kbd_protocol,
|
||||
(uint8_t *) &udi_hid_kbd_report_desc,
|
||||
udi_hid_kbd_setreport);
|
||||
}
|
||||
|
||||
uint8_t udi_hid_kbd_getsetting(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool udi_hid_kbd_setreport(void)
|
||||
{
|
||||
if ((USB_HID_REPORT_TYPE_OUTPUT == (udd_g_ctrlreq.req.wValue >> 8))
|
||||
&& (0 == (0xFF & udd_g_ctrlreq.req.wValue))
|
||||
&& (1 == udd_g_ctrlreq.req.wLength)) {
|
||||
// Report OUT type on report ID 0 from USB Host
|
||||
udd_g_ctrlreq.payload = &udi_hid_kbd_report_set;
|
||||
udd_g_ctrlreq.callback = udi_hid_kbd_setreport_valid;
|
||||
udd_g_ctrlreq.payload_size = 1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool udi_hid_kbd_send_report(void)
|
||||
{
|
||||
if (!main_b_kbd_enable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (udi_hid_kbd_b_report_trans_ongoing) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(udi_hid_kbd_report_trans, udi_hid_kbd_report, UDI_HID_KBD_REPORT_SIZE);
|
||||
udi_hid_kbd_b_report_valid = false;
|
||||
udi_hid_kbd_b_report_trans_ongoing =
|
||||
udd_ep_run(UDI_HID_KBD_EP_IN | USB_EP_DIR_IN,
|
||||
false,
|
||||
udi_hid_kbd_report_trans,
|
||||
UDI_HID_KBD_REPORT_SIZE,
|
||||
udi_hid_kbd_report_sent);
|
||||
|
||||
return udi_hid_kbd_b_report_trans_ongoing;
|
||||
}
|
||||
|
||||
static void udi_hid_kbd_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep)
|
||||
{
|
||||
UNUSED(status);
|
||||
UNUSED(nb_sent);
|
||||
UNUSED(ep);
|
||||
udi_hid_kbd_b_report_trans_ongoing = false;
|
||||
if (udi_hid_kbd_b_report_valid) {
|
||||
udi_hid_kbd_send_report();
|
||||
}
|
||||
}
|
||||
|
||||
static void udi_hid_kbd_setreport_valid(void)
|
||||
{
|
||||
//UDI_HID_KBD_CHANGE_LED(udi_hid_kbd_report_set);
|
||||
}
|
||||
|
||||
#endif //KBD
|
||||
|
||||
//********************************************************************************************
|
||||
// NKRO Keyboard
|
||||
//********************************************************************************************
|
||||
#ifdef NKRO
|
||||
|
||||
bool udi_hid_nkro_enable(void);
|
||||
void udi_hid_nkro_disable(void);
|
||||
bool udi_hid_nkro_setup(void);
|
||||
uint8_t udi_hid_nkro_getsetting(void);
|
||||
|
||||
UDC_DESC_STORAGE udi_api_t udi_api_hid_nkro = {
|
||||
.enable = (bool(*)(void))udi_hid_nkro_enable,
|
||||
.disable = (void (*)(void))udi_hid_nkro_disable,
|
||||
.setup = (bool(*)(void))udi_hid_nkro_setup,
|
||||
.getsetting = (uint8_t(*)(void))udi_hid_nkro_getsetting,
|
||||
.sof_notify = NULL,
|
||||
};
|
||||
|
||||
COMPILER_WORD_ALIGNED
|
||||
static uint8_t udi_hid_nkro_rate;
|
||||
|
||||
COMPILER_WORD_ALIGNED
|
||||
static uint8_t udi_hid_nkro_protocol;
|
||||
|
||||
COMPILER_WORD_ALIGNED
|
||||
uint8_t udi_hid_nkro_report_set;
|
||||
|
||||
bool udi_hid_nkro_b_report_valid;
|
||||
|
||||
COMPILER_WORD_ALIGNED
|
||||
uint8_t udi_hid_nkro_report[UDI_HID_NKRO_REPORT_SIZE];
|
||||
|
||||
volatile bool udi_hid_nkro_b_report_trans_ongoing;
|
||||
|
||||
COMPILER_WORD_ALIGNED
|
||||
static uint8_t udi_hid_nkro_report_trans[UDI_HID_NKRO_REPORT_SIZE];
|
||||
|
||||
COMPILER_WORD_ALIGNED
|
||||
UDC_DESC_STORAGE udi_hid_nkro_report_desc_t udi_hid_nkro_report_desc = {
|
||||
{
|
||||
0x05, 0x01, // Usage Page (Generic Desktop),
|
||||
0x09, 0x06, // Usage (Keyboard),
|
||||
0xA1, 0x01, // Collection (Application) - Keyboard,
|
||||
|
||||
//Mods
|
||||
0x75, 0x01, // Report Size (1),
|
||||
0x95, 0x08, // Report Count (8),
|
||||
0x15, 0x00, // Logical Minimum (0),
|
||||
0x25, 0x01, // Logical Maximum (1),
|
||||
0x05, 0x07, // Usage Page (Key Codes),
|
||||
0x19, 0xE0, // Usage Minimum (224),
|
||||
0x29, 0xE7, // Usage Maximum (231),
|
||||
0x81, 0x02, // Input (Data, Variable, Absolute),
|
||||
|
||||
//LED Report
|
||||
0x75, 0x01, // Report Size (1),
|
||||
0x95, 0x05, // Report Count (5),
|
||||
0x05, 0x08, // Usage Page (LEDs),
|
||||
0x19, 0x01, // Usage Minimum (1),
|
||||
0x29, 0x05, // Usage Maximum (5),
|
||||
0x91, 0x02, // Output (Data, Variable, Absolute),
|
||||
|
||||
//LED Report Padding
|
||||
0x75, 0x03, // Report Size (3),
|
||||
0x95, 0x01, // Report Count (1),
|
||||
0x91, 0x03, // Output (Constant),
|
||||
|
||||
//Main keys
|
||||
0x75, 0x01, // Report Size (1),
|
||||
0x95, 0xF8, // Report Count (248),
|
||||
0x15, 0x00, // Logical Minimum (0),
|
||||
0x25, 0x01, // Logical Maximum (1),
|
||||
0x05, 0x07, // Usage Page (Key Codes),
|
||||
0x19, 0x00, // Usage Minimum (0),
|
||||
0x29, 0xF7, // Usage Maximum (247),
|
||||
0x81, 0x02, // Input (Data, Variable, Absolute, Bitfield),
|
||||
0xc0, // End Collection - Keyboard
|
||||
}
|
||||
};
|
||||
|
||||
static bool udi_hid_nkro_setreport(void);
|
||||
static void udi_hid_nkro_setreport_valid(void);
|
||||
static void udi_hid_nkro_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep);
|
||||
|
||||
bool udi_hid_nkro_enable(void)
|
||||
{
|
||||
// Initialize internal values
|
||||
udi_hid_nkro_rate = 0;
|
||||
udi_hid_nkro_protocol = 0;
|
||||
udi_hid_nkro_b_report_trans_ongoing = false;
|
||||
memset(udi_hid_nkro_report, 0, UDI_HID_NKRO_REPORT_SIZE);
|
||||
udi_hid_nkro_b_report_valid = false;
|
||||
return UDI_HID_NKRO_ENABLE_EXT();
|
||||
}
|
||||
|
||||
void udi_hid_nkro_disable(void)
|
||||
{
|
||||
UDI_HID_NKRO_DISABLE_EXT();
|
||||
}
|
||||
|
||||
bool udi_hid_nkro_setup(void)
|
||||
{
|
||||
return udi_hid_setup(&udi_hid_nkro_rate,
|
||||
&udi_hid_nkro_protocol,
|
||||
(uint8_t *) &udi_hid_nkro_report_desc,
|
||||
udi_hid_nkro_setreport);
|
||||
}
|
||||
|
||||
uint8_t udi_hid_nkro_getsetting(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//keyboard receives LED report here
|
||||
static bool udi_hid_nkro_setreport(void)
|
||||
{
|
||||
if ((USB_HID_REPORT_TYPE_OUTPUT == (udd_g_ctrlreq.req.wValue >> 8))
|
||||
&& (0 == (0xFF & udd_g_ctrlreq.req.wValue))
|
||||
&& (1 == udd_g_ctrlreq.req.wLength)) {
|
||||
// Report OUT type on report ID 0 from USB Host
|
||||
udd_g_ctrlreq.payload = &udi_hid_nkro_report_set;
|
||||
udd_g_ctrlreq.callback = udi_hid_nkro_setreport_valid; //must call routine to transform setreport to LED state
|
||||
udd_g_ctrlreq.payload_size = 1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool udi_hid_nkro_send_report(void)
|
||||
{
|
||||
if (!main_b_nkro_enable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (udi_hid_nkro_b_report_trans_ongoing) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(udi_hid_nkro_report_trans, udi_hid_nkro_report, UDI_HID_NKRO_REPORT_SIZE);
|
||||
udi_hid_nkro_b_report_valid = false;
|
||||
udi_hid_nkro_b_report_trans_ongoing =
|
||||
udd_ep_run(UDI_HID_NKRO_EP_IN | USB_EP_DIR_IN,
|
||||
false,
|
||||
udi_hid_nkro_report_trans,
|
||||
UDI_HID_NKRO_REPORT_SIZE,
|
||||
udi_hid_nkro_report_sent);
|
||||
|
||||
return udi_hid_nkro_b_report_trans_ongoing;
|
||||
}
|
||||
|
||||
static void udi_hid_nkro_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep)
|
||||
{
|
||||
UNUSED(status);
|
||||
UNUSED(nb_sent);
|
||||
UNUSED(ep);
|
||||
udi_hid_nkro_b_report_trans_ongoing = false;
|
||||
if (udi_hid_nkro_b_report_valid) {
|
||||
udi_hid_nkro_send_report();
|
||||
}
|
||||
}
|
||||
|
||||
static void udi_hid_nkro_setreport_valid(void)
|
||||
{
|
||||
//UDI_HID_NKRO_CHANGE_LED(udi_hid_nkro_report_set);
|
||||
}
|
||||
|
||||
#endif //NKRO
|
||||
|
||||
//********************************************************************************************
|
||||
// EXK (extra-keys) SYS-CTRL Keyboard
|
||||
//********************************************************************************************
|
||||
#ifdef EXK
|
||||
|
||||
bool udi_hid_exk_enable(void);
|
||||
void udi_hid_exk_disable(void);
|
||||
bool udi_hid_exk_setup(void);
|
||||
uint8_t udi_hid_exk_getsetting(void);
|
||||
|
||||
UDC_DESC_STORAGE udi_api_t udi_api_hid_exk = {
|
||||
.enable = (bool(*)(void))udi_hid_exk_enable,
|
||||
.disable = (void (*)(void))udi_hid_exk_disable,
|
||||
.setup = (bool(*)(void))udi_hid_exk_setup,
|
||||
.getsetting = (uint8_t(*)(void))udi_hid_exk_getsetting,
|
||||
.sof_notify = NULL,
|
||||
};
|
||||
|
||||
COMPILER_WORD_ALIGNED
|
||||
static uint8_t udi_hid_exk_rate;
|
||||
|
||||
COMPILER_WORD_ALIGNED
|
||||
static uint8_t udi_hid_exk_protocol;
|
||||
|
||||
COMPILER_WORD_ALIGNED
|
||||
uint8_t udi_hid_exk_report_set;
|
||||
|
||||
bool udi_hid_exk_b_report_valid;
|
||||
|
||||
COMPILER_WORD_ALIGNED
|
||||
udi_hid_exk_report_t udi_hid_exk_report;
|
||||
|
||||
static bool udi_hid_exk_b_report_trans_ongoing;
|
||||
|
||||
COMPILER_WORD_ALIGNED
|
||||
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 = {
|
||||
{
|
||||
// System Control Collection (8 bits)
|
||||
|
||||
0x05, 0x01, // Usage Page (Generic Desktop),
|
||||
0x09, 0x80, // Usage (System Control),
|
||||
0xA1, 0x01, // Collection (Application),
|
||||
0x85, REPORT_ID_SYSTEM, // Report ID (2) (System),
|
||||
0x16, 0x01, 0x00, // Logical Minimum (1),
|
||||
0x26, 0x03, 0x00, // Logical Maximum (3),
|
||||
0x1A, 0x81, 0x00, // Usage Minimum (81) (System Power Down),
|
||||
0x2A, 0x83, 0x00, // Usage Maximum (83) (System Wake Up),
|
||||
0x75, 0x10, // Report Size (16),
|
||||
0x95, 0x01, // Report Count (1),
|
||||
0x81, 0x00, // Input (Data, Array),
|
||||
0xC0, // End Collection - System Control
|
||||
|
||||
// Consumer Control Collection - Media Keys (16 bits)
|
||||
|
||||
0x05, 0x0C, // Usage Page (Consumer),
|
||||
0x09, 0x01, // Usage (Consumer Control),
|
||||
0xA1, 0x01, // Collection (Application),
|
||||
0x85, REPORT_ID_CONSUMER, // Report ID (3) (Consumer),
|
||||
0x16, 0x01, 0x00, // Logical Minimum (1),
|
||||
0x26, 0x9C, 0x02, // Logical Maximum (668),
|
||||
0x1A, 0x01, 0x00, // Usage Minimum (1),
|
||||
0x2A, 0x9C, 0x02, // Usage Maximum (668),
|
||||
0x75, 0x10, // Report Size (16),
|
||||
0x95, 0x01, // Report Count (1),
|
||||
0x81, 0x00, // Input (Data, Array),
|
||||
0xC0, // End Collection - Consumer Control
|
||||
}
|
||||
};
|
||||
|
||||
static bool udi_hid_exk_setreport(void);
|
||||
|
||||
static void udi_hid_exk_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep);
|
||||
|
||||
static void udi_hid_exk_setreport_valid(void);
|
||||
|
||||
bool udi_hid_exk_enable(void)
|
||||
{
|
||||
// Initialize internal values
|
||||
udi_hid_exk_rate = 0;
|
||||
udi_hid_exk_protocol = 0;
|
||||
udi_hid_exk_b_report_trans_ongoing = false;
|
||||
memset(udi_hid_exk_report.raw, 0, UDI_HID_EXK_REPORT_SIZE);
|
||||
udi_hid_exk_b_report_valid = false;
|
||||
return UDI_HID_EXK_ENABLE_EXT();
|
||||
}
|
||||
|
||||
void udi_hid_exk_disable(void)
|
||||
{
|
||||
UDI_HID_EXK_DISABLE_EXT();
|
||||
}
|
||||
|
||||
bool udi_hid_exk_setup(void)
|
||||
{
|
||||
return udi_hid_setup(&udi_hid_exk_rate,
|
||||
&udi_hid_exk_protocol,
|
||||
(uint8_t *) &udi_hid_exk_report_desc,
|
||||
udi_hid_exk_setreport);
|
||||
}
|
||||
|
||||
uint8_t udi_hid_exk_getsetting(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool udi_hid_exk_setreport(void)
|
||||
{
|
||||
if ((USB_HID_REPORT_TYPE_OUTPUT == (udd_g_ctrlreq.req.wValue >> 8))
|
||||
&& (0 == (0xFF & udd_g_ctrlreq.req.wValue))
|
||||
&& (1 == udd_g_ctrlreq.req.wLength)) {
|
||||
// Report OUT type on report ID 0 from USB Host
|
||||
udd_g_ctrlreq.payload = &udi_hid_exk_report_set;
|
||||
udd_g_ctrlreq.callback = udi_hid_exk_setreport_valid;
|
||||
udd_g_ctrlreq.payload_size = 1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool udi_hid_exk_send_report(void)
|
||||
{
|
||||
if (!main_b_exk_enable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (udi_hid_exk_b_report_trans_ongoing) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(udi_hid_exk_report_trans, udi_hid_exk_report.raw, UDI_HID_EXK_REPORT_SIZE);
|
||||
udi_hid_exk_b_report_valid = false;
|
||||
udi_hid_exk_b_report_trans_ongoing =
|
||||
udd_ep_run(UDI_HID_EXK_EP_IN | USB_EP_DIR_IN,
|
||||
false,
|
||||
udi_hid_exk_report_trans,
|
||||
UDI_HID_EXK_REPORT_SIZE,
|
||||
udi_hid_exk_report_sent);
|
||||
|
||||
return udi_hid_exk_b_report_trans_ongoing;
|
||||
}
|
||||
|
||||
static void udi_hid_exk_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep)
|
||||
{
|
||||
UNUSED(status);
|
||||
UNUSED(nb_sent);
|
||||
UNUSED(ep);
|
||||
udi_hid_exk_b_report_trans_ongoing = false;
|
||||
if (udi_hid_exk_b_report_valid) {
|
||||
udi_hid_exk_send_report();
|
||||
}
|
||||
}
|
||||
|
||||
static void udi_hid_exk_setreport_valid(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endif //EXK
|
||||
|
||||
//********************************************************************************************
|
||||
// MOU Mouse
|
||||
//********************************************************************************************
|
||||
#ifdef MOU
|
||||
|
||||
bool udi_hid_mou_enable(void);
|
||||
void udi_hid_mou_disable(void);
|
||||
bool udi_hid_mou_setup(void);
|
||||
uint8_t udi_hid_mou_getsetting(void);
|
||||
|
||||
UDC_DESC_STORAGE udi_api_t udi_api_hid_mou = {
|
||||
.enable = (bool(*)(void))udi_hid_mou_enable,
|
||||
.disable = (void (*)(void))udi_hid_mou_disable,
|
||||
.setup = (bool(*)(void))udi_hid_mou_setup,
|
||||
.getsetting = (uint8_t(*)(void))udi_hid_mou_getsetting,
|
||||
.sof_notify = NULL,
|
||||
};
|
||||
|
||||
COMPILER_WORD_ALIGNED
|
||||
static uint8_t udi_hid_mou_rate;
|
||||
|
||||
COMPILER_WORD_ALIGNED
|
||||
static uint8_t udi_hid_mou_protocol;
|
||||
|
||||
//COMPILER_WORD_ALIGNED
|
||||
//uint8_t udi_hid_mou_report_set; //No set report
|
||||
|
||||
bool udi_hid_mou_b_report_valid;
|
||||
|
||||
COMPILER_WORD_ALIGNED
|
||||
uint8_t udi_hid_mou_report[UDI_HID_MOU_REPORT_SIZE];
|
||||
|
||||
static bool udi_hid_mou_b_report_trans_ongoing;
|
||||
|
||||
COMPILER_WORD_ALIGNED
|
||||
static uint8_t udi_hid_mou_report_trans[UDI_HID_MOU_REPORT_SIZE];
|
||||
|
||||
COMPILER_WORD_ALIGNED
|
||||
UDC_DESC_STORAGE udi_hid_mou_report_desc_t udi_hid_mou_report_desc = {
|
||||
{
|
||||
0x05, 0x01, // Usage Page (Generic Desktop),
|
||||
0x09, 0x02, // Usage (Mouse),
|
||||
0xA1, 0x01, // Collection (Application),
|
||||
0x09, 0x01, // Usage (Pointer),
|
||||
0xA1, 0x00, // Collection (Physical),
|
||||
0x05, 0x09, // Usage Page (Buttons),
|
||||
0x19, 0x01, // Usage Minimum (01),
|
||||
0x29, 0x05, // Usage Maximun (05),
|
||||
0x15, 0x00, // Logical Minimum (0),
|
||||
0x25, 0x01, // Logical Maximum (1),
|
||||
0x95, 0x05, // Report Count (5),
|
||||
0x75, 0x01, // Report Size (1),
|
||||
0x81, 0x02, // Input (Data, Variable, Absolute), ;5 button bits
|
||||
0x95, 0x01, // Report Count (1),
|
||||
0x75, 0x03, // Report Size (3),
|
||||
0x81, 0x01, // Input (Constant), ;3 bit padding,
|
||||
|
||||
0x05, 0x01, // Usage Page (Generic Desktop),
|
||||
0x09, 0x30, // Usage (X),
|
||||
0x09, 0x31, // Usage (Y),
|
||||
0x15, 0x81, // Logical Minimum (-127),
|
||||
0x25, 0x7F, // Logical Maximum (127),
|
||||
0x95, 0x02, // Report Count (2),
|
||||
0x75, 0x08, // Report Size (8),
|
||||
0x81, 0x06, // Input (Data, Variable, Relative), ;2 position bytes (X & Y),
|
||||
|
||||
0x09, 0x38, // Usage (Wheel),
|
||||
0x15, 0x81, // Logical Minimum (-127),
|
||||
0x25, 0x7F, // Logical Maximum (127),
|
||||
0x95, 0x01, // Report Count (1),
|
||||
0x75, 0x08, // Report Size (8),
|
||||
0x81, 0x06, // Input (Data, Variable, Relative),
|
||||
|
||||
0x05, 0x0C, // Usage Page (Consumer),
|
||||
0x0A, 0x38, 0x02, // Usage (AC Pan (Horizontal wheel)),
|
||||
0x15, 0x81, // Logical Minimum (-127),
|
||||
0x25, 0x7F, // Logical Maximum (127),
|
||||
0x95, 0x01, // Report Count (1),
|
||||
0x75, 0x08, // Report Size (8),
|
||||
0x81, 0x06, // Input (Data, Variable, Relative),
|
||||
|
||||
0xC0, // End Collection,
|
||||
0xC0, // End Collection
|
||||
}
|
||||
};
|
||||
|
||||
static void udi_hid_mou_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep);
|
||||
|
||||
bool udi_hid_mou_enable(void)
|
||||
{
|
||||
// Initialize internal values
|
||||
udi_hid_mou_rate = 0;
|
||||
udi_hid_mou_protocol = 0;
|
||||
udi_hid_mou_b_report_trans_ongoing = false;
|
||||
memset(udi_hid_mou_report, 0, UDI_HID_MOU_REPORT_SIZE);
|
||||
udi_hid_mou_b_report_valid = false;
|
||||
return UDI_HID_MOU_ENABLE_EXT();
|
||||
}
|
||||
|
||||
void udi_hid_mou_disable(void)
|
||||
{
|
||||
UDI_HID_MOU_DISABLE_EXT();
|
||||
}
|
||||
|
||||
bool udi_hid_mou_setup(void)
|
||||
{
|
||||
return udi_hid_setup(&udi_hid_mou_rate,
|
||||
&udi_hid_mou_protocol,
|
||||
(uint8_t *) &udi_hid_mou_report_desc,
|
||||
NULL);
|
||||
}
|
||||
|
||||
uint8_t udi_hid_mou_getsetting(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool udi_hid_mou_send_report(void)
|
||||
{
|
||||
if (!main_b_mou_enable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (udi_hid_mou_b_report_trans_ongoing) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(udi_hid_mou_report_trans, udi_hid_mou_report, UDI_HID_MOU_REPORT_SIZE);
|
||||
udi_hid_mou_b_report_valid = false;
|
||||
udi_hid_mou_b_report_trans_ongoing =
|
||||
udd_ep_run(UDI_HID_MOU_EP_IN | USB_EP_DIR_IN,
|
||||
false,
|
||||
udi_hid_mou_report_trans,
|
||||
UDI_HID_MOU_REPORT_SIZE,
|
||||
udi_hid_mou_report_sent);
|
||||
|
||||
return udi_hid_mou_b_report_trans_ongoing;
|
||||
}
|
||||
|
||||
static void udi_hid_mou_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep)
|
||||
{
|
||||
UNUSED(status);
|
||||
UNUSED(nb_sent);
|
||||
UNUSED(ep);
|
||||
udi_hid_mou_b_report_trans_ongoing = false;
|
||||
if (udi_hid_mou_b_report_valid) {
|
||||
udi_hid_mou_send_report();
|
||||
}
|
||||
}
|
||||
|
||||
#endif //MOU
|
||||
|
||||
//********************************************************************************************
|
||||
// RAW
|
||||
//********************************************************************************************
|
||||
#ifdef RAW
|
||||
|
||||
bool udi_hid_raw_enable(void);
|
||||
void udi_hid_raw_disable(void);
|
||||
bool udi_hid_raw_setup(void);
|
||||
uint8_t udi_hid_raw_getsetting(void);
|
||||
|
||||
UDC_DESC_STORAGE udi_api_t udi_api_hid_raw = {
|
||||
.enable = (bool(*)(void))udi_hid_raw_enable,
|
||||
.disable = (void (*)(void))udi_hid_raw_disable,
|
||||
.setup = (bool(*)(void))udi_hid_raw_setup,
|
||||
.getsetting = (uint8_t(*)(void))udi_hid_raw_getsetting,
|
||||
.sof_notify = NULL,
|
||||
};
|
||||
|
||||
COMPILER_WORD_ALIGNED
|
||||
static uint8_t udi_hid_raw_rate;
|
||||
|
||||
COMPILER_WORD_ALIGNED
|
||||
static uint8_t udi_hid_raw_protocol;
|
||||
|
||||
COMPILER_WORD_ALIGNED
|
||||
uint8_t udi_hid_raw_report_set[UDI_HID_RAW_REPORT_SIZE];
|
||||
|
||||
static bool udi_hid_raw_b_report_valid;
|
||||
|
||||
COMPILER_WORD_ALIGNED
|
||||
uint8_t udi_hid_raw_report[UDI_HID_RAW_REPORT_SIZE];
|
||||
|
||||
static bool udi_hid_raw_b_report_trans_ongoing;
|
||||
|
||||
COMPILER_WORD_ALIGNED
|
||||
static uint8_t udi_hid_raw_report_trans[UDI_HID_RAW_REPORT_SIZE];
|
||||
|
||||
COMPILER_WORD_ALIGNED
|
||||
UDC_DESC_STORAGE udi_hid_raw_report_desc_t udi_hid_raw_report_desc = {
|
||||
{
|
||||
0x06, // Usage Page (Vendor Defined)
|
||||
0xFF, 0xFF,
|
||||
0x0A, // Usage (Mouse)
|
||||
0xFF, 0xFF,
|
||||
0xA1, 0x01, // Collection (Application)
|
||||
0x75, 0x08, // Report Size (8)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x25, 0xFF, // Logical Maximum (255)
|
||||
0x95, 0x40, // Report Count
|
||||
0x09, 0x01, // Usage (Input)
|
||||
0x81, 0x02, // Input (Data
|
||||
0x95, 0x40, // Report Count
|
||||
0x09, 0x02, // Usage (Output)
|
||||
0x91, 0x02, // Output (Data
|
||||
0xC0, // End Collection - Consumer Control
|
||||
}
|
||||
};
|
||||
|
||||
static bool udi_hid_raw_setreport(void);
|
||||
static void udi_hid_raw_setreport_valid(void);
|
||||
|
||||
static void udi_hid_raw_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep);
|
||||
|
||||
bool udi_hid_raw_enable(void)
|
||||
{
|
||||
// Initialize internal values
|
||||
udi_hid_raw_rate = 0;
|
||||
udi_hid_raw_protocol = 0;
|
||||
udi_hid_raw_b_report_trans_ongoing = false;
|
||||
memset(udi_hid_raw_report, 0, UDI_HID_RAW_REPORT_SIZE);
|
||||
udi_hid_raw_b_report_valid = false;
|
||||
return UDI_HID_RAW_ENABLE_EXT();
|
||||
}
|
||||
|
||||
void udi_hid_raw_disable(void)
|
||||
{
|
||||
UDI_HID_RAW_DISABLE_EXT();
|
||||
}
|
||||
|
||||
bool udi_hid_raw_setup(void)
|
||||
{
|
||||
return udi_hid_setup(&udi_hid_raw_rate,
|
||||
&udi_hid_raw_protocol,
|
||||
(uint8_t *) &udi_hid_raw_report_desc,
|
||||
udi_hid_raw_setreport);
|
||||
}
|
||||
|
||||
uint8_t udi_hid_raw_getsetting(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool udi_hid_raw_setreport(void)
|
||||
{
|
||||
if ((USB_HID_REPORT_TYPE_OUTPUT == (udd_g_ctrlreq.req.wValue >> 8))
|
||||
&& (0 == (0xFF & udd_g_ctrlreq.req.wValue))
|
||||
&& (UDI_HID_RAW_REPORT_SIZE == udd_g_ctrlreq.req.wLength)) {
|
||||
// Report OUT type on report ID 0 from USB Host
|
||||
udd_g_ctrlreq.payload = udi_hid_raw_report_set;
|
||||
udd_g_ctrlreq.callback = udi_hid_raw_setreport_valid; //must call routine to transform setreport to LED state
|
||||
udd_g_ctrlreq.payload_size = UDI_HID_RAW_REPORT_SIZE;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool udi_hid_raw_send_report(void)
|
||||
{
|
||||
if (!main_b_raw_enable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (udi_hid_raw_b_report_trans_ongoing) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(udi_hid_raw_report_trans, udi_hid_raw_report,UDI_HID_RAW_REPORT_SIZE);
|
||||
udi_hid_raw_b_report_valid = false;
|
||||
udi_hid_raw_b_report_trans_ongoing =
|
||||
udd_ep_run(UDI_HID_RAW_EP_IN | USB_EP_DIR_IN,
|
||||
false,
|
||||
udi_hid_raw_report_trans,
|
||||
UDI_HID_RAW_REPORT_SIZE,
|
||||
udi_hid_raw_report_sent);
|
||||
|
||||
return udi_hid_raw_b_report_trans_ongoing;
|
||||
}
|
||||
|
||||
static void udi_hid_raw_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep)
|
||||
{
|
||||
UNUSED(status);
|
||||
UNUSED(nb_sent);
|
||||
UNUSED(ep);
|
||||
udi_hid_raw_b_report_trans_ongoing = false;
|
||||
if (udi_hid_raw_b_report_valid) {
|
||||
udi_hid_raw_send_report();
|
||||
}
|
||||
}
|
||||
|
||||
static void udi_hid_raw_setreport_valid(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endif //RAW
|
||||
|
||||
//********************************************************************************************
|
||||
// CON
|
||||
//********************************************************************************************
|
||||
#ifdef CON
|
||||
|
||||
bool udi_hid_con_enable(void);
|
||||
void udi_hid_con_disable(void);
|
||||
bool udi_hid_con_setup(void);
|
||||
uint8_t udi_hid_con_getsetting(void);
|
||||
|
||||
UDC_DESC_STORAGE udi_api_t udi_api_hid_con = {
|
||||
.enable = (bool(*)(void))udi_hid_con_enable,
|
||||
.disable = (void (*)(void))udi_hid_con_disable,
|
||||
.setup = (bool(*)(void))udi_hid_con_setup,
|
||||
.getsetting = (uint8_t(*)(void))udi_hid_con_getsetting,
|
||||
.sof_notify = NULL,
|
||||
};
|
||||
|
||||
COMPILER_WORD_ALIGNED
|
||||
static uint8_t udi_hid_con_rate;
|
||||
|
||||
COMPILER_WORD_ALIGNED
|
||||
static uint8_t udi_hid_con_protocol;
|
||||
|
||||
COMPILER_WORD_ALIGNED
|
||||
uint8_t udi_hid_con_report_set[UDI_HID_CON_REPORT_SIZE];
|
||||
|
||||
bool udi_hid_con_b_report_valid;
|
||||
|
||||
COMPILER_WORD_ALIGNED
|
||||
uint8_t udi_hid_con_report[UDI_HID_CON_REPORT_SIZE];
|
||||
|
||||
volatile bool udi_hid_con_b_report_trans_ongoing;
|
||||
|
||||
COMPILER_WORD_ALIGNED
|
||||
static uint8_t udi_hid_con_report_trans[UDI_HID_CON_REPORT_SIZE];
|
||||
|
||||
COMPILER_WORD_ALIGNED
|
||||
UDC_DESC_STORAGE udi_hid_con_report_desc_t udi_hid_con_report_desc = {
|
||||
{
|
||||
0x06, 0x31, 0xFF, // Vendor Page (PJRC Teensy compatible)
|
||||
0x09, 0x74, // Vendor Usage (PJRC Teensy compatible)
|
||||
0xA1, 0x01, // Collection (Application)
|
||||
0x09, 0x75, // Usage (Vendor)
|
||||
0x15, 0x00, // Logical Minimum (0x00)
|
||||
0x26, 0xFF, 0x00, // Logical Maximum (0x00FF)
|
||||
0x95, CONSOLE_EPSIZE, // Report Count
|
||||
0x75, 0x08, // Report Size (8)
|
||||
0x81, 0x02, // Input (Data)
|
||||
0x09, 0x76, // Usage (Vendor)
|
||||
0x15, 0x00, // Logical Minimum (0x00)
|
||||
0x26, 0xFF, 0x00, // Logical Maximum (0x00FF)
|
||||
0x95, CONSOLE_EPSIZE, // Report Count
|
||||
0x75, 0x08, // Report Size (8)
|
||||
0x91, 0x02, // Output (Data)
|
||||
0xC0, // End Collection
|
||||
}
|
||||
};
|
||||
|
||||
static bool udi_hid_con_setreport(void);
|
||||
static void udi_hid_con_setreport_valid(void);
|
||||
|
||||
static void udi_hid_con_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep);
|
||||
|
||||
bool udi_hid_con_enable(void)
|
||||
{
|
||||
// Initialize internal values
|
||||
udi_hid_con_rate = 0;
|
||||
udi_hid_con_protocol = 0;
|
||||
udi_hid_con_b_report_trans_ongoing = false;
|
||||
memset(udi_hid_con_report, 0, UDI_HID_CON_REPORT_SIZE);
|
||||
udi_hid_con_b_report_valid = false;
|
||||
return UDI_HID_CON_ENABLE_EXT();
|
||||
}
|
||||
|
||||
void udi_hid_con_disable(void)
|
||||
{
|
||||
UDI_HID_CON_DISABLE_EXT();
|
||||
}
|
||||
|
||||
bool udi_hid_con_setup(void)
|
||||
{
|
||||
return udi_hid_setup(&udi_hid_con_rate,
|
||||
&udi_hid_con_protocol,
|
||||
(uint8_t *) &udi_hid_con_report_desc,
|
||||
udi_hid_con_setreport);
|
||||
}
|
||||
|
||||
uint8_t udi_hid_con_getsetting(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool udi_hid_con_setreport(void)
|
||||
{
|
||||
if ((USB_HID_REPORT_TYPE_OUTPUT == (udd_g_ctrlreq.req.wValue >> 8))
|
||||
&& (0 == (0xFF & udd_g_ctrlreq.req.wValue))
|
||||
&& (UDI_HID_CON_REPORT_SIZE == udd_g_ctrlreq.req.wLength)) {
|
||||
udd_g_ctrlreq.payload = udi_hid_con_report_set;
|
||||
udd_g_ctrlreq.callback = udi_hid_con_setreport_valid;
|
||||
udd_g_ctrlreq.payload_size = UDI_HID_CON_REPORT_SIZE;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool udi_hid_con_send_report(void)
|
||||
{
|
||||
if (!main_b_con_enable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (udi_hid_con_b_report_trans_ongoing) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(udi_hid_con_report_trans, udi_hid_con_report,UDI_HID_CON_REPORT_SIZE);
|
||||
udi_hid_con_b_report_valid = false;
|
||||
udi_hid_con_b_report_trans_ongoing =
|
||||
udd_ep_run(UDI_HID_CON_EP_IN | USB_EP_DIR_IN,
|
||||
false,
|
||||
udi_hid_con_report_trans,
|
||||
UDI_HID_CON_REPORT_SIZE,
|
||||
udi_hid_con_report_sent);
|
||||
|
||||
return udi_hid_con_b_report_trans_ongoing;
|
||||
}
|
||||
|
||||
static void udi_hid_con_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep)
|
||||
{
|
||||
UNUSED(status);
|
||||
UNUSED(nb_sent);
|
||||
UNUSED(ep);
|
||||
udi_hid_con_b_report_trans_ongoing = false;
|
||||
if (udi_hid_con_b_report_valid) {
|
||||
udi_hid_con_send_report();
|
||||
}
|
||||
}
|
||||
|
||||
static void udi_hid_con_setreport_valid(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endif //CON
|
122
tmk_core/protocol/arm_atsam/usb/udi_hid_kbd.h
Normal file
122
tmk_core/protocol/arm_atsam/usb/udi_hid_kbd.h
Normal file
|
@ -0,0 +1,122 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief USB Device Human Interface Device (HID) keyboard interface.
|
||||
*
|
||||
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
|
||||
#ifndef _UDC_HID_KBD_H_
|
||||
#define _UDC_HID_KBD_H_
|
||||
|
||||
#include "udc_desc.h"
|
||||
#include "udi.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//******************************************************************************
|
||||
// Keyboard interface definitions
|
||||
//******************************************************************************
|
||||
#ifdef KBD
|
||||
extern UDC_DESC_STORAGE udi_api_t udi_api_hid_kbd;
|
||||
extern bool udi_hid_kbd_b_report_valid;
|
||||
extern volatile bool udi_hid_kbd_b_report_trans_ongoing;
|
||||
extern uint8_t udi_hid_kbd_report_set;
|
||||
bool udi_hid_kbd_send_report(void);
|
||||
#endif //KBD
|
||||
|
||||
//********************************************************************************************
|
||||
// NKRO Keyboard
|
||||
//********************************************************************************************
|
||||
#ifdef NKRO
|
||||
extern UDC_DESC_STORAGE udi_api_t udi_api_hid_nkro;
|
||||
extern bool udi_hid_nkro_b_report_valid;
|
||||
extern volatile bool udi_hid_nkro_b_report_trans_ongoing;
|
||||
bool udi_hid_nkro_send_report(void);
|
||||
#endif //NKRO
|
||||
|
||||
//********************************************************************************************
|
||||
// SYS-CTRL interface
|
||||
//********************************************************************************************
|
||||
#ifdef EXK
|
||||
extern UDC_DESC_STORAGE udi_api_t udi_api_hid_exk;
|
||||
extern bool udi_hid_exk_b_report_valid;
|
||||
extern uint8_t udi_hid_exk_report_set;
|
||||
bool udi_hid_exk_send_report(void);
|
||||
#endif //EXK
|
||||
|
||||
//********************************************************************************************
|
||||
// CON Console
|
||||
//********************************************************************************************
|
||||
#ifdef CON
|
||||
extern UDC_DESC_STORAGE udi_api_t udi_api_hid_con;
|
||||
extern bool udi_hid_con_b_report_valid;
|
||||
extern uint8_t udi_hid_con_report_set[UDI_HID_CON_REPORT_SIZE];
|
||||
extern volatile bool udi_hid_con_b_report_trans_ongoing;
|
||||
bool udi_hid_con_send_report(void);
|
||||
#endif //CON
|
||||
|
||||
//********************************************************************************************
|
||||
// MOU Mouse
|
||||
//********************************************************************************************
|
||||
#ifdef MOU
|
||||
extern UDC_DESC_STORAGE udi_api_t udi_api_hid_mou;
|
||||
extern bool udi_hid_mou_b_report_valid;
|
||||
bool udi_hid_mou_send_report(void);
|
||||
#endif //MOU
|
||||
|
||||
//********************************************************************************************
|
||||
// RAW Raw
|
||||
//********************************************************************************************
|
||||
#ifdef RAW
|
||||
extern UDC_DESC_STORAGE udi_api_t udi_api_hid_raw;
|
||||
bool udi_hid_raw_send_report(void);
|
||||
#endif //RAW
|
||||
|
||||
//@}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _UDC_HID_KBD_H_
|
60
tmk_core/protocol/arm_atsam/usb/udi_hid_kbd_conf.h
Normal file
60
tmk_core/protocol/arm_atsam/usb/udi_hid_kbd_conf.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Default HID keyboard configuration for a USB Device
|
||||
* with a single interface HID keyboard
|
||||
*
|
||||
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
|
||||
#ifndef _UDI_HID_KBD_CONF_H_
|
||||
#define _UDI_HID_KBD_CONF_H_
|
||||
|
||||
/**
|
||||
* \addtogroup udi_hid_keyboard_group_single_desc
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "udi_device_conf.h"
|
||||
|
||||
#include "udi_hid_kbd.h"
|
||||
|
||||
#endif // _UDI_HID_KBD_CONF_H_
|
185
tmk_core/protocol/arm_atsam/usb/udi_hid_kbd_desc.c
Normal file
185
tmk_core/protocol/arm_atsam/usb/udi_hid_kbd_desc.c
Normal file
|
@ -0,0 +1,185 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Default descriptors for a USB Device
|
||||
* with a single interface HID keyboard
|
||||
*
|
||||
* Copyright (c) 2009-2016 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
|
||||
#include "conf_usb.h"
|
||||
#include "usb_protocol.h"
|
||||
#include "udc_desc.h"
|
||||
#include "udi_device_conf.h"
|
||||
#include "udi_hid_kbd.h"
|
||||
#include "udi_cdc.h"
|
||||
|
||||
/**
|
||||
* \ingroup udi_hid_keyboard_group
|
||||
* \defgroup udi_hid_keyboard_group_single_desc USB device descriptors for a single interface
|
||||
*
|
||||
* The following structures provide the USB device descriptors required
|
||||
* for USB Device with a single interface HID keyboard.
|
||||
*
|
||||
* It is ready to use and do not require more definition.
|
||||
* @{
|
||||
*/
|
||||
|
||||
//! USB Device Descriptor
|
||||
COMPILER_WORD_ALIGNED
|
||||
UDC_DESC_STORAGE usb_dev_desc_t udc_device_desc = {
|
||||
.bLength = sizeof(usb_dev_desc_t),
|
||||
.bDescriptorType = USB_DT_DEVICE,
|
||||
.bcdUSB = LE16(USB_V2_0),
|
||||
.bDeviceClass = DEVICE_CLASS,
|
||||
.bDeviceSubClass = DEVICE_SUBCLASS,
|
||||
.bDeviceProtocol = DEVICE_PROTOCOL,
|
||||
.bMaxPacketSize0 = USB_DEVICE_EP_CTRL_SIZE,
|
||||
.idVendor = LE16(USB_DEVICE_VENDOR_ID),
|
||||
.idProduct = LE16(USB_DEVICE_PRODUCT_ID),
|
||||
.bcdDevice = LE16(USB_DEVICE_VERSION),
|
||||
#ifdef USB_DEVICE_MANUFACTURE_NAME
|
||||
.iManufacturer = 1,
|
||||
#else
|
||||
.iManufacturer = 0, // No manufacture string
|
||||
#endif
|
||||
#ifdef USB_DEVICE_PRODUCT_NAME
|
||||
.iProduct = 2,
|
||||
#else
|
||||
.iProduct = 0, // No product string
|
||||
#endif
|
||||
#if (defined USB_DEVICE_SERIAL_NAME || defined USB_DEVICE_GET_SERIAL_NAME_POINTER)
|
||||
.iSerialNumber = 3,
|
||||
#else
|
||||
.iSerialNumber = 0, // No serial string
|
||||
#endif
|
||||
.bNumConfigurations = 1
|
||||
};
|
||||
|
||||
#if 0
|
||||
#ifdef USB_DEVICE_HS_SUPPORT
|
||||
//! USB Device Qualifier Descriptor for HS
|
||||
COMPILER_WORD_ALIGNED
|
||||
UDC_DESC_STORAGE usb_dev_qual_desc_t udc_device_qual = {
|
||||
.bLength = sizeof(usb_dev_qual_desc_t),
|
||||
.bDescriptorType = USB_DT_DEVICE_QUALIFIER,
|
||||
.bcdUSB = LE16(USB_V2_0),
|
||||
.bDeviceClass = 0,
|
||||
.bDeviceSubClass = 0,
|
||||
.bDeviceProtocol = 0,
|
||||
.bMaxPacketSize0 = USB_DEVICE_EP_CTRL_SIZE,
|
||||
.bNumConfigurations = 1
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//! USB Device Configuration Descriptor filled for FS and HS
|
||||
COMPILER_WORD_ALIGNED
|
||||
UDC_DESC_STORAGE udc_desc_t udc_desc = {
|
||||
.conf.bLength = sizeof(usb_conf_desc_t),
|
||||
.conf.bDescriptorType = USB_DT_CONFIGURATION,
|
||||
.conf.wTotalLength = LE16(sizeof(udc_desc_t)),
|
||||
.conf.bNumInterfaces = USB_DEVICE_NB_INTERFACE,
|
||||
.conf.bConfigurationValue = 1,
|
||||
.conf.iConfiguration = 0,
|
||||
.conf.bmAttributes = /* USB_CONFIG_ATTR_MUST_SET | */ USB_DEVICE_ATTR,
|
||||
.conf.bMaxPower = USB_CONFIG_MAX_POWER(USB_DEVICE_POWER),
|
||||
#ifdef KBD
|
||||
.hid_kbd = UDI_HID_KBD_DESC,
|
||||
#endif
|
||||
#ifdef RAW
|
||||
.hid_raw = UDI_HID_RAW_DESC,
|
||||
#endif
|
||||
#ifdef MOU
|
||||
.hid_mou = UDI_HID_MOU_DESC,
|
||||
#endif
|
||||
#ifdef EXK
|
||||
.hid_exk = UDI_HID_EXK_DESC,
|
||||
#endif
|
||||
#ifdef CON
|
||||
.hid_con = UDI_HID_CON_DESC,
|
||||
#endif
|
||||
#ifdef NKRO
|
||||
.hid_nkro = UDI_HID_NKRO_DESC,
|
||||
#endif
|
||||
#ifdef CDC
|
||||
.cdc_serial = CDC_DESCRIPTOR,
|
||||
#endif
|
||||
};
|
||||
|
||||
UDC_DESC_STORAGE udi_api_t *udi_apis[USB_DEVICE_NB_INTERFACE] = {
|
||||
#ifdef KBD
|
||||
&udi_api_hid_kbd,
|
||||
#endif
|
||||
#ifdef RAW
|
||||
&udi_api_hid_raw,
|
||||
#endif
|
||||
#ifdef MOU
|
||||
&udi_api_hid_mou,
|
||||
#endif
|
||||
#ifdef EXK
|
||||
&udi_api_hid_exk,
|
||||
#endif
|
||||
#ifdef CON
|
||||
&udi_api_hid_con,
|
||||
#endif
|
||||
#ifdef NKRO
|
||||
&udi_api_hid_nkro,
|
||||
#endif
|
||||
#ifdef CDC
|
||||
&udi_api_cdc_comm, &udi_api_cdc_data,
|
||||
#endif
|
||||
};
|
||||
|
||||
//! Add UDI with USB Descriptors FS & HS
|
||||
UDC_DESC_STORAGE udc_config_speed_t udc_config_fshs[1] = {{
|
||||
.desc = (usb_conf_desc_t UDC_DESC_STORAGE*)&udc_desc,
|
||||
.udi_apis = udi_apis,
|
||||
}};
|
||||
|
||||
//! Add all information about USB Device in global structure for UDC
|
||||
UDC_DESC_STORAGE udc_config_t udc_config = {
|
||||
.confdev_lsfs = &udc_device_desc,
|
||||
.conf_lsfs = udc_config_fshs,
|
||||
};
|
||||
|
||||
//@}
|
||||
//@}
|
104
tmk_core/protocol/arm_atsam/usb/ui.c
Normal file
104
tmk_core/protocol/arm_atsam/usb/ui.c
Normal file
|
@ -0,0 +1,104 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief User Interface
|
||||
*
|
||||
* Copyright (c) 2014-2015 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
|
||||
#ifndef ARM_MATH_CM4
|
||||
#define ARM_MATH_CM4
|
||||
#endif
|
||||
|
||||
#undef LITTLE_ENDIAN //redefined in samd51j18a.h
|
||||
#include "samd51j18a.h"
|
||||
#include "ui.h"
|
||||
|
||||
//! Sequence process running each \c SEQUENCE_PERIOD ms
|
||||
#define SEQUENCE_PERIOD 150
|
||||
|
||||
#if 0
|
||||
/* Interrupt on "pin change" from push button to do wakeup on USB
|
||||
* Note:
|
||||
* This interrupt is enable when the USB host enable remote wakeup feature
|
||||
* This interrupt wakeup the CPU if this one is in idle mode
|
||||
*/
|
||||
static void ui_wakeup_handler(void)
|
||||
{
|
||||
/* It is a wakeup then send wakeup USB */
|
||||
udc_remotewakeup();
|
||||
}
|
||||
#endif
|
||||
|
||||
void ui_init(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ui_powerdown(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ui_wakeup_enable(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ui_wakeup_disable(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ui_wakeup(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ui_process(uint16_t framenumber)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ui_kbd_led(uint8_t value)
|
||||
{
|
||||
|
||||
}
|
76
tmk_core/protocol/arm_atsam/usb/ui.h
Normal file
76
tmk_core/protocol/arm_atsam/usb/ui.h
Normal file
|
@ -0,0 +1,76 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Common User Interface for HID Keyboard application
|
||||
*
|
||||
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
|
||||
#ifndef _UI_H_
|
||||
#define _UI_H_
|
||||
|
||||
//! \brief Initializes the user interface
|
||||
void ui_init(void);
|
||||
|
||||
//! \brief Enters the user interface in power down mode
|
||||
void ui_powerdown(void);
|
||||
|
||||
//! \brief Enables the asynchronous interrupts of the user interface
|
||||
void ui_wakeup_enable(void);
|
||||
|
||||
//! \brief Disables the asynchronous interrupts of the user interface
|
||||
void ui_wakeup_disable(void);
|
||||
|
||||
//! \brief Exits the user interface of power down mode
|
||||
void ui_wakeup(void);
|
||||
|
||||
/*! \brief This process is called each 1ms
|
||||
* It is called only if the USB interface is enabled.
|
||||
*
|
||||
* \param framenumber Current frame number
|
||||
*/
|
||||
void ui_process(uint16_t framenumber);
|
||||
|
||||
/*! \brief Turn on or off the keyboard LEDs
|
||||
*/
|
||||
void ui_kbd_led(uint8_t value);
|
||||
|
||||
#endif // _UI_H_
|
1144
tmk_core/protocol/arm_atsam/usb/usb.c
Normal file
1144
tmk_core/protocol/arm_atsam/usb/usb.c
Normal file
File diff suppressed because it is too large
Load diff
492
tmk_core/protocol/arm_atsam/usb/usb.h
Normal file
492
tmk_core/protocol/arm_atsam/usb/usb.h
Normal file
|
@ -0,0 +1,492 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief SAM USB Driver
|
||||
*
|
||||
* Copyright (C) 2014-2016 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
#ifndef USB_H_INCLUDED
|
||||
#define USB_H_INCLUDED
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \defgroup asfdoc_sam0_usb_group SAM Universal Serial Bus (USB)
|
||||
*
|
||||
* The Universal Serial Bus (USB) module complies with the USB 2.1 specification.
|
||||
*
|
||||
* The following peripherals are used by this module:
|
||||
* - USB (Universal Serial Bus)
|
||||
*
|
||||
* The following devices can use this module:
|
||||
* - Atmel | SMART SAM D51
|
||||
*
|
||||
* The USB module covers following mode:
|
||||
* \if USB_DEVICE_MODE
|
||||
* - USB Device Mode
|
||||
* \endif
|
||||
* \if USB_HOST_MODE
|
||||
* - USB Host Mode
|
||||
* \endif
|
||||
*
|
||||
* The USB module covers following speed:
|
||||
* \if USB_HS_MODE
|
||||
* - USB High Speed (480Mbit/s)
|
||||
* \endif
|
||||
* - USB Full Speed (12Mbit/s)
|
||||
* \if USB_LS_MODE
|
||||
* - USB Low Speed (1.5Mbit/s)
|
||||
* \endif
|
||||
*
|
||||
* \if USB_LPM_MODE
|
||||
* The USB module supports Link Power Management (LPM-L1) protocol.
|
||||
* \endif
|
||||
*
|
||||
* USB support needs whole set of enumeration process, to make the device
|
||||
* recognizable and usable. The USB driver is designed to interface to the
|
||||
* USB Stack in Atmel Software Framework (ASF).
|
||||
*
|
||||
* \if USB_DEVICE_MODE
|
||||
* \section asfdoc_sam0_usb_device USB Device Mode
|
||||
* The ASF USB Device Stack has defined the USB Device Driver (UDD) interface,
|
||||
* to support USB device operations. The USB module device driver complies with
|
||||
* this interface, so that the USB Device Stack can work based on the
|
||||
* USB module.
|
||||
*
|
||||
* Refer to <a href="http://www.atmel.com/images/doc8360.pdf">
|
||||
* "ASF - USB Device Stack"</a> for more details.
|
||||
* \endif
|
||||
*
|
||||
* \if USB_HOST_MODE
|
||||
* \section adfdoc_sam0_usb_host USB Host Mode
|
||||
* The ASF USB Host Stack has defined the USB Host Driver (UHD) interface,
|
||||
* to support USB host operations. The USB module host driver complies with
|
||||
* this interface, so that the USB Host Stack can work based on the USB module.
|
||||
*
|
||||
* Refer to <a href="http://www.atmel.com/images/doc8486.pdf">
|
||||
* "ASF - USB Host Stack"</a> for more details.
|
||||
* \endif
|
||||
*/
|
||||
|
||||
/** Enum for the speed status for the USB module */
|
||||
enum usb_speed {
|
||||
USB_SPEED_LOW,
|
||||
USB_SPEED_FULL,
|
||||
};
|
||||
|
||||
/** Enum for the possible callback types for the USB in host module */
|
||||
enum usb_host_callback {
|
||||
USB_HOST_CALLBACK_SOF,
|
||||
USB_HOST_CALLBACK_RESET,
|
||||
USB_HOST_CALLBACK_WAKEUP,
|
||||
USB_HOST_CALLBACK_DNRSM,
|
||||
USB_HOST_CALLBACK_UPRSM,
|
||||
USB_HOST_CALLBACK_RAMACER,
|
||||
USB_HOST_CALLBACK_CONNECT,
|
||||
USB_HOST_CALLBACK_DISCONNECT,
|
||||
USB_HOST_CALLBACK_N,
|
||||
};
|
||||
|
||||
/** Enum for the possible callback types for the USB pipe in host module */
|
||||
enum usb_host_pipe_callback {
|
||||
USB_HOST_PIPE_CALLBACK_TRANSFER_COMPLETE,
|
||||
USB_HOST_PIPE_CALLBACK_ERROR,
|
||||
USB_HOST_PIPE_CALLBACK_SETUP,
|
||||
USB_HOST_PIPE_CALLBACK_STALL,
|
||||
USB_HOST_PIPE_CALLBACK_N,
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Host pipe types.
|
||||
*/
|
||||
enum usb_host_pipe_type {
|
||||
USB_HOST_PIPE_TYPE_DISABLE,
|
||||
USB_HOST_PIPE_TYPE_CONTROL,
|
||||
USB_HOST_PIPE_TYPE_ISO,
|
||||
USB_HOST_PIPE_TYPE_BULK,
|
||||
USB_HOST_PIPE_TYPE_INTERRUPT,
|
||||
USB_HOST_PIPE_TYPE_EXTENDED,
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Host pipe token types.
|
||||
*/
|
||||
enum usb_host_pipe_token {
|
||||
USB_HOST_PIPE_TOKEN_SETUP,
|
||||
USB_HOST_PIPE_TOKEN_IN,
|
||||
USB_HOST_PIPE_TOKEN_OUT,
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Enumeration for the possible callback types for the USB in device module
|
||||
*/
|
||||
enum usb_device_callback {
|
||||
USB_DEVICE_CALLBACK_SOF,
|
||||
USB_DEVICE_CALLBACK_RESET,
|
||||
USB_DEVICE_CALLBACK_WAKEUP,
|
||||
USB_DEVICE_CALLBACK_RAMACER,
|
||||
USB_DEVICE_CALLBACK_SUSPEND,
|
||||
USB_DEVICE_CALLBACK_LPMNYET,
|
||||
USB_DEVICE_CALLBACK_LPMSUSP,
|
||||
USB_DEVICE_CALLBACK_N,
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Enumeration for the possible callback types for the USB endpoint in device module
|
||||
*/
|
||||
enum usb_device_endpoint_callback {
|
||||
USB_DEVICE_ENDPOINT_CALLBACK_TRCPT,
|
||||
USB_DEVICE_ENDPOINT_CALLBACK_TRFAIL,
|
||||
USB_DEVICE_ENDPOINT_CALLBACK_RXSTP,
|
||||
USB_DEVICE_ENDPOINT_CALLBACK_STALL,
|
||||
USB_DEVICE_EP_CALLBACK_N,
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Device Endpoint types.
|
||||
*/
|
||||
enum usb_device_endpoint_type {
|
||||
USB_DEVICE_ENDPOINT_TYPE_DISABLE,
|
||||
USB_DEVICE_ENDPOINT_TYPE_CONTROL,
|
||||
USB_DEVICE_ENDPOINT_TYPE_ISOCHRONOUS,
|
||||
USB_DEVICE_ENDPOINT_TYPE_BULK,
|
||||
USB_DEVICE_ENDPOINT_TYPE_INTERRUPT,
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Endpoint Size
|
||||
*/
|
||||
enum usb_endpoint_size {
|
||||
USB_ENDPOINT_8_BYTE,
|
||||
USB_ENDPOINT_16_BYTE,
|
||||
USB_ENDPOINT_32_BYTE,
|
||||
USB_ENDPOINT_64_BYTE,
|
||||
USB_ENDPOINT_128_BYTE,
|
||||
USB_ENDPOINT_256_BYTE,
|
||||
USB_ENDPOINT_512_BYTE,
|
||||
USB_ENDPOINT_1023_BYTE,
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Link Power Management Handshake.
|
||||
*/
|
||||
enum usb_device_lpm_mode {
|
||||
USB_DEVICE_LPM_NOT_SUPPORT,
|
||||
USB_DEVICE_LPM_ACK,
|
||||
USB_DEVICE_LPM_NYET,
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Module structure
|
||||
*/
|
||||
struct usb_module;
|
||||
|
||||
/**
|
||||
* \name Host Callback Functions Types
|
||||
* @{
|
||||
*/
|
||||
typedef void (*usb_host_callback_t)(struct usb_module *module_inst);
|
||||
typedef void (*usb_host_pipe_callback_t)(struct usb_module *module_inst, void *);
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* \name Device Callback Functions Types
|
||||
* @{
|
||||
*/
|
||||
typedef void (*usb_device_callback_t)(struct usb_module *module_inst, void* pointer);
|
||||
typedef void (*usb_device_endpoint_callback_t)(struct usb_module *module_inst, void* pointer);
|
||||
/** @} */
|
||||
|
||||
/** USB configurations */
|
||||
struct usb_config {
|
||||
/** \c true for host, \c false for device. */
|
||||
bool select_host_mode;
|
||||
/** When \c true the module is enabled during standby. */
|
||||
bool run_in_standby;
|
||||
/** Generic Clock Generator source channel. */
|
||||
// enum gclk_generator source_generator;
|
||||
uint8_t source_generator;
|
||||
/** Speed mode */
|
||||
//enum usb_speed speed_mode;
|
||||
uint8_t speed_mode;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief USB software module instance structure.
|
||||
*
|
||||
* USB software module instance structure, used to retain software state
|
||||
* information of an associated hardware module instance.
|
||||
*
|
||||
*/
|
||||
struct usb_module {
|
||||
/** Hardware module pointer of the associated USB peripheral. */
|
||||
Usb *hw;
|
||||
|
||||
/** Array to store device related callback functions */
|
||||
usb_device_callback_t device_callback[USB_DEVICE_CALLBACK_N];
|
||||
usb_device_endpoint_callback_t device_endpoint_callback[USB_EPT_NUM][USB_DEVICE_EP_CALLBACK_N];
|
||||
/** Bit mask for device callbacks registered */
|
||||
uint16_t device_registered_callback_mask;
|
||||
/** Bit mask for device callbacks enabled */
|
||||
uint16_t device_enabled_callback_mask;
|
||||
/** Bit mask for device endpoint callbacks registered */
|
||||
uint8_t device_endpoint_registered_callback_mask[USB_EPT_NUM];
|
||||
/** Bit mask for device endpoint callbacks enabled */
|
||||
uint8_t device_endpoint_enabled_callback_mask[USB_EPT_NUM];
|
||||
};
|
||||
|
||||
/** USB device endpoint configurations */
|
||||
struct usb_device_endpoint_config {
|
||||
/** device address */
|
||||
uint8_t ep_address;
|
||||
/** endpoint size */
|
||||
enum usb_endpoint_size ep_size;
|
||||
/** automatic zero length packet mode, \c true to enable */
|
||||
bool auto_zlp;
|
||||
/** type of endpoint with Bank */
|
||||
enum usb_device_endpoint_type ep_type;
|
||||
};
|
||||
|
||||
/** USB device endpoint callback status parameter structure */
|
||||
struct usb_endpoint_callback_parameter {
|
||||
uint16_t received_bytes;
|
||||
uint16_t sent_bytes;
|
||||
uint16_t out_buffer_size;
|
||||
uint8_t endpoint_address;
|
||||
};
|
||||
|
||||
void usb_enable(struct usb_module *module_inst);
|
||||
void usb_disable(struct usb_module *module_inst);
|
||||
|
||||
/**
|
||||
* \brief Get the status of USB module's state machine
|
||||
*
|
||||
* \param module_inst Pointer to USB module instance
|
||||
*/
|
||||
static inline uint8_t usb_get_state_machine_status(struct usb_module *module_inst)
|
||||
{
|
||||
/* Sanity check arguments */
|
||||
Assert(module_inst);
|
||||
Assert(module_inst->hw);
|
||||
|
||||
return module_inst->hw->DEVICE.FSMSTATUS.reg;
|
||||
}
|
||||
|
||||
void usb_get_config_defaults(struct usb_config *module_config);
|
||||
enum status_code usb_init(struct usb_module *module_inst, Usb *const hw,
|
||||
struct usb_config *module_config);
|
||||
|
||||
/**
|
||||
* \brief Attach USB device to the bus
|
||||
*
|
||||
* \param module_inst Pointer to USB device module instance
|
||||
*/
|
||||
static inline void usb_device_attach(struct usb_module *module_inst)
|
||||
{
|
||||
module_inst->hw->DEVICE.CTRLB.reg &= ~USB_DEVICE_CTRLB_DETACH;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Detach USB device from the bus
|
||||
*
|
||||
* \param module_inst Pointer to USB device module instance
|
||||
*/
|
||||
static inline void usb_device_detach(struct usb_module *module_inst)
|
||||
{
|
||||
module_inst->hw->DEVICE.CTRLB.reg |= USB_DEVICE_CTRLB_DETACH;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the speed mode of USB device
|
||||
*
|
||||
* \param module_inst Pointer to USB device module instance
|
||||
* \return USB Speed mode (\ref usb_speed).
|
||||
*/
|
||||
static inline enum usb_speed usb_device_get_speed(struct usb_module *module_inst)
|
||||
{
|
||||
if (!(module_inst->hw->DEVICE.STATUS.reg & USB_DEVICE_STATUS_SPEED_Msk)) {
|
||||
return USB_SPEED_FULL;
|
||||
} else {
|
||||
return USB_SPEED_LOW;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the address of USB device
|
||||
*
|
||||
* \param module_inst Pointer to USB device module instance
|
||||
* \return USB device address value.
|
||||
*/
|
||||
static inline uint8_t usb_device_get_address(struct usb_module *module_inst)
|
||||
{
|
||||
return ((uint8_t)(module_inst->hw->DEVICE.DADD.bit.DADD));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set the speed mode of USB device
|
||||
*
|
||||
* \param module_inst Pointer to USB device module instance
|
||||
* \param address USB device address value
|
||||
*/
|
||||
static inline void usb_device_set_address(struct usb_module *module_inst, uint8_t address)
|
||||
{
|
||||
module_inst->hw->DEVICE.DADD.reg = USB_DEVICE_DADD_ADDEN | address;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the frame number of USB device
|
||||
*
|
||||
* \param module_inst Pointer to USB device module instance
|
||||
* \return USB device frame number value.
|
||||
*/
|
||||
static inline uint16_t usb_device_get_frame_number(struct usb_module *module_inst)
|
||||
{
|
||||
return ((uint16_t)(module_inst->hw->DEVICE.FNUM.bit.FNUM));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the micro-frame number of USB device
|
||||
*
|
||||
* \param module_inst Pointer to USB device module instance
|
||||
* \return USB device micro-frame number value.
|
||||
*/
|
||||
static inline uint16_t usb_device_get_micro_frame_number(struct usb_module *module_inst)
|
||||
{
|
||||
return ((uint16_t)(module_inst->hw->DEVICE.FNUM.reg));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief USB device send the resume wakeup
|
||||
*
|
||||
* \param module_inst Pointer to USB device module instance
|
||||
*/
|
||||
static inline void usb_device_send_remote_wake_up(struct usb_module *module_inst)
|
||||
{
|
||||
module_inst->hw->DEVICE.CTRLB.reg |= USB_DEVICE_CTRLB_UPRSM;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief USB device set the LPM mode
|
||||
*
|
||||
* \param module_inst Pointer to USB device module instance
|
||||
* \param lpm_mode LPM mode
|
||||
*/
|
||||
static inline void usb_device_set_lpm_mode(struct usb_module *module_inst,
|
||||
enum usb_device_lpm_mode lpm_mode)
|
||||
{
|
||||
module_inst->hw->DEVICE.CTRLB.bit.LPMHDSK = lpm_mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* \name USB Device Callback Management
|
||||
* @{
|
||||
*/
|
||||
enum status_code usb_device_register_callback(struct usb_module *module_inst,
|
||||
enum usb_device_callback callback_type,
|
||||
usb_device_callback_t callback_func);
|
||||
enum status_code usb_device_unregister_callback(struct usb_module *module_inst,
|
||||
enum usb_device_callback callback_type);
|
||||
enum status_code usb_device_enable_callback(struct usb_module *module_inst,
|
||||
enum usb_device_callback callback_type);
|
||||
enum status_code usb_device_disable_callback(struct usb_module *module_inst,
|
||||
enum usb_device_callback callback_type);
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* \name USB Device Endpoint Configuration
|
||||
* @{
|
||||
*/
|
||||
void usb_device_endpoint_get_config_defaults(struct usb_device_endpoint_config *ep_config);
|
||||
enum status_code usb_device_endpoint_set_config(struct usb_module *module_inst,
|
||||
struct usb_device_endpoint_config *ep_config);
|
||||
bool usb_device_endpoint_is_configured(struct usb_module *module_inst, uint8_t ep);
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* \name USB Device Endpoint Callback Management
|
||||
* @{
|
||||
*/
|
||||
enum status_code usb_device_endpoint_register_callback(
|
||||
struct usb_module *module_inst, uint8_t ep_num,
|
||||
enum usb_device_endpoint_callback callback_type,
|
||||
usb_device_endpoint_callback_t callback_func);
|
||||
enum status_code usb_device_endpoint_unregister_callback(
|
||||
struct usb_module *module_inst, uint8_t ep_num,
|
||||
enum usb_device_endpoint_callback callback_type);
|
||||
enum status_code usb_device_endpoint_enable_callback(
|
||||
struct usb_module *module_inst, uint8_t ep,
|
||||
enum usb_device_endpoint_callback callback_type);
|
||||
enum status_code usb_device_endpoint_disable_callback(
|
||||
struct usb_module *module_inst, uint8_t ep,
|
||||
enum usb_device_endpoint_callback callback_type);
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* \name USB Device Endpoint Job Management
|
||||
* @{
|
||||
*/
|
||||
enum status_code usb_device_endpoint_write_buffer_job(struct usb_module *module_inst,uint8_t ep_num,
|
||||
uint8_t* pbuf, uint32_t buf_size);
|
||||
enum status_code usb_device_endpoint_read_buffer_job(struct usb_module *module_inst,uint8_t ep_num,
|
||||
uint8_t* pbuf, uint32_t buf_size);
|
||||
enum status_code usb_device_endpoint_setup_buffer_job(struct usb_module *module_inst,
|
||||
uint8_t* pbuf);
|
||||
void usb_device_endpoint_abort_job(struct usb_module *module_inst, uint8_t ep);
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* \name USB Device Endpoint Operations
|
||||
* @{
|
||||
*/
|
||||
|
||||
bool usb_device_endpoint_is_halted(struct usb_module *module_inst, uint8_t ep);
|
||||
void usb_device_endpoint_set_halt(struct usb_module *module_inst, uint8_t ep);
|
||||
void usb_device_endpoint_clear_halt(struct usb_module *module_inst, uint8_t ep);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USB_H_INCLUDED */
|
409
tmk_core/protocol/arm_atsam/usb/usb2422.c
Normal file
409
tmk_core/protocol/arm_atsam/usb/usb2422.c
Normal file
|
@ -0,0 +1,409 @@
|
|||
/*
|
||||
Copyright 2018 Massdrop Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "arm_atsam_protocol.h"
|
||||
#include <string.h>
|
||||
|
||||
Usb2422 USB2422_shadow;
|
||||
unsigned char i2c0_buf[34];
|
||||
|
||||
const uint16_t MFRNAME[] = { 'M','a','s','s','d','r','o','p',' ','I','n','c','.' }; //Massdrop Inc.
|
||||
const uint16_t PRDNAME[] = { 'M','a','s','s','d','r','o','p',' ','H','u','b' }; //Massdrop Hub
|
||||
#ifndef MD_BOOTLOADER
|
||||
//Serial number reported stops before first found space character or at last found character
|
||||
const uint16_t SERNAME[] = { 'U','n','a','v','a','i','l','a','b','l','e' }; //Unavailable
|
||||
#else
|
||||
//In production, this field is found, modified, and offset noted as the last 32-bit word in the bootloader space
|
||||
//The offset allows the application to use the factory programmed serial (which may differ from the physical serial label)
|
||||
//Serial number reported stops before first found space character or when max size is reached
|
||||
__attribute__((__aligned__(4)))
|
||||
const uint16_t SERNAME[BOOTLOADER_SERIAL_MAX_SIZE] = { 'M','D','H','U','B','B','O','O','T','L','0','0','0','0','0','0','0','0','0','0' };
|
||||
//NOTE: Serial replacer will not write a string longer than given here as a precaution, so give enough
|
||||
// space as needed and adjust BOOTLOADER_SERIAL_MAX_SIZE to match amount given
|
||||
#endif //MD_BOOTLOADER
|
||||
|
||||
uint8_t usb_host_port;
|
||||
|
||||
#ifndef MD_BOOTLOADER
|
||||
|
||||
uint8_t usb_extra_state;
|
||||
uint8_t usb_extra_manual;
|
||||
uint8_t usb_gcr_auto;
|
||||
|
||||
#endif //MD_BOOTLOADER
|
||||
|
||||
uint16_t adc_extra;
|
||||
|
||||
void USB_write2422_block(void)
|
||||
{
|
||||
unsigned char *dest = i2c0_buf;
|
||||
unsigned char *src;
|
||||
unsigned char *base = (unsigned char *)&USB2422_shadow;
|
||||
|
||||
DBGC(DC_USB_WRITE2422_BLOCK_BEGIN);
|
||||
|
||||
for (src = base; src < base + 256; src += 32)
|
||||
{
|
||||
dest[0] = src - base;
|
||||
dest[1] = 32;
|
||||
memcpy(&dest[2], src, 32);
|
||||
i2c0_transmit(USB2422_ADDR, dest, 34, 50000);
|
||||
SERCOM0->I2CM.CTRLB.bit.CMD = 0x03;
|
||||
while (SERCOM0->I2CM.SYNCBUSY.bit.SYSOP) { DBGC(DC_USB_WRITE2422_BLOCK_SYNC_SYSOP); }
|
||||
CLK_delay_us(100);
|
||||
}
|
||||
|
||||
DBGC(DC_USB_WRITE2422_BLOCK_COMPLETE);
|
||||
}
|
||||
|
||||
void USB2422_init(void)
|
||||
{
|
||||
Gclk *pgclk = GCLK;
|
||||
Mclk *pmclk = MCLK;
|
||||
Port *pport = PORT;
|
||||
Oscctrl *posc = OSCCTRL;
|
||||
Usb *pusb = USB;
|
||||
|
||||
DBGC(DC_USB2422_INIT_BEGIN);
|
||||
|
||||
while ((v_5v = adc_get(ADC_5V)) < ADC_5V_START_LEVEL) { DBGC(DC_USB2422_INIT_WAIT_5V_LOW); }
|
||||
|
||||
//setup peripheral and synchronous bus clocks to USB
|
||||
pgclk->PCHCTRL[10].bit.GEN = 0;
|
||||
pgclk->PCHCTRL[10].bit.CHEN = 1;
|
||||
pmclk->AHBMASK.bit.USB_ = 1;
|
||||
pmclk->APBBMASK.bit.USB_ = 1;
|
||||
|
||||
//setup port pins for D-, D+, and SOF_1KHZ
|
||||
pport->Group[0].PMUX[12].reg = 0x77; //PA24, PA25, function column H for USB D-, D+
|
||||
pport->Group[0].PINCFG[24].bit.PMUXEN = 1;
|
||||
pport->Group[0].PINCFG[25].bit.PMUXEN = 1;
|
||||
pport->Group[1].PMUX[11].bit.PMUXE = 7; //PB22, function column H for USB SOF_1KHz output
|
||||
pport->Group[1].PINCFG[22].bit.PMUXEN = 1;
|
||||
|
||||
//configure and enable DFLL for USB clock recovery mode at 48MHz
|
||||
posc->DFLLCTRLA.bit.ENABLE = 0;
|
||||
while (posc->DFLLSYNC.bit.ENABLE) { DBGC(DC_USB2422_INIT_OSC_SYNC_DISABLING); }
|
||||
while (posc->DFLLSYNC.bit.DFLLCTRLB) { DBGC(DC_USB2422_INIT_OSC_SYNC_DFLLCTRLB_1); }
|
||||
posc->DFLLCTRLB.bit.USBCRM = 1;
|
||||
while (posc->DFLLSYNC.bit.DFLLCTRLB) { DBGC(DC_USB2422_INIT_OSC_SYNC_DFLLCTRLB_2); }
|
||||
posc->DFLLCTRLB.bit.MODE = 1;
|
||||
while (posc->DFLLSYNC.bit.DFLLCTRLB) { DBGC(DC_USB2422_INIT_OSC_SYNC_DFLLCTRLB_3); }
|
||||
posc->DFLLCTRLB.bit.QLDIS = 0;
|
||||
while (posc->DFLLSYNC.bit.DFLLCTRLB) { DBGC(DC_USB2422_INIT_OSC_SYNC_DFLLCTRLB_4); }
|
||||
posc->DFLLCTRLB.bit.CCDIS = 1;
|
||||
posc->DFLLMUL.bit.MUL = 0xBB80; //4800 x 1KHz
|
||||
while (posc->DFLLSYNC.bit.DFLLMUL) { DBGC(DC_USB2422_INIT_OSC_SYNC_DFLLMUL); }
|
||||
posc->DFLLCTRLA.bit.ENABLE = 1;
|
||||
while (posc->DFLLSYNC.bit.ENABLE) { DBGC(DC_USB2422_INIT_OSC_SYNC_ENABLING); }
|
||||
|
||||
pusb->DEVICE.CTRLA.bit.SWRST = 1;
|
||||
while (pusb->DEVICE.SYNCBUSY.bit.SWRST) { DBGC(DC_USB2422_INIT_USB_SYNC_SWRST); }
|
||||
while (pusb->DEVICE.CTRLA.bit.SWRST) { DBGC(DC_USB2422_INIT_USB_WAIT_SWRST); }
|
||||
//calibration from factory presets
|
||||
pusb->DEVICE.PADCAL.bit.TRANSN = (USB_FUSES_TRANSN_ADDR >> USB_FUSES_TRANSN_Pos) & USB_FUSES_TRANSN_Msk;
|
||||
pusb->DEVICE.PADCAL.bit.TRANSP = (USB_FUSES_TRANSP_ADDR >> USB_FUSES_TRANSP_Pos) & USB_FUSES_TRANSP_Msk;
|
||||
pusb->DEVICE.PADCAL.bit.TRIM = (USB_FUSES_TRIM_ADDR >> USB_FUSES_TRIM_Pos) & USB_FUSES_TRIM_Msk;
|
||||
//device mode, enabled
|
||||
pusb->DEVICE.CTRLB.bit.SPDCONF = 0; //full speed
|
||||
pusb->DEVICE.CTRLA.bit.MODE = 0;
|
||||
pusb->DEVICE.CTRLA.bit.ENABLE = 1;
|
||||
while (pusb->DEVICE.SYNCBUSY.bit.ENABLE) { DBGC(DC_USB2422_INIT_USB_SYNC_ENABLING); }
|
||||
|
||||
pusb->DEVICE.QOSCTRL.bit.DQOS = 2;
|
||||
pusb->DEVICE.QOSCTRL.bit.CQOS = 2;
|
||||
|
||||
pport->Group[USB2422_HUB_ACTIVE_GROUP].PINCFG[USB2422_HUB_ACTIVE_PIN].bit.INEN = 1;
|
||||
|
||||
i2c0_init(); //IC2 clk must be high at USB2422 reset release time to signal SMB configuration
|
||||
|
||||
sr_exp_data.bit.HUB_CONNECT = 1; //connect signal
|
||||
sr_exp_data.bit.HUB_RESET_N = 1; //reset high
|
||||
SR_EXP_WriteData();
|
||||
|
||||
CLK_delay_us(100);
|
||||
|
||||
#ifndef MD_BOOTLOADER
|
||||
|
||||
usb_extra_manual = 0;
|
||||
usb_gcr_auto = 1;
|
||||
|
||||
#endif //MD_BOOTLOADER
|
||||
|
||||
DBGC(DC_USB2422_INIT_COMPLETE);
|
||||
}
|
||||
|
||||
void USB_reset(void)
|
||||
{
|
||||
DBGC(DC_USB_RESET_BEGIN);
|
||||
|
||||
//pulse reset for at least 1 usec
|
||||
sr_exp_data.bit.HUB_RESET_N = 0; //reset low
|
||||
SR_EXP_WriteData();
|
||||
CLK_delay_us(1);
|
||||
sr_exp_data.bit.HUB_RESET_N = 1; //reset high to run
|
||||
SR_EXP_WriteData();
|
||||
CLK_delay_us(1);
|
||||
|
||||
DBGC(DC_USB_RESET_COMPLETE);
|
||||
}
|
||||
|
||||
void USB_configure(void)
|
||||
{
|
||||
Usb2422 *pusb2422 = &USB2422_shadow;
|
||||
memset(pusb2422, 0, sizeof(Usb2422));
|
||||
|
||||
uint16_t *serial_use = (uint16_t *)SERNAME; //Default to use SERNAME from this file
|
||||
uint8_t serial_length = sizeof(SERNAME) / sizeof(uint16_t); //Default to use SERNAME from this file
|
||||
#ifndef MD_BOOTLOADER
|
||||
uint32_t serial_ptrloc = (uint32_t)&_srom - 4;
|
||||
#else //MD_BOOTLOADER
|
||||
uint32_t serial_ptrloc = (uint32_t)&_erom - 4;
|
||||
#endif //MD_BOOTLOADER
|
||||
uint32_t serial_address = *(uint32_t *)serial_ptrloc; //Address of bootloader's serial number if available
|
||||
|
||||
DBGC(DC_USB_CONFIGURE_BEGIN);
|
||||
|
||||
if (serial_address != 0xFFFFFFFF && serial_address < serial_ptrloc) //Check for factory programmed serial address
|
||||
{
|
||||
if ((serial_address & 0xFF) % 4 == 0) //Check alignment
|
||||
{
|
||||
serial_use = (uint16_t *)(serial_address);
|
||||
serial_length = 0;
|
||||
while ((*(serial_use + serial_length) > 32 && *(serial_use + serial_length) < 127) &&
|
||||
serial_length < BOOTLOADER_SERIAL_MAX_SIZE)
|
||||
{
|
||||
serial_length++;
|
||||
DBGC(DC_USB_CONFIGURE_GET_SERIAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//configure Usb2422 registers
|
||||
pusb2422->VID.reg = 0x04D8; // from Microchip 4/19/2018
|
||||
pusb2422->PID.reg = 0xEEC5; // from Microchip 4/19/2018 = Massdrop, Inc. USB Hub
|
||||
pusb2422->DID.reg = 0x0101; // BCD 01.01
|
||||
pusb2422->CFG1.bit.SELF_BUS_PWR = 1; // self powered for now
|
||||
pusb2422->CFG1.bit.HS_DISABLE = 1; // full or high speed
|
||||
//pusb2422->CFG2.bit.COMPOUND = 0; // compound device
|
||||
pusb2422->CFG3.bit.STRING_EN = 1; // strings enabled
|
||||
//pusb2422->NRD.bit.PORT2_NR = 0; // MCU is non-removable
|
||||
pusb2422->MAXPB.reg = 20; // 0mA
|
||||
pusb2422->HCMCB.reg = 20; // 0mA
|
||||
pusb2422->MFRSL.reg = sizeof(MFRNAME) / sizeof(uint16_t);
|
||||
pusb2422->PRDSL.reg = sizeof(PRDNAME) / sizeof(uint16_t);
|
||||
pusb2422->SERSL.reg = serial_length;
|
||||
memcpy(pusb2422->MFRSTR, MFRNAME, sizeof(MFRNAME));
|
||||
memcpy(pusb2422->PRDSTR, PRDNAME, sizeof(PRDNAME));
|
||||
memcpy(pusb2422->SERSTR, serial_use, serial_length * sizeof(uint16_t));
|
||||
//pusb2422->BOOSTUP.bit.BOOST=3; //upstream port
|
||||
//pusb2422->BOOSTDOWN.bit.BOOST1=0; // extra port
|
||||
//pusb2422->BOOSTDOWN.bit.BOOST2=2; //MCU is close
|
||||
pusb2422->STCD.bit.USB_ATTACH = 1;
|
||||
USB_write2422_block();
|
||||
|
||||
adc_extra = 0;
|
||||
|
||||
DBGC(DC_USB_CONFIGURE_COMPLETE);
|
||||
}
|
||||
|
||||
uint16_t USB_active(void)
|
||||
{
|
||||
return (PORT->Group[USB2422_HUB_ACTIVE_GROUP].IN.reg & (1 << USB2422_HUB_ACTIVE_PIN)) != 0;
|
||||
}
|
||||
|
||||
void USB_set_host_by_voltage(void)
|
||||
{
|
||||
//UP is upstream device (HOST)
|
||||
//DN1 is downstream device (EXTRA)
|
||||
//DN2 is keyboard (KEYB)
|
||||
|
||||
DBGC(DC_USB_SET_HOST_BY_VOLTAGE_BEGIN);
|
||||
|
||||
usb_host_port = USB_HOST_PORT_UNKNOWN;
|
||||
#ifndef MD_BOOTLOADER
|
||||
usb_extra_state = USB_EXTRA_STATE_UNKNOWN;
|
||||
#endif //MD_BOOTLOADER
|
||||
sr_exp_data.bit.SRC_1 = 1; //USBC-1 available for test
|
||||
sr_exp_data.bit.SRC_2 = 1; //USBC-2 available for test
|
||||
sr_exp_data.bit.E_UP_N = 1; //HOST disable
|
||||
sr_exp_data.bit.E_DN1_N = 1; //EXTRA disable
|
||||
sr_exp_data.bit.E_VBUS_1 = 0; //USBC-1 disable full power I/O
|
||||
sr_exp_data.bit.E_VBUS_2 = 0; //USBC-2 disable full power I/O
|
||||
|
||||
SR_EXP_WriteData();
|
||||
|
||||
CLK_delay_ms(250);
|
||||
|
||||
while ((v_5v = adc_get(ADC_5V)) < ADC_5V_START_LEVEL) { DBGC(DC_USB_SET_HOST_5V_LOW_WAITING); }
|
||||
|
||||
v_con_1 = adc_get(ADC_CON1);
|
||||
v_con_2 = adc_get(ADC_CON2);
|
||||
|
||||
v_con_1_boot = v_con_1;
|
||||
v_con_2_boot = v_con_2;
|
||||
|
||||
if (v_con_1 > v_con_2)
|
||||
{
|
||||
sr_exp_data.bit.S_UP = 0; //HOST to USBC-1
|
||||
sr_exp_data.bit.S_DN1 = 1; //EXTRA to USBC-2
|
||||
sr_exp_data.bit.SRC_1 = 1; //HOST on USBC-1
|
||||
sr_exp_data.bit.SRC_2 = 0; //EXTRA available on USBC-2
|
||||
|
||||
sr_exp_data.bit.E_VBUS_1 = 1; //USBC-1 enable full power I/O
|
||||
sr_exp_data.bit.E_VBUS_2 = 0; //USBC-2 disable full power I/O
|
||||
|
||||
SR_EXP_WriteData();
|
||||
|
||||
sr_exp_data.bit.E_UP_N = 0; //HOST enable
|
||||
|
||||
SR_EXP_WriteData();
|
||||
|
||||
usb_host_port = USB_HOST_PORT_1;
|
||||
}
|
||||
else
|
||||
{
|
||||
sr_exp_data.bit.S_UP = 1; //EXTRA to USBC-1
|
||||
sr_exp_data.bit.S_DN1 = 0; //HOST to USBC-2
|
||||
sr_exp_data.bit.SRC_1 = 0; //EXTRA available on USBC-1
|
||||
sr_exp_data.bit.SRC_2 = 1; //HOST on USBC-2
|
||||
|
||||
sr_exp_data.bit.E_VBUS_1 = 0; //USBC-1 disable full power I/O
|
||||
sr_exp_data.bit.E_VBUS_2 = 1; //USBC-2 enable full power I/O
|
||||
|
||||
SR_EXP_WriteData();
|
||||
|
||||
sr_exp_data.bit.E_UP_N = 0; //HOST enable
|
||||
|
||||
SR_EXP_WriteData();
|
||||
|
||||
usb_host_port = USB_HOST_PORT_2;
|
||||
}
|
||||
|
||||
#ifndef MD_BOOTLOADER
|
||||
usb_extra_state = USB_EXTRA_STATE_DISABLED;
|
||||
#endif //MD_BOOTLOADER
|
||||
|
||||
USB_reset();
|
||||
USB_configure();
|
||||
|
||||
DBGC(DC_USB_SET_HOST_BY_VOLTAGE_COMPLETE);
|
||||
}
|
||||
|
||||
uint8_t USB2422_Port_Detect_Init(void)
|
||||
{
|
||||
uint32_t port_detect_retry_ms;
|
||||
uint32_t tmod;
|
||||
|
||||
DBGC(DC_PORT_DETECT_INIT_BEGIN);
|
||||
|
||||
USB_set_host_by_voltage();
|
||||
|
||||
port_detect_retry_ms = CLK_get_ms() + PORT_DETECT_RETRY_INTERVAL;
|
||||
|
||||
while (!USB_active())
|
||||
{
|
||||
tmod = CLK_get_ms() % PORT_DETECT_RETRY_INTERVAL;
|
||||
|
||||
if (v_con_1 > v_con_2) //Values updated from USB_set_host_by_voltage();
|
||||
{
|
||||
//1 flash for port 1 detected
|
||||
if (tmod > 500 && tmod < 600) { DBG_LED_ON; }
|
||||
else { DBG_LED_OFF; }
|
||||
}
|
||||
else if (v_con_2 > v_con_1) //Values updated from USB_set_host_by_voltage();
|
||||
{
|
||||
//2 flash for port 2 detected
|
||||
if (tmod > 500 && tmod < 600) { DBG_LED_ON; }
|
||||
else if (tmod > 700 && tmod < 800) { DBG_LED_ON; }
|
||||
else { DBG_LED_OFF; }
|
||||
}
|
||||
|
||||
if (CLK_get_ms() > port_detect_retry_ms)
|
||||
{
|
||||
DBGC(DC_PORT_DETECT_INIT_FAILED);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
DBGC(DC_PORT_DETECT_INIT_COMPLETE);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef MD_BOOTLOADER
|
||||
|
||||
void USB_ExtraSetState(uint8_t state)
|
||||
{
|
||||
uint8_t state_save = state;
|
||||
|
||||
if (state == USB_EXTRA_STATE_DISABLED_UNTIL_REPLUG)
|
||||
state = USB_EXTRA_STATE_DISABLED;
|
||||
|
||||
if (usb_host_port == USB_HOST_PORT_1) sr_exp_data.bit.E_VBUS_2 = state;
|
||||
else if (usb_host_port == USB_HOST_PORT_2) sr_exp_data.bit.E_VBUS_1 = state;
|
||||
else return;
|
||||
|
||||
sr_exp_data.bit.E_DN1_N = !state;
|
||||
SR_EXP_WriteData();
|
||||
|
||||
usb_extra_state = state_save;
|
||||
|
||||
if (usb_extra_state == USB_EXTRA_STATE_ENABLED) CDC_print("USB: Extra enabled\r\n");
|
||||
else if (usb_extra_state == USB_EXTRA_STATE_DISABLED)
|
||||
{
|
||||
CDC_print("USB: Extra disabled\r\n");
|
||||
if (led_animation_breathing) gcr_breathe = gcr_desired;
|
||||
}
|
||||
else if (usb_extra_state == USB_EXTRA_STATE_DISABLED_UNTIL_REPLUG) CDC_print("USB: Extra disabled until replug\r\n");
|
||||
else CDC_print("USB: Extra state unknown\r\n");
|
||||
}
|
||||
|
||||
void USB_HandleExtraDevice(void)
|
||||
{
|
||||
uint16_t adcval;
|
||||
|
||||
if (usb_host_port == USB_HOST_PORT_1) adcval = adc_get(ADC_CON2);
|
||||
else if (usb_host_port == USB_HOST_PORT_2) adcval = adc_get(ADC_CON1);
|
||||
else return;
|
||||
|
||||
adc_extra = adc_extra * 0.9 + adcval * 0.1;
|
||||
|
||||
//Check for a forced disable state (such as overload prevention)
|
||||
if (usb_extra_state == USB_EXTRA_STATE_DISABLED_UNTIL_REPLUG)
|
||||
{
|
||||
//Detect unplug and reset state to disabled
|
||||
if (adc_extra > USB_EXTRA_ADC_THRESHOLD) usb_extra_state = USB_EXTRA_STATE_DISABLED;
|
||||
|
||||
return; //Return even if unplug detected
|
||||
}
|
||||
|
||||
if (usb_extra_manual)
|
||||
{
|
||||
if (usb_extra_state == USB_EXTRA_STATE_DISABLED)
|
||||
USB_ExtraSetState(USB_EXTRA_STATE_ENABLED);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//dpf("a %i %i\r\n",adcval, adc_extra);
|
||||
if (usb_extra_state == USB_EXTRA_STATE_DISABLED && adc_extra < USB_EXTRA_ADC_THRESHOLD) USB_ExtraSetState(USB_EXTRA_STATE_ENABLED);
|
||||
else if (usb_extra_state == USB_EXTRA_STATE_ENABLED && adc_extra > USB_EXTRA_ADC_THRESHOLD) USB_ExtraSetState(USB_EXTRA_STATE_DISABLED);
|
||||
}
|
||||
|
||||
#endif //MD_BOOTLOADER
|
||||
|
404
tmk_core/protocol/arm_atsam/usb/usb2422.h
Normal file
404
tmk_core/protocol/arm_atsam/usb/usb2422.h
Normal file
|
@ -0,0 +1,404 @@
|
|||
/*
|
||||
Copyright 2018 Massdrop Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _USB2422_H_
|
||||
#define _USB2422_H_
|
||||
|
||||
#define REV_USB2422 0x100
|
||||
|
||||
#define USB2422_ADDR 0x58 //I2C device address, one instance
|
||||
|
||||
#define USB2422_HUB_ACTIVE_GROUP 0 //PA
|
||||
#define USB2422_HUB_ACTIVE_PIN 18 //18
|
||||
|
||||
/* -------- USB2422_VID : (USB2422L Offset: 0x00) (R/W 16) Vendor ID -------- */
|
||||
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
|
||||
typedef union {
|
||||
struct {
|
||||
uint16_t VID_LSB : 8;
|
||||
uint16_t VID_MSB : 8;
|
||||
} bit; /*!< Structure used for bit access */
|
||||
uint16_t reg; /*!< Type used for register access */
|
||||
} USB2422_VID_Type;
|
||||
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
|
||||
|
||||
/* -------- USB2422_PID : (USB2422L Offset: 0x02) (R/W 16) Product ID -------- */
|
||||
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
|
||||
typedef union {
|
||||
struct {
|
||||
uint16_t PID_LSB : 8;
|
||||
uint16_t PID_MSB : 8;
|
||||
} bit; /*!< Structure used for bit access */
|
||||
uint16_t reg; /*!< Type used for register access */
|
||||
} USB2422_PID_Type;
|
||||
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
|
||||
|
||||
/* -------- USB2422_DID : (USB2422L Offset: 0x04) (R/W 16) Device ID -------- */
|
||||
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
|
||||
typedef union {
|
||||
struct {
|
||||
uint16_t DID_LSB : 8;
|
||||
uint16_t DID_MSB : 8;
|
||||
} bit; /*!< Structure used for bit access */
|
||||
uint16_t reg; /*!< Type used for register access */
|
||||
} USB2422_DID_Type;
|
||||
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
|
||||
|
||||
/* -------- USB2422_CFG1 : (USB2422L Offset: 0x06) (R/W 8) Configuration Data Byte 1-------- */
|
||||
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t PORT_PWR : 1;
|
||||
uint8_t CURRENT_SNS : 2;
|
||||
uint8_t EOP_DISABLE : 1;
|
||||
uint8_t MTT_ENABLE : 1;
|
||||
uint8_t HS_DISABLE :1;
|
||||
uint8_t :1;
|
||||
uint8_t SELF_BUS_PWR : 1;
|
||||
} bit; /*!< Structure used for bit access */
|
||||
uint8_t reg; /*!< Type used for register access */
|
||||
} USB2422_CFG1_Type;
|
||||
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
|
||||
|
||||
/* -------- USB2422_CFG2 : (USB2422L Offset: 0x07) (R/W 8) Configuration Data Byte 2-------- */
|
||||
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t : 3;
|
||||
uint8_t COMPOUND : 1;
|
||||
uint8_t OC_TIMER :2;
|
||||
uint8_t :1;
|
||||
uint8_t DYNAMIC : 1;
|
||||
} bit; /*!< Structure used for bit access */
|
||||
uint8_t reg; /*!< Type used for register access */
|
||||
} USB2422_CFG2_Type;
|
||||
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
|
||||
|
||||
/* -------- USB2422_CFG3 : (USB2422L Offset: 0x08) (R/W 16) Configuration Data Byte 3-------- */
|
||||
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t STRING_EN : 1;
|
||||
uint8_t :2;
|
||||
uint8_t PRTMAP_EN :1;
|
||||
uint8_t : 4;
|
||||
} bit; /*!< Structure used for bit access */
|
||||
uint8_t reg; /*!< Type used for register access */
|
||||
} USB2422_CFG3_Type;
|
||||
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
|
||||
|
||||
/* -------- USB2422_NRD : (USB2422L Offset: 0x09) (R/W 8) Non Removable Device -------- */
|
||||
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t : 5;
|
||||
uint8_t PORT2_NR :1;
|
||||
uint8_t PORT1_NR :1;
|
||||
uint8_t : 1;
|
||||
} bit; /*!< Structure used for bit access */
|
||||
uint8_t reg; /*!< Type used for register access */
|
||||
} USB2422_NRD_Type;
|
||||
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
|
||||
|
||||
/* -------- USB2422_PDS : (USB2422L Offset: 0x0A) (R/W 8) Port Diable for Self-Powered Operation -------- */
|
||||
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t : 1;
|
||||
uint8_t PORT1_DIS :1;
|
||||
uint8_t PORT2_DIS :1;
|
||||
uint8_t : 5;
|
||||
} bit; /*!< Structure used for bit access */
|
||||
uint8_t reg; /*!< Type used for register access */
|
||||
} USB2422_PDS_Type;
|
||||
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
|
||||
|
||||
/* -------- USB2422_PDB : (USB2422L Offset: 0x0B) (R/W 8) Port Diable for Bus-Powered Operation -------- */
|
||||
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t : 1;
|
||||
uint8_t PORT1_DIS :1;
|
||||
uint8_t PORT2_DIS :1;
|
||||
uint8_t : 5;
|
||||
} bit; /*!< Structure used for bit access */
|
||||
uint8_t reg; /*!< Type used for register access */
|
||||
} USB2422_PDB_Type;
|
||||
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
|
||||
|
||||
/* -------- USB2422_MAXPS : (USB2422L Offset: 0x0C) (R/W 8) Max Power for Self-Powered Operation -------- */
|
||||
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t MAX_PWR_SP : 8;
|
||||
} bit; /*!< Structure used for bit access */
|
||||
uint8_t reg; /*!< Type used for register access */
|
||||
} USB2422_MAXPS_Type;
|
||||
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
|
||||
|
||||
/* -------- USB2422_MAXPB : (USB2422L Offset: 0x0D) (R/W 8) Max Power for Bus-Powered Operation -------- */
|
||||
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t MAX_PWR_BP : 8;
|
||||
} bit; /*!< Structure used for bit access */
|
||||
uint8_t reg; /*!< Type used for register access */
|
||||
} USB2422_MAXPB_Type;
|
||||
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
|
||||
|
||||
/* -------- USB2422_HCMCS : (USB2422L Offset: 0x0E) (R/W 8) Hub Controller Max Current for Self-Powered Operation -------- */
|
||||
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t HC_MAX_C_SP : 8;
|
||||
} bit; /*!< Structure used for bit access */
|
||||
uint8_t reg; /*!< Type used for register access */
|
||||
} USB2422_HCMCS_Type;
|
||||
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
|
||||
|
||||
/* -------- USB2422_HCMCB : (USB2422L Offset: 0x0F) (R/W 8) Hub Controller Max Current for Bus-Powered Operation -------- */
|
||||
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t HC_MAX_C_BP : 8;
|
||||
} bit; /*!< Structure used for bit access */
|
||||
uint8_t reg; /*!< Type used for register access */
|
||||
} USB2422_HCMCB_Type;
|
||||
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
|
||||
|
||||
/* -------- USB2422_PWRT : (USB2422L Offset: 0x10) (R/W 8) Power On Time -------- */
|
||||
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t POWER_ON_TIME : 8;
|
||||
} bit; /*!< Structure used for bit access */
|
||||
uint8_t reg; /*!< Type used for register access */
|
||||
} USB2422_PWRT_Type;
|
||||
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
|
||||
|
||||
/* -------- USB2422_LANGID LSB : (USB2422L Offset: 0x11) (R/W 16) Language ID -------- */
|
||||
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t LANGID_LSB : 8;
|
||||
} bit; /*!< Structure used for bit access */
|
||||
uint8_t reg; /*!< Type used for register access */
|
||||
} USB2422_LANGID_LSB_Type;
|
||||
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
|
||||
|
||||
/* -------- USB2422_LANGID MSB : (USB2422L Offset: 0x12) (R/W 16) Language ID -------- */
|
||||
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t LANGID_MSB : 8;
|
||||
} bit; /*!< Structure used for bit access */
|
||||
uint8_t reg; /*!< Type used for register access */
|
||||
} USB2422_LANGID_MSB_Type;
|
||||
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
|
||||
|
||||
|
||||
/* -------- USB2422_MFRSL : (USB2422L Offset: 0x13) (R/W 8) Manufacturer String Length -------- */
|
||||
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t MFR_STR_LEN : 8;
|
||||
} bit; /*!< Structure used for bit access */
|
||||
uint8_t reg; /*!< Type used for register access */
|
||||
} USB2422_MFRSL_Type;
|
||||
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
|
||||
|
||||
/* -------- USB2422_PRDSL : (USB2422L Offset: 0x14) (R/W 8) Product String Length -------- */
|
||||
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t PRD_STR_LEN : 8;
|
||||
} bit; /*!< Structure used for bit access */
|
||||
uint8_t reg; /*!< Type used for register access */
|
||||
} USB2422_PRDSL_Type;
|
||||
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
|
||||
|
||||
/* -------- USB2422_SERSL : (USB2422L Offset: 0x15) (R/W 8) Serial String Length -------- */
|
||||
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t SER_STR_LEN : 8;
|
||||
} bit; /*!< Structure used for bit access */
|
||||
uint8_t reg; /*!< Type used for register access */
|
||||
} USB2422_SERSL_Type;
|
||||
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
|
||||
|
||||
/* -------- USB2422_MFRSTR : (USB2422L Offset: 0x16-53) (R/W 8) Maufacturer String -------- */
|
||||
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
|
||||
typedef uint16_t USB2422_MFRSTR_Type;
|
||||
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
|
||||
|
||||
/* -------- USB2422_PRDSTR : (USB2422L Offset: 0x54-91) (R/W 8) Product String -------- */
|
||||
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
|
||||
typedef uint16_t USB2422_PRDSTR_Type;
|
||||
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
|
||||
|
||||
/* -------- USB2422_SERSTR : (USB2422L Offset: 0x92-CF) (R/W 8) Serial String -------- */
|
||||
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
|
||||
typedef uint16_t USB2422_SERSTR_Type;
|
||||
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
|
||||
|
||||
/* -------- USB2422_BCEN : (USB2422L Offset: 0xD0) (R/W 8) Battery Charging Enable -------- */
|
||||
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t : 1;
|
||||
uint8_t PORT1_BCE :1;
|
||||
uint8_t PORT2_BCE :1;
|
||||
uint8_t : 5;
|
||||
} bit; /*!< Structure used for bit access */
|
||||
uint8_t reg; /*!< Type used for register access */
|
||||
} USB2422_BCEN_Type;
|
||||
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
|
||||
|
||||
/* -------- USB2422_BOOSTUP : (USB2422L Offset: 0xF6) (R/W 8) Boost Upstream -------- */
|
||||
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t BOOST :2;
|
||||
uint8_t : 6;
|
||||
} bit; /*!< Structure used for bit access */
|
||||
uint8_t reg; /*!< Type used for register access */
|
||||
} USB2422_BOOSTUP_Type;
|
||||
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
|
||||
|
||||
/* -------- USB2422_BOOSTDOWN : (USB2422L Offset: 0xF8) (R/W 8) Boost Downstream -------- */
|
||||
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t BOOST1 :2;
|
||||
uint8_t BOOST2 :2;
|
||||
uint8_t : 4;
|
||||
} bit; /*!< Structure used for bit access */
|
||||
uint8_t reg; /*!< Type used for register access */
|
||||
} USB2422_BOOSTDOWN_Type;
|
||||
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
|
||||
|
||||
/* -------- USB2422_PRTSP : (USB2422L Offset: 0xFA) (R/W 8) Port Swap -------- */
|
||||
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t : 1;
|
||||
uint8_t PORT1_SP :1;
|
||||
uint8_t PORT2_SP :1;
|
||||
uint8_t : 5;
|
||||
} bit; /*!< Structure used for bit access */
|
||||
uint8_t reg; /*!< Type used for register access */
|
||||
} USB2422_PRTSP_Type;
|
||||
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
|
||||
|
||||
/* -------- USB2422_PRTR12 : (USB2422L Offset: 0xFB) (R/W 8) Port 1/2 Remap -------- */
|
||||
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t PORT1_REMAP: 4;
|
||||
uint8_t PORT2_REMAP: 4;
|
||||
} bit; /*!< Structure used for bit access */
|
||||
uint8_t reg; /*!< Type used for register access */
|
||||
} USB2422_PRTR12_Type;
|
||||
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
|
||||
#define USB2422_PRTR12_DISABLE 0
|
||||
#define USB2422_PRT12_P2TOL1 1
|
||||
#define USB2422_PRT12_P2XTOL2 2
|
||||
#define USB2422_PRT12_P1TOL1 1
|
||||
#define USB2422_PRT12_P1XTOL2 2
|
||||
|
||||
/* -------- USB2422_STCD : (USB2422L Offset: 0xFF) (R/W 8) Status Command -------- */
|
||||
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t USB_ATTACH: 1;
|
||||
uint8_t RESET: 1;
|
||||
uint8_t INTF_PWRDN: 1;
|
||||
uint8_t : 5;
|
||||
} bit; /*!< Structure used for bit access */
|
||||
uint8_t reg; /*!< Type used for register access */
|
||||
} USB2422_STCD_Type;
|
||||
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
|
||||
|
||||
/** \brief USB2422 device hardware registers */
|
||||
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
|
||||
typedef struct {
|
||||
USB2422_VID_Type VID; /**< \brief Offset: 0x00*/
|
||||
USB2422_PID_Type PID; /**< \brief Offset: 0x02*/
|
||||
USB2422_DID_Type DID; /**< \brief Offset: 0x04*/
|
||||
USB2422_CFG1_Type CFG1; /**< \brief Offset: 0x06*/
|
||||
USB2422_CFG2_Type CFG2; /**< \brief Offset: 0x07*/
|
||||
USB2422_CFG3_Type CFG3; /**< \brief Offset: 0x08*/
|
||||
USB2422_NRD_Type NRD; /**< \brief Offset: 0x09*/
|
||||
USB2422_PDS_Type PDS; /**< \brief Offset: 0x0A*/
|
||||
USB2422_PDB_Type PDB; /**< \brief Offset: 0x0B*/
|
||||
USB2422_MAXPS_Type MAXPS; /**< \brief Offset: 0x0C*/
|
||||
USB2422_MAXPB_Type MAXPB; /**< \brief Offset: 0x0D*/
|
||||
USB2422_HCMCS_Type HCMCS; /**< \brief Offset: 0x0E*/
|
||||
USB2422_HCMCB_Type HCMCB; /**< \brief Offset: 0x0F*/
|
||||
USB2422_PWRT_Type PWRT; /**< \brief Offset: 0x10*/
|
||||
USB2422_LANGID_LSB_Type LANGID_LSB; /**< \brief Offset: 0x11*/
|
||||
USB2422_LANGID_MSB_Type LANGID_MSB; /**< \brief Offset: 0x12*/
|
||||
USB2422_MFRSL_Type MFRSL; /**< \brief Offset: 0x13*/
|
||||
USB2422_PRDSL_Type PRDSL; /**< \brief Offset: 0x14*/
|
||||
USB2422_SERSL_Type SERSL; /**< \brief Offset: 0x15*/
|
||||
USB2422_MFRSTR_Type MFRSTR[31]; /**< \brief Offset: 0x16*/
|
||||
USB2422_PRDSTR_Type PRDSTR[31]; /**< \brief Offset: 0x54*/
|
||||
USB2422_SERSTR_Type SERSTR[31]; /**< \brief Offset: 0x92*/
|
||||
USB2422_BCEN_Type BCEN; /**< \brief Offset: 0xD0*/
|
||||
uint8_t Reserved1[0x25];
|
||||
USB2422_BOOSTUP_Type BOOSTUP; /**< \brief Offset: 0xF6*/
|
||||
uint8_t Reserved2[0x1];
|
||||
USB2422_BOOSTDOWN_Type BOOSTDOWN; /**< \brief Offset: 0xF8*/
|
||||
uint8_t Reserved3[0x1];
|
||||
USB2422_PRTSP_Type PRTSP; /**< \brief Offset: 0xFA*/
|
||||
USB2422_PRTR12_Type PRTR12; /**< \brief Offset: 0xFB*/
|
||||
uint8_t Reserved4[0x3];
|
||||
USB2422_STCD_Type STCD; /**< \brief Offset: 0xFF*/
|
||||
} Usb2422;
|
||||
#endif
|
||||
|
||||
#define PORT_DETECT_RETRY_INTERVAL 2000
|
||||
|
||||
#define USB_EXTRA_ADC_THRESHOLD 900
|
||||
|
||||
#define USB_EXTRA_STATE_DISABLED 0
|
||||
#define USB_EXTRA_STATE_ENABLED 1
|
||||
#define USB_EXTRA_STATE_UNKNOWN 2
|
||||
#define USB_EXTRA_STATE_DISABLED_UNTIL_REPLUG 3
|
||||
|
||||
#define USB_HOST_PORT_1 0
|
||||
#define USB_HOST_PORT_2 1
|
||||
#define USB_HOST_PORT_UNKNOWN 2
|
||||
|
||||
extern uint8_t usb_host_port;
|
||||
extern uint8_t usb_extra_state;
|
||||
extern uint8_t usb_extra_manual;
|
||||
extern uint8_t usb_gcr_auto;
|
||||
|
||||
void USB2422_init(void);
|
||||
void USB_reset(void);
|
||||
void USB_configure(void);
|
||||
uint16_t USB_active(void);
|
||||
void USB_set_host_by_voltage(void);
|
||||
uint16_t adc_get(uint8_t muxpos);
|
||||
uint8_t USB2422_Port_Detect_Init(void);
|
||||
void USB_HandleExtraDevice(void);
|
||||
void USB_ExtraSetState(uint8_t state);
|
||||
|
||||
#endif //_USB2422_H_
|
||||
|
190
tmk_core/protocol/arm_atsam/usb/usb_atmel.h
Normal file
190
tmk_core/protocol/arm_atsam/usb/usb_atmel.h
Normal file
|
@ -0,0 +1,190 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief All USB VIDs and PIDs from Atmel USB applications
|
||||
*
|
||||
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
|
||||
#ifndef _USB_ATMEL_H_
|
||||
#define _USB_ATMEL_H_
|
||||
|
||||
/**
|
||||
* \defgroup usb_group USB Stack
|
||||
*
|
||||
* This stack includes the USB Device Stack, USB Host Stack and common
|
||||
* definitions.
|
||||
* @{
|
||||
*/
|
||||
|
||||
//! @}
|
||||
|
||||
/**
|
||||
* \ingroup usb_group
|
||||
* \defgroup usb_atmel_ids_group Atmel USB Identifiers
|
||||
*
|
||||
* This module defines Atmel PID and VIDs constants.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
//! \name Vendor Identifier assigned by USB org to ATMEL
|
||||
#define USB_VID_ATMEL 0x03EB
|
||||
|
||||
//! \name Product Identifier assigned by ATMEL to AVR applications
|
||||
//! @{
|
||||
|
||||
//! \name The range from 2000h to 20FFh is reserved to the old PID for C51, MEGA, and others.
|
||||
//! @{
|
||||
#define USB_PID_ATMEL_MEGA_HIDGENERIC 0x2013
|
||||
#define USB_PID_ATMEL_MEGA_HIDKEYBOARD 0x2017
|
||||
#define USB_PID_ATMEL_MEGA_CDC 0x2018
|
||||
#define USB_PID_ATMEL_MEGA_AUDIO_IN 0x2019
|
||||
#define USB_PID_ATMEL_MEGA_MS 0x201A
|
||||
#define USB_PID_ATMEL_MEGA_AUDIO_IN_OUT 0x201B
|
||||
#define USB_PID_ATMEL_MEGA_HIDMOUSE 0x201C
|
||||
#define USB_PID_ATMEL_MEGA_HIDMOUSE_CERTIF_U4 0x201D
|
||||
#define USB_PID_ATMEL_MEGA_CDC_MULTI 0x201E
|
||||
#define USB_PID_ATMEL_MEGA_MS_HIDMS_HID_USBKEY 0x2022
|
||||
#define USB_PID_ATMEL_MEGA_MS_HIDMS_HID_STK525 0x2023
|
||||
#define USB_PID_ATMEL_MEGA_MS_2 0x2029
|
||||
#define USB_PID_ATMEL_MEGA_MS_HIDMS 0x202A
|
||||
#define USB_PID_ATMEL_MEGA_MS_3 0x2032
|
||||
#define USB_PID_ATMEL_MEGA_LIBUSB 0x2050
|
||||
//! @}
|
||||
|
||||
//! \name The range 2100h to 21FFh is reserved to PIDs for AVR Tools.
|
||||
//! @{
|
||||
#define USB_PID_ATMEL_XPLAINED 0x2122
|
||||
#define USB_PID_ATMEL_XMEGA_USB_ZIGBIT_2_4GHZ 0x214A
|
||||
#define USB_PID_ATMEL_XMEGA_USB_ZIGBIT_SUBGHZ 0x214B
|
||||
//! @}
|
||||
|
||||
//! \name The range 2300h to 23FFh is reserved to PIDs for demo from ASF1.7=>
|
||||
//! @{
|
||||
#define USB_PID_ATMEL_UC3_ENUM 0x2300
|
||||
#define USB_PID_ATMEL_UC3_MS 0x2301
|
||||
#define USB_PID_ATMEL_UC3_MS_SDRAM_LOADER 0x2302
|
||||
#define USB_PID_ATMEL_UC3_EVK1100_CTRLPANEL 0x2303
|
||||
#define USB_PID_ATMEL_UC3_HID 0x2304
|
||||
#define USB_PID_ATMEL_UC3_EVK1101_CTRLPANEL_HID 0x2305
|
||||
#define USB_PID_ATMEL_UC3_EVK1101_CTRLPANEL_HID_MS 0x2306
|
||||
#define USB_PID_ATMEL_UC3_CDC 0x2307
|
||||
#define USB_PID_ATMEL_UC3_AUDIO_MICRO 0x2308
|
||||
#define USB_PID_ATMEL_UC3_CDC_DEBUG 0x2310 // Virtual Com (debug interface) on EVK11xx
|
||||
#define USB_PID_ATMEL_UC3_AUDIO_SPEAKER_MICRO 0x2311
|
||||
#define USB_PID_ATMEL_UC3_CDC_MSC 0x2312
|
||||
//! @}
|
||||
|
||||
//! \name The range 2400h to 24FFh is reserved to PIDs for ASF applications
|
||||
//! @{
|
||||
#define USB_PID_ATMEL_ASF_HIDMOUSE 0x2400
|
||||
#define USB_PID_ATMEL_ASF_HIDKEYBOARD 0x2401
|
||||
#define USB_PID_ATMEL_ASF_HIDGENERIC 0x2402
|
||||
#define USB_PID_ATMEL_ASF_MSC 0x2403
|
||||
#define USB_PID_ATMEL_ASF_CDC 0x2404
|
||||
#define USB_PID_ATMEL_ASF_PHDC 0x2405
|
||||
#define USB_PID_ATMEL_ASF_HIDMTOUCH 0x2406
|
||||
#define USB_PID_ATMEL_ASF_MSC_HIDMOUSE 0x2420
|
||||
#define USB_PID_ATMEL_ASF_MSC_HIDS_CDC 0x2421
|
||||
#define USB_PID_ATMEL_ASF_MSC_HIDKEYBOARD 0x2422
|
||||
#define USB_PID_ATMEL_ASF_VENDOR_CLASS 0x2423
|
||||
#define USB_PID_ATMEL_ASF_MSC_CDC 0x2424
|
||||
#define USB_PID_ATMEL_ASF_TWO_CDC 0x2425
|
||||
#define USB_PID_ATMEL_ASF_SEVEN_CDC 0x2426
|
||||
#define USB_PID_ATMEL_ASF_XPLAIN_BC_POWERONLY 0x2430
|
||||
#define USB_PID_ATMEL_ASF_XPLAIN_BC_TERMINAL 0x2431
|
||||
#define USB_PID_ATMEL_ASF_XPLAIN_BC_TOUCH 0x2432
|
||||
#define USB_PID_ATMEL_ASF_AUDIO_SPEAKER 0x2433
|
||||
#define USB_PID_ATMEL_ASF_XMEGA_B1_XPLAINED 0x2434
|
||||
//! @}
|
||||
|
||||
//! \name The range 2F00h to 2FFFh is reserved to official PIDs for AVR bootloaders
|
||||
//! Note, !!!! don't use this range for demos or examples !!!!
|
||||
//! @{
|
||||
#define USB_PID_ATMEL_DFU_ATXMEGA64C3 0x2FD6
|
||||
#define USB_PID_ATMEL_DFU_ATXMEGA128C3 0x2FD7
|
||||
#define USB_PID_ATMEL_DFU_ATXMEGA16C4 0x2FD8
|
||||
#define USB_PID_ATMEL_DFU_ATXMEGA32C4 0x2FD9
|
||||
#define USB_PID_ATMEL_DFU_ATXMEGA256C3 0x2FDA
|
||||
#define USB_PID_ATMEL_DFU_ATXMEGA384C3 0x2FDB
|
||||
#define USB_PID_ATMEL_DFU_ATUCL3_L4 0x2FDC
|
||||
#define USB_PID_ATMEL_DFU_ATXMEGA64A4U 0x2FDD
|
||||
#define USB_PID_ATMEL_DFU_ATXMEGA128A4U 0x2FDE
|
||||
|
||||
#define USB_PID_ATMEL_DFU_ATXMEGA64B3 0x2FDF
|
||||
#define USB_PID_ATMEL_DFU_ATXMEGA128B3 0x2FE0
|
||||
#define USB_PID_ATMEL_DFU_ATXMEGA64B1 0x2FE1
|
||||
#define USB_PID_ATMEL_DFU_ATXMEGA256A3BU 0x2FE2
|
||||
#define USB_PID_ATMEL_DFU_ATXMEGA16A4U 0x2FE3
|
||||
#define USB_PID_ATMEL_DFU_ATXMEGA32A4U 0x2FE4
|
||||
#define USB_PID_ATMEL_DFU_ATXMEGA64A3U 0x2FE5
|
||||
#define USB_PID_ATMEL_DFU_ATXMEGA128A3U 0x2FE6
|
||||
#define USB_PID_ATMEL_DFU_ATXMEGA192A3U 0x2FE7
|
||||
#define USB_PID_ATMEL_DFU_ATXMEGA64A1U 0x2FE8
|
||||
#define USB_PID_ATMEL_DFU_ATUC3D 0x2FE9
|
||||
#define USB_PID_ATMEL_DFU_ATXMEGA128B1 0x2FEA
|
||||
#define USB_PID_ATMEL_DFU_AT32UC3C 0x2FEB
|
||||
#define USB_PID_ATMEL_DFU_ATXMEGA256A3U 0x2FEC
|
||||
#define USB_PID_ATMEL_DFU_ATXMEGA128A1U 0x2FED
|
||||
#define USB_PID_ATMEL_DFU_ATMEGA8U2 0x2FEE
|
||||
#define USB_PID_ATMEL_DFU_ATMEGA16U2 0x2FEF
|
||||
#define USB_PID_ATMEL_DFU_ATMEGA32U2 0x2FF0
|
||||
#define USB_PID_ATMEL_DFU_AT32UC3A3 0x2FF1
|
||||
#define USB_PID_ATMEL_DFU_ATMEGA32U6 0x2FF2
|
||||
#define USB_PID_ATMEL_DFU_ATMEGA16U4 0x2FF3
|
||||
#define USB_PID_ATMEL_DFU_ATMEGA32U4 0x2FF4
|
||||
#define USB_PID_ATMEL_DFU_AT32AP7200 0x2FF5
|
||||
#define USB_PID_ATMEL_DFU_AT32UC3B 0x2FF6
|
||||
#define USB_PID_ATMEL_DFU_AT90USB82 0x2FF7
|
||||
#define USB_PID_ATMEL_DFU_AT32UC3A 0x2FF8
|
||||
#define USB_PID_ATMEL_DFU_AT90USB64 0x2FF9
|
||||
#define USB_PID_ATMEL_DFU_AT90USB162 0x2FFA
|
||||
#define USB_PID_ATMEL_DFU_AT90USB128 0x2FFB
|
||||
// 2FFCh to 2FFFh used by C51 family products
|
||||
//! @}
|
||||
|
||||
//! @}
|
||||
|
||||
//! @}
|
||||
|
||||
|
||||
#endif // _USB_ATMEL_H_
|
1097
tmk_core/protocol/arm_atsam/usb/usb_device_udd.c
Normal file
1097
tmk_core/protocol/arm_atsam/usb/usb_device_udd.c
Normal file
File diff suppressed because it is too large
Load diff
103
tmk_core/protocol/arm_atsam/usb/usb_main.h
Normal file
103
tmk_core/protocol/arm_atsam/usb/usb_main.h
Normal file
|
@ -0,0 +1,103 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Declaration of main function used by HID keyboard example
|
||||
*
|
||||
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
|
||||
#ifndef _MAIN_H_
|
||||
#define _MAIN_H_
|
||||
|
||||
//Enters the application in low power mode
|
||||
//Callback called when USB host sets USB line in suspend state
|
||||
void main_suspend_action(void);
|
||||
|
||||
//Called by UDD when the USB line exit of suspend state
|
||||
void main_resume_action(void);
|
||||
|
||||
//Called when a start of frame is received on USB line
|
||||
void main_sof_action(void);
|
||||
|
||||
//Called by UDC when USB Host request to enable remote wakeup
|
||||
void main_remotewakeup_enable(void);
|
||||
|
||||
//Called by UDC when USB Host request to disable remote wakeup
|
||||
void main_remotewakeup_disable(void);
|
||||
|
||||
|
||||
#ifdef KBD
|
||||
extern volatile bool main_b_kbd_enable;
|
||||
bool main_kbd_enable(void);
|
||||
void main_kbd_disable(void);
|
||||
#endif //KBD
|
||||
|
||||
#ifdef NKRO
|
||||
extern volatile bool main_b_nkro_enable;
|
||||
bool main_nkro_enable(void);
|
||||
void main_nkro_disable(void);
|
||||
#endif //NKRO
|
||||
|
||||
#ifdef EXK
|
||||
extern volatile bool main_b_exk_enable;
|
||||
bool main_exk_enable(void);
|
||||
void main_exk_disable(void);
|
||||
#endif //EXK
|
||||
|
||||
#ifdef CON
|
||||
extern volatile bool main_b_con_enable;
|
||||
bool main_con_enable(void);
|
||||
void main_con_disable(void);
|
||||
#endif //CON
|
||||
|
||||
#ifdef MOU
|
||||
extern volatile bool main_b_mou_enable;
|
||||
bool main_mou_enable(void);
|
||||
void main_mou_disable(void);
|
||||
#endif //MOU
|
||||
|
||||
#ifdef RAW
|
||||
extern volatile bool main_b_raw_enable;
|
||||
bool main_raw_enable(void);
|
||||
void main_raw_disable(void);
|
||||
#endif //RAW
|
||||
|
||||
#endif // _MAIN_H_
|
498
tmk_core/protocol/arm_atsam/usb/usb_protocol.h
Normal file
498
tmk_core/protocol/arm_atsam/usb/usb_protocol.h
Normal file
|
@ -0,0 +1,498 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief USB protocol definitions.
|
||||
*
|
||||
* This file contains the USB definitions and data structures provided by the
|
||||
* USB 2.0 specification.
|
||||
*
|
||||
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
|
||||
#ifndef _USB_PROTOCOL_H_
|
||||
#define _USB_PROTOCOL_H_
|
||||
|
||||
#include "usb_atmel.h"
|
||||
|
||||
/**
|
||||
* \ingroup usb_group
|
||||
* \defgroup usb_protocol_group USB Protocol Definitions
|
||||
*
|
||||
* This module defines constants and data structures provided by the USB
|
||||
* 2.0 specification.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
//! Value for field bcdUSB
|
||||
#define USB_V2_0 0x0200 //!< USB Specification version 2.00
|
||||
#define USB_V2_1 0x0201 //!< USB Specification version 2.01
|
||||
|
||||
/*! \name Generic definitions (Class, subclass and protocol)
|
||||
*/
|
||||
//! @{
|
||||
#define NO_CLASS 0x00
|
||||
#define CLASS_VENDOR_SPECIFIC 0xFF
|
||||
#define NO_SUBCLASS 0x00
|
||||
#define NO_PROTOCOL 0x00
|
||||
//! @}
|
||||
|
||||
//! \name IAD (Interface Association Descriptor) constants
|
||||
//! @{
|
||||
#define CLASS_IAD 0xEF
|
||||
#define SUB_CLASS_IAD 0x02
|
||||
#define PROTOCOL_IAD 0x01
|
||||
//! @}
|
||||
|
||||
/**
|
||||
* \brief USB request data transfer direction (bmRequestType)
|
||||
*/
|
||||
#define USB_REQ_DIR_OUT (0<<7) //!< Host to device
|
||||
#define USB_REQ_DIR_IN (1<<7) //!< Device to host
|
||||
#define USB_REQ_DIR_MASK (1<<7) //!< Mask
|
||||
|
||||
/**
|
||||
* \brief USB request types (bmRequestType)
|
||||
*/
|
||||
#define USB_REQ_TYPE_STANDARD (0<<5) //!< Standard request
|
||||
#define USB_REQ_TYPE_CLASS (1<<5) //!< Class-specific request
|
||||
#define USB_REQ_TYPE_VENDOR (2<<5) //!< Vendor-specific request
|
||||
#define USB_REQ_TYPE_MASK (3<<5) //!< Mask
|
||||
|
||||
/**
|
||||
* \brief USB recipient codes (bmRequestType)
|
||||
*/
|
||||
#define USB_REQ_RECIP_DEVICE (0<<0) //!< Recipient device
|
||||
#define USB_REQ_RECIP_INTERFACE (1<<0) //!< Recipient interface
|
||||
#define USB_REQ_RECIP_ENDPOINT (2<<0) //!< Recipient endpoint
|
||||
#define USB_REQ_RECIP_OTHER (3<<0) //!< Recipient other
|
||||
#define USB_REQ_RECIP_MASK (0x1F) //!< Mask
|
||||
|
||||
/**
|
||||
* \brief Standard USB requests (bRequest)
|
||||
*/
|
||||
enum usb_reqid {
|
||||
USB_REQ_GET_STATUS = 0,
|
||||
USB_REQ_CLEAR_FEATURE = 1,
|
||||
USB_REQ_SET_FEATURE = 3,
|
||||
USB_REQ_SET_ADDRESS = 5,
|
||||
USB_REQ_GET_DESCRIPTOR = 6,
|
||||
USB_REQ_SET_DESCRIPTOR = 7,
|
||||
USB_REQ_GET_CONFIGURATION = 8,
|
||||
USB_REQ_SET_CONFIGURATION = 9,
|
||||
USB_REQ_GET_INTERFACE = 10,
|
||||
USB_REQ_SET_INTERFACE = 11,
|
||||
USB_REQ_SYNCH_FRAME = 12,
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Standard USB device status flags
|
||||
*
|
||||
*/
|
||||
enum usb_device_status {
|
||||
USB_DEV_STATUS_BUS_POWERED = 0,
|
||||
USB_DEV_STATUS_SELF_POWERED = 1,
|
||||
USB_DEV_STATUS_REMOTEWAKEUP = 2
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Standard USB Interface status flags
|
||||
*
|
||||
*/
|
||||
enum usb_interface_status {
|
||||
USB_IFACE_STATUS_RESERVED = 0
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Standard USB endpoint status flags
|
||||
*
|
||||
*/
|
||||
enum usb_endpoint_status {
|
||||
USB_EP_STATUS_HALTED = 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Standard USB device feature flags
|
||||
*
|
||||
* \note valid for SetFeature request.
|
||||
*/
|
||||
enum usb_device_feature {
|
||||
USB_DEV_FEATURE_REMOTE_WAKEUP = 1, //!< Remote wakeup enabled
|
||||
USB_DEV_FEATURE_TEST_MODE = 2, //!< USB test mode
|
||||
USB_DEV_FEATURE_OTG_B_HNP_ENABLE = 3,
|
||||
USB_DEV_FEATURE_OTG_A_HNP_SUPPORT = 4,
|
||||
USB_DEV_FEATURE_OTG_A_ALT_HNP_SUPPORT = 5
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Test Mode possible on HS USB device
|
||||
*
|
||||
* \note valid for USB_DEV_FEATURE_TEST_MODE request.
|
||||
*/
|
||||
enum usb_device_hs_test_mode {
|
||||
USB_DEV_TEST_MODE_J = 1,
|
||||
USB_DEV_TEST_MODE_K = 2,
|
||||
USB_DEV_TEST_MODE_SE0_NAK = 3,
|
||||
USB_DEV_TEST_MODE_PACKET = 4,
|
||||
USB_DEV_TEST_MODE_FORCE_ENABLE = 5,
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Standard USB endpoint feature/status flags
|
||||
*/
|
||||
enum usb_endpoint_feature {
|
||||
USB_EP_FEATURE_HALT = 0,
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Standard USB Test Mode Selectors
|
||||
*/
|
||||
enum usb_test_mode_selector {
|
||||
USB_TEST_J = 0x01,
|
||||
USB_TEST_K = 0x02,
|
||||
USB_TEST_SE0_NAK = 0x03,
|
||||
USB_TEST_PACKET = 0x04,
|
||||
USB_TEST_FORCE_ENABLE = 0x05,
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Standard USB descriptor types
|
||||
*/
|
||||
enum usb_descriptor_type {
|
||||
USB_DT_DEVICE = 1,
|
||||
USB_DT_CONFIGURATION = 2,
|
||||
USB_DT_STRING = 3,
|
||||
USB_DT_INTERFACE = 4,
|
||||
USB_DT_ENDPOINT = 5,
|
||||
USB_DT_DEVICE_QUALIFIER = 6,
|
||||
USB_DT_OTHER_SPEED_CONFIGURATION = 7,
|
||||
USB_DT_INTERFACE_POWER = 8,
|
||||
USB_DT_OTG = 9,
|
||||
USB_DT_IAD = 0x0B,
|
||||
USB_DT_BOS = 0x0F,
|
||||
USB_DT_DEVICE_CAPABILITY = 0x10,
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief USB Device Capability types
|
||||
*/
|
||||
enum usb_capability_type {
|
||||
USB_DC_USB20_EXTENSION = 0x02,
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief USB Device Capability - USB 2.0 Extension
|
||||
* To fill bmAttributes field of usb_capa_ext_desc_t structure.
|
||||
*/
|
||||
enum usb_capability_extension_attr {
|
||||
USB_DC_EXT_LPM = 0x00000002,
|
||||
};
|
||||
|
||||
#define HIRD_50_US 0
|
||||
#define HIRD_125_US 1
|
||||
#define HIRD_200_US 2
|
||||
#define HIRD_275_US 3
|
||||
#define HIRD_350_US 4
|
||||
#define HIRD_425_US 5
|
||||
#define HIRD_500_US 6
|
||||
#define HIRD_575_US 7
|
||||
#define HIRD_650_US 8
|
||||
#define HIRD_725_US 9
|
||||
#define HIRD_800_US 10
|
||||
#define HIRD_875_US 11
|
||||
#define HIRD_950_US 12
|
||||
#define HIRD_1025_US 13
|
||||
#define HIRD_1100_US 14
|
||||
#define HIRD_1175_US 15
|
||||
|
||||
/** Fields definition from a LPM TOKEN */
|
||||
#define USB_LPM_ATTRIBUT_BLINKSTATE_MASK (0xF << 0)
|
||||
#define USB_LPM_ATTRIBUT_FIRD_MASK (0xF << 4)
|
||||
#define USB_LPM_ATTRIBUT_REMOTEWAKE_MASK (1 << 8)
|
||||
#define USB_LPM_ATTRIBUT_BLINKSTATE(value) ((value & 0xF) << 0)
|
||||
#define USB_LPM_ATTRIBUT_FIRD(value) ((value & 0xF) << 4)
|
||||
#define USB_LPM_ATTRIBUT_REMOTEWAKE(value) ((value & 1) << 8)
|
||||
#define USB_LPM_ATTRIBUT_BLINKSTATE_L1 USB_LPM_ATTRIBUT_BLINKSTATE(1)
|
||||
|
||||
/**
|
||||
* \brief Standard USB endpoint transfer types
|
||||
*/
|
||||
enum usb_ep_type {
|
||||
USB_EP_TYPE_CONTROL = 0x00,
|
||||
USB_EP_TYPE_ISOCHRONOUS = 0x01,
|
||||
USB_EP_TYPE_BULK = 0x02,
|
||||
USB_EP_TYPE_INTERRUPT = 0x03,
|
||||
USB_EP_TYPE_MASK = 0x03,
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Standard USB language IDs for string descriptors
|
||||
*/
|
||||
enum usb_langid {
|
||||
USB_LANGID_EN_US = 0x0409, //!< English (United States)
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Mask selecting the index part of an endpoint address
|
||||
*/
|
||||
#define USB_EP_ADDR_MASK 0x0f
|
||||
|
||||
//! \brief USB address identifier
|
||||
typedef uint8_t usb_add_t;
|
||||
|
||||
/**
|
||||
* \brief Endpoint transfer direction is IN
|
||||
*/
|
||||
#define USB_EP_DIR_IN 0x80
|
||||
|
||||
/**
|
||||
* \brief Endpoint transfer direction is OUT
|
||||
*/
|
||||
#define USB_EP_DIR_OUT 0x00
|
||||
|
||||
//! \brief Endpoint identifier
|
||||
typedef uint8_t usb_ep_t;
|
||||
|
||||
/**
|
||||
* \brief Maximum length in bytes of a USB descriptor
|
||||
*
|
||||
* The maximum length of a USB descriptor is limited by the 8-bit
|
||||
* bLength field.
|
||||
*/
|
||||
#define USB_MAX_DESC_LEN 255
|
||||
|
||||
/*
|
||||
* 2-byte alignment requested for all USB structures.
|
||||
*/
|
||||
COMPILER_PACK_SET(1)
|
||||
|
||||
/**
|
||||
* \brief A USB Device SETUP request
|
||||
*
|
||||
* The data payload of SETUP packets always follows this structure.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t bmRequestType;
|
||||
uint8_t bRequest;
|
||||
le16_t wValue;
|
||||
le16_t wIndex;
|
||||
le16_t wLength;
|
||||
} usb_setup_req_t;
|
||||
|
||||
/**
|
||||
* \brief Standard USB device descriptor structure
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
le16_t bcdUSB;
|
||||
uint8_t bDeviceClass;
|
||||
uint8_t bDeviceSubClass;
|
||||
uint8_t bDeviceProtocol;
|
||||
uint8_t bMaxPacketSize0;
|
||||
le16_t idVendor;
|
||||
le16_t idProduct;
|
||||
le16_t bcdDevice;
|
||||
uint8_t iManufacturer;
|
||||
uint8_t iProduct;
|
||||
uint8_t iSerialNumber;
|
||||
uint8_t bNumConfigurations;
|
||||
} usb_dev_desc_t;
|
||||
|
||||
/**
|
||||
* \brief Standard USB device qualifier descriptor structure
|
||||
*
|
||||
* This descriptor contains information about the device when running at
|
||||
* the "other" speed (i.e. if the device is currently operating at high
|
||||
* speed, this descriptor can be used to determine what would change if
|
||||
* the device was operating at full speed.)
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
le16_t bcdUSB;
|
||||
uint8_t bDeviceClass;
|
||||
uint8_t bDeviceSubClass;
|
||||
uint8_t bDeviceProtocol;
|
||||
uint8_t bMaxPacketSize0;
|
||||
uint8_t bNumConfigurations;
|
||||
uint8_t bReserved;
|
||||
} usb_dev_qual_desc_t;
|
||||
|
||||
/**
|
||||
* \brief USB Device BOS descriptor structure
|
||||
*
|
||||
* The BOS descriptor (Binary device Object Store) defines a root
|
||||
* descriptor that is similar to the configuration descriptor, and is
|
||||
* the base descriptor for accessing a family of related descriptors.
|
||||
* A host can read a BOS descriptor and learn from the wTotalLength field
|
||||
* the entire size of the device-level descriptor set, or it can read in
|
||||
* the entire BOS descriptor set of device capabilities.
|
||||
* The host accesses this descriptor using the GetDescriptor() request.
|
||||
* The descriptor type in the GetDescriptor() request is set to BOS.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
le16_t wTotalLength;
|
||||
uint8_t bNumDeviceCaps;
|
||||
} usb_dev_bos_desc_t;
|
||||
|
||||
|
||||
/**
|
||||
* \brief USB Device Capabilities - USB 2.0 Extension Descriptor structure
|
||||
*
|
||||
* Defines the set of USB 1.1-specific device level capabilities.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bDevCapabilityType;
|
||||
le32_t bmAttributes;
|
||||
} usb_dev_capa_ext_desc_t;
|
||||
|
||||
/**
|
||||
* \brief USB Device LPM Descriptor structure
|
||||
*
|
||||
* The BOS descriptor and capabilities descriptors for LPM.
|
||||
*/
|
||||
typedef struct {
|
||||
usb_dev_bos_desc_t bos;
|
||||
usb_dev_capa_ext_desc_t capa_ext;
|
||||
} usb_dev_lpm_desc_t;
|
||||
|
||||
/**
|
||||
* \brief Standard USB Interface Association Descriptor structure
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t bLength; //!< size of this descriptor in bytes
|
||||
uint8_t bDescriptorType; //!< INTERFACE descriptor type
|
||||
uint8_t bFirstInterface; //!< Number of interface
|
||||
uint8_t bInterfaceCount; //!< value to select alternate setting
|
||||
uint8_t bFunctionClass; //!< Class code assigned by the USB
|
||||
uint8_t bFunctionSubClass;//!< Sub-class code assigned by the USB
|
||||
uint8_t bFunctionProtocol;//!< Protocol code assigned by the USB
|
||||
uint8_t iFunction; //!< Index of string descriptor
|
||||
} usb_association_desc_t;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Standard USB configuration descriptor structure
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
le16_t wTotalLength;
|
||||
uint8_t bNumInterfaces;
|
||||
uint8_t bConfigurationValue;
|
||||
uint8_t iConfiguration;
|
||||
uint8_t bmAttributes;
|
||||
uint8_t bMaxPower;
|
||||
} usb_conf_desc_t;
|
||||
|
||||
|
||||
#define USB_CONFIG_ATTR_MUST_SET (1 << 7) //!< Must always be set
|
||||
#define USB_CONFIG_ATTR_BUS_POWERED (0 << 6) //!< Bus-powered
|
||||
#define USB_CONFIG_ATTR_SELF_POWERED (1 << 6) //!< Self-powered
|
||||
#define USB_CONFIG_ATTR_REMOTE_WAKEUP (1 << 5) //!< remote wakeup supported
|
||||
|
||||
#define USB_CONFIG_MAX_POWER(ma) (((ma) + 1) / 2) //!< Max power in mA
|
||||
|
||||
/**
|
||||
* \brief Standard USB association descriptor structure
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t bLength; //!< Size of this descriptor in bytes
|
||||
uint8_t bDescriptorType; //!< Interface descriptor type
|
||||
uint8_t bFirstInterface; //!< Number of interface
|
||||
uint8_t bInterfaceCount; //!< value to select alternate setting
|
||||
uint8_t bFunctionClass; //!< Class code assigned by the USB
|
||||
uint8_t bFunctionSubClass; //!< Sub-class code assigned by the USB
|
||||
uint8_t bFunctionProtocol; //!< Protocol code assigned by the USB
|
||||
uint8_t iFunction; //!< Index of string descriptor
|
||||
} usb_iad_desc_t;
|
||||
|
||||
/**
|
||||
* \brief Standard USB interface descriptor structure
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bInterfaceNumber;
|
||||
uint8_t bAlternateSetting;
|
||||
uint8_t bNumEndpoints;
|
||||
uint8_t bInterfaceClass;
|
||||
uint8_t bInterfaceSubClass;
|
||||
uint8_t bInterfaceProtocol;
|
||||
uint8_t iInterface;
|
||||
} usb_iface_desc_t;
|
||||
|
||||
/**
|
||||
* \brief Standard USB endpoint descriptor structure
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bEndpointAddress;
|
||||
uint8_t bmAttributes;
|
||||
le16_t wMaxPacketSize;
|
||||
uint8_t bInterval;
|
||||
} usb_ep_desc_t;
|
||||
|
||||
|
||||
/**
|
||||
* \brief A standard USB string descriptor structure
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
} usb_str_desc_t;
|
||||
|
||||
typedef struct {
|
||||
usb_str_desc_t desc;
|
||||
le16_t string[1];
|
||||
} usb_str_lgid_desc_t;
|
||||
|
||||
COMPILER_PACK_RESET()
|
||||
|
||||
//! @}
|
||||
|
||||
#endif /* _USB_PROTOCOL_H_ */
|
193
tmk_core/protocol/arm_atsam/usb/usb_protocol_cdc.h
Normal file
193
tmk_core/protocol/arm_atsam/usb/usb_protocol_cdc.h
Normal file
|
@ -0,0 +1,193 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief USB Communication Device Class (CDC) protocol definitions
|
||||
*
|
||||
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
#ifndef _USB_PROTOCOL_CDC_H_
|
||||
#define _USB_PROTOCOL_CDC_H_
|
||||
|
||||
#include "compiler.h"
|
||||
|
||||
#ifdef CDC
|
||||
|
||||
#define CDC_CLASS_DEVICE 0x02 //!< USB Communication Device Class
|
||||
#define CDC_CLASS_COMM 0x02 //!< CDC Communication Class Interface
|
||||
#define CDC_CLASS_DATA 0x0A //!< CDC Data Class Interface
|
||||
|
||||
#define CDC_SUBCLASS_DLCM 0x01 //!< Direct Line Control Model
|
||||
#define CDC_SUBCLASS_ACM 0x02 //!< Abstract Control Model
|
||||
#define CDC_SUBCLASS_TCM 0x03 //!< Telephone Control Model
|
||||
#define CDC_SUBCLASS_MCCM 0x04 //!< Multi-Channel Control Model
|
||||
#define CDC_SUBCLASS_CCM 0x05 //!< CAPI Control Model
|
||||
#define CDC_SUBCLASS_ETH 0x06 //!< Ethernet Networking Control Model
|
||||
#define CDC_SUBCLASS_ATM 0x07 //!< ATM Networking Control Model
|
||||
|
||||
#define CDC_PROTOCOL_V25TER 0x01 //!< Common AT commands
|
||||
|
||||
#define CDC_PROTOCOL_I430 0x30 //!< ISDN BRI
|
||||
#define CDC_PROTOCOL_HDLC 0x31 //!< HDLC
|
||||
#define CDC_PROTOCOL_TRANS 0x32 //!< Transparent
|
||||
#define CDC_PROTOCOL_Q921M 0x50 //!< Q.921 management protocol
|
||||
#define CDC_PROTOCOL_Q921 0x51 //!< Q.931 [sic] Data link protocol
|
||||
#define CDC_PROTOCOL_Q921TM 0x52 //!< Q.921 TEI-multiplexor
|
||||
#define CDC_PROTOCOL_V42BIS 0x90 //!< Data compression procedures
|
||||
#define CDC_PROTOCOL_Q931 0x91 //!< Euro-ISDN protocol control
|
||||
#define CDC_PROTOCOL_V120 0x92 //!< V.24 rate adaption to ISDN
|
||||
#define CDC_PROTOCOL_CAPI20 0x93 //!< CAPI Commands
|
||||
#define CDC_PROTOCOL_HOST 0xFD //!< Host based driver
|
||||
|
||||
#define CDC_PROTOCOL_PUFD 0xFE
|
||||
|
||||
#define CDC_CS_INTERFACE 0x24 //!< Interface Functional Descriptor
|
||||
#define CDC_CS_ENDPOINT 0x25 //!< Endpoint Functional Descriptor
|
||||
|
||||
#define CDC_SCS_HEADER 0x00 //!< Header Functional Descriptor
|
||||
#define CDC_SCS_CALL_MGMT 0x01 //!< Call Management
|
||||
#define CDC_SCS_ACM 0x02 //!< Abstract Control Management
|
||||
#define CDC_SCS_UNION 0x06 //!< Union Functional Descriptor
|
||||
|
||||
#define USB_REQ_CDC_SEND_ENCAPSULATED_COMMAND 0x00
|
||||
#define USB_REQ_CDC_GET_ENCAPSULATED_RESPONSE 0x01
|
||||
#define USB_REQ_CDC_SET_COMM_FEATURE 0x02
|
||||
#define USB_REQ_CDC_GET_COMM_FEATURE 0x03
|
||||
#define USB_REQ_CDC_CLEAR_COMM_FEATURE 0x04
|
||||
#define USB_REQ_CDC_SET_AUX_LINE_STATE 0x10
|
||||
#define USB_REQ_CDC_SET_HOOK_STATE 0x11
|
||||
#define USB_REQ_CDC_PULSE_SETUP 0x12
|
||||
#define USB_REQ_CDC_SEND_PULSE 0x13
|
||||
#define USB_REQ_CDC_SET_PULSE_TIME 0x14
|
||||
#define USB_REQ_CDC_RING_AUX_JACK 0x15
|
||||
#define USB_REQ_CDC_SET_LINE_CODING 0x20
|
||||
#define USB_REQ_CDC_GET_LINE_CODING 0x21
|
||||
#define USB_REQ_CDC_SET_CONTROL_LINE_STATE 0x22
|
||||
#define USB_REQ_CDC_SEND_BREAK 0x23
|
||||
#define USB_REQ_CDC_SET_RINGER_PARMS 0x30
|
||||
#define USB_REQ_CDC_GET_RINGER_PARMS 0x31
|
||||
#define USB_REQ_CDC_SET_OPERATION_PARMS 0x32
|
||||
#define USB_REQ_CDC_GET_OPERATION_PARMS 0x33
|
||||
#define USB_REQ_CDC_SET_LINE_PARMS 0x34
|
||||
#define USB_REQ_CDC_GET_LINE_PARMS 0x35
|
||||
#define USB_REQ_CDC_DIAL_DIGITS 0x36
|
||||
#define USB_REQ_CDC_SET_UNIT_PARAMETER 0x37
|
||||
#define USB_REQ_CDC_GET_UNIT_PARAMETER 0x38
|
||||
#define USB_REQ_CDC_CLEAR_UNIT_PARAMETER 0x39
|
||||
#define USB_REQ_CDC_GET_PROFILE 0x3A
|
||||
#define USB_REQ_CDC_SET_ETHERNET_MULTICAST_FILTERS 0x40
|
||||
#define USB_REQ_CDC_SET_ETHERNET_POWER_MANAGEMENT_PATTERNFILTER 0x41
|
||||
#define USB_REQ_CDC_GET_ETHERNET_POWER_MANAGEMENT_PATTERNFILTER 0x42
|
||||
#define USB_REQ_CDC_SET_ETHERNET_PACKET_FILTER 0x43
|
||||
#define USB_REQ_CDC_GET_ETHERNET_STATISTIC 0x44
|
||||
#define USB_REQ_CDC_SET_ATM_DATA_FORMAT 0x50
|
||||
#define USB_REQ_CDC_GET_ATM_DEVICE_STATISTICS 0x51
|
||||
#define USB_REQ_CDC_SET_ATM_DEFAULT_VC 0x52
|
||||
#define USB_REQ_CDC_GET_ATM_VC_STATISTICS 0x53
|
||||
// Added bNotification codes according cdc spec 1.1 chapter 6.3
|
||||
#define USB_REQ_CDC_NOTIFY_RING_DETECT 0x09
|
||||
#define USB_REQ_CDC_NOTIFY_SERIAL_STATE 0x20
|
||||
#define USB_REQ_CDC_NOTIFY_CALL_STATE_CHANGE 0x28
|
||||
#define USB_REQ_CDC_NOTIFY_LINE_STATE_CHANGE 0x29
|
||||
|
||||
|
||||
#define CDC_CALL_MGMT_SUPPORTED (1 << 0)
|
||||
#define CDC_CALL_MGMT_OVER_DCI (1 << 1)
|
||||
#define CDC_ACM_SUPPORT_FEATURE_REQUESTS (1 << 0)
|
||||
#define CDC_ACM_SUPPORT_LINE_REQUESTS (1 << 1)
|
||||
#define CDC_ACM_SUPPORT_SENDBREAK_REQUESTS (1 << 2)
|
||||
#define CDC_ACM_SUPPORT_NOTIFY_REQUESTS (1 << 3)
|
||||
|
||||
#pragma pack(push,1)
|
||||
typedef struct {
|
||||
le32_t dwDTERate;
|
||||
uint8_t bCharFormat;
|
||||
uint8_t bParityType;
|
||||
uint8_t bDataBits;
|
||||
} usb_cdc_line_coding_t;
|
||||
#pragma pack(pop)
|
||||
|
||||
enum cdc_char_format {
|
||||
CDC_STOP_BITS_1 = 0, //!< 1 stop bit
|
||||
CDC_STOP_BITS_1_5 = 1, //!< 1.5 stop bits
|
||||
CDC_STOP_BITS_2 = 2, //!< 2 stop bits
|
||||
};
|
||||
|
||||
enum cdc_parity {
|
||||
CDC_PAR_NONE = 0, //!< No parity
|
||||
CDC_PAR_ODD = 1, //!< Odd parity
|
||||
CDC_PAR_EVEN = 2, //!< Even parity
|
||||
CDC_PAR_MARK = 3, //!< Parity forced to 0 (space)
|
||||
CDC_PAR_SPACE = 4, //!< Parity forced to 1 (mark)
|
||||
};
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint16_t value;
|
||||
} usb_cdc_control_signal_t;
|
||||
|
||||
#define CDC_CTRL_SIGNAL_ACTIVATE_CARRIER (1 << 1)
|
||||
#define CDC_CTRL_SIGNAL_DTE_PRESENT (1 << 0)
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint8_t bmRequestType;
|
||||
uint8_t bNotification;
|
||||
le16_t wValue;
|
||||
le16_t wIndex;
|
||||
le16_t wLength;
|
||||
} usb_cdc_notify_msg_t;
|
||||
|
||||
typedef struct {
|
||||
usb_cdc_notify_msg_t header;
|
||||
le16_t value;
|
||||
} usb_cdc_notify_serial_state_t;
|
||||
|
||||
#define CDC_SERIAL_STATE_DCD CPU_TO_LE16((1<<0))
|
||||
#define CDC_SERIAL_STATE_DSR CPU_TO_LE16((1<<1))
|
||||
#define CDC_SERIAL_STATE_BREAK CPU_TO_LE16((1<<2))
|
||||
#define CDC_SERIAL_STATE_RING CPU_TO_LE16((1<<3))
|
||||
#define CDC_SERIAL_STATE_FRAMING CPU_TO_LE16((1<<4))
|
||||
#define CDC_SERIAL_STATE_PARITY CPU_TO_LE16((1<<5))
|
||||
#define CDC_SERIAL_STATE_OVERRUN CPU_TO_LE16((1<<6))
|
||||
|
||||
#endif
|
||||
|
||||
#endif // _USB_PROTOCOL_CDC_H_
|
319
tmk_core/protocol/arm_atsam/usb/usb_protocol_hid.h
Normal file
319
tmk_core/protocol/arm_atsam/usb/usb_protocol_hid.h
Normal file
|
@ -0,0 +1,319 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief USB Human Interface Device (HID) protocol definitions.
|
||||
*
|
||||
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
|
||||
#ifndef _USB_PROTOCOL_HID_H_
|
||||
#define _USB_PROTOCOL_HID_H_
|
||||
|
||||
/**
|
||||
* \ingroup usb_protocol_group
|
||||
* \defgroup usb_hid_protocol USB Human Interface Device (HID)
|
||||
* protocol definitions
|
||||
* \brief USB Human Interface Device (HID) protocol definitions
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
//! \name Possible Class value
|
||||
//@{
|
||||
#define HID_CLASS 0x03
|
||||
//@}
|
||||
|
||||
//! \name Possible SubClass value
|
||||
//@{
|
||||
//! Interface subclass NO support BOOT protocol
|
||||
#define HID_SUB_CLASS_NOBOOT 0x00
|
||||
//! Interface subclass support BOOT protocol
|
||||
#define HID_SUB_CLASS_BOOT 0x01
|
||||
//@}
|
||||
|
||||
//! \name Possible protocol value
|
||||
//@{
|
||||
//! Protocol generic standard
|
||||
#define HID_PROTOCOL_GENERIC 0x00
|
||||
//! Protocol keyboard standard
|
||||
#define HID_PROTOCOL_KEYBOARD 0x01
|
||||
//! Protocol mouse standard
|
||||
#define HID_PROTOCOL_MOUSE 0x02
|
||||
//@}
|
||||
|
||||
|
||||
//! \brief Hid USB requests (bRequest)
|
||||
enum usb_reqid_hid {
|
||||
USB_REQ_HID_GET_REPORT = 0x01,
|
||||
USB_REQ_HID_GET_IDLE = 0x02,
|
||||
USB_REQ_HID_GET_PROTOCOL = 0x03,
|
||||
USB_REQ_HID_SET_REPORT = 0x09,
|
||||
USB_REQ_HID_SET_IDLE = 0x0A,
|
||||
USB_REQ_HID_SET_PROTOCOL = 0x0B,
|
||||
};
|
||||
|
||||
//! \brief HID USB descriptor types
|
||||
enum usb_descriptor_type_hid {
|
||||
USB_DT_HID = 0x21,
|
||||
USB_DT_HID_REPORT = 0x22,
|
||||
USB_DT_HID_PHYSICAL = 0x23,
|
||||
};
|
||||
|
||||
//! \brief HID Type for report descriptor
|
||||
enum usb_hid_item_report_type {
|
||||
USB_HID_ITEM_REPORT_TYPE_MAIN = 0,
|
||||
USB_HID_ITEM_REPORT_TYPE_GLOBAL = 1,
|
||||
USB_HID_ITEM_REPORT_TYPE_LOCAL = 2,
|
||||
USB_HID_ITEM_REPORT_TYPE_LONG = 3,
|
||||
};
|
||||
|
||||
//! \brief HID report type
|
||||
enum usb_hid_report_type {
|
||||
USB_HID_REPORT_TYPE_INPUT = 1,
|
||||
USB_HID_REPORT_TYPE_OUTPUT = 2,
|
||||
USB_HID_REPORT_TYPE_FEATURE = 3,
|
||||
};
|
||||
|
||||
|
||||
//! \brief HID protocol
|
||||
enum usb_hid_protocol {
|
||||
USB_HID_PROCOTOL_BOOT = 0,
|
||||
USB_HID_PROCOTOL_REPORT = 1,
|
||||
};
|
||||
|
||||
COMPILER_PACK_SET(1)
|
||||
|
||||
//! \brief HID Descriptor
|
||||
typedef struct {
|
||||
uint8_t bLength; //!< Size of this descriptor in bytes
|
||||
uint8_t bDescriptorType; //!< HID descriptor type
|
||||
le16_t bcdHID; //!< Binary Coded Decimal Spec. release
|
||||
uint8_t bCountryCode; //!< Hardware target country
|
||||
uint8_t bNumDescriptors; //!< Number of HID class descriptors to follow
|
||||
uint8_t bRDescriptorType; //!< Report descriptor type
|
||||
le16_t wDescriptorLength; //!< Total length of Report descriptor
|
||||
} usb_hid_descriptor_t;
|
||||
|
||||
COMPILER_PACK_RESET()
|
||||
|
||||
//! \name HID Report type
|
||||
//! Used by SETUP_HID_GET_REPORT & SETUP_HID_SET_REPORT
|
||||
//! @{
|
||||
#define REPORT_TYPE_INPUT 0x01
|
||||
#define REPORT_TYPE_OUTPUT 0x02
|
||||
#define REPORT_TYPE_FEATURE 0x03
|
||||
//! @}
|
||||
|
||||
//! \name Constants of field DESCRIPTOR_HID
|
||||
//! @{
|
||||
//! Numeric expression identifying the HID Class
|
||||
//! Specification release (here V1.11)
|
||||
#define USB_HID_BDC_V1_11 0x0111
|
||||
//! Numeric expression specifying the number of class descriptors
|
||||
//! Note: Always at least one i.e. Report descriptor.
|
||||
#define USB_HID_NUM_DESC 0x01
|
||||
|
||||
//! \name Country code
|
||||
//! @{
|
||||
#define USB_HID_NO_COUNTRY_CODE 0 // Not Supported
|
||||
#define USB_HID_COUNTRY_ARABIC 1 // Arabic
|
||||
#define USB_HID_COUNTRY_BELGIAN 2 // Belgian
|
||||
#define USB_HID_COUNTRY_CANADIAN_BILINGUAL 3 // Canadian-Bilingual
|
||||
#define USB_HID_COUNTRY_CANADIAN_FRENCH 4 // Canadian-French
|
||||
#define USB_HID_COUNTRY_CZECH_REPUBLIC 5 // Czech Republic
|
||||
#define USB_HID_COUNTRY_DANISH 6 // Danish
|
||||
#define USB_HID_COUNTRY_FINNISH 7 // Finnish
|
||||
#define USB_HID_COUNTRY_FRENCH 8 // French
|
||||
#define USB_HID_COUNTRY_GERMAN 9 // German
|
||||
#define USB_HID_COUNTRY_GREEK 10 // Greek
|
||||
#define USB_HID_COUNTRY_HEBREW 11 // Hebrew
|
||||
#define USB_HID_COUNTRY_HUNGARY 12 // Hungary
|
||||
#define USB_HID_COUNTRY_INTERNATIONAL_ISO 13 // International (ISO)
|
||||
#define USB_HID_COUNTRY_ITALIAN 14 // Italian
|
||||
#define USB_HID_COUNTRY_JAPAN_KATAKANA 15 // Japan (Katakana)
|
||||
#define USB_HID_COUNTRY_KOREAN 16 // Korean
|
||||
#define USB_HID_COUNTRY_LATIN_AMERICAN 17 // Latin American
|
||||
#define USB_HID_COUNTRY_NETHERLANDS_DUTCH 18 // Netherlands/Dutch
|
||||
#define USB_HID_COUNTRY_NORWEGIAN 19 // Norwegian
|
||||
#define USB_HID_COUNTRY_PERSIAN_FARSI 20 // Persian (Farsi)
|
||||
#define USB_HID_COUNTRY_POLAND 21 // Poland
|
||||
#define USB_HID_COUNTRY_PORTUGUESE 22 // Portuguese
|
||||
#define USB_HID_COUNTRY_RUSSIA 23 // Russia
|
||||
#define USB_HID_COUNTRY_SLOVAKIA 24 // Slovakia
|
||||
#define USB_HID_COUNTRY_SPANISH 25 // Spanish
|
||||
#define USB_HID_COUNTRY_SWEDISH 26 // Swedish
|
||||
#define USB_HID_COUNTRY_SWISS_FRENCH 27 // Swiss/French
|
||||
#define USB_HID_COUNTRY_SWISS_GERMAN 28 // Swiss/German
|
||||
#define USB_HID_COUNTRY_SWITZERLAND 29 // Switzerland
|
||||
#define USB_HID_COUNTRY_TAIWAN 30 // Taiwan
|
||||
#define USB_HID_COUNTRY_TURKISH_Q 31 // Turkish-Q
|
||||
#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
|
||||
//! @}
|
||||
//! @}
|
||||
//! @}
|
||||
|
||||
|
||||
//! \name HID KEYS values
|
||||
//! @{
|
||||
#define HID_A 0x04
|
||||
#define HID_B 0x05
|
||||
#define HID_C 0x06
|
||||
#define HID_D 0x07
|
||||
#define HID_E 0x08
|
||||
#define HID_F 0x09
|
||||
#define HID_G 0x0A
|
||||
#define HID_H 0x0B
|
||||
#define HID_I 0x0C
|
||||
#define HID_J 0x0D
|
||||
#define HID_K 0x0E
|
||||
#define HID_L 0x0F
|
||||
#define HID_M 0x10
|
||||
#define HID_N 0x11
|
||||
#define HID_O 0x12
|
||||
#define HID_P 0x13
|
||||
#define HID_Q 0x14
|
||||
#define HID_R 0x15
|
||||
#define HID_S 0x16
|
||||
#define HID_T 0x17
|
||||
#define HID_U 0x18
|
||||
#define HID_V 0x19
|
||||
#define HID_W 0x1A
|
||||
#define HID_X 0x1B
|
||||
#define HID_Y 0x1C
|
||||
#define HID_Z 0x1D
|
||||
#define HID_1 30
|
||||
#define HID_2 31
|
||||
#define HID_3 32
|
||||
#define HID_4 33
|
||||
#define HID_5 34
|
||||
#define HID_6 35
|
||||
#define HID_7 36
|
||||
#define HID_8 37
|
||||
#define HID_9 38
|
||||
#define HID_0 39
|
||||
#define HID_ENTER 40
|
||||
#define HID_ESCAPE 41
|
||||
#define HID_BACKSPACE 42
|
||||
#define HID_TAB 43
|
||||
#define HID_SPACEBAR 44
|
||||
#define HID_UNDERSCORE 45
|
||||
#define HID_PLUS 46
|
||||
#define HID_OPEN_BRACKET 47 // {
|
||||
#define HID_CLOSE_BRACKET 48 // }
|
||||
#define HID_BACKSLASH 49
|
||||
#define HID_ASH 50 // # ~
|
||||
#define HID_COLON 51 // ; :
|
||||
#define HID_QUOTE 52 // ' "
|
||||
#define HID_TILDE 53
|
||||
#define HID_COMMA 54
|
||||
#define HID_DOT 55
|
||||
#define HID_SLASH 56
|
||||
#define HID_CAPS_LOCK 57
|
||||
#define HID_F1 58
|
||||
#define HID_F2 59
|
||||
#define HID_F3 60
|
||||
#define HID_F4 61
|
||||
#define HID_F5 62
|
||||
#define HID_F6 63
|
||||
#define HID_F7 64
|
||||
#define HID_F8 65
|
||||
#define HID_F9 66
|
||||
#define HID_F10 67
|
||||
#define HID_F11 68
|
||||
#define HID_F12 69
|
||||
#define HID_PRINTSCREEN 70
|
||||
#define HID_SCROLL_LOCK 71
|
||||
#define HID_PAUSE 72
|
||||
#define HID_INSERT 73
|
||||
#define HID_HOME 74
|
||||
#define HID_PAGEUP 75
|
||||
#define HID_DELETE 76
|
||||
#define HID_END 77
|
||||
#define HID_PAGEDOWN 78
|
||||
#define HID_RIGHT 79
|
||||
#define HID_LEFT 80
|
||||
#define HID_DOWN 81
|
||||
#define HID_UP 82
|
||||
#define HID_KEYPAD_NUM_LOCK 83
|
||||
#define HID_KEYPAD_DIVIDE 84
|
||||
#define HID_KEYPAD_AT 85
|
||||
#define HID_KEYPAD_MULTIPLY 85
|
||||
#define HID_KEYPAD_MINUS 86
|
||||
#define HID_KEYPAD_PLUS 87
|
||||
#define HID_KEYPAD_ENTER 88
|
||||
#define HID_KEYPAD_1 89
|
||||
#define HID_KEYPAD_2 90
|
||||
#define HID_KEYPAD_3 91
|
||||
#define HID_KEYPAD_4 92
|
||||
#define HID_KEYPAD_5 93
|
||||
#define HID_KEYPAD_6 94
|
||||
#define HID_KEYPAD_7 95
|
||||
#define HID_KEYPAD_8 96
|
||||
#define HID_KEYPAD_9 97
|
||||
#define HID_KEYPAD_0 98
|
||||
|
||||
//! \name HID modifier values
|
||||
//! @{
|
||||
#define HID_MODIFIER_NONE 0x00
|
||||
#define HID_MODIFIER_LEFT_CTRL 0x01
|
||||
#define HID_MODIFIER_LEFT_SHIFT 0x02
|
||||
#define HID_MODIFIER_LEFT_ALT 0x04
|
||||
#define HID_MODIFIER_LEFT_UI 0x08
|
||||
#define HID_MODIFIER_RIGHT_CTRL 0x10
|
||||
#define HID_MODIFIER_RIGHT_SHIFT 0x20
|
||||
#define HID_MODIFIER_RIGHT_ALT 0x40
|
||||
#define HID_MODIFIER_RIGHT_UI 0x80
|
||||
//! @}
|
||||
//! @}
|
||||
|
||||
//! \name HID KEYS values
|
||||
//! @{
|
||||
#define HID_LED_NUM_LOCK (1<<0)
|
||||
#define HID_LED_CAPS_LOCK (1<<1)
|
||||
#define HID_LED_SCROLL_LOCK (1<<2)
|
||||
#define HID_LED_COMPOSE (1<<3)
|
||||
#define HID_LED_KANA (1<<4)
|
||||
//! @}
|
||||
|
||||
#endif // _USB_PROTOCOL_HID_H_
|
59
tmk_core/protocol/arm_atsam/usb/usb_util.c
Normal file
59
tmk_core/protocol/arm_atsam/usb/usb_util.c
Normal file
|
@ -0,0 +1,59 @@
|
|||
#include "samd51j18a.h"
|
||||
#include "string.h"
|
||||
#include "usb_util.h"
|
||||
|
||||
char digit(int d, int radix)
|
||||
{
|
||||
if (d < 10)
|
||||
{
|
||||
return d + '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
return d - 10 + 'A';
|
||||
}
|
||||
}
|
||||
|
||||
int UTIL_ltoa_radix(int64_t value, char *dest, int radix)
|
||||
{
|
||||
int64_t original = value; //save original value
|
||||
char buf[25] = "";
|
||||
int c = sizeof(buf)-1;
|
||||
int last = c;
|
||||
int d;
|
||||
int size;
|
||||
|
||||
if (value < 0) //if it's negative, take the absolute value
|
||||
value = -value;
|
||||
|
||||
do //write least significant digit of value that's left
|
||||
{
|
||||
d = (value % radix);
|
||||
buf[--c] = digit(d, radix);
|
||||
value /= radix;
|
||||
} while (value);
|
||||
|
||||
if (original < 0)
|
||||
buf[--c] = '-';
|
||||
|
||||
size = last - c + 1; //includes null at end
|
||||
memcpy(dest, &buf[c], last - c + 1);
|
||||
|
||||
return (size - 1); //without null termination
|
||||
}
|
||||
|
||||
int UTIL_ltoa(int64_t value, char *dest)
|
||||
{
|
||||
return UTIL_ltoa_radix(value, dest, 10);
|
||||
}
|
||||
|
||||
int UTIL_itoa(int value, char *dest)
|
||||
{
|
||||
return UTIL_ltoa_radix((int64_t)value, dest, 10);
|
||||
}
|
||||
|
||||
int UTIL_utoa(uint32_t value, char *dest)
|
||||
{
|
||||
return UTIL_ltoa_radix((int64_t)value, dest, 10);
|
||||
}
|
||||
|
10
tmk_core/protocol/arm_atsam/usb/usb_util.h
Normal file
10
tmk_core/protocol/arm_atsam/usb/usb_util.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#ifndef _USB_UTIL_H_
|
||||
#define _USB_UTIL_H_
|
||||
|
||||
int UTIL_ltoa_radix(int64_t value, char *dest, int radix);
|
||||
int UTIL_ltoa(int64_t value, char *dest);
|
||||
int UTIL_itoa(int value, char *dest);
|
||||
int UTIL_utoa(uint32_t value, char *dest);
|
||||
|
||||
#endif //_USB_UTIL_H_
|
||||
|
8
tmk_core/protocol/arm_atsam/wait_api.h
Normal file
8
tmk_core/protocol/arm_atsam/wait_api.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#ifndef _wait_api_h_
|
||||
#define _wait_api_h_
|
||||
|
||||
void wait_ms(uint64_t msec);
|
||||
void wait_us(uint16_t usec);
|
||||
|
||||
#endif
|
||||
|
|
@ -44,6 +44,9 @@
|
|||
#ifdef MIDI_ENABLE
|
||||
#include "qmk_midi.h"
|
||||
#endif
|
||||
#ifdef STM32_EEPROM_ENABLE
|
||||
#include "eeprom_stm32.h"
|
||||
#endif
|
||||
#include "suspend.h"
|
||||
#include "wait.h"
|
||||
|
||||
|
@ -72,7 +75,7 @@ host_driver_t chibios_driver = {
|
|||
void virtser_task(void);
|
||||
#endif
|
||||
|
||||
#ifdef RAW_HID_ENABLE
|
||||
#ifdef RAW_ENABLE
|
||||
void raw_hid_task(void);
|
||||
#endif
|
||||
|
||||
|
@ -109,6 +112,10 @@ int main(void) {
|
|||
halInit();
|
||||
chSysInit();
|
||||
|
||||
#ifdef STM32_EEPROM_ENABLE
|
||||
EEPROM_init();
|
||||
#endif
|
||||
|
||||
// TESTING
|
||||
// chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);
|
||||
|
||||
|
@ -135,10 +142,15 @@ int main(void) {
|
|||
|
||||
/* Wait until the USB or serial link is active */
|
||||
while (true) {
|
||||
#if defined(WAIT_FOR_USB) || defined(SERIAL_LINK_ENABLE)
|
||||
if(USB_DRIVER.state == USB_ACTIVE) {
|
||||
driver = &chibios_driver;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
driver = &chibios_driver;
|
||||
break;
|
||||
#endif
|
||||
#ifdef SERIAL_LINK_ENABLE
|
||||
if(is_serial_link_connected()) {
|
||||
driver = get_serial_link_driver();
|
||||
|
@ -171,6 +183,7 @@ int main(void) {
|
|||
/* Main loop */
|
||||
while(true) {
|
||||
|
||||
#if !defined(NO_USB_STARTUP_CHECK)
|
||||
if(USB_DRIVER.state == USB_SUSPENDED) {
|
||||
print("[s]");
|
||||
#ifdef VISUALIZER_ENABLE
|
||||
|
@ -198,6 +211,7 @@ int main(void) {
|
|||
visualizer_resume();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
keyboard_task();
|
||||
#ifdef CONSOLE_ENABLE
|
||||
|
@ -206,7 +220,7 @@ int main(void) {
|
|||
#ifdef VIRTSER_ENABLE
|
||||
virtser_task();
|
||||
#endif
|
||||
#ifdef RAW_HID_ENABLE
|
||||
#ifdef RAW_ENABLE
|
||||
raw_hid_task();
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -95,6 +95,7 @@ static const USBDescriptor *usb_get_descriptor_cb(USBDriver *usbp, uint8_t dtype
|
|||
return &desc;
|
||||
}
|
||||
|
||||
#ifndef KEYBOARD_SHARED_EP
|
||||
/* keyboard endpoint state structure */
|
||||
static USBInEndpointState kbd_ep_state;
|
||||
/* keyboard endpoint initialization structure (IN) */
|
||||
|
@ -110,8 +111,9 @@ static const USBEndpointConfig kbd_ep_config = {
|
|||
2, /* IN multiplier */
|
||||
NULL /* SETUP buffer (not a SETUP endpoint) */
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef MOUSE_ENABLE
|
||||
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
|
||||
/* mouse endpoint state structure */
|
||||
static USBInEndpointState mouse_ep_state;
|
||||
|
||||
|
@ -128,45 +130,26 @@ static const USBEndpointConfig mouse_ep_config = {
|
|||
2, /* IN multiplier */
|
||||
NULL /* SETUP buffer (not a SETUP endpoint) */
|
||||
};
|
||||
#endif /* MOUSE_ENABLE */
|
||||
#endif
|
||||
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
/* extrakey endpoint state structure */
|
||||
static USBInEndpointState extra_ep_state;
|
||||
#ifdef SHARED_EP_ENABLE
|
||||
/* shared endpoint state structure */
|
||||
static USBInEndpointState shared_ep_state;
|
||||
|
||||
/* extrakey endpoint initialization structure (IN) */
|
||||
static const USBEndpointConfig extra_ep_config = {
|
||||
/* shared endpoint initialization structure (IN) */
|
||||
static const USBEndpointConfig shared_ep_config = {
|
||||
USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
|
||||
NULL, /* SETUP packet notification callback */
|
||||
extra_in_cb, /* IN notification callback */
|
||||
shared_in_cb, /* IN notification callback */
|
||||
NULL, /* OUT notification callback */
|
||||
EXTRAKEY_EPSIZE, /* IN maximum packet size */
|
||||
SHARED_EPSIZE, /* IN maximum packet size */
|
||||
0, /* OUT maximum packet size */
|
||||
&extra_ep_state, /* IN Endpoint state */
|
||||
&shared_ep_state, /* IN Endpoint state */
|
||||
NULL, /* OUT endpoint state */
|
||||
2, /* IN multiplier */
|
||||
NULL /* SETUP buffer (not a SETUP endpoint) */
|
||||
};
|
||||
#endif /* EXTRAKEY_ENABLE */
|
||||
|
||||
#ifdef NKRO_ENABLE
|
||||
/* nkro endpoint state structure */
|
||||
static USBInEndpointState nkro_ep_state;
|
||||
|
||||
/* nkro endpoint initialization structure (IN) */
|
||||
static const USBEndpointConfig nkro_ep_config = {
|
||||
USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
|
||||
NULL, /* SETUP packet notification callback */
|
||||
nkro_in_cb, /* IN notification callback */
|
||||
NULL, /* OUT notification callback */
|
||||
NKRO_EPSIZE, /* IN maximum packet size */
|
||||
0, /* OUT maximum packet size */
|
||||
&nkro_ep_state, /* IN Endpoint state */
|
||||
NULL, /* OUT endpoint state */
|
||||
2, /* IN multiplier */
|
||||
NULL /* SETUP buffer (not a SETUP endpoint) */
|
||||
};
|
||||
#endif /* NKRO_ENABLE */
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
size_t queue_capacity_in;
|
||||
|
@ -309,16 +292,15 @@ static void usb_event_cb(USBDriver *usbp, usbevent_t event) {
|
|||
case USB_EVENT_CONFIGURED:
|
||||
osalSysLockFromISR();
|
||||
/* Enable the endpoints specified into the configuration. */
|
||||
#ifndef KEYBOARD_SHARED_EP
|
||||
usbInitEndpointI(usbp, KEYBOARD_IN_EPNUM, &kbd_ep_config);
|
||||
#ifdef MOUSE_ENABLE
|
||||
#endif
|
||||
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
|
||||
usbInitEndpointI(usbp, MOUSE_IN_EPNUM, &mouse_ep_config);
|
||||
#endif /* MOUSE_ENABLE */
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
usbInitEndpointI(usbp, EXTRAKEY_IN_EPNUM, &extra_ep_config);
|
||||
#endif /* EXTRAKEY_ENABLE */
|
||||
#ifdef NKRO_ENABLE
|
||||
usbInitEndpointI(usbp, NKRO_IN_EPNUM, &nkro_ep_config);
|
||||
#endif /* NKRO_ENABLE */
|
||||
#endif
|
||||
#ifdef SHARED_EP_ENABLE
|
||||
usbInitEndpointI(usbp, SHARED_IN_EPNUM, &shared_ep_config);
|
||||
#endif
|
||||
for (int i=0;i<NUM_USB_DRIVERS;i++) {
|
||||
usbInitEndpointI(usbp, drivers.array[i].config.bulk_in, &drivers.array[i].in_ep_config);
|
||||
usbInitEndpointI(usbp, drivers.array[i].config.bulk_out, &drivers.array[i].out_ep_config);
|
||||
|
@ -389,9 +371,20 @@ static uint16_t get_hword(uint8_t *p) {
|
|||
* Other Device Required Optional Optional Optional Optional Optional
|
||||
*/
|
||||
|
||||
#ifdef SHARED_EP_ENABLE
|
||||
static uint8_t set_report_buf[2] __attribute__((aligned(2)));
|
||||
static void set_led_transfer_cb(USBDriver *usbp) {
|
||||
if ((set_report_buf[0] == REPORT_ID_KEYBOARD) ||
|
||||
(set_report_buf[0] == REPORT_ID_NKRO)) {
|
||||
keyboard_led_stats = set_report_buf[1];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Callback for SETUP request on the endpoint 0 (control) */
|
||||
static bool usb_request_hook_cb(USBDriver *usbp) {
|
||||
const USBDescriptor *dp;
|
||||
int has_report_id;
|
||||
|
||||
/* usbp->setup fields:
|
||||
* 0: bmRequestType (bitmask)
|
||||
|
@ -409,42 +402,16 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
|
|||
case HID_GET_REPORT:
|
||||
switch(usbp->setup[4]) { /* LSB(wIndex) (check MSB==0?) */
|
||||
case KEYBOARD_INTERFACE:
|
||||
#ifdef NKRO_ENABLE
|
||||
case NKRO_INTERFACE:
|
||||
#endif /* NKRO_ENABLE */
|
||||
usbSetupTransfer(usbp, (uint8_t *)&keyboard_report_sent, sizeof(keyboard_report_sent), NULL);
|
||||
return TRUE;
|
||||
break;
|
||||
|
||||
#ifdef MOUSE_ENABLE
|
||||
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
|
||||
case MOUSE_INTERFACE:
|
||||
usbSetupTransfer(usbp, (uint8_t *)&mouse_report_blank, sizeof(mouse_report_blank), NULL);
|
||||
return TRUE;
|
||||
break;
|
||||
#endif /* MOUSE_ENABLE */
|
||||
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
case EXTRAKEY_INTERFACE:
|
||||
if(usbp->setup[3] == 1) { /* MSB(wValue) [Report Type] == 1 [Input Report] */
|
||||
switch(usbp->setup[2]) { /* LSB(wValue) [Report ID] */
|
||||
case REPORT_ID_SYSTEM:
|
||||
extra_report_blank[0] = REPORT_ID_SYSTEM;
|
||||
usbSetupTransfer(usbp, (uint8_t *)extra_report_blank, sizeof(extra_report_blank), NULL);
|
||||
return TRUE;
|
||||
break;
|
||||
case REPORT_ID_CONSUMER:
|
||||
extra_report_blank[0] = REPORT_ID_CONSUMER;
|
||||
usbSetupTransfer(usbp, (uint8_t *)extra_report_blank, sizeof(extra_report_blank), NULL);
|
||||
return TRUE;
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
#endif /* EXTRAKEY_ENABLE */
|
||||
#endif
|
||||
|
||||
default:
|
||||
usbSetupTransfer(usbp, NULL, 0, NULL);
|
||||
|
@ -472,12 +439,25 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
|
|||
case HID_SET_REPORT:
|
||||
switch(usbp->setup[4]) { /* LSB(wIndex) (check MSB==0 and wLength==1?) */
|
||||
case KEYBOARD_INTERFACE:
|
||||
#ifdef NKRO_ENABLE
|
||||
case NKRO_INTERFACE:
|
||||
#endif /* NKRO_ENABLE */
|
||||
#if defined(SHARED_EP_ENABLE) && !defined(KEYBOARD_SHARED_EP)
|
||||
case SHARED_INTERFACE:
|
||||
#endif
|
||||
/* keyboard_led_stats = <read byte from next OUT report>
|
||||
* keyboard_led_stats needs be word (or dword), otherwise we get an exception on F0 */
|
||||
usbSetupTransfer(usbp, (uint8_t *)&keyboard_led_stats, 1, NULL);
|
||||
has_report_id = 0;
|
||||
#if defined(SHARED_EP_ENABLE)
|
||||
if (usbp->setup[4] == SHARED_INTERFACE) {
|
||||
has_report_id = 1;
|
||||
}
|
||||
#endif
|
||||
if (usbp->setup[4] == KEYBOARD_INTERFACE && !keyboard_protocol) {
|
||||
has_report_id = 0;
|
||||
}
|
||||
if (has_report_id) {
|
||||
usbSetupTransfer(usbp, set_report_buf, sizeof(set_report_buf), set_led_transfer_cb);
|
||||
} else {
|
||||
usbSetupTransfer(usbp, (uint8_t *)&keyboard_led_stats, 1, NULL);
|
||||
}
|
||||
return TRUE;
|
||||
break;
|
||||
}
|
||||
|
@ -591,20 +571,13 @@ void init_usb_driver(USBDriver *usbp) {
|
|||
* ---------------------------------------------------------
|
||||
*/
|
||||
/* keyboard IN callback hander (a kbd report has made it IN) */
|
||||
#ifndef KEYBOARD_SHARED_EP
|
||||
void kbd_in_cb(USBDriver *usbp, usbep_t ep) {
|
||||
/* STUB */
|
||||
(void)usbp;
|
||||
(void)ep;
|
||||
}
|
||||
|
||||
#ifdef NKRO_ENABLE
|
||||
/* nkro IN callback hander (a nkro report has made it IN) */
|
||||
void nkro_in_cb(USBDriver *usbp, usbep_t ep) {
|
||||
/* STUB */
|
||||
(void)usbp;
|
||||
(void)ep;
|
||||
}
|
||||
#endif /* NKRO_ENABLE */
|
||||
#endif
|
||||
|
||||
/* start-of-frame handler
|
||||
* TODO: i guess it would be better to re-implement using timers,
|
||||
|
@ -628,9 +601,9 @@ static void keyboard_idle_timer_cb(void *arg) {
|
|||
}
|
||||
|
||||
#ifdef NKRO_ENABLE
|
||||
if(!keymap_config.nkro && keyboard_idle) {
|
||||
if(!keymap_config.nkro && keyboard_idle && keyboard_protocol) {
|
||||
#else /* NKRO_ENABLE */
|
||||
if(keyboard_idle) {
|
||||
if(keyboard_idle && keyboard_protocol) {
|
||||
#endif /* NKRO_ENABLE */
|
||||
/* TODO: are we sure we want the KBD_ENDPOINT? */
|
||||
if(!usbGetTransmitStatusI(usbp, KEYBOARD_IN_EPNUM)) {
|
||||
|
@ -661,25 +634,25 @@ void send_keyboard(report_keyboard_t *report) {
|
|||
osalSysUnlock();
|
||||
|
||||
#ifdef NKRO_ENABLE
|
||||
if(keymap_config.nkro) { /* NKRO protocol */
|
||||
if(keymap_config.nkro && keyboard_protocol) { /* NKRO protocol */
|
||||
/* need to wait until the previous packet has made it through */
|
||||
/* can rewrite this using the synchronous API, then would wait
|
||||
* until *after* the packet has been transmitted. I think
|
||||
* this is more efficient */
|
||||
/* busy wait, should be short and not very common */
|
||||
osalSysLock();
|
||||
if(usbGetTransmitStatusI(&USB_DRIVER, NKRO_IN_EPNUM)) {
|
||||
if(usbGetTransmitStatusI(&USB_DRIVER, SHARED_IN_EPNUM)) {
|
||||
/* Need to either suspend, or loop and call unlock/lock during
|
||||
* every iteration - otherwise the system will remain locked,
|
||||
* no interrupts served, so USB not going through as well.
|
||||
* Note: for suspend, need USB_USE_WAIT == TRUE in halconf.h */
|
||||
osalThreadSuspendS(&(&USB_DRIVER)->epc[NKRO_IN_EPNUM]->in_state->thread);
|
||||
osalThreadSuspendS(&(&USB_DRIVER)->epc[SHARED_IN_EPNUM]->in_state->thread);
|
||||
}
|
||||
usbStartTransmitI(&USB_DRIVER, NKRO_IN_EPNUM, (uint8_t *)report, sizeof(report_keyboard_t));
|
||||
usbStartTransmitI(&USB_DRIVER, SHARED_IN_EPNUM, (uint8_t *)report, sizeof(struct nkro_report));
|
||||
osalSysUnlock();
|
||||
} else
|
||||
#endif /* NKRO_ENABLE */
|
||||
{ /* boot protocol */
|
||||
{ /* regular protocol */
|
||||
/* need to wait until the previous packet has made it through */
|
||||
/* busy wait, should be short and not very common */
|
||||
osalSysLock();
|
||||
|
@ -690,7 +663,15 @@ void send_keyboard(report_keyboard_t *report) {
|
|||
* Note: for suspend, need USB_USE_WAIT == TRUE in halconf.h */
|
||||
osalThreadSuspendS(&(&USB_DRIVER)->epc[KEYBOARD_IN_EPNUM]->in_state->thread);
|
||||
}
|
||||
usbStartTransmitI(&USB_DRIVER, KEYBOARD_IN_EPNUM, (uint8_t *)report, KEYBOARD_EPSIZE);
|
||||
uint8_t *data, size;
|
||||
if (keyboard_protocol) {
|
||||
data = (uint8_t*)report;
|
||||
size = KEYBOARD_REPORT_SIZE;
|
||||
} else { /* boot protocol */
|
||||
data = &report->mods;
|
||||
size = 8;
|
||||
}
|
||||
usbStartTransmitI(&USB_DRIVER, KEYBOARD_IN_EPNUM, data, size);
|
||||
osalSysUnlock();
|
||||
}
|
||||
keyboard_report_sent = *report;
|
||||
|
@ -703,11 +684,13 @@ void send_keyboard(report_keyboard_t *report) {
|
|||
|
||||
#ifdef MOUSE_ENABLE
|
||||
|
||||
#ifndef MOUSE_SHARED_EP
|
||||
/* mouse IN callback hander (a mouse report has made it IN) */
|
||||
void mouse_in_cb(USBDriver *usbp, usbep_t ep) {
|
||||
(void)usbp;
|
||||
(void)ep;
|
||||
}
|
||||
#endif
|
||||
|
||||
void send_mouse(report_mouse_t *report) {
|
||||
osalSysLock();
|
||||
|
@ -715,15 +698,16 @@ void send_mouse(report_mouse_t *report) {
|
|||
osalSysUnlock();
|
||||
return;
|
||||
}
|
||||
osalSysUnlock();
|
||||
|
||||
osalSysLock();
|
||||
if(usbGetTransmitStatusI(&USB_DRIVER, MOUSE_IN_EPNUM)) {
|
||||
/* Need to either suspend, or loop and call unlock/lock during
|
||||
* every iteration - otherwise the system will remain locked,
|
||||
* no interrupts served, so USB not going through as well.
|
||||
* Note: for suspend, need USB_USE_WAIT == TRUE in halconf.h */
|
||||
osalThreadSuspendS(&(&USB_DRIVER)->epc[MOUSE_IN_EPNUM]->in_state->thread);
|
||||
if (osalThreadSuspendTimeoutS(&(&USB_DRIVER)->epc[MOUSE_IN_EPNUM]->in_state->thread, MS2ST(10))==MSG_TIMEOUT) {
|
||||
osalSysUnlock();
|
||||
return;
|
||||
}
|
||||
}
|
||||
usbStartTransmitI(&USB_DRIVER, MOUSE_IN_EPNUM, (uint8_t *)report, sizeof(report_mouse_t));
|
||||
osalSysUnlock();
|
||||
|
@ -735,20 +719,25 @@ void send_mouse(report_mouse_t *report) {
|
|||
}
|
||||
#endif /* MOUSE_ENABLE */
|
||||
|
||||
/* ---------------------------------------------------------
|
||||
* Shared EP functions
|
||||
* ---------------------------------------------------------
|
||||
*/
|
||||
#ifdef SHARED_EP_ENABLE
|
||||
/* shared IN callback hander */
|
||||
void shared_in_cb(USBDriver *usbp, usbep_t ep) {
|
||||
/* STUB */
|
||||
(void)usbp;
|
||||
(void)ep;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------
|
||||
* Extrakey functions
|
||||
* ---------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
|
||||
/* extrakey IN callback hander */
|
||||
void extra_in_cb(USBDriver *usbp, usbep_t ep) {
|
||||
/* STUB */
|
||||
(void)usbp;
|
||||
(void)ep;
|
||||
}
|
||||
|
||||
static void send_extra_report(uint8_t report_id, uint16_t data) {
|
||||
osalSysLock();
|
||||
if(usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
|
||||
|
@ -761,7 +750,7 @@ static void send_extra_report(uint8_t report_id, uint16_t data) {
|
|||
.usage = data
|
||||
};
|
||||
|
||||
usbStartTransmitI(&USB_DRIVER, EXTRAKEY_IN_EPNUM, (uint8_t *)&report, sizeof(report_extra_t));
|
||||
usbStartTransmitI(&USB_DRIVER, SHARED_IN_EPNUM, (uint8_t *)&report, sizeof(report_extra_t));
|
||||
osalSysUnlock();
|
||||
}
|
||||
|
||||
|
|
|
@ -65,6 +65,14 @@ void nkro_in_cb(USBDriver *usbp, usbep_t ep);
|
|||
void mouse_in_cb(USBDriver *usbp, usbep_t ep);
|
||||
#endif /* MOUSE_ENABLE */
|
||||
|
||||
/* ---------------
|
||||
* Shared EP header
|
||||
* ---------------
|
||||
*/
|
||||
|
||||
/* shared IN request callback handler */
|
||||
void shared_in_cb(USBDriver *usbp, usbep_t ep);
|
||||
|
||||
/* ---------------
|
||||
* Extrakey header
|
||||
* ---------------
|
||||
|
@ -72,9 +80,6 @@ void mouse_in_cb(USBDriver *usbp, usbep_t ep);
|
|||
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
|
||||
/* extrakey IN request callback handler */
|
||||
void extra_in_cb(USBDriver *usbp, usbep_t ep);
|
||||
|
||||
/* extra report structure */
|
||||
typedef struct {
|
||||
uint8_t report_id;
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#include "quantum.h"
|
||||
#include <util/atomic.h>
|
||||
#include "outputselect.h"
|
||||
#include "rgblight_reconfig.h"
|
||||
|
||||
#ifdef NKRO_ENABLE
|
||||
#include "keycode_config.h"
|
||||
|
@ -408,19 +409,21 @@ void EVENT_USB_Device_ConfigurationChanged(void)
|
|||
bool ConfigSuccess = true;
|
||||
|
||||
/* Setup Keyboard HID Report Endpoints */
|
||||
#ifndef KEYBOARD_SHARED_EP
|
||||
ConfigSuccess &= ENDPOINT_CONFIG(KEYBOARD_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
|
||||
KEYBOARD_EPSIZE, ENDPOINT_BANK_SINGLE);
|
||||
#endif
|
||||
|
||||
#ifdef MOUSE_ENABLE
|
||||
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
|
||||
/* Setup Mouse HID Report Endpoint */
|
||||
ConfigSuccess &= ENDPOINT_CONFIG(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
|
||||
MOUSE_EPSIZE, ENDPOINT_BANK_SINGLE);
|
||||
#endif
|
||||
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
/* Setup Extra HID Report Endpoint */
|
||||
ConfigSuccess &= ENDPOINT_CONFIG(EXTRAKEY_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
|
||||
EXTRAKEY_EPSIZE, ENDPOINT_BANK_SINGLE);
|
||||
#ifdef SHARED_EP_ENABLE
|
||||
/* Setup Shared HID Report Endpoint */
|
||||
ConfigSuccess &= ENDPOINT_CONFIG(SHARED_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
|
||||
SHARED_EPSIZE, ENDPOINT_BANK_SINGLE);
|
||||
#endif
|
||||
|
||||
#ifdef RAW_ENABLE
|
||||
|
@ -441,12 +444,6 @@ void EVENT_USB_Device_ConfigurationChanged(void)
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef NKRO_ENABLE
|
||||
/* Setup NKRO HID Report Endpoints */
|
||||
ConfigSuccess &= ENDPOINT_CONFIG(NKRO_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
|
||||
NKRO_EPSIZE, ENDPOINT_BANK_SINGLE);
|
||||
#endif
|
||||
|
||||
#ifdef MIDI_ENABLE
|
||||
ConfigSuccess &= Endpoint_ConfigureEndpoint(MIDI_STREAM_IN_EPADDR, EP_TYPE_BULK, MIDI_STREAM_EPSIZE, ENDPOINT_BANK_SINGLE);
|
||||
ConfigSuccess &= Endpoint_ConfigureEndpoint(MIDI_STREAM_OUT_EPADDR, EP_TYPE_BULK, MIDI_STREAM_EPSIZE, ENDPOINT_BANK_SINGLE);
|
||||
|
@ -511,8 +508,8 @@ void EVENT_USB_Device_ControlRequest(void)
|
|||
// Interface
|
||||
switch (USB_ControlRequest.wIndex) {
|
||||
case KEYBOARD_INTERFACE:
|
||||
#ifdef NKRO_ENABLE
|
||||
case NKRO_INTERFACE:
|
||||
#if defined(SHARED_EP_ENABLE) && !defined(KEYBOARD_SHARED_EP)
|
||||
case SHARED_INTERFACE:
|
||||
#endif
|
||||
Endpoint_ClearSETUP();
|
||||
|
||||
|
@ -520,7 +517,17 @@ void EVENT_USB_Device_ControlRequest(void)
|
|||
if (USB_DeviceState == DEVICE_STATE_Unattached)
|
||||
return;
|
||||
}
|
||||
#ifdef KEYBOARD_SHARED_EP
|
||||
uint8_t report_id = REPORT_ID_KEYBOARD;
|
||||
if (keyboard_protocol) {
|
||||
report_id = Endpoint_Read_8();
|
||||
}
|
||||
if (report_id == REPORT_ID_KEYBOARD || report_id == REPORT_ID_NKRO) {
|
||||
keyboard_led_stats = Endpoint_Read_8();
|
||||
}
|
||||
#else
|
||||
keyboard_led_stats = Endpoint_Read_8();
|
||||
#endif
|
||||
|
||||
Endpoint_ClearOUT();
|
||||
Endpoint_ClearStatusStage();
|
||||
|
@ -611,16 +618,20 @@ static void send_keyboard(report_keyboard_t *report)
|
|||
#ifdef MODULE_ADAFRUIT_BLE
|
||||
adafruit_ble_send_keys(report->mods, report->keys, sizeof(report->keys));
|
||||
#elif MODULE_RN42
|
||||
bluefruit_serial_send(0xFD);
|
||||
bluefruit_serial_send(0x09);
|
||||
bluefruit_serial_send(0x01);
|
||||
for (uint8_t i = 0; i < KEYBOARD_EPSIZE; i++) {
|
||||
bluefruit_serial_send(report->raw[i]);
|
||||
}
|
||||
bluefruit_serial_send(0xFD);
|
||||
bluefruit_serial_send(0x09);
|
||||
bluefruit_serial_send(0x01);
|
||||
bluefruit_serial_send(report->mods);
|
||||
bluefruit_serial_send(report->reserved);
|
||||
for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
|
||||
bluefruit_serial_send(report->keys[i]);
|
||||
}
|
||||
#else
|
||||
bluefruit_serial_send(0xFD);
|
||||
for (uint8_t i = 0; i < KEYBOARD_EPSIZE; i++) {
|
||||
bluefruit_serial_send(report->raw[i]);
|
||||
bluefruit_serial_send(report->mods);
|
||||
bluefruit_serial_send(report->reserved);
|
||||
for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
|
||||
bluefruit_serial_send(report->keys[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -631,30 +642,24 @@ static void send_keyboard(report_keyboard_t *report)
|
|||
}
|
||||
|
||||
/* Select the Keyboard Report Endpoint */
|
||||
uint8_t ep = KEYBOARD_IN_EPNUM;
|
||||
uint8_t size = KEYBOARD_REPORT_SIZE;
|
||||
#ifdef NKRO_ENABLE
|
||||
if (keyboard_protocol && keymap_config.nkro) {
|
||||
/* Report protocol - NKRO */
|
||||
Endpoint_SelectEndpoint(NKRO_IN_EPNUM);
|
||||
|
||||
/* Check if write ready for a polling interval around 1ms */
|
||||
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(4);
|
||||
if (!Endpoint_IsReadWriteAllowed()) return;
|
||||
|
||||
/* Write Keyboard Report Data */
|
||||
Endpoint_Write_Stream_LE(report, NKRO_EPSIZE, NULL);
|
||||
ep = SHARED_IN_EPNUM;
|
||||
size = sizeof(struct nkro_report);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* Boot protocol */
|
||||
Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);
|
||||
Endpoint_SelectEndpoint(ep);
|
||||
/* Check if write ready for a polling interval around 10ms */
|
||||
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
|
||||
if (!Endpoint_IsReadWriteAllowed()) return;
|
||||
|
||||
/* Check if write ready for a polling interval around 10ms */
|
||||
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
|
||||
if (!Endpoint_IsReadWriteAllowed()) return;
|
||||
|
||||
/* Write Keyboard Report Data */
|
||||
Endpoint_Write_Stream_LE(report, KEYBOARD_EPSIZE, NULL);
|
||||
/* If we're in Boot Protocol, don't send any report ID or other funky fields */
|
||||
if (!keyboard_protocol) {
|
||||
Endpoint_Write_Stream_LE(&report->mods, 8, NULL);
|
||||
} else {
|
||||
Endpoint_Write_Stream_LE(report, size, NULL);
|
||||
}
|
||||
|
||||
/* Finalize the stream transfer to send the last packet */
|
||||
|
@ -717,6 +722,7 @@ static void send_mouse(report_mouse_t *report)
|
|||
*/
|
||||
static void send_system(uint16_t data)
|
||||
{
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
uint8_t timeout = 255;
|
||||
|
||||
if (USB_DeviceState != DEVICE_STATE_Configured)
|
||||
|
@ -726,7 +732,7 @@ static void send_system(uint16_t data)
|
|||
.report_id = REPORT_ID_SYSTEM,
|
||||
.usage = data - SYSTEM_POWER_DOWN + 1
|
||||
};
|
||||
Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
|
||||
Endpoint_SelectEndpoint(SHARED_IN_EPNUM);
|
||||
|
||||
/* Check if write ready for a polling interval around 10ms */
|
||||
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
|
||||
|
@ -734,6 +740,7 @@ static void send_system(uint16_t data)
|
|||
|
||||
Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
|
||||
Endpoint_ClearIN();
|
||||
#endif
|
||||
}
|
||||
|
||||
/** \brief Send Consumer
|
||||
|
@ -742,6 +749,7 @@ static void send_system(uint16_t data)
|
|||
*/
|
||||
static void send_consumer(uint16_t data)
|
||||
{
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
uint8_t timeout = 255;
|
||||
uint8_t where = where_to_send();
|
||||
|
||||
|
@ -785,7 +793,7 @@ static void send_consumer(uint16_t data)
|
|||
.report_id = REPORT_ID_CONSUMER,
|
||||
.usage = data
|
||||
};
|
||||
Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
|
||||
Endpoint_SelectEndpoint(SHARED_IN_EPNUM);
|
||||
|
||||
/* Check if write ready for a polling interval around 10ms */
|
||||
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
|
||||
|
@ -793,6 +801,7 @@ static void send_consumer(uint16_t data)
|
|||
|
||||
Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
|
||||
Endpoint_ClearIN();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -47,11 +47,18 @@
|
|||
/*******************************************************************************
|
||||
* HID Report Descriptors
|
||||
******************************************************************************/
|
||||
const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] =
|
||||
{
|
||||
#ifdef KEYBOARD_SHARED_EP
|
||||
const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
|
||||
#define SHARED_REPORT_STARTED
|
||||
#else
|
||||
const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] = {
|
||||
#endif
|
||||
HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
|
||||
HID_RI_USAGE(8, 0x06), /* Keyboard */
|
||||
HID_RI_COLLECTION(8, 0x01), /* Application */
|
||||
# ifdef KEYBOARD_SHARED_EP
|
||||
HID_RI_REPORT_ID(8, REPORT_ID_KEYBOARD),
|
||||
# endif
|
||||
HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */
|
||||
HID_RI_USAGE_MINIMUM(8, 0xE0), /* Keyboard Left Control */
|
||||
HID_RI_USAGE_MAXIMUM(8, 0xE7), /* Keyboard Right GUI */
|
||||
|
@ -84,14 +91,25 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] =
|
|||
HID_RI_REPORT_SIZE(8, 0x08),
|
||||
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE),
|
||||
HID_RI_END_COLLECTION(0),
|
||||
};
|
||||
|
||||
#ifdef MOUSE_ENABLE
|
||||
const USB_Descriptor_HIDReport_Datatype_t PROGMEM MouseReport[] =
|
||||
{
|
||||
#ifndef KEYBOARD_SHARED_EP
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(MOUSE_ENABLE)
|
||||
|
||||
# if !defined(MOUSE_SHARED_EP)
|
||||
const USB_Descriptor_HIDReport_Datatype_t PROGMEM MouseReport[] = {
|
||||
# elif !defined(SHARED_REPORT_STARTED)
|
||||
const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
|
||||
#define SHARED_REPORT_STARTED
|
||||
# endif
|
||||
HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
|
||||
HID_RI_USAGE(8, 0x02), /* Mouse */
|
||||
HID_RI_COLLECTION(8, 0x01), /* Application */
|
||||
# ifdef MOUSE_SHARED_EP
|
||||
HID_RI_REPORT_ID(8, REPORT_ID_MOUSE),
|
||||
# endif
|
||||
HID_RI_USAGE(8, 0x01), /* Pointer */
|
||||
HID_RI_COLLECTION(8, 0x00), /* Physical */
|
||||
|
||||
|
@ -133,12 +151,15 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM MouseReport[] =
|
|||
|
||||
HID_RI_END_COLLECTION(0),
|
||||
HID_RI_END_COLLECTION(0),
|
||||
# ifndef MOUSE_SHARED_EP
|
||||
};
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
const USB_Descriptor_HIDReport_Datatype_t PROGMEM ExtrakeyReport[] =
|
||||
{
|
||||
#if defined(SHARED_EP_ENABLE) && !defined(SHARED_REPORT_STARTED)
|
||||
const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
|
||||
#endif
|
||||
# ifdef EXTRAKEY_ENABLE
|
||||
HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
|
||||
HID_RI_USAGE(8, 0x80), /* System Control */
|
||||
HID_RI_COLLECTION(8, 0x01), /* Application */
|
||||
|
@ -164,6 +185,43 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM ExtrakeyReport[] =
|
|||
HID_RI_REPORT_COUNT(8, 1),
|
||||
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE),
|
||||
HID_RI_END_COLLECTION(0),
|
||||
# endif
|
||||
|
||||
# ifdef NKRO_ENABLE
|
||||
HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
|
||||
HID_RI_USAGE(8, 0x06), /* Keyboard */
|
||||
HID_RI_COLLECTION(8, 0x01), /* Application */
|
||||
HID_RI_REPORT_ID(8, REPORT_ID_NKRO),
|
||||
HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */
|
||||
HID_RI_USAGE_MINIMUM(8, 0xE0), /* Keyboard Left Control */
|
||||
HID_RI_USAGE_MAXIMUM(8, 0xE7), /* Keyboard Right GUI */
|
||||
HID_RI_LOGICAL_MINIMUM(8, 0x00),
|
||||
HID_RI_LOGICAL_MAXIMUM(8, 0x01),
|
||||
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),
|
||||
|
||||
HID_RI_USAGE_PAGE(8, 0x08), /* LEDs */
|
||||
HID_RI_USAGE_MINIMUM(8, 0x01), /* Num Lock */
|
||||
HID_RI_USAGE_MAXIMUM(8, 0x05), /* Kana */
|
||||
HID_RI_REPORT_COUNT(8, 0x05),
|
||||
HID_RI_REPORT_SIZE(8, 0x01),
|
||||
HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
|
||||
HID_RI_REPORT_COUNT(8, 0x01),
|
||||
HID_RI_REPORT_SIZE(8, 0x03),
|
||||
HID_RI_OUTPUT(8, HID_IOF_CONSTANT),
|
||||
|
||||
HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */
|
||||
HID_RI_USAGE_MINIMUM(8, 0x00), /* Keyboard 0 */
|
||||
HID_RI_USAGE_MAXIMUM(8, KEYBOARD_REPORT_BITS*8-1),
|
||||
HID_RI_LOGICAL_MINIMUM(8, 0x00),
|
||||
HID_RI_LOGICAL_MAXIMUM(8, 0x01),
|
||||
HID_RI_REPORT_COUNT(8, KEYBOARD_REPORT_BITS*8),
|
||||
HID_RI_REPORT_SIZE(8, 0x01),
|
||||
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
|
||||
HID_RI_END_COLLECTION(0),
|
||||
# endif
|
||||
#ifdef SHARED_EP_ENABLE
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -211,42 +269,6 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM ConsoleReport[] =
|
|||
};
|
||||
#endif
|
||||
|
||||
#ifdef NKRO_ENABLE
|
||||
const USB_Descriptor_HIDReport_Datatype_t PROGMEM NKROReport[] =
|
||||
{
|
||||
HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
|
||||
HID_RI_USAGE(8, 0x06), /* Keyboard */
|
||||
HID_RI_COLLECTION(8, 0x01), /* Application */
|
||||
HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */
|
||||
HID_RI_USAGE_MINIMUM(8, 0xE0), /* Keyboard Left Control */
|
||||
HID_RI_USAGE_MAXIMUM(8, 0xE7), /* Keyboard Right GUI */
|
||||
HID_RI_LOGICAL_MINIMUM(8, 0x00),
|
||||
HID_RI_LOGICAL_MAXIMUM(8, 0x01),
|
||||
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),
|
||||
|
||||
HID_RI_USAGE_PAGE(8, 0x08), /* LEDs */
|
||||
HID_RI_USAGE_MINIMUM(8, 0x01), /* Num Lock */
|
||||
HID_RI_USAGE_MAXIMUM(8, 0x05), /* Kana */
|
||||
HID_RI_REPORT_COUNT(8, 0x05),
|
||||
HID_RI_REPORT_SIZE(8, 0x01),
|
||||
HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
|
||||
HID_RI_REPORT_COUNT(8, 0x01),
|
||||
HID_RI_REPORT_SIZE(8, 0x03),
|
||||
HID_RI_OUTPUT(8, HID_IOF_CONSTANT),
|
||||
|
||||
HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */
|
||||
HID_RI_USAGE_MINIMUM(8, 0x00), /* Keyboard 0 */
|
||||
HID_RI_USAGE_MAXIMUM(8, (NKRO_EPSIZE-1)*8-1), /* Keyboard Right GUI */
|
||||
HID_RI_LOGICAL_MINIMUM(8, 0x00),
|
||||
HID_RI_LOGICAL_MAXIMUM(8, 0x01),
|
||||
HID_RI_REPORT_COUNT(8, (NKRO_EPSIZE-1)*8),
|
||||
HID_RI_REPORT_SIZE(8, 0x01),
|
||||
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
|
||||
HID_RI_END_COLLECTION(0),
|
||||
};
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Device Descriptors
|
||||
|
@ -303,6 +325,7 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
|
|||
/*
|
||||
* Keyboard
|
||||
*/
|
||||
#ifndef KEYBOARD_SHARED_EP
|
||||
.Keyboard_Interface =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
|
||||
|
@ -339,11 +362,12 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
|
|||
.EndpointSize = KEYBOARD_EPSIZE,
|
||||
.PollingIntervalMS = 0x0A
|
||||
},
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Mouse
|
||||
*/
|
||||
#ifdef MOUSE_ENABLE
|
||||
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
|
||||
.Mouse_Interface =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
|
||||
|
@ -383,26 +407,31 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
|
|||
#endif
|
||||
|
||||
/*
|
||||
* Extra
|
||||
* Shared
|
||||
*/
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
.Extrakey_Interface =
|
||||
#ifdef SHARED_EP_ENABLE
|
||||
.Shared_Interface =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
|
||||
|
||||
.InterfaceNumber = EXTRAKEY_INTERFACE,
|
||||
.InterfaceNumber = SHARED_INTERFACE,
|
||||
.AlternateSetting = 0x00,
|
||||
|
||||
.TotalEndpoints = 1,
|
||||
|
||||
.Class = HID_CSCP_HIDClass,
|
||||
# ifdef KEYBOARD_SHARED_EP
|
||||
.SubClass = HID_CSCP_BootSubclass,
|
||||
.Protocol = HID_CSCP_KeyboardBootProtocol,
|
||||
# else
|
||||
.SubClass = HID_CSCP_NonBootSubclass,
|
||||
.Protocol = HID_CSCP_NonBootProtocol,
|
||||
#endif
|
||||
|
||||
.InterfaceStrIndex = NO_DESCRIPTOR
|
||||
},
|
||||
|
||||
.Extrakey_HID =
|
||||
.Shared_HID =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
|
||||
|
||||
|
@ -410,16 +439,16 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
|
|||
.CountryCode = 0x00,
|
||||
.TotalReportDescriptors = 1,
|
||||
.HIDReportType = HID_DTYPE_Report,
|
||||
.HIDReportLength = sizeof(ExtrakeyReport)
|
||||
.HIDReportLength = sizeof(SharedReport)
|
||||
},
|
||||
|
||||
.Extrakey_INEndpoint =
|
||||
.Shared_INEndpoint =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
|
||||
|
||||
.EndpointAddress = (ENDPOINT_DIR_IN | EXTRAKEY_IN_EPNUM),
|
||||
.EndpointAddress = (ENDPOINT_DIR_IN | SHARED_IN_EPNUM),
|
||||
.Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
|
||||
.EndpointSize = EXTRAKEY_EPSIZE,
|
||||
.EndpointSize = SHARED_EPSIZE,
|
||||
.PollingIntervalMS = 0x0A
|
||||
},
|
||||
#endif
|
||||
|
@ -528,48 +557,6 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
|
|||
},
|
||||
#endif
|
||||
|
||||
/*
|
||||
* NKRO
|
||||
*/
|
||||
#ifdef NKRO_ENABLE
|
||||
.NKRO_Interface =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
|
||||
|
||||
.InterfaceNumber = NKRO_INTERFACE,
|
||||
.AlternateSetting = 0x00,
|
||||
|
||||
.TotalEndpoints = 1,
|
||||
|
||||
.Class = HID_CSCP_HIDClass,
|
||||
.SubClass = HID_CSCP_NonBootSubclass,
|
||||
.Protocol = HID_CSCP_NonBootProtocol,
|
||||
|
||||
.InterfaceStrIndex = NO_DESCRIPTOR
|
||||
},
|
||||
|
||||
.NKRO_HID =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
|
||||
|
||||
.HIDSpec = VERSION_BCD(1,1,1),
|
||||
.CountryCode = 0x00,
|
||||
.TotalReportDescriptors = 1,
|
||||
.HIDReportType = HID_DTYPE_Report,
|
||||
.HIDReportLength = sizeof(NKROReport)
|
||||
},
|
||||
|
||||
.NKRO_INEndpoint =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
|
||||
|
||||
.EndpointAddress = (ENDPOINT_DIR_IN | NKRO_IN_EPNUM),
|
||||
.Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
|
||||
.EndpointSize = NKRO_EPSIZE,
|
||||
.PollingIntervalMS = 0x01
|
||||
},
|
||||
#endif
|
||||
|
||||
#ifdef MIDI_ENABLE
|
||||
.Audio_Interface_Association =
|
||||
{
|
||||
|
@ -936,19 +923,21 @@ uint16_t get_usb_descriptor(const uint16_t wValue,
|
|||
break;
|
||||
case HID_DTYPE_HID:
|
||||
switch (wIndex) {
|
||||
#ifndef KEYBOARD_SHARED_EP
|
||||
case KEYBOARD_INTERFACE:
|
||||
Address = &ConfigurationDescriptor.Keyboard_HID;
|
||||
Size = sizeof(USB_HID_Descriptor_HID_t);
|
||||
break;
|
||||
#ifdef MOUSE_ENABLE
|
||||
#endif
|
||||
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
|
||||
case MOUSE_INTERFACE:
|
||||
Address = &ConfigurationDescriptor.Mouse_HID;
|
||||
Size = sizeof(USB_HID_Descriptor_HID_t);
|
||||
break;
|
||||
#endif
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
case EXTRAKEY_INTERFACE:
|
||||
Address = &ConfigurationDescriptor.Extrakey_HID;
|
||||
#ifdef SHARED_EP_ENABLE
|
||||
case SHARED_INTERFACE:
|
||||
Address = &ConfigurationDescriptor.Shared_HID;
|
||||
Size = sizeof(USB_HID_Descriptor_HID_t);
|
||||
break;
|
||||
#endif
|
||||
|
@ -963,31 +952,27 @@ uint16_t get_usb_descriptor(const uint16_t wValue,
|
|||
Address = &ConfigurationDescriptor.Console_HID;
|
||||
Size = sizeof(USB_HID_Descriptor_HID_t);
|
||||
break;
|
||||
#endif
|
||||
#ifdef NKRO_ENABLE
|
||||
case NKRO_INTERFACE:
|
||||
Address = &ConfigurationDescriptor.NKRO_HID;
|
||||
Size = sizeof(USB_HID_Descriptor_HID_t);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case HID_DTYPE_Report:
|
||||
switch (wIndex) {
|
||||
#ifndef KEYBOARD_SHARED_EP
|
||||
case KEYBOARD_INTERFACE:
|
||||
Address = &KeyboardReport;
|
||||
Size = sizeof(KeyboardReport);
|
||||
break;
|
||||
#ifdef MOUSE_ENABLE
|
||||
#endif
|
||||
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
|
||||
case MOUSE_INTERFACE:
|
||||
Address = &MouseReport;
|
||||
Size = sizeof(MouseReport);
|
||||
break;
|
||||
#endif
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
case EXTRAKEY_INTERFACE:
|
||||
Address = &ExtrakeyReport;
|
||||
Size = sizeof(ExtrakeyReport);
|
||||
#ifdef SHARED_EP_ENABLE
|
||||
case SHARED_INTERFACE:
|
||||
Address = &SharedReport;
|
||||
Size = sizeof(SharedReport);
|
||||
break;
|
||||
#endif
|
||||
#ifdef RAW_ENABLE
|
||||
|
@ -1001,12 +986,6 @@ uint16_t get_usb_descriptor(const uint16_t wValue,
|
|||
Address = &ConsoleReport;
|
||||
Size = sizeof(ConsoleReport);
|
||||
break;
|
||||
#endif
|
||||
#ifdef NKRO_ENABLE
|
||||
case NKRO_INTERFACE:
|
||||
Address = &NKROReport;
|
||||
Size = sizeof(NKROReport);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -53,26 +53,27 @@ typedef struct
|
|||
{
|
||||
USB_Descriptor_Configuration_Header_t Config;
|
||||
|
||||
#ifndef KEYBOARD_SHARED_EP
|
||||
// Keyboard HID Interface
|
||||
USB_Descriptor_Interface_t Keyboard_Interface;
|
||||
USB_HID_Descriptor_HID_t Keyboard_HID;
|
||||
USB_Descriptor_Endpoint_t Keyboard_INEndpoint;
|
||||
#endif
|
||||
|
||||
#ifdef MOUSE_ENABLE
|
||||
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
|
||||
// Mouse HID Interface
|
||||
USB_Descriptor_Interface_t Mouse_Interface;
|
||||
USB_HID_Descriptor_HID_t Mouse_HID;
|
||||
USB_Descriptor_Endpoint_t Mouse_INEndpoint;
|
||||
#endif
|
||||
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
// Extrakey HID Interface
|
||||
USB_Descriptor_Interface_t Extrakey_Interface;
|
||||
USB_HID_Descriptor_HID_t Extrakey_HID;
|
||||
USB_Descriptor_Endpoint_t Extrakey_INEndpoint;
|
||||
#if defined(SHARED_EP_ENABLE)
|
||||
USB_Descriptor_Interface_t Shared_Interface;
|
||||
USB_HID_Descriptor_HID_t Shared_HID;
|
||||
USB_Descriptor_Endpoint_t Shared_INEndpoint;
|
||||
#endif
|
||||
|
||||
#ifdef RAW_ENABLE
|
||||
#if defined(RAW_ENABLE)
|
||||
// Raw HID Interface
|
||||
USB_Descriptor_Interface_t Raw_Interface;
|
||||
USB_HID_Descriptor_HID_t Raw_HID;
|
||||
|
@ -88,13 +89,6 @@ typedef struct
|
|||
USB_Descriptor_Endpoint_t Console_OUTEndpoint;
|
||||
#endif
|
||||
|
||||
#ifdef NKRO_ENABLE
|
||||
// NKRO HID Interface
|
||||
USB_Descriptor_Interface_t NKRO_Interface;
|
||||
USB_HID_Descriptor_HID_t NKRO_HID;
|
||||
USB_Descriptor_Endpoint_t NKRO_INEndpoint;
|
||||
#endif
|
||||
|
||||
#ifdef MIDI_ENABLE
|
||||
USB_Descriptor_Interface_Association_t Audio_Interface_Association;
|
||||
// MIDI Audio Control Interface
|
||||
|
@ -133,133 +127,105 @@ typedef struct
|
|||
|
||||
|
||||
/* index of interface */
|
||||
#define KEYBOARD_INTERFACE 0
|
||||
|
||||
enum usb_interfaces {
|
||||
#if !defined(KEYBOARD_SHARED_EP)
|
||||
KEYBOARD_INTERFACE,
|
||||
#else
|
||||
# define KEYBOARD_INTERFACE SHARED_INTERFACE
|
||||
#endif
|
||||
// It is important that the Raw HID interface is at a constant
|
||||
// interface number, to support Linux/OSX platforms and chrome.hid
|
||||
// If Raw HID is enabled, let it be always 1.
|
||||
#ifdef RAW_ENABLE
|
||||
# define RAW_INTERFACE (KEYBOARD_INTERFACE + 1)
|
||||
#else
|
||||
# define RAW_INTERFACE KEYBOARD_INTERFACE
|
||||
#if defined(RAW_ENABLE)
|
||||
RAW_INTERFACE,
|
||||
#endif
|
||||
|
||||
#ifdef MOUSE_ENABLE
|
||||
# define MOUSE_INTERFACE (RAW_INTERFACE + 1)
|
||||
#else
|
||||
# define MOUSE_INTERFACE RAW_INTERFACE
|
||||
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
|
||||
MOUSE_INTERFACE,
|
||||
#endif
|
||||
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
# define EXTRAKEY_INTERFACE (MOUSE_INTERFACE + 1)
|
||||
#else
|
||||
# define EXTRAKEY_INTERFACE MOUSE_INTERFACE
|
||||
#if defined(SHARED_EP_ENABLE)
|
||||
SHARED_INTERFACE,
|
||||
#endif
|
||||
|
||||
#ifdef CONSOLE_ENABLE
|
||||
# define CONSOLE_INTERFACE (EXTRAKEY_INTERFACE + 1)
|
||||
#else
|
||||
# define CONSOLE_INTERFACE EXTRAKEY_INTERFACE
|
||||
#if defined(CONSOLE_ENABLE)
|
||||
CONSOLE_INTERFACE,
|
||||
#endif
|
||||
|
||||
#ifdef NKRO_ENABLE
|
||||
# define NKRO_INTERFACE (CONSOLE_INTERFACE + 1)
|
||||
#else
|
||||
# define NKRO_INTERFACE CONSOLE_INTERFACE
|
||||
#if defined(MIDI_ENABLE)
|
||||
AC_INTERFACE,
|
||||
AS_INTERFACE,
|
||||
#endif
|
||||
|
||||
#ifdef MIDI_ENABLE
|
||||
# define AC_INTERFACE (NKRO_INTERFACE + 1)
|
||||
# define AS_INTERFACE (NKRO_INTERFACE + 2)
|
||||
#else
|
||||
# define AS_INTERFACE NKRO_INTERFACE
|
||||
#if defined(VIRTSER_ENABLE)
|
||||
CCI_INTERFACE,
|
||||
CDI_INTERFACE,
|
||||
#endif
|
||||
TOTAL_INTERFACES
|
||||
};
|
||||
|
||||
#ifdef VIRTSER_ENABLE
|
||||
# define CCI_INTERFACE (AS_INTERFACE + 1)
|
||||
# define CDI_INTERFACE (AS_INTERFACE + 2)
|
||||
#define NEXT_EPNUM __COUNTER__
|
||||
|
||||
enum usb_endpoints {
|
||||
__unused_epnum__ = NEXT_EPNUM, /* EP numbering starts at 1 */
|
||||
#if !defined(KEYBOARD_SHARED_EP)
|
||||
KEYBOARD_IN_EPNUM = NEXT_EPNUM,
|
||||
#else
|
||||
# define CDI_INTERFACE AS_INTERFACE
|
||||
# define KEYBOARD_IN_EPNUM SHARED_IN_EPNUM
|
||||
#endif
|
||||
|
||||
/* nubmer of interfaces */
|
||||
#define TOTAL_INTERFACES (CDI_INTERFACE + 1)
|
||||
|
||||
|
||||
// Endopoint number and size
|
||||
#define KEYBOARD_IN_EPNUM 1
|
||||
|
||||
#ifdef MOUSE_ENABLE
|
||||
# define MOUSE_IN_EPNUM (KEYBOARD_IN_EPNUM + 1)
|
||||
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
|
||||
MOUSE_IN_EPNUM = NEXT_EPNUM,
|
||||
#else
|
||||
# define MOUSE_IN_EPNUM KEYBOARD_IN_EPNUM
|
||||
# define MOUSE_IN_EPNUM SHARED_IN_EPNUM
|
||||
#endif
|
||||
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
# define EXTRAKEY_IN_EPNUM (MOUSE_IN_EPNUM + 1)
|
||||
#else
|
||||
# define EXTRAKEY_IN_EPNUM MOUSE_IN_EPNUM
|
||||
#if defined(RAW_ENABLE)
|
||||
RAW_IN_EPNUM = NEXT_EPNUM,
|
||||
RAW_OUT_EPNUM = NEXT_EPNUM,
|
||||
#endif
|
||||
|
||||
#ifdef RAW_ENABLE
|
||||
# define RAW_IN_EPNUM (EXTRAKEY_IN_EPNUM + 1)
|
||||
# define RAW_OUT_EPNUM (EXTRAKEY_IN_EPNUM + 2)
|
||||
#else
|
||||
# define RAW_OUT_EPNUM EXTRAKEY_IN_EPNUM
|
||||
#if defined(SHARED_EP_ENABLE)
|
||||
SHARED_IN_EPNUM = NEXT_EPNUM,
|
||||
#endif
|
||||
|
||||
#ifdef CONSOLE_ENABLE
|
||||
# define CONSOLE_IN_EPNUM (RAW_OUT_EPNUM + 1)
|
||||
#if defined(CONSOLE_ENABLE)
|
||||
CONSOLE_IN_EPNUM = NEXT_EPNUM,
|
||||
#ifdef PROTOCOL_CHIBIOS
|
||||
// ChibiOS has enough memory and descriptor to actually enable the endpoint
|
||||
// It could use the same endpoint numbers, as that's supported by ChibiOS
|
||||
// But the QMK code currently assumes that the endpoint numbers are different
|
||||
# define CONSOLE_OUT_EPNUM (RAW_OUT_EPNUM + 2)
|
||||
CONSOLE_OUT_EPNUM = NEXT_EPNUM,
|
||||
#else
|
||||
# define CONSOLE_OUT_EPNUM (RAW_OUT_EPNUM + 1)
|
||||
#define CONSOLE_OUT_EPNUM CONSOLE_IN_EPNUM
|
||||
#endif
|
||||
#else
|
||||
# define CONSOLE_OUT_EPNUM RAW_OUT_EPNUM
|
||||
#endif
|
||||
|
||||
#ifdef NKRO_ENABLE
|
||||
# define NKRO_IN_EPNUM (CONSOLE_OUT_EPNUM + 1)
|
||||
#else
|
||||
# define NKRO_IN_EPNUM CONSOLE_OUT_EPNUM
|
||||
#endif
|
||||
|
||||
#ifdef MIDI_ENABLE
|
||||
# define MIDI_STREAM_IN_EPNUM (NKRO_IN_EPNUM + 1)
|
||||
// # define MIDI_STREAM_OUT_EPNUM (NKRO_IN_EPNUM + 1)
|
||||
# define MIDI_STREAM_OUT_EPNUM (NKRO_IN_EPNUM + 2)
|
||||
MIDI_STREAM_IN_EPNUM = NEXT_EPNUM,
|
||||
MIDI_STREAM_OUT_EPNUM = NEXT_EPNUM,
|
||||
# define MIDI_STREAM_IN_EPADDR (ENDPOINT_DIR_IN | MIDI_STREAM_IN_EPNUM)
|
||||
# define MIDI_STREAM_OUT_EPADDR (ENDPOINT_DIR_OUT | MIDI_STREAM_OUT_EPNUM)
|
||||
#else
|
||||
# define MIDI_STREAM_OUT_EPNUM NKRO_IN_EPNUM
|
||||
#endif
|
||||
|
||||
#ifdef VIRTSER_ENABLE
|
||||
# define CDC_NOTIFICATION_EPNUM (MIDI_STREAM_OUT_EPNUM + 1)
|
||||
# define CDC_IN_EPNUM (MIDI_STREAM_OUT_EPNUM + 2)
|
||||
# define CDC_OUT_EPNUM (MIDI_STREAM_OUT_EPNUM + 3)
|
||||
CDC_NOTIFICATION_EPNUM = NEXT_EPNUM,
|
||||
CDC_IN_EPNUM = NEXT_EPNUM,
|
||||
CDC_OUT_EPNUM = NEXT_EPNUM,
|
||||
# define CDC_NOTIFICATION_EPADDR (ENDPOINT_DIR_IN | CDC_NOTIFICATION_EPNUM)
|
||||
# define CDC_IN_EPADDR (ENDPOINT_DIR_IN | CDC_IN_EPNUM)
|
||||
# define CDC_OUT_EPADDR (ENDPOINT_DIR_OUT | CDC_OUT_EPNUM)
|
||||
#else
|
||||
# define CDC_OUT_EPNUM MIDI_STREAM_OUT_EPNUM
|
||||
#endif
|
||||
};
|
||||
|
||||
#if (defined(PROTOCOL_LUFA) && CDC_OUT_EPNUM > (ENDPOINT_TOTAL_ENDPOINTS - 1)) || \
|
||||
(defined(PROTOCOL_CHIBIOS) && CDC_OUT_EPNUM > USB_MAX_ENDPOINTS)
|
||||
# error "There are not enough available endpoints to support all functions. Remove some in the rules.mk file.(MOUSEKEY, EXTRAKEY, CONSOLE, NKRO, MIDI, SERIAL, STENO)"
|
||||
#if defined(PROTOCOL_LUFA)
|
||||
/* LUFA tells us total endpoints including control */
|
||||
#define MAX_ENDPOINTS (ENDPOINT_TOTAL_ENDPOINTS - 1)
|
||||
#elif defined(PROTOCOL_CHIBIOS)
|
||||
/* ChibiOS gives us number of available user endpoints, not control */
|
||||
#define MAX_ENDPOINTS USB_MAX_ENDPOINTS
|
||||
#endif
|
||||
/* TODO - ARM_ATSAM */
|
||||
|
||||
|
||||
#if (NEXT_EPNUM - 1) > MAX_ENDPOINTS
|
||||
# error There are not enough available endpoints to support all functions. Remove some in the rules.mk file. (MOUSEKEY, EXTRAKEY, CONSOLE, NKRO, MIDI, SERIAL, STENO)
|
||||
#endif
|
||||
|
||||
#define KEYBOARD_EPSIZE 8
|
||||
#define SHARED_EPSIZE 32
|
||||
#define MOUSE_EPSIZE 8
|
||||
#define EXTRAKEY_EPSIZE 8
|
||||
#define RAW_EPSIZE 32
|
||||
#define CONSOLE_EPSIZE 32
|
||||
#define NKRO_EPSIZE 32
|
||||
#define MIDI_STREAM_EPSIZE 64
|
||||
#define CDC_NOTIFICATION_EPSIZE 8
|
||||
#define CDC_EPSIZE 16
|
||||
|
|
|
@ -118,7 +118,7 @@ RTMODEL "__rt_version", "3"
|
|||
# define polyH r21
|
||||
# define scratch r23
|
||||
|
||||
#else /* __IAR_SYSTEMS_ASM__ */
|
||||
#else /* __IAR_SYSTEMS_ASM__ */
|
||||
/* Register assignments for usbCrc16 on gcc */
|
||||
/* Calling conventions on gcc:
|
||||
* First parameter passed in r24/r25, second in r22/23 and so on.
|
||||
|
@ -151,7 +151,7 @@ RTMODEL "__rt_version", "3"
|
|||
; unsigned table(unsigned char x)
|
||||
; {
|
||||
; unsigned value;
|
||||
;
|
||||
;
|
||||
; value = (unsigned)x << 6;
|
||||
; value ^= (unsigned)x << 7;
|
||||
; if(parity(x))
|
||||
|
@ -161,7 +161,7 @@ RTMODEL "__rt_version", "3"
|
|||
; unsigned usbCrc16(unsigned char *argPtr, unsigned char argLen)
|
||||
; {
|
||||
; unsigned crc = 0xffff;
|
||||
;
|
||||
;
|
||||
; while(argLen--)
|
||||
; crc = table(lo8(crc) ^ *argPtr++) ^ hi8(crc);
|
||||
; return ~crc;
|
||||
|
@ -299,7 +299,7 @@ usbCrc16Append:
|
|||
# define cnt16H r31
|
||||
# define cntH r18
|
||||
|
||||
#else /* __IAR_SYSTEMS_ASM__ */
|
||||
#else /* __IAR_SYSTEMS_ASM__ */
|
||||
/* Register assignments for usbMeasureFrameLength on gcc */
|
||||
/* Calling conventions on gcc:
|
||||
* First parameter passed in r24/r25, second in r22/23 and so on.
|
||||
|
|
71
tmk_core/protocol/xt.h
Normal file
71
tmk_core/protocol/xt.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
Copyright 2018 Jun WAKO <wakojun@gmail.com>
|
||||
Copyright 2016 Ethan Apodaca <papodaca@gmail.com>
|
||||
|
||||
This software is licensed with a Modified BSD License.
|
||||
All of this is supposed to be Free Software, Open Source, DFSG-free,
|
||||
GPL-compatible, and OK to use in both free and proprietary applications.
|
||||
Additions and corrections to this file are welcome.
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
* Neither the name of the copyright holders nor the names of
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef XT_H
|
||||
#define XT_H
|
||||
|
||||
#define XT_DATA_IN() do { \
|
||||
XT_DATA_DDR &= ~(1<<XT_DATA_BIT); \
|
||||
XT_DATA_PORT |= (1<<XT_DATA_BIT); \
|
||||
} while (0)
|
||||
|
||||
#define XT_DATA_READ() (XT_DATA_PIN&(1<<XT_DATA_BIT))
|
||||
|
||||
#define XT_DATA_LO() do { \
|
||||
XT_DATA_PORT &= ~(1<<XT_DATA_BIT); \
|
||||
XT_DATA_DDR |= (1<<XT_DATA_BIT); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define XT_CLOCK_IN() do { \
|
||||
XT_CLOCK_DDR &= ~(1<<XT_CLOCK_BIT); \
|
||||
XT_CLOCK_PORT |= (1<<XT_CLOCK_BIT); \
|
||||
} while (0)
|
||||
|
||||
#define XT_CLOCK_READ() (XT_CLOCK_PIN&(1<<XT_CLOCK_BIT))
|
||||
|
||||
#define XT_CLOCK_LO() do { \
|
||||
XT_CLOCK_PORT &= ~(1<<XT_CLOCK_BIT); \
|
||||
XT_CLOCK_DDR |= (1<<XT_CLOCK_BIT); \
|
||||
} while (0)
|
||||
|
||||
|
||||
void xt_host_init(void);
|
||||
uint8_t xt_host_recv(void);
|
||||
|
||||
#endif
|
173
tmk_core/protocol/xt_interrupt.c
Normal file
173
tmk_core/protocol/xt_interrupt.c
Normal file
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
Copyright 2018 Jun WAKO <wakojun@gmail.com>
|
||||
Copyright 2016 Ethan Apodaca <papodaca@gmail.com>
|
||||
|
||||
This software is licensed with a Modified BSD License.
|
||||
All of this is supposed to be Free Software, Open Source, DFSG-free,
|
||||
GPL-compatible, and OK to use in both free and proprietary applications.
|
||||
Additions and corrections to this file are welcome.
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
* Neither the name of the copyright holders nor the names of
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <util/delay.h>
|
||||
#include "xt.h"
|
||||
#include "wait.h"
|
||||
#include "print.h"
|
||||
|
||||
static inline uint8_t pbuf_dequeue(void);
|
||||
static inline void pbuf_enqueue(uint8_t data);
|
||||
static inline bool pbuf_has_data(void);
|
||||
static inline void pbuf_clear(void);
|
||||
|
||||
void xt_host_init(void)
|
||||
{
|
||||
XT_INT_INIT();
|
||||
XT_INT_OFF();
|
||||
|
||||
/* hard reset */
|
||||
#ifdef XT_RESET
|
||||
XT_RESET();
|
||||
#endif
|
||||
|
||||
/* soft reset: pull clock line down for 20ms */
|
||||
XT_DATA_LO();
|
||||
XT_CLOCK_LO();
|
||||
_delay_ms(20);
|
||||
|
||||
/* input mode with pullup */
|
||||
XT_CLOCK_IN();
|
||||
XT_DATA_IN();
|
||||
|
||||
XT_INT_ON();
|
||||
}
|
||||
|
||||
/* get data received by interrupt */
|
||||
uint8_t xt_host_recv(void)
|
||||
{
|
||||
if (pbuf_has_data()) {
|
||||
return pbuf_dequeue();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ISR(XT_INT_VECT)
|
||||
{
|
||||
/*
|
||||
* XT signal format consits of 10 or 9 clocks and sends start bits and 8-bit data,
|
||||
* which should be read on falling edge of clock.
|
||||
*
|
||||
* start(0), start(1), bit0, bit1, bit2, bit3, bit4, bit5, bit6, bit7
|
||||
*
|
||||
* Original IBM XT keyboard sends start(0) bit while some of clones don't.
|
||||
* Start(0) bit is read as low on data line while start(1) as high.
|
||||
*
|
||||
* https://github.com/tmk/tmk_keyboard/wiki/IBM-PC-XT-Keyboard-Protocol
|
||||
*/
|
||||
static enum {
|
||||
START, BIT0, BIT1, BIT2, BIT3, BIT4, BIT5, BIT6, BIT7
|
||||
} state = START;
|
||||
static uint8_t data = 0;
|
||||
|
||||
uint8_t dbit = XT_DATA_READ();
|
||||
|
||||
// This is needed if using PCINT which can be called on both falling and rising edge
|
||||
//if (XT_CLOCK_READ()) return;
|
||||
|
||||
switch (state) {
|
||||
case START:
|
||||
// ignore start(0) bit
|
||||
if (!dbit) return;
|
||||
break;
|
||||
case BIT0 ... BIT7:
|
||||
data >>= 1;
|
||||
if (dbit)
|
||||
data |= 0x80;
|
||||
break;
|
||||
}
|
||||
if (state++ == BIT7) {
|
||||
pbuf_enqueue(data);
|
||||
state = START;
|
||||
data = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* Ring buffer to store scan codes from keyboard
|
||||
*------------------------------------------------------------------*/
|
||||
#define PBUF_SIZE 32
|
||||
static uint8_t pbuf[PBUF_SIZE];
|
||||
static uint8_t pbuf_head = 0;
|
||||
static uint8_t pbuf_tail = 0;
|
||||
static inline void pbuf_enqueue(uint8_t data)
|
||||
{
|
||||
uint8_t sreg = SREG;
|
||||
cli();
|
||||
uint8_t next = (pbuf_head + 1) % PBUF_SIZE;
|
||||
if (next != pbuf_tail) {
|
||||
pbuf[pbuf_head] = data;
|
||||
pbuf_head = next;
|
||||
} else {
|
||||
print("pbuf: full\n");
|
||||
}
|
||||
SREG = sreg;
|
||||
}
|
||||
static inline uint8_t pbuf_dequeue(void)
|
||||
{
|
||||
uint8_t val = 0;
|
||||
|
||||
uint8_t sreg = SREG;
|
||||
cli();
|
||||
if (pbuf_head != pbuf_tail) {
|
||||
val = pbuf[pbuf_tail];
|
||||
pbuf_tail = (pbuf_tail + 1) % PBUF_SIZE;
|
||||
}
|
||||
SREG = sreg;
|
||||
|
||||
return val;
|
||||
}
|
||||
static inline bool pbuf_has_data(void)
|
||||
{
|
||||
uint8_t sreg = SREG;
|
||||
cli();
|
||||
bool has_data = (pbuf_head != pbuf_tail);
|
||||
SREG = sreg;
|
||||
return has_data;
|
||||
}
|
||||
static inline void pbuf_clear(void)
|
||||
{
|
||||
uint8_t sreg = SREG;
|
||||
cli();
|
||||
pbuf_head = pbuf_tail = 0;
|
||||
SREG = sreg;
|
||||
}
|
|
@ -28,12 +28,13 @@ VPATH :=
|
|||
|
||||
# Convert all SRC to OBJ
|
||||
define OBJ_FROM_SRC
|
||||
$(patsubst %.c,$1/%.o,$(patsubst %.cpp,$1/%.o,$(patsubst %.cc,$1/%.o,$(patsubst %.S,$1/%.o,$($1_SRC)))))
|
||||
$(patsubst %.c,$1/%.o,$(patsubst %.cpp,$1/%.o,$(patsubst %.cc,$1/%.o,$(patsubst %.S,$1/%.o,$(patsubst %.clib,$1/%.a,$($1_SRC))))))
|
||||
endef
|
||||
$(foreach OUTPUT,$(OUTPUTS),$(eval $(OUTPUT)_OBJ +=$(call OBJ_FROM_SRC,$(OUTPUT))))
|
||||
|
||||
# Define a list of all objects
|
||||
OBJ := $(foreach OUTPUT,$(OUTPUTS),$($(OUTPUT)_OBJ))
|
||||
NO_LTO_OBJ := $(filter %.a,$(OBJ))
|
||||
|
||||
MASTER_OUTPUT := $(firstword $(OUTPUTS))
|
||||
|
||||
|
@ -81,7 +82,9 @@ CSTANDARD = -std=gnu99
|
|||
# -Wall...: warning level
|
||||
# -Wa,...: tell GCC to pass this to the assembler.
|
||||
# -adhlns...: create assembler listing
|
||||
CFLAGS += -g$(DEBUG)
|
||||
ifndef SKIP_DEBUG_INFO
|
||||
CFLAGS += -g$(DEBUG)
|
||||
endif
|
||||
CFLAGS += $(CDEFS)
|
||||
CFLAGS += -O$(OPT)
|
||||
# add color
|
||||
|
@ -103,7 +106,6 @@ endif
|
|||
CFLAGS += -Wa,-adhlns=$(@:%.o=%.lst)
|
||||
CFLAGS += $(CSTANDARD)
|
||||
|
||||
|
||||
#---------------- Compiler Options C++ ----------------
|
||||
# -g*: generate debugging information
|
||||
# -O*: optimization level
|
||||
|
@ -111,7 +113,9 @@ CFLAGS += $(CSTANDARD)
|
|||
# -Wall...: warning level
|
||||
# -Wa,...: tell GCC to pass this to the assembler.
|
||||
# -adhlns...: create assembler listing
|
||||
CPPFLAGS += -g$(DEBUG)
|
||||
ifndef SKIP_DEBUG_INFO
|
||||
CPPFLAGS += -g$(DEBUG)
|
||||
endif
|
||||
CPPFLAGS += $(CPPDEFS)
|
||||
CPPFLAGS += -O$(OPT)
|
||||
# to supress "warning: only initialized variables can be placed into program memory area"
|
||||
|
@ -139,7 +143,11 @@ CPPFLAGS += -Wa,-adhlns=$(@:%.o=%.lst)
|
|||
# -listing-cont-lines: Sets the maximum number of continuation lines of hex
|
||||
# dump that will be displayed for a given single line of source input.
|
||||
ASFLAGS += $(ADEFS)
|
||||
ASFLAGS += -Wa,-adhlns=$(@:%.o=%.lst),-gstabs,--listing-cont-lines=100
|
||||
ifndef SKIP_DEBUG_INFO
|
||||
ASFLAGS += -Wa,-adhlns=$(@:%.o=%.lst),-gstabs,--listing-cont-lines=100
|
||||
else
|
||||
ASFLAGS += -Wa,-adhlns=$(@:%.o=%.lst),--listing-cont-lines=100
|
||||
endif
|
||||
|
||||
#---------------- Library Options ----------------
|
||||
# Minimalistic printf version
|
||||
|
@ -211,6 +219,11 @@ ALL_CFLAGS = $(MCUFLAGS) $(CFLAGS) $(EXTRAFLAGS)
|
|||
ALL_CPPFLAGS = $(MCUFLAGS) -x c++ $(CPPFLAGS) $(EXTRAFLAGS)
|
||||
ALL_ASFLAGS = $(MCUFLAGS) -x assembler-with-cpp $(ASFLAGS) $(EXTRAFLAGS)
|
||||
|
||||
define NO_LTO
|
||||
$(patsubst %.a,%.o,$1): NOLTO_CFLAGS += -fno-lto
|
||||
endef
|
||||
$(foreach LOBJ, $(NO_LTO_OBJ), $(eval $(call NO_LTO,$(LOBJ))))
|
||||
|
||||
MOVE_DEP = mv -f $(patsubst %.o,%.td,$@) $(patsubst %.o,%.d,$@)
|
||||
|
||||
|
||||
|
@ -291,8 +304,8 @@ $1_INCFLAGS := $$(patsubst %,-I%,$$($1_INC))
|
|||
ifdef $1_CONFIG
|
||||
$1_CONFIG_FLAGS += $$(patsubst %,-include %,$$($1_CONFIG))
|
||||
endif
|
||||
$1_CFLAGS = $$(ALL_CFLAGS) $$($1_DEFS) $$($1_INCFLAGS) $$($1_CONFIG_FLAGS)
|
||||
$1_CPPFLAGS= $$(ALL_CPPFLAGS) $$($1_DEFS) $$($1_INCFLAGS) $$($1_CONFIG_FLAGS)
|
||||
$1_CFLAGS = $$(ALL_CFLAGS) $$($1_DEFS) $$($1_INCFLAGS) $$($1_CONFIG_FLAGS) $$(NOLTO_CFLAGS)
|
||||
$1_CPPFLAGS= $$(ALL_CPPFLAGS) $$($1_DEFS) $$($1_INCFLAGS) $$($1_CONFIG_FLAGS) $$(NOLTO_CFLAGS)
|
||||
$1_ASFLAGS= $$(ALL_ASFLAGS) $$($1_DEFS) $$($1_INCFLAGS) $$($1_CONFIG_FLAGS)
|
||||
|
||||
# Compile: create object files from C source files.
|
||||
|
@ -322,6 +335,12 @@ $1/%.o : %.S $1/asflags.txt $1/compiler.txt | $(BEGIN)
|
|||
$$(eval CMD=$$(CC) -c $$($1_ASFLAGS) $$< -o $$@)
|
||||
@$$(BUILD_CMD)
|
||||
|
||||
$1/%.a : $1/%.o
|
||||
@mkdir -p $$(@D)
|
||||
@$(SILENT) || printf "Archiving: $$<" | $$(AWK_CMD)
|
||||
$$(eval CMD=$$(AR) $$@ $$<)
|
||||
@$$(BUILD_CMD)
|
||||
|
||||
$1/force:
|
||||
|
||||
$1/cflags.txt: $1/force
|
||||
|
@ -347,7 +366,7 @@ $(MASTER_OUTPUT)/ldflags.txt: $(MASTER_OUTPUT)/force
|
|||
|
||||
|
||||
# We have to use static rules for the .d files for some reason
|
||||
DEPS = $(patsubst %.o,%.d,$(OBJ))
|
||||
DEPS = $(patsubst %.o,%.d,$(patsubst %.a,%.o,$(OBJ)))
|
||||
# Keep the .d files
|
||||
.PRECIOUS: $(DEPS)
|
||||
# Empty rule to force recompilation if the .d file is missing
|
||||
|
@ -378,7 +397,7 @@ check-size:
|
|||
$(eval OVER_SIZE=$(shell expr $(CURRENT_SIZE) - $(MAX_SIZE)))
|
||||
if [ $(MAX_SIZE) -gt 0 ] && [ $(CURRENT_SIZE) -gt 0 ]; then \
|
||||
$(SILENT) || printf "$(MSG_CHECK_FILESIZE)" | $(AWK_CMD); \
|
||||
if [ $(CURRENT_SIZE) -gt $(MAX_SIZE) ]; then $(PRINT_WARNING_PLAIN); $(SILENT) || printf " * $(MSG_FILE_TOO_BIG)" ; else $(PRINT_OK); $(SILENT) || printf " * $(MSG_FILE_JUST_RIGHT)"; fi \
|
||||
if [ $(CURRENT_SIZE) -gt $(MAX_SIZE) ]; then printf "\n * $(MSG_FILE_TOO_BIG)"; $(PRINT_ERROR_PLAIN); else $(PRINT_OK); $(SILENT) || printf " * $(MSG_FILE_JUST_RIGHT)"; fi \
|
||||
fi
|
||||
else
|
||||
check-size:
|
||||
|
@ -392,7 +411,7 @@ $(shell mkdir -p $(BUILD_DIR) 2>/dev/null)
|
|||
$(eval $(foreach OUTPUT,$(OUTPUTS),$(shell mkdir -p $(OUTPUT) 2>/dev/null)))
|
||||
|
||||
# Include the dependency files.
|
||||
-include $(patsubst %.o,%.d,$(OBJ))
|
||||
-include $(patsubst %.o,%.d,$(patsubst %.a,%.o,$(OBJ)))
|
||||
|
||||
|
||||
# Listing of phony targets.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue