From a3cbc8a004f6ec5b0e1df326353a2a2fc8221129 Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Sun, 28 Feb 2021 15:50:15 +0000 Subject: Overhaul bootmagic logic to have single entrypoint (#8532) * Relocate bootmagic logic to have single entrypoint * Align init of layer state--- tmk_core/common.mk | 22 ------ tmk_core/common/bootmagic.c | 163 --------------------------------------- tmk_core/common/bootmagic.h | 102 ------------------------ tmk_core/common/bootmagic_lite.c | 49 ------------ tmk_core/common/keyboard.c | 10 --- tmk_core/common/magic.c | 39 ---------- tmk_core/common/magic.h | 3 - tmk_core/protocol.mk | 4 + 8 files changed, 4 insertions(+), 388 deletions(-) delete mode 100644 tmk_core/common/bootmagic.c delete mode 100644 tmk_core/common/bootmagic.h delete mode 100644 tmk_core/common/bootmagic_lite.c delete mode 100644 tmk_core/common/magic.c delete mode 100644 tmk_core/common/magic.h (limited to 'tmk_core') diff --git a/tmk_core/common.mk b/tmk_core/common.mk index 238b3c69fd..c2fc522cea 100644 --- a/tmk_core/common.mk +++ b/tmk_core/common.mk @@ -24,28 +24,6 @@ else include $(TMK_PATH)/$(COMMON_DIR)/lib_printf.mk endif -# Option modules -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_SRC += $(COMMON_DIR)/bootmagic_lite.c - - 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) diff --git a/tmk_core/common/bootmagic.c b/tmk_core/common/bootmagic.c deleted file mode 100644 index c1b3adf94d..0000000000 --- a/tmk_core/common/bootmagic.c +++ /dev/null @@ -1,163 +0,0 @@ -#include -#include -#include "wait.h" -#include "matrix.h" -#include "bootloader.h" -#include "debug.h" -#include "keymap.h" -#include "host.h" -#include "action_layer.h" -#include "eeconfig.h" -#include "bootmagic.h" - -keymap_config_t keymap_config; - -/** \brief Bootmagic - * - * FIXME: needs doc - */ -void bootmagic(void) { - /* check signature */ - if (!eeconfig_is_enabled()) { - eeconfig_init(); - } - - /* do scans in case of bounce */ - print("bootmagic scan: ... "); - uint8_t scan = 100; - while (scan--) { - matrix_scan(); - wait_ms(10); - } - print("done.\n"); - - /* bootmagic skip */ - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SKIP)) { - return; - } - - /* eeconfig clear */ - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_EEPROM_CLEAR)) { - eeconfig_init(); - } - - /* bootloader */ - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_BOOTLOADER)) { - bootloader_jump(); - } - - /* debug enable */ - debug_config.raw = eeconfig_read_debug(); - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_ENABLE)) { - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_MATRIX)) { - debug_config.matrix = !debug_config.matrix; - } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_KEYBOARD)) { - debug_config.keyboard = !debug_config.keyboard; - } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_MOUSE)) { - debug_config.mouse = !debug_config.mouse; - } else { - debug_config.enable = !debug_config.enable; - } - } - eeconfig_update_debug(debug_config.raw); - - /* keymap config */ - keymap_config.raw = eeconfig_read_keymap(); - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_CONTROL_CAPSLOCK)) { - keymap_config.swap_control_capslock = !keymap_config.swap_control_capslock; - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_CAPSLOCK_TO_CONTROL)) { - keymap_config.capslock_to_control = !keymap_config.capslock_to_control; - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_LALT_LGUI)) { - keymap_config.swap_lalt_lgui = !keymap_config.swap_lalt_lgui; - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_RALT_RGUI)) { - keymap_config.swap_ralt_rgui = !keymap_config.swap_ralt_rgui; - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_NO_GUI)) { - keymap_config.no_gui = !keymap_config.no_gui; - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_GRAVE_ESC)) { - keymap_config.swap_grave_esc = !keymap_config.swap_grave_esc; - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_BACKSLASH_BACKSPACE)) { - keymap_config.swap_backslash_backspace = !keymap_config.swap_backslash_backspace; - } - if (bootmagic_scan_keycode(BOOTMAGIC_HOST_NKRO)) { - keymap_config.nkro = !keymap_config.nkro; - } - eeconfig_update_keymap(keymap_config.raw); - - /* default layer */ - uint8_t default_layer = 0; - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_0)) { - default_layer |= (1 << 0); - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_1)) { - default_layer |= (1 << 1); - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_2)) { - default_layer |= (1 << 2); - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_3)) { - default_layer |= (1 << 3); - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_4)) { - default_layer |= (1 << 4); - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_5)) { - default_layer |= (1 << 5); - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_6)) { - default_layer |= (1 << 6); - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_7)) { - default_layer |= (1 << 7); - } - if (default_layer) { - eeconfig_update_default_layer(default_layer); - default_layer_set((layer_state_t)default_layer); - } else { - default_layer = eeconfig_read_default_layer(); - default_layer_set((layer_state_t)default_layer); - } - /* Also initialize layer state to trigger callback functions for layer_state */ - layer_state_set_kb((layer_state_t)layer_state); - - /* EE_HANDS handedness */ - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_EE_HANDS_LEFT)) { - eeconfig_update_handedness(true); - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_EE_HANDS_RIGHT)) { - eeconfig_update_handedness(false); - } -} - -/** \brief Scan Keycode - * - * FIXME: needs doc - */ -static bool scan_keycode(uint8_t keycode) { - for (uint8_t r = 0; r < MATRIX_ROWS; r++) { - matrix_row_t matrix_row = matrix_get_row(r); - for (uint8_t c = 0; c < MATRIX_COLS; c++) { - if (matrix_row & ((matrix_row_t)1 << c)) { - if (keycode == keymap_key_to_keycode(0, (keypos_t){.row = r, .col = c})) { - return true; - } - } - } - } - return false; -} - -/** \brief Bootmagic Scan Keycode - * - * FIXME: needs doc - */ -bool bootmagic_scan_keycode(uint8_t keycode) { - if (!scan_keycode(BOOTMAGIC_KEY_SALT)) return false; - - return scan_keycode(keycode); -} diff --git a/tmk_core/common/bootmagic.h b/tmk_core/common/bootmagic.h deleted file mode 100644 index 8209d0194f..0000000000 --- a/tmk_core/common/bootmagic.h +++ /dev/null @@ -1,102 +0,0 @@ -#pragma once - -/* FIXME: Add special doxygen comments for defines here. */ - -/* bootmagic salt key */ -#ifndef BOOTMAGIC_KEY_SALT -# define BOOTMAGIC_KEY_SALT KC_SPACE -#endif - -/* skip bootmagic and eeconfig */ -#ifndef BOOTMAGIC_KEY_SKIP -# define BOOTMAGIC_KEY_SKIP KC_ESC -#endif - -/* eeprom clear */ -#ifndef BOOTMAGIC_KEY_EEPROM_CLEAR -# define BOOTMAGIC_KEY_EEPROM_CLEAR KC_BSPACE -#endif - -/* kick up bootloader */ -#ifndef BOOTMAGIC_KEY_BOOTLOADER -# define BOOTMAGIC_KEY_BOOTLOADER KC_B -#endif - -/* debug enable */ -#ifndef BOOTMAGIC_KEY_DEBUG_ENABLE -# define BOOTMAGIC_KEY_DEBUG_ENABLE KC_D -#endif -#ifndef BOOTMAGIC_KEY_DEBUG_MATRIX -# define BOOTMAGIC_KEY_DEBUG_MATRIX KC_X -#endif -#ifndef BOOTMAGIC_KEY_DEBUG_KEYBOARD -# define BOOTMAGIC_KEY_DEBUG_KEYBOARD KC_K -#endif -#ifndef BOOTMAGIC_KEY_DEBUG_MOUSE -# define BOOTMAGIC_KEY_DEBUG_MOUSE KC_M -#endif -#ifndef BOOTMAGIC_KEY_EE_HANDS_LEFT -# define BOOTMAGIC_KEY_EE_HANDS_LEFT KC_L -#endif -#ifndef BOOTMAGIC_KEY_EE_HANDS_RIGHT -# define BOOTMAGIC_KEY_EE_HANDS_RIGHT KC_R -#endif - -/* - * keymap config - */ -#ifndef BOOTMAGIC_KEY_SWAP_CONTROL_CAPSLOCK -# define BOOTMAGIC_KEY_SWAP_CONTROL_CAPSLOCK KC_LCTRL -#endif -#ifndef BOOTMAGIC_KEY_CAPSLOCK_TO_CONTROL -# define BOOTMAGIC_KEY_CAPSLOCK_TO_CONTROL KC_CAPSLOCK -#endif -#ifndef BOOTMAGIC_KEY_SWAP_LALT_LGUI -# define BOOTMAGIC_KEY_SWAP_LALT_LGUI KC_LALT -#endif -#ifndef BOOTMAGIC_KEY_SWAP_RALT_RGUI -# define BOOTMAGIC_KEY_SWAP_RALT_RGUI KC_RALT -#endif -#ifndef BOOTMAGIC_KEY_NO_GUI -# define BOOTMAGIC_KEY_NO_GUI KC_LGUI -#endif -#ifndef BOOTMAGIC_KEY_SWAP_GRAVE_ESC -# define BOOTMAGIC_KEY_SWAP_GRAVE_ESC KC_GRAVE -#endif -#ifndef BOOTMAGIC_KEY_SWAP_BACKSLASH_BACKSPACE -# define BOOTMAGIC_KEY_SWAP_BACKSLASH_BACKSPACE KC_BSLASH -#endif -#ifndef BOOTMAGIC_HOST_NKRO -# define BOOTMAGIC_HOST_NKRO KC_N -#endif - -/* - * change default layer - */ -#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_0 -# define BOOTMAGIC_KEY_DEFAULT_LAYER_0 KC_0 -#endif -#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_1 -# define BOOTMAGIC_KEY_DEFAULT_LAYER_1 KC_1 -#endif -#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_2 -# define BOOTMAGIC_KEY_DEFAULT_LAYER_2 KC_2 -#endif -#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_3 -# define BOOTMAGIC_KEY_DEFAULT_LAYER_3 KC_3 -#endif -#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_4 -# define BOOTMAGIC_KEY_DEFAULT_LAYER_4 KC_4 -#endif -#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_5 -# define BOOTMAGIC_KEY_DEFAULT_LAYER_5 KC_5 -#endif -#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_6 -# define BOOTMAGIC_KEY_DEFAULT_LAYER_6 KC_6 -#endif -#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_7 -# define BOOTMAGIC_KEY_DEFAULT_LAYER_7 KC_7 -#endif - -void bootmagic(void); -bool bootmagic_scan_keycode(uint8_t keycode); diff --git a/tmk_core/common/bootmagic_lite.c b/tmk_core/common/bootmagic_lite.c deleted file mode 100644 index cbf756a175..0000000000 --- a/tmk_core/common/bootmagic_lite.c +++ /dev/null @@ -1,49 +0,0 @@ -#include "quantum.h" - -/** \brief Reset eeprom - * - * ...just incase someone wants to only change the eeprom behaviour - */ -__attribute__((weak)) void bootmagic_lite_reset_eeprom(void) { -#if defined(VIA_ENABLE) - via_eeprom_reset(); -#else - eeconfig_disable(); -#endif -} - -/** \brief The lite version of TMK's bootmagic based on Wilba. - * - * 100% less potential for accidentally making the keyboard do stupid things. - */ -__attribute__((weak)) void bootmagic_lite(void) { - // We need multiple scans because debouncing can't be turned off. - matrix_scan(); -#if defined(DEBOUNCE) && DEBOUNCE > 0 - wait_ms(DEBOUNCE * 2); -#else - wait_ms(30); -#endif - matrix_scan(); - - // If the configured key (commonly Esc) is held down on power up, - // reset the EEPROM valid state and jump to bootloader. - // This isn't very generalized, but we need something that doesn't - // rely on user's keymaps in firmware or EEPROM. - uint8_t row = BOOTMAGIC_LITE_ROW; - uint8_t col = BOOTMAGIC_LITE_COLUMN; - -#if defined(SPLIT_KEYBOARD) && defined(BOOTMAGIC_LITE_ROW_RIGHT) && defined(BOOTMAGIC_LITE_COLUMN_RIGHT) - if (!is_keyboard_left()) { - row = BOOTMAGIC_LITE_ROW_RIGHT; - col = BOOTMAGIC_LITE_COLUMN_RIGHT; - } -#endif - - if (matrix_get_row(row) & (1 << col)) { - bootmagic_lite_reset_eeprom(); - - // Jump to bootloader. - bootloader_jump(); - } -} diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c index ce3255c069..65d9e00c7a 100644 --- a/tmk_core/common/keyboard.c +++ b/tmk_core/common/keyboard.c @@ -34,11 +34,6 @@ along with this program. If not, see . #ifdef BACKLIGHT_ENABLE # include "backlight.h" #endif -#ifdef BOOTMAGIC_ENABLE -# include "bootmagic.h" -#else -# include "magic.h" -#endif #ifdef MOUSEKEY_ENABLE # include "mousekey.h" #endif @@ -296,11 +291,6 @@ void keyboard_init(void) { #ifdef ADB_MOUSE_ENABLE adb_mouse_init(); #endif -#ifdef BOOTMAGIC_ENABLE - bootmagic(); -#else - magic(); -#endif #ifdef BACKLIGHT_ENABLE backlight_init(); #endif diff --git a/tmk_core/common/magic.c b/tmk_core/common/magic.c deleted file mode 100644 index e14994164e..0000000000 --- a/tmk_core/common/magic.c +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include -#if defined(__AVR__) -# include -#endif -#include "matrix.h" -#include "bootloader.h" -#include "debug.h" -#include "keymap.h" -#include "host.h" -#include "action_layer.h" -#include "eeconfig.h" -#include "magic.h" - -keymap_config_t keymap_config; - -/** \brief Magic - * - * FIXME: Needs doc - */ -void magic(void) { - /* check signature */ - if (!eeconfig_is_enabled()) { - eeconfig_init(); - } - - /* debug enable */ - debug_config.raw = eeconfig_read_debug(); - - /* keymap config */ - keymap_config.raw = eeconfig_read_keymap(); - - uint8_t default_layer = 0; - default_layer = eeconfig_read_default_layer(); - default_layer_set((layer_state_t)default_layer); - - /* Also initialize layer state to trigger callback functions for layer_state */ - layer_state_set_kb((layer_state_t)layer_state); -} diff --git a/tmk_core/common/magic.h b/tmk_core/common/magic.h deleted file mode 100644 index a6552c04dc..0000000000 --- a/tmk_core/common/magic.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -void magic(void); diff --git a/tmk_core/protocol.mk b/tmk_core/protocol.mk index 0c41642b9b..cc87e83478 100644 --- a/tmk_core/protocol.mk +++ b/tmk_core/protocol.mk @@ -54,5 +54,9 @@ ifeq ($(strip $(XT_ENABLE)), yes) OPT_DEFS += -DXT_ENABLE endif +ifeq ($(strip $(USB_HID_ENABLE)), yes) + include $(TMK_DIR)/protocol/usb_hid.mk +endif + # Search Path VPATH += $(TMK_DIR)/protocol -- cgit v1.2.3 From 415a8bc249d5c366487f69b3547198d17044a5de Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Sun, 28 Feb 2021 15:52:43 +0000 Subject: ARM - Refactor SLEEP_LED to support more platforms (#8403) * Initial refactor of ARM SLEEP_LED to enable more platforms * fix build issues * Disable SLEEP_LED for boards with no caps lock code * Enable GPT14 for boards with caps lock code and SLEEP_LED enabled * Enable GPT for boards with caps lock code and SLEEP_LED enabled--- keyboards/aeboards/ext65/rev2/config.h | 2 + keyboards/aeboards/ext65/rev2/halconf.h | 2 + keyboards/aeboards/ext65/rev2/mcuconf.h | 2 + keyboards/cannonkeys/an_c/rules.mk | 2 +- keyboards/cannonkeys/chimera65/rules.mk | 2 +- keyboards/cannonkeys/instant60/rules.mk | 2 +- keyboards/cannonkeys/iron165/rules.mk | 2 +- keyboards/cannonkeys/satisfaction75/rules.mk | 2 +- keyboards/cannonkeys/savage65/rules.mk | 2 +- keyboards/cannonkeys/tmov2/rules.mk | 2 +- keyboards/cannonkeys/tsukuyomi/rules.mk | 2 +- keyboards/daji/seis_cinco/rules.mk | 2 +- keyboards/handwired/ck4x4/rules.mk | 2 +- keyboards/handwired/onekey/rules.mk | 4 +- keyboards/projectkb/alice/config.h | 3 + keyboards/projectkb/alice/halconf.h | 2 + keyboards/projectkb/alice/mcuconf.h | 2 + keyboards/projectkb/signature87/rules.mk | 2 +- keyboards/ramonimbao/wete/config.h | 2 + keyboards/ramonimbao/wete/halconf.h | 2 + keyboards/ramonimbao/wete/mcuconf.h | 2 + keyboards/westfoxtrot/prophet/config.h | 2 + keyboards/westfoxtrot/prophet/halconf.h | 27 +++++++++ keyboards/westfoxtrot/prophet/mcuconf.h | 5 +- tmk_core/common/chibios/sleep_led.c | 88 +++++++++++----------------- 25 files changed, 96 insertions(+), 71 deletions(-) create mode 100644 keyboards/projectkb/alice/config.h create mode 100644 keyboards/westfoxtrot/prophet/halconf.h (limited to 'tmk_core') diff --git a/keyboards/aeboards/ext65/rev2/config.h b/keyboards/aeboards/ext65/rev2/config.h index 541f07ee98..dc1bfb71c2 100644 --- a/keyboards/aeboards/ext65/rev2/config.h +++ b/keyboards/aeboards/ext65/rev2/config.h @@ -74,3 +74,5 @@ along with this program. If not, see . #define BACKLIGHT_LEVELS 6 #define BACKLIGHT_BREATHING #define BREATHING_PERIOD 6 + +#define SLEEP_LED_GPT_DRIVER GPTD1 diff --git a/keyboards/aeboards/ext65/rev2/halconf.h b/keyboards/aeboards/ext65/rev2/halconf.h index 6e2f536400..9fa1eca60b 100644 --- a/keyboards/aeboards/ext65/rev2/halconf.h +++ b/keyboards/aeboards/ext65/rev2/halconf.h @@ -27,5 +27,7 @@ #define HAL_USE_SPI TRUE +#define HAL_USE_GPT TRUE + #include_next diff --git a/keyboards/aeboards/ext65/rev2/mcuconf.h b/keyboards/aeboards/ext65/rev2/mcuconf.h index 26ce806150..43d53d4f2d 100644 --- a/keyboards/aeboards/ext65/rev2/mcuconf.h +++ b/keyboards/aeboards/ext65/rev2/mcuconf.h @@ -32,3 +32,5 @@ #undef STM32_SPI_USE_SPI2 #define STM32_SPI_USE_SPI2 TRUE +#undef STM32_GPT_USE_TIM1 +#define STM32_GPT_USE_TIM1 TRUE diff --git a/keyboards/cannonkeys/an_c/rules.mk b/keyboards/cannonkeys/an_c/rules.mk index 8ed2d0ead7..7309744d1e 100644 --- a/keyboards/cannonkeys/an_c/rules.mk +++ b/keyboards/cannonkeys/an_c/rules.mk @@ -11,7 +11,7 @@ MOUSEKEY_ENABLE = yes # Mouse keys EXTRAKEY_ENABLE = yes # Audio control and System control CONSOLE_ENABLE = yes # Console for debug COMMAND_ENABLE = yes # Commands for debug and configuration -SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend +SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend NKRO_ENABLE = yes # USB Nkey Rollover CUSTOM_MATRIX = no # Custom matrix file BACKLIGHT_ENABLE = yes diff --git a/keyboards/cannonkeys/chimera65/rules.mk b/keyboards/cannonkeys/chimera65/rules.mk index 4d940da78d..a08f2fa49d 100644 --- a/keyboards/cannonkeys/chimera65/rules.mk +++ b/keyboards/cannonkeys/chimera65/rules.mk @@ -11,7 +11,7 @@ MOUSEKEY_ENABLE = yes # Mouse keys EXTRAKEY_ENABLE = yes # Audio control and System control CONSOLE_ENABLE = yes # Console for debug COMMAND_ENABLE = yes # Commands for debug and configuration -SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend +SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend NKRO_ENABLE = yes # USB Nkey Rollover CUSTOM_MATRIX = no # Custom matrix file BACKLIGHT_ENABLE = yes diff --git a/keyboards/cannonkeys/instant60/rules.mk b/keyboards/cannonkeys/instant60/rules.mk index 0973ad9547..e5ba2903b6 100644 --- a/keyboards/cannonkeys/instant60/rules.mk +++ b/keyboards/cannonkeys/instant60/rules.mk @@ -10,7 +10,7 @@ MOUSEKEY_ENABLE = yes # Mouse keys EXTRAKEY_ENABLE = yes # Audio control and System control CONSOLE_ENABLE = yes # Console for debug COMMAND_ENABLE = yes # Commands for debug and configuration -SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend +SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend NKRO_ENABLE = yes # USB Nkey Rollover CUSTOM_MATRIX = no # Custom matrix file BACKLIGHT_ENABLE = yes diff --git a/keyboards/cannonkeys/iron165/rules.mk b/keyboards/cannonkeys/iron165/rules.mk index 3925458dda..9de75a6149 100644 --- a/keyboards/cannonkeys/iron165/rules.mk +++ b/keyboards/cannonkeys/iron165/rules.mk @@ -9,7 +9,7 @@ MOUSEKEY_ENABLE = yes # Mouse keys EXTRAKEY_ENABLE = yes # Audio control and System control CONSOLE_ENABLE = yes # Console for debug COMMAND_ENABLE = yes # Commands for debug and configuration -SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend +SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend NKRO_ENABLE = yes # USB Nkey Rollover CUSTOM_MATRIX = no # Custom matrix file BACKLIGHT_ENABLE = yes diff --git a/keyboards/cannonkeys/satisfaction75/rules.mk b/keyboards/cannonkeys/satisfaction75/rules.mk index e3abea5463..3861b4849f 100644 --- a/keyboards/cannonkeys/satisfaction75/rules.mk +++ b/keyboards/cannonkeys/satisfaction75/rules.mk @@ -15,7 +15,7 @@ MOUSEKEY_ENABLE = yes # Mouse keys EXTRAKEY_ENABLE = yes # Audio control and System control CONSOLE_ENABLE = yes # Console for debug COMMAND_ENABLE = yes # Commands for debug and configuration -SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend +SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend NKRO_ENABLE = yes # USB Nkey Rollover CUSTOM_MATRIX = no # Custom matrix file ENCODER_ENABLE = yes diff --git a/keyboards/cannonkeys/savage65/rules.mk b/keyboards/cannonkeys/savage65/rules.mk index 8e1b984fd4..2454573d2f 100644 --- a/keyboards/cannonkeys/savage65/rules.mk +++ b/keyboards/cannonkeys/savage65/rules.mk @@ -11,7 +11,7 @@ MOUSEKEY_ENABLE = yes # Mouse keys EXTRAKEY_ENABLE = yes # Audio control and System control CONSOLE_ENABLE = yes # Console for debug COMMAND_ENABLE = yes # Commands for debug and configuration -SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend +SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend NKRO_ENABLE = yes # USB Nkey Rollover CUSTOM_MATRIX = no # Custom matrix file BACKLIGHT_ENABLE = yes diff --git a/keyboards/cannonkeys/tmov2/rules.mk b/keyboards/cannonkeys/tmov2/rules.mk index 9b29e8fd17..294c873eec 100644 --- a/keyboards/cannonkeys/tmov2/rules.mk +++ b/keyboards/cannonkeys/tmov2/rules.mk @@ -11,7 +11,7 @@ MOUSEKEY_ENABLE = yes # Mouse keys EXTRAKEY_ENABLE = yes # Audio control and System control CONSOLE_ENABLE = yes # Console for debug COMMAND_ENABLE = yes # Commands for debug and configuration -SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend +SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend NKRO_ENABLE = yes # USB Nkey Rollover CUSTOM_MATRIX = no # Custom matrix file BACKLIGHT_ENABLE = yes diff --git a/keyboards/cannonkeys/tsukuyomi/rules.mk b/keyboards/cannonkeys/tsukuyomi/rules.mk index ce881f1986..4e7791a79f 100644 --- a/keyboards/cannonkeys/tsukuyomi/rules.mk +++ b/keyboards/cannonkeys/tsukuyomi/rules.mk @@ -10,7 +10,7 @@ EXTRAKEY_ENABLE = yes # Audio control and System control CONSOLE_ENABLE = yes # Console for debug COMMAND_ENABLE = yes # Commands for debug and configuration # Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE -SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend +SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend # if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work NKRO_ENABLE = yes # USB Nkey Rollover BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality diff --git a/keyboards/daji/seis_cinco/rules.mk b/keyboards/daji/seis_cinco/rules.mk index fa34092cd7..768e50069c 100644 --- a/keyboards/daji/seis_cinco/rules.mk +++ b/keyboards/daji/seis_cinco/rules.mk @@ -11,7 +11,7 @@ EXTRAKEY_ENABLE = yes # Audio control and System control CONSOLE_ENABLE = no # Console for debug COMMAND_ENABLE = no # Commands for debug and configuration # Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE -SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend +SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend # if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work NKRO_ENABLE = yes # USB Nkey Rollover BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality diff --git a/keyboards/handwired/ck4x4/rules.mk b/keyboards/handwired/ck4x4/rules.mk index 0709f341bf..e5785270bd 100644 --- a/keyboards/handwired/ck4x4/rules.mk +++ b/keyboards/handwired/ck4x4/rules.mk @@ -10,7 +10,7 @@ MOUSEKEY_ENABLE = yes # Mouse keys EXTRAKEY_ENABLE = yes # Audio control and System control CONSOLE_ENABLE = yes # Console for debug COMMAND_ENABLE = yes # Commands for debug and configuration -SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend +SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend NKRO_ENABLE = yes # USB Nkey Rollover CUSTOM_MATRIX = no # Custom matrix file diff --git a/keyboards/handwired/onekey/rules.mk b/keyboards/handwired/onekey/rules.mk index 259050d553..df2ec1ecf4 100644 --- a/keyboards/handwired/onekey/rules.mk +++ b/keyboards/handwired/onekey/rules.mk @@ -7,9 +7,9 @@ EXTRAKEY_ENABLE = yes # Audio control and System control(+450) CONSOLE_ENABLE = yes # Console for debug(+400) COMMAND_ENABLE = no # Commands for debug and configuration # Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE -SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend +SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend # if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work -NKRO_ENABLE = yes # USB Nkey Rollover +NKRO_ENABLE = yes # USB Nkey Rollover BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality on B7 by default RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow MIDI_ENABLE = no # MIDI support (+2400 to 4200, depending on config) diff --git a/keyboards/projectkb/alice/config.h b/keyboards/projectkb/alice/config.h new file mode 100644 index 0000000000..95fb682e17 --- /dev/null +++ b/keyboards/projectkb/alice/config.h @@ -0,0 +1,3 @@ +#pragma once + +#define SLEEP_LED_GPT_DRIVER GPTD1 diff --git a/keyboards/projectkb/alice/halconf.h b/keyboards/projectkb/alice/halconf.h index b17808ffeb..0016e53ba8 100644 --- a/keyboards/projectkb/alice/halconf.h +++ b/keyboards/projectkb/alice/halconf.h @@ -27,5 +27,7 @@ #define HAL_USE_SPI TRUE +#define HAL_USE_GPT TRUE + #include_next diff --git a/keyboards/projectkb/alice/mcuconf.h b/keyboards/projectkb/alice/mcuconf.h index 4bfc7f9465..6e0f1a50d8 100644 --- a/keyboards/projectkb/alice/mcuconf.h +++ b/keyboards/projectkb/alice/mcuconf.h @@ -32,3 +32,5 @@ #undef STM32_SPI_USE_SPI2 #define STM32_SPI_USE_SPI2 TRUE +#undef STM32_GPT_USE_TIM1 +#define STM32_GPT_USE_TIM1 TRUE diff --git a/keyboards/projectkb/signature87/rules.mk b/keyboards/projectkb/signature87/rules.mk index fe0d976d11..caad4c83c2 100644 --- a/keyboards/projectkb/signature87/rules.mk +++ b/keyboards/projectkb/signature87/rules.mk @@ -9,7 +9,7 @@ MOUSEKEY_ENABLE = yes # Mouse keys EXTRAKEY_ENABLE = yes # Audio control and System control CONSOLE_ENABLE = yes # Console for debug COMMAND_ENABLE = yes # Commands for debug and configuration -SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend +SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend NKRO_ENABLE = yes # USB Nkey Rollover BACKLIGHT_ENABLE = no diff --git a/keyboards/ramonimbao/wete/config.h b/keyboards/ramonimbao/wete/config.h index 5d68a7efd7..3d89550090 100644 --- a/keyboards/ramonimbao/wete/config.h +++ b/keyboards/ramonimbao/wete/config.h @@ -46,6 +46,8 @@ along with this program. If not, see . #define RGBLED_NUM 24 #define RGBLIGHT_ANIMATIONS +#define SLEEP_LED_GPT_DRIVER GPTD1 + /* define if matrix has ghost */ //#define MATRIX_HAS_GHOST diff --git a/keyboards/ramonimbao/wete/halconf.h b/keyboards/ramonimbao/wete/halconf.h index c43440a459..b3de873be1 100644 --- a/keyboards/ramonimbao/wete/halconf.h +++ b/keyboards/ramonimbao/wete/halconf.h @@ -23,5 +23,7 @@ #define HAL_USE_PWM TRUE +#define HAL_USE_GPT TRUE + #include_next diff --git a/keyboards/ramonimbao/wete/mcuconf.h b/keyboards/ramonimbao/wete/mcuconf.h index b7f2c481c6..7a2e877763 100644 --- a/keyboards/ramonimbao/wete/mcuconf.h +++ b/keyboards/ramonimbao/wete/mcuconf.h @@ -35,3 +35,5 @@ #undef STM32_SPI_USE_SPI2 #define STM32_SPI_USE_SPI2 TRUE +#undef STM32_GPT_USE_TIM1 +#define STM32_GPT_USE_TIM1 TRUE diff --git a/keyboards/westfoxtrot/prophet/config.h b/keyboards/westfoxtrot/prophet/config.h index 4f447e4ca0..0f2ddc1dc1 100644 --- a/keyboards/westfoxtrot/prophet/config.h +++ b/keyboards/westfoxtrot/prophet/config.h @@ -30,3 +30,5 @@ #define LOCKING_SUPPORT_ENABLE /* Locking resynchronize hack */ #define LOCKING_RESYNC_ENABLE + +#define SLEEP_LED_GPT_DRIVER GPTD1 diff --git a/keyboards/westfoxtrot/prophet/halconf.h b/keyboards/westfoxtrot/prophet/halconf.h new file mode 100644 index 0000000000..cbfd1307f1 --- /dev/null +++ b/keyboards/westfoxtrot/prophet/halconf.h @@ -0,0 +1,27 @@ +/* Copyright 2020 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* + * This file was auto-generated by: + * `qmk chibios-confmigrate -i keyboards/projectkb/alice/halconf.h -r platforms/chibios/common/configs/halconf.h` + */ + +#pragma once + +#define HAL_USE_GPT TRUE + +#include_next + diff --git a/keyboards/westfoxtrot/prophet/mcuconf.h b/keyboards/westfoxtrot/prophet/mcuconf.h index 2665f9c9e4..550141af6b 100644 --- a/keyboards/westfoxtrot/prophet/mcuconf.h +++ b/keyboards/westfoxtrot/prophet/mcuconf.h @@ -23,6 +23,5 @@ #include_next -#undef STM32_PWM_USE_TIM3 -#define STM32_PWM_USE_TIM3 TRUE - +#undef STM32_GPT_USE_TIM1 +#define STM32_GPT_USE_TIM1 TRUE diff --git a/tmk_core/common/chibios/sleep_led.c b/tmk_core/common/chibios/sleep_led.c index 5595eec0e5..477056a454 100644 --- a/tmk_core/common/chibios/sleep_led.c +++ b/tmk_core/common/chibios/sleep_led.c @@ -9,21 +9,13 @@ * Use LP timer on Kinetises, TIM14 on STM32F0. */ -#if defined(KL2x) || defined(K20x) - -/* Use Low Power Timer (LPTMR) */ -# define TIMER_INTERRUPT_VECTOR KINETIS_LPTMR0_IRQ_VECTOR -# define RESET_COUNTER LPTMR0->CSR |= LPTMRx_CSR_TCF - -#elif defined(STM32F0XX) - -/* Use TIM14 manually */ -# define TIMER_INTERRUPT_VECTOR STM32_TIM14_HANDLER -# define RESET_COUNTER STM32_TIM14->SR &= ~STM32_TIM_SR_UIF - +#ifndef SLEEP_LED_GPT_DRIVER +# if defined(STM32F0XX) +# define SLEEP_LED_GPT_DRIVER GPTD14 +# endif #endif -#if defined(KL2x) || defined(K20x) || defined(STM32F0XX) /* common parts for timers/interrupts */ +#if defined(KL2x) || defined(K20x) || defined(SLEEP_LED_GPT_DRIVER) /* common parts for timers/interrupts */ /* Breathing Sleep LED brighness(PWM On period) table * (64[steps] * 4[duration]) / 64[PWM periods/s] = 4 second breath cycle @@ -33,10 +25,7 @@ */ static const uint8_t breathing_table[64] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 6, 10, 15, 23, 32, 44, 58, 74, 93, 113, 135, 157, 179, 199, 218, 233, 245, 252, 255, 252, 245, 233, 218, 199, 179, 157, 135, 113, 93, 74, 58, 44, 32, 23, 15, 10, 6, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -/* interrupt handler */ -OSAL_IRQ_HANDLER(TIMER_INTERRUPT_VECTOR) { - OSAL_IRQ_PROLOGUE(); - +void sleep_led_timer_callback(void) { /* Software PWM * timer:1111 1111 1111 1111 * \_____/\/ \_______/____ count(0-255) @@ -64,17 +53,16 @@ OSAL_IRQ_HANDLER(TIMER_INTERRUPT_VECTOR) { if (timer.pwm.count == breathing_table[timer.pwm.index]) { led_set(0); } - - /* Reset the counter */ - RESET_COUNTER; - - OSAL_IRQ_EPILOGUE(); } #endif /* common parts for known platforms */ #if defined(KL2x) || defined(K20x) /* platform selection: familiar Kinetis chips */ +/* Use Low Power Timer (LPTMR) */ +# define TIMER_INTERRUPT_VECTOR KINETIS_LPTMR0_IRQ_VECTOR +# define RESET_COUNTER LPTMR0->CSR |= LPTMRx_CSR_TCF + /* LPTMR clock options */ # define LPTMR_CLOCK_MCGIRCLK 0 /* 4MHz clock */ # define LPTMR_CLOCK_LPO 1 /* 1kHz clock */ @@ -86,6 +74,18 @@ OSAL_IRQ_HANDLER(TIMER_INTERRUPT_VECTOR) { # define SIM_SCGC5_LPTMR SIM_SCGC5_LPTIMER # endif +/* interrupt handler */ +OSAL_IRQ_HANDLER(TIMER_INTERRUPT_VECTOR) { + OSAL_IRQ_PROLOGUE(); + + sleep_led_timer_callback(); + + /* Reset the counter */ + RESET_COUNTER; + + OSAL_IRQ_EPILOGUE(); +} + /* Initialise the timer */ void sleep_led_init(void) { /* Make sure the clock to the LPTMR is enabled */ @@ -159,45 +159,23 @@ void sleep_led_toggle(void) { LPTMR0->CSR ^= LPTMRx_CSR_TEN; } -#elif defined(STM32F0XX) /* platform selection: STM32F0XX */ - -/* Initialise the timer */ -void sleep_led_init(void) { - /* enable clock */ - rccEnableTIM14(FALSE); /* low power enable = FALSE */ - rccResetTIM14(); - - /* prescale */ - /* Assuming 48MHz internal clock */ - /* getting cca 65484 irqs/sec */ - STM32_TIM14->PSC = 733; +#elif defined(SLEEP_LED_GPT_DRIVER) - /* auto-reload */ - /* 0 => interrupt every time */ - STM32_TIM14->ARR = 3; +static void gptTimerCallback(GPTDriver *gptp) { + (void)gptp; + sleep_led_timer_callback(); +} - /* enable counter update event interrupt */ - STM32_TIM14->DIER |= STM32_TIM_DIER_UIE; +static const GPTConfig gptcfg = {1000000, gptTimerCallback, 0, 0}; - /* register interrupt vector */ - nvicEnableVector(STM32_TIM14_NUMBER, 2); /* vector, priority */ -} +/* Initialise the timer */ +void sleep_led_init(void) { gptStart(&SLEEP_LED_GPT_DRIVER, &gptcfg); } -void sleep_led_enable(void) { - /* Enable the timer */ - STM32_TIM14->CR1 = STM32_TIM_CR1_CEN | STM32_TIM_CR1_URS; - /* URS => update event only on overflow; setting UG bit disabled */ -} +void sleep_led_enable(void) { gptStartContinuous(&SLEEP_LED_GPT_DRIVER, gptcfg.frequency / 0xFFFF); } -void sleep_led_disable(void) { - /* Disable the timer */ - STM32_TIM14->CR1 = 0; -} +void sleep_led_disable(void) { gptStopTimer(&SLEEP_LED_GPT_DRIVER); } -void sleep_led_toggle(void) { - /* Toggle the timer */ - STM32_TIM14->CR1 ^= STM32_TIM_CR1_CEN; -} +void sleep_led_toggle(void) { (SLEEP_LED_GPT_DRIVER.state == GPT_READY) ? sleep_led_enable() : sleep_led_disable(); } #else /* platform selection: not on familiar chips */ -- cgit v1.2.3 From 5ba4391cf29ce624f17593417212b3dbca1609ad Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Sun, 28 Feb 2021 15:52:58 +0000 Subject: Refactor of USB code within split_common (#11890) * Initial refactor of usb code within split_common * Add headers * Correct disable condition * Format * Align func name--- quantum/split_common/split_util.c | 70 +++++++++++--------------------- tmk_core/common.mk | 1 + tmk_core/common/chibios/chibios_config.h | 2 + tmk_core/common/usb_util.c | 29 +++++++++++++ tmk_core/common/usb_util.h | 22 ++++++++++ tmk_core/protocol/chibios.mk | 1 + tmk_core/protocol/chibios/usb_util.c | 21 ++++++++++ tmk_core/protocol/lufa.mk | 1 + tmk_core/protocol/lufa/usb_util.c | 34 ++++++++++++++++ tmk_core/protocol/vusb.mk | 1 + tmk_core/protocol/vusb/usb_util.c | 24 +++++++++++ 11 files changed, 160 insertions(+), 46 deletions(-) create mode 100644 tmk_core/common/usb_util.c create mode 100644 tmk_core/common/usb_util.h create mode 100644 tmk_core/protocol/chibios/usb_util.c create mode 100644 tmk_core/protocol/lufa/usb_util.c create mode 100644 tmk_core/protocol/vusb/usb_util.c (limited to 'tmk_core') diff --git a/quantum/split_common/split_util.c b/quantum/split_common/split_util.c index 2ae44e6e15..9e75e19ce0 100644 --- a/quantum/split_common/split_util.c +++ b/quantum/split_common/split_util.c @@ -1,3 +1,18 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ #include "split_util.h" #include "matrix.h" #include "keyboard.h" @@ -6,14 +21,7 @@ #include "transport.h" #include "quantum.h" #include "wait.h" - -#ifdef PROTOCOL_LUFA -# include -#endif - -#ifdef PROTOCOL_VUSB -# include -#endif +#include "usb_util.h" #ifdef EE_HANDS # include "eeconfig.h" @@ -31,56 +39,21 @@ # define SPLIT_USB_TIMEOUT_POLL 10 #endif -#ifdef PROTOCOL_CHIBIOS -# define SPLIT_USB_DETECT // Force this on for now -#endif - volatile bool isLeftHand = true; #if defined(SPLIT_USB_DETECT) -# if defined(PROTOCOL_LUFA) -static inline bool usbHasActiveConnection(void) { return USB_Device_IsAddressSet(); } -static inline void usbDisable(void) { - USB_Disable(); - USB_DeviceState = DEVICE_STATE_Unattached; -} -# elif defined(PROTOCOL_CHIBIOS) -static inline bool usbHasActiveConnection(void) { return usbGetDriverStateI(&USBD1) == USB_ACTIVE; } -static inline void usbDisable(void) { usbStop(&USBD1); } -# elif defined(PROTOCOL_VUSB) -static inline bool usbHasActiveConnection(void) { - usbPoll(); - return usbConfiguration; -} -static inline void usbDisable(void) { usbDeviceDisconnect(); } -# else -static inline bool usbHasActiveConnection(void) { return true; } -static inline void usbDisable(void) {} -# endif - -bool usbIsActive(void) { +static bool usbIsActive(void) { for (uint8_t i = 0; i < (SPLIT_USB_TIMEOUT / SPLIT_USB_TIMEOUT_POLL); i++) { // This will return true if a USB connection has been established - if (usbHasActiveConnection()) { + if (usb_connected_state()) { return true; } wait_ms(SPLIT_USB_TIMEOUT_POLL); } - - // Avoid NO_USB_STARTUP_CHECK - Disable USB as the previous checks seem to enable it somehow - usbDisable(); - return false; } -#elif defined(PROTOCOL_LUFA) && defined(OTGPADE) -static inline bool usbIsActive(void) { - USB_OTGPAD_On(); // enables VBUS pad - wait_us(5); - - return USB_VBUS_GetStatus(); // checks state of VBUS -} #else -static inline bool usbIsActive(void) { return true; } +static inline bool usbIsActive(void) { return usb_vbus_state(); } #endif #ifdef SPLIT_HAND_MATRIX_GRID @@ -126,6 +99,11 @@ __attribute__((weak)) bool is_keyboard_master(void) { // only check once, as this is called often if (usbstate == UNKNOWN) { usbstate = usbIsActive() ? MASTER : SLAVE; + + // Avoid NO_USB_STARTUP_CHECK - Disable USB as the previous checks seem to enable it somehow + if (usbstate == SLAVE) { + usb_disable(); + } } return (usbstate == MASTER); diff --git a/tmk_core/common.mk b/tmk_core/common.mk index c2fc522cea..2f8f81126a 100644 --- a/tmk_core/common.mk +++ b/tmk_core/common.mk @@ -12,6 +12,7 @@ TMK_COMMON_SRC += $(COMMON_DIR)/host.c \ $(COMMON_DIR)/sendchar_null.c \ $(COMMON_DIR)/eeconfig.c \ $(COMMON_DIR)/report.c \ + $(COMMON_DIR)/usb_util.c \ $(PLATFORM_COMMON_DIR)/suspend.c \ $(PLATFORM_COMMON_DIR)/timer.c \ $(COMMON_DIR)/sync_timer.c \ diff --git a/tmk_core/common/chibios/chibios_config.h b/tmk_core/common/chibios/chibios_config.h index b4d96465d1..bebf026de7 100644 --- a/tmk_core/common/chibios/chibios_config.h +++ b/tmk_core/common/chibios/chibios_config.h @@ -15,6 +15,8 @@ */ #pragma once +#define SPLIT_USB_DETECT // Force this on for now + #if defined(STM32F1XX) # define USE_GPIOV1 #endif diff --git a/tmk_core/common/usb_util.c b/tmk_core/common/usb_util.c new file mode 100644 index 0000000000..e4c50fcb10 --- /dev/null +++ b/tmk_core/common/usb_util.c @@ -0,0 +1,29 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "usb_util.h" +#include "wait.h" + +__attribute__((weak)) void usb_disable(void) {} +__attribute__((weak)) bool usb_connected_state(void) { return true; } +__attribute__((weak)) bool usb_vbus_state(void) { +#ifdef USB_VBUS_PIN + setPinInput(USB_VBUS_PIN); + wait_us(5); + return readPin(USB_VBUS_PIN); +#else + return true; +#endif +} diff --git a/tmk_core/common/usb_util.h b/tmk_core/common/usb_util.h new file mode 100644 index 0000000000..4ebedb1e71 --- /dev/null +++ b/tmk_core/common/usb_util.h @@ -0,0 +1,22 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#include + +void usb_disable(void); +bool usb_connected_state(void); +bool usb_vbus_state(void); diff --git a/tmk_core/protocol/chibios.mk b/tmk_core/protocol/chibios.mk index 80554abb32..d01697835b 100644 --- a/tmk_core/protocol/chibios.mk +++ b/tmk_core/protocol/chibios.mk @@ -6,6 +6,7 @@ SRC += $(CHIBIOS_DIR)/usb_main.c SRC += $(CHIBIOS_DIR)/main.c SRC += usb_descriptor.c SRC += $(CHIBIOS_DIR)/usb_driver.c +SRC += $(CHIBIOS_DIR)/usb_util.c SRC += $(LIBSRC) VPATH += $(TMK_PATH)/$(PROTOCOL_DIR) diff --git a/tmk_core/protocol/chibios/usb_util.c b/tmk_core/protocol/chibios/usb_util.c new file mode 100644 index 0000000000..5945e8a8de --- /dev/null +++ b/tmk_core/protocol/chibios/usb_util.c @@ -0,0 +1,21 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include "usb_util.h" + +void usb_disable(void) { usbStop(&USBD1); } + +bool usb_connected_state(void) { return usbGetDriverStateI(&USBD1) == USB_ACTIVE; } diff --git a/tmk_core/protocol/lufa.mk b/tmk_core/protocol/lufa.mk index 1cc1fa04e5..9d9fb728b1 100644 --- a/tmk_core/protocol/lufa.mk +++ b/tmk_core/protocol/lufa.mk @@ -44,6 +44,7 @@ ifeq ($(strip $(VIRTSER_ENABLE)), yes) endif SRC += $(LUFA_SRC) +SRC += $(LUFA_DIR)/usb_util.c # Search Path VPATH += $(TMK_PATH)/$(LUFA_DIR) diff --git a/tmk_core/protocol/lufa/usb_util.c b/tmk_core/protocol/lufa/usb_util.c new file mode 100644 index 0000000000..9e943a21b9 --- /dev/null +++ b/tmk_core/protocol/lufa/usb_util.c @@ -0,0 +1,34 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include "usb_util.h" +#include "wait.h" + +void usb_disable(void) { + USB_Disable(); + USB_DeviceState = DEVICE_STATE_Unattached; +} + +bool usb_connected_state(void) { return USB_Device_IsAddressSet(); } + +#if defined(OTGPADE) +bool usb_vbus_state(void) { + USB_OTGPAD_On(); // enables VBUS pad + wait_us(5); + + return USB_VBUS_GetStatus(); // checks state of VBUS +} +#endif diff --git a/tmk_core/protocol/vusb.mk b/tmk_core/protocol/vusb.mk index 1de6003089..e4d013b38d 100644 --- a/tmk_core/protocol/vusb.mk +++ b/tmk_core/protocol/vusb.mk @@ -5,6 +5,7 @@ VUSB_PATH = $(LIB_PATH)/vusb SRC += $(VUSB_DIR)/main.c \ $(VUSB_DIR)/vusb.c \ + $(VUSB_DIR)/usb_util.c \ $(VUSB_PATH)/usbdrv/usbdrv.c \ $(VUSB_PATH)/usbdrv/usbdrvasm.S \ $(VUSB_PATH)/usbdrv/oddebug.c diff --git a/tmk_core/protocol/vusb/usb_util.c b/tmk_core/protocol/vusb/usb_util.c new file mode 100644 index 0000000000..602854dbe6 --- /dev/null +++ b/tmk_core/protocol/vusb/usb_util.c @@ -0,0 +1,24 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include "usb_util.h" + +void usb_disable(void) { usbDeviceDisconnect(); } + +bool usb_connected_state(void) { + usbPoll(); + return usbConfiguration; +} -- cgit v1.2.3 From 0e984b6e7e216a62df0b5d53f6a8f0d4bc13dca3 Mon Sep 17 00:00:00 2001 From: Drashna Jaelre Date: Mon, 1 Mar 2021 08:57:02 -0800 Subject: Add ability to toggle One Shot functionality (#4198) Co-authored-by: Nick Brassel Co-authored-by: Ryan --- docs/keycodes.md | 3 +++ docs/one_shot_keys.md | 3 +++ quantum/keycode_config.h | 1 + quantum/quantum.c | 11 ++++++++ quantum/quantum_keycodes.h | 9 +++++++ tmk_core/common/action_util.c | 58 ++++++++++++++++++++++++++++++++++++------- tmk_core/common/action_util.h | 5 ++++ 7 files changed, 81 insertions(+), 9 deletions(-) (limited to 'tmk_core') diff --git a/docs/keycodes.md b/docs/keycodes.md index 9acf8b6839..f3c519b130 100644 --- a/docs/keycodes.md +++ b/docs/keycodes.md @@ -516,6 +516,9 @@ See also: [One Shot Keys](one_shot_keys.md) |------------|----------------------------------| |`OSM(mod)` |Hold `mod` for one keypress | |`OSL(layer)`|Switch to `layer` for one keypress| +|`OS_ON` |Turns One Shot keys on | +|`OS_OFF` |Turns One Shot keys off | +|`OS_TOGG` |Toggles One Shot keys status | ## Space Cadet :id=space-cadet diff --git a/docs/one_shot_keys.md b/docs/one_shot_keys.md index 9a082d7d6d..9fc5486299 100644 --- a/docs/one_shot_keys.md +++ b/docs/one_shot_keys.md @@ -17,6 +17,9 @@ You can control the behavior of one shot keys by defining these in `config.h`: * `OSM(mod)` - Momentarily hold down *mod*. You must use the `MOD_*` keycodes as shown in [Mod Tap](mod_tap.md), not the `KC_*` codes. * `OSL(layer)` - momentary switch to *layer*. +* `OS_ON` - Turns on One Shot keys. +* `OS_OFF` - Turns off One Shot keys. OSM act as regular mod keys, OSL act like `MO`. +* `ON_TOGG` - Toggles the one shot key status. Sometimes, you want to activate a one-shot key as part of a macro or tap dance routine. diff --git a/quantum/keycode_config.h b/quantum/keycode_config.h index f878168c5f..d7e334fdc8 100644 --- a/quantum/keycode_config.h +++ b/quantum/keycode_config.h @@ -37,6 +37,7 @@ typedef union { bool nkro : 1; bool swap_lctl_lgui : 1; bool swap_rctl_rgui : 1; + bool oneshot_disable : 1; }; } keymap_config_t; diff --git a/quantum/quantum.c b/quantum/quantum.c index ef751a2331..78601ce6bf 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -318,6 +318,17 @@ bool process_record_quantum(keyrecord_t *record) { case OUT_BT: set_output(OUTPUT_BLUETOOTH); return false; +#endif +#ifndef NO_ACTION_ONESHOT + case ONESHOT_TOGGLE: + oneshot_toggle(); + break; + case ONESHOT_ENABLE: + oneshot_enable(); + break; + case ONESHOT_DISABLE: + oneshot_disable(); + break; #endif } } diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h index e0f5dbc61e..63945a17ca 100644 --- a/quantum/quantum_keycodes.h +++ b/quantum/quantum_keycodes.h @@ -578,6 +578,10 @@ enum quantum_keycodes { #endif + ONESHOT_ENABLE, + ONESHOT_DISABLE, + ONESHOT_TOGGLE, + // always leave at the end SAFE_RANGE }; @@ -885,3 +889,8 @@ enum quantum_keycodes { #define DM_RSTP DYN_REC_STOP #define DM_PLY1 DYN_MACRO_PLAY1 #define DM_PLY2 DYN_MACRO_PLAY2 + +// One Shot toggle +#define OS_TOGG ONESHOT_TOGGLE +#define OS_ON ONESHOT_ENABLE +#define OS_OFF ONESHOT_DISABLE diff --git a/tmk_core/common/action_util.c b/tmk_core/common/action_util.c index 000503b082..a57c8bf66a 100644 --- a/tmk_core/common/action_util.c +++ b/tmk_core/common/action_util.c @@ -147,12 +147,16 @@ void clear_oneshot_swaphands(void) { * FIXME: needs doc */ void set_oneshot_layer(uint8_t layer, uint8_t state) { - oneshot_layer_data = layer << 3 | state; - layer_on(layer); + if (!keymap_config.oneshot_disable) { + oneshot_layer_data = layer << 3 | state; + layer_on(layer); # if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) - oneshot_layer_time = timer_read(); + oneshot_layer_time = timer_read(); # endif - oneshot_layer_changed_kb(get_oneshot_layer()); + oneshot_layer_changed_kb(get_oneshot_layer()); + } else { + layer_on(layer); + } } /** \brief Reset oneshot layer * @@ -172,7 +176,7 @@ void reset_oneshot_layer(void) { void clear_oneshot_layer_state(oneshot_fullfillment_t state) { uint8_t start_state = oneshot_layer_data; oneshot_layer_data &= ~state; - if (!get_oneshot_layer_state() && start_state != oneshot_layer_data) { + if ((!get_oneshot_layer_state() && start_state != oneshot_layer_data) || keymap_config.oneshot_disable) { layer_off(get_oneshot_layer()); reset_oneshot_layer(); } @@ -182,6 +186,39 @@ void clear_oneshot_layer_state(oneshot_fullfillment_t state) { * FIXME: needs doc */ bool is_oneshot_layer_active(void) { return get_oneshot_layer_state(); } + +/** \brief set oneshot + * + * FIXME: needs doc + */ +void oneshot_set(bool active) { + if (keymap_config.oneshot_disable != active) { + keymap_config.oneshot_disable = active; + eeconfig_update_keymap(keymap_config.raw); + dprintf("Oneshot: active: %d\n", active); + } +} + +/** \brief toggle oneshot + * + * FIXME: needs doc + */ +void oneshot_toggle(void) { oneshot_set(!keymap_config.oneshot_disable); } + +/** \brief enable oneshot + * + * FIXME: needs doc + */ +void oneshot_enable(void) { oneshot_set(true); } + +/** \brief disable oneshot + * + * FIXME: needs doc + */ +void oneshot_disable(void) { oneshot_set(false); } + +bool is_oneshot_enabled(void) { return keymap_config.oneshot_disable; } + #endif /** \brief Send keyboard report @@ -321,14 +358,17 @@ void del_oneshot_mods(uint8_t mods) { * FIXME: needs doc */ void set_oneshot_mods(uint8_t mods) { - if (oneshot_mods != mods) { + if (!keymap_config.oneshot_disable) { + if (oneshot_mods != mods) { # if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) - oneshot_time = timer_read(); + oneshot_time = timer_read(); # endif - oneshot_mods = mods; - oneshot_mods_changed_kb(mods); + oneshot_mods = mods; + oneshot_mods_changed_kb(mods); + } } } + /** \brief clear oneshot mods * * FIXME: needs doc diff --git a/tmk_core/common/action_util.h b/tmk_core/common/action_util.h index ff29f79b09..f2b3897ae5 100644 --- a/tmk_core/common/action_util.h +++ b/tmk_core/common/action_util.h @@ -85,6 +85,11 @@ void oneshot_mods_changed_kb(uint8_t mods); void oneshot_layer_changed_user(uint8_t layer); void oneshot_layer_changed_kb(uint8_t layer); +void oneshot_toggle(void); +void oneshot_enable(void); +void oneshot_disable(void); +bool is_oneshot_enabled(void); + /* inspect */ uint8_t has_anymod(void); -- cgit v1.2.3 From cde2859a6591b1274da20978bd158f20229faa88 Mon Sep 17 00:00:00 2001 From: XScorpion2 Date: Tue, 2 Mar 2021 14:32:15 -0600 Subject: Split RGB Matrix (#11055) * Split RGB Matrix * Suspend State sync for rgb matrix--- docs/feature_rgb_matrix.md | 2 ++ quantum/rgb_matrix.c | 35 ++++++++++++++++++++++++++++++----- quantum/rgb_matrix_types.h | 1 + quantum/split_common/transport.c | 35 +++++++++++++++++++++++++++++++++++ tmk_core/common/avr/suspend.c | 4 ++++ tmk_core/common/chibios/suspend.c | 8 ++++++++ tmk_core/common/eeconfig.c | 2 +- tmk_core/common/eeconfig.h | 9 +++++---- 8 files changed, 86 insertions(+), 10 deletions(-) (limited to 'tmk_core') diff --git a/docs/feature_rgb_matrix.md b/docs/feature_rgb_matrix.md index fd866bd571..878acaf8b3 100644 --- a/docs/feature_rgb_matrix.md +++ b/docs/feature_rgb_matrix.md @@ -439,6 +439,8 @@ These are defined in [`rgblight_list.h`](https://github.com/qmk/qmk_firmware/blo #define RGB_MATRIX_STARTUP_VAL RGB_MATRIX_MAXIMUM_BRIGHTNESS // Sets the default brightness value, if none has been set #define RGB_MATRIX_STARTUP_SPD 127 // Sets the default animation speed, if none has been set #define RGB_MATRIX_DISABLE_KEYCODES // disables control of rgb matrix by keycodes (must use code functions to control the feature) +#define RGB_MATRIX_SPLIT { X, Y } // (Optional) For split keyboards, the number of LEDs connected on each half. X = left, Y = Right. + // If RGB_MATRIX_KEYPRESSES or RGB_MATRIX_KEYRELEASES is enabled, you also will want to enable SPLIT_TRANSPORT_MIRROR ``` ## EEPROM storage :id=eeprom-storage diff --git a/quantum/rgb_matrix.c b/quantum/rgb_matrix.c index ec17b4d72c..69d4c02093 100644 --- a/quantum/rgb_matrix.c +++ b/quantum/rgb_matrix.c @@ -131,7 +131,7 @@ last_hit_t g_last_hit_tracker; // internals static uint8_t rgb_last_enable = UINT8_MAX; static uint8_t rgb_last_effect = UINT8_MAX; -static effect_params_t rgb_effect_params = {0, 0xFF}; +static effect_params_t rgb_effect_params = {0, LED_FLAG_ALL, false}; static rgb_task_states rgb_task_state = SYNCING; #if RGB_DISABLE_TIMEOUT > 0 static uint32_t rgb_anykey_timer; @@ -143,6 +143,11 @@ static uint32_t rgb_timer_buffer; static last_hit_t last_hit_buffer; #endif // RGB_MATRIX_KEYREACTIVE_ENABLED +// split rgb matrix +#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) +const uint8_t k_rgb_matrix_split[2] = RGB_MATRIX_SPLIT; +#endif + void eeconfig_read_rgb_matrix(void) { eeprom_read_block(&rgb_matrix_config, EECONFIG_RGB_MATRIX, sizeof(rgb_matrix_config)); } void eeconfig_update_rgb_matrix(void) { eeprom_update_block(&rgb_matrix_config, EECONFIG_RGB_MATRIX, sizeof(rgb_matrix_config)); } @@ -153,6 +158,7 @@ void eeconfig_update_rgb_matrix_default(void) { rgb_matrix_config.mode = RGB_MATRIX_STARTUP_MODE; rgb_matrix_config.hsv = (HSV){RGB_MATRIX_STARTUP_HUE, RGB_MATRIX_STARTUP_SAT, RGB_MATRIX_STARTUP_VAL}; rgb_matrix_config.speed = RGB_MATRIX_STARTUP_SPD; + rgb_matrix_config.flags = LED_FLAG_ALL; eeconfig_update_rgb_matrix(); } @@ -164,6 +170,7 @@ void eeconfig_debug_rgb_matrix(void) { dprintf("rgb_matrix_config.hsv.s = %d\n", rgb_matrix_config.hsv.s); dprintf("rgb_matrix_config.hsv.v = %d\n", rgb_matrix_config.hsv.v); dprintf("rgb_matrix_config.speed = %d\n", rgb_matrix_config.speed); + dprintf("rgb_matrix_config.flags = %d\n", rgb_matrix_config.flags); } __attribute__((weak)) uint8_t rgb_matrix_map_row_column_to_led_kb(uint8_t row, uint8_t column, uint8_t *led_i) { return 0; } @@ -180,9 +187,23 @@ uint8_t rgb_matrix_map_row_column_to_led(uint8_t row, uint8_t column, uint8_t *l void rgb_matrix_update_pwm_buffers(void) { rgb_matrix_driver.flush(); } -void rgb_matrix_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) { rgb_matrix_driver.set_color(index, red, green, blue); } +void rgb_matrix_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) { +#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) + if (!is_keyboard_left() && index >= k_rgb_matrix_split[0]) + rgb_matrix_driver.set_color(index - k_rgb_matrix_split[0], red, green, blue); + else if (is_keyboard_left() && index < k_rgb_matrix_split[0]) +#endif + rgb_matrix_driver.set_color(index, red, green, blue); +} -void rgb_matrix_set_color_all(uint8_t red, uint8_t green, uint8_t blue) { rgb_matrix_driver.set_color_all(red, green, blue); } +void rgb_matrix_set_color_all(uint8_t red, uint8_t green, uint8_t blue) { +#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) + for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) + rgb_matrix_set_color(i, red, green, blue); +#else + rgb_matrix_driver.set_color_all(red, green, blue); +#endif +} void process_rgb_matrix(uint8_t row, uint8_t col, bool pressed) { #ifndef RGB_MATRIX_SPLIT @@ -315,6 +336,10 @@ static void rgb_task_start(void) { static void rgb_task_render(uint8_t effect) { bool rendering = false; rgb_effect_params.init = (effect != rgb_last_effect) || (rgb_matrix_config.enable != rgb_last_enable); + if (rgb_effect_params.flags != rgb_matrix_config.flags) { + rgb_effect_params.flags = rgb_matrix_config.flags; + rgb_matrix_set_color_all(0, 0, 0); + } // each effect can opt to do calculations // and/or request PWM buffer updates. @@ -618,6 +643,6 @@ void rgb_matrix_decrease_speed_helper(bool write_to_eeprom) { rgb_matrix_set_spe void rgb_matrix_decrease_speed_noeeprom(void) { rgb_matrix_decrease_speed_helper(false); } void rgb_matrix_decrease_speed(void) { rgb_matrix_decrease_speed_helper(true); } -led_flags_t rgb_matrix_get_flags(void) { return rgb_effect_params.flags; } +led_flags_t rgb_matrix_get_flags(void) { return rgb_matrix_config.flags; } -void rgb_matrix_set_flags(led_flags_t flags) { rgb_effect_params.flags = flags; } +void rgb_matrix_set_flags(led_flags_t flags) { rgb_matrix_config.flags = flags; } diff --git a/quantum/rgb_matrix_types.h b/quantum/rgb_matrix_types.h index 7b8171fb23..8cd5b17a77 100644 --- a/quantum/rgb_matrix_types.h +++ b/quantum/rgb_matrix_types.h @@ -89,6 +89,7 @@ typedef union { uint8_t mode : 6; HSV hsv; uint8_t speed; // EECONFIG needs to be increased to support this + led_flags_t flags; }; } rgb_config_t; diff --git a/quantum/split_common/transport.c b/quantum/split_common/transport.c index 61b61ea08c..daa60bb734 100644 --- a/quantum/split_common/transport.c +++ b/quantum/split_common/transport.c @@ -22,6 +22,10 @@ static pin_t encoders_pad[] = ENCODERS_PAD_A; # define NUMBER_OF_ENCODERS (sizeof(encoders_pad) / sizeof(pin_t)) #endif +#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) +# include "rgb_matrix.h" +#endif + #if defined(USE_I2C) # include "i2c_master.h" @@ -54,6 +58,10 @@ typedef struct _I2C_slave_buffer_t { # ifdef WPM_ENABLE uint8_t current_wpm; # endif +# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) + rgb_config_t rgb_matrix; + bool rgb_suspend_state; +# endif } I2C_slave_buffer_t; static I2C_slave_buffer_t *const i2c_buffer = (I2C_slave_buffer_t *)i2c_slave_reg; @@ -68,6 +76,8 @@ static I2C_slave_buffer_t *const i2c_buffer = (I2C_slave_buffer_t *)i2c_slave_re # define I2C_RGB_START offsetof(I2C_slave_buffer_t, rgblight_sync) # define I2C_ENCODER_START offsetof(I2C_slave_buffer_t, encoder_state) # define I2C_WPM_START offsetof(I2C_slave_buffer_t, current_wpm) +# define I2C_RGB_MATRIX_START offsetof(I2C_slave_buffer_t, rgb_matrix) +# define I2C_RGB_SUSPEND_START offsetof(I2C_slave_buffer_t, rgb_suspend_state) # define TIMEOUT 100 @@ -141,6 +151,11 @@ bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) # endif # endif +# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) + i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_MATRIX_START, (void *)rgb_matrix_config, sizeof(i2c_buffer->rgb_matrix), TIMEOUT); + i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_SUSPEND_START, (void *)g_suspend_state, sizeof(i2c_buffer->rgb_suspend_state), TIMEOUT); +# endif + # ifndef DISABLE_SYNC_TIMER i2c_buffer->sync_timer = sync_timer_read32() + SYNC_TIMER_OFFSET; i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_SYNC_TIME_START, (void *)&i2c_buffer->sync_timer, sizeof(i2c_buffer->sync_timer), TIMEOUT); @@ -186,6 +201,11 @@ void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) set_oneshot_mods(i2c_buffer->oneshot_mods); # endif # endif + +# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) + memcpy((void*)i2c_buffer->rgb_matrix, (void *)rgb_matrix_config, sizeof(i2c_buffer->rgb_matrix)); + memcpy((void*)i2c_buffer->rgb_suspend_state, (void *)g_suspend_state, sizeof(i2c_buffer->rgb_suspend_state)); +# endif } void transport_master_init(void) { i2c_init(); } @@ -226,6 +246,10 @@ typedef struct _Serial_m2s_buffer_t { # ifdef WPM_ENABLE uint8_t current_wpm; # endif +# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) + rgb_config_t rgb_matrix; + bool rgb_suspend_state; +# endif } Serial_m2s_buffer_t; # if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) @@ -343,6 +367,12 @@ bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) serial_m2s_buffer.oneshot_mods = get_oneshot_mods(); # endif # endif + +# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) + serial_m2s_buffer.rgb_matrix = rgb_matrix_config; + serial_m2s_buffer.rgb_suspend_state = g_suspend_state; +# endif + # ifndef DISABLE_SYNC_TIMER serial_m2s_buffer.sync_timer = sync_timer_read32() + SYNC_TIMER_OFFSET; # endif @@ -381,6 +411,11 @@ void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) set_oneshot_mods(serial_m2s_buffer.oneshot_mods); # endif # endif + +# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) + rgb_matrix_config = serial_m2s_buffer.rgb_matrix; + g_suspend_state = serial_m2s_buffer.rgb_suspend_state; +# endif } #endif diff --git a/tmk_core/common/avr/suspend.c b/tmk_core/common/avr/suspend.c index 47a82a2eec..d52c8ac410 100644 --- a/tmk_core/common/avr/suspend.c +++ b/tmk_core/common/avr/suspend.c @@ -28,6 +28,10 @@ # include "rgblight.h" #endif +#ifdef RGB_MATRIX_ENABLE +# include "rgb_matrix.h" +#endif + /** \brief Suspend idle * * FIXME: needs doc diff --git a/tmk_core/common/chibios/suspend.c b/tmk_core/common/chibios/suspend.c index 49e20641fb..17f024caba 100644 --- a/tmk_core/common/chibios/suspend.c +++ b/tmk_core/common/chibios/suspend.c @@ -24,6 +24,10 @@ # include "rgblight.h" #endif +#ifdef RGB_MATRIX_ENABLE +# include "rgb_matrix.h" +#endif + /** \brief suspend idle * * FIXME: needs doc @@ -53,6 +57,10 @@ void suspend_power_down(void) { backlight_set(0); #endif +#ifdef RGB_MATRIX_ENABLE + rgb_matrix_task(); +#endif + // Turn off LED indicators uint8_t leds_off = 0; #if defined(BACKLIGHT_CAPS_LOCK) && defined(BACKLIGHT_ENABLE) diff --git a/tmk_core/common/eeconfig.c b/tmk_core/common/eeconfig.c index 5e3ebe6ee6..92a5092176 100644 --- a/tmk_core/common/eeconfig.c +++ b/tmk_core/common/eeconfig.c @@ -57,7 +57,7 @@ void eeconfig_init_quantum(void) { eeprom_update_dword(EECONFIG_HAPTIC, 0); eeprom_update_byte(EECONFIG_VELOCIKEY, 0); eeprom_update_dword(EECONFIG_RGB_MATRIX, 0); - eeprom_update_byte(EECONFIG_RGB_MATRIX_SPEED, 0); + eeprom_update_word(EECONFIG_RGB_MATRIX_EXTENDED, 0); // TODO: Remove once ARM has a way to configure EECONFIG_HANDEDNESS // within the emulated eeprom via dfu-util or another tool diff --git a/tmk_core/common/eeconfig.h b/tmk_core/common/eeconfig.h index 86b9e6f99b..39bc51d5db 100644 --- a/tmk_core/common/eeconfig.h +++ b/tmk_core/common/eeconfig.h @@ -21,7 +21,7 @@ along with this program. If not, see . #include #ifndef EECONFIG_MAGIC_NUMBER -# define EECONFIG_MAGIC_NUMBER (uint16_t)0xFEEB // When changing, decrement this value to avoid future re-init issues +# define EECONFIG_MAGIC_NUMBER (uint16_t)0xFEEA // When changing, decrement this value to avoid future re-init issues #endif #define EECONFIG_MAGIC_NUMBER_OFF (uint16_t)0xFFFF @@ -44,11 +44,12 @@ along with this program. If not, see . #define EECONFIG_HAPTIC (uint32_t *)24 #define EECONFIG_RGB_MATRIX (uint32_t *)28 -#define EECONFIG_RGB_MATRIX_SPEED (uint8_t *)32 +// Speed & Flags +#define EECONFIG_RGB_MATRIX_EXTENDED (uint16_t *)32 // TODO: Combine these into a single word and single block of EEPROM -#define EECONFIG_KEYMAP_UPPER_BYTE (uint8_t *)33 +#define EECONFIG_KEYMAP_UPPER_BYTE (uint8_t *)34 // Size of EEPROM being used, other code can refer to this for available EEPROM -#define EECONFIG_SIZE 34 +#define EECONFIG_SIZE 35 /* debug bit */ #define EECONFIG_DEBUG_ENABLE (1 << 0) #define EECONFIG_DEBUG_MATRIX (1 << 1) -- cgit v1.2.3 From 9155b59e1a496b64f7aa576e6e4cb84fd0a9607b Mon Sep 17 00:00:00 2001 From: Ryan Date: Mon, 8 Mar 2021 16:55:00 +1100 Subject: LED Matrix: decouple from Backlight (#12054) --- common_features.mk | 5 ++--- quantum/led_matrix.c | 8 +------- quantum/led_matrix.h | 4 ---- quantum/process_keycode/process_backlight.c | 29 +++++++++++++++++++++++++++-- quantum/quantum.c | 9 ++++----- quantum/quantum.h | 12 ++++++------ tmk_core/common/eeconfig.h | 5 +++++ 7 files changed, 45 insertions(+), 27 deletions(-) (limited to 'tmk_core') diff --git a/common_features.mk b/common_features.mk index bdde278b98..fdc481fd2a 100644 --- a/common_features.mk +++ b/common_features.mk @@ -223,11 +223,10 @@ VALID_LED_MATRIX_TYPES := IS31FL3731 custom ifeq ($(strip $(LED_MATRIX_ENABLE)), yes) ifeq ($(filter $(LED_MATRIX_DRIVER),$(VALID_LED_MATRIX_TYPES)),) - $(error LED_MATRIX_DRIVER="$(LED_MATRIX_DRIVER)" is not a valid matrix type) + $(error "$(LED_MATRIX_DRIVER)" is not a valid matrix type) else - BACKLIGHT_ENABLE = yes - BACKLIGHT_DRIVER = custom OPT_DEFS += -DLED_MATRIX_ENABLE + SRC += $(QUANTUM_DIR)/process_keycode/process_backlight.c SRC += $(QUANTUM_DIR)/led_matrix.c SRC += $(QUANTUM_DIR)/led_matrix_drivers.c endif diff --git a/quantum/led_matrix.c b/quantum/led_matrix.c index 4f1f06c7ac..39bccdd580 100644 --- a/quantum/led_matrix.c +++ b/quantum/led_matrix.c @@ -45,10 +45,6 @@ led_eeconfig_t led_matrix_eeconfig; # define LED_DISABLE_WHEN_USB_SUSPENDED false #endif -#ifndef EECONFIG_LED_MATRIX -# define EECONFIG_LED_MATRIX EECONFIG_RGBLIGHT -#endif - #if !defined(LED_MATRIX_MAXIMUM_BRIGHTNESS) || LED_MATRIX_MAXIMUM_BRIGHTNESS > 255 # define LED_MATRIX_MAXIMUM_BRIGHTNESS 255 #endif @@ -135,7 +131,7 @@ void led_matrix_set_suspend_state(bool state) { g_suspend_state = state; } void led_matrix_all_off(void) { led_matrix_set_index_value_all(0); } // Uniform brightness -void led_matrix_uniform_brightness(void) { led_matrix_set_index_value_all(LED_MATRIX_MAXIMUM_BRIGHTNESS / BACKLIGHT_LEVELS * led_matrix_eeconfig.val); } +void led_matrix_uniform_brightness(void) { led_matrix_set_index_value_all(led_matrix_eeconfig.val); } void led_matrix_custom(void) {} @@ -344,5 +340,3 @@ void led_matrix_set_value(uint8_t val) { led_matrix_set_value_noeeprom(val); eeconfig_update_led_matrix(led_matrix_eeconfig.raw); } - -void backlight_set(uint8_t val) { led_matrix_set_value(val); } diff --git a/quantum/led_matrix.h b/quantum/led_matrix.h index 85bae43c15..0817d13573 100644 --- a/quantum/led_matrix.h +++ b/quantum/led_matrix.h @@ -21,10 +21,6 @@ #include "led_matrix_types.h" -#ifndef BACKLIGHT_ENABLE -# error You must define BACKLIGHT_ENABLE with LED_MATRIX_ENABLE -#endif - enum led_matrix_effects { LED_MATRIX_UNIFORM_BRIGHTNESS = 1, // All new effects go above this line diff --git a/quantum/process_keycode/process_backlight.c b/quantum/process_keycode/process_backlight.c index 4d12f6813a..8b70339a55 100644 --- a/quantum/process_keycode/process_backlight.c +++ b/quantum/process_keycode/process_backlight.c @@ -16,11 +16,35 @@ #include "process_backlight.h" -#include "backlight.h" +#ifdef LED_MATRIX_ENABLE +# include "led_matrix.h" +#else +# include "backlight.h" +#endif bool process_backlight(uint16_t keycode, keyrecord_t *record) { if (record->event.pressed) { switch (keycode) { +#ifdef LED_MATRIX_ENABLE + case BL_ON: + led_matrix_enable(); + return false; + case BL_OFF: + led_matrix_disable(); + return false; + case BL_DEC: + led_matrix_decrease_val(); + return false; + case BL_INC: + led_matrix_increase_val(); + return false; + case BL_TOGG: + led_matrix_toggle(); + return false; + case BL_STEP: + led_matrix_step(); + return false; +#else case BL_ON: backlight_level(BACKLIGHT_LEVELS); return false; @@ -39,10 +63,11 @@ bool process_backlight(uint16_t keycode, keyrecord_t *record) { case BL_STEP: backlight_step(); return false; -#ifdef BACKLIGHT_BREATHING +# ifdef BACKLIGHT_BREATHING case BL_BRTG: backlight_toggle_breathing(); return false; +# endif #endif } } diff --git a/quantum/quantum.c b/quantum/quantum.c index 78601ce6bf..59d95f2f54 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -234,7 +234,7 @@ bool process_record_quantum(keyrecord_t *record) { #ifdef AUDIO_ENABLE process_audio(keycode, record) && #endif -#ifdef BACKLIGHT_ENABLE +#if defined(BACKLIGHT_ENABLE) || defined(LED_MATRIX_ENABLE) process_backlight(keycode, record) && #endif #ifdef STENO_ENABLE @@ -387,15 +387,14 @@ void matrix_init_quantum() { led_init_ports(); #endif #ifdef BACKLIGHT_ENABLE -# ifdef LED_MATRIX_ENABLE - led_matrix_init(); -# else backlight_init_ports(); -# endif #endif #ifdef AUDIO_ENABLE audio_init(); #endif +#ifdef LED_MATRIX_ENABLE + led_matrix_init(); +#endif #ifdef RGB_MATRIX_ENABLE rgb_matrix_init(); #endif diff --git a/quantum/quantum.h b/quantum/quantum.h index 070bd01317..7c2dcaa829 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h @@ -30,11 +30,11 @@ #include "keymap.h" #ifdef BACKLIGHT_ENABLE -# ifdef LED_MATRIX_ENABLE -# include "led_matrix.h" -# else -# include "backlight.h" -# endif +# include "backlight.h" +#endif + +#ifdef LED_MATRIX_ENABLE +# include "led_matrix.h" #endif #if defined(RGBLIGHT_ENABLE) @@ -98,7 +98,7 @@ extern layer_state_t layer_state; # include "process_music.h" #endif -#ifdef BACKLIGHT_ENABLE +#if defined(BACKLIGHT_ENABLE) || defined(LED_MATRIX_ENABLE) # include "process_backlight.h" #endif diff --git a/tmk_core/common/eeconfig.h b/tmk_core/common/eeconfig.h index 39bc51d5db..9e18fd4e15 100644 --- a/tmk_core/common/eeconfig.h +++ b/tmk_core/common/eeconfig.h @@ -43,9 +43,14 @@ along with this program. If not, see . #define EECONFIG_VELOCIKEY (uint8_t *)23 #define EECONFIG_HAPTIC (uint32_t *)24 + +// Mutually exclusive +#define EECONFIG_LED_MATRIX (uint32_t *)28 #define EECONFIG_RGB_MATRIX (uint32_t *)28 // Speed & Flags +#define EECONFIG_LED_MATRIX_EXTENDED (uint16_t *)32 #define EECONFIG_RGB_MATRIX_EXTENDED (uint16_t *)32 + // TODO: Combine these into a single word and single block of EEPROM #define EECONFIG_KEYMAP_UPPER_BYTE (uint8_t *)34 // Size of EEPROM being used, other code can refer to this for available EEPROM -- cgit v1.2.3 From 40c7ecfdeaf50ab76e10854a84aebfcb82ddb092 Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Wed, 10 Mar 2021 22:47:36 +0000 Subject: Move gpio wait logic to wait.h (#12067) --- quantum/quantum.h | 33 -------- tmk_core/common/arm_atsam/_wait.h | 22 ++++++ tmk_core/common/avr/_wait.h | 29 +++++++ tmk_core/common/chibios/_wait.h | 55 ++++++++++++++ tmk_core/common/chibios/chibios_config.h | 1 + tmk_core/common/chibios/wait.c | 89 ++++++++++++++++++++++ tmk_core/common/test/_wait.h | 22 ++++++ tmk_core/common/wait.h | 125 +++++-------------------------- 8 files changed, 235 insertions(+), 141 deletions(-) create mode 100644 tmk_core/common/arm_atsam/_wait.h create mode 100644 tmk_core/common/avr/_wait.h create mode 100644 tmk_core/common/chibios/_wait.h create mode 100644 tmk_core/common/chibios/wait.c create mode 100644 tmk_core/common/test/_wait.h (limited to 'tmk_core') diff --git a/quantum/quantum.h b/quantum/quantum.h index 7c2dcaa829..7c546b5152 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h @@ -200,39 +200,6 @@ extern layer_state_t layer_state; # include "usbpd.h" #endif -// Function substitutions to ease GPIO manipulation -#if defined(__AVR__) - -/* The AVR series GPIOs have a one clock read delay for changes in the digital input signal. - * But here's more margin to make it two clocks. */ -# if !defined(GPIO_INPUT_PIN_DELAY) -# define GPIO_INPUT_PIN_DELAY 2 -# endif -# define waitInputPinDelay() wait_cpuclock(GPIO_INPUT_PIN_DELAY) - -#elif defined(__ARMEL__) || defined(__ARMEB__) - -/* For GPIOs on ARM-based MCUs, the input pins are sampled by the clock of the bus - * to which the GPIO is connected. - * The connected buses differ depending on the various series of MCUs. - * And since the instruction execution clock of the CPU and the bus clock of GPIO are different, - * there is a delay of several clocks to read the change of the input signal. - * - * Define this delay with the GPIO_INPUT_PIN_DELAY macro. - * If the GPIO_INPUT_PIN_DELAY macro is not defined, the following default values will be used. - * (A fairly large value of 0.25 microseconds is set.) - */ -# if !defined(GPIO_INPUT_PIN_DELAY) -# if defined(STM32_SYSCLK) -# define GPIO_INPUT_PIN_DELAY (STM32_SYSCLK / 1000000L / 4) -# elif defined(KINETIS_SYSCLK_FREQUENCY) -# define GPIO_INPUT_PIN_DELAY (KINETIS_SYSCLK_FREQUENCY / 1000000L / 4) -# endif -# endif -# define waitInputPinDelay() wait_cpuclock(GPIO_INPUT_PIN_DELAY) - -#endif - // For tri-layer void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3); layer_state_t update_tri_layer_state(layer_state_t state, uint8_t layer1, uint8_t layer2, uint8_t layer3); diff --git a/tmk_core/common/arm_atsam/_wait.h b/tmk_core/common/arm_atsam/_wait.h new file mode 100644 index 0000000000..41b686b56c --- /dev/null +++ b/tmk_core/common/arm_atsam/_wait.h @@ -0,0 +1,22 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#include "clks.h" + +#define wait_ms(ms) CLK_delay_ms(ms) +#define wait_us(us) CLK_delay_us(us) +#define waitInputPinDelay() diff --git a/tmk_core/common/avr/_wait.h b/tmk_core/common/avr/_wait.h new file mode 100644 index 0000000000..56eb316faf --- /dev/null +++ b/tmk_core/common/avr/_wait.h @@ -0,0 +1,29 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#include + +#define wait_ms(ms) _delay_ms(ms) +#define wait_us(us) _delay_us(us) + +/* The AVR series GPIOs have a one clock read delay for changes in the digital input signal. + * But here's more margin to make it two clocks. */ +#ifndef GPIO_INPUT_PIN_DELAY +# define GPIO_INPUT_PIN_DELAY 2 +#endif + +#define waitInputPinDelay() __builtin_avr_delay_cycles(GPIO_INPUT_PIN_DELAY) diff --git a/tmk_core/common/chibios/_wait.h b/tmk_core/common/chibios/_wait.h new file mode 100644 index 0000000000..5bface53e1 --- /dev/null +++ b/tmk_core/common/chibios/_wait.h @@ -0,0 +1,55 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#include + +/* chThdSleepX of zero maps to infinite - so we map to a tiny delay to still yield */ +#define wait_ms(ms) \ + do { \ + if (ms != 0) { \ + chThdSleepMilliseconds(ms); \ + } else { \ + chThdSleepMicroseconds(1); \ + } \ + } while (0) +#define wait_us(us) \ + do { \ + if (us != 0) { \ + chThdSleepMicroseconds(us); \ + } else { \ + chThdSleepMicroseconds(1); \ + } \ + } while (0) + +/* For GPIOs on ARM-based MCUs, the input pins are sampled by the clock of the bus + * to which the GPIO is connected. + * The connected buses differ depending on the various series of MCUs. + * And since the instruction execution clock of the CPU and the bus clock of GPIO are different, + * there is a delay of several clocks to read the change of the input signal. + * + * Define this delay with the GPIO_INPUT_PIN_DELAY macro. + * If the GPIO_INPUT_PIN_DELAY macro is not defined, the following default values will be used. + * (A fairly large value of 0.25 microseconds is set.) + */ + +#include "wait.c" + +#ifndef GPIO_INPUT_PIN_DELAY +# define GPIO_INPUT_PIN_DELAY (STM32_SYSCLK / 1000000L / 4) +#endif + +#define waitInputPinDelay() wait_cpuclock(GPIO_INPUT_PIN_DELAY) diff --git a/tmk_core/common/chibios/chibios_config.h b/tmk_core/common/chibios/chibios_config.h index bebf026de7..9a66ac3174 100644 --- a/tmk_core/common/chibios/chibios_config.h +++ b/tmk_core/common/chibios/chibios_config.h @@ -30,4 +30,5 @@ # define USE_I2CV1 # define USE_I2CV1_CONTRIB // for some reason a bunch of ChibiOS-Contrib boards only have clock_speed # define USE_GPIOV1 +# define STM32_SYSCLK KINETIS_SYSCLK_FREQUENCY #endif diff --git a/tmk_core/common/chibios/wait.c b/tmk_core/common/chibios/wait.c new file mode 100644 index 0000000000..c6270fd95e --- /dev/null +++ b/tmk_core/common/chibios/wait.c @@ -0,0 +1,89 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __OPTIMIZE__ +# pragma message "Compiler optimizations disabled; wait_cpuclock() won't work as designed" +#endif + +#define CLOCK_DELAY_NOP8 "nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t" + +__attribute__((always_inline)) static inline void wait_cpuclock(unsigned int n) { /* n: 1..135 */ + /* The argument n must be a constant expression. + * That way, compiler optimization will remove unnecessary code. */ + if (n < 1) { + return; + } + if (n > 8) { + unsigned int n8 = n / 8; + n = n - n8 * 8; + switch (n8) { + case 16: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 15: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 14: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 13: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 12: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 11: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 10: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 9: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 8: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 7: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 6: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 5: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 4: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 3: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 2: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 1: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 0: + break; + } + } + switch (n) { + case 8: + asm volatile("nop" ::: "memory"); + case 7: + asm volatile("nop" ::: "memory"); + case 6: + asm volatile("nop" ::: "memory"); + case 5: + asm volatile("nop" ::: "memory"); + case 4: + asm volatile("nop" ::: "memory"); + case 3: + asm volatile("nop" ::: "memory"); + case 2: + asm volatile("nop" ::: "memory"); + case 1: + asm volatile("nop" ::: "memory"); + case 0: + break; + } +} \ No newline at end of file diff --git a/tmk_core/common/test/_wait.h b/tmk_core/common/test/_wait.h new file mode 100644 index 0000000000..4e22f593b7 --- /dev/null +++ b/tmk_core/common/test/_wait.h @@ -0,0 +1,22 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#include + +void wait_ms(uint32_t ms); +#define wait_us(us) wait_ms(us / 1000) +#define waitInputPinDelay() diff --git a/tmk_core/common/wait.h b/tmk_core/common/wait.h index 28224fe3aa..cf7180fb07 100644 --- a/tmk_core/common/wait.h +++ b/tmk_core/common/wait.h @@ -1,3 +1,18 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ #pragma once #include @@ -6,114 +21,8 @@ extern "C" { #endif -#if defined(__ARMEL__) || defined(__ARMEB__) -# ifndef __OPTIMIZE__ -# pragma message "Compiler optimizations disabled; wait_cpuclock() won't work as designed" -# endif - -# define wait_cpuclock(x) wait_cpuclock_allnop(x) - -# define CLOCK_DELAY_NOP8 "nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t" - -__attribute__((always_inline)) static inline void wait_cpuclock_allnop(unsigned int n) { /* n: 1..135 */ - /* The argument n must be a constant expression. - * That way, compiler optimization will remove unnecessary code. */ - if (n < 1) { - return; - } - if (n > 8) { - unsigned int n8 = n / 8; - n = n - n8 * 8; - switch (n8) { - case 16: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 15: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 14: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 13: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 12: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 11: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 10: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 9: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 8: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 7: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 6: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 5: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 4: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 3: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 2: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 1: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 0: - break; - } - } - switch (n) { - case 8: - asm volatile("nop" ::: "memory"); - case 7: - asm volatile("nop" ::: "memory"); - case 6: - asm volatile("nop" ::: "memory"); - case 5: - asm volatile("nop" ::: "memory"); - case 4: - asm volatile("nop" ::: "memory"); - case 3: - asm volatile("nop" ::: "memory"); - case 2: - asm volatile("nop" ::: "memory"); - case 1: - asm volatile("nop" ::: "memory"); - case 0: - break; - } -} -#endif - -#if defined(__AVR__) -# include -# define wait_ms(ms) _delay_ms(ms) -# define wait_us(us) _delay_us(us) -# define wait_cpuclock(x) __builtin_avr_delay_cycles(x) -#elif defined PROTOCOL_CHIBIOS -# include -# define wait_ms(ms) \ - do { \ - if (ms != 0) { \ - chThdSleepMilliseconds(ms); \ - } else { \ - chThdSleepMicroseconds(1); \ - } \ - } while (0) -# define wait_us(us) \ - do { \ - if (us != 0) { \ - chThdSleepMicroseconds(us); \ - } else { \ - chThdSleepMicroseconds(1); \ - } \ - } while (0) -#elif defined PROTOCOL_ARM_ATSAM -# include "clks.h" -# define wait_ms(ms) CLK_delay_ms(ms) -# define wait_us(us) CLK_delay_us(us) -#else // Unit tests -void wait_ms(uint32_t ms); -# define wait_us(us) wait_ms(us / 1000) +#if __has_include_next("_wait.h") +# include_next "_wait.h" /* Include the platforms _wait.h */ #endif #ifdef __cplusplus -- cgit v1.2.3 From 1d341ffbb0dfbf45139c103123549c3c0fec816e Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 16 Mar 2021 20:45:21 +0100 Subject: core: add support for MK66F18 (Teensy 3.6) micro controller (#12258) This is in preparation for https://github.com/qmk/qmk_firmware/pull/10171--- data/schemas/keyboard.jsonschema | 2 +- lib/python/qmk/constants.py | 2 +- quantum/mcu_selection.mk | 27 +++++++++++++++++++++++++++ tmk_core/common/chibios/bootloader.c | 2 +- tmk_core/common/chibios/chibios_config.h | 4 ++++ 5 files changed, 34 insertions(+), 3 deletions(-) (limited to 'tmk_core') diff --git a/data/schemas/keyboard.jsonschema b/data/schemas/keyboard.jsonschema index ec03a8828b..3034242fd9 100644 --- a/data/schemas/keyboard.jsonschema +++ b/data/schemas/keyboard.jsonschema @@ -25,7 +25,7 @@ }, "processor": { "type": "string", - "enum": ["cortex-m0", "cortex-m0plus", "cortex-m3", "cortex-m4", "MKL26Z64", "MK20DX128", "MK20DX256", "STM32F042", "STM32F072", "STM32F103", "STM32F303", "STM32F401", "STM32F411", "STM32G431", "STM32G474", "atmega16u2", "atmega32u2", "atmega16u4", "atmega32u4", "at90usb162", "at90usb646", "at90usb647", "at90usb1286", "at90usb1287", "atmega32a", "atmega328p", "atmega328", "attiny85", "unknown"] + "enum": ["cortex-m0", "cortex-m0plus", "cortex-m3", "cortex-m4", "MKL26Z64", "MK20DX128", "MK20DX256", "MK66F18", "STM32F042", "STM32F072", "STM32F103", "STM32F303", "STM32F401", "STM32F411", "STM32G431", "STM32G474", "atmega16u2", "atmega32u2", "atmega16u4", "atmega32u4", "at90usb162", "at90usb646", "at90usb647", "at90usb1286", "at90usb1287", "atmega32a", "atmega328p", "atmega328", "attiny85", "unknown"] }, "board": { "type": "string", diff --git a/lib/python/qmk/constants.py b/lib/python/qmk/constants.py index 3ed69f3bf9..b5cdaf6a60 100644 --- a/lib/python/qmk/constants.py +++ b/lib/python/qmk/constants.py @@ -10,7 +10,7 @@ QMK_FIRMWARE = Path.cwd() MAX_KEYBOARD_SUBFOLDERS = 5 # Supported processor types -CHIBIOS_PROCESSORS = 'cortex-m0', 'cortex-m0plus', 'cortex-m3', 'cortex-m4', 'MKL26Z64', 'MK20DX128', 'MK20DX256', 'STM32F042', 'STM32F072', 'STM32F103', 'STM32F303', 'STM32F401', 'STM32F411', 'STM32G431', 'STM32G474' +CHIBIOS_PROCESSORS = 'cortex-m0', 'cortex-m0plus', 'cortex-m3', 'cortex-m4', 'MKL26Z64', 'MK20DX128', 'MK20DX256', 'MK66F18', 'STM32F042', 'STM32F072', 'STM32F103', 'STM32F303', 'STM32F401', 'STM32F411', 'STM32G431', 'STM32G474' LUFA_PROCESSORS = 'at90usb162', 'atmega16u2', 'atmega32u2', 'atmega16u4', 'atmega32u4', 'at90usb646', 'at90usb647', 'at90usb1286', 'at90usb1287', None VUSB_PROCESSORS = 'atmega32a', 'atmega328p', 'atmega328', 'attiny85' diff --git a/quantum/mcu_selection.mk b/quantum/mcu_selection.mk index f7329fc4d9..53e03a8054 100644 --- a/quantum/mcu_selection.mk +++ b/quantum/mcu_selection.mk @@ -81,6 +81,33 @@ ifneq ($(findstring MK20DX256, $(MCU)),) BOARD ?= PJRC_TEENSY_3_1 endif +ifneq ($(findstring MK66F18, $(MCU)),) + # Cortex version + MCU = cortex-m4 + + # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7 + ARMV = 7 + + ## chip/board settings + # - the next two should match the directories in + # /os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES) + MCU_FAMILY = KINETIS + MCU_SERIES = MK66F18 + + # Linker script to use + # - it should exist either in /os/common/ports/ARMCMx/compilers/GCC/ld/ + # or /ld/ + MCU_LDSCRIPT ?= MK66FX1M0 + + # Startup code to use + # - it should exist in /os/common/startup/ARMCMx/compilers/GCC/mk/ + MCU_STARTUP ?= MK66F18 + + # Board: it should exist either in /os/hal/boards/, + # /boards/, or drivers/boards/ + BOARD ?= PJRC_TEENSY_3_6 +endif + ifneq ($(findstring STM32F042, $(MCU)),) # Cortex version MCU = cortex-m0 diff --git a/tmk_core/common/chibios/bootloader.c b/tmk_core/common/chibios/bootloader.c index 6cabcc4b81..4a175a6283 100644 --- a/tmk_core/common/chibios/bootloader.c +++ b/tmk_core/common/chibios/bootloader.c @@ -79,7 +79,7 @@ void enter_bootloader_mode_if_requested(void) { } } -#elif defined(KL2x) || defined(K20x) // STM32_BOOTLOADER_DUAL_BANK // STM32_BOOTLOADER_ADDRESS +#elif defined(KL2x) || defined(K20x) || defined(MK66F18) // STM32_BOOTLOADER_DUAL_BANK // STM32_BOOTLOADER_ADDRESS /* Kinetis */ # if defined(BOOTLOADER_KIIBOHD) diff --git a/tmk_core/common/chibios/chibios_config.h b/tmk_core/common/chibios/chibios_config.h index 9a66ac3174..1d8ace4955 100644 --- a/tmk_core/common/chibios/chibios_config.h +++ b/tmk_core/common/chibios/chibios_config.h @@ -32,3 +32,7 @@ # define USE_GPIOV1 # define STM32_SYSCLK KINETIS_SYSCLK_FREQUENCY #endif + +#if defined(MK66F18) +# define STM32_SYSCLK KINETIS_SYSCLK_FREQUENCY +#endif -- cgit v1.2.3 From 2ae38e9c43cc689be65f04ea5c101b9f46a38c5e Mon Sep 17 00:00:00 2001 From: Ryan Date: Sun, 28 Mar 2021 17:59:44 +1100 Subject: LED Matrix: Config functions (#12361) --- quantum/led_matrix.c | 160 ++++++++++++++++++++------------------------- quantum/led_matrix.h | 32 +++++++-- tmk_core/common/keyboard.c | 6 ++ 3 files changed, 104 insertions(+), 94 deletions(-) (limited to 'tmk_core') diff --git a/quantum/led_matrix.c b/quantum/led_matrix.c index ceb236809f..ec8ff852d5 100644 --- a/quantum/led_matrix.c +++ b/quantum/led_matrix.c @@ -24,6 +24,8 @@ #include #include +#include + led_eeconfig_t led_matrix_eeconfig; #ifndef MAX @@ -211,23 +213,6 @@ __attribute__((weak)) void led_matrix_indicators_kb(void) {} __attribute__((weak)) void led_matrix_indicators_user(void) {} -// void led_matrix_set_indicator_index(uint8_t *index, uint8_t row, uint8_t column) -// { -// if (row >= MATRIX_ROWS) -// { -// // Special value, 255=none, 254=all -// *index = row; -// } -// else -// { -// // This needs updated to something like -// // uint8_t led[8]; -// // uint8_t led_count = map_row_column_to_led(row, column, led); -// // for(uint8_t i = 0; i < led_count; i++) -// map_row_column_to_led(row, column, index); -// } -// } - void led_matrix_init(void) { led_matrix_driver.init(); @@ -254,109 +239,108 @@ void led_matrix_init(void) { eeconfig_debug_led_matrix(); // display current eeprom values } -// Deals with the messy details of incrementing an integer -static uint8_t increment(uint8_t value, uint8_t step, uint8_t min, uint8_t max) { - int16_t new_value = value; - new_value += step; - return MIN(MAX(new_value, min), max); -} - -static uint8_t decrement(uint8_t value, uint8_t step, uint8_t min, uint8_t max) { - int16_t new_value = value; - new_value -= step; - return MIN(MAX(new_value, min), max); -} - -// void *backlight_get_custom_key_value_eeprom_address(uint8_t led) { -// // 3 bytes per value -// return EECONFIG_LED_MATRIX + (led * 3); -// } - -// void backlight_get_key_value(uint8_t led, uint8_t *value) { -// void *address = backlight_get_custom_key_value_eeprom_address(led); -// value = eeprom_read_byte(address); -// } - -// void backlight_set_key_value(uint8_t row, uint8_t column, uint8_t value) { -// uint8_t led[8]; -// uint8_t led_count = map_row_column_to_led(row, column, led); -// for(uint8_t i = 0; i < led_count; i++) { -// if (led[i] < DRIVER_LED_TOTAL) { -// void *address = backlight_get_custom_key_value_eeprom_address(led[i]); -// eeprom_update_byte(address, value); -// } -// } -// } - uint32_t led_matrix_get_tick(void) { return g_tick; } -void led_matrix_toggle(void) { +void led_matrix_toggle_eeprom_helper(bool write_to_eeprom) { led_matrix_eeconfig.enable ^= 1; - eeconfig_update_led_matrix(); + if (write_to_eeprom) { + eeconfig_update_led_matrix(); + } + dprintf("led matrix toggle [%s]: led_matrix_eeconfig.enable = %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.enable); } +void led_matrix_toggle_noeeprom(void) { led_matrix_toggle_eeprom_helper(false); } +void led_matrix_toggle(void) { led_matrix_toggle_eeprom_helper(true); } void led_matrix_enable(void) { - led_matrix_eeconfig.enable = 1; + led_matrix_enable_noeeprom(); eeconfig_update_led_matrix(); } void led_matrix_enable_noeeprom(void) { led_matrix_eeconfig.enable = 1; } void led_matrix_disable(void) { - led_matrix_eeconfig.enable = 0; + led_matrix_disable_noeeprom(); eeconfig_update_led_matrix(); } void led_matrix_disable_noeeprom(void) { led_matrix_eeconfig.enable = 0; } -void led_matrix_step(void) { - led_matrix_eeconfig.mode++; - if (led_matrix_eeconfig.mode >= LED_MATRIX_EFFECT_MAX) { - led_matrix_eeconfig.mode = 1; - } - eeconfig_update_led_matrix(); -} +uint8_t led_matrix_is_enabled(void) { return led_matrix_eeconfig.enable; } -void led_matrix_step_reverse(void) { - led_matrix_eeconfig.mode--; - if (led_matrix_eeconfig.mode < 1) { +void led_matrix_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) { + if (!led_matrix_eeconfig.enable) { + return; + } + if (mode < 1) { + led_matrix_eeconfig.mode = 1; + } else if (mode >= LED_MATRIX_EFFECT_MAX) { led_matrix_eeconfig.mode = LED_MATRIX_EFFECT_MAX - 1; + } else { + led_matrix_eeconfig.mode = mode; } - eeconfig_update_led_matrix(); + if (write_to_eeprom) { + eeconfig_update_led_matrix(); + } + dprintf("led matrix mode [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.mode); } +void led_matrix_mode_noeeprom(uint8_t mode) { led_matrix_mode_eeprom_helper(mode, false); } +void led_matrix_mode(uint8_t mode) { led_matrix_mode_eeprom_helper(mode, true); } -void led_matrix_increase_val(void) { - led_matrix_eeconfig.val = increment(led_matrix_eeconfig.val, 8, 0, LED_MATRIX_MAXIMUM_BRIGHTNESS); - eeconfig_update_led_matrix(); -} +uint8_t led_matrix_get_mode(void) { return led_matrix_eeconfig.mode; } -void led_matrix_decrease_val(void) { - led_matrix_eeconfig.val = decrement(led_matrix_eeconfig.val, 8, 0, LED_MATRIX_MAXIMUM_BRIGHTNESS); - eeconfig_update_led_matrix(); +void led_matrix_step_helper(bool write_to_eeprom) { + uint8_t mode = led_matrix_eeconfig.mode + 1; + led_matrix_mode_eeprom_helper((mode < LED_MATRIX_EFFECT_MAX) ? mode : 1, write_to_eeprom); } +void led_matrix_step_noeeprom(void) { led_matrix_step_helper(false); } +void led_matrix_step(void) { led_matrix_step_helper(true); } -void led_matrix_increase_speed(void) { - led_matrix_eeconfig.speed = increment(led_matrix_eeconfig.speed, 1, 0, 3); - eeconfig_update_led_matrix(); // EECONFIG needs to be increased to support this +void led_matrix_step_reverse_helper(bool write_to_eeprom) { + uint8_t mode = led_matrix_eeconfig.mode - 1; + led_matrix_mode_eeprom_helper((mode < 1) ? LED_MATRIX_EFFECT_MAX - 1 : mode, write_to_eeprom); } +void led_matrix_step_reverse_noeeprom(void) { led_matrix_step_reverse_helper(false); } +void led_matrix_step_reverse(void) { led_matrix_step_reverse_helper(true); } -void led_matrix_decrease_speed(void) { - led_matrix_eeconfig.speed = decrement(led_matrix_eeconfig.speed, 1, 0, 3); - eeconfig_update_led_matrix(); // EECONFIG needs to be increased to support this +void led_matrix_set_val_eeprom_helper(uint8_t val, bool write_to_eeprom) { + if (!led_matrix_eeconfig.enable) { + return; + } + led_matrix_eeconfig.val = (val > LED_MATRIX_MAXIMUM_BRIGHTNESS) ? LED_MATRIX_MAXIMUM_BRIGHTNESS : val; + if (write_to_eeprom) { + eeconfig_update_led_matrix(); + } + dprintf("led matrix set val [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.val); } +void led_matrix_set_val_noeeprom(uint8_t val) { led_matrix_set_val_eeprom_helper(val, false); } +void led_matrix_set_val(uint8_t val) { led_matrix_set_val_eeprom_helper(val, true); } + +uint8_t led_matrix_get_val(void) { return led_matrix_eeconfig.val; } + +void led_matrix_increase_val_helper(bool write_to_eeprom) { led_matrix_set_val_eeprom_helper(qadd8(led_matrix_eeconfig.val, LED_MATRIX_VAL_STEP), write_to_eeprom); } +void led_matrix_increase_val_noeeprom(void) { led_matrix_increase_val_helper(false); } +void led_matrix_increase_val(void) { led_matrix_increase_val_helper(true); } -void led_matrix_mode(uint8_t mode, bool eeprom_write) { - led_matrix_eeconfig.mode = mode; - if (eeprom_write) { +void led_matrix_decrease_val_helper(bool write_to_eeprom) { led_matrix_set_val_eeprom_helper(qsub8(led_matrix_eeconfig.val, LED_MATRIX_VAL_STEP), write_to_eeprom); } +void led_matrix_decrease_val_noeeprom(void) { led_matrix_decrease_val_helper(false); } +void led_matrix_decrease_val(void) { led_matrix_decrease_val_helper(true); } + +void led_matrix_set_speed_eeprom_helper(uint8_t speed, bool write_to_eeprom) { + led_matrix_eeconfig.speed = speed; + if (write_to_eeprom) { eeconfig_update_led_matrix(); } + dprintf("led matrix set speed [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.speed); } +void led_matrix_set_speed_noeeprom(uint8_t speed) { led_matrix_set_speed_eeprom_helper(speed, false); } +void led_matrix_set_speed(uint8_t speed) { led_matrix_set_speed_eeprom_helper(speed, true); } -uint8_t led_matrix_get_mode(void) { return led_matrix_eeconfig.mode; } +uint8_t led_matrix_get_speed(void) { return led_matrix_eeconfig.speed; } -void led_matrix_set_value_noeeprom(uint8_t val) { led_matrix_eeconfig.val = val; } +void led_matrix_increase_speed_helper(bool write_to_eeprom) { led_matrix_set_speed_eeprom_helper(qadd8(led_matrix_eeconfig.speed, LED_MATRIX_SPD_STEP), write_to_eeprom); } +void led_matrix_increase_speed_noeeprom(void) { led_matrix_increase_speed_helper(false); } +void led_matrix_increase_speed(void) { led_matrix_increase_speed_helper(true); } -void led_matrix_set_value(uint8_t val) { - led_matrix_set_value_noeeprom(val); - eeconfig_update_led_matrix(); -} +void led_matrix_decrease_speed_helper(bool write_to_eeprom) { led_matrix_set_speed_eeprom_helper(qsub8(led_matrix_eeconfig.speed, LED_MATRIX_SPD_STEP), write_to_eeprom); } +void led_matrix_decrease_speed_noeeprom(void) { led_matrix_decrease_speed_helper(false); } +void led_matrix_decrease_speed(void) { led_matrix_decrease_speed_helper(true); } diff --git a/quantum/led_matrix.h b/quantum/led_matrix.h index e4322a1509..fd7ef7d29e 100644 --- a/quantum/led_matrix.h +++ b/quantum/led_matrix.h @@ -28,6 +28,14 @@ # include "is31fl3731-simple.h" #endif +#ifndef LED_MATRIX_LED_FLUSH_LIMIT +# define LED_MATRIX_LED_FLUSH_LIMIT 16 +#endif + +#ifndef LED_MATRIX_LED_PROCESS_LIMIT +# define LED_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 +#endif + enum led_matrix_effects { LED_MATRIX_UNIFORM_BRIGHTNESS = 1, // All new effects go above this line @@ -38,7 +46,7 @@ void led_matrix_set_index_value(int index, uint8_t value); void led_matrix_set_index_value_all(uint8_t value); // This runs after another backlight effect and replaces -// colors already set +// values already set void led_matrix_indicators(void); void led_matrix_indicators_kb(void); void led_matrix_indicators_user(void); @@ -62,21 +70,33 @@ bool process_led_matrix(uint16_t keycode, keyrecord_t *record); uint32_t led_matrix_get_tick(void); void led_matrix_toggle(void); +void led_matrix_toggle_noeeprom(void); void led_matrix_enable(void); void led_matrix_enable_noeeprom(void); void led_matrix_disable(void); void led_matrix_disable_noeeprom(void); +uint8_t led_matrix_is_enabled(void); +void led_matrix_mode(uint8_t mode); +void led_matrix_mode_noeeprom(uint8_t mode); +uint8_t led_matrix_get_mode(void); void led_matrix_step(void); +void led_matrix_step_noeeprom(void); void led_matrix_step_reverse(void); +void led_matrix_step_reverse_noeeprom(void); +void led_matrix_set_val(uint8_t val); +void led_matrix_set_val_noeeprom(uint8_t val); +uint8_t led_matrix_get_val(void); void led_matrix_increase_val(void); +void led_matrix_increase_val_noeeprom(void); void led_matrix_decrease_val(void); +void led_matrix_decrease_val_noeeprom(void); +void led_matrix_set_speed(uint8_t speed); +void led_matrix_set_speed_noeeprom(uint8_t speed); +uint8_t led_matrix_get_speed(void); void led_matrix_increase_speed(void); +void led_matrix_increase_speed_noeeprom(void); void led_matrix_decrease_speed(void); -void led_matrix_mode(uint8_t mode, bool eeprom_write); -void led_matrix_mode_noeeprom(uint8_t mode); -uint8_t led_matrix_get_mode(void); -void led_matrix_set_value(uint8_t mode); -void led_matrix_set_value_noeeprom(uint8_t mode); +void led_matrix_decrease_speed_noeeprom(void); typedef struct { /* Perform any initialisation required for the other driver functions to work. */ diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c index 65d9e00c7a..e473806b21 100644 --- a/tmk_core/common/keyboard.c +++ b/tmk_core/common/keyboard.c @@ -49,6 +49,9 @@ along with this program. If not, see . #ifdef RGBLIGHT_ENABLE # include "rgblight.h" #endif +#ifdef LED_MATRIX_ENABLE +# include "led_matrix.h" +#endif #ifdef RGB_MATRIX_ENABLE # include "rgb_matrix.h" #endif @@ -412,6 +415,9 @@ MATRIX_LOOP_END: rgblight_task(); #endif +#ifdef LED_MATRIX_ENABLE + led_matrix_task(); +#endif #ifdef RGB_MATRIX_ENABLE rgb_matrix_task(); #endif -- cgit v1.2.3 From e95a4f4f52f7792927c480e76dba11c5a8cbd07e Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 30 Mar 2021 12:11:40 +0200 Subject: core: add pin_defs for MK66F18 (#12419) This is in preparation for https://github.com/qmk/qmk_firmware/pull/10171--- tmk_core/common/chibios/pin_defs.h | 81 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) (limited to 'tmk_core') diff --git a/tmk_core/common/chibios/pin_defs.h b/tmk_core/common/chibios/pin_defs.h index 86bc1076e8..c03f8de0c2 100644 --- a/tmk_core/common/chibios/pin_defs.h +++ b/tmk_core/common/chibios/pin_defs.h @@ -70,6 +70,23 @@ # define A13 PAL_LINE(GPIOA, 13) # define A14 PAL_LINE(GPIOA, 14) # define A15 PAL_LINE(GPIOA, 15) +# define A16 PAL_LINE(GPIOA, 16) +# define A17 PAL_LINE(GPIOA, 17) +# define A18 PAL_LINE(GPIOA, 18) +# define A19 PAL_LINE(GPIOA, 19) +# define A20 PAL_LINE(GPIOA, 20) +# define A21 PAL_LINE(GPIOA, 21) +# define A22 PAL_LINE(GPIOA, 22) +# define A23 PAL_LINE(GPIOA, 23) +# define A24 PAL_LINE(GPIOA, 24) +# define A25 PAL_LINE(GPIOA, 25) +# define A26 PAL_LINE(GPIOA, 26) +# define A27 PAL_LINE(GPIOA, 27) +# define A28 PAL_LINE(GPIOA, 28) +# define A29 PAL_LINE(GPIOA, 29) +# define A30 PAL_LINE(GPIOA, 30) +# define A31 PAL_LINE(GPIOA, 31) +# define A32 PAL_LINE(GPIOA, 32) # define B0 PAL_LINE(GPIOB, 0) # define B1 PAL_LINE(GPIOB, 1) # define B2 PAL_LINE(GPIOB, 2) @@ -90,6 +107,19 @@ # define B17 PAL_LINE(GPIOB, 17) # define B18 PAL_LINE(GPIOB, 18) # define B19 PAL_LINE(GPIOB, 19) +# define B20 PAL_LINE(GPIOB, 20) +# define B21 PAL_LINE(GPIOB, 21) +# define B22 PAL_LINE(GPIOB, 22) +# define B23 PAL_LINE(GPIOB, 23) +# define B24 PAL_LINE(GPIOB, 24) +# define B25 PAL_LINE(GPIOB, 25) +# define B26 PAL_LINE(GPIOB, 26) +# define B27 PAL_LINE(GPIOB, 27) +# define B28 PAL_LINE(GPIOB, 28) +# define B29 PAL_LINE(GPIOB, 29) +# define B30 PAL_LINE(GPIOB, 30) +# define B31 PAL_LINE(GPIOB, 31) +# define B32 PAL_LINE(GPIOB, 32) # define C0 PAL_LINE(GPIOC, 0) # define C1 PAL_LINE(GPIOC, 1) # define C2 PAL_LINE(GPIOC, 2) @@ -106,6 +136,23 @@ # define C13 PAL_LINE(GPIOC, 13) # define C14 PAL_LINE(GPIOC, 14) # define C15 PAL_LINE(GPIOC, 15) +# define C16 PAL_LINE(GPIOC, 16) +# define C17 PAL_LINE(GPIOC, 17) +# define C18 PAL_LINE(GPIOC, 18) +# define C19 PAL_LINE(GPIOC, 19) +# define C20 PAL_LINE(GPIOC, 20) +# define C21 PAL_LINE(GPIOC, 21) +# define C22 PAL_LINE(GPIOC, 22) +# define C23 PAL_LINE(GPIOC, 23) +# define C24 PAL_LINE(GPIOC, 24) +# define C25 PAL_LINE(GPIOC, 25) +# define C26 PAL_LINE(GPIOC, 26) +# define C27 PAL_LINE(GPIOC, 27) +# define C28 PAL_LINE(GPIOC, 28) +# define C29 PAL_LINE(GPIOC, 29) +# define C30 PAL_LINE(GPIOC, 30) +# define C31 PAL_LINE(GPIOC, 31) +# define C32 PAL_LINE(GPIOC, 32) # define D0 PAL_LINE(GPIOD, 0) # define D1 PAL_LINE(GPIOD, 1) # define D2 PAL_LINE(GPIOD, 2) @@ -122,6 +169,23 @@ # define D13 PAL_LINE(GPIOD, 13) # define D14 PAL_LINE(GPIOD, 14) # define D15 PAL_LINE(GPIOD, 15) +# define D16 PAL_LINE(GPIOD, 16) +# define D17 PAL_LINE(GPIOD, 17) +# define D18 PAL_LINE(GPIOD, 18) +# define D19 PAL_LINE(GPIOD, 19) +# define D20 PAL_LINE(GPIOD, 20) +# define D21 PAL_LINE(GPIOD, 21) +# define D22 PAL_LINE(GPIOD, 22) +# define D23 PAL_LINE(GPIOD, 23) +# define D24 PAL_LINE(GPIOD, 24) +# define D25 PAL_LINE(GPIOD, 25) +# define D26 PAL_LINE(GPIOD, 26) +# define D27 PAL_LINE(GPIOD, 27) +# define D28 PAL_LINE(GPIOD, 28) +# define D29 PAL_LINE(GPIOD, 29) +# define D30 PAL_LINE(GPIOD, 30) +# define D31 PAL_LINE(GPIOD, 31) +# define D32 PAL_LINE(GPIOD, 32) # define E0 PAL_LINE(GPIOE, 0) # define E1 PAL_LINE(GPIOE, 1) # define E2 PAL_LINE(GPIOE, 2) @@ -138,6 +202,23 @@ # define E13 PAL_LINE(GPIOE, 13) # define E14 PAL_LINE(GPIOE, 14) # define E15 PAL_LINE(GPIOE, 15) +# define E16 PAL_LINE(GPIOE, 16) +# define E17 PAL_LINE(GPIOE, 17) +# define E18 PAL_LINE(GPIOE, 18) +# define E19 PAL_LINE(GPIOE, 19) +# define E20 PAL_LINE(GPIOE, 20) +# define E21 PAL_LINE(GPIOE, 21) +# define E22 PAL_LINE(GPIOE, 22) +# define E23 PAL_LINE(GPIOE, 23) +# define E24 PAL_LINE(GPIOE, 24) +# define E25 PAL_LINE(GPIOE, 25) +# define E26 PAL_LINE(GPIOE, 26) +# define E27 PAL_LINE(GPIOE, 27) +# define E28 PAL_LINE(GPIOE, 28) +# define E29 PAL_LINE(GPIOE, 29) +# define E30 PAL_LINE(GPIOE, 30) +# define E31 PAL_LINE(GPIOE, 31) +# define E32 PAL_LINE(GPIOE, 32) # define F0 PAL_LINE(GPIOF, 0) # define F1 PAL_LINE(GPIOF, 1) # define F2 PAL_LINE(GPIOF, 2) -- cgit v1.2.3 From 64a0f5a659190518a9361e0bd2e8caff0b3354f1 Mon Sep 17 00:00:00 2001 From: Nick Brassel Date: Tue, 6 Apr 2021 16:39:15 +1000 Subject: Add support for producing UF2-format binaries. (#12435) * First stab at enabling builds of UF2-format binaries. * Add description on producing a UF2 file.--- .gitignore | 1 + Makefile | 4 +- message.mk | 2 + quantum/mcu_selection.mk | 24 ++++ tmk_core/rules.mk | 31 ++++- util/uf2conv.py | 319 +++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 373 insertions(+), 8 deletions(-) create mode 100755 util/uf2conv.py (limited to 'tmk_core') diff --git a/.gitignore b/.gitignore index d6846cf63b..518b2df83a 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ *.eep *.elf *.hex +*.uf2 *.qmk !util/bootloader.hex !quantum/tools/eeprom_reset.hex diff --git a/Makefile b/Makefile index 80e1a90a19..e007ae3679 100644 --- a/Makefile +++ b/Makefile @@ -93,8 +93,8 @@ clean: .PHONY: distclean distclean: clean - echo -n 'Deleting *.bin and *.hex ... ' - rm -f *.bin *.hex + echo -n 'Deleting *.bin, *.hex, and *.uf2 ... ' + rm -f *.bin *.hex *.uf2 echo 'done.' #Compatibility with the old make variables, anything you specify directly on the command line diff --git a/message.mk b/message.mk index 3240c041b9..c3f3919198 100644 --- a/message.mk +++ b/message.mk @@ -47,10 +47,12 @@ MSG_SIZE_AFTER = Size after: MSG_COFF = Converting to AVR COFF: MSG_EXTENDED_COFF = Converting to AVR Extended COFF: MSG_FLASH = Creating load file for flashing: +MSG_UF2 = Creating UF2 file for deployment: MSG_EEPROM = Creating load file for EEPROM: MSG_BIN = Creating binary load file for flashing: MSG_EXTENDED_LISTING = Creating Extended Listing: MSG_SYMBOL_TABLE = Creating Symbol Table: +MSG_EXECUTING = Executing: MSG_LINKING = Linking: MSG_COMPILING = Compiling: MSG_COMPILING_CXX = Compiling: diff --git a/quantum/mcu_selection.mk b/quantum/mcu_selection.mk index 53e03a8054..2e4d250089 100644 --- a/quantum/mcu_selection.mk +++ b/quantum/mcu_selection.mk @@ -139,6 +139,9 @@ ifneq ($(findstring STM32F042, $(MCU)),) # Options to pass to dfu-util when flashing DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 + + # UF2 settings + UF2_FAMILY ?= STM32F0 endif ifneq ($(findstring STM32F072, $(MCU)),) @@ -172,6 +175,9 @@ ifneq ($(findstring STM32F072, $(MCU)),) # Options to pass to dfu-util when flashing DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 + + # UF2 settings + UF2_FAMILY ?= STM32F0 endif ifneq ($(findstring STM32F103, $(MCU)),) @@ -205,6 +211,9 @@ ifneq ($(findstring STM32F103, $(MCU)),) # Options to pass to dfu-util when flashing DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 + + # UF2 settings + UF2_FAMILY ?= STM32F1 endif ifneq ($(findstring STM32F303, $(MCU)),) @@ -238,6 +247,9 @@ ifneq ($(findstring STM32F303, $(MCU)),) # Options to pass to dfu-util when flashing DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 + + # UF2 settings + UF2_FAMILY ?= STM32F3 endif ifneq ($(findstring STM32F401, $(MCU)),) @@ -271,6 +283,9 @@ ifneq ($(findstring STM32F401, $(MCU)),) # Options to pass to dfu-util when flashing DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 + + # UF2 settings + UF2_FAMILY ?= STM32F4 endif ifneq ($(findstring STM32F411, $(MCU)),) @@ -304,6 +319,9 @@ ifneq ($(findstring STM32F411, $(MCU)),) # Options to pass to dfu-util when flashing DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 + + # UF2 settings + UF2_FAMILY ?= STM32F4 endif ifneq ($(findstring STM32G431, $(MCU)),) @@ -337,6 +355,9 @@ ifneq ($(findstring STM32G431, $(MCU)),) # Options to pass to dfu-util when flashing DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 + + # UF2 settings + UF2_FAMILY ?= STM32G4 endif ifneq ($(findstring STM32G474, $(MCU)),) @@ -370,6 +391,9 @@ ifneq ($(findstring STM32G474, $(MCU)),) # Options to pass to dfu-util when flashing DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 + + # UF2 settings + UF2_FAMILY ?= STM32G4 endif ifneq (,$(filter $(MCU),at90usb162 atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 at90usb647 at90usb1286 at90usb1287)) diff --git a/tmk_core/rules.mk b/tmk_core/rules.mk index bbcfc1e4d1..8dbed35fb5 100644 --- a/tmk_core/rules.mk +++ b/tmk_core/rules.mk @@ -223,6 +223,12 @@ ifneq ($(filter Darwin FreeBSD,$(shell uname -s)),) MD5SUM = md5 endif +# UF2 format settings +# To produce a UF2 file in your build, add to your keyboard's rules.mk: +# FIRMWARE_FORMAT = uf2 +UF2CONV = $(TOP_DIR)/util/uf2conv.py +UF2_FAMILY ?= 0x0 + # Compiler flags to generate dependency files. #GENDEPFLAGS = -MMD -MP -MF .dep/$(@F).d GENDEPFLAGS = -MMD -MP -MF $(patsubst %.o,%.td,$@) @@ -255,6 +261,7 @@ DFU_SUFFIX_ARGS ?= elf: $(BUILD_DIR)/$(TARGET).elf hex: $(BUILD_DIR)/$(TARGET).hex +uf2: $(BUILD_DIR)/$(TARGET).uf2 cpfirmware: $(FIRMWARE_FORMAT) $(SILENT) || printf "Copying $(TARGET).$(FIRMWARE_FORMAT) to qmk_firmware folder" | $(AWK_CMD) $(COPY) $(BUILD_DIR)/$(TARGET).$(FIRMWARE_FORMAT) $(TARGET).$(FIRMWARE_FORMAT) && $(PRINT_OK) @@ -283,32 +290,44 @@ gccversion : # Create final output files (.hex, .eep) from ELF output file. %.hex: %.elf - @$(SILENT) || printf "$(MSG_FLASH) $@" | $(AWK_CMD) $(eval CMD=$(HEX) $< $@) + #@$(SILENT) || printf "$(MSG_EXECUTING) '$(CMD)':\n" + @$(SILENT) || printf "$(MSG_FLASH) $@" | $(AWK_CMD) + @$(BUILD_CMD) + +%.uf2: %.hex + $(eval CMD=$(UF2CONV) $(BUILD_DIR)/$(TARGET).hex -o $(BUILD_DIR)/$(TARGET).uf2 -c -f $(UF2_FAMILY) >/dev/null 2>&1) + #@$(SILENT) || printf "$(MSG_EXECUTING) '$(CMD)':\n" + @$(SILENT) || printf "$(MSG_UF2) $@" | $(AWK_CMD) @$(BUILD_CMD) %.eep: %.elf - @$(SILENT) || printf "$(MSG_EEPROM) $@" | $(AWK_CMD) $(eval CMD=$(EEP) $< $@ || exit 0) + #@$(SILENT) || printf "$(MSG_EXECUTING) '$(CMD)':\n" + @$(SILENT) || printf "$(MSG_EEPROM) $@" | $(AWK_CMD) @$(BUILD_CMD) # Create extended listing file from ELF output file. %.lss: %.elf - @$(SILENT) || printf "$(MSG_EXTENDED_LISTING) $@" | $(AWK_CMD) $(eval CMD=$(OBJDUMP) -h -S -z $< > $@) + #@$(SILENT) || printf "$(MSG_EXECUTING) '$(CMD)':\n" + @$(SILENT) || printf "$(MSG_EXTENDED_LISTING) $@" | $(AWK_CMD) @$(BUILD_CMD) # Create a symbol table from ELF output file. %.sym: %.elf - @$(SILENT) || printf "$(MSG_SYMBOL_TABLE) $@" | $(AWK_CMD) $(eval CMD=$(NM) -n $< > $@ ) + #@$(SILENT) || printf "$(MSG_EXECUTING) '$(CMD)':\n" + @$(SILENT) || printf "$(MSG_SYMBOL_TABLE) $@" | $(AWK_CMD) @$(BUILD_CMD) %.bin: %.elf - @$(SILENT) || printf "$(MSG_BIN) $@" | $(AWK_CMD) $(eval CMD=$(BIN) $< $@ || exit 0) + #@$(SILENT) || printf "$(MSG_EXECUTING) '$(CMD)':\n" + @$(SILENT) || printf "$(MSG_BIN) $@" | $(AWK_CMD) @$(BUILD_CMD) if [ ! -z "$(DFU_SUFFIX_ARGS)" ]; then \ + #$(SILENT) || printf "$(MSG_EXECUTING) '$(DFU_SUFFIX) $(DFU_SUFFIX_ARGS) -a $(BUILD_DIR)/$(TARGET).bin 1>/dev/null':\n" ;\ $(DFU_SUFFIX) $(DFU_SUFFIX_ARGS) -a $(BUILD_DIR)/$(TARGET).bin 1>/dev/null ;\ fi $(COPY) $(BUILD_DIR)/$(TARGET).bin $(TARGET).bin; @@ -476,7 +495,7 @@ $(eval $(foreach OUTPUT,$(OUTPUTS),$(shell mkdir -p $(OUTPUT) 2>/dev/null))) # Listing of phony targets. .PHONY : all dump_vars finish sizebefore sizeafter qmkversion \ -gccversion build elf hex eep lss sym coff extcoff \ +gccversion build elf hex uf2 eep lss sym coff extcoff \ clean clean_list debug gdb-config show_path \ program teensy dfu dfu-ee dfu-start \ flash dfu-split-left dfu-split-right \ diff --git a/util/uf2conv.py b/util/uf2conv.py new file mode 100755 index 0000000000..044a7f2318 --- /dev/null +++ b/util/uf2conv.py @@ -0,0 +1,319 @@ +#!/usr/bin/env python3 +import sys +import struct +import subprocess +import re +import os +import os.path +import argparse + + +UF2_MAGIC_START0 = 0x0A324655 # "UF2\n" +UF2_MAGIC_START1 = 0x9E5D5157 # Randomly selected +UF2_MAGIC_END = 0x0AB16F30 # Ditto + +families = { + 'SAMD21': 0x68ed2b88, + 'SAML21': 0x1851780a, + 'SAMD51': 0x55114460, + 'NRF52': 0x1b57745f, + 'STM32F0': 0x647824b6, + 'STM32F1': 0x5ee21072, + 'STM32F2': 0x5d1a0a2e, + 'STM32F3': 0x6b846188, + 'STM32F4': 0x57755a57, + 'STM32F7': 0x53b80f00, + 'STM32G0': 0x300f5633, + 'STM32G4': 0x4c71240a, + 'STM32H7': 0x6db66082, + 'STM32L0': 0x202e3a91, + 'STM32L1': 0x1e1f432d, + 'STM32L4': 0x00ff6919, + 'STM32L5': 0x04240bdf, + 'STM32WB': 0x70d16653, + 'STM32WL': 0x21460ff0, + 'ATMEGA32': 0x16573617, + 'MIMXRT10XX': 0x4FB2D5BD, + 'LPC55': 0x2abc77ec, + 'GD32F350': 0x31D228C6, + 'ESP32S2': 0xbfdd4eee, + 'RP2040': 0xe48bff56 +} + +INFO_FILE = "/INFO_UF2.TXT" + +appstartaddr = 0x2000 +familyid = 0x0 + + +def is_uf2(buf): + w = struct.unpack(" 476: + assert False, "Invalid UF2 data size at " + ptr + newaddr = hd[3] + if curraddr == None: + appstartaddr = newaddr + curraddr = newaddr + padding = newaddr - curraddr + if padding < 0: + assert False, "Block out of order at " + ptr + if padding > 10*1024*1024: + assert False, "More than 10M of padding needed at " + ptr + if padding % 4 != 0: + assert False, "Non-word padding size at " + ptr + while padding > 0: + padding -= 4 + outp += b"\x00\x00\x00\x00" + outp.append(block[32 : 32 + datalen]) + curraddr = newaddr + datalen + return b"".join(outp) + +def convert_to_carray(file_content): + outp = "const unsigned long bindata_len = %d;\n" % len(file_content) + outp += "const unsigned char bindata[] __attribute__((aligned(16))) = {" + for i in range(len(file_content)): + if i % 16 == 0: + outp += "\n" + outp += "0x%02x, " % file_content[i] + outp += "\n};\n" + return bytes(outp, "utf-8") + +def convert_to_uf2(file_content): + global familyid + datapadding = b"" + while len(datapadding) < 512 - 256 - 32 - 4: + datapadding += b"\x00\x00\x00\x00" + numblocks = (len(file_content) + 255) // 256 + outp = [] + for blockno in range(numblocks): + ptr = 256 * blockno + chunk = file_content[ptr:ptr + 256] + flags = 0x0 + if familyid: + flags |= 0x2000 + hd = struct.pack(b"= 3 and words[1] == "2" and words[2] == "FAT": + drives.append(words[0]) + else: + rootpath = "/media" + if sys.platform == "darwin": + rootpath = "/Volumes" + elif sys.platform == "linux": + tmp = rootpath + "/" + os.environ["USER"] + if os.path.isdir(tmp): + rootpath = tmp + for d in os.listdir(rootpath): + drives.append(os.path.join(rootpath, d)) + + + def has_info(d): + try: + return os.path.isfile(d + INFO_FILE) + except: + return False + + return list(filter(has_info, drives)) + + +def board_id(path): + with open(path + INFO_FILE, mode='r') as file: + file_content = file.read() + return re.search("Board-ID: ([^\r\n]*)", file_content).group(1) + + +def list_drives(): + for d in get_drives(): + print(d, board_id(d)) + + +def write_file(name, buf): + with open(name, "wb") as f: + f.write(buf) + print("Wrote %d bytes to %s" % (len(buf), name)) + + +def main(): + global appstartaddr, familyid + def error(msg): + print(msg) + sys.exit(1) + parser = argparse.ArgumentParser(description='Convert to UF2 or flash directly.') + parser.add_argument('input', metavar='INPUT', type=str, nargs='?', + help='input file (HEX, BIN or UF2)') + parser.add_argument('-b' , '--base', dest='base', type=str, + default="0x2000", + help='set base address of application for BIN format (default: 0x2000)') + parser.add_argument('-o' , '--output', metavar="FILE", dest='output', type=str, + help='write output to named file; defaults to "flash.uf2" or "flash.bin" where sensible') + parser.add_argument('-d' , '--device', dest="device_path", + help='select a device path to flash') + parser.add_argument('-l' , '--list', action='store_true', + help='list connected devices') + parser.add_argument('-c' , '--convert', action='store_true', + help='do not flash, just convert') + parser.add_argument('-D' , '--deploy', action='store_true', + help='just flash, do not convert') + parser.add_argument('-f' , '--family', dest='family', type=str, + default="0x0", + help='specify familyID - number or name (default: 0x0)') + parser.add_argument('-C' , '--carray', action='store_true', + help='convert binary file to a C array, not UF2') + args = parser.parse_args() + appstartaddr = int(args.base, 0) + + if args.family.upper() in families: + familyid = families[args.family.upper()] + else: + try: + familyid = int(args.family, 0) + except ValueError: + error("Family ID needs to be a number or one of: " + ", ".join(families.keys())) + + if args.list: + list_drives() + else: + if not args.input: + error("Need input file") + with open(args.input, mode='rb') as f: + inpbuf = f.read() + from_uf2 = is_uf2(inpbuf) + ext = "uf2" + if args.deploy: + outbuf = inpbuf + elif from_uf2: + outbuf = convert_from_uf2(inpbuf) + ext = "bin" + elif is_hex(inpbuf): + outbuf = convert_from_hex_to_uf2(inpbuf.decode("utf-8")) + elif args.carray: + outbuf = convert_to_carray(inpbuf) + ext = "h" + else: + outbuf = convert_to_uf2(inpbuf) + print("Converting to %s, output size: %d, start address: 0x%x" % + (ext, len(outbuf), appstartaddr)) + if args.convert or ext != "uf2": + drives = [] + if args.output == None: + args.output = "flash." + ext + else: + drives = get_drives() + + if args.output: + write_file(args.output, outbuf) + else: + if len(drives) == 0: + error("No drive to deploy.") + for d in drives: + print("Flashing %s (%s)" % (d, board_id(d))) + write_file(d + "/NEW.UF2", outbuf) + + +if __name__ == "__main__": + main() -- cgit v1.2.3 From ce99f98bb5217ede628cfbf7e20924346b4279da Mon Sep 17 00:00:00 2001 From: Ryan Date: Tue, 13 Apr 2021 19:51:03 +1000 Subject: LED Matrix: suspend code (#12509) --- quantum/led_matrix.c | 57 ++++++++++++++++++++++----------------- quantum/led_matrix.h | 7 +++-- tmk_core/common/avr/suspend.c | 3 +++ tmk_core/common/chibios/suspend.c | 6 +++++ tmk_core/common/keyboard.c | 3 +++ 5 files changed, 49 insertions(+), 27 deletions(-) (limited to 'tmk_core') diff --git a/quantum/led_matrix.c b/quantum/led_matrix.c index e133764556..5258b3acfd 100644 --- a/quantum/led_matrix.c +++ b/quantum/led_matrix.c @@ -27,8 +27,6 @@ #include -led_eeconfig_t led_matrix_eeconfig; - #ifndef MAX # define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) #endif @@ -74,7 +72,9 @@ led_eeconfig_t led_matrix_eeconfig; # define LED_MATRIX_STARTUP_SPD UINT8_MAX / 2 #endif -bool g_suspend_state = false; +// globals +bool g_suspend_state = false; +led_eeconfig_t led_matrix_eeconfig; // TODO: would like to prefix this with g_ for global consistancy, do this in another pr // Global tick at 20 Hz uint32_t g_tick = 0; @@ -139,10 +139,10 @@ void led_matrix_set_value_all(uint8_t value) { #endif } -bool process_led_matrix(uint16_t keycode, keyrecord_t *record) { - if (record->event.pressed) { +void process_led_matrix(uint8_t row, uint8_t col, bool pressed) { + if (pressed) { uint8_t led[8]; - uint8_t led_count = led_matrix_map_row_column_to_led(record->event.key.row, record->event.key.col, led); + uint8_t led_count = led_matrix_map_row_column_to_led(row, col, led); if (led_count > 0) { for (uint8_t i = LED_HITS_TO_REMEMBER; i > 1; i--) { g_last_led_hit[i - 1] = g_last_led_hit[i - 2]; @@ -155,35 +155,24 @@ bool process_led_matrix(uint16_t keycode, keyrecord_t *record) { } else { #ifdef LED_MATRIX_KEYRELEASES uint8_t led[8]; - uint8_t led_count = led_matrix_map_row_column_to_led(record->event.key.row, record->event.key.col, led); + uint8_t led_count = led_matrix_map_row_column_to_led(row, .col, led); for (uint8_t i = 0; i < led_count; i++) g_key_hit[led[i]] = 255; g_any_key_hit = 255; #endif } - return true; } -void led_matrix_set_suspend_state(bool state) { - if (LED_DISABLE_WHEN_USB_SUSPENDED && state) { - led_matrix_set_value_all(0); // turn off all LEDs when suspending - } - g_suspend_state = state; -} - -bool led_matrix_get_suspend_state(void) { return g_suspend_state; } - -// All LEDs off -void led_matrix_all_off(void) { led_matrix_set_index_value_all(0); } +static void led_matrix_none(void) { led_matrix_set_value_all(0); } // Uniform brightness -void led_matrix_uniform_brightness(void) { led_matrix_set_index_value_all(led_matrix_eeconfig.val); } +void led_matrix_uniform_brightness(void) { led_matrix_set_value_all(led_matrix_eeconfig.val); } void led_matrix_custom(void) {} void led_matrix_task(void) { if (!led_matrix_eeconfig.enable) { - led_matrix_all_off(); + led_matrix_none(); led_matrix_indicators(); return; } @@ -203,13 +192,23 @@ void led_matrix_task(void) { // Ideally we would also stop sending zeros to the LED driver PWM buffers // while suspended and just do a software shutdown. This is a cheap hack for now. - bool suspend_backlight = ((g_suspend_state && LED_DISABLE_WHEN_USB_SUSPENDED) || (LED_DISABLE_TIMEOUT > 0 && g_any_key_hit > LED_DISABLE_TIMEOUT)); - uint8_t effect = suspend_backlight ? 0 : led_matrix_eeconfig.mode; + bool suspend_backlight = +#if LED_DISABLE_WHEN_USB_SUSPENDED == true + g_suspend_state || +#endif // LED_DISABLE_WHEN_USB_SUSPENDED == true +#if LED_DISABLE_TIMEOUT > 0 + (g_any_key_hit > (uint32_t)LED_DISABLE_TIMEOUT) || +#endif // LED_DISABLE_TIMEOUT > 0 + false; + + uint8_t effect = suspend_backlight || !led_matrix_eeconfig.enable ? 0 : led_matrix_eeconfig.mode; // this gets ticked at 20 Hz. // each effect can opt to do calculations // and/or request PWM buffer updates. switch (effect) { + case LED_MATRIX_NONE: + led_matrix_none(); case LED_MATRIX_UNIFORM_BRIGHTNESS: led_matrix_uniform_brightness(); break; @@ -218,7 +217,7 @@ void led_matrix_task(void) { break; } - if (!suspend_backlight) { + if (effect) { led_matrix_indicators(); } @@ -257,10 +256,18 @@ void led_matrix_init(void) { dprintf("led_matrix_init_drivers led_matrix_eeconfig.mode = 0. Write default values to EEPROM.\n"); eeconfig_update_led_matrix_default(); } - eeconfig_debug_led_matrix(); // display current eeprom values } +void led_matrix_set_suspend_state(bool state) { + if (LED_DISABLE_WHEN_USB_SUSPENDED && state) { + led_matrix_set_value_all(0); // turn off all LEDs when suspending + } + g_suspend_state = state; +} + +bool led_matrix_get_suspend_state(void) { return g_suspend_state; } + void led_matrix_toggle_eeprom_helper(bool write_to_eeprom) { led_matrix_eeconfig.enable ^= 1; if (write_to_eeprom) { diff --git a/quantum/led_matrix.h b/quantum/led_matrix.h index ba8f0279a6..48c9483b2d 100644 --- a/quantum/led_matrix.h +++ b/quantum/led_matrix.h @@ -48,8 +48,11 @@ #endif enum led_matrix_effects { - LED_MATRIX_UNIFORM_BRIGHTNESS = 1, + LED_MATRIX_NONE = 0, + + LED_MATRIX_UNIFORM_BRIGHTNESS, // All new effects go above this line + LED_MATRIX_EFFECT_MAX }; @@ -63,7 +66,7 @@ uint8_t led_matrix_map_row_column_to_led(uint8_t row, uint8_t column, uint8_t *l void led_matrix_set_value(int index, uint8_t value); void led_matrix_set_value_all(uint8_t value); -bool process_led_matrix(uint16_t keycode, keyrecord_t *record); +void process_led_matrix(uint8_t row, uint8_t col, bool pressed); void led_matrix_task(void); diff --git a/tmk_core/common/avr/suspend.c b/tmk_core/common/avr/suspend.c index d52c8ac410..96b19a77fd 100644 --- a/tmk_core/common/avr/suspend.c +++ b/tmk_core/common/avr/suspend.c @@ -28,6 +28,9 @@ # include "rgblight.h" #endif +#ifdef LED_MATRIX_ENABLE +# include "led_matrix.h" +#endif #ifdef RGB_MATRIX_ENABLE # include "rgb_matrix.h" #endif diff --git a/tmk_core/common/chibios/suspend.c b/tmk_core/common/chibios/suspend.c index 17f024caba..b3949185e9 100644 --- a/tmk_core/common/chibios/suspend.c +++ b/tmk_core/common/chibios/suspend.c @@ -24,6 +24,9 @@ # include "rgblight.h" #endif +#ifdef LED_MATRIX_ENABLE +# include "led_matrix.h" +#endif #ifdef RGB_MATRIX_ENABLE # include "rgb_matrix.h" #endif @@ -57,6 +60,9 @@ void suspend_power_down(void) { backlight_set(0); #endif +#ifdef LED_MATRIX_ENABLE + led_matrix_task(); +#endif #ifdef RGB_MATRIX_ENABLE rgb_matrix_task(); #endif diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c index e473806b21..132affe7a8 100644 --- a/tmk_core/common/keyboard.c +++ b/tmk_core/common/keyboard.c @@ -330,6 +330,9 @@ void keyboard_init(void) { * This is differnet than keycode events as no layer processing, or filtering occurs. */ void switch_events(uint8_t row, uint8_t col, bool pressed) { +#if defined(LED_MATRIX_ENABLE) + process_led_matrix(row, col, pressed); +#endif #if defined(RGB_MATRIX_ENABLE) process_rgb_matrix(row, col, pressed); #endif -- cgit v1.2.3 From dcb8407ed694505403df010852d497f0bb33c607 Mon Sep 17 00:00:00 2001 From: Purdea Andrei Date: Mon, 19 Apr 2021 19:33:24 +0300 Subject: Apply the "NO_LIMITED_CONTROLLER_CONNECT" fix to atmega16u2 (#12482) Co-authored-by: Ryan --- tmk_core/protocol/lufa.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tmk_core') diff --git a/tmk_core/protocol/lufa.mk b/tmk_core/protocol/lufa.mk index 9d9fb728b1..514d5fac41 100644 --- a/tmk_core/protocol/lufa.mk +++ b/tmk_core/protocol/lufa.mk @@ -67,8 +67,8 @@ LUFA_OPTS += -DFIXED_CONTROL_ENDPOINT_SIZE=8 LUFA_OPTS += -DFIXED_CONTROL_ENDPOINT_SIZE=8 LUFA_OPTS += -DFIXED_NUM_CONFIGURATIONS=1 -# Remote wakeup fix for ATmega32U2 https://github.com/tmk/tmk_keyboard/issues/361 -ifeq ($(MCU),atmega32u2) +# Remote wakeup fix for ATmega16/32U2 https://github.com/tmk/tmk_keyboard/issues/361 +ifneq (,$(filter $(MCU), at90usb162 atmega16u2 atmega32u2)) LUFA_OPTS += -DNO_LIMITED_CONTROLLER_CONNECT endif -- cgit v1.2.3 From 891d18d3565090abd5f218a8787acc3e25349b73 Mon Sep 17 00:00:00 2001 From: Nick Brassel Date: Sun, 25 Apr 2021 13:40:56 +1000 Subject: Add initial support for tinyuf2 bootloader (when hosted on F411 blackpill) (#12600) * Add support for jumping to tinyuf2 bootloader. Adds blackpill UF2 example. * Update flashing.md * Update chconf.h * Update config.h * Update halconf.h * Update mcuconf.h--- bootloader.mk | 3 + data/schemas/keyboard.jsonschema | 2 +- docs/flashing.md | 26 +++++++ .../onekey/blackpill_f411_tinyuf2/chconf.h | 21 +++++ .../onekey/blackpill_f411_tinyuf2/config.h | 31 ++++++++ .../onekey/blackpill_f411_tinyuf2/halconf.h | 22 ++++++ .../onekey/blackpill_f411_tinyuf2/mcuconf.h | 24 ++++++ .../onekey/blackpill_f411_tinyuf2/readme.md | 9 +++ .../onekey/blackpill_f411_tinyuf2/rules.mk | 10 +++ .../BLACKPILL_STM32_F411/ld/STM32F411xC_tinyuf2.ld | 89 ++++++++++++++++++++++ .../BLACKPILL_STM32_F411/ld/STM32F411xE_tinyuf2.ld | 89 ++++++++++++++++++++++ quantum/mcu_selection.mk | 7 +- tmk_core/chibios.mk | 2 + tmk_core/common/chibios/bootloader.c | 17 ++++- 14 files changed, 349 insertions(+), 3 deletions(-) create mode 100644 keyboards/handwired/onekey/blackpill_f411_tinyuf2/chconf.h create mode 100755 keyboards/handwired/onekey/blackpill_f411_tinyuf2/config.h create mode 100644 keyboards/handwired/onekey/blackpill_f411_tinyuf2/halconf.h create mode 100755 keyboards/handwired/onekey/blackpill_f411_tinyuf2/mcuconf.h create mode 100755 keyboards/handwired/onekey/blackpill_f411_tinyuf2/readme.md create mode 100755 keyboards/handwired/onekey/blackpill_f411_tinyuf2/rules.mk create mode 100644 platforms/chibios/BLACKPILL_STM32_F411/ld/STM32F411xC_tinyuf2.ld create mode 100644 platforms/chibios/BLACKPILL_STM32_F411/ld/STM32F411xE_tinyuf2.ld (limited to 'tmk_core') diff --git a/bootloader.mk b/bootloader.mk index fd76446e99..ead52cbe3d 100644 --- a/bootloader.mk +++ b/bootloader.mk @@ -137,3 +137,6 @@ ifeq ($(strip $(BOOTLOADER)), stm32duino) DFU_ARGS = -d 1EAF:0003 -a 2 -R DFU_SUFFIX_ARGS = -v 1EAF -p 0003 endif +ifeq ($(strip $(BOOTLOADER)), tinyuf2) + OPT_DEFS += -DBOOTLOADER_TINYUF2 +endif diff --git a/data/schemas/keyboard.jsonschema b/data/schemas/keyboard.jsonschema index 3034242fd9..276f66413e 100644 --- a/data/schemas/keyboard.jsonschema +++ b/data/schemas/keyboard.jsonschema @@ -34,7 +34,7 @@ }, "bootloader": { "type": "string", - "enum": ["atmel-dfu", "bootloadHID", "caterina", "halfkay", "kiibohd", "lufa-dfu", "lufa-ms", "micronucleus", "qmk-dfu", "stm32-dfu", "stm32duino", "unknown", "USBasp"] + "enum": ["atmel-dfu", "bootloadHID", "caterina", "halfkay", "kiibohd", "lufa-dfu", "lufa-ms", "micronucleus", "qmk-dfu", "stm32-dfu", "stm32duino", "unknown", "USBasp", "tinyuf2"] }, "diode_direction": { "type": "string", diff --git a/docs/flashing.md b/docs/flashing.md index 7804a6bad8..83c97444e1 100644 --- a/docs/flashing.md +++ b/docs/flashing.md @@ -249,3 +249,29 @@ Flashing sequence: 2. Wait for the OS to detect the device 3. Flash a .bin file 4. Reset the device into application mode (may be done automatically) + +## tinyuf2 + +Keyboards may opt into supporting the tinyuf2 bootloader. This is currently only supported on the F411 blackpill. + +The `rules.mk` setting for this bootloader is `tinyuf2`, and can be specified at the keymap or user level. + +To ensure compatibility with the tinyuf2 bootloader, make sure this block is present in your `rules.mk`: + +```make +# Bootloader selection +BOOTLOADER = tinyuf2 +``` + +Compatible flashers: + +* Any application able to copy a file from one place to another, such as _macOS Finder_ or _Windows Explorer_. + +Flashing sequence: + +1. Enter the bootloader using any of the following methods: + * Tap the `RESET` keycode + * Double-tap the `nRST` button on the PCB. +2. Wait for the OS to detect the device +3. Copy the .uf2 file to the new USB disk +4. Wait for the keyboard to become available diff --git a/keyboards/handwired/onekey/blackpill_f411_tinyuf2/chconf.h b/keyboards/handwired/onekey/blackpill_f411_tinyuf2/chconf.h new file mode 100644 index 0000000000..3d9a393638 --- /dev/null +++ b/keyboards/handwired/onekey/blackpill_f411_tinyuf2/chconf.h @@ -0,0 +1,21 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#define CH_CFG_ST_FREQUENCY 10000 + +#include_next diff --git a/keyboards/handwired/onekey/blackpill_f411_tinyuf2/config.h b/keyboards/handwired/onekey/blackpill_f411_tinyuf2/config.h new file mode 100755 index 0000000000..95e99aacc1 --- /dev/null +++ b/keyboards/handwired/onekey/blackpill_f411_tinyuf2/config.h @@ -0,0 +1,31 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "config_common.h" + +#define MATRIX_COL_PINS { B0 } +#define MATRIX_ROW_PINS { A7 } +#define UNUSED_PINS + +#define BACKLIGHT_PIN A0 +#define BACKLIGHT_PWM_DRIVER PWMD5 +#define BACKLIGHT_PWM_CHANNEL 1 + +#define RGB_DI_PIN A1 + +#define ADC_PIN A0 diff --git a/keyboards/handwired/onekey/blackpill_f411_tinyuf2/halconf.h b/keyboards/handwired/onekey/blackpill_f411_tinyuf2/halconf.h new file mode 100644 index 0000000000..e15870984f --- /dev/null +++ b/keyboards/handwired/onekey/blackpill_f411_tinyuf2/halconf.h @@ -0,0 +1,22 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 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 . + */ + +#pragma once + +#define HAL_USE_I2C TRUE +#define HAL_USE_PWM TRUE + +#include_next diff --git a/keyboards/handwired/onekey/blackpill_f411_tinyuf2/mcuconf.h b/keyboards/handwired/onekey/blackpill_f411_tinyuf2/mcuconf.h new file mode 100755 index 0000000000..ad8aecdb10 --- /dev/null +++ b/keyboards/handwired/onekey/blackpill_f411_tinyuf2/mcuconf.h @@ -0,0 +1,24 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#include_next "mcuconf.h" + +#undef STM32_I2C_USE_I2C1 +#define STM32_I2C_USE_I2C1 TRUE + +#undef STM32_PWM_USE_TIM5 +#define STM32_PWM_USE_TIM5 TRUE diff --git a/keyboards/handwired/onekey/blackpill_f411_tinyuf2/readme.md b/keyboards/handwired/onekey/blackpill_f411_tinyuf2/readme.md new file mode 100755 index 0000000000..ff43658f4c --- /dev/null +++ b/keyboards/handwired/onekey/blackpill_f411_tinyuf2/readme.md @@ -0,0 +1,9 @@ +# f411 blackpill onekey + +Supported Hardware: *STM32F411CEU6 WeAct v1.3*. + +To trigger keypress, short together pins *B0* and *A7*. + +This variant requires the TinyUF2 bootloader to be installed. This can be downloaded from the [tinyuf2 releases page](https://github.com/adafruit/tinyuf2/releases). The F401 blackpill binary works for both F401- and F411-based blackpill devices. + +Double-tap reset to enter bootloader mode. Copy the built uf2 file to the device by dragging the file to the new USB disk. \ No newline at end of file diff --git a/keyboards/handwired/onekey/blackpill_f411_tinyuf2/rules.mk b/keyboards/handwired/onekey/blackpill_f411_tinyuf2/rules.mk new file mode 100755 index 0000000000..ec38577b2b --- /dev/null +++ b/keyboards/handwired/onekey/blackpill_f411_tinyuf2/rules.mk @@ -0,0 +1,10 @@ +# MCU name +MCU = STM32F411 + +# Build Options +# change yes to no to disable +# +KEYBOARD_SHARED_EP = yes + +# We want to use the tinyuf2 bootloader... +BOOTLOADER = tinyuf2 \ No newline at end of file diff --git a/platforms/chibios/BLACKPILL_STM32_F411/ld/STM32F411xC_tinyuf2.ld b/platforms/chibios/BLACKPILL_STM32_F411/ld/STM32F411xC_tinyuf2.ld new file mode 100644 index 0000000000..82253d3de5 --- /dev/null +++ b/platforms/chibios/BLACKPILL_STM32_F411/ld/STM32F411xC_tinyuf2.ld @@ -0,0 +1,89 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + 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 License 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. +*/ + +/* + * STM32F411xC memory setup. + */ +MEMORY +{ + flash0 (rx) : org = 0x08000000 + 64k, len = 256k - 64k /* tinyuf2 bootloader requires app to be located at 64k offset for this MCU */ + flash1 (rx) : org = 0x00000000, len = 0 + flash2 (rx) : org = 0x00000000, len = 0 + flash3 (rx) : org = 0x00000000, len = 0 + flash4 (rx) : org = 0x00000000, len = 0 + flash5 (rx) : org = 0x00000000, len = 0 + flash6 (rx) : org = 0x00000000, len = 0 + flash7 (rx) : org = 0x00000000, len = 0 + ram0 (wx) : org = 0x20000000, len = 128k + ram1 (wx) : org = 0x00000000, len = 0 + ram2 (wx) : org = 0x00000000, len = 0 + ram3 (wx) : org = 0x00000000, len = 0 + ram4 (wx) : org = 0x00000000, len = 0 + ram5 (wx) : org = 0x00000000, len = 0 + ram6 (wx) : org = 0x00000000, len = 0 + ram7 (wx) : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash0); +REGION_ALIAS("VECTORS_FLASH_LMA", flash0); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash0); +REGION_ALIAS("XTORS_FLASH_LMA", flash0); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash0); +REGION_ALIAS("TEXT_FLASH_LMA", flash0); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash0); +REGION_ALIAS("RODATA_FLASH_LMA", flash0); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash0); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash0); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash0); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* Generic rules inclusion.*/ +INCLUDE rules.ld + +/* TinyUF2 bootloader reset support */ +_board_dfu_dbl_tap = ORIGIN(ram0) + 64k - 4; /* this is based off the linker file for tinyuf2 */ + diff --git a/platforms/chibios/BLACKPILL_STM32_F411/ld/STM32F411xE_tinyuf2.ld b/platforms/chibios/BLACKPILL_STM32_F411/ld/STM32F411xE_tinyuf2.ld new file mode 100644 index 0000000000..1656c67bf7 --- /dev/null +++ b/platforms/chibios/BLACKPILL_STM32_F411/ld/STM32F411xE_tinyuf2.ld @@ -0,0 +1,89 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + 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 License 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. +*/ + +/* + * STM32F411xE memory setup. + */ +MEMORY +{ + flash0 (rx) : org = 0x08000000 + 64k, len = 512k - 64k /* tinyuf2 bootloader requires app to be located at 64k offset for this MCU */ + flash1 (rx) : org = 0x00000000, len = 0 + flash2 (rx) : org = 0x00000000, len = 0 + flash3 (rx) : org = 0x00000000, len = 0 + flash4 (rx) : org = 0x00000000, len = 0 + flash5 (rx) : org = 0x00000000, len = 0 + flash6 (rx) : org = 0x00000000, len = 0 + flash7 (rx) : org = 0x00000000, len = 0 + ram0 (wx) : org = 0x20000000, len = 128k + ram1 (wx) : org = 0x00000000, len = 0 + ram2 (wx) : org = 0x00000000, len = 0 + ram3 (wx) : org = 0x00000000, len = 0 + ram4 (wx) : org = 0x00000000, len = 0 + ram5 (wx) : org = 0x00000000, len = 0 + ram6 (wx) : org = 0x00000000, len = 0 + ram7 (wx) : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash0); +REGION_ALIAS("VECTORS_FLASH_LMA", flash0); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash0); +REGION_ALIAS("XTORS_FLASH_LMA", flash0); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash0); +REGION_ALIAS("TEXT_FLASH_LMA", flash0); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash0); +REGION_ALIAS("RODATA_FLASH_LMA", flash0); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash0); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash0); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash0); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* Generic rules inclusion.*/ +INCLUDE rules.ld + +/* TinyUF2 bootloader reset support */ +_board_dfu_dbl_tap = ORIGIN(ram0) + 64k - 4; /* this is based off the linker file for tinyuf2 */ + diff --git a/quantum/mcu_selection.mk b/quantum/mcu_selection.mk index 2e4d250089..437d354fbe 100644 --- a/quantum/mcu_selection.mk +++ b/quantum/mcu_selection.mk @@ -304,7 +304,12 @@ ifneq ($(findstring STM32F411, $(MCU)),) # Linker script to use # - it should exist either in /os/common/ports/ARMCMx/compilers/GCC/ld/ # or /ld/ - MCU_LDSCRIPT ?= STM32F411xE + ifeq ($(strip $(BOOTLOADER)), tinyuf2) + MCU_LDSCRIPT ?= STM32F411xE_tinyuf2 + FIRMWARE_FORMAT ?= uf2 + else + MCU_LDSCRIPT ?= STM32F411xE + endif # Startup code to use # - it should exist in /os/common/startup/ARMCMx/compilers/GCC/mk/ diff --git a/tmk_core/chibios.mk b/tmk_core/chibios.mk index 40595a1e3b..cdf9ba6495 100644 --- a/tmk_core/chibios.mk +++ b/tmk_core/chibios.mk @@ -190,6 +190,8 @@ else ifneq ("$(wildcard $(KEYBOARD_PATH_2)/ld/$(MCU_LDSCRIPT).ld)","") LDSCRIPT = $(KEYBOARD_PATH_2)/ld/$(MCU_LDSCRIPT).ld else ifneq ("$(wildcard $(KEYBOARD_PATH_1)/ld/$(MCU_LDSCRIPT).ld)","") LDSCRIPT = $(KEYBOARD_PATH_1)/ld/$(MCU_LDSCRIPT).ld +else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/$(BOARD)/ld/$(MCU_LDSCRIPT).ld)","") + LDSCRIPT = $(TOP_DIR)/platforms/chibios/$(BOARD)/ld/$(MCU_LDSCRIPT).ld else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/common/ld/$(MCU_LDSCRIPT).ld)","") LDSCRIPT = $(TOP_DIR)/platforms/chibios/common/ld/$(MCU_LDSCRIPT).ld else ifneq ("$(wildcard $(STARTUPLD_CONTRIB)/$(MCU_LDSCRIPT).ld)","") diff --git a/tmk_core/common/chibios/bootloader.c b/tmk_core/common/chibios/bootloader.c index 4a175a6283..f91ac7d9eb 100644 --- a/tmk_core/common/chibios/bootloader.c +++ b/tmk_core/common/chibios/bootloader.c @@ -13,7 +13,22 @@ # define STM32_BOOTLOADER_DUAL_BANK FALSE #endif -#if STM32_BOOTLOADER_DUAL_BANK +#ifdef BOOTLOADER_TINYUF2 + +# define DBL_TAP_MAGIC 0xf01669ef // From tinyuf2's board_api.h + +// defined by linker script +extern uint32_t _board_dfu_dbl_tap[]; +# define DBL_TAP_REG _board_dfu_dbl_tap[0] + +void bootloader_jump(void) { + DBL_TAP_REG = DBL_TAP_MAGIC; + NVIC_SystemReset(); +} + +void enter_bootloader_mode_if_requested(void) { /* not needed, no two-stage reset */ } + +#elif STM32_BOOTLOADER_DUAL_BANK // Need pin definitions # include "config_common.h" -- cgit v1.2.3 From 412e7a03e49d044a2dea0fb38b05fb24c8d6eabe Mon Sep 17 00:00:00 2001 From: Purdea Andrei Date: Sun, 25 Apr 2021 11:57:49 +0300 Subject: eeprom driver: Refactor where eeprom driver initialisation (and EEPROM emulation initialisation) occurs to make it non-target-specific. (#12671) --- tmk_core/common/keyboard.c | 12 ++++++++++++ tmk_core/protocol/chibios/main.c | 13 ------------- 2 files changed, 12 insertions(+), 13 deletions(-) (limited to 'tmk_core') diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c index 132affe7a8..24baf41c00 100644 --- a/tmk_core/common/keyboard.c +++ b/tmk_core/common/keyboard.c @@ -94,6 +94,12 @@ along with this program. If not, see . #ifdef DIP_SWITCH_ENABLE # include "dip_switch.h" #endif +#ifdef STM32_EEPROM_ENABLE +# include "eeprom_stm32.h" +#endif +#ifdef EEPROM_DRIVER +# include "eeprom_driver.h" +#endif static uint32_t last_input_modification_time = 0; uint32_t last_input_activity_time(void) { return last_input_modification_time; } @@ -231,6 +237,12 @@ void keyboard_setup(void) { disable_jtag(); #endif print_set_sendchar(sendchar); +#ifdef STM32_EEPROM_ENABLE + EEPROM_Init(); +#endif +#ifdef EEPROM_DRIVER + eeprom_driver_init(); +#endif matrix_setup(); keyboard_pre_init_kb(); } diff --git a/tmk_core/protocol/chibios/main.c b/tmk_core/protocol/chibios/main.c index 63e4c99d21..e2ec011186 100644 --- a/tmk_core/protocol/chibios/main.c +++ b/tmk_core/protocol/chibios/main.c @@ -51,12 +51,6 @@ #ifdef MIDI_ENABLE # include "qmk_midi.h" #endif -#ifdef STM32_EEPROM_ENABLE -# include "eeprom_stm32.h" -#endif -#ifdef EEPROM_DRIVER -# include "eeprom_driver.h" -#endif #include "suspend.h" #include "wait.h" @@ -150,13 +144,6 @@ int main(void) { halInit(); chSysInit(); -#ifdef STM32_EEPROM_ENABLE - EEPROM_Init(); -#endif -#ifdef EEPROM_DRIVER - eeprom_driver_init(); -#endif - // TESTING // chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL); -- cgit v1.2.3 From 8c12fa2e59583b22969aea2c6eeab054a23ea064 Mon Sep 17 00:00:00 2001 From: github-actions[bot] Date: Sun, 25 Apr 2021 19:00:22 +1000 Subject: Format code according to conventions (#12682) Co-authored-by: QMK Bot --- tmk_core/common/chibios/bootloader.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'tmk_core') diff --git a/tmk_core/common/chibios/bootloader.c b/tmk_core/common/chibios/bootloader.c index f91ac7d9eb..11f7abf432 100644 --- a/tmk_core/common/chibios/bootloader.c +++ b/tmk_core/common/chibios/bootloader.c @@ -26,7 +26,8 @@ void bootloader_jump(void) { NVIC_SystemReset(); } -void enter_bootloader_mode_if_requested(void) { /* not needed, no two-stage reset */ } +void enter_bootloader_mode_if_requested(void) { /* not needed, no two-stage reset */ +} #elif STM32_BOOTLOADER_DUAL_BANK -- cgit v1.2.3 From d8167779cdfb243cb140782210d2cc6a7cb9b123 Mon Sep 17 00:00:00 2001 From: Drashna Jaelre Date: Wed, 28 Apr 2021 19:39:54 -0700 Subject: Change RGB/LED Matrix to use a simple define for USB suspend (#12697) --- docs/feature_rgb_matrix.md | 2 +- keyboards/mt64rgb/keymaps/default/keymap.c | 32 +++++++++++++++--------------- keyboards/mt84/keymaps/default/keymap.c | 30 +++++++++++++--------------- quantum/led_matrix.c | 18 ++++++++--------- quantum/led_matrix.h | 1 - quantum/rgb_matrix.c | 18 ++++++++--------- quantum/rgb_matrix.h | 1 - tmk_core/common/avr/suspend.c | 7 +++++++ tmk_core/common/chibios/suspend.c | 6 ++++++ 9 files changed, 62 insertions(+), 53 deletions(-) (limited to 'tmk_core') diff --git a/docs/feature_rgb_matrix.md b/docs/feature_rgb_matrix.md index 046b1f17fa..63ff7d6ad6 100644 --- a/docs/feature_rgb_matrix.md +++ b/docs/feature_rgb_matrix.md @@ -437,7 +437,7 @@ These are defined in [`rgblight_list.h`](https://github.com/qmk/qmk_firmware/blo #define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses) #define RGB_DISABLE_TIMEOUT 0 // number of milliseconds to wait until rgb automatically turns off #define RGB_DISABLE_AFTER_TIMEOUT 0 // OBSOLETE: number of ticks to wait until disabling effects -#define RGB_DISABLE_WHEN_USB_SUSPENDED false // turn off effects when suspended +#define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended #define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness) #define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness) #define RGB_MATRIX_MAXIMUM_BRIGHTNESS 200 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255 diff --git a/keyboards/mt64rgb/keymaps/default/keymap.c b/keyboards/mt64rgb/keymaps/default/keymap.c index c7e027ba73..84f3b1d35e 100644 --- a/keyboards/mt64rgb/keymaps/default/keymap.c +++ b/keyboards/mt64rgb/keymaps/default/keymap.c @@ -1,18 +1,18 @@ -/* Copyright 2020 MT - * - * 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 . - */ +/* Copyright 2020 MT + * + * 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 . + */ #include QMK_KEYBOARD_H @@ -37,7 +37,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { }; void rgb_matrix_indicators_user(void) { - if (!g_suspend_state && layer_state_is(1)) { + if (layer_state_is(1)) { rgb_matrix_set_color(77,0xFF, 0x80, 0x00); } if (host_keyboard_led_state().caps_lock) { diff --git a/keyboards/mt84/keymaps/default/keymap.c b/keyboards/mt84/keymaps/default/keymap.c index fc8481da9d..bb7d5b447f 100644 --- a/keyboards/mt84/keymaps/default/keymap.c +++ b/keyboards/mt84/keymaps/default/keymap.c @@ -1,18 +1,18 @@ /* Copyright 2020 mt<704340378@qq.com> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ + * + * 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 . + */ #include QMK_KEYBOARD_H @@ -44,12 +44,10 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { void rgb_matrix_indicators_user(void) { led_t led_state = host_keyboard_led_state(); - if (!g_suspend_state) { switch (get_highest_layer(layer_state)) { case _FN: rgb_matrix_set_color(77,0xFF, 0x80, 0x00); break; - } } if (led_state.caps_lock) { rgb_matrix_set_color(46, 0xFF, 0xFF, 0xFF); diff --git a/quantum/led_matrix.c b/quantum/led_matrix.c index 72eb5190b3..5dd37dff14 100644 --- a/quantum/led_matrix.c +++ b/quantum/led_matrix.c @@ -35,8 +35,8 @@ # define LED_DISABLE_TIMEOUT 0 #endif -#ifndef LED_DISABLE_WHEN_USB_SUSPENDED -# define LED_DISABLE_WHEN_USB_SUSPENDED false +#if LED_DISABLE_WHEN_USB_SUSPENDED == false +# undef LED_DISABLE_WHEN_USB_SUSPENDED #endif #if !defined(LED_MATRIX_MAXIMUM_BRIGHTNESS) || LED_MATRIX_MAXIMUM_BRIGHTNESS > UINT8_MAX @@ -65,7 +65,6 @@ #endif // globals -bool g_suspend_state = false; led_eeconfig_t led_matrix_eeconfig; // TODO: would like to prefix this with g_ for global consistancy, do this in another pr uint32_t g_led_timer; #ifdef LED_MATRIX_FRAMEBUFFER_EFFECTS @@ -76,6 +75,7 @@ last_hit_t g_last_hit_tracker; #endif // LED_MATRIX_KEYREACTIVE_ENABLED // internals +static bool suspend_state = false; static uint8_t led_last_enable = UINT8_MAX; static uint8_t led_last_effect = UINT8_MAX; static effect_params_t led_effect_params = {0, LED_FLAG_ALL, false}; @@ -325,9 +325,7 @@ void led_matrix_task(void) { // Ideally we would also stop sending zeros to the LED driver PWM buffers // while suspended and just do a software shutdown. This is a cheap hack for now. bool suspend_backlight = -#if LED_DISABLE_WHEN_USB_SUSPENDED == true - g_suspend_state || -#endif // LED_DISABLE_WHEN_USB_SUSPENDED == true + suspend_state || #if LED_DISABLE_TIMEOUT > 0 (led_anykey_timer > (uint32_t)LED_DISABLE_TIMEOUT) || #endif // LED_DISABLE_TIMEOUT > 0 @@ -416,13 +414,15 @@ void led_matrix_init(void) { } void led_matrix_set_suspend_state(bool state) { - if (LED_DISABLE_WHEN_USB_SUSPENDED && state) { +#ifdef LED_DISABLE_WHEN_USB_SUSPENDED + if (state) { led_matrix_set_value_all(0); // turn off all LEDs when suspending } - g_suspend_state = state; + suspend_state = state; +#endif } -bool led_matrix_get_suspend_state(void) { return g_suspend_state; } +bool led_matrix_get_suspend_state(void) { return suspend_state; } void led_matrix_toggle_eeprom_helper(bool write_to_eeprom) { led_matrix_eeconfig.enable ^= 1; diff --git a/quantum/led_matrix.h b/quantum/led_matrix.h index f35bbe2096..a3fa552b0a 100644 --- a/quantum/led_matrix.h +++ b/quantum/led_matrix.h @@ -134,7 +134,6 @@ extern const led_matrix_driver_t led_matrix_driver; extern led_eeconfig_t led_matrix_eeconfig; -extern bool g_suspend_state; extern uint32_t g_led_timer; extern led_config_t g_led_config; #ifdef LED_MATRIX_KEYREACTIVE_ENABLED diff --git a/quantum/rgb_matrix.c b/quantum/rgb_matrix.c index 8aae486034..1f76049430 100644 --- a/quantum/rgb_matrix.c +++ b/quantum/rgb_matrix.c @@ -67,8 +67,8 @@ __attribute__((weak)) RGB rgb_matrix_hsv_to_rgb(HSV hsv) { return hsv_to_rgb(hsv # define RGB_DISABLE_TIMEOUT 0 #endif -#ifndef RGB_DISABLE_WHEN_USB_SUSPENDED -# define RGB_DISABLE_WHEN_USB_SUSPENDED false +#if RGB_DISABLE_WHEN_USB_SUSPENDED == false +# undef RGB_DISABLE_WHEN_USB_SUSPENDED #endif #if !defined(RGB_MATRIX_MAXIMUM_BRIGHTNESS) || RGB_MATRIX_MAXIMUM_BRIGHTNESS > UINT8_MAX @@ -118,7 +118,6 @@ __attribute__((weak)) RGB rgb_matrix_hsv_to_rgb(HSV hsv) { return hsv_to_rgb(hsv #endif // globals -bool g_suspend_state = false; rgb_config_t rgb_matrix_config; // TODO: would like to prefix this with g_ for global consistancy, do this in another pr uint32_t g_rgb_timer; #ifdef RGB_MATRIX_FRAMEBUFFER_EFFECTS @@ -129,6 +128,7 @@ last_hit_t g_last_hit_tracker; #endif // RGB_MATRIX_KEYREACTIVE_ENABLED // internals +static bool suspend_state = false; static uint8_t rgb_last_enable = UINT8_MAX; static uint8_t rgb_last_effect = UINT8_MAX; static effect_params_t rgb_effect_params = {0, LED_FLAG_ALL, false}; @@ -410,9 +410,7 @@ void rgb_matrix_task(void) { // Ideally we would also stop sending zeros to the LED driver PWM buffers // while suspended and just do a software shutdown. This is a cheap hack for now. bool suspend_backlight = -#if RGB_DISABLE_WHEN_USB_SUSPENDED == true - g_suspend_state || -#endif // RGB_DISABLE_WHEN_USB_SUSPENDED == true + suspend_state || #if RGB_DISABLE_TIMEOUT > 0 (rgb_anykey_timer > (uint32_t)RGB_DISABLE_TIMEOUT) || #endif // RGB_DISABLE_TIMEOUT > 0 @@ -501,13 +499,15 @@ void rgb_matrix_init(void) { } void rgb_matrix_set_suspend_state(bool state) { - if (RGB_DISABLE_WHEN_USB_SUSPENDED && state) { +#ifdef RGB_DISABLE_WHEN_USB_SUSPENDED + if (state) { rgb_matrix_set_color_all(0, 0, 0); // turn off all LEDs when suspending } - g_suspend_state = state; + suspend_state = state; +#endif } -bool rgb_matrix_get_suspend_state(void) { return g_suspend_state; } +bool rgb_matrix_get_suspend_state(void) { return suspend_state; } void rgb_matrix_toggle_eeprom_helper(bool write_to_eeprom) { rgb_matrix_config.enable ^= 1; diff --git a/quantum/rgb_matrix.h b/quantum/rgb_matrix.h index bb8bcfab68..a615b8422c 100644 --- a/quantum/rgb_matrix.h +++ b/quantum/rgb_matrix.h @@ -216,7 +216,6 @@ extern const rgb_matrix_driver_t rgb_matrix_driver; extern rgb_config_t rgb_matrix_config; -extern bool g_suspend_state; extern uint32_t g_rgb_timer; extern led_config_t g_led_config; #ifdef RGB_MATRIX_KEYREACTIVE_ENABLED diff --git a/tmk_core/common/avr/suspend.c b/tmk_core/common/avr/suspend.c index 96b19a77fd..1c2bf9cb46 100644 --- a/tmk_core/common/avr/suspend.c +++ b/tmk_core/common/avr/suspend.c @@ -163,6 +163,10 @@ void suspend_power_down(void) { rgblight_suspend(); # endif +# if defined(RGB_MATRIX_ENABLE) + rgb_matrix_set_suspend_state(true); +# endif + // Enter sleep state if possible (ie, the MCU has a watchdog timeout interrupt) # if defined(WDT_vect) power_down(WDTO_15MS); @@ -214,6 +218,9 @@ void suspend_wakeup_init(void) { #if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE) rgblight_wakeup(); #endif +# if defined(RGB_MATRIX_ENABLE) + rgb_matrix_set_suspend_state(false); +# endif suspend_wakeup_init_kb(); } diff --git a/tmk_core/common/chibios/suspend.c b/tmk_core/common/chibios/suspend.c index b3949185e9..1f4f93c455 100644 --- a/tmk_core/common/chibios/suspend.c +++ b/tmk_core/common/chibios/suspend.c @@ -83,6 +83,9 @@ void suspend_power_down(void) { #if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE) rgblight_suspend(); #endif +# if defined(RGB_MATRIX_ENABLE) + rgb_matrix_set_suspend_state(true); +# endif #ifdef AUDIO_ENABLE stop_all_notes(); #endif /* AUDIO_ENABLE */ @@ -151,5 +154,8 @@ void suspend_wakeup_init(void) { #if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE) rgblight_wakeup(); #endif +# if defined(RGB_MATRIX_ENABLE) + rgb_matrix_set_suspend_state(false); +# endif suspend_wakeup_init_kb(); } -- cgit v1.2.3 From 39bc8163d013b5c7e148b7e95b3883dc0adb95ba Mon Sep 17 00:00:00 2001 From: github-actions[bot] Date: Thu, 29 Apr 2021 13:36:47 +1000 Subject: [CI] Format code according to conventions (#12731) Co-authored-by: QMK Bot --- quantum/led_matrix.c | 9 ++++----- quantum/rgb_matrix.c | 9 ++++----- tmk_core/common/avr/suspend.c | 4 ++-- tmk_core/common/chibios/suspend.c | 8 ++++---- 4 files changed, 14 insertions(+), 16 deletions(-) (limited to 'tmk_core') diff --git a/quantum/led_matrix.c b/quantum/led_matrix.c index 5dd37dff14..3674c9b97e 100644 --- a/quantum/led_matrix.c +++ b/quantum/led_matrix.c @@ -75,7 +75,7 @@ last_hit_t g_last_hit_tracker; #endif // LED_MATRIX_KEYREACTIVE_ENABLED // internals -static bool suspend_state = false; +static bool suspend_state = false; static uint8_t led_last_enable = UINT8_MAX; static uint8_t led_last_effect = UINT8_MAX; static effect_params_t led_effect_params = {0, LED_FLAG_ALL, false}; @@ -324,12 +324,11 @@ void led_matrix_task(void) { // Ideally we would also stop sending zeros to the LED driver PWM buffers // while suspended and just do a software shutdown. This is a cheap hack for now. - bool suspend_backlight = - suspend_state || + bool suspend_backlight = suspend_state || #if LED_DISABLE_TIMEOUT > 0 - (led_anykey_timer > (uint32_t)LED_DISABLE_TIMEOUT) || + (led_anykey_timer > (uint32_t)LED_DISABLE_TIMEOUT) || #endif // LED_DISABLE_TIMEOUT > 0 - false; + false; uint8_t effect = suspend_backlight || !led_matrix_eeconfig.enable ? 0 : led_matrix_eeconfig.mode; diff --git a/quantum/rgb_matrix.c b/quantum/rgb_matrix.c index 1f76049430..097c5302df 100644 --- a/quantum/rgb_matrix.c +++ b/quantum/rgb_matrix.c @@ -128,7 +128,7 @@ last_hit_t g_last_hit_tracker; #endif // RGB_MATRIX_KEYREACTIVE_ENABLED // internals -static bool suspend_state = false; +static bool suspend_state = false; static uint8_t rgb_last_enable = UINT8_MAX; static uint8_t rgb_last_effect = UINT8_MAX; static effect_params_t rgb_effect_params = {0, LED_FLAG_ALL, false}; @@ -409,12 +409,11 @@ void rgb_matrix_task(void) { // Ideally we would also stop sending zeros to the LED driver PWM buffers // while suspended and just do a software shutdown. This is a cheap hack for now. - bool suspend_backlight = - suspend_state || + bool suspend_backlight = suspend_state || #if RGB_DISABLE_TIMEOUT > 0 - (rgb_anykey_timer > (uint32_t)RGB_DISABLE_TIMEOUT) || + (rgb_anykey_timer > (uint32_t)RGB_DISABLE_TIMEOUT) || #endif // RGB_DISABLE_TIMEOUT > 0 - false; + false; uint8_t effect = suspend_backlight || !rgb_matrix_config.enable ? 0 : rgb_matrix_config.mode; diff --git a/tmk_core/common/avr/suspend.c b/tmk_core/common/avr/suspend.c index 1c2bf9cb46..e9ee0aefdd 100644 --- a/tmk_core/common/avr/suspend.c +++ b/tmk_core/common/avr/suspend.c @@ -218,9 +218,9 @@ void suspend_wakeup_init(void) { #if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE) rgblight_wakeup(); #endif -# if defined(RGB_MATRIX_ENABLE) +#if defined(RGB_MATRIX_ENABLE) rgb_matrix_set_suspend_state(false); -# endif +#endif suspend_wakeup_init_kb(); } diff --git a/tmk_core/common/chibios/suspend.c b/tmk_core/common/chibios/suspend.c index 1f4f93c455..14a9aecb31 100644 --- a/tmk_core/common/chibios/suspend.c +++ b/tmk_core/common/chibios/suspend.c @@ -83,9 +83,9 @@ void suspend_power_down(void) { #if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE) rgblight_suspend(); #endif -# if defined(RGB_MATRIX_ENABLE) +#if defined(RGB_MATRIX_ENABLE) rgb_matrix_set_suspend_state(true); -# endif +#endif #ifdef AUDIO_ENABLE stop_all_notes(); #endif /* AUDIO_ENABLE */ @@ -154,8 +154,8 @@ void suspend_wakeup_init(void) { #if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE) rgblight_wakeup(); #endif -# if defined(RGB_MATRIX_ENABLE) +#if defined(RGB_MATRIX_ENABLE) rgb_matrix_set_suspend_state(false); -# endif +#endif suspend_wakeup_init_kb(); } -- cgit v1.2.3 From f0b30e0027cb890c7510fa22e5824a43c0d9e86f Mon Sep 17 00:00:00 2001 From: Drashna Jaelre Date: Sun, 9 May 2021 23:21:09 -0700 Subject: Make Swap Hands use PROGMEM (#12284) This converts the array that the Swap Hands feature uses to use PROGMEM, and to read from that array, as such. Since this array never changes at runtime, there is no reason to keep it in memory. Especially for AVR boards, as memory is a precious resource.--- docs/feature_swap_hands.md | 2 +- docs/ja/feature_swap_hands.md | 2 +- keyboards/40percentclub/25/25.c | 2 +- keyboards/40percentclub/6lit/6lit.c | 2 +- keyboards/40percentclub/foobar/foobar.c | 2 +- keyboards/adkb96/adkb96.c | 2 +- keyboards/centromere/centromere.c | 10 +++++----- keyboards/crkbd/crkbd.c | 3 +-- keyboards/ergo42/ergo42.c | 2 +- keyboards/ergodox_ez/ergodox_ez.c | 2 +- keyboards/ergodox_infinity/ergodox_infinity.c | 2 +- keyboards/ergoslab/rev1/rev1.c | 2 +- keyboards/gergo/gergo.c | 2 +- keyboards/handwired/dactyl/dactyl.c | 2 +- .../dactyl_manuform/5x6_right_trackball/5x6_right_trackball.c | 2 +- keyboards/handwired/pterodactyl/pterodactyl.c | 2 +- keyboards/jian/handwired/handwired.c | 2 +- keyboards/jian/nsrev2/nsrev2.c | 2 +- keyboards/jian/rev1/rev1.c | 2 +- keyboards/jian/rev2/rev2.c | 2 +- keyboards/keebio/iris/rev1/rev1.c | 2 +- keyboards/keebio/iris/rev1_led/rev1_led.c | 2 +- keyboards/keebio/iris/rev2/rev2.c | 2 +- keyboards/keebio/iris/rev3/rev3.c | 2 +- keyboards/keebio/levinson/levinson.c | 2 +- keyboards/keebio/wavelet/wavelet.c | 2 +- keyboards/kyria/rev1/rev1.c | 4 ++-- keyboards/lets_split/lets_split.c | 2 +- keyboards/lets_split_eh/lets_split_eh.c | 2 +- keyboards/mitosis/mitosis.c | 2 +- keyboards/moonlander/moonlander.c | 2 +- keyboards/niu_mini/niu_mini.c | 2 +- keyboards/orthodox/rev1/rev1.c | 2 +- keyboards/orthodox/rev3/rev3.c | 2 +- keyboards/orthodox/rev3_teensy/rev3_teensy.c | 2 +- keyboards/planck/planck.c | 2 +- keyboards/preonic/rev1/rev1.c | 2 +- keyboards/preonic/rev2/rev2.c | 2 +- keyboards/preonic/rev3/rev3.c | 2 +- keyboards/redox_w/redox_w.c | 2 +- keyboards/sirius/uni660/rev1/rev1.c | 2 +- keyboards/sirius/uni660/rev2/rev2.c | 2 +- keyboards/splitty/splitty.c | 2 +- keyboards/telophase/telophase.c | 2 +- keyboards/vitamins_included/vitamins_included.c | 2 +- tmk_core/common/action.c | 3 ++- tmk_core/common/action.h | 2 +- 47 files changed, 53 insertions(+), 53 deletions(-) (limited to 'tmk_core') diff --git a/docs/feature_swap_hands.md b/docs/feature_swap_hands.md index 009477d203..cbc574b6b8 100644 --- a/docs/feature_swap_hands.md +++ b/docs/feature_swap_hands.md @@ -7,7 +7,7 @@ The swap-hands action allows support for one-handed typing without requiring a s The configuration table is a simple 2-dimensional array to map from column/row to new column/row. Example `hand_swap_config` for Planck: ```C -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{11, 0}, {10, 0}, {9, 0}, {8, 0}, {7, 0}, {6, 0}, {5, 0}, {4, 0}, {3, 0}, {2, 0}, {1, 0}, {0, 0}}, {{11, 1}, {10, 1}, {9, 1}, {8, 1}, {7, 1}, {6, 1}, {5, 1}, {4, 1}, {3, 1}, {2, 1}, {1, 1}, {0, 1}}, {{11, 2}, {10, 2}, {9, 2}, {8, 2}, {7, 2}, {6, 2}, {5, 2}, {4, 2}, {3, 2}, {2, 2}, {1, 2}, {0, 2}}, diff --git a/docs/ja/feature_swap_hands.md b/docs/ja/feature_swap_hands.md index 3150801c55..5164584e8a 100644 --- a/docs/ja/feature_swap_hands.md +++ b/docs/ja/feature_swap_hands.md @@ -12,7 +12,7 @@ 設定テーブルは列/行から新しい列/行にマップするための単純な2次元配列です。Planck の `hand_swap_config` の例: ```C -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{11, 0}, {10, 0}, {9, 0}, {8, 0}, {7, 0}, {6, 0}, {5, 0}, {4, 0}, {3, 0}, {2, 0}, {1, 0}, {0, 0}}, {{11, 1}, {10, 1}, {9, 1}, {8, 1}, {7, 1}, {6, 1}, {5, 1}, {4, 1}, {3, 1}, {2, 1}, {1, 1}, {0, 1}}, {{11, 2}, {10, 2}, {9, 2}, {8, 2}, {7, 2}, {6, 2}, {5, 2}, {4, 2}, {3, 2}, {2, 2}, {1, 2}, {0, 2}}, diff --git a/keyboards/40percentclub/25/25.c b/keyboards/40percentclub/25/25.c index 54a42d263c..de1b038aa8 100644 --- a/keyboards/40percentclub/25/25.c +++ b/keyboards/40percentclub/25/25.c @@ -44,7 +44,7 @@ void led_set_kb(uint8_t usb_led) { #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{4, 5}, {3, 5}, {2, 5}, {1, 5}, {0, 5}}, {{4, 6}, {3, 6}, {2, 6}, {1, 6}, {0, 6}}, {{4, 7}, {3, 7}, {2, 7}, {1, 7}, {0, 7}}, diff --git a/keyboards/40percentclub/6lit/6lit.c b/keyboards/40percentclub/6lit/6lit.c index fd3ae7d009..59d7e33bd6 100644 --- a/keyboards/40percentclub/6lit/6lit.c +++ b/keyboards/40percentclub/6lit/6lit.c @@ -44,7 +44,7 @@ void led_set_kb(uint8_t usb_led) { #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{2, 2}, {1, 2}, {0, 2}}, {{2, 3}, {1, 3}, {0, 3}}, {{0, 0}, {1, 0}, {2, 0}}, diff --git a/keyboards/40percentclub/foobar/foobar.c b/keyboards/40percentclub/foobar/foobar.c index c032056a15..b0a1518df1 100644 --- a/keyboards/40percentclub/foobar/foobar.c +++ b/keyboards/40percentclub/foobar/foobar.c @@ -44,7 +44,7 @@ void led_set_kb(uint8_t usb_led) { #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{4, 3}, {3, 3}, {2, 3}, {1, 3}, {0, 3}}, {{4, 4}, {3, 4}, {2, 4}, {1, 4}, {0, 4}}, {{4, 5}, {3, 5}, {2, 5}, {1, 5}, {0, 5}}, diff --git a/keyboards/adkb96/adkb96.c b/keyboards/adkb96/adkb96.c index 9a1c85a2ce..93230ee00c 100644 --- a/keyboards/adkb96/adkb96.c +++ b/keyboards/adkb96/adkb96.c @@ -2,7 +2,7 @@ #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{0, 6}, {1, 6}, {2, 6}, {3, 6}, {4, 6}, {5, 6}, {6, 6}, {7, 6}}, {{0, 7}, {1, 7}, {2, 7}, {3, 7}, {4, 7}, {5, 7}, {6, 7}, {7, 7}}, {{0, 8}, {1, 8}, {2, 8}, {3, 8}, {4, 8}, {5, 8}, {6, 8}, {7, 8}}, diff --git a/keyboards/centromere/centromere.c b/keyboards/centromere/centromere.c index 269c60fd75..8d46520e38 100644 --- a/keyboards/centromere/centromere.c +++ b/keyboards/centromere/centromere.c @@ -5,21 +5,21 @@ void led_init(void) { setPinOutput(C4); // Set red LED pin as output setPinOutput(C5); // Set blue LED pin as output setPinOutput(D1); // Set green LED pin as output - + writePinHigh(C4); // Turn off red LED pin writePinHigh(C5); // Turn off blue LED pin writePinHigh(D1); // Turn off green LED pin - + #else setPinOutput(F4); // Set red LED pin as output setPinOutput(F5); // Set blue LED pin as output setPinOutput(D1); // Set green LED pin as output - + writePinHigh(F4); // Turn off red LED pin writePinHigh(F5); // Turn off blue LED pin writePinHigh(D1); // Turn off green LED pin - + #endif } @@ -33,7 +33,7 @@ void matrix_init_kb(void) { #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{9, 0}, {8, 0}, {7, 0}, {6, 0}, {5, 0}, {4, 0}, {3, 0}, {2, 0}, {1, 0}, {0, 0}}, {{9, 1}, {8, 1}, {7, 1}, {6, 1}, {5, 1}, {4, 1}, {3, 1}, {2, 1}, {1, 1}, {0, 1}}, {{9, 2}, {8, 2}, {7, 2}, {6, 2}, {5, 2}, {4, 2}, {3, 2}, {2, 2}, {1, 2}, {0, 2}}, diff --git a/keyboards/crkbd/crkbd.c b/keyboards/crkbd/crkbd.c index ab1381a39b..6220c9822a 100644 --- a/keyboards/crkbd/crkbd.c +++ b/keyboards/crkbd/crkbd.c @@ -20,7 +20,7 @@ along with this program. If not, see . #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { // Left {{0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}, {5, 4}}, {{0, 5}, {1, 5}, {2, 5}, {3, 5}, {4, 5}, {5, 5}}, @@ -33,4 +33,3 @@ const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{0, 3}, {1, 3}, {2, 3}, {3, 3}, {4, 3}, {5, 3}} }; #endif - diff --git a/keyboards/ergo42/ergo42.c b/keyboards/ergo42/ergo42.c index e42dcb2261..bd7a7ffe19 100644 --- a/keyboards/ergo42/ergo42.c +++ b/keyboards/ergo42/ergo42.c @@ -2,7 +2,7 @@ #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}, {5, 4}, {6, 4}}, {{0, 5}, {1, 5}, {2, 5}, {3, 5}, {4, 5}, {5, 5}, {6, 5}}, diff --git a/keyboards/ergodox_ez/ergodox_ez.c b/keyboards/ergodox_ez/ergodox_ez.c index e6f48c49fb..4d35675211 100644 --- a/keyboards/ergodox_ez/ergodox_ez.c +++ b/keyboards/ergodox_ez/ergodox_ez.c @@ -220,7 +220,7 @@ uint8_t ergodox_left_leds_update(void) { #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) // swap-hands action needs a matrix to define the swap -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { /* Left hand, matrix positions */ {{0,13}, {1,13}, {2,13}, {3,13}, {4,13}, {5,13}}, {{0,12}, {1,12}, {2,12}, {3,12}, {4,12}, {5,12}}, diff --git a/keyboards/ergodox_infinity/ergodox_infinity.c b/keyboards/ergodox_infinity/ergodox_infinity.c index a9962f96a0..97b628470b 100644 --- a/keyboards/ergodox_infinity/ergodox_infinity.c +++ b/keyboards/ergodox_infinity/ergodox_infinity.c @@ -205,7 +205,7 @@ void ergodox_right_led_3_set(uint8_t n) { #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{0, 9}, {1, 9}, {2, 9}, {3, 9}, {4, 9}}, {{0, 10}, {1, 10}, {2, 10}, {3, 10}, {4, 10}}, {{0, 11}, {1, 11}, {2, 11}, {3, 11}, {4, 11}}, diff --git a/keyboards/ergoslab/rev1/rev1.c b/keyboards/ergoslab/rev1/rev1.c index 0e3e0fe996..115dab51e4 100644 --- a/keyboards/ergoslab/rev1/rev1.c +++ b/keyboards/ergoslab/rev1/rev1.c @@ -2,7 +2,7 @@ #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{0, 5}, {1, 5}, {2, 5}, {3, 5}, {4, 5}, {5, 5}}, {{0, 6}, {1, 6}, {2, 6}, {3, 6}, {4, 6}, {5, 6}}, {{0, 7}, {1, 7}, {2, 7}, {3, 7}, {4, 7}, {5, 7}}, diff --git a/keyboards/gergo/gergo.c b/keyboards/gergo/gergo.c index fab8d0f44c..ba359f8145 100644 --- a/keyboards/gergo/gergo.c +++ b/keyboards/gergo/gergo.c @@ -65,7 +65,7 @@ out: return mcp23018_status; } -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { { {0,0}, {0,7}, {2,7}, {3,7} }, { {0,8}, {1,8}, {2,8}, {3,8} }, { {0,9}, {1,9}, {2,9}, {3,9} }, diff --git a/keyboards/handwired/dactyl/dactyl.c b/keyboards/handwired/dactyl/dactyl.c index 81b9dce0f9..ff9b4e08af 100644 --- a/keyboards/handwired/dactyl/dactyl.c +++ b/keyboards/handwired/dactyl/dactyl.c @@ -4,7 +4,7 @@ #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) // swap-hands action needs a matrix to define the swap -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{0,11}, {0,10}, {0,9}, {0,8}, {0,7}, {0,6}, {0,5}, {0,4}, {0,3}, {0,2}, {0,1}, {0,0}}, {{1,11}, {1,11}, {1,9}, {1,8}, {1,7}, {1,6}, {1,5}, {1,4}, {1,3}, {1,2}, {1,1}, {1,0}}, {{2,11}, {2,12}, {2,9}, {2,8}, {2,7}, {2,6}, {2,5}, {2,4}, {2,3}, {2,2}, {2,1}, {2,0}}, diff --git a/keyboards/handwired/dactyl_manuform/5x6_right_trackball/5x6_right_trackball.c b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/5x6_right_trackball.c index 69f7500957..4f1b3f0bbf 100644 --- a/keyboards/handwired/dactyl_manuform/5x6_right_trackball/5x6_right_trackball.c +++ b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/5x6_right_trackball.c @@ -206,7 +206,7 @@ void pointing_device_send(void) { #endif #ifdef SWAP_HANDS_ENABLE -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { /* Left hand, matrix positions */ {{5, 6}, {4, 6}, {3, 6}, {2, 6}, {1, 6}, {0, 6}}, {{5, 7}, {4, 7}, {3, 7}, {2, 7}, {1, 7}, {0, 7}}, diff --git a/keyboards/handwired/pterodactyl/pterodactyl.c b/keyboards/handwired/pterodactyl/pterodactyl.c index 736b0a62c4..f379569f5a 100644 --- a/keyboards/handwired/pterodactyl/pterodactyl.c +++ b/keyboards/handwired/pterodactyl/pterodactyl.c @@ -3,7 +3,7 @@ #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) // swap-hands action needs a matrix to define the swap -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{0,11}, {0,10}, {0,9}, {0,8}, {0,7}, {0,6}, {0,5}, {0,4}, {0,3}, {0,2}, {0,1}, {0,0}}, {{1,11}, {1,11}, {1,9}, {1,8}, {1,7}, {1,6}, {1,5}, {1,4}, {1,3}, {1,2}, {1,1}, {1,0}}, {{2,11}, {2,12}, {2,9}, {2,8}, {2,7}, {2,6}, {2,5}, {2,4}, {2,3}, {2,2}, {2,1}, {2,0}}, diff --git a/keyboards/jian/handwired/handwired.c b/keyboards/jian/handwired/handwired.c index bcb7ec7102..2c14518299 100644 --- a/keyboards/jian/handwired/handwired.c +++ b/keyboards/jian/handwired/handwired.c @@ -1,6 +1,6 @@ #include "handwired.h" -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{13, 0}, {12, 0}, {11, 0}, {10, 0}, {9, 0}, {8, 0}, {7, 0}, {6, 0}, {5, 0}, {4, 0}, {3, 0}, {2, 0}, {1, 0}, {0, 0}}, {{13, 1}, {12, 1}, {11, 1}, {10, 1}, {9, 1}, {8, 1}, {7, 1}, {6, 1}, {5, 1}, {4, 1}, {3, 1}, {2, 1}, {1, 1}, {0, 1}}, {{13, 2}, {12, 2}, {11, 2}, {10, 2}, {9, 2}, {8, 2}, {7, 2}, {6, 2}, {5, 2}, {4, 2}, {3, 2}, {2, 2}, {1, 2}, {0, 2}}, diff --git a/keyboards/jian/nsrev2/nsrev2.c b/keyboards/jian/nsrev2/nsrev2.c index c3acff55ee..48827416f1 100644 --- a/keyboards/jian/nsrev2/nsrev2.c +++ b/keyboards/jian/nsrev2/nsrev2.c @@ -2,7 +2,7 @@ #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}, {5, 4}}, {{0, 5}, {1, 5}, {2, 5}, {3, 5}, {4, 5}, {5, 5}}, {{0, 6}, {1, 6}, {2, 6}, {3, 6}, {4, 6}, {5, 6}}, diff --git a/keyboards/jian/rev1/rev1.c b/keyboards/jian/rev1/rev1.c index 1c7e936270..40d9f3beda 100644 --- a/keyboards/jian/rev1/rev1.c +++ b/keyboards/jian/rev1/rev1.c @@ -2,7 +2,7 @@ #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}, {5, 4}, {6, 4}}, {{0, 5}, {1, 5}, {2, 5}, {3, 5}, {4, 5}, {5, 5}, {6, 5}}, {{0, 6}, {1, 6}, {2, 6}, {3, 6}, {4, 6}, {5, 6}, {6, 6}}, diff --git a/keyboards/jian/rev2/rev2.c b/keyboards/jian/rev2/rev2.c index 09824c6652..b18676af38 100644 --- a/keyboards/jian/rev2/rev2.c +++ b/keyboards/jian/rev2/rev2.c @@ -2,7 +2,7 @@ #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}, {5, 4}}, {{0, 5}, {1, 5}, {2, 5}, {3, 5}, {4, 5}, {5, 5}}, {{0, 6}, {1, 6}, {2, 6}, {3, 6}, {4, 6}, {5, 6}}, diff --git a/keyboards/keebio/iris/rev1/rev1.c b/keyboards/keebio/iris/rev1/rev1.c index 9694d122df..6249d2f0ac 100644 --- a/keyboards/keebio/iris/rev1/rev1.c +++ b/keyboards/keebio/iris/rev1/rev1.c @@ -10,7 +10,7 @@ void led_set_kb(uint8_t usb_led) { #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) // swap-hands action needs a matrix to define the swap -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { /* Left hand, matrix positions */ {{0,5}, {1,5}, {2,5}, {3,5}, {4,5}, {5,5}}, {{0,6}, {1,6}, {2,6}, {3,6}, {4,6}, {5,6}}, diff --git a/keyboards/keebio/iris/rev1_led/rev1_led.c b/keyboards/keebio/iris/rev1_led/rev1_led.c index af5fc9440b..c330189c7c 100644 --- a/keyboards/keebio/iris/rev1_led/rev1_led.c +++ b/keyboards/keebio/iris/rev1_led/rev1_led.c @@ -10,7 +10,7 @@ void led_set_kb(uint8_t usb_led) { #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) // swap-hands action needs a matrix to define the swap -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { /* Left hand, matrix positions */ {{0,5}, {1,5}, {2,5}, {3,5}, {4,5}, {5,5}}, {{0,6}, {1,6}, {2,6}, {3,6}, {4,6}, {5,6}}, diff --git a/keyboards/keebio/iris/rev2/rev2.c b/keyboards/keebio/iris/rev2/rev2.c index 70c30695ad..e8c2a66c98 100644 --- a/keyboards/keebio/iris/rev2/rev2.c +++ b/keyboards/keebio/iris/rev2/rev2.c @@ -3,7 +3,7 @@ #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) // swap-hands action needs a matrix to define the swap -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { /* Left hand, matrix positions */ {{0,5}, {1,5}, {2,5}, {3,5}, {4,5}, {5,5}}, {{0,6}, {1,6}, {2,6}, {3,6}, {4,6}, {5,6}}, diff --git a/keyboards/keebio/iris/rev3/rev3.c b/keyboards/keebio/iris/rev3/rev3.c index f58c2093c4..b97b097b78 100644 --- a/keyboards/keebio/iris/rev3/rev3.c +++ b/keyboards/keebio/iris/rev3/rev3.c @@ -3,7 +3,7 @@ #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) // swap-hands action needs a matrix to define the swap -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { /* Left hand, matrix positions */ {{0,5}, {1,5}, {2,5}, {3,5}, {4,5}, {5,5}}, {{0,6}, {1,6}, {2,6}, {3,6}, {4,6}, {5,6}}, diff --git a/keyboards/keebio/levinson/levinson.c b/keyboards/keebio/levinson/levinson.c index 95f3fe9ef8..b361640bcf 100644 --- a/keyboards/keebio/levinson/levinson.c +++ b/keyboards/keebio/levinson/levinson.c @@ -2,7 +2,7 @@ #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{5, 4}, {4, 4}, {3, 4}, {2, 4}, {1, 4}, {0, 4}}, {{5, 5}, {4, 5}, {3, 5}, {2, 5}, {1, 5}, {0, 5}}, diff --git a/keyboards/keebio/wavelet/wavelet.c b/keyboards/keebio/wavelet/wavelet.c index 2bc9c65a52..68011e266c 100644 --- a/keyboards/keebio/wavelet/wavelet.c +++ b/keyboards/keebio/wavelet/wavelet.c @@ -15,7 +15,7 @@ void matrix_init_kb(void) { #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{5, 4}, {4, 4}, {3, 4}, {2, 4}, {1, 4}, {0, 4}}, {{5, 5}, {4, 5}, {3, 5}, {2, 5}, {1, 5}, {0, 5}}, diff --git a/keyboards/kyria/rev1/rev1.c b/keyboards/kyria/rev1/rev1.c index 970a359e71..622ac279bd 100644 --- a/keyboards/kyria/rev1/rev1.c +++ b/keyboards/kyria/rev1/rev1.c @@ -3,7 +3,7 @@ #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}, {5, 4}, {6, 4}, {7, 4}}, {{0, 5}, {1, 5}, {2, 5}, {3, 5}, {4, 5}, {5, 5}, {6, 5}, {7, 5}}, {{0, 6}, {1, 6}, {2, 6}, {3, 6}, {4, 6}, {5, 6}, {6, 6}, {7, 6}}, @@ -12,6 +12,6 @@ const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1}, {6, 1}, {7, 1}}, {{0, 2}, {1, 2}, {2, 2}, {3, 2}, {4, 2}, {5, 2}, {6, 2}, {7, 2}}, {{0, 3}, {1, 3}, {2, 3}, {3, 3}, {4, 3}, {5, 3}, {6, 3}, {7, 3}} -}; +}; #endif diff --git a/keyboards/lets_split/lets_split.c b/keyboards/lets_split/lets_split.c index c400ab7bb8..ee0c931be2 100644 --- a/keyboards/lets_split/lets_split.c +++ b/keyboards/lets_split/lets_split.c @@ -2,7 +2,7 @@ #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}, {5, 4}}, {{0, 5}, {1, 5}, {2, 5}, {3, 5}, {4, 5}, {5, 5}}, diff --git a/keyboards/lets_split_eh/lets_split_eh.c b/keyboards/lets_split_eh/lets_split_eh.c index 7249f54cf2..37075aa67d 100644 --- a/keyboards/lets_split_eh/lets_split_eh.c +++ b/keyboards/lets_split_eh/lets_split_eh.c @@ -2,7 +2,7 @@ #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}, {5, 4}}, {{0, 5}, {1, 5}, {2, 5}, {3, 5}, {4, 5}, {5, 5}}, diff --git a/keyboards/mitosis/mitosis.c b/keyboards/mitosis/mitosis.c index 50b6d8452f..ea3d1c99d7 100644 --- a/keyboards/mitosis/mitosis.c +++ b/keyboards/mitosis/mitosis.c @@ -16,7 +16,7 @@ void matrix_init_kb(void) { #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{9, 0}, {8, 0}, {7, 0}, {6, 0}, {5, 0}, {4, 0}, {3, 0}, {2, 0}, {1, 0}, {0, 0}}, {{9, 1}, {8, 1}, {7, 1}, {6, 1}, {5, 1}, {4, 1}, {3, 1}, {2, 1}, {1, 1}, {0, 1}}, {{9, 2}, {8, 2}, {7, 2}, {6, 2}, {5, 2}, {4, 2}, {3, 2}, {2, 2}, {1, 2}, {0, 2}}, diff --git a/keyboards/moonlander/moonlander.c b/keyboards/moonlander/moonlander.c index 39f61b5c40..bc4047b847 100644 --- a/keyboards/moonlander/moonlander.c +++ b/keyboards/moonlander/moonlander.c @@ -370,7 +370,7 @@ bool music_mask_kb(uint16_t keycode) { #ifdef SWAP_HANDS_ENABLE // swap-hands action needs a matrix to define the swap // clang-format off -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { /* Left hand, matrix positions */ {{6,6}, {5,6}, {4,6}, {3,6}, {2,6}, {1,6},{0,6}}, {{6,7}, {5,7}, {4,7}, {3,7}, {2,7}, {1,7},{0,7}}, diff --git a/keyboards/niu_mini/niu_mini.c b/keyboards/niu_mini/niu_mini.c index 835625ee4f..cd9c0cdfed 100644 --- a/keyboards/niu_mini/niu_mini.c +++ b/keyboards/niu_mini/niu_mini.c @@ -2,7 +2,7 @@ #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{11, 0}, {10, 0}, {9, 0}, {8, 0}, {7, 0}, {6, 0}, {5, 0}, {4, 0}, {3, 0}, {2, 0}, {1, 0}, {0, 0}}, {{11, 1}, {10, 1}, {9, 1}, {8, 1}, {7, 1}, {6, 1}, {5, 1}, {4, 1}, {3, 1}, {2, 1}, {1, 1}, {0, 1}}, {{11, 2}, {10, 2}, {9, 2}, {8, 2}, {7, 2}, {6, 2}, {5, 2}, {4, 2}, {3, 2}, {2, 2}, {1, 2}, {0, 2}}, diff --git a/keyboards/orthodox/rev1/rev1.c b/keyboards/orthodox/rev1/rev1.c index ecb908b3ae..db8d435c33 100644 --- a/keyboards/orthodox/rev1/rev1.c +++ b/keyboards/orthodox/rev1/rev1.c @@ -37,7 +37,7 @@ void matrix_init_kb(void) { #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) // swap-hands action needs a matrix to define the swap -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { /* Left hand, matrix positions */ {{0,3}, {1,3}, {2,3}, {3,3}, {4,3}, {5,3}, {6,3}, {7,3}, {8,3}}, {{0,4}, {1,4}, {2,4}, {3,4}, {4,4}, {5,4}, {6,4}, {7,4}, {8,4}}, diff --git a/keyboards/orthodox/rev3/rev3.c b/keyboards/orthodox/rev3/rev3.c index ecb908b3ae..db8d435c33 100644 --- a/keyboards/orthodox/rev3/rev3.c +++ b/keyboards/orthodox/rev3/rev3.c @@ -37,7 +37,7 @@ void matrix_init_kb(void) { #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) // swap-hands action needs a matrix to define the swap -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { /* Left hand, matrix positions */ {{0,3}, {1,3}, {2,3}, {3,3}, {4,3}, {5,3}, {6,3}, {7,3}, {8,3}}, {{0,4}, {1,4}, {2,4}, {3,4}, {4,4}, {5,4}, {6,4}, {7,4}, {8,4}}, diff --git a/keyboards/orthodox/rev3_teensy/rev3_teensy.c b/keyboards/orthodox/rev3_teensy/rev3_teensy.c index ecb908b3ae..db8d435c33 100644 --- a/keyboards/orthodox/rev3_teensy/rev3_teensy.c +++ b/keyboards/orthodox/rev3_teensy/rev3_teensy.c @@ -37,7 +37,7 @@ void matrix_init_kb(void) { #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) // swap-hands action needs a matrix to define the swap -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { /* Left hand, matrix positions */ {{0,3}, {1,3}, {2,3}, {3,3}, {4,3}, {5,3}, {6,3}, {7,3}, {8,3}}, {{0,4}, {1,4}, {2,4}, {3,4}, {4,4}, {5,4}, {6,4}, {7,4}, {8,4}}, diff --git a/keyboards/planck/planck.c b/keyboards/planck/planck.c index 5a65d5e5f3..1f824efaae 100644 --- a/keyboards/planck/planck.c +++ b/keyboards/planck/planck.c @@ -2,7 +2,7 @@ #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{11, 0}, {10, 0}, {9, 0}, {8, 0}, {7, 0}, {6, 0}, {5, 0}, {4, 0}, {3, 0}, {2, 0}, {1, 0}, {0, 0}}, {{11, 1}, {10, 1}, {9, 1}, {8, 1}, {7, 1}, {6, 1}, {5, 1}, {4, 1}, {3, 1}, {2, 1}, {1, 1}, {0, 1}}, {{11, 2}, {10, 2}, {9, 2}, {8, 2}, {7, 2}, {6, 2}, {5, 2}, {4, 2}, {3, 2}, {2, 2}, {1, 2}, {0, 2}}, diff --git a/keyboards/preonic/rev1/rev1.c b/keyboards/preonic/rev1/rev1.c index c9fd8330ef..bf83743605 100644 --- a/keyboards/preonic/rev1/rev1.c +++ b/keyboards/preonic/rev1/rev1.c @@ -26,7 +26,7 @@ void matrix_init_kb(void) { #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) - const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { + const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{11, 0}, {10, 0}, {9, 0}, {8, 0}, {7, 0}, {6, 0}, {5, 0}, {4, 0}, {3, 0}, {2, 0}, {1, 0}, {0, 0}}, {{11, 1}, {10, 1}, {9, 1}, {8, 1}, {7, 1}, {6, 1}, {5, 1}, {4, 1}, {3, 1}, {2, 1}, {1, 1}, {0, 1}}, {{11, 2}, {10, 2}, {9, 2}, {8, 2}, {7, 2}, {6, 2}, {5, 2}, {4, 2}, {3, 2}, {2, 2}, {1, 2}, {0, 2}}, diff --git a/keyboards/preonic/rev2/rev2.c b/keyboards/preonic/rev2/rev2.c index c0e72620ed..a3929249d0 100644 --- a/keyboards/preonic/rev2/rev2.c +++ b/keyboards/preonic/rev2/rev2.c @@ -26,7 +26,7 @@ void matrix_init_kb(void) { #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) - const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { + const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{11, 0}, {10, 0}, {9, 0}, {8, 0}, {7, 0}, {6, 0}, {5, 0}, {4, 0}, {3, 0}, {2, 0}, {1, 0}, {0, 0}}, {{11, 1}, {10, 1}, {9, 1}, {8, 1}, {7, 1}, {6, 1}, {5, 1}, {4, 1}, {3, 1}, {2, 1}, {1, 1}, {0, 1}}, {{11, 2}, {10, 2}, {9, 2}, {8, 2}, {7, 2}, {6, 2}, {5, 2}, {4, 2}, {3, 2}, {2, 2}, {1, 2}, {0, 2}}, diff --git a/keyboards/preonic/rev3/rev3.c b/keyboards/preonic/rev3/rev3.c index 161c1c9636..ec8a56108e 100644 --- a/keyboards/preonic/rev3/rev3.c +++ b/keyboards/preonic/rev3/rev3.c @@ -63,7 +63,7 @@ void dip_switch_update_user(uint8_t index, bool active) { #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{5, 4}, {4, 4}, {3, 4}, {2, 4}, {1, 4}, {0, 4}}, {{5, 5}, {4, 5}, {3, 5}, {2, 5}, {1, 5}, {0, 5}}, {{5, 6}, {4, 6}, {3, 6}, {2, 6}, {1, 6}, {0, 6}}, diff --git a/keyboards/redox_w/redox_w.c b/keyboards/redox_w/redox_w.c index 05fa339571..a94e731b39 100644 --- a/keyboards/redox_w/redox_w.c +++ b/keyboards/redox_w/redox_w.c @@ -17,7 +17,7 @@ void matrix_init_kb(void) { #ifdef ONEHAND_ENABLE __attribute__ ((weak)) -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{13, 0}, {12, 0}, {11, 0}, {10, 0}, {9, 0}, {8, 0}, {7, 0}, {6, 0}, {5, 0}, {4, 0}, {3, 0}, {2, 0}, {1, 0}, {0, 0}}, {{13, 1}, {12, 1}, {11, 1}, {10, 1}, {9, 1}, {8, 1}, {7, 1}, {6, 1}, {5, 1}, {4, 1}, {3, 1}, {2, 1}, {1, 1}, {0, 1}}, {{13, 2}, {12, 2}, {11, 2}, {10, 2}, {9, 2}, {8, 2}, {7, 2}, {6, 2}, {5, 2}, {4, 2}, {3, 2}, {2, 2}, {1, 2}, {0, 2}}, diff --git a/keyboards/sirius/uni660/rev1/rev1.c b/keyboards/sirius/uni660/rev1/rev1.c index d4adac24b5..7cc75ee22a 100644 --- a/keyboards/sirius/uni660/rev1/rev1.c +++ b/keyboards/sirius/uni660/rev1/rev1.c @@ -19,7 +19,7 @@ void matrix_init_kb(void) { /* #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{9, 0}, {8, 0}, {7, 0}, {6, 0}, {5, 0}, {4, 0}, {3, 0}, {2, 0}, {1, 0}, {0, 0}}, {{9, 1}, {8, 1}, {7, 1}, {6, 1}, {5, 1}, {4, 1}, {3, 1}, {2, 1}, {1, 1}, {0, 1}}, {{9, 2}, {8, 2}, {7, 2}, {6, 2}, {5, 2}, {4, 2}, {3, 2}, {2, 2}, {1, 2}, {0, 2}}, diff --git a/keyboards/sirius/uni660/rev2/rev2.c b/keyboards/sirius/uni660/rev2/rev2.c index 048495b992..2c2515c0ed 100644 --- a/keyboards/sirius/uni660/rev2/rev2.c +++ b/keyboards/sirius/uni660/rev2/rev2.c @@ -19,7 +19,7 @@ void matrix_init_kb(void) { /* #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{9, 0}, {8, 0}, {7, 0}, {6, 0}, {5, 0}, {4, 0}, {3, 0}, {2, 0}, {1, 0}, {0, 0}}, {{9, 1}, {8, 1}, {7, 1}, {6, 1}, {5, 1}, {4, 1}, {3, 1}, {2, 1}, {1, 1}, {0, 1}}, {{9, 2}, {8, 2}, {7, 2}, {6, 2}, {5, 2}, {4, 2}, {3, 2}, {2, 2}, {1, 2}, {0, 2}}, diff --git a/keyboards/splitty/splitty.c b/keyboards/splitty/splitty.c index 652d1f781b..707f289832 100644 --- a/keyboards/splitty/splitty.c +++ b/keyboards/splitty/splitty.c @@ -19,7 +19,7 @@ #ifdef SWAP_HANDS_ENABLE // clang-format off __attribute__ ((weak)) -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{0, 5}, {1, 5}, {2, 5}, {3, 5}, {4, 5}, {5, 5}, {6, 5}}, {{0, 6}, {1, 6}, {2, 6}, {3, 6}, {4, 6}, {5, 6}, {6, 6}}, diff --git a/keyboards/telophase/telophase.c b/keyboards/telophase/telophase.c index 0e04debeb8..7484551c91 100644 --- a/keyboards/telophase/telophase.c +++ b/keyboards/telophase/telophase.c @@ -17,7 +17,7 @@ void matrix_init_kb(void) { #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{12, 0}, {11, 0}, {10, 0}, {9, 0}, {8, 0}, {7, 0}, {6, 0}, {5, 0}, {4, 0}, {3, 0}, {2, 0}, {1, 0}, {0, 0}}, {{12, 1}, {11, 1}, {10, 1}, {9, 1}, {8, 1}, {7, 1}, {6, 1}, {5, 1}, {4, 1}, {3, 1}, {2, 1}, {1, 1}, {0, 1}}, {{12, 2}, {11, 2}, {10, 2}, {9, 2}, {8, 2}, {7, 2}, {6, 2}, {5, 2}, {4, 2}, {3, 2}, {2, 2}, {1, 2}, {0, 2}}, diff --git a/keyboards/vitamins_included/vitamins_included.c b/keyboards/vitamins_included/vitamins_included.c index 650f26001e..078f93e0e6 100644 --- a/keyboards/vitamins_included/vitamins_included.c +++ b/keyboards/vitamins_included/vitamins_included.c @@ -2,7 +2,7 @@ #ifdef ONEHAND_ENABLE __attribute__ ((weak)) -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}, {5, 4}}, {{0, 5}, {1, 5}, {2, 5}, {3, 5}, {4, 5}, {5, 5}}, diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c index aae5cbfa5f..f41665b06c 100644 --- a/tmk_core/common/action.c +++ b/tmk_core/common/action.c @@ -133,7 +133,8 @@ void process_hand_swap(keyevent_t *event) { bool do_swap = event->pressed ? swap_hands : swap_state[pos.row] & (col_bit); if (do_swap) { - event->key = hand_swap_config[pos.row][pos.col]; + event->key.row = pgm_read_byte(&hand_swap_config[pos.row][pos.col].row); + event->key.col = pgm_read_byte(&hand_swap_config[pos.row][pos.col].col); swap_state[pos.row] |= col_bit; } else { swap_state[pos.row] &= ~(col_bit); diff --git a/tmk_core/common/action.h b/tmk_core/common/action.h index 9a991de1c2..6c84561785 100644 --- a/tmk_core/common/action.h +++ b/tmk_core/common/action.h @@ -78,7 +78,7 @@ extern bool disable_action_cache; /* Code for handling one-handed key modifiers. */ #ifdef SWAP_HANDS_ENABLE extern bool swap_hands; -extern const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS]; +extern const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS]; # if (MATRIX_COLS <= 8) typedef uint8_t swap_state_row_t; # elif (MATRIX_COLS <= 16) -- cgit v1.2.3 From ffe81cbec135e9a72d0df5e447fd8fc90afcf7d9 Mon Sep 17 00:00:00 2001 From: Sergey Vlasov Date: Mon, 10 May 2021 19:21:13 +0300 Subject: Fix another bin/qmk reference (#12856) --- tmk_core/avr.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tmk_core') diff --git a/tmk_core/avr.mk b/tmk_core/avr.mk index 2bc7cc9553..521305f1b4 100644 --- a/tmk_core/avr.mk +++ b/tmk_core/avr.mk @@ -294,7 +294,7 @@ ifneq ($(strip $(BOOTLOADER)), qmk-dfu) $(error Please set BOOTLOADER = qmk-dfu first!) endif make -C lib/lufa/Bootloaders/DFU/ clean - bin/qmk generate-dfu-header --quiet --keyboard $(KEYBOARD) --output lib/lufa/Bootloaders/DFU/Keyboard.h + $(QMK_BIN) generate-dfu-header --quiet --keyboard $(KEYBOARD) --output lib/lufa/Bootloaders/DFU/Keyboard.h $(eval MAX_SIZE=$(shell n=`$(CC) -E -mmcu=$(MCU) $(CFLAGS) $(OPT_DEFS) tmk_core/common/avr/bootloader_size.c 2> /dev/null | sed -ne 's/\r//;/^#/n;/^AVR_SIZE:/,$${s/^AVR_SIZE: //;p;}'` && echo $$(($$n)) || echo 0)) $(eval PROGRAM_SIZE_KB=$(shell n=`expr $(MAX_SIZE) / 1024` && echo $$(($$n)) || echo 0)) $(eval BOOT_SECTION_SIZE_KB=$(shell n=`expr $(BOOTLOADER_SIZE) / 1024` && echo $$(($$n)) || echo 0)) -- cgit v1.2.3 From d84cbc3cecd0254df776fc56e9baaa1b1823a6d1 Mon Sep 17 00:00:00 2001 From: Ryan Date: Wed, 12 May 2021 01:17:28 +1000 Subject: Fix syntax error when compiling for ARM (#12866) --- tmk_core/rules.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tmk_core') diff --git a/tmk_core/rules.mk b/tmk_core/rules.mk index 8dbed35fb5..fc2dc68be2 100644 --- a/tmk_core/rules.mk +++ b/tmk_core/rules.mk @@ -327,9 +327,9 @@ gccversion : @$(SILENT) || printf "$(MSG_BIN) $@" | $(AWK_CMD) @$(BUILD_CMD) if [ ! -z "$(DFU_SUFFIX_ARGS)" ]; then \ - #$(SILENT) || printf "$(MSG_EXECUTING) '$(DFU_SUFFIX) $(DFU_SUFFIX_ARGS) -a $(BUILD_DIR)/$(TARGET).bin 1>/dev/null':\n" ;\ $(DFU_SUFFIX) $(DFU_SUFFIX_ARGS) -a $(BUILD_DIR)/$(TARGET).bin 1>/dev/null ;\ fi + #$(SILENT) || printf "$(MSG_EXECUTING) '$(DFU_SUFFIX) $(DFU_SUFFIX_ARGS) -a $(BUILD_DIR)/$(TARGET).bin 1>/dev/null':\n" ;\ $(COPY) $(BUILD_DIR)/$(TARGET).bin $(TARGET).bin; BEGIN = gccversion sizebefore -- cgit v1.2.3 From da0c551692b117e4f91ca3e446155027290e3c96 Mon Sep 17 00:00:00 2001 From: Drashna Jaelre Date: Wed, 12 May 2021 18:24:44 -0700 Subject: Add missing LED Matrix suspend code to suspend.c (#12878) Co-authored-by: Ryan --- tmk_core/common/avr/suspend.c | 7 +++++++ tmk_core/common/chibios/suspend.c | 8 ++++++++ 2 files changed, 15 insertions(+) (limited to 'tmk_core') diff --git a/tmk_core/common/avr/suspend.c b/tmk_core/common/avr/suspend.c index e9ee0aefdd..690d7f38ca 100644 --- a/tmk_core/common/avr/suspend.c +++ b/tmk_core/common/avr/suspend.c @@ -163,6 +163,9 @@ void suspend_power_down(void) { rgblight_suspend(); # endif +# if defined(LED_MATRIX_ENABLE) + led_matrix_set_suspend_state(true); +# endif # if defined(RGB_MATRIX_ENABLE) rgb_matrix_set_suspend_state(true); # endif @@ -218,6 +221,10 @@ void suspend_wakeup_init(void) { #if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE) rgblight_wakeup(); #endif + +#if defined(LED_MATRIX_ENABLE) + led_matrix_set_suspend_state(false); +#endif #if defined(RGB_MATRIX_ENABLE) rgb_matrix_set_suspend_state(false); #endif diff --git a/tmk_core/common/chibios/suspend.c b/tmk_core/common/chibios/suspend.c index 14a9aecb31..38517e06f0 100644 --- a/tmk_core/common/chibios/suspend.c +++ b/tmk_core/common/chibios/suspend.c @@ -83,6 +83,10 @@ void suspend_power_down(void) { #if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE) rgblight_suspend(); #endif + +#if defined(LED_MATRIX_ENABLE) + led_matrix_set_suspend_state(true); +#endif #if defined(RGB_MATRIX_ENABLE) rgb_matrix_set_suspend_state(true); #endif @@ -154,6 +158,10 @@ void suspend_wakeup_init(void) { #if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE) rgblight_wakeup(); #endif + +#if defined(LED_MATRIX_ENABLE) + led_matrix_set_suspend_state(false); +#endif #if defined(RGB_MATRIX_ENABLE) rgb_matrix_set_suspend_state(false); #endif -- cgit v1.2.3 From 58142f0726147d538167ff3ab793743348f40dcd Mon Sep 17 00:00:00 2001 From: Nick Brassel Date: Tue, 18 May 2021 17:02:28 +1000 Subject: Fixup housekeeping from being invoked twice per loop. (#12933) --- tmk_core/common/keyboard.c | 12 +++++++++--- tmk_core/common/keyboard.h | 5 +++-- tmk_core/protocol/arm_atsam/main_arm_atsam.c | 3 +++ tmk_core/protocol/chibios/main.c | 3 +-- tmk_core/protocol/lufa/lufa.c | 3 +-- tmk_core/protocol/vusb/main.c | 3 +-- 6 files changed, 18 insertions(+), 11 deletions(-) (limited to 'tmk_core') diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c index 24baf41c00..3d6092e71c 100644 --- a/tmk_core/common/keyboard.c +++ b/tmk_core/common/keyboard.c @@ -280,6 +280,15 @@ __attribute__((weak)) void housekeeping_task_kb(void) {} */ __attribute__((weak)) void housekeeping_task_user(void) {} +/** \brief housekeeping_task + * + * Invokes hooks for executing code after QMK is done after each loop iteration. + */ +void housekeeping_task(void) { + housekeeping_task_kb(); + housekeeping_task_user(); +} + /** \brief keyboard_init * * FIXME: needs doc @@ -374,9 +383,6 @@ void keyboard_task(void) { bool encoders_changed = false; #endif - housekeeping_task_kb(); - housekeeping_task_user(); - uint8_t matrix_changed = matrix_scan(); if (matrix_changed) last_matrix_activity_trigger(); diff --git a/tmk_core/common/keyboard.h b/tmk_core/common/keyboard.h index eaf74bac58..779973f1d6 100644 --- a/tmk_core/common/keyboard.h +++ b/tmk_core/common/keyboard.h @@ -70,8 +70,9 @@ void keyboard_pre_init_user(void); void keyboard_post_init_kb(void); void keyboard_post_init_user(void); -void housekeeping_task_kb(void); -void housekeeping_task_user(void); +void housekeeping_task(void); // To be executed by the main loop in each backend TMK protocol +void housekeeping_task_kb(void); // To be overridden by keyboard-level code +void housekeeping_task_user(void); // To be overridden by user/keymap-level code uint32_t last_input_activity_time(void); // Timestamp of the last matrix or encoder activity uint32_t last_input_activity_elapsed(void); // Number of milliseconds since the last matrix or encoder activity diff --git a/tmk_core/protocol/arm_atsam/main_arm_atsam.c b/tmk_core/protocol/arm_atsam/main_arm_atsam.c index e4e79d3510..ce0f54593c 100644 --- a/tmk_core/protocol/arm_atsam/main_arm_atsam.c +++ b/tmk_core/protocol/arm_atsam/main_arm_atsam.c @@ -305,6 +305,9 @@ int main(void) { // dprintf("5v=%u 5vu=%u dlow=%u dhi=%u gca=%u gcd=%u\r\n", v_5v, v_5v_avg, v_5v_avg - V5_LOW, v_5v_avg - V5_HIGH, gcr_actual, gcr_desired); } #endif // CONSOLE_ENABLE + + // Run housekeeping + housekeeping_task(); } return 1; diff --git a/tmk_core/protocol/chibios/main.c b/tmk_core/protocol/chibios/main.c index e2ec011186..199741594a 100644 --- a/tmk_core/protocol/chibios/main.c +++ b/tmk_core/protocol/chibios/main.c @@ -257,7 +257,6 @@ int main(void) { #endif // Run housekeeping - housekeeping_task_kb(); - housekeeping_task_user(); + housekeeping_task(); } } diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c index 85d71d0835..63619fdb3b 100644 --- a/tmk_core/protocol/lufa/lufa.c +++ b/tmk_core/protocol/lufa/lufa.c @@ -1107,8 +1107,7 @@ int main(void) { #endif // Run housekeeping - housekeeping_task_kb(); - housekeeping_task_user(); + housekeeping_task(); } } diff --git a/tmk_core/protocol/vusb/main.c b/tmk_core/protocol/vusb/main.c index 2de4f6a80a..53926a7493 100644 --- a/tmk_core/protocol/vusb/main.c +++ b/tmk_core/protocol/vusb/main.c @@ -173,8 +173,7 @@ int main(void) { #endif // Run housekeeping - housekeeping_task_kb(); - housekeeping_task_user(); + housekeeping_task(); } } } -- cgit v1.2.3 From 06aea834c420d5c11bbcf64d37596cb0cee9af98 Mon Sep 17 00:00:00 2001 From: Ryan Date: Thu, 27 May 2021 15:21:15 +1000 Subject: Backlight: add defines for default level and breathing state (#12560) --- docs/feature_backlight.md | 20 +++++++++++--------- quantum/backlight/backlight.c | 23 ++++++++++++++++++++--- quantum/backlight/backlight.h | 4 ++++ tmk_core/common/eeconfig.c | 11 ----------- tmk_core/common/eeconfig.h | 5 ----- 5 files changed, 35 insertions(+), 28 deletions(-) (limited to 'tmk_core') diff --git a/docs/feature_backlight.md b/docs/feature_backlight.md index 74511dd43f..d47ecc6824 100644 --- a/docs/feature_backlight.md +++ b/docs/feature_backlight.md @@ -62,15 +62,17 @@ Valid driver values are `pwm`, `software`, `custom` or `no`. See below for help To configure the backlighting, `#define` these in your `config.h`: -| Define | Default | Description | -|------------------------|---------------|-------------------------------------------------------------------------------------------------------------------| -| `BACKLIGHT_PIN` | *Not defined* | The pin that controls the LED(s) | -| `BACKLIGHT_LEVELS` | `3` | The number of brightness levels (maximum 31 excluding off) | -| `BACKLIGHT_CAPS_LOCK` | *Not defined* | Enable Caps Lock indicator using backlight (for keyboards without dedicated LED) | -| `BACKLIGHT_BREATHING` | *Not defined* | Enable backlight breathing, if supported | -| `BREATHING_PERIOD` | `6` | The length of one backlight "breath" in seconds | -| `BACKLIGHT_ON_STATE` | `1` | The state of the backlight pin when the backlight is "on" - `1` for high, `0` for low | -| `BACKLIGHT_LIMIT_VAL ` | `255` | The maximum duty cycle of the backlight -- `255` allows for full brightness, any lower will decrease the maximum. | +|Define |Default |Description | +|-----------------------------|------------------|-----------------------------------------------------------------------------------------------------------------| +|`BACKLIGHT_PIN` |*Not defined* |The pin that controls the LED(s) | +|`BACKLIGHT_LEVELS` |`3` |The number of brightness levels (maximum 31 excluding off) | +|`BACKLIGHT_CAPS_LOCK` |*Not defined* |Enable Caps Lock indicator using backlight (for keyboards without dedicated LED) | +|`BACKLIGHT_BREATHING` |*Not defined* |Enable backlight breathing, if supported | +|`BREATHING_PERIOD` |`6` |The length of one backlight "breath" in seconds | +|`BACKLIGHT_ON_STATE` |`1` |The state of the backlight pin when the backlight is "on" - `1` for high, `0` for low | +|`BACKLIGHT_LIMIT_VAL` |`255` |The maximum duty cycle of the backlight -- `255` allows for full brightness, any lower will decrease the maximum.| +|`BACKLIGHT_DEFAULT_LEVEL` |`BACKLIGHT_LEVELS`|The default backlight level to use upon clearing the EEPROM | +|`BACKLIGHT_DEFAULT_BREATHING`|*Not defined* |Whether to enable backlight breathing upon clearing the EEPROM | Unless you are designing your own keyboard, you generally should not need to change the `BACKLIGHT_PIN` or `BACKLIGHT_ON_STATE`. diff --git a/quantum/backlight/backlight.c b/quantum/backlight/backlight.c index 113beb832f..1bc276899c 100644 --- a/quantum/backlight/backlight.c +++ b/quantum/backlight/backlight.c @@ -22,6 +22,10 @@ along with this program. If not, see . backlight_config_t backlight_config; +#ifndef BACKLIGHT_DEFAULT_LEVEL +# define BACKLIGHT_DEFAULT_LEVEL BACKLIGHT_LEVELS +#endif + #ifdef BACKLIGHT_BREATHING // TODO: migrate to backlight_config_t static uint8_t breathing_period = BREATHING_PERIOD; @@ -35,6 +39,7 @@ void backlight_init(void) { /* check signature */ if (!eeconfig_is_enabled()) { eeconfig_init(); + eeconfig_update_backlight_default(); } backlight_config.raw = eeconfig_read_backlight(); if (backlight_config.level > BACKLIGHT_LEVELS) { @@ -152,11 +157,23 @@ void backlight_level(uint8_t level) { eeconfig_update_backlight(backlight_config.raw); } -/** \brief Update current backlight state to EEPROM - * - */ +uint8_t eeconfig_read_backlight(void) { return eeprom_read_byte(EECONFIG_BACKLIGHT); } + +void eeconfig_update_backlight(uint8_t val) { eeprom_update_byte(EECONFIG_BACKLIGHT, val); } + void eeconfig_update_backlight_current(void) { eeconfig_update_backlight(backlight_config.raw); } +void eeconfig_update_backlight_default(void) { + backlight_config.enable = 1; +#ifdef BACKLIGHT_DEFAULT_BREATHING + backlight_config.breathing = 1; +#else + backlight_config.breathing = 0; +#endif + backlight_config.level = BACKLIGHT_DEFAULT_LEVEL; + eeconfig_update_backlight(backlight_config.raw); +} + /** \brief Get backlight level * * FIXME: needs doc diff --git a/quantum/backlight/backlight.h b/quantum/backlight/backlight.h index 3e506737d4..c30c70fd62 100644 --- a/quantum/backlight/backlight.h +++ b/quantum/backlight/backlight.h @@ -55,7 +55,11 @@ void backlight_decrease(void); void backlight_level_noeeprom(uint8_t level); void backlight_level(uint8_t level); uint8_t get_backlight_level(void); + +uint8_t eeconfig_read_backlight(void); +void eeconfig_update_backlight(uint8_t val); void eeconfig_update_backlight_current(void); +void eeconfig_update_backlight_default(void); // implementation specific void backlight_init_ports(void); diff --git a/tmk_core/common/eeconfig.c b/tmk_core/common/eeconfig.c index 92a5092176..ffa56ab56d 100644 --- a/tmk_core/common/eeconfig.c +++ b/tmk_core/common/eeconfig.c @@ -155,17 +155,6 @@ void eeconfig_update_keymap(uint16_t val) { eeprom_update_byte(EECONFIG_KEYMAP_UPPER_BYTE, (val >> 8) & 0xFF); } -/** \brief eeconfig read backlight - * - * FIXME: needs doc - */ -uint8_t eeconfig_read_backlight(void) { return eeprom_read_byte(EECONFIG_BACKLIGHT); } -/** \brief eeconfig update backlight - * - * FIXME: needs doc - */ -void eeconfig_update_backlight(uint8_t val) { eeprom_update_byte(EECONFIG_BACKLIGHT, val); } - /** \brief eeconfig read audio * * FIXME: needs doc diff --git a/tmk_core/common/eeconfig.h b/tmk_core/common/eeconfig.h index 9e18fd4e15..a88071729d 100644 --- a/tmk_core/common/eeconfig.h +++ b/tmk_core/common/eeconfig.h @@ -94,11 +94,6 @@ void eeconfig_update_default_layer(uint8_t val); uint16_t eeconfig_read_keymap(void); void eeconfig_update_keymap(uint16_t val); -#ifdef BACKLIGHT_ENABLE -uint8_t eeconfig_read_backlight(void); -void eeconfig_update_backlight(uint8_t val); -#endif - #ifdef AUDIO_ENABLE uint8_t eeconfig_read_audio(void); void eeconfig_update_audio(uint8_t val); -- cgit v1.2.3 From 7d1194de01ea94f065bd5176607b4d66279ef51b Mon Sep 17 00:00:00 2001 From: James Young Date: Sat, 29 May 2021 13:53:10 -0700 Subject: run: qmk cformat --core-only --- drivers/chibios/analog.c | 2 +- drivers/chibios/serial_usart.h | 20 ++++-- quantum/led_matrix_animations/alpha_mods_anim.h | 2 +- quantum/led_matrix_animations/band_anim.h | 6 +- quantum/led_matrix_animations/band_pinwheel_anim.h | 10 +-- quantum/led_matrix_animations/band_spiral_anim.h | 10 +-- quantum/led_matrix_animations/breathing_anim.h | 2 +- .../led_matrix_animations/cycle_left_right_anim.h | 10 +-- quantum/led_matrix_animations/cycle_out_in_anim.h | 10 +-- quantum/led_matrix_animations/cycle_up_down_anim.h | 10 +-- quantum/led_matrix_animations/dual_beacon_anim.h | 10 +-- .../led_matrix_animations/solid_reactive_cross.h | 12 ++-- .../led_matrix_animations/solid_reactive_nexus.h | 12 ++-- .../solid_reactive_simple_anim.h | 12 ++-- .../led_matrix_animations/solid_reactive_wide.h | 12 ++-- quantum/led_matrix_animations/solid_splash_anim.h | 12 ++-- .../led_matrix_animations/wave_left_right_anim.h | 10 +-- quantum/led_matrix_animations/wave_up_down_anim.h | 10 +-- quantum/led_matrix_drivers.c | 2 +- quantum/quantum_keycodes.h | 12 ++-- quantum/rgb_matrix_drivers.c | 6 +- quantum/rgblight.c | 8 +-- quantum/split_common/transport.c | 34 ++++----- tmk_core/common/action.c | 83 ++++++++++------------ tmk_core/common/action.h | 2 +- tmk_core/common/chibios/sleep_led.c | 4 +- tmk_core/common/keyboard.h | 6 +- 27 files changed, 139 insertions(+), 190 deletions(-) (limited to 'tmk_core') diff --git a/drivers/chibios/analog.c b/drivers/chibios/analog.c index b1081623d3..8c476fcac2 100644 --- a/drivers/chibios/analog.c +++ b/drivers/chibios/analog.c @@ -123,7 +123,7 @@ static ADCConversionGroup adcConversionGroup = { .smpr = ADC_SAMPLING_RATE, #elif defined(USE_ADCV2) # if !defined(STM32F1XX) - .cr2 = ADC_CR2_SWSTART, // F103 seem very unhappy with, F401 seems very unhappy without... + .cr2 = ADC_CR2_SWSTART, // F103 seem very unhappy with, F401 seems very unhappy without... # endif .smpr2 = ADC_SMPR2_SMP_AN0(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN1(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN2(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN3(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN4(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN5(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN6(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN7(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN8(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN9(ADC_SAMPLING_RATE), .smpr1 = ADC_SMPR1_SMP_AN10(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN11(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN12(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN13(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN14(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN15(ADC_SAMPLING_RATE), diff --git a/drivers/chibios/serial_usart.h b/drivers/chibios/serial_usart.h index d35b5d12c6..fee7b4d159 100644 --- a/drivers/chibios/serial_usart.h +++ b/drivers/chibios/serial_usart.h @@ -40,13 +40,25 @@ #endif #if defined(USART1_REMAP) -# define USART_REMAP do { (AFIO->MAPR |= AFIO_MAPR_USART1_REMAP); } while(0) +# define USART_REMAP \ + do { \ + (AFIO->MAPR |= AFIO_MAPR_USART1_REMAP); \ + } while (0) #elif defined(USART2_REMAP) -# define USART_REMAP do { (AFIO->MAPR |= AFIO_MAPR_USART2_REMAP); } while(0) +# define USART_REMAP \ + do { \ + (AFIO->MAPR |= AFIO_MAPR_USART2_REMAP); \ + } while (0) #elif defined(USART3_PARTIALREMAP) -# define USART_REMAP do { (AFIO->MAPR |= AFIO_MAPR_USART3_REMAP_PARTIALREMAP); } while(0) +# define USART_REMAP \ + do { \ + (AFIO->MAPR |= AFIO_MAPR_USART3_REMAP_PARTIALREMAP); \ + } while (0) #elif defined(USART3_FULLREMAP) -# define USART_REMAP do { (AFIO->MAPR |= AFIO_MAPR_USART3_REMAP_FULLREMAP); } while(0) +# define USART_REMAP \ + do { \ + (AFIO->MAPR |= AFIO_MAPR_USART3_REMAP_FULLREMAP); \ + } while (0) #endif #ifndef SELECT_SOFT_SERIAL_SPEED diff --git a/quantum/led_matrix_animations/alpha_mods_anim.h b/quantum/led_matrix_animations/alpha_mods_anim.h index a4638fde69..6f69f6892b 100644 --- a/quantum/led_matrix_animations/alpha_mods_anim.h +++ b/quantum/led_matrix_animations/alpha_mods_anim.h @@ -21,4 +21,4 @@ bool ALPHAS_MODS(effect_params_t* params) { } # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_LED_MATRIX_ALPHAS_MODS +#endif // DISABLE_LED_MATRIX_ALPHAS_MODS diff --git a/quantum/led_matrix_animations/band_anim.h b/quantum/led_matrix_animations/band_anim.h index 4a2b746a76..523dba1b78 100644 --- a/quantum/led_matrix_animations/band_anim.h +++ b/quantum/led_matrix_animations/band_anim.h @@ -7,9 +7,7 @@ static uint8_t BAND_math(uint8_t val, uint8_t i, uint8_t time) { return scale8(v < 0 ? 0 : v, val); } -bool BAND(effect_params_t* params) { - return effect_runner_i(params, &BAND_math); -} +bool BAND(effect_params_t* params) { return effect_runner_i(params, &BAND_math); } # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_LED_MATRIX_BAND +#endif // DISABLE_LED_MATRIX_BAND diff --git a/quantum/led_matrix_animations/band_pinwheel_anim.h b/quantum/led_matrix_animations/band_pinwheel_anim.h index 9836320d2a..fb3b835cad 100644 --- a/quantum/led_matrix_animations/band_pinwheel_anim.h +++ b/quantum/led_matrix_animations/band_pinwheel_anim.h @@ -2,13 +2,9 @@ LED_MATRIX_EFFECT(BAND_PINWHEEL) # ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS -static uint8_t BAND_PINWHEEL_math(uint8_t val, int16_t dx, int16_t dy, uint8_t time) { - return scale8(val - time - atan2_8(dy, dx) * 3, val); -} +static uint8_t BAND_PINWHEEL_math(uint8_t val, int16_t dx, int16_t dy, uint8_t time) { return scale8(val - time - atan2_8(dy, dx) * 3, val); } -bool BAND_PINWHEEL(effect_params_t* params) { - return effect_runner_dx_dy(params, &BAND_PINWHEEL_math); -} +bool BAND_PINWHEEL(effect_params_t* params) { return effect_runner_dx_dy(params, &BAND_PINWHEEL_math); } # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_LED_MATRIX_BAND_PINWHEEL +#endif // DISABLE_LED_MATRIX_BAND_PINWHEEL diff --git a/quantum/led_matrix_animations/band_spiral_anim.h b/quantum/led_matrix_animations/band_spiral_anim.h index be17c03aad..fca22aad9c 100644 --- a/quantum/led_matrix_animations/band_spiral_anim.h +++ b/quantum/led_matrix_animations/band_spiral_anim.h @@ -2,13 +2,9 @@ LED_MATRIX_EFFECT(BAND_SPIRAL) # ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS -static uint8_t BAND_SPIRAL_math(uint8_t val, int16_t dx, int16_t dy, uint8_t dist, uint8_t time) { - return scale8(val + dist - time - atan2_8(dy, dx), val); -} +static uint8_t BAND_SPIRAL_math(uint8_t val, int16_t dx, int16_t dy, uint8_t dist, uint8_t time) { return scale8(val + dist - time - atan2_8(dy, dx), val); } -bool BAND_SPIRAL(effect_params_t* params) { - return effect_runner_dx_dy_dist(params, &BAND_SPIRAL_math); -} +bool BAND_SPIRAL(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &BAND_SPIRAL_math); } # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_LED_MATRIX_BAND_SPIRAL +#endif // DISABLE_LED_MATRIX_BAND_SPIRAL diff --git a/quantum/led_matrix_animations/breathing_anim.h b/quantum/led_matrix_animations/breathing_anim.h index 4f49f50690..00310e3f65 100644 --- a/quantum/led_matrix_animations/breathing_anim.h +++ b/quantum/led_matrix_animations/breathing_anim.h @@ -16,4 +16,4 @@ bool BREATHING(effect_params_t* params) { } # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_LED_MATRIX_BREATHING +#endif // DISABLE_LED_MATRIX_BREATHING diff --git a/quantum/led_matrix_animations/cycle_left_right_anim.h b/quantum/led_matrix_animations/cycle_left_right_anim.h index 404fda26f5..51e81d57ca 100644 --- a/quantum/led_matrix_animations/cycle_left_right_anim.h +++ b/quantum/led_matrix_animations/cycle_left_right_anim.h @@ -2,13 +2,9 @@ LED_MATRIX_EFFECT(CYCLE_LEFT_RIGHT) # ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS -static uint8_t CYCLE_LEFT_RIGHT_math(uint8_t val, uint8_t i, uint8_t time) { - return scale8(g_led_config.point[i].x - time, val); -} +static uint8_t CYCLE_LEFT_RIGHT_math(uint8_t val, uint8_t i, uint8_t time) { return scale8(g_led_config.point[i].x - time, val); } -bool CYCLE_LEFT_RIGHT(effect_params_t* params) { - return effect_runner_i(params, &CYCLE_LEFT_RIGHT_math); -} +bool CYCLE_LEFT_RIGHT(effect_params_t* params) { return effect_runner_i(params, &CYCLE_LEFT_RIGHT_math); } # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_LED_MATRIX_CYCLE_LEFT_RIGHT +#endif // DISABLE_LED_MATRIX_CYCLE_LEFT_RIGHT diff --git a/quantum/led_matrix_animations/cycle_out_in_anim.h b/quantum/led_matrix_animations/cycle_out_in_anim.h index 3f5fc5b187..f62061552c 100644 --- a/quantum/led_matrix_animations/cycle_out_in_anim.h +++ b/quantum/led_matrix_animations/cycle_out_in_anim.h @@ -2,13 +2,9 @@ LED_MATRIX_EFFECT(CYCLE_OUT_IN) # ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS -static uint8_t CYCLE_OUT_IN_math(uint8_t val, int16_t dx, int16_t dy, uint8_t dist, uint8_t time) { - return scale8(3 * dist / 2 + time, val); -} +static uint8_t CYCLE_OUT_IN_math(uint8_t val, int16_t dx, int16_t dy, uint8_t dist, uint8_t time) { return scale8(3 * dist / 2 + time, val); } -bool CYCLE_OUT_IN(effect_params_t* params) { - return effect_runner_dx_dy_dist(params, &CYCLE_OUT_IN_math); -} +bool CYCLE_OUT_IN(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &CYCLE_OUT_IN_math); } # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_LED_MATRIX_CYCLE_OUT_IN +#endif // DISABLE_LED_MATRIX_CYCLE_OUT_IN diff --git a/quantum/led_matrix_animations/cycle_up_down_anim.h b/quantum/led_matrix_animations/cycle_up_down_anim.h index 25fc211b17..bd1d125672 100644 --- a/quantum/led_matrix_animations/cycle_up_down_anim.h +++ b/quantum/led_matrix_animations/cycle_up_down_anim.h @@ -2,13 +2,9 @@ LED_MATRIX_EFFECT(CYCLE_UP_DOWN) # ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS -static uint8_t CYCLE_UP_DOWN_math(uint8_t val, uint8_t i, uint8_t time) { - return scale8(g_led_config.point[i].y - time, val); -} +static uint8_t CYCLE_UP_DOWN_math(uint8_t val, uint8_t i, uint8_t time) { return scale8(g_led_config.point[i].y - time, val); } -bool CYCLE_UP_DOWN(effect_params_t* params) { - return effect_runner_i(params, &CYCLE_UP_DOWN_math); -} +bool CYCLE_UP_DOWN(effect_params_t* params) { return effect_runner_i(params, &CYCLE_UP_DOWN_math); } # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_LED_MATRIX_CYCLE_UP_DOWN +#endif // DISABLE_LED_MATRIX_CYCLE_UP_DOWN diff --git a/quantum/led_matrix_animations/dual_beacon_anim.h b/quantum/led_matrix_animations/dual_beacon_anim.h index 1fa1df1395..9b8a7877c9 100644 --- a/quantum/led_matrix_animations/dual_beacon_anim.h +++ b/quantum/led_matrix_animations/dual_beacon_anim.h @@ -2,13 +2,9 @@ LED_MATRIX_EFFECT(DUAL_BEACON) # ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS -static uint8_t DUAL_BEACON_math(uint8_t val, int8_t sin, int8_t cos, uint8_t i, uint8_t time) { - return scale8(((g_led_config.point[i].y - k_led_matrix_center.y) * cos + (g_led_config.point[i].x - k_led_matrix_center.x) * sin) / 128, val); -} +static uint8_t DUAL_BEACON_math(uint8_t val, int8_t sin, int8_t cos, uint8_t i, uint8_t time) { return scale8(((g_led_config.point[i].y - k_led_matrix_center.y) * cos + (g_led_config.point[i].x - k_led_matrix_center.x) * sin) / 128, val); } -bool DUAL_BEACON(effect_params_t* params) { - return effect_runner_sin_cos_i(params, &DUAL_BEACON_math); -} +bool DUAL_BEACON(effect_params_t* params) { return effect_runner_sin_cos_i(params, &DUAL_BEACON_math); } # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_LED_MATRIX_DUAL_BEACON +#endif // DISABLE_LED_MATRIX_DUAL_BEACON diff --git a/quantum/led_matrix_animations/solid_reactive_cross.h b/quantum/led_matrix_animations/solid_reactive_cross.h index a50d1fc629..f402d99b37 100644 --- a/quantum/led_matrix_animations/solid_reactive_cross.h +++ b/quantum/led_matrix_animations/solid_reactive_cross.h @@ -23,17 +23,13 @@ static uint8_t SOLID_REACTIVE_CROSS_math(uint8_t val, int16_t dx, int16_t dy, ui } # ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_CROSS -bool SOLID_REACTIVE_CROSS(effect_params_t* params) { - return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_REACTIVE_CROSS_math); -} +bool SOLID_REACTIVE_CROSS(effect_params_t* params) { return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_REACTIVE_CROSS_math); } # endif # ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS -bool SOLID_REACTIVE_MULTICROSS(effect_params_t* params) { - return effect_runner_reactive_splash(0, params, &SOLID_REACTIVE_CROSS_math); -} +bool SOLID_REACTIVE_MULTICROSS(effect_params_t* params) { return effect_runner_reactive_splash(0, params, &SOLID_REACTIVE_CROSS_math); } # endif # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS -# endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_CROSS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS) -#endif // LED_MATRIX_KEYREACTIVE_ENABLED +# endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_CROSS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS) +#endif // LED_MATRIX_KEYREACTIVE_ENABLED diff --git a/quantum/led_matrix_animations/solid_reactive_nexus.h b/quantum/led_matrix_animations/solid_reactive_nexus.h index 4638aac5a4..4d0d252263 100644 --- a/quantum/led_matrix_animations/solid_reactive_nexus.h +++ b/quantum/led_matrix_animations/solid_reactive_nexus.h @@ -20,17 +20,13 @@ static uint8_t SOLID_REACTIVE_NEXUS_math(uint8_t val, int16_t dx, int16_t dy, ui } # ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS -bool SOLID_REACTIVE_NEXUS(effect_params_t* params) { - return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_REACTIVE_NEXUS_math); -} +bool SOLID_REACTIVE_NEXUS(effect_params_t* params) { return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_REACTIVE_NEXUS_math); } # endif # ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS -bool SOLID_REACTIVE_MULTINEXUS(effect_params_t* params) { - return effect_runner_reactive_splash(0, params, &SOLID_REACTIVE_NEXUS_math); -} +bool SOLID_REACTIVE_MULTINEXUS(effect_params_t* params) { return effect_runner_reactive_splash(0, params, &SOLID_REACTIVE_NEXUS_math); } # endif # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS -# endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS) -#endif // LED_MATRIX_KEYREACTIVE_ENABLED +# endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS) +#endif // LED_MATRIX_KEYREACTIVE_ENABLED diff --git a/quantum/led_matrix_animations/solid_reactive_simple_anim.h b/quantum/led_matrix_animations/solid_reactive_simple_anim.h index e1166a4fb6..30e2527f60 100644 --- a/quantum/led_matrix_animations/solid_reactive_simple_anim.h +++ b/quantum/led_matrix_animations/solid_reactive_simple_anim.h @@ -3,14 +3,10 @@ LED_MATRIX_EFFECT(SOLID_REACTIVE_SIMPLE) # ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS -static uint8_t SOLID_REACTIVE_SIMPLE_math(uint8_t val, uint16_t offset) { - return scale8(255 - offset, val); -} +static uint8_t SOLID_REACTIVE_SIMPLE_math(uint8_t val, uint16_t offset) { return scale8(255 - offset, val); } -bool SOLID_REACTIVE_SIMPLE(effect_params_t* params) { - return effect_runner_reactive(params, &SOLID_REACTIVE_SIMPLE_math); -} +bool SOLID_REACTIVE_SIMPLE(effect_params_t* params) { return effect_runner_reactive(params, &SOLID_REACTIVE_SIMPLE_math); } # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS -# endif // DISABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE -#endif // LED_MATRIX_KEYREACTIVE_ENABLED +# endif // DISABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE +#endif // LED_MATRIX_KEYREACTIVE_ENABLED diff --git a/quantum/led_matrix_animations/solid_reactive_wide.h b/quantum/led_matrix_animations/solid_reactive_wide.h index 4bcaba331e..34a230c259 100644 --- a/quantum/led_matrix_animations/solid_reactive_wide.h +++ b/quantum/led_matrix_animations/solid_reactive_wide.h @@ -18,17 +18,13 @@ static uint8_t SOLID_REACTIVE_WIDE_math(uint8_t val, int16_t dx, int16_t dy, uin } # ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_WIDE -bool SOLID_REACTIVE_WIDE(effect_params_t* params) { - return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_REACTIVE_WIDE_math); -} +bool SOLID_REACTIVE_WIDE(effect_params_t* params) { return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_REACTIVE_WIDE_math); } # endif # ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE -bool SOLID_REACTIVE_MULTIWIDE(effect_params_t* params) { - return effect_runner_reactive_splash(0, params, &SOLID_REACTIVE_WIDE_math); -} +bool SOLID_REACTIVE_MULTIWIDE(effect_params_t* params) { return effect_runner_reactive_splash(0, params, &SOLID_REACTIVE_WIDE_math); } # endif # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS -# endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_WIDE) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE) -#endif // LED_MATRIX_KEYREACTIVE_ENABLED +# endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_WIDE) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE) +#endif // LED_MATRIX_KEYREACTIVE_ENABLED diff --git a/quantum/led_matrix_animations/solid_splash_anim.h b/quantum/led_matrix_animations/solid_splash_anim.h index 3e9046640e..4f6ba3d343 100644 --- a/quantum/led_matrix_animations/solid_splash_anim.h +++ b/quantum/led_matrix_animations/solid_splash_anim.h @@ -18,17 +18,13 @@ uint8_t SOLID_SPLASH_math(uint8_t val, int16_t dx, int16_t dy, uint8_t dist, uin } # ifndef DISABLE_LED_MATRIX_SOLID_SPLASH -bool SOLID_SPLASH(effect_params_t* params) { - return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_SPLASH_math); -} +bool SOLID_SPLASH(effect_params_t* params) { return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_SPLASH_math); } # endif # ifndef DISABLE_LED_MATRIX_SOLID_MULTISPLASH -bool SOLID_MULTISPLASH(effect_params_t* params) { - return effect_runner_reactive_splash(0, params, &SOLID_SPLASH_math); -} +bool SOLID_MULTISPLASH(effect_params_t* params) { return effect_runner_reactive_splash(0, params, &SOLID_SPLASH_math); } # endif # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS -# endif // !defined(DISABLE_LED_MATRIX_SPLASH) && !defined(DISABLE_LED_MATRIX_MULTISPLASH) -#endif // LED_MATRIX_KEYREACTIVE_ENABLED +# endif // !defined(DISABLE_LED_MATRIX_SPLASH) && !defined(DISABLE_LED_MATRIX_MULTISPLASH) +#endif // LED_MATRIX_KEYREACTIVE_ENABLED diff --git a/quantum/led_matrix_animations/wave_left_right_anim.h b/quantum/led_matrix_animations/wave_left_right_anim.h index d547c72cee..736f22ddc5 100644 --- a/quantum/led_matrix_animations/wave_left_right_anim.h +++ b/quantum/led_matrix_animations/wave_left_right_anim.h @@ -2,13 +2,9 @@ LED_MATRIX_EFFECT(WAVE_LEFT_RIGHT) # ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS -static uint8_t WAVE_LEFT_RIGHT_math(uint8_t val, uint8_t i, uint8_t time) { - return scale8(sin8(g_led_config.point[i].x - time), val); -} +static uint8_t WAVE_LEFT_RIGHT_math(uint8_t val, uint8_t i, uint8_t time) { return scale8(sin8(g_led_config.point[i].x - time), val); } -bool WAVE_LEFT_RIGHT(effect_params_t* params) { - return effect_runner_i(params, &WAVE_LEFT_RIGHT_math); -} +bool WAVE_LEFT_RIGHT(effect_params_t* params) { return effect_runner_i(params, &WAVE_LEFT_RIGHT_math); } # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_LED_MATRIX_WAVE_LEFT_RIGHT +#endif // DISABLE_LED_MATRIX_WAVE_LEFT_RIGHT diff --git a/quantum/led_matrix_animations/wave_up_down_anim.h b/quantum/led_matrix_animations/wave_up_down_anim.h index b68ff9bbc6..3cab0597d4 100644 --- a/quantum/led_matrix_animations/wave_up_down_anim.h +++ b/quantum/led_matrix_animations/wave_up_down_anim.h @@ -2,13 +2,9 @@ LED_MATRIX_EFFECT(WAVE_UP_DOWN) # ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS -static uint8_t WAVE_UP_DOWN_math(uint8_t val, uint8_t i, uint8_t time) { - return scale8(sin8(g_led_config.point[i].y - time), val); -} +static uint8_t WAVE_UP_DOWN_math(uint8_t val, uint8_t i, uint8_t time) { return scale8(sin8(g_led_config.point[i].y - time), val); } -bool WAVE_UP_DOWN(effect_params_t* params) { - return effect_runner_i(params, &WAVE_UP_DOWN_math); -} +bool WAVE_UP_DOWN(effect_params_t* params) { return effect_runner_i(params, &WAVE_UP_DOWN_math); } # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#endif // DISABLE_LED_MATRIX_WAVE_UP_DOWN +#endif // DISABLE_LED_MATRIX_WAVE_UP_DOWN diff --git a/quantum/led_matrix_drivers.c b/quantum/led_matrix_drivers.c index f3d4bc896e..1d46b2c506 100644 --- a/quantum/led_matrix_drivers.c +++ b/quantum/led_matrix_drivers.c @@ -145,7 +145,7 @@ const led_matrix_driver_t led_matrix_driver = { .set_value = IS31FL3731_set_value, .set_value_all = IS31FL3731_set_value_all, # else - .set_value = IS31FL3733_set_value, + .set_value = IS31FL3733_set_value, .set_value_all = IS31FL3733_set_value_all, # endif }; diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h index 26021598a1..316c20fcef 100644 --- a/quantum/quantum_keycodes.h +++ b/quantum/quantum_keycodes.h @@ -760,12 +760,12 @@ enum quantum_keycodes { #define CMD_T(kc) LCMD_T(kc) #define WIN_T(kc) LWIN_T(kc) -#define C_S_T(kc) MT(MOD_LCTL | MOD_LSFT, kc) // Left Control + Shift e.g. for gnome-terminal -#define MEH_T(kc) MT(MOD_LCTL | MOD_LSFT | MOD_LALT, kc) // Meh is a less hyper version of the Hyper key -- doesn't include GUI, so just Left Control + Shift + Alt -#define LCAG_T(kc) MT(MOD_LCTL | MOD_LALT | MOD_LGUI, kc) // Left Control + Alt + GUI -#define RCAG_T(kc) MT(MOD_RCTL | MOD_RALT | MOD_RGUI, kc) // Right Control + Alt + GUI +#define C_S_T(kc) MT(MOD_LCTL | MOD_LSFT, kc) // Left Control + Shift e.g. for gnome-terminal +#define MEH_T(kc) MT(MOD_LCTL | MOD_LSFT | MOD_LALT, kc) // Meh is a less hyper version of the Hyper key -- doesn't include GUI, so just Left Control + Shift + Alt +#define LCAG_T(kc) MT(MOD_LCTL | MOD_LALT | MOD_LGUI, kc) // Left Control + Alt + GUI +#define RCAG_T(kc) MT(MOD_RCTL | MOD_RALT | MOD_RGUI, kc) // Right Control + Alt + GUI #define HYPR_T(kc) MT(MOD_LCTL | MOD_LSFT | MOD_LALT | MOD_LGUI, kc) // see http://brettterpstra.com/2012/12/08/a-useful-caps-lock-key/ -#define SGUI_T(kc) MT(MOD_LGUI | MOD_LSFT, kc) // Left Shift + GUI +#define SGUI_T(kc) MT(MOD_LGUI | MOD_LSFT, kc) // Left Shift + GUI #define SCMD_T(kc) SGUI_T(kc) #define SWIN_T(kc) SGUI_T(kc) #define LCA_T(kc) MT(MOD_LCTL | MOD_LALT, kc) // Left Control + Alt @@ -792,7 +792,7 @@ enum quantum_keycodes { #define UC_M_MA UNICODE_MODE_MAC #define UNICODE_MODE_OSX UNICODE_MODE_MAC // Deprecated alias -#define UC_M_OS UNICODE_MODE_MAC // Deprecated alias +#define UC_M_OS UNICODE_MODE_MAC // Deprecated alias #define UC_M_LN UNICODE_MODE_LNX #define UC_M_WI UNICODE_MODE_WIN #define UC_M_BS UNICODE_MODE_BSD diff --git a/quantum/rgb_matrix_drivers.c b/quantum/rgb_matrix_drivers.c index a4db86d196..896fa6d0ef 100644 --- a/quantum/rgb_matrix_drivers.c +++ b/quantum/rgb_matrix_drivers.c @@ -146,9 +146,9 @@ static void flush(void) { } const rgb_matrix_driver_t rgb_matrix_driver = { - .init = init, - .flush = flush, - .set_color = IS31FL3733_set_color, + .init = init, + .flush = flush, + .set_color = IS31FL3733_set_color, .set_color_all = IS31FL3733_set_color_all, }; # elif defined(IS31FL3737) diff --git a/quantum/rgblight.c b/quantum/rgblight.c index e4c4d555e5..baa10ec416 100644 --- a/quantum/rgblight.c +++ b/quantum/rgblight.c @@ -727,13 +727,11 @@ static uint16_t _repeat_timer; static uint8_t _times_remaining; static uint16_t _dur; -void rgblight_blink_layer(uint8_t layer, uint16_t duration_ms) { - rgblight_blink_layer_repeat(layer, duration_ms, 1); -} +void rgblight_blink_layer(uint8_t layer, uint16_t duration_ms) { rgblight_blink_layer_repeat(layer, duration_ms, 1); } void rgblight_blink_layer_repeat(uint8_t layer, uint16_t duration_ms, uint8_t times) { _times_remaining = times * 2; - _dur = duration_ms; + _dur = duration_ms; rgblight_set_layer_state(layer, true); _times_remaining--; @@ -892,7 +890,7 @@ void rgblight_update_sync(rgblight_syncinfo_t *syncinfo, bool write_to_eeprom) { animation_status.restart = true; } # endif /* RGBLIGHT_SPLIT_NO_ANIMATION_SYNC */ -# endif /* RGBLIGHT_USE_TIMER */ +# endif /* RGBLIGHT_USE_TIMER */ } #endif /* RGBLIGHT_SPLIT */ diff --git a/quantum/split_common/transport.c b/quantum/split_common/transport.c index bf942c5260..9ed0f7591b 100644 --- a/quantum/split_common/transport.c +++ b/quantum/split_common/transport.c @@ -240,38 +240,38 @@ typedef struct _Serial_s2m_buffer_t { matrix_row_t smatrix[ROWS_PER_HAND]; # ifdef ENCODER_ENABLE - uint8_t encoder_state[NUMBER_OF_ENCODERS]; + uint8_t encoder_state[NUMBER_OF_ENCODERS]; # endif } Serial_s2m_buffer_t; typedef struct _Serial_m2s_buffer_t { # ifdef SPLIT_MODS_ENABLE - uint8_t real_mods; - uint8_t weak_mods; + uint8_t real_mods; + uint8_t weak_mods; # ifndef NO_ACTION_ONESHOT - uint8_t oneshot_mods; + uint8_t oneshot_mods; # endif # endif # ifndef DISABLE_SYNC_TIMER - uint32_t sync_timer; + uint32_t sync_timer; # endif # ifdef SPLIT_TRANSPORT_MIRROR - matrix_row_t mmatrix[ROWS_PER_HAND]; + matrix_row_t mmatrix[ROWS_PER_HAND]; # endif # ifdef BACKLIGHT_ENABLE - uint8_t backlight_level; + uint8_t backlight_level; # endif # ifdef WPM_ENABLE - uint8_t current_wpm; + uint8_t current_wpm; # endif # if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) led_eeconfig_t led_matrix; bool led_suspend_state; # endif # if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) - rgb_config_t rgb_matrix; - bool rgb_suspend_state; + rgb_config_t rgb_matrix; + bool rgb_suspend_state; # endif } Serial_m2s_buffer_t; @@ -363,7 +363,7 @@ bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) // TODO: if MATRIX_COLS > 8 change to unpack() for (int i = 0; i < ROWS_PER_HAND; ++i) { - slave_matrix[i] = serial_s2m_buffer.smatrix[i]; + slave_matrix[i] = serial_s2m_buffer.smatrix[i]; # ifdef SPLIT_TRANSPORT_MIRROR serial_m2s_buffer.mmatrix[i] = master_matrix[i]; # endif @@ -380,14 +380,14 @@ bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) # ifdef WPM_ENABLE // Write wpm to slave - serial_m2s_buffer.current_wpm = get_current_wpm(); + serial_m2s_buffer.current_wpm = get_current_wpm(); # endif # ifdef SPLIT_MODS_ENABLE - serial_m2s_buffer.real_mods = get_mods(); - serial_m2s_buffer.weak_mods = get_weak_mods(); + serial_m2s_buffer.real_mods = get_mods(); + serial_m2s_buffer.weak_mods = get_weak_mods(); # ifndef NO_ACTION_ONESHOT - serial_m2s_buffer.oneshot_mods = get_oneshot_mods(); + serial_m2s_buffer.oneshot_mods = get_oneshot_mods(); # endif # endif @@ -401,7 +401,7 @@ bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) # endif # ifndef DISABLE_SYNC_TIMER - serial_m2s_buffer.sync_timer = sync_timer_read32() + SYNC_TIMER_OFFSET; + serial_m2s_buffer.sync_timer = sync_timer_read32() + SYNC_TIMER_OFFSET; # endif return true; } @@ -416,7 +416,7 @@ void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) for (int i = 0; i < ROWS_PER_HAND; ++i) { serial_s2m_buffer.smatrix[i] = slave_matrix[i]; # ifdef SPLIT_TRANSPORT_MIRROR - master_matrix[i] = serial_m2s_buffer.mmatrix[i]; + master_matrix[i] = serial_m2s_buffer.mmatrix[i]; # endif } # ifdef BACKLIGHT_ENABLE diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c index f41665b06c..bd41d28b66 100644 --- a/tmk_core/common/action.c +++ b/tmk_core/common/action.c @@ -773,10 +773,9 @@ void register_code(uint8_t code) { } #endif - else if - IS_KEY(code) { - // TODO: should push command_proc out of this block? - if (command_proc(code)) return; + else if IS_KEY (code) { + // TODO: should push command_proc out of this block? + if (command_proc(code)) return; #ifndef NO_ACTION_ONESHOT /* TODO: remove @@ -793,35 +792,33 @@ void register_code(uint8_t code) { } else */ #endif - { - // Force a new key press if the key is already pressed - // without this, keys with the same keycode, but different - // modifiers will be reported incorrectly, see issue #1708 - if (is_key_pressed(keyboard_report, code)) { - del_key(code); - send_keyboard_report(); - } - add_key(code); + { + // Force a new key press if the key is already pressed + // without this, keys with the same keycode, but different + // modifiers will be reported incorrectly, see issue #1708 + if (is_key_pressed(keyboard_report, code)) { + del_key(code); send_keyboard_report(); } - } - else if - IS_MOD(code) { - add_mods(MOD_BIT(code)); + add_key(code); send_keyboard_report(); } + } else if IS_MOD (code) { + add_mods(MOD_BIT(code)); + send_keyboard_report(); + } #ifdef EXTRAKEY_ENABLE - else if - IS_SYSTEM(code) { host_system_send(KEYCODE2SYSTEM(code)); } - else if - IS_CONSUMER(code) { host_consumer_send(KEYCODE2CONSUMER(code)); } + else if IS_SYSTEM (code) { + host_system_send(KEYCODE2SYSTEM(code)); + } else if IS_CONSUMER (code) { + host_consumer_send(KEYCODE2CONSUMER(code)); + } #endif #ifdef MOUSEKEY_ENABLE - else if - IS_MOUSEKEY(code) { - mousekey_on(code); - mousekey_send(); - } + else if IS_MOUSEKEY (code) { + mousekey_on(code); + mousekey_send(); + } #endif } @@ -866,26 +863,22 @@ void unregister_code(uint8_t code) { } #endif - else if - IS_KEY(code) { - del_key(code); - send_keyboard_report(); - } - else if - IS_MOD(code) { - del_mods(MOD_BIT(code)); - send_keyboard_report(); - } - else if - IS_SYSTEM(code) { host_system_send(0); } - else if - IS_CONSUMER(code) { host_consumer_send(0); } + else if IS_KEY (code) { + del_key(code); + send_keyboard_report(); + } else if IS_MOD (code) { + del_mods(MOD_BIT(code)); + send_keyboard_report(); + } else if IS_SYSTEM (code) { + host_system_send(0); + } else if IS_CONSUMER (code) { + host_consumer_send(0); + } #ifdef MOUSEKEY_ENABLE - else if - IS_MOUSEKEY(code) { - mousekey_off(code); - mousekey_send(); - } + else if IS_MOUSEKEY (code) { + mousekey_off(code); + mousekey_send(); + } #endif } diff --git a/tmk_core/common/action.h b/tmk_core/common/action.h index 6c84561785..8cb4722c6e 100644 --- a/tmk_core/common/action.h +++ b/tmk_core/common/action.h @@ -77,7 +77,7 @@ extern bool disable_action_cache; /* Code for handling one-handed key modifiers. */ #ifdef SWAP_HANDS_ENABLE -extern bool swap_hands; +extern bool swap_hands; extern const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS]; # if (MATRIX_COLS <= 8) typedef uint8_t swap_state_row_t; diff --git a/tmk_core/common/chibios/sleep_led.c b/tmk_core/common/chibios/sleep_led.c index 477056a454..1c65016a42 100644 --- a/tmk_core/common/chibios/sleep_led.c +++ b/tmk_core/common/chibios/sleep_led.c @@ -65,7 +65,7 @@ void sleep_led_timer_callback(void) { /* LPTMR clock options */ # define LPTMR_CLOCK_MCGIRCLK 0 /* 4MHz clock */ -# define LPTMR_CLOCK_LPO 1 /* 1kHz clock */ +# define LPTMR_CLOCK_LPO 1 /* 1kHz clock */ # define LPTMR_CLOCK_ERCLK32K 2 /* external 32kHz crystal */ # define LPTMR_CLOCK_OSCERCLK 3 /* output from OSC */ @@ -121,7 +121,7 @@ void sleep_led_init(void) { MCG->C2 |= MCG_C2_IRCS; // fast (4MHz) internal ref clock # if defined(KL27) // divide the 8MHz IRC by 2, to have the same MCGIRCLK speed as others MCG->MC |= MCG_MC_LIRC_DIV2_DIV2; -# endif /* KL27 */ +# endif /* KL27 */ MCG->C1 |= MCG_C1_IRCLKEN; // enable internal ref clock // to work in stop mode, also MCG_C1_IREFSTEN // Divide 4MHz by 2^N (N=6) => 62500 irqs/sec => diff --git a/tmk_core/common/keyboard.h b/tmk_core/common/keyboard.h index 779973f1d6..08f4e84f94 100644 --- a/tmk_core/common/keyboard.h +++ b/tmk_core/common/keyboard.h @@ -70,9 +70,9 @@ void keyboard_pre_init_user(void); void keyboard_post_init_kb(void); void keyboard_post_init_user(void); -void housekeeping_task(void); // To be executed by the main loop in each backend TMK protocol -void housekeeping_task_kb(void); // To be overridden by keyboard-level code -void housekeeping_task_user(void); // To be overridden by user/keymap-level code +void housekeeping_task(void); // To be executed by the main loop in each backend TMK protocol +void housekeeping_task_kb(void); // To be overridden by keyboard-level code +void housekeeping_task_user(void); // To be overridden by user/keymap-level code uint32_t last_input_activity_time(void); // Timestamp of the last matrix or encoder activity uint32_t last_input_activity_elapsed(void); // Number of milliseconds since the last matrix or encoder activity -- cgit v1.2.3 From 7e4f01f454cc03e6c204be9947fc23ea020d4ce5 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Mon, 7 Jun 2021 00:48:26 +0200 Subject: core: bump USB spec version in device descriptor to 2.0 (#13078) Co-authored-by: Ryan --- tmk_core/protocol/usb_descriptor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tmk_core') diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c index ba7760f283..c88aceb6ed 100644 --- a/tmk_core/protocol/usb_descriptor.c +++ b/tmk_core/protocol/usb_descriptor.c @@ -351,7 +351,7 @@ const USB_Descriptor_Device_t PROGMEM DeviceDescriptor = { .Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device }, - .USBSpecification = VERSION_BCD(1, 1, 0), + .USBSpecification = VERSION_BCD(2, 0, 0), #if VIRTSER_ENABLE .Class = USB_CSCP_IADDeviceClass, -- cgit v1.2.3 From 49fd3c0760e06b7eab3647098530f1a9bdfc5054 Mon Sep 17 00:00:00 2001 From: Stefan Kerkmann Date: Mon, 7 Jun 2021 07:16:55 +0200 Subject: [Core] ChibiOS fix O3 and LTO breakage of extra keys and joystick (#12819) --- tmk_core/protocol/chibios/usb_main.c | 34 +++++++++++++++++----------------- tmk_core/protocol/lufa/lufa.c | 34 +++++++++++++++++----------------- tmk_core/protocol/vusb/vusb.c | 3 ++- 3 files changed, 36 insertions(+), 35 deletions(-) (limited to 'tmk_core') diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c index d04302acae..407b8ea75d 100644 --- a/tmk_core/protocol/chibios/usb_main.c +++ b/tmk_core/protocol/chibios/usb_main.c @@ -903,7 +903,8 @@ static void send_extra(uint8_t report_id, uint16_t data) { return; } - report_extra_t report = {.report_id = report_id, .usage = data}; + static report_extra_t report; + report = (report_extra_t){.report_id = report_id, .usage = data}; usbStartTransmitI(&USB_DRIVER, SHARED_IN_EPNUM, (uint8_t *)&report, sizeof(report_extra_t)); osalSysUnlock(); @@ -1051,45 +1052,44 @@ void virtser_task(void) { #ifdef JOYSTICK_ENABLE void send_joystick_packet(joystick_t *joystick) { - joystick_report_t rep = { + static joystick_report_t rep; + rep = (joystick_report_t) { # if JOYSTICK_AXES_COUNT > 0 .axes = - { - joystick->axes[0], + { joystick->axes[0], # if JOYSTICK_AXES_COUNT >= 2 - joystick->axes[1], + joystick->axes[1], # endif # if JOYSTICK_AXES_COUNT >= 3 - joystick->axes[2], + joystick->axes[2], # endif # if JOYSTICK_AXES_COUNT >= 4 - joystick->axes[3], + joystick->axes[3], # endif # if JOYSTICK_AXES_COUNT >= 5 - joystick->axes[4], + joystick->axes[4], # endif # if JOYSTICK_AXES_COUNT >= 6 - joystick->axes[5], + joystick->axes[5], # endif - }, + }, # endif // JOYSTICK_AXES_COUNT>0 # if JOYSTICK_BUTTON_COUNT > 0 - .buttons = - { - joystick->buttons[0], + .buttons = { + joystick->buttons[0], # if JOYSTICK_BUTTON_COUNT > 8 - joystick->buttons[1], + joystick->buttons[1], # endif # if JOYSTICK_BUTTON_COUNT > 16 - joystick->buttons[2], + joystick->buttons[2], # endif # if JOYSTICK_BUTTON_COUNT > 24 - joystick->buttons[3], + joystick->buttons[3], # endif - } + } # endif // JOYSTICK_BUTTON_COUNT>0 }; diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c index 63619fdb3b..4ac079e168 100644 --- a/tmk_core/protocol/lufa/lufa.c +++ b/tmk_core/protocol/lufa/lufa.c @@ -314,45 +314,44 @@ static void Console_Task(void) { void send_joystick_packet(joystick_t *joystick) { uint8_t timeout = 255; - joystick_report_t r = { + static joystick_report_t; + r = (joystick_report_t) { # if JOYSTICK_AXES_COUNT > 0 .axes = - { - joystick->axes[0], + { joystick->axes[0], # if JOYSTICK_AXES_COUNT >= 2 - joystick->axes[1], + joystick->axes[1], # endif # if JOYSTICK_AXES_COUNT >= 3 - joystick->axes[2], + joystick->axes[2], # endif # if JOYSTICK_AXES_COUNT >= 4 - joystick->axes[3], + joystick->axes[3], # endif # if JOYSTICK_AXES_COUNT >= 5 - joystick->axes[4], + joystick->axes[4], # endif # if JOYSTICK_AXES_COUNT >= 6 - joystick->axes[5], + joystick->axes[5], # endif - }, + }, # endif // JOYSTICK_AXES_COUNT>0 # if JOYSTICK_BUTTON_COUNT > 0 - .buttons = - { - joystick->buttons[0], + .buttons = { + joystick->buttons[0], # if JOYSTICK_BUTTON_COUNT > 8 - joystick->buttons[1], + joystick->buttons[1], # endif # if JOYSTICK_BUTTON_COUNT > 16 - joystick->buttons[2], + joystick->buttons[2], # endif # if JOYSTICK_BUTTON_COUNT > 24 - joystick->buttons[3], + joystick->buttons[3], # endif - } + } # endif // JOYSTICK_BUTTON_COUNT>0 }; @@ -768,7 +767,8 @@ static void send_extra(uint8_t report_id, uint16_t data) { if (USB_DeviceState != DEVICE_STATE_Configured) return; - report_extra_t r = {.report_id = report_id, .usage = data}; + static report_extra_t r; + r = (report_extra_t){.report_id = report_id, .usage = data}; Endpoint_SelectEndpoint(SHARED_IN_EPNUM); /* Check if write ready for a polling interval around 10ms */ diff --git a/tmk_core/protocol/vusb/vusb.c b/tmk_core/protocol/vusb/vusb.c index 9362fbde78..876a313786 100644 --- a/tmk_core/protocol/vusb/vusb.c +++ b/tmk_core/protocol/vusb/vusb.c @@ -272,7 +272,8 @@ static void send_extra(uint8_t report_id, uint16_t data) { last_id = report_id; last_data = data; - report_extra_t report = {.report_id = report_id, .usage = data}; + static report_extra_t report; + report = (report_extra_t){.report_id = report_id, .usage = data}; if (usbInterruptIsReadyShared()) { usbSetInterruptShared((void *)&report, sizeof(report_extra_t)); } -- cgit v1.2.3 From 680cc1fab4a9e1bc7a75a5a7fe063ae4717a86ae Mon Sep 17 00:00:00 2001 From: Sergey Vlasov Date: Mon, 7 Jun 2021 08:42:08 +0300 Subject: Fix firmware size check with avr-libc 1:2.0.0+Atmel3.6.2-1.1 (Debian bullseye) (#12951) Debian bullseye (testing at the moment, but seems close to release) has avr-libc 1:2.0.0+Atmel3.6.2-1.1 with some changes taken from the Atmel-distributed toolchain. In particular, the header for ATmega32A (avr/iom32a.h) now defines the FLASHEND constant as `0x7FFFU`, and that `U` suffix breaks the firmware size check code, because the shell arithmetic expansion that is used to calculate `MAX_SIZE` does not support those C-specific suffixes. As a workaround, add `-D__ASSEMBLER__` to the C preprocessor invocation that is used to expand those macros; in this case avr/iom32a.h defines `FLASHEND` without the `U` suffix, and everything works as it did before with older avr-libc versions. The exact same code is present in two places; they are both changed, even though the code in `tmk_core/avr.mk` is actually never used for ATmega32A (and the header for ATmega32U4 does not add that `U` suffix to `FLASHEND` for some reason).--- tmk_core/avr.mk | 2 +- tmk_core/rules.mk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'tmk_core') diff --git a/tmk_core/avr.mk b/tmk_core/avr.mk index 521305f1b4..2ba193c762 100644 --- a/tmk_core/avr.mk +++ b/tmk_core/avr.mk @@ -295,7 +295,7 @@ ifneq ($(strip $(BOOTLOADER)), qmk-dfu) endif make -C lib/lufa/Bootloaders/DFU/ clean $(QMK_BIN) generate-dfu-header --quiet --keyboard $(KEYBOARD) --output lib/lufa/Bootloaders/DFU/Keyboard.h - $(eval MAX_SIZE=$(shell n=`$(CC) -E -mmcu=$(MCU) $(CFLAGS) $(OPT_DEFS) tmk_core/common/avr/bootloader_size.c 2> /dev/null | sed -ne 's/\r//;/^#/n;/^AVR_SIZE:/,$${s/^AVR_SIZE: //;p;}'` && echo $$(($$n)) || echo 0)) + $(eval MAX_SIZE=$(shell n=`$(CC) -E -mmcu=$(MCU) -D__ASSEMBLER__ $(CFLAGS) $(OPT_DEFS) tmk_core/common/avr/bootloader_size.c 2> /dev/null | sed -ne 's/\r//;/^#/n;/^AVR_SIZE:/,$${s/^AVR_SIZE: //;p;}'` && echo $$(($$n)) || echo 0)) $(eval PROGRAM_SIZE_KB=$(shell n=`expr $(MAX_SIZE) / 1024` && echo $$(($$n)) || echo 0)) $(eval BOOT_SECTION_SIZE_KB=$(shell n=`expr $(BOOTLOADER_SIZE) / 1024` && echo $$(($$n)) || echo 0)) $(eval FLASH_SIZE_KB=$(shell n=`expr $(PROGRAM_SIZE_KB) + $(BOOT_SECTION_SIZE_KB)` && echo $$(($$n)) || echo 0)) diff --git a/tmk_core/rules.mk b/tmk_core/rules.mk index fc2dc68be2..597f7aa827 100644 --- a/tmk_core/rules.mk +++ b/tmk_core/rules.mk @@ -458,7 +458,7 @@ ifeq ($(findstring avr-gcc,$(CC)),avr-gcc) SIZE_MARGIN = 1024 check-size: - $(eval MAX_SIZE=$(shell n=`$(CC) -E -mmcu=$(MCU) $(CFLAGS) $(OPT_DEFS) tmk_core/common/avr/bootloader_size.c 2> /dev/null | sed -ne 's/\r//;/^#/n;/^AVR_SIZE:/,$${s/^AVR_SIZE: //;p;}'` && echo $$(($$n)) || echo 0)) + $(eval MAX_SIZE=$(shell n=`$(CC) -E -mmcu=$(MCU) -D__ASSEMBLER__ $(CFLAGS) $(OPT_DEFS) tmk_core/common/avr/bootloader_size.c 2> /dev/null | sed -ne 's/\r//;/^#/n;/^AVR_SIZE:/,$${s/^AVR_SIZE: //;p;}'` && echo $$(($$n)) || echo 0)) $(eval CURRENT_SIZE=$(shell if [ -f $(BUILD_DIR)/$(TARGET).hex ]; then $(SIZE) --target=$(FORMAT) $(BUILD_DIR)/$(TARGET).hex | $(AWK) 'NR==2 {print $$4}'; else printf 0; fi)) $(eval FREE_SIZE=$(shell expr $(MAX_SIZE) - $(CURRENT_SIZE))) $(eval OVER_SIZE=$(shell expr $(CURRENT_SIZE) - $(MAX_SIZE))) -- cgit v1.2.3 From b72f10c6357eee628ab1f3762f66ba8a0a279a4e Mon Sep 17 00:00:00 2001 From: Takeshi ISHII Date: Mon, 7 Jun 2021 18:23:21 +0900 Subject: Add readPort() and some API to 'tmk_core/common/*/gpio.h' (#12754) * add readPort() and some API to 'tmk_core/common/*/gpio.h' The following macros have been added to gpio.h. * readPort(port) * setPortBitInput(port, bit) * setPortBitInputHigh(port, bit) * setPortBitOutput(port, bit) * writePortBitLow(port, bit) * writePortBitHigh(port, bit) * add data type 'port_data_t' into gpio.h * rename qmk_pin to pin--- tmk_core/common/avr/gpio.h | 15 +++++++++++++++ tmk_core/common/chibios/gpio.h | 16 ++++++++++++++++ 2 files changed, 31 insertions(+) (limited to 'tmk_core') diff --git a/tmk_core/common/avr/gpio.h b/tmk_core/common/avr/gpio.h index 231556c29c..e9be68491d 100644 --- a/tmk_core/common/avr/gpio.h +++ b/tmk_core/common/avr/gpio.h @@ -20,6 +20,8 @@ typedef uint8_t pin_t; +/* Operation of GPIO by pin. */ + #define setPinInput(pin) (DDRx_ADDRESS(pin) &= ~_BV((pin)&0xF), PORTx_ADDRESS(pin) &= ~_BV((pin)&0xF)) #define setPinInputHigh(pin) (DDRx_ADDRESS(pin) &= ~_BV((pin)&0xF), PORTx_ADDRESS(pin) |= _BV((pin)&0xF)) #define setPinInputLow(pin) _Static_assert(0, "AVR processors cannot implement an input as pull low") @@ -32,3 +34,16 @@ typedef uint8_t pin_t; #define readPin(pin) ((bool)(PINx_ADDRESS(pin) & _BV((pin)&0xF))) #define togglePin(pin) (PORTx_ADDRESS(pin) ^= _BV((pin)&0xF)) + +/* Operation of GPIO by port. */ + +typedef uint8_t port_data_t; + +#define readPort(port) PINx_ADDRESS(port) + +#define setPortBitInput(port, bit) (DDRx_ADDRESS(port) &= ~_BV((bit)&0xF), PORTx_ADDRESS(port) &= ~_BV((bit)&0xF)) +#define setPortBitInputHigh(port, bit) (DDRx_ADDRESS(port) &= ~_BV((bit)&0xF), PORTx_ADDRESS(port) |= _BV((bit)&0xF)) +#define setPortBitOutput(port, bit) (DDRx_ADDRESS(port) |= _BV((bit)&0xF)) + +#define writePortBitLow(port, bit) (PORTx_ADDRESS(port) &= ~_BV((bit)&0xF)) +#define writePortBitHigh(port, bit) (PORTx_ADDRESS(port) |= _BV((bit)&0xF)) diff --git a/tmk_core/common/chibios/gpio.h b/tmk_core/common/chibios/gpio.h index 5d0e142abc..4d057f1cab 100644 --- a/tmk_core/common/chibios/gpio.h +++ b/tmk_core/common/chibios/gpio.h @@ -20,6 +20,8 @@ typedef ioline_t pin_t; +/* Operation of GPIO by pin. */ + #define setPinInput(pin) palSetLineMode(pin, PAL_MODE_INPUT) #define setPinInputHigh(pin) palSetLineMode(pin, PAL_MODE_INPUT_PULLUP) #define setPinInputLow(pin) palSetLineMode(pin, PAL_MODE_INPUT_PULLDOWN) @@ -32,3 +34,17 @@ typedef ioline_t pin_t; #define readPin(pin) palReadLine(pin) #define togglePin(pin) palToggleLine(pin) + +/* Operation of GPIO by port. */ + +typedef uint16_t port_data_t; + +#define readPort(pin) palReadPort(PAL_PORT(pin)) + +#define setPortBitInput(pin, bit) palSetPadMode(PAL_PORT(pin), bit, PAL_MODE_INPUT) +#define setPortBitInputHigh(pin, bit) palSetPadMode(PAL_PORT(pin), bit, PAL_MODE_INPUT_PULLUP) +#define setPortBitInputLow(pin, bit) palSetPadMode(PAL_PORT(pin), bit, PAL_MODE_INPUT_PULLDOWN) +#define setPortBitOutput(pin, bit) palSetPadMode(PAL_PORT(pin), bit, PAL_MODE_OUTPUT_PUSHPULL) + +#define writePortBitLow(pin, bit) palClearLine(PAL_LINE(PAL_PORT(pin), bit)) +#define writePortBitHigh(pin, bit) palSetLine(PAL_LINE(PAL_PORT(pin), bit)) -- cgit v1.2.3 From b829a1d2648abd0751e9d3505554547faf643425 Mon Sep 17 00:00:00 2001 From: Simon Arlott Date: Wed, 9 Jun 2021 08:23:21 +0100 Subject: Avoid 8-bit timer overflows in debounce algorithms (#12240) * Add fast_timer_t that is 16-bit or 32-bit based on architecture A 16-bit timer will overflow sooner but be faster to compare on AVR. * Avoid 8-bit timer overflows in debounce algorithms Count down remaining elapsed time instead of trying to do 8-bit timer comparisons. Add a "none" implementation that is automatically used if DEBOUNCE is 0 otherwise it will break the _pk/_pr count down. * Avoid unnecessary polling of the entire matrix in sym_eager_pk The matrix only needs to be updated when a debounce timer expires. * Avoid unnecessary polling of the entire matrix in sym_eager_pr The matrix only needs to be updated when a debounce timer expires. The use of the "needed_update" variable is trying to do what "matrix_need_update" was added to fix but didn't work because it only applied when all keys finished debouncing. * Fix sym_defer_g timing inconsistency compared to other debounce algorithms DEBOUNCE=5 should process the key after 5ms, not 6ms * Add debounce tests--- build_test.mk | 1 + quantum/debounce.h | 2 + quantum/debounce/none.c | 31 +++ quantum/debounce/sym_defer_g.c | 26 +-- quantum/debounce/sym_defer_pk.c | 67 ++++-- quantum/debounce/sym_eager_pk.c | 72 +++--- quantum/debounce/sym_eager_pr.c | 76 ++++--- quantum/debounce/tests/debounce_test_common.cpp | 229 +++++++++++++++++++ quantum/debounce/tests/debounce_test_common.h | 83 +++++++ quantum/debounce/tests/rules.mk | 39 ++++ quantum/debounce/tests/sym_defer_g_tests.cpp | 223 +++++++++++++++++++ quantum/debounce/tests/sym_defer_pk_tests.cpp | 225 +++++++++++++++++++ quantum/debounce/tests/sym_eager_pk_tests.cpp | 237 ++++++++++++++++++++ quantum/debounce/tests/sym_eager_pr_tests.cpp | 280 ++++++++++++++++++++++++ quantum/debounce/tests/testlist.mk | 5 + testlist.mk | 1 + tmk_core/common/arm_atsam/_timer.h | 19 ++ tmk_core/common/avr/_timer.h | 19 ++ tmk_core/common/chibios/_timer.h | 19 ++ tmk_core/common/timer.h | 24 +- 20 files changed, 1587 insertions(+), 91 deletions(-) create mode 100644 quantum/debounce/none.c create mode 100644 quantum/debounce/tests/debounce_test_common.cpp create mode 100644 quantum/debounce/tests/debounce_test_common.h create mode 100644 quantum/debounce/tests/rules.mk create mode 100644 quantum/debounce/tests/sym_defer_g_tests.cpp create mode 100644 quantum/debounce/tests/sym_defer_pk_tests.cpp create mode 100644 quantum/debounce/tests/sym_eager_pk_tests.cpp create mode 100644 quantum/debounce/tests/sym_eager_pr_tests.cpp create mode 100644 quantum/debounce/tests/testlist.mk create mode 100644 tmk_core/common/arm_atsam/_timer.h create mode 100644 tmk_core/common/avr/_timer.h create mode 100644 tmk_core/common/chibios/_timer.h (limited to 'tmk_core') diff --git a/build_test.mk b/build_test.mk index 77c4265f93..5171c58c36 100644 --- a/build_test.mk +++ b/build_test.mk @@ -49,6 +49,7 @@ endif include common_features.mk include $(TMK_PATH)/common.mk +include $(QUANTUM_PATH)/debounce/tests/rules.mk include $(QUANTUM_PATH)/sequencer/tests/rules.mk include $(QUANTUM_PATH)/serial_link/tests/rules.mk ifneq ($(filter $(FULL_TESTS),$(TEST)),) diff --git a/quantum/debounce.h b/quantum/debounce.h index 9ca05c6824..5043868289 100644 --- a/quantum/debounce.h +++ b/quantum/debounce.h @@ -9,3 +9,5 @@ void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool bool debounce_active(void); void debounce_init(uint8_t num_rows); + +void debounce_free(void); diff --git a/quantum/debounce/none.c b/quantum/debounce/none.c new file mode 100644 index 0000000000..b03892bc5b --- /dev/null +++ b/quantum/debounce/none.c @@ -0,0 +1,31 @@ +/* Copyright 2021 Simon Arlott + * + * 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 . + */ + +#include "matrix.h" +#include "quantum.h" +#include + +void debounce_init(uint8_t num_rows) {} + +void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { + for (int i = 0; i < num_rows; i++) { + cooked[i] = raw[i]; + } +} + +bool debounce_active(void) { return false; } + +void debounce_free(void) {} diff --git a/quantum/debounce/sym_defer_g.c b/quantum/debounce/sym_defer_g.c index 3ed9055d2a..fbefd55ede 100644 --- a/quantum/debounce/sym_defer_g.c +++ b/quantum/debounce/sym_defer_g.c @@ -1,5 +1,6 @@ /* Copyright 2017 Alex Ong +Copyright 2021 Simon Arlott 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 @@ -23,30 +24,29 @@ When no state changes have occured for DEBOUNCE milliseconds, we push the state. # define DEBOUNCE 5 #endif -void debounce_init(uint8_t num_rows) {} +#if DEBOUNCE > 0 static bool debouncing = false; +static fast_timer_t debouncing_time; -#if DEBOUNCE > 0 -static uint16_t debouncing_time; -void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { +void debounce_init(uint8_t num_rows) {} + +void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { if (changed) { debouncing = true; - debouncing_time = timer_read(); + debouncing_time = timer_read_fast(); } - if (debouncing && timer_elapsed(debouncing_time) > DEBOUNCE) { + if (debouncing && timer_elapsed_fast(debouncing_time) >= DEBOUNCE) { for (int i = 0; i < num_rows; i++) { cooked[i] = raw[i]; } debouncing = false; } } -#else // no debouncing. -void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { - for (int i = 0; i < num_rows; i++) { - cooked[i] = raw[i]; - } -} -#endif bool debounce_active(void) { return debouncing; } + +void debounce_free(void) {} +#else // no debouncing. +# include "none.c" +#endif diff --git a/quantum/debounce/sym_defer_pk.c b/quantum/debounce/sym_defer_pk.c index 60513f98e1..626a9be841 100644 --- a/quantum/debounce/sym_defer_pk.c +++ b/quantum/debounce/sym_defer_pk.c @@ -1,6 +1,7 @@ /* Copyright 2017 Alex Ong Copyright 2020 Andrei Purdea +Copyright 2021 Simon Arlott 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 @@ -33,28 +34,25 @@ When no state changes have occured for DEBOUNCE milliseconds, we push the state. # define DEBOUNCE 5 #endif +// Maximum debounce: 255ms +#if DEBOUNCE > UINT8_MAX +# undef DEBOUNCE +# define DEBOUNCE UINT8_MAX +#endif + #define ROW_SHIFTER ((matrix_row_t)1) -#define debounce_counter_t uint8_t +typedef uint8_t debounce_counter_t; +#if DEBOUNCE > 0 static debounce_counter_t *debounce_counters; +static fast_timer_t last_time; static bool counters_need_update; -#define DEBOUNCE_ELAPSED 251 -#define MAX_DEBOUNCE (DEBOUNCE_ELAPSED - 1) - -static uint8_t wrapping_timer_read(void) { - static uint16_t time = 0; - static uint8_t last_result = 0; - uint16_t new_time = timer_read(); - uint16_t diff = new_time - time; - time = new_time; - last_result = (last_result + diff) % (MAX_DEBOUNCE + 1); - return last_result; -} +#define DEBOUNCE_ELAPSED 0 -void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time); -void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time); +static void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t elapsed_time); +static void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows); // we use num_rows rather than MATRIX_ROWS to support split keyboards void debounce_init(uint8_t num_rows) { @@ -67,27 +65,49 @@ void debounce_init(uint8_t num_rows) { } } +void debounce_free(void) { + free(debounce_counters); + debounce_counters = NULL; +} + void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { - uint8_t current_time = wrapping_timer_read(); + bool updated_last = false; + if (counters_need_update) { - update_debounce_counters_and_transfer_if_expired(raw, cooked, num_rows, current_time); + fast_timer_t now = timer_read_fast(); + fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time); + + last_time = now; + updated_last = true; + if (elapsed_time > UINT8_MAX) { + elapsed_time = UINT8_MAX; + } + + if (elapsed_time > 0) { + update_debounce_counters_and_transfer_if_expired(raw, cooked, num_rows, elapsed_time); + } } if (changed) { - start_debounce_counters(raw, cooked, num_rows, current_time); + if (!updated_last) { + last_time = timer_read_fast(); + } + + start_debounce_counters(raw, cooked, num_rows); } } -void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time) { +static void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t elapsed_time) { counters_need_update = false; debounce_counter_t *debounce_pointer = debounce_counters; for (uint8_t row = 0; row < num_rows; row++) { for (uint8_t col = 0; col < MATRIX_COLS; col++) { if (*debounce_pointer != DEBOUNCE_ELAPSED) { - if (TIMER_DIFF(current_time, *debounce_pointer, MAX_DEBOUNCE) >= DEBOUNCE) { + if (*debounce_pointer <= elapsed_time) { *debounce_pointer = DEBOUNCE_ELAPSED; cooked[row] = (cooked[row] & ~(ROW_SHIFTER << col)) | (raw[row] & (ROW_SHIFTER << col)); } else { + *debounce_pointer -= elapsed_time; counters_need_update = true; } } @@ -96,14 +116,14 @@ void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix } } -void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time) { +static void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows) { debounce_counter_t *debounce_pointer = debounce_counters; for (uint8_t row = 0; row < num_rows; row++) { matrix_row_t delta = raw[row] ^ cooked[row]; for (uint8_t col = 0; col < MATRIX_COLS; col++) { if (delta & (ROW_SHIFTER << col)) { if (*debounce_pointer == DEBOUNCE_ELAPSED) { - *debounce_pointer = current_time; + *debounce_pointer = DEBOUNCE; counters_need_update = true; } } else { @@ -115,3 +135,6 @@ void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], uint8_t } bool debounce_active(void) { return true; } +#else +# include "none.c" +#endif diff --git a/quantum/debounce/sym_eager_pk.c b/quantum/debounce/sym_eager_pk.c index e66cf92d79..15a3242e68 100644 --- a/quantum/debounce/sym_eager_pk.c +++ b/quantum/debounce/sym_eager_pk.c @@ -1,5 +1,6 @@ /* Copyright 2017 Alex Ong +Copyright 2021 Simon Arlott 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 @@ -33,29 +34,26 @@ No further inputs are accepted until DEBOUNCE milliseconds have occurred. # define DEBOUNCE 5 #endif +// Maximum debounce: 255ms +#if DEBOUNCE > UINT8_MAX +# undef DEBOUNCE +# define DEBOUNCE UINT8_MAX +#endif + #define ROW_SHIFTER ((matrix_row_t)1) -#define debounce_counter_t uint8_t +typedef uint8_t debounce_counter_t; +#if DEBOUNCE > 0 static debounce_counter_t *debounce_counters; +static fast_timer_t last_time; static bool counters_need_update; static bool matrix_need_update; -#define DEBOUNCE_ELAPSED 251 -#define MAX_DEBOUNCE (DEBOUNCE_ELAPSED - 1) - -static uint8_t wrapping_timer_read(void) { - static uint16_t time = 0; - static uint8_t last_result = 0; - uint16_t new_time = timer_read(); - uint16_t diff = new_time - time; - time = new_time; - last_result = (last_result + diff) % (MAX_DEBOUNCE + 1); - return last_result; -} +#define DEBOUNCE_ELAPSED 0 -void update_debounce_counters(uint8_t num_rows, uint8_t current_time); -void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time); +static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time); +static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows); // we use num_rows rather than MATRIX_ROWS to support split keyboards void debounce_init(uint8_t num_rows) { @@ -68,27 +66,51 @@ void debounce_init(uint8_t num_rows) { } } +void debounce_free(void) { + free(debounce_counters); + debounce_counters = NULL; +} + void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { - uint8_t current_time = wrapping_timer_read(); + bool updated_last = false; + if (counters_need_update) { - update_debounce_counters(num_rows, current_time); + fast_timer_t now = timer_read_fast(); + fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time); + + last_time = now; + updated_last = true; + if (elapsed_time > UINT8_MAX) { + elapsed_time = UINT8_MAX; + } + + if (elapsed_time > 0) { + update_debounce_counters(num_rows, elapsed_time); + } } if (changed || matrix_need_update) { - transfer_matrix_values(raw, cooked, num_rows, current_time); + if (!updated_last) { + last_time = timer_read_fast(); + } + + transfer_matrix_values(raw, cooked, num_rows); } } // If the current time is > debounce counter, set the counter to enable input. -void update_debounce_counters(uint8_t num_rows, uint8_t current_time) { +static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time) { counters_need_update = false; + matrix_need_update = false; debounce_counter_t *debounce_pointer = debounce_counters; for (uint8_t row = 0; row < num_rows; row++) { for (uint8_t col = 0; col < MATRIX_COLS; col++) { if (*debounce_pointer != DEBOUNCE_ELAPSED) { - if (TIMER_DIFF(current_time, *debounce_pointer, MAX_DEBOUNCE) >= DEBOUNCE) { + if (*debounce_pointer <= elapsed_time) { *debounce_pointer = DEBOUNCE_ELAPSED; + matrix_need_update = true; } else { + *debounce_pointer -= elapsed_time; counters_need_update = true; } } @@ -98,8 +120,7 @@ void update_debounce_counters(uint8_t num_rows, uint8_t current_time) { } // upload from raw_matrix to final matrix; -void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time) { - matrix_need_update = false; +static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows) { debounce_counter_t *debounce_pointer = debounce_counters; for (uint8_t row = 0; row < num_rows; row++) { matrix_row_t delta = raw[row] ^ cooked[row]; @@ -108,11 +129,9 @@ void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t n matrix_row_t col_mask = (ROW_SHIFTER << col); if (delta & col_mask) { if (*debounce_pointer == DEBOUNCE_ELAPSED) { - *debounce_pointer = current_time; + *debounce_pointer = DEBOUNCE; counters_need_update = true; existing_row ^= col_mask; // flip the bit. - } else { - matrix_need_update = true; } } debounce_pointer++; @@ -122,3 +141,6 @@ void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t n } bool debounce_active(void) { return true; } +#else +# include "none.c" +#endif diff --git a/quantum/debounce/sym_eager_pr.c b/quantum/debounce/sym_eager_pr.c index 20ccb46f1d..2ad592c5a6 100644 --- a/quantum/debounce/sym_eager_pr.c +++ b/quantum/debounce/sym_eager_pr.c @@ -1,5 +1,6 @@ /* Copyright 2019 Alex Ong +Copyright 2021 Simon Arlott 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 @@ -33,27 +34,25 @@ No further inputs are accepted until DEBOUNCE milliseconds have occurred. # define DEBOUNCE 5 #endif -#define debounce_counter_t uint8_t +// Maximum debounce: 255ms +#if DEBOUNCE > UINT8_MAX +# undef DEBOUNCE +# define DEBOUNCE UINT8_MAX +#endif + +typedef uint8_t debounce_counter_t; + +#if DEBOUNCE > 0 static bool matrix_need_update; static debounce_counter_t *debounce_counters; +static fast_timer_t last_time; static bool counters_need_update; -#define DEBOUNCE_ELAPSED 251 -#define MAX_DEBOUNCE (DEBOUNCE_ELAPSED - 1) - -static uint8_t wrapping_timer_read(void) { - static uint16_t time = 0; - static uint8_t last_result = 0; - uint16_t new_time = timer_read(); - uint16_t diff = new_time - time; - time = new_time; - last_result = (last_result + diff) % (MAX_DEBOUNCE + 1); - return last_result; -} +#define DEBOUNCE_ELAPSED 0 -void update_debounce_counters(uint8_t num_rows, uint8_t current_time); -void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time); +static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time); +static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows); // we use num_rows rather than MATRIX_ROWS to support split keyboards void debounce_init(uint8_t num_rows) { @@ -63,27 +62,50 @@ void debounce_init(uint8_t num_rows) { } } +void debounce_free(void) { + free(debounce_counters); + debounce_counters = NULL; +} + void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { - uint8_t current_time = wrapping_timer_read(); - bool needed_update = counters_need_update; + bool updated_last = false; + if (counters_need_update) { - update_debounce_counters(num_rows, current_time); + fast_timer_t now = timer_read_fast(); + fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time); + + last_time = now; + updated_last = true; + if (elapsed_time > UINT8_MAX) { + elapsed_time = UINT8_MAX; + } + + if (elapsed_time > 0) { + update_debounce_counters(num_rows, elapsed_time); + } } - if (changed || (needed_update && !counters_need_update) || matrix_need_update) { - transfer_matrix_values(raw, cooked, num_rows, current_time); + if (changed || matrix_need_update) { + if (!updated_last) { + last_time = timer_read_fast(); + } + + transfer_matrix_values(raw, cooked, num_rows); } } // If the current time is > debounce counter, set the counter to enable input. -void update_debounce_counters(uint8_t num_rows, uint8_t current_time) { +static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time) { counters_need_update = false; + matrix_need_update = false; debounce_counter_t *debounce_pointer = debounce_counters; for (uint8_t row = 0; row < num_rows; row++) { if (*debounce_pointer != DEBOUNCE_ELAPSED) { - if (TIMER_DIFF(current_time, *debounce_pointer, MAX_DEBOUNCE) >= DEBOUNCE) { + if (*debounce_pointer <= elapsed_time) { *debounce_pointer = DEBOUNCE_ELAPSED; + matrix_need_update = true; } else { + *debounce_pointer -= elapsed_time; counters_need_update = true; } } @@ -92,8 +114,7 @@ void update_debounce_counters(uint8_t num_rows, uint8_t current_time) { } // upload from raw_matrix to final matrix; -void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time) { - matrix_need_update = false; +static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows) { debounce_counter_t *debounce_pointer = debounce_counters; for (uint8_t row = 0; row < num_rows; row++) { matrix_row_t existing_row = cooked[row]; @@ -102,11 +123,9 @@ void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t n // determine new value basd on debounce pointer + raw value if (existing_row != raw_row) { if (*debounce_pointer == DEBOUNCE_ELAPSED) { - *debounce_pointer = current_time; + *debounce_pointer = DEBOUNCE; cooked[row] = raw_row; counters_need_update = true; - } else { - matrix_need_update = true; } } debounce_pointer++; @@ -114,3 +133,6 @@ void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t n } bool debounce_active(void) { return true; } +#else +# include "none.c" +#endif diff --git a/quantum/debounce/tests/debounce_test_common.cpp b/quantum/debounce/tests/debounce_test_common.cpp new file mode 100644 index 0000000000..1c5e7c9f4e --- /dev/null +++ b/quantum/debounce/tests/debounce_test_common.cpp @@ -0,0 +1,229 @@ +/* Copyright 2021 Simon Arlott + * + * 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 . + */ + +#include "gtest/gtest.h" + +#include "debounce_test_common.h" + +#include +#include +#include + +extern "C" { +#include "quantum.h" +#include "timer.h" +#include "debounce.h" + +void set_time(uint32_t t); +void advance_time(uint32_t ms); +} + +void DebounceTest::addEvents(std::initializer_list events) { + events_.insert(events_.end(), events.begin(), events.end()); +} + +void DebounceTest::runEvents() { + /* Run the test multiple times, from 1kHz to 10kHz scan rate */ + for (extra_iterations_ = 0; extra_iterations_ < 10; extra_iterations_++) { + if (time_jumps_) { + /* Don't advance time smoothly, jump to the next event (some tests require this) */ + auto_advance_time_ = false; + runEventsInternal(); + } else { + /* Run the test with both smooth and irregular time; it must produce the same result */ + auto_advance_time_ = true; + runEventsInternal(); + auto_advance_time_ = false; + runEventsInternal(); + } + } +} + +void DebounceTest::runEventsInternal() { + fast_timer_t previous = 0; + bool first = true; + + /* Initialise keyboard with start time (offset to avoid testing at 0) and all keys UP */ + debounce_init(MATRIX_ROWS); + set_time(time_offset_); + std::fill(std::begin(input_matrix_), std::end(input_matrix_), 0); + std::fill(std::begin(output_matrix_), std::end(output_matrix_), 0); + + for (auto &event : events_) { + if (!auto_advance_time_) { + /* Jump to the next event */ + set_time(time_offset_ + event.time_); + } else if (!first && event.time_ == previous + 1) { + /* This event immediately follows the previous one, don't make extra debounce() calls */ + advance_time(1); + } else { + /* Fast forward to the time for this event, calling debounce() with no changes */ + ASSERT_LT((time_offset_ + event.time_) - timer_read_fast(), 60000) << "Test tries to advance more than 1 minute of time"; + + while (timer_read_fast() != time_offset_ + event.time_) { + runDebounce(false); + checkCookedMatrix(false, "debounce() modified cooked matrix"); + advance_time(1); + } + } + + first = false; + previous = event.time_; + + /* Prepare input matrix */ + for (auto &input : event.inputs_) { + matrixUpdate(input_matrix_, "input", input); + } + + /* Call debounce */ + runDebounce(!event.inputs_.empty()); + + /* Prepare output matrix */ + for (auto &output : event.outputs_) { + matrixUpdate(output_matrix_, "output", output); + } + + /* Check output matrix has expected change events */ + for (auto &output : event.outputs_) { + EXPECT_EQ(!!(cooked_matrix_[output.row_] & (1U << output.col_)), directionValue(output.direction_)) + << "Missing event at " << strTime() + << " expected key " << output.row_ << "," << output.col_ << " " << directionLabel(output.direction_) + << "\ninput_matrix: changed=" << !event.inputs_.empty() << "\n" << strMatrix(input_matrix_) + << "\nexpected_matrix:\n" << strMatrix(output_matrix_) + << "\nactual_matrix:\n" << strMatrix(cooked_matrix_); + } + + /* Check output matrix has no other changes */ + checkCookedMatrix(!event.inputs_.empty(), "debounce() cooked matrix does not match expected output matrix"); + + /* Perform some extra iterations of the matrix scan with no changes */ + for (int i = 0; i < extra_iterations_; i++) { + runDebounce(false); + checkCookedMatrix(false, "debounce() modified cooked matrix"); + } + } + + /* Check that no further changes happen for 1 minute */ + for (int i = 0; i < 60000; i++) { + runDebounce(false); + checkCookedMatrix(false, "debounce() modified cooked matrix"); + advance_time(1); + } + + debounce_free(); +} + +void DebounceTest::runDebounce(bool changed) { + std::copy(std::begin(input_matrix_), std::end(input_matrix_), std::begin(raw_matrix_)); + std::copy(std::begin(output_matrix_), std::end(output_matrix_), std::begin(cooked_matrix_)); + + debounce(raw_matrix_, cooked_matrix_, MATRIX_ROWS, changed); + + if (!std::equal(std::begin(input_matrix_), std::end(input_matrix_), std::begin(raw_matrix_))) { + FAIL() << "Fatal error: debounce() modified raw matrix at " << strTime() + << "\ninput_matrix: changed=" << changed << "\n" << strMatrix(input_matrix_) + << "\nraw_matrix:\n" << strMatrix(raw_matrix_); + } +} + +void DebounceTest::checkCookedMatrix(bool changed, const std::string &error_message) { + if (!std::equal(std::begin(output_matrix_), std::end(output_matrix_), std::begin(cooked_matrix_))) { + FAIL() << "Unexpected event: " << error_message << " at " << strTime() + << "\ninput_matrix: changed=" << changed << "\n" << strMatrix(input_matrix_) + << "\nexpected_matrix:\n" << strMatrix(output_matrix_) + << "\nactual_matrix:\n" << strMatrix(cooked_matrix_); + } +} + +std::string DebounceTest::strTime() { + std::stringstream text; + + text << "time " << (timer_read_fast() - time_offset_) + << " (extra_iterations=" << extra_iterations_ + << ", auto_advance_time=" << auto_advance_time_ << ")"; + + return text.str(); +} + +std::string DebounceTest::strMatrix(matrix_row_t matrix[]) { + std::stringstream text; + + text << "\t" << std::setw(3) << ""; + for (int col = 0; col < MATRIX_COLS; col++) { + text << " " << std::setw(2) << col; + } + text << "\n"; + + for (int row = 0; row < MATRIX_ROWS; row++) { + text << "\t" << std::setw(2) << row << ":"; + for (int col = 0; col < MATRIX_COLS; col++) { + text << ((matrix[row] & (1U << col)) ? " XX" : " __"); + } + + text << "\n"; + } + + return text.str(); +} + +bool DebounceTest::directionValue(Direction direction) { + switch (direction) { + case DOWN: + return true; + + case UP: + return false; + } +} + +std::string DebounceTest::directionLabel(Direction direction) { + switch (direction) { + case DOWN: + return "DOWN"; + + case UP: + return "UP"; + } +} + +/* Modify a matrix and verify that events always specify a change */ +void DebounceTest::matrixUpdate(matrix_row_t matrix[], const std::string &name, const MatrixTestEvent &event) { + ASSERT_NE(!!(matrix[event.row_] & (1U << event.col_)), directionValue(event.direction_)) + << "Test " << name << " at " << strTime() + << " sets key " << event.row_ << "," << event.col_ << " " << directionLabel(event.direction_) + << " but it is already " << directionLabel(event.direction_) + << "\n" << name << "_matrix:\n" << strMatrix(matrix); + + switch (event.direction_) { + case DOWN: + matrix[event.row_] |= (1U << event.col_); + break; + + case UP: + matrix[event.row_] &= ~(1U << event.col_); + break; + } +} + +DebounceTestEvent::DebounceTestEvent(fast_timer_t time, + std::initializer_list inputs, + std::initializer_list outputs) + : time_(time), inputs_(inputs), outputs_(outputs) { +} + +MatrixTestEvent::MatrixTestEvent(int row, int col, Direction direction) + : row_(row), col_(col), direction_(direction) { +} diff --git a/quantum/debounce/tests/debounce_test_common.h b/quantum/debounce/tests/debounce_test_common.h new file mode 100644 index 0000000000..d87e310594 --- /dev/null +++ b/quantum/debounce/tests/debounce_test_common.h @@ -0,0 +1,83 @@ +/* Copyright 2021 Simon Arlott + * + * 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 . + */ + +#include "gtest/gtest.h" + +#include +#include +#include + +extern "C" { +#include "quantum.h" +#include "timer.h" +} + +enum Direction { + DOWN, + UP, +}; + +class MatrixTestEvent { +public: + MatrixTestEvent(int row, int col, Direction direction); + + const int row_; + const int col_; + const Direction direction_; +}; + +class DebounceTestEvent { +public: + // 0, {{0, 1, DOWN}}, {{0, 1, DOWN}}) + DebounceTestEvent(fast_timer_t time, + std::initializer_list inputs, + std::initializer_list outputs); + + const fast_timer_t time_; + const std::list inputs_; + const std::list outputs_; +}; + +class DebounceTest : public ::testing::Test { +protected: + void addEvents(std::initializer_list events); + void runEvents(); + + fast_timer_t time_offset_ = 7777; + bool time_jumps_ = false; + +private: + static bool directionValue(Direction direction); + static std::string directionLabel(Direction direction); + + void runEventsInternal(); + void runDebounce(bool changed); + void checkCookedMatrix(bool changed, const std::string &error_message); + void matrixUpdate(matrix_row_t matrix[], const std::string &name, const MatrixTestEvent &event); + + std::string strTime(); + std::string strMatrix(matrix_row_t matrix[]); + + std::list events_; + + matrix_row_t input_matrix_[MATRIX_ROWS]; + matrix_row_t raw_matrix_[MATRIX_ROWS]; + matrix_row_t cooked_matrix_[MATRIX_ROWS]; + matrix_row_t output_matrix_[MATRIX_ROWS]; + + int extra_iterations_; + bool auto_advance_time_; +}; diff --git a/quantum/debounce/tests/rules.mk b/quantum/debounce/tests/rules.mk new file mode 100644 index 0000000000..29fda7889f --- /dev/null +++ b/quantum/debounce/tests/rules.mk @@ -0,0 +1,39 @@ +# Copyright 2021 Simon Arlott +# +# 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 . + +DEBOUNCE_COMMON_DEFS := -DMATRIX_ROWS=4 -DMATRIX_COLS=10 -DDEBOUNCE=5 + +DEBOUNCE_COMMON_SRC := $(QUANTUM_PATH)/debounce/tests/debounce_test_common.cpp \ + $(TMK_PATH)/common/test/timer.c + +debounce_sym_defer_g_DEFS := $(DEBOUNCE_COMMON_DEFS) +debounce_sym_defer_g_SRC := $(DEBOUNCE_COMMON_SRC) \ + $(QUANTUM_PATH)/debounce/sym_defer_g.c \ + $(QUANTUM_PATH)/debounce/tests/sym_defer_g_tests.cpp + +debounce_sym_defer_pk_DEFS := $(DEBOUNCE_COMMON_DEFS) +debounce_sym_defer_pk_SRC := $(DEBOUNCE_COMMON_SRC) \ + $(QUANTUM_PATH)/debounce/sym_defer_pk.c \ + $(QUANTUM_PATH)/debounce/tests/sym_defer_pk_tests.cpp + +debounce_sym_eager_pk_DEFS := $(DEBOUNCE_COMMON_DEFS) +debounce_sym_eager_pk_SRC := $(DEBOUNCE_COMMON_SRC) \ + $(QUANTUM_PATH)/debounce/sym_eager_pk.c \ + $(QUANTUM_PATH)/debounce/tests/sym_eager_pk_tests.cpp + +debounce_sym_eager_pr_DEFS := $(DEBOUNCE_COMMON_DEFS) +debounce_sym_eager_pr_SRC := $(DEBOUNCE_COMMON_SRC) \ + $(QUANTUM_PATH)/debounce/sym_eager_pr.c \ + $(QUANTUM_PATH)/debounce/tests/sym_eager_pr_tests.cpp diff --git a/quantum/debounce/tests/sym_defer_g_tests.cpp b/quantum/debounce/tests/sym_defer_g_tests.cpp new file mode 100644 index 0000000000..a56aecd8f3 --- /dev/null +++ b/quantum/debounce/tests/sym_defer_g_tests.cpp @@ -0,0 +1,223 @@ +/* Copyright 2021 Simon Arlott + * + * 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 . + */ + +#include "gtest/gtest.h" + +#include "debounce_test_common.h" + +TEST_F(DebounceTest, OneKeyShort1) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {}}, + + {5, {}, {{0, 1, DOWN}}}, + /* 0ms delay (fast scan rate) */ + {5, {{0, 1, UP}}, {}}, + + {10, {}, {{0, 1, UP}}}, + }); + runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort2) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {}}, + + {5, {}, {{0, 1, DOWN}}}, + /* 1ms delay */ + {6, {{0, 1, UP}}, {}}, + + {11, {}, {{0, 1, UP}}}, + }); + runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort3) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {}}, + + {5, {}, {{0, 1, DOWN}}}, + /* 2ms delay */ + {7, {{0, 1, UP}}, {}}, + + {12, {}, {{0, 1, UP}}}, + }); + runEvents(); +} + +TEST_F(DebounceTest, OneKeyTooQuick1) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {}}, + /* Release key exactly on the debounce time */ + {5, {{0, 1, UP}}, {}}, + }); + runEvents(); +} + +TEST_F(DebounceTest, OneKeyTooQuick2) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {}}, + + {5, {}, {{0, 1, DOWN}}}, + {6, {{0, 1, UP}}, {}}, + + /* Press key exactly on the debounce time */ + {11, {{0, 1, DOWN}}, {}}, + }); + runEvents(); +} + +TEST_F(DebounceTest, OneKeyBouncing1) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {}}, + {1, {{0, 1, UP}}, {}}, + {2, {{0, 1, DOWN}}, {}}, + {3, {{0, 1, UP}}, {}}, + {4, {{0, 1, DOWN}}, {}}, + {5, {{0, 1, UP}}, {}}, + {6, {{0, 1, DOWN}}, {}}, + {11, {}, {{0, 1, DOWN}}}, /* 5ms after DOWN at time 7 */ + }); + runEvents(); +} + +TEST_F(DebounceTest, OneKeyBouncing2) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {}}, + {5, {}, {{0, 1, DOWN}}}, + {6, {{0, 1, UP}}, {}}, + {7, {{0, 1, DOWN}}, {}}, + {8, {{0, 1, UP}}, {}}, + {9, {{0, 1, DOWN}}, {}}, + {10, {{0, 1, UP}}, {}}, + {15, {}, {{0, 1, UP}}}, /* 5ms after UP at time 10 */ + }); + runEvents(); +} + +TEST_F(DebounceTest, OneKeyLong) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {}}, + + {5, {}, {{0, 1, DOWN}}}, + + {25, {{0, 1, UP}}, {}}, + + {30, {}, {{0, 1, UP}}}, + + {50, {{0, 1, DOWN}}, {}}, + + {55, {}, {{0, 1, DOWN}}}, + }); + runEvents(); +} + +TEST_F(DebounceTest, TwoKeysShort) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {}}, + {1, {{0, 2, DOWN}}, {}}, + + {6, {}, {{0, 1, DOWN}, {0, 2, DOWN}}}, + + {7, {{0, 1, UP}}, {}}, + {8, {{0, 2, UP}}, {}}, + + {13, {}, {{0, 1, UP}, {0, 2, UP}}}, + }); + runEvents(); +} + +TEST_F(DebounceTest, TwoKeysSimultaneous1) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}, {0, 2, DOWN}}, {}}, + + {5, {}, {{0, 1, DOWN}, {0, 2, DOWN}}}, + {6, {{0, 1, UP}, {0, 2, UP}}, {}}, + + {11, {}, {{0, 1, UP}, {0, 2, UP}}}, + }); + runEvents(); +} + +TEST_F(DebounceTest, TwoKeysSimultaneous2) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {}}, + {1, {{0, 2, DOWN}}, {}}, + + {5, {}, {}}, + {6, {}, {{0, 1, DOWN}, {0, 2, DOWN}}}, + {7, {{0, 1, UP}}, {}}, + {8, {{0, 2, UP}}, {}}, + + {13, {}, {{0, 1, UP}, {0, 2, UP}}}, + }); + runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan1) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {}}, + + /* Processing is very late */ + {300, {}, {{0, 1, DOWN}}}, + /* Immediately release key */ + {300, {{0, 1, UP}}, {}}, + + {305, {}, {{0, 1, UP}}}, + }); + time_jumps_ = true; + runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan2) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {}}, + + /* Processing is very late */ + {300, {}, {{0, 1, DOWN}}}, + /* Release key after 1ms */ + {301, {{0, 1, UP}}, {}}, + + {306, {}, {{0, 1, UP}}}, + }); + time_jumps_ = true; + runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan3) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {}}, + + /* Release key before debounce expires */ + {300, {{0, 1, UP}}, {}}, + }); + time_jumps_ = true; + runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan4) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {}}, + + /* Processing is a bit late */ + {50, {}, {{0, 1, DOWN}}}, + /* Release key after 1ms */ + {51, {{0, 1, UP}}, {}}, + + {56, {}, {{0, 1, UP}}}, + }); + time_jumps_ = true; + runEvents(); +} diff --git a/quantum/debounce/tests/sym_defer_pk_tests.cpp b/quantum/debounce/tests/sym_defer_pk_tests.cpp new file mode 100644 index 0000000000..1f3061e59c --- /dev/null +++ b/quantum/debounce/tests/sym_defer_pk_tests.cpp @@ -0,0 +1,225 @@ +/* Copyright 2021 Simon Arlott + * + * 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 . + */ + +#include "gtest/gtest.h" + +#include "debounce_test_common.h" + +TEST_F(DebounceTest, OneKeyShort1) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {}}, + + {5, {}, {{0, 1, DOWN}}}, + /* 0ms delay (fast scan rate) */ + {5, {{0, 1, UP}}, {}}, + + {10, {}, {{0, 1, UP}}}, + }); + runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort2) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {}}, + + {5, {}, {{0, 1, DOWN}}}, + /* 1ms delay */ + {6, {{0, 1, UP}}, {}}, + + {11, {}, {{0, 1, UP}}}, + }); + runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort3) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {}}, + + {5, {}, {{0, 1, DOWN}}}, + /* 2ms delay */ + {7, {{0, 1, UP}}, {}}, + + {12, {}, {{0, 1, UP}}}, + }); + runEvents(); +} + +TEST_F(DebounceTest, OneKeyTooQuick1) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {}}, + /* Release key exactly on the debounce time */ + {5, {{0, 1, UP}}, {}}, + }); + runEvents(); +} + +TEST_F(DebounceTest, OneKeyTooQuick2) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {}}, + + {5, {}, {{0, 1, DOWN}}}, + {6, {{0, 1, UP}}, {}}, + + /* Press key exactly on the debounce time */ + {11, {{0, 1, DOWN}}, {}}, + }); + runEvents(); +} + +TEST_F(DebounceTest, OneKeyBouncing1) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {}}, + {1, {{0, 1, UP}}, {}}, + {2, {{0, 1, DOWN}}, {}}, + {3, {{0, 1, UP}}, {}}, + {4, {{0, 1, DOWN}}, {}}, + {5, {{0, 1, UP}}, {}}, + {6, {{0, 1, DOWN}}, {}}, + {11, {}, {{0, 1, DOWN}}}, /* 5ms after DOWN at time 7 */ + }); + runEvents(); +} + +TEST_F(DebounceTest, OneKeyBouncing2) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {}}, + {5, {}, {{0, 1, DOWN}}}, + {6, {{0, 1, UP}}, {}}, + {7, {{0, 1, DOWN}}, {}}, + {8, {{0, 1, UP}}, {}}, + {9, {{0, 1, DOWN}}, {}}, + {10, {{0, 1, UP}}, {}}, + {15, {}, {{0, 1, UP}}}, /* 5ms after UP at time 10 */ + }); + runEvents(); +} + +TEST_F(DebounceTest, OneKeyLong) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {}}, + + {5, {}, {{0, 1, DOWN}}}, + + {25, {{0, 1, UP}}, {}}, + + {30, {}, {{0, 1, UP}}}, + + {50, {{0, 1, DOWN}}, {}}, + + {55, {}, {{0, 1, DOWN}}}, + }); + runEvents(); +} + +TEST_F(DebounceTest, TwoKeysShort) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {}}, + {1, {{0, 2, DOWN}}, {}}, + + {5, {}, {{0, 1, DOWN}}}, + {6, {}, {{0, 2, DOWN}}}, + + {7, {{0, 1, UP}}, {}}, + {8, {{0, 2, UP}}, {}}, + + {12, {}, {{0, 1, UP}}}, + {13, {}, {{0, 2, UP}}}, + }); + runEvents(); +} + +TEST_F(DebounceTest, TwoKeysSimultaneous1) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}, {0, 2, DOWN}}, {}}, + + {5, {}, {{0, 1, DOWN}, {0, 2, DOWN}}}, + {6, {{0, 1, UP}, {0, 2, UP}}, {}}, + + {11, {}, {{0, 1, UP}, {0, 2, UP}}}, + }); + runEvents(); +} + +TEST_F(DebounceTest, TwoKeysSimultaneous2) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {}}, + {1, {{0, 2, DOWN}}, {}}, + + {5, {}, {{0, 1, DOWN}}}, + {6, {{0, 1, UP}}, {{0, 2, DOWN}}}, + {7, {{0, 2, UP}}, {}}, + + {11, {}, {{0, 1, UP}}}, + {12, {}, {{0, 2, UP}}}, + }); + runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan1) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {}}, + + /* Processing is very late */ + {300, {}, {{0, 1, DOWN}}}, + /* Immediately release key */ + {300, {{0, 1, UP}}, {}}, + + {305, {}, {{0, 1, UP}}}, + }); + time_jumps_ = true; + runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan2) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {}}, + + /* Processing is very late */ + {300, {}, {{0, 1, DOWN}}}, + /* Release key after 1ms */ + {301, {{0, 1, UP}}, {}}, + + {306, {}, {{0, 1, UP}}}, + }); + time_jumps_ = true; + runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan3) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {}}, + + /* Release key before debounce expires */ + {300, {{0, 1, UP}}, {}}, + }); + time_jumps_ = true; + runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan4) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {}}, + + /* Processing is a bit late */ + {50, {}, {{0, 1, DOWN}}}, + /* Release key after 1ms */ + {51, {{0, 1, UP}}, {}}, + + {56, {}, {{0, 1, UP}}}, + }); + time_jumps_ = true; + runEvents(); +} diff --git a/quantum/debounce/tests/sym_eager_pk_tests.cpp b/quantum/debounce/tests/sym_eager_pk_tests.cpp new file mode 100644 index 0000000000..e0fc205e33 --- /dev/null +++ b/quantum/debounce/tests/sym_eager_pk_tests.cpp @@ -0,0 +1,237 @@ +/* Copyright 2021 Simon Arlott + * + * 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 . + */ + +#include "gtest/gtest.h" + +#include "debounce_test_common.h" + +TEST_F(DebounceTest, OneKeyShort1) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + {1, {{0, 1, UP}}, {}}, + + {5, {}, {{0, 1, UP}}}, + /* Press key again after 1ms delay (debounce has not yet finished) */ + {6, {{0, 1, DOWN}}, {}}, + {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ + }); + runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort2) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + {1, {{0, 1, UP}}, {}}, + + {5, {}, {{0, 1, UP}}}, + /* Press key again after 2ms delay (debounce has not yet finished) */ + {7, {{0, 1, DOWN}}, {}}, + {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ + }); + runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort3) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + {1, {{0, 1, UP}}, {}}, + + {5, {}, {{0, 1, UP}}}, + /* Press key again after 3ms delay (debounce has not yet finished) */ + {8, {{0, 1, DOWN}}, {}}, + {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ + }); + runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort4) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + {1, {{0, 1, UP}}, {}}, + + {5, {}, {{0, 1, UP}}}, + /* Press key again after 4ms delay (debounce has not yet finished) */ + {9, {{0, 1, DOWN}}, {}}, + {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ + }); + runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort5) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + {1, {{0, 1, UP}}, {}}, + + {5, {}, {{0, 1, UP}}}, + /* Press key again after 5ms delay (debounce has finished) */ + {10, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + }); + runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort6) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + {1, {{0, 1, UP}}, {}}, + + {5, {}, {{0, 1, UP}}}, + /* Press key after after 6ms delay (debounce has finished) */ + {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + }); + runEvents(); +} + +TEST_F(DebounceTest, OneKeyBouncing1) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + {1, {{0, 1, UP}}, {}}, + {2, {{0, 1, DOWN}}, {}}, + {3, {{0, 1, UP}}, {}}, + {4, {{0, 1, DOWN}}, {}}, + {5, {{0, 1, UP}}, {{0, 1, UP}}}, + /* Press key again after 1ms delay (debounce has not yet finished) */ + {6, {{0, 1, DOWN}}, {}}, + {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ + }); + runEvents(); +} + +TEST_F(DebounceTest, OneKeyBouncing2) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + /* Change twice in the same time period */ + {1, {{0, 1, UP}}, {}}, + {1, {{0, 1, DOWN}}, {}}, + /* Change three times in the same time period */ + {2, {{0, 1, UP}}, {}}, + {2, {{0, 1, DOWN}}, {}}, + {2, {{0, 1, UP}}, {}}, + /* Change three times in the same time period */ + {3, {{0, 1, DOWN}}, {}}, + {3, {{0, 1, UP}}, {}}, + {3, {{0, 1, DOWN}}, {}}, + /* Change twice in the same time period */ + {4, {{0, 1, UP}}, {}}, + {4, {{0, 1, DOWN}}, {}}, + {5, {{0, 1, UP}}, {{0, 1, UP}}}, + /* Press key again after 1ms delay (debounce has not yet finished) */ + {6, {{0, 1, DOWN}}, {}}, + {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ + }); + runEvents(); +} + +TEST_F(DebounceTest, OneKeyLong) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + + {25, {{0, 1, UP}}, {{0, 1, UP}}}, + + {50, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + }); + runEvents(); +} + +TEST_F(DebounceTest, TwoKeysShort) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + {1, {{0, 1, UP}}, {}}, + {2, {{0, 2, DOWN}}, {{0, 2, DOWN}}}, + {3, {{0, 2, UP}}, {}}, + + {5, {}, {{0, 1, UP}}}, + /* Press key again after 1ms delay (debounce has not yet finished) */ + {6, {{0, 1, DOWN}}, {}}, + {7, {}, {{0, 2, UP}}}, + + /* Press key again after 1ms delay (debounce has not yet finished) */ + {9, {{0, 2, DOWN}}, {}}, + {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ + + {12, {}, {{0, 2, DOWN}}}, /* 5ms after UP at time 7 */ + }); + runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan1) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + + /* Processing is very late but the change will now be accepted */ + {300, {{0, 1, UP}}, {{0, 1, UP}}}, + }); + time_jumps_ = true; + runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan2) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + + /* Processing is very late but the change will now be accepted even with a 1 scan delay */ + {300, {}, {}}, + {300, {{0, 1, UP}}, {{0, 1, UP}}}, + }); + time_jumps_ = true; + runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan3) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + + /* Processing is very late but the change will now be accepted even with a 1ms delay */ + {300, {}, {}}, + {301, {{0, 1, UP}}, {{0, 1, UP}}}, + }); + time_jumps_ = true; + runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan4) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + + /* Processing is a bit late but the change will now be accepted */ + {50, {{0, 1, UP}}, {{0, 1, UP}}}, + }); + time_jumps_ = true; + runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan5) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + + /* Processing is very late but the change will now be accepted even with a 1 scan delay */ + {50, {}, {}}, + {50, {{0, 1, UP}}, {{0, 1, UP}}}, + }); + time_jumps_ = true; + runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan6) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + + /* Processing is very late but the change will now be accepted even with a 1ms delay */ + {50, {}, {}}, + {51, {{0, 1, UP}}, {{0, 1, UP}}}, + }); + time_jumps_ = true; + runEvents(); +} diff --git a/quantum/debounce/tests/sym_eager_pr_tests.cpp b/quantum/debounce/tests/sym_eager_pr_tests.cpp new file mode 100644 index 0000000000..2c4bca127e --- /dev/null +++ b/quantum/debounce/tests/sym_eager_pr_tests.cpp @@ -0,0 +1,280 @@ +/* Copyright 2021 Simon Arlott + * + * 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 . + */ + +#include "gtest/gtest.h" + +#include "debounce_test_common.h" + +TEST_F(DebounceTest, OneKeyShort1) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + {1, {{0, 1, UP}}, {}}, + + {5, {}, {{0, 1, UP}}}, + /* Press key again after 1ms delay (debounce has not yet finished) */ + {6, {{0, 1, DOWN}}, {}}, + {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ + }); + runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort2) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + {1, {{0, 1, UP}}, {}}, + + {5, {}, {{0, 1, UP}}}, + /* Press key again after 2ms delay (debounce has not yet finished) */ + {7, {{0, 1, DOWN}}, {}}, + {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ + }); + runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort3) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + {1, {{0, 1, UP}}, {}}, + + {5, {}, {{0, 1, UP}}}, + /* Press key again after 3ms delay (debounce has not yet finished) */ + {8, {{0, 1, DOWN}}, {}}, + {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ + }); + runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort4) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + {1, {{0, 1, UP}}, {}}, + + {5, {}, {{0, 1, UP}}}, + /* Press key again after 4ms delay (debounce has not yet finished) */ + {9, {{0, 1, DOWN}}, {}}, + {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ + }); + runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort5) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + {1, {{0, 1, UP}}, {}}, + + {5, {}, {{0, 1, UP}}}, + /* Press key again after 5ms delay (debounce has finished) */ + {10, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + }); + runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort6) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + {1, {{0, 1, UP}}, {}}, + + {5, {}, {{0, 1, UP}}}, + /* Press key after after 6ms delay (debounce has finished) */ + {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + }); + runEvents(); +} + +TEST_F(DebounceTest, OneKeyBouncing1) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + {1, {{0, 1, UP}}, {}}, + {2, {{0, 1, DOWN}}, {}}, + {3, {{0, 1, UP}}, {}}, + {4, {{0, 1, DOWN}}, {}}, + {5, {{0, 1, UP}}, {{0, 1, UP}}}, + /* Press key again after 1ms delay (debounce has not yet finished) */ + {6, {{0, 1, DOWN}}, {}}, + {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ + }); + runEvents(); +} + +TEST_F(DebounceTest, OneKeyBouncing2) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + /* Change twice in the same time period */ + {1, {{0, 1, UP}}, {}}, + {1, {{0, 1, DOWN}}, {}}, + /* Change three times in the same time period */ + {2, {{0, 1, UP}}, {}}, + {2, {{0, 1, DOWN}}, {}}, + {2, {{0, 1, UP}}, {}}, + /* Change three times in the same time period */ + {3, {{0, 1, DOWN}}, {}}, + {3, {{0, 1, UP}}, {}}, + {3, {{0, 1, DOWN}}, {}}, + /* Change twice in the same time period */ + {4, {{0, 1, UP}}, {}}, + {4, {{0, 1, DOWN}}, {}}, + {5, {{0, 1, UP}}, {{0, 1, UP}}}, + /* Press key again after 1ms delay (debounce has not yet finished) */ + {6, {{0, 1, DOWN}}, {}}, + {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ + }); + runEvents(); +} + +TEST_F(DebounceTest, OneKeyLong) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + + {25, {{0, 1, UP}}, {{0, 1, UP}}}, + + {50, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + }); + runEvents(); +} + +TEST_F(DebounceTest, TwoRowsShort) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + {1, {{0, 1, UP}}, {}}, + {2, {{2, 0, DOWN}}, {{2, 0, DOWN}}}, + {3, {{2, 0, UP}}, {}}, + + {5, {}, {{0, 1, UP}}}, + /* Press key again after 1ms delay (debounce has not yet finished) */ + {6, {{0, 1, DOWN}}, {}}, + {7, {}, {{2, 0, UP}}}, + + /* Press key again after 1ms delay (debounce has not yet finished) */ + {9, {{2, 0, DOWN}}, {}}, + {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ + + {12, {}, {{2, 0, DOWN}}}, /* 5ms after UP at time 7 */ + }); + runEvents(); +} + +TEST_F(DebounceTest, TwoKeysOverlap) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + {1, {{0, 1, UP}}, {}}, + /* Press a second key during the first debounce */ + {2, {{0, 2, DOWN}}, {}}, + + /* Key registers as soon as debounce finishes, 5ms after time 0 */ + {5, {}, {{0, 1, UP}, {0, 2, DOWN}}}, + {6, {{0, 1, DOWN}}, {}}, + + /* Key registers as soon as debounce finishes, 5ms after time 5 */ + {10, {}, {{0, 1, DOWN}}}, + /* Release both keys */ + {11, {{0, 1, UP}}, {}}, + {12, {{0, 2, UP}}, {}}, + + /* Keys register as soon as debounce finishes, 5ms after time 10 */ + {15, {}, {{0, 1, UP}, {0, 2, UP}}}, + }); + runEvents(); +} + +TEST_F(DebounceTest, TwoKeysSimultaneous1) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}, {0, 2, DOWN}}, {{0, 1, DOWN}, {0, 2, DOWN}}}, + {20, {{0, 1, UP}}, {{0, 1, UP}}}, + {21, {{0, 2, UP}}, {}}, + + /* Key registers as soon as debounce finishes, 5ms after time 20 */ + {25, {}, {{0, 2, UP}}}, + }); + runEvents(); +} + +TEST_F(DebounceTest, TwoKeysSimultaneous2) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}, {0, 2, DOWN}}, {{0, 1, DOWN}, {0, 2, DOWN}}}, + {20, {{0, 1, UP}, {0, 2, UP}}, {{0, 1, UP}, {0, 2, UP}}}, + }); + runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan1) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + + /* Processing is very late but the change will now be accepted */ + {300, {{0, 1, UP}}, {{0, 1, UP}}}, + }); + time_jumps_ = true; + runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan2) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + + /* Processing is very late but the change will now be accepted even with a 1 scan delay */ + {300, {}, {}}, + {300, {{0, 1, UP}}, {{0, 1, UP}}}, + }); + time_jumps_ = true; + runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan3) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + + /* Processing is very late but the change will now be accepted even with a 1ms delay */ + {300, {}, {}}, + {301, {{0, 1, UP}}, {{0, 1, UP}}}, + }); + time_jumps_ = true; + runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan4) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + + /* Processing is a bit late but the change will now be accepted */ + {50, {{0, 1, UP}}, {{0, 1, UP}}}, + }); + time_jumps_ = true; + runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan5) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + + /* Processing is very late but the change will now be accepted even with a 1 scan delay */ + {50, {}, {}}, + {50, {{0, 1, UP}}, {{0, 1, UP}}}, + }); + time_jumps_ = true; + runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan6) { + addEvents({ /* Time, Inputs, Outputs */ + {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + + /* Processing is very late but the change will now be accepted even with a 1ms delay */ + {50, {}, {}}, + {51, {{0, 1, UP}}, {{0, 1, UP}}}, + }); + time_jumps_ = true; + runEvents(); +} diff --git a/quantum/debounce/tests/testlist.mk b/quantum/debounce/tests/testlist.mk new file mode 100644 index 0000000000..16ce8a0a8e --- /dev/null +++ b/quantum/debounce/tests/testlist.mk @@ -0,0 +1,5 @@ +TEST_LIST += \ + debounce_sym_defer_g \ + debounce_sym_defer_pk \ + debounce_sym_eager_pk \ + debounce_sym_eager_pr diff --git a/testlist.mk b/testlist.mk index 0d7609b9f0..d256f4c815 100644 --- a/testlist.mk +++ b/testlist.mk @@ -1,6 +1,7 @@ TEST_LIST = $(notdir $(patsubst %/rules.mk,%,$(wildcard $(ROOT_DIR)/tests/*/rules.mk))) FULL_TESTS := $(TEST_LIST) +include $(ROOT_DIR)/quantum/debounce/tests/testlist.mk include $(ROOT_DIR)/quantum/sequencer/tests/testlist.mk include $(ROOT_DIR)/quantum/serial_link/tests/testlist.mk diff --git a/tmk_core/common/arm_atsam/_timer.h b/tmk_core/common/arm_atsam/_timer.h new file mode 100644 index 0000000000..77402b612a --- /dev/null +++ b/tmk_core/common/arm_atsam/_timer.h @@ -0,0 +1,19 @@ +/* Copyright 2021 Simon Arlott + * + * 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 . + */ +#pragma once + +// The platform is 32-bit, so prefer 32-bit timers to avoid overflow +#define FAST_TIMER_T_SIZE 32 diff --git a/tmk_core/common/avr/_timer.h b/tmk_core/common/avr/_timer.h new file mode 100644 index 0000000000..b81e0f68b7 --- /dev/null +++ b/tmk_core/common/avr/_timer.h @@ -0,0 +1,19 @@ +/* Copyright 2021 Simon Arlott + * + * 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 . + */ +#pragma once + +// The platform is 8-bit, so prefer 16-bit timers to reduce code size +#define FAST_TIMER_T_SIZE 16 diff --git a/tmk_core/common/chibios/_timer.h b/tmk_core/common/chibios/_timer.h new file mode 100644 index 0000000000..77402b612a --- /dev/null +++ b/tmk_core/common/chibios/_timer.h @@ -0,0 +1,19 @@ +/* Copyright 2021 Simon Arlott + * + * 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 . + */ +#pragma once + +// The platform is 32-bit, so prefer 32-bit timers to avoid overflow +#define FAST_TIMER_T_SIZE 32 diff --git a/tmk_core/common/timer.h b/tmk_core/common/timer.h index 58f637dd93..928811a2b7 100644 --- a/tmk_core/common/timer.h +++ b/tmk_core/common/timer.h @@ -1,5 +1,6 @@ /* Copyright 2011 Jun Wako +Copyright 2021 Simon Arlott 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 @@ -17,13 +18,13 @@ along with this program. If not, see . #pragma once +#if __has_include_next("_timer.h") +# include_next "_timer.h" /* Include the platform's _timer.h */ +#endif + #include #include -#if defined(__AVR__) -# include "avr/timer_avr.h" -#endif - #define TIMER_DIFF(a, b, max) ((max == UINT8_MAX) ? ((uint8_t)((a) - (b))) : ((max == UINT16_MAX) ? ((uint16_t)((a) - (b))) : ((max == UINT32_MAX) ? ((uint32_t)((a) - (b))) : ((a) >= (b) ? (a) - (b) : (max) + 1 - (b) + (a))))) #define TIMER_DIFF_8(a, b) TIMER_DIFF(a, b, UINT8_MAX) #define TIMER_DIFF_16(a, b) TIMER_DIFF(a, b, UINT16_MAX) @@ -47,6 +48,21 @@ uint32_t timer_elapsed32(uint32_t last); #define timer_expired(current, future) ((uint16_t)(current - future) < UINT16_MAX / 2) #define timer_expired32(current, future) ((uint32_t)(current - future) < UINT32_MAX / 2) +// Use an appropriate timer integer size based on architecture (16-bit will overflow sooner) +#if FAST_TIMER_T_SIZE < 32 +# define TIMER_DIFF_FAST(a, b) TIMER_DIFF_16(a, b) +# define timer_expired_fast(current, future) timer_expired(current, future) +typedef uint16_t fast_timer_t; +fast_timer_t inline timer_read_fast(void) { return timer_read(); } +fast_timer_t inline timer_elapsed_fast(fast_timer_t last) { return timer_elapsed(last); } +#else +# define TIMER_DIFF_FAST(a, b) TIMER_DIFF_32(a, b) +# define timer_expired_fast(current, future) timer_expired32(current, future) +typedef uint32_t fast_timer_t; +fast_timer_t inline timer_read_fast(void) { return timer_read32(); } +fast_timer_t inline timer_elapsed_fast(fast_timer_t last) { return timer_elapsed32(last); } +#endif + #ifdef __cplusplus } #endif -- cgit v1.2.3 From b2fdd4874434ef6921a436fc82d9f24909c726f8 Mon Sep 17 00:00:00 2001 From: Ryan Date: Thu, 10 Jun 2021 17:16:09 +1000 Subject: Add ST7565 LCD driver (#13089) Co-authored-by: Joakim Tufvegren --- common_features.mk | 8 + docs/_summary.md | 1 + docs/feature_st7565.md | 270 +++++++++++++++++++++++++ drivers/lcd/st7565.c | 479 +++++++++++++++++++++++++++++++++++++++++++++ drivers/lcd/st7565.h | 215 ++++++++++++++++++++ quantum/quantum.h | 4 + tmk_core/common/keyboard.c | 18 ++ 7 files changed, 995 insertions(+) create mode 100644 docs/feature_st7565.md create mode 100644 drivers/lcd/st7565.c create mode 100644 drivers/lcd/st7565.h (limited to 'tmk_core') diff --git a/common_features.mk b/common_features.mk index 37ce928e2a..b259af46c0 100644 --- a/common_features.mk +++ b/common_features.mk @@ -587,6 +587,14 @@ ifeq ($(strip $(OLED_DRIVER_ENABLE)), yes) SRC += oled_driver.c endif +ifeq ($(strip $(ST7565_ENABLE)), yes) + OPT_DEFS += -DST7565_ENABLE + COMMON_VPATH += $(DRIVER_PATH)/oled # For glcdfont.h + COMMON_VPATH += $(DRIVER_PATH)/lcd + QUANTUM_LIB_SRC += spi_master.c + SRC += st7565.c +endif + include $(DRIVER_PATH)/qwiic/qwiic.mk ifeq ($(strip $(UCIS_ENABLE)), yes) diff --git a/docs/_summary.md b/docs/_summary.md index 9798ef5127..4141e01e77 100644 --- a/docs/_summary.md +++ b/docs/_summary.md @@ -93,6 +93,7 @@ * Hardware Features * Displays * [HD44780 LCD Controller](feature_hd44780.md) + * [ST7565 LCD Driver](feature_st7565.md) * [OLED Driver](feature_oled_driver.md) * Lighting * [Backlight](feature_backlight.md) diff --git a/docs/feature_st7565.md b/docs/feature_st7565.md new file mode 100644 index 0000000000..7db0f9ac4a --- /dev/null +++ b/docs/feature_st7565.md @@ -0,0 +1,270 @@ +# ST7565 LCD Driver + +## Supported Hardware + +LCD modules using ST7565 driver IC, communicating over SPI. + +|Module |IC |Size |Notes | +|------------------------------|-------|------|----------------------------------------------------------| +|Newhaven Display NHD-C12832A1Z|ST7565R|128x32|Used by Ergodox Infinity; primary consumer of this feature| +|Zolentech ZLE12864B |ST7565P|128x64|Requires contrast adjustment | + +## Usage + +To enable the feature, there are three steps. First, when compiling your keyboard, you'll need to add the following to your `rules.mk`: + +```make +ST7565_ENABLE = yes +``` + +Then in your `keymap.c` file, implement the ST7565 task call. This example assumes your keymap has three layers named `_QWERTY`, `_FN` and `_ADJ`: + +```c +#ifdef ST7565_ENABLE +void st7565_task_user(void) { + // Host Keyboard Layer Status + st7565_write_P(PSTR("Layer: "), false); + + switch (get_highest_layer(layer_state)) { + case _QWERTY: + st7565_write_P(PSTR("Default\n"), false); + break; + case _FN: + st7565_write_P(PSTR("FN\n"), false); + break; + case _ADJ: + st7565_write_P(PSTR("ADJ\n"), false); + break; + default: + // Or use the write_ln shortcut over adding '\n' to the end of your string + st7565_write_ln_P(PSTR("Undefined"), false); + } + + // Host Keyboard LED Status + led_t led_state = host_keyboard_led_state(); + st7565_write_P(led_state.num_lock ? PSTR("NUM ") : PSTR(" "), false); + st7565_write_P(led_state.caps_lock ? PSTR("CAP ") : PSTR(" "), false); + st7565_write_P(led_state.scroll_lock ? PSTR("SCR ") : PSTR(" "), false); +} +#endif +``` + +## Logo Example + +In the default font, certain ranges of characters are reserved for a QMK logo. To render this logo to the screen, use the following code example: + +```c +static void render_logo(void) { + static const char PROGMEM qmk_logo[] = { + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, + 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, + 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0x00 + }; + + st7565_write_P(qmk_logo, false); +} +``` + +## Buffer Read Example +For some purposes, you may need to read the current state of the display buffer. The `st7565_read_raw` function can be used to safely read bytes from the buffer. + +In this example, calling `fade_display` in the `st7565_task_user` function will slowly fade away whatever is on the screen by turning random pixels off over time. +```c +//Setup some mask which can be or'd with bytes to turn off pixels +const uint8_t single_bit_masks[8] = {127, 191, 223, 239, 247, 251, 253, 254}; + +static void fade_display(void) { + //Define the reader structure + display_buffer_reader_t reader; + uint8_t buff_char; + if (random() % 30 == 0) { + srand(timer_read()); + // Fetch a pointer for the buffer byte at index 0. The return structure + // will have the pointer and the number of bytes remaining from this + // index position if we want to perform a sequential read by + // incrementing the buffer pointer + reader = st7565_read_raw(0); + //Loop over the remaining buffer and erase pixels as we go + for (uint16_t i = 0; i < reader.remaining_element_count; i++) { + //Get the actual byte in the buffer by dereferencing the pointer + buff_char = *reader.current_element; + if (buff_char != 0) { + st7565_write_raw_byte(buff_char & single_bit_masks[rand() % 8], i); + } + //increment the pointer to fetch a new byte during the next loop + reader.current_element++; + } + } +} +``` + +## Other Examples + +In split keyboards, it is very common to have two displays that each render different content and are oriented or flipped differently. You can do this by switching which content to render by using the return value from `is_keyboard_master()` or `is_keyboard_left()` found in `split_util.h`, e.g: + +```c +#ifdef ST7565_ENABLE +display_rotation_t st7565_init_user(display_rotation_t rotation) { + if (!is_keyboard_master()) { + return DISPLAY_ROTATION_180; // flips the display 180 degrees if offhand + } + + return rotation; +} + +void st7565_task_user(void) { + if (is_keyboard_master()) { + render_status(); // Renders the current keyboard state (layer, lock, caps, scroll, etc) + } else { + render_logo(); // Renders a static logo + } +} +#endif +``` + +## Basic Configuration + +|Define |Default |Description | +|------------------------|--------------|-----------------------------------------------------------------------------------------------------| +|`ST7565_A0_PIN` |*Not defined* |(Required) The GPIO connected to the display's A0 (data/command) pin | +|`ST7565_RST_PIN` |*Not defined* |(Required) The GPIO connected to the display's reset pin | +|`ST7565_SS_PIN` |*Not defined* |(Required) The GPIO connected to the display's slave select pin | +|`ST7565_SPI_CLK_DIVISOR`|`4` |The SPI clock divisor to use | +|`ST7565_FONT_H` |`"glcdfont.c"`|The font code file to use for custom fonts | +|`ST7565_FONT_START` |`0` |The starting character index for custom fonts | +|`ST7565_FONT_END` |`223` |The ending character index for custom fonts | +|`ST7565_FONT_WIDTH` |`6` |The font width | +|`ST7565_FONT_HEIGHT` |`8` |The font height (untested) | +|`ST7565_TIMEOUT` |`60000` |Turns off the screen after 60000ms of keyboard inactivity. Helps reduce burn-in. Set to 0 to disable.| +|`ST7565_COLUMN_OFFSET` |`0` |Shift output to the right this many pixels. | +|`ST7565_CONTRAST` |`32` |The default contrast level of the display, from 0 to 255. | +|`ST7565_UPDATE_INTERVAL`|`0` |Set the time interval for updating the display in ms. This will improve the matrix scan rate. | + +## Custom sized displays + +The default display size for this feature is 128x32 and all necessary defines are precalculated with that in mind. + +|Define |Default |Description | +|-----------------------|----------|-----------------------------------------------------------------------------------------------------------| +|`ST7565_DISPLAY_WIDTH` |`128` |The width of the display. | +|`ST7565_DISPLAY_HEIGHT`|`32` |The height of the display. | +|`ST7565_MATRIX_SIZE` |`512` |The local buffer size to allocate.
`(ST7565_DISPLAY_HEIGHT / 8 * ST7565_DISPLAY_WIDTH)`. | +|`ST7565_BLOCK_TYPE` |`uint16_t`|The unsigned integer type to use for dirty rendering. | +|`ST7565_BLOCK_COUNT` |`16` |The number of blocks the display is divided into for dirty rendering.
`(sizeof(ST7565_BLOCK_TYPE) * 8)`.| +|`ST7565_BLOCK_SIZE` |`32` |The size of each block for dirty rendering
`(ST7565_MATRIX_SIZE / ST7565_BLOCK_COUNT)`. | + +## API + +```c +// Rotation enum values are flags +typedef enum { + DISPLAY_ROTATION_0, + DISPLAY_ROTATION_180 +} display_rotation_t; + +// Initialize the display, rotating the rendered output based on the define passed in. +// Returns true if the was initialized successfully +bool st7565_init(display_rotation_t rotation); + +// Called at the start of st7565_init, weak function overridable by the user +// rotation - the value passed into st7565_init +// Return new display_rotation_t if you want to override default rotation +display_rotation_t st7565_init_user(display_rotation_t rotation); + +// Clears the display buffer, resets cursor position to 0, and sets the buffer to dirty for rendering +void st7565_clear(void); + +// Renders the dirty chunks of the buffer to display +void st7565_render(void); + +// Moves cursor to character position indicated by column and line, wraps if out of bounds +// Max column denoted by 'st7565_max_chars()' and max lines by 'st7565_max_lines()' functions +void st7565_set_cursor(uint8_t col, uint8_t line); + +// Advances the cursor to the next page, writing ' ' if true +// Wraps to the begining when out of bounds +void st7565_advance_page(bool clearPageRemainder); + +// Moves the cursor forward 1 character length +// Advance page if there is not enough room for the next character +// Wraps to the begining when out of bounds +void st7565_advance_char(void); + +// Writes a single character to the buffer at current cursor position +// Advances the cursor while writing, inverts the pixels if true +// Main handler that writes character data to the display buffer +void st7565_write_char(const char data, bool invert); + +// Writes a string to the buffer at current cursor position +// Advances the cursor while writing, inverts the pixels if true +void st7565_write(const char *data, bool invert); + +// Writes a string to the buffer at current cursor position +// Advances the cursor while writing, inverts the pixels if true +// Advances the cursor to the next page, wiring ' ' to the remainder of the current page +void st7565_write_ln(const char *data, bool invert); + +// Pans the buffer to the right (or left by passing true) by moving contents of the buffer +// Useful for moving the screen in preparation for new drawing +void st7565_pan(bool left); + +// Returns a pointer to the requested start index in the buffer plus remaining +// buffer length as struct +display_buffer_reader_t st7565_read_raw(uint16_t start_index); + +// Writes a string to the buffer at current cursor position +void st7565_write_raw(const char *data, uint16_t size); + +// Writes a single byte into the buffer at the specified index +void st7565_write_raw_byte(const char data, uint16_t index); + +// Sets a specific pixel on or off +// Coordinates start at top-left and go right and down for positive x and y +void st7565_write_pixel(uint8_t x, uint8_t y, bool on); + +// Writes a PROGMEM string to the buffer at current cursor position +// Advances the cursor while writing, inverts the pixels if true +// Remapped to call 'void st7565_write(const char *data, bool invert);' on ARM +void st7565_write_P(const char *data, bool invert); + +// Writes a PROGMEM string to the buffer at current cursor position +// Advances the cursor while writing, inverts the pixels if true +// Advances the cursor to the next page, wiring ' ' to the remainder of the current page +// Remapped to call 'void st7565_write_ln(const char *data, bool invert);' on ARM +void st7565_write_ln_P(const char *data, bool invert); + +// Writes a PROGMEM string to the buffer at current cursor position +void st7565_write_raw_P(const char *data, uint16_t size); + +// Can be used to manually turn on the screen if it is off +// Returns true if the screen was on or turns on +bool st7565_on(void); + +// Called when st7565_on() turns on the screen, weak function overridable by the user +// Not called if the screen is already on +void st7565_on_user(void); + +// Can be used to manually turn off the screen if it is on +// Returns true if the screen was off or turns off +bool st7565_off(void); + +// Called when st7565_off() turns off the screen, weak function overridable by the user +// Not called if the screen is already off +void st7565_off_user(void); + +// Returns true if the screen is currently on, false if it is +// not +bool st7565_is_on(void); + +// Basically it's st7565_render, but with timeout management and st7565_task_user calling! +void st7565_task(void); + +// Called at the start of st7565_task, weak function overridable by the user +void st7565_task_user(void); + +// Returns the maximum number of characters that will fit on a line +uint8_t st7565_max_chars(void); + +// Returns the maximum number of lines that will fit on the display +uint8_t st7565_max_lines(void); +``` diff --git a/drivers/lcd/st7565.c b/drivers/lcd/st7565.c new file mode 100644 index 0000000000..4b4891ce71 --- /dev/null +++ b/drivers/lcd/st7565.c @@ -0,0 +1,479 @@ +/* +Copyright 2021 + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include "st7565.h" + +#include + +#include "keyboard.h" +#include "progmem.h" +#include "timer.h" +#include "wait.h" + +#include ST7565_FONT_H + +// Fundamental Commands +#define CONTRAST 0x81 +#define DISPLAY_ALL_ON 0xA5 +#define DISPLAY_ALL_ON_RESUME 0xA4 +#define NORMAL_DISPLAY 0xA6 +#define DISPLAY_ON 0xAF +#define DISPLAY_OFF 0xAE +#define NOP 0xE3 + +// Addressing Setting Commands +#define PAM_SETCOLUMN_LSB 0x00 +#define PAM_SETCOLUMN_MSB 0x10 +#define PAM_PAGE_ADDR 0xB0 // 0xb0 -- 0xb7 + +// Hardware Configuration Commands +#define DISPLAY_START_LINE 0x40 +#define SEGMENT_REMAP 0xA0 +#define SEGMENT_REMAP_INV 0xA1 +#define COM_SCAN_INC 0xC0 +#define COM_SCAN_DEC 0xC8 +#define LCD_BIAS_7 0xA3 +#define LCD_BIAS_9 0xA2 +#define RESISTOR_RATIO 0x20 +#define POWER_CONTROL 0x28 + +// Misc defines +#ifndef ST7565_BLOCK_COUNT +# define ST7565_BLOCK_COUNT (sizeof(ST7565_BLOCK_TYPE) * 8) +#endif +#ifndef ST7565_BLOCK_SIZE +# define ST7565_BLOCK_SIZE (ST7565_MATRIX_SIZE / ST7565_BLOCK_COUNT) +#endif + +#define ST7565_ALL_BLOCKS_MASK (((((ST7565_BLOCK_TYPE)1 << (ST7565_BLOCK_COUNT - 1)) - 1) << 1) | 1) + +#define HAS_FLAGS(bits, flags) ((bits & flags) == flags) + +// Display buffer's is the same as the display memory layout +// this is so we don't end up with rounding errors with +// parts of the display unusable or don't get cleared correctly +// and also allows for drawing & inverting +uint8_t st7565_buffer[ST7565_MATRIX_SIZE]; +uint8_t * st7565_cursor; +ST7565_BLOCK_TYPE st7565_dirty = 0; +bool st7565_initialized = false; +bool st7565_active = false; +display_rotation_t st7565_rotation = DISPLAY_ROTATION_0; +#if ST7565_TIMEOUT > 0 +uint32_t st7565_timeout; +#endif +#if ST7565_UPDATE_INTERVAL > 0 +uint16_t st7565_update_timeout; +#endif + +// Flips the rendering bits for a character at the current cursor position +static void InvertCharacter(uint8_t *cursor) { + const uint8_t *end = cursor + ST7565_FONT_WIDTH; + while (cursor < end) { + *cursor = ~(*cursor); + cursor++; + } +} + +bool st7565_init(display_rotation_t rotation) { + setPinOutput(ST7565_A0_PIN); + writePinHigh(ST7565_A0_PIN); + setPinOutput(ST7565_RST_PIN); + writePinHigh(ST7565_RST_PIN); + + st7565_rotation = st7565_init_user(rotation); + + spi_init(); + spi_start(ST7565_SS_PIN, false, 0, ST7565_SPI_CLK_DIVISOR); + + st7565_reset(); + + st7565_send_cmd(LCD_BIAS_7); + if (!HAS_FLAGS(st7565_rotation, DISPLAY_ROTATION_180)) { + st7565_send_cmd(SEGMENT_REMAP); + st7565_send_cmd(COM_SCAN_DEC); + } else { + st7565_send_cmd(SEGMENT_REMAP_INV); + st7565_send_cmd(COM_SCAN_INC); + } + st7565_send_cmd(DISPLAY_START_LINE | 0x00); + st7565_send_cmd(CONTRAST); + st7565_send_cmd(ST7565_CONTRAST); + st7565_send_cmd(RESISTOR_RATIO | 0x01); + st7565_send_cmd(POWER_CONTROL | 0x04); + wait_ms(50); + st7565_send_cmd(POWER_CONTROL | 0x06); + wait_ms(50); + st7565_send_cmd(POWER_CONTROL | 0x07); + wait_ms(10); + st7565_send_cmd(DISPLAY_ON); + st7565_send_cmd(DISPLAY_ALL_ON_RESUME); + st7565_send_cmd(NORMAL_DISPLAY); + + spi_stop(); + +#if ST7565_TIMEOUT > 0 + st7565_timeout = timer_read32() + ST7565_TIMEOUT; +#endif + + st7565_clear(); + st7565_initialized = true; + st7565_active = true; + return true; +} + +__attribute__((weak)) display_rotation_t st7565_init_user(display_rotation_t rotation) { return rotation; } + +void st7565_clear(void) { + memset(st7565_buffer, 0, sizeof(st7565_buffer)); + st7565_cursor = &st7565_buffer[0]; + st7565_dirty = ST7565_ALL_BLOCKS_MASK; +} + +uint8_t crot(uint8_t a, int8_t n) { + const uint8_t mask = 0x7; + n &= mask; + return a << n | a >> (-n & mask); +} + +void st7565_render(void) { + if (!st7565_initialized) { + return; + } + + // Do we have work to do? + st7565_dirty &= ST7565_ALL_BLOCKS_MASK; + if (!st7565_dirty) { + return; + } + + // Find first dirty block + uint8_t update_start = 0; + while (!(st7565_dirty & ((ST7565_BLOCK_TYPE)1 << update_start))) { + ++update_start; + } + + // Calculate commands to set memory addressing bounds. + uint8_t start_page = ST7565_BLOCK_SIZE * update_start / ST7565_DISPLAY_WIDTH; + uint8_t start_column = ST7565_BLOCK_SIZE * update_start % ST7565_DISPLAY_WIDTH; + // IC has 132 segment drivers, for panels with less width we need to offset the starting column + if (HAS_FLAGS(st7565_rotation, DISPLAY_ROTATION_180)) { + start_column += (132 - ST7565_DISPLAY_WIDTH); + } + + spi_start(ST7565_SS_PIN, false, 0, ST7565_SPI_CLK_DIVISOR); + + st7565_send_cmd(PAM_PAGE_ADDR | start_page); + st7565_send_cmd(PAM_SETCOLUMN_LSB | ((ST7565_COLUMN_OFFSET + start_column) & 0x0f)); + st7565_send_cmd(PAM_SETCOLUMN_MSB | ((ST7565_COLUMN_OFFSET + start_column) >> 4 & 0x0f)); + + st7565_send_data(&st7565_buffer[ST7565_BLOCK_SIZE * update_start], ST7565_BLOCK_SIZE); + + // Turn on display if it is off + st7565_on(); + + // Clear dirty flag + st7565_dirty &= ~((ST7565_BLOCK_TYPE)1 << update_start); +} + +void st7565_set_cursor(uint8_t col, uint8_t line) { + uint16_t index = line * ST7565_DISPLAY_WIDTH + col * ST7565_FONT_WIDTH; + + // Out of bounds? + if (index >= ST7565_MATRIX_SIZE) { + index = 0; + } + + st7565_cursor = &st7565_buffer[index]; +} + +void st7565_advance_page(bool clearPageRemainder) { + uint16_t index = st7565_cursor - &st7565_buffer[0]; + uint8_t remaining = ST7565_DISPLAY_WIDTH - (index % ST7565_DISPLAY_WIDTH); + + if (clearPageRemainder) { + // Remaining Char count + remaining = remaining / ST7565_FONT_WIDTH; + + // Write empty character until next line + while (remaining--) st7565_write_char(' ', false); + } else { + // Next page index out of bounds? + if (index + remaining >= ST7565_MATRIX_SIZE) { + index = 0; + remaining = 0; + } + + st7565_cursor = &st7565_buffer[index + remaining]; + } +} + +void st7565_advance_char(void) { + uint16_t nextIndex = st7565_cursor - &st7565_buffer[0] + ST7565_FONT_WIDTH; + uint8_t remainingSpace = ST7565_DISPLAY_WIDTH - (nextIndex % ST7565_DISPLAY_WIDTH); + + // Do we have enough space on the current line for the next character + if (remainingSpace < ST7565_FONT_WIDTH) { + nextIndex += remainingSpace; + } + + // Did we go out of bounds + if (nextIndex >= ST7565_MATRIX_SIZE) { + nextIndex = 0; + } + + // Update cursor position + st7565_cursor = &st7565_buffer[nextIndex]; +} + +// Main handler that writes character data to the display buffer +void st7565_write_char(const char data, bool invert) { + // Advance to the next line if newline + if (data == '\n') { + // Old source wrote ' ' until end of line... + st7565_advance_page(true); + return; + } + + if (data == '\r') { + st7565_advance_page(false); + return; + } + + // copy the current render buffer to check for dirty after + static uint8_t st7565_temp_buffer[ST7565_FONT_WIDTH]; + memcpy(&st7565_temp_buffer, st7565_cursor, ST7565_FONT_WIDTH); + + _Static_assert(sizeof(font) >= ((ST7565_FONT_END + 1 - ST7565_FONT_START) * ST7565_FONT_WIDTH), "ST7565_FONT_END references outside array"); + + // set the reder buffer data + uint8_t cast_data = (uint8_t)data; // font based on unsigned type for index + if (cast_data < ST7565_FONT_START || cast_data > ST7565_FONT_END) { + memset(st7565_cursor, 0x00, ST7565_FONT_WIDTH); + } else { + const uint8_t *glyph = &font[(cast_data - ST7565_FONT_START) * ST7565_FONT_WIDTH]; + memcpy_P(st7565_cursor, glyph, ST7565_FONT_WIDTH); + } + + // Invert if needed + if (invert) { + InvertCharacter(st7565_cursor); + } + + // Dirty check + if (memcmp(&st7565_temp_buffer, st7565_cursor, ST7565_FONT_WIDTH)) { + uint16_t index = st7565_cursor - &st7565_buffer[0]; + st7565_dirty |= ((ST7565_BLOCK_TYPE)1 << (index / ST7565_BLOCK_SIZE)); + // Edgecase check if the written data spans the 2 chunks + st7565_dirty |= ((ST7565_BLOCK_TYPE)1 << ((index + ST7565_FONT_WIDTH - 1) / ST7565_BLOCK_SIZE)); + } + + // Finally move to the next char + st7565_advance_char(); +} + +void st7565_write(const char *data, bool invert) { + const char *end = data + strlen(data); + while (data < end) { + st7565_write_char(*data, invert); + data++; + } +} + +void st7565_write_ln(const char *data, bool invert) { + st7565_write(data, invert); + st7565_advance_page(true); +} + +void st7565_pan(bool left) { + uint16_t i = 0; + for (uint16_t y = 0; y < ST7565_DISPLAY_HEIGHT / 8; y++) { + if (left) { + for (uint16_t x = 0; x < ST7565_DISPLAY_WIDTH - 1; x++) { + i = y * ST7565_DISPLAY_WIDTH + x; + st7565_buffer[i] = st7565_buffer[i + 1]; + } + } else { + for (uint16_t x = ST7565_DISPLAY_WIDTH - 1; x > 0; x--) { + i = y * ST7565_DISPLAY_WIDTH + x; + st7565_buffer[i] = st7565_buffer[i - 1]; + } + } + } + st7565_dirty = ST7565_ALL_BLOCKS_MASK; +} + +display_buffer_reader_t st7565_read_raw(uint16_t start_index) { + if (start_index > ST7565_MATRIX_SIZE) start_index = ST7565_MATRIX_SIZE; + display_buffer_reader_t ret_reader; + ret_reader.current_element = &st7565_buffer[start_index]; + ret_reader.remaining_element_count = ST7565_MATRIX_SIZE - start_index; + return ret_reader; +} + +void st7565_write_raw_byte(const char data, uint16_t index) { + if (index > ST7565_MATRIX_SIZE) index = ST7565_MATRIX_SIZE; + if (st7565_buffer[index] == data) return; + st7565_buffer[index] = data; + st7565_dirty |= ((ST7565_BLOCK_TYPE)1 << (index / ST7565_BLOCK_SIZE)); +} + +void st7565_write_raw(const char *data, uint16_t size) { + uint16_t cursor_start_index = st7565_cursor - &st7565_buffer[0]; + if ((size + cursor_start_index) > ST7565_MATRIX_SIZE) size = ST7565_MATRIX_SIZE - cursor_start_index; + for (uint16_t i = cursor_start_index; i < cursor_start_index + size; i++) { + if (st7565_buffer[i] == data[i]) continue; + st7565_buffer[i] = data[i]; + st7565_dirty |= ((ST7565_BLOCK_TYPE)1 << (i / ST7565_BLOCK_SIZE)); + } +} + +void st7565_write_pixel(uint8_t x, uint8_t y, bool on) { + if (x >= ST7565_DISPLAY_WIDTH) { + return; + } + uint16_t index = x + (y / 8) * ST7565_DISPLAY_WIDTH; + if (index >= ST7565_MATRIX_SIZE) { + return; + } + uint8_t data = st7565_buffer[index]; + if (on) { + data |= (1 << (y % 8)); + } else { + data &= ~(1 << (y % 8)); + } + if (st7565_buffer[index] != data) { + st7565_buffer[index] = data; + st7565_dirty |= ((ST7565_BLOCK_TYPE)1 << (index / ST7565_BLOCK_SIZE)); + } +} + +#if defined(__AVR__) +void st7565_write_P(const char *data, bool invert) { + uint8_t c = pgm_read_byte(data); + while (c != 0) { + st7565_write_char(c, invert); + c = pgm_read_byte(++data); + } +} + +void st7565_write_ln_P(const char *data, bool invert) { + st7565_write_P(data, invert); + st7565_advance_page(true); +} + +void st7565_write_raw_P(const char *data, uint16_t size) { + uint16_t cursor_start_index = st7565_cursor - &st7565_buffer[0]; + if ((size + cursor_start_index) > ST7565_MATRIX_SIZE) size = ST7565_MATRIX_SIZE - cursor_start_index; + for (uint16_t i = cursor_start_index; i < cursor_start_index + size; i++) { + uint8_t c = pgm_read_byte(data++); + if (st7565_buffer[i] == c) continue; + st7565_buffer[i] = c; + st7565_dirty |= ((ST7565_BLOCK_TYPE)1 << (i / ST7565_BLOCK_SIZE)); + } +} +#endif // defined(__AVR__) + +bool st7565_on(void) { + if (!st7565_initialized) { + return st7565_active; + } + +#if ST7565_TIMEOUT > 0 + st7565_timeout = timer_read32() + ST7565_TIMEOUT; +#endif + + if (!st7565_active) { + spi_start(ST7565_SS_PIN, false, 0, ST7565_SPI_CLK_DIVISOR); + st7565_send_cmd(DISPLAY_ON); + spi_stop(); + st7565_active = true; + st7565_on_user(); + } + return st7565_active; +} + +__attribute__((weak)) void st7565_on_user(void) {} + +bool st7565_off(void) { + if (!st7565_initialized) { + return !st7565_active; + } + + if (st7565_active) { + spi_start(ST7565_SS_PIN, false, 0, ST7565_SPI_CLK_DIVISOR); + st7565_send_cmd(DISPLAY_OFF); + spi_stop(); + st7565_active = false; + st7565_off_user(); + } + return !st7565_active; +} + +__attribute__((weak)) void st7565_off_user(void) {} + +bool st7565_is_on(void) { return st7565_active; } + +uint8_t st7565_max_chars(void) { return ST7565_DISPLAY_WIDTH / ST7565_FONT_WIDTH; } + +uint8_t st7565_max_lines(void) { return ST7565_DISPLAY_HEIGHT / ST7565_FONT_HEIGHT; } + +void st7565_task(void) { + if (!st7565_initialized) { + return; + } + +#if ST7565_UPDATE_INTERVAL > 0 + if (timer_elapsed(st7565_update_timeout) >= ST7565_UPDATE_INTERVAL) { + st7565_update_timeout = timer_read(); + st7565_set_cursor(0, 0); + st7565_task_user(); + } +#else + st7565_set_cursor(0, 0); + st7565_task_user(); +#endif + + // Smart render system, no need to check for dirty + st7565_render(); + + // Display timeout check +#if ST7565_TIMEOUT > 0 + if (st7565_active && timer_expired32(timer_read32(), st7565_timeout)) { + st7565_off(); + } +#endif +} + +__attribute__((weak)) void st7565_task_user(void) {} + +void st7565_reset(void) { + writePinLow(ST7565_RST_PIN); + wait_ms(20); + writePinHigh(ST7565_RST_PIN); + wait_ms(20); +} + +spi_status_t st7565_send_cmd(uint8_t cmd) { + writePinLow(ST7565_A0_PIN); + return spi_write(cmd); +} + +spi_status_t st7565_send_data(uint8_t *data, uint16_t length) { + writePinHigh(ST7565_A0_PIN); + return spi_transmit(data, length); +} diff --git a/drivers/lcd/st7565.h b/drivers/lcd/st7565.h new file mode 100644 index 0000000000..53cfc9a810 --- /dev/null +++ b/drivers/lcd/st7565.h @@ -0,0 +1,215 @@ +/* +Copyright 2021 + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#pragma once + +#include +#include + +#include "spi_master.h" + +#ifndef ST7565_DISPLAY_WIDTH +# define ST7565_DISPLAY_WIDTH 128 +#endif +#ifndef ST7565_DISPLAY_HEIGHT +# define ST7565_DISPLAY_HEIGHT 32 +#endif +#ifndef ST7565_MATRIX_SIZE +# define ST7565_MATRIX_SIZE (ST7565_DISPLAY_HEIGHT / 8 * ST7565_DISPLAY_WIDTH) // 1024 (compile time mathed) +#endif +#ifndef ST7565_BLOCK_TYPE +# define ST7565_BLOCK_TYPE uint16_t +#endif +#ifndef ST7565_BLOCK_COUNT +# define ST7565_BLOCK_COUNT (sizeof(ST7565_BLOCK_TYPE) * 8) // 32 (compile time mathed) +#endif +#ifndef ST7565_BLOCK_SIZE +# define ST7565_BLOCK_SIZE (ST7565_MATRIX_SIZE / ST7565_BLOCK_COUNT) // 32 (compile time mathed) +#endif + +// the column address corresponding to the first column in the display hardware +#if !defined(ST7565_COLUMN_OFFSET) +# define ST7565_COLUMN_OFFSET 0 +#endif + +// spi clock divisor +#if !defined(ST7565_SPI_CLK_DIVISOR) +# define ST7565_SPI_CLK_DIVISOR 4 +#endif + +// Custom font file to use +#if !defined(ST7565_FONT_H) +# define ST7565_FONT_H "glcdfont.c" +#endif +// unsigned char value of the first character in the font file +#if !defined(ST7565_FONT_START) +# define ST7565_FONT_START 0 +#endif +// unsigned char value of the last character in the font file +#if !defined(ST7565_FONT_END) +# define ST7565_FONT_END 223 +#endif +// Font render width +#if !defined(ST7565_FONT_WIDTH) +# define ST7565_FONT_WIDTH 6 +#endif +// Font render height +#if !defined(ST7565_FONT_HEIGHT) +# define ST7565_FONT_HEIGHT 8 +#endif +// Default contrast level +#if !defined(ST7565_CONTRAST) +# define ST7565_CONTRAST 32 +#endif + +#if !defined(ST7565_TIMEOUT) +# if defined(ST7565_DISABLE_TIMEOUT) +# define ST7565_TIMEOUT 0 +# else +# define ST7565_TIMEOUT 60000 +# endif +#endif + +#if !defined(ST7565_UPDATE_INTERVAL) && defined(SPLIT_KEYBOARD) +# define ST7565_UPDATE_INTERVAL 50 +#endif + +typedef struct __attribute__((__packed__)) { + uint8_t *current_element; + uint16_t remaining_element_count; +} display_buffer_reader_t; + +// Rotation enum values are flags +typedef enum { DISPLAY_ROTATION_0, DISPLAY_ROTATION_180 } display_rotation_t; + +// Initialize the display, rotating the rendered output based on the define passed in. +// Returns true if the display was initialized successfully +bool st7565_init(display_rotation_t rotation); + +// Called at the start of st7565_init, weak function overridable by the user +// rotation - the value passed into st7565_init +// Return new display_rotation_t if you want to override default rotation +display_rotation_t st7565_init_user(display_rotation_t rotation); + +// Clears the display buffer, resets cursor position to 0, and sets the buffer to dirty for rendering +void st7565_clear(void); + +// Renders the dirty chunks of the buffer to display +void st7565_render(void); + +// Moves cursor to character position indicated by column and line, wraps if out of bounds +// Max column denoted by 'st7565_max_chars()' and max lines by 'st7565_max_lines()' functions +void st7565_set_cursor(uint8_t col, uint8_t line); + +// Advances the cursor to the next page, writing ' ' if true +// Wraps to the begining when out of bounds +void st7565_advance_page(bool clearPageRemainder); + +// Moves the cursor forward 1 character length +// Advance page if there is not enough room for the next character +// Wraps to the begining when out of bounds +void st7565_advance_char(void); + +// Writes a single character to the buffer at current cursor position +// Advances the cursor while writing, inverts the pixels if true +// Main handler that writes character data to the display buffer +void st7565_write_char(const char data, bool invert); + +// Writes a string to the buffer at current cursor position +// Advances the cursor while writing, inverts the pixels if true +void st7565_write(const char *data, bool invert); + +// Writes a string to the buffer at current cursor position +// Advances the cursor while writing, inverts the pixels if true +// Advances the cursor to the next page, wiring ' ' to the remainder of the current page +void st7565_write_ln(const char *data, bool invert); + +// Pans the buffer to the right (or left by passing true) by moving contents of the buffer +// Useful for moving the screen in preparation for new drawing +void st7565_pan(bool left); + +// Returns a pointer to the requested start index in the buffer plus remaining +// buffer length as struct +display_buffer_reader_t st7565_read_raw(uint16_t start_index); + +// Writes a string to the buffer at current cursor position +void st7565_write_raw(const char *data, uint16_t size); + +// Writes a single byte into the buffer at the specified index +void st7565_write_raw_byte(const char data, uint16_t index); + +// Sets a specific pixel on or off +// Coordinates start at top-left and go right and down for positive x and y +void st7565_write_pixel(uint8_t x, uint8_t y, bool on); + +#if defined(__AVR__) +// Writes a PROGMEM string to the buffer at current cursor position +// Advances the cursor while writing, inverts the pixels if true +// Remapped to call 'void st7565_write(const char *data, bool invert);' on ARM +void st7565_write_P(const char *data, bool invert); + +// Writes a PROGMEM string to the buffer at current cursor position +// Advances the cursor while writing, inverts the pixels if true +// Advances the cursor to the next page, wiring ' ' to the remainder of the current page +// Remapped to call 'void st7565_write_ln(const char *data, bool invert);' on ARM +void st7565_write_ln_P(const char *data, bool invert); + +// Writes a PROGMEM string to the buffer at current cursor position +void st7565_write_raw_P(const char *data, uint16_t size); +#else +# define st7565_write_P(data, invert) st7565_write(data, invert) +# define st7565_write_ln_P(data, invert) st7565_write_ln(data, invert) +# define st7565_write_raw_P(data, size) st7565_write_raw(data, size) +#endif // defined(__AVR__) + +// Can be used to manually turn on the screen if it is off +// Returns true if the screen was on or turns on +bool st7565_on(void); + +// Called when st7565_on() turns on the screen, weak function overridable by the user +// Not called if the screen is already on +void st7565_on_user(void); + +// Can be used to manually turn off the screen if it is on +// Returns true if the screen was off or turns off +bool st7565_off(void); + +// Called when st7565_off() turns off the screen, weak function overridable by the user +// Not called if the screen is already off +void st7565_off_user(void); + +// Returns true if the screen is currently on, false if it is +// not +bool st7565_is_on(void); + +// Basically it's st7565_render, but with timeout management and st7565_task_user calling! +void st7565_task(void); + +// Called at the start of st7565_task, weak function overridable by the user +void st7565_task_user(void); + +// Returns the maximum number of characters that will fit on a line +uint8_t st7565_max_chars(void); + +// Returns the maximum number of lines that will fit on the display +uint8_t st7565_max_lines(void); + +void st7565_reset(void); + +spi_status_t st7565_send_cmd(uint8_t cmd); + +spi_status_t st7565_send_data(uint8_t *data, uint16_t length); diff --git a/quantum/quantum.h b/quantum/quantum.h index e4a7c5723c..66ba96fde8 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h @@ -176,6 +176,10 @@ extern layer_state_t layer_state; # include "oled_driver.h" #endif +#ifdef ST7565_ENABLE +# include "st7565.h" +#endif + #ifdef DIP_SWITCH_ENABLE # include "dip_switch.h" #endif diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c index 3d6092e71c..249da85bd2 100644 --- a/tmk_core/common/keyboard.c +++ b/tmk_core/common/keyboard.c @@ -85,6 +85,9 @@ along with this program. If not, see . #ifdef OLED_DRIVER_ENABLE # include "oled_driver.h" #endif +#ifdef ST7565_ENABLE +# include "st7565.h" +#endif #ifdef VELOCIKEY_ENABLE # include "velocikey.h" #endif @@ -306,6 +309,9 @@ void keyboard_init(void) { #ifdef OLED_DRIVER_ENABLE oled_init(OLED_ROTATION_0); #endif +#ifdef ST7565_ENABLE + st7565_init(DISPLAY_ROTATION_0); +#endif #ifdef PS2_MOUSE_ENABLE ps2_mouse_init(); #endif @@ -470,6 +476,18 @@ MATRIX_LOOP_END: # endif #endif +#ifdef ST7565_ENABLE + st7565_task(); +# ifndef ST7565_DISABLE_TIMEOUT + // Wake up display if user is using those fabulous keys or spinning those encoders! +# ifdef ENCODER_ENABLE + if (matrix_changed || encoders_changed) st7565_on(); +# else + if (matrix_changed) st7565_on(); +# endif +# endif +#endif + #ifdef MOUSEKEY_ENABLE // mousekey repeat & acceleration mousekey_task(); -- cgit v1.2.3 From e2c58934052e2ca93a92cd97ef8b9c0425fa3cf6 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Wed, 16 Jun 2021 06:53:27 +0200 Subject: core: make RESET key work with Teensy 4.x (#13076) related to https://github.com/kinx-project/kint/issues/5--- tmk_core/common/chibios/bootloader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tmk_core') diff --git a/tmk_core/common/chibios/bootloader.c b/tmk_core/common/chibios/bootloader.c index 11f7abf432..76d52ea608 100644 --- a/tmk_core/common/chibios/bootloader.c +++ b/tmk_core/common/chibios/bootloader.c @@ -95,7 +95,7 @@ void enter_bootloader_mode_if_requested(void) { } } -#elif defined(KL2x) || defined(K20x) || defined(MK66F18) // STM32_BOOTLOADER_DUAL_BANK // STM32_BOOTLOADER_ADDRESS +#elif defined(KL2x) || defined(K20x) || defined(MK66F18) || defined(MIMXRT1062) // STM32_BOOTLOADER_DUAL_BANK // STM32_BOOTLOADER_ADDRESS /* Kinetis */ # if defined(BOOTLOADER_KIIBOHD) -- cgit v1.2.3 From 9956ff4e031b33c5e1fe1ff6ee44885f1080d966 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Wed, 16 Jun 2021 20:15:45 +0200 Subject: core: wire up flash make target for Teensy 4.x (#13077) related to https://github.com/kinx-project/kint/issues/5--- platforms/chibios/IC_TEENSY_4_1/board/board.mk | 1 + platforms/chibios/IC_TEENSY_4_1/rules.mk | 1 + tmk_core/chibios.mk | 6 +++++- 3 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 platforms/chibios/IC_TEENSY_4_1/board/board.mk create mode 100644 platforms/chibios/IC_TEENSY_4_1/rules.mk (limited to 'tmk_core') diff --git a/platforms/chibios/IC_TEENSY_4_1/board/board.mk b/platforms/chibios/IC_TEENSY_4_1/board/board.mk new file mode 100644 index 0000000000..bc242ac3c5 --- /dev/null +++ b/platforms/chibios/IC_TEENSY_4_1/board/board.mk @@ -0,0 +1 @@ +include $(CHIBIOS_CONTRIB)/os/hal/boards/PJRC_TEENSY_4_1/board.mk diff --git a/platforms/chibios/IC_TEENSY_4_1/rules.mk b/platforms/chibios/IC_TEENSY_4_1/rules.mk new file mode 100644 index 0000000000..0c62d209c5 --- /dev/null +++ b/platforms/chibios/IC_TEENSY_4_1/rules.mk @@ -0,0 +1 @@ +TEENSY_LOADER_CLI_MCU = imxrt1062 diff --git a/tmk_core/chibios.mk b/tmk_core/chibios.mk index 97299b7d32..7eda360460 100644 --- a/tmk_core/chibios.mk +++ b/tmk_core/chibios.mk @@ -390,8 +390,10 @@ ifndef TEENSY_LOADER_CLI endif endif +TEENSY_LOADER_CLI_MCU ?= $(MCU_LDSCRIPT) + define EXEC_TEENSY - $(TEENSY_LOADER_CLI) -mmcu=$(MCU_LDSCRIPT) -w -v $(BUILD_DIR)/$(TARGET).hex + $(TEENSY_LOADER_CLI) -mmcu=$(TEENSY_LOADER_CLI_MCU) -w -v $(BUILD_DIR)/$(TARGET).hex endef teensy: $(BUILD_DIR)/$(TARGET).hex cpfirmware sizeafter @@ -408,6 +410,8 @@ else ifeq ($(strip $(BOOTLOADER)),kiibohd) $(call EXEC_DFU_UTIL) else ifeq ($(strip $(MCU_FAMILY)),KINETIS) $(call EXEC_TEENSY) +else ifeq ($(strip $(MCU_FAMILY)),MIMXRT1062) + $(call EXEC_TEENSY) else ifeq ($(strip $(MCU_FAMILY)),STM32) $(call EXEC_DFU_UTIL) else -- cgit v1.2.3 From ef92c9ee2cf4745637635ec1895399e4f013914c Mon Sep 17 00:00:00 2001 From: Stefan Kerkmann Date: Fri, 18 Jun 2021 01:09:43 +0200 Subject: Add CRC8 calculation subsystem to quantum (#12641) * Intended usage is data validation in split transport code. * Default space efficient algorithm. * Opt-in fast table based algorithmn with #define CRC8_USE_TABLE switch. * Define switches for size and speed optimized versions, the default is size optimized by using uint_least8_t as datatype for calculations. * #define CRC8_OPTIMIZE_SPEED uses uint_fast8_t as datatype for calculations, this only affects 32-bit Archs like ARM and RISC-V. * Placeholder crc_init() function for hardware backed crc calculation, not implemented yet.--- common_features.mk | 6 +++++ quantum/crc.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++ quantum/crc.h | 44 ++++++++++++++++++++++++++++++++++ tmk_core/common/keyboard.c | 6 +++++ 4 files changed, 115 insertions(+) create mode 100644 quantum/crc.c create mode 100644 quantum/crc.h (limited to 'tmk_core') diff --git a/common_features.mk b/common_features.mk index b259af46c0..1a079a8df2 100644 --- a/common_features.mk +++ b/common_features.mk @@ -530,6 +530,7 @@ endif ifeq ($(strip $(SPLIT_KEYBOARD)), yes) POST_CONFIG_H += $(QUANTUM_DIR)/split_common/post_config.h OPT_DEFS += -DSPLIT_KEYBOARD + CRC_ENABLE := yes # Include files used by all split keyboards QUANTUM_SRC += $(QUANTUM_DIR)/split_common/split_util.c @@ -557,6 +558,11 @@ ifeq ($(strip $(SPLIT_KEYBOARD)), yes) COMMON_VPATH += $(QUANTUM_PATH)/split_common endif +ifeq ($(strip $(CRC_ENABLE)), yes) + OPT_DEFS += -DCRC_ENABLE + QUANTUM_LIB_SRC += crc.c +endif + HAPTIC_ENABLE ?= no ifneq ($(strip $(HAPTIC_ENABLE)),no) COMMON_VPATH += $(DRIVER_PATH)/haptic diff --git a/quantum/crc.c b/quantum/crc.c new file mode 100644 index 0000000000..0d8b9d6017 --- /dev/null +++ b/quantum/crc.c @@ -0,0 +1,59 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "crc.h" + +__attribute__((weak)) void crc_init(void){ + /* Software implementation nothing todo here. */ +}; + +#if defined(CRC8_USE_TABLE) +/** + * Static table used for the table_driven implementation. + */ +static const crc_t crc_table[256] = {0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d, 0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65, 0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d, 0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5, 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd, 0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, 0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd, 0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2, 0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea, 0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2, 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a, 0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32, 0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a, 0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42, 0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a, + 0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c, 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4, 0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec, 0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4, 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c, 0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44, 0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c, 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34, 0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, 0x76, 0x71, 0x78, 0x7f, 0x6a, 0x6d, 0x64, 0x63, 0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b, 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13, 0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb, 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83, 0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3}; + +__attribute__((weak)) uint8_t crc8(const void *data, size_t data_len) { + const uint8_t *d = (const uint8_t *)data; + crc_t crc = 0xff; + size_t tbl_idx; + + while (data_len--) { + tbl_idx = crc ^ *d; + crc = crc_table[tbl_idx] & 0xff; + d++; + } + return crc & 0xff; +} +#else +__attribute__((weak)) uint8_t crc8(const void *data, size_t data_len) { + const uint8_t *d = (const uint8_t *)data; + crc_t crc = 0xff; + size_t i, j; + + for (i = 0; i < data_len; i++) { + crc ^= d[i]; + for (j = 0; j < 8; j++) { + if ((crc & 0x80) != 0) + crc = (crc_t)((crc << 1) ^ 0x31); + else + crc <<= 1; + } + } + return crc; +} +#endif \ No newline at end of file diff --git a/quantum/crc.h b/quantum/crc.h new file mode 100644 index 0000000000..c17f5888e2 --- /dev/null +++ b/quantum/crc.h @@ -0,0 +1,44 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "quantum.h" + +/** + * The type of the CRC values. + * + * This type must be big enough to contain at least 8 bits. + */ +#if defined(CRC8_OPTIMIZE_SPEED) +typedef uint_fast8_t crc_t; +#else +typedef uint_least8_t crc_t; +#endif + +/** + * Initialize crc subsystem. + */ +__attribute__((weak)) void crc_init(void); + +/** + * Generate CRC8 value from given data. + * + * \param[in] data Pointer to a buffer of \a data_len bytes. + * \param[in] data_len Number of bytes in the \a data buffer. + * \return The calculated crc value. + */ +__attribute__((weak)) uint8_t crc8(const void *data, size_t data_len); \ No newline at end of file diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c index 249da85bd2..28fa97bc8f 100644 --- a/tmk_core/common/keyboard.c +++ b/tmk_core/common/keyboard.c @@ -103,6 +103,9 @@ along with this program. If not, see . #ifdef EEPROM_DRIVER # include "eeprom_driver.h" #endif +#if defined(CRC_ENABLE) +# include "crc.h" +#endif static uint32_t last_input_modification_time = 0; uint32_t last_input_activity_time(void) { return last_input_modification_time; } @@ -300,6 +303,9 @@ void keyboard_init(void) { timer_init(); sync_timer_init(); matrix_init(); +#if defined(CRC_ENABLE) + crc_init(); +#endif #ifdef VIA_ENABLE via_init(); #endif -- cgit v1.2.3 From 172e6a703041363decd6fc829542f33180c13beb Mon Sep 17 00:00:00 2001 From: Nick Brassel Date: Fri, 18 Jun 2021 09:10:06 +1000 Subject: Extensible split data sync (#11930) * Extensible split data sync capability through transactions. - Split common transport has been split up between the transport layer and data layer. - Split "transactions" model used, with convergence between I2C and serial data definitions. - Slave matrix "generation count" is used to determine if the full slave matrix needs to be retrieved. - Encoders get the same "generation count" treatment. - All other blocks of data are synchronised when a change is detected. - All transmissions have a globally-configurable deadline before a transmission is forced (`FORCED_SYNC_THROTTLE_MS`, default 100ms). - Added atomicity for all core-synced data, preventing partial updates - Added retries to AVR i2c_master's i2c_start, to minimise the number of failed transactions when interrupts are disabled on the slave due to atomicity checks. - Some keyboards have had slight modifications made in order to ensure that they still build due to firmware size restrictions. * Fixup LED_MATRIX compile. * Parameterise ERROR_DISCONNECT_COUNT.--- common_features.mk | 6 +- docs/config_options.md | 26 +- docs/feature_split_keyboard.md | 114 ++++- drivers/avr/i2c_master.c | 19 +- drivers/avr/i2c_slave.c | 29 +- drivers/avr/i2c_slave.h | 13 +- drivers/avr/serial.c | 82 +--- drivers/avr/serial.h | 62 --- drivers/chibios/serial.c | 52 +- drivers/chibios/serial.h | 62 --- drivers/chibios/serial_usart.c | 47 +- drivers/serial.h | 46 ++ keyboards/draculad/config.h | 2 + keyboards/handwired/freoduo/rules.mk | 4 +- keyboards/helix/rev2/keymaps/default/rules.mk | 2 +- keyboards/keebio/iris/rev2/rules.mk | 2 + keyboards/keebio/iris/rev3/rules.mk | 1 + keyboards/keebio/iris/rev4/rules.mk | 2 + keyboards/keebio/quefrency/rules.mk | 1 + keyboards/keebio/viterbi/rev2/rules.mk | 2 + keyboards/keebio/viterbi/rules.mk | 8 +- quantum/split_common/matrix.c | 6 +- quantum/split_common/post_config.h | 9 - quantum/split_common/transaction_id_define.h | 94 ++++ quantum/split_common/transactions.c | 670 ++++++++++++++++++++++++++ quantum/split_common/transactions.h | 54 +++ quantum/split_common/transport.c | 484 +++---------------- quantum/split_common/transport.h | 165 +++++++ tmk_core/common/host.c | 14 +- 29 files changed, 1387 insertions(+), 691 deletions(-) delete mode 100644 drivers/avr/serial.h delete mode 100644 drivers/chibios/serial.h create mode 100644 drivers/serial.h create mode 100644 quantum/split_common/transaction_id_define.h create mode 100644 quantum/split_common/transactions.c create mode 100644 quantum/split_common/transactions.h (limited to 'tmk_core') diff --git a/common_features.mk b/common_features.mk index 1a079a8df2..15637d7608 100644 --- a/common_features.mk +++ b/common_features.mk @@ -537,7 +537,11 @@ ifeq ($(strip $(SPLIT_KEYBOARD)), yes) # Determine which (if any) transport files are required ifneq ($(strip $(SPLIT_TRANSPORT)), custom) - QUANTUM_LIB_SRC += $(QUANTUM_DIR)/split_common/transport.c + QUANTUM_SRC += $(QUANTUM_DIR)/split_common/transport.c \ + $(QUANTUM_DIR)/split_common/transactions.c + + OPT_DEFS += -DSPLIT_COMMON_TRANSACTIONS + # Functions added via QUANTUM_LIB_SRC are only included in the final binary if they're called. # Unused functions are pruned away, which is why we can add multiple drivers here without bloat. ifeq ($(PLATFORM),AVR) diff --git a/docs/config_options.md b/docs/config_options.md index 26fe8cea55..980195ac68 100644 --- a/docs/config_options.md +++ b/docs/config_options.md @@ -274,7 +274,7 @@ There are a few different ways to set handedness for split keyboards (listed in ### Other Options * `#define USE_I2C` - * For using I2C instead of Serial (defaults to serial) + * For using I2C instead of Serial (default is serial; serial transport is supported on ARM -- I2C is AVR-only) * `#define SOFT_SERIAL_PIN D0` * When using serial, define this. `D0` or `D1`,`D2`,`D3`,`E6`. @@ -303,7 +303,7 @@ There are a few different ways to set handedness for split keyboards (listed in * `#define SPLIT_USB_DETECT` * Detect (with timeout) USB connection when delegating master/slave * Default behavior for ARM - * Required for AVR Teensy + * Required for AVR Teensy (without hardware mods) * `#define SPLIT_USB_TIMEOUT 2000` * Maximum timeout when detecting master/slave when using `SPLIT_USB_DETECT` @@ -311,6 +311,28 @@ There are a few different ways to set handedness for split keyboards (listed in * `#define SPLIT_USB_TIMEOUT_POLL 10` * Poll frequency when detecting master/slave when using `SPLIT_USB_DETECT` +* `#define FORCED_SYNC_THROTTLE_MS 100` + * Deadline for synchronizing data from master to slave when using the QMK-provided split transport. + +* `#define SPLIT_TRANSPORT_MIRROR` + * Mirrors the master-side matrix on the slave when using the QMK-provided split transport. + +* `#define SPLIT_LAYER_STATE_ENABLE` + * Ensures the current layer state is available on the slave when using the QMK-provided split transport. + +* `#define SPLIT_LED_STATE_ENABLE` + * Ensures the current host indicator state (caps/num/scroll) is available on the slave when using the QMK-provided split transport. + +* `#define SPLIT_MODS_ENABLE` + * Ensures the current modifier state (normal, weak, and oneshot) is available on the slave when using the QMK-provided split transport. + +* `#define SPLIT_WPM_ENABLE` + * Ensures the current WPM is available on the slave when using the QMK-provided split transport. + +* `#define SPLIT_TRANSACTION_IDS_KB .....` +* `#define SPLIT_TRANSACTION_IDS_USER .....` + * Allows for custom data sync with the slave when using the QMK-provided split transport. See [custom data sync between sides](feature_split_keyboard.md#custom-data-sync) for more information. + # The `rules.mk` File This is a [make](https://www.gnu.org/software/make/manual/make.html) file that is included by the top-level `Makefile`. It is used to set some information about the MCU that we will be compiling for as well as enabling and disabling certain features. diff --git a/docs/feature_split_keyboard.md b/docs/feature_split_keyboard.md index 4ebf585f5c..603c387c2d 100644 --- a/docs/feature_split_keyboard.md +++ b/docs/feature_split_keyboard.md @@ -8,8 +8,7 @@ QMK Firmware has a generic implementation that is usable by any board, as well a For this, we will mostly be talking about the generic implementation used by the Let's Split and other keyboards. -!> ARM is not yet fully supported for Split Keyboards and has many limitations. Progress is being made, but we have not yet reached 100% feature parity. - +!> ARM split supports most QMK subsystems when using the 'serial' and 'serial_usart' drivers. I2C slave is currently unsupported. ## Compatibility Overview @@ -169,7 +168,7 @@ Because not every split keyboard is identical, there are a number of additional #define USE_I2C ``` -This enables I2C support for split keyboards. This isn't strictly for communication, but can be used for OLED or other I2C-based devices. +This configures the use of I2C support for split keyboard transport (AVR only). ```c #define SOFT_SERIAL_PIN D0 @@ -193,20 +192,115 @@ If you're having issues with serial communication, you can change this value, as * **`5`**: about 20kbps ```c -#define SPLIT_MODS_ENABLE +#define FORCED_SYNC_THROTTLE_MS 100 ``` -This enables transmitting modifier state (normal, weak and oneshot) to the non -primary side of the split keyboard. This adds a few bytes of data to the split -communication protocol and may impact the matrix scan speed when enabled. -The purpose of this feature is to support cosmetic use of modifer state (e.g. -displaying status on an OLED screen). +This sets the maximum number of milliseconds before forcing a synchronization of data from master to slave. Under normal circumstances this sync occurs whenever the data _changes_, for safety a data transfer occurs after this number of milliseconds if no change has been detected since the last sync. ```c #define SPLIT_TRANSPORT_MIRROR ``` -This mirrors the master side matrix to the slave side for features that react or require knowledge of master side key presses on the slave side. This adds a few bytes of data to the split communication protocol and may impact the matrix scan speed when enabled. The purpose of this feature is to support cosmetic use of key events (e.g. RGB reacting to Keypresses). +This mirrors the master side matrix to the slave side for features that react or require knowledge of master side key presses on the slave side. The purpose of this feature is to support cosmetic use of key events (e.g. RGB reacting to keypresses). This adds overhead to the split communication protocol and may negatively impact the matrix scan speed when enabled. + +```c +#define SPLIT_LAYER_STATE_ENABLE +``` + +This enables syncing of the layer state between both halves of the split keyboard. The main purpose of this feature is to enable support for use of things like OLED display of the currently active layer. This adds overhead to the split communication protocol and may negatively impact the matrix scan speed when enabled. + +```c +#define SPLIT_LED_STATE_ENABLE +``` + +This enables syncing of the Host LED status (caps lock, num lock, etc) between both halves of the split keyboard. The main purpose of this feature is to enable support for use of things like OLED display of the Host LED status. This adds overhead to the split communication protocol and may negatively impact the matrix scan speed when enabled. + +```c +#define SPLIT_MODS_ENABLE +``` + +This enables transmitting modifier state (normal, weak and oneshot) to the non primary side of the split keyboard. The purpose of this feature is to support cosmetic use of modifer state (e.g. displaying status on an OLED screen). This adds overhead to the split communication protocol and may negatively impact the matrix scan speed when enabled. + +```c +#define SPLIT_WPM_ENABLE +``` + +This enables transmitting the current WPM to the slave side of the split keyboard. The purpose of this feature is to support cosmetic use of WPM (e.g. displaying the current value on an OLED screen). This adds overhead to the split communication protocol and may negatively impact the matrix scan speed when enabled. + +### Custom data sync between sides :id=custom-data-sync + +QMK's split transport allows for arbitrary data transactions at both the keyboard and user levels. This is modelled on a remote procedure call, with the master invoking a function on the slave side, with the ability to send data from master to slave, process it slave side, and send data back from slave to master. + +To leverage this, a keyboard or user/keymap can define a comma-separated list of _transaction IDs_: + +```c +// for keyboard-level data sync: +#define SPLIT_TRANSACTION_IDS_KB KEYBOARD_SYNC_A, KEYBOARD_SYNC_B +// or, for user: +#define SPLIT_TRANSACTION_IDS_USER USER_SYNC_A, USER_SYNC_B, USER_SYNC_C +``` + +These _transaction IDs_ then need a slave-side handler function to be registered with the split transport, for example: + +```c +typedef struct _master_to_slave_t { + int m2s_data; +} master_to_slave_t; + +typedef struct _slave_to_master_t { + int s2m_data; +} slave_to_master_t; + +void user_sync_a_slave_handler(uint8_t in_buflen, const void* in_data, uint8_t out_buflen, void* out_data) { + const master_to_slave_t *m2s = (const master_to_slave_t*)in_data; + slave_to_master_t *s2m = (slave_to_master_t*)out_data; + s2m->s2m_data = m2s->m2s_data + 5; // whatever comes in, add 5 so it can be sent back +} + +void keyboard_post_init_user(void) { + transaction_register_rpc(USER_SYNC_A, user_sync_a_slave_handler); +} +``` + +The master side can then invoke the slave-side handler - for normal keyboard functionality to be minimally affected, any keyboard- or user-level code attempting to sync data should be throttled: + +```c +void housekeeping_task_user(void) { + if (is_keyboard_master()) { + // Interact with slave every 500ms + static uint32_t last_sync = 0; + if (timer_elapsed32(last_sync) > 500) { + master_to_slave_t m2s = {6}; + slave_to_master_t s2m = {0}; + if(transaction_rpc_exec(USER_SYNC_A, sizeof(m2s), &m2s, sizeof(s2m), &s2m)) { + last_sync = timer_read32(); + dprintf("Slave value: %d\n", s2m.s2m_data); // this will now be 11, as the slave adds 5 + } else { + dprint("Slave sync failed!\n"); + } + } + } +} +``` + +!> It is recommended that any data sync between halves happens during the master side's _housekeeping task_. This ensures timely retries should failures occur. + +If only one-way data transfer is needed, helper methods are provided: + +```c +bool transaction_rpc_exec(int8_t transaction_id, uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer); +bool transaction_rpc_send(int8_t transaction_id, uint8_t initiator2target_buffer_size, const void *initiator2target_buffer); +bool transaction_rpc_recv(int8_t transaction_id, uint8_t target2initiator_buffer_size, void *target2initiator_buffer); +``` + +By default, the inbound and outbound data is limited to a maximum of 32 bytes each. The sizes can be altered if required: + +```c +// Master to slave: +#define RPC_M2S_BUFFER_SIZE 48 +// Slave to master: +#define RPC_S2M_BUFFER_SIZE 48 +``` ### Hardware Configuration Options diff --git a/drivers/avr/i2c_master.c b/drivers/avr/i2c_master.c index b1e4885298..2773e00778 100644 --- a/drivers/avr/i2c_master.c +++ b/drivers/avr/i2c_master.c @@ -28,8 +28,14 @@ # define F_SCL 400000UL // SCL frequency #endif +#ifndef I2C_START_RETRY_COUNT +# define I2C_START_RETRY_COUNT 20 +#endif // I2C_START_RETRY_COUNT + #define TWBR_val (((F_CPU / F_SCL) - 16) / 2) +#define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) + void i2c_init(void) { TWSR = 0; /* no prescaler */ TWBR = (uint8_t)TWBR_val; @@ -47,7 +53,7 @@ void i2c_init(void) { #endif } -i2c_status_t i2c_start(uint8_t address, uint16_t timeout) { +static i2c_status_t i2c_start_impl(uint8_t address, uint16_t timeout) { // reset TWI control register TWCR = 0; // transmit START condition @@ -86,6 +92,17 @@ i2c_status_t i2c_start(uint8_t address, uint16_t timeout) { return I2C_STATUS_SUCCESS; } +i2c_status_t i2c_start(uint8_t address, uint16_t timeout) { + // Retry i2c_start_impl a bunch times in case the remote side has interrupts disabled. + uint16_t timeout_timer = timer_read(); + uint16_t time_slice = MAX(1, (timeout == (I2C_TIMEOUT_INFINITE)) ? 5 : (timeout / (I2C_START_RETRY_COUNT))); // if it's infinite, wait 1ms between attempts, otherwise split up the entire timeout into the number of retries + i2c_status_t status; + do { + status = i2c_start_impl(address, time_slice); + } while ((status < 0) && ((timeout == I2C_TIMEOUT_INFINITE) || (timer_elapsed(timeout_timer) < timeout))); + return status; +} + i2c_status_t i2c_write(uint8_t data, uint16_t timeout) { // load data into data register TWDR = data; diff --git a/drivers/avr/i2c_slave.c b/drivers/avr/i2c_slave.c index 62a378165a..2907f164c0 100644 --- a/drivers/avr/i2c_slave.c +++ b/drivers/avr/i2c_slave.c @@ -17,6 +17,7 @@ * GitHub repository: https://github.com/g4lvanix/I2C-slave-lib */ +#include #include #include #include @@ -24,6 +25,12 @@ #include "i2c_slave.h" +#if defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS) +# include "transactions.h" + +static volatile bool is_callback_executor = false; +#endif // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS) + volatile uint8_t i2c_slave_reg[I2C_SLAVE_REG_COUNT]; static volatile uint8_t buffer_address; @@ -48,11 +55,14 @@ ISR(TWI_vect) { case TW_SR_SLA_ACK: // The device is now a slave receiver slave_has_register_set = false; +#if defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS) + is_callback_executor = false; +#endif // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS) break; case TW_SR_DATA_ACK: // This device is a slave receiver and has received data - // First byte is the location then the bytes will be writen in buffer with auto-incriment + // First byte is the location then the bytes will be writen in buffer with auto-increment if (!slave_has_register_set) { buffer_address = TWDR; @@ -60,10 +70,25 @@ ISR(TWI_vect) { ack = 0; buffer_address = 0; } - slave_has_register_set = true; // address has been receaved now fill in buffer + slave_has_register_set = true; // address has been received now fill in buffer + +#if defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS) + // Work out if we're attempting to execute a callback + is_callback_executor = buffer_address == split_transaction_table[I2C_EXECUTE_CALLBACK].initiator2target_offset; +#endif // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS) } else { i2c_slave_reg[buffer_address] = TWDR; buffer_address++; + +#if defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS) + // If we're intending to execute a transaction callback, do so, as we've just received the transaction ID + if (is_callback_executor) { + split_transaction_desc_t *trans = &split_transaction_table[split_shmem->transaction_id]; + if (trans->slave_callback) { + trans->slave_callback(trans->initiator2target_buffer_size, split_trans_initiator2target_buffer(trans), trans->target2initiator_buffer_size, split_trans_target2initiator_buffer(trans)); + } + } +#endif // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS) } break; diff --git a/drivers/avr/i2c_slave.h b/drivers/avr/i2c_slave.h index 1cd0625ef4..a8647c9da3 100644 --- a/drivers/avr/i2c_slave.h +++ b/drivers/avr/i2c_slave.h @@ -22,7 +22,18 @@ #pragma once -#define I2C_SLAVE_REG_COUNT 30 +#ifndef I2C_SLAVE_REG_COUNT + +# if defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS) +# include "transport.h" +# define I2C_SLAVE_REG_COUNT sizeof(split_shared_memory_t) +# else // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS) +# define I2C_SLAVE_REG_COUNT 30 +# endif // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS) + +#endif // I2C_SLAVE_REG_COUNT + +_Static_assert(I2C_SLAVE_REG_COUNT < 256, "I2C target registers must be single byte"); extern volatile uint8_t i2c_slave_reg[I2C_SLAVE_REG_COUNT]; diff --git a/drivers/avr/serial.c b/drivers/avr/serial.c index 3647bee0d3..9a7345a53d 100644 --- a/drivers/avr/serial.c +++ b/drivers/avr/serial.c @@ -224,15 +224,8 @@ # define SERIAL_DELAY_HALF2 (SERIAL_DELAY - SERIAL_DELAY / 2) # define SLAVE_INT_WIDTH_US 1 -# ifndef SERIAL_USE_MULTI_TRANSACTION -# define SLAVE_INT_RESPONSE_TIME SERIAL_DELAY -# else -# define SLAVE_INT_ACK_WIDTH_UNIT 2 -# define SLAVE_INT_ACK_WIDTH 4 -# endif - -static SSTD_t *Transaction_table = NULL; -static uint8_t Transaction_table_size = 0; +# define SLAVE_INT_ACK_WIDTH_UNIT 2 +# define SLAVE_INT_ACK_WIDTH 4 inline static void serial_delay(void) ALWAYS_INLINE; inline static void serial_delay(void) { _delay_us(SERIAL_DELAY); } @@ -259,16 +252,12 @@ inline static void serial_low(void) { writePinLow(SOFT_SERIAL_PIN); } inline static void serial_high(void) ALWAYS_INLINE; inline static void serial_high(void) { writePinHigh(SOFT_SERIAL_PIN); } -void soft_serial_initiator_init(SSTD_t *sstd_table, int sstd_table_size) { - Transaction_table = sstd_table; - Transaction_table_size = (uint8_t)sstd_table_size; +void soft_serial_initiator_init(void) { serial_output(); serial_high(); } -void soft_serial_target_init(SSTD_t *sstd_table, int sstd_table_size) { - Transaction_table = sstd_table; - Transaction_table_size = (uint8_t)sstd_table_size; +void soft_serial_target_init(void) { serial_input_with_pullup(); // Enable INT0-INT7 @@ -395,19 +384,14 @@ static inline uint8_t nibble_bits_count(uint8_t bits) { // interrupt handle to be used by the target device ISR(SERIAL_PIN_INTERRUPT) { -# ifndef SERIAL_USE_MULTI_TRANSACTION - serial_low(); - serial_output(); - SSTD_t *trans = Transaction_table; -# else // recive transaction table index uint8_t tid, bits; uint8_t pecount = 0; sync_recv(); - bits = serial_read_chunk(&pecount, 7); + bits = serial_read_chunk(&pecount, 8); tid = bits >> 3; - bits = (bits & 7) != nibble_bits_count(tid); - if (bits || pecount > 0 || tid > Transaction_table_size) { + bits = (bits & 7) != (nibble_bits_count(tid) & 7); + if (bits || pecount > 0 || tid > NUM_TOTAL_TRANSACTIONS) { return; } serial_delay_half1(); @@ -415,18 +399,22 @@ ISR(SERIAL_PIN_INTERRUPT) { serial_high(); // response step1 low->high serial_output(); _delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT * SLAVE_INT_ACK_WIDTH); - SSTD_t *trans = &Transaction_table[tid]; + split_transaction_desc_t *trans = &split_transaction_table[tid]; serial_low(); // response step2 ack high->low -# endif + + // If the transaction has a callback, we can execute it now + if (trans->slave_callback) { + trans->slave_callback(trans->initiator2target_buffer_size, split_trans_initiator2target_buffer(trans), trans->target2initiator_buffer_size, split_trans_target2initiator_buffer(trans)); + } // target send phase - if (trans->target2initiator_buffer_size > 0) serial_send_packet((uint8_t *)trans->target2initiator_buffer, trans->target2initiator_buffer_size); + if (trans->target2initiator_buffer_size > 0) serial_send_packet((uint8_t *)split_trans_target2initiator_buffer(trans), trans->target2initiator_buffer_size); // target switch to input change_sender2reciver(); // target recive phase if (trans->initiator2target_buffer_size > 0) { - if (serial_recive_packet((uint8_t *)trans->initiator2target_buffer, trans->initiator2target_buffer_size)) { + if (serial_recive_packet((uint8_t *)split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size)) { *trans->status = TRANSACTION_ACCEPTED; } else { *trans->status = TRANSACTION_DATA_ERROR; @@ -448,14 +436,12 @@ ISR(SERIAL_PIN_INTERRUPT) { // TRANSACTION_NO_RESPONSE // TRANSACTION_DATA_ERROR // this code is very time dependent, so we need to disable interrupts -# ifndef SERIAL_USE_MULTI_TRANSACTION -int soft_serial_transaction(void) { - SSTD_t *trans = Transaction_table; -# else int soft_serial_transaction(int sstd_index) { - if (sstd_index > Transaction_table_size) return TRANSACTION_TYPE_ERROR; - SSTD_t *trans = &Transaction_table[sstd_index]; -# endif + if (sstd_index > NUM_TOTAL_TRANSACTIONS) return TRANSACTION_TYPE_ERROR; + split_transaction_desc_t *trans = &split_transaction_table[sstd_index]; + + if (!trans->status) return TRANSACTION_TYPE_ERROR; // not registered + cli(); // signal to the target that we want to start a transaction @@ -463,27 +449,11 @@ int soft_serial_transaction(int sstd_index) { serial_low(); _delay_us(SLAVE_INT_WIDTH_US); -# ifndef SERIAL_USE_MULTI_TRANSACTION - // wait for the target response - serial_input_with_pullup(); - _delay_us(SLAVE_INT_RESPONSE_TIME); - - // check if the target is present - if (serial_read_pin()) { - // target failed to pull the line low, assume not present - serial_output(); - serial_high(); - *trans->status = TRANSACTION_NO_RESPONSE; - sei(); - return TRANSACTION_NO_RESPONSE; - } - -# else // send transaction table index int tid = (sstd_index << 3) | (7 & nibble_bits_count(sstd_index)); sync_send(); _delay_sub_us(TID_SEND_ADJUST); - serial_write_chunk(tid, 7); + serial_write_chunk(tid, 8); serial_delay_half1(); // wait for the target response (step1 low->high) @@ -504,12 +474,11 @@ int soft_serial_transaction(int sstd_index) { } _delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT); } -# endif // initiator recive phase // if the target is present syncronize with it if (trans->target2initiator_buffer_size > 0) { - if (!serial_recive_packet((uint8_t *)trans->target2initiator_buffer, trans->target2initiator_buffer_size)) { + if (!serial_recive_packet((uint8_t *)split_trans_target2initiator_buffer(trans), trans->target2initiator_buffer_size)) { serial_output(); serial_high(); *trans->status = TRANSACTION_DATA_ERROR; @@ -523,7 +492,7 @@ int soft_serial_transaction(int sstd_index) { // initiator send phase if (trans->initiator2target_buffer_size > 0) { - serial_send_packet((uint8_t *)trans->initiator2target_buffer, trans->initiator2target_buffer_size); + serial_send_packet((uint8_t *)split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size); } // always, release the line when not in use @@ -534,9 +503,8 @@ int soft_serial_transaction(int sstd_index) { return TRANSACTION_END; } -# ifdef SERIAL_USE_MULTI_TRANSACTION int soft_serial_get_and_clean_status(int sstd_index) { - SSTD_t *trans = &Transaction_table[sstd_index]; + split_transaction_desc_t *trans = &split_transaction_table[sstd_index]; cli(); int retval = *trans->status; *trans->status = 0; @@ -544,8 +512,6 @@ int soft_serial_get_and_clean_status(int sstd_index) { sei(); return retval; } -# endif - #endif // Helix serial.c history diff --git a/drivers/avr/serial.h b/drivers/avr/serial.h deleted file mode 100644 index 53e66cf905..0000000000 --- a/drivers/avr/serial.h +++ /dev/null @@ -1,62 +0,0 @@ -#pragma once - -#include - -// ///////////////////////////////////////////////////////////////// -// Need Soft Serial defines in config.h -// ///////////////////////////////////////////////////////////////// -// ex. -// #define SOFT_SERIAL_PIN ?? // ?? = D0,D1,D2,D3,E6 -// OPTIONAL: #define SELECT_SOFT_SERIAL_SPEED ? // ? = 1,2,3,4,5 -// // 1: about 137kbps (default) -// // 2: about 75kbps -// // 3: about 39kbps -// // 4: about 26kbps -// // 5: about 20kbps -// -// //// USE simple API (using signle-type transaction function) -// /* nothing */ -// //// USE flexible API (using multi-type transaction function) -// #define SERIAL_USE_MULTI_TRANSACTION -// -// ///////////////////////////////////////////////////////////////// - -// Soft Serial Transaction Descriptor -typedef struct _SSTD_t { - uint8_t *status; - uint8_t initiator2target_buffer_size; - uint8_t *initiator2target_buffer; - uint8_t target2initiator_buffer_size; - uint8_t *target2initiator_buffer; -} SSTD_t; -#define TID_LIMIT(table) (sizeof(table) / sizeof(SSTD_t)) - -// initiator is transaction start side -void soft_serial_initiator_init(SSTD_t *sstd_table, int sstd_table_size); -// target is interrupt accept side -void soft_serial_target_init(SSTD_t *sstd_table, int sstd_table_size); - -// initiator resullt -#define TRANSACTION_END 0 -#define TRANSACTION_NO_RESPONSE 0x1 -#define TRANSACTION_DATA_ERROR 0x2 -#define TRANSACTION_TYPE_ERROR 0x4 -#ifndef SERIAL_USE_MULTI_TRANSACTION -int soft_serial_transaction(void); -#else -int soft_serial_transaction(int sstd_index); -#endif - -// target status -// *SSTD_t.status has -// initiator: -// TRANSACTION_END -// or TRANSACTION_NO_RESPONSE -// or TRANSACTION_DATA_ERROR -// target: -// TRANSACTION_DATA_ERROR -// or TRANSACTION_ACCEPTED -#define TRANSACTION_ACCEPTED 0x8 -#ifdef SERIAL_USE_MULTI_TRANSACTION -int soft_serial_get_and_clean_status(int sstd_index); -#endif diff --git a/drivers/chibios/serial.c b/drivers/chibios/serial.c index 54f7e1321f..f54fbcee4e 100644 --- a/drivers/chibios/serial.c +++ b/drivers/chibios/serial.c @@ -74,21 +74,12 @@ static THD_FUNCTION(Thread1, arg) { } } -static SSTD_t *Transaction_table = NULL; -static uint8_t Transaction_table_size = 0; - -void soft_serial_initiator_init(SSTD_t *sstd_table, int sstd_table_size) { - Transaction_table = sstd_table; - Transaction_table_size = (uint8_t)sstd_table_size; - +void soft_serial_initiator_init(void) { serial_output(); serial_high(); } -void soft_serial_target_init(SSTD_t *sstd_table, int sstd_table_size) { - Transaction_table = sstd_table; - Transaction_table_size = (uint8_t)sstd_table_size; - +void soft_serial_target_init(void) { serial_input(); palEnablePadEvent(PAL_PORT(SOFT_SERIAL_PIN), PAL_PAD(SOFT_SERIAL_PIN), PAL_EVENT_MODE_FALLING_EDGE); @@ -154,16 +145,14 @@ void interrupt_handler(void *arg) { uint8_t checksum_computed = 0; int sstd_index = 0; -#ifdef SERIAL_USE_MULTI_TRANSACTION sstd_index = serial_read_byte(); sync_send(); -#endif - SSTD_t *trans = &Transaction_table[sstd_index]; + split_transaction_desc_t *trans = &split_transaction_table[sstd_index]; for (int i = 0; i < trans->initiator2target_buffer_size; ++i) { - trans->initiator2target_buffer[i] = serial_read_byte(); + split_trans_initiator2target_buffer(trans)[i] = serial_read_byte(); sync_send(); - checksum_computed += trans->initiator2target_buffer[i]; + checksum_computed += split_trans_initiator2target_buffer(trans)[i]; } checksum_computed ^= 7; uint8_t checksum_received = serial_read_byte(); @@ -172,12 +161,17 @@ void interrupt_handler(void *arg) { // wait for the sync to finish sending serial_delay(); + // Allow any slave processing to occur + if (trans->slave_callback) { + trans->slave_callback(trans->initiator2target_buffer_size, split_trans_initiator2target_buffer(trans), trans->target2initiator_buffer_size, split_trans_target2initiator_buffer(trans)); + } + uint8_t checksum = 0; for (int i = 0; i < trans->target2initiator_buffer_size; ++i) { - serial_write_byte(trans->target2initiator_buffer[i]); + serial_write_byte(split_trans_target2initiator_buffer(trans)[i]); sync_send(); serial_delay_half(); - checksum += trans->target2initiator_buffer[i]; + checksum += split_trans_target2initiator_buffer(trans)[i]; } serial_write_byte(checksum ^ 7); sync_send(); @@ -206,15 +200,10 @@ void interrupt_handler(void *arg) { // TRANSACTION_NO_RESPONSE // TRANSACTION_DATA_ERROR // this code is very time dependent, so we need to disable interrupts -#ifndef SERIAL_USE_MULTI_TRANSACTION -int soft_serial_transaction(void) { - int sstd_index = 0; -#else int soft_serial_transaction(int sstd_index) { -#endif - - if (sstd_index > Transaction_table_size) return TRANSACTION_TYPE_ERROR; - SSTD_t *trans = &Transaction_table[sstd_index]; + if (sstd_index > NUM_TOTAL_TRANSACTIONS) return TRANSACTION_TYPE_ERROR; + split_transaction_desc_t *trans = &split_transaction_table[sstd_index]; + if (!trans->status) return TRANSACTION_TYPE_ERROR; // not registered // TODO: remove extra delay between transactions serial_delay(); @@ -244,14 +233,13 @@ int soft_serial_transaction(int sstd_index) { uint8_t checksum = 0; // send data to the slave -#ifdef SERIAL_USE_MULTI_TRANSACTION serial_write_byte(sstd_index); // first chunk is transaction id sync_recv(); -#endif + for (int i = 0; i < trans->initiator2target_buffer_size; ++i) { - serial_write_byte(trans->initiator2target_buffer[i]); + serial_write_byte(split_trans_initiator2target_buffer(trans)[i]); sync_recv(); - checksum += trans->initiator2target_buffer[i]; + checksum += split_trans_initiator2target_buffer(trans)[i]; } serial_write_byte(checksum ^ 7); sync_recv(); @@ -262,9 +250,9 @@ int soft_serial_transaction(int sstd_index) { // receive data from the slave uint8_t checksum_computed = 0; for (int i = 0; i < trans->target2initiator_buffer_size; ++i) { - trans->target2initiator_buffer[i] = serial_read_byte(); + split_trans_target2initiator_buffer(trans)[i] = serial_read_byte(); sync_recv(); - checksum_computed += trans->target2initiator_buffer[i]; + checksum_computed += split_trans_target2initiator_buffer(trans)[i]; } checksum_computed ^= 7; uint8_t checksum_received = serial_read_byte(); diff --git a/drivers/chibios/serial.h b/drivers/chibios/serial.h deleted file mode 100644 index 0c1857d52e..0000000000 --- a/drivers/chibios/serial.h +++ /dev/null @@ -1,62 +0,0 @@ -#pragma once - -#include - -// ///////////////////////////////////////////////////////////////// -// Need Soft Serial defines in config.h -// ///////////////////////////////////////////////////////////////// -// ex. -// #define SOFT_SERIAL_PIN ?? // ?? = D0,D1,D2,D3,E6 -// OPTIONAL: #define SELECT_SOFT_SERIAL_SPEED ? // ? = 1,2,3,4,5 -// // 1: about 137kbps (default) -// // 2: about 75kbps -// // 3: about 39kbps -// // 4: about 26kbps -// // 5: about 20kbps -// -// //// USE simple API (using signle-type transaction function) -// /* nothing */ -// //// USE flexible API (using multi-type transaction function) -// #define SERIAL_USE_MULTI_TRANSACTION -// -// ///////////////////////////////////////////////////////////////// - -// Soft Serial Transaction Descriptor -typedef struct _SSTD_t { - uint8_t *status; - uint8_t initiator2target_buffer_size; - uint8_t *initiator2target_buffer; - uint8_t target2initiator_buffer_size; - uint8_t *target2initiator_buffer; -} SSTD_t; -#define TID_LIMIT(table) (sizeof(table) / sizeof(SSTD_t)) - -// initiator is transaction start side -void soft_serial_initiator_init(SSTD_t *sstd_table, int sstd_table_size); -// target is interrupt accept side -void soft_serial_target_init(SSTD_t *sstd_table, int sstd_table_size); - -// initiator result -#define TRANSACTION_END 0 -#define TRANSACTION_NO_RESPONSE 0x1 -#define TRANSACTION_DATA_ERROR 0x2 -#define TRANSACTION_TYPE_ERROR 0x4 -#ifndef SERIAL_USE_MULTI_TRANSACTION -int soft_serial_transaction(void); -#else -int soft_serial_transaction(int sstd_index); -#endif - -// target status -// *SSTD_t.status has -// initiator: -// TRANSACTION_END -// or TRANSACTION_NO_RESPONSE -// or TRANSACTION_DATA_ERROR -// target: -// TRANSACTION_DATA_ERROR -// or TRANSACTION_ACCEPTED -#define TRANSACTION_ACCEPTED 0x8 -#ifdef SERIAL_USE_MULTI_TRANSACTION -int soft_serial_get_and_clean_status(int sstd_index); -#endif diff --git a/drivers/chibios/serial_usart.c b/drivers/chibios/serial_usart.c index cae29388c3..9f180d2d74 100644 --- a/drivers/chibios/serial_usart.c +++ b/drivers/chibios/serial_usart.c @@ -113,37 +113,29 @@ void usart_slave_init(void) { chThdCreateStatic(waSlaveThread, sizeof(waSlaveThread), HIGHPRIO, SlaveThread, NULL); } -static SSTD_t* Transaction_table = NULL; -static uint8_t Transaction_table_size = 0; +void soft_serial_initiator_init(void) { usart_master_init(); } -void soft_serial_initiator_init(SSTD_t* sstd_table, int sstd_table_size) { - Transaction_table = sstd_table; - Transaction_table_size = (uint8_t)sstd_table_size; - - usart_master_init(); -} - -void soft_serial_target_init(SSTD_t* sstd_table, int sstd_table_size) { - Transaction_table = sstd_table; - Transaction_table_size = (uint8_t)sstd_table_size; - - usart_slave_init(); -} +void soft_serial_target_init(void) { usart_slave_init(); } void handle_soft_serial_slave(void) { - uint8_t sstd_index = sdGet(&SERIAL_USART_DRIVER); // first chunk is always transaction id - SSTD_t* trans = &Transaction_table[sstd_index]; + uint8_t sstd_index = sdGet(&SERIAL_USART_DRIVER); // first chunk is always transaction id + split_transaction_desc_t* trans = &split_transaction_table[sstd_index]; // Always write back the sstd_index as part of a basic handshake sstd_index ^= HANDSHAKE_MAGIC; sdWrite(&SERIAL_USART_DRIVER, &sstd_index, sizeof(sstd_index)); if (trans->initiator2target_buffer_size) { - sdRead(&SERIAL_USART_DRIVER, trans->initiator2target_buffer, trans->initiator2target_buffer_size); + sdRead(&SERIAL_USART_DRIVER, split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size); + } + + // Allow any slave processing to occur + if (trans->slave_callback) { + trans->slave_callback(trans->initiator2target_buffer_size, split_trans_initiator2target_buffer(trans), trans->target2initiator_buffer_size, split_trans_target2initiator_buffer(trans)); } if (trans->target2initiator_buffer_size) { - sdWrite(&SERIAL_USART_DRIVER, trans->target2initiator_buffer, trans->target2initiator_buffer_size); + sdWrite(&SERIAL_USART_DRIVER, split_trans_target2initiator_buffer(trans), trans->target2initiator_buffer_size); } if (trans->status) { @@ -160,17 +152,14 @@ void handle_soft_serial_slave(void) { // TRANSACTION_END // TRANSACTION_NO_RESPONSE // TRANSACTION_DATA_ERROR -#ifndef SERIAL_USE_MULTI_TRANSACTION -int soft_serial_transaction(void) { - uint8_t sstd_index = 0; -#else int soft_serial_transaction(int index) { uint8_t sstd_index = index; -#endif - if (sstd_index > Transaction_table_size) return TRANSACTION_TYPE_ERROR; - SSTD_t* trans = &Transaction_table[sstd_index]; - msg_t res = 0; + if (sstd_index > NUM_TOTAL_TRANSACTIONS) return TRANSACTION_TYPE_ERROR; + split_transaction_desc_t* trans = &split_transaction_table[sstd_index]; + msg_t res = 0; + + if (!trans->status) return TRANSACTION_TYPE_ERROR; // not registered sdClear(&SERIAL_USART_DRIVER); @@ -189,7 +178,7 @@ int soft_serial_transaction(int index) { } if (trans->initiator2target_buffer_size) { - res = sdWriteTimeout(&SERIAL_USART_DRIVER, trans->initiator2target_buffer, trans->initiator2target_buffer_size, TIME_MS2I(SERIAL_USART_TIMEOUT)); + res = sdWriteTimeout(&SERIAL_USART_DRIVER, split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size, TIME_MS2I(SERIAL_USART_TIMEOUT)); if (res < 0) { dprintf("serial::usart_transmit NO_RESPONSE\n"); return TRANSACTION_NO_RESPONSE; @@ -197,7 +186,7 @@ int soft_serial_transaction(int index) { } if (trans->target2initiator_buffer_size) { - res = sdReadTimeout(&SERIAL_USART_DRIVER, trans->target2initiator_buffer, trans->target2initiator_buffer_size, TIME_MS2I(SERIAL_USART_TIMEOUT)); + res = sdReadTimeout(&SERIAL_USART_DRIVER, split_trans_target2initiator_buffer(trans), trans->target2initiator_buffer_size, TIME_MS2I(SERIAL_USART_TIMEOUT)); if (res < 0) { dprintf("serial::usart_receive NO_RESPONSE\n"); return TRANSACTION_NO_RESPONSE; diff --git a/drivers/serial.h b/drivers/serial.h new file mode 100644 index 0000000000..d9c2a69e96 --- /dev/null +++ b/drivers/serial.h @@ -0,0 +1,46 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#include + +#include + +// initiator is transaction start side +void soft_serial_initiator_init(void); +// target is interrupt accept side +void soft_serial_target_init(void); + +// initiator result +#define TRANSACTION_END 0 +#define TRANSACTION_NO_RESPONSE 0x1 +#define TRANSACTION_DATA_ERROR 0x2 +#define TRANSACTION_TYPE_ERROR 0x4 +int soft_serial_transaction(int sstd_index); + +// target status +// *SSTD_t.status has +// initiator: +// TRANSACTION_END +// or TRANSACTION_NO_RESPONSE +// or TRANSACTION_DATA_ERROR +// target: +// TRANSACTION_DATA_ERROR +// or TRANSACTION_ACCEPTED +#define TRANSACTION_ACCEPTED 0x8 +int soft_serial_get_and_clean_status(int sstd_index); diff --git a/keyboards/draculad/config.h b/keyboards/draculad/config.h index 8a27fdea4d..d8a9fbd37c 100644 --- a/keyboards/draculad/config.h +++ b/keyboards/draculad/config.h @@ -65,3 +65,5 @@ along with this program. If not, see . #define UNUSED_PINS #define EE_HANDS + +#define LAYER_STATE_8BIT \ No newline at end of file diff --git a/keyboards/handwired/freoduo/rules.mk b/keyboards/handwired/freoduo/rules.mk index e3da3753e4..d8923557d6 100644 --- a/keyboards/handwired/freoduo/rules.mk +++ b/keyboards/handwired/freoduo/rules.mk @@ -11,7 +11,7 @@ BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration MOUSEKEY_ENABLE = yes # Mouse keys EXTRAKEY_ENABLE = yes # Audio control and System control CONSOLE_ENABLE = no # Console for debug -COMMAND_ENABLE = yes # Commands for debug and configuration +COMMAND_ENABLE = no # Commands for debug and configuration # Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend # if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work @@ -21,4 +21,4 @@ RGBLIGHT_ENABLE = yes # Enable keyboard RGB underglow BLUETOOTH_ENABLE = no # Enable Bluetooth AUDIO_ENABLE = no # Audio output VELOCIKEY_ENABLE = yes -SPLIT_KEYBOARD = yes \ No newline at end of file +SPLIT_KEYBOARD = yes diff --git a/keyboards/helix/rev2/keymaps/default/rules.mk b/keyboards/helix/rev2/keymaps/default/rules.mk index 206e836ec0..c16f3e2b87 100644 --- a/keyboards/helix/rev2/keymaps/default/rules.mk +++ b/keyboards/helix/rev2/keymaps/default/rules.mk @@ -5,7 +5,7 @@ # See TOP/keyboards/helix/rules.mk for a list of options that can be set. # See TOP/docs/config_options.md for more information. # -LTO_ENABLE = no # if firmware size over limit, try this option +LTO_ENABLE = yes # if firmware size over limit, try this option # Helix Spacific Build Options # you can uncomment and edit follows 7 Variables diff --git a/keyboards/keebio/iris/rev2/rules.mk b/keyboards/keebio/iris/rev2/rules.mk index 765fa7f07a..197bad4764 100644 --- a/keyboards/keebio/iris/rev2/rules.mk +++ b/keyboards/keebio/iris/rev2/rules.mk @@ -32,3 +32,5 @@ RGBLIGHT_ENABLE = yes # Enable WS2812 RGB underlight. SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend SPLIT_KEYBOARD = yes + +LTO_ENABLE = yes \ No newline at end of file diff --git a/keyboards/keebio/iris/rev3/rules.mk b/keyboards/keebio/iris/rev3/rules.mk index ea92bc98f5..b64eab5a4b 100644 --- a/keyboards/keebio/iris/rev3/rules.mk +++ b/keyboards/keebio/iris/rev3/rules.mk @@ -33,3 +33,4 @@ SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend SPLIT_KEYBOARD = yes ENCODER_ENABLE = yes +LTO_ENABLE = yes \ No newline at end of file diff --git a/keyboards/keebio/iris/rev4/rules.mk b/keyboards/keebio/iris/rev4/rules.mk index ea92bc98f5..9bf5688da0 100644 --- a/keyboards/keebio/iris/rev4/rules.mk +++ b/keyboards/keebio/iris/rev4/rules.mk @@ -33,3 +33,5 @@ SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend SPLIT_KEYBOARD = yes ENCODER_ENABLE = yes + +LTO_ENABLE = yes \ No newline at end of file diff --git a/keyboards/keebio/quefrency/rules.mk b/keyboards/keebio/quefrency/rules.mk index 2c5ad0c36b..c674e10162 100644 --- a/keyboards/keebio/quefrency/rules.mk +++ b/keyboards/keebio/quefrency/rules.mk @@ -19,3 +19,4 @@ SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend SPLIT_KEYBOARD = yes DEFAULT_FOLDER = keebio/quefrency/rev1 +LTO_ENABLE = yes diff --git a/keyboards/keebio/viterbi/rev2/rules.mk b/keyboards/keebio/viterbi/rev2/rules.mk index f95e7ae6a4..829d6a56e0 100644 --- a/keyboards/keebio/viterbi/rev2/rules.mk +++ b/keyboards/keebio/viterbi/rev2/rules.mk @@ -1,3 +1,5 @@ BACKLIGHT_ENABLE = yes LAYOUTS = ortho_5x14 + +LTO_ENABLE = yes \ No newline at end of file diff --git a/keyboards/keebio/viterbi/rules.mk b/keyboards/keebio/viterbi/rules.mk index 0b746d1720..92576d33e8 100644 --- a/keyboards/keebio/viterbi/rules.mk +++ b/keyboards/keebio/viterbi/rules.mk @@ -19,16 +19,16 @@ BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration MOUSEKEY_ENABLE = yes # Mouse keys EXTRAKEY_ENABLE = yes # Audio control and System control CONSOLE_ENABLE = no # Console for debug -COMMAND_ENABLE = yes # Commands for debug and configuration +COMMAND_ENABLE = no # Commands for debug and configuration NKRO_ENABLE = no # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work -BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality +BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality MIDI_ENABLE = no # MIDI controls AUDIO_ENABLE = no # Audio output on port C6 UNICODE_ENABLE = no # Unicode BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID -RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. +RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. # Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE -SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend +SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend SPLIT_KEYBOARD = yes diff --git a/quantum/split_common/matrix.c b/quantum/split_common/matrix.c index 2cf7b70582..56d91b07fe 100644 --- a/quantum/split_common/matrix.c +++ b/quantum/split_common/matrix.c @@ -23,9 +23,11 @@ along with this program. If not, see . #include "quantum.h" #include "split_util.h" #include "config.h" -#include "transport.h" +#include "transactions.h" -#define ERROR_DISCONNECT_COUNT 5 +#ifndef ERROR_DISCONNECT_COUNT +# define ERROR_DISCONNECT_COUNT 5 +#endif // ERROR_DISCONNECT_COUNT #define ROWS_PER_HAND (MATRIX_ROWS / 2) diff --git a/quantum/split_common/post_config.h b/quantum/split_common/post_config.h index 4ae1d52732..a4c0a1956b 100644 --- a/quantum/split_common/post_config.h +++ b/quantum/split_common/post_config.h @@ -7,13 +7,4 @@ # ifndef F_SCL # define F_SCL 100000UL // SCL frequency # endif - -#else // use serial -// When using serial, the user must define RGBLIGHT_SPLIT explicitly -// in config.h as needed. -// see quantum/rgblight_post_config.h -# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) -// When using serial and RGBLIGHT_SPLIT need separate transaction -# define SERIAL_USE_MULTI_TRANSACTION -# endif #endif diff --git a/quantum/split_common/transaction_id_define.h b/quantum/split_common/transaction_id_define.h new file mode 100644 index 0000000000..464c73478a --- /dev/null +++ b/quantum/split_common/transaction_id_define.h @@ -0,0 +1,94 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +enum serial_transaction_id { +#ifdef USE_I2C + I2C_EXECUTE_CALLBACK, +#endif // USE_I2C + + GET_SLAVE_MATRIX_CHECKSUM, + GET_SLAVE_MATRIX_DATA, + +#ifdef SPLIT_TRANSPORT_MIRROR + PUT_MASTER_MATRIX, +#endif // SPLIT_TRANSPORT_MIRROR + +#ifdef ENCODER_ENABLE + GET_ENCODERS_CHECKSUM, + GET_ENCODERS_DATA, +#endif // ENCODER_ENABLE + +#ifndef DISABLE_SYNC_TIMER + PUT_SYNC_TIMER, +#endif // DISABLE_SYNC_TIMER + +#if !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE) + PUT_LAYER_STATE, + PUT_DEFAULT_LAYER_STATE, +#endif // !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE) + +#ifdef SPLIT_LED_STATE_ENABLE + PUT_LED_STATE, +#endif // SPLIT_LED_STATE_ENABLE + +#ifdef SPLIT_MODS_ENABLE + PUT_MODS, +#endif // SPLIT_MODS_ENABLE + +#ifdef BACKLIGHT_ENABLE + PUT_BACKLIGHT, +#endif // BACKLIGHT_ENABLE + +#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) + PUT_RGBLIGHT, +#endif // defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) + +#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) + PUT_LED_MATRIX, +#endif // defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) + +#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) + PUT_RGB_MATRIX, +#endif // defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) + +#if defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE) + PUT_WPM, +#endif // defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE) + +#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) + PUT_RPC_INFO, + PUT_RPC_REQ_DATA, + EXECUTE_RPC, + GET_RPC_RESP_DATA, +#endif // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) + +// keyboard-specific +#ifdef SPLIT_TRANSACTION_IDS_KB + SPLIT_TRANSACTION_IDS_KB, +#endif // SPLIT_TRANSACTION_IDS_KB + +// user/keymap-specific +#ifdef SPLIT_TRANSACTION_IDS_USER + SPLIT_TRANSACTION_IDS_USER, +#endif // SPLIT_TRANSACTION_IDS_USER + + NUM_TOTAL_TRANSACTIONS +}; + +// Ensure we only use 5 bits for transaction +_Static_assert(NUM_TOTAL_TRANSACTIONS <= (1 << 5), "Max number of usable transactions exceeded"); diff --git a/quantum/split_common/transactions.c b/quantum/split_common/transactions.c new file mode 100644 index 0000000000..99a8623b3c --- /dev/null +++ b/quantum/split_common/transactions.c @@ -0,0 +1,670 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "debug.h" +#include "matrix.h" +#include "quantum.h" +#include "transactions.h" +#include "transport.h" +#include "transaction_id_define.h" + +#define SYNC_TIMER_OFFSET 2 + +#ifndef FORCED_SYNC_THROTTLE_MS +# define FORCED_SYNC_THROTTLE_MS 100 +#endif // FORCED_SYNC_THROTTLE_MS + +#define sizeof_member(type, member) sizeof(((type *)NULL)->member) + +#define trans_initiator2target_initializer_cb(member, cb) \ + { &dummy, sizeof_member(split_shared_memory_t, member), offsetof(split_shared_memory_t, member), 0, 0, cb } +#define trans_initiator2target_initializer(member) trans_initiator2target_initializer_cb(member, NULL) + +#define trans_target2initiator_initializer_cb(member, cb) \ + { &dummy, 0, 0, sizeof_member(split_shared_memory_t, member), offsetof(split_shared_memory_t, member), cb } +#define trans_target2initiator_initializer(member) trans_target2initiator_initializer_cb(member, NULL) + +#define transport_write(id, data, length) transport_execute_transaction(id, data, length, NULL, 0) +#define transport_read(id, data, length) transport_execute_transaction(id, NULL, 0, data, length) + +static uint8_t crc8(const void *data, size_t len) { + const uint8_t *p = (const uint8_t *)data; + uint8_t crc = 0xff; + size_t i, j; + for (i = 0; i < len; i++) { + crc ^= p[i]; + for (j = 0; j < 8; j++) { + if ((crc & 0x80) != 0) + crc = (uint8_t)((crc << 1) ^ 0x31); + else + crc <<= 1; + } + } + return crc; +} + +#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) +// Forward-declare the RPC callback handlers +void slave_rpc_info_callback(uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer); +void slave_rpc_exec_callback(uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer); +#endif // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) + +//////////////////////////////////////////////////// +// Helpers + +bool transaction_handler_master(bool okay, matrix_row_t master_matrix[], matrix_row_t slave_matrix[], const char *prefix, bool (*handler)(matrix_row_t master_matrix[], matrix_row_t slave_matrix[])) { + if (okay) { + bool this_okay = true; + for (int iter = 1; iter <= 10; ++iter) { + if (!this_okay) { + for (int i = 0; i < iter * iter; ++i) { + wait_us(10); + } + } + ATOMIC_BLOCK_FORCEON { this_okay = handler(master_matrix, slave_matrix); }; + if (this_okay) break; + } + okay &= this_okay; + if (!okay) { + dprintf("Failed to execute %s\n", prefix); + } + } + return okay; +} + +#define TRANSACTION_HANDLER_MASTER(prefix) \ + do { \ + okay &= transaction_handler_master(okay, master_matrix, slave_matrix, #prefix, &prefix##_master); \ + } while (0) + +#define TRANSACTION_HANDLER_SLAVE(prefix) \ + do { \ + ATOMIC_BLOCK_FORCEON { prefix##_slave(master_matrix, slave_matrix); }; \ + } while (0) + +inline static bool read_if_checksum_mismatch(int8_t trans_id_checksum, int8_t trans_id_retrieve, uint32_t *last_update, void *destination, const void *equiv_shmem, size_t length) { + uint8_t curr_checksum; + bool okay = transport_read(trans_id_checksum, &curr_checksum, sizeof(curr_checksum)); + if (okay && (timer_elapsed32(*last_update) >= FORCED_SYNC_THROTTLE_MS || curr_checksum != crc8(equiv_shmem, length))) { + okay &= transport_read(trans_id_retrieve, destination, length); + okay &= curr_checksum == crc8(equiv_shmem, length); + if (okay) { + *last_update = timer_read32(); + } + } else { + memcpy(destination, equiv_shmem, length); + } + return okay; +} + +inline static bool send_if_condition(int8_t trans_id, uint32_t *last_update, bool condition, void *source, size_t length) { + bool okay = true; + if (timer_elapsed32(*last_update) >= FORCED_SYNC_THROTTLE_MS || condition) { + okay &= transport_write(trans_id, source, length); + if (okay) { + *last_update = timer_read32(); + } + } + return okay; +} + +inline static bool send_if_data_mismatch(int8_t trans_id, uint32_t *last_update, void *source, const void *equiv_shmem, size_t length) { + // Just run a memcmp to compare the source and equivalent shmem location + return send_if_condition(trans_id, last_update, (memcmp(source, equiv_shmem, length) != 0), source, length); +} + +//////////////////////////////////////////////////// +// Slave matrix + +static bool slave_matrix_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { + static uint32_t last_update = 0; + static matrix_row_t last_matrix[(MATRIX_ROWS) / 2] = {0}; // last successfully-read matrix, so we can replicate if there are checksum errors + matrix_row_t temp_matrix[(MATRIX_ROWS) / 2]; // holding area while we test whether or not checksum is correct + + bool okay = read_if_checksum_mismatch(GET_SLAVE_MATRIX_CHECKSUM, GET_SLAVE_MATRIX_DATA, &last_update, temp_matrix, split_shmem->smatrix.matrix, sizeof(split_shmem->smatrix.matrix)); + if (okay) { + // Checksum matches the received data, save as the last matrix state + memcpy(last_matrix, temp_matrix, sizeof(temp_matrix)); + } + // Copy out the last-known-good matrix state to the slave matrix + memcpy(slave_matrix, last_matrix, sizeof(last_matrix)); + return okay; +} + +static void slave_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { + memcpy(split_shmem->smatrix.matrix, slave_matrix, sizeof(split_shmem->smatrix.matrix)); + split_shmem->smatrix.checksum = crc8(split_shmem->smatrix.matrix, sizeof(split_shmem->smatrix.matrix)); +} + +// clang-format off +#define TRANSACTIONS_SLAVE_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(slave_matrix_handlers) +#define TRANSACTIONS_SLAVE_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(slave_matrix_handlers) +#define TRANSACTIONS_SLAVE_MATRIX_REGISTRATIONS \ + [GET_SLAVE_MATRIX_CHECKSUM] = trans_target2initiator_initializer(smatrix.checksum), \ + [GET_SLAVE_MATRIX_DATA] = trans_target2initiator_initializer(smatrix.matrix), +// clang-format on + +//////////////////////////////////////////////////// +// Master matrix + +#ifdef SPLIT_TRANSPORT_MIRROR + +static bool master_matrix_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { + static uint32_t last_update = 0; + return send_if_data_mismatch(PUT_MASTER_MATRIX, &last_update, master_matrix, split_shmem->mmatrix.matrix, sizeof(split_shmem->mmatrix.matrix)); +} + +static void master_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { + // Always copy to the master matrix + memcpy(master_matrix, split_shmem->mmatrix.matrix, sizeof(split_shmem->mmatrix.matrix)); +} + +# define TRANSACTIONS_MASTER_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(master_matrix_handlers) +# define TRANSACTIONS_MASTER_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(master_matrix_handlers) +# define TRANSACTIONS_MASTER_MATRIX_REGISTRATIONS [PUT_MASTER_MATRIX] = trans_initiator2target_initializer(mmatrix.matrix), + +#else // SPLIT_TRANSPORT_MIRROR + +# define TRANSACTIONS_MASTER_MATRIX_MASTER() +# define TRANSACTIONS_MASTER_MATRIX_SLAVE() +# define TRANSACTIONS_MASTER_MATRIX_REGISTRATIONS + +#endif // SPLIT_TRANSPORT_MIRROR + +//////////////////////////////////////////////////// +// Encoders + +#ifdef ENCODER_ENABLE + +static bool encoder_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { + static uint32_t last_update = 0; + uint8_t temp_state[NUMBER_OF_ENCODERS]; + + bool okay = read_if_checksum_mismatch(GET_ENCODERS_CHECKSUM, GET_ENCODERS_DATA, &last_update, temp_state, split_shmem->encoders.state, sizeof(temp_state)); + if (okay) encoder_update_raw(temp_state); + return okay; +} + +static void encoder_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { + uint8_t encoder_state[NUMBER_OF_ENCODERS]; + encoder_state_raw(encoder_state); + // Always prepare the encoder state for read. + memcpy(split_shmem->encoders.state, encoder_state, sizeof(encoder_state)); + // Now update the checksum given that the encoders has been written to + split_shmem->encoders.checksum = crc8(encoder_state, sizeof(encoder_state)); +} + +// clang-format off +# define TRANSACTIONS_ENCODERS_MASTER() TRANSACTION_HANDLER_MASTER(encoder_handlers) +# define TRANSACTIONS_ENCODERS_SLAVE() TRANSACTION_HANDLER_SLAVE(encoder_handlers) +# define TRANSACTIONS_ENCODERS_REGISTRATIONS \ + [GET_ENCODERS_CHECKSUM] = trans_target2initiator_initializer(encoders.checksum), \ + [GET_ENCODERS_DATA] = trans_target2initiator_initializer(encoders.state), +// clang-format on + +#else // ENCODER_ENABLE + +# define TRANSACTIONS_ENCODERS_MASTER() +# define TRANSACTIONS_ENCODERS_SLAVE() +# define TRANSACTIONS_ENCODERS_REGISTRATIONS + +#endif // ENCODER_ENABLE + +//////////////////////////////////////////////////// +// Sync timer + +#ifndef DISABLE_SYNC_TIMER + +static bool sync_timer_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { + static uint32_t last_update = 0; + + bool okay = true; + if (timer_elapsed32(last_update) >= FORCED_SYNC_THROTTLE_MS) { + uint32_t sync_timer = sync_timer_read32() + SYNC_TIMER_OFFSET; + okay &= transport_write(PUT_SYNC_TIMER, &sync_timer, sizeof(sync_timer)); + if (okay) { + last_update = timer_read32(); + } + } + return okay; +} + +static void sync_timer_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { + static uint32_t last_sync_timer = 0; + if (last_sync_timer != split_shmem->sync_timer) { + last_sync_timer = split_shmem->sync_timer; + sync_timer_update(last_sync_timer); + } +} + +# define TRANSACTIONS_SYNC_TIMER_MASTER() TRANSACTION_HANDLER_MASTER(sync_timer_handlers) +# define TRANSACTIONS_SYNC_TIMER_SLAVE() TRANSACTION_HANDLER_SLAVE(sync_timer_handlers) +# define TRANSACTIONS_SYNC_TIMER_REGISTRATIONS [PUT_SYNC_TIMER] = trans_initiator2target_initializer(sync_timer), + +#else // DISABLE_SYNC_TIMER + +# define TRANSACTIONS_SYNC_TIMER_MASTER() +# define TRANSACTIONS_SYNC_TIMER_SLAVE() +# define TRANSACTIONS_SYNC_TIMER_REGISTRATIONS + +#endif // DISABLE_SYNC_TIMER + +//////////////////////////////////////////////////// +// Layer state + +#if !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE) + +static bool layer_state_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { + static uint32_t last_layer_state_update = 0; + static uint32_t last_default_layer_state_update = 0; + + bool okay = send_if_condition(PUT_LAYER_STATE, &last_layer_state_update, (layer_state != split_shmem->layers.layer_state), &layer_state, sizeof(layer_state)); + if (okay) { + okay &= send_if_condition(PUT_DEFAULT_LAYER_STATE, &last_default_layer_state_update, (default_layer_state != split_shmem->layers.default_layer_state), &default_layer_state, sizeof(default_layer_state)); + } + return okay; +} + +static void layer_state_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { + layer_state = split_shmem->layers.layer_state; + default_layer_state = split_shmem->layers.default_layer_state; +} + +// clang-format off +# define TRANSACTIONS_LAYER_STATE_MASTER() TRANSACTION_HANDLER_MASTER(layer_state_handlers) +# define TRANSACTIONS_LAYER_STATE_SLAVE() TRANSACTION_HANDLER_SLAVE(layer_state_handlers) +# define TRANSACTIONS_LAYER_STATE_REGISTRATIONS \ + [PUT_LAYER_STATE] = trans_initiator2target_initializer(layers.layer_state), \ + [PUT_DEFAULT_LAYER_STATE] = trans_initiator2target_initializer(layers.default_layer_state), +// clang-format on + +#else // !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE) + +# define TRANSACTIONS_LAYER_STATE_MASTER() +# define TRANSACTIONS_LAYER_STATE_SLAVE() +# define TRANSACTIONS_LAYER_STATE_REGISTRATIONS + +#endif // !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE) + +//////////////////////////////////////////////////// +// LED state + +#ifdef SPLIT_LED_STATE_ENABLE + +static bool led_state_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { + static uint32_t last_update = 0; + uint8_t led_state = host_keyboard_leds(); + return send_if_data_mismatch(PUT_LED_STATE, &last_update, &led_state, &split_shmem->led_state, sizeof(led_state)); +} + +static void led_state_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { + void set_split_host_keyboard_leds(uint8_t led_state); + set_split_host_keyboard_leds(split_shmem->led_state); +} + +# define TRANSACTIONS_LED_STATE_MASTER() TRANSACTION_HANDLER_MASTER(led_state_handlers) +# define TRANSACTIONS_LED_STATE_SLAVE() TRANSACTION_HANDLER_SLAVE(led_state_handlers) +# define TRANSACTIONS_LED_STATE_REGISTRATIONS [PUT_LED_STATE] = trans_initiator2target_initializer(led_state), + +#else // SPLIT_LED_STATE_ENABLE + +# define TRANSACTIONS_LED_STATE_MASTER() +# define TRANSACTIONS_LED_STATE_SLAVE() +# define TRANSACTIONS_LED_STATE_REGISTRATIONS + +#endif // SPLIT_LED_STATE_ENABLE + +//////////////////////////////////////////////////// +// Mods + +#ifdef SPLIT_MODS_ENABLE + +static bool mods_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { + static uint32_t last_update = 0; + bool mods_need_sync = timer_elapsed32(last_update) >= FORCED_SYNC_THROTTLE_MS; + split_mods_sync_t new_mods; + new_mods.real_mods = get_mods(); + if (!mods_need_sync && new_mods.real_mods != split_shmem->mods.real_mods) { + mods_need_sync = true; + } + + new_mods.weak_mods = get_weak_mods(); + if (!mods_need_sync && new_mods.weak_mods != split_shmem->mods.weak_mods) { + mods_need_sync = true; + } + +# ifndef NO_ACTION_ONESHOT + new_mods.oneshot_mods = get_oneshot_mods(); + if (!mods_need_sync && new_mods.oneshot_mods != split_shmem->mods.oneshot_mods) { + mods_need_sync = true; + } +# endif // NO_ACTION_ONESHOT + + bool okay = true; + if (mods_need_sync) { + okay &= transport_write(PUT_MODS, &new_mods, sizeof(new_mods)); + if (okay) { + last_update = timer_read32(); + } + } + + return okay; +} + +static void mods_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { + set_mods(split_shmem->mods.real_mods); + set_weak_mods(split_shmem->mods.weak_mods); +# ifndef NO_ACTION_ONESHOT + set_oneshot_mods(split_shmem->mods.oneshot_mods); +# endif +} + +# define TRANSACTIONS_MODS_MASTER() TRANSACTION_HANDLER_MASTER(mods_handlers) +# define TRANSACTIONS_MODS_SLAVE() TRANSACTION_HANDLER_SLAVE(mods_handlers) +# define TRANSACTIONS_MODS_REGISTRATIONS [PUT_MODS] = trans_initiator2target_initializer(mods), + +#else // SPLIT_MODS_ENABLE + +# define TRANSACTIONS_MODS_MASTER() +# define TRANSACTIONS_MODS_SLAVE() +# define TRANSACTIONS_MODS_REGISTRATIONS + +#endif // SPLIT_MODS_ENABLE + +//////////////////////////////////////////////////// +// Backlight + +#ifdef BACKLIGHT_ENABLE + +static bool backlight_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { + static uint32_t last_update = 0; + uint8_t level = is_backlight_enabled() ? get_backlight_level() : 0; + return send_if_condition(PUT_BACKLIGHT, &last_update, (level != split_shmem->backlight_level), &level, sizeof(level)); +} + +static void backlight_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { backlight_set(split_shmem->backlight_level); } + +# define TRANSACTIONS_BACKLIGHT_MASTER() TRANSACTION_HANDLER_MASTER(backlight_handlers) +# define TRANSACTIONS_BACKLIGHT_SLAVE() TRANSACTION_HANDLER_SLAVE(backlight_handlers) +# define TRANSACTIONS_BACKLIGHT_REGISTRATIONS [PUT_BACKLIGHT] = trans_initiator2target_initializer(backlight_level), + +#else // BACKLIGHT_ENABLE + +# define TRANSACTIONS_BACKLIGHT_MASTER() +# define TRANSACTIONS_BACKLIGHT_SLAVE() +# define TRANSACTIONS_BACKLIGHT_REGISTRATIONS + +#endif // BACKLIGHT_ENABLE + +//////////////////////////////////////////////////// +// RGBLIGHT + +#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) + +static bool rgblight_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { + static uint32_t last_update = 0; + rgblight_syncinfo_t rgblight_sync; + rgblight_get_syncinfo(&rgblight_sync); + if (send_if_condition(PUT_RGBLIGHT, &last_update, (rgblight_sync.status.change_flags != 0), &rgblight_sync, sizeof(rgblight_sync))) { + rgblight_clear_change_flags(); + } else { + return false; + } + return true; +} + +static void rgblight_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { + // Update the RGB with the new data + if (split_shmem->rgblight_sync.status.change_flags != 0) { + rgblight_update_sync(&split_shmem->rgblight_sync, false); + split_shmem->rgblight_sync.status.change_flags = 0; + } +} + +# define TRANSACTIONS_RGBLIGHT_MASTER() TRANSACTION_HANDLER_MASTER(rgblight_handlers) +# define TRANSACTIONS_RGBLIGHT_SLAVE() TRANSACTION_HANDLER_SLAVE(rgblight_handlers) +# define TRANSACTIONS_RGBLIGHT_REGISTRATIONS [PUT_RGBLIGHT] = trans_initiator2target_initializer(rgblight_sync), + +#else // defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) + +# define TRANSACTIONS_RGBLIGHT_MASTER() +# define TRANSACTIONS_RGBLIGHT_SLAVE() +# define TRANSACTIONS_RGBLIGHT_REGISTRATIONS + +#endif // defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) + +//////////////////////////////////////////////////// +// LED Matrix + +#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) + +static bool led_matrix_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { + static uint32_t last_update = 0; + led_matrix_sync_t led_matrix_sync; + memcpy(&led_matrix_sync.led_matrix, &led_matrix_eeconfig, sizeof(led_eeconfig_t)); + led_matrix_sync.led_suspend_state = led_matrix_get_suspend_state(); + return send_if_data_mismatch(PUT_LED_MATRIX, &last_update, &led_matrix_sync, &split_shmem->led_matrix_sync, sizeof(led_matrix_sync)); +} + +static void led_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { + memcpy(&led_matrix_eeconfig, &split_shmem->led_matrix_sync.led_matrix, sizeof(led_eeconfig_t)); + led_matrix_set_suspend_state(split_shmem->led_matrix_sync.led_suspend_state); +} + +# define TRANSACTIONS_LED_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(led_matrix_handlers) +# define TRANSACTIONS_LED_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(led_matrix_handlers) +# define TRANSACTIONS_LED_MATRIX_REGISTRATIONS [PUT_LED_MATRIX] = trans_initiator2target_initializer(led_matrix_sync), + +#else // defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) + +# define TRANSACTIONS_LED_MATRIX_MASTER() +# define TRANSACTIONS_LED_MATRIX_SLAVE() +# define TRANSACTIONS_LED_MATRIX_REGISTRATIONS + +#endif // defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) + +//////////////////////////////////////////////////// +// RGB Matrix + +#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) + +static bool rgb_matrix_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { + static uint32_t last_update = 0; + rgb_matrix_sync_t rgb_matrix_sync; + memcpy(&rgb_matrix_sync.rgb_matrix, &rgb_matrix_config, sizeof(rgb_config_t)); + rgb_matrix_sync.rgb_suspend_state = rgb_matrix_get_suspend_state(); + return send_if_data_mismatch(PUT_RGB_MATRIX, &last_update, &rgb_matrix_sync, &split_shmem->rgb_matrix_sync, sizeof(rgb_matrix_sync)); +} + +static void rgb_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { + memcpy(&rgb_matrix_config, &split_shmem->rgb_matrix_sync.rgb_matrix, sizeof(rgb_config_t)); + rgb_matrix_set_suspend_state(split_shmem->rgb_matrix_sync.rgb_suspend_state); +} + +# define TRANSACTIONS_RGB_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(rgb_matrix_handlers) +# define TRANSACTIONS_RGB_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(rgb_matrix_handlers) +# define TRANSACTIONS_RGB_MATRIX_REGISTRATIONS [PUT_RGB_MATRIX] = trans_initiator2target_initializer(rgb_matrix_sync), + +#else // defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) + +# define TRANSACTIONS_RGB_MATRIX_MASTER() +# define TRANSACTIONS_RGB_MATRIX_SLAVE() +# define TRANSACTIONS_RGB_MATRIX_REGISTRATIONS + +#endif // defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) + +//////////////////////////////////////////////////// +// WPM + +#if defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE) + +static bool wpm_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { + static uint32_t last_update = 0; + uint8_t current_wpm = get_current_wpm(); + return send_if_condition(PUT_WPM, &last_update, (current_wpm != split_shmem->current_wpm), ¤t_wpm, sizeof(current_wpm)); +} + +static void wpm_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { set_current_wpm(split_shmem->current_wpm); } + +# define TRANSACTIONS_WPM_MASTER() TRANSACTION_HANDLER_MASTER(wpm_handlers) +# define TRANSACTIONS_WPM_SLAVE() TRANSACTION_HANDLER_SLAVE(wpm_handlers) +# define TRANSACTIONS_WPM_REGISTRATIONS [PUT_WPM] = trans_initiator2target_initializer(current_wpm), + +#else // defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE) + +# define TRANSACTIONS_WPM_MASTER() +# define TRANSACTIONS_WPM_SLAVE() +# define TRANSACTIONS_WPM_REGISTRATIONS + +#endif // defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE) + +//////////////////////////////////////////////////// + +uint8_t dummy; +split_transaction_desc_t split_transaction_table[NUM_TOTAL_TRANSACTIONS] = { + // Set defaults + [0 ...(NUM_TOTAL_TRANSACTIONS - 1)] = {NULL, 0, 0, 0, 0, 0}, + +#ifdef USE_I2C + [I2C_EXECUTE_CALLBACK] = trans_initiator2target_initializer(transaction_id), +#endif // USE_I2C + + // clang-format off + TRANSACTIONS_SLAVE_MATRIX_REGISTRATIONS + TRANSACTIONS_MASTER_MATRIX_REGISTRATIONS + TRANSACTIONS_ENCODERS_REGISTRATIONS + TRANSACTIONS_SYNC_TIMER_REGISTRATIONS + TRANSACTIONS_LAYER_STATE_REGISTRATIONS + TRANSACTIONS_LED_STATE_REGISTRATIONS + TRANSACTIONS_MODS_REGISTRATIONS + TRANSACTIONS_BACKLIGHT_REGISTRATIONS + TRANSACTIONS_RGBLIGHT_REGISTRATIONS + TRANSACTIONS_LED_MATRIX_REGISTRATIONS + TRANSACTIONS_RGB_MATRIX_REGISTRATIONS + TRANSACTIONS_WPM_REGISTRATIONS +// clang-format on + +#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) + [PUT_RPC_INFO] = trans_initiator2target_initializer_cb(rpc_info, slave_rpc_info_callback), + [PUT_RPC_REQ_DATA] = trans_initiator2target_initializer(rpc_m2s_buffer), + [EXECUTE_RPC] = trans_initiator2target_initializer_cb(rpc_info.transaction_id, slave_rpc_exec_callback), + [GET_RPC_RESP_DATA] = trans_target2initiator_initializer(rpc_s2m_buffer), +#endif // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) +}; + +bool transactions_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { + bool okay = true; + TRANSACTIONS_SLAVE_MATRIX_MASTER(); + TRANSACTIONS_MASTER_MATRIX_MASTER(); + TRANSACTIONS_ENCODERS_MASTER(); + TRANSACTIONS_SYNC_TIMER_MASTER(); + TRANSACTIONS_LAYER_STATE_MASTER(); + TRANSACTIONS_LED_STATE_MASTER(); + TRANSACTIONS_MODS_MASTER(); + TRANSACTIONS_BACKLIGHT_MASTER(); + TRANSACTIONS_RGBLIGHT_MASTER(); + TRANSACTIONS_LED_MATRIX_MASTER(); + TRANSACTIONS_RGB_MATRIX_MASTER(); + TRANSACTIONS_WPM_MASTER(); + return okay; +} + +void transactions_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { + TRANSACTIONS_SLAVE_MATRIX_SLAVE(); + TRANSACTIONS_MASTER_MATRIX_SLAVE(); + TRANSACTIONS_ENCODERS_SLAVE(); + TRANSACTIONS_SYNC_TIMER_SLAVE(); + TRANSACTIONS_LAYER_STATE_SLAVE(); + TRANSACTIONS_LED_STATE_SLAVE(); + TRANSACTIONS_MODS_SLAVE(); + TRANSACTIONS_BACKLIGHT_SLAVE(); + TRANSACTIONS_RGBLIGHT_SLAVE(); + TRANSACTIONS_LED_MATRIX_SLAVE(); + TRANSACTIONS_RGB_MATRIX_SLAVE(); + TRANSACTIONS_WPM_SLAVE(); +} + +#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) + +void transaction_register_rpc(int8_t transaction_id, slave_callback_t callback) { + // Prevent invoking RPC on QMK core sync data + if (transaction_id <= GET_RPC_RESP_DATA) return; + + // Set the callback + split_transaction_table[transaction_id].slave_callback = callback; + split_transaction_table[transaction_id].initiator2target_offset = offsetof(split_shared_memory_t, rpc_m2s_buffer); + split_transaction_table[transaction_id].target2initiator_offset = offsetof(split_shared_memory_t, rpc_s2m_buffer); +} + +bool transaction_rpc_exec(int8_t transaction_id, uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer) { + // Prevent invoking RPC on QMK core sync data + if (transaction_id <= GET_RPC_RESP_DATA) return false; + // Prevent sizing issues + if (initiator2target_buffer_size > RPC_M2S_BUFFER_SIZE) return false; + if (target2initiator_buffer_size > RPC_S2M_BUFFER_SIZE) return false; + + // Prepare the metadata block + rpc_sync_info_t info = {.transaction_id = transaction_id, .m2s_length = initiator2target_buffer_size, .s2m_length = target2initiator_buffer_size}; + + // Make sure the local side knows that we're not sending the full block of data + split_transaction_table[PUT_RPC_REQ_DATA].initiator2target_buffer_size = initiator2target_buffer_size; + split_transaction_table[GET_RPC_RESP_DATA].target2initiator_buffer_size = target2initiator_buffer_size; + + // Run through the sequence: + // * set the transaction ID and lengths + // * send the request data + // * execute RPC callback + // * retrieve the response data + if (!transport_write(PUT_RPC_INFO, &info, sizeof(info))) { + return false; + } + if (!transport_write(PUT_RPC_REQ_DATA, initiator2target_buffer, initiator2target_buffer_size)) { + return false; + } + if (!transport_write(EXECUTE_RPC, &transaction_id, sizeof(transaction_id))) { + return false; + } + if (!transport_read(GET_RPC_RESP_DATA, target2initiator_buffer, target2initiator_buffer_size)) { + return false; + } + return true; +} + +void slave_rpc_info_callback(uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer) { + // The RPC info block contains the intended transaction ID, as well as the sizes for both inbound and outbound data. + // Ignore the args -- the `split_shmem` already has the info, we just need to act upon it. + // We must keep the `split_transaction_table` non-const, so that it is able to be modified at runtime. + + split_transaction_table[PUT_RPC_REQ_DATA].initiator2target_buffer_size = split_shmem->rpc_info.m2s_length; + split_transaction_table[GET_RPC_RESP_DATA].target2initiator_buffer_size = split_shmem->rpc_info.s2m_length; +} + +void slave_rpc_exec_callback(uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer) { + // We can assume that the buffer lengths are correctly set, now, given that sequentially the rpc_info callback was already executed. + // Go through the rpc_info and execute _that_ transaction's callback, with the scratch buffers as inputs. + int8_t transaction_id = split_shmem->rpc_info.transaction_id; + if (transaction_id < NUM_TOTAL_TRANSACTIONS) { + split_transaction_desc_t *trans = &split_transaction_table[transaction_id]; + if (trans->slave_callback) { + trans->slave_callback(split_shmem->rpc_info.m2s_length, split_shmem->rpc_m2s_buffer, split_shmem->rpc_info.s2m_length, split_shmem->rpc_s2m_buffer); + } + } +} + +#endif // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) diff --git a/quantum/split_common/transactions.h b/quantum/split_common/transactions.h new file mode 100644 index 0000000000..4306ba1d87 --- /dev/null +++ b/quantum/split_common/transactions.h @@ -0,0 +1,54 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "stdint.h" +#include "stdbool.h" + +#include "matrix.h" +#include "transaction_id_define.h" +#include "transport.h" + +typedef void (*slave_callback_t)(uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer); + +// Split transaction Descriptor +typedef struct _split_transaction_desc_t { + uint8_t * status; + uint8_t initiator2target_buffer_size; + uint16_t initiator2target_offset; + uint8_t target2initiator_buffer_size; + uint16_t target2initiator_offset; + slave_callback_t slave_callback; +} split_transaction_desc_t; + +// Forward declaration for the split transactions +extern split_transaction_desc_t split_transaction_table[NUM_TOTAL_TRANSACTIONS]; + +#define split_shmem_offset_ptr(offset) ((void *)(((uint8_t *)split_shmem) + (offset))) +#define split_trans_initiator2target_buffer(trans) (split_shmem_offset_ptr((trans)->initiator2target_offset)) +#define split_trans_target2initiator_buffer(trans) (split_shmem_offset_ptr((trans)->target2initiator_offset)) + +// returns false if valid data not received from slave +bool transactions_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]); +void transactions_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]); + +void transaction_register_rpc(int8_t transaction_id, slave_callback_t callback); + +bool transaction_rpc_exec(int8_t transaction_id, uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer); + +#define transaction_rpc_send(transaction_id, initiator2target_buffer_size, initiator2target_buffer) transaction_rpc_exec(transaction_id, initiator2target_buffer_size, initiator2target_buffer, 0, NULL) +#define transaction_rpc_recv(transaction_id, target2initiator_buffer_size, target2initiator_buffer) transaction_rpc_exec(transaction_id, 0, NULL, target2initiator_buffer_size, target2initiator_buffer) diff --git a/quantum/split_common/transport.c b/quantum/split_common/transport.c index 9ed0f7591b..a711ef85f0 100644 --- a/quantum/split_common/transport.c +++ b/quantum/split_common/transport.c @@ -1,452 +1,118 @@ -#include -#include - -#include "config.h" -#include "matrix.h" -#include "quantum.h" - -#define ROWS_PER_HAND (MATRIX_ROWS / 2) -#define SYNC_TIMER_OFFSET 2 - -#ifdef RGBLIGHT_ENABLE -# include "rgblight.h" -#endif - -#ifdef BACKLIGHT_ENABLE -# include "backlight.h" -#endif - -#ifdef ENCODER_ENABLE -# include "encoder.h" -static pin_t encoders_pad[] = ENCODERS_PAD_A; -# define NUMBER_OF_ENCODERS (sizeof(encoders_pad) / sizeof(pin_t)) -#endif - -#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) -# include "led_matrix.h" -#endif -#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) -# include "rgb_matrix.h" -#endif - -#if defined(USE_I2C) +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ -# include "i2c_master.h" -# include "i2c_slave.h" - -typedef struct _I2C_slave_buffer_t { -# ifndef DISABLE_SYNC_TIMER - uint32_t sync_timer; -# endif -# ifdef SPLIT_TRANSPORT_MIRROR - matrix_row_t mmatrix[ROWS_PER_HAND]; -# endif - matrix_row_t smatrix[ROWS_PER_HAND]; -# ifdef SPLIT_MODS_ENABLE - uint8_t real_mods; - uint8_t weak_mods; -# ifndef NO_ACTION_ONESHOT - uint8_t oneshot_mods; -# endif -# endif -# ifdef BACKLIGHT_ENABLE - uint8_t backlight_level; -# endif -# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) - rgblight_syncinfo_t rgblight_sync; -# endif -# ifdef ENCODER_ENABLE - uint8_t encoder_state[NUMBER_OF_ENCODERS]; -# endif -# ifdef WPM_ENABLE - uint8_t current_wpm; -# endif -# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) - led_eeconfig_t led_matrix; - bool led_suspend_state; -# endif -# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) - rgb_config_t rgb_matrix; - bool rgb_suspend_state; -# endif -} I2C_slave_buffer_t; +#include +#include -static I2C_slave_buffer_t *const i2c_buffer = (I2C_slave_buffer_t *)i2c_slave_reg; +#include "transactions.h" +#include "transport.h" +#include "transaction_id_define.h" +#include "atomic_util.h" -# define I2C_SYNC_TIME_START offsetof(I2C_slave_buffer_t, sync_timer) -# define I2C_KEYMAP_MASTER_START offsetof(I2C_slave_buffer_t, mmatrix) -# define I2C_KEYMAP_SLAVE_START offsetof(I2C_slave_buffer_t, smatrix) -# define I2C_REAL_MODS_START offsetof(I2C_slave_buffer_t, real_mods) -# define I2C_WEAK_MODS_START offsetof(I2C_slave_buffer_t, weak_mods) -# define I2C_ONESHOT_MODS_START offsetof(I2C_slave_buffer_t, oneshot_mods) -# define I2C_BACKLIGHT_START offsetof(I2C_slave_buffer_t, backlight_level) -# define I2C_RGB_START offsetof(I2C_slave_buffer_t, rgblight_sync) -# define I2C_ENCODER_START offsetof(I2C_slave_buffer_t, encoder_state) -# define I2C_WPM_START offsetof(I2C_slave_buffer_t, current_wpm) -# define I2C_LED_MATRIX_START offsetof(I2C_slave_buffer_t, led_matrix) -# define I2C_LED_SUSPEND_START offsetof(I2C_slave_buffer_t, led_suspend_state) -# define I2C_RGB_MATRIX_START offsetof(I2C_slave_buffer_t, rgb_matrix) -# define I2C_RGB_SUSPEND_START offsetof(I2C_slave_buffer_t, rgb_suspend_state) +#ifdef USE_I2C -# define TIMEOUT 100 +# ifndef SLAVE_I2C_TIMEOUT +# define SLAVE_I2C_TIMEOUT 100 +# endif // SLAVE_I2C_TIMEOUT # ifndef SLAVE_I2C_ADDRESS # define SLAVE_I2C_ADDRESS 0x32 # endif -// Get rows from other half over i2c -bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { - i2c_readReg(SLAVE_I2C_ADDRESS, I2C_KEYMAP_SLAVE_START, (void *)slave_matrix, sizeof(i2c_buffer->smatrix), TIMEOUT); -# ifdef SPLIT_TRANSPORT_MIRROR - i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_KEYMAP_MASTER_START, (void *)master_matrix, sizeof(i2c_buffer->mmatrix), TIMEOUT); -# endif +# include "i2c_master.h" +# include "i2c_slave.h" - // write backlight info -# ifdef BACKLIGHT_ENABLE - uint8_t level = is_backlight_enabled() ? get_backlight_level() : 0; - if (level != i2c_buffer->backlight_level) { - if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_BACKLIGHT_START, (void *)&level, sizeof(level), TIMEOUT) >= 0) { - i2c_buffer->backlight_level = level; - } - } -# endif +// Ensure the I2C buffer has enough space +_Static_assert(sizeof(split_shared_memory_t) <= I2C_SLAVE_REG_COUNT, "split_shared_memory_t too large for I2C_SLAVE_REG_COUNT"); -# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) - if (rgblight_get_change_flags()) { - rgblight_syncinfo_t rgblight_sync; - rgblight_get_syncinfo(&rgblight_sync); - if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_START, (void *)&rgblight_sync, sizeof(rgblight_sync), TIMEOUT) >= 0) { - rgblight_clear_change_flags(); - } - } -# endif +split_shared_memory_t *const split_shmem = (split_shared_memory_t *)i2c_slave_reg; -# ifdef ENCODER_ENABLE - i2c_readReg(SLAVE_I2C_ADDRESS, I2C_ENCODER_START, (void *)i2c_buffer->encoder_state, sizeof(i2c_buffer->encoder_state), TIMEOUT); - encoder_update_raw(i2c_buffer->encoder_state); -# endif +void transport_master_init(void) { i2c_init(); } +void transport_slave_init(void) { i2c_slave_init(SLAVE_I2C_ADDRESS); } -# ifdef WPM_ENABLE - uint8_t current_wpm = get_current_wpm(); - if (current_wpm != i2c_buffer->current_wpm) { - if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_WPM_START, (void *)¤t_wpm, sizeof(current_wpm), TIMEOUT) >= 0) { - i2c_buffer->current_wpm = current_wpm; - } +i2c_status_t transport_trigger_callback(int8_t id) { + // If there's no callback, indicate that we were successful + if (!split_transaction_table[id].slave_callback) { + return I2C_STATUS_SUCCESS; } -# endif -# ifdef SPLIT_MODS_ENABLE - uint8_t real_mods = get_mods(); - if (real_mods != i2c_buffer->real_mods) { - if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_REAL_MODS_START, (void *)&real_mods, sizeof(real_mods), TIMEOUT) >= 0) { - i2c_buffer->real_mods = real_mods; + // Kick off the "callback executor", now that data has been written to the slave + split_shmem->transaction_id = id; + split_transaction_desc_t *trans = &split_transaction_table[I2C_EXECUTE_CALLBACK]; + return i2c_writeReg(SLAVE_I2C_ADDRESS, trans->initiator2target_offset, split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size, SLAVE_I2C_TIMEOUT); +} + +bool transport_execute_transaction(int8_t id, const void *initiator2target_buf, uint16_t initiator2target_length, void *target2initiator_buf, uint16_t target2initiator_length) { + i2c_status_t status; + split_transaction_desc_t *trans = &split_transaction_table[id]; + if (initiator2target_length > 0) { + size_t len = trans->initiator2target_buffer_size < initiator2target_length ? trans->initiator2target_buffer_size : initiator2target_length; + memcpy(split_trans_initiator2target_buffer(trans), initiator2target_buf, len); + if ((status = i2c_writeReg(SLAVE_I2C_ADDRESS, trans->initiator2target_offset, split_trans_initiator2target_buffer(trans), len, SLAVE_I2C_TIMEOUT)) < 0) { + return false; } } - uint8_t weak_mods = get_weak_mods(); - if (weak_mods != i2c_buffer->weak_mods) { - if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_WEAK_MODS_START, (void *)&weak_mods, sizeof(weak_mods), TIMEOUT) >= 0) { - i2c_buffer->weak_mods = weak_mods; - } + // If we need to execute a callback on the slave, do so + if ((status = transport_trigger_callback(id)) < 0) { + return false; } -# ifndef NO_ACTION_ONESHOT - uint8_t oneshot_mods = get_oneshot_mods(); - if (oneshot_mods != i2c_buffer->oneshot_mods) { - if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_ONESHOT_MODS_START, (void *)&oneshot_mods, sizeof(oneshot_mods), TIMEOUT) >= 0) { - i2c_buffer->oneshot_mods = oneshot_mods; + if (target2initiator_length > 0) { + size_t len = trans->target2initiator_buffer_size < target2initiator_length ? trans->target2initiator_buffer_size : target2initiator_length; + if ((status = i2c_readReg(SLAVE_I2C_ADDRESS, trans->target2initiator_offset, split_trans_target2initiator_buffer(trans), len, SLAVE_I2C_TIMEOUT)) < 0) { + return false; } + memcpy(target2initiator_buf, split_trans_target2initiator_buffer(trans), len); } -# endif -# endif -# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) - i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_LED_MATRIX_START, (void *)led_matrix_eeconfig, sizeof(i2c_buffer->led_matrix), TIMEOUT); - bool suspend_state = led_matrix_get_suspend_state(); - i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_LED_SUSPEND_START, (void *)suspend_state, sizeof(i2c_buffer->led_suspend_state), TIMEOUT); -# endif -# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) - i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_MATRIX_START, (void *)rgb_matrix_config, sizeof(i2c_buffer->rgb_matrix), TIMEOUT); - bool suspend_state = rgb_matrix_get_suspend_state(); - i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_SUSPEND_START, (void *)suspend_state, sizeof(i2c_buffer->rgb_suspend_state), TIMEOUT); -# endif - -# ifndef DISABLE_SYNC_TIMER - i2c_buffer->sync_timer = sync_timer_read32() + SYNC_TIMER_OFFSET; - i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_SYNC_TIME_START, (void *)&i2c_buffer->sync_timer, sizeof(i2c_buffer->sync_timer), TIMEOUT); -# endif return true; } -void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { -# ifndef DISABLE_SYNC_TIMER - sync_timer_update(i2c_buffer->sync_timer); -# endif - // Copy matrix to I2C buffer - memcpy((void *)i2c_buffer->smatrix, (void *)slave_matrix, sizeof(i2c_buffer->smatrix)); -# ifdef SPLIT_TRANSPORT_MIRROR - memcpy((void *)master_matrix, (void *)i2c_buffer->mmatrix, sizeof(i2c_buffer->mmatrix)); -# endif - -// Read Backlight Info -# ifdef BACKLIGHT_ENABLE - backlight_set(i2c_buffer->backlight_level); -# endif - -# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) - // Update the RGB with the new data - if (i2c_buffer->rgblight_sync.status.change_flags != 0) { - rgblight_update_sync(&i2c_buffer->rgblight_sync, false); - i2c_buffer->rgblight_sync.status.change_flags = 0; - } -# endif - -# ifdef ENCODER_ENABLE - encoder_state_raw(i2c_buffer->encoder_state); -# endif - -# ifdef WPM_ENABLE - set_current_wpm(i2c_buffer->current_wpm); -# endif - -# ifdef SPLIT_MODS_ENABLE - set_mods(i2c_buffer->real_mods); - set_weak_mods(i2c_buffer->weak_mods); -# ifndef NO_ACTION_ONESHOT - set_oneshot_mods(i2c_buffer->oneshot_mods); -# endif -# endif - -# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) - memcpy((void *)i2c_buffer->led_matrix, (void *)led_matrix_eeconfig, sizeof(i2c_buffer->led_matrix)); - led_matrix_set_suspend_state(i2c_buffer->led_suspend_state); -# endif -# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) - memcpy((void *)i2c_buffer->rgb_matrix, (void *)rgb_matrix_config, sizeof(i2c_buffer->rgb_matrix)); - rgb_matrix_set_suspend_state(i2c_buffer->rgb_suspend_state); -# endif -} - -void transport_master_init(void) { i2c_init(); } - -void transport_slave_init(void) { i2c_slave_init(SLAVE_I2C_ADDRESS); } - -#else // USE_SERIAL +#else // USE_I2C # include "serial.h" -typedef struct _Serial_s2m_buffer_t { - // TODO: if MATRIX_COLS > 8 change to uint8_t packed_matrix[] for pack/unpack - matrix_row_t smatrix[ROWS_PER_HAND]; - -# ifdef ENCODER_ENABLE - uint8_t encoder_state[NUMBER_OF_ENCODERS]; -# endif - -} Serial_s2m_buffer_t; - -typedef struct _Serial_m2s_buffer_t { -# ifdef SPLIT_MODS_ENABLE - uint8_t real_mods; - uint8_t weak_mods; -# ifndef NO_ACTION_ONESHOT - uint8_t oneshot_mods; -# endif -# endif -# ifndef DISABLE_SYNC_TIMER - uint32_t sync_timer; -# endif -# ifdef SPLIT_TRANSPORT_MIRROR - matrix_row_t mmatrix[ROWS_PER_HAND]; -# endif -# ifdef BACKLIGHT_ENABLE - uint8_t backlight_level; -# endif -# ifdef WPM_ENABLE - uint8_t current_wpm; -# endif -# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) - led_eeconfig_t led_matrix; - bool led_suspend_state; -# endif -# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) - rgb_config_t rgb_matrix; - bool rgb_suspend_state; -# endif -} Serial_m2s_buffer_t; - -# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) -// When MCUs on both sides drive their respective RGB LED chains, -// it is necessary to synchronize, so it is necessary to communicate RGB -// information. In that case, define RGBLIGHT_SPLIT with info on the number -// of LEDs on each half. -// -// Otherwise, if the master side MCU drives both sides RGB LED chains, -// there is no need to communicate. - -typedef struct _Serial_rgblight_t { - rgblight_syncinfo_t rgblight_sync; -} Serial_rgblight_t; +static split_shared_memory_t shared_memory; +split_shared_memory_t *const split_shmem = &shared_memory; -volatile Serial_rgblight_t serial_rgblight = {}; -uint8_t volatile status_rgblight = 0; -# endif - -volatile Serial_s2m_buffer_t serial_s2m_buffer = {}; -volatile Serial_m2s_buffer_t serial_m2s_buffer = {}; -uint8_t volatile status0 = 0; - -enum serial_transaction_id { - GET_SLAVE_MATRIX = 0, -# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) - PUT_RGBLIGHT, -# endif -}; - -SSTD_t transactions[] = { - [GET_SLAVE_MATRIX] = - { - (uint8_t *)&status0, - sizeof(serial_m2s_buffer), - (uint8_t *)&serial_m2s_buffer, - sizeof(serial_s2m_buffer), - (uint8_t *)&serial_s2m_buffer, - }, -# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) - [PUT_RGBLIGHT] = - { - (uint8_t *)&status_rgblight, sizeof(serial_rgblight), (uint8_t *)&serial_rgblight, 0, NULL // no slave to master transfer - }, -# endif -}; - -void transport_master_init(void) { soft_serial_initiator_init(transactions, TID_LIMIT(transactions)); } - -void transport_slave_init(void) { soft_serial_target_init(transactions, TID_LIMIT(transactions)); } +void transport_master_init(void) { soft_serial_initiator_init(); } +void transport_slave_init(void) { soft_serial_target_init(); } -# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) - -// rgblight synchronization information communication. - -void transport_rgblight_master(void) { - if (rgblight_get_change_flags()) { - rgblight_get_syncinfo((rgblight_syncinfo_t *)&serial_rgblight.rgblight_sync); - if (soft_serial_transaction(PUT_RGBLIGHT) == TRANSACTION_END) { - rgblight_clear_change_flags(); - } - } -} - -void transport_rgblight_slave(void) { - if (status_rgblight == TRANSACTION_ACCEPTED) { - rgblight_update_sync((rgblight_syncinfo_t *)&serial_rgblight.rgblight_sync, false); - status_rgblight = TRANSACTION_END; +bool transport_execute_transaction(int8_t id, const void *initiator2target_buf, uint16_t initiator2target_length, void *target2initiator_buf, uint16_t target2initiator_length) { + split_transaction_desc_t *trans = &split_transaction_table[id]; + if (initiator2target_length > 0) { + size_t len = trans->initiator2target_buffer_size < initiator2target_length ? trans->initiator2target_buffer_size : initiator2target_length; + memcpy(split_trans_initiator2target_buffer(trans), initiator2target_buf, len); } -} -# else -# define transport_rgblight_master() -# define transport_rgblight_slave() -# endif - -bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { -# ifndef SERIAL_USE_MULTI_TRANSACTION - if (soft_serial_transaction() != TRANSACTION_END) { - return false; - } -# else - transport_rgblight_master(); - if (soft_serial_transaction(GET_SLAVE_MATRIX) != TRANSACTION_END) { + if (soft_serial_transaction(id) != TRANSACTION_END) { return false; } -# endif - // TODO: if MATRIX_COLS > 8 change to unpack() - for (int i = 0; i < ROWS_PER_HAND; ++i) { - slave_matrix[i] = serial_s2m_buffer.smatrix[i]; -# ifdef SPLIT_TRANSPORT_MIRROR - serial_m2s_buffer.mmatrix[i] = master_matrix[i]; -# endif + if (target2initiator_length > 0) { + size_t len = trans->target2initiator_buffer_size < target2initiator_length ? trans->target2initiator_buffer_size : target2initiator_length; + memcpy(target2initiator_buf, split_trans_target2initiator_buffer(trans), len); } -# ifdef BACKLIGHT_ENABLE - // Write backlight level for slave to read - serial_m2s_buffer.backlight_level = is_backlight_enabled() ? get_backlight_level() : 0; -# endif - -# ifdef ENCODER_ENABLE - encoder_update_raw((uint8_t *)serial_s2m_buffer.encoder_state); -# endif - -# ifdef WPM_ENABLE - // Write wpm to slave - serial_m2s_buffer.current_wpm = get_current_wpm(); -# endif - -# ifdef SPLIT_MODS_ENABLE - serial_m2s_buffer.real_mods = get_mods(); - serial_m2s_buffer.weak_mods = get_weak_mods(); -# ifndef NO_ACTION_ONESHOT - serial_m2s_buffer.oneshot_mods = get_oneshot_mods(); -# endif -# endif - -# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) - serial_m2s_buffer.led_matrix = led_matrix_eeconfig; - serial_m2s_buffer.led_suspend_state = led_matrix_get_suspend_state(); -# endif -# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) - serial_m2s_buffer.rgb_matrix = rgb_matrix_config; - serial_m2s_buffer.rgb_suspend_state = rgb_matrix_get_suspend_state(); -# endif - -# ifndef DISABLE_SYNC_TIMER - serial_m2s_buffer.sync_timer = sync_timer_read32() + SYNC_TIMER_OFFSET; -# endif return true; } -void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { - transport_rgblight_slave(); -# ifndef DISABLE_SYNC_TIMER - sync_timer_update(serial_m2s_buffer.sync_timer); -# endif - - // TODO: if MATRIX_COLS > 8 change to pack() - for (int i = 0; i < ROWS_PER_HAND; ++i) { - serial_s2m_buffer.smatrix[i] = slave_matrix[i]; -# ifdef SPLIT_TRANSPORT_MIRROR - master_matrix[i] = serial_m2s_buffer.mmatrix[i]; -# endif - } -# ifdef BACKLIGHT_ENABLE - backlight_set(serial_m2s_buffer.backlight_level); -# endif - -# ifdef ENCODER_ENABLE - encoder_state_raw((uint8_t *)serial_s2m_buffer.encoder_state); -# endif +#endif // USE_I2C -# ifdef WPM_ENABLE - set_current_wpm(serial_m2s_buffer.current_wpm); -# endif - -# ifdef SPLIT_MODS_ENABLE - set_mods(serial_m2s_buffer.real_mods); - set_weak_mods(serial_m2s_buffer.weak_mods); -# ifndef NO_ACTION_ONESHOT - set_oneshot_mods(serial_m2s_buffer.oneshot_mods); -# endif -# endif - -# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) - led_matrix_eeconfig = serial_m2s_buffer.led_matrix; - led_matrix_set_suspend_state(serial_m2s_buffer.led_suspend_state); -# endif -# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) - rgb_matrix_config = serial_m2s_buffer.rgb_matrix; - rgb_matrix_set_suspend_state(serial_m2s_buffer.rgb_suspend_state); -# endif -} +bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { return transactions_master(master_matrix, slave_matrix); } -#endif +void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { transactions_slave(master_matrix, slave_matrix); } \ No newline at end of file diff --git a/quantum/split_common/transport.h b/quantum/split_common/transport.h index a9f66301bf..2e07f6b25c 100644 --- a/quantum/split_common/transport.h +++ b/quantum/split_common/transport.h @@ -1,10 +1,175 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #pragma once +#include "stdint.h" +#include "stdbool.h" + +#include "progmem.h" +#include "action_layer.h" #include "matrix.h" +#ifndef RPC_M2S_BUFFER_SIZE +# define RPC_M2S_BUFFER_SIZE 32 +#endif // RPC_M2S_BUFFER_SIZE + +#ifndef RPC_S2M_BUFFER_SIZE +# define RPC_S2M_BUFFER_SIZE 32 +#endif // RPC_S2M_BUFFER_SIZE + void transport_master_init(void); void transport_slave_init(void); // returns false if valid data not received from slave bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]); void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]); + +bool transport_execute_transaction(int8_t id, const void *initiator2target_buf, uint16_t initiator2target_length, void *target2initiator_buf, uint16_t target2initiator_length); + +#ifdef ENCODER_ENABLE +# include "encoder.h" +# define NUMBER_OF_ENCODERS (sizeof((pin_t[])ENCODERS_PAD_A) / sizeof(pin_t)) +#endif // ENCODER_ENABLE + +#ifdef BACKLIGHT_ENABLE +# include "backlight.h" +#endif // BACKLIGHT_ENABLE + +#ifdef RGBLIGHT_ENABLE +# include "rgblight.h" +#endif // RGBLIGHT_ENABLE + +typedef struct _split_slave_matrix_sync_t { + uint8_t checksum; + matrix_row_t matrix[(MATRIX_ROWS) / 2]; +} split_slave_matrix_sync_t; + +#ifdef SPLIT_TRANSPORT_MIRROR +typedef struct _split_master_matrix_sync_t { + matrix_row_t matrix[(MATRIX_ROWS) / 2]; +} split_master_matrix_sync_t; +#endif // SPLIT_TRANSPORT_MIRROR + +#ifdef ENCODER_ENABLE +typedef struct _split_slave_encoder_sync_t { + uint8_t checksum; + uint8_t state[NUMBER_OF_ENCODERS]; +} split_slave_encoder_sync_t; +#endif // ENCODER_ENABLE + +#if !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE) +typedef struct _split_layers_sync_t { + layer_state_t layer_state; + layer_state_t default_layer_state; +} split_layers_sync_t; +#endif // !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE) + +#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) +# include "led_matrix.h" + +typedef struct _led_matrix_sync_t { + led_eeconfig_t led_matrix; + bool led_suspend_state; +} led_matrix_sync_t; +#endif // defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) + +#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) +# include "rgb_matrix.h" + +typedef struct _rgb_matrix_sync_t { + rgb_config_t rgb_matrix; + bool rgb_suspend_state; +} rgb_matrix_sync_t; +#endif // defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) + +#ifdef SPLIT_MODS_ENABLE +typedef struct _split_mods_sync_t { + uint8_t real_mods; + uint8_t weak_mods; +# ifndef NO_ACTION_ONESHOT + uint8_t oneshot_mods; +# endif // NO_ACTION_ONESHOT +} split_mods_sync_t; +#endif // SPLIT_MODS_ENABLE + +#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) +typedef struct _rpc_sync_info_t { + int8_t transaction_id; + uint8_t m2s_length; + uint8_t s2m_length; +} rpc_sync_info_t; +#endif // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) + +typedef struct _split_shared_memory_t { +#ifdef USE_I2C + int8_t transaction_id; +#endif // USE_I2C + + split_slave_matrix_sync_t smatrix; + +#ifdef SPLIT_TRANSPORT_MIRROR + split_master_matrix_sync_t mmatrix; +#endif // SPLIT_TRANSPORT_MIRROR + +#ifdef ENCODER_ENABLE + split_slave_encoder_sync_t encoders; +#endif // ENCODER_ENABLE + +#ifndef DISABLE_SYNC_TIMER + uint32_t sync_timer; +#endif // DISABLE_SYNC_TIMER + +#if !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE) + split_layers_sync_t layers; +#endif // !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE) + +#ifdef SPLIT_LED_STATE_ENABLE + uint8_t led_state; +#endif // SPLIT_LED_STATE_ENABLE + +#ifdef SPLIT_MODS_ENABLE + split_mods_sync_t mods; +#endif // SPLIT_MODS_ENABLE + +#ifdef BACKLIGHT_ENABLE + uint8_t backlight_level; +#endif // BACKLIGHT_ENABLE + +#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) + rgblight_syncinfo_t rgblight_sync; +#endif // defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) + +#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) + led_matrix_sync_t led_matrix_sync; +#endif // defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) + +#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) + rgb_matrix_sync_t rgb_matrix_sync; +#endif // defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) + +#if defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE) + uint8_t current_wpm; +#endif // defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE) + +#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) + rpc_sync_info_t rpc_info; + uint8_t rpc_m2s_buffer[RPC_M2S_BUFFER_SIZE]; + uint8_t rpc_s2m_buffer[RPC_S2M_BUFFER_SIZE]; +#endif // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) +} split_shared_memory_t; + +extern split_shared_memory_t *const split_shmem; \ No newline at end of file diff --git a/tmk_core/common/host.c b/tmk_core/common/host.c index e7d92cfac6..a8b391e893 100644 --- a/tmk_core/common/host.c +++ b/tmk_core/common/host.c @@ -17,6 +17,7 @@ along with this program. If not, see . #include //#include +#include "keyboard.h" #include "keycode.h" #include "host.h" #include "util.h" @@ -35,15 +36,20 @@ void host_set_driver(host_driver_t *d) { driver = d; } host_driver_t *host_get_driver(void) { return driver; } +#ifdef SPLIT_KEYBOARD +uint8_t split_led_state = 0; +void set_split_host_keyboard_leds(uint8_t led_state) { split_led_state = led_state; } +#endif + uint8_t host_keyboard_leds(void) { +#ifdef SPLIT_KEYBOARD + if (!is_keyboard_master()) return split_led_state; +#endif if (!driver) return 0; return (*driver->keyboard_leds)(); } -led_t host_keyboard_led_state(void) { - if (!driver) return (led_t){0}; - return (led_t)((*driver->keyboard_leds)()); -} +led_t host_keyboard_led_state(void) { return (led_t)host_keyboard_leds(); } /* send report */ void host_keyboard_send(report_keyboard_t *report) { -- cgit v1.2.3 From 8d9f527081d3a5fc8a0286e47022a70df8eb9111 Mon Sep 17 00:00:00 2001 From: Joakim Tufvegren Date: Sun, 20 Jun 2021 04:18:00 +0200 Subject: Add sync_timer support over serial_link (i.e. Ergodox Infinity) (#12845) --- quantum/serial_link/system/serial_link.c | 22 ++++++++++++++++++++++ tmk_core/common/sync_timer.c | 2 +- tmk_core/common/sync_timer.h | 2 +- 3 files changed, 24 insertions(+), 2 deletions(-) (limited to 'tmk_core') diff --git a/quantum/serial_link/system/serial_link.c b/quantum/serial_link/system/serial_link.c index f77483ad8c..6363f8ff3b 100644 --- a/quantum/serial_link/system/serial_link.c +++ b/quantum/serial_link/system/serial_link.c @@ -29,10 +29,13 @@ SOFTWARE. #include "serial_link/protocol/transport.h" #include "serial_link/protocol/frame_router.h" #include "matrix.h" +#include "sync_timer.h" #include #include "print.h" #include "config.h" +#define SYNC_TIMER_OFFSET 2 + static event_source_t new_data_event; static bool serial_link_connected; static bool is_master = false; @@ -159,10 +162,16 @@ static matrix_object_t last_matrix = {}; SLAVE_TO_MASTER_OBJECT(keyboard_matrix, matrix_object_t); MASTER_TO_ALL_SLAVES_OBJECT(serial_link_connected, bool); +#ifndef DISABLE_SYNC_TIMER +MASTER_TO_ALL_SLAVES_OBJECT(sync_timer, uint32_t); +#endif static remote_object_t* remote_objects[] = { REMOTE_OBJECT(serial_link_connected), REMOTE_OBJECT(keyboard_matrix), +#ifndef DISABLE_SYNC_TIMER + REMOTE_OBJECT(sync_timer), +#endif }; void init_serial_link(void) { @@ -200,14 +209,27 @@ void serial_link_update(void) { m->rows[i] = matrix.rows[i]; } end_write_keyboard_matrix(); + *begin_write_serial_link_connected() = true; end_write_serial_link_connected(); + +#ifndef DISABLE_SYNC_TIMER + *begin_write_sync_timer() = sync_timer_read32() + SYNC_TIMER_OFFSET; + end_write_sync_timer(); +#endif } matrix_object_t* m = read_keyboard_matrix(0); if (m) { matrix_set_remote(m->rows, 0); } + +#ifndef DISABLE_SYNC_TIMER + uint32_t* t = read_sync_timer(); + if (t) { + sync_timer_update(*t); + } +#endif } void signal_data_written(void) { chEvtBroadcast(&new_data_event); } diff --git a/tmk_core/common/sync_timer.c b/tmk_core/common/sync_timer.c index de24b463b6..68b92d8b43 100644 --- a/tmk_core/common/sync_timer.c +++ b/tmk_core/common/sync_timer.c @@ -26,7 +26,7 @@ SOFTWARE. #include "sync_timer.h" #include "keyboard.h" -#if defined(SPLIT_KEYBOARD) && !defined(DISABLE_SYNC_TIMER) +#if (defined(SPLIT_KEYBOARD) || defined(SERIAL_LINK_ENABLE)) && !defined(DISABLE_SYNC_TIMER) volatile int32_t sync_timer_ms; void sync_timer_init(void) { sync_timer_ms = 0; } diff --git a/tmk_core/common/sync_timer.h b/tmk_core/common/sync_timer.h index 9ddef45bb2..744e2b50d5 100644 --- a/tmk_core/common/sync_timer.h +++ b/tmk_core/common/sync_timer.h @@ -32,7 +32,7 @@ SOFTWARE. extern "C" { #endif -#if defined(SPLIT_KEYBOARD) && !defined(DISABLE_SYNC_TIMER) +#if (defined(SPLIT_KEYBOARD) || defined(SERIAL_LINK_ENABLE)) && !defined(DISABLE_SYNC_TIMER) void sync_timer_init(void); void sync_timer_update(uint32_t time); uint16_t sync_timer_read(void); -- cgit v1.2.3 From 8da8aabbe5796232c0f17f849badd455d42b0277 Mon Sep 17 00:00:00 2001 From: Drashna Jaelre Date: Sat, 3 Jul 2021 00:19:52 -0700 Subject: Improve layer mask handling (#13065) --- quantum/command.c | 2 +- quantum/quantum.c | 8 ++++---- tmk_core/common/action_layer.c | 12 ++++++------ tmk_core/common/action_layer.h | 29 +++++++++++++++++++++++++++-- 4 files changed, 38 insertions(+), 13 deletions(-) (limited to 'tmk_core') diff --git a/quantum/command.c b/quantum/command.c index 34c4b36b1c..3a7dc0f8ca 100644 --- a/quantum/command.c +++ b/quantum/command.c @@ -781,6 +781,6 @@ uint8_t numkey2num(uint8_t code) { static void switch_default_layer(uint8_t layer) { xprintf("L%d\n", layer); - default_layer_set(1UL << layer); + default_layer_set((layer_state_t)1 << layer); clear_keyboard(); } diff --git a/quantum/quantum.c b/quantum/quantum.c index 8ccdb774bd..b4cfa28d7d 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -340,13 +340,13 @@ void set_single_persistent_default_layer(uint8_t default_layer) { #if defined(AUDIO_ENABLE) && defined(DEFAULT_LAYER_SONGS) PLAY_SONG(default_layer_songs[default_layer]); #endif - eeconfig_update_default_layer(1U << default_layer); - default_layer_set(1U << default_layer); + eeconfig_update_default_layer((layer_state_t)1 << default_layer); + default_layer_set((layer_state_t)1 << default_layer); } layer_state_t update_tri_layer_state(layer_state_t state, uint8_t layer1, uint8_t layer2, uint8_t layer3) { - layer_state_t mask12 = (1UL << layer1) | (1UL << layer2); - layer_state_t mask3 = 1UL << layer3; + layer_state_t mask12 = ((layer_state_t)1 << layer1) | ((layer_state_t)1 << layer2); + layer_state_t mask3 = (layer_state_t)1 << layer3; return (state & mask12) == mask12 ? (state | mask3) : (state & ~mask3); } diff --git a/tmk_core/common/action_layer.c b/tmk_core/common/action_layer.c index af2d7d964b..ed1a4bd20d 100644 --- a/tmk_core/common/action_layer.c +++ b/tmk_core/common/action_layer.c @@ -131,32 +131,32 @@ bool layer_state_cmp(layer_state_t cmp_layer_state, uint8_t layer) { if (!cmp_layer_state) { return layer == 0; } - return (cmp_layer_state & (1UL << layer)) != 0; + return (cmp_layer_state & ((layer_state_t)1 << layer)) != 0; } /** \brief Layer move * * Turns on the given layer and turn off all other layers */ -void layer_move(uint8_t layer) { layer_state_set(1UL << layer); } +void layer_move(uint8_t layer) { layer_state_set((layer_state_t)1 << layer); } /** \brief Layer on * * Turns on given layer */ -void layer_on(uint8_t layer) { layer_state_set(layer_state | (1UL << layer)); } +void layer_on(uint8_t layer) { layer_state_set(layer_state | ((layer_state_t)1 << layer)); } /** \brief Layer off * * Turns off given layer */ -void layer_off(uint8_t layer) { layer_state_set(layer_state & ~(1UL << layer)); } +void layer_off(uint8_t layer) { layer_state_set(layer_state & ~((layer_state_t)1 << layer)); } /** \brief Layer invert * * Toggle the given layer (set it if it's unset, or unset it if it's set) */ -void layer_invert(uint8_t layer) { layer_state_set(layer_state ^ (1UL << layer)); } +void layer_invert(uint8_t layer) { layer_state_set(layer_state ^ ((layer_state_t)1 << layer)); } /** \brief Layer or * @@ -258,7 +258,7 @@ uint8_t layer_switch_get_layer(keypos_t key) { layer_state_t layers = layer_state | default_layer_state; /* check top layer first */ for (int8_t i = MAX_LAYER - 1; i >= 0; i--) { - if (layers & (1UL << i)) { + if (layers & ((layer_state_t)1 << i)) { action = action_for_key(i, key); if (action.code != ACTION_TRANSPARENT) { return i; diff --git a/tmk_core/common/action_layer.h b/tmk_core/common/action_layer.h index d72cd3e3a5..b87d096eed 100644 --- a/tmk_core/common/action_layer.h +++ b/tmk_core/common/action_layer.h @@ -21,6 +21,29 @@ along with this program. If not, see . #include "keyboard.h" #include "action.h" +#ifdef DYNAMIC_KEYMAP_ENABLE +# ifndef DYNAMIC_KEYMAP_LAYER_COUNT +# define DYNAMIC_KEYMAP_LAYER_COUNT 4 +# endif +# if DYNAMIC_KEYMAP_LAYER_COUNT <= 8 +# ifndef LAYER_STATE_8BIT +# define LAYER_STATE_8BIT +# endif +# elif DYNAMIC_KEYMAP_LAYER_COUNT <= 16 +# ifndef LAYER_STATE_16BIT +# define LAYER_STATE_16BIT +# endif +# else +# ifndef LAYER_STATE_32BIT +# define LAYER_STATE_32BIT +# endif +# endif +#endif + +#if !defined(LAYER_STATE_8BIT) && !defined(LAYER_STATE_16BIT) && !defined(LAYER_STATE_32BIT) +# define LAYER_STATE_32BIT +#endif + #if defined(LAYER_STATE_8BIT) typedef uint8_t layer_state_t; # define MAX_LAYER_BITS 3 @@ -35,13 +58,15 @@ typedef uint16_t layer_state_t; # define MAX_LAYER 16 # endif # define get_highest_layer(state) biton16(state) -#else +#elif defined(LAYER_STATE_32BIT) typedef uint32_t layer_state_t; # define MAX_LAYER_BITS 5 # ifndef MAX_LAYER # define MAX_LAYER 32 # endif # define get_highest_layer(state) biton32(state) +#else +# error Layer Mask size not specified. HOW?! #endif /* @@ -92,7 +117,7 @@ layer_state_t layer_state_set_kb(layer_state_t state); # define layer_state_set(layer) # define layer_state_is(layer) (layer == 0) -# define layer_state_cmp(state, layer) (state == 0 ? layer == 0 : (state & 1UL << layer) != 0) +# define layer_state_cmp(state, layer) (state == 0 ? layer == 0 : (state & (layer_state_t)1 << layer) != 0) # define layer_debug() # define layer_clear() -- cgit v1.2.3 From a535d24ecfd465124cdb255e53b5cc301cbda6d9 Mon Sep 17 00:00:00 2001 From: Thomas Weißschuh Date: Tue, 6 Jul 2021 01:24:48 +0200 Subject: core: chibios: bootloader: use integer pointers as volatile (#13450) This prevents gcc from incorrectly trying to validate array bounds. ``` tmk_core/common/chibios/bootloader.c: error: '__builtin_memcpy' offset [0, 21] is out of the bounds [0, 0] [-Werror=array-bounds] 107 | __builtin_memcpy((void *) VBAT, (const void *)sys_reset_to_loader_magic, sizeof(sys_reset_to_loader_magic)); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``` See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99578#c16 Fixes #12925--- tmk_core/common/chibios/bootloader.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'tmk_core') diff --git a/tmk_core/common/chibios/bootloader.c b/tmk_core/common/chibios/bootloader.c index 76d52ea608..f9514ee5f3 100644 --- a/tmk_core/common/chibios/bootloader.c +++ b/tmk_core/common/chibios/bootloader.c @@ -103,7 +103,8 @@ void enter_bootloader_mode_if_requested(void) { # define SCB_AIRCR_VECTKEY_WRITEMAGIC 0x05FA0000 const uint8_t sys_reset_to_loader_magic[] = "\xff\x00\x7fRESET TO LOADER\x7f\x00\xff"; __attribute__((weak)) void bootloader_jump(void) { - __builtin_memcpy((void *)VBAT, (const void *)sys_reset_to_loader_magic, sizeof(sys_reset_to_loader_magic)); + void *volatile vbat = (void *)VBAT; + __builtin_memcpy(vbat, (const void *)sys_reset_to_loader_magic, sizeof(sys_reset_to_loader_magic)); // request reset SCB->AIRCR = SCB_AIRCR_VECTKEY_WRITEMAGIC | SCB_AIRCR_SYSRESETREQ_Msk; } -- cgit v1.2.3 From 9c74fd14bc9777ec45cc93fa57bf83ab17b988db Mon Sep 17 00:00:00 2001 From: Chris Cullin Date: Tue, 13 Jul 2021 01:51:23 +1000 Subject: Enable g_is31_leds PROGMEM for RGB Matrix IS31FL3737 driver (#13480) --- docs/feature_rgb_matrix.md | 2 +- drivers/issi/is31fl3737.c | 9 +++++++-- keyboards/mt84/mt84.c | 40 ++++++++++++++++++++-------------------- keyboards/planck/ez/ez.c | 2 +- tmk_core/common/progmem.h | 1 + 5 files changed, 30 insertions(+), 24 deletions(-) (limited to 'tmk_core') diff --git a/docs/feature_rgb_matrix.md b/docs/feature_rgb_matrix.md index 675b7a1be0..be763ee025 100644 --- a/docs/feature_rgb_matrix.md +++ b/docs/feature_rgb_matrix.md @@ -171,7 +171,7 @@ Currently only a single drivers is supported, but it would be trivial to support Define these arrays listing all the LEDs in your `.c`: ```c -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location diff --git a/drivers/issi/is31fl3737.c b/drivers/issi/is31fl3737.c index 8647c93cc1..e40bfa0d79 100644 --- a/drivers/issi/is31fl3737.c +++ b/drivers/issi/is31fl3737.c @@ -19,6 +19,7 @@ #include "is31fl3737.h" #include "i2c_master.h" #include "wait.h" +#include "progmem.h" // This is a 7-bit address, that gets left-shifted and bit 0 // set to 0 for write, 1 for read (as per I2C protocol) @@ -153,7 +154,9 @@ void IS31FL3737_init(uint8_t addr) { void IS31FL3737_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) { if (index >= 0 && index < DRIVER_LED_TOTAL) { - is31_led led = g_is31_leds[index]; + // copy the led config from progmem to SRAM + is31_led led; + memcpy_P(&led, (&g_is31_leds[index]), sizeof(led)); g_pwm_buffer[led.driver][led.r] = red; g_pwm_buffer[led.driver][led.g] = green; @@ -169,7 +172,9 @@ void IS31FL3737_set_color_all(uint8_t red, uint8_t green, uint8_t blue) { } void IS31FL3737_set_led_control_register(uint8_t index, bool red, bool green, bool blue) { - is31_led led = g_is31_leds[index]; + // copy the led config from progmem to SRAM + is31_led led; + memcpy_P(&led, (&g_is31_leds[index]), sizeof(led)); uint8_t control_register_r = led.r / 8; uint8_t control_register_g = led.g / 8; diff --git a/keyboards/mt84/mt84.c b/keyboards/mt84/mt84.c index d9f509e14d..e15a1ff951 100644 --- a/keyboards/mt84/mt84.c +++ b/keyboards/mt84/mt84.c @@ -1,22 +1,22 @@ - /* Copyright 2020 MT<704340378@qq.com> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ + /* Copyright 2020 MT<704340378@qq.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ #include "mt84.h" #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location @@ -40,7 +40,7 @@ const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { {1, D_12, E_12, F_12}, {1, G_12, H_12, I_12}, {1, J_12, K_12, L_12}, - + {0, A_1, B_1, C_1}, {0, D_1, E_1, F_1}, {0, G_1, H_1, I_1}, @@ -72,7 +72,7 @@ const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { {1, A_7, B_7, C_7}, {1, D_7, E_7, F_7}, {1, G_7, H_7, I_7}, - + {0, A_3, B_3, C_3}, {0, D_3, E_3, F_3}, {0, G_3, H_3, I_3}, @@ -87,7 +87,7 @@ const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { {1, J_3, K_3, L_3}, {1, A_8, B_8, C_8}, {1, G_8, H_8, I_8}, - + {0, A_4, B_4, C_4}, {0, D_4, E_4, F_4}, {0, G_4, H_4, I_4}, @@ -130,7 +130,7 @@ led_config_t g_led_config = {{ { 9, 52 }, { 27, 52 }, { 43, 52 }, { 59, 52 }, { 75, 52 }, { 91, 52 }, { 107, 52 }, { 123, 52 }, { 139, 52 }, { 155, 52 }, { 171, 52 }, { 187, 52 }, { 212, 52 }, { 224, 52 }, { 2, 64 }, { 18, 64 }, { 33, 64 }, { 93, 64 }, { 150, 64 }, { 165, 64 }, { 180, 64 }, { 195, 64 }, { 210, 64 }, { 224, 64 } }, { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, diff --git a/keyboards/planck/ez/ez.c b/keyboards/planck/ez/ez.c index 8c498a5520..818dc66587 100644 --- a/keyboards/planck/ez/ez.c +++ b/keyboards/planck/ez/ez.c @@ -19,7 +19,7 @@ keyboard_config_t keyboard_config; #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location diff --git a/tmk_core/common/progmem.h b/tmk_core/common/progmem.h index 4e4771e523..3a7a169682 100644 --- a/tmk_core/common/progmem.h +++ b/tmk_core/common/progmem.h @@ -3,6 +3,7 @@ #if defined(__AVR__) # include #else +# include # define PROGMEM # define PSTR(x) x # define PGM_P const char* -- cgit v1.2.3 From 52cfc9259b58a3a11a244fbe35c49c7dd1a9cae0 Mon Sep 17 00:00:00 2001 From: Jonas Gessner Date: Tue, 13 Jul 2021 19:13:51 +0200 Subject: [Feature] Key Overrides (#11422) --- common_features.mk | 5 + docs/_summary.md | 1 + docs/config_options.md | 4 + docs/feature_key_overrides.md | 229 +++++++++ docs/syllabus.md | 1 + docs/understanding_qmk.md | 1 + quantum/process_keycode/process_key_override.c | 518 +++++++++++++++++++++ quantum/process_keycode/process_key_override.h | 147 ++++++ .../process_keycode/process_key_override_private.h | 24 + quantum/quantum.c | 19 +- quantum/quantum.h | 4 + quantum/quantum_keycodes.h | 5 + show_options.mk | 1 + tmk_core/common/action_util.c | 28 ++ 14 files changed, 984 insertions(+), 3 deletions(-) create mode 100644 docs/feature_key_overrides.md create mode 100644 quantum/process_keycode/process_key_override.c create mode 100644 quantum/process_keycode/process_key_override.h create mode 100644 quantum/process_keycode/process_key_override_private.h (limited to 'tmk_core') diff --git a/common_features.mk b/common_features.mk index 8080113efd..74b94ecd77 100644 --- a/common_features.mk +++ b/common_features.mk @@ -335,6 +335,11 @@ ifeq ($(strip $(PRINTING_ENABLE)), yes) SRC += $(TMK_DIR)/protocol/serial_uart.c endif +ifeq ($(strip $(KEY_OVERRIDE_ENABLE)), yes) + OPT_DEFS += -DKEY_OVERRIDE_ENABLE + SRC += $(QUANTUM_DIR)/process_keycode/process_key_override.c +endif + ifeq ($(strip $(SERIAL_LINK_ENABLE)), yes) SERIAL_SRC := $(wildcard $(SERIAL_PATH)/protocol/*.c) SERIAL_SRC += $(wildcard $(SERIAL_PATH)/system/*.c) diff --git a/docs/_summary.md b/docs/_summary.md index 4141e01e77..6c39aeda09 100644 --- a/docs/_summary.md +++ b/docs/_summary.md @@ -77,6 +77,7 @@ * [Combos](feature_combo.md) * [Debounce API](feature_debounce_type.md) * [Key Lock](feature_key_lock.md) + * [Key Overrides](feature_key_overrides.md) * [Layers](feature_layers.md) * [One Shot Keys](one_shot_keys.md) * [Pointing Device](feature_pointing_device.md) diff --git a/docs/config_options.md b/docs/config_options.md index 980195ac68..0c98b31010 100644 --- a/docs/config_options.md +++ b/docs/config_options.md @@ -195,6 +195,8 @@ If you define these options you will enable the associated feature, which may in * Sets the delay between `register_code` and `unregister_code`, if you're having issues with it registering properly (common on VUSB boards). The value is in milliseconds. * `#define TAP_HOLD_CAPS_DELAY 80` * Sets the delay for Tap Hold keys (`LT`, `MT`) when using `KC_CAPSLOCK` keycode, as this has some special handling on MacOS. The value is in milliseconds, and defaults to 80 ms if not defined. For macOS, you may want to set this to 200 or higher. +* `#define KEY_OVERRIDE_REPEAT_DELAY 500` + * Sets the key repeat interval for [key overrides](feature_key_overrides.md). ## RGB Light Configuration @@ -400,6 +402,8 @@ Use these to enable or disable building certain features. The more you have enab * USB N-Key Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work * `AUDIO_ENABLE` * Enable the audio subsystem. +* `KEY_OVERRIDE_ENABLE` + * Enable the key override feature * `RGBLIGHT_ENABLE` * Enable keyboard underlight functionality * `LEADER_ENABLE` diff --git a/docs/feature_key_overrides.md b/docs/feature_key_overrides.md new file mode 100644 index 0000000000..861c4bef5d --- /dev/null +++ b/docs/feature_key_overrides.md @@ -0,0 +1,229 @@ +# Key Overrides + +Key overrides allow you to override modifier-key combinations to send a different modifier-key combination or perform completely custom actions. Don't want `shift` + `1` to type `!` on your computer? Use a key override to make your keyboard type something different when you press `shift` + `1`. The general behavior is like this: If `modifiers w` + `key x` are pressed, replace these keys with `modifiers y` + `key z` in the keyboard report. + +You can use key overrides in a similar way to momentary layer/fn keys to activate custom keycodes/shortcuts, with a number of benefits: You completely keep the original use of the modifier keys, while being able to save space by removing fn keys from your keyboard. You can also easily configure _combinations of modifiers_ to trigger different actions than individual modifiers, and much more. The possibilities are quite vast and this documentation contains a few examples for inspiration throughout. + +##### A few more examples to get started: You could use key overrides to... +- Send `brightness up/down` when pressing `ctrl` + `volume up/down`. +- Send `delete` when pressing `shift` + `backspace`. +- Create custom shortcuts or change existing ones: E.g. Send `ctrl`+`shift`+`z` when `ctrl`+`y` is pressed. +- Run custom code when `ctrl` + `alt` + `esc` is pressed. + +## Setup + +To enable this feature, you need to add `KEY_OVERRIDE_ENABLE = yes` to your `rules.mk`. + +Then, in your `keymap.c` file, you'll need to define the array `key_overrides`, which defines all key overrides to be used. Each override is a value of type `key_override_t`. The array `key_overrides` is `NULL`-terminated and contains pointers to `key_override_t` values (`const key_override_t **`). + +## Creating Key Overrides + +The `key_override_t` struct has many options that allow you to precisely tune your overrides. The full reference is shown below. Instead of manually creating a `key_override_t` value, it is recommended to use these dedicated initializers: + +#### `ko_make_basic(modifiers, key, replacement)` +Returns a `key_override_t`, which sends `replacement` (can be a key-modifer combination), when `key` and `modifiers` are all pressed down. This override still activates if any additional modifiers not specified in `modifiers` are also pressed down. See `ko_make_with_layers_and_negmods` to customize this behavior. + +#### `ko_make_with_layers(modifiers, key, replacement, layers)` +Additionally takes a bitmask `layers` that defines on which layers the override is used. + +#### `ko_make_with_layers_and_negmods(modifiers, key, replacement, layers, negative_mods)` +Additionally takes a bitmask `negative_mods` that defines which modifiers may not be pressed for this override to activate. + +#### `ko_make_with_layers_negmods_and_options(modifiers, key, replacement, layers, negative_mods, options)` +Additionally takes a bitmask `options` that specifies additional options. See `ko_option_t` for available options. + +For more customization possibilities, you may directly create a `key_override_t`, which allows you to customize even more behavior. Read further below for details and examples. + +## Simple Example + +This shows how the mentioned example of sending `delete` when `shift` + `backspace` are pressed is realized: + +```c +const key_override_t delete_key_override = ko_make_basic(MOD_MASK_SHIFT, KC_BSPACE, KC_DELETE); + +// This globally defines all key overrides to be used +const key_override_t **key_overrides = (const key_override_t *[]){ + &delete_key_override, + NULL // Null terminate the array of overrides! +}; +``` + +## Intermediate Difficulty Examples + +### Media Controls & Screen Brightness + +In this example a single key is configured to control media, volume and screen brightness by using key overrides. + +- The key is set to send `play/pause` in the keymap. + +The following key overrides will be configured: + +- `Ctrl` + `play/pause` will send `next track`. +- `Ctrl` + `Shift` + `play/pause` will send `previous track`. +- `Alt` + `play/pause` will send `volume up`. +- `Alt` + `Shift` + `play/pause` will send `volume down`. +- `Ctrl` + `Alt` + `play/pause` will send `brightness up`. +- `Ctrl` + `Alt` + `Shift` + `play/pause` will send `brightness down`. + + +```c +const key_override_t next_track_override = + ko_make_with_layers_negmods_and_options( + MOD_MASK_CTRL, // Trigger modifiers: ctrl + KC_MPLY, // Trigger key: play/pause + KC_MNXT, // Replacement key + ~0, // Activate on all layers + MOD_MASK_SA, // Do not activate when shift or alt are pressed + ko_option_no_reregister_trigger); // Specifies that the play key is not registered again after lifting ctrl + +const key_override_t prev_track_override = ko_make_with_layers_negmods_and_options(MOD_MASK_CS, KC_MPLY, + KC_MPRV, ~0, MOD_MASK_ALT, ko_option_no_reregister_trigger); + +const key_override_t vol_up_override = ko_make_with_layers_negmods_and_options(MOD_MASK_ALT, KC_MPLY, + KC_VOLU, ~0, MOD_MASK_CS, ko_option_no_reregister_trigger); + +const key_override_t vol_down_override = ko_make_with_layers_negmods_and_options(MOD_MASK_SA, KC_MPLY, + KC_VOLD, ~0, MOD_MASK_CTRL, ko_option_no_reregister_trigger); + +const key_override_t brightness_up_override = ko_make_with_layers_negmods_and_options(MOD_MASK_CA, KC_MPLY, + KC_BRIU, ~0, MOD_MASK_SHIFT, ko_option_no_reregister_trigger); + +const key_override_t brightness_down_override = ko_make_basic(MOD_MASK_CSA, KC_MPLY, KC_BRID); + +// This globally defines all key overrides to be used +const key_override_t **key_overrides = (const key_override_t *[]){ + &next_track_override, + &prev_track_override, + &vol_up_override, + &vol_down_override, + &brightness_up_override, + &brightness_down_override, + NULL +}; +``` + +### Flexible macOS-friendly Grave Escape +The [Grave Escape feature](https://docs.qmk.fm/using-qmk/advanced-keycodes/feature_grave_esc) is limited in its configurability and has [bugs when used on macOS](https://docs.qmk.fm/using-qmk/advanced-keycodes/feature_grave_esc#caveats). Key overrides can be used to achieve a similar functionality as Grave Escape, but with more customization and without bugs on macOS. + +```c +// Shift + esc = ~ +const key_override_t tilde_esc_override = ko_make_basic(MOD_MASK_SHIFT, KC_ESC, S(KC_GRAVE)); + +// GUI + esc = ` +const key_override_t grave_esc_override = ko_make_basic(MOD_MASK_GUI, KC_ESC, KC_GRAVE); + +const key_override_t **key_overrides = (const key_override_t *[]){ + &tilde_esc_override, + &grave_esc_override, + NULL +}; +``` + +In addition to not encountering unexpected bugs on macOS, you can also change the behavior as you wish. Instead setting `GUI` + `ESC` = `` ` `` you may change it to an arbitrary other modifier, for example `Ctrl` + `ESC` = `` ` ``. + +## Advanced Examples +### Modifiers as Layer Keys + +Do you really need a dedicated key to toggle your fn layer? With key overrides, perhaps not. This example shows how you can configure to use `rGUI` + `rAlt` (right GUI and right alt) to access a momentary layer like an fn layer. With this you completely eliminate the need to use a dedicated layer key. Of course the choice of modifier keys can be changed as needed, `rGUI` + `rAlt` is just an example here. + +```c +// This is called when the override activates and deactivates. Enable the fn layer on activation and disable on deactivation +bool momentary_layer(bool key_down, void *layer) { + if (key_down) { + layer_on((uint8_t)(uintptr_t)layer); + } else { + layer_off((uint8_t)(uintptr_t)layer); + } + + return false; +} + +const key_override_t fn_override = {.trigger_mods = MOD_BIT(KC_RGUI) | MOD_BIT(KC_RCTL), // + .layers = ~(1 << LAYER_FN), // + .suppressed_mods = MOD_BIT(KC_RGUI) | MOD_BIT(KC_RCTL), // + .options = ko_option_no_unregister_on_other_key_down, // + .negative_mod_mask = (uint8_t) ~(MOD_BIT(KC_RGUI) | MOD_BIT(KC_RCTL)), // + .custom_action = momentary_layer, // + .context = (void *)LAYER_FN, // + .trigger = KC_NO, // + .replacement = KC_NO, // + .enabled = NULL}; +``` + +## Keycodes + +You can enable, disable and toggle all key overrides on the fly. + +|Keycode |Description |Function Equivalent| +|----------|---------------------------------|--------| +|`KEY_OVERRIDE_ON` |Turns on Key Override feature | `key_override_on(void)`| +|`KEY_OVERRIDE_OFF` |Turns off Key Override feature |`key_override_off(void)`| +|`KEY_OVERRIDE_TOGGLE` |Toggles Key Override feature on and off |`key_override_toggle(void)`| + +## Reference for `key_override_t` + +Advanced users may need more customization than what is offered by the simple `ko_make` initializers. For this, directly create a `key_override_t` value and set all members. Below is a reference for all members of `key_override_t`. + +| Member | Description | +|--------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `uint16_t trigger` | The non-modifier keycode that triggers the override. This keycode, and the necessary modifiers (`trigger_mods`) must be pressed to activate this override. Set this to the keycode of the key that should activate the override. Set to `KC_NO` to require only the necessary modifiers to be pressed and no non-modifier. | +| `uint8_t trigger_mods` | Which mods need to be down for activation. If both sides of a modifier are set (e.g. left ctrl and right ctrl) then only one is required to be pressed (e.g. left ctrl suffices). Use the `MOD_MASK_XXX` and `MOD_BIT()` macros for this. | +| `layer_state_t layers` | This is a BITMASK (!), defining which layers this override applies to. To use this override on layer i set the ith bit `(1 << i)`. | +| `uint8_t negative_mod_mask` | Which modifiers cannot be down. It must hold that `(active_modifiers & negative_mod_mask) == 0`, otherwise the key override will not be activated. An active override will be deactivated once this is no longer true. | +| `uint8_t suppressed_mods` | Modifiers to 'suppress' while the override is active. To suppress a modifier means that even though the modifier key is held down, the host OS sees the modifier as not pressed. Can be used to suppress the trigger modifiers, as a trivial example. | +| `uint16_t replacement` | The complex keycode to send as replacement when this override is triggered. This can be a simple keycode, a key-modifier combination (e.g. `C(KC_A)`), or `KC_NO` (to register no replacement keycode). Use in combination with suppressed_mods to get the correct modifiers to be sent. | +| `ko_option_t options` | Options controlling the behavior of the override, such as what actions are allowed to activate the override. | +| `bool (*custom_action)(bool activated, void *context)` | If not NULL, this function will be called right before the replacement key is registered, along with the provided context and a flag indicating whether the override was activated or deactivated. This function allows you to run some custom actions for specific key overrides. If you return `false`, the replacement key is not registered/unregistered as it would normally. Return `true` to register and unregister the override normally. | +| `void *context` | A context that will be passed to the custom action function. | +| `bool *enabled` | If this points to false this override will not be used. Set to NULL to always have this override enabled. | + +### Reference for `ko_option_t` + +Bitfield with various options controlling the behavior of a key override. + +| Value | Description | +|------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `ko_option_activation_trigger_down` | Allow activating when the trigger key is pressed down. | +| `ko_option_activation_required_mod_down` | Allow activating when a necessary modifier is pressed down. | +| `ko_option_activation_negative_mod_up` | Allow activating when a negative modifier is released. | +| `ko_option_one_mod` | If set, any of the modifiers in `trigger_mods` will be enough to activate the override (logical OR of modifiers). If not set, all the modifiers in `trigger_mods` have to be pressed (logical AND of modifiers). | +| `ko_option_no_unregister_on_other_key_down` | If set, the override will not deactivate when another key is pressed down. Use only if you really know you need this. | +| `ko_option_no_reregister_trigger` | If set, the trigger key will never be registered again after the override is deactivated. | +| `ko_options_default` | The default options used by the `ko_make_xxx` functions | + +## For Advanced Users: Inner Workings + +This section explains how a key override works in detail, explaining where each member of `key_override_t` comes into play. Understanding this is essential to be able to take full advantage of all the options offered by key overrides. + +#### Activation + +When the necessary keys are pressed (`trigger_mods` + `trigger`), the override is 'activated' and the replacement key is registered in the keyboard report (`replacement`), while the `trigger` key is removed from the keyboard report. The trigger modifiers may also be removed from the keyboard report upon activation of an override (`suppressed_mods`). The override will not activate if any of the `negative_modifiers` are pressed. + +Overrides can activate in three different cases: + +1. The trigger key is pressed down and necessary modifiers are already down. +2. A necessary modifier is pressed down, while the trigger key and other necessary modifiers are already down. +3. A negative modifier is released, while all necessary modifiers and the trigger key are already down. + +Use the `option` member to customize which of these events are allowed to activate your overrides (default: all three). + +In any case, a key override can only activate if the `trigger` key is the _last_ non-modifier key that was pressed down. This emulates the behavior of how standard OSes (macOS, Windows, Linux) handle normal key input (to understand: Hold down `a`, then also hold down `b`, then hold down `shift`; `B` will be typed but not `A`). + +#### Deactivation + +An override is 'deactivated' when one of the trigger keys (`trigger_mods`, `trigger`) is lifted, another non-modifier key is pressed down, or one of the `negative_modifiers` is pressed down. When an override deactivates, the `replacement` key is removed from the keyboard report, while the `suppressed_mods` that are still held down are re-added to the keyboard report. By default, the `trigger` key is re-added to the keyboard report if it is still held down and no other non-modifier key has been pressed since. This again emulates the behavior of how standard OSes handle normal key input (To understand: hold down `a`, then also hold down `b`, then also `shift`, then release `b`; `A` will not be typed even though you are holding the `a` and `shift` keys). Use the `option` field `ko_option_no_reregister_trigger` to prevent re-registering the trigger key in all cases. + +#### Key Repeat Delay + +A third way in which standard OS-handling of modifier-key input is emulated in key overrides is with a ['key repeat delay'](https://www.dummies.com/computers/pcs/set-your-keyboards-repeat-delay-and-repeat-rate/). To explain what this is, let's look at how normal keyboard input is handled by mainstream OSes again: If you hold down `a`, followed by `shift`, you will see the letter `a` is first typed, then for a short moment nothing is typed and then repeating `A`s are typed. Take note that, although shift is pressed down just after `a` is pressed, it takes a moment until `A` is typed. This is caused by the aforementioned key repeat delay, and it is a feature that prevents unwanted repeated characters from being typed. + +This applies equally to releasing a modifier: When you hold `shift`, then press `a`, the letter `A` is typed. Now if you release `shift` first, followed by `a` shortly after, you will not see the letter `a` being typed, even though for a short moment of time you were just holding down the key `a`. This is because no modified characters are typed until the key repeat delay has passed. + + This exact behavior is implemented in key overrides as well: If a key override for `shift` + `a` = `b` exists, and `a` is pressed and held, followed by `shift`, you will not immediately see the letter `b` being typed. Instead, this event is deferred for a short moment, until the key repeat delay has passed, measured from the moment when the trigger key (`a`) was pressed down. + +The duration of the key repeat delay is controlled with the `KEY_OVERRIDE_REPEAT_DELAY` macro. Define this value in your `config.h` file to change it. It is 500ms by default. + + +## Difference to Combos + +Note that key overrides are very different from [combos](https://docs.qmk.fm/#/feature_combo). Combos require that you press down several keys almost _at the same time_ and can work with any combination of non-modifier keys. Key overrides work like keyboard shortcuts (e.g. `ctrl` + `z`): They take combinations of _multiple_ modifiers and _one_ non-modifier key to then perform some custom action. Key overrides are implemented with much care to behave just like normal keyboard shortcuts would in regards to the order of pressed keys, timing, and interacton with other pressed keys. There are a number of optional settings that can be used to really fine-tune the behavior of each key override as well. Using key overrides also does not delay key input for regular key presses, which inherently happens in combos and may be undesirable. diff --git a/docs/syllabus.md b/docs/syllabus.md index ec7f66ba78..b33bd9e727 100644 --- a/docs/syllabus.md +++ b/docs/syllabus.md @@ -40,6 +40,7 @@ These topics start to dig into some of the features that QMK supports. You don't * [Tap Dance](feature_tap_dance.md) * [Combos](feature_combo.md) * [Userspace](feature_userspace.md) + * [Key Overrides](feature_key_overrides.md) # Advanced Topics diff --git a/docs/understanding_qmk.md b/docs/understanding_qmk.md index 331b1c893c..e3dd5cb780 100644 --- a/docs/understanding_qmk.md +++ b/docs/understanding_qmk.md @@ -146,6 +146,7 @@ The `process_record()` function itself is deceptively simple, but hidden within * [`bool process_audio(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_audio.c#L19) * [`bool process_steno(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_steno.c#L160) * [`bool process_music(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_music.c#L114) + * [`bool process_key_override(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/5a1b857dea45a17698f6baa7dd1b7a7ea907fb0a/quantum/process_keycode/process_key_override.c#L397) * [`bool process_tap_dance(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_tap_dance.c#L141) * [`bool process_unicode_common(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_unicode_common.c#L169) calls one of: diff --git a/quantum/process_keycode/process_key_override.c b/quantum/process_keycode/process_key_override.c new file mode 100644 index 0000000000..fe43eacc40 --- /dev/null +++ b/quantum/process_keycode/process_key_override.c @@ -0,0 +1,518 @@ +/* + * Copyright 2021 Jonas Gessner + * + * 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 . + */ + +#include "quantum.h" +#include "report.h" +#include "timer.h" +#include "process_key_override_private.h" + +#include + +#ifndef KEY_OVERRIDE_REPEAT_DELAY +# define KEY_OVERRIDE_REPEAT_DELAY 500 +#endif + +// For benchmarking the time it takes to call process_key_override on every key press (needs keyboard debugging enabled as well) +// #define BENCH_KEY_OVERRIDE + +// For debug output (needs keyboard debugging enabled as well) +// #define DEBUG_KEY_OVERRIDE + +#ifdef DEBUG_KEY_OVERRIDE +# define key_override_printf dprintf +#else +# define key_override_printf(str, ...) \ + {} +#endif + +// Helpers + +// Private functions implemented elsewhere in qmk/tmk +extern uint8_t extract_mod_bits(uint16_t code); +extern void set_weak_override_mods(uint8_t mods); +extern void clear_weak_override_mods(void); +extern void set_suppressed_override_mods(uint8_t mods); +extern void clear_suppressed_override_mods(void); + +static uint16_t clear_mods_from(uint16_t keycode) { + switch (keycode) { + case QK_MODS ... QK_MODS_MAX: + break; + default: + return keycode; + } + + static const uint16_t all_mods = QK_LCTL | QK_LSFT | QK_LALT | QK_LGUI | QK_RCTL | QK_RSFT | QK_RALT | QK_RGUI; + + return (keycode & ~(all_mods)); +} + +// Internal variables +static const key_override_t *active_override = NULL; +static bool active_override_trigger_is_down = false; + +// Used to keep track of what non-modifier key was last pressed down. We never want to activate an override for a trigger key that is not the last non-mod key that was pressed down. OSes internally completely unregister a key that is held when a different key is held down after. We want to respect this here. +static uint16_t last_key_down = 0; +// When was the last key pressed down? +static uint32_t last_key_down_time = 0; + +// What timestamp are we comparing to when waiting to register a deferred key? +static uint32_t defer_reference_time = 0; +// What delay should pass until deferred key is registered? +static uint32_t defer_delay = 0; + +// Holds the keycode that should be registered at a later time, in order to not get false key presses +static uint16_t deferred_register = 0; + +// TODO: in future maybe save in EEPROM? +static bool enabled = true; + +// Public variables +__attribute__((weak)) const key_override_t **key_overrides = NULL; + +// Forward decls +static const key_override_t *clear_active_override(const bool allow_reregister); + +void key_override_on(void) { + enabled = true; + key_override_printf("Key override ON\n"); +} + +void key_override_off(void) { + enabled = false; + clear_active_override(false); + key_override_printf("Key override OFF\n"); +} + +void key_override_toggle(void) { + if (key_override_is_enabled()) { + key_override_off(); + } else { + key_override_on(); + } +} + +bool key_override_is_enabled(void) { return enabled; } + +// Returns whether the modifiers that are pressed are such that the override should activate +static bool key_override_matches_active_modifiers(const key_override_t *override, const uint8_t mods) { + // Check that negative keys pass + if ((override->negative_mod_mask & mods) != 0) { + return false; + } + + // Immediately return true if the override requires no mods down + if (override->trigger_mods == 0) { + return true; + } + + if ((override->options & ko_option_one_mod) != 0) { + // At least one of the trigger modifiers must be down + return (override->trigger_mods & mods) != 0; + } else { + // All trigger modifiers must be down, but each mod can be active on either side (if both sides are specified). + + // Which mods, regardless of side, are required? + uint8_t one_sided_required_mods = (override->trigger_mods & 0b1111) | (override->trigger_mods >> 4); + + // Which of the required modifiers are active? + uint8_t active_required_mods = override->trigger_mods & mods; + + // Move the active requird mods to one side + uint8_t one_sided_active_required_mods = (active_required_mods & 0b1111) | (active_required_mods >> 4); + + // Check that there is a full match between the required one-sided mods and active required one sided mods + return one_sided_active_required_mods == one_sided_required_mods; + } + + return false; +} + +static void schedule_deferred_register(const uint16_t keycode) { + if (timer_elapsed32(last_key_down_time) < KEY_OVERRIDE_REPEAT_DELAY) { + // Defer until KEY_OVERRIDE_REPEAT_DELAY has passed since the trigger key was pressed down. This emulates the behavior as holding down a key x, then holding down shift shortly after. Usually the shifted key X is not immediately produced, but rather a 'key repeat delay' passes before any repeated character is output. + defer_reference_time = last_key_down_time; + defer_delay = KEY_OVERRIDE_REPEAT_DELAY; + } else { + // Wait a very short time when a modifier event triggers the override to avoid false activations when e.g. a modifier is pressed just before a key is released (with the intention of pairing the modifier with a different key), or a modifier is lifted shortly before the trigger key is lifted. Operating systems by default reject modifier-events that happen very close to a non-modifier event. + defer_reference_time = timer_read32(); + defer_delay = 50; // 50ms + } + deferred_register = keycode; +} + +const key_override_t *clear_active_override(const bool allow_reregister) { + if (active_override == NULL) { + return NULL; + } + + key_override_printf("Deactivating override\n"); + + deferred_register = 0; + + // Clear the suppressed mods + clear_suppressed_override_mods(); + + // Unregister the replacement. First remove the weak override mods + clear_weak_override_mods(); + + const key_override_t *const old = active_override; + + const uint8_t mod_free_replacement = clear_mods_from(active_override->replacement); + + bool unregister_replacement = mod_free_replacement != KC_NO && // KC_NO is never registered + mod_free_replacement < SAFE_RANGE; // Custom keycodes are never registered + + // Try firing the custom handler + if (active_override->custom_action != NULL) { + unregister_replacement &= active_override->custom_action(false, active_override->context); + } + + // Then unregister the mod-free replacement key if desired + if (unregister_replacement) { + if (IS_KEY(mod_free_replacement)) { + del_key(mod_free_replacement); + } else { + key_override_printf("NOT KEY 1\n"); + send_keyboard_report(); + unregister_code(mod_free_replacement); + } + } + + const uint16_t trigger = active_override->trigger; + + const bool reregister_trigger = allow_reregister && // Check if allowed from caller + (active_override->options & ko_option_no_reregister_trigger) == 0 && // Check if override allows + active_override_trigger_is_down && // Check if trigger is even down + trigger != KC_NO && // KC_NO is never registered + trigger < SAFE_RANGE; // A custom keycode should not be registered + + // Optionally re-register the trigger if it is still down + if (reregister_trigger) { + key_override_printf("Re-registering trigger deferred: %u\n", trigger); + + // This will always be a modifier event, so defer always + schedule_deferred_register(trigger); + } + + send_keyboard_report(); + + active_override = NULL; + active_override_trigger_is_down = false; + + return old; +} + +/** Checks if the key event is an allowed activation event for the provided override. Does not check things like whether the correct mods or correct trigger key is down. */ +static bool check_activation_event(const key_override_t *override, const bool key_down, const bool is_mod) { + ko_option_t options = override->options; + + if ((options & ko_options_all_activations) == 0) { + // No activation option provided at all. This is wrong, but let's assume the default activations (ko_options_all_activations) were meant... + options = ko_options_all_activations; + } + + if (is_mod) { + if (key_down) { + return (options & ko_option_activation_required_mod_down) != 0; + } else { + return (options & ko_option_activation_negative_mod_up) != 0; + } + } else { + if (key_down) { + return (options & ko_option_activation_trigger_down) != 0; + } else { + return false; + } + } +} + +/** Iterates through the list of key overrides and tries activating each, until it finds one that activates or reaches the end of overrides. Returns true if the key action for `keycode` should be sent */ +static bool try_activating_override(const uint16_t keycode, const uint8_t layer, const bool key_down, const bool is_mod, const uint8_t active_mods, bool *activated) { + if (key_overrides == NULL) { + return true; + } + + for (uint8_t i = 0;; i++) { + const key_override_t *const override = key_overrides[i]; + + // End of array + if (override == NULL) { + break; + } + + // Fast, but not full mods check. Most key presses will not have any mods down, and most overrides will require mods. Hence here we filter overrides that require mods to be down while no mods are down + if (active_mods == 0 && override->trigger_mods != 0) { + key_override_printf("Not activating override: Modifiers don't match\n"); + continue; + } + + // Check layer + if ((override->layers & (1 << layer)) == 0) { + key_override_printf("Not activating override: Not set to activate on pressed layer\n"); + continue; + } + + // Check allowed activation events + if (!check_activation_event(override, key_down, is_mod)) { + key_override_printf("Not activating override: Activation event not allowed\n"); + continue; + } + + const bool is_trigger = override->trigger == keycode; + + // Check if trigger lifted. This is a small optimization in order to skip the remaining checks + if (is_trigger && !key_down) { + key_override_printf("Not activating override: Trigger lifted\n"); + continue; + } + + // If the trigger is KC_NO it means 'no key', so only the required modifiers need to be down. + const bool no_trigger = override->trigger == KC_NO; + + // Check if aleady active + if (override == active_override) { + key_override_printf("Not activating override: Alerady actived\n"); + continue; + } + + // Check if enabled + if (override->enabled != NULL && !((*(override->enabled) & 1))) { + key_override_printf("Not activating override: Not enabled\n"); + continue; + } + + // Check mods precisely + if (!key_override_matches_active_modifiers(override, active_mods)) { + key_override_printf("Not activating override: Modifiers don't match\n"); + continue; + } + + // Check if trigger key is down. + const bool trigger_down = is_trigger && key_down; + + // At this point, all requirements for activation are checked, except whether the trigger key is pressed. Now we check if the required trigger is down + // If no trigger key is required, yes. + // If the trigger was just pressed, yes. + // If the last non-mod key that was pressed down is the trigger key, yes. + bool should_activate = no_trigger || trigger_down || last_key_down == override->trigger; + + if (!should_activate) { + key_override_printf("Not activating override. Trigger not down\n"); + continue; + } + + key_override_printf("Activating override\n"); + + clear_active_override(false); + + active_override = override; + active_override_trigger_is_down = true; + + set_suppressed_override_mods(override->suppressed_mods); + + if (!trigger_down && !no_trigger) { + // When activating a key override the trigger is is always unregistered. In the case where the key that newly pressed is not the trigger key, we have to explicitly remove the trigger key from the keyboard report. If the trigger was just pressed down we simply suppress the event which also has the effect of the trigger key not being registered in the keyboard report. + if (IS_KEY(override->trigger)) { + del_key(override->trigger); + } else { + unregister_code(override->trigger); + } + } + + const uint16_t mod_free_replacement = clear_mods_from(override->replacement); + + bool register_replacement = mod_free_replacement != KC_NO && // KC_NO is never registered + mod_free_replacement < SAFE_RANGE; // Custom keycodes are never registered + + // Try firing the custom handler + if (override->custom_action != NULL) { + register_replacement &= override->custom_action(true, override->context); + } + + if (register_replacement) { + const uint8_t override_mods = extract_mod_bits(override->replacement); + set_weak_override_mods(override_mods); + + // If this is a modifier event that activates the key override we _always_ defer the actual full activation of the override + if (is_mod) { + key_override_printf("Deferring register replacement key\n"); + schedule_deferred_register(mod_free_replacement); + send_keyboard_report(); + } else { + if (IS_KEY(mod_free_replacement)) { + add_key(mod_free_replacement); + } else { + key_override_printf("NOT KEY 2\n"); + send_keyboard_report(); + // On macOS there seems to be a race condition when it comes to the keyboard report and consumer keycodes. It seems the OS may recognize a consumer keycode before an updated keyboard report, even if the keyboard report is actually sent before the consumer key. I assume it is some sort of race condition because it happens infrequently and very irregularly. Waiting for about at least 10ms between sending the keyboard report and sending the consumer code has shown to fix this. + wait_ms(10); + register_code(mod_free_replacement); + } + } + } else { + // If not registering the replacement key send keyboard report to update the unregistered keys. + send_keyboard_report(); + } + + *activated = true; + + // If the trigger is down, suppress the event so that it does not get added to the keyboard report. + return !trigger_down; + } + + *activated = false; + + return true; +} + +void matrix_scan_key_override(void) { + if (deferred_register == 0) { + return; + } + + if (timer_elapsed32(defer_reference_time) >= defer_delay) { + key_override_printf("Registering deferred key\n"); + register_code16(deferred_register); + deferred_register = 0; + defer_reference_time = 0; + defer_delay = 0; + } +} + +bool process_key_override(const uint16_t keycode, const keyrecord_t *const record) { +#ifdef BENCH_KEY_OVERRIDE + uint16_t start = timer_read(); +#endif + + const bool key_down = record->event.pressed; + const bool is_mod = IS_MOD(keycode); + + if (key_down) { + switch (keycode) { + case KEY_OVERRIDE_TOGGLE: + key_override_toggle(); + return false; + + case KEY_OVERRIDE_ON: + key_override_on(); + return false; + + case KEY_OVERRIDE_OFF: + key_override_off(); + return false; + + default: + break; + } + } + + if (!enabled) { + return true; + } + + uint8_t effective_mods = get_mods(); + +#ifdef KEY_OVERRIDE_INCLUDE_WEAK_MODS + effective_mods |= get_weak_mods(); +#endif + +#ifndef NO_ACTION_ONESHOT + // Locked one shot mods are added to get_mods(), I think (why??) while oneshot mods are in get_oneshot_mods(). Still OR with get_locked_oneshot_mods because that's where those mods _should_ be saved. + effective_mods |= get_oneshot_locked_mods() | get_oneshot_mods(); +#endif + + if (is_mod) { + // The mods returned from get_mods() will be updated with this new event _after_ this code runs. Hence we manually update the effective mods here to really know the effective mods. + if (key_down) { + effective_mods |= MOD_BIT(keycode); + } else { + effective_mods &= ~MOD_BIT(keycode); + } + } else { + if (key_down) { + last_key_down = keycode; + last_key_down_time = timer_read32(); + deferred_register = 0; + } + + // The last key that was pressed was just released. No more keys are therefore sending input + if (!key_down && keycode == last_key_down) { + last_key_down = 0; + last_key_down_time = 0; + // We also cancel any deferred registers because, again, no keys are sending any input. Only the last key that is pressed creates an input – this key was just lifted. + deferred_register = 0; + } + } + + key_override_printf("key down: %u keycode: %u is mod: %u effective mods: %u\n", key_down, keycode, is_mod, effective_mods); + + bool send_key_action = true; + bool activated = false; + + // Non-mod key up events never activate a key override + if (is_mod || key_down) { + // Get the exact layer that was hit. It will be cached at this point + const uint8_t layer = read_source_layers_cache(record->event.key); + + // Use blocked to ensure the same override is not activated again immediately after it is deactivated + send_key_action = try_activating_override(keycode, layer, key_down, is_mod, effective_mods, &activated); + + if (!send_key_action) { + send_keyboard_report(); + } + } + + if (!activated && active_override != NULL) { + if (is_mod) { + // Check if necessary modifier of current override goes up or a negative mod goes down + if (!key_override_matches_active_modifiers(active_override, effective_mods)) { + key_override_printf("Deactivating override because necessary modifier lifted or negative mod pressed\n"); + clear_active_override(true); + } + } else { + // Check if trigger of current override goes up or if override does not allow additional keys to be down and another key goes down + const bool is_trigger = keycode == active_override->trigger; + bool should_deactivate = false; + + // Check if trigger key lifted + if (is_trigger && !key_down) { + should_deactivate = true; + active_override_trigger_is_down = false; + key_override_printf("Deactivating override because trigger key up\n"); + } + + // Check if another key was pressed + if (key_down && (active_override->options & ko_option_no_unregister_on_other_key_down) == 0) { + should_deactivate = true; + key_override_printf("Deactivating override because another key was pressed\n"); + } + + if (should_deactivate) { + clear_active_override(false); + } + } + } + +#ifdef BENCH_KEY_OVERRIDE + uint16_t elapsed = timer_elapsed(start); + + dprintf("Processing key overrides took: %u ms\n", elapsed); +#endif + + return send_key_action; +} diff --git a/quantum/process_keycode/process_key_override.h b/quantum/process_keycode/process_key_override.h new file mode 100644 index 0000000000..9ba59e4e9b --- /dev/null +++ b/quantum/process_keycode/process_key_override.h @@ -0,0 +1,147 @@ +/* + * Copyright 2021 Jonas Gessner + * + * 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 . + */ + +#pragma once + +#include +#include +#include + +#include "action_layer.h" + +/** + * Key overrides allow you to send a different key-modifier combination or perform a custom action when a certain modifier-key combination is pressed. + * + * For example, you may configure a key override to send the delete key when shift + backspace are pressed together, or that your volume keys become screen brightness keys when holding ctrl. The possibilities are quite vast and the documentation contains a few examples for inspiration. + * + * See the documentation and examples here: https://docs.qmk.fm/#/feature_key_overrides + */ + +/** Bitfield with various options controlling the behavior of a key override. */ +typedef enum { + /** Allow activating when the trigger key is pressed down. */ + ko_option_activation_trigger_down = (1 << 0), + /** Allow activating when a necessary modifier is pressed down. */ + ko_option_activation_required_mod_down = (1 << 1), + /** Allow activating when a negative modifier is released. */ + ko_option_activation_negative_mod_up = (1 << 2), + + ko_options_all_activations = ko_option_activation_negative_mod_up | ko_option_activation_required_mod_down | ko_option_activation_trigger_down, + + /** If set, any of the modifiers in trigger_mods will be enough to activate the override (logical OR of modifiers). If not set, all the modifiers in trigger_mods have to be pressed (logical AND of modifiers). */ + ko_option_one_mod = (1 << 3), + + /** If set, the trigger key will never be registered again after the override is deactivated. */ + ko_option_no_reregister_trigger = (1 << 4), + + /** If set, the override will not deactivate when another key is pressed down. Use only if you really know you need this. */ + ko_option_no_unregister_on_other_key_down = (1 << 5), + + /** The default options used by the ko_make_xxx functions. */ + ko_options_default = ko_options_all_activations, +} ko_option_t; + +/** Defines a single key override */ +typedef struct { + // The non-modifier keycode that triggers the override. This keycode, and the necessary modifiers (trigger_mods) must be pressed to activate this override. Set this to the keycode of the key that should activate the override. Set to KC_NO to require only the necessary modifiers to be pressed and no non-modifier. + uint16_t trigger; + + // Which mods need to be down for activation. If both sides of a modifier are set (e.g. left ctrl and right ctrl) then only one is required to be pressed (e.g. left ctrl suffices). Use the MOD_MASK_XXX and MOD_BIT() macros for this. + uint8_t trigger_mods; + + // This is a BITMASK (!), defining which layers this override applies to. To use this override on layer i set the ith bit (1 << i). + layer_state_t layers; + + // Which modifiers cannot be down. It must hold that (active_mods & negative_mod_mask) == 0, otherwise the key override will not be activated. An active override will be deactivated once this is no longer true. + uint8_t negative_mod_mask; + + // Modifiers to 'suppress' while the override is active. To suppress a modifier means that even though the modifier key is held down, the host OS sees the modifier as not pressed. Can be used to suppress the trigger modifiers, as a trivial example. + uint8_t suppressed_mods; + + // The complex keycode to send as replacement when this override is triggered. This can be a simple keycode, a key-modifier combination (e.g. C(KC_A)), or KC_NO (to register no replacement keycode). Use in combination with suppressed_mods to get the correct modifiers to be sent. + uint16_t replacement; + + // Options controlling the behavior of the override, such as what actions are allowed to activate the override. + ko_option_t options; + + // If not NULL, this function will be called right before the replacement key is registered, along with the provided context and a flag indicating whether the override was activated or deactivated. This function allows you to run some custom actions for specific key overrides. If you return `false`, the replacement key is not registered/unregistered as it would normally. Return `true` to register and unregister the override normally. + bool (*custom_action)(bool activated, void *context); + + // A context that will be passed to the custom action function. + void *context; + + // If this points to false this override will not be used. Set to NULL to always have this override enabled. + bool *enabled; +} key_override_t; + +/** Define this as a null-terminated array of pointers to key overrides. These key overrides will be used by qmk. */ +extern const key_override_t **key_overrides; + +/** Turns key overrides on */ +extern void key_override_on(void); + +/** Turns key overrides off */ +extern void key_override_off(void); + +/** Toggles key overrides on */ +extern void key_override_toggle(void); + +/** Returns whether key overrides are enabled */ +extern bool key_override_is_enabled(void); + +/** + * Preferrably use these macros to create key overrides. They fix many of the options to a standard setting that should satisfy most basic use-cases. Only directly create a key_override_t struct when you really need to. + */ + +// clang-format off + +/** + * Convenience initializer to create a basic key override. Activates the override on all layers. + */ +#define ko_make_basic(trigger_mods, trigger_key, replacement_key) \ + ko_make_with_layers(trigger_mods, trigger_key, replacement_key, ~0) + +/** + * Convenience initializer to create a basic key override. Provide a bitmap (of type layer_state_t) with the bits set for each layer on which the override should activate. + */ +#define ko_make_with_layers(trigger_mods, trigger_key, replacement_key, layers) \ + ko_make_with_layers_and_negmods(trigger_mods, trigger_key, replacement_key, layers, 0) + +/** + * Convenience initializer to create a basic key override. Provide a bitmap with the bits set for each layer on which the override should activate. Also provide a negative modifier mask, that is used to define which modifiers may not be pressed. + */ +#define ko_make_with_layers_and_negmods(trigger_mods, trigger_key, replacement_key, layers, negative_mask) \ + ko_make_with_layers_negmods_and_options(trigger_mods, trigger_key, replacement_key, layers, negative_mask, ko_options_default) + + /** + * Convenience initializer to create a basic key override. Provide a bitmap with the bits set for each layer on which the override should activate. Also provide a negative modifier mask, that is used to define which modifiers may not be pressed. Provide options for additional control of the behavior of the override. + */ +#define ko_make_with_layers_negmods_and_options(trigger_mods_, trigger_key, replacement_key, layer_mask, negative_mask, options_) \ + ((const key_override_t){ \ + .trigger_mods = (trigger_mods_), \ + .layers = (layer_mask), \ + .suppressed_mods = (trigger_mods_), \ + .options = (options_), \ + .negative_mod_mask = (negative_mask), \ + .custom_action = NULL, \ + .context = NULL, \ + .trigger = (trigger_key), \ + .replacement = (replacement_key), \ + .enabled = NULL \ + }) + +// clang-format on diff --git a/quantum/process_keycode/process_key_override_private.h b/quantum/process_keycode/process_key_override_private.h new file mode 100644 index 0000000000..1d0e134a19 --- /dev/null +++ b/quantum/process_keycode/process_key_override_private.h @@ -0,0 +1,24 @@ +/* + * Copyright 2021 Jonas Gessner + * + * 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 . + */ + +#pragma once + +#include +#include "action.h" + +bool process_key_override(const uint16_t keycode, const keyrecord_t *const record); +void matrix_scan_key_override(void); diff --git a/quantum/quantum.c b/quantum/quantum.c index b4cfa28d7d..9cfffd9317 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -58,12 +58,16 @@ float bell_song[][2] = SONG(TERMINAL_SOUND); # include "process_auto_shift.h" #endif -static void do_code16(uint16_t code, void (*f)(uint8_t)) { +#ifdef KEY_OVERRIDE_ENABLE +# include "process_key_override_private.h" +#endif + +uint8_t extract_mod_bits(uint16_t code) { switch (code) { case QK_MODS ... QK_MODS_MAX: break; default: - return; + return 0; } uint8_t mods_to_send = 0; @@ -80,9 +84,11 @@ static void do_code16(uint16_t code, void (*f)(uint8_t)) { if (code & QK_LGUI) mods_to_send |= MOD_BIT(KC_LGUI); } - f(mods_to_send); + return mods_to_send; } +static void do_code16(uint16_t code, void (*f)(uint8_t)) { f(extract_mod_bits(code)); } + void register_code16(uint16_t code) { if (IS_MOD(code) || code == KC_NO) { do_code16(code, register_mods); @@ -243,6 +249,9 @@ bool process_record_quantum(keyrecord_t *record) { #if (defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC))) && !defined(NO_MUSIC_MODE) process_music(keycode, record) && #endif +#ifdef KEY_OVERRIDE_ENABLE + process_key_override(keycode, record) && +#endif #ifdef TAP_DANCE_ENABLE process_tap_dance(keycode, record) && #endif @@ -408,6 +417,10 @@ void matrix_scan_quantum() { matrix_scan_music(); #endif +#ifdef KEY_OVERRIDE_ENABLE + matrix_scan_key_override(); +#endif + #ifdef SEQUENCER_ENABLE matrix_scan_sequencer(); #endif diff --git a/quantum/quantum.h b/quantum/quantum.h index 66ba96fde8..673796e6b1 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h @@ -118,6 +118,10 @@ extern layer_state_t layer_state; # include "process_unicodemap.h" #endif +#ifdef KEY_OVERRIDE_ENABLE +# include "process_key_override.h" +#endif + #ifdef TAP_DANCE_ENABLE # include "process_tap_dance.h" #endif diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h index c361dd670e..3d2dbde922 100644 --- a/quantum/quantum_keycodes.h +++ b/quantum/quantum_keycodes.h @@ -514,6 +514,11 @@ enum quantum_keycodes { // RGB underglow/matrix (continued) RGB_MODE_TWINKLE, + // Key Overrides + KEY_OVERRIDE_TOGGLE, + KEY_OVERRIDE_ON, + KEY_OVERRIDE_OFF, + // Start of custom keycode range for keyboards and keymaps - always leave at the end SAFE_RANGE }; diff --git a/show_options.mk b/show_options.mk index af38bcb24b..dd1ad5171f 100644 --- a/show_options.mk +++ b/show_options.mk @@ -44,6 +44,7 @@ OTHER_OPTION_NAMES = \ AUTO_SHIFT_MODIFIERS \ COMBO_ENABLE \ KEY_LOCK_ENABLE \ + KEY_OVERRIDE_ENABLE \ LEADER_ENABLE \ PRINTING_ENABLE \ STENO_ENABLE \ diff --git a/tmk_core/common/action_util.c b/tmk_core/common/action_util.c index a57c8bf66a..2b3c00cba0 100644 --- a/tmk_core/common/action_util.c +++ b/tmk_core/common/action_util.c @@ -27,6 +27,10 @@ extern keymap_config_t keymap_config; static uint8_t real_mods = 0; static uint8_t weak_mods = 0; static uint8_t macro_mods = 0; +#ifdef KEY_OVERRIDE_ENABLE +static uint8_t weak_override_mods = 0; +static uint8_t suppressed_mods = 0; +#endif #ifdef USB_6KRO_ENABLE # define RO_ADD(a, b) ((a + b) % KEYBOARD_REPORT_KEYS) @@ -229,6 +233,7 @@ void send_keyboard_report(void) { keyboard_report->mods = real_mods; keyboard_report->mods |= weak_mods; keyboard_report->mods |= macro_mods; + #ifndef NO_ACTION_ONESHOT if (oneshot_mods) { # if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) @@ -244,6 +249,13 @@ void send_keyboard_report(void) { } #endif + +#ifdef KEY_OVERRIDE_ENABLE + // These need to be last to be able to properly control key overrides + keyboard_report->mods &= ~suppressed_mods; + keyboard_report->mods |= weak_override_mods; +#endif + host_keyboard_send(keyboard_report); } @@ -299,6 +311,22 @@ void set_weak_mods(uint8_t mods) { weak_mods = mods; } */ void clear_weak_mods(void) { weak_mods = 0; } +#ifdef KEY_OVERRIDE_ENABLE +/** \brief set weak mods used by key overrides. DO not call this manually + */ +void set_weak_override_mods(uint8_t mods) { weak_override_mods = mods; } +/** \brief clear weak mods used by key overrides. DO not call this manually + */ +void clear_weak_override_mods(void) { weak_override_mods = 0; } + +/** \brief set suppressed mods used by key overrides. DO not call this manually + */ +void set_suppressed_override_mods(uint8_t mods) { suppressed_mods = mods; } +/** \brief clear suppressed mods used by key overrides. DO not call this manually + */ +void clear_suppressed_override_mods(void) { suppressed_mods = 0; } +#endif + /* macro modifier */ /** \brief get macro mods * -- cgit v1.2.3 From 7ed5ac4a6026939898810f9a9c706fb7a09db171 Mon Sep 17 00:00:00 2001 From: Ryan Date: Fri, 16 Jul 2021 19:43:18 +1000 Subject: Use string literals for `SERIAL_NUMBER` (#13403) --- tmk_core/protocol/usb_descriptor.c | 4 ++-- tmk_core/protocol/usb_descriptor_common.h | 4 ++++ tmk_core/protocol/vusb/vusb.c | 4 ++-- 3 files changed, 8 insertions(+), 4 deletions(-) (limited to 'tmk_core') diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c index c88aceb6ed..7a4a790315 100644 --- a/tmk_core/protocol/usb_descriptor.c +++ b/tmk_core/protocol/usb_descriptor.c @@ -953,10 +953,10 @@ const USB_Descriptor_String_t PROGMEM ProductString = { #if defined(SERIAL_NUMBER) const USB_Descriptor_String_t PROGMEM SerialNumberString = { .Header = { - .Size = USB_STRING_LEN(sizeof(STR(SERIAL_NUMBER)) - 1), // Subtract 1 for null terminator + .Size = USB_STRING_LEN(sizeof(SERIAL_NUMBER) - 1), // Subtract 1 for null terminator .Type = DTYPE_String }, - .UnicodeString = LSTR(SERIAL_NUMBER) + .UnicodeString = USBSTR(SERIAL_NUMBER) }; #endif diff --git a/tmk_core/protocol/usb_descriptor_common.h b/tmk_core/protocol/usb_descriptor_common.h index b1f602c82e..ce0cf09763 100644 --- a/tmk_core/protocol/usb_descriptor_common.h +++ b/tmk_core/protocol/usb_descriptor_common.h @@ -16,6 +16,10 @@ #pragma once +// Prefix string literal with L for descriptors +#define USBCONCAT(a, b) a##b +#define USBSTR(s) USBCONCAT(L, s) + ///////////////////// // RAW Usage page and ID configuration diff --git a/tmk_core/protocol/vusb/vusb.c b/tmk_core/protocol/vusb/vusb.c index 876a313786..98cebf6012 100644 --- a/tmk_core/protocol/vusb/vusb.c +++ b/tmk_core/protocol/vusb/vusb.c @@ -599,10 +599,10 @@ const PROGMEM usbStringDescriptor_t usbStringDescriptorProduct = { #if defined(SERIAL_NUMBER) const PROGMEM usbStringDescriptor_t usbStringDescriptorSerial = { .header = { - .bLength = USB_STRING_LEN(sizeof(STR(SERIAL_NUMBER)) - 1), + .bLength = USB_STRING_LEN(sizeof(SERIAL_NUMBER) - 1), .bDescriptorType = USBDESCR_STRING }, - .bString = LSTR(SERIAL_NUMBER) + .bString = USBSTR(SERIAL_NUMBER) }; #endif -- cgit v1.2.3 From 567da49ed027a936a6f56aa069aad0db4605a198 Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Sat, 24 Jul 2021 12:13:06 +0100 Subject: Avoid LTO conficts on arm_atsam (#13676) --- quantum/split_common/split_util.c | 2 +- tmk_core/common/usb_util.c | 2 +- tmk_core/common/usb_util.h | 2 +- tmk_core/protocol/chibios/usb_util.c | 2 +- tmk_core/protocol/lufa/usb_util.c | 2 +- tmk_core/protocol/vusb/usb_util.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) (limited to 'tmk_core') diff --git a/quantum/split_common/split_util.c b/quantum/split_common/split_util.c index 989829d2dc..8d414f6fe6 100644 --- a/quantum/split_common/split_util.c +++ b/quantum/split_common/split_util.c @@ -106,7 +106,7 @@ __attribute__((weak)) bool is_keyboard_master(void) { // Avoid NO_USB_STARTUP_CHECK - Disable USB as the previous checks seem to enable it somehow if (usbstate == SLAVE) { - usb_disable(); + usb_disconnect(); } } diff --git a/tmk_core/common/usb_util.c b/tmk_core/common/usb_util.c index d4134a0446..dd1deeaa11 100644 --- a/tmk_core/common/usb_util.c +++ b/tmk_core/common/usb_util.c @@ -16,7 +16,7 @@ #include "quantum.h" #include "usb_util.h" -__attribute__((weak)) void usb_disable(void) {} +__attribute__((weak)) void usb_disconnect(void) {} __attribute__((weak)) bool usb_connected_state(void) { return true; } __attribute__((weak)) bool usb_vbus_state(void) { #ifdef USB_VBUS_PIN diff --git a/tmk_core/common/usb_util.h b/tmk_core/common/usb_util.h index 4ebedb1e71..13db9fbfbd 100644 --- a/tmk_core/common/usb_util.h +++ b/tmk_core/common/usb_util.h @@ -17,6 +17,6 @@ #include -void usb_disable(void); +void usb_disconnect(void); bool usb_connected_state(void); bool usb_vbus_state(void); diff --git a/tmk_core/protocol/chibios/usb_util.c b/tmk_core/protocol/chibios/usb_util.c index 5945e8a8de..e32d6ebfa4 100644 --- a/tmk_core/protocol/chibios/usb_util.c +++ b/tmk_core/protocol/chibios/usb_util.c @@ -16,6 +16,6 @@ #include #include "usb_util.h" -void usb_disable(void) { usbStop(&USBD1); } +void usb_disconnect(void) { usbStop(&USBD1); } bool usb_connected_state(void) { return usbGetDriverStateI(&USBD1) == USB_ACTIVE; } diff --git a/tmk_core/protocol/lufa/usb_util.c b/tmk_core/protocol/lufa/usb_util.c index 9e943a21b9..9691eff1e4 100644 --- a/tmk_core/protocol/lufa/usb_util.c +++ b/tmk_core/protocol/lufa/usb_util.c @@ -17,7 +17,7 @@ #include "usb_util.h" #include "wait.h" -void usb_disable(void) { +void usb_disconnect(void) { USB_Disable(); USB_DeviceState = DEVICE_STATE_Unattached; } diff --git a/tmk_core/protocol/vusb/usb_util.c b/tmk_core/protocol/vusb/usb_util.c index 602854dbe6..4ee2d3188b 100644 --- a/tmk_core/protocol/vusb/usb_util.c +++ b/tmk_core/protocol/vusb/usb_util.c @@ -16,7 +16,7 @@ #include #include "usb_util.h" -void usb_disable(void) { usbDeviceDisconnect(); } +void usb_disconnect(void) { usbDeviceDisconnect(); } bool usb_connected_state(void) { usbPoll(); -- cgit v1.2.3 From 71e9f8fc11f617278497611e169bf2ddccd2211c Mon Sep 17 00:00:00 2001 From: Drashna Jaelre Date: Sat, 24 Jul 2021 23:00:57 -0700 Subject: Update LUFA (18-07-2021) and add QMK-HID Bootloader support (#13588) Co-authored-by: Ryan --- bootloader.mk | 6 +++++ data/schemas/keyboard.jsonschema | 2 +- docs/driver_installation_zadig.md | 1 + docs/flashing.md | 46 +++++++++++++++++++++++++++++++++++++++ lib/lufa | 2 +- tmk_core/avr.mk | 34 ++++++++++++++++++++++------- 6 files changed, 81 insertions(+), 10 deletions(-) (limited to 'tmk_core') diff --git a/bootloader.mk b/bootloader.mk index 4f2d69d998..abdfd20fd0 100644 --- a/bootloader.mk +++ b/bootloader.mk @@ -26,6 +26,7 @@ # atmel-dfu Atmel factory DFU # lufa-dfu LUFA DFU # qmk-dfu QMK DFU (LUFA + blinkenlight) +# qmk-hid QMK HID (LUFA + blinkenlight) # bootloadHID HIDBootFlash compatible (ATmega32A) # USBasp USBaspLoader (ATmega328P) # ARM: @@ -67,6 +68,11 @@ ifeq ($(strip $(BOOTLOADER)), qmk-dfu) BOOTLOADER_SIZE = 8192 endif endif +ifeq ($(strip $(BOOTLOADER)), qmk-hid) + OPT_DEFS += -DBOOTLOADER_QMK_HID + OPT_DEFS += -DBOOTLOADER_HID + BOOTLOADER_SIZE = 4096 +endif ifeq ($(strip $(BOOTLOADER)), halfkay) OPT_DEFS += -DBOOTLOADER_HALFKAY ifeq ($(strip $(MCU)), atmega32u4) diff --git a/data/schemas/keyboard.jsonschema b/data/schemas/keyboard.jsonschema index 3a77b20678..6ac2c7c60c 100644 --- a/data/schemas/keyboard.jsonschema +++ b/data/schemas/keyboard.jsonschema @@ -22,7 +22,7 @@ }, "bootloader": { "type": "string", - "enum": ["atmel-dfu", "bootloadHID", "caterina", "halfkay", "kiibohd", "lufa-dfu", "lufa-ms", "micronucleus", "qmk-dfu", "stm32-dfu", "stm32duino", "unknown", "USBasp", "tinyuf2"] + "enum": ["atmel-dfu", "bootloadHID", "caterina", "halfkay", "kiibohd", "lufa-dfu", "lufa-ms", "micronucleus", "qmk-dfu", "qmk-hid", "stm32-dfu", "stm32duino", "unknown", "USBasp", "tinyuf2"] }, "diode_direction": { "type": "string", diff --git a/docs/driver_installation_zadig.md b/docs/driver_installation_zadig.md index fd5d3e92fc..e4db069f1d 100644 --- a/docs/driver_installation_zadig.md +++ b/docs/driver_installation_zadig.md @@ -95,3 +95,4 @@ The device name here is the name that appears in Zadig, and may not be what the |`stm32-dfu` |STM32 BOOTLOADER |`0483:DF11` |WinUSB | |`kiibohd` |Kiibohd DFU Bootloader |`1C11:B007` |WinUSB | |`stm32duino` |Maple 003 |`1EAF:0003` |WinUSB | +|`qmk-hid` |(keyboard name) Bootloader |`03EB:2067` |HidUsb | diff --git a/docs/flashing.md b/docs/flashing.md index 83c97444e1..da3c64c4a4 100644 --- a/docs/flashing.md +++ b/docs/flashing.md @@ -171,6 +171,52 @@ Flashing sequence: 3. Flash a .hex file 4. Reset the device into application mode (may be done automatically) +### QMK HID + +QMK maintains [a fork of the LUFA HID bootloader](https://github.com/qmk/lufa/tree/master/Bootloaders/HID), which uses a USB HID Endpoint for flashing in the way that the PJRC's Teensy Loader flasher and HalfKay bootloader work. Additionally, it performs a simple matrix scan for exiting the bootloader and returning to the application, as well as flashing an LED/making a ticking noise with a speaker when things are happening. + +To ensure compatibility with the QMK HID bootloader, make sure this block is present in your `rules.mk`: + +```make +# Bootloader selection +BOOTLOADER = qmk-hid +``` + +To enable the additional features, add the following defines to your `config.h`: + +```c +#define QMK_ESC_OUTPUT F1 // COL pin if COL2ROW +#define QMK_ESC_INPUT D5 // ROW pin if COL2ROW +// Optional: +//#define QMK_LED E6 +//#define QMK_SPEAKER C6 +``` + +Currently we do not recommend making `QMK_ESC` the same key as the one designated for [Bootmagic Lite](feature_bootmagic.md#bootmagic-lite), as holding it down will cause the MCU to loop back and forth between entering and exiting the bootloader. + +The manufacturer and product strings are automatically pulled from `config.h`, with " Bootloader" appended to the product string. + +To generate this bootloader, use the `bootloader` target, eg. `make planck/rev4:default:bootloader`. To generate a production-ready .hex file (combining QMK and the bootloader), use the `production` target, eg. `make planck/rev4:default:production`. + +Compatible flashers: + +* TBD + * Currently, you need to either use the [Python script](https://github.com/qmk/lufa/tree/master/Bootloaders/HID/HostLoaderApp_python), or compile [`hid_bootloader_cli`](https://github.com/qmk/lufa/tree/master/Bootloaders/HID/HostLoaderApp), from the LUFA repo. Homebrew may (will) have support for this directly (via `brew install qmk/qmk/hid_bootloader_cli`). + +Flashing sequence: + +1. Enter the bootloader using any of the following methods: + * Press the `RESET` keycode + * Press the `RESET` button on the PCB if available + * short RST to GND quickly +2. Wait for the OS to detect the device +3. Flash a .hex file +4. Reset the device into application mode (may be done automatically) + +### `make` Targets + +* `:qmk-hid`: Checks every 5 seconds until a DFU device is available, and then flashes the firmware. + ## STM32/APM32 DFU All STM32 and APM32 MCUs, except for F103 (see the [STM32duino section](#stm32duino)) come preloaded with a factory bootloader that cannot be modified nor deleted. diff --git a/lib/lufa b/lib/lufa index ce10f7642b..c7c5f65903 160000 --- a/lib/lufa +++ b/lib/lufa @@ -1 +1 @@ -Subproject commit ce10f7642b0459e409839b23cc91498945119b4d +Subproject commit c7c5f659031ac8bae22623a2f8fe6a7c6f81b243 diff --git a/tmk_core/avr.mk b/tmk_core/avr.mk index 2efde22127..d942e7ade5 100644 --- a/tmk_core/avr.mk +++ b/tmk_core/avr.mk @@ -237,6 +237,15 @@ endef bootloadHID: $(BUILD_DIR)/$(TARGET).hex check-size cpfirmware $(call EXEC_BOOTLOADHID) +HID_BOOTLOADER_CLI ?= hid_bootloader_cli + +define EXEC_HID_LUFA + $(HID_BOOTLOADER_CLI) -mmcu=$(MCU) -w -v $(BUILD_DIR)/$(TARGET).hex +endef + +hid_bootloader: $(BUILD_DIR)/$(TARGET).hex check-size cpfirmware + $(call EXEC_HID_LUFA) + # Convert hex to bin. bin: $(BUILD_DIR)/$(TARGET).hex $(OBJCOPY) -Iihex -Obinary $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin @@ -295,19 +304,26 @@ extcoff: $(BUILD_DIR)/$(TARGET).elf @$(SECHO) $(MSG_EXTENDED_COFF) $(BUILD_DIR)/$(TARGET).cof $(COFFCONVERT) -O coff-ext-avr $< $(BUILD_DIR)/$(TARGET).cof -bootloader: -ifneq ($(strip $(BOOTLOADER)), qmk-dfu) - $(error Please set BOOTLOADER = qmk-dfu first!) +ifeq ($(strip $(BOOTLOADER)), qmk-dfu) +QMK_BOOTLOADER_TYPE = DFU +else ifeq ($(strip $(BOOTLOADER)), qmk-hid) +QMK_BOOTLOADER_TYPE = HID endif - make -C lib/lufa/Bootloaders/DFU/ clean - $(QMK_BIN) generate-dfu-header --quiet --keyboard $(KEYBOARD) --output lib/lufa/Bootloaders/DFU/Keyboard.h + +bootloader: +ifeq ($(strip $(QMK_BOOTLOADER_TYPE)),) + $(error Please set BOOTLOADER to "qmk-dfu" or "qmk-hid" first!) +else + make -C lib/lufa/Bootloaders/$(QMK_BOOTLOADER_TYPE)/ clean + $(QMK_BIN) generate-dfu-header --quiet --keyboard $(KEYBOARD) --output lib/lufa/Bootloaders/$(QMK_BOOTLOADER_TYPE)/Keyboard.h $(eval MAX_SIZE=$(shell n=`$(CC) -E -mmcu=$(MCU) -D__ASSEMBLER__ $(CFLAGS) $(OPT_DEFS) tmk_core/common/avr/bootloader_size.c 2> /dev/null | sed -ne 's/\r//;/^#/n;/^AVR_SIZE:/,$${s/^AVR_SIZE: //;p;}'` && echo $$(($$n)) || echo 0)) $(eval PROGRAM_SIZE_KB=$(shell n=`expr $(MAX_SIZE) / 1024` && echo $$(($$n)) || echo 0)) $(eval BOOT_SECTION_SIZE_KB=$(shell n=`expr $(BOOTLOADER_SIZE) / 1024` && echo $$(($$n)) || echo 0)) $(eval FLASH_SIZE_KB=$(shell n=`expr $(PROGRAM_SIZE_KB) + $(BOOT_SECTION_SIZE_KB)` && echo $$(($$n)) || echo 0)) - make -C lib/lufa/Bootloaders/DFU/ MCU=$(MCU) ARCH=$(ARCH) F_CPU=$(F_CPU) FLASH_SIZE_KB=$(FLASH_SIZE_KB) BOOT_SECTION_SIZE_KB=$(BOOT_SECTION_SIZE_KB) - printf "BootloaderDFU.hex copied to $(TARGET)_bootloader.hex\n" - cp lib/lufa/Bootloaders/DFU/BootloaderDFU.hex $(TARGET)_bootloader.hex + make -C lib/lufa/Bootloaders/$(QMK_BOOTLOADER_TYPE)/ MCU=$(MCU) ARCH=$(ARCH) F_CPU=$(F_CPU) FLASH_SIZE_KB=$(FLASH_SIZE_KB) BOOT_SECTION_SIZE_KB=$(BOOT_SECTION_SIZE_KB) + printf "Bootloader$(QMK_BOOTLOADER_TYPE).hex copied to $(TARGET)_bootloader.hex\n" + cp lib/lufa/Bootloaders/$(QMK_BOOTLOADER_TYPE)/Bootloader$(QMK_BOOTLOADER_TYPE).hex $(TARGET)_bootloader.hex +endif production: $(BUILD_DIR)/$(TARGET).hex bootloader cpfirmware @cat $(BUILD_DIR)/$(TARGET).hex | awk '/^:00000001FF/ == 0' > $(TARGET)_production.hex @@ -328,6 +344,8 @@ else ifeq ($(strip $(BOOTLOADER)), USBasp) $(call EXEC_USBASP) else ifeq ($(strip $(BOOTLOADER)), bootloadHID) $(call EXEC_BOOTLOADHID) +else ifeq ($(strip $(BOOTLOADER)), qmk-hid) + $(call EXEC_HID_LUFA) else $(PRINT_OK); $(SILENT) || printf "$(MSG_FLASH_BOOTLOADER)" endif -- cgit v1.2.3 From c52c69d45f180e8ab677be4707ea2c8180a14254 Mon Sep 17 00:00:00 2001 From: Drashna Jaelre Date: Wed, 28 Jul 2021 04:00:16 -0700 Subject: Allow for higher USB Polling rate on ATSAM boards (#13755) --- tmk_core/protocol/arm_atsam/usb/udi_device_conf.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'tmk_core') diff --git a/tmk_core/protocol/arm_atsam/usb/udi_device_conf.h b/tmk_core/protocol/arm_atsam/usb/udi_device_conf.h index 9c9d94789d..1c0983115c 100644 --- a/tmk_core/protocol/arm_atsam/usb/udi_device_conf.h +++ b/tmk_core/protocol/arm_atsam/usb/udi_device_conf.h @@ -23,6 +23,10 @@ along with this program. If not, see . #include "compiler.h" #include "usb_protocol_hid.h" +#ifndef USB_POLLING_INTERVAL_MS +# define USB_POLLING_INTERVAL_MS 10 +#endif + #ifdef VIRTSER_ENABLE // because CDC uses IAD (interface association descriptor // per USB Interface Association Descriptor Device Class Code and Use Model 7/23/2003 Rev 1.0) @@ -118,7 +122,7 @@ along with this program. If not, see . #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 +#define KBD_POLLING_INTERVAL USB_POLLING_INTERVAL_MS #ifndef UDI_HID_KBD_STRING_ID # define UDI_HID_KBD_STRING_ID 0 #endif @@ -128,7 +132,7 @@ along with this program. If not, see . # 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 +# define MOU_POLLING_INTERVAL USB_POLLING_INTERVAL_MS # ifndef UDI_HID_MOU_STRING_ID # define UDI_HID_MOU_STRING_ID 0 # endif @@ -141,7 +145,7 @@ along with this program. If not, see . # 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 +# define EXTRAKEY_POLLING_INTERVAL USB_POLLING_INTERVAL_MS # ifndef UDI_HID_EXK_STRING_ID # define UDI_HID_EXK_STRING_ID 0 # endif -- cgit v1.2.3 From 70fb3e1aaf406cbbd5137916a93ed814d6891ef2 Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Sat, 31 Jul 2021 14:35:30 +0100 Subject: __flash? (#13799) --- docs/feature_led_matrix.md | 2 +- docs/feature_rgb_matrix.md | 8 ++++---- docs/ja/feature_led_matrix.md | 2 +- drivers/led/aw20216.h | 3 ++- drivers/led/issi/is31fl3731-simple.h | 3 ++- drivers/led/issi/is31fl3731.h | 3 ++- drivers/led/issi/is31fl3733.h | 3 ++- drivers/led/issi/is31fl3736.h | 3 ++- drivers/led/issi/is31fl3737.c | 9 ++------- drivers/led/issi/is31fl3737.h | 3 ++- drivers/led/issi/is31fl3741.h | 3 ++- keyboards/clueboard/66_hotswap/gen1/gen1.c | 2 +- keyboards/dp60/dp60.c | 2 +- keyboards/durgod/dgk6x/galaxy/galaxy.c | 2 +- keyboards/durgod/dgk6x/hades/hades.c | 2 +- keyboards/durgod/dgk6x/venus/venus.c | 2 +- keyboards/dztech/dz60rgb/dz60rgb.c | 2 +- keyboards/dztech/dz60rgb_ansi/dz60rgb_ansi.c | 2 +- keyboards/dztech/dz60rgb_wkl/dz60rgb_wkl.c | 2 +- keyboards/dztech/dz65rgb/v1/v1.c | 2 +- keyboards/dztech/dz65rgb/v2/v2.c | 2 +- keyboards/dztech/dz65rgb/v3/v3.c | 2 +- keyboards/ergodox_ez/ergodox_ez.c | 2 +- keyboards/ergodox_infinity/ergodox_infinity.c | 2 +- keyboards/exclusive/e6_rgb/e6_rgb.c | 2 +- keyboards/fallacy/indicators.c | 2 +- keyboards/geekboards/tester/tester.c | 2 +- keyboards/hs60/v1/v1.c | 4 ++-- keyboards/inett_studio/sqx/hotswap/hotswap.c | 2 +- keyboards/inett_studio/sqx/universal/universal.c | 2 +- keyboards/k_type/is31fl3733-dual.h | 2 +- keyboards/k_type/k_type.c | 2 +- keyboards/kbdfans/bella/rgb/rgb.c | 2 +- keyboards/kbdfans/bella/rgb_iso/rgb_iso.c | 2 +- keyboards/kbdfans/kbd67/mkiirgb/mkiirgb.c | 2 +- keyboards/kbdfans/kbdmini/kbdmini.c | 2 +- keyboards/kbdfans/maja/maja.c | 2 +- keyboards/keychron/q1/q1.c | 2 +- keyboards/latin17rgb/latin17rgb.c | 2 +- keyboards/latin60rgb/latin60rgb.c | 2 +- keyboards/latin6rgb/latin6rgb.c | 2 +- keyboards/matrix/m20add/rgb_ring.c | 2 +- keyboards/matrix/noah/noah.c | 2 +- keyboards/mechlovin/adelais/rgb_led/rev2/rev2.c | 2 +- keyboards/mechlovin/delphine/rgb_led/rgb_led.c | 2 +- keyboards/mechlovin/hannah60rgb/rev2/rev2.c | 2 +- keyboards/mechlovin/infinity87/rgb_rev1/rgb_rev1.c | 2 +- keyboards/melgeek/mj61/rev1/rev1.c | 2 +- keyboards/melgeek/mj61/rev2/rev2.c | 2 +- keyboards/melgeek/mj63/rev1/rev1.c | 2 +- keyboards/melgeek/mj63/rev2/rev2.c | 2 +- keyboards/melgeek/mj64/rev1/rev1.c | 2 +- keyboards/melgeek/mj64/rev2/rev2.c | 2 +- keyboards/melgeek/mj64/rev3/rev3.c | 2 +- keyboards/melgeek/mj65/rev3/rev3.c | 2 +- keyboards/melgeek/mojo75/rev1/rev1.c | 2 +- keyboards/melgeek/z70ultra/z70ultra.c | 2 +- keyboards/miller/gm862/gm862.c | 2 +- keyboards/moonlander/moonlander.c | 2 +- keyboards/mt64rgb/mt64rgb.c | 2 +- keyboards/mt84/mt84.c | 2 +- keyboards/opendeck/32/rev1/rev1.c | 2 +- keyboards/planck/ez/ez.c | 2 +- keyboards/planck/light/light.c | 2 +- keyboards/terrazzo/terrazzo.c | 2 +- keyboards/tkc/portico/portico.c | 2 +- keyboards/whitefox/whitefox.c | 2 +- keyboards/wilba_tech/wt_rgb_backlight.c | 16 ++++++++-------- keyboards/xbows/knight/knight.c | 2 +- keyboards/xbows/knight_plus/knight_plus.c | 2 +- keyboards/xbows/nature/nature.c | 2 +- keyboards/xbows/numpad/numpad.c | 2 +- keyboards/xbows/woody/woody.c | 2 +- keyboards/xelus/dawn60/rev1_qmk/rev1_qmk.c | 2 +- keyboards/xelus/pachi/rgb/rgb.c | 2 +- tmk_core/common/progmem.h | 1 + 76 files changed, 95 insertions(+), 92 deletions(-) (limited to 'tmk_core') diff --git a/docs/feature_led_matrix.md b/docs/feature_led_matrix.md index afa11e7232..7d7971bbed 100644 --- a/docs/feature_led_matrix.md +++ b/docs/feature_led_matrix.md @@ -52,7 +52,7 @@ Here is an example using 2 drivers. Define these arrays listing all the LEDs in your `.c`: ```c -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | LED address diff --git a/docs/feature_rgb_matrix.md b/docs/feature_rgb_matrix.md index 18e38955ec..670d7e09bf 100644 --- a/docs/feature_rgb_matrix.md +++ b/docs/feature_rgb_matrix.md @@ -52,7 +52,7 @@ Here is an example using 2 drivers. Define these arrays listing all the LEDs in your `.c`: ```c -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location @@ -122,7 +122,7 @@ Currently only 4 drivers are supported, but it would be trivial to support all 8 Define these arrays listing all the LEDs in your `.c`: ```c -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location @@ -186,7 +186,7 @@ Currently only 2 drivers are supported, but it would be trivial to support all 4 Define these arrays listing all the LEDs in your `.c`: ```c -const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location @@ -287,7 +287,7 @@ Here is an example using 2 drivers. Define these arrays listing all the LEDs in your `.c`: ```c -const aw_led g_aw_leds[DRIVER_LED_TOTAL] = { +const aw_led __flash g_aw_leds[DRIVER_LED_TOTAL] = { /* Each AW20216 channel is controlled by a register at some offset between 0x00 * and 0xD7 inclusive. * See drivers/awinic/aw20216.h for the mapping between register offsets and diff --git a/docs/ja/feature_led_matrix.md b/docs/ja/feature_led_matrix.md index f132d716f6..6511b28249 100644 --- a/docs/ja/feature_led_matrix.md +++ b/docs/ja/feature_led_matrix.md @@ -52,7 +52,7 @@ I2C IS31FL3731 RGB コントローラを使ったアドレス指定可能な LED `.c` に全ての LED を列挙する配列を定義します: - const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { + const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* これらの位置については IS31 マニュアルを参照してください * driver * | LED address diff --git a/drivers/led/aw20216.h b/drivers/led/aw20216.h index c55d9605fc..97ac6dc5bf 100644 --- a/drivers/led/aw20216.h +++ b/drivers/led/aw20216.h @@ -18,6 +18,7 @@ #include #include +#include "progmem.h" #include "gpio.h" typedef struct aw_led { @@ -27,7 +28,7 @@ typedef struct aw_led { uint8_t b; } aw_led; -extern const aw_led g_aw_leds[DRIVER_LED_TOTAL]; +extern const aw_led __flash g_aw_leds[DRIVER_LED_TOTAL]; void AW20216_init(pin_t cs_pin, pin_t en_pin); void AW20216_set_color(int index, uint8_t red, uint8_t green, uint8_t blue); diff --git a/drivers/led/issi/is31fl3731-simple.h b/drivers/led/issi/is31fl3731-simple.h index 9665d6ed35..ecde31eed5 100644 --- a/drivers/led/issi/is31fl3731-simple.h +++ b/drivers/led/issi/is31fl3731-simple.h @@ -20,13 +20,14 @@ #include #include +#include "progmem.h" typedef struct is31_led { uint8_t driver : 2; uint8_t v; } __attribute__((packed)) is31_led; -extern const is31_led g_is31_leds[DRIVER_LED_TOTAL]; +extern const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL]; void IS31FL3731_init(uint8_t addr); void IS31FL3731_write_register(uint8_t addr, uint8_t reg, uint8_t data); diff --git a/drivers/led/issi/is31fl3731.h b/drivers/led/issi/is31fl3731.h index 19e8e6251f..803ea3ea12 100644 --- a/drivers/led/issi/is31fl3731.h +++ b/drivers/led/issi/is31fl3731.h @@ -19,6 +19,7 @@ #include #include +#include "progmem.h" typedef struct is31_led { uint8_t driver : 2; @@ -27,7 +28,7 @@ typedef struct is31_led { uint8_t b; } __attribute__((packed)) is31_led; -extern const is31_led g_is31_leds[DRIVER_LED_TOTAL]; +extern const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL]; void IS31FL3731_init(uint8_t addr); void IS31FL3731_write_register(uint8_t addr, uint8_t reg, uint8_t data); diff --git a/drivers/led/issi/is31fl3733.h b/drivers/led/issi/is31fl3733.h index 603d505a13..64fd38eb19 100644 --- a/drivers/led/issi/is31fl3733.h +++ b/drivers/led/issi/is31fl3733.h @@ -20,6 +20,7 @@ #include #include +#include "progmem.h" typedef struct is31_led { uint8_t driver : 2; @@ -28,7 +29,7 @@ typedef struct is31_led { uint8_t b; } __attribute__((packed)) is31_led; -extern const is31_led g_is31_leds[DRIVER_LED_TOTAL]; +extern const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL]; void IS31FL3733_init(uint8_t addr, uint8_t sync); bool IS31FL3733_write_register(uint8_t addr, uint8_t reg, uint8_t data); diff --git a/drivers/led/issi/is31fl3736.h b/drivers/led/issi/is31fl3736.h index e48e31c279..c956c87f7c 100644 --- a/drivers/led/issi/is31fl3736.h +++ b/drivers/led/issi/is31fl3736.h @@ -18,6 +18,7 @@ #include #include +#include "progmem.h" // Simple interface option. // If these aren't defined, just define them to make it compile @@ -37,7 +38,7 @@ typedef struct is31_led { uint8_t b; } __attribute__((packed)) is31_led; -extern const is31_led g_is31_leds[DRIVER_LED_TOTAL]; +extern const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL]; void IS31FL3736_init(uint8_t addr); void IS31FL3736_write_register(uint8_t addr, uint8_t reg, uint8_t data); diff --git a/drivers/led/issi/is31fl3737.c b/drivers/led/issi/is31fl3737.c index 30906b4840..0bb4ddd425 100644 --- a/drivers/led/issi/is31fl3737.c +++ b/drivers/led/issi/is31fl3737.c @@ -19,7 +19,6 @@ #include "is31fl3737.h" #include "i2c_master.h" #include "wait.h" -#include "progmem.h" // This is a 7-bit address, that gets left-shifted and bit 0 // set to 0 for write, 1 for read (as per I2C protocol) @@ -155,9 +154,7 @@ void IS31FL3737_init(uint8_t addr) { void IS31FL3737_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) { if (index >= 0 && index < DRIVER_LED_TOTAL) { - // copy the led config from progmem to SRAM - is31_led led; - memcpy_P(&led, (&g_is31_leds[index]), sizeof(led)); + is31_led led = g_is31_leds[index]; g_pwm_buffer[led.driver][led.r] = red; g_pwm_buffer[led.driver][led.g] = green; @@ -173,9 +170,7 @@ void IS31FL3737_set_color_all(uint8_t red, uint8_t green, uint8_t blue) { } void IS31FL3737_set_led_control_register(uint8_t index, bool red, bool green, bool blue) { - // copy the led config from progmem to SRAM - is31_led led; - memcpy_P(&led, (&g_is31_leds[index]), sizeof(led)); + is31_led led = g_is31_leds[index]; uint8_t control_register_r = led.r / 8; uint8_t control_register_g = led.g / 8; diff --git a/drivers/led/issi/is31fl3737.h b/drivers/led/issi/is31fl3737.h index a1d2281778..06886e9c9b 100644 --- a/drivers/led/issi/is31fl3737.h +++ b/drivers/led/issi/is31fl3737.h @@ -20,6 +20,7 @@ #include #include +#include "progmem.h" typedef struct is31_led { uint8_t driver : 2; @@ -28,7 +29,7 @@ typedef struct is31_led { uint8_t b; } __attribute__((packed)) is31_led; -extern const is31_led g_is31_leds[DRIVER_LED_TOTAL]; +extern const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL]; void IS31FL3737_init(uint8_t addr); void IS31FL3737_write_register(uint8_t addr, uint8_t reg, uint8_t data); diff --git a/drivers/led/issi/is31fl3741.h b/drivers/led/issi/is31fl3741.h index 2df0c5b1a7..cea6761ca8 100644 --- a/drivers/led/issi/is31fl3741.h +++ b/drivers/led/issi/is31fl3741.h @@ -21,6 +21,7 @@ #include #include +#include "progmem.h" typedef struct is31_led { uint32_t driver : 2; @@ -29,7 +30,7 @@ typedef struct is31_led { uint32_t b : 10; } __attribute__((packed)) is31_led; -extern const is31_led g_is31_leds[DRIVER_LED_TOTAL]; +extern const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL]; void IS31FL3741_init(uint8_t addr); void IS31FL3741_write_register(uint8_t addr, uint8_t reg, uint8_t data); diff --git a/keyboards/clueboard/66_hotswap/gen1/gen1.c b/keyboards/clueboard/66_hotswap/gen1/gen1.c index 339bd78d5a..8e3db70d07 100644 --- a/keyboards/clueboard/66_hotswap/gen1/gen1.c +++ b/keyboards/clueboard/66_hotswap/gen1/gen1.c @@ -16,7 +16,7 @@ #include "gen1.h" #ifdef LED_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | LED address diff --git a/keyboards/dp60/dp60.c b/keyboards/dp60/dp60.c index 475084b049..87543b2a1c 100644 --- a/keyboards/dp60/dp60.c +++ b/keyboards/dp60/dp60.c @@ -17,7 +17,7 @@ #include "dp60.h" #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location diff --git a/keyboards/durgod/dgk6x/galaxy/galaxy.c b/keyboards/durgod/dgk6x/galaxy/galaxy.c index d101533b16..5f793ed85b 100644 --- a/keyboards/durgod/dgk6x/galaxy/galaxy.c +++ b/keyboards/durgod/dgk6x/galaxy/galaxy.c @@ -18,7 +18,7 @@ #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location diff --git a/keyboards/durgod/dgk6x/hades/hades.c b/keyboards/durgod/dgk6x/hades/hades.c index 21b2722913..3e235683f1 100644 --- a/keyboards/durgod/dgk6x/hades/hades.c +++ b/keyboards/durgod/dgk6x/hades/hades.c @@ -19,7 +19,7 @@ #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location diff --git a/keyboards/durgod/dgk6x/venus/venus.c b/keyboards/durgod/dgk6x/venus/venus.c index 2d49b34daf..3398acb19d 100644 --- a/keyboards/durgod/dgk6x/venus/venus.c +++ b/keyboards/durgod/dgk6x/venus/venus.c @@ -18,7 +18,7 @@ #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location diff --git a/keyboards/dztech/dz60rgb/dz60rgb.c b/keyboards/dztech/dz60rgb/dz60rgb.c index aa02fb902d..a7fc3dbc5c 100644 --- a/keyboards/dztech/dz60rgb/dz60rgb.c +++ b/keyboards/dztech/dz60rgb/dz60rgb.c @@ -1,7 +1,7 @@ #include "dz60rgb.h" #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { { 0, K_14, J_14, L_14 }, { 0, K_13, J_13, L_13 }, { 0, K_12, J_12, L_12 }, diff --git a/keyboards/dztech/dz60rgb_ansi/dz60rgb_ansi.c b/keyboards/dztech/dz60rgb_ansi/dz60rgb_ansi.c index 4bb5938b66..ab24410912 100644 --- a/keyboards/dztech/dz60rgb_ansi/dz60rgb_ansi.c +++ b/keyboards/dztech/dz60rgb_ansi/dz60rgb_ansi.c @@ -1,7 +1,7 @@ #include "dz60rgb_ansi.h" #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { { 0, K_14, J_14, L_14 }, { 0, K_13, J_13, L_13 }, { 0, K_12, J_12, L_12 }, diff --git a/keyboards/dztech/dz60rgb_wkl/dz60rgb_wkl.c b/keyboards/dztech/dz60rgb_wkl/dz60rgb_wkl.c index b57560bacd..455624471d 100644 --- a/keyboards/dztech/dz60rgb_wkl/dz60rgb_wkl.c +++ b/keyboards/dztech/dz60rgb_wkl/dz60rgb_wkl.c @@ -1,7 +1,7 @@ #include "dz60rgb_wkl.h" #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { { 0, H_15, G_15, I_15 }, { 0, K_14, J_14, L_14 }, { 0, K_13, J_13, L_13 }, diff --git a/keyboards/dztech/dz65rgb/v1/v1.c b/keyboards/dztech/dz65rgb/v1/v1.c index 8a3f0e27bf..aabe41c313 100644 --- a/keyboards/dztech/dz65rgb/v1/v1.c +++ b/keyboards/dztech/dz65rgb/v1/v1.c @@ -16,7 +16,7 @@ #include "v1.h" #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { { 0, C8_8, C7_8, C6_8 }, { 0, C9_8, C7_7, C6_7 }, { 0, C9_7, C8_7, C6_6 }, diff --git a/keyboards/dztech/dz65rgb/v2/v2.c b/keyboards/dztech/dz65rgb/v2/v2.c index 788709d989..dce167c73f 100644 --- a/keyboards/dztech/dz65rgb/v2/v2.c +++ b/keyboards/dztech/dz65rgb/v2/v2.c @@ -16,7 +16,7 @@ #include "v2.h" #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { { 0, C8_8, C7_8, C6_8 }, { 0, C9_8, C7_7, C6_7 }, { 0, C9_7, C8_7, C6_6 }, diff --git a/keyboards/dztech/dz65rgb/v3/v3.c b/keyboards/dztech/dz65rgb/v3/v3.c index dec75814ca..c3719bfa51 100755 --- a/keyboards/dztech/dz65rgb/v3/v3.c +++ b/keyboards/dztech/dz65rgb/v3/v3.c @@ -18,7 +18,7 @@ #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { {0, CS21_SW1, CS20_SW1, CS19_SW1}, {0, CS21_SW2, CS20_SW2, CS19_SW2}, {0, CS21_SW3, CS20_SW3, CS19_SW3}, diff --git a/keyboards/ergodox_ez/ergodox_ez.c b/keyboards/ergodox_ez/ergodox_ez.c index 47dd1b0cc9..7af76cb624 100644 --- a/keyboards/ergodox_ez/ergodox_ez.c +++ b/keyboards/ergodox_ez/ergodox_ez.c @@ -243,7 +243,7 @@ const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { #ifdef RGB_MATRIX_ENABLE // clang-format off -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* driver * | R location * | | G location diff --git a/keyboards/ergodox_infinity/ergodox_infinity.c b/keyboards/ergodox_infinity/ergodox_infinity.c index 76cbca07f8..90aa522427 100644 --- a/keyboards/ergodox_infinity/ergodox_infinity.c +++ b/keyboards/ergodox_infinity/ergodox_infinity.c @@ -191,7 +191,7 @@ const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { #endif #ifdef LED_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { // The numbers in the comments are the led numbers DXX on the PCB /* Refer to IS31 manual for these locations * driver diff --git a/keyboards/exclusive/e6_rgb/e6_rgb.c b/keyboards/exclusive/e6_rgb/e6_rgb.c index 0e248a2023..e0d313f835 100644 --- a/keyboards/exclusive/e6_rgb/e6_rgb.c +++ b/keyboards/exclusive/e6_rgb/e6_rgb.c @@ -11,7 +11,7 @@ void matrix_init_kb(void) { matrix_init_user(); } -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location diff --git a/keyboards/fallacy/indicators.c b/keyboards/fallacy/indicators.c index 08c500064d..dcf1b4de07 100755 --- a/keyboards/fallacy/indicators.c +++ b/keyboards/fallacy/indicators.c @@ -54,7 +54,7 @@ void set_fallacy_led(int index, bool state) { /* define LED matrix */ -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { {0, C1_1}, {0, C2_1}, {0, C3_1}, diff --git a/keyboards/geekboards/tester/tester.c b/keyboards/geekboards/tester/tester.c index 4fab1a7012..0c5c056cc0 100644 --- a/keyboards/geekboards/tester/tester.c +++ b/keyboards/geekboards/tester/tester.c @@ -1,5 +1,5 @@ #include "tester.h" -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location diff --git a/keyboards/hs60/v1/v1.c b/keyboards/hs60/v1/v1.c index 70c1c2128e..58b19b6408 100644 --- a/keyboards/hs60/v1/v1.c +++ b/keyboards/hs60/v1/v1.c @@ -91,7 +91,7 @@ void raw_hid_receive( uint8_t *data, uint8_t length ) #ifdef HS60_ANSI -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location @@ -199,7 +199,7 @@ led_config_t g_led_config = { { #else -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location diff --git a/keyboards/inett_studio/sqx/hotswap/hotswap.c b/keyboards/inett_studio/sqx/hotswap/hotswap.c index be8985c87e..5b3c8df822 100644 --- a/keyboards/inett_studio/sqx/hotswap/hotswap.c +++ b/keyboards/inett_studio/sqx/hotswap/hotswap.c @@ -20,7 +20,7 @@ #include "hotswap.h" #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location diff --git a/keyboards/inett_studio/sqx/universal/universal.c b/keyboards/inett_studio/sqx/universal/universal.c index 42d99330d5..dd431a7f45 100644 --- a/keyboards/inett_studio/sqx/universal/universal.c +++ b/keyboards/inett_studio/sqx/universal/universal.c @@ -20,7 +20,7 @@ #include "universal.h" #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location diff --git a/keyboards/k_type/is31fl3733-dual.h b/keyboards/k_type/is31fl3733-dual.h index 272bcdc417..aab170a3fd 100644 --- a/keyboards/k_type/is31fl3733-dual.h +++ b/keyboards/k_type/is31fl3733-dual.h @@ -28,7 +28,7 @@ typedef struct is31_led { uint8_t b; } __attribute__((packed)) is31_led; -extern const is31_led g_is31_leds[DRIVER_LED_TOTAL]; +extern const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL]; void IS31FL3733_init(uint8_t bus, uint8_t addr, uint8_t sync); bool IS31FL3733_write_register(uint8_t index, uint8_t addr, uint8_t reg, uint8_t data); diff --git a/keyboards/k_type/k_type.c b/keyboards/k_type/k_type.c index 61c5881454..924862277f 100644 --- a/keyboards/k_type/k_type.c +++ b/keyboards/k_type/k_type.c @@ -23,7 +23,7 @@ along with this program. If not, see . #include "is31fl3733-dual.h" -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { { 0, B_1, A_1, C_1 }, { 0, B_2, A_2, C_2 }, { 0, B_3, A_3, C_3 }, diff --git a/keyboards/kbdfans/bella/rgb/rgb.c b/keyboards/kbdfans/bella/rgb/rgb.c index e197d9b538..17cf992146 100644 --- a/keyboards/kbdfans/bella/rgb/rgb.c +++ b/keyboards/kbdfans/bella/rgb/rgb.c @@ -15,7 +15,7 @@ */ #include "rgb.h" #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { {0, CS18_SW1, CS17_SW1, CS16_SW1}, /* RGB6 */ {0, CS18_SW3, CS17_SW3, CS16_SW3}, /* RGB32 */ {0, CS18_SW4, CS17_SW4, CS16_SW4}, /* RGB45 */ diff --git a/keyboards/kbdfans/bella/rgb_iso/rgb_iso.c b/keyboards/kbdfans/bella/rgb_iso/rgb_iso.c index 1a853ac8af..0c431b1543 100644 --- a/keyboards/kbdfans/bella/rgb_iso/rgb_iso.c +++ b/keyboards/kbdfans/bella/rgb_iso/rgb_iso.c @@ -15,7 +15,7 @@ */ #include "rgb_iso.h" #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { {0, CS18_SW1, CS17_SW1, CS16_SW1}, /* RGB6 */ {0, CS18_SW3, CS17_SW3, CS16_SW3}, /* RGB32 */ {0, CS18_SW4, CS17_SW4, CS16_SW4}, /* RGB45 */ diff --git a/keyboards/kbdfans/kbd67/mkiirgb/mkiirgb.c b/keyboards/kbdfans/kbd67/mkiirgb/mkiirgb.c index 323cb23848..2826c08988 100644 --- a/keyboards/kbdfans/kbd67/mkiirgb/mkiirgb.c +++ b/keyboards/kbdfans/kbd67/mkiirgb/mkiirgb.c @@ -1,6 +1,6 @@ #include "mkiirgb.h" #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { {0, C8_8, C7_8, C6_8}, // LA17 {0, C9_8, C7_7, C6_7}, // LA16 diff --git a/keyboards/kbdfans/kbdmini/kbdmini.c b/keyboards/kbdfans/kbdmini/kbdmini.c index 0e0df2f9af..799803c6fa 100644 --- a/keyboards/kbdfans/kbdmini/kbdmini.c +++ b/keyboards/kbdfans/kbdmini/kbdmini.c @@ -1,6 +1,6 @@ #include "kbdmini.h" -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { { 0, B_9, A_9, C_9 }, //LA33 { 0, B_10, A_10, C_10 }, //LA37 { 0, B_11, A_11, C_11 }, //LA41 diff --git a/keyboards/kbdfans/maja/maja.c b/keyboards/kbdfans/maja/maja.c index a0afcbda8a..9619a84b48 100755 --- a/keyboards/kbdfans/maja/maja.c +++ b/keyboards/kbdfans/maja/maja.c @@ -1,6 +1,6 @@ #include "maja.h" -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { {0, C2_1, C3_1, C4_1}, // LA0 {0, C1_1, C3_2, C4_2}, // LA1 {0, C1_2, C2_2, C4_3}, // LA2 diff --git a/keyboards/keychron/q1/q1.c b/keyboards/keychron/q1/q1.c index 520e6e4c57..6beb96e7eb 100644 --- a/keyboards/keychron/q1/q1.c +++ b/keyboards/keychron/q1/q1.c @@ -33,7 +33,7 @@ bool dip_switch_update_kb(uint8_t index, bool active) { return true; } -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location diff --git a/keyboards/latin17rgb/latin17rgb.c b/keyboards/latin17rgb/latin17rgb.c index 8d9eaae8ae..f7bbe125c2 100644 --- a/keyboards/latin17rgb/latin17rgb.c +++ b/keyboards/latin17rgb/latin17rgb.c @@ -17,7 +17,7 @@ #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location diff --git a/keyboards/latin60rgb/latin60rgb.c b/keyboards/latin60rgb/latin60rgb.c index cdd6fed44d..fe5d2eea8f 100644 --- a/keyboards/latin60rgb/latin60rgb.c +++ b/keyboards/latin60rgb/latin60rgb.c @@ -16,7 +16,7 @@ #include "latin60rgb.h" #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { { 0, K_13, J_13, L_13 }, { 0, K_12, J_12, L_12 }, { 0, K_11, J_11, L_11 }, diff --git a/keyboards/latin6rgb/latin6rgb.c b/keyboards/latin6rgb/latin6rgb.c index 76b39c86bb..9ea4721ecb 100644 --- a/keyboards/latin6rgb/latin6rgb.c +++ b/keyboards/latin6rgb/latin6rgb.c @@ -17,7 +17,7 @@ #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location diff --git a/keyboards/matrix/m20add/rgb_ring.c b/keyboards/matrix/m20add/rgb_ring.c index fa70dea7eb..3a8af7cd3b 100644 --- a/keyboards/matrix/m20add/rgb_ring.c +++ b/keyboards/matrix/m20add/rgb_ring.c @@ -30,7 +30,7 @@ #endif // rgb ring leds setting -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location diff --git a/keyboards/matrix/noah/noah.c b/keyboards/matrix/noah/noah.c index 1e2f4bb7d9..6b624b9e09 100644 --- a/keyboards/matrix/noah/noah.c +++ b/keyboards/matrix/noah/noah.c @@ -66,7 +66,7 @@ __attribute__((weak)) void matrix_scan_user(void) { } #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location diff --git a/keyboards/mechlovin/adelais/rgb_led/rev2/rev2.c b/keyboards/mechlovin/adelais/rgb_led/rev2/rev2.c index 5087174b96..fe946169a7 100644 --- a/keyboards/mechlovin/adelais/rgb_led/rev2/rev2.c +++ b/keyboards/mechlovin/adelais/rgb_led/rev2/rev2.c @@ -17,7 +17,7 @@ #include "adelais.h" #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { {0, C2_1, C3_1, C4_1}, //D102-A0-0 {0, C5_1, C6_1, C7_1}, //D108-A1-1 diff --git a/keyboards/mechlovin/delphine/rgb_led/rgb_led.c b/keyboards/mechlovin/delphine/rgb_led/rgb_led.c index 6f3e3ec731..29b6d1f783 100644 --- a/keyboards/mechlovin/delphine/rgb_led/rgb_led.c +++ b/keyboards/mechlovin/delphine/rgb_led/rgb_led.c @@ -18,7 +18,7 @@ #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { // left CA {0, C5_2, C6_2, C7_2}, //D2-0 {0, C1_1, C3_2, C4_2}, //D20-1 diff --git a/keyboards/mechlovin/hannah60rgb/rev2/rev2.c b/keyboards/mechlovin/hannah60rgb/rev2/rev2.c index 05469a1bbe..8b30538cc2 100644 --- a/keyboards/mechlovin/hannah60rgb/rev2/rev2.c +++ b/keyboards/mechlovin/hannah60rgb/rev2/rev2.c @@ -17,7 +17,7 @@ #include "rev2.h" #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location diff --git a/keyboards/mechlovin/infinity87/rgb_rev1/rgb_rev1.c b/keyboards/mechlovin/infinity87/rgb_rev1/rgb_rev1.c index f13fee8add..bd1fd8abf7 100644 --- a/keyboards/mechlovin/infinity87/rgb_rev1/rgb_rev1.c +++ b/keyboards/mechlovin/infinity87/rgb_rev1/rgb_rev1.c @@ -17,7 +17,7 @@ #include "rgb_rev1.h" #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { {0, CS34_SW1, CS35_SW1, CS36_SW1}, //D92-K00-0 {0, CS37_SW1, CS38_SW1, CS39_SW1}, //D94-K01-1 {0, CS31_SW1, CS32_SW1, CS33_SW1}, //D96-K02-2 diff --git a/keyboards/melgeek/mj61/rev1/rev1.c b/keyboards/melgeek/mj61/rev1/rev1.c index be58f57a95..e51c57548f 100644 --- a/keyboards/melgeek/mj61/rev1/rev1.c +++ b/keyboards/melgeek/mj61/rev1/rev1.c @@ -17,7 +17,7 @@ #include "mj61.h" #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { {0, CS12_SW1, CS11_SW1, CS10_SW1}, /* RGB1 */ {0, CS12_SW2, CS11_SW2, CS10_SW2}, /* RGB2 */ {0, CS12_SW3, CS11_SW3, CS10_SW3}, /* RGB3 */ diff --git a/keyboards/melgeek/mj61/rev2/rev2.c b/keyboards/melgeek/mj61/rev2/rev2.c index 236b003972..3f6b1bff77 100644 --- a/keyboards/melgeek/mj61/rev2/rev2.c +++ b/keyboards/melgeek/mj61/rev2/rev2.c @@ -19,7 +19,7 @@ #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { {0, CS9_SW1, CS8_SW1, CS7_SW1}, /* RGB1 */ {0, CS9_SW2, CS8_SW2, CS7_SW2}, /* RGB3 */ {0, CS9_SW3, CS8_SW3, CS7_SW3}, /* RGB4 */ diff --git a/keyboards/melgeek/mj63/rev1/rev1.c b/keyboards/melgeek/mj63/rev1/rev1.c index 34ff28d25f..a6ee8859b0 100644 --- a/keyboards/melgeek/mj63/rev1/rev1.c +++ b/keyboards/melgeek/mj63/rev1/rev1.c @@ -19,7 +19,7 @@ #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { {0, CS9_SW1, CS8_SW1, CS7_SW1}, /* RGB1 */ {0, CS9_SW2, CS8_SW2, CS7_SW2}, /* RGB2 */ {0, CS9_SW3, CS8_SW3, CS7_SW3}, /* RGB3 */ diff --git a/keyboards/melgeek/mj63/rev2/rev2.c b/keyboards/melgeek/mj63/rev2/rev2.c index c2379dabe9..8cacc689ae 100644 --- a/keyboards/melgeek/mj63/rev2/rev2.c +++ b/keyboards/melgeek/mj63/rev2/rev2.c @@ -19,7 +19,7 @@ #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { {0, CS9_SW1, CS8_SW1, CS7_SW1}, /* RGB1 */ {0, CS9_SW2, CS8_SW2, CS7_SW2}, /* RGB3 */ {0, CS9_SW3, CS8_SW3, CS7_SW3}, /* RGB4 */ diff --git a/keyboards/melgeek/mj64/rev1/rev1.c b/keyboards/melgeek/mj64/rev1/rev1.c index e01765b694..446ba779d0 100644 --- a/keyboards/melgeek/mj64/rev1/rev1.c +++ b/keyboards/melgeek/mj64/rev1/rev1.c @@ -18,7 +18,7 @@ #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { {0, CS9_SW1, CS8_SW1, CS7_SW1}, /* RGB1 */ {0, CS9_SW2, CS8_SW2, CS7_SW2}, /* RGB2 */ {0, CS9_SW3, CS8_SW3, CS7_SW3}, /* RGB3 */ diff --git a/keyboards/melgeek/mj64/rev2/rev2.c b/keyboards/melgeek/mj64/rev2/rev2.c index d5486b9086..444e8f60ac 100644 --- a/keyboards/melgeek/mj64/rev2/rev2.c +++ b/keyboards/melgeek/mj64/rev2/rev2.c @@ -18,7 +18,7 @@ #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { {0, CS9_SW1, CS8_SW1, CS7_SW1}, /* RGB1 */ {0, CS9_SW2, CS8_SW2, CS7_SW2}, /* RGB2 */ {0, CS9_SW3, CS8_SW3, CS7_SW3}, /* RGB3 */ diff --git a/keyboards/melgeek/mj64/rev3/rev3.c b/keyboards/melgeek/mj64/rev3/rev3.c index 03ed9fe007..2a1283ec70 100644 --- a/keyboards/melgeek/mj64/rev3/rev3.c +++ b/keyboards/melgeek/mj64/rev3/rev3.c @@ -18,7 +18,7 @@ #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { {0, CS9_SW1, CS8_SW1, CS7_SW1}, /* RGB1 */ {0, CS9_SW2, CS8_SW2, CS7_SW2}, /* RGB3 */ {0, CS9_SW3, CS8_SW3, CS7_SW3}, /* RGB4 */ diff --git a/keyboards/melgeek/mj65/rev3/rev3.c b/keyboards/melgeek/mj65/rev3/rev3.c index 43fae53a36..6335edd796 100644 --- a/keyboards/melgeek/mj65/rev3/rev3.c +++ b/keyboards/melgeek/mj65/rev3/rev3.c @@ -18,7 +18,7 @@ #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { {0, CS9_SW1, CS8_SW1, CS7_SW1}, /* RGB1 */ {0, CS9_SW2, CS8_SW2, CS7_SW2}, /* RGB2 */ {0, CS9_SW3, CS8_SW3, CS7_SW3}, /* RGB3 */ diff --git a/keyboards/melgeek/mojo75/rev1/rev1.c b/keyboards/melgeek/mojo75/rev1/rev1.c index 670116fcd6..07ae916da2 100644 --- a/keyboards/melgeek/mojo75/rev1/rev1.c +++ b/keyboards/melgeek/mojo75/rev1/rev1.c @@ -18,7 +18,7 @@ #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { {0, CS6_SW1, CS5_SW1, CS4_SW1}, /* RGB1 */ {0, CS6_SW2, CS5_SW2, CS4_SW2}, /* RGB2 */ {0, CS6_SW3, CS5_SW3, CS4_SW3}, /* RGB3 */ diff --git a/keyboards/melgeek/z70ultra/z70ultra.c b/keyboards/melgeek/z70ultra/z70ultra.c index 740720681a..552576cd7c 100644 --- a/keyboards/melgeek/z70ultra/z70ultra.c +++ b/keyboards/melgeek/z70ultra/z70ultra.c @@ -18,7 +18,7 @@ #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { {0, CS28_SW1, CS30_SW1, CS29_SW1}, /* RGB10 */ {0, CS28_SW2, CS30_SW2, CS29_SW2}, /* RGB11 */ {0, CS28_SW3, CS30_SW3, CS29_SW3}, /* RGB12 */ diff --git a/keyboards/miller/gm862/gm862.c b/keyboards/miller/gm862/gm862.c index 5af66dd398..d67104838b 100644 --- a/keyboards/miller/gm862/gm862.c +++ b/keyboards/miller/gm862/gm862.c @@ -1,7 +1,7 @@ #include "gm862.h" #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { {0, B_1, A_1, C_1}, {0, B_2, A_2, C_2}, {0, B_3, A_3, C_3}, diff --git a/keyboards/moonlander/moonlander.c b/keyboards/moonlander/moonlander.c index d66b74d973..8688b9efa4 100644 --- a/keyboards/moonlander/moonlander.c +++ b/keyboards/moonlander/moonlander.c @@ -203,7 +203,7 @@ layer_state_t layer_state_set_kb(layer_state_t state) { #ifdef RGB_MATRIX_ENABLE // clang-format off -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location diff --git a/keyboards/mt64rgb/mt64rgb.c b/keyboards/mt64rgb/mt64rgb.c index 73f0e562e7..a0b8e8da71 100644 --- a/keyboards/mt64rgb/mt64rgb.c +++ b/keyboards/mt64rgb/mt64rgb.c @@ -16,7 +16,7 @@ #include "mt64rgb.h" #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location diff --git a/keyboards/mt84/mt84.c b/keyboards/mt84/mt84.c index e15a1ff951..9b00aa635e 100644 --- a/keyboards/mt84/mt84.c +++ b/keyboards/mt84/mt84.c @@ -16,7 +16,7 @@ #include "mt84.h" #ifdef RGB_MATRIX_ENABLE -const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location diff --git a/keyboards/opendeck/32/rev1/rev1.c b/keyboards/opendeck/32/rev1/rev1.c index 297af907e2..91f59a60b7 100644 --- a/keyboards/opendeck/32/rev1/rev1.c +++ b/keyboards/opendeck/32/rev1/rev1.c @@ -17,7 +17,7 @@ #include "rev1.h" #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location diff --git a/keyboards/planck/ez/ez.c b/keyboards/planck/ez/ez.c index 5c68726a01..27cb2a1d1d 100644 --- a/keyboards/planck/ez/ez.c +++ b/keyboards/planck/ez/ez.c @@ -21,7 +21,7 @@ keyboard_config_t keyboard_config; #ifdef RGB_MATRIX_ENABLE -const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location diff --git a/keyboards/planck/light/light.c b/keyboards/planck/light/light.c index 896ec44587..3a53e39985 100644 --- a/keyboards/planck/light/light.c +++ b/keyboards/planck/light/light.c @@ -16,7 +16,7 @@ #include "light.h" -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location diff --git a/keyboards/terrazzo/terrazzo.c b/keyboards/terrazzo/terrazzo.c index e6ba1f6c39..19ac6be491 100644 --- a/keyboards/terrazzo/terrazzo.c +++ b/keyboards/terrazzo/terrazzo.c @@ -21,7 +21,7 @@ #include "print.h" #include "quantum.h" -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * https://cdn-learn.adafruit.com/downloads/pdf/adafruit-15x7-7x15-charlieplex-led-matrix-charliewing-featherwing.pdf */ diff --git a/keyboards/tkc/portico/portico.c b/keyboards/tkc/portico/portico.c index a65a85d242..e3d3a14880 100644 --- a/keyboards/tkc/portico/portico.c +++ b/keyboards/tkc/portico/portico.c @@ -19,7 +19,7 @@ along with this program. If not, see . #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { { 0, C2_1, C3_1, C4_1 }, { 0, C1_1, C3_2, C4_2 }, { 0, C1_2, C2_2, C4_3 }, diff --git a/keyboards/whitefox/whitefox.c b/keyboards/whitefox/whitefox.c index f10f0fd5c4..b17af15127 100644 --- a/keyboards/whitefox/whitefox.c +++ b/keyboards/whitefox/whitefox.c @@ -18,7 +18,7 @@ along with this program. If not, see . #include "whitefox.h" #ifdef LED_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { // The numbers in the comments are the led numbers DXX on the PCB /* Refer to IS31 manual for these locations * driver diff --git a/keyboards/wilba_tech/wt_rgb_backlight.c b/keyboards/wilba_tech/wt_rgb_backlight.c index e0359daab4..77613a3338 100644 --- a/keyboards/wilba_tech/wt_rgb_backlight.c +++ b/keyboards/wilba_tech/wt_rgb_backlight.c @@ -158,7 +158,7 @@ uint32_t g_any_key_hit = 0; // ADDR_2 is not needed. it is here as a dummy #define ISSI_ADDR_1 0x50 -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location @@ -239,7 +239,7 @@ const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { #define ISSI_ADDR_1 0x50 #define ISSI_ADDR_2 0x52 -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location @@ -382,7 +382,7 @@ const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { // set to 0 for write, 1 for read (as per I2C protocol) #define ISSI_ADDR_1 0x74 -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location @@ -414,7 +414,7 @@ const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { #define ISSI_ADDR_2 0x76 // 11101[10] <- SDA #define ISSI_ADDR_3 0x75 // 11101[01] <- SCL -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location @@ -541,7 +541,7 @@ const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { #define ISSI_ADDR_1 0x74 #define ISSI_ADDR_2 0x76 -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location @@ -622,7 +622,7 @@ const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { #define ISSI_ADDR_1 0x74 #define ISSI_ADDR_2 0x77 -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location @@ -709,7 +709,7 @@ const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { #define ISSI_ADDR_1 0x74 #define ISSI_ADDR_2 -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { {0, C1_9, C3_10, C4_10}, // LB1 {0, C1_10, C2_10, C4_11}, // LB2 {0, C1_11, C2_11, C3_11}, // LB3 @@ -729,7 +729,7 @@ const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { #define ISSI_ADDR_1 0x74 #define ISSI_ADDR_2 0x76 -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location diff --git a/keyboards/xbows/knight/knight.c b/keyboards/xbows/knight/knight.c index 1a1aebf18f..539ecb653e 100644 --- a/keyboards/xbows/knight/knight.c +++ b/keyboards/xbows/knight/knight.c @@ -15,7 +15,7 @@ */ #include "knight.h" #ifdef RGB_MATRIX_ENABLE - const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { + const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { {0, C1_3, C2_3, C3_3}, // L01 {0, C1_4, C2_4, C3_4}, // L02 diff --git a/keyboards/xbows/knight_plus/knight_plus.c b/keyboards/xbows/knight_plus/knight_plus.c index f2cf5399b6..c5dd1a5fd6 100644 --- a/keyboards/xbows/knight_plus/knight_plus.c +++ b/keyboards/xbows/knight_plus/knight_plus.c @@ -15,7 +15,7 @@ */ #include "knight_plus.h" #ifdef RGB_MATRIX_ENABLE - const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { + const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { {0, C1_3, C2_3, C3_3}, // L01 {0, C1_4, C2_4, C3_4}, // L02 diff --git a/keyboards/xbows/nature/nature.c b/keyboards/xbows/nature/nature.c index f1b0615845..b7b10d5abb 100644 --- a/keyboards/xbows/nature/nature.c +++ b/keyboards/xbows/nature/nature.c @@ -15,7 +15,7 @@ */ #include "nature.h" #ifdef RGB_MATRIX_ENABLE - const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { + const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { {0, C1_3, C2_3, C3_3}, // L01 {0, C1_4, C2_4, C3_4}, // L02 diff --git a/keyboards/xbows/numpad/numpad.c b/keyboards/xbows/numpad/numpad.c index 0ab677c769..4e05473b67 100644 --- a/keyboards/xbows/numpad/numpad.c +++ b/keyboards/xbows/numpad/numpad.c @@ -15,7 +15,7 @@ */ #include "numpad.h" #ifdef RGB_MATRIX_ENABLE - const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { + const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { {0, C3_3, C2_3, C1_3}, // L01 {0, C3_4, C2_4, C1_4}, // L02 diff --git a/keyboards/xbows/woody/woody.c b/keyboards/xbows/woody/woody.c index 9821f5f655..1027e3ca37 100644 --- a/keyboards/xbows/woody/woody.c +++ b/keyboards/xbows/woody/woody.c @@ -1,6 +1,6 @@ #include "woody.h" #ifdef RGB_MATRIX_ENABLE -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { {0, C8_8, C7_8, C6_8}, // LA17 {0, C9_8, C7_7, C6_7}, // LA16 diff --git a/keyboards/xelus/dawn60/rev1_qmk/rev1_qmk.c b/keyboards/xelus/dawn60/rev1_qmk/rev1_qmk.c index c305ecae14..c6ddef0931 100644 --- a/keyboards/xelus/dawn60/rev1_qmk/rev1_qmk.c +++ b/keyboards/xelus/dawn60/rev1_qmk/rev1_qmk.c @@ -25,7 +25,7 @@ #ifdef RGB_MATRIX_ENABLE LED_TYPE rgb_matrix_ws2812_array[WS2812_LED_TOTAL]; -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location diff --git a/keyboards/xelus/pachi/rgb/rgb.c b/keyboards/xelus/pachi/rgb/rgb.c index ea9812d6b1..6f44b13e12 100644 --- a/keyboards/xelus/pachi/rgb/rgb.c +++ b/keyboards/xelus/pachi/rgb/rgb.c @@ -24,7 +24,7 @@ void matrix_io_delay(void) { __asm__ volatile("nop\nnop\nnop\n"); } #ifdef RGB_MATRIX_ENABLE #include #include "drivers/led/issi/is31fl3741.h" -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = { /* Refer to IS31 manual for these locations * driver * | R location diff --git a/tmk_core/common/progmem.h b/tmk_core/common/progmem.h index 3a7a169682..a70d8e299f 100644 --- a/tmk_core/common/progmem.h +++ b/tmk_core/common/progmem.h @@ -5,6 +5,7 @@ #else # include # define PROGMEM +# define __flash # define PSTR(x) x # define PGM_P const char* # define memcpy_P(dest, src, n) memcpy(dest, src, n) -- cgit v1.2.3 From 26b62f7a6c4e5dd98e9a1e7b60c7e3a927e00ec2 Mon Sep 17 00:00:00 2001 From: a_p_u_r_o Date: Mon, 2 Aug 2021 08:32:26 +0900 Subject: Fix alignment of USB out report buffer 2 -> 4 (#13838) --- tmk_core/protocol/chibios/usb_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tmk_core') diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c index 407b8ea75d..3adbb97994 100644 --- a/tmk_core/protocol/chibios/usb_main.c +++ b/tmk_core/protocol/chibios/usb_main.c @@ -518,7 +518,7 @@ static uint16_t get_hword(uint8_t *p) { * Other Device Required Optional Optional Optional Optional Optional */ -static uint8_t set_report_buf[2] __attribute__((aligned(2))); +static uint8_t set_report_buf[2] __attribute__((aligned(4))); static void set_led_transfer_cb(USBDriver *usbp) { if (usbp->setup[6] == 2) { /* LSB(wLength) */ uint8_t report_id = set_report_buf[0]; -- cgit v1.2.3 From 34de7ca224d613e1ae19a45860e27c15d40254dd Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Tue, 3 Aug 2021 18:49:33 +0100 Subject: Move print/debug files to quantum (#12069) * move print/debug files to quantum * Update comments--- build_test.mk | 2 +- common_features.mk | 10 ++- quantum/logging/debug.c | 25 ++++++ quantum/logging/debug.h | 169 ++++++++++++++++++++++++++++++++++++++++ quantum/logging/nodebug.h | 26 +++++++ quantum/logging/print.c | 27 +++++++ quantum/logging/print.h | 135 ++++++++++++++++++++++++++++++++ quantum/logging/print.mk | 9 +++ quantum/logging/sendchar.c | 20 +++++ quantum/logging/sendchar.h | 33 ++++++++ tmk_core/common.mk | 13 +--- tmk_core/common/debug.c | 25 ------ tmk_core/common/debug.h | 169 ---------------------------------------- tmk_core/common/lib_printf.mk | 9 --- tmk_core/common/nodebug.h | 26 ------- tmk_core/common/print.h | 135 -------------------------------- tmk_core/common/printf.c | 27 ------- tmk_core/common/sendchar.h | 33 -------- tmk_core/common/sendchar_null.c | 19 ----- tmk_core/common/sendchar_uart.c | 23 ------ 20 files changed, 458 insertions(+), 477 deletions(-) create mode 100644 quantum/logging/debug.c create mode 100644 quantum/logging/debug.h create mode 100644 quantum/logging/nodebug.h create mode 100644 quantum/logging/print.c create mode 100644 quantum/logging/print.h create mode 100644 quantum/logging/print.mk create mode 100644 quantum/logging/sendchar.c create mode 100644 quantum/logging/sendchar.h delete mode 100644 tmk_core/common/debug.c delete mode 100644 tmk_core/common/debug.h delete mode 100644 tmk_core/common/lib_printf.mk delete mode 100644 tmk_core/common/nodebug.h delete mode 100644 tmk_core/common/print.h delete mode 100644 tmk_core/common/printf.c delete mode 100644 tmk_core/common/sendchar.h delete mode 100644 tmk_core/common/sendchar_null.c delete mode 100644 tmk_core/common/sendchar_uart.c (limited to 'tmk_core') diff --git a/build_test.mk b/build_test.mk index 4c09bf0278..b6b8782174 100644 --- a/build_test.mk +++ b/build_test.mk @@ -63,7 +63,7 @@ endif $(TEST)_SRC += \ tests/test_common/main.c \ $(LIB_PATH)/printf/printf.c \ - $(COMMON_DIR)/printf.c + $(QUANTUM_PATH)/logging/print.c $(TEST_OBJ)/$(TEST)_SRC := $($(TEST)_SRC) $(TEST_OBJ)/$(TEST)_INC := $($(TEST)_INC) $(VPATH) $(GTEST_INC) diff --git a/common_features.mk b/common_features.mk index 75a9e1f2eb..15b7b464fd 100644 --- a/common_features.mk +++ b/common_features.mk @@ -21,7 +21,15 @@ QUANTUM_SRC += \ $(QUANTUM_DIR)/bitwise.c \ $(QUANTUM_DIR)/led.c \ $(QUANTUM_DIR)/keymap_common.c \ - $(QUANTUM_DIR)/keycode_config.c + $(QUANTUM_DIR)/keycode_config.c \ + $(QUANTUM_DIR)/logging/debug.c \ + $(QUANTUM_DIR)/logging/sendchar.c \ + +VPATH += $(QUANTUM_DIR)/logging +# Fall back to lib/printf if there is no platform provided print +ifeq ("$(wildcard $(TMK_PATH)/common/$(PLATFORM_KEY)/printf.mk)","") + include $(QUANTUM_PATH)/logging/print.mk +endif ifeq ($(strip $(DEBUG_MATRIX_SCAN_RATE_ENABLE)), yes) OPT_DEFS += -DDEBUG_MATRIX_SCAN_RATE diff --git a/quantum/logging/debug.c b/quantum/logging/debug.c new file mode 100644 index 0000000000..ea62deaa8c --- /dev/null +++ b/quantum/logging/debug.c @@ -0,0 +1,25 @@ +/* +Copyright 2011 Jun Wako + +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 . +*/ +#include "debug.h" + +debug_config_t debug_config = { + .enable = false, // + .matrix = false, // + .keyboard = false, // + .mouse = false, // + .reserved = 0 // +}; diff --git a/quantum/logging/debug.h b/quantum/logging/debug.h new file mode 100644 index 0000000000..8415310356 --- /dev/null +++ b/quantum/logging/debug.h @@ -0,0 +1,169 @@ +/* +Copyright 2011 Jun Wako + +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 . +*/ + +#pragma once + +#include +#include "print.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Debug output control + */ +typedef union { + struct { + bool enable : 1; + bool matrix : 1; + bool keyboard : 1; + bool mouse : 1; + uint8_t reserved : 4; + }; + uint8_t raw; +} debug_config_t; + +extern debug_config_t debug_config; + +#ifdef __cplusplus +} +#endif + +/* for backward compatibility */ +#define debug_enable (debug_config.enable) +#define debug_matrix (debug_config.matrix) +#define debug_keyboard (debug_config.keyboard) +#define debug_mouse (debug_config.mouse) + +/* + * Debug print utils + */ +#ifndef NO_DEBUG + +# define dprint(s) \ + do { \ + if (debug_enable) print(s); \ + } while (0) +# define dprintln(s) \ + do { \ + if (debug_enable) println(s); \ + } while (0) +# define dprintf(fmt, ...) \ + do { \ + if (debug_enable) xprintf(fmt, ##__VA_ARGS__); \ + } while (0) +# define dmsg(s) dprintf("%s at %d: %s\n", __FILE__, __LINE__, s) + +/* Deprecated. DO NOT USE these anymore, use dprintf instead. */ +# define debug(s) \ + do { \ + if (debug_enable) print(s); \ + } while (0) +# define debugln(s) \ + do { \ + if (debug_enable) println(s); \ + } while (0) +# define debug_msg(s) \ + do { \ + if (debug_enable) { \ + print(__FILE__); \ + print(" at "); \ + print_dec(__LINE__); \ + print(" in "); \ + print(": "); \ + print(s); \ + } \ + } while (0) +# define debug_dec(data) \ + do { \ + if (debug_enable) print_dec(data); \ + } while (0) +# define debug_decs(data) \ + do { \ + if (debug_enable) print_decs(data); \ + } while (0) +# define debug_hex4(data) \ + do { \ + if (debug_enable) print_hex4(data); \ + } while (0) +# define debug_hex8(data) \ + do { \ + if (debug_enable) print_hex8(data); \ + } while (0) +# define debug_hex16(data) \ + do { \ + if (debug_enable) print_hex16(data); \ + } while (0) +# define debug_hex32(data) \ + do { \ + if (debug_enable) print_hex32(data); \ + } while (0) +# define debug_bin8(data) \ + do { \ + if (debug_enable) print_bin8(data); \ + } while (0) +# define debug_bin16(data) \ + do { \ + if (debug_enable) print_bin16(data); \ + } while (0) +# define debug_bin32(data) \ + do { \ + if (debug_enable) print_bin32(data); \ + } while (0) +# define debug_bin_reverse8(data) \ + do { \ + if (debug_enable) print_bin_reverse8(data); \ + } while (0) +# define debug_bin_reverse16(data) \ + do { \ + if (debug_enable) print_bin_reverse16(data); \ + } while (0) +# define debug_bin_reverse32(data) \ + do { \ + if (debug_enable) print_bin_reverse32(data); \ + } while (0) +# define debug_hex(data) debug_hex8(data) +# define debug_bin(data) debug_bin8(data) +# define debug_bin_reverse(data) debug_bin8(data) + +#else /* NO_DEBUG */ + +# define dprint(s) +# define dprintln(s) +# define dprintf(fmt, ...) +# define dmsg(s) +# define debug(s) +# define debugln(s) +# define debug_msg(s) +# define debug_dec(data) +# define debug_decs(data) +# define debug_hex4(data) +# define debug_hex8(data) +# define debug_hex16(data) +# define debug_hex32(data) +# define debug_bin8(data) +# define debug_bin16(data) +# define debug_bin32(data) +# define debug_bin_reverse8(data) +# define debug_bin_reverse16(data) +# define debug_bin_reverse32(data) +# define debug_hex(data) +# define debug_bin(data) +# define debug_bin_reverse(data) + +#endif /* NO_DEBUG */ diff --git a/quantum/logging/nodebug.h b/quantum/logging/nodebug.h new file mode 100644 index 0000000000..0b176684bd --- /dev/null +++ b/quantum/logging/nodebug.h @@ -0,0 +1,26 @@ +/* +Copyright 2013 Jun Wako + +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 . +*/ + +#pragma once + +#ifndef NO_DEBUG +# define NO_DEBUG +# include "debug.h" +# undef NO_DEBUG +#else +# include "debug.h" +#endif diff --git a/quantum/logging/print.c b/quantum/logging/print.c new file mode 100644 index 0000000000..e8440e55ee --- /dev/null +++ b/quantum/logging/print.c @@ -0,0 +1,27 @@ +/* +Copyright 2011 Jun Wako + +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 . +*/ +#include +#include "sendchar.h" + +// bind lib/printf to console interface - sendchar + +static int8_t null_sendchar_func(uint8_t c) { return 0; } +static sendchar_func_t func = null_sendchar_func; + +void print_set_sendchar(sendchar_func_t send) { func = send; } + +void _putchar(char character) { func(character); } diff --git a/quantum/logging/print.h b/quantum/logging/print.h new file mode 100644 index 0000000000..8c055f549e --- /dev/null +++ b/quantum/logging/print.h @@ -0,0 +1,135 @@ +/* Copyright 2012 Jun Wako */ +/* Very basic print functions, intended to be used with usb_debug_only.c + * http://www.pjrc.com/teensy/ + * Copyright (c) 2008 PJRC.COM, LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +#include +#include +#include "util.h" +#include "sendchar.h" +#include "progmem.h" + +void print_set_sendchar(sendchar_func_t func); + +#ifndef NO_PRINT +# if __has_include_next("_print.h") +# include_next "_print.h" /* Include the platforms print.h */ +# else +// Fall back to lib/printf +# include "printf.h" // lib/printf/printf.h + +// Create user & normal print defines +# define print(s) printf(s) +# define println(s) printf(s "\r\n") +# define xprintf printf +# define uprint(s) printf(s) +# define uprintln(s) printf(s "\r\n") +# define uprintf printf + +# endif /* __has_include_next("_print.h") */ +#else /* NO_PRINT */ +# undef xprintf +// Remove print defines +# define print(s) +# define println(s) +# define xprintf(fmt, ...) +# define uprintf(fmt, ...) +# define uprint(s) +# define uprintln(s) + +#endif /* NO_PRINT */ + +#ifdef USER_PRINT +// Remove normal print defines +# undef print +# undef println +# undef xprintf +# define print(s) +# define println(s) +# define xprintf(fmt, ...) +#endif + +#define print_dec(i) xprintf("%u", i) +#define print_decs(i) xprintf("%d", i) +/* hex */ +#define print_hex4(i) xprintf("%X", i) +#define print_hex8(i) xprintf("%02X", i) +#define print_hex16(i) xprintf("%04X", i) +#define print_hex32(i) xprintf("%08lX", i) +/* binary */ +#define print_bin4(i) xprintf("%04b", i) +#define print_bin8(i) xprintf("%08b", i) +#define print_bin16(i) xprintf("%016b", i) +#define print_bin32(i) xprintf("%032lb", i) +#define print_bin_reverse8(i) xprintf("%08b", bitrev(i)) +#define print_bin_reverse16(i) xprintf("%016b", bitrev16(i)) +#define print_bin_reverse32(i) xprintf("%032lb", bitrev32(i)) +/* print value utility */ +#define print_val_dec(v) xprintf(#v ": %u\n", v) +#define print_val_decs(v) xprintf(#v ": %d\n", v) +#define print_val_hex8(v) xprintf(#v ": %X\n", v) +#define print_val_hex16(v) xprintf(#v ": %02X\n", v) +#define print_val_hex32(v) xprintf(#v ": %04lX\n", v) +#define print_val_bin8(v) xprintf(#v ": %08b\n", v) +#define print_val_bin16(v) xprintf(#v ": %016b\n", v) +#define print_val_bin32(v) xprintf(#v ": %032lb\n", v) +#define print_val_bin_reverse8(v) xprintf(#v ": %08b\n", bitrev(v)) +#define print_val_bin_reverse16(v) xprintf(#v ": %016b\n", bitrev16(v)) +#define print_val_bin_reverse32(v) xprintf(#v ": %032lb\n", bitrev32(v)) + +// User print disables the normal print messages in the body of QMK/TMK code and +// is meant as a lightweight alternative to NOPRINT. Use it when you only want to do +// a spot of debugging but lack flash resources for allowing all of the codebase to +// print (and store their wasteful strings). +// +// !!! DO NOT USE USER PRINT CALLS IN THE BODY OF QMK/TMK !!! + +/* decimal */ +#define uprint_dec(i) uprintf("%u", i) +#define uprint_decs(i) uprintf("%d", i) +/* hex */ +#define uprint_hex4(i) uprintf("%X", i) +#define uprint_hex8(i) uprintf("%02X", i) +#define uprint_hex16(i) uprintf("%04X", i) +#define uprint_hex32(i) uprintf("%08lX", i) +/* binary */ +#define uprint_bin4(i) uprintf("%04b", i) +#define uprint_bin8(i) uprintf("%08b", i) +#define uprint_bin16(i) uprintf("%016b", i) +#define uprint_bin32(i) uprintf("%032lb", i) +#define uprint_bin_reverse8(i) uprintf("%08b", bitrev(i)) +#define uprint_bin_reverse16(i) uprintf("%016b", bitrev16(i)) +#define uprint_bin_reverse32(i) uprintf("%032lb", bitrev32(i)) +/* print value utility */ +#define uprint_val_dec(v) uprintf(#v ": %u\n", v) +#define uprint_val_decs(v) uprintf(#v ": %d\n", v) +#define uprint_val_hex8(v) uprintf(#v ": %X\n", v) +#define uprint_val_hex16(v) uprintf(#v ": %02X\n", v) +#define uprint_val_hex32(v) uprintf(#v ": %04lX\n", v) +#define uprint_val_bin8(v) uprintf(#v ": %08b\n", v) +#define uprint_val_bin16(v) uprintf(#v ": %016b\n", v) +#define uprint_val_bin32(v) uprintf(#v ": %032lb\n", v) +#define uprint_val_bin_reverse8(v) uprintf(#v ": %08b\n", bitrev(v)) +#define uprint_val_bin_reverse16(v) uprintf(#v ": %016b\n", bitrev16(v)) +#define uprint_val_bin_reverse32(v) uprintf(#v ": %032lb\n", bitrev32(v)) diff --git a/quantum/logging/print.mk b/quantum/logging/print.mk new file mode 100644 index 0000000000..67c004192d --- /dev/null +++ b/quantum/logging/print.mk @@ -0,0 +1,9 @@ +PRINTF_PATH = $(LIB_PATH)/printf + +VPATH += $(PRINTF_PATH) +SRC += $(PRINTF_PATH)/printf.c +QUANTUM_SRC +=$(QUANTUM_DIR)/logging/print.c +OPT_DEFS += -DPRINTF_DISABLE_SUPPORT_FLOAT +OPT_DEFS += -DPRINTF_DISABLE_SUPPORT_EXPONENTIAL +OPT_DEFS += -DPRINTF_DISABLE_SUPPORT_LONG_LONG +OPT_DEFS += -DPRINTF_DISABLE_SUPPORT_PTRDIFF_T diff --git a/quantum/logging/sendchar.c b/quantum/logging/sendchar.c new file mode 100644 index 0000000000..9422382f6f --- /dev/null +++ b/quantum/logging/sendchar.c @@ -0,0 +1,20 @@ +/* +Copyright 2011 Jun Wako + +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 . +*/ +#include "sendchar.h" + +/* default noop "null" implementation */ +__attribute__((weak)) int8_t sendchar(uint8_t c) { return 0; } diff --git a/quantum/logging/sendchar.h b/quantum/logging/sendchar.h new file mode 100644 index 0000000000..edcddaa6bb --- /dev/null +++ b/quantum/logging/sendchar.h @@ -0,0 +1,33 @@ +/* +Copyright 2011 Jun Wako + +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 . +*/ + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int8_t (*sendchar_func_t)(uint8_t c); + +/* transmit a character. return 0 on success, -1 on error. */ +int8_t sendchar(uint8_t c); + +#ifdef __cplusplus +} +#endif diff --git a/tmk_core/common.mk b/tmk_core/common.mk index 2f8f81126a..bd4142364c 100644 --- a/tmk_core/common.mk +++ b/tmk_core/common.mk @@ -8,22 +8,16 @@ TMK_COMMON_SRC += $(COMMON_DIR)/host.c \ $(COMMON_DIR)/action_macro.c \ $(COMMON_DIR)/action_layer.c \ $(COMMON_DIR)/action_util.c \ - $(COMMON_DIR)/debug.c \ - $(COMMON_DIR)/sendchar_null.c \ $(COMMON_DIR)/eeconfig.c \ $(COMMON_DIR)/report.c \ + $(COMMON_DIR)/sync_timer.c \ $(COMMON_DIR)/usb_util.c \ $(PLATFORM_COMMON_DIR)/suspend.c \ $(PLATFORM_COMMON_DIR)/timer.c \ - $(COMMON_DIR)/sync_timer.c \ $(PLATFORM_COMMON_DIR)/bootloader.c \ -# Use platform provided print - fall back to lib/printf -ifneq ("$(wildcard $(TMK_PATH)/$(PLATFORM_COMMON_DIR)/printf.mk)","") - include $(TMK_PATH)/$(PLATFORM_COMMON_DIR)/printf.mk -else - include $(TMK_PATH)/$(COMMON_DIR)/lib_printf.mk -endif +# Use platform provided print if it exists +-include $(TMK_PATH)/$(PLATFORM_COMMON_DIR)/printf.mk SHARED_EP_ENABLE = no MOUSE_SHARED_EP ?= yes @@ -55,6 +49,7 @@ endif ifeq ($(strip $(CONSOLE_ENABLE)), yes) TMK_COMMON_DEFS += -DCONSOLE_ENABLE else + # TODO: decouple this so other print backends can exist TMK_COMMON_DEFS += -DNO_PRINT TMK_COMMON_DEFS += -DNO_DEBUG endif diff --git a/tmk_core/common/debug.c b/tmk_core/common/debug.c deleted file mode 100644 index ea62deaa8c..0000000000 --- a/tmk_core/common/debug.c +++ /dev/null @@ -1,25 +0,0 @@ -/* -Copyright 2011 Jun Wako - -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 . -*/ -#include "debug.h" - -debug_config_t debug_config = { - .enable = false, // - .matrix = false, // - .keyboard = false, // - .mouse = false, // - .reserved = 0 // -}; diff --git a/tmk_core/common/debug.h b/tmk_core/common/debug.h deleted file mode 100644 index 3d2e2315ef..0000000000 --- a/tmk_core/common/debug.h +++ /dev/null @@ -1,169 +0,0 @@ -/* -Copyright 2011 Jun Wako - -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 . -*/ - -#pragma once - -#include -#include "print.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Debug output control - */ -typedef union { - struct { - bool enable : 1; - bool matrix : 1; - bool keyboard : 1; - bool mouse : 1; - uint8_t reserved : 4; - }; - uint8_t raw; -} debug_config_t; - -extern debug_config_t debug_config; - -#ifdef __cplusplus -} -#endif - -/* for backward compatibility */ -#define debug_enable (debug_config.enable) -#define debug_matrix (debug_config.matrix) -#define debug_keyboard (debug_config.keyboard) -#define debug_mouse (debug_config.mouse) - -/* - * Debug print utils - */ -#ifndef NO_DEBUG - -# define dprint(s) \ - do { \ - if (debug_enable) print(s); \ - } while (0) -# define dprintln(s) \ - do { \ - if (debug_enable) println(s); \ - } while (0) -# define dprintf(fmt, ...) \ - do { \ - if (debug_enable) xprintf(fmt, ##__VA_ARGS__); \ - } while (0) -# define dmsg(s) dprintf("%s at %s: %S\n", __FILE__, __LINE__, PSTR(s)) - -/* Deprecated. DO NOT USE these anymore, use dprintf instead. */ -# define debug(s) \ - do { \ - if (debug_enable) print(s); \ - } while (0) -# define debugln(s) \ - do { \ - if (debug_enable) println(s); \ - } while (0) -# define debug_msg(s) \ - do { \ - if (debug_enable) { \ - print(__FILE__); \ - print(" at "); \ - print_dec(__LINE__); \ - print(" in "); \ - print(": "); \ - print(s); \ - } \ - } while (0) -# define debug_dec(data) \ - do { \ - if (debug_enable) print_dec(data); \ - } while (0) -# define debug_decs(data) \ - do { \ - if (debug_enable) print_decs(data); \ - } while (0) -# define debug_hex4(data) \ - do { \ - if (debug_enable) print_hex4(data); \ - } while (0) -# define debug_hex8(data) \ - do { \ - if (debug_enable) print_hex8(data); \ - } while (0) -# define debug_hex16(data) \ - do { \ - if (debug_enable) print_hex16(data); \ - } while (0) -# define debug_hex32(data) \ - do { \ - if (debug_enable) print_hex32(data); \ - } while (0) -# define debug_bin8(data) \ - do { \ - if (debug_enable) print_bin8(data); \ - } while (0) -# define debug_bin16(data) \ - do { \ - if (debug_enable) print_bin16(data); \ - } while (0) -# define debug_bin32(data) \ - do { \ - if (debug_enable) print_bin32(data); \ - } while (0) -# define debug_bin_reverse8(data) \ - do { \ - if (debug_enable) print_bin_reverse8(data); \ - } while (0) -# define debug_bin_reverse16(data) \ - do { \ - if (debug_enable) print_bin_reverse16(data); \ - } while (0) -# define debug_bin_reverse32(data) \ - do { \ - if (debug_enable) print_bin_reverse32(data); \ - } while (0) -# define debug_hex(data) debug_hex8(data) -# define debug_bin(data) debug_bin8(data) -# define debug_bin_reverse(data) debug_bin8(data) - -#else /* NO_DEBUG */ - -# define dprint(s) -# define dprintln(s) -# define dprintf(fmt, ...) -# define dmsg(s) -# define debug(s) -# define debugln(s) -# define debug_msg(s) -# define debug_dec(data) -# define debug_decs(data) -# define debug_hex4(data) -# define debug_hex8(data) -# define debug_hex16(data) -# define debug_hex32(data) -# define debug_bin8(data) -# define debug_bin16(data) -# define debug_bin32(data) -# define debug_bin_reverse8(data) -# define debug_bin_reverse16(data) -# define debug_bin_reverse32(data) -# define debug_hex(data) -# define debug_bin(data) -# define debug_bin_reverse(data) - -#endif /* NO_DEBUG */ diff --git a/tmk_core/common/lib_printf.mk b/tmk_core/common/lib_printf.mk deleted file mode 100644 index 10d2d8468d..0000000000 --- a/tmk_core/common/lib_printf.mk +++ /dev/null @@ -1,9 +0,0 @@ -PRINTF_PATH = $(LIB_PATH)/printf - -TMK_COMMON_SRC += $(PRINTF_PATH)/printf.c -TMK_COMMON_SRC += $(COMMON_DIR)/printf.c -TMK_COMMON_DEFS += -DPRINTF_DISABLE_SUPPORT_FLOAT -TMK_COMMON_DEFS += -DPRINTF_DISABLE_SUPPORT_EXPONENTIAL -TMK_COMMON_DEFS += -DPRINTF_DISABLE_SUPPORT_LONG_LONG -TMK_COMMON_DEFS += -DPRINTF_DISABLE_SUPPORT_PTRDIFF_T -VPATH += $(PRINTF_PATH) diff --git a/tmk_core/common/nodebug.h b/tmk_core/common/nodebug.h deleted file mode 100644 index 0b176684bd..0000000000 --- a/tmk_core/common/nodebug.h +++ /dev/null @@ -1,26 +0,0 @@ -/* -Copyright 2013 Jun Wako - -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 . -*/ - -#pragma once - -#ifndef NO_DEBUG -# define NO_DEBUG -# include "debug.h" -# undef NO_DEBUG -#else -# include "debug.h" -#endif diff --git a/tmk_core/common/print.h b/tmk_core/common/print.h deleted file mode 100644 index 8c055f549e..0000000000 --- a/tmk_core/common/print.h +++ /dev/null @@ -1,135 +0,0 @@ -/* Copyright 2012 Jun Wako */ -/* Very basic print functions, intended to be used with usb_debug_only.c - * http://www.pjrc.com/teensy/ - * Copyright (c) 2008 PJRC.COM, LLC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#pragma once - -#include -#include -#include "util.h" -#include "sendchar.h" -#include "progmem.h" - -void print_set_sendchar(sendchar_func_t func); - -#ifndef NO_PRINT -# if __has_include_next("_print.h") -# include_next "_print.h" /* Include the platforms print.h */ -# else -// Fall back to lib/printf -# include "printf.h" // lib/printf/printf.h - -// Create user & normal print defines -# define print(s) printf(s) -# define println(s) printf(s "\r\n") -# define xprintf printf -# define uprint(s) printf(s) -# define uprintln(s) printf(s "\r\n") -# define uprintf printf - -# endif /* __has_include_next("_print.h") */ -#else /* NO_PRINT */ -# undef xprintf -// Remove print defines -# define print(s) -# define println(s) -# define xprintf(fmt, ...) -# define uprintf(fmt, ...) -# define uprint(s) -# define uprintln(s) - -#endif /* NO_PRINT */ - -#ifdef USER_PRINT -// Remove normal print defines -# undef print -# undef println -# undef xprintf -# define print(s) -# define println(s) -# define xprintf(fmt, ...) -#endif - -#define print_dec(i) xprintf("%u", i) -#define print_decs(i) xprintf("%d", i) -/* hex */ -#define print_hex4(i) xprintf("%X", i) -#define print_hex8(i) xprintf("%02X", i) -#define print_hex16(i) xprintf("%04X", i) -#define print_hex32(i) xprintf("%08lX", i) -/* binary */ -#define print_bin4(i) xprintf("%04b", i) -#define print_bin8(i) xprintf("%08b", i) -#define print_bin16(i) xprintf("%016b", i) -#define print_bin32(i) xprintf("%032lb", i) -#define print_bin_reverse8(i) xprintf("%08b", bitrev(i)) -#define print_bin_reverse16(i) xprintf("%016b", bitrev16(i)) -#define print_bin_reverse32(i) xprintf("%032lb", bitrev32(i)) -/* print value utility */ -#define print_val_dec(v) xprintf(#v ": %u\n", v) -#define print_val_decs(v) xprintf(#v ": %d\n", v) -#define print_val_hex8(v) xprintf(#v ": %X\n", v) -#define print_val_hex16(v) xprintf(#v ": %02X\n", v) -#define print_val_hex32(v) xprintf(#v ": %04lX\n", v) -#define print_val_bin8(v) xprintf(#v ": %08b\n", v) -#define print_val_bin16(v) xprintf(#v ": %016b\n", v) -#define print_val_bin32(v) xprintf(#v ": %032lb\n", v) -#define print_val_bin_reverse8(v) xprintf(#v ": %08b\n", bitrev(v)) -#define print_val_bin_reverse16(v) xprintf(#v ": %016b\n", bitrev16(v)) -#define print_val_bin_reverse32(v) xprintf(#v ": %032lb\n", bitrev32(v)) - -// User print disables the normal print messages in the body of QMK/TMK code and -// is meant as a lightweight alternative to NOPRINT. Use it when you only want to do -// a spot of debugging but lack flash resources for allowing all of the codebase to -// print (and store their wasteful strings). -// -// !!! DO NOT USE USER PRINT CALLS IN THE BODY OF QMK/TMK !!! - -/* decimal */ -#define uprint_dec(i) uprintf("%u", i) -#define uprint_decs(i) uprintf("%d", i) -/* hex */ -#define uprint_hex4(i) uprintf("%X", i) -#define uprint_hex8(i) uprintf("%02X", i) -#define uprint_hex16(i) uprintf("%04X", i) -#define uprint_hex32(i) uprintf("%08lX", i) -/* binary */ -#define uprint_bin4(i) uprintf("%04b", i) -#define uprint_bin8(i) uprintf("%08b", i) -#define uprint_bin16(i) uprintf("%016b", i) -#define uprint_bin32(i) uprintf("%032lb", i) -#define uprint_bin_reverse8(i) uprintf("%08b", bitrev(i)) -#define uprint_bin_reverse16(i) uprintf("%016b", bitrev16(i)) -#define uprint_bin_reverse32(i) uprintf("%032lb", bitrev32(i)) -/* print value utility */ -#define uprint_val_dec(v) uprintf(#v ": %u\n", v) -#define uprint_val_decs(v) uprintf(#v ": %d\n", v) -#define uprint_val_hex8(v) uprintf(#v ": %X\n", v) -#define uprint_val_hex16(v) uprintf(#v ": %02X\n", v) -#define uprint_val_hex32(v) uprintf(#v ": %04lX\n", v) -#define uprint_val_bin8(v) uprintf(#v ": %08b\n", v) -#define uprint_val_bin16(v) uprintf(#v ": %016b\n", v) -#define uprint_val_bin32(v) uprintf(#v ": %032lb\n", v) -#define uprint_val_bin_reverse8(v) uprintf(#v ": %08b\n", bitrev(v)) -#define uprint_val_bin_reverse16(v) uprintf(#v ": %016b\n", bitrev16(v)) -#define uprint_val_bin_reverse32(v) uprintf(#v ": %032lb\n", bitrev32(v)) diff --git a/tmk_core/common/printf.c b/tmk_core/common/printf.c deleted file mode 100644 index e8440e55ee..0000000000 --- a/tmk_core/common/printf.c +++ /dev/null @@ -1,27 +0,0 @@ -/* -Copyright 2011 Jun Wako - -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 . -*/ -#include -#include "sendchar.h" - -// bind lib/printf to console interface - sendchar - -static int8_t null_sendchar_func(uint8_t c) { return 0; } -static sendchar_func_t func = null_sendchar_func; - -void print_set_sendchar(sendchar_func_t send) { func = send; } - -void _putchar(char character) { func(character); } diff --git a/tmk_core/common/sendchar.h b/tmk_core/common/sendchar.h deleted file mode 100644 index edcddaa6bb..0000000000 --- a/tmk_core/common/sendchar.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -Copyright 2011 Jun Wako - -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 . -*/ - -#pragma once - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef int8_t (*sendchar_func_t)(uint8_t c); - -/* transmit a character. return 0 on success, -1 on error. */ -int8_t sendchar(uint8_t c); - -#ifdef __cplusplus -} -#endif diff --git a/tmk_core/common/sendchar_null.c b/tmk_core/common/sendchar_null.c deleted file mode 100644 index fb67f70866..0000000000 --- a/tmk_core/common/sendchar_null.c +++ /dev/null @@ -1,19 +0,0 @@ -/* -Copyright 2011 Jun Wako - -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 . -*/ -#include "sendchar.h" - -__attribute__((weak)) int8_t sendchar(uint8_t c) { return 0; } diff --git a/tmk_core/common/sendchar_uart.c b/tmk_core/common/sendchar_uart.c deleted file mode 100644 index 2fc48bafff..0000000000 --- a/tmk_core/common/sendchar_uart.c +++ /dev/null @@ -1,23 +0,0 @@ -/* -Copyright 2011 Jun Wako - -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 . -*/ -#include "uart.h" -#include "sendchar.h" - -int8_t sendchar(uint8_t c) { - uart_putchar(c); - return 0; -} -- cgit v1.2.3 From 1409b368517a8ce9af1320acc75f7a8fbcdfca18 Mon Sep 17 00:00:00 2001 From: Joakim Tufvegren Date: Tue, 3 Aug 2021 23:38:37 +0200 Subject: Remove the #10088 hotfix for Teensy 3.1-like Input:Club keyboards (#12870) * Remove the #10088 hotfix for K20x MCU:s. It seems to _cause_ the issue it intended to solve there. * Cleaner way of removing #10088 hotfix. Now only affects Ergodox Infinity, Whitefox and K-type, though. Switches over Ergodox Infinity to the `IC_TEENSY_3_1` board, since that was a nice place to implement the `restart_usb_driver` override. However, I would guess this issue is present for other K20x/Teensy 3.1 boards as well... * Fix comment regarding `IC_TEENSY_3_1` for all keyboards using it.--- keyboards/ergodox_infinity/rules.mk | 7 +++++++ keyboards/k_type/rules.mk | 3 ++- keyboards/whitefox/rules.mk | 8 +++----- platforms/chibios/IC_TEENSY_3_1/board/board.c | 5 +++++ tmk_core/protocol/chibios/usb_main.c | 2 +- 5 files changed, 18 insertions(+), 7 deletions(-) (limited to 'tmk_core') diff --git a/keyboards/ergodox_infinity/rules.mk b/keyboards/ergodox_infinity/rules.mk index fbd52cd257..6c490ca0d8 100644 --- a/keyboards/ergodox_infinity/rules.mk +++ b/keyboards/ergodox_infinity/rules.mk @@ -4,6 +4,13 @@ MCU = MK20DX256 # Bootloader selection BOOTLOADER = kiibohd +# Board: it should exist either in /os/hal/boards/ +# or /boards +# This board was copied from PJRC_TEENSY_3_1. The only difference should be a +# hack to ensure the watchdog has started before trying to disable it, and an +# override to disable restart of USB driver after returning from suspend. +BOARD = IC_TEENSY_3_1 + # Build Options # comment out to disable the options. # diff --git a/keyboards/k_type/rules.mk b/keyboards/k_type/rules.mk index 369cab4f09..ffd350ef8a 100644 --- a/keyboards/k_type/rules.mk +++ b/keyboards/k_type/rules.mk @@ -7,7 +7,8 @@ BOOTLOADER = kiibohd # Board: it should exist either in /os/hal/boards/ # or /boards # This board was copied from PJRC_TEENSY_3_1. The only difference should be a -# hack to ensure the watchdog has started before trying to disable it. +# hack to ensure the watchdog has started before trying to disable it, and an +# override to disable restart of USB driver after returning from suspend. BOARD = IC_TEENSY_3_1 # Build Options diff --git a/keyboards/whitefox/rules.mk b/keyboards/whitefox/rules.mk index 7c1d0c3def..cc02f3472e 100644 --- a/keyboards/whitefox/rules.mk +++ b/keyboards/whitefox/rules.mk @@ -6,11 +6,9 @@ BOOTLOADER = kiibohd # Board: it should exist either in /os/hal/boards/ # or /boards -# - BOARD = -# - PJRC_TEENSY_LC for Teensy LC -# - PJRC_TEENSY_3 for Teensy 3.0 -# - PJRC_TEENSY_3_1 for Teensy 3.1 or 3.2 -# - MCHCK_K20 for Infinity KB +# This board was copied from PJRC_TEENSY_3_1. The only difference should be a +# hack to ensure the watchdog has started before trying to disable it, and an +# override to disable restart of USB driver after returning from suspend. BOARD = IC_TEENSY_3_1 # Build Options diff --git a/platforms/chibios/IC_TEENSY_3_1/board/board.c b/platforms/chibios/IC_TEENSY_3_1/board/board.c index 36ae8051ee..424e0c975b 100644 --- a/platforms/chibios/IC_TEENSY_3_1/board/board.c +++ b/platforms/chibios/IC_TEENSY_3_1/board/board.c @@ -144,3 +144,8 @@ void __early_init(void) { * @todo Add your board-specific code, if any. */ void boardInit(void) {} + + +void restart_usb_driver(USBDriver *usbp) { + // Do nothing. Restarting the USB driver on these boards breaks it. +} diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c index 3adbb97994..441cfab970 100644 --- a/tmk_core/protocol/chibios/usb_main.c +++ b/tmk_core/protocol/chibios/usb_main.c @@ -705,7 +705,7 @@ void init_usb_driver(USBDriver *usbp) { chVTObjectInit(&keyboard_idle_timer); } -void restart_usb_driver(USBDriver *usbp) { +__attribute__((weak)) void restart_usb_driver(USBDriver *usbp) { usbStop(usbp); usbDisconnectBus(usbp); -- cgit v1.2.3 From 982b782ce30e421f2ad3034bc86efdec58c2ea88 Mon Sep 17 00:00:00 2001 From: Joakim Tufvegren Date: Tue, 3 Aug 2021 23:39:34 +0200 Subject: Trigger a wakeup after USB Reset on ChibiOS. (#12831) After a USB Reset event the device must, according to the spec wake up from any suspend state, so the Configured event that arrives afterwards should be interpreted as an implicit wakeup.--- tmk_core/protocol/chibios/usb_main.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'tmk_core') diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c index 441cfab970..e5edd74dcb 100644 --- a/tmk_core/protocol/chibios/usb_main.c +++ b/tmk_core/protocol/chibios/usb_main.c @@ -415,14 +415,18 @@ static inline void usb_event_wakeup_handler(void) { #endif /* SLEEP_LED_ENABLE */ } +bool last_suspend_state = false; + void usb_event_queue_task(void) { usbevent_t event; while (usb_event_queue_dequeue(&event)) { switch (event) { case USB_EVENT_SUSPEND: + last_suspend_state = true; usb_event_suspend_handler(); break; case USB_EVENT_WAKEUP: + last_suspend_state = false; usb_event_wakeup_handler(); break; default: @@ -464,6 +468,9 @@ static void usb_event_cb(USBDriver *usbp, usbevent_t event) { qmkusbConfigureHookI(&drivers.array[i].driver); } osalSysUnlockFromISR(); + if (last_suspend_state) { + usb_event_queue_enqueue(USB_EVENT_WAKEUP); + } return; case USB_EVENT_SUSPEND: usb_event_queue_enqueue(USB_EVENT_SUSPEND); -- cgit v1.2.3 From bcb6e23387290afb64712314bfb095f8d96c1a4e Mon Sep 17 00:00:00 2001 From: JohSchneider Date: Thu, 5 Aug 2021 21:51:24 +0000 Subject: Arm ps2 mouse interrupt (#6490) * ps2_mouse on ARM: an interrupt-version of the ps2-mouse code ported to ARM/chibios * ps2_mouse on ARM: link EXT callback-channel selection to the user defined PS2_LINE_CLOCK * ps2_mouse on ARM: replace DELAY_X defines with hardware-agnostic wait_X * ps2_mouse on ARM: replace chibios-specific defines for the pins/lines with defines from quantum/config_common.h and drop the '_LINE' component from teh define name * ps2_mouse on ARM: expose the software-intterupt port as a user editable define * Update docs/feature_ps2_mouse.md Co-Authored-By: Hugo van Kemenade * Update feature_ps2_mouse.md * use a define to deduce the PS_DATA_PORT instead * reduce all-zero extcfg to oneliner * ps2_mouse: use generic wait instead of avr-delay * Update docs/feature_ps2_mouse.md * ps2_mouse: changes for new chibios version (17.6.0 -> 19.1.0) replacing the legacy externa-interrupt driver with pal-callbacks * ps2_mouse: use PLATFORM_KEY Co-Authored-By: Joel Challis * ps2_mouse: clang-format corrections * ps2_mouse: add systemlocks using the chibios equivalent to AVRs cli: chSys[Unl|L]ock Co-authored-by: Johannes Co-authored-by: Hugo van Kemenade Co-authored-by: Joel Challis --- docs/feature_ps2_mouse.md | 28 +++++++++++- tmk_core/protocol.mk | 4 +- tmk_core/protocol/ps2_interrupt.c | 91 +++++++++++++++++++++++++++++++++----- tmk_core/protocol/ps2_io_chibios.c | 55 +++++++++++++++++++++++ tmk_core/protocol/ps2_mouse.c | 14 +++--- 5 files changed, 172 insertions(+), 20 deletions(-) create mode 100644 tmk_core/protocol/ps2_io_chibios.c (limited to 'tmk_core') diff --git a/docs/feature_ps2_mouse.md b/docs/feature_ps2_mouse.md index 8e84e22d8a..00c7ee72ee 100644 --- a/docs/feature_ps2_mouse.md +++ b/docs/feature_ps2_mouse.md @@ -50,7 +50,7 @@ In your keyboard config.h: #endif ``` -## Interrupt Version :id=interrupt-version +### Interrupt Version (AVR/ATMega32u4) :id=interrupt-version-avr The following example uses D2 for clock and D5 for data. You can use any INT or PCINT pin for clock, and any pin for data. @@ -88,7 +88,31 @@ In your keyboard config.h: #endif ``` -## USART Version :id=usart-version +### Interrupt Version (ARM chibios) :id=interrupt-version-chibios + +Pretty much any two pins can be used for the (software) interrupt variant on ARM cores. The example below uses A8 for clock, and A9 for data. + +In rules.mk: + +``` +PS2_MOUSE_ENABLE = yes +PS2_USE_INT = yes +``` + +In your keyboard config.h: + +```c +#define PS2_CLOCK A8 +#define PS2_DATA A9 +``` + +And in the chibios specifig halconf.h: +```c +#define PAL_USE_CALLBACKS TRUE +``` + + +### USART Version :id=usart-version To use USART on the ATMega32u4, you have to use PD5 for clock and PD2 for data. If one of those are unavailable, you need to use interrupt version. diff --git a/tmk_core/protocol.mk b/tmk_core/protocol.mk index cc87e83478..b61f2f5463 100644 --- a/tmk_core/protocol.mk +++ b/tmk_core/protocol.mk @@ -14,13 +14,13 @@ endif ifeq ($(strip $(PS2_USE_INT)), yes) SRC += protocol/ps2_interrupt.c - SRC += protocol/ps2_io_avr.c + SRC += protocol/ps2_io_$(PLATFORM_KEY).c OPT_DEFS += -DPS2_USE_INT endif ifeq ($(strip $(PS2_USE_USART)), yes) SRC += protocol/ps2_usart.c - SRC += protocol/ps2_io_avr.c + SRC += protocol/ps2_io_$(PLATFORM_KEY).c OPT_DEFS += -DPS2_USE_USART endif diff --git a/tmk_core/protocol/ps2_interrupt.c b/tmk_core/protocol/ps2_interrupt.c index 5afc8a82e4..780040d152 100644 --- a/tmk_core/protocol/ps2_interrupt.c +++ b/tmk_core/protocol/ps2_interrupt.c @@ -40,11 +40,19 @@ POSSIBILITY OF SUCH DAMAGE. */ #include -#include -#include + +#if defined(__AVR__) +# include +#elif defined(PROTOCOL_CHIBIOS) // TODO: or STM32 ? +// chibiOS headers +# include "ch.h" +# include "hal.h" +#endif + #include "ps2.h" #include "ps2_io.h" #include "print.h" +#include "wait.h" #define WAIT(stat, us, err) \ do { \ @@ -61,12 +69,30 @@ static inline void pbuf_enqueue(uint8_t data); static inline bool pbuf_has_data(void); static inline void pbuf_clear(void); +#if defined(PROTOCOL_CHIBIOS) +void ps2_interrupt_service_routine(void); +void palCallback(void *arg) { ps2_interrupt_service_routine(); } + +# define PS2_INT_INIT() \ + { palSetLineMode(PS2_CLOCK, PAL_MODE_INPUT); } \ + while (0) +# define PS2_INT_ON() \ + { \ + palEnableLineEvent(PS2_CLOCK, PAL_EVENT_MODE_FALLING_EDGE); \ + palSetLineCallback(PS2_CLOCK, palCallback, NULL); \ + } \ + while (0) +# define PS2_INT_OFF() \ + { palDisableLineEvent(PS2_CLOCK); } \ + while (0) +#endif // PROTOCOL_CHIBIOS + void ps2_host_init(void) { idle(); PS2_INT_INIT(); PS2_INT_ON(); // POR(150-2000ms) plus BAT(300-500ms) may take 2.5sec([3]p.20) - //_delay_ms(2500); + // wait_ms(2500); } uint8_t ps2_host_send(uint8_t data) { @@ -77,7 +103,7 @@ uint8_t ps2_host_send(uint8_t data) { /* terminate a transmission if we have */ inhibit(); - _delay_us(100); // 100us [4]p.13, [5]p.50 + wait_us(100); // 100us [4]p.13, [5]p.50 /* 'Request to Send' and Start bit */ data_lo(); @@ -86,7 +112,6 @@ uint8_t ps2_host_send(uint8_t data) { /* Data bit[2-9] */ for (uint8_t i = 0; i < 8; i++) { - _delay_us(15); if (data & (1 << i)) { parity = !parity; data_hi(); @@ -98,7 +123,7 @@ uint8_t ps2_host_send(uint8_t data) { } /* Parity bit */ - _delay_us(15); + wait_us(15); if (parity) { data_hi(); } else { @@ -108,7 +133,7 @@ uint8_t ps2_host_send(uint8_t data) { WAIT(clock_lo, 50, 5); /* Stop bit */ - _delay_us(15); + wait_us(15); data_hi(); /* Ack */ @@ -132,7 +157,7 @@ uint8_t ps2_host_recv_response(void) { // Command may take 25ms/20ms at most([5]p.46, [3]p.21) uint8_t retry = 25; while (retry-- && !pbuf_has_data()) { - _delay_ms(1); + wait_ms(1); } return pbuf_dequeue(); } @@ -148,7 +173,7 @@ uint8_t ps2_host_recv(void) { } } -ISR(PS2_INT_VECT) { +void ps2_interrupt_service_routine(void) { static enum { INIT, START, @@ -218,6 +243,10 @@ RETURN: return; } +#if defined(__AVR__) +ISR(PS2_INT_VECT) { ps2_interrupt_service_routine(); } +#endif + /* send LED state to keyboard */ void ps2_host_set_led(uint8_t led) { ps2_host_send(0xED); @@ -232,8 +261,13 @@ static uint8_t pbuf[PBUF_SIZE]; static uint8_t pbuf_head = 0; static uint8_t pbuf_tail = 0; static inline void pbuf_enqueue(uint8_t data) { +#if defined(__AVR__) uint8_t sreg = SREG; cli(); +#elif defined(PROTOCOL_CHIBIOS) + chSysLockFromISR(); +#endif + uint8_t next = (pbuf_head + 1) % PBUF_SIZE; if (next != pbuf_tail) { pbuf[pbuf_head] = data; @@ -241,31 +275,66 @@ static inline void pbuf_enqueue(uint8_t data) { } else { print("pbuf: full\n"); } + +#if defined(__AVR__) SREG = sreg; +#elif defined(PROTOCOL_CHIBIOS) + chSysUnlockFromISR(); +#endif } static inline uint8_t pbuf_dequeue(void) { uint8_t val = 0; +#if defined(__AVR__) uint8_t sreg = SREG; cli(); +#elif defined(PROTOCOL_CHIBIOS) + chSysLock(); +#endif + if (pbuf_head != pbuf_tail) { val = pbuf[pbuf_tail]; pbuf_tail = (pbuf_tail + 1) % PBUF_SIZE; } + +#if defined(__AVR__) SREG = sreg; +#elif defined(PROTOCOL_CHIBIOS) + chSysUnlock(); +#endif return val; } static inline bool pbuf_has_data(void) { +#if defined(__AVR__) uint8_t sreg = SREG; cli(); +#elif defined(PROTOCOL_CHIBIOS) + chSysLock(); +#endif + bool has_data = (pbuf_head != pbuf_tail); - SREG = sreg; + +#if defined(__AVR__) + SREG = sreg; +#elif defined(PROTOCOL_CHIBIOS) + chSysUnlock(); +#endif return has_data; } static inline void pbuf_clear(void) { +#if defined(__AVR__) uint8_t sreg = SREG; cli(); +#elif defined(PROTOCOL_CHIBIOS) + chSysLock(); +#endif + pbuf_head = pbuf_tail = 0; - SREG = sreg; + +#if defined(__AVR__) + SREG = sreg; +#elif defined(PROTOCOL_CHIBIOS) + chSysUnlock(); +#endif } diff --git a/tmk_core/protocol/ps2_io_chibios.c b/tmk_core/protocol/ps2_io_chibios.c new file mode 100644 index 0000000000..b672bd1f47 --- /dev/null +++ b/tmk_core/protocol/ps2_io_chibios.c @@ -0,0 +1,55 @@ +#include +#include "ps2_io.h" + +// chibiOS headers +#include "ch.h" +#include "hal.h" + +/* Check port settings for clock and data line */ +#if !(defined(PS2_CLOCK)) +# error "PS/2 clock setting is required in config.h" +#endif + +#if !(defined(PS2_DATA)) +# error "PS/2 data setting is required in config.h" +#endif + +/* + * Clock + */ +void clock_init(void) {} + +void clock_lo(void) { + palSetLineMode(PS2_CLOCK, PAL_MODE_OUTPUT_OPENDRAIN); + palWriteLine(PS2_CLOCK, PAL_LOW); +} + +void clock_hi(void) { + palSetLineMode(PS2_CLOCK, PAL_MODE_OUTPUT_OPENDRAIN); + palWriteLine(PS2_CLOCK, PAL_HIGH); +} + +bool clock_in(void) { + palSetLineMode(PS2_CLOCK, PAL_MODE_INPUT); + return palReadLine(PS2_CLOCK); +} + +/* + * Data + */ +void data_init(void) {} + +void data_lo(void) { + palSetLineMode(PS2_DATA, PAL_MODE_OUTPUT_OPENDRAIN); + palWriteLine(PS2_DATA, PAL_LOW); +} + +void data_hi(void) { + palSetLineMode(PS2_DATA, PAL_MODE_OUTPUT_OPENDRAIN); + palWriteLine(PS2_DATA, PAL_HIGH); +} + +bool data_in(void) { + palSetLineMode(PS2_DATA, PAL_MODE_INPUT); + return palReadLine(PS2_DATA); +} diff --git a/tmk_core/protocol/ps2_mouse.c b/tmk_core/protocol/ps2_mouse.c index 5415453a05..525aeb45a0 100644 --- a/tmk_core/protocol/ps2_mouse.c +++ b/tmk_core/protocol/ps2_mouse.c @@ -16,9 +16,13 @@ along with this program. If not, see . */ #include -#include -#include + +#if defined(__AVR__) +# include +#endif + #include "ps2_mouse.h" +#include "wait.h" #include "host.h" #include "timer.h" #include "print.h" @@ -42,7 +46,7 @@ static inline void ps2_mouse_scroll_button_task(report_mouse_t *mouse_report); void ps2_mouse_init(void) { ps2_host_init(); - _delay_ms(PS2_MOUSE_INIT_DELAY); // wait for powering up + wait_ms(PS2_MOUSE_INIT_DELAY); // wait for powering up PS2_MOUSE_SEND(PS2_MOUSE_RESET, "ps2_mouse_init: sending reset"); @@ -210,7 +214,7 @@ static inline void ps2_mouse_enable_scrolling(void) { PS2_MOUSE_SEND(PS2_MOUSE_SET_SAMPLE_RATE, "Set sample rate"); PS2_MOUSE_SEND(80, "80"); PS2_MOUSE_SEND(PS2_MOUSE_GET_DEVICE_ID, "Finished enabling scroll wheel"); - _delay_ms(20); + wait_ms(20); } #define PRESS_SCROLL_BUTTONS mouse_report->buttons |= (PS2_MOUSE_SCROLL_BTN_MASK) @@ -252,7 +256,7 @@ static inline void ps2_mouse_scroll_button_task(report_mouse_t *mouse_report) { if (scroll_state == SCROLL_BTN && timer_elapsed(scroll_button_time) < PS2_MOUSE_SCROLL_BTN_SEND) { PRESS_SCROLL_BUTTONS; host_mouse_send(mouse_report); - _delay_ms(100); + wait_ms(100); RELEASE_SCROLL_BUTTONS; } #endif -- cgit v1.2.3 From 07553b41f0a03ca6549c09cecf9cd3dec7332346 Mon Sep 17 00:00:00 2001 From: Juan Pablo Kutianski Date: Thu, 5 Aug 2021 16:09:58 -0700 Subject: [Feature] Swap buttons on PS2 Mouse/Trackball (#9205) * [Feature Request] Swap buttons on PS2 Mouse/Trackball * [Feature Request] Swap buttons on PS2 Mouse/Trackball * Added id: to the doc * Missing space * Solve comment https://github.com/qmk/qmk_firmware/pull/9205#discussion_r430783182 * Solve comments https://github.com/qmk/qmk_firmware/pull/9205#discussion_r430783182 & https://github.com/qmk/qmk_firmware/pull/9205#discussion_r430783884 * Format code more according to https://docs.qmk.fm/#/coding_conventions_c * change logic to LUT * WIP: Clean up * WIP: Solution with xor operators to mask the change * delete #endif & added the missed xor operator (ahhh) * Variable (mouse_report->buttons): avoid setting twice https://github.com/qmk/qmk_firmware/pull/9205#discussion_r430783884 * Update tmk_core/protocol/ps2_mouse.c Co-authored-by: Nick Brassel Co-authored-by: juank Co-authored-by: Nick Brassel --- docs/feature_ps2_mouse.md | 10 ++++++++++ tmk_core/protocol/ps2_mouse.c | 7 +++++++ 2 files changed, 17 insertions(+) (limited to 'tmk_core') diff --git a/docs/feature_ps2_mouse.md b/docs/feature_ps2_mouse.md index 00c7ee72ee..776a33150e 100644 --- a/docs/feature_ps2_mouse.md +++ b/docs/feature_ps2_mouse.md @@ -270,6 +270,16 @@ Fine control over the scrolling is supported with the following defines: #define PS2_MOUSE_SCROLL_DIVISOR_V 2 ``` +### Invert Mouse buttons :id=invert-buttons + +To invert the left & right buttons you can put: + +```c +#define PS2_MOUSE_INVERT_BUTTONS +``` + +into config.h. + ### Invert Mouse and Scroll Axes :id=invert-mouse-and-scroll-axes To invert the X and Y axes you can put: diff --git a/tmk_core/protocol/ps2_mouse.c b/tmk_core/protocol/ps2_mouse.c index 525aeb45a0..39251a6434 100644 --- a/tmk_core/protocol/ps2_mouse.c +++ b/tmk_core/protocol/ps2_mouse.c @@ -156,8 +156,15 @@ static inline void ps2_mouse_convert_report_to_hid(report_mouse_t *mouse_report) mouse_report->x = X_IS_NEG ? ((!X_IS_OVF && -127 <= mouse_report->x && mouse_report->x <= -1) ? mouse_report->x : -127) : ((!X_IS_OVF && 0 <= mouse_report->x && mouse_report->x <= 127) ? mouse_report->x : 127); mouse_report->y = Y_IS_NEG ? ((!Y_IS_OVF && -127 <= mouse_report->y && mouse_report->y <= -1) ? mouse_report->y : -127) : ((!Y_IS_OVF && 0 <= mouse_report->y && mouse_report->y <= 127) ? mouse_report->y : 127); +#ifdef PS2_MOUSE_INVERT_BUTTONS + // swap left & right buttons + uint8_t needs_left = mouse_report->buttons & PS2_MOUSE_BTN_RIGHT; + uint8_t needs_right = mouse_report->buttons & PS2_MOUSE_BTN_LEFT; + mouse_report->buttons = (mouse_report->buttons & ~(PS2_MOUSE_BTN_MASK)) | (needs_left ? PS2_MOUSE_BTN_LEFT : 0) | (needs_right ? PS2_MOUSE_BTN_RIGHT : 0); +#else // remove sign and overflow flags mouse_report->buttons &= PS2_MOUSE_BTN_MASK; +#endif #ifdef PS2_MOUSE_INVERT_X mouse_report->x = -mouse_report->x; -- cgit v1.2.3 From 7e983796e18e7401c062c158f23966aeb7b1405b Mon Sep 17 00:00:00 2001 From: Pete Sevander Date: Fri, 6 Aug 2021 02:44:57 +0300 Subject: Process combos earlier & overlapping combos (#8591) * Combo processing improvements. Now it is possible to use ModTap and LayerTap keys as part of combos. Overlapping combos also don't trigger all the combos, just exactly the one that you press. New settings: - COMBO_MUST_HOLD_MODS - COMBO_MOD_TERM - COMBO_TERM_PER_COMBO - COMBO_MUST_HOLD_PER_COMBO - COMBO_STRICT_TIMER - COMBO_NO_TIMER * Remove the size flags from combo_t struct boolean members. This in the end actually saves space as the members are accessed so many times. The amount of operations needed to access the bits uses more memory than setting the size saves. * Fix `process_combo_key_release` not called correctly with tap-only combos * Fix not passing a pointer when NO_ACTION_TAPPING is defined. * Docs for `COMBO_ONLY_FROM_LAYER` * Update docs/feature_combo.md Co-authored-by: precondition <57645186+precondition@users.noreply.github.com> * Update quantum/process_keycode/process_combo.c Co-authored-by: precondition <57645186+precondition@users.noreply.github.com> * Add `EXTRA_SHORT_COMBOS` option. Stuff combo's `disabled` and `active` flags into `state`. Possibly can save some space. * Add more examples and clarify things with dict management system. - Simple examples now has a combo that has modifiers included. - The slightly more advanced examples now are actually more advanced instead of just `tap_code16()`. - Added a note that `COMBO_ACTION`s are not needed anymore as you can just use custom keycodes. - Added a note that the `g/keymap_combo.h` macros use the `process_combo_event` function and that it is not usable in one's keymap afterwards. * Update docs/feature_combo.md Co-authored-by: precondition <57645186+precondition@users.noreply.github.com> * Update docs/feature_combo.md Co-authored-by: precondition <57645186+precondition@users.noreply.github.com> * Update docs/feature_combo.md Co-authored-by: precondition <57645186+precondition@users.noreply.github.com> * Update docs/feature_combo.md Co-authored-by: precondition <57645186+precondition@users.noreply.github.com> * Update docs/feature_combo.md Co-authored-by: precondition <57645186+precondition@users.noreply.github.com> * Change "the" combo action example to "email" example. * Update docs/feature_combo.md Co-authored-by: precondition <57645186+precondition@users.noreply.github.com> * Fix sneaky infinite loop with `combo_disable()` No need to call `dump_key_buffer` when disabling combos because the buffer is either being dumped if a combo-key was pressed, or the buffer is empty if a non-combo-key is pressed. * Update docs/feature_combo.md Co-authored-by: precondition <57645186+precondition@users.noreply.github.com> * Update docs/feature_combo.md Co-authored-by: precondition <57645186+precondition@users.noreply.github.com> Co-authored-by: precondition <57645186+precondition@users.noreply.github.com> Co-authored-by: Drashna Jaelre --- docs/config_options.md | 14 +- docs/feature_combo.md | 292 +++++++++++++++-- keyboards/gboards/g/keymap_combo.h | 6 +- quantum/keymap_common.c | 3 + quantum/process_keycode/process_combo.c | 548 ++++++++++++++++++++++++++------ quantum/process_keycode/process_combo.h | 36 ++- quantum/quantum.c | 23 +- tmk_core/common/action.c | 37 ++- tmk_core/common/action.h | 5 + tmk_core/common/action_tapping.c | 41 ++- tmk_core/common/action_tapping.h | 1 + 11 files changed, 841 insertions(+), 165 deletions(-) (limited to 'tmk_core') diff --git a/docs/config_options.md b/docs/config_options.md index 0c98b31010..78c1f70fd7 100644 --- a/docs/config_options.md +++ b/docs/config_options.md @@ -188,9 +188,21 @@ If you define these options you will enable the associated feature, which may in few ms of delay from this. But if you're doing chording on something with 3-4ms scan times? You probably want this. * `#define COMBO_COUNT 2` - * Set this to the number of combos that you're using in the [Combo](feature_combo.md) feature. + * Set this to the number of combos that you're using in the [Combo](feature_combo.md) feature. Or leave it undefined and programmatically set the count. * `#define COMBO_TERM 200` * how long for the Combo keys to be detected. Defaults to `TAPPING_TERM` if not defined. +* `#define COMBO_MUST_HOLD_MODS` + * Flag for enabling extending timeout on Combos containing modifers +* `#define COMBO_MOD_TERM 200` + * Allows for extending COMBO_TERM for mod keys while mid-combo. +* `#define COMBO_MUST_HOLD_PER_COMBO` + * Flag to enable per-combo COMBO_TERM extension and `get_combo_must_hold()` function +* `#define COMBO_TERM_PER_COMBO` + * Flag to enable per-combo COMBO_TERM extension and `get_combo_term()` function +* `#define COMBO_STRICT_TIMER` + * Only start the combo timer on the first key press instead of on all key presses. +* `#define COMBO_NO_TIMER` + * Disable the combo timer completely for relaxed combos. * `#define TAP_CODE_DELAY 100` * Sets the delay between `register_code` and `unregister_code`, if you're having issues with it registering properly (common on VUSB boards). The value is in milliseconds. * `#define TAP_HOLD_CAPS_DELAY 80` diff --git a/docs/feature_combo.md b/docs/feature_combo.md index d831328f69..d98e6f2ac7 100644 --- a/docs/feature_combo.md +++ b/docs/feature_combo.md @@ -1,24 +1,39 @@ # Combos -The Combo feature is a chording type solution for adding custom actions. It lets you hit multiple keys at once and produce a different effect. For instance, hitting `A` and `S` within the tapping term would hit `ESC` instead, or have it perform even more complex tasks. +The Combo feature is a chording type solution for adding custom actions. It lets you hit multiple keys at once and produce a different effect. For instance, hitting `A` and `S` within the combo term would hit `ESC` instead, or have it perform even more complex tasks. To enable this feature, you need to add `COMBO_ENABLE = yes` to your `rules.mk`. -Additionally, in your `config.h`, you'll need to specify the number of combos that you'll be using, by adding `#define COMBO_COUNT 1` (replacing 1 with the number that you're using). - +Additionally, in your `config.h`, you'll need to specify the number of combos that you'll be using, by adding `#define COMBO_COUNT 1` (replacing 1 with the number that you're using). It is also possible to not define this and instead set the variable `COMBO_LEN` yourself. There's a trick where we don't need to think about this variable at all. More on this later. -Also, by default, the tapping term for the Combos is set to the same value as `TAPPING_TERM` (200 by default on most boards). But you can specify a different value by defining it in your `config.h`. For instance: `#define COMBO_TERM 300` would set the time out period for combos to 300ms. -Then, your `keymap.c` file, you'll need to define a sequence of keys, terminated with `COMBO_END`, and a structure to list the combination of keys, and it's resulting action. +Then, in your `keymap.c` file, you'll need to define a sequence of keys, terminated with `COMBO_END`, and a structure to list the combination of keys, and its resulting action. ```c -const uint16_t PROGMEM test_combo[] = {KC_A, KC_B, COMBO_END}; -combo_t key_combos[COMBO_COUNT] = {COMBO(test_combo, KC_ESC)}; +const uint16_t PROGMEM test_combo1[] = {KC_A, KC_B, COMBO_END}; +const uint16_t PROGMEM test_combo2[] = {KC_C, KC_D, COMBO_END}; +combo_t key_combos[COMBO_COUNT] = { + COMBO(test_combo1, KC_ESC), + COMBO(test_combo2, LCTL(KC_Z)), // keycodes with modifiers are possible too! +}; ``` -This will send "Escape" if you hit the A and B keys. +This will send "Escape" if you hit the A and B keys, and Ctrl+Z when you hit the C and D keys. + +As of [PR#8591](https://github.com/qmk/qmk_firmware/pull/8591/), it is possible to fire combos from ModTap keys and LayerTap keys. So in the above example you could have keys `LSFT_T(KC_A)` and `LT(_LAYER, KC_B)` and it would work. So Home Row Mods and Home Row Combos at same time is now a thing! -!> This method only supports [basic keycodes](keycodes_basic.md). See the examples for more control. +It is also now possible to overlap combos. Before, with the example below both combos would activate when all three keys were pressed. Now only the three key combo will activate. + +```c +const uint16_t PROGMEM test_combo1[] = {LSFT_T(KC_A), LT(_LAYER, KC_B), COMBO_END}; +const uint16_t PROGMEM test_combo2[] = {LSFT_T(KC_A), LT(_LAYER, KC_B), KC_C, COMBO_END}; +combo_t key_combos[COMBO_COUNT] = { + COMBO(test_combo1, KC_ESC) + COMBO(test_combo2, KC_TAB) +}; +``` + +Executing more complex keycodes like ModTaps and LayerTaps is now also possible. ## Examples @@ -27,63 +42,68 @@ If you want to add a list, then you'd use something like this: ```c enum combos { AB_ESC, - JK_TAB + JK_TAB, + QW_SFT, + SD_LAYER, }; const uint16_t PROGMEM ab_combo[] = {KC_A, KC_B, COMBO_END}; const uint16_t PROGMEM jk_combo[] = {KC_J, KC_K, COMBO_END}; +const uint16_t PROGMEM qw_combo[] = {KC_Q, KC_W, COMBO_END}; +const uint16_t PROGMEM sd_combo[] = {KC_S, KC_D, COMBO_END}; combo_t key_combos[COMBO_COUNT] = { [AB_ESC] = COMBO(ab_combo, KC_ESC), - [JK_TAB] = COMBO(jk_combo, KC_TAB) + [JK_TAB] = COMBO(jk_combo, KC_TAB), + [QW_SFT] = COMBO(qw_combo, KC_LSFT) + [SD_LAYER] = COMBO(layer_combo, MO(_LAYER)), }; ``` For a more complicated implementation, you can use the `process_combo_event` function to add custom handling. +Additionally, this example shows how you can leave `COMBO_COUNT` undefined. ```c enum combo_events { - ZC_COPY, - XV_PASTE + EM_EMAIL, + BSPC_LSFT_CLEAR, + COMBO_LENGTH }; +uint16_t COMBO_LEN = COMBO_LENGTH; // remove the COMBO_COUNT define and use this instead! -const uint16_t PROGMEM copy_combo[] = {KC_Z, KC_C, COMBO_END}; -const uint16_t PROGMEM paste_combo[] = {KC_X, KC_V, COMBO_END}; +const uint16_t PROGMEM email_combo[] = {KC_E, KC_M, COMBO_END}; +const uint16_t PROGMEM clear_line_combo[] = {KC_BSPC, KC_LSFT, COMBO_END}; -combo_t key_combos[COMBO_COUNT] = { - [ZC_COPY] = COMBO_ACTION(copy_combo), - [XV_PASTE] = COMBO_ACTION(paste_combo), +combo_t key_combos[] = { + [EM_EMAIL] = COMBO_ACTION(email_combo), + [BSPC_LSFT_CLEAR] = COMBO_ACTION(clear_line_combo), }; +/* COMBO_ACTION(x) is same as COMBO(x, KC_NO) */ void process_combo_event(uint16_t combo_index, bool pressed) { switch(combo_index) { - case ZC_COPY: + case EM_EMAIL: if (pressed) { - tap_code16(LCTL(KC_C)); + SEND_STRING("john.doe@example.com"); } break; - case XV_PASTE: + case BSPC_LSFT_CLEAR: if (pressed) { - tap_code16(LCTL(KC_V)); + tap_code16(KC_END); + tap_code16(S(KC_HOME)); + tap_code16(KC_BSPC); } break; } } ``` -This will send Ctrl+C if you hit Z and C, and Ctrl+V if you hit X and V. But you could change this to do stuff like change layers, play sounds, or change settings. - -## Additional Configuration +This will send "john.doe@example.com" if you chord E and M together, and clear the current line with Backspace and Left-Shift. You could change this to do stuff like play sounds or change settings. -If you're using long combos, or even longer combos, you may run into issues with this, as the structure may not be large enough to accommodate what you're doing. +It is worth noting that `COMBO_ACTION`s are not needed anymore. As of [PR#8591](https://github.com/qmk/qmk_firmware/pull/8591/), it is possible to run your own custom keycodes from combos. Just define the custom keycode, program its functionality in `process_record_user`, and define a combo with `COMBO(, )`. -In this case, you can add either `#define EXTRA_LONG_COMBOS` or `#define EXTRA_EXTRA_LONG_COMBOS` in your `config.h` file. - -You may also be able to enable action keys by defining `COMBO_ALLOW_ACTION_KEYS`. - -## Keycodes - -You can enable, disable and toggle the Combo feature on the fly. This is useful if you need to disable them temporarily, such as for a game. +## Keycodes +You can enable, disable and toggle the Combo feature on the fly. This is useful if you need to disable them temporarily, such as for a game. The following keycodes are available for use in your `keymap.c` |Keycode |Description | |----------|---------------------------------| @@ -91,6 +111,187 @@ You can enable, disable and toggle the Combo feature on the fly. This is useful |`CMB_OFF` |Turns off Combo feature | |`CMB_TOG` |Toggles Combo feature on and off | +# Advanced Configuration +These configuration settings can be set in your `config.h` file. + +## Combo Term +By default, the timeout for the Combos to be recognized is set to 50ms. This can be changed if accidental combo misfires are happening or if you're having difficulties pressing keys at the same time. For instance, `#define COMBO_TERM 40` would set the timeout period for combos to 40ms. + +## Buffer and state sizes +If you're using long combos, or you have a lot of overlapping combos, you may run into issues with this, as the buffers may not be large enough to accommodate what you're doing. In this case, you can configure the sizes of the buffers used. Be aware, larger combo sizes and larger buffers will increase memory usage! + +To configure the amount of keys a combo can be composed of, change the following: + +| Keys | Define to be set | +|------|-----------------------------------| +| 6 | `#define EXTRA_SHORT_COMBOS` | +| 8 | QMK Default | +| 16 | `#define EXTRA_LONG_COMBOS` | +| 32 | `#define EXTRA_EXTRA_LONG_COMBOS` | + +Defining `EXTRA_SHORT_COMBOS` combines a combo's internal state into just one byte. This can, in some cases, save some memory. If it doesn't, no point using it. If you do, you also have to make sure you don't define combos with more than 6 keys. + +Processing combos has two buffers, one for the key presses, another for the combos being activated. Use the following options to configure the sizes of these buffers: + +| Define | Default | +|-------------------------------------|------------------------------------------------------| +| `#define COMBO_KEY_BUFFER_LENGTH 8` | 8 (the key amount `(EXTRA_)EXTRA_LONG_COMBOS` gives) | +| `#define COMBO_BUFFER_LENGTH 4` | 4 | + +## Modifier Combos +If a combo resolves to a Modifier, the window for processing the combo can be extended independently from normal combos. By default, this is disabled but can be enabled with `#define COMBO_MUST_HOLD_MODS`, and the time window can be configured with `#define COMBO_HOLD_TERM 150` (default: `TAPPING_TERM`). With `COMBO_MUST_HOLD_MODS`, you cannot tap the combo any more which makes the combo less prone to misfires. + +## Per Combo Timing, Holding and Tapping +For each combo, it is possible to configure the time window it has to pressed in, if it needs to be held down, or if it needs to be tapped. + +For example, tap-only combos are useful if any (or all) of the underlying keys is a Mod-Tap or a Layer-Tap key. When you tap the combo, you get the combo result. When you press the combo and hold it down, the combo doesn't actually activate. Instead the keys are processed separately as if the combo wasn't even there. + +In order to use these features, the following configuration options and functions need to be defined. Coming up with useful timings and configuration is left as an exercise for the reader. + +| Config Flag | Function | Description | +|-----------------------------|-----------------------------------------------------------|--------------------------------------------------------------------------------------------------------| +| `COMBO_TERM_PER_COMBO` | uint16_t get_combo_term(uint16_t index, combo_t \*combo) | Optional per-combo timeout window. (default: `COMBO_TERM`) | +| `COMBO_MUST_HOLD_PER_COMBO` | bool get_combo_must_hold(uint16_t index, combo_t \*combo) | Controls if a given combo should fire immediately on tap or if it needs to be held. (default: `false`) | +| `COMBO_MUST_TAP_PER_COMBO` | bool get_combo_must_tap(uint16_t index, combo_t \*combo) | Controls if a given combo should fire only if tapped within `COMBO_HOLD_TERM`. (default: `false`) | + +Examples: +```c +uint16_t get_combo_term(uint16_t index, combo_t *combo) { + // decide by combo->keycode + switch (combo->keycode) { + case KC_X: + return 50; + } + + // or with combo index, i.e. its name from enum. + switch (index) { + case COMBO_NAME_HERE: + return 9001; + } + + // And if you're feeling adventurous, you can even decide by the keys in the chord, + // i.e. the exact array of keys you defined for the combo. + // This can be useful if your combos have a common key and you want to apply the + // same combo term for all of them. + if (combo->keys[0] == KC_ENTER) { // if first key in the array is KC_ENTER + return 150; + } + + return COMBO_TERM; +} + +bool get_combo_must_hold(uint16_t index, combo_t *combo) { + // Same as above, decide by keycode, the combo index, or by the keys in the chord. + + if (KEYCODE_IS_MOD(combo->keycode) || + (combo->keycode >= QK_MOMENTARY && combo->keycode <= QK_MOMENTARY_MAX) // MO(kc) keycodes + ) { + return true; + } + + switch (index) { + case COMBO_NAME_HERE: + return true; + } + + return false; +} + +bool get_combo_must_tap(uint16_t index, combo_t *combo) { + // If you want all combos to be tap-only, just uncomment the next line + // return true + + // If you want *all* combos, that have Mod-Tap/Layer-Tap/Momentary keys in its chord, to be tap-only, this is for you: + uint16_t key; + uint8_t idx = 0; + while ((key = pgm_read_word(&combo->keys[idx])) != COMBO_END) { + switch (key) { + case QK_MOD_TAP...QK_MOD_TAP_MAX: + case QK_LAYER_TAP...QK_LAYER_TAP_MAX: + case QK_MOMENTARY...QK_MOMENTARY_MAX: + return true; + } + idx += 1; + } + return false; + +} +``` + +## Variable Length Combos +If you leave `COMBO_COUNT` undefined in `config.h`, it allows you to programmatically declare the size of the Combo data structure and avoid updating `COMBO_COUNT`. Instead a variable called `COMBO_LEN` has to be set. It can be set with something similar to the following in `keymap.c`: `uint16_t COMBO_LEN = sizeof(key_combos) / sizeof(key_combos[0]);` or by adding `COMBO_LENGTH` as the *last* entry in the combo enum and then `uint16_t COMBO_LEN = COMBO_LENGTH;` as such: +```c +enum myCombos { + ..., + COMBO_LENGTH +}; +uint16_t COMBO_LEN = COMBO_LENGTH; +``` +Regardless of the method used to declare `COMBO_LEN`, this also requires to convert the `combo_t key_combos[COMBO_COUNT] = {...};` line to `combo_t key_combos[] = {...};`. + + +## Combo timer + +Normally, the timer is started on the first key press and then reset on every subsequent key press within the `COMBO_TERM`. +Inputting combos is relaxed like this, but also slightly more prone to accidental misfires. + +The next two options alter the behaviour of the timer. + +### `#define COMBO_STRICT_TIMER` + +With `COMBO_STRICT_TIMER`, the timer is started only on the first key press. +Inputting combos is now less relaxed; you need to make sure the full chord is pressed within the `COMBO_TERM`. +Misfires are less common but if you type multiple combos fast, there is a +chance that the latter ones might not activate properly. + +### `#define COMBO_NO_TIMER` + +By defining `COMBO_NO_TIMER`, the timer is disabled completely and combos are activated on the first key release. +This also disables the "must hold" functionalities as they just wouldn't work at all. + +## Customizable key releases + +By defining `COMBO_PROCESS_KEY_RELEASE` and implementing the function `bool process_combo_key_release(uint16_t combo_index, combo_t *combo, uint8_t key_index, uint16_t keycode)`, you can run your custom code on each key release after a combo was activated. For example you could change the RGB colors, activate haptics, or alter the modifiers. + +You can also release a combo early by returning `true` from the function. + +Here's an example where a combo resolves to two modifiers, and on key releases the modifiers are unregistered one by one, depending on which key was released. + +```c +enum combos { + AB_MODS, + COMBO_LENGTH +}; +uint16_t COMBO_LEN = COMBO_LENGTH; + +const uint16_t PROGMEM ab_combo[] = {KC_A, KC_B, COMBO_END}; + +combo_t key_combos[] = { + [AB_MODS] = COMBO(ab_combo, LCTL(KC_LSFT)), +}; + +bool process_combo_key_release(uint16_t combo_index, combo_t *combo, uint8_t key_index, uint16_t keycode) { + switch (combo_index) { + case AB_MODS: + switch(keycode) { + case KC_A: + unregister_mods(MOD_MASK_CTRL); + break; + case KC_B: + unregister_mods(MOD_MASK_SHIFT); + break; + } + return false; // do not release combo + } + return false; +} +``` +## Layer independent combos + +If you, for example, use multiple base layers for different key layouts, one for QWERTY, and another one for Colemak, you might want your combos to work from the same key positions on all layers. Defining the same combos again for another layout is redundant and takes more memory. The solution is to just check the keycodes from one layer. + +With `#define COMBO_ONLY_FROM_LAYER _LAYER_A` the combos' keys are always checked from layer `_LAYER_A` even though the active layer would be `_LAYER_B`. + ## User callbacks In addition to the keycodes, there are a few functions that you can use to set the status, or check it: @@ -101,3 +302,28 @@ In addition to the keycodes, there are a few functions that you can use to set t | `combo_disable()` | Disables the combo feature, and clears the combo buffer | | `combo_toggle()` | Toggles the state of the combo feature | | `is_combo_enabled()` | Returns the status of the combo feature state (true or false) | + + +# Dictionary Management + +Having 3 places to update when adding new combos or altering old ones does become cumbersome when you have a lot of combos. We can alleviate this with some magic! ... If you consider C macros magic. +First, you need to add `VPATH += keyboards/gboards` to your `rules.mk`. Next, include the file `g/keymap_combo.h` in your `keymap.c`. + +!> This functionality uses the same `process_combo_event` function as `COMBO_ACTION` macros do, so you cannot use the function yourself in your keymap. Instead, you have to define the `case`s of the `switch` statement by themselves within `inject.h`, which `g/keymap_combo.h` will then include into the function. + +Then, write your combos in `combos.def` file in the following manner: + +```c +// name result chord keys +COMB(AB_ESC, KC_ESC, KC_A, KC_B) +COMB(JK_TAB, KC_TAB, KC_J, KC_K) +COMB(JKL_SPC, KC_SPC, KC_J, KC_K, KC_L) +COMB(BSSL_CLR, KC_NO, KC_BSPC, KC_LSFT) // using KC_NO as the resulting keycode is the same as COMBO_ACTION before. +COMB(QW_UNDO, C(KC_Z), KC_Q, KC_W) +SUBS(TH_THE, "the", KC_T, KC_H) // SUBS uses SEND_STRING to output the given string. +... +``` + +Now, you can update only one place to add or alter combos. You don't even need to remember to update the `COMBO_COUNT` or the `COMBO_LEN` variables at all. Everything is taken care of. Magic! + +For small to huge ready made dictionaries of combos, you can check out http://combos.gboards.ca/. diff --git a/keyboards/gboards/g/keymap_combo.h b/keyboards/gboards/g/keymap_combo.h index 58e99863ea..b92b6a4bc4 100644 --- a/keyboards/gboards/g/keymap_combo.h +++ b/keyboards/gboards/g/keymap_combo.h @@ -28,7 +28,10 @@ #define TOGG A_ENUM enum combos { #include "combos.def" + COMBO_LENGTH }; +// Export length to combo module +uint16_t COMBO_LEN = COMBO_LENGTH; // Bake combos into mem #undef COMB @@ -53,9 +56,6 @@ combo_t key_combos[] = { #undef SUBS #undef TOGG -// Export length to combo module -int COMBO_LEN = sizeof(key_combos) / sizeof(key_combos[0]); - // Fill QMK hook #define COMB BLANK #define SUBS A_ACTI diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c index e0fd6d4793..780c71ab9b 100644 --- a/quantum/keymap_common.c +++ b/quantum/keymap_common.c @@ -40,7 +40,10 @@ extern keymap_config_t keymap_config; action_t action_for_key(uint8_t layer, keypos_t key) { // 16bit keycodes - important uint16_t keycode = keymap_key_to_keycode(layer, key); + return action_for_keycode(keycode); +}; +action_t action_for_keycode(uint16_t keycode) { // keycode remapping keycode = keycode_config(keycode); diff --git a/quantum/process_keycode/process_combo.c b/quantum/process_keycode/process_combo.c index 9e16292486..b4e698decd 100644 --- a/quantum/process_keycode/process_combo.c +++ b/quantum/process_keycode/process_combo.c @@ -16,114 +16,445 @@ #include "print.h" #include "process_combo.h" +#include "action_tapping.h" -#ifndef COMBO_VARIABLE_LEN -__attribute__((weak)) combo_t key_combos[COMBO_COUNT] = {}; + +#ifdef COMBO_COUNT +__attribute__((weak)) combo_t key_combos[COMBO_COUNT]; +uint16_t COMBO_LEN = COMBO_COUNT; #else extern combo_t key_combos[]; -extern int COMBO_LEN; +extern uint16_t COMBO_LEN; #endif __attribute__((weak)) void process_combo_event(uint16_t combo_index, bool pressed) {} -static uint16_t timer = 0; -static uint16_t current_combo_index = 0; -static bool drop_buffer = false; -static bool is_active = false; -static bool b_combo_enable = true; // defaults to enabled +#ifdef COMBO_MUST_HOLD_PER_COMBO +__attribute__((weak)) bool get_combo_must_hold(uint16_t index, combo_t *combo) { return false; } +#endif + +#ifdef COMBO_MUST_TAP_PER_COMBO +__attribute__((weak)) bool get_combo_must_tap(uint16_t index, combo_t *combo) { return false; } +#endif -static uint8_t buffer_size = 0; -#ifdef COMBO_ALLOW_ACTION_KEYS -static keyrecord_t key_buffer[MAX_COMBO_LENGTH]; +#ifdef COMBO_TERM_PER_COMBO +__attribute__((weak)) uint16_t get_combo_term(uint16_t index, combo_t *combo) { return COMBO_TERM; } +#endif + +#ifdef COMBO_PROCESS_KEY_RELEASE +__attribute__((weak)) bool process_combo_key_release(uint16_t combo_index, combo_t *combo, uint8_t key_index, uint16_t keycode) { return false; } +#endif + +#ifndef COMBO_NO_TIMER +static uint16_t timer = 0; +#endif +static bool b_combo_enable = true; // defaults to enabled +static uint16_t longest_term = 0; + +typedef struct { + keyrecord_t record; + uint16_t combo_index; + uint16_t keycode; +} queued_record_t; +static uint8_t key_buffer_size = 0; +static queued_record_t key_buffer[COMBO_KEY_BUFFER_LENGTH]; + +typedef struct { + uint16_t combo_index; +} queued_combo_t; +static uint8_t combo_buffer_write= 0; +static uint8_t combo_buffer_read = 0; +static queued_combo_t combo_buffer[COMBO_BUFFER_LENGTH]; + +#define INCREMENT_MOD(i) i = (i + 1) % COMBO_BUFFER_LENGTH + +#define COMBO_KEY_POS ((keypos_t){.col=254, .row=254}) + + +#ifndef EXTRA_SHORT_COMBOS +/* flags are their own elements in combo_t struct. */ +# define COMBO_ACTIVE(combo) (combo->active) +# define COMBO_DISABLED(combo) (combo->disabled) +# define COMBO_STATE(combo) (combo->state) + +# define ACTIVATE_COMBO(combo) do {combo->active = true;}while(0) +# define DEACTIVATE_COMBO(combo) do {combo->active = false;}while(0) +# define DISABLE_COMBO(combo) do {combo->disabled = true;}while(0) +# define RESET_COMBO_STATE(combo) do { \ + combo->disabled = false; \ + combo->state = 0; \ +}while(0) #else -static uint16_t key_buffer[MAX_COMBO_LENGTH]; +/* flags are at the two high bits of state. */ +# define COMBO_ACTIVE(combo) (combo->state & 0x80) +# define COMBO_DISABLED(combo) (combo->state & 0x40) +# define COMBO_STATE(combo) (combo->state & 0x3F) + +# define ACTIVATE_COMBO(combo) do {combo->state |= 0x80;}while(0) +# define DEACTIVATE_COMBO(combo) do {combo->state &= ~0x80;}while(0) +# define DISABLE_COMBO(combo) do {combo->state |= 0x40;}while(0) +# define RESET_COMBO_STATE(combo) do {combo->state &= ~0x7F;}while(0) #endif -static inline void send_combo(uint16_t action, bool pressed) { - if (action) { - if (pressed) { - register_code16(action); - } else { - unregister_code16(action); - } +static inline void release_combo(uint16_t combo_index, combo_t *combo) { + if (combo->keycode) { + keyrecord_t record = { + .event = { + .key = COMBO_KEY_POS, + .time = timer_read()|1, + .pressed = false, + }, + .keycode = combo->keycode, + }; +#ifndef NO_ACTION_TAPPING + action_tapping_process(record); +#else + process_record(&record); +#endif } else { - process_combo_event(current_combo_index, pressed); + process_combo_event(combo_index, false); + } + DEACTIVATE_COMBO(combo); +} + +static inline bool _get_combo_must_hold(uint16_t combo_index, combo_t *combo) { +#ifdef COMBO_NO_TIMER + return false; +#elif defined(COMBO_MUST_HOLD_PER_COMBO) + return get_combo_must_hold(combo_index, combo); +#elif defined(COMBO_MUST_HOLD_MODS) + return (KEYCODE_IS_MOD(combo->keycode) || + (combo->keycode >= QK_MOMENTARY && combo->keycode <= QK_MOMENTARY_MAX)); +#endif + return false; +} + +static inline uint16_t _get_wait_time(uint16_t combo_index, combo_t *combo ) { + if (_get_combo_must_hold(combo_index, combo) +#ifdef COMBO_MUST_TAP_PER_COMBO + || get_combo_must_tap(combo_index, combo) +#endif + ) { + if (longest_term < COMBO_HOLD_TERM) { + return COMBO_HOLD_TERM; + } + } + + return longest_term; +} + +static inline uint16_t _get_combo_term(uint16_t combo_index, combo_t *combo) { + +#if defined(COMBO_TERM_PER_COMBO) + return get_combo_term(combo_index, combo); +#endif + + return COMBO_TERM; +} + +void clear_combos(void) { + uint16_t index = 0; + longest_term = 0; + for (index = 0; index < COMBO_LEN; ++index) { + combo_t *combo = &key_combos[index]; + if (!COMBO_ACTIVE(combo)) { + RESET_COMBO_STATE(combo); + } } } -static inline void dump_key_buffer(bool emit) { - if (buffer_size == 0) { +static inline void dump_key_buffer(void) { + if (key_buffer_size == 0) { return; } - if (emit) { - for (uint8_t i = 0; i < buffer_size; i++) { -#ifdef COMBO_ALLOW_ACTION_KEYS - const action_t action = store_or_get_action(key_buffer[i].event.pressed, key_buffer[i].event.key); - process_action(&(key_buffer[i]), action); + for (uint8_t key_buffer_i = 0; key_buffer_i < key_buffer_size; key_buffer_i++) { + + queued_record_t *qrecord = &key_buffer[key_buffer_i]; + keyrecord_t *record = &qrecord->record; + + if (IS_NOEVENT(record->event)) { + continue; + } + + if (!record->keycode && qrecord->combo_index != (uint16_t)-1) { + process_combo_event(qrecord->combo_index, true); + } else { +#ifndef NO_ACTION_TAPPING + action_tapping_process(*record); #else - register_code16(key_buffer[i]); - send_keyboard_report(); + process_record(record); #endif } + record->event.time = 0; } - buffer_size = 0; + key_buffer_size = 0; } -#define ALL_COMBO_KEYS_ARE_DOWN (((1 << count) - 1) == combo->state) -#define KEY_STATE_DOWN(key) \ - do { \ - combo->state |= (1 << key); \ +#define NO_COMBO_KEYS_ARE_DOWN (0 == COMBO_STATE(combo)) +#define ALL_COMBO_KEYS_ARE_DOWN(state, key_count) (((1 << key_count) - 1) == state) +#define ONLY_ONE_KEY_IS_DOWN(state) !(state & (state - 1)) +#define KEY_NOT_YET_RELEASED(state, key_index) ((1 << key_index) & state) +#define KEY_STATE_DOWN(state, key_index) \ + do { \ + state |= (1 << key_index); \ } while (0) -#define KEY_STATE_UP(key) \ - do { \ - combo->state &= ~(1 << key); \ +#define KEY_STATE_UP(state, key_index) \ + do { \ + state &= ~(1 << key_index); \ } while (0) -static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *record) { - uint8_t count = 0; - uint16_t index = -1; - /* Find index of keycode and number of combo keys */ - for (const uint16_t *keys = combo->keys;; ++count) { - uint16_t key = pgm_read_word(&keys[count]); - if (keycode == key) index = count; +static inline void _find_key_index_and_count(const uint16_t *keys, uint16_t keycode, uint16_t *key_index, uint8_t *key_count) { + while (true) { + uint16_t key = pgm_read_word(&keys[*key_count]); + if (keycode == key) *key_index = *key_count; if (COMBO_END == key) break; + (*key_count)++; + } +} + +void drop_combo_from_buffer(uint16_t combo_index) { + /* Mark a combo as processed from the buffer. If the buffer is in the + * beginning of the buffer, drop it. */ + uint8_t i = combo_buffer_read; + while (i != combo_buffer_write) { + queued_combo_t *qcombo = &combo_buffer[i]; + + if (qcombo->combo_index == combo_index) { + combo_t *combo = &key_combos[combo_index]; + DISABLE_COMBO(combo); + + if (i == combo_buffer_read) { + INCREMENT_MOD(combo_buffer_read); + } + break; + } + INCREMENT_MOD(i); } +} + +void apply_combo(uint16_t combo_index, combo_t *combo) { + /* Apply combo's result keycode to the last chord key of the combo and + * disable the other keys. */ - /* Continue processing if not a combo key */ - if (-1 == (int8_t)index) return false; + if (COMBO_DISABLED(combo)) { return; } - bool is_combo_active = is_active; + // state to check against so we find the last key of the combo from the buffer +#if defined(EXTRA_EXTRA_LONG_COMBOS) + uint32_t state = 0; +#elif defined(EXTRA_LONG_COMBOS) + uint16_t state = 0; +#else + uint8_t state = 0; +#endif + + for (uint8_t key_buffer_i = 0; key_buffer_i < key_buffer_size; key_buffer_i++) { + + queued_record_t *qrecord = &key_buffer[key_buffer_i]; + keyrecord_t *record = &qrecord->record; + uint16_t keycode = qrecord->keycode; + + uint8_t key_count = 0; + uint16_t key_index = -1; + _find_key_index_and_count(combo->keys, keycode, &key_index, &key_count); + + if (-1 == (int16_t)key_index) { + // key not part of this combo + continue; + } - if (record->event.pressed) { - KEY_STATE_DOWN(index); + KEY_STATE_DOWN(state, key_index); + if (ALL_COMBO_KEYS_ARE_DOWN(state, key_count)) { + // this in the end executes the combo when the key_buffer is dumped. + record->keycode = combo->keycode; + record->event.key = COMBO_KEY_POS; - if (is_combo_active) { - if (ALL_COMBO_KEYS_ARE_DOWN) { /* Combo was pressed */ - send_combo(combo->keycode, true); - drop_buffer = true; + qrecord->combo_index = combo_index; + ACTIVATE_COMBO(combo); + + break; + } else { + // key was part of the combo but not the last one, "disable" it + // by making it a TICK event. + record->event.time = 0; + } + + } + drop_combo_from_buffer(combo_index); +} + +static inline void apply_combos(void) { + // Apply all buffered normal combos. + for (uint8_t i = combo_buffer_read; + i != combo_buffer_write; + INCREMENT_MOD(i)) { + + queued_combo_t *buffered_combo = &combo_buffer[i]; + combo_t *combo = &key_combos[buffered_combo->combo_index]; + +#ifdef COMBO_MUST_TAP_PER_COMBO + if (get_combo_must_tap(buffered_combo->combo_index, combo)) { + // Tap-only combos are applied on key release only, so let's drop 'em here. + drop_combo_from_buffer(buffered_combo->combo_index); + continue; + } +#endif + apply_combo(buffered_combo->combo_index, combo); + } + dump_key_buffer(); + clear_combos(); +} + +combo_t* overlaps(combo_t *combo1, combo_t *combo2) { + /* Checks if the combos overlap and returns the combo that should be + * dropped from the combo buffer. + * The combo that has less keys will be dropped. If they have the same + * amount of keys, drop combo1. */ + + uint8_t idx1 = 0, idx2 = 0; + uint16_t key1, key2; + bool overlaps = false; + + while ((key1 = pgm_read_word(&combo1->keys[idx1])) != COMBO_END) { + idx2 = 0; + while ((key2 = pgm_read_word(&combo2->keys[idx2])) != COMBO_END) { + if (key1 == key2) overlaps = true; + idx2 += 1; + } + idx1 += 1; + } + + if (!overlaps) return NULL; + if (idx2 < idx1) return combo2; + return combo1; +} + +static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *record, uint16_t combo_index) { + uint8_t key_count = 0; + uint16_t key_index = -1; + _find_key_index_and_count(combo->keys, keycode, &key_index, &key_count); + + /* Continue processing if key isn't part of current combo. */ + if (-1 == (int16_t)key_index) { + return false; + } + + bool key_is_part_of_combo = !COMBO_DISABLED(combo); + + if (record->event.pressed && !COMBO_DISABLED(combo)) { + uint16_t time = _get_combo_term(combo_index, combo); + if (!COMBO_ACTIVE(combo)) { + KEY_STATE_DOWN(combo->state, key_index); + if (longest_term < time) { + longest_term = time; } } + if (ALL_COMBO_KEYS_ARE_DOWN(COMBO_STATE(combo), key_count)) { + /* Combo was fully pressed */ + /* Buffer the combo so we can fire it after COMBO_TERM */ + +#ifndef COMBO_NO_TIMER + /* Don't buffer this combo if its combo term has passed. */ + if (timer && timer_elapsed(timer) > time) { + DISABLE_COMBO(combo); + return true; + } else +#endif + { + + // disable readied combos that overlap with this combo + combo_t *drop = NULL; + for (uint8_t combo_buffer_i = combo_buffer_read; + combo_buffer_i != combo_buffer_write; + INCREMENT_MOD(combo_buffer_i)) { + + queued_combo_t *qcombo = &combo_buffer[combo_buffer_i]; + combo_t *buffered_combo = &key_combos[qcombo->combo_index]; + + if ((drop = overlaps(buffered_combo, combo))) { + DISABLE_COMBO(drop); + if (drop == combo) { + // stop checking for overlaps if dropped combo was current combo. + break; + } else if (combo_buffer_i == combo_buffer_read && drop == buffered_combo) { + /* Drop the disabled buffered combo from the buffer if + * it is in the beginning of the buffer. */ + INCREMENT_MOD(combo_buffer_read); + } + } + + } + + if (drop != combo) { + // save this combo to buffer + combo_buffer[combo_buffer_write] = (queued_combo_t){ + .combo_index=combo_index, + }; + INCREMENT_MOD(combo_buffer_write); + + // get possible longer waiting time for tap-/hold-only combos. + longest_term = _get_wait_time(combo_index, combo); + } + } // if timer elapsed end + + } } else { - if (ALL_COMBO_KEYS_ARE_DOWN) { /* Combo was released */ - send_combo(combo->keycode, false); + // chord releases + if (!COMBO_ACTIVE(combo) && ALL_COMBO_KEYS_ARE_DOWN(COMBO_STATE(combo), key_count)) { + /* First key quickly released */ + if (COMBO_DISABLED(combo) || _get_combo_must_hold(combo_index, combo)) { + // combo wasn't tappable, disable it and drop it from buffer. + drop_combo_from_buffer(combo_index); + key_is_part_of_combo = false; + } +#ifdef COMBO_MUST_TAP_PER_COMBO + else if (get_combo_must_tap(combo_index, combo)) { + // immediately apply tap-only combo + apply_combo(combo_index, combo); + apply_combos(); // also apply other prepared combos and dump key buffer +# ifdef COMBO_PROCESS_KEY_RELEASE + if (process_combo_key_release(combo_index, combo, key_index, keycode)) { + release_combo(combo_index, combo); + } +# endif + } +#endif + } else if (COMBO_ACTIVE(combo) + && ONLY_ONE_KEY_IS_DOWN(COMBO_STATE(combo)) + && KEY_NOT_YET_RELEASED(COMBO_STATE(combo), key_index) + ) { + /* last key released */ + release_combo(combo_index, combo); + key_is_part_of_combo = true; + +#ifdef COMBO_PROCESS_KEY_RELEASE + process_combo_key_release(combo_index, combo, key_index, keycode); +#endif + } else if (COMBO_ACTIVE(combo) + && KEY_NOT_YET_RELEASED(COMBO_STATE(combo), key_index) + ) { + /* first or middle key released */ + key_is_part_of_combo = true; + +#ifdef COMBO_PROCESS_KEY_RELEASE + if (process_combo_key_release(combo_index, combo, key_index, keycode)) { + release_combo(combo_index, combo); + } +#endif } else { - /* continue processing without immediately returning */ - is_combo_active = false; + /* The released key was part of an incomplete combo */ + key_is_part_of_combo = false; } - KEY_STATE_UP(index); + KEY_STATE_UP(combo->state, key_index); } - return is_combo_active; + return key_is_part_of_combo; } -#define NO_COMBO_KEYS_ARE_DOWN (0 == combo->state) - bool process_combo(uint16_t keycode, keyrecord_t *record) { bool is_combo_key = false; - drop_buffer = false; bool no_combo_keys_pressed = true; if (keycode == CMB_ON && record->event.pressed) { @@ -144,62 +475,81 @@ bool process_combo(uint16_t keycode, keyrecord_t *record) { if (!is_combo_enabled()) { return true; } -#ifndef COMBO_VARIABLE_LEN - for (current_combo_index = 0; current_combo_index < COMBO_COUNT; ++current_combo_index) { -#else - for (current_combo_index = 0; current_combo_index < COMBO_LEN; ++current_combo_index) { + +#ifdef COMBO_ONLY_FROM_LAYER + /* Only check keycodes from one layer. */ + keycode = keymap_key_to_keycode(COMBO_ONLY_FROM_LAYER, record->event.key); #endif - combo_t *combo = &key_combos[current_combo_index]; - is_combo_key |= process_single_combo(combo, keycode, record); - no_combo_keys_pressed = no_combo_keys_pressed && NO_COMBO_KEYS_ARE_DOWN; + + for (uint16_t idx = 0; idx < COMBO_LEN; ++idx) { + combo_t *combo = &key_combos[idx]; + is_combo_key |= process_single_combo(combo, keycode, record, idx); + no_combo_keys_pressed = no_combo_keys_pressed && (NO_COMBO_KEYS_ARE_DOWN || COMBO_ACTIVE(combo) || COMBO_DISABLED(combo)); } - if (drop_buffer) { - /* buffer is only dropped when we complete a combo, so we refresh the timer - * here */ - timer = timer_read(); - dump_key_buffer(false); - } else if (!is_combo_key) { - /* if no combos claim the key we need to emit the keybuffer */ - dump_key_buffer(true); - - // reset state if there are no combo keys pressed at all - if (no_combo_keys_pressed) { - timer = 0; - is_active = true; - } - } else if (record->event.pressed && is_active) { - /* otherwise the key is consumed and placed in the buffer */ + if (record->event.pressed && is_combo_key) { +#ifndef COMBO_NO_TIMER +# ifdef COMBO_STRICT_TIMER + if (!timer) { + // timer is set only on the first key + timer = timer_read(); + } +# else timer = timer_read(); +# endif +#endif - if (buffer_size < MAX_COMBO_LENGTH) { -#ifdef COMBO_ALLOW_ACTION_KEYS - key_buffer[buffer_size++] = *record; -#else - key_buffer[buffer_size++] = keycode; + if (key_buffer_size < COMBO_KEY_BUFFER_LENGTH) { + key_buffer[key_buffer_size++] = (queued_record_t){ + .record = *record, + .keycode = keycode, + .combo_index = -1, // this will be set when applying combos + }; + } + } else { + if (combo_buffer_read != combo_buffer_write) { + // some combo is prepared + apply_combos(); + } else { + // reset state if there are no combo keys pressed at all + dump_key_buffer(); +#ifndef COMBO_NO_TIMER + timer = 0; #endif + clear_combos(); } } - return !is_combo_key; } void combo_task(void) { - if (b_combo_enable && is_active && timer && timer_elapsed(timer) > COMBO_TERM) { - /* This disables the combo, meaning key events for this - * combo will be handled by the next processors in the chain - */ - is_active = false; - dump_key_buffer(true); + if (!b_combo_enable) { + return; } + +#ifndef COMBO_NO_TIMER + if (timer && timer_elapsed(timer) > longest_term) { + if (combo_buffer_read != combo_buffer_write) { + apply_combos(); + longest_term = 0; + timer = 0; + } else { + dump_key_buffer(); + timer = 0; + clear_combos(); + } + } +#endif } void combo_enable(void) { b_combo_enable = true; } void combo_disable(void) { - b_combo_enable = is_active = false; +#ifndef COMBO_NO_TIMER timer = 0; - dump_key_buffer(true); +#endif + b_combo_enable = false; + combo_buffer_read = combo_buffer_write; } void combo_toggle(void) { diff --git a/quantum/process_keycode/process_combo.h b/quantum/process_keycode/process_combo.h index 9af97588b2..43c36d79e6 100644 --- a/quantum/process_keycode/process_combo.h +++ b/quantum/process_keycode/process_combo.h @@ -20,23 +20,38 @@ #include "quantum.h" #include -#ifdef EXTRA_EXTRA_LONG_COMBOS +#ifdef EXTRA_SHORT_COMBOS +# define MAX_COMBO_LENGTH 6 +#elif defined(EXTRA_EXTRA_LONG_COMBOS) # define MAX_COMBO_LENGTH 32 -#elif EXTRA_LONG_COMBOS +#elif defined(EXTRA_LONG_COMBOS) # define MAX_COMBO_LENGTH 16 #else # define MAX_COMBO_LENGTH 8 #endif +#ifndef COMBO_KEY_BUFFER_LENGTH +# define COMBO_KEY_BUFFER_LENGTH MAX_COMBO_LENGTH +#endif +#ifndef COMBO_BUFFER_LENGTH +# define COMBO_BUFFER_LENGTH 4 +#endif + typedef struct { const uint16_t *keys; uint16_t keycode; -#ifdef EXTRA_EXTRA_LONG_COMBOS +#ifdef EXTRA_SHORT_COMBOS + uint8_t state; +#else + bool disabled; + bool active; +# if defined(EXTRA_EXTRA_LONG_COMBOS) uint32_t state; -#elif EXTRA_LONG_COMBOS +# elif defined(EXTRA_LONG_COMBOS) uint16_t state; -#else +# else uint8_t state; +# endif #endif } combo_t; @@ -46,12 +61,15 @@ typedef struct { { .keys = &(ck)[0] } #define COMBO_END 0 -#ifndef COMBO_COUNT -# define COMBO_COUNT 0 -#endif #ifndef COMBO_TERM -# define COMBO_TERM TAPPING_TERM +# define COMBO_TERM 50 #endif +#ifndef COMBO_HOLD_TERM +# define COMBO_HOLD_TERM TAPPING_TERM +#endif + +/* check if keycode is only modifiers */ +#define KEYCODE_IS_MOD(code) (IS_MOD(code) || (code >= QK_MODS && code <= QK_MODS_MAX && !(code & QK_BASIC_MAX))) bool process_combo(uint16_t keycode, keyrecord_t *record); void combo_task(void); diff --git a/quantum/quantum.c b/quantum/quantum.c index 3329c1146b..d173388714 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -143,7 +143,13 @@ void reset_keyboard(void) { } /* Convert record into usable keycode via the contained event. */ -uint16_t get_record_keycode(keyrecord_t *record, bool update_layer_cache) { return get_event_keycode(record->event, update_layer_cache); } +uint16_t get_record_keycode(keyrecord_t *record, bool update_layer_cache) { +#ifdef COMBO_ENABLE + if (record->keycode) { return record->keycode; } +#endif + return get_event_keycode(record->event, update_layer_cache); +} + /* Convert event into usable keycode. Checks the layer cache to ensure that it * retains the correct keycode after a layer change, if the key is still pressed. @@ -169,6 +175,18 @@ uint16_t get_event_keycode(keyevent_t event, bool update_layer_cache) { return keymap_key_to_keycode(layer_switch_get_layer(event.key), event.key); } +/* Get keycode, and then process pre tapping functionality */ +bool pre_process_record_quantum(keyrecord_t *record) { + if (!( +#ifdef COMBO_ENABLE + process_combo(get_record_keycode(record, true), record) && +#endif + true)) { + return false; + } + return true; // continue processing +} + /* Get keycode, and then call keyboard function */ void post_process_record_quantum(keyrecord_t *record) { uint16_t keycode = get_record_keycode(record, false); @@ -254,9 +272,6 @@ bool process_record_quantum(keyrecord_t *record) { #ifdef LEADER_ENABLE process_leader(keycode, record) && #endif -#ifdef COMBO_ENABLE - process_combo(keycode, record) && -#endif #ifdef PRINTING_ENABLE process_printer(keycode, record) && #endif diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c index bd41d28b66..d19fd2a045 100644 --- a/tmk_core/common/action.c +++ b/tmk_core/common/action.c @@ -55,6 +55,8 @@ __attribute__((weak)) bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrec __attribute__((weak)) bool get_retro_tapping(uint16_t keycode, keyrecord_t *record) { return false; } #endif +__attribute__((weak)) bool pre_process_record_quantum(keyrecord_t *record) { return true; } + #ifndef TAP_CODE_DELAY # define TAP_CODE_DELAY 0 #endif @@ -106,9 +108,13 @@ void action_exec(keyevent_t event) { #endif #ifndef NO_ACTION_TAPPING - action_tapping_process(record); + if (IS_NOEVENT(record.event) || pre_process_record_quantum(&record)) { + action_tapping_process(record); + } #else - process_record(&record); + if (IS_NOEVENT(record.event) || pre_process_record_quantum(&record)) { + process_record(&record); + } if (!IS_NOEVENT(record.event)) { dprint("processed: "); debug_record(record); @@ -206,7 +212,16 @@ void process_record(keyrecord_t *record) { } void process_record_handler(keyrecord_t *record) { +#ifdef COMBO_ENABLE + action_t action; + if (record->keycode) { + action = action_for_keycode(record->keycode); + } else { + action = store_or_get_action(record->event.pressed, record->event.key); + } +#else action_t action = store_or_get_action(record->event.pressed, record->event.key); +#endif dprint("ACTION: "); debug_action(action); #ifndef NO_ACTION_LAYER @@ -990,6 +1005,24 @@ bool is_tap_key(keypos_t key) { return is_tap_action(action); } +/** \brief Utilities for actions. (FIXME: Needs better description) + * + * FIXME: Needs documentation. + */ +bool is_tap_record(keyrecord_t *record) { +#ifdef COMBO_ENABLE + action_t action; + if (record->keycode) { + action = action_for_keycode(record->keycode); + } else { + action = layer_switch_get_action(record->event.key); + } +#else + action_t action = layer_switch_get_action(record->event.key); +#endif + return is_tap_action(action); +} + /** \brief Utilities for actions. (FIXME: Needs better description) * * FIXME: Needs documentation. diff --git a/tmk_core/common/action.h b/tmk_core/common/action.h index 8cb4722c6e..3d357b33b8 100644 --- a/tmk_core/common/action.h +++ b/tmk_core/common/action.h @@ -53,6 +53,9 @@ typedef struct { #ifndef NO_ACTION_TAPPING tap_t tap; #endif +#ifdef COMBO_ENABLE + uint16_t keycode; +#endif } keyrecord_t; /* Execute action per keyevent */ @@ -60,6 +63,7 @@ void action_exec(keyevent_t event); /* action for key */ action_t action_for_key(uint8_t layer, keypos_t key); +action_t action_for_keycode(uint16_t keycode); /* macro */ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt); @@ -111,6 +115,7 @@ 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); +bool is_tap_record(keyrecord_t *record); bool is_tap_action(action_t action); #ifndef NO_ACTION_TAPPING diff --git a/tmk_core/common/action_tapping.c b/tmk_core/common/action_tapping.c index 56044e096d..1701ae4717 100644 --- a/tmk_core/common/action_tapping.c +++ b/tmk_core/common/action_tapping.c @@ -18,11 +18,16 @@ # define IS_TAPPING_PRESSED() (IS_TAPPING() && tapping_key.event.pressed) # define IS_TAPPING_RELEASED() (IS_TAPPING() && !tapping_key.event.pressed) # define IS_TAPPING_KEY(k) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (k))) +#ifndef COMBO_ENABLE +# define IS_TAPPING_RECORD(r) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (r->event.key))) +#else +# define IS_TAPPING_RECORD(r) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (r->event.key)) && tapping_key.keycode == r->keycode) +#endif __attribute__((weak)) uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) { return TAPPING_TERM; } # ifdef TAPPING_TERM_PER_KEY -# define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < get_tapping_term(get_event_keycode(tapping_key.event, false), &tapping_key)) +# define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < get_tapping_term(get_record_keycode(&tapping_key, false), &tapping_key)) # else # define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < TAPPING_TERM) # endif @@ -103,7 +108,7 @@ bool process_tapping(keyrecord_t *keyp) { if (IS_TAPPING_PRESSED()) { if (WITHIN_TAPPING_TERM(event)) { if (tapping_key.tap.count == 0) { - if (IS_TAPPING_KEY(event.key) && !event.pressed) { + if (IS_TAPPING_RECORD(keyp) && !event.pressed) { // first tap! debug("Tapping: First tap(0->1).\n"); tapping_key.tap.count = 1; @@ -122,14 +127,14 @@ bool process_tapping(keyrecord_t *keyp) { # if defined(TAPPING_TERM_PER_KEY) || (TAPPING_TERM >= 500) || defined(PERMISSIVE_HOLD) || defined(PERMISSIVE_HOLD_PER_KEY) else if ((( # ifdef TAPPING_TERM_PER_KEY - get_tapping_term(get_event_keycode(tapping_key.event, false), keyp) + get_tapping_term(get_record_keycode(&tapping_key, false), keyp) # else TAPPING_TERM # endif >= 500) # ifdef PERMISSIVE_HOLD_PER_KEY - || get_permissive_hold(get_event_keycode(tapping_key.event, false), keyp) + || get_permissive_hold(get_record_keycode(&tapping_key, false), keyp) # elif defined(PERMISSIVE_HOLD) || true # endif @@ -177,7 +182,7 @@ bool process_tapping(keyrecord_t *keyp) { } // tap_count > 0 else { - if (IS_TAPPING_KEY(event.key) && !event.pressed) { + if (IS_TAPPING_RECORD(keyp) && !event.pressed) { debug("Tapping: Tap release("); debug_dec(tapping_key.tap.count); debug(")\n"); @@ -186,11 +191,15 @@ bool process_tapping(keyrecord_t *keyp) { tapping_key = *keyp; debug_tapping_key(); return true; - } else if (is_tap_key(event.key) && event.pressed) { + } else if (is_tap_record(keyp) && event.pressed) { if (tapping_key.tap.count > 1) { debug("Tapping: Start new tap with releasing last tap(>1).\n"); // unregister key - process_record(&(keyrecord_t){.tap = tapping_key.tap, .event.key = tapping_key.event.key, .event.time = event.time, .event.pressed = false}); + process_record(&(keyrecord_t){.tap = tapping_key.tap, .event.key = tapping_key.event.key, .event.time = event.time, .event.pressed = false, +#ifdef COMBO_ENABLE + .keycode = tapping_key.keycode, +#endif + }); } else { debug("Tapping: Start while last tap(1).\n"); } @@ -218,17 +227,21 @@ bool process_tapping(keyrecord_t *keyp) { debug_tapping_key(); return false; } else { - if (IS_TAPPING_KEY(event.key) && !event.pressed) { + if (IS_TAPPING_RECORD(keyp) && !event.pressed) { debug("Tapping: End. last timeout tap release(>0)."); keyp->tap = tapping_key.tap; process_record(keyp); tapping_key = (keyrecord_t){}; return true; - } else if (is_tap_key(event.key) && event.pressed) { + } else if (is_tap_record(keyp) && event.pressed) { if (tapping_key.tap.count > 1) { debug("Tapping: Start new tap with releasing last timeout tap(>1).\n"); // unregister key - process_record(&(keyrecord_t){.tap = tapping_key.tap, .event.key = tapping_key.event.key, .event.time = event.time, .event.pressed = false}); + process_record(&(keyrecord_t){.tap = tapping_key.tap, .event.key = tapping_key.event.key, .event.time = event.time, .event.pressed = false, +#ifdef COMBO_ENABLE + .keycode = tapping_key.keycode, +#endif + }); } else { debug("Tapping: Start while last timeout tap(1).\n"); } @@ -248,12 +261,12 @@ bool process_tapping(keyrecord_t *keyp) { } else if (IS_TAPPING_RELEASED()) { if (WITHIN_TAPPING_TERM(event)) { if (event.pressed) { - if (IS_TAPPING_KEY(event.key)) { + if (IS_TAPPING_RECORD(keyp)) { //# ifndef TAPPING_FORCE_HOLD # if !defined(TAPPING_FORCE_HOLD) || defined(TAPPING_FORCE_HOLD_PER_KEY) if ( # ifdef TAPPING_FORCE_HOLD_PER_KEY - !get_tapping_force_hold(get_event_keycode(tapping_key.event, false), keyp) && + !get_tapping_force_hold(get_record_keycode(&tapping_key, false), keyp) && # endif !tapping_key.tap.interrupted && tapping_key.tap.count > 0) { // sequential tap. @@ -271,7 +284,7 @@ bool process_tapping(keyrecord_t *keyp) { // FIX: start new tap again tapping_key = *keyp; return true; - } else if (is_tap_key(event.key)) { + } else if (is_tap_record(keyp)) { // Sequential tap can be interfered with other tap key. debug("Tapping: Start with interfering other tap.\n"); tapping_key = *keyp; @@ -303,7 +316,7 @@ bool process_tapping(keyrecord_t *keyp) { } // not tapping state else { - if (event.pressed && is_tap_key(event.key)) { + if (event.pressed && is_tap_record(keyp)) { debug("Tapping: Start(Press tap key).\n"); tapping_key = *keyp; process_record_tap_hint(&tapping_key); diff --git a/tmk_core/common/action_tapping.h b/tmk_core/common/action_tapping.h index 893ccb1ce1..7de8049c7f 100644 --- a/tmk_core/common/action_tapping.h +++ b/tmk_core/common/action_tapping.h @@ -30,6 +30,7 @@ along with this program. If not, see . #define WAITING_BUFFER_SIZE 8 #ifndef NO_ACTION_TAPPING +uint16_t get_record_keycode(keyrecord_t *record, bool update_layer_cache); uint16_t get_event_keycode(keyevent_t event, bool update_layer_cache); void action_tapping_process(keyrecord_t record); -- cgit v1.2.3 From 610035dce8f4f7010779e61e1cb590eebc8cea46 Mon Sep 17 00:00:00 2001 From: Sergey Vlasov Date: Sat, 7 Aug 2021 02:16:26 +0300 Subject: Add HOLD_ON_OTHER_KEY_PRESS option for dual-role keys (#9404) * Add HOLD_ON_OTHER_KEY_PRESS option for dual-role keys Implement an additional option for dual-role keys which converts the dual-role key press into a hold action immediately when another key is pressed (this is different from the existing PERMISSIVE_HOLD option, which selects the hold action when another key is tapped (pressed and then released) while the dual-role key is pressed). The Mod-Tap keys already behave in a similar way, unless the IGNORE_MOD_TAP_INTERRUPT option is enabled (but with some additional delays); the added option makes this behavior available for all other kinds of dual-role keys. * [Docs] Update tap-hold docs for HOLD_ON_OTHER_KEY_PRESS Document the newly added HOLD_ON_OTHER_KEY_PRESS option and update the documentation for closely related options (PERMISSIVE_HOLD and IGNORE_MOD_TAP_INTERRUPT). Use Layer Tap instead of Mod Tap in examples for PERMISSIVE_HOLD and HOLD_ON_OTHER_KEY_PRESS, because the effect of using these options with Mod Tap keys is mostly invisible without IGNORE_MOD_TAP_INTERRUPT. Add comments before return statements in sample implementations of `get_ignore_mod_tap_interrupt()`, `get_hold_on_other_key_press()` and `get_permissive_hold()`. Thanks to @Erovia and @precondition for comments and suggestions to improve the documentation.--- docs/tap_hold.md | 108 ++++++++++++++++++++++++++++++++------- tmk_core/common/action_tapping.c | 17 ++++++ 2 files changed, 106 insertions(+), 19 deletions(-) (limited to 'tmk_core') diff --git a/docs/tap_hold.md b/docs/tap_hold.md index 085bbde16a..71bff30baa 100644 --- a/docs/tap_hold.md +++ b/docs/tap_hold.md @@ -36,29 +36,49 @@ uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) { } ``` +## Tap-Or-Hold Decision Modes -## Permissive Hold +The code which decides between the tap and hold actions of dual-role keys supports three different modes, in increasing order of preference for the hold action: -As of [PR#1359](https://github.com/qmk/qmk_firmware/pull/1359/), there is a new `config.h` option: +1. The default mode selects the hold action only if the dual-role key is held down longer than the tapping term. In this mode pressing other keys while the dual-role key is held down does not influence the tap-or-hold decision. + +2. The “permissive hold” mode, in addition to the default behavior, immediately selects the hold action when another key is tapped (pressed and then released) while the dual-role key is held down, even if this happens earlier than the tapping term. If another key is just pressed, but then the dual-role key is released before that other key (and earlier than the tapping term), this mode will still select the tap action. + +3. The “hold on other key press” mode, in addition to the default behavior, immediately selects the hold action when another key is pressed while the dual-role key is held down, even if this happens earlier than the tapping term. + +Note that until the tap-or-hold decision completes (which happens when either the dual-role key is released, or the tapping term has expired, or the extra condition for the selected decision mode is satisfied), key events are delayed and not transmitted to the host immediately. The default mode gives the most delay (if the dual-role key is held down, this mode always waits for the whole tapping term), and the other modes may give less delay when other keys are pressed, because the hold action may be selected earlier. + +### Permissive Hold + +The “permissive hold” mode can be enabled for all dual-role keys by adding the corresponding option to `config.h`: ```c #define PERMISSIVE_HOLD ``` -This makes tap and hold keys (like Mod Tap) work better for fast typists, or for high `TAPPING_TERM` settings. +This makes tap and hold keys (like Layer Tap) work better for fast typists, or for high `TAPPING_TERM` settings. -If you press a Mod Tap key, tap another key (press and release) and then release the Mod Tap key, all within the tapping term, it will output the tapping function for both keys. +If you press a dual-role key, tap another key (press and release) and then release the dual-role key, all within the tapping term, by default the dual-role key will perform its tap action. If the `PERMISSIVE_HOLD` option is enabled, the dual-role key will perform its hold action instead. -For Instance: +An example of a sequence which is affected by the “permissive hold” mode: -- `SFT_T(KC_A)` Down -- `KC_X` Down -- `KC_X` Up -- `SFT_T(KC_A)` Up +- `LT(2, KC_A)` Down +- `KC_L` Down (the `L` key is also mapped to `KC_RGHT` on layer 2) +- `KC_L` Up +- `LT(2, KC_A)` Up + +Normally, if you do all this within the `TAPPING_TERM` (default: 200ms), this will be registered as `al` by the firmware and host system. With the `PERMISSIVE_HOLD` option enabled, the Layer Tap key is considered as a layer switch if another key is tapped, and the above sequence would be registered as `KC_RGHT` (the mapping of `L` on layer 2). + +However, this slightly different sequence will not be affected by the “permissive hold” mode: -Normally, if you do all this within the `TAPPING_TERM` (default: 200ms) this will be registered as `ax` by the firmware and host system. With permissive hold enabled, this modifies how this is handled by considering the Mod Tap keys as a Mod if another key is tapped, and would registered as `X` (`SHIFT`+`x`). +- `LT(2, KC_A)` Down +- `KC_L` Down (the `L` key is also mapped to `KC_RGHT` on layer 2) +- `LT(2, KC_A)` Up +- `KC_L` Up -?> If you have `Ignore Mod Tap Interrupt` enabled, as well, this will modify how both work. The regular key has the modifier added if the first key is released first or if both keys are held longer than the `TAPPING_TERM`. +In the sequence above the dual-role key is released before the other key is released, and if that happens within the tapping term, the “permissive hold” mode will still choose the tap action for the dual-role key, and the sequence will be registered as `al` by the host. + +?> The `PERMISSIVE_HOLD` option also affects Mod Tap keys, but this may not be noticeable if you do not also enable the `IGNORE_MOD_TAP_INTERRUPT` option for those keys, because the default handler for Mod Tap keys also considers both the “nested press” and “rolling press” sequences like shown above as a modifier hold, not the tap action. If you do not enable `IGNORE_MOD_TAP_INTERRUPT`, the effect of `PERMISSIVE_HOLD` on Mod Tap keys would be limited to reducing the delay before the key events are made visible to the host. For more granular control of this feature, you can add the following to your `config.h`: @@ -72,13 +92,60 @@ You can then add the following function to your keymap: bool get_permissive_hold(uint16_t keycode, keyrecord_t *record) { switch (keycode) { case LT(1, KC_BSPC): + // Immediately select the hold action when another key is tapped. + return true; + default: + // Do not select the hold action when another key is tapped. + return false; + } +} +``` + +### Hold On Other Key Press + +The “hold on other key press” mode can be enabled for all dual-role keys by adding the corresponding option to `config.h`: + +```c +#define HOLD_ON_OTHER_KEY_PRESS +``` + +This mode makes tap and hold keys (like Layer Tap) work better for fast typists, or for high `TAPPING_TERM` settings. Compared to the “permissive hold” mode, this mode selects the hold action in more cases. + +If you press a dual-role key, press another key, and then release the dual-role key, all within the tapping term, by default the dual-role key will perform its tap action. If the `HOLD_ON_OTHER_KEY_PRESS` option is enabled, the dual-role key will perform its hold action instead. + +An example of a sequence which is affected by the “hold on other key press” mode, but not by the “permissive hold” mode: + +- `LT(2, KC_A)` Down +- `KC_L` Down (the `L` key is also mapped to `KC_RGHT` on layer 2) +- `LT(2, KC_A)` Up +- `KC_L` Up + +Normally, if you do all this within the `TAPPING_TERM` (default: 200ms), this will be registered as `al` by the firmware and host system. With the `HOLD_ON_OTHER_KEY_PRESS` option enabled, the Layer Tap key is considered as a layer switch if another key is pressed, and the above sequence would be registered as `KC_RGHT` (the mapping of `L` on layer 2). + +?> The `HOLD_ON_OTHER_KEY_PRESS` option also affects Mod Tap keys, but this may not be noticeable if you do not also enable the `IGNORE_MOD_TAP_INTERRUPT` option for those keys, because the default handler for Mod Tap keys also considers the “rolling press” sequence like shown above as a modifier hold, not the tap action. If you do not enable `IGNORE_MOD_TAP_INTERRUPT`, the effect of `HOLD_ON_OTHER_KEY_PRESS` on Mod Tap keys would be limited to reducing the delay before the key events are made visible to the host. + +For more granular control of this feature, you can add the following to your `config.h`: + +```c +#define HOLD_ON_OTHER_KEY_PRESS_PER_KEY +``` + +You can then add the following function to your keymap: + +```c +bool get_hold_on_other_key_press(uint16_t keycode, keyrecord_t *record) { + switch (keycode) { + case LT(1, KC_BSPC): + // Immediately select the hold action when another key is pressed. return true; default: + // Do not select the hold action when another key is pressed. return false; } } ``` + ## Ignore Mod Tap Interrupt To enable this setting, add this to your `config.h`: @@ -87,23 +154,22 @@ To enable this setting, add this to your `config.h`: #define IGNORE_MOD_TAP_INTERRUPT ``` -Similar to Permissive Hold, this alters how the firmware processes inputs for fast typists. If you press a Mod Tap key, press another key, release the Mod Tap key, and then release the normal key, it would normally output the Mod plus the normal key, even if pressed within the `TAPPING_TERM`. This may not be desirable for rolling combo keys, or for fast typists who have a Mod Tap on a frequently used key (`RCTL_T(KC_QUOT)`, for example). +?> This option affects only the Mod Tap keys; it does not affect other dual-role keys such as Layer Tap. + +By default the tap-or-hold decision for Mod Tap keys strongly prefers the hold action. If you press a Mod Tap key, then press another key while still holding the Mod Tap key down, the Mod Tap press will be handled as a modifier hold even if the Mod Tap key is then released within the tapping term, and irrespective of the order in which those keys are released. Using options such as `PERMISSIVE_HOLD` or `HOLD_ON_OTHER_KEY_PRESS` will not affect the functionality of Mod Tap keys in a major way (these options would still affect the delay until the common code for dual-role keys finishes its tap-or-hold decision, but then the special code for Mod Tap keys will override the result of that decision and choose the hold action if another key was pressed). In fact, by default the tap-or-hold decision for Mod Tap keys is done in the same way as if the `HOLD_ON_OTHER_KEY_PRESS` option was enabled, but without the decreased delay provided by `HOLD_ON_OTHER_KEY_PRESS`. -Setting `Ignore Mod Tap Interrupt` requires holding both keys for the `TAPPING_TERM` to trigger the hold function (the mod). +If the `IGNORE_MOD_TAP_INTERRUPT` option is enabled, Mod Tap keys are no longer treated as a special case, and their behavior will match the behavior of other dual-role keys such as Layer Tap. Then the behavior of Mod Tap keys can be further tuned using other options such as `PERMISSIVE_HOLD` or `HOLD_ON_OTHER_KEY_PRESS`. -For Instance: +An example of a sequence which will be affected by the `IGNORE_MOD_TAP_INTERRUPT` option (assuming that options like `PERMISSIVE_HOLD` or `HOLD_ON_OTHER_KEY_PRESS` are not enabled): - `SFT_T(KC_A)` Down - `KC_X` Down - `SFT_T(KC_A)` Up - `KC_X` Up -Normally, this would send a capital `X` (`SHIFT`+`x`), or, Mod + key. With `Ignore Mod Tap Interrupt` enabled, holding both keys are required for the `TAPPING_TERM` to register the hold action. A quick tap will output `ax` in this case, while a hold on both will still output capital `X` (`SHIFT`+`x`). - - -?> __Note__: This only concerns modifiers and not layer switching keys. +Normally, this would send a capital `X` (`SHIFT`+`x`), even if the sequence is performed faster than the `TAPPING_TERM`. However, if the `IGNORE_MOD_TAP_INTERRUPT` option is enabled, the `SFT_T(KC_A)` key must be held longer than the `TAPPING_TERM` to register the hold action. A quick tap will output `ax` in this case, while a hold will still output a capital `X` (`SHIFT`+`x`). -?> If you have `Permissive Hold` enabled, as well, this will modify how both work. The regular key has the modifier added if the first key is released first or if both keys are held longer than the `TAPPING_TERM`. +However, if the `HOLD_ON_OTHER_KEY_PRESS` option is enabled in addition to `IGNORE_MOD_TAP_INTERRUPT`, the above sequence will again send a capital `X` (`SHIFT`+`x`) even if performed faster that the `TAPPING_TERM`. The difference from the default configuration is that by default the host will receive the key events only after the `SFT_T(KC_A)` key is released, but with the `HOLD_ON_OTHER_KEY_PRESS` option the host will start receiving key events when the `KC_X` key is pressed. For more granular control of this feature, you can add the following to your `config.h`: @@ -117,8 +183,12 @@ You can then add the following function to your keymap: bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record) { switch (keycode) { case SFT_T(KC_SPC): + // Do not force the mod-tap key press to be handled as a modifier + // if any other key was pressed while the mod-tap key is held down. return true; default: + // Force the mod-tap key press to be handled as a modifier if any + // other key was pressed while the mod-tap key is held down. return false; } } diff --git a/tmk_core/common/action_tapping.c b/tmk_core/common/action_tapping.c index 1701ae4717..36839f9faf 100644 --- a/tmk_core/common/action_tapping.c +++ b/tmk_core/common/action_tapping.c @@ -40,6 +40,10 @@ __attribute__((weak)) bool get_tapping_force_hold(uint16_t keycode, keyrecord_t __attribute__((weak)) bool get_permissive_hold(uint16_t keycode, keyrecord_t *record) { return false; } # endif +# ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY +__attribute__((weak)) bool get_hold_on_other_key_press(uint16_t keycode, keyrecord_t *record) { return false; } +# endif + static keyrecord_t tapping_key = {}; static keyrecord_t waiting_buffer[WAITING_BUFFER_SIZE] = {}; static uint8_t waiting_buffer_head = 0; @@ -175,6 +179,19 @@ bool process_tapping(keyrecord_t *keyp) { // set interrupted flag when other key preesed during tapping if (event.pressed) { tapping_key.tap.interrupted = true; +# if defined(HOLD_ON_OTHER_KEY_PRESS) || defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY) +# if defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY) + if (get_hold_on_other_key_press(get_record_keycode(&tapping_key, false), keyp)) +# endif + { + debug("Tapping: End. No tap. Interfered by pressed key\n"); + process_record(&tapping_key); + tapping_key = (keyrecord_t){}; + debug_tapping_key(); + // enqueue + return false; + } +# endif } // enqueue return false; -- cgit v1.2.3 From 7c691d82bf21f8bdbc98d4193d2ad3956528c25a Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Mon, 9 Aug 2021 19:46:03 +0100 Subject: Remove ONEHAND_ENABLE (#13920) --- keyboards/ergodox_ez/keymaps/bpruitt-goddard/rules.mk | 2 +- keyboards/redox_w/redox_w.c | 2 +- keyboards/vitamins_included/vitamins_included.c | 2 +- show_options.mk | 1 - tmk_core/common.mk | 3 --- 5 files changed, 3 insertions(+), 7 deletions(-) (limited to 'tmk_core') diff --git a/keyboards/ergodox_ez/keymaps/bpruitt-goddard/rules.mk b/keyboards/ergodox_ez/keymaps/bpruitt-goddard/rules.mk index 5036ed7fe2..a7f524fa43 100644 --- a/keyboards/ergodox_ez/keymaps/bpruitt-goddard/rules.mk +++ b/keyboards/ergodox_ez/keymaps/bpruitt-goddard/rules.mk @@ -2,7 +2,7 @@ MOUSEKEY_ENABLE = yes # Mouse keys EXTRAKEY_ENABLE = yes # Audio control and System control COMMAND_ENABLE = yes # Commands for debug and configuration NKRO_ENABLE = yes # USB Nkey Rollover - for issues, see github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work -ONEHAND_ENABLE = yes # Allow swapping hands of keyboard +SWAP_HANDS_ENABLE = yes # Allow swapping hands of keyboard KEY_LOCK_ENABLE = yes # Enable the KC_LOCK key TAP_DANCE_ENABLE = yes # Enable the tap dance feature. CONSOLE_ENABLE = yes # Console for debug diff --git a/keyboards/redox_w/redox_w.c b/keyboards/redox_w/redox_w.c index a94e731b39..5b86344536 100644 --- a/keyboards/redox_w/redox_w.c +++ b/keyboards/redox_w/redox_w.c @@ -15,7 +15,7 @@ void matrix_init_kb(void) { led_init(); } -#ifdef ONEHAND_ENABLE +#ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { {{13, 0}, {12, 0}, {11, 0}, {10, 0}, {9, 0}, {8, 0}, {7, 0}, {6, 0}, {5, 0}, {4, 0}, {3, 0}, {2, 0}, {1, 0}, {0, 0}}, diff --git a/keyboards/vitamins_included/vitamins_included.c b/keyboards/vitamins_included/vitamins_included.c index 078f93e0e6..e83c81633c 100644 --- a/keyboards/vitamins_included/vitamins_included.c +++ b/keyboards/vitamins_included/vitamins_included.c @@ -1,6 +1,6 @@ #include QMK_KEYBOARD_H -#ifdef ONEHAND_ENABLE +#ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { diff --git a/show_options.mk b/show_options.mk index 31375d112f..8aed634dae 100644 --- a/show_options.mk +++ b/show_options.mk @@ -69,7 +69,6 @@ OTHER_OPTION_NAMES = \ KEYLOGGER_ENABLE \ LCD_BACKLIGHT_ENABLE \ MACROS_ENABLED \ - ONEHAND_ENABLE \ PS2_MOUSE_ENABLE \ RAW_ENABLE \ SWAP_HANDS_ENABLE \ diff --git a/tmk_core/common.mk b/tmk_core/common.mk index bd4142364c..6c8cf69356 100644 --- a/tmk_core/common.mk +++ b/tmk_core/common.mk @@ -98,9 +98,6 @@ ifeq ($(strip $(BLUETOOTH)), RN42) TMK_COMMON_DEFS += -DNO_USB_STARTUP_CHECK endif -ifeq ($(strip $(ONEHAND_ENABLE)), yes) - SWAP_HANDS_ENABLE = yes # backwards compatibility -endif ifeq ($(strip $(SWAP_HANDS_ENABLE)), yes) TMK_COMMON_DEFS += -DSWAP_HANDS_ENABLE endif -- cgit v1.2.3 From ab941ce614e19a7f4bb5bd34dd0ab9eee86bdc27 Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Sun, 15 Aug 2021 21:55:23 +0100 Subject: Move all the flash logic from tmk_core (#13927) --- build_keyboard.mk | 1 + platforms/arm_atsam/flash.mk | 11 +++ platforms/avr/flash.mk | 179 +++++++++++++++++++++++++++++++++++++++++++ platforms/chibios/flash.mk | 87 +++++++++++++++++++++ tmk_core/arm_atsam.mk | 7 -- tmk_core/avr.mk | 175 ------------------------------------------ tmk_core/chibios.mk | 87 --------------------- 7 files changed, 278 insertions(+), 269 deletions(-) create mode 100644 platforms/arm_atsam/flash.mk create mode 100644 platforms/avr/flash.mk create mode 100644 platforms/chibios/flash.mk (limited to 'tmk_core') diff --git a/build_keyboard.mk b/build_keyboard.mk index 38ca2aaa99..262bfd9a70 100644 --- a/build_keyboard.mk +++ b/build_keyboard.mk @@ -375,6 +375,7 @@ ifneq ($(strip $(PROTOCOL)),) else include $(TMK_PATH)/protocol/$(PLATFORM_KEY).mk endif +-include $(TOP_DIR)/platforms/$(PLATFORM_KEY)/flash.mk # TODO: remove this bodge? PROJECT_DEFS := $(OPT_DEFS) diff --git a/platforms/arm_atsam/flash.mk b/platforms/arm_atsam/flash.mk new file mode 100644 index 0000000000..444ba77f53 --- /dev/null +++ b/platforms/arm_atsam/flash.mk @@ -0,0 +1,11 @@ +# Hey Emacs, this is a -*- makefile -*- +############################################################################## +# Architecture or project specific options +# + +flash: bin +ifneq ($(strip $(PROGRAM_CMD)),) + $(PROGRAM_CMD) +else + $(PRINT_OK); $(SILENT) || printf "$(MSG_FLASH_ARCH)" +endif diff --git a/platforms/avr/flash.mk b/platforms/avr/flash.mk new file mode 100644 index 0000000000..e679bf0ace --- /dev/null +++ b/platforms/avr/flash.mk @@ -0,0 +1,179 @@ +# Hey Emacs, this is a -*- makefile -*- +############################################################################## +# Architecture or project specific options +# + +# Autodetect teensy loader +ifndef TEENSY_LOADER_CLI + ifneq (, $(shell which teensy-loader-cli 2>/dev/null)) + TEENSY_LOADER_CLI ?= teensy-loader-cli + else + TEENSY_LOADER_CLI ?= teensy_loader_cli + endif +endif + +define EXEC_TEENSY + $(TEENSY_LOADER_CLI) -mmcu=$(MCU) -w -v $(BUILD_DIR)/$(TARGET).hex +endef + +teensy: $(BUILD_DIR)/$(TARGET).hex check-size cpfirmware + $(call EXEC_TEENSY) + +DFU_PROGRAMMER ?= dfu-programmer +GREP ?= grep + +define EXEC_DFU + if [ "$(1)" ]; then \ + echo "Flashing '$(1)' for EE_HANDS split keyboard support." ;\ + fi; \ + if ! $(DFU_PROGRAMMER) $(MCU) get bootloader-version >/dev/null 2>/dev/null; then\ + printf "$(MSG_BOOTLOADER_NOT_FOUND_QUICK_RETRY)" ;\ + sleep $(BOOTLOADER_RETRY_TIME) ;\ + while ! $(DFU_PROGRAMMER) $(MCU) get bootloader-version >/dev/null 2>/dev/null; do\ + printf "." ;\ + sleep $(BOOTLOADER_RETRY_TIME) ;\ + done ;\ + printf "\n" ;\ + fi; \ + $(DFU_PROGRAMMER) $(MCU) get bootloader-version ;\ + if $(DFU_PROGRAMMER) --version 2>&1 | $(GREP) -q 0.7 ; then\ + $(DFU_PROGRAMMER) $(MCU) erase --force; \ + if [ "$(1)" ]; then \ + $(DFU_PROGRAMMER) $(MCU) flash --force --eeprom $(QUANTUM_PATH)/split_common/$(1);\ + fi; \ + $(DFU_PROGRAMMER) $(MCU) flash --force $(BUILD_DIR)/$(TARGET).hex;\ + else \ + $(DFU_PROGRAMMER) $(MCU) erase; \ + if [ "$(1)" ]; then \ + $(DFU_PROGRAMMER) $(MCU) flash-eeprom $(QUANTUM_PATH)/split_common/$(1);\ + fi; \ + $(DFU_PROGRAMMER) $(MCU) flash $(BUILD_DIR)/$(TARGET).hex;\ + fi; \ + $(DFU_PROGRAMMER) $(MCU) reset +endef + +dfu: $(BUILD_DIR)/$(TARGET).hex cpfirmware check-size + $(call EXEC_DFU) + +dfu-start: + $(DFU_PROGRAMMER) $(MCU) reset + $(DFU_PROGRAMMER) $(MCU) start + +dfu-ee: $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).eep + if $(DFU_PROGRAMMER) --version 2>&1 | $(GREP) -q 0.7 ; then\ + $(DFU_PROGRAMMER) $(MCU) flash --force --eeprom $(BUILD_DIR)/$(TARGET).eep;\ + else\ + $(DFU_PROGRAMMER) $(MCU) flash-eeprom $(BUILD_DIR)/$(TARGET).eep;\ + fi + $(DFU_PROGRAMMER) $(MCU) reset + +dfu-split-left: $(BUILD_DIR)/$(TARGET).hex cpfirmware check-size + $(call EXEC_DFU,eeprom-lefthand.eep) + +dfu-split-right: $(BUILD_DIR)/$(TARGET).hex cpfirmware check-size + $(call EXEC_DFU,eeprom-righthand.eep) + +AVRDUDE_PROGRAMMER ?= avrdude + +define EXEC_AVRDUDE + list_devices() { \ + if $(GREP) -q -s icrosoft /proc/version; then \ + wmic.exe path Win32_SerialPort get DeviceID 2>/dev/null | LANG=C perl -pne 's/COM(\d+)/COM.($$1-1)/e' | sed 's!COM!/dev/ttyS!' | xargs echo -n | sort; \ + elif [ "`uname`" = "FreeBSD" ]; then \ + ls /dev/tty* | grep -v '\.lock$$' | grep -v '\.init$$'; \ + else \ + ls /dev/tty*; \ + fi; \ + }; \ + USB= ;\ + printf "Waiting for USB serial port - reset your controller now (Ctrl+C to cancel)"; \ + TMP1=`mktemp`; \ + TMP2=`mktemp`; \ + list_devices > $$TMP1; \ + while [ -z "$$USB" ]; do \ + sleep $(BOOTLOADER_RETRY_TIME); \ + printf "."; \ + list_devices > $$TMP2; \ + USB=`comm -13 $$TMP1 $$TMP2 | $(GREP) -o '/dev/tty.*'`; \ + mv $$TMP2 $$TMP1; \ + done; \ + rm $$TMP1; \ + echo ""; \ + echo "Device $$USB has appeared; assuming it is the controller."; \ + if $(GREP) -q -s 'MINGW\|MSYS\|icrosoft' /proc/version; then \ + USB=`echo "$$USB" | LANG=C perl -pne 's/\/dev\/ttyS(\d+)/COM.($$1+1)/e'`; \ + echo "Remapped USB port to $$USB"; \ + sleep 1; \ + else \ + printf "Waiting for $$USB to become writable."; \ + while [ ! -w "$$USB" ]; do sleep $(BOOTLOADER_RETRY_TIME); printf "."; done; echo ""; \ + fi; \ + if [ -z "$(1)" ]; then \ + $(AVRDUDE_PROGRAMMER) -p $(MCU) -c avr109 -P $$USB -U flash:w:$(BUILD_DIR)/$(TARGET).hex; \ + else \ + $(AVRDUDE_PROGRAMMER) -p $(MCU) -c avr109 -P $$USB -U flash:w:$(BUILD_DIR)/$(TARGET).hex -U eeprom:w:$(QUANTUM_PATH)/split_common/$(1); \ + fi +endef + +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 + +avrdude-split-left: $(BUILD_DIR)/$(TARGET).hex check-size cpfirmware + $(call EXEC_AVRDUDE,eeprom-lefthand.eep) + +avrdude-split-right: $(BUILD_DIR)/$(TARGET).hex check-size cpfirmware + $(call EXEC_AVRDUDE,eeprom-righthand.eep) + +define EXEC_USBASP + $(AVRDUDE_PROGRAMMER) -p $(AVRDUDE_MCU) -c usbasp -U flash:w:$(BUILD_DIR)/$(TARGET).hex +endef + +usbasp: $(BUILD_DIR)/$(TARGET).hex check-size cpfirmware + $(call EXEC_USBASP) + +BOOTLOADHID_PROGRAMMER ?= bootloadHID + +define EXEC_BOOTLOADHID + # bootloadHid executable has no cross platform detect methods + # so keep running bootloadHid if the output contains "The specified device was not found" + until $(BOOTLOADHID_PROGRAMMER) -r $(BUILD_DIR)/$(TARGET).hex 2>&1 | tee /dev/stderr | grep -v "device was not found"; do\ + printf "$(MSG_BOOTLOADER_NOT_FOUND)" ;\ + sleep 5 ;\ + done +endef + +bootloadHID: $(BUILD_DIR)/$(TARGET).hex check-size cpfirmware + $(call EXEC_BOOTLOADHID) + +HID_BOOTLOADER_CLI ?= hid_bootloader_cli + +define EXEC_HID_LUFA + $(HID_BOOTLOADER_CLI) -mmcu=$(MCU) -w -v $(BUILD_DIR)/$(TARGET).hex +endef + +hid_bootloader: $(BUILD_DIR)/$(TARGET).hex check-size cpfirmware + $(call EXEC_HID_LUFA) + +flash: $(BUILD_DIR)/$(TARGET).hex check-size cpfirmware +ifneq ($(strip $(PROGRAM_CMD)),) + $(PROGRAM_CMD) +else ifeq ($(strip $(BOOTLOADER)), caterina) + $(call EXEC_AVRDUDE) +else ifeq ($(strip $(BOOTLOADER)), halfkay) + $(call EXEC_TEENSY) +else ifeq (dfu,$(findstring dfu,$(BOOTLOADER))) + $(call EXEC_DFU) +else ifeq ($(strip $(BOOTLOADER)), USBasp) + $(call EXEC_USBASP) +else ifeq ($(strip $(BOOTLOADER)), bootloadHID) + $(call EXEC_BOOTLOADHID) +else ifeq ($(strip $(BOOTLOADER)), qmk-hid) + $(call EXEC_HID_LUFA) +else + $(PRINT_OK); $(SILENT) || printf "$(MSG_FLASH_BOOTLOADER)" +endif diff --git a/platforms/chibios/flash.mk b/platforms/chibios/flash.mk new file mode 100644 index 0000000000..46aff6e4b0 --- /dev/null +++ b/platforms/chibios/flash.mk @@ -0,0 +1,87 @@ +# Hey Emacs, this is a -*- makefile -*- +############################################################################## +# Architecture or project specific options +# + +DFU_ARGS ?= +ifneq ("$(SERIAL)","") + DFU_ARGS += -S $(SERIAL) +endif + +DFU_UTIL ?= dfu-util + +define EXEC_DFU_UTIL + if ! $(DFU_UTIL) -l | grep -q "Found DFU"; then \ + printf "$(MSG_BOOTLOADER_NOT_FOUND_QUICK_RETRY)" ;\ + sleep $(BOOTLOADER_RETRY_TIME) ;\ + while ! $(DFU_UTIL) -l | grep -q "Found DFU"; do \ + printf "." ;\ + sleep $(BOOTLOADER_RETRY_TIME) ;\ + done ;\ + printf "\n" ;\ + fi + $(DFU_UTIL) $(DFU_ARGS) -D $(BUILD_DIR)/$(TARGET).bin +endef + +dfu-util: $(BUILD_DIR)/$(TARGET).bin cpfirmware sizeafter + $(call EXEC_DFU_UTIL) + +# TODO: Remove once ARM has a way to configure EECONFIG_HANDEDNESS +# within the emulated eeprom via dfu-util or another tool +ifneq (,$(filter $(MAKECMDGOALS),dfu-util-split-left)) + OPT_DEFS += -DINIT_EE_HANDS_LEFT +endif + +ifneq (,$(filter $(MAKECMDGOALS),dfu-util-split-right)) + OPT_DEFS += -DINIT_EE_HANDS_RIGHT +endif + +dfu-util-split-left: dfu-util + +dfu-util-split-right: dfu-util + +ST_LINK_CLI ?= st-link_cli +ST_LINK_ARGS ?= + +st-link-cli: $(BUILD_DIR)/$(TARGET).hex sizeafter + $(ST_LINK_CLI) $(ST_LINK_ARGS) -q -c SWD -p $(BUILD_DIR)/$(TARGET).hex -Rst + +ST_FLASH ?= st-flash +ST_FLASH_ARGS ?= + +st-flash: $(BUILD_DIR)/$(TARGET).hex sizeafter + $(ST_FLASH) $(ST_FLASH_ARGS) --reset --format ihex write $(BUILD_DIR)/$(TARGET).hex + +# Autodetect teensy loader +ifndef TEENSY_LOADER_CLI + ifneq (, $(shell which teensy-loader-cli 2>/dev/null)) + TEENSY_LOADER_CLI ?= teensy-loader-cli + else + TEENSY_LOADER_CLI ?= teensy_loader_cli + endif +endif + +TEENSY_LOADER_CLI_MCU ?= $(MCU_LDSCRIPT) + +define EXEC_TEENSY + $(TEENSY_LOADER_CLI) -mmcu=$(TEENSY_LOADER_CLI_MCU) -w -v $(BUILD_DIR)/$(TARGET).hex +endef + +teensy: $(BUILD_DIR)/$(TARGET).hex cpfirmware sizeafter + $(call EXEC_TEENSY) + + +flash: $(BUILD_DIR)/$(TARGET).bin cpfirmware sizeafter +ifneq ($(strip $(PROGRAM_CMD)),) + $(PROGRAM_CMD) +else ifeq ($(strip $(BOOTLOADER)),kiibohd) + $(call EXEC_DFU_UTIL) +else ifeq ($(strip $(MCU_FAMILY)),KINETIS) + $(call EXEC_TEENSY) +else ifeq ($(strip $(MCU_FAMILY)),MIMXRT1062) + $(call EXEC_TEENSY) +else ifeq ($(strip $(MCU_FAMILY)),STM32) + $(call EXEC_DFU_UTIL) +else + $(PRINT_OK); $(SILENT) || printf "$(MSG_FLASH_BOOTLOADER)" +endif diff --git a/tmk_core/arm_atsam.mk b/tmk_core/arm_atsam.mk index e4bf60e1af..e9bdc2c3c1 100644 --- a/tmk_core/arm_atsam.mk +++ b/tmk_core/arm_atsam.mk @@ -54,10 +54,3 @@ EXTRALIBDIRS = bin: $(BUILD_DIR)/$(TARGET).hex $(OBJCOPY) -Iihex -Obinary $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin $(COPY) $(BUILD_DIR)/$(TARGET).bin $(TARGET).bin; - -flash: bin -ifneq ($(strip $(PROGRAM_CMD)),) - $(PROGRAM_CMD) -else - $(PRINT_OK); $(SILENT) || printf "$(MSG_FLASH_ARCH)" -endif diff --git a/tmk_core/avr.mk b/tmk_core/avr.mk index a44e15700e..d7bee6d34c 100644 --- a/tmk_core/avr.mk +++ b/tmk_core/avr.mk @@ -89,162 +89,6 @@ DEBUG_PORT = 4242 DEBUG_HOST = localhost #============================================================================ -# Autodetect teensy loader -ifndef TEENSY_LOADER_CLI - ifneq (, $(shell which teensy-loader-cli 2>/dev/null)) - TEENSY_LOADER_CLI ?= teensy-loader-cli - else - TEENSY_LOADER_CLI ?= teensy_loader_cli - endif -endif - -define EXEC_TEENSY - $(TEENSY_LOADER_CLI) -mmcu=$(MCU) -w -v $(BUILD_DIR)/$(TARGET).hex -endef - -teensy: $(BUILD_DIR)/$(TARGET).hex check-size cpfirmware - $(call EXEC_TEENSY) - -DFU_PROGRAMMER ?= dfu-programmer -GREP ?= grep - - -define EXEC_DFU - if [ "$(1)" ]; then \ - echo "Flashing '$(1)' for EE_HANDS split keyboard support." ;\ - fi; \ - if ! $(DFU_PROGRAMMER) $(MCU) get bootloader-version >/dev/null 2>/dev/null; then\ - printf "$(MSG_BOOTLOADER_NOT_FOUND_QUICK_RETRY)" ;\ - sleep $(BOOTLOADER_RETRY_TIME) ;\ - while ! $(DFU_PROGRAMMER) $(MCU) get bootloader-version >/dev/null 2>/dev/null; do\ - printf "." ;\ - sleep $(BOOTLOADER_RETRY_TIME) ;\ - done ;\ - printf "\n" ;\ - fi; \ - $(DFU_PROGRAMMER) $(MCU) get bootloader-version ;\ - if $(DFU_PROGRAMMER) --version 2>&1 | $(GREP) -q 0.7 ; then\ - $(DFU_PROGRAMMER) $(MCU) erase --force; \ - if [ "$(1)" ]; then \ - $(DFU_PROGRAMMER) $(MCU) flash --force --eeprom $(QUANTUM_PATH)/split_common/$(1);\ - fi; \ - $(DFU_PROGRAMMER) $(MCU) flash --force $(BUILD_DIR)/$(TARGET).hex;\ - else \ - $(DFU_PROGRAMMER) $(MCU) erase; \ - if [ "$(1)" ]; then \ - $(DFU_PROGRAMMER) $(MCU) flash-eeprom $(QUANTUM_PATH)/split_common/$(1);\ - fi; \ - $(DFU_PROGRAMMER) $(MCU) flash $(BUILD_DIR)/$(TARGET).hex;\ - fi; \ - $(DFU_PROGRAMMER) $(MCU) reset -endef - -dfu: $(BUILD_DIR)/$(TARGET).hex cpfirmware check-size - $(call EXEC_DFU) - -dfu-start: - $(DFU_PROGRAMMER) $(MCU) reset - $(DFU_PROGRAMMER) $(MCU) start - -dfu-ee: $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).eep - if $(DFU_PROGRAMMER) --version 2>&1 | $(GREP) -q 0.7 ; then\ - $(DFU_PROGRAMMER) $(MCU) flash --force --eeprom $(BUILD_DIR)/$(TARGET).eep;\ - else\ - $(DFU_PROGRAMMER) $(MCU) flash-eeprom $(BUILD_DIR)/$(TARGET).eep;\ - fi - $(DFU_PROGRAMMER) $(MCU) reset - -dfu-split-left: $(BUILD_DIR)/$(TARGET).hex cpfirmware check-size - $(call EXEC_DFU,eeprom-lefthand.eep) - -dfu-split-right: $(BUILD_DIR)/$(TARGET).hex cpfirmware check-size - $(call EXEC_DFU,eeprom-righthand.eep) - -AVRDUDE_PROGRAMMER ?= avrdude - -define EXEC_AVRDUDE - list_devices() { \ - if $(GREP) -q -s icrosoft /proc/version; then \ - wmic.exe path Win32_SerialPort get DeviceID 2>/dev/null | LANG=C perl -pne 's/COM(\d+)/COM.($$1-1)/e' | sed 's!COM!/dev/ttyS!' | xargs echo -n | sort; \ - elif [ "`uname`" = "FreeBSD" ]; then \ - ls /dev/tty* | grep -v '\.lock$$' | grep -v '\.init$$'; \ - else \ - ls /dev/tty*; \ - fi; \ - }; \ - USB= ;\ - printf "Waiting for USB serial port - reset your controller now (Ctrl+C to cancel)"; \ - TMP1=`mktemp`; \ - TMP2=`mktemp`; \ - list_devices > $$TMP1; \ - while [ -z "$$USB" ]; do \ - sleep $(BOOTLOADER_RETRY_TIME); \ - printf "."; \ - list_devices > $$TMP2; \ - USB=`comm -13 $$TMP1 $$TMP2 | $(GREP) -o '/dev/tty.*'`; \ - mv $$TMP2 $$TMP1; \ - done; \ - rm $$TMP1; \ - echo ""; \ - echo "Device $$USB has appeared; assuming it is the controller."; \ - if $(GREP) -q -s 'MINGW\|MSYS\|icrosoft' /proc/version; then \ - USB=`echo "$$USB" | LANG=C perl -pne 's/\/dev\/ttyS(\d+)/COM.($$1+1)/e'`; \ - echo "Remapped USB port to $$USB"; \ - sleep 1; \ - else \ - printf "Waiting for $$USB to become writable."; \ - while [ ! -w "$$USB" ]; do sleep $(BOOTLOADER_RETRY_TIME); printf "."; done; echo ""; \ - fi; \ - if [ -z "$(1)" ]; then \ - $(AVRDUDE_PROGRAMMER) -p $(MCU) -c avr109 -P $$USB -U flash:w:$(BUILD_DIR)/$(TARGET).hex; \ - else \ - $(AVRDUDE_PROGRAMMER) -p $(MCU) -c avr109 -P $$USB -U flash:w:$(BUILD_DIR)/$(TARGET).hex -U eeprom:w:$(QUANTUM_PATH)/split_common/$(1); \ - fi -endef - -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 - -avrdude-split-left: $(BUILD_DIR)/$(TARGET).hex check-size cpfirmware - $(call EXEC_AVRDUDE,eeprom-lefthand.eep) - -avrdude-split-right: $(BUILD_DIR)/$(TARGET).hex check-size cpfirmware - $(call EXEC_AVRDUDE,eeprom-righthand.eep) - -define EXEC_USBASP - $(AVRDUDE_PROGRAMMER) -p $(AVRDUDE_MCU) -c usbasp -U flash:w:$(BUILD_DIR)/$(TARGET).hex -endef - -usbasp: $(BUILD_DIR)/$(TARGET).hex check-size cpfirmware - $(call EXEC_USBASP) - -BOOTLOADHID_PROGRAMMER ?= bootloadHID - -define EXEC_BOOTLOADHID - # bootloadHid executable has no cross platform detect methods - # so keep running bootloadHid if the output contains "The specified device was not found" - until $(BOOTLOADHID_PROGRAMMER) -r $(BUILD_DIR)/$(TARGET).hex 2>&1 | tee /dev/stderr | grep -v "device was not found"; do\ - printf "$(MSG_BOOTLOADER_NOT_FOUND)" ;\ - sleep 5 ;\ - done -endef - -bootloadHID: $(BUILD_DIR)/$(TARGET).hex check-size cpfirmware - $(call EXEC_BOOTLOADHID) - -HID_BOOTLOADER_CLI ?= hid_bootloader_cli - -define EXEC_HID_LUFA - $(HID_BOOTLOADER_CLI) -mmcu=$(MCU) -w -v $(BUILD_DIR)/$(TARGET).hex -endef - -hid_bootloader: $(BUILD_DIR)/$(TARGET).hex check-size cpfirmware - $(call EXEC_HID_LUFA) # Convert hex to bin. bin: $(BUILD_DIR)/$(TARGET).hex @@ -335,22 +179,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 - -flash: $(BUILD_DIR)/$(TARGET).hex check-size cpfirmware -ifneq ($(strip $(PROGRAM_CMD)),) - $(PROGRAM_CMD) -else ifeq ($(strip $(BOOTLOADER)), caterina) - $(call EXEC_AVRDUDE) -else ifeq ($(strip $(BOOTLOADER)), halfkay) - $(call EXEC_TEENSY) -else ifeq (dfu,$(findstring dfu,$(BOOTLOADER))) - $(call EXEC_DFU) -else ifeq ($(strip $(BOOTLOADER)), USBasp) - $(call EXEC_USBASP) -else ifeq ($(strip $(BOOTLOADER)), bootloadHID) - $(call EXEC_BOOTLOADHID) -else ifeq ($(strip $(BOOTLOADER)), qmk-hid) - $(call EXEC_HID_LUFA) -else - $(PRINT_OK); $(SILENT) || printf "$(MSG_FLASH_BOOTLOADER)" -endif diff --git a/tmk_core/chibios.mk b/tmk_core/chibios.mk index 7eda360460..827f080e58 100644 --- a/tmk_core/chibios.mk +++ b/tmk_core/chibios.mk @@ -325,95 +325,8 @@ MCUFLAGS = -mcpu=$(MCU) DEBUG = gdb -DFU_ARGS ?= -ifneq ("$(SERIAL)","") - DFU_ARGS += -S $(SERIAL) -endif - -ST_LINK_ARGS ?= -ST_FLASH_ARGS ?= - # List any extra directories to look for libraries here. EXTRALIBDIRS = $(RULESPATH)/ld -DFU_UTIL ?= dfu-util -ST_LINK_CLI ?= st-link_cli -ST_FLASH ?= st-flash - -define EXEC_DFU_UTIL - if ! $(DFU_UTIL) -l | grep -q "Found DFU"; then \ - printf "$(MSG_BOOTLOADER_NOT_FOUND_QUICK_RETRY)" ;\ - sleep $(BOOTLOADER_RETRY_TIME) ;\ - while ! $(DFU_UTIL) -l | grep -q "Found DFU"; do \ - printf "." ;\ - sleep $(BOOTLOADER_RETRY_TIME) ;\ - done ;\ - printf "\n" ;\ - fi - $(DFU_UTIL) $(DFU_ARGS) -D $(BUILD_DIR)/$(TARGET).bin -endef - -dfu-util: $(BUILD_DIR)/$(TARGET).bin cpfirmware sizeafter - $(call EXEC_DFU_UTIL) - -# Legacy alias -dfu-util-wait: dfu-util - -# TODO: Remove once ARM has a way to configure EECONFIG_HANDEDNESS -# within the emulated eeprom via dfu-util or another tool -ifneq (,$(filter $(MAKECMDGOALS),dfu-util-split-left)) - OPT_DEFS += -DINIT_EE_HANDS_LEFT -endif - -ifneq (,$(filter $(MAKECMDGOALS),dfu-util-split-right)) - OPT_DEFS += -DINIT_EE_HANDS_RIGHT -endif - -dfu-util-split-left: dfu-util - -dfu-util-split-right: dfu-util - - -st-link-cli: $(BUILD_DIR)/$(TARGET).hex sizeafter - $(ST_LINK_CLI) $(ST_LINK_ARGS) -q -c SWD -p $(BUILD_DIR)/$(TARGET).hex -Rst - -st-flash: $(BUILD_DIR)/$(TARGET).hex sizeafter - $(ST_FLASH) $(ST_FLASH_ARGS) --reset --format ihex write $(BUILD_DIR)/$(TARGET).hex - - -# Autodetect teensy loader -ifndef TEENSY_LOADER_CLI - ifneq (, $(shell which teensy-loader-cli 2>/dev/null)) - TEENSY_LOADER_CLI ?= teensy-loader-cli - else - TEENSY_LOADER_CLI ?= teensy_loader_cli - endif -endif - -TEENSY_LOADER_CLI_MCU ?= $(MCU_LDSCRIPT) - -define EXEC_TEENSY - $(TEENSY_LOADER_CLI) -mmcu=$(TEENSY_LOADER_CLI_MCU) -w -v $(BUILD_DIR)/$(TARGET).hex -endef - -teensy: $(BUILD_DIR)/$(TARGET).hex cpfirmware sizeafter - $(call EXEC_TEENSY) - bin: $(BUILD_DIR)/$(TARGET).bin sizeafter $(COPY) $(BUILD_DIR)/$(TARGET).bin $(TARGET).bin; - - -flash: $(BUILD_DIR)/$(TARGET).bin cpfirmware sizeafter -ifneq ($(strip $(PROGRAM_CMD)),) - $(PROGRAM_CMD) -else ifeq ($(strip $(BOOTLOADER)),kiibohd) - $(call EXEC_DFU_UTIL) -else ifeq ($(strip $(MCU_FAMILY)),KINETIS) - $(call EXEC_TEENSY) -else ifeq ($(strip $(MCU_FAMILY)),MIMXRT1062) - $(call EXEC_TEENSY) -else ifeq ($(strip $(MCU_FAMILY)),STM32) - $(call EXEC_DFU_UTIL) -else - $(PRINT_OK); $(SILENT) || printf "$(MSG_FLASH_BOOTLOADER)" -endif -- cgit v1.2.3 From 2bc8215ce5f5c7473bb75de95cef4ab468d7e837 Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Mon, 16 Aug 2021 17:28:12 +0100 Subject: Unify behaviour of wait on AVR (#14025) --- tmk_core/common/avr/_wait.h | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'tmk_core') diff --git a/tmk_core/common/avr/_wait.h b/tmk_core/common/avr/_wait.h index 56eb316faf..ae1a25131a 100644 --- a/tmk_core/common/avr/_wait.h +++ b/tmk_core/common/avr/_wait.h @@ -17,8 +17,26 @@ #include -#define wait_ms(ms) _delay_ms(ms) -#define wait_us(us) _delay_us(us) +#define wait_ms(ms) \ + do { \ + if (__builtin_constant_p(ms)) { \ + _delay_ms(ms); \ + } else { \ + for (uint16_t i = ms; i > 0; i--) { \ + _delay_ms(1); \ + } \ + } \ + } while (0) +#define wait_us(us) \ + do { \ + if (__builtin_constant_p(us)) { \ + _delay_us(us); \ + } else { \ + for (uint16_t i = us; i > 0; i--) { \ + _delay_us(1); \ + } \ + } \ + } while (0) /* The AVR series GPIOs have a one clock read delay for changes in the digital input signal. * But here's more margin to make it two clocks. */ -- cgit v1.2.3 From 37496f4b6047248c25195e13e0f90593dc492fff Mon Sep 17 00:00:00 2001 From: Ryan Date: Wed, 18 Aug 2021 04:23:22 +1000 Subject: Add alternate ldscript for STM32duino (F103xB) (#12914) * Add alternate ldscript for STM32duino (F103xB) * Refactor out common ldscript stuff * Move ldscripts into stm32duino board dir, add search path to ldflags--- .../ld/STM32F103x8_stm32duino_bootloader.ld | 22 ++++++ .../ld/STM32F103xB_stm32duino_bootloader.ld | 22 ++++++ .../ld/stm32duino_bootloader_common.ld | 85 ++++++++++++++++++++++ .../common/ld/STM32F103x8_stm32duino_bootloader.ld | 85 ---------------------- tmk_core/chibios.mk | 1 + 5 files changed, 130 insertions(+), 85 deletions(-) create mode 100644 platforms/chibios/STM32_F103_STM32DUINO/ld/STM32F103x8_stm32duino_bootloader.ld create mode 100644 platforms/chibios/STM32_F103_STM32DUINO/ld/STM32F103xB_stm32duino_bootloader.ld create mode 100644 platforms/chibios/STM32_F103_STM32DUINO/ld/stm32duino_bootloader_common.ld delete mode 100644 platforms/chibios/common/ld/STM32F103x8_stm32duino_bootloader.ld (limited to 'tmk_core') diff --git a/platforms/chibios/STM32_F103_STM32DUINO/ld/STM32F103x8_stm32duino_bootloader.ld b/platforms/chibios/STM32_F103_STM32DUINO/ld/STM32F103x8_stm32duino_bootloader.ld new file mode 100644 index 0000000000..a4bd566b59 --- /dev/null +++ b/platforms/chibios/STM32_F103_STM32DUINO/ld/STM32F103x8_stm32duino_bootloader.ld @@ -0,0 +1,22 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + 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 License 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. +*/ + +/* + * STM32F103x8 memory setup for use with the STM32Duino bootloader. + */ +f103_flash_size = 64k; + +INCLUDE stm32duino_bootloader_common.ld diff --git a/platforms/chibios/STM32_F103_STM32DUINO/ld/STM32F103xB_stm32duino_bootloader.ld b/platforms/chibios/STM32_F103_STM32DUINO/ld/STM32F103xB_stm32duino_bootloader.ld new file mode 100644 index 0000000000..dc47400dc5 --- /dev/null +++ b/platforms/chibios/STM32_F103_STM32DUINO/ld/STM32F103xB_stm32duino_bootloader.ld @@ -0,0 +1,22 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + 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 License 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. +*/ + +/* + * STM32F103xB memory setup for use with the STM32Duino bootloader. + */ +f103_flash_size = 128k; + +INCLUDE stm32duino_bootloader_common.ld diff --git a/platforms/chibios/STM32_F103_STM32DUINO/ld/stm32duino_bootloader_common.ld b/platforms/chibios/STM32_F103_STM32DUINO/ld/stm32duino_bootloader_common.ld new file mode 100644 index 0000000000..76cd3153be --- /dev/null +++ b/platforms/chibios/STM32_F103_STM32DUINO/ld/stm32duino_bootloader_common.ld @@ -0,0 +1,85 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + 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 License 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. +*/ + +/* + * STM32Duino bootloader common memory setup. + */ +MEMORY +{ + flash0 : org = 0x08002000, len = f103_flash_size - 0x2000 + flash1 : org = 0x00000000, len = 0 + flash2 : org = 0x00000000, len = 0 + flash3 : org = 0x00000000, len = 0 + flash4 : org = 0x00000000, len = 0 + flash5 : org = 0x00000000, len = 0 + flash6 : org = 0x00000000, len = 0 + flash7 : org = 0x00000000, len = 0 + ram0 : org = 0x20000000, len = 20k + ram1 : org = 0x00000000, len = 0 + ram2 : org = 0x00000000, len = 0 + ram3 : org = 0x00000000, len = 0 + ram4 : org = 0x00000000, len = 0 + ram5 : org = 0x00000000, len = 0 + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash0); +REGION_ALIAS("VECTORS_FLASH_LMA", flash0); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash0); +REGION_ALIAS("XTORS_FLASH_LMA", flash0); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash0); +REGION_ALIAS("TEXT_FLASH_LMA", flash0); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash0); +REGION_ALIAS("RODATA_FLASH_LMA", flash0); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash0); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash0); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash0); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* Generic rules inclusion.*/ +INCLUDE rules.ld diff --git a/platforms/chibios/common/ld/STM32F103x8_stm32duino_bootloader.ld b/platforms/chibios/common/ld/STM32F103x8_stm32duino_bootloader.ld deleted file mode 100644 index bb852422a3..0000000000 --- a/platforms/chibios/common/ld/STM32F103x8_stm32duino_bootloader.ld +++ /dev/null @@ -1,85 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - 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 License 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. -*/ - -/* - * ST32F103xB memory setup for use with the maplemini bootloader. - */ -MEMORY -{ - flash0 : org = 0x08002000, len = 64k - 0x2000 - flash1 : org = 0x00000000, len = 0 - flash2 : org = 0x00000000, len = 0 - flash3 : org = 0x00000000, len = 0 - flash4 : org = 0x00000000, len = 0 - flash5 : org = 0x00000000, len = 0 - flash6 : org = 0x00000000, len = 0 - flash7 : org = 0x00000000, len = 0 - ram0 : org = 0x20000000, len = 20k - ram1 : org = 0x00000000, len = 0 - ram2 : org = 0x00000000, len = 0 - ram3 : org = 0x00000000, len = 0 - ram4 : org = 0x00000000, len = 0 - ram5 : org = 0x00000000, len = 0 - ram6 : org = 0x00000000, len = 0 - ram7 : org = 0x00000000, len = 0 -} - -/* For each data/text section two region are defined, a virtual region - and a load region (_LMA suffix).*/ - -/* Flash region to be used for exception vectors.*/ -REGION_ALIAS("VECTORS_FLASH", flash0); -REGION_ALIAS("VECTORS_FLASH_LMA", flash0); - -/* Flash region to be used for constructors and destructors.*/ -REGION_ALIAS("XTORS_FLASH", flash0); -REGION_ALIAS("XTORS_FLASH_LMA", flash0); - -/* Flash region to be used for code text.*/ -REGION_ALIAS("TEXT_FLASH", flash0); -REGION_ALIAS("TEXT_FLASH_LMA", flash0); - -/* Flash region to be used for read only data.*/ -REGION_ALIAS("RODATA_FLASH", flash0); -REGION_ALIAS("RODATA_FLASH_LMA", flash0); - -/* Flash region to be used for various.*/ -REGION_ALIAS("VARIOUS_FLASH", flash0); -REGION_ALIAS("VARIOUS_FLASH_LMA", flash0); - -/* Flash region to be used for RAM(n) initialization data.*/ -REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0); - -/* RAM region to be used for Main stack. This stack accommodates the processing - of all exceptions and interrupts.*/ -REGION_ALIAS("MAIN_STACK_RAM", ram0); - -/* RAM region to be used for the process stack. This is the stack used by - the main() function.*/ -REGION_ALIAS("PROCESS_STACK_RAM", ram0); - -/* RAM region to be used for data segment.*/ -REGION_ALIAS("DATA_RAM", ram0); -REGION_ALIAS("DATA_RAM_LMA", flash0); - -/* RAM region to be used for BSS segment.*/ -REGION_ALIAS("BSS_RAM", ram0); - -/* RAM region to be used for the default heap.*/ -REGION_ALIAS("HEAP_RAM", ram0); - -/* Generic rules inclusion.*/ -INCLUDE rules.ld diff --git a/tmk_core/chibios.mk b/tmk_core/chibios.mk index 827f080e58..cbd9fff692 100644 --- a/tmk_core/chibios.mk +++ b/tmk_core/chibios.mk @@ -191,6 +191,7 @@ else ifneq ("$(wildcard $(KEYBOARD_PATH_2)/ld/$(MCU_LDSCRIPT).ld)","") else ifneq ("$(wildcard $(KEYBOARD_PATH_1)/ld/$(MCU_LDSCRIPT).ld)","") LDSCRIPT = $(KEYBOARD_PATH_1)/ld/$(MCU_LDSCRIPT).ld else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/$(BOARD)/ld/$(MCU_LDSCRIPT).ld)","") + LDFLAGS += -L$(TOP_DIR)/platforms/chibios/$(BOARD)/ld LDSCRIPT = $(TOP_DIR)/platforms/chibios/$(BOARD)/ld/$(MCU_LDSCRIPT).ld else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/common/ld/$(MCU_LDSCRIPT).ld)","") LDSCRIPT = $(TOP_DIR)/platforms/chibios/common/ld/$(MCU_LDSCRIPT).ld -- cgit v1.2.3 From 4b96d5876eb01dfd8063949a2e5cb4b70e01786d Mon Sep 17 00:00:00 2001 From: 50an6xy06r6n Date: Tue, 17 Aug 2021 11:44:19 -0700 Subject: Fix Indicator LED issues (#12097) --- keyboards/massdrop/ctrl/config_led.c | 5 ++--- tmk_core/protocol/arm_atsam/md_rgb_matrix.c | 4 ++-- tmk_core/protocol/arm_atsam/md_rgb_matrix.h | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) (limited to 'tmk_core') diff --git a/keyboards/massdrop/ctrl/config_led.c b/keyboards/massdrop/ctrl/config_led.c index 27ddb5c388..bd708c2cb8 100644 --- a/keyboards/massdrop/ctrl/config_led.c +++ b/keyboards/massdrop/ctrl/config_led.c @@ -73,9 +73,8 @@ led_config_t g_led_config = { { #ifdef USB_LED_INDICATOR_ENABLE -void rgb_matrix_indicators_kb(void) -{ - md_rgb_matrix_indicators(); +void rgb_matrix_indicators_advanced_kb(uint8_t led_min, uint8_t led_max) { + md_rgb_matrix_indicators_advanced(led_min, led_max); } #endif // USB_LED_INDICATOR_ENABLE diff --git a/tmk_core/protocol/arm_atsam/md_rgb_matrix.c b/tmk_core/protocol/arm_atsam/md_rgb_matrix.c index 609ae047e6..98967aac88 100644 --- a/tmk_core/protocol/arm_atsam/md_rgb_matrix.c +++ b/tmk_core/protocol/arm_atsam/md_rgb_matrix.c @@ -291,10 +291,10 @@ static void flush(void) { i2c_led_q_run(); } -void md_rgb_matrix_indicators(void) { +void md_rgb_matrix_indicators_advanced(uint8_t led_min, uint8_t led_max) { uint8_t kbled = keyboard_leds(); if (kbled && rgb_matrix_config.enable) { - for (uint8_t i = 0; i < ISSI3733_LED_COUNT; i++) { + for (uint8_t i = led_min; i < led_max; i++) { if ( # if USB_LED_NUM_LOCK_SCANCODE != 255 (led_map[i].scan == USB_LED_NUM_LOCK_SCANCODE && (kbled & (1 << USB_LED_NUM_LOCK))) || diff --git a/tmk_core/protocol/arm_atsam/md_rgb_matrix.h b/tmk_core/protocol/arm_atsam/md_rgb_matrix.h index 322b0f99d1..76ccaa678b 100644 --- a/tmk_core/protocol/arm_atsam/md_rgb_matrix.h +++ b/tmk_core/protocol/arm_atsam/md_rgb_matrix.h @@ -86,7 +86,7 @@ extern uint8_t gcr_actual_last; void gcr_compute(void); -void md_rgb_matrix_indicators(void); +void md_rgb_matrix_indicators_advanced(uint8_t led_min, uint8_t led_max); /*------------------------- Legacy Lighting Support ------------------------*/ -- cgit v1.2.3 From 75b49aff56436c57a424e622c91f6d80e1d0ecc2 Mon Sep 17 00:00:00 2001 From: a-chol Date: Tue, 17 Aug 2021 20:52:44 +0200 Subject: Digitizer HID interface : absolute coordinates for mouse cursor (#12851) * Add digitizer HID interface for setting the mouse cursor position at absolute screen coordinates. Tested on Pro Micro, Proton C and Blackpill. * Update docs/feature_digitizer.md Co-authored-by: Ryan * Update tmk_core/protocol/usb_descriptor.c Co-authored-by: Ryan * Add missing copyrights Add V-USB support * Add support for digitizer dedicated endpoint for lufa and chibios. Fix formatting issues Move digitizer_task definition to the feature's base implementation file * Run cformat on modified files * Change digitizer report usage to Digitizer instead of Pen to avoid pointer disappearing on Windows. * Update tmk_core/protocol/vusb/vusb.c Co-authored-by: Ryan * Run cformat from docker image * Remove send_digitizer from host_driver_t and instead rely on the declaration being the interface to the implementation in each HW-specific usb implementation. * Fix build : send_digitizer shouldn't be static in vusb and add weak-linkage implementation for tests without usb implementation * Change digitizer user interface to match pointing device's * Update documentation with new API Co-authored-by: a-chol Co-authored-by: Ryan --- common_features.mk | 5 + docs/_summary.md | 1 + docs/feature_digitizer.md | 35 +++++++ .../handwired/onekey/keymaps/digitizer/keymap.c | 38 ++++++++ .../handwired/onekey/keymaps/digitizer/rules.mk | 1 + quantum/digitizer.c | 34 +++++++ quantum/digitizer.h | 41 +++++++++ tmk_core/common.mk | 13 +++ tmk_core/common/host.c | 19 ++++ tmk_core/common/host_driver.h | 2 + tmk_core/common/keyboard.c | 7 ++ tmk_core/common/report.h | 14 ++- tmk_core/protocol/chibios/main.c | 1 + tmk_core/protocol/chibios/usb_main.c | 28 ++++++ tmk_core/protocol/lufa/lufa.c | 26 +++++- tmk_core/protocol/usb_descriptor.c | 101 +++++++++++++++++++++ tmk_core/protocol/usb_descriptor.h | 27 +++++- tmk_core/protocol/vusb/vusb.c | 48 +++++++++- 18 files changed, 435 insertions(+), 6 deletions(-) create mode 100644 docs/feature_digitizer.md create mode 100644 keyboards/handwired/onekey/keymaps/digitizer/keymap.c create mode 100644 keyboards/handwired/onekey/keymaps/digitizer/rules.mk create mode 100644 quantum/digitizer.c create mode 100644 quantum/digitizer.h (limited to 'tmk_core') diff --git a/common_features.mk b/common_features.mk index e442222eae..493aab6353 100644 --- a/common_features.mk +++ b/common_features.mk @@ -695,6 +695,11 @@ ifeq ($(strip $(JOYSTICK_ENABLE)), digital) OPT_DEFS += -DDIGITAL_JOYSTICK_ENABLE endif +DIGITIZER_ENABLE ?= no +ifneq ($(strip $(DIGITIZER_ENABLE)), no) + SRC += $(QUANTUM_DIR)/digitizer.c +endif + USBPD_ENABLE ?= no VALID_USBPD_DRIVER_TYPES = custom vendor USBPD_DRIVER ?= vendor diff --git a/docs/_summary.md b/docs/_summary.md index 48115cef46..2f6309e41d 100644 --- a/docs/_summary.md +++ b/docs/_summary.md @@ -108,6 +108,7 @@ * [Bluetooth](feature_bluetooth.md) * [Bootmagic Lite](feature_bootmagic.md) * [Custom Matrix](custom_matrix.md) + * [Digitizer](feature_digitizer.md) * [DIP Switch](feature_dip_switch.md) * [Encoders](feature_encoders.md) * [Haptic Feedback](feature_haptic_feedback.md) diff --git a/docs/feature_digitizer.md b/docs/feature_digitizer.md new file mode 100644 index 0000000000..9b6aeddbaa --- /dev/null +++ b/docs/feature_digitizer.md @@ -0,0 +1,35 @@ +## Digitizer + +The digitizer HID interface allows setting the mouse cursor position at absolute coordinates, unlike the Pointing Device feature that applies relative displacements. + +To enable the digitizer interface, add the following line to your rules.mk: + +```makefile +DIGITIZER_ENABLE = yes +``` + +In order to change the mouse cursor position from your keymap.c file, include the digitizer header : + +```c +#include "digitizer.h" +``` + +This gives you access to the `digitizer` structure which members allow you to change the cursor position. + +The coordinates are normalized, meaning there value must be set between 0 and 1. For the `x` coordinate, the value `0` is the leftmost position, whereas the value `1` is the rightmost position. +For the `y` coordinate, `0` is at the top and `1` at the bottom. + +Here is an example setting the cursor in the middle of the screen: + +```c +digitizer_t digitizer; +digitizer.x = 0.5; +digitizer.y = 0.5; +digitizer.tipswitch = 0; +digitizer.inrange = 1; +digitizer_set_report(digitizer); +``` + +The `tipswitch` member triggers what equates to a click when set to `1`. The `inrange` member is required for the change in coordinates to be taken. It can then be set to `0` in a new report to signal the end of the digitizer interaction, but it is not strictly required. + +Once all members are set to the desired value, the `status` member needs its bitmask `DZ_UPDATED` to be set so the report is sent during the next main loop iteration. diff --git a/keyboards/handwired/onekey/keymaps/digitizer/keymap.c b/keyboards/handwired/onekey/keymaps/digitizer/keymap.c new file mode 100644 index 0000000000..6b304e86fe --- /dev/null +++ b/keyboards/handwired/onekey/keymaps/digitizer/keymap.c @@ -0,0 +1,38 @@ + /* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include QMK_KEYBOARD_H + +#include "digitizer.h" + +#include "math.h" + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {LAYOUT_ortho_1x1(KC_A)}; + +uint32_t timer = 0; + +void matrix_scan_user() { + if (timer_elapsed32(timer) < 200) { + return; + } + + timer = timer_read32(); + digitizer_t digitizer; + digitizer.x = 0.5 - 0.2 * cos(timer_read() / 250. / 6.28); + digitizer.y = 0.5 - 0.2 * sin(timer_read() / 250. / 6.28); + digitizer.tipswitch = 0; + digitizer.inrange = 1; + digitizer_set_report(digitizer); +} diff --git a/keyboards/handwired/onekey/keymaps/digitizer/rules.mk b/keyboards/handwired/onekey/keymaps/digitizer/rules.mk new file mode 100644 index 0000000000..ea9f9bd9ac --- /dev/null +++ b/keyboards/handwired/onekey/keymaps/digitizer/rules.mk @@ -0,0 +1 @@ +DIGITIZER_ENABLE = yes \ No newline at end of file diff --git a/quantum/digitizer.c b/quantum/digitizer.c new file mode 100644 index 0000000000..e299867429 --- /dev/null +++ b/quantum/digitizer.c @@ -0,0 +1,34 @@ +/* Copyright 2021 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "digitizer.h" + +digitizer_t digitizerReport = {.tipswitch = 0, .inrange = 0, .id = 0, .x = 0, .y = 0, .status = DZ_INITIALIZED}; + +__attribute__((weak)) void digitizer_send(void) { + if (digitizerReport.status & DZ_UPDATED) { + host_digitizer_send(&digitizerReport); + digitizerReport.status &= ~DZ_UPDATED; + } +} + +__attribute__((weak)) void digitizer_task(void) { digitizer_send(); } + +digitizer_t digitizer_get_report(void) { return digitizerReport; } + +void digitizer_set_report(digitizer_t newDigitizerReport) { + digitizerReport = newDigitizerReport; + digitizerReport.status |= DZ_UPDATED; +} \ No newline at end of file diff --git a/quantum/digitizer.h b/quantum/digitizer.h new file mode 100644 index 0000000000..cef551567e --- /dev/null +++ b/quantum/digitizer.h @@ -0,0 +1,41 @@ +/* Copyright 2021 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#include "quantum.h" + +#include + +enum digitizer_status { DZ_INITIALIZED = 1, DZ_UPDATED = 2 }; + +typedef struct { + int8_t tipswitch; + int8_t inrange; + uint8_t id; + float x; + float y; + uint8_t status : 2; +} digitizer_t; + +extern digitizer_t digitizer; + +digitizer_t digitizer_get_report(void); + +void digitizer_set_report(digitizer_t newDigitizerReport); + +void digitizer_task(void); + +void host_digitizer_send(digitizer_t *digitizer); diff --git a/tmk_core/common.mk b/tmk_core/common.mk index 6c8cf69356..fa907b47b8 100644 --- a/tmk_core/common.mk +++ b/tmk_core/common.mk @@ -106,6 +106,19 @@ ifeq ($(strip $(NO_USB_STARTUP_CHECK)), yes) TMK_COMMON_DEFS += -DNO_USB_STARTUP_CHECK endif +ifeq ($(strip $(DIGITIZER_SHARED_EP)), yes) + TMK_COMMON_DEFS += -DDIGITIZER_SHARED_EP + SHARED_EP_ENABLE = yes +endif + +ifeq ($(strip $(DIGITIZER_ENABLE)), yes) + TMK_COMMON_DEFS += -DDIGITIZER_ENABLE + ifeq ($(strip $(SHARED_EP_ENABLE)), yes) + TMK_COMMON_DEFS += -DDIGITIZER_SHARED_EP + SHARED_EP_ENABLE = yes + endif +endif + ifeq ($(strip $(SHARED_EP_ENABLE)), yes) TMK_COMMON_DEFS += -DSHARED_EP_ENABLE endif diff --git a/tmk_core/common/host.c b/tmk_core/common/host.c index a8b391e893..f0c396b189 100644 --- a/tmk_core/common/host.c +++ b/tmk_core/common/host.c @@ -22,6 +22,7 @@ along with this program. If not, see . #include "host.h" #include "util.h" #include "debug.h" +#include "digitizer.h" #ifdef NKRO_ENABLE # include "keycode_config.h" @@ -103,6 +104,24 @@ void host_consumer_send(uint16_t report) { (*driver->send_consumer)(report); } +void host_digitizer_send(digitizer_t *digitizer) { + if (!driver) return; + + report_digitizer_t report = { +#ifdef DIGITIZER_SHARED_EP + .report_id = REPORT_ID_DIGITIZER, +#endif + .tip = digitizer->tipswitch & 0x1, + .inrange = digitizer->inrange & 0x1, + .x = (uint16_t)(digitizer->x * 0x7FFF), + .y = (uint16_t)(digitizer->y * 0x7FFF), + }; + + send_digitizer(&report); +} + +__attribute__((weak)) void send_digitizer(report_digitizer_t *report) {} + uint16_t host_last_system_report(void) { return last_system_report; } uint16_t host_last_consumer_report(void) { return last_consumer_report; } diff --git a/tmk_core/common/host_driver.h b/tmk_core/common/host_driver.h index f34a220530..2aebca043d 100644 --- a/tmk_core/common/host_driver.h +++ b/tmk_core/common/host_driver.h @@ -30,3 +30,5 @@ typedef struct { void (*send_system)(uint16_t); void (*send_consumer)(uint16_t); } host_driver_t; + +void send_digitizer(report_digitizer_t *report); \ No newline at end of file diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c index 28fa97bc8f..fcc51973fd 100644 --- a/tmk_core/common/keyboard.c +++ b/tmk_core/common/keyboard.c @@ -106,6 +106,9 @@ along with this program. If not, see . #if defined(CRC_ENABLE) # include "crc.h" #endif +#ifdef DIGITIZER_ENABLE +# include "digitizer.h" +#endif static uint32_t last_input_modification_time = 0; uint32_t last_input_activity_time(void) { return last_input_modification_time; } @@ -537,6 +540,10 @@ MATRIX_LOOP_END: joystick_task(); #endif +#ifdef DIGITIZER_ENABLE + digitizer_task(); +#endif + // update LED if (led_status != host_keyboard_leds()) { led_status = host_keyboard_leds(); diff --git a/tmk_core/common/report.h b/tmk_core/common/report.h index db6370657d..f2223e8063 100644 --- a/tmk_core/common/report.h +++ b/tmk_core/common/report.h @@ -30,7 +30,8 @@ enum hid_report_ids { REPORT_ID_SYSTEM, REPORT_ID_CONSUMER, REPORT_ID_NKRO, - REPORT_ID_JOYSTICK + REPORT_ID_JOYSTICK, + REPORT_ID_DIGITIZER }; /* Mouse buttons */ @@ -205,6 +206,17 @@ typedef struct { int8_t h; } __attribute__((packed)) report_mouse_t; +typedef struct { +#ifdef DIGITIZER_SHARED_EP + uint8_t report_id; +#endif + uint8_t tip : 1; + uint8_t inrange : 1; + uint8_t pad2 : 6; + uint16_t x; + uint16_t y; +} __attribute__((packed)) report_digitizer_t; + typedef struct { #if JOYSTICK_AXES_COUNT > 0 # if JOYSTICK_AXES_RESOLUTION > 8 diff --git a/tmk_core/protocol/chibios/main.c b/tmk_core/protocol/chibios/main.c index 199741594a..e41d6ff195 100644 --- a/tmk_core/protocol/chibios/main.c +++ b/tmk_core/protocol/chibios/main.c @@ -65,6 +65,7 @@ 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); +void send_digitizer(report_digitizer_t *report); /* host struct */ host_driver_t chibios_driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer}; diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c index e5edd74dcb..cc282e6a9b 100644 --- a/tmk_core/protocol/chibios/usb_main.c +++ b/tmk_core/protocol/chibios/usb_main.c @@ -315,6 +315,9 @@ typedef struct { #endif #ifdef JOYSTICK_ENABLE usb_driver_config_t joystick_driver; +#endif +#if defined(DIGITIZER_ENABLE) && !defined(DIGITIZER_SHARED_EP) + usb_driver_config_t digitizer_driver; #endif }; usb_driver_config_t array[0]; @@ -360,6 +363,14 @@ static usb_driver_configs_t drivers = { # define JOYSTICK_OUT_MODE USB_EP_MODE_TYPE_BULK .joystick_driver = QMK_USB_DRIVER_CONFIG(JOYSTICK, 0, false), #endif + +#if defined(DIGITIZER_ENABLE) && !defined(DIGITIZER_SHARED_EP) +# define DIGITIZER_IN_CAPACITY 4 +# define DIGITIZER_OUT_CAPACITY 4 +# define DIGITIZER_IN_MODE USB_EP_MODE_TYPE_BULK +# define DIGITIZER_OUT_MODE USB_EP_MODE_TYPE_BULK + .digitizer_driver = QMK_USB_DRIVER_CONFIG(DIGITIZER, 0, false), +#endif }; #define NUM_USB_DRIVERS (sizeof(drivers) / sizeof(usb_driver_config_t)) @@ -930,6 +941,23 @@ void send_consumer(uint16_t data) { #endif } +void send_digitizer(report_digitizer_t *report) { +#ifdef DIGITIZER_ENABLE +# ifdef DIGITIZER_SHARED_EP + osalSysLock(); + if (usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) { + osalSysUnlock(); + return; + } + + usbStartTransmitI(&USB_DRIVER, DIGITIZER_IN_EPNUM, (uint8_t *)report, sizeof(report_digitizer_t)); + osalSysUnlock(); +# else + chnWrite(&drivers.digitizer_driver.driver, (uint8_t *)report, sizeof(report_digitizer_t)); +# endif +#endif +} + /* --------------------------------------------------------- * Console functions * --------------------------------------------------------- diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c index 4ac079e168..8ddb8b1c4b 100644 --- a/tmk_core/protocol/lufa/lufa.c +++ b/tmk_core/protocol/lufa/lufa.c @@ -142,9 +142,7 @@ static void send_keyboard(report_keyboard_t *report); static void send_mouse(report_mouse_t *report); static void send_system(uint16_t data); static void send_consumer(uint16_t data); -host_driver_t lufa_driver = { - keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer, -}; +host_driver_t lufa_driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer}; #ifdef VIRTSER_ENABLE // clang-format off @@ -525,6 +523,11 @@ void EVENT_USB_Device_ConfigurationChanged(void) { /* Setup joystick endpoint */ ConfigSuccess &= Endpoint_ConfigureEndpoint((JOYSTICK_IN_EPNUM | ENDPOINT_DIR_IN), EP_TYPE_INTERRUPT, JOYSTICK_EPSIZE, 1); #endif + +#if defined(DIGITIZER_ENABLE) && !defined(DIGITIZER_SHARED_EP) + /* Setup digitizer endpoint */ + ConfigSuccess &= Endpoint_ConfigureEndpoint((DIGITIZER_IN_EPNUM | ENDPOINT_DIR_IN), EP_TYPE_INTERRUPT, DIGITIZER_EPSIZE, 1); +#endif } /* FIXME: Expose this table in the docs somehow @@ -983,6 +986,23 @@ void virtser_send(const uint8_t byte) { } #endif +void send_digitizer(report_digitizer_t *report) { +#ifdef DIGITIZER_ENABLE + uint8_t timeout = 255; + + if (USB_DeviceState != DEVICE_STATE_Configured) return; + + Endpoint_SelectEndpoint(DIGITIZER_IN_EPNUM); + + /* Check if write ready for a polling interval around 10ms */ + while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40); + if (!Endpoint_IsReadWriteAllowed()) return; + + Endpoint_Write_Stream_LE(report, sizeof(report_digitizer_t), NULL); + Endpoint_ClearIN(); +#endif +} + /******************************************************************************* * main ******************************************************************************/ diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c index 7a4a790315..099964ae56 100644 --- a/tmk_core/protocol/usb_descriptor.c +++ b/tmk_core/protocol/usb_descriptor.c @@ -158,6 +158,53 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = { # endif #endif +#ifdef DIGITIZER_ENABLE +# ifndef DIGITIZER_SHARED_EP +const USB_Descriptor_HIDReport_Datatype_t PROGMEM DigitizerReport[] = { +# elif !defined(SHARED_REPORT_STARTED) +const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = { +# define SHARED_REPORT_STARTED +# endif + HID_RI_USAGE_PAGE(8, 0x0D), // Digitizers + HID_RI_USAGE(8, 0x01), // Digitizer + HID_RI_COLLECTION(8, 0x01), // Application +# ifdef DIGITIZER_SHARED_EP + HID_RI_REPORT_ID(8, REPORT_ID_DIGITIZER), +# endif + HID_RI_USAGE(8, 0x20), // Stylus + HID_RI_COLLECTION(8, 0x00), // Physical + // Tip Switch (1 bit) + HID_RI_USAGE(8, 0x42), // Tip Switch + HID_RI_LOGICAL_MINIMUM(8, 0x00), + HID_RI_LOGICAL_MAXIMUM(8, 0x01), + HID_RI_REPORT_SIZE(8, 0x01), + HID_RI_REPORT_COUNT(8, 0x01), + HID_RI_INPUT(8, HID_IOF_VARIABLE), + // In Range (1 bit) + HID_RI_USAGE(8, 0x32), // In Range + HID_RI_INPUT(8, HID_IOF_VARIABLE), + // Padding (6 bits) + HID_RI_REPORT_COUNT(8, 0x06), + HID_RI_INPUT(8, HID_IOF_CONSTANT | HID_IOF_VARIABLE), + + // X/Y Position (4 bytes) + HID_RI_USAGE_PAGE(8, 0x01), // Generic Desktop + HID_RI_LOGICAL_MAXIMUM(16, 0x7FFF), + HID_RI_REPORT_SIZE(8, 0x10), + HID_RI_REPORT_COUNT(8, 0x01), + HID_RI_UNIT(8, 0x33), // Inch, English Linear + HID_RI_UNIT_EXPONENT(8, 0x0E), // -2 + HID_RI_USAGE(8, 0x30), // X + HID_RI_INPUT(8, HID_IOF_VARIABLE), + HID_RI_USAGE(8, 0x31), // Y + HID_RI_INPUT(8, HID_IOF_VARIABLE), + HID_RI_END_COLLECTION(0), + HID_RI_END_COLLECTION(0), +# ifndef DIGITIZER_SHARED_EP +}; +# endif +#endif + #if defined(SHARED_EP_ENABLE) && !defined(SHARED_REPORT_STARTED) const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = { #endif @@ -227,6 +274,7 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = { HID_RI_OUTPUT(8, HID_IOF_CONSTANT), HID_RI_END_COLLECTION(0), #endif + #ifdef SHARED_EP_ENABLE }; #endif @@ -921,6 +969,46 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = { .PollingIntervalMS = USB_POLLING_INTERVAL_MS } #endif + +#if defined(DIGITIZER_ENABLE) && !defined(DIGITIZER_SHARED_EP) + /* + * Digitizer + */ + .Digitizer_Interface = { + .Header = { + .Size = sizeof(USB_Descriptor_Interface_t), + .Type = DTYPE_Interface + }, + .InterfaceNumber = DIGITIZER_INTERFACE, + .AlternateSetting = 0x00, + .TotalEndpoints = 1, + .Class = HID_CSCP_HIDClass, + .SubClass = HID_CSCP_NonBootSubclass, + .Protocol = HID_CSCP_NonBootProtocol, + .InterfaceStrIndex = NO_DESCRIPTOR + }, + .Digitizer_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(DigitizerReport) + }, + .Digitizer_INEndpoint = { + .Header = { + .Size = sizeof(USB_Descriptor_Endpoint_t), + .Type = DTYPE_Endpoint + }, + .EndpointAddress = (ENDPOINT_DIR_IN | DIGITIZER_IN_EPNUM), + .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), + .EndpointSize = DIGITIZER_EPSIZE, + .PollingIntervalMS = USB_POLLING_INTERVAL_MS + }, +#endif }; /* @@ -1059,6 +1147,13 @@ uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const Size = sizeof(USB_HID_Descriptor_HID_t); break; #endif +#if defined(DIGITIZER_ENABLE) && !defined(DIGITIZER_SHARED_EP) + case DIGITIZER_INTERFACE: + Address = &ConfigurationDescriptor.Digitizer_HID; + Size = sizeof(USB_HID_Descriptor_HID_t); + + break; +#endif } break; @@ -1108,6 +1203,12 @@ uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const Address = &JoystickReport; Size = sizeof(JoystickReport); break; +#endif +#if defined(DIGITIZER_ENABLE) && !defined(DIGITIZER_SHARED_EP) + case DIGITIZER_INTERFACE: + Address = &DigitizerReport; + Size = sizeof(DigitizerReport); + break; #endif } diff --git a/tmk_core/protocol/usb_descriptor.h b/tmk_core/protocol/usb_descriptor.h index 867e549b4f..0f0c78f66c 100644 --- a/tmk_core/protocol/usb_descriptor.h +++ b/tmk_core/protocol/usb_descriptor.h @@ -135,6 +135,13 @@ typedef struct { USB_HID_Descriptor_HID_t Joystick_HID; USB_Descriptor_Endpoint_t Joystick_INEndpoint; #endif + +#if defined(DIGITIZER_ENABLE) && !defined(DIGITIZER_SHARED_EP) + // Digitizer HID Interface + USB_Descriptor_Interface_t Digitizer_Interface; + USB_HID_Descriptor_HID_t Digitizer_HID; + USB_Descriptor_Endpoint_t Digitizer_INEndpoint; +#endif } USB_Descriptor_Configuration_t; /* @@ -180,6 +187,10 @@ enum usb_interfaces { #if defined(JOYSTICK_ENABLE) JOYSTICK_INTERFACE, #endif + +#if defined(DIGITIZER_ENABLE) && !defined(DIGITIZER_SHARED_EP) + DIGITIZER_INTERFACE, +#endif TOTAL_INTERFACES }; @@ -226,7 +237,7 @@ enum usb_endpoints { # if STM32_USB_USE_OTG1 # define CONSOLE_OUT_EPNUM CONSOLE_IN_EPNUM # else - CONSOLE_OUT_EPNUM = NEXT_EPNUM, + CONSOLE_OUT_EPNUM = NEXT_EPNUM, # endif # else # define CONSOLE_OUT_EPNUM CONSOLE_IN_EPNUM @@ -259,6 +270,19 @@ enum usb_endpoints { JOYSTICK_OUT_EPNUM = NEXT_EPNUM, # endif #endif + +#ifdef DIGITIZER_ENABLE +# if !defined(DIGITIZER_SHARED_EP) + DIGITIZER_IN_EPNUM = NEXT_EPNUM, +# if STM32_USB_USE_OTG1 + DIGITIZER_OUT_EPNUM = DIGITIZER_IN_EPNUM, +# else + DIGITIZER_OUT_EPNUM = NEXT_EPNUM, +# endif +# else +# define DIGITIZER_IN_EPNUM SHARED_IN_EPNUM +# endif +#endif }; #ifdef PROTOCOL_LUFA @@ -284,5 +308,6 @@ enum usb_endpoints { #define CDC_NOTIFICATION_EPSIZE 8 #define CDC_EPSIZE 16 #define JOYSTICK_EPSIZE 8 +#define DIGITIZER_EPSIZE 8 uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const void** const DescriptorAddress); diff --git a/tmk_core/protocol/vusb/vusb.c b/tmk_core/protocol/vusb/vusb.c index 98cebf6012..485b20c900 100644 --- a/tmk_core/protocol/vusb/vusb.c +++ b/tmk_core/protocol/vusb/vusb.c @@ -292,6 +292,14 @@ static void send_consumer(uint16_t data) { #endif } +void send_digitizer(report_digitizer_t *report) { +#ifdef DIGITIZER_ENABLE + if (usbInterruptIsReadyShared()) { + usbSetInterruptShared((void *)report, sizeof(report_digitizer_t)); + } +#endif +} + /*------------------------------------------------------------------* * Request from host * *------------------------------------------------------------------*/ @@ -510,8 +518,46 @@ const PROGMEM uchar shared_hid_report[] = { 0x95, 0x01, // Report Count (1) 0x75, 0x10, // Report Size (16) 0x81, 0x00, // Input (Data, Array, Absolute) - 0xC0 // End Collection + 0xC0, // End Collection +#endif + +#ifdef DIGITIZER_ENABLE + // Digitizer report descriptor + 0x05, 0x0D, // Usage Page (Digitizers) + 0x09, 0x01, // Usage (Digitizer) + 0xA1, 0x01, // Collection (Application) + 0x85, REPORT_ID_DIGITIZER, // Report ID + 0x09, 0x22, // Usage (Finger) + 0xA1, 0x00, // Collection (Physical) + // Tip Switch (1 bit) + 0x09, 0x42, // Usage (Tip Switch) + 0x15, 0x00, // Logical Minimum + 0x25, 0x01, // Logical Maximum + 0x95, 0x01, // Report Count (1) + 0x75, 0x01, // Report Size (16) + 0x81, 0x02, // Input (Data, Variable, Absolute) + // In Range (1 bit) + 0x09, 0x32, // Usage (In Range) + 0x81, 0x02, // Input (Data, Variable, Absolute) + // Padding (6 bits) + 0x95, 0x06, // Report Count (6) + 0x81, 0x03, // Input (Constant) + + // X/Y Position (4 bytes) + 0x05, 0x01, // Usage Page (Generic Desktop) + 0x26, 0xFF, 0x7F, // Logical Maximum (32767) + 0x95, 0x01, // Report Count (1) + 0x75, 0x10, // Report Size (16) + 0x65, 0x33, // Unit (Inch, English Linear) + 0x55, 0x0E, // Unit Exponent (-2) + 0x09, 0x30, // Usage (X) + 0x81, 0x02, // Input (Data, Variable, Absolute) + 0x09, 0x31, // Usage (Y) + 0x81, 0x02, // Input (Data, Variable, Absolute) + 0xC0, // End Collection + 0xC0 // End Collection #endif + #ifdef SHARED_EP_ENABLE }; #endif -- cgit v1.2.3 From 483691dd73e5260fac958c524e0a12e705db43f6 Mon Sep 17 00:00:00 2001 From: Donald Kjer Date: Tue, 17 Aug 2021 14:12:12 -0700 Subject: Fixes for clang not being able to run unit tests (#13546) --- tmk_core/native.mk | 5 +++++ tmk_core/rules.mk | 7 +++++++ 2 files changed, 12 insertions(+) (limited to 'tmk_core') diff --git a/tmk_core/native.mk b/tmk_core/native.mk index 3caf644546..f609fd0e6f 100644 --- a/tmk_core/native.mk +++ b/tmk_core/native.mk @@ -1,4 +1,5 @@ SYSTEM_TYPE := $(shell gcc -dumpmachine) +GCC_VERSION := $(shell gcc --version 2>/dev/null) CC = gcc OBJCOPY = @@ -12,7 +13,9 @@ BIN = COMPILEFLAGS += -funsigned-char +ifeq ($(findstring clang, ${GCC_VERSION}),) COMPILEFLAGS += -funsigned-bitfields +endif COMPILEFLAGS += -ffunction-sections COMPILEFLAGS += -fdata-sections COMPILEFLAGS += -fshort-enums @@ -21,7 +24,9 @@ COMPILEFLAGS += -mno-ms-bitfields endif CFLAGS += $(COMPILEFLAGS) +ifeq ($(findstring clang, ${GCC_VERSION}),) CFLAGS += -fno-inline-small-functions +endif CFLAGS += -fno-strict-aliasing CXXFLAGS += $(COMPILEFLAGS) diff --git a/tmk_core/rules.mk b/tmk_core/rules.mk index 597f7aa827..5a7f299102 100644 --- a/tmk_core/rules.mk +++ b/tmk_core/rules.mk @@ -105,7 +105,10 @@ endif #CFLAGS += -Wundef #CFLAGS += -Wunreachable-code #CFLAGS += -Wsign-compare +GCC_VERSION := $(shell gcc --version 2>/dev/null) +ifeq ($(findstring clang, ${GCC_VERSION}),) CFLAGS += -Wa,-adhlns=$(@:%.o=%.lst) +endif CFLAGS += $(CSTANDARD) # This fixes lots of keyboards linking errors but SHOULDN'T BE A FINAL SOLUTION @@ -137,7 +140,9 @@ endif #CXXFLAGS += -Wstrict-prototypes #CXXFLAGS += -Wunreachable-code #CXXFLAGS += -Wsign-compare +ifeq ($(findstring clang, ${GCC_VERSION}),) CXXFLAGS += -Wa,-adhlns=$(@:%.o=%.lst) +endif #CXXFLAGS += $(CSTANDARD) #---------------- Assembler Options ---------------- @@ -150,11 +155,13 @@ CXXFLAGS += -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) +ifeq ($(findstring clang, ${GCC_VERSION}),) ifeq ($(strip $(DEBUG_ENABLE)),yes) ASFLAGS += -Wa,-adhlns=$(@:%.o=%.lst),-gstabs,--listing-cont-lines=100 else ASFLAGS += -Wa,-adhlns=$(@:%.o=%.lst),--listing-cont-lines=100 endif +endif ifeq ($(VERBOSE_AS_CMD),yes) ASFLAGS += -v endif -- cgit v1.2.3 From 1bb7af4d446174b7181c9bb22dbd14c93642ea10 Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Tue, 17 Aug 2021 23:43:09 +0100 Subject: Relocate platform specific drivers (#13894) * Relocate platform specific drivers * Move stm eeprom * Tidy up slightly--- common.mk | 3 + common_features.mk | 1 + drivers/avr/analog.c | 138 ------ drivers/avr/analog.h | 53 -- drivers/avr/glcdfont.c | 23 - drivers/avr/hd44780.c | 536 --------------------- drivers/avr/hd44780.h | 348 ------------- drivers/avr/i2c_master.c | 241 --------- drivers/avr/i2c_master.h | 43 -- drivers/avr/i2c_slave.c | 111 ----- drivers/avr/i2c_slave.h | 41 -- drivers/avr/serial.c | 529 -------------------- drivers/avr/spi_master.c | 180 ------- drivers/avr/spi_master.h | 59 --- drivers/avr/ssd1306.c | 319 ------------ drivers/avr/ssd1306.h | 87 ---- drivers/avr/uart.c | 170 ------- drivers/avr/uart.h | 35 -- drivers/avr/ws2812.c | 176 ------- drivers/avr/ws2812_i2c.c | 27 -- drivers/chibios/analog.c | 321 ------------ drivers/chibios/analog.h | 41 -- drivers/chibios/i2c_master.c | 121 ----- drivers/chibios/i2c_master.h | 113 ----- drivers/chibios/serial.c | 278 ----------- drivers/chibios/serial_usart.c | 318 ------------ drivers/chibios/serial_usart.h | 116 ----- drivers/chibios/spi_master.c | 202 -------- drivers/chibios/spi_master.h | 93 ---- drivers/chibios/uart.c | 50 -- drivers/chibios/uart.h | 77 --- drivers/chibios/usbpd_stm32g4.c | 76 --- drivers/chibios/ws2812.c | 114 ----- drivers/chibios/ws2812_pwm.c | 311 ------------ drivers/chibios/ws2812_spi.c | 159 ------ drivers/eeprom/eeprom_stm32_L0_L1.c | 96 ---- drivers/eeprom/eeprom_stm32_L0_L1.h | 33 -- platforms/avr/drivers/analog.c | 138 ++++++ platforms/avr/drivers/analog.h | 53 ++ platforms/avr/drivers/glcdfont.c | 23 + platforms/avr/drivers/hd44780.c | 536 +++++++++++++++++++++ platforms/avr/drivers/hd44780.h | 348 +++++++++++++ platforms/avr/drivers/i2c_master.c | 241 +++++++++ platforms/avr/drivers/i2c_master.h | 43 ++ platforms/avr/drivers/i2c_slave.c | 111 +++++ platforms/avr/drivers/i2c_slave.h | 41 ++ platforms/avr/drivers/serial.c | 529 ++++++++++++++++++++ platforms/avr/drivers/spi_master.c | 180 +++++++ platforms/avr/drivers/spi_master.h | 59 +++ platforms/avr/drivers/ssd1306.c | 319 ++++++++++++ platforms/avr/drivers/ssd1306.h | 87 ++++ platforms/avr/drivers/uart.c | 170 +++++++ platforms/avr/drivers/uart.h | 35 ++ platforms/avr/drivers/ws2812.c | 176 +++++++ platforms/avr/drivers/ws2812_i2c.c | 27 ++ platforms/chibios/drivers/analog.c | 321 ++++++++++++ platforms/chibios/drivers/analog.h | 41 ++ .../chibios/drivers/eeprom/eeprom_stm32_L0_L1.c | 96 ++++ .../chibios/drivers/eeprom/eeprom_stm32_L0_L1.h | 33 ++ platforms/chibios/drivers/i2c_master.c | 121 +++++ platforms/chibios/drivers/i2c_master.h | 113 +++++ platforms/chibios/drivers/serial.c | 278 +++++++++++ platforms/chibios/drivers/serial_usart.c | 318 ++++++++++++ platforms/chibios/drivers/serial_usart.h | 116 +++++ platforms/chibios/drivers/spi_master.c | 202 ++++++++ platforms/chibios/drivers/spi_master.h | 93 ++++ platforms/chibios/drivers/uart.c | 50 ++ platforms/chibios/drivers/uart.h | 77 +++ platforms/chibios/drivers/usbpd_stm32g4.c | 76 +++ platforms/chibios/drivers/ws2812.c | 114 +++++ platforms/chibios/drivers/ws2812_pwm.c | 311 ++++++++++++ platforms/chibios/drivers/ws2812_spi.c | 159 ++++++ tmk_core/avr.mk | 2 - tmk_core/chibios.mk | 2 - tmk_core/common.mk | 1 + tmk_core/protocol/lufa.mk | 1 - 76 files changed, 5640 insertions(+), 5640 deletions(-) delete mode 100644 drivers/avr/analog.c delete mode 100644 drivers/avr/analog.h delete mode 100644 drivers/avr/glcdfont.c delete mode 100644 drivers/avr/hd44780.c delete mode 100644 drivers/avr/hd44780.h delete mode 100644 drivers/avr/i2c_master.c delete mode 100644 drivers/avr/i2c_master.h delete mode 100644 drivers/avr/i2c_slave.c delete mode 100644 drivers/avr/i2c_slave.h delete mode 100644 drivers/avr/serial.c delete mode 100644 drivers/avr/spi_master.c delete mode 100644 drivers/avr/spi_master.h delete mode 100644 drivers/avr/ssd1306.c delete mode 100644 drivers/avr/ssd1306.h delete mode 100644 drivers/avr/uart.c delete mode 100644 drivers/avr/uart.h delete mode 100644 drivers/avr/ws2812.c delete mode 100644 drivers/avr/ws2812_i2c.c delete mode 100644 drivers/chibios/analog.c delete mode 100644 drivers/chibios/analog.h delete mode 100644 drivers/chibios/i2c_master.c delete mode 100644 drivers/chibios/i2c_master.h delete mode 100644 drivers/chibios/serial.c delete mode 100644 drivers/chibios/serial_usart.c delete mode 100644 drivers/chibios/serial_usart.h delete mode 100644 drivers/chibios/spi_master.c delete mode 100644 drivers/chibios/spi_master.h delete mode 100644 drivers/chibios/uart.c delete mode 100644 drivers/chibios/uart.h delete mode 100644 drivers/chibios/usbpd_stm32g4.c delete mode 100644 drivers/chibios/ws2812.c delete mode 100644 drivers/chibios/ws2812_pwm.c delete mode 100644 drivers/chibios/ws2812_spi.c delete mode 100644 drivers/eeprom/eeprom_stm32_L0_L1.c delete mode 100644 drivers/eeprom/eeprom_stm32_L0_L1.h create mode 100644 platforms/avr/drivers/analog.c create mode 100644 platforms/avr/drivers/analog.h create mode 100644 platforms/avr/drivers/glcdfont.c create mode 100644 platforms/avr/drivers/hd44780.c create mode 100644 platforms/avr/drivers/hd44780.h create mode 100644 platforms/avr/drivers/i2c_master.c create mode 100644 platforms/avr/drivers/i2c_master.h create mode 100644 platforms/avr/drivers/i2c_slave.c create mode 100644 platforms/avr/drivers/i2c_slave.h create mode 100644 platforms/avr/drivers/serial.c create mode 100644 platforms/avr/drivers/spi_master.c create mode 100644 platforms/avr/drivers/spi_master.h create mode 100644 platforms/avr/drivers/ssd1306.c create mode 100644 platforms/avr/drivers/ssd1306.h create mode 100644 platforms/avr/drivers/uart.c create mode 100644 platforms/avr/drivers/uart.h create mode 100644 platforms/avr/drivers/ws2812.c create mode 100644 platforms/avr/drivers/ws2812_i2c.c create mode 100644 platforms/chibios/drivers/analog.c create mode 100644 platforms/chibios/drivers/analog.h create mode 100644 platforms/chibios/drivers/eeprom/eeprom_stm32_L0_L1.c create mode 100644 platforms/chibios/drivers/eeprom/eeprom_stm32_L0_L1.h create mode 100644 platforms/chibios/drivers/i2c_master.c create mode 100644 platforms/chibios/drivers/i2c_master.h create mode 100644 platforms/chibios/drivers/serial.c create mode 100644 platforms/chibios/drivers/serial_usart.c create mode 100644 platforms/chibios/drivers/serial_usart.h create mode 100644 platforms/chibios/drivers/spi_master.c create mode 100644 platforms/chibios/drivers/spi_master.h create mode 100644 platforms/chibios/drivers/uart.c create mode 100644 platforms/chibios/drivers/uart.h create mode 100644 platforms/chibios/drivers/usbpd_stm32g4.c create mode 100644 platforms/chibios/drivers/ws2812.c create mode 100644 platforms/chibios/drivers/ws2812_pwm.c create mode 100644 platforms/chibios/drivers/ws2812_spi.c (limited to 'tmk_core') diff --git a/common.mk b/common.mk index c13b5e2768..8acea39376 100644 --- a/common.mk +++ b/common.mk @@ -12,6 +12,9 @@ QUANTUM_PATH = $(QUANTUM_DIR) DRIVER_DIR = drivers DRIVER_PATH = $(DRIVER_DIR) +PLATFORM_DIR = platforms +PLATFORM_PATH = $(PLATFORM_DIR) + BUILD_DIR := .build COMMON_VPATH := $(TOP_DIR) diff --git a/common_features.mk b/common_features.mk index 493aab6353..1eece0242e 100644 --- a/common_features.mk +++ b/common_features.mk @@ -178,6 +178,7 @@ else else ifneq ($(filter $(MCU_SERIES),STM32L0xx STM32L1xx),) OPT_DEFS += -DEEPROM_DRIVER COMMON_VPATH += $(DRIVER_PATH)/eeprom + COMMON_VPATH += $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_DIR)/eeprom SRC += eeprom_driver.c eeprom_stm32_L0_L1.c else # This will effectively work the same as "transient" if not supported by the chip diff --git a/drivers/avr/analog.c b/drivers/avr/analog.c deleted file mode 100644 index 8d299ffdb9..0000000000 --- a/drivers/avr/analog.c +++ /dev/null @@ -1,138 +0,0 @@ -/* Copyright 2015 Jack Humbert - * - * 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 . - */ - -#include -#include -#include -#include "analog.h" - -static uint8_t aref = ADC_REF_POWER; - -void analogReference(uint8_t mode) { aref = mode & (_BV(REFS1) | _BV(REFS0)); } - -// Arduino compatible pin input -int16_t analogRead(uint8_t pin) { -#if defined(__AVR_ATmega32U4__) - // clang-format off - static const uint8_t PROGMEM pin_to_mux[] = { - //A0 A1 A2 A3 A4 A5 - //F7 F6 F5 F4 F1 F0 - 0x07, 0x06, 0x05, 0x04, 0x01, 0x00, - //A6 A7 A8 A9 A10 A11 - //D4 D7 B4 B5 B6 D6 - 0x20, 0x22, 0x23, 0x24, 0x25, 0x21 - }; - // clang-format on - if (pin >= 12) return 0; - return adc_read(pgm_read_byte(pin_to_mux + pin)); -#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) - if (pin >= 8) return 0; - return adc_read(pin); -#else - return 0; -#endif -} - -int16_t analogReadPin(pin_t pin) { return adc_read(pinToMux(pin)); } - -uint8_t pinToMux(pin_t pin) { - switch (pin) { - // clang-format off -#if defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) - case F0: return 0; // ADC0 - case F1: return _BV(MUX0); // ADC1 - case F2: return _BV(MUX1); // ADC2 - case F3: return _BV(MUX1) | _BV(MUX0); // ADC3 - case F4: return _BV(MUX2); // ADC4 - case F5: return _BV(MUX2) | _BV(MUX0); // ADC5 - case F6: return _BV(MUX2) | _BV(MUX1); // ADC6 - case F7: return _BV(MUX2) | _BV(MUX1) | _BV(MUX0); // ADC7 - default: return _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0); // 0V -#elif defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) - case F0: return 0; // ADC0 - case F1: return _BV(MUX0); // ADC1 - case F4: return _BV(MUX2); // ADC4 - case F5: return _BV(MUX2) | _BV(MUX0); // ADC5 - case F6: return _BV(MUX2) | _BV(MUX1); // ADC6 - case F7: return _BV(MUX2) | _BV(MUX1) | _BV(MUX0); // ADC7 - case D4: return _BV(MUX5); // ADC8 - case D6: return _BV(MUX5) | _BV(MUX0); // ADC9 - case D7: return _BV(MUX5) | _BV(MUX1); // ADC10 - case B4: return _BV(MUX5) | _BV(MUX1) | _BV(MUX0); // ADC11 - case B5: return _BV(MUX5) | _BV(MUX2); // ADC12 - case B6: return _BV(MUX5) | _BV(MUX2) | _BV(MUX0); // ADC13 - default: return _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0); // 0V -#elif defined(__AVR_ATmega32A__) - case A0: return 0; // ADC0 - case A1: return _BV(MUX0); // ADC1 - case A2: return _BV(MUX1); // ADC2 - case A3: return _BV(MUX1) | _BV(MUX0); // ADC3 - case A4: return _BV(MUX2); // ADC4 - case A5: return _BV(MUX2) | _BV(MUX0); // ADC5 - case A6: return _BV(MUX2) | _BV(MUX1); // ADC6 - case A7: return _BV(MUX2) | _BV(MUX1) | _BV(MUX0); // ADC7 - default: return _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0); // 0V -#elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) - case C0: return 0; // ADC0 - case C1: return _BV(MUX0); // ADC1 - case C2: return _BV(MUX1); // ADC2 - case C3: return _BV(MUX1) | _BV(MUX0); // ADC3 - case C4: return _BV(MUX2); // ADC4 - case C5: return _BV(MUX2) | _BV(MUX0); // ADC5 - // ADC7:6 not present in DIP package and not shared by GPIO pins - default: return _BV(MUX3) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0); // 0V -#endif - // clang-format on - } - return 0; -} - -int16_t adc_read(uint8_t mux) { - uint16_t low; - - // Enable ADC and configure prescaler - ADCSRA = _BV(ADEN) | ADC_PRESCALER; - -#if defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) - // High speed mode and ADC8-13 - ADCSRB = _BV(ADHSM) | (mux & _BV(MUX5)); -#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) - // High speed mode only - ADCSRB = _BV(ADHSM); -#endif - - // Configure mux input -#if defined(MUX4) - ADMUX = aref | (mux & (_BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0))); -#else - ADMUX = aref | (mux & (_BV(MUX3) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0))); -#endif - - // Start the conversion - ADCSRA |= _BV(ADSC); - // Wait for result - while (ADCSRA & _BV(ADSC)) - ; - // Must read LSB first - low = ADCL; - // Must read MSB only once! - low |= (ADCH << 8); - - // turn off the ADC - ADCSRA &= ~(1 << ADEN); - - return low; -} diff --git a/drivers/avr/analog.h b/drivers/avr/analog.h deleted file mode 100644 index 058882450d..0000000000 --- a/drivers/avr/analog.h +++ /dev/null @@ -1,53 +0,0 @@ -/* Copyright 2015 Jack Humbert - * - * 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 . - */ - -#pragma once - -#include -#include "quantum.h" - -#ifdef __cplusplus -extern "C" { -#endif -void analogReference(uint8_t mode); -int16_t analogRead(uint8_t pin); - -int16_t analogReadPin(pin_t pin); -uint8_t pinToMux(pin_t pin); - -int16_t adc_read(uint8_t mux); -#ifdef __cplusplus -} -#endif - -#define ADC_REF_EXTERNAL 0 // AREF, Internal Vref turned off -#define ADC_REF_POWER _BV(REFS0) // AVCC with external capacitor on AREF pin -#define ADC_REF_INTERNAL (_BV(REFS1) | _BV(REFS0)) // Internal 2.56V Voltage Reference with external capacitor on AREF pin (1.1V for 328P) - -// These prescaler values are for high speed mode, ADHSM = 1 -#if F_CPU == 16000000L || F_CPU == 12000000L -# define ADC_PRESCALER (_BV(ADPS2) | _BV(ADPS1)) // /64 -#elif F_CPU == 8000000L -# define ADC_PRESCALER (_BV(ADPS2) | _BV(ADPS0)) // /32 -#elif F_CPU == 4000000L -# define ADC_PRESCALER (_BV(ADPS2)) // /16 -#elif F_CPU == 2000000L -# define ADC_PRESCALER (_BV(ADPS1) | _BV(ADPS0)) // /8 -#elif F_CPU == 1000000L -# define ADC_PRESCALER _BV(ADPS1) // /4 -#else -# define ADC_PRESCALER _BV(ADPS0) // /2 -#endif diff --git a/drivers/avr/glcdfont.c b/drivers/avr/glcdfont.c deleted file mode 100644 index 5e763b054f..0000000000 --- a/drivers/avr/glcdfont.c +++ /dev/null @@ -1,23 +0,0 @@ -// This is the 'classic' fixed-space bitmap font for Adafruit_GFX since 1.0. -// See gfxfont.h for newer custom bitmap font info. - -#include "progmem.h" - -// Standard ASCII 5x7 font - -static const unsigned char font[] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x5B, 0x4F, 0x5B, 0x3E, 0x3E, 0x6B, 0x4F, 0x6B, 0x3E, 0x1C, 0x3E, 0x7C, 0x3E, 0x1C, 0x18, 0x3C, 0x7E, 0x3C, 0x18, 0x1C, 0x57, 0x7D, 0x57, 0x1C, 0x1C, 0x5E, 0x7F, 0x5E, 0x1C, 0x00, 0x18, 0x3C, 0x18, 0x00, 0xFF, 0xE7, 0xC3, 0xE7, 0xFF, 0x00, 0x18, 0x24, 0x18, 0x00, 0xFF, 0xE7, 0xDB, 0xE7, 0xFF, 0x30, 0x48, 0x3A, 0x06, 0x0E, 0x26, 0x29, 0x79, 0x29, 0x26, 0x40, 0x7F, 0x05, 0x05, 0x07, 0x40, 0x7F, 0x05, 0x25, 0x3F, 0x5A, 0x3C, 0xE7, 0x3C, 0x5A, 0x7F, 0x3E, 0x1C, 0x1C, 0x08, 0x08, 0x1C, 0x1C, 0x3E, 0x7F, 0x14, 0x22, 0x7F, 0x22, 0x14, 0x5F, 0x5F, 0x00, 0x5F, 0x5F, 0x06, 0x09, 0x7F, 0x01, 0x7F, 0x00, 0x66, 0x89, 0x95, 0x6A, 0x60, 0x60, 0x60, 0x60, 0x60, 0x94, 0xA2, 0xFF, 0xA2, 0x94, 0x08, 0x04, 0x7E, 0x04, 0x08, 0x10, 0x20, 0x7E, 0x20, 0x10, 0x08, 0x08, 0x2A, 0x1C, 0x08, 0x08, 0x1C, 0x2A, 0x08, 0x08, 0x1E, 0x10, 0x10, 0x10, 0x10, 0x0C, 0x1E, 0x0C, 0x1E, 0x0C, - 0x30, 0x38, 0x3E, 0x38, 0x30, 0x06, 0x0E, 0x3E, 0x0E, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0x14, 0x7F, 0x14, 0x7F, 0x14, 0x24, 0x2A, 0x7F, 0x2A, 0x12, 0x23, 0x13, 0x08, 0x64, 0x62, 0x36, 0x49, 0x56, 0x20, 0x50, 0x00, 0x08, 0x07, 0x03, 0x00, 0x00, 0x1C, 0x22, 0x41, 0x00, 0x00, 0x41, 0x22, 0x1C, 0x00, 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00, 0x80, 0x70, 0x30, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x60, 0x60, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00, 0x42, 0x7F, 0x40, 0x00, 0x72, 0x49, 0x49, 0x49, 0x46, 0x21, 0x41, 0x49, 0x4D, 0x33, 0x18, 0x14, 0x12, 0x7F, 0x10, 0x27, 0x45, 0x45, 0x45, 0x39, 0x3C, 0x4A, 0x49, 0x49, 0x31, 0x41, 0x21, 0x11, 0x09, 0x07, 0x36, 0x49, 0x49, 0x49, 0x36, 0x46, 0x49, 0x49, 0x29, 0x1E, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x40, 0x34, 0x00, 0x00, - 0x00, 0x08, 0x14, 0x22, 0x41, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00, 0x41, 0x22, 0x14, 0x08, 0x02, 0x01, 0x59, 0x09, 0x06, 0x3E, 0x41, 0x5D, 0x59, 0x4E, 0x7C, 0x12, 0x11, 0x12, 0x7C, 0x7F, 0x49, 0x49, 0x49, 0x36, 0x3E, 0x41, 0x41, 0x41, 0x22, 0x7F, 0x41, 0x41, 0x41, 0x3E, 0x7F, 0x49, 0x49, 0x49, 0x41, 0x7F, 0x09, 0x09, 0x09, 0x01, 0x3E, 0x41, 0x41, 0x51, 0x73, 0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00, 0x41, 0x7F, 0x41, 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01, 0x7F, 0x08, 0x14, 0x22, 0x41, 0x7F, 0x40, 0x40, 0x40, 0x40, 0x7F, 0x02, 0x1C, 0x02, 0x7F, 0x7F, 0x04, 0x08, 0x10, 0x7F, 0x3E, 0x41, 0x41, 0x41, 0x3E, 0x7F, 0x09, 0x09, 0x09, 0x06, 0x3E, 0x41, 0x51, 0x21, 0x5E, 0x7F, 0x09, 0x19, 0x29, 0x46, 0x26, 0x49, 0x49, 0x49, 0x32, 0x03, 0x01, 0x7F, 0x01, 0x03, 0x3F, 0x40, 0x40, 0x40, 0x3F, 0x1F, 0x20, 0x40, 0x20, 0x1F, 0x3F, 0x40, 0x38, 0x40, 0x3F, 0x63, 0x14, 0x08, 0x14, 0x63, 0x03, 0x04, 0x78, 0x04, 0x03, - 0x61, 0x59, 0x49, 0x4D, 0x43, 0x00, 0x7F, 0x41, 0x41, 0x41, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, 0x41, 0x41, 0x41, 0x7F, 0x04, 0x02, 0x01, 0x02, 0x04, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x03, 0x07, 0x08, 0x00, 0x20, 0x54, 0x54, 0x78, 0x40, 0x7F, 0x28, 0x44, 0x44, 0x38, 0x38, 0x44, 0x44, 0x44, 0x28, 0x38, 0x44, 0x44, 0x28, 0x7F, 0x38, 0x54, 0x54, 0x54, 0x18, 0x00, 0x08, 0x7E, 0x09, 0x02, 0x18, 0xA4, 0xA4, 0x9C, 0x78, 0x7F, 0x08, 0x04, 0x04, 0x78, 0x00, 0x44, 0x7D, 0x40, 0x00, 0x20, 0x40, 0x40, 0x3D, 0x00, 0x7F, 0x10, 0x28, 0x44, 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00, 0x7C, 0x04, 0x78, 0x04, 0x78, 0x7C, 0x08, 0x04, 0x04, 0x78, 0x38, 0x44, 0x44, 0x44, 0x38, 0xFC, 0x18, 0x24, 0x24, 0x18, 0x18, 0x24, 0x24, 0x18, 0xFC, 0x7C, 0x08, 0x04, 0x04, 0x08, 0x48, 0x54, 0x54, 0x54, 0x24, 0x04, 0x04, 0x3F, 0x44, 0x24, 0x3C, 0x40, 0x40, 0x20, 0x7C, 0x1C, 0x20, 0x40, 0x20, 0x1C, 0x3C, 0x40, 0x30, 0x40, 0x3C, - 0x44, 0x28, 0x10, 0x28, 0x44, 0x4C, 0x90, 0x90, 0x90, 0x7C, 0x44, 0x64, 0x54, 0x4C, 0x44, 0x00, 0x08, 0x36, 0x41, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x41, 0x36, 0x08, 0x00, 0x02, 0x01, 0x02, 0x04, 0x02, 0x3C, 0x26, 0x23, 0x26, 0x3C, 0x1E, 0xA1, 0xA1, 0x61, 0x12, 0x3A, 0x40, 0x40, 0x20, 0x7A, 0x38, 0x54, 0x54, 0x55, 0x59, 0x21, 0x55, 0x55, 0x79, 0x41, 0x22, 0x54, 0x54, 0x78, 0x42, // a-umlaut - 0x21, 0x55, 0x54, 0x78, 0x40, 0x20, 0x54, 0x55, 0x79, 0x40, 0x0C, 0x1E, 0x52, 0x72, 0x12, 0x39, 0x55, 0x55, 0x55, 0x59, 0x39, 0x54, 0x54, 0x54, 0x59, 0x39, 0x55, 0x54, 0x54, 0x58, 0x00, 0x00, 0x45, 0x7C, 0x41, 0x00, 0x02, 0x45, 0x7D, 0x42, 0x00, 0x01, 0x45, 0x7C, 0x40, 0x7D, 0x12, 0x11, 0x12, 0x7D, // A-umlaut - 0xF0, 0x28, 0x25, 0x28, 0xF0, 0x7C, 0x54, 0x55, 0x45, 0x00, 0x20, 0x54, 0x54, 0x7C, 0x54, 0x7C, 0x0A, 0x09, 0x7F, 0x49, 0x32, 0x49, 0x49, 0x49, 0x32, 0x3A, 0x44, 0x44, 0x44, 0x3A, // o-umlaut - 0x32, 0x4A, 0x48, 0x48, 0x30, 0x3A, 0x41, 0x41, 0x21, 0x7A, 0x3A, 0x42, 0x40, 0x20, 0x78, 0x00, 0x9D, 0xA0, 0xA0, 0x7D, 0x3D, 0x42, 0x42, 0x42, 0x3D, // O-umlaut - 0x3D, 0x40, 0x40, 0x40, 0x3D, 0x3C, 0x24, 0xFF, 0x24, 0x24, 0x48, 0x7E, 0x49, 0x43, 0x66, 0x2B, 0x2F, 0xFC, 0x2F, 0x2B, 0xFF, 0x09, 0x29, 0xF6, 0x20, 0xC0, 0x88, 0x7E, 0x09, 0x03, 0x20, 0x54, 0x54, 0x79, 0x41, 0x00, 0x00, 0x44, 0x7D, 0x41, 0x30, 0x48, 0x48, 0x4A, 0x32, 0x38, 0x40, 0x40, 0x22, 0x7A, 0x00, 0x7A, 0x0A, 0x0A, 0x72, 0x7D, 0x0D, 0x19, 0x31, 0x7D, 0x26, 0x29, 0x29, 0x2F, 0x28, 0x26, 0x29, 0x29, 0x29, 0x26, 0x30, 0x48, 0x4D, 0x40, 0x20, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x2F, 0x10, 0xC8, 0xAC, 0xBA, 0x2F, 0x10, 0x28, 0x34, 0xFA, 0x00, 0x00, 0x7B, 0x00, 0x00, 0x08, 0x14, 0x2A, 0x14, 0x22, 0x22, 0x14, 0x2A, 0x14, 0x08, 0x55, 0x00, 0x55, 0x00, 0x55, // #176 (25% block) missing in old code - 0xAA, 0x55, 0xAA, 0x55, 0xAA, // 50% block - 0xFF, 0x55, 0xFF, 0x55, 0xFF, // 75% block - 0x00, 0x00, 0x00, 0xFF, 0x00, 0x10, 0x10, 0x10, 0xFF, 0x00, 0x14, 0x14, 0x14, 0xFF, 0x00, 0x10, 0x10, 0xFF, 0x00, 0xFF, 0x10, 0x10, 0xF0, 0x10, 0xF0, 0x14, 0x14, 0x14, 0xFC, 0x00, 0x14, 0x14, 0xF7, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x14, 0x14, 0xF4, 0x04, 0xFC, 0x14, 0x14, 0x17, 0x10, 0x1F, 0x10, 0x10, 0x1F, 0x10, 0x1F, 0x14, 0x14, 0x14, 0x1F, 0x00, 0x10, 0x10, 0x10, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x1F, 0x10, 0x10, 0x10, 0x10, 0xF0, 0x10, 0x00, 0x00, 0x00, 0xFF, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xFF, 0x10, 0x00, 0x00, 0x00, 0xFF, 0x14, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x1F, 0x10, 0x17, 0x00, 0x00, 0xFC, 0x04, 0xF4, 0x14, 0x14, 0x17, 0x10, 0x17, 0x14, 0x14, 0xF4, 0x04, 0xF4, 0x00, 0x00, 0xFF, 0x00, 0xF7, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0xF7, 0x00, 0xF7, 0x14, 0x14, 0x14, 0x17, 0x14, 0x10, 0x10, 0x1F, 0x10, 0x1F, - 0x14, 0x14, 0x14, 0xF4, 0x14, 0x10, 0x10, 0xF0, 0x10, 0xF0, 0x00, 0x00, 0x1F, 0x10, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x14, 0x00, 0x00, 0x00, 0xFC, 0x14, 0x00, 0x00, 0xF0, 0x10, 0xF0, 0x10, 0x10, 0xFF, 0x10, 0xFF, 0x14, 0x14, 0x14, 0xFF, 0x14, 0x10, 0x10, 0x10, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x38, 0x44, 0x44, 0x38, 0x44, 0xFC, 0x4A, 0x4A, 0x4A, 0x34, // sharp-s or beta - 0x7E, 0x02, 0x02, 0x06, 0x06, 0x02, 0x7E, 0x02, 0x7E, 0x02, 0x63, 0x55, 0x49, 0x41, 0x63, 0x38, 0x44, 0x44, 0x3C, 0x04, 0x40, 0x7E, 0x20, 0x1E, 0x20, 0x06, 0x02, 0x7E, 0x02, 0x02, 0x99, 0xA5, 0xE7, 0xA5, 0x99, 0x1C, 0x2A, 0x49, 0x2A, 0x1C, 0x4C, 0x72, 0x01, 0x72, 0x4C, 0x30, 0x4A, 0x4D, 0x4D, 0x30, 0x30, 0x48, 0x78, 0x48, 0x30, 0xBC, 0x62, 0x5A, 0x46, 0x3D, 0x3E, 0x49, 0x49, 0x49, 0x00, 0x7E, 0x01, 0x01, 0x01, 0x7E, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x44, 0x44, 0x5F, 0x44, 0x44, 0x40, 0x51, 0x4A, 0x44, 0x40, 0x40, 0x44, 0x4A, 0x51, 0x40, 0x00, 0x00, 0xFF, 0x01, 0x03, 0xE0, 0x80, 0xFF, 0x00, 0x00, 0x08, 0x08, 0x6B, 0x6B, 0x08, 0x36, 0x12, 0x36, 0x24, 0x36, 0x06, 0x0F, 0x09, 0x0F, 0x06, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x30, 0x40, 0xFF, 0x01, 0x01, 0x00, 0x1F, 0x01, 0x01, 0x1E, 0x00, 0x19, 0x1D, 0x17, 0x12, 0x00, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00 // #255 NBSP -}; diff --git a/drivers/avr/hd44780.c b/drivers/avr/hd44780.c deleted file mode 100644 index f71069dece..0000000000 --- a/drivers/avr/hd44780.c +++ /dev/null @@ -1,536 +0,0 @@ -/**************************************************************************** - Title: HD44780U LCD library - Author: Peter Fleury http://tinyurl.com/peterfleury - License: GNU General Public License Version 3 - File: $Id: lcd.c,v 1.15.2.2 2015/01/17 12:16:05 peter Exp $ - Software: AVR-GCC 3.3 - Target: any AVR device, memory mapped mode only for AT90S4414/8515/Mega - - DESCRIPTION - Basic routines for interfacing a HD44780U-based text lcd display - - Originally based on Volker Oth's lcd library, - changed lcd_init(), added additional constants for lcd_command(), - added 4-bit I/O mode, improved and optimized code. - - Library can be operated in memory mapped mode (LCD_IO_MODE=0) or in - 4-bit IO port mode (LCD_IO_MODE=1). 8-bit IO port mode not supported. - - Memory mapped mode compatible with Kanda STK200, but supports also - generation of R/W signal through A8 address line. - - USAGE - See the C include lcd.h file for a description of each function - -*****************************************************************************/ -#include -#include -#include -#include -#include "hd44780.h" - -/* -** constants/macros -*/ -#define DDR(x) (*(&x - 1)) /* address of data direction register of port x */ -#if defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) -/* on ATmega64/128 PINF is on port 0x00 and not 0x60 */ -# define PIN(x) (&PORTF == &(x) ? _SFR_IO8(0x00) : (*(&x - 2))) -#else -# define PIN(x) (*(&x - 2)) /* address of input register of port x */ -#endif - -#if LCD_IO_MODE -# define lcd_e_delay() _delay_us(LCD_DELAY_ENABLE_PULSE) -# define lcd_e_high() LCD_E_PORT |= _BV(LCD_E_PIN); -# define lcd_e_low() LCD_E_PORT &= ~_BV(LCD_E_PIN); -# define lcd_e_toggle() toggle_e() -# define lcd_rw_high() LCD_RW_PORT |= _BV(LCD_RW_PIN) -# define lcd_rw_low() LCD_RW_PORT &= ~_BV(LCD_RW_PIN) -# define lcd_rs_high() LCD_RS_PORT |= _BV(LCD_RS_PIN) -# define lcd_rs_low() LCD_RS_PORT &= ~_BV(LCD_RS_PIN) -#endif - -#if LCD_IO_MODE -# if LCD_LINES == 1 -# define LCD_FUNCTION_DEFAULT LCD_FUNCTION_4BIT_1LINE -# else -# define LCD_FUNCTION_DEFAULT LCD_FUNCTION_4BIT_2LINES -# endif -#else -# if LCD_LINES == 1 -# define LCD_FUNCTION_DEFAULT LCD_FUNCTION_8BIT_1LINE -# else -# define LCD_FUNCTION_DEFAULT LCD_FUNCTION_8BIT_2LINES -# endif -#endif - -#if LCD_CONTROLLER_KS0073 -# if LCD_LINES == 4 - -# define KS0073_EXTENDED_FUNCTION_REGISTER_ON 0x2C /* |0|010|1100 4-bit mode, extension-bit RE = 1 */ -# define KS0073_EXTENDED_FUNCTION_REGISTER_OFF 0x28 /* |0|010|1000 4-bit mode, extension-bit RE = 0 */ -# define KS0073_4LINES_MODE 0x09 /* |0|000|1001 4 lines mode */ - -# endif -#endif - -/* -** function prototypes -*/ -#if LCD_IO_MODE -static void toggle_e(void); -#endif - -/* -** local functions -*/ - -/************************************************************************* -delay for a minimum of microseconds -the number of loops is calculated at compile-time from MCU clock frequency -*************************************************************************/ -#define delay(us) _delay_us(us) - -#if LCD_IO_MODE -/* toggle Enable Pin to initiate write */ -static void toggle_e(void) { - lcd_e_high(); - lcd_e_delay(); - lcd_e_low(); -} -#endif - -/************************************************************************* -Low-level function to write byte to LCD controller -Input: data byte to write to LCD - rs 1: write data - 0: write instruction -Returns: none -*************************************************************************/ -#if LCD_IO_MODE -static void lcd_write(uint8_t data, uint8_t rs) { - unsigned char dataBits; - - if (rs) { /* write data (RS=1, RW=0) */ - lcd_rs_high(); - } else { /* write instruction (RS=0, RW=0) */ - lcd_rs_low(); - } - lcd_rw_low(); /* RW=0 write mode */ - - if ((&LCD_DATA0_PORT == &LCD_DATA1_PORT) && (&LCD_DATA1_PORT == &LCD_DATA2_PORT) && (&LCD_DATA2_PORT == &LCD_DATA3_PORT) && (LCD_DATA0_PIN == 0) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3)) { - /* configure data pins as output */ - DDR(LCD_DATA0_PORT) |= 0x0F; - - /* output high nibble first */ - dataBits = LCD_DATA0_PORT & 0xF0; - LCD_DATA0_PORT = dataBits | ((data >> 4) & 0x0F); - lcd_e_toggle(); - - /* output low nibble */ - LCD_DATA0_PORT = dataBits | (data & 0x0F); - lcd_e_toggle(); - - /* all data pins high (inactive) */ - LCD_DATA0_PORT = dataBits | 0x0F; - } else { - /* configure data pins as output */ - DDR(LCD_DATA0_PORT) |= _BV(LCD_DATA0_PIN); - DDR(LCD_DATA1_PORT) |= _BV(LCD_DATA1_PIN); - DDR(LCD_DATA2_PORT) |= _BV(LCD_DATA2_PIN); - DDR(LCD_DATA3_PORT) |= _BV(LCD_DATA3_PIN); - - /* output high nibble first */ - LCD_DATA3_PORT &= ~_BV(LCD_DATA3_PIN); - LCD_DATA2_PORT &= ~_BV(LCD_DATA2_PIN); - LCD_DATA1_PORT &= ~_BV(LCD_DATA1_PIN); - LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN); - if (data & 0x80) LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN); - if (data & 0x40) LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN); - if (data & 0x20) LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN); - if (data & 0x10) LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN); - lcd_e_toggle(); - - /* output low nibble */ - LCD_DATA3_PORT &= ~_BV(LCD_DATA3_PIN); - LCD_DATA2_PORT &= ~_BV(LCD_DATA2_PIN); - LCD_DATA1_PORT &= ~_BV(LCD_DATA1_PIN); - LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN); - if (data & 0x08) LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN); - if (data & 0x04) LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN); - if (data & 0x02) LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN); - if (data & 0x01) LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN); - lcd_e_toggle(); - - /* all data pins high (inactive) */ - LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN); - LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN); - LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN); - LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN); - } -} -#else -# define lcd_write(d, rs) \ - if (rs) \ - *(volatile uint8_t *)(LCD_IO_DATA) = d; \ - else \ - *(volatile uint8_t *)(LCD_IO_FUNCTION) = d; -/* rs==0 -> write instruction to LCD_IO_FUNCTION */ -/* rs==1 -> write data to LCD_IO_DATA */ -#endif - -/************************************************************************* -Low-level function to read byte from LCD controller -Input: rs 1: read data - 0: read busy flag / address counter -Returns: byte read from LCD controller -*************************************************************************/ -#if LCD_IO_MODE -static uint8_t lcd_read(uint8_t rs) { - uint8_t data; - - if (rs) - lcd_rs_high(); /* RS=1: read data */ - else - lcd_rs_low(); /* RS=0: read busy flag */ - lcd_rw_high(); /* RW=1 read mode */ - - if ((&LCD_DATA0_PORT == &LCD_DATA1_PORT) && (&LCD_DATA1_PORT == &LCD_DATA2_PORT) && (&LCD_DATA2_PORT == &LCD_DATA3_PORT) && (LCD_DATA0_PIN == 0) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3)) { - DDR(LCD_DATA0_PORT) &= 0xF0; /* configure data pins as input */ - - lcd_e_high(); - lcd_e_delay(); - data = PIN(LCD_DATA0_PORT) << 4; /* read high nibble first */ - lcd_e_low(); - - lcd_e_delay(); /* Enable 500ns low */ - - lcd_e_high(); - lcd_e_delay(); - data |= PIN(LCD_DATA0_PORT) & 0x0F; /* read low nibble */ - lcd_e_low(); - } else { - /* configure data pins as input */ - DDR(LCD_DATA0_PORT) &= ~_BV(LCD_DATA0_PIN); - DDR(LCD_DATA1_PORT) &= ~_BV(LCD_DATA1_PIN); - DDR(LCD_DATA2_PORT) &= ~_BV(LCD_DATA2_PIN); - DDR(LCD_DATA3_PORT) &= ~_BV(LCD_DATA3_PIN); - - /* read high nibble first */ - lcd_e_high(); - lcd_e_delay(); - data = 0; - if (PIN(LCD_DATA0_PORT) & _BV(LCD_DATA0_PIN)) data |= 0x10; - if (PIN(LCD_DATA1_PORT) & _BV(LCD_DATA1_PIN)) data |= 0x20; - if (PIN(LCD_DATA2_PORT) & _BV(LCD_DATA2_PIN)) data |= 0x40; - if (PIN(LCD_DATA3_PORT) & _BV(LCD_DATA3_PIN)) data |= 0x80; - lcd_e_low(); - - lcd_e_delay(); /* Enable 500ns low */ - - /* read low nibble */ - lcd_e_high(); - lcd_e_delay(); - if (PIN(LCD_DATA0_PORT) & _BV(LCD_DATA0_PIN)) data |= 0x01; - if (PIN(LCD_DATA1_PORT) & _BV(LCD_DATA1_PIN)) data |= 0x02; - if (PIN(LCD_DATA2_PORT) & _BV(LCD_DATA2_PIN)) data |= 0x04; - if (PIN(LCD_DATA3_PORT) & _BV(LCD_DATA3_PIN)) data |= 0x08; - lcd_e_low(); - } - return data; -} -#else -# define lcd_read(rs) (rs) ? *(volatile uint8_t *)(LCD_IO_DATA + LCD_IO_READ) : *(volatile uint8_t *)(LCD_IO_FUNCTION + LCD_IO_READ) -/* rs==0 -> read instruction from LCD_IO_FUNCTION */ -/* rs==1 -> read data from LCD_IO_DATA */ -#endif - -/************************************************************************* -loops while lcd is busy, returns address counter -*************************************************************************/ -static uint8_t lcd_waitbusy(void) - -{ - register uint8_t c; - - /* wait until busy flag is cleared */ - while ((c = lcd_read(0)) & (1 << LCD_BUSY)) { - } - - /* the address counter is updated 4us after the busy flag is cleared */ - delay(LCD_DELAY_BUSY_FLAG); - - /* now read the address counter */ - return (lcd_read(0)); // return address counter - -} /* lcd_waitbusy */ - -/************************************************************************* -Move cursor to the start of next line or to the first line if the cursor -is already on the last line. -*************************************************************************/ -static inline void lcd_newline(uint8_t pos) { - register uint8_t addressCounter; - -#if LCD_LINES == 1 - addressCounter = 0; -#endif -#if LCD_LINES == 2 - if (pos < (LCD_START_LINE2)) - addressCounter = LCD_START_LINE2; - else - addressCounter = LCD_START_LINE1; -#endif -#if LCD_LINES == 4 -# if KS0073_4LINES_MODE - if (pos < LCD_START_LINE2) - addressCounter = LCD_START_LINE2; - else if ((pos >= LCD_START_LINE2) && (pos < LCD_START_LINE3)) - addressCounter = LCD_START_LINE3; - else if ((pos >= LCD_START_LINE3) && (pos < LCD_START_LINE4)) - addressCounter = LCD_START_LINE4; - else - addressCounter = LCD_START_LINE1; -# else - if (pos < LCD_START_LINE3) - addressCounter = LCD_START_LINE2; - else if ((pos >= LCD_START_LINE2) && (pos < LCD_START_LINE4)) - addressCounter = LCD_START_LINE3; - else if ((pos >= LCD_START_LINE3) && (pos < LCD_START_LINE2)) - addressCounter = LCD_START_LINE4; - else - addressCounter = LCD_START_LINE1; -# endif -#endif - lcd_command((1 << LCD_DDRAM) + addressCounter); - -} /* lcd_newline */ - -/* -** PUBLIC FUNCTIONS -*/ - -/************************************************************************* -Send LCD controller instruction command -Input: instruction to send to LCD controller, see HD44780 data sheet -Returns: none -*************************************************************************/ -void lcd_command(uint8_t cmd) { - lcd_waitbusy(); - lcd_write(cmd, 0); -} - -/************************************************************************* -Send data byte to LCD controller -Input: data to send to LCD controller, see HD44780 data sheet -Returns: none -*************************************************************************/ -void lcd_data(uint8_t data) { - lcd_waitbusy(); - lcd_write(data, 1); -} - -/************************************************************************* -Set cursor to specified position -Input: x horizontal position (0: left most position) - y vertical position (0: first line) -Returns: none -*************************************************************************/ -void lcd_gotoxy(uint8_t x, uint8_t y) { -#if LCD_LINES == 1 - lcd_command((1 << LCD_DDRAM) + LCD_START_LINE1 + x); -#endif -#if LCD_LINES == 2 - if (y == 0) - lcd_command((1 << LCD_DDRAM) + LCD_START_LINE1 + x); - else - lcd_command((1 << LCD_DDRAM) + LCD_START_LINE2 + x); -#endif -#if LCD_LINES == 4 - if (y == 0) - lcd_command((1 << LCD_DDRAM) + LCD_START_LINE1 + x); - else if (y == 1) - lcd_command((1 << LCD_DDRAM) + LCD_START_LINE2 + x); - else if (y == 2) - lcd_command((1 << LCD_DDRAM) + LCD_START_LINE3 + x); - else /* y==3 */ - lcd_command((1 << LCD_DDRAM) + LCD_START_LINE4 + x); -#endif - -} /* lcd_gotoxy */ - -/************************************************************************* -*************************************************************************/ -int lcd_getxy(void) { return lcd_waitbusy(); } - -/************************************************************************* -Clear display and set cursor to home position -*************************************************************************/ -void lcd_clrscr(void) { lcd_command(1 << LCD_CLR); } - -/************************************************************************* -Set cursor to home position -*************************************************************************/ -void lcd_home(void) { lcd_command(1 << LCD_HOME); } - -/************************************************************************* -Display character at current cursor position -Input: character to be displayed -Returns: none -*************************************************************************/ -void lcd_putc(char c) { - uint8_t pos; - - pos = lcd_waitbusy(); // read busy-flag and address counter - if (c == '\n') { - lcd_newline(pos); - } else { -#if LCD_WRAP_LINES == 1 -# if LCD_LINES == 1 - if (pos == LCD_START_LINE1 + LCD_DISP_LENGTH) { - lcd_write((1 << LCD_DDRAM) + LCD_START_LINE1, 0); - } -# elif LCD_LINES == 2 - if (pos == LCD_START_LINE1 + LCD_DISP_LENGTH) { - lcd_write((1 << LCD_DDRAM) + LCD_START_LINE2, 0); - } else if (pos == LCD_START_LINE2 + LCD_DISP_LENGTH) { - lcd_write((1 << LCD_DDRAM) + LCD_START_LINE1, 0); - } -# elif LCD_LINES == 4 - if (pos == LCD_START_LINE1 + LCD_DISP_LENGTH) { - lcd_write((1 << LCD_DDRAM) + LCD_START_LINE2, 0); - } else if (pos == LCD_START_LINE2 + LCD_DISP_LENGTH) { - lcd_write((1 << LCD_DDRAM) + LCD_START_LINE3, 0); - } else if (pos == LCD_START_LINE3 + LCD_DISP_LENGTH) { - lcd_write((1 << LCD_DDRAM) + LCD_START_LINE4, 0); - } else if (pos == LCD_START_LINE4 + LCD_DISP_LENGTH) { - lcd_write((1 << LCD_DDRAM) + LCD_START_LINE1, 0); - } -# endif - lcd_waitbusy(); -#endif - lcd_write(c, 1); - } - -} /* lcd_putc */ - -/************************************************************************* -Display string without auto linefeed -Input: string to be displayed -Returns: none -*************************************************************************/ -void lcd_puts(const char *s) -/* print string on lcd (no auto linefeed) */ -{ - register char c; - - while ((c = *s++)) { - lcd_putc(c); - } - -} /* lcd_puts */ - -/************************************************************************* -Display string from program memory without auto linefeed -Input: string from program memory be be displayed -Returns: none -*************************************************************************/ -void lcd_puts_p(const char *progmem_s) -/* print string from program memory on lcd (no auto linefeed) */ -{ - register char c; - - while ((c = pgm_read_byte(progmem_s++))) { - lcd_putc(c); - } - -} /* lcd_puts_p */ - -/************************************************************************* -Initialize display and select type of cursor -Input: dispAttr LCD_DISP_OFF display off - LCD_DISP_ON display on, cursor off - LCD_DISP_ON_CURSOR display on, cursor on - LCD_DISP_CURSOR_BLINK display on, cursor on flashing -Returns: none -*************************************************************************/ -void lcd_init(uint8_t dispAttr) { -#if LCD_IO_MODE - /* - * Initialize LCD to 4 bit I/O mode - */ - - if ((&LCD_DATA0_PORT == &LCD_DATA1_PORT) && (&LCD_DATA1_PORT == &LCD_DATA2_PORT) && (&LCD_DATA2_PORT == &LCD_DATA3_PORT) && (&LCD_RS_PORT == &LCD_DATA0_PORT) && (&LCD_RW_PORT == &LCD_DATA0_PORT) && (&LCD_E_PORT == &LCD_DATA0_PORT) && (LCD_DATA0_PIN == 0) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3) && (LCD_RS_PIN == 4) && (LCD_RW_PIN == 5) && (LCD_E_PIN == 6)) { - /* configure all port bits as output (all LCD lines on same port) */ - DDR(LCD_DATA0_PORT) |= 0x7F; - } else if ((&LCD_DATA0_PORT == &LCD_DATA1_PORT) && (&LCD_DATA1_PORT == &LCD_DATA2_PORT) && (&LCD_DATA2_PORT == &LCD_DATA3_PORT) && (LCD_DATA0_PIN == 0) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3)) { - /* configure all port bits as output (all LCD data lines on same port, but control lines on different ports) */ - DDR(LCD_DATA0_PORT) |= 0x0F; - DDR(LCD_RS_PORT) |= _BV(LCD_RS_PIN); - DDR(LCD_RW_PORT) |= _BV(LCD_RW_PIN); - DDR(LCD_E_PORT) |= _BV(LCD_E_PIN); - } else { - /* configure all port bits as output (LCD data and control lines on different ports */ - DDR(LCD_RS_PORT) |= _BV(LCD_RS_PIN); - DDR(LCD_RW_PORT) |= _BV(LCD_RW_PIN); - DDR(LCD_E_PORT) |= _BV(LCD_E_PIN); - DDR(LCD_DATA0_PORT) |= _BV(LCD_DATA0_PIN); - DDR(LCD_DATA1_PORT) |= _BV(LCD_DATA1_PIN); - DDR(LCD_DATA2_PORT) |= _BV(LCD_DATA2_PIN); - DDR(LCD_DATA3_PORT) |= _BV(LCD_DATA3_PIN); - } - delay(LCD_DELAY_BOOTUP); /* wait 16ms or more after power-on */ - - /* initial write to lcd is 8bit */ - LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN); // LCD_FUNCTION>>4; - LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN); // LCD_FUNCTION_8BIT>>4; - lcd_e_toggle(); - delay(LCD_DELAY_INIT); /* delay, busy flag can't be checked here */ - - /* repeat last command */ - lcd_e_toggle(); - delay(LCD_DELAY_INIT_REP); /* delay, busy flag can't be checked here */ - - /* repeat last command a third time */ - lcd_e_toggle(); - delay(LCD_DELAY_INIT_REP); /* delay, busy flag can't be checked here */ - - /* now configure for 4bit mode */ - LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN); // LCD_FUNCTION_4BIT_1LINE>>4 - lcd_e_toggle(); - delay(LCD_DELAY_INIT_4BIT); /* some displays need this additional delay */ - - /* from now the LCD only accepts 4 bit I/O, we can use lcd_command() */ -#else - /* - * Initialize LCD to 8 bit memory mapped mode - */ - - /* enable external SRAM (memory mapped lcd) and one wait state */ - MCUCR = _BV(SRE) | _BV(SRW); - - /* reset LCD */ - delay(LCD_DELAY_BOOTUP); /* wait 16ms after power-on */ - lcd_write(LCD_FUNCTION_8BIT_1LINE, 0); /* function set: 8bit interface */ - delay(LCD_DELAY_INIT); /* wait 5ms */ - lcd_write(LCD_FUNCTION_8BIT_1LINE, 0); /* function set: 8bit interface */ - delay(LCD_DELAY_INIT_REP); /* wait 64us */ - lcd_write(LCD_FUNCTION_8BIT_1LINE, 0); /* function set: 8bit interface */ - delay(LCD_DELAY_INIT_REP); /* wait 64us */ -#endif - -#if KS0073_4LINES_MODE - /* Display with KS0073 controller requires special commands for enabling 4 line mode */ - lcd_command(KS0073_EXTENDED_FUNCTION_REGISTER_ON); - lcd_command(KS0073_4LINES_MODE); - lcd_command(KS0073_EXTENDED_FUNCTION_REGISTER_OFF); -#else - lcd_command(LCD_FUNCTION_DEFAULT); /* function set: display lines */ -#endif - lcd_command(LCD_DISP_OFF); /* display off */ - lcd_clrscr(); /* display clear */ - lcd_command(LCD_MODE_DEFAULT); /* set entry mode */ - lcd_command(dispAttr); /* display/cursor control */ - -} /* lcd_init */ diff --git a/drivers/avr/hd44780.h b/drivers/avr/hd44780.h deleted file mode 100644 index 08e60f8a44..0000000000 --- a/drivers/avr/hd44780.h +++ /dev/null @@ -1,348 +0,0 @@ -/************************************************************************* - Title : C include file for the HD44780U LCD library (lcd.c) - Author: Peter Fleury http://tinyurl.com/peterfleury - License: GNU General Public License Version 3 - File: $Id: lcd.h,v 1.14.2.4 2015/01/20 17:16:07 peter Exp $ - Software: AVR-GCC 4.x - Hardware: any AVR device, memory mapped mode only for AVR with - memory mapped interface (AT90S8515/ATmega8515/ATmega128) -***************************************************************************/ - -/** - @mainpage - Collection of libraries for AVR-GCC - @author Peter Fleury pfleury@gmx.ch http://tinyurl.com/peterfleury - @copyright (C) 2015 Peter Fleury, GNU General Public License Version 3 - - @file - @defgroup pfleury_lcd LCD library - @code #include @endcode - - @brief Basic routines for interfacing a HD44780U-based character LCD display - - LCD character displays can be found in many devices, like espresso machines, laser printers. - The Hitachi HD44780 controller and its compatible controllers like Samsung KS0066U have become an industry standard for these types of displays. - - This library allows easy interfacing with a HD44780 compatible display and can be - operated in memory mapped mode (LCD_IO_MODE defined as 0 in the include file lcd.h.) or in - 4-bit IO port mode (LCD_IO_MODE defined as 1). 8-bit IO port mode is not supported. - - Memory mapped mode is compatible with old Kanda STK200 starter kit, but also supports - generation of R/W signal through A8 address line. - - @see The chapter Interfacing a HD44780 Based LCD to an AVR - on my home page, which shows example circuits how to connect an LCD to an AVR controller. - - @author Peter Fleury pfleury@gmx.ch http://tinyurl.com/peterfleury - - @version 2.0 - - @copyright (C) 2015 Peter Fleury, GNU General Public License Version 3 - -*/ - -#pragma once - -#include -#include - -#if (__GNUC__ * 100 + __GNUC_MINOR__) < 405 -# error "This library requires AVR-GCC 4.5 or later, update to newer AVR-GCC compiler !" -#endif - -/**@{*/ - -/* - * LCD and target specific definitions below can be defined in a separate include file with name lcd_definitions.h instead modifying this file - * by adding -D_LCD_DEFINITIONS_FILE to the CDEFS section in the Makefile - * All definitions added to the file lcd_definitions.h will override the default definitions from lcd.h - */ -#ifdef _LCD_DEFINITIONS_FILE -# include "lcd_definitions.h" -#endif - -/** - * @name Definition for LCD controller type - * Use 0 for HD44780 controller, change to 1 for displays with KS0073 controller. - */ -#ifndef LCD_CONTROLLER_KS0073 -# define LCD_CONTROLLER_KS0073 0 /**< Use 0 for HD44780 controller, 1 for KS0073 controller */ -#endif - -/** - * @name Definitions for Display Size - * Change these definitions to adapt setting to your display - * - * These definitions can be defined in a separate include file \b lcd_definitions.h instead modifying this file by - * adding -D_LCD_DEFINITIONS_FILE to the CDEFS section in the Makefile. - * All definitions added to the file lcd_definitions.h will override the default definitions from lcd.h - * - */ -#ifndef LCD_LINES -# define LCD_LINES 2 /**< number of visible lines of the display */ -#endif -#ifndef LCD_DISP_LENGTH -# define LCD_DISP_LENGTH 16 /**< visibles characters per line of the display */ -#endif -#ifndef LCD_LINE_LENGTH -# define LCD_LINE_LENGTH 0x40 /**< internal line length of the display */ -#endif -#ifndef LCD_START_LINE1 -# define LCD_START_LINE1 0x00 /**< DDRAM address of first char of line 1 */ -#endif -#ifndef LCD_START_LINE2 -# define LCD_START_LINE2 0x40 /**< DDRAM address of first char of line 2 */ -#endif -#ifndef LCD_START_LINE3 -# define LCD_START_LINE3 0x14 /**< DDRAM address of first char of line 3 */ -#endif -#ifndef LCD_START_LINE4 -# define LCD_START_LINE4 0x54 /**< DDRAM address of first char of line 4 */ -#endif -#ifndef LCD_WRAP_LINES -# define LCD_WRAP_LINES 0 /**< 0: no wrap, 1: wrap at end of visibile line */ -#endif - -/** - * @name Definitions for 4-bit IO mode - * - * The four LCD data lines and the three control lines RS, RW, E can be on the - * same port or on different ports. - * Change LCD_RS_PORT, LCD_RW_PORT, LCD_E_PORT if you want the control lines on - * different ports. - * - * Normally the four data lines should be mapped to bit 0..3 on one port, but it - * is possible to connect these data lines in different order or even on different - * ports by adapting the LCD_DATAx_PORT and LCD_DATAx_PIN definitions. - * - * Adjust these definitions to your target.\n - * These definitions can be defined in a separate include file \b lcd_definitions.h instead modifying this file by - * adding \b -D_LCD_DEFINITIONS_FILE to the \b CDEFS section in the Makefile. - * All definitions added to the file lcd_definitions.h will override the default definitions from lcd.h - * - */ -#define LCD_IO_MODE 1 /**< 0: memory mapped mode, 1: IO port mode */ - -#if LCD_IO_MODE - -# ifndef LCD_PORT -# define LCD_PORT PORTA /**< port for the LCD lines */ -# endif -# ifndef LCD_DATA0_PORT -# define LCD_DATA0_PORT LCD_PORT /**< port for 4bit data bit 0 */ -# endif -# ifndef LCD_DATA1_PORT -# define LCD_DATA1_PORT LCD_PORT /**< port for 4bit data bit 1 */ -# endif -# ifndef LCD_DATA2_PORT -# define LCD_DATA2_PORT LCD_PORT /**< port for 4bit data bit 2 */ -# endif -# ifndef LCD_DATA3_PORT -# define LCD_DATA3_PORT LCD_PORT /**< port for 4bit data bit 3 */ -# endif -# ifndef LCD_DATA0_PIN -# define LCD_DATA0_PIN 4 /**< pin for 4bit data bit 0 */ -# endif -# ifndef LCD_DATA1_PIN -# define LCD_DATA1_PIN 5 /**< pin for 4bit data bit 1 */ -# endif -# ifndef LCD_DATA2_PIN -# define LCD_DATA2_PIN 6 /**< pin for 4bit data bit 2 */ -# endif -# ifndef LCD_DATA3_PIN -# define LCD_DATA3_PIN 7 /**< pin for 4bit data bit 3 */ -# endif -# ifndef LCD_RS_PORT -# define LCD_RS_PORT LCD_PORT /**< port for RS line */ -# endif -# ifndef LCD_RS_PIN -# define LCD_RS_PIN 3 /**< pin for RS line */ -# endif -# ifndef LCD_RW_PORT -# define LCD_RW_PORT LCD_PORT /**< port for RW line */ -# endif -# ifndef LCD_RW_PIN -# define LCD_RW_PIN 2 /**< pin for RW line */ -# endif -# ifndef LCD_E_PORT -# define LCD_E_PORT LCD_PORT /**< port for Enable line */ -# endif -# ifndef LCD_E_PIN -# define LCD_E_PIN 1 /**< pin for Enable line */ -# endif - -#elif defined(__AVR_AT90S4414__) || defined(__AVR_AT90S8515__) || defined(__AVR_ATmega64__) || defined(__AVR_ATmega8515__) || defined(__AVR_ATmega103__) || defined(__AVR_ATmega128__) || defined(__AVR_ATmega161__) || defined(__AVR_ATmega162__) -/* - * memory mapped mode is only supported when the device has an external data memory interface - */ -# define LCD_IO_DATA 0xC000 /* A15=E=1, A14=RS=1 */ -# define LCD_IO_FUNCTION 0x8000 /* A15=E=1, A14=RS=0 */ -# define LCD_IO_READ 0x0100 /* A8 =R/W=1 (R/W: 1=Read, 0=Write */ - -#else -# error "external data memory interface not available for this device, use 4-bit IO port mode" - -#endif - -/** - * @name Definitions of delays - * Used to calculate delay timers. - * Adapt the F_CPU define in the Makefile to the clock frequency in Hz of your target - * - * These delay times can be adjusted, if some displays require different delays.\n - * These definitions can be defined in a separate include file \b lcd_definitions.h instead modifying this file by - * adding \b -D_LCD_DEFINITIONS_FILE to the \b CDEFS section in the Makefile. - * All definitions added to the file lcd_definitions.h will override the default definitions from lcd.h - */ -#ifndef LCD_DELAY_BOOTUP -# define LCD_DELAY_BOOTUP 16000 /**< delay in micro seconds after power-on */ -#endif -#ifndef LCD_DELAY_INIT -# define LCD_DELAY_INIT 5000 /**< delay in micro seconds after initialization command sent */ -#endif -#ifndef LCD_DELAY_INIT_REP -# define LCD_DELAY_INIT_REP 64 /**< delay in micro seconds after initialization command repeated */ -#endif -#ifndef LCD_DELAY_INIT_4BIT -# define LCD_DELAY_INIT_4BIT 64 /**< delay in micro seconds after setting 4-bit mode */ -#endif -#ifndef LCD_DELAY_BUSY_FLAG -# define LCD_DELAY_BUSY_FLAG 4 /**< time in micro seconds the address counter is updated after busy flag is cleared */ -#endif -#ifndef LCD_DELAY_ENABLE_PULSE -# define LCD_DELAY_ENABLE_PULSE 1 /**< enable signal pulse width in micro seconds */ -#endif - -/** - * @name Definitions for LCD command instructions - * The constants define the various LCD controller instructions which can be passed to the - * function lcd_command(), see HD44780 data sheet for a complete description. - */ - -/* instruction register bit positions, see HD44780U data sheet */ -#define LCD_CLR 0 /* DB0: clear display */ -#define LCD_HOME 1 /* DB1: return to home position */ -#define LCD_ENTRY_MODE 2 /* DB2: set entry mode */ -#define LCD_ENTRY_INC 1 /* DB1: 1=increment, 0=decrement */ -#define LCD_ENTRY_SHIFT 0 /* DB2: 1=display shift on */ -#define LCD_ON 3 /* DB3: turn lcd/cursor on */ -#define LCD_ON_DISPLAY 2 /* DB2: turn display on */ -#define LCD_ON_CURSOR 1 /* DB1: turn cursor on */ -#define LCD_ON_BLINK 0 /* DB0: blinking cursor ? */ -#define LCD_MOVE 4 /* DB4: move cursor/display */ -#define LCD_MOVE_DISP 3 /* DB3: move display (0-> cursor) ? */ -#define LCD_MOVE_RIGHT 2 /* DB2: move right (0-> left) ? */ -#define LCD_FUNCTION 5 /* DB5: function set */ -#define LCD_FUNCTION_8BIT 4 /* DB4: set 8BIT mode (0->4BIT mode) */ -#define LCD_FUNCTION_2LINES 3 /* DB3: two lines (0->one line) */ -#define LCD_FUNCTION_10DOTS 2 /* DB2: 5x10 font (0->5x7 font) */ -#define LCD_CGRAM 6 /* DB6: set CG RAM address */ -#define LCD_DDRAM 7 /* DB7: set DD RAM address */ -#define LCD_BUSY 7 /* DB7: LCD is busy */ - -/* set entry mode: display shift on/off, dec/inc cursor move direction */ -#define LCD_ENTRY_DEC 0x04 /* display shift off, dec cursor move dir */ -#define LCD_ENTRY_DEC_SHIFT 0x05 /* display shift on, dec cursor move dir */ -#define LCD_ENTRY_INC_ 0x06 /* display shift off, inc cursor move dir */ -#define LCD_ENTRY_INC_SHIFT 0x07 /* display shift on, inc cursor move dir */ - -/* display on/off, cursor on/off, blinking char at cursor position */ -#define LCD_DISP_OFF 0x08 /* display off */ -#define LCD_DISP_ON 0x0C /* display on, cursor off */ -#define LCD_DISP_ON_BLINK 0x0D /* display on, cursor off, blink char */ -#define LCD_DISP_ON_CURSOR 0x0E /* display on, cursor on */ -#define LCD_DISP_ON_CURSOR_BLINK 0x0F /* display on, cursor on, blink char */ - -/* move cursor/shift display */ -#define LCD_MOVE_CURSOR_LEFT 0x10 /* move cursor left (decrement) */ -#define LCD_MOVE_CURSOR_RIGHT 0x14 /* move cursor right (increment) */ -#define LCD_MOVE_DISP_LEFT 0x18 /* shift display left */ -#define LCD_MOVE_DISP_RIGHT 0x1C /* shift display right */ - -/* function set: set interface data length and number of display lines */ -#define LCD_FUNCTION_4BIT_1LINE 0x20 /* 4-bit interface, single line, 5x7 dots */ -#define LCD_FUNCTION_4BIT_2LINES 0x28 /* 4-bit interface, dual line, 5x7 dots */ -#define LCD_FUNCTION_8BIT_1LINE 0x30 /* 8-bit interface, single line, 5x7 dots */ -#define LCD_FUNCTION_8BIT_2LINES 0x38 /* 8-bit interface, dual line, 5x7 dots */ - -#define LCD_MODE_DEFAULT ((1 << LCD_ENTRY_MODE) | (1 << LCD_ENTRY_INC)) - -/** - * @name Functions - */ - -/** - @brief Initialize display and select type of cursor - @param dispAttr \b LCD_DISP_OFF display off\n - \b LCD_DISP_ON display on, cursor off\n - \b LCD_DISP_ON_CURSOR display on, cursor on\n - \b LCD_DISP_ON_CURSOR_BLINK display on, cursor on flashing - @return none -*/ -extern void lcd_init(uint8_t dispAttr); - -/** - @brief Clear display and set cursor to home position - @return none -*/ -extern void lcd_clrscr(void); - -/** - @brief Set cursor to home position - @return none -*/ -extern void lcd_home(void); - -/** - @brief Set cursor to specified position - - @param x horizontal position\n (0: left most position) - @param y vertical position\n (0: first line) - @return none -*/ -extern void lcd_gotoxy(uint8_t x, uint8_t y); - -/** - @brief Display character at current cursor position - @param c character to be displayed - @return none -*/ -extern void lcd_putc(char c); - -/** - @brief Display string without auto linefeed - @param s string to be displayed - @return none -*/ -extern void lcd_puts(const char *s); - -/** - @brief Display string from program memory without auto linefeed - @param progmem_s string from program memory be be displayed - @return none - @see lcd_puts_P -*/ -extern void lcd_puts_p(const char *progmem_s); - -/** - @brief Send LCD controller instruction command - @param cmd instruction to send to LCD controller, see HD44780 data sheet - @return none -*/ -extern void lcd_command(uint8_t cmd); - -/** - @brief Send data byte to LCD controller - - Similar to lcd_putc(), but without interpreting LF - @param data byte to send to LCD controller, see HD44780 data sheet - @return none -*/ -extern void lcd_data(uint8_t data); - -/** - @brief macros for automatically storing string constant in program memory -*/ -#define lcd_puts_P(__s) lcd_puts_p(PSTR(__s)) - -/**@}*/ diff --git a/drivers/avr/i2c_master.c b/drivers/avr/i2c_master.c deleted file mode 100644 index 2773e00778..0000000000 --- a/drivers/avr/i2c_master.c +++ /dev/null @@ -1,241 +0,0 @@ -/* Copyright (C) 2019 Elia Ritterbusch - + - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -/* Library made by: g4lvanix - * GitHub repository: https://github.com/g4lvanix/I2C-master-lib - */ - -#include -#include - -#include "i2c_master.h" -#include "timer.h" -#include "wait.h" - -#ifndef F_SCL -# define F_SCL 400000UL // SCL frequency -#endif - -#ifndef I2C_START_RETRY_COUNT -# define I2C_START_RETRY_COUNT 20 -#endif // I2C_START_RETRY_COUNT - -#define TWBR_val (((F_CPU / F_SCL) - 16) / 2) - -#define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) - -void i2c_init(void) { - TWSR = 0; /* no prescaler */ - TWBR = (uint8_t)TWBR_val; - -#ifdef __AVR_ATmega32A__ - // set pull-up resistors on I2C bus pins - PORTC |= 0b11; - - // enable TWI (two-wire interface) - TWCR |= (1 << TWEN); - - // enable TWI interrupt and slave address ACK - TWCR |= (1 << TWIE); - TWCR |= (1 << TWEA); -#endif -} - -static i2c_status_t i2c_start_impl(uint8_t address, uint16_t timeout) { - // reset TWI control register - TWCR = 0; - // transmit START condition - TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); - - uint16_t timeout_timer = timer_read(); - while (!(TWCR & (1 << TWINT))) { - if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { - return I2C_STATUS_TIMEOUT; - } - } - - // check if the start condition was successfully transmitted - if (((TW_STATUS & 0xF8) != TW_START) && ((TW_STATUS & 0xF8) != TW_REP_START)) { - return I2C_STATUS_ERROR; - } - - // load slave address into data register - TWDR = address; - // start transmission of address - TWCR = (1 << TWINT) | (1 << TWEN); - - timeout_timer = timer_read(); - while (!(TWCR & (1 << TWINT))) { - if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { - return I2C_STATUS_TIMEOUT; - } - } - - // check if the device has acknowledged the READ / WRITE mode - uint8_t twst = TW_STATUS & 0xF8; - if ((twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK)) { - return I2C_STATUS_ERROR; - } - - return I2C_STATUS_SUCCESS; -} - -i2c_status_t i2c_start(uint8_t address, uint16_t timeout) { - // Retry i2c_start_impl a bunch times in case the remote side has interrupts disabled. - uint16_t timeout_timer = timer_read(); - uint16_t time_slice = MAX(1, (timeout == (I2C_TIMEOUT_INFINITE)) ? 5 : (timeout / (I2C_START_RETRY_COUNT))); // if it's infinite, wait 1ms between attempts, otherwise split up the entire timeout into the number of retries - i2c_status_t status; - do { - status = i2c_start_impl(address, time_slice); - } while ((status < 0) && ((timeout == I2C_TIMEOUT_INFINITE) || (timer_elapsed(timeout_timer) < timeout))); - return status; -} - -i2c_status_t i2c_write(uint8_t data, uint16_t timeout) { - // load data into data register - TWDR = data; - // start transmission of data - TWCR = (1 << TWINT) | (1 << TWEN); - - uint16_t timeout_timer = timer_read(); - while (!(TWCR & (1 << TWINT))) { - if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { - return I2C_STATUS_TIMEOUT; - } - } - - if ((TW_STATUS & 0xF8) != TW_MT_DATA_ACK) { - return I2C_STATUS_ERROR; - } - - return I2C_STATUS_SUCCESS; -} - -int16_t i2c_read_ack(uint16_t timeout) { - // start TWI module and acknowledge data after reception - TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA); - - uint16_t timeout_timer = timer_read(); - while (!(TWCR & (1 << TWINT))) { - if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { - return I2C_STATUS_TIMEOUT; - } - } - - // return received data from TWDR - return TWDR; -} - -int16_t i2c_read_nack(uint16_t timeout) { - // start receiving without acknowledging reception - TWCR = (1 << TWINT) | (1 << TWEN); - - uint16_t timeout_timer = timer_read(); - while (!(TWCR & (1 << TWINT))) { - if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { - return I2C_STATUS_TIMEOUT; - } - } - - // return received data from TWDR - return TWDR; -} - -i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout) { - i2c_status_t status = i2c_start(address | I2C_WRITE, timeout); - - for (uint16_t i = 0; i < length && status >= 0; i++) { - status = i2c_write(data[i], timeout); - } - - i2c_stop(); - - return status; -} - -i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) { - i2c_status_t status = i2c_start(address | I2C_READ, timeout); - - for (uint16_t i = 0; i < (length - 1) && status >= 0; i++) { - status = i2c_read_ack(timeout); - if (status >= 0) { - data[i] = status; - } - } - - if (status >= 0) { - status = i2c_read_nack(timeout); - if (status >= 0) { - data[(length - 1)] = status; - } - } - - i2c_stop(); - - return (status < 0) ? status : I2C_STATUS_SUCCESS; -} - -i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) { - i2c_status_t status = i2c_start(devaddr | 0x00, timeout); - if (status >= 0) { - status = i2c_write(regaddr, timeout); - - for (uint16_t i = 0; i < length && status >= 0; i++) { - status = i2c_write(data[i], timeout); - } - } - - i2c_stop(); - - return status; -} - -i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) { - i2c_status_t status = i2c_start(devaddr, timeout); - if (status < 0) { - goto error; - } - - status = i2c_write(regaddr, timeout); - if (status < 0) { - goto error; - } - - status = i2c_start(devaddr | 0x01, timeout); - - for (uint16_t i = 0; i < (length - 1) && status >= 0; i++) { - status = i2c_read_ack(timeout); - if (status >= 0) { - data[i] = status; - } - } - - if (status >= 0) { - status = i2c_read_nack(timeout); - if (status >= 0) { - data[(length - 1)] = status; - } - } - -error: - i2c_stop(); - - return (status < 0) ? status : I2C_STATUS_SUCCESS; -} - -void i2c_stop(void) { - // transmit STOP condition - TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO); -} diff --git a/drivers/avr/i2c_master.h b/drivers/avr/i2c_master.h deleted file mode 100644 index e5af73364b..0000000000 --- a/drivers/avr/i2c_master.h +++ /dev/null @@ -1,43 +0,0 @@ -/* Copyright (C) 2019 Elia Ritterbusch - + - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -/* Library made by: g4lvanix - * GitHub repository: https://github.com/g4lvanix/I2C-master-lib - */ - -#pragma once - -#define I2C_READ 0x01 -#define I2C_WRITE 0x00 - -typedef int16_t i2c_status_t; - -#define I2C_STATUS_SUCCESS (0) -#define I2C_STATUS_ERROR (-1) -#define I2C_STATUS_TIMEOUT (-2) - -#define I2C_TIMEOUT_IMMEDIATE (0) -#define I2C_TIMEOUT_INFINITE (0xFFFF) - -void i2c_init(void); -i2c_status_t i2c_start(uint8_t address, uint16_t timeout); -i2c_status_t i2c_write(uint8_t data, uint16_t timeout); -int16_t i2c_read_ack(uint16_t timeout); -int16_t i2c_read_nack(uint16_t timeout); -i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout); -i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout); -i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout); -i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); -void i2c_stop(void); diff --git a/drivers/avr/i2c_slave.c b/drivers/avr/i2c_slave.c deleted file mode 100644 index 2907f164c0..0000000000 --- a/drivers/avr/i2c_slave.c +++ /dev/null @@ -1,111 +0,0 @@ -/* Copyright (C) 2019 Elia Ritterbusch - + - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -/* Library made by: g4lvanix - * GitHub repository: https://github.com/g4lvanix/I2C-slave-lib - */ - -#include -#include -#include -#include -#include - -#include "i2c_slave.h" - -#if defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS) -# include "transactions.h" - -static volatile bool is_callback_executor = false; -#endif // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS) - -volatile uint8_t i2c_slave_reg[I2C_SLAVE_REG_COUNT]; - -static volatile uint8_t buffer_address; -static volatile bool slave_has_register_set = false; - -void i2c_slave_init(uint8_t address) { - // load address into TWI address register - TWAR = address; - // set the TWCR to enable address matching and enable TWI, clear TWINT, enable TWI interrupt - TWCR = (1 << TWIE) | (1 << TWEA) | (1 << TWINT) | (1 << TWEN); -} - -void i2c_slave_stop(void) { - // clear acknowledge and enable bits - TWCR &= ~((1 << TWEA) | (1 << TWEN)); -} - -ISR(TWI_vect) { - uint8_t ack = 1; - - switch (TW_STATUS) { - case TW_SR_SLA_ACK: - // The device is now a slave receiver - slave_has_register_set = false; -#if defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS) - is_callback_executor = false; -#endif // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS) - break; - - case TW_SR_DATA_ACK: - // This device is a slave receiver and has received data - // First byte is the location then the bytes will be writen in buffer with auto-increment - if (!slave_has_register_set) { - buffer_address = TWDR; - - if (buffer_address >= I2C_SLAVE_REG_COUNT) { // address out of bounds dont ack - ack = 0; - buffer_address = 0; - } - slave_has_register_set = true; // address has been received now fill in buffer - -#if defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS) - // Work out if we're attempting to execute a callback - is_callback_executor = buffer_address == split_transaction_table[I2C_EXECUTE_CALLBACK].initiator2target_offset; -#endif // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS) - } else { - i2c_slave_reg[buffer_address] = TWDR; - buffer_address++; - -#if defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS) - // If we're intending to execute a transaction callback, do so, as we've just received the transaction ID - if (is_callback_executor) { - split_transaction_desc_t *trans = &split_transaction_table[split_shmem->transaction_id]; - if (trans->slave_callback) { - trans->slave_callback(trans->initiator2target_buffer_size, split_trans_initiator2target_buffer(trans), trans->target2initiator_buffer_size, split_trans_target2initiator_buffer(trans)); - } - } -#endif // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS) - } - break; - - case TW_ST_SLA_ACK: - case TW_ST_DATA_ACK: - // This device is a slave transmitter and master has requested data - TWDR = i2c_slave_reg[buffer_address]; - buffer_address++; - break; - - case TW_BUS_ERROR: - // We got an error, reset i2c - TWCR = 0; - default: - break; - } - - // Reset i2c state machine to be ready for next interrupt - TWCR |= (1 << TWIE) | (1 << TWINT) | (ack << TWEA) | (1 << TWEN); -} diff --git a/drivers/avr/i2c_slave.h b/drivers/avr/i2c_slave.h deleted file mode 100644 index a8647c9da3..0000000000 --- a/drivers/avr/i2c_slave.h +++ /dev/null @@ -1,41 +0,0 @@ -/* Copyright (C) 2019 Elia Ritterbusch - + - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -/* Library made by: g4lvanix - * GitHub repository: https://github.com/g4lvanix/I2C-slave-lib - - Info: Inititate the library by giving the required address. - Read or write to the necessary buffer according to the opperation. - */ - -#pragma once - -#ifndef I2C_SLAVE_REG_COUNT - -# if defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS) -# include "transport.h" -# define I2C_SLAVE_REG_COUNT sizeof(split_shared_memory_t) -# else // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS) -# define I2C_SLAVE_REG_COUNT 30 -# endif // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS) - -#endif // I2C_SLAVE_REG_COUNT - -_Static_assert(I2C_SLAVE_REG_COUNT < 256, "I2C target registers must be single byte"); - -extern volatile uint8_t i2c_slave_reg[I2C_SLAVE_REG_COUNT]; - -void i2c_slave_init(uint8_t address); -void i2c_slave_stop(void); diff --git a/drivers/avr/serial.c b/drivers/avr/serial.c deleted file mode 100644 index 9a7345a53d..0000000000 --- a/drivers/avr/serial.c +++ /dev/null @@ -1,529 +0,0 @@ -/* - * WARNING: be careful changing this code, it is very timing dependent - * - * 2018-10-28 checked - * avr-gcc 4.9.2 - * avr-gcc 5.4.0 - * avr-gcc 7.3.0 - */ - -#ifndef F_CPU -# define F_CPU 16000000 -#endif - -#include -#include -#include -#include -#include -#include "serial.h" - -#ifdef SOFT_SERIAL_PIN - -# if !(defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__)) -# error serial.c is not supported for the currently selected MCU -# endif -// if using ATmega32U4/2, AT90USBxxx I2C, can not use PD0 and PD1 in soft serial. -# if defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) -# if defined(USE_AVR_I2C) && (SOFT_SERIAL_PIN == D0 || SOFT_SERIAL_PIN == D1) -# error Using I2C, so can not use PD0, PD1 -# endif -# endif -// PD0..PD3, common config -# if SOFT_SERIAL_PIN == D0 -# define EIMSK_BIT _BV(INT0) -# define EICRx_BIT (~(_BV(ISC00) | _BV(ISC01))) -# define SERIAL_PIN_INTERRUPT INT0_vect -# define EICRx EICRA -# elif SOFT_SERIAL_PIN == D1 -# define EIMSK_BIT _BV(INT1) -# define EICRx_BIT (~(_BV(ISC10) | _BV(ISC11))) -# define SERIAL_PIN_INTERRUPT INT1_vect -# define EICRx EICRA -# elif SOFT_SERIAL_PIN == D2 -# define EIMSK_BIT _BV(INT2) -# define EICRx_BIT (~(_BV(ISC20) | _BV(ISC21))) -# define SERIAL_PIN_INTERRUPT INT2_vect -# define EICRx EICRA -# elif SOFT_SERIAL_PIN == D3 -# define EIMSK_BIT _BV(INT3) -# define EICRx_BIT (~(_BV(ISC30) | _BV(ISC31))) -# define SERIAL_PIN_INTERRUPT INT3_vect -# define EICRx EICRA -# endif - -// ATmegaxxU2/AT90USB162 specific config -# if defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || defined(__AVR_AT90USB162__) -// PD4(INT5), PD6(INT6), PD7(INT7), PC7(INT4) -# if SOFT_SERIAL_PIN == D4 -# define EIMSK_BIT _BV(INT5) -# define EICRx_BIT (~(_BV(ISC50) | _BV(ISC51))) -# define SERIAL_PIN_INTERRUPT INT5_vect -# define EICRx EICRB -# elif SOFT_SERIAL_PIN == D6 -# define EIMSK_BIT _BV(INT6) -# define EICRx_BIT (~(_BV(ISC60) | _BV(ISC61))) -# define SERIAL_PIN_INTERRUPT INT6_vect -# define EICRx EICRB -# elif SOFT_SERIAL_PIN == D7 -# define EIMSK_BIT _BV(INT7) -# define EICRx_BIT (~(_BV(ISC70) | _BV(ISC71))) -# define SERIAL_PIN_INTERRUPT INT7_vect -# define EICRx EICRB -# elif SOFT_SERIAL_PIN == C7 -# define EIMSK_BIT _BV(INT4) -# define EICRx_BIT (~(_BV(ISC40) | _BV(ISC41))) -# define SERIAL_PIN_INTERRUPT INT4_vect -# define EICRx EICRB -# endif -# endif - -// ATmegaxxU4 specific config -# if defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) -// PE6(INT6) -# if SOFT_SERIAL_PIN == E6 -# define EIMSK_BIT _BV(INT6) -# define EICRx_BIT (~(_BV(ISC60) | _BV(ISC61))) -# define SERIAL_PIN_INTERRUPT INT6_vect -# define EICRx EICRB -# endif -# endif - -// AT90USBxxx specific config -# if defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) -// PE4..PE7(INT4..INT7) -# if SOFT_SERIAL_PIN == E4 -# define EIMSK_BIT _BV(INT4) -# define EICRx_BIT (~(_BV(ISC40) | _BV(ISC41))) -# define SERIAL_PIN_INTERRUPT INT4_vect -# define EICRx EICRB -# elif SOFT_SERIAL_PIN == E5 -# define EIMSK_BIT _BV(INT5) -# define EICRx_BIT (~(_BV(ISC50) | _BV(ISC51))) -# define SERIAL_PIN_INTERRUPT INT5_vect -# define EICRx EICRB -# elif SOFT_SERIAL_PIN == E6 -# define EIMSK_BIT _BV(INT6) -# define EICRx_BIT (~(_BV(ISC60) | _BV(ISC61))) -# define SERIAL_PIN_INTERRUPT INT6_vect -# define EICRx EICRB -# elif SOFT_SERIAL_PIN == E7 -# define EIMSK_BIT _BV(INT7) -# define EICRx_BIT (~(_BV(ISC70) | _BV(ISC71))) -# define SERIAL_PIN_INTERRUPT INT7_vect -# define EICRx EICRB -# endif -# endif - -# ifndef SERIAL_PIN_INTERRUPT -# error invalid SOFT_SERIAL_PIN value -# endif - -# define setPinInputHigh(pin) (DDRx_ADDRESS(pin) &= ~_BV((pin)&0xF), PORTx_ADDRESS(pin) |= _BV((pin)&0xF)) -# define setPinOutput(pin) (DDRx_ADDRESS(pin) |= _BV((pin)&0xF)) -# define writePinHigh(pin) (PORTx_ADDRESS(pin) |= _BV((pin)&0xF)) -# define writePinLow(pin) (PORTx_ADDRESS(pin) &= ~_BV((pin)&0xF)) -# define readPin(pin) ((bool)(PINx_ADDRESS(pin) & _BV((pin)&0xF))) - -# define ALWAYS_INLINE __attribute__((always_inline)) -# define NO_INLINE __attribute__((noinline)) -# define _delay_sub_us(x) __builtin_avr_delay_cycles(x) - -// parity check -# define ODD_PARITY 1 -# define EVEN_PARITY 0 -# define PARITY EVEN_PARITY - -# ifdef SERIAL_DELAY -// custom setup in config.h -// #define TID_SEND_ADJUST 2 -// #define SERIAL_DELAY 6 // micro sec -// #define READ_WRITE_START_ADJUST 30 // cycles -// #define READ_WRITE_WIDTH_ADJUST 8 // cycles -# else -// ============ Standard setups ============ - -# ifndef SELECT_SOFT_SERIAL_SPEED -# define SELECT_SOFT_SERIAL_SPEED 1 -// 0: about 189kbps (Experimental only) -// 1: about 137kbps (default) -// 2: about 75kbps -// 3: about 39kbps -// 4: about 26kbps -// 5: about 20kbps -# endif - -# if __GNUC__ < 6 -# define TID_SEND_ADJUST 14 -# else -# define TID_SEND_ADJUST 2 -# endif - -# if SELECT_SOFT_SERIAL_SPEED == 0 -// Very High speed -# define SERIAL_DELAY 4 // micro sec -# if __GNUC__ < 6 -# define READ_WRITE_START_ADJUST 33 // cycles -# define READ_WRITE_WIDTH_ADJUST 3 // cycles -# else -# define READ_WRITE_START_ADJUST 34 // cycles -# define READ_WRITE_WIDTH_ADJUST 7 // cycles -# endif -# elif SELECT_SOFT_SERIAL_SPEED == 1 -// High speed -# define SERIAL_DELAY 6 // micro sec -# if __GNUC__ < 6 -# define READ_WRITE_START_ADJUST 30 // cycles -# define READ_WRITE_WIDTH_ADJUST 3 // cycles -# else -# define READ_WRITE_START_ADJUST 33 // cycles -# define READ_WRITE_WIDTH_ADJUST 7 // cycles -# endif -# elif SELECT_SOFT_SERIAL_SPEED == 2 -// Middle speed -# define SERIAL_DELAY 12 // micro sec -# define READ_WRITE_START_ADJUST 30 // cycles -# if __GNUC__ < 6 -# define READ_WRITE_WIDTH_ADJUST 3 // cycles -# else -# define READ_WRITE_WIDTH_ADJUST 7 // cycles -# endif -# elif SELECT_SOFT_SERIAL_SPEED == 3 -// Low speed -# define SERIAL_DELAY 24 // micro sec -# define READ_WRITE_START_ADJUST 30 // cycles -# if __GNUC__ < 6 -# define READ_WRITE_WIDTH_ADJUST 3 // cycles -# else -# define READ_WRITE_WIDTH_ADJUST 7 // cycles -# endif -# elif SELECT_SOFT_SERIAL_SPEED == 4 -// Very Low speed -# define SERIAL_DELAY 36 // micro sec -# define READ_WRITE_START_ADJUST 30 // cycles -# if __GNUC__ < 6 -# define READ_WRITE_WIDTH_ADJUST 3 // cycles -# else -# define READ_WRITE_WIDTH_ADJUST 7 // cycles -# endif -# elif SELECT_SOFT_SERIAL_SPEED == 5 -// Ultra Low speed -# define SERIAL_DELAY 48 // micro sec -# define READ_WRITE_START_ADJUST 30 // cycles -# if __GNUC__ < 6 -# define READ_WRITE_WIDTH_ADJUST 3 // cycles -# else -# define READ_WRITE_WIDTH_ADJUST 7 // cycles -# endif -# else -# error invalid SELECT_SOFT_SERIAL_SPEED value -# endif /* SELECT_SOFT_SERIAL_SPEED */ -# endif /* SERIAL_DELAY */ - -# define SERIAL_DELAY_HALF1 (SERIAL_DELAY / 2) -# define SERIAL_DELAY_HALF2 (SERIAL_DELAY - SERIAL_DELAY / 2) - -# define SLAVE_INT_WIDTH_US 1 -# define SLAVE_INT_ACK_WIDTH_UNIT 2 -# define SLAVE_INT_ACK_WIDTH 4 - -inline static void serial_delay(void) ALWAYS_INLINE; -inline static void serial_delay(void) { _delay_us(SERIAL_DELAY); } - -inline static void serial_delay_half1(void) ALWAYS_INLINE; -inline static void serial_delay_half1(void) { _delay_us(SERIAL_DELAY_HALF1); } - -inline static void serial_delay_half2(void) ALWAYS_INLINE; -inline static void serial_delay_half2(void) { _delay_us(SERIAL_DELAY_HALF2); } - -inline static void serial_output(void) ALWAYS_INLINE; -inline static void serial_output(void) { setPinOutput(SOFT_SERIAL_PIN); } - -// make the serial pin an input with pull-up resistor -inline static void serial_input_with_pullup(void) ALWAYS_INLINE; -inline static void serial_input_with_pullup(void) { setPinInputHigh(SOFT_SERIAL_PIN); } - -inline static uint8_t serial_read_pin(void) ALWAYS_INLINE; -inline static uint8_t serial_read_pin(void) { return !!readPin(SOFT_SERIAL_PIN); } - -inline static void serial_low(void) ALWAYS_INLINE; -inline static void serial_low(void) { writePinLow(SOFT_SERIAL_PIN); } - -inline static void serial_high(void) ALWAYS_INLINE; -inline static void serial_high(void) { writePinHigh(SOFT_SERIAL_PIN); } - -void soft_serial_initiator_init(void) { - serial_output(); - serial_high(); -} - -void soft_serial_target_init(void) { - serial_input_with_pullup(); - - // Enable INT0-INT7 - EIMSK |= EIMSK_BIT; - EICRx &= EICRx_BIT; -} - -// Used by the sender to synchronize timing with the reciver. -static void sync_recv(void) NO_INLINE; -static void sync_recv(void) { - for (uint8_t i = 0; i < SERIAL_DELAY * 5 && serial_read_pin(); i++) { - } - // This shouldn't hang if the target disconnects because the - // serial line will float to high if the target does disconnect. - while (!serial_read_pin()) - ; -} - -// Used by the reciver to send a synchronization signal to the sender. -static void sync_send(void) NO_INLINE; -static void sync_send(void) { - serial_low(); - serial_delay(); - serial_high(); -} - -// Reads a byte from the serial line -static uint8_t serial_read_chunk(uint8_t *pterrcount, uint8_t bit) NO_INLINE; -static uint8_t serial_read_chunk(uint8_t *pterrcount, uint8_t bit) { - uint8_t byte, i, p, pb; - - _delay_sub_us(READ_WRITE_START_ADJUST); - for (i = 0, byte = 0, p = PARITY; i < bit; i++) { - serial_delay_half1(); // read the middle of pulses - if (serial_read_pin()) { - byte = (byte << 1) | 1; - p ^= 1; - } else { - byte = (byte << 1) | 0; - p ^= 0; - } - _delay_sub_us(READ_WRITE_WIDTH_ADJUST); - serial_delay_half2(); - } - /* recive parity bit */ - serial_delay_half1(); // read the middle of pulses - pb = serial_read_pin(); - _delay_sub_us(READ_WRITE_WIDTH_ADJUST); - serial_delay_half2(); - - *pterrcount += (p != pb) ? 1 : 0; - - return byte; -} - -// Sends a byte with MSB ordering -void serial_write_chunk(uint8_t data, uint8_t bit) NO_INLINE; -void serial_write_chunk(uint8_t data, uint8_t bit) { - uint8_t b, p; - for (p = PARITY, b = 1 << (bit - 1); b; b >>= 1) { - if (data & b) { - serial_high(); - p ^= 1; - } else { - serial_low(); - p ^= 0; - } - serial_delay(); - } - /* send parity bit */ - if (p & 1) { - serial_high(); - } else { - serial_low(); - } - serial_delay(); - - serial_low(); // sync_send() / senc_recv() need raise edge -} - -static void serial_send_packet(uint8_t *buffer, uint8_t size) NO_INLINE; -static void serial_send_packet(uint8_t *buffer, uint8_t size) { - for (uint8_t i = 0; i < size; ++i) { - uint8_t data; - data = buffer[i]; - sync_send(); - serial_write_chunk(data, 8); - } -} - -static uint8_t serial_recive_packet(uint8_t *buffer, uint8_t size) NO_INLINE; -static uint8_t serial_recive_packet(uint8_t *buffer, uint8_t size) { - uint8_t pecount = 0; - for (uint8_t i = 0; i < size; ++i) { - uint8_t data; - sync_recv(); - data = serial_read_chunk(&pecount, 8); - buffer[i] = data; - } - return pecount == 0; -} - -inline static void change_sender2reciver(void) { - sync_send(); // 0 - serial_delay_half1(); // 1 - serial_low(); // 2 - serial_input_with_pullup(); // 2 - serial_delay_half1(); // 3 -} - -inline static void change_reciver2sender(void) { - sync_recv(); // 0 - serial_delay(); // 1 - serial_low(); // 3 - serial_output(); // 3 - serial_delay_half1(); // 4 -} - -static inline uint8_t nibble_bits_count(uint8_t bits) { - bits = (bits & 0x5) + (bits >> 1 & 0x5); - bits = (bits & 0x3) + (bits >> 2 & 0x3); - return bits; -} - -// interrupt handle to be used by the target device -ISR(SERIAL_PIN_INTERRUPT) { - // recive transaction table index - uint8_t tid, bits; - uint8_t pecount = 0; - sync_recv(); - bits = serial_read_chunk(&pecount, 8); - tid = bits >> 3; - bits = (bits & 7) != (nibble_bits_count(tid) & 7); - if (bits || pecount > 0 || tid > NUM_TOTAL_TRANSACTIONS) { - return; - } - serial_delay_half1(); - - serial_high(); // response step1 low->high - serial_output(); - _delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT * SLAVE_INT_ACK_WIDTH); - split_transaction_desc_t *trans = &split_transaction_table[tid]; - serial_low(); // response step2 ack high->low - - // If the transaction has a callback, we can execute it now - if (trans->slave_callback) { - trans->slave_callback(trans->initiator2target_buffer_size, split_trans_initiator2target_buffer(trans), trans->target2initiator_buffer_size, split_trans_target2initiator_buffer(trans)); - } - - // target send phase - if (trans->target2initiator_buffer_size > 0) serial_send_packet((uint8_t *)split_trans_target2initiator_buffer(trans), trans->target2initiator_buffer_size); - // target switch to input - change_sender2reciver(); - - // target recive phase - if (trans->initiator2target_buffer_size > 0) { - if (serial_recive_packet((uint8_t *)split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size)) { - *trans->status = TRANSACTION_ACCEPTED; - } else { - *trans->status = TRANSACTION_DATA_ERROR; - } - } else { - *trans->status = TRANSACTION_ACCEPTED; - } - - sync_recv(); // weit initiator output to high -} - -///////// -// start transaction by initiator -// -// int soft_serial_transaction(int sstd_index) -// -// Returns: -// TRANSACTION_END -// TRANSACTION_NO_RESPONSE -// TRANSACTION_DATA_ERROR -// this code is very time dependent, so we need to disable interrupts -int soft_serial_transaction(int sstd_index) { - if (sstd_index > NUM_TOTAL_TRANSACTIONS) return TRANSACTION_TYPE_ERROR; - split_transaction_desc_t *trans = &split_transaction_table[sstd_index]; - - if (!trans->status) return TRANSACTION_TYPE_ERROR; // not registered - - cli(); - - // signal to the target that we want to start a transaction - serial_output(); - serial_low(); - _delay_us(SLAVE_INT_WIDTH_US); - - // send transaction table index - int tid = (sstd_index << 3) | (7 & nibble_bits_count(sstd_index)); - sync_send(); - _delay_sub_us(TID_SEND_ADJUST); - serial_write_chunk(tid, 8); - serial_delay_half1(); - - // wait for the target response (step1 low->high) - serial_input_with_pullup(); - while (!serial_read_pin()) { - _delay_sub_us(2); - } - - // check if the target is present (step2 high->low) - for (int i = 0; serial_read_pin(); i++) { - if (i > SLAVE_INT_ACK_WIDTH + 1) { - // slave failed to pull the line low, assume not present - serial_output(); - serial_high(); - *trans->status = TRANSACTION_NO_RESPONSE; - sei(); - return TRANSACTION_NO_RESPONSE; - } - _delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT); - } - - // initiator recive phase - // if the target is present syncronize with it - if (trans->target2initiator_buffer_size > 0) { - if (!serial_recive_packet((uint8_t *)split_trans_target2initiator_buffer(trans), trans->target2initiator_buffer_size)) { - serial_output(); - serial_high(); - *trans->status = TRANSACTION_DATA_ERROR; - sei(); - return TRANSACTION_DATA_ERROR; - } - } - - // initiator switch to output - change_reciver2sender(); - - // initiator send phase - if (trans->initiator2target_buffer_size > 0) { - serial_send_packet((uint8_t *)split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size); - } - - // always, release the line when not in use - sync_send(); - - *trans->status = TRANSACTION_END; - sei(); - return TRANSACTION_END; -} - -int soft_serial_get_and_clean_status(int sstd_index) { - split_transaction_desc_t *trans = &split_transaction_table[sstd_index]; - cli(); - int retval = *trans->status; - *trans->status = 0; - ; - sei(); - return retval; -} -#endif - -// Helix serial.c history -// 2018-1-29 fork from let's split and add PD2, modify sync_recv() (#2308, bceffdefc) -// 2018-6-28 bug fix master to slave comm and speed up (#3255, 1038bbef4) -// (adjusted with avr-gcc 4.9.2) -// 2018-7-13 remove USE_SERIAL_PD2 macro (#3374, f30d6dd78) -// (adjusted with avr-gcc 4.9.2) -// 2018-8-11 add support multi-type transaction (#3608, feb5e4aae) -// (adjusted with avr-gcc 4.9.2) -// 2018-10-21 fix serial and RGB animation conflict (#4191, 4665e4fff) -// (adjusted with avr-gcc 7.3.0) -// 2018-10-28 re-adjust compiler depend value of delay (#4269, 8517f8a66) -// (adjusted with avr-gcc 5.4.0, 7.3.0) -// 2018-12-17 copy to TOP/quantum/split_common/ and remove backward compatibility code (#4669) diff --git a/drivers/avr/spi_master.c b/drivers/avr/spi_master.c deleted file mode 100644 index 4e8fd3bcdf..0000000000 --- a/drivers/avr/spi_master.c +++ /dev/null @@ -1,180 +0,0 @@ -/* Copyright 2020 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "spi_master.h" - -#include "timer.h" - -#if defined(__AVR_AT90USB162__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) -# define SPI_SCK_PIN B1 -# define SPI_MOSI_PIN B2 -# define SPI_MISO_PIN B3 -#elif defined(__AVR_ATmega32A__) -# define SPI_SCK_PIN B7 -# define SPI_MOSI_PIN B5 -# define SPI_MISO_PIN B6 -#elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) -# define SPI_SCK_PIN B5 -# define SPI_MOSI_PIN B3 -# define SPI_MISO_PIN B4 -#endif - -#ifndef SPI_TIMEOUT -# define SPI_TIMEOUT 100 -#endif - -static pin_t currentSlavePin = NO_PIN; -static uint8_t currentSlaveConfig = 0; -static bool currentSlave2X = false; - -void spi_init(void) { - writePinHigh(SPI_SS_PIN); - setPinOutput(SPI_SCK_PIN); - setPinOutput(SPI_MOSI_PIN); - setPinInput(SPI_MISO_PIN); - - SPCR = (_BV(SPE) | _BV(MSTR)); -} - -bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { - if (currentSlavePin != NO_PIN || slavePin == NO_PIN) { - return false; - } - - currentSlaveConfig = 0; - - if (lsbFirst) { - currentSlaveConfig |= _BV(DORD); - } - - switch (mode) { - case 1: - currentSlaveConfig |= _BV(CPHA); - break; - case 2: - currentSlaveConfig |= _BV(CPOL); - break; - case 3: - currentSlaveConfig |= (_BV(CPOL) | _BV(CPHA)); - break; - } - - uint16_t roundedDivisor = 1; - while (roundedDivisor < divisor) { - roundedDivisor <<= 1; - } - - switch (roundedDivisor) { - case 16: - currentSlaveConfig |= _BV(SPR0); - break; - case 64: - currentSlaveConfig |= _BV(SPR1); - break; - case 128: - currentSlaveConfig |= (_BV(SPR1) | _BV(SPR0)); - break; - case 2: - currentSlave2X = true; - break; - case 8: - currentSlave2X = true; - currentSlaveConfig |= _BV(SPR0); - break; - case 32: - currentSlave2X = true; - currentSlaveConfig |= _BV(SPR1); - break; - } - - SPCR |= currentSlaveConfig; - if (currentSlave2X) { - SPSR |= _BV(SPI2X); - } - currentSlavePin = slavePin; - setPinOutput(currentSlavePin); - writePinLow(currentSlavePin); - - return true; -} - -spi_status_t spi_write(uint8_t data) { - SPDR = data; - - uint16_t timeout_timer = timer_read(); - while (!(SPSR & _BV(SPIF))) { - if ((timer_read() - timeout_timer) >= SPI_TIMEOUT) { - return SPI_STATUS_TIMEOUT; - } - } - - return SPDR; -} - -spi_status_t spi_read() { - SPDR = 0x00; // Dummy - - uint16_t timeout_timer = timer_read(); - while (!(SPSR & _BV(SPIF))) { - if ((timer_read() - timeout_timer) >= SPI_TIMEOUT) { - return SPI_STATUS_TIMEOUT; - } - } - - return SPDR; -} - -spi_status_t spi_transmit(const uint8_t *data, uint16_t length) { - spi_status_t status; - - for (uint16_t i = 0; i < length; i++) { - status = spi_write(data[i]); - - if (status < 0) { - return status; - } - } - - return SPI_STATUS_SUCCESS; -} - -spi_status_t spi_receive(uint8_t *data, uint16_t length) { - spi_status_t status; - - for (uint16_t i = 0; i < length; i++) { - status = spi_read(); - - if (status >= 0) { - data[i] = status; - } else { - return status; - } - } - - return SPI_STATUS_SUCCESS; -} - -void spi_stop(void) { - if (currentSlavePin != NO_PIN) { - setPinOutput(currentSlavePin); - writePinHigh(currentSlavePin); - currentSlavePin = NO_PIN; - SPSR &= ~(_BV(SPI2X)); - SPCR &= ~(currentSlaveConfig); - currentSlaveConfig = 0; - currentSlave2X = false; - } -} diff --git a/drivers/avr/spi_master.h b/drivers/avr/spi_master.h deleted file mode 100644 index 8a30f47ae4..0000000000 --- a/drivers/avr/spi_master.h +++ /dev/null @@ -1,59 +0,0 @@ -/* Copyright 2020 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include - -#include "gpio.h" - -typedef int16_t spi_status_t; - -// Hardware SS pin is defined in the header so that user code can refer to it -#if defined(__AVR_AT90USB162__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) -# define SPI_SS_PIN B0 -#elif defined(__AVR_ATmega32A__) -# define SPI_SS_PIN B4 -#elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) -# define SPI_SS_PIN B2 -#endif - -#define SPI_STATUS_SUCCESS (0) -#define SPI_STATUS_ERROR (-1) -#define SPI_STATUS_TIMEOUT (-2) - -#define SPI_TIMEOUT_IMMEDIATE (0) -#define SPI_TIMEOUT_INFINITE (0xFFFF) - -#ifdef __cplusplus -extern "C" { -#endif -void spi_init(void); - -bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor); - -spi_status_t spi_write(uint8_t data); - -spi_status_t spi_read(void); - -spi_status_t spi_transmit(const uint8_t *data, uint16_t length); - -spi_status_t spi_receive(uint8_t *data, uint16_t length); - -void spi_stop(void); -#ifdef __cplusplus -} -#endif diff --git a/drivers/avr/ssd1306.c b/drivers/avr/ssd1306.c deleted file mode 100644 index 1a09a2bcb7..0000000000 --- a/drivers/avr/ssd1306.c +++ /dev/null @@ -1,319 +0,0 @@ -#ifdef SSD1306OLED - -# include "ssd1306.h" -# include "i2c.h" -# include -# include "print.h" -# include "glcdfont.c" -# ifdef PROTOCOL_LUFA -# include "lufa.h" -# endif -# include "sendchar.h" -# include "timer.h" - -struct CharacterMatrix display; - -// Set this to 1 to help diagnose early startup problems -// when testing power-on with ble. Turn it off otherwise, -// as the latency of printing most of the debug info messes -// with the matrix scan, causing keys to drop. -# define DEBUG_TO_SCREEN 0 - -// static uint16_t last_battery_update; -// static uint32_t vbat; -//#define BatteryUpdateInterval 10000 /* milliseconds */ -# define ScreenOffInterval 300000 /* milliseconds */ -# if DEBUG_TO_SCREEN -static uint8_t displaying; -# endif -static uint16_t last_flush; - -// Write command sequence. -// Returns true on success. -static inline bool _send_cmd1(uint8_t cmd) { - bool res = false; - - if (i2c_start_write(SSD1306_ADDRESS)) { - xprintf("failed to start write to %d\n", SSD1306_ADDRESS); - goto done; - } - - if (i2c_master_write(0x0 /* command byte follows */)) { - print("failed to write control byte\n"); - - goto done; - } - - if (i2c_master_write(cmd)) { - xprintf("failed to write command %d\n", cmd); - goto done; - } - res = true; -done: - i2c_master_stop(); - return res; -} - -// Write 2-byte command sequence. -// Returns true on success -static inline bool _send_cmd2(uint8_t cmd, uint8_t opr) { - if (!_send_cmd1(cmd)) { - return false; - } - return _send_cmd1(opr); -} - -// Write 3-byte command sequence. -// Returns true on success -static inline bool _send_cmd3(uint8_t cmd, uint8_t opr1, uint8_t opr2) { - if (!_send_cmd1(cmd)) { - return false; - } - if (!_send_cmd1(opr1)) { - return false; - } - return _send_cmd1(opr2); -} - -# define send_cmd1(c) \ - if (!_send_cmd1(c)) { \ - goto done; \ - } -# define send_cmd2(c, o) \ - if (!_send_cmd2(c, o)) { \ - goto done; \ - } -# define send_cmd3(c, o1, o2) \ - if (!_send_cmd3(c, o1, o2)) { \ - goto done; \ - } - -static void clear_display(void) { - matrix_clear(&display); - - // Clear all of the display bits (there can be random noise - // in the RAM on startup) - send_cmd3(PageAddr, 0, (DisplayHeight / 8) - 1); - send_cmd3(ColumnAddr, 0, DisplayWidth - 1); - - if (i2c_start_write(SSD1306_ADDRESS)) { - goto done; - } - if (i2c_master_write(0x40)) { - // Data mode - goto done; - } - for (uint8_t row = 0; row < MatrixRows; ++row) { - for (uint8_t col = 0; col < DisplayWidth; ++col) { - i2c_master_write(0); - } - } - - display.dirty = false; - -done: - i2c_master_stop(); -} - -# if DEBUG_TO_SCREEN -# undef sendchar -static int8_t capture_sendchar(uint8_t c) { - sendchar(c); - iota_gfx_write_char(c); - - if (!displaying) { - iota_gfx_flush(); - } - return 0; -} -# endif - -bool iota_gfx_init(void) { - bool success = false; - - send_cmd1(DisplayOff); - send_cmd2(SetDisplayClockDiv, 0x80); - send_cmd2(SetMultiPlex, DisplayHeight - 1); - - send_cmd2(SetDisplayOffset, 0); - - send_cmd1(SetStartLine | 0x0); - send_cmd2(SetChargePump, 0x14 /* Enable */); - send_cmd2(SetMemoryMode, 0 /* horizontal addressing */); - -# ifdef OLED_ROTATE180 - // the following Flip the display orientation 180 degrees - send_cmd1(SegRemap); - send_cmd1(ComScanInc); -# endif -# ifndef OLED_ROTATE180 - // Flips the display orientation 0 degrees - send_cmd1(SegRemap | 0x1); - send_cmd1(ComScanDec); -# endif - - send_cmd2(SetComPins, 0x2); - send_cmd2(SetContrast, 0x8f); - send_cmd2(SetPreCharge, 0xf1); - send_cmd2(SetVComDetect, 0x40); - send_cmd1(DisplayAllOnResume); - send_cmd1(NormalDisplay); - send_cmd1(DeActivateScroll); - send_cmd1(DisplayOn); - - send_cmd2(SetContrast, 0); // Dim - - clear_display(); - - success = true; - - iota_gfx_flush(); - -# if DEBUG_TO_SCREEN - print_set_sendchar(capture_sendchar); -# endif - -done: - return success; -} - -bool iota_gfx_off(void) { - bool success = false; - - send_cmd1(DisplayOff); - success = true; - -done: - return success; -} - -bool iota_gfx_on(void) { - bool success = false; - - send_cmd1(DisplayOn); - success = true; - -done: - return success; -} - -void matrix_write_char_inner(struct CharacterMatrix *matrix, uint8_t c) { - *matrix->cursor = c; - ++matrix->cursor; - - if (matrix->cursor - &matrix->display[0][0] == sizeof(matrix->display)) { - // We went off the end; scroll the display upwards by one line - memmove(&matrix->display[0], &matrix->display[1], MatrixCols * (MatrixRows - 1)); - matrix->cursor = &matrix->display[MatrixRows - 1][0]; - memset(matrix->cursor, ' ', MatrixCols); - } -} - -void matrix_write_char(struct CharacterMatrix *matrix, uint8_t c) { - matrix->dirty = true; - - if (c == '\n') { - // Clear to end of line from the cursor and then move to the - // start of the next line - uint8_t cursor_col = (matrix->cursor - &matrix->display[0][0]) % MatrixCols; - - while (cursor_col++ < MatrixCols) { - matrix_write_char_inner(matrix, ' '); - } - return; - } - - matrix_write_char_inner(matrix, c); -} - -void iota_gfx_write_char(uint8_t c) { matrix_write_char(&display, c); } - -void matrix_write(struct CharacterMatrix *matrix, const char *data) { - const char *end = data + strlen(data); - while (data < end) { - matrix_write_char(matrix, *data); - ++data; - } -} - -void iota_gfx_write(const char *data) { matrix_write(&display, data); } - -void matrix_write_P(struct CharacterMatrix *matrix, const char *data) { - while (true) { - uint8_t c = pgm_read_byte(data); - if (c == 0) { - return; - } - matrix_write_char(matrix, c); - ++data; - } -} - -void iota_gfx_write_P(const char *data) { matrix_write_P(&display, data); } - -void matrix_clear(struct CharacterMatrix *matrix) { - memset(matrix->display, ' ', sizeof(matrix->display)); - matrix->cursor = &matrix->display[0][0]; - matrix->dirty = true; -} - -void iota_gfx_clear_screen(void) { matrix_clear(&display); } - -void matrix_render(struct CharacterMatrix *matrix) { - last_flush = timer_read(); - iota_gfx_on(); -# if DEBUG_TO_SCREEN - ++displaying; -# endif - - // Move to the home position - send_cmd3(PageAddr, 0, MatrixRows - 1); - send_cmd3(ColumnAddr, 0, (MatrixCols * FontWidth) - 1); - - if (i2c_start_write(SSD1306_ADDRESS)) { - goto done; - } - if (i2c_master_write(0x40)) { - // Data mode - goto done; - } - - for (uint8_t row = 0; row < MatrixRows; ++row) { - for (uint8_t col = 0; col < MatrixCols; ++col) { - const uint8_t *glyph = font + (matrix->display[row][col] * (FontWidth - 1)); - - for (uint8_t glyphCol = 0; glyphCol < FontWidth - 1; ++glyphCol) { - uint8_t colBits = pgm_read_byte(glyph + glyphCol); - i2c_master_write(colBits); - } - - // 1 column of space between chars (it's not included in the glyph) - i2c_master_write(0); - } - } - - matrix->dirty = false; - -done: - i2c_master_stop(); -# if DEBUG_TO_SCREEN - --displaying; -# endif -} - -void iota_gfx_flush(void) { matrix_render(&display); } - -__attribute__((weak)) void iota_gfx_task_user(void) {} - -void iota_gfx_task(void) { - iota_gfx_task_user(); - - if (display.dirty) { - iota_gfx_flush(); - } - - if (timer_elapsed(last_flush) > ScreenOffInterval) { - iota_gfx_off(); - } -} -#endif diff --git a/drivers/avr/ssd1306.h b/drivers/avr/ssd1306.h deleted file mode 100644 index 6eecdcfaa4..0000000000 --- a/drivers/avr/ssd1306.h +++ /dev/null @@ -1,87 +0,0 @@ -#pragma once - -#include -#include -#include "config.h" - -enum ssd1306_cmds { - DisplayOff = 0xAE, - DisplayOn = 0xAF, - - SetContrast = 0x81, - DisplayAllOnResume = 0xA4, - - DisplayAllOn = 0xA5, - NormalDisplay = 0xA6, - InvertDisplay = 0xA7, - SetDisplayOffset = 0xD3, - SetComPins = 0xda, - SetVComDetect = 0xdb, - SetDisplayClockDiv = 0xD5, - SetPreCharge = 0xd9, - SetMultiPlex = 0xa8, - SetLowColumn = 0x00, - SetHighColumn = 0x10, - SetStartLine = 0x40, - - SetMemoryMode = 0x20, - ColumnAddr = 0x21, - PageAddr = 0x22, - - ComScanInc = 0xc0, - ComScanDec = 0xc8, - SegRemap = 0xa0, - SetChargePump = 0x8d, - ExternalVcc = 0x01, - SwitchCapVcc = 0x02, - - ActivateScroll = 0x2f, - DeActivateScroll = 0x2e, - SetVerticalScrollArea = 0xa3, - RightHorizontalScroll = 0x26, - LeftHorizontalScroll = 0x27, - VerticalAndRightHorizontalScroll = 0x29, - VerticalAndLeftHorizontalScroll = 0x2a, -}; - -// Controls the SSD1306 128x32 OLED display via i2c - -#ifndef SSD1306_ADDRESS -# define SSD1306_ADDRESS 0x3C -#endif - -#define DisplayHeight 32 -#define DisplayWidth 128 - -#define FontHeight 8 -#define FontWidth 6 - -#define MatrixRows (DisplayHeight / FontHeight) -#define MatrixCols (DisplayWidth / FontWidth) - -struct CharacterMatrix { - uint8_t display[MatrixRows][MatrixCols]; - uint8_t *cursor; - bool dirty; -}; - -extern struct CharacterMatrix display; - -bool iota_gfx_init(void); -void iota_gfx_task(void); -bool iota_gfx_off(void); -bool iota_gfx_on(void); -void iota_gfx_flush(void); -void iota_gfx_write_char(uint8_t c); -void iota_gfx_write(const char *data); -void iota_gfx_write_P(const char *data); -void iota_gfx_clear_screen(void); - -void iota_gfx_task_user(void); - -void matrix_clear(struct CharacterMatrix *matrix); -void matrix_write_char_inner(struct CharacterMatrix *matrix, uint8_t c); -void matrix_write_char(struct CharacterMatrix *matrix, uint8_t c); -void matrix_write(struct CharacterMatrix *matrix, const char *data); -void matrix_write_P(struct CharacterMatrix *matrix, const char *data); -void matrix_render(struct CharacterMatrix *matrix); diff --git a/drivers/avr/uart.c b/drivers/avr/uart.c deleted file mode 100644 index c6abcb6fe0..0000000000 --- a/drivers/avr/uart.c +++ /dev/null @@ -1,170 +0,0 @@ -/* UART Example for Teensy USB Development Board - * http://www.pjrc.com/teensy/ - * Copyright (c) 2009 PJRC.COM, LLC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -// Version 1.0: Initial Release -// Version 1.1: Add support for Teensy 2.0, minor optimizations - -#include -#include - -#include "uart.h" - -#if defined(__AVR_AT90USB162__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) -# define UDRn UDR1 -# define UBRRnL UBRR1L -# define UCSRnA UCSR1A -# define UCSRnB UCSR1B -# define UCSRnC UCSR1C -# define U2Xn U2X1 -# define RXENn RXEN1 -# define TXENn TXEN1 -# define RXCIEn RXCIE1 -# define UCSZn1 UCSZ11 -# define UCSZn0 UCSZ10 -# define UDRIEn UDRIE1 -# define USARTn_UDRE_vect USART1_UDRE_vect -# define USARTn_RX_vect USART1_RX_vect -#elif defined(__AVR_ATmega32A__) -# define UDRn UDR -# define UBRRnL UBRRL -# define UCSRnA UCSRA -# define UCSRnB UCSRB -# define UCSRnC UCSRC -# define U2Xn U2X -# define RXENn RXEN -# define TXENn TXEN -# define RXCIEn RXCIE -# define UCSZn1 UCSZ1 -# define UCSZn0 UCSZ0 -# define UDRIEn UDRIE -# define USARTn_UDRE_vect USART_UDRE_vect -# define USARTn_RX_vect USART_RX_vect -#elif defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) -# define UDRn UDR0 -# define UBRRnL UBRR0L -# define UCSRnA UCSR0A -# define UCSRnB UCSR0B -# define UCSRnC UCSR0C -# define U2Xn U2X0 -# define RXENn RXEN0 -# define TXENn TXEN0 -# define RXCIEn RXCIE0 -# define UCSZn1 UCSZ01 -# define UCSZn0 UCSZ00 -# define UDRIEn UDRIE0 -# define USARTn_UDRE_vect USART_UDRE_vect -# define USARTn_RX_vect USART_RX_vect -#endif - -// These buffers may be any size from 2 to 256 bytes. -#define RX_BUFFER_SIZE 64 -#define TX_BUFFER_SIZE 256 - -static volatile uint8_t tx_buffer[TX_BUFFER_SIZE]; -static volatile uint8_t tx_buffer_head; -static volatile uint8_t tx_buffer_tail; -static volatile uint8_t rx_buffer[RX_BUFFER_SIZE]; -static volatile uint8_t rx_buffer_head; -static volatile uint8_t rx_buffer_tail; - -// Initialize the UART -void uart_init(uint32_t baud) { - cli(); - UBRRnL = (F_CPU / 4 / baud - 1) / 2; - UCSRnA = (1 << U2Xn); - UCSRnB = (1 << RXENn) | (1 << TXENn) | (1 << RXCIEn); - UCSRnC = (1 << UCSZn1) | (1 << UCSZn0); - tx_buffer_head = tx_buffer_tail = 0; - rx_buffer_head = rx_buffer_tail = 0; - sei(); -} - -// Transmit a byte -void uart_putchar(uint8_t c) { - uint8_t i; - - i = tx_buffer_head + 1; - if (i >= TX_BUFFER_SIZE) i = 0; - // return immediately to avoid deadlock when interrupt is disabled(called from ISR) - if (tx_buffer_tail == i && (SREG & (1 << SREG_I)) == 0) return; - while (tx_buffer_tail == i) - ; // wait until space in buffer - // cli(); - tx_buffer[i] = c; - tx_buffer_head = i; - UCSRnB = (1 << RXENn) | (1 << TXENn) | (1 << RXCIEn) | (1 << UDRIEn); - // sei(); -} - -// Receive a byte -uint8_t uart_getchar(void) { - uint8_t c, i; - - while (rx_buffer_head == rx_buffer_tail) - ; // wait for character - i = rx_buffer_tail + 1; - if (i >= RX_BUFFER_SIZE) i = 0; - c = rx_buffer[i]; - rx_buffer_tail = i; - return c; -} - -// Return whether the number of bytes waiting in the receive buffer is nonzero. -// Call this before uart_getchar() to check if it will need -// to wait for a byte to arrive. -bool uart_available(void) { - uint8_t head, tail; - - head = rx_buffer_head; - tail = rx_buffer_tail; - if (head >= tail) return (head - tail) > 0; - return (RX_BUFFER_SIZE + head - tail) > 0; -} - -// Transmit Interrupt -ISR(USARTn_UDRE_vect) { - uint8_t i; - - if (tx_buffer_head == tx_buffer_tail) { - // buffer is empty, disable transmit interrupt - UCSRnB = (1 << RXENn) | (1 << TXENn) | (1 << RXCIEn); - } else { - i = tx_buffer_tail + 1; - if (i >= TX_BUFFER_SIZE) i = 0; - UDRn = tx_buffer[i]; - tx_buffer_tail = i; - } -} - -// Receive Interrupt -ISR(USARTn_RX_vect) { - uint8_t c, i; - - c = UDRn; - i = rx_buffer_head + 1; - if (i >= RX_BUFFER_SIZE) i = 0; - if (i != rx_buffer_tail) { - rx_buffer[i] = c; - rx_buffer_head = i; - } -} diff --git a/drivers/avr/uart.h b/drivers/avr/uart.h deleted file mode 100644 index 602eb3d8b0..0000000000 --- a/drivers/avr/uart.h +++ /dev/null @@ -1,35 +0,0 @@ -/* UART Example for Teensy USB Development Board - * http://www.pjrc.com/teensy/ - * Copyright (c) 2009 PJRC.COM, LLC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#pragma once - -#include -#include - -void uart_init(uint32_t baud); - -void uart_putchar(uint8_t c); - -uint8_t uart_getchar(void); - -bool uart_available(void); diff --git a/drivers/avr/ws2812.c b/drivers/avr/ws2812.c deleted file mode 100644 index 77c492cd4c..0000000000 --- a/drivers/avr/ws2812.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * light weight WS2812 lib V2.0b - * - * Controls WS2811/WS2812/WS2812B RGB-LEDs - * Author: Tim (cpldcpu@gmail.com) - * - * Jan 18th, 2014 v2.0b Initial Version - * Nov 29th, 2015 v2.3 Added SK6812RGBW support - * - * 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 . - */ -#include "ws2812.h" -#include -#include -#include - -#define pinmask(pin) (_BV((pin)&0xF)) - -/* - * Forward declare internal functions - * - * The functions take a byte-array and send to the data output as WS2812 bitstream. - * The length is the number of bytes to send - three per LED. - */ - -static inline void ws2812_sendarray_mask(uint8_t *data, uint16_t datlen, uint8_t masklo, uint8_t maskhi); - -void ws2812_setleds(LED_TYPE *ledarray, uint16_t number_of_leds) { - DDRx_ADDRESS(RGB_DI_PIN) |= pinmask(RGB_DI_PIN); - - uint8_t masklo = ~(pinmask(RGB_DI_PIN)) & PORTx_ADDRESS(RGB_DI_PIN); - uint8_t maskhi = pinmask(RGB_DI_PIN) | PORTx_ADDRESS(RGB_DI_PIN); - - ws2812_sendarray_mask((uint8_t *)ledarray, number_of_leds * sizeof(LED_TYPE), masklo, maskhi); - - _delay_us(WS2812_TRST_US); -} - -/* - This routine writes an array of bytes with RGB values to the Dataout pin - using the fast 800kHz clockless WS2811/2812 protocol. -*/ - -// Timing in ns -#define w_zeropulse 350 -#define w_onepulse 900 -#define w_totalperiod 1250 - -// Fixed cycles used by the inner loop -#define w_fixedlow 2 -#define w_fixedhigh 4 -#define w_fixedtotal 8 - -// Insert NOPs to match the timing, if possible -#define w_zerocycles (((F_CPU / 1000) * w_zeropulse) / 1000000) -#define w_onecycles (((F_CPU / 1000) * w_onepulse + 500000) / 1000000) -#define w_totalcycles (((F_CPU / 1000) * w_totalperiod + 500000) / 1000000) - -// w1_nops - nops between rising edge and falling edge - low -#if w_zerocycles >= w_fixedlow -# define w1_nops (w_zerocycles - w_fixedlow) -#else -# define w1_nops 0 -#endif - -// w2_nops - nops between fe low and fe high -#if w_onecycles >= (w_fixedhigh + w1_nops) -# define w2_nops (w_onecycles - w_fixedhigh - w1_nops) -#else -# define w2_nops 0 -#endif - -// w3_nops - nops to complete loop -#if w_totalcycles >= (w_fixedtotal + w1_nops + w2_nops) -# define w3_nops (w_totalcycles - w_fixedtotal - w1_nops - w2_nops) -#else -# define w3_nops 0 -#endif - -// The only critical timing parameter is the minimum pulse length of the "0" -// Warn or throw error if this timing can not be met with current F_CPU settings. -#define w_lowtime ((w1_nops + w_fixedlow) * 1000000) / (F_CPU / 1000) -#if w_lowtime > 550 -# error "Light_ws2812: Sorry, the clock speed is too low. Did you set F_CPU correctly?" -#elif w_lowtime > 450 -# warning "Light_ws2812: The timing is critical and may only work on WS2812B, not on WS2812(S)." -# warning "Please consider a higher clockspeed, if possible" -#endif - -#define w_nop1 "nop \n\t" -#define w_nop2 "rjmp .+0 \n\t" -#define w_nop4 w_nop2 w_nop2 -#define w_nop8 w_nop4 w_nop4 -#define w_nop16 w_nop8 w_nop8 - -static inline void ws2812_sendarray_mask(uint8_t *data, uint16_t datlen, uint8_t masklo, uint8_t maskhi) { - uint8_t curbyte, ctr, sreg_prev; - - sreg_prev = SREG; - cli(); - - while (datlen--) { - curbyte = (*data++); - - asm volatile(" ldi %0,8 \n\t" - "loop%=: \n\t" - " out %2,%3 \n\t" // '1' [01] '0' [01] - re -#if (w1_nops & 1) - w_nop1 -#endif -#if (w1_nops & 2) - w_nop2 -#endif -#if (w1_nops & 4) - w_nop4 -#endif -#if (w1_nops & 8) - w_nop8 -#endif -#if (w1_nops & 16) - w_nop16 -#endif - " sbrs %1,7 \n\t" // '1' [03] '0' [02] - " out %2,%4 \n\t" // '1' [--] '0' [03] - fe-low - " lsl %1 \n\t" // '1' [04] '0' [04] -#if (w2_nops & 1) - w_nop1 -#endif -#if (w2_nops & 2) - w_nop2 -#endif -#if (w2_nops & 4) - w_nop4 -#endif -#if (w2_nops & 8) - w_nop8 -#endif -#if (w2_nops & 16) - w_nop16 -#endif - " out %2,%4 \n\t" // '1' [+1] '0' [+1] - fe-high -#if (w3_nops & 1) - w_nop1 -#endif -#if (w3_nops & 2) - w_nop2 -#endif -#if (w3_nops & 4) - w_nop4 -#endif -#if (w3_nops & 8) - w_nop8 -#endif -#if (w3_nops & 16) - w_nop16 -#endif - - " dec %0 \n\t" // '1' [+2] '0' [+2] - " brne loop%=\n\t" // '1' [+3] '0' [+4] - : "=&d"(ctr) - : "r"(curbyte), "I"(_SFR_IO_ADDR(PORTx_ADDRESS(RGB_DI_PIN))), "r"(maskhi), "r"(masklo)); - } - - SREG = sreg_prev; -} diff --git a/drivers/avr/ws2812_i2c.c b/drivers/avr/ws2812_i2c.c deleted file mode 100644 index 1c332e24b6..0000000000 --- a/drivers/avr/ws2812_i2c.c +++ /dev/null @@ -1,27 +0,0 @@ -#include "ws2812.h" -#include "i2c_master.h" - -#ifdef RGBW -# error "RGBW not supported" -#endif - -#ifndef WS2812_ADDRESS -# define WS2812_ADDRESS 0xb0 -#endif - -#ifndef WS2812_TIMEOUT -# define WS2812_TIMEOUT 100 -#endif - -void ws2812_init(void) { i2c_init(); } - -// Setleds for standard RGB -void ws2812_setleds(LED_TYPE *ledarray, uint16_t leds) { - static bool s_init = false; - if (!s_init) { - ws2812_init(); - s_init = true; - } - - i2c_transmit(WS2812_ADDRESS, (uint8_t *)ledarray, sizeof(LED_TYPE) * leds, WS2812_TIMEOUT); -} diff --git a/drivers/chibios/analog.c b/drivers/chibios/analog.c deleted file mode 100644 index 8c476fcac2..0000000000 --- a/drivers/chibios/analog.c +++ /dev/null @@ -1,321 +0,0 @@ -/* Copyright 2019 Drew Mills - * - * 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 . - */ - -#include "quantum.h" -#include "analog.h" -#include -#include - -#if !HAL_USE_ADC -# error "You need to set HAL_USE_ADC to TRUE in your halconf.h to use the ADC." -#endif - -#if !STM32_ADC_USE_ADC1 && !STM32_ADC_USE_ADC2 && !STM32_ADC_USE_ADC3 && !STM32_ADC_USE_ADC4 -# error "You need to set one of the 'STM32_ADC_USE_ADCx' settings to TRUE in your mcuconf.h to use the ADC." -#endif - -#if STM32_ADC_DUAL_MODE -# error "STM32 ADC Dual Mode is not supported at this time." -#endif - -#if STM32_ADCV3_OVERSAMPLING -# error "STM32 ADCV3 Oversampling is not supported at this time." -#endif - -// Otherwise assume V3 -#if defined(STM32F0XX) || defined(STM32L0XX) -# define USE_ADCV1 -#elif defined(STM32F1XX) || defined(STM32F2XX) || defined(STM32F4XX) -# define USE_ADCV2 -#endif - -// BODGE to make v2 look like v1,3 and 4 -#ifdef USE_ADCV2 -# if !defined(ADC_SMPR_SMP_1P5) && defined(ADC_SAMPLE_3) -# define ADC_SMPR_SMP_1P5 ADC_SAMPLE_3 -# define ADC_SMPR_SMP_7P5 ADC_SAMPLE_15 -# define ADC_SMPR_SMP_13P5 ADC_SAMPLE_28 -# define ADC_SMPR_SMP_28P5 ADC_SAMPLE_56 -# define ADC_SMPR_SMP_41P5 ADC_SAMPLE_84 -# define ADC_SMPR_SMP_55P5 ADC_SAMPLE_112 -# define ADC_SMPR_SMP_71P5 ADC_SAMPLE_144 -# define ADC_SMPR_SMP_239P5 ADC_SAMPLE_480 -# endif - -# if !defined(ADC_SMPR_SMP_1P5) && defined(ADC_SAMPLE_1P5) -# define ADC_SMPR_SMP_1P5 ADC_SAMPLE_1P5 -# define ADC_SMPR_SMP_7P5 ADC_SAMPLE_7P5 -# define ADC_SMPR_SMP_13P5 ADC_SAMPLE_13P5 -# define ADC_SMPR_SMP_28P5 ADC_SAMPLE_28P5 -# define ADC_SMPR_SMP_41P5 ADC_SAMPLE_41P5 -# define ADC_SMPR_SMP_55P5 ADC_SAMPLE_55P5 -# define ADC_SMPR_SMP_71P5 ADC_SAMPLE_71P5 -# define ADC_SMPR_SMP_239P5 ADC_SAMPLE_239P5 -# endif - -// we still sample at 12bit, but scale down to the requested bit range -# define ADC_CFGR1_RES_12BIT 12 -# define ADC_CFGR1_RES_10BIT 10 -# define ADC_CFGR1_RES_8BIT 8 -# define ADC_CFGR1_RES_6BIT 6 -#endif - -/* User configurable ADC options */ -#ifndef ADC_COUNT -# if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F4XX) -# define ADC_COUNT 1 -# elif defined(STM32F3XX) -# define ADC_COUNT 4 -# else -# error "ADC_COUNT has not been set for this ARM microcontroller." -# endif -#endif - -#ifndef ADC_NUM_CHANNELS -# define ADC_NUM_CHANNELS 1 -#elif ADC_NUM_CHANNELS != 1 -# error "The ARM ADC implementation currently only supports reading one channel at a time." -#endif - -#ifndef ADC_BUFFER_DEPTH -# define ADC_BUFFER_DEPTH 1 -#endif - -// For more sampling rate options, look at hal_adc_lld.h in ChibiOS -#ifndef ADC_SAMPLING_RATE -# define ADC_SAMPLING_RATE ADC_SMPR_SMP_1P5 -#endif - -// Options are 12, 10, 8, and 6 bit. -#ifndef ADC_RESOLUTION -# ifdef ADC_CFGR_RES_10BITS // ADCv3, ADCv4 -# define ADC_RESOLUTION ADC_CFGR_RES_10BITS -# else // ADCv1, ADCv5, or the bodge for ADCv2 above -# define ADC_RESOLUTION ADC_CFGR1_RES_10BIT -# endif -#endif - -static ADCConfig adcCfg = {}; -static adcsample_t sampleBuffer[ADC_NUM_CHANNELS * ADC_BUFFER_DEPTH]; - -// Initialize to max number of ADCs, set to empty object to initialize all to false. -static bool adcInitialized[ADC_COUNT] = {}; - -// TODO: add back TR handling??? -static ADCConversionGroup adcConversionGroup = { - .circular = FALSE, - .num_channels = (uint16_t)(ADC_NUM_CHANNELS), -#if defined(USE_ADCV1) - .cfgr1 = ADC_CFGR1_CONT | ADC_RESOLUTION, - .smpr = ADC_SAMPLING_RATE, -#elif defined(USE_ADCV2) -# if !defined(STM32F1XX) - .cr2 = ADC_CR2_SWSTART, // F103 seem very unhappy with, F401 seems very unhappy without... -# endif - .smpr2 = ADC_SMPR2_SMP_AN0(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN1(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN2(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN3(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN4(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN5(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN6(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN7(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN8(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN9(ADC_SAMPLING_RATE), - .smpr1 = ADC_SMPR1_SMP_AN10(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN11(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN12(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN13(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN14(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN15(ADC_SAMPLING_RATE), -#else - .cfgr = ADC_CFGR_CONT | ADC_RESOLUTION, - .smpr = {ADC_SMPR1_SMP_AN0(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN1(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN2(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN3(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN4(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN5(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN6(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN7(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN8(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN9(ADC_SAMPLING_RATE), ADC_SMPR2_SMP_AN10(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN11(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN12(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN13(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN14(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN15(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN16(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN17(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN18(ADC_SAMPLING_RATE)}, -#endif -}; - -// clang-format off -__attribute__((weak)) adc_mux pinToMux(pin_t pin) { - switch (pin) { -#if defined(STM32F0XX) - case A0: return TO_MUX( ADC_CHSELR_CHSEL0, 0 ); - case A1: return TO_MUX( ADC_CHSELR_CHSEL1, 0 ); - case A2: return TO_MUX( ADC_CHSELR_CHSEL2, 0 ); - case A3: return TO_MUX( ADC_CHSELR_CHSEL3, 0 ); - case A4: return TO_MUX( ADC_CHSELR_CHSEL4, 0 ); - case A5: return TO_MUX( ADC_CHSELR_CHSEL5, 0 ); - case A6: return TO_MUX( ADC_CHSELR_CHSEL6, 0 ); - case A7: return TO_MUX( ADC_CHSELR_CHSEL7, 0 ); - case B0: return TO_MUX( ADC_CHSELR_CHSEL8, 0 ); - case B1: return TO_MUX( ADC_CHSELR_CHSEL9, 0 ); - case C0: return TO_MUX( ADC_CHSELR_CHSEL10, 0 ); - case C1: return TO_MUX( ADC_CHSELR_CHSEL11, 0 ); - case C2: return TO_MUX( ADC_CHSELR_CHSEL12, 0 ); - case C3: return TO_MUX( ADC_CHSELR_CHSEL13, 0 ); - case C4: return TO_MUX( ADC_CHSELR_CHSEL14, 0 ); - case C5: return TO_MUX( ADC_CHSELR_CHSEL15, 0 ); -#elif defined(STM32F3XX) - case A0: return TO_MUX( ADC_CHANNEL_IN1, 0 ); - case A1: return TO_MUX( ADC_CHANNEL_IN2, 0 ); - case A2: return TO_MUX( ADC_CHANNEL_IN3, 0 ); - case A3: return TO_MUX( ADC_CHANNEL_IN4, 0 ); - case A4: return TO_MUX( ADC_CHANNEL_IN1, 1 ); - case A5: return TO_MUX( ADC_CHANNEL_IN2, 1 ); - case A6: return TO_MUX( ADC_CHANNEL_IN3, 1 ); - case A7: return TO_MUX( ADC_CHANNEL_IN4, 1 ); - case B0: return TO_MUX( ADC_CHANNEL_IN12, 2 ); - case B1: return TO_MUX( ADC_CHANNEL_IN1, 2 ); - case B2: return TO_MUX( ADC_CHANNEL_IN12, 1 ); - case B12: return TO_MUX( ADC_CHANNEL_IN3, 3 ); - case B13: return TO_MUX( ADC_CHANNEL_IN5, 2 ); - case B14: return TO_MUX( ADC_CHANNEL_IN4, 3 ); - case B15: return TO_MUX( ADC_CHANNEL_IN5, 3 ); - case C0: return TO_MUX( ADC_CHANNEL_IN6, 0 ); // Can also be ADC2 - case C1: return TO_MUX( ADC_CHANNEL_IN7, 0 ); // Can also be ADC2 - case C2: return TO_MUX( ADC_CHANNEL_IN8, 0 ); // Can also be ADC2 - case C3: return TO_MUX( ADC_CHANNEL_IN9, 0 ); // Can also be ADC2 - case C4: return TO_MUX( ADC_CHANNEL_IN5, 1 ); - case C5: return TO_MUX( ADC_CHANNEL_IN11, 1 ); - case D8: return TO_MUX( ADC_CHANNEL_IN12, 3 ); - case D9: return TO_MUX( ADC_CHANNEL_IN13, 3 ); - case D10: return TO_MUX( ADC_CHANNEL_IN7, 2 ); // Can also be ADC4 - case D11: return TO_MUX( ADC_CHANNEL_IN8, 2 ); // Can also be ADC4 - case D12: return TO_MUX( ADC_CHANNEL_IN9, 2 ); // Can also be ADC4 - case D13: return TO_MUX( ADC_CHANNEL_IN10, 2 ); // Can also be ADC4 - case D14: return TO_MUX( ADC_CHANNEL_IN11, 2 ); // Can also be ADC4 - case E7: return TO_MUX( ADC_CHANNEL_IN13, 2 ); - case E8: return TO_MUX( ADC_CHANNEL_IN6, 2 ); // Can also be ADC4 - case E9: return TO_MUX( ADC_CHANNEL_IN2, 2 ); - case E10: return TO_MUX( ADC_CHANNEL_IN14, 2 ); - case E11: return TO_MUX( ADC_CHANNEL_IN15, 2 ); - case E12: return TO_MUX( ADC_CHANNEL_IN16, 2 ); - case E13: return TO_MUX( ADC_CHANNEL_IN3, 2 ); - case E14: return TO_MUX( ADC_CHANNEL_IN1, 3 ); - case E15: return TO_MUX( ADC_CHANNEL_IN2, 3 ); - case F2: return TO_MUX( ADC_CHANNEL_IN10, 0 ); // Can also be ADC2 - case F4: return TO_MUX( ADC_CHANNEL_IN5, 0 ); -#elif defined(STM32F4XX) - case A0: return TO_MUX( ADC_CHANNEL_IN0, 0 ); - case A1: return TO_MUX( ADC_CHANNEL_IN1, 0 ); - case A2: return TO_MUX( ADC_CHANNEL_IN2, 0 ); - case A3: return TO_MUX( ADC_CHANNEL_IN3, 0 ); - case A4: return TO_MUX( ADC_CHANNEL_IN4, 0 ); - case A5: return TO_MUX( ADC_CHANNEL_IN5, 0 ); - case A6: return TO_MUX( ADC_CHANNEL_IN6, 0 ); - case A7: return TO_MUX( ADC_CHANNEL_IN7, 0 ); - case B0: return TO_MUX( ADC_CHANNEL_IN8, 0 ); - case B1: return TO_MUX( ADC_CHANNEL_IN9, 0 ); - case C0: return TO_MUX( ADC_CHANNEL_IN10, 0 ); - case C1: return TO_MUX( ADC_CHANNEL_IN11, 0 ); - case C2: return TO_MUX( ADC_CHANNEL_IN12, 0 ); - case C3: return TO_MUX( ADC_CHANNEL_IN13, 0 ); - case C4: return TO_MUX( ADC_CHANNEL_IN14, 0 ); - case C5: return TO_MUX( ADC_CHANNEL_IN15, 0 ); -# if STM32_ADC_USE_ADC3 - case F3: return TO_MUX( ADC_CHANNEL_IN9, 2 ); - case F4: return TO_MUX( ADC_CHANNEL_IN14, 2 ); - case F5: return TO_MUX( ADC_CHANNEL_IN15, 2 ); - case F6: return TO_MUX( ADC_CHANNEL_IN4, 2 ); - case F7: return TO_MUX( ADC_CHANNEL_IN5, 2 ); - case F8: return TO_MUX( ADC_CHANNEL_IN6, 2 ); - case F9: return TO_MUX( ADC_CHANNEL_IN7, 2 ); - case F10: return TO_MUX( ADC_CHANNEL_IN8, 2 ); -# endif -#elif defined(STM32F1XX) - case A0: return TO_MUX( ADC_CHANNEL_IN0, 0 ); - case A1: return TO_MUX( ADC_CHANNEL_IN1, 0 ); - case A2: return TO_MUX( ADC_CHANNEL_IN2, 0 ); - case A3: return TO_MUX( ADC_CHANNEL_IN3, 0 ); - case A4: return TO_MUX( ADC_CHANNEL_IN4, 0 ); - case A5: return TO_MUX( ADC_CHANNEL_IN5, 0 ); - case A6: return TO_MUX( ADC_CHANNEL_IN6, 0 ); - case A7: return TO_MUX( ADC_CHANNEL_IN7, 0 ); - case B0: return TO_MUX( ADC_CHANNEL_IN8, 0 ); - case B1: return TO_MUX( ADC_CHANNEL_IN9, 0 ); - case C0: return TO_MUX( ADC_CHANNEL_IN10, 0 ); - case C1: return TO_MUX( ADC_CHANNEL_IN11, 0 ); - case C2: return TO_MUX( ADC_CHANNEL_IN12, 0 ); - case C3: return TO_MUX( ADC_CHANNEL_IN13, 0 ); - case C4: return TO_MUX( ADC_CHANNEL_IN14, 0 ); - case C5: return TO_MUX( ADC_CHANNEL_IN15, 0 ); - // STM32F103x[C-G] in 144-pin packages also have analog inputs on F6...F10, but they are on ADC3, and the - // ChibiOS ADC driver for STM32F1xx currently supports only ADC1, therefore these pins are not usable. -#endif - } - - // return an adc that would never be used so intToADCDriver will bail out - return TO_MUX(0, 0xFF); -} -// clang-format on - -static inline ADCDriver* intToADCDriver(uint8_t adcInt) { - switch (adcInt) { -#if STM32_ADC_USE_ADC1 - case 0: - return &ADCD1; -#endif -#if STM32_ADC_USE_ADC2 - case 1: - return &ADCD2; -#endif -#if STM32_ADC_USE_ADC3 - case 2: - return &ADCD3; -#endif -#if STM32_ADC_USE_ADC4 - case 3: - return &ADCD4; -#endif - } - - return NULL; -} - -static inline void manageAdcInitializationDriver(uint8_t adc, ADCDriver* adcDriver) { - if (!adcInitialized[adc]) { - adcStart(adcDriver, &adcCfg); - adcInitialized[adc] = true; - } -} - -int16_t analogReadPin(pin_t pin) { - palSetLineMode(pin, PAL_MODE_INPUT_ANALOG); - - return adc_read(pinToMux(pin)); -} - -int16_t analogReadPinAdc(pin_t pin, uint8_t adc) { - palSetLineMode(pin, PAL_MODE_INPUT_ANALOG); - - adc_mux target = pinToMux(pin); - target.adc = adc; - return adc_read(target); -} - -int16_t adc_read(adc_mux mux) { -#if defined(USE_ADCV1) - // TODO: fix previous assumption of only 1 input... - adcConversionGroup.chselr = 1 << mux.input; /*no macro to convert N to ADC_CHSELR_CHSEL1*/ -#elif defined(USE_ADCV2) - adcConversionGroup.sqr3 = ADC_SQR3_SQ1_N(mux.input); -#else - adcConversionGroup.sqr[0] = ADC_SQR1_SQ1_N(mux.input); -#endif - - ADCDriver* targetDriver = intToADCDriver(mux.adc); - if (!targetDriver) { - return 0; - } - - manageAdcInitializationDriver(mux.adc, targetDriver); - if (adcConvert(targetDriver, &adcConversionGroup, &sampleBuffer[0], ADC_BUFFER_DEPTH) != MSG_OK) { - return 0; - } - -#ifdef USE_ADCV2 - // fake 12-bit -> N-bit scale - return (*sampleBuffer) >> (12 - ADC_RESOLUTION); -#else - // already handled as part of adcConvert - return *sampleBuffer; -#endif -} diff --git a/drivers/chibios/analog.h b/drivers/chibios/analog.h deleted file mode 100644 index e61c394265..0000000000 --- a/drivers/chibios/analog.h +++ /dev/null @@ -1,41 +0,0 @@ -/* Copyright 2019 Drew Mills - * - * 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 . - */ - -#pragma once - -#include -#include "quantum.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - uint16_t input; - uint8_t adc; -} adc_mux; -#define TO_MUX(i, a) \ - (adc_mux) { i, a } - -int16_t analogReadPin(pin_t pin); -int16_t analogReadPinAdc(pin_t pin, uint8_t adc); -adc_mux pinToMux(pin_t pin); - -int16_t adc_read(adc_mux mux); - -#ifdef __cplusplus -} -#endif diff --git a/drivers/chibios/i2c_master.c b/drivers/chibios/i2c_master.c deleted file mode 100644 index fc4bb2ab37..0000000000 --- a/drivers/chibios/i2c_master.c +++ /dev/null @@ -1,121 +0,0 @@ -/* Copyright 2018 Jack Humbert - * Copyright 2018 Yiancar - * - * 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 . - */ - -/* This library is only valid for STM32 processors. - * This library follows the convention of the AVR i2c_master library. - * As a result addresses are expected to be already shifted (addr << 1). - * I2CD1 is the default driver which corresponds to pins B6 and B7. This - * can be changed. - * Please ensure that HAL_USE_I2C is TRUE in the halconf.h file and that - * STM32_I2C_USE_I2C1 is TRUE in the mcuconf.h file. Pins B6 and B7 are used - * but using any other I2C pins should be trivial. - */ -#include "quantum.h" -#include "i2c_master.h" -#include -#include - -static uint8_t i2c_address; - -static const I2CConfig i2cconfig = { -#if defined(USE_I2CV1_CONTRIB) - I2C1_CLOCK_SPEED, -#elif defined(USE_I2CV1) - I2C1_OPMODE, - I2C1_CLOCK_SPEED, - I2C1_DUTY_CYCLE, -#else - // This configures the I2C clock to 400khz assuming a 72Mhz clock - // For more info : https://www.st.com/en/embedded-software/stsw-stm32126.html - STM32_TIMINGR_PRESC(I2C1_TIMINGR_PRESC) | STM32_TIMINGR_SCLDEL(I2C1_TIMINGR_SCLDEL) | STM32_TIMINGR_SDADEL(I2C1_TIMINGR_SDADEL) | STM32_TIMINGR_SCLH(I2C1_TIMINGR_SCLH) | STM32_TIMINGR_SCLL(I2C1_TIMINGR_SCLL), 0, 0 -#endif -}; - -static i2c_status_t chibios_to_qmk(const msg_t* status) { - switch (*status) { - case I2C_NO_ERROR: - return I2C_STATUS_SUCCESS; - case I2C_TIMEOUT: - return I2C_STATUS_TIMEOUT; - // I2C_BUS_ERROR, I2C_ARBITRATION_LOST, I2C_ACK_FAILURE, I2C_OVERRUN, I2C_PEC_ERROR, I2C_SMB_ALERT - default: - return I2C_STATUS_ERROR; - } -} - -__attribute__((weak)) void i2c_init(void) { - static bool is_initialised = false; - if (!is_initialised) { - is_initialised = true; - - // Try releasing special pins for a short time - palSetPadMode(I2C1_SCL_BANK, I2C1_SCL, PAL_MODE_INPUT); - palSetPadMode(I2C1_SDA_BANK, I2C1_SDA, PAL_MODE_INPUT); - - chThdSleepMilliseconds(10); -#if defined(USE_GPIOV1) - palSetPadMode(I2C1_SCL_BANK, I2C1_SCL, I2C1_SCL_PAL_MODE); - palSetPadMode(I2C1_SDA_BANK, I2C1_SDA, I2C1_SDA_PAL_MODE); -#else - palSetPadMode(I2C1_SCL_BANK, I2C1_SCL, PAL_MODE_ALTERNATE(I2C1_SCL_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN); - palSetPadMode(I2C1_SDA_BANK, I2C1_SDA, PAL_MODE_ALTERNATE(I2C1_SDA_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN); -#endif - } -} - -i2c_status_t i2c_start(uint8_t address) { - i2c_address = address; - i2cStart(&I2C_DRIVER, &i2cconfig); - return I2C_STATUS_SUCCESS; -} - -i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout) { - i2c_address = address; - i2cStart(&I2C_DRIVER, &i2cconfig); - msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), data, length, 0, 0, TIME_MS2I(timeout)); - return chibios_to_qmk(&status); -} - -i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) { - i2c_address = address; - i2cStart(&I2C_DRIVER, &i2cconfig); - msg_t status = i2cMasterReceiveTimeout(&I2C_DRIVER, (i2c_address >> 1), data, length, TIME_MS2I(timeout)); - return chibios_to_qmk(&status); -} - -i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) { - i2c_address = devaddr; - i2cStart(&I2C_DRIVER, &i2cconfig); - - uint8_t complete_packet[length + 1]; - for (uint8_t i = 0; i < length; i++) { - complete_packet[i + 1] = data[i]; - } - complete_packet[0] = regaddr; - - msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), complete_packet, length + 1, 0, 0, TIME_MS2I(timeout)); - return chibios_to_qmk(&status); -} - -i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) { - i2c_address = devaddr; - i2cStart(&I2C_DRIVER, &i2cconfig); - msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), ®addr, 1, data, length, TIME_MS2I(timeout)); - return chibios_to_qmk(&status); -} - -void i2c_stop(void) { i2cStop(&I2C_DRIVER); } diff --git a/drivers/chibios/i2c_master.h b/drivers/chibios/i2c_master.h deleted file mode 100644 index c68109acbd..0000000000 --- a/drivers/chibios/i2c_master.h +++ /dev/null @@ -1,113 +0,0 @@ -/* Copyright 2018 Jack Humbert - * Copyright 2018 Yiancar - * - * 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 . - */ - -/* This library follows the convention of the AVR i2c_master library. - * As a result addresses are expected to be already shifted (addr << 1). - * I2CD1 is the default driver which corresponds to pins B6 and B7. This - * can be changed. - * Please ensure that HAL_USE_I2C is TRUE in the halconf.h file and that - * STM32_I2C_USE_I2C1 is TRUE in the mcuconf.h file. - */ -#pragma once - -#include -#include - -#ifdef I2C1_BANK -# define I2C1_SCL_BANK I2C1_BANK -# define I2C1_SDA_BANK I2C1_BANK -#endif - -#ifndef I2C1_SCL_BANK -# define I2C1_SCL_BANK GPIOB -#endif - -#ifndef I2C1_SDA_BANK -# define I2C1_SDA_BANK GPIOB -#endif - -#ifndef I2C1_SCL -# define I2C1_SCL 6 -#endif -#ifndef I2C1_SDA -# define I2C1_SDA 7 -#endif - -#ifdef USE_I2CV1 -# ifndef I2C1_OPMODE -# define I2C1_OPMODE OPMODE_I2C -# endif -# ifndef I2C1_CLOCK_SPEED -# define I2C1_CLOCK_SPEED 100000 /* 400000 */ -# endif -# ifndef I2C1_DUTY_CYCLE -# define I2C1_DUTY_CYCLE STD_DUTY_CYCLE /* FAST_DUTY_CYCLE_2 */ -# endif -#else -// The default timing values below configures the I2C clock to 400khz assuming a 72Mhz clock -// For more info : https://www.st.com/en/embedded-software/stsw-stm32126.html -# ifndef I2C1_TIMINGR_PRESC -# define I2C1_TIMINGR_PRESC 0U -# endif -# ifndef I2C1_TIMINGR_SCLDEL -# define I2C1_TIMINGR_SCLDEL 7U -# endif -# ifndef I2C1_TIMINGR_SDADEL -# define I2C1_TIMINGR_SDADEL 0U -# endif -# ifndef I2C1_TIMINGR_SCLH -# define I2C1_TIMINGR_SCLH 38U -# endif -# ifndef I2C1_TIMINGR_SCLL -# define I2C1_TIMINGR_SCLL 129U -# endif -#endif - -#ifndef I2C_DRIVER -# define I2C_DRIVER I2CD1 -#endif - -#ifdef USE_GPIOV1 -# ifndef I2C1_SCL_PAL_MODE -# define I2C1_SCL_PAL_MODE PAL_MODE_STM32_ALTERNATE_OPENDRAIN -# endif -# ifndef I2C1_SDA_PAL_MODE -# define I2C1_SDA_PAL_MODE PAL_MODE_STM32_ALTERNATE_OPENDRAIN -# endif -#else -// The default PAL alternate modes are used to signal that the pins are used for I2C -# ifndef I2C1_SCL_PAL_MODE -# define I2C1_SCL_PAL_MODE 4 -# endif -# ifndef I2C1_SDA_PAL_MODE -# define I2C1_SDA_PAL_MODE 4 -# endif -#endif - -typedef int16_t i2c_status_t; - -#define I2C_STATUS_SUCCESS (0) -#define I2C_STATUS_ERROR (-1) -#define I2C_STATUS_TIMEOUT (-2) - -void i2c_init(void); -i2c_status_t i2c_start(uint8_t address); -i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout); -i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout); -i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout); -i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); -void i2c_stop(void); diff --git a/drivers/chibios/serial.c b/drivers/chibios/serial.c deleted file mode 100644 index f54fbcee4e..0000000000 --- a/drivers/chibios/serial.c +++ /dev/null @@ -1,278 +0,0 @@ -/* - * WARNING: be careful changing this code, it is very timing dependent - */ - -#include "quantum.h" -#include "serial.h" -#include "wait.h" - -#include - -// TODO: resolve/remove build warnings -#if defined(RGBLIGHT_ENABLE) && defined(RGBLED_SPLIT) && defined(PROTOCOL_CHIBIOS) && defined(WS2812_DRIVER_BITBANG) -# warning "RGBLED_SPLIT not supported with bitbang WS2812 driver" -#endif - -// default wait implementation cannot be called within interrupt -// this method seems to be more accurate than GPT timers -#if PORT_SUPPORTS_RT == FALSE -# error "chSysPolledDelayX method not supported on this platform" -#else -# undef wait_us -# define wait_us(x) chSysPolledDelayX(US2RTC(STM32_SYSCLK, x)) -#endif - -#ifndef SELECT_SOFT_SERIAL_SPEED -# define SELECT_SOFT_SERIAL_SPEED 1 -// TODO: correct speeds... -// 0: about 189kbps (Experimental only) -// 1: about 137kbps (default) -// 2: about 75kbps -// 3: about 39kbps -// 4: about 26kbps -// 5: about 20kbps -#endif - -// Serial pulse period in microseconds. At the moment, going lower than 12 causes communication failure -#if SELECT_SOFT_SERIAL_SPEED == 0 -# define SERIAL_DELAY 12 -#elif SELECT_SOFT_SERIAL_SPEED == 1 -# define SERIAL_DELAY 16 -#elif SELECT_SOFT_SERIAL_SPEED == 2 -# define SERIAL_DELAY 24 -#elif SELECT_SOFT_SERIAL_SPEED == 3 -# define SERIAL_DELAY 32 -#elif SELECT_SOFT_SERIAL_SPEED == 4 -# define SERIAL_DELAY 48 -#elif SELECT_SOFT_SERIAL_SPEED == 5 -# define SERIAL_DELAY 64 -#else -# error invalid SELECT_SOFT_SERIAL_SPEED value -#endif - -inline static void serial_delay(void) { wait_us(SERIAL_DELAY); } -inline static void serial_delay_half(void) { wait_us(SERIAL_DELAY / 2); } -inline static void serial_delay_blip(void) { wait_us(1); } -inline static void serial_output(void) { setPinOutput(SOFT_SERIAL_PIN); } -inline static void serial_input(void) { setPinInputHigh(SOFT_SERIAL_PIN); } -inline static bool serial_read_pin(void) { return !!readPin(SOFT_SERIAL_PIN); } -inline static void serial_low(void) { writePinLow(SOFT_SERIAL_PIN); } -inline static void serial_high(void) { writePinHigh(SOFT_SERIAL_PIN); } - -void interrupt_handler(void *arg); - -// Use thread + palWaitLineTimeout instead of palSetLineCallback -// - Methods like setPinOutput and palEnableLineEvent/palDisableLineEvent -// cause the interrupt to lock up, which would limit to only receiving data... -static THD_WORKING_AREA(waThread1, 128); -static THD_FUNCTION(Thread1, arg) { - (void)arg; - chRegSetThreadName("blinker"); - while (true) { - palWaitLineTimeout(SOFT_SERIAL_PIN, TIME_INFINITE); - interrupt_handler(NULL); - } -} - -void soft_serial_initiator_init(void) { - serial_output(); - serial_high(); -} - -void soft_serial_target_init(void) { - serial_input(); - - palEnablePadEvent(PAL_PORT(SOFT_SERIAL_PIN), PAL_PAD(SOFT_SERIAL_PIN), PAL_EVENT_MODE_FALLING_EDGE); - chThdCreateStatic(waThread1, sizeof(waThread1), HIGHPRIO, Thread1, NULL); -} - -// Used by the master to synchronize timing with the slave. -static void __attribute__((noinline)) sync_recv(void) { - serial_input(); - // This shouldn't hang if the slave disconnects because the - // serial line will float to high if the slave does disconnect. - while (!serial_read_pin()) { - } - - serial_delay(); -} - -// Used by the slave to send a synchronization signal to the master. -static void __attribute__((noinline)) sync_send(void) { - serial_output(); - - serial_low(); - serial_delay(); - - serial_high(); -} - -// Reads a byte from the serial line -static uint8_t __attribute__((noinline)) serial_read_byte(void) { - uint8_t byte = 0; - serial_input(); - for (uint8_t i = 0; i < 8; ++i) { - byte = (byte << 1) | serial_read_pin(); - serial_delay(); - } - - return byte; -} - -// Sends a byte with MSB ordering -static void __attribute__((noinline)) serial_write_byte(uint8_t data) { - uint8_t b = 8; - serial_output(); - while (b--) { - if (data & (1 << b)) { - serial_high(); - } else { - serial_low(); - } - serial_delay(); - } -} - -// interrupt handle to be used by the slave device -void interrupt_handler(void *arg) { - chSysLockFromISR(); - - sync_send(); - - // read mid pulses - serial_delay_blip(); - - uint8_t checksum_computed = 0; - int sstd_index = 0; - - sstd_index = serial_read_byte(); - sync_send(); - - split_transaction_desc_t *trans = &split_transaction_table[sstd_index]; - for (int i = 0; i < trans->initiator2target_buffer_size; ++i) { - split_trans_initiator2target_buffer(trans)[i] = serial_read_byte(); - sync_send(); - checksum_computed += split_trans_initiator2target_buffer(trans)[i]; - } - checksum_computed ^= 7; - uint8_t checksum_received = serial_read_byte(); - sync_send(); - - // wait for the sync to finish sending - serial_delay(); - - // Allow any slave processing to occur - if (trans->slave_callback) { - trans->slave_callback(trans->initiator2target_buffer_size, split_trans_initiator2target_buffer(trans), trans->target2initiator_buffer_size, split_trans_target2initiator_buffer(trans)); - } - - uint8_t checksum = 0; - for (int i = 0; i < trans->target2initiator_buffer_size; ++i) { - serial_write_byte(split_trans_target2initiator_buffer(trans)[i]); - sync_send(); - serial_delay_half(); - checksum += split_trans_target2initiator_buffer(trans)[i]; - } - serial_write_byte(checksum ^ 7); - sync_send(); - - // wait for the sync to finish sending - serial_delay(); - - *trans->status = (checksum_computed == checksum_received) ? TRANSACTION_ACCEPTED : TRANSACTION_DATA_ERROR; - - // end transaction - serial_input(); - - // TODO: remove extra delay between transactions - serial_delay(); - - chSysUnlockFromISR(); -} - -///////// -// start transaction by initiator -// -// int soft_serial_transaction(int sstd_index) -// -// Returns: -// TRANSACTION_END -// TRANSACTION_NO_RESPONSE -// TRANSACTION_DATA_ERROR -// this code is very time dependent, so we need to disable interrupts -int soft_serial_transaction(int sstd_index) { - if (sstd_index > NUM_TOTAL_TRANSACTIONS) return TRANSACTION_TYPE_ERROR; - split_transaction_desc_t *trans = &split_transaction_table[sstd_index]; - if (!trans->status) return TRANSACTION_TYPE_ERROR; // not registered - - // TODO: remove extra delay between transactions - serial_delay(); - - // this code is very time dependent, so we need to disable interrupts - chSysLock(); - - // signal to the slave that we want to start a transaction - serial_output(); - serial_low(); - serial_delay_blip(); - - // wait for the slaves response - serial_input(); - serial_high(); - serial_delay(); - - // check if the slave is present - if (serial_read_pin()) { - // slave failed to pull the line low, assume not present - dprintf("serial::NO_RESPONSE\n"); - chSysUnlock(); - return TRANSACTION_NO_RESPONSE; - } - - // if the slave is present syncronize with it - - uint8_t checksum = 0; - // send data to the slave - serial_write_byte(sstd_index); // first chunk is transaction id - sync_recv(); - - for (int i = 0; i < trans->initiator2target_buffer_size; ++i) { - serial_write_byte(split_trans_initiator2target_buffer(trans)[i]); - sync_recv(); - checksum += split_trans_initiator2target_buffer(trans)[i]; - } - serial_write_byte(checksum ^ 7); - sync_recv(); - - serial_delay(); - serial_delay(); // read mid pulses - - // receive data from the slave - uint8_t checksum_computed = 0; - for (int i = 0; i < trans->target2initiator_buffer_size; ++i) { - split_trans_target2initiator_buffer(trans)[i] = serial_read_byte(); - sync_recv(); - checksum_computed += split_trans_target2initiator_buffer(trans)[i]; - } - checksum_computed ^= 7; - uint8_t checksum_received = serial_read_byte(); - - sync_recv(); - serial_delay(); - - if ((checksum_computed) != (checksum_received)) { - dprintf("serial::FAIL[%u,%u,%u]\n", checksum_computed, checksum_received, sstd_index); - serial_output(); - serial_high(); - - chSysUnlock(); - return TRANSACTION_DATA_ERROR; - } - - // always, release the line when not in use - serial_high(); - serial_output(); - - chSysUnlock(); - return TRANSACTION_END; -} diff --git a/drivers/chibios/serial_usart.c b/drivers/chibios/serial_usart.c deleted file mode 100644 index ea4473791c..0000000000 --- a/drivers/chibios/serial_usart.c +++ /dev/null @@ -1,318 +0,0 @@ -/* Copyright 2021 QMK - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "serial_usart.h" - -#if defined(SERIAL_USART_CONFIG) -static SerialConfig serial_config = SERIAL_USART_CONFIG; -#else -static SerialConfig serial_config = { - .speed = (SERIAL_USART_SPEED), /* speed - mandatory */ - .cr1 = (SERIAL_USART_CR1), - .cr2 = (SERIAL_USART_CR2), -# if !defined(SERIAL_USART_FULL_DUPLEX) - .cr3 = ((SERIAL_USART_CR3) | USART_CR3_HDSEL) /* activate half-duplex mode */ -# else - .cr3 = (SERIAL_USART_CR3) -# endif -}; -#endif - -static SerialDriver* serial_driver = &SERIAL_USART_DRIVER; - -static inline bool react_to_transactions(void); -static inline bool __attribute__((nonnull)) receive(uint8_t* destination, const size_t size); -static inline bool __attribute__((nonnull)) send(const uint8_t* source, const size_t size); -static inline int initiate_transaction(uint8_t sstd_index); -static inline void usart_clear(void); - -/** - * @brief Clear the receive input queue. - */ -static inline void usart_clear(void) { - osalSysLock(); - bool volatile queue_not_empty = !iqIsEmptyI(&serial_driver->iqueue); - osalSysUnlock(); - - while (queue_not_empty) { - osalSysLock(); - /* Hard reset the input queue. */ - iqResetI(&serial_driver->iqueue); - osalSysUnlock(); - /* Allow pending interrupts to preempt. - * Do not merge the lock/unlock blocks into one - * or the code will not work properly. - * The empty read adds a tiny amount of delay. */ - (void)queue_not_empty; - osalSysLock(); - queue_not_empty = !iqIsEmptyI(&serial_driver->iqueue); - osalSysUnlock(); - } -} - -/** - * @brief Blocking send of buffer with timeout. - * - * @return true Send success. - * @return false Send failed. - */ -static inline bool send(const uint8_t* source, const size_t size) { - bool success = (size_t)sdWriteTimeout(serial_driver, source, size, TIME_MS2I(SERIAL_USART_TIMEOUT)) == size; - -#if !defined(SERIAL_USART_FULL_DUPLEX) - if (success) { - /* Half duplex fills the input queue with the data we wrote - just throw it away. - Under the right circumstances (e.g. bad cables paired with high baud rates) - less bytes can be present in the input queue, therefore a timeout is needed. */ - uint8_t dump[size]; - return receive(dump, size); - } -#endif - - return success; -} - -/** - * @brief Blocking receive of size * bytes with timeout. - * - * @return true Receive success. - * @return false Receive failed. - */ -static inline bool receive(uint8_t* destination, const size_t size) { - bool success = (size_t)sdReadTimeout(serial_driver, destination, size, TIME_MS2I(SERIAL_USART_TIMEOUT)) == size; - return success; -} - -#if !defined(SERIAL_USART_FULL_DUPLEX) - -/** - * @brief Initiate pins for USART peripheral. Half-duplex configuration. - */ -__attribute__((weak)) void usart_init(void) { -# if defined(MCU_STM32) -# if defined(USE_GPIOV1) - palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_STM32_ALTERNATE_OPENDRAIN); -# else - palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_ALTERNATE(SERIAL_USART_TX_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN); -# endif - -# if defined(USART_REMAP) - USART_REMAP; -# endif -# else -# pragma message "usart_init: MCU Familiy not supported by default, please supply your own init code by implementing usart_init() in your keyboard files." -# endif -} - -#else - -/** - * @brief Initiate pins for USART peripheral. Full-duplex configuration. - */ -__attribute__((weak)) void usart_init(void) { -# if defined(MCU_STM32) -# if defined(USE_GPIOV1) - palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_STM32_ALTERNATE_PUSHPULL); - palSetLineMode(SERIAL_USART_RX_PIN, PAL_MODE_INPUT); -# else - palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_ALTERNATE(SERIAL_USART_TX_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); - palSetLineMode(SERIAL_USART_RX_PIN, PAL_MODE_ALTERNATE(SERIAL_USART_RX_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); -# endif - -# if defined(USART_REMAP) - USART_REMAP; -# endif -# else -# pragma message "usart_init: MCU Familiy not supported by default, please supply your own init code by implementing usart_init() in your keyboard files." -# endif -} - -#endif - -/** - * @brief Overridable master specific initializations. - */ -__attribute__((weak, nonnull)) void usart_master_init(SerialDriver** driver) { - (void)driver; - usart_init(); -} - -/** - * @brief Overridable slave specific initializations. - */ -__attribute__((weak, nonnull)) void usart_slave_init(SerialDriver** driver) { - (void)driver; - usart_init(); -} - -/** - * @brief This thread runs on the slave and responds to transactions initiated - * by the master. - */ -static THD_WORKING_AREA(waSlaveThread, 1024); -static THD_FUNCTION(SlaveThread, arg) { - (void)arg; - chRegSetThreadName("usart_tx_rx"); - - while (true) { - if (!react_to_transactions()) { - /* Clear the receive queue, to start with a clean slate. - * Parts of failed transactions or spurious bytes could still be in it. */ - usart_clear(); - } - } -} - -/** - * @brief Slave specific initializations. - */ -void soft_serial_target_init(void) { - usart_slave_init(&serial_driver); - - sdStart(serial_driver, &serial_config); - - /* Start transport thread. */ - chThdCreateStatic(waSlaveThread, sizeof(waSlaveThread), HIGHPRIO, SlaveThread, NULL); -} - -/** - * @brief React to transactions started by the master. - */ -static inline bool react_to_transactions(void) { - /* Wait until there is a transaction for us. */ - uint8_t sstd_index = (uint8_t)sdGet(serial_driver); - - /* Sanity check that we are actually responding to a valid transaction. */ - if (sstd_index >= NUM_TOTAL_TRANSACTIONS) { - return false; - } - - split_transaction_desc_t* trans = &split_transaction_table[sstd_index]; - - /* Send back the handshake which is XORed as a simple checksum, - to signal that the slave is ready to receive possible transaction buffers */ - sstd_index ^= HANDSHAKE_MAGIC; - if (!send(&sstd_index, sizeof(sstd_index))) { - *trans->status = TRANSACTION_DATA_ERROR; - return false; - } - - /* Receive transaction buffer from the master. If this transaction requires it.*/ - if (trans->initiator2target_buffer_size) { - if (!receive(split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size)) { - *trans->status = TRANSACTION_DATA_ERROR; - return false; - } - } - - /* Allow any slave processing to occur. */ - if (trans->slave_callback) { - trans->slave_callback(trans->initiator2target_buffer_size, split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size, split_trans_target2initiator_buffer(trans)); - } - - /* Send transaction buffer to the master. If this transaction requires it. */ - if (trans->target2initiator_buffer_size) { - if (!send(split_trans_target2initiator_buffer(trans), trans->target2initiator_buffer_size)) { - *trans->status = TRANSACTION_DATA_ERROR; - return false; - } - } - - *trans->status = TRANSACTION_ACCEPTED; - return true; -} - -/** - * @brief Master specific initializations. - */ -void soft_serial_initiator_init(void) { - usart_master_init(&serial_driver); - -#if defined(MCU_STM32) && defined(SERIAL_USART_PIN_SWAP) - serial_config.cr2 |= USART_CR2_SWAP; // master has swapped TX/RX pins -#endif - - sdStart(serial_driver, &serial_config); -} - -/** - * @brief Start transaction from the master half to the slave half. - * - * @param index Transaction Table index of the transaction to start. - * @return int TRANSACTION_NO_RESPONSE in case of Timeout. - * TRANSACTION_TYPE_ERROR in case of invalid transaction index. - * TRANSACTION_END in case of success. - */ -int soft_serial_transaction(int index) { - /* Clear the receive queue, to start with a clean slate. - * Parts of failed transactions or spurious bytes could still be in it. */ - usart_clear(); - return initiate_transaction((uint8_t)index); -} - -/** - * @brief Initiate transaction to slave half. - */ -static inline int initiate_transaction(uint8_t sstd_index) { - /* Sanity check that we are actually starting a valid transaction. */ - if (sstd_index >= NUM_TOTAL_TRANSACTIONS) { - dprintln("USART: Illegal transaction Id."); - return TRANSACTION_TYPE_ERROR; - } - - split_transaction_desc_t* trans = &split_transaction_table[sstd_index]; - - /* Transaction is not registered. Abort. */ - if (!trans->status) { - dprintln("USART: Transaction not registered."); - return TRANSACTION_TYPE_ERROR; - } - - /* Send transaction table index to the slave, which doubles as basic handshake token. */ - if (!send(&sstd_index, sizeof(sstd_index))) { - dprintln("USART: Send Handshake failed."); - return TRANSACTION_TYPE_ERROR; - } - - uint8_t sstd_index_shake = 0xFF; - - /* Which we always read back first so that we can error out correctly. - * - due to the half duplex limitations on return codes, we always have to read *something*. - * - without the read, write only transactions *always* succeed, even during the boot process where the slave is not ready. - */ - if (!receive(&sstd_index_shake, sizeof(sstd_index_shake)) || (sstd_index_shake != (sstd_index ^ HANDSHAKE_MAGIC))) { - dprintln("USART: Handshake failed."); - return TRANSACTION_NO_RESPONSE; - } - - /* Send transaction buffer to the slave. If this transaction requires it. */ - if (trans->initiator2target_buffer_size) { - if (!send(split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size)) { - dprintln("USART: Send failed."); - return TRANSACTION_NO_RESPONSE; - } - } - - /* Receive transaction buffer from the slave. If this transaction requires it. */ - if (trans->target2initiator_buffer_size) { - if (!receive(split_trans_target2initiator_buffer(trans), trans->target2initiator_buffer_size)) { - dprintln("USART: Receive failed."); - return TRANSACTION_NO_RESPONSE; - } - } - - return TRANSACTION_END; -} diff --git a/drivers/chibios/serial_usart.h b/drivers/chibios/serial_usart.h deleted file mode 100644 index c64e15566f..0000000000 --- a/drivers/chibios/serial_usart.h +++ /dev/null @@ -1,116 +0,0 @@ -/* Copyright 2021 QMK - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include "quantum.h" -#include "serial.h" -#include "printf.h" - -#include -#include - -#if !defined(SERIAL_USART_DRIVER) -# define SERIAL_USART_DRIVER SD1 -#endif - -#if !defined(USE_GPIOV1) -/* The default PAL alternate modes are used to signal that the pins are used for USART. */ -# if !defined(SERIAL_USART_TX_PAL_MODE) -# define SERIAL_USART_TX_PAL_MODE 7 -# endif -# if !defined(SERIAL_USART_RX_PAL_MODE) -# define SERIAL_USART_RX_PAL_MODE 7 -# endif -#endif - -#if defined(SOFT_SERIAL_PIN) -# define SERIAL_USART_TX_PIN SOFT_SERIAL_PIN -#endif - -#if !defined(SERIAL_USART_TX_PIN) -# define SERIAL_USART_TX_PIN A9 -#endif - -#if !defined(SERIAL_USART_RX_PIN) -# define SERIAL_USART_RX_PIN A10 -#endif - -#if !defined(USART_CR1_M0) -# define USART_CR1_M0 USART_CR1_M // some platforms (f1xx) dont have this so -#endif - -#if !defined(SERIAL_USART_CR1) -# define SERIAL_USART_CR1 (USART_CR1_PCE | USART_CR1_PS | USART_CR1_M0) // parity enable, odd parity, 9 bit length -#endif - -#if !defined(SERIAL_USART_CR2) -# define SERIAL_USART_CR2 (USART_CR2_STOP_1) // 2 stop bits -#endif - -#if !defined(SERIAL_USART_CR3) -# define SERIAL_USART_CR3 0 -#endif - -#if defined(USART1_REMAP) -# define USART_REMAP \ - do { \ - (AFIO->MAPR |= AFIO_MAPR_USART1_REMAP); \ - } while (0) -#elif defined(USART2_REMAP) -# define USART_REMAP \ - do { \ - (AFIO->MAPR |= AFIO_MAPR_USART2_REMAP); \ - } while (0) -#elif defined(USART3_PARTIALREMAP) -# define USART_REMAP \ - do { \ - (AFIO->MAPR |= AFIO_MAPR_USART3_REMAP_PARTIALREMAP); \ - } while (0) -#elif defined(USART3_FULLREMAP) -# define USART_REMAP \ - do { \ - (AFIO->MAPR |= AFIO_MAPR_USART3_REMAP_FULLREMAP); \ - } while (0) -#endif - -#if !defined(SELECT_SOFT_SERIAL_SPEED) -# define SELECT_SOFT_SERIAL_SPEED 1 -#endif - -#if defined(SERIAL_USART_SPEED) -// Allow advanced users to directly set SERIAL_USART_SPEED -#elif SELECT_SOFT_SERIAL_SPEED == 0 -# define SERIAL_USART_SPEED 460800 -#elif SELECT_SOFT_SERIAL_SPEED == 1 -# define SERIAL_USART_SPEED 230400 -#elif SELECT_SOFT_SERIAL_SPEED == 2 -# define SERIAL_USART_SPEED 115200 -#elif SELECT_SOFT_SERIAL_SPEED == 3 -# define SERIAL_USART_SPEED 57600 -#elif SELECT_SOFT_SERIAL_SPEED == 4 -# define SERIAL_USART_SPEED 38400 -#elif SELECT_SOFT_SERIAL_SPEED == 5 -# define SERIAL_USART_SPEED 19200 -#else -# error invalid SELECT_SOFT_SERIAL_SPEED value -#endif - -#if !defined(SERIAL_USART_TIMEOUT) -# define SERIAL_USART_TIMEOUT 100 -#endif - -#define HANDSHAKE_MAGIC 7 diff --git a/drivers/chibios/spi_master.c b/drivers/chibios/spi_master.c deleted file mode 100644 index 28ddcbb2ba..0000000000 --- a/drivers/chibios/spi_master.c +++ /dev/null @@ -1,202 +0,0 @@ -/* Copyright 2020 Nick Brassel (tzarc) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "spi_master.h" - -#include "timer.h" - -static pin_t currentSlavePin = NO_PIN; - -#if defined(K20x) || defined(KL2x) -static SPIConfig spiConfig = {NULL, 0, 0, 0}; -#else -static SPIConfig spiConfig = {false, NULL, 0, 0, 0, 0}; -#endif - -__attribute__((weak)) void spi_init(void) { - static bool is_initialised = false; - if (!is_initialised) { - is_initialised = true; - - // Try releasing special pins for a short time - setPinInput(SPI_SCK_PIN); - setPinInput(SPI_MOSI_PIN); - setPinInput(SPI_MISO_PIN); - - chThdSleepMilliseconds(10); -#if defined(USE_GPIOV1) - palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), SPI_SCK_PAL_MODE); - palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), SPI_MOSI_PAL_MODE); - palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), SPI_MISO_PAL_MODE); -#else - palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), PAL_MODE_ALTERNATE(SPI_SCK_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); - palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), PAL_MODE_ALTERNATE(SPI_MOSI_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); - palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), PAL_MODE_ALTERNATE(SPI_MISO_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); -#endif - } -} - -bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { - if (currentSlavePin != NO_PIN || slavePin == NO_PIN) { - return false; - } - - uint16_t roundedDivisor = 2; - while (roundedDivisor < divisor) { - roundedDivisor <<= 1; - } - - if (roundedDivisor < 2 || roundedDivisor > 256) { - return false; - } - -#if defined(K20x) || defined(KL2x) - spiConfig.tar0 = SPIx_CTARn_FMSZ(7) | SPIx_CTARn_ASC(1); - - if (lsbFirst) { - spiConfig.tar0 |= SPIx_CTARn_LSBFE; - } - - switch (mode) { - case 0: - break; - case 1: - spiConfig.tar0 |= SPIx_CTARn_CPHA; - break; - case 2: - spiConfig.tar0 |= SPIx_CTARn_CPOL; - break; - case 3: - spiConfig.tar0 |= SPIx_CTARn_CPHA | SPIx_CTARn_CPOL; - break; - } - - switch (roundedDivisor) { - case 2: - spiConfig.tar0 |= SPIx_CTARn_BR(0); - break; - case 4: - spiConfig.tar0 |= SPIx_CTARn_BR(1); - break; - case 8: - spiConfig.tar0 |= SPIx_CTARn_BR(3); - break; - case 16: - spiConfig.tar0 |= SPIx_CTARn_BR(4); - break; - case 32: - spiConfig.tar0 |= SPIx_CTARn_BR(5); - break; - case 64: - spiConfig.tar0 |= SPIx_CTARn_BR(6); - break; - case 128: - spiConfig.tar0 |= SPIx_CTARn_BR(7); - break; - case 256: - spiConfig.tar0 |= SPIx_CTARn_BR(8); - break; - } -#else - spiConfig.cr1 = 0; - - if (lsbFirst) { - spiConfig.cr1 |= SPI_CR1_LSBFIRST; - } - - switch (mode) { - case 0: - break; - case 1: - spiConfig.cr1 |= SPI_CR1_CPHA; - break; - case 2: - spiConfig.cr1 |= SPI_CR1_CPOL; - break; - case 3: - spiConfig.cr1 |= SPI_CR1_CPHA | SPI_CR1_CPOL; - break; - } - - switch (roundedDivisor) { - case 2: - break; - case 4: - spiConfig.cr1 |= SPI_CR1_BR_0; - break; - case 8: - spiConfig.cr1 |= SPI_CR1_BR_1; - break; - case 16: - spiConfig.cr1 |= SPI_CR1_BR_1 | SPI_CR1_BR_0; - break; - case 32: - spiConfig.cr1 |= SPI_CR1_BR_2; - break; - case 64: - spiConfig.cr1 |= SPI_CR1_BR_2 | SPI_CR1_BR_0; - break; - case 128: - spiConfig.cr1 |= SPI_CR1_BR_2 | SPI_CR1_BR_1; - break; - case 256: - spiConfig.cr1 |= SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_BR_0; - break; - } -#endif - - currentSlavePin = slavePin; - spiConfig.ssport = PAL_PORT(slavePin); - spiConfig.sspad = PAL_PAD(slavePin); - - setPinOutput(slavePin); - spiStart(&SPI_DRIVER, &spiConfig); - spiSelect(&SPI_DRIVER); - - return true; -} - -spi_status_t spi_write(uint8_t data) { - uint8_t rxData; - spiExchange(&SPI_DRIVER, 1, &data, &rxData); - - return rxData; -} - -spi_status_t spi_read(void) { - uint8_t data = 0; - spiReceive(&SPI_DRIVER, 1, &data); - - return data; -} - -spi_status_t spi_transmit(const uint8_t *data, uint16_t length) { - spiSend(&SPI_DRIVER, length, data); - return SPI_STATUS_SUCCESS; -} - -spi_status_t spi_receive(uint8_t *data, uint16_t length) { - spiReceive(&SPI_DRIVER, length, data); - return SPI_STATUS_SUCCESS; -} - -void spi_stop(void) { - if (currentSlavePin != NO_PIN) { - spiUnselect(&SPI_DRIVER); - spiStop(&SPI_DRIVER); - currentSlavePin = NO_PIN; - } -} diff --git a/drivers/chibios/spi_master.h b/drivers/chibios/spi_master.h deleted file mode 100644 index b5a6ef1437..0000000000 --- a/drivers/chibios/spi_master.h +++ /dev/null @@ -1,93 +0,0 @@ -/* Copyright 2020 Nick Brassel (tzarc) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include -#include -#include - -#include "gpio.h" -#include "chibios_config.h" - -#ifndef SPI_DRIVER -# define SPI_DRIVER SPID2 -#endif - -#ifndef SPI_SCK_PIN -# define SPI_SCK_PIN B13 -#endif - -#ifndef SPI_SCK_PAL_MODE -# if defined(USE_GPIOV1) -# define SPI_SCK_PAL_MODE PAL_MODE_STM32_ALTERNATE_PUSHPULL -# else -# define SPI_SCK_PAL_MODE 5 -# endif -#endif - -#ifndef SPI_MOSI_PIN -# define SPI_MOSI_PIN B15 -#endif - -#ifndef SPI_MOSI_PAL_MODE -# if defined(USE_GPIOV1) -# define SPI_MOSI_PAL_MODE PAL_MODE_STM32_ALTERNATE_PUSHPULL -# else -# define SPI_MOSI_PAL_MODE 5 -# endif -#endif - -#ifndef SPI_MISO_PIN -# define SPI_MISO_PIN B14 -#endif - -#ifndef SPI_MISO_PAL_MODE -# if defined(USE_GPIOV1) -# define SPI_MISO_PAL_MODE PAL_MODE_STM32_ALTERNATE_PUSHPULL -# else -# define SPI_MISO_PAL_MODE 5 -# endif -#endif - -typedef int16_t spi_status_t; - -#define SPI_STATUS_SUCCESS (0) -#define SPI_STATUS_ERROR (-1) -#define SPI_STATUS_TIMEOUT (-2) - -#define SPI_TIMEOUT_IMMEDIATE (0) -#define SPI_TIMEOUT_INFINITE (0xFFFF) - -#ifdef __cplusplus -extern "C" { -#endif -void spi_init(void); - -bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor); - -spi_status_t spi_write(uint8_t data); - -spi_status_t spi_read(void); - -spi_status_t spi_transmit(const uint8_t *data, uint16_t length); - -spi_status_t spi_receive(uint8_t *data, uint16_t length); - -void spi_stop(void); -#ifdef __cplusplus -} -#endif diff --git a/drivers/chibios/uart.c b/drivers/chibios/uart.c deleted file mode 100644 index 030335b342..0000000000 --- a/drivers/chibios/uart.c +++ /dev/null @@ -1,50 +0,0 @@ -/* Copyright 2021 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "uart.h" - -#include "quantum.h" - -static SerialConfig serialConfig = {SERIAL_DEFAULT_BITRATE, SD1_CR1, SD1_CR2, SD1_CR3}; - -void uart_init(uint32_t baud) { - static bool is_initialised = false; - - if (!is_initialised) { - is_initialised = true; - - serialConfig.speed = baud; - -#if defined(USE_GPIOV1) - palSetLineMode(SD1_TX_PIN, PAL_MODE_STM32_ALTERNATE_OPENDRAIN); - palSetLineMode(SD1_RX_PIN, PAL_MODE_STM32_ALTERNATE_OPENDRAIN); -#else - palSetLineMode(SD1_TX_PIN, PAL_MODE_ALTERNATE(SD1_TX_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN); - palSetLineMode(SD1_RX_PIN, PAL_MODE_ALTERNATE(SD1_RX_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN); -#endif - sdStart(&SERIAL_DRIVER, &serialConfig); - } -} - -void uart_putchar(uint8_t c) { sdPut(&SERIAL_DRIVER, c); } - -uint8_t uart_getchar(void) { - msg_t res = sdGet(&SERIAL_DRIVER); - - return (uint8_t)res; -} - -bool uart_available(void) { return !sdGetWouldBlock(&SERIAL_DRIVER); } diff --git a/drivers/chibios/uart.h b/drivers/chibios/uart.h deleted file mode 100644 index b4e20e9fd3..0000000000 --- a/drivers/chibios/uart.h +++ /dev/null @@ -1,77 +0,0 @@ -/* Copyright 2021 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include - -#include - -#ifndef SERIAL_DRIVER -# define SERIAL_DRIVER SD1 -#endif - -#ifndef SD1_TX_PIN -# define SD1_TX_PIN A9 -#endif - -#ifndef SD1_TX_PAL_MODE -# define SD1_TX_PAL_MODE 7 -#endif - -#ifndef SD1_RX_PIN -# define SD1_RX_PIN A10 -#endif - -#ifndef SD1_RX_PAL_MODE -# define SD1_RX_PAL_MODE 7 -#endif - -#ifndef SD1_CTS_PIN -# define SD1_CTS_PIN A11 -#endif - -#ifndef SD1_CTS_PAL_MODE -# define SD1_CTS_PAL_MODE 7 -#endif - -#ifndef SD1_RTS_PIN -# define SD1_RTS_PIN A12 -#endif - -#ifndef SD1_RTS_PAL_MODE -# define SD1_RTS_PAL_MODE 7 -#endif - -#ifndef SD1_CR1 -# define SD1_CR1 0 -#endif - -#ifndef SD1_CR2 -# define SD1_CR2 0 -#endif - -#ifndef SD1_CR3 -# define SD1_CR3 0 -#endif - -void uart_init(uint32_t baud); - -void uart_putchar(uint8_t c); - -uint8_t uart_getchar(void); - -bool uart_available(void); diff --git a/drivers/chibios/usbpd_stm32g4.c b/drivers/chibios/usbpd_stm32g4.c deleted file mode 100644 index f16ca8aeae..0000000000 --- a/drivers/chibios/usbpd_stm32g4.c +++ /dev/null @@ -1,76 +0,0 @@ -/* Copyright 2021 Nick Brassel (@tzarc) - * - * 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 . - */ - -#include - -#ifndef USBPD_UCPD1_CFG1 -# define USBPD_UCPD1_CFG1 (UCPD_CFG1_PSC_UCPDCLK_0 | UCPD_CFG1_TRANSWIN_3 | UCPD_CFG1_IFRGAP_4 | UCPD_CFG1_HBITCLKDIV_4) -#endif // USBPD_UCPD1_CFG1 - -// Initialises the USBPD subsystem -__attribute__((weak)) void usbpd_init(void) { - // Disable dead-battery signals - PWR->CR3 |= PWR_CR3_UCPD_DBDIS; - // Enable the clock for the UCPD1 peripheral - RCC->APB1ENR2 |= RCC_APB1ENR2_UCPD1EN; - - // Copy the existing value - uint32_t CFG1 = UCPD1->CFG1; - // Force-disable UCPD1 before configuring - CFG1 &= ~UCPD_CFG1_UCPDEN; - // Configure UCPD1 - CFG1 = USBPD_UCPD1_CFG1; - // Apply the changes - UCPD1->CFG1 = CFG1; - // Enable UCPD1 - UCPD1->CFG1 |= UCPD_CFG1_UCPDEN; - - // Copy the existing value - uint32_t CR = UCPD1->CR; - // Clear out ANASUBMODE (irrelevant as a sink device) - CR &= ~UCPD_CR_ANASUBMODE_Msk; - // Advertise our capabilities as a sink, with both CC lines enabled - CR |= UCPD_CR_ANAMODE | UCPD_CR_CCENABLE_Msk; - // Apply the changes - UCPD1->CR = CR; -} - -// Gets the current state of the USBPD allowance -__attribute__((weak)) usbpd_allowance_t usbpd_get_allowance(void) { - uint32_t CR = UCPD1->CR; - - int ucpd_enabled = (UCPD1->CFG1 & UCPD_CFG1_UCPDEN_Msk) >> UCPD_CFG1_UCPDEN_Pos; - int anamode = (CR & UCPD_CR_ANAMODE_Msk) >> UCPD_CR_ANAMODE_Pos; - int cc_enabled = (CR & UCPD_CR_CCENABLE_Msk) >> UCPD_CR_CCENABLE_Pos; - - if (ucpd_enabled && anamode && cc_enabled) { - uint32_t SR = UCPD1->SR; - int vstate_cc1 = (SR & UCPD_SR_TYPEC_VSTATE_CC1_Msk) >> UCPD_SR_TYPEC_VSTATE_CC1_Pos; - int vstate_cc2 = (SR & UCPD_SR_TYPEC_VSTATE_CC2_Msk) >> UCPD_SR_TYPEC_VSTATE_CC2_Pos; - int vstate_max = vstate_cc1 > vstate_cc2 ? vstate_cc1 : vstate_cc2; - switch (vstate_max) { - case 0: - case 1: - return USBPD_500MA; // Note that this is 500mA (i.e. max USB 2.0), not 900mA, as we're not using USB 3.1 as a sink device. - case 2: - return USBPD_1500MA; - case 3: - return USBPD_3000MA; - } - } - - return USBPD_500MA; -} \ No newline at end of file diff --git a/drivers/chibios/ws2812.c b/drivers/chibios/ws2812.c deleted file mode 100644 index 0d12e2fb79..0000000000 --- a/drivers/chibios/ws2812.c +++ /dev/null @@ -1,114 +0,0 @@ -#include "quantum.h" -#include "ws2812.h" -#include -#include - -/* Adapted from https://github.com/bigjosh/SimpleNeoPixelDemo/ */ - -#ifndef NOP_FUDGE -# if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F3XX) || defined(STM32F4XX) || defined(STM32L0XX) -# define NOP_FUDGE 0.4 -# else -# error("NOP_FUDGE configuration required") -# define NOP_FUDGE 1 // this just pleases the compile so the above error is easier to spot -# endif -#endif - -// Push Pull or Open Drain Configuration -// Default Push Pull -#ifndef WS2812_EXTERNAL_PULLUP -# define WS2812_OUTPUT_MODE PAL_MODE_OUTPUT_PUSHPULL -#else -# define WS2812_OUTPUT_MODE PAL_MODE_OUTPUT_OPENDRAIN -#endif - -#define NUMBER_NOPS 6 -#define CYCLES_PER_SEC (STM32_SYSCLK / NUMBER_NOPS * NOP_FUDGE) -#define NS_PER_SEC (1000000000L) // Note that this has to be SIGNED since we want to be able to check for negative values of derivatives -#define NS_PER_CYCLE (NS_PER_SEC / CYCLES_PER_SEC) -#define NS_TO_CYCLES(n) ((n) / NS_PER_CYCLE) - -#define wait_ns(x) \ - do { \ - for (int i = 0; i < NS_TO_CYCLES(x); i++) { \ - __asm__ volatile("nop\n\t" \ - "nop\n\t" \ - "nop\n\t" \ - "nop\n\t" \ - "nop\n\t" \ - "nop\n\t"); \ - } \ - } while (0) - -// These are the timing constraints taken mostly from the WS2812 datasheets -// These are chosen to be conservative and avoid problems rather than for maximum throughput - -#define T1H 900 // Width of a 1 bit in ns -#define T1L (1250 - T1H) // Width of a 1 bit in ns - -#define T0H 350 // Width of a 0 bit in ns -#define T0L (1250 - T0H) // Width of a 0 bit in ns - -// The reset gap can be 6000 ns, but depending on the LED strip it may have to be increased -// to values like 600000 ns. If it is too small, the pixels will show nothing most of the time. -#define RES (1000 * WS2812_TRST_US) // Width of the low gap between bits to cause a frame to latch - -void sendByte(uint8_t byte) { - // WS2812 protocol wants most significant bits first - for (unsigned char bit = 0; bit < 8; bit++) { - bool is_one = byte & (1 << (7 - bit)); - // using something like wait_ns(is_one ? T1L : T0L) here throws off timings - if (is_one) { - // 1 - writePinHigh(RGB_DI_PIN); - wait_ns(T1H); - writePinLow(RGB_DI_PIN); - wait_ns(T1L); - } else { - // 0 - writePinHigh(RGB_DI_PIN); - wait_ns(T0H); - writePinLow(RGB_DI_PIN); - wait_ns(T0L); - } - } -} - -void ws2812_init(void) { palSetLineMode(RGB_DI_PIN, WS2812_OUTPUT_MODE); } - -// Setleds for standard RGB -void ws2812_setleds(LED_TYPE *ledarray, uint16_t leds) { - static bool s_init = false; - if (!s_init) { - ws2812_init(); - s_init = true; - } - - // this code is very time dependent, so we need to disable interrupts - chSysLock(); - - for (uint8_t i = 0; i < leds; i++) { - // WS2812 protocol dictates grb order -#if (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_GRB) - sendByte(ledarray[i].g); - sendByte(ledarray[i].r); - sendByte(ledarray[i].b); -#elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_RGB) - sendByte(ledarray[i].r); - sendByte(ledarray[i].g); - sendByte(ledarray[i].b); -#elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_BGR) - sendByte(ledarray[i].b); - sendByte(ledarray[i].g); - sendByte(ledarray[i].r); -#endif - -#ifdef RGBW - sendByte(ledarray[i].w); -#endif - } - - wait_ns(RES); - - chSysUnlock(); -} diff --git a/drivers/chibios/ws2812_pwm.c b/drivers/chibios/ws2812_pwm.c deleted file mode 100644 index e6af55b6b3..0000000000 --- a/drivers/chibios/ws2812_pwm.c +++ /dev/null @@ -1,311 +0,0 @@ -#include "ws2812.h" -#include "quantum.h" -#include - -/* Adapted from https://github.com/joewa/WS2812-LED-Driver_ChibiOS/ */ - -#ifdef RGBW -# error "RGBW not supported" -#endif - -#ifndef WS2812_PWM_DRIVER -# define WS2812_PWM_DRIVER PWMD2 // TIMx -#endif -#ifndef WS2812_PWM_CHANNEL -# define WS2812_PWM_CHANNEL 2 // Channel -#endif -#ifndef WS2812_PWM_PAL_MODE -# define WS2812_PWM_PAL_MODE 2 // DI Pin's alternate function value -#endif -#ifndef WS2812_DMA_STREAM -# define WS2812_DMA_STREAM STM32_DMA1_STREAM2 // DMA Stream for TIMx_UP -#endif -#ifndef WS2812_DMA_CHANNEL -# define WS2812_DMA_CHANNEL 2 // DMA Channel for TIMx_UP -#endif -#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) && !defined(WS2812_DMAMUX_ID) -# error "please consult your MCU's datasheet and specify in your config.h: #define WS2812_DMAMUX_ID STM32_DMAMUX1_TIM?_UP" -#endif - -#ifndef WS2812_PWM_COMPLEMENTARY_OUTPUT -# define WS2812_PWM_OUTPUT_MODE PWM_OUTPUT_ACTIVE_HIGH -#else -# if !STM32_PWM_USE_ADVANCED -# error "WS2812_PWM_COMPLEMENTARY_OUTPUT requires STM32_PWM_USE_ADVANCED == TRUE" -# endif -# define WS2812_PWM_OUTPUT_MODE PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH -#endif - -// Push Pull or Open Drain Configuration -// Default Push Pull -#ifndef WS2812_EXTERNAL_PULLUP -# if defined(USE_GPIOV1) -# define WS2812_OUTPUT_MODE PAL_MODE_STM32_ALTERNATE_PUSHPULL -# else -# define WS2812_OUTPUT_MODE PAL_MODE_ALTERNATE(WS2812_PWM_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST | PAL_STM32_PUPDR_FLOATING -# endif -#else -# if defined(USE_GPIOV1) -# define WS2812_OUTPUT_MODE PAL_MODE_STM32_ALTERNATE_OPENDRAIN -# else -# define WS2812_OUTPUT_MODE PAL_MODE_ALTERNATE(WS2812_PWM_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_OSPEED_HIGHEST | PAL_STM32_PUPDR_FLOATING -# endif -#endif - -#ifndef WS2812_PWM_TARGET_PERIOD -//# define WS2812_PWM_TARGET_PERIOD 800000 // Original code is 800k...? -# define WS2812_PWM_TARGET_PERIOD 80000 // TODO: work out why 10x less on f303/f4x1 -#endif - -/* --- PRIVATE CONSTANTS ---------------------------------------------------- */ - -#define WS2812_PWM_FREQUENCY (STM32_SYSCLK / 2) /**< Clock frequency of PWM, must be valid with respect to system clock! */ -#define WS2812_PWM_PERIOD (WS2812_PWM_FREQUENCY / WS2812_PWM_TARGET_PERIOD) /**< Clock period in ticks. 1 / 800kHz = 1.25 uS (as per datasheet) */ - -/** - * @brief Number of bit-periods to hold the data line low at the end of a frame - * - * The reset period for each frame is defined in WS2812_TRST_US. - * Calculate the number of zeroes to add at the end assuming 1.25 uS/bit: - */ -#define WS2812_RESET_BIT_N (1000 * WS2812_TRST_US / 1250) -#define WS2812_COLOR_BIT_N (RGBLED_NUM * 24) /**< Number of data bits */ -#define WS2812_BIT_N (WS2812_COLOR_BIT_N + WS2812_RESET_BIT_N) /**< Total number of bits in a frame */ - -/** - * @brief High period for a zero, in ticks - * - * Per the datasheet: - * WS2812: - * - T0H: 200 nS to 500 nS, inclusive - * - T0L: 650 nS to 950 nS, inclusive - * WS2812B: - * - T0H: 200 nS to 500 nS, inclusive - * - T0L: 750 nS to 1050 nS, inclusive - * - * The duty cycle is calculated for a high period of 350 nS. - */ -#define WS2812_DUTYCYCLE_0 (WS2812_PWM_FREQUENCY / (1000000000 / 350)) - -/** - * @brief High period for a one, in ticks - * - * Per the datasheet: - * WS2812: - * - T1H: 550 nS to 850 nS, inclusive - * - T1L: 450 nS to 750 nS, inclusive - * WS2812B: - * - T1H: 750 nS to 1050 nS, inclusive - * - T1L: 200 nS to 500 nS, inclusive - * - * The duty cycle is calculated for a high period of 800 nS. - * This is in the middle of the specifications of the WS2812 and WS2812B. - */ -#define WS2812_DUTYCYCLE_1 (WS2812_PWM_FREQUENCY / (1000000000 / 800)) - -/* --- PRIVATE MACROS ------------------------------------------------------- */ - -/** - * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given bit - * - * @param[in] led: The led index [0, @ref RGBLED_NUM) - * @param[in] byte: The byte number [0, 2] - * @param[in] bit: The bit number [0, 7] - * - * @return The bit index - */ -#define WS2812_BIT(led, byte, bit) (24 * (led) + 8 * (byte) + (7 - (bit))) - -#if (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_GRB) -/** - * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given red bit - * - * @note The red byte is the middle byte in the color packet - * - * @param[in] led: The led index [0, @ref RGBLED_NUM) - * @param[in] bit: The bit number [0, 7] - * - * @return The bit index - */ -# define WS2812_RED_BIT(led, bit) WS2812_BIT((led), 1, (bit)) - -/** - * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given green bit - * - * @note The red byte is the first byte in the color packet - * - * @param[in] led: The led index [0, @ref RGBLED_NUM) - * @param[in] bit: The bit number [0, 7] - * - * @return The bit index - */ -# define WS2812_GREEN_BIT(led, bit) WS2812_BIT((led), 0, (bit)) - -/** - * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given blue bit - * - * @note The red byte is the last byte in the color packet - * - * @param[in] led: The led index [0, @ref RGBLED_NUM) - * @param[in] bit: The bit index [0, 7] - * - * @return The bit index - */ -# define WS2812_BLUE_BIT(led, bit) WS2812_BIT((led), 2, (bit)) - -#elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_RGB) -/** - * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given red bit - * - * @note The red byte is the middle byte in the color packet - * - * @param[in] led: The led index [0, @ref RGBLED_NUM) - * @param[in] bit: The bit number [0, 7] - * - * @return The bit index - */ -# define WS2812_RED_BIT(led, bit) WS2812_BIT((led), 0, (bit)) - -/** - * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given green bit - * - * @note The red byte is the first byte in the color packet - * - * @param[in] led: The led index [0, @ref RGBLED_NUM) - * @param[in] bit: The bit number [0, 7] - * - * @return The bit index - */ -# define WS2812_GREEN_BIT(led, bit) WS2812_BIT((led), 1, (bit)) - -/** - * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given blue bit - * - * @note The red byte is the last byte in the color packet - * - * @param[in] led: The led index [0, @ref RGBLED_NUM) - * @param[in] bit: The bit index [0, 7] - * - * @return The bit index - */ -# define WS2812_BLUE_BIT(led, bit) WS2812_BIT((led), 2, (bit)) - -#elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_BGR) -/** - * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given red bit - * - * @note The red byte is the middle byte in the color packet - * - * @param[in] led: The led index [0, @ref RGBLED_NUM) - * @param[in] bit: The bit number [0, 7] - * - * @return The bit index - */ -# define WS2812_RED_BIT(led, bit) WS2812_BIT((led), 2, (bit)) - -/** - * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given green bit - * - * @note The red byte is the first byte in the color packet - * - * @param[in] led: The led index [0, @ref RGBLED_NUM) - * @param[in] bit: The bit number [0, 7] - * - * @return The bit index - */ -# define WS2812_GREEN_BIT(led, bit) WS2812_BIT((led), 1, (bit)) - -/** - * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given blue bit - * - * @note The red byte is the last byte in the color packet - * - * @param[in] led: The led index [0, @ref RGBLED_NUM) - * @param[in] bit: The bit index [0, 7] - * - * @return The bit index - */ -# define WS2812_BLUE_BIT(led, bit) WS2812_BIT((led), 0, (bit)) -#endif - -/* --- PRIVATE VARIABLES ---------------------------------------------------- */ - -static uint32_t ws2812_frame_buffer[WS2812_BIT_N + 1]; /**< Buffer for a frame */ - -/* --- PUBLIC FUNCTIONS ----------------------------------------------------- */ -/* - * Gedanke: Double-buffer type transactions: double buffer transfers using two memory pointers for -the memory (while the DMA is reading/writing from/to a buffer, the application can -write/read to/from the other buffer). - */ - -void ws2812_init(void) { - // Initialize led frame buffer - uint32_t i; - for (i = 0; i < WS2812_COLOR_BIT_N; i++) ws2812_frame_buffer[i] = WS2812_DUTYCYCLE_0; // All color bits are zero duty cycle - for (i = 0; i < WS2812_RESET_BIT_N; i++) ws2812_frame_buffer[i + WS2812_COLOR_BIT_N] = 0; // All reset bits are zero - - palSetLineMode(RGB_DI_PIN, WS2812_OUTPUT_MODE); - - // PWM Configuration - //#pragma GCC diagnostic ignored "-Woverride-init" // Turn off override-init warning for this struct. We use the overriding ability to set a "default" channel config - static const PWMConfig ws2812_pwm_config = { - .frequency = WS2812_PWM_FREQUENCY, - .period = WS2812_PWM_PERIOD, // Mit dieser Periode wird UDE-Event erzeugt und ein neuer Wert (Länge WS2812_BIT_N) vom DMA ins CCR geschrieben - .callback = NULL, - .channels = - { - [0 ... 3] = {.mode = PWM_OUTPUT_DISABLED, .callback = NULL}, // Channels default to disabled - [WS2812_PWM_CHANNEL - 1] = {.mode = WS2812_PWM_OUTPUT_MODE, .callback = NULL}, // Turn on the channel we care about - }, - .cr2 = 0, - .dier = TIM_DIER_UDE, // DMA on update event for next period - }; - //#pragma GCC diagnostic pop // Restore command-line warning options - - // Configure DMA - // dmaInit(); // Joe added this - dmaStreamAlloc(WS2812_DMA_STREAM - STM32_DMA_STREAM(0), 10, NULL, NULL); - dmaStreamSetPeripheral(WS2812_DMA_STREAM, &(WS2812_PWM_DRIVER.tim->CCR[WS2812_PWM_CHANNEL - 1])); // Ziel ist der An-Zeit im Cap-Comp-Register - dmaStreamSetMemory0(WS2812_DMA_STREAM, ws2812_frame_buffer); - dmaStreamSetTransactionSize(WS2812_DMA_STREAM, WS2812_BIT_N); - dmaStreamSetMode(WS2812_DMA_STREAM, STM32_DMA_CR_CHSEL(WS2812_DMA_CHANNEL) | STM32_DMA_CR_DIR_M2P | STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC | STM32_DMA_CR_PL(3)); - // M2P: Memory 2 Periph; PL: Priority Level - -#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) - // If the MCU has a DMAMUX we need to assign the correct resource - dmaSetRequestSource(WS2812_DMA_STREAM, WS2812_DMAMUX_ID); -#endif - - // Start DMA - dmaStreamEnable(WS2812_DMA_STREAM); - - // Configure PWM - // NOTE: It's required that preload be enabled on the timer channel CCR register. This is currently enabled in the - // ChibiOS driver code, so we don't have to do anything special to the timer. If we did, we'd have to start the timer, - // disable counting, enable the channel, and then make whatever configuration changes we need. - pwmStart(&WS2812_PWM_DRIVER, &ws2812_pwm_config); - pwmEnableChannel(&WS2812_PWM_DRIVER, WS2812_PWM_CHANNEL - 1, 0); // Initial period is 0; output will be low until first duty cycle is DMA'd in -} - -void ws2812_write_led(uint16_t led_number, uint8_t r, uint8_t g, uint8_t b) { - // Write color to frame buffer - for (uint8_t bit = 0; bit < 8; bit++) { - ws2812_frame_buffer[WS2812_RED_BIT(led_number, bit)] = ((r >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0; - ws2812_frame_buffer[WS2812_GREEN_BIT(led_number, bit)] = ((g >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0; - ws2812_frame_buffer[WS2812_BLUE_BIT(led_number, bit)] = ((b >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0; - } -} - -// Setleds for standard RGB -void ws2812_setleds(LED_TYPE* ledarray, uint16_t leds) { - static bool s_init = false; - if (!s_init) { - ws2812_init(); - s_init = true; - } - - for (uint16_t i = 0; i < leds; i++) { - ws2812_write_led(i, ledarray[i].r, ledarray[i].g, ledarray[i].b); - } -} diff --git a/drivers/chibios/ws2812_spi.c b/drivers/chibios/ws2812_spi.c deleted file mode 100644 index 377a929b94..0000000000 --- a/drivers/chibios/ws2812_spi.c +++ /dev/null @@ -1,159 +0,0 @@ -#include "quantum.h" -#include "ws2812.h" - -/* Adapted from https://github.com/gamazeps/ws2812b-chibios-SPIDMA/ */ - -#ifdef RGBW -# error "RGBW not supported" -#endif - -// Define the spi your LEDs are plugged to here -#ifndef WS2812_SPI -# define WS2812_SPI SPID1 -#endif - -#ifndef WS2812_SPI_MOSI_PAL_MODE -# define WS2812_SPI_MOSI_PAL_MODE 5 -#endif - -#ifndef WS2812_SPI_SCK_PAL_MODE -# define WS2812_SPI_SCK_PAL_MODE 5 -#endif - -// Push Pull or Open Drain Configuration -// Default Push Pull -#ifndef WS2812_EXTERNAL_PULLUP -# if defined(USE_GPIOV1) -# define WS2812_MOSI_OUTPUT_MODE PAL_MODE_STM32_ALTERNATE_PUSHPULL -# else -# define WS2812_MOSI_OUTPUT_MODE PAL_MODE_ALTERNATE(WS2812_SPI_MOSI_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL -# endif -#else -# if defined(USE_GPIOV1) -# define WS2812_MOSI_OUTPUT_MODE PAL_MODE_STM32_ALTERNATE_OPENDRAIN -# else -# define WS2812_MOSI_OUTPUT_MODE PAL_MODE_ALTERNATE(WS2812_SPI_MOSI_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN -# endif -#endif - -// Define SPI config speed -// baudrate should target 3.2MHz -// F072 fpclk = 48MHz -// 48/16 = 3Mhz -#if WS2812_SPI_DIVISOR == 2 -# define WS2812_SPI_DIVISOR (0) -#elif WS2812_SPI_DIVISOR == 4 -# define WS2812_SPI_DIVISOR (SPI_CR1_BR_0) -#elif WS2812_SPI_DIVISOR == 8 -# define WS2812_SPI_DIVISOR (SPI_CR1_BR_1) -#elif WS2812_SPI_DIVISOR == 16 // same as default -# define WS2812_SPI_DIVISOR (SPI_CR1_BR_1 | SPI_CR1_BR_0) -#elif WS2812_SPI_DIVISOR == 32 -# define WS2812_SPI_DIVISOR (SPI_CR1_BR_2) -#elif WS2812_SPI_DIVISOR == 64 -# define WS2812_SPI_DIVISOR (SPI_CR1_BR_2 | SPI_CR1_BR_0) -#elif WS2812_SPI_DIVISOR == 128 -# define WS2812_SPI_DIVISOR (SPI_CR1_BR_2 | SPI_CR1_BR_1) -#elif WS2812_SPI_DIVISOR == 256 -# define WS2812_SPI_DIVISOR (SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_BR_0) -#else -# define WS2812_SPI_DIVISOR (SPI_CR1_BR_1 | SPI_CR1_BR_0) // default -#endif - -// Use SPI circular buffer -#ifdef WS2812_SPI_USE_CIRCULAR_BUFFER -# define WS2812_SPI_BUFFER_MODE 1 // circular buffer -#else -# define WS2812_SPI_BUFFER_MODE 0 // normal buffer -#endif - -#if defined(USE_GPIOV1) -# define WS2812_SCK_OUTPUT_MODE PAL_MODE_STM32_ALTERNATE_PUSHPULL -#else -# define WS2812_SCK_OUTPUT_MODE PAL_MODE_ALTERNATE(WS2812_SPI_SCK_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL -#endif - -#define BYTES_FOR_LED_BYTE 4 -#define NB_COLORS 3 -#define BYTES_FOR_LED (BYTES_FOR_LED_BYTE * NB_COLORS) -#define DATA_SIZE (BYTES_FOR_LED * RGBLED_NUM) -#define RESET_SIZE (1000 * WS2812_TRST_US / (2 * 1250)) -#define PREAMBLE_SIZE 4 - -static uint8_t txbuf[PREAMBLE_SIZE + DATA_SIZE + RESET_SIZE] = {0}; - -/* - * As the trick here is to use the SPI to send a huge pattern of 0 and 1 to - * the ws2812b protocol, we use this helper function to translate bytes into - * 0s and 1s for the LED (with the appropriate timing). - */ -static uint8_t get_protocol_eq(uint8_t data, int pos) { - uint8_t eq = 0; - if (data & (1 << (2 * (3 - pos)))) - eq = 0b1110; - else - eq = 0b1000; - if (data & (2 << (2 * (3 - pos)))) - eq += 0b11100000; - else - eq += 0b10000000; - return eq; -} - -static void set_led_color_rgb(LED_TYPE color, int pos) { - uint8_t* tx_start = &txbuf[PREAMBLE_SIZE]; - -#if (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_GRB) - for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + j] = get_protocol_eq(color.g, j); - for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE + j] = get_protocol_eq(color.r, j); - for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE * 2 + j] = get_protocol_eq(color.b, j); -#elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_RGB) - for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + j] = get_protocol_eq(color.r, j); - for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE + j] = get_protocol_eq(color.g, j); - for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE * 2 + j] = get_protocol_eq(color.b, j); -#elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_BGR) - for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + j] = get_protocol_eq(color.b, j); - for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE + j] = get_protocol_eq(color.g, j); - for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE * 2 + j] = get_protocol_eq(color.r, j); -#endif -} - -void ws2812_init(void) { - palSetLineMode(RGB_DI_PIN, WS2812_MOSI_OUTPUT_MODE); - -#ifdef WS2812_SPI_SCK_PIN - palSetLineMode(WS2812_SPI_SCK_PIN, WS2812_SCK_OUTPUT_MODE); -#endif // WS2812_SPI_SCK_PIN - - // TODO: more dynamic baudrate - static const SPIConfig spicfg = {WS2812_SPI_BUFFER_MODE, NULL, PAL_PORT(RGB_DI_PIN), PAL_PAD(RGB_DI_PIN), WS2812_SPI_DIVISOR}; - - spiAcquireBus(&WS2812_SPI); /* Acquire ownership of the bus. */ - spiStart(&WS2812_SPI, &spicfg); /* Setup transfer parameters. */ - spiSelect(&WS2812_SPI); /* Slave Select assertion. */ -#ifdef WS2812_SPI_USE_CIRCULAR_BUFFER - spiStartSend(&WS2812_SPI, sizeof(txbuf) / sizeof(txbuf[0]), txbuf); -#endif -} - -void ws2812_setleds(LED_TYPE* ledarray, uint16_t leds) { - static bool s_init = false; - if (!s_init) { - ws2812_init(); - s_init = true; - } - - for (uint8_t i = 0; i < leds; i++) { - set_led_color_rgb(ledarray[i], i); - } - - // Send async - each led takes ~0.03ms, 50 leds ~1.5ms, animations flushing faster than send will cause issues. - // Instead spiSend can be used to send synchronously (or the thread logic can be added back). -#ifndef WS2812_SPI_USE_CIRCULAR_BUFFER -# ifdef WS2812_SPI_SYNC - spiSend(&WS2812_SPI, sizeof(txbuf) / sizeof(txbuf[0]), txbuf); -# else - spiStartSend(&WS2812_SPI, sizeof(txbuf) / sizeof(txbuf[0]), txbuf); -# endif -#endif -} diff --git a/drivers/eeprom/eeprom_stm32_L0_L1.c b/drivers/eeprom/eeprom_stm32_L0_L1.c deleted file mode 100644 index ed26cc7145..0000000000 --- a/drivers/eeprom/eeprom_stm32_L0_L1.c +++ /dev/null @@ -1,96 +0,0 @@ -/* Copyright 2020 Nick Brassel (tzarc) - * - * 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 . - */ - -#include -#include - -#include -#include "eeprom_driver.h" -#include "eeprom_stm32_L0_L1.h" - -#define EEPROM_BASE_ADDR 0x08080000 -#define EEPROM_ADDR(offset) (EEPROM_BASE_ADDR + (offset)) -#define EEPROM_PTR(offset) ((__IO uint8_t *)EEPROM_ADDR(offset)) -#define EEPROM_BYTE(location, offset) (*(EEPROM_PTR(((uint32_t)location) + ((uint32_t)offset)))) - -#define BUFFER_BYTE(buffer, offset) (*(((uint8_t *)buffer) + offset)) - -#define FLASH_PEKEY1 0x89ABCDEF -#define FLASH_PEKEY2 0x02030405 - -static inline void STM32_L0_L1_EEPROM_WaitNotBusy(void) { - while (FLASH->SR & FLASH_SR_BSY) { - __WFI(); - } -} - -static inline void STM32_L0_L1_EEPROM_Unlock(void) { - STM32_L0_L1_EEPROM_WaitNotBusy(); - if (FLASH->PECR & FLASH_PECR_PELOCK) { - FLASH->PEKEYR = FLASH_PEKEY1; - FLASH->PEKEYR = FLASH_PEKEY2; - } -} - -static inline void STM32_L0_L1_EEPROM_Lock(void) { - STM32_L0_L1_EEPROM_WaitNotBusy(); - FLASH->PECR |= FLASH_PECR_PELOCK; -} - -void eeprom_driver_init(void) {} - -void eeprom_driver_erase(void) { - STM32_L0_L1_EEPROM_Unlock(); - - for (size_t offset = 0; offset < STM32_ONBOARD_EEPROM_SIZE; offset += sizeof(uint32_t)) { - FLASH->PECR |= FLASH_PECR_ERASE | FLASH_PECR_DATA; - - *(__IO uint32_t *)EEPROM_ADDR(offset) = (uint32_t)0; - - STM32_L0_L1_EEPROM_WaitNotBusy(); - FLASH->PECR &= ~(FLASH_PECR_ERASE | FLASH_PECR_DATA); - } - - STM32_L0_L1_EEPROM_Lock(); -} - -void eeprom_read_block(void *buf, const void *addr, size_t len) { - for (size_t offset = 0; offset < len; ++offset) { - // Drop out if we've hit the limit of the EEPROM - if ((((uint32_t)addr) + offset) >= STM32_ONBOARD_EEPROM_SIZE) { - break; - } - - STM32_L0_L1_EEPROM_WaitNotBusy(); - BUFFER_BYTE(buf, offset) = EEPROM_BYTE(addr, offset); - } -} - -void eeprom_write_block(const void *buf, void *addr, size_t len) { - STM32_L0_L1_EEPROM_Unlock(); - - for (size_t offset = 0; offset < len; ++offset) { - // Drop out if we've hit the limit of the EEPROM - if ((((uint32_t)addr) + offset) >= STM32_ONBOARD_EEPROM_SIZE) { - break; - } - - STM32_L0_L1_EEPROM_WaitNotBusy(); - EEPROM_BYTE(addr, offset) = BUFFER_BYTE(buf, offset); - } - - STM32_L0_L1_EEPROM_Lock(); -} diff --git a/drivers/eeprom/eeprom_stm32_L0_L1.h b/drivers/eeprom/eeprom_stm32_L0_L1.h deleted file mode 100644 index a35defca8b..0000000000 --- a/drivers/eeprom/eeprom_stm32_L0_L1.h +++ /dev/null @@ -1,33 +0,0 @@ -/* Copyright 2020 Nick Brassel (tzarc) - * - * 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 . - */ - -#pragma once - -/* - The size used by the STM32 L0/L1 EEPROM driver. -*/ -#ifndef STM32_ONBOARD_EEPROM_SIZE -# ifdef VIA_ENABLE -# define STM32_ONBOARD_EEPROM_SIZE 1024 -# else -# include "eeconfig.h" -# define STM32_ONBOARD_EEPROM_SIZE (((EECONFIG_SIZE + 3) / 4) * 4) // based off eeconfig's current usage, aligned to 4-byte sizes, to deal with LTO and EEPROM page sizing -# endif -#endif - -#if STM32_ONBOARD_EEPROM_SIZE > 128 -# pragma message("Please note: resetting EEPROM using an STM32L0/L1 device takes up to 1 second for every 1kB of internal EEPROM used.") -#endif diff --git a/platforms/avr/drivers/analog.c b/platforms/avr/drivers/analog.c new file mode 100644 index 0000000000..8d299ffdb9 --- /dev/null +++ b/platforms/avr/drivers/analog.c @@ -0,0 +1,138 @@ +/* Copyright 2015 Jack Humbert + * + * 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 . + */ + +#include +#include +#include +#include "analog.h" + +static uint8_t aref = ADC_REF_POWER; + +void analogReference(uint8_t mode) { aref = mode & (_BV(REFS1) | _BV(REFS0)); } + +// Arduino compatible pin input +int16_t analogRead(uint8_t pin) { +#if defined(__AVR_ATmega32U4__) + // clang-format off + static const uint8_t PROGMEM pin_to_mux[] = { + //A0 A1 A2 A3 A4 A5 + //F7 F6 F5 F4 F1 F0 + 0x07, 0x06, 0x05, 0x04, 0x01, 0x00, + //A6 A7 A8 A9 A10 A11 + //D4 D7 B4 B5 B6 D6 + 0x20, 0x22, 0x23, 0x24, 0x25, 0x21 + }; + // clang-format on + if (pin >= 12) return 0; + return adc_read(pgm_read_byte(pin_to_mux + pin)); +#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) + if (pin >= 8) return 0; + return adc_read(pin); +#else + return 0; +#endif +} + +int16_t analogReadPin(pin_t pin) { return adc_read(pinToMux(pin)); } + +uint8_t pinToMux(pin_t pin) { + switch (pin) { + // clang-format off +#if defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) + case F0: return 0; // ADC0 + case F1: return _BV(MUX0); // ADC1 + case F2: return _BV(MUX1); // ADC2 + case F3: return _BV(MUX1) | _BV(MUX0); // ADC3 + case F4: return _BV(MUX2); // ADC4 + case F5: return _BV(MUX2) | _BV(MUX0); // ADC5 + case F6: return _BV(MUX2) | _BV(MUX1); // ADC6 + case F7: return _BV(MUX2) | _BV(MUX1) | _BV(MUX0); // ADC7 + default: return _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0); // 0V +#elif defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) + case F0: return 0; // ADC0 + case F1: return _BV(MUX0); // ADC1 + case F4: return _BV(MUX2); // ADC4 + case F5: return _BV(MUX2) | _BV(MUX0); // ADC5 + case F6: return _BV(MUX2) | _BV(MUX1); // ADC6 + case F7: return _BV(MUX2) | _BV(MUX1) | _BV(MUX0); // ADC7 + case D4: return _BV(MUX5); // ADC8 + case D6: return _BV(MUX5) | _BV(MUX0); // ADC9 + case D7: return _BV(MUX5) | _BV(MUX1); // ADC10 + case B4: return _BV(MUX5) | _BV(MUX1) | _BV(MUX0); // ADC11 + case B5: return _BV(MUX5) | _BV(MUX2); // ADC12 + case B6: return _BV(MUX5) | _BV(MUX2) | _BV(MUX0); // ADC13 + default: return _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0); // 0V +#elif defined(__AVR_ATmega32A__) + case A0: return 0; // ADC0 + case A1: return _BV(MUX0); // ADC1 + case A2: return _BV(MUX1); // ADC2 + case A3: return _BV(MUX1) | _BV(MUX0); // ADC3 + case A4: return _BV(MUX2); // ADC4 + case A5: return _BV(MUX2) | _BV(MUX0); // ADC5 + case A6: return _BV(MUX2) | _BV(MUX1); // ADC6 + case A7: return _BV(MUX2) | _BV(MUX1) | _BV(MUX0); // ADC7 + default: return _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0); // 0V +#elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) + case C0: return 0; // ADC0 + case C1: return _BV(MUX0); // ADC1 + case C2: return _BV(MUX1); // ADC2 + case C3: return _BV(MUX1) | _BV(MUX0); // ADC3 + case C4: return _BV(MUX2); // ADC4 + case C5: return _BV(MUX2) | _BV(MUX0); // ADC5 + // ADC7:6 not present in DIP package and not shared by GPIO pins + default: return _BV(MUX3) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0); // 0V +#endif + // clang-format on + } + return 0; +} + +int16_t adc_read(uint8_t mux) { + uint16_t low; + + // Enable ADC and configure prescaler + ADCSRA = _BV(ADEN) | ADC_PRESCALER; + +#if defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) + // High speed mode and ADC8-13 + ADCSRB = _BV(ADHSM) | (mux & _BV(MUX5)); +#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) + // High speed mode only + ADCSRB = _BV(ADHSM); +#endif + + // Configure mux input +#if defined(MUX4) + ADMUX = aref | (mux & (_BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0))); +#else + ADMUX = aref | (mux & (_BV(MUX3) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0))); +#endif + + // Start the conversion + ADCSRA |= _BV(ADSC); + // Wait for result + while (ADCSRA & _BV(ADSC)) + ; + // Must read LSB first + low = ADCL; + // Must read MSB only once! + low |= (ADCH << 8); + + // turn off the ADC + ADCSRA &= ~(1 << ADEN); + + return low; +} diff --git a/platforms/avr/drivers/analog.h b/platforms/avr/drivers/analog.h new file mode 100644 index 0000000000..058882450d --- /dev/null +++ b/platforms/avr/drivers/analog.h @@ -0,0 +1,53 @@ +/* Copyright 2015 Jack Humbert + * + * 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 . + */ + +#pragma once + +#include +#include "quantum.h" + +#ifdef __cplusplus +extern "C" { +#endif +void analogReference(uint8_t mode); +int16_t analogRead(uint8_t pin); + +int16_t analogReadPin(pin_t pin); +uint8_t pinToMux(pin_t pin); + +int16_t adc_read(uint8_t mux); +#ifdef __cplusplus +} +#endif + +#define ADC_REF_EXTERNAL 0 // AREF, Internal Vref turned off +#define ADC_REF_POWER _BV(REFS0) // AVCC with external capacitor on AREF pin +#define ADC_REF_INTERNAL (_BV(REFS1) | _BV(REFS0)) // Internal 2.56V Voltage Reference with external capacitor on AREF pin (1.1V for 328P) + +// These prescaler values are for high speed mode, ADHSM = 1 +#if F_CPU == 16000000L || F_CPU == 12000000L +# define ADC_PRESCALER (_BV(ADPS2) | _BV(ADPS1)) // /64 +#elif F_CPU == 8000000L +# define ADC_PRESCALER (_BV(ADPS2) | _BV(ADPS0)) // /32 +#elif F_CPU == 4000000L +# define ADC_PRESCALER (_BV(ADPS2)) // /16 +#elif F_CPU == 2000000L +# define ADC_PRESCALER (_BV(ADPS1) | _BV(ADPS0)) // /8 +#elif F_CPU == 1000000L +# define ADC_PRESCALER _BV(ADPS1) // /4 +#else +# define ADC_PRESCALER _BV(ADPS0) // /2 +#endif diff --git a/platforms/avr/drivers/glcdfont.c b/platforms/avr/drivers/glcdfont.c new file mode 100644 index 0000000000..5e763b054f --- /dev/null +++ b/platforms/avr/drivers/glcdfont.c @@ -0,0 +1,23 @@ +// This is the 'classic' fixed-space bitmap font for Adafruit_GFX since 1.0. +// See gfxfont.h for newer custom bitmap font info. + +#include "progmem.h" + +// Standard ASCII 5x7 font + +static const unsigned char font[] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x5B, 0x4F, 0x5B, 0x3E, 0x3E, 0x6B, 0x4F, 0x6B, 0x3E, 0x1C, 0x3E, 0x7C, 0x3E, 0x1C, 0x18, 0x3C, 0x7E, 0x3C, 0x18, 0x1C, 0x57, 0x7D, 0x57, 0x1C, 0x1C, 0x5E, 0x7F, 0x5E, 0x1C, 0x00, 0x18, 0x3C, 0x18, 0x00, 0xFF, 0xE7, 0xC3, 0xE7, 0xFF, 0x00, 0x18, 0x24, 0x18, 0x00, 0xFF, 0xE7, 0xDB, 0xE7, 0xFF, 0x30, 0x48, 0x3A, 0x06, 0x0E, 0x26, 0x29, 0x79, 0x29, 0x26, 0x40, 0x7F, 0x05, 0x05, 0x07, 0x40, 0x7F, 0x05, 0x25, 0x3F, 0x5A, 0x3C, 0xE7, 0x3C, 0x5A, 0x7F, 0x3E, 0x1C, 0x1C, 0x08, 0x08, 0x1C, 0x1C, 0x3E, 0x7F, 0x14, 0x22, 0x7F, 0x22, 0x14, 0x5F, 0x5F, 0x00, 0x5F, 0x5F, 0x06, 0x09, 0x7F, 0x01, 0x7F, 0x00, 0x66, 0x89, 0x95, 0x6A, 0x60, 0x60, 0x60, 0x60, 0x60, 0x94, 0xA2, 0xFF, 0xA2, 0x94, 0x08, 0x04, 0x7E, 0x04, 0x08, 0x10, 0x20, 0x7E, 0x20, 0x10, 0x08, 0x08, 0x2A, 0x1C, 0x08, 0x08, 0x1C, 0x2A, 0x08, 0x08, 0x1E, 0x10, 0x10, 0x10, 0x10, 0x0C, 0x1E, 0x0C, 0x1E, 0x0C, + 0x30, 0x38, 0x3E, 0x38, 0x30, 0x06, 0x0E, 0x3E, 0x0E, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0x14, 0x7F, 0x14, 0x7F, 0x14, 0x24, 0x2A, 0x7F, 0x2A, 0x12, 0x23, 0x13, 0x08, 0x64, 0x62, 0x36, 0x49, 0x56, 0x20, 0x50, 0x00, 0x08, 0x07, 0x03, 0x00, 0x00, 0x1C, 0x22, 0x41, 0x00, 0x00, 0x41, 0x22, 0x1C, 0x00, 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00, 0x80, 0x70, 0x30, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x60, 0x60, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00, 0x42, 0x7F, 0x40, 0x00, 0x72, 0x49, 0x49, 0x49, 0x46, 0x21, 0x41, 0x49, 0x4D, 0x33, 0x18, 0x14, 0x12, 0x7F, 0x10, 0x27, 0x45, 0x45, 0x45, 0x39, 0x3C, 0x4A, 0x49, 0x49, 0x31, 0x41, 0x21, 0x11, 0x09, 0x07, 0x36, 0x49, 0x49, 0x49, 0x36, 0x46, 0x49, 0x49, 0x29, 0x1E, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x40, 0x34, 0x00, 0x00, + 0x00, 0x08, 0x14, 0x22, 0x41, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00, 0x41, 0x22, 0x14, 0x08, 0x02, 0x01, 0x59, 0x09, 0x06, 0x3E, 0x41, 0x5D, 0x59, 0x4E, 0x7C, 0x12, 0x11, 0x12, 0x7C, 0x7F, 0x49, 0x49, 0x49, 0x36, 0x3E, 0x41, 0x41, 0x41, 0x22, 0x7F, 0x41, 0x41, 0x41, 0x3E, 0x7F, 0x49, 0x49, 0x49, 0x41, 0x7F, 0x09, 0x09, 0x09, 0x01, 0x3E, 0x41, 0x41, 0x51, 0x73, 0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00, 0x41, 0x7F, 0x41, 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01, 0x7F, 0x08, 0x14, 0x22, 0x41, 0x7F, 0x40, 0x40, 0x40, 0x40, 0x7F, 0x02, 0x1C, 0x02, 0x7F, 0x7F, 0x04, 0x08, 0x10, 0x7F, 0x3E, 0x41, 0x41, 0x41, 0x3E, 0x7F, 0x09, 0x09, 0x09, 0x06, 0x3E, 0x41, 0x51, 0x21, 0x5E, 0x7F, 0x09, 0x19, 0x29, 0x46, 0x26, 0x49, 0x49, 0x49, 0x32, 0x03, 0x01, 0x7F, 0x01, 0x03, 0x3F, 0x40, 0x40, 0x40, 0x3F, 0x1F, 0x20, 0x40, 0x20, 0x1F, 0x3F, 0x40, 0x38, 0x40, 0x3F, 0x63, 0x14, 0x08, 0x14, 0x63, 0x03, 0x04, 0x78, 0x04, 0x03, + 0x61, 0x59, 0x49, 0x4D, 0x43, 0x00, 0x7F, 0x41, 0x41, 0x41, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, 0x41, 0x41, 0x41, 0x7F, 0x04, 0x02, 0x01, 0x02, 0x04, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x03, 0x07, 0x08, 0x00, 0x20, 0x54, 0x54, 0x78, 0x40, 0x7F, 0x28, 0x44, 0x44, 0x38, 0x38, 0x44, 0x44, 0x44, 0x28, 0x38, 0x44, 0x44, 0x28, 0x7F, 0x38, 0x54, 0x54, 0x54, 0x18, 0x00, 0x08, 0x7E, 0x09, 0x02, 0x18, 0xA4, 0xA4, 0x9C, 0x78, 0x7F, 0x08, 0x04, 0x04, 0x78, 0x00, 0x44, 0x7D, 0x40, 0x00, 0x20, 0x40, 0x40, 0x3D, 0x00, 0x7F, 0x10, 0x28, 0x44, 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00, 0x7C, 0x04, 0x78, 0x04, 0x78, 0x7C, 0x08, 0x04, 0x04, 0x78, 0x38, 0x44, 0x44, 0x44, 0x38, 0xFC, 0x18, 0x24, 0x24, 0x18, 0x18, 0x24, 0x24, 0x18, 0xFC, 0x7C, 0x08, 0x04, 0x04, 0x08, 0x48, 0x54, 0x54, 0x54, 0x24, 0x04, 0x04, 0x3F, 0x44, 0x24, 0x3C, 0x40, 0x40, 0x20, 0x7C, 0x1C, 0x20, 0x40, 0x20, 0x1C, 0x3C, 0x40, 0x30, 0x40, 0x3C, + 0x44, 0x28, 0x10, 0x28, 0x44, 0x4C, 0x90, 0x90, 0x90, 0x7C, 0x44, 0x64, 0x54, 0x4C, 0x44, 0x00, 0x08, 0x36, 0x41, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x41, 0x36, 0x08, 0x00, 0x02, 0x01, 0x02, 0x04, 0x02, 0x3C, 0x26, 0x23, 0x26, 0x3C, 0x1E, 0xA1, 0xA1, 0x61, 0x12, 0x3A, 0x40, 0x40, 0x20, 0x7A, 0x38, 0x54, 0x54, 0x55, 0x59, 0x21, 0x55, 0x55, 0x79, 0x41, 0x22, 0x54, 0x54, 0x78, 0x42, // a-umlaut + 0x21, 0x55, 0x54, 0x78, 0x40, 0x20, 0x54, 0x55, 0x79, 0x40, 0x0C, 0x1E, 0x52, 0x72, 0x12, 0x39, 0x55, 0x55, 0x55, 0x59, 0x39, 0x54, 0x54, 0x54, 0x59, 0x39, 0x55, 0x54, 0x54, 0x58, 0x00, 0x00, 0x45, 0x7C, 0x41, 0x00, 0x02, 0x45, 0x7D, 0x42, 0x00, 0x01, 0x45, 0x7C, 0x40, 0x7D, 0x12, 0x11, 0x12, 0x7D, // A-umlaut + 0xF0, 0x28, 0x25, 0x28, 0xF0, 0x7C, 0x54, 0x55, 0x45, 0x00, 0x20, 0x54, 0x54, 0x7C, 0x54, 0x7C, 0x0A, 0x09, 0x7F, 0x49, 0x32, 0x49, 0x49, 0x49, 0x32, 0x3A, 0x44, 0x44, 0x44, 0x3A, // o-umlaut + 0x32, 0x4A, 0x48, 0x48, 0x30, 0x3A, 0x41, 0x41, 0x21, 0x7A, 0x3A, 0x42, 0x40, 0x20, 0x78, 0x00, 0x9D, 0xA0, 0xA0, 0x7D, 0x3D, 0x42, 0x42, 0x42, 0x3D, // O-umlaut + 0x3D, 0x40, 0x40, 0x40, 0x3D, 0x3C, 0x24, 0xFF, 0x24, 0x24, 0x48, 0x7E, 0x49, 0x43, 0x66, 0x2B, 0x2F, 0xFC, 0x2F, 0x2B, 0xFF, 0x09, 0x29, 0xF6, 0x20, 0xC0, 0x88, 0x7E, 0x09, 0x03, 0x20, 0x54, 0x54, 0x79, 0x41, 0x00, 0x00, 0x44, 0x7D, 0x41, 0x30, 0x48, 0x48, 0x4A, 0x32, 0x38, 0x40, 0x40, 0x22, 0x7A, 0x00, 0x7A, 0x0A, 0x0A, 0x72, 0x7D, 0x0D, 0x19, 0x31, 0x7D, 0x26, 0x29, 0x29, 0x2F, 0x28, 0x26, 0x29, 0x29, 0x29, 0x26, 0x30, 0x48, 0x4D, 0x40, 0x20, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x2F, 0x10, 0xC8, 0xAC, 0xBA, 0x2F, 0x10, 0x28, 0x34, 0xFA, 0x00, 0x00, 0x7B, 0x00, 0x00, 0x08, 0x14, 0x2A, 0x14, 0x22, 0x22, 0x14, 0x2A, 0x14, 0x08, 0x55, 0x00, 0x55, 0x00, 0x55, // #176 (25% block) missing in old code + 0xAA, 0x55, 0xAA, 0x55, 0xAA, // 50% block + 0xFF, 0x55, 0xFF, 0x55, 0xFF, // 75% block + 0x00, 0x00, 0x00, 0xFF, 0x00, 0x10, 0x10, 0x10, 0xFF, 0x00, 0x14, 0x14, 0x14, 0xFF, 0x00, 0x10, 0x10, 0xFF, 0x00, 0xFF, 0x10, 0x10, 0xF0, 0x10, 0xF0, 0x14, 0x14, 0x14, 0xFC, 0x00, 0x14, 0x14, 0xF7, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x14, 0x14, 0xF4, 0x04, 0xFC, 0x14, 0x14, 0x17, 0x10, 0x1F, 0x10, 0x10, 0x1F, 0x10, 0x1F, 0x14, 0x14, 0x14, 0x1F, 0x00, 0x10, 0x10, 0x10, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x1F, 0x10, 0x10, 0x10, 0x10, 0xF0, 0x10, 0x00, 0x00, 0x00, 0xFF, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xFF, 0x10, 0x00, 0x00, 0x00, 0xFF, 0x14, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x1F, 0x10, 0x17, 0x00, 0x00, 0xFC, 0x04, 0xF4, 0x14, 0x14, 0x17, 0x10, 0x17, 0x14, 0x14, 0xF4, 0x04, 0xF4, 0x00, 0x00, 0xFF, 0x00, 0xF7, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0xF7, 0x00, 0xF7, 0x14, 0x14, 0x14, 0x17, 0x14, 0x10, 0x10, 0x1F, 0x10, 0x1F, + 0x14, 0x14, 0x14, 0xF4, 0x14, 0x10, 0x10, 0xF0, 0x10, 0xF0, 0x00, 0x00, 0x1F, 0x10, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x14, 0x00, 0x00, 0x00, 0xFC, 0x14, 0x00, 0x00, 0xF0, 0x10, 0xF0, 0x10, 0x10, 0xFF, 0x10, 0xFF, 0x14, 0x14, 0x14, 0xFF, 0x14, 0x10, 0x10, 0x10, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x38, 0x44, 0x44, 0x38, 0x44, 0xFC, 0x4A, 0x4A, 0x4A, 0x34, // sharp-s or beta + 0x7E, 0x02, 0x02, 0x06, 0x06, 0x02, 0x7E, 0x02, 0x7E, 0x02, 0x63, 0x55, 0x49, 0x41, 0x63, 0x38, 0x44, 0x44, 0x3C, 0x04, 0x40, 0x7E, 0x20, 0x1E, 0x20, 0x06, 0x02, 0x7E, 0x02, 0x02, 0x99, 0xA5, 0xE7, 0xA5, 0x99, 0x1C, 0x2A, 0x49, 0x2A, 0x1C, 0x4C, 0x72, 0x01, 0x72, 0x4C, 0x30, 0x4A, 0x4D, 0x4D, 0x30, 0x30, 0x48, 0x78, 0x48, 0x30, 0xBC, 0x62, 0x5A, 0x46, 0x3D, 0x3E, 0x49, 0x49, 0x49, 0x00, 0x7E, 0x01, 0x01, 0x01, 0x7E, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x44, 0x44, 0x5F, 0x44, 0x44, 0x40, 0x51, 0x4A, 0x44, 0x40, 0x40, 0x44, 0x4A, 0x51, 0x40, 0x00, 0x00, 0xFF, 0x01, 0x03, 0xE0, 0x80, 0xFF, 0x00, 0x00, 0x08, 0x08, 0x6B, 0x6B, 0x08, 0x36, 0x12, 0x36, 0x24, 0x36, 0x06, 0x0F, 0x09, 0x0F, 0x06, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x30, 0x40, 0xFF, 0x01, 0x01, 0x00, 0x1F, 0x01, 0x01, 0x1E, 0x00, 0x19, 0x1D, 0x17, 0x12, 0x00, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00 // #255 NBSP +}; diff --git a/platforms/avr/drivers/hd44780.c b/platforms/avr/drivers/hd44780.c new file mode 100644 index 0000000000..f71069dece --- /dev/null +++ b/platforms/avr/drivers/hd44780.c @@ -0,0 +1,536 @@ +/**************************************************************************** + Title: HD44780U LCD library + Author: Peter Fleury http://tinyurl.com/peterfleury + License: GNU General Public License Version 3 + File: $Id: lcd.c,v 1.15.2.2 2015/01/17 12:16:05 peter Exp $ + Software: AVR-GCC 3.3 + Target: any AVR device, memory mapped mode only for AT90S4414/8515/Mega + + DESCRIPTION + Basic routines for interfacing a HD44780U-based text lcd display + + Originally based on Volker Oth's lcd library, + changed lcd_init(), added additional constants for lcd_command(), + added 4-bit I/O mode, improved and optimized code. + + Library can be operated in memory mapped mode (LCD_IO_MODE=0) or in + 4-bit IO port mode (LCD_IO_MODE=1). 8-bit IO port mode not supported. + + Memory mapped mode compatible with Kanda STK200, but supports also + generation of R/W signal through A8 address line. + + USAGE + See the C include lcd.h file for a description of each function + +*****************************************************************************/ +#include +#include +#include +#include +#include "hd44780.h" + +/* +** constants/macros +*/ +#define DDR(x) (*(&x - 1)) /* address of data direction register of port x */ +#if defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) +/* on ATmega64/128 PINF is on port 0x00 and not 0x60 */ +# define PIN(x) (&PORTF == &(x) ? _SFR_IO8(0x00) : (*(&x - 2))) +#else +# define PIN(x) (*(&x - 2)) /* address of input register of port x */ +#endif + +#if LCD_IO_MODE +# define lcd_e_delay() _delay_us(LCD_DELAY_ENABLE_PULSE) +# define lcd_e_high() LCD_E_PORT |= _BV(LCD_E_PIN); +# define lcd_e_low() LCD_E_PORT &= ~_BV(LCD_E_PIN); +# define lcd_e_toggle() toggle_e() +# define lcd_rw_high() LCD_RW_PORT |= _BV(LCD_RW_PIN) +# define lcd_rw_low() LCD_RW_PORT &= ~_BV(LCD_RW_PIN) +# define lcd_rs_high() LCD_RS_PORT |= _BV(LCD_RS_PIN) +# define lcd_rs_low() LCD_RS_PORT &= ~_BV(LCD_RS_PIN) +#endif + +#if LCD_IO_MODE +# if LCD_LINES == 1 +# define LCD_FUNCTION_DEFAULT LCD_FUNCTION_4BIT_1LINE +# else +# define LCD_FUNCTION_DEFAULT LCD_FUNCTION_4BIT_2LINES +# endif +#else +# if LCD_LINES == 1 +# define LCD_FUNCTION_DEFAULT LCD_FUNCTION_8BIT_1LINE +# else +# define LCD_FUNCTION_DEFAULT LCD_FUNCTION_8BIT_2LINES +# endif +#endif + +#if LCD_CONTROLLER_KS0073 +# if LCD_LINES == 4 + +# define KS0073_EXTENDED_FUNCTION_REGISTER_ON 0x2C /* |0|010|1100 4-bit mode, extension-bit RE = 1 */ +# define KS0073_EXTENDED_FUNCTION_REGISTER_OFF 0x28 /* |0|010|1000 4-bit mode, extension-bit RE = 0 */ +# define KS0073_4LINES_MODE 0x09 /* |0|000|1001 4 lines mode */ + +# endif +#endif + +/* +** function prototypes +*/ +#if LCD_IO_MODE +static void toggle_e(void); +#endif + +/* +** local functions +*/ + +/************************************************************************* +delay for a minimum of microseconds +the number of loops is calculated at compile-time from MCU clock frequency +*************************************************************************/ +#define delay(us) _delay_us(us) + +#if LCD_IO_MODE +/* toggle Enable Pin to initiate write */ +static void toggle_e(void) { + lcd_e_high(); + lcd_e_delay(); + lcd_e_low(); +} +#endif + +/************************************************************************* +Low-level function to write byte to LCD controller +Input: data byte to write to LCD + rs 1: write data + 0: write instruction +Returns: none +*************************************************************************/ +#if LCD_IO_MODE +static void lcd_write(uint8_t data, uint8_t rs) { + unsigned char dataBits; + + if (rs) { /* write data (RS=1, RW=0) */ + lcd_rs_high(); + } else { /* write instruction (RS=0, RW=0) */ + lcd_rs_low(); + } + lcd_rw_low(); /* RW=0 write mode */ + + if ((&LCD_DATA0_PORT == &LCD_DATA1_PORT) && (&LCD_DATA1_PORT == &LCD_DATA2_PORT) && (&LCD_DATA2_PORT == &LCD_DATA3_PORT) && (LCD_DATA0_PIN == 0) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3)) { + /* configure data pins as output */ + DDR(LCD_DATA0_PORT) |= 0x0F; + + /* output high nibble first */ + dataBits = LCD_DATA0_PORT & 0xF0; + LCD_DATA0_PORT = dataBits | ((data >> 4) & 0x0F); + lcd_e_toggle(); + + /* output low nibble */ + LCD_DATA0_PORT = dataBits | (data & 0x0F); + lcd_e_toggle(); + + /* all data pins high (inactive) */ + LCD_DATA0_PORT = dataBits | 0x0F; + } else { + /* configure data pins as output */ + DDR(LCD_DATA0_PORT) |= _BV(LCD_DATA0_PIN); + DDR(LCD_DATA1_PORT) |= _BV(LCD_DATA1_PIN); + DDR(LCD_DATA2_PORT) |= _BV(LCD_DATA2_PIN); + DDR(LCD_DATA3_PORT) |= _BV(LCD_DATA3_PIN); + + /* output high nibble first */ + LCD_DATA3_PORT &= ~_BV(LCD_DATA3_PIN); + LCD_DATA2_PORT &= ~_BV(LCD_DATA2_PIN); + LCD_DATA1_PORT &= ~_BV(LCD_DATA1_PIN); + LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN); + if (data & 0x80) LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN); + if (data & 0x40) LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN); + if (data & 0x20) LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN); + if (data & 0x10) LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN); + lcd_e_toggle(); + + /* output low nibble */ + LCD_DATA3_PORT &= ~_BV(LCD_DATA3_PIN); + LCD_DATA2_PORT &= ~_BV(LCD_DATA2_PIN); + LCD_DATA1_PORT &= ~_BV(LCD_DATA1_PIN); + LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN); + if (data & 0x08) LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN); + if (data & 0x04) LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN); + if (data & 0x02) LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN); + if (data & 0x01) LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN); + lcd_e_toggle(); + + /* all data pins high (inactive) */ + LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN); + LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN); + LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN); + LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN); + } +} +#else +# define lcd_write(d, rs) \ + if (rs) \ + *(volatile uint8_t *)(LCD_IO_DATA) = d; \ + else \ + *(volatile uint8_t *)(LCD_IO_FUNCTION) = d; +/* rs==0 -> write instruction to LCD_IO_FUNCTION */ +/* rs==1 -> write data to LCD_IO_DATA */ +#endif + +/************************************************************************* +Low-level function to read byte from LCD controller +Input: rs 1: read data + 0: read busy flag / address counter +Returns: byte read from LCD controller +*************************************************************************/ +#if LCD_IO_MODE +static uint8_t lcd_read(uint8_t rs) { + uint8_t data; + + if (rs) + lcd_rs_high(); /* RS=1: read data */ + else + lcd_rs_low(); /* RS=0: read busy flag */ + lcd_rw_high(); /* RW=1 read mode */ + + if ((&LCD_DATA0_PORT == &LCD_DATA1_PORT) && (&LCD_DATA1_PORT == &LCD_DATA2_PORT) && (&LCD_DATA2_PORT == &LCD_DATA3_PORT) && (LCD_DATA0_PIN == 0) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3)) { + DDR(LCD_DATA0_PORT) &= 0xF0; /* configure data pins as input */ + + lcd_e_high(); + lcd_e_delay(); + data = PIN(LCD_DATA0_PORT) << 4; /* read high nibble first */ + lcd_e_low(); + + lcd_e_delay(); /* Enable 500ns low */ + + lcd_e_high(); + lcd_e_delay(); + data |= PIN(LCD_DATA0_PORT) & 0x0F; /* read low nibble */ + lcd_e_low(); + } else { + /* configure data pins as input */ + DDR(LCD_DATA0_PORT) &= ~_BV(LCD_DATA0_PIN); + DDR(LCD_DATA1_PORT) &= ~_BV(LCD_DATA1_PIN); + DDR(LCD_DATA2_PORT) &= ~_BV(LCD_DATA2_PIN); + DDR(LCD_DATA3_PORT) &= ~_BV(LCD_DATA3_PIN); + + /* read high nibble first */ + lcd_e_high(); + lcd_e_delay(); + data = 0; + if (PIN(LCD_DATA0_PORT) & _BV(LCD_DATA0_PIN)) data |= 0x10; + if (PIN(LCD_DATA1_PORT) & _BV(LCD_DATA1_PIN)) data |= 0x20; + if (PIN(LCD_DATA2_PORT) & _BV(LCD_DATA2_PIN)) data |= 0x40; + if (PIN(LCD_DATA3_PORT) & _BV(LCD_DATA3_PIN)) data |= 0x80; + lcd_e_low(); + + lcd_e_delay(); /* Enable 500ns low */ + + /* read low nibble */ + lcd_e_high(); + lcd_e_delay(); + if (PIN(LCD_DATA0_PORT) & _BV(LCD_DATA0_PIN)) data |= 0x01; + if (PIN(LCD_DATA1_PORT) & _BV(LCD_DATA1_PIN)) data |= 0x02; + if (PIN(LCD_DATA2_PORT) & _BV(LCD_DATA2_PIN)) data |= 0x04; + if (PIN(LCD_DATA3_PORT) & _BV(LCD_DATA3_PIN)) data |= 0x08; + lcd_e_low(); + } + return data; +} +#else +# define lcd_read(rs) (rs) ? *(volatile uint8_t *)(LCD_IO_DATA + LCD_IO_READ) : *(volatile uint8_t *)(LCD_IO_FUNCTION + LCD_IO_READ) +/* rs==0 -> read instruction from LCD_IO_FUNCTION */ +/* rs==1 -> read data from LCD_IO_DATA */ +#endif + +/************************************************************************* +loops while lcd is busy, returns address counter +*************************************************************************/ +static uint8_t lcd_waitbusy(void) + +{ + register uint8_t c; + + /* wait until busy flag is cleared */ + while ((c = lcd_read(0)) & (1 << LCD_BUSY)) { + } + + /* the address counter is updated 4us after the busy flag is cleared */ + delay(LCD_DELAY_BUSY_FLAG); + + /* now read the address counter */ + return (lcd_read(0)); // return address counter + +} /* lcd_waitbusy */ + +/************************************************************************* +Move cursor to the start of next line or to the first line if the cursor +is already on the last line. +*************************************************************************/ +static inline void lcd_newline(uint8_t pos) { + register uint8_t addressCounter; + +#if LCD_LINES == 1 + addressCounter = 0; +#endif +#if LCD_LINES == 2 + if (pos < (LCD_START_LINE2)) + addressCounter = LCD_START_LINE2; + else + addressCounter = LCD_START_LINE1; +#endif +#if LCD_LINES == 4 +# if KS0073_4LINES_MODE + if (pos < LCD_START_LINE2) + addressCounter = LCD_START_LINE2; + else if ((pos >= LCD_START_LINE2) && (pos < LCD_START_LINE3)) + addressCounter = LCD_START_LINE3; + else if ((pos >= LCD_START_LINE3) && (pos < LCD_START_LINE4)) + addressCounter = LCD_START_LINE4; + else + addressCounter = LCD_START_LINE1; +# else + if (pos < LCD_START_LINE3) + addressCounter = LCD_START_LINE2; + else if ((pos >= LCD_START_LINE2) && (pos < LCD_START_LINE4)) + addressCounter = LCD_START_LINE3; + else if ((pos >= LCD_START_LINE3) && (pos < LCD_START_LINE2)) + addressCounter = LCD_START_LINE4; + else + addressCounter = LCD_START_LINE1; +# endif +#endif + lcd_command((1 << LCD_DDRAM) + addressCounter); + +} /* lcd_newline */ + +/* +** PUBLIC FUNCTIONS +*/ + +/************************************************************************* +Send LCD controller instruction command +Input: instruction to send to LCD controller, see HD44780 data sheet +Returns: none +*************************************************************************/ +void lcd_command(uint8_t cmd) { + lcd_waitbusy(); + lcd_write(cmd, 0); +} + +/************************************************************************* +Send data byte to LCD controller +Input: data to send to LCD controller, see HD44780 data sheet +Returns: none +*************************************************************************/ +void lcd_data(uint8_t data) { + lcd_waitbusy(); + lcd_write(data, 1); +} + +/************************************************************************* +Set cursor to specified position +Input: x horizontal position (0: left most position) + y vertical position (0: first line) +Returns: none +*************************************************************************/ +void lcd_gotoxy(uint8_t x, uint8_t y) { +#if LCD_LINES == 1 + lcd_command((1 << LCD_DDRAM) + LCD_START_LINE1 + x); +#endif +#if LCD_LINES == 2 + if (y == 0) + lcd_command((1 << LCD_DDRAM) + LCD_START_LINE1 + x); + else + lcd_command((1 << LCD_DDRAM) + LCD_START_LINE2 + x); +#endif +#if LCD_LINES == 4 + if (y == 0) + lcd_command((1 << LCD_DDRAM) + LCD_START_LINE1 + x); + else if (y == 1) + lcd_command((1 << LCD_DDRAM) + LCD_START_LINE2 + x); + else if (y == 2) + lcd_command((1 << LCD_DDRAM) + LCD_START_LINE3 + x); + else /* y==3 */ + lcd_command((1 << LCD_DDRAM) + LCD_START_LINE4 + x); +#endif + +} /* lcd_gotoxy */ + +/************************************************************************* +*************************************************************************/ +int lcd_getxy(void) { return lcd_waitbusy(); } + +/************************************************************************* +Clear display and set cursor to home position +*************************************************************************/ +void lcd_clrscr(void) { lcd_command(1 << LCD_CLR); } + +/************************************************************************* +Set cursor to home position +*************************************************************************/ +void lcd_home(void) { lcd_command(1 << LCD_HOME); } + +/************************************************************************* +Display character at current cursor position +Input: character to be displayed +Returns: none +*************************************************************************/ +void lcd_putc(char c) { + uint8_t pos; + + pos = lcd_waitbusy(); // read busy-flag and address counter + if (c == '\n') { + lcd_newline(pos); + } else { +#if LCD_WRAP_LINES == 1 +# if LCD_LINES == 1 + if (pos == LCD_START_LINE1 + LCD_DISP_LENGTH) { + lcd_write((1 << LCD_DDRAM) + LCD_START_LINE1, 0); + } +# elif LCD_LINES == 2 + if (pos == LCD_START_LINE1 + LCD_DISP_LENGTH) { + lcd_write((1 << LCD_DDRAM) + LCD_START_LINE2, 0); + } else if (pos == LCD_START_LINE2 + LCD_DISP_LENGTH) { + lcd_write((1 << LCD_DDRAM) + LCD_START_LINE1, 0); + } +# elif LCD_LINES == 4 + if (pos == LCD_START_LINE1 + LCD_DISP_LENGTH) { + lcd_write((1 << LCD_DDRAM) + LCD_START_LINE2, 0); + } else if (pos == LCD_START_LINE2 + LCD_DISP_LENGTH) { + lcd_write((1 << LCD_DDRAM) + LCD_START_LINE3, 0); + } else if (pos == LCD_START_LINE3 + LCD_DISP_LENGTH) { + lcd_write((1 << LCD_DDRAM) + LCD_START_LINE4, 0); + } else if (pos == LCD_START_LINE4 + LCD_DISP_LENGTH) { + lcd_write((1 << LCD_DDRAM) + LCD_START_LINE1, 0); + } +# endif + lcd_waitbusy(); +#endif + lcd_write(c, 1); + } + +} /* lcd_putc */ + +/************************************************************************* +Display string without auto linefeed +Input: string to be displayed +Returns: none +*************************************************************************/ +void lcd_puts(const char *s) +/* print string on lcd (no auto linefeed) */ +{ + register char c; + + while ((c = *s++)) { + lcd_putc(c); + } + +} /* lcd_puts */ + +/************************************************************************* +Display string from program memory without auto linefeed +Input: string from program memory be be displayed +Returns: none +*************************************************************************/ +void lcd_puts_p(const char *progmem_s) +/* print string from program memory on lcd (no auto linefeed) */ +{ + register char c; + + while ((c = pgm_read_byte(progmem_s++))) { + lcd_putc(c); + } + +} /* lcd_puts_p */ + +/************************************************************************* +Initialize display and select type of cursor +Input: dispAttr LCD_DISP_OFF display off + LCD_DISP_ON display on, cursor off + LCD_DISP_ON_CURSOR display on, cursor on + LCD_DISP_CURSOR_BLINK display on, cursor on flashing +Returns: none +*************************************************************************/ +void lcd_init(uint8_t dispAttr) { +#if LCD_IO_MODE + /* + * Initialize LCD to 4 bit I/O mode + */ + + if ((&LCD_DATA0_PORT == &LCD_DATA1_PORT) && (&LCD_DATA1_PORT == &LCD_DATA2_PORT) && (&LCD_DATA2_PORT == &LCD_DATA3_PORT) && (&LCD_RS_PORT == &LCD_DATA0_PORT) && (&LCD_RW_PORT == &LCD_DATA0_PORT) && (&LCD_E_PORT == &LCD_DATA0_PORT) && (LCD_DATA0_PIN == 0) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3) && (LCD_RS_PIN == 4) && (LCD_RW_PIN == 5) && (LCD_E_PIN == 6)) { + /* configure all port bits as output (all LCD lines on same port) */ + DDR(LCD_DATA0_PORT) |= 0x7F; + } else if ((&LCD_DATA0_PORT == &LCD_DATA1_PORT) && (&LCD_DATA1_PORT == &LCD_DATA2_PORT) && (&LCD_DATA2_PORT == &LCD_DATA3_PORT) && (LCD_DATA0_PIN == 0) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3)) { + /* configure all port bits as output (all LCD data lines on same port, but control lines on different ports) */ + DDR(LCD_DATA0_PORT) |= 0x0F; + DDR(LCD_RS_PORT) |= _BV(LCD_RS_PIN); + DDR(LCD_RW_PORT) |= _BV(LCD_RW_PIN); + DDR(LCD_E_PORT) |= _BV(LCD_E_PIN); + } else { + /* configure all port bits as output (LCD data and control lines on different ports */ + DDR(LCD_RS_PORT) |= _BV(LCD_RS_PIN); + DDR(LCD_RW_PORT) |= _BV(LCD_RW_PIN); + DDR(LCD_E_PORT) |= _BV(LCD_E_PIN); + DDR(LCD_DATA0_PORT) |= _BV(LCD_DATA0_PIN); + DDR(LCD_DATA1_PORT) |= _BV(LCD_DATA1_PIN); + DDR(LCD_DATA2_PORT) |= _BV(LCD_DATA2_PIN); + DDR(LCD_DATA3_PORT) |= _BV(LCD_DATA3_PIN); + } + delay(LCD_DELAY_BOOTUP); /* wait 16ms or more after power-on */ + + /* initial write to lcd is 8bit */ + LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN); // LCD_FUNCTION>>4; + LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN); // LCD_FUNCTION_8BIT>>4; + lcd_e_toggle(); + delay(LCD_DELAY_INIT); /* delay, busy flag can't be checked here */ + + /* repeat last command */ + lcd_e_toggle(); + delay(LCD_DELAY_INIT_REP); /* delay, busy flag can't be checked here */ + + /* repeat last command a third time */ + lcd_e_toggle(); + delay(LCD_DELAY_INIT_REP); /* delay, busy flag can't be checked here */ + + /* now configure for 4bit mode */ + LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN); // LCD_FUNCTION_4BIT_1LINE>>4 + lcd_e_toggle(); + delay(LCD_DELAY_INIT_4BIT); /* some displays need this additional delay */ + + /* from now the LCD only accepts 4 bit I/O, we can use lcd_command() */ +#else + /* + * Initialize LCD to 8 bit memory mapped mode + */ + + /* enable external SRAM (memory mapped lcd) and one wait state */ + MCUCR = _BV(SRE) | _BV(SRW); + + /* reset LCD */ + delay(LCD_DELAY_BOOTUP); /* wait 16ms after power-on */ + lcd_write(LCD_FUNCTION_8BIT_1LINE, 0); /* function set: 8bit interface */ + delay(LCD_DELAY_INIT); /* wait 5ms */ + lcd_write(LCD_FUNCTION_8BIT_1LINE, 0); /* function set: 8bit interface */ + delay(LCD_DELAY_INIT_REP); /* wait 64us */ + lcd_write(LCD_FUNCTION_8BIT_1LINE, 0); /* function set: 8bit interface */ + delay(LCD_DELAY_INIT_REP); /* wait 64us */ +#endif + +#if KS0073_4LINES_MODE + /* Display with KS0073 controller requires special commands for enabling 4 line mode */ + lcd_command(KS0073_EXTENDED_FUNCTION_REGISTER_ON); + lcd_command(KS0073_4LINES_MODE); + lcd_command(KS0073_EXTENDED_FUNCTION_REGISTER_OFF); +#else + lcd_command(LCD_FUNCTION_DEFAULT); /* function set: display lines */ +#endif + lcd_command(LCD_DISP_OFF); /* display off */ + lcd_clrscr(); /* display clear */ + lcd_command(LCD_MODE_DEFAULT); /* set entry mode */ + lcd_command(dispAttr); /* display/cursor control */ + +} /* lcd_init */ diff --git a/platforms/avr/drivers/hd44780.h b/platforms/avr/drivers/hd44780.h new file mode 100644 index 0000000000..08e60f8a44 --- /dev/null +++ b/platforms/avr/drivers/hd44780.h @@ -0,0 +1,348 @@ +/************************************************************************* + Title : C include file for the HD44780U LCD library (lcd.c) + Author: Peter Fleury http://tinyurl.com/peterfleury + License: GNU General Public License Version 3 + File: $Id: lcd.h,v 1.14.2.4 2015/01/20 17:16:07 peter Exp $ + Software: AVR-GCC 4.x + Hardware: any AVR device, memory mapped mode only for AVR with + memory mapped interface (AT90S8515/ATmega8515/ATmega128) +***************************************************************************/ + +/** + @mainpage + Collection of libraries for AVR-GCC + @author Peter Fleury pfleury@gmx.ch http://tinyurl.com/peterfleury + @copyright (C) 2015 Peter Fleury, GNU General Public License Version 3 + + @file + @defgroup pfleury_lcd LCD library + @code #include @endcode + + @brief Basic routines for interfacing a HD44780U-based character LCD display + + LCD character displays can be found in many devices, like espresso machines, laser printers. + The Hitachi HD44780 controller and its compatible controllers like Samsung KS0066U have become an industry standard for these types of displays. + + This library allows easy interfacing with a HD44780 compatible display and can be + operated in memory mapped mode (LCD_IO_MODE defined as 0 in the include file lcd.h.) or in + 4-bit IO port mode (LCD_IO_MODE defined as 1). 8-bit IO port mode is not supported. + + Memory mapped mode is compatible with old Kanda STK200 starter kit, but also supports + generation of R/W signal through A8 address line. + + @see The chapter Interfacing a HD44780 Based LCD to an AVR + on my home page, which shows example circuits how to connect an LCD to an AVR controller. + + @author Peter Fleury pfleury@gmx.ch http://tinyurl.com/peterfleury + + @version 2.0 + + @copyright (C) 2015 Peter Fleury, GNU General Public License Version 3 + +*/ + +#pragma once + +#include +#include + +#if (__GNUC__ * 100 + __GNUC_MINOR__) < 405 +# error "This library requires AVR-GCC 4.5 or later, update to newer AVR-GCC compiler !" +#endif + +/**@{*/ + +/* + * LCD and target specific definitions below can be defined in a separate include file with name lcd_definitions.h instead modifying this file + * by adding -D_LCD_DEFINITIONS_FILE to the CDEFS section in the Makefile + * All definitions added to the file lcd_definitions.h will override the default definitions from lcd.h + */ +#ifdef _LCD_DEFINITIONS_FILE +# include "lcd_definitions.h" +#endif + +/** + * @name Definition for LCD controller type + * Use 0 for HD44780 controller, change to 1 for displays with KS0073 controller. + */ +#ifndef LCD_CONTROLLER_KS0073 +# define LCD_CONTROLLER_KS0073 0 /**< Use 0 for HD44780 controller, 1 for KS0073 controller */ +#endif + +/** + * @name Definitions for Display Size + * Change these definitions to adapt setting to your display + * + * These definitions can be defined in a separate include file \b lcd_definitions.h instead modifying this file by + * adding -D_LCD_DEFINITIONS_FILE to the CDEFS section in the Makefile. + * All definitions added to the file lcd_definitions.h will override the default definitions from lcd.h + * + */ +#ifndef LCD_LINES +# define LCD_LINES 2 /**< number of visible lines of the display */ +#endif +#ifndef LCD_DISP_LENGTH +# define LCD_DISP_LENGTH 16 /**< visibles characters per line of the display */ +#endif +#ifndef LCD_LINE_LENGTH +# define LCD_LINE_LENGTH 0x40 /**< internal line length of the display */ +#endif +#ifndef LCD_START_LINE1 +# define LCD_START_LINE1 0x00 /**< DDRAM address of first char of line 1 */ +#endif +#ifndef LCD_START_LINE2 +# define LCD_START_LINE2 0x40 /**< DDRAM address of first char of line 2 */ +#endif +#ifndef LCD_START_LINE3 +# define LCD_START_LINE3 0x14 /**< DDRAM address of first char of line 3 */ +#endif +#ifndef LCD_START_LINE4 +# define LCD_START_LINE4 0x54 /**< DDRAM address of first char of line 4 */ +#endif +#ifndef LCD_WRAP_LINES +# define LCD_WRAP_LINES 0 /**< 0: no wrap, 1: wrap at end of visibile line */ +#endif + +/** + * @name Definitions for 4-bit IO mode + * + * The four LCD data lines and the three control lines RS, RW, E can be on the + * same port or on different ports. + * Change LCD_RS_PORT, LCD_RW_PORT, LCD_E_PORT if you want the control lines on + * different ports. + * + * Normally the four data lines should be mapped to bit 0..3 on one port, but it + * is possible to connect these data lines in different order or even on different + * ports by adapting the LCD_DATAx_PORT and LCD_DATAx_PIN definitions. + * + * Adjust these definitions to your target.\n + * These definitions can be defined in a separate include file \b lcd_definitions.h instead modifying this file by + * adding \b -D_LCD_DEFINITIONS_FILE to the \b CDEFS section in the Makefile. + * All definitions added to the file lcd_definitions.h will override the default definitions from lcd.h + * + */ +#define LCD_IO_MODE 1 /**< 0: memory mapped mode, 1: IO port mode */ + +#if LCD_IO_MODE + +# ifndef LCD_PORT +# define LCD_PORT PORTA /**< port for the LCD lines */ +# endif +# ifndef LCD_DATA0_PORT +# define LCD_DATA0_PORT LCD_PORT /**< port for 4bit data bit 0 */ +# endif +# ifndef LCD_DATA1_PORT +# define LCD_DATA1_PORT LCD_PORT /**< port for 4bit data bit 1 */ +# endif +# ifndef LCD_DATA2_PORT +# define LCD_DATA2_PORT LCD_PORT /**< port for 4bit data bit 2 */ +# endif +# ifndef LCD_DATA3_PORT +# define LCD_DATA3_PORT LCD_PORT /**< port for 4bit data bit 3 */ +# endif +# ifndef LCD_DATA0_PIN +# define LCD_DATA0_PIN 4 /**< pin for 4bit data bit 0 */ +# endif +# ifndef LCD_DATA1_PIN +# define LCD_DATA1_PIN 5 /**< pin for 4bit data bit 1 */ +# endif +# ifndef LCD_DATA2_PIN +# define LCD_DATA2_PIN 6 /**< pin for 4bit data bit 2 */ +# endif +# ifndef LCD_DATA3_PIN +# define LCD_DATA3_PIN 7 /**< pin for 4bit data bit 3 */ +# endif +# ifndef LCD_RS_PORT +# define LCD_RS_PORT LCD_PORT /**< port for RS line */ +# endif +# ifndef LCD_RS_PIN +# define LCD_RS_PIN 3 /**< pin for RS line */ +# endif +# ifndef LCD_RW_PORT +# define LCD_RW_PORT LCD_PORT /**< port for RW line */ +# endif +# ifndef LCD_RW_PIN +# define LCD_RW_PIN 2 /**< pin for RW line */ +# endif +# ifndef LCD_E_PORT +# define LCD_E_PORT LCD_PORT /**< port for Enable line */ +# endif +# ifndef LCD_E_PIN +# define LCD_E_PIN 1 /**< pin for Enable line */ +# endif + +#elif defined(__AVR_AT90S4414__) || defined(__AVR_AT90S8515__) || defined(__AVR_ATmega64__) || defined(__AVR_ATmega8515__) || defined(__AVR_ATmega103__) || defined(__AVR_ATmega128__) || defined(__AVR_ATmega161__) || defined(__AVR_ATmega162__) +/* + * memory mapped mode is only supported when the device has an external data memory interface + */ +# define LCD_IO_DATA 0xC000 /* A15=E=1, A14=RS=1 */ +# define LCD_IO_FUNCTION 0x8000 /* A15=E=1, A14=RS=0 */ +# define LCD_IO_READ 0x0100 /* A8 =R/W=1 (R/W: 1=Read, 0=Write */ + +#else +# error "external data memory interface not available for this device, use 4-bit IO port mode" + +#endif + +/** + * @name Definitions of delays + * Used to calculate delay timers. + * Adapt the F_CPU define in the Makefile to the clock frequency in Hz of your target + * + * These delay times can be adjusted, if some displays require different delays.\n + * These definitions can be defined in a separate include file \b lcd_definitions.h instead modifying this file by + * adding \b -D_LCD_DEFINITIONS_FILE to the \b CDEFS section in the Makefile. + * All definitions added to the file lcd_definitions.h will override the default definitions from lcd.h + */ +#ifndef LCD_DELAY_BOOTUP +# define LCD_DELAY_BOOTUP 16000 /**< delay in micro seconds after power-on */ +#endif +#ifndef LCD_DELAY_INIT +# define LCD_DELAY_INIT 5000 /**< delay in micro seconds after initialization command sent */ +#endif +#ifndef LCD_DELAY_INIT_REP +# define LCD_DELAY_INIT_REP 64 /**< delay in micro seconds after initialization command repeated */ +#endif +#ifndef LCD_DELAY_INIT_4BIT +# define LCD_DELAY_INIT_4BIT 64 /**< delay in micro seconds after setting 4-bit mode */ +#endif +#ifndef LCD_DELAY_BUSY_FLAG +# define LCD_DELAY_BUSY_FLAG 4 /**< time in micro seconds the address counter is updated after busy flag is cleared */ +#endif +#ifndef LCD_DELAY_ENABLE_PULSE +# define LCD_DELAY_ENABLE_PULSE 1 /**< enable signal pulse width in micro seconds */ +#endif + +/** + * @name Definitions for LCD command instructions + * The constants define the various LCD controller instructions which can be passed to the + * function lcd_command(), see HD44780 data sheet for a complete description. + */ + +/* instruction register bit positions, see HD44780U data sheet */ +#define LCD_CLR 0 /* DB0: clear display */ +#define LCD_HOME 1 /* DB1: return to home position */ +#define LCD_ENTRY_MODE 2 /* DB2: set entry mode */ +#define LCD_ENTRY_INC 1 /* DB1: 1=increment, 0=decrement */ +#define LCD_ENTRY_SHIFT 0 /* DB2: 1=display shift on */ +#define LCD_ON 3 /* DB3: turn lcd/cursor on */ +#define LCD_ON_DISPLAY 2 /* DB2: turn display on */ +#define LCD_ON_CURSOR 1 /* DB1: turn cursor on */ +#define LCD_ON_BLINK 0 /* DB0: blinking cursor ? */ +#define LCD_MOVE 4 /* DB4: move cursor/display */ +#define LCD_MOVE_DISP 3 /* DB3: move display (0-> cursor) ? */ +#define LCD_MOVE_RIGHT 2 /* DB2: move right (0-> left) ? */ +#define LCD_FUNCTION 5 /* DB5: function set */ +#define LCD_FUNCTION_8BIT 4 /* DB4: set 8BIT mode (0->4BIT mode) */ +#define LCD_FUNCTION_2LINES 3 /* DB3: two lines (0->one line) */ +#define LCD_FUNCTION_10DOTS 2 /* DB2: 5x10 font (0->5x7 font) */ +#define LCD_CGRAM 6 /* DB6: set CG RAM address */ +#define LCD_DDRAM 7 /* DB7: set DD RAM address */ +#define LCD_BUSY 7 /* DB7: LCD is busy */ + +/* set entry mode: display shift on/off, dec/inc cursor move direction */ +#define LCD_ENTRY_DEC 0x04 /* display shift off, dec cursor move dir */ +#define LCD_ENTRY_DEC_SHIFT 0x05 /* display shift on, dec cursor move dir */ +#define LCD_ENTRY_INC_ 0x06 /* display shift off, inc cursor move dir */ +#define LCD_ENTRY_INC_SHIFT 0x07 /* display shift on, inc cursor move dir */ + +/* display on/off, cursor on/off, blinking char at cursor position */ +#define LCD_DISP_OFF 0x08 /* display off */ +#define LCD_DISP_ON 0x0C /* display on, cursor off */ +#define LCD_DISP_ON_BLINK 0x0D /* display on, cursor off, blink char */ +#define LCD_DISP_ON_CURSOR 0x0E /* display on, cursor on */ +#define LCD_DISP_ON_CURSOR_BLINK 0x0F /* display on, cursor on, blink char */ + +/* move cursor/shift display */ +#define LCD_MOVE_CURSOR_LEFT 0x10 /* move cursor left (decrement) */ +#define LCD_MOVE_CURSOR_RIGHT 0x14 /* move cursor right (increment) */ +#define LCD_MOVE_DISP_LEFT 0x18 /* shift display left */ +#define LCD_MOVE_DISP_RIGHT 0x1C /* shift display right */ + +/* function set: set interface data length and number of display lines */ +#define LCD_FUNCTION_4BIT_1LINE 0x20 /* 4-bit interface, single line, 5x7 dots */ +#define LCD_FUNCTION_4BIT_2LINES 0x28 /* 4-bit interface, dual line, 5x7 dots */ +#define LCD_FUNCTION_8BIT_1LINE 0x30 /* 8-bit interface, single line, 5x7 dots */ +#define LCD_FUNCTION_8BIT_2LINES 0x38 /* 8-bit interface, dual line, 5x7 dots */ + +#define LCD_MODE_DEFAULT ((1 << LCD_ENTRY_MODE) | (1 << LCD_ENTRY_INC)) + +/** + * @name Functions + */ + +/** + @brief Initialize display and select type of cursor + @param dispAttr \b LCD_DISP_OFF display off\n + \b LCD_DISP_ON display on, cursor off\n + \b LCD_DISP_ON_CURSOR display on, cursor on\n + \b LCD_DISP_ON_CURSOR_BLINK display on, cursor on flashing + @return none +*/ +extern void lcd_init(uint8_t dispAttr); + +/** + @brief Clear display and set cursor to home position + @return none +*/ +extern void lcd_clrscr(void); + +/** + @brief Set cursor to home position + @return none +*/ +extern void lcd_home(void); + +/** + @brief Set cursor to specified position + + @param x horizontal position\n (0: left most position) + @param y vertical position\n (0: first line) + @return none +*/ +extern void lcd_gotoxy(uint8_t x, uint8_t y); + +/** + @brief Display character at current cursor position + @param c character to be displayed + @return none +*/ +extern void lcd_putc(char c); + +/** + @brief Display string without auto linefeed + @param s string to be displayed + @return none +*/ +extern void lcd_puts(const char *s); + +/** + @brief Display string from program memory without auto linefeed + @param progmem_s string from program memory be be displayed + @return none + @see lcd_puts_P +*/ +extern void lcd_puts_p(const char *progmem_s); + +/** + @brief Send LCD controller instruction command + @param cmd instruction to send to LCD controller, see HD44780 data sheet + @return none +*/ +extern void lcd_command(uint8_t cmd); + +/** + @brief Send data byte to LCD controller + + Similar to lcd_putc(), but without interpreting LF + @param data byte to send to LCD controller, see HD44780 data sheet + @return none +*/ +extern void lcd_data(uint8_t data); + +/** + @brief macros for automatically storing string constant in program memory +*/ +#define lcd_puts_P(__s) lcd_puts_p(PSTR(__s)) + +/**@}*/ diff --git a/platforms/avr/drivers/i2c_master.c b/platforms/avr/drivers/i2c_master.c new file mode 100644 index 0000000000..2773e00778 --- /dev/null +++ b/platforms/avr/drivers/i2c_master.c @@ -0,0 +1,241 @@ +/* Copyright (C) 2019 Elia Ritterbusch + + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/* Library made by: g4lvanix + * GitHub repository: https://github.com/g4lvanix/I2C-master-lib + */ + +#include +#include + +#include "i2c_master.h" +#include "timer.h" +#include "wait.h" + +#ifndef F_SCL +# define F_SCL 400000UL // SCL frequency +#endif + +#ifndef I2C_START_RETRY_COUNT +# define I2C_START_RETRY_COUNT 20 +#endif // I2C_START_RETRY_COUNT + +#define TWBR_val (((F_CPU / F_SCL) - 16) / 2) + +#define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) + +void i2c_init(void) { + TWSR = 0; /* no prescaler */ + TWBR = (uint8_t)TWBR_val; + +#ifdef __AVR_ATmega32A__ + // set pull-up resistors on I2C bus pins + PORTC |= 0b11; + + // enable TWI (two-wire interface) + TWCR |= (1 << TWEN); + + // enable TWI interrupt and slave address ACK + TWCR |= (1 << TWIE); + TWCR |= (1 << TWEA); +#endif +} + +static i2c_status_t i2c_start_impl(uint8_t address, uint16_t timeout) { + // reset TWI control register + TWCR = 0; + // transmit START condition + TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); + + uint16_t timeout_timer = timer_read(); + while (!(TWCR & (1 << TWINT))) { + if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { + return I2C_STATUS_TIMEOUT; + } + } + + // check if the start condition was successfully transmitted + if (((TW_STATUS & 0xF8) != TW_START) && ((TW_STATUS & 0xF8) != TW_REP_START)) { + return I2C_STATUS_ERROR; + } + + // load slave address into data register + TWDR = address; + // start transmission of address + TWCR = (1 << TWINT) | (1 << TWEN); + + timeout_timer = timer_read(); + while (!(TWCR & (1 << TWINT))) { + if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { + return I2C_STATUS_TIMEOUT; + } + } + + // check if the device has acknowledged the READ / WRITE mode + uint8_t twst = TW_STATUS & 0xF8; + if ((twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK)) { + return I2C_STATUS_ERROR; + } + + return I2C_STATUS_SUCCESS; +} + +i2c_status_t i2c_start(uint8_t address, uint16_t timeout) { + // Retry i2c_start_impl a bunch times in case the remote side has interrupts disabled. + uint16_t timeout_timer = timer_read(); + uint16_t time_slice = MAX(1, (timeout == (I2C_TIMEOUT_INFINITE)) ? 5 : (timeout / (I2C_START_RETRY_COUNT))); // if it's infinite, wait 1ms between attempts, otherwise split up the entire timeout into the number of retries + i2c_status_t status; + do { + status = i2c_start_impl(address, time_slice); + } while ((status < 0) && ((timeout == I2C_TIMEOUT_INFINITE) || (timer_elapsed(timeout_timer) < timeout))); + return status; +} + +i2c_status_t i2c_write(uint8_t data, uint16_t timeout) { + // load data into data register + TWDR = data; + // start transmission of data + TWCR = (1 << TWINT) | (1 << TWEN); + + uint16_t timeout_timer = timer_read(); + while (!(TWCR & (1 << TWINT))) { + if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { + return I2C_STATUS_TIMEOUT; + } + } + + if ((TW_STATUS & 0xF8) != TW_MT_DATA_ACK) { + return I2C_STATUS_ERROR; + } + + return I2C_STATUS_SUCCESS; +} + +int16_t i2c_read_ack(uint16_t timeout) { + // start TWI module and acknowledge data after reception + TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA); + + uint16_t timeout_timer = timer_read(); + while (!(TWCR & (1 << TWINT))) { + if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { + return I2C_STATUS_TIMEOUT; + } + } + + // return received data from TWDR + return TWDR; +} + +int16_t i2c_read_nack(uint16_t timeout) { + // start receiving without acknowledging reception + TWCR = (1 << TWINT) | (1 << TWEN); + + uint16_t timeout_timer = timer_read(); + while (!(TWCR & (1 << TWINT))) { + if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { + return I2C_STATUS_TIMEOUT; + } + } + + // return received data from TWDR + return TWDR; +} + +i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout) { + i2c_status_t status = i2c_start(address | I2C_WRITE, timeout); + + for (uint16_t i = 0; i < length && status >= 0; i++) { + status = i2c_write(data[i], timeout); + } + + i2c_stop(); + + return status; +} + +i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) { + i2c_status_t status = i2c_start(address | I2C_READ, timeout); + + for (uint16_t i = 0; i < (length - 1) && status >= 0; i++) { + status = i2c_read_ack(timeout); + if (status >= 0) { + data[i] = status; + } + } + + if (status >= 0) { + status = i2c_read_nack(timeout); + if (status >= 0) { + data[(length - 1)] = status; + } + } + + i2c_stop(); + + return (status < 0) ? status : I2C_STATUS_SUCCESS; +} + +i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) { + i2c_status_t status = i2c_start(devaddr | 0x00, timeout); + if (status >= 0) { + status = i2c_write(regaddr, timeout); + + for (uint16_t i = 0; i < length && status >= 0; i++) { + status = i2c_write(data[i], timeout); + } + } + + i2c_stop(); + + return status; +} + +i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) { + i2c_status_t status = i2c_start(devaddr, timeout); + if (status < 0) { + goto error; + } + + status = i2c_write(regaddr, timeout); + if (status < 0) { + goto error; + } + + status = i2c_start(devaddr | 0x01, timeout); + + for (uint16_t i = 0; i < (length - 1) && status >= 0; i++) { + status = i2c_read_ack(timeout); + if (status >= 0) { + data[i] = status; + } + } + + if (status >= 0) { + status = i2c_read_nack(timeout); + if (status >= 0) { + data[(length - 1)] = status; + } + } + +error: + i2c_stop(); + + return (status < 0) ? status : I2C_STATUS_SUCCESS; +} + +void i2c_stop(void) { + // transmit STOP condition + TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO); +} diff --git a/platforms/avr/drivers/i2c_master.h b/platforms/avr/drivers/i2c_master.h new file mode 100644 index 0000000000..e5af73364b --- /dev/null +++ b/platforms/avr/drivers/i2c_master.h @@ -0,0 +1,43 @@ +/* Copyright (C) 2019 Elia Ritterbusch + + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/* Library made by: g4lvanix + * GitHub repository: https://github.com/g4lvanix/I2C-master-lib + */ + +#pragma once + +#define I2C_READ 0x01 +#define I2C_WRITE 0x00 + +typedef int16_t i2c_status_t; + +#define I2C_STATUS_SUCCESS (0) +#define I2C_STATUS_ERROR (-1) +#define I2C_STATUS_TIMEOUT (-2) + +#define I2C_TIMEOUT_IMMEDIATE (0) +#define I2C_TIMEOUT_INFINITE (0xFFFF) + +void i2c_init(void); +i2c_status_t i2c_start(uint8_t address, uint16_t timeout); +i2c_status_t i2c_write(uint8_t data, uint16_t timeout); +int16_t i2c_read_ack(uint16_t timeout); +int16_t i2c_read_nack(uint16_t timeout); +i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout); +i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout); +i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout); +i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); +void i2c_stop(void); diff --git a/platforms/avr/drivers/i2c_slave.c b/platforms/avr/drivers/i2c_slave.c new file mode 100644 index 0000000000..2907f164c0 --- /dev/null +++ b/platforms/avr/drivers/i2c_slave.c @@ -0,0 +1,111 @@ +/* Copyright (C) 2019 Elia Ritterbusch + + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/* Library made by: g4lvanix + * GitHub repository: https://github.com/g4lvanix/I2C-slave-lib + */ + +#include +#include +#include +#include +#include + +#include "i2c_slave.h" + +#if defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS) +# include "transactions.h" + +static volatile bool is_callback_executor = false; +#endif // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS) + +volatile uint8_t i2c_slave_reg[I2C_SLAVE_REG_COUNT]; + +static volatile uint8_t buffer_address; +static volatile bool slave_has_register_set = false; + +void i2c_slave_init(uint8_t address) { + // load address into TWI address register + TWAR = address; + // set the TWCR to enable address matching and enable TWI, clear TWINT, enable TWI interrupt + TWCR = (1 << TWIE) | (1 << TWEA) | (1 << TWINT) | (1 << TWEN); +} + +void i2c_slave_stop(void) { + // clear acknowledge and enable bits + TWCR &= ~((1 << TWEA) | (1 << TWEN)); +} + +ISR(TWI_vect) { + uint8_t ack = 1; + + switch (TW_STATUS) { + case TW_SR_SLA_ACK: + // The device is now a slave receiver + slave_has_register_set = false; +#if defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS) + is_callback_executor = false; +#endif // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS) + break; + + case TW_SR_DATA_ACK: + // This device is a slave receiver and has received data + // First byte is the location then the bytes will be writen in buffer with auto-increment + if (!slave_has_register_set) { + buffer_address = TWDR; + + if (buffer_address >= I2C_SLAVE_REG_COUNT) { // address out of bounds dont ack + ack = 0; + buffer_address = 0; + } + slave_has_register_set = true; // address has been received now fill in buffer + +#if defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS) + // Work out if we're attempting to execute a callback + is_callback_executor = buffer_address == split_transaction_table[I2C_EXECUTE_CALLBACK].initiator2target_offset; +#endif // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS) + } else { + i2c_slave_reg[buffer_address] = TWDR; + buffer_address++; + +#if defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS) + // If we're intending to execute a transaction callback, do so, as we've just received the transaction ID + if (is_callback_executor) { + split_transaction_desc_t *trans = &split_transaction_table[split_shmem->transaction_id]; + if (trans->slave_callback) { + trans->slave_callback(trans->initiator2target_buffer_size, split_trans_initiator2target_buffer(trans), trans->target2initiator_buffer_size, split_trans_target2initiator_buffer(trans)); + } + } +#endif // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS) + } + break; + + case TW_ST_SLA_ACK: + case TW_ST_DATA_ACK: + // This device is a slave transmitter and master has requested data + TWDR = i2c_slave_reg[buffer_address]; + buffer_address++; + break; + + case TW_BUS_ERROR: + // We got an error, reset i2c + TWCR = 0; + default: + break; + } + + // Reset i2c state machine to be ready for next interrupt + TWCR |= (1 << TWIE) | (1 << TWINT) | (ack << TWEA) | (1 << TWEN); +} diff --git a/platforms/avr/drivers/i2c_slave.h b/platforms/avr/drivers/i2c_slave.h new file mode 100644 index 0000000000..a8647c9da3 --- /dev/null +++ b/platforms/avr/drivers/i2c_slave.h @@ -0,0 +1,41 @@ +/* Copyright (C) 2019 Elia Ritterbusch + + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/* Library made by: g4lvanix + * GitHub repository: https://github.com/g4lvanix/I2C-slave-lib + + Info: Inititate the library by giving the required address. + Read or write to the necessary buffer according to the opperation. + */ + +#pragma once + +#ifndef I2C_SLAVE_REG_COUNT + +# if defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS) +# include "transport.h" +# define I2C_SLAVE_REG_COUNT sizeof(split_shared_memory_t) +# else // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS) +# define I2C_SLAVE_REG_COUNT 30 +# endif // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS) + +#endif // I2C_SLAVE_REG_COUNT + +_Static_assert(I2C_SLAVE_REG_COUNT < 256, "I2C target registers must be single byte"); + +extern volatile uint8_t i2c_slave_reg[I2C_SLAVE_REG_COUNT]; + +void i2c_slave_init(uint8_t address); +void i2c_slave_stop(void); diff --git a/platforms/avr/drivers/serial.c b/platforms/avr/drivers/serial.c new file mode 100644 index 0000000000..9a7345a53d --- /dev/null +++ b/platforms/avr/drivers/serial.c @@ -0,0 +1,529 @@ +/* + * WARNING: be careful changing this code, it is very timing dependent + * + * 2018-10-28 checked + * avr-gcc 4.9.2 + * avr-gcc 5.4.0 + * avr-gcc 7.3.0 + */ + +#ifndef F_CPU +# define F_CPU 16000000 +#endif + +#include +#include +#include +#include +#include +#include "serial.h" + +#ifdef SOFT_SERIAL_PIN + +# if !(defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__)) +# error serial.c is not supported for the currently selected MCU +# endif +// if using ATmega32U4/2, AT90USBxxx I2C, can not use PD0 and PD1 in soft serial. +# if defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) +# if defined(USE_AVR_I2C) && (SOFT_SERIAL_PIN == D0 || SOFT_SERIAL_PIN == D1) +# error Using I2C, so can not use PD0, PD1 +# endif +# endif +// PD0..PD3, common config +# if SOFT_SERIAL_PIN == D0 +# define EIMSK_BIT _BV(INT0) +# define EICRx_BIT (~(_BV(ISC00) | _BV(ISC01))) +# define SERIAL_PIN_INTERRUPT INT0_vect +# define EICRx EICRA +# elif SOFT_SERIAL_PIN == D1 +# define EIMSK_BIT _BV(INT1) +# define EICRx_BIT (~(_BV(ISC10) | _BV(ISC11))) +# define SERIAL_PIN_INTERRUPT INT1_vect +# define EICRx EICRA +# elif SOFT_SERIAL_PIN == D2 +# define EIMSK_BIT _BV(INT2) +# define EICRx_BIT (~(_BV(ISC20) | _BV(ISC21))) +# define SERIAL_PIN_INTERRUPT INT2_vect +# define EICRx EICRA +# elif SOFT_SERIAL_PIN == D3 +# define EIMSK_BIT _BV(INT3) +# define EICRx_BIT (~(_BV(ISC30) | _BV(ISC31))) +# define SERIAL_PIN_INTERRUPT INT3_vect +# define EICRx EICRA +# endif + +// ATmegaxxU2/AT90USB162 specific config +# if defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || defined(__AVR_AT90USB162__) +// PD4(INT5), PD6(INT6), PD7(INT7), PC7(INT4) +# if SOFT_SERIAL_PIN == D4 +# define EIMSK_BIT _BV(INT5) +# define EICRx_BIT (~(_BV(ISC50) | _BV(ISC51))) +# define SERIAL_PIN_INTERRUPT INT5_vect +# define EICRx EICRB +# elif SOFT_SERIAL_PIN == D6 +# define EIMSK_BIT _BV(INT6) +# define EICRx_BIT (~(_BV(ISC60) | _BV(ISC61))) +# define SERIAL_PIN_INTERRUPT INT6_vect +# define EICRx EICRB +# elif SOFT_SERIAL_PIN == D7 +# define EIMSK_BIT _BV(INT7) +# define EICRx_BIT (~(_BV(ISC70) | _BV(ISC71))) +# define SERIAL_PIN_INTERRUPT INT7_vect +# define EICRx EICRB +# elif SOFT_SERIAL_PIN == C7 +# define EIMSK_BIT _BV(INT4) +# define EICRx_BIT (~(_BV(ISC40) | _BV(ISC41))) +# define SERIAL_PIN_INTERRUPT INT4_vect +# define EICRx EICRB +# endif +# endif + +// ATmegaxxU4 specific config +# if defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) +// PE6(INT6) +# if SOFT_SERIAL_PIN == E6 +# define EIMSK_BIT _BV(INT6) +# define EICRx_BIT (~(_BV(ISC60) | _BV(ISC61))) +# define SERIAL_PIN_INTERRUPT INT6_vect +# define EICRx EICRB +# endif +# endif + +// AT90USBxxx specific config +# if defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) +// PE4..PE7(INT4..INT7) +# if SOFT_SERIAL_PIN == E4 +# define EIMSK_BIT _BV(INT4) +# define EICRx_BIT (~(_BV(ISC40) | _BV(ISC41))) +# define SERIAL_PIN_INTERRUPT INT4_vect +# define EICRx EICRB +# elif SOFT_SERIAL_PIN == E5 +# define EIMSK_BIT _BV(INT5) +# define EICRx_BIT (~(_BV(ISC50) | _BV(ISC51))) +# define SERIAL_PIN_INTERRUPT INT5_vect +# define EICRx EICRB +# elif SOFT_SERIAL_PIN == E6 +# define EIMSK_BIT _BV(INT6) +# define EICRx_BIT (~(_BV(ISC60) | _BV(ISC61))) +# define SERIAL_PIN_INTERRUPT INT6_vect +# define EICRx EICRB +# elif SOFT_SERIAL_PIN == E7 +# define EIMSK_BIT _BV(INT7) +# define EICRx_BIT (~(_BV(ISC70) | _BV(ISC71))) +# define SERIAL_PIN_INTERRUPT INT7_vect +# define EICRx EICRB +# endif +# endif + +# ifndef SERIAL_PIN_INTERRUPT +# error invalid SOFT_SERIAL_PIN value +# endif + +# define setPinInputHigh(pin) (DDRx_ADDRESS(pin) &= ~_BV((pin)&0xF), PORTx_ADDRESS(pin) |= _BV((pin)&0xF)) +# define setPinOutput(pin) (DDRx_ADDRESS(pin) |= _BV((pin)&0xF)) +# define writePinHigh(pin) (PORTx_ADDRESS(pin) |= _BV((pin)&0xF)) +# define writePinLow(pin) (PORTx_ADDRESS(pin) &= ~_BV((pin)&0xF)) +# define readPin(pin) ((bool)(PINx_ADDRESS(pin) & _BV((pin)&0xF))) + +# define ALWAYS_INLINE __attribute__((always_inline)) +# define NO_INLINE __attribute__((noinline)) +# define _delay_sub_us(x) __builtin_avr_delay_cycles(x) + +// parity check +# define ODD_PARITY 1 +# define EVEN_PARITY 0 +# define PARITY EVEN_PARITY + +# ifdef SERIAL_DELAY +// custom setup in config.h +// #define TID_SEND_ADJUST 2 +// #define SERIAL_DELAY 6 // micro sec +// #define READ_WRITE_START_ADJUST 30 // cycles +// #define READ_WRITE_WIDTH_ADJUST 8 // cycles +# else +// ============ Standard setups ============ + +# ifndef SELECT_SOFT_SERIAL_SPEED +# define SELECT_SOFT_SERIAL_SPEED 1 +// 0: about 189kbps (Experimental only) +// 1: about 137kbps (default) +// 2: about 75kbps +// 3: about 39kbps +// 4: about 26kbps +// 5: about 20kbps +# endif + +# if __GNUC__ < 6 +# define TID_SEND_ADJUST 14 +# else +# define TID_SEND_ADJUST 2 +# endif + +# if SELECT_SOFT_SERIAL_SPEED == 0 +// Very High speed +# define SERIAL_DELAY 4 // micro sec +# if __GNUC__ < 6 +# define READ_WRITE_START_ADJUST 33 // cycles +# define READ_WRITE_WIDTH_ADJUST 3 // cycles +# else +# define READ_WRITE_START_ADJUST 34 // cycles +# define READ_WRITE_WIDTH_ADJUST 7 // cycles +# endif +# elif SELECT_SOFT_SERIAL_SPEED == 1 +// High speed +# define SERIAL_DELAY 6 // micro sec +# if __GNUC__ < 6 +# define READ_WRITE_START_ADJUST 30 // cycles +# define READ_WRITE_WIDTH_ADJUST 3 // cycles +# else +# define READ_WRITE_START_ADJUST 33 // cycles +# define READ_WRITE_WIDTH_ADJUST 7 // cycles +# endif +# elif SELECT_SOFT_SERIAL_SPEED == 2 +// Middle speed +# define SERIAL_DELAY 12 // micro sec +# define READ_WRITE_START_ADJUST 30 // cycles +# if __GNUC__ < 6 +# define READ_WRITE_WIDTH_ADJUST 3 // cycles +# else +# define READ_WRITE_WIDTH_ADJUST 7 // cycles +# endif +# elif SELECT_SOFT_SERIAL_SPEED == 3 +// Low speed +# define SERIAL_DELAY 24 // micro sec +# define READ_WRITE_START_ADJUST 30 // cycles +# if __GNUC__ < 6 +# define READ_WRITE_WIDTH_ADJUST 3 // cycles +# else +# define READ_WRITE_WIDTH_ADJUST 7 // cycles +# endif +# elif SELECT_SOFT_SERIAL_SPEED == 4 +// Very Low speed +# define SERIAL_DELAY 36 // micro sec +# define READ_WRITE_START_ADJUST 30 // cycles +# if __GNUC__ < 6 +# define READ_WRITE_WIDTH_ADJUST 3 // cycles +# else +# define READ_WRITE_WIDTH_ADJUST 7 // cycles +# endif +# elif SELECT_SOFT_SERIAL_SPEED == 5 +// Ultra Low speed +# define SERIAL_DELAY 48 // micro sec +# define READ_WRITE_START_ADJUST 30 // cycles +# if __GNUC__ < 6 +# define READ_WRITE_WIDTH_ADJUST 3 // cycles +# else +# define READ_WRITE_WIDTH_ADJUST 7 // cycles +# endif +# else +# error invalid SELECT_SOFT_SERIAL_SPEED value +# endif /* SELECT_SOFT_SERIAL_SPEED */ +# endif /* SERIAL_DELAY */ + +# define SERIAL_DELAY_HALF1 (SERIAL_DELAY / 2) +# define SERIAL_DELAY_HALF2 (SERIAL_DELAY - SERIAL_DELAY / 2) + +# define SLAVE_INT_WIDTH_US 1 +# define SLAVE_INT_ACK_WIDTH_UNIT 2 +# define SLAVE_INT_ACK_WIDTH 4 + +inline static void serial_delay(void) ALWAYS_INLINE; +inline static void serial_delay(void) { _delay_us(SERIAL_DELAY); } + +inline static void serial_delay_half1(void) ALWAYS_INLINE; +inline static void serial_delay_half1(void) { _delay_us(SERIAL_DELAY_HALF1); } + +inline static void serial_delay_half2(void) ALWAYS_INLINE; +inline static void serial_delay_half2(void) { _delay_us(SERIAL_DELAY_HALF2); } + +inline static void serial_output(void) ALWAYS_INLINE; +inline static void serial_output(void) { setPinOutput(SOFT_SERIAL_PIN); } + +// make the serial pin an input with pull-up resistor +inline static void serial_input_with_pullup(void) ALWAYS_INLINE; +inline static void serial_input_with_pullup(void) { setPinInputHigh(SOFT_SERIAL_PIN); } + +inline static uint8_t serial_read_pin(void) ALWAYS_INLINE; +inline static uint8_t serial_read_pin(void) { return !!readPin(SOFT_SERIAL_PIN); } + +inline static void serial_low(void) ALWAYS_INLINE; +inline static void serial_low(void) { writePinLow(SOFT_SERIAL_PIN); } + +inline static void serial_high(void) ALWAYS_INLINE; +inline static void serial_high(void) { writePinHigh(SOFT_SERIAL_PIN); } + +void soft_serial_initiator_init(void) { + serial_output(); + serial_high(); +} + +void soft_serial_target_init(void) { + serial_input_with_pullup(); + + // Enable INT0-INT7 + EIMSK |= EIMSK_BIT; + EICRx &= EICRx_BIT; +} + +// Used by the sender to synchronize timing with the reciver. +static void sync_recv(void) NO_INLINE; +static void sync_recv(void) { + for (uint8_t i = 0; i < SERIAL_DELAY * 5 && serial_read_pin(); i++) { + } + // This shouldn't hang if the target disconnects because the + // serial line will float to high if the target does disconnect. + while (!serial_read_pin()) + ; +} + +// Used by the reciver to send a synchronization signal to the sender. +static void sync_send(void) NO_INLINE; +static void sync_send(void) { + serial_low(); + serial_delay(); + serial_high(); +} + +// Reads a byte from the serial line +static uint8_t serial_read_chunk(uint8_t *pterrcount, uint8_t bit) NO_INLINE; +static uint8_t serial_read_chunk(uint8_t *pterrcount, uint8_t bit) { + uint8_t byte, i, p, pb; + + _delay_sub_us(READ_WRITE_START_ADJUST); + for (i = 0, byte = 0, p = PARITY; i < bit; i++) { + serial_delay_half1(); // read the middle of pulses + if (serial_read_pin()) { + byte = (byte << 1) | 1; + p ^= 1; + } else { + byte = (byte << 1) | 0; + p ^= 0; + } + _delay_sub_us(READ_WRITE_WIDTH_ADJUST); + serial_delay_half2(); + } + /* recive parity bit */ + serial_delay_half1(); // read the middle of pulses + pb = serial_read_pin(); + _delay_sub_us(READ_WRITE_WIDTH_ADJUST); + serial_delay_half2(); + + *pterrcount += (p != pb) ? 1 : 0; + + return byte; +} + +// Sends a byte with MSB ordering +void serial_write_chunk(uint8_t data, uint8_t bit) NO_INLINE; +void serial_write_chunk(uint8_t data, uint8_t bit) { + uint8_t b, p; + for (p = PARITY, b = 1 << (bit - 1); b; b >>= 1) { + if (data & b) { + serial_high(); + p ^= 1; + } else { + serial_low(); + p ^= 0; + } + serial_delay(); + } + /* send parity bit */ + if (p & 1) { + serial_high(); + } else { + serial_low(); + } + serial_delay(); + + serial_low(); // sync_send() / senc_recv() need raise edge +} + +static void serial_send_packet(uint8_t *buffer, uint8_t size) NO_INLINE; +static void serial_send_packet(uint8_t *buffer, uint8_t size) { + for (uint8_t i = 0; i < size; ++i) { + uint8_t data; + data = buffer[i]; + sync_send(); + serial_write_chunk(data, 8); + } +} + +static uint8_t serial_recive_packet(uint8_t *buffer, uint8_t size) NO_INLINE; +static uint8_t serial_recive_packet(uint8_t *buffer, uint8_t size) { + uint8_t pecount = 0; + for (uint8_t i = 0; i < size; ++i) { + uint8_t data; + sync_recv(); + data = serial_read_chunk(&pecount, 8); + buffer[i] = data; + } + return pecount == 0; +} + +inline static void change_sender2reciver(void) { + sync_send(); // 0 + serial_delay_half1(); // 1 + serial_low(); // 2 + serial_input_with_pullup(); // 2 + serial_delay_half1(); // 3 +} + +inline static void change_reciver2sender(void) { + sync_recv(); // 0 + serial_delay(); // 1 + serial_low(); // 3 + serial_output(); // 3 + serial_delay_half1(); // 4 +} + +static inline uint8_t nibble_bits_count(uint8_t bits) { + bits = (bits & 0x5) + (bits >> 1 & 0x5); + bits = (bits & 0x3) + (bits >> 2 & 0x3); + return bits; +} + +// interrupt handle to be used by the target device +ISR(SERIAL_PIN_INTERRUPT) { + // recive transaction table index + uint8_t tid, bits; + uint8_t pecount = 0; + sync_recv(); + bits = serial_read_chunk(&pecount, 8); + tid = bits >> 3; + bits = (bits & 7) != (nibble_bits_count(tid) & 7); + if (bits || pecount > 0 || tid > NUM_TOTAL_TRANSACTIONS) { + return; + } + serial_delay_half1(); + + serial_high(); // response step1 low->high + serial_output(); + _delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT * SLAVE_INT_ACK_WIDTH); + split_transaction_desc_t *trans = &split_transaction_table[tid]; + serial_low(); // response step2 ack high->low + + // If the transaction has a callback, we can execute it now + if (trans->slave_callback) { + trans->slave_callback(trans->initiator2target_buffer_size, split_trans_initiator2target_buffer(trans), trans->target2initiator_buffer_size, split_trans_target2initiator_buffer(trans)); + } + + // target send phase + if (trans->target2initiator_buffer_size > 0) serial_send_packet((uint8_t *)split_trans_target2initiator_buffer(trans), trans->target2initiator_buffer_size); + // target switch to input + change_sender2reciver(); + + // target recive phase + if (trans->initiator2target_buffer_size > 0) { + if (serial_recive_packet((uint8_t *)split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size)) { + *trans->status = TRANSACTION_ACCEPTED; + } else { + *trans->status = TRANSACTION_DATA_ERROR; + } + } else { + *trans->status = TRANSACTION_ACCEPTED; + } + + sync_recv(); // weit initiator output to high +} + +///////// +// start transaction by initiator +// +// int soft_serial_transaction(int sstd_index) +// +// Returns: +// TRANSACTION_END +// TRANSACTION_NO_RESPONSE +// TRANSACTION_DATA_ERROR +// this code is very time dependent, so we need to disable interrupts +int soft_serial_transaction(int sstd_index) { + if (sstd_index > NUM_TOTAL_TRANSACTIONS) return TRANSACTION_TYPE_ERROR; + split_transaction_desc_t *trans = &split_transaction_table[sstd_index]; + + if (!trans->status) return TRANSACTION_TYPE_ERROR; // not registered + + cli(); + + // signal to the target that we want to start a transaction + serial_output(); + serial_low(); + _delay_us(SLAVE_INT_WIDTH_US); + + // send transaction table index + int tid = (sstd_index << 3) | (7 & nibble_bits_count(sstd_index)); + sync_send(); + _delay_sub_us(TID_SEND_ADJUST); + serial_write_chunk(tid, 8); + serial_delay_half1(); + + // wait for the target response (step1 low->high) + serial_input_with_pullup(); + while (!serial_read_pin()) { + _delay_sub_us(2); + } + + // check if the target is present (step2 high->low) + for (int i = 0; serial_read_pin(); i++) { + if (i > SLAVE_INT_ACK_WIDTH + 1) { + // slave failed to pull the line low, assume not present + serial_output(); + serial_high(); + *trans->status = TRANSACTION_NO_RESPONSE; + sei(); + return TRANSACTION_NO_RESPONSE; + } + _delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT); + } + + // initiator recive phase + // if the target is present syncronize with it + if (trans->target2initiator_buffer_size > 0) { + if (!serial_recive_packet((uint8_t *)split_trans_target2initiator_buffer(trans), trans->target2initiator_buffer_size)) { + serial_output(); + serial_high(); + *trans->status = TRANSACTION_DATA_ERROR; + sei(); + return TRANSACTION_DATA_ERROR; + } + } + + // initiator switch to output + change_reciver2sender(); + + // initiator send phase + if (trans->initiator2target_buffer_size > 0) { + serial_send_packet((uint8_t *)split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size); + } + + // always, release the line when not in use + sync_send(); + + *trans->status = TRANSACTION_END; + sei(); + return TRANSACTION_END; +} + +int soft_serial_get_and_clean_status(int sstd_index) { + split_transaction_desc_t *trans = &split_transaction_table[sstd_index]; + cli(); + int retval = *trans->status; + *trans->status = 0; + ; + sei(); + return retval; +} +#endif + +// Helix serial.c history +// 2018-1-29 fork from let's split and add PD2, modify sync_recv() (#2308, bceffdefc) +// 2018-6-28 bug fix master to slave comm and speed up (#3255, 1038bbef4) +// (adjusted with avr-gcc 4.9.2) +// 2018-7-13 remove USE_SERIAL_PD2 macro (#3374, f30d6dd78) +// (adjusted with avr-gcc 4.9.2) +// 2018-8-11 add support multi-type transaction (#3608, feb5e4aae) +// (adjusted with avr-gcc 4.9.2) +// 2018-10-21 fix serial and RGB animation conflict (#4191, 4665e4fff) +// (adjusted with avr-gcc 7.3.0) +// 2018-10-28 re-adjust compiler depend value of delay (#4269, 8517f8a66) +// (adjusted with avr-gcc 5.4.0, 7.3.0) +// 2018-12-17 copy to TOP/quantum/split_common/ and remove backward compatibility code (#4669) diff --git a/platforms/avr/drivers/spi_master.c b/platforms/avr/drivers/spi_master.c new file mode 100644 index 0000000000..4e8fd3bcdf --- /dev/null +++ b/platforms/avr/drivers/spi_master.c @@ -0,0 +1,180 @@ +/* Copyright 2020 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "spi_master.h" + +#include "timer.h" + +#if defined(__AVR_AT90USB162__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) +# define SPI_SCK_PIN B1 +# define SPI_MOSI_PIN B2 +# define SPI_MISO_PIN B3 +#elif defined(__AVR_ATmega32A__) +# define SPI_SCK_PIN B7 +# define SPI_MOSI_PIN B5 +# define SPI_MISO_PIN B6 +#elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) +# define SPI_SCK_PIN B5 +# define SPI_MOSI_PIN B3 +# define SPI_MISO_PIN B4 +#endif + +#ifndef SPI_TIMEOUT +# define SPI_TIMEOUT 100 +#endif + +static pin_t currentSlavePin = NO_PIN; +static uint8_t currentSlaveConfig = 0; +static bool currentSlave2X = false; + +void spi_init(void) { + writePinHigh(SPI_SS_PIN); + setPinOutput(SPI_SCK_PIN); + setPinOutput(SPI_MOSI_PIN); + setPinInput(SPI_MISO_PIN); + + SPCR = (_BV(SPE) | _BV(MSTR)); +} + +bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { + if (currentSlavePin != NO_PIN || slavePin == NO_PIN) { + return false; + } + + currentSlaveConfig = 0; + + if (lsbFirst) { + currentSlaveConfig |= _BV(DORD); + } + + switch (mode) { + case 1: + currentSlaveConfig |= _BV(CPHA); + break; + case 2: + currentSlaveConfig |= _BV(CPOL); + break; + case 3: + currentSlaveConfig |= (_BV(CPOL) | _BV(CPHA)); + break; + } + + uint16_t roundedDivisor = 1; + while (roundedDivisor < divisor) { + roundedDivisor <<= 1; + } + + switch (roundedDivisor) { + case 16: + currentSlaveConfig |= _BV(SPR0); + break; + case 64: + currentSlaveConfig |= _BV(SPR1); + break; + case 128: + currentSlaveConfig |= (_BV(SPR1) | _BV(SPR0)); + break; + case 2: + currentSlave2X = true; + break; + case 8: + currentSlave2X = true; + currentSlaveConfig |= _BV(SPR0); + break; + case 32: + currentSlave2X = true; + currentSlaveConfig |= _BV(SPR1); + break; + } + + SPCR |= currentSlaveConfig; + if (currentSlave2X) { + SPSR |= _BV(SPI2X); + } + currentSlavePin = slavePin; + setPinOutput(currentSlavePin); + writePinLow(currentSlavePin); + + return true; +} + +spi_status_t spi_write(uint8_t data) { + SPDR = data; + + uint16_t timeout_timer = timer_read(); + while (!(SPSR & _BV(SPIF))) { + if ((timer_read() - timeout_timer) >= SPI_TIMEOUT) { + return SPI_STATUS_TIMEOUT; + } + } + + return SPDR; +} + +spi_status_t spi_read() { + SPDR = 0x00; // Dummy + + uint16_t timeout_timer = timer_read(); + while (!(SPSR & _BV(SPIF))) { + if ((timer_read() - timeout_timer) >= SPI_TIMEOUT) { + return SPI_STATUS_TIMEOUT; + } + } + + return SPDR; +} + +spi_status_t spi_transmit(const uint8_t *data, uint16_t length) { + spi_status_t status; + + for (uint16_t i = 0; i < length; i++) { + status = spi_write(data[i]); + + if (status < 0) { + return status; + } + } + + return SPI_STATUS_SUCCESS; +} + +spi_status_t spi_receive(uint8_t *data, uint16_t length) { + spi_status_t status; + + for (uint16_t i = 0; i < length; i++) { + status = spi_read(); + + if (status >= 0) { + data[i] = status; + } else { + return status; + } + } + + return SPI_STATUS_SUCCESS; +} + +void spi_stop(void) { + if (currentSlavePin != NO_PIN) { + setPinOutput(currentSlavePin); + writePinHigh(currentSlavePin); + currentSlavePin = NO_PIN; + SPSR &= ~(_BV(SPI2X)); + SPCR &= ~(currentSlaveConfig); + currentSlaveConfig = 0; + currentSlave2X = false; + } +} diff --git a/platforms/avr/drivers/spi_master.h b/platforms/avr/drivers/spi_master.h new file mode 100644 index 0000000000..8a30f47ae4 --- /dev/null +++ b/platforms/avr/drivers/spi_master.h @@ -0,0 +1,59 @@ +/* Copyright 2020 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include + +#include "gpio.h" + +typedef int16_t spi_status_t; + +// Hardware SS pin is defined in the header so that user code can refer to it +#if defined(__AVR_AT90USB162__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) +# define SPI_SS_PIN B0 +#elif defined(__AVR_ATmega32A__) +# define SPI_SS_PIN B4 +#elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) +# define SPI_SS_PIN B2 +#endif + +#define SPI_STATUS_SUCCESS (0) +#define SPI_STATUS_ERROR (-1) +#define SPI_STATUS_TIMEOUT (-2) + +#define SPI_TIMEOUT_IMMEDIATE (0) +#define SPI_TIMEOUT_INFINITE (0xFFFF) + +#ifdef __cplusplus +extern "C" { +#endif +void spi_init(void); + +bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor); + +spi_status_t spi_write(uint8_t data); + +spi_status_t spi_read(void); + +spi_status_t spi_transmit(const uint8_t *data, uint16_t length); + +spi_status_t spi_receive(uint8_t *data, uint16_t length); + +void spi_stop(void); +#ifdef __cplusplus +} +#endif diff --git a/platforms/avr/drivers/ssd1306.c b/platforms/avr/drivers/ssd1306.c new file mode 100644 index 0000000000..1a09a2bcb7 --- /dev/null +++ b/platforms/avr/drivers/ssd1306.c @@ -0,0 +1,319 @@ +#ifdef SSD1306OLED + +# include "ssd1306.h" +# include "i2c.h" +# include +# include "print.h" +# include "glcdfont.c" +# ifdef PROTOCOL_LUFA +# include "lufa.h" +# endif +# include "sendchar.h" +# include "timer.h" + +struct CharacterMatrix display; + +// Set this to 1 to help diagnose early startup problems +// when testing power-on with ble. Turn it off otherwise, +// as the latency of printing most of the debug info messes +// with the matrix scan, causing keys to drop. +# define DEBUG_TO_SCREEN 0 + +// static uint16_t last_battery_update; +// static uint32_t vbat; +//#define BatteryUpdateInterval 10000 /* milliseconds */ +# define ScreenOffInterval 300000 /* milliseconds */ +# if DEBUG_TO_SCREEN +static uint8_t displaying; +# endif +static uint16_t last_flush; + +// Write command sequence. +// Returns true on success. +static inline bool _send_cmd1(uint8_t cmd) { + bool res = false; + + if (i2c_start_write(SSD1306_ADDRESS)) { + xprintf("failed to start write to %d\n", SSD1306_ADDRESS); + goto done; + } + + if (i2c_master_write(0x0 /* command byte follows */)) { + print("failed to write control byte\n"); + + goto done; + } + + if (i2c_master_write(cmd)) { + xprintf("failed to write command %d\n", cmd); + goto done; + } + res = true; +done: + i2c_master_stop(); + return res; +} + +// Write 2-byte command sequence. +// Returns true on success +static inline bool _send_cmd2(uint8_t cmd, uint8_t opr) { + if (!_send_cmd1(cmd)) { + return false; + } + return _send_cmd1(opr); +} + +// Write 3-byte command sequence. +// Returns true on success +static inline bool _send_cmd3(uint8_t cmd, uint8_t opr1, uint8_t opr2) { + if (!_send_cmd1(cmd)) { + return false; + } + if (!_send_cmd1(opr1)) { + return false; + } + return _send_cmd1(opr2); +} + +# define send_cmd1(c) \ + if (!_send_cmd1(c)) { \ + goto done; \ + } +# define send_cmd2(c, o) \ + if (!_send_cmd2(c, o)) { \ + goto done; \ + } +# define send_cmd3(c, o1, o2) \ + if (!_send_cmd3(c, o1, o2)) { \ + goto done; \ + } + +static void clear_display(void) { + matrix_clear(&display); + + // Clear all of the display bits (there can be random noise + // in the RAM on startup) + send_cmd3(PageAddr, 0, (DisplayHeight / 8) - 1); + send_cmd3(ColumnAddr, 0, DisplayWidth - 1); + + if (i2c_start_write(SSD1306_ADDRESS)) { + goto done; + } + if (i2c_master_write(0x40)) { + // Data mode + goto done; + } + for (uint8_t row = 0; row < MatrixRows; ++row) { + for (uint8_t col = 0; col < DisplayWidth; ++col) { + i2c_master_write(0); + } + } + + display.dirty = false; + +done: + i2c_master_stop(); +} + +# if DEBUG_TO_SCREEN +# undef sendchar +static int8_t capture_sendchar(uint8_t c) { + sendchar(c); + iota_gfx_write_char(c); + + if (!displaying) { + iota_gfx_flush(); + } + return 0; +} +# endif + +bool iota_gfx_init(void) { + bool success = false; + + send_cmd1(DisplayOff); + send_cmd2(SetDisplayClockDiv, 0x80); + send_cmd2(SetMultiPlex, DisplayHeight - 1); + + send_cmd2(SetDisplayOffset, 0); + + send_cmd1(SetStartLine | 0x0); + send_cmd2(SetChargePump, 0x14 /* Enable */); + send_cmd2(SetMemoryMode, 0 /* horizontal addressing */); + +# ifdef OLED_ROTATE180 + // the following Flip the display orientation 180 degrees + send_cmd1(SegRemap); + send_cmd1(ComScanInc); +# endif +# ifndef OLED_ROTATE180 + // Flips the display orientation 0 degrees + send_cmd1(SegRemap | 0x1); + send_cmd1(ComScanDec); +# endif + + send_cmd2(SetComPins, 0x2); + send_cmd2(SetContrast, 0x8f); + send_cmd2(SetPreCharge, 0xf1); + send_cmd2(SetVComDetect, 0x40); + send_cmd1(DisplayAllOnResume); + send_cmd1(NormalDisplay); + send_cmd1(DeActivateScroll); + send_cmd1(DisplayOn); + + send_cmd2(SetContrast, 0); // Dim + + clear_display(); + + success = true; + + iota_gfx_flush(); + +# if DEBUG_TO_SCREEN + print_set_sendchar(capture_sendchar); +# endif + +done: + return success; +} + +bool iota_gfx_off(void) { + bool success = false; + + send_cmd1(DisplayOff); + success = true; + +done: + return success; +} + +bool iota_gfx_on(void) { + bool success = false; + + send_cmd1(DisplayOn); + success = true; + +done: + return success; +} + +void matrix_write_char_inner(struct CharacterMatrix *matrix, uint8_t c) { + *matrix->cursor = c; + ++matrix->cursor; + + if (matrix->cursor - &matrix->display[0][0] == sizeof(matrix->display)) { + // We went off the end; scroll the display upwards by one line + memmove(&matrix->display[0], &matrix->display[1], MatrixCols * (MatrixRows - 1)); + matrix->cursor = &matrix->display[MatrixRows - 1][0]; + memset(matrix->cursor, ' ', MatrixCols); + } +} + +void matrix_write_char(struct CharacterMatrix *matrix, uint8_t c) { + matrix->dirty = true; + + if (c == '\n') { + // Clear to end of line from the cursor and then move to the + // start of the next line + uint8_t cursor_col = (matrix->cursor - &matrix->display[0][0]) % MatrixCols; + + while (cursor_col++ < MatrixCols) { + matrix_write_char_inner(matrix, ' '); + } + return; + } + + matrix_write_char_inner(matrix, c); +} + +void iota_gfx_write_char(uint8_t c) { matrix_write_char(&display, c); } + +void matrix_write(struct CharacterMatrix *matrix, const char *data) { + const char *end = data + strlen(data); + while (data < end) { + matrix_write_char(matrix, *data); + ++data; + } +} + +void iota_gfx_write(const char *data) { matrix_write(&display, data); } + +void matrix_write_P(struct CharacterMatrix *matrix, const char *data) { + while (true) { + uint8_t c = pgm_read_byte(data); + if (c == 0) { + return; + } + matrix_write_char(matrix, c); + ++data; + } +} + +void iota_gfx_write_P(const char *data) { matrix_write_P(&display, data); } + +void matrix_clear(struct CharacterMatrix *matrix) { + memset(matrix->display, ' ', sizeof(matrix->display)); + matrix->cursor = &matrix->display[0][0]; + matrix->dirty = true; +} + +void iota_gfx_clear_screen(void) { matrix_clear(&display); } + +void matrix_render(struct CharacterMatrix *matrix) { + last_flush = timer_read(); + iota_gfx_on(); +# if DEBUG_TO_SCREEN + ++displaying; +# endif + + // Move to the home position + send_cmd3(PageAddr, 0, MatrixRows - 1); + send_cmd3(ColumnAddr, 0, (MatrixCols * FontWidth) - 1); + + if (i2c_start_write(SSD1306_ADDRESS)) { + goto done; + } + if (i2c_master_write(0x40)) { + // Data mode + goto done; + } + + for (uint8_t row = 0; row < MatrixRows; ++row) { + for (uint8_t col = 0; col < MatrixCols; ++col) { + const uint8_t *glyph = font + (matrix->display[row][col] * (FontWidth - 1)); + + for (uint8_t glyphCol = 0; glyphCol < FontWidth - 1; ++glyphCol) { + uint8_t colBits = pgm_read_byte(glyph + glyphCol); + i2c_master_write(colBits); + } + + // 1 column of space between chars (it's not included in the glyph) + i2c_master_write(0); + } + } + + matrix->dirty = false; + +done: + i2c_master_stop(); +# if DEBUG_TO_SCREEN + --displaying; +# endif +} + +void iota_gfx_flush(void) { matrix_render(&display); } + +__attribute__((weak)) void iota_gfx_task_user(void) {} + +void iota_gfx_task(void) { + iota_gfx_task_user(); + + if (display.dirty) { + iota_gfx_flush(); + } + + if (timer_elapsed(last_flush) > ScreenOffInterval) { + iota_gfx_off(); + } +} +#endif diff --git a/platforms/avr/drivers/ssd1306.h b/platforms/avr/drivers/ssd1306.h new file mode 100644 index 0000000000..6eecdcfaa4 --- /dev/null +++ b/platforms/avr/drivers/ssd1306.h @@ -0,0 +1,87 @@ +#pragma once + +#include +#include +#include "config.h" + +enum ssd1306_cmds { + DisplayOff = 0xAE, + DisplayOn = 0xAF, + + SetContrast = 0x81, + DisplayAllOnResume = 0xA4, + + DisplayAllOn = 0xA5, + NormalDisplay = 0xA6, + InvertDisplay = 0xA7, + SetDisplayOffset = 0xD3, + SetComPins = 0xda, + SetVComDetect = 0xdb, + SetDisplayClockDiv = 0xD5, + SetPreCharge = 0xd9, + SetMultiPlex = 0xa8, + SetLowColumn = 0x00, + SetHighColumn = 0x10, + SetStartLine = 0x40, + + SetMemoryMode = 0x20, + ColumnAddr = 0x21, + PageAddr = 0x22, + + ComScanInc = 0xc0, + ComScanDec = 0xc8, + SegRemap = 0xa0, + SetChargePump = 0x8d, + ExternalVcc = 0x01, + SwitchCapVcc = 0x02, + + ActivateScroll = 0x2f, + DeActivateScroll = 0x2e, + SetVerticalScrollArea = 0xa3, + RightHorizontalScroll = 0x26, + LeftHorizontalScroll = 0x27, + VerticalAndRightHorizontalScroll = 0x29, + VerticalAndLeftHorizontalScroll = 0x2a, +}; + +// Controls the SSD1306 128x32 OLED display via i2c + +#ifndef SSD1306_ADDRESS +# define SSD1306_ADDRESS 0x3C +#endif + +#define DisplayHeight 32 +#define DisplayWidth 128 + +#define FontHeight 8 +#define FontWidth 6 + +#define MatrixRows (DisplayHeight / FontHeight) +#define MatrixCols (DisplayWidth / FontWidth) + +struct CharacterMatrix { + uint8_t display[MatrixRows][MatrixCols]; + uint8_t *cursor; + bool dirty; +}; + +extern struct CharacterMatrix display; + +bool iota_gfx_init(void); +void iota_gfx_task(void); +bool iota_gfx_off(void); +bool iota_gfx_on(void); +void iota_gfx_flush(void); +void iota_gfx_write_char(uint8_t c); +void iota_gfx_write(const char *data); +void iota_gfx_write_P(const char *data); +void iota_gfx_clear_screen(void); + +void iota_gfx_task_user(void); + +void matrix_clear(struct CharacterMatrix *matrix); +void matrix_write_char_inner(struct CharacterMatrix *matrix, uint8_t c); +void matrix_write_char(struct CharacterMatrix *matrix, uint8_t c); +void matrix_write(struct CharacterMatrix *matrix, const char *data); +void matrix_write_P(struct CharacterMatrix *matrix, const char *data); +void matrix_render(struct CharacterMatrix *matrix); diff --git a/platforms/avr/drivers/uart.c b/platforms/avr/drivers/uart.c new file mode 100644 index 0000000000..c6abcb6fe0 --- /dev/null +++ b/platforms/avr/drivers/uart.c @@ -0,0 +1,170 @@ +/* UART Example for Teensy USB Development Board + * http://www.pjrc.com/teensy/ + * Copyright (c) 2009 PJRC.COM, LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// Version 1.0: Initial Release +// Version 1.1: Add support for Teensy 2.0, minor optimizations + +#include +#include + +#include "uart.h" + +#if defined(__AVR_AT90USB162__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) +# define UDRn UDR1 +# define UBRRnL UBRR1L +# define UCSRnA UCSR1A +# define UCSRnB UCSR1B +# define UCSRnC UCSR1C +# define U2Xn U2X1 +# define RXENn RXEN1 +# define TXENn TXEN1 +# define RXCIEn RXCIE1 +# define UCSZn1 UCSZ11 +# define UCSZn0 UCSZ10 +# define UDRIEn UDRIE1 +# define USARTn_UDRE_vect USART1_UDRE_vect +# define USARTn_RX_vect USART1_RX_vect +#elif defined(__AVR_ATmega32A__) +# define UDRn UDR +# define UBRRnL UBRRL +# define UCSRnA UCSRA +# define UCSRnB UCSRB +# define UCSRnC UCSRC +# define U2Xn U2X +# define RXENn RXEN +# define TXENn TXEN +# define RXCIEn RXCIE +# define UCSZn1 UCSZ1 +# define UCSZn0 UCSZ0 +# define UDRIEn UDRIE +# define USARTn_UDRE_vect USART_UDRE_vect +# define USARTn_RX_vect USART_RX_vect +#elif defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) +# define UDRn UDR0 +# define UBRRnL UBRR0L +# define UCSRnA UCSR0A +# define UCSRnB UCSR0B +# define UCSRnC UCSR0C +# define U2Xn U2X0 +# define RXENn RXEN0 +# define TXENn TXEN0 +# define RXCIEn RXCIE0 +# define UCSZn1 UCSZ01 +# define UCSZn0 UCSZ00 +# define UDRIEn UDRIE0 +# define USARTn_UDRE_vect USART_UDRE_vect +# define USARTn_RX_vect USART_RX_vect +#endif + +// These buffers may be any size from 2 to 256 bytes. +#define RX_BUFFER_SIZE 64 +#define TX_BUFFER_SIZE 256 + +static volatile uint8_t tx_buffer[TX_BUFFER_SIZE]; +static volatile uint8_t tx_buffer_head; +static volatile uint8_t tx_buffer_tail; +static volatile uint8_t rx_buffer[RX_BUFFER_SIZE]; +static volatile uint8_t rx_buffer_head; +static volatile uint8_t rx_buffer_tail; + +// Initialize the UART +void uart_init(uint32_t baud) { + cli(); + UBRRnL = (F_CPU / 4 / baud - 1) / 2; + UCSRnA = (1 << U2Xn); + UCSRnB = (1 << RXENn) | (1 << TXENn) | (1 << RXCIEn); + UCSRnC = (1 << UCSZn1) | (1 << UCSZn0); + tx_buffer_head = tx_buffer_tail = 0; + rx_buffer_head = rx_buffer_tail = 0; + sei(); +} + +// Transmit a byte +void uart_putchar(uint8_t c) { + uint8_t i; + + i = tx_buffer_head + 1; + if (i >= TX_BUFFER_SIZE) i = 0; + // return immediately to avoid deadlock when interrupt is disabled(called from ISR) + if (tx_buffer_tail == i && (SREG & (1 << SREG_I)) == 0) return; + while (tx_buffer_tail == i) + ; // wait until space in buffer + // cli(); + tx_buffer[i] = c; + tx_buffer_head = i; + UCSRnB = (1 << RXENn) | (1 << TXENn) | (1 << RXCIEn) | (1 << UDRIEn); + // sei(); +} + +// Receive a byte +uint8_t uart_getchar(void) { + uint8_t c, i; + + while (rx_buffer_head == rx_buffer_tail) + ; // wait for character + i = rx_buffer_tail + 1; + if (i >= RX_BUFFER_SIZE) i = 0; + c = rx_buffer[i]; + rx_buffer_tail = i; + return c; +} + +// Return whether the number of bytes waiting in the receive buffer is nonzero. +// Call this before uart_getchar() to check if it will need +// to wait for a byte to arrive. +bool uart_available(void) { + uint8_t head, tail; + + head = rx_buffer_head; + tail = rx_buffer_tail; + if (head >= tail) return (head - tail) > 0; + return (RX_BUFFER_SIZE + head - tail) > 0; +} + +// Transmit Interrupt +ISR(USARTn_UDRE_vect) { + uint8_t i; + + if (tx_buffer_head == tx_buffer_tail) { + // buffer is empty, disable transmit interrupt + UCSRnB = (1 << RXENn) | (1 << TXENn) | (1 << RXCIEn); + } else { + i = tx_buffer_tail + 1; + if (i >= TX_BUFFER_SIZE) i = 0; + UDRn = tx_buffer[i]; + tx_buffer_tail = i; + } +} + +// Receive Interrupt +ISR(USARTn_RX_vect) { + uint8_t c, i; + + c = UDRn; + i = rx_buffer_head + 1; + if (i >= RX_BUFFER_SIZE) i = 0; + if (i != rx_buffer_tail) { + rx_buffer[i] = c; + rx_buffer_head = i; + } +} diff --git a/platforms/avr/drivers/uart.h b/platforms/avr/drivers/uart.h new file mode 100644 index 0000000000..602eb3d8b0 --- /dev/null +++ b/platforms/avr/drivers/uart.h @@ -0,0 +1,35 @@ +/* UART Example for Teensy USB Development Board + * http://www.pjrc.com/teensy/ + * Copyright (c) 2009 PJRC.COM, LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +#include +#include + +void uart_init(uint32_t baud); + +void uart_putchar(uint8_t c); + +uint8_t uart_getchar(void); + +bool uart_available(void); diff --git a/platforms/avr/drivers/ws2812.c b/platforms/avr/drivers/ws2812.c new file mode 100644 index 0000000000..77c492cd4c --- /dev/null +++ b/platforms/avr/drivers/ws2812.c @@ -0,0 +1,176 @@ +/* + * light weight WS2812 lib V2.0b + * + * Controls WS2811/WS2812/WS2812B RGB-LEDs + * Author: Tim (cpldcpu@gmail.com) + * + * Jan 18th, 2014 v2.0b Initial Version + * Nov 29th, 2015 v2.3 Added SK6812RGBW support + * + * 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 . + */ +#include "ws2812.h" +#include +#include +#include + +#define pinmask(pin) (_BV((pin)&0xF)) + +/* + * Forward declare internal functions + * + * The functions take a byte-array and send to the data output as WS2812 bitstream. + * The length is the number of bytes to send - three per LED. + */ + +static inline void ws2812_sendarray_mask(uint8_t *data, uint16_t datlen, uint8_t masklo, uint8_t maskhi); + +void ws2812_setleds(LED_TYPE *ledarray, uint16_t number_of_leds) { + DDRx_ADDRESS(RGB_DI_PIN) |= pinmask(RGB_DI_PIN); + + uint8_t masklo = ~(pinmask(RGB_DI_PIN)) & PORTx_ADDRESS(RGB_DI_PIN); + uint8_t maskhi = pinmask(RGB_DI_PIN) | PORTx_ADDRESS(RGB_DI_PIN); + + ws2812_sendarray_mask((uint8_t *)ledarray, number_of_leds * sizeof(LED_TYPE), masklo, maskhi); + + _delay_us(WS2812_TRST_US); +} + +/* + This routine writes an array of bytes with RGB values to the Dataout pin + using the fast 800kHz clockless WS2811/2812 protocol. +*/ + +// Timing in ns +#define w_zeropulse 350 +#define w_onepulse 900 +#define w_totalperiod 1250 + +// Fixed cycles used by the inner loop +#define w_fixedlow 2 +#define w_fixedhigh 4 +#define w_fixedtotal 8 + +// Insert NOPs to match the timing, if possible +#define w_zerocycles (((F_CPU / 1000) * w_zeropulse) / 1000000) +#define w_onecycles (((F_CPU / 1000) * w_onepulse + 500000) / 1000000) +#define w_totalcycles (((F_CPU / 1000) * w_totalperiod + 500000) / 1000000) + +// w1_nops - nops between rising edge and falling edge - low +#if w_zerocycles >= w_fixedlow +# define w1_nops (w_zerocycles - w_fixedlow) +#else +# define w1_nops 0 +#endif + +// w2_nops - nops between fe low and fe high +#if w_onecycles >= (w_fixedhigh + w1_nops) +# define w2_nops (w_onecycles - w_fixedhigh - w1_nops) +#else +# define w2_nops 0 +#endif + +// w3_nops - nops to complete loop +#if w_totalcycles >= (w_fixedtotal + w1_nops + w2_nops) +# define w3_nops (w_totalcycles - w_fixedtotal - w1_nops - w2_nops) +#else +# define w3_nops 0 +#endif + +// The only critical timing parameter is the minimum pulse length of the "0" +// Warn or throw error if this timing can not be met with current F_CPU settings. +#define w_lowtime ((w1_nops + w_fixedlow) * 1000000) / (F_CPU / 1000) +#if w_lowtime > 550 +# error "Light_ws2812: Sorry, the clock speed is too low. Did you set F_CPU correctly?" +#elif w_lowtime > 450 +# warning "Light_ws2812: The timing is critical and may only work on WS2812B, not on WS2812(S)." +# warning "Please consider a higher clockspeed, if possible" +#endif + +#define w_nop1 "nop \n\t" +#define w_nop2 "rjmp .+0 \n\t" +#define w_nop4 w_nop2 w_nop2 +#define w_nop8 w_nop4 w_nop4 +#define w_nop16 w_nop8 w_nop8 + +static inline void ws2812_sendarray_mask(uint8_t *data, uint16_t datlen, uint8_t masklo, uint8_t maskhi) { + uint8_t curbyte, ctr, sreg_prev; + + sreg_prev = SREG; + cli(); + + while (datlen--) { + curbyte = (*data++); + + asm volatile(" ldi %0,8 \n\t" + "loop%=: \n\t" + " out %2,%3 \n\t" // '1' [01] '0' [01] - re +#if (w1_nops & 1) + w_nop1 +#endif +#if (w1_nops & 2) + w_nop2 +#endif +#if (w1_nops & 4) + w_nop4 +#endif +#if (w1_nops & 8) + w_nop8 +#endif +#if (w1_nops & 16) + w_nop16 +#endif + " sbrs %1,7 \n\t" // '1' [03] '0' [02] + " out %2,%4 \n\t" // '1' [--] '0' [03] - fe-low + " lsl %1 \n\t" // '1' [04] '0' [04] +#if (w2_nops & 1) + w_nop1 +#endif +#if (w2_nops & 2) + w_nop2 +#endif +#if (w2_nops & 4) + w_nop4 +#endif +#if (w2_nops & 8) + w_nop8 +#endif +#if (w2_nops & 16) + w_nop16 +#endif + " out %2,%4 \n\t" // '1' [+1] '0' [+1] - fe-high +#if (w3_nops & 1) + w_nop1 +#endif +#if (w3_nops & 2) + w_nop2 +#endif +#if (w3_nops & 4) + w_nop4 +#endif +#if (w3_nops & 8) + w_nop8 +#endif +#if (w3_nops & 16) + w_nop16 +#endif + + " dec %0 \n\t" // '1' [+2] '0' [+2] + " brne loop%=\n\t" // '1' [+3] '0' [+4] + : "=&d"(ctr) + : "r"(curbyte), "I"(_SFR_IO_ADDR(PORTx_ADDRESS(RGB_DI_PIN))), "r"(maskhi), "r"(masklo)); + } + + SREG = sreg_prev; +} diff --git a/platforms/avr/drivers/ws2812_i2c.c b/platforms/avr/drivers/ws2812_i2c.c new file mode 100644 index 0000000000..1c332e24b6 --- /dev/null +++ b/platforms/avr/drivers/ws2812_i2c.c @@ -0,0 +1,27 @@ +#include "ws2812.h" +#include "i2c_master.h" + +#ifdef RGBW +# error "RGBW not supported" +#endif + +#ifndef WS2812_ADDRESS +# define WS2812_ADDRESS 0xb0 +#endif + +#ifndef WS2812_TIMEOUT +# define WS2812_TIMEOUT 100 +#endif + +void ws2812_init(void) { i2c_init(); } + +// Setleds for standard RGB +void ws2812_setleds(LED_TYPE *ledarray, uint16_t leds) { + static bool s_init = false; + if (!s_init) { + ws2812_init(); + s_init = true; + } + + i2c_transmit(WS2812_ADDRESS, (uint8_t *)ledarray, sizeof(LED_TYPE) * leds, WS2812_TIMEOUT); +} diff --git a/platforms/chibios/drivers/analog.c b/platforms/chibios/drivers/analog.c new file mode 100644 index 0000000000..8c476fcac2 --- /dev/null +++ b/platforms/chibios/drivers/analog.c @@ -0,0 +1,321 @@ +/* Copyright 2019 Drew Mills + * + * 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 . + */ + +#include "quantum.h" +#include "analog.h" +#include +#include + +#if !HAL_USE_ADC +# error "You need to set HAL_USE_ADC to TRUE in your halconf.h to use the ADC." +#endif + +#if !STM32_ADC_USE_ADC1 && !STM32_ADC_USE_ADC2 && !STM32_ADC_USE_ADC3 && !STM32_ADC_USE_ADC4 +# error "You need to set one of the 'STM32_ADC_USE_ADCx' settings to TRUE in your mcuconf.h to use the ADC." +#endif + +#if STM32_ADC_DUAL_MODE +# error "STM32 ADC Dual Mode is not supported at this time." +#endif + +#if STM32_ADCV3_OVERSAMPLING +# error "STM32 ADCV3 Oversampling is not supported at this time." +#endif + +// Otherwise assume V3 +#if defined(STM32F0XX) || defined(STM32L0XX) +# define USE_ADCV1 +#elif defined(STM32F1XX) || defined(STM32F2XX) || defined(STM32F4XX) +# define USE_ADCV2 +#endif + +// BODGE to make v2 look like v1,3 and 4 +#ifdef USE_ADCV2 +# if !defined(ADC_SMPR_SMP_1P5) && defined(ADC_SAMPLE_3) +# define ADC_SMPR_SMP_1P5 ADC_SAMPLE_3 +# define ADC_SMPR_SMP_7P5 ADC_SAMPLE_15 +# define ADC_SMPR_SMP_13P5 ADC_SAMPLE_28 +# define ADC_SMPR_SMP_28P5 ADC_SAMPLE_56 +# define ADC_SMPR_SMP_41P5 ADC_SAMPLE_84 +# define ADC_SMPR_SMP_55P5 ADC_SAMPLE_112 +# define ADC_SMPR_SMP_71P5 ADC_SAMPLE_144 +# define ADC_SMPR_SMP_239P5 ADC_SAMPLE_480 +# endif + +# if !defined(ADC_SMPR_SMP_1P5) && defined(ADC_SAMPLE_1P5) +# define ADC_SMPR_SMP_1P5 ADC_SAMPLE_1P5 +# define ADC_SMPR_SMP_7P5 ADC_SAMPLE_7P5 +# define ADC_SMPR_SMP_13P5 ADC_SAMPLE_13P5 +# define ADC_SMPR_SMP_28P5 ADC_SAMPLE_28P5 +# define ADC_SMPR_SMP_41P5 ADC_SAMPLE_41P5 +# define ADC_SMPR_SMP_55P5 ADC_SAMPLE_55P5 +# define ADC_SMPR_SMP_71P5 ADC_SAMPLE_71P5 +# define ADC_SMPR_SMP_239P5 ADC_SAMPLE_239P5 +# endif + +// we still sample at 12bit, but scale down to the requested bit range +# define ADC_CFGR1_RES_12BIT 12 +# define ADC_CFGR1_RES_10BIT 10 +# define ADC_CFGR1_RES_8BIT 8 +# define ADC_CFGR1_RES_6BIT 6 +#endif + +/* User configurable ADC options */ +#ifndef ADC_COUNT +# if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F4XX) +# define ADC_COUNT 1 +# elif defined(STM32F3XX) +# define ADC_COUNT 4 +# else +# error "ADC_COUNT has not been set for this ARM microcontroller." +# endif +#endif + +#ifndef ADC_NUM_CHANNELS +# define ADC_NUM_CHANNELS 1 +#elif ADC_NUM_CHANNELS != 1 +# error "The ARM ADC implementation currently only supports reading one channel at a time." +#endif + +#ifndef ADC_BUFFER_DEPTH +# define ADC_BUFFER_DEPTH 1 +#endif + +// For more sampling rate options, look at hal_adc_lld.h in ChibiOS +#ifndef ADC_SAMPLING_RATE +# define ADC_SAMPLING_RATE ADC_SMPR_SMP_1P5 +#endif + +// Options are 12, 10, 8, and 6 bit. +#ifndef ADC_RESOLUTION +# ifdef ADC_CFGR_RES_10BITS // ADCv3, ADCv4 +# define ADC_RESOLUTION ADC_CFGR_RES_10BITS +# else // ADCv1, ADCv5, or the bodge for ADCv2 above +# define ADC_RESOLUTION ADC_CFGR1_RES_10BIT +# endif +#endif + +static ADCConfig adcCfg = {}; +static adcsample_t sampleBuffer[ADC_NUM_CHANNELS * ADC_BUFFER_DEPTH]; + +// Initialize to max number of ADCs, set to empty object to initialize all to false. +static bool adcInitialized[ADC_COUNT] = {}; + +// TODO: add back TR handling??? +static ADCConversionGroup adcConversionGroup = { + .circular = FALSE, + .num_channels = (uint16_t)(ADC_NUM_CHANNELS), +#if defined(USE_ADCV1) + .cfgr1 = ADC_CFGR1_CONT | ADC_RESOLUTION, + .smpr = ADC_SAMPLING_RATE, +#elif defined(USE_ADCV2) +# if !defined(STM32F1XX) + .cr2 = ADC_CR2_SWSTART, // F103 seem very unhappy with, F401 seems very unhappy without... +# endif + .smpr2 = ADC_SMPR2_SMP_AN0(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN1(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN2(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN3(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN4(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN5(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN6(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN7(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN8(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN9(ADC_SAMPLING_RATE), + .smpr1 = ADC_SMPR1_SMP_AN10(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN11(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN12(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN13(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN14(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN15(ADC_SAMPLING_RATE), +#else + .cfgr = ADC_CFGR_CONT | ADC_RESOLUTION, + .smpr = {ADC_SMPR1_SMP_AN0(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN1(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN2(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN3(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN4(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN5(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN6(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN7(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN8(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN9(ADC_SAMPLING_RATE), ADC_SMPR2_SMP_AN10(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN11(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN12(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN13(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN14(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN15(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN16(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN17(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN18(ADC_SAMPLING_RATE)}, +#endif +}; + +// clang-format off +__attribute__((weak)) adc_mux pinToMux(pin_t pin) { + switch (pin) { +#if defined(STM32F0XX) + case A0: return TO_MUX( ADC_CHSELR_CHSEL0, 0 ); + case A1: return TO_MUX( ADC_CHSELR_CHSEL1, 0 ); + case A2: return TO_MUX( ADC_CHSELR_CHSEL2, 0 ); + case A3: return TO_MUX( ADC_CHSELR_CHSEL3, 0 ); + case A4: return TO_MUX( ADC_CHSELR_CHSEL4, 0 ); + case A5: return TO_MUX( ADC_CHSELR_CHSEL5, 0 ); + case A6: return TO_MUX( ADC_CHSELR_CHSEL6, 0 ); + case A7: return TO_MUX( ADC_CHSELR_CHSEL7, 0 ); + case B0: return TO_MUX( ADC_CHSELR_CHSEL8, 0 ); + case B1: return TO_MUX( ADC_CHSELR_CHSEL9, 0 ); + case C0: return TO_MUX( ADC_CHSELR_CHSEL10, 0 ); + case C1: return TO_MUX( ADC_CHSELR_CHSEL11, 0 ); + case C2: return TO_MUX( ADC_CHSELR_CHSEL12, 0 ); + case C3: return TO_MUX( ADC_CHSELR_CHSEL13, 0 ); + case C4: return TO_MUX( ADC_CHSELR_CHSEL14, 0 ); + case C5: return TO_MUX( ADC_CHSELR_CHSEL15, 0 ); +#elif defined(STM32F3XX) + case A0: return TO_MUX( ADC_CHANNEL_IN1, 0 ); + case A1: return TO_MUX( ADC_CHANNEL_IN2, 0 ); + case A2: return TO_MUX( ADC_CHANNEL_IN3, 0 ); + case A3: return TO_MUX( ADC_CHANNEL_IN4, 0 ); + case A4: return TO_MUX( ADC_CHANNEL_IN1, 1 ); + case A5: return TO_MUX( ADC_CHANNEL_IN2, 1 ); + case A6: return TO_MUX( ADC_CHANNEL_IN3, 1 ); + case A7: return TO_MUX( ADC_CHANNEL_IN4, 1 ); + case B0: return TO_MUX( ADC_CHANNEL_IN12, 2 ); + case B1: return TO_MUX( ADC_CHANNEL_IN1, 2 ); + case B2: return TO_MUX( ADC_CHANNEL_IN12, 1 ); + case B12: return TO_MUX( ADC_CHANNEL_IN3, 3 ); + case B13: return TO_MUX( ADC_CHANNEL_IN5, 2 ); + case B14: return TO_MUX( ADC_CHANNEL_IN4, 3 ); + case B15: return TO_MUX( ADC_CHANNEL_IN5, 3 ); + case C0: return TO_MUX( ADC_CHANNEL_IN6, 0 ); // Can also be ADC2 + case C1: return TO_MUX( ADC_CHANNEL_IN7, 0 ); // Can also be ADC2 + case C2: return TO_MUX( ADC_CHANNEL_IN8, 0 ); // Can also be ADC2 + case C3: return TO_MUX( ADC_CHANNEL_IN9, 0 ); // Can also be ADC2 + case C4: return TO_MUX( ADC_CHANNEL_IN5, 1 ); + case C5: return TO_MUX( ADC_CHANNEL_IN11, 1 ); + case D8: return TO_MUX( ADC_CHANNEL_IN12, 3 ); + case D9: return TO_MUX( ADC_CHANNEL_IN13, 3 ); + case D10: return TO_MUX( ADC_CHANNEL_IN7, 2 ); // Can also be ADC4 + case D11: return TO_MUX( ADC_CHANNEL_IN8, 2 ); // Can also be ADC4 + case D12: return TO_MUX( ADC_CHANNEL_IN9, 2 ); // Can also be ADC4 + case D13: return TO_MUX( ADC_CHANNEL_IN10, 2 ); // Can also be ADC4 + case D14: return TO_MUX( ADC_CHANNEL_IN11, 2 ); // Can also be ADC4 + case E7: return TO_MUX( ADC_CHANNEL_IN13, 2 ); + case E8: return TO_MUX( ADC_CHANNEL_IN6, 2 ); // Can also be ADC4 + case E9: return TO_MUX( ADC_CHANNEL_IN2, 2 ); + case E10: return TO_MUX( ADC_CHANNEL_IN14, 2 ); + case E11: return TO_MUX( ADC_CHANNEL_IN15, 2 ); + case E12: return TO_MUX( ADC_CHANNEL_IN16, 2 ); + case E13: return TO_MUX( ADC_CHANNEL_IN3, 2 ); + case E14: return TO_MUX( ADC_CHANNEL_IN1, 3 ); + case E15: return TO_MUX( ADC_CHANNEL_IN2, 3 ); + case F2: return TO_MUX( ADC_CHANNEL_IN10, 0 ); // Can also be ADC2 + case F4: return TO_MUX( ADC_CHANNEL_IN5, 0 ); +#elif defined(STM32F4XX) + case A0: return TO_MUX( ADC_CHANNEL_IN0, 0 ); + case A1: return TO_MUX( ADC_CHANNEL_IN1, 0 ); + case A2: return TO_MUX( ADC_CHANNEL_IN2, 0 ); + case A3: return TO_MUX( ADC_CHANNEL_IN3, 0 ); + case A4: return TO_MUX( ADC_CHANNEL_IN4, 0 ); + case A5: return TO_MUX( ADC_CHANNEL_IN5, 0 ); + case A6: return TO_MUX( ADC_CHANNEL_IN6, 0 ); + case A7: return TO_MUX( ADC_CHANNEL_IN7, 0 ); + case B0: return TO_MUX( ADC_CHANNEL_IN8, 0 ); + case B1: return TO_MUX( ADC_CHANNEL_IN9, 0 ); + case C0: return TO_MUX( ADC_CHANNEL_IN10, 0 ); + case C1: return TO_MUX( ADC_CHANNEL_IN11, 0 ); + case C2: return TO_MUX( ADC_CHANNEL_IN12, 0 ); + case C3: return TO_MUX( ADC_CHANNEL_IN13, 0 ); + case C4: return TO_MUX( ADC_CHANNEL_IN14, 0 ); + case C5: return TO_MUX( ADC_CHANNEL_IN15, 0 ); +# if STM32_ADC_USE_ADC3 + case F3: return TO_MUX( ADC_CHANNEL_IN9, 2 ); + case F4: return TO_MUX( ADC_CHANNEL_IN14, 2 ); + case F5: return TO_MUX( ADC_CHANNEL_IN15, 2 ); + case F6: return TO_MUX( ADC_CHANNEL_IN4, 2 ); + case F7: return TO_MUX( ADC_CHANNEL_IN5, 2 ); + case F8: return TO_MUX( ADC_CHANNEL_IN6, 2 ); + case F9: return TO_MUX( ADC_CHANNEL_IN7, 2 ); + case F10: return TO_MUX( ADC_CHANNEL_IN8, 2 ); +# endif +#elif defined(STM32F1XX) + case A0: return TO_MUX( ADC_CHANNEL_IN0, 0 ); + case A1: return TO_MUX( ADC_CHANNEL_IN1, 0 ); + case A2: return TO_MUX( ADC_CHANNEL_IN2, 0 ); + case A3: return TO_MUX( ADC_CHANNEL_IN3, 0 ); + case A4: return TO_MUX( ADC_CHANNEL_IN4, 0 ); + case A5: return TO_MUX( ADC_CHANNEL_IN5, 0 ); + case A6: return TO_MUX( ADC_CHANNEL_IN6, 0 ); + case A7: return TO_MUX( ADC_CHANNEL_IN7, 0 ); + case B0: return TO_MUX( ADC_CHANNEL_IN8, 0 ); + case B1: return TO_MUX( ADC_CHANNEL_IN9, 0 ); + case C0: return TO_MUX( ADC_CHANNEL_IN10, 0 ); + case C1: return TO_MUX( ADC_CHANNEL_IN11, 0 ); + case C2: return TO_MUX( ADC_CHANNEL_IN12, 0 ); + case C3: return TO_MUX( ADC_CHANNEL_IN13, 0 ); + case C4: return TO_MUX( ADC_CHANNEL_IN14, 0 ); + case C5: return TO_MUX( ADC_CHANNEL_IN15, 0 ); + // STM32F103x[C-G] in 144-pin packages also have analog inputs on F6...F10, but they are on ADC3, and the + // ChibiOS ADC driver for STM32F1xx currently supports only ADC1, therefore these pins are not usable. +#endif + } + + // return an adc that would never be used so intToADCDriver will bail out + return TO_MUX(0, 0xFF); +} +// clang-format on + +static inline ADCDriver* intToADCDriver(uint8_t adcInt) { + switch (adcInt) { +#if STM32_ADC_USE_ADC1 + case 0: + return &ADCD1; +#endif +#if STM32_ADC_USE_ADC2 + case 1: + return &ADCD2; +#endif +#if STM32_ADC_USE_ADC3 + case 2: + return &ADCD3; +#endif +#if STM32_ADC_USE_ADC4 + case 3: + return &ADCD4; +#endif + } + + return NULL; +} + +static inline void manageAdcInitializationDriver(uint8_t adc, ADCDriver* adcDriver) { + if (!adcInitialized[adc]) { + adcStart(adcDriver, &adcCfg); + adcInitialized[adc] = true; + } +} + +int16_t analogReadPin(pin_t pin) { + palSetLineMode(pin, PAL_MODE_INPUT_ANALOG); + + return adc_read(pinToMux(pin)); +} + +int16_t analogReadPinAdc(pin_t pin, uint8_t adc) { + palSetLineMode(pin, PAL_MODE_INPUT_ANALOG); + + adc_mux target = pinToMux(pin); + target.adc = adc; + return adc_read(target); +} + +int16_t adc_read(adc_mux mux) { +#if defined(USE_ADCV1) + // TODO: fix previous assumption of only 1 input... + adcConversionGroup.chselr = 1 << mux.input; /*no macro to convert N to ADC_CHSELR_CHSEL1*/ +#elif defined(USE_ADCV2) + adcConversionGroup.sqr3 = ADC_SQR3_SQ1_N(mux.input); +#else + adcConversionGroup.sqr[0] = ADC_SQR1_SQ1_N(mux.input); +#endif + + ADCDriver* targetDriver = intToADCDriver(mux.adc); + if (!targetDriver) { + return 0; + } + + manageAdcInitializationDriver(mux.adc, targetDriver); + if (adcConvert(targetDriver, &adcConversionGroup, &sampleBuffer[0], ADC_BUFFER_DEPTH) != MSG_OK) { + return 0; + } + +#ifdef USE_ADCV2 + // fake 12-bit -> N-bit scale + return (*sampleBuffer) >> (12 - ADC_RESOLUTION); +#else + // already handled as part of adcConvert + return *sampleBuffer; +#endif +} diff --git a/platforms/chibios/drivers/analog.h b/platforms/chibios/drivers/analog.h new file mode 100644 index 0000000000..e61c394265 --- /dev/null +++ b/platforms/chibios/drivers/analog.h @@ -0,0 +1,41 @@ +/* Copyright 2019 Drew Mills + * + * 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 . + */ + +#pragma once + +#include +#include "quantum.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + uint16_t input; + uint8_t adc; +} adc_mux; +#define TO_MUX(i, a) \ + (adc_mux) { i, a } + +int16_t analogReadPin(pin_t pin); +int16_t analogReadPinAdc(pin_t pin, uint8_t adc); +adc_mux pinToMux(pin_t pin); + +int16_t adc_read(adc_mux mux); + +#ifdef __cplusplus +} +#endif diff --git a/platforms/chibios/drivers/eeprom/eeprom_stm32_L0_L1.c b/platforms/chibios/drivers/eeprom/eeprom_stm32_L0_L1.c new file mode 100644 index 0000000000..ed26cc7145 --- /dev/null +++ b/platforms/chibios/drivers/eeprom/eeprom_stm32_L0_L1.c @@ -0,0 +1,96 @@ +/* Copyright 2020 Nick Brassel (tzarc) + * + * 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 . + */ + +#include +#include + +#include +#include "eeprom_driver.h" +#include "eeprom_stm32_L0_L1.h" + +#define EEPROM_BASE_ADDR 0x08080000 +#define EEPROM_ADDR(offset) (EEPROM_BASE_ADDR + (offset)) +#define EEPROM_PTR(offset) ((__IO uint8_t *)EEPROM_ADDR(offset)) +#define EEPROM_BYTE(location, offset) (*(EEPROM_PTR(((uint32_t)location) + ((uint32_t)offset)))) + +#define BUFFER_BYTE(buffer, offset) (*(((uint8_t *)buffer) + offset)) + +#define FLASH_PEKEY1 0x89ABCDEF +#define FLASH_PEKEY2 0x02030405 + +static inline void STM32_L0_L1_EEPROM_WaitNotBusy(void) { + while (FLASH->SR & FLASH_SR_BSY) { + __WFI(); + } +} + +static inline void STM32_L0_L1_EEPROM_Unlock(void) { + STM32_L0_L1_EEPROM_WaitNotBusy(); + if (FLASH->PECR & FLASH_PECR_PELOCK) { + FLASH->PEKEYR = FLASH_PEKEY1; + FLASH->PEKEYR = FLASH_PEKEY2; + } +} + +static inline void STM32_L0_L1_EEPROM_Lock(void) { + STM32_L0_L1_EEPROM_WaitNotBusy(); + FLASH->PECR |= FLASH_PECR_PELOCK; +} + +void eeprom_driver_init(void) {} + +void eeprom_driver_erase(void) { + STM32_L0_L1_EEPROM_Unlock(); + + for (size_t offset = 0; offset < STM32_ONBOARD_EEPROM_SIZE; offset += sizeof(uint32_t)) { + FLASH->PECR |= FLASH_PECR_ERASE | FLASH_PECR_DATA; + + *(__IO uint32_t *)EEPROM_ADDR(offset) = (uint32_t)0; + + STM32_L0_L1_EEPROM_WaitNotBusy(); + FLASH->PECR &= ~(FLASH_PECR_ERASE | FLASH_PECR_DATA); + } + + STM32_L0_L1_EEPROM_Lock(); +} + +void eeprom_read_block(void *buf, const void *addr, size_t len) { + for (size_t offset = 0; offset < len; ++offset) { + // Drop out if we've hit the limit of the EEPROM + if ((((uint32_t)addr) + offset) >= STM32_ONBOARD_EEPROM_SIZE) { + break; + } + + STM32_L0_L1_EEPROM_WaitNotBusy(); + BUFFER_BYTE(buf, offset) = EEPROM_BYTE(addr, offset); + } +} + +void eeprom_write_block(const void *buf, void *addr, size_t len) { + STM32_L0_L1_EEPROM_Unlock(); + + for (size_t offset = 0; offset < len; ++offset) { + // Drop out if we've hit the limit of the EEPROM + if ((((uint32_t)addr) + offset) >= STM32_ONBOARD_EEPROM_SIZE) { + break; + } + + STM32_L0_L1_EEPROM_WaitNotBusy(); + EEPROM_BYTE(addr, offset) = BUFFER_BYTE(buf, offset); + } + + STM32_L0_L1_EEPROM_Lock(); +} diff --git a/platforms/chibios/drivers/eeprom/eeprom_stm32_L0_L1.h b/platforms/chibios/drivers/eeprom/eeprom_stm32_L0_L1.h new file mode 100644 index 0000000000..a35defca8b --- /dev/null +++ b/platforms/chibios/drivers/eeprom/eeprom_stm32_L0_L1.h @@ -0,0 +1,33 @@ +/* Copyright 2020 Nick Brassel (tzarc) + * + * 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 . + */ + +#pragma once + +/* + The size used by the STM32 L0/L1 EEPROM driver. +*/ +#ifndef STM32_ONBOARD_EEPROM_SIZE +# ifdef VIA_ENABLE +# define STM32_ONBOARD_EEPROM_SIZE 1024 +# else +# include "eeconfig.h" +# define STM32_ONBOARD_EEPROM_SIZE (((EECONFIG_SIZE + 3) / 4) * 4) // based off eeconfig's current usage, aligned to 4-byte sizes, to deal with LTO and EEPROM page sizing +# endif +#endif + +#if STM32_ONBOARD_EEPROM_SIZE > 128 +# pragma message("Please note: resetting EEPROM using an STM32L0/L1 device takes up to 1 second for every 1kB of internal EEPROM used.") +#endif diff --git a/platforms/chibios/drivers/i2c_master.c b/platforms/chibios/drivers/i2c_master.c new file mode 100644 index 0000000000..fc4bb2ab37 --- /dev/null +++ b/platforms/chibios/drivers/i2c_master.c @@ -0,0 +1,121 @@ +/* Copyright 2018 Jack Humbert + * Copyright 2018 Yiancar + * + * 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 . + */ + +/* This library is only valid for STM32 processors. + * This library follows the convention of the AVR i2c_master library. + * As a result addresses are expected to be already shifted (addr << 1). + * I2CD1 is the default driver which corresponds to pins B6 and B7. This + * can be changed. + * Please ensure that HAL_USE_I2C is TRUE in the halconf.h file and that + * STM32_I2C_USE_I2C1 is TRUE in the mcuconf.h file. Pins B6 and B7 are used + * but using any other I2C pins should be trivial. + */ +#include "quantum.h" +#include "i2c_master.h" +#include +#include + +static uint8_t i2c_address; + +static const I2CConfig i2cconfig = { +#if defined(USE_I2CV1_CONTRIB) + I2C1_CLOCK_SPEED, +#elif defined(USE_I2CV1) + I2C1_OPMODE, + I2C1_CLOCK_SPEED, + I2C1_DUTY_CYCLE, +#else + // This configures the I2C clock to 400khz assuming a 72Mhz clock + // For more info : https://www.st.com/en/embedded-software/stsw-stm32126.html + STM32_TIMINGR_PRESC(I2C1_TIMINGR_PRESC) | STM32_TIMINGR_SCLDEL(I2C1_TIMINGR_SCLDEL) | STM32_TIMINGR_SDADEL(I2C1_TIMINGR_SDADEL) | STM32_TIMINGR_SCLH(I2C1_TIMINGR_SCLH) | STM32_TIMINGR_SCLL(I2C1_TIMINGR_SCLL), 0, 0 +#endif +}; + +static i2c_status_t chibios_to_qmk(const msg_t* status) { + switch (*status) { + case I2C_NO_ERROR: + return I2C_STATUS_SUCCESS; + case I2C_TIMEOUT: + return I2C_STATUS_TIMEOUT; + // I2C_BUS_ERROR, I2C_ARBITRATION_LOST, I2C_ACK_FAILURE, I2C_OVERRUN, I2C_PEC_ERROR, I2C_SMB_ALERT + default: + return I2C_STATUS_ERROR; + } +} + +__attribute__((weak)) void i2c_init(void) { + static bool is_initialised = false; + if (!is_initialised) { + is_initialised = true; + + // Try releasing special pins for a short time + palSetPadMode(I2C1_SCL_BANK, I2C1_SCL, PAL_MODE_INPUT); + palSetPadMode(I2C1_SDA_BANK, I2C1_SDA, PAL_MODE_INPUT); + + chThdSleepMilliseconds(10); +#if defined(USE_GPIOV1) + palSetPadMode(I2C1_SCL_BANK, I2C1_SCL, I2C1_SCL_PAL_MODE); + palSetPadMode(I2C1_SDA_BANK, I2C1_SDA, I2C1_SDA_PAL_MODE); +#else + palSetPadMode(I2C1_SCL_BANK, I2C1_SCL, PAL_MODE_ALTERNATE(I2C1_SCL_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN); + palSetPadMode(I2C1_SDA_BANK, I2C1_SDA, PAL_MODE_ALTERNATE(I2C1_SDA_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN); +#endif + } +} + +i2c_status_t i2c_start(uint8_t address) { + i2c_address = address; + i2cStart(&I2C_DRIVER, &i2cconfig); + return I2C_STATUS_SUCCESS; +} + +i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout) { + i2c_address = address; + i2cStart(&I2C_DRIVER, &i2cconfig); + msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), data, length, 0, 0, TIME_MS2I(timeout)); + return chibios_to_qmk(&status); +} + +i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) { + i2c_address = address; + i2cStart(&I2C_DRIVER, &i2cconfig); + msg_t status = i2cMasterReceiveTimeout(&I2C_DRIVER, (i2c_address >> 1), data, length, TIME_MS2I(timeout)); + return chibios_to_qmk(&status); +} + +i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) { + i2c_address = devaddr; + i2cStart(&I2C_DRIVER, &i2cconfig); + + uint8_t complete_packet[length + 1]; + for (uint8_t i = 0; i < length; i++) { + complete_packet[i + 1] = data[i]; + } + complete_packet[0] = regaddr; + + msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), complete_packet, length + 1, 0, 0, TIME_MS2I(timeout)); + return chibios_to_qmk(&status); +} + +i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) { + i2c_address = devaddr; + i2cStart(&I2C_DRIVER, &i2cconfig); + msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), ®addr, 1, data, length, TIME_MS2I(timeout)); + return chibios_to_qmk(&status); +} + +void i2c_stop(void) { i2cStop(&I2C_DRIVER); } diff --git a/platforms/chibios/drivers/i2c_master.h b/platforms/chibios/drivers/i2c_master.h new file mode 100644 index 0000000000..c68109acbd --- /dev/null +++ b/platforms/chibios/drivers/i2c_master.h @@ -0,0 +1,113 @@ +/* Copyright 2018 Jack Humbert + * Copyright 2018 Yiancar + * + * 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 . + */ + +/* This library follows the convention of the AVR i2c_master library. + * As a result addresses are expected to be already shifted (addr << 1). + * I2CD1 is the default driver which corresponds to pins B6 and B7. This + * can be changed. + * Please ensure that HAL_USE_I2C is TRUE in the halconf.h file and that + * STM32_I2C_USE_I2C1 is TRUE in the mcuconf.h file. + */ +#pragma once + +#include +#include + +#ifdef I2C1_BANK +# define I2C1_SCL_BANK I2C1_BANK +# define I2C1_SDA_BANK I2C1_BANK +#endif + +#ifndef I2C1_SCL_BANK +# define I2C1_SCL_BANK GPIOB +#endif + +#ifndef I2C1_SDA_BANK +# define I2C1_SDA_BANK GPIOB +#endif + +#ifndef I2C1_SCL +# define I2C1_SCL 6 +#endif +#ifndef I2C1_SDA +# define I2C1_SDA 7 +#endif + +#ifdef USE_I2CV1 +# ifndef I2C1_OPMODE +# define I2C1_OPMODE OPMODE_I2C +# endif +# ifndef I2C1_CLOCK_SPEED +# define I2C1_CLOCK_SPEED 100000 /* 400000 */ +# endif +# ifndef I2C1_DUTY_CYCLE +# define I2C1_DUTY_CYCLE STD_DUTY_CYCLE /* FAST_DUTY_CYCLE_2 */ +# endif +#else +// The default timing values below configures the I2C clock to 400khz assuming a 72Mhz clock +// For more info : https://www.st.com/en/embedded-software/stsw-stm32126.html +# ifndef I2C1_TIMINGR_PRESC +# define I2C1_TIMINGR_PRESC 0U +# endif +# ifndef I2C1_TIMINGR_SCLDEL +# define I2C1_TIMINGR_SCLDEL 7U +# endif +# ifndef I2C1_TIMINGR_SDADEL +# define I2C1_TIMINGR_SDADEL 0U +# endif +# ifndef I2C1_TIMINGR_SCLH +# define I2C1_TIMINGR_SCLH 38U +# endif +# ifndef I2C1_TIMINGR_SCLL +# define I2C1_TIMINGR_SCLL 129U +# endif +#endif + +#ifndef I2C_DRIVER +# define I2C_DRIVER I2CD1 +#endif + +#ifdef USE_GPIOV1 +# ifndef I2C1_SCL_PAL_MODE +# define I2C1_SCL_PAL_MODE PAL_MODE_STM32_ALTERNATE_OPENDRAIN +# endif +# ifndef I2C1_SDA_PAL_MODE +# define I2C1_SDA_PAL_MODE PAL_MODE_STM32_ALTERNATE_OPENDRAIN +# endif +#else +// The default PAL alternate modes are used to signal that the pins are used for I2C +# ifndef I2C1_SCL_PAL_MODE +# define I2C1_SCL_PAL_MODE 4 +# endif +# ifndef I2C1_SDA_PAL_MODE +# define I2C1_SDA_PAL_MODE 4 +# endif +#endif + +typedef int16_t i2c_status_t; + +#define I2C_STATUS_SUCCESS (0) +#define I2C_STATUS_ERROR (-1) +#define I2C_STATUS_TIMEOUT (-2) + +void i2c_init(void); +i2c_status_t i2c_start(uint8_t address); +i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout); +i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout); +i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout); +i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); +void i2c_stop(void); diff --git a/platforms/chibios/drivers/serial.c b/platforms/chibios/drivers/serial.c new file mode 100644 index 0000000000..f54fbcee4e --- /dev/null +++ b/platforms/chibios/drivers/serial.c @@ -0,0 +1,278 @@ +/* + * WARNING: be careful changing this code, it is very timing dependent + */ + +#include "quantum.h" +#include "serial.h" +#include "wait.h" + +#include + +// TODO: resolve/remove build warnings +#if defined(RGBLIGHT_ENABLE) && defined(RGBLED_SPLIT) && defined(PROTOCOL_CHIBIOS) && defined(WS2812_DRIVER_BITBANG) +# warning "RGBLED_SPLIT not supported with bitbang WS2812 driver" +#endif + +// default wait implementation cannot be called within interrupt +// this method seems to be more accurate than GPT timers +#if PORT_SUPPORTS_RT == FALSE +# error "chSysPolledDelayX method not supported on this platform" +#else +# undef wait_us +# define wait_us(x) chSysPolledDelayX(US2RTC(STM32_SYSCLK, x)) +#endif + +#ifndef SELECT_SOFT_SERIAL_SPEED +# define SELECT_SOFT_SERIAL_SPEED 1 +// TODO: correct speeds... +// 0: about 189kbps (Experimental only) +// 1: about 137kbps (default) +// 2: about 75kbps +// 3: about 39kbps +// 4: about 26kbps +// 5: about 20kbps +#endif + +// Serial pulse period in microseconds. At the moment, going lower than 12 causes communication failure +#if SELECT_SOFT_SERIAL_SPEED == 0 +# define SERIAL_DELAY 12 +#elif SELECT_SOFT_SERIAL_SPEED == 1 +# define SERIAL_DELAY 16 +#elif SELECT_SOFT_SERIAL_SPEED == 2 +# define SERIAL_DELAY 24 +#elif SELECT_SOFT_SERIAL_SPEED == 3 +# define SERIAL_DELAY 32 +#elif SELECT_SOFT_SERIAL_SPEED == 4 +# define SERIAL_DELAY 48 +#elif SELECT_SOFT_SERIAL_SPEED == 5 +# define SERIAL_DELAY 64 +#else +# error invalid SELECT_SOFT_SERIAL_SPEED value +#endif + +inline static void serial_delay(void) { wait_us(SERIAL_DELAY); } +inline static void serial_delay_half(void) { wait_us(SERIAL_DELAY / 2); } +inline static void serial_delay_blip(void) { wait_us(1); } +inline static void serial_output(void) { setPinOutput(SOFT_SERIAL_PIN); } +inline static void serial_input(void) { setPinInputHigh(SOFT_SERIAL_PIN); } +inline static bool serial_read_pin(void) { return !!readPin(SOFT_SERIAL_PIN); } +inline static void serial_low(void) { writePinLow(SOFT_SERIAL_PIN); } +inline static void serial_high(void) { writePinHigh(SOFT_SERIAL_PIN); } + +void interrupt_handler(void *arg); + +// Use thread + palWaitLineTimeout instead of palSetLineCallback +// - Methods like setPinOutput and palEnableLineEvent/palDisableLineEvent +// cause the interrupt to lock up, which would limit to only receiving data... +static THD_WORKING_AREA(waThread1, 128); +static THD_FUNCTION(Thread1, arg) { + (void)arg; + chRegSetThreadName("blinker"); + while (true) { + palWaitLineTimeout(SOFT_SERIAL_PIN, TIME_INFINITE); + interrupt_handler(NULL); + } +} + +void soft_serial_initiator_init(void) { + serial_output(); + serial_high(); +} + +void soft_serial_target_init(void) { + serial_input(); + + palEnablePadEvent(PAL_PORT(SOFT_SERIAL_PIN), PAL_PAD(SOFT_SERIAL_PIN), PAL_EVENT_MODE_FALLING_EDGE); + chThdCreateStatic(waThread1, sizeof(waThread1), HIGHPRIO, Thread1, NULL); +} + +// Used by the master to synchronize timing with the slave. +static void __attribute__((noinline)) sync_recv(void) { + serial_input(); + // This shouldn't hang if the slave disconnects because the + // serial line will float to high if the slave does disconnect. + while (!serial_read_pin()) { + } + + serial_delay(); +} + +// Used by the slave to send a synchronization signal to the master. +static void __attribute__((noinline)) sync_send(void) { + serial_output(); + + serial_low(); + serial_delay(); + + serial_high(); +} + +// Reads a byte from the serial line +static uint8_t __attribute__((noinline)) serial_read_byte(void) { + uint8_t byte = 0; + serial_input(); + for (uint8_t i = 0; i < 8; ++i) { + byte = (byte << 1) | serial_read_pin(); + serial_delay(); + } + + return byte; +} + +// Sends a byte with MSB ordering +static void __attribute__((noinline)) serial_write_byte(uint8_t data) { + uint8_t b = 8; + serial_output(); + while (b--) { + if (data & (1 << b)) { + serial_high(); + } else { + serial_low(); + } + serial_delay(); + } +} + +// interrupt handle to be used by the slave device +void interrupt_handler(void *arg) { + chSysLockFromISR(); + + sync_send(); + + // read mid pulses + serial_delay_blip(); + + uint8_t checksum_computed = 0; + int sstd_index = 0; + + sstd_index = serial_read_byte(); + sync_send(); + + split_transaction_desc_t *trans = &split_transaction_table[sstd_index]; + for (int i = 0; i < trans->initiator2target_buffer_size; ++i) { + split_trans_initiator2target_buffer(trans)[i] = serial_read_byte(); + sync_send(); + checksum_computed += split_trans_initiator2target_buffer(trans)[i]; + } + checksum_computed ^= 7; + uint8_t checksum_received = serial_read_byte(); + sync_send(); + + // wait for the sync to finish sending + serial_delay(); + + // Allow any slave processing to occur + if (trans->slave_callback) { + trans->slave_callback(trans->initiator2target_buffer_size, split_trans_initiator2target_buffer(trans), trans->target2initiator_buffer_size, split_trans_target2initiator_buffer(trans)); + } + + uint8_t checksum = 0; + for (int i = 0; i < trans->target2initiator_buffer_size; ++i) { + serial_write_byte(split_trans_target2initiator_buffer(trans)[i]); + sync_send(); + serial_delay_half(); + checksum += split_trans_target2initiator_buffer(trans)[i]; + } + serial_write_byte(checksum ^ 7); + sync_send(); + + // wait for the sync to finish sending + serial_delay(); + + *trans->status = (checksum_computed == checksum_received) ? TRANSACTION_ACCEPTED : TRANSACTION_DATA_ERROR; + + // end transaction + serial_input(); + + // TODO: remove extra delay between transactions + serial_delay(); + + chSysUnlockFromISR(); +} + +///////// +// start transaction by initiator +// +// int soft_serial_transaction(int sstd_index) +// +// Returns: +// TRANSACTION_END +// TRANSACTION_NO_RESPONSE +// TRANSACTION_DATA_ERROR +// this code is very time dependent, so we need to disable interrupts +int soft_serial_transaction(int sstd_index) { + if (sstd_index > NUM_TOTAL_TRANSACTIONS) return TRANSACTION_TYPE_ERROR; + split_transaction_desc_t *trans = &split_transaction_table[sstd_index]; + if (!trans->status) return TRANSACTION_TYPE_ERROR; // not registered + + // TODO: remove extra delay between transactions + serial_delay(); + + // this code is very time dependent, so we need to disable interrupts + chSysLock(); + + // signal to the slave that we want to start a transaction + serial_output(); + serial_low(); + serial_delay_blip(); + + // wait for the slaves response + serial_input(); + serial_high(); + serial_delay(); + + // check if the slave is present + if (serial_read_pin()) { + // slave failed to pull the line low, assume not present + dprintf("serial::NO_RESPONSE\n"); + chSysUnlock(); + return TRANSACTION_NO_RESPONSE; + } + + // if the slave is present syncronize with it + + uint8_t checksum = 0; + // send data to the slave + serial_write_byte(sstd_index); // first chunk is transaction id + sync_recv(); + + for (int i = 0; i < trans->initiator2target_buffer_size; ++i) { + serial_write_byte(split_trans_initiator2target_buffer(trans)[i]); + sync_recv(); + checksum += split_trans_initiator2target_buffer(trans)[i]; + } + serial_write_byte(checksum ^ 7); + sync_recv(); + + serial_delay(); + serial_delay(); // read mid pulses + + // receive data from the slave + uint8_t checksum_computed = 0; + for (int i = 0; i < trans->target2initiator_buffer_size; ++i) { + split_trans_target2initiator_buffer(trans)[i] = serial_read_byte(); + sync_recv(); + checksum_computed += split_trans_target2initiator_buffer(trans)[i]; + } + checksum_computed ^= 7; + uint8_t checksum_received = serial_read_byte(); + + sync_recv(); + serial_delay(); + + if ((checksum_computed) != (checksum_received)) { + dprintf("serial::FAIL[%u,%u,%u]\n", checksum_computed, checksum_received, sstd_index); + serial_output(); + serial_high(); + + chSysUnlock(); + return TRANSACTION_DATA_ERROR; + } + + // always, release the line when not in use + serial_high(); + serial_output(); + + chSysUnlock(); + return TRANSACTION_END; +} diff --git a/platforms/chibios/drivers/serial_usart.c b/platforms/chibios/drivers/serial_usart.c new file mode 100644 index 0000000000..ea4473791c --- /dev/null +++ b/platforms/chibios/drivers/serial_usart.c @@ -0,0 +1,318 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "serial_usart.h" + +#if defined(SERIAL_USART_CONFIG) +static SerialConfig serial_config = SERIAL_USART_CONFIG; +#else +static SerialConfig serial_config = { + .speed = (SERIAL_USART_SPEED), /* speed - mandatory */ + .cr1 = (SERIAL_USART_CR1), + .cr2 = (SERIAL_USART_CR2), +# if !defined(SERIAL_USART_FULL_DUPLEX) + .cr3 = ((SERIAL_USART_CR3) | USART_CR3_HDSEL) /* activate half-duplex mode */ +# else + .cr3 = (SERIAL_USART_CR3) +# endif +}; +#endif + +static SerialDriver* serial_driver = &SERIAL_USART_DRIVER; + +static inline bool react_to_transactions(void); +static inline bool __attribute__((nonnull)) receive(uint8_t* destination, const size_t size); +static inline bool __attribute__((nonnull)) send(const uint8_t* source, const size_t size); +static inline int initiate_transaction(uint8_t sstd_index); +static inline void usart_clear(void); + +/** + * @brief Clear the receive input queue. + */ +static inline void usart_clear(void) { + osalSysLock(); + bool volatile queue_not_empty = !iqIsEmptyI(&serial_driver->iqueue); + osalSysUnlock(); + + while (queue_not_empty) { + osalSysLock(); + /* Hard reset the input queue. */ + iqResetI(&serial_driver->iqueue); + osalSysUnlock(); + /* Allow pending interrupts to preempt. + * Do not merge the lock/unlock blocks into one + * or the code will not work properly. + * The empty read adds a tiny amount of delay. */ + (void)queue_not_empty; + osalSysLock(); + queue_not_empty = !iqIsEmptyI(&serial_driver->iqueue); + osalSysUnlock(); + } +} + +/** + * @brief Blocking send of buffer with timeout. + * + * @return true Send success. + * @return false Send failed. + */ +static inline bool send(const uint8_t* source, const size_t size) { + bool success = (size_t)sdWriteTimeout(serial_driver, source, size, TIME_MS2I(SERIAL_USART_TIMEOUT)) == size; + +#if !defined(SERIAL_USART_FULL_DUPLEX) + if (success) { + /* Half duplex fills the input queue with the data we wrote - just throw it away. + Under the right circumstances (e.g. bad cables paired with high baud rates) + less bytes can be present in the input queue, therefore a timeout is needed. */ + uint8_t dump[size]; + return receive(dump, size); + } +#endif + + return success; +} + +/** + * @brief Blocking receive of size * bytes with timeout. + * + * @return true Receive success. + * @return false Receive failed. + */ +static inline bool receive(uint8_t* destination, const size_t size) { + bool success = (size_t)sdReadTimeout(serial_driver, destination, size, TIME_MS2I(SERIAL_USART_TIMEOUT)) == size; + return success; +} + +#if !defined(SERIAL_USART_FULL_DUPLEX) + +/** + * @brief Initiate pins for USART peripheral. Half-duplex configuration. + */ +__attribute__((weak)) void usart_init(void) { +# if defined(MCU_STM32) +# if defined(USE_GPIOV1) + palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_STM32_ALTERNATE_OPENDRAIN); +# else + palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_ALTERNATE(SERIAL_USART_TX_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN); +# endif + +# if defined(USART_REMAP) + USART_REMAP; +# endif +# else +# pragma message "usart_init: MCU Familiy not supported by default, please supply your own init code by implementing usart_init() in your keyboard files." +# endif +} + +#else + +/** + * @brief Initiate pins for USART peripheral. Full-duplex configuration. + */ +__attribute__((weak)) void usart_init(void) { +# if defined(MCU_STM32) +# if defined(USE_GPIOV1) + palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_STM32_ALTERNATE_PUSHPULL); + palSetLineMode(SERIAL_USART_RX_PIN, PAL_MODE_INPUT); +# else + palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_ALTERNATE(SERIAL_USART_TX_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); + palSetLineMode(SERIAL_USART_RX_PIN, PAL_MODE_ALTERNATE(SERIAL_USART_RX_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); +# endif + +# if defined(USART_REMAP) + USART_REMAP; +# endif +# else +# pragma message "usart_init: MCU Familiy not supported by default, please supply your own init code by implementing usart_init() in your keyboard files." +# endif +} + +#endif + +/** + * @brief Overridable master specific initializations. + */ +__attribute__((weak, nonnull)) void usart_master_init(SerialDriver** driver) { + (void)driver; + usart_init(); +} + +/** + * @brief Overridable slave specific initializations. + */ +__attribute__((weak, nonnull)) void usart_slave_init(SerialDriver** driver) { + (void)driver; + usart_init(); +} + +/** + * @brief This thread runs on the slave and responds to transactions initiated + * by the master. + */ +static THD_WORKING_AREA(waSlaveThread, 1024); +static THD_FUNCTION(SlaveThread, arg) { + (void)arg; + chRegSetThreadName("usart_tx_rx"); + + while (true) { + if (!react_to_transactions()) { + /* Clear the receive queue, to start with a clean slate. + * Parts of failed transactions or spurious bytes could still be in it. */ + usart_clear(); + } + } +} + +/** + * @brief Slave specific initializations. + */ +void soft_serial_target_init(void) { + usart_slave_init(&serial_driver); + + sdStart(serial_driver, &serial_config); + + /* Start transport thread. */ + chThdCreateStatic(waSlaveThread, sizeof(waSlaveThread), HIGHPRIO, SlaveThread, NULL); +} + +/** + * @brief React to transactions started by the master. + */ +static inline bool react_to_transactions(void) { + /* Wait until there is a transaction for us. */ + uint8_t sstd_index = (uint8_t)sdGet(serial_driver); + + /* Sanity check that we are actually responding to a valid transaction. */ + if (sstd_index >= NUM_TOTAL_TRANSACTIONS) { + return false; + } + + split_transaction_desc_t* trans = &split_transaction_table[sstd_index]; + + /* Send back the handshake which is XORed as a simple checksum, + to signal that the slave is ready to receive possible transaction buffers */ + sstd_index ^= HANDSHAKE_MAGIC; + if (!send(&sstd_index, sizeof(sstd_index))) { + *trans->status = TRANSACTION_DATA_ERROR; + return false; + } + + /* Receive transaction buffer from the master. If this transaction requires it.*/ + if (trans->initiator2target_buffer_size) { + if (!receive(split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size)) { + *trans->status = TRANSACTION_DATA_ERROR; + return false; + } + } + + /* Allow any slave processing to occur. */ + if (trans->slave_callback) { + trans->slave_callback(trans->initiator2target_buffer_size, split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size, split_trans_target2initiator_buffer(trans)); + } + + /* Send transaction buffer to the master. If this transaction requires it. */ + if (trans->target2initiator_buffer_size) { + if (!send(split_trans_target2initiator_buffer(trans), trans->target2initiator_buffer_size)) { + *trans->status = TRANSACTION_DATA_ERROR; + return false; + } + } + + *trans->status = TRANSACTION_ACCEPTED; + return true; +} + +/** + * @brief Master specific initializations. + */ +void soft_serial_initiator_init(void) { + usart_master_init(&serial_driver); + +#if defined(MCU_STM32) && defined(SERIAL_USART_PIN_SWAP) + serial_config.cr2 |= USART_CR2_SWAP; // master has swapped TX/RX pins +#endif + + sdStart(serial_driver, &serial_config); +} + +/** + * @brief Start transaction from the master half to the slave half. + * + * @param index Transaction Table index of the transaction to start. + * @return int TRANSACTION_NO_RESPONSE in case of Timeout. + * TRANSACTION_TYPE_ERROR in case of invalid transaction index. + * TRANSACTION_END in case of success. + */ +int soft_serial_transaction(int index) { + /* Clear the receive queue, to start with a clean slate. + * Parts of failed transactions or spurious bytes could still be in it. */ + usart_clear(); + return initiate_transaction((uint8_t)index); +} + +/** + * @brief Initiate transaction to slave half. + */ +static inline int initiate_transaction(uint8_t sstd_index) { + /* Sanity check that we are actually starting a valid transaction. */ + if (sstd_index >= NUM_TOTAL_TRANSACTIONS) { + dprintln("USART: Illegal transaction Id."); + return TRANSACTION_TYPE_ERROR; + } + + split_transaction_desc_t* trans = &split_transaction_table[sstd_index]; + + /* Transaction is not registered. Abort. */ + if (!trans->status) { + dprintln("USART: Transaction not registered."); + return TRANSACTION_TYPE_ERROR; + } + + /* Send transaction table index to the slave, which doubles as basic handshake token. */ + if (!send(&sstd_index, sizeof(sstd_index))) { + dprintln("USART: Send Handshake failed."); + return TRANSACTION_TYPE_ERROR; + } + + uint8_t sstd_index_shake = 0xFF; + + /* Which we always read back first so that we can error out correctly. + * - due to the half duplex limitations on return codes, we always have to read *something*. + * - without the read, write only transactions *always* succeed, even during the boot process where the slave is not ready. + */ + if (!receive(&sstd_index_shake, sizeof(sstd_index_shake)) || (sstd_index_shake != (sstd_index ^ HANDSHAKE_MAGIC))) { + dprintln("USART: Handshake failed."); + return TRANSACTION_NO_RESPONSE; + } + + /* Send transaction buffer to the slave. If this transaction requires it. */ + if (trans->initiator2target_buffer_size) { + if (!send(split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size)) { + dprintln("USART: Send failed."); + return TRANSACTION_NO_RESPONSE; + } + } + + /* Receive transaction buffer from the slave. If this transaction requires it. */ + if (trans->target2initiator_buffer_size) { + if (!receive(split_trans_target2initiator_buffer(trans), trans->target2initiator_buffer_size)) { + dprintln("USART: Receive failed."); + return TRANSACTION_NO_RESPONSE; + } + } + + return TRANSACTION_END; +} diff --git a/platforms/chibios/drivers/serial_usart.h b/platforms/chibios/drivers/serial_usart.h new file mode 100644 index 0000000000..c64e15566f --- /dev/null +++ b/platforms/chibios/drivers/serial_usart.h @@ -0,0 +1,116 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "quantum.h" +#include "serial.h" +#include "printf.h" + +#include +#include + +#if !defined(SERIAL_USART_DRIVER) +# define SERIAL_USART_DRIVER SD1 +#endif + +#if !defined(USE_GPIOV1) +/* The default PAL alternate modes are used to signal that the pins are used for USART. */ +# if !defined(SERIAL_USART_TX_PAL_MODE) +# define SERIAL_USART_TX_PAL_MODE 7 +# endif +# if !defined(SERIAL_USART_RX_PAL_MODE) +# define SERIAL_USART_RX_PAL_MODE 7 +# endif +#endif + +#if defined(SOFT_SERIAL_PIN) +# define SERIAL_USART_TX_PIN SOFT_SERIAL_PIN +#endif + +#if !defined(SERIAL_USART_TX_PIN) +# define SERIAL_USART_TX_PIN A9 +#endif + +#if !defined(SERIAL_USART_RX_PIN) +# define SERIAL_USART_RX_PIN A10 +#endif + +#if !defined(USART_CR1_M0) +# define USART_CR1_M0 USART_CR1_M // some platforms (f1xx) dont have this so +#endif + +#if !defined(SERIAL_USART_CR1) +# define SERIAL_USART_CR1 (USART_CR1_PCE | USART_CR1_PS | USART_CR1_M0) // parity enable, odd parity, 9 bit length +#endif + +#if !defined(SERIAL_USART_CR2) +# define SERIAL_USART_CR2 (USART_CR2_STOP_1) // 2 stop bits +#endif + +#if !defined(SERIAL_USART_CR3) +# define SERIAL_USART_CR3 0 +#endif + +#if defined(USART1_REMAP) +# define USART_REMAP \ + do { \ + (AFIO->MAPR |= AFIO_MAPR_USART1_REMAP); \ + } while (0) +#elif defined(USART2_REMAP) +# define USART_REMAP \ + do { \ + (AFIO->MAPR |= AFIO_MAPR_USART2_REMAP); \ + } while (0) +#elif defined(USART3_PARTIALREMAP) +# define USART_REMAP \ + do { \ + (AFIO->MAPR |= AFIO_MAPR_USART3_REMAP_PARTIALREMAP); \ + } while (0) +#elif defined(USART3_FULLREMAP) +# define USART_REMAP \ + do { \ + (AFIO->MAPR |= AFIO_MAPR_USART3_REMAP_FULLREMAP); \ + } while (0) +#endif + +#if !defined(SELECT_SOFT_SERIAL_SPEED) +# define SELECT_SOFT_SERIAL_SPEED 1 +#endif + +#if defined(SERIAL_USART_SPEED) +// Allow advanced users to directly set SERIAL_USART_SPEED +#elif SELECT_SOFT_SERIAL_SPEED == 0 +# define SERIAL_USART_SPEED 460800 +#elif SELECT_SOFT_SERIAL_SPEED == 1 +# define SERIAL_USART_SPEED 230400 +#elif SELECT_SOFT_SERIAL_SPEED == 2 +# define SERIAL_USART_SPEED 115200 +#elif SELECT_SOFT_SERIAL_SPEED == 3 +# define SERIAL_USART_SPEED 57600 +#elif SELECT_SOFT_SERIAL_SPEED == 4 +# define SERIAL_USART_SPEED 38400 +#elif SELECT_SOFT_SERIAL_SPEED == 5 +# define SERIAL_USART_SPEED 19200 +#else +# error invalid SELECT_SOFT_SERIAL_SPEED value +#endif + +#if !defined(SERIAL_USART_TIMEOUT) +# define SERIAL_USART_TIMEOUT 100 +#endif + +#define HANDSHAKE_MAGIC 7 diff --git a/platforms/chibios/drivers/spi_master.c b/platforms/chibios/drivers/spi_master.c new file mode 100644 index 0000000000..28ddcbb2ba --- /dev/null +++ b/platforms/chibios/drivers/spi_master.c @@ -0,0 +1,202 @@ +/* Copyright 2020 Nick Brassel (tzarc) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "spi_master.h" + +#include "timer.h" + +static pin_t currentSlavePin = NO_PIN; + +#if defined(K20x) || defined(KL2x) +static SPIConfig spiConfig = {NULL, 0, 0, 0}; +#else +static SPIConfig spiConfig = {false, NULL, 0, 0, 0, 0}; +#endif + +__attribute__((weak)) void spi_init(void) { + static bool is_initialised = false; + if (!is_initialised) { + is_initialised = true; + + // Try releasing special pins for a short time + setPinInput(SPI_SCK_PIN); + setPinInput(SPI_MOSI_PIN); + setPinInput(SPI_MISO_PIN); + + chThdSleepMilliseconds(10); +#if defined(USE_GPIOV1) + palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), SPI_SCK_PAL_MODE); + palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), SPI_MOSI_PAL_MODE); + palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), SPI_MISO_PAL_MODE); +#else + palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), PAL_MODE_ALTERNATE(SPI_SCK_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); + palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), PAL_MODE_ALTERNATE(SPI_MOSI_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); + palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), PAL_MODE_ALTERNATE(SPI_MISO_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); +#endif + } +} + +bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { + if (currentSlavePin != NO_PIN || slavePin == NO_PIN) { + return false; + } + + uint16_t roundedDivisor = 2; + while (roundedDivisor < divisor) { + roundedDivisor <<= 1; + } + + if (roundedDivisor < 2 || roundedDivisor > 256) { + return false; + } + +#if defined(K20x) || defined(KL2x) + spiConfig.tar0 = SPIx_CTARn_FMSZ(7) | SPIx_CTARn_ASC(1); + + if (lsbFirst) { + spiConfig.tar0 |= SPIx_CTARn_LSBFE; + } + + switch (mode) { + case 0: + break; + case 1: + spiConfig.tar0 |= SPIx_CTARn_CPHA; + break; + case 2: + spiConfig.tar0 |= SPIx_CTARn_CPOL; + break; + case 3: + spiConfig.tar0 |= SPIx_CTARn_CPHA | SPIx_CTARn_CPOL; + break; + } + + switch (roundedDivisor) { + case 2: + spiConfig.tar0 |= SPIx_CTARn_BR(0); + break; + case 4: + spiConfig.tar0 |= SPIx_CTARn_BR(1); + break; + case 8: + spiConfig.tar0 |= SPIx_CTARn_BR(3); + break; + case 16: + spiConfig.tar0 |= SPIx_CTARn_BR(4); + break; + case 32: + spiConfig.tar0 |= SPIx_CTARn_BR(5); + break; + case 64: + spiConfig.tar0 |= SPIx_CTARn_BR(6); + break; + case 128: + spiConfig.tar0 |= SPIx_CTARn_BR(7); + break; + case 256: + spiConfig.tar0 |= SPIx_CTARn_BR(8); + break; + } +#else + spiConfig.cr1 = 0; + + if (lsbFirst) { + spiConfig.cr1 |= SPI_CR1_LSBFIRST; + } + + switch (mode) { + case 0: + break; + case 1: + spiConfig.cr1 |= SPI_CR1_CPHA; + break; + case 2: + spiConfig.cr1 |= SPI_CR1_CPOL; + break; + case 3: + spiConfig.cr1 |= SPI_CR1_CPHA | SPI_CR1_CPOL; + break; + } + + switch (roundedDivisor) { + case 2: + break; + case 4: + spiConfig.cr1 |= SPI_CR1_BR_0; + break; + case 8: + spiConfig.cr1 |= SPI_CR1_BR_1; + break; + case 16: + spiConfig.cr1 |= SPI_CR1_BR_1 | SPI_CR1_BR_0; + break; + case 32: + spiConfig.cr1 |= SPI_CR1_BR_2; + break; + case 64: + spiConfig.cr1 |= SPI_CR1_BR_2 | SPI_CR1_BR_0; + break; + case 128: + spiConfig.cr1 |= SPI_CR1_BR_2 | SPI_CR1_BR_1; + break; + case 256: + spiConfig.cr1 |= SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_BR_0; + break; + } +#endif + + currentSlavePin = slavePin; + spiConfig.ssport = PAL_PORT(slavePin); + spiConfig.sspad = PAL_PAD(slavePin); + + setPinOutput(slavePin); + spiStart(&SPI_DRIVER, &spiConfig); + spiSelect(&SPI_DRIVER); + + return true; +} + +spi_status_t spi_write(uint8_t data) { + uint8_t rxData; + spiExchange(&SPI_DRIVER, 1, &data, &rxData); + + return rxData; +} + +spi_status_t spi_read(void) { + uint8_t data = 0; + spiReceive(&SPI_DRIVER, 1, &data); + + return data; +} + +spi_status_t spi_transmit(const uint8_t *data, uint16_t length) { + spiSend(&SPI_DRIVER, length, data); + return SPI_STATUS_SUCCESS; +} + +spi_status_t spi_receive(uint8_t *data, uint16_t length) { + spiReceive(&SPI_DRIVER, length, data); + return SPI_STATUS_SUCCESS; +} + +void spi_stop(void) { + if (currentSlavePin != NO_PIN) { + spiUnselect(&SPI_DRIVER); + spiStop(&SPI_DRIVER); + currentSlavePin = NO_PIN; + } +} diff --git a/platforms/chibios/drivers/spi_master.h b/platforms/chibios/drivers/spi_master.h new file mode 100644 index 0000000000..b5a6ef1437 --- /dev/null +++ b/platforms/chibios/drivers/spi_master.h @@ -0,0 +1,93 @@ +/* Copyright 2020 Nick Brassel (tzarc) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#include +#include + +#include "gpio.h" +#include "chibios_config.h" + +#ifndef SPI_DRIVER +# define SPI_DRIVER SPID2 +#endif + +#ifndef SPI_SCK_PIN +# define SPI_SCK_PIN B13 +#endif + +#ifndef SPI_SCK_PAL_MODE +# if defined(USE_GPIOV1) +# define SPI_SCK_PAL_MODE PAL_MODE_STM32_ALTERNATE_PUSHPULL +# else +# define SPI_SCK_PAL_MODE 5 +# endif +#endif + +#ifndef SPI_MOSI_PIN +# define SPI_MOSI_PIN B15 +#endif + +#ifndef SPI_MOSI_PAL_MODE +# if defined(USE_GPIOV1) +# define SPI_MOSI_PAL_MODE PAL_MODE_STM32_ALTERNATE_PUSHPULL +# else +# define SPI_MOSI_PAL_MODE 5 +# endif +#endif + +#ifndef SPI_MISO_PIN +# define SPI_MISO_PIN B14 +#endif + +#ifndef SPI_MISO_PAL_MODE +# if defined(USE_GPIOV1) +# define SPI_MISO_PAL_MODE PAL_MODE_STM32_ALTERNATE_PUSHPULL +# else +# define SPI_MISO_PAL_MODE 5 +# endif +#endif + +typedef int16_t spi_status_t; + +#define SPI_STATUS_SUCCESS (0) +#define SPI_STATUS_ERROR (-1) +#define SPI_STATUS_TIMEOUT (-2) + +#define SPI_TIMEOUT_IMMEDIATE (0) +#define SPI_TIMEOUT_INFINITE (0xFFFF) + +#ifdef __cplusplus +extern "C" { +#endif +void spi_init(void); + +bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor); + +spi_status_t spi_write(uint8_t data); + +spi_status_t spi_read(void); + +spi_status_t spi_transmit(const uint8_t *data, uint16_t length); + +spi_status_t spi_receive(uint8_t *data, uint16_t length); + +void spi_stop(void); +#ifdef __cplusplus +} +#endif diff --git a/platforms/chibios/drivers/uart.c b/platforms/chibios/drivers/uart.c new file mode 100644 index 0000000000..030335b342 --- /dev/null +++ b/platforms/chibios/drivers/uart.c @@ -0,0 +1,50 @@ +/* Copyright 2021 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "uart.h" + +#include "quantum.h" + +static SerialConfig serialConfig = {SERIAL_DEFAULT_BITRATE, SD1_CR1, SD1_CR2, SD1_CR3}; + +void uart_init(uint32_t baud) { + static bool is_initialised = false; + + if (!is_initialised) { + is_initialised = true; + + serialConfig.speed = baud; + +#if defined(USE_GPIOV1) + palSetLineMode(SD1_TX_PIN, PAL_MODE_STM32_ALTERNATE_OPENDRAIN); + palSetLineMode(SD1_RX_PIN, PAL_MODE_STM32_ALTERNATE_OPENDRAIN); +#else + palSetLineMode(SD1_TX_PIN, PAL_MODE_ALTERNATE(SD1_TX_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN); + palSetLineMode(SD1_RX_PIN, PAL_MODE_ALTERNATE(SD1_RX_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN); +#endif + sdStart(&SERIAL_DRIVER, &serialConfig); + } +} + +void uart_putchar(uint8_t c) { sdPut(&SERIAL_DRIVER, c); } + +uint8_t uart_getchar(void) { + msg_t res = sdGet(&SERIAL_DRIVER); + + return (uint8_t)res; +} + +bool uart_available(void) { return !sdGetWouldBlock(&SERIAL_DRIVER); } diff --git a/platforms/chibios/drivers/uart.h b/platforms/chibios/drivers/uart.h new file mode 100644 index 0000000000..b4e20e9fd3 --- /dev/null +++ b/platforms/chibios/drivers/uart.h @@ -0,0 +1,77 @@ +/* Copyright 2021 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include + +#include + +#ifndef SERIAL_DRIVER +# define SERIAL_DRIVER SD1 +#endif + +#ifndef SD1_TX_PIN +# define SD1_TX_PIN A9 +#endif + +#ifndef SD1_TX_PAL_MODE +# define SD1_TX_PAL_MODE 7 +#endif + +#ifndef SD1_RX_PIN +# define SD1_RX_PIN A10 +#endif + +#ifndef SD1_RX_PAL_MODE +# define SD1_RX_PAL_MODE 7 +#endif + +#ifndef SD1_CTS_PIN +# define SD1_CTS_PIN A11 +#endif + +#ifndef SD1_CTS_PAL_MODE +# define SD1_CTS_PAL_MODE 7 +#endif + +#ifndef SD1_RTS_PIN +# define SD1_RTS_PIN A12 +#endif + +#ifndef SD1_RTS_PAL_MODE +# define SD1_RTS_PAL_MODE 7 +#endif + +#ifndef SD1_CR1 +# define SD1_CR1 0 +#endif + +#ifndef SD1_CR2 +# define SD1_CR2 0 +#endif + +#ifndef SD1_CR3 +# define SD1_CR3 0 +#endif + +void uart_init(uint32_t baud); + +void uart_putchar(uint8_t c); + +uint8_t uart_getchar(void); + +bool uart_available(void); diff --git a/platforms/chibios/drivers/usbpd_stm32g4.c b/platforms/chibios/drivers/usbpd_stm32g4.c new file mode 100644 index 0000000000..f16ca8aeae --- /dev/null +++ b/platforms/chibios/drivers/usbpd_stm32g4.c @@ -0,0 +1,76 @@ +/* Copyright 2021 Nick Brassel (@tzarc) + * + * 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 . + */ + +#include + +#ifndef USBPD_UCPD1_CFG1 +# define USBPD_UCPD1_CFG1 (UCPD_CFG1_PSC_UCPDCLK_0 | UCPD_CFG1_TRANSWIN_3 | UCPD_CFG1_IFRGAP_4 | UCPD_CFG1_HBITCLKDIV_4) +#endif // USBPD_UCPD1_CFG1 + +// Initialises the USBPD subsystem +__attribute__((weak)) void usbpd_init(void) { + // Disable dead-battery signals + PWR->CR3 |= PWR_CR3_UCPD_DBDIS; + // Enable the clock for the UCPD1 peripheral + RCC->APB1ENR2 |= RCC_APB1ENR2_UCPD1EN; + + // Copy the existing value + uint32_t CFG1 = UCPD1->CFG1; + // Force-disable UCPD1 before configuring + CFG1 &= ~UCPD_CFG1_UCPDEN; + // Configure UCPD1 + CFG1 = USBPD_UCPD1_CFG1; + // Apply the changes + UCPD1->CFG1 = CFG1; + // Enable UCPD1 + UCPD1->CFG1 |= UCPD_CFG1_UCPDEN; + + // Copy the existing value + uint32_t CR = UCPD1->CR; + // Clear out ANASUBMODE (irrelevant as a sink device) + CR &= ~UCPD_CR_ANASUBMODE_Msk; + // Advertise our capabilities as a sink, with both CC lines enabled + CR |= UCPD_CR_ANAMODE | UCPD_CR_CCENABLE_Msk; + // Apply the changes + UCPD1->CR = CR; +} + +// Gets the current state of the USBPD allowance +__attribute__((weak)) usbpd_allowance_t usbpd_get_allowance(void) { + uint32_t CR = UCPD1->CR; + + int ucpd_enabled = (UCPD1->CFG1 & UCPD_CFG1_UCPDEN_Msk) >> UCPD_CFG1_UCPDEN_Pos; + int anamode = (CR & UCPD_CR_ANAMODE_Msk) >> UCPD_CR_ANAMODE_Pos; + int cc_enabled = (CR & UCPD_CR_CCENABLE_Msk) >> UCPD_CR_CCENABLE_Pos; + + if (ucpd_enabled && anamode && cc_enabled) { + uint32_t SR = UCPD1->SR; + int vstate_cc1 = (SR & UCPD_SR_TYPEC_VSTATE_CC1_Msk) >> UCPD_SR_TYPEC_VSTATE_CC1_Pos; + int vstate_cc2 = (SR & UCPD_SR_TYPEC_VSTATE_CC2_Msk) >> UCPD_SR_TYPEC_VSTATE_CC2_Pos; + int vstate_max = vstate_cc1 > vstate_cc2 ? vstate_cc1 : vstate_cc2; + switch (vstate_max) { + case 0: + case 1: + return USBPD_500MA; // Note that this is 500mA (i.e. max USB 2.0), not 900mA, as we're not using USB 3.1 as a sink device. + case 2: + return USBPD_1500MA; + case 3: + return USBPD_3000MA; + } + } + + return USBPD_500MA; +} \ No newline at end of file diff --git a/platforms/chibios/drivers/ws2812.c b/platforms/chibios/drivers/ws2812.c new file mode 100644 index 0000000000..0d12e2fb79 --- /dev/null +++ b/platforms/chibios/drivers/ws2812.c @@ -0,0 +1,114 @@ +#include "quantum.h" +#include "ws2812.h" +#include +#include + +/* Adapted from https://github.com/bigjosh/SimpleNeoPixelDemo/ */ + +#ifndef NOP_FUDGE +# if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F3XX) || defined(STM32F4XX) || defined(STM32L0XX) +# define NOP_FUDGE 0.4 +# else +# error("NOP_FUDGE configuration required") +# define NOP_FUDGE 1 // this just pleases the compile so the above error is easier to spot +# endif +#endif + +// Push Pull or Open Drain Configuration +// Default Push Pull +#ifndef WS2812_EXTERNAL_PULLUP +# define WS2812_OUTPUT_MODE PAL_MODE_OUTPUT_PUSHPULL +#else +# define WS2812_OUTPUT_MODE PAL_MODE_OUTPUT_OPENDRAIN +#endif + +#define NUMBER_NOPS 6 +#define CYCLES_PER_SEC (STM32_SYSCLK / NUMBER_NOPS * NOP_FUDGE) +#define NS_PER_SEC (1000000000L) // Note that this has to be SIGNED since we want to be able to check for negative values of derivatives +#define NS_PER_CYCLE (NS_PER_SEC / CYCLES_PER_SEC) +#define NS_TO_CYCLES(n) ((n) / NS_PER_CYCLE) + +#define wait_ns(x) \ + do { \ + for (int i = 0; i < NS_TO_CYCLES(x); i++) { \ + __asm__ volatile("nop\n\t" \ + "nop\n\t" \ + "nop\n\t" \ + "nop\n\t" \ + "nop\n\t" \ + "nop\n\t"); \ + } \ + } while (0) + +// These are the timing constraints taken mostly from the WS2812 datasheets +// These are chosen to be conservative and avoid problems rather than for maximum throughput + +#define T1H 900 // Width of a 1 bit in ns +#define T1L (1250 - T1H) // Width of a 1 bit in ns + +#define T0H 350 // Width of a 0 bit in ns +#define T0L (1250 - T0H) // Width of a 0 bit in ns + +// The reset gap can be 6000 ns, but depending on the LED strip it may have to be increased +// to values like 600000 ns. If it is too small, the pixels will show nothing most of the time. +#define RES (1000 * WS2812_TRST_US) // Width of the low gap between bits to cause a frame to latch + +void sendByte(uint8_t byte) { + // WS2812 protocol wants most significant bits first + for (unsigned char bit = 0; bit < 8; bit++) { + bool is_one = byte & (1 << (7 - bit)); + // using something like wait_ns(is_one ? T1L : T0L) here throws off timings + if (is_one) { + // 1 + writePinHigh(RGB_DI_PIN); + wait_ns(T1H); + writePinLow(RGB_DI_PIN); + wait_ns(T1L); + } else { + // 0 + writePinHigh(RGB_DI_PIN); + wait_ns(T0H); + writePinLow(RGB_DI_PIN); + wait_ns(T0L); + } + } +} + +void ws2812_init(void) { palSetLineMode(RGB_DI_PIN, WS2812_OUTPUT_MODE); } + +// Setleds for standard RGB +void ws2812_setleds(LED_TYPE *ledarray, uint16_t leds) { + static bool s_init = false; + if (!s_init) { + ws2812_init(); + s_init = true; + } + + // this code is very time dependent, so we need to disable interrupts + chSysLock(); + + for (uint8_t i = 0; i < leds; i++) { + // WS2812 protocol dictates grb order +#if (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_GRB) + sendByte(ledarray[i].g); + sendByte(ledarray[i].r); + sendByte(ledarray[i].b); +#elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_RGB) + sendByte(ledarray[i].r); + sendByte(ledarray[i].g); + sendByte(ledarray[i].b); +#elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_BGR) + sendByte(ledarray[i].b); + sendByte(ledarray[i].g); + sendByte(ledarray[i].r); +#endif + +#ifdef RGBW + sendByte(ledarray[i].w); +#endif + } + + wait_ns(RES); + + chSysUnlock(); +} diff --git a/platforms/chibios/drivers/ws2812_pwm.c b/platforms/chibios/drivers/ws2812_pwm.c new file mode 100644 index 0000000000..e6af55b6b3 --- /dev/null +++ b/platforms/chibios/drivers/ws2812_pwm.c @@ -0,0 +1,311 @@ +#include "ws2812.h" +#include "quantum.h" +#include + +/* Adapted from https://github.com/joewa/WS2812-LED-Driver_ChibiOS/ */ + +#ifdef RGBW +# error "RGBW not supported" +#endif + +#ifndef WS2812_PWM_DRIVER +# define WS2812_PWM_DRIVER PWMD2 // TIMx +#endif +#ifndef WS2812_PWM_CHANNEL +# define WS2812_PWM_CHANNEL 2 // Channel +#endif +#ifndef WS2812_PWM_PAL_MODE +# define WS2812_PWM_PAL_MODE 2 // DI Pin's alternate function value +#endif +#ifndef WS2812_DMA_STREAM +# define WS2812_DMA_STREAM STM32_DMA1_STREAM2 // DMA Stream for TIMx_UP +#endif +#ifndef WS2812_DMA_CHANNEL +# define WS2812_DMA_CHANNEL 2 // DMA Channel for TIMx_UP +#endif +#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) && !defined(WS2812_DMAMUX_ID) +# error "please consult your MCU's datasheet and specify in your config.h: #define WS2812_DMAMUX_ID STM32_DMAMUX1_TIM?_UP" +#endif + +#ifndef WS2812_PWM_COMPLEMENTARY_OUTPUT +# define WS2812_PWM_OUTPUT_MODE PWM_OUTPUT_ACTIVE_HIGH +#else +# if !STM32_PWM_USE_ADVANCED +# error "WS2812_PWM_COMPLEMENTARY_OUTPUT requires STM32_PWM_USE_ADVANCED == TRUE" +# endif +# define WS2812_PWM_OUTPUT_MODE PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH +#endif + +// Push Pull or Open Drain Configuration +// Default Push Pull +#ifndef WS2812_EXTERNAL_PULLUP +# if defined(USE_GPIOV1) +# define WS2812_OUTPUT_MODE PAL_MODE_STM32_ALTERNATE_PUSHPULL +# else +# define WS2812_OUTPUT_MODE PAL_MODE_ALTERNATE(WS2812_PWM_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST | PAL_STM32_PUPDR_FLOATING +# endif +#else +# if defined(USE_GPIOV1) +# define WS2812_OUTPUT_MODE PAL_MODE_STM32_ALTERNATE_OPENDRAIN +# else +# define WS2812_OUTPUT_MODE PAL_MODE_ALTERNATE(WS2812_PWM_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_OSPEED_HIGHEST | PAL_STM32_PUPDR_FLOATING +# endif +#endif + +#ifndef WS2812_PWM_TARGET_PERIOD +//# define WS2812_PWM_TARGET_PERIOD 800000 // Original code is 800k...? +# define WS2812_PWM_TARGET_PERIOD 80000 // TODO: work out why 10x less on f303/f4x1 +#endif + +/* --- PRIVATE CONSTANTS ---------------------------------------------------- */ + +#define WS2812_PWM_FREQUENCY (STM32_SYSCLK / 2) /**< Clock frequency of PWM, must be valid with respect to system clock! */ +#define WS2812_PWM_PERIOD (WS2812_PWM_FREQUENCY / WS2812_PWM_TARGET_PERIOD) /**< Clock period in ticks. 1 / 800kHz = 1.25 uS (as per datasheet) */ + +/** + * @brief Number of bit-periods to hold the data line low at the end of a frame + * + * The reset period for each frame is defined in WS2812_TRST_US. + * Calculate the number of zeroes to add at the end assuming 1.25 uS/bit: + */ +#define WS2812_RESET_BIT_N (1000 * WS2812_TRST_US / 1250) +#define WS2812_COLOR_BIT_N (RGBLED_NUM * 24) /**< Number of data bits */ +#define WS2812_BIT_N (WS2812_COLOR_BIT_N + WS2812_RESET_BIT_N) /**< Total number of bits in a frame */ + +/** + * @brief High period for a zero, in ticks + * + * Per the datasheet: + * WS2812: + * - T0H: 200 nS to 500 nS, inclusive + * - T0L: 650 nS to 950 nS, inclusive + * WS2812B: + * - T0H: 200 nS to 500 nS, inclusive + * - T0L: 750 nS to 1050 nS, inclusive + * + * The duty cycle is calculated for a high period of 350 nS. + */ +#define WS2812_DUTYCYCLE_0 (WS2812_PWM_FREQUENCY / (1000000000 / 350)) + +/** + * @brief High period for a one, in ticks + * + * Per the datasheet: + * WS2812: + * - T1H: 550 nS to 850 nS, inclusive + * - T1L: 450 nS to 750 nS, inclusive + * WS2812B: + * - T1H: 750 nS to 1050 nS, inclusive + * - T1L: 200 nS to 500 nS, inclusive + * + * The duty cycle is calculated for a high period of 800 nS. + * This is in the middle of the specifications of the WS2812 and WS2812B. + */ +#define WS2812_DUTYCYCLE_1 (WS2812_PWM_FREQUENCY / (1000000000 / 800)) + +/* --- PRIVATE MACROS ------------------------------------------------------- */ + +/** + * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given bit + * + * @param[in] led: The led index [0, @ref RGBLED_NUM) + * @param[in] byte: The byte number [0, 2] + * @param[in] bit: The bit number [0, 7] + * + * @return The bit index + */ +#define WS2812_BIT(led, byte, bit) (24 * (led) + 8 * (byte) + (7 - (bit))) + +#if (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_GRB) +/** + * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given red bit + * + * @note The red byte is the middle byte in the color packet + * + * @param[in] led: The led index [0, @ref RGBLED_NUM) + * @param[in] bit: The bit number [0, 7] + * + * @return The bit index + */ +# define WS2812_RED_BIT(led, bit) WS2812_BIT((led), 1, (bit)) + +/** + * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given green bit + * + * @note The red byte is the first byte in the color packet + * + * @param[in] led: The led index [0, @ref RGBLED_NUM) + * @param[in] bit: The bit number [0, 7] + * + * @return The bit index + */ +# define WS2812_GREEN_BIT(led, bit) WS2812_BIT((led), 0, (bit)) + +/** + * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given blue bit + * + * @note The red byte is the last byte in the color packet + * + * @param[in] led: The led index [0, @ref RGBLED_NUM) + * @param[in] bit: The bit index [0, 7] + * + * @return The bit index + */ +# define WS2812_BLUE_BIT(led, bit) WS2812_BIT((led), 2, (bit)) + +#elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_RGB) +/** + * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given red bit + * + * @note The red byte is the middle byte in the color packet + * + * @param[in] led: The led index [0, @ref RGBLED_NUM) + * @param[in] bit: The bit number [0, 7] + * + * @return The bit index + */ +# define WS2812_RED_BIT(led, bit) WS2812_BIT((led), 0, (bit)) + +/** + * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given green bit + * + * @note The red byte is the first byte in the color packet + * + * @param[in] led: The led index [0, @ref RGBLED_NUM) + * @param[in] bit: The bit number [0, 7] + * + * @return The bit index + */ +# define WS2812_GREEN_BIT(led, bit) WS2812_BIT((led), 1, (bit)) + +/** + * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given blue bit + * + * @note The red byte is the last byte in the color packet + * + * @param[in] led: The led index [0, @ref RGBLED_NUM) + * @param[in] bit: The bit index [0, 7] + * + * @return The bit index + */ +# define WS2812_BLUE_BIT(led, bit) WS2812_BIT((led), 2, (bit)) + +#elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_BGR) +/** + * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given red bit + * + * @note The red byte is the middle byte in the color packet + * + * @param[in] led: The led index [0, @ref RGBLED_NUM) + * @param[in] bit: The bit number [0, 7] + * + * @return The bit index + */ +# define WS2812_RED_BIT(led, bit) WS2812_BIT((led), 2, (bit)) + +/** + * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given green bit + * + * @note The red byte is the first byte in the color packet + * + * @param[in] led: The led index [0, @ref RGBLED_NUM) + * @param[in] bit: The bit number [0, 7] + * + * @return The bit index + */ +# define WS2812_GREEN_BIT(led, bit) WS2812_BIT((led), 1, (bit)) + +/** + * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given blue bit + * + * @note The red byte is the last byte in the color packet + * + * @param[in] led: The led index [0, @ref RGBLED_NUM) + * @param[in] bit: The bit index [0, 7] + * + * @return The bit index + */ +# define WS2812_BLUE_BIT(led, bit) WS2812_BIT((led), 0, (bit)) +#endif + +/* --- PRIVATE VARIABLES ---------------------------------------------------- */ + +static uint32_t ws2812_frame_buffer[WS2812_BIT_N + 1]; /**< Buffer for a frame */ + +/* --- PUBLIC FUNCTIONS ----------------------------------------------------- */ +/* + * Gedanke: Double-buffer type transactions: double buffer transfers using two memory pointers for +the memory (while the DMA is reading/writing from/to a buffer, the application can +write/read to/from the other buffer). + */ + +void ws2812_init(void) { + // Initialize led frame buffer + uint32_t i; + for (i = 0; i < WS2812_COLOR_BIT_N; i++) ws2812_frame_buffer[i] = WS2812_DUTYCYCLE_0; // All color bits are zero duty cycle + for (i = 0; i < WS2812_RESET_BIT_N; i++) ws2812_frame_buffer[i + WS2812_COLOR_BIT_N] = 0; // All reset bits are zero + + palSetLineMode(RGB_DI_PIN, WS2812_OUTPUT_MODE); + + // PWM Configuration + //#pragma GCC diagnostic ignored "-Woverride-init" // Turn off override-init warning for this struct. We use the overriding ability to set a "default" channel config + static const PWMConfig ws2812_pwm_config = { + .frequency = WS2812_PWM_FREQUENCY, + .period = WS2812_PWM_PERIOD, // Mit dieser Periode wird UDE-Event erzeugt und ein neuer Wert (Länge WS2812_BIT_N) vom DMA ins CCR geschrieben + .callback = NULL, + .channels = + { + [0 ... 3] = {.mode = PWM_OUTPUT_DISABLED, .callback = NULL}, // Channels default to disabled + [WS2812_PWM_CHANNEL - 1] = {.mode = WS2812_PWM_OUTPUT_MODE, .callback = NULL}, // Turn on the channel we care about + }, + .cr2 = 0, + .dier = TIM_DIER_UDE, // DMA on update event for next period + }; + //#pragma GCC diagnostic pop // Restore command-line warning options + + // Configure DMA + // dmaInit(); // Joe added this + dmaStreamAlloc(WS2812_DMA_STREAM - STM32_DMA_STREAM(0), 10, NULL, NULL); + dmaStreamSetPeripheral(WS2812_DMA_STREAM, &(WS2812_PWM_DRIVER.tim->CCR[WS2812_PWM_CHANNEL - 1])); // Ziel ist der An-Zeit im Cap-Comp-Register + dmaStreamSetMemory0(WS2812_DMA_STREAM, ws2812_frame_buffer); + dmaStreamSetTransactionSize(WS2812_DMA_STREAM, WS2812_BIT_N); + dmaStreamSetMode(WS2812_DMA_STREAM, STM32_DMA_CR_CHSEL(WS2812_DMA_CHANNEL) | STM32_DMA_CR_DIR_M2P | STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC | STM32_DMA_CR_PL(3)); + // M2P: Memory 2 Periph; PL: Priority Level + +#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) + // If the MCU has a DMAMUX we need to assign the correct resource + dmaSetRequestSource(WS2812_DMA_STREAM, WS2812_DMAMUX_ID); +#endif + + // Start DMA + dmaStreamEnable(WS2812_DMA_STREAM); + + // Configure PWM + // NOTE: It's required that preload be enabled on the timer channel CCR register. This is currently enabled in the + // ChibiOS driver code, so we don't have to do anything special to the timer. If we did, we'd have to start the timer, + // disable counting, enable the channel, and then make whatever configuration changes we need. + pwmStart(&WS2812_PWM_DRIVER, &ws2812_pwm_config); + pwmEnableChannel(&WS2812_PWM_DRIVER, WS2812_PWM_CHANNEL - 1, 0); // Initial period is 0; output will be low until first duty cycle is DMA'd in +} + +void ws2812_write_led(uint16_t led_number, uint8_t r, uint8_t g, uint8_t b) { + // Write color to frame buffer + for (uint8_t bit = 0; bit < 8; bit++) { + ws2812_frame_buffer[WS2812_RED_BIT(led_number, bit)] = ((r >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0; + ws2812_frame_buffer[WS2812_GREEN_BIT(led_number, bit)] = ((g >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0; + ws2812_frame_buffer[WS2812_BLUE_BIT(led_number, bit)] = ((b >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0; + } +} + +// Setleds for standard RGB +void ws2812_setleds(LED_TYPE* ledarray, uint16_t leds) { + static bool s_init = false; + if (!s_init) { + ws2812_init(); + s_init = true; + } + + for (uint16_t i = 0; i < leds; i++) { + ws2812_write_led(i, ledarray[i].r, ledarray[i].g, ledarray[i].b); + } +} diff --git a/platforms/chibios/drivers/ws2812_spi.c b/platforms/chibios/drivers/ws2812_spi.c new file mode 100644 index 0000000000..377a929b94 --- /dev/null +++ b/platforms/chibios/drivers/ws2812_spi.c @@ -0,0 +1,159 @@ +#include "quantum.h" +#include "ws2812.h" + +/* Adapted from https://github.com/gamazeps/ws2812b-chibios-SPIDMA/ */ + +#ifdef RGBW +# error "RGBW not supported" +#endif + +// Define the spi your LEDs are plugged to here +#ifndef WS2812_SPI +# define WS2812_SPI SPID1 +#endif + +#ifndef WS2812_SPI_MOSI_PAL_MODE +# define WS2812_SPI_MOSI_PAL_MODE 5 +#endif + +#ifndef WS2812_SPI_SCK_PAL_MODE +# define WS2812_SPI_SCK_PAL_MODE 5 +#endif + +// Push Pull or Open Drain Configuration +// Default Push Pull +#ifndef WS2812_EXTERNAL_PULLUP +# if defined(USE_GPIOV1) +# define WS2812_MOSI_OUTPUT_MODE PAL_MODE_STM32_ALTERNATE_PUSHPULL +# else +# define WS2812_MOSI_OUTPUT_MODE PAL_MODE_ALTERNATE(WS2812_SPI_MOSI_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL +# endif +#else +# if defined(USE_GPIOV1) +# define WS2812_MOSI_OUTPUT_MODE PAL_MODE_STM32_ALTERNATE_OPENDRAIN +# else +# define WS2812_MOSI_OUTPUT_MODE PAL_MODE_ALTERNATE(WS2812_SPI_MOSI_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN +# endif +#endif + +// Define SPI config speed +// baudrate should target 3.2MHz +// F072 fpclk = 48MHz +// 48/16 = 3Mhz +#if WS2812_SPI_DIVISOR == 2 +# define WS2812_SPI_DIVISOR (0) +#elif WS2812_SPI_DIVISOR == 4 +# define WS2812_SPI_DIVISOR (SPI_CR1_BR_0) +#elif WS2812_SPI_DIVISOR == 8 +# define WS2812_SPI_DIVISOR (SPI_CR1_BR_1) +#elif WS2812_SPI_DIVISOR == 16 // same as default +# define WS2812_SPI_DIVISOR (SPI_CR1_BR_1 | SPI_CR1_BR_0) +#elif WS2812_SPI_DIVISOR == 32 +# define WS2812_SPI_DIVISOR (SPI_CR1_BR_2) +#elif WS2812_SPI_DIVISOR == 64 +# define WS2812_SPI_DIVISOR (SPI_CR1_BR_2 | SPI_CR1_BR_0) +#elif WS2812_SPI_DIVISOR == 128 +# define WS2812_SPI_DIVISOR (SPI_CR1_BR_2 | SPI_CR1_BR_1) +#elif WS2812_SPI_DIVISOR == 256 +# define WS2812_SPI_DIVISOR (SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_BR_0) +#else +# define WS2812_SPI_DIVISOR (SPI_CR1_BR_1 | SPI_CR1_BR_0) // default +#endif + +// Use SPI circular buffer +#ifdef WS2812_SPI_USE_CIRCULAR_BUFFER +# define WS2812_SPI_BUFFER_MODE 1 // circular buffer +#else +# define WS2812_SPI_BUFFER_MODE 0 // normal buffer +#endif + +#if defined(USE_GPIOV1) +# define WS2812_SCK_OUTPUT_MODE PAL_MODE_STM32_ALTERNATE_PUSHPULL +#else +# define WS2812_SCK_OUTPUT_MODE PAL_MODE_ALTERNATE(WS2812_SPI_SCK_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL +#endif + +#define BYTES_FOR_LED_BYTE 4 +#define NB_COLORS 3 +#define BYTES_FOR_LED (BYTES_FOR_LED_BYTE * NB_COLORS) +#define DATA_SIZE (BYTES_FOR_LED * RGBLED_NUM) +#define RESET_SIZE (1000 * WS2812_TRST_US / (2 * 1250)) +#define PREAMBLE_SIZE 4 + +static uint8_t txbuf[PREAMBLE_SIZE + DATA_SIZE + RESET_SIZE] = {0}; + +/* + * As the trick here is to use the SPI to send a huge pattern of 0 and 1 to + * the ws2812b protocol, we use this helper function to translate bytes into + * 0s and 1s for the LED (with the appropriate timing). + */ +static uint8_t get_protocol_eq(uint8_t data, int pos) { + uint8_t eq = 0; + if (data & (1 << (2 * (3 - pos)))) + eq = 0b1110; + else + eq = 0b1000; + if (data & (2 << (2 * (3 - pos)))) + eq += 0b11100000; + else + eq += 0b10000000; + return eq; +} + +static void set_led_color_rgb(LED_TYPE color, int pos) { + uint8_t* tx_start = &txbuf[PREAMBLE_SIZE]; + +#if (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_GRB) + for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + j] = get_protocol_eq(color.g, j); + for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE + j] = get_protocol_eq(color.r, j); + for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE * 2 + j] = get_protocol_eq(color.b, j); +#elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_RGB) + for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + j] = get_protocol_eq(color.r, j); + for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE + j] = get_protocol_eq(color.g, j); + for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE * 2 + j] = get_protocol_eq(color.b, j); +#elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_BGR) + for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + j] = get_protocol_eq(color.b, j); + for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE + j] = get_protocol_eq(color.g, j); + for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE * 2 + j] = get_protocol_eq(color.r, j); +#endif +} + +void ws2812_init(void) { + palSetLineMode(RGB_DI_PIN, WS2812_MOSI_OUTPUT_MODE); + +#ifdef WS2812_SPI_SCK_PIN + palSetLineMode(WS2812_SPI_SCK_PIN, WS2812_SCK_OUTPUT_MODE); +#endif // WS2812_SPI_SCK_PIN + + // TODO: more dynamic baudrate + static const SPIConfig spicfg = {WS2812_SPI_BUFFER_MODE, NULL, PAL_PORT(RGB_DI_PIN), PAL_PAD(RGB_DI_PIN), WS2812_SPI_DIVISOR}; + + spiAcquireBus(&WS2812_SPI); /* Acquire ownership of the bus. */ + spiStart(&WS2812_SPI, &spicfg); /* Setup transfer parameters. */ + spiSelect(&WS2812_SPI); /* Slave Select assertion. */ +#ifdef WS2812_SPI_USE_CIRCULAR_BUFFER + spiStartSend(&WS2812_SPI, sizeof(txbuf) / sizeof(txbuf[0]), txbuf); +#endif +} + +void ws2812_setleds(LED_TYPE* ledarray, uint16_t leds) { + static bool s_init = false; + if (!s_init) { + ws2812_init(); + s_init = true; + } + + for (uint8_t i = 0; i < leds; i++) { + set_led_color_rgb(ledarray[i], i); + } + + // Send async - each led takes ~0.03ms, 50 leds ~1.5ms, animations flushing faster than send will cause issues. + // Instead spiSend can be used to send synchronously (or the thread logic can be added back). +#ifndef WS2812_SPI_USE_CIRCULAR_BUFFER +# ifdef WS2812_SPI_SYNC + spiSend(&WS2812_SPI, sizeof(txbuf) / sizeof(txbuf[0]), txbuf); +# else + spiStartSend(&WS2812_SPI, sizeof(txbuf) / sizeof(txbuf[0]), txbuf); +# endif +#endif +} diff --git a/tmk_core/avr.mk b/tmk_core/avr.mk index d7bee6d34c..940e95397b 100644 --- a/tmk_core/avr.mk +++ b/tmk_core/avr.mk @@ -12,8 +12,6 @@ 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 += $(DRIVER_PATH)/avr - COMPILEFLAGS += -funsigned-char COMPILEFLAGS += -funsigned-bitfields COMPILEFLAGS += -ffunction-sections diff --git a/tmk_core/chibios.mk b/tmk_core/chibios.mk index cbd9fff692..28aaaecba0 100644 --- a/tmk_core/chibios.mk +++ b/tmk_core/chibios.mk @@ -278,8 +278,6 @@ HEX = $(OBJCOPY) -O $(FORMAT) EEP = BIN = $(OBJCOPY) -O binary -COMMON_VPATH += $(DRIVER_PATH)/chibios - THUMBFLAGS = -DTHUMB_PRESENT -mno-thumb-interwork -DTHUMB_NO_INTERWORKING -mthumb -DTHUMB COMPILEFLAGS += -fomit-frame-pointer diff --git a/tmk_core/common.mk b/tmk_core/common.mk index fa907b47b8..923a736d35 100644 --- a/tmk_core/common.mk +++ b/tmk_core/common.mk @@ -138,3 +138,4 @@ endif # Search Path VPATH += $(TMK_PATH)/$(COMMON_DIR) VPATH += $(TMK_PATH)/$(PLATFORM_COMMON_DIR) +VPATH += $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_DIR) diff --git a/tmk_core/protocol/lufa.mk b/tmk_core/protocol/lufa.mk index 514d5fac41..c8935dacb7 100644 --- a/tmk_core/protocol/lufa.mk +++ b/tmk_core/protocol/lufa.mk @@ -49,7 +49,6 @@ SRC += $(LUFA_DIR)/usb_util.c # Search Path VPATH += $(TMK_PATH)/$(LUFA_DIR) VPATH += $(LUFA_PATH) -VPATH += $(DRIVER_PATH)/avr # Option modules #ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE) -- cgit v1.2.3 From 4c9003b1779b7b404e3bb0ce103db683bd92bccb Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Wed, 18 Aug 2021 00:04:15 +0100 Subject: Move chibios board files to allow tmk_core platform migration (#13777) * Move board files * fix up after rebase--- build_keyboard.mk | 2 +- .../chibios/BLACKPILL_STM32_F401/board/board.mk | 9 - .../chibios/BLACKPILL_STM32_F401/configs/board.h | 20 - .../BLACKPILL_STM32_F401/configs/bootloader_defs.h | 5 - .../chibios/BLACKPILL_STM32_F401/configs/config.h | 30 - .../chibios/BLACKPILL_STM32_F401/configs/mcuconf.h | 253 ------ .../chibios/BLACKPILL_STM32_F411/board/board.mk | 9 - .../chibios/BLACKPILL_STM32_F411/configs/board.h | 20 - .../BLACKPILL_STM32_F411/configs/bootloader_defs.h | 5 - .../chibios/BLACKPILL_STM32_F411/configs/config.h | 30 - .../chibios/BLACKPILL_STM32_F411/configs/mcuconf.h | 253 ------ .../BLACKPILL_STM32_F411/ld/STM32F411xC_tinyuf2.ld | 89 -- .../BLACKPILL_STM32_F411/ld/STM32F411xE_tinyuf2.ld | 89 -- .../chibios/GENERIC_STM32_F042X6/board/board.c | 265 ------ .../chibios/GENERIC_STM32_F042X6/board/board.h | 896 --------------------- .../chibios/GENERIC_STM32_F042X6/board/board.mk | 9 - .../GENERIC_STM32_F042X6/configs/bootloader_defs.h | 5 - .../chibios/GENERIC_STM32_F042X6/configs/config.h | 20 - .../chibios/GENERIC_STM32_F042X6/configs/mcuconf.h | 168 ---- .../chibios/GENERIC_STM32_F072XB/board/board.mk | 9 - .../chibios/GENERIC_STM32_F072XB/configs/board.h | 20 - .../GENERIC_STM32_F072XB/configs/bootloader_defs.h | 5 - .../chibios/GENERIC_STM32_F072XB/configs/config.h | 20 - .../chibios/GENERIC_STM32_F072XB/configs/mcuconf.h | 179 ---- .../chibios/GENERIC_STM32_F303XC/board/board.mk | 9 - .../chibios/GENERIC_STM32_F303XC/configs/board.h | 37 - .../GENERIC_STM32_F303XC/configs/bootloader_defs.h | 5 - .../chibios/GENERIC_STM32_F303XC/configs/config.h | 20 - .../chibios/GENERIC_STM32_F303XC/configs/mcuconf.h | 273 ------- .../chibios/GENERIC_STM32_F407XE/board/board.mk | 9 - .../chibios/GENERIC_STM32_F407XE/configs/board.h | 24 - .../chibios/GENERIC_STM32_F407XE/configs/config.h | 23 - .../chibios/GENERIC_STM32_F407XE/configs/mcuconf.h | 355 -------- .../chibios/GENERIC_STM32_F446XE/board/board.mk | 9 - .../chibios/GENERIC_STM32_F446XE/configs/board.h | 24 - .../chibios/GENERIC_STM32_F446XE/configs/config.h | 23 - .../chibios/GENERIC_STM32_F446XE/configs/mcuconf.h | 361 --------- .../chibios/GENERIC_STM32_G431XB/board/board.mk | 9 - .../chibios/GENERIC_STM32_G431XB/configs/config.h | 23 - .../chibios/GENERIC_STM32_G431XB/configs/mcuconf.h | 307 ------- .../chibios/GENERIC_STM32_G474XE/board/board.mk | 9 - .../chibios/GENERIC_STM32_G474XE/configs/config.h | 30 - .../chibios/GENERIC_STM32_G474XE/configs/mcuconf.h | 372 --------- .../chibios/GENERIC_STM32_L412XB/board/board.mk | 9 - .../chibios/GENERIC_STM32_L412XB/configs/board.h | 24 - .../chibios/GENERIC_STM32_L412XB/configs/config.h | 26 - .../chibios/GENERIC_STM32_L412XB/configs/mcuconf.h | 282 ------- .../chibios/GENERIC_STM32_L433XC/board/board.mk | 9 - .../chibios/GENERIC_STM32_L433XC/configs/board.h | 24 - .../chibios/GENERIC_STM32_L433XC/configs/config.h | 26 - .../chibios/GENERIC_STM32_L433XC/configs/mcuconf.h | 292 ------- platforms/chibios/IC_TEENSY_3_1/board/board.c | 151 ---- platforms/chibios/IC_TEENSY_3_1/board/board.h | 295 ------- platforms/chibios/IC_TEENSY_3_1/board/board.mk | 9 - platforms/chibios/IC_TEENSY_4_1/board/board.mk | 1 - platforms/chibios/IC_TEENSY_4_1/rules.mk | 1 - platforms/chibios/QMK_PROTON_C/board/board.mk | 9 - platforms/chibios/QMK_PROTON_C/configs/board.h | 37 - .../chibios/QMK_PROTON_C/configs/bootloader_defs.h | 7 - platforms/chibios/QMK_PROTON_C/configs/chconf.h | 756 ----------------- platforms/chibios/QMK_PROTON_C/configs/config.h | 20 - platforms/chibios/QMK_PROTON_C/configs/halconf.h | 531 ------------ platforms/chibios/QMK_PROTON_C/configs/mcuconf.h | 273 ------- .../chibios/QMK_PROTON_C/convert_to_proton_c.mk | 10 - .../chibios/STM32_F103_STM32DUINO/board/board.c | 59 -- .../chibios/STM32_F103_STM32DUINO/board/board.h | 166 ---- .../chibios/STM32_F103_STM32DUINO/board/board.mk | 9 - .../STM32_F103_STM32DUINO/configs/mcuconf.h | 209 ----- .../ld/STM32F103x8_stm32duino_bootloader.ld | 22 - .../ld/STM32F103xB_stm32duino_bootloader.ld | 22 - .../ld/stm32duino_bootloader_common.ld | 85 -- .../boards/BLACKPILL_STM32_F401/board/board.mk | 9 + .../boards/BLACKPILL_STM32_F401/configs/board.h | 20 + .../BLACKPILL_STM32_F401/configs/bootloader_defs.h | 5 + .../boards/BLACKPILL_STM32_F401/configs/config.h | 30 + .../boards/BLACKPILL_STM32_F401/configs/mcuconf.h | 253 ++++++ .../boards/BLACKPILL_STM32_F411/board/board.mk | 9 + .../boards/BLACKPILL_STM32_F411/configs/board.h | 20 + .../BLACKPILL_STM32_F411/configs/bootloader_defs.h | 5 + .../boards/BLACKPILL_STM32_F411/configs/config.h | 30 + .../boards/BLACKPILL_STM32_F411/configs/mcuconf.h | 253 ++++++ .../BLACKPILL_STM32_F411/ld/STM32F411xC_tinyuf2.ld | 89 ++ .../BLACKPILL_STM32_F411/ld/STM32F411xE_tinyuf2.ld | 89 ++ .../boards/GENERIC_STM32_F042X6/board/board.c | 265 ++++++ .../boards/GENERIC_STM32_F042X6/board/board.h | 896 +++++++++++++++++++++ .../boards/GENERIC_STM32_F042X6/board/board.mk | 9 + .../GENERIC_STM32_F042X6/configs/bootloader_defs.h | 5 + .../boards/GENERIC_STM32_F042X6/configs/config.h | 20 + .../boards/GENERIC_STM32_F042X6/configs/mcuconf.h | 168 ++++ .../boards/GENERIC_STM32_F072XB/board/board.mk | 9 + .../boards/GENERIC_STM32_F072XB/configs/board.h | 20 + .../GENERIC_STM32_F072XB/configs/bootloader_defs.h | 5 + .../boards/GENERIC_STM32_F072XB/configs/config.h | 20 + .../boards/GENERIC_STM32_F072XB/configs/mcuconf.h | 179 ++++ .../boards/GENERIC_STM32_F303XC/board/board.mk | 9 + .../boards/GENERIC_STM32_F303XC/configs/board.h | 37 + .../GENERIC_STM32_F303XC/configs/bootloader_defs.h | 5 + .../boards/GENERIC_STM32_F303XC/configs/config.h | 20 + .../boards/GENERIC_STM32_F303XC/configs/mcuconf.h | 273 +++++++ .../boards/GENERIC_STM32_F407XE/board/board.mk | 9 + .../boards/GENERIC_STM32_F407XE/configs/board.h | 24 + .../boards/GENERIC_STM32_F407XE/configs/config.h | 23 + .../boards/GENERIC_STM32_F407XE/configs/mcuconf.h | 355 ++++++++ .../boards/GENERIC_STM32_F446XE/board/board.mk | 9 + .../boards/GENERIC_STM32_F446XE/configs/board.h | 24 + .../boards/GENERIC_STM32_F446XE/configs/config.h | 23 + .../boards/GENERIC_STM32_F446XE/configs/mcuconf.h | 361 +++++++++ .../boards/GENERIC_STM32_G431XB/board/board.mk | 9 + .../boards/GENERIC_STM32_G431XB/configs/config.h | 23 + .../boards/GENERIC_STM32_G431XB/configs/mcuconf.h | 307 +++++++ .../boards/GENERIC_STM32_G474XE/board/board.mk | 9 + .../boards/GENERIC_STM32_G474XE/configs/config.h | 30 + .../boards/GENERIC_STM32_G474XE/configs/mcuconf.h | 372 +++++++++ .../boards/GENERIC_STM32_L412XB/board/board.mk | 9 + .../boards/GENERIC_STM32_L412XB/configs/board.h | 24 + .../boards/GENERIC_STM32_L412XB/configs/config.h | 26 + .../boards/GENERIC_STM32_L412XB/configs/mcuconf.h | 282 +++++++ .../boards/GENERIC_STM32_L433XC/board/board.mk | 9 + .../boards/GENERIC_STM32_L433XC/configs/board.h | 24 + .../boards/GENERIC_STM32_L433XC/configs/config.h | 26 + .../boards/GENERIC_STM32_L433XC/configs/mcuconf.h | 292 +++++++ .../chibios/boards/IC_TEENSY_3_1/board/board.c | 151 ++++ .../chibios/boards/IC_TEENSY_3_1/board/board.h | 295 +++++++ .../chibios/boards/IC_TEENSY_3_1/board/board.mk | 9 + .../chibios/boards/IC_TEENSY_4_1/board/board.mk | 1 + platforms/chibios/boards/IC_TEENSY_4_1/rules.mk | 1 + .../chibios/boards/QMK_PROTON_C/board/board.mk | 9 + .../chibios/boards/QMK_PROTON_C/configs/board.h | 37 + .../boards/QMK_PROTON_C/configs/bootloader_defs.h | 7 + .../chibios/boards/QMK_PROTON_C/configs/chconf.h | 756 +++++++++++++++++ .../chibios/boards/QMK_PROTON_C/configs/config.h | 20 + .../chibios/boards/QMK_PROTON_C/configs/halconf.h | 531 ++++++++++++ .../chibios/boards/QMK_PROTON_C/configs/mcuconf.h | 273 +++++++ .../boards/QMK_PROTON_C/convert_to_proton_c.mk | 10 + .../boards/STM32_F103_STM32DUINO/board/board.c | 59 ++ .../boards/STM32_F103_STM32DUINO/board/board.h | 166 ++++ .../boards/STM32_F103_STM32DUINO/board/board.mk | 9 + .../boards/STM32_F103_STM32DUINO/configs/mcuconf.h | 209 +++++ .../ld/STM32F103x8_stm32duino_bootloader.ld | 22 + .../ld/STM32F103xB_stm32duino_bootloader.ld | 22 + .../ld/stm32duino_bootloader_common.ld | 85 ++ platforms/chibios/boards/common/configs/chconf.h | 756 +++++++++++++++++ platforms/chibios/boards/common/configs/halconf.h | 531 ++++++++++++ platforms/chibios/boards/common/ld/MKL26Z64.ld | 105 +++ platforms/chibios/boards/common/ld/STM32L412xB.ld | 85 ++ .../boards/keyboard-config-templates/board.h | 20 + .../boards/keyboard-config-templates/chconf.h | 20 + .../boards/keyboard-config-templates/halconf.h | 20 + .../boards/keyboard-config-templates/mcuconf.h | 21 + platforms/chibios/common/configs/chconf.h | 756 ----------------- platforms/chibios/common/configs/halconf.h | 531 ------------ platforms/chibios/common/ld/MKL26Z64.ld | 105 --- platforms/chibios/common/ld/STM32L412xB.ld | 85 -- .../chibios/keyboard-config-templates/board.h | 20 - .../chibios/keyboard-config-templates/chconf.h | 20 - .../chibios/keyboard-config-templates/halconf.h | 20 - .../chibios/keyboard-config-templates/mcuconf.h | 21 - tmk_core/chibios.mk | 38 +- 158 files changed, 9272 insertions(+), 9272 deletions(-) delete mode 100644 platforms/chibios/BLACKPILL_STM32_F401/board/board.mk delete mode 100644 platforms/chibios/BLACKPILL_STM32_F401/configs/board.h delete mode 100644 platforms/chibios/BLACKPILL_STM32_F401/configs/bootloader_defs.h delete mode 100644 platforms/chibios/BLACKPILL_STM32_F401/configs/config.h delete mode 100644 platforms/chibios/BLACKPILL_STM32_F401/configs/mcuconf.h delete mode 100644 platforms/chibios/BLACKPILL_STM32_F411/board/board.mk delete mode 100644 platforms/chibios/BLACKPILL_STM32_F411/configs/board.h delete mode 100644 platforms/chibios/BLACKPILL_STM32_F411/configs/bootloader_defs.h delete mode 100644 platforms/chibios/BLACKPILL_STM32_F411/configs/config.h delete mode 100644 platforms/chibios/BLACKPILL_STM32_F411/configs/mcuconf.h delete mode 100644 platforms/chibios/BLACKPILL_STM32_F411/ld/STM32F411xC_tinyuf2.ld delete mode 100644 platforms/chibios/BLACKPILL_STM32_F411/ld/STM32F411xE_tinyuf2.ld delete mode 100644 platforms/chibios/GENERIC_STM32_F042X6/board/board.c delete mode 100644 platforms/chibios/GENERIC_STM32_F042X6/board/board.h delete mode 100644 platforms/chibios/GENERIC_STM32_F042X6/board/board.mk delete mode 100644 platforms/chibios/GENERIC_STM32_F042X6/configs/bootloader_defs.h delete mode 100644 platforms/chibios/GENERIC_STM32_F042X6/configs/config.h delete mode 100644 platforms/chibios/GENERIC_STM32_F042X6/configs/mcuconf.h delete mode 100644 platforms/chibios/GENERIC_STM32_F072XB/board/board.mk delete mode 100644 platforms/chibios/GENERIC_STM32_F072XB/configs/board.h delete mode 100644 platforms/chibios/GENERIC_STM32_F072XB/configs/bootloader_defs.h delete mode 100644 platforms/chibios/GENERIC_STM32_F072XB/configs/config.h delete mode 100644 platforms/chibios/GENERIC_STM32_F072XB/configs/mcuconf.h delete mode 100644 platforms/chibios/GENERIC_STM32_F303XC/board/board.mk delete mode 100644 platforms/chibios/GENERIC_STM32_F303XC/configs/board.h delete mode 100644 platforms/chibios/GENERIC_STM32_F303XC/configs/bootloader_defs.h delete mode 100644 platforms/chibios/GENERIC_STM32_F303XC/configs/config.h delete mode 100644 platforms/chibios/GENERIC_STM32_F303XC/configs/mcuconf.h delete mode 100644 platforms/chibios/GENERIC_STM32_F407XE/board/board.mk delete mode 100644 platforms/chibios/GENERIC_STM32_F407XE/configs/board.h delete mode 100644 platforms/chibios/GENERIC_STM32_F407XE/configs/config.h delete mode 100644 platforms/chibios/GENERIC_STM32_F407XE/configs/mcuconf.h delete mode 100644 platforms/chibios/GENERIC_STM32_F446XE/board/board.mk delete mode 100644 platforms/chibios/GENERIC_STM32_F446XE/configs/board.h delete mode 100644 platforms/chibios/GENERIC_STM32_F446XE/configs/config.h delete mode 100644 platforms/chibios/GENERIC_STM32_F446XE/configs/mcuconf.h delete mode 100644 platforms/chibios/GENERIC_STM32_G431XB/board/board.mk delete mode 100644 platforms/chibios/GENERIC_STM32_G431XB/configs/config.h delete mode 100644 platforms/chibios/GENERIC_STM32_G431XB/configs/mcuconf.h delete mode 100644 platforms/chibios/GENERIC_STM32_G474XE/board/board.mk delete mode 100644 platforms/chibios/GENERIC_STM32_G474XE/configs/config.h delete mode 100644 platforms/chibios/GENERIC_STM32_G474XE/configs/mcuconf.h delete mode 100644 platforms/chibios/GENERIC_STM32_L412XB/board/board.mk delete mode 100644 platforms/chibios/GENERIC_STM32_L412XB/configs/board.h delete mode 100644 platforms/chibios/GENERIC_STM32_L412XB/configs/config.h delete mode 100644 platforms/chibios/GENERIC_STM32_L412XB/configs/mcuconf.h delete mode 100644 platforms/chibios/GENERIC_STM32_L433XC/board/board.mk delete mode 100644 platforms/chibios/GENERIC_STM32_L433XC/configs/board.h delete mode 100644 platforms/chibios/GENERIC_STM32_L433XC/configs/config.h delete mode 100644 platforms/chibios/GENERIC_STM32_L433XC/configs/mcuconf.h delete mode 100644 platforms/chibios/IC_TEENSY_3_1/board/board.c delete mode 100644 platforms/chibios/IC_TEENSY_3_1/board/board.h delete mode 100644 platforms/chibios/IC_TEENSY_3_1/board/board.mk delete mode 100644 platforms/chibios/IC_TEENSY_4_1/board/board.mk delete mode 100644 platforms/chibios/IC_TEENSY_4_1/rules.mk delete mode 100644 platforms/chibios/QMK_PROTON_C/board/board.mk delete mode 100644 platforms/chibios/QMK_PROTON_C/configs/board.h delete mode 100644 platforms/chibios/QMK_PROTON_C/configs/bootloader_defs.h delete mode 100644 platforms/chibios/QMK_PROTON_C/configs/chconf.h delete mode 100644 platforms/chibios/QMK_PROTON_C/configs/config.h delete mode 100644 platforms/chibios/QMK_PROTON_C/configs/halconf.h delete mode 100644 platforms/chibios/QMK_PROTON_C/configs/mcuconf.h delete mode 100644 platforms/chibios/QMK_PROTON_C/convert_to_proton_c.mk delete mode 100644 platforms/chibios/STM32_F103_STM32DUINO/board/board.c delete mode 100644 platforms/chibios/STM32_F103_STM32DUINO/board/board.h delete mode 100644 platforms/chibios/STM32_F103_STM32DUINO/board/board.mk delete mode 100644 platforms/chibios/STM32_F103_STM32DUINO/configs/mcuconf.h delete mode 100644 platforms/chibios/STM32_F103_STM32DUINO/ld/STM32F103x8_stm32duino_bootloader.ld delete mode 100644 platforms/chibios/STM32_F103_STM32DUINO/ld/STM32F103xB_stm32duino_bootloader.ld delete mode 100644 platforms/chibios/STM32_F103_STM32DUINO/ld/stm32duino_bootloader_common.ld create mode 100644 platforms/chibios/boards/BLACKPILL_STM32_F401/board/board.mk create mode 100644 platforms/chibios/boards/BLACKPILL_STM32_F401/configs/board.h create mode 100644 platforms/chibios/boards/BLACKPILL_STM32_F401/configs/bootloader_defs.h create mode 100644 platforms/chibios/boards/BLACKPILL_STM32_F401/configs/config.h create mode 100644 platforms/chibios/boards/BLACKPILL_STM32_F401/configs/mcuconf.h create mode 100644 platforms/chibios/boards/BLACKPILL_STM32_F411/board/board.mk create mode 100644 platforms/chibios/boards/BLACKPILL_STM32_F411/configs/board.h create mode 100644 platforms/chibios/boards/BLACKPILL_STM32_F411/configs/bootloader_defs.h create mode 100644 platforms/chibios/boards/BLACKPILL_STM32_F411/configs/config.h create mode 100644 platforms/chibios/boards/BLACKPILL_STM32_F411/configs/mcuconf.h create mode 100644 platforms/chibios/boards/BLACKPILL_STM32_F411/ld/STM32F411xC_tinyuf2.ld create mode 100644 platforms/chibios/boards/BLACKPILL_STM32_F411/ld/STM32F411xE_tinyuf2.ld create mode 100644 platforms/chibios/boards/GENERIC_STM32_F042X6/board/board.c create mode 100644 platforms/chibios/boards/GENERIC_STM32_F042X6/board/board.h create mode 100644 platforms/chibios/boards/GENERIC_STM32_F042X6/board/board.mk create mode 100644 platforms/chibios/boards/GENERIC_STM32_F042X6/configs/bootloader_defs.h create mode 100644 platforms/chibios/boards/GENERIC_STM32_F042X6/configs/config.h create mode 100644 platforms/chibios/boards/GENERIC_STM32_F042X6/configs/mcuconf.h create mode 100644 platforms/chibios/boards/GENERIC_STM32_F072XB/board/board.mk create mode 100644 platforms/chibios/boards/GENERIC_STM32_F072XB/configs/board.h create mode 100644 platforms/chibios/boards/GENERIC_STM32_F072XB/configs/bootloader_defs.h create mode 100644 platforms/chibios/boards/GENERIC_STM32_F072XB/configs/config.h create mode 100644 platforms/chibios/boards/GENERIC_STM32_F072XB/configs/mcuconf.h create mode 100644 platforms/chibios/boards/GENERIC_STM32_F303XC/board/board.mk create mode 100644 platforms/chibios/boards/GENERIC_STM32_F303XC/configs/board.h create mode 100644 platforms/chibios/boards/GENERIC_STM32_F303XC/configs/bootloader_defs.h create mode 100644 platforms/chibios/boards/GENERIC_STM32_F303XC/configs/config.h create mode 100644 platforms/chibios/boards/GENERIC_STM32_F303XC/configs/mcuconf.h create mode 100644 platforms/chibios/boards/GENERIC_STM32_F407XE/board/board.mk create mode 100644 platforms/chibios/boards/GENERIC_STM32_F407XE/configs/board.h create mode 100644 platforms/chibios/boards/GENERIC_STM32_F407XE/configs/config.h create mode 100644 platforms/chibios/boards/GENERIC_STM32_F407XE/configs/mcuconf.h create mode 100644 platforms/chibios/boards/GENERIC_STM32_F446XE/board/board.mk create mode 100644 platforms/chibios/boards/GENERIC_STM32_F446XE/configs/board.h create mode 100644 platforms/chibios/boards/GENERIC_STM32_F446XE/configs/config.h create mode 100644 platforms/chibios/boards/GENERIC_STM32_F446XE/configs/mcuconf.h create mode 100644 platforms/chibios/boards/GENERIC_STM32_G431XB/board/board.mk create mode 100644 platforms/chibios/boards/GENERIC_STM32_G431XB/configs/config.h create mode 100644 platforms/chibios/boards/GENERIC_STM32_G431XB/configs/mcuconf.h create mode 100644 platforms/chibios/boards/GENERIC_STM32_G474XE/board/board.mk create mode 100644 platforms/chibios/boards/GENERIC_STM32_G474XE/configs/config.h create mode 100644 platforms/chibios/boards/GENERIC_STM32_G474XE/configs/mcuconf.h create mode 100644 platforms/chibios/boards/GENERIC_STM32_L412XB/board/board.mk create mode 100644 platforms/chibios/boards/GENERIC_STM32_L412XB/configs/board.h create mode 100644 platforms/chibios/boards/GENERIC_STM32_L412XB/configs/config.h create mode 100644 platforms/chibios/boards/GENERIC_STM32_L412XB/configs/mcuconf.h create mode 100644 platforms/chibios/boards/GENERIC_STM32_L433XC/board/board.mk create mode 100644 platforms/chibios/boards/GENERIC_STM32_L433XC/configs/board.h create mode 100644 platforms/chibios/boards/GENERIC_STM32_L433XC/configs/config.h create mode 100644 platforms/chibios/boards/GENERIC_STM32_L433XC/configs/mcuconf.h create mode 100644 platforms/chibios/boards/IC_TEENSY_3_1/board/board.c create mode 100644 platforms/chibios/boards/IC_TEENSY_3_1/board/board.h create mode 100644 platforms/chibios/boards/IC_TEENSY_3_1/board/board.mk create mode 100644 platforms/chibios/boards/IC_TEENSY_4_1/board/board.mk create mode 100644 platforms/chibios/boards/IC_TEENSY_4_1/rules.mk create mode 100644 platforms/chibios/boards/QMK_PROTON_C/board/board.mk create mode 100644 platforms/chibios/boards/QMK_PROTON_C/configs/board.h create mode 100644 platforms/chibios/boards/QMK_PROTON_C/configs/bootloader_defs.h create mode 100644 platforms/chibios/boards/QMK_PROTON_C/configs/chconf.h create mode 100644 platforms/chibios/boards/QMK_PROTON_C/configs/config.h create mode 100644 platforms/chibios/boards/QMK_PROTON_C/configs/halconf.h create mode 100644 platforms/chibios/boards/QMK_PROTON_C/configs/mcuconf.h create mode 100644 platforms/chibios/boards/QMK_PROTON_C/convert_to_proton_c.mk create mode 100644 platforms/chibios/boards/STM32_F103_STM32DUINO/board/board.c create mode 100644 platforms/chibios/boards/STM32_F103_STM32DUINO/board/board.h create mode 100644 platforms/chibios/boards/STM32_F103_STM32DUINO/board/board.mk create mode 100644 platforms/chibios/boards/STM32_F103_STM32DUINO/configs/mcuconf.h create mode 100644 platforms/chibios/boards/STM32_F103_STM32DUINO/ld/STM32F103x8_stm32duino_bootloader.ld create mode 100644 platforms/chibios/boards/STM32_F103_STM32DUINO/ld/STM32F103xB_stm32duino_bootloader.ld create mode 100644 platforms/chibios/boards/STM32_F103_STM32DUINO/ld/stm32duino_bootloader_common.ld create mode 100644 platforms/chibios/boards/common/configs/chconf.h create mode 100644 platforms/chibios/boards/common/configs/halconf.h create mode 100644 platforms/chibios/boards/common/ld/MKL26Z64.ld create mode 100644 platforms/chibios/boards/common/ld/STM32L412xB.ld create mode 100644 platforms/chibios/boards/keyboard-config-templates/board.h create mode 100644 platforms/chibios/boards/keyboard-config-templates/chconf.h create mode 100644 platforms/chibios/boards/keyboard-config-templates/halconf.h create mode 100644 platforms/chibios/boards/keyboard-config-templates/mcuconf.h delete mode 100644 platforms/chibios/common/configs/chconf.h delete mode 100644 platforms/chibios/common/configs/halconf.h delete mode 100644 platforms/chibios/common/ld/MKL26Z64.ld delete mode 100644 platforms/chibios/common/ld/STM32L412xB.ld delete mode 100644 platforms/chibios/keyboard-config-templates/board.h delete mode 100644 platforms/chibios/keyboard-config-templates/chconf.h delete mode 100644 platforms/chibios/keyboard-config-templates/halconf.h delete mode 100644 platforms/chibios/keyboard-config-templates/mcuconf.h (limited to 'tmk_core') diff --git a/build_keyboard.mk b/build_keyboard.mk index 262bfd9a70..62a7ba6a0d 100644 --- a/build_keyboard.mk +++ b/build_keyboard.mk @@ -151,7 +151,7 @@ ifeq ($(strip $(CTPC)), yes) endif ifeq ($(strip $(CONVERT_TO_PROTON_C)), yes) - include platforms/chibios/QMK_PROTON_C/convert_to_proton_c.mk + include platforms/chibios/boards/QMK_PROTON_C/convert_to_proton_c.mk endif include quantum/mcu_selection.mk diff --git a/platforms/chibios/BLACKPILL_STM32_F401/board/board.mk b/platforms/chibios/BLACKPILL_STM32_F401/board/board.mk deleted file mode 100644 index fddf7dace4..0000000000 --- a/platforms/chibios/BLACKPILL_STM32_F401/board/board.mk +++ /dev/null @@ -1,9 +0,0 @@ -# List of all the board related files. -BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_STM32F401C_DISCOVERY/board.c - -# Required include directories -BOARDINC = $(CHIBIOS)/os/hal/boards/ST_STM32F401C_DISCOVERY - -# Shared variables -ALLCSRC += $(BOARDSRC) -ALLINC += $(BOARDINC) diff --git a/platforms/chibios/BLACKPILL_STM32_F401/configs/board.h b/platforms/chibios/BLACKPILL_STM32_F401/configs/board.h deleted file mode 100644 index 30af6b0c86..0000000000 --- a/platforms/chibios/BLACKPILL_STM32_F401/configs/board.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Copyright 2020 Nick Brassel (tzarc) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#pragma once - -#include_next "board.h" - -#undef STM32_HSE_BYPASS diff --git a/platforms/chibios/BLACKPILL_STM32_F401/configs/bootloader_defs.h b/platforms/chibios/BLACKPILL_STM32_F401/configs/bootloader_defs.h deleted file mode 100644 index 4da3d39a32..0000000000 --- a/platforms/chibios/BLACKPILL_STM32_F401/configs/bootloader_defs.h +++ /dev/null @@ -1,5 +0,0 @@ -/* Address for jumping to bootloader on STM32 chips. */ -/* It is chip dependent, the correct number can be looked up here: - * http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf - */ -#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000 diff --git a/platforms/chibios/BLACKPILL_STM32_F401/configs/config.h b/platforms/chibios/BLACKPILL_STM32_F401/configs/config.h deleted file mode 100644 index e181422eba..0000000000 --- a/platforms/chibios/BLACKPILL_STM32_F401/configs/config.h +++ /dev/null @@ -1,30 +0,0 @@ -/* Copyright 2020 Nick Brassel (tzarc) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#pragma once - -#define BOARD_OTG_NOVBUSSENS 1 - -#ifndef STM32_LSECLK -# define STM32_LSECLK 32768U -#endif // STM32_LSECLK - -#ifndef STM32_HSECLK -# define STM32_HSECLK 25000000U -#endif // STM32_HSECLK - -#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP -# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE -#endif diff --git a/platforms/chibios/BLACKPILL_STM32_F401/configs/mcuconf.h b/platforms/chibios/BLACKPILL_STM32_F401/configs/mcuconf.h deleted file mode 100644 index ba6e934fe7..0000000000 --- a/platforms/chibios/BLACKPILL_STM32_F401/configs/mcuconf.h +++ /dev/null @@ -1,253 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - 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 License 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. -*/ - -#ifndef MCUCONF_H -#define MCUCONF_H - -/* - * STM32F4xx drivers configuration. - * The following settings override the default settings present in - * the various device driver implementation headers. - * Note that the settings for each driver only have effect if the whole - * driver is enabled in halconf.h. - * - * IRQ priorities: - * 15...0 Lowest...Highest. - * - * DMA priorities: - * 0...3 Lowest...Highest. - */ - -#define STM32F4xx_MCUCONF - -/* - * HAL driver system settings. - */ -#define STM32_NO_INIT FALSE -#define STM32_HSI_ENABLED TRUE -#define STM32_LSI_ENABLED TRUE -#define STM32_HSE_ENABLED TRUE -#define STM32_LSE_ENABLED FALSE -#define STM32_CLOCK48_REQUIRED TRUE -#define STM32_SW STM32_SW_PLL -#define STM32_PLLSRC STM32_PLLSRC_HSE -#define STM32_PLLM_VALUE 25 -#define STM32_PLLN_VALUE 336 -#define STM32_PLLP_VALUE 4 -#define STM32_PLLQ_VALUE 7 -#define STM32_HPRE STM32_HPRE_DIV1 -#define STM32_PPRE1 STM32_PPRE1_DIV4 -#define STM32_PPRE2 STM32_PPRE2_DIV2 -#define STM32_RTCSEL STM32_RTCSEL_LSI -#define STM32_RTCPRE_VALUE 8 -#define STM32_MCO1SEL STM32_MCO1SEL_HSI -#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 -#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK -#define STM32_MCO2PRE STM32_MCO2PRE_DIV5 -#define STM32_I2SSRC STM32_I2SSRC_CKIN -#define STM32_PLLI2SN_VALUE 192 -#define STM32_PLLI2SR_VALUE 5 -#define STM32_PVD_ENABLE FALSE -#define STM32_PLS STM32_PLS_LEV0 -#define STM32_BKPRAM_ENABLE FALSE - -/* - * IRQ system settings. - */ -#define STM32_IRQ_EXTI0_PRIORITY 6 -#define STM32_IRQ_EXTI1_PRIORITY 6 -#define STM32_IRQ_EXTI2_PRIORITY 6 -#define STM32_IRQ_EXTI3_PRIORITY 6 -#define STM32_IRQ_EXTI4_PRIORITY 6 -#define STM32_IRQ_EXTI5_9_PRIORITY 6 -#define STM32_IRQ_EXTI10_15_PRIORITY 6 -#define STM32_IRQ_EXTI16_PRIORITY 6 -#define STM32_IRQ_EXTI17_PRIORITY 15 -#define STM32_IRQ_EXTI18_PRIORITY 6 -#define STM32_IRQ_EXTI19_PRIORITY 6 -#define STM32_IRQ_EXTI20_PRIORITY 6 -#define STM32_IRQ_EXTI21_PRIORITY 15 -#define STM32_IRQ_EXTI22_PRIORITY 15 - -/* - * ADC driver system settings. - */ -#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 -#define STM32_ADC_USE_ADC1 FALSE -#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) -#define STM32_ADC_ADC1_DMA_PRIORITY 2 -#define STM32_ADC_IRQ_PRIORITY 6 -#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 - -/* - * GPT driver system settings. - */ -#define STM32_GPT_USE_TIM1 FALSE -#define STM32_GPT_USE_TIM2 FALSE -#define STM32_GPT_USE_TIM3 FALSE -#define STM32_GPT_USE_TIM4 FALSE -#define STM32_GPT_USE_TIM5 FALSE -#define STM32_GPT_USE_TIM9 FALSE -#define STM32_GPT_USE_TIM11 FALSE -#define STM32_GPT_TIM1_IRQ_PRIORITY 7 -#define STM32_GPT_TIM2_IRQ_PRIORITY 7 -#define STM32_GPT_TIM3_IRQ_PRIORITY 7 -#define STM32_GPT_TIM4_IRQ_PRIORITY 7 -#define STM32_GPT_TIM5_IRQ_PRIORITY 7 -#define STM32_GPT_TIM9_IRQ_PRIORITY 7 -#define STM32_GPT_TIM11_IRQ_PRIORITY 7 - -/* - * I2C driver system settings. - */ -#define STM32_I2C_USE_I2C1 FALSE -#define STM32_I2C_USE_I2C2 FALSE -#define STM32_I2C_USE_I2C3 FALSE -#define STM32_I2C_BUSY_TIMEOUT 50 -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_I2C_I2C1_IRQ_PRIORITY 5 -#define STM32_I2C_I2C2_IRQ_PRIORITY 5 -#define STM32_I2C_I2C3_IRQ_PRIORITY 5 -#define STM32_I2C_I2C1_DMA_PRIORITY 3 -#define STM32_I2C_I2C2_DMA_PRIORITY 3 -#define STM32_I2C_I2C3_DMA_PRIORITY 3 -#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") - -/* - * I2S driver system settings. - */ -#define STM32_I2S_USE_SPI2 FALSE -#define STM32_I2S_USE_SPI3 FALSE -#define STM32_I2S_SPI2_IRQ_PRIORITY 10 -#define STM32_I2S_SPI3_IRQ_PRIORITY 10 -#define STM32_I2S_SPI2_DMA_PRIORITY 1 -#define STM32_I2S_SPI3_DMA_PRIORITY 1 -#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) -#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") - -/* - * ICU driver system settings. - */ -#define STM32_ICU_USE_TIM1 FALSE -#define STM32_ICU_USE_TIM2 FALSE -#define STM32_ICU_USE_TIM3 FALSE -#define STM32_ICU_USE_TIM4 FALSE -#define STM32_ICU_USE_TIM5 FALSE -#define STM32_ICU_USE_TIM9 FALSE -#define STM32_ICU_TIM1_IRQ_PRIORITY 7 -#define STM32_ICU_TIM2_IRQ_PRIORITY 7 -#define STM32_ICU_TIM3_IRQ_PRIORITY 7 -#define STM32_ICU_TIM4_IRQ_PRIORITY 7 -#define STM32_ICU_TIM5_IRQ_PRIORITY 7 -#define STM32_ICU_TIM9_IRQ_PRIORITY 7 - -/* - * PWM driver system settings. - */ -#define STM32_PWM_USE_ADVANCED FALSE -#define STM32_PWM_USE_TIM1 FALSE -#define STM32_PWM_USE_TIM2 FALSE -#define STM32_PWM_USE_TIM3 FALSE -#define STM32_PWM_USE_TIM4 FALSE -#define STM32_PWM_USE_TIM5 FALSE -#define STM32_PWM_USE_TIM9 FALSE -#define STM32_PWM_TIM1_IRQ_PRIORITY 7 -#define STM32_PWM_TIM2_IRQ_PRIORITY 7 -#define STM32_PWM_TIM3_IRQ_PRIORITY 7 -#define STM32_PWM_TIM4_IRQ_PRIORITY 7 -#define STM32_PWM_TIM5_IRQ_PRIORITY 7 -#define STM32_PWM_TIM9_IRQ_PRIORITY 7 - -/* - * SERIAL driver system settings. - */ -#define STM32_SERIAL_USE_USART1 FALSE -#define STM32_SERIAL_USE_USART2 FALSE -#define STM32_SERIAL_USE_USART6 FALSE -#define STM32_SERIAL_USART1_PRIORITY 12 -#define STM32_SERIAL_USART2_PRIORITY 12 -#define STM32_SERIAL_USART6_PRIORITY 12 - -/* - * SPI driver system settings. - */ -#define STM32_SPI_USE_SPI1 FALSE -#define STM32_SPI_USE_SPI2 FALSE -#define STM32_SPI_USE_SPI3 FALSE -#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) -#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) -#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) -#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_SPI_SPI1_DMA_PRIORITY 1 -#define STM32_SPI_SPI2_DMA_PRIORITY 1 -#define STM32_SPI_SPI3_DMA_PRIORITY 1 -#define STM32_SPI_SPI1_IRQ_PRIORITY 10 -#define STM32_SPI_SPI2_IRQ_PRIORITY 10 -#define STM32_SPI_SPI3_IRQ_PRIORITY 10 -#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") - -/* - * ST driver system settings. - */ -#define STM32_ST_IRQ_PRIORITY 8 -#define STM32_ST_USE_TIMER 2 - -/* - * UART driver system settings. - */ -#define STM32_UART_USE_USART1 FALSE -#define STM32_UART_USE_USART2 FALSE -#define STM32_UART_USE_USART6 FALSE -#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) -#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) -#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) -#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) -#define STM32_UART_USART1_IRQ_PRIORITY 12 -#define STM32_UART_USART2_IRQ_PRIORITY 12 -#define STM32_UART_USART6_IRQ_PRIORITY 12 -#define STM32_UART_USART1_DMA_PRIORITY 0 -#define STM32_UART_USART2_DMA_PRIORITY 0 -#define STM32_UART_USART6_DMA_PRIORITY 0 -#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") - -/* - * USB driver system settings. - */ -#define STM32_USB_USE_OTG1 TRUE -#define STM32_USB_OTG1_IRQ_PRIORITY 14 -#define STM32_USB_OTG1_RX_FIFO_SIZE 512 -#define STM32_USB_OTG_THREAD_PRIO NORMALPRIO+1 -#define STM32_USB_OTG_THREAD_STACK_SIZE 128 -#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 - -/* - * WDG driver system settings. - */ -#define STM32_WDG_USE_IWDG FALSE - -#endif /* MCUCONF_H */ diff --git a/platforms/chibios/BLACKPILL_STM32_F411/board/board.mk b/platforms/chibios/BLACKPILL_STM32_F411/board/board.mk deleted file mode 100644 index bb00b1a2b0..0000000000 --- a/platforms/chibios/BLACKPILL_STM32_F411/board/board.mk +++ /dev/null @@ -1,9 +0,0 @@ -# List of all the board related files. -BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_F411RE/board.c - -# Required include directories -BOARDINC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_F411RE - -# Shared variables -ALLCSRC += $(BOARDSRC) -ALLINC += $(BOARDINC) diff --git a/platforms/chibios/BLACKPILL_STM32_F411/configs/board.h b/platforms/chibios/BLACKPILL_STM32_F411/configs/board.h deleted file mode 100644 index 30af6b0c86..0000000000 --- a/platforms/chibios/BLACKPILL_STM32_F411/configs/board.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Copyright 2020 Nick Brassel (tzarc) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#pragma once - -#include_next "board.h" - -#undef STM32_HSE_BYPASS diff --git a/platforms/chibios/BLACKPILL_STM32_F411/configs/bootloader_defs.h b/platforms/chibios/BLACKPILL_STM32_F411/configs/bootloader_defs.h deleted file mode 100644 index 4da3d39a32..0000000000 --- a/platforms/chibios/BLACKPILL_STM32_F411/configs/bootloader_defs.h +++ /dev/null @@ -1,5 +0,0 @@ -/* Address for jumping to bootloader on STM32 chips. */ -/* It is chip dependent, the correct number can be looked up here: - * http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf - */ -#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000 diff --git a/platforms/chibios/BLACKPILL_STM32_F411/configs/config.h b/platforms/chibios/BLACKPILL_STM32_F411/configs/config.h deleted file mode 100644 index e181422eba..0000000000 --- a/platforms/chibios/BLACKPILL_STM32_F411/configs/config.h +++ /dev/null @@ -1,30 +0,0 @@ -/* Copyright 2020 Nick Brassel (tzarc) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#pragma once - -#define BOARD_OTG_NOVBUSSENS 1 - -#ifndef STM32_LSECLK -# define STM32_LSECLK 32768U -#endif // STM32_LSECLK - -#ifndef STM32_HSECLK -# define STM32_HSECLK 25000000U -#endif // STM32_HSECLK - -#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP -# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE -#endif diff --git a/platforms/chibios/BLACKPILL_STM32_F411/configs/mcuconf.h b/platforms/chibios/BLACKPILL_STM32_F411/configs/mcuconf.h deleted file mode 100644 index 0394ff56bb..0000000000 --- a/platforms/chibios/BLACKPILL_STM32_F411/configs/mcuconf.h +++ /dev/null @@ -1,253 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - 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 License 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. -*/ - -#ifndef MCUCONF_H -#define MCUCONF_H - -/* - * STM32F4xx drivers configuration. - * The following settings override the default settings present in - * the various device driver implementation headers. - * Note that the settings for each driver only have effect if the whole - * driver is enabled in halconf.h. - * - * IRQ priorities: - * 15...0 Lowest...Highest. - * - * DMA priorities: - * 0...3 Lowest...Highest. - */ - -#define STM32F4xx_MCUCONF - -/* - * HAL driver system settings. - */ -#define STM32_NO_INIT FALSE -#define STM32_HSI_ENABLED TRUE -#define STM32_LSI_ENABLED TRUE -#define STM32_HSE_ENABLED TRUE -#define STM32_LSE_ENABLED FALSE -#define STM32_CLOCK48_REQUIRED TRUE -#define STM32_SW STM32_SW_PLL -#define STM32_PLLSRC STM32_PLLSRC_HSE -#define STM32_PLLM_VALUE 25 -#define STM32_PLLN_VALUE 384 -#define STM32_PLLP_VALUE 4 -#define STM32_PLLQ_VALUE 8 -#define STM32_HPRE STM32_HPRE_DIV1 -#define STM32_PPRE1 STM32_PPRE1_DIV4 -#define STM32_PPRE2 STM32_PPRE2_DIV2 -#define STM32_RTCSEL STM32_RTCSEL_LSI -#define STM32_RTCPRE_VALUE 8 -#define STM32_MCO1SEL STM32_MCO1SEL_HSI -#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 -#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK -#define STM32_MCO2PRE STM32_MCO2PRE_DIV5 -#define STM32_I2SSRC STM32_I2SSRC_CKIN -#define STM32_PLLI2SN_VALUE 192 -#define STM32_PLLI2SR_VALUE 5 -#define STM32_PVD_ENABLE FALSE -#define STM32_PLS STM32_PLS_LEV0 -#define STM32_BKPRAM_ENABLE FALSE - -/* - * IRQ system settings. - */ -#define STM32_IRQ_EXTI0_PRIORITY 6 -#define STM32_IRQ_EXTI1_PRIORITY 6 -#define STM32_IRQ_EXTI2_PRIORITY 6 -#define STM32_IRQ_EXTI3_PRIORITY 6 -#define STM32_IRQ_EXTI4_PRIORITY 6 -#define STM32_IRQ_EXTI5_9_PRIORITY 6 -#define STM32_IRQ_EXTI10_15_PRIORITY 6 -#define STM32_IRQ_EXTI16_PRIORITY 6 -#define STM32_IRQ_EXTI17_PRIORITY 15 -#define STM32_IRQ_EXTI18_PRIORITY 6 -#define STM32_IRQ_EXTI19_PRIORITY 6 -#define STM32_IRQ_EXTI20_PRIORITY 6 -#define STM32_IRQ_EXTI21_PRIORITY 15 -#define STM32_IRQ_EXTI22_PRIORITY 15 - -/* - * ADC driver system settings. - */ -#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 -#define STM32_ADC_USE_ADC1 FALSE -#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) -#define STM32_ADC_ADC1_DMA_PRIORITY 2 -#define STM32_ADC_IRQ_PRIORITY 6 -#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 - -/* - * GPT driver system settings. - */ -#define STM32_GPT_USE_TIM1 FALSE -#define STM32_GPT_USE_TIM2 FALSE -#define STM32_GPT_USE_TIM3 FALSE -#define STM32_GPT_USE_TIM4 FALSE -#define STM32_GPT_USE_TIM5 FALSE -#define STM32_GPT_USE_TIM9 FALSE -#define STM32_GPT_USE_TIM11 FALSE -#define STM32_GPT_TIM1_IRQ_PRIORITY 7 -#define STM32_GPT_TIM2_IRQ_PRIORITY 7 -#define STM32_GPT_TIM3_IRQ_PRIORITY 7 -#define STM32_GPT_TIM4_IRQ_PRIORITY 7 -#define STM32_GPT_TIM5_IRQ_PRIORITY 7 -#define STM32_GPT_TIM9_IRQ_PRIORITY 7 -#define STM32_GPT_TIM11_IRQ_PRIORITY 7 - -/* - * I2C driver system settings. - */ -#define STM32_I2C_USE_I2C1 FALSE -#define STM32_I2C_USE_I2C2 FALSE -#define STM32_I2C_USE_I2C3 FALSE -#define STM32_I2C_BUSY_TIMEOUT 50 -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_I2C_I2C1_IRQ_PRIORITY 5 -#define STM32_I2C_I2C2_IRQ_PRIORITY 5 -#define STM32_I2C_I2C3_IRQ_PRIORITY 5 -#define STM32_I2C_I2C1_DMA_PRIORITY 3 -#define STM32_I2C_I2C2_DMA_PRIORITY 3 -#define STM32_I2C_I2C3_DMA_PRIORITY 3 -#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") - -/* - * I2S driver system settings. - */ -#define STM32_I2S_USE_SPI2 FALSE -#define STM32_I2S_USE_SPI3 FALSE -#define STM32_I2S_SPI2_IRQ_PRIORITY 10 -#define STM32_I2S_SPI3_IRQ_PRIORITY 10 -#define STM32_I2S_SPI2_DMA_PRIORITY 1 -#define STM32_I2S_SPI3_DMA_PRIORITY 1 -#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) -#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") - -/* - * ICU driver system settings. - */ -#define STM32_ICU_USE_TIM1 FALSE -#define STM32_ICU_USE_TIM2 FALSE -#define STM32_ICU_USE_TIM3 FALSE -#define STM32_ICU_USE_TIM4 FALSE -#define STM32_ICU_USE_TIM5 FALSE -#define STM32_ICU_USE_TIM9 FALSE -#define STM32_ICU_TIM1_IRQ_PRIORITY 7 -#define STM32_ICU_TIM2_IRQ_PRIORITY 7 -#define STM32_ICU_TIM3_IRQ_PRIORITY 7 -#define STM32_ICU_TIM4_IRQ_PRIORITY 7 -#define STM32_ICU_TIM5_IRQ_PRIORITY 7 -#define STM32_ICU_TIM9_IRQ_PRIORITY 7 - -/* - * PWM driver system settings. - */ -#define STM32_PWM_USE_ADVANCED FALSE -#define STM32_PWM_USE_TIM1 FALSE -#define STM32_PWM_USE_TIM2 FALSE -#define STM32_PWM_USE_TIM3 FALSE -#define STM32_PWM_USE_TIM4 FALSE -#define STM32_PWM_USE_TIM5 FALSE -#define STM32_PWM_USE_TIM9 FALSE -#define STM32_PWM_TIM1_IRQ_PRIORITY 7 -#define STM32_PWM_TIM2_IRQ_PRIORITY 7 -#define STM32_PWM_TIM3_IRQ_PRIORITY 7 -#define STM32_PWM_TIM4_IRQ_PRIORITY 7 -#define STM32_PWM_TIM5_IRQ_PRIORITY 7 -#define STM32_PWM_TIM9_IRQ_PRIORITY 7 - -/* - * SERIAL driver system settings. - */ -#define STM32_SERIAL_USE_USART1 FALSE -#define STM32_SERIAL_USE_USART2 FALSE -#define STM32_SERIAL_USE_USART6 FALSE -#define STM32_SERIAL_USART1_PRIORITY 12 -#define STM32_SERIAL_USART2_PRIORITY 12 -#define STM32_SERIAL_USART6_PRIORITY 12 - -/* - * SPI driver system settings. - */ -#define STM32_SPI_USE_SPI1 FALSE -#define STM32_SPI_USE_SPI2 FALSE -#define STM32_SPI_USE_SPI3 FALSE -#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) -#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) -#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) -#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_SPI_SPI1_DMA_PRIORITY 1 -#define STM32_SPI_SPI2_DMA_PRIORITY 1 -#define STM32_SPI_SPI3_DMA_PRIORITY 1 -#define STM32_SPI_SPI1_IRQ_PRIORITY 10 -#define STM32_SPI_SPI2_IRQ_PRIORITY 10 -#define STM32_SPI_SPI3_IRQ_PRIORITY 10 -#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") - -/* - * ST driver system settings. - */ -#define STM32_ST_IRQ_PRIORITY 8 -#define STM32_ST_USE_TIMER 2 - -/* - * UART driver system settings. - */ -#define STM32_UART_USE_USART1 FALSE -#define STM32_UART_USE_USART2 FALSE -#define STM32_UART_USE_USART6 FALSE -#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) -#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) -#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) -#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) -#define STM32_UART_USART1_IRQ_PRIORITY 12 -#define STM32_UART_USART2_IRQ_PRIORITY 12 -#define STM32_UART_USART6_IRQ_PRIORITY 12 -#define STM32_UART_USART1_DMA_PRIORITY 0 -#define STM32_UART_USART2_DMA_PRIORITY 0 -#define STM32_UART_USART6_DMA_PRIORITY 0 -#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") - -/* - * USB driver system settings. - */ -#define STM32_USB_USE_OTG1 TRUE -#define STM32_USB_OTG1_IRQ_PRIORITY 14 -#define STM32_USB_OTG1_RX_FIFO_SIZE 512 -#define STM32_USB_OTG_THREAD_PRIO NORMALPRIO+1 -#define STM32_USB_OTG_THREAD_STACK_SIZE 128 -#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 - -/* - * WDG driver system settings. - */ -#define STM32_WDG_USE_IWDG FALSE - -#endif /* MCUCONF_H */ diff --git a/platforms/chibios/BLACKPILL_STM32_F411/ld/STM32F411xC_tinyuf2.ld b/platforms/chibios/BLACKPILL_STM32_F411/ld/STM32F411xC_tinyuf2.ld deleted file mode 100644 index 82253d3de5..0000000000 --- a/platforms/chibios/BLACKPILL_STM32_F411/ld/STM32F411xC_tinyuf2.ld +++ /dev/null @@ -1,89 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - 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 License 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. -*/ - -/* - * STM32F411xC memory setup. - */ -MEMORY -{ - flash0 (rx) : org = 0x08000000 + 64k, len = 256k - 64k /* tinyuf2 bootloader requires app to be located at 64k offset for this MCU */ - flash1 (rx) : org = 0x00000000, len = 0 - flash2 (rx) : org = 0x00000000, len = 0 - flash3 (rx) : org = 0x00000000, len = 0 - flash4 (rx) : org = 0x00000000, len = 0 - flash5 (rx) : org = 0x00000000, len = 0 - flash6 (rx) : org = 0x00000000, len = 0 - flash7 (rx) : org = 0x00000000, len = 0 - ram0 (wx) : org = 0x20000000, len = 128k - ram1 (wx) : org = 0x00000000, len = 0 - ram2 (wx) : org = 0x00000000, len = 0 - ram3 (wx) : org = 0x00000000, len = 0 - ram4 (wx) : org = 0x00000000, len = 0 - ram5 (wx) : org = 0x00000000, len = 0 - ram6 (wx) : org = 0x00000000, len = 0 - ram7 (wx) : org = 0x00000000, len = 0 -} - -/* For each data/text section two region are defined, a virtual region - and a load region (_LMA suffix).*/ - -/* Flash region to be used for exception vectors.*/ -REGION_ALIAS("VECTORS_FLASH", flash0); -REGION_ALIAS("VECTORS_FLASH_LMA", flash0); - -/* Flash region to be used for constructors and destructors.*/ -REGION_ALIAS("XTORS_FLASH", flash0); -REGION_ALIAS("XTORS_FLASH_LMA", flash0); - -/* Flash region to be used for code text.*/ -REGION_ALIAS("TEXT_FLASH", flash0); -REGION_ALIAS("TEXT_FLASH_LMA", flash0); - -/* Flash region to be used for read only data.*/ -REGION_ALIAS("RODATA_FLASH", flash0); -REGION_ALIAS("RODATA_FLASH_LMA", flash0); - -/* Flash region to be used for various.*/ -REGION_ALIAS("VARIOUS_FLASH", flash0); -REGION_ALIAS("VARIOUS_FLASH_LMA", flash0); - -/* Flash region to be used for RAM(n) initialization data.*/ -REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0); - -/* RAM region to be used for Main stack. This stack accommodates the processing - of all exceptions and interrupts.*/ -REGION_ALIAS("MAIN_STACK_RAM", ram0); - -/* RAM region to be used for the process stack. This is the stack used by - the main() function.*/ -REGION_ALIAS("PROCESS_STACK_RAM", ram0); - -/* RAM region to be used for data segment.*/ -REGION_ALIAS("DATA_RAM", ram0); -REGION_ALIAS("DATA_RAM_LMA", flash0); - -/* RAM region to be used for BSS segment.*/ -REGION_ALIAS("BSS_RAM", ram0); - -/* RAM region to be used for the default heap.*/ -REGION_ALIAS("HEAP_RAM", ram0); - -/* Generic rules inclusion.*/ -INCLUDE rules.ld - -/* TinyUF2 bootloader reset support */ -_board_dfu_dbl_tap = ORIGIN(ram0) + 64k - 4; /* this is based off the linker file for tinyuf2 */ - diff --git a/platforms/chibios/BLACKPILL_STM32_F411/ld/STM32F411xE_tinyuf2.ld b/platforms/chibios/BLACKPILL_STM32_F411/ld/STM32F411xE_tinyuf2.ld deleted file mode 100644 index 1656c67bf7..0000000000 --- a/platforms/chibios/BLACKPILL_STM32_F411/ld/STM32F411xE_tinyuf2.ld +++ /dev/null @@ -1,89 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - 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 License 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. -*/ - -/* - * STM32F411xE memory setup. - */ -MEMORY -{ - flash0 (rx) : org = 0x08000000 + 64k, len = 512k - 64k /* tinyuf2 bootloader requires app to be located at 64k offset for this MCU */ - flash1 (rx) : org = 0x00000000, len = 0 - flash2 (rx) : org = 0x00000000, len = 0 - flash3 (rx) : org = 0x00000000, len = 0 - flash4 (rx) : org = 0x00000000, len = 0 - flash5 (rx) : org = 0x00000000, len = 0 - flash6 (rx) : org = 0x00000000, len = 0 - flash7 (rx) : org = 0x00000000, len = 0 - ram0 (wx) : org = 0x20000000, len = 128k - ram1 (wx) : org = 0x00000000, len = 0 - ram2 (wx) : org = 0x00000000, len = 0 - ram3 (wx) : org = 0x00000000, len = 0 - ram4 (wx) : org = 0x00000000, len = 0 - ram5 (wx) : org = 0x00000000, len = 0 - ram6 (wx) : org = 0x00000000, len = 0 - ram7 (wx) : org = 0x00000000, len = 0 -} - -/* For each data/text section two region are defined, a virtual region - and a load region (_LMA suffix).*/ - -/* Flash region to be used for exception vectors.*/ -REGION_ALIAS("VECTORS_FLASH", flash0); -REGION_ALIAS("VECTORS_FLASH_LMA", flash0); - -/* Flash region to be used for constructors and destructors.*/ -REGION_ALIAS("XTORS_FLASH", flash0); -REGION_ALIAS("XTORS_FLASH_LMA", flash0); - -/* Flash region to be used for code text.*/ -REGION_ALIAS("TEXT_FLASH", flash0); -REGION_ALIAS("TEXT_FLASH_LMA", flash0); - -/* Flash region to be used for read only data.*/ -REGION_ALIAS("RODATA_FLASH", flash0); -REGION_ALIAS("RODATA_FLASH_LMA", flash0); - -/* Flash region to be used for various.*/ -REGION_ALIAS("VARIOUS_FLASH", flash0); -REGION_ALIAS("VARIOUS_FLASH_LMA", flash0); - -/* Flash region to be used for RAM(n) initialization data.*/ -REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0); - -/* RAM region to be used for Main stack. This stack accommodates the processing - of all exceptions and interrupts.*/ -REGION_ALIAS("MAIN_STACK_RAM", ram0); - -/* RAM region to be used for the process stack. This is the stack used by - the main() function.*/ -REGION_ALIAS("PROCESS_STACK_RAM", ram0); - -/* RAM region to be used for data segment.*/ -REGION_ALIAS("DATA_RAM", ram0); -REGION_ALIAS("DATA_RAM_LMA", flash0); - -/* RAM region to be used for BSS segment.*/ -REGION_ALIAS("BSS_RAM", ram0); - -/* RAM region to be used for the default heap.*/ -REGION_ALIAS("HEAP_RAM", ram0); - -/* Generic rules inclusion.*/ -INCLUDE rules.ld - -/* TinyUF2 bootloader reset support */ -_board_dfu_dbl_tap = ORIGIN(ram0) + 64k - 4; /* this is based off the linker file for tinyuf2 */ - diff --git a/platforms/chibios/GENERIC_STM32_F042X6/board/board.c b/platforms/chibios/GENERIC_STM32_F042X6/board/board.c deleted file mode 100644 index 0d7c88756a..0000000000 --- a/platforms/chibios/GENERIC_STM32_F042X6/board/board.c +++ /dev/null @@ -1,265 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - 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 License 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. -*/ - -/* - * This file has been automatically generated using ChibiStudio board - * generator plugin. Do not edit manually. - */ - -#include -#include - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/** - * @brief Type of STM32 GPIO port setup. - */ -typedef struct { - uint32_t moder; - uint32_t otyper; - uint32_t ospeedr; - uint32_t pupdr; - uint32_t odr; - uint32_t afrl; - uint32_t afrh; -} gpio_setup_t; - -/** - * @brief Type of STM32 GPIO initialization data. - */ -typedef struct { -#if STM32_HAS_GPIOA || defined(__DOXYGEN__) - gpio_setup_t PAData; -#endif -#if STM32_HAS_GPIOB || defined(__DOXYGEN__) - gpio_setup_t PBData; -#endif -#if STM32_HAS_GPIOC || defined(__DOXYGEN__) - gpio_setup_t PCData; -#endif -#if STM32_HAS_GPIOD || defined(__DOXYGEN__) - gpio_setup_t PDData; -#endif -#if STM32_HAS_GPIOE || defined(__DOXYGEN__) - gpio_setup_t PEData; -#endif -#if STM32_HAS_GPIOF || defined(__DOXYGEN__) - gpio_setup_t PFData; -#endif -#if STM32_HAS_GPIOG || defined(__DOXYGEN__) - gpio_setup_t PGData; -#endif -#if STM32_HAS_GPIOH || defined(__DOXYGEN__) - gpio_setup_t PHData; -#endif -#if STM32_HAS_GPIOI || defined(__DOXYGEN__) - gpio_setup_t PIData; -#endif -#if STM32_HAS_GPIOJ || defined(__DOXYGEN__) - gpio_setup_t PJData; -#endif -#if STM32_HAS_GPIOK || defined(__DOXYGEN__) - gpio_setup_t PKData; -#endif -} gpio_config_t; - -/** - * @brief STM32 GPIO static initialization data. - */ -static const gpio_config_t gpio_default_config = { -#if STM32_HAS_GPIOA - {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR, - VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH}, -#endif -#if STM32_HAS_GPIOB - {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR, - VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH}, -#endif -#if STM32_HAS_GPIOC - {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR, - VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH}, -#endif -#if STM32_HAS_GPIOD - {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR, - VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH}, -#endif -#if STM32_HAS_GPIOE - {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR, - VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH}, -#endif -#if STM32_HAS_GPIOF - {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR, - VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH}, -#endif -#if STM32_HAS_GPIOG - {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR, - VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH}, -#endif -#if STM32_HAS_GPIOH - {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR, - VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH}, -#endif -#if STM32_HAS_GPIOI - {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR, - VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH}, -#endif -#if STM32_HAS_GPIOJ - {VAL_GPIOJ_MODER, VAL_GPIOJ_OTYPER, VAL_GPIOJ_OSPEEDR, VAL_GPIOJ_PUPDR, - VAL_GPIOJ_ODR, VAL_GPIOJ_AFRL, VAL_GPIOJ_AFRH}, -#endif -#if STM32_HAS_GPIOK - {VAL_GPIOK_MODER, VAL_GPIOK_OTYPER, VAL_GPIOK_OSPEEDR, VAL_GPIOK_PUPDR, - VAL_GPIOK_ODR, VAL_GPIOK_AFRL, VAL_GPIOK_AFRH} -#endif -}; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -static void gpio_init(stm32_gpio_t *gpiop, const gpio_setup_t *config) { - - gpiop->OTYPER = config->otyper; - gpiop->OSPEEDR = config->ospeedr; - gpiop->PUPDR = config->pupdr; - gpiop->ODR = config->odr; - gpiop->AFRL = config->afrl; - gpiop->AFRH = config->afrh; - gpiop->MODER = config->moder; -} - -static void stm32_gpio_init(void) { - - /* Enabling GPIO-related clocks, the mask comes from the - registry header file.*/ - rccResetAHB(STM32_GPIO_EN_MASK); - rccEnableAHB(STM32_GPIO_EN_MASK, true); - - /* Initializing all the defined GPIO ports.*/ -#if STM32_HAS_GPIOA - gpio_init(GPIOA, &gpio_default_config.PAData); -#endif -#if STM32_HAS_GPIOB - gpio_init(GPIOB, &gpio_default_config.PBData); -#endif -#if STM32_HAS_GPIOC - gpio_init(GPIOC, &gpio_default_config.PCData); -#endif -#if STM32_HAS_GPIOD - gpio_init(GPIOD, &gpio_default_config.PDData); -#endif -#if STM32_HAS_GPIOE - gpio_init(GPIOE, &gpio_default_config.PEData); -#endif -#if STM32_HAS_GPIOF - gpio_init(GPIOF, &gpio_default_config.PFData); -#endif -#if STM32_HAS_GPIOG - gpio_init(GPIOG, &gpio_default_config.PGData); -#endif -#if STM32_HAS_GPIOH - gpio_init(GPIOH, &gpio_default_config.PHData); -#endif -#if STM32_HAS_GPIOI - gpio_init(GPIOI, &gpio_default_config.PIData); -#endif -#if STM32_HAS_GPIOJ - gpio_init(GPIOJ, &gpio_default_config.PJData); -#endif -#if STM32_HAS_GPIOK - gpio_init(GPIOK, &gpio_default_config.PKData); -#endif -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Early initialization code. - * @details GPIO ports and system clocks are initialized before everything - * else. - */ -void __early_init(void) { - stm32_gpio_init(); - stm32_clock_init(); -} - -#if HAL_USE_SDC || defined(__DOXYGEN__) -/** - * @brief SDC card detection. - */ -bool sdc_lld_is_card_inserted(SDCDriver *sdcp) { - - (void)sdcp; - /* TODO: Fill the implementation.*/ - return true; -} - -/** - * @brief SDC card write protection detection. - */ -bool sdc_lld_is_write_protected(SDCDriver *sdcp) { - - (void)sdcp; - /* TODO: Fill the implementation.*/ - return false; -} -#endif /* HAL_USE_SDC */ - -#if HAL_USE_MMC_SPI || defined(__DOXYGEN__) -/** - * @brief MMC_SPI card detection. - */ -bool mmc_lld_is_card_inserted(MMCDriver *mmcp) { - - (void)mmcp; - /* TODO: Fill the implementation.*/ - return true; -} - -/** - * @brief MMC_SPI card write protection detection. - */ -bool mmc_lld_is_write_protected(MMCDriver *mmcp) { - - (void)mmcp; - /* TODO: Fill the implementation.*/ - return false; -} -#endif - -/** - * @brief Board-specific initialization code. - * @todo Add your board-specific code, if any. - */ -void boardInit(void) { - -} diff --git a/platforms/chibios/GENERIC_STM32_F042X6/board/board.h b/platforms/chibios/GENERIC_STM32_F042X6/board/board.h deleted file mode 100644 index ee9d31e04a..0000000000 --- a/platforms/chibios/GENERIC_STM32_F042X6/board/board.h +++ /dev/null @@ -1,896 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - 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 License 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. -*/ -#ifndef _BOARD_H -#define _BOARD_H - -/* - * Setup for STMicroelectronics STM32 Nucleo32-F042K6 board. - */ - -/* - * Board identifier. - */ -#define BOARD_GENERIC_STM32_F042X6 -#define BOARD_NAME "Generic STM32F042 PCB" - -/* - * Board oscillators-related settings. - * NOTE: LSE not fitted. - * NOTE: HSE not fitted. - */ -#if !defined(STM32_LSECLK) -#define STM32_LSECLK 0U -#endif - -#define STM32_LSEDRV (3U << 3U) - -#if !defined(STM32_HSECLK) -#define STM32_HSECLK 0U -#endif - -/* - * MCU type as defined in the ST header. - */ -#define STM32F042x6 - -/* - * IO pins assignments. - */ -#define GPIOA_PIN0 0U -#define GPIOA_PIN1 1U -#define GPIOA_PIN2 2U -#define GPIOA_PIN3 3U -#define GPIOA_PIN4 4U -#define GPIOA_PIN5 5U -#define GPIOA_PIN6 6U -#define GPIOA_PIN7 7U -#define GPIOA_PIN8 8U -#define GPIOA_PIN9 9U -#define GPIOA_PIN10 10U -#define GPIOA_PIN11 11U -#define GPIOA_PIN12 12U -#define GPIOA_PIN13 13U -#define GPIOA_PIN14 14U -#define GPIOA_PIN15 15U - -#define GPIOB_PIN0 0U -#define GPIOB_PIN1 1U -#define GPIOB_PIN2 2U -#define GPIOB_PIN3 3U -#define GPIOB_PIN4 4U -#define GPIOB_PIN5 5U -#define GPIOB_PIN6 6U -#define GPIOB_PIN7 7U -#define GPIOB_PIN8 8U -#define GPIOB_PIN9 9U -#define GPIOB_PIN10 10U -#define GPIOB_PIN11 11U -#define GPIOB_PIN12 12U -#define GPIOB_PIN13 13U -#define GPIOB_PIN14 14U -#define GPIOB_PIN15 15U - -#define GPIOC_PIN0 0U -#define GPIOC_PIN1 1U -#define GPIOC_PIN2 2U -#define GPIOC_PIN3 3U -#define GPIOC_PIN4 4U -#define GPIOC_PIN5 5U -#define GPIOC_PIN6 6U -#define GPIOC_PIN7 7U -#define GPIOC_PIN8 8U -#define GPIOC_PIN9 9U -#define GPIOC_PIN10 10U -#define GPIOC_PIN11 11U -#define GPIOC_PIN12 12U -#define GPIOC_PIN13 13U -#define GPIOC_PIN14 14U -#define GPIOC_PIN15 15U - -#define GPIOD_PIN0 0U -#define GPIOD_PIN1 1U -#define GPIOD_PIN2 2U -#define GPIOD_PIN3 3U -#define GPIOD_PIN4 4U -#define GPIOD_PIN5 5U -#define GPIOD_PIN6 6U -#define GPIOD_PIN7 7U -#define GPIOD_PIN8 8U -#define GPIOD_PIN9 9U -#define GPIOD_PIN10 10U -#define GPIOD_PIN11 11U -#define GPIOD_PIN12 12U -#define GPIOD_PIN13 13U -#define GPIOD_PIN14 14U -#define GPIOD_PIN15 15U - -#define GPIOE_PIN0 0U -#define GPIOE_PIN1 1U -#define GPIOE_PIN2 2U -#define GPIOE_PIN3 3U -#define GPIOE_PIN4 4U -#define GPIOE_PIN5 5U -#define GPIOE_PIN6 6U -#define GPIOE_PIN7 7U -#define GPIOE_PIN8 8U -#define GPIOE_PIN9 9U -#define GPIOE_PIN10 10U -#define GPIOE_PIN11 11U -#define GPIOE_PIN12 12U -#define GPIOE_PIN13 13U -#define GPIOE_PIN14 14U -#define GPIOE_PIN15 15U - -#define GPIOF_PIN0 0U -#define GPIOF_PIN1 1U -#define GPIOF_PIN2 2U -#define GPIOF_PIN3 3U -#define GPIOF_PIN4 4U -#define GPIOF_PIN5 5U -#define GPIOF_PIN6 6U -#define GPIOF_PIN7 7U -#define GPIOF_PIN8 8U -#define GPIOF_PIN9 9U -#define GPIOF_PIN10 10U -#define GPIOF_PIN11 11U -#define GPIOF_PIN12 12U -#define GPIOF_PIN13 13U -#define GPIOF_PIN14 14U -#define GPIOF_PIN15 15U - -/* - * IO lines assignments. - */ - -#define LINE_BOOT0 PAL_LINE(GPIOB, 8U) -#define LINE_SWCLK PAL_LINE(GPIOA, 14U) -#define LINE_SWDIO PAL_LINE(GPIOA, 13U) - -/* - * I/O ports initial setup, this configuration is established soon after reset - * in the initialization code. - * Please refer to the STM32 Reference Manual for details. - */ -#define PIN_MODE_INPUT(n) (0U << ((n) * 2U)) -#define PIN_MODE_OUTPUT(n) (1U << ((n) * 2U)) -#define PIN_MODE_ALTERNATE(n) (2U << ((n) * 2U)) -#define PIN_MODE_ANALOG(n) (3U << ((n) * 2U)) -#define PIN_ODR_LOW(n) (0U << (n)) -#define PIN_ODR_HIGH(n) (1U << (n)) -#define PIN_OTYPE_PUSHPULL(n) (0U << (n)) -#define PIN_OTYPE_OPENDRAIN(n) (1U << (n)) -#define PIN_OSPEED_VERYLOW(n) (0U << ((n) * 2U)) -#define PIN_OSPEED_LOW(n) (1U << ((n) * 2U)) -#define PIN_OSPEED_MEDIUM(n) (2U << ((n) * 2U)) -#define PIN_OSPEED_HIGH(n) (3U << ((n) * 2U)) -#define PIN_PUPDR_FLOATING(n) (0U << ((n) * 2U)) -#define PIN_PUPDR_PULLUP(n) (1U << ((n) * 2U)) -#define PIN_PUPDR_PULLDOWN(n) (2U << ((n) * 2U)) -#define PIN_AFIO_AF(n, v) ((v) << (((n) % 8U) * 4U)) - -/* - * GPIOA setup: - * - * PA0 - COL5 - * PA1 - COL4 - * PA2 - COL3 - * PA3 - COL2 - * PA4 - COL1 - * PA5 - COL0 - * PA6 - ROW4 - * PA7 - ROW3 - * PA8 - NC - * PA9 - ROW1 - * PA10 - ROW0 - * PA11 - USB_DM - * PA12 - USB_DP - * PA13 - COL15/SWDIO (for now, COL15) - * PA14 - COL14/SWCLK (for now, COL14) - * PA15 - COL13 - */ -#define VAL_GPIOA_MODER (PIN_MODE_INPUT(GPIOA_PIN0) | \ - PIN_MODE_INPUT(GPIOA_PIN1) | \ - PIN_MODE_INPUT(GPIOA_PIN2) | \ - PIN_MODE_INPUT(GPIOA_PIN3) | \ - PIN_MODE_INPUT(GPIOA_PIN4) | \ - PIN_MODE_INPUT(GPIOA_PIN5) | \ - PIN_MODE_INPUT(GPIOA_PIN6) | \ - PIN_MODE_INPUT(GPIOA_PIN7) | \ - PIN_MODE_INPUT(GPIOA_PIN8) | \ - PIN_MODE_INPUT(GPIOA_PIN9) | \ - PIN_MODE_INPUT(GPIOA_PIN10) | \ - PIN_MODE_INPUT(GPIOA_PIN11) | \ - PIN_MODE_INPUT(GPIOA_PIN12) | \ - PIN_MODE_INPUT(GPIOA_PIN13) | \ - PIN_MODE_INPUT(GPIOA_PIN14) | \ - PIN_MODE_INPUT(GPIOA_PIN15)) -#define VAL_GPIOA_OTYPER (PIN_OTYPE_PUSHPULL(GPIOA_PIN0) | \ - PIN_OTYPE_PUSHPULL(GPIOA_PIN1) | \ - PIN_OTYPE_PUSHPULL(GPIOA_PIN2) | \ - PIN_OTYPE_PUSHPULL(GPIOA_PIN3) | \ - PIN_OTYPE_PUSHPULL(GPIOA_PIN4) | \ - PIN_OTYPE_PUSHPULL(GPIOA_PIN5) | \ - PIN_OTYPE_PUSHPULL(GPIOA_PIN6) | \ - PIN_OTYPE_PUSHPULL(GPIOA_PIN7) | \ - PIN_OTYPE_PUSHPULL(GPIOA_PIN8) | \ - PIN_OTYPE_PUSHPULL(GPIOA_PIN9) | \ - PIN_OTYPE_PUSHPULL(GPIOA_PIN10) | \ - PIN_OTYPE_PUSHPULL(GPIOA_PIN11) | \ - PIN_OTYPE_PUSHPULL(GPIOA_PIN12) | \ - PIN_OTYPE_PUSHPULL(GPIOA_PIN13) | \ - PIN_OTYPE_PUSHPULL(GPIOA_PIN14) | \ - PIN_OTYPE_PUSHPULL(GPIOA_PIN15)) -#define VAL_GPIOA_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOA_PIN0) | \ - PIN_OSPEED_VERYLOW(GPIOA_PIN1) | \ - PIN_OSPEED_VERYLOW(GPIOA_PIN2) | \ - PIN_OSPEED_VERYLOW(GPIOA_PIN3) | \ - PIN_OSPEED_VERYLOW(GPIOA_PIN4) | \ - PIN_OSPEED_VERYLOW(GPIOA_PIN5) | \ - PIN_OSPEED_VERYLOW(GPIOA_PIN6) | \ - PIN_OSPEED_VERYLOW(GPIOA_PIN7) | \ - PIN_OSPEED_VERYLOW(GPIOA_PIN8) | \ - PIN_OSPEED_VERYLOW(GPIOA_PIN9) | \ - PIN_OSPEED_VERYLOW(GPIOA_PIN10) | \ - PIN_OSPEED_HIGH(GPIOA_PIN11) | \ - PIN_OSPEED_VERYLOW(GPIOA_PIN12) | \ - PIN_OSPEED_VERYLOW(GPIOA_PIN13) | \ - PIN_OSPEED_VERYLOW(GPIOA_PIN14) | \ - PIN_OSPEED_VERYLOW(GPIOA_PIN15)) -#define VAL_GPIOA_PUPDR (PIN_PUPDR_PULLUP(GPIOA_PIN0) | \ - PIN_PUPDR_PULLUP(GPIOA_PIN1) | \ - PIN_PUPDR_PULLUP(GPIOA_PIN2) | \ - PIN_PUPDR_PULLUP(GPIOA_PIN3) | \ - PIN_PUPDR_PULLUP(GPIOA_PIN4) | \ - PIN_PUPDR_PULLUP(GPIOA_PIN5) | \ - PIN_PUPDR_PULLUP(GPIOA_PIN6) | \ - PIN_PUPDR_PULLUP(GPIOA_PIN7) | \ - PIN_PUPDR_PULLUP(GPIOA_PIN8) | \ - PIN_PUPDR_PULLUP(GPIOA_PIN9) | \ - PIN_PUPDR_PULLUP(GPIOA_PIN10) | \ - PIN_PUPDR_FLOATING(GPIOA_PIN11) | \ - PIN_PUPDR_FLOATING(GPIOA_PIN12) | \ - PIN_PUPDR_PULLUP(GPIOA_PIN13) | \ - PIN_PUPDR_PULLUP(GPIOA_PIN14) | \ - PIN_PUPDR_PULLUP(GPIOA_PIN15)) -#define VAL_GPIOA_ODR (PIN_ODR_HIGH(GPIOA_PIN0) | \ - PIN_ODR_HIGH(GPIOA_PIN1) | \ - PIN_ODR_HIGH(GPIOA_PIN2) | \ - PIN_ODR_HIGH(GPIOA_PIN3) | \ - PIN_ODR_HIGH(GPIOA_PIN4) | \ - PIN_ODR_HIGH(GPIOA_PIN5) | \ - PIN_ODR_HIGH(GPIOA_PIN6) | \ - PIN_ODR_HIGH(GPIOA_PIN7) | \ - PIN_ODR_HIGH(GPIOA_PIN8) | \ - PIN_ODR_HIGH(GPIOA_PIN9) | \ - PIN_ODR_HIGH(GPIOA_PIN10) | \ - PIN_ODR_HIGH(GPIOA_PIN11) | \ - PIN_ODR_HIGH(GPIOA_PIN12) | \ - PIN_ODR_HIGH(GPIOA_PIN13) | \ - PIN_ODR_HIGH(GPIOA_PIN14) | \ - PIN_ODR_HIGH(GPIOA_PIN15)) -#define VAL_GPIOA_AFRL (PIN_AFIO_AF(GPIOA_PIN0, 0U) | \ - PIN_AFIO_AF(GPIOA_PIN1, 0U) | \ - PIN_AFIO_AF(GPIOA_PIN2, 0U) | \ - PIN_AFIO_AF(GPIOA_PIN3, 0U) | \ - PIN_AFIO_AF(GPIOA_PIN4, 0U) | \ - PIN_AFIO_AF(GPIOA_PIN5, 0U) | \ - PIN_AFIO_AF(GPIOA_PIN6, 0U) | \ - PIN_AFIO_AF(GPIOA_PIN7, 0U)) -#define VAL_GPIOA_AFRH (PIN_AFIO_AF(GPIOA_PIN8, 0U) | \ - PIN_AFIO_AF(GPIOA_PIN9, 0U) | \ - PIN_AFIO_AF(GPIOA_PIN10, 0U) | \ - PIN_AFIO_AF(GPIOA_PIN11, 0U) | \ - PIN_AFIO_AF(GPIOA_PIN12, 0U) | \ - PIN_AFIO_AF(GPIOA_PIN13, 0U) | \ - PIN_AFIO_AF(GPIOA_PIN14, 0U) | \ - PIN_AFIO_AF(GPIOA_PIN15, 0U)) - -/* - * GPIOB setup: - * - * PB0 - ROW2 - * PB1 - RGB_D - * PB2 - PIN2 (input pullup). - * PB3 - COL12 - * PB4 - COL11 - * PB5 - COL10 - * PB6 - COL9 - * PB7 - COL8 - * PB8 - BOOT0 (set as output for STM32F042) - * PB9 - PIN9 (input pullup). - * PB10 - PIN10 (input pullup). - * PB11 - PIN11 (input pullup). - * PB12 - PIN12 (input pullup). - * PB13 - PIN13 (input pullup). - * PB14 - PIN14 (input pullup). - * PB15 - PIN15 (input pullup). - */ -#define VAL_GPIOB_MODER (PIN_MODE_INPUT(GPIOB_PIN0) | \ - PIN_MODE_OUTPUT(GPIOB_PIN1) | \ - PIN_MODE_INPUT(GPIOB_PIN2) | \ - PIN_MODE_INPUT(GPIOB_PIN3) | \ - PIN_MODE_INPUT(GPIOB_PIN4) | \ - PIN_MODE_INPUT(GPIOB_PIN5) | \ - PIN_MODE_INPUT(GPIOB_PIN6) | \ - PIN_MODE_INPUT(GPIOB_PIN7) | \ - PIN_MODE_OUTPUT(GPIOB_PIN8) | \ - PIN_MODE_INPUT(GPIOB_PIN9) | \ - PIN_MODE_INPUT(GPIOB_PIN10) | \ - PIN_MODE_INPUT(GPIOB_PIN11) | \ - PIN_MODE_INPUT(GPIOB_PIN12) | \ - PIN_MODE_INPUT(GPIOB_PIN13) | \ - PIN_MODE_INPUT(GPIOB_PIN14) | \ - PIN_MODE_INPUT(GPIOB_PIN15)) -#define VAL_GPIOB_OTYPER (PIN_OTYPE_PUSHPULL(GPIOB_PIN0) | \ - PIN_OTYPE_PUSHPULL(GPIOB_PIN1) | \ - PIN_OTYPE_PUSHPULL(GPIOB_PIN2) | \ - PIN_OTYPE_PUSHPULL(GPIOB_PIN3) | \ - PIN_OTYPE_PUSHPULL(GPIOB_PIN4) | \ - PIN_OTYPE_PUSHPULL(GPIOB_PIN5) | \ - PIN_OTYPE_PUSHPULL(GPIOB_PIN6) | \ - PIN_OTYPE_PUSHPULL(GPIOB_PIN7) | \ - PIN_OTYPE_PUSHPULL(GPIOB_PIN8) | \ - PIN_OTYPE_PUSHPULL(GPIOB_PIN9) | \ - PIN_OTYPE_PUSHPULL(GPIOB_PIN10) | \ - PIN_OTYPE_PUSHPULL(GPIOB_PIN11) | \ - PIN_OTYPE_PUSHPULL(GPIOB_PIN12) | \ - PIN_OTYPE_PUSHPULL(GPIOB_PIN13) | \ - PIN_OTYPE_PUSHPULL(GPIOB_PIN14) | \ - PIN_OTYPE_PUSHPULL(GPIOB_PIN15)) -#define VAL_GPIOB_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOB_PIN0) | \ - PIN_OSPEED_HIGH(GPIOB_PIN1) | \ - PIN_OSPEED_HIGH(GPIOB_PIN2) | \ - PIN_OSPEED_VERYLOW(GPIOB_PIN3) | \ - PIN_OSPEED_VERYLOW(GPIOB_PIN4) | \ - PIN_OSPEED_VERYLOW(GPIOB_PIN5) | \ - PIN_OSPEED_VERYLOW(GPIOB_PIN6) | \ - PIN_OSPEED_VERYLOW(GPIOB_PIN7) | \ - PIN_OSPEED_VERYLOW(GPIOB_PIN8) | \ - PIN_OSPEED_HIGH(GPIOB_PIN9) | \ - PIN_OSPEED_HIGH(GPIOB_PIN10) | \ - PIN_OSPEED_HIGH(GPIOB_PIN11) | \ - PIN_OSPEED_HIGH(GPIOB_PIN12) | \ - PIN_OSPEED_HIGH(GPIOB_PIN13) | \ - PIN_OSPEED_HIGH(GPIOB_PIN14) | \ - PIN_OSPEED_HIGH(GPIOB_PIN15)) -#define VAL_GPIOB_PUPDR (PIN_PUPDR_PULLUP(GPIOB_PIN0) | \ - PIN_PUPDR_FLOATING(GPIOB_PIN1) | \ - PIN_PUPDR_PULLUP(GPIOB_PIN2) | \ - PIN_PUPDR_PULLUP(GPIOB_PIN3) | \ - PIN_PUPDR_PULLUP(GPIOB_PIN4) | \ - PIN_PUPDR_PULLUP(GPIOB_PIN5) | \ - PIN_PUPDR_PULLUP(GPIOB_PIN6) | \ - PIN_PUPDR_PULLUP(GPIOB_PIN7) | \ - PIN_PUPDR_PULLDOWN(GPIOB_PIN8) | \ - PIN_PUPDR_PULLUP(GPIOB_PIN9) | \ - PIN_PUPDR_PULLUP(GPIOB_PIN10) | \ - PIN_PUPDR_PULLUP(GPIOB_PIN11) | \ - PIN_PUPDR_PULLUP(GPIOB_PIN12) | \ - PIN_PUPDR_PULLUP(GPIOB_PIN13) | \ - PIN_PUPDR_PULLUP(GPIOB_PIN14) | \ - PIN_PUPDR_PULLUP(GPIOB_PIN15)) -#define VAL_GPIOB_ODR (PIN_ODR_HIGH(GPIOB_PIN0) | \ - PIN_ODR_HIGH(GPIOB_PIN1) | \ - PIN_ODR_HIGH(GPIOB_PIN2) | \ - PIN_ODR_HIGH(GPIOB_PIN3) | \ - PIN_ODR_HIGH(GPIOB_PIN4) | \ - PIN_ODR_HIGH(GPIOB_PIN5) | \ - PIN_ODR_HIGH(GPIOB_PIN6) | \ - PIN_ODR_HIGH(GPIOB_PIN7) | \ - PIN_ODR_HIGH(GPIOB_PIN8) | \ - PIN_ODR_HIGH(GPIOB_PIN9) | \ - PIN_ODR_HIGH(GPIOB_PIN10) | \ - PIN_ODR_HIGH(GPIOB_PIN11) | \ - PIN_ODR_HIGH(GPIOB_PIN12) | \ - PIN_ODR_HIGH(GPIOB_PIN13) | \ - PIN_ODR_HIGH(GPIOB_PIN14) | \ - PIN_ODR_HIGH(GPIOB_PIN15)) -#define VAL_GPIOB_AFRL (PIN_AFIO_AF(GPIOB_PIN0, 0U) | \ - PIN_AFIO_AF(GPIOB_PIN1, 0U) | \ - PIN_AFIO_AF(GPIOB_PIN2, 0U) | \ - PIN_AFIO_AF(GPIOB_PIN3, 0U) | \ - PIN_AFIO_AF(GPIOB_PIN4, 0U) | \ - PIN_AFIO_AF(GPIOB_PIN5, 0U) | \ - PIN_AFIO_AF(GPIOB_PIN6, 0U) | \ - PIN_AFIO_AF(GPIOB_PIN7, 0U)) -#define VAL_GPIOB_AFRH (PIN_AFIO_AF(GPIOB_PIN8, 0U) | \ - PIN_AFIO_AF(GPIOB_PIN9, 0U) | \ - PIN_AFIO_AF(GPIOB_PIN10, 0U) | \ - PIN_AFIO_AF(GPIOB_PIN11, 0U) | \ - PIN_AFIO_AF(GPIOB_PIN12, 0U) | \ - PIN_AFIO_AF(GPIOB_PIN13, 0U) | \ - PIN_AFIO_AF(GPIOB_PIN14, 0U) | \ - PIN_AFIO_AF(GPIOB_PIN15, 0U)) - -/* - * GPIOC setup: - * - * PC0 - PIN0 (input pullup). - * PC1 - PIN1 (input pullup). - * PC2 - PIN2 (input pullup). - * PC3 - PIN3 (input pullup). - * PC4 - PIN4 (input pullup). - * PC5 - PIN5 (input pullup). - * PC6 - PIN6 (input pullup). - * PC7 - PIN7 (input pullup). - * PC8 - PIN8 (input pullup). - * PC9 - PIN9 (input pullup). - * PC10 - PIN10 (input pullup). - * PC11 - PIN11 (input pullup). - * PC12 - PIN12 (input pullup). - * PC13 - PIN13 (input pullup). - * PC14 - PIN14 (input pullup). - * PC15 - PIN15 (input pullup). - */ -#define VAL_GPIOC_MODER (PIN_MODE_INPUT(GPIOC_PIN0) | \ - PIN_MODE_INPUT(GPIOC_PIN1) | \ - PIN_MODE_INPUT(GPIOC_PIN2) | \ - PIN_MODE_INPUT(GPIOC_PIN3) | \ - PIN_MODE_INPUT(GPIOC_PIN4) | \ - PIN_MODE_INPUT(GPIOC_PIN5) | \ - PIN_MODE_INPUT(GPIOC_PIN6) | \ - PIN_MODE_INPUT(GPIOC_PIN7) | \ - PIN_MODE_INPUT(GPIOC_PIN8) | \ - PIN_MODE_INPUT(GPIOC_PIN9) | \ - PIN_MODE_INPUT(GPIOC_PIN10) | \ - PIN_MODE_INPUT(GPIOC_PIN11) | \ - PIN_MODE_INPUT(GPIOC_PIN12) | \ - PIN_MODE_INPUT(GPIOC_PIN13) | \ - PIN_MODE_INPUT(GPIOC_PIN14) | \ - PIN_MODE_INPUT(GPIOC_PIN15)) -#define VAL_GPIOC_OTYPER (PIN_OTYPE_PUSHPULL(GPIOC_PIN0) | \ - PIN_OTYPE_PUSHPULL(GPIOC_PIN1) | \ - PIN_OTYPE_PUSHPULL(GPIOC_PIN2) | \ - PIN_OTYPE_PUSHPULL(GPIOC_PIN3) | \ - PIN_OTYPE_PUSHPULL(GPIOC_PIN4) | \ - PIN_OTYPE_PUSHPULL(GPIOC_PIN5) | \ - PIN_OTYPE_PUSHPULL(GPIOC_PIN6) | \ - PIN_OTYPE_PUSHPULL(GPIOC_PIN7) | \ - PIN_OTYPE_PUSHPULL(GPIOC_PIN8) | \ - PIN_OTYPE_PUSHPULL(GPIOC_PIN9) | \ - PIN_OTYPE_PUSHPULL(GPIOC_PIN10) | \ - PIN_OTYPE_PUSHPULL(GPIOC_PIN11) | \ - PIN_OTYPE_PUSHPULL(GPIOC_PIN12) | \ - PIN_OTYPE_PUSHPULL(GPIOC_PIN13) | \ - PIN_OTYPE_PUSHPULL(GPIOC_PIN14) | \ - PIN_OTYPE_PUSHPULL(GPIOC_PIN15)) -#define VAL_GPIOC_OSPEEDR (PIN_OSPEED_HIGH(GPIOC_PIN0) | \ - PIN_OSPEED_HIGH(GPIOC_PIN1) | \ - PIN_OSPEED_HIGH(GPIOC_PIN2) | \ - PIN_OSPEED_HIGH(GPIOC_PIN3) | \ - PIN_OSPEED_HIGH(GPIOC_PIN4) | \ - PIN_OSPEED_HIGH(GPIOC_PIN5) | \ - PIN_OSPEED_HIGH(GPIOC_PIN6) | \ - PIN_OSPEED_HIGH(GPIOC_PIN7) | \ - PIN_OSPEED_HIGH(GPIOC_PIN8) | \ - PIN_OSPEED_HIGH(GPIOC_PIN9) | \ - PIN_OSPEED_HIGH(GPIOC_PIN10) | \ - PIN_OSPEED_HIGH(GPIOC_PIN11) | \ - PIN_OSPEED_HIGH(GPIOC_PIN12) | \ - PIN_OSPEED_HIGH(GPIOC_PIN13) | \ - PIN_OSPEED_HIGH(GPIOC_PIN14) | \ - PIN_OSPEED_HIGH(GPIOC_PIN15)) -#define VAL_GPIOC_PUPDR (PIN_PUPDR_PULLUP(GPIOC_PIN0) | \ - PIN_PUPDR_PULLUP(GPIOC_PIN1) | \ - PIN_PUPDR_PULLUP(GPIOC_PIN2) | \ - PIN_PUPDR_PULLUP(GPIOC_PIN3) | \ - PIN_PUPDR_PULLUP(GPIOC_PIN4) | \ - PIN_PUPDR_PULLUP(GPIOC_PIN5) | \ - PIN_PUPDR_PULLUP(GPIOC_PIN6) | \ - PIN_PUPDR_PULLUP(GPIOC_PIN7) | \ - PIN_PUPDR_PULLUP(GPIOC_PIN8) | \ - PIN_PUPDR_PULLUP(GPIOC_PIN9) | \ - PIN_PUPDR_PULLUP(GPIOC_PIN10) | \ - PIN_PUPDR_PULLUP(GPIOC_PIN11) | \ - PIN_PUPDR_PULLUP(GPIOC_PIN12) | \ - PIN_PUPDR_PULLUP(GPIOC_PIN13) | \ - PIN_PUPDR_PULLUP(GPIOC_PIN14) | \ - PIN_PUPDR_PULLUP(GPIOC_PIN15)) -#define VAL_GPIOC_ODR (PIN_ODR_HIGH(GPIOC_PIN0) | \ - PIN_ODR_HIGH(GPIOC_PIN1) | \ - PIN_ODR_HIGH(GPIOC_PIN2) | \ - PIN_ODR_HIGH(GPIOC_PIN3) | \ - PIN_ODR_HIGH(GPIOC_PIN4) | \ - PIN_ODR_HIGH(GPIOC_PIN5) | \ - PIN_ODR_HIGH(GPIOC_PIN6) | \ - PIN_ODR_HIGH(GPIOC_PIN7) | \ - PIN_ODR_HIGH(GPIOC_PIN8) | \ - PIN_ODR_HIGH(GPIOC_PIN9) | \ - PIN_ODR_HIGH(GPIOC_PIN10) | \ - PIN_ODR_HIGH(GPIOC_PIN11) | \ - PIN_ODR_HIGH(GPIOC_PIN12) | \ - PIN_ODR_HIGH(GPIOC_PIN13) | \ - PIN_ODR_HIGH(GPIOC_PIN14) | \ - PIN_ODR_HIGH(GPIOC_PIN15)) -#define VAL_GPIOC_AFRL (PIN_AFIO_AF(GPIOC_PIN0, 0U) | \ - PIN_AFIO_AF(GPIOC_PIN1, 0U) | \ - PIN_AFIO_AF(GPIOC_PIN2, 0U) | \ - PIN_AFIO_AF(GPIOC_PIN3, 0U) | \ - PIN_AFIO_AF(GPIOC_PIN4, 0U) | \ - PIN_AFIO_AF(GPIOC_PIN5, 0U) | \ - PIN_AFIO_AF(GPIOC_PIN6, 0U) | \ - PIN_AFIO_AF(GPIOC_PIN7, 0U)) -#define VAL_GPIOC_AFRH (PIN_AFIO_AF(GPIOC_PIN8, 0U) | \ - PIN_AFIO_AF(GPIOC_PIN9, 0U) | \ - PIN_AFIO_AF(GPIOC_PIN10, 0U) | \ - PIN_AFIO_AF(GPIOC_PIN11, 0U) | \ - PIN_AFIO_AF(GPIOC_PIN12, 0U) | \ - PIN_AFIO_AF(GPIOC_PIN13, 0U) | \ - PIN_AFIO_AF(GPIOC_PIN14, 0U) | \ - PIN_AFIO_AF(GPIOC_PIN15, 0U)) - -/* - * GPIOD setup: - * - * PD0 - PIN0 (input pullup). - * PD1 - PIN1 (input pullup). - * PD2 - PIN2 (input pullup). - * PD3 - PIN3 (input pullup). - * PD4 - PIN4 (input pullup). - * PD5 - PIN5 (input pullup). - * PD6 - PIN6 (input pullup). - * PD7 - PIN7 (input pullup). - * PD8 - PIN8 (input pullup). - * PD9 - PIN9 (input pullup). - * PD10 - PIN10 (input pullup). - * PD11 - PIN11 (input pullup). - * PD12 - PIN12 (input pullup). - * PD13 - PIN13 (input pullup). - * PD14 - PIN14 (input pullup). - * PD15 - PIN15 (input pullup). - */ -#define VAL_GPIOD_MODER (PIN_MODE_INPUT(GPIOD_PIN0) | \ - PIN_MODE_INPUT(GPIOD_PIN1) | \ - PIN_MODE_INPUT(GPIOD_PIN2) | \ - PIN_MODE_INPUT(GPIOD_PIN3) | \ - PIN_MODE_INPUT(GPIOD_PIN4) | \ - PIN_MODE_INPUT(GPIOD_PIN5) | \ - PIN_MODE_INPUT(GPIOD_PIN6) | \ - PIN_MODE_INPUT(GPIOD_PIN7) | \ - PIN_MODE_INPUT(GPIOD_PIN8) | \ - PIN_MODE_INPUT(GPIOD_PIN9) | \ - PIN_MODE_INPUT(GPIOD_PIN10) | \ - PIN_MODE_INPUT(GPIOD_PIN11) | \ - PIN_MODE_INPUT(GPIOD_PIN12) | \ - PIN_MODE_INPUT(GPIOD_PIN13) | \ - PIN_MODE_INPUT(GPIOD_PIN14) | \ - PIN_MODE_INPUT(GPIOD_PIN15)) -#define VAL_GPIOD_OTYPER (PIN_OTYPE_PUSHPULL(GPIOD_PIN0) | \ - PIN_OTYPE_PUSHPULL(GPIOD_PIN1) | \ - PIN_OTYPE_PUSHPULL(GPIOD_PIN2) | \ - PIN_OTYPE_PUSHPULL(GPIOD_PIN3) | \ - PIN_OTYPE_PUSHPULL(GPIOD_PIN4) | \ - PIN_OTYPE_PUSHPULL(GPIOD_PIN5) | \ - PIN_OTYPE_PUSHPULL(GPIOD_PIN6) | \ - PIN_OTYPE_PUSHPULL(GPIOD_PIN7) | \ - PIN_OTYPE_PUSHPULL(GPIOD_PIN8) | \ - PIN_OTYPE_PUSHPULL(GPIOD_PIN9) | \ - PIN_OTYPE_PUSHPULL(GPIOD_PIN10) | \ - PIN_OTYPE_PUSHPULL(GPIOD_PIN11) | \ - PIN_OTYPE_PUSHPULL(GPIOD_PIN12) | \ - PIN_OTYPE_PUSHPULL(GPIOD_PIN13) | \ - PIN_OTYPE_PUSHPULL(GPIOD_PIN14) | \ - PIN_OTYPE_PUSHPULL(GPIOD_PIN15)) -#define VAL_GPIOD_OSPEEDR (PIN_OSPEED_HIGH(GPIOD_PIN0) | \ - PIN_OSPEED_HIGH(GPIOD_PIN1) | \ - PIN_OSPEED_HIGH(GPIOD_PIN2) | \ - PIN_OSPEED_HIGH(GPIOD_PIN3) | \ - PIN_OSPEED_HIGH(GPIOD_PIN4) | \ - PIN_OSPEED_HIGH(GPIOD_PIN5) | \ - PIN_OSPEED_HIGH(GPIOD_PIN6) | \ - PIN_OSPEED_HIGH(GPIOD_PIN7) | \ - PIN_OSPEED_HIGH(GPIOD_PIN8) | \ - PIN_OSPEED_HIGH(GPIOD_PIN9) | \ - PIN_OSPEED_HIGH(GPIOD_PIN10) | \ - PIN_OSPEED_HIGH(GPIOD_PIN11) | \ - PIN_OSPEED_HIGH(GPIOD_PIN12) | \ - PIN_OSPEED_HIGH(GPIOD_PIN13) | \ - PIN_OSPEED_HIGH(GPIOD_PIN14) | \ - PIN_OSPEED_HIGH(GPIOD_PIN15)) -#define VAL_GPIOD_PUPDR (PIN_PUPDR_PULLUP(GPIOD_PIN0) | \ - PIN_PUPDR_PULLUP(GPIOD_PIN1) | \ - PIN_PUPDR_PULLUP(GPIOD_PIN2) | \ - PIN_PUPDR_PULLUP(GPIOD_PIN3) | \ - PIN_PUPDR_PULLUP(GPIOD_PIN4) | \ - PIN_PUPDR_PULLUP(GPIOD_PIN5) | \ - PIN_PUPDR_PULLUP(GPIOD_PIN6) | \ - PIN_PUPDR_PULLUP(GPIOD_PIN7) | \ - PIN_PUPDR_PULLUP(GPIOD_PIN8) | \ - PIN_PUPDR_PULLUP(GPIOD_PIN9) | \ - PIN_PUPDR_PULLUP(GPIOD_PIN10) | \ - PIN_PUPDR_PULLUP(GPIOD_PIN11) | \ - PIN_PUPDR_PULLUP(GPIOD_PIN12) | \ - PIN_PUPDR_PULLUP(GPIOD_PIN13) | \ - PIN_PUPDR_PULLUP(GPIOD_PIN14) | \ - PIN_PUPDR_PULLUP(GPIOD_PIN15)) -#define VAL_GPIOD_ODR (PIN_ODR_HIGH(GPIOD_PIN0) | \ - PIN_ODR_HIGH(GPIOD_PIN1) | \ - PIN_ODR_HIGH(GPIOD_PIN2) | \ - PIN_ODR_HIGH(GPIOD_PIN3) | \ - PIN_ODR_HIGH(GPIOD_PIN4) | \ - PIN_ODR_HIGH(GPIOD_PIN5) | \ - PIN_ODR_HIGH(GPIOD_PIN6) | \ - PIN_ODR_HIGH(GPIOD_PIN7) | \ - PIN_ODR_HIGH(GPIOD_PIN8) | \ - PIN_ODR_HIGH(GPIOD_PIN9) | \ - PIN_ODR_HIGH(GPIOD_PIN10) | \ - PIN_ODR_HIGH(GPIOD_PIN11) | \ - PIN_ODR_HIGH(GPIOD_PIN12) | \ - PIN_ODR_HIGH(GPIOD_PIN13) | \ - PIN_ODR_HIGH(GPIOD_PIN14) | \ - PIN_ODR_HIGH(GPIOD_PIN15)) -#define VAL_GPIOD_AFRL (PIN_AFIO_AF(GPIOD_PIN0, 0U) | \ - PIN_AFIO_AF(GPIOD_PIN1, 0U) | \ - PIN_AFIO_AF(GPIOD_PIN2, 0U) | \ - PIN_AFIO_AF(GPIOD_PIN3, 0U) | \ - PIN_AFIO_AF(GPIOD_PIN4, 0U) | \ - PIN_AFIO_AF(GPIOD_PIN5, 0U) | \ - PIN_AFIO_AF(GPIOD_PIN6, 0U) | \ - PIN_AFIO_AF(GPIOD_PIN7, 0U)) -#define VAL_GPIOD_AFRH (PIN_AFIO_AF(GPIOD_PIN8, 0U) | \ - PIN_AFIO_AF(GPIOD_PIN9, 0U) | \ - PIN_AFIO_AF(GPIOD_PIN10, 0U) | \ - PIN_AFIO_AF(GPIOD_PIN11, 0U) | \ - PIN_AFIO_AF(GPIOD_PIN12, 0U) | \ - PIN_AFIO_AF(GPIOD_PIN13, 0U) | \ - PIN_AFIO_AF(GPIOD_PIN14, 0U) | \ - PIN_AFIO_AF(GPIOD_PIN15, 0U)) - -/* - * GPIOE setup: - * - * PE0 - PIN0 (input pullup). - * PE1 - PIN1 (input pullup). - * PE2 - PIN2 (input pullup). - * PE3 - PIN3 (input pullup). - * PE4 - PIN4 (input pullup). - * PE5 - PIN5 (input pullup). - * PE6 - PIN6 (input pullup). - * PE7 - PIN7 (input pullup). - * PE8 - PIN8 (input pullup). - * PE9 - PIN9 (input pullup). - * PE10 - PIN10 (input pullup). - * PE11 - PIN11 (input pullup). - * PE12 - PIN12 (input pullup). - * PE13 - PIN13 (input pullup). - * PE14 - PIN14 (input pullup). - * PE15 - PIN15 (input pullup). - */ -#define VAL_GPIOE_MODER (PIN_MODE_INPUT(GPIOE_PIN0) | \ - PIN_MODE_INPUT(GPIOE_PIN1) | \ - PIN_MODE_INPUT(GPIOE_PIN2) | \ - PIN_MODE_INPUT(GPIOE_PIN3) | \ - PIN_MODE_INPUT(GPIOE_PIN4) | \ - PIN_MODE_INPUT(GPIOE_PIN5) | \ - PIN_MODE_INPUT(GPIOE_PIN6) | \ - PIN_MODE_INPUT(GPIOE_PIN7) | \ - PIN_MODE_INPUT(GPIOE_PIN8) | \ - PIN_MODE_INPUT(GPIOE_PIN9) | \ - PIN_MODE_INPUT(GPIOE_PIN10) | \ - PIN_MODE_INPUT(GPIOE_PIN11) | \ - PIN_MODE_INPUT(GPIOE_PIN12) | \ - PIN_MODE_INPUT(GPIOE_PIN13) | \ - PIN_MODE_INPUT(GPIOE_PIN14) | \ - PIN_MODE_INPUT(GPIOE_PIN15)) -#define VAL_GPIOE_OTYPER (PIN_OTYPE_PUSHPULL(GPIOE_PIN0) | \ - PIN_OTYPE_PUSHPULL(GPIOE_PIN1) | \ - PIN_OTYPE_PUSHPULL(GPIOE_PIN2) | \ - PIN_OTYPE_PUSHPULL(GPIOE_PIN3) | \ - PIN_OTYPE_PUSHPULL(GPIOE_PIN4) | \ - PIN_OTYPE_PUSHPULL(GPIOE_PIN5) | \ - PIN_OTYPE_PUSHPULL(GPIOE_PIN6) | \ - PIN_OTYPE_PUSHPULL(GPIOE_PIN7) | \ - PIN_OTYPE_PUSHPULL(GPIOE_PIN8) | \ - PIN_OTYPE_PUSHPULL(GPIOE_PIN9) | \ - PIN_OTYPE_PUSHPULL(GPIOE_PIN10) | \ - PIN_OTYPE_PUSHPULL(GPIOE_PIN11) | \ - PIN_OTYPE_PUSHPULL(GPIOE_PIN12) | \ - PIN_OTYPE_PUSHPULL(GPIOE_PIN13) | \ - PIN_OTYPE_PUSHPULL(GPIOE_PIN14) | \ - PIN_OTYPE_PUSHPULL(GPIOE_PIN15)) -#define VAL_GPIOE_OSPEEDR (PIN_OSPEED_HIGH(GPIOE_PIN0) | \ - PIN_OSPEED_HIGH(GPIOE_PIN1) | \ - PIN_OSPEED_HIGH(GPIOE_PIN2) | \ - PIN_OSPEED_HIGH(GPIOE_PIN3) | \ - PIN_OSPEED_HIGH(GPIOE_PIN4) | \ - PIN_OSPEED_HIGH(GPIOE_PIN5) | \ - PIN_OSPEED_HIGH(GPIOE_PIN6) | \ - PIN_OSPEED_HIGH(GPIOE_PIN7) | \ - PIN_OSPEED_HIGH(GPIOE_PIN8) | \ - PIN_OSPEED_HIGH(GPIOE_PIN9) | \ - PIN_OSPEED_HIGH(GPIOE_PIN10) | \ - PIN_OSPEED_HIGH(GPIOE_PIN11) | \ - PIN_OSPEED_HIGH(GPIOE_PIN12) | \ - PIN_OSPEED_HIGH(GPIOE_PIN13) | \ - PIN_OSPEED_HIGH(GPIOE_PIN14) | \ - PIN_OSPEED_HIGH(GPIOE_PIN15)) -#define VAL_GPIOE_PUPDR (PIN_PUPDR_PULLUP(GPIOE_PIN0) | \ - PIN_PUPDR_PULLUP(GPIOE_PIN1) | \ - PIN_PUPDR_PULLUP(GPIOE_PIN2) | \ - PIN_PUPDR_PULLUP(GPIOE_PIN3) | \ - PIN_PUPDR_PULLUP(GPIOE_PIN4) | \ - PIN_PUPDR_PULLUP(GPIOE_PIN5) | \ - PIN_PUPDR_PULLUP(GPIOE_PIN6) | \ - PIN_PUPDR_PULLUP(GPIOE_PIN7) | \ - PIN_PUPDR_PULLUP(GPIOE_PIN8) | \ - PIN_PUPDR_PULLUP(GPIOE_PIN9) | \ - PIN_PUPDR_PULLUP(GPIOE_PIN10) | \ - PIN_PUPDR_PULLUP(GPIOE_PIN11) | \ - PIN_PUPDR_PULLUP(GPIOE_PIN12) | \ - PIN_PUPDR_PULLUP(GPIOE_PIN13) | \ - PIN_PUPDR_PULLUP(GPIOE_PIN14) | \ - PIN_PUPDR_PULLUP(GPIOE_PIN15)) -#define VAL_GPIOE_ODR (PIN_ODR_HIGH(GPIOE_PIN0) | \ - PIN_ODR_HIGH(GPIOE_PIN1) | \ - PIN_ODR_HIGH(GPIOE_PIN2) | \ - PIN_ODR_HIGH(GPIOE_PIN3) | \ - PIN_ODR_HIGH(GPIOE_PIN4) | \ - PIN_ODR_HIGH(GPIOE_PIN5) | \ - PIN_ODR_HIGH(GPIOE_PIN6) | \ - PIN_ODR_HIGH(GPIOE_PIN7) | \ - PIN_ODR_HIGH(GPIOE_PIN8) | \ - PIN_ODR_HIGH(GPIOE_PIN9) | \ - PIN_ODR_HIGH(GPIOE_PIN10) | \ - PIN_ODR_HIGH(GPIOE_PIN11) | \ - PIN_ODR_HIGH(GPIOE_PIN12) | \ - PIN_ODR_HIGH(GPIOE_PIN13) | \ - PIN_ODR_HIGH(GPIOE_PIN14) | \ - PIN_ODR_HIGH(GPIOE_PIN15)) -#define VAL_GPIOE_AFRL (PIN_AFIO_AF(GPIOE_PIN0, 0U) | \ - PIN_AFIO_AF(GPIOE_PIN1, 0U) | \ - PIN_AFIO_AF(GPIOE_PIN2, 0U) | \ - PIN_AFIO_AF(GPIOE_PIN3, 0U) | \ - PIN_AFIO_AF(GPIOE_PIN4, 0U) | \ - PIN_AFIO_AF(GPIOE_PIN5, 0U) | \ - PIN_AFIO_AF(GPIOE_PIN6, 0U) | \ - PIN_AFIO_AF(GPIOE_PIN7, 0U)) -#define VAL_GPIOE_AFRH (PIN_AFIO_AF(GPIOE_PIN8, 0U) | \ - PIN_AFIO_AF(GPIOE_PIN9, 0U) | \ - PIN_AFIO_AF(GPIOE_PIN10, 0U) | \ - PIN_AFIO_AF(GPIOE_PIN11, 0U) | \ - PIN_AFIO_AF(GPIOE_PIN12, 0U) | \ - PIN_AFIO_AF(GPIOE_PIN13, 0U) | \ - PIN_AFIO_AF(GPIOE_PIN14, 0U) | \ - PIN_AFIO_AF(GPIOE_PIN15, 0U)) - -/* - * GPIOF setup: - * - * PF0 - COL7 - * PF1 - COL6 - * PF2 - PIN2 (input pullup). - * PF3 - PIN3 (input pullup). - * PF4 - PIN4 (input pullup). - * PF5 - PIN5 (input pullup). - * PF6 - PIN6 (input pullup). - * PF7 - PIN7 (input pullup). - * PF8 - PIN8 (input pullup). - * PF9 - PIN9 (input pullup). - * PF10 - PIN10 (input pullup). - * PF11 - PIN11 (input pullup). - * PF12 - PIN12 (input pullup). - * PF13 - PIN13 (input pullup). - * PF14 - PIN14 (input pullup). - * PF15 - PIN15 (input pullup). - */ -#define VAL_GPIOF_MODER (PIN_MODE_INPUT(GPIOF_PIN0) | \ - PIN_MODE_INPUT(GPIOF_PIN1) | \ - PIN_MODE_INPUT(GPIOF_PIN2) | \ - PIN_MODE_INPUT(GPIOF_PIN3) | \ - PIN_MODE_INPUT(GPIOF_PIN4) | \ - PIN_MODE_INPUT(GPIOF_PIN5) | \ - PIN_MODE_INPUT(GPIOF_PIN6) | \ - PIN_MODE_INPUT(GPIOF_PIN7) | \ - PIN_MODE_INPUT(GPIOF_PIN8) | \ - PIN_MODE_INPUT(GPIOF_PIN9) | \ - PIN_MODE_INPUT(GPIOF_PIN10) | \ - PIN_MODE_INPUT(GPIOF_PIN11) | \ - PIN_MODE_INPUT(GPIOF_PIN12) | \ - PIN_MODE_INPUT(GPIOF_PIN13) | \ - PIN_MODE_INPUT(GPIOF_PIN14) | \ - PIN_MODE_INPUT(GPIOF_PIN15)) -#define VAL_GPIOF_OTYPER (PIN_OTYPE_PUSHPULL(GPIOF_PIN0) | \ - PIN_OTYPE_PUSHPULL(GPIOF_PIN1) | \ - PIN_OTYPE_PUSHPULL(GPIOF_PIN2) | \ - PIN_OTYPE_PUSHPULL(GPIOF_PIN3) | \ - PIN_OTYPE_PUSHPULL(GPIOF_PIN4) | \ - PIN_OTYPE_PUSHPULL(GPIOF_PIN5) | \ - PIN_OTYPE_PUSHPULL(GPIOF_PIN6) | \ - PIN_OTYPE_PUSHPULL(GPIOF_PIN7) | \ - PIN_OTYPE_PUSHPULL(GPIOF_PIN8) | \ - PIN_OTYPE_PUSHPULL(GPIOF_PIN9) | \ - PIN_OTYPE_PUSHPULL(GPIOF_PIN10) | \ - PIN_OTYPE_PUSHPULL(GPIOF_PIN11) | \ - PIN_OTYPE_PUSHPULL(GPIOF_PIN12) | \ - PIN_OTYPE_PUSHPULL(GPIOF_PIN13) | \ - PIN_OTYPE_PUSHPULL(GPIOF_PIN14) | \ - PIN_OTYPE_PUSHPULL(GPIOF_PIN15)) -#define VAL_GPIOF_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOF_PIN0) | \ - PIN_OSPEED_VERYLOW(GPIOF_PIN1) | \ - PIN_OSPEED_HIGH(GPIOF_PIN2) | \ - PIN_OSPEED_HIGH(GPIOF_PIN3) | \ - PIN_OSPEED_HIGH(GPIOF_PIN4) | \ - PIN_OSPEED_HIGH(GPIOF_PIN5) | \ - PIN_OSPEED_HIGH(GPIOF_PIN6) | \ - PIN_OSPEED_HIGH(GPIOF_PIN7) | \ - PIN_OSPEED_HIGH(GPIOF_PIN8) | \ - PIN_OSPEED_HIGH(GPIOF_PIN9) | \ - PIN_OSPEED_HIGH(GPIOF_PIN10) | \ - PIN_OSPEED_HIGH(GPIOF_PIN11) | \ - PIN_OSPEED_HIGH(GPIOF_PIN12) | \ - PIN_OSPEED_HIGH(GPIOF_PIN13) | \ - PIN_OSPEED_HIGH(GPIOF_PIN14) | \ - PIN_OSPEED_HIGH(GPIOF_PIN15)) -#define VAL_GPIOF_PUPDR (PIN_PUPDR_PULLUP(GPIOF_PIN0) | \ - PIN_PUPDR_PULLUP(GPIOF_PIN1) | \ - PIN_PUPDR_PULLUP(GPIOF_PIN2) | \ - PIN_PUPDR_PULLUP(GPIOF_PIN3) | \ - PIN_PUPDR_PULLUP(GPIOF_PIN4) | \ - PIN_PUPDR_PULLUP(GPIOF_PIN5) | \ - PIN_PUPDR_PULLUP(GPIOF_PIN6) | \ - PIN_PUPDR_PULLUP(GPIOF_PIN7) | \ - PIN_PUPDR_PULLUP(GPIOF_PIN8) | \ - PIN_PUPDR_PULLUP(GPIOF_PIN9) | \ - PIN_PUPDR_PULLUP(GPIOF_PIN10) | \ - PIN_PUPDR_PULLUP(GPIOF_PIN11) | \ - PIN_PUPDR_PULLUP(GPIOF_PIN12) | \ - PIN_PUPDR_PULLUP(GPIOF_PIN13) | \ - PIN_PUPDR_PULLUP(GPIOF_PIN14) | \ - PIN_PUPDR_PULLUP(GPIOF_PIN15)) -#define VAL_GPIOF_ODR (PIN_ODR_HIGH(GPIOF_PIN0) | \ - PIN_ODR_HIGH(GPIOF_PIN1) | \ - PIN_ODR_HIGH(GPIOF_PIN2) | \ - PIN_ODR_HIGH(GPIOF_PIN3) | \ - PIN_ODR_HIGH(GPIOF_PIN4) | \ - PIN_ODR_HIGH(GPIOF_PIN5) | \ - PIN_ODR_HIGH(GPIOF_PIN6) | \ - PIN_ODR_HIGH(GPIOF_PIN7) | \ - PIN_ODR_HIGH(GPIOF_PIN8) | \ - PIN_ODR_HIGH(GPIOF_PIN9) | \ - PIN_ODR_HIGH(GPIOF_PIN10) | \ - PIN_ODR_HIGH(GPIOF_PIN11) | \ - PIN_ODR_HIGH(GPIOF_PIN12) | \ - PIN_ODR_HIGH(GPIOF_PIN13) | \ - PIN_ODR_HIGH(GPIOF_PIN14) | \ - PIN_ODR_HIGH(GPIOF_PIN15)) -#define VAL_GPIOF_AFRL (PIN_AFIO_AF(GPIOF_PIN0, 0U) | \ - PIN_AFIO_AF(GPIOF_PIN1, 0U) | \ - PIN_AFIO_AF(GPIOF_PIN2, 0U) | \ - PIN_AFIO_AF(GPIOF_PIN3, 0U) | \ - PIN_AFIO_AF(GPIOF_PIN4, 0U) | \ - PIN_AFIO_AF(GPIOF_PIN5, 0U) | \ - PIN_AFIO_AF(GPIOF_PIN6, 0U) | \ - PIN_AFIO_AF(GPIOF_PIN7, 0U)) -#define VAL_GPIOF_AFRH (PIN_AFIO_AF(GPIOF_PIN8, 0U) | \ - PIN_AFIO_AF(GPIOF_PIN9, 0U) | \ - PIN_AFIO_AF(GPIOF_PIN10, 0U) | \ - PIN_AFIO_AF(GPIOF_PIN11, 0U) | \ - PIN_AFIO_AF(GPIOF_PIN12, 0U) | \ - PIN_AFIO_AF(GPIOF_PIN13, 0U) | \ - PIN_AFIO_AF(GPIOF_PIN14, 0U) | \ - PIN_AFIO_AF(GPIOF_PIN15, 0U)) - -#if !defined(_FROM_ASM_) -#ifdef __cplusplus -extern "C" { -#endif - void boardInit(void); -#ifdef __cplusplus -} -#endif -#endif /* _FROM_ASM_ */ - -#endif /* _BOARD_H */ diff --git a/platforms/chibios/GENERIC_STM32_F042X6/board/board.mk b/platforms/chibios/GENERIC_STM32_F042X6/board/board.mk deleted file mode 100644 index 842e335905..0000000000 --- a/platforms/chibios/GENERIC_STM32_F042X6/board/board.mk +++ /dev/null @@ -1,9 +0,0 @@ -# List of all the board related files. -BOARDSRC = $(BOARD_PATH)/board/board.c - -# Required include directories -BOARDINC = $(BOARD_PATH)/board - -# Shared variables -ALLCSRC += $(BOARDSRC) -ALLINC += $(BOARDINC) diff --git a/platforms/chibios/GENERIC_STM32_F042X6/configs/bootloader_defs.h b/platforms/chibios/GENERIC_STM32_F042X6/configs/bootloader_defs.h deleted file mode 100644 index 25113425a6..0000000000 --- a/platforms/chibios/GENERIC_STM32_F042X6/configs/bootloader_defs.h +++ /dev/null @@ -1,5 +0,0 @@ -/* Address for jumping to bootloader on STM32 chips. */ -/* It is chip dependent, the correct number can be looked up here: - * http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf - */ -#define STM32_BOOTLOADER_ADDRESS 0x1FFFC400 diff --git a/platforms/chibios/GENERIC_STM32_F042X6/configs/config.h b/platforms/chibios/GENERIC_STM32_F042X6/configs/config.h deleted file mode 100644 index a73f0c0b47..0000000000 --- a/platforms/chibios/GENERIC_STM32_F042X6/configs/config.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Copyright 2020 Nick Brassel (tzarc) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#pragma once - -#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP -# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE -#endif diff --git a/platforms/chibios/GENERIC_STM32_F042X6/configs/mcuconf.h b/platforms/chibios/GENERIC_STM32_F042X6/configs/mcuconf.h deleted file mode 100644 index 286e1230ce..0000000000 --- a/platforms/chibios/GENERIC_STM32_F042X6/configs/mcuconf.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio - 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 License 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. -*/ - -#ifndef _MCUCONF_H_ -#define _MCUCONF_H_ - -/* - * STM32F0xx drivers configuration. - * The following settings override the default settings present in - * the various device driver implementation headers. - * Note that the settings for each driver only have effect if the whole - * driver is enabled in halconf.h. - * - * IRQ priorities: - * 3...0 Lowest...Highest. - * - * DMA priorities: - * 0...3 Lowest...Highest. - */ - -#define STM32F0xx_MCUCONF - -/* - * HAL driver system settings. - */ -#define STM32_NO_INIT FALSE -#define STM32_PVD_ENABLE FALSE -#define STM32_PLS STM32_PLS_LEV0 -#define STM32_HSI_ENABLED TRUE -#define STM32_HSI14_ENABLED TRUE -#define STM32_HSI48_ENABLED FALSE -#define STM32_LSI_ENABLED TRUE -#define STM32_HSE_ENABLED FALSE -#define STM32_LSE_ENABLED FALSE -#define STM32_SW STM32_SW_PLL -#define STM32_PLLSRC STM32_PLLSRC_HSI_DIV2 -#define STM32_PREDIV_VALUE 1 -#define STM32_PLLMUL_VALUE 12 -#define STM32_HPRE STM32_HPRE_DIV1 -#define STM32_PPRE STM32_PPRE_DIV1 -#define STM32_ADCSW STM32_ADCSW_HSI14 -#define STM32_ADCPRE STM32_ADCPRE_DIV4 -#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK -#define STM32_ADCPRE STM32_ADCPRE_DIV4 -#define STM32_ADCSW STM32_ADCSW_HSI14 -#define STM32_USBSW STM32_USBSW_HSI48 -#define STM32_CECSW STM32_CECSW_HSI -#define STM32_I2C1SW STM32_I2C1SW_HSI -#define STM32_USART1SW STM32_USART1SW_PCLK -#define STM32_RTCSEL STM32_RTCSEL_LSI - -/* - * ADC driver system settings. - */ -#define STM32_ADC_USE_ADC1 FALSE -#define STM32_ADC_ADC1_DMA_PRIORITY 2 -#define STM32_ADC_IRQ_PRIORITY 2 -#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 2 - -/* - * EXT driver system settings. - */ -#define STM32_EXT_EXTI0_1_IRQ_PRIORITY 3 -#define STM32_EXT_EXTI2_3_IRQ_PRIORITY 3 -#define STM32_EXT_EXTI4_15_IRQ_PRIORITY 3 -#define STM32_EXT_EXTI16_IRQ_PRIORITY 3 -#define STM32_EXT_EXTI17_IRQ_PRIORITY 3 - -/* - * GPT driver system settings. - */ -#define STM32_GPT_USE_TIM1 FALSE -#define STM32_GPT_USE_TIM2 FALSE -#define STM32_GPT_USE_TIM3 FALSE -#define STM32_GPT_USE_TIM14 FALSE -#define STM32_GPT_TIM1_IRQ_PRIORITY 2 -#define STM32_GPT_TIM2_IRQ_PRIORITY 2 -#define STM32_GPT_TIM3_IRQ_PRIORITY 2 -#define STM32_GPT_TIM14_IRQ_PRIORITY 2 - -/* - * I2C driver system settings. - */ -#define STM32_I2C_USE_I2C1 FALSE -#define STM32_I2C_USE_I2C2 FALSE -#define STM32_I2C_BUSY_TIMEOUT 50 -#define STM32_I2C_I2C1_IRQ_PRIORITY 3 -#define STM32_I2C_I2C2_IRQ_PRIORITY 3 -#define STM32_I2C_USE_DMA TRUE -#define STM32_I2C_I2C1_DMA_PRIORITY 1 -#define STM32_I2C_I2C2_DMA_PRIORITY 1 -#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") - -/* - * ICU driver system settings. - */ -#define STM32_ICU_USE_TIM1 FALSE -#define STM32_ICU_USE_TIM2 FALSE -#define STM32_ICU_USE_TIM3 FALSE -#define STM32_ICU_TIM1_IRQ_PRIORITY 3 -#define STM32_ICU_TIM2_IRQ_PRIORITY 3 -#define STM32_ICU_TIM3_IRQ_PRIORITY 3 - -/* - * PWM driver system settings. - */ -#define STM32_PWM_USE_ADVANCED FALSE -#define STM32_PWM_USE_TIM1 FALSE -#define STM32_PWM_USE_TIM2 FALSE -#define STM32_PWM_USE_TIM3 FALSE -#define STM32_PWM_TIM1_IRQ_PRIORITY 3 -#define STM32_PWM_TIM2_IRQ_PRIORITY 3 -#define STM32_PWM_TIM3_IRQ_PRIORITY 3 - -/* - * SERIAL driver system settings. - */ -#define STM32_SERIAL_USE_USART1 FALSE -#define STM32_SERIAL_USE_USART2 FALSE -#define STM32_SERIAL_USART1_PRIORITY 3 -#define STM32_SERIAL_USART2_PRIORITY 3 - -/* - * SPI driver system settings. - */ -#define STM32_SPI_USE_SPI1 FALSE -#define STM32_SPI_USE_SPI2 FALSE -#define STM32_SPI_SPI1_DMA_PRIORITY 1 -#define STM32_SPI_SPI2_DMA_PRIORITY 1 -#define STM32_SPI_SPI1_IRQ_PRIORITY 2 -#define STM32_SPI_SPI2_IRQ_PRIORITY 2 -#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") - -/* - * ST driver system settings. - */ -#define STM32_ST_IRQ_PRIORITY 2 -#define STM32_ST_USE_TIMER 2 - -/* - * UART driver system settings. - */ -#define STM32_UART_USE_USART1 FALSE -#define STM32_UART_USE_USART2 FALSE -#define STM32_UART_USART1_IRQ_PRIORITY 3 -#define STM32_UART_USART2_IRQ_PRIORITY 3 -#define STM32_UART_USART1_DMA_PRIORITY 0 -#define STM32_UART_USART2_DMA_PRIORITY 0 -#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") - -/* - * USB driver system settings. - */ -#define STM32_USB_USE_USB1 TRUE -#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE -#define STM32_USB_USB1_LP_IRQ_PRIORITY 3 - -#endif /* _MCUCONF_H_ */ diff --git a/platforms/chibios/GENERIC_STM32_F072XB/board/board.mk b/platforms/chibios/GENERIC_STM32_F072XB/board/board.mk deleted file mode 100644 index 3f0e6c46e8..0000000000 --- a/platforms/chibios/GENERIC_STM32_F072XB/board/board.mk +++ /dev/null @@ -1,9 +0,0 @@ -# List of all the board related files. -BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_F072RB/board.c - -# Required include directories -BOARDINC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_F072RB - -# Shared variables -ALLCSRC += $(BOARDSRC) -ALLINC += $(BOARDINC) diff --git a/platforms/chibios/GENERIC_STM32_F072XB/configs/board.h b/platforms/chibios/GENERIC_STM32_F072XB/configs/board.h deleted file mode 100644 index 30af6b0c86..0000000000 --- a/platforms/chibios/GENERIC_STM32_F072XB/configs/board.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Copyright 2020 Nick Brassel (tzarc) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#pragma once - -#include_next "board.h" - -#undef STM32_HSE_BYPASS diff --git a/platforms/chibios/GENERIC_STM32_F072XB/configs/bootloader_defs.h b/platforms/chibios/GENERIC_STM32_F072XB/configs/bootloader_defs.h deleted file mode 100644 index dccd0fa5d1..0000000000 --- a/platforms/chibios/GENERIC_STM32_F072XB/configs/bootloader_defs.h +++ /dev/null @@ -1,5 +0,0 @@ -/* Address for jumping to bootloader on STM32 chips. */ -/* It is chip dependent, the correct number can be looked up here (page 175): - * http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf - */ -#define STM32_BOOTLOADER_ADDRESS 0x1FFFC800 diff --git a/platforms/chibios/GENERIC_STM32_F072XB/configs/config.h b/platforms/chibios/GENERIC_STM32_F072XB/configs/config.h deleted file mode 100644 index a73f0c0b47..0000000000 --- a/platforms/chibios/GENERIC_STM32_F072XB/configs/config.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Copyright 2020 Nick Brassel (tzarc) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#pragma once - -#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP -# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE -#endif diff --git a/platforms/chibios/GENERIC_STM32_F072XB/configs/mcuconf.h b/platforms/chibios/GENERIC_STM32_F072XB/configs/mcuconf.h deleted file mode 100644 index 32b2777a81..0000000000 --- a/platforms/chibios/GENERIC_STM32_F072XB/configs/mcuconf.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio - - 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 License 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. -*/ - -#ifndef _MCUCONF_H_ -#define _MCUCONF_H_ - -/* - * STM32F0xx drivers configuration. - * The following settings override the default settings present in - * the various device driver implementation headers. - * Note that the settings for each driver only have effect if the whole - * driver is enabled in halconf.h. - * - * IRQ priorities: - * 3...0 Lowest...Highest. - * - * DMA priorities: - * 0...3 Lowest...Highest. - */ - -#define STM32F0xx_MCUCONF -// #define STM32F070xB - -/* - * HAL driver system settings. - */ -#define STM32_NO_INIT FALSE -#define STM32_PVD_ENABLE FALSE -#define STM32_PLS STM32_PLS_LEV0 -#define STM32_HSI_ENABLED TRUE -#define STM32_HSI14_ENABLED TRUE -#define STM32_HSI48_ENABLED FALSE -#define STM32_LSI_ENABLED TRUE -#define STM32_HSE_ENABLED FALSE -#define STM32_LSE_ENABLED FALSE -#define STM32_SW STM32_SW_PLL -#define STM32_PLLSRC STM32_PLLSRC_HSI_DIV2 -#define STM32_PREDIV_VALUE 1 -#define STM32_PLLMUL_VALUE 12 -#define STM32_HPRE STM32_HPRE_DIV1 -#define STM32_PPRE STM32_PPRE_DIV1 -#define STM32_ADCSW STM32_ADCSW_HSI14 -#define STM32_ADCPRE STM32_ADCPRE_DIV4 -#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK -#define STM32_ADCPRE STM32_ADCPRE_DIV4 -#define STM32_ADCSW STM32_ADCSW_HSI14 -#define STM32_USBSW STM32_USBSW_HSI48 -#define STM32_CECSW STM32_CECSW_HSI -#define STM32_I2C1SW STM32_I2C1SW_HSI -#define STM32_USART1SW STM32_USART1SW_PCLK -#define STM32_RTCSEL STM32_RTCSEL_LSI - -/* - * IRQ system settings. - */ -#define STM32_IRQ_EXTI0_1_IRQ_PRIORITY 3 -#define STM32_IRQ_EXTI2_3_IRQ_PRIORITY 3 -#define STM32_IRQ_EXTI4_15_IRQ_PRIORITY 3 -#define STM32_IRQ_EXTI16_IRQ_PRIORITY 3 -#define STM32_IRQ_EXTI17_20_IRQ_PRIORITY 3 -#define STM32_IRQ_EXTI21_22_IRQ_PRIORITY 3 - -/* - * ADC driver system settings. - */ -#define STM32_ADC_USE_ADC1 FALSE -#define STM32_ADC_ADC1_DMA_PRIORITY 2 -#define STM32_ADC_IRQ_PRIORITY 2 -#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 2 - -/* - * GPT driver system settings. - */ -#define STM32_GPT_USE_TIM1 FALSE -#define STM32_GPT_USE_TIM2 FALSE -#define STM32_GPT_USE_TIM3 FALSE -#define STM32_GPT_USE_TIM14 FALSE -#define STM32_GPT_TIM1_IRQ_PRIORITY 2 -#define STM32_GPT_TIM2_IRQ_PRIORITY 2 -#define STM32_GPT_TIM3_IRQ_PRIORITY 2 -#define STM32_GPT_TIM14_IRQ_PRIORITY 2 - -/* - * I2C driver system settings. - */ -#define STM32_I2C_USE_I2C1 FALSE -#define STM32_I2C_USE_I2C2 FALSE -#define STM32_I2C_BUSY_TIMEOUT 50 -#define STM32_I2C_I2C1_IRQ_PRIORITY 3 -#define STM32_I2C_I2C2_IRQ_PRIORITY 3 -#define STM32_I2C_USE_DMA TRUE -#define STM32_I2C_I2C1_DMA_PRIORITY 1 -#define STM32_I2C_I2C2_DMA_PRIORITY 1 -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") - -/* - * ICU driver system settings. - */ -#define STM32_ICU_USE_TIM1 FALSE -#define STM32_ICU_USE_TIM2 FALSE -#define STM32_ICU_USE_TIM3 FALSE -#define STM32_ICU_TIM1_IRQ_PRIORITY 3 -#define STM32_ICU_TIM2_IRQ_PRIORITY 3 -#define STM32_ICU_TIM3_IRQ_PRIORITY 3 - -/* - * PWM driver system settings. - */ -#define STM32_PWM_USE_ADVANCED FALSE -#define STM32_PWM_USE_TIM1 FALSE -#define STM32_PWM_USE_TIM2 FALSE -#define STM32_PWM_USE_TIM3 FALSE -#define STM32_PWM_TIM1_IRQ_PRIORITY 3 -#define STM32_PWM_TIM2_IRQ_PRIORITY 3 -#define STM32_PWM_TIM3_IRQ_PRIORITY 3 - -/* - * SERIAL driver system settings. - */ -#define STM32_SERIAL_USE_USART1 FALSE -#define STM32_SERIAL_USE_USART2 FALSE -#define STM32_SERIAL_USART1_PRIORITY 3 -#define STM32_SERIAL_USART2_PRIORITY 3 - -/* - * SPI driver system settings. - */ -#define STM32_SPI_USE_SPI1 FALSE -#define STM32_SPI_USE_SPI2 FALSE -#define STM32_SPI_SPI1_DMA_PRIORITY 1 -#define STM32_SPI_SPI2_DMA_PRIORITY 1 -#define STM32_SPI_SPI1_IRQ_PRIORITY 2 -#define STM32_SPI_SPI2_IRQ_PRIORITY 2 -#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") - -/* - * ST driver system settings. - */ -#define STM32_ST_IRQ_PRIORITY 2 -#define STM32_ST_USE_TIMER 2 - -/* - * UART driver system settings. - */ -#define STM32_UART_USE_USART1 FALSE -#define STM32_UART_USE_USART2 FALSE -#define STM32_UART_USART1_IRQ_PRIORITY 3 -#define STM32_UART_USART2_IRQ_PRIORITY 3 -#define STM32_UART_USART1_DMA_PRIORITY 0 -#define STM32_UART_USART2_DMA_PRIORITY 0 -#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") - -/* - * USB driver system settings. - */ -#define STM32_USB_USE_USB1 TRUE -#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE -#define STM32_USB_USB1_LP_IRQ_PRIORITY 3 - -#endif /* _MCUCONF_H_ */ diff --git a/platforms/chibios/GENERIC_STM32_F303XC/board/board.mk b/platforms/chibios/GENERIC_STM32_F303XC/board/board.mk deleted file mode 100644 index f891e65247..0000000000 --- a/platforms/chibios/GENERIC_STM32_F303XC/board/board.mk +++ /dev/null @@ -1,9 +0,0 @@ -# List of all the board related files. -BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_STM32F3_DISCOVERY/board.c - -# Required include directories -BOARDINC = $(CHIBIOS)/os/hal/boards/ST_STM32F3_DISCOVERY - -# Shared variables -ALLCSRC += $(BOARDSRC) -ALLINC += $(BOARDINC) diff --git a/platforms/chibios/GENERIC_STM32_F303XC/configs/board.h b/platforms/chibios/GENERIC_STM32_F303XC/configs/board.h deleted file mode 100644 index 97159964d0..0000000000 --- a/platforms/chibios/GENERIC_STM32_F303XC/configs/board.h +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright 2020 Nick Brassel (tzarc) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#pragma once - -#include_next "board.h" - -#undef STM32_HSE_BYPASS - -/* - * USB bus activation macro, required by the USB driver. - */ -#define usb_lld_connect_bus(usbp) \ - do { \ - palSetPadMode(GPIOA, GPIOA_USB_DP, PAL_MODE_ALTERNATE(14)); \ - } while (0) - -/* - * USB bus de-activation macro, required by the USB driver. - */ -#define usb_lld_disconnect_bus(usbp) \ - do { \ - palSetPadMode(GPIOA, GPIOA_USB_DP, PAL_MODE_OUTPUT_PUSHPULL); \ - palClearPad(GPIOA, GPIOA_USB_DP); \ - } while (0) diff --git a/platforms/chibios/GENERIC_STM32_F303XC/configs/bootloader_defs.h b/platforms/chibios/GENERIC_STM32_F303XC/configs/bootloader_defs.h deleted file mode 100644 index 87ac7b10dc..0000000000 --- a/platforms/chibios/GENERIC_STM32_F303XC/configs/bootloader_defs.h +++ /dev/null @@ -1,5 +0,0 @@ -/* Address for jumping to bootloader on STM32 chips. */ -/* It is chip dependent, the correct number can be looked up here: - * http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf - */ -#define STM32_BOOTLOADER_ADDRESS 0x1FFFD800 diff --git a/platforms/chibios/GENERIC_STM32_F303XC/configs/config.h b/platforms/chibios/GENERIC_STM32_F303XC/configs/config.h deleted file mode 100644 index a73f0c0b47..0000000000 --- a/platforms/chibios/GENERIC_STM32_F303XC/configs/config.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Copyright 2020 Nick Brassel (tzarc) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#pragma once - -#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP -# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE -#endif diff --git a/platforms/chibios/GENERIC_STM32_F303XC/configs/mcuconf.h b/platforms/chibios/GENERIC_STM32_F303XC/configs/mcuconf.h deleted file mode 100644 index c6f5a8ac52..0000000000 --- a/platforms/chibios/GENERIC_STM32_F303XC/configs/mcuconf.h +++ /dev/null @@ -1,273 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - 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 License 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. -*/ - -#ifndef MCUCONF_H -#define MCUCONF_H - -/* - * STM32F3xx drivers configuration. - * The following settings override the default settings present in - * the various device driver implementation headers. - * Note that the settings for each driver only have effect if the whole - * driver is enabled in halconf.h. - * - * IRQ priorities: - * 15...0 Lowest...Highest. - * - * DMA priorities: - * 0...3 Lowest...Highest. - */ - -#define STM32F3xx_MCUCONF -#define STM32F303_MCUCONF - -/* - * HAL driver system settings. - */ -#define STM32_NO_INIT FALSE -#define STM32_PVD_ENABLE FALSE -#define STM32_PLS STM32_PLS_LEV0 -#define STM32_HSI_ENABLED TRUE -#define STM32_LSI_ENABLED TRUE -#define STM32_HSE_ENABLED TRUE -#define STM32_LSE_ENABLED FALSE -#define STM32_SW STM32_SW_PLL -#define STM32_PLLSRC STM32_PLLSRC_HSE -#define STM32_PREDIV_VALUE 1 -#define STM32_PLLMUL_VALUE 9 -#define STM32_HPRE STM32_HPRE_DIV1 -#define STM32_PPRE1 STM32_PPRE1_DIV2 -#define STM32_PPRE2 STM32_PPRE2_DIV2 -#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK -#define STM32_ADC12PRES STM32_ADC12PRES_DIV1 -#define STM32_ADC34PRES STM32_ADC34PRES_DIV1 -#define STM32_USART1SW STM32_USART1SW_PCLK -#define STM32_USART2SW STM32_USART2SW_PCLK -#define STM32_USART3SW STM32_USART3SW_PCLK -#define STM32_UART4SW STM32_UART4SW_PCLK -#define STM32_UART5SW STM32_UART5SW_PCLK -#define STM32_I2C1SW STM32_I2C1SW_SYSCLK -#define STM32_I2C2SW STM32_I2C2SW_SYSCLK -#define STM32_TIM1SW STM32_TIM1SW_PCLK2 -#define STM32_TIM8SW STM32_TIM8SW_PCLK2 -#define STM32_RTCSEL STM32_RTCSEL_LSI -#define STM32_USB_CLOCK_REQUIRED TRUE -#define STM32_USBPRE STM32_USBPRE_DIV1P5 - -/* - * IRQ system settings. - */ -#define STM32_IRQ_EXTI0_PRIORITY 6 -#define STM32_IRQ_EXTI1_PRIORITY 6 -#define STM32_IRQ_EXTI2_PRIORITY 6 -#define STM32_IRQ_EXTI3_PRIORITY 6 -#define STM32_IRQ_EXTI4_PRIORITY 6 -#define STM32_IRQ_EXTI5_9_PRIORITY 6 -#define STM32_IRQ_EXTI10_15_PRIORITY 6 -#define STM32_IRQ_EXTI16_PRIORITY 6 -#define STM32_IRQ_EXTI17_PRIORITY 15 -#define STM32_IRQ_EXTI18_PRIORITY 6 -#define STM32_IRQ_EXTI19_PRIORITY 15 -#define STM32_IRQ_EXTI20_PRIORITY 15 -#define STM32_IRQ_EXTI21_22_29_PRIORITY 6 -#define STM32_IRQ_EXTI30_32_PRIORITY 6 -#define STM32_IRQ_EXTI33_PRIORITY 6 -#define STM32_IRQ_TIM1_BRK_TIM15_PRIORITY 7 -#define STM32_IRQ_TIM1_UP_TIM16_PRIORITY 7 -#define STM32_IRQ_TIM1_TRGCO_TIM17_PRIORITY 7 -#define STM32_IRQ_TIM1_CC_PRIORITY 7 - -/* - * ADC driver system settings. - */ -#define STM32_ADC_DUAL_MODE FALSE -#define STM32_ADC_COMPACT_SAMPLES FALSE -#define STM32_ADC_USE_ADC1 FALSE -#define STM32_ADC_USE_ADC2 FALSE -#define STM32_ADC_USE_ADC3 FALSE -#define STM32_ADC_USE_ADC4 FALSE -#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) -#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) -#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) -#define STM32_ADC_ADC4_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) -#define STM32_ADC_ADC1_DMA_PRIORITY 2 -#define STM32_ADC_ADC2_DMA_PRIORITY 2 -#define STM32_ADC_ADC3_DMA_PRIORITY 2 -#define STM32_ADC_ADC4_DMA_PRIORITY 2 -#define STM32_ADC_ADC12_IRQ_PRIORITY 5 -#define STM32_ADC_ADC3_IRQ_PRIORITY 5 -#define STM32_ADC_ADC4_IRQ_PRIORITY 5 -#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 5 -#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 5 -#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 5 -#define STM32_ADC_ADC4_DMA_IRQ_PRIORITY 5 -#define STM32_ADC_ADC12_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1 -#define STM32_ADC_ADC34_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1 - -/* - * CAN driver system settings. - */ -#define STM32_CAN_USE_CAN1 FALSE -#define STM32_CAN_CAN1_IRQ_PRIORITY 11 - -/* - * DAC driver system settings. - */ -#define STM32_DAC_DUAL_MODE FALSE -#define STM32_DAC_USE_DAC1_CH1 FALSE -#define STM32_DAC_USE_DAC1_CH2 FALSE -#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 -#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 -#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 -#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 - -/* - * GPT driver system settings. - */ -#define STM32_GPT_USE_TIM1 FALSE -#define STM32_GPT_USE_TIM2 FALSE -#define STM32_GPT_USE_TIM3 FALSE -#define STM32_GPT_USE_TIM4 FALSE -#define STM32_GPT_USE_TIM6 FALSE -#define STM32_GPT_USE_TIM7 FALSE -#define STM32_GPT_USE_TIM8 FALSE -#define STM32_GPT_USE_TIM15 FALSE -#define STM32_GPT_USE_TIM16 FALSE -#define STM32_GPT_USE_TIM17 FALSE -#define STM32_GPT_TIM1_IRQ_PRIORITY 7 -#define STM32_GPT_TIM2_IRQ_PRIORITY 7 -#define STM32_GPT_TIM3_IRQ_PRIORITY 7 -#define STM32_GPT_TIM4_IRQ_PRIORITY 7 -#define STM32_GPT_TIM6_IRQ_PRIORITY 7 -#define STM32_GPT_TIM7_IRQ_PRIORITY 7 -#define STM32_GPT_TIM8_IRQ_PRIORITY 7 - -/* - * I2C driver system settings. - */ -#define STM32_I2C_USE_I2C1 FALSE -#define STM32_I2C_USE_I2C2 FALSE -#define STM32_I2C_BUSY_TIMEOUT 50 -#define STM32_I2C_I2C1_IRQ_PRIORITY 10 -#define STM32_I2C_I2C2_IRQ_PRIORITY 10 -#define STM32_I2C_USE_DMA TRUE -#define STM32_I2C_I2C1_DMA_PRIORITY 1 -#define STM32_I2C_I2C2_DMA_PRIORITY 1 -#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") - -/* - * ICU driver system settings. - */ -#define STM32_ICU_USE_TIM1 FALSE -#define STM32_ICU_USE_TIM2 FALSE -#define STM32_ICU_USE_TIM3 FALSE -#define STM32_ICU_USE_TIM4 FALSE -#define STM32_ICU_USE_TIM8 FALSE -#define STM32_ICU_USE_TIM15 FALSE -#define STM32_ICU_TIM1_IRQ_PRIORITY 7 -#define STM32_ICU_TIM2_IRQ_PRIORITY 7 -#define STM32_ICU_TIM3_IRQ_PRIORITY 7 -#define STM32_ICU_TIM4_IRQ_PRIORITY 7 -#define STM32_ICU_TIM8_IRQ_PRIORITY 7 - -/* - * PWM driver system settings. - */ -#define STM32_PWM_USE_ADVANCED FALSE -#define STM32_PWM_USE_TIM1 FALSE -#define STM32_PWM_USE_TIM2 FALSE -#define STM32_PWM_USE_TIM3 FALSE -#define STM32_PWM_USE_TIM4 FALSE -#define STM32_PWM_USE_TIM8 FALSE -#define STM32_PWM_USE_TIM15 FALSE -#define STM32_PWM_USE_TIM16 FALSE -#define STM32_PWM_USE_TIM17 FALSE -#define STM32_PWM_TIM1_IRQ_PRIORITY 7 -#define STM32_PWM_TIM2_IRQ_PRIORITY 7 -#define STM32_PWM_TIM3_IRQ_PRIORITY 7 -#define STM32_PWM_TIM4_IRQ_PRIORITY 7 -#define STM32_PWM_TIM8_IRQ_PRIORITY 7 - -/* - * RTC driver system settings. - */ -#define STM32_RTC_PRESA_VALUE 32 -#define STM32_RTC_PRESS_VALUE 1024 -#define STM32_RTC_CR_INIT 0 -#define STM32_RTC_TAMPCR_INIT 0 - -/* - * SERIAL driver system settings. - */ -#define STM32_SERIAL_USE_USART1 FALSE -#define STM32_SERIAL_USE_USART2 FALSE -#define STM32_SERIAL_USE_USART3 FALSE -#define STM32_SERIAL_USE_UART4 FALSE -#define STM32_SERIAL_USE_UART5 FALSE -#define STM32_SERIAL_USART1_PRIORITY 12 -#define STM32_SERIAL_USART2_PRIORITY 12 -#define STM32_SERIAL_USART3_PRIORITY 12 -#define STM32_SERIAL_UART4_PRIORITY 12 -#define STM32_SERIAL_UART5_PRIORITY 12 - -/* - * SPI driver system settings. - */ -#define STM32_SPI_USE_SPI1 FALSE -#define STM32_SPI_USE_SPI2 FALSE -#define STM32_SPI_USE_SPI3 FALSE -#define STM32_SPI_SPI1_DMA_PRIORITY 1 -#define STM32_SPI_SPI2_DMA_PRIORITY 1 -#define STM32_SPI_SPI3_DMA_PRIORITY 1 -#define STM32_SPI_SPI1_IRQ_PRIORITY 10 -#define STM32_SPI_SPI2_IRQ_PRIORITY 10 -#define STM32_SPI_SPI3_IRQ_PRIORITY 10 -#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") - -/* - * ST driver system settings. - */ -#define STM32_ST_IRQ_PRIORITY 8 -#define STM32_ST_USE_TIMER 2 - -/* - * UART driver system settings. - */ -#define STM32_UART_USE_USART1 FALSE -#define STM32_UART_USE_USART2 FALSE -#define STM32_UART_USE_USART3 FALSE -#define STM32_UART_USART1_IRQ_PRIORITY 12 -#define STM32_UART_USART2_IRQ_PRIORITY 12 -#define STM32_UART_USART3_IRQ_PRIORITY 12 -#define STM32_UART_USART1_DMA_PRIORITY 0 -#define STM32_UART_USART2_DMA_PRIORITY 0 -#define STM32_UART_USART3_DMA_PRIORITY 0 -#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") - -/* - * USB driver system settings. - */ -#define STM32_USB_USE_USB1 TRUE -#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE -#define STM32_USB_USB1_HP_IRQ_PRIORITY 13 -#define STM32_USB_USB1_LP_IRQ_PRIORITY 14 - -/* - * WDG driver system settings. - */ -#define STM32_WDG_USE_IWDG FALSE - -#endif /* MCUCONF_H */ diff --git a/platforms/chibios/GENERIC_STM32_F407XE/board/board.mk b/platforms/chibios/GENERIC_STM32_F407XE/board/board.mk deleted file mode 100644 index 6c837bb8ee..0000000000 --- a/platforms/chibios/GENERIC_STM32_F407XE/board/board.mk +++ /dev/null @@ -1,9 +0,0 @@ -# List of all the board related files. -BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_STM32F4_DISCOVERY/board.c - -# Required include directories -BOARDINC = $(CHIBIOS)/os/hal/boards/ST_STM32F4_DISCOVERY - -# Shared variables -ALLCSRC += $(BOARDSRC) -ALLINC += $(BOARDINC) \ No newline at end of file diff --git a/platforms/chibios/GENERIC_STM32_F407XE/configs/board.h b/platforms/chibios/GENERIC_STM32_F407XE/configs/board.h deleted file mode 100644 index 22c4e4cd7e..0000000000 --- a/platforms/chibios/GENERIC_STM32_F407XE/configs/board.h +++ /dev/null @@ -1,24 +0,0 @@ -/* Copyright 2020 Nick Brassel (tzarc) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#pragma once - -#define STM32_HSECLK 8000000 -// The following is required to disable the pull-down on PA9, when PA9 is used for the keyboard matrix: -#define BOARD_OTG_NOVBUSSENS - -#include_next "board.h" - -#undef STM32_HSE_BYPASS \ No newline at end of file diff --git a/platforms/chibios/GENERIC_STM32_F407XE/configs/config.h b/platforms/chibios/GENERIC_STM32_F407XE/configs/config.h deleted file mode 100644 index cc52a953ed..0000000000 --- a/platforms/chibios/GENERIC_STM32_F407XE/configs/config.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright 2021 Andrei Purdea - * - * 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 . - */ - -/* Address for jumping to bootloader on STM32 chips. */ -/* It is chip dependent, the correct number can be looked up by checking against ST's application note AN2606. - */ -#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000 -#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP -# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE -#endif diff --git a/platforms/chibios/GENERIC_STM32_F407XE/configs/mcuconf.h b/platforms/chibios/GENERIC_STM32_F407XE/configs/mcuconf.h deleted file mode 100644 index 4be47fe1b0..0000000000 --- a/platforms/chibios/GENERIC_STM32_F407XE/configs/mcuconf.h +++ /dev/null @@ -1,355 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - 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 License 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. -*/ - -#ifndef MCUCONF_H -#define MCUCONF_H - -/* - * STM32F4xx drivers configuration. - * The following settings override the default settings present in - * the various device driver implementation headers. - * Note that the settings for each driver only have effect if the whole - * driver is enabled in halconf.h. - * - * IRQ priorities: - * 15...0 Lowest...Highest. - * - * DMA priorities: - * 0...3 Lowest...Highest. - */ - -#define STM32F4xx_MCUCONF -#define STM32F405_MCUCONF -#define STM32F415_MCUCONF -#define STM32F407_MCUCONF -#define STM32F417_MCUCONF - -/* - * HAL driver system settings. - */ -#define STM32_NO_INIT FALSE -#define STM32_PVD_ENABLE FALSE -#define STM32_PLS STM32_PLS_LEV0 -#define STM32_BKPRAM_ENABLE FALSE -#define STM32_HSI_ENABLED TRUE -#define STM32_LSI_ENABLED TRUE -#define STM32_HSE_ENABLED TRUE -#define STM32_LSE_ENABLED FALSE -#define STM32_CLOCK48_REQUIRED TRUE -#define STM32_SW STM32_SW_PLL -#define STM32_PLLSRC STM32_PLLSRC_HSE -#define STM32_PLLM_VALUE 8 -#define STM32_PLLN_VALUE 336 -#define STM32_PLLP_VALUE 2 -#define STM32_PLLQ_VALUE 7 -#define STM32_HPRE STM32_HPRE_DIV1 -#define STM32_PPRE1 STM32_PPRE1_DIV4 -#define STM32_PPRE2 STM32_PPRE2_DIV2 -#define STM32_RTCSEL STM32_RTCSEL_LSI -#define STM32_RTCPRE_VALUE 8 -#define STM32_MCO1SEL STM32_MCO1SEL_HSI -#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 -#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK -#define STM32_MCO2PRE STM32_MCO2PRE_DIV5 -#define STM32_I2SSRC STM32_I2SSRC_CKIN -#define STM32_PLLI2SN_VALUE 192 -#define STM32_PLLI2SR_VALUE 5 - -/* - * IRQ system settings. - */ -#define STM32_IRQ_EXTI0_PRIORITY 6 -#define STM32_IRQ_EXTI1_PRIORITY 6 -#define STM32_IRQ_EXTI2_PRIORITY 6 -#define STM32_IRQ_EXTI3_PRIORITY 6 -#define STM32_IRQ_EXTI4_PRIORITY 6 -#define STM32_IRQ_EXTI5_9_PRIORITY 6 -#define STM32_IRQ_EXTI10_15_PRIORITY 6 -#define STM32_IRQ_EXTI16_PRIORITY 6 -#define STM32_IRQ_EXTI17_PRIORITY 15 -#define STM32_IRQ_EXTI18_PRIORITY 6 -#define STM32_IRQ_EXTI19_PRIORITY 6 -#define STM32_IRQ_EXTI20_PRIORITY 6 -#define STM32_IRQ_EXTI21_PRIORITY 15 -#define STM32_IRQ_EXTI22_PRIORITY 15 - -/* - * ADC driver system settings. - */ -#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 -#define STM32_ADC_USE_ADC1 FALSE -#define STM32_ADC_USE_ADC2 FALSE -#define STM32_ADC_USE_ADC3 FALSE -#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) -#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) -#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) -#define STM32_ADC_ADC1_DMA_PRIORITY 2 -#define STM32_ADC_ADC2_DMA_PRIORITY 2 -#define STM32_ADC_ADC3_DMA_PRIORITY 2 -#define STM32_ADC_IRQ_PRIORITY 6 -#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 -#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6 -#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6 - -/* - * CAN driver system settings. - */ -#define STM32_CAN_USE_CAN1 FALSE -#define STM32_CAN_USE_CAN2 FALSE -#define STM32_CAN_CAN1_IRQ_PRIORITY 11 -#define STM32_CAN_CAN2_IRQ_PRIORITY 11 - -/* - * DAC driver system settings. - */ -#define STM32_DAC_DUAL_MODE FALSE -#define STM32_DAC_USE_DAC1_CH1 FALSE -#define STM32_DAC_USE_DAC1_CH2 FALSE -#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 -#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 -#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 -#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 -#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) - -/* - * GPT driver system settings. - */ -#define STM32_GPT_USE_TIM1 FALSE -#define STM32_GPT_USE_TIM2 FALSE -#define STM32_GPT_USE_TIM3 FALSE -#define STM32_GPT_USE_TIM4 FALSE -#define STM32_GPT_USE_TIM5 FALSE -#define STM32_GPT_USE_TIM6 FALSE -#define STM32_GPT_USE_TIM7 FALSE -#define STM32_GPT_USE_TIM8 FALSE -#define STM32_GPT_USE_TIM9 FALSE -#define STM32_GPT_USE_TIM11 FALSE -#define STM32_GPT_USE_TIM12 FALSE -#define STM32_GPT_USE_TIM14 FALSE -#define STM32_GPT_TIM1_IRQ_PRIORITY 7 -#define STM32_GPT_TIM2_IRQ_PRIORITY 7 -#define STM32_GPT_TIM3_IRQ_PRIORITY 7 -#define STM32_GPT_TIM4_IRQ_PRIORITY 7 -#define STM32_GPT_TIM5_IRQ_PRIORITY 7 -#define STM32_GPT_TIM6_IRQ_PRIORITY 7 -#define STM32_GPT_TIM7_IRQ_PRIORITY 7 -#define STM32_GPT_TIM8_IRQ_PRIORITY 7 -#define STM32_GPT_TIM9_IRQ_PRIORITY 7 -#define STM32_GPT_TIM11_IRQ_PRIORITY 7 -#define STM32_GPT_TIM12_IRQ_PRIORITY 7 -#define STM32_GPT_TIM14_IRQ_PRIORITY 7 - -/* - * I2C driver system settings. - */ -#define STM32_I2C_USE_I2C1 FALSE -#define STM32_I2C_USE_I2C2 FALSE -#define STM32_I2C_USE_I2C3 FALSE -#define STM32_I2C_BUSY_TIMEOUT 50 -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_I2C_I2C1_IRQ_PRIORITY 5 -#define STM32_I2C_I2C2_IRQ_PRIORITY 5 -#define STM32_I2C_I2C3_IRQ_PRIORITY 5 -#define STM32_I2C_I2C1_DMA_PRIORITY 3 -#define STM32_I2C_I2C2_DMA_PRIORITY 3 -#define STM32_I2C_I2C3_DMA_PRIORITY 3 -#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") - -/* - * I2S driver system settings. - */ -#define STM32_I2S_USE_SPI2 FALSE -#define STM32_I2S_USE_SPI3 FALSE -#define STM32_I2S_SPI2_IRQ_PRIORITY 10 -#define STM32_I2S_SPI3_IRQ_PRIORITY 10 -#define STM32_I2S_SPI2_DMA_PRIORITY 1 -#define STM32_I2S_SPI3_DMA_PRIORITY 1 -#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) -#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") - -/* - * ICU driver system settings. - */ -#define STM32_ICU_USE_TIM1 FALSE -#define STM32_ICU_USE_TIM2 FALSE -#define STM32_ICU_USE_TIM3 FALSE -#define STM32_ICU_USE_TIM4 FALSE -#define STM32_ICU_USE_TIM5 FALSE -#define STM32_ICU_USE_TIM8 FALSE -#define STM32_ICU_USE_TIM9 FALSE -#define STM32_ICU_TIM1_IRQ_PRIORITY 7 -#define STM32_ICU_TIM2_IRQ_PRIORITY 7 -#define STM32_ICU_TIM3_IRQ_PRIORITY 7 -#define STM32_ICU_TIM4_IRQ_PRIORITY 7 -#define STM32_ICU_TIM5_IRQ_PRIORITY 7 -#define STM32_ICU_TIM8_IRQ_PRIORITY 7 -#define STM32_ICU_TIM9_IRQ_PRIORITY 7 - -/* - * MAC driver system settings. - */ -#define STM32_MAC_TRANSMIT_BUFFERS 2 -#define STM32_MAC_RECEIVE_BUFFERS 4 -#define STM32_MAC_BUFFERS_SIZE 1522 -#define STM32_MAC_PHY_TIMEOUT 100 -#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE -#define STM32_MAC_ETH1_IRQ_PRIORITY 13 -#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 - -/* - * PWM driver system settings. - */ -#define STM32_PWM_USE_ADVANCED FALSE -#define STM32_PWM_USE_TIM1 FALSE -#define STM32_PWM_USE_TIM2 FALSE -#define STM32_PWM_USE_TIM3 FALSE -#define STM32_PWM_USE_TIM4 FALSE -#define STM32_PWM_USE_TIM5 FALSE -#define STM32_PWM_USE_TIM8 FALSE -#define STM32_PWM_USE_TIM9 FALSE -#define STM32_PWM_TIM1_IRQ_PRIORITY 7 -#define STM32_PWM_TIM2_IRQ_PRIORITY 7 -#define STM32_PWM_TIM3_IRQ_PRIORITY 7 -#define STM32_PWM_TIM4_IRQ_PRIORITY 7 -#define STM32_PWM_TIM5_IRQ_PRIORITY 7 -#define STM32_PWM_TIM8_IRQ_PRIORITY 7 -#define STM32_PWM_TIM9_IRQ_PRIORITY 7 - -/* - * RTC driver system settings. - */ -#define STM32_RTC_PRESA_VALUE 32 -#define STM32_RTC_PRESS_VALUE 1024 -#define STM32_RTC_CR_INIT 0 -#define STM32_RTC_TAMPCR_INIT 0 - -/* - * SDC driver system settings. - */ -#define STM32_SDC_SDIO_DMA_PRIORITY 3 -#define STM32_SDC_SDIO_IRQ_PRIORITY 9 -#define STM32_SDC_WRITE_TIMEOUT_MS 1000 -#define STM32_SDC_READ_TIMEOUT_MS 1000 -#define STM32_SDC_CLOCK_ACTIVATION_DELAY 10 -#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE -#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) - -/* - * SERIAL driver system settings. - */ -#define STM32_SERIAL_USE_USART1 FALSE -#define STM32_SERIAL_USE_USART2 FALSE -#define STM32_SERIAL_USE_USART3 FALSE -#define STM32_SERIAL_USE_UART4 FALSE -#define STM32_SERIAL_USE_UART5 FALSE -#define STM32_SERIAL_USE_USART6 FALSE -#define STM32_SERIAL_USART1_PRIORITY 12 -#define STM32_SERIAL_USART2_PRIORITY 12 -#define STM32_SERIAL_USART3_PRIORITY 12 -#define STM32_SERIAL_UART4_PRIORITY 12 -#define STM32_SERIAL_UART5_PRIORITY 12 -#define STM32_SERIAL_USART6_PRIORITY 12 - -/* - * SPI driver system settings. - */ -#define STM32_SPI_USE_SPI1 FALSE -#define STM32_SPI_USE_SPI2 FALSE -#define STM32_SPI_USE_SPI3 FALSE -#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) -#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) -#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) -#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_SPI_SPI1_DMA_PRIORITY 1 -#define STM32_SPI_SPI2_DMA_PRIORITY 1 -#define STM32_SPI_SPI3_DMA_PRIORITY 1 -#define STM32_SPI_SPI1_IRQ_PRIORITY 10 -#define STM32_SPI_SPI2_IRQ_PRIORITY 10 -#define STM32_SPI_SPI3_IRQ_PRIORITY 10 -#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") - -/* - * ST driver system settings. - */ -#define STM32_ST_IRQ_PRIORITY 8 -#define STM32_ST_USE_TIMER 2 - -/* - * UART driver system settings. - */ -#define STM32_UART_USE_USART1 FALSE -#define STM32_UART_USE_USART2 FALSE -#define STM32_UART_USE_USART3 FALSE -#define STM32_UART_USE_UART4 FALSE -#define STM32_UART_USE_UART5 FALSE -#define STM32_UART_USE_USART6 FALSE -#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) -#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) -#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) -#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) -#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) -#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) -#define STM32_UART_USART1_IRQ_PRIORITY 12 -#define STM32_UART_USART2_IRQ_PRIORITY 12 -#define STM32_UART_USART3_IRQ_PRIORITY 12 -#define STM32_UART_UART4_IRQ_PRIORITY 12 -#define STM32_UART_UART5_IRQ_PRIORITY 12 -#define STM32_UART_USART6_IRQ_PRIORITY 12 -#define STM32_UART_USART1_DMA_PRIORITY 0 -#define STM32_UART_USART2_DMA_PRIORITY 0 -#define STM32_UART_USART3_DMA_PRIORITY 0 -#define STM32_UART_UART4_DMA_PRIORITY 0 -#define STM32_UART_UART5_DMA_PRIORITY 0 -#define STM32_UART_USART6_DMA_PRIORITY 0 -#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") - -/* - * USB driver system settings. - */ -#define STM32_USB_USE_OTG1 TRUE -#define STM32_USB_USE_OTG2 FALSE -#define STM32_USB_OTG1_IRQ_PRIORITY 14 -#define STM32_USB_OTG2_IRQ_PRIORITY 14 -#define STM32_USB_OTG1_RX_FIFO_SIZE 512 -#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 -#define STM32_USB_HOST_WAKEUP_DURATION 2 - -#define STM32_USB_OTG_THREAD_PRIO NORMALPRIO+1 -#define STM32_USB_OTG_THREAD_STACK_SIZE 128 - -/* - * WDG driver system settings. - */ -#define STM32_WDG_USE_IWDG FALSE - -#endif /* MCUCONF_H */ diff --git a/platforms/chibios/GENERIC_STM32_F446XE/board/board.mk b/platforms/chibios/GENERIC_STM32_F446XE/board/board.mk deleted file mode 100644 index 57897941ca..0000000000 --- a/platforms/chibios/GENERIC_STM32_F446XE/board/board.mk +++ /dev/null @@ -1,9 +0,0 @@ -# List of all the board related files. -BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_F446RE/board.c - -# Required include directories -BOARDINC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_F446RE - -# Shared variables -ALLCSRC += $(BOARDSRC) -ALLINC += $(BOARDINC) diff --git a/platforms/chibios/GENERIC_STM32_F446XE/configs/board.h b/platforms/chibios/GENERIC_STM32_F446XE/configs/board.h deleted file mode 100644 index 80dfcffa99..0000000000 --- a/platforms/chibios/GENERIC_STM32_F446XE/configs/board.h +++ /dev/null @@ -1,24 +0,0 @@ -/* Copyright 2020 Nick Brassel (tzarc) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#pragma once - -#define STM32_HSECLK 16000000 -// The following is required to disable the pull-down on PA9, when PA9 is used for the keyboard matrix: -#define BOARD_OTG_NOVBUSSENS - -#include_next "board.h" - -#undef STM32_HSE_BYPASS diff --git a/platforms/chibios/GENERIC_STM32_F446XE/configs/config.h b/platforms/chibios/GENERIC_STM32_F446XE/configs/config.h deleted file mode 100644 index cc52a953ed..0000000000 --- a/platforms/chibios/GENERIC_STM32_F446XE/configs/config.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright 2021 Andrei Purdea - * - * 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 . - */ - -/* Address for jumping to bootloader on STM32 chips. */ -/* It is chip dependent, the correct number can be looked up by checking against ST's application note AN2606. - */ -#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000 -#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP -# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE -#endif diff --git a/platforms/chibios/GENERIC_STM32_F446XE/configs/mcuconf.h b/platforms/chibios/GENERIC_STM32_F446XE/configs/mcuconf.h deleted file mode 100644 index d2de75590e..0000000000 --- a/platforms/chibios/GENERIC_STM32_F446XE/configs/mcuconf.h +++ /dev/null @@ -1,361 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - 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 License 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. -*/ - -#ifndef MCUCONF_H -#define MCUCONF_H - -/* - * STM32F4xx drivers configuration. - * The following settings override the default settings present in - * the various device driver implementation headers. - * Note that the settings for each driver only have effect if the whole - * driver is enabled in halconf.h. - * - * IRQ priorities: - * 15...0 Lowest...Highest. - * - * DMA priorities: - * 0...3 Lowest...Highest. - */ - -#define STM32F4xx_MCUCONF - -/* - * HAL driver system settings. - */ -#define STM32_NO_INIT FALSE -#define STM32_HSI_ENABLED FALSE -#define STM32_LSI_ENABLED TRUE -#define STM32_HSE_ENABLED TRUE -#define STM32_LSE_ENABLED FALSE -#define STM32_CLOCK48_REQUIRED TRUE -#define STM32_SW STM32_SW_PLL -#define STM32_PLLSRC STM32_PLLSRC_HSE -#define STM32_PLLM_VALUE 8 -#define STM32_PLLN_VALUE 180 -#define STM32_PLLP_VALUE 2 -#define STM32_PLLQ_VALUE 7 -#define STM32_PLLI2SN_VALUE 192 -#define STM32_PLLI2SM_VALUE 8 -#define STM32_PLLI2SR_VALUE 4 -#define STM32_PLLI2SP_VALUE 4 -#define STM32_PLLI2SQ_VALUE 4 -#define STM32_PLLSAIN_VALUE 192 -#define STM32_PLLSAIM_VALUE 8 -#define STM32_PLLSAIP_VALUE 8 -#define STM32_PLLSAIQ_VALUE 4 -#define STM32_HPRE STM32_HPRE_DIV1 -#define STM32_PPRE1 STM32_PPRE1_DIV4 -#define STM32_PPRE2 STM32_PPRE2_DIV2 -#define STM32_RTCSEL STM32_RTCSEL_LSI -#define STM32_RTCPRE_VALUE 8 -#define STM32_MCO1SEL STM32_MCO1SEL_HSE -#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 -#define STM32_MCO2SEL STM32_MCO2SEL_PLLI2S -#define STM32_MCO2PRE STM32_MCO2PRE_DIV1 -#define STM32_I2SSRC STM32_I2SSRC_PLLI2S -#define STM32_SAI1SEL STM32_SAI2SEL_PLLR -#define STM32_SAI2SEL STM32_SAI2SEL_PLLR -#define STM32_CK48MSEL STM32_CK48MSEL_PLLALT -#define STM32_PVD_ENABLE FALSE -#define STM32_PLS STM32_PLS_LEV0 -#define STM32_BKPRAM_ENABLE FALSE - -/* - * IRQ system settings. - */ -#define STM32_IRQ_EXTI0_PRIORITY 6 -#define STM32_IRQ_EXTI1_PRIORITY 6 -#define STM32_IRQ_EXTI2_PRIORITY 6 -#define STM32_IRQ_EXTI3_PRIORITY 6 -#define STM32_IRQ_EXTI4_PRIORITY 6 -#define STM32_IRQ_EXTI5_9_PRIORITY 6 -#define STM32_IRQ_EXTI10_15_PRIORITY 6 -#define STM32_IRQ_EXTI16_PRIORITY 6 -#define STM32_IRQ_EXTI17_PRIORITY 15 -#define STM32_IRQ_EXTI18_PRIORITY 6 -#define STM32_IRQ_EXTI19_PRIORITY 6 -#define STM32_IRQ_EXTI20_PRIORITY 6 -#define STM32_IRQ_EXTI21_PRIORITY 15 -#define STM32_IRQ_EXTI22_PRIORITY 15 - -/* - * ADC driver system settings. - */ -#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 -#define STM32_ADC_USE_ADC1 FALSE -#define STM32_ADC_USE_ADC2 FALSE -#define STM32_ADC_USE_ADC3 FALSE -#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) -#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) -#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) -#define STM32_ADC_ADC1_DMA_PRIORITY 2 -#define STM32_ADC_ADC2_DMA_PRIORITY 2 -#define STM32_ADC_ADC3_DMA_PRIORITY 2 -#define STM32_ADC_IRQ_PRIORITY 6 -#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 -#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6 -#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6 - -/* - * CAN driver system settings. - */ -#define STM32_CAN_USE_CAN1 FALSE -#define STM32_CAN_USE_CAN2 FALSE -#define STM32_CAN_CAN1_IRQ_PRIORITY 11 -#define STM32_CAN_CAN2_IRQ_PRIORITY 11 - -/* - * DAC driver system settings. - */ -#define STM32_DAC_DUAL_MODE FALSE -#define STM32_DAC_USE_DAC1_CH1 FALSE -#define STM32_DAC_USE_DAC1_CH2 FALSE -#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 -#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 -#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 -#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 -#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) - -/* - * GPT driver system settings. - */ -#define STM32_GPT_USE_TIM1 FALSE -#define STM32_GPT_USE_TIM2 FALSE -#define STM32_GPT_USE_TIM3 FALSE -#define STM32_GPT_USE_TIM4 FALSE -#define STM32_GPT_USE_TIM5 FALSE -#define STM32_GPT_USE_TIM6 FALSE -#define STM32_GPT_USE_TIM7 FALSE -#define STM32_GPT_USE_TIM8 FALSE -#define STM32_GPT_USE_TIM9 FALSE -#define STM32_GPT_USE_TIM11 FALSE -#define STM32_GPT_USE_TIM12 FALSE -#define STM32_GPT_USE_TIM14 FALSE -#define STM32_GPT_TIM1_IRQ_PRIORITY 7 -#define STM32_GPT_TIM2_IRQ_PRIORITY 7 -#define STM32_GPT_TIM3_IRQ_PRIORITY 7 -#define STM32_GPT_TIM4_IRQ_PRIORITY 7 -#define STM32_GPT_TIM5_IRQ_PRIORITY 7 -#define STM32_GPT_TIM6_IRQ_PRIORITY 7 -#define STM32_GPT_TIM7_IRQ_PRIORITY 7 -#define STM32_GPT_TIM8_IRQ_PRIORITY 7 -#define STM32_GPT_TIM9_IRQ_PRIORITY 7 -#define STM32_GPT_TIM11_IRQ_PRIORITY 7 -#define STM32_GPT_TIM12_IRQ_PRIORITY 7 -#define STM32_GPT_TIM14_IRQ_PRIORITY 7 - -/* - * I2C driver system settings. - */ -#define STM32_I2C_USE_I2C1 FALSE -#define STM32_I2C_USE_I2C2 FALSE -#define STM32_I2C_USE_I2C3 FALSE -#define STM32_I2C_BUSY_TIMEOUT 50 -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_I2C_I2C1_IRQ_PRIORITY 5 -#define STM32_I2C_I2C2_IRQ_PRIORITY 5 -#define STM32_I2C_I2C3_IRQ_PRIORITY 5 -#define STM32_I2C_I2C1_DMA_PRIORITY 3 -#define STM32_I2C_I2C2_DMA_PRIORITY 3 -#define STM32_I2C_I2C3_DMA_PRIORITY 3 -#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") - -/* - * I2S driver system settings. - */ -#define STM32_I2S_USE_SPI2 FALSE -#define STM32_I2S_USE_SPI3 FALSE -#define STM32_I2S_SPI2_IRQ_PRIORITY 10 -#define STM32_I2S_SPI3_IRQ_PRIORITY 10 -#define STM32_I2S_SPI2_DMA_PRIORITY 1 -#define STM32_I2S_SPI3_DMA_PRIORITY 1 -#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) -#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") - -/* - * ICU driver system settings. - */ -#define STM32_ICU_USE_TIM1 FALSE -#define STM32_ICU_USE_TIM2 FALSE -#define STM32_ICU_USE_TIM3 FALSE -#define STM32_ICU_USE_TIM4 FALSE -#define STM32_ICU_USE_TIM5 FALSE -#define STM32_ICU_USE_TIM8 FALSE -#define STM32_ICU_USE_TIM9 FALSE -#define STM32_ICU_TIM1_IRQ_PRIORITY 7 -#define STM32_ICU_TIM2_IRQ_PRIORITY 7 -#define STM32_ICU_TIM3_IRQ_PRIORITY 7 -#define STM32_ICU_TIM4_IRQ_PRIORITY 7 -#define STM32_ICU_TIM5_IRQ_PRIORITY 7 -#define STM32_ICU_TIM8_IRQ_PRIORITY 7 -#define STM32_ICU_TIM9_IRQ_PRIORITY 7 - -/* - * MAC driver system settings. - */ -#define STM32_MAC_TRANSMIT_BUFFERS 2 -#define STM32_MAC_RECEIVE_BUFFERS 4 -#define STM32_MAC_BUFFERS_SIZE 1522 -#define STM32_MAC_PHY_TIMEOUT 100 -#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE -#define STM32_MAC_ETH1_IRQ_PRIORITY 13 -#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 - -/* - * PWM driver system settings. - */ -#define STM32_PWM_USE_ADVANCED FALSE -#define STM32_PWM_USE_TIM1 FALSE -#define STM32_PWM_USE_TIM2 FALSE -#define STM32_PWM_USE_TIM3 FALSE -#define STM32_PWM_USE_TIM4 FALSE -#define STM32_PWM_USE_TIM5 FALSE -#define STM32_PWM_USE_TIM8 FALSE -#define STM32_PWM_USE_TIM9 FALSE -#define STM32_PWM_TIM1_IRQ_PRIORITY 7 -#define STM32_PWM_TIM2_IRQ_PRIORITY 7 -#define STM32_PWM_TIM3_IRQ_PRIORITY 7 -#define STM32_PWM_TIM4_IRQ_PRIORITY 7 -#define STM32_PWM_TIM5_IRQ_PRIORITY 7 -#define STM32_PWM_TIM8_IRQ_PRIORITY 7 -#define STM32_PWM_TIM9_IRQ_PRIORITY 7 - -/* - * SDC driver system settings. - */ -#define STM32_SDC_SDIO_DMA_PRIORITY 3 -#define STM32_SDC_SDIO_IRQ_PRIORITY 9 -#define STM32_SDC_WRITE_TIMEOUT_MS 1000 -#define STM32_SDC_READ_TIMEOUT_MS 1000 -#define STM32_SDC_CLOCK_ACTIVATION_DELAY 10 -#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE -#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) - -/* - * SERIAL driver system settings. - */ -#define STM32_SERIAL_USE_USART1 FALSE -#define STM32_SERIAL_USE_USART2 FALSE -#define STM32_SERIAL_USE_USART3 FALSE -#define STM32_SERIAL_USE_UART4 FALSE -#define STM32_SERIAL_USE_UART5 FALSE -#define STM32_SERIAL_USE_USART6 FALSE -#define STM32_SERIAL_USE_UART7 FALSE -#define STM32_SERIAL_USE_UART8 FALSE -#define STM32_SERIAL_USART1_PRIORITY 12 -#define STM32_SERIAL_USART2_PRIORITY 12 -#define STM32_SERIAL_USART3_PRIORITY 12 -#define STM32_SERIAL_UART4_PRIORITY 12 -#define STM32_SERIAL_UART5_PRIORITY 12 -#define STM32_SERIAL_USART6_PRIORITY 12 -#define STM32_SERIAL_UART7_PRIORITY 12 -#define STM32_SERIAL_UART8_PRIORITY 12 - -/* - * SPI driver system settings. - */ -#define STM32_SPI_USE_SPI1 FALSE -#define STM32_SPI_USE_SPI2 FALSE -#define STM32_SPI_USE_SPI3 FALSE -#define STM32_SPI_USE_SPI4 FALSE -#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) -#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) -#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) -#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_SPI_SPI4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) -#define STM32_SPI_SPI4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) -#define STM32_SPI_SPI1_DMA_PRIORITY 1 -#define STM32_SPI_SPI2_DMA_PRIORITY 1 -#define STM32_SPI_SPI3_DMA_PRIORITY 1 -#define STM32_SPI_SPI4_DMA_PRIORITY 1 -#define STM32_SPI_SPI1_IRQ_PRIORITY 10 -#define STM32_SPI_SPI2_IRQ_PRIORITY 10 -#define STM32_SPI_SPI3_IRQ_PRIORITY 10 -#define STM32_SPI_SPI4_IRQ_PRIORITY 10 -#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") - -/* - * ST driver system settings. - */ -#define STM32_ST_IRQ_PRIORITY 8 -#define STM32_ST_USE_TIMER 2 - -/* - * UART driver system settings. - */ -#define STM32_UART_USE_USART1 FALSE -#define STM32_UART_USE_USART2 FALSE -#define STM32_UART_USE_USART3 FALSE -#define STM32_UART_USE_UART4 FALSE -#define STM32_UART_USE_UART5 FALSE -#define STM32_UART_USE_USART6 FALSE -#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) -#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) -#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) -#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) -#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) -#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) -#define STM32_UART_USART1_IRQ_PRIORITY 12 -#define STM32_UART_USART2_IRQ_PRIORITY 12 -#define STM32_UART_USART3_IRQ_PRIORITY 12 -#define STM32_UART_UART4_IRQ_PRIORITY 12 -#define STM32_UART_UART5_IRQ_PRIORITY 12 -#define STM32_UART_USART6_IRQ_PRIORITY 12 -#define STM32_UART_USART1_DMA_PRIORITY 0 -#define STM32_UART_USART2_DMA_PRIORITY 0 -#define STM32_UART_USART3_DMA_PRIORITY 0 -#define STM32_UART_UART4_DMA_PRIORITY 0 -#define STM32_UART_UART5_DMA_PRIORITY 0 -#define STM32_UART_USART6_DMA_PRIORITY 0 -#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") - -/* - * USB driver system settings. - */ -#define STM32_USB_USE_OTG1 TRUE -#define STM32_USB_USE_OTG2 FALSE -#define STM32_USB_OTG1_IRQ_PRIORITY 14 -#define STM32_USB_OTG2_IRQ_PRIORITY 14 -#define STM32_USB_OTG1_RX_FIFO_SIZE 512 -#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 -#define STM32_USB_OTG_THREAD_PRIO LOWPRIO -#define STM32_USB_OTG_THREAD_STACK_SIZE 128 -#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 - -/* - * WDG driver system settings. - */ -#define STM32_WDG_USE_IWDG FALSE - -#endif /* MCUCONF_H */ diff --git a/platforms/chibios/GENERIC_STM32_G431XB/board/board.mk b/platforms/chibios/GENERIC_STM32_G431XB/board/board.mk deleted file mode 100644 index 0acbcd83c7..0000000000 --- a/platforms/chibios/GENERIC_STM32_G431XB/board/board.mk +++ /dev/null @@ -1,9 +0,0 @@ -# List of all the board related files. -BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_G431RB/board.c - -# Required include directories -BOARDINC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_G431RB - -# Shared variables -ALLCSRC += $(BOARDSRC) -ALLINC += $(BOARDINC) diff --git a/platforms/chibios/GENERIC_STM32_G431XB/configs/config.h b/platforms/chibios/GENERIC_STM32_G431XB/configs/config.h deleted file mode 100644 index 39ce627e77..0000000000 --- a/platforms/chibios/GENERIC_STM32_G431XB/configs/config.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright 2018-2020 Nick Brassel (@tzarc) - * - * 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 . - */ - -/* Address for jumping to bootloader on STM32 chips. */ -/* It is chip dependent, the correct number can be looked up here (page 175): - * http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf - * This also requires a patch to chibios: - * /tmk_core/tool/chibios/ch-bootloader-jump.patch - */ -#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000 diff --git a/platforms/chibios/GENERIC_STM32_G431XB/configs/mcuconf.h b/platforms/chibios/GENERIC_STM32_G431XB/configs/mcuconf.h deleted file mode 100644 index 182d4885d7..0000000000 --- a/platforms/chibios/GENERIC_STM32_G431XB/configs/mcuconf.h +++ /dev/null @@ -1,307 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - 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 License 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. -*/ - -/* - * STM32G4xx drivers configuration. - * The following settings override the default settings present in - * the various device driver implementation headers. - * Note that the settings for each driver only have effect if the whole - * driver is enabled in halconf.h. - * - * IRQ priorities: - * 15...0 Lowest...Highest. - * - * DMA priorities: - * 0...3 Lowest...Highest. - */ - -#ifndef MCUCONF_H -#define MCUCONF_H - -#define STM32G4xx_MCUCONF -#define STM32G431_MCUCONF -#define STM32G441_MCUCONF - -/* - * HAL driver system settings. - */ -#define STM32_NO_INIT FALSE -#define STM32_VOS STM32_VOS_RANGE1 -#define STM32_PWR_CR2 (PWR_CR2_PLS_LEV0) -#define STM32_PWR_CR3 (PWR_CR3_EIWF) -#define STM32_PWR_CR4 (0U) -#define STM32_HSI16_ENABLED TRUE -#define STM32_HSI48_ENABLED TRUE -#define STM32_HSE_ENABLED FALSE -#define STM32_LSI_ENABLED TRUE -#define STM32_LSE_ENABLED FALSE -#define STM32_SW STM32_SW_PLLRCLK -#define STM32_PLLSRC STM32_PLLSRC_HSI16 -#define STM32_PLLM_VALUE 4 -#define STM32_PLLN_VALUE 80 -#define STM32_PLLPDIV_VALUE 0 -#define STM32_PLLP_VALUE 7 -#define STM32_PLLQ_VALUE 8 -#define STM32_PLLR_VALUE 2 -#define STM32_HPRE STM32_HPRE_DIV1 -#define STM32_PPRE1 STM32_PPRE1_DIV1 -#define STM32_PPRE2 STM32_PPRE2_DIV1 -#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK -#define STM32_MCOPRE STM32_MCOPRE_DIV1 -#define STM32_LSCOSEL STM32_LSCOSEL_NOCLOCK - -/* - * Peripherals clock sources. - */ -#define STM32_USART1SEL STM32_USART1SEL_SYSCLK -#define STM32_USART2SEL STM32_USART2SEL_SYSCLK -#define STM32_USART3SEL STM32_USART3SEL_SYSCLK -#define STM32_UART4SEL STM32_UART4SEL_SYSCLK -#define STM32_LPUART1SEL STM32_LPUART1SEL_PCLK1 -#define STM32_I2C1SEL STM32_I2C1SEL_PCLK1 -#define STM32_I2C2SEL STM32_I2C2SEL_PCLK1 -#define STM32_I2C3SEL STM32_I2C3SEL_PCLK1 -#define STM32_LPTIM1SEL STM32_LPTIM1SEL_PCLK1 -#define STM32_SAI1SEL STM32_SAI1SEL_SYSCLK -#define STM32_I2S23SEL STM32_I2S23SEL_SYSCLK -#define STM32_FDCANSEL STM32_FDCANSEL_PCLK1 -#define STM32_CLK48SEL STM32_CLK48SEL_HSI48 -#define STM32_ADC12SEL STM32_ADC12SEL_PLLPCLK -#define STM32_RTCSEL STM32_RTCSEL_NOCLOCK - -/* - * IRQ system settings. - */ -#define STM32_IRQ_EXTI0_PRIORITY 6 -#define STM32_IRQ_EXTI1_PRIORITY 6 -#define STM32_IRQ_EXTI2_PRIORITY 6 -#define STM32_IRQ_EXTI3_PRIORITY 6 -#define STM32_IRQ_EXTI4_PRIORITY 6 -#define STM32_IRQ_EXTI5_9_PRIORITY 6 -#define STM32_IRQ_EXTI10_15_PRIORITY 6 -#define STM32_IRQ_EXTI164041_PRIORITY 6 -#define STM32_IRQ_EXTI17_PRIORITY 6 -#define STM32_IRQ_EXTI18_PRIORITY 6 -#define STM32_IRQ_EXTI19_PRIORITY 6 -#define STM32_IRQ_EXTI20_PRIORITY 6 -#define STM32_IRQ_EXTI212229_PRIORITY 6 -#define STM32_IRQ_EXTI30_32_PRIORITY 6 -#define STM32_IRQ_EXTI33_PRIORITY 6 - -#define STM32_IRQ_FDCAN1_PRIORITY 10 - -#define STM32_IRQ_TIM1_BRK_TIM15_PRIORITY 7 -#define STM32_IRQ_TIM1_UP_TIM16_PRIORITY 7 -#define STM32_IRQ_TIM1_TRGCO_TIM17_PRIORITY 7 -#define STM32_IRQ_TIM1_CC_PRIORITY 7 -#define STM32_IRQ_TIM2_PRIORITY 7 -#define STM32_IRQ_TIM3_PRIORITY 7 -#define STM32_IRQ_TIM4_PRIORITY 7 -#define STM32_IRQ_TIM6_PRIORITY 7 -#define STM32_IRQ_TIM7_PRIORITY 7 -#define STM32_IRQ_TIM8_UP_PRIORITY 7 -#define STM32_IRQ_TIM8_CC_PRIORITY 7 - -#define STM32_IRQ_USART1_PRIORITY 12 -#define STM32_IRQ_USART2_PRIORITY 12 -#define STM32_IRQ_USART3_PRIORITY 12 -#define STM32_IRQ_UART4_PRIORITY 12 -#define STM32_IRQ_LPUART1_PRIORITY 12 - -/* - * ADC driver system settings. - */ -#define STM32_ADC_DUAL_MODE FALSE -#define STM32_ADC_COMPACT_SAMPLES FALSE -#define STM32_ADC_USE_ADC1 FALSE -#define STM32_ADC_USE_ADC2 FALSE -#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_ADC_ADC1_DMA_PRIORITY 2 -#define STM32_ADC_ADC2_DMA_PRIORITY 2 -#define STM32_ADC_ADC12_IRQ_PRIORITY 5 -#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 5 -#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 5 -#define STM32_ADC_ADC12_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV4 -#define STM32_ADC_ADC12_PRESC ADC_CCR_PRESC_DIV2 - -/* - * CAN driver system settings. - */ -#define STM32_CAN_USE_FDCAN1 FALSE - -/* - * DAC driver system settings. - */ -#define STM32_DAC_DUAL_MODE FALSE -#define STM32_DAC_USE_DAC1_CH1 FALSE -#define STM32_DAC_USE_DAC1_CH2 FALSE -#define STM32_DAC_USE_DAC3_CH1 FALSE -#define STM32_DAC_USE_DAC3_CH2 FALSE -#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 -#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 -#define STM32_DAC_DAC3_CH1_IRQ_PRIORITY 10 -#define STM32_DAC_DAC3_CH2_IRQ_PRIORITY 10 -#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 -#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 -#define STM32_DAC_DAC3_CH1_DMA_PRIORITY 2 -#define STM32_DAC_DAC3_CH2_DMA_PRIORITY 2 -#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_DAC_DAC3_CH1_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_DAC_DAC3_CH2_DMA_STREAM STM32_DMA_STREAM_ID_ANY - -/* - * GPT driver system settings. - */ -#define STM32_GPT_USE_TIM1 FALSE -#define STM32_GPT_USE_TIM2 FALSE -#define STM32_GPT_USE_TIM3 FALSE -#define STM32_GPT_USE_TIM4 FALSE -#define STM32_GPT_USE_TIM6 FALSE -#define STM32_GPT_USE_TIM7 FALSE -#define STM32_GPT_USE_TIM8 FALSE -#define STM32_GPT_USE_TIM15 FALSE -#define STM32_GPT_USE_TIM16 FALSE -#define STM32_GPT_USE_TIM17 FALSE - -/* - * I2C driver system settings. - */ -#define STM32_I2C_USE_I2C1 FALSE -#define STM32_I2C_USE_I2C2 FALSE -#define STM32_I2C_USE_I2C3 FALSE -#define STM32_I2C_BUSY_TIMEOUT 50 -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_I2C_I2C1_IRQ_PRIORITY 5 -#define STM32_I2C_I2C2_IRQ_PRIORITY 5 -#define STM32_I2C_I2C3_IRQ_PRIORITY 5 -#define STM32_I2C_I2C1_DMA_PRIORITY 3 -#define STM32_I2C_I2C2_DMA_PRIORITY 3 -#define STM32_I2C_I2C3_DMA_PRIORITY 3 -#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") - -/* - * ICU driver system settings. - */ -#define STM32_ICU_USE_TIM1 FALSE -#define STM32_ICU_USE_TIM2 FALSE -#define STM32_ICU_USE_TIM3 FALSE -#define STM32_ICU_USE_TIM4 FALSE -#define STM32_ICU_USE_TIM8 FALSE -#define STM32_ICU_USE_TIM15 FALSE - -/* - * PWM driver system settings. - */ -#define STM32_PWM_USE_ADVANCED FALSE -#define STM32_PWM_USE_TIM1 FALSE -#define STM32_PWM_USE_TIM2 FALSE -#define STM32_PWM_USE_TIM3 FALSE -#define STM32_PWM_USE_TIM4 FALSE -#define STM32_PWM_USE_TIM8 FALSE -#define STM32_PWM_USE_TIM15 FALSE -#define STM32_PWM_USE_TIM16 FALSE -#define STM32_PWM_USE_TIM17 FALSE - -/* - * RTC driver system settings. - */ - -/* - * SDC driver system settings. - */ - -/* - * SERIAL driver system settings. - */ -#define STM32_SERIAL_USE_USART1 FALSE -#define STM32_SERIAL_USE_USART2 FALSE -#define STM32_SERIAL_USE_USART3 FALSE -#define STM32_SERIAL_USE_UART4 FALSE -#define STM32_SERIAL_USE_LPUART1 FALSE - -/* - * SPI driver system settings. - */ -#define STM32_SPI_USE_SPI1 FALSE -#define STM32_SPI_USE_SPI2 FALSE -#define STM32_SPI_USE_SPI3 FALSE -#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_SPI_SPI1_DMA_PRIORITY 1 -#define STM32_SPI_SPI2_DMA_PRIORITY 1 -#define STM32_SPI_SPI3_DMA_PRIORITY 1 -#define STM32_SPI_SPI1_IRQ_PRIORITY 10 -#define STM32_SPI_SPI2_IRQ_PRIORITY 10 -#define STM32_SPI_SPI3_IRQ_PRIORITY 10 -#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") - -/* - * ST driver system settings. - */ -#define STM32_ST_IRQ_PRIORITY 8 -#define STM32_ST_USE_TIMER 2 - -/* - * TRNG driver system settings. - */ -#define STM32_TRNG_USE_RNG1 FALSE - -/* - * UART driver system settings. - */ -#define STM32_UART_USE_USART1 FALSE -#define STM32_UART_USE_USART2 FALSE -#define STM32_UART_USE_USART3 FALSE -#define STM32_UART_USE_UART4 FALSE -#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_UART_USART1_DMA_PRIORITY 0 -#define STM32_UART_USART2_DMA_PRIORITY 0 -#define STM32_UART_USART3_DMA_PRIORITY 0 -#define STM32_UART_UART4_DMA_PRIORITY 0 -#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") - -/* - * USB driver system settings. - */ -#define STM32_USB_USE_USB1 TRUE -#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE -#define STM32_USB_USB1_HP_IRQ_PRIORITY 5 -#define STM32_USB_USB1_LP_IRQ_PRIORITY 6 - -/* - * WDG driver system settings. - */ -#define STM32_WDG_USE_IWDG FALSE - -#endif /* MCUCONF_H */ diff --git a/platforms/chibios/GENERIC_STM32_G474XE/board/board.mk b/platforms/chibios/GENERIC_STM32_G474XE/board/board.mk deleted file mode 100644 index 957adf509b..0000000000 --- a/platforms/chibios/GENERIC_STM32_G474XE/board/board.mk +++ /dev/null @@ -1,9 +0,0 @@ -# List of all the board related files. -BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_G474RE/board.c - -# Required include directories -BOARDINC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_G474RE - -# Shared variables -ALLCSRC += $(BOARDSRC) -ALLINC += $(BOARDINC) diff --git a/platforms/chibios/GENERIC_STM32_G474XE/configs/config.h b/platforms/chibios/GENERIC_STM32_G474XE/configs/config.h deleted file mode 100644 index eb74d68e85..0000000000 --- a/platforms/chibios/GENERIC_STM32_G474XE/configs/config.h +++ /dev/null @@ -1,30 +0,0 @@ -/* Copyright 2020 Nick Brassel (tzarc) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#pragma once - -#ifndef STM32_BOOTLOADER_DUAL_BANK -# define STM32_BOOTLOADER_DUAL_BANK FALSE -#endif - -// To Enter bootloader from `RESET` keycode, you'll need to dedicate a GPIO to -// charge an RC network on the BOOT0 pin. -// See the QMK Discord's #hardware channel pins for an example circuit. -// Insert these two lines into your keyboard's `config.h` file. -// In the case below, PB7 is selected to charge. -#if 0 -#define STM32_BOOTLOADER_DUAL_BANK TRUE -#define STM32_BOOTLOADER_DUAL_BANK_GPIO B7 -#endif \ No newline at end of file diff --git a/platforms/chibios/GENERIC_STM32_G474XE/configs/mcuconf.h b/platforms/chibios/GENERIC_STM32_G474XE/configs/mcuconf.h deleted file mode 100644 index 117e920e3b..0000000000 --- a/platforms/chibios/GENERIC_STM32_G474XE/configs/mcuconf.h +++ /dev/null @@ -1,372 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - 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 License 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. -*/ - -/* - * STM32G4xx drivers configuration. - * The following settings override the default settings present in - * the various device driver implementation headers. - * Note that the settings for each driver only have effect if the whole - * driver is enabled in halconf.h. - * - * IRQ priorities: - * 15...0 Lowest...Highest. - * - * DMA priorities: - * 0...3 Lowest...Highest. - */ - -#ifndef MCUCONF_H -#define MCUCONF_H - -#define STM32G4xx_MCUCONF -#define STM32G473_MCUCONF -#define STM32G483_MCUCONF -#define STM32G474_MCUCONF -#define STM32G484_MCUCONF - -/* - * HAL driver system settings. - */ -#define STM32_NO_INIT FALSE -#define STM32_VOS STM32_VOS_RANGE1 -#define STM32_PWR_CR2 (PWR_CR2_PLS_LEV0) -#define STM32_PWR_CR3 (PWR_CR3_EIWF) -#define STM32_PWR_CR4 (0U) -#define STM32_HSI16_ENABLED TRUE -#define STM32_HSI48_ENABLED TRUE -#define STM32_HSE_ENABLED FALSE -#define STM32_LSI_ENABLED FALSE -#define STM32_LSE_ENABLED FALSE -#define STM32_SW STM32_SW_PLLRCLK -#define STM32_PLLSRC STM32_PLLSRC_HSI16 -#define STM32_PLLM_VALUE 2 -#define STM32_PLLN_VALUE 40 -#define STM32_PLLPDIV_VALUE 0 -#define STM32_PLLP_VALUE 7 -#define STM32_PLLQ_VALUE 2 -#define STM32_PLLR_VALUE 2 -#define STM32_HPRE STM32_HPRE_DIV1 -#define STM32_PPRE1 STM32_PPRE1_DIV1 -#define STM32_PPRE2 STM32_PPRE2_DIV1 -#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK -#define STM32_MCOPRE STM32_MCOPRE_DIV1 -#define STM32_LSCOSEL STM32_LSCOSEL_NOCLOCK - -/* - * Peripherals clock sources. - */ -#define STM32_USART1SEL STM32_USART1SEL_SYSCLK -#define STM32_USART2SEL STM32_USART2SEL_SYSCLK -#define STM32_USART3SEL STM32_USART3SEL_SYSCLK -#define STM32_UART4SEL STM32_UART4SEL_SYSCLK -#define STM32_UART5SEL STM32_UART5SEL_SYSCLK -#define STM32_LPUART1SEL STM32_LPUART1SEL_PCLK1 -#define STM32_I2C1SEL STM32_I2C1SEL_PCLK1 -#define STM32_I2C2SEL STM32_I2C2SEL_PCLK1 -#define STM32_I2C3SEL STM32_I2C3SEL_PCLK1 -#define STM32_I2C4SEL STM32_I2C4SEL_PCLK1 -#define STM32_LPTIM1SEL STM32_LPTIM1SEL_PCLK1 -#define STM32_SAI1SEL STM32_SAI1SEL_SYSCLK -#define STM32_I2S23SEL STM32_I2S23SEL_SYSCLK -#define STM32_FDCANSEL STM32_FDCANSEL_HSE -#define STM32_CLK48SEL STM32_CLK48SEL_HSI48 -#define STM32_ADC12SEL STM32_ADC12SEL_PLLPCLK -#define STM32_ADC345SEL STM32_ADC345SEL_PLLPCLK -#define STM32_QSPISEL STM32_QSPISEL_SYSCLK -#define STM32_RTCSEL STM32_RTCSEL_NOCLOCK - -/* - * IRQ system settings. - */ -#define STM32_IRQ_EXTI0_PRIORITY 6 -#define STM32_IRQ_EXTI1_PRIORITY 6 -#define STM32_IRQ_EXTI2_PRIORITY 6 -#define STM32_IRQ_EXTI3_PRIORITY 6 -#define STM32_IRQ_EXTI4_PRIORITY 6 -#define STM32_IRQ_EXTI5_9_PRIORITY 6 -#define STM32_IRQ_EXTI10_15_PRIORITY 6 -#define STM32_IRQ_EXTI164041_PRIORITY 6 -#define STM32_IRQ_EXTI17_PRIORITY 6 -#define STM32_IRQ_EXTI18_PRIORITY 6 -#define STM32_IRQ_EXTI19_PRIORITY 6 -#define STM32_IRQ_EXTI20_PRIORITY 6 -#define STM32_IRQ_EXTI212229_PRIORITY 6 -#define STM32_IRQ_EXTI30_32_PRIORITY 6 -#define STM32_IRQ_EXTI33_PRIORITY 6 - -#define STM32_IRQ_FDCAN1_PRIORITY 10 -#define STM32_IRQ_FDCAN2_PRIORITY 10 -#define STM32_IRQ_FDCAN3_PRIORITY 10 - -#define STM32_IRQ_TIM1_BRK_TIM15_PRIORITY 7 -#define STM32_IRQ_TIM1_UP_TIM16_PRIORITY 7 -#define STM32_IRQ_TIM1_TRGCO_TIM17_PRIORITY 7 -#define STM32_IRQ_TIM1_CC_PRIORITY 7 -#define STM32_IRQ_TIM2_PRIORITY 7 -#define STM32_IRQ_TIM3_PRIORITY 7 -#define STM32_IRQ_TIM4_PRIORITY 7 -#define STM32_IRQ_TIM5_PRIORITY 7 -#define STM32_IRQ_TIM6_PRIORITY 7 -#define STM32_IRQ_TIM7_PRIORITY 7 -#define STM32_IRQ_TIM8_UP_PRIORITY 7 -#define STM32_IRQ_TIM8_CC_PRIORITY 7 -#define STM32_IRQ_TIM20_UP_PRIORITY 7 -#define STM32_IRQ_TIM20_CC_PRIORITY 7 - -#define STM32_IRQ_USART1_PRIORITY 12 -#define STM32_IRQ_USART2_PRIORITY 12 -#define STM32_IRQ_USART3_PRIORITY 12 -#define STM32_IRQ_UART4_PRIORITY 12 -#define STM32_IRQ_UART5_PRIORITY 12 -#define STM32_IRQ_LPUART1_PRIORITY 12 - -/* - * ADC driver system settings. - */ -#define STM32_ADC_DUAL_MODE FALSE -#define STM32_ADC_COMPACT_SAMPLES FALSE -#define STM32_ADC_USE_ADC1 FALSE -#define STM32_ADC_USE_ADC2 FALSE -#define STM32_ADC_USE_ADC3 FALSE -#define STM32_ADC_USE_ADC4 FALSE -#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_ADC_ADC4_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_ADC_ADC1_DMA_PRIORITY 2 -#define STM32_ADC_ADC2_DMA_PRIORITY 2 -#define STM32_ADC_ADC3_DMA_PRIORITY 2 -#define STM32_ADC_ADC4_DMA_PRIORITY 2 -#define STM32_ADC_ADC12_IRQ_PRIORITY 5 -#define STM32_ADC_ADC3_IRQ_PRIORITY 5 -#define STM32_ADC_ADC4_IRQ_PRIORITY 5 -#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 5 -#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 5 -#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 5 -#define STM32_ADC_ADC4_DMA_IRQ_PRIORITY 5 -#define STM32_ADC_ADC12_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV4 -#define STM32_ADC_ADC345_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV4 -#define STM32_ADC_ADC12_PRESC ADC_CCR_PRESC_DIV2 -#define STM32_ADC_ADC345_PRESC ADC_CCR_PRESC_DIV2 - -/* - * CAN driver system settings. - */ -#define STM32_CAN_USE_FDCAN1 FALSE -#define STM32_CAN_USE_FDCAN2 FALSE -#define STM32_CAN_USE_FDCAN3 FALSE - -/* - * DAC driver system settings. - */ -#define STM32_DAC_DUAL_MODE FALSE -#define STM32_DAC_USE_DAC1_CH1 FALSE -#define STM32_DAC_USE_DAC1_CH2 FALSE -#define STM32_DAC_USE_DAC2_CH1 FALSE -#define STM32_DAC_USE_DAC3_CH1 FALSE -#define STM32_DAC_USE_DAC3_CH2 FALSE -#define STM32_DAC_USE_DAC4_CH1 FALSE -#define STM32_DAC_USE_DAC4_CH2 FALSE -#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 -#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 -#define STM32_DAC_DAC2_CH1_IRQ_PRIORITY 10 -#define STM32_DAC_DAC3_CH1_IRQ_PRIORITY 10 -#define STM32_DAC_DAC3_CH2_IRQ_PRIORITY 10 -#define STM32_DAC_DAC4_CH1_IRQ_PRIORITY 10 -#define STM32_DAC_DAC4_CH2_IRQ_PRIORITY 10 -#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 -#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 -#define STM32_DAC_DAC2_CH1_DMA_PRIORITY 2 -#define STM32_DAC_DAC3_CH1_DMA_PRIORITY 2 -#define STM32_DAC_DAC3_CH2_DMA_PRIORITY 2 -#define STM32_DAC_DAC4_CH1_DMA_PRIORITY 2 -#define STM32_DAC_DAC4_CH2_DMA_PRIORITY 2 -#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_DAC_DAC2_CH1_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_DAC_DAC3_CH1_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_DAC_DAC3_CH2_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_DAC_DAC4_CH1_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_DAC_DAC4_CH2_DMA_STREAM STM32_DMA_STREAM_ID_ANY - -/* - * GPT driver system settings. - */ -#define STM32_GPT_USE_TIM1 FALSE -#define STM32_GPT_USE_TIM2 FALSE -#define STM32_GPT_USE_TIM3 FALSE -#define STM32_GPT_USE_TIM4 FALSE -#define STM32_GPT_USE_TIM5 FALSE -#define STM32_GPT_USE_TIM6 FALSE -#define STM32_GPT_USE_TIM7 FALSE -#define STM32_GPT_USE_TIM8 FALSE -#define STM32_GPT_USE_TIM15 FALSE -#define STM32_GPT_USE_TIM16 FALSE -#define STM32_GPT_USE_TIM17 FALSE - -/* - * I2C driver system settings. - */ -#define STM32_I2C_USE_I2C1 FALSE -#define STM32_I2C_USE_I2C2 FALSE -#define STM32_I2C_USE_I2C3 FALSE -#define STM32_I2C_USE_I2C4 FALSE -#define STM32_I2C_BUSY_TIMEOUT 50 -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_I2C_I2C4_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_I2C_I2C4_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_I2C_I2C1_IRQ_PRIORITY 5 -#define STM32_I2C_I2C2_IRQ_PRIORITY 5 -#define STM32_I2C_I2C3_IRQ_PRIORITY 5 -#define STM32_I2C_I2C4_IRQ_PRIORITY 5 -#define STM32_I2C_I2C1_DMA_PRIORITY 3 -#define STM32_I2C_I2C2_DMA_PRIORITY 3 -#define STM32_I2C_I2C3_DMA_PRIORITY 3 -#define STM32_I2C_I2C4_DMA_PRIORITY 3 -#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") - -/* - * ICU driver system settings. - */ -#define STM32_ICU_USE_TIM1 FALSE -#define STM32_ICU_USE_TIM2 FALSE -#define STM32_ICU_USE_TIM3 FALSE -#define STM32_ICU_USE_TIM4 FALSE -#define STM32_ICU_USE_TIM5 FALSE -#define STM32_ICU_USE_TIM8 FALSE -#define STM32_ICU_USE_TIM15 FALSE -#define STM32_ICU_USE_TIM16 FALSE -#define STM32_ICU_USE_TIM17 FALSE - -/* - * PWM driver system settings. - */ -#define STM32_PWM_USE_ADVANCED FALSE -#define STM32_PWM_USE_TIM1 FALSE -#define STM32_PWM_USE_TIM2 FALSE -#define STM32_PWM_USE_TIM3 FALSE -#define STM32_PWM_USE_TIM4 FALSE -#define STM32_PWM_USE_TIM5 FALSE -#define STM32_PWM_USE_TIM8 FALSE -#define STM32_PWM_USE_TIM15 FALSE -#define STM32_PWM_USE_TIM16 FALSE -#define STM32_PWM_USE_TIM17 FALSE -#define STM32_PWM_USE_TIM20 FALSE - -/* - * RTC driver system settings. - */ - -/* - * SDC driver system settings. - */ - -/* - * SERIAL driver system settings. - */ -#define STM32_SERIAL_USE_USART1 FALSE -#define STM32_SERIAL_USE_USART2 FALSE -#define STM32_SERIAL_USE_USART3 FALSE -#define STM32_SERIAL_USE_UART4 FALSE -#define STM32_SERIAL_USE_UART5 FALSE -#define STM32_SERIAL_USE_LPUART1 FALSE - -/* - * SPI driver system settings. - */ -#define STM32_SPI_USE_SPI1 FALSE -#define STM32_SPI_USE_SPI2 FALSE -#define STM32_SPI_USE_SPI3 FALSE -#define STM32_SPI_USE_SPI4 FALSE -#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_SPI_SPI4_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_SPI_SPI4_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_SPI_SPI1_DMA_PRIORITY 1 -#define STM32_SPI_SPI2_DMA_PRIORITY 1 -#define STM32_SPI_SPI3_DMA_PRIORITY 1 -#define STM32_SPI_SPI4_DMA_PRIORITY 1 -#define STM32_SPI_SPI1_IRQ_PRIORITY 10 -#define STM32_SPI_SPI2_IRQ_PRIORITY 10 -#define STM32_SPI_SPI3_IRQ_PRIORITY 10 -#define STM32_SPI_SPI4_IRQ_PRIORITY 10 -#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") - -/* - * ST driver system settings. - */ -#define STM32_ST_IRQ_PRIORITY 8 -#define STM32_ST_USE_TIMER 2 - -/* - * TRNG driver system settings. - */ -#define STM32_TRNG_USE_RNG1 FALSE - -/* - * UART driver system settings. - */ -#define STM32_UART_USE_USART1 FALSE -#define STM32_UART_USE_USART2 FALSE -#define STM32_UART_USE_USART3 FALSE -#define STM32_UART_USE_UART4 FALSE -#define STM32_UART_USE_UART5 FALSE -#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY -#define STM32_UART_USART1_DMA_PRIORITY 0 -#define STM32_UART_USART2_DMA_PRIORITY 0 -#define STM32_UART_USART3_DMA_PRIORITY 0 -#define STM32_UART_UART4_DMA_PRIORITY 0 -#define STM32_UART_UART5_DMA_PRIORITY 0 -#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") - -/* - * USB driver system settings. - */ -#define STM32_USB_USE_USB1 TRUE -#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE -#define STM32_USB_USB1_HP_IRQ_PRIORITY 5 -#define STM32_USB_USB1_LP_IRQ_PRIORITY 5 - -/* - * WDG driver system settings. - */ -#define STM32_WDG_USE_IWDG FALSE - -/* - * WSPI driver system settings. - */ -#define STM32_WSPI_USE_QUADSPI1 FALSE -#define STM32_WSPI_QUADSPI1_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) - -#endif /* MCUCONF_H */ diff --git a/platforms/chibios/GENERIC_STM32_L412XB/board/board.mk b/platforms/chibios/GENERIC_STM32_L412XB/board/board.mk deleted file mode 100644 index 1250385eb8..0000000000 --- a/platforms/chibios/GENERIC_STM32_L412XB/board/board.mk +++ /dev/null @@ -1,9 +0,0 @@ -# List of all the board related files. -BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO32_L432KC/board.c - -# Required include directories -BOARDINC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO32_L432KC - -# Shared variables -ALLCSRC += $(BOARDSRC) -ALLINC += $(BOARDINC) diff --git a/platforms/chibios/GENERIC_STM32_L412XB/configs/board.h b/platforms/chibios/GENERIC_STM32_L412XB/configs/board.h deleted file mode 100644 index 2e37d95fe3..0000000000 --- a/platforms/chibios/GENERIC_STM32_L412XB/configs/board.h +++ /dev/null @@ -1,24 +0,0 @@ -/* Copyright 2018-2021 Harrison Chan (@Xelus) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#pragma once - -#include_next "board.h" - -#undef STM32L432xx - -// Pretend that we're an L443xx as the ChibiOS definitions for L4x2/L4x3 mistakenly don't enable GPIOH, I2C2, or SPI2. -// Until ChibiOS upstream is fixed, this should be kept at L443, as nothing in QMK currently utilises the crypto peripheral on the L443. -#define STM32L443xx diff --git a/platforms/chibios/GENERIC_STM32_L412XB/configs/config.h b/platforms/chibios/GENERIC_STM32_L412XB/configs/config.h deleted file mode 100644 index c27c61b19a..0000000000 --- a/platforms/chibios/GENERIC_STM32_L412XB/configs/config.h +++ /dev/null @@ -1,26 +0,0 @@ -/* Copyright 2018-2021 Harrison Chan (@Xelus) - * - * 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 . - */ - -/* Address for jumping to bootloader on STM32 chips. */ -/* It is chip dependent, the correct number can be looked up by checking against ST's application note AN2606. - */ -#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000 - -#define PAL_STM32_OSPEED_HIGHEST PAL_STM32_OSPEED_HIGH - -#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP -# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE -#endif diff --git a/platforms/chibios/GENERIC_STM32_L412XB/configs/mcuconf.h b/platforms/chibios/GENERIC_STM32_L412XB/configs/mcuconf.h deleted file mode 100644 index 8ad5a8da21..0000000000 --- a/platforms/chibios/GENERIC_STM32_L412XB/configs/mcuconf.h +++ /dev/null @@ -1,282 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - 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 License 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. -*/ - -/* - * STM32L4xx drivers configuration. - * The following settings override the default settings present in - * the various device driver implementation headers. - * Note that the settings for each driver only have effect if the whole - * driver is enabled in halconf.h. - * - * IRQ priorities: - * 15...0 Lowest...Highest. - * - * DMA priorities: - * 0...3 Lowest...Highest. - */ - -#ifndef MCUCONF_H -#define MCUCONF_H - -#define STM32L4xx_MCUCONF -#define STM32L412_MCUCONF -#define STM32L422_MCUCONF -#define STM32L432_MCUCONF -#define STM32L433_MCUCONF -#define STM32L442_MCUCONF -#define STM32L443_MCUCONF - -/* - * HAL driver system settings. - */ -#define STM32_NO_INIT FALSE -#define STM32_VOS STM32_VOS_RANGE1 -#define STM32_PVD_ENABLE FALSE -#define STM32_PLS STM32_PLS_LEV0 -#define STM32_HSI16_ENABLED TRUE -#define STM32_HSI48_ENABLED TRUE -#define STM32_LSI_ENABLED FALSE -#define STM32_HSE_ENABLED FALSE -#define STM32_LSE_ENABLED FALSE -#define STM32_MSIPLL_ENABLED FALSE -#define STM32_ADC_CLOCK_ENABLED TRUE -#define STM32_USB_CLOCK_ENABLED TRUE -#define STM32_SAI1_CLOCK_ENABLED TRUE -#define STM32_SAI2_CLOCK_ENABLED TRUE -#define STM32_MSIRANGE STM32_MSIRANGE_4M -#define STM32_MSISRANGE STM32_MSISRANGE_4M -#define STM32_SW STM32_SW_PLL -#define STM32_PLLSRC STM32_PLLSRC_HSI16 -#define STM32_PLLM_VALUE 4 -#define STM32_PLLN_VALUE 80 -#define STM32_PLLP_VALUE 7 -#define STM32_PLLQ_VALUE 4 -#define STM32_PLLR_VALUE 4 -#define STM32_HPRE STM32_HPRE_DIV1 -#define STM32_PPRE1 STM32_PPRE1_DIV1 -#define STM32_PPRE2 STM32_PPRE2_DIV1 -#define STM32_STOPWUCK STM32_STOPWUCK_MSI -#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK -#define STM32_MCOPRE STM32_MCOPRE_DIV1 -#define STM32_LSCOSEL STM32_LSCOSEL_NOCLOCK -#define STM32_PLLSAI1N_VALUE 72 -#define STM32_PLLSAI1P_VALUE 7 -#define STM32_PLLSAI1Q_VALUE 6 -#define STM32_PLLSAI1R_VALUE 6 -#define STM32_PLLSAI2N_VALUE 72 -#define STM32_PLLSAI2P_VALUE 7 -#define STM32_PLLSAI2R_VALUE 6 - -/* - * Peripherals clock sources. - */ -#define STM32_USART1SEL STM32_USART1SEL_SYSCLK -#define STM32_USART2SEL STM32_USART2SEL_SYSCLK -#define STM32_USART3SEL STM32_USART3SEL_SYSCLK -#define STM32_UART4SEL STM32_UART4SEL_SYSCLK -#define STM32_UART5SEL STM32_UART5SEL_SYSCLK -#define STM32_LPUART1SEL STM32_LPUART1SEL_SYSCLK -#define STM32_I2C1SEL STM32_I2C1SEL_SYSCLK -#define STM32_I2C2SEL STM32_I2C2SEL_SYSCLK -#define STM32_I2C3SEL STM32_I2C3SEL_SYSCLK -#define STM32_LPTIM1SEL STM32_LPTIM1SEL_PCLK1 -#define STM32_LPTIM2SEL STM32_LPTIM2SEL_PCLK1 -#define STM32_SAI1SEL STM32_SAI1SEL_OFF -#define STM32_SAI2SEL STM32_SAI2SEL_OFF -#define STM32_CLK48SEL STM32_CLK48SEL_HSI48 -#define STM32_ADCSEL STM32_ADCSEL_SYSCLK -#define STM32_SWPMI1SEL STM32_SWPMI1SEL_PCLK1 -#define STM32_RTCSEL STM32_RTCSEL_LSI - -/* - * IRQ system settings. - */ -#define STM32_IRQ_EXTI0_PRIORITY 6 -#define STM32_IRQ_EXTI1_PRIORITY 6 -#define STM32_IRQ_EXTI2_PRIORITY 6 -#define STM32_IRQ_EXTI3_PRIORITY 6 -#define STM32_IRQ_EXTI4_PRIORITY 6 -#define STM32_IRQ_EXTI5_9_PRIORITY 6 -#define STM32_IRQ_EXTI10_15_PRIORITY 6 -#define STM32_IRQ_EXTI1635_38_PRIORITY 6 -#define STM32_IRQ_EXTI18_PRIORITY 6 -#define STM32_IRQ_EXTI19_PRIORITY 6 -#define STM32_IRQ_EXTI20_PRIORITY 6 -#define STM32_IRQ_EXTI21_22_PRIORITY 15 - -#define STM32_IRQ_TIM1_BRK_TIM15_PRIORITY 7 -#define STM32_IRQ_TIM1_UP_TIM16_PRIORITY 7 -#define STM32_IRQ_TIM1_TRGCO_TIM17_PRIORITY 7 -#define STM32_IRQ_TIM1_CC_PRIORITY 7 -#define STM32_IRQ_TIM2_PRIORITY 7 -#define STM32_IRQ_TIM6_PRIORITY 7 -#define STM32_IRQ_TIM7_PRIORITY 7 - -#define STM32_IRQ_USART1_PRIORITY 12 -#define STM32_IRQ_USART2_PRIORITY 12 -#define STM32_IRQ_USART3_PRIORITY 12 -#define STM32_IRQ_LPUART1_PRIORITY 12 - -/* - * ADC driver system settings. - */ -#define STM32_ADC_COMPACT_SAMPLES FALSE -#define STM32_ADC_USE_ADC1 FALSE -#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) -#define STM32_ADC_ADC1_DMA_PRIORITY 2 -#define STM32_ADC_ADC12_IRQ_PRIORITY 5 -#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 5 -#define STM32_ADC_ADC123_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1 -#define STM32_ADC_ADC123_PRESC ADC_CCR_PRESC_DIV2 - -/* - * CAN driver system settings. - */ -#define STM32_CAN_USE_CAN1 FALSE -#define STM32_CAN_CAN1_IRQ_PRIORITY 11 - -/* - * DAC driver system settings. - */ -#define STM32_DAC_DUAL_MODE FALSE -#define STM32_DAC_USE_DAC1_CH1 FALSE -#define STM32_DAC_USE_DAC1_CH2 FALSE -#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 -#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 -#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 -#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 -#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) -#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -/* - * GPT driver system settings. - */ -#define STM32_GPT_USE_TIM1 FALSE -#define STM32_GPT_USE_TIM2 FALSE -#define STM32_GPT_USE_TIM6 FALSE -#define STM32_GPT_USE_TIM7 FALSE -#define STM32_GPT_USE_TIM15 FALSE -#define STM32_GPT_USE_TIM16 FALSE - -/* - * I2C driver system settings. - */ -#define STM32_I2C_USE_I2C1 FALSE -#define STM32_I2C_USE_I2C3 FALSE -#define STM32_I2C_BUSY_TIMEOUT 50 -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_I2C_I2C1_IRQ_PRIORITY 5 -#define STM32_I2C_I2C3_IRQ_PRIORITY 5 -#define STM32_I2C_I2C1_DMA_PRIORITY 3 -#define STM32_I2C_I2C3_DMA_PRIORITY 3 -#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") - -/* - * ICU driver system settings. - */ -#define STM32_ICU_USE_TIM1 FALSE -#define STM32_ICU_USE_TIM2 FALSE -#define STM32_ICU_USE_TIM15 FALSE -#define STM32_ICU_USE_TIM16 FALSE - -/* - * PWM driver system settings. - */ -#define STM32_PWM_USE_ADVANCED FALSE -#define STM32_PWM_USE_TIM1 FALSE -#define STM32_PWM_USE_TIM2 FALSE -#define STM32_PWM_USE_TIM15 FALSE -#define STM32_PWM_USE_TIM16 FALSE - -/* - * RTC driver system settings. - */ -#define STM32_RTC_PRESA_VALUE 32 -#define STM32_RTC_PRESS_VALUE 1024 -#define STM32_RTC_CR_INIT 0 -#define STM32_RTC_TAMPCR_INIT 0 - -/* - * SERIAL driver system settings. - */ -#define STM32_SERIAL_USE_USART1 FALSE -#define STM32_SERIAL_USE_USART2 FALSE -#define STM32_SERIAL_USE_LPUART1 FALSE -#define STM32_SERIAL_USART1_PRIORITY 12 -#define STM32_SERIAL_USART2_PRIORITY 12 -#define STM32_SERIAL_LPUART1_PRIORITY 12 - -/* - * SPI driver system settings. - */ -#define STM32_SPI_USE_SPI1 FALSE -#define STM32_SPI_USE_SPI3 FALSE -#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) -#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) -#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) -#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) -#define STM32_SPI_SPI1_DMA_PRIORITY 1 -#define STM32_SPI_SPI3_DMA_PRIORITY 1 -#define STM32_SPI_SPI1_IRQ_PRIORITY 10 -#define STM32_SPI_SPI3_IRQ_PRIORITY 10 -#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") - -/* - * ST driver system settings. - */ -#define STM32_ST_IRQ_PRIORITY 8 -#define STM32_ST_USE_TIMER 2 - -/* - * TRNG driver system settings. - */ -#define STM32_TRNG_USE_RNG1 FALSE - -/* - * UART driver system settings. - */ -#define STM32_UART_USE_USART1 FALSE -#define STM32_UART_USE_USART2 FALSE -#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) -#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 6) -#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") - -/* - * USB driver system settings. - */ -#define STM32_USB_USE_USB1 TRUE -#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE -#define STM32_USB_USB1_HP_IRQ_PRIORITY 13 -#define STM32_USB_USB1_LP_IRQ_PRIORITY 14 - -/* - * WDG driver system settings. - */ -#define STM32_WDG_USE_IWDG FALSE - -/* - * WSPI driver system settings. - */ -#define STM32_WSPI_USE_QUADSPI1 FALSE -#define STM32_WSPI_QUADSPI1_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) -#define STM32_WSPI_QUADSPI1_PRESCALER_VALUE 1 - -#endif /* MCUCONF_H */ diff --git a/platforms/chibios/GENERIC_STM32_L433XC/board/board.mk b/platforms/chibios/GENERIC_STM32_L433XC/board/board.mk deleted file mode 100644 index 1250385eb8..0000000000 --- a/platforms/chibios/GENERIC_STM32_L433XC/board/board.mk +++ /dev/null @@ -1,9 +0,0 @@ -# List of all the board related files. -BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO32_L432KC/board.c - -# Required include directories -BOARDINC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO32_L432KC - -# Shared variables -ALLCSRC += $(BOARDSRC) -ALLINC += $(BOARDINC) diff --git a/platforms/chibios/GENERIC_STM32_L433XC/configs/board.h b/platforms/chibios/GENERIC_STM32_L433XC/configs/board.h deleted file mode 100644 index 2e37d95fe3..0000000000 --- a/platforms/chibios/GENERIC_STM32_L433XC/configs/board.h +++ /dev/null @@ -1,24 +0,0 @@ -/* Copyright 2018-2021 Harrison Chan (@Xelus) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#pragma once - -#include_next "board.h" - -#undef STM32L432xx - -// Pretend that we're an L443xx as the ChibiOS definitions for L4x2/L4x3 mistakenly don't enable GPIOH, I2C2, or SPI2. -// Until ChibiOS upstream is fixed, this should be kept at L443, as nothing in QMK currently utilises the crypto peripheral on the L443. -#define STM32L443xx diff --git a/platforms/chibios/GENERIC_STM32_L433XC/configs/config.h b/platforms/chibios/GENERIC_STM32_L433XC/configs/config.h deleted file mode 100644 index c27c61b19a..0000000000 --- a/platforms/chibios/GENERIC_STM32_L433XC/configs/config.h +++ /dev/null @@ -1,26 +0,0 @@ -/* Copyright 2018-2021 Harrison Chan (@Xelus) - * - * 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 . - */ - -/* Address for jumping to bootloader on STM32 chips. */ -/* It is chip dependent, the correct number can be looked up by checking against ST's application note AN2606. - */ -#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000 - -#define PAL_STM32_OSPEED_HIGHEST PAL_STM32_OSPEED_HIGH - -#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP -# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE -#endif diff --git a/platforms/chibios/GENERIC_STM32_L433XC/configs/mcuconf.h b/platforms/chibios/GENERIC_STM32_L433XC/configs/mcuconf.h deleted file mode 100644 index 948c740f6e..0000000000 --- a/platforms/chibios/GENERIC_STM32_L433XC/configs/mcuconf.h +++ /dev/null @@ -1,292 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - 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 License 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. -*/ - -/* - * STM32L4xx drivers configuration. - * The following settings override the default settings present in - * the various device driver implementation headers. - * Note that the settings for each driver only have effect if the whole - * driver is enabled in halconf.h. - * - * IRQ priorities: - * 15...0 Lowest...Highest. - * - * DMA priorities: - * 0...3 Lowest...Highest. - */ - -#ifndef MCUCONF_H -#define MCUCONF_H - -#define STM32L4xx_MCUCONF -#define STM32L443_MCUCONF - -/* - * HAL driver system settings. - */ -#define STM32_NO_INIT FALSE -#define STM32_VOS STM32_VOS_RANGE1 -#define STM32_PVD_ENABLE FALSE -#define STM32_PLS STM32_PLS_LEV0 -#define STM32_HSI16_ENABLED TRUE -#define STM32_HSI48_ENABLED TRUE -#define STM32_LSI_ENABLED TRUE -#define STM32_HSE_ENABLED FALSE -#define STM32_LSE_ENABLED FALSE -#define STM32_MSIPLL_ENABLED FALSE -#define STM32_MSIRANGE STM32_MSIRANGE_4M -#define STM32_MSISRANGE STM32_MSISRANGE_4M -#define STM32_SW STM32_SW_PLL -#define STM32_PLLSRC STM32_PLLSRC_HSI16 -#define STM32_PLLM_VALUE 1 -#define STM32_PLLN_VALUE 10 -#define STM32_PLLPDIV_VALUE 0 -#define STM32_PLLP_VALUE 7 -#define STM32_PLLQ_VALUE 2 -#define STM32_PLLR_VALUE 2 -#define STM32_HPRE STM32_HPRE_DIV1 -#define STM32_PPRE1 STM32_PPRE1_DIV1 -#define STM32_PPRE2 STM32_PPRE2_DIV1 -#define STM32_STOPWUCK STM32_STOPWUCK_MSI -#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK -#define STM32_MCOPRE STM32_MCOPRE_DIV1 -#define STM32_LSCOSEL STM32_LSCOSEL_NOCLOCK -#define STM32_PLLSAI1N_VALUE 24 -#define STM32_PLLSAI1PDIV_VALUE 0 -#define STM32_PLLSAI1P_VALUE 7 -#define STM32_PLLSAI1Q_VALUE 2 -#define STM32_PLLSAI1R_VALUE 2 - -/* - * Peripherals clock sources. - */ -#define STM32_USART1SEL STM32_USART1SEL_SYSCLK -#define STM32_USART2SEL STM32_USART2SEL_SYSCLK -#define STM32_USART3SEL STM32_USART3SEL_SYSCLK -#define STM32_LPUART1SEL STM32_LPUART1SEL_SYSCLK -#define STM32_I2C1SEL STM32_I2C1SEL_SYSCLK -#define STM32_I2C2SEL STM32_I2C2SEL_SYSCLK -#define STM32_I2C3SEL STM32_I2C3SEL_SYSCLK -#define STM32_LPTIM1SEL STM32_LPTIM1SEL_PCLK1 -#define STM32_LPTIM2SEL STM32_LPTIM2SEL_PCLK1 -#define STM32_SAI1SEL STM32_SAI1SEL_OFF -#define STM32_CLK48SEL STM32_CLK48SEL_HSI48 -#define STM32_ADCSEL STM32_ADCSEL_SYSCLK -#define STM32_SWPMI1SEL STM32_SWPMI1SEL_PCLK1 -#define STM32_RTCSEL STM32_RTCSEL_LSI - -/* - * IRQ system settings. - */ -#define STM32_IRQ_EXTI0_PRIORITY 6 -#define STM32_IRQ_EXTI1_PRIORITY 6 -#define STM32_IRQ_EXTI2_PRIORITY 6 -#define STM32_IRQ_EXTI3_PRIORITY 6 -#define STM32_IRQ_EXTI4_PRIORITY 6 -#define STM32_IRQ_EXTI5_9_PRIORITY 6 -#define STM32_IRQ_EXTI10_15_PRIORITY 6 -#define STM32_IRQ_EXTI1635_38_PRIORITY 6 -#define STM32_IRQ_EXTI18_PRIORITY 6 -#define STM32_IRQ_EXTI19_PRIORITY 6 -#define STM32_IRQ_EXTI20_PRIORITY 6 -#define STM32_IRQ_EXTI21_22_PRIORITY 15 - -#define STM32_IRQ_TIM1_BRK_TIM15_PRIORITY 7 -#define STM32_IRQ_TIM1_UP_TIM16_PRIORITY 7 -#define STM32_IRQ_TIM1_TRGCO_TIM17_PRIORITY 7 -#define STM32_IRQ_TIM1_CC_PRIORITY 7 -#define STM32_IRQ_TIM2_PRIORITY 7 -#define STM32_IRQ_TIM6_PRIORITY 7 -#define STM32_IRQ_TIM7_PRIORITY 7 - -#define STM32_IRQ_USART1_PRIORITY 12 -#define STM32_IRQ_USART2_PRIORITY 12 -#define STM32_IRQ_USART3_PRIORITY 12 -#define STM32_IRQ_LPUART1_PRIORITY 12 - -/* - * ADC driver system settings. - */ -#define STM32_ADC_COMPACT_SAMPLES FALSE -#define STM32_ADC_USE_ADC1 FALSE -#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) -#define STM32_ADC_ADC1_DMA_PRIORITY 2 -#define STM32_ADC_ADC12_IRQ_PRIORITY 5 -#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 5 -#define STM32_ADC_ADC123_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1 -#define STM32_ADC_ADC123_PRESC ADC_CCR_PRESC_DIV2 - -/* - * CAN driver system settings. - */ -#define STM32_CAN_USE_CAN1 FALSE -#define STM32_CAN_CAN1_IRQ_PRIORITY 11 - -/* - * DAC driver system settings. - */ -#define STM32_DAC_DUAL_MODE FALSE -#define STM32_DAC_USE_DAC1_CH1 FALSE -#define STM32_DAC_USE_DAC1_CH2 FALSE -#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 -#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 -#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 -#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 -#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) -#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -/* - * GPT driver system settings. - */ -#define STM32_GPT_USE_TIM1 FALSE -#define STM32_GPT_USE_TIM2 FALSE -#define STM32_GPT_USE_TIM6 FALSE -#define STM32_GPT_USE_TIM7 FALSE -#define STM32_GPT_USE_TIM15 FALSE -#define STM32_GPT_USE_TIM16 FALSE - -/* - * I2C driver system settings. - */ -#define STM32_I2C_USE_I2C1 FALSE -#define STM32_I2C_USE_I2C2 FALSE -#define STM32_I2C_USE_I2C3 FALSE -#define STM32_I2C_BUSY_TIMEOUT 50 -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_I2C_I2C1_IRQ_PRIORITY 5 -#define STM32_I2C_I2C2_IRQ_PRIORITY 5 -#define STM32_I2C_I2C3_IRQ_PRIORITY 5 -#define STM32_I2C_I2C1_DMA_PRIORITY 3 -#define STM32_I2C_I2C2_DMA_PRIORITY 3 -#define STM32_I2C_I2C3_DMA_PRIORITY 3 -#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") - -/* - * ICU driver system settings. - */ -#define STM32_ICU_USE_TIM1 FALSE -#define STM32_ICU_USE_TIM2 FALSE -#define STM32_ICU_USE_TIM15 FALSE -#define STM32_ICU_USE_TIM16 FALSE - -/* - * PWM driver system settings. - */ -#define STM32_PWM_USE_ADVANCED FALSE -#define STM32_PWM_USE_TIM1 FALSE -#define STM32_PWM_USE_TIM2 FALSE -#define STM32_PWM_USE_TIM15 FALSE -#define STM32_PWM_USE_TIM16 FALSE - -/* - * RTC driver system settings. - */ -#define STM32_RTC_PRESA_VALUE 32 -#define STM32_RTC_PRESS_VALUE 1024 -#define STM32_RTC_CR_INIT 0 -#define STM32_RTC_TAMPCR_INIT 0 - -/* - * SDMMC drive system settings. - */ -#define STM32_SDC_USE_SDMMC1 FALSE -#define STM32_SDC_SDMMC_UNALIGNED_SUPPORT TRUE -#define STM32_SDC_SDMMC_WRITE_TIMEOUT 1000 -#define STM32_SDC_SDMMC_READ_TIMEOUT 1000 -#define STM32_SDC_SDMMC_CLOCK_DELAY 10 -#define STM32_SDC_SDMMC1_DMA_PRIORITY 3 -#define STM32_SDC_SDMMC1_IRQ_PRIORITY 9 -#define STM32_SDC_SDMMC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) - -/* - * SERIAL driver system settings. - */ -#define STM32_SERIAL_USE_USART1 FALSE -#define STM32_SERIAL_USE_USART2 FALSE -#define STM32_SERIAL_USE_USART3 FALSE -#define STM32_SERIAL_USE_LPUART1 FALSE -#define STM32_SERIAL_USART1_PRIORITY 12 -#define STM32_SERIAL_USART2_PRIORITY 12 -#define STM32_SERIAL_USART3_PRIORITY 12 -#define STM32_SERIAL_LPUART1_PRIORITY 12 - -/* - * SPI driver system settings. - */ -#define STM32_SPI_USE_SPI1 FALSE -#define STM32_SPI_USE_SPI2 FALSE -#define STM32_SPI_USE_SPI3 FALSE -#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) -#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) -#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) -#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) -#define STM32_SPI_SPI1_DMA_PRIORITY 1 -#define STM32_SPI_SPI2_DMA_PRIORITY 1 -#define STM32_SPI_SPI3_DMA_PRIORITY 1 -#define STM32_SPI_SPI1_IRQ_PRIORITY 10 -#define STM32_SPI_SPI2_IRQ_PRIORITY 10 -#define STM32_SPI_SPI3_IRQ_PRIORITY 10 -#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") - -/* - * ST driver system settings. - */ -#define STM32_ST_IRQ_PRIORITY 8 -#define STM32_ST_USE_TIMER 2 - -/* - * TRNG driver system settings. - */ -#define STM32_TRNG_USE_RNG1 FALSE - -/* - * UART driver system settings. - */ -#define STM32_UART_USE_USART1 FALSE -#define STM32_UART_USE_USART2 FALSE -#define STM32_UART_USE_USART3 FALSE -#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) -#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 6) -#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) -#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") - -/* - * USB driver system settings. - */ -#define STM32_USB_USE_USB1 TRUE -#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE -#define STM32_USB_USB1_HP_IRQ_PRIORITY 13 -#define STM32_USB_USB1_LP_IRQ_PRIORITY 14 - -/* - * WDG driver system settings. - */ -#define STM32_WDG_USE_IWDG FALSE - -/* - * WSPI driver system settings. - */ -#define STM32_WSPI_USE_QUADSPI1 FALSE -#define STM32_WSPI_QUADSPI1_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) - -#endif /* MCUCONF_H */ diff --git a/platforms/chibios/IC_TEENSY_3_1/board/board.c b/platforms/chibios/IC_TEENSY_3_1/board/board.c deleted file mode 100644 index 424e0c975b..0000000000 --- a/platforms/chibios/IC_TEENSY_3_1/board/board.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - ChibiOS - Copyright (C) 2015 RedoX https://github.com/RedoXyde - - 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 License 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. -*/ -#include - -#if HAL_USE_PAL || defined(__DOXYGEN__) -/** - * @brief PAL setup. - * @details Digital I/O ports static configuration as defined in @p board.h. - * This variable is used by the HAL when initializing the PAL driver. - */ -const PALConfig pal_default_config = { - .ports = - { - { - /* - * PORTA setup. - * - * PTA4 - PIN33 - * PTA5 - PIN24 - * PTA12 - PIN3 - * PTA13 - PIN4 - * - * PTA18/19 crystal - * PTA0/3 SWD - */ - .port = IOPORT1, - .pads = - { - PAL_MODE_ALTERNATIVE_7, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_ALTERNATIVE_7, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_INPUT_ANALOG, PAL_MODE_INPUT_ANALOG, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, - }, - }, - { - /* - * PORTB setup. - * - * PTB0 - PIN16 - * PTB1 - PIN17 - * PTB2 - PIN19 - * PTB3 - PIN18 - * PTB16 - PIN0 - UART0_TX - * PTB17 - PIN1 - UART0_RX - * PTB18 - PIN32 - * PTB19 - PIN25 - */ - .port = IOPORT2, - .pads = - { - PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_ALTERNATIVE_3, PAL_MODE_ALTERNATIVE_3, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, - }, - }, - { - /* - * PORTC setup. - * - * PTC0 - PIN15 - * PTC1 - PIN22 - * PTC2 - PIN23 - * PTC3 - PIN9 - * PTC4 - PIN10 - * PTC5 - PIN13 - * PTC6 - PIN11 - * PTC7 - PIN12 - * PTC8 - PIN28 - * PTC9 - PIN27 - * PTC10 - PIN29 - * PTC11 - PIN30 - */ - .port = IOPORT3, - .pads = - { - PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, - }, - }, - { - /* - * PORTD setup. - * - * PTD0 - PIN2 - * PTD1 - PIN14 - * PTD2 - PIN7 - * PTD3 - PIN8 - * PTD4 - PIN6 - * PTD5 - PIN20 - * PTD6 - PIN21 - * PTD7 - PIN5 - */ - .port = IOPORT4, - .pads = - { - PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, - }, - }, - { - /* - * PORTE setup. - * - * PTE0 - PIN31 - * PTE1 - PIN26 - */ - .port = IOPORT5, - .pads = - { - PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, - }, - }, - }, -}; -#endif - -// NOTE: This value comes from kiibohd/controller and is the location of a value -// which needs to be checked before disabling the watchdog (which happens in -// k20x_clock_init) -#define WDOG_TMROUTL *(volatile uint16_t *)0x40052012 - -/** - * @brief Early initialization code. - * @details This initialization must be performed just after stack setup - * and before any other initialization. - */ -void __early_init(void) { - // This is a dirty hack and should only be used as a temporary fix until this - // is upstreamed. - while (WDOG_TMROUTL < 2) - ; // Must wait for WDOG timer if already running, before jumping - - k20x_clock_init(); -} - -/** - * @brief Board-specific initialization code. - * @todo Add your board-specific code, if any. - */ -void boardInit(void) {} - - -void restart_usb_driver(USBDriver *usbp) { - // Do nothing. Restarting the USB driver on these boards breaks it. -} diff --git a/platforms/chibios/IC_TEENSY_3_1/board/board.h b/platforms/chibios/IC_TEENSY_3_1/board/board.h deleted file mode 100644 index c8259ab0c7..0000000000 --- a/platforms/chibios/IC_TEENSY_3_1/board/board.h +++ /dev/null @@ -1,295 +0,0 @@ -/* - ChibiOS - Copyright (C) 2015 RedoX https://github.com/RedoXyde - - 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 License 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. -*/ - -#ifndef _BOARD_H_ -#define _BOARD_H_ - -/* - * Setup for the PJRC Teensy 3.1 board. - */ - -/* - * Board identifier. - */ -#define BOARD_PJRC_TEENSY_3_1 -#define BOARD_NAME "PJRC Teensy 3.1" - -/* External 16 MHz crystal */ -#define KINETIS_XTAL_FREQUENCY 16000000UL - -/* Use internal capacitors for the crystal */ -#define KINETIS_BOARD_OSCILLATOR_SETTING OSC_CR_SC8P | OSC_CR_SC2P - -/* - * MCU type - */ -#define K20x7 - -/* - * IO pins assignments. - */ -#define PORTA_PIN0 0 -#define PORTA_PIN1 1 -#define PORTA_PIN2 2 -#define PORTA_PIN3 3 -#define TEENSY_PIN33 4 -#define TEENSY_PIN24 5 -#define PORTA_PIN6 6 -#define PORTA_PIN7 7 -#define PORTA_PIN8 8 -#define PORTA_PIN9 9 -#define PORTA_PIN10 10 -#define PORTA_PIN11 11 -#define TEENSY_PIN3 12 -#define TEENSY_PIN4 13 -#define PORTA_PIN14 14 -#define PORTA_PIN15 15 -#define PORTA_PIN16 16 -#define PORTA_PIN17 17 -#define PORTA_PIN18 18 -#define PORTA_PIN19 19 -#define PORTA_PIN20 20 -#define PORTA_PIN21 21 -#define PORTA_PIN22 22 -#define PORTA_PIN23 23 -#define PORTA_PIN24 24 -#define PORTA_PIN25 25 -#define PORTA_PIN26 26 -#define PORTA_PIN27 27 -#define PORTA_PIN28 28 -#define PORTA_PIN29 29 -#define PORTA_PIN30 30 -#define PORTA_PIN31 31 - -#define TEENSY_PIN3_IOPORT IOPORT1 -#define TEENSY_PIN4_IOPORT IOPORT1 -#define TEENSY_PIN24_IOPORT IOPORT1 -#define TEENSY_PIN33_IOPORT IOPORT1 - -#define TEENSY_PIN16 0 -#define TEENSY_PIN17 1 -#define TEENSY_PIN19 2 -#define TEENSY_PIN18 3 -#define PORTB_PIN4 4 -#define PORTB_PIN5 5 -#define PORTB_PIN6 6 -#define PORTB_PIN7 7 -#define PORTB_PIN8 8 -#define PORTB_PIN9 9 -#define PORTB_PIN10 10 -#define PORTB_PIN11 11 -#define PORTB_PIN12 12 -#define PORTB_PIN13 13 -#define PORTB_PIN14 14 -#define PORTB_PIN15 15 -#define TEENSY_PIN0 16 -#define TEENSY_PIN1 17 -#define TEENSY_PIN32 18 -#define TEENSY_PIN25 19 -#define PORTB_PIN20 20 -#define PORTB_PIN21 21 -#define PORTB_PIN22 22 -#define PORTB_PIN23 23 -#define PORTB_PIN24 24 -#define PORTB_PIN25 25 -#define PORTB_PIN26 26 -#define PORTB_PIN27 27 -#define PORTB_PIN28 28 -#define PORTB_PIN29 29 -#define PORTB_PIN30 30 -#define PORTB_PIN31 31 - -#define TEENSY_PIN0_IOPORT IOPORT2 -#define TEENSY_PIN1_IOPORT IOPORT2 -#define TEENSY_PIN16_IOPORT IOPORT2 -#define TEENSY_PIN17_IOPORT IOPORT2 -#define TEENSY_PIN18_IOPORT IOPORT2 -#define TEENSY_PIN19_IOPORT IOPORT2 -#define TEENSY_PIN25_IOPORT IOPORT2 -#define TEENSY_PIN32_IOPORT IOPORT2 - -#define TEENSY_PIN15 0 -#define TEENSY_PIN22 1 -#define TEENSY_PIN23 2 -#define TEENSY_PIN9 3 -#define TEENSY_PIN10 4 -#define TEENSY_PIN13 5 -#define TEENSY_PIN11 6 -#define TEENSY_PIN12 7 -#define TEENSY_PIN28 8 -#define TEENSY_PIN27 9 -#define TEENSY_PIN29 10 -#define TEENSY_PIN30 11 -#define PORTC_PIN12 12 -#define PORTC_PIN13 13 -#define PORTC_PIN14 14 -#define PORTC_PIN15 15 -#define PORTC_PIN16 16 -#define PORTC_PIN17 17 -#define PORTC_PIN18 18 -#define PORTC_PIN19 19 -#define PORTC_PIN20 20 -#define PORTC_PIN21 21 -#define PORTC_PIN22 22 -#define PORTC_PIN23 23 -#define PORTC_PIN24 24 -#define PORTC_PIN25 25 -#define PORTC_PIN26 26 -#define PORTC_PIN27 27 -#define PORTC_PIN28 28 -#define PORTC_PIN29 29 -#define PORTC_PIN30 30 -#define PORTC_PIN31 31 - -#define TEENSY_PIN9_IOPORT IOPORT3 -#define TEENSY_PIN10_IOPORT IOPORT3 -#define TEENSY_PIN11_IOPORT IOPORT3 -#define TEENSY_PIN12_IOPORT IOPORT3 -#define TEENSY_PIN13_IOPORT IOPORT3 -#define TEENSY_PIN15_IOPORT IOPORT3 -#define TEENSY_PIN22_IOPORT IOPORT3 -#define TEENSY_PIN23_IOPORT IOPORT3 -#define TEENSY_PIN27_IOPORT IOPORT3 -#define TEENSY_PIN28_IOPORT IOPORT3 -#define TEENSY_PIN29_IOPORT IOPORT3 -#define TEENSY_PIN30_IOPORT IOPORT3 - -#define TEENSY_PIN2 0 -#define TEENSY_PIN14 1 -#define TEENSY_PIN7 2 -#define TEENSY_PIN8 3 -#define TEENSY_PIN6 4 -#define TEENSY_PIN20 5 -#define TEENSY_PIN21 6 -#define TEENSY_PIN5 7 -#define PORTD_PIN8 8 -#define PORTD_PIN9 9 -#define PORTD_PIN10 10 -#define PORTD_PIN11 11 -#define PORTD_PIN12 12 -#define PORTD_PIN13 13 -#define PORTD_PIN14 14 -#define PORTD_PIN15 15 -#define PORTD_PIN16 16 -#define PORTD_PIN17 17 -#define PORTD_PIN18 18 -#define PORTD_PIN19 19 -#define PORTD_PIN20 20 -#define PORTD_PIN21 21 -#define PORTD_PIN22 22 -#define PORTD_PIN23 23 -#define PORTD_PIN24 24 -#define PORTD_PIN25 25 -#define PORTD_PIN26 26 -#define PORTD_PIN27 27 -#define PORTD_PIN28 28 -#define PORTD_PIN29 29 -#define PORTD_PIN30 30 -#define PORTD_PIN31 31 - -#define TEENSY_PIN2_IOPORT IOPORT4 -#define TEENSY_PIN5_IOPORT IOPORT4 -#define TEENSY_PIN6_IOPORT IOPORT4 -#define TEENSY_PIN7_IOPORT IOPORT4 -#define TEENSY_PIN8_IOPORT IOPORT4 -#define TEENSY_PIN14_IOPORT IOPORT4 -#define TEENSY_PIN20_IOPORT IOPORT4 -#define TEENSY_PIN21_IOPORT IOPORT4 - -#define TEENSY_PIN31 0 -#define TEENSY_PIN26 1 -#define PORTE_PIN2 2 -#define PORTE_PIN3 3 -#define PORTE_PIN4 4 -#define PORTE_PIN5 5 -#define PORTE_PIN6 6 -#define PORTE_PIN7 7 -#define PORTE_PIN8 8 -#define PORTE_PIN9 9 -#define PORTE_PIN10 10 -#define PORTE_PIN11 11 -#define PORTE_PIN12 12 -#define PORTE_PIN13 13 -#define PORTE_PIN14 14 -#define PORTE_PIN15 15 -#define PORTE_PIN16 16 -#define PORTE_PIN17 17 -#define PORTE_PIN18 18 -#define PORTE_PIN19 19 -#define PORTE_PIN20 20 -#define PORTE_PIN21 21 -#define PORTE_PIN22 22 -#define PORTE_PIN23 23 -#define PORTE_PIN24 24 -#define PORTE_PIN25 25 -#define PORTE_PIN26 26 -#define PORTE_PIN27 27 -#define PORTE_PIN28 28 -#define PORTE_PIN29 29 -#define PORTE_PIN30 30 -#define PORTE_PIN31 31 - -#define TEENSY_PIN26_IOPORT IOPORT5 -#define TEENSY_PIN31_IOPORT IOPORT5 - -#define LINE_PIN1 PAL_LINE(TEENSY_PIN1_IOPORT, TEENSY_PIN1) -#define LINE_PIN2 PAL_LINE(TEENSY_PIN2_IOPORT, TEENSY_PIN2) -#define LINE_PIN3 PAL_LINE(TEENSY_PIN3_IOPORT, TEENSY_PIN3) -#define LINE_PIN4 PAL_LINE(TEENSY_PIN4_IOPORT, TEENSY_PIN4) -#define LINE_PIN5 PAL_LINE(TEENSY_PIN5_IOPORT, TEENSY_PIN5) -#define LINE_PIN6 PAL_LINE(TEENSY_PIN6_IOPORT, TEENSY_PIN6) -#define LINE_PIN7 PAL_LINE(TEENSY_PIN7_IOPORT, TEENSY_PIN7) -#define LINE_PIN8 PAL_LINE(TEENSY_PIN8_IOPORT, TEENSY_PIN8) -#define LINE_PIN9 PAL_LINE(TEENSY_PIN9_IOPORT, TEENSY_PIN9) -#define LINE_PIN10 PAL_LINE(TEENSY_PIN10_IOPORT, TEENSY_PIN10) -#define LINE_PIN11 PAL_LINE(TEENSY_PIN11_IOPORT, TEENSY_PIN11) -#define LINE_PIN12 PAL_LINE(TEENSY_PIN12_IOPORT, TEENSY_PIN12) -#define LINE_PIN13 PAL_LINE(TEENSY_PIN13_IOPORT, TEENSY_PIN13) -#define LINE_PIN14 PAL_LINE(TEENSY_PIN14_IOPORT, TEENSY_PIN14) -#define LINE_PIN15 PAL_LINE(TEENSY_PIN15_IOPORT, TEENSY_PIN15) -#define LINE_PIN16 PAL_LINE(TEENSY_PIN16_IOPORT, TEENSY_PIN16) -#define LINE_PIN17 PAL_LINE(TEENSY_PIN17_IOPORT, TEENSY_PIN17) -#define LINE_PIN18 PAL_LINE(TEENSY_PIN18_IOPORT, TEENSY_PIN18) -#define LINE_PIN19 PAL_LINE(TEENSY_PIN19_IOPORT, TEENSY_PIN19) -#define LINE_PIN20 PAL_LINE(TEENSY_PIN20_IOPORT, TEENSY_PIN20) -#define LINE_PIN21 PAL_LINE(TEENSY_PIN21_IOPORT, TEENSY_PIN21) -#define LINE_PIN22 PAL_LINE(TEENSY_PIN22_IOPORT, TEENSY_PIN22) -#define LINE_PIN23 PAL_LINE(TEENSY_PIN23_IOPORT, TEENSY_PIN23) -#define LINE_PIN24 PAL_LINE(TEENSY_PIN24_IOPORT, TEENSY_PIN24) -#define LINE_PIN25 PAL_LINE(TEENSY_PIN25_IOPORT, TEENSY_PIN25) -#define LINE_PIN25 PAL_LINE(TEENSY_PIN25_IOPORT, TEENSY_PIN25) -#define LINE_PIN26 PAL_LINE(TEENSY_PIN26_IOPORT, TEENSY_PIN26) -#define LINE_PIN27 PAL_LINE(TEENSY_PIN27_IOPORT, TEENSY_PIN27) -#define LINE_PIN28 PAL_LINE(TEENSY_PIN28_IOPORT, TEENSY_PIN28) -#define LINE_PIN29 PAL_LINE(TEENSY_PIN29_IOPORT, TEENSY_PIN29) -#define LINE_PIN30 PAL_LINE(TEENSY_PIN30_IOPORT, TEENSY_PIN30) -#define LINE_PIN31 PAL_LINE(TEENSY_PIN31_IOPORT, TEENSY_PIN31) -#define LINE_PIN32 PAL_LINE(TEENSY_PIN32_IOPORT, TEENSY_PIN32) -#define LINE_PIN33 PAL_LINE(TEENSY_PIN33_IOPORT, TEENSY_PIN33) - -#define LINE_LED LINE_PIN13 - -#if !defined(_FROM_ASM_) -# ifdef __cplusplus -extern "C" { -# endif -void boardInit(void); -# ifdef __cplusplus -} -# endif -#endif /* _FROM_ASM_ */ - -#endif /* _BOARD_H_ */ diff --git a/platforms/chibios/IC_TEENSY_3_1/board/board.mk b/platforms/chibios/IC_TEENSY_3_1/board/board.mk deleted file mode 100644 index 842e335905..0000000000 --- a/platforms/chibios/IC_TEENSY_3_1/board/board.mk +++ /dev/null @@ -1,9 +0,0 @@ -# List of all the board related files. -BOARDSRC = $(BOARD_PATH)/board/board.c - -# Required include directories -BOARDINC = $(BOARD_PATH)/board - -# Shared variables -ALLCSRC += $(BOARDSRC) -ALLINC += $(BOARDINC) diff --git a/platforms/chibios/IC_TEENSY_4_1/board/board.mk b/platforms/chibios/IC_TEENSY_4_1/board/board.mk deleted file mode 100644 index bc242ac3c5..0000000000 --- a/platforms/chibios/IC_TEENSY_4_1/board/board.mk +++ /dev/null @@ -1 +0,0 @@ -include $(CHIBIOS_CONTRIB)/os/hal/boards/PJRC_TEENSY_4_1/board.mk diff --git a/platforms/chibios/IC_TEENSY_4_1/rules.mk b/platforms/chibios/IC_TEENSY_4_1/rules.mk deleted file mode 100644 index 0c62d209c5..0000000000 --- a/platforms/chibios/IC_TEENSY_4_1/rules.mk +++ /dev/null @@ -1 +0,0 @@ -TEENSY_LOADER_CLI_MCU = imxrt1062 diff --git a/platforms/chibios/QMK_PROTON_C/board/board.mk b/platforms/chibios/QMK_PROTON_C/board/board.mk deleted file mode 100644 index f891e65247..0000000000 --- a/platforms/chibios/QMK_PROTON_C/board/board.mk +++ /dev/null @@ -1,9 +0,0 @@ -# List of all the board related files. -BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_STM32F3_DISCOVERY/board.c - -# Required include directories -BOARDINC = $(CHIBIOS)/os/hal/boards/ST_STM32F3_DISCOVERY - -# Shared variables -ALLCSRC += $(BOARDSRC) -ALLINC += $(BOARDINC) diff --git a/platforms/chibios/QMK_PROTON_C/configs/board.h b/platforms/chibios/QMK_PROTON_C/configs/board.h deleted file mode 100644 index 97159964d0..0000000000 --- a/platforms/chibios/QMK_PROTON_C/configs/board.h +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright 2020 Nick Brassel (tzarc) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#pragma once - -#include_next "board.h" - -#undef STM32_HSE_BYPASS - -/* - * USB bus activation macro, required by the USB driver. - */ -#define usb_lld_connect_bus(usbp) \ - do { \ - palSetPadMode(GPIOA, GPIOA_USB_DP, PAL_MODE_ALTERNATE(14)); \ - } while (0) - -/* - * USB bus de-activation macro, required by the USB driver. - */ -#define usb_lld_disconnect_bus(usbp) \ - do { \ - palSetPadMode(GPIOA, GPIOA_USB_DP, PAL_MODE_OUTPUT_PUSHPULL); \ - palClearPad(GPIOA, GPIOA_USB_DP); \ - } while (0) diff --git a/platforms/chibios/QMK_PROTON_C/configs/bootloader_defs.h b/platforms/chibios/QMK_PROTON_C/configs/bootloader_defs.h deleted file mode 100644 index 3b0e9d20a6..0000000000 --- a/platforms/chibios/QMK_PROTON_C/configs/bootloader_defs.h +++ /dev/null @@ -1,7 +0,0 @@ -/* Address for jumping to bootloader on STM32 chips. */ -/* It is chip dependent, the correct number can be looked up here: - * http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf - * This also requires a patch to chibios: - * /tmk_core/tool/chibios/ch-bootloader-jump.patch - */ -#define STM32_BOOTLOADER_ADDRESS 0x1FFFD800 diff --git a/platforms/chibios/QMK_PROTON_C/configs/chconf.h b/platforms/chibios/QMK_PROTON_C/configs/chconf.h deleted file mode 100644 index a1cbf68086..0000000000 --- a/platforms/chibios/QMK_PROTON_C/configs/chconf.h +++ /dev/null @@ -1,756 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - 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 License 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. -*/ - -/** - * @file rt/templates/chconf.h - * @brief Configuration file template. - * @details A copy of this file must be placed in each project directory, it - * contains the application specific kernel settings. - * - * @addtogroup config - * @details Kernel related settings and hooks. - * @{ - */ - -#ifndef CHCONF_H -#define CHCONF_H - -#define _CHIBIOS_RT_CONF_ -#define _CHIBIOS_RT_CONF_VER_6_1_ - -/*===========================================================================*/ -/** - * @name System timers settings - * @{ - */ -/*===========================================================================*/ - -/** - * @brief System time counter resolution. - * @note Allowed values are 16 or 32 bits. - */ -#if !defined(CH_CFG_ST_RESOLUTION) -#define CH_CFG_ST_RESOLUTION 32 -#endif - -/** - * @brief System tick frequency. - * @details Frequency of the system timer that drives the system ticks. This - * setting also defines the system tick time unit. - */ -#if !defined(CH_CFG_ST_FREQUENCY) -#define CH_CFG_ST_FREQUENCY 100000 -#endif - -/** - * @brief Time intervals data size. - * @note Allowed values are 16, 32 or 64 bits. - */ -#if !defined(CH_CFG_INTERVALS_SIZE) -#define CH_CFG_INTERVALS_SIZE 32 -#endif - -/** - * @brief Time types data size. - * @note Allowed values are 16 or 32 bits. - */ -#if !defined(CH_CFG_TIME_TYPES_SIZE) -#define CH_CFG_TIME_TYPES_SIZE 32 -#endif - -/** - * @brief Time delta constant for the tick-less mode. - * @note If this value is zero then the system uses the classic - * periodic tick. This value represents the minimum number - * of ticks that is safe to specify in a timeout directive. - * The value one is not valid, timeouts are rounded up to - * this value. - */ -#if !defined(CH_CFG_ST_TIMEDELTA) -#define CH_CFG_ST_TIMEDELTA 2 -#endif - -/** @} */ - -/*===========================================================================*/ -/** - * @name Kernel parameters and options - * @{ - */ -/*===========================================================================*/ - -/** - * @brief Round robin interval. - * @details This constant is the number of system ticks allowed for the - * threads before preemption occurs. Setting this value to zero - * disables the preemption for threads with equal priority and the - * round robin becomes cooperative. Note that higher priority - * threads can still preempt, the kernel is always preemptive. - * @note Disabling the round robin preemption makes the kernel more compact - * and generally faster. - * @note The round robin preemption is not supported in tickless mode and - * must be set to zero in that case. - */ -#if !defined(CH_CFG_TIME_QUANTUM) -#define CH_CFG_TIME_QUANTUM 0 -#endif - -/** - * @brief Idle thread automatic spawn suppression. - * @details When this option is activated the function @p chSysInit() - * does not spawn the idle thread. The application @p main() - * function becomes the idle thread and must implement an - * infinite loop. - */ -#if !defined(CH_CFG_NO_IDLE_THREAD) -#define CH_CFG_NO_IDLE_THREAD FALSE -#endif - -/** @} */ - -/*===========================================================================*/ -/** - * @name Performance options - * @{ - */ -/*===========================================================================*/ - -/** - * @brief OS optimization. - * @details If enabled then time efficient rather than space efficient code - * is used when two possible implementations exist. - * - * @note This is not related to the compiler optimization options. - * @note The default is @p TRUE. - */ -#if !defined(CH_CFG_OPTIMIZE_SPEED) -#define CH_CFG_OPTIMIZE_SPEED TRUE -#endif - -/** @} */ - -/*===========================================================================*/ -/** - * @name Subsystem options - * @{ - */ -/*===========================================================================*/ - -/** - * @brief Time Measurement APIs. - * @details If enabled then the time measurement APIs are included in - * the kernel. - * - * @note The default is @p TRUE. - */ -#if !defined(CH_CFG_USE_TM) -#define CH_CFG_USE_TM TRUE -#endif - -/** - * @brief Threads registry APIs. - * @details If enabled then the registry APIs are included in the kernel. - * - * @note The default is @p TRUE. - */ -#if !defined(CH_CFG_USE_REGISTRY) -#define CH_CFG_USE_REGISTRY TRUE -#endif - -/** - * @brief Threads synchronization APIs. - * @details If enabled then the @p chThdWait() function is included in - * the kernel. - * - * @note The default is @p TRUE. - */ -#if !defined(CH_CFG_USE_WAITEXIT) -#define CH_CFG_USE_WAITEXIT TRUE -#endif - -/** - * @brief Semaphores APIs. - * @details If enabled then the Semaphores APIs are included in the kernel. - * - * @note The default is @p TRUE. - */ -#if !defined(CH_CFG_USE_SEMAPHORES) -#define CH_CFG_USE_SEMAPHORES TRUE -#endif - -/** - * @brief Semaphores queuing mode. - * @details If enabled then the threads are enqueued on semaphores by - * priority rather than in FIFO order. - * - * @note The default is @p FALSE. Enable this if you have special - * requirements. - * @note Requires @p CH_CFG_USE_SEMAPHORES. - */ -#if !defined(CH_CFG_USE_SEMAPHORES_PRIORITY) -#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE -#endif - -/** - * @brief Mutexes APIs. - * @details If enabled then the mutexes APIs are included in the kernel. - * - * @note The default is @p TRUE. - */ -#if !defined(CH_CFG_USE_MUTEXES) -#define CH_CFG_USE_MUTEXES TRUE -#endif - -/** - * @brief Enables recursive behavior on mutexes. - * @note Recursive mutexes are heavier and have an increased - * memory footprint. - * - * @note The default is @p FALSE. - * @note Requires @p CH_CFG_USE_MUTEXES. - */ -#if !defined(CH_CFG_USE_MUTEXES_RECURSIVE) -#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE -#endif - -/** - * @brief Conditional Variables APIs. - * @details If enabled then the conditional variables APIs are included - * in the kernel. - * - * @note The default is @p TRUE. - * @note Requires @p CH_CFG_USE_MUTEXES. - */ -#if !defined(CH_CFG_USE_CONDVARS) -#define CH_CFG_USE_CONDVARS TRUE -#endif - -/** - * @brief Conditional Variables APIs with timeout. - * @details If enabled then the conditional variables APIs with timeout - * specification are included in the kernel. - * - * @note The default is @p TRUE. - * @note Requires @p CH_CFG_USE_CONDVARS. - */ -#if !defined(CH_CFG_USE_CONDVARS_TIMEOUT) -#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE -#endif - -/** - * @brief Events Flags APIs. - * @details If enabled then the event flags APIs are included in the kernel. - * - * @note The default is @p TRUE. - */ -#if !defined(CH_CFG_USE_EVENTS) -#define CH_CFG_USE_EVENTS TRUE -#endif - -/** - * @brief Events Flags APIs with timeout. - * @details If enabled then the events APIs with timeout specification - * are included in the kernel. - * - * @note The default is @p TRUE. - * @note Requires @p CH_CFG_USE_EVENTS. - */ -#if !defined(CH_CFG_USE_EVENTS_TIMEOUT) -#define CH_CFG_USE_EVENTS_TIMEOUT TRUE -#endif - -/** - * @brief Synchronous Messages APIs. - * @details If enabled then the synchronous messages APIs are included - * in the kernel. - * - * @note The default is @p TRUE. - */ -#if !defined(CH_CFG_USE_MESSAGES) -#define CH_CFG_USE_MESSAGES TRUE -#endif - -/** - * @brief Synchronous Messages queuing mode. - * @details If enabled then messages are served by priority rather than in - * FIFO order. - * - * @note The default is @p FALSE. Enable this if you have special - * requirements. - * @note Requires @p CH_CFG_USE_MESSAGES. - */ -#if !defined(CH_CFG_USE_MESSAGES_PRIORITY) -#define CH_CFG_USE_MESSAGES_PRIORITY TRUE -#endif - -/** - * @brief Dynamic Threads APIs. - * @details If enabled then the dynamic threads creation APIs are included - * in the kernel. - * - * @note The default is @p TRUE. - * @note Requires @p CH_CFG_USE_WAITEXIT. - * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. - */ -#if !defined(CH_CFG_USE_DYNAMIC) -#define CH_CFG_USE_DYNAMIC TRUE -#endif - -/** @} */ - -/*===========================================================================*/ -/** - * @name OSLIB options - * @{ - */ -/*===========================================================================*/ - -/** - * @brief Mailboxes APIs. - * @details If enabled then the asynchronous messages (mailboxes) APIs are - * included in the kernel. - * - * @note The default is @p TRUE. - * @note Requires @p CH_CFG_USE_SEMAPHORES. - */ -#if !defined(CH_CFG_USE_MAILBOXES) -#define CH_CFG_USE_MAILBOXES TRUE -#endif - -/** - * @brief Core Memory Manager APIs. - * @details If enabled then the core memory manager APIs are included - * in the kernel. - * - * @note The default is @p TRUE. - */ -#if !defined(CH_CFG_USE_MEMCORE) -#define CH_CFG_USE_MEMCORE TRUE -#endif - -/** - * @brief Managed RAM size. - * @details Size of the RAM area to be managed by the OS. If set to zero - * then the whole available RAM is used. The core memory is made - * available to the heap allocator and/or can be used directly through - * the simplified core memory allocator. - * - * @note In order to let the OS manage the whole RAM the linker script must - * provide the @p __heap_base__ and @p __heap_end__ symbols. - * @note Requires @p CH_CFG_USE_MEMCORE. - */ -#if !defined(CH_CFG_MEMCORE_SIZE) -#define CH_CFG_MEMCORE_SIZE 0 -#endif - -/** - * @brief Heap Allocator APIs. - * @details If enabled then the memory heap allocator APIs are included - * in the kernel. - * - * @note The default is @p TRUE. - * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or - * @p CH_CFG_USE_SEMAPHORES. - * @note Mutexes are recommended. - */ -#if !defined(CH_CFG_USE_HEAP) -#define CH_CFG_USE_HEAP TRUE -#endif - -/** - * @brief Memory Pools Allocator APIs. - * @details If enabled then the memory pools allocator APIs are included - * in the kernel. - * - * @note The default is @p TRUE. - */ -#if !defined(CH_CFG_USE_MEMPOOLS) -#define CH_CFG_USE_MEMPOOLS TRUE -#endif - -/** - * @brief Objects FIFOs APIs. - * @details If enabled then the objects FIFOs APIs are included - * in the kernel. - * - * @note The default is @p TRUE. - */ -#if !defined(CH_CFG_USE_OBJ_FIFOS) -#define CH_CFG_USE_OBJ_FIFOS TRUE -#endif - -/** - * @brief Pipes APIs. - * @details If enabled then the pipes APIs are included - * in the kernel. - * - * @note The default is @p TRUE. - */ -#if !defined(CH_CFG_USE_PIPES) -#define CH_CFG_USE_PIPES TRUE -#endif - -/** - * @brief Objects Caches APIs. - * @details If enabled then the objects caches APIs are included - * in the kernel. - * - * @note The default is @p TRUE. - */ -#if !defined(CH_CFG_USE_OBJ_CACHES) -#define CH_CFG_USE_OBJ_CACHES FALSE -#endif - -/** - * @brief Delegate threads APIs. - * @details If enabled then the delegate threads APIs are included - * in the kernel. - * - * @note The default is @p TRUE. - */ -#if !defined(CH_CFG_USE_DELEGATES) -#define CH_CFG_USE_DELEGATES FALSE -#endif - -/** - * @brief Jobs Queues APIs. - * @details If enabled then the jobs queues APIs are included - * in the kernel. - * - * @note The default is @p TRUE. - */ -#if !defined(CH_CFG_USE_JOBS) -#define CH_CFG_USE_JOBS FALSE -#endif - -/** @} */ - -/*===========================================================================*/ -/** - * @name Objects factory options - * @{ - */ -/*===========================================================================*/ - -/** - * @brief Objects Factory APIs. - * @details If enabled then the objects factory APIs are included in the - * kernel. - * - * @note The default is @p FALSE. - */ -#if !defined(CH_CFG_USE_FACTORY) -#define CH_CFG_USE_FACTORY FALSE -#endif - -/** - * @brief Maximum length for object names. - * @details If the specified length is zero then the name is stored by - * pointer but this could have unintended side effects. - */ -#if !defined(CH_CFG_FACTORY_MAX_NAMES_LENGTH) -#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 -#endif - -/** - * @brief Enables the registry of generic objects. - */ -#if !defined(CH_CFG_FACTORY_OBJECTS_REGISTRY) -#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE -#endif - -/** - * @brief Enables factory for generic buffers. - */ -#if !defined(CH_CFG_FACTORY_GENERIC_BUFFERS) -#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE -#endif - -/** - * @brief Enables factory for semaphores. - */ -#if !defined(CH_CFG_FACTORY_SEMAPHORES) -#define CH_CFG_FACTORY_SEMAPHORES TRUE -#endif - -/** - * @brief Enables factory for mailboxes. - */ -#if !defined(CH_CFG_FACTORY_MAILBOXES) -#define CH_CFG_FACTORY_MAILBOXES TRUE -#endif - -/** - * @brief Enables factory for objects FIFOs. - */ -#if !defined(CH_CFG_FACTORY_OBJ_FIFOS) -#define CH_CFG_FACTORY_OBJ_FIFOS TRUE -#endif - -/** - * @brief Enables factory for Pipes. - */ -#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) -#define CH_CFG_FACTORY_PIPES TRUE -#endif - -/** @} */ - -/*===========================================================================*/ -/** - * @name Debug options - * @{ - */ -/*===========================================================================*/ - -/** - * @brief Debug option, kernel statistics. - * - * @note The default is @p FALSE. - */ -#if !defined(CH_DBG_STATISTICS) -#define CH_DBG_STATISTICS FALSE -#endif - -/** - * @brief Debug option, system state check. - * @details If enabled the correct call protocol for system APIs is checked - * at runtime. - * - * @note The default is @p FALSE. - */ -#if !defined(CH_DBG_SYSTEM_STATE_CHECK) -#define CH_DBG_SYSTEM_STATE_CHECK FALSE -#endif - -/** - * @brief Debug option, parameters checks. - * @details If enabled then the checks on the API functions input - * parameters are activated. - * - * @note The default is @p FALSE. - */ -#if !defined(CH_DBG_ENABLE_CHECKS) -#define CH_DBG_ENABLE_CHECKS FALSE -#endif - -/** - * @brief Debug option, consistency checks. - * @details If enabled then all the assertions in the kernel code are - * activated. This includes consistency checks inside the kernel, - * runtime anomalies and port-defined checks. - * - * @note The default is @p FALSE. - */ -#if !defined(CH_DBG_ENABLE_ASSERTS) -#define CH_DBG_ENABLE_ASSERTS FALSE -#endif - -/** - * @brief Debug option, trace buffer. - * @details If enabled then the trace buffer is activated. - * - * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. - */ -#if !defined(CH_DBG_TRACE_MASK) -#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED -#endif - -/** - * @brief Trace buffer entries. - * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is - * different from @p CH_DBG_TRACE_MASK_DISABLED. - */ -#if !defined(CH_DBG_TRACE_BUFFER_SIZE) -#define CH_DBG_TRACE_BUFFER_SIZE 128 -#endif - -/** - * @brief Debug option, stack checks. - * @details If enabled then a runtime stack check is performed. - * - * @note The default is @p FALSE. - * @note The stack check is performed in a architecture/port dependent way. - * It may not be implemented or some ports. - * @note The default failure mode is to halt the system with the global - * @p panic_msg variable set to @p NULL. - */ -#if !defined(CH_DBG_ENABLE_STACK_CHECK) -#define CH_DBG_ENABLE_STACK_CHECK TRUE -#endif - -/** - * @brief Debug option, stacks initialization. - * @details If enabled then the threads working area is filled with a byte - * value when a thread is created. This can be useful for the - * runtime measurement of the used stack. - * - * @note The default is @p FALSE. - */ -#if !defined(CH_DBG_FILL_THREADS) -#define CH_DBG_FILL_THREADS FALSE -#endif - -/** - * @brief Debug option, threads profiling. - * @details If enabled then a field is added to the @p thread_t structure that - * counts the system ticks occurred while executing the thread. - * - * @note The default is @p FALSE. - * @note This debug option is not currently compatible with the - * tickless mode. - */ -#if !defined(CH_DBG_THREADS_PROFILING) -#define CH_DBG_THREADS_PROFILING FALSE -#endif - -/** @} */ - -/*===========================================================================*/ -/** - * @name Kernel hooks - * @{ - */ -/*===========================================================================*/ - -/** - * @brief System structure extension. - * @details User fields added to the end of the @p ch_system_t structure. - */ -#define CH_CFG_SYSTEM_EXTRA_FIELDS \ - /* Add threads custom fields here.*/ - -/** - * @brief System initialization hook. - * @details User initialization code added to the @p chSysInit() function - * just before interrupts are enabled globally. - */ -#define CH_CFG_SYSTEM_INIT_HOOK() { \ - /* Add threads initialization code here.*/ \ -} - -/** - * @brief Threads descriptor structure extension. - * @details User fields added to the end of the @p thread_t structure. - */ -#define CH_CFG_THREAD_EXTRA_FIELDS \ - /* Add threads custom fields here.*/ - -/** - * @brief Threads initialization hook. - * @details User initialization code added to the @p _thread_init() function. - * - * @note It is invoked from within @p _thread_init() and implicitly from all - * the threads creation APIs. - */ -#define CH_CFG_THREAD_INIT_HOOK(tp) { \ - /* Add threads initialization code here.*/ \ -} - -/** - * @brief Threads finalization hook. - * @details User finalization code added to the @p chThdExit() API. - */ -#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ - /* Add threads finalization code here.*/ \ -} - -/** - * @brief Context switch hook. - * @details This hook is invoked just before switching between threads. - */ -#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ - /* Context switch code here.*/ \ -} - -/** - * @brief ISR enter hook. - */ -#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ - /* IRQ prologue code here.*/ \ -} - -/** - * @brief ISR exit hook. - */ -#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ - /* IRQ epilogue code here.*/ \ -} - -/** - * @brief Idle thread enter hook. - * @note This hook is invoked within a critical zone, no OS functions - * should be invoked from here. - * @note This macro can be used to activate a power saving mode. - */ -#define CH_CFG_IDLE_ENTER_HOOK() { \ - /* Idle-enter code here.*/ \ -} - -/** - * @brief Idle thread leave hook. - * @note This hook is invoked within a critical zone, no OS functions - * should be invoked from here. - * @note This macro can be used to deactivate a power saving mode. - */ -#define CH_CFG_IDLE_LEAVE_HOOK() { \ - /* Idle-leave code here.*/ \ -} - -/** - * @brief Idle Loop hook. - * @details This hook is continuously invoked by the idle thread loop. - */ -#define CH_CFG_IDLE_LOOP_HOOK() { \ - /* Idle loop code here.*/ \ -} - -/** - * @brief System tick event hook. - * @details This hook is invoked in the system tick handler immediately - * after processing the virtual timers queue. - */ -#define CH_CFG_SYSTEM_TICK_HOOK() { \ - /* System tick event code here.*/ \ -} - -/** - * @brief System halt hook. - * @details This hook is invoked in case to a system halting error before - * the system is halted. - */ -#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ - /* System halt code here.*/ \ -} - -/** - * @brief Trace hook. - * @details This hook is invoked each time a new record is written in the - * trace buffer. - */ -#define CH_CFG_TRACE_HOOK(tep) { \ - /* Trace code here.*/ \ -} - -/** @} */ - -/*===========================================================================*/ -/* Port-specific settings (override port settings defaulted in chcore.h). */ -/*===========================================================================*/ - -#endif /* CHCONF_H */ - -/** @} */ diff --git a/platforms/chibios/QMK_PROTON_C/configs/config.h b/platforms/chibios/QMK_PROTON_C/configs/config.h deleted file mode 100644 index a73f0c0b47..0000000000 --- a/platforms/chibios/QMK_PROTON_C/configs/config.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Copyright 2020 Nick Brassel (tzarc) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#pragma once - -#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP -# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE -#endif diff --git a/platforms/chibios/QMK_PROTON_C/configs/halconf.h b/platforms/chibios/QMK_PROTON_C/configs/halconf.h deleted file mode 100644 index d7a639a6d0..0000000000 --- a/platforms/chibios/QMK_PROTON_C/configs/halconf.h +++ /dev/null @@ -1,531 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - 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 License 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. -*/ - -/** - * @file templates/halconf.h - * @brief HAL configuration header. - * @details HAL configuration file, this file allows to enable or disable the - * various device drivers from your application. You may also use - * this file in order to override the device drivers default settings. - * - * @addtogroup HAL_CONF - * @{ - */ - -#ifndef HALCONF_H -#define HALCONF_H - -#define _CHIBIOS_HAL_CONF_ -#define _CHIBIOS_HAL_CONF_VER_7_1_ - -#include - -/** - * @brief Enables the PAL subsystem. - */ -#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) -#define HAL_USE_PAL TRUE -#endif - -/** - * @brief Enables the ADC subsystem. - */ -#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) -#define HAL_USE_ADC FALSE -#endif - -/** - * @brief Enables the CAN subsystem. - */ -#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) -#define HAL_USE_CAN FALSE -#endif - -/** - * @brief Enables the cryptographic subsystem. - */ -#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) -#define HAL_USE_CRY FALSE -#endif - -/** - * @brief Enables the DAC subsystem. - */ -#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) -#define HAL_USE_DAC TRUE -#endif - -/** - * @brief Enables the EFlash subsystem. - */ -#if !defined(HAL_USE_EFL) || defined(__DOXYGEN__) -#define HAL_USE_EFL FALSE -#endif - -/** - * @brief Enables the GPT subsystem. - */ -#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) -#define HAL_USE_GPT TRUE -#endif - -/** - * @brief Enables the I2C subsystem. - */ -#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) -#define HAL_USE_I2C TRUE -#endif - -/** - * @brief Enables the I2S subsystem. - */ -#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) -#define HAL_USE_I2S FALSE -#endif - -/** - * @brief Enables the ICU subsystem. - */ -#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) -#define HAL_USE_ICU FALSE -#endif - -/** - * @brief Enables the MAC subsystem. - */ -#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) -#define HAL_USE_MAC FALSE -#endif - -/** - * @brief Enables the MMC_SPI subsystem. - */ -#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) -#define HAL_USE_MMC_SPI FALSE -#endif - -/** - * @brief Enables the PWM subsystem. - */ -#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) -#define HAL_USE_PWM TRUE -#endif - -/** - * @brief Enables the RTC subsystem. - */ -#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) -#define HAL_USE_RTC FALSE -#endif - -/** - * @brief Enables the SDC subsystem. - */ -#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) -#define HAL_USE_SDC FALSE -#endif - -/** - * @brief Enables the SERIAL subsystem. - */ -#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) -#define HAL_USE_SERIAL FALSE -#endif - -/** - * @brief Enables the SERIAL over USB subsystem. - */ -#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) -#define HAL_USE_SERIAL_USB TRUE -#endif - -/** - * @brief Enables the SIO subsystem. - */ -#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__) -#define HAL_USE_SIO FALSE -#endif - -/** - * @brief Enables the SPI subsystem. - */ -#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) -#define HAL_USE_SPI TRUE -#endif - -/** - * @brief Enables the TRNG subsystem. - */ -#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__) -#define HAL_USE_TRNG FALSE -#endif - -/** - * @brief Enables the UART subsystem. - */ -#if !defined(HAL_USE_UART) || defined(__DOXYGEN__) -#define HAL_USE_UART FALSE -#endif - -/** - * @brief Enables the USB subsystem. - */ -#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) -#define HAL_USE_USB TRUE -#endif - -/** - * @brief Enables the WDG subsystem. - */ -#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) -#define HAL_USE_WDG FALSE -#endif - -/** - * @brief Enables the WSPI subsystem. - */ -#if !defined(HAL_USE_WSPI) || defined(__DOXYGEN__) -#define HAL_USE_WSPI FALSE -#endif - -/*===========================================================================*/ -/* PAL driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Enables synchronous APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) -#define PAL_USE_CALLBACKS TRUE -#endif - -/** - * @brief Enables synchronous APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) -#define PAL_USE_WAIT TRUE -#endif - -/*===========================================================================*/ -/* ADC driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Enables synchronous APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) -#define ADC_USE_WAIT TRUE -#endif - -/** - * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) -#define ADC_USE_MUTUAL_EXCLUSION TRUE -#endif - -/*===========================================================================*/ -/* CAN driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Sleep mode related APIs inclusion switch. - */ -#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) -#define CAN_USE_SLEEP_MODE TRUE -#endif - -/** - * @brief Enforces the driver to use direct callbacks rather than OSAL events. - */ -#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__) -#define CAN_ENFORCE_USE_CALLBACKS FALSE -#endif - -/*===========================================================================*/ -/* CRY driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Enables the SW fall-back of the cryptographic driver. - * @details When enabled, this option, activates a fall-back software - * implementation for algorithms not supported by the underlying - * hardware. - * @note Fall-back implementations may not be present for all algorithms. - */ -#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) -#define HAL_CRY_USE_FALLBACK FALSE -#endif - -/** - * @brief Makes the driver forcibly use the fall-back implementations. - */ -#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) -#define HAL_CRY_ENFORCE_FALLBACK FALSE -#endif - -/*===========================================================================*/ -/* DAC driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Enables synchronous APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) -#define DAC_USE_WAIT TRUE -#endif - -/** - * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) -#define DAC_USE_MUTUAL_EXCLUSION TRUE -#endif - -/*===========================================================================*/ -/* I2C driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Enables the mutual exclusion APIs on the I2C bus. - */ -#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) -#define I2C_USE_MUTUAL_EXCLUSION TRUE -#endif - -/*===========================================================================*/ -/* MAC driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Enables the zero-copy API. - */ -#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) -#define MAC_USE_ZERO_COPY FALSE -#endif - -/** - * @brief Enables an event sources for incoming packets. - */ -#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) -#define MAC_USE_EVENTS TRUE -#endif - -/*===========================================================================*/ -/* MMC_SPI driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Delays insertions. - * @details If enabled this options inserts delays into the MMC waiting - * routines releasing some extra CPU time for the threads with - * lower priority, this may slow down the driver a bit however. - * This option is recommended also if the SPI driver does not - * use a DMA channel and heavily loads the CPU. - */ -#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) -#define MMC_NICE_WAITING TRUE -#endif - -/*===========================================================================*/ -/* SDC driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Number of initialization attempts before rejecting the card. - * @note Attempts are performed at 10mS intervals. - */ -#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) -#define SDC_INIT_RETRY 100 -#endif - -/** - * @brief Include support for MMC cards. - * @note MMC support is not yet implemented so this option must be kept - * at @p FALSE. - */ -#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) -#define SDC_MMC_SUPPORT FALSE -#endif - -/** - * @brief Delays insertions. - * @details If enabled this options inserts delays into the MMC waiting - * routines releasing some extra CPU time for the threads with - * lower priority, this may slow down the driver a bit however. - */ -#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) -#define SDC_NICE_WAITING TRUE -#endif - -/** - * @brief OCR initialization constant for V20 cards. - */ -#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__) -#define SDC_INIT_OCR_V20 0x50FF8000U -#endif - -/** - * @brief OCR initialization constant for non-V20 cards. - */ -#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__) -#define SDC_INIT_OCR 0x80100000U -#endif - -/*===========================================================================*/ -/* SERIAL driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Default bit rate. - * @details Configuration parameter, this is the baud rate selected for the - * default configuration. - */ -#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) -#define SERIAL_DEFAULT_BITRATE 38400 -#endif - -/** - * @brief Serial buffers size. - * @details Configuration parameter, you can change the depth of the queue - * buffers depending on the requirements of your application. - * @note The default is 16 bytes for both the transmission and receive - * buffers. - */ -#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) -#define SERIAL_BUFFERS_SIZE 128 -#endif - -/*===========================================================================*/ -/* SERIAL_USB driver related setting. */ -/*===========================================================================*/ - -/** - * @brief Serial over USB buffers size. - * @details Configuration parameter, the buffer size must be a multiple of - * the USB data endpoint maximum packet size. - * @note The default is 256 bytes for both the transmission and receive - * buffers. - */ -#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) -#define SERIAL_USB_BUFFERS_SIZE 1 -#endif - -/** - * @brief Serial over USB number of buffers. - * @note The default is 2 buffers. - */ -#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) -#define SERIAL_USB_BUFFERS_NUMBER 2 -#endif - -/*===========================================================================*/ -/* SPI driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Enables synchronous APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) -#define SPI_USE_WAIT TRUE -#endif - -/** - * @brief Enables circular transfers APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__) -#define SPI_USE_CIRCULAR FALSE -#endif - -/** - * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) -#define SPI_USE_MUTUAL_EXCLUSION TRUE -#endif - -/** - * @brief Handling method for SPI CS line. - * @note Disabling this option saves both code and data space. - */ -#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) -#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD -#endif - -/*===========================================================================*/ -/* UART driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Enables synchronous APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) -#define UART_USE_WAIT FALSE -#endif - -/** - * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) -#define UART_USE_MUTUAL_EXCLUSION FALSE -#endif - -/*===========================================================================*/ -/* USB driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Enables synchronous APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) -#define USB_USE_WAIT TRUE -#endif - -/*===========================================================================*/ -/* WSPI driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Enables synchronous APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) -#define WSPI_USE_WAIT TRUE -#endif - -/** - * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) -#define WSPI_USE_MUTUAL_EXCLUSION TRUE -#endif - -#endif /* HALCONF_H */ - -/** @} */ diff --git a/platforms/chibios/QMK_PROTON_C/configs/mcuconf.h b/platforms/chibios/QMK_PROTON_C/configs/mcuconf.h deleted file mode 100644 index 4d7b586c08..0000000000 --- a/platforms/chibios/QMK_PROTON_C/configs/mcuconf.h +++ /dev/null @@ -1,273 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - 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 License 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. -*/ - -#ifndef MCUCONF_H -#define MCUCONF_H - -/* - * STM32F3xx drivers configuration. - * The following settings override the default settings present in - * the various device driver implementation headers. - * Note that the settings for each driver only have effect if the whole - * driver is enabled in halconf.h. - * - * IRQ priorities: - * 15...0 Lowest...Highest. - * - * DMA priorities: - * 0...3 Lowest...Highest. - */ - -#define STM32F3xx_MCUCONF -#define STM32F303_MCUCONF - -/* - * HAL driver system settings. - */ -#define STM32_NO_INIT FALSE -#define STM32_PVD_ENABLE FALSE -#define STM32_PLS STM32_PLS_LEV0 -#define STM32_HSI_ENABLED TRUE -#define STM32_LSI_ENABLED TRUE -#define STM32_HSE_ENABLED TRUE -#define STM32_LSE_ENABLED FALSE -#define STM32_SW STM32_SW_PLL -#define STM32_PLLSRC STM32_PLLSRC_HSE -#define STM32_PREDIV_VALUE 1 -#define STM32_PLLMUL_VALUE 9 -#define STM32_HPRE STM32_HPRE_DIV1 -#define STM32_PPRE1 STM32_PPRE1_DIV2 -#define STM32_PPRE2 STM32_PPRE2_DIV2 -#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK -#define STM32_ADC12PRES STM32_ADC12PRES_DIV1 -#define STM32_ADC34PRES STM32_ADC34PRES_DIV1 -#define STM32_USART1SW STM32_USART1SW_PCLK -#define STM32_USART2SW STM32_USART2SW_PCLK -#define STM32_USART3SW STM32_USART3SW_PCLK -#define STM32_UART4SW STM32_UART4SW_PCLK -#define STM32_UART5SW STM32_UART5SW_PCLK -#define STM32_I2C1SW STM32_I2C1SW_SYSCLK -#define STM32_I2C2SW STM32_I2C2SW_SYSCLK -#define STM32_TIM1SW STM32_TIM1SW_PCLK2 -#define STM32_TIM8SW STM32_TIM8SW_PCLK2 -#define STM32_RTCSEL STM32_RTCSEL_LSI -#define STM32_USB_CLOCK_REQUIRED TRUE -#define STM32_USBPRE STM32_USBPRE_DIV1P5 - -/* - * IRQ system settings. - */ -#define STM32_IRQ_EXTI0_PRIORITY 6 -#define STM32_IRQ_EXTI1_PRIORITY 6 -#define STM32_IRQ_EXTI2_PRIORITY 6 -#define STM32_IRQ_EXTI3_PRIORITY 6 -#define STM32_IRQ_EXTI4_PRIORITY 6 -#define STM32_IRQ_EXTI5_9_PRIORITY 6 -#define STM32_IRQ_EXTI10_15_PRIORITY 6 -#define STM32_IRQ_EXTI16_PRIORITY 6 -#define STM32_IRQ_EXTI17_PRIORITY 15 -#define STM32_IRQ_EXTI18_PRIORITY 6 -#define STM32_IRQ_EXTI19_PRIORITY 15 -#define STM32_IRQ_EXTI20_PRIORITY 15 -#define STM32_IRQ_EXTI21_22_29_PRIORITY 6 -#define STM32_IRQ_EXTI30_32_PRIORITY 6 -#define STM32_IRQ_EXTI33_PRIORITY 6 -#define STM32_IRQ_TIM1_BRK_TIM15_PRIORITY 7 -#define STM32_IRQ_TIM1_UP_TIM16_PRIORITY 7 -#define STM32_IRQ_TIM1_TRGCO_TIM17_PRIORITY 7 -#define STM32_IRQ_TIM1_CC_PRIORITY 7 - -/* - * ADC driver system settings. - */ -#define STM32_ADC_DUAL_MODE FALSE -#define STM32_ADC_COMPACT_SAMPLES FALSE -#define STM32_ADC_USE_ADC1 FALSE -#define STM32_ADC_USE_ADC2 FALSE -#define STM32_ADC_USE_ADC3 FALSE -#define STM32_ADC_USE_ADC4 FALSE -#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) -#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) -#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) -#define STM32_ADC_ADC4_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) -#define STM32_ADC_ADC1_DMA_PRIORITY 2 -#define STM32_ADC_ADC2_DMA_PRIORITY 2 -#define STM32_ADC_ADC3_DMA_PRIORITY 2 -#define STM32_ADC_ADC4_DMA_PRIORITY 2 -#define STM32_ADC_ADC12_IRQ_PRIORITY 5 -#define STM32_ADC_ADC3_IRQ_PRIORITY 5 -#define STM32_ADC_ADC4_IRQ_PRIORITY 5 -#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 5 -#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 5 -#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 5 -#define STM32_ADC_ADC4_DMA_IRQ_PRIORITY 5 -#define STM32_ADC_ADC12_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1 -#define STM32_ADC_ADC34_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1 - -/* - * CAN driver system settings. - */ -#define STM32_CAN_USE_CAN1 FALSE -#define STM32_CAN_CAN1_IRQ_PRIORITY 11 - -/* - * DAC driver system settings. - */ -#define STM32_DAC_DUAL_MODE FALSE -#define STM32_DAC_USE_DAC1_CH1 TRUE -#define STM32_DAC_USE_DAC1_CH2 TRUE -#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 -#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 -#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 -#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 - -/* - * GPT driver system settings. - */ -#define STM32_GPT_USE_TIM1 FALSE -#define STM32_GPT_USE_TIM2 FALSE -#define STM32_GPT_USE_TIM3 FALSE -#define STM32_GPT_USE_TIM4 FALSE -#define STM32_GPT_USE_TIM6 TRUE -#define STM32_GPT_USE_TIM7 TRUE -#define STM32_GPT_USE_TIM8 TRUE -#define STM32_GPT_USE_TIM15 TRUE -#define STM32_GPT_USE_TIM16 FALSE -#define STM32_GPT_USE_TIM17 FALSE -#define STM32_GPT_TIM1_IRQ_PRIORITY 7 -#define STM32_GPT_TIM2_IRQ_PRIORITY 7 -#define STM32_GPT_TIM3_IRQ_PRIORITY 7 -#define STM32_GPT_TIM4_IRQ_PRIORITY 7 -#define STM32_GPT_TIM6_IRQ_PRIORITY 7 -#define STM32_GPT_TIM7_IRQ_PRIORITY 7 -#define STM32_GPT_TIM8_IRQ_PRIORITY 7 - -/* - * I2C driver system settings. - */ -#define STM32_I2C_USE_I2C1 TRUE -#define STM32_I2C_USE_I2C2 FALSE -#define STM32_I2C_BUSY_TIMEOUT 50 -#define STM32_I2C_I2C1_IRQ_PRIORITY 10 -#define STM32_I2C_I2C2_IRQ_PRIORITY 10 -#define STM32_I2C_USE_DMA TRUE -#define STM32_I2C_I2C1_DMA_PRIORITY 1 -#define STM32_I2C_I2C2_DMA_PRIORITY 1 -#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") - -/* - * ICU driver system settings. - */ -#define STM32_ICU_USE_TIM1 FALSE -#define STM32_ICU_USE_TIM2 FALSE -#define STM32_ICU_USE_TIM3 FALSE -#define STM32_ICU_USE_TIM4 FALSE -#define STM32_ICU_USE_TIM8 FALSE -#define STM32_ICU_USE_TIM15 FALSE -#define STM32_ICU_TIM1_IRQ_PRIORITY 7 -#define STM32_ICU_TIM2_IRQ_PRIORITY 7 -#define STM32_ICU_TIM3_IRQ_PRIORITY 7 -#define STM32_ICU_TIM4_IRQ_PRIORITY 7 -#define STM32_ICU_TIM8_IRQ_PRIORITY 7 - -/* - * PWM driver system settings. - */ -#define STM32_PWM_USE_ADVANCED FALSE -#define STM32_PWM_USE_TIM1 FALSE -#define STM32_PWM_USE_TIM2 FALSE -#define STM32_PWM_USE_TIM3 TRUE -#define STM32_PWM_USE_TIM4 TRUE -#define STM32_PWM_USE_TIM8 FALSE -#define STM32_PWM_USE_TIM15 FALSE -#define STM32_PWM_USE_TIM16 FALSE -#define STM32_PWM_USE_TIM17 FALSE -#define STM32_PWM_TIM1_IRQ_PRIORITY 7 -#define STM32_PWM_TIM2_IRQ_PRIORITY 7 -#define STM32_PWM_TIM3_IRQ_PRIORITY 7 -#define STM32_PWM_TIM4_IRQ_PRIORITY 7 -#define STM32_PWM_TIM8_IRQ_PRIORITY 7 - -/* - * RTC driver system settings. - */ -#define STM32_RTC_PRESA_VALUE 32 -#define STM32_RTC_PRESS_VALUE 1024 -#define STM32_RTC_CR_INIT 0 -#define STM32_RTC_TAMPCR_INIT 0 - -/* - * SERIAL driver system settings. - */ -#define STM32_SERIAL_USE_USART1 TRUE -#define STM32_SERIAL_USE_USART2 FALSE -#define STM32_SERIAL_USE_USART3 FALSE -#define STM32_SERIAL_USE_UART4 FALSE -#define STM32_SERIAL_USE_UART5 FALSE -#define STM32_SERIAL_USART1_PRIORITY 12 -#define STM32_SERIAL_USART2_PRIORITY 12 -#define STM32_SERIAL_USART3_PRIORITY 12 -#define STM32_SERIAL_UART4_PRIORITY 12 -#define STM32_SERIAL_UART5_PRIORITY 12 - -/* - * SPI driver system settings. - */ -#define STM32_SPI_USE_SPI1 FALSE -#define STM32_SPI_USE_SPI2 TRUE -#define STM32_SPI_USE_SPI3 FALSE -#define STM32_SPI_SPI1_DMA_PRIORITY 1 -#define STM32_SPI_SPI2_DMA_PRIORITY 1 -#define STM32_SPI_SPI3_DMA_PRIORITY 1 -#define STM32_SPI_SPI1_IRQ_PRIORITY 10 -#define STM32_SPI_SPI2_IRQ_PRIORITY 10 -#define STM32_SPI_SPI3_IRQ_PRIORITY 10 -#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") - -/* - * ST driver system settings. - */ -#define STM32_ST_IRQ_PRIORITY 8 -#define STM32_ST_USE_TIMER 2 - -/* - * UART driver system settings. - */ -#define STM32_UART_USE_USART1 FALSE -#define STM32_UART_USE_USART2 FALSE -#define STM32_UART_USE_USART3 FALSE -#define STM32_UART_USART1_IRQ_PRIORITY 12 -#define STM32_UART_USART2_IRQ_PRIORITY 12 -#define STM32_UART_USART3_IRQ_PRIORITY 12 -#define STM32_UART_USART1_DMA_PRIORITY 0 -#define STM32_UART_USART2_DMA_PRIORITY 0 -#define STM32_UART_USART3_DMA_PRIORITY 0 -#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") - -/* - * USB driver system settings. - */ -#define STM32_USB_USE_USB1 TRUE -#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE -#define STM32_USB_USB1_HP_IRQ_PRIORITY 13 -#define STM32_USB_USB1_LP_IRQ_PRIORITY 14 - -/* - * WDG driver system settings. - */ -#define STM32_WDG_USE_IWDG FALSE - -#endif /* MCUCONF_H */ diff --git a/platforms/chibios/QMK_PROTON_C/convert_to_proton_c.mk b/platforms/chibios/QMK_PROTON_C/convert_to_proton_c.mk deleted file mode 100644 index 0618154678..0000000000 --- a/platforms/chibios/QMK_PROTON_C/convert_to_proton_c.mk +++ /dev/null @@ -1,10 +0,0 @@ -# Proton C MCU settings for converting AVR projects -TARGET := $(TARGET)_proton_c -MCU := STM32F303 -BOARD := QMK_PROTON_C -BOOTLOADER := stm32-dfu -OPT_DEFS += -DCONVERT_TO_PROTON_C - -# These are defaults based on what has been implemented for ARM boards -AUDIO_ENABLE ?= yes -WS2812_DRIVER ?= bitbang diff --git a/platforms/chibios/STM32_F103_STM32DUINO/board/board.c b/platforms/chibios/STM32_F103_STM32DUINO/board/board.c deleted file mode 100644 index 8a34e81f25..0000000000 --- a/platforms/chibios/STM32_F103_STM32DUINO/board/board.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio - - 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 License 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. -*/ - -#include - -// Value to place in RTC backup register 10 for persistent bootloader mode -#define RTC_BOOTLOADER_FLAG 0x424C - -/** - * @brief PAL setup. - * @details Digital I/O ports static configuration as defined in @p board.h. - * This variable is used by the HAL when initializing the PAL driver. - */ -#if HAL_USE_PAL || defined(__DOXYGEN__) -const PALConfig pal_default_config = -{ - {VAL_GPIOAODR, VAL_GPIOACRL, VAL_GPIOACRH}, - {VAL_GPIOBODR, VAL_GPIOBCRL, VAL_GPIOBCRH}, - {VAL_GPIOCODR, VAL_GPIOCCRL, VAL_GPIOCCRH}, - {VAL_GPIODODR, VAL_GPIODCRL, VAL_GPIODCRH}, - {VAL_GPIOEODR, VAL_GPIOECRL, VAL_GPIOECRH}, -}; -#endif - -__attribute__((weak)) void enter_bootloader_mode_if_requested(void) {} - -/* - * Early initialization code. - * This initialization must be performed just after stack setup and before - * any other initialization. - */ -void __early_init(void) { - enter_bootloader_mode_if_requested(); - - stm32_clock_init(); -} - -/* - * Board-specific initialization code. - */ -void boardInit(void) { - //JTAG-DP Disabled and SW-DP Enabled - AFIO->MAPR |= AFIO_MAPR_SWJ_CFG_JTAGDISABLE; - //Set backup register DR10 to enter bootloader on reset - BKP->DR10 = RTC_BOOTLOADER_FLAG; -} diff --git a/platforms/chibios/STM32_F103_STM32DUINO/board/board.h b/platforms/chibios/STM32_F103_STM32DUINO/board/board.h deleted file mode 100644 index 09d182d6ca..0000000000 --- a/platforms/chibios/STM32_F103_STM32DUINO/board/board.h +++ /dev/null @@ -1,166 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio - - 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 License 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. -*/ - -#ifndef _BOARD_H_ -#define _BOARD_H_ - -/* - * Setup for a Generic STM32F103 board. - */ - -/* - * Board identifier. - */ -#define BOARD_STM32_F103_STM32DUINO -#define BOARD_NAME "GENERIC STM32F103C8T6 board - stm32duino bootloader" - -/* - * Board frequencies. - */ -#define STM32_LSECLK 32768 -#define STM32_HSECLK 8000000 - -/* - * MCU type, supported types are defined in ./os/hal/platforms/hal_lld.h. - */ -#define STM32F103xB - -/* - * IO pins assignments - */ - -/* on-board */ - -#define GPIOA_LED 8 -#define GPIOD_OSC_IN 0 -#define GPIOD_OSC_OUT 1 - -/* In case your board has a "USB enable" hardware - controlled by a pin, define it here. (It could be just - a 1.5k resistor connected to D+ line.) -*/ -/* -#define GPIOB_USB_DISC 10 -*/ - -/* - * I/O ports initial setup, this configuration is established soon after reset - * in the initialization code. - * - * The digits have the following meaning: - * 0 - Analog input. - * 1 - Push Pull output 10MHz. - * 2 - Push Pull output 2MHz. - * 3 - Push Pull output 50MHz. - * 4 - Digital input. - * 5 - Open Drain output 10MHz. - * 6 - Open Drain output 2MHz. - * 7 - Open Drain output 50MHz. - * 8 - Digital input with PullUp or PullDown resistor depending on ODR. - * 9 - Alternate Push Pull output 10MHz. - * A - Alternate Push Pull output 2MHz. - * B - Alternate Push Pull output 50MHz. - * C - Reserved. - * D - Alternate Open Drain output 10MHz. - * E - Alternate Open Drain output 2MHz. - * F - Alternate Open Drain output 50MHz. - * Please refer to the STM32 Reference Manual for details. - */ - -/* - * Port A setup. - * Everything input with pull-up except: - * PA2 - Alternate output (USART2 TX). - * PA3 - Normal input (USART2 RX). - * PA9 - Alternate output (USART1 TX). - * PA10 - Normal input (USART1 RX). - */ -#define VAL_GPIOACRL 0x88884B88 /* PA7...PA0 */ -#define VAL_GPIOACRH 0x888884B8 /* PA15...PA8 */ -#define VAL_GPIOAODR 0xFFFFFFFF - -/* - * Port B setup. - * Everything input with pull-up except: - * PB10 - Push Pull output (USB switch). - */ -#define VAL_GPIOBCRL 0x88888888 /* PB7...PB0 */ -#define VAL_GPIOBCRH 0x88888388 /* PB15...PB8 */ -#define VAL_GPIOBODR 0xFFFFFFFF - -/* - * Port C setup. - * Everything input with pull-up except: - * PC13 - Push Pull output (LED). - */ -#define VAL_GPIOCCRL 0x88888888 /* PC7...PC0 */ -#define VAL_GPIOCCRH 0x88388888 /* PC15...PC8 */ -#define VAL_GPIOCODR 0xFFFFFFFF - -/* - * Port D setup. - * Everything input with pull-up except: - * PD0 - Normal input (XTAL). - * PD1 - Normal input (XTAL). - */ -#define VAL_GPIODCRL 0x88888844 /* PD7...PD0 */ -#define VAL_GPIODCRH 0x88888888 /* PD15...PD8 */ -#define VAL_GPIODODR 0xFFFFFFFF - -/* - * Port E setup. - * Everything input with pull-up except: - */ -#define VAL_GPIOECRL 0x88888888 /* PE7...PE0 */ -#define VAL_GPIOECRH 0x88888888 /* PE15...PE8 */ -#define VAL_GPIOEODR 0xFFFFFFFF - -/* - * USB bus activation macro, required by the USB driver. - */ -/* The point is that most of the generic STM32F103* boards - have a 1.5k resistor connected on one end to the D+ line - and on the other end to some pin. Or even a slightly more - complicated "USB enable" circuit, controlled by a pin. - That should go here. - - However on some boards (e.g. one that I have), there's no - such hardware. In which case it's better to not do anything. -*/ -/* -#define usb_lld_connect_bus(usbp) palClearPad(GPIOB, GPIOB_USB_DISC) -*/ -#define usb_lld_connect_bus(usbp) palSetPadMode(GPIOA, 12, PAL_MODE_INPUT); - -/* - * USB bus de-activation macro, required by the USB driver. - */ -/* -#define usb_lld_disconnect_bus(usbp) palSetPad(GPIOB, GPIOB_USB_DISC) -*/ -#define usb_lld_disconnect_bus(usbp) palSetPadMode(GPIOA, 12, PAL_MODE_OUTPUT_PUSHPULL); palClearPad(GPIOA, 12); - -#if !defined(_FROM_ASM_) -#ifdef __cplusplus -extern "C" { -#endif - void boardInit(void); -#ifdef __cplusplus -} -#endif -#endif /* _FROM_ASM_ */ - -#endif /* _BOARD_H_ */ diff --git a/platforms/chibios/STM32_F103_STM32DUINO/board/board.mk b/platforms/chibios/STM32_F103_STM32DUINO/board/board.mk deleted file mode 100644 index 842e335905..0000000000 --- a/platforms/chibios/STM32_F103_STM32DUINO/board/board.mk +++ /dev/null @@ -1,9 +0,0 @@ -# List of all the board related files. -BOARDSRC = $(BOARD_PATH)/board/board.c - -# Required include directories -BOARDINC = $(BOARD_PATH)/board - -# Shared variables -ALLCSRC += $(BOARDSRC) -ALLINC += $(BOARDINC) diff --git a/platforms/chibios/STM32_F103_STM32DUINO/configs/mcuconf.h b/platforms/chibios/STM32_F103_STM32DUINO/configs/mcuconf.h deleted file mode 100644 index 9945e7408d..0000000000 --- a/platforms/chibios/STM32_F103_STM32DUINO/configs/mcuconf.h +++ /dev/null @@ -1,209 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio - - 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 License 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. -*/ - -#ifndef _MCUCONF_H_ -#define _MCUCONF_H_ - -#define STM32F103_MCUCONF - -/* - * STM32F103 drivers configuration. - * The following settings override the default settings present in - * the various device driver implementation headers. - * Note that the settings for each driver only have effect if the whole - * driver is enabled in halconf.h. - * - * IRQ priorities: - * 15...0 Lowest...Highest. - * - * DMA priorities: - * 0...3 Lowest...Highest. - */ - -/* - * HAL driver system settings. - */ -#define STM32_NO_INIT FALSE -#define STM32_HSI_ENABLED TRUE -#define STM32_LSI_ENABLED FALSE -#define STM32_HSE_ENABLED TRUE -#define STM32_LSE_ENABLED FALSE -#define STM32_SW STM32_SW_PLL -#define STM32_PLLSRC STM32_PLLSRC_HSE -#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1 -#define STM32_PLLMUL_VALUE 9 -#define STM32_HPRE STM32_HPRE_DIV1 -#define STM32_PPRE1 STM32_PPRE1_DIV2 -#define STM32_PPRE2 STM32_PPRE2_DIV2 -#define STM32_ADCPRE STM32_ADCPRE_DIV4 -#define STM32_USB_CLOCK_REQUIRED TRUE -#define STM32_USBPRE STM32_USBPRE_DIV1P5 -#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK -#define STM32_RTCSEL STM32_RTCSEL_HSEDIV -#define STM32_PVD_ENABLE FALSE -#define STM32_PLS STM32_PLS_LEV0 - -/* - * ADC driver system settings. - */ -#define STM32_ADC_USE_ADC1 FALSE -#define STM32_ADC_ADC1_DMA_PRIORITY 2 -#define STM32_ADC_ADC1_IRQ_PRIORITY 6 - -/* - * CAN driver system settings. - */ -#define STM32_CAN_USE_CAN1 FALSE -#define STM32_CAN_CAN1_IRQ_PRIORITY 11 - -/* - * EXT driver system settings. - */ -#define STM32_EXT_EXTI0_IRQ_PRIORITY 6 -#define STM32_EXT_EXTI1_IRQ_PRIORITY 6 -#define STM32_EXT_EXTI2_IRQ_PRIORITY 6 -#define STM32_EXT_EXTI3_IRQ_PRIORITY 6 -#define STM32_EXT_EXTI4_IRQ_PRIORITY 6 -#define STM32_EXT_EXTI5_9_IRQ_PRIORITY 6 -#define STM32_EXT_EXTI10_15_IRQ_PRIORITY 6 -#define STM32_EXT_EXTI16_IRQ_PRIORITY 6 -#define STM32_EXT_EXTI17_IRQ_PRIORITY 6 -#define STM32_EXT_EXTI18_IRQ_PRIORITY 6 -#define STM32_EXT_EXTI19_IRQ_PRIORITY 6 - -/* - * GPT driver system settings. - */ -#define STM32_GPT_USE_TIM1 FALSE -#define STM32_GPT_USE_TIM2 FALSE -#define STM32_GPT_USE_TIM3 FALSE -#define STM32_GPT_USE_TIM4 FALSE -#define STM32_GPT_USE_TIM5 FALSE -#define STM32_GPT_USE_TIM8 FALSE -#define STM32_GPT_TIM1_IRQ_PRIORITY 7 -#define STM32_GPT_TIM2_IRQ_PRIORITY 7 -#define STM32_GPT_TIM3_IRQ_PRIORITY 7 -#define STM32_GPT_TIM4_IRQ_PRIORITY 7 -#define STM32_GPT_TIM5_IRQ_PRIORITY 7 -#define STM32_GPT_TIM8_IRQ_PRIORITY 7 - -/* - * I2C driver system settings. - */ -#define STM32_I2C_USE_I2C1 FALSE -#define STM32_I2C_USE_I2C2 FALSE -#define STM32_I2C_BUSY_TIMEOUT 50 -#define STM32_I2C_I2C1_IRQ_PRIORITY 5 -#define STM32_I2C_I2C2_IRQ_PRIORITY 5 -#define STM32_I2C_I2C1_DMA_PRIORITY 3 -#define STM32_I2C_I2C2_DMA_PRIORITY 3 -#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") - -/* - * ICU driver system settings. - */ -#define STM32_ICU_USE_TIM1 FALSE -#define STM32_ICU_USE_TIM2 FALSE -#define STM32_ICU_USE_TIM3 FALSE -#define STM32_ICU_USE_TIM4 FALSE -#define STM32_ICU_USE_TIM5 FALSE -#define STM32_ICU_USE_TIM8 FALSE -#define STM32_ICU_TIM1_IRQ_PRIORITY 7 -#define STM32_ICU_TIM2_IRQ_PRIORITY 7 -#define STM32_ICU_TIM3_IRQ_PRIORITY 7 -#define STM32_ICU_TIM4_IRQ_PRIORITY 7 -#define STM32_ICU_TIM5_IRQ_PRIORITY 7 -#define STM32_ICU_TIM8_IRQ_PRIORITY 7 - -/* - * PWM driver system settings. - */ -#define STM32_PWM_USE_ADVANCED FALSE -#define STM32_PWM_USE_TIM1 FALSE -#define STM32_PWM_USE_TIM2 FALSE -#define STM32_PWM_USE_TIM3 FALSE -#define STM32_PWM_USE_TIM4 FALSE -#define STM32_PWM_USE_TIM5 FALSE -#define STM32_PWM_USE_TIM8 FALSE -#define STM32_PWM_TIM1_IRQ_PRIORITY 7 -#define STM32_PWM_TIM2_IRQ_PRIORITY 7 -#define STM32_PWM_TIM3_IRQ_PRIORITY 7 -#define STM32_PWM_TIM4_IRQ_PRIORITY 7 -#define STM32_PWM_TIM5_IRQ_PRIORITY 7 -#define STM32_PWM_TIM8_IRQ_PRIORITY 7 - -/* - * RTC driver system settings. - */ -#define STM32_RTC_IRQ_PRIORITY 15 - -/* - * SERIAL driver system settings. - */ -#define STM32_SERIAL_USE_USART1 FALSE -#define STM32_SERIAL_USE_USART2 FALSE -#define STM32_SERIAL_USE_USART3 FALSE -#define STM32_SERIAL_USE_UART4 FALSE -#define STM32_SERIAL_USE_UART5 FALSE -#define STM32_SERIAL_USART1_PRIORITY 12 -#define STM32_SERIAL_USART2_PRIORITY 12 -#define STM32_SERIAL_USART3_PRIORITY 12 -#define STM32_SERIAL_UART4_PRIORITY 12 -#define STM32_SERIAL_UART5_PRIORITY 12 - -/* - * SPI driver system settings. - */ -#define STM32_SPI_USE_SPI1 FALSE -#define STM32_SPI_USE_SPI2 TRUE -#define STM32_SPI_USE_SPI3 FALSE -#define STM32_SPI_SPI1_DMA_PRIORITY 1 -#define STM32_SPI_SPI2_DMA_PRIORITY 1 -#define STM32_SPI_SPI3_DMA_PRIORITY 1 -#define STM32_SPI_SPI1_IRQ_PRIORITY 10 -#define STM32_SPI_SPI2_IRQ_PRIORITY 10 -#define STM32_SPI_SPI3_IRQ_PRIORITY 10 -#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") - -/* - * ST driver system settings. - */ -#define STM32_ST_IRQ_PRIORITY 8 -#define STM32_ST_USE_TIMER 2 - -/* - * UART driver system settings. - */ -#define STM32_UART_USE_USART1 FALSE -#define STM32_UART_USE_USART2 FALSE -#define STM32_UART_USE_USART3 FALSE -#define STM32_UART_USART1_IRQ_PRIORITY 12 -#define STM32_UART_USART2_IRQ_PRIORITY 12 -#define STM32_UART_USART3_IRQ_PRIORITY 12 -#define STM32_UART_USART1_DMA_PRIORITY 0 -#define STM32_UART_USART2_DMA_PRIORITY 0 -#define STM32_UART_USART3_DMA_PRIORITY 0 -#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") - -/* - * USB driver system settings. - */ -#define STM32_USB_USE_USB1 TRUE -#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE -#define STM32_USB_USB1_HP_IRQ_PRIORITY 13 -#define STM32_USB_USB1_LP_IRQ_PRIORITY 14 - -#endif /* _MCUCONF_H_ */ diff --git a/platforms/chibios/STM32_F103_STM32DUINO/ld/STM32F103x8_stm32duino_bootloader.ld b/platforms/chibios/STM32_F103_STM32DUINO/ld/STM32F103x8_stm32duino_bootloader.ld deleted file mode 100644 index a4bd566b59..0000000000 --- a/platforms/chibios/STM32_F103_STM32DUINO/ld/STM32F103x8_stm32duino_bootloader.ld +++ /dev/null @@ -1,22 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - 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 License 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. -*/ - -/* - * STM32F103x8 memory setup for use with the STM32Duino bootloader. - */ -f103_flash_size = 64k; - -INCLUDE stm32duino_bootloader_common.ld diff --git a/platforms/chibios/STM32_F103_STM32DUINO/ld/STM32F103xB_stm32duino_bootloader.ld b/platforms/chibios/STM32_F103_STM32DUINO/ld/STM32F103xB_stm32duino_bootloader.ld deleted file mode 100644 index dc47400dc5..0000000000 --- a/platforms/chibios/STM32_F103_STM32DUINO/ld/STM32F103xB_stm32duino_bootloader.ld +++ /dev/null @@ -1,22 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - 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 License 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. -*/ - -/* - * STM32F103xB memory setup for use with the STM32Duino bootloader. - */ -f103_flash_size = 128k; - -INCLUDE stm32duino_bootloader_common.ld diff --git a/platforms/chibios/STM32_F103_STM32DUINO/ld/stm32duino_bootloader_common.ld b/platforms/chibios/STM32_F103_STM32DUINO/ld/stm32duino_bootloader_common.ld deleted file mode 100644 index 76cd3153be..0000000000 --- a/platforms/chibios/STM32_F103_STM32DUINO/ld/stm32duino_bootloader_common.ld +++ /dev/null @@ -1,85 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - 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 License 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. -*/ - -/* - * STM32Duino bootloader common memory setup. - */ -MEMORY -{ - flash0 : org = 0x08002000, len = f103_flash_size - 0x2000 - flash1 : org = 0x00000000, len = 0 - flash2 : org = 0x00000000, len = 0 - flash3 : org = 0x00000000, len = 0 - flash4 : org = 0x00000000, len = 0 - flash5 : org = 0x00000000, len = 0 - flash6 : org = 0x00000000, len = 0 - flash7 : org = 0x00000000, len = 0 - ram0 : org = 0x20000000, len = 20k - ram1 : org = 0x00000000, len = 0 - ram2 : org = 0x00000000, len = 0 - ram3 : org = 0x00000000, len = 0 - ram4 : org = 0x00000000, len = 0 - ram5 : org = 0x00000000, len = 0 - ram6 : org = 0x00000000, len = 0 - ram7 : org = 0x00000000, len = 0 -} - -/* For each data/text section two region are defined, a virtual region - and a load region (_LMA suffix).*/ - -/* Flash region to be used for exception vectors.*/ -REGION_ALIAS("VECTORS_FLASH", flash0); -REGION_ALIAS("VECTORS_FLASH_LMA", flash0); - -/* Flash region to be used for constructors and destructors.*/ -REGION_ALIAS("XTORS_FLASH", flash0); -REGION_ALIAS("XTORS_FLASH_LMA", flash0); - -/* Flash region to be used for code text.*/ -REGION_ALIAS("TEXT_FLASH", flash0); -REGION_ALIAS("TEXT_FLASH_LMA", flash0); - -/* Flash region to be used for read only data.*/ -REGION_ALIAS("RODATA_FLASH", flash0); -REGION_ALIAS("RODATA_FLASH_LMA", flash0); - -/* Flash region to be used for various.*/ -REGION_ALIAS("VARIOUS_FLASH", flash0); -REGION_ALIAS("VARIOUS_FLASH_LMA", flash0); - -/* Flash region to be used for RAM(n) initialization data.*/ -REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0); - -/* RAM region to be used for Main stack. This stack accommodates the processing - of all exceptions and interrupts.*/ -REGION_ALIAS("MAIN_STACK_RAM", ram0); - -/* RAM region to be used for the process stack. This is the stack used by - the main() function.*/ -REGION_ALIAS("PROCESS_STACK_RAM", ram0); - -/* RAM region to be used for data segment.*/ -REGION_ALIAS("DATA_RAM", ram0); -REGION_ALIAS("DATA_RAM_LMA", flash0); - -/* RAM region to be used for BSS segment.*/ -REGION_ALIAS("BSS_RAM", ram0); - -/* RAM region to be used for the default heap.*/ -REGION_ALIAS("HEAP_RAM", ram0); - -/* Generic rules inclusion.*/ -INCLUDE rules.ld diff --git a/platforms/chibios/boards/BLACKPILL_STM32_F401/board/board.mk b/platforms/chibios/boards/BLACKPILL_STM32_F401/board/board.mk new file mode 100644 index 0000000000..fddf7dace4 --- /dev/null +++ b/platforms/chibios/boards/BLACKPILL_STM32_F401/board/board.mk @@ -0,0 +1,9 @@ +# List of all the board related files. +BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_STM32F401C_DISCOVERY/board.c + +# Required include directories +BOARDINC = $(CHIBIOS)/os/hal/boards/ST_STM32F401C_DISCOVERY + +# Shared variables +ALLCSRC += $(BOARDSRC) +ALLINC += $(BOARDINC) diff --git a/platforms/chibios/boards/BLACKPILL_STM32_F401/configs/board.h b/platforms/chibios/boards/BLACKPILL_STM32_F401/configs/board.h new file mode 100644 index 0000000000..30af6b0c86 --- /dev/null +++ b/platforms/chibios/boards/BLACKPILL_STM32_F401/configs/board.h @@ -0,0 +1,20 @@ +/* Copyright 2020 Nick Brassel (tzarc) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#include_next "board.h" + +#undef STM32_HSE_BYPASS diff --git a/platforms/chibios/boards/BLACKPILL_STM32_F401/configs/bootloader_defs.h b/platforms/chibios/boards/BLACKPILL_STM32_F401/configs/bootloader_defs.h new file mode 100644 index 0000000000..4da3d39a32 --- /dev/null +++ b/platforms/chibios/boards/BLACKPILL_STM32_F401/configs/bootloader_defs.h @@ -0,0 +1,5 @@ +/* Address for jumping to bootloader on STM32 chips. */ +/* It is chip dependent, the correct number can be looked up here: + * http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf + */ +#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000 diff --git a/platforms/chibios/boards/BLACKPILL_STM32_F401/configs/config.h b/platforms/chibios/boards/BLACKPILL_STM32_F401/configs/config.h new file mode 100644 index 0000000000..e181422eba --- /dev/null +++ b/platforms/chibios/boards/BLACKPILL_STM32_F401/configs/config.h @@ -0,0 +1,30 @@ +/* Copyright 2020 Nick Brassel (tzarc) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#define BOARD_OTG_NOVBUSSENS 1 + +#ifndef STM32_LSECLK +# define STM32_LSECLK 32768U +#endif // STM32_LSECLK + +#ifndef STM32_HSECLK +# define STM32_HSECLK 25000000U +#endif // STM32_HSECLK + +#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP +# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE +#endif diff --git a/platforms/chibios/boards/BLACKPILL_STM32_F401/configs/mcuconf.h b/platforms/chibios/boards/BLACKPILL_STM32_F401/configs/mcuconf.h new file mode 100644 index 0000000000..ba6e934fe7 --- /dev/null +++ b/platforms/chibios/boards/BLACKPILL_STM32_F401/configs/mcuconf.h @@ -0,0 +1,253 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + 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 License 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. +*/ + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F4xx_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_HSI_ENABLED TRUE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED FALSE +#define STM32_CLOCK48_REQUIRED TRUE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PLLM_VALUE 25 +#define STM32_PLLN_VALUE 336 +#define STM32_PLLP_VALUE 4 +#define STM32_PLLQ_VALUE 7 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV4 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_RTCSEL STM32_RTCSEL_LSI +#define STM32_RTCPRE_VALUE 8 +#define STM32_MCO1SEL STM32_MCO1SEL_HSI +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK +#define STM32_MCO2PRE STM32_MCO2PRE_DIV5 +#define STM32_I2SSRC STM32_I2SSRC_CKIN +#define STM32_PLLI2SN_VALUE 192 +#define STM32_PLLI2SR_VALUE 5 +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_BKPRAM_ENABLE FALSE + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_PRIORITY 15 +#define STM32_IRQ_EXTI22_PRIORITY 15 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 6 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM9 FALSE +#define STM32_GPT_USE_TIM11 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 FALSE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * I2S driver system settings. + */ +#define STM32_I2S_USE_SPI2 FALSE +#define STM32_I2S_USE_SPI3 FALSE +#define STM32_I2S_SPI2_IRQ_PRIORITY 10 +#define STM32_I2S_SPI3_IRQ_PRIORITY 10 +#define STM32_I2S_SPI2_DMA_PRIORITY 1 +#define STM32_I2S_SPI3_DMA_PRIORITY 1 +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM9 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED FALSE +#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 FALSE +#define STM32_PWM_USE_TIM4 FALSE +#define STM32_PWM_USE_TIM5 FALSE +#define STM32_PWM_USE_TIM9 FALSE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 FALSE +#define STM32_SERIAL_USE_USART6 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART6_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART6 FALSE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_OTG1 TRUE +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#define STM32_USB_OTG_THREAD_PRIO NORMALPRIO+1 +#define STM32_USB_OTG_THREAD_STACK_SIZE 128 +#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG FALSE + +#endif /* MCUCONF_H */ diff --git a/platforms/chibios/boards/BLACKPILL_STM32_F411/board/board.mk b/platforms/chibios/boards/BLACKPILL_STM32_F411/board/board.mk new file mode 100644 index 0000000000..bb00b1a2b0 --- /dev/null +++ b/platforms/chibios/boards/BLACKPILL_STM32_F411/board/board.mk @@ -0,0 +1,9 @@ +# List of all the board related files. +BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_F411RE/board.c + +# Required include directories +BOARDINC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_F411RE + +# Shared variables +ALLCSRC += $(BOARDSRC) +ALLINC += $(BOARDINC) diff --git a/platforms/chibios/boards/BLACKPILL_STM32_F411/configs/board.h b/platforms/chibios/boards/BLACKPILL_STM32_F411/configs/board.h new file mode 100644 index 0000000000..30af6b0c86 --- /dev/null +++ b/platforms/chibios/boards/BLACKPILL_STM32_F411/configs/board.h @@ -0,0 +1,20 @@ +/* Copyright 2020 Nick Brassel (tzarc) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#include_next "board.h" + +#undef STM32_HSE_BYPASS diff --git a/platforms/chibios/boards/BLACKPILL_STM32_F411/configs/bootloader_defs.h b/platforms/chibios/boards/BLACKPILL_STM32_F411/configs/bootloader_defs.h new file mode 100644 index 0000000000..4da3d39a32 --- /dev/null +++ b/platforms/chibios/boards/BLACKPILL_STM32_F411/configs/bootloader_defs.h @@ -0,0 +1,5 @@ +/* Address for jumping to bootloader on STM32 chips. */ +/* It is chip dependent, the correct number can be looked up here: + * http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf + */ +#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000 diff --git a/platforms/chibios/boards/BLACKPILL_STM32_F411/configs/config.h b/platforms/chibios/boards/BLACKPILL_STM32_F411/configs/config.h new file mode 100644 index 0000000000..e181422eba --- /dev/null +++ b/platforms/chibios/boards/BLACKPILL_STM32_F411/configs/config.h @@ -0,0 +1,30 @@ +/* Copyright 2020 Nick Brassel (tzarc) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#define BOARD_OTG_NOVBUSSENS 1 + +#ifndef STM32_LSECLK +# define STM32_LSECLK 32768U +#endif // STM32_LSECLK + +#ifndef STM32_HSECLK +# define STM32_HSECLK 25000000U +#endif // STM32_HSECLK + +#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP +# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE +#endif diff --git a/platforms/chibios/boards/BLACKPILL_STM32_F411/configs/mcuconf.h b/platforms/chibios/boards/BLACKPILL_STM32_F411/configs/mcuconf.h new file mode 100644 index 0000000000..0394ff56bb --- /dev/null +++ b/platforms/chibios/boards/BLACKPILL_STM32_F411/configs/mcuconf.h @@ -0,0 +1,253 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + 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 License 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. +*/ + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F4xx_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_HSI_ENABLED TRUE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED FALSE +#define STM32_CLOCK48_REQUIRED TRUE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PLLM_VALUE 25 +#define STM32_PLLN_VALUE 384 +#define STM32_PLLP_VALUE 4 +#define STM32_PLLQ_VALUE 8 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV4 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_RTCSEL STM32_RTCSEL_LSI +#define STM32_RTCPRE_VALUE 8 +#define STM32_MCO1SEL STM32_MCO1SEL_HSI +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK +#define STM32_MCO2PRE STM32_MCO2PRE_DIV5 +#define STM32_I2SSRC STM32_I2SSRC_CKIN +#define STM32_PLLI2SN_VALUE 192 +#define STM32_PLLI2SR_VALUE 5 +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_BKPRAM_ENABLE FALSE + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_PRIORITY 15 +#define STM32_IRQ_EXTI22_PRIORITY 15 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 6 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM9 FALSE +#define STM32_GPT_USE_TIM11 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 FALSE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * I2S driver system settings. + */ +#define STM32_I2S_USE_SPI2 FALSE +#define STM32_I2S_USE_SPI3 FALSE +#define STM32_I2S_SPI2_IRQ_PRIORITY 10 +#define STM32_I2S_SPI3_IRQ_PRIORITY 10 +#define STM32_I2S_SPI2_DMA_PRIORITY 1 +#define STM32_I2S_SPI3_DMA_PRIORITY 1 +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM9 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED FALSE +#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 FALSE +#define STM32_PWM_USE_TIM4 FALSE +#define STM32_PWM_USE_TIM5 FALSE +#define STM32_PWM_USE_TIM9 FALSE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 FALSE +#define STM32_SERIAL_USE_USART6 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART6_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART6 FALSE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_OTG1 TRUE +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#define STM32_USB_OTG_THREAD_PRIO NORMALPRIO+1 +#define STM32_USB_OTG_THREAD_STACK_SIZE 128 +#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG FALSE + +#endif /* MCUCONF_H */ diff --git a/platforms/chibios/boards/BLACKPILL_STM32_F411/ld/STM32F411xC_tinyuf2.ld b/platforms/chibios/boards/BLACKPILL_STM32_F411/ld/STM32F411xC_tinyuf2.ld new file mode 100644 index 0000000000..82253d3de5 --- /dev/null +++ b/platforms/chibios/boards/BLACKPILL_STM32_F411/ld/STM32F411xC_tinyuf2.ld @@ -0,0 +1,89 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + 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 License 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. +*/ + +/* + * STM32F411xC memory setup. + */ +MEMORY +{ + flash0 (rx) : org = 0x08000000 + 64k, len = 256k - 64k /* tinyuf2 bootloader requires app to be located at 64k offset for this MCU */ + flash1 (rx) : org = 0x00000000, len = 0 + flash2 (rx) : org = 0x00000000, len = 0 + flash3 (rx) : org = 0x00000000, len = 0 + flash4 (rx) : org = 0x00000000, len = 0 + flash5 (rx) : org = 0x00000000, len = 0 + flash6 (rx) : org = 0x00000000, len = 0 + flash7 (rx) : org = 0x00000000, len = 0 + ram0 (wx) : org = 0x20000000, len = 128k + ram1 (wx) : org = 0x00000000, len = 0 + ram2 (wx) : org = 0x00000000, len = 0 + ram3 (wx) : org = 0x00000000, len = 0 + ram4 (wx) : org = 0x00000000, len = 0 + ram5 (wx) : org = 0x00000000, len = 0 + ram6 (wx) : org = 0x00000000, len = 0 + ram7 (wx) : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash0); +REGION_ALIAS("VECTORS_FLASH_LMA", flash0); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash0); +REGION_ALIAS("XTORS_FLASH_LMA", flash0); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash0); +REGION_ALIAS("TEXT_FLASH_LMA", flash0); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash0); +REGION_ALIAS("RODATA_FLASH_LMA", flash0); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash0); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash0); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash0); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* Generic rules inclusion.*/ +INCLUDE rules.ld + +/* TinyUF2 bootloader reset support */ +_board_dfu_dbl_tap = ORIGIN(ram0) + 64k - 4; /* this is based off the linker file for tinyuf2 */ + diff --git a/platforms/chibios/boards/BLACKPILL_STM32_F411/ld/STM32F411xE_tinyuf2.ld b/platforms/chibios/boards/BLACKPILL_STM32_F411/ld/STM32F411xE_tinyuf2.ld new file mode 100644 index 0000000000..1656c67bf7 --- /dev/null +++ b/platforms/chibios/boards/BLACKPILL_STM32_F411/ld/STM32F411xE_tinyuf2.ld @@ -0,0 +1,89 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + 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 License 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. +*/ + +/* + * STM32F411xE memory setup. + */ +MEMORY +{ + flash0 (rx) : org = 0x08000000 + 64k, len = 512k - 64k /* tinyuf2 bootloader requires app to be located at 64k offset for this MCU */ + flash1 (rx) : org = 0x00000000, len = 0 + flash2 (rx) : org = 0x00000000, len = 0 + flash3 (rx) : org = 0x00000000, len = 0 + flash4 (rx) : org = 0x00000000, len = 0 + flash5 (rx) : org = 0x00000000, len = 0 + flash6 (rx) : org = 0x00000000, len = 0 + flash7 (rx) : org = 0x00000000, len = 0 + ram0 (wx) : org = 0x20000000, len = 128k + ram1 (wx) : org = 0x00000000, len = 0 + ram2 (wx) : org = 0x00000000, len = 0 + ram3 (wx) : org = 0x00000000, len = 0 + ram4 (wx) : org = 0x00000000, len = 0 + ram5 (wx) : org = 0x00000000, len = 0 + ram6 (wx) : org = 0x00000000, len = 0 + ram7 (wx) : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash0); +REGION_ALIAS("VECTORS_FLASH_LMA", flash0); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash0); +REGION_ALIAS("XTORS_FLASH_LMA", flash0); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash0); +REGION_ALIAS("TEXT_FLASH_LMA", flash0); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash0); +REGION_ALIAS("RODATA_FLASH_LMA", flash0); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash0); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash0); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash0); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* Generic rules inclusion.*/ +INCLUDE rules.ld + +/* TinyUF2 bootloader reset support */ +_board_dfu_dbl_tap = ORIGIN(ram0) + 64k - 4; /* this is based off the linker file for tinyuf2 */ + diff --git a/platforms/chibios/boards/GENERIC_STM32_F042X6/board/board.c b/platforms/chibios/boards/GENERIC_STM32_F042X6/board/board.c new file mode 100644 index 0000000000..0d7c88756a --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_F042X6/board/board.c @@ -0,0 +1,265 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + 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 License 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. +*/ + +/* + * This file has been automatically generated using ChibiStudio board + * generator plugin. Do not edit manually. + */ + +#include +#include + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** + * @brief Type of STM32 GPIO port setup. + */ +typedef struct { + uint32_t moder; + uint32_t otyper; + uint32_t ospeedr; + uint32_t pupdr; + uint32_t odr; + uint32_t afrl; + uint32_t afrh; +} gpio_setup_t; + +/** + * @brief Type of STM32 GPIO initialization data. + */ +typedef struct { +#if STM32_HAS_GPIOA || defined(__DOXYGEN__) + gpio_setup_t PAData; +#endif +#if STM32_HAS_GPIOB || defined(__DOXYGEN__) + gpio_setup_t PBData; +#endif +#if STM32_HAS_GPIOC || defined(__DOXYGEN__) + gpio_setup_t PCData; +#endif +#if STM32_HAS_GPIOD || defined(__DOXYGEN__) + gpio_setup_t PDData; +#endif +#if STM32_HAS_GPIOE || defined(__DOXYGEN__) + gpio_setup_t PEData; +#endif +#if STM32_HAS_GPIOF || defined(__DOXYGEN__) + gpio_setup_t PFData; +#endif +#if STM32_HAS_GPIOG || defined(__DOXYGEN__) + gpio_setup_t PGData; +#endif +#if STM32_HAS_GPIOH || defined(__DOXYGEN__) + gpio_setup_t PHData; +#endif +#if STM32_HAS_GPIOI || defined(__DOXYGEN__) + gpio_setup_t PIData; +#endif +#if STM32_HAS_GPIOJ || defined(__DOXYGEN__) + gpio_setup_t PJData; +#endif +#if STM32_HAS_GPIOK || defined(__DOXYGEN__) + gpio_setup_t PKData; +#endif +} gpio_config_t; + +/** + * @brief STM32 GPIO static initialization data. + */ +static const gpio_config_t gpio_default_config = { +#if STM32_HAS_GPIOA + {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR, + VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH}, +#endif +#if STM32_HAS_GPIOB + {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR, + VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH}, +#endif +#if STM32_HAS_GPIOC + {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR, + VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH}, +#endif +#if STM32_HAS_GPIOD + {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR, + VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH}, +#endif +#if STM32_HAS_GPIOE + {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR, + VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH}, +#endif +#if STM32_HAS_GPIOF + {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR, + VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH}, +#endif +#if STM32_HAS_GPIOG + {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR, + VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH}, +#endif +#if STM32_HAS_GPIOH + {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR, + VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH}, +#endif +#if STM32_HAS_GPIOI + {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR, + VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH}, +#endif +#if STM32_HAS_GPIOJ + {VAL_GPIOJ_MODER, VAL_GPIOJ_OTYPER, VAL_GPIOJ_OSPEEDR, VAL_GPIOJ_PUPDR, + VAL_GPIOJ_ODR, VAL_GPIOJ_AFRL, VAL_GPIOJ_AFRH}, +#endif +#if STM32_HAS_GPIOK + {VAL_GPIOK_MODER, VAL_GPIOK_OTYPER, VAL_GPIOK_OSPEEDR, VAL_GPIOK_PUPDR, + VAL_GPIOK_ODR, VAL_GPIOK_AFRL, VAL_GPIOK_AFRH} +#endif +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +static void gpio_init(stm32_gpio_t *gpiop, const gpio_setup_t *config) { + + gpiop->OTYPER = config->otyper; + gpiop->OSPEEDR = config->ospeedr; + gpiop->PUPDR = config->pupdr; + gpiop->ODR = config->odr; + gpiop->AFRL = config->afrl; + gpiop->AFRH = config->afrh; + gpiop->MODER = config->moder; +} + +static void stm32_gpio_init(void) { + + /* Enabling GPIO-related clocks, the mask comes from the + registry header file.*/ + rccResetAHB(STM32_GPIO_EN_MASK); + rccEnableAHB(STM32_GPIO_EN_MASK, true); + + /* Initializing all the defined GPIO ports.*/ +#if STM32_HAS_GPIOA + gpio_init(GPIOA, &gpio_default_config.PAData); +#endif +#if STM32_HAS_GPIOB + gpio_init(GPIOB, &gpio_default_config.PBData); +#endif +#if STM32_HAS_GPIOC + gpio_init(GPIOC, &gpio_default_config.PCData); +#endif +#if STM32_HAS_GPIOD + gpio_init(GPIOD, &gpio_default_config.PDData); +#endif +#if STM32_HAS_GPIOE + gpio_init(GPIOE, &gpio_default_config.PEData); +#endif +#if STM32_HAS_GPIOF + gpio_init(GPIOF, &gpio_default_config.PFData); +#endif +#if STM32_HAS_GPIOG + gpio_init(GPIOG, &gpio_default_config.PGData); +#endif +#if STM32_HAS_GPIOH + gpio_init(GPIOH, &gpio_default_config.PHData); +#endif +#if STM32_HAS_GPIOI + gpio_init(GPIOI, &gpio_default_config.PIData); +#endif +#if STM32_HAS_GPIOJ + gpio_init(GPIOJ, &gpio_default_config.PJData); +#endif +#if STM32_HAS_GPIOK + gpio_init(GPIOK, &gpio_default_config.PKData); +#endif +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Early initialization code. + * @details GPIO ports and system clocks are initialized before everything + * else. + */ +void __early_init(void) { + stm32_gpio_init(); + stm32_clock_init(); +} + +#if HAL_USE_SDC || defined(__DOXYGEN__) +/** + * @brief SDC card detection. + */ +bool sdc_lld_is_card_inserted(SDCDriver *sdcp) { + + (void)sdcp; + /* TODO: Fill the implementation.*/ + return true; +} + +/** + * @brief SDC card write protection detection. + */ +bool sdc_lld_is_write_protected(SDCDriver *sdcp) { + + (void)sdcp; + /* TODO: Fill the implementation.*/ + return false; +} +#endif /* HAL_USE_SDC */ + +#if HAL_USE_MMC_SPI || defined(__DOXYGEN__) +/** + * @brief MMC_SPI card detection. + */ +bool mmc_lld_is_card_inserted(MMCDriver *mmcp) { + + (void)mmcp; + /* TODO: Fill the implementation.*/ + return true; +} + +/** + * @brief MMC_SPI card write protection detection. + */ +bool mmc_lld_is_write_protected(MMCDriver *mmcp) { + + (void)mmcp; + /* TODO: Fill the implementation.*/ + return false; +} +#endif + +/** + * @brief Board-specific initialization code. + * @todo Add your board-specific code, if any. + */ +void boardInit(void) { + +} diff --git a/platforms/chibios/boards/GENERIC_STM32_F042X6/board/board.h b/platforms/chibios/boards/GENERIC_STM32_F042X6/board/board.h new file mode 100644 index 0000000000..ee9d31e04a --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_F042X6/board/board.h @@ -0,0 +1,896 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + 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 License 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. +*/ +#ifndef _BOARD_H +#define _BOARD_H + +/* + * Setup for STMicroelectronics STM32 Nucleo32-F042K6 board. + */ + +/* + * Board identifier. + */ +#define BOARD_GENERIC_STM32_F042X6 +#define BOARD_NAME "Generic STM32F042 PCB" + +/* + * Board oscillators-related settings. + * NOTE: LSE not fitted. + * NOTE: HSE not fitted. + */ +#if !defined(STM32_LSECLK) +#define STM32_LSECLK 0U +#endif + +#define STM32_LSEDRV (3U << 3U) + +#if !defined(STM32_HSECLK) +#define STM32_HSECLK 0U +#endif + +/* + * MCU type as defined in the ST header. + */ +#define STM32F042x6 + +/* + * IO pins assignments. + */ +#define GPIOA_PIN0 0U +#define GPIOA_PIN1 1U +#define GPIOA_PIN2 2U +#define GPIOA_PIN3 3U +#define GPIOA_PIN4 4U +#define GPIOA_PIN5 5U +#define GPIOA_PIN6 6U +#define GPIOA_PIN7 7U +#define GPIOA_PIN8 8U +#define GPIOA_PIN9 9U +#define GPIOA_PIN10 10U +#define GPIOA_PIN11 11U +#define GPIOA_PIN12 12U +#define GPIOA_PIN13 13U +#define GPIOA_PIN14 14U +#define GPIOA_PIN15 15U + +#define GPIOB_PIN0 0U +#define GPIOB_PIN1 1U +#define GPIOB_PIN2 2U +#define GPIOB_PIN3 3U +#define GPIOB_PIN4 4U +#define GPIOB_PIN5 5U +#define GPIOB_PIN6 6U +#define GPIOB_PIN7 7U +#define GPIOB_PIN8 8U +#define GPIOB_PIN9 9U +#define GPIOB_PIN10 10U +#define GPIOB_PIN11 11U +#define GPIOB_PIN12 12U +#define GPIOB_PIN13 13U +#define GPIOB_PIN14 14U +#define GPIOB_PIN15 15U + +#define GPIOC_PIN0 0U +#define GPIOC_PIN1 1U +#define GPIOC_PIN2 2U +#define GPIOC_PIN3 3U +#define GPIOC_PIN4 4U +#define GPIOC_PIN5 5U +#define GPIOC_PIN6 6U +#define GPIOC_PIN7 7U +#define GPIOC_PIN8 8U +#define GPIOC_PIN9 9U +#define GPIOC_PIN10 10U +#define GPIOC_PIN11 11U +#define GPIOC_PIN12 12U +#define GPIOC_PIN13 13U +#define GPIOC_PIN14 14U +#define GPIOC_PIN15 15U + +#define GPIOD_PIN0 0U +#define GPIOD_PIN1 1U +#define GPIOD_PIN2 2U +#define GPIOD_PIN3 3U +#define GPIOD_PIN4 4U +#define GPIOD_PIN5 5U +#define GPIOD_PIN6 6U +#define GPIOD_PIN7 7U +#define GPIOD_PIN8 8U +#define GPIOD_PIN9 9U +#define GPIOD_PIN10 10U +#define GPIOD_PIN11 11U +#define GPIOD_PIN12 12U +#define GPIOD_PIN13 13U +#define GPIOD_PIN14 14U +#define GPIOD_PIN15 15U + +#define GPIOE_PIN0 0U +#define GPIOE_PIN1 1U +#define GPIOE_PIN2 2U +#define GPIOE_PIN3 3U +#define GPIOE_PIN4 4U +#define GPIOE_PIN5 5U +#define GPIOE_PIN6 6U +#define GPIOE_PIN7 7U +#define GPIOE_PIN8 8U +#define GPIOE_PIN9 9U +#define GPIOE_PIN10 10U +#define GPIOE_PIN11 11U +#define GPIOE_PIN12 12U +#define GPIOE_PIN13 13U +#define GPIOE_PIN14 14U +#define GPIOE_PIN15 15U + +#define GPIOF_PIN0 0U +#define GPIOF_PIN1 1U +#define GPIOF_PIN2 2U +#define GPIOF_PIN3 3U +#define GPIOF_PIN4 4U +#define GPIOF_PIN5 5U +#define GPIOF_PIN6 6U +#define GPIOF_PIN7 7U +#define GPIOF_PIN8 8U +#define GPIOF_PIN9 9U +#define GPIOF_PIN10 10U +#define GPIOF_PIN11 11U +#define GPIOF_PIN12 12U +#define GPIOF_PIN13 13U +#define GPIOF_PIN14 14U +#define GPIOF_PIN15 15U + +/* + * IO lines assignments. + */ + +#define LINE_BOOT0 PAL_LINE(GPIOB, 8U) +#define LINE_SWCLK PAL_LINE(GPIOA, 14U) +#define LINE_SWDIO PAL_LINE(GPIOA, 13U) + +/* + * I/O ports initial setup, this configuration is established soon after reset + * in the initialization code. + * Please refer to the STM32 Reference Manual for details. + */ +#define PIN_MODE_INPUT(n) (0U << ((n) * 2U)) +#define PIN_MODE_OUTPUT(n) (1U << ((n) * 2U)) +#define PIN_MODE_ALTERNATE(n) (2U << ((n) * 2U)) +#define PIN_MODE_ANALOG(n) (3U << ((n) * 2U)) +#define PIN_ODR_LOW(n) (0U << (n)) +#define PIN_ODR_HIGH(n) (1U << (n)) +#define PIN_OTYPE_PUSHPULL(n) (0U << (n)) +#define PIN_OTYPE_OPENDRAIN(n) (1U << (n)) +#define PIN_OSPEED_VERYLOW(n) (0U << ((n) * 2U)) +#define PIN_OSPEED_LOW(n) (1U << ((n) * 2U)) +#define PIN_OSPEED_MEDIUM(n) (2U << ((n) * 2U)) +#define PIN_OSPEED_HIGH(n) (3U << ((n) * 2U)) +#define PIN_PUPDR_FLOATING(n) (0U << ((n) * 2U)) +#define PIN_PUPDR_PULLUP(n) (1U << ((n) * 2U)) +#define PIN_PUPDR_PULLDOWN(n) (2U << ((n) * 2U)) +#define PIN_AFIO_AF(n, v) ((v) << (((n) % 8U) * 4U)) + +/* + * GPIOA setup: + * + * PA0 - COL5 + * PA1 - COL4 + * PA2 - COL3 + * PA3 - COL2 + * PA4 - COL1 + * PA5 - COL0 + * PA6 - ROW4 + * PA7 - ROW3 + * PA8 - NC + * PA9 - ROW1 + * PA10 - ROW0 + * PA11 - USB_DM + * PA12 - USB_DP + * PA13 - COL15/SWDIO (for now, COL15) + * PA14 - COL14/SWCLK (for now, COL14) + * PA15 - COL13 + */ +#define VAL_GPIOA_MODER (PIN_MODE_INPUT(GPIOA_PIN0) | \ + PIN_MODE_INPUT(GPIOA_PIN1) | \ + PIN_MODE_INPUT(GPIOA_PIN2) | \ + PIN_MODE_INPUT(GPIOA_PIN3) | \ + PIN_MODE_INPUT(GPIOA_PIN4) | \ + PIN_MODE_INPUT(GPIOA_PIN5) | \ + PIN_MODE_INPUT(GPIOA_PIN6) | \ + PIN_MODE_INPUT(GPIOA_PIN7) | \ + PIN_MODE_INPUT(GPIOA_PIN8) | \ + PIN_MODE_INPUT(GPIOA_PIN9) | \ + PIN_MODE_INPUT(GPIOA_PIN10) | \ + PIN_MODE_INPUT(GPIOA_PIN11) | \ + PIN_MODE_INPUT(GPIOA_PIN12) | \ + PIN_MODE_INPUT(GPIOA_PIN13) | \ + PIN_MODE_INPUT(GPIOA_PIN14) | \ + PIN_MODE_INPUT(GPIOA_PIN15)) +#define VAL_GPIOA_OTYPER (PIN_OTYPE_PUSHPULL(GPIOA_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN15)) +#define VAL_GPIOA_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOA_PIN0) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN10) | \ + PIN_OSPEED_HIGH(GPIOA_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN15)) +#define VAL_GPIOA_PUPDR (PIN_PUPDR_PULLUP(GPIOA_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN10) | \ + PIN_PUPDR_FLOATING(GPIOA_PIN11) | \ + PIN_PUPDR_FLOATING(GPIOA_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN15)) +#define VAL_GPIOA_ODR (PIN_ODR_HIGH(GPIOA_PIN0) | \ + PIN_ODR_HIGH(GPIOA_PIN1) | \ + PIN_ODR_HIGH(GPIOA_PIN2) | \ + PIN_ODR_HIGH(GPIOA_PIN3) | \ + PIN_ODR_HIGH(GPIOA_PIN4) | \ + PIN_ODR_HIGH(GPIOA_PIN5) | \ + PIN_ODR_HIGH(GPIOA_PIN6) | \ + PIN_ODR_HIGH(GPIOA_PIN7) | \ + PIN_ODR_HIGH(GPIOA_PIN8) | \ + PIN_ODR_HIGH(GPIOA_PIN9) | \ + PIN_ODR_HIGH(GPIOA_PIN10) | \ + PIN_ODR_HIGH(GPIOA_PIN11) | \ + PIN_ODR_HIGH(GPIOA_PIN12) | \ + PIN_ODR_HIGH(GPIOA_PIN13) | \ + PIN_ODR_HIGH(GPIOA_PIN14) | \ + PIN_ODR_HIGH(GPIOA_PIN15)) +#define VAL_GPIOA_AFRL (PIN_AFIO_AF(GPIOA_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOA_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOA_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOA_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOA_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOA_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOA_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOA_PIN7, 0U)) +#define VAL_GPIOA_AFRH (PIN_AFIO_AF(GPIOA_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOA_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOA_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOA_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOA_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOA_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOA_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOA_PIN15, 0U)) + +/* + * GPIOB setup: + * + * PB0 - ROW2 + * PB1 - RGB_D + * PB2 - PIN2 (input pullup). + * PB3 - COL12 + * PB4 - COL11 + * PB5 - COL10 + * PB6 - COL9 + * PB7 - COL8 + * PB8 - BOOT0 (set as output for STM32F042) + * PB9 - PIN9 (input pullup). + * PB10 - PIN10 (input pullup). + * PB11 - PIN11 (input pullup). + * PB12 - PIN12 (input pullup). + * PB13 - PIN13 (input pullup). + * PB14 - PIN14 (input pullup). + * PB15 - PIN15 (input pullup). + */ +#define VAL_GPIOB_MODER (PIN_MODE_INPUT(GPIOB_PIN0) | \ + PIN_MODE_OUTPUT(GPIOB_PIN1) | \ + PIN_MODE_INPUT(GPIOB_PIN2) | \ + PIN_MODE_INPUT(GPIOB_PIN3) | \ + PIN_MODE_INPUT(GPIOB_PIN4) | \ + PIN_MODE_INPUT(GPIOB_PIN5) | \ + PIN_MODE_INPUT(GPIOB_PIN6) | \ + PIN_MODE_INPUT(GPIOB_PIN7) | \ + PIN_MODE_OUTPUT(GPIOB_PIN8) | \ + PIN_MODE_INPUT(GPIOB_PIN9) | \ + PIN_MODE_INPUT(GPIOB_PIN10) | \ + PIN_MODE_INPUT(GPIOB_PIN11) | \ + PIN_MODE_INPUT(GPIOB_PIN12) | \ + PIN_MODE_INPUT(GPIOB_PIN13) | \ + PIN_MODE_INPUT(GPIOB_PIN14) | \ + PIN_MODE_INPUT(GPIOB_PIN15)) +#define VAL_GPIOB_OTYPER (PIN_OTYPE_PUSHPULL(GPIOB_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN15)) +#define VAL_GPIOB_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOB_PIN0) | \ + PIN_OSPEED_HIGH(GPIOB_PIN1) | \ + PIN_OSPEED_HIGH(GPIOB_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN8) | \ + PIN_OSPEED_HIGH(GPIOB_PIN9) | \ + PIN_OSPEED_HIGH(GPIOB_PIN10) | \ + PIN_OSPEED_HIGH(GPIOB_PIN11) | \ + PIN_OSPEED_HIGH(GPIOB_PIN12) | \ + PIN_OSPEED_HIGH(GPIOB_PIN13) | \ + PIN_OSPEED_HIGH(GPIOB_PIN14) | \ + PIN_OSPEED_HIGH(GPIOB_PIN15)) +#define VAL_GPIOB_PUPDR (PIN_PUPDR_PULLUP(GPIOB_PIN0) | \ + PIN_PUPDR_FLOATING(GPIOB_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN7) | \ + PIN_PUPDR_PULLDOWN(GPIOB_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN15)) +#define VAL_GPIOB_ODR (PIN_ODR_HIGH(GPIOB_PIN0) | \ + PIN_ODR_HIGH(GPIOB_PIN1) | \ + PIN_ODR_HIGH(GPIOB_PIN2) | \ + PIN_ODR_HIGH(GPIOB_PIN3) | \ + PIN_ODR_HIGH(GPIOB_PIN4) | \ + PIN_ODR_HIGH(GPIOB_PIN5) | \ + PIN_ODR_HIGH(GPIOB_PIN6) | \ + PIN_ODR_HIGH(GPIOB_PIN7) | \ + PIN_ODR_HIGH(GPIOB_PIN8) | \ + PIN_ODR_HIGH(GPIOB_PIN9) | \ + PIN_ODR_HIGH(GPIOB_PIN10) | \ + PIN_ODR_HIGH(GPIOB_PIN11) | \ + PIN_ODR_HIGH(GPIOB_PIN12) | \ + PIN_ODR_HIGH(GPIOB_PIN13) | \ + PIN_ODR_HIGH(GPIOB_PIN14) | \ + PIN_ODR_HIGH(GPIOB_PIN15)) +#define VAL_GPIOB_AFRL (PIN_AFIO_AF(GPIOB_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN7, 0U)) +#define VAL_GPIOB_AFRH (PIN_AFIO_AF(GPIOB_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOB_PIN15, 0U)) + +/* + * GPIOC setup: + * + * PC0 - PIN0 (input pullup). + * PC1 - PIN1 (input pullup). + * PC2 - PIN2 (input pullup). + * PC3 - PIN3 (input pullup). + * PC4 - PIN4 (input pullup). + * PC5 - PIN5 (input pullup). + * PC6 - PIN6 (input pullup). + * PC7 - PIN7 (input pullup). + * PC8 - PIN8 (input pullup). + * PC9 - PIN9 (input pullup). + * PC10 - PIN10 (input pullup). + * PC11 - PIN11 (input pullup). + * PC12 - PIN12 (input pullup). + * PC13 - PIN13 (input pullup). + * PC14 - PIN14 (input pullup). + * PC15 - PIN15 (input pullup). + */ +#define VAL_GPIOC_MODER (PIN_MODE_INPUT(GPIOC_PIN0) | \ + PIN_MODE_INPUT(GPIOC_PIN1) | \ + PIN_MODE_INPUT(GPIOC_PIN2) | \ + PIN_MODE_INPUT(GPIOC_PIN3) | \ + PIN_MODE_INPUT(GPIOC_PIN4) | \ + PIN_MODE_INPUT(GPIOC_PIN5) | \ + PIN_MODE_INPUT(GPIOC_PIN6) | \ + PIN_MODE_INPUT(GPIOC_PIN7) | \ + PIN_MODE_INPUT(GPIOC_PIN8) | \ + PIN_MODE_INPUT(GPIOC_PIN9) | \ + PIN_MODE_INPUT(GPIOC_PIN10) | \ + PIN_MODE_INPUT(GPIOC_PIN11) | \ + PIN_MODE_INPUT(GPIOC_PIN12) | \ + PIN_MODE_INPUT(GPIOC_PIN13) | \ + PIN_MODE_INPUT(GPIOC_PIN14) | \ + PIN_MODE_INPUT(GPIOC_PIN15)) +#define VAL_GPIOC_OTYPER (PIN_OTYPE_PUSHPULL(GPIOC_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN15)) +#define VAL_GPIOC_OSPEEDR (PIN_OSPEED_HIGH(GPIOC_PIN0) | \ + PIN_OSPEED_HIGH(GPIOC_PIN1) | \ + PIN_OSPEED_HIGH(GPIOC_PIN2) | \ + PIN_OSPEED_HIGH(GPIOC_PIN3) | \ + PIN_OSPEED_HIGH(GPIOC_PIN4) | \ + PIN_OSPEED_HIGH(GPIOC_PIN5) | \ + PIN_OSPEED_HIGH(GPIOC_PIN6) | \ + PIN_OSPEED_HIGH(GPIOC_PIN7) | \ + PIN_OSPEED_HIGH(GPIOC_PIN8) | \ + PIN_OSPEED_HIGH(GPIOC_PIN9) | \ + PIN_OSPEED_HIGH(GPIOC_PIN10) | \ + PIN_OSPEED_HIGH(GPIOC_PIN11) | \ + PIN_OSPEED_HIGH(GPIOC_PIN12) | \ + PIN_OSPEED_HIGH(GPIOC_PIN13) | \ + PIN_OSPEED_HIGH(GPIOC_PIN14) | \ + PIN_OSPEED_HIGH(GPIOC_PIN15)) +#define VAL_GPIOC_PUPDR (PIN_PUPDR_PULLUP(GPIOC_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN15)) +#define VAL_GPIOC_ODR (PIN_ODR_HIGH(GPIOC_PIN0) | \ + PIN_ODR_HIGH(GPIOC_PIN1) | \ + PIN_ODR_HIGH(GPIOC_PIN2) | \ + PIN_ODR_HIGH(GPIOC_PIN3) | \ + PIN_ODR_HIGH(GPIOC_PIN4) | \ + PIN_ODR_HIGH(GPIOC_PIN5) | \ + PIN_ODR_HIGH(GPIOC_PIN6) | \ + PIN_ODR_HIGH(GPIOC_PIN7) | \ + PIN_ODR_HIGH(GPIOC_PIN8) | \ + PIN_ODR_HIGH(GPIOC_PIN9) | \ + PIN_ODR_HIGH(GPIOC_PIN10) | \ + PIN_ODR_HIGH(GPIOC_PIN11) | \ + PIN_ODR_HIGH(GPIOC_PIN12) | \ + PIN_ODR_HIGH(GPIOC_PIN13) | \ + PIN_ODR_HIGH(GPIOC_PIN14) | \ + PIN_ODR_HIGH(GPIOC_PIN15)) +#define VAL_GPIOC_AFRL (PIN_AFIO_AF(GPIOC_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN7, 0U)) +#define VAL_GPIOC_AFRH (PIN_AFIO_AF(GPIOC_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOC_PIN15, 0U)) + +/* + * GPIOD setup: + * + * PD0 - PIN0 (input pullup). + * PD1 - PIN1 (input pullup). + * PD2 - PIN2 (input pullup). + * PD3 - PIN3 (input pullup). + * PD4 - PIN4 (input pullup). + * PD5 - PIN5 (input pullup). + * PD6 - PIN6 (input pullup). + * PD7 - PIN7 (input pullup). + * PD8 - PIN8 (input pullup). + * PD9 - PIN9 (input pullup). + * PD10 - PIN10 (input pullup). + * PD11 - PIN11 (input pullup). + * PD12 - PIN12 (input pullup). + * PD13 - PIN13 (input pullup). + * PD14 - PIN14 (input pullup). + * PD15 - PIN15 (input pullup). + */ +#define VAL_GPIOD_MODER (PIN_MODE_INPUT(GPIOD_PIN0) | \ + PIN_MODE_INPUT(GPIOD_PIN1) | \ + PIN_MODE_INPUT(GPIOD_PIN2) | \ + PIN_MODE_INPUT(GPIOD_PIN3) | \ + PIN_MODE_INPUT(GPIOD_PIN4) | \ + PIN_MODE_INPUT(GPIOD_PIN5) | \ + PIN_MODE_INPUT(GPIOD_PIN6) | \ + PIN_MODE_INPUT(GPIOD_PIN7) | \ + PIN_MODE_INPUT(GPIOD_PIN8) | \ + PIN_MODE_INPUT(GPIOD_PIN9) | \ + PIN_MODE_INPUT(GPIOD_PIN10) | \ + PIN_MODE_INPUT(GPIOD_PIN11) | \ + PIN_MODE_INPUT(GPIOD_PIN12) | \ + PIN_MODE_INPUT(GPIOD_PIN13) | \ + PIN_MODE_INPUT(GPIOD_PIN14) | \ + PIN_MODE_INPUT(GPIOD_PIN15)) +#define VAL_GPIOD_OTYPER (PIN_OTYPE_PUSHPULL(GPIOD_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN15)) +#define VAL_GPIOD_OSPEEDR (PIN_OSPEED_HIGH(GPIOD_PIN0) | \ + PIN_OSPEED_HIGH(GPIOD_PIN1) | \ + PIN_OSPEED_HIGH(GPIOD_PIN2) | \ + PIN_OSPEED_HIGH(GPIOD_PIN3) | \ + PIN_OSPEED_HIGH(GPIOD_PIN4) | \ + PIN_OSPEED_HIGH(GPIOD_PIN5) | \ + PIN_OSPEED_HIGH(GPIOD_PIN6) | \ + PIN_OSPEED_HIGH(GPIOD_PIN7) | \ + PIN_OSPEED_HIGH(GPIOD_PIN8) | \ + PIN_OSPEED_HIGH(GPIOD_PIN9) | \ + PIN_OSPEED_HIGH(GPIOD_PIN10) | \ + PIN_OSPEED_HIGH(GPIOD_PIN11) | \ + PIN_OSPEED_HIGH(GPIOD_PIN12) | \ + PIN_OSPEED_HIGH(GPIOD_PIN13) | \ + PIN_OSPEED_HIGH(GPIOD_PIN14) | \ + PIN_OSPEED_HIGH(GPIOD_PIN15)) +#define VAL_GPIOD_PUPDR (PIN_PUPDR_PULLUP(GPIOD_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN15)) +#define VAL_GPIOD_ODR (PIN_ODR_HIGH(GPIOD_PIN0) | \ + PIN_ODR_HIGH(GPIOD_PIN1) | \ + PIN_ODR_HIGH(GPIOD_PIN2) | \ + PIN_ODR_HIGH(GPIOD_PIN3) | \ + PIN_ODR_HIGH(GPIOD_PIN4) | \ + PIN_ODR_HIGH(GPIOD_PIN5) | \ + PIN_ODR_HIGH(GPIOD_PIN6) | \ + PIN_ODR_HIGH(GPIOD_PIN7) | \ + PIN_ODR_HIGH(GPIOD_PIN8) | \ + PIN_ODR_HIGH(GPIOD_PIN9) | \ + PIN_ODR_HIGH(GPIOD_PIN10) | \ + PIN_ODR_HIGH(GPIOD_PIN11) | \ + PIN_ODR_HIGH(GPIOD_PIN12) | \ + PIN_ODR_HIGH(GPIOD_PIN13) | \ + PIN_ODR_HIGH(GPIOD_PIN14) | \ + PIN_ODR_HIGH(GPIOD_PIN15)) +#define VAL_GPIOD_AFRL (PIN_AFIO_AF(GPIOD_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN7, 0U)) +#define VAL_GPIOD_AFRH (PIN_AFIO_AF(GPIOD_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOD_PIN15, 0U)) + +/* + * GPIOE setup: + * + * PE0 - PIN0 (input pullup). + * PE1 - PIN1 (input pullup). + * PE2 - PIN2 (input pullup). + * PE3 - PIN3 (input pullup). + * PE4 - PIN4 (input pullup). + * PE5 - PIN5 (input pullup). + * PE6 - PIN6 (input pullup). + * PE7 - PIN7 (input pullup). + * PE8 - PIN8 (input pullup). + * PE9 - PIN9 (input pullup). + * PE10 - PIN10 (input pullup). + * PE11 - PIN11 (input pullup). + * PE12 - PIN12 (input pullup). + * PE13 - PIN13 (input pullup). + * PE14 - PIN14 (input pullup). + * PE15 - PIN15 (input pullup). + */ +#define VAL_GPIOE_MODER (PIN_MODE_INPUT(GPIOE_PIN0) | \ + PIN_MODE_INPUT(GPIOE_PIN1) | \ + PIN_MODE_INPUT(GPIOE_PIN2) | \ + PIN_MODE_INPUT(GPIOE_PIN3) | \ + PIN_MODE_INPUT(GPIOE_PIN4) | \ + PIN_MODE_INPUT(GPIOE_PIN5) | \ + PIN_MODE_INPUT(GPIOE_PIN6) | \ + PIN_MODE_INPUT(GPIOE_PIN7) | \ + PIN_MODE_INPUT(GPIOE_PIN8) | \ + PIN_MODE_INPUT(GPIOE_PIN9) | \ + PIN_MODE_INPUT(GPIOE_PIN10) | \ + PIN_MODE_INPUT(GPIOE_PIN11) | \ + PIN_MODE_INPUT(GPIOE_PIN12) | \ + PIN_MODE_INPUT(GPIOE_PIN13) | \ + PIN_MODE_INPUT(GPIOE_PIN14) | \ + PIN_MODE_INPUT(GPIOE_PIN15)) +#define VAL_GPIOE_OTYPER (PIN_OTYPE_PUSHPULL(GPIOE_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN15)) +#define VAL_GPIOE_OSPEEDR (PIN_OSPEED_HIGH(GPIOE_PIN0) | \ + PIN_OSPEED_HIGH(GPIOE_PIN1) | \ + PIN_OSPEED_HIGH(GPIOE_PIN2) | \ + PIN_OSPEED_HIGH(GPIOE_PIN3) | \ + PIN_OSPEED_HIGH(GPIOE_PIN4) | \ + PIN_OSPEED_HIGH(GPIOE_PIN5) | \ + PIN_OSPEED_HIGH(GPIOE_PIN6) | \ + PIN_OSPEED_HIGH(GPIOE_PIN7) | \ + PIN_OSPEED_HIGH(GPIOE_PIN8) | \ + PIN_OSPEED_HIGH(GPIOE_PIN9) | \ + PIN_OSPEED_HIGH(GPIOE_PIN10) | \ + PIN_OSPEED_HIGH(GPIOE_PIN11) | \ + PIN_OSPEED_HIGH(GPIOE_PIN12) | \ + PIN_OSPEED_HIGH(GPIOE_PIN13) | \ + PIN_OSPEED_HIGH(GPIOE_PIN14) | \ + PIN_OSPEED_HIGH(GPIOE_PIN15)) +#define VAL_GPIOE_PUPDR (PIN_PUPDR_PULLUP(GPIOE_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN15)) +#define VAL_GPIOE_ODR (PIN_ODR_HIGH(GPIOE_PIN0) | \ + PIN_ODR_HIGH(GPIOE_PIN1) | \ + PIN_ODR_HIGH(GPIOE_PIN2) | \ + PIN_ODR_HIGH(GPIOE_PIN3) | \ + PIN_ODR_HIGH(GPIOE_PIN4) | \ + PIN_ODR_HIGH(GPIOE_PIN5) | \ + PIN_ODR_HIGH(GPIOE_PIN6) | \ + PIN_ODR_HIGH(GPIOE_PIN7) | \ + PIN_ODR_HIGH(GPIOE_PIN8) | \ + PIN_ODR_HIGH(GPIOE_PIN9) | \ + PIN_ODR_HIGH(GPIOE_PIN10) | \ + PIN_ODR_HIGH(GPIOE_PIN11) | \ + PIN_ODR_HIGH(GPIOE_PIN12) | \ + PIN_ODR_HIGH(GPIOE_PIN13) | \ + PIN_ODR_HIGH(GPIOE_PIN14) | \ + PIN_ODR_HIGH(GPIOE_PIN15)) +#define VAL_GPIOE_AFRL (PIN_AFIO_AF(GPIOE_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN7, 0U)) +#define VAL_GPIOE_AFRH (PIN_AFIO_AF(GPIOE_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOE_PIN15, 0U)) + +/* + * GPIOF setup: + * + * PF0 - COL7 + * PF1 - COL6 + * PF2 - PIN2 (input pullup). + * PF3 - PIN3 (input pullup). + * PF4 - PIN4 (input pullup). + * PF5 - PIN5 (input pullup). + * PF6 - PIN6 (input pullup). + * PF7 - PIN7 (input pullup). + * PF8 - PIN8 (input pullup). + * PF9 - PIN9 (input pullup). + * PF10 - PIN10 (input pullup). + * PF11 - PIN11 (input pullup). + * PF12 - PIN12 (input pullup). + * PF13 - PIN13 (input pullup). + * PF14 - PIN14 (input pullup). + * PF15 - PIN15 (input pullup). + */ +#define VAL_GPIOF_MODER (PIN_MODE_INPUT(GPIOF_PIN0) | \ + PIN_MODE_INPUT(GPIOF_PIN1) | \ + PIN_MODE_INPUT(GPIOF_PIN2) | \ + PIN_MODE_INPUT(GPIOF_PIN3) | \ + PIN_MODE_INPUT(GPIOF_PIN4) | \ + PIN_MODE_INPUT(GPIOF_PIN5) | \ + PIN_MODE_INPUT(GPIOF_PIN6) | \ + PIN_MODE_INPUT(GPIOF_PIN7) | \ + PIN_MODE_INPUT(GPIOF_PIN8) | \ + PIN_MODE_INPUT(GPIOF_PIN9) | \ + PIN_MODE_INPUT(GPIOF_PIN10) | \ + PIN_MODE_INPUT(GPIOF_PIN11) | \ + PIN_MODE_INPUT(GPIOF_PIN12) | \ + PIN_MODE_INPUT(GPIOF_PIN13) | \ + PIN_MODE_INPUT(GPIOF_PIN14) | \ + PIN_MODE_INPUT(GPIOF_PIN15)) +#define VAL_GPIOF_OTYPER (PIN_OTYPE_PUSHPULL(GPIOF_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN15)) +#define VAL_GPIOF_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOF_PIN0) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN1) | \ + PIN_OSPEED_HIGH(GPIOF_PIN2) | \ + PIN_OSPEED_HIGH(GPIOF_PIN3) | \ + PIN_OSPEED_HIGH(GPIOF_PIN4) | \ + PIN_OSPEED_HIGH(GPIOF_PIN5) | \ + PIN_OSPEED_HIGH(GPIOF_PIN6) | \ + PIN_OSPEED_HIGH(GPIOF_PIN7) | \ + PIN_OSPEED_HIGH(GPIOF_PIN8) | \ + PIN_OSPEED_HIGH(GPIOF_PIN9) | \ + PIN_OSPEED_HIGH(GPIOF_PIN10) | \ + PIN_OSPEED_HIGH(GPIOF_PIN11) | \ + PIN_OSPEED_HIGH(GPIOF_PIN12) | \ + PIN_OSPEED_HIGH(GPIOF_PIN13) | \ + PIN_OSPEED_HIGH(GPIOF_PIN14) | \ + PIN_OSPEED_HIGH(GPIOF_PIN15)) +#define VAL_GPIOF_PUPDR (PIN_PUPDR_PULLUP(GPIOF_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN15)) +#define VAL_GPIOF_ODR (PIN_ODR_HIGH(GPIOF_PIN0) | \ + PIN_ODR_HIGH(GPIOF_PIN1) | \ + PIN_ODR_HIGH(GPIOF_PIN2) | \ + PIN_ODR_HIGH(GPIOF_PIN3) | \ + PIN_ODR_HIGH(GPIOF_PIN4) | \ + PIN_ODR_HIGH(GPIOF_PIN5) | \ + PIN_ODR_HIGH(GPIOF_PIN6) | \ + PIN_ODR_HIGH(GPIOF_PIN7) | \ + PIN_ODR_HIGH(GPIOF_PIN8) | \ + PIN_ODR_HIGH(GPIOF_PIN9) | \ + PIN_ODR_HIGH(GPIOF_PIN10) | \ + PIN_ODR_HIGH(GPIOF_PIN11) | \ + PIN_ODR_HIGH(GPIOF_PIN12) | \ + PIN_ODR_HIGH(GPIOF_PIN13) | \ + PIN_ODR_HIGH(GPIOF_PIN14) | \ + PIN_ODR_HIGH(GPIOF_PIN15)) +#define VAL_GPIOF_AFRL (PIN_AFIO_AF(GPIOF_PIN0, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN1, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN2, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN3, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN4, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN5, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN6, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN7, 0U)) +#define VAL_GPIOF_AFRH (PIN_AFIO_AF(GPIOF_PIN8, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN9, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN10, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN11, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN12, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN13, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN14, 0U) | \ + PIN_AFIO_AF(GPIOF_PIN15, 0U)) + +#if !defined(_FROM_ASM_) +#ifdef __cplusplus +extern "C" { +#endif + void boardInit(void); +#ifdef __cplusplus +} +#endif +#endif /* _FROM_ASM_ */ + +#endif /* _BOARD_H */ diff --git a/platforms/chibios/boards/GENERIC_STM32_F042X6/board/board.mk b/platforms/chibios/boards/GENERIC_STM32_F042X6/board/board.mk new file mode 100644 index 0000000000..842e335905 --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_F042X6/board/board.mk @@ -0,0 +1,9 @@ +# List of all the board related files. +BOARDSRC = $(BOARD_PATH)/board/board.c + +# Required include directories +BOARDINC = $(BOARD_PATH)/board + +# Shared variables +ALLCSRC += $(BOARDSRC) +ALLINC += $(BOARDINC) diff --git a/platforms/chibios/boards/GENERIC_STM32_F042X6/configs/bootloader_defs.h b/platforms/chibios/boards/GENERIC_STM32_F042X6/configs/bootloader_defs.h new file mode 100644 index 0000000000..25113425a6 --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_F042X6/configs/bootloader_defs.h @@ -0,0 +1,5 @@ +/* Address for jumping to bootloader on STM32 chips. */ +/* It is chip dependent, the correct number can be looked up here: + * http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf + */ +#define STM32_BOOTLOADER_ADDRESS 0x1FFFC400 diff --git a/platforms/chibios/boards/GENERIC_STM32_F042X6/configs/config.h b/platforms/chibios/boards/GENERIC_STM32_F042X6/configs/config.h new file mode 100644 index 0000000000..a73f0c0b47 --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_F042X6/configs/config.h @@ -0,0 +1,20 @@ +/* Copyright 2020 Nick Brassel (tzarc) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP +# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE +#endif diff --git a/platforms/chibios/boards/GENERIC_STM32_F042X6/configs/mcuconf.h b/platforms/chibios/boards/GENERIC_STM32_F042X6/configs/mcuconf.h new file mode 100644 index 0000000000..286e1230ce --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_F042X6/configs/mcuconf.h @@ -0,0 +1,168 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio + 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 License 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. +*/ + +#ifndef _MCUCONF_H_ +#define _MCUCONF_H_ + +/* + * STM32F0xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 3...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F0xx_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_HSI_ENABLED TRUE +#define STM32_HSI14_ENABLED TRUE +#define STM32_HSI48_ENABLED FALSE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED FALSE +#define STM32_LSE_ENABLED FALSE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSI_DIV2 +#define STM32_PREDIV_VALUE 1 +#define STM32_PLLMUL_VALUE 12 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE STM32_PPRE_DIV1 +#define STM32_ADCSW STM32_ADCSW_HSI14 +#define STM32_ADCPRE STM32_ADCPRE_DIV4 +#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK +#define STM32_ADCPRE STM32_ADCPRE_DIV4 +#define STM32_ADCSW STM32_ADCSW_HSI14 +#define STM32_USBSW STM32_USBSW_HSI48 +#define STM32_CECSW STM32_CECSW_HSI +#define STM32_I2C1SW STM32_I2C1SW_HSI +#define STM32_USART1SW STM32_USART1SW_PCLK +#define STM32_RTCSEL STM32_RTCSEL_LSI + +/* + * ADC driver system settings. + */ +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 2 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 2 + +/* + * EXT driver system settings. + */ +#define STM32_EXT_EXTI0_1_IRQ_PRIORITY 3 +#define STM32_EXT_EXTI2_3_IRQ_PRIORITY 3 +#define STM32_EXT_EXTI4_15_IRQ_PRIORITY 3 +#define STM32_EXT_EXTI16_IRQ_PRIORITY 3 +#define STM32_EXT_EXTI17_IRQ_PRIORITY 3 + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 2 +#define STM32_GPT_TIM2_IRQ_PRIORITY 2 +#define STM32_GPT_TIM3_IRQ_PRIORITY 2 +#define STM32_GPT_TIM14_IRQ_PRIORITY 2 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 FALSE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_IRQ_PRIORITY 3 +#define STM32_I2C_I2C2_IRQ_PRIORITY 3 +#define STM32_I2C_USE_DMA TRUE +#define STM32_I2C_I2C1_DMA_PRIORITY 1 +#define STM32_I2C_I2C2_DMA_PRIORITY 1 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 3 +#define STM32_ICU_TIM2_IRQ_PRIORITY 3 +#define STM32_ICU_TIM3_IRQ_PRIORITY 3 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED FALSE +#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 FALSE +#define STM32_PWM_TIM1_IRQ_PRIORITY 3 +#define STM32_PWM_TIM2_IRQ_PRIORITY 3 +#define STM32_PWM_TIM3_IRQ_PRIORITY 3 + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 FALSE +#define STM32_SERIAL_USART1_PRIORITY 3 +#define STM32_SERIAL_USART2_PRIORITY 3 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 2 +#define STM32_SPI_SPI2_IRQ_PRIORITY 2 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 2 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USART1_IRQ_PRIORITY 3 +#define STM32_UART_USART2_IRQ_PRIORITY 3 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_USB1 TRUE +#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE +#define STM32_USB_USB1_LP_IRQ_PRIORITY 3 + +#endif /* _MCUCONF_H_ */ diff --git a/platforms/chibios/boards/GENERIC_STM32_F072XB/board/board.mk b/platforms/chibios/boards/GENERIC_STM32_F072XB/board/board.mk new file mode 100644 index 0000000000..3f0e6c46e8 --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_F072XB/board/board.mk @@ -0,0 +1,9 @@ +# List of all the board related files. +BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_F072RB/board.c + +# Required include directories +BOARDINC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_F072RB + +# Shared variables +ALLCSRC += $(BOARDSRC) +ALLINC += $(BOARDINC) diff --git a/platforms/chibios/boards/GENERIC_STM32_F072XB/configs/board.h b/platforms/chibios/boards/GENERIC_STM32_F072XB/configs/board.h new file mode 100644 index 0000000000..30af6b0c86 --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_F072XB/configs/board.h @@ -0,0 +1,20 @@ +/* Copyright 2020 Nick Brassel (tzarc) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#include_next "board.h" + +#undef STM32_HSE_BYPASS diff --git a/platforms/chibios/boards/GENERIC_STM32_F072XB/configs/bootloader_defs.h b/platforms/chibios/boards/GENERIC_STM32_F072XB/configs/bootloader_defs.h new file mode 100644 index 0000000000..dccd0fa5d1 --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_F072XB/configs/bootloader_defs.h @@ -0,0 +1,5 @@ +/* Address for jumping to bootloader on STM32 chips. */ +/* It is chip dependent, the correct number can be looked up here (page 175): + * http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf + */ +#define STM32_BOOTLOADER_ADDRESS 0x1FFFC800 diff --git a/platforms/chibios/boards/GENERIC_STM32_F072XB/configs/config.h b/platforms/chibios/boards/GENERIC_STM32_F072XB/configs/config.h new file mode 100644 index 0000000000..a73f0c0b47 --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_F072XB/configs/config.h @@ -0,0 +1,20 @@ +/* Copyright 2020 Nick Brassel (tzarc) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP +# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE +#endif diff --git a/platforms/chibios/boards/GENERIC_STM32_F072XB/configs/mcuconf.h b/platforms/chibios/boards/GENERIC_STM32_F072XB/configs/mcuconf.h new file mode 100644 index 0000000000..32b2777a81 --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_F072XB/configs/mcuconf.h @@ -0,0 +1,179 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio + + 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 License 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. +*/ + +#ifndef _MCUCONF_H_ +#define _MCUCONF_H_ + +/* + * STM32F0xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 3...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F0xx_MCUCONF +// #define STM32F070xB + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_HSI_ENABLED TRUE +#define STM32_HSI14_ENABLED TRUE +#define STM32_HSI48_ENABLED FALSE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED FALSE +#define STM32_LSE_ENABLED FALSE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSI_DIV2 +#define STM32_PREDIV_VALUE 1 +#define STM32_PLLMUL_VALUE 12 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE STM32_PPRE_DIV1 +#define STM32_ADCSW STM32_ADCSW_HSI14 +#define STM32_ADCPRE STM32_ADCPRE_DIV4 +#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK +#define STM32_ADCPRE STM32_ADCPRE_DIV4 +#define STM32_ADCSW STM32_ADCSW_HSI14 +#define STM32_USBSW STM32_USBSW_HSI48 +#define STM32_CECSW STM32_CECSW_HSI +#define STM32_I2C1SW STM32_I2C1SW_HSI +#define STM32_USART1SW STM32_USART1SW_PCLK +#define STM32_RTCSEL STM32_RTCSEL_LSI + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_1_IRQ_PRIORITY 3 +#define STM32_IRQ_EXTI2_3_IRQ_PRIORITY 3 +#define STM32_IRQ_EXTI4_15_IRQ_PRIORITY 3 +#define STM32_IRQ_EXTI16_IRQ_PRIORITY 3 +#define STM32_IRQ_EXTI17_20_IRQ_PRIORITY 3 +#define STM32_IRQ_EXTI21_22_IRQ_PRIORITY 3 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 2 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 2 + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 2 +#define STM32_GPT_TIM2_IRQ_PRIORITY 2 +#define STM32_GPT_TIM3_IRQ_PRIORITY 2 +#define STM32_GPT_TIM14_IRQ_PRIORITY 2 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 FALSE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_IRQ_PRIORITY 3 +#define STM32_I2C_I2C2_IRQ_PRIORITY 3 +#define STM32_I2C_USE_DMA TRUE +#define STM32_I2C_I2C1_DMA_PRIORITY 1 +#define STM32_I2C_I2C2_DMA_PRIORITY 1 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 3 +#define STM32_ICU_TIM2_IRQ_PRIORITY 3 +#define STM32_ICU_TIM3_IRQ_PRIORITY 3 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED FALSE +#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 FALSE +#define STM32_PWM_TIM1_IRQ_PRIORITY 3 +#define STM32_PWM_TIM2_IRQ_PRIORITY 3 +#define STM32_PWM_TIM3_IRQ_PRIORITY 3 + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 FALSE +#define STM32_SERIAL_USART1_PRIORITY 3 +#define STM32_SERIAL_USART2_PRIORITY 3 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 2 +#define STM32_SPI_SPI2_IRQ_PRIORITY 2 +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 2 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USART1_IRQ_PRIORITY 3 +#define STM32_UART_USART2_IRQ_PRIORITY 3 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_USB1 TRUE +#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE +#define STM32_USB_USB1_LP_IRQ_PRIORITY 3 + +#endif /* _MCUCONF_H_ */ diff --git a/platforms/chibios/boards/GENERIC_STM32_F303XC/board/board.mk b/platforms/chibios/boards/GENERIC_STM32_F303XC/board/board.mk new file mode 100644 index 0000000000..f891e65247 --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_F303XC/board/board.mk @@ -0,0 +1,9 @@ +# List of all the board related files. +BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_STM32F3_DISCOVERY/board.c + +# Required include directories +BOARDINC = $(CHIBIOS)/os/hal/boards/ST_STM32F3_DISCOVERY + +# Shared variables +ALLCSRC += $(BOARDSRC) +ALLINC += $(BOARDINC) diff --git a/platforms/chibios/boards/GENERIC_STM32_F303XC/configs/board.h b/platforms/chibios/boards/GENERIC_STM32_F303XC/configs/board.h new file mode 100644 index 0000000000..97159964d0 --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_F303XC/configs/board.h @@ -0,0 +1,37 @@ +/* Copyright 2020 Nick Brassel (tzarc) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#include_next "board.h" + +#undef STM32_HSE_BYPASS + +/* + * USB bus activation macro, required by the USB driver. + */ +#define usb_lld_connect_bus(usbp) \ + do { \ + palSetPadMode(GPIOA, GPIOA_USB_DP, PAL_MODE_ALTERNATE(14)); \ + } while (0) + +/* + * USB bus de-activation macro, required by the USB driver. + */ +#define usb_lld_disconnect_bus(usbp) \ + do { \ + palSetPadMode(GPIOA, GPIOA_USB_DP, PAL_MODE_OUTPUT_PUSHPULL); \ + palClearPad(GPIOA, GPIOA_USB_DP); \ + } while (0) diff --git a/platforms/chibios/boards/GENERIC_STM32_F303XC/configs/bootloader_defs.h b/platforms/chibios/boards/GENERIC_STM32_F303XC/configs/bootloader_defs.h new file mode 100644 index 0000000000..87ac7b10dc --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_F303XC/configs/bootloader_defs.h @@ -0,0 +1,5 @@ +/* Address for jumping to bootloader on STM32 chips. */ +/* It is chip dependent, the correct number can be looked up here: + * http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf + */ +#define STM32_BOOTLOADER_ADDRESS 0x1FFFD800 diff --git a/platforms/chibios/boards/GENERIC_STM32_F303XC/configs/config.h b/platforms/chibios/boards/GENERIC_STM32_F303XC/configs/config.h new file mode 100644 index 0000000000..a73f0c0b47 --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_F303XC/configs/config.h @@ -0,0 +1,20 @@ +/* Copyright 2020 Nick Brassel (tzarc) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP +# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE +#endif diff --git a/platforms/chibios/boards/GENERIC_STM32_F303XC/configs/mcuconf.h b/platforms/chibios/boards/GENERIC_STM32_F303XC/configs/mcuconf.h new file mode 100644 index 0000000000..c6f5a8ac52 --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_F303XC/configs/mcuconf.h @@ -0,0 +1,273 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + 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 License 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. +*/ + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F3xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F3xx_MCUCONF +#define STM32F303_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_HSI_ENABLED TRUE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED FALSE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PREDIV_VALUE 1 +#define STM32_PLLMUL_VALUE 9 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV2 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK +#define STM32_ADC12PRES STM32_ADC12PRES_DIV1 +#define STM32_ADC34PRES STM32_ADC34PRES_DIV1 +#define STM32_USART1SW STM32_USART1SW_PCLK +#define STM32_USART2SW STM32_USART2SW_PCLK +#define STM32_USART3SW STM32_USART3SW_PCLK +#define STM32_UART4SW STM32_UART4SW_PCLK +#define STM32_UART5SW STM32_UART5SW_PCLK +#define STM32_I2C1SW STM32_I2C1SW_SYSCLK +#define STM32_I2C2SW STM32_I2C2SW_SYSCLK +#define STM32_TIM1SW STM32_TIM1SW_PCLK2 +#define STM32_TIM8SW STM32_TIM8SW_PCLK2 +#define STM32_RTCSEL STM32_RTCSEL_LSI +#define STM32_USB_CLOCK_REQUIRED TRUE +#define STM32_USBPRE STM32_USBPRE_DIV1P5 + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 15 +#define STM32_IRQ_EXTI20_PRIORITY 15 +#define STM32_IRQ_EXTI21_22_29_PRIORITY 6 +#define STM32_IRQ_EXTI30_32_PRIORITY 6 +#define STM32_IRQ_EXTI33_PRIORITY 6 +#define STM32_IRQ_TIM1_BRK_TIM15_PRIORITY 7 +#define STM32_IRQ_TIM1_UP_TIM16_PRIORITY 7 +#define STM32_IRQ_TIM1_TRGCO_TIM17_PRIORITY 7 +#define STM32_IRQ_TIM1_CC_PRIORITY 7 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_DUAL_MODE FALSE +#define STM32_ADC_COMPACT_SAMPLES FALSE +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_USE_ADC2 FALSE +#define STM32_ADC_USE_ADC3 FALSE +#define STM32_ADC_USE_ADC4 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_ADC_ADC4_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#define STM32_ADC_ADC4_DMA_PRIORITY 2 +#define STM32_ADC_ADC12_IRQ_PRIORITY 5 +#define STM32_ADC_ADC3_IRQ_PRIORITY 5 +#define STM32_ADC_ADC4_IRQ_PRIORITY 5 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 5 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 5 +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 5 +#define STM32_ADC_ADC4_DMA_IRQ_PRIORITY 5 +#define STM32_ADC_ADC12_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1 +#define STM32_ADC_ADC34_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 FALSE +#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM8 FALSE +#define STM32_GPT_USE_TIM15 FALSE +#define STM32_GPT_USE_TIM16 FALSE +#define STM32_GPT_USE_TIM17 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 FALSE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_IRQ_PRIORITY 10 +#define STM32_I2C_I2C2_IRQ_PRIORITY 10 +#define STM32_I2C_USE_DMA TRUE +#define STM32_I2C_I2C1_DMA_PRIORITY 1 +#define STM32_I2C_I2C2_DMA_PRIORITY 1 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM15 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED FALSE +#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 FALSE +#define STM32_PWM_USE_TIM4 FALSE +#define STM32_PWM_USE_TIM8 FALSE +#define STM32_PWM_USE_TIM15 FALSE +#define STM32_PWM_USE_TIM16 FALSE +#define STM32_PWM_USE_TIM17 FALSE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 + +/* + * RTC driver system settings. + */ +#define STM32_RTC_PRESA_VALUE 32 +#define STM32_RTC_PRESS_VALUE 1024 +#define STM32_RTC_CR_INIT 0 +#define STM32_RTC_TAMPCR_INIT 0 + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 FALSE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_USB1 TRUE +#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE +#define STM32_USB_USB1_HP_IRQ_PRIORITY 13 +#define STM32_USB_USB1_LP_IRQ_PRIORITY 14 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG FALSE + +#endif /* MCUCONF_H */ diff --git a/platforms/chibios/boards/GENERIC_STM32_F407XE/board/board.mk b/platforms/chibios/boards/GENERIC_STM32_F407XE/board/board.mk new file mode 100644 index 0000000000..6c837bb8ee --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_F407XE/board/board.mk @@ -0,0 +1,9 @@ +# List of all the board related files. +BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_STM32F4_DISCOVERY/board.c + +# Required include directories +BOARDINC = $(CHIBIOS)/os/hal/boards/ST_STM32F4_DISCOVERY + +# Shared variables +ALLCSRC += $(BOARDSRC) +ALLINC += $(BOARDINC) \ No newline at end of file diff --git a/platforms/chibios/boards/GENERIC_STM32_F407XE/configs/board.h b/platforms/chibios/boards/GENERIC_STM32_F407XE/configs/board.h new file mode 100644 index 0000000000..22c4e4cd7e --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_F407XE/configs/board.h @@ -0,0 +1,24 @@ +/* Copyright 2020 Nick Brassel (tzarc) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#define STM32_HSECLK 8000000 +// The following is required to disable the pull-down on PA9, when PA9 is used for the keyboard matrix: +#define BOARD_OTG_NOVBUSSENS + +#include_next "board.h" + +#undef STM32_HSE_BYPASS \ No newline at end of file diff --git a/platforms/chibios/boards/GENERIC_STM32_F407XE/configs/config.h b/platforms/chibios/boards/GENERIC_STM32_F407XE/configs/config.h new file mode 100644 index 0000000000..cc52a953ed --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_F407XE/configs/config.h @@ -0,0 +1,23 @@ +/* Copyright 2021 Andrei Purdea + * + * 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 . + */ + +/* Address for jumping to bootloader on STM32 chips. */ +/* It is chip dependent, the correct number can be looked up by checking against ST's application note AN2606. + */ +#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000 +#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP +# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE +#endif diff --git a/platforms/chibios/boards/GENERIC_STM32_F407XE/configs/mcuconf.h b/platforms/chibios/boards/GENERIC_STM32_F407XE/configs/mcuconf.h new file mode 100644 index 0000000000..4be47fe1b0 --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_F407XE/configs/mcuconf.h @@ -0,0 +1,355 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + 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 License 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. +*/ + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F4xx_MCUCONF +#define STM32F405_MCUCONF +#define STM32F415_MCUCONF +#define STM32F407_MCUCONF +#define STM32F417_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_BKPRAM_ENABLE FALSE +#define STM32_HSI_ENABLED TRUE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED FALSE +#define STM32_CLOCK48_REQUIRED TRUE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PLLM_VALUE 8 +#define STM32_PLLN_VALUE 336 +#define STM32_PLLP_VALUE 2 +#define STM32_PLLQ_VALUE 7 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV4 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_RTCSEL STM32_RTCSEL_LSI +#define STM32_RTCPRE_VALUE 8 +#define STM32_MCO1SEL STM32_MCO1SEL_HSI +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK +#define STM32_MCO2PRE STM32_MCO2PRE_DIV5 +#define STM32_I2SSRC STM32_I2SSRC_CKIN +#define STM32_PLLI2SN_VALUE 192 +#define STM32_PLLI2SR_VALUE 5 + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_PRIORITY 15 +#define STM32_IRQ_EXTI22_PRIORITY 15 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_USE_ADC2 FALSE +#define STM32_ADC_USE_ADC3 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 6 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_USE_CAN2 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 +#define STM32_CAN_CAN2_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 FALSE +#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM8 FALSE +#define STM32_GPT_USE_TIM9 FALSE +#define STM32_GPT_USE_TIM11 FALSE +#define STM32_GPT_USE_TIM12 FALSE +#define STM32_GPT_USE_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 +#define STM32_GPT_TIM12_IRQ_PRIORITY 7 +#define STM32_GPT_TIM14_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 FALSE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * I2S driver system settings. + */ +#define STM32_I2S_USE_SPI2 FALSE +#define STM32_I2S_USE_SPI3 FALSE +#define STM32_I2S_SPI2_IRQ_PRIORITY 10 +#define STM32_I2S_SPI3_IRQ_PRIORITY 10 +#define STM32_I2S_SPI2_DMA_PRIORITY 1 +#define STM32_I2S_SPI3_DMA_PRIORITY 1 +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM9 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 + +/* + * MAC driver system settings. + */ +#define STM32_MAC_TRANSMIT_BUFFERS 2 +#define STM32_MAC_RECEIVE_BUFFERS 4 +#define STM32_MAC_BUFFERS_SIZE 1522 +#define STM32_MAC_PHY_TIMEOUT 100 +#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE +#define STM32_MAC_ETH1_IRQ_PRIORITY 13 +#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED FALSE +#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 FALSE +#define STM32_PWM_USE_TIM4 FALSE +#define STM32_PWM_USE_TIM5 FALSE +#define STM32_PWM_USE_TIM8 FALSE +#define STM32_PWM_USE_TIM9 FALSE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 + +/* + * RTC driver system settings. + */ +#define STM32_RTC_PRESA_VALUE 32 +#define STM32_RTC_PRESS_VALUE 1024 +#define STM32_RTC_CR_INIT 0 +#define STM32_RTC_TAMPCR_INIT 0 + +/* + * SDC driver system settings. + */ +#define STM32_SDC_SDIO_DMA_PRIORITY 3 +#define STM32_SDC_SDIO_IRQ_PRIORITY 9 +#define STM32_SDC_WRITE_TIMEOUT_MS 1000 +#define STM32_SDC_READ_TIMEOUT_MS 1000 +#define STM32_SDC_CLOCK_ACTIVATION_DELAY 10 +#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE +#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 FALSE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USE_USART6 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 +#define STM32_SERIAL_USART6_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USE_UART4 FALSE +#define STM32_UART_USE_UART5 FALSE +#define STM32_UART_USE_USART6 FALSE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_UART4_IRQ_PRIORITY 12 +#define STM32_UART_UART5_IRQ_PRIORITY 12 +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_UART4_DMA_PRIORITY 0 +#define STM32_UART_UART5_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_OTG1 TRUE +#define STM32_USB_USE_OTG2 FALSE +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#define STM32_USB_OTG2_IRQ_PRIORITY 14 +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 +#define STM32_USB_HOST_WAKEUP_DURATION 2 + +#define STM32_USB_OTG_THREAD_PRIO NORMALPRIO+1 +#define STM32_USB_OTG_THREAD_STACK_SIZE 128 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG FALSE + +#endif /* MCUCONF_H */ diff --git a/platforms/chibios/boards/GENERIC_STM32_F446XE/board/board.mk b/platforms/chibios/boards/GENERIC_STM32_F446XE/board/board.mk new file mode 100644 index 0000000000..57897941ca --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_F446XE/board/board.mk @@ -0,0 +1,9 @@ +# List of all the board related files. +BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_F446RE/board.c + +# Required include directories +BOARDINC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_F446RE + +# Shared variables +ALLCSRC += $(BOARDSRC) +ALLINC += $(BOARDINC) diff --git a/platforms/chibios/boards/GENERIC_STM32_F446XE/configs/board.h b/platforms/chibios/boards/GENERIC_STM32_F446XE/configs/board.h new file mode 100644 index 0000000000..80dfcffa99 --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_F446XE/configs/board.h @@ -0,0 +1,24 @@ +/* Copyright 2020 Nick Brassel (tzarc) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#define STM32_HSECLK 16000000 +// The following is required to disable the pull-down on PA9, when PA9 is used for the keyboard matrix: +#define BOARD_OTG_NOVBUSSENS + +#include_next "board.h" + +#undef STM32_HSE_BYPASS diff --git a/platforms/chibios/boards/GENERIC_STM32_F446XE/configs/config.h b/platforms/chibios/boards/GENERIC_STM32_F446XE/configs/config.h new file mode 100644 index 0000000000..cc52a953ed --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_F446XE/configs/config.h @@ -0,0 +1,23 @@ +/* Copyright 2021 Andrei Purdea + * + * 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 . + */ + +/* Address for jumping to bootloader on STM32 chips. */ +/* It is chip dependent, the correct number can be looked up by checking against ST's application note AN2606. + */ +#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000 +#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP +# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE +#endif diff --git a/platforms/chibios/boards/GENERIC_STM32_F446XE/configs/mcuconf.h b/platforms/chibios/boards/GENERIC_STM32_F446XE/configs/mcuconf.h new file mode 100644 index 0000000000..d2de75590e --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_F446XE/configs/mcuconf.h @@ -0,0 +1,361 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + 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 License 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. +*/ + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F4xx_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_HSI_ENABLED FALSE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED FALSE +#define STM32_CLOCK48_REQUIRED TRUE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PLLM_VALUE 8 +#define STM32_PLLN_VALUE 180 +#define STM32_PLLP_VALUE 2 +#define STM32_PLLQ_VALUE 7 +#define STM32_PLLI2SN_VALUE 192 +#define STM32_PLLI2SM_VALUE 8 +#define STM32_PLLI2SR_VALUE 4 +#define STM32_PLLI2SP_VALUE 4 +#define STM32_PLLI2SQ_VALUE 4 +#define STM32_PLLSAIN_VALUE 192 +#define STM32_PLLSAIM_VALUE 8 +#define STM32_PLLSAIP_VALUE 8 +#define STM32_PLLSAIQ_VALUE 4 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV4 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_RTCSEL STM32_RTCSEL_LSI +#define STM32_RTCPRE_VALUE 8 +#define STM32_MCO1SEL STM32_MCO1SEL_HSE +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#define STM32_MCO2SEL STM32_MCO2SEL_PLLI2S +#define STM32_MCO2PRE STM32_MCO2PRE_DIV1 +#define STM32_I2SSRC STM32_I2SSRC_PLLI2S +#define STM32_SAI1SEL STM32_SAI2SEL_PLLR +#define STM32_SAI2SEL STM32_SAI2SEL_PLLR +#define STM32_CK48MSEL STM32_CK48MSEL_PLLALT +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_BKPRAM_ENABLE FALSE + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_PRIORITY 15 +#define STM32_IRQ_EXTI22_PRIORITY 15 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_USE_ADC2 FALSE +#define STM32_ADC_USE_ADC3 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 6 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_USE_CAN2 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 +#define STM32_CAN_CAN2_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 FALSE +#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM8 FALSE +#define STM32_GPT_USE_TIM9 FALSE +#define STM32_GPT_USE_TIM11 FALSE +#define STM32_GPT_USE_TIM12 FALSE +#define STM32_GPT_USE_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 +#define STM32_GPT_TIM12_IRQ_PRIORITY 7 +#define STM32_GPT_TIM14_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 FALSE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * I2S driver system settings. + */ +#define STM32_I2S_USE_SPI2 FALSE +#define STM32_I2S_USE_SPI3 FALSE +#define STM32_I2S_SPI2_IRQ_PRIORITY 10 +#define STM32_I2S_SPI3_IRQ_PRIORITY 10 +#define STM32_I2S_SPI2_DMA_PRIORITY 1 +#define STM32_I2S_SPI3_DMA_PRIORITY 1 +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM9 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 + +/* + * MAC driver system settings. + */ +#define STM32_MAC_TRANSMIT_BUFFERS 2 +#define STM32_MAC_RECEIVE_BUFFERS 4 +#define STM32_MAC_BUFFERS_SIZE 1522 +#define STM32_MAC_PHY_TIMEOUT 100 +#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE +#define STM32_MAC_ETH1_IRQ_PRIORITY 13 +#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED FALSE +#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 FALSE +#define STM32_PWM_USE_TIM4 FALSE +#define STM32_PWM_USE_TIM5 FALSE +#define STM32_PWM_USE_TIM8 FALSE +#define STM32_PWM_USE_TIM9 FALSE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 + +/* + * SDC driver system settings. + */ +#define STM32_SDC_SDIO_DMA_PRIORITY 3 +#define STM32_SDC_SDIO_IRQ_PRIORITY 9 +#define STM32_SDC_WRITE_TIMEOUT_MS 1000 +#define STM32_SDC_READ_TIMEOUT_MS 1000 +#define STM32_SDC_CLOCK_ACTIVATION_DELAY 10 +#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE +#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 FALSE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USE_USART6 FALSE +#define STM32_SERIAL_USE_UART7 FALSE +#define STM32_SERIAL_USE_UART8 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 +#define STM32_SERIAL_USART6_PRIORITY 12 +#define STM32_SERIAL_UART7_PRIORITY 12 +#define STM32_SERIAL_UART8_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_USE_SPI4 FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_SPI_SPI4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI4_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_SPI4_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USE_UART4 FALSE +#define STM32_UART_USE_UART5 FALSE +#define STM32_UART_USE_USART6 FALSE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_UART4_IRQ_PRIORITY 12 +#define STM32_UART_UART5_IRQ_PRIORITY 12 +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_UART4_DMA_PRIORITY 0 +#define STM32_UART_UART5_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_OTG1 TRUE +#define STM32_USB_USE_OTG2 FALSE +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#define STM32_USB_OTG2_IRQ_PRIORITY 14 +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 +#define STM32_USB_OTG_THREAD_PRIO LOWPRIO +#define STM32_USB_OTG_THREAD_STACK_SIZE 128 +#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG FALSE + +#endif /* MCUCONF_H */ diff --git a/platforms/chibios/boards/GENERIC_STM32_G431XB/board/board.mk b/platforms/chibios/boards/GENERIC_STM32_G431XB/board/board.mk new file mode 100644 index 0000000000..0acbcd83c7 --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_G431XB/board/board.mk @@ -0,0 +1,9 @@ +# List of all the board related files. +BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_G431RB/board.c + +# Required include directories +BOARDINC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_G431RB + +# Shared variables +ALLCSRC += $(BOARDSRC) +ALLINC += $(BOARDINC) diff --git a/platforms/chibios/boards/GENERIC_STM32_G431XB/configs/config.h b/platforms/chibios/boards/GENERIC_STM32_G431XB/configs/config.h new file mode 100644 index 0000000000..39ce627e77 --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_G431XB/configs/config.h @@ -0,0 +1,23 @@ +/* Copyright 2018-2020 Nick Brassel (@tzarc) + * + * 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 . + */ + +/* Address for jumping to bootloader on STM32 chips. */ +/* It is chip dependent, the correct number can be looked up here (page 175): + * http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf + * This also requires a patch to chibios: + * /tmk_core/tool/chibios/ch-bootloader-jump.patch + */ +#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000 diff --git a/platforms/chibios/boards/GENERIC_STM32_G431XB/configs/mcuconf.h b/platforms/chibios/boards/GENERIC_STM32_G431XB/configs/mcuconf.h new file mode 100644 index 0000000000..182d4885d7 --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_G431XB/configs/mcuconf.h @@ -0,0 +1,307 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + 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 License 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. +*/ + +/* + * STM32G4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#ifndef MCUCONF_H +#define MCUCONF_H + +#define STM32G4xx_MCUCONF +#define STM32G431_MCUCONF +#define STM32G441_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_VOS STM32_VOS_RANGE1 +#define STM32_PWR_CR2 (PWR_CR2_PLS_LEV0) +#define STM32_PWR_CR3 (PWR_CR3_EIWF) +#define STM32_PWR_CR4 (0U) +#define STM32_HSI16_ENABLED TRUE +#define STM32_HSI48_ENABLED TRUE +#define STM32_HSE_ENABLED FALSE +#define STM32_LSI_ENABLED TRUE +#define STM32_LSE_ENABLED FALSE +#define STM32_SW STM32_SW_PLLRCLK +#define STM32_PLLSRC STM32_PLLSRC_HSI16 +#define STM32_PLLM_VALUE 4 +#define STM32_PLLN_VALUE 80 +#define STM32_PLLPDIV_VALUE 0 +#define STM32_PLLP_VALUE 7 +#define STM32_PLLQ_VALUE 8 +#define STM32_PLLR_VALUE 2 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV1 +#define STM32_PPRE2 STM32_PPRE2_DIV1 +#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK +#define STM32_MCOPRE STM32_MCOPRE_DIV1 +#define STM32_LSCOSEL STM32_LSCOSEL_NOCLOCK + +/* + * Peripherals clock sources. + */ +#define STM32_USART1SEL STM32_USART1SEL_SYSCLK +#define STM32_USART2SEL STM32_USART2SEL_SYSCLK +#define STM32_USART3SEL STM32_USART3SEL_SYSCLK +#define STM32_UART4SEL STM32_UART4SEL_SYSCLK +#define STM32_LPUART1SEL STM32_LPUART1SEL_PCLK1 +#define STM32_I2C1SEL STM32_I2C1SEL_PCLK1 +#define STM32_I2C2SEL STM32_I2C2SEL_PCLK1 +#define STM32_I2C3SEL STM32_I2C3SEL_PCLK1 +#define STM32_LPTIM1SEL STM32_LPTIM1SEL_PCLK1 +#define STM32_SAI1SEL STM32_SAI1SEL_SYSCLK +#define STM32_I2S23SEL STM32_I2S23SEL_SYSCLK +#define STM32_FDCANSEL STM32_FDCANSEL_PCLK1 +#define STM32_CLK48SEL STM32_CLK48SEL_HSI48 +#define STM32_ADC12SEL STM32_ADC12SEL_PLLPCLK +#define STM32_RTCSEL STM32_RTCSEL_NOCLOCK + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI164041_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 6 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI212229_PRIORITY 6 +#define STM32_IRQ_EXTI30_32_PRIORITY 6 +#define STM32_IRQ_EXTI33_PRIORITY 6 + +#define STM32_IRQ_FDCAN1_PRIORITY 10 + +#define STM32_IRQ_TIM1_BRK_TIM15_PRIORITY 7 +#define STM32_IRQ_TIM1_UP_TIM16_PRIORITY 7 +#define STM32_IRQ_TIM1_TRGCO_TIM17_PRIORITY 7 +#define STM32_IRQ_TIM1_CC_PRIORITY 7 +#define STM32_IRQ_TIM2_PRIORITY 7 +#define STM32_IRQ_TIM3_PRIORITY 7 +#define STM32_IRQ_TIM4_PRIORITY 7 +#define STM32_IRQ_TIM6_PRIORITY 7 +#define STM32_IRQ_TIM7_PRIORITY 7 +#define STM32_IRQ_TIM8_UP_PRIORITY 7 +#define STM32_IRQ_TIM8_CC_PRIORITY 7 + +#define STM32_IRQ_USART1_PRIORITY 12 +#define STM32_IRQ_USART2_PRIORITY 12 +#define STM32_IRQ_USART3_PRIORITY 12 +#define STM32_IRQ_UART4_PRIORITY 12 +#define STM32_IRQ_LPUART1_PRIORITY 12 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_DUAL_MODE FALSE +#define STM32_ADC_COMPACT_SAMPLES FALSE +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_USE_ADC2 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC12_IRQ_PRIORITY 5 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 5 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 5 +#define STM32_ADC_ADC12_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV4 +#define STM32_ADC_ADC12_PRESC ADC_CCR_PRESC_DIV2 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_FDCAN1 FALSE + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 FALSE +#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_USE_DAC3_CH1 FALSE +#define STM32_DAC_USE_DAC3_CH2 FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC3_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC3_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC3_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC3_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_DAC_DAC3_CH1_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_DAC_DAC3_CH2_DMA_STREAM STM32_DMA_STREAM_ID_ANY + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM8 FALSE +#define STM32_GPT_USE_TIM15 FALSE +#define STM32_GPT_USE_TIM16 FALSE +#define STM32_GPT_USE_TIM17 FALSE + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 FALSE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM15 FALSE + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED FALSE +#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 FALSE +#define STM32_PWM_USE_TIM4 FALSE +#define STM32_PWM_USE_TIM8 FALSE +#define STM32_PWM_USE_TIM15 FALSE +#define STM32_PWM_USE_TIM16 FALSE +#define STM32_PWM_USE_TIM17 FALSE + +/* + * RTC driver system settings. + */ + +/* + * SDC driver system settings. + */ + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 FALSE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_LPUART1 FALSE + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * TRNG driver system settings. + */ +#define STM32_TRNG_USE_RNG1 FALSE + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USE_UART4 FALSE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_UART4_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_USB1 TRUE +#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE +#define STM32_USB_USB1_HP_IRQ_PRIORITY 5 +#define STM32_USB_USB1_LP_IRQ_PRIORITY 6 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG FALSE + +#endif /* MCUCONF_H */ diff --git a/platforms/chibios/boards/GENERIC_STM32_G474XE/board/board.mk b/platforms/chibios/boards/GENERIC_STM32_G474XE/board/board.mk new file mode 100644 index 0000000000..957adf509b --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_G474XE/board/board.mk @@ -0,0 +1,9 @@ +# List of all the board related files. +BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_G474RE/board.c + +# Required include directories +BOARDINC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_G474RE + +# Shared variables +ALLCSRC += $(BOARDSRC) +ALLINC += $(BOARDINC) diff --git a/platforms/chibios/boards/GENERIC_STM32_G474XE/configs/config.h b/platforms/chibios/boards/GENERIC_STM32_G474XE/configs/config.h new file mode 100644 index 0000000000..eb74d68e85 --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_G474XE/configs/config.h @@ -0,0 +1,30 @@ +/* Copyright 2020 Nick Brassel (tzarc) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#ifndef STM32_BOOTLOADER_DUAL_BANK +# define STM32_BOOTLOADER_DUAL_BANK FALSE +#endif + +// To Enter bootloader from `RESET` keycode, you'll need to dedicate a GPIO to +// charge an RC network on the BOOT0 pin. +// See the QMK Discord's #hardware channel pins for an example circuit. +// Insert these two lines into your keyboard's `config.h` file. +// In the case below, PB7 is selected to charge. +#if 0 +#define STM32_BOOTLOADER_DUAL_BANK TRUE +#define STM32_BOOTLOADER_DUAL_BANK_GPIO B7 +#endif \ No newline at end of file diff --git a/platforms/chibios/boards/GENERIC_STM32_G474XE/configs/mcuconf.h b/platforms/chibios/boards/GENERIC_STM32_G474XE/configs/mcuconf.h new file mode 100644 index 0000000000..117e920e3b --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_G474XE/configs/mcuconf.h @@ -0,0 +1,372 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + 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 License 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. +*/ + +/* + * STM32G4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#ifndef MCUCONF_H +#define MCUCONF_H + +#define STM32G4xx_MCUCONF +#define STM32G473_MCUCONF +#define STM32G483_MCUCONF +#define STM32G474_MCUCONF +#define STM32G484_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_VOS STM32_VOS_RANGE1 +#define STM32_PWR_CR2 (PWR_CR2_PLS_LEV0) +#define STM32_PWR_CR3 (PWR_CR3_EIWF) +#define STM32_PWR_CR4 (0U) +#define STM32_HSI16_ENABLED TRUE +#define STM32_HSI48_ENABLED TRUE +#define STM32_HSE_ENABLED FALSE +#define STM32_LSI_ENABLED FALSE +#define STM32_LSE_ENABLED FALSE +#define STM32_SW STM32_SW_PLLRCLK +#define STM32_PLLSRC STM32_PLLSRC_HSI16 +#define STM32_PLLM_VALUE 2 +#define STM32_PLLN_VALUE 40 +#define STM32_PLLPDIV_VALUE 0 +#define STM32_PLLP_VALUE 7 +#define STM32_PLLQ_VALUE 2 +#define STM32_PLLR_VALUE 2 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV1 +#define STM32_PPRE2 STM32_PPRE2_DIV1 +#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK +#define STM32_MCOPRE STM32_MCOPRE_DIV1 +#define STM32_LSCOSEL STM32_LSCOSEL_NOCLOCK + +/* + * Peripherals clock sources. + */ +#define STM32_USART1SEL STM32_USART1SEL_SYSCLK +#define STM32_USART2SEL STM32_USART2SEL_SYSCLK +#define STM32_USART3SEL STM32_USART3SEL_SYSCLK +#define STM32_UART4SEL STM32_UART4SEL_SYSCLK +#define STM32_UART5SEL STM32_UART5SEL_SYSCLK +#define STM32_LPUART1SEL STM32_LPUART1SEL_PCLK1 +#define STM32_I2C1SEL STM32_I2C1SEL_PCLK1 +#define STM32_I2C2SEL STM32_I2C2SEL_PCLK1 +#define STM32_I2C3SEL STM32_I2C3SEL_PCLK1 +#define STM32_I2C4SEL STM32_I2C4SEL_PCLK1 +#define STM32_LPTIM1SEL STM32_LPTIM1SEL_PCLK1 +#define STM32_SAI1SEL STM32_SAI1SEL_SYSCLK +#define STM32_I2S23SEL STM32_I2S23SEL_SYSCLK +#define STM32_FDCANSEL STM32_FDCANSEL_HSE +#define STM32_CLK48SEL STM32_CLK48SEL_HSI48 +#define STM32_ADC12SEL STM32_ADC12SEL_PLLPCLK +#define STM32_ADC345SEL STM32_ADC345SEL_PLLPCLK +#define STM32_QSPISEL STM32_QSPISEL_SYSCLK +#define STM32_RTCSEL STM32_RTCSEL_NOCLOCK + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI164041_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 6 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI212229_PRIORITY 6 +#define STM32_IRQ_EXTI30_32_PRIORITY 6 +#define STM32_IRQ_EXTI33_PRIORITY 6 + +#define STM32_IRQ_FDCAN1_PRIORITY 10 +#define STM32_IRQ_FDCAN2_PRIORITY 10 +#define STM32_IRQ_FDCAN3_PRIORITY 10 + +#define STM32_IRQ_TIM1_BRK_TIM15_PRIORITY 7 +#define STM32_IRQ_TIM1_UP_TIM16_PRIORITY 7 +#define STM32_IRQ_TIM1_TRGCO_TIM17_PRIORITY 7 +#define STM32_IRQ_TIM1_CC_PRIORITY 7 +#define STM32_IRQ_TIM2_PRIORITY 7 +#define STM32_IRQ_TIM3_PRIORITY 7 +#define STM32_IRQ_TIM4_PRIORITY 7 +#define STM32_IRQ_TIM5_PRIORITY 7 +#define STM32_IRQ_TIM6_PRIORITY 7 +#define STM32_IRQ_TIM7_PRIORITY 7 +#define STM32_IRQ_TIM8_UP_PRIORITY 7 +#define STM32_IRQ_TIM8_CC_PRIORITY 7 +#define STM32_IRQ_TIM20_UP_PRIORITY 7 +#define STM32_IRQ_TIM20_CC_PRIORITY 7 + +#define STM32_IRQ_USART1_PRIORITY 12 +#define STM32_IRQ_USART2_PRIORITY 12 +#define STM32_IRQ_USART3_PRIORITY 12 +#define STM32_IRQ_UART4_PRIORITY 12 +#define STM32_IRQ_UART5_PRIORITY 12 +#define STM32_IRQ_LPUART1_PRIORITY 12 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_DUAL_MODE FALSE +#define STM32_ADC_COMPACT_SAMPLES FALSE +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_USE_ADC2 FALSE +#define STM32_ADC_USE_ADC3 FALSE +#define STM32_ADC_USE_ADC4 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_ADC_ADC4_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#define STM32_ADC_ADC4_DMA_PRIORITY 2 +#define STM32_ADC_ADC12_IRQ_PRIORITY 5 +#define STM32_ADC_ADC3_IRQ_PRIORITY 5 +#define STM32_ADC_ADC4_IRQ_PRIORITY 5 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 5 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 5 +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 5 +#define STM32_ADC_ADC4_DMA_IRQ_PRIORITY 5 +#define STM32_ADC_ADC12_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV4 +#define STM32_ADC_ADC345_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV4 +#define STM32_ADC_ADC12_PRESC ADC_CCR_PRESC_DIV2 +#define STM32_ADC_ADC345_PRESC ADC_CCR_PRESC_DIV2 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_FDCAN1 FALSE +#define STM32_CAN_USE_FDCAN2 FALSE +#define STM32_CAN_USE_FDCAN3 FALSE + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 FALSE +#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_USE_DAC2_CH1 FALSE +#define STM32_DAC_USE_DAC3_CH1 FALSE +#define STM32_DAC_USE_DAC3_CH2 FALSE +#define STM32_DAC_USE_DAC4_CH1 FALSE +#define STM32_DAC_USE_DAC4_CH2 FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC2_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC3_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC3_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC4_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC4_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC2_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC3_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC3_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC4_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC4_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_DAC_DAC2_CH1_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_DAC_DAC3_CH1_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_DAC_DAC3_CH2_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_DAC_DAC4_CH1_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_DAC_DAC4_CH2_DMA_STREAM STM32_DMA_STREAM_ID_ANY + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM8 FALSE +#define STM32_GPT_USE_TIM15 FALSE +#define STM32_GPT_USE_TIM16 FALSE +#define STM32_GPT_USE_TIM17 FALSE + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 FALSE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_USE_I2C4 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_I2C_I2C4_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_I2C_I2C4_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C4_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_I2C4_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM15 FALSE +#define STM32_ICU_USE_TIM16 FALSE +#define STM32_ICU_USE_TIM17 FALSE + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED FALSE +#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 FALSE +#define STM32_PWM_USE_TIM4 FALSE +#define STM32_PWM_USE_TIM5 FALSE +#define STM32_PWM_USE_TIM8 FALSE +#define STM32_PWM_USE_TIM15 FALSE +#define STM32_PWM_USE_TIM16 FALSE +#define STM32_PWM_USE_TIM17 FALSE +#define STM32_PWM_USE_TIM20 FALSE + +/* + * RTC driver system settings. + */ + +/* + * SDC driver system settings. + */ + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 FALSE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USE_LPUART1 FALSE + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_USE_SPI4 FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_SPI_SPI4_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_SPI_SPI4_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI4_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_SPI4_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * TRNG driver system settings. + */ +#define STM32_TRNG_USE_RNG1 FALSE + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USE_UART4 FALSE +#define STM32_UART_USE_UART5 FALSE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_UART4_DMA_PRIORITY 0 +#define STM32_UART_UART5_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_USB1 TRUE +#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE +#define STM32_USB_USB1_HP_IRQ_PRIORITY 5 +#define STM32_USB_USB1_LP_IRQ_PRIORITY 5 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG FALSE + +/* + * WSPI driver system settings. + */ +#define STM32_WSPI_USE_QUADSPI1 FALSE +#define STM32_WSPI_QUADSPI1_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) + +#endif /* MCUCONF_H */ diff --git a/platforms/chibios/boards/GENERIC_STM32_L412XB/board/board.mk b/platforms/chibios/boards/GENERIC_STM32_L412XB/board/board.mk new file mode 100644 index 0000000000..1250385eb8 --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_L412XB/board/board.mk @@ -0,0 +1,9 @@ +# List of all the board related files. +BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO32_L432KC/board.c + +# Required include directories +BOARDINC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO32_L432KC + +# Shared variables +ALLCSRC += $(BOARDSRC) +ALLINC += $(BOARDINC) diff --git a/platforms/chibios/boards/GENERIC_STM32_L412XB/configs/board.h b/platforms/chibios/boards/GENERIC_STM32_L412XB/configs/board.h new file mode 100644 index 0000000000..2e37d95fe3 --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_L412XB/configs/board.h @@ -0,0 +1,24 @@ +/* Copyright 2018-2021 Harrison Chan (@Xelus) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#include_next "board.h" + +#undef STM32L432xx + +// Pretend that we're an L443xx as the ChibiOS definitions for L4x2/L4x3 mistakenly don't enable GPIOH, I2C2, or SPI2. +// Until ChibiOS upstream is fixed, this should be kept at L443, as nothing in QMK currently utilises the crypto peripheral on the L443. +#define STM32L443xx diff --git a/platforms/chibios/boards/GENERIC_STM32_L412XB/configs/config.h b/platforms/chibios/boards/GENERIC_STM32_L412XB/configs/config.h new file mode 100644 index 0000000000..c27c61b19a --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_L412XB/configs/config.h @@ -0,0 +1,26 @@ +/* Copyright 2018-2021 Harrison Chan (@Xelus) + * + * 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 . + */ + +/* Address for jumping to bootloader on STM32 chips. */ +/* It is chip dependent, the correct number can be looked up by checking against ST's application note AN2606. + */ +#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000 + +#define PAL_STM32_OSPEED_HIGHEST PAL_STM32_OSPEED_HIGH + +#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP +# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE +#endif diff --git a/platforms/chibios/boards/GENERIC_STM32_L412XB/configs/mcuconf.h b/platforms/chibios/boards/GENERIC_STM32_L412XB/configs/mcuconf.h new file mode 100644 index 0000000000..8ad5a8da21 --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_L412XB/configs/mcuconf.h @@ -0,0 +1,282 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + 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 License 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. +*/ + +/* + * STM32L4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#ifndef MCUCONF_H +#define MCUCONF_H + +#define STM32L4xx_MCUCONF +#define STM32L412_MCUCONF +#define STM32L422_MCUCONF +#define STM32L432_MCUCONF +#define STM32L433_MCUCONF +#define STM32L442_MCUCONF +#define STM32L443_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_VOS STM32_VOS_RANGE1 +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_HSI16_ENABLED TRUE +#define STM32_HSI48_ENABLED TRUE +#define STM32_LSI_ENABLED FALSE +#define STM32_HSE_ENABLED FALSE +#define STM32_LSE_ENABLED FALSE +#define STM32_MSIPLL_ENABLED FALSE +#define STM32_ADC_CLOCK_ENABLED TRUE +#define STM32_USB_CLOCK_ENABLED TRUE +#define STM32_SAI1_CLOCK_ENABLED TRUE +#define STM32_SAI2_CLOCK_ENABLED TRUE +#define STM32_MSIRANGE STM32_MSIRANGE_4M +#define STM32_MSISRANGE STM32_MSISRANGE_4M +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSI16 +#define STM32_PLLM_VALUE 4 +#define STM32_PLLN_VALUE 80 +#define STM32_PLLP_VALUE 7 +#define STM32_PLLQ_VALUE 4 +#define STM32_PLLR_VALUE 4 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV1 +#define STM32_PPRE2 STM32_PPRE2_DIV1 +#define STM32_STOPWUCK STM32_STOPWUCK_MSI +#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK +#define STM32_MCOPRE STM32_MCOPRE_DIV1 +#define STM32_LSCOSEL STM32_LSCOSEL_NOCLOCK +#define STM32_PLLSAI1N_VALUE 72 +#define STM32_PLLSAI1P_VALUE 7 +#define STM32_PLLSAI1Q_VALUE 6 +#define STM32_PLLSAI1R_VALUE 6 +#define STM32_PLLSAI2N_VALUE 72 +#define STM32_PLLSAI2P_VALUE 7 +#define STM32_PLLSAI2R_VALUE 6 + +/* + * Peripherals clock sources. + */ +#define STM32_USART1SEL STM32_USART1SEL_SYSCLK +#define STM32_USART2SEL STM32_USART2SEL_SYSCLK +#define STM32_USART3SEL STM32_USART3SEL_SYSCLK +#define STM32_UART4SEL STM32_UART4SEL_SYSCLK +#define STM32_UART5SEL STM32_UART5SEL_SYSCLK +#define STM32_LPUART1SEL STM32_LPUART1SEL_SYSCLK +#define STM32_I2C1SEL STM32_I2C1SEL_SYSCLK +#define STM32_I2C2SEL STM32_I2C2SEL_SYSCLK +#define STM32_I2C3SEL STM32_I2C3SEL_SYSCLK +#define STM32_LPTIM1SEL STM32_LPTIM1SEL_PCLK1 +#define STM32_LPTIM2SEL STM32_LPTIM2SEL_PCLK1 +#define STM32_SAI1SEL STM32_SAI1SEL_OFF +#define STM32_SAI2SEL STM32_SAI2SEL_OFF +#define STM32_CLK48SEL STM32_CLK48SEL_HSI48 +#define STM32_ADCSEL STM32_ADCSEL_SYSCLK +#define STM32_SWPMI1SEL STM32_SWPMI1SEL_PCLK1 +#define STM32_RTCSEL STM32_RTCSEL_LSI + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI1635_38_PRIORITY 6 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_22_PRIORITY 15 + +#define STM32_IRQ_TIM1_BRK_TIM15_PRIORITY 7 +#define STM32_IRQ_TIM1_UP_TIM16_PRIORITY 7 +#define STM32_IRQ_TIM1_TRGCO_TIM17_PRIORITY 7 +#define STM32_IRQ_TIM1_CC_PRIORITY 7 +#define STM32_IRQ_TIM2_PRIORITY 7 +#define STM32_IRQ_TIM6_PRIORITY 7 +#define STM32_IRQ_TIM7_PRIORITY 7 + +#define STM32_IRQ_USART1_PRIORITY 12 +#define STM32_IRQ_USART2_PRIORITY 12 +#define STM32_IRQ_USART3_PRIORITY 12 +#define STM32_IRQ_LPUART1_PRIORITY 12 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_COMPACT_SAMPLES FALSE +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC12_IRQ_PRIORITY 5 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 5 +#define STM32_ADC_ADC123_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1 +#define STM32_ADC_ADC123_PRESC ADC_CCR_PRESC_DIV2 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 FALSE +#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM15 FALSE +#define STM32_GPT_USE_TIM16 FALSE + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 FALSE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM15 FALSE +#define STM32_ICU_USE_TIM16 FALSE + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED FALSE +#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM15 FALSE +#define STM32_PWM_USE_TIM16 FALSE + +/* + * RTC driver system settings. + */ +#define STM32_RTC_PRESA_VALUE 32 +#define STM32_RTC_PRESS_VALUE 1024 +#define STM32_RTC_CR_INIT 0 +#define STM32_RTC_TAMPCR_INIT 0 + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 FALSE +#define STM32_SERIAL_USE_LPUART1 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_LPUART1_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * TRNG driver system settings. + */ +#define STM32_TRNG_USE_RNG1 FALSE + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 6) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_USB1 TRUE +#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE +#define STM32_USB_USB1_HP_IRQ_PRIORITY 13 +#define STM32_USB_USB1_LP_IRQ_PRIORITY 14 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG FALSE + +/* + * WSPI driver system settings. + */ +#define STM32_WSPI_USE_QUADSPI1 FALSE +#define STM32_WSPI_QUADSPI1_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_WSPI_QUADSPI1_PRESCALER_VALUE 1 + +#endif /* MCUCONF_H */ diff --git a/platforms/chibios/boards/GENERIC_STM32_L433XC/board/board.mk b/platforms/chibios/boards/GENERIC_STM32_L433XC/board/board.mk new file mode 100644 index 0000000000..1250385eb8 --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_L433XC/board/board.mk @@ -0,0 +1,9 @@ +# List of all the board related files. +BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO32_L432KC/board.c + +# Required include directories +BOARDINC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO32_L432KC + +# Shared variables +ALLCSRC += $(BOARDSRC) +ALLINC += $(BOARDINC) diff --git a/platforms/chibios/boards/GENERIC_STM32_L433XC/configs/board.h b/platforms/chibios/boards/GENERIC_STM32_L433XC/configs/board.h new file mode 100644 index 0000000000..2e37d95fe3 --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_L433XC/configs/board.h @@ -0,0 +1,24 @@ +/* Copyright 2018-2021 Harrison Chan (@Xelus) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#include_next "board.h" + +#undef STM32L432xx + +// Pretend that we're an L443xx as the ChibiOS definitions for L4x2/L4x3 mistakenly don't enable GPIOH, I2C2, or SPI2. +// Until ChibiOS upstream is fixed, this should be kept at L443, as nothing in QMK currently utilises the crypto peripheral on the L443. +#define STM32L443xx diff --git a/platforms/chibios/boards/GENERIC_STM32_L433XC/configs/config.h b/platforms/chibios/boards/GENERIC_STM32_L433XC/configs/config.h new file mode 100644 index 0000000000..c27c61b19a --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_L433XC/configs/config.h @@ -0,0 +1,26 @@ +/* Copyright 2018-2021 Harrison Chan (@Xelus) + * + * 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 . + */ + +/* Address for jumping to bootloader on STM32 chips. */ +/* It is chip dependent, the correct number can be looked up by checking against ST's application note AN2606. + */ +#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000 + +#define PAL_STM32_OSPEED_HIGHEST PAL_STM32_OSPEED_HIGH + +#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP +# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE +#endif diff --git a/platforms/chibios/boards/GENERIC_STM32_L433XC/configs/mcuconf.h b/platforms/chibios/boards/GENERIC_STM32_L433XC/configs/mcuconf.h new file mode 100644 index 0000000000..948c740f6e --- /dev/null +++ b/platforms/chibios/boards/GENERIC_STM32_L433XC/configs/mcuconf.h @@ -0,0 +1,292 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + 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 License 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. +*/ + +/* + * STM32L4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#ifndef MCUCONF_H +#define MCUCONF_H + +#define STM32L4xx_MCUCONF +#define STM32L443_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_VOS STM32_VOS_RANGE1 +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_HSI16_ENABLED TRUE +#define STM32_HSI48_ENABLED TRUE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED FALSE +#define STM32_LSE_ENABLED FALSE +#define STM32_MSIPLL_ENABLED FALSE +#define STM32_MSIRANGE STM32_MSIRANGE_4M +#define STM32_MSISRANGE STM32_MSISRANGE_4M +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSI16 +#define STM32_PLLM_VALUE 1 +#define STM32_PLLN_VALUE 10 +#define STM32_PLLPDIV_VALUE 0 +#define STM32_PLLP_VALUE 7 +#define STM32_PLLQ_VALUE 2 +#define STM32_PLLR_VALUE 2 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV1 +#define STM32_PPRE2 STM32_PPRE2_DIV1 +#define STM32_STOPWUCK STM32_STOPWUCK_MSI +#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK +#define STM32_MCOPRE STM32_MCOPRE_DIV1 +#define STM32_LSCOSEL STM32_LSCOSEL_NOCLOCK +#define STM32_PLLSAI1N_VALUE 24 +#define STM32_PLLSAI1PDIV_VALUE 0 +#define STM32_PLLSAI1P_VALUE 7 +#define STM32_PLLSAI1Q_VALUE 2 +#define STM32_PLLSAI1R_VALUE 2 + +/* + * Peripherals clock sources. + */ +#define STM32_USART1SEL STM32_USART1SEL_SYSCLK +#define STM32_USART2SEL STM32_USART2SEL_SYSCLK +#define STM32_USART3SEL STM32_USART3SEL_SYSCLK +#define STM32_LPUART1SEL STM32_LPUART1SEL_SYSCLK +#define STM32_I2C1SEL STM32_I2C1SEL_SYSCLK +#define STM32_I2C2SEL STM32_I2C2SEL_SYSCLK +#define STM32_I2C3SEL STM32_I2C3SEL_SYSCLK +#define STM32_LPTIM1SEL STM32_LPTIM1SEL_PCLK1 +#define STM32_LPTIM2SEL STM32_LPTIM2SEL_PCLK1 +#define STM32_SAI1SEL STM32_SAI1SEL_OFF +#define STM32_CLK48SEL STM32_CLK48SEL_HSI48 +#define STM32_ADCSEL STM32_ADCSEL_SYSCLK +#define STM32_SWPMI1SEL STM32_SWPMI1SEL_PCLK1 +#define STM32_RTCSEL STM32_RTCSEL_LSI + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI1635_38_PRIORITY 6 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_22_PRIORITY 15 + +#define STM32_IRQ_TIM1_BRK_TIM15_PRIORITY 7 +#define STM32_IRQ_TIM1_UP_TIM16_PRIORITY 7 +#define STM32_IRQ_TIM1_TRGCO_TIM17_PRIORITY 7 +#define STM32_IRQ_TIM1_CC_PRIORITY 7 +#define STM32_IRQ_TIM2_PRIORITY 7 +#define STM32_IRQ_TIM6_PRIORITY 7 +#define STM32_IRQ_TIM7_PRIORITY 7 + +#define STM32_IRQ_USART1_PRIORITY 12 +#define STM32_IRQ_USART2_PRIORITY 12 +#define STM32_IRQ_USART3_PRIORITY 12 +#define STM32_IRQ_LPUART1_PRIORITY 12 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_COMPACT_SAMPLES FALSE +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC12_IRQ_PRIORITY 5 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 5 +#define STM32_ADC_ADC123_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1 +#define STM32_ADC_ADC123_PRESC ADC_CCR_PRESC_DIV2 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 FALSE +#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM15 FALSE +#define STM32_GPT_USE_TIM16 FALSE + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 FALSE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM15 FALSE +#define STM32_ICU_USE_TIM16 FALSE + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED FALSE +#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM15 FALSE +#define STM32_PWM_USE_TIM16 FALSE + +/* + * RTC driver system settings. + */ +#define STM32_RTC_PRESA_VALUE 32 +#define STM32_RTC_PRESS_VALUE 1024 +#define STM32_RTC_CR_INIT 0 +#define STM32_RTC_TAMPCR_INIT 0 + +/* + * SDMMC drive system settings. + */ +#define STM32_SDC_USE_SDMMC1 FALSE +#define STM32_SDC_SDMMC_UNALIGNED_SUPPORT TRUE +#define STM32_SDC_SDMMC_WRITE_TIMEOUT 1000 +#define STM32_SDC_SDMMC_READ_TIMEOUT 1000 +#define STM32_SDC_SDMMC_CLOCK_DELAY 10 +#define STM32_SDC_SDMMC1_DMA_PRIORITY 3 +#define STM32_SDC_SDMMC1_IRQ_PRIORITY 9 +#define STM32_SDC_SDMMC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 FALSE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_LPUART1 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_LPUART1_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * TRNG driver system settings. + */ +#define STM32_TRNG_USE_RNG1 FALSE + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 6) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_USB1 TRUE +#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE +#define STM32_USB_USB1_HP_IRQ_PRIORITY 13 +#define STM32_USB_USB1_LP_IRQ_PRIORITY 14 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG FALSE + +/* + * WSPI driver system settings. + */ +#define STM32_WSPI_USE_QUADSPI1 FALSE +#define STM32_WSPI_QUADSPI1_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) + +#endif /* MCUCONF_H */ diff --git a/platforms/chibios/boards/IC_TEENSY_3_1/board/board.c b/platforms/chibios/boards/IC_TEENSY_3_1/board/board.c new file mode 100644 index 0000000000..424e0c975b --- /dev/null +++ b/platforms/chibios/boards/IC_TEENSY_3_1/board/board.c @@ -0,0 +1,151 @@ +/* + ChibiOS - Copyright (C) 2015 RedoX https://github.com/RedoXyde + + 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 License 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. +*/ +#include + +#if HAL_USE_PAL || defined(__DOXYGEN__) +/** + * @brief PAL setup. + * @details Digital I/O ports static configuration as defined in @p board.h. + * This variable is used by the HAL when initializing the PAL driver. + */ +const PALConfig pal_default_config = { + .ports = + { + { + /* + * PORTA setup. + * + * PTA4 - PIN33 + * PTA5 - PIN24 + * PTA12 - PIN3 + * PTA13 - PIN4 + * + * PTA18/19 crystal + * PTA0/3 SWD + */ + .port = IOPORT1, + .pads = + { + PAL_MODE_ALTERNATIVE_7, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_ALTERNATIVE_7, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_INPUT_ANALOG, PAL_MODE_INPUT_ANALOG, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + }, + }, + { + /* + * PORTB setup. + * + * PTB0 - PIN16 + * PTB1 - PIN17 + * PTB2 - PIN19 + * PTB3 - PIN18 + * PTB16 - PIN0 - UART0_TX + * PTB17 - PIN1 - UART0_RX + * PTB18 - PIN32 + * PTB19 - PIN25 + */ + .port = IOPORT2, + .pads = + { + PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_ALTERNATIVE_3, PAL_MODE_ALTERNATIVE_3, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + }, + }, + { + /* + * PORTC setup. + * + * PTC0 - PIN15 + * PTC1 - PIN22 + * PTC2 - PIN23 + * PTC3 - PIN9 + * PTC4 - PIN10 + * PTC5 - PIN13 + * PTC6 - PIN11 + * PTC7 - PIN12 + * PTC8 - PIN28 + * PTC9 - PIN27 + * PTC10 - PIN29 + * PTC11 - PIN30 + */ + .port = IOPORT3, + .pads = + { + PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + }, + }, + { + /* + * PORTD setup. + * + * PTD0 - PIN2 + * PTD1 - PIN14 + * PTD2 - PIN7 + * PTD3 - PIN8 + * PTD4 - PIN6 + * PTD5 - PIN20 + * PTD6 - PIN21 + * PTD7 - PIN5 + */ + .port = IOPORT4, + .pads = + { + PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + }, + }, + { + /* + * PORTE setup. + * + * PTE0 - PIN31 + * PTE1 - PIN26 + */ + .port = IOPORT5, + .pads = + { + PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + }, + }, + }, +}; +#endif + +// NOTE: This value comes from kiibohd/controller and is the location of a value +// which needs to be checked before disabling the watchdog (which happens in +// k20x_clock_init) +#define WDOG_TMROUTL *(volatile uint16_t *)0x40052012 + +/** + * @brief Early initialization code. + * @details This initialization must be performed just after stack setup + * and before any other initialization. + */ +void __early_init(void) { + // This is a dirty hack and should only be used as a temporary fix until this + // is upstreamed. + while (WDOG_TMROUTL < 2) + ; // Must wait for WDOG timer if already running, before jumping + + k20x_clock_init(); +} + +/** + * @brief Board-specific initialization code. + * @todo Add your board-specific code, if any. + */ +void boardInit(void) {} + + +void restart_usb_driver(USBDriver *usbp) { + // Do nothing. Restarting the USB driver on these boards breaks it. +} diff --git a/platforms/chibios/boards/IC_TEENSY_3_1/board/board.h b/platforms/chibios/boards/IC_TEENSY_3_1/board/board.h new file mode 100644 index 0000000000..c8259ab0c7 --- /dev/null +++ b/platforms/chibios/boards/IC_TEENSY_3_1/board/board.h @@ -0,0 +1,295 @@ +/* + ChibiOS - Copyright (C) 2015 RedoX https://github.com/RedoXyde + + 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 License 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. +*/ + +#ifndef _BOARD_H_ +#define _BOARD_H_ + +/* + * Setup for the PJRC Teensy 3.1 board. + */ + +/* + * Board identifier. + */ +#define BOARD_PJRC_TEENSY_3_1 +#define BOARD_NAME "PJRC Teensy 3.1" + +/* External 16 MHz crystal */ +#define KINETIS_XTAL_FREQUENCY 16000000UL + +/* Use internal capacitors for the crystal */ +#define KINETIS_BOARD_OSCILLATOR_SETTING OSC_CR_SC8P | OSC_CR_SC2P + +/* + * MCU type + */ +#define K20x7 + +/* + * IO pins assignments. + */ +#define PORTA_PIN0 0 +#define PORTA_PIN1 1 +#define PORTA_PIN2 2 +#define PORTA_PIN3 3 +#define TEENSY_PIN33 4 +#define TEENSY_PIN24 5 +#define PORTA_PIN6 6 +#define PORTA_PIN7 7 +#define PORTA_PIN8 8 +#define PORTA_PIN9 9 +#define PORTA_PIN10 10 +#define PORTA_PIN11 11 +#define TEENSY_PIN3 12 +#define TEENSY_PIN4 13 +#define PORTA_PIN14 14 +#define PORTA_PIN15 15 +#define PORTA_PIN16 16 +#define PORTA_PIN17 17 +#define PORTA_PIN18 18 +#define PORTA_PIN19 19 +#define PORTA_PIN20 20 +#define PORTA_PIN21 21 +#define PORTA_PIN22 22 +#define PORTA_PIN23 23 +#define PORTA_PIN24 24 +#define PORTA_PIN25 25 +#define PORTA_PIN26 26 +#define PORTA_PIN27 27 +#define PORTA_PIN28 28 +#define PORTA_PIN29 29 +#define PORTA_PIN30 30 +#define PORTA_PIN31 31 + +#define TEENSY_PIN3_IOPORT IOPORT1 +#define TEENSY_PIN4_IOPORT IOPORT1 +#define TEENSY_PIN24_IOPORT IOPORT1 +#define TEENSY_PIN33_IOPORT IOPORT1 + +#define TEENSY_PIN16 0 +#define TEENSY_PIN17 1 +#define TEENSY_PIN19 2 +#define TEENSY_PIN18 3 +#define PORTB_PIN4 4 +#define PORTB_PIN5 5 +#define PORTB_PIN6 6 +#define PORTB_PIN7 7 +#define PORTB_PIN8 8 +#define PORTB_PIN9 9 +#define PORTB_PIN10 10 +#define PORTB_PIN11 11 +#define PORTB_PIN12 12 +#define PORTB_PIN13 13 +#define PORTB_PIN14 14 +#define PORTB_PIN15 15 +#define TEENSY_PIN0 16 +#define TEENSY_PIN1 17 +#define TEENSY_PIN32 18 +#define TEENSY_PIN25 19 +#define PORTB_PIN20 20 +#define PORTB_PIN21 21 +#define PORTB_PIN22 22 +#define PORTB_PIN23 23 +#define PORTB_PIN24 24 +#define PORTB_PIN25 25 +#define PORTB_PIN26 26 +#define PORTB_PIN27 27 +#define PORTB_PIN28 28 +#define PORTB_PIN29 29 +#define PORTB_PIN30 30 +#define PORTB_PIN31 31 + +#define TEENSY_PIN0_IOPORT IOPORT2 +#define TEENSY_PIN1_IOPORT IOPORT2 +#define TEENSY_PIN16_IOPORT IOPORT2 +#define TEENSY_PIN17_IOPORT IOPORT2 +#define TEENSY_PIN18_IOPORT IOPORT2 +#define TEENSY_PIN19_IOPORT IOPORT2 +#define TEENSY_PIN25_IOPORT IOPORT2 +#define TEENSY_PIN32_IOPORT IOPORT2 + +#define TEENSY_PIN15 0 +#define TEENSY_PIN22 1 +#define TEENSY_PIN23 2 +#define TEENSY_PIN9 3 +#define TEENSY_PIN10 4 +#define TEENSY_PIN13 5 +#define TEENSY_PIN11 6 +#define TEENSY_PIN12 7 +#define TEENSY_PIN28 8 +#define TEENSY_PIN27 9 +#define TEENSY_PIN29 10 +#define TEENSY_PIN30 11 +#define PORTC_PIN12 12 +#define PORTC_PIN13 13 +#define PORTC_PIN14 14 +#define PORTC_PIN15 15 +#define PORTC_PIN16 16 +#define PORTC_PIN17 17 +#define PORTC_PIN18 18 +#define PORTC_PIN19 19 +#define PORTC_PIN20 20 +#define PORTC_PIN21 21 +#define PORTC_PIN22 22 +#define PORTC_PIN23 23 +#define PORTC_PIN24 24 +#define PORTC_PIN25 25 +#define PORTC_PIN26 26 +#define PORTC_PIN27 27 +#define PORTC_PIN28 28 +#define PORTC_PIN29 29 +#define PORTC_PIN30 30 +#define PORTC_PIN31 31 + +#define TEENSY_PIN9_IOPORT IOPORT3 +#define TEENSY_PIN10_IOPORT IOPORT3 +#define TEENSY_PIN11_IOPORT IOPORT3 +#define TEENSY_PIN12_IOPORT IOPORT3 +#define TEENSY_PIN13_IOPORT IOPORT3 +#define TEENSY_PIN15_IOPORT IOPORT3 +#define TEENSY_PIN22_IOPORT IOPORT3 +#define TEENSY_PIN23_IOPORT IOPORT3 +#define TEENSY_PIN27_IOPORT IOPORT3 +#define TEENSY_PIN28_IOPORT IOPORT3 +#define TEENSY_PIN29_IOPORT IOPORT3 +#define TEENSY_PIN30_IOPORT IOPORT3 + +#define TEENSY_PIN2 0 +#define TEENSY_PIN14 1 +#define TEENSY_PIN7 2 +#define TEENSY_PIN8 3 +#define TEENSY_PIN6 4 +#define TEENSY_PIN20 5 +#define TEENSY_PIN21 6 +#define TEENSY_PIN5 7 +#define PORTD_PIN8 8 +#define PORTD_PIN9 9 +#define PORTD_PIN10 10 +#define PORTD_PIN11 11 +#define PORTD_PIN12 12 +#define PORTD_PIN13 13 +#define PORTD_PIN14 14 +#define PORTD_PIN15 15 +#define PORTD_PIN16 16 +#define PORTD_PIN17 17 +#define PORTD_PIN18 18 +#define PORTD_PIN19 19 +#define PORTD_PIN20 20 +#define PORTD_PIN21 21 +#define PORTD_PIN22 22 +#define PORTD_PIN23 23 +#define PORTD_PIN24 24 +#define PORTD_PIN25 25 +#define PORTD_PIN26 26 +#define PORTD_PIN27 27 +#define PORTD_PIN28 28 +#define PORTD_PIN29 29 +#define PORTD_PIN30 30 +#define PORTD_PIN31 31 + +#define TEENSY_PIN2_IOPORT IOPORT4 +#define TEENSY_PIN5_IOPORT IOPORT4 +#define TEENSY_PIN6_IOPORT IOPORT4 +#define TEENSY_PIN7_IOPORT IOPORT4 +#define TEENSY_PIN8_IOPORT IOPORT4 +#define TEENSY_PIN14_IOPORT IOPORT4 +#define TEENSY_PIN20_IOPORT IOPORT4 +#define TEENSY_PIN21_IOPORT IOPORT4 + +#define TEENSY_PIN31 0 +#define TEENSY_PIN26 1 +#define PORTE_PIN2 2 +#define PORTE_PIN3 3 +#define PORTE_PIN4 4 +#define PORTE_PIN5 5 +#define PORTE_PIN6 6 +#define PORTE_PIN7 7 +#define PORTE_PIN8 8 +#define PORTE_PIN9 9 +#define PORTE_PIN10 10 +#define PORTE_PIN11 11 +#define PORTE_PIN12 12 +#define PORTE_PIN13 13 +#define PORTE_PIN14 14 +#define PORTE_PIN15 15 +#define PORTE_PIN16 16 +#define PORTE_PIN17 17 +#define PORTE_PIN18 18 +#define PORTE_PIN19 19 +#define PORTE_PIN20 20 +#define PORTE_PIN21 21 +#define PORTE_PIN22 22 +#define PORTE_PIN23 23 +#define PORTE_PIN24 24 +#define PORTE_PIN25 25 +#define PORTE_PIN26 26 +#define PORTE_PIN27 27 +#define PORTE_PIN28 28 +#define PORTE_PIN29 29 +#define PORTE_PIN30 30 +#define PORTE_PIN31 31 + +#define TEENSY_PIN26_IOPORT IOPORT5 +#define TEENSY_PIN31_IOPORT IOPORT5 + +#define LINE_PIN1 PAL_LINE(TEENSY_PIN1_IOPORT, TEENSY_PIN1) +#define LINE_PIN2 PAL_LINE(TEENSY_PIN2_IOPORT, TEENSY_PIN2) +#define LINE_PIN3 PAL_LINE(TEENSY_PIN3_IOPORT, TEENSY_PIN3) +#define LINE_PIN4 PAL_LINE(TEENSY_PIN4_IOPORT, TEENSY_PIN4) +#define LINE_PIN5 PAL_LINE(TEENSY_PIN5_IOPORT, TEENSY_PIN5) +#define LINE_PIN6 PAL_LINE(TEENSY_PIN6_IOPORT, TEENSY_PIN6) +#define LINE_PIN7 PAL_LINE(TEENSY_PIN7_IOPORT, TEENSY_PIN7) +#define LINE_PIN8 PAL_LINE(TEENSY_PIN8_IOPORT, TEENSY_PIN8) +#define LINE_PIN9 PAL_LINE(TEENSY_PIN9_IOPORT, TEENSY_PIN9) +#define LINE_PIN10 PAL_LINE(TEENSY_PIN10_IOPORT, TEENSY_PIN10) +#define LINE_PIN11 PAL_LINE(TEENSY_PIN11_IOPORT, TEENSY_PIN11) +#define LINE_PIN12 PAL_LINE(TEENSY_PIN12_IOPORT, TEENSY_PIN12) +#define LINE_PIN13 PAL_LINE(TEENSY_PIN13_IOPORT, TEENSY_PIN13) +#define LINE_PIN14 PAL_LINE(TEENSY_PIN14_IOPORT, TEENSY_PIN14) +#define LINE_PIN15 PAL_LINE(TEENSY_PIN15_IOPORT, TEENSY_PIN15) +#define LINE_PIN16 PAL_LINE(TEENSY_PIN16_IOPORT, TEENSY_PIN16) +#define LINE_PIN17 PAL_LINE(TEENSY_PIN17_IOPORT, TEENSY_PIN17) +#define LINE_PIN18 PAL_LINE(TEENSY_PIN18_IOPORT, TEENSY_PIN18) +#define LINE_PIN19 PAL_LINE(TEENSY_PIN19_IOPORT, TEENSY_PIN19) +#define LINE_PIN20 PAL_LINE(TEENSY_PIN20_IOPORT, TEENSY_PIN20) +#define LINE_PIN21 PAL_LINE(TEENSY_PIN21_IOPORT, TEENSY_PIN21) +#define LINE_PIN22 PAL_LINE(TEENSY_PIN22_IOPORT, TEENSY_PIN22) +#define LINE_PIN23 PAL_LINE(TEENSY_PIN23_IOPORT, TEENSY_PIN23) +#define LINE_PIN24 PAL_LINE(TEENSY_PIN24_IOPORT, TEENSY_PIN24) +#define LINE_PIN25 PAL_LINE(TEENSY_PIN25_IOPORT, TEENSY_PIN25) +#define LINE_PIN25 PAL_LINE(TEENSY_PIN25_IOPORT, TEENSY_PIN25) +#define LINE_PIN26 PAL_LINE(TEENSY_PIN26_IOPORT, TEENSY_PIN26) +#define LINE_PIN27 PAL_LINE(TEENSY_PIN27_IOPORT, TEENSY_PIN27) +#define LINE_PIN28 PAL_LINE(TEENSY_PIN28_IOPORT, TEENSY_PIN28) +#define LINE_PIN29 PAL_LINE(TEENSY_PIN29_IOPORT, TEENSY_PIN29) +#define LINE_PIN30 PAL_LINE(TEENSY_PIN30_IOPORT, TEENSY_PIN30) +#define LINE_PIN31 PAL_LINE(TEENSY_PIN31_IOPORT, TEENSY_PIN31) +#define LINE_PIN32 PAL_LINE(TEENSY_PIN32_IOPORT, TEENSY_PIN32) +#define LINE_PIN33 PAL_LINE(TEENSY_PIN33_IOPORT, TEENSY_PIN33) + +#define LINE_LED LINE_PIN13 + +#if !defined(_FROM_ASM_) +# ifdef __cplusplus +extern "C" { +# endif +void boardInit(void); +# ifdef __cplusplus +} +# endif +#endif /* _FROM_ASM_ */ + +#endif /* _BOARD_H_ */ diff --git a/platforms/chibios/boards/IC_TEENSY_3_1/board/board.mk b/platforms/chibios/boards/IC_TEENSY_3_1/board/board.mk new file mode 100644 index 0000000000..842e335905 --- /dev/null +++ b/platforms/chibios/boards/IC_TEENSY_3_1/board/board.mk @@ -0,0 +1,9 @@ +# List of all the board related files. +BOARDSRC = $(BOARD_PATH)/board/board.c + +# Required include directories +BOARDINC = $(BOARD_PATH)/board + +# Shared variables +ALLCSRC += $(BOARDSRC) +ALLINC += $(BOARDINC) diff --git a/platforms/chibios/boards/IC_TEENSY_4_1/board/board.mk b/platforms/chibios/boards/IC_TEENSY_4_1/board/board.mk new file mode 100644 index 0000000000..bc242ac3c5 --- /dev/null +++ b/platforms/chibios/boards/IC_TEENSY_4_1/board/board.mk @@ -0,0 +1 @@ +include $(CHIBIOS_CONTRIB)/os/hal/boards/PJRC_TEENSY_4_1/board.mk diff --git a/platforms/chibios/boards/IC_TEENSY_4_1/rules.mk b/platforms/chibios/boards/IC_TEENSY_4_1/rules.mk new file mode 100644 index 0000000000..0c62d209c5 --- /dev/null +++ b/platforms/chibios/boards/IC_TEENSY_4_1/rules.mk @@ -0,0 +1 @@ +TEENSY_LOADER_CLI_MCU = imxrt1062 diff --git a/platforms/chibios/boards/QMK_PROTON_C/board/board.mk b/platforms/chibios/boards/QMK_PROTON_C/board/board.mk new file mode 100644 index 0000000000..f891e65247 --- /dev/null +++ b/platforms/chibios/boards/QMK_PROTON_C/board/board.mk @@ -0,0 +1,9 @@ +# List of all the board related files. +BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_STM32F3_DISCOVERY/board.c + +# Required include directories +BOARDINC = $(CHIBIOS)/os/hal/boards/ST_STM32F3_DISCOVERY + +# Shared variables +ALLCSRC += $(BOARDSRC) +ALLINC += $(BOARDINC) diff --git a/platforms/chibios/boards/QMK_PROTON_C/configs/board.h b/platforms/chibios/boards/QMK_PROTON_C/configs/board.h new file mode 100644 index 0000000000..97159964d0 --- /dev/null +++ b/platforms/chibios/boards/QMK_PROTON_C/configs/board.h @@ -0,0 +1,37 @@ +/* Copyright 2020 Nick Brassel (tzarc) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#include_next "board.h" + +#undef STM32_HSE_BYPASS + +/* + * USB bus activation macro, required by the USB driver. + */ +#define usb_lld_connect_bus(usbp) \ + do { \ + palSetPadMode(GPIOA, GPIOA_USB_DP, PAL_MODE_ALTERNATE(14)); \ + } while (0) + +/* + * USB bus de-activation macro, required by the USB driver. + */ +#define usb_lld_disconnect_bus(usbp) \ + do { \ + palSetPadMode(GPIOA, GPIOA_USB_DP, PAL_MODE_OUTPUT_PUSHPULL); \ + palClearPad(GPIOA, GPIOA_USB_DP); \ + } while (0) diff --git a/platforms/chibios/boards/QMK_PROTON_C/configs/bootloader_defs.h b/platforms/chibios/boards/QMK_PROTON_C/configs/bootloader_defs.h new file mode 100644 index 0000000000..3b0e9d20a6 --- /dev/null +++ b/platforms/chibios/boards/QMK_PROTON_C/configs/bootloader_defs.h @@ -0,0 +1,7 @@ +/* Address for jumping to bootloader on STM32 chips. */ +/* It is chip dependent, the correct number can be looked up here: + * http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf + * This also requires a patch to chibios: + * /tmk_core/tool/chibios/ch-bootloader-jump.patch + */ +#define STM32_BOOTLOADER_ADDRESS 0x1FFFD800 diff --git a/platforms/chibios/boards/QMK_PROTON_C/configs/chconf.h b/platforms/chibios/boards/QMK_PROTON_C/configs/chconf.h new file mode 100644 index 0000000000..a1cbf68086 --- /dev/null +++ b/platforms/chibios/boards/QMK_PROTON_C/configs/chconf.h @@ -0,0 +1,756 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + 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 License 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. +*/ + +/** + * @file rt/templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ +#define _CHIBIOS_RT_CONF_VER_6_1_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#if !defined(CH_CFG_ST_RESOLUTION) +#define CH_CFG_ST_RESOLUTION 32 +#endif + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#if !defined(CH_CFG_ST_FREQUENCY) +#define CH_CFG_ST_FREQUENCY 100000 +#endif + +/** + * @brief Time intervals data size. + * @note Allowed values are 16, 32 or 64 bits. + */ +#if !defined(CH_CFG_INTERVALS_SIZE) +#define CH_CFG_INTERVALS_SIZE 32 +#endif + +/** + * @brief Time types data size. + * @note Allowed values are 16 or 32 bits. + */ +#if !defined(CH_CFG_TIME_TYPES_SIZE) +#define CH_CFG_TIME_TYPES_SIZE 32 +#endif + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#if !defined(CH_CFG_ST_TIMEDELTA) +#define CH_CFG_ST_TIMEDELTA 2 +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#if !defined(CH_CFG_TIME_QUANTUM) +#define CH_CFG_TIME_QUANTUM 0 +#endif + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#if !defined(CH_CFG_NO_IDLE_THREAD) +#define CH_CFG_NO_IDLE_THREAD FALSE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_OPTIMIZE_SPEED) +#define CH_CFG_OPTIMIZE_SPEED TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_TM) +#define CH_CFG_USE_TM TRUE +#endif + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_REGISTRY) +#define CH_CFG_USE_REGISTRY TRUE +#endif + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_WAITEXIT) +#define CH_CFG_USE_WAITEXIT TRUE +#endif + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_SEMAPHORES) +#define CH_CFG_USE_SEMAPHORES TRUE +#endif + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#if !defined(CH_CFG_USE_SEMAPHORES_PRIORITY) +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE +#endif + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MUTEXES) +#define CH_CFG_USE_MUTEXES TRUE +#endif + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#if !defined(CH_CFG_USE_MUTEXES_RECURSIVE) +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE +#endif + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#if !defined(CH_CFG_USE_CONDVARS) +#define CH_CFG_USE_CONDVARS TRUE +#endif + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#if !defined(CH_CFG_USE_CONDVARS_TIMEOUT) +#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE +#endif + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_EVENTS) +#define CH_CFG_USE_EVENTS TRUE +#endif + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#if !defined(CH_CFG_USE_EVENTS_TIMEOUT) +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE +#endif + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MESSAGES) +#define CH_CFG_USE_MESSAGES TRUE +#endif + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#if !defined(CH_CFG_USE_MESSAGES_PRIORITY) +#define CH_CFG_USE_MESSAGES_PRIORITY TRUE +#endif + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#if !defined(CH_CFG_USE_DYNAMIC) +#define CH_CFG_USE_DYNAMIC TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name OSLIB options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#if !defined(CH_CFG_USE_MAILBOXES) +#define CH_CFG_USE_MAILBOXES TRUE +#endif + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MEMCORE) +#define CH_CFG_USE_MEMCORE TRUE +#endif + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#if !defined(CH_CFG_MEMCORE_SIZE) +#define CH_CFG_MEMCORE_SIZE 0 +#endif + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#if !defined(CH_CFG_USE_HEAP) +#define CH_CFG_USE_HEAP TRUE +#endif + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MEMPOOLS) +#define CH_CFG_USE_MEMPOOLS TRUE +#endif + +/** + * @brief Objects FIFOs APIs. + * @details If enabled then the objects FIFOs APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_OBJ_FIFOS) +#define CH_CFG_USE_OBJ_FIFOS TRUE +#endif + +/** + * @brief Pipes APIs. + * @details If enabled then the pipes APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_PIPES) +#define CH_CFG_USE_PIPES TRUE +#endif + +/** + * @brief Objects Caches APIs. + * @details If enabled then the objects caches APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_OBJ_CACHES) +#define CH_CFG_USE_OBJ_CACHES FALSE +#endif + +/** + * @brief Delegate threads APIs. + * @details If enabled then the delegate threads APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_DELEGATES) +#define CH_CFG_USE_DELEGATES FALSE +#endif + +/** + * @brief Jobs Queues APIs. + * @details If enabled then the jobs queues APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_JOBS) +#define CH_CFG_USE_JOBS FALSE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Objects factory options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Objects Factory APIs. + * @details If enabled then the objects factory APIs are included in the + * kernel. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_CFG_USE_FACTORY) +#define CH_CFG_USE_FACTORY FALSE +#endif + +/** + * @brief Maximum length for object names. + * @details If the specified length is zero then the name is stored by + * pointer but this could have unintended side effects. + */ +#if !defined(CH_CFG_FACTORY_MAX_NAMES_LENGTH) +#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 +#endif + +/** + * @brief Enables the registry of generic objects. + */ +#if !defined(CH_CFG_FACTORY_OBJECTS_REGISTRY) +#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE +#endif + +/** + * @brief Enables factory for generic buffers. + */ +#if !defined(CH_CFG_FACTORY_GENERIC_BUFFERS) +#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE +#endif + +/** + * @brief Enables factory for semaphores. + */ +#if !defined(CH_CFG_FACTORY_SEMAPHORES) +#define CH_CFG_FACTORY_SEMAPHORES TRUE +#endif + +/** + * @brief Enables factory for mailboxes. + */ +#if !defined(CH_CFG_FACTORY_MAILBOXES) +#define CH_CFG_FACTORY_MAILBOXES TRUE +#endif + +/** + * @brief Enables factory for objects FIFOs. + */ +#if !defined(CH_CFG_FACTORY_OBJ_FIFOS) +#define CH_CFG_FACTORY_OBJ_FIFOS TRUE +#endif + +/** + * @brief Enables factory for Pipes. + */ +#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_PIPES TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_STATISTICS) +#define CH_DBG_STATISTICS FALSE +#endif + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_SYSTEM_STATE_CHECK) +#define CH_DBG_SYSTEM_STATE_CHECK FALSE +#endif + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_ENABLE_CHECKS) +#define CH_DBG_ENABLE_CHECKS FALSE +#endif + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_ENABLE_ASSERTS) +#define CH_DBG_ENABLE_ASSERTS FALSE +#endif + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#if !defined(CH_DBG_TRACE_MASK) +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED +#endif + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#if !defined(CH_DBG_TRACE_BUFFER_SIZE) +#define CH_DBG_TRACE_BUFFER_SIZE 128 +#endif + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#if !defined(CH_DBG_ENABLE_STACK_CHECK) +#define CH_DBG_ENABLE_STACK_CHECK TRUE +#endif + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_FILL_THREADS) +#define CH_DBG_FILL_THREADS FALSE +#endif + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#if !defined(CH_DBG_THREADS_PROFILING) +#define CH_DBG_THREADS_PROFILING FALSE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System structure extension. + * @details User fields added to the end of the @p ch_system_t structure. + */ +#define CH_CFG_SYSTEM_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief System initialization hook. + * @details User initialization code added to the @p chSysInit() function + * just before interrupts are enabled globally. + */ +#define CH_CFG_SYSTEM_INIT_HOOK() { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p _thread_init() function. + * + * @note It is invoked from within @p _thread_init() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/platforms/chibios/boards/QMK_PROTON_C/configs/config.h b/platforms/chibios/boards/QMK_PROTON_C/configs/config.h new file mode 100644 index 0000000000..a73f0c0b47 --- /dev/null +++ b/platforms/chibios/boards/QMK_PROTON_C/configs/config.h @@ -0,0 +1,20 @@ +/* Copyright 2020 Nick Brassel (tzarc) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP +# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE +#endif diff --git a/platforms/chibios/boards/QMK_PROTON_C/configs/halconf.h b/platforms/chibios/boards/QMK_PROTON_C/configs/halconf.h new file mode 100644 index 0000000000..d7a639a6d0 --- /dev/null +++ b/platforms/chibios/boards/QMK_PROTON_C/configs/halconf.h @@ -0,0 +1,531 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + 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 License 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. +*/ + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#define _CHIBIOS_HAL_CONF_ +#define _CHIBIOS_HAL_CONF_VER_7_1_ + +#include + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +#define HAL_USE_ADC FALSE +#endif + +/** + * @brief Enables the CAN subsystem. + */ +#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +#define HAL_USE_CAN FALSE +#endif + +/** + * @brief Enables the cryptographic subsystem. + */ +#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) +#define HAL_USE_CRY FALSE +#endif + +/** + * @brief Enables the DAC subsystem. + */ +#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +#define HAL_USE_DAC TRUE +#endif + +/** + * @brief Enables the EFlash subsystem. + */ +#if !defined(HAL_USE_EFL) || defined(__DOXYGEN__) +#define HAL_USE_EFL FALSE +#endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT TRUE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +#define HAL_USE_I2C TRUE +#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +#define HAL_USE_MAC FALSE +#endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +#define HAL_USE_PWM TRUE +#endif + +/** + * @brief Enables the RTC subsystem. + */ +#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +#define HAL_USE_RTC FALSE +#endif + +/** + * @brief Enables the SDC subsystem. + */ +#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +#define HAL_USE_SDC FALSE +#endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL FALSE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB TRUE +#endif + +/** + * @brief Enables the SIO subsystem. + */ +#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__) +#define HAL_USE_SIO FALSE +#endif + +/** + * @brief Enables the SPI subsystem. + */ +#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +#define HAL_USE_SPI TRUE +#endif + +/** + * @brief Enables the TRNG subsystem. + */ +#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__) +#define HAL_USE_TRNG FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +#if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +#define HAL_USE_UART FALSE +#endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB TRUE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +#define HAL_USE_WDG FALSE +#endif + +/** + * @brief Enables the WSPI subsystem. + */ +#if !defined(HAL_USE_WSPI) || defined(__DOXYGEN__) +#define HAL_USE_WSPI FALSE +#endif + +/*===========================================================================*/ +/* PAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) +#define PAL_USE_CALLBACKS TRUE +#endif + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) +#define PAL_USE_WAIT TRUE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + +/** + * @brief Enforces the driver to use direct callbacks rather than OSAL events. + */ +#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__) +#define CAN_ENFORCE_USE_CALLBACKS FALSE +#endif + +/*===========================================================================*/ +/* CRY driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the SW fall-back of the cryptographic driver. + * @details When enabled, this option, activates a fall-back software + * implementation for algorithms not supported by the underlying + * hardware. + * @note Fall-back implementations may not be present for all algorithms. + */ +#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_USE_FALLBACK FALSE +#endif + +/** + * @brief Makes the driver forcibly use the fall-back implementations. + */ +#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_ENFORCE_FALLBACK FALSE +#endif + +/*===========================================================================*/ +/* DAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) +#define DAC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define DAC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the zero-copy API. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/** + * @brief OCR initialization constant for V20 cards. + */ +#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__) +#define SDC_INIT_OCR_V20 0x50FF8000U +#endif + +/** + * @brief OCR initialization constant for non-V20 cards. + */ +#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__) +#define SDC_INIT_OCR 0x80100000U +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 38400 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 128 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 1 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 2 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables circular transfers APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__) +#define SPI_USE_CIRCULAR FALSE +#endif + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT FALSE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION FALSE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT TRUE +#endif + +/*===========================================================================*/ +/* WSPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) +#define WSPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define WSPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +#endif /* HALCONF_H */ + +/** @} */ diff --git a/platforms/chibios/boards/QMK_PROTON_C/configs/mcuconf.h b/platforms/chibios/boards/QMK_PROTON_C/configs/mcuconf.h new file mode 100644 index 0000000000..4d7b586c08 --- /dev/null +++ b/platforms/chibios/boards/QMK_PROTON_C/configs/mcuconf.h @@ -0,0 +1,273 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + 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 License 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. +*/ + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F3xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F3xx_MCUCONF +#define STM32F303_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_HSI_ENABLED TRUE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED FALSE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PREDIV_VALUE 1 +#define STM32_PLLMUL_VALUE 9 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV2 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK +#define STM32_ADC12PRES STM32_ADC12PRES_DIV1 +#define STM32_ADC34PRES STM32_ADC34PRES_DIV1 +#define STM32_USART1SW STM32_USART1SW_PCLK +#define STM32_USART2SW STM32_USART2SW_PCLK +#define STM32_USART3SW STM32_USART3SW_PCLK +#define STM32_UART4SW STM32_UART4SW_PCLK +#define STM32_UART5SW STM32_UART5SW_PCLK +#define STM32_I2C1SW STM32_I2C1SW_SYSCLK +#define STM32_I2C2SW STM32_I2C2SW_SYSCLK +#define STM32_TIM1SW STM32_TIM1SW_PCLK2 +#define STM32_TIM8SW STM32_TIM8SW_PCLK2 +#define STM32_RTCSEL STM32_RTCSEL_LSI +#define STM32_USB_CLOCK_REQUIRED TRUE +#define STM32_USBPRE STM32_USBPRE_DIV1P5 + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 15 +#define STM32_IRQ_EXTI20_PRIORITY 15 +#define STM32_IRQ_EXTI21_22_29_PRIORITY 6 +#define STM32_IRQ_EXTI30_32_PRIORITY 6 +#define STM32_IRQ_EXTI33_PRIORITY 6 +#define STM32_IRQ_TIM1_BRK_TIM15_PRIORITY 7 +#define STM32_IRQ_TIM1_UP_TIM16_PRIORITY 7 +#define STM32_IRQ_TIM1_TRGCO_TIM17_PRIORITY 7 +#define STM32_IRQ_TIM1_CC_PRIORITY 7 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_DUAL_MODE FALSE +#define STM32_ADC_COMPACT_SAMPLES FALSE +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_USE_ADC2 FALSE +#define STM32_ADC_USE_ADC3 FALSE +#define STM32_ADC_USE_ADC4 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_ADC_ADC4_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#define STM32_ADC_ADC4_DMA_PRIORITY 2 +#define STM32_ADC_ADC12_IRQ_PRIORITY 5 +#define STM32_ADC_ADC3_IRQ_PRIORITY 5 +#define STM32_ADC_ADC4_IRQ_PRIORITY 5 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 5 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 5 +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 5 +#define STM32_ADC_ADC4_DMA_IRQ_PRIORITY 5 +#define STM32_ADC_ADC12_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1 +#define STM32_ADC_ADC34_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 TRUE +#define STM32_DAC_USE_DAC1_CH2 TRUE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM6 TRUE +#define STM32_GPT_USE_TIM7 TRUE +#define STM32_GPT_USE_TIM8 TRUE +#define STM32_GPT_USE_TIM15 TRUE +#define STM32_GPT_USE_TIM16 FALSE +#define STM32_GPT_USE_TIM17 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 TRUE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_IRQ_PRIORITY 10 +#define STM32_I2C_I2C2_IRQ_PRIORITY 10 +#define STM32_I2C_USE_DMA TRUE +#define STM32_I2C_I2C1_DMA_PRIORITY 1 +#define STM32_I2C_I2C2_DMA_PRIORITY 1 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM15 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED FALSE +#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 TRUE +#define STM32_PWM_USE_TIM4 TRUE +#define STM32_PWM_USE_TIM8 FALSE +#define STM32_PWM_USE_TIM15 FALSE +#define STM32_PWM_USE_TIM16 FALSE +#define STM32_PWM_USE_TIM17 FALSE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 + +/* + * RTC driver system settings. + */ +#define STM32_RTC_PRESA_VALUE 32 +#define STM32_RTC_PRESS_VALUE 1024 +#define STM32_RTC_CR_INIT 0 +#define STM32_RTC_TAMPCR_INIT 0 + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 TRUE +#define STM32_SERIAL_USE_USART2 FALSE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 TRUE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_USB1 TRUE +#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE +#define STM32_USB_USB1_HP_IRQ_PRIORITY 13 +#define STM32_USB_USB1_LP_IRQ_PRIORITY 14 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG FALSE + +#endif /* MCUCONF_H */ diff --git a/platforms/chibios/boards/QMK_PROTON_C/convert_to_proton_c.mk b/platforms/chibios/boards/QMK_PROTON_C/convert_to_proton_c.mk new file mode 100644 index 0000000000..0618154678 --- /dev/null +++ b/platforms/chibios/boards/QMK_PROTON_C/convert_to_proton_c.mk @@ -0,0 +1,10 @@ +# Proton C MCU settings for converting AVR projects +TARGET := $(TARGET)_proton_c +MCU := STM32F303 +BOARD := QMK_PROTON_C +BOOTLOADER := stm32-dfu +OPT_DEFS += -DCONVERT_TO_PROTON_C + +# These are defaults based on what has been implemented for ARM boards +AUDIO_ENABLE ?= yes +WS2812_DRIVER ?= bitbang diff --git a/platforms/chibios/boards/STM32_F103_STM32DUINO/board/board.c b/platforms/chibios/boards/STM32_F103_STM32DUINO/board/board.c new file mode 100644 index 0000000000..8a34e81f25 --- /dev/null +++ b/platforms/chibios/boards/STM32_F103_STM32DUINO/board/board.c @@ -0,0 +1,59 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio + + 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 License 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. +*/ + +#include + +// Value to place in RTC backup register 10 for persistent bootloader mode +#define RTC_BOOTLOADER_FLAG 0x424C + +/** + * @brief PAL setup. + * @details Digital I/O ports static configuration as defined in @p board.h. + * This variable is used by the HAL when initializing the PAL driver. + */ +#if HAL_USE_PAL || defined(__DOXYGEN__) +const PALConfig pal_default_config = +{ + {VAL_GPIOAODR, VAL_GPIOACRL, VAL_GPIOACRH}, + {VAL_GPIOBODR, VAL_GPIOBCRL, VAL_GPIOBCRH}, + {VAL_GPIOCODR, VAL_GPIOCCRL, VAL_GPIOCCRH}, + {VAL_GPIODODR, VAL_GPIODCRL, VAL_GPIODCRH}, + {VAL_GPIOEODR, VAL_GPIOECRL, VAL_GPIOECRH}, +}; +#endif + +__attribute__((weak)) void enter_bootloader_mode_if_requested(void) {} + +/* + * Early initialization code. + * This initialization must be performed just after stack setup and before + * any other initialization. + */ +void __early_init(void) { + enter_bootloader_mode_if_requested(); + + stm32_clock_init(); +} + +/* + * Board-specific initialization code. + */ +void boardInit(void) { + //JTAG-DP Disabled and SW-DP Enabled + AFIO->MAPR |= AFIO_MAPR_SWJ_CFG_JTAGDISABLE; + //Set backup register DR10 to enter bootloader on reset + BKP->DR10 = RTC_BOOTLOADER_FLAG; +} diff --git a/platforms/chibios/boards/STM32_F103_STM32DUINO/board/board.h b/platforms/chibios/boards/STM32_F103_STM32DUINO/board/board.h new file mode 100644 index 0000000000..09d182d6ca --- /dev/null +++ b/platforms/chibios/boards/STM32_F103_STM32DUINO/board/board.h @@ -0,0 +1,166 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio + + 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 License 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. +*/ + +#ifndef _BOARD_H_ +#define _BOARD_H_ + +/* + * Setup for a Generic STM32F103 board. + */ + +/* + * Board identifier. + */ +#define BOARD_STM32_F103_STM32DUINO +#define BOARD_NAME "GENERIC STM32F103C8T6 board - stm32duino bootloader" + +/* + * Board frequencies. + */ +#define STM32_LSECLK 32768 +#define STM32_HSECLK 8000000 + +/* + * MCU type, supported types are defined in ./os/hal/platforms/hal_lld.h. + */ +#define STM32F103xB + +/* + * IO pins assignments + */ + +/* on-board */ + +#define GPIOA_LED 8 +#define GPIOD_OSC_IN 0 +#define GPIOD_OSC_OUT 1 + +/* In case your board has a "USB enable" hardware + controlled by a pin, define it here. (It could be just + a 1.5k resistor connected to D+ line.) +*/ +/* +#define GPIOB_USB_DISC 10 +*/ + +/* + * I/O ports initial setup, this configuration is established soon after reset + * in the initialization code. + * + * The digits have the following meaning: + * 0 - Analog input. + * 1 - Push Pull output 10MHz. + * 2 - Push Pull output 2MHz. + * 3 - Push Pull output 50MHz. + * 4 - Digital input. + * 5 - Open Drain output 10MHz. + * 6 - Open Drain output 2MHz. + * 7 - Open Drain output 50MHz. + * 8 - Digital input with PullUp or PullDown resistor depending on ODR. + * 9 - Alternate Push Pull output 10MHz. + * A - Alternate Push Pull output 2MHz. + * B - Alternate Push Pull output 50MHz. + * C - Reserved. + * D - Alternate Open Drain output 10MHz. + * E - Alternate Open Drain output 2MHz. + * F - Alternate Open Drain output 50MHz. + * Please refer to the STM32 Reference Manual for details. + */ + +/* + * Port A setup. + * Everything input with pull-up except: + * PA2 - Alternate output (USART2 TX). + * PA3 - Normal input (USART2 RX). + * PA9 - Alternate output (USART1 TX). + * PA10 - Normal input (USART1 RX). + */ +#define VAL_GPIOACRL 0x88884B88 /* PA7...PA0 */ +#define VAL_GPIOACRH 0x888884B8 /* PA15...PA8 */ +#define VAL_GPIOAODR 0xFFFFFFFF + +/* + * Port B setup. + * Everything input with pull-up except: + * PB10 - Push Pull output (USB switch). + */ +#define VAL_GPIOBCRL 0x88888888 /* PB7...PB0 */ +#define VAL_GPIOBCRH 0x88888388 /* PB15...PB8 */ +#define VAL_GPIOBODR 0xFFFFFFFF + +/* + * Port C setup. + * Everything input with pull-up except: + * PC13 - Push Pull output (LED). + */ +#define VAL_GPIOCCRL 0x88888888 /* PC7...PC0 */ +#define VAL_GPIOCCRH 0x88388888 /* PC15...PC8 */ +#define VAL_GPIOCODR 0xFFFFFFFF + +/* + * Port D setup. + * Everything input with pull-up except: + * PD0 - Normal input (XTAL). + * PD1 - Normal input (XTAL). + */ +#define VAL_GPIODCRL 0x88888844 /* PD7...PD0 */ +#define VAL_GPIODCRH 0x88888888 /* PD15...PD8 */ +#define VAL_GPIODODR 0xFFFFFFFF + +/* + * Port E setup. + * Everything input with pull-up except: + */ +#define VAL_GPIOECRL 0x88888888 /* PE7...PE0 */ +#define VAL_GPIOECRH 0x88888888 /* PE15...PE8 */ +#define VAL_GPIOEODR 0xFFFFFFFF + +/* + * USB bus activation macro, required by the USB driver. + */ +/* The point is that most of the generic STM32F103* boards + have a 1.5k resistor connected on one end to the D+ line + and on the other end to some pin. Or even a slightly more + complicated "USB enable" circuit, controlled by a pin. + That should go here. + + However on some boards (e.g. one that I have), there's no + such hardware. In which case it's better to not do anything. +*/ +/* +#define usb_lld_connect_bus(usbp) palClearPad(GPIOB, GPIOB_USB_DISC) +*/ +#define usb_lld_connect_bus(usbp) palSetPadMode(GPIOA, 12, PAL_MODE_INPUT); + +/* + * USB bus de-activation macro, required by the USB driver. + */ +/* +#define usb_lld_disconnect_bus(usbp) palSetPad(GPIOB, GPIOB_USB_DISC) +*/ +#define usb_lld_disconnect_bus(usbp) palSetPadMode(GPIOA, 12, PAL_MODE_OUTPUT_PUSHPULL); palClearPad(GPIOA, 12); + +#if !defined(_FROM_ASM_) +#ifdef __cplusplus +extern "C" { +#endif + void boardInit(void); +#ifdef __cplusplus +} +#endif +#endif /* _FROM_ASM_ */ + +#endif /* _BOARD_H_ */ diff --git a/platforms/chibios/boards/STM32_F103_STM32DUINO/board/board.mk b/platforms/chibios/boards/STM32_F103_STM32DUINO/board/board.mk new file mode 100644 index 0000000000..842e335905 --- /dev/null +++ b/platforms/chibios/boards/STM32_F103_STM32DUINO/board/board.mk @@ -0,0 +1,9 @@ +# List of all the board related files. +BOARDSRC = $(BOARD_PATH)/board/board.c + +# Required include directories +BOARDINC = $(BOARD_PATH)/board + +# Shared variables +ALLCSRC += $(BOARDSRC) +ALLINC += $(BOARDINC) diff --git a/platforms/chibios/boards/STM32_F103_STM32DUINO/configs/mcuconf.h b/platforms/chibios/boards/STM32_F103_STM32DUINO/configs/mcuconf.h new file mode 100644 index 0000000000..9945e7408d --- /dev/null +++ b/platforms/chibios/boards/STM32_F103_STM32DUINO/configs/mcuconf.h @@ -0,0 +1,209 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio + + 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 License 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. +*/ + +#ifndef _MCUCONF_H_ +#define _MCUCONF_H_ + +#define STM32F103_MCUCONF + +/* + * STM32F103 drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_HSI_ENABLED TRUE +#define STM32_LSI_ENABLED FALSE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED FALSE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1 +#define STM32_PLLMUL_VALUE 9 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV2 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_ADCPRE STM32_ADCPRE_DIV4 +#define STM32_USB_CLOCK_REQUIRED TRUE +#define STM32_USBPRE STM32_USBPRE_DIV1P5 +#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK +#define STM32_RTCSEL STM32_RTCSEL_HSEDIV +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC1_IRQ_PRIORITY 6 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 + +/* + * EXT driver system settings. + */ +#define STM32_EXT_EXTI0_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI1_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI2_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI3_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI4_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI5_9_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI10_15_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI16_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI17_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI18_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI19_IRQ_PRIORITY 6 + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM8 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 FALSE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED FALSE +#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 FALSE +#define STM32_PWM_USE_TIM4 FALSE +#define STM32_PWM_USE_TIM5 FALSE +#define STM32_PWM_USE_TIM8 FALSE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 + +/* + * RTC driver system settings. + */ +#define STM32_RTC_IRQ_PRIORITY 15 + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 FALSE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 TRUE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_USB1 TRUE +#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE +#define STM32_USB_USB1_HP_IRQ_PRIORITY 13 +#define STM32_USB_USB1_LP_IRQ_PRIORITY 14 + +#endif /* _MCUCONF_H_ */ diff --git a/platforms/chibios/boards/STM32_F103_STM32DUINO/ld/STM32F103x8_stm32duino_bootloader.ld b/platforms/chibios/boards/STM32_F103_STM32DUINO/ld/STM32F103x8_stm32duino_bootloader.ld new file mode 100644 index 0000000000..a4bd566b59 --- /dev/null +++ b/platforms/chibios/boards/STM32_F103_STM32DUINO/ld/STM32F103x8_stm32duino_bootloader.ld @@ -0,0 +1,22 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + 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 License 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. +*/ + +/* + * STM32F103x8 memory setup for use with the STM32Duino bootloader. + */ +f103_flash_size = 64k; + +INCLUDE stm32duino_bootloader_common.ld diff --git a/platforms/chibios/boards/STM32_F103_STM32DUINO/ld/STM32F103xB_stm32duino_bootloader.ld b/platforms/chibios/boards/STM32_F103_STM32DUINO/ld/STM32F103xB_stm32duino_bootloader.ld new file mode 100644 index 0000000000..dc47400dc5 --- /dev/null +++ b/platforms/chibios/boards/STM32_F103_STM32DUINO/ld/STM32F103xB_stm32duino_bootloader.ld @@ -0,0 +1,22 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + 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 License 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. +*/ + +/* + * STM32F103xB memory setup for use with the STM32Duino bootloader. + */ +f103_flash_size = 128k; + +INCLUDE stm32duino_bootloader_common.ld diff --git a/platforms/chibios/boards/STM32_F103_STM32DUINO/ld/stm32duino_bootloader_common.ld b/platforms/chibios/boards/STM32_F103_STM32DUINO/ld/stm32duino_bootloader_common.ld new file mode 100644 index 0000000000..76cd3153be --- /dev/null +++ b/platforms/chibios/boards/STM32_F103_STM32DUINO/ld/stm32duino_bootloader_common.ld @@ -0,0 +1,85 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + 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 License 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. +*/ + +/* + * STM32Duino bootloader common memory setup. + */ +MEMORY +{ + flash0 : org = 0x08002000, len = f103_flash_size - 0x2000 + flash1 : org = 0x00000000, len = 0 + flash2 : org = 0x00000000, len = 0 + flash3 : org = 0x00000000, len = 0 + flash4 : org = 0x00000000, len = 0 + flash5 : org = 0x00000000, len = 0 + flash6 : org = 0x00000000, len = 0 + flash7 : org = 0x00000000, len = 0 + ram0 : org = 0x20000000, len = 20k + ram1 : org = 0x00000000, len = 0 + ram2 : org = 0x00000000, len = 0 + ram3 : org = 0x00000000, len = 0 + ram4 : org = 0x00000000, len = 0 + ram5 : org = 0x00000000, len = 0 + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash0); +REGION_ALIAS("VECTORS_FLASH_LMA", flash0); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash0); +REGION_ALIAS("XTORS_FLASH_LMA", flash0); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash0); +REGION_ALIAS("TEXT_FLASH_LMA", flash0); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash0); +REGION_ALIAS("RODATA_FLASH_LMA", flash0); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash0); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash0); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash0); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* Generic rules inclusion.*/ +INCLUDE rules.ld diff --git a/platforms/chibios/boards/common/configs/chconf.h b/platforms/chibios/boards/common/configs/chconf.h new file mode 100644 index 0000000000..44327a82d7 --- /dev/null +++ b/platforms/chibios/boards/common/configs/chconf.h @@ -0,0 +1,756 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + 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 License 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. +*/ + +/** + * @file rt/templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ +#define _CHIBIOS_RT_CONF_VER_6_1_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#if !defined(CH_CFG_ST_RESOLUTION) +#define CH_CFG_ST_RESOLUTION 32 +#endif + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#if !defined(CH_CFG_ST_FREQUENCY) +#define CH_CFG_ST_FREQUENCY 100000 +#endif + +/** + * @brief Time intervals data size. + * @note Allowed values are 16, 32 or 64 bits. + */ +#if !defined(CH_CFG_INTERVALS_SIZE) +#define CH_CFG_INTERVALS_SIZE 32 +#endif + +/** + * @brief Time types data size. + * @note Allowed values are 16 or 32 bits. + */ +#if !defined(CH_CFG_TIME_TYPES_SIZE) +#define CH_CFG_TIME_TYPES_SIZE 32 +#endif + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#if !defined(CH_CFG_ST_TIMEDELTA) +#define CH_CFG_ST_TIMEDELTA 2 +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#if !defined(CH_CFG_TIME_QUANTUM) +#define CH_CFG_TIME_QUANTUM 0 +#endif + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#if !defined(CH_CFG_NO_IDLE_THREAD) +#define CH_CFG_NO_IDLE_THREAD FALSE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_OPTIMIZE_SPEED) +#define CH_CFG_OPTIMIZE_SPEED TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_TM) +#define CH_CFG_USE_TM FALSE +#endif + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_REGISTRY) +#define CH_CFG_USE_REGISTRY FALSE +#endif + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_WAITEXIT) +#define CH_CFG_USE_WAITEXIT FALSE +#endif + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_SEMAPHORES) +#define CH_CFG_USE_SEMAPHORES TRUE +#endif + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#if !defined(CH_CFG_USE_SEMAPHORES_PRIORITY) +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE +#endif + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MUTEXES) +#define CH_CFG_USE_MUTEXES TRUE +#endif + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#if !defined(CH_CFG_USE_MUTEXES_RECURSIVE) +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE +#endif + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#if !defined(CH_CFG_USE_CONDVARS) +#define CH_CFG_USE_CONDVARS FALSE +#endif + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#if !defined(CH_CFG_USE_CONDVARS_TIMEOUT) +#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE +#endif + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_EVENTS) +#define CH_CFG_USE_EVENTS TRUE +#endif + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#if !defined(CH_CFG_USE_EVENTS_TIMEOUT) +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE +#endif + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MESSAGES) +#define CH_CFG_USE_MESSAGES FALSE +#endif + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#if !defined(CH_CFG_USE_MESSAGES_PRIORITY) +#define CH_CFG_USE_MESSAGES_PRIORITY FALSE +#endif + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#if !defined(CH_CFG_USE_DYNAMIC) +#define CH_CFG_USE_DYNAMIC FALSE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name OSLIB options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#if !defined(CH_CFG_USE_MAILBOXES) +#define CH_CFG_USE_MAILBOXES FALSE +#endif + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MEMCORE) +#define CH_CFG_USE_MEMCORE TRUE +#endif + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#if !defined(CH_CFG_MEMCORE_SIZE) +#define CH_CFG_MEMCORE_SIZE 0 +#endif + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#if !defined(CH_CFG_USE_HEAP) +#define CH_CFG_USE_HEAP FALSE +#endif + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MEMPOOLS) +#define CH_CFG_USE_MEMPOOLS FALSE +#endif + +/** + * @brief Objects FIFOs APIs. + * @details If enabled then the objects FIFOs APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_OBJ_FIFOS) +#define CH_CFG_USE_OBJ_FIFOS FALSE +#endif + +/** + * @brief Pipes APIs. + * @details If enabled then the pipes APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_PIPES) +#define CH_CFG_USE_PIPES FALSE +#endif + +/** + * @brief Objects Caches APIs. + * @details If enabled then the objects caches APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_OBJ_CACHES) +#define CH_CFG_USE_OBJ_CACHES FALSE +#endif + +/** + * @brief Delegate threads APIs. + * @details If enabled then the delegate threads APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_DELEGATES) +#define CH_CFG_USE_DELEGATES FALSE +#endif + +/** + * @brief Jobs Queues APIs. + * @details If enabled then the jobs queues APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_JOBS) +#define CH_CFG_USE_JOBS FALSE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Objects factory options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Objects Factory APIs. + * @details If enabled then the objects factory APIs are included in the + * kernel. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_CFG_USE_FACTORY) +#define CH_CFG_USE_FACTORY FALSE +#endif + +/** + * @brief Maximum length for object names. + * @details If the specified length is zero then the name is stored by + * pointer but this could have unintended side effects. + */ +#if !defined(CH_CFG_FACTORY_MAX_NAMES_LENGTH) +#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 +#endif + +/** + * @brief Enables the registry of generic objects. + */ +#if !defined(CH_CFG_FACTORY_OBJECTS_REGISTRY) +#define CH_CFG_FACTORY_OBJECTS_REGISTRY FALSE +#endif + +/** + * @brief Enables factory for generic buffers. + */ +#if !defined(CH_CFG_FACTORY_GENERIC_BUFFERS) +#define CH_CFG_FACTORY_GENERIC_BUFFERS FALSE +#endif + +/** + * @brief Enables factory for semaphores. + */ +#if !defined(CH_CFG_FACTORY_SEMAPHORES) +#define CH_CFG_FACTORY_SEMAPHORES FALSE +#endif + +/** + * @brief Enables factory for mailboxes. + */ +#if !defined(CH_CFG_FACTORY_MAILBOXES) +#define CH_CFG_FACTORY_MAILBOXES FALSE +#endif + +/** + * @brief Enables factory for objects FIFOs. + */ +#if !defined(CH_CFG_FACTORY_OBJ_FIFOS) +#define CH_CFG_FACTORY_OBJ_FIFOS FALSE +#endif + +/** + * @brief Enables factory for Pipes. + */ +#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_PIPES FALSE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_STATISTICS) +#define CH_DBG_STATISTICS FALSE +#endif + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_SYSTEM_STATE_CHECK) +#define CH_DBG_SYSTEM_STATE_CHECK FALSE +#endif + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_ENABLE_CHECKS) +#define CH_DBG_ENABLE_CHECKS FALSE +#endif + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_ENABLE_ASSERTS) +#define CH_DBG_ENABLE_ASSERTS FALSE +#endif + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#if !defined(CH_DBG_TRACE_MASK) +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED +#endif + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#if !defined(CH_DBG_TRACE_BUFFER_SIZE) +#define CH_DBG_TRACE_BUFFER_SIZE 128 +#endif + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#if !defined(CH_DBG_ENABLE_STACK_CHECK) +#define CH_DBG_ENABLE_STACK_CHECK FALSE +#endif + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_FILL_THREADS) +#define CH_DBG_FILL_THREADS FALSE +#endif + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#if !defined(CH_DBG_THREADS_PROFILING) +#define CH_DBG_THREADS_PROFILING FALSE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System structure extension. + * @details User fields added to the end of the @p ch_system_t structure. + */ +#define CH_CFG_SYSTEM_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief System initialization hook. + * @details User initialization code added to the @p chSysInit() function + * just before interrupts are enabled globally. + */ +#define CH_CFG_SYSTEM_INIT_HOOK() { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p _thread_init() function. + * + * @note It is invoked from within @p _thread_init() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/platforms/chibios/boards/common/configs/halconf.h b/platforms/chibios/boards/common/configs/halconf.h new file mode 100644 index 0000000000..c80f67ee27 --- /dev/null +++ b/platforms/chibios/boards/common/configs/halconf.h @@ -0,0 +1,531 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + 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 License 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. +*/ + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#define _CHIBIOS_HAL_CONF_ +#define _CHIBIOS_HAL_CONF_VER_7_1_ + +#include + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +#define HAL_USE_ADC FALSE +#endif + +/** + * @brief Enables the CAN subsystem. + */ +#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +#define HAL_USE_CAN FALSE +#endif + +/** + * @brief Enables the cryptographic subsystem. + */ +#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) +#define HAL_USE_CRY FALSE +#endif + +/** + * @brief Enables the DAC subsystem. + */ +#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +#define HAL_USE_DAC FALSE +#endif + +/** + * @brief Enables the EFlash subsystem. + */ +#if !defined(HAL_USE_EFL) || defined(__DOXYGEN__) +#define HAL_USE_EFL FALSE +#endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT FALSE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +#define HAL_USE_I2C FALSE +#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +#define HAL_USE_MAC FALSE +#endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +#define HAL_USE_PWM FALSE +#endif + +/** + * @brief Enables the RTC subsystem. + */ +#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +#define HAL_USE_RTC FALSE +#endif + +/** + * @brief Enables the SDC subsystem. + */ +#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +#define HAL_USE_SDC FALSE +#endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL FALSE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB FALSE +#endif + +/** + * @brief Enables the SIO subsystem. + */ +#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__) +#define HAL_USE_SIO FALSE +#endif + +/** + * @brief Enables the SPI subsystem. + */ +#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +#define HAL_USE_SPI FALSE +#endif + +/** + * @brief Enables the TRNG subsystem. + */ +#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__) +#define HAL_USE_TRNG FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +#if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +#define HAL_USE_UART FALSE +#endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB TRUE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +#define HAL_USE_WDG FALSE +#endif + +/** + * @brief Enables the WSPI subsystem. + */ +#if !defined(HAL_USE_WSPI) || defined(__DOXYGEN__) +#define HAL_USE_WSPI FALSE +#endif + +/*===========================================================================*/ +/* PAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) +#define PAL_USE_CALLBACKS FALSE +#endif + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) +#define PAL_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + +/** + * @brief Enforces the driver to use direct callbacks rather than OSAL events. + */ +#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__) +#define CAN_ENFORCE_USE_CALLBACKS FALSE +#endif + +/*===========================================================================*/ +/* CRY driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the SW fall-back of the cryptographic driver. + * @details When enabled, this option, activates a fall-back software + * implementation for algorithms not supported by the underlying + * hardware. + * @note Fall-back implementations may not be present for all algorithms. + */ +#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_USE_FALLBACK FALSE +#endif + +/** + * @brief Makes the driver forcibly use the fall-back implementations. + */ +#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) +#define HAL_CRY_ENFORCE_FALLBACK FALSE +#endif + +/*===========================================================================*/ +/* DAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) +#define DAC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define DAC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the zero-copy API. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/** + * @brief OCR initialization constant for V20 cards. + */ +#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__) +#define SDC_INIT_OCR_V20 0x50FF8000U +#endif + +/** + * @brief OCR initialization constant for non-V20 cards. + */ +#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__) +#define SDC_INIT_OCR 0x80100000U +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 38400 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 128 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 1 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 2 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables circular transfers APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__) +#define SPI_USE_CIRCULAR FALSE +#endif + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT FALSE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION FALSE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT TRUE +#endif + +/*===========================================================================*/ +/* WSPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) +#define WSPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define WSPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +#endif /* HALCONF_H */ + +/** @} */ diff --git a/platforms/chibios/boards/common/ld/MKL26Z64.ld b/platforms/chibios/boards/common/ld/MKL26Z64.ld new file mode 100644 index 0000000000..c4ca8b874c --- /dev/null +++ b/platforms/chibios/boards/common/ld/MKL26Z64.ld @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2013-2016 Fabio Utzig, http://fabioutzig.com + * (C) 2016 flabbergast + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* + * KL26Z64 memory setup. + */ +MEMORY +{ + flash0 : org = 0x00000000, len = 0x100 + flash1 : org = 0x00000400, len = 0x10 + flash2 : org = 0x00000410, len = 62k - 0x410 + flash3 : org = 0x0000F800, len = 2k + flash4 : org = 0x00000000, len = 0 + flash5 : org = 0x00000000, len = 0 + flash6 : org = 0x00000000, len = 0 + flash7 : org = 0x00000000, len = 0 + ram0 : org = 0x1FFFF800, len = 8k + ram1 : org = 0x00000000, len = 0 + ram2 : org = 0x00000000, len = 0 + ram3 : org = 0x00000000, len = 0 + ram4 : org = 0x00000000, len = 0 + ram5 : org = 0x00000000, len = 0 + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* Flash region for the configuration bytes.*/ +SECTIONS +{ + .cfmprotect : ALIGN(4) SUBALIGN(4) + { + KEEP(*(.cfmconfig)) + } > flash1 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash0); +REGION_ALIAS("VECTORS_FLASH_LMA", flash0); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash2); +REGION_ALIAS("XTORS_FLASH_LMA", flash2); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash2); +REGION_ALIAS("TEXT_FLASH_LMA", flash2); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash2); +REGION_ALIAS("RODATA_FLASH_LMA", flash2); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash2); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash2); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash2); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash2); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +__eeprom_workarea_start__ = ORIGIN(flash3); +__eeprom_workarea_size__ = LENGTH(flash3); +__eeprom_workarea_end__ = __eeprom_workarea_start__ + __eeprom_workarea_size__; + +/* Generic rules inclusion.*/ +INCLUDE rules.ld diff --git a/platforms/chibios/boards/common/ld/STM32L412xB.ld b/platforms/chibios/boards/common/ld/STM32L412xB.ld new file mode 100644 index 0000000000..5718d6bc71 --- /dev/null +++ b/platforms/chibios/boards/common/ld/STM32L412xB.ld @@ -0,0 +1,85 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + 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 License 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. +*/ + +/* + * STM32L412xB memory setup. + */ +MEMORY +{ + flash0 : org = 0x08000000, len = 128k + flash1 : org = 0x00000000, len = 0 + flash2 : org = 0x00000000, len = 0 + flash3 : org = 0x00000000, len = 0 + flash4 : org = 0x00000000, len = 0 + flash5 : org = 0x00000000, len = 0 + flash6 : org = 0x00000000, len = 0 + flash7 : org = 0x00000000, len = 0 + ram0 : org = 0x20000000, len = 32k + ram1 : org = 0x00000000, len = 0 + ram2 : org = 0x00000000, len = 0 + ram3 : org = 0x00000000, len = 0 + ram4 : org = 0x00000000, len = 0 + ram5 : org = 0x00000000, len = 0 + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash0); +REGION_ALIAS("VECTORS_FLASH_LMA", flash0); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash0); +REGION_ALIAS("XTORS_FLASH_LMA", flash0); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash0); +REGION_ALIAS("TEXT_FLASH_LMA", flash0); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash0); +REGION_ALIAS("RODATA_FLASH_LMA", flash0); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash0); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash0); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash0); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* Generic rules inclusion.*/ +INCLUDE rules.ld diff --git a/platforms/chibios/boards/keyboard-config-templates/board.h b/platforms/chibios/boards/keyboard-config-templates/board.h new file mode 100644 index 0000000000..5b840c389c --- /dev/null +++ b/platforms/chibios/boards/keyboard-config-templates/board.h @@ -0,0 +1,20 @@ +/* Copyright 2020 Nick Brassel (tzarc) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#include_next + +// #undef STM32_HSE_BYPASS diff --git a/platforms/chibios/boards/keyboard-config-templates/chconf.h b/platforms/chibios/boards/keyboard-config-templates/chconf.h new file mode 100644 index 0000000000..fca444747c --- /dev/null +++ b/platforms/chibios/boards/keyboard-config-templates/chconf.h @@ -0,0 +1,20 @@ +/* Copyright 2020 Nick Brassel (tzarc) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +// #define CH_CFG_OPTIMIZE_SPEED TRUE + +#include_next diff --git a/platforms/chibios/boards/keyboard-config-templates/halconf.h b/platforms/chibios/boards/keyboard-config-templates/halconf.h new file mode 100644 index 0000000000..456020f16a --- /dev/null +++ b/platforms/chibios/boards/keyboard-config-templates/halconf.h @@ -0,0 +1,20 @@ +/* Copyright 2020 Nick Brassel (tzarc) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +// #define HAL_USE_DAC TRUE + +#include_next diff --git a/platforms/chibios/boards/keyboard-config-templates/mcuconf.h b/platforms/chibios/boards/keyboard-config-templates/mcuconf.h new file mode 100644 index 0000000000..c690b02f4b --- /dev/null +++ b/platforms/chibios/boards/keyboard-config-templates/mcuconf.h @@ -0,0 +1,21 @@ +/* Copyright 2020 Nick Brassel (tzarc) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#include_next + +// #undef STM32_HSE_ENABLED +// #define STM32_HSE_ENABLED FALSE diff --git a/platforms/chibios/common/configs/chconf.h b/platforms/chibios/common/configs/chconf.h deleted file mode 100644 index 44327a82d7..0000000000 --- a/platforms/chibios/common/configs/chconf.h +++ /dev/null @@ -1,756 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - 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 License 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. -*/ - -/** - * @file rt/templates/chconf.h - * @brief Configuration file template. - * @details A copy of this file must be placed in each project directory, it - * contains the application specific kernel settings. - * - * @addtogroup config - * @details Kernel related settings and hooks. - * @{ - */ - -#ifndef CHCONF_H -#define CHCONF_H - -#define _CHIBIOS_RT_CONF_ -#define _CHIBIOS_RT_CONF_VER_6_1_ - -/*===========================================================================*/ -/** - * @name System timers settings - * @{ - */ -/*===========================================================================*/ - -/** - * @brief System time counter resolution. - * @note Allowed values are 16 or 32 bits. - */ -#if !defined(CH_CFG_ST_RESOLUTION) -#define CH_CFG_ST_RESOLUTION 32 -#endif - -/** - * @brief System tick frequency. - * @details Frequency of the system timer that drives the system ticks. This - * setting also defines the system tick time unit. - */ -#if !defined(CH_CFG_ST_FREQUENCY) -#define CH_CFG_ST_FREQUENCY 100000 -#endif - -/** - * @brief Time intervals data size. - * @note Allowed values are 16, 32 or 64 bits. - */ -#if !defined(CH_CFG_INTERVALS_SIZE) -#define CH_CFG_INTERVALS_SIZE 32 -#endif - -/** - * @brief Time types data size. - * @note Allowed values are 16 or 32 bits. - */ -#if !defined(CH_CFG_TIME_TYPES_SIZE) -#define CH_CFG_TIME_TYPES_SIZE 32 -#endif - -/** - * @brief Time delta constant for the tick-less mode. - * @note If this value is zero then the system uses the classic - * periodic tick. This value represents the minimum number - * of ticks that is safe to specify in a timeout directive. - * The value one is not valid, timeouts are rounded up to - * this value. - */ -#if !defined(CH_CFG_ST_TIMEDELTA) -#define CH_CFG_ST_TIMEDELTA 2 -#endif - -/** @} */ - -/*===========================================================================*/ -/** - * @name Kernel parameters and options - * @{ - */ -/*===========================================================================*/ - -/** - * @brief Round robin interval. - * @details This constant is the number of system ticks allowed for the - * threads before preemption occurs. Setting this value to zero - * disables the preemption for threads with equal priority and the - * round robin becomes cooperative. Note that higher priority - * threads can still preempt, the kernel is always preemptive. - * @note Disabling the round robin preemption makes the kernel more compact - * and generally faster. - * @note The round robin preemption is not supported in tickless mode and - * must be set to zero in that case. - */ -#if !defined(CH_CFG_TIME_QUANTUM) -#define CH_CFG_TIME_QUANTUM 0 -#endif - -/** - * @brief Idle thread automatic spawn suppression. - * @details When this option is activated the function @p chSysInit() - * does not spawn the idle thread. The application @p main() - * function becomes the idle thread and must implement an - * infinite loop. - */ -#if !defined(CH_CFG_NO_IDLE_THREAD) -#define CH_CFG_NO_IDLE_THREAD FALSE -#endif - -/** @} */ - -/*===========================================================================*/ -/** - * @name Performance options - * @{ - */ -/*===========================================================================*/ - -/** - * @brief OS optimization. - * @details If enabled then time efficient rather than space efficient code - * is used when two possible implementations exist. - * - * @note This is not related to the compiler optimization options. - * @note The default is @p TRUE. - */ -#if !defined(CH_CFG_OPTIMIZE_SPEED) -#define CH_CFG_OPTIMIZE_SPEED TRUE -#endif - -/** @} */ - -/*===========================================================================*/ -/** - * @name Subsystem options - * @{ - */ -/*===========================================================================*/ - -/** - * @brief Time Measurement APIs. - * @details If enabled then the time measurement APIs are included in - * the kernel. - * - * @note The default is @p TRUE. - */ -#if !defined(CH_CFG_USE_TM) -#define CH_CFG_USE_TM FALSE -#endif - -/** - * @brief Threads registry APIs. - * @details If enabled then the registry APIs are included in the kernel. - * - * @note The default is @p TRUE. - */ -#if !defined(CH_CFG_USE_REGISTRY) -#define CH_CFG_USE_REGISTRY FALSE -#endif - -/** - * @brief Threads synchronization APIs. - * @details If enabled then the @p chThdWait() function is included in - * the kernel. - * - * @note The default is @p TRUE. - */ -#if !defined(CH_CFG_USE_WAITEXIT) -#define CH_CFG_USE_WAITEXIT FALSE -#endif - -/** - * @brief Semaphores APIs. - * @details If enabled then the Semaphores APIs are included in the kernel. - * - * @note The default is @p TRUE. - */ -#if !defined(CH_CFG_USE_SEMAPHORES) -#define CH_CFG_USE_SEMAPHORES TRUE -#endif - -/** - * @brief Semaphores queuing mode. - * @details If enabled then the threads are enqueued on semaphores by - * priority rather than in FIFO order. - * - * @note The default is @p FALSE. Enable this if you have special - * requirements. - * @note Requires @p CH_CFG_USE_SEMAPHORES. - */ -#if !defined(CH_CFG_USE_SEMAPHORES_PRIORITY) -#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE -#endif - -/** - * @brief Mutexes APIs. - * @details If enabled then the mutexes APIs are included in the kernel. - * - * @note The default is @p TRUE. - */ -#if !defined(CH_CFG_USE_MUTEXES) -#define CH_CFG_USE_MUTEXES TRUE -#endif - -/** - * @brief Enables recursive behavior on mutexes. - * @note Recursive mutexes are heavier and have an increased - * memory footprint. - * - * @note The default is @p FALSE. - * @note Requires @p CH_CFG_USE_MUTEXES. - */ -#if !defined(CH_CFG_USE_MUTEXES_RECURSIVE) -#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE -#endif - -/** - * @brief Conditional Variables APIs. - * @details If enabled then the conditional variables APIs are included - * in the kernel. - * - * @note The default is @p TRUE. - * @note Requires @p CH_CFG_USE_MUTEXES. - */ -#if !defined(CH_CFG_USE_CONDVARS) -#define CH_CFG_USE_CONDVARS FALSE -#endif - -/** - * @brief Conditional Variables APIs with timeout. - * @details If enabled then the conditional variables APIs with timeout - * specification are included in the kernel. - * - * @note The default is @p TRUE. - * @note Requires @p CH_CFG_USE_CONDVARS. - */ -#if !defined(CH_CFG_USE_CONDVARS_TIMEOUT) -#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE -#endif - -/** - * @brief Events Flags APIs. - * @details If enabled then the event flags APIs are included in the kernel. - * - * @note The default is @p TRUE. - */ -#if !defined(CH_CFG_USE_EVENTS) -#define CH_CFG_USE_EVENTS TRUE -#endif - -/** - * @brief Events Flags APIs with timeout. - * @details If enabled then the events APIs with timeout specification - * are included in the kernel. - * - * @note The default is @p TRUE. - * @note Requires @p CH_CFG_USE_EVENTS. - */ -#if !defined(CH_CFG_USE_EVENTS_TIMEOUT) -#define CH_CFG_USE_EVENTS_TIMEOUT TRUE -#endif - -/** - * @brief Synchronous Messages APIs. - * @details If enabled then the synchronous messages APIs are included - * in the kernel. - * - * @note The default is @p TRUE. - */ -#if !defined(CH_CFG_USE_MESSAGES) -#define CH_CFG_USE_MESSAGES FALSE -#endif - -/** - * @brief Synchronous Messages queuing mode. - * @details If enabled then messages are served by priority rather than in - * FIFO order. - * - * @note The default is @p FALSE. Enable this if you have special - * requirements. - * @note Requires @p CH_CFG_USE_MESSAGES. - */ -#if !defined(CH_CFG_USE_MESSAGES_PRIORITY) -#define CH_CFG_USE_MESSAGES_PRIORITY FALSE -#endif - -/** - * @brief Dynamic Threads APIs. - * @details If enabled then the dynamic threads creation APIs are included - * in the kernel. - * - * @note The default is @p TRUE. - * @note Requires @p CH_CFG_USE_WAITEXIT. - * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. - */ -#if !defined(CH_CFG_USE_DYNAMIC) -#define CH_CFG_USE_DYNAMIC FALSE -#endif - -/** @} */ - -/*===========================================================================*/ -/** - * @name OSLIB options - * @{ - */ -/*===========================================================================*/ - -/** - * @brief Mailboxes APIs. - * @details If enabled then the asynchronous messages (mailboxes) APIs are - * included in the kernel. - * - * @note The default is @p TRUE. - * @note Requires @p CH_CFG_USE_SEMAPHORES. - */ -#if !defined(CH_CFG_USE_MAILBOXES) -#define CH_CFG_USE_MAILBOXES FALSE -#endif - -/** - * @brief Core Memory Manager APIs. - * @details If enabled then the core memory manager APIs are included - * in the kernel. - * - * @note The default is @p TRUE. - */ -#if !defined(CH_CFG_USE_MEMCORE) -#define CH_CFG_USE_MEMCORE TRUE -#endif - -/** - * @brief Managed RAM size. - * @details Size of the RAM area to be managed by the OS. If set to zero - * then the whole available RAM is used. The core memory is made - * available to the heap allocator and/or can be used directly through - * the simplified core memory allocator. - * - * @note In order to let the OS manage the whole RAM the linker script must - * provide the @p __heap_base__ and @p __heap_end__ symbols. - * @note Requires @p CH_CFG_USE_MEMCORE. - */ -#if !defined(CH_CFG_MEMCORE_SIZE) -#define CH_CFG_MEMCORE_SIZE 0 -#endif - -/** - * @brief Heap Allocator APIs. - * @details If enabled then the memory heap allocator APIs are included - * in the kernel. - * - * @note The default is @p TRUE. - * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or - * @p CH_CFG_USE_SEMAPHORES. - * @note Mutexes are recommended. - */ -#if !defined(CH_CFG_USE_HEAP) -#define CH_CFG_USE_HEAP FALSE -#endif - -/** - * @brief Memory Pools Allocator APIs. - * @details If enabled then the memory pools allocator APIs are included - * in the kernel. - * - * @note The default is @p TRUE. - */ -#if !defined(CH_CFG_USE_MEMPOOLS) -#define CH_CFG_USE_MEMPOOLS FALSE -#endif - -/** - * @brief Objects FIFOs APIs. - * @details If enabled then the objects FIFOs APIs are included - * in the kernel. - * - * @note The default is @p TRUE. - */ -#if !defined(CH_CFG_USE_OBJ_FIFOS) -#define CH_CFG_USE_OBJ_FIFOS FALSE -#endif - -/** - * @brief Pipes APIs. - * @details If enabled then the pipes APIs are included - * in the kernel. - * - * @note The default is @p TRUE. - */ -#if !defined(CH_CFG_USE_PIPES) -#define CH_CFG_USE_PIPES FALSE -#endif - -/** - * @brief Objects Caches APIs. - * @details If enabled then the objects caches APIs are included - * in the kernel. - * - * @note The default is @p TRUE. - */ -#if !defined(CH_CFG_USE_OBJ_CACHES) -#define CH_CFG_USE_OBJ_CACHES FALSE -#endif - -/** - * @brief Delegate threads APIs. - * @details If enabled then the delegate threads APIs are included - * in the kernel. - * - * @note The default is @p TRUE. - */ -#if !defined(CH_CFG_USE_DELEGATES) -#define CH_CFG_USE_DELEGATES FALSE -#endif - -/** - * @brief Jobs Queues APIs. - * @details If enabled then the jobs queues APIs are included - * in the kernel. - * - * @note The default is @p TRUE. - */ -#if !defined(CH_CFG_USE_JOBS) -#define CH_CFG_USE_JOBS FALSE -#endif - -/** @} */ - -/*===========================================================================*/ -/** - * @name Objects factory options - * @{ - */ -/*===========================================================================*/ - -/** - * @brief Objects Factory APIs. - * @details If enabled then the objects factory APIs are included in the - * kernel. - * - * @note The default is @p FALSE. - */ -#if !defined(CH_CFG_USE_FACTORY) -#define CH_CFG_USE_FACTORY FALSE -#endif - -/** - * @brief Maximum length for object names. - * @details If the specified length is zero then the name is stored by - * pointer but this could have unintended side effects. - */ -#if !defined(CH_CFG_FACTORY_MAX_NAMES_LENGTH) -#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 -#endif - -/** - * @brief Enables the registry of generic objects. - */ -#if !defined(CH_CFG_FACTORY_OBJECTS_REGISTRY) -#define CH_CFG_FACTORY_OBJECTS_REGISTRY FALSE -#endif - -/** - * @brief Enables factory for generic buffers. - */ -#if !defined(CH_CFG_FACTORY_GENERIC_BUFFERS) -#define CH_CFG_FACTORY_GENERIC_BUFFERS FALSE -#endif - -/** - * @brief Enables factory for semaphores. - */ -#if !defined(CH_CFG_FACTORY_SEMAPHORES) -#define CH_CFG_FACTORY_SEMAPHORES FALSE -#endif - -/** - * @brief Enables factory for mailboxes. - */ -#if !defined(CH_CFG_FACTORY_MAILBOXES) -#define CH_CFG_FACTORY_MAILBOXES FALSE -#endif - -/** - * @brief Enables factory for objects FIFOs. - */ -#if !defined(CH_CFG_FACTORY_OBJ_FIFOS) -#define CH_CFG_FACTORY_OBJ_FIFOS FALSE -#endif - -/** - * @brief Enables factory for Pipes. - */ -#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) -#define CH_CFG_FACTORY_PIPES FALSE -#endif - -/** @} */ - -/*===========================================================================*/ -/** - * @name Debug options - * @{ - */ -/*===========================================================================*/ - -/** - * @brief Debug option, kernel statistics. - * - * @note The default is @p FALSE. - */ -#if !defined(CH_DBG_STATISTICS) -#define CH_DBG_STATISTICS FALSE -#endif - -/** - * @brief Debug option, system state check. - * @details If enabled the correct call protocol for system APIs is checked - * at runtime. - * - * @note The default is @p FALSE. - */ -#if !defined(CH_DBG_SYSTEM_STATE_CHECK) -#define CH_DBG_SYSTEM_STATE_CHECK FALSE -#endif - -/** - * @brief Debug option, parameters checks. - * @details If enabled then the checks on the API functions input - * parameters are activated. - * - * @note The default is @p FALSE. - */ -#if !defined(CH_DBG_ENABLE_CHECKS) -#define CH_DBG_ENABLE_CHECKS FALSE -#endif - -/** - * @brief Debug option, consistency checks. - * @details If enabled then all the assertions in the kernel code are - * activated. This includes consistency checks inside the kernel, - * runtime anomalies and port-defined checks. - * - * @note The default is @p FALSE. - */ -#if !defined(CH_DBG_ENABLE_ASSERTS) -#define CH_DBG_ENABLE_ASSERTS FALSE -#endif - -/** - * @brief Debug option, trace buffer. - * @details If enabled then the trace buffer is activated. - * - * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. - */ -#if !defined(CH_DBG_TRACE_MASK) -#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED -#endif - -/** - * @brief Trace buffer entries. - * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is - * different from @p CH_DBG_TRACE_MASK_DISABLED. - */ -#if !defined(CH_DBG_TRACE_BUFFER_SIZE) -#define CH_DBG_TRACE_BUFFER_SIZE 128 -#endif - -/** - * @brief Debug option, stack checks. - * @details If enabled then a runtime stack check is performed. - * - * @note The default is @p FALSE. - * @note The stack check is performed in a architecture/port dependent way. - * It may not be implemented or some ports. - * @note The default failure mode is to halt the system with the global - * @p panic_msg variable set to @p NULL. - */ -#if !defined(CH_DBG_ENABLE_STACK_CHECK) -#define CH_DBG_ENABLE_STACK_CHECK FALSE -#endif - -/** - * @brief Debug option, stacks initialization. - * @details If enabled then the threads working area is filled with a byte - * value when a thread is created. This can be useful for the - * runtime measurement of the used stack. - * - * @note The default is @p FALSE. - */ -#if !defined(CH_DBG_FILL_THREADS) -#define CH_DBG_FILL_THREADS FALSE -#endif - -/** - * @brief Debug option, threads profiling. - * @details If enabled then a field is added to the @p thread_t structure that - * counts the system ticks occurred while executing the thread. - * - * @note The default is @p FALSE. - * @note This debug option is not currently compatible with the - * tickless mode. - */ -#if !defined(CH_DBG_THREADS_PROFILING) -#define CH_DBG_THREADS_PROFILING FALSE -#endif - -/** @} */ - -/*===========================================================================*/ -/** - * @name Kernel hooks - * @{ - */ -/*===========================================================================*/ - -/** - * @brief System structure extension. - * @details User fields added to the end of the @p ch_system_t structure. - */ -#define CH_CFG_SYSTEM_EXTRA_FIELDS \ - /* Add threads custom fields here.*/ - -/** - * @brief System initialization hook. - * @details User initialization code added to the @p chSysInit() function - * just before interrupts are enabled globally. - */ -#define CH_CFG_SYSTEM_INIT_HOOK() { \ - /* Add threads initialization code here.*/ \ -} - -/** - * @brief Threads descriptor structure extension. - * @details User fields added to the end of the @p thread_t structure. - */ -#define CH_CFG_THREAD_EXTRA_FIELDS \ - /* Add threads custom fields here.*/ - -/** - * @brief Threads initialization hook. - * @details User initialization code added to the @p _thread_init() function. - * - * @note It is invoked from within @p _thread_init() and implicitly from all - * the threads creation APIs. - */ -#define CH_CFG_THREAD_INIT_HOOK(tp) { \ - /* Add threads initialization code here.*/ \ -} - -/** - * @brief Threads finalization hook. - * @details User finalization code added to the @p chThdExit() API. - */ -#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ - /* Add threads finalization code here.*/ \ -} - -/** - * @brief Context switch hook. - * @details This hook is invoked just before switching between threads. - */ -#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ - /* Context switch code here.*/ \ -} - -/** - * @brief ISR enter hook. - */ -#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ - /* IRQ prologue code here.*/ \ -} - -/** - * @brief ISR exit hook. - */ -#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ - /* IRQ epilogue code here.*/ \ -} - -/** - * @brief Idle thread enter hook. - * @note This hook is invoked within a critical zone, no OS functions - * should be invoked from here. - * @note This macro can be used to activate a power saving mode. - */ -#define CH_CFG_IDLE_ENTER_HOOK() { \ - /* Idle-enter code here.*/ \ -} - -/** - * @brief Idle thread leave hook. - * @note This hook is invoked within a critical zone, no OS functions - * should be invoked from here. - * @note This macro can be used to deactivate a power saving mode. - */ -#define CH_CFG_IDLE_LEAVE_HOOK() { \ - /* Idle-leave code here.*/ \ -} - -/** - * @brief Idle Loop hook. - * @details This hook is continuously invoked by the idle thread loop. - */ -#define CH_CFG_IDLE_LOOP_HOOK() { \ - /* Idle loop code here.*/ \ -} - -/** - * @brief System tick event hook. - * @details This hook is invoked in the system tick handler immediately - * after processing the virtual timers queue. - */ -#define CH_CFG_SYSTEM_TICK_HOOK() { \ - /* System tick event code here.*/ \ -} - -/** - * @brief System halt hook. - * @details This hook is invoked in case to a system halting error before - * the system is halted. - */ -#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ - /* System halt code here.*/ \ -} - -/** - * @brief Trace hook. - * @details This hook is invoked each time a new record is written in the - * trace buffer. - */ -#define CH_CFG_TRACE_HOOK(tep) { \ - /* Trace code here.*/ \ -} - -/** @} */ - -/*===========================================================================*/ -/* Port-specific settings (override port settings defaulted in chcore.h). */ -/*===========================================================================*/ - -#endif /* CHCONF_H */ - -/** @} */ diff --git a/platforms/chibios/common/configs/halconf.h b/platforms/chibios/common/configs/halconf.h deleted file mode 100644 index c80f67ee27..0000000000 --- a/platforms/chibios/common/configs/halconf.h +++ /dev/null @@ -1,531 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - 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 License 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. -*/ - -/** - * @file templates/halconf.h - * @brief HAL configuration header. - * @details HAL configuration file, this file allows to enable or disable the - * various device drivers from your application. You may also use - * this file in order to override the device drivers default settings. - * - * @addtogroup HAL_CONF - * @{ - */ - -#ifndef HALCONF_H -#define HALCONF_H - -#define _CHIBIOS_HAL_CONF_ -#define _CHIBIOS_HAL_CONF_VER_7_1_ - -#include - -/** - * @brief Enables the PAL subsystem. - */ -#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) -#define HAL_USE_PAL TRUE -#endif - -/** - * @brief Enables the ADC subsystem. - */ -#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) -#define HAL_USE_ADC FALSE -#endif - -/** - * @brief Enables the CAN subsystem. - */ -#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) -#define HAL_USE_CAN FALSE -#endif - -/** - * @brief Enables the cryptographic subsystem. - */ -#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) -#define HAL_USE_CRY FALSE -#endif - -/** - * @brief Enables the DAC subsystem. - */ -#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) -#define HAL_USE_DAC FALSE -#endif - -/** - * @brief Enables the EFlash subsystem. - */ -#if !defined(HAL_USE_EFL) || defined(__DOXYGEN__) -#define HAL_USE_EFL FALSE -#endif - -/** - * @brief Enables the GPT subsystem. - */ -#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) -#define HAL_USE_GPT FALSE -#endif - -/** - * @brief Enables the I2C subsystem. - */ -#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) -#define HAL_USE_I2C FALSE -#endif - -/** - * @brief Enables the I2S subsystem. - */ -#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) -#define HAL_USE_I2S FALSE -#endif - -/** - * @brief Enables the ICU subsystem. - */ -#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) -#define HAL_USE_ICU FALSE -#endif - -/** - * @brief Enables the MAC subsystem. - */ -#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) -#define HAL_USE_MAC FALSE -#endif - -/** - * @brief Enables the MMC_SPI subsystem. - */ -#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) -#define HAL_USE_MMC_SPI FALSE -#endif - -/** - * @brief Enables the PWM subsystem. - */ -#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) -#define HAL_USE_PWM FALSE -#endif - -/** - * @brief Enables the RTC subsystem. - */ -#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) -#define HAL_USE_RTC FALSE -#endif - -/** - * @brief Enables the SDC subsystem. - */ -#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) -#define HAL_USE_SDC FALSE -#endif - -/** - * @brief Enables the SERIAL subsystem. - */ -#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) -#define HAL_USE_SERIAL FALSE -#endif - -/** - * @brief Enables the SERIAL over USB subsystem. - */ -#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) -#define HAL_USE_SERIAL_USB FALSE -#endif - -/** - * @brief Enables the SIO subsystem. - */ -#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__) -#define HAL_USE_SIO FALSE -#endif - -/** - * @brief Enables the SPI subsystem. - */ -#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) -#define HAL_USE_SPI FALSE -#endif - -/** - * @brief Enables the TRNG subsystem. - */ -#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__) -#define HAL_USE_TRNG FALSE -#endif - -/** - * @brief Enables the UART subsystem. - */ -#if !defined(HAL_USE_UART) || defined(__DOXYGEN__) -#define HAL_USE_UART FALSE -#endif - -/** - * @brief Enables the USB subsystem. - */ -#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) -#define HAL_USE_USB TRUE -#endif - -/** - * @brief Enables the WDG subsystem. - */ -#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) -#define HAL_USE_WDG FALSE -#endif - -/** - * @brief Enables the WSPI subsystem. - */ -#if !defined(HAL_USE_WSPI) || defined(__DOXYGEN__) -#define HAL_USE_WSPI FALSE -#endif - -/*===========================================================================*/ -/* PAL driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Enables synchronous APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) -#define PAL_USE_CALLBACKS FALSE -#endif - -/** - * @brief Enables synchronous APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) -#define PAL_USE_WAIT FALSE -#endif - -/*===========================================================================*/ -/* ADC driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Enables synchronous APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) -#define ADC_USE_WAIT TRUE -#endif - -/** - * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) -#define ADC_USE_MUTUAL_EXCLUSION TRUE -#endif - -/*===========================================================================*/ -/* CAN driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Sleep mode related APIs inclusion switch. - */ -#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) -#define CAN_USE_SLEEP_MODE TRUE -#endif - -/** - * @brief Enforces the driver to use direct callbacks rather than OSAL events. - */ -#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__) -#define CAN_ENFORCE_USE_CALLBACKS FALSE -#endif - -/*===========================================================================*/ -/* CRY driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Enables the SW fall-back of the cryptographic driver. - * @details When enabled, this option, activates a fall-back software - * implementation for algorithms not supported by the underlying - * hardware. - * @note Fall-back implementations may not be present for all algorithms. - */ -#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) -#define HAL_CRY_USE_FALLBACK FALSE -#endif - -/** - * @brief Makes the driver forcibly use the fall-back implementations. - */ -#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) -#define HAL_CRY_ENFORCE_FALLBACK FALSE -#endif - -/*===========================================================================*/ -/* DAC driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Enables synchronous APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) -#define DAC_USE_WAIT TRUE -#endif - -/** - * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) -#define DAC_USE_MUTUAL_EXCLUSION TRUE -#endif - -/*===========================================================================*/ -/* I2C driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Enables the mutual exclusion APIs on the I2C bus. - */ -#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) -#define I2C_USE_MUTUAL_EXCLUSION TRUE -#endif - -/*===========================================================================*/ -/* MAC driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Enables the zero-copy API. - */ -#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) -#define MAC_USE_ZERO_COPY FALSE -#endif - -/** - * @brief Enables an event sources for incoming packets. - */ -#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) -#define MAC_USE_EVENTS TRUE -#endif - -/*===========================================================================*/ -/* MMC_SPI driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Delays insertions. - * @details If enabled this options inserts delays into the MMC waiting - * routines releasing some extra CPU time for the threads with - * lower priority, this may slow down the driver a bit however. - * This option is recommended also if the SPI driver does not - * use a DMA channel and heavily loads the CPU. - */ -#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) -#define MMC_NICE_WAITING TRUE -#endif - -/*===========================================================================*/ -/* SDC driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Number of initialization attempts before rejecting the card. - * @note Attempts are performed at 10mS intervals. - */ -#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) -#define SDC_INIT_RETRY 100 -#endif - -/** - * @brief Include support for MMC cards. - * @note MMC support is not yet implemented so this option must be kept - * at @p FALSE. - */ -#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) -#define SDC_MMC_SUPPORT FALSE -#endif - -/** - * @brief Delays insertions. - * @details If enabled this options inserts delays into the MMC waiting - * routines releasing some extra CPU time for the threads with - * lower priority, this may slow down the driver a bit however. - */ -#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) -#define SDC_NICE_WAITING TRUE -#endif - -/** - * @brief OCR initialization constant for V20 cards. - */ -#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__) -#define SDC_INIT_OCR_V20 0x50FF8000U -#endif - -/** - * @brief OCR initialization constant for non-V20 cards. - */ -#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__) -#define SDC_INIT_OCR 0x80100000U -#endif - -/*===========================================================================*/ -/* SERIAL driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Default bit rate. - * @details Configuration parameter, this is the baud rate selected for the - * default configuration. - */ -#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) -#define SERIAL_DEFAULT_BITRATE 38400 -#endif - -/** - * @brief Serial buffers size. - * @details Configuration parameter, you can change the depth of the queue - * buffers depending on the requirements of your application. - * @note The default is 16 bytes for both the transmission and receive - * buffers. - */ -#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) -#define SERIAL_BUFFERS_SIZE 128 -#endif - -/*===========================================================================*/ -/* SERIAL_USB driver related setting. */ -/*===========================================================================*/ - -/** - * @brief Serial over USB buffers size. - * @details Configuration parameter, the buffer size must be a multiple of - * the USB data endpoint maximum packet size. - * @note The default is 256 bytes for both the transmission and receive - * buffers. - */ -#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) -#define SERIAL_USB_BUFFERS_SIZE 1 -#endif - -/** - * @brief Serial over USB number of buffers. - * @note The default is 2 buffers. - */ -#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) -#define SERIAL_USB_BUFFERS_NUMBER 2 -#endif - -/*===========================================================================*/ -/* SPI driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Enables synchronous APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) -#define SPI_USE_WAIT TRUE -#endif - -/** - * @brief Enables circular transfers APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__) -#define SPI_USE_CIRCULAR FALSE -#endif - -/** - * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) -#define SPI_USE_MUTUAL_EXCLUSION TRUE -#endif - -/** - * @brief Handling method for SPI CS line. - * @note Disabling this option saves both code and data space. - */ -#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) -#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD -#endif - -/*===========================================================================*/ -/* UART driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Enables synchronous APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) -#define UART_USE_WAIT FALSE -#endif - -/** - * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) -#define UART_USE_MUTUAL_EXCLUSION FALSE -#endif - -/*===========================================================================*/ -/* USB driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Enables synchronous APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) -#define USB_USE_WAIT TRUE -#endif - -/*===========================================================================*/ -/* WSPI driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Enables synchronous APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) -#define WSPI_USE_WAIT TRUE -#endif - -/** - * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) -#define WSPI_USE_MUTUAL_EXCLUSION TRUE -#endif - -#endif /* HALCONF_H */ - -/** @} */ diff --git a/platforms/chibios/common/ld/MKL26Z64.ld b/platforms/chibios/common/ld/MKL26Z64.ld deleted file mode 100644 index c4ca8b874c..0000000000 --- a/platforms/chibios/common/ld/MKL26Z64.ld +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2013-2016 Fabio Utzig, http://fabioutzig.com - * (C) 2016 flabbergast - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/* - * KL26Z64 memory setup. - */ -MEMORY -{ - flash0 : org = 0x00000000, len = 0x100 - flash1 : org = 0x00000400, len = 0x10 - flash2 : org = 0x00000410, len = 62k - 0x410 - flash3 : org = 0x0000F800, len = 2k - flash4 : org = 0x00000000, len = 0 - flash5 : org = 0x00000000, len = 0 - flash6 : org = 0x00000000, len = 0 - flash7 : org = 0x00000000, len = 0 - ram0 : org = 0x1FFFF800, len = 8k - ram1 : org = 0x00000000, len = 0 - ram2 : org = 0x00000000, len = 0 - ram3 : org = 0x00000000, len = 0 - ram4 : org = 0x00000000, len = 0 - ram5 : org = 0x00000000, len = 0 - ram6 : org = 0x00000000, len = 0 - ram7 : org = 0x00000000, len = 0 -} - -/* Flash region for the configuration bytes.*/ -SECTIONS -{ - .cfmprotect : ALIGN(4) SUBALIGN(4) - { - KEEP(*(.cfmconfig)) - } > flash1 -} - -/* For each data/text section two region are defined, a virtual region - and a load region (_LMA suffix).*/ - -/* Flash region to be used for exception vectors.*/ -REGION_ALIAS("VECTORS_FLASH", flash0); -REGION_ALIAS("VECTORS_FLASH_LMA", flash0); - -/* Flash region to be used for constructors and destructors.*/ -REGION_ALIAS("XTORS_FLASH", flash2); -REGION_ALIAS("XTORS_FLASH_LMA", flash2); - -/* Flash region to be used for code text.*/ -REGION_ALIAS("TEXT_FLASH", flash2); -REGION_ALIAS("TEXT_FLASH_LMA", flash2); - -/* Flash region to be used for read only data.*/ -REGION_ALIAS("RODATA_FLASH", flash2); -REGION_ALIAS("RODATA_FLASH_LMA", flash2); - -/* Flash region to be used for various.*/ -REGION_ALIAS("VARIOUS_FLASH", flash2); -REGION_ALIAS("VARIOUS_FLASH_LMA", flash2); - -/* Flash region to be used for RAM(n) initialization data.*/ -REGION_ALIAS("RAM_INIT_FLASH_LMA", flash2); - -/* RAM region to be used for Main stack. This stack accommodates the processing - of all exceptions and interrupts.*/ -REGION_ALIAS("MAIN_STACK_RAM", ram0); - -/* RAM region to be used for the process stack. This is the stack used by - the main() function.*/ -REGION_ALIAS("PROCESS_STACK_RAM", ram0); - -/* RAM region to be used for data segment.*/ -REGION_ALIAS("DATA_RAM", ram0); -REGION_ALIAS("DATA_RAM_LMA", flash2); - -/* RAM region to be used for BSS segment.*/ -REGION_ALIAS("BSS_RAM", ram0); - -/* RAM region to be used for the default heap.*/ -REGION_ALIAS("HEAP_RAM", ram0); - -__eeprom_workarea_start__ = ORIGIN(flash3); -__eeprom_workarea_size__ = LENGTH(flash3); -__eeprom_workarea_end__ = __eeprom_workarea_start__ + __eeprom_workarea_size__; - -/* Generic rules inclusion.*/ -INCLUDE rules.ld diff --git a/platforms/chibios/common/ld/STM32L412xB.ld b/platforms/chibios/common/ld/STM32L412xB.ld deleted file mode 100644 index 5718d6bc71..0000000000 --- a/platforms/chibios/common/ld/STM32L412xB.ld +++ /dev/null @@ -1,85 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - 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 License 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. -*/ - -/* - * STM32L412xB memory setup. - */ -MEMORY -{ - flash0 : org = 0x08000000, len = 128k - flash1 : org = 0x00000000, len = 0 - flash2 : org = 0x00000000, len = 0 - flash3 : org = 0x00000000, len = 0 - flash4 : org = 0x00000000, len = 0 - flash5 : org = 0x00000000, len = 0 - flash6 : org = 0x00000000, len = 0 - flash7 : org = 0x00000000, len = 0 - ram0 : org = 0x20000000, len = 32k - ram1 : org = 0x00000000, len = 0 - ram2 : org = 0x00000000, len = 0 - ram3 : org = 0x00000000, len = 0 - ram4 : org = 0x00000000, len = 0 - ram5 : org = 0x00000000, len = 0 - ram6 : org = 0x00000000, len = 0 - ram7 : org = 0x00000000, len = 0 -} - -/* For each data/text section two region are defined, a virtual region - and a load region (_LMA suffix).*/ - -/* Flash region to be used for exception vectors.*/ -REGION_ALIAS("VECTORS_FLASH", flash0); -REGION_ALIAS("VECTORS_FLASH_LMA", flash0); - -/* Flash region to be used for constructors and destructors.*/ -REGION_ALIAS("XTORS_FLASH", flash0); -REGION_ALIAS("XTORS_FLASH_LMA", flash0); - -/* Flash region to be used for code text.*/ -REGION_ALIAS("TEXT_FLASH", flash0); -REGION_ALIAS("TEXT_FLASH_LMA", flash0); - -/* Flash region to be used for read only data.*/ -REGION_ALIAS("RODATA_FLASH", flash0); -REGION_ALIAS("RODATA_FLASH_LMA", flash0); - -/* Flash region to be used for various.*/ -REGION_ALIAS("VARIOUS_FLASH", flash0); -REGION_ALIAS("VARIOUS_FLASH_LMA", flash0); - -/* Flash region to be used for RAM(n) initialization data.*/ -REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0); - -/* RAM region to be used for Main stack. This stack accommodates the processing - of all exceptions and interrupts.*/ -REGION_ALIAS("MAIN_STACK_RAM", ram0); - -/* RAM region to be used for the process stack. This is the stack used by - the main() function.*/ -REGION_ALIAS("PROCESS_STACK_RAM", ram0); - -/* RAM region to be used for data segment.*/ -REGION_ALIAS("DATA_RAM", ram0); -REGION_ALIAS("DATA_RAM_LMA", flash0); - -/* RAM region to be used for BSS segment.*/ -REGION_ALIAS("BSS_RAM", ram0); - -/* RAM region to be used for the default heap.*/ -REGION_ALIAS("HEAP_RAM", ram0); - -/* Generic rules inclusion.*/ -INCLUDE rules.ld diff --git a/platforms/chibios/keyboard-config-templates/board.h b/platforms/chibios/keyboard-config-templates/board.h deleted file mode 100644 index 5b840c389c..0000000000 --- a/platforms/chibios/keyboard-config-templates/board.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Copyright 2020 Nick Brassel (tzarc) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#pragma once - -#include_next - -// #undef STM32_HSE_BYPASS diff --git a/platforms/chibios/keyboard-config-templates/chconf.h b/platforms/chibios/keyboard-config-templates/chconf.h deleted file mode 100644 index fca444747c..0000000000 --- a/platforms/chibios/keyboard-config-templates/chconf.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Copyright 2020 Nick Brassel (tzarc) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#pragma once - -// #define CH_CFG_OPTIMIZE_SPEED TRUE - -#include_next diff --git a/platforms/chibios/keyboard-config-templates/halconf.h b/platforms/chibios/keyboard-config-templates/halconf.h deleted file mode 100644 index 456020f16a..0000000000 --- a/platforms/chibios/keyboard-config-templates/halconf.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Copyright 2020 Nick Brassel (tzarc) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#pragma once - -// #define HAL_USE_DAC TRUE - -#include_next diff --git a/platforms/chibios/keyboard-config-templates/mcuconf.h b/platforms/chibios/keyboard-config-templates/mcuconf.h deleted file mode 100644 index c690b02f4b..0000000000 --- a/platforms/chibios/keyboard-config-templates/mcuconf.h +++ /dev/null @@ -1,21 +0,0 @@ -/* Copyright 2020 Nick Brassel (tzarc) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#pragma once - -#include_next - -// #undef STM32_HSE_ENABLED -// #define STM32_HSE_ENABLED FALSE diff --git a/tmk_core/chibios.mk b/tmk_core/chibios.mk index 28aaaecba0..7962516a0a 100644 --- a/tmk_core/chibios.mk +++ b/tmk_core/chibios.mk @@ -67,9 +67,9 @@ else ifneq ("$(wildcard $(KEYBOARD_PATH_2)/boards/$(BOARD)/board.mk)","") else ifneq ("$(wildcard $(KEYBOARD_PATH_1)/boards/$(BOARD)/board.mk)","") BOARD_PATH = $(KEYBOARD_PATH_1) BOARD_MK += $(KEYBOARD_PATH_1)/boards/$(BOARD)/board.mk -else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/$(BOARD)/board/board.mk)","") - BOARD_PATH = $(TOP_DIR)/platforms/chibios/$(BOARD) - BOARD_MK += $(TOP_DIR)/platforms/chibios/$(BOARD)/board/board.mk +else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/boards/$(BOARD)/board/board.mk)","") + BOARD_PATH = $(TOP_DIR)/platforms/chibios/boards/$(BOARD) + BOARD_MK += $(TOP_DIR)/platforms/chibios/boards/$(BOARD)/board/board.mk KEYBOARD_PATHS += $(BOARD_PATH)/configs ifneq ("$(wildcard $(BOARD_PATH)/rules.mk)","") include $(BOARD_PATH)/rules.mk @@ -124,10 +124,10 @@ else ifneq ("$(wildcard $(KEYBOARD_PATH_2)/chconf.h)","") CHCONFDIR = $(KEYBOARD_PATH_2) else ifneq ("$(wildcard $(KEYBOARD_PATH_1)/chconf.h)","") CHCONFDIR = $(KEYBOARD_PATH_1) -else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/$(BOARD)/configs/chconf.h)","") - CHCONFDIR = $(TOP_DIR)/platforms/chibios/$(BOARD)/configs -else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/common/configs/chconf.h)","") - CHCONFDIR = $(TOP_DIR)/platforms/chibios/common/configs +else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/boards/$(BOARD)/configs/chconf.h)","") + CHCONFDIR = $(TOP_DIR)/platforms/chibios/boards/$(BOARD)/configs +else ifneq ("$(wildcard $(TOP_DIR)/platforms/boards/chibios/common/configs/chconf.h)","") + CHCONFDIR = $(TOP_DIR)/platforms/chibios/boards/common/configs endif ifneq ("$(wildcard $(KEYBOARD_PATH_5)/halconf.h)","") @@ -140,10 +140,10 @@ else ifneq ("$(wildcard $(KEYBOARD_PATH_2)/halconf.h)","") HALCONFDIR = $(KEYBOARD_PATH_2) else ifneq ("$(wildcard $(KEYBOARD_PATH_1)/halconf.h)","") HALCONFDIR = $(KEYBOARD_PATH_1) -else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/$(BOARD)/configs/halconf.h)","") - HALCONFDIR = $(TOP_DIR)/platforms/chibios/$(BOARD)/configs -else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/common/configs/halconf.h)","") - HALCONFDIR = $(TOP_DIR)/platforms/chibios/common/configs +else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/boards/$(BOARD)/configs/halconf.h)","") + HALCONFDIR = $(TOP_DIR)/platforms/chibios/boards/$(BOARD)/configs +else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/boards/common/configs/halconf.h)","") + HALCONFDIR = $(TOP_DIR)/platforms/chibios/boards/common/configs endif # HAL-OSAL files (optional). @@ -190,11 +190,11 @@ else ifneq ("$(wildcard $(KEYBOARD_PATH_2)/ld/$(MCU_LDSCRIPT).ld)","") LDSCRIPT = $(KEYBOARD_PATH_2)/ld/$(MCU_LDSCRIPT).ld else ifneq ("$(wildcard $(KEYBOARD_PATH_1)/ld/$(MCU_LDSCRIPT).ld)","") LDSCRIPT = $(KEYBOARD_PATH_1)/ld/$(MCU_LDSCRIPT).ld -else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/$(BOARD)/ld/$(MCU_LDSCRIPT).ld)","") - LDFLAGS += -L$(TOP_DIR)/platforms/chibios/$(BOARD)/ld - LDSCRIPT = $(TOP_DIR)/platforms/chibios/$(BOARD)/ld/$(MCU_LDSCRIPT).ld -else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/common/ld/$(MCU_LDSCRIPT).ld)","") - LDSCRIPT = $(TOP_DIR)/platforms/chibios/common/ld/$(MCU_LDSCRIPT).ld +else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/boards/$(BOARD)/ld/$(MCU_LDSCRIPT).ld)","") + LDFLAGS += -L$(TOP_DIR)/platforms/chibios/boards/$(BOARD)/ld + LDSCRIPT = $(TOP_DIR)/platforms/chibios/boards/$(BOARD)/ld/$(MCU_LDSCRIPT).ld +else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/boards/common/ld/$(MCU_LDSCRIPT).ld)","") + LDSCRIPT = $(TOP_DIR)/platforms/chibios/boards/common/ld/$(MCU_LDSCRIPT).ld else ifneq ("$(wildcard $(STARTUPLD_CONTRIB)/$(MCU_LDSCRIPT).ld)","") LDSCRIPT = $(STARTUPLD_CONTRIB)/$(MCU_LDSCRIPT).ld USE_CHIBIOS_CONTRIB = yes @@ -219,8 +219,8 @@ QUANTUM_LIB_SRC += $(STARTUPASM) $(PORTASM) $(OSALASM) $(PLATFORMASM) CHIBISRC := $(patsubst $(TOP_DIR)/%,%,$(CHIBISRC)) EXTRAINCDIRS += $(CHIBIOS)/os/license $(CHIBIOS)/os/oslib/include \ - $(TOP_DIR)/platforms/chibios/$(BOARD)/configs \ - $(TOP_DIR)/platforms/chibios/common/configs \ + $(TOP_DIR)/platforms/chibios/boards/$(BOARD)/configs \ + $(TOP_DIR)/platforms/chibios/boards/common/configs \ $(HALCONFDIR) $(CHCONFDIR) \ $(STARTUPINC) $(KERNINC) $(PORTINC) $(OSALINC) \ $(HALINC) $(PLATFORMINC) $(BOARDINC) $(TESTINC) \ @@ -241,7 +241,7 @@ else ifneq ("$(wildcard $(KEYBOARD_PATH_2)/halconf_community.h)","") USE_CHIBIOS_CONTRIB = yes else ifneq ("$(wildcard $(KEYBOARD_PATH_1)/halconf_community.h)","") USE_CHIBIOS_CONTRIB = yes -else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/$(BOARD)/configs/halconf_community.h)","") +else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/boards/$(BOARD)/configs/halconf_community.h)","") USE_CHIBIOS_CONTRIB = yes endif -- cgit v1.2.3 From 96e2b13d1de227cdc2b918fb0292bd832d346a25 Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Wed, 18 Aug 2021 00:11:07 +0100 Subject: Begin to carve out platform/protocol API - Single main loop (#13843) * Begin to carve out platform/protocol API * Fix up after rebase--- build_keyboard.mk | 6 +- quantum/main.c | 41 ++++++ tmk_core/common.mk | 1 + tmk_core/common/arm_atsam/platform.c | 21 +++ tmk_core/common/avr/platform.c | 21 +++ tmk_core/common/chibios/platform.c | 22 +++ tmk_core/common/test/platform.c | 21 +++ tmk_core/protocol/chibios.mk | 2 +- tmk_core/protocol/chibios/chibios.c | 255 +++++++++++++++++++++++++++++++++ tmk_core/protocol/chibios/main.c | 263 ----------------------------------- tmk_core/protocol/lufa/lufa.c | 64 ++++----- tmk_core/protocol/vusb.mk | 2 +- tmk_core/protocol/vusb/main.c | 179 ------------------------ tmk_core/protocol/vusb/protocol.c | 178 ++++++++++++++++++++++++ 14 files changed, 596 insertions(+), 480 deletions(-) create mode 100644 quantum/main.c create mode 100644 tmk_core/common/arm_atsam/platform.c create mode 100644 tmk_core/common/avr/platform.c create mode 100644 tmk_core/common/chibios/platform.c create mode 100644 tmk_core/common/test/platform.c create mode 100644 tmk_core/protocol/chibios/chibios.c delete mode 100644 tmk_core/protocol/chibios/main.c delete mode 100644 tmk_core/protocol/vusb/main.c create mode 100644 tmk_core/protocol/vusb/protocol.c (limited to 'tmk_core') diff --git a/build_keyboard.mk b/build_keyboard.mk index 62a7ba6a0d..46d1e45667 100644 --- a/build_keyboard.mk +++ b/build_keyboard.mk @@ -338,9 +338,11 @@ ifneq ("$(wildcard $(KEYMAP_PATH)/config.h)","") endif # project specific files -SRC += $(KEYBOARD_SRC) \ +SRC += \ + $(KEYBOARD_SRC) \ $(KEYMAP_C) \ - $(QUANTUM_SRC) + $(QUANTUM_SRC) \ + $(QUANTUM_DIR)/main.c \ # Optimize size but this may cause error "relocation truncated to fit" #EXTRALDFLAGS = -Wl,--relax diff --git a/quantum/main.c b/quantum/main.c new file mode 100644 index 0000000000..2cbcd73d8f --- /dev/null +++ b/quantum/main.c @@ -0,0 +1,41 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "keyboard.h" + +void platform_setup(void); + +void protocol_setup(void); +void protocol_init(void); +void protocol_task(void); + +/** \brief Main + * + * FIXME: Needs doc + */ +int main(void) __attribute__((weak)); +int main(void) { + platform_setup(); + protocol_setup(); + + protocol_init(); + + /* Main loop */ + while (true) { + protocol_task(); + housekeeping_task(); + } +} diff --git a/tmk_core/common.mk b/tmk_core/common.mk index 923a736d35..57de8d95e8 100644 --- a/tmk_core/common.mk +++ b/tmk_core/common.mk @@ -12,6 +12,7 @@ TMK_COMMON_SRC += $(COMMON_DIR)/host.c \ $(COMMON_DIR)/report.c \ $(COMMON_DIR)/sync_timer.c \ $(COMMON_DIR)/usb_util.c \ + $(PLATFORM_COMMON_DIR)/platform.c \ $(PLATFORM_COMMON_DIR)/suspend.c \ $(PLATFORM_COMMON_DIR)/timer.c \ $(PLATFORM_COMMON_DIR)/bootloader.c \ diff --git a/tmk_core/common/arm_atsam/platform.c b/tmk_core/common/arm_atsam/platform.c new file mode 100644 index 0000000000..3e35b4fe4c --- /dev/null +++ b/tmk_core/common/arm_atsam/platform.c @@ -0,0 +1,21 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "platform_deps.h" + +void platform_setup(void) { + // do nothing +} diff --git a/tmk_core/common/avr/platform.c b/tmk_core/common/avr/platform.c new file mode 100644 index 0000000000..3e35b4fe4c --- /dev/null +++ b/tmk_core/common/avr/platform.c @@ -0,0 +1,21 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "platform_deps.h" + +void platform_setup(void) { + // do nothing +} diff --git a/tmk_core/common/chibios/platform.c b/tmk_core/common/chibios/platform.c new file mode 100644 index 0000000000..d4a229f278 --- /dev/null +++ b/tmk_core/common/chibios/platform.c @@ -0,0 +1,22 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "platform_deps.h" + +void platform_setup(void) { + halInit(); + chSysInit(); +} \ No newline at end of file diff --git a/tmk_core/common/test/platform.c b/tmk_core/common/test/platform.c new file mode 100644 index 0000000000..8ddceeda8f --- /dev/null +++ b/tmk_core/common/test/platform.c @@ -0,0 +1,21 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "platform_deps.h" + +void platform_setup(void) { + // do nothing +} \ No newline at end of file diff --git a/tmk_core/protocol/chibios.mk b/tmk_core/protocol/chibios.mk index d01697835b..a7f2d8e93d 100644 --- a/tmk_core/protocol/chibios.mk +++ b/tmk_core/protocol/chibios.mk @@ -3,7 +3,7 @@ CHIBIOS_DIR = $(PROTOCOL_DIR)/chibios SRC += $(CHIBIOS_DIR)/usb_main.c -SRC += $(CHIBIOS_DIR)/main.c +SRC += $(CHIBIOS_DIR)/chibios.c SRC += usb_descriptor.c SRC += $(CHIBIOS_DIR)/usb_driver.c SRC += $(CHIBIOS_DIR)/usb_util.c diff --git a/tmk_core/protocol/chibios/chibios.c b/tmk_core/protocol/chibios/chibios.c new file mode 100644 index 0000000000..78a2e3fcbb --- /dev/null +++ b/tmk_core/protocol/chibios/chibios.c @@ -0,0 +1,255 @@ +/* + * (c) 2015 flabberast + * + * Based on the following work: + * - Guillaume Duc's raw hid example (MIT License) + * https://github.com/guiduc/usb-hid-chibios-example + * - PJRC Teensy examples (MIT License) + * https://www.pjrc.com/teensy/usb_keyboard.html + * - hasu's TMK keyboard code (GPL v2 and some code Modified BSD) + * https://github.com/tmk/tmk_keyboard/ + * - ChibiOS demo code (Apache 2.0 License) + * http://www.chibios.org + * + * Since some GPL'd code is used, this work is licensed under + * GPL v2 or later. + */ + +#include +#include + +#include "usb_main.h" + +/* TMK includes */ +#include "report.h" +#include "host.h" +#include "host_driver.h" +#include "keyboard.h" +#include "action.h" +#include "action_util.h" +#include "mousekey.h" +#include "led.h" +#include "sendchar.h" +#include "debug.h" +#include "print.h" + +#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP +// Change this to be TRUE once we've migrated keyboards to the new init system +// Remember to change docs/platformdev_chibios_earlyinit.md as well. +# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP FALSE +#endif + +#ifdef SLEEP_LED_ENABLE +# include "sleep_led.h" +#endif +#ifdef SERIAL_LINK_ENABLE +# include "serial_link/system/serial_link.h" +#endif +#ifdef VISUALIZER_ENABLE +# include "visualizer/visualizer.h" +#endif +#ifdef MIDI_ENABLE +# include "qmk_midi.h" +#endif +#include "suspend.h" +#include "wait.h" + +/* ------------------------- + * TMK host driver defs + * ------------------------- + */ + +/* declarations */ +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); +void send_digitizer(report_digitizer_t *report); + +/* host struct */ +host_driver_t chibios_driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer}; + +#ifdef VIRTSER_ENABLE +void virtser_task(void); +#endif + +#ifdef RAW_ENABLE +void raw_hid_task(void); +#endif + +#ifdef CONSOLE_ENABLE +void console_task(void); +#endif +#ifdef MIDI_ENABLE +void midi_ep_task(void); +#endif + +/* TESTING + * Amber LED blinker thread, times are in milliseconds. + */ +/* set this variable to non-zero anywhere to blink once */ +// static THD_WORKING_AREA(waThread1, 128); +// static THD_FUNCTION(Thread1, arg) { + +// (void)arg; +// chRegSetThreadName("blinker"); +// while (true) { +// systime_t time; + +// time = USB_DRIVER.state == USB_ACTIVE ? 250 : 500; +// palClearLine(LINE_CAPS_LOCK); +// chSysPolledDelayX(MS2RTC(STM32_HCLK, time)); +// palSetLine(LINE_CAPS_LOCK); +// chSysPolledDelayX(MS2RTC(STM32_HCLK, time)); +// } +// } + +/* Early initialisation + */ +__attribute__((weak)) void early_hardware_init_pre(void) { +#if EARLY_INIT_PERFORM_BOOTLOADER_JUMP + void enter_bootloader_mode_if_requested(void); + enter_bootloader_mode_if_requested(); +#endif // EARLY_INIT_PERFORM_BOOTLOADER_JUMP +} + +__attribute__((weak)) void early_hardware_init_post(void) {} + +__attribute__((weak)) void board_init(void) {} + +// This overrides what's normally in ChibiOS board definitions +void __early_init(void) { + early_hardware_init_pre(); + + // This is the renamed equivalent of __early_init in the board.c file + void __chibios_override___early_init(void); + __chibios_override___early_init(); + + early_hardware_init_post(); +} + +// This overrides what's normally in ChibiOS board definitions +void boardInit(void) { + // This is the renamed equivalent of boardInit in the board.c file + void __chibios_override_boardInit(void); + __chibios_override_boardInit(); + + board_init(); +} + +void protocol_setup(void) { + // TESTING + // chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL); + + keyboard_setup(); +} + +void protocol_init(void) { + /* Init USB */ + usb_event_queue_init(); + init_usb_driver(&USB_DRIVER); + +#ifdef MIDI_ENABLE + setup_midi(); +#endif + +#ifdef SERIAL_LINK_ENABLE + init_serial_link(); +#endif + +#ifdef VISUALIZER_ENABLE + visualizer_init(); +#endif + + host_driver_t *driver = NULL; + + /* Wait until the USB or serial link is active */ + 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(); + break; + } + serial_link_update(); +#endif + wait_ms(50); + } + + /* Do need to wait here! + * Otherwise the next print might start a transfer on console EP + * before the USB is completely ready, which sometimes causes + * HardFaults. + */ + wait_ms(50); + + print("USB configured.\n"); + + /* init TMK modules */ + keyboard_init(); + host_set_driver(driver); + +#ifdef SLEEP_LED_ENABLE + sleep_led_init(); +#endif + + print("Keyboard start.\n"); +} + +void protocol_task(void) { + usb_event_queue_task(); + +#if !defined(NO_USB_STARTUP_CHECK) + if (USB_DRIVER.state == USB_SUSPENDED) { + print("[s]"); +# ifdef VISUALIZER_ENABLE + visualizer_suspend(); +# endif + while (USB_DRIVER.state == USB_SUSPENDED) { + /* Do this in the suspended state */ +# ifdef SERIAL_LINK_ENABLE + serial_link_update(); +# endif + suspend_power_down(); // on AVR this deep sleeps for 15ms + /* Remote wakeup */ + if (suspend_wakeup_condition()) { + usbWakeupHost(&USB_DRIVER); + restart_usb_driver(&USB_DRIVER); + } + } + /* Woken up */ + // variables has been already cleared by the wakeup hook + send_keyboard_report(); +# ifdef MOUSEKEY_ENABLE + mousekey_send(); +# endif /* MOUSEKEY_ENABLE */ + +# ifdef VISUALIZER_ENABLE + visualizer_resume(); +# endif + } +#endif + + keyboard_task(); +#ifdef CONSOLE_ENABLE + console_task(); +#endif +#ifdef MIDI_ENABLE + midi_ep_task(); +#endif +#ifdef VIRTSER_ENABLE + virtser_task(); +#endif +#ifdef RAW_ENABLE + raw_hid_task(); +#endif +} diff --git a/tmk_core/protocol/chibios/main.c b/tmk_core/protocol/chibios/main.c deleted file mode 100644 index e41d6ff195..0000000000 --- a/tmk_core/protocol/chibios/main.c +++ /dev/null @@ -1,263 +0,0 @@ -/* - * (c) 2015 flabberast - * - * Based on the following work: - * - Guillaume Duc's raw hid example (MIT License) - * https://github.com/guiduc/usb-hid-chibios-example - * - PJRC Teensy examples (MIT License) - * https://www.pjrc.com/teensy/usb_keyboard.html - * - hasu's TMK keyboard code (GPL v2 and some code Modified BSD) - * https://github.com/tmk/tmk_keyboard/ - * - ChibiOS demo code (Apache 2.0 License) - * http://www.chibios.org - * - * Since some GPL'd code is used, this work is licensed under - * GPL v2 or later. - */ - -#include -#include - -#include "usb_main.h" - -/* TMK includes */ -#include "report.h" -#include "host.h" -#include "host_driver.h" -#include "keyboard.h" -#include "action.h" -#include "action_util.h" -#include "mousekey.h" -#include "led.h" -#include "sendchar.h" -#include "debug.h" -#include "print.h" - -#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP -// Change this to be TRUE once we've migrated keyboards to the new init system -// Remember to change docs/platformdev_chibios_earlyinit.md as well. -# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP FALSE -#endif - -#ifdef SLEEP_LED_ENABLE -# include "sleep_led.h" -#endif -#ifdef SERIAL_LINK_ENABLE -# include "serial_link/system/serial_link.h" -#endif -#ifdef VISUALIZER_ENABLE -# include "visualizer/visualizer.h" -#endif -#ifdef MIDI_ENABLE -# include "qmk_midi.h" -#endif -#include "suspend.h" -#include "wait.h" - -/* ------------------------- - * TMK host driver defs - * ------------------------- - */ - -/* declarations */ -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); -void send_digitizer(report_digitizer_t *report); - -/* host struct */ -host_driver_t chibios_driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer}; - -#ifdef VIRTSER_ENABLE -void virtser_task(void); -#endif - -#ifdef RAW_ENABLE -void raw_hid_task(void); -#endif - -#ifdef CONSOLE_ENABLE -void console_task(void); -#endif -#ifdef MIDI_ENABLE -void midi_ep_task(void); -#endif - -/* TESTING - * Amber LED blinker thread, times are in milliseconds. - */ -/* set this variable to non-zero anywhere to blink once */ -// static THD_WORKING_AREA(waThread1, 128); -// static THD_FUNCTION(Thread1, arg) { - -// (void)arg; -// chRegSetThreadName("blinker"); -// while (true) { -// systime_t time; - -// time = USB_DRIVER.state == USB_ACTIVE ? 250 : 500; -// palClearLine(LINE_CAPS_LOCK); -// chSysPolledDelayX(MS2RTC(STM32_HCLK, time)); -// palSetLine(LINE_CAPS_LOCK); -// chSysPolledDelayX(MS2RTC(STM32_HCLK, time)); -// } -// } - -/* Early initialisation - */ -__attribute__((weak)) void early_hardware_init_pre(void) { -#if EARLY_INIT_PERFORM_BOOTLOADER_JUMP - void enter_bootloader_mode_if_requested(void); - enter_bootloader_mode_if_requested(); -#endif // EARLY_INIT_PERFORM_BOOTLOADER_JUMP -} - -__attribute__((weak)) void early_hardware_init_post(void) {} - -__attribute__((weak)) void board_init(void) {} - -// This overrides what's normally in ChibiOS board definitions -void __early_init(void) { - early_hardware_init_pre(); - - // This is the renamed equivalent of __early_init in the board.c file - void __chibios_override___early_init(void); - __chibios_override___early_init(); - - early_hardware_init_post(); -} - -// This overrides what's normally in ChibiOS board definitions -void boardInit(void) { - // This is the renamed equivalent of boardInit in the board.c file - void __chibios_override_boardInit(void); - __chibios_override_boardInit(); - - board_init(); -} - -/* Main thread - */ -int main(void) { - /* ChibiOS/RT init */ - halInit(); - chSysInit(); - - // TESTING - // chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL); - - keyboard_setup(); - - /* Init USB */ - usb_event_queue_init(); - init_usb_driver(&USB_DRIVER); - -#ifdef MIDI_ENABLE - setup_midi(); -#endif - -#ifdef SERIAL_LINK_ENABLE - init_serial_link(); -#endif - -#ifdef VISUALIZER_ENABLE - visualizer_init(); -#endif - - host_driver_t *driver = NULL; - - /* Wait until the USB or serial link is active */ - 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(); - break; - } - serial_link_update(); -#endif - wait_ms(50); - } - - /* Do need to wait here! - * Otherwise the next print might start a transfer on console EP - * before the USB is completely ready, which sometimes causes - * HardFaults. - */ - wait_ms(50); - - print("USB configured.\n"); - - /* init TMK modules */ - keyboard_init(); - host_set_driver(driver); - -#ifdef SLEEP_LED_ENABLE - sleep_led_init(); -#endif - - print("Keyboard start.\n"); - - /* Main loop */ - while (true) { - usb_event_queue_task(); - -#if !defined(NO_USB_STARTUP_CHECK) - if (USB_DRIVER.state == USB_SUSPENDED) { - print("[s]"); -# ifdef VISUALIZER_ENABLE - visualizer_suspend(); -# endif - while (USB_DRIVER.state == USB_SUSPENDED) { - /* Do this in the suspended state */ -# ifdef SERIAL_LINK_ENABLE - serial_link_update(); -# endif - suspend_power_down(); // on AVR this deep sleeps for 15ms - /* Remote wakeup */ - if (suspend_wakeup_condition()) { - usbWakeupHost(&USB_DRIVER); - restart_usb_driver(&USB_DRIVER); - } - } - /* Woken up */ - // variables has been already cleared by the wakeup hook - send_keyboard_report(); -# ifdef MOUSEKEY_ENABLE - mousekey_send(); -# endif /* MOUSEKEY_ENABLE */ - -# ifdef VISUALIZER_ENABLE - visualizer_resume(); -# endif - } -#endif - - keyboard_task(); -#ifdef CONSOLE_ENABLE - console_task(); -#endif -#ifdef MIDI_ENABLE - midi_ep_task(); -#endif -#ifdef VIRTSER_ENABLE - virtser_task(); -#endif -#ifdef RAW_ENABLE - raw_hid_task(); -#endif - - // Run housekeeping - housekeeping_task(); - } -} diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c index 8ddb8b1c4b..e638dbc0fb 100644 --- a/tmk_core/protocol/lufa/lufa.c +++ b/tmk_core/protocol/lufa/lufa.c @@ -1033,18 +1033,16 @@ static void setup_usb(void) { USB_Device_EnableSOFEvents(); } -/** \brief Main - * - * FIXME: Needs doc - */ -int main(void) __attribute__((weak)); -int main(void) { +void protocol_setup(void) { #ifdef MIDI_ENABLE setup_midi(); #endif setup_mcu(); keyboard_setup(); +} + +void protocol_init(void) { setup_usb(); sei(); @@ -1078,57 +1076,55 @@ int main(void) { #endif print("Keyboard start.\n"); - while (1) { +} + +void protocol_task(void) { #if !defined(NO_USB_STARTUP_CHECK) - if (USB_DeviceState == DEVICE_STATE_Suspended) { - print("[s]"); - while (USB_DeviceState == DEVICE_STATE_Suspended) { - suspend_power_down(); - if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) { - USB_Device_SendRemoteWakeup(); - clear_keyboard(); + if (USB_DeviceState == DEVICE_STATE_Suspended) { + print("[s]"); + while (USB_DeviceState == DEVICE_STATE_Suspended) { + suspend_power_down(); + if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) { + USB_Device_SendRemoteWakeup(); + clear_keyboard(); # if USB_SUSPEND_WAKEUP_DELAY > 0 - // Some hubs, kvm switches, and monitors do - // weird things, with USB device state bouncing - // around wildly on wakeup, yielding race - // conditions that can corrupt the keyboard state. - // - // Pause for a while to let things settle... - wait_ms(USB_SUSPEND_WAKEUP_DELAY); + // Some hubs, kvm switches, and monitors do + // weird things, with USB device state bouncing + // around wildly on wakeup, yielding race + // conditions that can corrupt the keyboard state. + // + // Pause for a while to let things settle... + wait_ms(USB_SUSPEND_WAKEUP_DELAY); # endif - } } - suspend_wakeup_init(); } + suspend_wakeup_init(); + } #endif - keyboard_task(); + keyboard_task(); #ifdef MIDI_ENABLE - MIDI_Device_USBTask(&USB_MIDI_Interface); + MIDI_Device_USBTask(&USB_MIDI_Interface); #endif #ifdef MODULE_ADAFRUIT_BLE - adafruit_ble_task(); + adafruit_ble_task(); #endif #ifdef VIRTSER_ENABLE - virtser_task(); - CDC_Device_USBTask(&cdc_device); + virtser_task(); + CDC_Device_USBTask(&cdc_device); #endif #ifdef RAW_ENABLE - raw_hid_task(); + raw_hid_task(); #endif #if !defined(INTERRUPT_CONTROL_ENDPOINT) - USB_USBTask(); + USB_USBTask(); #endif - - // Run housekeeping - housekeeping_task(); - } } uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, const uint16_t wIndex, const void **const DescriptorAddress) { return get_usb_descriptor(wValue, wIndex, DescriptorAddress); } diff --git a/tmk_core/protocol/vusb.mk b/tmk_core/protocol/vusb.mk index e4d013b38d..5572597e21 100644 --- a/tmk_core/protocol/vusb.mk +++ b/tmk_core/protocol/vusb.mk @@ -3,7 +3,7 @@ VUSB_DIR = protocol/vusb # Path to the V-USB library VUSB_PATH = $(LIB_PATH)/vusb -SRC += $(VUSB_DIR)/main.c \ +SRC += $(VUSB_DIR)/protocol.c \ $(VUSB_DIR)/vusb.c \ $(VUSB_DIR)/usb_util.c \ $(VUSB_PATH)/usbdrv/usbdrv.c \ diff --git a/tmk_core/protocol/vusb/main.c b/tmk_core/protocol/vusb/main.c deleted file mode 100644 index 53926a7493..0000000000 --- a/tmk_core/protocol/vusb/main.c +++ /dev/null @@ -1,179 +0,0 @@ -/* Name: main.c - * Project: hid-mouse, a very simple HID example - * Author: Christian Starkjohann - * Creation Date: 2008-04-07 - * Tabsize: 4 - * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH - * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) - * This Revision: $Id: main.c 790 2010-05-30 21:00:26Z cs $ - */ - -#include - -#include -#include -#include -#include - -#include - -#include "vusb.h" - -#include "keyboard.h" -#include "host.h" -#include "timer.h" -#include "print.h" -#include "suspend.h" -#include "wait.h" -#include "sendchar.h" - -#ifdef SLEEP_LED_ENABLE -# include "sleep_led.h" -#endif - -#ifdef CONSOLE_ENABLE -void console_task(void); -#endif - -#ifdef RAW_ENABLE -void raw_hid_task(void); -#endif - -/* This is from main.c of USBaspLoader */ -static void initForUsbConnectivity(void) { - uint8_t i = 0; - - usbInit(); - /* enforce USB re-enumerate: */ - usbDeviceDisconnect(); /* do this while interrupts are disabled */ - while (--i) { /* fake USB disconnect for > 250 ms */ - wdt_reset(); - wait_ms(1); - } - usbDeviceConnect(); -} - -static void vusb_send_remote_wakeup(void) { - cli(); - - uint8_t ddr_orig = USBDDR; - USBOUT |= (1 << USBMINUS); - USBDDR = ddr_orig | USBMASK; - USBOUT ^= USBMASK; - - wait_ms(25); - - USBOUT ^= USBMASK; - USBDDR = ddr_orig; - USBOUT &= ~(1 << USBMINUS); - - sei(); -} - -bool vusb_suspended = false; - -static void vusb_suspend(void) { - vusb_suspended = true; - -#ifdef SLEEP_LED_ENABLE - sleep_led_enable(); -#endif - - suspend_power_down(); -} - -#if USB_COUNT_SOF -static void vusb_wakeup(void) { - vusb_suspended = false; - suspend_wakeup_init(); - -# ifdef SLEEP_LED_ENABLE - sleep_led_disable(); -# endif -} -#endif - -/** \brief Setup USB - * - * FIXME: Needs doc - */ -static void setup_usb(void) { initForUsbConnectivity(); } - -/** \brief Main - * - * FIXME: Needs doc - */ -int main(void) __attribute__((weak)); -int main(void) { -#if USB_COUNT_SOF - uint16_t sof_timer = timer_read(); -#endif - -#ifdef CLKPR - // avoid unintentional changes of clock frequency in devices that have a - // clock prescaler - clock_prescale_set(clock_div_1); -#endif - keyboard_setup(); - setup_usb(); - sei(); - keyboard_init(); - host_set_driver(vusb_driver()); - - wait_ms(50); - -#ifdef SLEEP_LED_ENABLE - sleep_led_init(); -#endif - - while (1) { -#if USB_COUNT_SOF - if (usbSofCount != 0) { - usbSofCount = 0; - sof_timer = timer_read(); - if (vusb_suspended) { - vusb_wakeup(); - } - } else { - // Suspend when no SOF in 3ms-10ms(7.1.7.4 Suspending of USB1.1) - if (!vusb_suspended && timer_elapsed(sof_timer) > 5) { - vusb_suspend(); - } - } -#endif - if (vusb_suspended) { - vusb_suspend(); - if (suspend_wakeup_condition()) { - vusb_send_remote_wakeup(); - } - } else { - usbPoll(); - - // TODO: configuration process is inconsistent. it sometime fails. - // To prevent failing to configure NOT scan keyboard during configuration - if (usbConfiguration && usbInterruptIsReady()) { - keyboard_task(); - } - vusb_transfer_keyboard(); - -#ifdef RAW_ENABLE - usbPoll(); - - if (usbConfiguration && usbInterruptIsReady3()) { - raw_hid_task(); - } -#endif - -#ifdef CONSOLE_ENABLE - usbPoll(); - - if (usbConfiguration && usbInterruptIsReady3()) { - console_task(); - } -#endif - - // Run housekeeping - housekeeping_task(); - } - } -} diff --git a/tmk_core/protocol/vusb/protocol.c b/tmk_core/protocol/vusb/protocol.c new file mode 100644 index 0000000000..89dc795b21 --- /dev/null +++ b/tmk_core/protocol/vusb/protocol.c @@ -0,0 +1,178 @@ +/* Name: main.c + * Project: hid-mouse, a very simple HID example + * Author: Christian Starkjohann + * Creation Date: 2008-04-07 + * Tabsize: 4 + * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH + * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) + * This Revision: $Id: main.c 790 2010-05-30 21:00:26Z cs $ + */ + +#include + +#include +#include +#include +#include + +#include + +#include "vusb.h" + +#include "keyboard.h" +#include "host.h" +#include "timer.h" +#include "print.h" +#include "suspend.h" +#include "wait.h" +#include "sendchar.h" + +#ifdef SLEEP_LED_ENABLE +# include "sleep_led.h" +#endif + +#ifdef CONSOLE_ENABLE +void console_task(void); +#endif + +#ifdef RAW_ENABLE +void raw_hid_task(void); +#endif + +/* This is from main.c of USBaspLoader */ +static void initForUsbConnectivity(void) { + uint8_t i = 0; + + usbInit(); + /* enforce USB re-enumerate: */ + usbDeviceDisconnect(); /* do this while interrupts are disabled */ + while (--i) { /* fake USB disconnect for > 250 ms */ + wdt_reset(); + wait_ms(1); + } + usbDeviceConnect(); +} + +static void vusb_send_remote_wakeup(void) { + cli(); + + uint8_t ddr_orig = USBDDR; + USBOUT |= (1 << USBMINUS); + USBDDR = ddr_orig | USBMASK; + USBOUT ^= USBMASK; + + wait_ms(25); + + USBOUT ^= USBMASK; + USBDDR = ddr_orig; + USBOUT &= ~(1 << USBMINUS); + + sei(); +} + +bool vusb_suspended = false; + +static void vusb_suspend(void) { + vusb_suspended = true; + +#ifdef SLEEP_LED_ENABLE + sleep_led_enable(); +#endif + + suspend_power_down(); +} + +#if USB_COUNT_SOF +static void vusb_wakeup(void) { + vusb_suspended = false; + suspend_wakeup_init(); + +# ifdef SLEEP_LED_ENABLE + sleep_led_disable(); +# endif +} +#endif + +/** \brief Setup USB + * + * FIXME: Needs doc + */ +static void setup_usb(void) { initForUsbConnectivity(); } + +uint16_t sof_timer = 0; + +void protocol_setup(void) { +#if USB_COUNT_SOF + sof_timer = timer_read(); +#endif + +#ifdef CLKPR + // avoid unintentional changes of clock frequency in devices that have a + // clock prescaler + clock_prescale_set(clock_div_1); +#endif + keyboard_setup(); +} + +void protocol_init(void) { + setup_usb(); + sei(); + + keyboard_init(); + + host_set_driver(vusb_driver()); + + wait_ms(50); + +#ifdef SLEEP_LED_ENABLE + sleep_led_init(); +#endif +} + +void protocol_task(void) { +#if USB_COUNT_SOF + if (usbSofCount != 0) { + usbSofCount = 0; + sof_timer = timer_read(); + if (vusb_suspended) { + vusb_wakeup(); + } + } else { + // Suspend when no SOF in 3ms-10ms(7.1.7.4 Suspending of USB1.1) + if (!vusb_suspended && timer_elapsed(sof_timer) > 5) { + vusb_suspend(); + } + } +#endif + if (vusb_suspended) { + vusb_suspend(); + if (suspend_wakeup_condition()) { + vusb_send_remote_wakeup(); + } + } else { + usbPoll(); + + // TODO: configuration process is inconsistent. it sometime fails. + // To prevent failing to configure NOT scan keyboard during configuration + if (usbConfiguration && usbInterruptIsReady()) { + keyboard_task(); + } + vusb_transfer_keyboard(); + +#ifdef RAW_ENABLE + usbPoll(); + + if (usbConfiguration && usbInterruptIsReady3()) { + raw_hid_task(); + } +#endif + +#ifdef CONSOLE_ENABLE + usbPoll(); + + if (usbConfiguration && usbInterruptIsReady3()) { + console_task(); + } +#endif + } +} -- cgit v1.2.3 From b8e913c8db73ebf890e4604ee41991a34354a600 Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Wed, 18 Aug 2021 00:18:58 +0100 Subject: Migrate platform independent code from tmk_core -> quantum (#13673) * Migrate action|keyboard|keycode|eeconfig from tmk_core -> quantum--- common_features.mk | 7 + quantum/action.c | 1126 ++++++++++++++++++++++++++++++++++++++ quantum/action.h | 132 +++++ quantum/action_code.h | 308 +++++++++++ quantum/action_layer.c | 279 ++++++++++ quantum/action_layer.h | 147 +++++ quantum/action_macro.c | 93 ++++ quantum/action_macro.h | 123 +++++ quantum/action_tapping.c | 456 +++++++++++++++ quantum/action_tapping.h | 42 ++ quantum/action_util.c | 455 +++++++++++++++ quantum/action_util.h | 105 ++++ quantum/eeconfig.c | 211 +++++++ quantum/eeconfig.h | 113 ++++ quantum/keyboard.c | 569 +++++++++++++++++++ quantum/keyboard.h | 90 +++ quantum/keycode.h | 560 +++++++++++++++++++ quantum/via.h | 2 +- tmk_core/common.mk | 10 +- tmk_core/common/action.c | 1126 -------------------------------------- tmk_core/common/action.h | 132 ----- tmk_core/common/action_code.h | 308 ----------- tmk_core/common/action_layer.c | 279 ---------- tmk_core/common/action_layer.h | 147 ----- tmk_core/common/action_macro.c | 93 ---- tmk_core/common/action_macro.h | 123 ----- tmk_core/common/action_tapping.c | 456 --------------- tmk_core/common/action_tapping.h | 42 -- tmk_core/common/action_util.c | 455 --------------- tmk_core/common/action_util.h | 105 ---- tmk_core/common/eeconfig.c | 211 ------- tmk_core/common/eeconfig.h | 113 ---- tmk_core/common/keyboard.c | 565 ------------------- tmk_core/common/keyboard.h | 90 --- tmk_core/common/keycode.h | 560 ------------------- 35 files changed, 4819 insertions(+), 4814 deletions(-) create mode 100644 quantum/action.c create mode 100644 quantum/action.h create mode 100644 quantum/action_code.h create mode 100644 quantum/action_layer.c create mode 100644 quantum/action_layer.h create mode 100644 quantum/action_macro.c create mode 100644 quantum/action_macro.h create mode 100644 quantum/action_tapping.c create mode 100644 quantum/action_tapping.h create mode 100644 quantum/action_util.c create mode 100644 quantum/action_util.h create mode 100644 quantum/eeconfig.c create mode 100644 quantum/eeconfig.h create mode 100644 quantum/keyboard.c create mode 100644 quantum/keyboard.h create mode 100644 quantum/keycode.h delete mode 100644 tmk_core/common/action.c delete mode 100644 tmk_core/common/action.h delete mode 100644 tmk_core/common/action_code.h delete mode 100644 tmk_core/common/action_layer.c delete mode 100644 tmk_core/common/action_layer.h delete mode 100644 tmk_core/common/action_macro.c delete mode 100644 tmk_core/common/action_macro.h delete mode 100644 tmk_core/common/action_tapping.c delete mode 100644 tmk_core/common/action_tapping.h delete mode 100644 tmk_core/common/action_util.c delete mode 100644 tmk_core/common/action_util.h delete mode 100644 tmk_core/common/eeconfig.c delete mode 100644 tmk_core/common/eeconfig.h delete mode 100644 tmk_core/common/keyboard.c delete mode 100644 tmk_core/common/keyboard.h delete mode 100644 tmk_core/common/keycode.h (limited to 'tmk_core') diff --git a/common_features.mk b/common_features.mk index 1eece0242e..d09d4f1eff 100644 --- a/common_features.mk +++ b/common_features.mk @@ -20,6 +20,13 @@ QUANTUM_SRC += \ $(QUANTUM_DIR)/send_string.c \ $(QUANTUM_DIR)/bitwise.c \ $(QUANTUM_DIR)/led.c \ + $(QUANTUM_DIR)/action.c \ + $(QUANTUM_DIR)/action_layer.c \ + $(QUANTUM_DIR)/action_macro.c \ + $(QUANTUM_DIR)/action_tapping.c \ + $(QUANTUM_DIR)/action_util.c \ + $(QUANTUM_DIR)/eeconfig.c \ + $(QUANTUM_DIR)/keyboard.c \ $(QUANTUM_DIR)/keymap_common.c \ $(QUANTUM_DIR)/keycode_config.c \ $(QUANTUM_DIR)/logging/debug.c \ diff --git a/quantum/action.c b/quantum/action.c new file mode 100644 index 0000000000..d19fd2a045 --- /dev/null +++ b/quantum/action.c @@ -0,0 +1,1126 @@ +/* +Copyright 2012,2013 Jun Wako + +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 . +*/ +#include "host.h" +#include "keycode.h" +#include "keyboard.h" +#include "mousekey.h" +#include "command.h" +#include "led.h" +#include "action_layer.h" +#include "action_tapping.h" +#include "action_macro.h" +#include "action_util.h" +#include "action.h" +#include "wait.h" + +#ifdef BACKLIGHT_ENABLE +# include "backlight.h" +#endif + +#ifdef DEBUG_ACTION +# include "debug.h" +#else +# include "nodebug.h" +#endif + +#ifdef POINTING_DEVICE_ENABLE +# include "pointing_device.h" +#endif + +int tp_buttons; + +#if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) +int retro_tapping_counter = 0; +#endif + +#ifdef IGNORE_MOD_TAP_INTERRUPT_PER_KEY +__attribute__((weak)) bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record) { return false; } +#endif + +#ifdef RETRO_TAPPING_PER_KEY +__attribute__((weak)) bool get_retro_tapping(uint16_t keycode, keyrecord_t *record) { return false; } +#endif + +__attribute__((weak)) bool pre_process_record_quantum(keyrecord_t *record) { return true; } + +#ifndef TAP_CODE_DELAY +# define TAP_CODE_DELAY 0 +#endif +#ifndef TAP_HOLD_CAPS_DELAY +# define TAP_HOLD_CAPS_DELAY 80 +#endif +/** \brief Called to execute an action. + * + * FIXME: Needs documentation. + */ +void action_exec(keyevent_t event) { + if (!IS_NOEVENT(event)) { + dprint("\n---- action_exec: start -----\n"); + dprint("EVENT: "); + debug_event(event); + dprintln(); +#if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) + retro_tapping_counter++; +#endif + } + + if (event.pressed) { + // clear the potential weak mods left by previously pressed keys + clear_weak_mods(); + } + +#ifdef SWAP_HANDS_ENABLE + if (!IS_NOEVENT(event)) { + process_hand_swap(&event); + } +#endif + + keyrecord_t record = {.event = event}; + +#ifndef NO_ACTION_ONESHOT +# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) + if (has_oneshot_layer_timed_out()) { + clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); + } + if (has_oneshot_mods_timed_out()) { + clear_oneshot_mods(); + } +# ifdef SWAP_HANDS_ENABLE + if (has_oneshot_swaphands_timed_out()) { + clear_oneshot_swaphands(); + } +# endif +# endif +#endif + +#ifndef NO_ACTION_TAPPING + if (IS_NOEVENT(record.event) || pre_process_record_quantum(&record)) { + action_tapping_process(record); + } +#else + if (IS_NOEVENT(record.event) || pre_process_record_quantum(&record)) { + process_record(&record); + } + if (!IS_NOEVENT(record.event)) { + dprint("processed: "); + debug_record(record); + dprintln(); + } +#endif +} + +#ifdef SWAP_HANDS_ENABLE +bool swap_hands = false; +bool swap_held = false; + +/** \brief Process Hand Swap + * + * FIXME: Needs documentation. + */ +void process_hand_swap(keyevent_t *event) { + static swap_state_row_t swap_state[MATRIX_ROWS]; + + keypos_t pos = event->key; + swap_state_row_t col_bit = (swap_state_row_t)1 << pos.col; + bool do_swap = event->pressed ? swap_hands : swap_state[pos.row] & (col_bit); + + if (do_swap) { + event->key.row = pgm_read_byte(&hand_swap_config[pos.row][pos.col].row); + event->key.col = pgm_read_byte(&hand_swap_config[pos.row][pos.col].col); + swap_state[pos.row] |= col_bit; + } else { + swap_state[pos.row] &= ~(col_bit); + } +} +#endif + +#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE) +bool disable_action_cache = false; + +void process_record_nocache(keyrecord_t *record) { + disable_action_cache = true; + process_record(record); + disable_action_cache = false; +} +#else +void process_record_nocache(keyrecord_t *record) { process_record(record); } +#endif + +__attribute__((weak)) bool process_record_quantum(keyrecord_t *record) { return true; } + +__attribute__((weak)) void post_process_record_quantum(keyrecord_t *record) {} + +#ifndef NO_ACTION_TAPPING +/** \brief Allows for handling tap-hold actions immediately instead of waiting for TAPPING_TERM or another keypress. + * + * FIXME: Needs documentation. + */ +void process_record_tap_hint(keyrecord_t *record) { + action_t action = layer_switch_get_action(record->event.key); + + switch (action.kind.id) { +# ifdef SWAP_HANDS_ENABLE + case ACT_SWAP_HANDS: + switch (action.swap.code) { + case OP_SH_ONESHOT: + break; + case OP_SH_TAP_TOGGLE: + default: + swap_hands = !swap_hands; + swap_held = true; + } + break; +# endif + } +} +#endif + +/** \brief Take a key event (key press or key release) and processes it. + * + * FIXME: Needs documentation. + */ +void process_record(keyrecord_t *record) { + if (IS_NOEVENT(record->event)) { + return; + } + + if (!process_record_quantum(record)) { +#ifndef NO_ACTION_ONESHOT + if (is_oneshot_layer_active() && record->event.pressed) { + clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); + } +#endif + return; + } + + process_record_handler(record); + post_process_record_quantum(record); +} + +void process_record_handler(keyrecord_t *record) { +#ifdef COMBO_ENABLE + action_t action; + if (record->keycode) { + action = action_for_keycode(record->keycode); + } else { + action = store_or_get_action(record->event.pressed, record->event.key); + } +#else + action_t action = store_or_get_action(record->event.pressed, record->event.key); +#endif + dprint("ACTION: "); + debug_action(action); +#ifndef NO_ACTION_LAYER + dprint(" layer_state: "); + layer_debug(); + dprint(" default_layer_state: "); + default_layer_debug(); +#endif + dprintln(); + + process_action(record, action); +} + +#if defined(PS2_MOUSE_ENABLE) || defined(POINTING_DEVICE_ENABLE) +void register_button(bool pressed, enum mouse_buttons button) { +# ifdef PS2_MOUSE_ENABLE + tp_buttons = pressed ? tp_buttons | button : tp_buttons & ~button; +# endif +# ifdef POINTING_DEVICE_ENABLE + report_mouse_t currentReport = pointing_device_get_report(); + currentReport.buttons = pressed ? currentReport.buttons | button : currentReport.buttons & ~button; + pointing_device_set_report(currentReport); +# endif +} +#endif + +/** \brief Take an action and processes it. + * + * FIXME: Needs documentation. + */ +void process_action(keyrecord_t *record, action_t action) { + keyevent_t event = record->event; +#ifndef NO_ACTION_TAPPING + uint8_t tap_count = record->tap.count; +#endif + +#ifndef NO_ACTION_ONESHOT + bool do_release_oneshot = false; + // notice we only clear the one shot layer if the pressed key is not a modifier. + if (is_oneshot_layer_active() && event.pressed && (action.kind.id == ACT_USAGE || !IS_MOD(action.key.code)) +# ifdef SWAP_HANDS_ENABLE + && !(action.kind.id == ACT_SWAP_HANDS && action.swap.code == OP_SH_ONESHOT) +# endif + ) { + clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); + do_release_oneshot = !is_oneshot_layer_active(); + } +#endif + + switch (action.kind.id) { + /* Key and Mods */ + case ACT_LMODS: + case ACT_RMODS: { + uint8_t mods = (action.kind.id == ACT_LMODS) ? action.key.mods : action.key.mods << 4; + if (event.pressed) { + if (mods) { + if (IS_MOD(action.key.code) || action.key.code == KC_NO) { + // e.g. LSFT(KC_LGUI): we don't want the LSFT to be weak as it would make it useless. + // This also makes LSFT(KC_LGUI) behave exactly the same as LGUI(KC_LSFT). + // Same applies for some keys like KC_MEH which are declared as MEH(KC_NO). + add_mods(mods); + } else { + add_weak_mods(mods); + } + send_keyboard_report(); + } + register_code(action.key.code); + } else { + unregister_code(action.key.code); + if (mods) { + if (IS_MOD(action.key.code) || action.key.code == KC_NO) { + del_mods(mods); + } else { + del_weak_mods(mods); + } + send_keyboard_report(); + } + } + } break; +#ifndef NO_ACTION_TAPPING + case ACT_LMODS_TAP: + case ACT_RMODS_TAP: { + uint8_t mods = (action.kind.id == ACT_LMODS_TAP) ? action.key.mods : action.key.mods << 4; + switch (action.layer_tap.code) { +# ifndef NO_ACTION_ONESHOT + case MODS_ONESHOT: + // Oneshot modifier + if (event.pressed) { + if (tap_count == 0) { + dprint("MODS_TAP: Oneshot: 0\n"); + register_mods(mods | get_oneshot_mods()); + } else if (tap_count == 1) { + dprint("MODS_TAP: Oneshot: start\n"); + set_oneshot_mods(mods | get_oneshot_mods()); +# if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1 + } else if (tap_count == ONESHOT_TAP_TOGGLE) { + dprint("MODS_TAP: Toggling oneshot"); + clear_oneshot_mods(); + set_oneshot_locked_mods(mods); + register_mods(mods); +# endif + } else { + register_mods(mods | get_oneshot_mods()); + } + } else { + if (tap_count == 0) { + clear_oneshot_mods(); + unregister_mods(mods); + } else if (tap_count == 1) { + // Retain Oneshot mods +# if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1 + if (mods & get_mods()) { + clear_oneshot_locked_mods(); + clear_oneshot_mods(); + unregister_mods(mods); + } + } else if (tap_count == ONESHOT_TAP_TOGGLE) { + // Toggle Oneshot Layer +# endif + } else { + clear_oneshot_mods(); + unregister_mods(mods); + } + } + break; +# endif + case MODS_TAP_TOGGLE: + if (event.pressed) { + if (tap_count <= TAPPING_TOGGLE) { + register_mods(mods); + } + } else { + if (tap_count < TAPPING_TOGGLE) { + unregister_mods(mods); + } + } + break; + default: + if (event.pressed) { + if (tap_count > 0) { +# if !defined(IGNORE_MOD_TAP_INTERRUPT) || defined(IGNORE_MOD_TAP_INTERRUPT_PER_KEY) + if ( +# ifdef IGNORE_MOD_TAP_INTERRUPT_PER_KEY + !get_ignore_mod_tap_interrupt(get_event_keycode(record->event, false), record) && +# endif + record->tap.interrupted) { + dprint("mods_tap: tap: cancel: add_mods\n"); + // ad hoc: set 0 to cancel tap + record->tap.count = 0; + register_mods(mods); + } else +# endif + { + dprint("MODS_TAP: Tap: register_code\n"); + register_code(action.key.code); + } + } else { + dprint("MODS_TAP: No tap: add_mods\n"); + register_mods(mods); + } + } else { + if (tap_count > 0) { + dprint("MODS_TAP: Tap: unregister_code\n"); + if (action.layer_tap.code == KC_CAPS) { + wait_ms(TAP_HOLD_CAPS_DELAY); + } else { + wait_ms(TAP_CODE_DELAY); + } + unregister_code(action.key.code); + } else { + dprint("MODS_TAP: No tap: add_mods\n"); + unregister_mods(mods); + } + } + break; + } + } break; +#endif +#ifdef EXTRAKEY_ENABLE + /* other HID usage */ + case ACT_USAGE: + switch (action.usage.page) { + case PAGE_SYSTEM: + if (event.pressed) { + host_system_send(action.usage.code); + } else { + host_system_send(0); + } + break; + case PAGE_CONSUMER: + if (event.pressed) { + host_consumer_send(action.usage.code); + } else { + host_consumer_send(0); + } + break; + } + break; +#endif +#ifdef MOUSEKEY_ENABLE + /* Mouse key */ + case ACT_MOUSEKEY: + if (event.pressed) { + mousekey_on(action.key.code); + } else { + mousekey_off(action.key.code); + } + switch (action.key.code) { +# if defined(PS2_MOUSE_ENABLE) || defined(POINTING_DEVICE_ENABLE) +# ifdef POINTING_DEVICE_ENABLE + case KC_MS_BTN1 ... KC_MS_BTN8: +# else + case KC_MS_BTN1 ... KC_MS_BTN3: +# endif + register_button(event.pressed, MOUSE_BTN_MASK(action.key.code - KC_MS_BTN1)); + break; +# endif + default: + mousekey_send(); + break; + } + break; +#endif +#ifndef NO_ACTION_LAYER + case ACT_LAYER: + if (action.layer_bitop.on == 0) { + /* Default Layer Bitwise Operation */ + if (!event.pressed) { + uint8_t shift = action.layer_bitop.part * 4; + layer_state_t bits = ((layer_state_t)action.layer_bitop.bits) << shift; + layer_state_t mask = (action.layer_bitop.xbit) ? ~(((layer_state_t)0xf) << shift) : 0; + switch (action.layer_bitop.op) { + case OP_BIT_AND: + default_layer_and(bits | mask); + break; + case OP_BIT_OR: + default_layer_or(bits | mask); + break; + case OP_BIT_XOR: + default_layer_xor(bits | mask); + break; + case OP_BIT_SET: + default_layer_set(bits | mask); + break; + } + } + } else { + /* Layer Bitwise Operation */ + if (event.pressed ? (action.layer_bitop.on & ON_PRESS) : (action.layer_bitop.on & ON_RELEASE)) { + uint8_t shift = action.layer_bitop.part * 4; + layer_state_t bits = ((layer_state_t)action.layer_bitop.bits) << shift; + layer_state_t mask = (action.layer_bitop.xbit) ? ~(((layer_state_t)0xf) << shift) : 0; + switch (action.layer_bitop.op) { + case OP_BIT_AND: + layer_and(bits | mask); + break; + case OP_BIT_OR: + layer_or(bits | mask); + break; + case OP_BIT_XOR: + layer_xor(bits | mask); + break; + case OP_BIT_SET: + layer_state_set(bits | mask); + break; + } + } + } + break; + case ACT_LAYER_MODS: + if (event.pressed) { + layer_on(action.layer_mods.layer); + register_mods(action.layer_mods.mods); + } else { + unregister_mods(action.layer_mods.mods); + layer_off(action.layer_mods.layer); + } + break; +# ifndef NO_ACTION_TAPPING + case ACT_LAYER_TAP: + case ACT_LAYER_TAP_EXT: + switch (action.layer_tap.code) { + case OP_TAP_TOGGLE: + /* tap toggle */ + if (event.pressed) { + if (tap_count < TAPPING_TOGGLE) { + layer_invert(action.layer_tap.val); + } + } else { + if (tap_count <= TAPPING_TOGGLE) { + layer_invert(action.layer_tap.val); + } + } + break; + case OP_ON_OFF: + event.pressed ? layer_on(action.layer_tap.val) : layer_off(action.layer_tap.val); + break; + case OP_OFF_ON: + event.pressed ? layer_off(action.layer_tap.val) : layer_on(action.layer_tap.val); + break; + case OP_SET_CLEAR: + event.pressed ? layer_move(action.layer_tap.val) : layer_clear(); + break; +# ifndef NO_ACTION_ONESHOT + case OP_ONESHOT: + // Oneshot modifier +# if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1 + do_release_oneshot = false; + if (event.pressed) { + del_mods(get_oneshot_locked_mods()); + if (get_oneshot_layer_state() == ONESHOT_TOGGLED) { + reset_oneshot_layer(); + layer_off(action.layer_tap.val); + break; + } else if (tap_count < ONESHOT_TAP_TOGGLE) { + layer_on(action.layer_tap.val); + set_oneshot_layer(action.layer_tap.val, ONESHOT_START); + } + } else { + add_mods(get_oneshot_locked_mods()); + if (tap_count >= ONESHOT_TAP_TOGGLE) { + reset_oneshot_layer(); + clear_oneshot_locked_mods(); + set_oneshot_layer(action.layer_tap.val, ONESHOT_TOGGLED); + } else { + clear_oneshot_layer_state(ONESHOT_PRESSED); + } + } +# else + if (event.pressed) { + layer_on(action.layer_tap.val); + set_oneshot_layer(action.layer_tap.val, ONESHOT_START); + } else { + clear_oneshot_layer_state(ONESHOT_PRESSED); + if (tap_count > 1) { + clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); + } + } +# endif + break; +# endif + default: + /* tap key */ + if (event.pressed) { + if (tap_count > 0) { + dprint("KEYMAP_TAP_KEY: Tap: register_code\n"); + register_code(action.layer_tap.code); + } else { + dprint("KEYMAP_TAP_KEY: No tap: On on press\n"); + layer_on(action.layer_tap.val); + } + } else { + if (tap_count > 0) { + dprint("KEYMAP_TAP_KEY: Tap: unregister_code\n"); + if (action.layer_tap.code == KC_CAPS) { + wait_ms(TAP_HOLD_CAPS_DELAY); + } else { + wait_ms(TAP_CODE_DELAY); + } + unregister_code(action.layer_tap.code); + } else { + dprint("KEYMAP_TAP_KEY: No tap: Off on release\n"); + layer_off(action.layer_tap.val); + } + } + break; + } + break; +# endif +#endif + /* Extentions */ +#ifndef NO_ACTION_MACRO + case ACT_MACRO: + action_macro_play(action_get_macro(record, action.func.id, action.func.opt)); + break; +#endif +#ifdef SWAP_HANDS_ENABLE + case ACT_SWAP_HANDS: + switch (action.swap.code) { + case OP_SH_TOGGLE: + if (event.pressed) { + swap_hands = !swap_hands; + } + break; + case OP_SH_ON_OFF: + swap_hands = event.pressed; + break; + case OP_SH_OFF_ON: + swap_hands = !event.pressed; + break; + case OP_SH_ON: + if (!event.pressed) { + swap_hands = true; + } + break; + case OP_SH_OFF: + if (!event.pressed) { + swap_hands = false; + } + break; +# ifndef NO_ACTION_ONESHOT + case OP_SH_ONESHOT: + if (event.pressed) { + set_oneshot_swaphands(); + } else { + release_oneshot_swaphands(); + } + break; +# endif + +# ifndef NO_ACTION_TAPPING + case OP_SH_TAP_TOGGLE: + /* tap toggle */ + + if (event.pressed) { + if (swap_held) { + swap_held = false; + } else { + swap_hands = !swap_hands; + } + } else { + if (tap_count < TAPPING_TOGGLE) { + swap_hands = !swap_hands; + } + } + break; + default: + /* tap key */ + if (tap_count > 0) { + if (swap_held) { + swap_hands = !swap_hands; // undo hold set up in _tap_hint + swap_held = false; + } + if (event.pressed) { + register_code(action.swap.code); + } else { + wait_ms(TAP_CODE_DELAY); + unregister_code(action.swap.code); + *record = (keyrecord_t){}; // hack: reset tap mode + } + } else { + if (swap_held && !event.pressed) { + swap_hands = !swap_hands; // undo hold set up in _tap_hint + swap_held = false; + } + } +# endif + } +#endif +#ifndef NO_ACTION_FUNCTION + case ACT_FUNCTION: + action_function(record, action.func.id, action.func.opt); + break; +#endif + default: + break; + } + +#ifndef NO_ACTION_LAYER + // if this event is a layer action, update the leds + switch (action.kind.id) { + case ACT_LAYER: + case ACT_LAYER_MODS: +# ifndef NO_ACTION_TAPPING + case ACT_LAYER_TAP: + case ACT_LAYER_TAP_EXT: +# endif + led_set(host_keyboard_leds()); + break; + default: + break; + } +#endif + +#ifndef NO_ACTION_TAPPING +# if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) + if (!is_tap_action(action)) { + retro_tapping_counter = 0; + } else { + if (event.pressed) { + if (tap_count > 0) { + retro_tapping_counter = 0; + } + } else { + if (tap_count > 0) { + retro_tapping_counter = 0; + } else { + if ( +# ifdef RETRO_TAPPING_PER_KEY + get_retro_tapping(get_event_keycode(record->event, false), record) && +# endif + retro_tapping_counter == 2) { + tap_code(action.layer_tap.code); + } + retro_tapping_counter = 0; + } + } + } +# endif +#endif + +#ifdef SWAP_HANDS_ENABLE +# ifndef NO_ACTION_ONESHOT + if (event.pressed && !(action.kind.id == ACT_SWAP_HANDS && action.swap.code == OP_SH_ONESHOT)) { + use_oneshot_swaphands(); + } +# endif +#endif + +#ifndef NO_ACTION_ONESHOT + /* Because we switch layers after a oneshot event, we need to release the + * key before we leave the layer or no key up event will be generated. + */ + if (do_release_oneshot && !(get_oneshot_layer_state() & ONESHOT_PRESSED)) { + record->event.pressed = false; + layer_on(get_oneshot_layer()); + process_record(record); + layer_off(get_oneshot_layer()); + } +#endif +} + +/** \brief Utilities for actions. (FIXME: Needs better description) + * + * FIXME: Needs documentation. + */ +void register_code(uint8_t code) { + if (code == KC_NO) { + return; + } +#ifdef LOCKING_SUPPORT_ENABLE + else if (KC_LOCKING_CAPS == code) { +# ifdef LOCKING_RESYNC_ENABLE + // Resync: ignore if caps lock already is on + if (host_keyboard_leds() & (1 << USB_LED_CAPS_LOCK)) return; +# endif + add_key(KC_CAPSLOCK); + send_keyboard_report(); + wait_ms(100); + del_key(KC_CAPSLOCK); + send_keyboard_report(); + } + + else if (KC_LOCKING_NUM == code) { +# ifdef LOCKING_RESYNC_ENABLE + if (host_keyboard_leds() & (1 << USB_LED_NUM_LOCK)) return; +# endif + add_key(KC_NUMLOCK); + send_keyboard_report(); + wait_ms(100); + del_key(KC_NUMLOCK); + send_keyboard_report(); + } + + else if (KC_LOCKING_SCROLL == code) { +# ifdef LOCKING_RESYNC_ENABLE + if (host_keyboard_leds() & (1 << USB_LED_SCROLL_LOCK)) return; +# endif + add_key(KC_SCROLLLOCK); + send_keyboard_report(); + wait_ms(100); + del_key(KC_SCROLLLOCK); + send_keyboard_report(); + } +#endif + + else if IS_KEY (code) { + // TODO: should push command_proc out of this block? + if (command_proc(code)) return; + +#ifndef NO_ACTION_ONESHOT +/* TODO: remove + if (oneshot_state.mods && !oneshot_state.disabled) { + uint8_t tmp_mods = get_mods(); + add_mods(oneshot_state.mods); + + add_key(code); + send_keyboard_report(); + + set_mods(tmp_mods); + send_keyboard_report(); + oneshot_cancel(); + } else +*/ +#endif + { + // Force a new key press if the key is already pressed + // without this, keys with the same keycode, but different + // modifiers will be reported incorrectly, see issue #1708 + if (is_key_pressed(keyboard_report, code)) { + del_key(code); + send_keyboard_report(); + } + add_key(code); + send_keyboard_report(); + } + } else if IS_MOD (code) { + add_mods(MOD_BIT(code)); + send_keyboard_report(); + } +#ifdef EXTRAKEY_ENABLE + else if IS_SYSTEM (code) { + host_system_send(KEYCODE2SYSTEM(code)); + } else if IS_CONSUMER (code) { + host_consumer_send(KEYCODE2CONSUMER(code)); + } +#endif +#ifdef MOUSEKEY_ENABLE + else if IS_MOUSEKEY (code) { + mousekey_on(code); + mousekey_send(); + } +#endif +} + +/** \brief Utilities for actions. (FIXME: Needs better description) + * + * FIXME: Needs documentation. + */ +void unregister_code(uint8_t code) { + if (code == KC_NO) { + return; + } +#ifdef LOCKING_SUPPORT_ENABLE + else if (KC_LOCKING_CAPS == code) { +# ifdef LOCKING_RESYNC_ENABLE + // Resync: ignore if caps lock already is off + if (!(host_keyboard_leds() & (1 << USB_LED_CAPS_LOCK))) return; +# endif + add_key(KC_CAPSLOCK); + send_keyboard_report(); + del_key(KC_CAPSLOCK); + send_keyboard_report(); + } + + else if (KC_LOCKING_NUM == code) { +# ifdef LOCKING_RESYNC_ENABLE + if (!(host_keyboard_leds() & (1 << USB_LED_NUM_LOCK))) return; +# endif + add_key(KC_NUMLOCK); + send_keyboard_report(); + del_key(KC_NUMLOCK); + send_keyboard_report(); + } + + else if (KC_LOCKING_SCROLL == code) { +# ifdef LOCKING_RESYNC_ENABLE + if (!(host_keyboard_leds() & (1 << USB_LED_SCROLL_LOCK))) return; +# endif + add_key(KC_SCROLLLOCK); + send_keyboard_report(); + del_key(KC_SCROLLLOCK); + send_keyboard_report(); + } +#endif + + else if IS_KEY (code) { + del_key(code); + send_keyboard_report(); + } else if IS_MOD (code) { + del_mods(MOD_BIT(code)); + send_keyboard_report(); + } else if IS_SYSTEM (code) { + host_system_send(0); + } else if IS_CONSUMER (code) { + host_consumer_send(0); + } +#ifdef MOUSEKEY_ENABLE + else if IS_MOUSEKEY (code) { + mousekey_off(code); + mousekey_send(); + } +#endif +} + +/** \brief Tap a keycode with a delay. + * + * \param code The basic keycode to tap. + * \param delay The amount of time in milliseconds to leave the keycode registered, before unregistering it. + */ +void tap_code_delay(uint8_t code, uint16_t delay) { + register_code(code); + for (uint16_t i = delay; i > 0; i--) { + wait_ms(1); + } + unregister_code(code); +} + +/** \brief Tap a keycode with the default delay. + * + * \param code The basic keycode to tap. If `code` is `KC_CAPS`, the delay will be `TAP_HOLD_CAPS_DELAY`, otherwise `TAP_CODE_DELAY`, if defined. + */ +void tap_code(uint8_t code) { tap_code_delay(code, code == KC_CAPS ? TAP_HOLD_CAPS_DELAY : TAP_CODE_DELAY); } + +/** \brief Adds the given physically pressed modifiers and sends a keyboard report immediately. + * + * \param mods A bitfield of modifiers to register. + */ +void register_mods(uint8_t mods) { + if (mods) { + add_mods(mods); + send_keyboard_report(); + } +} + +/** \brief Removes the given physically pressed modifiers and sends a keyboard report immediately. + * + * \param mods A bitfield of modifiers to unregister. + */ +void unregister_mods(uint8_t mods) { + if (mods) { + del_mods(mods); + send_keyboard_report(); + } +} + +/** \brief Adds the given weak modifiers and sends a keyboard report immediately. + * + * \param mods A bitfield of modifiers to register. + */ +void register_weak_mods(uint8_t mods) { + if (mods) { + add_weak_mods(mods); + send_keyboard_report(); + } +} + +/** \brief Removes the given weak modifiers and sends a keyboard report immediately. + * + * \param mods A bitfield of modifiers to unregister. + */ +void unregister_weak_mods(uint8_t mods) { + if (mods) { + del_weak_mods(mods); + send_keyboard_report(); + } +} + +/** \brief Utilities for actions. (FIXME: Needs better description) + * + * FIXME: Needs documentation. + */ +void clear_keyboard(void) { + clear_mods(); + clear_keyboard_but_mods(); +} + +/** \brief Utilities for actions. (FIXME: Needs better description) + * + * 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() { +#ifdef EXTRAKEY_ENABLE + host_system_send(0); + host_consumer_send(0); +#endif + clear_weak_mods(); + clear_macro_mods(); + send_keyboard_report(); +#ifdef MOUSEKEY_ENABLE + mousekey_clear(); + mousekey_send(); +#endif +} + +/** \brief Utilities for actions. (FIXME: Needs better description) + * + * FIXME: Needs documentation. + */ +bool is_tap_key(keypos_t key) { + action_t action = layer_switch_get_action(key); + return is_tap_action(action); +} + +/** \brief Utilities for actions. (FIXME: Needs better description) + * + * FIXME: Needs documentation. + */ +bool is_tap_record(keyrecord_t *record) { +#ifdef COMBO_ENABLE + action_t action; + if (record->keycode) { + action = action_for_keycode(record->keycode); + } else { + action = layer_switch_get_action(record->event.key); + } +#else + action_t action = layer_switch_get_action(record->event.key); +#endif + return is_tap_action(action); +} + +/** \brief Utilities for actions. (FIXME: Needs better description) + * + * FIXME: Needs documentation. + */ +bool is_tap_action(action_t action) { + switch (action.kind.id) { + case ACT_LMODS_TAP: + case ACT_RMODS_TAP: + case ACT_LAYER_TAP: + case ACT_LAYER_TAP_EXT: + switch (action.layer_tap.code) { + case KC_NO ... KC_RGUI: + case OP_TAP_TOGGLE: + case OP_ONESHOT: + return true; + } + return false; + case ACT_SWAP_HANDS: + switch (action.swap.code) { + case KC_NO ... KC_RGUI: + case OP_SH_TAP_TOGGLE: + return true; + } + return false; + case ACT_MACRO: + case ACT_FUNCTION: + if (action.func.opt & FUNC_TAP) { + return true; + } + return false; + } + return false; +} + +/** \brief Debug print (FIXME: Needs better description) + * + * FIXME: Needs documentation. + */ +void debug_event(keyevent_t event) { dprintf("%04X%c(%u)", (event.key.row << 8 | event.key.col), (event.pressed ? 'd' : 'u'), event.time); } +/** \brief Debug print (FIXME: Needs better description) + * + * FIXME: Needs documentation. + */ +void debug_record(keyrecord_t record) { + debug_event(record.event); +#ifndef NO_ACTION_TAPPING + dprintf(":%u%c", record.tap.count, (record.tap.interrupted ? '-' : ' ')); +#endif +} + +/** \brief Debug print (FIXME: Needs better description) + * + * FIXME: Needs documentation. + */ +void debug_action(action_t action) { + switch (action.kind.id) { + case ACT_LMODS: + dprint("ACT_LMODS"); + break; + case ACT_RMODS: + dprint("ACT_RMODS"); + break; + case ACT_LMODS_TAP: + dprint("ACT_LMODS_TAP"); + break; + case ACT_RMODS_TAP: + dprint("ACT_RMODS_TAP"); + break; + case ACT_USAGE: + dprint("ACT_USAGE"); + break; + case ACT_MOUSEKEY: + dprint("ACT_MOUSEKEY"); + break; + case ACT_LAYER: + dprint("ACT_LAYER"); + break; + case ACT_LAYER_MODS: + dprint("ACT_LAYER_MODS"); + break; + case ACT_LAYER_TAP: + dprint("ACT_LAYER_TAP"); + break; + case ACT_LAYER_TAP_EXT: + dprint("ACT_LAYER_TAP_EXT"); + break; + case ACT_MACRO: + dprint("ACT_MACRO"); + break; + case ACT_FUNCTION: + dprint("ACT_FUNCTION"); + break; + case ACT_SWAP_HANDS: + dprint("ACT_SWAP_HANDS"); + break; + default: + dprint("UNKNOWN"); + break; + } + dprintf("[%X:%02X]", action.kind.param >> 8, action.kind.param & 0xff); +} diff --git a/quantum/action.h b/quantum/action.h new file mode 100644 index 0000000000..3d357b33b8 --- /dev/null +++ b/quantum/action.h @@ -0,0 +1,132 @@ +/* +Copyright 2012,2013 Jun Wako + +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 . +*/ + +#pragma once + +#include +#include +#include "keyboard.h" +#include "keycode.h" +#include "action_code.h" +#include "action_macro.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Disable macro and function features when LTO is enabled, since they break */ +#ifdef LTO_ENABLE +# ifndef NO_ACTION_MACRO +# define NO_ACTION_MACRO +# endif +# ifndef NO_ACTION_FUNCTION +# define NO_ACTION_FUNCTION +# endif +#endif + +/* tapping count and state */ +typedef struct { + bool interrupted : 1; + bool reserved2 : 1; + bool reserved1 : 1; + bool reserved0 : 1; + uint8_t count : 4; +} tap_t; + +/* Key event container for recording */ +typedef struct { + keyevent_t event; +#ifndef NO_ACTION_TAPPING + tap_t tap; +#endif +#ifdef COMBO_ENABLE + uint16_t keycode; +#endif +} keyrecord_t; + +/* Execute action per keyevent */ +void action_exec(keyevent_t event); + +/* action for key */ +action_t action_for_key(uint8_t layer, keypos_t key); +action_t action_for_keycode(uint16_t keycode); + +/* macro */ +const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt); + +/* user defined special function */ +void action_function(keyrecord_t *record, uint8_t id, uint8_t opt); + +/* keyboard-specific key event (pre)processing */ +bool process_record_quantum(keyrecord_t *record); + +/* Utilities for actions. */ +#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE) +extern bool disable_action_cache; +#endif + +/* Code for handling one-handed key modifiers. */ +#ifdef SWAP_HANDS_ENABLE +extern bool swap_hands; +extern const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS]; +# if (MATRIX_COLS <= 8) +typedef uint8_t swap_state_row_t; +# elif (MATRIX_COLS <= 16) +typedef uint16_t swap_state_row_t; +# elif (MATRIX_COLS <= 32) +typedef uint32_t swap_state_row_t; +# else +# error "MATRIX_COLS: invalid value" +# endif + +void process_hand_swap(keyevent_t *record); +#endif + +void process_record_nocache(keyrecord_t *record); +void process_record(keyrecord_t *record); +void process_record_handler(keyrecord_t *record); +void post_process_record_quantum(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 tap_code_delay(uint8_t code, uint16_t delay); +void register_mods(uint8_t mods); +void unregister_mods(uint8_t mods); +void register_weak_mods(uint8_t mods); +void unregister_weak_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); +bool is_tap_record(keyrecord_t *record); +bool is_tap_action(action_t action); + +#ifndef NO_ACTION_TAPPING +void process_record_tap_hint(keyrecord_t *record); +#endif + +/* debug */ +void debug_event(keyevent_t event); +void debug_record(keyrecord_t record); +void debug_action(action_t action); + +#ifdef __cplusplus +} +#endif diff --git a/quantum/action_code.h b/quantum/action_code.h new file mode 100644 index 0000000000..eb18c36ae8 --- /dev/null +++ b/quantum/action_code.h @@ -0,0 +1,308 @@ +/* +Copyright 2013 Jun Wako + +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 . +*/ + +#pragma once + +/** \brief Action codes + * + * 16bit code: action_kind(4bit) + action_parameter(12bit) + * + * Key Actions(00xx) + * ----------------- + * ACT_MODS(000r): + * 000r|0000|0000 0000 No action code + * 000r|0000|0000 0001 Transparent code + * 000r|0000| keycode Key + * 000r|mods|0000 0000 Modifiers + * 000r|mods| keycode Modifiers+Key(Modified key) + * r: Left/Right flag(Left:0, Right:1) + * + * ACT_MODS_TAP(001r): + * 001r|mods|0000 0000 Modifiers with OneShot + * 001r|mods|0000 0001 Modifiers with tap toggle + * 001r|mods|0000 00xx (reserved) + * 001r|mods| keycode Modifiers with Tap Key(Dual role) + * + * Other Keys(01xx) + * ---------------- + * ACT_USAGE(0100): TODO: Not needed? + * 0100|00| usage(10) System control(0x80) - General Desktop page(0x01) + * 0100|01| usage(10) Consumer control(0x01) - Consumer page(0x0C) + * 0100|10| usage(10) (reserved) + * 0100|11| usage(10) (reserved) + * + * ACT_MOUSEKEY(0101): TODO: Merge these two actions to conserve space? + * 0101|xxxx| keycode Mouse key + * + * ACT_SWAP_HANDS(0110): + * 0110|xxxx| keycode Swap hands (keycode on tap, or options) + * + * 0111|xxxx xxxx xxxx (reserved) + * + * Layer Actions(10xx) + * ------------------- + * ACT_LAYER(1000): + * 1000|oo00|pppE BBBB Default Layer Bitwise operation + * oo: operation(00:AND, 01:OR, 10:XOR, 11:SET) + * ppp: 4-bit chunk part(0-7) + * EBBBB: bits and extra bit + * 1000|ooee|pppE BBBB Layer Bitwise Operation + * oo: operation(00:AND, 01:OR, 10:XOR, 11:SET) + * ppp: 4-bit chunk part(0-7) + * EBBBB: bits and extra bit + * ee: on event(01:press, 10:release, 11:both) + * + * ACT_LAYER_MODS(1001): + * 1001|LLLL| mods Layer with modifiers held + * + * ACT_LAYER_TAP(101x): + * 101E|LLLL| keycode On/Off with tap key (0x00-DF)[TAP] + * 101E|LLLL|1110 mods On/Off with modifiers (0xE0-EF)[NOT TAP] + * 101E|LLLL|1111 0000 Invert with tap toggle (0xF0) [TAP] + * 101E|LLLL|1111 0001 On/Off (0xF1) [NOT TAP] + * 101E|LLLL|1111 0010 Off/On (0xF2) [NOT TAP] + * 101E|LLLL|1111 0011 Set/Clear (0xF3) [NOT TAP] + * 101E|LLLL|1111 0100 One Shot Layer (0xF4) [TAP] + * 101E|LLLL|1111 xxxx Reserved (0xF5-FF) + * ELLLL: layer 0-31(E: extra bit for layer 16-31) + * + * Extensions(11xx) + * ---------------- + * ACT_MACRO(1100): + * 1100|opt | id(8) Macro play? + * 1100|1111| id(8) Macro record? + * + * 1101|xxxx xxxx xxxx (reserved) + * 1110|xxxx xxxx xxxx (reserved) + * + * ACT_FUNCTION(1111): + * 1111| address(12) Function? + * 1111|opt | id(8) Function? + */ +enum action_kind_id { + /* Key Actions */ + ACT_MODS = 0b0000, + ACT_LMODS = 0b0000, + ACT_RMODS = 0b0001, + ACT_MODS_TAP = 0b0010, + ACT_LMODS_TAP = 0b0010, + ACT_RMODS_TAP = 0b0011, + /* Other Keys */ + ACT_USAGE = 0b0100, + ACT_MOUSEKEY = 0b0101, + /* One-hand Support */ + ACT_SWAP_HANDS = 0b0110, + /* Layer Actions */ + ACT_LAYER = 0b1000, + ACT_LAYER_MODS = 0b1001, + ACT_LAYER_TAP = 0b1010, /* Layer 0-15 */ + ACT_LAYER_TAP_EXT = 0b1011, /* Layer 16-31 */ + /* Extensions */ + ACT_MACRO = 0b1100, + ACT_FUNCTION = 0b1111 +}; + +/** \brief Action Code Struct + * + * NOTE: + * In avr-gcc bit field seems to be assigned from LSB(bit0) to MSB(bit15). + * AVR looks like a little endian in avr-gcc. + * Not portable across compiler/endianness? + * + * Byte order and bit order of 0x1234: + * Big endian: Little endian: + * -------------------- -------------------- + * FEDC BA98 7654 3210 0123 4567 89AB CDEF + * 0001 0010 0011 0100 0010 1100 0100 1000 + * 0x12 0x34 0x34 0x12 + */ +typedef union { + uint16_t code; + struct action_kind { + uint16_t param : 12; + uint8_t id : 4; + } kind; + struct action_key { + uint8_t code : 8; + uint8_t mods : 4; + uint8_t kind : 4; + } key; + struct action_layer_bitop { + uint8_t bits : 4; + uint8_t xbit : 1; + uint8_t part : 3; + uint8_t on : 2; + uint8_t op : 2; + uint8_t kind : 4; + } layer_bitop; + struct action_layer_mods { + uint8_t mods : 8; + uint8_t layer : 4; + uint8_t kind : 4; + } layer_mods; + struct action_layer_tap { + uint8_t code : 8; + uint8_t val : 5; + uint8_t kind : 3; + } layer_tap; + struct action_usage { + uint16_t code : 10; + uint8_t page : 2; + uint8_t kind : 4; + } usage; + struct action_function { + uint8_t id : 8; + uint8_t opt : 4; + uint8_t kind : 4; + } func; + struct action_swap { + uint8_t code : 8; + uint8_t opt : 4; + uint8_t kind : 4; + } swap; +} action_t; + +/* action utility */ +#define ACTION_NO 0 +#define ACTION_TRANSPARENT 1 +#define ACTION(kind, param) ((kind) << 12 | (param)) + +/** \brief Key Actions + * + * Mod bits: 43210 + * bit 0 ||||+- Control + * bit 1 |||+-- Shift + * bit 2 ||+--- Alt + * bit 3 |+---- Gui + * bit 4 +----- LR flag(Left:0, Right:1) + */ +enum mods_bit { + MOD_LCTL = 0x01, + MOD_LSFT = 0x02, + MOD_LALT = 0x04, + MOD_LGUI = 0x08, + MOD_RCTL = 0x11, + MOD_RSFT = 0x12, + MOD_RALT = 0x14, + MOD_RGUI = 0x18, +}; +enum mods_codes { + MODS_ONESHOT = 0x00, + MODS_TAP_TOGGLE = 0x01, +}; +#define ACTION_KEY(key) ACTION(ACT_MODS, (key)) +#define ACTION_MODS(mods) ACTION(ACT_MODS, ((mods)&0x1f) << 8 | 0) +#define ACTION_MODS_KEY(mods, key) ACTION(ACT_MODS, ((mods)&0x1f) << 8 | (key)) +#define ACTION_MODS_TAP_KEY(mods, key) ACTION(ACT_MODS_TAP, ((mods)&0x1f) << 8 | (key)) +#define ACTION_MODS_ONESHOT(mods) ACTION(ACT_MODS_TAP, ((mods)&0x1f) << 8 | MODS_ONESHOT) +#define ACTION_MODS_TAP_TOGGLE(mods) ACTION(ACT_MODS_TAP, ((mods)&0x1f) << 8 | MODS_TAP_TOGGLE) + +/** \brief Other Keys + */ +enum usage_pages { PAGE_SYSTEM, PAGE_CONSUMER }; +#define ACTION_USAGE_SYSTEM(id) ACTION(ACT_USAGE, PAGE_SYSTEM << 10 | (id)) +#define ACTION_USAGE_CONSUMER(id) ACTION(ACT_USAGE, PAGE_CONSUMER << 10 | (id)) +#define ACTION_MOUSEKEY(key) ACTION(ACT_MOUSEKEY, key) + +/** \brief Layer Actions + */ +enum layer_param_on { + ON_PRESS = 1, + ON_RELEASE = 2, + ON_BOTH = 3, +}; + +/** \brief Layer Actions + */ +enum layer_param_bit_op { + OP_BIT_AND = 0, + OP_BIT_OR = 1, + OP_BIT_XOR = 2, + OP_BIT_SET = 3, +}; + +/** \brief Layer Actions + */ +enum layer_param_tap_op { + OP_TAP_TOGGLE = 0xF0, + OP_ON_OFF, + OP_OFF_ON, + OP_SET_CLEAR, + OP_ONESHOT, +}; +#define ACTION_LAYER_BITOP(op, part, bits, on) ACTION(ACT_LAYER, (op) << 10 | (on) << 8 | (part) << 5 | ((bits)&0x1f)) +#define ACTION_LAYER_TAP(layer, key) ACTION(ACT_LAYER_TAP, (layer) << 8 | (key)) +/* Default Layer */ +#define ACTION_DEFAULT_LAYER_SET(layer) ACTION_DEFAULT_LAYER_BIT_SET((layer) / 4, 1 << ((layer) % 4)) +/* Layer Operation */ +#define ACTION_LAYER_CLEAR(on) ACTION_LAYER_BIT_AND(0, 0, (on)) +#define ACTION_LAYER_MOMENTARY(layer) ACTION_LAYER_ON_OFF(layer) +#define ACTION_LAYER_TOGGLE(layer) ACTION_LAYER_INVERT(layer, ON_RELEASE) +#define ACTION_LAYER_INVERT(layer, on) ACTION_LAYER_BIT_XOR((layer) / 4, 1 << ((layer) % 4), (on)) +#define ACTION_LAYER_ON(layer, on) ACTION_LAYER_BIT_OR((layer) / 4, 1 << ((layer) % 4), (on)) +#define ACTION_LAYER_OFF(layer, on) ACTION_LAYER_BIT_AND((layer) / 4, ~(1 << ((layer) % 4)), (on)) +#define ACTION_LAYER_SET(layer, on) ACTION_LAYER_BIT_SET((layer) / 4, 1 << ((layer) % 4), (on)) +#define ACTION_LAYER_ON_OFF(layer) ACTION_LAYER_TAP((layer), OP_ON_OFF) +#define ACTION_LAYER_OFF_ON(layer) ACTION_LAYER_TAP((layer), OP_OFF_ON) +#define ACTION_LAYER_SET_CLEAR(layer) ACTION_LAYER_TAP((layer), OP_SET_CLEAR) +#define ACTION_LAYER_ONESHOT(layer) ACTION_LAYER_TAP((layer), OP_ONESHOT) +#define ACTION_LAYER_MODS(layer, mods) ACTION(ACT_LAYER_MODS, (layer) << 8 | (mods)) +/* With Tapping */ +#define ACTION_LAYER_TAP_KEY(layer, key) ACTION_LAYER_TAP((layer), (key)) +#define ACTION_LAYER_TAP_TOGGLE(layer) ACTION_LAYER_TAP((layer), OP_TAP_TOGGLE) +/* Bitwise Operation */ +#define ACTION_LAYER_BIT_AND(part, bits, on) ACTION_LAYER_BITOP(OP_BIT_AND, (part), (bits), (on)) +#define ACTION_LAYER_BIT_OR(part, bits, on) ACTION_LAYER_BITOP(OP_BIT_OR, (part), (bits), (on)) +#define ACTION_LAYER_BIT_XOR(part, bits, on) ACTION_LAYER_BITOP(OP_BIT_XOR, (part), (bits), (on)) +#define ACTION_LAYER_BIT_SET(part, bits, on) ACTION_LAYER_BITOP(OP_BIT_SET, (part), (bits), (on)) +/* Default Layer Bitwise Operation */ +#define ACTION_DEFAULT_LAYER_BIT_AND(part, bits) ACTION_LAYER_BITOP(OP_BIT_AND, (part), (bits), 0) +#define ACTION_DEFAULT_LAYER_BIT_OR(part, bits) ACTION_LAYER_BITOP(OP_BIT_OR, (part), (bits), 0) +#define ACTION_DEFAULT_LAYER_BIT_XOR(part, bits) ACTION_LAYER_BITOP(OP_BIT_XOR, (part), (bits), 0) +#define ACTION_DEFAULT_LAYER_BIT_SET(part, bits) ACTION_LAYER_BITOP(OP_BIT_SET, (part), (bits), 0) + +/* Macro */ +#define ACTION_MACRO(id) ACTION(ACT_MACRO, (id)) +#define ACTION_MACRO_TAP(id) ACTION(ACT_MACRO, FUNC_TAP << 8 | (id)) +#define ACTION_MACRO_OPT(id, opt) ACTION(ACT_MACRO, (opt) << 8 | (id)) +/* Function */ +enum function_opts { + FUNC_TAP = 0x8, /* indciates function is tappable */ +}; +#define ACTION_FUNCTION(id) ACTION(ACT_FUNCTION, (id)) +#define ACTION_FUNCTION_TAP(id) ACTION(ACT_FUNCTION, FUNC_TAP << 8 | (id)) +#define ACTION_FUNCTION_OPT(id, opt) ACTION(ACT_FUNCTION, (opt) << 8 | (id)) +/* OneHand Support */ +enum swap_hands_param_tap_op { + OP_SH_TOGGLE = 0xF0, + OP_SH_TAP_TOGGLE, + OP_SH_ON_OFF, + OP_SH_OFF_ON, + OP_SH_OFF, + OP_SH_ON, + OP_SH_ONESHOT, +}; + +#define ACTION_SWAP_HANDS() ACTION_SWAP_HANDS_ON_OFF() +#define ACTION_SWAP_HANDS_TOGGLE() ACTION(ACT_SWAP_HANDS, OP_SH_TOGGLE) +#define ACTION_SWAP_HANDS_TAP_TOGGLE() ACTION(ACT_SWAP_HANDS, OP_SH_TAP_TOGGLE) +#define ACTION_SWAP_HANDS_ONESHOT() ACTION(ACT_SWAP_HANDS, OP_SH_ONESHOT) +#define ACTION_SWAP_HANDS_TAP_KEY(key) ACTION(ACT_SWAP_HANDS, key) +#define ACTION_SWAP_HANDS_ON_OFF() ACTION(ACT_SWAP_HANDS, OP_SH_ON_OFF) +#define ACTION_SWAP_HANDS_OFF_ON() ACTION(ACT_SWAP_HANDS, OP_SH_OFF_ON) +#define ACTION_SWAP_HANDS_ON() ACTION(ACT_SWAP_HANDS, OP_SH_ON) +#define ACTION_SWAP_HANDS_OFF() ACTION(ACT_SWAP_HANDS, OP_SH_OFF) diff --git a/quantum/action_layer.c b/quantum/action_layer.c new file mode 100644 index 0000000000..ed1a4bd20d --- /dev/null +++ b/quantum/action_layer.c @@ -0,0 +1,279 @@ +#include +#include "keyboard.h" +#include "action.h" +#include "util.h" +#include "action_layer.h" + +#ifdef DEBUG_ACTION +# include "debug.h" +#else +# include "nodebug.h" +#endif + +/** \brief Default Layer State + */ +layer_state_t default_layer_state = 0; + +/** \brief Default Layer State Set At user Level + * + * Run user code on default layer state change + */ +__attribute__((weak)) layer_state_t default_layer_state_set_user(layer_state_t state) { return state; } + +/** \brief Default Layer State Set At Keyboard Level + * + * Run keyboard code on default layer state change + */ +__attribute__((weak)) layer_state_t default_layer_state_set_kb(layer_state_t state) { return default_layer_state_set_user(state); } + +/** \brief Default Layer State Set + * + * Static function to set the default layer state, prints debug info and clears keys + */ +static void default_layer_state_set(layer_state_t state) { + state = default_layer_state_set_kb(state); + debug("default_layer_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 + * + * Print out the hex value of the 32-bit default layer state, as well as the value of the highest bit. + */ +void default_layer_debug(void) { dprintf("%08lX(%u)", default_layer_state, get_highest_layer(default_layer_state)); } + +/** \brief Default Layer Set + * + * Sets the default layer state. + */ +void default_layer_set(layer_state_t state) { default_layer_state_set(state); } + +#ifndef NO_ACTION_LAYER +/** \brief Default Layer Or + * + * Turns on the default layer based on matching bits between specifed layer and existing layer state + */ +void default_layer_or(layer_state_t state) { default_layer_state_set(default_layer_state | state); } +/** \brief Default Layer And + * + * Turns on default layer based on matching enabled bits between specifed layer and existing layer state + */ +void default_layer_and(layer_state_t state) { default_layer_state_set(default_layer_state & state); } +/** \brief Default Layer Xor + * + * Turns on default layer based on non-matching bits between specifed layer and existing layer state + */ +void default_layer_xor(layer_state_t state) { default_layer_state_set(default_layer_state ^ state); } +#endif + +#ifndef NO_ACTION_LAYER +/** \brief Keymap Layer State + */ +layer_state_t layer_state = 0; + +/** \brief Layer state set user + * + * Runs user code on layer state change + */ +__attribute__((weak)) layer_state_t layer_state_set_user(layer_state_t state) { return state; } + +/** \brief Layer state set keyboard + * + * Runs keyboard code on layer state change + */ +__attribute__((weak)) layer_state_t layer_state_set_kb(layer_state_t state) { return layer_state_set_user(state); } + +/** \brief Layer state set + * + * Sets the layer to match the specifed state (a bitmask) + */ +void layer_state_set(layer_state_t state) { + state = layer_state_set_kb(state); + dprint("layer_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 + * + * Turn off all layers + */ +void layer_clear(void) { layer_state_set(0); } + +/** \brief Layer state is + * + * Return whether the given state is on (it might still be shadowed by a higher state, though) + */ +bool layer_state_is(uint8_t layer) { return layer_state_cmp(layer_state, layer); } + +/** \brief Layer state compare + * + * Used for comparing layers {mostly used for unit testing} + */ +bool layer_state_cmp(layer_state_t cmp_layer_state, uint8_t layer) { + if (!cmp_layer_state) { + return layer == 0; + } + return (cmp_layer_state & ((layer_state_t)1 << layer)) != 0; +} + +/** \brief Layer move + * + * Turns on the given layer and turn off all other layers + */ +void layer_move(uint8_t layer) { layer_state_set((layer_state_t)1 << layer); } + +/** \brief Layer on + * + * Turns on given layer + */ +void layer_on(uint8_t layer) { layer_state_set(layer_state | ((layer_state_t)1 << layer)); } + +/** \brief Layer off + * + * Turns off given layer + */ +void layer_off(uint8_t layer) { layer_state_set(layer_state & ~((layer_state_t)1 << layer)); } + +/** \brief Layer invert + * + * Toggle the given layer (set it if it's unset, or unset it if it's set) + */ +void layer_invert(uint8_t layer) { layer_state_set(layer_state ^ ((layer_state_t)1 << layer)); } + +/** \brief Layer or + * + * Turns on layers based on matching bits between specifed layer and existing layer state + */ +void layer_or(layer_state_t state) { layer_state_set(layer_state | state); } +/** \brief Layer and + * + * Turns on layers based on matching enabled bits between specifed layer and existing layer state + */ +void layer_and(layer_state_t state) { layer_state_set(layer_state & state); } +/** \brief Layer xor + * + * Turns on layers based on non-matching bits between specifed layer and existing layer state + */ +void layer_xor(layer_state_t state) { layer_state_set(layer_state ^ state); } + +/** \brief Layer debug printing + * + * Print out the hex value of the 32-bit layer state, as well as the value of the highest bit. + */ +void layer_debug(void) { dprintf("%08lX(%u)", layer_state, get_highest_layer(layer_state)); } +#endif + +#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE) +/** \brief source layer cache + */ + +uint8_t source_layers_cache[(MATRIX_ROWS * MATRIX_COLS + 7) / 8][MAX_LAYER_BITS] = {{0}}; + +/** \brief update source layers cache + * + * Updates the cached keys when changing layers + */ +void update_source_layers_cache(keypos_t key, uint8_t layer) { + const uint8_t key_number = key.col + (key.row * MATRIX_COLS); + const uint8_t storage_row = key_number / 8; + const uint8_t storage_bit = key_number % 8; + + for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) { + source_layers_cache[storage_row][bit_number] ^= (-((layer & (1U << bit_number)) != 0) ^ source_layers_cache[storage_row][bit_number]) & (1U << storage_bit); + } +} + +/** \brief read source layers cache + * + * reads the cached keys stored when the layer was changed + */ +uint8_t read_source_layers_cache(keypos_t key) { + const uint8_t key_number = key.col + (key.row * MATRIX_COLS); + const uint8_t storage_row = key_number / 8; + const uint8_t storage_bit = key_number % 8; + uint8_t layer = 0; + + for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) { + layer |= ((source_layers_cache[storage_row][bit_number] & (1U << storage_bit)) != 0) << bit_number; + } + + return layer; +} +#endif + +/** \brief Store or get action (FIXME: Needs better summary) + * + * Make sure the action triggered when the key is released is the same + * one as the one triggered on press. It's important for the mod keys + * when the layer is switched after the down event but before the up + * event as they may get stuck otherwise. + */ +action_t store_or_get_action(bool pressed, keypos_t key) { +#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE) + if (disable_action_cache) { + return layer_switch_get_action(key); + } + + uint8_t layer; + + if (pressed) { + layer = layer_switch_get_layer(key); + update_source_layers_cache(key, layer); + } else { + layer = read_source_layers_cache(key); + } + return action_for_key(layer, key); +#else + return layer_switch_get_action(key); +#endif +} + +/** \brief Layer switch get layer + * + * Gets the layer based on key info + */ +uint8_t layer_switch_get_layer(keypos_t key) { +#ifndef NO_ACTION_LAYER + action_t action; + action.code = ACTION_TRANSPARENT; + + layer_state_t layers = layer_state | default_layer_state; + /* check top layer first */ + for (int8_t i = MAX_LAYER - 1; i >= 0; i--) { + if (layers & ((layer_state_t)1 << i)) { + action = action_for_key(i, key); + if (action.code != ACTION_TRANSPARENT) { + return i; + } + } + } + /* fall back to layer 0 */ + return 0; +#else + return get_highest_layer(default_layer_state); +#endif +} + +/** \brief Layer switch get layer + * + * Gets action code based on key position + */ +action_t layer_switch_get_action(keypos_t key) { return action_for_key(layer_switch_get_layer(key), key); } diff --git a/quantum/action_layer.h b/quantum/action_layer.h new file mode 100644 index 0000000000..b87d096eed --- /dev/null +++ b/quantum/action_layer.h @@ -0,0 +1,147 @@ +/* +Copyright 2013 Jun Wako + +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 . +*/ + +#pragma once + +#include +#include "keyboard.h" +#include "action.h" + +#ifdef DYNAMIC_KEYMAP_ENABLE +# ifndef DYNAMIC_KEYMAP_LAYER_COUNT +# define DYNAMIC_KEYMAP_LAYER_COUNT 4 +# endif +# if DYNAMIC_KEYMAP_LAYER_COUNT <= 8 +# ifndef LAYER_STATE_8BIT +# define LAYER_STATE_8BIT +# endif +# elif DYNAMIC_KEYMAP_LAYER_COUNT <= 16 +# ifndef LAYER_STATE_16BIT +# define LAYER_STATE_16BIT +# endif +# else +# ifndef LAYER_STATE_32BIT +# define LAYER_STATE_32BIT +# endif +# endif +#endif + +#if !defined(LAYER_STATE_8BIT) && !defined(LAYER_STATE_16BIT) && !defined(LAYER_STATE_32BIT) +# define LAYER_STATE_32BIT +#endif + +#if defined(LAYER_STATE_8BIT) +typedef uint8_t layer_state_t; +# define MAX_LAYER_BITS 3 +# ifndef MAX_LAYER +# define MAX_LAYER 8 +# endif +# define get_highest_layer(state) biton(state) +#elif defined(LAYER_STATE_16BIT) +typedef uint16_t layer_state_t; +# define MAX_LAYER_BITS 4 +# ifndef MAX_LAYER +# define MAX_LAYER 16 +# endif +# define get_highest_layer(state) biton16(state) +#elif defined(LAYER_STATE_32BIT) +typedef uint32_t layer_state_t; +# define MAX_LAYER_BITS 5 +# ifndef MAX_LAYER +# define MAX_LAYER 32 +# endif +# define get_highest_layer(state) biton32(state) +#else +# error Layer Mask size not specified. HOW?! +#endif + +/* + * Default Layer + */ +extern layer_state_t default_layer_state; +void default_layer_debug(void); +void default_layer_set(layer_state_t state); + +__attribute__((weak)) layer_state_t default_layer_state_set_kb(layer_state_t state); +__attribute__((weak)) layer_state_t default_layer_state_set_user(layer_state_t state); + +#ifndef NO_ACTION_LAYER +/* bitwise operation */ +void default_layer_or(layer_state_t state); +void default_layer_and(layer_state_t state); +void default_layer_xor(layer_state_t state); +#else +# define default_layer_or(state) +# define default_layer_and(state) +# define default_layer_xor(state) +#endif + +/* + * Keymap Layer + */ +#ifndef NO_ACTION_LAYER +extern layer_state_t layer_state; + +void layer_state_set(layer_state_t state); +bool layer_state_is(uint8_t layer); +bool layer_state_cmp(layer_state_t layer1, uint8_t layer2); + +void layer_debug(void); +void layer_clear(void); +void layer_move(uint8_t layer); +void layer_on(uint8_t layer); +void layer_off(uint8_t layer); +void layer_invert(uint8_t layer); +/* bitwise operation */ +void layer_or(layer_state_t state); +void layer_and(layer_state_t state); +void layer_xor(layer_state_t state); +layer_state_t layer_state_set_user(layer_state_t state); +layer_state_t layer_state_set_kb(layer_state_t state); +#else +# define layer_state 0 + +# define layer_state_set(layer) +# define layer_state_is(layer) (layer == 0) +# define layer_state_cmp(state, layer) (state == 0 ? layer == 0 : (state & (layer_state_t)1 << layer) != 0) + +# define layer_debug() +# define layer_clear() +# define layer_move(layer) (void)layer +# define layer_on(layer) (void)layer +# define layer_off(layer) (void)layer +# define layer_invert(layer) (void)layer +# define layer_or(state) (void)state +# define layer_and(state) (void)state +# define layer_xor(state) (void)state +# define layer_state_set_kb(state) (void)state +# define layer_state_set_user(state) (void)state +#endif + +/* pressed actions cache */ +#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE) + +void update_source_layers_cache(keypos_t key, uint8_t layer); +uint8_t read_source_layers_cache(keypos_t key); +#endif +action_t store_or_get_action(bool pressed, keypos_t key); + +/* return the topmost non-transparent layer currently associated with key */ +uint8_t layer_switch_get_layer(keypos_t key); + +/* return action depending on current layer status */ +action_t layer_switch_get_action(keypos_t key); diff --git a/quantum/action_macro.c b/quantum/action_macro.c new file mode 100644 index 0000000000..92228c0ba8 --- /dev/null +++ b/quantum/action_macro.c @@ -0,0 +1,93 @@ +/* +Copyright 2013 Jun Wako + +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 . +*/ +#include "action.h" +#include "action_util.h" +#include "action_macro.h" +#include "wait.h" + +#ifdef DEBUG_ACTION +# include "debug.h" +#else +# include "nodebug.h" +#endif + +#ifndef NO_ACTION_MACRO + +# define MACRO_READ() (macro = MACRO_GET(macro_p++)) +/** \brief Action Macro Play + * + * FIXME: Needs doc + */ +void action_macro_play(const macro_t *macro_p) { + macro_t macro = END; + uint8_t interval = 0; + + if (!macro_p) return; + while (true) { + switch (MACRO_READ()) { + case KEY_DOWN: + MACRO_READ(); + dprintf("KEY_DOWN(%02X)\n", macro); + if (IS_MOD(macro)) { + add_macro_mods(MOD_BIT(macro)); + send_keyboard_report(); + } else { + register_code(macro); + } + break; + case KEY_UP: + MACRO_READ(); + dprintf("KEY_UP(%02X)\n", macro); + if (IS_MOD(macro)) { + del_macro_mods(MOD_BIT(macro)); + send_keyboard_report(); + } else { + unregister_code(macro); + } + break; + case WAIT: + MACRO_READ(); + dprintf("WAIT(%u)\n", macro); + { + uint8_t ms = macro; + while (ms--) wait_ms(1); + } + break; + case INTERVAL: + interval = MACRO_READ(); + dprintf("INTERVAL(%u)\n", interval); + break; + case 0x04 ... 0x73: + dprintf("DOWN(%02X)\n", macro); + register_code(macro); + break; + case 0x84 ... 0xF3: + dprintf("UP(%02X)\n", macro); + unregister_code(macro & 0x7F); + break; + case END: + default: + return; + } + // interval + { + uint8_t ms = interval; + while (ms--) wait_ms(1); + } + } +} +#endif diff --git a/quantum/action_macro.h b/quantum/action_macro.h new file mode 100644 index 0000000000..685e2c6ffc --- /dev/null +++ b/quantum/action_macro.h @@ -0,0 +1,123 @@ +/* +Copyright 2013 Jun Wako + +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 . +*/ + +#pragma once + +#include +#include "progmem.h" + +typedef uint8_t macro_t; + +#define MACRO_NONE (macro_t *)0 +#define MACRO(...) \ + ({ \ + static const macro_t __m[] PROGMEM = {__VA_ARGS__}; \ + &__m[0]; \ + }) +#define MACRO_GET(p) pgm_read_byte(p) + +// Sends press when the macro key is pressed, release when release, or tap_macro when the key has been tapped +#define MACRO_TAP_HOLD(record, press, release, tap_macro) (((record)->event.pressed) ? (((record)->tap.count <= 0 || (record)->tap.interrupted) ? (press) : MACRO_NONE) : (((record)->tap.count > 0 && !((record)->tap.interrupted)) ? (tap_macro) : (release))) + +// Holds down the modifier mod when the macro key is held, or sends macro instead when tapped +#define MACRO_TAP_HOLD_MOD(record, macro, mod) MACRO_TAP_HOLD(record, (MACRO(D(mod), END)), MACRO(U(mod), END), macro) + +// Holds down the modifier mod when the macro key is held, or pressed a shifted key when tapped (eg: shift+3 for #) +#define MACRO_TAP_SHFT_KEY_HOLD_MOD(record, key, mod) MACRO_TAP_HOLD_MOD(record, (MACRO(I(10), D(LSFT), T(key), U(LSFT), END)), mod) + +// Momentary switch layer when held, sends macro if tapped +#define MACRO_TAP_HOLD_LAYER(record, macro, layer) \ + (((record)->event.pressed) ? (((record)->tap.count <= 0 || (record)->tap.interrupted) ? ({ \ + layer_on((layer)); \ + MACRO_NONE; \ + }) \ + : MACRO_NONE) \ + : (((record)->tap.count > 0 && !((record)->tap.interrupted)) ? (macro) : ({ \ + layer_off((layer)); \ + MACRO_NONE; \ + }))) + +// Momentary switch layer when held, presses a shifted key when tapped (eg: shift+3 for #) +#define MACRO_TAP_SHFT_KEY_HOLD_LAYER(record, key, layer) MACRO_TAP_HOLD_LAYER(record, MACRO(I(10), D(LSFT), T(key), U(LSFT), END), layer) + +#ifndef NO_ACTION_MACRO +void action_macro_play(const macro_t *macro_p); +#else +# define action_macro_play(macro) +#endif + +/* Macro commands + * code(0x04-73) // key down(1byte) + * code(0x04-73) | 0x80 // key up(1byte) + * { KEY_DOWN, code(0x04-0xff) } // key down(2bytes) + * { KEY_UP, code(0x04-0xff) } // key up(2bytes) + * WAIT // wait milli-seconds + * INTERVAL // set interval between macro commands + * END // stop macro execution + * + * Ideas(Not implemented): + * modifiers + * system usage + * consumer usage + * unicode usage + * function call + * conditionals + * loop + */ +enum macro_command_id { + /* 0x00 - 0x03 */ + END = 0x00, + KEY_DOWN, + KEY_UP, + + /* 0x04 - 0x73 (reserved for keycode down) */ + + /* 0x74 - 0x83 */ + WAIT = 0x74, + INTERVAL, + + /* 0x84 - 0xf3 (reserved for keycode up) */ + + /* 0xf4 - 0xff */ +}; + +/* TODO: keycode:0x04-0x73 can be handled by 1byte command else 2bytes are needed + * if keycode between 0x04 and 0x73 + * keycode / (keycode|0x80) + * else + * {KEY_DOWN, keycode} / {KEY_UP, keycode} + */ +#define DOWN(key) KEY_DOWN, (key) +#define UP(key) KEY_UP, (key) +#define TYPE(key) DOWN(key), UP(key) +#define WAIT(ms) WAIT, (ms) +#define INTERVAL(ms) INTERVAL, (ms) + +/* key down */ +#define D(key) DOWN(KC_##key) +/* key up */ +#define U(key) UP(KC_##key) +/* key type */ +#define T(key) TYPE(KC_##key) +/* wait */ +#define W(ms) WAIT(ms) +/* interval */ +#define I(ms) INTERVAL(ms) + +/* for backward comaptibility */ +#define MD(key) DOWN(KC_##key) +#define MU(key) UP(KC_##key) diff --git a/quantum/action_tapping.c b/quantum/action_tapping.c new file mode 100644 index 0000000000..36839f9faf --- /dev/null +++ b/quantum/action_tapping.c @@ -0,0 +1,456 @@ +#include +#include +#include "action.h" +#include "action_layer.h" +#include "action_tapping.h" +#include "keycode.h" +#include "timer.h" + +#ifdef DEBUG_ACTION +# include "debug.h" +#else +# include "nodebug.h" +#endif + +#ifndef NO_ACTION_TAPPING + +# define IS_TAPPING() !IS_NOEVENT(tapping_key.event) +# define IS_TAPPING_PRESSED() (IS_TAPPING() && tapping_key.event.pressed) +# define IS_TAPPING_RELEASED() (IS_TAPPING() && !tapping_key.event.pressed) +# define IS_TAPPING_KEY(k) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (k))) +#ifndef COMBO_ENABLE +# define IS_TAPPING_RECORD(r) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (r->event.key))) +#else +# define IS_TAPPING_RECORD(r) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (r->event.key)) && tapping_key.keycode == r->keycode) +#endif + +__attribute__((weak)) uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) { return TAPPING_TERM; } + +# ifdef TAPPING_TERM_PER_KEY +# define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < get_tapping_term(get_record_keycode(&tapping_key, false), &tapping_key)) +# else +# define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < TAPPING_TERM) +# endif + +# ifdef TAPPING_FORCE_HOLD_PER_KEY +__attribute__((weak)) bool get_tapping_force_hold(uint16_t keycode, keyrecord_t *record) { return false; } +# endif + +# ifdef PERMISSIVE_HOLD_PER_KEY +__attribute__((weak)) bool get_permissive_hold(uint16_t keycode, keyrecord_t *record) { return false; } +# endif + +# ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY +__attribute__((weak)) bool get_hold_on_other_key_press(uint16_t keycode, keyrecord_t *record) { return false; } +# endif + +static keyrecord_t tapping_key = {}; +static keyrecord_t waiting_buffer[WAITING_BUFFER_SIZE] = {}; +static uint8_t waiting_buffer_head = 0; +static uint8_t waiting_buffer_tail = 0; + +static bool process_tapping(keyrecord_t *record); +static bool waiting_buffer_enq(keyrecord_t record); +static void waiting_buffer_clear(void); +static bool waiting_buffer_typed(keyevent_t event); +static bool waiting_buffer_has_anykey_pressed(void); +static void waiting_buffer_scan_tap(void); +static void debug_tapping_key(void); +static void debug_waiting_buffer(void); + +/** \brief Action Tapping Process + * + * FIXME: Needs doc + */ +void action_tapping_process(keyrecord_t record) { + if (process_tapping(&record)) { + if (!IS_NOEVENT(record.event)) { + debug("processed: "); + debug_record(record); + debug("\n"); + } + } else { + if (!waiting_buffer_enq(record)) { + // clear all in case of overflow. + debug("OVERFLOW: CLEAR ALL STATES\n"); + clear_keyboard(); + waiting_buffer_clear(); + tapping_key = (keyrecord_t){}; + } + } + + // process waiting_buffer + if (!IS_NOEVENT(record.event) && waiting_buffer_head != waiting_buffer_tail) { + debug("---- action_exec: process waiting_buffer -----\n"); + } + for (; waiting_buffer_tail != waiting_buffer_head; waiting_buffer_tail = (waiting_buffer_tail + 1) % WAITING_BUFFER_SIZE) { + if (process_tapping(&waiting_buffer[waiting_buffer_tail])) { + debug("processed: waiting_buffer["); + debug_dec(waiting_buffer_tail); + debug("] = "); + debug_record(waiting_buffer[waiting_buffer_tail]); + debug("\n\n"); + } else { + break; + } + } + if (!IS_NOEVENT(record.event)) { + debug("\n"); + } +} + +/** \brief Tapping + * + * Rule: Tap key is typed(pressed and released) within TAPPING_TERM. + * (without interfering by typing other key) + */ +/* return true when key event is processed or consumed. */ +bool process_tapping(keyrecord_t *keyp) { + keyevent_t event = keyp->event; + + // if tapping + if (IS_TAPPING_PRESSED()) { + if (WITHIN_TAPPING_TERM(event)) { + if (tapping_key.tap.count == 0) { + if (IS_TAPPING_RECORD(keyp) && !event.pressed) { + // first tap! + debug("Tapping: First tap(0->1).\n"); + tapping_key.tap.count = 1; + debug_tapping_key(); + process_record(&tapping_key); + + // copy tapping state + keyp->tap = tapping_key.tap; + // enqueue + return false; + } + /* Process a key typed within TAPPING_TERM + * This can register the key before settlement of tapping, + * useful for long TAPPING_TERM but may prevent fast typing. + */ +# if defined(TAPPING_TERM_PER_KEY) || (TAPPING_TERM >= 500) || defined(PERMISSIVE_HOLD) || defined(PERMISSIVE_HOLD_PER_KEY) + else if ((( +# ifdef TAPPING_TERM_PER_KEY + get_tapping_term(get_record_keycode(&tapping_key, false), keyp) +# else + TAPPING_TERM +# endif + >= 500) + +# ifdef PERMISSIVE_HOLD_PER_KEY + || get_permissive_hold(get_record_keycode(&tapping_key, false), keyp) +# elif defined(PERMISSIVE_HOLD) + || true +# endif + ) && + IS_RELEASED(event) && waiting_buffer_typed(event)) { + debug("Tapping: End. No tap. Interfered by typing key\n"); + process_record(&tapping_key); + tapping_key = (keyrecord_t){}; + debug_tapping_key(); + // enqueue + return false; + } +# endif + /* Process release event of a key pressed before tapping starts + * Without this unexpected repeating will occur with having fast repeating setting + * https://github.com/tmk/tmk_keyboard/issues/60 + */ + else if (IS_RELEASED(event) && !waiting_buffer_typed(event)) { + // Modifier should be retained till end of this tapping. + action_t action = layer_switch_get_action(event.key); + switch (action.kind.id) { + case ACT_LMODS: + case ACT_RMODS: + if (action.key.mods && !action.key.code) return false; + if (IS_MOD(action.key.code)) return false; + break; + case ACT_LMODS_TAP: + case ACT_RMODS_TAP: + if (action.key.mods && keyp->tap.count == 0) return false; + if (IS_MOD(action.key.code)) return false; + break; + } + // Release of key should be process immediately. + debug("Tapping: release event of a key pressed before tapping\n"); + process_record(keyp); + return true; + } else { + // set interrupted flag when other key preesed during tapping + if (event.pressed) { + tapping_key.tap.interrupted = true; +# if defined(HOLD_ON_OTHER_KEY_PRESS) || defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY) +# if defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY) + if (get_hold_on_other_key_press(get_record_keycode(&tapping_key, false), keyp)) +# endif + { + debug("Tapping: End. No tap. Interfered by pressed key\n"); + process_record(&tapping_key); + tapping_key = (keyrecord_t){}; + debug_tapping_key(); + // enqueue + return false; + } +# endif + } + // enqueue + return false; + } + } + // tap_count > 0 + else { + if (IS_TAPPING_RECORD(keyp) && !event.pressed) { + debug("Tapping: Tap release("); + debug_dec(tapping_key.tap.count); + debug(")\n"); + keyp->tap = tapping_key.tap; + process_record(keyp); + tapping_key = *keyp; + debug_tapping_key(); + return true; + } else if (is_tap_record(keyp) && event.pressed) { + if (tapping_key.tap.count > 1) { + debug("Tapping: Start new tap with releasing last tap(>1).\n"); + // unregister key + process_record(&(keyrecord_t){.tap = tapping_key.tap, .event.key = tapping_key.event.key, .event.time = event.time, .event.pressed = false, +#ifdef COMBO_ENABLE + .keycode = tapping_key.keycode, +#endif + }); + } else { + debug("Tapping: Start while last tap(1).\n"); + } + tapping_key = *keyp; + waiting_buffer_scan_tap(); + debug_tapping_key(); + return true; + } else { + if (!IS_NOEVENT(event)) { + debug("Tapping: key event while last tap(>0).\n"); + } + process_record(keyp); + return true; + } + } + } + // after TAPPING_TERM + else { + if (tapping_key.tap.count == 0) { + debug("Tapping: End. Timeout. Not tap(0): "); + debug_event(event); + debug("\n"); + process_record(&tapping_key); + tapping_key = (keyrecord_t){}; + debug_tapping_key(); + return false; + } else { + if (IS_TAPPING_RECORD(keyp) && !event.pressed) { + debug("Tapping: End. last timeout tap release(>0)."); + keyp->tap = tapping_key.tap; + process_record(keyp); + tapping_key = (keyrecord_t){}; + return true; + } else if (is_tap_record(keyp) && event.pressed) { + if (tapping_key.tap.count > 1) { + debug("Tapping: Start new tap with releasing last timeout tap(>1).\n"); + // unregister key + process_record(&(keyrecord_t){.tap = tapping_key.tap, .event.key = tapping_key.event.key, .event.time = event.time, .event.pressed = false, +#ifdef COMBO_ENABLE + .keycode = tapping_key.keycode, +#endif + }); + } else { + debug("Tapping: Start while last timeout tap(1).\n"); + } + tapping_key = *keyp; + waiting_buffer_scan_tap(); + debug_tapping_key(); + return true; + } else { + if (!IS_NOEVENT(event)) { + debug("Tapping: key event while last timeout tap(>0).\n"); + } + process_record(keyp); + return true; + } + } + } + } else if (IS_TAPPING_RELEASED()) { + if (WITHIN_TAPPING_TERM(event)) { + if (event.pressed) { + if (IS_TAPPING_RECORD(keyp)) { +//# ifndef TAPPING_FORCE_HOLD +# if !defined(TAPPING_FORCE_HOLD) || defined(TAPPING_FORCE_HOLD_PER_KEY) + if ( +# ifdef TAPPING_FORCE_HOLD_PER_KEY + !get_tapping_force_hold(get_record_keycode(&tapping_key, false), keyp) && +# endif + !tapping_key.tap.interrupted && tapping_key.tap.count > 0) { + // sequential tap. + keyp->tap = tapping_key.tap; + if (keyp->tap.count < 15) keyp->tap.count += 1; + debug("Tapping: Tap press("); + debug_dec(keyp->tap.count); + debug(")\n"); + process_record(keyp); + tapping_key = *keyp; + debug_tapping_key(); + return true; + } +# endif + // FIX: start new tap again + tapping_key = *keyp; + return true; + } else if (is_tap_record(keyp)) { + // Sequential tap can be interfered with other tap key. + debug("Tapping: Start with interfering other tap.\n"); + tapping_key = *keyp; + waiting_buffer_scan_tap(); + debug_tapping_key(); + return true; + } else { + // should none in buffer + // FIX: interrupted when other key is pressed + tapping_key.tap.interrupted = true; + process_record(keyp); + return true; + } + } else { + if (!IS_NOEVENT(event)) debug("Tapping: other key just after tap.\n"); + process_record(keyp); + return true; + } + } else { + // FIX: process_action here? + // timeout. no sequential tap. + debug("Tapping: End(Timeout after releasing last tap): "); + debug_event(event); + debug("\n"); + tapping_key = (keyrecord_t){}; + debug_tapping_key(); + return false; + } + } + // not tapping state + else { + if (event.pressed && is_tap_record(keyp)) { + debug("Tapping: Start(Press tap key).\n"); + tapping_key = *keyp; + process_record_tap_hint(&tapping_key); + waiting_buffer_scan_tap(); + debug_tapping_key(); + return true; + } else { + process_record(keyp); + return true; + } + } +} + +/** \brief Waiting buffer enq + * + * FIXME: Needs docs + */ +bool waiting_buffer_enq(keyrecord_t record) { + if (IS_NOEVENT(record.event)) { + return true; + } + + if ((waiting_buffer_head + 1) % WAITING_BUFFER_SIZE == waiting_buffer_tail) { + debug("waiting_buffer_enq: Over flow.\n"); + return false; + } + + waiting_buffer[waiting_buffer_head] = record; + waiting_buffer_head = (waiting_buffer_head + 1) % WAITING_BUFFER_SIZE; + + debug("waiting_buffer_enq: "); + debug_waiting_buffer(); + return true; +} + +/** \brief Waiting buffer clear + * + * FIXME: Needs docs + */ +void waiting_buffer_clear(void) { + waiting_buffer_head = 0; + waiting_buffer_tail = 0; +} + +/** \brief Waiting buffer typed + * + * FIXME: Needs docs + */ +bool waiting_buffer_typed(keyevent_t event) { + for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) { + if (KEYEQ(event.key, waiting_buffer[i].event.key) && event.pressed != waiting_buffer[i].event.pressed) { + return true; + } + } + return false; +} + +/** \brief Waiting buffer has anykey pressed + * + * FIXME: Needs docs + */ +__attribute__((unused)) bool waiting_buffer_has_anykey_pressed(void) { + for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) { + if (waiting_buffer[i].event.pressed) return true; + } + return false; +} + +/** \brief Scan buffer for tapping + * + * FIXME: Needs docs + */ +void waiting_buffer_scan_tap(void) { + // tapping already is settled + if (tapping_key.tap.count > 0) return; + // invalid state: tapping_key released && tap.count == 0 + if (!tapping_key.event.pressed) return; + + for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) { + if (IS_TAPPING_KEY(waiting_buffer[i].event.key) && !waiting_buffer[i].event.pressed && WITHIN_TAPPING_TERM(waiting_buffer[i].event)) { + tapping_key.tap.count = 1; + waiting_buffer[i].tap.count = 1; + process_record(&tapping_key); + + debug("waiting_buffer_scan_tap: found at ["); + debug_dec(i); + debug("]\n"); + debug_waiting_buffer(); + return; + } + } +} + +/** \brief Tapping key debug print + * + * FIXME: Needs docs + */ +static void debug_tapping_key(void) { + debug("TAPPING_KEY="); + debug_record(tapping_key); + debug("\n"); +} + +/** \brief Waiting buffer debug print + * + * FIXME: Needs docs + */ +static void debug_waiting_buffer(void) { + debug("{ "); + for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) { + debug("["); + debug_dec(i); + debug("]="); + debug_record(waiting_buffer[i]); + debug(" "); + } + debug("}\n"); +} + +#endif diff --git a/quantum/action_tapping.h b/quantum/action_tapping.h new file mode 100644 index 0000000000..7de8049c7f --- /dev/null +++ b/quantum/action_tapping.h @@ -0,0 +1,42 @@ +/* +Copyright 2013 Jun Wako + +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 . +*/ + +#pragma once + +/* period of tapping(ms) */ +#ifndef TAPPING_TERM +# define TAPPING_TERM 200 +#endif + +/* tap count needed for toggling a feature */ +#ifndef TAPPING_TOGGLE +# define TAPPING_TOGGLE 5 +#endif + +#define WAITING_BUFFER_SIZE 8 + +#ifndef NO_ACTION_TAPPING +uint16_t get_record_keycode(keyrecord_t *record, bool update_layer_cache); +uint16_t get_event_keycode(keyevent_t event, bool update_layer_cache); +void action_tapping_process(keyrecord_t record); + +uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record); +bool get_permissive_hold(uint16_t keycode, keyrecord_t *record); +bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record); +bool get_tapping_force_hold(uint16_t keycode, keyrecord_t *record); +bool get_retro_tapping(uint16_t keycode, keyrecord_t *record); +#endif diff --git a/quantum/action_util.c b/quantum/action_util.c new file mode 100644 index 0000000000..2b3c00cba0 --- /dev/null +++ b/quantum/action_util.c @@ -0,0 +1,455 @@ +/* +Copyright 2013 Jun Wako + +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 . +*/ +#include "host.h" +#include "report.h" +#include "debug.h" +#include "action_util.h" +#include "action_layer.h" +#include "timer.h" +#include "keycode_config.h" + +extern keymap_config_t keymap_config; + +static uint8_t real_mods = 0; +static uint8_t weak_mods = 0; +static uint8_t macro_mods = 0; +#ifdef KEY_OVERRIDE_ENABLE +static uint8_t weak_override_mods = 0; +static uint8_t suppressed_mods = 0; +#endif + +#ifdef USB_6KRO_ENABLE +# define RO_ADD(a, b) ((a + b) % KEYBOARD_REPORT_KEYS) +# define RO_SUB(a, b) ((a - b + KEYBOARD_REPORT_KEYS) % KEYBOARD_REPORT_KEYS) +# define RO_INC(a) RO_ADD(a, 1) +# define RO_DEC(a) RO_SUB(a, 1) +static int8_t cb_head = 0; +static int8_t cb_tail = 0; +static int8_t cb_count = 0; +#endif + +// TODO: pointer variable is not needed +// report_keyboard_t keyboard_report = {}; +report_keyboard_t *keyboard_report = &(report_keyboard_t){}; + +extern inline void add_key(uint8_t key); +extern inline void del_key(uint8_t key); +extern inline void clear_keys(void); + +#ifndef NO_ACTION_ONESHOT +static uint8_t oneshot_mods = 0; +static uint8_t oneshot_locked_mods = 0; +uint8_t get_oneshot_locked_mods(void) { return oneshot_locked_mods; } +void set_oneshot_locked_mods(uint8_t mods) { + if (mods != oneshot_locked_mods) { + oneshot_locked_mods = mods; + oneshot_locked_mods_changed_kb(oneshot_locked_mods); + } +} +void clear_oneshot_locked_mods(void) { + if (oneshot_locked_mods) { + oneshot_locked_mods = 0; + oneshot_locked_mods_changed_kb(oneshot_locked_mods); + } +} +# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) +static uint16_t oneshot_time = 0; +bool has_oneshot_mods_timed_out(void) { return TIMER_DIFF_16(timer_read(), oneshot_time) >= ONESHOT_TIMEOUT; } +# else +bool has_oneshot_mods_timed_out(void) { return false; } +# endif +#endif + +/* oneshot layer */ +#ifndef NO_ACTION_ONESHOT +/** \brief oneshot_layer_data bits + * LLLL LSSS + * where: + * L => are layer bits + * S => oneshot state bits + */ +static int8_t oneshot_layer_data = 0; + +inline uint8_t get_oneshot_layer(void) { return oneshot_layer_data >> 3; } +inline uint8_t get_oneshot_layer_state(void) { return oneshot_layer_data & 0b111; } + +# ifdef SWAP_HANDS_ENABLE +enum { + SHO_OFF, + SHO_ACTIVE, // Swap hands button was pressed, and we didn't send any swapped keys yet + SHO_PRESSED, // Swap hands button is currently pressed + SHO_USED, // Swap hands button is still pressed, and we already sent swapped keys +} swap_hands_oneshot = SHO_OFF; +# endif + +# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) +static uint16_t oneshot_layer_time = 0; +inline bool has_oneshot_layer_timed_out() { return TIMER_DIFF_16(timer_read(), oneshot_layer_time) >= ONESHOT_TIMEOUT && !(get_oneshot_layer_state() & ONESHOT_TOGGLED); } +# ifdef SWAP_HANDS_ENABLE +static uint16_t oneshot_swaphands_time = 0; +inline bool has_oneshot_swaphands_timed_out() { return TIMER_DIFF_16(timer_read(), oneshot_swaphands_time) >= ONESHOT_TIMEOUT && (swap_hands_oneshot == SHO_ACTIVE); } +# endif +# endif + +# ifdef SWAP_HANDS_ENABLE + +void set_oneshot_swaphands(void) { + swap_hands_oneshot = SHO_PRESSED; + swap_hands = true; +# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) + oneshot_swaphands_time = timer_read(); + if (oneshot_layer_time != 0) { + oneshot_layer_time = oneshot_swaphands_time; + } +# endif +} + +void release_oneshot_swaphands(void) { + if (swap_hands_oneshot == SHO_PRESSED) { + swap_hands_oneshot = SHO_ACTIVE; + } + if (swap_hands_oneshot == SHO_USED) { + clear_oneshot_swaphands(); + } +} + +void use_oneshot_swaphands(void) { + if (swap_hands_oneshot == SHO_PRESSED) { + swap_hands_oneshot = SHO_USED; + } + if (swap_hands_oneshot == SHO_ACTIVE) { + clear_oneshot_swaphands(); + } +} + +void clear_oneshot_swaphands(void) { + swap_hands_oneshot = SHO_OFF; + swap_hands = false; +# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) + oneshot_swaphands_time = 0; +# endif +} + +# endif + +/** \brief Set oneshot layer + * + * FIXME: needs doc + */ +void set_oneshot_layer(uint8_t layer, uint8_t state) { + if (!keymap_config.oneshot_disable) { + oneshot_layer_data = layer << 3 | state; + layer_on(layer); +# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) + oneshot_layer_time = timer_read(); +# endif + oneshot_layer_changed_kb(get_oneshot_layer()); + } else { + layer_on(layer); + } +} +/** \brief Reset oneshot layer + * + * FIXME: needs doc + */ +void reset_oneshot_layer(void) { + oneshot_layer_data = 0; +# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) + oneshot_layer_time = 0; +# endif + oneshot_layer_changed_kb(get_oneshot_layer()); +} +/** \brief Clear oneshot layer + * + * FIXME: needs doc + */ +void clear_oneshot_layer_state(oneshot_fullfillment_t state) { + uint8_t start_state = oneshot_layer_data; + oneshot_layer_data &= ~state; + if ((!get_oneshot_layer_state() && start_state != oneshot_layer_data) || keymap_config.oneshot_disable) { + layer_off(get_oneshot_layer()); + reset_oneshot_layer(); + } +} +/** \brief Is oneshot layer active + * + * FIXME: needs doc + */ +bool is_oneshot_layer_active(void) { return get_oneshot_layer_state(); } + +/** \brief set oneshot + * + * FIXME: needs doc + */ +void oneshot_set(bool active) { + if (keymap_config.oneshot_disable != active) { + keymap_config.oneshot_disable = active; + eeconfig_update_keymap(keymap_config.raw); + dprintf("Oneshot: active: %d\n", active); + } +} + +/** \brief toggle oneshot + * + * FIXME: needs doc + */ +void oneshot_toggle(void) { oneshot_set(!keymap_config.oneshot_disable); } + +/** \brief enable oneshot + * + * FIXME: needs doc + */ +void oneshot_enable(void) { oneshot_set(true); } + +/** \brief disable oneshot + * + * FIXME: needs doc + */ +void oneshot_disable(void) { oneshot_set(false); } + +bool is_oneshot_enabled(void) { return keymap_config.oneshot_disable; } + +#endif + +/** \brief Send keyboard report + * + * FIXME: needs doc + */ +void send_keyboard_report(void) { + keyboard_report->mods = real_mods; + keyboard_report->mods |= weak_mods; + keyboard_report->mods |= macro_mods; + +#ifndef NO_ACTION_ONESHOT + if (oneshot_mods) { +# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) + if (has_oneshot_mods_timed_out()) { + dprintf("Oneshot: timeout\n"); + clear_oneshot_mods(); + } +# endif + keyboard_report->mods |= oneshot_mods; + if (has_anykey(keyboard_report)) { + clear_oneshot_mods(); + } + } + +#endif + +#ifdef KEY_OVERRIDE_ENABLE + // These need to be last to be able to properly control key overrides + keyboard_report->mods &= ~suppressed_mods; + keyboard_report->mods |= weak_override_mods; +#endif + + host_keyboard_send(keyboard_report); +} + +/** \brief Get mods + * + * FIXME: needs doc + */ +uint8_t get_mods(void) { return real_mods; } +/** \brief add mods + * + * FIXME: needs doc + */ +void add_mods(uint8_t mods) { real_mods |= mods; } +/** \brief del mods + * + * FIXME: needs doc + */ +void del_mods(uint8_t mods) { real_mods &= ~mods; } +/** \brief set mods + * + * FIXME: needs doc + */ +void set_mods(uint8_t mods) { real_mods = mods; } +/** \brief clear mods + * + * FIXME: needs doc + */ +void clear_mods(void) { real_mods = 0; } + +/** \brief get weak mods + * + * FIXME: needs doc + */ +uint8_t get_weak_mods(void) { return weak_mods; } +/** \brief add weak mods + * + * FIXME: needs doc + */ +void add_weak_mods(uint8_t mods) { weak_mods |= mods; } +/** \brief del weak mods + * + * FIXME: needs doc + */ +void del_weak_mods(uint8_t mods) { weak_mods &= ~mods; } +/** \brief set weak mods + * + * FIXME: needs doc + */ +void set_weak_mods(uint8_t mods) { weak_mods = mods; } +/** \brief clear weak mods + * + * FIXME: needs doc + */ +void clear_weak_mods(void) { weak_mods = 0; } + +#ifdef KEY_OVERRIDE_ENABLE +/** \brief set weak mods used by key overrides. DO not call this manually + */ +void set_weak_override_mods(uint8_t mods) { weak_override_mods = mods; } +/** \brief clear weak mods used by key overrides. DO not call this manually + */ +void clear_weak_override_mods(void) { weak_override_mods = 0; } + +/** \brief set suppressed mods used by key overrides. DO not call this manually + */ +void set_suppressed_override_mods(uint8_t mods) { suppressed_mods = mods; } +/** \brief clear suppressed mods used by key overrides. DO not call this manually + */ +void clear_suppressed_override_mods(void) { suppressed_mods = 0; } +#endif + +/* macro modifier */ +/** \brief get macro mods + * + * FIXME: needs doc + */ +uint8_t get_macro_mods(void) { return macro_mods; } +/** \brief add macro mods + * + * FIXME: needs doc + */ +void add_macro_mods(uint8_t mods) { macro_mods |= mods; } +/** \brief del macro mods + * + * FIXME: needs doc + */ +void del_macro_mods(uint8_t mods) { macro_mods &= ~mods; } +/** \brief set macro mods + * + * FIXME: needs doc + */ +void set_macro_mods(uint8_t mods) { macro_mods = mods; } +/** \brief clear macro mods + * + * FIXME: needs doc + */ +void clear_macro_mods(void) { macro_mods = 0; } + +#ifndef NO_ACTION_ONESHOT +/** \brief get oneshot mods + * + * FIXME: needs doc + */ +uint8_t get_oneshot_mods(void) { return oneshot_mods; } + +void add_oneshot_mods(uint8_t mods) { + if ((oneshot_mods & mods) != mods) { +# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) + oneshot_time = timer_read(); +# endif + oneshot_mods |= mods; + oneshot_mods_changed_kb(mods); + } +} + +void del_oneshot_mods(uint8_t mods) { + if (oneshot_mods & mods) { + oneshot_mods &= ~mods; +# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) + oneshot_time = oneshot_mods ? timer_read() : 0; +# endif + oneshot_mods_changed_kb(oneshot_mods); + } +} + +/** \brief set oneshot mods + * + * FIXME: needs doc + */ +void set_oneshot_mods(uint8_t mods) { + if (!keymap_config.oneshot_disable) { + if (oneshot_mods != mods) { +# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) + oneshot_time = timer_read(); +# endif + oneshot_mods = mods; + oneshot_mods_changed_kb(mods); + } + } +} + +/** \brief clear oneshot mods + * + * FIXME: needs doc + */ +void clear_oneshot_mods(void) { + if (oneshot_mods) { + oneshot_mods = 0; +# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) + oneshot_time = 0; +# endif + oneshot_mods_changed_kb(oneshot_mods); + } +} +#endif + +/** \brief Called when the one shot modifiers have been changed. + * + * \param mods Contains the active modifiers active after the change. + */ +__attribute__((weak)) void oneshot_locked_mods_changed_user(uint8_t mods) {} + +/** \brief Called when the locked one shot modifiers have been changed. + * + * \param mods Contains the active modifiers active after the change. + */ +__attribute__((weak)) void oneshot_locked_mods_changed_kb(uint8_t mods) { oneshot_locked_mods_changed_user(mods); } + +/** \brief Called when the one shot modifiers have been changed. + * + * \param mods Contains the active modifiers active after the change. + */ +__attribute__((weak)) void oneshot_mods_changed_user(uint8_t mods) {} + +/** \brief Called when the one shot modifiers have been changed. + * + * \param mods Contains the active modifiers active after the change. + */ +__attribute__((weak)) void oneshot_mods_changed_kb(uint8_t mods) { oneshot_mods_changed_user(mods); } + +/** \brief Called when the one shot layers have been changed. + * + * \param layer Contains the layer that is toggled on, or zero when toggled off. + */ +__attribute__((weak)) void oneshot_layer_changed_user(uint8_t layer) {} + +/** \brief Called when the one shot layers have been changed. + * + * \param layer Contains the layer that is toggled on, or zero when toggled off. + */ +__attribute__((weak)) void oneshot_layer_changed_kb(uint8_t layer) { oneshot_layer_changed_user(layer); } + +/** \brief inspect keyboard state + * + * FIXME: needs doc + */ +uint8_t has_anymod(void) { return bitpop(real_mods); } diff --git a/quantum/action_util.h b/quantum/action_util.h new file mode 100644 index 0000000000..f2b3897ae5 --- /dev/null +++ b/quantum/action_util.h @@ -0,0 +1,105 @@ +/* +Copyright 2013 Jun Wako + +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 . +*/ + +#pragma once + +#include +#include "report.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern report_keyboard_t *keyboard_report; + +void send_keyboard_report(void); + +/* key */ +inline void add_key(uint8_t key) { add_key_to_report(keyboard_report, key); } + +inline void del_key(uint8_t key) { del_key_from_report(keyboard_report, key); } + +inline void clear_keys(void) { clear_keys_from_report(keyboard_report); } + +/* modifier */ +uint8_t get_mods(void); +void add_mods(uint8_t mods); +void del_mods(uint8_t mods); +void set_mods(uint8_t mods); +void clear_mods(void); + +/* weak modifier */ +uint8_t get_weak_mods(void); +void add_weak_mods(uint8_t mods); +void del_weak_mods(uint8_t mods); +void set_weak_mods(uint8_t mods); +void clear_weak_mods(void); + +/* macro modifier */ +uint8_t get_macro_mods(void); +void add_macro_mods(uint8_t mods); +void del_macro_mods(uint8_t mods); +void set_macro_mods(uint8_t mods); +void clear_macro_mods(void); + +/* oneshot modifier */ +uint8_t get_oneshot_mods(void); +void add_oneshot_mods(uint8_t mods); +void del_oneshot_mods(uint8_t mods); +void set_oneshot_mods(uint8_t mods); +void clear_oneshot_mods(void); +bool has_oneshot_mods_timed_out(void); + +uint8_t get_oneshot_locked_mods(void); +void set_oneshot_locked_mods(uint8_t mods); +void clear_oneshot_locked_mods(void); + +typedef enum { ONESHOT_PRESSED = 0b01, ONESHOT_OTHER_KEY_PRESSED = 0b10, ONESHOT_START = 0b11, ONESHOT_TOGGLED = 0b100 } oneshot_fullfillment_t; +void set_oneshot_layer(uint8_t layer, uint8_t state); +uint8_t get_oneshot_layer(void); +void clear_oneshot_layer_state(oneshot_fullfillment_t state); +void reset_oneshot_layer(void); +bool is_oneshot_layer_active(void); +uint8_t get_oneshot_layer_state(void); +bool has_oneshot_layer_timed_out(void); +bool has_oneshot_swaphands_timed_out(void); + +void oneshot_locked_mods_changed_user(uint8_t mods); +void oneshot_locked_mods_changed_kb(uint8_t mods); +void oneshot_mods_changed_user(uint8_t mods); +void oneshot_mods_changed_kb(uint8_t mods); +void oneshot_layer_changed_user(uint8_t layer); +void oneshot_layer_changed_kb(uint8_t layer); + +void oneshot_toggle(void); +void oneshot_enable(void); +void oneshot_disable(void); +bool is_oneshot_enabled(void); + +/* inspect */ +uint8_t has_anymod(void); + +#ifdef SWAP_HANDS_ENABLE +void set_oneshot_swaphands(void); +void release_oneshot_swaphands(void); +void use_oneshot_swaphands(void); +void clear_oneshot_swaphands(void); +#endif + +#ifdef __cplusplus +} +#endif diff --git a/quantum/eeconfig.c b/quantum/eeconfig.c new file mode 100644 index 0000000000..ffa56ab56d --- /dev/null +++ b/quantum/eeconfig.c @@ -0,0 +1,211 @@ +#include +#include +#include "eeprom.h" +#include "eeconfig.h" +#include "action_layer.h" + +#ifdef STM32_EEPROM_ENABLE +# include +# include "eeprom_stm32.h" +#endif + +#if defined(EEPROM_DRIVER) +# include "eeprom_driver.h" +#endif + +#if defined(HAPTIC_ENABLE) +# include "haptic.h" +#endif + +/** \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_Erase(); +#endif +#if defined(EEPROM_DRIVER) + eeprom_driver_erase(); +#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_LOWER_BYTE, 0); + eeprom_update_byte(EECONFIG_KEYMAP_UPPER_BYTE, 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); + eeprom_update_dword(EECONFIG_HAPTIC, 0); + eeprom_update_byte(EECONFIG_VELOCIKEY, 0); + eeprom_update_dword(EECONFIG_RGB_MATRIX, 0); + eeprom_update_word(EECONFIG_RGB_MATRIX_EXTENDED, 0); + + // TODO: Remove once ARM has a way to configure EECONFIG_HANDEDNESS + // within the emulated eeprom via dfu-util or another tool +#if defined INIT_EE_HANDS_LEFT +# pragma message "Faking EE_HANDS for left hand" + eeprom_update_byte(EECONFIG_HANDEDNESS, 1); +#elif defined INIT_EE_HANDS_RIGHT +# pragma message "Faking EE_HANDS for right hand" + eeprom_update_byte(EECONFIG_HANDEDNESS, 0); +#endif + +#if defined(HAPTIC_ENABLE) + haptic_reset(); +#else + // this is used in case haptic is disabled, but we still want sane defaults + // in the haptic configuration eeprom. All zero will trigger a haptic_reset + // when a haptic-enabled firmware is loaded onto the keyboard. + eeprom_update_dword(EECONFIG_HAPTIC, 0); +#endif + + eeconfig_init_kb(); +} + +/** \brief eeconfig initialization + * + * FIXME: needs doc + */ +void eeconfig_init(void) { eeconfig_init_quantum(); } + +/** \brief eeconfig enable + * + * FIXME: needs doc + */ +void eeconfig_enable(void) { eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER); } + +/** \brief eeconfig disable + * + * FIXME: needs doc + */ +void eeconfig_disable(void) { +#ifdef STM32_EEPROM_ENABLE + EEPROM_Erase(); +#endif +#if defined(EEPROM_DRIVER) + eeprom_driver_erase(); +#endif + eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER_OFF); +} + +/** \brief eeconfig is enabled + * + * FIXME: needs doc + */ +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 + */ +uint8_t eeconfig_read_debug(void) { return eeprom_read_byte(EECONFIG_DEBUG); } +/** \brief eeconfig update debug + * + * FIXME: needs doc + */ +void eeconfig_update_debug(uint8_t val) { eeprom_update_byte(EECONFIG_DEBUG, val); } + +/** \brief eeconfig read default layer + * + * FIXME: needs doc + */ +uint8_t eeconfig_read_default_layer(void) { return eeprom_read_byte(EECONFIG_DEFAULT_LAYER); } +/** \brief eeconfig update default layer + * + * FIXME: needs doc + */ +void eeconfig_update_default_layer(uint8_t val) { eeprom_update_byte(EECONFIG_DEFAULT_LAYER, val); } + +/** \brief eeconfig read keymap + * + * FIXME: needs doc + */ +uint16_t eeconfig_read_keymap(void) { return (eeprom_read_byte(EECONFIG_KEYMAP_LOWER_BYTE) | (eeprom_read_byte(EECONFIG_KEYMAP_UPPER_BYTE) << 8)); } +/** \brief eeconfig update keymap + * + * FIXME: needs doc + */ +void eeconfig_update_keymap(uint16_t val) { + eeprom_update_byte(EECONFIG_KEYMAP_LOWER_BYTE, val & 0xFF); + eeprom_update_byte(EECONFIG_KEYMAP_UPPER_BYTE, (val >> 8) & 0xFF); +} + +/** \brief eeconfig read audio + * + * FIXME: needs doc + */ +uint8_t eeconfig_read_audio(void) { return eeprom_read_byte(EECONFIG_AUDIO); } +/** \brief eeconfig update audio + * + * FIXME: needs doc + */ +void eeconfig_update_audio(uint8_t val) { eeprom_update_byte(EECONFIG_AUDIO, val); } + +/** \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); } + +/** \brief eeconfig read haptic + * + * FIXME: needs doc + */ +uint32_t eeconfig_read_haptic(void) { return eeprom_read_dword(EECONFIG_HAPTIC); } +/** \brief eeconfig update haptic + * + * FIXME: needs doc + */ +void eeconfig_update_haptic(uint32_t val) { eeprom_update_dword(EECONFIG_HAPTIC, val); } + +/** \brief eeconfig read split handedness + * + * FIXME: needs doc + */ +bool eeconfig_read_handedness(void) { return !!eeprom_read_byte(EECONFIG_HANDEDNESS); } +/** \brief eeconfig update split handedness + * + * FIXME: needs doc + */ +void eeconfig_update_handedness(bool val) { eeprom_update_byte(EECONFIG_HANDEDNESS, !!val); } diff --git a/quantum/eeconfig.h b/quantum/eeconfig.h new file mode 100644 index 0000000000..a88071729d --- /dev/null +++ b/quantum/eeconfig.h @@ -0,0 +1,113 @@ +/* +Copyright 2013 Jun Wako + +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 . +*/ + +#pragma once + +#include +#include + +#ifndef EECONFIG_MAGIC_NUMBER +# define EECONFIG_MAGIC_NUMBER (uint16_t)0xFEEA // When changing, decrement this value to avoid future re-init issues +#endif +#define EECONFIG_MAGIC_NUMBER_OFF (uint16_t)0xFFFF + +/* EEPROM parameter address */ +#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_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_KEYBOARD (uint32_t *)15 +#define EECONFIG_USER (uint32_t *)19 +#define EECONFIG_VELOCIKEY (uint8_t *)23 + +#define EECONFIG_HAPTIC (uint32_t *)24 + +// Mutually exclusive +#define EECONFIG_LED_MATRIX (uint32_t *)28 +#define EECONFIG_RGB_MATRIX (uint32_t *)28 +// Speed & Flags +#define EECONFIG_LED_MATRIX_EXTENDED (uint16_t *)32 +#define EECONFIG_RGB_MATRIX_EXTENDED (uint16_t *)32 + +// TODO: Combine these into a single word and single block of EEPROM +#define EECONFIG_KEYMAP_UPPER_BYTE (uint8_t *)34 +// Size of EEPROM being used, other code can refer to this for available EEPROM +#define EECONFIG_SIZE 35 +/* debug bit */ +#define EECONFIG_DEBUG_ENABLE (1 << 0) +#define EECONFIG_DEBUG_MATRIX (1 << 1) +#define EECONFIG_DEBUG_KEYBOARD (1 << 2) +#define EECONFIG_DEBUG_MOUSE (1 << 3) + +/* keyconf bit */ +#define EECONFIG_KEYMAP_SWAP_CONTROL_CAPSLOCK (1 << 0) +#define EECONFIG_KEYMAP_CAPSLOCK_TO_CONTROL (1 << 1) +#define EECONFIG_KEYMAP_SWAP_LALT_LGUI (1 << 2) +#define EECONFIG_KEYMAP_SWAP_RALT_RGUI (1 << 3) +#define EECONFIG_KEYMAP_NO_GUI (1 << 4) +#define EECONFIG_KEYMAP_SWAP_GRAVE_ESC (1 << 5) +#define EECONFIG_KEYMAP_SWAP_BACKSLASH_BACKSPACE (1 << 6) +#define EECONFIG_KEYMAP_NKRO (1 << 7) + +#define EECONFIG_KEYMAP_LOWER_BYTE EECONFIG_KEYMAP + +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); + +void eeconfig_disable(void); + +uint8_t eeconfig_read_debug(void); +void eeconfig_update_debug(uint8_t val); + +uint8_t eeconfig_read_default_layer(void); +void eeconfig_update_default_layer(uint8_t val); + +uint16_t eeconfig_read_keymap(void); +void eeconfig_update_keymap(uint16_t val); + +#ifdef AUDIO_ENABLE +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); + +#ifdef HAPTIC_ENABLE +uint32_t eeconfig_read_haptic(void); +void eeconfig_update_haptic(uint32_t val); +#endif + +bool eeconfig_read_handedness(void); +void eeconfig_update_handedness(bool val); diff --git a/quantum/keyboard.c b/quantum/keyboard.c new file mode 100644 index 0000000000..0eb41e7d30 --- /dev/null +++ b/quantum/keyboard.c @@ -0,0 +1,569 @@ +/* +Copyright 2011, 2012, 2013 Jun Wako + +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 . +*/ + +#include +#include "keyboard.h" +#include "matrix.h" +#include "keymap.h" +#include "host.h" +#include "led.h" +#include "keycode.h" +#include "timer.h" +#include "sync_timer.h" +#include "print.h" +#include "debug.h" +#include "command.h" +#include "util.h" +#include "sendchar.h" +#include "eeconfig.h" +#include "action_layer.h" +#ifdef BACKLIGHT_ENABLE +# include "backlight.h" +#endif +#ifdef MOUSEKEY_ENABLE +# include "mousekey.h" +#endif +#ifdef PS2_MOUSE_ENABLE +# include "ps2_mouse.h" +#endif +#ifdef SERIAL_MOUSE_ENABLE +# include "serial_mouse.h" +#endif +#ifdef ADB_MOUSE_ENABLE +# include "adb.h" +#endif +#ifdef RGBLIGHT_ENABLE +# include "rgblight.h" +#endif +#ifdef LED_MATRIX_ENABLE +# include "led_matrix.h" +#endif +#ifdef RGB_MATRIX_ENABLE +# include "rgb_matrix.h" +#endif +#ifdef ENCODER_ENABLE +# include "encoder.h" +#endif +#ifdef STENO_ENABLE +# include "process_steno.h" +#endif +#ifdef SERIAL_LINK_ENABLE +# include "serial_link/system/serial_link.h" +#endif +#ifdef VISUALIZER_ENABLE +# include "visualizer/visualizer.h" +#endif +#ifdef POINTING_DEVICE_ENABLE +# include "pointing_device.h" +#endif +#ifdef MIDI_ENABLE +# include "process_midi.h" +#endif +#ifdef JOYSTICK_ENABLE +# include "process_joystick.h" +#endif +#ifdef HD44780_ENABLE +# include "hd44780.h" +#endif +#ifdef QWIIC_ENABLE +# include "qwiic.h" +#endif +#ifdef OLED_DRIVER_ENABLE +# include "oled_driver.h" +#endif +#ifdef ST7565_ENABLE +# include "st7565.h" +#endif +#ifdef VELOCIKEY_ENABLE +# include "velocikey.h" +#endif +#ifdef VIA_ENABLE +# include "via.h" +#endif +#ifdef DIP_SWITCH_ENABLE +# include "dip_switch.h" +#endif +#ifdef STM32_EEPROM_ENABLE +# include "eeprom_stm32.h" +#endif +#ifdef EEPROM_DRIVER +# include "eeprom_driver.h" +#endif +#if defined(CRC_ENABLE) +# include "crc.h" +#endif +#ifdef DIGITIZER_ENABLE +# include "digitizer.h" +#endif + +static uint32_t last_input_modification_time = 0; +uint32_t last_input_activity_time(void) { return last_input_modification_time; } +uint32_t last_input_activity_elapsed(void) { return timer_elapsed32(last_input_modification_time); } + +static uint32_t last_matrix_modification_time = 0; +uint32_t last_matrix_activity_time(void) { return last_matrix_modification_time; } +uint32_t last_matrix_activity_elapsed(void) { return timer_elapsed32(last_matrix_modification_time); } +void last_matrix_activity_trigger(void) { last_matrix_modification_time = last_input_modification_time = timer_read32(); } + +static uint32_t last_encoder_modification_time = 0; +uint32_t last_encoder_activity_time(void) { return last_encoder_modification_time; } +uint32_t last_encoder_activity_elapsed(void) { return timer_elapsed32(last_encoder_modification_time); } +void last_encoder_activity_trigger(void) { last_encoder_modification_time = last_input_modification_time = timer_read32(); } + +// Only enable this if console is enabled to print to +#if defined(DEBUG_MATRIX_SCAN_RATE) +static uint32_t matrix_timer = 0; +static uint32_t matrix_scan_count = 0; +static uint32_t last_matrix_scan_count = 0; + +void matrix_scan_perf_task(void) { + matrix_scan_count++; + + uint32_t timer_now = timer_read32(); + if (TIMER_DIFF_32(timer_now, matrix_timer) > 1000) { +# if defined(CONSOLE_ENABLE) + dprintf("matrix scan frequency: %lu\n", matrix_scan_count); +# endif + last_matrix_scan_count = matrix_scan_count; + matrix_timer = timer_now; + matrix_scan_count = 0; + } +} + +uint32_t get_matrix_scan_rate(void) { return last_matrix_scan_count; } +#else +# define matrix_scan_perf_task() +#endif + +#ifdef MATRIX_HAS_GHOST +extern const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS]; +static matrix_row_t get_real_keys(uint8_t row, matrix_row_t rowdata) { + matrix_row_t out = 0; + for (uint8_t col = 0; col < MATRIX_COLS; col++) { + // read each key in the row data and check if the keymap defines it as a real key + if (pgm_read_byte(&keymaps[0][row][col]) && (rowdata & (1 << col))) { + // this creates new row data, if a key is defined in the keymap, it will be set here + out |= 1 << col; + } + } + return out; +} + +static inline bool popcount_more_than_one(matrix_row_t rowdata) { + rowdata &= rowdata - 1; // if there are less than two bits (keys) set, rowdata will become zero + return rowdata; +} + +static inline bool has_ghost_in_row(uint8_t row, matrix_row_t rowdata) { + /* No ghost exists when less than 2 keys are down on the row. + If there are "active" blanks in the matrix, the key can't be pressed by the user, + there is no doubt as to which keys are really being pressed. + The ghosts will be ignored, they are KC_NO. */ + rowdata = get_real_keys(row, rowdata); + if ((popcount_more_than_one(rowdata)) == 0) { + return false; + } + /* Ghost occurs when the row shares a column line with other row, + and two columns are read on each row. Blanks in the matrix don't matter, + so they are filtered out. + If there are two or more real keys pressed and they match columns with + at least two of another row's real keys, the row will be ignored. Keep in mind, + we are checking one row at a time, not all of them at once. + */ + for (uint8_t i = 0; i < MATRIX_ROWS; i++) { + if (i != row && popcount_more_than_one(get_real_keys(i, matrix_get_row(i)) & rowdata)) { + return true; + } + } + return false; +} + +#endif + +void disable_jtag(void) { +// To use PF4-7 (PC2-5 on ATmega32A), disable JTAG by writing JTD bit twice within four cycles. +#if (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__)) + MCUCR |= _BV(JTD); + MCUCR |= _BV(JTD); +#elif defined(__AVR_ATmega32A__) + MCUCSR |= _BV(JTD); + MCUCSR |= _BV(JTD); +#endif +} + +/** \brief matrix_setup + * + * FIXME: needs doc + */ +__attribute__((weak)) void matrix_setup(void) {} + +/** \brief keyboard_pre_init_user + * + * FIXME: needs doc + */ +__attribute__((weak)) void keyboard_pre_init_user(void) {} + +/** \brief keyboard_pre_init_kb + * + * FIXME: needs doc + */ +__attribute__((weak)) void keyboard_pre_init_kb(void) { keyboard_pre_init_user(); } + +/** \brief keyboard_post_init_user + * + * FIXME: needs doc + */ + +__attribute__((weak)) void keyboard_post_init_user() {} + +/** \brief keyboard_post_init_kb + * + * FIXME: needs doc + */ + +__attribute__((weak)) void keyboard_post_init_kb(void) { keyboard_post_init_user(); } + +/** \brief keyboard_setup + * + * FIXME: needs doc + */ +void keyboard_setup(void) { +#ifndef NO_JTAG_DISABLE + disable_jtag(); +#endif + print_set_sendchar(sendchar); +#ifdef STM32_EEPROM_ENABLE + EEPROM_Init(); +#endif +#ifdef EEPROM_DRIVER + eeprom_driver_init(); +#endif + matrix_setup(); + keyboard_pre_init_kb(); +} + +#ifndef SPLIT_KEYBOARD + +/** \brief is_keyboard_master + * + * FIXME: needs doc + */ +__attribute__((weak)) bool is_keyboard_master(void) { return true; } + +/** \brief is_keyboard_left + * + * FIXME: needs doc + */ +__attribute__((weak)) bool is_keyboard_left(void) { return true; } + +#endif + +/** \brief should_process_keypress + * + * Override this function if you have a condition where keypresses processing should change: + * - splits where the slave side needs to process for rgb/oled functionality + */ +__attribute__((weak)) bool should_process_keypress(void) { return is_keyboard_master(); } + +/** \brief housekeeping_task_kb + * + * Override this function if you have a need to execute code for every keyboard main loop iteration. + * This is specific to keyboard-level functionality. + */ +__attribute__((weak)) void housekeeping_task_kb(void) {} + +/** \brief housekeeping_task_user + * + * Override this function if you have a need to execute code for every keyboard main loop iteration. + * This is specific to user/keymap-level functionality. + */ +__attribute__((weak)) void housekeeping_task_user(void) {} + +/** \brief housekeeping_task + * + * Invokes hooks for executing code after QMK is done after each loop iteration. + */ +void housekeeping_task(void) { + housekeeping_task_kb(); + housekeeping_task_user(); +} + +/** \brief keyboard_init + * + * FIXME: needs doc + */ +void keyboard_init(void) { + timer_init(); + sync_timer_init(); + matrix_init(); +#if defined(CRC_ENABLE) + crc_init(); +#endif +#ifdef VIA_ENABLE + via_init(); +#endif +#ifdef QWIIC_ENABLE + qwiic_init(); +#endif +#ifdef OLED_DRIVER_ENABLE + oled_init(OLED_ROTATION_0); +#endif +#ifdef ST7565_ENABLE + st7565_init(DISPLAY_ROTATION_0); +#endif +#ifdef PS2_MOUSE_ENABLE + ps2_mouse_init(); +#endif +#ifdef SERIAL_MOUSE_ENABLE + serial_mouse_init(); +#endif +#ifdef ADB_MOUSE_ENABLE + adb_mouse_init(); +#endif +#ifdef BACKLIGHT_ENABLE + backlight_init(); +#endif +#ifdef RGBLIGHT_ENABLE + rgblight_init(); +#endif +#ifdef ENCODER_ENABLE + encoder_init(); +#endif +#ifdef STENO_ENABLE + steno_init(); +#endif +#ifdef POINTING_DEVICE_ENABLE + pointing_device_init(); +#endif +#if defined(NKRO_ENABLE) && defined(FORCE_NKRO) + keymap_config.nkro = 1; + eeconfig_update_keymap(keymap_config.raw); +#endif +#ifdef DIP_SWITCH_ENABLE + dip_switch_init(); +#endif + +#if defined(DEBUG_MATRIX_SCAN_RATE) && defined(CONSOLE_ENABLE) + debug_enable = true; +#endif + + keyboard_post_init_kb(); /* Always keep this last */ +} + +/** \brief key_event_task + * + * This function is responsible for calling into other systems when they need to respond to electrical switch press events. + * This is differnet than keycode events as no layer processing, or filtering occurs. + */ +void switch_events(uint8_t row, uint8_t col, bool pressed) { +#if defined(LED_MATRIX_ENABLE) + process_led_matrix(row, col, pressed); +#endif +#if defined(RGB_MATRIX_ENABLE) + process_rgb_matrix(row, col, pressed); +#endif +} + +/** \brief Keyboard task: Do keyboard routine jobs + * + * Do routine keyboard jobs: + * + * * scan matrix + * * handle mouse movements + * * run visualizer code + * * handle midi commands + * * light LEDs + * + * This is repeatedly called as fast as possible. + */ +void keyboard_task(void) { + static matrix_row_t matrix_prev[MATRIX_ROWS]; + static uint8_t led_status = 0; + matrix_row_t matrix_row = 0; + matrix_row_t matrix_change = 0; +#ifdef QMK_KEYS_PER_SCAN + uint8_t keys_processed = 0; +#endif +#ifdef ENCODER_ENABLE + bool encoders_changed = false; +#endif + + uint8_t matrix_changed = matrix_scan(); + if (matrix_changed) last_matrix_activity_trigger(); + + for (uint8_t r = 0; r < MATRIX_ROWS; r++) { + matrix_row = matrix_get_row(r); + matrix_change = matrix_row ^ matrix_prev[r]; + if (matrix_change) { +#ifdef MATRIX_HAS_GHOST + if (has_ghost_in_row(r, matrix_row)) { + continue; + } +#endif + if (debug_matrix) matrix_print(); + matrix_row_t col_mask = 1; + for (uint8_t c = 0; c < MATRIX_COLS; c++, col_mask <<= 1) { + if (matrix_change & col_mask) { + if (should_process_keypress()) { + action_exec((keyevent_t){ + .key = (keypos_t){.row = r, .col = c}, .pressed = (matrix_row & col_mask), .time = (timer_read() | 1) /* time should not be 0 */ + }); + } + // record a processed key + matrix_prev[r] ^= col_mask; + + switch_events(r, c, (matrix_row & col_mask)); + +#ifdef QMK_KEYS_PER_SCAN + // only jump out if we have processed "enough" keys. + if (++keys_processed >= QMK_KEYS_PER_SCAN) +#endif + // process a key per task call + goto MATRIX_LOOP_END; + } + } + } + } + // call with pseudo tick event when no real key event. +#ifdef QMK_KEYS_PER_SCAN + // we can get here with some keys processed now. + if (!keys_processed) +#endif + action_exec(TICK); + +MATRIX_LOOP_END: + +#ifdef DEBUG_MATRIX_SCAN_RATE + matrix_scan_perf_task(); +#endif + +#if defined(RGBLIGHT_ENABLE) + rgblight_task(); +#endif + +#ifdef LED_MATRIX_ENABLE + led_matrix_task(); +#endif +#ifdef RGB_MATRIX_ENABLE + rgb_matrix_task(); +#endif + +#if defined(BACKLIGHT_ENABLE) +# if defined(BACKLIGHT_PIN) || defined(BACKLIGHT_PINS) + backlight_task(); +# endif +#endif + +#ifdef ENCODER_ENABLE + encoders_changed = encoder_read(); + if (encoders_changed) last_encoder_activity_trigger(); +#endif + +#ifdef QWIIC_ENABLE + qwiic_task(); +#endif + +#ifdef OLED_DRIVER_ENABLE + oled_task(); +# ifndef OLED_DISABLE_TIMEOUT + // Wake up oled if user is using those fabulous keys or spinning those encoders! +# ifdef ENCODER_ENABLE + if (matrix_changed || encoders_changed) oled_on(); +# else + if (matrix_changed) oled_on(); +# endif +# endif +#endif + +#ifdef ST7565_ENABLE + st7565_task(); +# ifndef ST7565_DISABLE_TIMEOUT + // Wake up display if user is using those fabulous keys or spinning those encoders! +# ifdef ENCODER_ENABLE + if (matrix_changed || encoders_changed) st7565_on(); +# else + if (matrix_changed) st7565_on(); +# endif +# endif +#endif + +#ifdef MOUSEKEY_ENABLE + // mousekey repeat & acceleration + mousekey_task(); +#endif + +#ifdef PS2_MOUSE_ENABLE + ps2_mouse_task(); +#endif + +#ifdef SERIAL_MOUSE_ENABLE + serial_mouse_task(); +#endif + +#ifdef ADB_MOUSE_ENABLE + adb_mouse_task(); +#endif + +#ifdef SERIAL_LINK_ENABLE + serial_link_update(); +#endif + +#ifdef VISUALIZER_ENABLE + visualizer_update(default_layer_state, layer_state, visualizer_get_mods(), host_keyboard_leds()); +#endif + +#ifdef POINTING_DEVICE_ENABLE + pointing_device_task(); +#endif + +#ifdef MIDI_ENABLE + midi_task(); +#endif + +#ifdef VELOCIKEY_ENABLE + if (velocikey_enabled()) { + velocikey_decelerate(); + } +#endif + +#ifdef JOYSTICK_ENABLE + joystick_task(); +#endif + +#ifdef DIGITIZER_ENABLE + digitizer_task(); +#endif + + // update LED + if (led_status != host_keyboard_leds()) { + led_status = host_keyboard_leds(); + keyboard_set_leds(led_status); + } +} + +/** \brief keyboard set leds + * + * FIXME: needs doc + */ +void keyboard_set_leds(uint8_t leds) { + if (debug_keyboard) { + debug("keyboard_set_led: "); + debug_hex8(leds); + debug("\n"); + } + led_set(leds); +} diff --git a/quantum/keyboard.h b/quantum/keyboard.h new file mode 100644 index 0000000000..08f4e84f94 --- /dev/null +++ b/quantum/keyboard.h @@ -0,0 +1,90 @@ +/* +Copyright 2011,2012,2013 Jun Wako + +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 . +*/ + +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* key matrix position */ +typedef struct { + uint8_t col; + uint8_t row; +} keypos_t; + +/* key event */ +typedef struct { + keypos_t key; + bool pressed; + uint16_t time; +} keyevent_t; + +/* equivalent test of keypos_t */ +#define KEYEQ(keya, keyb) ((keya).row == (keyb).row && (keya).col == (keyb).col) + +/* Rules for No Event: + * 1) (time == 0) to handle (keyevent_t){} as empty event + * 2) Matrix(255, 255) to make TICK event available + */ +static inline bool IS_NOEVENT(keyevent_t event) { return event.time == 0 || (event.key.row == 255 && event.key.col == 255); } +static inline bool IS_PRESSED(keyevent_t event) { return (!IS_NOEVENT(event) && event.pressed); } +static inline bool IS_RELEASED(keyevent_t event) { return (!IS_NOEVENT(event) && !event.pressed); } + +/* Tick event */ +#define TICK \ + (keyevent_t) { .key = (keypos_t){.row = 255, .col = 255}, .pressed = false, .time = (timer_read() | 1) } + +/* 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. */ +void keyboard_init(void); +/* it runs repeatedly in main loop */ +void keyboard_task(void); +/* it runs when host LED status is updated */ +void keyboard_set_leds(uint8_t leds); +/* it runs whenever code has to behave differently on a slave */ +bool is_keyboard_master(void); +/* it runs whenever code has to behave differently on left vs right split */ +bool is_keyboard_left(void); + +void keyboard_pre_init_kb(void); +void keyboard_pre_init_user(void); +void keyboard_post_init_kb(void); +void keyboard_post_init_user(void); + +void housekeeping_task(void); // To be executed by the main loop in each backend TMK protocol +void housekeeping_task_kb(void); // To be overridden by keyboard-level code +void housekeeping_task_user(void); // To be overridden by user/keymap-level code + +uint32_t last_input_activity_time(void); // Timestamp of the last matrix or encoder activity +uint32_t last_input_activity_elapsed(void); // Number of milliseconds since the last matrix or encoder activity + +uint32_t last_matrix_activity_time(void); // Timestamp of the last matrix activity +uint32_t last_matrix_activity_elapsed(void); // Number of milliseconds since the last matrix activity + +uint32_t last_encoder_activity_time(void); // Timestamp of the last encoder activity +uint32_t last_encoder_activity_elapsed(void); // Number of milliseconds since the last encoder activity + +uint32_t get_matrix_scan_rate(void); + +#ifdef __cplusplus +} +#endif diff --git a/quantum/keycode.h b/quantum/keycode.h new file mode 100644 index 0000000000..8facabd818 --- /dev/null +++ b/quantum/keycode.h @@ -0,0 +1,560 @@ +/* +Copyright 2011,2012 Jun Wako + +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 . +*/ + +/* + * Keycodes based on HID Keyboard/Keypad Usage Page (0x07) plus media keys from Generic Desktop Page (0x01) and Consumer Page (0x0C) + * + * See https://web.archive.org/web/20060218214400/http://www.usb.org/developers/devclass_docs/Hut1_12.pdf + * or http://www.usb.org/developers/hidpage/Hut1_12v2.pdf (older) + */ + +#pragma once + +/* FIXME: Add doxygen comments here */ + +#define IS_ERROR(code) (KC_ROLL_OVER <= (code) && (code) <= KC_UNDEFINED) +#define IS_ANY(code) (KC_A <= (code) && (code) <= 0xFF) +#define IS_KEY(code) (KC_A <= (code) && (code) <= KC_EXSEL) +#define IS_MOD(code) (KC_LCTRL <= (code) && (code) <= KC_RGUI) + +#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_BRID) + +#define IS_FN(code) (KC_FN0 <= (code) && (code) <= KC_FN31) + +#define IS_MOUSEKEY(code) (KC_MS_UP <= (code) && (code) <= KC_MS_ACCEL2) +#define IS_MOUSEKEY_MOVE(code) (KC_MS_UP <= (code) && (code) <= KC_MS_RIGHT) +#define IS_MOUSEKEY_BUTTON(code) (KC_MS_BTN1 <= (code) && (code) <= KC_MS_BTN8) +#define IS_MOUSEKEY_WHEEL(code) (KC_MS_WH_UP <= (code) && (code) <= KC_MS_WH_RIGHT) +#define IS_MOUSEKEY_ACCEL(code) (KC_MS_ACCEL0 <= (code) && (code) <= KC_MS_ACCEL2) + +#define MOD_BIT(code) (1 << MOD_INDEX(code)) +#define MOD_INDEX(code) ((code)&0x07) + +#define MOD_MASK_CTRL (MOD_BIT(KC_LCTRL) | MOD_BIT(KC_RCTRL)) +#define MOD_MASK_SHIFT (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) +#define MOD_MASK_ALT (MOD_BIT(KC_LALT) | MOD_BIT(KC_RALT)) +#define MOD_MASK_GUI (MOD_BIT(KC_LGUI) | MOD_BIT(KC_RGUI)) +#define MOD_MASK_CS (MOD_MASK_CTRL | MOD_MASK_SHIFT) +#define MOD_MASK_CA (MOD_MASK_CTRL | MOD_MASK_ALT) +#define MOD_MASK_CG (MOD_MASK_CTRL | MOD_MASK_GUI) +#define MOD_MASK_SA (MOD_MASK_SHIFT | MOD_MASK_ALT) +#define MOD_MASK_SG (MOD_MASK_SHIFT | MOD_MASK_GUI) +#define MOD_MASK_AG (MOD_MASK_ALT | MOD_MASK_GUI) +#define MOD_MASK_CSA (MOD_MASK_CTRL | MOD_MASK_SHIFT | MOD_MASK_ALT) +#define MOD_MASK_CSG (MOD_MASK_CTRL | MOD_MASK_SHIFT | MOD_MASK_GUI) +#define MOD_MASK_CAG (MOD_MASK_CTRL | MOD_MASK_ALT | MOD_MASK_GUI) +#define MOD_MASK_SAG (MOD_MASK_SHIFT | MOD_MASK_ALT | MOD_MASK_GUI) +#define MOD_MASK_CSAG (MOD_MASK_CTRL | MOD_MASK_SHIFT | MOD_MASK_ALT | MOD_MASK_GUI) + +#define FN_BIT(code) (1 << FN_INDEX(code)) +#define FN_INDEX(code) ((code)-KC_FN0) +#define FN_MIN KC_FN0 +#define FN_MAX KC_FN31 + +/* + * Short names for ease of definition of keymap + */ +/* Transparent */ +#define KC_TRANSPARENT 0x01 +#define KC_TRNS KC_TRANSPARENT + +/* Punctuation */ +#define KC_ENT KC_ENTER +#define KC_ESC KC_ESCAPE +#define KC_BSPC KC_BSPACE +#define KC_SPC KC_SPACE +#define KC_MINS KC_MINUS +#define KC_EQL KC_EQUAL +#define KC_LBRC KC_LBRACKET +#define KC_RBRC KC_RBRACKET +#define KC_BSLS KC_BSLASH +#define KC_NUHS KC_NONUS_HASH +#define KC_SCLN KC_SCOLON +#define KC_QUOT KC_QUOTE +#define KC_GRV KC_GRAVE +#define KC_COMM KC_COMMA +#define KC_SLSH KC_SLASH +#define KC_NUBS KC_NONUS_BSLASH + +/* Lock Keys */ +#define KC_CLCK KC_CAPSLOCK +#define KC_CAPS KC_CAPSLOCK +#define KC_SLCK KC_SCROLLLOCK +#define KC_NLCK KC_NUMLOCK +#define KC_LCAP KC_LOCKING_CAPS +#define KC_LNUM KC_LOCKING_NUM +#define KC_LSCR KC_LOCKING_SCROLL + +/* Commands */ +#define KC_PSCR KC_PSCREEN +#define KC_PAUS KC_PAUSE +#define KC_BRK KC_PAUSE +#define KC_INS KC_INSERT +#define KC_DEL KC_DELETE +#define KC_PGDN KC_PGDOWN +#define KC_RGHT KC_RIGHT +#define KC_APP KC_APPLICATION +#define KC_EXEC KC_EXECUTE +#define KC_SLCT KC_SELECT +#define KC_AGIN KC_AGAIN +#define KC_PSTE KC_PASTE +#define KC_ERAS KC_ALT_ERASE +#define KC_CLR KC_CLEAR + +/* Keypad */ +#define KC_PSLS KC_KP_SLASH +#define KC_PAST KC_KP_ASTERISK +#define KC_PMNS KC_KP_MINUS +#define KC_PPLS KC_KP_PLUS +#define KC_PENT KC_KP_ENTER +#define KC_P1 KC_KP_1 +#define KC_P2 KC_KP_2 +#define KC_P3 KC_KP_3 +#define KC_P4 KC_KP_4 +#define KC_P5 KC_KP_5 +#define KC_P6 KC_KP_6 +#define KC_P7 KC_KP_7 +#define KC_P8 KC_KP_8 +#define KC_P9 KC_KP_9 +#define KC_P0 KC_KP_0 +#define KC_PDOT KC_KP_DOT +#define KC_PEQL KC_KP_EQUAL +#define KC_PCMM KC_KP_COMMA + +/* Japanese specific */ +#define KC_ZKHK KC_GRAVE +#define KC_RO KC_INT1 +#define KC_KANA KC_INT2 +#define KC_JYEN KC_INT3 +#define KC_HENK KC_INT4 +#define KC_MHEN KC_INT5 + +/* Korean specific */ +#define KC_HAEN KC_LANG1 +#define KC_HANJ KC_LANG2 + +/* Modifiers */ +#define KC_LCTL KC_LCTRL +#define KC_LSFT KC_LSHIFT +#define KC_LOPT KC_LALT +#define KC_LCMD KC_LGUI +#define KC_LWIN KC_LGUI +#define KC_RCTL KC_RCTRL +#define KC_RSFT KC_RSHIFT +#define KC_ALGR KC_RALT +#define KC_ROPT KC_RALT +#define KC_RCMD KC_RGUI +#define KC_RWIN KC_RGUI + +/* Generic Desktop Page (0x01) */ +#define KC_PWR KC_SYSTEM_POWER +#define KC_SLEP KC_SYSTEM_SLEEP +#define KC_WAKE KC_SYSTEM_WAKE + +/* Consumer Page (0x0C) */ +#define KC_MUTE KC_AUDIO_MUTE +#define KC_VOLU KC_AUDIO_VOL_UP +#define KC_VOLD KC_AUDIO_VOL_DOWN +#define KC_MNXT KC_MEDIA_NEXT_TRACK +#define KC_MPRV KC_MEDIA_PREV_TRACK +#define KC_MSTP KC_MEDIA_STOP +#define KC_MPLY KC_MEDIA_PLAY_PAUSE +#define KC_MSEL KC_MEDIA_SELECT +#define KC_EJCT KC_MEDIA_EJECT +#define KC_CALC KC_CALCULATOR +#define KC_MYCM KC_MY_COMPUTER +#define KC_WSCH KC_WWW_SEARCH +#define KC_WHOM KC_WWW_HOME +#define KC_WBAK KC_WWW_BACK +#define KC_WFWD KC_WWW_FORWARD +#define KC_WSTP KC_WWW_STOP +#define KC_WREF KC_WWW_REFRESH +#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 + +/* System Specific */ +#define KC_BRMU KC_PAUSE +#define KC_BRMD KC_SCROLLLOCK + +/* Mouse Keys */ +#define KC_MS_U KC_MS_UP +#define KC_MS_D KC_MS_DOWN +#define KC_MS_L KC_MS_LEFT +#define KC_MS_R KC_MS_RIGHT +#define KC_BTN1 KC_MS_BTN1 +#define KC_BTN2 KC_MS_BTN2 +#define KC_BTN3 KC_MS_BTN3 +#define KC_BTN4 KC_MS_BTN4 +#define KC_BTN5 KC_MS_BTN5 +#define KC_BTN6 KC_MS_BTN6 +#define KC_BTN7 KC_MS_BTN7 +#define KC_BTN8 KC_MS_BTN8 +#define KC_WH_U KC_MS_WH_UP +#define KC_WH_D KC_MS_WH_DOWN +#define KC_WH_L KC_MS_WH_LEFT +#define KC_WH_R KC_MS_WH_RIGHT +#define KC_ACL0 KC_MS_ACCEL0 +#define KC_ACL1 KC_MS_ACCEL1 +#define KC_ACL2 KC_MS_ACCEL2 + +/* Keyboard/Keypad Page (0x07) */ +enum hid_keyboard_keypad_usage { + KC_NO = 0x00, + KC_ROLL_OVER, + KC_POST_FAIL, + KC_UNDEFINED, + KC_A, + KC_B, + KC_C, + KC_D, + KC_E, + KC_F, + KC_G, + KC_H, + KC_I, + KC_J, + KC_K, + KC_L, + KC_M, // 0x10 + KC_N, + KC_O, + KC_P, + KC_Q, + KC_R, + KC_S, + KC_T, + KC_U, + KC_V, + KC_W, + KC_X, + KC_Y, + KC_Z, + KC_1, + KC_2, + KC_3, // 0x20 + KC_4, + KC_5, + KC_6, + KC_7, + KC_8, + KC_9, + KC_0, + KC_ENTER, + KC_ESCAPE, + KC_BSPACE, + KC_TAB, + KC_SPACE, + KC_MINUS, + KC_EQUAL, + KC_LBRACKET, + KC_RBRACKET, // 0x30 + KC_BSLASH, + KC_NONUS_HASH, + KC_SCOLON, + KC_QUOTE, + KC_GRAVE, + KC_COMMA, + KC_DOT, + KC_SLASH, + KC_CAPSLOCK, + KC_F1, + KC_F2, + KC_F3, + KC_F4, + KC_F5, + KC_F6, + KC_F7, // 0x40 + KC_F8, + KC_F9, + KC_F10, + KC_F11, + KC_F12, + KC_PSCREEN, + KC_SCROLLLOCK, + KC_PAUSE, + KC_INSERT, + KC_HOME, + KC_PGUP, + KC_DELETE, + KC_END, + KC_PGDOWN, + KC_RIGHT, + KC_LEFT, // 0x50 + KC_DOWN, + KC_UP, + KC_NUMLOCK, + KC_KP_SLASH, + KC_KP_ASTERISK, + KC_KP_MINUS, + KC_KP_PLUS, + KC_KP_ENTER, + KC_KP_1, + KC_KP_2, + KC_KP_3, + KC_KP_4, + KC_KP_5, + KC_KP_6, + KC_KP_7, + KC_KP_8, // 0x60 + KC_KP_9, + KC_KP_0, + KC_KP_DOT, + KC_NONUS_BSLASH, + KC_APPLICATION, + KC_POWER, + KC_KP_EQUAL, + KC_F13, + KC_F14, + KC_F15, + KC_F16, + KC_F17, + KC_F18, + KC_F19, + KC_F20, + KC_F21, // 0x70 + KC_F22, + KC_F23, + KC_F24, + KC_EXECUTE, + KC_HELP, + KC_MENU, + KC_SELECT, + KC_STOP, + KC_AGAIN, + KC_UNDO, + KC_CUT, + KC_COPY, + KC_PASTE, + KC_FIND, + KC__MUTE, + KC__VOLUP, // 0x80 + KC__VOLDOWN, + KC_LOCKING_CAPS, + KC_LOCKING_NUM, + KC_LOCKING_SCROLL, + KC_KP_COMMA, + KC_KP_EQUAL_AS400, + KC_INT1, + KC_INT2, + KC_INT3, + KC_INT4, + KC_INT5, + KC_INT6, + KC_INT7, + KC_INT8, + KC_INT9, + KC_LANG1, // 0x90 + KC_LANG2, + KC_LANG3, + KC_LANG4, + KC_LANG5, + KC_LANG6, + KC_LANG7, + KC_LANG8, + KC_LANG9, + KC_ALT_ERASE, + KC_SYSREQ, + KC_CANCEL, + KC_CLEAR, + KC_PRIOR, + KC_RETURN, + KC_SEPARATOR, + KC_OUT, // 0xA0 + KC_OPER, + KC_CLEAR_AGAIN, + KC_CRSEL, + KC_EXSEL, + +#if 0 + // *************************************************************** + // These keycodes are present in the HID spec, but are * + // nonfunctional on modern OSes. QMK uses this range (0xA5-0xDF) * + // for the media and function keys instead - see below. * + // *************************************************************** + + KC_KP_00 = 0xB0, + KC_KP_000, + KC_THOUSANDS_SEPARATOR, + KC_DECIMAL_SEPARATOR, + KC_CURRENCY_UNIT, + KC_CURRENCY_SUB_UNIT, + KC_KP_LPAREN, + KC_KP_RPAREN, + KC_KP_LCBRACKET, + KC_KP_RCBRACKET, + KC_KP_TAB, + KC_KP_BSPACE, + KC_KP_A, + KC_KP_B, + KC_KP_C, + KC_KP_D, + KC_KP_E, //0xC0 + KC_KP_F, + KC_KP_XOR, + KC_KP_HAT, + KC_KP_PERC, + KC_KP_LT, + KC_KP_GT, + KC_KP_AND, + KC_KP_LAZYAND, + KC_KP_OR, + KC_KP_LAZYOR, + KC_KP_COLON, + KC_KP_HASH, + KC_KP_SPACE, + KC_KP_ATMARK, + KC_KP_EXCLAMATION, + KC_KP_MEM_STORE, //0xD0 + KC_KP_MEM_RECALL, + KC_KP_MEM_CLEAR, + KC_KP_MEM_ADD, + KC_KP_MEM_SUB, + KC_KP_MEM_MUL, + KC_KP_MEM_DIV, + KC_KP_PLUS_MINUS, + KC_KP_CLEAR, + KC_KP_CLEAR_ENTRY, + KC_KP_BINARY, + KC_KP_OCTAL, + KC_KP_DECIMAL, + KC_KP_HEXADECIMAL, +#endif + + /* Modifiers */ + KC_LCTRL = 0xE0, + KC_LSHIFT, + KC_LALT, + KC_LGUI, + KC_RCTRL, + KC_RSHIFT, + KC_RALT, + KC_RGUI + + // ********************************************** + // * 0xF0-0xFF are unallocated in the HID spec. * + // * QMK uses these for Mouse Keys - see below. * + // ********************************************** +}; + +/* Media and Function keys */ +enum internal_special_keycodes { + /* Generic Desktop Page (0x01) */ + KC_SYSTEM_POWER = 0xA5, + KC_SYSTEM_SLEEP, + KC_SYSTEM_WAKE, + + /* Consumer Page (0x0C) */ + KC_AUDIO_MUTE, + KC_AUDIO_VOL_UP, + KC_AUDIO_VOL_DOWN, + KC_MEDIA_NEXT_TRACK, + KC_MEDIA_PREV_TRACK, + KC_MEDIA_STOP, + KC_MEDIA_PLAY_PAUSE, + KC_MEDIA_SELECT, + KC_MEDIA_EJECT, // 0xB0 + KC_MAIL, + KC_CALCULATOR, + KC_MY_COMPUTER, + KC_WWW_SEARCH, + KC_WWW_HOME, + KC_WWW_BACK, + KC_WWW_FORWARD, + KC_WWW_STOP, + KC_WWW_REFRESH, + KC_WWW_FAVORITES, + KC_MEDIA_FAST_FORWARD, + KC_MEDIA_REWIND, + KC_BRIGHTNESS_UP, + KC_BRIGHTNESS_DOWN, + + /* Fn keys */ + KC_FN0 = 0xC0, + KC_FN1, + KC_FN2, + KC_FN3, + KC_FN4, + KC_FN5, + KC_FN6, + KC_FN7, + KC_FN8, + KC_FN9, + KC_FN10, + KC_FN11, + KC_FN12, + KC_FN13, + KC_FN14, + KC_FN15, + KC_FN16, // 0xD0 + KC_FN17, + KC_FN18, + KC_FN19, + KC_FN20, + KC_FN21, + KC_FN22, + KC_FN23, + KC_FN24, + KC_FN25, + KC_FN26, + KC_FN27, + KC_FN28, + KC_FN29, + KC_FN30, + KC_FN31 +}; + +enum mouse_keys { +/* Mouse Buttons */ +#ifdef VIA_ENABLE + KC_MS_UP = 0xF0, +#else + KC_MS_UP = 0xED, +#endif + KC_MS_DOWN, + KC_MS_LEFT, + KC_MS_RIGHT, // 0xF0 + KC_MS_BTN1, + KC_MS_BTN2, + KC_MS_BTN3, + KC_MS_BTN4, + KC_MS_BTN5, +#ifdef VIA_ENABLE + KC_MS_BTN6 = KC_MS_BTN5, + KC_MS_BTN7 = KC_MS_BTN5, + KC_MS_BTN8 = KC_MS_BTN5, +#else + KC_MS_BTN6, + KC_MS_BTN7, + KC_MS_BTN8, +#endif + + /* Mouse Wheel */ + KC_MS_WH_UP, + KC_MS_WH_DOWN, + KC_MS_WH_LEFT, + KC_MS_WH_RIGHT, + + /* Acceleration */ + KC_MS_ACCEL0, + KC_MS_ACCEL1, + KC_MS_ACCEL2 // 0xFF +}; diff --git a/quantum/via.h b/quantum/via.h index d0510fcabd..de0a21da20 100644 --- a/quantum/via.h +++ b/quantum/via.h @@ -16,7 +16,7 @@ #pragma once -#include "tmk_core/common/eeconfig.h" // for EECONFIG_SIZE +#include "eeconfig.h" // for EECONFIG_SIZE // Keyboard level code can change where VIA stores the magic. // The magic is the build date YYMMDD encoded as BCD in 3 bytes, diff --git a/tmk_core/common.mk b/tmk_core/common.mk index 57de8d95e8..69d27e6c0b 100644 --- a/tmk_core/common.mk +++ b/tmk_core/common.mk @@ -1,14 +1,8 @@ COMMON_DIR = common PLATFORM_COMMON_DIR = $(COMMON_DIR)/$(PLATFORM_KEY) -TMK_COMMON_SRC += $(COMMON_DIR)/host.c \ - $(COMMON_DIR)/keyboard.c \ - $(COMMON_DIR)/action.c \ - $(COMMON_DIR)/action_tapping.c \ - $(COMMON_DIR)/action_macro.c \ - $(COMMON_DIR)/action_layer.c \ - $(COMMON_DIR)/action_util.c \ - $(COMMON_DIR)/eeconfig.c \ +TMK_COMMON_SRC += \ + $(COMMON_DIR)/host.c \ $(COMMON_DIR)/report.c \ $(COMMON_DIR)/sync_timer.c \ $(COMMON_DIR)/usb_util.c \ diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c deleted file mode 100644 index d19fd2a045..0000000000 --- a/tmk_core/common/action.c +++ /dev/null @@ -1,1126 +0,0 @@ -/* -Copyright 2012,2013 Jun Wako - -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 . -*/ -#include "host.h" -#include "keycode.h" -#include "keyboard.h" -#include "mousekey.h" -#include "command.h" -#include "led.h" -#include "action_layer.h" -#include "action_tapping.h" -#include "action_macro.h" -#include "action_util.h" -#include "action.h" -#include "wait.h" - -#ifdef BACKLIGHT_ENABLE -# include "backlight.h" -#endif - -#ifdef DEBUG_ACTION -# include "debug.h" -#else -# include "nodebug.h" -#endif - -#ifdef POINTING_DEVICE_ENABLE -# include "pointing_device.h" -#endif - -int tp_buttons; - -#if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) -int retro_tapping_counter = 0; -#endif - -#ifdef IGNORE_MOD_TAP_INTERRUPT_PER_KEY -__attribute__((weak)) bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record) { return false; } -#endif - -#ifdef RETRO_TAPPING_PER_KEY -__attribute__((weak)) bool get_retro_tapping(uint16_t keycode, keyrecord_t *record) { return false; } -#endif - -__attribute__((weak)) bool pre_process_record_quantum(keyrecord_t *record) { return true; } - -#ifndef TAP_CODE_DELAY -# define TAP_CODE_DELAY 0 -#endif -#ifndef TAP_HOLD_CAPS_DELAY -# define TAP_HOLD_CAPS_DELAY 80 -#endif -/** \brief Called to execute an action. - * - * FIXME: Needs documentation. - */ -void action_exec(keyevent_t event) { - if (!IS_NOEVENT(event)) { - dprint("\n---- action_exec: start -----\n"); - dprint("EVENT: "); - debug_event(event); - dprintln(); -#if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) - retro_tapping_counter++; -#endif - } - - if (event.pressed) { - // clear the potential weak mods left by previously pressed keys - clear_weak_mods(); - } - -#ifdef SWAP_HANDS_ENABLE - if (!IS_NOEVENT(event)) { - process_hand_swap(&event); - } -#endif - - keyrecord_t record = {.event = event}; - -#ifndef NO_ACTION_ONESHOT -# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) - if (has_oneshot_layer_timed_out()) { - clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); - } - if (has_oneshot_mods_timed_out()) { - clear_oneshot_mods(); - } -# ifdef SWAP_HANDS_ENABLE - if (has_oneshot_swaphands_timed_out()) { - clear_oneshot_swaphands(); - } -# endif -# endif -#endif - -#ifndef NO_ACTION_TAPPING - if (IS_NOEVENT(record.event) || pre_process_record_quantum(&record)) { - action_tapping_process(record); - } -#else - if (IS_NOEVENT(record.event) || pre_process_record_quantum(&record)) { - process_record(&record); - } - if (!IS_NOEVENT(record.event)) { - dprint("processed: "); - debug_record(record); - dprintln(); - } -#endif -} - -#ifdef SWAP_HANDS_ENABLE -bool swap_hands = false; -bool swap_held = false; - -/** \brief Process Hand Swap - * - * FIXME: Needs documentation. - */ -void process_hand_swap(keyevent_t *event) { - static swap_state_row_t swap_state[MATRIX_ROWS]; - - keypos_t pos = event->key; - swap_state_row_t col_bit = (swap_state_row_t)1 << pos.col; - bool do_swap = event->pressed ? swap_hands : swap_state[pos.row] & (col_bit); - - if (do_swap) { - event->key.row = pgm_read_byte(&hand_swap_config[pos.row][pos.col].row); - event->key.col = pgm_read_byte(&hand_swap_config[pos.row][pos.col].col); - swap_state[pos.row] |= col_bit; - } else { - swap_state[pos.row] &= ~(col_bit); - } -} -#endif - -#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE) -bool disable_action_cache = false; - -void process_record_nocache(keyrecord_t *record) { - disable_action_cache = true; - process_record(record); - disable_action_cache = false; -} -#else -void process_record_nocache(keyrecord_t *record) { process_record(record); } -#endif - -__attribute__((weak)) bool process_record_quantum(keyrecord_t *record) { return true; } - -__attribute__((weak)) void post_process_record_quantum(keyrecord_t *record) {} - -#ifndef NO_ACTION_TAPPING -/** \brief Allows for handling tap-hold actions immediately instead of waiting for TAPPING_TERM or another keypress. - * - * FIXME: Needs documentation. - */ -void process_record_tap_hint(keyrecord_t *record) { - action_t action = layer_switch_get_action(record->event.key); - - switch (action.kind.id) { -# ifdef SWAP_HANDS_ENABLE - case ACT_SWAP_HANDS: - switch (action.swap.code) { - case OP_SH_ONESHOT: - break; - case OP_SH_TAP_TOGGLE: - default: - swap_hands = !swap_hands; - swap_held = true; - } - break; -# endif - } -} -#endif - -/** \brief Take a key event (key press or key release) and processes it. - * - * FIXME: Needs documentation. - */ -void process_record(keyrecord_t *record) { - if (IS_NOEVENT(record->event)) { - return; - } - - if (!process_record_quantum(record)) { -#ifndef NO_ACTION_ONESHOT - if (is_oneshot_layer_active() && record->event.pressed) { - clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); - } -#endif - return; - } - - process_record_handler(record); - post_process_record_quantum(record); -} - -void process_record_handler(keyrecord_t *record) { -#ifdef COMBO_ENABLE - action_t action; - if (record->keycode) { - action = action_for_keycode(record->keycode); - } else { - action = store_or_get_action(record->event.pressed, record->event.key); - } -#else - action_t action = store_or_get_action(record->event.pressed, record->event.key); -#endif - dprint("ACTION: "); - debug_action(action); -#ifndef NO_ACTION_LAYER - dprint(" layer_state: "); - layer_debug(); - dprint(" default_layer_state: "); - default_layer_debug(); -#endif - dprintln(); - - process_action(record, action); -} - -#if defined(PS2_MOUSE_ENABLE) || defined(POINTING_DEVICE_ENABLE) -void register_button(bool pressed, enum mouse_buttons button) { -# ifdef PS2_MOUSE_ENABLE - tp_buttons = pressed ? tp_buttons | button : tp_buttons & ~button; -# endif -# ifdef POINTING_DEVICE_ENABLE - report_mouse_t currentReport = pointing_device_get_report(); - currentReport.buttons = pressed ? currentReport.buttons | button : currentReport.buttons & ~button; - pointing_device_set_report(currentReport); -# endif -} -#endif - -/** \brief Take an action and processes it. - * - * FIXME: Needs documentation. - */ -void process_action(keyrecord_t *record, action_t action) { - keyevent_t event = record->event; -#ifndef NO_ACTION_TAPPING - uint8_t tap_count = record->tap.count; -#endif - -#ifndef NO_ACTION_ONESHOT - bool do_release_oneshot = false; - // notice we only clear the one shot layer if the pressed key is not a modifier. - if (is_oneshot_layer_active() && event.pressed && (action.kind.id == ACT_USAGE || !IS_MOD(action.key.code)) -# ifdef SWAP_HANDS_ENABLE - && !(action.kind.id == ACT_SWAP_HANDS && action.swap.code == OP_SH_ONESHOT) -# endif - ) { - clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); - do_release_oneshot = !is_oneshot_layer_active(); - } -#endif - - switch (action.kind.id) { - /* Key and Mods */ - case ACT_LMODS: - case ACT_RMODS: { - uint8_t mods = (action.kind.id == ACT_LMODS) ? action.key.mods : action.key.mods << 4; - if (event.pressed) { - if (mods) { - if (IS_MOD(action.key.code) || action.key.code == KC_NO) { - // e.g. LSFT(KC_LGUI): we don't want the LSFT to be weak as it would make it useless. - // This also makes LSFT(KC_LGUI) behave exactly the same as LGUI(KC_LSFT). - // Same applies for some keys like KC_MEH which are declared as MEH(KC_NO). - add_mods(mods); - } else { - add_weak_mods(mods); - } - send_keyboard_report(); - } - register_code(action.key.code); - } else { - unregister_code(action.key.code); - if (mods) { - if (IS_MOD(action.key.code) || action.key.code == KC_NO) { - del_mods(mods); - } else { - del_weak_mods(mods); - } - send_keyboard_report(); - } - } - } break; -#ifndef NO_ACTION_TAPPING - case ACT_LMODS_TAP: - case ACT_RMODS_TAP: { - uint8_t mods = (action.kind.id == ACT_LMODS_TAP) ? action.key.mods : action.key.mods << 4; - switch (action.layer_tap.code) { -# ifndef NO_ACTION_ONESHOT - case MODS_ONESHOT: - // Oneshot modifier - if (event.pressed) { - if (tap_count == 0) { - dprint("MODS_TAP: Oneshot: 0\n"); - register_mods(mods | get_oneshot_mods()); - } else if (tap_count == 1) { - dprint("MODS_TAP: Oneshot: start\n"); - set_oneshot_mods(mods | get_oneshot_mods()); -# if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1 - } else if (tap_count == ONESHOT_TAP_TOGGLE) { - dprint("MODS_TAP: Toggling oneshot"); - clear_oneshot_mods(); - set_oneshot_locked_mods(mods); - register_mods(mods); -# endif - } else { - register_mods(mods | get_oneshot_mods()); - } - } else { - if (tap_count == 0) { - clear_oneshot_mods(); - unregister_mods(mods); - } else if (tap_count == 1) { - // Retain Oneshot mods -# if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1 - if (mods & get_mods()) { - clear_oneshot_locked_mods(); - clear_oneshot_mods(); - unregister_mods(mods); - } - } else if (tap_count == ONESHOT_TAP_TOGGLE) { - // Toggle Oneshot Layer -# endif - } else { - clear_oneshot_mods(); - unregister_mods(mods); - } - } - break; -# endif - case MODS_TAP_TOGGLE: - if (event.pressed) { - if (tap_count <= TAPPING_TOGGLE) { - register_mods(mods); - } - } else { - if (tap_count < TAPPING_TOGGLE) { - unregister_mods(mods); - } - } - break; - default: - if (event.pressed) { - if (tap_count > 0) { -# if !defined(IGNORE_MOD_TAP_INTERRUPT) || defined(IGNORE_MOD_TAP_INTERRUPT_PER_KEY) - if ( -# ifdef IGNORE_MOD_TAP_INTERRUPT_PER_KEY - !get_ignore_mod_tap_interrupt(get_event_keycode(record->event, false), record) && -# endif - record->tap.interrupted) { - dprint("mods_tap: tap: cancel: add_mods\n"); - // ad hoc: set 0 to cancel tap - record->tap.count = 0; - register_mods(mods); - } else -# endif - { - dprint("MODS_TAP: Tap: register_code\n"); - register_code(action.key.code); - } - } else { - dprint("MODS_TAP: No tap: add_mods\n"); - register_mods(mods); - } - } else { - if (tap_count > 0) { - dprint("MODS_TAP: Tap: unregister_code\n"); - if (action.layer_tap.code == KC_CAPS) { - wait_ms(TAP_HOLD_CAPS_DELAY); - } else { - wait_ms(TAP_CODE_DELAY); - } - unregister_code(action.key.code); - } else { - dprint("MODS_TAP: No tap: add_mods\n"); - unregister_mods(mods); - } - } - break; - } - } break; -#endif -#ifdef EXTRAKEY_ENABLE - /* other HID usage */ - case ACT_USAGE: - switch (action.usage.page) { - case PAGE_SYSTEM: - if (event.pressed) { - host_system_send(action.usage.code); - } else { - host_system_send(0); - } - break; - case PAGE_CONSUMER: - if (event.pressed) { - host_consumer_send(action.usage.code); - } else { - host_consumer_send(0); - } - break; - } - break; -#endif -#ifdef MOUSEKEY_ENABLE - /* Mouse key */ - case ACT_MOUSEKEY: - if (event.pressed) { - mousekey_on(action.key.code); - } else { - mousekey_off(action.key.code); - } - switch (action.key.code) { -# if defined(PS2_MOUSE_ENABLE) || defined(POINTING_DEVICE_ENABLE) -# ifdef POINTING_DEVICE_ENABLE - case KC_MS_BTN1 ... KC_MS_BTN8: -# else - case KC_MS_BTN1 ... KC_MS_BTN3: -# endif - register_button(event.pressed, MOUSE_BTN_MASK(action.key.code - KC_MS_BTN1)); - break; -# endif - default: - mousekey_send(); - break; - } - break; -#endif -#ifndef NO_ACTION_LAYER - case ACT_LAYER: - if (action.layer_bitop.on == 0) { - /* Default Layer Bitwise Operation */ - if (!event.pressed) { - uint8_t shift = action.layer_bitop.part * 4; - layer_state_t bits = ((layer_state_t)action.layer_bitop.bits) << shift; - layer_state_t mask = (action.layer_bitop.xbit) ? ~(((layer_state_t)0xf) << shift) : 0; - switch (action.layer_bitop.op) { - case OP_BIT_AND: - default_layer_and(bits | mask); - break; - case OP_BIT_OR: - default_layer_or(bits | mask); - break; - case OP_BIT_XOR: - default_layer_xor(bits | mask); - break; - case OP_BIT_SET: - default_layer_set(bits | mask); - break; - } - } - } else { - /* Layer Bitwise Operation */ - if (event.pressed ? (action.layer_bitop.on & ON_PRESS) : (action.layer_bitop.on & ON_RELEASE)) { - uint8_t shift = action.layer_bitop.part * 4; - layer_state_t bits = ((layer_state_t)action.layer_bitop.bits) << shift; - layer_state_t mask = (action.layer_bitop.xbit) ? ~(((layer_state_t)0xf) << shift) : 0; - switch (action.layer_bitop.op) { - case OP_BIT_AND: - layer_and(bits | mask); - break; - case OP_BIT_OR: - layer_or(bits | mask); - break; - case OP_BIT_XOR: - layer_xor(bits | mask); - break; - case OP_BIT_SET: - layer_state_set(bits | mask); - break; - } - } - } - break; - case ACT_LAYER_MODS: - if (event.pressed) { - layer_on(action.layer_mods.layer); - register_mods(action.layer_mods.mods); - } else { - unregister_mods(action.layer_mods.mods); - layer_off(action.layer_mods.layer); - } - break; -# ifndef NO_ACTION_TAPPING - case ACT_LAYER_TAP: - case ACT_LAYER_TAP_EXT: - switch (action.layer_tap.code) { - case OP_TAP_TOGGLE: - /* tap toggle */ - if (event.pressed) { - if (tap_count < TAPPING_TOGGLE) { - layer_invert(action.layer_tap.val); - } - } else { - if (tap_count <= TAPPING_TOGGLE) { - layer_invert(action.layer_tap.val); - } - } - break; - case OP_ON_OFF: - event.pressed ? layer_on(action.layer_tap.val) : layer_off(action.layer_tap.val); - break; - case OP_OFF_ON: - event.pressed ? layer_off(action.layer_tap.val) : layer_on(action.layer_tap.val); - break; - case OP_SET_CLEAR: - event.pressed ? layer_move(action.layer_tap.val) : layer_clear(); - break; -# ifndef NO_ACTION_ONESHOT - case OP_ONESHOT: - // Oneshot modifier -# if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1 - do_release_oneshot = false; - if (event.pressed) { - del_mods(get_oneshot_locked_mods()); - if (get_oneshot_layer_state() == ONESHOT_TOGGLED) { - reset_oneshot_layer(); - layer_off(action.layer_tap.val); - break; - } else if (tap_count < ONESHOT_TAP_TOGGLE) { - layer_on(action.layer_tap.val); - set_oneshot_layer(action.layer_tap.val, ONESHOT_START); - } - } else { - add_mods(get_oneshot_locked_mods()); - if (tap_count >= ONESHOT_TAP_TOGGLE) { - reset_oneshot_layer(); - clear_oneshot_locked_mods(); - set_oneshot_layer(action.layer_tap.val, ONESHOT_TOGGLED); - } else { - clear_oneshot_layer_state(ONESHOT_PRESSED); - } - } -# else - if (event.pressed) { - layer_on(action.layer_tap.val); - set_oneshot_layer(action.layer_tap.val, ONESHOT_START); - } else { - clear_oneshot_layer_state(ONESHOT_PRESSED); - if (tap_count > 1) { - clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); - } - } -# endif - break; -# endif - default: - /* tap key */ - if (event.pressed) { - if (tap_count > 0) { - dprint("KEYMAP_TAP_KEY: Tap: register_code\n"); - register_code(action.layer_tap.code); - } else { - dprint("KEYMAP_TAP_KEY: No tap: On on press\n"); - layer_on(action.layer_tap.val); - } - } else { - if (tap_count > 0) { - dprint("KEYMAP_TAP_KEY: Tap: unregister_code\n"); - if (action.layer_tap.code == KC_CAPS) { - wait_ms(TAP_HOLD_CAPS_DELAY); - } else { - wait_ms(TAP_CODE_DELAY); - } - unregister_code(action.layer_tap.code); - } else { - dprint("KEYMAP_TAP_KEY: No tap: Off on release\n"); - layer_off(action.layer_tap.val); - } - } - break; - } - break; -# endif -#endif - /* Extentions */ -#ifndef NO_ACTION_MACRO - case ACT_MACRO: - action_macro_play(action_get_macro(record, action.func.id, action.func.opt)); - break; -#endif -#ifdef SWAP_HANDS_ENABLE - case ACT_SWAP_HANDS: - switch (action.swap.code) { - case OP_SH_TOGGLE: - if (event.pressed) { - swap_hands = !swap_hands; - } - break; - case OP_SH_ON_OFF: - swap_hands = event.pressed; - break; - case OP_SH_OFF_ON: - swap_hands = !event.pressed; - break; - case OP_SH_ON: - if (!event.pressed) { - swap_hands = true; - } - break; - case OP_SH_OFF: - if (!event.pressed) { - swap_hands = false; - } - break; -# ifndef NO_ACTION_ONESHOT - case OP_SH_ONESHOT: - if (event.pressed) { - set_oneshot_swaphands(); - } else { - release_oneshot_swaphands(); - } - break; -# endif - -# ifndef NO_ACTION_TAPPING - case OP_SH_TAP_TOGGLE: - /* tap toggle */ - - if (event.pressed) { - if (swap_held) { - swap_held = false; - } else { - swap_hands = !swap_hands; - } - } else { - if (tap_count < TAPPING_TOGGLE) { - swap_hands = !swap_hands; - } - } - break; - default: - /* tap key */ - if (tap_count > 0) { - if (swap_held) { - swap_hands = !swap_hands; // undo hold set up in _tap_hint - swap_held = false; - } - if (event.pressed) { - register_code(action.swap.code); - } else { - wait_ms(TAP_CODE_DELAY); - unregister_code(action.swap.code); - *record = (keyrecord_t){}; // hack: reset tap mode - } - } else { - if (swap_held && !event.pressed) { - swap_hands = !swap_hands; // undo hold set up in _tap_hint - swap_held = false; - } - } -# endif - } -#endif -#ifndef NO_ACTION_FUNCTION - case ACT_FUNCTION: - action_function(record, action.func.id, action.func.opt); - break; -#endif - default: - break; - } - -#ifndef NO_ACTION_LAYER - // if this event is a layer action, update the leds - switch (action.kind.id) { - case ACT_LAYER: - case ACT_LAYER_MODS: -# ifndef NO_ACTION_TAPPING - case ACT_LAYER_TAP: - case ACT_LAYER_TAP_EXT: -# endif - led_set(host_keyboard_leds()); - break; - default: - break; - } -#endif - -#ifndef NO_ACTION_TAPPING -# if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) - if (!is_tap_action(action)) { - retro_tapping_counter = 0; - } else { - if (event.pressed) { - if (tap_count > 0) { - retro_tapping_counter = 0; - } - } else { - if (tap_count > 0) { - retro_tapping_counter = 0; - } else { - if ( -# ifdef RETRO_TAPPING_PER_KEY - get_retro_tapping(get_event_keycode(record->event, false), record) && -# endif - retro_tapping_counter == 2) { - tap_code(action.layer_tap.code); - } - retro_tapping_counter = 0; - } - } - } -# endif -#endif - -#ifdef SWAP_HANDS_ENABLE -# ifndef NO_ACTION_ONESHOT - if (event.pressed && !(action.kind.id == ACT_SWAP_HANDS && action.swap.code == OP_SH_ONESHOT)) { - use_oneshot_swaphands(); - } -# endif -#endif - -#ifndef NO_ACTION_ONESHOT - /* Because we switch layers after a oneshot event, we need to release the - * key before we leave the layer or no key up event will be generated. - */ - if (do_release_oneshot && !(get_oneshot_layer_state() & ONESHOT_PRESSED)) { - record->event.pressed = false; - layer_on(get_oneshot_layer()); - process_record(record); - layer_off(get_oneshot_layer()); - } -#endif -} - -/** \brief Utilities for actions. (FIXME: Needs better description) - * - * FIXME: Needs documentation. - */ -void register_code(uint8_t code) { - if (code == KC_NO) { - return; - } -#ifdef LOCKING_SUPPORT_ENABLE - else if (KC_LOCKING_CAPS == code) { -# ifdef LOCKING_RESYNC_ENABLE - // Resync: ignore if caps lock already is on - if (host_keyboard_leds() & (1 << USB_LED_CAPS_LOCK)) return; -# endif - add_key(KC_CAPSLOCK); - send_keyboard_report(); - wait_ms(100); - del_key(KC_CAPSLOCK); - send_keyboard_report(); - } - - else if (KC_LOCKING_NUM == code) { -# ifdef LOCKING_RESYNC_ENABLE - if (host_keyboard_leds() & (1 << USB_LED_NUM_LOCK)) return; -# endif - add_key(KC_NUMLOCK); - send_keyboard_report(); - wait_ms(100); - del_key(KC_NUMLOCK); - send_keyboard_report(); - } - - else if (KC_LOCKING_SCROLL == code) { -# ifdef LOCKING_RESYNC_ENABLE - if (host_keyboard_leds() & (1 << USB_LED_SCROLL_LOCK)) return; -# endif - add_key(KC_SCROLLLOCK); - send_keyboard_report(); - wait_ms(100); - del_key(KC_SCROLLLOCK); - send_keyboard_report(); - } -#endif - - else if IS_KEY (code) { - // TODO: should push command_proc out of this block? - if (command_proc(code)) return; - -#ifndef NO_ACTION_ONESHOT -/* TODO: remove - if (oneshot_state.mods && !oneshot_state.disabled) { - uint8_t tmp_mods = get_mods(); - add_mods(oneshot_state.mods); - - add_key(code); - send_keyboard_report(); - - set_mods(tmp_mods); - send_keyboard_report(); - oneshot_cancel(); - } else -*/ -#endif - { - // Force a new key press if the key is already pressed - // without this, keys with the same keycode, but different - // modifiers will be reported incorrectly, see issue #1708 - if (is_key_pressed(keyboard_report, code)) { - del_key(code); - send_keyboard_report(); - } - add_key(code); - send_keyboard_report(); - } - } else if IS_MOD (code) { - add_mods(MOD_BIT(code)); - send_keyboard_report(); - } -#ifdef EXTRAKEY_ENABLE - else if IS_SYSTEM (code) { - host_system_send(KEYCODE2SYSTEM(code)); - } else if IS_CONSUMER (code) { - host_consumer_send(KEYCODE2CONSUMER(code)); - } -#endif -#ifdef MOUSEKEY_ENABLE - else if IS_MOUSEKEY (code) { - mousekey_on(code); - mousekey_send(); - } -#endif -} - -/** \brief Utilities for actions. (FIXME: Needs better description) - * - * FIXME: Needs documentation. - */ -void unregister_code(uint8_t code) { - if (code == KC_NO) { - return; - } -#ifdef LOCKING_SUPPORT_ENABLE - else if (KC_LOCKING_CAPS == code) { -# ifdef LOCKING_RESYNC_ENABLE - // Resync: ignore if caps lock already is off - if (!(host_keyboard_leds() & (1 << USB_LED_CAPS_LOCK))) return; -# endif - add_key(KC_CAPSLOCK); - send_keyboard_report(); - del_key(KC_CAPSLOCK); - send_keyboard_report(); - } - - else if (KC_LOCKING_NUM == code) { -# ifdef LOCKING_RESYNC_ENABLE - if (!(host_keyboard_leds() & (1 << USB_LED_NUM_LOCK))) return; -# endif - add_key(KC_NUMLOCK); - send_keyboard_report(); - del_key(KC_NUMLOCK); - send_keyboard_report(); - } - - else if (KC_LOCKING_SCROLL == code) { -# ifdef LOCKING_RESYNC_ENABLE - if (!(host_keyboard_leds() & (1 << USB_LED_SCROLL_LOCK))) return; -# endif - add_key(KC_SCROLLLOCK); - send_keyboard_report(); - del_key(KC_SCROLLLOCK); - send_keyboard_report(); - } -#endif - - else if IS_KEY (code) { - del_key(code); - send_keyboard_report(); - } else if IS_MOD (code) { - del_mods(MOD_BIT(code)); - send_keyboard_report(); - } else if IS_SYSTEM (code) { - host_system_send(0); - } else if IS_CONSUMER (code) { - host_consumer_send(0); - } -#ifdef MOUSEKEY_ENABLE - else if IS_MOUSEKEY (code) { - mousekey_off(code); - mousekey_send(); - } -#endif -} - -/** \brief Tap a keycode with a delay. - * - * \param code The basic keycode to tap. - * \param delay The amount of time in milliseconds to leave the keycode registered, before unregistering it. - */ -void tap_code_delay(uint8_t code, uint16_t delay) { - register_code(code); - for (uint16_t i = delay; i > 0; i--) { - wait_ms(1); - } - unregister_code(code); -} - -/** \brief Tap a keycode with the default delay. - * - * \param code The basic keycode to tap. If `code` is `KC_CAPS`, the delay will be `TAP_HOLD_CAPS_DELAY`, otherwise `TAP_CODE_DELAY`, if defined. - */ -void tap_code(uint8_t code) { tap_code_delay(code, code == KC_CAPS ? TAP_HOLD_CAPS_DELAY : TAP_CODE_DELAY); } - -/** \brief Adds the given physically pressed modifiers and sends a keyboard report immediately. - * - * \param mods A bitfield of modifiers to register. - */ -void register_mods(uint8_t mods) { - if (mods) { - add_mods(mods); - send_keyboard_report(); - } -} - -/** \brief Removes the given physically pressed modifiers and sends a keyboard report immediately. - * - * \param mods A bitfield of modifiers to unregister. - */ -void unregister_mods(uint8_t mods) { - if (mods) { - del_mods(mods); - send_keyboard_report(); - } -} - -/** \brief Adds the given weak modifiers and sends a keyboard report immediately. - * - * \param mods A bitfield of modifiers to register. - */ -void register_weak_mods(uint8_t mods) { - if (mods) { - add_weak_mods(mods); - send_keyboard_report(); - } -} - -/** \brief Removes the given weak modifiers and sends a keyboard report immediately. - * - * \param mods A bitfield of modifiers to unregister. - */ -void unregister_weak_mods(uint8_t mods) { - if (mods) { - del_weak_mods(mods); - send_keyboard_report(); - } -} - -/** \brief Utilities for actions. (FIXME: Needs better description) - * - * FIXME: Needs documentation. - */ -void clear_keyboard(void) { - clear_mods(); - clear_keyboard_but_mods(); -} - -/** \brief Utilities for actions. (FIXME: Needs better description) - * - * 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() { -#ifdef EXTRAKEY_ENABLE - host_system_send(0); - host_consumer_send(0); -#endif - clear_weak_mods(); - clear_macro_mods(); - send_keyboard_report(); -#ifdef MOUSEKEY_ENABLE - mousekey_clear(); - mousekey_send(); -#endif -} - -/** \brief Utilities for actions. (FIXME: Needs better description) - * - * FIXME: Needs documentation. - */ -bool is_tap_key(keypos_t key) { - action_t action = layer_switch_get_action(key); - return is_tap_action(action); -} - -/** \brief Utilities for actions. (FIXME: Needs better description) - * - * FIXME: Needs documentation. - */ -bool is_tap_record(keyrecord_t *record) { -#ifdef COMBO_ENABLE - action_t action; - if (record->keycode) { - action = action_for_keycode(record->keycode); - } else { - action = layer_switch_get_action(record->event.key); - } -#else - action_t action = layer_switch_get_action(record->event.key); -#endif - return is_tap_action(action); -} - -/** \brief Utilities for actions. (FIXME: Needs better description) - * - * FIXME: Needs documentation. - */ -bool is_tap_action(action_t action) { - switch (action.kind.id) { - case ACT_LMODS_TAP: - case ACT_RMODS_TAP: - case ACT_LAYER_TAP: - case ACT_LAYER_TAP_EXT: - switch (action.layer_tap.code) { - case KC_NO ... KC_RGUI: - case OP_TAP_TOGGLE: - case OP_ONESHOT: - return true; - } - return false; - case ACT_SWAP_HANDS: - switch (action.swap.code) { - case KC_NO ... KC_RGUI: - case OP_SH_TAP_TOGGLE: - return true; - } - return false; - case ACT_MACRO: - case ACT_FUNCTION: - if (action.func.opt & FUNC_TAP) { - return true; - } - return false; - } - return false; -} - -/** \brief Debug print (FIXME: Needs better description) - * - * FIXME: Needs documentation. - */ -void debug_event(keyevent_t event) { dprintf("%04X%c(%u)", (event.key.row << 8 | event.key.col), (event.pressed ? 'd' : 'u'), event.time); } -/** \brief Debug print (FIXME: Needs better description) - * - * FIXME: Needs documentation. - */ -void debug_record(keyrecord_t record) { - debug_event(record.event); -#ifndef NO_ACTION_TAPPING - dprintf(":%u%c", record.tap.count, (record.tap.interrupted ? '-' : ' ')); -#endif -} - -/** \brief Debug print (FIXME: Needs better description) - * - * FIXME: Needs documentation. - */ -void debug_action(action_t action) { - switch (action.kind.id) { - case ACT_LMODS: - dprint("ACT_LMODS"); - break; - case ACT_RMODS: - dprint("ACT_RMODS"); - break; - case ACT_LMODS_TAP: - dprint("ACT_LMODS_TAP"); - break; - case ACT_RMODS_TAP: - dprint("ACT_RMODS_TAP"); - break; - case ACT_USAGE: - dprint("ACT_USAGE"); - break; - case ACT_MOUSEKEY: - dprint("ACT_MOUSEKEY"); - break; - case ACT_LAYER: - dprint("ACT_LAYER"); - break; - case ACT_LAYER_MODS: - dprint("ACT_LAYER_MODS"); - break; - case ACT_LAYER_TAP: - dprint("ACT_LAYER_TAP"); - break; - case ACT_LAYER_TAP_EXT: - dprint("ACT_LAYER_TAP_EXT"); - break; - case ACT_MACRO: - dprint("ACT_MACRO"); - break; - case ACT_FUNCTION: - dprint("ACT_FUNCTION"); - break; - case ACT_SWAP_HANDS: - dprint("ACT_SWAP_HANDS"); - break; - default: - dprint("UNKNOWN"); - break; - } - dprintf("[%X:%02X]", action.kind.param >> 8, action.kind.param & 0xff); -} diff --git a/tmk_core/common/action.h b/tmk_core/common/action.h deleted file mode 100644 index 3d357b33b8..0000000000 --- a/tmk_core/common/action.h +++ /dev/null @@ -1,132 +0,0 @@ -/* -Copyright 2012,2013 Jun Wako - -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 . -*/ - -#pragma once - -#include -#include -#include "keyboard.h" -#include "keycode.h" -#include "action_code.h" -#include "action_macro.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Disable macro and function features when LTO is enabled, since they break */ -#ifdef LTO_ENABLE -# ifndef NO_ACTION_MACRO -# define NO_ACTION_MACRO -# endif -# ifndef NO_ACTION_FUNCTION -# define NO_ACTION_FUNCTION -# endif -#endif - -/* tapping count and state */ -typedef struct { - bool interrupted : 1; - bool reserved2 : 1; - bool reserved1 : 1; - bool reserved0 : 1; - uint8_t count : 4; -} tap_t; - -/* Key event container for recording */ -typedef struct { - keyevent_t event; -#ifndef NO_ACTION_TAPPING - tap_t tap; -#endif -#ifdef COMBO_ENABLE - uint16_t keycode; -#endif -} keyrecord_t; - -/* Execute action per keyevent */ -void action_exec(keyevent_t event); - -/* action for key */ -action_t action_for_key(uint8_t layer, keypos_t key); -action_t action_for_keycode(uint16_t keycode); - -/* macro */ -const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt); - -/* user defined special function */ -void action_function(keyrecord_t *record, uint8_t id, uint8_t opt); - -/* keyboard-specific key event (pre)processing */ -bool process_record_quantum(keyrecord_t *record); - -/* Utilities for actions. */ -#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE) -extern bool disable_action_cache; -#endif - -/* Code for handling one-handed key modifiers. */ -#ifdef SWAP_HANDS_ENABLE -extern bool swap_hands; -extern const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS]; -# if (MATRIX_COLS <= 8) -typedef uint8_t swap_state_row_t; -# elif (MATRIX_COLS <= 16) -typedef uint16_t swap_state_row_t; -# elif (MATRIX_COLS <= 32) -typedef uint32_t swap_state_row_t; -# else -# error "MATRIX_COLS: invalid value" -# endif - -void process_hand_swap(keyevent_t *record); -#endif - -void process_record_nocache(keyrecord_t *record); -void process_record(keyrecord_t *record); -void process_record_handler(keyrecord_t *record); -void post_process_record_quantum(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 tap_code_delay(uint8_t code, uint16_t delay); -void register_mods(uint8_t mods); -void unregister_mods(uint8_t mods); -void register_weak_mods(uint8_t mods); -void unregister_weak_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); -bool is_tap_record(keyrecord_t *record); -bool is_tap_action(action_t action); - -#ifndef NO_ACTION_TAPPING -void process_record_tap_hint(keyrecord_t *record); -#endif - -/* debug */ -void debug_event(keyevent_t event); -void debug_record(keyrecord_t record); -void debug_action(action_t action); - -#ifdef __cplusplus -} -#endif diff --git a/tmk_core/common/action_code.h b/tmk_core/common/action_code.h deleted file mode 100644 index eb18c36ae8..0000000000 --- a/tmk_core/common/action_code.h +++ /dev/null @@ -1,308 +0,0 @@ -/* -Copyright 2013 Jun Wako - -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 . -*/ - -#pragma once - -/** \brief Action codes - * - * 16bit code: action_kind(4bit) + action_parameter(12bit) - * - * Key Actions(00xx) - * ----------------- - * ACT_MODS(000r): - * 000r|0000|0000 0000 No action code - * 000r|0000|0000 0001 Transparent code - * 000r|0000| keycode Key - * 000r|mods|0000 0000 Modifiers - * 000r|mods| keycode Modifiers+Key(Modified key) - * r: Left/Right flag(Left:0, Right:1) - * - * ACT_MODS_TAP(001r): - * 001r|mods|0000 0000 Modifiers with OneShot - * 001r|mods|0000 0001 Modifiers with tap toggle - * 001r|mods|0000 00xx (reserved) - * 001r|mods| keycode Modifiers with Tap Key(Dual role) - * - * Other Keys(01xx) - * ---------------- - * ACT_USAGE(0100): TODO: Not needed? - * 0100|00| usage(10) System control(0x80) - General Desktop page(0x01) - * 0100|01| usage(10) Consumer control(0x01) - Consumer page(0x0C) - * 0100|10| usage(10) (reserved) - * 0100|11| usage(10) (reserved) - * - * ACT_MOUSEKEY(0101): TODO: Merge these two actions to conserve space? - * 0101|xxxx| keycode Mouse key - * - * ACT_SWAP_HANDS(0110): - * 0110|xxxx| keycode Swap hands (keycode on tap, or options) - * - * 0111|xxxx xxxx xxxx (reserved) - * - * Layer Actions(10xx) - * ------------------- - * ACT_LAYER(1000): - * 1000|oo00|pppE BBBB Default Layer Bitwise operation - * oo: operation(00:AND, 01:OR, 10:XOR, 11:SET) - * ppp: 4-bit chunk part(0-7) - * EBBBB: bits and extra bit - * 1000|ooee|pppE BBBB Layer Bitwise Operation - * oo: operation(00:AND, 01:OR, 10:XOR, 11:SET) - * ppp: 4-bit chunk part(0-7) - * EBBBB: bits and extra bit - * ee: on event(01:press, 10:release, 11:both) - * - * ACT_LAYER_MODS(1001): - * 1001|LLLL| mods Layer with modifiers held - * - * ACT_LAYER_TAP(101x): - * 101E|LLLL| keycode On/Off with tap key (0x00-DF)[TAP] - * 101E|LLLL|1110 mods On/Off with modifiers (0xE0-EF)[NOT TAP] - * 101E|LLLL|1111 0000 Invert with tap toggle (0xF0) [TAP] - * 101E|LLLL|1111 0001 On/Off (0xF1) [NOT TAP] - * 101E|LLLL|1111 0010 Off/On (0xF2) [NOT TAP] - * 101E|LLLL|1111 0011 Set/Clear (0xF3) [NOT TAP] - * 101E|LLLL|1111 0100 One Shot Layer (0xF4) [TAP] - * 101E|LLLL|1111 xxxx Reserved (0xF5-FF) - * ELLLL: layer 0-31(E: extra bit for layer 16-31) - * - * Extensions(11xx) - * ---------------- - * ACT_MACRO(1100): - * 1100|opt | id(8) Macro play? - * 1100|1111| id(8) Macro record? - * - * 1101|xxxx xxxx xxxx (reserved) - * 1110|xxxx xxxx xxxx (reserved) - * - * ACT_FUNCTION(1111): - * 1111| address(12) Function? - * 1111|opt | id(8) Function? - */ -enum action_kind_id { - /* Key Actions */ - ACT_MODS = 0b0000, - ACT_LMODS = 0b0000, - ACT_RMODS = 0b0001, - ACT_MODS_TAP = 0b0010, - ACT_LMODS_TAP = 0b0010, - ACT_RMODS_TAP = 0b0011, - /* Other Keys */ - ACT_USAGE = 0b0100, - ACT_MOUSEKEY = 0b0101, - /* One-hand Support */ - ACT_SWAP_HANDS = 0b0110, - /* Layer Actions */ - ACT_LAYER = 0b1000, - ACT_LAYER_MODS = 0b1001, - ACT_LAYER_TAP = 0b1010, /* Layer 0-15 */ - ACT_LAYER_TAP_EXT = 0b1011, /* Layer 16-31 */ - /* Extensions */ - ACT_MACRO = 0b1100, - ACT_FUNCTION = 0b1111 -}; - -/** \brief Action Code Struct - * - * NOTE: - * In avr-gcc bit field seems to be assigned from LSB(bit0) to MSB(bit15). - * AVR looks like a little endian in avr-gcc. - * Not portable across compiler/endianness? - * - * Byte order and bit order of 0x1234: - * Big endian: Little endian: - * -------------------- -------------------- - * FEDC BA98 7654 3210 0123 4567 89AB CDEF - * 0001 0010 0011 0100 0010 1100 0100 1000 - * 0x12 0x34 0x34 0x12 - */ -typedef union { - uint16_t code; - struct action_kind { - uint16_t param : 12; - uint8_t id : 4; - } kind; - struct action_key { - uint8_t code : 8; - uint8_t mods : 4; - uint8_t kind : 4; - } key; - struct action_layer_bitop { - uint8_t bits : 4; - uint8_t xbit : 1; - uint8_t part : 3; - uint8_t on : 2; - uint8_t op : 2; - uint8_t kind : 4; - } layer_bitop; - struct action_layer_mods { - uint8_t mods : 8; - uint8_t layer : 4; - uint8_t kind : 4; - } layer_mods; - struct action_layer_tap { - uint8_t code : 8; - uint8_t val : 5; - uint8_t kind : 3; - } layer_tap; - struct action_usage { - uint16_t code : 10; - uint8_t page : 2; - uint8_t kind : 4; - } usage; - struct action_function { - uint8_t id : 8; - uint8_t opt : 4; - uint8_t kind : 4; - } func; - struct action_swap { - uint8_t code : 8; - uint8_t opt : 4; - uint8_t kind : 4; - } swap; -} action_t; - -/* action utility */ -#define ACTION_NO 0 -#define ACTION_TRANSPARENT 1 -#define ACTION(kind, param) ((kind) << 12 | (param)) - -/** \brief Key Actions - * - * Mod bits: 43210 - * bit 0 ||||+- Control - * bit 1 |||+-- Shift - * bit 2 ||+--- Alt - * bit 3 |+---- Gui - * bit 4 +----- LR flag(Left:0, Right:1) - */ -enum mods_bit { - MOD_LCTL = 0x01, - MOD_LSFT = 0x02, - MOD_LALT = 0x04, - MOD_LGUI = 0x08, - MOD_RCTL = 0x11, - MOD_RSFT = 0x12, - MOD_RALT = 0x14, - MOD_RGUI = 0x18, -}; -enum mods_codes { - MODS_ONESHOT = 0x00, - MODS_TAP_TOGGLE = 0x01, -}; -#define ACTION_KEY(key) ACTION(ACT_MODS, (key)) -#define ACTION_MODS(mods) ACTION(ACT_MODS, ((mods)&0x1f) << 8 | 0) -#define ACTION_MODS_KEY(mods, key) ACTION(ACT_MODS, ((mods)&0x1f) << 8 | (key)) -#define ACTION_MODS_TAP_KEY(mods, key) ACTION(ACT_MODS_TAP, ((mods)&0x1f) << 8 | (key)) -#define ACTION_MODS_ONESHOT(mods) ACTION(ACT_MODS_TAP, ((mods)&0x1f) << 8 | MODS_ONESHOT) -#define ACTION_MODS_TAP_TOGGLE(mods) ACTION(ACT_MODS_TAP, ((mods)&0x1f) << 8 | MODS_TAP_TOGGLE) - -/** \brief Other Keys - */ -enum usage_pages { PAGE_SYSTEM, PAGE_CONSUMER }; -#define ACTION_USAGE_SYSTEM(id) ACTION(ACT_USAGE, PAGE_SYSTEM << 10 | (id)) -#define ACTION_USAGE_CONSUMER(id) ACTION(ACT_USAGE, PAGE_CONSUMER << 10 | (id)) -#define ACTION_MOUSEKEY(key) ACTION(ACT_MOUSEKEY, key) - -/** \brief Layer Actions - */ -enum layer_param_on { - ON_PRESS = 1, - ON_RELEASE = 2, - ON_BOTH = 3, -}; - -/** \brief Layer Actions - */ -enum layer_param_bit_op { - OP_BIT_AND = 0, - OP_BIT_OR = 1, - OP_BIT_XOR = 2, - OP_BIT_SET = 3, -}; - -/** \brief Layer Actions - */ -enum layer_param_tap_op { - OP_TAP_TOGGLE = 0xF0, - OP_ON_OFF, - OP_OFF_ON, - OP_SET_CLEAR, - OP_ONESHOT, -}; -#define ACTION_LAYER_BITOP(op, part, bits, on) ACTION(ACT_LAYER, (op) << 10 | (on) << 8 | (part) << 5 | ((bits)&0x1f)) -#define ACTION_LAYER_TAP(layer, key) ACTION(ACT_LAYER_TAP, (layer) << 8 | (key)) -/* Default Layer */ -#define ACTION_DEFAULT_LAYER_SET(layer) ACTION_DEFAULT_LAYER_BIT_SET((layer) / 4, 1 << ((layer) % 4)) -/* Layer Operation */ -#define ACTION_LAYER_CLEAR(on) ACTION_LAYER_BIT_AND(0, 0, (on)) -#define ACTION_LAYER_MOMENTARY(layer) ACTION_LAYER_ON_OFF(layer) -#define ACTION_LAYER_TOGGLE(layer) ACTION_LAYER_INVERT(layer, ON_RELEASE) -#define ACTION_LAYER_INVERT(layer, on) ACTION_LAYER_BIT_XOR((layer) / 4, 1 << ((layer) % 4), (on)) -#define ACTION_LAYER_ON(layer, on) ACTION_LAYER_BIT_OR((layer) / 4, 1 << ((layer) % 4), (on)) -#define ACTION_LAYER_OFF(layer, on) ACTION_LAYER_BIT_AND((layer) / 4, ~(1 << ((layer) % 4)), (on)) -#define ACTION_LAYER_SET(layer, on) ACTION_LAYER_BIT_SET((layer) / 4, 1 << ((layer) % 4), (on)) -#define ACTION_LAYER_ON_OFF(layer) ACTION_LAYER_TAP((layer), OP_ON_OFF) -#define ACTION_LAYER_OFF_ON(layer) ACTION_LAYER_TAP((layer), OP_OFF_ON) -#define ACTION_LAYER_SET_CLEAR(layer) ACTION_LAYER_TAP((layer), OP_SET_CLEAR) -#define ACTION_LAYER_ONESHOT(layer) ACTION_LAYER_TAP((layer), OP_ONESHOT) -#define ACTION_LAYER_MODS(layer, mods) ACTION(ACT_LAYER_MODS, (layer) << 8 | (mods)) -/* With Tapping */ -#define ACTION_LAYER_TAP_KEY(layer, key) ACTION_LAYER_TAP((layer), (key)) -#define ACTION_LAYER_TAP_TOGGLE(layer) ACTION_LAYER_TAP((layer), OP_TAP_TOGGLE) -/* Bitwise Operation */ -#define ACTION_LAYER_BIT_AND(part, bits, on) ACTION_LAYER_BITOP(OP_BIT_AND, (part), (bits), (on)) -#define ACTION_LAYER_BIT_OR(part, bits, on) ACTION_LAYER_BITOP(OP_BIT_OR, (part), (bits), (on)) -#define ACTION_LAYER_BIT_XOR(part, bits, on) ACTION_LAYER_BITOP(OP_BIT_XOR, (part), (bits), (on)) -#define ACTION_LAYER_BIT_SET(part, bits, on) ACTION_LAYER_BITOP(OP_BIT_SET, (part), (bits), (on)) -/* Default Layer Bitwise Operation */ -#define ACTION_DEFAULT_LAYER_BIT_AND(part, bits) ACTION_LAYER_BITOP(OP_BIT_AND, (part), (bits), 0) -#define ACTION_DEFAULT_LAYER_BIT_OR(part, bits) ACTION_LAYER_BITOP(OP_BIT_OR, (part), (bits), 0) -#define ACTION_DEFAULT_LAYER_BIT_XOR(part, bits) ACTION_LAYER_BITOP(OP_BIT_XOR, (part), (bits), 0) -#define ACTION_DEFAULT_LAYER_BIT_SET(part, bits) ACTION_LAYER_BITOP(OP_BIT_SET, (part), (bits), 0) - -/* Macro */ -#define ACTION_MACRO(id) ACTION(ACT_MACRO, (id)) -#define ACTION_MACRO_TAP(id) ACTION(ACT_MACRO, FUNC_TAP << 8 | (id)) -#define ACTION_MACRO_OPT(id, opt) ACTION(ACT_MACRO, (opt) << 8 | (id)) -/* Function */ -enum function_opts { - FUNC_TAP = 0x8, /* indciates function is tappable */ -}; -#define ACTION_FUNCTION(id) ACTION(ACT_FUNCTION, (id)) -#define ACTION_FUNCTION_TAP(id) ACTION(ACT_FUNCTION, FUNC_TAP << 8 | (id)) -#define ACTION_FUNCTION_OPT(id, opt) ACTION(ACT_FUNCTION, (opt) << 8 | (id)) -/* OneHand Support */ -enum swap_hands_param_tap_op { - OP_SH_TOGGLE = 0xF0, - OP_SH_TAP_TOGGLE, - OP_SH_ON_OFF, - OP_SH_OFF_ON, - OP_SH_OFF, - OP_SH_ON, - OP_SH_ONESHOT, -}; - -#define ACTION_SWAP_HANDS() ACTION_SWAP_HANDS_ON_OFF() -#define ACTION_SWAP_HANDS_TOGGLE() ACTION(ACT_SWAP_HANDS, OP_SH_TOGGLE) -#define ACTION_SWAP_HANDS_TAP_TOGGLE() ACTION(ACT_SWAP_HANDS, OP_SH_TAP_TOGGLE) -#define ACTION_SWAP_HANDS_ONESHOT() ACTION(ACT_SWAP_HANDS, OP_SH_ONESHOT) -#define ACTION_SWAP_HANDS_TAP_KEY(key) ACTION(ACT_SWAP_HANDS, key) -#define ACTION_SWAP_HANDS_ON_OFF() ACTION(ACT_SWAP_HANDS, OP_SH_ON_OFF) -#define ACTION_SWAP_HANDS_OFF_ON() ACTION(ACT_SWAP_HANDS, OP_SH_OFF_ON) -#define ACTION_SWAP_HANDS_ON() ACTION(ACT_SWAP_HANDS, OP_SH_ON) -#define ACTION_SWAP_HANDS_OFF() ACTION(ACT_SWAP_HANDS, OP_SH_OFF) diff --git a/tmk_core/common/action_layer.c b/tmk_core/common/action_layer.c deleted file mode 100644 index ed1a4bd20d..0000000000 --- a/tmk_core/common/action_layer.c +++ /dev/null @@ -1,279 +0,0 @@ -#include -#include "keyboard.h" -#include "action.h" -#include "util.h" -#include "action_layer.h" - -#ifdef DEBUG_ACTION -# include "debug.h" -#else -# include "nodebug.h" -#endif - -/** \brief Default Layer State - */ -layer_state_t default_layer_state = 0; - -/** \brief Default Layer State Set At user Level - * - * Run user code on default layer state change - */ -__attribute__((weak)) layer_state_t default_layer_state_set_user(layer_state_t state) { return state; } - -/** \brief Default Layer State Set At Keyboard Level - * - * Run keyboard code on default layer state change - */ -__attribute__((weak)) layer_state_t default_layer_state_set_kb(layer_state_t state) { return default_layer_state_set_user(state); } - -/** \brief Default Layer State Set - * - * Static function to set the default layer state, prints debug info and clears keys - */ -static void default_layer_state_set(layer_state_t state) { - state = default_layer_state_set_kb(state); - debug("default_layer_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 - * - * Print out the hex value of the 32-bit default layer state, as well as the value of the highest bit. - */ -void default_layer_debug(void) { dprintf("%08lX(%u)", default_layer_state, get_highest_layer(default_layer_state)); } - -/** \brief Default Layer Set - * - * Sets the default layer state. - */ -void default_layer_set(layer_state_t state) { default_layer_state_set(state); } - -#ifndef NO_ACTION_LAYER -/** \brief Default Layer Or - * - * Turns on the default layer based on matching bits between specifed layer and existing layer state - */ -void default_layer_or(layer_state_t state) { default_layer_state_set(default_layer_state | state); } -/** \brief Default Layer And - * - * Turns on default layer based on matching enabled bits between specifed layer and existing layer state - */ -void default_layer_and(layer_state_t state) { default_layer_state_set(default_layer_state & state); } -/** \brief Default Layer Xor - * - * Turns on default layer based on non-matching bits between specifed layer and existing layer state - */ -void default_layer_xor(layer_state_t state) { default_layer_state_set(default_layer_state ^ state); } -#endif - -#ifndef NO_ACTION_LAYER -/** \brief Keymap Layer State - */ -layer_state_t layer_state = 0; - -/** \brief Layer state set user - * - * Runs user code on layer state change - */ -__attribute__((weak)) layer_state_t layer_state_set_user(layer_state_t state) { return state; } - -/** \brief Layer state set keyboard - * - * Runs keyboard code on layer state change - */ -__attribute__((weak)) layer_state_t layer_state_set_kb(layer_state_t state) { return layer_state_set_user(state); } - -/** \brief Layer state set - * - * Sets the layer to match the specifed state (a bitmask) - */ -void layer_state_set(layer_state_t state) { - state = layer_state_set_kb(state); - dprint("layer_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 - * - * Turn off all layers - */ -void layer_clear(void) { layer_state_set(0); } - -/** \brief Layer state is - * - * Return whether the given state is on (it might still be shadowed by a higher state, though) - */ -bool layer_state_is(uint8_t layer) { return layer_state_cmp(layer_state, layer); } - -/** \brief Layer state compare - * - * Used for comparing layers {mostly used for unit testing} - */ -bool layer_state_cmp(layer_state_t cmp_layer_state, uint8_t layer) { - if (!cmp_layer_state) { - return layer == 0; - } - return (cmp_layer_state & ((layer_state_t)1 << layer)) != 0; -} - -/** \brief Layer move - * - * Turns on the given layer and turn off all other layers - */ -void layer_move(uint8_t layer) { layer_state_set((layer_state_t)1 << layer); } - -/** \brief Layer on - * - * Turns on given layer - */ -void layer_on(uint8_t layer) { layer_state_set(layer_state | ((layer_state_t)1 << layer)); } - -/** \brief Layer off - * - * Turns off given layer - */ -void layer_off(uint8_t layer) { layer_state_set(layer_state & ~((layer_state_t)1 << layer)); } - -/** \brief Layer invert - * - * Toggle the given layer (set it if it's unset, or unset it if it's set) - */ -void layer_invert(uint8_t layer) { layer_state_set(layer_state ^ ((layer_state_t)1 << layer)); } - -/** \brief Layer or - * - * Turns on layers based on matching bits between specifed layer and existing layer state - */ -void layer_or(layer_state_t state) { layer_state_set(layer_state | state); } -/** \brief Layer and - * - * Turns on layers based on matching enabled bits between specifed layer and existing layer state - */ -void layer_and(layer_state_t state) { layer_state_set(layer_state & state); } -/** \brief Layer xor - * - * Turns on layers based on non-matching bits between specifed layer and existing layer state - */ -void layer_xor(layer_state_t state) { layer_state_set(layer_state ^ state); } - -/** \brief Layer debug printing - * - * Print out the hex value of the 32-bit layer state, as well as the value of the highest bit. - */ -void layer_debug(void) { dprintf("%08lX(%u)", layer_state, get_highest_layer(layer_state)); } -#endif - -#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE) -/** \brief source layer cache - */ - -uint8_t source_layers_cache[(MATRIX_ROWS * MATRIX_COLS + 7) / 8][MAX_LAYER_BITS] = {{0}}; - -/** \brief update source layers cache - * - * Updates the cached keys when changing layers - */ -void update_source_layers_cache(keypos_t key, uint8_t layer) { - const uint8_t key_number = key.col + (key.row * MATRIX_COLS); - const uint8_t storage_row = key_number / 8; - const uint8_t storage_bit = key_number % 8; - - for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) { - source_layers_cache[storage_row][bit_number] ^= (-((layer & (1U << bit_number)) != 0) ^ source_layers_cache[storage_row][bit_number]) & (1U << storage_bit); - } -} - -/** \brief read source layers cache - * - * reads the cached keys stored when the layer was changed - */ -uint8_t read_source_layers_cache(keypos_t key) { - const uint8_t key_number = key.col + (key.row * MATRIX_COLS); - const uint8_t storage_row = key_number / 8; - const uint8_t storage_bit = key_number % 8; - uint8_t layer = 0; - - for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) { - layer |= ((source_layers_cache[storage_row][bit_number] & (1U << storage_bit)) != 0) << bit_number; - } - - return layer; -} -#endif - -/** \brief Store or get action (FIXME: Needs better summary) - * - * Make sure the action triggered when the key is released is the same - * one as the one triggered on press. It's important for the mod keys - * when the layer is switched after the down event but before the up - * event as they may get stuck otherwise. - */ -action_t store_or_get_action(bool pressed, keypos_t key) { -#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE) - if (disable_action_cache) { - return layer_switch_get_action(key); - } - - uint8_t layer; - - if (pressed) { - layer = layer_switch_get_layer(key); - update_source_layers_cache(key, layer); - } else { - layer = read_source_layers_cache(key); - } - return action_for_key(layer, key); -#else - return layer_switch_get_action(key); -#endif -} - -/** \brief Layer switch get layer - * - * Gets the layer based on key info - */ -uint8_t layer_switch_get_layer(keypos_t key) { -#ifndef NO_ACTION_LAYER - action_t action; - action.code = ACTION_TRANSPARENT; - - layer_state_t layers = layer_state | default_layer_state; - /* check top layer first */ - for (int8_t i = MAX_LAYER - 1; i >= 0; i--) { - if (layers & ((layer_state_t)1 << i)) { - action = action_for_key(i, key); - if (action.code != ACTION_TRANSPARENT) { - return i; - } - } - } - /* fall back to layer 0 */ - return 0; -#else - return get_highest_layer(default_layer_state); -#endif -} - -/** \brief Layer switch get layer - * - * Gets action code based on key position - */ -action_t layer_switch_get_action(keypos_t key) { return action_for_key(layer_switch_get_layer(key), key); } diff --git a/tmk_core/common/action_layer.h b/tmk_core/common/action_layer.h deleted file mode 100644 index b87d096eed..0000000000 --- a/tmk_core/common/action_layer.h +++ /dev/null @@ -1,147 +0,0 @@ -/* -Copyright 2013 Jun Wako - -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 . -*/ - -#pragma once - -#include -#include "keyboard.h" -#include "action.h" - -#ifdef DYNAMIC_KEYMAP_ENABLE -# ifndef DYNAMIC_KEYMAP_LAYER_COUNT -# define DYNAMIC_KEYMAP_LAYER_COUNT 4 -# endif -# if DYNAMIC_KEYMAP_LAYER_COUNT <= 8 -# ifndef LAYER_STATE_8BIT -# define LAYER_STATE_8BIT -# endif -# elif DYNAMIC_KEYMAP_LAYER_COUNT <= 16 -# ifndef LAYER_STATE_16BIT -# define LAYER_STATE_16BIT -# endif -# else -# ifndef LAYER_STATE_32BIT -# define LAYER_STATE_32BIT -# endif -# endif -#endif - -#if !defined(LAYER_STATE_8BIT) && !defined(LAYER_STATE_16BIT) && !defined(LAYER_STATE_32BIT) -# define LAYER_STATE_32BIT -#endif - -#if defined(LAYER_STATE_8BIT) -typedef uint8_t layer_state_t; -# define MAX_LAYER_BITS 3 -# ifndef MAX_LAYER -# define MAX_LAYER 8 -# endif -# define get_highest_layer(state) biton(state) -#elif defined(LAYER_STATE_16BIT) -typedef uint16_t layer_state_t; -# define MAX_LAYER_BITS 4 -# ifndef MAX_LAYER -# define MAX_LAYER 16 -# endif -# define get_highest_layer(state) biton16(state) -#elif defined(LAYER_STATE_32BIT) -typedef uint32_t layer_state_t; -# define MAX_LAYER_BITS 5 -# ifndef MAX_LAYER -# define MAX_LAYER 32 -# endif -# define get_highest_layer(state) biton32(state) -#else -# error Layer Mask size not specified. HOW?! -#endif - -/* - * Default Layer - */ -extern layer_state_t default_layer_state; -void default_layer_debug(void); -void default_layer_set(layer_state_t state); - -__attribute__((weak)) layer_state_t default_layer_state_set_kb(layer_state_t state); -__attribute__((weak)) layer_state_t default_layer_state_set_user(layer_state_t state); - -#ifndef NO_ACTION_LAYER -/* bitwise operation */ -void default_layer_or(layer_state_t state); -void default_layer_and(layer_state_t state); -void default_layer_xor(layer_state_t state); -#else -# define default_layer_or(state) -# define default_layer_and(state) -# define default_layer_xor(state) -#endif - -/* - * Keymap Layer - */ -#ifndef NO_ACTION_LAYER -extern layer_state_t layer_state; - -void layer_state_set(layer_state_t state); -bool layer_state_is(uint8_t layer); -bool layer_state_cmp(layer_state_t layer1, uint8_t layer2); - -void layer_debug(void); -void layer_clear(void); -void layer_move(uint8_t layer); -void layer_on(uint8_t layer); -void layer_off(uint8_t layer); -void layer_invert(uint8_t layer); -/* bitwise operation */ -void layer_or(layer_state_t state); -void layer_and(layer_state_t state); -void layer_xor(layer_state_t state); -layer_state_t layer_state_set_user(layer_state_t state); -layer_state_t layer_state_set_kb(layer_state_t state); -#else -# define layer_state 0 - -# define layer_state_set(layer) -# define layer_state_is(layer) (layer == 0) -# define layer_state_cmp(state, layer) (state == 0 ? layer == 0 : (state & (layer_state_t)1 << layer) != 0) - -# define layer_debug() -# define layer_clear() -# define layer_move(layer) (void)layer -# define layer_on(layer) (void)layer -# define layer_off(layer) (void)layer -# define layer_invert(layer) (void)layer -# define layer_or(state) (void)state -# define layer_and(state) (void)state -# define layer_xor(state) (void)state -# define layer_state_set_kb(state) (void)state -# define layer_state_set_user(state) (void)state -#endif - -/* pressed actions cache */ -#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE) - -void update_source_layers_cache(keypos_t key, uint8_t layer); -uint8_t read_source_layers_cache(keypos_t key); -#endif -action_t store_or_get_action(bool pressed, keypos_t key); - -/* return the topmost non-transparent layer currently associated with key */ -uint8_t layer_switch_get_layer(keypos_t key); - -/* return action depending on current layer status */ -action_t layer_switch_get_action(keypos_t key); diff --git a/tmk_core/common/action_macro.c b/tmk_core/common/action_macro.c deleted file mode 100644 index 92228c0ba8..0000000000 --- a/tmk_core/common/action_macro.c +++ /dev/null @@ -1,93 +0,0 @@ -/* -Copyright 2013 Jun Wako - -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 . -*/ -#include "action.h" -#include "action_util.h" -#include "action_macro.h" -#include "wait.h" - -#ifdef DEBUG_ACTION -# include "debug.h" -#else -# include "nodebug.h" -#endif - -#ifndef NO_ACTION_MACRO - -# define MACRO_READ() (macro = MACRO_GET(macro_p++)) -/** \brief Action Macro Play - * - * FIXME: Needs doc - */ -void action_macro_play(const macro_t *macro_p) { - macro_t macro = END; - uint8_t interval = 0; - - if (!macro_p) return; - while (true) { - switch (MACRO_READ()) { - case KEY_DOWN: - MACRO_READ(); - dprintf("KEY_DOWN(%02X)\n", macro); - if (IS_MOD(macro)) { - add_macro_mods(MOD_BIT(macro)); - send_keyboard_report(); - } else { - register_code(macro); - } - break; - case KEY_UP: - MACRO_READ(); - dprintf("KEY_UP(%02X)\n", macro); - if (IS_MOD(macro)) { - del_macro_mods(MOD_BIT(macro)); - send_keyboard_report(); - } else { - unregister_code(macro); - } - break; - case WAIT: - MACRO_READ(); - dprintf("WAIT(%u)\n", macro); - { - uint8_t ms = macro; - while (ms--) wait_ms(1); - } - break; - case INTERVAL: - interval = MACRO_READ(); - dprintf("INTERVAL(%u)\n", interval); - break; - case 0x04 ... 0x73: - dprintf("DOWN(%02X)\n", macro); - register_code(macro); - break; - case 0x84 ... 0xF3: - dprintf("UP(%02X)\n", macro); - unregister_code(macro & 0x7F); - break; - case END: - default: - return; - } - // interval - { - uint8_t ms = interval; - while (ms--) wait_ms(1); - } - } -} -#endif diff --git a/tmk_core/common/action_macro.h b/tmk_core/common/action_macro.h deleted file mode 100644 index 685e2c6ffc..0000000000 --- a/tmk_core/common/action_macro.h +++ /dev/null @@ -1,123 +0,0 @@ -/* -Copyright 2013 Jun Wako - -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 . -*/ - -#pragma once - -#include -#include "progmem.h" - -typedef uint8_t macro_t; - -#define MACRO_NONE (macro_t *)0 -#define MACRO(...) \ - ({ \ - static const macro_t __m[] PROGMEM = {__VA_ARGS__}; \ - &__m[0]; \ - }) -#define MACRO_GET(p) pgm_read_byte(p) - -// Sends press when the macro key is pressed, release when release, or tap_macro when the key has been tapped -#define MACRO_TAP_HOLD(record, press, release, tap_macro) (((record)->event.pressed) ? (((record)->tap.count <= 0 || (record)->tap.interrupted) ? (press) : MACRO_NONE) : (((record)->tap.count > 0 && !((record)->tap.interrupted)) ? (tap_macro) : (release))) - -// Holds down the modifier mod when the macro key is held, or sends macro instead when tapped -#define MACRO_TAP_HOLD_MOD(record, macro, mod) MACRO_TAP_HOLD(record, (MACRO(D(mod), END)), MACRO(U(mod), END), macro) - -// Holds down the modifier mod when the macro key is held, or pressed a shifted key when tapped (eg: shift+3 for #) -#define MACRO_TAP_SHFT_KEY_HOLD_MOD(record, key, mod) MACRO_TAP_HOLD_MOD(record, (MACRO(I(10), D(LSFT), T(key), U(LSFT), END)), mod) - -// Momentary switch layer when held, sends macro if tapped -#define MACRO_TAP_HOLD_LAYER(record, macro, layer) \ - (((record)->event.pressed) ? (((record)->tap.count <= 0 || (record)->tap.interrupted) ? ({ \ - layer_on((layer)); \ - MACRO_NONE; \ - }) \ - : MACRO_NONE) \ - : (((record)->tap.count > 0 && !((record)->tap.interrupted)) ? (macro) : ({ \ - layer_off((layer)); \ - MACRO_NONE; \ - }))) - -// Momentary switch layer when held, presses a shifted key when tapped (eg: shift+3 for #) -#define MACRO_TAP_SHFT_KEY_HOLD_LAYER(record, key, layer) MACRO_TAP_HOLD_LAYER(record, MACRO(I(10), D(LSFT), T(key), U(LSFT), END), layer) - -#ifndef NO_ACTION_MACRO -void action_macro_play(const macro_t *macro_p); -#else -# define action_macro_play(macro) -#endif - -/* Macro commands - * code(0x04-73) // key down(1byte) - * code(0x04-73) | 0x80 // key up(1byte) - * { KEY_DOWN, code(0x04-0xff) } // key down(2bytes) - * { KEY_UP, code(0x04-0xff) } // key up(2bytes) - * WAIT // wait milli-seconds - * INTERVAL // set interval between macro commands - * END // stop macro execution - * - * Ideas(Not implemented): - * modifiers - * system usage - * consumer usage - * unicode usage - * function call - * conditionals - * loop - */ -enum macro_command_id { - /* 0x00 - 0x03 */ - END = 0x00, - KEY_DOWN, - KEY_UP, - - /* 0x04 - 0x73 (reserved for keycode down) */ - - /* 0x74 - 0x83 */ - WAIT = 0x74, - INTERVAL, - - /* 0x84 - 0xf3 (reserved for keycode up) */ - - /* 0xf4 - 0xff */ -}; - -/* TODO: keycode:0x04-0x73 can be handled by 1byte command else 2bytes are needed - * if keycode between 0x04 and 0x73 - * keycode / (keycode|0x80) - * else - * {KEY_DOWN, keycode} / {KEY_UP, keycode} - */ -#define DOWN(key) KEY_DOWN, (key) -#define UP(key) KEY_UP, (key) -#define TYPE(key) DOWN(key), UP(key) -#define WAIT(ms) WAIT, (ms) -#define INTERVAL(ms) INTERVAL, (ms) - -/* key down */ -#define D(key) DOWN(KC_##key) -/* key up */ -#define U(key) UP(KC_##key) -/* key type */ -#define T(key) TYPE(KC_##key) -/* wait */ -#define W(ms) WAIT(ms) -/* interval */ -#define I(ms) INTERVAL(ms) - -/* for backward comaptibility */ -#define MD(key) DOWN(KC_##key) -#define MU(key) UP(KC_##key) diff --git a/tmk_core/common/action_tapping.c b/tmk_core/common/action_tapping.c deleted file mode 100644 index 36839f9faf..0000000000 --- a/tmk_core/common/action_tapping.c +++ /dev/null @@ -1,456 +0,0 @@ -#include -#include -#include "action.h" -#include "action_layer.h" -#include "action_tapping.h" -#include "keycode.h" -#include "timer.h" - -#ifdef DEBUG_ACTION -# include "debug.h" -#else -# include "nodebug.h" -#endif - -#ifndef NO_ACTION_TAPPING - -# define IS_TAPPING() !IS_NOEVENT(tapping_key.event) -# define IS_TAPPING_PRESSED() (IS_TAPPING() && tapping_key.event.pressed) -# define IS_TAPPING_RELEASED() (IS_TAPPING() && !tapping_key.event.pressed) -# define IS_TAPPING_KEY(k) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (k))) -#ifndef COMBO_ENABLE -# define IS_TAPPING_RECORD(r) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (r->event.key))) -#else -# define IS_TAPPING_RECORD(r) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (r->event.key)) && tapping_key.keycode == r->keycode) -#endif - -__attribute__((weak)) uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) { return TAPPING_TERM; } - -# ifdef TAPPING_TERM_PER_KEY -# define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < get_tapping_term(get_record_keycode(&tapping_key, false), &tapping_key)) -# else -# define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < TAPPING_TERM) -# endif - -# ifdef TAPPING_FORCE_HOLD_PER_KEY -__attribute__((weak)) bool get_tapping_force_hold(uint16_t keycode, keyrecord_t *record) { return false; } -# endif - -# ifdef PERMISSIVE_HOLD_PER_KEY -__attribute__((weak)) bool get_permissive_hold(uint16_t keycode, keyrecord_t *record) { return false; } -# endif - -# ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY -__attribute__((weak)) bool get_hold_on_other_key_press(uint16_t keycode, keyrecord_t *record) { return false; } -# endif - -static keyrecord_t tapping_key = {}; -static keyrecord_t waiting_buffer[WAITING_BUFFER_SIZE] = {}; -static uint8_t waiting_buffer_head = 0; -static uint8_t waiting_buffer_tail = 0; - -static bool process_tapping(keyrecord_t *record); -static bool waiting_buffer_enq(keyrecord_t record); -static void waiting_buffer_clear(void); -static bool waiting_buffer_typed(keyevent_t event); -static bool waiting_buffer_has_anykey_pressed(void); -static void waiting_buffer_scan_tap(void); -static void debug_tapping_key(void); -static void debug_waiting_buffer(void); - -/** \brief Action Tapping Process - * - * FIXME: Needs doc - */ -void action_tapping_process(keyrecord_t record) { - if (process_tapping(&record)) { - if (!IS_NOEVENT(record.event)) { - debug("processed: "); - debug_record(record); - debug("\n"); - } - } else { - if (!waiting_buffer_enq(record)) { - // clear all in case of overflow. - debug("OVERFLOW: CLEAR ALL STATES\n"); - clear_keyboard(); - waiting_buffer_clear(); - tapping_key = (keyrecord_t){}; - } - } - - // process waiting_buffer - if (!IS_NOEVENT(record.event) && waiting_buffer_head != waiting_buffer_tail) { - debug("---- action_exec: process waiting_buffer -----\n"); - } - for (; waiting_buffer_tail != waiting_buffer_head; waiting_buffer_tail = (waiting_buffer_tail + 1) % WAITING_BUFFER_SIZE) { - if (process_tapping(&waiting_buffer[waiting_buffer_tail])) { - debug("processed: waiting_buffer["); - debug_dec(waiting_buffer_tail); - debug("] = "); - debug_record(waiting_buffer[waiting_buffer_tail]); - debug("\n\n"); - } else { - break; - } - } - if (!IS_NOEVENT(record.event)) { - debug("\n"); - } -} - -/** \brief Tapping - * - * Rule: Tap key is typed(pressed and released) within TAPPING_TERM. - * (without interfering by typing other key) - */ -/* return true when key event is processed or consumed. */ -bool process_tapping(keyrecord_t *keyp) { - keyevent_t event = keyp->event; - - // if tapping - if (IS_TAPPING_PRESSED()) { - if (WITHIN_TAPPING_TERM(event)) { - if (tapping_key.tap.count == 0) { - if (IS_TAPPING_RECORD(keyp) && !event.pressed) { - // first tap! - debug("Tapping: First tap(0->1).\n"); - tapping_key.tap.count = 1; - debug_tapping_key(); - process_record(&tapping_key); - - // copy tapping state - keyp->tap = tapping_key.tap; - // enqueue - return false; - } - /* Process a key typed within TAPPING_TERM - * This can register the key before settlement of tapping, - * useful for long TAPPING_TERM but may prevent fast typing. - */ -# if defined(TAPPING_TERM_PER_KEY) || (TAPPING_TERM >= 500) || defined(PERMISSIVE_HOLD) || defined(PERMISSIVE_HOLD_PER_KEY) - else if ((( -# ifdef TAPPING_TERM_PER_KEY - get_tapping_term(get_record_keycode(&tapping_key, false), keyp) -# else - TAPPING_TERM -# endif - >= 500) - -# ifdef PERMISSIVE_HOLD_PER_KEY - || get_permissive_hold(get_record_keycode(&tapping_key, false), keyp) -# elif defined(PERMISSIVE_HOLD) - || true -# endif - ) && - IS_RELEASED(event) && waiting_buffer_typed(event)) { - debug("Tapping: End. No tap. Interfered by typing key\n"); - process_record(&tapping_key); - tapping_key = (keyrecord_t){}; - debug_tapping_key(); - // enqueue - return false; - } -# endif - /* Process release event of a key pressed before tapping starts - * Without this unexpected repeating will occur with having fast repeating setting - * https://github.com/tmk/tmk_keyboard/issues/60 - */ - else if (IS_RELEASED(event) && !waiting_buffer_typed(event)) { - // Modifier should be retained till end of this tapping. - action_t action = layer_switch_get_action(event.key); - switch (action.kind.id) { - case ACT_LMODS: - case ACT_RMODS: - if (action.key.mods && !action.key.code) return false; - if (IS_MOD(action.key.code)) return false; - break; - case ACT_LMODS_TAP: - case ACT_RMODS_TAP: - if (action.key.mods && keyp->tap.count == 0) return false; - if (IS_MOD(action.key.code)) return false; - break; - } - // Release of key should be process immediately. - debug("Tapping: release event of a key pressed before tapping\n"); - process_record(keyp); - return true; - } else { - // set interrupted flag when other key preesed during tapping - if (event.pressed) { - tapping_key.tap.interrupted = true; -# if defined(HOLD_ON_OTHER_KEY_PRESS) || defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY) -# if defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY) - if (get_hold_on_other_key_press(get_record_keycode(&tapping_key, false), keyp)) -# endif - { - debug("Tapping: End. No tap. Interfered by pressed key\n"); - process_record(&tapping_key); - tapping_key = (keyrecord_t){}; - debug_tapping_key(); - // enqueue - return false; - } -# endif - } - // enqueue - return false; - } - } - // tap_count > 0 - else { - if (IS_TAPPING_RECORD(keyp) && !event.pressed) { - debug("Tapping: Tap release("); - debug_dec(tapping_key.tap.count); - debug(")\n"); - keyp->tap = tapping_key.tap; - process_record(keyp); - tapping_key = *keyp; - debug_tapping_key(); - return true; - } else if (is_tap_record(keyp) && event.pressed) { - if (tapping_key.tap.count > 1) { - debug("Tapping: Start new tap with releasing last tap(>1).\n"); - // unregister key - process_record(&(keyrecord_t){.tap = tapping_key.tap, .event.key = tapping_key.event.key, .event.time = event.time, .event.pressed = false, -#ifdef COMBO_ENABLE - .keycode = tapping_key.keycode, -#endif - }); - } else { - debug("Tapping: Start while last tap(1).\n"); - } - tapping_key = *keyp; - waiting_buffer_scan_tap(); - debug_tapping_key(); - return true; - } else { - if (!IS_NOEVENT(event)) { - debug("Tapping: key event while last tap(>0).\n"); - } - process_record(keyp); - return true; - } - } - } - // after TAPPING_TERM - else { - if (tapping_key.tap.count == 0) { - debug("Tapping: End. Timeout. Not tap(0): "); - debug_event(event); - debug("\n"); - process_record(&tapping_key); - tapping_key = (keyrecord_t){}; - debug_tapping_key(); - return false; - } else { - if (IS_TAPPING_RECORD(keyp) && !event.pressed) { - debug("Tapping: End. last timeout tap release(>0)."); - keyp->tap = tapping_key.tap; - process_record(keyp); - tapping_key = (keyrecord_t){}; - return true; - } else if (is_tap_record(keyp) && event.pressed) { - if (tapping_key.tap.count > 1) { - debug("Tapping: Start new tap with releasing last timeout tap(>1).\n"); - // unregister key - process_record(&(keyrecord_t){.tap = tapping_key.tap, .event.key = tapping_key.event.key, .event.time = event.time, .event.pressed = false, -#ifdef COMBO_ENABLE - .keycode = tapping_key.keycode, -#endif - }); - } else { - debug("Tapping: Start while last timeout tap(1).\n"); - } - tapping_key = *keyp; - waiting_buffer_scan_tap(); - debug_tapping_key(); - return true; - } else { - if (!IS_NOEVENT(event)) { - debug("Tapping: key event while last timeout tap(>0).\n"); - } - process_record(keyp); - return true; - } - } - } - } else if (IS_TAPPING_RELEASED()) { - if (WITHIN_TAPPING_TERM(event)) { - if (event.pressed) { - if (IS_TAPPING_RECORD(keyp)) { -//# ifndef TAPPING_FORCE_HOLD -# if !defined(TAPPING_FORCE_HOLD) || defined(TAPPING_FORCE_HOLD_PER_KEY) - if ( -# ifdef TAPPING_FORCE_HOLD_PER_KEY - !get_tapping_force_hold(get_record_keycode(&tapping_key, false), keyp) && -# endif - !tapping_key.tap.interrupted && tapping_key.tap.count > 0) { - // sequential tap. - keyp->tap = tapping_key.tap; - if (keyp->tap.count < 15) keyp->tap.count += 1; - debug("Tapping: Tap press("); - debug_dec(keyp->tap.count); - debug(")\n"); - process_record(keyp); - tapping_key = *keyp; - debug_tapping_key(); - return true; - } -# endif - // FIX: start new tap again - tapping_key = *keyp; - return true; - } else if (is_tap_record(keyp)) { - // Sequential tap can be interfered with other tap key. - debug("Tapping: Start with interfering other tap.\n"); - tapping_key = *keyp; - waiting_buffer_scan_tap(); - debug_tapping_key(); - return true; - } else { - // should none in buffer - // FIX: interrupted when other key is pressed - tapping_key.tap.interrupted = true; - process_record(keyp); - return true; - } - } else { - if (!IS_NOEVENT(event)) debug("Tapping: other key just after tap.\n"); - process_record(keyp); - return true; - } - } else { - // FIX: process_action here? - // timeout. no sequential tap. - debug("Tapping: End(Timeout after releasing last tap): "); - debug_event(event); - debug("\n"); - tapping_key = (keyrecord_t){}; - debug_tapping_key(); - return false; - } - } - // not tapping state - else { - if (event.pressed && is_tap_record(keyp)) { - debug("Tapping: Start(Press tap key).\n"); - tapping_key = *keyp; - process_record_tap_hint(&tapping_key); - waiting_buffer_scan_tap(); - debug_tapping_key(); - return true; - } else { - process_record(keyp); - return true; - } - } -} - -/** \brief Waiting buffer enq - * - * FIXME: Needs docs - */ -bool waiting_buffer_enq(keyrecord_t record) { - if (IS_NOEVENT(record.event)) { - return true; - } - - if ((waiting_buffer_head + 1) % WAITING_BUFFER_SIZE == waiting_buffer_tail) { - debug("waiting_buffer_enq: Over flow.\n"); - return false; - } - - waiting_buffer[waiting_buffer_head] = record; - waiting_buffer_head = (waiting_buffer_head + 1) % WAITING_BUFFER_SIZE; - - debug("waiting_buffer_enq: "); - debug_waiting_buffer(); - return true; -} - -/** \brief Waiting buffer clear - * - * FIXME: Needs docs - */ -void waiting_buffer_clear(void) { - waiting_buffer_head = 0; - waiting_buffer_tail = 0; -} - -/** \brief Waiting buffer typed - * - * FIXME: Needs docs - */ -bool waiting_buffer_typed(keyevent_t event) { - for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) { - if (KEYEQ(event.key, waiting_buffer[i].event.key) && event.pressed != waiting_buffer[i].event.pressed) { - return true; - } - } - return false; -} - -/** \brief Waiting buffer has anykey pressed - * - * FIXME: Needs docs - */ -__attribute__((unused)) bool waiting_buffer_has_anykey_pressed(void) { - for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) { - if (waiting_buffer[i].event.pressed) return true; - } - return false; -} - -/** \brief Scan buffer for tapping - * - * FIXME: Needs docs - */ -void waiting_buffer_scan_tap(void) { - // tapping already is settled - if (tapping_key.tap.count > 0) return; - // invalid state: tapping_key released && tap.count == 0 - if (!tapping_key.event.pressed) return; - - for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) { - if (IS_TAPPING_KEY(waiting_buffer[i].event.key) && !waiting_buffer[i].event.pressed && WITHIN_TAPPING_TERM(waiting_buffer[i].event)) { - tapping_key.tap.count = 1; - waiting_buffer[i].tap.count = 1; - process_record(&tapping_key); - - debug("waiting_buffer_scan_tap: found at ["); - debug_dec(i); - debug("]\n"); - debug_waiting_buffer(); - return; - } - } -} - -/** \brief Tapping key debug print - * - * FIXME: Needs docs - */ -static void debug_tapping_key(void) { - debug("TAPPING_KEY="); - debug_record(tapping_key); - debug("\n"); -} - -/** \brief Waiting buffer debug print - * - * FIXME: Needs docs - */ -static void debug_waiting_buffer(void) { - debug("{ "); - for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) { - debug("["); - debug_dec(i); - debug("]="); - debug_record(waiting_buffer[i]); - debug(" "); - } - debug("}\n"); -} - -#endif diff --git a/tmk_core/common/action_tapping.h b/tmk_core/common/action_tapping.h deleted file mode 100644 index 7de8049c7f..0000000000 --- a/tmk_core/common/action_tapping.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -Copyright 2013 Jun Wako - -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 . -*/ - -#pragma once - -/* period of tapping(ms) */ -#ifndef TAPPING_TERM -# define TAPPING_TERM 200 -#endif - -/* tap count needed for toggling a feature */ -#ifndef TAPPING_TOGGLE -# define TAPPING_TOGGLE 5 -#endif - -#define WAITING_BUFFER_SIZE 8 - -#ifndef NO_ACTION_TAPPING -uint16_t get_record_keycode(keyrecord_t *record, bool update_layer_cache); -uint16_t get_event_keycode(keyevent_t event, bool update_layer_cache); -void action_tapping_process(keyrecord_t record); - -uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record); -bool get_permissive_hold(uint16_t keycode, keyrecord_t *record); -bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record); -bool get_tapping_force_hold(uint16_t keycode, keyrecord_t *record); -bool get_retro_tapping(uint16_t keycode, keyrecord_t *record); -#endif diff --git a/tmk_core/common/action_util.c b/tmk_core/common/action_util.c deleted file mode 100644 index 2b3c00cba0..0000000000 --- a/tmk_core/common/action_util.c +++ /dev/null @@ -1,455 +0,0 @@ -/* -Copyright 2013 Jun Wako - -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 . -*/ -#include "host.h" -#include "report.h" -#include "debug.h" -#include "action_util.h" -#include "action_layer.h" -#include "timer.h" -#include "keycode_config.h" - -extern keymap_config_t keymap_config; - -static uint8_t real_mods = 0; -static uint8_t weak_mods = 0; -static uint8_t macro_mods = 0; -#ifdef KEY_OVERRIDE_ENABLE -static uint8_t weak_override_mods = 0; -static uint8_t suppressed_mods = 0; -#endif - -#ifdef USB_6KRO_ENABLE -# define RO_ADD(a, b) ((a + b) % KEYBOARD_REPORT_KEYS) -# define RO_SUB(a, b) ((a - b + KEYBOARD_REPORT_KEYS) % KEYBOARD_REPORT_KEYS) -# define RO_INC(a) RO_ADD(a, 1) -# define RO_DEC(a) RO_SUB(a, 1) -static int8_t cb_head = 0; -static int8_t cb_tail = 0; -static int8_t cb_count = 0; -#endif - -// TODO: pointer variable is not needed -// report_keyboard_t keyboard_report = {}; -report_keyboard_t *keyboard_report = &(report_keyboard_t){}; - -extern inline void add_key(uint8_t key); -extern inline void del_key(uint8_t key); -extern inline void clear_keys(void); - -#ifndef NO_ACTION_ONESHOT -static uint8_t oneshot_mods = 0; -static uint8_t oneshot_locked_mods = 0; -uint8_t get_oneshot_locked_mods(void) { return oneshot_locked_mods; } -void set_oneshot_locked_mods(uint8_t mods) { - if (mods != oneshot_locked_mods) { - oneshot_locked_mods = mods; - oneshot_locked_mods_changed_kb(oneshot_locked_mods); - } -} -void clear_oneshot_locked_mods(void) { - if (oneshot_locked_mods) { - oneshot_locked_mods = 0; - oneshot_locked_mods_changed_kb(oneshot_locked_mods); - } -} -# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) -static uint16_t oneshot_time = 0; -bool has_oneshot_mods_timed_out(void) { return TIMER_DIFF_16(timer_read(), oneshot_time) >= ONESHOT_TIMEOUT; } -# else -bool has_oneshot_mods_timed_out(void) { return false; } -# endif -#endif - -/* oneshot layer */ -#ifndef NO_ACTION_ONESHOT -/** \brief oneshot_layer_data bits - * LLLL LSSS - * where: - * L => are layer bits - * S => oneshot state bits - */ -static int8_t oneshot_layer_data = 0; - -inline uint8_t get_oneshot_layer(void) { return oneshot_layer_data >> 3; } -inline uint8_t get_oneshot_layer_state(void) { return oneshot_layer_data & 0b111; } - -# ifdef SWAP_HANDS_ENABLE -enum { - SHO_OFF, - SHO_ACTIVE, // Swap hands button was pressed, and we didn't send any swapped keys yet - SHO_PRESSED, // Swap hands button is currently pressed - SHO_USED, // Swap hands button is still pressed, and we already sent swapped keys -} swap_hands_oneshot = SHO_OFF; -# endif - -# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) -static uint16_t oneshot_layer_time = 0; -inline bool has_oneshot_layer_timed_out() { return TIMER_DIFF_16(timer_read(), oneshot_layer_time) >= ONESHOT_TIMEOUT && !(get_oneshot_layer_state() & ONESHOT_TOGGLED); } -# ifdef SWAP_HANDS_ENABLE -static uint16_t oneshot_swaphands_time = 0; -inline bool has_oneshot_swaphands_timed_out() { return TIMER_DIFF_16(timer_read(), oneshot_swaphands_time) >= ONESHOT_TIMEOUT && (swap_hands_oneshot == SHO_ACTIVE); } -# endif -# endif - -# ifdef SWAP_HANDS_ENABLE - -void set_oneshot_swaphands(void) { - swap_hands_oneshot = SHO_PRESSED; - swap_hands = true; -# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) - oneshot_swaphands_time = timer_read(); - if (oneshot_layer_time != 0) { - oneshot_layer_time = oneshot_swaphands_time; - } -# endif -} - -void release_oneshot_swaphands(void) { - if (swap_hands_oneshot == SHO_PRESSED) { - swap_hands_oneshot = SHO_ACTIVE; - } - if (swap_hands_oneshot == SHO_USED) { - clear_oneshot_swaphands(); - } -} - -void use_oneshot_swaphands(void) { - if (swap_hands_oneshot == SHO_PRESSED) { - swap_hands_oneshot = SHO_USED; - } - if (swap_hands_oneshot == SHO_ACTIVE) { - clear_oneshot_swaphands(); - } -} - -void clear_oneshot_swaphands(void) { - swap_hands_oneshot = SHO_OFF; - swap_hands = false; -# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) - oneshot_swaphands_time = 0; -# endif -} - -# endif - -/** \brief Set oneshot layer - * - * FIXME: needs doc - */ -void set_oneshot_layer(uint8_t layer, uint8_t state) { - if (!keymap_config.oneshot_disable) { - oneshot_layer_data = layer << 3 | state; - layer_on(layer); -# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) - oneshot_layer_time = timer_read(); -# endif - oneshot_layer_changed_kb(get_oneshot_layer()); - } else { - layer_on(layer); - } -} -/** \brief Reset oneshot layer - * - * FIXME: needs doc - */ -void reset_oneshot_layer(void) { - oneshot_layer_data = 0; -# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) - oneshot_layer_time = 0; -# endif - oneshot_layer_changed_kb(get_oneshot_layer()); -} -/** \brief Clear oneshot layer - * - * FIXME: needs doc - */ -void clear_oneshot_layer_state(oneshot_fullfillment_t state) { - uint8_t start_state = oneshot_layer_data; - oneshot_layer_data &= ~state; - if ((!get_oneshot_layer_state() && start_state != oneshot_layer_data) || keymap_config.oneshot_disable) { - layer_off(get_oneshot_layer()); - reset_oneshot_layer(); - } -} -/** \brief Is oneshot layer active - * - * FIXME: needs doc - */ -bool is_oneshot_layer_active(void) { return get_oneshot_layer_state(); } - -/** \brief set oneshot - * - * FIXME: needs doc - */ -void oneshot_set(bool active) { - if (keymap_config.oneshot_disable != active) { - keymap_config.oneshot_disable = active; - eeconfig_update_keymap(keymap_config.raw); - dprintf("Oneshot: active: %d\n", active); - } -} - -/** \brief toggle oneshot - * - * FIXME: needs doc - */ -void oneshot_toggle(void) { oneshot_set(!keymap_config.oneshot_disable); } - -/** \brief enable oneshot - * - * FIXME: needs doc - */ -void oneshot_enable(void) { oneshot_set(true); } - -/** \brief disable oneshot - * - * FIXME: needs doc - */ -void oneshot_disable(void) { oneshot_set(false); } - -bool is_oneshot_enabled(void) { return keymap_config.oneshot_disable; } - -#endif - -/** \brief Send keyboard report - * - * FIXME: needs doc - */ -void send_keyboard_report(void) { - keyboard_report->mods = real_mods; - keyboard_report->mods |= weak_mods; - keyboard_report->mods |= macro_mods; - -#ifndef NO_ACTION_ONESHOT - if (oneshot_mods) { -# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) - if (has_oneshot_mods_timed_out()) { - dprintf("Oneshot: timeout\n"); - clear_oneshot_mods(); - } -# endif - keyboard_report->mods |= oneshot_mods; - if (has_anykey(keyboard_report)) { - clear_oneshot_mods(); - } - } - -#endif - -#ifdef KEY_OVERRIDE_ENABLE - // These need to be last to be able to properly control key overrides - keyboard_report->mods &= ~suppressed_mods; - keyboard_report->mods |= weak_override_mods; -#endif - - host_keyboard_send(keyboard_report); -} - -/** \brief Get mods - * - * FIXME: needs doc - */ -uint8_t get_mods(void) { return real_mods; } -/** \brief add mods - * - * FIXME: needs doc - */ -void add_mods(uint8_t mods) { real_mods |= mods; } -/** \brief del mods - * - * FIXME: needs doc - */ -void del_mods(uint8_t mods) { real_mods &= ~mods; } -/** \brief set mods - * - * FIXME: needs doc - */ -void set_mods(uint8_t mods) { real_mods = mods; } -/** \brief clear mods - * - * FIXME: needs doc - */ -void clear_mods(void) { real_mods = 0; } - -/** \brief get weak mods - * - * FIXME: needs doc - */ -uint8_t get_weak_mods(void) { return weak_mods; } -/** \brief add weak mods - * - * FIXME: needs doc - */ -void add_weak_mods(uint8_t mods) { weak_mods |= mods; } -/** \brief del weak mods - * - * FIXME: needs doc - */ -void del_weak_mods(uint8_t mods) { weak_mods &= ~mods; } -/** \brief set weak mods - * - * FIXME: needs doc - */ -void set_weak_mods(uint8_t mods) { weak_mods = mods; } -/** \brief clear weak mods - * - * FIXME: needs doc - */ -void clear_weak_mods(void) { weak_mods = 0; } - -#ifdef KEY_OVERRIDE_ENABLE -/** \brief set weak mods used by key overrides. DO not call this manually - */ -void set_weak_override_mods(uint8_t mods) { weak_override_mods = mods; } -/** \brief clear weak mods used by key overrides. DO not call this manually - */ -void clear_weak_override_mods(void) { weak_override_mods = 0; } - -/** \brief set suppressed mods used by key overrides. DO not call this manually - */ -void set_suppressed_override_mods(uint8_t mods) { suppressed_mods = mods; } -/** \brief clear suppressed mods used by key overrides. DO not call this manually - */ -void clear_suppressed_override_mods(void) { suppressed_mods = 0; } -#endif - -/* macro modifier */ -/** \brief get macro mods - * - * FIXME: needs doc - */ -uint8_t get_macro_mods(void) { return macro_mods; } -/** \brief add macro mods - * - * FIXME: needs doc - */ -void add_macro_mods(uint8_t mods) { macro_mods |= mods; } -/** \brief del macro mods - * - * FIXME: needs doc - */ -void del_macro_mods(uint8_t mods) { macro_mods &= ~mods; } -/** \brief set macro mods - * - * FIXME: needs doc - */ -void set_macro_mods(uint8_t mods) { macro_mods = mods; } -/** \brief clear macro mods - * - * FIXME: needs doc - */ -void clear_macro_mods(void) { macro_mods = 0; } - -#ifndef NO_ACTION_ONESHOT -/** \brief get oneshot mods - * - * FIXME: needs doc - */ -uint8_t get_oneshot_mods(void) { return oneshot_mods; } - -void add_oneshot_mods(uint8_t mods) { - if ((oneshot_mods & mods) != mods) { -# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) - oneshot_time = timer_read(); -# endif - oneshot_mods |= mods; - oneshot_mods_changed_kb(mods); - } -} - -void del_oneshot_mods(uint8_t mods) { - if (oneshot_mods & mods) { - oneshot_mods &= ~mods; -# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) - oneshot_time = oneshot_mods ? timer_read() : 0; -# endif - oneshot_mods_changed_kb(oneshot_mods); - } -} - -/** \brief set oneshot mods - * - * FIXME: needs doc - */ -void set_oneshot_mods(uint8_t mods) { - if (!keymap_config.oneshot_disable) { - if (oneshot_mods != mods) { -# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) - oneshot_time = timer_read(); -# endif - oneshot_mods = mods; - oneshot_mods_changed_kb(mods); - } - } -} - -/** \brief clear oneshot mods - * - * FIXME: needs doc - */ -void clear_oneshot_mods(void) { - if (oneshot_mods) { - oneshot_mods = 0; -# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) - oneshot_time = 0; -# endif - oneshot_mods_changed_kb(oneshot_mods); - } -} -#endif - -/** \brief Called when the one shot modifiers have been changed. - * - * \param mods Contains the active modifiers active after the change. - */ -__attribute__((weak)) void oneshot_locked_mods_changed_user(uint8_t mods) {} - -/** \brief Called when the locked one shot modifiers have been changed. - * - * \param mods Contains the active modifiers active after the change. - */ -__attribute__((weak)) void oneshot_locked_mods_changed_kb(uint8_t mods) { oneshot_locked_mods_changed_user(mods); } - -/** \brief Called when the one shot modifiers have been changed. - * - * \param mods Contains the active modifiers active after the change. - */ -__attribute__((weak)) void oneshot_mods_changed_user(uint8_t mods) {} - -/** \brief Called when the one shot modifiers have been changed. - * - * \param mods Contains the active modifiers active after the change. - */ -__attribute__((weak)) void oneshot_mods_changed_kb(uint8_t mods) { oneshot_mods_changed_user(mods); } - -/** \brief Called when the one shot layers have been changed. - * - * \param layer Contains the layer that is toggled on, or zero when toggled off. - */ -__attribute__((weak)) void oneshot_layer_changed_user(uint8_t layer) {} - -/** \brief Called when the one shot layers have been changed. - * - * \param layer Contains the layer that is toggled on, or zero when toggled off. - */ -__attribute__((weak)) void oneshot_layer_changed_kb(uint8_t layer) { oneshot_layer_changed_user(layer); } - -/** \brief inspect keyboard state - * - * FIXME: needs doc - */ -uint8_t has_anymod(void) { return bitpop(real_mods); } diff --git a/tmk_core/common/action_util.h b/tmk_core/common/action_util.h deleted file mode 100644 index f2b3897ae5..0000000000 --- a/tmk_core/common/action_util.h +++ /dev/null @@ -1,105 +0,0 @@ -/* -Copyright 2013 Jun Wako - -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 . -*/ - -#pragma once - -#include -#include "report.h" - -#ifdef __cplusplus -extern "C" { -#endif - -extern report_keyboard_t *keyboard_report; - -void send_keyboard_report(void); - -/* key */ -inline void add_key(uint8_t key) { add_key_to_report(keyboard_report, key); } - -inline void del_key(uint8_t key) { del_key_from_report(keyboard_report, key); } - -inline void clear_keys(void) { clear_keys_from_report(keyboard_report); } - -/* modifier */ -uint8_t get_mods(void); -void add_mods(uint8_t mods); -void del_mods(uint8_t mods); -void set_mods(uint8_t mods); -void clear_mods(void); - -/* weak modifier */ -uint8_t get_weak_mods(void); -void add_weak_mods(uint8_t mods); -void del_weak_mods(uint8_t mods); -void set_weak_mods(uint8_t mods); -void clear_weak_mods(void); - -/* macro modifier */ -uint8_t get_macro_mods(void); -void add_macro_mods(uint8_t mods); -void del_macro_mods(uint8_t mods); -void set_macro_mods(uint8_t mods); -void clear_macro_mods(void); - -/* oneshot modifier */ -uint8_t get_oneshot_mods(void); -void add_oneshot_mods(uint8_t mods); -void del_oneshot_mods(uint8_t mods); -void set_oneshot_mods(uint8_t mods); -void clear_oneshot_mods(void); -bool has_oneshot_mods_timed_out(void); - -uint8_t get_oneshot_locked_mods(void); -void set_oneshot_locked_mods(uint8_t mods); -void clear_oneshot_locked_mods(void); - -typedef enum { ONESHOT_PRESSED = 0b01, ONESHOT_OTHER_KEY_PRESSED = 0b10, ONESHOT_START = 0b11, ONESHOT_TOGGLED = 0b100 } oneshot_fullfillment_t; -void set_oneshot_layer(uint8_t layer, uint8_t state); -uint8_t get_oneshot_layer(void); -void clear_oneshot_layer_state(oneshot_fullfillment_t state); -void reset_oneshot_layer(void); -bool is_oneshot_layer_active(void); -uint8_t get_oneshot_layer_state(void); -bool has_oneshot_layer_timed_out(void); -bool has_oneshot_swaphands_timed_out(void); - -void oneshot_locked_mods_changed_user(uint8_t mods); -void oneshot_locked_mods_changed_kb(uint8_t mods); -void oneshot_mods_changed_user(uint8_t mods); -void oneshot_mods_changed_kb(uint8_t mods); -void oneshot_layer_changed_user(uint8_t layer); -void oneshot_layer_changed_kb(uint8_t layer); - -void oneshot_toggle(void); -void oneshot_enable(void); -void oneshot_disable(void); -bool is_oneshot_enabled(void); - -/* inspect */ -uint8_t has_anymod(void); - -#ifdef SWAP_HANDS_ENABLE -void set_oneshot_swaphands(void); -void release_oneshot_swaphands(void); -void use_oneshot_swaphands(void); -void clear_oneshot_swaphands(void); -#endif - -#ifdef __cplusplus -} -#endif diff --git a/tmk_core/common/eeconfig.c b/tmk_core/common/eeconfig.c deleted file mode 100644 index ffa56ab56d..0000000000 --- a/tmk_core/common/eeconfig.c +++ /dev/null @@ -1,211 +0,0 @@ -#include -#include -#include "eeprom.h" -#include "eeconfig.h" -#include "action_layer.h" - -#ifdef STM32_EEPROM_ENABLE -# include -# include "eeprom_stm32.h" -#endif - -#if defined(EEPROM_DRIVER) -# include "eeprom_driver.h" -#endif - -#if defined(HAPTIC_ENABLE) -# include "haptic.h" -#endif - -/** \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_Erase(); -#endif -#if defined(EEPROM_DRIVER) - eeprom_driver_erase(); -#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_LOWER_BYTE, 0); - eeprom_update_byte(EECONFIG_KEYMAP_UPPER_BYTE, 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); - eeprom_update_dword(EECONFIG_HAPTIC, 0); - eeprom_update_byte(EECONFIG_VELOCIKEY, 0); - eeprom_update_dword(EECONFIG_RGB_MATRIX, 0); - eeprom_update_word(EECONFIG_RGB_MATRIX_EXTENDED, 0); - - // TODO: Remove once ARM has a way to configure EECONFIG_HANDEDNESS - // within the emulated eeprom via dfu-util or another tool -#if defined INIT_EE_HANDS_LEFT -# pragma message "Faking EE_HANDS for left hand" - eeprom_update_byte(EECONFIG_HANDEDNESS, 1); -#elif defined INIT_EE_HANDS_RIGHT -# pragma message "Faking EE_HANDS for right hand" - eeprom_update_byte(EECONFIG_HANDEDNESS, 0); -#endif - -#if defined(HAPTIC_ENABLE) - haptic_reset(); -#else - // this is used in case haptic is disabled, but we still want sane defaults - // in the haptic configuration eeprom. All zero will trigger a haptic_reset - // when a haptic-enabled firmware is loaded onto the keyboard. - eeprom_update_dword(EECONFIG_HAPTIC, 0); -#endif - - eeconfig_init_kb(); -} - -/** \brief eeconfig initialization - * - * FIXME: needs doc - */ -void eeconfig_init(void) { eeconfig_init_quantum(); } - -/** \brief eeconfig enable - * - * FIXME: needs doc - */ -void eeconfig_enable(void) { eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER); } - -/** \brief eeconfig disable - * - * FIXME: needs doc - */ -void eeconfig_disable(void) { -#ifdef STM32_EEPROM_ENABLE - EEPROM_Erase(); -#endif -#if defined(EEPROM_DRIVER) - eeprom_driver_erase(); -#endif - eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER_OFF); -} - -/** \brief eeconfig is enabled - * - * FIXME: needs doc - */ -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 - */ -uint8_t eeconfig_read_debug(void) { return eeprom_read_byte(EECONFIG_DEBUG); } -/** \brief eeconfig update debug - * - * FIXME: needs doc - */ -void eeconfig_update_debug(uint8_t val) { eeprom_update_byte(EECONFIG_DEBUG, val); } - -/** \brief eeconfig read default layer - * - * FIXME: needs doc - */ -uint8_t eeconfig_read_default_layer(void) { return eeprom_read_byte(EECONFIG_DEFAULT_LAYER); } -/** \brief eeconfig update default layer - * - * FIXME: needs doc - */ -void eeconfig_update_default_layer(uint8_t val) { eeprom_update_byte(EECONFIG_DEFAULT_LAYER, val); } - -/** \brief eeconfig read keymap - * - * FIXME: needs doc - */ -uint16_t eeconfig_read_keymap(void) { return (eeprom_read_byte(EECONFIG_KEYMAP_LOWER_BYTE) | (eeprom_read_byte(EECONFIG_KEYMAP_UPPER_BYTE) << 8)); } -/** \brief eeconfig update keymap - * - * FIXME: needs doc - */ -void eeconfig_update_keymap(uint16_t val) { - eeprom_update_byte(EECONFIG_KEYMAP_LOWER_BYTE, val & 0xFF); - eeprom_update_byte(EECONFIG_KEYMAP_UPPER_BYTE, (val >> 8) & 0xFF); -} - -/** \brief eeconfig read audio - * - * FIXME: needs doc - */ -uint8_t eeconfig_read_audio(void) { return eeprom_read_byte(EECONFIG_AUDIO); } -/** \brief eeconfig update audio - * - * FIXME: needs doc - */ -void eeconfig_update_audio(uint8_t val) { eeprom_update_byte(EECONFIG_AUDIO, val); } - -/** \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); } - -/** \brief eeconfig read haptic - * - * FIXME: needs doc - */ -uint32_t eeconfig_read_haptic(void) { return eeprom_read_dword(EECONFIG_HAPTIC); } -/** \brief eeconfig update haptic - * - * FIXME: needs doc - */ -void eeconfig_update_haptic(uint32_t val) { eeprom_update_dword(EECONFIG_HAPTIC, val); } - -/** \brief eeconfig read split handedness - * - * FIXME: needs doc - */ -bool eeconfig_read_handedness(void) { return !!eeprom_read_byte(EECONFIG_HANDEDNESS); } -/** \brief eeconfig update split handedness - * - * FIXME: needs doc - */ -void eeconfig_update_handedness(bool val) { eeprom_update_byte(EECONFIG_HANDEDNESS, !!val); } diff --git a/tmk_core/common/eeconfig.h b/tmk_core/common/eeconfig.h deleted file mode 100644 index a88071729d..0000000000 --- a/tmk_core/common/eeconfig.h +++ /dev/null @@ -1,113 +0,0 @@ -/* -Copyright 2013 Jun Wako - -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 . -*/ - -#pragma once - -#include -#include - -#ifndef EECONFIG_MAGIC_NUMBER -# define EECONFIG_MAGIC_NUMBER (uint16_t)0xFEEA // When changing, decrement this value to avoid future re-init issues -#endif -#define EECONFIG_MAGIC_NUMBER_OFF (uint16_t)0xFFFF - -/* EEPROM parameter address */ -#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_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_KEYBOARD (uint32_t *)15 -#define EECONFIG_USER (uint32_t *)19 -#define EECONFIG_VELOCIKEY (uint8_t *)23 - -#define EECONFIG_HAPTIC (uint32_t *)24 - -// Mutually exclusive -#define EECONFIG_LED_MATRIX (uint32_t *)28 -#define EECONFIG_RGB_MATRIX (uint32_t *)28 -// Speed & Flags -#define EECONFIG_LED_MATRIX_EXTENDED (uint16_t *)32 -#define EECONFIG_RGB_MATRIX_EXTENDED (uint16_t *)32 - -// TODO: Combine these into a single word and single block of EEPROM -#define EECONFIG_KEYMAP_UPPER_BYTE (uint8_t *)34 -// Size of EEPROM being used, other code can refer to this for available EEPROM -#define EECONFIG_SIZE 35 -/* debug bit */ -#define EECONFIG_DEBUG_ENABLE (1 << 0) -#define EECONFIG_DEBUG_MATRIX (1 << 1) -#define EECONFIG_DEBUG_KEYBOARD (1 << 2) -#define EECONFIG_DEBUG_MOUSE (1 << 3) - -/* keyconf bit */ -#define EECONFIG_KEYMAP_SWAP_CONTROL_CAPSLOCK (1 << 0) -#define EECONFIG_KEYMAP_CAPSLOCK_TO_CONTROL (1 << 1) -#define EECONFIG_KEYMAP_SWAP_LALT_LGUI (1 << 2) -#define EECONFIG_KEYMAP_SWAP_RALT_RGUI (1 << 3) -#define EECONFIG_KEYMAP_NO_GUI (1 << 4) -#define EECONFIG_KEYMAP_SWAP_GRAVE_ESC (1 << 5) -#define EECONFIG_KEYMAP_SWAP_BACKSLASH_BACKSPACE (1 << 6) -#define EECONFIG_KEYMAP_NKRO (1 << 7) - -#define EECONFIG_KEYMAP_LOWER_BYTE EECONFIG_KEYMAP - -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); - -void eeconfig_disable(void); - -uint8_t eeconfig_read_debug(void); -void eeconfig_update_debug(uint8_t val); - -uint8_t eeconfig_read_default_layer(void); -void eeconfig_update_default_layer(uint8_t val); - -uint16_t eeconfig_read_keymap(void); -void eeconfig_update_keymap(uint16_t val); - -#ifdef AUDIO_ENABLE -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); - -#ifdef HAPTIC_ENABLE -uint32_t eeconfig_read_haptic(void); -void eeconfig_update_haptic(uint32_t val); -#endif - -bool eeconfig_read_handedness(void); -void eeconfig_update_handedness(bool val); diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c deleted file mode 100644 index fcc51973fd..0000000000 --- a/tmk_core/common/keyboard.c +++ /dev/null @@ -1,565 +0,0 @@ -/* -Copyright 2011, 2012, 2013 Jun Wako - -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 . -*/ - -#include -#include "keyboard.h" -#include "matrix.h" -#include "keymap.h" -#include "host.h" -#include "led.h" -#include "keycode.h" -#include "timer.h" -#include "sync_timer.h" -#include "print.h" -#include "debug.h" -#include "command.h" -#include "util.h" -#include "sendchar.h" -#include "eeconfig.h" -#include "action_layer.h" -#ifdef BACKLIGHT_ENABLE -# include "backlight.h" -#endif -#ifdef MOUSEKEY_ENABLE -# include "mousekey.h" -#endif -#ifdef PS2_MOUSE_ENABLE -# include "ps2_mouse.h" -#endif -#ifdef SERIAL_MOUSE_ENABLE -# include "serial_mouse.h" -#endif -#ifdef ADB_MOUSE_ENABLE -# include "adb.h" -#endif -#ifdef RGBLIGHT_ENABLE -# include "rgblight.h" -#endif -#ifdef LED_MATRIX_ENABLE -# include "led_matrix.h" -#endif -#ifdef RGB_MATRIX_ENABLE -# include "rgb_matrix.h" -#endif -#ifdef ENCODER_ENABLE -# include "encoder.h" -#endif -#ifdef STENO_ENABLE -# include "process_steno.h" -#endif -#ifdef SERIAL_LINK_ENABLE -# include "serial_link/system/serial_link.h" -#endif -#ifdef VISUALIZER_ENABLE -# include "visualizer/visualizer.h" -#endif -#ifdef POINTING_DEVICE_ENABLE -# include "pointing_device.h" -#endif -#ifdef MIDI_ENABLE -# include "process_midi.h" -#endif -#ifdef JOYSTICK_ENABLE -# include "process_joystick.h" -#endif -#ifdef HD44780_ENABLE -# include "hd44780.h" -#endif -#ifdef QWIIC_ENABLE -# include "qwiic.h" -#endif -#ifdef OLED_DRIVER_ENABLE -# include "oled_driver.h" -#endif -#ifdef ST7565_ENABLE -# include "st7565.h" -#endif -#ifdef VELOCIKEY_ENABLE -# include "velocikey.h" -#endif -#ifdef VIA_ENABLE -# include "via.h" -#endif -#ifdef DIP_SWITCH_ENABLE -# include "dip_switch.h" -#endif -#ifdef STM32_EEPROM_ENABLE -# include "eeprom_stm32.h" -#endif -#ifdef EEPROM_DRIVER -# include "eeprom_driver.h" -#endif -#if defined(CRC_ENABLE) -# include "crc.h" -#endif -#ifdef DIGITIZER_ENABLE -# include "digitizer.h" -#endif - -static uint32_t last_input_modification_time = 0; -uint32_t last_input_activity_time(void) { return last_input_modification_time; } -uint32_t last_input_activity_elapsed(void) { return timer_elapsed32(last_input_modification_time); } - -static uint32_t last_matrix_modification_time = 0; -uint32_t last_matrix_activity_time(void) { return last_matrix_modification_time; } -uint32_t last_matrix_activity_elapsed(void) { return timer_elapsed32(last_matrix_modification_time); } -void last_matrix_activity_trigger(void) { last_matrix_modification_time = last_input_modification_time = timer_read32(); } - -static uint32_t last_encoder_modification_time = 0; -uint32_t last_encoder_activity_time(void) { return last_encoder_modification_time; } -uint32_t last_encoder_activity_elapsed(void) { return timer_elapsed32(last_encoder_modification_time); } -void last_encoder_activity_trigger(void) { last_encoder_modification_time = last_input_modification_time = timer_read32(); } - -// Only enable this if console is enabled to print to -#if defined(DEBUG_MATRIX_SCAN_RATE) -static uint32_t matrix_timer = 0; -static uint32_t matrix_scan_count = 0; -static uint32_t last_matrix_scan_count = 0; - -void matrix_scan_perf_task(void) { - matrix_scan_count++; - - uint32_t timer_now = timer_read32(); - if (TIMER_DIFF_32(timer_now, matrix_timer) > 1000) { -# if defined(CONSOLE_ENABLE) - dprintf("matrix scan frequency: %lu\n", matrix_scan_count); -# endif - last_matrix_scan_count = matrix_scan_count; - matrix_timer = timer_now; - matrix_scan_count = 0; - } -} - -uint32_t get_matrix_scan_rate(void) { return last_matrix_scan_count; } -#else -# define matrix_scan_perf_task() -#endif - -#ifdef MATRIX_HAS_GHOST -extern const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS]; -static matrix_row_t get_real_keys(uint8_t row, matrix_row_t rowdata) { - matrix_row_t out = 0; - for (uint8_t col = 0; col < MATRIX_COLS; col++) { - // read each key in the row data and check if the keymap defines it as a real key - if (pgm_read_byte(&keymaps[0][row][col]) && (rowdata & (1 << col))) { - // this creates new row data, if a key is defined in the keymap, it will be set here - out |= 1 << col; - } - } - return out; -} - -static inline bool popcount_more_than_one(matrix_row_t rowdata) { - rowdata &= rowdata - 1; // if there are less than two bits (keys) set, rowdata will become zero - return rowdata; -} - -static inline bool has_ghost_in_row(uint8_t row, matrix_row_t rowdata) { - /* No ghost exists when less than 2 keys are down on the row. - If there are "active" blanks in the matrix, the key can't be pressed by the user, - there is no doubt as to which keys are really being pressed. - The ghosts will be ignored, they are KC_NO. */ - rowdata = get_real_keys(row, rowdata); - if ((popcount_more_than_one(rowdata)) == 0) { - return false; - } - /* Ghost occurs when the row shares a column line with other row, - and two columns are read on each row. Blanks in the matrix don't matter, - so they are filtered out. - If there are two or more real keys pressed and they match columns with - at least two of another row's real keys, the row will be ignored. Keep in mind, - we are checking one row at a time, not all of them at once. - */ - for (uint8_t i = 0; i < MATRIX_ROWS; i++) { - if (i != row && popcount_more_than_one(get_real_keys(i, matrix_get_row(i)) & rowdata)) { - return true; - } - } - return false; -} - -#endif - -void disable_jtag(void) { -// To use PF4-7 (PC2-5 on ATmega32A), disable JTAG by writing JTD bit twice within four cycles. -#if (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__)) - MCUCR |= _BV(JTD); - MCUCR |= _BV(JTD); -#elif defined(__AVR_ATmega32A__) - MCUCSR |= _BV(JTD); - MCUCSR |= _BV(JTD); -#endif -} - -/** \brief matrix_setup - * - * FIXME: needs doc - */ -__attribute__((weak)) void matrix_setup(void) {} - -/** \brief keyboard_pre_init_user - * - * FIXME: needs doc - */ -__attribute__((weak)) void keyboard_pre_init_user(void) {} - -/** \brief keyboard_pre_init_kb - * - * FIXME: needs doc - */ -__attribute__((weak)) void keyboard_pre_init_kb(void) { keyboard_pre_init_user(); } - -/** \brief keyboard_post_init_user - * - * FIXME: needs doc - */ - -__attribute__((weak)) void keyboard_post_init_user() {} - -/** \brief keyboard_post_init_kb - * - * FIXME: needs doc - */ - -__attribute__((weak)) void keyboard_post_init_kb(void) { keyboard_post_init_user(); } - -/** \brief keyboard_setup - * - * FIXME: needs doc - */ -void keyboard_setup(void) { -#ifndef NO_JTAG_DISABLE - disable_jtag(); -#endif - print_set_sendchar(sendchar); -#ifdef STM32_EEPROM_ENABLE - EEPROM_Init(); -#endif -#ifdef EEPROM_DRIVER - eeprom_driver_init(); -#endif - matrix_setup(); - keyboard_pre_init_kb(); -} - -/** \brief is_keyboard_master - * - * FIXME: needs doc - */ -__attribute__((weak)) bool is_keyboard_master(void) { return true; } - -/** \brief is_keyboard_left - * - * FIXME: needs doc - */ -__attribute__((weak)) bool is_keyboard_left(void) { return true; } - -/** \brief should_process_keypress - * - * Override this function if you have a condition where keypresses processing should change: - * - splits where the slave side needs to process for rgb/oled functionality - */ -__attribute__((weak)) bool should_process_keypress(void) { return is_keyboard_master(); } - -/** \brief housekeeping_task_kb - * - * Override this function if you have a need to execute code for every keyboard main loop iteration. - * This is specific to keyboard-level functionality. - */ -__attribute__((weak)) void housekeeping_task_kb(void) {} - -/** \brief housekeeping_task_user - * - * Override this function if you have a need to execute code for every keyboard main loop iteration. - * This is specific to user/keymap-level functionality. - */ -__attribute__((weak)) void housekeeping_task_user(void) {} - -/** \brief housekeeping_task - * - * Invokes hooks for executing code after QMK is done after each loop iteration. - */ -void housekeeping_task(void) { - housekeeping_task_kb(); - housekeeping_task_user(); -} - -/** \brief keyboard_init - * - * FIXME: needs doc - */ -void keyboard_init(void) { - timer_init(); - sync_timer_init(); - matrix_init(); -#if defined(CRC_ENABLE) - crc_init(); -#endif -#ifdef VIA_ENABLE - via_init(); -#endif -#ifdef QWIIC_ENABLE - qwiic_init(); -#endif -#ifdef OLED_DRIVER_ENABLE - oled_init(OLED_ROTATION_0); -#endif -#ifdef ST7565_ENABLE - st7565_init(DISPLAY_ROTATION_0); -#endif -#ifdef PS2_MOUSE_ENABLE - ps2_mouse_init(); -#endif -#ifdef SERIAL_MOUSE_ENABLE - serial_mouse_init(); -#endif -#ifdef ADB_MOUSE_ENABLE - adb_mouse_init(); -#endif -#ifdef BACKLIGHT_ENABLE - backlight_init(); -#endif -#ifdef RGBLIGHT_ENABLE - rgblight_init(); -#endif -#ifdef ENCODER_ENABLE - encoder_init(); -#endif -#ifdef STENO_ENABLE - steno_init(); -#endif -#ifdef POINTING_DEVICE_ENABLE - pointing_device_init(); -#endif -#if defined(NKRO_ENABLE) && defined(FORCE_NKRO) - keymap_config.nkro = 1; - eeconfig_update_keymap(keymap_config.raw); -#endif -#ifdef DIP_SWITCH_ENABLE - dip_switch_init(); -#endif - -#if defined(DEBUG_MATRIX_SCAN_RATE) && defined(CONSOLE_ENABLE) - debug_enable = true; -#endif - - keyboard_post_init_kb(); /* Always keep this last */ -} - -/** \brief key_event_task - * - * This function is responsible for calling into other systems when they need to respond to electrical switch press events. - * This is differnet than keycode events as no layer processing, or filtering occurs. - */ -void switch_events(uint8_t row, uint8_t col, bool pressed) { -#if defined(LED_MATRIX_ENABLE) - process_led_matrix(row, col, pressed); -#endif -#if defined(RGB_MATRIX_ENABLE) - process_rgb_matrix(row, col, pressed); -#endif -} - -/** \brief Keyboard task: Do keyboard routine jobs - * - * Do routine keyboard jobs: - * - * * scan matrix - * * handle mouse movements - * * run visualizer code - * * handle midi commands - * * light LEDs - * - * This is repeatedly called as fast as possible. - */ -void keyboard_task(void) { - static matrix_row_t matrix_prev[MATRIX_ROWS]; - static uint8_t led_status = 0; - matrix_row_t matrix_row = 0; - matrix_row_t matrix_change = 0; -#ifdef QMK_KEYS_PER_SCAN - uint8_t keys_processed = 0; -#endif -#ifdef ENCODER_ENABLE - bool encoders_changed = false; -#endif - - uint8_t matrix_changed = matrix_scan(); - if (matrix_changed) last_matrix_activity_trigger(); - - for (uint8_t r = 0; r < MATRIX_ROWS; r++) { - matrix_row = matrix_get_row(r); - matrix_change = matrix_row ^ matrix_prev[r]; - if (matrix_change) { -#ifdef MATRIX_HAS_GHOST - if (has_ghost_in_row(r, matrix_row)) { - continue; - } -#endif - if (debug_matrix) matrix_print(); - matrix_row_t col_mask = 1; - for (uint8_t c = 0; c < MATRIX_COLS; c++, col_mask <<= 1) { - if (matrix_change & col_mask) { - if (should_process_keypress()) { - action_exec((keyevent_t){ - .key = (keypos_t){.row = r, .col = c}, .pressed = (matrix_row & col_mask), .time = (timer_read() | 1) /* time should not be 0 */ - }); - } - // record a processed key - matrix_prev[r] ^= col_mask; - - switch_events(r, c, (matrix_row & col_mask)); - -#ifdef QMK_KEYS_PER_SCAN - // only jump out if we have processed "enough" keys. - if (++keys_processed >= QMK_KEYS_PER_SCAN) -#endif - // process a key per task call - goto MATRIX_LOOP_END; - } - } - } - } - // call with pseudo tick event when no real key event. -#ifdef QMK_KEYS_PER_SCAN - // we can get here with some keys processed now. - if (!keys_processed) -#endif - action_exec(TICK); - -MATRIX_LOOP_END: - -#ifdef DEBUG_MATRIX_SCAN_RATE - matrix_scan_perf_task(); -#endif - -#if defined(RGBLIGHT_ENABLE) - rgblight_task(); -#endif - -#ifdef LED_MATRIX_ENABLE - led_matrix_task(); -#endif -#ifdef RGB_MATRIX_ENABLE - rgb_matrix_task(); -#endif - -#if defined(BACKLIGHT_ENABLE) -# if defined(BACKLIGHT_PIN) || defined(BACKLIGHT_PINS) - backlight_task(); -# endif -#endif - -#ifdef ENCODER_ENABLE - encoders_changed = encoder_read(); - if (encoders_changed) last_encoder_activity_trigger(); -#endif - -#ifdef QWIIC_ENABLE - qwiic_task(); -#endif - -#ifdef OLED_DRIVER_ENABLE - oled_task(); -# ifndef OLED_DISABLE_TIMEOUT - // Wake up oled if user is using those fabulous keys or spinning those encoders! -# ifdef ENCODER_ENABLE - if (matrix_changed || encoders_changed) oled_on(); -# else - if (matrix_changed) oled_on(); -# endif -# endif -#endif - -#ifdef ST7565_ENABLE - st7565_task(); -# ifndef ST7565_DISABLE_TIMEOUT - // Wake up display if user is using those fabulous keys or spinning those encoders! -# ifdef ENCODER_ENABLE - if (matrix_changed || encoders_changed) st7565_on(); -# else - if (matrix_changed) st7565_on(); -# endif -# endif -#endif - -#ifdef MOUSEKEY_ENABLE - // mousekey repeat & acceleration - mousekey_task(); -#endif - -#ifdef PS2_MOUSE_ENABLE - ps2_mouse_task(); -#endif - -#ifdef SERIAL_MOUSE_ENABLE - serial_mouse_task(); -#endif - -#ifdef ADB_MOUSE_ENABLE - adb_mouse_task(); -#endif - -#ifdef SERIAL_LINK_ENABLE - serial_link_update(); -#endif - -#ifdef VISUALIZER_ENABLE - visualizer_update(default_layer_state, layer_state, visualizer_get_mods(), host_keyboard_leds()); -#endif - -#ifdef POINTING_DEVICE_ENABLE - pointing_device_task(); -#endif - -#ifdef MIDI_ENABLE - midi_task(); -#endif - -#ifdef VELOCIKEY_ENABLE - if (velocikey_enabled()) { - velocikey_decelerate(); - } -#endif - -#ifdef JOYSTICK_ENABLE - joystick_task(); -#endif - -#ifdef DIGITIZER_ENABLE - digitizer_task(); -#endif - - // update LED - if (led_status != host_keyboard_leds()) { - led_status = host_keyboard_leds(); - keyboard_set_leds(led_status); - } -} - -/** \brief keyboard set leds - * - * FIXME: needs doc - */ -void keyboard_set_leds(uint8_t leds) { - if (debug_keyboard) { - debug("keyboard_set_led: "); - debug_hex8(leds); - debug("\n"); - } - led_set(leds); -} diff --git a/tmk_core/common/keyboard.h b/tmk_core/common/keyboard.h deleted file mode 100644 index 08f4e84f94..0000000000 --- a/tmk_core/common/keyboard.h +++ /dev/null @@ -1,90 +0,0 @@ -/* -Copyright 2011,2012,2013 Jun Wako - -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 . -*/ - -#pragma once - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* key matrix position */ -typedef struct { - uint8_t col; - uint8_t row; -} keypos_t; - -/* key event */ -typedef struct { - keypos_t key; - bool pressed; - uint16_t time; -} keyevent_t; - -/* equivalent test of keypos_t */ -#define KEYEQ(keya, keyb) ((keya).row == (keyb).row && (keya).col == (keyb).col) - -/* Rules for No Event: - * 1) (time == 0) to handle (keyevent_t){} as empty event - * 2) Matrix(255, 255) to make TICK event available - */ -static inline bool IS_NOEVENT(keyevent_t event) { return event.time == 0 || (event.key.row == 255 && event.key.col == 255); } -static inline bool IS_PRESSED(keyevent_t event) { return (!IS_NOEVENT(event) && event.pressed); } -static inline bool IS_RELEASED(keyevent_t event) { return (!IS_NOEVENT(event) && !event.pressed); } - -/* Tick event */ -#define TICK \ - (keyevent_t) { .key = (keypos_t){.row = 255, .col = 255}, .pressed = false, .time = (timer_read() | 1) } - -/* 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. */ -void keyboard_init(void); -/* it runs repeatedly in main loop */ -void keyboard_task(void); -/* it runs when host LED status is updated */ -void keyboard_set_leds(uint8_t leds); -/* it runs whenever code has to behave differently on a slave */ -bool is_keyboard_master(void); -/* it runs whenever code has to behave differently on left vs right split */ -bool is_keyboard_left(void); - -void keyboard_pre_init_kb(void); -void keyboard_pre_init_user(void); -void keyboard_post_init_kb(void); -void keyboard_post_init_user(void); - -void housekeeping_task(void); // To be executed by the main loop in each backend TMK protocol -void housekeeping_task_kb(void); // To be overridden by keyboard-level code -void housekeeping_task_user(void); // To be overridden by user/keymap-level code - -uint32_t last_input_activity_time(void); // Timestamp of the last matrix or encoder activity -uint32_t last_input_activity_elapsed(void); // Number of milliseconds since the last matrix or encoder activity - -uint32_t last_matrix_activity_time(void); // Timestamp of the last matrix activity -uint32_t last_matrix_activity_elapsed(void); // Number of milliseconds since the last matrix activity - -uint32_t last_encoder_activity_time(void); // Timestamp of the last encoder activity -uint32_t last_encoder_activity_elapsed(void); // Number of milliseconds since the last encoder activity - -uint32_t get_matrix_scan_rate(void); - -#ifdef __cplusplus -} -#endif diff --git a/tmk_core/common/keycode.h b/tmk_core/common/keycode.h deleted file mode 100644 index 8facabd818..0000000000 --- a/tmk_core/common/keycode.h +++ /dev/null @@ -1,560 +0,0 @@ -/* -Copyright 2011,2012 Jun Wako - -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 . -*/ - -/* - * Keycodes based on HID Keyboard/Keypad Usage Page (0x07) plus media keys from Generic Desktop Page (0x01) and Consumer Page (0x0C) - * - * See https://web.archive.org/web/20060218214400/http://www.usb.org/developers/devclass_docs/Hut1_12.pdf - * or http://www.usb.org/developers/hidpage/Hut1_12v2.pdf (older) - */ - -#pragma once - -/* FIXME: Add doxygen comments here */ - -#define IS_ERROR(code) (KC_ROLL_OVER <= (code) && (code) <= KC_UNDEFINED) -#define IS_ANY(code) (KC_A <= (code) && (code) <= 0xFF) -#define IS_KEY(code) (KC_A <= (code) && (code) <= KC_EXSEL) -#define IS_MOD(code) (KC_LCTRL <= (code) && (code) <= KC_RGUI) - -#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_BRID) - -#define IS_FN(code) (KC_FN0 <= (code) && (code) <= KC_FN31) - -#define IS_MOUSEKEY(code) (KC_MS_UP <= (code) && (code) <= KC_MS_ACCEL2) -#define IS_MOUSEKEY_MOVE(code) (KC_MS_UP <= (code) && (code) <= KC_MS_RIGHT) -#define IS_MOUSEKEY_BUTTON(code) (KC_MS_BTN1 <= (code) && (code) <= KC_MS_BTN8) -#define IS_MOUSEKEY_WHEEL(code) (KC_MS_WH_UP <= (code) && (code) <= KC_MS_WH_RIGHT) -#define IS_MOUSEKEY_ACCEL(code) (KC_MS_ACCEL0 <= (code) && (code) <= KC_MS_ACCEL2) - -#define MOD_BIT(code) (1 << MOD_INDEX(code)) -#define MOD_INDEX(code) ((code)&0x07) - -#define MOD_MASK_CTRL (MOD_BIT(KC_LCTRL) | MOD_BIT(KC_RCTRL)) -#define MOD_MASK_SHIFT (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) -#define MOD_MASK_ALT (MOD_BIT(KC_LALT) | MOD_BIT(KC_RALT)) -#define MOD_MASK_GUI (MOD_BIT(KC_LGUI) | MOD_BIT(KC_RGUI)) -#define MOD_MASK_CS (MOD_MASK_CTRL | MOD_MASK_SHIFT) -#define MOD_MASK_CA (MOD_MASK_CTRL | MOD_MASK_ALT) -#define MOD_MASK_CG (MOD_MASK_CTRL | MOD_MASK_GUI) -#define MOD_MASK_SA (MOD_MASK_SHIFT | MOD_MASK_ALT) -#define MOD_MASK_SG (MOD_MASK_SHIFT | MOD_MASK_GUI) -#define MOD_MASK_AG (MOD_MASK_ALT | MOD_MASK_GUI) -#define MOD_MASK_CSA (MOD_MASK_CTRL | MOD_MASK_SHIFT | MOD_MASK_ALT) -#define MOD_MASK_CSG (MOD_MASK_CTRL | MOD_MASK_SHIFT | MOD_MASK_GUI) -#define MOD_MASK_CAG (MOD_MASK_CTRL | MOD_MASK_ALT | MOD_MASK_GUI) -#define MOD_MASK_SAG (MOD_MASK_SHIFT | MOD_MASK_ALT | MOD_MASK_GUI) -#define MOD_MASK_CSAG (MOD_MASK_CTRL | MOD_MASK_SHIFT | MOD_MASK_ALT | MOD_MASK_GUI) - -#define FN_BIT(code) (1 << FN_INDEX(code)) -#define FN_INDEX(code) ((code)-KC_FN0) -#define FN_MIN KC_FN0 -#define FN_MAX KC_FN31 - -/* - * Short names for ease of definition of keymap - */ -/* Transparent */ -#define KC_TRANSPARENT 0x01 -#define KC_TRNS KC_TRANSPARENT - -/* Punctuation */ -#define KC_ENT KC_ENTER -#define KC_ESC KC_ESCAPE -#define KC_BSPC KC_BSPACE -#define KC_SPC KC_SPACE -#define KC_MINS KC_MINUS -#define KC_EQL KC_EQUAL -#define KC_LBRC KC_LBRACKET -#define KC_RBRC KC_RBRACKET -#define KC_BSLS KC_BSLASH -#define KC_NUHS KC_NONUS_HASH -#define KC_SCLN KC_SCOLON -#define KC_QUOT KC_QUOTE -#define KC_GRV KC_GRAVE -#define KC_COMM KC_COMMA -#define KC_SLSH KC_SLASH -#define KC_NUBS KC_NONUS_BSLASH - -/* Lock Keys */ -#define KC_CLCK KC_CAPSLOCK -#define KC_CAPS KC_CAPSLOCK -#define KC_SLCK KC_SCROLLLOCK -#define KC_NLCK KC_NUMLOCK -#define KC_LCAP KC_LOCKING_CAPS -#define KC_LNUM KC_LOCKING_NUM -#define KC_LSCR KC_LOCKING_SCROLL - -/* Commands */ -#define KC_PSCR KC_PSCREEN -#define KC_PAUS KC_PAUSE -#define KC_BRK KC_PAUSE -#define KC_INS KC_INSERT -#define KC_DEL KC_DELETE -#define KC_PGDN KC_PGDOWN -#define KC_RGHT KC_RIGHT -#define KC_APP KC_APPLICATION -#define KC_EXEC KC_EXECUTE -#define KC_SLCT KC_SELECT -#define KC_AGIN KC_AGAIN -#define KC_PSTE KC_PASTE -#define KC_ERAS KC_ALT_ERASE -#define KC_CLR KC_CLEAR - -/* Keypad */ -#define KC_PSLS KC_KP_SLASH -#define KC_PAST KC_KP_ASTERISK -#define KC_PMNS KC_KP_MINUS -#define KC_PPLS KC_KP_PLUS -#define KC_PENT KC_KP_ENTER -#define KC_P1 KC_KP_1 -#define KC_P2 KC_KP_2 -#define KC_P3 KC_KP_3 -#define KC_P4 KC_KP_4 -#define KC_P5 KC_KP_5 -#define KC_P6 KC_KP_6 -#define KC_P7 KC_KP_7 -#define KC_P8 KC_KP_8 -#define KC_P9 KC_KP_9 -#define KC_P0 KC_KP_0 -#define KC_PDOT KC_KP_DOT -#define KC_PEQL KC_KP_EQUAL -#define KC_PCMM KC_KP_COMMA - -/* Japanese specific */ -#define KC_ZKHK KC_GRAVE -#define KC_RO KC_INT1 -#define KC_KANA KC_INT2 -#define KC_JYEN KC_INT3 -#define KC_HENK KC_INT4 -#define KC_MHEN KC_INT5 - -/* Korean specific */ -#define KC_HAEN KC_LANG1 -#define KC_HANJ KC_LANG2 - -/* Modifiers */ -#define KC_LCTL KC_LCTRL -#define KC_LSFT KC_LSHIFT -#define KC_LOPT KC_LALT -#define KC_LCMD KC_LGUI -#define KC_LWIN KC_LGUI -#define KC_RCTL KC_RCTRL -#define KC_RSFT KC_RSHIFT -#define KC_ALGR KC_RALT -#define KC_ROPT KC_RALT -#define KC_RCMD KC_RGUI -#define KC_RWIN KC_RGUI - -/* Generic Desktop Page (0x01) */ -#define KC_PWR KC_SYSTEM_POWER -#define KC_SLEP KC_SYSTEM_SLEEP -#define KC_WAKE KC_SYSTEM_WAKE - -/* Consumer Page (0x0C) */ -#define KC_MUTE KC_AUDIO_MUTE -#define KC_VOLU KC_AUDIO_VOL_UP -#define KC_VOLD KC_AUDIO_VOL_DOWN -#define KC_MNXT KC_MEDIA_NEXT_TRACK -#define KC_MPRV KC_MEDIA_PREV_TRACK -#define KC_MSTP KC_MEDIA_STOP -#define KC_MPLY KC_MEDIA_PLAY_PAUSE -#define KC_MSEL KC_MEDIA_SELECT -#define KC_EJCT KC_MEDIA_EJECT -#define KC_CALC KC_CALCULATOR -#define KC_MYCM KC_MY_COMPUTER -#define KC_WSCH KC_WWW_SEARCH -#define KC_WHOM KC_WWW_HOME -#define KC_WBAK KC_WWW_BACK -#define KC_WFWD KC_WWW_FORWARD -#define KC_WSTP KC_WWW_STOP -#define KC_WREF KC_WWW_REFRESH -#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 - -/* System Specific */ -#define KC_BRMU KC_PAUSE -#define KC_BRMD KC_SCROLLLOCK - -/* Mouse Keys */ -#define KC_MS_U KC_MS_UP -#define KC_MS_D KC_MS_DOWN -#define KC_MS_L KC_MS_LEFT -#define KC_MS_R KC_MS_RIGHT -#define KC_BTN1 KC_MS_BTN1 -#define KC_BTN2 KC_MS_BTN2 -#define KC_BTN3 KC_MS_BTN3 -#define KC_BTN4 KC_MS_BTN4 -#define KC_BTN5 KC_MS_BTN5 -#define KC_BTN6 KC_MS_BTN6 -#define KC_BTN7 KC_MS_BTN7 -#define KC_BTN8 KC_MS_BTN8 -#define KC_WH_U KC_MS_WH_UP -#define KC_WH_D KC_MS_WH_DOWN -#define KC_WH_L KC_MS_WH_LEFT -#define KC_WH_R KC_MS_WH_RIGHT -#define KC_ACL0 KC_MS_ACCEL0 -#define KC_ACL1 KC_MS_ACCEL1 -#define KC_ACL2 KC_MS_ACCEL2 - -/* Keyboard/Keypad Page (0x07) */ -enum hid_keyboard_keypad_usage { - KC_NO = 0x00, - KC_ROLL_OVER, - KC_POST_FAIL, - KC_UNDEFINED, - KC_A, - KC_B, - KC_C, - KC_D, - KC_E, - KC_F, - KC_G, - KC_H, - KC_I, - KC_J, - KC_K, - KC_L, - KC_M, // 0x10 - KC_N, - KC_O, - KC_P, - KC_Q, - KC_R, - KC_S, - KC_T, - KC_U, - KC_V, - KC_W, - KC_X, - KC_Y, - KC_Z, - KC_1, - KC_2, - KC_3, // 0x20 - KC_4, - KC_5, - KC_6, - KC_7, - KC_8, - KC_9, - KC_0, - KC_ENTER, - KC_ESCAPE, - KC_BSPACE, - KC_TAB, - KC_SPACE, - KC_MINUS, - KC_EQUAL, - KC_LBRACKET, - KC_RBRACKET, // 0x30 - KC_BSLASH, - KC_NONUS_HASH, - KC_SCOLON, - KC_QUOTE, - KC_GRAVE, - KC_COMMA, - KC_DOT, - KC_SLASH, - KC_CAPSLOCK, - KC_F1, - KC_F2, - KC_F3, - KC_F4, - KC_F5, - KC_F6, - KC_F7, // 0x40 - KC_F8, - KC_F9, - KC_F10, - KC_F11, - KC_F12, - KC_PSCREEN, - KC_SCROLLLOCK, - KC_PAUSE, - KC_INSERT, - KC_HOME, - KC_PGUP, - KC_DELETE, - KC_END, - KC_PGDOWN, - KC_RIGHT, - KC_LEFT, // 0x50 - KC_DOWN, - KC_UP, - KC_NUMLOCK, - KC_KP_SLASH, - KC_KP_ASTERISK, - KC_KP_MINUS, - KC_KP_PLUS, - KC_KP_ENTER, - KC_KP_1, - KC_KP_2, - KC_KP_3, - KC_KP_4, - KC_KP_5, - KC_KP_6, - KC_KP_7, - KC_KP_8, // 0x60 - KC_KP_9, - KC_KP_0, - KC_KP_DOT, - KC_NONUS_BSLASH, - KC_APPLICATION, - KC_POWER, - KC_KP_EQUAL, - KC_F13, - KC_F14, - KC_F15, - KC_F16, - KC_F17, - KC_F18, - KC_F19, - KC_F20, - KC_F21, // 0x70 - KC_F22, - KC_F23, - KC_F24, - KC_EXECUTE, - KC_HELP, - KC_MENU, - KC_SELECT, - KC_STOP, - KC_AGAIN, - KC_UNDO, - KC_CUT, - KC_COPY, - KC_PASTE, - KC_FIND, - KC__MUTE, - KC__VOLUP, // 0x80 - KC__VOLDOWN, - KC_LOCKING_CAPS, - KC_LOCKING_NUM, - KC_LOCKING_SCROLL, - KC_KP_COMMA, - KC_KP_EQUAL_AS400, - KC_INT1, - KC_INT2, - KC_INT3, - KC_INT4, - KC_INT5, - KC_INT6, - KC_INT7, - KC_INT8, - KC_INT9, - KC_LANG1, // 0x90 - KC_LANG2, - KC_LANG3, - KC_LANG4, - KC_LANG5, - KC_LANG6, - KC_LANG7, - KC_LANG8, - KC_LANG9, - KC_ALT_ERASE, - KC_SYSREQ, - KC_CANCEL, - KC_CLEAR, - KC_PRIOR, - KC_RETURN, - KC_SEPARATOR, - KC_OUT, // 0xA0 - KC_OPER, - KC_CLEAR_AGAIN, - KC_CRSEL, - KC_EXSEL, - -#if 0 - // *************************************************************** - // These keycodes are present in the HID spec, but are * - // nonfunctional on modern OSes. QMK uses this range (0xA5-0xDF) * - // for the media and function keys instead - see below. * - // *************************************************************** - - KC_KP_00 = 0xB0, - KC_KP_000, - KC_THOUSANDS_SEPARATOR, - KC_DECIMAL_SEPARATOR, - KC_CURRENCY_UNIT, - KC_CURRENCY_SUB_UNIT, - KC_KP_LPAREN, - KC_KP_RPAREN, - KC_KP_LCBRACKET, - KC_KP_RCBRACKET, - KC_KP_TAB, - KC_KP_BSPACE, - KC_KP_A, - KC_KP_B, - KC_KP_C, - KC_KP_D, - KC_KP_E, //0xC0 - KC_KP_F, - KC_KP_XOR, - KC_KP_HAT, - KC_KP_PERC, - KC_KP_LT, - KC_KP_GT, - KC_KP_AND, - KC_KP_LAZYAND, - KC_KP_OR, - KC_KP_LAZYOR, - KC_KP_COLON, - KC_KP_HASH, - KC_KP_SPACE, - KC_KP_ATMARK, - KC_KP_EXCLAMATION, - KC_KP_MEM_STORE, //0xD0 - KC_KP_MEM_RECALL, - KC_KP_MEM_CLEAR, - KC_KP_MEM_ADD, - KC_KP_MEM_SUB, - KC_KP_MEM_MUL, - KC_KP_MEM_DIV, - KC_KP_PLUS_MINUS, - KC_KP_CLEAR, - KC_KP_CLEAR_ENTRY, - KC_KP_BINARY, - KC_KP_OCTAL, - KC_KP_DECIMAL, - KC_KP_HEXADECIMAL, -#endif - - /* Modifiers */ - KC_LCTRL = 0xE0, - KC_LSHIFT, - KC_LALT, - KC_LGUI, - KC_RCTRL, - KC_RSHIFT, - KC_RALT, - KC_RGUI - - // ********************************************** - // * 0xF0-0xFF are unallocated in the HID spec. * - // * QMK uses these for Mouse Keys - see below. * - // ********************************************** -}; - -/* Media and Function keys */ -enum internal_special_keycodes { - /* Generic Desktop Page (0x01) */ - KC_SYSTEM_POWER = 0xA5, - KC_SYSTEM_SLEEP, - KC_SYSTEM_WAKE, - - /* Consumer Page (0x0C) */ - KC_AUDIO_MUTE, - KC_AUDIO_VOL_UP, - KC_AUDIO_VOL_DOWN, - KC_MEDIA_NEXT_TRACK, - KC_MEDIA_PREV_TRACK, - KC_MEDIA_STOP, - KC_MEDIA_PLAY_PAUSE, - KC_MEDIA_SELECT, - KC_MEDIA_EJECT, // 0xB0 - KC_MAIL, - KC_CALCULATOR, - KC_MY_COMPUTER, - KC_WWW_SEARCH, - KC_WWW_HOME, - KC_WWW_BACK, - KC_WWW_FORWARD, - KC_WWW_STOP, - KC_WWW_REFRESH, - KC_WWW_FAVORITES, - KC_MEDIA_FAST_FORWARD, - KC_MEDIA_REWIND, - KC_BRIGHTNESS_UP, - KC_BRIGHTNESS_DOWN, - - /* Fn keys */ - KC_FN0 = 0xC0, - KC_FN1, - KC_FN2, - KC_FN3, - KC_FN4, - KC_FN5, - KC_FN6, - KC_FN7, - KC_FN8, - KC_FN9, - KC_FN10, - KC_FN11, - KC_FN12, - KC_FN13, - KC_FN14, - KC_FN15, - KC_FN16, // 0xD0 - KC_FN17, - KC_FN18, - KC_FN19, - KC_FN20, - KC_FN21, - KC_FN22, - KC_FN23, - KC_FN24, - KC_FN25, - KC_FN26, - KC_FN27, - KC_FN28, - KC_FN29, - KC_FN30, - KC_FN31 -}; - -enum mouse_keys { -/* Mouse Buttons */ -#ifdef VIA_ENABLE - KC_MS_UP = 0xF0, -#else - KC_MS_UP = 0xED, -#endif - KC_MS_DOWN, - KC_MS_LEFT, - KC_MS_RIGHT, // 0xF0 - KC_MS_BTN1, - KC_MS_BTN2, - KC_MS_BTN3, - KC_MS_BTN4, - KC_MS_BTN5, -#ifdef VIA_ENABLE - KC_MS_BTN6 = KC_MS_BTN5, - KC_MS_BTN7 = KC_MS_BTN5, - KC_MS_BTN8 = KC_MS_BTN5, -#else - KC_MS_BTN6, - KC_MS_BTN7, - KC_MS_BTN8, -#endif - - /* Mouse Wheel */ - KC_MS_WH_UP, - KC_MS_WH_DOWN, - KC_MS_WH_LEFT, - KC_MS_WH_RIGHT, - - /* Acceleration */ - KC_MS_ACCEL0, - KC_MS_ACCEL1, - KC_MS_ACCEL2 // 0xFF -}; -- cgit v1.2.3 From ceb3ebda462390418b037669da8d631429bdd175 Mon Sep 17 00:00:00 2001 From: Nick Brassel Date: Wed, 18 Aug 2021 10:59:22 +1000 Subject: Fixup atsam builds. (#14052) --- tmk_core/protocol/arm_atsam/main_arm_atsam.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tmk_core') diff --git a/tmk_core/protocol/arm_atsam/main_arm_atsam.c b/tmk_core/protocol/arm_atsam/main_arm_atsam.c index abea121344..858b4cd9fc 100644 --- a/tmk_core/protocol/arm_atsam/main_arm_atsam.c +++ b/tmk_core/protocol/arm_atsam/main_arm_atsam.c @@ -16,7 +16,7 @@ along with this program. If not, see . */ #include "samd51j18a.h" -#include "tmk_core/common/keyboard.h" +#include "keyboard.h" #include "report.h" #include "host.h" -- cgit v1.2.3 From b16091659cc9a724a8800f77e631643b4ab089ad Mon Sep 17 00:00:00 2001 From: Ryan Date: Wed, 18 Aug 2021 18:20:25 +1000 Subject: Move USB Host Shield and Arduino core to `lib/` (#13973) --- lib/usbhost/USB_Host_Shield_2.0/.gitattributes | 23 + lib/usbhost/USB_Host_Shield_2.0/.gitignore | 4 + lib/usbhost/USB_Host_Shield_2.0/.gitmodules | 12 + lib/usbhost/USB_Host_Shield_2.0/BTD.cpp | 1364 +++++++++++++++++ lib/usbhost/USB_Host_Shield_2.0/BTD.h | 620 ++++++++ lib/usbhost/USB_Host_Shield_2.0/BTHID.cpp | 399 +++++ lib/usbhost/USB_Host_Shield_2.0/BTHID.h | 155 ++ lib/usbhost/USB_Host_Shield_2.0/PS3BT.cpp | 634 ++++++++ lib/usbhost/USB_Host_Shield_2.0/PS3BT.h | 240 +++ lib/usbhost/USB_Host_Shield_2.0/PS3Enums.h | 141 ++ lib/usbhost/USB_Host_Shield_2.0/PS3USB.cpp | 572 +++++++ lib/usbhost/USB_Host_Shield_2.0/PS3USB.h | 303 ++++ lib/usbhost/USB_Host_Shield_2.0/PS4BT.h | 121 ++ lib/usbhost/USB_Host_Shield_2.0/PS4Parser.cpp | 116 ++ lib/usbhost/USB_Host_Shield_2.0/PS4Parser.h | 407 +++++ lib/usbhost/USB_Host_Shield_2.0/PS4USB.h | 130 ++ lib/usbhost/USB_Host_Shield_2.0/PSBuzz.cpp | 82 + lib/usbhost/USB_Host_Shield_2.0/PSBuzz.h | 185 +++ lib/usbhost/USB_Host_Shield_2.0/README.md | 351 +++++ lib/usbhost/USB_Host_Shield_2.0/SPP.cpp | 829 ++++++++++ lib/usbhost/USB_Host_Shield_2.0/SPP.h | 225 +++ lib/usbhost/USB_Host_Shield_2.0/Usb.cpp | 812 ++++++++++ lib/usbhost/USB_Host_Shield_2.0/Usb.h | 41 + lib/usbhost/USB_Host_Shield_2.0/UsbCore.h | 298 ++++ lib/usbhost/USB_Host_Shield_2.0/Wii.cpp | 1268 ++++++++++++++++ lib/usbhost/USB_Host_Shield_2.0/Wii.h | 518 +++++++ lib/usbhost/USB_Host_Shield_2.0/WiiCameraReadme.md | 13 + lib/usbhost/USB_Host_Shield_2.0/XBOXOLD.cpp | 337 +++++ lib/usbhost/USB_Host_Shield_2.0/XBOXOLD.h | 185 +++ lib/usbhost/USB_Host_Shield_2.0/XBOXONE.cpp | 374 +++++ lib/usbhost/USB_Host_Shield_2.0/XBOXONE.h | 172 +++ lib/usbhost/USB_Host_Shield_2.0/XBOXRECV.cpp | 583 +++++++ lib/usbhost/USB_Host_Shield_2.0/XBOXRECV.h | 276 ++++ lib/usbhost/USB_Host_Shield_2.0/XBOXUSB.cpp | 361 +++++ lib/usbhost/USB_Host_Shield_2.0/XBOXUSB.h | 225 +++ lib/usbhost/USB_Host_Shield_2.0/address.h | 282 ++++ lib/usbhost/USB_Host_Shield_2.0/adk.cpp | 371 +++++ lib/usbhost/USB_Host_Shield_2.0/adk.h | 140 ++ lib/usbhost/USB_Host_Shield_2.0/avrpins.h | 1130 ++++++++++++++ lib/usbhost/USB_Host_Shield_2.0/cdc_XR21B1411.cpp | 211 +++ lib/usbhost/USB_Host_Shield_2.0/cdc_XR21B1411.h | 272 ++++ lib/usbhost/USB_Host_Shield_2.0/cdcacm.cpp | 331 ++++ lib/usbhost/USB_Host_Shield_2.0/cdcacm.h | 252 ++++ lib/usbhost/USB_Host_Shield_2.0/cdcftdi.cpp | 334 ++++ lib/usbhost/USB_Host_Shield_2.0/cdcftdi.h | 145 ++ lib/usbhost/USB_Host_Shield_2.0/cdcprolific.cpp | 247 +++ lib/usbhost/USB_Host_Shield_2.0/cdcprolific.h | 159 ++ lib/usbhost/USB_Host_Shield_2.0/confdescparser.h | 213 +++ lib/usbhost/USB_Host_Shield_2.0/controllerEnums.h | 204 +++ .../examples/Bluetooth/BTHID/BTHID.ino | 55 + .../examples/Bluetooth/BTHID/KeyboardParser.h | 105 ++ .../examples/Bluetooth/BTHID/MouseParser.h | 46 + .../examples/Bluetooth/PS3BT/PS3BT.ino | 188 +++ .../examples/Bluetooth/PS3Multi/PS3Multi.ino | 149 ++ .../examples/Bluetooth/PS3SPP/PS3SPP.ino | 162 ++ .../examples/Bluetooth/PS4BT/PS4BT.ino | 146 ++ .../examples/Bluetooth/SPP/SPP.ino | 52 + .../examples/Bluetooth/SPPMulti/SPPMulti.ino | 67 + .../examples/Bluetooth/Wii/Wii.ino | 118 ++ .../Bluetooth/WiiBalanceBoard/WiiBalanceBoard.ino | 51 + .../examples/Bluetooth/WiiIRCamera/WiiIRCamera.ino | 133 ++ .../examples/Bluetooth/WiiMulti/WiiMulti.ino | 132 ++ .../WiiUProController/WiiUProController.ino | 104 ++ .../examples/HID/USBHIDBootKbd/USBHIDBootKbd.ino | 129 ++ .../USBHIDBootKbdAndMouse.ino | 178 +++ .../HID/USBHIDBootMouse/USBHIDBootMouse.ino | 83 + .../examples/HID/USBHIDJoystick/USBHIDJoystick.ino | 38 + .../HID/USBHIDJoystick/hidjoystickrptparser.cpp | 84 ++ .../HID/USBHIDJoystick/hidjoystickrptparser.h | 33 + .../examples/HID/USBHID_desc/USBHID_desc.ino | 77 + .../examples/HID/USBHID_desc/pgmstrings.h | 52 + .../examples/HID/le3dp/le3dp.ino | 42 + .../examples/HID/le3dp/le3dp_rptparser.cpp | 43 + .../examples/HID/le3dp/le3dp_rptparser.h | 42 + .../examples/HID/scale/scale.ino | 51 + .../examples/HID/scale/scale_rptparser.cpp | 150 ++ .../examples/HID/scale/scale_rptparser.h | 55 + .../USB_Host_Shield_2.0/examples/PS3USB/PS3USB.ino | 148 ++ .../USB_Host_Shield_2.0/examples/PS4USB/PS4USB.ino | 133 ++ .../USB_Host_Shield_2.0/examples/PSBuzz/PSBuzz.ino | 49 + .../examples/USB_desc/USB_desc.ino | 349 +++++ .../examples/USB_desc/pgmstrings.h | 52 + .../examples/Xbox/XBOXOLD/XBOXOLD.ino | 110 ++ .../examples/Xbox/XBOXONE/XBOXONE.ino | 106 ++ .../examples/Xbox/XBOXRECV/XBOXRECV.ino | 122 ++ .../examples/Xbox/XBOXUSB/XBOXUSB.ino | 113 ++ .../examples/acm/acm_terminal/acm_terminal.ino | 100 ++ .../examples/acm/acm_terminal/pgmstrings.h | 52 + .../adk/ArduinoBlinkLED/ArduinoBlinkLED.ino | 89 ++ .../examples/adk/adk_barcode/adk_barcode.ino | 91 ++ .../examples/adk/demokit_20/demokit_20.ino | 103 ++ .../examples/adk/term_test/term_test.ino | 65 + .../examples/adk/term_time/term_time.ino | 50 + .../examples/board_qc/board_qc.ino | 259 ++++ .../cdc_XR21B1411/XR_terminal/XR_terminal.ino | 83 + .../ftdi/USBFTDILoopback/USBFTDILoopback.ino | 98 ++ .../examples/ftdi/USBFTDILoopback/pgmstrings.h | 52 + .../examples/hub_demo/hub_demo.ino | 345 +++++ .../examples/hub_demo/pgmstrings.h | 52 + .../examples/max_LCD/max_LCD.ino | 29 + .../pl2303_gprs_terminal/pl2303_gprs_terminal.ino | 101 ++ .../examples/pl2303/pl2303_gps/pl2303_gps.ino | 88 ++ .../pl2303/pl2303_tinygps/pl2303_tinygps.ino | 217 +++ .../pl2303_xbee_terminal/pl2303_xbee_terminal.ino | 117 ++ .../examples/testusbhostFAT/Makefile | 64 + .../examples/testusbhostFAT/README.md | 29 + .../examples/testusbhostFAT/testusbhostFAT.ino | 736 +++++++++ lib/usbhost/USB_Host_Shield_2.0/gpl2.txt | 340 +++++ lib/usbhost/USB_Host_Shield_2.0/hexdump.h | 61 + lib/usbhost/USB_Host_Shield_2.0/hid.cpp | 112 ++ lib/usbhost/USB_Host_Shield_2.0/hid.h | 188 +++ lib/usbhost/USB_Host_Shield_2.0/hidboot.cpp | 201 +++ lib/usbhost/USB_Host_Shield_2.0/hidboot.h | 618 ++++++++ .../USB_Host_Shield_2.0/hidescriptorparser.cpp | 1588 ++++++++++++++++++++ .../USB_Host_Shield_2.0/hidescriptorparser.h | 176 +++ lib/usbhost/USB_Host_Shield_2.0/hiduniversal.cpp | 425 ++++++ lib/usbhost/USB_Host_Shield_2.0/hiduniversal.h | 108 ++ lib/usbhost/USB_Host_Shield_2.0/hidusagestr.h | 977 ++++++++++++ .../USB_Host_Shield_2.0/hidusagetitlearrays.cpp | 1048 +++++++++++++ lib/usbhost/USB_Host_Shield_2.0/keywords.txt | 371 +++++ lib/usbhost/USB_Host_Shield_2.0/library.json | 47 + lib/usbhost/USB_Host_Shield_2.0/library.properties | 9 + lib/usbhost/USB_Host_Shield_2.0/macros.h | 82 + lib/usbhost/USB_Host_Shield_2.0/masstorage.cpp | 1266 ++++++++++++++++ lib/usbhost/USB_Host_Shield_2.0/masstorage.h | 571 +++++++ lib/usbhost/USB_Host_Shield_2.0/max3421e.h | 228 +++ lib/usbhost/USB_Host_Shield_2.0/max_LCD.cpp | 255 ++++ lib/usbhost/USB_Host_Shield_2.0/max_LCD.h | 106 ++ lib/usbhost/USB_Host_Shield_2.0/message.cpp | 116 ++ lib/usbhost/USB_Host_Shield_2.0/message.h | 78 + lib/usbhost/USB_Host_Shield_2.0/parsetools.cpp | 67 + lib/usbhost/USB_Host_Shield_2.0/parsetools.h | 140 ++ lib/usbhost/USB_Host_Shield_2.0/printhex.h | 84 ++ lib/usbhost/USB_Host_Shield_2.0/settings.h | 139 ++ lib/usbhost/USB_Host_Shield_2.0/sink_parser.h | 41 + lib/usbhost/USB_Host_Shield_2.0/usb_ch9.h | 166 ++ lib/usbhost/USB_Host_Shield_2.0/usbhost.h | 529 +++++++ lib/usbhost/USB_Host_Shield_2.0/usbhub.cpp | 425 ++++++ lib/usbhost/USB_Host_Shield_2.0/usbhub.h | 252 ++++ lib/usbhost/USB_Host_Shield_2.0/version_helper.h | 194 +++ lib/usbhost/USB_Host_Shield_2.0/xboxEnums.h | 65 + lib/usbhost/arduino-1.0.1/cores/arduino/Arduino.h | 215 +++ lib/usbhost/arduino-1.0.1/cores/arduino/CDC.cpp | 233 +++ lib/usbhost/arduino-1.0.1/cores/arduino/Client.h | 26 + lib/usbhost/arduino-1.0.1/cores/arduino/HID.cpp | 520 +++++++ .../arduino-1.0.1/cores/arduino/HardwareSerial.cpp | 428 ++++++ .../arduino-1.0.1/cores/arduino/HardwareSerial.h | 81 + .../arduino-1.0.1/cores/arduino/IPAddress.cpp | 56 + .../arduino-1.0.1/cores/arduino/IPAddress.h | 76 + lib/usbhost/arduino-1.0.1/cores/arduino/Platform.h | 23 + lib/usbhost/arduino-1.0.1/cores/arduino/Print.cpp | 263 ++++ lib/usbhost/arduino-1.0.1/cores/arduino/Print.h | 78 + .../arduino-1.0.1/cores/arduino/Printable.h | 40 + lib/usbhost/arduino-1.0.1/cores/arduino/Server.h | 9 + lib/usbhost/arduino-1.0.1/cores/arduino/Stream.cpp | 270 ++++ lib/usbhost/arduino-1.0.1/cores/arduino/Stream.h | 96 ++ lib/usbhost/arduino-1.0.1/cores/arduino/Tone.cpp | 601 ++++++++ lib/usbhost/arduino-1.0.1/cores/arduino/USBAPI.h | 195 +++ .../arduino-1.0.1/cores/arduino/USBCore.cpp | 672 +++++++++ lib/usbhost/arduino-1.0.1/cores/arduino/USBCore.h | 303 ++++ lib/usbhost/arduino-1.0.1/cores/arduino/USBDesc.h | 63 + lib/usbhost/arduino-1.0.1/cores/arduino/Udp.h | 88 ++ .../arduino-1.0.1/cores/arduino/WCharacter.h | 168 +++ .../arduino-1.0.1/cores/arduino/WInterrupts.c | 298 ++++ lib/usbhost/arduino-1.0.1/cores/arduino/WMath.cpp | 60 + .../arduino-1.0.1/cores/arduino/WString.cpp | 645 ++++++++ lib/usbhost/arduino-1.0.1/cores/arduino/WString.h | 205 +++ lib/usbhost/arduino-1.0.1/cores/arduino/binary.h | 515 +++++++ lib/usbhost/arduino-1.0.1/cores/arduino/main.cpp | 20 + lib/usbhost/arduino-1.0.1/cores/arduino/new.cpp | 18 + lib/usbhost/arduino-1.0.1/cores/arduino/new.h | 22 + lib/usbhost/arduino-1.0.1/cores/arduino/wiring.c | 324 ++++ .../arduino-1.0.1/cores/arduino/wiring_analog.c | 282 ++++ .../arduino-1.0.1/cores/arduino/wiring_digital.c | 178 +++ .../arduino-1.0.1/cores/arduino/wiring_private.h | 69 + .../arduino-1.0.1/cores/arduino/wiring_pulse.c | 69 + .../arduino-1.0.1/cores/arduino/wiring_shift.c | 55 + .../variants/eightanaloginputs/pins_arduino.h | 27 + .../arduino-1.0.1/variants/leonardo/pins_arduino.h | 256 ++++ .../arduino-1.0.1/variants/mega/pins_arduino.h | 363 +++++ .../arduino-1.0.1/variants/standard/pins_arduino.h | 218 +++ tmk_core/protocol/usb_hid.mk | 12 +- .../usb_hid/USB_Host_Shield_2.0/.gitattributes | 23 - .../usb_hid/USB_Host_Shield_2.0/.gitignore | 4 - .../usb_hid/USB_Host_Shield_2.0/.gitmodules | 12 - .../protocol/usb_hid/USB_Host_Shield_2.0/BTD.cpp | 1364 ----------------- .../protocol/usb_hid/USB_Host_Shield_2.0/BTD.h | 620 -------- .../protocol/usb_hid/USB_Host_Shield_2.0/BTHID.cpp | 399 ----- .../protocol/usb_hid/USB_Host_Shield_2.0/BTHID.h | 155 -- .../protocol/usb_hid/USB_Host_Shield_2.0/PS3BT.cpp | 634 -------- .../protocol/usb_hid/USB_Host_Shield_2.0/PS3BT.h | 240 --- .../usb_hid/USB_Host_Shield_2.0/PS3Enums.h | 141 -- .../usb_hid/USB_Host_Shield_2.0/PS3USB.cpp | 572 ------- .../protocol/usb_hid/USB_Host_Shield_2.0/PS3USB.h | 303 ---- .../protocol/usb_hid/USB_Host_Shield_2.0/PS4BT.h | 121 -- .../usb_hid/USB_Host_Shield_2.0/PS4Parser.cpp | 116 -- .../usb_hid/USB_Host_Shield_2.0/PS4Parser.h | 407 ----- .../protocol/usb_hid/USB_Host_Shield_2.0/PS4USB.h | 130 -- .../usb_hid/USB_Host_Shield_2.0/PSBuzz.cpp | 82 - .../protocol/usb_hid/USB_Host_Shield_2.0/PSBuzz.h | 185 --- .../protocol/usb_hid/USB_Host_Shield_2.0/README.md | 351 ----- .../protocol/usb_hid/USB_Host_Shield_2.0/SPP.cpp | 829 ---------- .../protocol/usb_hid/USB_Host_Shield_2.0/SPP.h | 225 --- .../protocol/usb_hid/USB_Host_Shield_2.0/Usb.cpp | 812 ---------- .../protocol/usb_hid/USB_Host_Shield_2.0/Usb.h | 41 - .../protocol/usb_hid/USB_Host_Shield_2.0/UsbCore.h | 298 ---- .../protocol/usb_hid/USB_Host_Shield_2.0/Wii.cpp | 1268 ---------------- .../protocol/usb_hid/USB_Host_Shield_2.0/Wii.h | 518 ------- .../usb_hid/USB_Host_Shield_2.0/WiiCameraReadme.md | 13 - .../usb_hid/USB_Host_Shield_2.0/XBOXOLD.cpp | 337 ----- .../protocol/usb_hid/USB_Host_Shield_2.0/XBOXOLD.h | 185 --- .../usb_hid/USB_Host_Shield_2.0/XBOXONE.cpp | 374 ----- .../protocol/usb_hid/USB_Host_Shield_2.0/XBOXONE.h | 172 --- .../usb_hid/USB_Host_Shield_2.0/XBOXRECV.cpp | 583 ------- .../usb_hid/USB_Host_Shield_2.0/XBOXRECV.h | 276 ---- .../usb_hid/USB_Host_Shield_2.0/XBOXUSB.cpp | 361 ----- .../protocol/usb_hid/USB_Host_Shield_2.0/XBOXUSB.h | 225 --- .../protocol/usb_hid/USB_Host_Shield_2.0/address.h | 282 ---- .../protocol/usb_hid/USB_Host_Shield_2.0/adk.cpp | 371 ----- .../protocol/usb_hid/USB_Host_Shield_2.0/adk.h | 140 -- .../protocol/usb_hid/USB_Host_Shield_2.0/avrpins.h | 1130 -------------- .../usb_hid/USB_Host_Shield_2.0/cdc_XR21B1411.cpp | 211 --- .../usb_hid/USB_Host_Shield_2.0/cdc_XR21B1411.h | 272 ---- .../usb_hid/USB_Host_Shield_2.0/cdcacm.cpp | 331 ---- .../protocol/usb_hid/USB_Host_Shield_2.0/cdcacm.h | 252 ---- .../usb_hid/USB_Host_Shield_2.0/cdcftdi.cpp | 334 ---- .../protocol/usb_hid/USB_Host_Shield_2.0/cdcftdi.h | 145 -- .../usb_hid/USB_Host_Shield_2.0/cdcprolific.cpp | 247 --- .../usb_hid/USB_Host_Shield_2.0/cdcprolific.h | 159 -- .../usb_hid/USB_Host_Shield_2.0/confdescparser.h | 213 --- .../usb_hid/USB_Host_Shield_2.0/controllerEnums.h | 204 --- .../examples/Bluetooth/BTHID/BTHID.ino | 55 - .../examples/Bluetooth/BTHID/KeyboardParser.h | 105 -- .../examples/Bluetooth/BTHID/MouseParser.h | 46 - .../examples/Bluetooth/PS3BT/PS3BT.ino | 188 --- .../examples/Bluetooth/PS3Multi/PS3Multi.ino | 149 -- .../examples/Bluetooth/PS3SPP/PS3SPP.ino | 162 -- .../examples/Bluetooth/PS4BT/PS4BT.ino | 146 -- .../examples/Bluetooth/SPP/SPP.ino | 52 - .../examples/Bluetooth/SPPMulti/SPPMulti.ino | 67 - .../examples/Bluetooth/Wii/Wii.ino | 118 -- .../Bluetooth/WiiBalanceBoard/WiiBalanceBoard.ino | 51 - .../examples/Bluetooth/WiiIRCamera/WiiIRCamera.ino | 133 -- .../examples/Bluetooth/WiiMulti/WiiMulti.ino | 132 -- .../WiiUProController/WiiUProController.ino | 104 -- .../examples/HID/USBHIDBootKbd/USBHIDBootKbd.ino | 129 -- .../USBHIDBootKbdAndMouse.ino | 178 --- .../HID/USBHIDBootMouse/USBHIDBootMouse.ino | 83 - .../examples/HID/USBHIDJoystick/USBHIDJoystick.ino | 38 - .../HID/USBHIDJoystick/hidjoystickrptparser.cpp | 84 -- .../HID/USBHIDJoystick/hidjoystickrptparser.h | 33 - .../examples/HID/USBHID_desc/USBHID_desc.ino | 77 - .../examples/HID/USBHID_desc/pgmstrings.h | 52 - .../examples/HID/le3dp/le3dp.ino | 42 - .../examples/HID/le3dp/le3dp_rptparser.cpp | 43 - .../examples/HID/le3dp/le3dp_rptparser.h | 42 - .../examples/HID/scale/scale.ino | 51 - .../examples/HID/scale/scale_rptparser.cpp | 150 -- .../examples/HID/scale/scale_rptparser.h | 55 - .../USB_Host_Shield_2.0/examples/PS3USB/PS3USB.ino | 148 -- .../USB_Host_Shield_2.0/examples/PS4USB/PS4USB.ino | 133 -- .../USB_Host_Shield_2.0/examples/PSBuzz/PSBuzz.ino | 49 - .../examples/USB_desc/USB_desc.ino | 349 ----- .../examples/USB_desc/pgmstrings.h | 52 - .../examples/Xbox/XBOXOLD/XBOXOLD.ino | 110 -- .../examples/Xbox/XBOXONE/XBOXONE.ino | 106 -- .../examples/Xbox/XBOXRECV/XBOXRECV.ino | 122 -- .../examples/Xbox/XBOXUSB/XBOXUSB.ino | 113 -- .../examples/acm/acm_terminal/acm_terminal.ino | 100 -- .../examples/acm/acm_terminal/pgmstrings.h | 52 - .../adk/ArduinoBlinkLED/ArduinoBlinkLED.ino | 89 -- .../examples/adk/adk_barcode/adk_barcode.ino | 91 -- .../examples/adk/demokit_20/demokit_20.ino | 103 -- .../examples/adk/term_test/term_test.ino | 65 - .../examples/adk/term_time/term_time.ino | 50 - .../examples/board_qc/board_qc.ino | 259 ---- .../cdc_XR21B1411/XR_terminal/XR_terminal.ino | 83 - .../ftdi/USBFTDILoopback/USBFTDILoopback.ino | 98 -- .../examples/ftdi/USBFTDILoopback/pgmstrings.h | 52 - .../examples/hub_demo/hub_demo.ino | 345 ----- .../examples/hub_demo/pgmstrings.h | 52 - .../examples/max_LCD/max_LCD.ino | 29 - .../pl2303_gprs_terminal/pl2303_gprs_terminal.ino | 101 -- .../examples/pl2303/pl2303_gps/pl2303_gps.ino | 88 -- .../pl2303/pl2303_tinygps/pl2303_tinygps.ino | 217 --- .../pl2303_xbee_terminal/pl2303_xbee_terminal.ino | 117 -- .../examples/testusbhostFAT/Makefile | 64 - .../examples/testusbhostFAT/README.md | 29 - .../examples/testusbhostFAT/testusbhostFAT.ino | 736 --------- .../protocol/usb_hid/USB_Host_Shield_2.0/gpl2.txt | 340 ----- .../protocol/usb_hid/USB_Host_Shield_2.0/hexdump.h | 61 - .../protocol/usb_hid/USB_Host_Shield_2.0/hid.cpp | 112 -- .../protocol/usb_hid/USB_Host_Shield_2.0/hid.h | 188 --- .../usb_hid/USB_Host_Shield_2.0/hidboot.cpp | 201 --- .../protocol/usb_hid/USB_Host_Shield_2.0/hidboot.h | 618 -------- .../USB_Host_Shield_2.0/hidescriptorparser.cpp | 1588 -------------------- .../USB_Host_Shield_2.0/hidescriptorparser.h | 176 --- .../usb_hid/USB_Host_Shield_2.0/hiduniversal.cpp | 425 ------ .../usb_hid/USB_Host_Shield_2.0/hiduniversal.h | 108 -- .../usb_hid/USB_Host_Shield_2.0/hidusagestr.h | 977 ------------ .../USB_Host_Shield_2.0/hidusagetitlearrays.cpp | 1048 ------------- .../usb_hid/USB_Host_Shield_2.0/keywords.txt | 371 ----- .../usb_hid/USB_Host_Shield_2.0/library.json | 47 - .../usb_hid/USB_Host_Shield_2.0/library.properties | 9 - .../protocol/usb_hid/USB_Host_Shield_2.0/macros.h | 82 - .../usb_hid/USB_Host_Shield_2.0/masstorage.cpp | 1266 ---------------- .../usb_hid/USB_Host_Shield_2.0/masstorage.h | 571 ------- .../usb_hid/USB_Host_Shield_2.0/max3421e.h | 228 --- .../usb_hid/USB_Host_Shield_2.0/max_LCD.cpp | 255 ---- .../protocol/usb_hid/USB_Host_Shield_2.0/max_LCD.h | 106 -- .../usb_hid/USB_Host_Shield_2.0/message.cpp | 116 -- .../protocol/usb_hid/USB_Host_Shield_2.0/message.h | 78 - .../usb_hid/USB_Host_Shield_2.0/parsetools.cpp | 67 - .../usb_hid/USB_Host_Shield_2.0/parsetools.h | 140 -- .../usb_hid/USB_Host_Shield_2.0/printhex.h | 84 -- .../usb_hid/USB_Host_Shield_2.0/settings.h | 139 -- .../usb_hid/USB_Host_Shield_2.0/sink_parser.h | 41 - .../protocol/usb_hid/USB_Host_Shield_2.0/usb_ch9.h | 166 -- .../protocol/usb_hid/USB_Host_Shield_2.0/usbhost.h | 529 ------- .../usb_hid/USB_Host_Shield_2.0/usbhub.cpp | 425 ------ .../protocol/usb_hid/USB_Host_Shield_2.0/usbhub.h | 252 ---- .../usb_hid/USB_Host_Shield_2.0/version_helper.h | 194 --- .../usb_hid/USB_Host_Shield_2.0/xboxEnums.h | 65 - .../usb_hid/arduino-1.0.1/cores/arduino/Arduino.h | 215 --- .../usb_hid/arduino-1.0.1/cores/arduino/CDC.cpp | 233 --- .../usb_hid/arduino-1.0.1/cores/arduino/Client.h | 26 - .../usb_hid/arduino-1.0.1/cores/arduino/HID.cpp | 520 ------- .../arduino-1.0.1/cores/arduino/HardwareSerial.cpp | 428 ------ .../arduino-1.0.1/cores/arduino/HardwareSerial.h | 81 - .../arduino-1.0.1/cores/arduino/IPAddress.cpp | 56 - .../arduino-1.0.1/cores/arduino/IPAddress.h | 76 - .../usb_hid/arduino-1.0.1/cores/arduino/Platform.h | 23 - .../usb_hid/arduino-1.0.1/cores/arduino/Print.cpp | 263 ---- .../usb_hid/arduino-1.0.1/cores/arduino/Print.h | 78 - .../arduino-1.0.1/cores/arduino/Printable.h | 40 - .../usb_hid/arduino-1.0.1/cores/arduino/Server.h | 9 - .../usb_hid/arduino-1.0.1/cores/arduino/Stream.cpp | 270 ---- .../usb_hid/arduino-1.0.1/cores/arduino/Stream.h | 96 -- .../usb_hid/arduino-1.0.1/cores/arduino/Tone.cpp | 601 -------- .../usb_hid/arduino-1.0.1/cores/arduino/USBAPI.h | 195 --- .../arduino-1.0.1/cores/arduino/USBCore.cpp | 672 --------- .../usb_hid/arduino-1.0.1/cores/arduino/USBCore.h | 303 ---- .../usb_hid/arduino-1.0.1/cores/arduino/USBDesc.h | 63 - .../usb_hid/arduino-1.0.1/cores/arduino/Udp.h | 88 -- .../arduino-1.0.1/cores/arduino/WCharacter.h | 168 --- .../arduino-1.0.1/cores/arduino/WInterrupts.c | 298 ---- .../usb_hid/arduino-1.0.1/cores/arduino/WMath.cpp | 60 - .../arduino-1.0.1/cores/arduino/WString.cpp | 645 -------- .../usb_hid/arduino-1.0.1/cores/arduino/WString.h | 205 --- .../usb_hid/arduino-1.0.1/cores/arduino/binary.h | 515 ------- .../usb_hid/arduino-1.0.1/cores/arduino/main.cpp | 20 - .../usb_hid/arduino-1.0.1/cores/arduino/new.cpp | 18 - .../usb_hid/arduino-1.0.1/cores/arduino/new.h | 22 - .../usb_hid/arduino-1.0.1/cores/arduino/wiring.c | 324 ---- .../arduino-1.0.1/cores/arduino/wiring_analog.c | 282 ---- .../arduino-1.0.1/cores/arduino/wiring_digital.c | 178 --- .../arduino-1.0.1/cores/arduino/wiring_private.h | 69 - .../arduino-1.0.1/cores/arduino/wiring_pulse.c | 69 - .../arduino-1.0.1/cores/arduino/wiring_shift.c | 55 - .../variants/eightanaloginputs/pins_arduino.h | 27 - .../arduino-1.0.1/variants/leonardo/pins_arduino.h | 256 ---- .../arduino-1.0.1/variants/mega/pins_arduino.h | 363 ----- .../arduino-1.0.1/variants/standard/pins_arduino.h | 218 --- 363 files changed, 42441 insertions(+), 42441 deletions(-) create mode 100644 lib/usbhost/USB_Host_Shield_2.0/.gitattributes create mode 100644 lib/usbhost/USB_Host_Shield_2.0/.gitignore create mode 100644 lib/usbhost/USB_Host_Shield_2.0/.gitmodules create mode 100644 lib/usbhost/USB_Host_Shield_2.0/BTD.cpp create mode 100644 lib/usbhost/USB_Host_Shield_2.0/BTD.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/BTHID.cpp create mode 100644 lib/usbhost/USB_Host_Shield_2.0/BTHID.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/PS3BT.cpp create mode 100644 lib/usbhost/USB_Host_Shield_2.0/PS3BT.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/PS3Enums.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/PS3USB.cpp create mode 100644 lib/usbhost/USB_Host_Shield_2.0/PS3USB.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/PS4BT.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/PS4Parser.cpp create mode 100644 lib/usbhost/USB_Host_Shield_2.0/PS4Parser.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/PS4USB.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/PSBuzz.cpp create mode 100644 lib/usbhost/USB_Host_Shield_2.0/PSBuzz.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/README.md create mode 100644 lib/usbhost/USB_Host_Shield_2.0/SPP.cpp create mode 100644 lib/usbhost/USB_Host_Shield_2.0/SPP.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/Usb.cpp create mode 100644 lib/usbhost/USB_Host_Shield_2.0/Usb.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/UsbCore.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/Wii.cpp create mode 100644 lib/usbhost/USB_Host_Shield_2.0/Wii.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/WiiCameraReadme.md create mode 100644 lib/usbhost/USB_Host_Shield_2.0/XBOXOLD.cpp create mode 100644 lib/usbhost/USB_Host_Shield_2.0/XBOXOLD.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/XBOXONE.cpp create mode 100644 lib/usbhost/USB_Host_Shield_2.0/XBOXONE.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/XBOXRECV.cpp create mode 100644 lib/usbhost/USB_Host_Shield_2.0/XBOXRECV.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/XBOXUSB.cpp create mode 100644 lib/usbhost/USB_Host_Shield_2.0/XBOXUSB.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/address.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/adk.cpp create mode 100644 lib/usbhost/USB_Host_Shield_2.0/adk.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/avrpins.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/cdc_XR21B1411.cpp create mode 100644 lib/usbhost/USB_Host_Shield_2.0/cdc_XR21B1411.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/cdcacm.cpp create mode 100644 lib/usbhost/USB_Host_Shield_2.0/cdcacm.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/cdcftdi.cpp create mode 100644 lib/usbhost/USB_Host_Shield_2.0/cdcftdi.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/cdcprolific.cpp create mode 100644 lib/usbhost/USB_Host_Shield_2.0/cdcprolific.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/confdescparser.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/controllerEnums.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/BTHID.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/KeyboardParser.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/MouseParser.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/PS3BT/PS3BT.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/PS3Multi/PS3Multi.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/PS3SPP/PS3SPP.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/PS4BT/PS4BT.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/SPP/SPP.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/SPPMulti/SPPMulti.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/Wii/Wii.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/WiiBalanceBoard/WiiBalanceBoard.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/WiiIRCamera/WiiIRCamera.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/WiiMulti/WiiMulti.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/WiiUProController/WiiUProController.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/HID/USBHIDBootKbd/USBHIDBootKbd.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/HID/USBHIDBootKbdAndMouse/USBHIDBootKbdAndMouse.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/HID/USBHIDBootMouse/USBHIDBootMouse.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/USBHIDJoystick.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/hidjoystickrptparser.cpp create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/hidjoystickrptparser.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/HID/USBHID_desc/USBHID_desc.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/HID/USBHID_desc/pgmstrings.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp_rptparser.cpp create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp_rptparser.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/HID/scale/scale.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/HID/scale/scale_rptparser.cpp create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/HID/scale/scale_rptparser.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/PS3USB/PS3USB.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/PS4USB/PS4USB.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/PSBuzz/PSBuzz.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/USB_desc/USB_desc.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/USB_desc/pgmstrings.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/Xbox/XBOXOLD/XBOXOLD.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/Xbox/XBOXONE/XBOXONE.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/Xbox/XBOXRECV/XBOXRECV.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/Xbox/XBOXUSB/XBOXUSB.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/acm/acm_terminal/acm_terminal.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/acm/acm_terminal/pgmstrings.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/adk/ArduinoBlinkLED/ArduinoBlinkLED.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/adk/adk_barcode/adk_barcode.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/adk/demokit_20/demokit_20.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/adk/term_test/term_test.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/adk/term_time/term_time.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/board_qc/board_qc.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/cdc_XR21B1411/XR_terminal/XR_terminal.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/ftdi/USBFTDILoopback/USBFTDILoopback.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/ftdi/USBFTDILoopback/pgmstrings.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/hub_demo/hub_demo.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/hub_demo/pgmstrings.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/max_LCD/max_LCD.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/pl2303/pl2303_gprs_terminal/pl2303_gprs_terminal.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/pl2303/pl2303_gps/pl2303_gps.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/pl2303/pl2303_tinygps/pl2303_tinygps.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/pl2303/pl2303_xbee_terminal/pl2303_xbee_terminal.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/testusbhostFAT/Makefile create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/testusbhostFAT/README.md create mode 100644 lib/usbhost/USB_Host_Shield_2.0/examples/testusbhostFAT/testusbhostFAT.ino create mode 100644 lib/usbhost/USB_Host_Shield_2.0/gpl2.txt create mode 100644 lib/usbhost/USB_Host_Shield_2.0/hexdump.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/hid.cpp create mode 100644 lib/usbhost/USB_Host_Shield_2.0/hid.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/hidboot.cpp create mode 100644 lib/usbhost/USB_Host_Shield_2.0/hidboot.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/hidescriptorparser.cpp create mode 100644 lib/usbhost/USB_Host_Shield_2.0/hidescriptorparser.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/hiduniversal.cpp create mode 100644 lib/usbhost/USB_Host_Shield_2.0/hiduniversal.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/hidusagestr.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/hidusagetitlearrays.cpp create mode 100644 lib/usbhost/USB_Host_Shield_2.0/keywords.txt create mode 100644 lib/usbhost/USB_Host_Shield_2.0/library.json create mode 100644 lib/usbhost/USB_Host_Shield_2.0/library.properties create mode 100644 lib/usbhost/USB_Host_Shield_2.0/macros.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/masstorage.cpp create mode 100644 lib/usbhost/USB_Host_Shield_2.0/masstorage.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/max3421e.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/max_LCD.cpp create mode 100644 lib/usbhost/USB_Host_Shield_2.0/max_LCD.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/message.cpp create mode 100644 lib/usbhost/USB_Host_Shield_2.0/message.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/parsetools.cpp create mode 100644 lib/usbhost/USB_Host_Shield_2.0/parsetools.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/printhex.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/settings.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/sink_parser.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/usb_ch9.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/usbhost.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/usbhub.cpp create mode 100644 lib/usbhost/USB_Host_Shield_2.0/usbhub.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/version_helper.h create mode 100644 lib/usbhost/USB_Host_Shield_2.0/xboxEnums.h create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/Arduino.h create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/CDC.cpp create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/Client.h create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/HID.cpp create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/HardwareSerial.cpp create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/HardwareSerial.h create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/IPAddress.cpp create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/IPAddress.h create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/Platform.h create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/Print.cpp create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/Print.h create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/Printable.h create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/Server.h create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/Stream.cpp create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/Stream.h create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/Tone.cpp create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/USBAPI.h create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/USBCore.cpp create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/USBCore.h create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/USBDesc.h create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/Udp.h create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/WCharacter.h create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/WInterrupts.c create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/WMath.cpp create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/WString.cpp create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/WString.h create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/binary.h create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/main.cpp create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/new.cpp create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/new.h create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/wiring.c create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/wiring_analog.c create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/wiring_digital.c create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/wiring_private.h create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/wiring_pulse.c create mode 100644 lib/usbhost/arduino-1.0.1/cores/arduino/wiring_shift.c create mode 100644 lib/usbhost/arduino-1.0.1/variants/eightanaloginputs/pins_arduino.h create mode 100644 lib/usbhost/arduino-1.0.1/variants/leonardo/pins_arduino.h create mode 100644 lib/usbhost/arduino-1.0.1/variants/mega/pins_arduino.h create mode 100644 lib/usbhost/arduino-1.0.1/variants/standard/pins_arduino.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/.gitattributes delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/.gitignore delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/.gitmodules delete mode 100755 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/BTD.cpp delete mode 100755 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/BTD.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/BTHID.cpp delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/BTHID.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3BT.cpp delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3BT.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3Enums.h delete mode 100755 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3USB.cpp delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3USB.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS4BT.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS4Parser.cpp delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS4Parser.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS4USB.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PSBuzz.cpp delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PSBuzz.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/README.md delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/SPP.cpp delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/SPP.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/Usb.cpp delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/Usb.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/UsbCore.h delete mode 100755 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/Wii.cpp delete mode 100755 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/Wii.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/WiiCameraReadme.md delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXOLD.cpp delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXOLD.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXONE.cpp delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXONE.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXRECV.cpp delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXRECV.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXUSB.cpp delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXUSB.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/address.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/adk.cpp delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/adk.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/avrpins.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdc_XR21B1411.cpp delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdc_XR21B1411.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcacm.cpp delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcacm.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcftdi.cpp delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcftdi.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcprolific.cpp delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcprolific.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/confdescparser.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/controllerEnums.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/BTHID.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/KeyboardParser.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/MouseParser.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/PS3BT/PS3BT.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/PS3Multi/PS3Multi.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/PS3SPP/PS3SPP.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/PS4BT/PS4BT.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/SPP/SPP.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/SPPMulti/SPPMulti.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/Wii/Wii.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/WiiBalanceBoard/WiiBalanceBoard.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/WiiIRCamera/WiiIRCamera.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/WiiMulti/WiiMulti.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/WiiUProController/WiiUProController.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDBootKbd/USBHIDBootKbd.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDBootKbdAndMouse/USBHIDBootKbdAndMouse.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDBootMouse/USBHIDBootMouse.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/USBHIDJoystick.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/hidjoystickrptparser.cpp delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/hidjoystickrptparser.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHID_desc/USBHID_desc.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHID_desc/pgmstrings.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp_rptparser.cpp delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp_rptparser.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/scale/scale.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/scale/scale_rptparser.cpp delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/scale/scale_rptparser.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/PS3USB/PS3USB.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/PS4USB/PS4USB.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/PSBuzz/PSBuzz.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/USB_desc/USB_desc.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/USB_desc/pgmstrings.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Xbox/XBOXOLD/XBOXOLD.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Xbox/XBOXONE/XBOXONE.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Xbox/XBOXRECV/XBOXRECV.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Xbox/XBOXUSB/XBOXUSB.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/acm/acm_terminal/acm_terminal.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/acm/acm_terminal/pgmstrings.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/ArduinoBlinkLED/ArduinoBlinkLED.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/adk_barcode/adk_barcode.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/demokit_20/demokit_20.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/term_test/term_test.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/term_time/term_time.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/board_qc/board_qc.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/cdc_XR21B1411/XR_terminal/XR_terminal.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/ftdi/USBFTDILoopback/USBFTDILoopback.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/ftdi/USBFTDILoopback/pgmstrings.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/hub_demo/hub_demo.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/hub_demo/pgmstrings.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/max_LCD/max_LCD.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/pl2303/pl2303_gprs_terminal/pl2303_gprs_terminal.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/pl2303/pl2303_gps/pl2303_gps.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/pl2303/pl2303_tinygps/pl2303_tinygps.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/pl2303/pl2303_xbee_terminal/pl2303_xbee_terminal.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/testusbhostFAT/Makefile delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/testusbhostFAT/README.md delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/testusbhostFAT/testusbhostFAT.ino delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/gpl2.txt delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hexdump.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hid.cpp delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hid.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidboot.cpp delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidboot.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidescriptorparser.cpp delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidescriptorparser.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hiduniversal.cpp delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hiduniversal.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidusagestr.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidusagetitlearrays.cpp delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/keywords.txt delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/library.json delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/library.properties delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/macros.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/masstorage.cpp delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/masstorage.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/max3421e.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/max_LCD.cpp delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/max_LCD.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/message.cpp delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/message.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/parsetools.cpp delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/parsetools.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/printhex.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/settings.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/sink_parser.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/usb_ch9.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/usbhost.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/usbhub.cpp delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/usbhub.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/version_helper.h delete mode 100644 tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/xboxEnums.h delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Arduino.h delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/CDC.cpp delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Client.h delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/HID.cpp delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/HardwareSerial.cpp delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/HardwareSerial.h delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/IPAddress.cpp delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/IPAddress.h delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Platform.h delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Print.cpp delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Print.h delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Printable.h delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Server.h delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Stream.cpp delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Stream.h delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Tone.cpp delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/USBAPI.h delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/USBCore.cpp delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/USBCore.h delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/USBDesc.h delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Udp.h delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WCharacter.h delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WInterrupts.c delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WMath.cpp delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WString.cpp delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WString.h delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/binary.h delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/main.cpp delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/new.cpp delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/new.h delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring.c delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_analog.c delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_digital.c delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_private.h delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_pulse.c delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_shift.c delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/variants/eightanaloginputs/pins_arduino.h delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/variants/leonardo/pins_arduino.h delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/variants/mega/pins_arduino.h delete mode 100644 tmk_core/protocol/usb_hid/arduino-1.0.1/variants/standard/pins_arduino.h (limited to 'tmk_core') diff --git a/lib/usbhost/USB_Host_Shield_2.0/.gitattributes b/lib/usbhost/USB_Host_Shield_2.0/.gitattributes new file mode 100644 index 0000000000..6238b035a3 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/.gitattributes @@ -0,0 +1,23 @@ +# Auto detect text files and perform LF normalization +* text=auto +* text eol=lf + +# Custom for Visual Studio +*.cs diff=csharp +*.sln merge=union +*.csproj merge=union +*.vbproj merge=union +*.fsproj merge=union +*.dbproj merge=union + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/lib/usbhost/USB_Host_Shield_2.0/.gitignore b/lib/usbhost/USB_Host_Shield_2.0/.gitignore new file mode 100644 index 0000000000..7e69f457ba --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/.gitignore @@ -0,0 +1,4 @@ +*.bak +*.zip +*.rar +build/ \ No newline at end of file diff --git a/lib/usbhost/USB_Host_Shield_2.0/.gitmodules b/lib/usbhost/USB_Host_Shield_2.0/.gitmodules new file mode 100644 index 0000000000..32a0783a89 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/.gitmodules @@ -0,0 +1,12 @@ +[submodule "examples/testusbhostFAT/generic_storage"] + path = examples/testusbhostFAT/generic_storage + url = https://github.com/xxxajk/generic_storage +[submodule "examples/testusbhostFAT/xmem2"] + path = examples/testusbhostFAT/xmem2 + url = https://github.com/xxxajk/xmem2 +[submodule "examples/testusbhostFAT/Arduino_Makefile_master"] + path = examples/testusbhostFAT/Arduino_Makefile_master + url = https://github.com/xxxajk/Arduino_Makefile_master +[submodule "examples/testusbhostFAT/RTClib"] + path = examples/testusbhostFAT/RTClib + url = https://github.com/xxxajk/RTClib diff --git a/lib/usbhost/USB_Host_Shield_2.0/BTD.cpp b/lib/usbhost/USB_Host_Shield_2.0/BTD.cpp new file mode 100644 index 0000000000..bcfba14b2b --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/BTD.cpp @@ -0,0 +1,1364 @@ +/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. + + This software may be distributed and modified under the terms of the GNU + General Public License version 2 (GPL2) as published by the Free Software + Foundation and appearing in the file GPL2.TXT included in the packaging of + this file. Please note that GPL2 Section 2[b] requires that all works based + on this software must also be made publicly available under the terms of + the GPL2 ("Copyleft"). + + Contact information + ------------------- + + Kristian Lauszus, TKJ Electronics + Web : http://www.tkjelectronics.com + e-mail : kristianl@tkjelectronics.com + */ + +#include "BTD.h" +// To enable serial debugging see "settings.h" +//#define EXTRADEBUG // Uncomment to get even more debugging data + +const uint8_t BTD::BTD_CONTROL_PIPE = 0; +const uint8_t BTD::BTD_EVENT_PIPE = 1; +const uint8_t BTD::BTD_DATAIN_PIPE = 2; +const uint8_t BTD::BTD_DATAOUT_PIPE = 3; + +BTD::BTD(USB *p) : +connectToWii(false), +pairWithWii(false), +connectToHIDDevice(false), +pairWithHIDDevice(false), +pUsb(p), // Pointer to USB class instance - mandatory +bAddress(0), // Device address - mandatory +bNumEP(1), // If config descriptor needs to be parsed +qNextPollTime(0), // Reset NextPollTime +pollInterval(0), +bPollEnable(false) // Don't start polling before dongle is connected +{ + for(uint8_t i = 0; i < BTD_NUM_SERVICES; i++) + btService[i] = NULL; + + Initialize(); // Set all variables, endpoint structs etc. to default values + + if(pUsb) // Register in USB subsystem + pUsb->RegisterDeviceClass(this); // Set devConfig[] entry +} + +uint8_t BTD::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) { + const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR); + uint8_t buf[constBufSize]; + USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + + Initialize(); // Set all variables, endpoint structs etc. to default values + + AddressPool &addrPool = pUsb->GetAddressPool(); // Get memory address of USB device address pool +#ifdef EXTRADEBUG + Notify(PSTR("\r\nBTD ConfigureDevice"), 0x80); +#endif + + if(bAddress) { // Check if address has already been assigned to an instance +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nAddress in use"), 0x80); +#endif + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; + } + + p = addrPool.GetUsbDevicePtr(0); // Get pointer to pseudo device with address 0 assigned + if(!p) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nAddress not found"), 0x80); +#endif + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + } + + if(!p->epinfo) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nepinfo is null"), 0x80); +#endif + return USB_ERROR_EPINFO_IS_NULL; + } + + oldep_ptr = p->epinfo; // Save old pointer to EP_RECORD of address 0 + p->epinfo = epInfo; // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence + p->lowspeed = lowspeed; + rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data + + p->epinfo = oldep_ptr; // Restore p->epinfo + + if(rcode) + goto FailGetDevDescr; + + bAddress = addrPool.AllocAddress(parent, false, port); // Allocate new address according to device class + + if(!bAddress) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nOut of address space"), 0x80); +#endif + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + } + + epInfo[0].maxPktSize = udd->bMaxPacketSize0; // Extract Max Packet Size from device descriptor + epInfo[1].epAddr = udd->bNumConfigurations; // Steal and abuse from epInfo structure to save memory + + VID = udd->idVendor; + PID = udd->idProduct; + + return USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET; + +FailGetDevDescr: +#ifdef DEBUG_USB_HOST + NotifyFailGetDevDescr(rcode); +#endif + if(rcode != hrJERR) + rcode = USB_ERROR_FailGetDevDescr; + Release(); + return rcode; +}; + +uint8_t BTD::Init(uint8_t parent, uint8_t port, bool lowspeed) { + uint8_t rcode; + uint8_t num_of_conf = epInfo[1].epAddr; // Number of configurations + epInfo[1].epAddr = 0; + + AddressPool &addrPool = pUsb->GetAddressPool(); +#ifdef EXTRADEBUG + Notify(PSTR("\r\nBTD Init"), 0x80); +#endif + UsbDevice *p = addrPool.GetUsbDevicePtr(bAddress); // Get pointer to assigned address record + + if(!p) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nAddress not found"), 0x80); +#endif + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + } + + delay(300); // Assign new address to the device + + rcode = pUsb->setAddr(0, 0, bAddress); // Assign new address to the device + if(rcode) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nsetAddr: "), 0x80); + D_PrintHex (rcode, 0x80); +#endif + p->lowspeed = false; + goto Fail; + } +#ifdef EXTRADEBUG + Notify(PSTR("\r\nAddr: "), 0x80); + D_PrintHex (bAddress, 0x80); +#endif + + p->lowspeed = false; + + p = addrPool.GetUsbDevicePtr(bAddress); // Get pointer to assigned address record + if(!p) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nAddress not found"), 0x80); +#endif + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + } + + p->lowspeed = lowspeed; + + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); // Assign epInfo to epinfo pointer - only EP0 is known + if(rcode) + goto FailSetDevTblEntry; + + if(VID == PS3_VID && (PID == PS3_PID || PID == PS3NAVIGATION_PID || PID == PS3MOVE_PID)) { + delay(100); + rcode = pUsb->setConf(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, 1); // We only need the Control endpoint, so we don't have to initialize the other endpoints of device + if(rcode) + goto FailSetConfDescr; + +#ifdef DEBUG_USB_HOST + if(PID == PS3_PID || PID == PS3NAVIGATION_PID) { + if(PID == PS3_PID) + Notify(PSTR("\r\nDualshock 3 Controller Connected"), 0x80); + else // It must be a navigation controller + Notify(PSTR("\r\nNavigation Controller Connected"), 0x80); + } else // It must be a Motion controller + Notify(PSTR("\r\nMotion Controller Connected"), 0x80); +#endif + + if(my_bdaddr[0] == 0x00 && my_bdaddr[1] == 0x00 && my_bdaddr[2] == 0x00 && my_bdaddr[3] == 0x00 && my_bdaddr[4] == 0x00 && my_bdaddr[5] == 0x00) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nPlease plug in the dongle before trying to pair with the PS3 Controller\r\nor set the Bluetooth address in the constructor of the PS3BT class"), 0x80); +#endif + } else { + if(PID == PS3_PID || PID == PS3NAVIGATION_PID) + setBdaddr(my_bdaddr); // Set internal Bluetooth address + else + setMoveBdaddr(my_bdaddr); // Set internal Bluetooth address +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nBluetooth Address was set to: "), 0x80); + for(int8_t i = 5; i > 0; i--) { + D_PrintHex (my_bdaddr[i], 0x80); + Notify(PSTR(":"), 0x80); + } + D_PrintHex (my_bdaddr[0], 0x80); +#endif + } + + pUsb->setConf(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, 0); // Reset configuration value + pUsb->setAddr(bAddress, 0, 0); // Reset address + Release(); // Release device + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; // Return + } else { + // Check if attached device is a Bluetooth dongle and fill endpoint data structure + // First interface in the configuration must have Bluetooth assigned Class/Subclass/Protocol + // And 3 endpoints - interrupt-IN, bulk-IN, bulk-OUT, not necessarily in this order + for(uint8_t i = 0; i < num_of_conf; i++) { + if(VID == IOGEAR_GBU521_VID && PID == IOGEAR_GBU521_PID) { + ConfigDescParser confDescrParser(this); // Needed for the IOGEAR GBU521 + rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); + } else { + ConfigDescParser confDescrParser(this); + rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); + } + if(rcode) // Check error code + goto FailGetConfDescr; + if(bNumEP >= BTD_MAX_ENDPOINTS) // All endpoints extracted + break; + } + + if(bNumEP < BTD_MAX_ENDPOINTS) + goto FailUnknownDevice; + + // Assign epInfo to epinfo pointer - this time all 3 endpoins + rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); + if(rcode) + goto FailSetDevTblEntry; + + // Set Configuration Value + rcode = pUsb->setConf(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, bConfNum); + if(rcode) + goto FailSetConfDescr; + + hci_num_reset_loops = 100; // only loop 100 times before trying to send the hci reset command + hci_counter = 0; + hci_state = HCI_INIT_STATE; + watingForConnection = false; + bPollEnable = true; + +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nBluetooth Dongle Initialized"), 0x80); +#endif + } + return 0; // Successful configuration + + /* Diagnostic messages */ +FailSetDevTblEntry: +#ifdef DEBUG_USB_HOST + NotifyFailSetDevTblEntry(); + goto Fail; +#endif + +FailGetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailGetConfDescr(); + goto Fail; +#endif + +FailSetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailSetConfDescr(); +#endif + goto Fail; + +FailUnknownDevice: +#ifdef DEBUG_USB_HOST + NotifyFailUnknownDevice(VID, PID); +#endif + pUsb->setAddr(bAddress, 0, 0); // Reset address + rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; +Fail: +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nBTD Init Failed, error code: "), 0x80); + NotifyFail(rcode); +#endif + Release(); + return rcode; +} + +void BTD::Initialize() { + uint8_t i; + for(i = 0; i < BTD_MAX_ENDPOINTS; i++) { + epInfo[i].epAddr = 0; + epInfo[i].maxPktSize = (i) ? 0 : 8; + epInfo[i].epAttribs = 0; + epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; + } + for(i = 0; i < BTD_NUM_SERVICES; i++) { + if(btService[i]) + btService[i]->Reset(); // Reset all Bluetooth services + } + + connectToWii = false; + incomingWii = false; + connectToHIDDevice = false; + incomingHIDDevice = false; + incomingPS4 = false; + bAddress = 0; // Clear device address + bNumEP = 1; // Must have to be reset to 1 + qNextPollTime = 0; // Reset next poll time + pollInterval = 0; + bPollEnable = false; // Don't start polling before dongle is connected +} + +/* Extracts interrupt-IN, bulk-IN, bulk-OUT endpoint information from config descriptor */ +void BTD::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) { + //ErrorMessage(PSTR("Conf.Val"),conf); + //ErrorMessage(PSTR("Iface Num"),iface); + //ErrorMessage(PSTR("Alt.Set"),alt); + + if(alt) // Wrong interface - by BT spec, no alt setting + return; + + bConfNum = conf; + uint8_t index; + + if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) { // Interrupt In endpoint found + index = BTD_EVENT_PIPE; + epInfo[index].bmNakPower = USB_NAK_NOWAIT; + } else { + if((pep->bmAttributes & 0x02) == 2) // Bulk endpoint found + index = ((pep->bEndpointAddress & 0x80) == 0x80) ? BTD_DATAIN_PIPE : BTD_DATAOUT_PIPE; + else + return; + } + + // Fill the rest of endpoint data structure + epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); + epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; +#ifdef EXTRADEBUG + PrintEndpointDescriptor(pep); +#endif + if(pollInterval < pep->bInterval) // Set the polling interval as the largest polling interval obtained from endpoints + pollInterval = pep->bInterval; + bNumEP++; +} + +void BTD::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) { +#ifdef EXTRADEBUG + Notify(PSTR("\r\nEndpoint descriptor:"), 0x80); + Notify(PSTR("\r\nLength:\t\t"), 0x80); + D_PrintHex (ep_ptr->bLength, 0x80); + Notify(PSTR("\r\nType:\t\t"), 0x80); + D_PrintHex (ep_ptr->bDescriptorType, 0x80); + Notify(PSTR("\r\nAddress:\t"), 0x80); + D_PrintHex (ep_ptr->bEndpointAddress, 0x80); + Notify(PSTR("\r\nAttributes:\t"), 0x80); + D_PrintHex (ep_ptr->bmAttributes, 0x80); + Notify(PSTR("\r\nMaxPktSize:\t"), 0x80); + D_PrintHex (ep_ptr->wMaxPacketSize, 0x80); + Notify(PSTR("\r\nPoll Intrv:\t"), 0x80); + D_PrintHex (ep_ptr->bInterval, 0x80); +#endif +} + +/* Performs a cleanup after failed Init() attempt */ +uint8_t BTD::Release() { + Initialize(); // Set all variables, endpoint structs etc. to default values + pUsb->GetAddressPool().FreeAddress(bAddress); + return 0; +} + +uint8_t BTD::Poll() { + if(!bPollEnable) + return 0; + if((long)(millis() - qNextPollTime) >= 0L) { // Don't poll if shorter than polling interval + qNextPollTime = millis() + pollInterval; // Set new poll time + HCI_event_task(); // Poll the HCI event pipe + HCI_task(); // HCI state machine + ACL_event_task(); // Poll the ACL input pipe too + } + return 0; +} + +void BTD::disconnect() { + for(uint8_t i = 0; i < BTD_NUM_SERVICES; i++) + if(btService[i]) + btService[i]->disconnect(); +}; + +void BTD::HCI_event_task() { + uint16_t length = BULK_MAXPKTSIZE; // Request more than 16 bytes anyway, the inTransfer routine will take care of this + uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[ BTD_EVENT_PIPE ].epAddr, &length, hcibuf); // Input on endpoint 1 + + if(!rcode || rcode == hrNAK) { // Check for errors + switch(hcibuf[0]) { // Switch on event type + case EV_COMMAND_COMPLETE: + if(!hcibuf[5]) { // Check if command succeeded + hci_set_flag(HCI_FLAG_CMD_COMPLETE); // Set command complete flag + if((hcibuf[3] == 0x01) && (hcibuf[4] == 0x10)) { // Parameters from read local version information + hci_version = hcibuf[6]; // Used to check if it supports 2.0+EDR - see http://www.bluetooth.org/Technical/AssignedNumbers/hci.htm + hci_set_flag(HCI_FLAG_READ_VERSION); + } else if((hcibuf[3] == 0x09) && (hcibuf[4] == 0x10)) { // Parameters from read local bluetooth address + for(uint8_t i = 0; i < 6; i++) + my_bdaddr[i] = hcibuf[6 + i]; + hci_set_flag(HCI_FLAG_READ_BDADDR); + } + } + break; + + case EV_COMMAND_STATUS: + if(hcibuf[2]) { // Show status on serial if not OK +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nHCI Command Failed: "), 0x80); + D_PrintHex (hcibuf[2], 0x80); +#endif + } + break; + + case EV_INQUIRY_COMPLETE: + if(inquiry_counter >= 5 && (pairWithWii || pairWithHIDDevice)) { + inquiry_counter = 0; +#ifdef DEBUG_USB_HOST + if(pairWithWii) + Notify(PSTR("\r\nCouldn't find Wiimote"), 0x80); + else + Notify(PSTR("\r\nCouldn't find HID device"), 0x80); +#endif + connectToWii = false; + pairWithWii = false; + connectToHIDDevice = false; + pairWithHIDDevice = false; + hci_state = HCI_SCANNING_STATE; + } + inquiry_counter++; + break; + + case EV_INQUIRY_RESULT: + if(hcibuf[2]) { // Check that there is more than zero responses +#ifdef EXTRADEBUG + Notify(PSTR("\r\nNumber of responses: "), 0x80); + Notify(hcibuf[2], 0x80); +#endif + for(uint8_t i = 0; i < hcibuf[2]; i++) { + uint8_t offset = 8 * hcibuf[2] + 3 * i; + + for(uint8_t j = 0; j < 3; j++) + classOfDevice[j] = hcibuf[j + 4 + offset]; + +#ifdef EXTRADEBUG + Notify(PSTR("\r\nClass of device: "), 0x80); + D_PrintHex (classOfDevice[2], 0x80); + Notify(PSTR(" "), 0x80); + D_PrintHex (classOfDevice[1], 0x80); + Notify(PSTR(" "), 0x80); + D_PrintHex (classOfDevice[0], 0x80); +#endif + + if(pairWithWii && classOfDevice[2] == 0x00 && (classOfDevice[1] & 0x05) && (classOfDevice[0] & 0x0C)) { // See http://wiibrew.org/wiki/Wiimote#SDP_information + checkRemoteName = true; // Check remote name to distinguish between the different controllers + + for(uint8_t j = 0; j < 6; j++) + disc_bdaddr[j] = hcibuf[j + 3 + 6 * i]; + + hci_set_flag(HCI_FLAG_DEVICE_FOUND); + break; + } else if(pairWithHIDDevice && (classOfDevice[1] & 0x05) && (classOfDevice[0] & 0xC8)) { // Check if it is a mouse, keyboard or a gamepad - see: http://bluetooth-pentest.narod.ru/software/bluetooth_class_of_device-service_generator.html +#ifdef DEBUG_USB_HOST + if(classOfDevice[0] & 0x80) + Notify(PSTR("\r\nMouse found"), 0x80); + if(classOfDevice[0] & 0x40) + Notify(PSTR("\r\nKeyboard found"), 0x80); + if(classOfDevice[0] & 0x08) + Notify(PSTR("\r\nGamepad found"), 0x80); +#endif + + for(uint8_t j = 0; j < 6; j++) + disc_bdaddr[j] = hcibuf[j + 3 + 6 * i]; + + hci_set_flag(HCI_FLAG_DEVICE_FOUND); + break; + } + } + } + break; + + case EV_CONNECT_COMPLETE: + hci_set_flag(HCI_FLAG_CONNECT_EVENT); + if(!hcibuf[2]) { // Check if connected OK +#ifdef EXTRADEBUG + Notify(PSTR("\r\nConnection established"), 0x80); +#endif + hci_handle = hcibuf[3] | ((hcibuf[4] & 0x0F) << 8); // Store the handle for the ACL connection + hci_set_flag(HCI_FLAG_CONNECT_COMPLETE); // Set connection complete flag + } else { + hci_state = HCI_CHECK_DEVICE_SERVICE; +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nConnection Failed: "), 0x80); + D_PrintHex (hcibuf[2], 0x80); +#endif + } + break; + + case EV_DISCONNECT_COMPLETE: + if(!hcibuf[2]) { // Check if disconnected OK + hci_set_flag(HCI_FLAG_DISCONNECT_COMPLETE); // Set disconnect command complete flag + hci_clear_flag(HCI_FLAG_CONNECT_COMPLETE); // Clear connection complete flag + } + break; + + case EV_REMOTE_NAME_COMPLETE: + if(!hcibuf[2]) { // Check if reading is OK + for(uint8_t i = 0; i < min(sizeof (remote_name), sizeof (hcibuf) - 9); i++) { + remote_name[i] = hcibuf[9 + i]; + if(remote_name[i] == '\0') // End of string + break; + } + // TODO: Altid sæt '\0' i remote name! + hci_set_flag(HCI_FLAG_REMOTE_NAME_COMPLETE); + } + break; + + case EV_INCOMING_CONNECT: + for(uint8_t i = 0; i < 6; i++) + disc_bdaddr[i] = hcibuf[i + 2]; + + for(uint8_t i = 0; i < 3; i++) + classOfDevice[i] = hcibuf[i + 8]; + + if((classOfDevice[1] & 0x05) && (classOfDevice[0] & 0xC8)) { // Check if it is a mouse, keyboard or a gamepad +#ifdef DEBUG_USB_HOST + if(classOfDevice[0] & 0x80) + Notify(PSTR("\r\nMouse is connecting"), 0x80); + if(classOfDevice[0] & 0x40) + Notify(PSTR("\r\nKeyboard is connecting"), 0x80); + if(classOfDevice[0] & 0x08) + Notify(PSTR("\r\nGamepad is connecting"), 0x80); +#endif + incomingHIDDevice = true; + } + +#ifdef EXTRADEBUG + Notify(PSTR("\r\nClass of device: "), 0x80); + D_PrintHex (classOfDevice[2], 0x80); + Notify(PSTR(" "), 0x80); + D_PrintHex (classOfDevice[1], 0x80); + Notify(PSTR(" "), 0x80); + D_PrintHex (classOfDevice[0], 0x80); +#endif + hci_set_flag(HCI_FLAG_INCOMING_REQUEST); + break; + + case EV_PIN_CODE_REQUEST: + if(pairWithWii) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nPairing with Wiimote"), 0x80); +#endif + hci_pin_code_request_reply(); + } else if(btdPin != NULL) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nBluetooth pin is set too: "), 0x80); + NotifyStr(btdPin, 0x80); +#endif + hci_pin_code_request_reply(); + } else { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nNo pin was set"), 0x80); +#endif + hci_pin_code_negative_request_reply(); + } + break; + + case EV_LINK_KEY_REQUEST: +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nReceived Key Request"), 0x80); +#endif + hci_link_key_request_negative_reply(); + break; + + case EV_AUTHENTICATION_COMPLETE: + if(pairWithWii && !connectToWii) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nPairing successful with Wiimote"), 0x80); +#endif + connectToWii = true; // Used to indicate to the Wii service, that it should connect to this device + } else if(pairWithHIDDevice && !connectToHIDDevice) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nPairing successful with HID device"), 0x80); +#endif + connectToHIDDevice = true; // Used to indicate to the BTHID service, that it should connect to this device + } + break; + /* We will just ignore the following events */ + case EV_NUM_COMPLETE_PKT: + case EV_ROLE_CHANGED: + case EV_PAGE_SCAN_REP_MODE: + case EV_LOOPBACK_COMMAND: + case EV_DATA_BUFFER_OVERFLOW: + case EV_CHANGE_CONNECTION_LINK: + case EV_MAX_SLOTS_CHANGE: + case EV_QOS_SETUP_COMPLETE: + case EV_LINK_KEY_NOTIFICATION: + case EV_ENCRYPTION_CHANGE: + case EV_READ_REMOTE_VERSION_INFORMATION_COMPLETE: + break; +#ifdef EXTRADEBUG + default: + if(hcibuf[0] != 0x00) { + Notify(PSTR("\r\nUnmanaged HCI Event: "), 0x80); + D_PrintHex (hcibuf[0], 0x80); + } + break; +#endif + } // Switch + } +#ifdef EXTRADEBUG + else { + Notify(PSTR("\r\nHCI event error: "), 0x80); + D_PrintHex (rcode, 0x80); + } +#endif +} + +/* Poll Bluetooth and print result */ +void BTD::HCI_task() { + switch(hci_state) { + case HCI_INIT_STATE: + hci_counter++; + if(hci_counter > hci_num_reset_loops) { // wait until we have looped x times to clear any old events + hci_reset(); + hci_state = HCI_RESET_STATE; + hci_counter = 0; + } + break; + + case HCI_RESET_STATE: + hci_counter++; + if(hci_check_flag(HCI_FLAG_CMD_COMPLETE)) { + hci_counter = 0; +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nHCI Reset complete"), 0x80); +#endif + hci_state = HCI_CLASS_STATE; + hci_write_class_of_device(); + } else if(hci_counter > hci_num_reset_loops) { + hci_num_reset_loops *= 10; + if(hci_num_reset_loops > 2000) + hci_num_reset_loops = 2000; +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nNo response to HCI Reset"), 0x80); +#endif + hci_state = HCI_INIT_STATE; + hci_counter = 0; + } + break; + + case HCI_CLASS_STATE: + if(hci_check_flag(HCI_FLAG_CMD_COMPLETE)) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nWrite class of device"), 0x80); +#endif + hci_state = HCI_BDADDR_STATE; + hci_read_bdaddr(); + } + break; + + case HCI_BDADDR_STATE: + if(hci_check_flag(HCI_FLAG_READ_BDADDR)) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nLocal Bluetooth Address: "), 0x80); + for(int8_t i = 5; i > 0; i--) { + D_PrintHex (my_bdaddr[i], 0x80); + Notify(PSTR(":"), 0x80); + } + D_PrintHex (my_bdaddr[0], 0x80); +#endif + hci_read_local_version_information(); + hci_state = HCI_LOCAL_VERSION_STATE; + } + break; + + case HCI_LOCAL_VERSION_STATE: // The local version is used by the PS3BT class + if(hci_check_flag(HCI_FLAG_READ_VERSION)) { + if(btdName != NULL) { + hci_set_local_name(btdName); + hci_state = HCI_SET_NAME_STATE; + } else + hci_state = HCI_CHECK_DEVICE_SERVICE; + } + break; + + case HCI_SET_NAME_STATE: + if(hci_check_flag(HCI_FLAG_CMD_COMPLETE)) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nThe name is set to: "), 0x80); + NotifyStr(btdName, 0x80); +#endif + hci_state = HCI_CHECK_DEVICE_SERVICE; + } + break; + + case HCI_CHECK_DEVICE_SERVICE: + if(pairWithHIDDevice || pairWithWii) { // Check if it should try to connect to a Wiimote +#ifdef DEBUG_USB_HOST + if(pairWithWii) + Notify(PSTR("\r\nStarting inquiry\r\nPress 1 & 2 on the Wiimote\r\nOr press the SYNC button if you are using a Wii U Pro Controller or a Wii Balance Board"), 0x80); + else + Notify(PSTR("\r\nPlease enable discovery of your device"), 0x80); +#endif + hci_inquiry(); + hci_state = HCI_INQUIRY_STATE; + } else + hci_state = HCI_SCANNING_STATE; // Don't try to connect to a Wiimote + break; + + case HCI_INQUIRY_STATE: + if(hci_check_flag(HCI_FLAG_DEVICE_FOUND)) { + hci_inquiry_cancel(); // Stop inquiry +#ifdef DEBUG_USB_HOST + if(pairWithWii) + Notify(PSTR("\r\nWiimote found"), 0x80); + else + Notify(PSTR("\r\nHID device found"), 0x80); + + Notify(PSTR("\r\nNow just create the instance like so:"), 0x80); + if(pairWithWii) + Notify(PSTR("\r\nWII Wii(&Btd);"), 0x80); + else + Notify(PSTR("\r\nBTHID bthid(&Btd);"), 0x80); + + Notify(PSTR("\r\nAnd then press any button on the "), 0x80); + if(pairWithWii) + Notify(PSTR("Wiimote"), 0x80); + else + Notify(PSTR("device"), 0x80); +#endif + if(checkRemoteName) { + hci_remote_name(); // We need to know the name to distinguish between the Wiimote, the new Wiimote with Motion Plus inside, a Wii U Pro Controller and a Wii Balance Board + hci_state = HCI_REMOTE_NAME_STATE; + } else + hci_state = HCI_CONNECT_DEVICE_STATE; + } + break; + + case HCI_CONNECT_DEVICE_STATE: + if(hci_check_flag(HCI_FLAG_CMD_COMPLETE)) { +#ifdef DEBUG_USB_HOST + if(pairWithWii) + Notify(PSTR("\r\nConnecting to Wiimote"), 0x80); + else + Notify(PSTR("\r\nConnecting to HID device"), 0x80); +#endif + checkRemoteName = false; + hci_connect(); + hci_state = HCI_CONNECTED_DEVICE_STATE; + } + break; + + case HCI_CONNECTED_DEVICE_STATE: + if(hci_check_flag(HCI_FLAG_CONNECT_EVENT)) { + if(hci_check_flag(HCI_FLAG_CONNECT_COMPLETE)) { +#ifdef DEBUG_USB_HOST + if(pairWithWii) + Notify(PSTR("\r\nConnected to Wiimote"), 0x80); + else + Notify(PSTR("\r\nConnected to HID device"), 0x80); +#endif + hci_authentication_request(); // This will start the pairing with the Wiimote + hci_state = HCI_SCANNING_STATE; + } else { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nTrying to connect one more time..."), 0x80); +#endif + hci_connect(); // Try to connect one more time + } + } + break; + + case HCI_SCANNING_STATE: + if(!connectToWii && !pairWithWii && !connectToHIDDevice && !pairWithHIDDevice) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nWait For Incoming Connection Request"), 0x80); +#endif + hci_write_scan_enable(); + watingForConnection = true; + hci_state = HCI_CONNECT_IN_STATE; + } + break; + + case HCI_CONNECT_IN_STATE: + if(hci_check_flag(HCI_FLAG_INCOMING_REQUEST)) { + watingForConnection = false; +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nIncoming Connection Request"), 0x80); +#endif + hci_remote_name(); + hci_state = HCI_REMOTE_NAME_STATE; + } else if(hci_check_flag(HCI_FLAG_DISCONNECT_COMPLETE)) + hci_state = HCI_DISCONNECT_STATE; + break; + + case HCI_REMOTE_NAME_STATE: + if(hci_check_flag(HCI_FLAG_REMOTE_NAME_COMPLETE)) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nRemote Name: "), 0x80); + for(uint8_t i = 0; i < strlen(remote_name); i++) + Notifyc(remote_name[i], 0x80); +#endif + if(strncmp((const char*)remote_name, "Nintendo", 8) == 0) { + incomingWii = true; + motionPlusInside = false; + wiiUProController = false; + pairWiiUsingSync = false; +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nWiimote is connecting"), 0x80); +#endif + if(strncmp((const char*)remote_name, "Nintendo RVL-CNT-01-TR", 22) == 0) { +#ifdef DEBUG_USB_HOST + Notify(PSTR(" with Motion Plus Inside"), 0x80); +#endif + motionPlusInside = true; + } else if(strncmp((const char*)remote_name, "Nintendo RVL-CNT-01-UC", 22) == 0) { +#ifdef DEBUG_USB_HOST + Notify(PSTR(" - Wii U Pro Controller"), 0x80); +#endif + wiiUProController = motionPlusInside = pairWiiUsingSync = true; + } else if(strncmp((const char*)remote_name, "Nintendo RVL-WBC-01", 19) == 0) { +#ifdef DEBUG_USB_HOST + Notify(PSTR(" - Wii Balance Board"), 0x80); +#endif + pairWiiUsingSync = true; + } + } + if(classOfDevice[2] == 0 && classOfDevice[1] == 0x25 && classOfDevice[0] == 0x08 && strncmp((const char*)remote_name, "Wireless Controller", 19) == 0) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nPS4 controller is connecting"), 0x80); +#endif + incomingPS4 = true; + } + if(pairWithWii && checkRemoteName) + hci_state = HCI_CONNECT_DEVICE_STATE; + else { + hci_accept_connection(); + hci_state = HCI_CONNECTED_STATE; + } + } + break; + + case HCI_CONNECTED_STATE: + if(hci_check_flag(HCI_FLAG_CONNECT_COMPLETE)) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nConnected to Device: "), 0x80); + for(int8_t i = 5; i > 0; i--) { + D_PrintHex (disc_bdaddr[i], 0x80); + Notify(PSTR(":"), 0x80); + } + D_PrintHex (disc_bdaddr[0], 0x80); +#endif + if(incomingPS4) + connectToHIDDevice = true; // We should always connect to the PS4 controller + + // Clear these flags for a new connection + l2capConnectionClaimed = false; + sdpConnectionClaimed = false; + rfcommConnectionClaimed = false; + + hci_event_flag = 0; + hci_state = HCI_DONE_STATE; + } + break; + + case HCI_DONE_STATE: + hci_counter++; + if(hci_counter > 1000) { // Wait until we have looped 1000 times to make sure that the L2CAP connection has been started + hci_counter = 0; + hci_state = HCI_SCANNING_STATE; + } + break; + + case HCI_DISCONNECT_STATE: + if(hci_check_flag(HCI_FLAG_DISCONNECT_COMPLETE)) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nHCI Disconnected from Device"), 0x80); +#endif + hci_event_flag = 0; // Clear all flags + + // Reset all buffers + memset(hcibuf, 0, BULK_MAXPKTSIZE); + memset(l2capinbuf, 0, BULK_MAXPKTSIZE); + + connectToWii = incomingWii = pairWithWii = false; + connectToHIDDevice = incomingHIDDevice = pairWithHIDDevice = checkRemoteName = false; + incomingPS4 = false; + + hci_state = HCI_SCANNING_STATE; + } + break; + default: + break; + } +} + +void BTD::ACL_event_task() { + uint16_t length = BULK_MAXPKTSIZE; + uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[ BTD_DATAIN_PIPE ].epAddr, &length, l2capinbuf); // Input on endpoint 2 + + if(!rcode) { // Check for errors + if(length > 0) { // Check if any data was read + for(uint8_t i = 0; i < BTD_NUM_SERVICES; i++) { + if(btService[i]) + btService[i]->ACLData(l2capinbuf); + } + } + } +#ifdef EXTRADEBUG + else if(rcode != hrNAK) { + Notify(PSTR("\r\nACL data in error: "), 0x80); + D_PrintHex (rcode, 0x80); + } +#endif + for(uint8_t i = 0; i < BTD_NUM_SERVICES; i++) + if(btService[i]) + btService[i]->Run(); +} + +/************************************************************/ +/* HCI Commands */ + +/************************************************************/ +void BTD::HCI_Command(uint8_t* data, uint16_t nbytes) { + hci_clear_flag(HCI_FLAG_CMD_COMPLETE); + pUsb->ctrlReq(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, bmREQ_HCI_OUT, 0x00, 0x00, 0x00, 0x00, nbytes, nbytes, data, NULL); +} + +void BTD::hci_reset() { + hci_event_flag = 0; // Clear all the flags + hcibuf[0] = 0x03; // HCI OCF = 3 + hcibuf[1] = 0x03 << 2; // HCI OGF = 3 + hcibuf[2] = 0x00; + + HCI_Command(hcibuf, 3); +} + +void BTD::hci_write_scan_enable() { + hci_clear_flag(HCI_FLAG_INCOMING_REQUEST); + hcibuf[0] = 0x1A; // HCI OCF = 1A + hcibuf[1] = 0x03 << 2; // HCI OGF = 3 + hcibuf[2] = 0x01; // parameter length = 1 + if(btdName != NULL) + hcibuf[3] = 0x03; // Inquiry Scan enabled. Page Scan enabled. + else + hcibuf[3] = 0x02; // Inquiry Scan disabled. Page Scan enabled. + + HCI_Command(hcibuf, 4); +} + +void BTD::hci_write_scan_disable() { + hcibuf[0] = 0x1A; // HCI OCF = 1A + hcibuf[1] = 0x03 << 2; // HCI OGF = 3 + hcibuf[2] = 0x01; // parameter length = 1 + hcibuf[3] = 0x00; // Inquiry Scan disabled. Page Scan disabled. + + HCI_Command(hcibuf, 4); +} + +void BTD::hci_read_bdaddr() { + hci_clear_flag(HCI_FLAG_READ_BDADDR); + hcibuf[0] = 0x09; // HCI OCF = 9 + hcibuf[1] = 0x04 << 2; // HCI OGF = 4 + hcibuf[2] = 0x00; + + HCI_Command(hcibuf, 3); +} + +void BTD::hci_read_local_version_information() { + hci_clear_flag(HCI_FLAG_READ_VERSION); + hcibuf[0] = 0x01; // HCI OCF = 1 + hcibuf[1] = 0x04 << 2; // HCI OGF = 4 + hcibuf[2] = 0x00; + + HCI_Command(hcibuf, 3); +} + +void BTD::hci_accept_connection() { + hci_clear_flag(HCI_FLAG_CONNECT_COMPLETE); + hcibuf[0] = 0x09; // HCI OCF = 9 + hcibuf[1] = 0x01 << 2; // HCI OGF = 1 + hcibuf[2] = 0x07; // parameter length 7 + hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr + hcibuf[4] = disc_bdaddr[1]; + hcibuf[5] = disc_bdaddr[2]; + hcibuf[6] = disc_bdaddr[3]; + hcibuf[7] = disc_bdaddr[4]; + hcibuf[8] = disc_bdaddr[5]; + hcibuf[9] = 0x00; // Switch role to master + + HCI_Command(hcibuf, 10); +} + +void BTD::hci_remote_name() { + hci_clear_flag(HCI_FLAG_REMOTE_NAME_COMPLETE); + hcibuf[0] = 0x19; // HCI OCF = 19 + hcibuf[1] = 0x01 << 2; // HCI OGF = 1 + hcibuf[2] = 0x0A; // parameter length = 10 + hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr + hcibuf[4] = disc_bdaddr[1]; + hcibuf[5] = disc_bdaddr[2]; + hcibuf[6] = disc_bdaddr[3]; + hcibuf[7] = disc_bdaddr[4]; + hcibuf[8] = disc_bdaddr[5]; + hcibuf[9] = 0x01; // Page Scan Repetition Mode + hcibuf[10] = 0x00; // Reserved + hcibuf[11] = 0x00; // Clock offset - low byte + hcibuf[12] = 0x00; // Clock offset - high byte + + HCI_Command(hcibuf, 13); +} + +void BTD::hci_set_local_name(const char* name) { + hcibuf[0] = 0x13; // HCI OCF = 13 + hcibuf[1] = 0x03 << 2; // HCI OGF = 3 + hcibuf[2] = strlen(name) + 1; // parameter length = the length of the string + end byte + uint8_t i; + for(i = 0; i < strlen(name); i++) + hcibuf[i + 3] = name[i]; + hcibuf[i + 3] = 0x00; // End of string + + HCI_Command(hcibuf, 4 + strlen(name)); +} + +void BTD::hci_inquiry() { + hci_clear_flag(HCI_FLAG_DEVICE_FOUND); + hcibuf[0] = 0x01; + hcibuf[1] = 0x01 << 2; // HCI OGF = 1 + hcibuf[2] = 0x05; // Parameter Total Length = 5 + hcibuf[3] = 0x33; // LAP: Genera/Unlimited Inquiry Access Code (GIAC = 0x9E8B33) - see https://www.bluetooth.org/Technical/AssignedNumbers/baseband.htm + hcibuf[4] = 0x8B; + hcibuf[5] = 0x9E; + hcibuf[6] = 0x30; // Inquiry time = 61.44 sec (maximum) + hcibuf[7] = 0x0A; // 10 number of responses + + HCI_Command(hcibuf, 8); +} + +void BTD::hci_inquiry_cancel() { + hcibuf[0] = 0x02; + hcibuf[1] = 0x01 << 2; // HCI OGF = 1 + hcibuf[2] = 0x00; // Parameter Total Length = 0 + + HCI_Command(hcibuf, 3); +} + +void BTD::hci_connect() { + hci_connect(disc_bdaddr); // Use last discovered device +} + +void BTD::hci_connect(uint8_t *bdaddr) { + hci_clear_flag(HCI_FLAG_CONNECT_COMPLETE | HCI_FLAG_CONNECT_EVENT); + hcibuf[0] = 0x05; + hcibuf[1] = 0x01 << 2; // HCI OGF = 1 + hcibuf[2] = 0x0D; // parameter Total Length = 13 + hcibuf[3] = bdaddr[0]; // 6 octet bdaddr (LSB) + hcibuf[4] = bdaddr[1]; + hcibuf[5] = bdaddr[2]; + hcibuf[6] = bdaddr[3]; + hcibuf[7] = bdaddr[4]; + hcibuf[8] = bdaddr[5]; + hcibuf[9] = 0x18; // DM1 or DH1 may be used + hcibuf[10] = 0xCC; // DM3, DH3, DM5, DH5 may be used + hcibuf[11] = 0x01; // Page repetition mode R1 + hcibuf[12] = 0x00; // Reserved + hcibuf[13] = 0x00; // Clock offset + hcibuf[14] = 0x00; // Invalid clock offset + hcibuf[15] = 0x00; // Do not allow role switch + + HCI_Command(hcibuf, 16); +} + +void BTD::hci_pin_code_request_reply() { + hcibuf[0] = 0x0D; // HCI OCF = 0D + hcibuf[1] = 0x01 << 2; // HCI OGF = 1 + hcibuf[2] = 0x17; // parameter length 23 + hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr + hcibuf[4] = disc_bdaddr[1]; + hcibuf[5] = disc_bdaddr[2]; + hcibuf[6] = disc_bdaddr[3]; + hcibuf[7] = disc_bdaddr[4]; + hcibuf[8] = disc_bdaddr[5]; + if(pairWithWii) { + hcibuf[9] = 6; // Pin length is the length of the Bluetooth address + if(pairWiiUsingSync) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nParing with Wii controller via SYNC"), 0x80); +#endif + for(uint8_t i = 0; i < 6; i++) + hcibuf[10 + i] = my_bdaddr[i]; // The pin is the Bluetooth dongles Bluetooth address backwards + } else { + for(uint8_t i = 0; i < 6; i++) + hcibuf[10 + i] = disc_bdaddr[i]; // The pin is the Wiimote's Bluetooth address backwards + } + for(uint8_t i = 16; i < 26; i++) + hcibuf[i] = 0x00; // The rest should be 0 + } else { + hcibuf[9] = strlen(btdPin); // Length of pin + uint8_t i; + for(i = 0; i < strlen(btdPin); i++) // The maximum size of the pin is 16 + hcibuf[i + 10] = btdPin[i]; + for(; i < 16; i++) + hcibuf[i + 10] = 0x00; // The rest should be 0 + } + + HCI_Command(hcibuf, 26); +} + +void BTD::hci_pin_code_negative_request_reply() { + hcibuf[0] = 0x0E; // HCI OCF = 0E + hcibuf[1] = 0x01 << 2; // HCI OGF = 1 + hcibuf[2] = 0x06; // parameter length 6 + hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr + hcibuf[4] = disc_bdaddr[1]; + hcibuf[5] = disc_bdaddr[2]; + hcibuf[6] = disc_bdaddr[3]; + hcibuf[7] = disc_bdaddr[4]; + hcibuf[8] = disc_bdaddr[5]; + + HCI_Command(hcibuf, 9); +} + +void BTD::hci_link_key_request_negative_reply() { + hcibuf[0] = 0x0C; // HCI OCF = 0C + hcibuf[1] = 0x01 << 2; // HCI OGF = 1 + hcibuf[2] = 0x06; // parameter length 6 + hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr + hcibuf[4] = disc_bdaddr[1]; + hcibuf[5] = disc_bdaddr[2]; + hcibuf[6] = disc_bdaddr[3]; + hcibuf[7] = disc_bdaddr[4]; + hcibuf[8] = disc_bdaddr[5]; + + HCI_Command(hcibuf, 9); +} + +void BTD::hci_authentication_request() { + hcibuf[0] = 0x11; // HCI OCF = 11 + hcibuf[1] = 0x01 << 2; // HCI OGF = 1 + hcibuf[2] = 0x02; // parameter length = 2 + hcibuf[3] = (uint8_t)(hci_handle & 0xFF); //connection handle - low byte + hcibuf[4] = (uint8_t)((hci_handle >> 8) & 0x0F); //connection handle - high byte + + HCI_Command(hcibuf, 5); +} + +void BTD::hci_disconnect(uint16_t handle) { // This is called by the different services + hci_clear_flag(HCI_FLAG_DISCONNECT_COMPLETE); + hcibuf[0] = 0x06; // HCI OCF = 6 + hcibuf[1] = 0x01 << 2; // HCI OGF = 1 + hcibuf[2] = 0x03; // parameter length = 3 + hcibuf[3] = (uint8_t)(handle & 0xFF); //connection handle - low byte + hcibuf[4] = (uint8_t)((handle >> 8) & 0x0F); //connection handle - high byte + hcibuf[5] = 0x13; // reason + + HCI_Command(hcibuf, 6); +} + +void BTD::hci_write_class_of_device() { // See http://bluetooth-pentest.narod.ru/software/bluetooth_class_of_device-service_generator.html + hcibuf[0] = 0x24; // HCI OCF = 24 + hcibuf[1] = 0x03 << 2; // HCI OGF = 3 + hcibuf[2] = 0x03; // parameter length = 3 + hcibuf[3] = 0x04; // Robot + hcibuf[4] = 0x08; // Toy + hcibuf[5] = 0x00; + + HCI_Command(hcibuf, 6); +} +/******************************************************************* + * * + * HCI ACL Data Packet * + * * + * buf[0] buf[1] buf[2] buf[3] + * 0 4 8 11 12 16 24 31 MSB + * .-+-+-+-+-+-+-+-|-+-+-+-|-+-|-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-. + * | HCI Handle |PB |BC | Data Total Length | HCI ACL Data Packet + * .-+-+-+-+-+-+-+-|-+-+-+-|-+-|-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-. + * + * buf[4] buf[5] buf[6] buf[7] + * 0 8 16 31 MSB + * .-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-. + * | Length | Channel ID | Basic L2CAP header + * .-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-. + * + * buf[8] buf[9] buf[10] buf[11] + * 0 8 16 31 MSB + * .-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-. + * | Code | Identifier | Length | Control frame (C-frame) + * .-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-. (signaling packet format) + */ +/************************************************************/ +/* L2CAP Commands */ + +/************************************************************/ +void BTD::L2CAP_Command(uint16_t handle, uint8_t* data, uint8_t nbytes, uint8_t channelLow, uint8_t channelHigh) { + uint8_t buf[8 + nbytes]; + buf[0] = (uint8_t)(handle & 0xff); // HCI handle with PB,BC flag + buf[1] = (uint8_t)(((handle >> 8) & 0x0f) | 0x20); + buf[2] = (uint8_t)((4 + nbytes) & 0xff); // HCI ACL total data length + buf[3] = (uint8_t)((4 + nbytes) >> 8); + buf[4] = (uint8_t)(nbytes & 0xff); // L2CAP header: Length + buf[5] = (uint8_t)(nbytes >> 8); + buf[6] = channelLow; + buf[7] = channelHigh; + + for(uint16_t i = 0; i < nbytes; i++) // L2CAP C-frame + buf[8 + i] = data[i]; + + uint8_t rcode = pUsb->outTransfer(bAddress, epInfo[ BTD_DATAOUT_PIPE ].epAddr, (8 + nbytes), buf); + if(rcode) { + delay(100); // This small delay prevents it from overflowing if it fails +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nError sending L2CAP message: 0x"), 0x80); + D_PrintHex (rcode, 0x80); + Notify(PSTR(" - Channel ID: "), 0x80); + D_PrintHex (channelHigh, 0x80); + Notify(PSTR(" "), 0x80); + D_PrintHex (channelLow, 0x80); +#endif + } +} + +void BTD::l2cap_connection_request(uint16_t handle, uint8_t rxid, uint8_t* scid, uint16_t psm) { + l2capoutbuf[0] = L2CAP_CMD_CONNECTION_REQUEST; // Code + l2capoutbuf[1] = rxid; // Identifier + l2capoutbuf[2] = 0x04; // Length + l2capoutbuf[3] = 0x00; + l2capoutbuf[4] = (uint8_t)(psm & 0xff); // PSM + l2capoutbuf[5] = (uint8_t)(psm >> 8); + l2capoutbuf[6] = scid[0]; // Source CID + l2capoutbuf[7] = scid[1]; + + L2CAP_Command(handle, l2capoutbuf, 8); +} + +void BTD::l2cap_connection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid, uint8_t result) { + l2capoutbuf[0] = L2CAP_CMD_CONNECTION_RESPONSE; // Code + l2capoutbuf[1] = rxid; // Identifier + l2capoutbuf[2] = 0x08; // Length + l2capoutbuf[3] = 0x00; + l2capoutbuf[4] = dcid[0]; // Destination CID + l2capoutbuf[5] = dcid[1]; + l2capoutbuf[6] = scid[0]; // Source CID + l2capoutbuf[7] = scid[1]; + l2capoutbuf[8] = result; // Result: Pending or Success + l2capoutbuf[9] = 0x00; + l2capoutbuf[10] = 0x00; // No further information + l2capoutbuf[11] = 0x00; + + L2CAP_Command(handle, l2capoutbuf, 12); +} + +void BTD::l2cap_config_request(uint16_t handle, uint8_t rxid, uint8_t* dcid) { + l2capoutbuf[0] = L2CAP_CMD_CONFIG_REQUEST; // Code + l2capoutbuf[1] = rxid; // Identifier + l2capoutbuf[2] = 0x08; // Length + l2capoutbuf[3] = 0x00; + l2capoutbuf[4] = dcid[0]; // Destination CID + l2capoutbuf[5] = dcid[1]; + l2capoutbuf[6] = 0x00; // Flags + l2capoutbuf[7] = 0x00; + l2capoutbuf[8] = 0x01; // Config Opt: type = MTU (Maximum Transmission Unit) - Hint + l2capoutbuf[9] = 0x02; // Config Opt: length + l2capoutbuf[10] = 0xFF; // MTU + l2capoutbuf[11] = 0xFF; + + L2CAP_Command(handle, l2capoutbuf, 12); +} + +void BTD::l2cap_config_response(uint16_t handle, uint8_t rxid, uint8_t* scid) { + l2capoutbuf[0] = L2CAP_CMD_CONFIG_RESPONSE; // Code + l2capoutbuf[1] = rxid; // Identifier + l2capoutbuf[2] = 0x0A; // Length + l2capoutbuf[3] = 0x00; + l2capoutbuf[4] = scid[0]; // Source CID + l2capoutbuf[5] = scid[1]; + l2capoutbuf[6] = 0x00; // Flag + l2capoutbuf[7] = 0x00; + l2capoutbuf[8] = 0x00; // Result + l2capoutbuf[9] = 0x00; + l2capoutbuf[10] = 0x01; // Config + l2capoutbuf[11] = 0x02; + l2capoutbuf[12] = 0xA0; + l2capoutbuf[13] = 0x02; + + L2CAP_Command(handle, l2capoutbuf, 14); +} + +void BTD::l2cap_disconnection_request(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid) { + l2capoutbuf[0] = L2CAP_CMD_DISCONNECT_REQUEST; // Code + l2capoutbuf[1] = rxid; // Identifier + l2capoutbuf[2] = 0x04; // Length + l2capoutbuf[3] = 0x00; + l2capoutbuf[4] = dcid[0]; + l2capoutbuf[5] = dcid[1]; + l2capoutbuf[6] = scid[0]; + l2capoutbuf[7] = scid[1]; + + L2CAP_Command(handle, l2capoutbuf, 8); +} + +void BTD::l2cap_disconnection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid) { + l2capoutbuf[0] = L2CAP_CMD_DISCONNECT_RESPONSE; // Code + l2capoutbuf[1] = rxid; // Identifier + l2capoutbuf[2] = 0x04; // Length + l2capoutbuf[3] = 0x00; + l2capoutbuf[4] = dcid[0]; + l2capoutbuf[5] = dcid[1]; + l2capoutbuf[6] = scid[0]; + l2capoutbuf[7] = scid[1]; + + L2CAP_Command(handle, l2capoutbuf, 8); +} + +void BTD::l2cap_information_response(uint16_t handle, uint8_t rxid, uint8_t infoTypeLow, uint8_t infoTypeHigh) { + l2capoutbuf[0] = L2CAP_CMD_INFORMATION_RESPONSE; // Code + l2capoutbuf[1] = rxid; // Identifier + l2capoutbuf[2] = 0x08; // Length + l2capoutbuf[3] = 0x00; + l2capoutbuf[4] = infoTypeLow; + l2capoutbuf[5] = infoTypeHigh; + l2capoutbuf[6] = 0x00; // Result = success + l2capoutbuf[7] = 0x00; // Result = success + l2capoutbuf[8] = 0x00; + l2capoutbuf[9] = 0x00; + l2capoutbuf[10] = 0x00; + l2capoutbuf[11] = 0x00; + + L2CAP_Command(handle, l2capoutbuf, 12); +} + +/* PS3 Commands - only set Bluetooth address is implemented in this library */ +void BTD::setBdaddr(uint8_t* bdaddr) { + /* Set the internal Bluetooth address */ + uint8_t buf[8]; + buf[0] = 0x01; + buf[1] = 0x00; + + for(uint8_t i = 0; i < 6; i++) + buf[i + 2] = bdaddr[5 - i]; // Copy into buffer, has to be written reversed, so it is MSB first + + // bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF5), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data + pUsb->ctrlReq(bAddress, epInfo[BTD_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL); +} + +void BTD::setMoveBdaddr(uint8_t* bdaddr) { + /* Set the internal Bluetooth address */ + uint8_t buf[11]; + buf[0] = 0x05; + buf[7] = 0x10; + buf[8] = 0x01; + buf[9] = 0x02; + buf[10] = 0x12; + + for(uint8_t i = 0; i < 6; i++) + buf[i + 1] = bdaddr[i]; + + // bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x05), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data + pUsb->ctrlReq(bAddress, epInfo[BTD_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x05, 0x03, 0x00, 11, 11, buf, NULL); +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/BTD.h b/lib/usbhost/USB_Host_Shield_2.0/BTD.h new file mode 100644 index 0000000000..6549c30c98 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/BTD.h @@ -0,0 +1,620 @@ +/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. + + This software may be distributed and modified under the terms of the GNU + General Public License version 2 (GPL2) as published by the Free Software + Foundation and appearing in the file GPL2.TXT included in the packaging of + this file. Please note that GPL2 Section 2[b] requires that all works based + on this software must also be made publicly available under the terms of + the GPL2 ("Copyleft"). + + Contact information + ------------------- + + Kristian Lauszus, TKJ Electronics + Web : http://www.tkjelectronics.com + e-mail : kristianl@tkjelectronics.com + */ + +#ifndef _btd_h_ +#define _btd_h_ + +#include "Usb.h" +#include "hid.h" + +//PID and VID of the Sony PS3 devices +#define PS3_VID 0x054C // Sony Corporation +#define PS3_PID 0x0268 // PS3 Controller DualShock 3 +#define PS3NAVIGATION_PID 0x042F // Navigation controller +#define PS3MOVE_PID 0x03D5 // Motion controller + +#define IOGEAR_GBU521_VID 0x0A5C // The IOGEAR GBU521 dongle does not presents itself correctly, so we have to check for it manually +#define IOGEAR_GBU521_PID 0x21E8 + +/* Bluetooth dongle data taken from descriptors */ +#define BULK_MAXPKTSIZE 64 // Max size for ACL data + +// Used in control endpoint header for HCI Commands +#define bmREQ_HCI_OUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE + +/* Bluetooth HCI states for hci_task() */ +#define HCI_INIT_STATE 0 +#define HCI_RESET_STATE 1 +#define HCI_CLASS_STATE 2 +#define HCI_BDADDR_STATE 3 +#define HCI_LOCAL_VERSION_STATE 4 +#define HCI_SET_NAME_STATE 5 +#define HCI_CHECK_DEVICE_SERVICE 6 + +#define HCI_INQUIRY_STATE 7 // These three states are only used if it should pair and connect to a device +#define HCI_CONNECT_DEVICE_STATE 8 +#define HCI_CONNECTED_DEVICE_STATE 9 + +#define HCI_SCANNING_STATE 10 +#define HCI_CONNECT_IN_STATE 11 +#define HCI_REMOTE_NAME_STATE 12 +#define HCI_CONNECTED_STATE 13 +#define HCI_DISABLE_SCAN_STATE 14 +#define HCI_DONE_STATE 15 +#define HCI_DISCONNECT_STATE 16 + +/* HCI event flags*/ +#define HCI_FLAG_CMD_COMPLETE (1UL << 0) +#define HCI_FLAG_CONNECT_COMPLETE (1UL << 1) +#define HCI_FLAG_DISCONNECT_COMPLETE (1UL << 2) +#define HCI_FLAG_REMOTE_NAME_COMPLETE (1UL << 3) +#define HCI_FLAG_INCOMING_REQUEST (1UL << 4) +#define HCI_FLAG_READ_BDADDR (1UL << 5) +#define HCI_FLAG_READ_VERSION (1UL << 6) +#define HCI_FLAG_DEVICE_FOUND (1UL << 7) +#define HCI_FLAG_CONNECT_EVENT (1UL << 8) + +/* Macros for HCI event flag tests */ +#define hci_check_flag(flag) (hci_event_flag & (flag)) +#define hci_set_flag(flag) (hci_event_flag |= (flag)) +#define hci_clear_flag(flag) (hci_event_flag &= ~(flag)) + +/* HCI Events managed */ +#define EV_INQUIRY_COMPLETE 0x01 +#define EV_INQUIRY_RESULT 0x02 +#define EV_CONNECT_COMPLETE 0x03 +#define EV_INCOMING_CONNECT 0x04 +#define EV_DISCONNECT_COMPLETE 0x05 +#define EV_AUTHENTICATION_COMPLETE 0x06 +#define EV_REMOTE_NAME_COMPLETE 0x07 +#define EV_ENCRYPTION_CHANGE 0x08 +#define EV_CHANGE_CONNECTION_LINK 0x09 +#define EV_ROLE_CHANGED 0x12 +#define EV_NUM_COMPLETE_PKT 0x13 +#define EV_PIN_CODE_REQUEST 0x16 +#define EV_LINK_KEY_REQUEST 0x17 +#define EV_LINK_KEY_NOTIFICATION 0x18 +#define EV_DATA_BUFFER_OVERFLOW 0x1A +#define EV_MAX_SLOTS_CHANGE 0x1B +#define EV_READ_REMOTE_VERSION_INFORMATION_COMPLETE 0x0C +#define EV_QOS_SETUP_COMPLETE 0x0D +#define EV_COMMAND_COMPLETE 0x0E +#define EV_COMMAND_STATUS 0x0F +#define EV_LOOPBACK_COMMAND 0x19 +#define EV_PAGE_SCAN_REP_MODE 0x20 + +/* Bluetooth states for the different Bluetooth drivers */ +#define L2CAP_WAIT 0 +#define L2CAP_DONE 1 + +/* Used for HID Control channel */ +#define L2CAP_CONTROL_CONNECT_REQUEST 2 +#define L2CAP_CONTROL_CONFIG_REQUEST 3 +#define L2CAP_CONTROL_SUCCESS 4 +#define L2CAP_CONTROL_DISCONNECT 5 + +/* Used for HID Interrupt channel */ +#define L2CAP_INTERRUPT_SETUP 6 +#define L2CAP_INTERRUPT_CONNECT_REQUEST 7 +#define L2CAP_INTERRUPT_CONFIG_REQUEST 8 +#define L2CAP_INTERRUPT_DISCONNECT 9 + +/* Used for SDP channel */ +#define L2CAP_SDP_WAIT 10 +#define L2CAP_SDP_SUCCESS 11 + +/* Used for RFCOMM channel */ +#define L2CAP_RFCOMM_WAIT 12 +#define L2CAP_RFCOMM_SUCCESS 13 + +#define L2CAP_DISCONNECT_RESPONSE 14 // Used for both SDP and RFCOMM channel + +/* Bluetooth states used by some drivers */ +#define TURN_ON_LED 17 +#define PS3_ENABLE_SIXAXIS 18 +#define WII_CHECK_MOTION_PLUS_STATE 19 +#define WII_CHECK_EXTENSION_STATE 20 +#define WII_INIT_MOTION_PLUS_STATE 21 + +/* L2CAP event flags for HID Control channel */ +#define L2CAP_FLAG_CONNECTION_CONTROL_REQUEST (1UL << 0) +#define L2CAP_FLAG_CONFIG_CONTROL_SUCCESS (1UL << 1) +#define L2CAP_FLAG_CONTROL_CONNECTED (1UL << 2) +#define L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE (1UL << 3) + +/* L2CAP event flags for HID Interrupt channel */ +#define L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST (1UL << 4) +#define L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS (1UL << 5) +#define L2CAP_FLAG_INTERRUPT_CONNECTED (1UL << 6) +#define L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE (1UL << 7) + +/* L2CAP event flags for SDP channel */ +#define L2CAP_FLAG_CONNECTION_SDP_REQUEST (1UL << 8) +#define L2CAP_FLAG_CONFIG_SDP_SUCCESS (1UL << 9) +#define L2CAP_FLAG_DISCONNECT_SDP_REQUEST (1UL << 10) + +/* L2CAP event flags for RFCOMM channel */ +#define L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST (1UL << 11) +#define L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS (1UL << 12) +#define L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST (1UL << 13) + +#define L2CAP_FLAG_DISCONNECT_RESPONSE (1UL << 14) + +/* Macros for L2CAP event flag tests */ +#define l2cap_check_flag(flag) (l2cap_event_flag & (flag)) +#define l2cap_set_flag(flag) (l2cap_event_flag |= (flag)) +#define l2cap_clear_flag(flag) (l2cap_event_flag &= ~(flag)) + +/* L2CAP signaling commands */ +#define L2CAP_CMD_COMMAND_REJECT 0x01 +#define L2CAP_CMD_CONNECTION_REQUEST 0x02 +#define L2CAP_CMD_CONNECTION_RESPONSE 0x03 +#define L2CAP_CMD_CONFIG_REQUEST 0x04 +#define L2CAP_CMD_CONFIG_RESPONSE 0x05 +#define L2CAP_CMD_DISCONNECT_REQUEST 0x06 +#define L2CAP_CMD_DISCONNECT_RESPONSE 0x07 +#define L2CAP_CMD_INFORMATION_REQUEST 0x0A +#define L2CAP_CMD_INFORMATION_RESPONSE 0x0B + +// Used For Connection Response - Remember to Include High Byte +#define PENDING 0x01 +#define SUCCESSFUL 0x00 + +/* Bluetooth L2CAP PSM - see http://www.bluetooth.org/Technical/AssignedNumbers/logical_link.htm */ +#define SDP_PSM 0x01 // Service Discovery Protocol PSM Value +#define RFCOMM_PSM 0x03 // RFCOMM PSM Value +#define HID_CTRL_PSM 0x11 // HID_Control PSM Value +#define HID_INTR_PSM 0x13 // HID_Interrupt PSM Value + +// Used to determine if it is a Bluetooth dongle +#define WI_SUBCLASS_RF 0x01 // RF Controller +#define WI_PROTOCOL_BT 0x01 // Bluetooth Programming Interface + +#define BTD_MAX_ENDPOINTS 4 +#define BTD_NUM_SERVICES 4 // Max number of Bluetooth services - if you need more than 4 simply increase this number + +#define PAIR 1 + +class BluetoothService; + +/** + * The Bluetooth Dongle class will take care of all the USB communication + * and then pass the data to the BluetoothService classes. + */ +class BTD : public USBDeviceConfig, public UsbConfigXtracter { +public: + /** + * Constructor for the BTD class. + * @param p Pointer to USB class instance. + */ + BTD(USB *p); + + /** @name USBDeviceConfig implementation */ + /** + * Address assignment and basic initialization is done here. + * @param parent Hub number. + * @param port Port number on the hub. + * @param lowspeed Speed of the device. + * @return 0 on success. + */ + uint8_t ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed); + /** + * Initialize the Bluetooth dongle. + * @param parent Hub number. + * @param port Port number on the hub. + * @param lowspeed Speed of the device. + * @return 0 on success. + */ + uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + /** + * Release the USB device. + * @return 0 on success. + */ + uint8_t Release(); + /** + * Poll the USB Input endpoints and run the state machines. + * @return 0 on success. + */ + uint8_t Poll(); + + /** + * Get the device address. + * @return The device address. + */ + virtual uint8_t GetAddress() { + return bAddress; + }; + + /** + * Used to check if the dongle has been initialized. + * @return True if it's ready. + */ + virtual bool isReady() { + return bPollEnable; + }; + + /** + * Used by the USB core to check what this driver support. + * @param klass The device's USB class. + * @return Returns true if the device's USB class matches this driver. + */ + virtual bool DEVCLASSOK(uint8_t klass) { + return (klass == USB_CLASS_WIRELESS_CTRL); + }; + + /** + * Used by the USB core to check what this driver support. + * Used to set the Bluetooth address into the PS3 controllers. + * @param vid The device's VID. + * @param pid The device's PID. + * @return Returns true if the device's VID and PID matches this driver. + */ + virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) { + if(vid == IOGEAR_GBU521_VID && pid == IOGEAR_GBU521_PID) + return true; + if(my_bdaddr[0] != 0x00 || my_bdaddr[1] != 0x00 || my_bdaddr[2] != 0x00 || my_bdaddr[3] != 0x00 || my_bdaddr[4] != 0x00 || my_bdaddr[5] != 0x00) { // Check if Bluetooth address is set + if(vid == PS3_VID && (pid == PS3_PID || pid == PS3NAVIGATION_PID || pid == PS3MOVE_PID)) + return true; + } + return false; + }; + /**@}*/ + + /** @name UsbConfigXtracter implementation */ + /** + * UsbConfigXtracter implementation, used to extract endpoint information. + * @param conf Configuration value. + * @param iface Interface number. + * @param alt Alternate setting. + * @param proto Interface Protocol. + * @param ep Endpoint Descriptor. + */ + void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); + /**@}*/ + + /** Disconnects both the L2CAP Channel and the HCI Connection for all Bluetooth services. */ + void disconnect(); + + /** + * Register Bluetooth dongle members/services. + * @param pService Pointer to BluetoothService class instance. + * @return The service ID on success or -1 on fail. + */ + int8_t registerBluetoothService(BluetoothService *pService) { + for(uint8_t i = 0; i < BTD_NUM_SERVICES; i++) { + if(!btService[i]) { + btService[i] = pService; + return i; // Return ID + } + } + return -1; // Error registering BluetoothService + }; + + /** @name HCI Commands */ + /** + * Used to send a HCI Command. + * @param data Data to send. + * @param nbytes Number of bytes to send. + */ + void HCI_Command(uint8_t* data, uint16_t nbytes); + /** Reset the Bluetooth dongle. */ + void hci_reset(); + /** Read the Bluetooth address of the dongle. */ + void hci_read_bdaddr(); + /** Read the HCI Version of the Bluetooth dongle. */ + void hci_read_local_version_information(); + /** + * Set the local name of the Bluetooth dongle. + * @param name Desired name. + */ + void hci_set_local_name(const char* name); + /** Enable visibility to other Bluetooth devices. */ + void hci_write_scan_enable(); + /** Disable visibility to other Bluetooth devices. */ + void hci_write_scan_disable(); + /** Read the remote devices name. */ + void hci_remote_name(); + /** Accept the connection with the Bluetooth device. */ + void hci_accept_connection(); + /** + * Disconnect the HCI connection. + * @param handle The HCI Handle for the connection. + */ + void hci_disconnect(uint16_t handle); + /** + * Respond with the pin for the connection. + * The pin is automatically set for the Wii library, + * but can be customized for the SPP library. + */ + void hci_pin_code_request_reply(); + /** Respons when no pin was set. */ + void hci_pin_code_negative_request_reply(); + /** + * Command is used to reply to a Link Key Request event from the BR/EDR Controller + * if the Host does not have a stored Link Key for the connection. + */ + void hci_link_key_request_negative_reply(); + /** Used to try to authenticate with the remote device. */ + void hci_authentication_request(); + /** Start a HCI inquiry. */ + void hci_inquiry(); + /** Cancel a HCI inquiry. */ + void hci_inquiry_cancel(); + /** Connect to last device communicated with. */ + void hci_connect(); + /** + * Connect to device. + * @param bdaddr Bluetooth address of the device. + */ + void hci_connect(uint8_t *bdaddr); + /** Used to a set the class of the device. */ + void hci_write_class_of_device(); + /**@}*/ + + /** @name L2CAP Commands */ + /** + * Used to send L2CAP Commands. + * @param handle HCI Handle. + * @param data Data to send. + * @param nbytes Number of bytes to send. + * @param channelLow,channelHigh Low and high byte of channel to send to. + * If argument is omitted then the Standard L2CAP header: Channel ID (0x01) for ACL-U will be used. + */ + void L2CAP_Command(uint16_t handle, uint8_t* data, uint8_t nbytes, uint8_t channelLow = 0x01, uint8_t channelHigh = 0x00); + /** + * L2CAP Connection Request. + * @param handle HCI handle. + * @param rxid Identifier. + * @param scid Source Channel Identifier. + * @param psm Protocol/Service Multiplexer - see: https://www.bluetooth.org/Technical/AssignedNumbers/logical_link.htm. + */ + void l2cap_connection_request(uint16_t handle, uint8_t rxid, uint8_t* scid, uint16_t psm); + /** + * L2CAP Connection Response. + * @param handle HCI handle. + * @param rxid Identifier. + * @param dcid Destination Channel Identifier. + * @param scid Source Channel Identifier. + * @param result Result - First send ::PENDING and then ::SUCCESSFUL. + */ + void l2cap_connection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid, uint8_t result); + /** + * L2CAP Config Request. + * @param handle HCI Handle. + * @param rxid Identifier. + * @param dcid Destination Channel Identifier. + */ + void l2cap_config_request(uint16_t handle, uint8_t rxid, uint8_t* dcid); + /** + * L2CAP Config Response. + * @param handle HCI Handle. + * @param rxid Identifier. + * @param scid Source Channel Identifier. + */ + void l2cap_config_response(uint16_t handle, uint8_t rxid, uint8_t* scid); + /** + * L2CAP Disconnection Request. + * @param handle HCI Handle. + * @param rxid Identifier. + * @param dcid Device Channel Identifier. + * @param scid Source Channel Identifier. + */ + void l2cap_disconnection_request(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid); + /** + * L2CAP Disconnection Response. + * @param handle HCI Handle. + * @param rxid Identifier. + * @param dcid Device Channel Identifier. + * @param scid Source Channel Identifier. + */ + void l2cap_disconnection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid); + /** + * L2CAP Information Response. + * @param handle HCI Handle. + * @param rxid Identifier. + * @param infoTypeLow,infoTypeHigh Infotype. + */ + void l2cap_information_response(uint16_t handle, uint8_t rxid, uint8_t infoTypeLow, uint8_t infoTypeHigh); + /**@}*/ + + /** Use this to see if it is waiting for a incoming connection. */ + bool watingForConnection; + /** This is used by the service to know when to store the device information. */ + bool l2capConnectionClaimed; + /** This is used by the SPP library to claim the current SDP incoming request. */ + bool sdpConnectionClaimed; + /** This is used by the SPP library to claim the current RFCOMM incoming request. */ + bool rfcommConnectionClaimed; + + /** The name you wish to make the dongle show up as. It is set automatically by the SPP library. */ + const char* btdName; + /** The pin you wish to make the dongle use for authentication. It is set automatically by the SPP and BTHID library. */ + const char* btdPin; + + /** The bluetooth dongles Bluetooth address. */ + uint8_t my_bdaddr[6]; + /** HCI handle for the last connection. */ + uint16_t hci_handle; + /** Last incoming devices Bluetooth address. */ + uint8_t disc_bdaddr[6]; + /** First 30 chars of last remote name. */ + char remote_name[30]; + /** + * The supported HCI Version read from the Bluetooth dongle. + * Used by the PS3BT library to check the HCI Version of the Bluetooth dongle, + * it should be at least 3 to work properly with the library. + */ + uint8_t hci_version; + + /** Call this function to pair with a Wiimote */ + void pairWithWiimote() { + pairWithWii = true; + hci_state = HCI_CHECK_DEVICE_SERVICE; + }; + /** Used to only send the ACL data to the Wiimote. */ + bool connectToWii; + /** True if a Wiimote is connecting. */ + bool incomingWii; + /** True when it should pair with a Wiimote. */ + bool pairWithWii; + /** True if it's the new Wiimote with the Motion Plus Inside or a Wii U Pro Controller. */ + bool motionPlusInside; + /** True if it's a Wii U Pro Controller. */ + bool wiiUProController; + + /** Call this function to pair with a Wiimote */ + void pairWithHID() { + pairWithHIDDevice = true; + hci_state = HCI_CHECK_DEVICE_SERVICE; + }; + /** Used to only send the ACL data to the Wiimote. */ + bool connectToHIDDevice; + /** True if a Wiimote is connecting. */ + bool incomingHIDDevice; + /** True when it should pair with a device like a mouse or keyboard. */ + bool pairWithHIDDevice; + + /** + * Read the poll interval taken from the endpoint descriptors. + * @return The poll interval in ms. + */ + uint8_t readPollInterval() { + return pollInterval; + }; + +protected: + /** Pointer to USB class instance. */ + USB *pUsb; + /** Device address. */ + uint8_t bAddress; + /** Endpoint info structure. */ + EpInfo epInfo[BTD_MAX_ENDPOINTS]; + + /** Configuration number. */ + uint8_t bConfNum; + /** Total number of endpoints in the configuration. */ + uint8_t bNumEP; + /** Next poll time based on poll interval taken from the USB descriptor. */ + uint32_t qNextPollTime; + + /** Bluetooth dongle control endpoint. */ + static const uint8_t BTD_CONTROL_PIPE; + /** HCI event endpoint index. */ + static const uint8_t BTD_EVENT_PIPE; + /** ACL In endpoint index. */ + static const uint8_t BTD_DATAIN_PIPE; + /** ACL Out endpoint index. */ + static const uint8_t BTD_DATAOUT_PIPE; + + /** + * Used to print the USB Endpoint Descriptor. + * @param ep_ptr Pointer to USB Endpoint Descriptor. + */ + void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); + +private: + void Initialize(); // Set all variables, endpoint structs etc. to default values + BluetoothService *btService[BTD_NUM_SERVICES]; + + uint16_t PID, VID; // PID and VID of device connected + + uint8_t pollInterval; + bool bPollEnable; + + bool pairWiiUsingSync; // True if paring was done using the Wii SYNC button. + bool checkRemoteName; // Used to check remote device's name before connecting. + bool incomingPS4; // True if a PS4 controller is connecting + uint8_t classOfDevice[3]; // Class of device of last device + + /* Variables used by high level HCI task */ + uint8_t hci_state; // Current state of Bluetooth HCI connection + uint16_t hci_counter; // Counter used for Bluetooth HCI reset loops + uint16_t hci_num_reset_loops; // This value indicate how many times it should read before trying to reset + uint16_t hci_event_flag; // HCI flags of received Bluetooth events + uint8_t inquiry_counter; + + uint8_t hcibuf[BULK_MAXPKTSIZE]; // General purpose buffer for HCI data + uint8_t l2capinbuf[BULK_MAXPKTSIZE]; // General purpose buffer for L2CAP in data + uint8_t l2capoutbuf[14]; // General purpose buffer for L2CAP out data + + /* State machines */ + void HCI_event_task(); // Poll the HCI event pipe + void HCI_task(); // HCI state machine + void ACL_event_task(); // ACL input pipe + + /* Used to set the Bluetooth Address internally to the PS3 Controllers */ + void setBdaddr(uint8_t* BDADDR); + void setMoveBdaddr(uint8_t* BDADDR); +}; + +/** All Bluetooth services should inherit this class. */ +class BluetoothService { +public: + BluetoothService(BTD *p) : pBtd(p) { + if(pBtd) + pBtd->registerBluetoothService(this); // Register it as a Bluetooth service + }; + /** + * Used to pass acldata to the Bluetooth service. + * @param ACLData Pointer to the incoming acldata. + */ + virtual void ACLData(uint8_t* ACLData) = 0; + /** Used to run the different state machines in the Bluetooth service. */ + virtual void Run() = 0; + /** Used to reset the Bluetooth service. */ + virtual void Reset() = 0; + /** Used to disconnect both the L2CAP Channel and the HCI Connection for the Bluetooth service. */ + virtual void disconnect() = 0; + + /** + * Used to call your own function when the device is successfully initialized. + * @param funcOnInit Function to call. + */ + void attachOnInit(void (*funcOnInit)(void)) { + pFuncOnInit = funcOnInit; // TODO: This really belong in a class of it's own as it is repeated several times + }; + +protected: + /** + * Called when a device is successfully initialized. + * Use attachOnInit(void (*funcOnInit)(void)) to call your own function. + * This is useful for instance if you want to set the LEDs in a specific way. + */ + virtual void onInit() = 0; + + /** Used to check if the incoming L2CAP data matches the HCI Handle */ + bool checkHciHandle(uint8_t *buf, uint16_t handle) { + return (buf[0] == (handle & 0xFF)) && (buf[1] == ((handle >> 8) | 0x20)); + } + + /** Pointer to function called in onInit(). */ + void (*pFuncOnInit)(void); + + /** Pointer to BTD instance. */ + BTD *pBtd; + + /** The HCI Handle for the connection. */ + uint16_t hci_handle; + + /** L2CAP flags of received Bluetooth events. */ + uint32_t l2cap_event_flag; + + /** Identifier for L2CAP commands. */ + uint8_t identifier; +}; + +#endif diff --git a/lib/usbhost/USB_Host_Shield_2.0/BTHID.cpp b/lib/usbhost/USB_Host_Shield_2.0/BTHID.cpp new file mode 100644 index 0000000000..bfa9202c39 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/BTHID.cpp @@ -0,0 +1,399 @@ +/* Copyright (C) 2013 Kristian Lauszus, TKJ Electronics. All rights reserved. + + This software may be distributed and modified under the terms of the GNU + General Public License version 2 (GPL2) as published by the Free Software + Foundation and appearing in the file GPL2.TXT included in the packaging of + this file. Please note that GPL2 Section 2[b] requires that all works based + on this software must also be made publicly available under the terms of + the GPL2 ("Copyleft"). + + Contact information + ------------------- + + Kristian Lauszus, TKJ Electronics + Web : http://www.tkjelectronics.com + e-mail : kristianl@tkjelectronics.com + */ + +#include "BTHID.h" +// To enable serial debugging see "settings.h" +//#define EXTRADEBUG // Uncomment to get even more debugging data +//#define PRINTREPORT // Uncomment to print the report send by the HID device + +BTHID::BTHID(BTD *p, bool pair, const char *pin) : +BluetoothService(p), // Pointer to USB class instance - mandatory +protocolMode(HID_BOOT_PROTOCOL) { + for(uint8_t i = 0; i < NUM_PARSERS; i++) + pRptParser[i] = NULL; + + pBtd->pairWithHIDDevice = pair; + pBtd->btdPin = pin; + + /* Set device cid for the control and intterrupt channelse - LSB */ + control_dcid[0] = 0x70; // 0x0070 + control_dcid[1] = 0x00; + interrupt_dcid[0] = 0x71; // 0x0071 + interrupt_dcid[1] = 0x00; + + Reset(); +} + +void BTHID::Reset() { + connected = false; + activeConnection = false; + l2cap_event_flag = 0; // Reset flags + l2cap_state = L2CAP_WAIT; + ResetBTHID(); +} + +void BTHID::disconnect() { // Use this void to disconnect the device + // First the HID interrupt channel has to be disconnected, then the HID control channel and finally the HCI connection + pBtd->l2cap_disconnection_request(hci_handle, ++identifier, interrupt_scid, interrupt_dcid); + Reset(); + l2cap_state = L2CAP_INTERRUPT_DISCONNECT; +} + +void BTHID::ACLData(uint8_t* l2capinbuf) { + if(!pBtd->l2capConnectionClaimed && pBtd->incomingHIDDevice && !connected && !activeConnection) { + if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { + if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) { + pBtd->incomingHIDDevice = false; + pBtd->l2capConnectionClaimed = true; // Claim that the incoming connection belongs to this service + activeConnection = true; + hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection + l2cap_state = L2CAP_WAIT; + } + } + } + + if(checkHciHandle(l2capinbuf, hci_handle)) { // acl_handle_ok + if((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001U) { // l2cap_control - Channel ID for ACL-U + if(l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80); + D_PrintHex (l2capinbuf[13], 0x80); + Notify(PSTR(" "), 0x80); + D_PrintHex (l2capinbuf[12], 0x80); + Notify(PSTR(" "), 0x80); + D_PrintHex (l2capinbuf[17], 0x80); + Notify(PSTR(" "), 0x80); + D_PrintHex (l2capinbuf[16], 0x80); + Notify(PSTR(" "), 0x80); + D_PrintHex (l2capinbuf[15], 0x80); + Notify(PSTR(" "), 0x80); + D_PrintHex (l2capinbuf[14], 0x80); +#endif + } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_RESPONSE) { + if(((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) && ((l2capinbuf[18] | (l2capinbuf[19] << 8)) == SUCCESSFUL)) { // Success + if(l2capinbuf[14] == control_dcid[0] && l2capinbuf[15] == control_dcid[1]) { + //Notify(PSTR("\r\nHID Control Connection Complete"), 0x80); + identifier = l2capinbuf[9]; + control_scid[0] = l2capinbuf[12]; + control_scid[1] = l2capinbuf[13]; + l2cap_set_flag(L2CAP_FLAG_CONTROL_CONNECTED); + } else if(l2capinbuf[14] == interrupt_dcid[0] && l2capinbuf[15] == interrupt_dcid[1]) { + //Notify(PSTR("\r\nHID Interrupt Connection Complete"), 0x80); + identifier = l2capinbuf[9]; + interrupt_scid[0] = l2capinbuf[12]; + interrupt_scid[1] = l2capinbuf[13]; + l2cap_set_flag(L2CAP_FLAG_INTERRUPT_CONNECTED); + } + } + } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { +#ifdef EXTRADEBUG + Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80); + D_PrintHex (l2capinbuf[13], 0x80); + Notify(PSTR(" "), 0x80); + D_PrintHex (l2capinbuf[12], 0x80); + Notify(PSTR(" SCID: "), 0x80); + D_PrintHex (l2capinbuf[15], 0x80); + Notify(PSTR(" "), 0x80); + D_PrintHex (l2capinbuf[14], 0x80); + Notify(PSTR(" Identifier: "), 0x80); + D_PrintHex (l2capinbuf[9], 0x80); +#endif + if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) { + identifier = l2capinbuf[9]; + control_scid[0] = l2capinbuf[14]; + control_scid[1] = l2capinbuf[15]; + l2cap_set_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST); + } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_INTR_PSM) { + identifier = l2capinbuf[9]; + interrupt_scid[0] = l2capinbuf[14]; + interrupt_scid[1] = l2capinbuf[15]; + l2cap_set_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST); + } + } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) { + if((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success + if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { + //Notify(PSTR("\r\nHID Control Configuration Complete"), 0x80); + identifier = l2capinbuf[9]; + l2cap_set_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS); + } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { + //Notify(PSTR("\r\nHID Interrupt Configuration Complete"), 0x80); + identifier = l2capinbuf[9]; + l2cap_set_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS); + } + } + } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) { + if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { + //Notify(PSTR("\r\nHID Control Configuration Request"), 0x80); + pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], control_scid); + } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { + //Notify(PSTR("\r\nHID Interrupt Configuration Request"), 0x80); + pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], interrupt_scid); + } + } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) { + if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nDisconnect Request: Control Channel"), 0x80); +#endif + identifier = l2capinbuf[9]; + pBtd->l2cap_disconnection_response(hci_handle, identifier, control_dcid, control_scid); + Reset(); + } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nDisconnect Request: Interrupt Channel"), 0x80); +#endif + identifier = l2capinbuf[9]; + pBtd->l2cap_disconnection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid); + Reset(); + } + } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) { + if(l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) { + //Notify(PSTR("\r\nDisconnect Response: Control Channel"), 0x80); + identifier = l2capinbuf[9]; + l2cap_set_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE); + } else if(l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) { + //Notify(PSTR("\r\nDisconnect Response: Interrupt Channel"), 0x80); + identifier = l2capinbuf[9]; + l2cap_set_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE); + } + } +#ifdef EXTRADEBUG + else { + identifier = l2capinbuf[9]; + Notify(PSTR("\r\nL2CAP Unknown Signaling Command: "), 0x80); + D_PrintHex (l2capinbuf[8], 0x80); + } +#endif + } else if(l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt +#ifdef PRINTREPORT + Notify(PSTR("\r\nL2CAP Interrupt: "), 0x80); + for(uint16_t i = 0; i < ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); i++) { + D_PrintHex (l2capinbuf[i + 8], 0x80); + Notify(PSTR(" "), 0x80); + } +#endif + if(l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT + uint16_t length = ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); + ParseBTHIDData((uint8_t)(length - 1), &l2capinbuf[9]); + + switch(l2capinbuf[9]) { + case 0x01: // Keyboard or Joystick events + if(pRptParser[KEYBOARD_PARSER_ID]) + pRptParser[KEYBOARD_PARSER_ID]->Parse(reinterpret_cast(this), 0, (uint8_t)(length - 2), &l2capinbuf[10]); // Use reinterpret_cast again to extract the instance + break; + + case 0x02: // Mouse events + if(pRptParser[MOUSE_PARSER_ID]) + pRptParser[MOUSE_PARSER_ID]->Parse(reinterpret_cast(this), 0, (uint8_t)(length - 2), &l2capinbuf[10]); // Use reinterpret_cast again to extract the instance + break; +#ifdef EXTRADEBUG + default: + Notify(PSTR("\r\nUnknown Report type: "), 0x80); + D_PrintHex (l2capinbuf[9], 0x80); + break; +#endif + } + } + } else if(l2capinbuf[6] == control_dcid[0] && l2capinbuf[7] == control_dcid[1]) { // l2cap_control +#ifdef PRINTREPORT + Notify(PSTR("\r\nL2CAP Control: "), 0x80); + for(uint16_t i = 0; i < ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); i++) { + D_PrintHex (l2capinbuf[i + 8], 0x80); + Notify(PSTR(" "), 0x80); + } +#endif + } +#ifdef EXTRADEBUG + else { + Notify(PSTR("\r\nUnsupported L2CAP Data - Channel ID: "), 0x80); + D_PrintHex (l2capinbuf[7], 0x80); + Notify(PSTR(" "), 0x80); + D_PrintHex (l2capinbuf[6], 0x80); + + Notify(PSTR("\r\nData: "), 0x80); + Notify(PSTR("\r\n"), 0x80); + for(uint16_t i = 0; i < ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); i++) { + D_PrintHex (l2capinbuf[i + 8], 0x80); + Notify(PSTR(" "), 0x80); + } + } +#endif + L2CAP_task(); + } +} + +void BTHID::L2CAP_task() { + switch(l2cap_state) { + /* These states are used if the HID device is the host */ + case L2CAP_CONTROL_SUCCESS: + if(l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nHID Control Successfully Configured"), 0x80); +#endif + setProtocol(); // Set protocol before establishing HID interrupt channel + l2cap_state = L2CAP_INTERRUPT_SETUP; + } + break; + + case L2CAP_INTERRUPT_SETUP: + if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST)) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nHID Interrupt Incoming Connection Request"), 0x80); +#endif + pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, PENDING); + delay(1); + pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, SUCCESSFUL); + identifier++; + delay(1); + pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid); + + l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST; + } + break; + + /* These states are used if the Arduino is the host */ + case L2CAP_CONTROL_CONNECT_REQUEST: + if(l2cap_check_flag(L2CAP_FLAG_CONTROL_CONNECTED)) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nSend HID Control Config Request"), 0x80); +#endif + identifier++; + pBtd->l2cap_config_request(hci_handle, identifier, control_scid); + l2cap_state = L2CAP_CONTROL_CONFIG_REQUEST; + } + break; + + case L2CAP_CONTROL_CONFIG_REQUEST: + if(l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) { + setProtocol(); // Set protocol before establishing HID interrupt channel + delay(1); // Short delay between commands - just to be sure +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nSend HID Interrupt Connection Request"), 0x80); +#endif + identifier++; + pBtd->l2cap_connection_request(hci_handle, identifier, interrupt_dcid, HID_INTR_PSM); + l2cap_state = L2CAP_INTERRUPT_CONNECT_REQUEST; + } + break; + + case L2CAP_INTERRUPT_CONNECT_REQUEST: + if(l2cap_check_flag(L2CAP_FLAG_INTERRUPT_CONNECTED)) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nSend HID Interrupt Config Request"), 0x80); +#endif + identifier++; + pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid); + l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST; + } + break; + + case L2CAP_INTERRUPT_CONFIG_REQUEST: + if(l2cap_check_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS)) { // Now the HID channels is established +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nHID Channels Established"), 0x80); +#endif + pBtd->connectToHIDDevice = false; + pBtd->pairWithHIDDevice = false; + connected = true; + onInit(); + l2cap_state = L2CAP_DONE; + } + break; + + case L2CAP_DONE: + break; + + case L2CAP_INTERRUPT_DISCONNECT: + if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE)) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nDisconnected Interrupt Channel"), 0x80); +#endif + identifier++; + pBtd->l2cap_disconnection_request(hci_handle, identifier, control_scid, control_dcid); + l2cap_state = L2CAP_CONTROL_DISCONNECT; + } + break; + + case L2CAP_CONTROL_DISCONNECT: + if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE)) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nDisconnected Control Channel"), 0x80); +#endif + pBtd->hci_disconnect(hci_handle); + hci_handle = -1; // Reset handle + l2cap_event_flag = 0; // Reset flags + l2cap_state = L2CAP_WAIT; + } + break; + } +} + +void BTHID::Run() { + switch(l2cap_state) { + case L2CAP_WAIT: + if(pBtd->connectToHIDDevice && !pBtd->l2capConnectionClaimed && !connected && !activeConnection) { + pBtd->l2capConnectionClaimed = true; + activeConnection = true; +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nSend HID Control Connection Request"), 0x80); +#endif + hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection + l2cap_event_flag = 0; // Reset flags + identifier = 0; + pBtd->l2cap_connection_request(hci_handle, identifier, control_dcid, HID_CTRL_PSM); + l2cap_state = L2CAP_CONTROL_CONNECT_REQUEST; + } else if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST)) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nHID Control Incoming Connection Request"), 0x80); +#endif + pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, PENDING); + delay(1); + pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, SUCCESSFUL); + identifier++; + delay(1); + pBtd->l2cap_config_request(hci_handle, identifier, control_scid); + l2cap_state = L2CAP_CONTROL_SUCCESS; + } + break; + } +} + +/************************************************************/ +/* HID Commands */ + +/************************************************************/ +void BTHID::setProtocol() { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nSet protocol mode: "), 0x80); + D_PrintHex (protocolMode, 0x80); +#endif + if (protocolMode != HID_BOOT_PROTOCOL && protocolMode != HID_RPT_PROTOCOL) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nNot a valid protocol mode. Using Boot protocol instead."), 0x80); +#endif + protocolMode = HID_BOOT_PROTOCOL; // Use Boot Protocol by default + } + uint8_t command = 0x70 | protocolMode; // Set Protocol, see Bluetooth HID specs page 33 + pBtd->L2CAP_Command(hci_handle, &command, 1, control_scid[0], control_scid[1]); +} + +void BTHID::setLeds(uint8_t data) { + uint8_t buf[3]; + buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) + buf[1] = 0x01; // Report ID + buf[2] = data; + pBtd->L2CAP_Command(hci_handle, buf, 3, interrupt_scid[0], interrupt_scid[1]); +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/BTHID.h b/lib/usbhost/USB_Host_Shield_2.0/BTHID.h new file mode 100644 index 0000000000..1a7d8687c7 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/BTHID.h @@ -0,0 +1,155 @@ +/* Copyright (C) 2013 Kristian Lauszus, TKJ Electronics. All rights reserved. + + This software may be distributed and modified under the terms of the GNU + General Public License version 2 (GPL2) as published by the Free Software + Foundation and appearing in the file GPL2.TXT included in the packaging of + this file. Please note that GPL2 Section 2[b] requires that all works based + on this software must also be made publicly available under the terms of + the GPL2 ("Copyleft"). + + Contact information + ------------------- + + Kristian Lauszus, TKJ Electronics + Web : http://www.tkjelectronics.com + e-mail : kristianl@tkjelectronics.com + */ + +#ifndef _bthid_h_ +#define _bthid_h_ + +#include "BTD.h" +#include "hidboot.h" + +#define KEYBOARD_PARSER_ID 0 +#define MOUSE_PARSER_ID 1 +#define NUM_PARSERS 2 + +/** This BluetoothService class implements support for Bluetooth HID devices. */ +class BTHID : public BluetoothService { +public: + /** + * Constructor for the BTHID class. + * @param p Pointer to the BTD class instance. + * @param pair Set this to true in order to pair with the device. If the argument is omitted then it will not pair with it. One can use ::PAIR to set it to true. + * @param pin Write the pin to BTD#btdPin. If argument is omitted, then "0000" will be used. + */ + BTHID(BTD *p, bool pair = false, const char *pin = "0000"); + + /** @name BluetoothService implementation */ + /** Used this to disconnect the devices. */ + void disconnect(); + /**@}*/ + + /** + * Get HIDReportParser. + * @param id ID of parser. + * @return Returns the corresponding HIDReportParser. Returns NULL if id is not valid. + */ + HIDReportParser *GetReportParser(uint8_t id) { + if (id >= NUM_PARSERS) + return NULL; + return pRptParser[id]; + }; + + /** + * Set HIDReportParser to be used. + * @param id Id of parser. + * @param prs Pointer to HIDReportParser. + * @return Returns true if the HIDReportParser is set. False otherwise. + */ + bool SetReportParser(uint8_t id, HIDReportParser *prs) { + if (id >= NUM_PARSERS) + return false; + pRptParser[id] = prs; + return true; + }; + + /** + * Set HID protocol mode. + * @param mode HID protocol to use. Either HID_BOOT_PROTOCOL or HID_RPT_PROTOCOL. + */ + void setProtocolMode(uint8_t mode) { + protocolMode = mode; + }; + + /** + * Used to set the leds on a keyboard. + * @param data See KBDLEDS in hidboot.h + */ + void setLeds(uint8_t data); + + /** True if a device is connected */ + bool connected; + + /** Call this to start the paring sequence with a device */ + void pair(void) { + if(pBtd) + pBtd->pairWithHID(); + }; + +protected: + /** @name BluetoothService implementation */ + /** + * Used to pass acldata to the services. + * @param ACLData Incoming acldata. + */ + void ACLData(uint8_t* ACLData); + /** Used to run part of the state machine. */ + void Run(); + /** Use this to reset the service. */ + void Reset(); + /** + * Called when a device is successfully initialized. + * Use attachOnInit(void (*funcOnInit)(void)) to call your own function. + * This is useful for instance if you want to set the LEDs in a specific way. + */ + void onInit() { + if(pFuncOnInit) + pFuncOnInit(); // Call the user function + OnInitBTHID(); + }; + /**@}*/ + + /** @name Overridable functions */ + /** + * Used to parse Bluetooth HID data to any class that inherits this class. + * @param len The length of the incoming data. + * @param buf Pointer to the data buffer. + */ + virtual void ParseBTHIDData(uint8_t len, uint8_t *buf) { + return; + }; + /** Called when a device is connected */ + virtual void OnInitBTHID() { + return; + }; + /** Used to reset any buffers in the class that inherits this */ + virtual void ResetBTHID() { + return; + } + /**@}*/ + + /** L2CAP source CID for HID_Control */ + uint8_t control_scid[2]; + + /** L2CAP source CID for HID_Interrupt */ + uint8_t interrupt_scid[2]; + +private: + HIDReportParser *pRptParser[NUM_PARSERS]; // Pointer to HIDReportParsers. + + /** Set report protocol. */ + void setProtocol(); + uint8_t protocolMode; + + void L2CAP_task(); // L2CAP state machine + + bool activeConnection; // Used to indicate if it already has established a connection + + /* Variables used for L2CAP communication */ + uint8_t control_dcid[2]; // L2CAP device CID for HID_Control - Always 0x0070 + uint8_t interrupt_dcid[2]; // L2CAP device CID for HID_Interrupt - Always 0x0071 + uint8_t l2cap_state; +}; +#endif diff --git a/lib/usbhost/USB_Host_Shield_2.0/PS3BT.cpp b/lib/usbhost/USB_Host_Shield_2.0/PS3BT.cpp new file mode 100644 index 0000000000..235092e0ac --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/PS3BT.cpp @@ -0,0 +1,634 @@ +/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. + + This software may be distributed and modified under the terms of the GNU + General Public License version 2 (GPL2) as published by the Free Software + Foundation and appearing in the file GPL2.TXT included in the packaging of + this file. Please note that GPL2 Section 2[b] requires that all works based + on this software must also be made publicly available under the terms of + the GPL2 ("Copyleft"). + + Contact information + ------------------- + + Kristian Lauszus, TKJ Electronics + Web : http://www.tkjelectronics.com + e-mail : kristianl@tkjelectronics.com + */ + +#include "PS3BT.h" +// To enable serial debugging see "settings.h" +//#define EXTRADEBUG // Uncomment to get even more debugging data +//#define PRINTREPORT // Uncomment to print the report send by the PS3 Controllers + +PS3BT::PS3BT(BTD *p, uint8_t btadr5, uint8_t btadr4, uint8_t btadr3, uint8_t btadr2, uint8_t btadr1, uint8_t btadr0) : +BluetoothService(p) // Pointer to USB class instance - mandatory +{ + pBtd->my_bdaddr[5] = btadr5; // Change to your dongle's Bluetooth address instead + pBtd->my_bdaddr[4] = btadr4; + pBtd->my_bdaddr[3] = btadr3; + pBtd->my_bdaddr[2] = btadr2; + pBtd->my_bdaddr[1] = btadr1; + pBtd->my_bdaddr[0] = btadr0; + + HIDBuffer[0] = 0x52; // HID BT Set_report (0x50) | Report Type (Output 0x02) + HIDBuffer[1] = 0x01; // Report ID + + // Needed for PS3 Move Controller commands to work via bluetooth + HIDMoveBuffer[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) + HIDMoveBuffer[1] = 0x02; // Report ID + + /* Set device cid for the control and intterrupt channelse - LSB */ + control_dcid[0] = 0x40; // 0x0040 + control_dcid[1] = 0x00; + interrupt_dcid[0] = 0x41; // 0x0041 + interrupt_dcid[1] = 0x00; + + Reset(); +} + +bool PS3BT::getButtonPress(ButtonEnum b) { + return (ButtonState & pgm_read_dword(&PS3_BUTTONS[(uint8_t)b])); +} + +bool PS3BT::getButtonClick(ButtonEnum b) { + uint32_t button = pgm_read_dword(&PS3_BUTTONS[(uint8_t)b]); + bool click = (ButtonClickState & button); + ButtonClickState &= ~button; // Clear "click" event + return click; +} + +uint8_t PS3BT::getAnalogButton(ButtonEnum a) { + return (uint8_t)(l2capinbuf[pgm_read_byte(&PS3_ANALOG_BUTTONS[(uint8_t)a])]); +} + +uint8_t PS3BT::getAnalogHat(AnalogHatEnum a) { + return (uint8_t)(l2capinbuf[(uint8_t)a + 15]); +} + +int16_t PS3BT::getSensor(SensorEnum a) { + if(PS3Connected) { + if(a == aX || a == aY || a == aZ || a == gZ) + return ((l2capinbuf[(uint16_t)a] << 8) | l2capinbuf[(uint16_t)a + 1]); + else + return 0; + } else if(PS3MoveConnected) { + if(a == mXmove || a == mYmove) // These are all 12-bits long + return (((l2capinbuf[(uint16_t)a] & 0x0F) << 8) | (l2capinbuf[(uint16_t)a + 1])); + else if(a == mZmove || a == tempMove) // The tempearature is also 12 bits long + return ((l2capinbuf[(uint16_t)a] << 4) | ((l2capinbuf[(uint16_t)a + 1] & 0xF0) >> 4)); + else // aXmove, aYmove, aZmove, gXmove, gYmove and gZmove + return (l2capinbuf[(uint16_t)a] | (l2capinbuf[(uint16_t)a + 1] << 8)); + } else + return 0; +} + +double PS3BT::getAngle(AngleEnum a) { + double accXval, accYval, accZval; + + if(PS3Connected) { + // Data for the Kionix KXPC4 used in the DualShock 3 + const double zeroG = 511.5; // 1.65/3.3*1023 (1.65V) + accXval = -((double)getSensor(aX) - zeroG); + accYval = -((double)getSensor(aY) - zeroG); + accZval = -((double)getSensor(aZ) - zeroG); + } else if(PS3MoveConnected) { + // It's a Kionix KXSC4 inside the Motion controller + const uint16_t zeroG = 0x8000; + accXval = -(int16_t)(getSensor(aXmove) - zeroG); + accYval = (int16_t)(getSensor(aYmove) - zeroG); + accZval = (int16_t)(getSensor(aZmove) - zeroG); + } else + return 0; + + // Convert to 360 degrees resolution + // atan2 outputs the value of -π to π (radians) + // We are then converting it to 0 to 2π and then to degrees + if(a == Pitch) + return (atan2(accYval, accZval) + PI) * RAD_TO_DEG; + else + return (atan2(accXval, accZval) + PI) * RAD_TO_DEG; +} + +double PS3BT::get9DOFValues(SensorEnum a) { // Thanks to Manfred Piendl + if(!PS3MoveConnected) + return 0; + int16_t value = getSensor(a); + if(a == mXmove || a == mYmove || a == mZmove) { + if(value > 2047) + value -= 0x1000; + return (double)value / 3.2; // unit: muT = 10^(-6) Tesla + } else if(a == aXmove || a == aYmove || a == aZmove) { + if(value < 0) + value += 0x8000; + else + value -= 0x8000; + return (double)value / 442.0; // unit: m/(s^2) + } else if(a == gXmove || a == gYmove || a == gZmove) { + if(value < 0) + value += 0x8000; + else + value -= 0x8000; + if(a == gXmove) + return (double)value / 11.6; // unit: deg/s + else if(a == gYmove) + return (double)value / 11.2; // unit: deg/s + else // gZmove + return (double)value / 9.6; // unit: deg/s + } else + return 0; +} + +String PS3BT::getTemperature() { + if(PS3MoveConnected) { + int16_t input = getSensor(tempMove); + + String output = String(input / 100); + output += "."; + if(input % 100 < 10) + output += "0"; + output += String(input % 100); + + return output; + } else + return "Error"; +} + +bool PS3BT::getStatus(StatusEnum c) { + return (l2capinbuf[(uint16_t)c >> 8] == ((uint8_t)c & 0xff)); +} + +void PS3BT::printStatusString() { + char statusOutput[100]; // Max string length plus null character + if(PS3Connected || PS3NavigationConnected) { + strcpy_P(statusOutput, PSTR("ConnectionStatus: ")); + + if(getStatus(Plugged)) strcat_P(statusOutput, PSTR("Plugged")); + else if(getStatus(Unplugged)) strcat_P(statusOutput, PSTR("Unplugged")); + else strcat_P(statusOutput, PSTR("Error")); + + strcat_P(statusOutput, PSTR(" - PowerRating: ")); + + if(getStatus(Charging)) strcat_P(statusOutput, PSTR("Charging")); + else if(getStatus(NotCharging)) strcat_P(statusOutput, PSTR("Not Charging")); + else if(getStatus(Shutdown)) strcat_P(statusOutput, PSTR("Shutdown")); + else if(getStatus(Dying)) strcat_P(statusOutput, PSTR("Dying")); + else if(getStatus(Low)) strcat_P(statusOutput, PSTR("Low")); + else if(getStatus(High)) strcat_P(statusOutput, PSTR("High")); + else if(getStatus(Full)) strcat_P(statusOutput, PSTR("Full")); + else strcat_P(statusOutput, PSTR("Error")); + + strcat_P(statusOutput, PSTR(" - WirelessStatus: ")); + + if(getStatus(CableRumble)) strcat_P(statusOutput, PSTR("Cable - Rumble is on")); + else if(getStatus(Cable)) strcat_P(statusOutput, PSTR("Cable - Rumble is off")); + else if(getStatus(BluetoothRumble)) strcat_P(statusOutput, PSTR("Bluetooth - Rumble is on")); + else if(getStatus(Bluetooth)) strcat_P(statusOutput, PSTR("Bluetooth - Rumble is off")); + else strcat_P(statusOutput, PSTR("Error")); + } else if(PS3MoveConnected) { + strcpy_P(statusOutput, PSTR("PowerRating: ")); + + if(getStatus(MoveCharging)) strcat_P(statusOutput, PSTR("Charging")); + else if(getStatus(MoveNotCharging)) strcat_P(statusOutput, PSTR("Not Charging")); + else if(getStatus(MoveShutdown)) strcat_P(statusOutput, PSTR("Shutdown")); + else if(getStatus(MoveDying)) strcat_P(statusOutput, PSTR("Dying")); + else if(getStatus(MoveLow)) strcat_P(statusOutput, PSTR("Low")); + else if(getStatus(MoveHigh)) strcat_P(statusOutput, PSTR("High")); + else if(getStatus(MoveFull)) strcat_P(statusOutput, PSTR("Full")); + else strcat_P(statusOutput, PSTR("Error")); + } else + strcpy_P(statusOutput, PSTR("Error")); + + USB_HOST_SERIAL.write(statusOutput); +} + +void PS3BT::Reset() { + PS3Connected = false; + PS3MoveConnected = false; + PS3NavigationConnected = false; + activeConnection = false; + l2cap_event_flag = 0; // Reset flags + l2cap_state = L2CAP_WAIT; + + // Needed for PS3 Dualshock Controller commands to work via Bluetooth + for(uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++) + HIDBuffer[i + 2] = pgm_read_byte(&PS3_REPORT_BUFFER[i]); // First two bytes reserved for report type and ID +} + +void PS3BT::disconnect() { // Use this void to disconnect any of the controllers + // First the HID interrupt channel has to be disconnected, then the HID control channel and finally the HCI connection + pBtd->l2cap_disconnection_request(hci_handle, ++identifier, interrupt_scid, interrupt_dcid); + Reset(); + l2cap_state = L2CAP_INTERRUPT_DISCONNECT; +} + +void PS3BT::ACLData(uint8_t* ACLData) { + if(!pBtd->l2capConnectionClaimed && !PS3Connected && !PS3MoveConnected && !PS3NavigationConnected && !activeConnection && !pBtd->connectToWii && !pBtd->incomingWii && !pBtd->pairWithWii) { + if(ACLData[8] == L2CAP_CMD_CONNECTION_REQUEST) { + if((ACLData[12] | (ACLData[13] << 8)) == HID_CTRL_PSM) { + pBtd->l2capConnectionClaimed = true; // Claim that the incoming connection belongs to this service + activeConnection = true; + hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection + l2cap_state = L2CAP_WAIT; + remote_name_first = pBtd->remote_name[0]; // Store the first letter in remote name for the connection +#ifdef DEBUG_USB_HOST + if(pBtd->hci_version < 3) { // Check the HCI Version of the Bluetooth dongle + Notify(PSTR("\r\nYour dongle may not support reading the analog buttons, sensors and status\r\nYour HCI Version is: "), 0x80); + Notify(pBtd->hci_version, 0x80); + Notify(PSTR("\r\nBut should be at least 3\r\nThis means that it doesn't support Bluetooth Version 2.0+EDR"), 0x80); + } +#endif + } + } + } + + if(checkHciHandle(ACLData, hci_handle)) { // acl_handle_ok + memcpy(l2capinbuf, ACLData, BULK_MAXPKTSIZE); + if((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001U) { // l2cap_control - Channel ID for ACL-U + if(l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80); + D_PrintHex (l2capinbuf[13], 0x80); + Notify(PSTR(" "), 0x80); + D_PrintHex (l2capinbuf[12], 0x80); + Notify(PSTR(" Data: "), 0x80); + D_PrintHex (l2capinbuf[17], 0x80); + Notify(PSTR(" "), 0x80); + D_PrintHex (l2capinbuf[16], 0x80); + Notify(PSTR(" "), 0x80); + D_PrintHex (l2capinbuf[15], 0x80); + Notify(PSTR(" "), 0x80); + D_PrintHex (l2capinbuf[14], 0x80); +#endif + } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { +#ifdef EXTRADEBUG + Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80); + D_PrintHex (l2capinbuf[13], 0x80); + Notify(PSTR(" "), 0x80); + D_PrintHex (l2capinbuf[12], 0x80); + Notify(PSTR(" SCID: "), 0x80); + D_PrintHex (l2capinbuf[15], 0x80); + Notify(PSTR(" "), 0x80); + D_PrintHex (l2capinbuf[14], 0x80); + Notify(PSTR(" Identifier: "), 0x80); + D_PrintHex (l2capinbuf[9], 0x80); +#endif + if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) { + identifier = l2capinbuf[9]; + control_scid[0] = l2capinbuf[14]; + control_scid[1] = l2capinbuf[15]; + l2cap_set_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST); + } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_INTR_PSM) { + identifier = l2capinbuf[9]; + interrupt_scid[0] = l2capinbuf[14]; + interrupt_scid[1] = l2capinbuf[15]; + l2cap_set_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST); + } + } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) { + if((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success + if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { + //Notify(PSTR("\r\nHID Control Configuration Complete"), 0x80); + l2cap_set_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS); + } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { + //Notify(PSTR("\r\nHID Interrupt Configuration Complete"), 0x80); + l2cap_set_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS); + } + } + } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) { + if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { + //Notify(PSTR("\r\nHID Control Configuration Request"), 0x80); + pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], control_scid); + } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { + //Notify(PSTR("\r\nHID Interrupt Configuration Request"), 0x80); + pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], interrupt_scid); + } + } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) { + if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nDisconnect Request: Control Channel"), 0x80); +#endif + identifier = l2capinbuf[9]; + pBtd->l2cap_disconnection_response(hci_handle, identifier, control_dcid, control_scid); + Reset(); + } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nDisconnect Request: Interrupt Channel"), 0x80); +#endif + identifier = l2capinbuf[9]; + pBtd->l2cap_disconnection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid); + Reset(); + } + } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) { + if(l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) { + //Notify(PSTR("\r\nDisconnect Response: Control Channel"), 0x80); + identifier = l2capinbuf[9]; + l2cap_set_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE); + } else if(l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) { + //Notify(PSTR("\r\nDisconnect Response: Interrupt Channel"), 0x80); + identifier = l2capinbuf[9]; + l2cap_set_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE); + } + } +#ifdef EXTRADEBUG + else { + Notify(PSTR("\r\nL2CAP Unknown Signaling Command: "), 0x80); + D_PrintHex (l2capinbuf[8], 0x80); + } +#endif + } else if(l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt + //Notify(PSTR("\r\nL2CAP Interrupt"), 0x80); + if(PS3Connected || PS3MoveConnected || PS3NavigationConnected) { + /* Read Report */ + if(l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT + lastMessageTime = millis(); // Store the last message time + + if(PS3Connected || PS3NavigationConnected) + ButtonState = (uint32_t)(l2capinbuf[11] | ((uint16_t)l2capinbuf[12] << 8) | ((uint32_t)l2capinbuf[13] << 16)); + else if(PS3MoveConnected) + ButtonState = (uint32_t)(l2capinbuf[10] | ((uint16_t)l2capinbuf[11] << 8) | ((uint32_t)l2capinbuf[12] << 16)); + + //Notify(PSTR("\r\nButtonState", 0x80); + //PrintHex(ButtonState, 0x80); + + if(ButtonState != OldButtonState) { + ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable + OldButtonState = ButtonState; + } + +#ifdef PRINTREPORT // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers + for(uint8_t i = 10; i < 58; i++) { + D_PrintHex (l2capinbuf[i], 0x80); + Notify(PSTR(" "), 0x80); + } + Notify(PSTR("\r\n"), 0x80); +#endif + } + } + } + L2CAP_task(); + } +} + +void PS3BT::L2CAP_task() { + switch(l2cap_state) { + case L2CAP_WAIT: + if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST)) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nHID Control Incoming Connection Request"), 0x80); +#endif + pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, PENDING); + delay(1); + pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, SUCCESSFUL); + identifier++; + delay(1); + pBtd->l2cap_config_request(hci_handle, identifier, control_scid); + l2cap_state = L2CAP_CONTROL_SUCCESS; + } + break; + + case L2CAP_CONTROL_SUCCESS: + if(l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nHID Control Successfully Configured"), 0x80); +#endif + l2cap_state = L2CAP_INTERRUPT_SETUP; + } + break; + + case L2CAP_INTERRUPT_SETUP: + if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST)) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nHID Interrupt Incoming Connection Request"), 0x80); +#endif + pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, PENDING); + delay(1); + pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, SUCCESSFUL); + identifier++; + delay(1); + pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid); + + l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST; + } + break; + + case L2CAP_INTERRUPT_CONFIG_REQUEST: + if(l2cap_check_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS)) { // Now the HID channels is established +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nHID Interrupt Successfully Configured"), 0x80); +#endif + if(remote_name_first == 'M') { // First letter in Motion Controller ('M') + memset(l2capinbuf, 0, BULK_MAXPKTSIZE); // Reset l2cap in buffer as it sometimes read it as a button has been pressed + l2cap_state = TURN_ON_LED; + } else + l2cap_state = PS3_ENABLE_SIXAXIS; + timer = millis(); + } + break; + + /* These states are handled in Run() */ + + case L2CAP_INTERRUPT_DISCONNECT: + if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE)) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nDisconnected Interrupt Channel"), 0x80); +#endif + identifier++; + pBtd->l2cap_disconnection_request(hci_handle, identifier, control_scid, control_dcid); + l2cap_state = L2CAP_CONTROL_DISCONNECT; + } + break; + + case L2CAP_CONTROL_DISCONNECT: + if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE)) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nDisconnected Control Channel"), 0x80); +#endif + pBtd->hci_disconnect(hci_handle); + hci_handle = -1; // Reset handle + l2cap_event_flag = 0; // Reset flags + l2cap_state = L2CAP_WAIT; + } + break; + } +} + +void PS3BT::Run() { + switch(l2cap_state) { + case PS3_ENABLE_SIXAXIS: + if(millis() - timer > 1000) { // loop 1 second before sending the command + memset(l2capinbuf, 0, BULK_MAXPKTSIZE); // Reset l2cap in buffer as it sometimes read it as a button has been pressed + for(uint8_t i = 15; i < 19; i++) + l2capinbuf[i] = 0x7F; // Set the analog joystick values to center position + enable_sixaxis(); + l2cap_state = TURN_ON_LED; + timer = millis(); + } + break; + + case TURN_ON_LED: + if(millis() - timer > 1000) { // loop 1 second before sending the command + if(remote_name_first == 'P') { // First letter in PLAYSTATION(R)3 Controller ('P') +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nDualshock 3 Controller Enabled\r\n"), 0x80); +#endif + PS3Connected = true; + } else if(remote_name_first == 'N') { // First letter in Navigation Controller ('N') +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nNavigation Controller Enabled\r\n"), 0x80); +#endif + PS3NavigationConnected = true; + } else if(remote_name_first == 'M') { // First letter in Motion Controller ('M') + timer = millis(); +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nMotion Controller Enabled\r\n"), 0x80); +#endif + PS3MoveConnected = true; + } + ButtonState = 0; // Clear all values + OldButtonState = 0; + ButtonClickState = 0; + + onInit(); // Turn on the LED on the controller + l2cap_state = L2CAP_DONE; + } + break; + + case L2CAP_DONE: + if(PS3MoveConnected) { // The Bulb and rumble values, has to be send at approximately every 5th second for it to stay on + if(millis() - timer > 4000) { // Send at least every 4th second + HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE); // The Bulb and rumble values, has to be written again and again, for it to stay turned on + timer = millis(); + } + } + break; + } +} + +/************************************************************/ +/* HID Commands */ +/************************************************************/ + +// Playstation Sixaxis Dualshock and Navigation Controller commands + +void PS3BT::HID_Command(uint8_t* data, uint8_t nbytes) { + if(millis() - timerHID <= 150) // Check if is has been more than 150ms since last command + delay((uint32_t)(150 - (millis() - timerHID))); // There have to be a delay between commands + pBtd->L2CAP_Command(hci_handle, data, nbytes, control_scid[0], control_scid[1]); // Both the Navigation and Dualshock controller sends data via the control channel + timerHID = millis(); +} + +void PS3BT::setAllOff() { + HIDBuffer[3] = 0x00; // Rumble bytes + HIDBuffer[4] = 0x00; + HIDBuffer[5] = 0x00; + HIDBuffer[6] = 0x00; + + HIDBuffer[11] = 0x00; // LED byte + + HID_Command(HIDBuffer, HID_BUFFERSIZE); +} + +void PS3BT::setRumbleOff() { + HIDBuffer[3] = 0x00; + HIDBuffer[4] = 0x00; + HIDBuffer[5] = 0x00; + HIDBuffer[6] = 0x00; + + HID_Command(HIDBuffer, HID_BUFFERSIZE); +} + +void PS3BT::setRumbleOn(RumbleEnum mode) { + uint8_t power[2] = {0xff, 0x00}; // Defaults to RumbleLow + if(mode == RumbleHigh) { + power[0] = 0x00; + power[1] = 0xff; + } + setRumbleOn(0xfe, power[0], 0xfe, power[1]); +} + +void PS3BT::setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower) { + HIDBuffer[3] = rightDuration; + HIDBuffer[4] = rightPower; + HIDBuffer[5] = leftDuration; + HIDBuffer[6] = leftPower; + HID_Command(HIDBuffer, HID_BUFFERSIZE); +} + +void PS3BT::setLedRaw(uint8_t value) { + HIDBuffer[11] = value << 1; + HID_Command(HIDBuffer, HID_BUFFERSIZE); +} + +void PS3BT::setLedOff(LEDEnum a) { + HIDBuffer[11] &= ~((uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1)); + HID_Command(HIDBuffer, HID_BUFFERSIZE); +} + +void PS3BT::setLedOn(LEDEnum a) { + if(a == OFF) + setLedRaw(0); + else { + HIDBuffer[11] |= (uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1); + HID_Command(HIDBuffer, HID_BUFFERSIZE); + } +} + +void PS3BT::setLedToggle(LEDEnum a) { + HIDBuffer[11] ^= (uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1); + HID_Command(HIDBuffer, HID_BUFFERSIZE); +} + +void PS3BT::enable_sixaxis() { // Command used to enable the Dualshock 3 and Navigation controller to send data via Bluetooth + uint8_t cmd_buf[6]; + cmd_buf[0] = 0x53; // HID BT Set_report (0x50) | Report Type (Feature 0x03) + cmd_buf[1] = 0xF4; // Report ID + cmd_buf[2] = 0x42; // Special PS3 Controller enable commands + cmd_buf[3] = 0x03; + cmd_buf[4] = 0x00; + cmd_buf[5] = 0x00; + + HID_Command(cmd_buf, 6); +} + +// Playstation Move Controller commands + +void PS3BT::HIDMove_Command(uint8_t* data, uint8_t nbytes) { + if(millis() - timerHID <= 150)// Check if is has been less than 150ms since last command + delay((uint32_t)(150 - (millis() - timerHID))); // There have to be a delay between commands + pBtd->L2CAP_Command(hci_handle, data, nbytes, interrupt_scid[0], interrupt_scid[1]); // The Move controller sends it's data via the intterrupt channel + timerHID = millis(); +} + +void PS3BT::moveSetBulb(uint8_t r, uint8_t g, uint8_t b) { // Use this to set the Color using RGB values + // Set the Bulb's values into the write buffer + HIDMoveBuffer[3] = r; + HIDMoveBuffer[4] = g; + HIDMoveBuffer[5] = b; + + HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE); +} + +void PS3BT::moveSetBulb(ColorsEnum color) { // Use this to set the Color using the predefined colors in enum + moveSetBulb((uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color)); +} + +void PS3BT::moveSetRumble(uint8_t rumble) { +#ifdef DEBUG_USB_HOST + if(rumble < 64 && rumble != 0) // The rumble value has to at least 64, or approximately 25% (64/255*100) + Notify(PSTR("\r\nThe rumble value has to at least 64, or approximately 25%"), 0x80); +#endif + // Set the rumble value into the write buffer + HIDMoveBuffer[7] = rumble; + + HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE); +} + +void PS3BT::onInit() { + if(pFuncOnInit) + pFuncOnInit(); // Call the user function + else { + if(PS3MoveConnected) + moveSetBulb(Red); + else // Dualshock 3 or Navigation controller + setLedOn(LED1); + } +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/PS3BT.h b/lib/usbhost/USB_Host_Shield_2.0/PS3BT.h new file mode 100644 index 0000000000..c25ac5e59d --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/PS3BT.h @@ -0,0 +1,240 @@ +/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. + + This software may be distributed and modified under the terms of the GNU + General Public License version 2 (GPL2) as published by the Free Software + Foundation and appearing in the file GPL2.TXT included in the packaging of + this file. Please note that GPL2 Section 2[b] requires that all works based + on this software must also be made publicly available under the terms of + the GPL2 ("Copyleft"). + + Contact information + ------------------- + + Kristian Lauszus, TKJ Electronics + Web : http://www.tkjelectronics.com + e-mail : kristianl@tkjelectronics.com + */ + +#ifndef _ps3bt_h_ +#define _ps3bt_h_ + +#include "BTD.h" +#include "PS3Enums.h" + +#define HID_BUFFERSIZE 50 // Size of the buffer for the Playstation Motion Controller + +/** + * This BluetoothService class implements support for all the official PS3 Controllers: + * Dualshock 3, Navigation or a Motion controller via Bluetooth. + * + * Information about the protocol can be found at the wiki: https://github.com/felis/USB_Host_Shield_2.0/wiki/PS3-Information. + */ +class PS3BT : public BluetoothService { +public: + /** + * Constructor for the PS3BT class. + * @param pBtd Pointer to BTD class instance. + * @param btadr5,btadr4,btadr3,btadr2,btadr1,btadr0 + * Pass your dongles Bluetooth address into the constructor, + * This will set BTD#my_bdaddr, so you don't have to plug in the dongle before pairing with your controller. + */ + PS3BT(BTD *pBtd, uint8_t btadr5 = 0, uint8_t btadr4 = 0, uint8_t btadr3 = 0, uint8_t btadr2 = 0, uint8_t btadr1 = 0, uint8_t btadr0 = 0); + + /** @name BluetoothService implementation */ + /** Used this to disconnect any of the controllers. */ + void disconnect(); + /**@}*/ + + /** @name PS3 Controller functions */ + /** + * getButtonPress(ButtonEnum b) will return true as long as the button is held down. + * + * While getButtonClick(ButtonEnum b) will only return it once. + * + * So you instance if you need to increase a variable once you would use getButtonClick(ButtonEnum b), + * but if you need to drive a robot forward you would use getButtonPress(ButtonEnum b). + * @param b ::ButtonEnum to read. + * @return getButtonPress(ButtonEnum b) will return a true as long as a button is held down, while getButtonClick(ButtonEnum b) will return true once for each button press. + */ + bool getButtonPress(ButtonEnum b); + bool getButtonClick(ButtonEnum b); + /**@}*/ + /** @name PS3 Controller functions */ + /** + * Used to get the analog value from button presses. + * @param a The ::ButtonEnum to read. + * The supported buttons are: + * ::UP, ::RIGHT, ::DOWN, ::LEFT, ::L1, ::L2, ::R1, ::R2, + * ::TRIANGLE, ::CIRCLE, ::CROSS, ::SQUARE, and ::T. + * @return Analog value in the range of 0-255. + */ + uint8_t getAnalogButton(ButtonEnum a); + /** + * Used to read the analog joystick. + * @param a ::LeftHatX, ::LeftHatY, ::RightHatX, and ::RightHatY. + * @return Return the analog value in the range of 0-255. + */ + uint8_t getAnalogHat(AnalogHatEnum a); + /** + * Used to read the sensors inside the Dualshock 3 and Move controller. + * @param a + * The Dualshock 3 has a 3-axis accelerometer and a 1-axis gyro inside. + * The Move controller has a 3-axis accelerometer, a 3-axis gyro, a 3-axis magnetometer + * and a temperature sensor inside. + * @return Return the raw sensor value. + */ + int16_t getSensor(SensorEnum a); + /** + * Use this to get ::Pitch and ::Roll calculated using the accelerometer. + * @param a Either ::Pitch or ::Roll. + * @return Return the angle in the range of 0-360. + */ + double getAngle(AngleEnum a); + /** + * Read the sensors inside the Move controller. + * @param a ::aXmove, ::aYmove, ::aZmove, ::gXmove, ::gYmove, ::gZmove, ::mXmove, ::mYmove, and ::mXmove. + * @return The value in SI units. + */ + double get9DOFValues(SensorEnum a); + /** + * Get the status from the controller. + * @param c The ::StatusEnum you want to read. + * @return True if correct and false if not. + */ + bool getStatus(StatusEnum c); + /** Read all the available statuses from the controller and prints it as a nice formated string. */ + void printStatusString(); + /** + * Read the temperature from the Move controller. + * @return The temperature in degrees Celsius. + */ + String getTemperature(); + + /** Used to set all LEDs and rumble off. */ + void setAllOff(); + /** Turn off rumble. */ + void setRumbleOff(); + /** + * Turn on rumble. + * @param mode Either ::RumbleHigh or ::RumbleLow. + */ + void setRumbleOn(RumbleEnum mode); + /** + * Turn on rumble using custom duration and power. + * @param rightDuration The duration of the right/low rumble effect. + * @param rightPower The intensity of the right/low rumble effect. + * @param leftDuration The duration of the left/high rumble effect. + * @param leftPower The intensity of the left/high rumble effect. + */ + void setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower); + + /** + * Set LED value without using ::LEDEnum. + * @param value See: ::LEDEnum. + */ + void setLedRaw(uint8_t value); + + /** Turn all LEDs off. */ + void setLedOff() { + setLedRaw(0); + }; + /** + * Turn the specific LED off. + * @param a The ::LEDEnum to turn off. + */ + void setLedOff(LEDEnum a); + /** + * Turn the specific LED on. + * @param a The ::LEDEnum to turn on. + */ + void setLedOn(LEDEnum a); + /** + * Toggle the specific LED. + * @param a The ::LEDEnum to toggle. + */ + void setLedToggle(LEDEnum a); + + /** + * Use this to set the Color using RGB values. + * @param r,g,b RGB value. + */ + void moveSetBulb(uint8_t r, uint8_t g, uint8_t b); + /** + * Use this to set the color using the predefined colors in ::ColorsEnum. + * @param color The desired color. + */ + void moveSetBulb(ColorsEnum color); + /** + * Set the rumble value inside the Move controller. + * @param rumble The desired value in the range from 64-255. + */ + void moveSetRumble(uint8_t rumble); + + /** Used to get the millis() of the last message */ + uint32_t getLastMessageTime() { + return lastMessageTime; + }; + /**@}*/ + + /** Variable used to indicate if the normal Playstation controller is successfully connected. */ + bool PS3Connected; + /** Variable used to indicate if the Move controller is successfully connected. */ + bool PS3MoveConnected; + /** Variable used to indicate if the Navigation controller is successfully connected. */ + bool PS3NavigationConnected; + +protected: + /** @name BluetoothService implementation */ + /** + * Used to pass acldata to the services. + * @param ACLData Incoming acldata. + */ + void ACLData(uint8_t* ACLData); + /** Used to run part of the state machine. */ + void Run(); + /** Use this to reset the service. */ + void Reset(); + /** + * Called when the controller is successfully initialized. + * Use attachOnInit(void (*funcOnInit)(void)) to call your own function. + * This is useful for instance if you want to set the LEDs in a specific way. + */ + void onInit(); + /**@}*/ + +private: + + void L2CAP_task(); // L2CAP state machine + + /* Variables filled from HCI event management */ + char remote_name_first; // First letter in remote name + bool activeConnection; // Used to indicate if it's already has established a connection + + /* Variables used by high level L2CAP task */ + uint8_t l2cap_state; + + uint32_t lastMessageTime; // Variable used to store the millis value of the last message. + + uint32_t ButtonState; + uint32_t OldButtonState; + uint32_t ButtonClickState; + + uint32_t timer; // Timer used to limit time between messages and also used to continuously set PS3 Move controller Bulb and rumble values + uint32_t timerHID; // Timer used see if there has to be a delay before a new HID command + + uint8_t l2capinbuf[BULK_MAXPKTSIZE]; // General purpose buffer for L2CAP in data + uint8_t HIDBuffer[HID_BUFFERSIZE]; // Used to store HID commands + uint8_t HIDMoveBuffer[HID_BUFFERSIZE]; // Used to store HID commands for the Move controller + + /* L2CAP Channels */ + uint8_t control_scid[2]; // L2CAP source CID for HID_Control + uint8_t control_dcid[2]; // 0x0040 + uint8_t interrupt_scid[2]; // L2CAP source CID for HID_Interrupt + uint8_t interrupt_dcid[2]; // 0x0041 + + /* HID Commands */ + void HID_Command(uint8_t* data, uint8_t nbytes); + void HIDMove_Command(uint8_t* data, uint8_t nbytes); + void enable_sixaxis(); // Command used to enable the Dualshock 3 and Navigation controller to send data via Bluetooth +}; +#endif diff --git a/lib/usbhost/USB_Host_Shield_2.0/PS3Enums.h b/lib/usbhost/USB_Host_Shield_2.0/PS3Enums.h new file mode 100644 index 0000000000..77801945f2 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/PS3Enums.h @@ -0,0 +1,141 @@ +/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. + + This software may be distributed and modified under the terms of the GNU + General Public License version 2 (GPL2) as published by the Free Software + Foundation and appearing in the file GPL2.TXT included in the packaging of + this file. Please note that GPL2 Section 2[b] requires that all works based + on this software must also be made publicly available under the terms of + the GPL2 ("Copyleft"). + + Contact information + ------------------- + + Kristian Lauszus, TKJ Electronics + Web : http://www.tkjelectronics.com + e-mail : kristianl@tkjelectronics.com + */ + +#ifndef _ps3enums_h +#define _ps3enums_h + +#include "controllerEnums.h" + +/** Size of the output report buffer for the Dualshock and Navigation controllers */ +#define PS3_REPORT_BUFFER_SIZE 48 + +/** Report buffer for all PS3 commands */ +const uint8_t PS3_REPORT_BUFFER[PS3_REPORT_BUFFER_SIZE] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/** Size of the output report buffer for the Move Controller */ +#define MOVE_REPORT_BUFFER_SIZE 7 + +/** Used to set the LEDs on the controllers */ +const uint8_t PS3_LEDS[] PROGMEM = { + 0x00, // OFF + 0x01, // LED1 + 0x02, // LED2 + 0x04, // LED3 + 0x08, // LED4 + + 0x09, // LED5 + 0x0A, // LED6 + 0x0C, // LED7 + 0x0D, // LED8 + 0x0E, // LED9 + 0x0F, // LED10 +}; + +/** + * Buttons on the controllers. + * Note: that the location is shifted 9 when it's connected via USB. + */ +const uint32_t PS3_BUTTONS[] PROGMEM = { + 0x10, // UP + 0x20, // RIGHT + 0x40, // DOWN + 0x80, // LEFT + + 0x01, // SELECT + 0x08, // START + 0x02, // L3 + 0x04, // R3 + + 0x0100, // L2 + 0x0200, // R2 + 0x0400, // L1 + 0x0800, // R1 + + 0x1000, // TRIANGLE + 0x2000, // CIRCLE + 0x4000, // CROSS + 0x8000, // SQUARE + + 0x010000, // PS + 0x080000, // MOVE - covers 12 bits - we only need to read the top 8 + 0x100000, // T - covers 12 bits - we only need to read the top 8 +}; + +/** + * Analog buttons on the controllers. + * Note: that the location is shifted 9 when it's connected via USB. + */ +const uint8_t PS3_ANALOG_BUTTONS[] PROGMEM = { + 23, // UP_ANALOG + 24, // RIGHT_ANALOG + 25, // DOWN_ANALOG + 26, // LEFT_ANALOG + 0, 0, 0, 0, // Skip SELECT, L3, R3 and START + + 27, // L2_ANALOG + 28, // R2_ANALOG + 29, // L1_ANALOG + 30, // R1_ANALOG + 31, // TRIANGLE_ANALOG + 32, // CIRCLE_ANALOG + 33, // CROSS_ANALOG + 34, // SQUARE_ANALOG + 0, 0, // Skip PS and MOVE + + // Playstation Move Controller + 15, // T_ANALOG - Both at byte 14 (last reading) and byte 15 (current reading) +}; + +enum StatusEnum { + // Note that the location is shifted 9 when it's connected via USB + // Byte location | bit location + Plugged = (38 << 8) | 0x02, + Unplugged = (38 << 8) | 0x03, + + Charging = (39 << 8) | 0xEE, + NotCharging = (39 << 8) | 0xF1, + Shutdown = (39 << 8) | 0x01, + Dying = (39 << 8) | 0x02, + Low = (39 << 8) | 0x03, + High = (39 << 8) | 0x04, + Full = (39 << 8) | 0x05, + + MoveCharging = (21 << 8) | 0xEE, + MoveNotCharging = (21 << 8) | 0xF1, + MoveShutdown = (21 << 8) | 0x01, + MoveDying = (21 << 8) | 0x02, + MoveLow = (21 << 8) | 0x03, + MoveHigh = (21 << 8) | 0x04, + MoveFull = (21 << 8) | 0x05, + + CableRumble = (40 << 8) | 0x10, // Operating by USB and rumble is turned on + Cable = (40 << 8) | 0x12, // Operating by USB and rumble is turned off + BluetoothRumble = (40 << 8) | 0x14, // Operating by Bluetooth and rumble is turned on + Bluetooth = (40 << 8) | 0x16, // Operating by Bluetooth and rumble is turned off +}; + +#endif diff --git a/lib/usbhost/USB_Host_Shield_2.0/PS3USB.cpp b/lib/usbhost/USB_Host_Shield_2.0/PS3USB.cpp new file mode 100644 index 0000000000..c32175389c --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/PS3USB.cpp @@ -0,0 +1,572 @@ +/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. + + This software may be distributed and modified under the terms of the GNU + General Public License version 2 (GPL2) as published by the Free Software + Foundation and appearing in the file GPL2.TXT included in the packaging of + this file. Please note that GPL2 Section 2[b] requires that all works based + on this software must also be made publicly available under the terms of + the GPL2 ("Copyleft"). + + Contact information + ------------------- + + Kristian Lauszus, TKJ Electronics + Web : http://www.tkjelectronics.com + e-mail : kristianl@tkjelectronics.com + */ + +#include "PS3USB.h" +// To enable serial debugging see "settings.h" +//#define EXTRADEBUG // Uncomment to get even more debugging data +//#define PRINTREPORT // Uncomment to print the report send by the PS3 Controllers + +PS3USB::PS3USB(USB *p, uint8_t btadr5, uint8_t btadr4, uint8_t btadr3, uint8_t btadr2, uint8_t btadr1, uint8_t btadr0) : +pUsb(p), // pointer to USB class instance - mandatory +bAddress(0), // device address - mandatory +bPollEnable(false) // don't start polling before dongle is connected +{ + for(uint8_t i = 0; i < PS3_MAX_ENDPOINTS; i++) { + epInfo[i].epAddr = 0; + epInfo[i].maxPktSize = (i) ? 0 : 8; + epInfo[i].epAttribs = 0; + epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; + } + + if(pUsb) // register in USB subsystem + pUsb->RegisterDeviceClass(this); //set devConfig[] entry + + my_bdaddr[5] = btadr5; // Change to your dongle's Bluetooth address instead + my_bdaddr[4] = btadr4; + my_bdaddr[3] = btadr3; + my_bdaddr[2] = btadr2; + my_bdaddr[1] = btadr1; + my_bdaddr[0] = btadr0; +} + +uint8_t PS3USB::Init(uint8_t parent, uint8_t port, bool lowspeed) { + uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)]; + USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + uint16_t PID; + uint16_t VID; + + // get memory address of USB device address pool + AddressPool &addrPool = pUsb->GetAddressPool(); +#ifdef EXTRADEBUG + Notify(PSTR("\r\nPS3USB Init"), 0x80); +#endif + // check if address has already been assigned to an instance + if(bAddress) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nAddress in use"), 0x80); +#endif + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; + } + + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); + + if(!p) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nAddress not found"), 0x80); +#endif + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + } + + if(!p->epinfo) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nepinfo is null"), 0x80); +#endif + return USB_ERROR_EPINFO_IS_NULL; + } + + // Save old pointer to EP_RECORD of address 0 + oldep_ptr = p->epinfo; + + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence + p->epinfo = epInfo; + + p->lowspeed = lowspeed; + + // Get device descriptor + rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data + // Restore p->epinfo + p->epinfo = oldep_ptr; + + if(rcode) + goto FailGetDevDescr; + + VID = udd->idVendor; + PID = udd->idProduct; + + if(VID != PS3_VID || (PID != PS3_PID && PID != PS3NAVIGATION_PID && PID != PS3MOVE_PID)) + goto FailUnknownDevice; + + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, false, port); + + if(!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + // Extract Max Packet Size from device descriptor + epInfo[0].maxPktSize = udd->bMaxPacketSize0; + + // Assign new address to the device + rcode = pUsb->setAddr(0, 0, bAddress); + if(rcode) { + p->lowspeed = false; + addrPool.FreeAddress(bAddress); + bAddress = 0; +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nsetAddr: "), 0x80); + D_PrintHex (rcode, 0x80); +#endif + return rcode; + } +#ifdef EXTRADEBUG + Notify(PSTR("\r\nAddr: "), 0x80); + D_PrintHex (bAddress, 0x80); +#endif + //delay(300); // Spec says you should wait at least 200ms + + p->lowspeed = false; + + //get pointer to assigned address record + p = addrPool.GetUsbDevicePtr(bAddress); + if(!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->lowspeed = lowspeed; + + // Assign epInfo to epinfo pointer - only EP0 is known + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); + if(rcode) + goto FailSetDevTblEntry; + + + /* The application will work in reduced host mode, so we can save program and data + memory space. After verifying the PID and VID we will use known values for the + configuration values for device, interface, endpoints and HID for the PS3 Controllers */ + + /* Initialize data structures for endpoints of device */ + epInfo[ PS3_OUTPUT_PIPE ].epAddr = 0x02; // PS3 output endpoint + epInfo[ PS3_OUTPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; + epInfo[ PS3_OUTPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints + epInfo[ PS3_OUTPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; + epInfo[ PS3_OUTPUT_PIPE ].bmSndToggle = 0; + epInfo[ PS3_OUTPUT_PIPE ].bmRcvToggle = 0; + epInfo[ PS3_INPUT_PIPE ].epAddr = 0x01; // PS3 report endpoint + epInfo[ PS3_INPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; + epInfo[ PS3_INPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints + epInfo[ PS3_INPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; + epInfo[ PS3_INPUT_PIPE ].bmSndToggle = 0; + epInfo[ PS3_INPUT_PIPE ].bmRcvToggle = 0; + + rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo); + if(rcode) + goto FailSetDevTblEntry; + + delay(200); //Give time for address change + + rcode = pUsb->setConf(bAddress, epInfo[ PS3_CONTROL_PIPE ].epAddr, 1); + if(rcode) + goto FailSetConfDescr; + + if(PID == PS3_PID || PID == PS3NAVIGATION_PID) { + if(PID == PS3_PID) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nDualshock 3 Controller Connected"), 0x80); +#endif + PS3Connected = true; + } else { // must be a navigation controller +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nNavigation Controller Connected"), 0x80); +#endif + PS3NavigationConnected = true; + } + enable_sixaxis(); // The PS3 controller needs a special command before it starts sending data + + // Needed for PS3 Dualshock and Navigation commands to work + for(uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++) + writeBuf[i] = pgm_read_byte(&PS3_REPORT_BUFFER[i]); + + for(uint8_t i = 6; i < 10; i++) + readBuf[i] = 0x7F; // Set the analog joystick values to center position + } else { // must be a Motion controller +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nMotion Controller Connected"), 0x80); +#endif + PS3MoveConnected = true; + writeBuf[0] = 0x02; // Set report ID, this is needed for Move commands to work + } + if(my_bdaddr[0] != 0x00 || my_bdaddr[1] != 0x00 || my_bdaddr[2] != 0x00 || my_bdaddr[3] != 0x00 || my_bdaddr[4] != 0x00 || my_bdaddr[5] != 0x00) { + if(PS3MoveConnected) + setMoveBdaddr(my_bdaddr); // Set internal Bluetooth address + else + setBdaddr(my_bdaddr); // Set internal Bluetooth address + +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nBluetooth Address was set to: "), 0x80); + for(int8_t i = 5; i > 0; i--) { + D_PrintHex (my_bdaddr[i], 0x80); + Notify(PSTR(":"), 0x80); + } + D_PrintHex (my_bdaddr[0], 0x80); +#endif + } + onInit(); + + bPollEnable = true; + Notify(PSTR("\r\n"), 0x80); + timer = millis(); + return 0; // Successful configuration + + /* Diagnostic messages */ +FailGetDevDescr: +#ifdef DEBUG_USB_HOST + NotifyFailGetDevDescr(); + goto Fail; +#endif + +FailSetDevTblEntry: +#ifdef DEBUG_USB_HOST + NotifyFailSetDevTblEntry(); + goto Fail; +#endif + +FailSetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailSetConfDescr(); +#endif + goto Fail; + +FailUnknownDevice: +#ifdef DEBUG_USB_HOST + NotifyFailUnknownDevice(VID, PID); +#endif + rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + +Fail: +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nPS3 Init Failed, error code: "), 0x80); + NotifyFail(rcode); +#endif + Release(); + return rcode; +} + +/* Performs a cleanup after failed Init() attempt */ +uint8_t PS3USB::Release() { + PS3Connected = false; + PS3MoveConnected = false; + PS3NavigationConnected = false; + pUsb->GetAddressPool().FreeAddress(bAddress); + bAddress = 0; + bPollEnable = false; + return 0; +} + +uint8_t PS3USB::Poll() { + if(!bPollEnable) + return 0; + + if(PS3Connected || PS3NavigationConnected) { + uint16_t BUFFER_SIZE = EP_MAXPKTSIZE; + pUsb->inTransfer(bAddress, epInfo[ PS3_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf); // input on endpoint 1 + if(millis() - timer > 100) { // Loop 100ms before processing data + readReport(); +#ifdef PRINTREPORT + printReport(); // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers +#endif + } + } else if(PS3MoveConnected) { // One can only set the color of the bulb, set the rumble, set and get the bluetooth address and calibrate the magnetometer via USB + if(millis() - timer > 4000) { // Send at least every 4th second + Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE); // The Bulb and rumble values, has to be written again and again, for it to stay turned on + timer = millis(); + } + } + return 0; +} + +void PS3USB::readReport() { + ButtonState = (uint32_t)(readBuf[2] | ((uint16_t)readBuf[3] << 8) | ((uint32_t)readBuf[4] << 16)); + + //Notify(PSTR("\r\nButtonState", 0x80); + //PrintHex(ButtonState, 0x80); + + if(ButtonState != OldButtonState) { + ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable + OldButtonState = ButtonState; + } +} + +void PS3USB::printReport() { // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers +#ifdef PRINTREPORT + for(uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++) { + D_PrintHex (readBuf[i], 0x80); + Notify(PSTR(" "), 0x80); + } + Notify(PSTR("\r\n"), 0x80); +#endif +} + +bool PS3USB::getButtonPress(ButtonEnum b) { + return (ButtonState & pgm_read_dword(&PS3_BUTTONS[(uint8_t)b])); +} + +bool PS3USB::getButtonClick(ButtonEnum b) { + uint32_t button = pgm_read_dword(&PS3_BUTTONS[(uint8_t)b]); + bool click = (ButtonClickState & button); + ButtonClickState &= ~button; // Clear "click" event + return click; +} + +uint8_t PS3USB::getAnalogButton(ButtonEnum a) { + return (uint8_t)(readBuf[(pgm_read_byte(&PS3_ANALOG_BUTTONS[(uint8_t)a])) - 9]); +} + +uint8_t PS3USB::getAnalogHat(AnalogHatEnum a) { + return (uint8_t)(readBuf[((uint8_t)a + 6)]); +} + +uint16_t PS3USB::getSensor(SensorEnum a) { + return ((readBuf[((uint16_t)a) - 9] << 8) | readBuf[((uint16_t)a + 1) - 9]); +} + +double PS3USB::getAngle(AngleEnum a) { + if(PS3Connected) { + double accXval; + double accYval; + double accZval; + + // Data for the Kionix KXPC4 used in the DualShock 3 + const double zeroG = 511.5; // 1.65/3.3*1023 (1,65V) + accXval = -((double)getSensor(aX) - zeroG); + accYval = -((double)getSensor(aY) - zeroG); + accZval = -((double)getSensor(aZ) - zeroG); + + // Convert to 360 degrees resolution + // atan2 outputs the value of -π to π (radians) + // We are then converting it to 0 to 2π and then to degrees + if(a == Pitch) + return (atan2(accYval, accZval) + PI) * RAD_TO_DEG; + else + return (atan2(accXval, accZval) + PI) * RAD_TO_DEG; + } else + return 0; +} + +bool PS3USB::getStatus(StatusEnum c) { + return (readBuf[((uint16_t)c >> 8) - 9] == ((uint8_t)c & 0xff)); +} + +void PS3USB::printStatusString() { + char statusOutput[100]; // Max string length plus null character + if(PS3Connected || PS3NavigationConnected) { + strcpy_P(statusOutput, PSTR("ConnectionStatus: ")); + + if(getStatus(Plugged)) strcat_P(statusOutput, PSTR("Plugged")); + else if(getStatus(Unplugged)) strcat_P(statusOutput, PSTR("Unplugged")); + else strcat_P(statusOutput, PSTR("Error")); + + strcat_P(statusOutput, PSTR(" - PowerRating: ")); + + if(getStatus(Charging)) strcat_P(statusOutput, PSTR("Charging")); + else if(getStatus(NotCharging)) strcat_P(statusOutput, PSTR("Not Charging")); + else if(getStatus(Shutdown)) strcat_P(statusOutput, PSTR("Shutdown")); + else if(getStatus(Dying)) strcat_P(statusOutput, PSTR("Dying")); + else if(getStatus(Low)) strcat_P(statusOutput, PSTR("Low")); + else if(getStatus(High)) strcat_P(statusOutput, PSTR("High")); + else if(getStatus(Full)) strcat_P(statusOutput, PSTR("Full")); + else strcat_P(statusOutput, PSTR("Error")); + + strcat_P(statusOutput, PSTR(" - WirelessStatus: ")); + + if(getStatus(CableRumble)) strcat_P(statusOutput, PSTR("Cable - Rumble is on")); + else if(getStatus(Cable)) strcat_P(statusOutput, PSTR("Cable - Rumble is off")); + else if(getStatus(BluetoothRumble)) strcat_P(statusOutput, PSTR("Bluetooth - Rumble is on")); + else if(getStatus(Bluetooth)) strcat_P(statusOutput, PSTR("Bluetooth - Rumble is off")); + else strcat_P(statusOutput, PSTR("Error")); + } else + strcpy_P(statusOutput, PSTR("Error")); + + USB_HOST_SERIAL.write(statusOutput); +} + +/* Playstation Sixaxis Dualshock and Navigation Controller commands */ +void PS3USB::PS3_Command(uint8_t *data, uint16_t nbytes) { + // bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x01), Report Type (Output 0x02), interface (0x00), datalength, datalength, data) + pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x01, 0x02, 0x00, nbytes, nbytes, data, NULL); +} + +void PS3USB::setAllOff() { + for(uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++) + writeBuf[i] = pgm_read_byte(&PS3_REPORT_BUFFER[i]); // Reset buffer + + PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); +} + +void PS3USB::setRumbleOff() { + writeBuf[1] = 0x00; + writeBuf[2] = 0x00; // Low mode off + writeBuf[3] = 0x00; + writeBuf[4] = 0x00; // High mode off + + PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); +} + +void PS3USB::setRumbleOn(RumbleEnum mode) { + if((mode & 0x30) > 0x00) { + uint8_t power[2] = {0xff, 0x00}; // Defaults to RumbleLow + if(mode == RumbleHigh) { + power[0] = 0x00; + power[1] = 0xff; + } + setRumbleOn(0xfe, power[0], 0xfe, power[1]); + } +} + +void PS3USB::setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower) { + writeBuf[1] = rightDuration; + writeBuf[2] = rightPower; + writeBuf[3] = leftDuration; + writeBuf[4] = leftPower; + PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); +} + +void PS3USB::setLedRaw(uint8_t value) { + writeBuf[9] = value << 1; + PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); +} + +void PS3USB::setLedOff(LEDEnum a) { + writeBuf[9] &= ~((uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1)); + PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); +} + +void PS3USB::setLedOn(LEDEnum a) { + if(a == OFF) + setLedRaw(0); + else { + writeBuf[9] |= (uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1); + PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); + } +} + +void PS3USB::setLedToggle(LEDEnum a) { + writeBuf[9] ^= (uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1); + PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); +} + +void PS3USB::setBdaddr(uint8_t *bdaddr) { + /* Set the internal Bluetooth address */ + uint8_t buf[8]; + buf[0] = 0x01; + buf[1] = 0x00; + + for(uint8_t i = 0; i < 6; i++) + buf[i + 2] = bdaddr[5 - i]; // Copy into buffer, has to be written reversed, so it is MSB first + + // bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF5), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data + pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL); +} + +void PS3USB::getBdaddr(uint8_t *bdaddr) { + uint8_t buf[8]; + + // bmRequest = Device to host (0x80) | Class (0x20) | Interface (0x01) = 0xA1, bRequest = Get Report (0x01), Report ID (0xF5), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data + pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL); + + for(uint8_t i = 0; i < 6; i++) + bdaddr[5 - i] = buf[i + 2]; // Copy into buffer reversed, so it is LSB first +} + +void PS3USB::enable_sixaxis() { // Command used to enable the Dualshock 3 and Navigation controller to send data via USB + uint8_t cmd_buf[4]; + cmd_buf[0] = 0x42; // Special PS3 Controller enable commands + cmd_buf[1] = 0x0c; + cmd_buf[2] = 0x00; + cmd_buf[3] = 0x00; + + // bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF4), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data) + pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF4, 0x03, 0x00, 4, 4, cmd_buf, NULL); +} + +/* Playstation Move Controller commands */ +void PS3USB::Move_Command(uint8_t *data, uint16_t nbytes) { + pUsb->outTransfer(bAddress, epInfo[ PS3_OUTPUT_PIPE ].epAddr, nbytes, data); +} + +void PS3USB::moveSetBulb(uint8_t r, uint8_t g, uint8_t b) { // Use this to set the Color using RGB values + // Set the Bulb's values into the write buffer + writeBuf[2] = r; + writeBuf[3] = g; + writeBuf[4] = b; + + Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE); +} + +void PS3USB::moveSetBulb(ColorsEnum color) { // Use this to set the Color using the predefined colors in "enums.h" + moveSetBulb((uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color)); +} + +void PS3USB::moveSetRumble(uint8_t rumble) { +#ifdef DEBUG_USB_HOST + if(rumble < 64 && rumble != 0) // The rumble value has to at least 64, or approximately 25% (64/255*100) + Notify(PSTR("\r\nThe rumble value has to at least 64, or approximately 25%"), 0x80); +#endif + writeBuf[6] = rumble; // Set the rumble value into the write buffer + + Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE); +} + +void PS3USB::setMoveBdaddr(uint8_t *bdaddr) { + /* Set the internal Bluetooth address */ + uint8_t buf[11]; + buf[0] = 0x05; + buf[7] = 0x10; + buf[8] = 0x01; + buf[9] = 0x02; + buf[10] = 0x12; + + for(uint8_t i = 0; i < 6; i++) + buf[i + 1] = bdaddr[i]; + + // bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x05), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data + pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x05, 0x03, 0x00, 11, 11, buf, NULL); +} + +void PS3USB::getMoveBdaddr(uint8_t *bdaddr) { + uint8_t buf[16]; + + // bmRequest = Device to host (0x80) | Class (0x20) | Interface (0x01) = 0xA1, bRequest = Get Report (0x01), Report ID (0x04), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data + pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, 0x04, 0x03, 0x00, 16, 16, buf, NULL); + + for(uint8_t i = 0; i < 6; i++) + bdaddr[i] = buf[10 + i]; +} + +void PS3USB::getMoveCalibration(uint8_t *data) { + uint8_t buf[49]; + + for(uint8_t i = 0; i < 3; i++) { + // bmRequest = Device to host (0x80) | Class (0x20) | Interface (0x01) = 0xA1, bRequest = Get Report (0x01), Report ID (0x10), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data + pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, 0x10, 0x03, 0x00, 49, 49, buf, NULL); + + for(byte j = 0; j < 49; j++) + data[49 * i + j] = buf[j]; + } +} + +void PS3USB::onInit() { + if(pFuncOnInit) + pFuncOnInit(); // Call the user function + else { + if(PS3MoveConnected) + moveSetBulb(Red); + else // Dualshock 3 or Navigation controller + setLedOn(LED1); + } +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/PS3USB.h b/lib/usbhost/USB_Host_Shield_2.0/PS3USB.h new file mode 100644 index 0000000000..2eba9258cf --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/PS3USB.h @@ -0,0 +1,303 @@ +/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. + + This software may be distributed and modified under the terms of the GNU + General Public License version 2 (GPL2) as published by the Free Software + Foundation and appearing in the file GPL2.TXT included in the packaging of + this file. Please note that GPL2 Section 2[b] requires that all works based + on this software must also be made publicly available under the terms of + the GPL2 ("Copyleft"). + + Contact information + ------------------- + + Kristian Lauszus, TKJ Electronics + Web : http://www.tkjelectronics.com + e-mail : kristianl@tkjelectronics.com + */ + +#ifndef _ps3usb_h_ +#define _ps3usb_h_ + +#include "Usb.h" +#include "hid.h" +#include "PS3Enums.h" + +/* PS3 data taken from descriptors */ +#define EP_MAXPKTSIZE 64 // max size for data via USB + +/* Names we give to the 3 ps3 pipes - this is only used for setting the bluetooth address into the ps3 controllers */ +#define PS3_CONTROL_PIPE 0 +#define PS3_OUTPUT_PIPE 1 +#define PS3_INPUT_PIPE 2 + +//PID and VID of the different devices +#define PS3_VID 0x054C // Sony Corporation +#define PS3_PID 0x0268 // PS3 Controller DualShock 3 +#define PS3NAVIGATION_PID 0x042F // Navigation controller +#define PS3MOVE_PID 0x03D5 // Motion controller + +#define PS3_MAX_ENDPOINTS 3 + +/** + * This class implements support for all the official PS3 Controllers: + * Dualshock 3, Navigation or a Motion controller via USB. + * + * One can only set the color of the bulb, set the rumble, set and get the bluetooth address and calibrate the magnetometer via USB on the Move controller. + * + * Information about the protocol can be found at the wiki: https://github.com/felis/USB_Host_Shield_2.0/wiki/PS3-Information. + */ +class PS3USB : public USBDeviceConfig { +public: + /** + * Constructor for the PS3USB class. + * @param pUsb Pointer to USB class instance. + * @param btadr5,btadr4,btadr3,btadr2,btadr1,btadr0 + * Pass your dongles Bluetooth address into the constructor, + * so you are able to pair the controller with a Bluetooth dongle. + */ + PS3USB(USB *pUsb, uint8_t btadr5 = 0, uint8_t btadr4 = 0, uint8_t btadr3 = 0, uint8_t btadr2 = 0, uint8_t btadr1 = 0, uint8_t btadr0 = 0); + + /** @name USBDeviceConfig implementation */ + /** + * Initialize the PS3 Controller. + * @param parent Hub number. + * @param port Port number on the hub. + * @param lowspeed Speed of the device. + * @return 0 on success. + */ + uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + /** + * Release the USB device. + * @return 0 on success. + */ + uint8_t Release(); + /** + * Poll the USB Input endpoins and run the state machines. + * @return 0 on success. + */ + uint8_t Poll(); + + /** + * Get the device address. + * @return The device address. + */ + virtual uint8_t GetAddress() { + return bAddress; + }; + + /** + * Used to check if the controller has been initialized. + * @return True if it's ready. + */ + virtual bool isReady() { + return bPollEnable; + }; + + /** + * Used by the USB core to check what this driver support. + * @param vid The device's VID. + * @param pid The device's PID. + * @return Returns true if the device's VID and PID matches this driver. + */ + virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) { + return (vid == PS3_VID && (pid == PS3_PID || pid == PS3NAVIGATION_PID || pid == PS3MOVE_PID)); + }; + /**@}*/ + + /** + * Used to set the Bluetooth address inside the Dualshock 3 and Navigation controller. + * Set using LSB first. + * @param bdaddr Your dongles Bluetooth address. + */ + void setBdaddr(uint8_t *bdaddr); + /** + * Used to get the Bluetooth address inside the Dualshock 3 and Navigation controller. + * Will return LSB first. + * @param bdaddr Your dongles Bluetooth address. + */ + void getBdaddr(uint8_t *bdaddr); + + /** + * Used to set the Bluetooth address inside the Move controller. + * Set using LSB first. + * @param bdaddr Your dongles Bluetooth address. + */ + void setMoveBdaddr(uint8_t *bdaddr); + /** + * Used to get the Bluetooth address inside the Move controller. + * Will return LSB first. + * @param bdaddr Your dongles Bluetooth address. + */ + void getMoveBdaddr(uint8_t *bdaddr); + /** + * Used to get the calibration data inside the Move controller. + * @param data Buffer to store data in. Must be at least 147 bytes + */ + void getMoveCalibration(uint8_t *data); + + /** @name PS3 Controller functions */ + /** + * getButtonPress(ButtonEnum b) will return true as long as the button is held down. + * + * While getButtonClick(ButtonEnum b) will only return it once. + * + * So you instance if you need to increase a variable once you would use getButtonClick(ButtonEnum b), + * but if you need to drive a robot forward you would use getButtonPress(ButtonEnum b). + * @param b ::ButtonEnum to read. + * @return getButtonPress(ButtonEnum b) will return a true as long as a button is held down, while getButtonClick(ButtonEnum b) will return true once for each button press. + */ + bool getButtonPress(ButtonEnum b); + bool getButtonClick(ButtonEnum b); + /**@}*/ + /** @name PS3 Controller functions */ + /** + * Used to get the analog value from button presses. + * @param a The ::ButtonEnum to read. + * The supported buttons are: + * ::UP, ::RIGHT, ::DOWN, ::LEFT, ::L1, ::L2, ::R1, ::R2, + * ::TRIANGLE, ::CIRCLE, ::CROSS, ::SQUARE, and ::T. + * @return Analog value in the range of 0-255. + */ + uint8_t getAnalogButton(ButtonEnum a); + /** + * Used to read the analog joystick. + * @param a ::LeftHatX, ::LeftHatY, ::RightHatX, and ::RightHatY. + * @return Return the analog value in the range of 0-255. + */ + uint8_t getAnalogHat(AnalogHatEnum a); + /** + * Used to read the sensors inside the Dualshock 3 controller. + * @param a + * The Dualshock 3 has a 3-axis accelerometer and a 1-axis gyro inside. + * @return Return the raw sensor value. + */ + uint16_t getSensor(SensorEnum a); + /** + * Use this to get ::Pitch and ::Roll calculated using the accelerometer. + * @param a Either ::Pitch or ::Roll. + * @return Return the angle in the range of 0-360. + */ + double getAngle(AngleEnum a); + /** + * Get the ::StatusEnum from the controller. + * @param c The ::StatusEnum you want to read. + * @return True if correct and false if not. + */ + bool getStatus(StatusEnum c); + /** Read all the available statuses from the controller and prints it as a nice formated string. */ + void printStatusString(); + + /** Used to set all LEDs and rumble off. */ + void setAllOff(); + /** Turn off rumble. */ + void setRumbleOff(); + /** + * Turn on rumble. + * @param mode Either ::RumbleHigh or ::RumbleLow. + */ + void setRumbleOn(RumbleEnum mode); + /** + * Turn on rumble using custom duration and power. + * @param rightDuration The duration of the right/low rumble effect. + * @param rightPower The intensity of the right/low rumble effect. + * @param leftDuration The duration of the left/high rumble effect. + * @param leftPower The intensity of the left/high rumble effect. + */ + void setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower); + + /** + * Set LED value without using the ::LEDEnum. + * @param value See: ::LEDEnum. + */ + void setLedRaw(uint8_t value); + + /** Turn all LEDs off. */ + void setLedOff() { + setLedRaw(0); + } + /** + * Turn the specific ::LEDEnum off. + * @param a The ::LEDEnum to turn off. + */ + void setLedOff(LEDEnum a); + /** + * Turn the specific ::LEDEnum on. + * @param a The ::LEDEnum to turn on. + */ + void setLedOn(LEDEnum a); + /** + * Toggle the specific ::LEDEnum. + * @param a The ::LEDEnum to toggle. + */ + void setLedToggle(LEDEnum a); + + /** + * Use this to set the Color using RGB values. + * @param r,g,b RGB value. + */ + void moveSetBulb(uint8_t r, uint8_t g, uint8_t b); + /** + * Use this to set the color using the predefined colors in ::ColorsEnum. + * @param color The desired color. + */ + void moveSetBulb(ColorsEnum color); + /** + * Set the rumble value inside the Move controller. + * @param rumble The desired value in the range from 64-255. + */ + void moveSetRumble(uint8_t rumble); + + /** + * Used to call your own function when the controller is successfully initialized. + * @param funcOnInit Function to call. + */ + void attachOnInit(void (*funcOnInit)(void)) { + pFuncOnInit = funcOnInit; + }; + /**@}*/ + + /** Variable used to indicate if the normal playstation controller is successfully connected. */ + bool PS3Connected; + /** Variable used to indicate if the move controller is successfully connected. */ + bool PS3MoveConnected; + /** Variable used to indicate if the navigation controller is successfully connected. */ + bool PS3NavigationConnected; + +protected: + /** Pointer to USB class instance. */ + USB *pUsb; + /** Device address. */ + uint8_t bAddress; + /** Endpoint info structure. */ + EpInfo epInfo[PS3_MAX_ENDPOINTS]; + +private: + /** + * Called when the controller is successfully initialized. + * Use attachOnInit(void (*funcOnInit)(void)) to call your own function. + * This is useful for instance if you want to set the LEDs in a specific way. + */ + void onInit(); + void (*pFuncOnInit)(void); // Pointer to function called in onInit() + + bool bPollEnable; + + uint32_t timer; // used to continuously set PS3 Move controller Bulb and rumble values + + uint32_t ButtonState; + uint32_t OldButtonState; + uint32_t ButtonClickState; + + uint8_t my_bdaddr[6]; // Change to your dongles Bluetooth address in the constructor + uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data + uint8_t writeBuf[EP_MAXPKTSIZE]; // General purpose buffer for output data + + void readReport(); // read incoming data + void printReport(); // print incoming date - Uncomment for debugging + + /* Private commands */ + void PS3_Command(uint8_t *data, uint16_t nbytes); + void enable_sixaxis(); // Command used to enable the Dualshock 3 and Navigation controller to send data via USB + void Move_Command(uint8_t *data, uint16_t nbytes); +}; +#endif diff --git a/lib/usbhost/USB_Host_Shield_2.0/PS4BT.h b/lib/usbhost/USB_Host_Shield_2.0/PS4BT.h new file mode 100644 index 0000000000..b7eb4b5a91 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/PS4BT.h @@ -0,0 +1,121 @@ +/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved. + + This software may be distributed and modified under the terms of the GNU + General Public License version 2 (GPL2) as published by the Free Software + Foundation and appearing in the file GPL2.TXT included in the packaging of + this file. Please note that GPL2 Section 2[b] requires that all works based + on this software must also be made publicly available under the terms of + the GPL2 ("Copyleft"). + + Contact information + ------------------- + + Kristian Lauszus, TKJ Electronics + Web : http://www.tkjelectronics.com + e-mail : kristianl@tkjelectronics.com + */ + +#ifndef _ps4bt_h_ +#define _ps4bt_h_ + +#include "BTHID.h" +#include "PS4Parser.h" + +/** + * This class implements support for the PS4 controller via Bluetooth. + * It uses the BTHID class for all the Bluetooth communication. + */ +class PS4BT : public BTHID, public PS4Parser { +public: + /** + * Constructor for the PS4BT class. + * @param p Pointer to the BTD class instance. + * @param pair Set this to true in order to pair with the device. If the argument is omitted then it will not pair with it. One can use ::PAIR to set it to true. + * @param pin Write the pin to BTD#btdPin. If argument is omitted, then "0000" will be used. + */ + PS4BT(BTD *p, bool pair = false, const char *pin = "0000") : + BTHID(p, pair, pin) { + PS4Parser::Reset(); + }; + + /** + * Used to check if a PS4 controller is connected. + * @return Returns true if it is connected. + */ + bool connected() { + return BTHID::connected; + }; + +protected: + /** @name BTHID implementation */ + /** + * Used to parse Bluetooth HID data. + * @param len The length of the incoming data. + * @param buf Pointer to the data buffer. + */ + virtual void ParseBTHIDData(uint8_t len, uint8_t *buf) { + PS4Parser::Parse(len, buf); + }; + + /** + * Called when a device is successfully initialized. + * Use attachOnInit(void (*funcOnInit)(void)) to call your own function. + * This is useful for instance if you want to set the LEDs in a specific way. + */ + virtual void OnInitBTHID() { + PS4Parser::Reset(); + enable_sixaxis(); // Make the controller send out the entire output report + if (pFuncOnInit) + pFuncOnInit(); // Call the user function + else + setLed(Blue); + }; + + /** Used to reset the different buffers to there default values */ + virtual void ResetBTHID() { + PS4Parser::Reset(); + }; + /**@}*/ + + /** @name PS4Parser implementation */ + virtual void sendOutputReport(PS4Output *output) { // Source: https://github.com/chrippa/ds4drv + uint8_t buf[79]; + memset(buf, 0, sizeof(buf)); + + buf[0] = 0x52; // HID BT Set_report (0x50) | Report Type (Output 0x02) + buf[1] = 0x11; // Report ID + buf[2] = 0x80; + buf[4]= 0xFF; + + buf[7] = output->smallRumble; // Small Rumble + buf[8] = output->bigRumble; // Big rumble + + buf[9] = output->r; // Red + buf[10] = output->g; // Green + buf[11] = output->b; // Blue + + buf[12] = output->flashOn; // Time to flash bright (255 = 2.5 seconds) + buf[13] = output->flashOff; // Time to flash dark (255 = 2.5 seconds) + + output->reportChanged = false; + + // The PS4 console actually set the four last bytes to a CRC32 checksum, but it seems like it is actually not needed + + HID_Command(buf, sizeof(buf)); + }; + /**@}*/ + +private: + void enable_sixaxis() { // Command used to make the PS4 controller send out the entire output report + uint8_t buf[2]; + buf[0] = 0x43; // HID BT Get_report (0x40) | Report Type (Feature 0x03) + buf[1] = 0x02; // Report ID + + HID_Command(buf, 2); + }; + + void HID_Command(uint8_t *data, uint8_t nbytes) { + pBtd->L2CAP_Command(hci_handle, data, nbytes, control_scid[0], control_scid[1]); + }; +}; +#endif diff --git a/lib/usbhost/USB_Host_Shield_2.0/PS4Parser.cpp b/lib/usbhost/USB_Host_Shield_2.0/PS4Parser.cpp new file mode 100644 index 0000000000..ca6adce403 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/PS4Parser.cpp @@ -0,0 +1,116 @@ +/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved. + + This software may be distributed and modified under the terms of the GNU + General Public License version 2 (GPL2) as published by the Free Software + Foundation and appearing in the file GPL2.TXT included in the packaging of + this file. Please note that GPL2 Section 2[b] requires that all works based + on this software must also be made publicly available under the terms of + the GPL2 ("Copyleft"). + + Contact information + ------------------- + + Kristian Lauszus, TKJ Electronics + Web : http://www.tkjelectronics.com + e-mail : kristianl@tkjelectronics.com + */ + +#include "PS4Parser.h" + +// To enable serial debugging see "settings.h" +//#define PRINTREPORT // Uncomment to print the report send by the PS4 Controller + +bool PS4Parser::checkDpad(ButtonEnum b) { + switch (b) { + case UP: + return ps4Data.btn.dpad == DPAD_LEFT_UP || ps4Data.btn.dpad == DPAD_UP || ps4Data.btn.dpad == DPAD_UP_RIGHT; + case RIGHT: + return ps4Data.btn.dpad == DPAD_UP_RIGHT || ps4Data.btn.dpad == DPAD_RIGHT || ps4Data.btn.dpad == DPAD_RIGHT_DOWN; + case DOWN: + return ps4Data.btn.dpad == DPAD_RIGHT_DOWN || ps4Data.btn.dpad == DPAD_DOWN || ps4Data.btn.dpad == DPAD_DOWN_LEFT; + case LEFT: + return ps4Data.btn.dpad == DPAD_DOWN_LEFT || ps4Data.btn.dpad == DPAD_LEFT || ps4Data.btn.dpad == DPAD_LEFT_UP; + default: + return false; + } +} + +bool PS4Parser::getButtonPress(ButtonEnum b) { + if (b <= LEFT) // Dpad + return checkDpad(b); + else + return ps4Data.btn.val & (1UL << pgm_read_byte(&PS4_BUTTONS[(uint8_t)b])); +} + +bool PS4Parser::getButtonClick(ButtonEnum b) { + uint32_t mask = 1UL << pgm_read_byte(&PS4_BUTTONS[(uint8_t)b]); + bool click = buttonClickState.val & mask; + buttonClickState.val &= ~mask; // Clear "click" event + return click; +} + +uint8_t PS4Parser::getAnalogButton(ButtonEnum b) { + if (b == L2) // These are the only analog buttons on the controller + return ps4Data.trigger[0]; + else if (b == R2) + return ps4Data.trigger[1]; + return 0; +} + +uint8_t PS4Parser::getAnalogHat(AnalogHatEnum a) { + return ps4Data.hatValue[(uint8_t)a]; +} + +void PS4Parser::Parse(uint8_t len, uint8_t *buf) { + if (len > 1 && buf) { +#ifdef PRINTREPORT + Notify(PSTR("\r\n"), 0x80); + for (uint8_t i = 0; i < len; i++) { + D_PrintHex (buf[i], 0x80); + Notify(PSTR(" "), 0x80); + } +#endif + + if (buf[0] == 0x01) // Check report ID + memcpy(&ps4Data, buf + 1, min((uint8_t)(len - 1), sizeof(ps4Data))); + else if (buf[0] == 0x11) { // This report is send via Bluetooth, it has an offset of 2 compared to the USB data + if (len < 4) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nReport is too short: "), 0x80); + D_PrintHex (len, 0x80); +#endif + return; + } + memcpy(&ps4Data, buf + 3, min((uint8_t)(len - 3), sizeof(ps4Data))); + } else { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nUnknown report id: "), 0x80); + D_PrintHex (buf[0], 0x80); +#endif + return; + } + + if (ps4Data.btn.val != oldButtonState.val) { // Check if anything has changed + buttonClickState.val = ps4Data.btn.val & ~oldButtonState.val; // Update click state variable + oldButtonState.val = ps4Data.btn.val; + + // The DPAD buttons does not set the different bits, but set a value corresponding to the buttons pressed, we will simply set the bits ourself + uint8_t newDpad = 0; + if (checkDpad(UP)) + newDpad |= 1 << UP; + if (checkDpad(RIGHT)) + newDpad |= 1 << RIGHT; + if (checkDpad(DOWN)) + newDpad |= 1 << DOWN; + if (checkDpad(LEFT)) + newDpad |= 1 << LEFT; + if (newDpad != oldDpad) { + buttonClickState.dpad = newDpad & ~oldDpad; // Override values + oldDpad = newDpad; + } + } + } + + if (ps4Output.reportChanged) + sendOutputReport(&ps4Output); // Send output report +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/PS4Parser.h b/lib/usbhost/USB_Host_Shield_2.0/PS4Parser.h new file mode 100644 index 0000000000..51f0806361 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/PS4Parser.h @@ -0,0 +1,407 @@ +/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved. + + This software may be distributed and modified under the terms of the GNU + General Public License version 2 (GPL2) as published by the Free Software + Foundation and appearing in the file GPL2.TXT included in the packaging of + this file. Please note that GPL2 Section 2[b] requires that all works based + on this software must also be made publicly available under the terms of + the GPL2 ("Copyleft"). + + Contact information + ------------------- + + Kristian Lauszus, TKJ Electronics + Web : http://www.tkjelectronics.com + e-mail : kristianl@tkjelectronics.com + */ + +#ifndef _ps4parser_h_ +#define _ps4parser_h_ + +#include "Usb.h" +#include "controllerEnums.h" + +/** Buttons on the controller */ +const uint8_t PS4_BUTTONS[] PROGMEM = { + UP, // UP + RIGHT, // RIGHT + DOWN, // DOWN + LEFT, // LEFT + + 0x0C, // SHARE + 0x0D, // OPTIONS + 0x0E, // L3 + 0x0F, // R3 + + 0x0A, // L2 + 0x0B, // R2 + 0x08, // L1 + 0x09, // R1 + + 0x07, // TRIANGLE + 0x06, // CIRCLE + 0x05, // CROSS + 0x04, // SQUARE + + 0x10, // PS + 0x11, // TOUCHPAD +}; + +union PS4Buttons { + struct { + uint8_t dpad : 4; + uint8_t square : 1; + uint8_t cross : 1; + uint8_t circle : 1; + uint8_t triangle : 1; + + uint8_t l1 : 1; + uint8_t r1 : 1; + uint8_t l2 : 1; + uint8_t r2 : 1; + uint8_t share : 1; + uint8_t options : 1; + uint8_t l3 : 1; + uint8_t r3 : 1; + + uint8_t ps : 1; + uint8_t touchpad : 1; + uint8_t reportCounter : 6; + } __attribute__((packed)); + uint32_t val : 24; +} __attribute__((packed)); + +struct touchpadXY { + uint8_t dummy; // I can not figure out what this data is for, it seems to change randomly, maybe a timestamp? + struct { + uint8_t counter : 7; // Increments every time a finger is touching the touchpad + uint8_t touching : 1; // The top bit is cleared if the finger is touching the touchpad + uint16_t x : 12; + uint16_t y : 12; + } __attribute__((packed)) finger[2]; // 0 = first finger, 1 = second finger +} __attribute__((packed)); + +struct PS4Status { + uint8_t battery : 4; + uint8_t usb : 1; + uint8_t audio : 1; + uint8_t mic : 1; + uint8_t unknown : 1; // Extension port? +} __attribute__((packed)); + +struct PS4Data { + /* Button and joystick values */ + uint8_t hatValue[4]; + PS4Buttons btn; + uint8_t trigger[2]; + + /* Gyro and accelerometer values */ + uint8_t dummy[3]; // First two looks random, while the third one might be some kind of status - it increments once in a while + int16_t gyroY, gyroZ, gyroX; + int16_t accX, accZ, accY; + + uint8_t dummy2[5]; + PS4Status status; + uint8_t dummy3[3]; + + /* The rest is data for the touchpad */ + touchpadXY xy[3]; // It looks like it sends out three coordinates each time, this might be because the microcontroller inside the PS4 controller is much faster than the Bluetooth connection. + // The last data is read from the last position in the array while the oldest measurement is from the first position. + // The first position will also keep it's value after the finger is released, while the other two will set them to zero. + // Note that if you read fast enough from the device, then only the first one will contain any data. + + // The last three bytes are always: 0x00, 0x80, 0x00 +} __attribute__((packed)); + +struct PS4Output { + uint8_t bigRumble, smallRumble; // Rumble + uint8_t r, g, b; // RGB + uint8_t flashOn, flashOff; // Time to flash bright/dark (255 = 2.5 seconds) + bool reportChanged; // The data is send when data is received from the controller +} __attribute__((packed)); + +enum DPADEnum { + DPAD_UP = 0x0, + DPAD_UP_RIGHT = 0x1, + DPAD_RIGHT = 0x2, + DPAD_RIGHT_DOWN = 0x3, + DPAD_DOWN = 0x4, + DPAD_DOWN_LEFT = 0x5, + DPAD_LEFT = 0x6, + DPAD_LEFT_UP = 0x7, + DPAD_OFF = 0x8, +}; + +/** This class parses all the data sent by the PS4 controller */ +class PS4Parser { +public: + /** Constructor for the PS4Parser class. */ + PS4Parser() { + Reset(); + }; + + /** @name PS4 Controller functions */ + /** + * getButtonPress(ButtonEnum b) will return true as long as the button is held down. + * + * While getButtonClick(ButtonEnum b) will only return it once. + * + * So you instance if you need to increase a variable once you would use getButtonClick(ButtonEnum b), + * but if you need to drive a robot forward you would use getButtonPress(ButtonEnum b). + * @param b ::ButtonEnum to read. + * @return getButtonPress(ButtonEnum b) will return a true as long as a button is held down, while getButtonClick(ButtonEnum b) will return true once for each button press. + */ + bool getButtonPress(ButtonEnum b); + bool getButtonClick(ButtonEnum b); + /**@}*/ + /** @name PS4 Controller functions */ + /** + * Used to get the analog value from button presses. + * @param b The ::ButtonEnum to read. + * The supported buttons are: + * ::UP, ::RIGHT, ::DOWN, ::LEFT, ::L1, ::L2, ::R1, ::R2, + * ::TRIANGLE, ::CIRCLE, ::CROSS, ::SQUARE, and ::T. + * @return Analog value in the range of 0-255. + */ + uint8_t getAnalogButton(ButtonEnum b); + + /** + * Used to read the analog joystick. + * @param a ::LeftHatX, ::LeftHatY, ::RightHatX, and ::RightHatY. + * @return Return the analog value in the range of 0-255. + */ + uint8_t getAnalogHat(AnalogHatEnum a); + + /** + * Get the x-coordinate of the touchpad. Position 0 is in the top left. + * @param finger 0 = first finger, 1 = second finger. If omitted, then 0 will be used. + * @param xyId The controller sends out three packets with the same structure. + * The third one will contain the last measure, but if you read from the controller then there is only be data in the first one. + * For that reason it will be set to 0 if the argument is omitted. + * @return Returns the x-coordinate of the finger. + */ + uint16_t getX(uint8_t finger = 0, uint8_t xyId = 0) { + return ps4Data.xy[xyId].finger[finger].x; + }; + + /** + * Get the y-coordinate of the touchpad. Position 0 is in the top left. + * @param finger 0 = first finger, 1 = second finger. If omitted, then 0 will be used. + * @param xyId The controller sends out three packets with the same structure. + * The third one will contain the last measure, but if you read from the controller then there is only be data in the first one. + * For that reason it will be set to 0 if the argument is omitted. + * @return Returns the y-coordinate of the finger. + */ + uint16_t getY(uint8_t finger = 0, uint8_t xyId = 0) { + return ps4Data.xy[xyId].finger[finger].y; + }; + + /** + * Returns whenever the user is toucing the touchpad. + * @param finger 0 = first finger, 1 = second finger. If omitted, then 0 will be used. + * @param xyId The controller sends out three packets with the same structure. + * The third one will contain the last measure, but if you read from the controller then there is only be data in the first one. + * For that reason it will be set to 0 if the argument is omitted. + * @return Returns true if the specific finger is touching the touchpad. + */ + bool isTouching(uint8_t finger = 0, uint8_t xyId = 0) { + return !(ps4Data.xy[xyId].finger[finger].touching); // The bit is cleared when a finger is touching the touchpad + }; + + /** + * This counter increments every time a finger touches the touchpad. + * @param finger 0 = first finger, 1 = second finger. If omitted, then 0 will be used. + * @param xyId The controller sends out three packets with the same structure. + * The third one will contain the last measure, but if you read from the controller then there is only be data in the first one. + * For that reason it will be set to 0 if the argument is omitted. + * @return Return the value of the counter, note that it is only a 7-bit value. + */ + uint8_t getTouchCounter(uint8_t finger = 0, uint8_t xyId = 0) { + return ps4Data.xy[xyId].finger[finger].counter; + }; + + /** + * Get the angle of the controller calculated using the accelerometer. + * @param a Either ::Pitch or ::Roll. + * @return Return the angle in the range of 0-360. + */ + double getAngle(AngleEnum a) { + if (a == Pitch) + return (atan2(ps4Data.accY, ps4Data.accZ) + PI) * RAD_TO_DEG; + else + return (atan2(ps4Data.accX, ps4Data.accZ) + PI) * RAD_TO_DEG; + }; + + /** + * Used to get the raw values from the 3-axis gyroscope and 3-axis accelerometer inside the PS4 controller. + * @param s The sensor to read. + * @return Returns the raw sensor reading. + */ + int16_t getSensor(SensorEnum s) { + switch(s) { + case gX: + return ps4Data.gyroX; + case gY: + return ps4Data.gyroY; + case gZ: + return ps4Data.gyroZ; + case aX: + return ps4Data.accX; + case aY: + return ps4Data.accY; + case aZ: + return ps4Data.accZ; + default: + return 0; + } + }; + + /** + * Return the battery level of the PS4 controller. + * @return The battery level in the range 0-15. + */ + uint8_t getBatteryLevel() { + return ps4Data.status.battery; + }; + + /** + * Use this to check if an USB cable is connected to the PS4 controller. + * @return Returns true if an USB cable is connected. + */ + bool getUsbStatus() { + return ps4Data.status.usb; + }; + + /** + * Use this to check if an audio jack cable is connected to the PS4 controller. + * @return Returns true if an audio jack cable is connected. + */ + bool getAudioStatus() { + return ps4Data.status.audio; + }; + + /** + * Use this to check if a microphone is connected to the PS4 controller. + * @return Returns true if a microphone is connected. + */ + bool getMicStatus() { + return ps4Data.status.mic; + }; + + /** Turn both rumble and the LEDs off. */ + void setAllOff() { + setRumbleOff(); + setLedOff(); + }; + + /** Set rumble off. */ + void setRumbleOff() { + setRumbleOn(0, 0); + }; + + /** + * Turn on rumble. + * @param mode Either ::RumbleHigh or ::RumbleLow. + */ + void setRumbleOn(RumbleEnum mode) { + if (mode == RumbleLow) + setRumbleOn(0x00, 0xFF); + else + setRumbleOn(0xFF, 0x00); + }; + + /** + * Turn on rumble. + * @param bigRumble Value for big motor. + * @param smallRumble Value for small motor. + */ + void setRumbleOn(uint8_t bigRumble, uint8_t smallRumble) { + ps4Output.bigRumble = bigRumble; + ps4Output.smallRumble = smallRumble; + ps4Output.reportChanged = true; + }; + + /** Turn all LEDs off. */ + void setLedOff() { + setLed(0, 0, 0); + }; + + /** + * Use this to set the color using RGB values. + * @param r,g,b RGB value. + */ + void setLed(uint8_t r, uint8_t g, uint8_t b) { + ps4Output.r = r; + ps4Output.g = g; + ps4Output.b = b; + ps4Output.reportChanged = true; + }; + + /** + * Use this to set the color using the predefined colors in ::ColorsEnum. + * @param color The desired color. + */ + void setLed(ColorsEnum color) { + setLed((uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color)); + }; + + /** + * Set the LEDs flash time. + * @param flashOn Time to flash bright (255 = 2.5 seconds). + * @param flashOff Time to flash dark (255 = 2.5 seconds). + */ + void setLedFlash(uint8_t flashOn, uint8_t flashOff) { + ps4Output.flashOn = flashOn; + ps4Output.flashOff = flashOff; + ps4Output.reportChanged = true; + }; + /**@}*/ + +protected: + /** + * Used to parse data sent from the PS4 controller. + * @param len Length of the data. + * @param buf Pointer to the data buffer. + */ + void Parse(uint8_t len, uint8_t *buf); + + /** Used to reset the different buffers to their default values */ + void Reset() { + uint8_t i; + for (i = 0; i < sizeof(ps4Data.hatValue); i++) + ps4Data.hatValue[i] = 127; // Center value + ps4Data.btn.val = 0; + oldButtonState.val = 0; + for (i = 0; i < sizeof(ps4Data.trigger); i++) + ps4Data.trigger[i] = 0; + for (i = 0; i < sizeof(ps4Data.xy)/sizeof(ps4Data.xy[0]); i++) { + for (uint8_t j = 0; j < sizeof(ps4Data.xy[0].finger)/sizeof(ps4Data.xy[0].finger[0]); j++) + ps4Data.xy[i].finger[j].touching = 1; // The bit is cleared if the finger is touching the touchpad + } + + ps4Data.btn.dpad = DPAD_OFF; + oldButtonState.dpad = DPAD_OFF; + buttonClickState.dpad = 0; + oldDpad = 0; + + ps4Output.bigRumble = ps4Output.smallRumble = 0; + ps4Output.r = ps4Output.g = ps4Output.b = 0; + ps4Output.flashOn = ps4Output.flashOff = 0; + ps4Output.reportChanged = false; + }; + + /** + * Send the output to the PS4 controller. This is implemented in PS4BT.h and PS4USB.h. + * @param output Pointer to PS4Output buffer; + */ + virtual void sendOutputReport(PS4Output *output) = 0; + +private: + bool checkDpad(ButtonEnum b); // Used to check PS4 DPAD buttons + + PS4Data ps4Data; + PS4Buttons oldButtonState, buttonClickState; + PS4Output ps4Output; + uint8_t oldDpad; +}; +#endif diff --git a/lib/usbhost/USB_Host_Shield_2.0/PS4USB.h b/lib/usbhost/USB_Host_Shield_2.0/PS4USB.h new file mode 100644 index 0000000000..b43079a6e9 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/PS4USB.h @@ -0,0 +1,130 @@ +/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved. + + This software may be distributed and modified under the terms of the GNU + General Public License version 2 (GPL2) as published by the Free Software + Foundation and appearing in the file GPL2.TXT included in the packaging of + this file. Please note that GPL2 Section 2[b] requires that all works based + on this software must also be made publicly available under the terms of + the GPL2 ("Copyleft"). + + Contact information + ------------------- + + Kristian Lauszus, TKJ Electronics + Web : http://www.tkjelectronics.com + e-mail : kristianl@tkjelectronics.com + */ + +#ifndef _ps4usb_h_ +#define _ps4usb_h_ + +#include "hiduniversal.h" +#include "PS4Parser.h" + +#define PS4_VID 0x054C // Sony Corporation +#define PS4_PID 0x05C4 // PS4 Controller + +/** + * This class implements support for the PS4 controller via USB. + * It uses the HIDUniversal class for all the USB communication. + */ +class PS4USB : public HIDUniversal, public PS4Parser { +public: + /** + * Constructor for the PS4USB class. + * @param p Pointer to the USB class instance. + */ + PS4USB(USB *p) : + HIDUniversal(p) { + PS4Parser::Reset(); + }; + + /** + * Used to check if a PS4 controller is connected. + * @return Returns true if it is connected. + */ + bool connected() { + return HIDUniversal::isReady() && HIDUniversal::VID == PS4_VID && HIDUniversal::PID == PS4_PID; + }; + + /** + * Used to call your own function when the device is successfully initialized. + * @param funcOnInit Function to call. + */ + void attachOnInit(void (*funcOnInit)(void)) { + pFuncOnInit = funcOnInit; + }; + +protected: + /** @name HIDUniversal implementation */ + /** + * Used to parse USB HID data. + * @param hid Pointer to the HID class. + * @param is_rpt_id Only used for Hubs. + * @param len The length of the incoming data. + * @param buf Pointer to the data buffer. + */ + virtual void ParseHIDData(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) { + if (HIDUniversal::VID == PS4_VID && HIDUniversal::PID == PS4_PID) + PS4Parser::Parse(len, buf); + }; + + /** + * Called when a device is successfully initialized. + * Use attachOnInit(void (*funcOnInit)(void)) to call your own function. + * This is useful for instance if you want to set the LEDs in a specific way. + */ + virtual uint8_t OnInitSuccessful() { + if (HIDUniversal::VID == PS4_VID && HIDUniversal::PID == PS4_PID) { + PS4Parser::Reset(); + if (pFuncOnInit) + pFuncOnInit(); // Call the user function + else + setLed(Blue); + }; + return 0; + }; + /**@}*/ + + /** @name PS4Parser implementation */ + virtual void sendOutputReport(PS4Output *output) { // Source: https://github.com/chrippa/ds4drv + uint8_t buf[32]; + memset(buf, 0, sizeof(buf)); + + buf[0] = 0x05; // Report ID + buf[1]= 0xFF; + + buf[4] = output->smallRumble; // Small Rumble + buf[5] = output->bigRumble; // Big rumble + + buf[6] = output->r; // Red + buf[7] = output->g; // Green + buf[8] = output->b; // Blue + + buf[9] = output->flashOn; // Time to flash bright (255 = 2.5 seconds) + buf[10] = output->flashOff; // Time to flash dark (255 = 2.5 seconds) + + output->reportChanged = false; + + // The PS4 console actually set the four last bytes to a CRC32 checksum, but it seems like it is actually not needed + + pUsb->outTransfer(bAddress, epInfo[ hidInterfaces[0].epIndex[epInterruptOutIndex] ].epAddr, sizeof(buf), buf); + }; + /**@}*/ + + /** @name USBDeviceConfig implementation */ + /** + * Used by the USB core to check what this driver support. + * @param vid The device's VID. + * @param pid The device's PID. + * @return Returns true if the device's VID and PID matches this driver. + */ + virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) { + return (vid == PS4_VID && pid == PS4_PID); + }; + /**@}*/ + +private: + void (*pFuncOnInit)(void); // Pointer to function called in onInit() +}; +#endif diff --git a/lib/usbhost/USB_Host_Shield_2.0/PSBuzz.cpp b/lib/usbhost/USB_Host_Shield_2.0/PSBuzz.cpp new file mode 100644 index 0000000000..498164d5a6 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/PSBuzz.cpp @@ -0,0 +1,82 @@ +/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved. + + This software may be distributed and modified under the terms of the GNU + General Public License version 2 (GPL2) as published by the Free Software + Foundation and appearing in the file GPL2.TXT included in the packaging of + this file. Please note that GPL2 Section 2[b] requires that all works based + on this software must also be made publicly available under the terms of + the GPL2 ("Copyleft"). + + Contact information + ------------------- + + Kristian Lauszus, TKJ Electronics + Web : http://www.tkjelectronics.com + e-mail : kristianl@tkjelectronics.com + */ + +#include "PSBuzz.h" + +// To enable serial debugging see "settings.h" +//#define PRINTREPORT // Uncomment to print the report send by the PS Buzz Controllers + +void PSBuzz::ParseHIDData(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) { + if (HIDUniversal::VID == PSBUZZ_VID && HIDUniversal::PID == PSBUZZ_PID && len > 2 && buf) { +#ifdef PRINTREPORT + Notify(PSTR("\r\n"), 0x80); + for (uint8_t i = 0; i < len; i++) { + D_PrintHex (buf[i], 0x80); + Notify(PSTR(" "), 0x80); + } +#endif + memcpy(&psbuzzButtons, buf + 2, min((uint8_t)(len - 2), sizeof(psbuzzButtons))); + + if (psbuzzButtons.val != oldButtonState.val) { // Check if anything has changed + buttonClickState.val = psbuzzButtons.val & ~oldButtonState.val; // Update click state variable + oldButtonState.val = psbuzzButtons.val; + } + } +}; + +uint8_t PSBuzz::OnInitSuccessful() { + if (HIDUniversal::VID == PSBUZZ_VID && HIDUniversal::PID == PSBUZZ_PID) { + Reset(); + if (pFuncOnInit) + pFuncOnInit(); // Call the user function + else + setLedOnAll(); // Turn the LED on, on all four controllers + }; + return 0; +}; + +bool PSBuzz::getButtonPress(ButtonEnum b, uint8_t controller) { + return psbuzzButtons.val & (1UL << (b + 5 * controller)); // Each controller uses 5 bits, so the value is shifted 5 for each controller +}; + +bool PSBuzz::getButtonClick(ButtonEnum b, uint8_t controller) { + uint32_t mask = (1UL << (b + 5 * controller)); // Each controller uses 5 bits, so the value is shifted 5 for each controller + bool click = buttonClickState.val & mask; + buttonClickState.val &= ~mask; // Clear "click" event + return click; +}; + +// Source: http://www.developerfusion.com/article/84338/making-usb-c-friendly/ and https://github.com/torvalds/linux/blob/master/drivers/hid/hid-sony.c +void PSBuzz::setLedRaw(bool value, uint8_t controller) { + ledState[controller] = value; // Save value for next time it is called + + uint8_t buf[7]; + buf[0] = 0x00; + buf[1] = ledState[0] ? 0xFF : 0x00; + buf[2] = ledState[1] ? 0xFF : 0x00; + buf[3] = ledState[2] ? 0xFF : 0x00; + buf[4] = ledState[3] ? 0xFF : 0x00; + buf[5] = 0x00; + buf[6] = 0x00; + + PSBuzz_Command(buf, sizeof(buf)); +}; + +void PSBuzz::PSBuzz_Command(uint8_t *data, uint16_t nbytes) { + // bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x00), Report Type (Output 0x02), interface (0x00), datalength, datalength, data) + pUsb->ctrlReq(bAddress, epInfo[0].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x00, 0x02, 0x00, nbytes, nbytes, data, NULL); +}; diff --git a/lib/usbhost/USB_Host_Shield_2.0/PSBuzz.h b/lib/usbhost/USB_Host_Shield_2.0/PSBuzz.h new file mode 100644 index 0000000000..8880d9e50a --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/PSBuzz.h @@ -0,0 +1,185 @@ +/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved. + + This software may be distributed and modified under the terms of the GNU + General Public License version 2 (GPL2) as published by the Free Software + Foundation and appearing in the file GPL2.TXT included in the packaging of + this file. Please note that GPL2 Section 2[b] requires that all works based + on this software must also be made publicly available under the terms of + the GPL2 ("Copyleft"). + + Contact information + ------------------- + + Kristian Lauszus, TKJ Electronics + Web : http://www.tkjelectronics.com + e-mail : kristianl@tkjelectronics.com + */ + +#ifndef _psbuzz_h_ +#define _psbuzz_h_ + +#include "hiduniversal.h" +#include "controllerEnums.h" + +#define PSBUZZ_VID 0x054C // Sony Corporation +#define PSBUZZ_PID 0x1000 // PS Buzz Controller + +/** Struct used to easily read the different buttons on the controllers */ +union PSBUZZButtons { + struct { + uint8_t red : 1; + uint8_t yellow : 1; + uint8_t green : 1; + uint8_t orange : 1; + uint8_t blue : 1; + } __attribute__((packed)) btn[4]; + uint32_t val : 20; +} __attribute__((packed)); + +/** + * This class implements support for the PS Buzz controllers via USB. + * It uses the HIDUniversal class for all the USB communication. + */ +class PSBuzz : public HIDUniversal { +public: + /** + * Constructor for the PSBuzz class. + * @param p Pointer to the USB class instance. + */ + PSBuzz(USB *p) : + HIDUniversal(p) { + Reset(); + }; + + /** + * Used to check if a PS Buzz controller is connected. + * @return Returns true if it is connected. + */ + bool connected() { + return HIDUniversal::isReady() && HIDUniversal::VID == PSBUZZ_VID && HIDUniversal::PID == PSBUZZ_PID; + }; + + /** + * Used to call your own function when the device is successfully initialized. + * @param funcOnInit Function to call. + */ + void attachOnInit(void (*funcOnInit)(void)) { + pFuncOnInit = funcOnInit; + }; + + /** @name PS Buzzer Controller functions */ + /** + * getButtonPress(ButtonEnum b) will return true as long as the button is held down. + * + * While getButtonClick(ButtonEnum b) will only return it once. + * + * So you instance if you need to increase a variable once you would use getButtonClick(ButtonEnum b), + * but if you need to drive a robot forward you would use getButtonPress(ButtonEnum b). + * @param b ::ButtonEnum to read. + * @param controller The controller to read from. Default to 0. + * @return getButtonPress(ButtonEnum b) will return a true as long as a button is held down, while getButtonClick(ButtonEnum b) will return true once for each button press. + */ + bool getButtonPress(ButtonEnum b, uint8_t controller = 0); + bool getButtonClick(ButtonEnum b, uint8_t controller = 0); + /**@}*/ + /** @name PS Buzzer Controller functions */ + /** + * Set LED value without using ::LEDEnum. + * @param value See: ::LEDEnum. + */ + /** + * Set LED values directly. + * @param value Used to set whenever the LED should be on or off + * @param controller The controller to control. Defaults to 0. + */ + void setLedRaw(bool value, uint8_t controller = 0); + + /** Turn all LEDs off. */ + void setLedOffAll() { + for (uint8_t i = 1; i < 4; i++) // Skip first as it will be set in setLedRaw + ledState[i] = false; // Just an easy way to set all four off at the same time + setLedRaw(false); // Turn the LED off, on all four controllers + }; + + /** + * Turn the LED off on a specific controller. + * @param controller The controller to turn off. Defaults to 0. + */ + void setLedOff(uint8_t controller = 0) { + setLedRaw(false, controller); + }; + + + /** Turn all LEDs on. */ + void setLedOnAll() { + for (uint8_t i = 1; i < 4; i++) // Skip first as it will be set in setLedRaw + ledState[i] = true; // Just an easy way to set all four off at the same time + setLedRaw(true); // Turn the LED on, on all four controllers + }; + + /** + * Turn the LED on on a specific controller. + * @param controller The controller to turn off. Defaults to 0. + */ + void setLedOn(uint8_t controller = 0) { + setLedRaw(true, controller); + }; + + /** + * Toggle the LED on a specific controller. + * @param controller The controller to turn off. Defaults to 0. + */ + void setLedToggle(uint8_t controller = 0) { + setLedRaw(!ledState[controller], controller); + }; + /**@}*/ + +protected: + /** @name HIDUniversal implementation */ + /** + * Used to parse USB HID data. + * @param hid Pointer to the HID class. + * @param is_rpt_id Only used for Hubs. + * @param len The length of the incoming data. + * @param buf Pointer to the data buffer. + */ + void ParseHIDData(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); + + /** + * Called when a device is successfully initialized. + * Use attachOnInit(void (*funcOnInit)(void)) to call your own function. + * This is useful for instance if you want to set the LEDs in a specific way. + */ + uint8_t OnInitSuccessful(); + /**@}*/ + + /** Used to reset the different buffers to their default values */ + void Reset() { + psbuzzButtons.val = 0; + oldButtonState.val = 0; + buttonClickState.val = 0; + for (uint8_t i = 0; i < sizeof(ledState); i++) + ledState[i] = 0; + }; + + /** @name USBDeviceConfig implementation */ + /** + * Used by the USB core to check what this driver support. + * @param vid The device's VID. + * @param pid The device's PID. + * @return Returns true if the device's VID and PID matches this driver. + */ + virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) { + return (vid == PSBUZZ_VID && pid == PSBUZZ_PID); + }; + /**@}*/ + +private: + void (*pFuncOnInit)(void); // Pointer to function called in onInit() + + void PSBuzz_Command(uint8_t *data, uint16_t nbytes); + + PSBUZZButtons psbuzzButtons, oldButtonState, buttonClickState; + bool ledState[4]; +}; +#endif diff --git a/lib/usbhost/USB_Host_Shield_2.0/README.md b/lib/usbhost/USB_Host_Shield_2.0/README.md new file mode 100644 index 0000000000..1eecb78ef2 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/README.md @@ -0,0 +1,351 @@ +# USB Host Library Rev.2.0 + +The code is released under the GNU General Public License. +__________ + +# Summary +This is Revision 2.0 of MAX3421E-based USB Host Shield Library for AVR's. + +Project main web site is: . + +Some information can also be found at: . + +The shield can be purchased at the main site: or from [TKJ Electronics](http://tkjelectronics.com/): . + +![USB Host Shield](http://shop.tkjelectronics.dk/images/USB_Host_Shield1.jpg) + +For more information about the hardware see the [Hardware Manual](http://www.circuitsathome.com/usb-host-shield-hardware-manual). + +# Developed By + +* __Oleg Mazurov, Circuits@Home__ - +* __Alexei Glushchenko, Circuits@Home__ - + * Developers of the USB Core, HID, FTDI, ADK, ACM, and PL2303 libraries +* __Kristian Lauszus, TKJ Electronics__ - + * Developer of the [BTD](#bluetooth-libraries), [BTHID](#bthid-library), [SPP](#spp-library), [PS4](#ps4-library), [PS3](#ps3-library), [Wii](#wii-library), [Xbox](#xbox-library), and [PSBuzz](#ps-buzz-library) libraries +* __Andrew Kroll__ - + * Major contributor to mass storage code +* __guruthree__ + * [Xbox ONE](#xbox-one-library) controller support + +# Donate + +Help yourself by helping us support you! Many thousands of hours have been spent developing the USB Host Shield library. Since you find it useful, please consider donating via the button below. Donations will allow us to support you by ensuring hardware that you have can be acquired in order to add support for your microcontroller board. + +PayPal - The safer, easier way to pay online! + +# Table of Contents + +* [How to include the library](#how-to-include-the-library) + * [Arduino Library Manager](#arduino-library-manager) + * [Manual installation](#manual-installation) +* [How to use the library](#how-to-use-the-library) + * [Documentation](#documentation) + * [Enable debugging](#enable-debugging) + * [Boards](#boards) + * [Bluetooth libraries](#bluetooth-libraries) + * [BTHID library](#bthid-library) + * [SPP library](#spp-library) + * [PS4 Library](#ps4-library) + * [PS3 Library](#ps3-library) + * [Xbox Libraries](#xbox-libraries) + * [Xbox library](#xbox-library) + * [Xbox 360 Library](#xbox-360-library) + * [Xbox ONE Library](#xbox-one-library) + * [Wii library](#wii-library) + * [PS Buzz Library](#ps-buzz-library) +* [Interface modifications](#interface-modifications) +* [FAQ](#faq) + +# How to include the library + +### Arduino Library Manager + +First install Arduino IDE version 1.6.2 or newer, then simply use the Arduino Library Manager to install the library. + +Please see the following page for instructions: . + +### Manual installation + +First download the library by clicking on the following link: . + +Then uncompress the zip folder and rename the directory to "USB\_Host\_Shield\_20", as any special characters are not supported by the Arduino IDE. + +Now open up the Arduino IDE and open "File>Preferences". There you will see the location of your sketchbook. Open that directory and create a directory called "libraries" inside that directory. +Now move the "USB\_Host\_Shield\_20" directory to the "libraries" directory. + +The final structure should look like this: + +* Arduino/ + * libraries/ + * USB\_Host\_Shield\_20/ + +Now quit the Arduino IDE and reopen it. + +Now you should be able to go open all the examples codes by navigating to "File>Examples>USB\_Host\_Shield\_20" and then select the example you will like to open. + +For more information visit the following sites: and . + +# How to use the library + +### Documentation + +Documentation for the library can be found at the following link: . + +### Enable debugging + +By default serial debugging is disabled. To turn it on simply change ```ENABLE_UHS_DEBUGGING``` to 1 in [settings.h](settings.h) like so: + +```C++ +#define ENABLE_UHS_DEBUGGING 1 +``` + +### Boards + +Currently the following boards are supported by the library: + +* All official Arduino AVR boards (Uno, Duemilanove, Mega, Mega 2560, Mega ADK, Leonardo etc.) +* Arduino Due, Intel Galileo, Intel Galileo 2, and Intel Edison + * Note that the Intel Galileo uses pin 2 and 3 as INT and SS pin respectively by default, so some modifications to the shield are needed. See the "Interface modifications" section in the [hardware manual](https://www.circuitsathome.com/usb-host-shield-hardware-manual) for more information. +* Teensy (Teensy++ 1.0, Teensy 2.0, Teensy++ 2.0, and Teensy 3.x) + * Note if you are using the Teensy 3.x you should download this SPI library as well: . You should then add ```#include ``` to your .ino file. +* Balanduino +* Sanguino +* Black Widdow +* RedBearLab nRF51822 +* Digilent chipKIT + * Please see: . + +The following boards need to be activated manually in [settings.h](settings.h): + +* Arduino Mega ADK + * If you are using Arduino 1.5.5 or newer there is no need to activate the Arduino Mega ADK manually +* Black Widdow + +Simply set the corresponding value to 1 instead of 0. + +### [Bluetooth libraries](BTD.cpp) + +The [BTD library](BTD.cpp) is a general purpose library for an ordinary Bluetooth dongle. +This library make it easy to add support for different Bluetooth services like a PS3 or a Wii controller or SPP which is a virtual serial port via Bluetooth. +Some different examples can be found in the [example directory](examples/Bluetooth). + +The BTD library also makes it possible to use multiple services at once, the following example sketch is an example of this: +[PS3SPP.ino](examples/Bluetooth/PS3SPP/PS3SPP.ino). + +### [BTHID library](BTHID.cpp) + +The [Bluetooth HID library](BTHID.cpp) allows you to connect HID devices via Bluetooth to the USB Host Shield. + +Currently HID mice and keyboards are supported. + +It uses the standard Boot protocol by default, but it is also able to use the Report protocol as well. You would simply have to call ```setProtocolMode()``` and then parse ```HID_RPT_PROTOCOL``` as an argument. You will then have to modify the parser for your device. See the example: [BTHID.ino](examples/Bluetooth/BTHID/BTHID.ino) for more information. + +The [PS4 library](#ps4-library) also uses this class to handle all Bluetooth communication. + +For information see the following blog post: . + +### [SPP library](SPP.cpp) + +SPP stands for "Serial Port Profile" and is a Bluetooth protocol that implements a virtual comport which allows you to send data back and forth from your computer/phone to your Arduino via Bluetooth. +It has been tested successfully on Windows, Mac OS X, Linux, and Android. + +Take a look at the [SPP.ino](examples/Bluetooth/SPP/SPP.ino) example for more information. + +More information can be found at these blog posts: + +* +* + +To implement the SPP protocol I used a Bluetooth sniffing tool called [PacketLogger](http://www.tkjelectronics.com/uploads/PacketLogger.zip) developed by Apple. +It enables me to see the Bluetooth communication between my Mac and any device. + +### PS4 Library + +The PS4BT library is split up into the [PS4BT](PS4BT.h) and the [PS4USB](PS4USB.h) library. These allow you to use the Sony PS4 controller via Bluetooth and USB. + +The [PS4BT.ino](examples/Bluetooth/PS4BT/PS4BT.ino) and [PS4USB.ino](examples/PS4USB/PS4USB.ino) examples shows how to easily read the buttons, joysticks, touchpad and IMU on the controller via Bluetooth and USB respectively. It is also possible to control the rumble and light on the controller and get the battery level. + +Before you can use the PS4 controller via Bluetooth you will need to pair with it. + +Simply create the PS4BT instance like so: ```PS4BT PS4(&Btd, PAIR);``` and then hold down the Share button and then hold down the PS without releasing the Share button. The PS4 controller will then start to blink rapidly indicating that it is in paring mode. + +It should then automatically pair the dongle with your controller. This only have to be done once. + +For information see the following blog post: . + +Also check out this excellent Wiki by Frank Zhao about the PS4 controller: and this Linux driver: . + +### PS3 Library + +These libraries consist of the [PS3BT](PS3BT.cpp) and [PS3USB](PS3USB.cpp). These libraries allows you to use a Dualshock 3, Navigation or a Motion controller with the USB Host Shield both via Bluetooth and USB. + +In order to use your Playstation controller via Bluetooth you have to set the Bluetooth address of the dongle internally to your PS3 Controller. This can be achieved by first plugging in the Bluetooth dongle and wait a few seconds. Now plug in the controller via USB and wait until the LEDs start to flash. The library has now written the Bluetooth address of the dongle to the PS3 controller. + +Finally simply plug in the Bluetooth dongle again and press PS on the PS3 controller. After a few seconds it should be connected to the dongle and ready to use. + +__Note:__ You will have to plug in the Bluetooth dongle before connecting the controller, as the library needs to read the address of the dongle. Alternatively you could set it in code like so: [PS3BT.ino#L20](examples/Bluetooth/PS3BT/PS3BT.ino#L20). + +For more information about the PS3 protocol see the official wiki: . + +Also take a look at the blog posts: + +* +* +* + +A special thanks go to the following people: + +1. _Richard Ibbotson_ who made this excellent guide: +2. _Tomoyuki Tanaka_ for releasing his code for the Arduino USB Host shield connected to the wiimote: + +Also a big thanks all the people behind these sites about the Motion controller: + +* +* +* +* + +### Xbox Libraries + +The library supports both the original Xbox controller via USB and the Xbox 360 controller both via USB and wirelessly. + +#### Xbox library + +The [XBOXOLD](XBOXOLD.cpp) class implements support for the original Xbox controller via USB. + +All the information are from the following sites: + +* +* +* +* + +#### Xbox 360 Library + +The library support one Xbox 360 via USB or up to four Xbox 360 controllers wirelessly by using a [Xbox 360 wireless receiver](http://blog.tkjelectronics.dk/wp-content/uploads/xbox360-wireless-receiver.jpg). + +To use it via USB use the [XBOXUSB](XBOXUSB.cpp) library or to use it wirelessly use the [XBOXRECV](XBOXRECV.cpp) library. + +__Note that a Wireless controller can NOT be used via USB!__ + +Examples code can be found in the [examples directory](examples/Xbox). + +Also see the following blog posts: + +* +* +* + +All the information regarding the Xbox 360 controller protocol are form these sites: + +* +* +* + +#### Xbox ONE Library + +An Xbox ONE controller is supported via USB in the [XBOXONE](XBOXONE.cpp) class. It is heavily based on the 360 library above. In addition to cross referencing the above, information on the protocol was found at: + +* +* +* + +### [Wii library](Wii.cpp) + +The [Wii](Wii.cpp) library support the Wiimote, but also the Nunchuch and Motion Plus extensions via Bluetooth. The Wii U Pro Controller and Wii Balance Board are also supported via Bluetooth. + +First you have to pair with the controller, this is done automatically by the library if you create the instance like so: + +```C++ +WII Wii(&Btd, PAIR); +``` + +And then press 1 & 2 at once on the Wiimote or the SYNC buttons if you are using a Wii U Pro Controller or a Wii Balance Board. + +After that you can simply create the instance like so: + +```C++ +WII Wii(&Btd); +``` + +Then just press any button on the Wiimote and it will then connect to the dongle. + +Take a look at the example for more information: [Wii.ino](examples/Bluetooth/Wii/Wii.ino). + +Also take a look at the blog post: + +* + +The Wii IR camera can also be used, but you will have to activate the code for it manually as it is quite large. Simply set ```ENABLE_WII_IR_CAMERA``` to 1 in [settings.h](settings.h). + +The [WiiIRCamera.ino](examples/Bluetooth/WiiIRCamera/WiiIRCamera.ino) example shows how it can be used. + +All the information about the Wii controllers are from these sites: + +* +* +* +* +* +* The old library created by _Tomoyuki Tanaka_: also helped a lot. + +### [PS Buzz Library](PSBuzz.cpp) + +This library implements support for the Playstation Buzz controllers via USB. + +It is essentially just a wrapper around the [HIDUniversal](hiduniversal.cpp) which takes care of the initializing and reading of the controllers. The [PSBuzz](PSBuzz.cpp) class simply inherits this and parses the data, so it is easy for users to read the buttons and turn the big red button on the controllers on and off. + +The example [PSBuzz.ino](examples/PSBuzz/PSBuzz.ino) shows how one can do this with just a few lines of code. + +More information about the controller can be found at the following sites: + +* http://www.developerfusion.com/article/84338/making-usb-c-friendly/ +* https://github.com/torvalds/linux/blob/master/drivers/hid/hid-sony.c + +# Interface modifications + +The shield is using SPI for communicating with the MAX3421E USB host controller. It uses the SCK, MISO and MOSI pins via the ICSP on your board. + +Note this means that it uses pin 13, 12, 11 on an Arduino Uno, so these pins can not be used for anything else than SPI communication! + +Furthermore it uses one pin as SS and one INT pin. These are by default located on pin 10 and 9 respectively. They can easily be reconfigured in case you need to use them for something else by cutting the jumper on the shield and then solder a wire from the pad to the new pin. + +After that you need modify the following entry in [UsbCore.h](UsbCore.h): + +```C++ +typedef MAX3421e MAX3421E; +``` + +For instance if you have rerouted SS to pin 7 it should read: + +```C++ +typedef MAX3421e MAX3421E; +``` + +See the "Interface modifications" section in the [hardware manual](https://www.circuitsathome.com/usb-host-shield-hardware-manual) for more information. + +# FAQ + +> When I plug my device into the USB connector nothing happens? + +* Try to connect a external power supply to the Arduino - this solves the problem in most cases. +* You can also use a powered hub between the device and the USB Host Shield. You should then include the USB hub library: ```#include ``` and create the instance like so: ```USBHub Hub1(&Usb);```. + +> When I connecting my PS3 controller I get a output like this: + +``` +Dualshock 3 Controller Enabled + +LeftHatX: 0 LeftHatY: 0 RightHatX: 0 RightHatY: 0 +LeftHatX: 0 LeftHatY: 0 RightHatX: 0 RightHatY: 0 +LeftHatX: 0 LeftHatY: 0 RightHatX: 0 RightHatY: 0 +LeftHatX: 0 LeftHatY: 0 RightHatX: 0 RightHatY: 0 +LeftHatX: 0 LeftHatY: 0 RightHatX: 0 RightHatY: 0 +``` + +* This means that your dongle does not support 2.0+EDR, so you will need another dongle. Please see the following [list](https://github.com/felis/USB_Host_Shield_2.0/wiki/Bluetooth-dongles) for tested working dongles. + +> When compiling I am getting the following error: "fatal error: SPI.h: No such file or directory". + +* Please make sure to include the SPI library like so: ```#include ``` in your .ino file. diff --git a/lib/usbhost/USB_Host_Shield_2.0/SPP.cpp b/lib/usbhost/USB_Host_Shield_2.0/SPP.cpp new file mode 100644 index 0000000000..0f4ee5e981 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/SPP.cpp @@ -0,0 +1,829 @@ +/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. + + This software may be distributed and modified under the terms of the GNU + General Public License version 2 (GPL2) as published by the Free Software + Foundation and appearing in the file GPL2.TXT included in the packaging of + this file. Please note that GPL2 Section 2[b] requires that all works based + on this software must also be made publicly available under the terms of + the GPL2 ("Copyleft"). + + Contact information + ------------------- + + Kristian Lauszus, TKJ Electronics + Web : http://www.tkjelectronics.com + e-mail : kristianl@tkjelectronics.com + */ + +#include "SPP.h" +// To enable serial debugging see "settings.h" +//#define EXTRADEBUG // Uncomment to get even more debugging data +//#define PRINTREPORT // Uncomment to print the report sent to the Arduino + +/* + * CRC (reversed crc) lookup table as calculated by the table generator in ETSI TS 101 369 V6.3.0. + */ +const uint8_t rfcomm_crc_table[256] PROGMEM = {/* reversed, 8-bit, poly=0x07 */ + 0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B, + 0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69, 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67, + 0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D, 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43, + 0x24, 0xB5, 0xC7, 0x56, 0x23, 0xB2, 0xC0, 0x51, 0x2A, 0xBB, 0xC9, 0x58, 0x2D, 0xBC, 0xCE, 0x5F, + 0x70, 0xE1, 0x93, 0x02, 0x77, 0xE6, 0x94, 0x05, 0x7E, 0xEF, 0x9D, 0x0C, 0x79, 0xE8, 0x9A, 0x0B, + 0x6C, 0xFD, 0x8F, 0x1E, 0x6B, 0xFA, 0x88, 0x19, 0x62, 0xF3, 0x81, 0x10, 0x65, 0xF4, 0x86, 0x17, + 0x48, 0xD9, 0xAB, 0x3A, 0x4F, 0xDE, 0xAC, 0x3D, 0x46, 0xD7, 0xA5, 0x34, 0x41, 0xD0, 0xA2, 0x33, + 0x54, 0xC5, 0xB7, 0x26, 0x53, 0xC2, 0xB0, 0x21, 0x5A, 0xCB, 0xB9, 0x28, 0x5D, 0xCC, 0xBE, 0x2F, + 0xE0, 0x71, 0x03, 0x92, 0xE7, 0x76, 0x04, 0x95, 0xEE, 0x7F, 0x0D, 0x9C, 0xE9, 0x78, 0x0A, 0x9B, + 0xFC, 0x6D, 0x1F, 0x8E, 0xFB, 0x6A, 0x18, 0x89, 0xF2, 0x63, 0x11, 0x80, 0xF5, 0x64, 0x16, 0x87, + 0xD8, 0x49, 0x3B, 0xAA, 0xDF, 0x4E, 0x3C, 0xAD, 0xD6, 0x47, 0x35, 0xA4, 0xD1, 0x40, 0x32, 0xA3, + 0xC4, 0x55, 0x27, 0xB6, 0xC3, 0x52, 0x20, 0xB1, 0xCA, 0x5B, 0x29, 0xB8, 0xCD, 0x5C, 0x2E, 0xBF, + 0x90, 0x01, 0x73, 0xE2, 0x97, 0x06, 0x74, 0xE5, 0x9E, 0x0F, 0x7D, 0xEC, 0x99, 0x08, 0x7A, 0xEB, + 0x8C, 0x1D, 0x6F, 0xFE, 0x8B, 0x1A, 0x68, 0xF9, 0x82, 0x13, 0x61, 0xF0, 0x85, 0x14, 0x66, 0xF7, + 0xA8, 0x39, 0x4B, 0xDA, 0xAF, 0x3E, 0x4C, 0xDD, 0xA6, 0x37, 0x45, 0xD4, 0xA1, 0x30, 0x42, 0xD3, + 0xB4, 0x25, 0x57, 0xC6, 0xB3, 0x22, 0x50, 0xC1, 0xBA, 0x2B, 0x59, 0xC8, 0xBD, 0x2C, 0x5E, 0xCF +}; + +SPP::SPP(BTD *p, const char* name, const char* pin) : +BluetoothService(p) // Pointer to BTD class instance - mandatory +{ + pBtd->btdName = name; + pBtd->btdPin = pin; + + /* Set device cid for the SDP and RFCOMM channelse */ + sdp_dcid[0] = 0x50; // 0x0050 + sdp_dcid[1] = 0x00; + rfcomm_dcid[0] = 0x51; // 0x0051 + rfcomm_dcid[1] = 0x00; + + Reset(); +} + +void SPP::Reset() { + connected = false; + RFCOMMConnected = false; + SDPConnected = false; + waitForLastCommand = false; + l2cap_sdp_state = L2CAP_SDP_WAIT; + l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT; + l2cap_event_flag = 0; + sppIndex = 0; + creditSent = false; +} + +void SPP::disconnect() { + connected = false; + // First the two L2CAP channels has to be disconnected and then the HCI connection + if(RFCOMMConnected) + pBtd->l2cap_disconnection_request(hci_handle, ++identifier, rfcomm_scid, rfcomm_dcid); + if(RFCOMMConnected && SDPConnected) + delay(1); // Add delay between commands + if(SDPConnected) + pBtd->l2cap_disconnection_request(hci_handle, ++identifier, sdp_scid, sdp_dcid); + l2cap_sdp_state = L2CAP_DISCONNECT_RESPONSE; +} + +void SPP::ACLData(uint8_t* l2capinbuf) { + if(!connected) { + if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { + if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == SDP_PSM && !pBtd->sdpConnectionClaimed) { + pBtd->sdpConnectionClaimed = true; + hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection + l2cap_sdp_state = L2CAP_SDP_WAIT; // Reset state + } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == RFCOMM_PSM && !pBtd->rfcommConnectionClaimed) { + pBtd->rfcommConnectionClaimed = true; + hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection + l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT; // Reset state + } + } + } + + if(checkHciHandle(l2capinbuf, hci_handle)) { // acl_handle_ok + if((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001U) { // l2cap_control - Channel ID for ACL-U + if(l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80); + D_PrintHex (l2capinbuf[13], 0x80); + Notify(PSTR(" "), 0x80); + D_PrintHex (l2capinbuf[12], 0x80); + Notify(PSTR(" Data: "), 0x80); + D_PrintHex (l2capinbuf[17], 0x80); + Notify(PSTR(" "), 0x80); + D_PrintHex (l2capinbuf[16], 0x80); + Notify(PSTR(" "), 0x80); + D_PrintHex (l2capinbuf[15], 0x80); + Notify(PSTR(" "), 0x80); + D_PrintHex (l2capinbuf[14], 0x80); +#endif + } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { +#ifdef EXTRADEBUG + Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80); + D_PrintHex (l2capinbuf[13], 0x80); + Notify(PSTR(" "), 0x80); + D_PrintHex (l2capinbuf[12], 0x80); + Notify(PSTR(" SCID: "), 0x80); + D_PrintHex (l2capinbuf[15], 0x80); + Notify(PSTR(" "), 0x80); + D_PrintHex (l2capinbuf[14], 0x80); + Notify(PSTR(" Identifier: "), 0x80); + D_PrintHex (l2capinbuf[9], 0x80); +#endif + if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == SDP_PSM) { // It doesn't matter if it receives another reqeust, since it waits for the channel to disconnect in the L2CAP_SDP_DONE state, and the l2cap_event_flag will be cleared if so + identifier = l2capinbuf[9]; + sdp_scid[0] = l2capinbuf[14]; + sdp_scid[1] = l2capinbuf[15]; + l2cap_set_flag(L2CAP_FLAG_CONNECTION_SDP_REQUEST); + } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == RFCOMM_PSM) { // ----- || ----- + identifier = l2capinbuf[9]; + rfcomm_scid[0] = l2capinbuf[14]; + rfcomm_scid[1] = l2capinbuf[15]; + l2cap_set_flag(L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST); + } + } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) { + if((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success + if(l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) { + //Notify(PSTR("\r\nSDP Configuration Complete"), 0x80); + l2cap_set_flag(L2CAP_FLAG_CONFIG_SDP_SUCCESS); + } else if(l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) { + //Notify(PSTR("\r\nRFCOMM Configuration Complete"), 0x80); + l2cap_set_flag(L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS); + } + } + } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) { + if(l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) { + //Notify(PSTR("\r\nSDP Configuration Request"), 0x80); + pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], sdp_scid); + } else if(l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) { + //Notify(PSTR("\r\nRFCOMM Configuration Request"), 0x80); + pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], rfcomm_scid); + } + } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) { + if(l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) { + //Notify(PSTR("\r\nDisconnect Request: SDP Channel"), 0x80); + identifier = l2capinbuf[9]; + l2cap_set_flag(L2CAP_FLAG_DISCONNECT_SDP_REQUEST); + } else if(l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) { + //Notify(PSTR("\r\nDisconnect Request: RFCOMM Channel"), 0x80); + identifier = l2capinbuf[9]; + l2cap_set_flag(L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST); + } + } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) { + if(l2capinbuf[12] == sdp_scid[0] && l2capinbuf[13] == sdp_scid[1]) { + //Notify(PSTR("\r\nDisconnect Response: SDP Channel"), 0x80); + identifier = l2capinbuf[9]; + l2cap_set_flag(L2CAP_FLAG_DISCONNECT_RESPONSE); + } else if(l2capinbuf[12] == rfcomm_scid[0] && l2capinbuf[13] == rfcomm_scid[1]) { + //Notify(PSTR("\r\nDisconnect Response: RFCOMM Channel"), 0x80); + identifier = l2capinbuf[9]; + l2cap_set_flag(L2CAP_FLAG_DISCONNECT_RESPONSE); + } + } else if(l2capinbuf[8] == L2CAP_CMD_INFORMATION_REQUEST) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nInformation request"), 0x80); +#endif + identifier = l2capinbuf[9]; + pBtd->l2cap_information_response(hci_handle, identifier, l2capinbuf[12], l2capinbuf[13]); + } +#ifdef EXTRADEBUG + else { + Notify(PSTR("\r\nL2CAP Unknown Signaling Command: "), 0x80); + D_PrintHex (l2capinbuf[8], 0x80); + } +#endif + } else if(l2capinbuf[6] == sdp_dcid[0] && l2capinbuf[7] == sdp_dcid[1]) { // SDP + if(l2capinbuf[8] == SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST_PDU) { + if(((l2capinbuf[16] << 8 | l2capinbuf[17]) == SERIALPORT_UUID) || ((l2capinbuf[16] << 8 | l2capinbuf[17]) == 0x0000 && (l2capinbuf[18] << 8 | l2capinbuf[19]) == SERIALPORT_UUID)) { // Check if it's sending the full UUID, see: https://www.bluetooth.org/Technical/AssignedNumbers/service_discovery.htm, we will just check the first four bytes + if(firstMessage) { + serialPortResponse1(l2capinbuf[9], l2capinbuf[10]); + firstMessage = false; + } else { + serialPortResponse2(l2capinbuf[9], l2capinbuf[10]); // Serialport continuation state + firstMessage = true; + } + } else if(((l2capinbuf[16] << 8 | l2capinbuf[17]) == L2CAP_UUID) || ((l2capinbuf[16] << 8 | l2capinbuf[17]) == 0x0000 && (l2capinbuf[18] << 8 | l2capinbuf[19]) == L2CAP_UUID)) { + if(firstMessage) { + l2capResponse1(l2capinbuf[9], l2capinbuf[10]); + firstMessage = false; + } else { + l2capResponse2(l2capinbuf[9], l2capinbuf[10]); // L2CAP continuation state + firstMessage = true; + } + } else + serviceNotSupported(l2capinbuf[9], l2capinbuf[10]); // The service is not supported +#ifdef EXTRADEBUG + Notify(PSTR("\r\nUUID: "), 0x80); + uint16_t uuid; + if((l2capinbuf[16] << 8 | l2capinbuf[17]) == 0x0000) // Check if it's sending the UUID as a 128-bit UUID + uuid = (l2capinbuf[18] << 8 | l2capinbuf[19]); + else // Short UUID + uuid = (l2capinbuf[16] << 8 | l2capinbuf[17]); + D_PrintHex (uuid, 0x80); + + Notify(PSTR("\r\nLength: "), 0x80); + uint16_t length = l2capinbuf[11] << 8 | l2capinbuf[12]; + D_PrintHex (length, 0x80); + Notify(PSTR("\r\nData: "), 0x80); + for(uint8_t i = 0; i < length; i++) { + D_PrintHex (l2capinbuf[13 + i], 0x80); + Notify(PSTR(" "), 0x80); + } +#endif + } +#ifdef EXTRADEBUG + else { + Notify(PSTR("\r\nUnknown PDU: "), 0x80); + D_PrintHex (l2capinbuf[8], 0x80); + } +#endif + } else if(l2capinbuf[6] == rfcomm_dcid[0] && l2capinbuf[7] == rfcomm_dcid[1]) { // RFCOMM + rfcommChannel = l2capinbuf[8] & 0xF8; + rfcommDirection = l2capinbuf[8] & 0x04; + rfcommCommandResponse = l2capinbuf[8] & 0x02; + rfcommChannelType = l2capinbuf[9] & 0xEF; + rfcommPfBit = l2capinbuf[9] & 0x10; + + if(rfcommChannel >> 3 != 0x00) + rfcommChannelConnection = rfcommChannel; + +#ifdef EXTRADEBUG + Notify(PSTR("\r\nRFCOMM Channel: "), 0x80); + D_PrintHex (rfcommChannel >> 3, 0x80); + Notify(PSTR(" Direction: "), 0x80); + D_PrintHex (rfcommDirection >> 2, 0x80); + Notify(PSTR(" CommandResponse: "), 0x80); + D_PrintHex (rfcommCommandResponse >> 1, 0x80); + Notify(PSTR(" ChannelType: "), 0x80); + D_PrintHex (rfcommChannelType, 0x80); + Notify(PSTR(" PF_BIT: "), 0x80); + D_PrintHex (rfcommPfBit, 0x80); +#endif + if(rfcommChannelType == RFCOMM_DISC) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nReceived Disconnect RFCOMM Command on channel: "), 0x80); + D_PrintHex (rfcommChannel >> 3, 0x80); +#endif + connected = false; + sendRfcomm(rfcommChannel, rfcommDirection, rfcommCommandResponse, RFCOMM_UA, rfcommPfBit, rfcommbuf, 0x00); // UA Command + } + if(connected) { + /* Read the incoming message */ + if(rfcommChannelType == RFCOMM_UIH && rfcommChannel == rfcommChannelConnection) { + uint8_t length = l2capinbuf[10] >> 1; // Get length + uint8_t offset = l2capinbuf[4] - length - 4; // Check if there is credit + if(checkFcs(&l2capinbuf[8], l2capinbuf[11 + length + offset])) { + uint8_t i = 0; + for(; i < length; i++) { + if(rfcommAvailable + i >= sizeof (rfcommDataBuffer)) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nWarning: Buffer is full!"), 0x80); +#endif + break; + } + rfcommDataBuffer[rfcommAvailable + i] = l2capinbuf[11 + i + offset]; + } + rfcommAvailable += i; +#ifdef EXTRADEBUG + Notify(PSTR("\r\nRFCOMM Data Available: "), 0x80); + Notify(rfcommAvailable, 0x80); + if(offset) { + Notify(PSTR(" - Credit: 0x"), 0x80); + D_PrintHex (l2capinbuf[11], 0x80); + } +#endif + } +#ifdef DEBUG_USB_HOST + else + Notify(PSTR("\r\nError in FCS checksum!"), 0x80); +#endif +#ifdef PRINTREPORT // Uncomment "#define PRINTREPORT" to print the report send to the Arduino via Bluetooth + for(uint8_t i = 0; i < length; i++) + Notifyc(l2capinbuf[i + 11 + offset], 0x80); +#endif + } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_RPN_CMD) { // UIH Remote Port Negotiation Command +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nReceived UIH Remote Port Negotiation Command"), 0x80); +#endif + rfcommbuf[0] = BT_RFCOMM_RPN_RSP; // Command + rfcommbuf[1] = l2capinbuf[12]; // Length and shiftet like so: length << 1 | 1 + rfcommbuf[2] = l2capinbuf[13]; // Channel: channel << 1 | 1 + rfcommbuf[3] = l2capinbuf[14]; // Pre difined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM + rfcommbuf[4] = l2capinbuf[15]; // Priority + rfcommbuf[5] = l2capinbuf[16]; // Timer + rfcommbuf[6] = l2capinbuf[17]; // Max Fram Size LSB + rfcommbuf[7] = l2capinbuf[18]; // Max Fram Size MSB + rfcommbuf[8] = l2capinbuf[19]; // MaxRatransm. + rfcommbuf[9] = l2capinbuf[20]; // Number of Frames + sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x0A); // UIH Remote Port Negotiation Response + } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_MSC_CMD) { // UIH Modem Status Command +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nSend UIH Modem Status Response"), 0x80); +#endif + rfcommbuf[0] = BT_RFCOMM_MSC_RSP; // UIH Modem Status Response + rfcommbuf[1] = 2 << 1 | 1; // Length and shiftet like so: length << 1 | 1 + rfcommbuf[2] = l2capinbuf[13]; // Channel: (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3) + rfcommbuf[3] = l2capinbuf[14]; + sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x04); + } + } else { + if(rfcommChannelType == RFCOMM_SABM) { // SABM Command - this is sent twice: once for channel 0 and then for the channel to establish +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nReceived SABM Command"), 0x80); +#endif + sendRfcomm(rfcommChannel, rfcommDirection, rfcommCommandResponse, RFCOMM_UA, rfcommPfBit, rfcommbuf, 0x00); // UA Command + } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_PN_CMD) { // UIH Parameter Negotiation Command +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nReceived UIH Parameter Negotiation Command"), 0x80); +#endif + rfcommbuf[0] = BT_RFCOMM_PN_RSP; // UIH Parameter Negotiation Response + rfcommbuf[1] = l2capinbuf[12]; // Length and shiftet like so: length << 1 | 1 + rfcommbuf[2] = l2capinbuf[13]; // Channel: channel << 1 | 1 + rfcommbuf[3] = 0xE0; // Pre difined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM + rfcommbuf[4] = 0x00; // Priority + rfcommbuf[5] = 0x00; // Timer + rfcommbuf[6] = BULK_MAXPKTSIZE - 14; // Max Fram Size LSB - set to the size of received data (50) + rfcommbuf[7] = 0x00; // Max Fram Size MSB + rfcommbuf[8] = 0x00; // MaxRatransm. + rfcommbuf[9] = 0x00; // Number of Frames + sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x0A); + } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_MSC_CMD) { // UIH Modem Status Command +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nSend UIH Modem Status Response"), 0x80); +#endif + rfcommbuf[0] = BT_RFCOMM_MSC_RSP; // UIH Modem Status Response + rfcommbuf[1] = 2 << 1 | 1; // Length and shiftet like so: length << 1 | 1 + rfcommbuf[2] = l2capinbuf[13]; // Channel: (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3) + rfcommbuf[3] = l2capinbuf[14]; + sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x04); + + delay(1); +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nSend UIH Modem Status Command"), 0x80); +#endif + rfcommbuf[0] = BT_RFCOMM_MSC_CMD; // UIH Modem Status Command + rfcommbuf[1] = 2 << 1 | 1; // Length and shiftet like so: length << 1 | 1 + rfcommbuf[2] = l2capinbuf[13]; // Channel: (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3) + rfcommbuf[3] = 0x8D; // Can receive frames (YES), Ready to Communicate (YES), Ready to Receive (YES), Incomig Call (NO), Data is Value (YES) + + sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x04); + } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_MSC_RSP) { // UIH Modem Status Response + if(!creditSent) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nSend UIH Command with credit"), 0x80); +#endif + sendRfcommCredit(rfcommChannelConnection, rfcommDirection, 0, RFCOMM_UIH, 0x10, sizeof (rfcommDataBuffer)); // Send credit + creditSent = true; + timer = millis(); + waitForLastCommand = true; + } + } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[10] == 0x01) { // UIH Command with credit +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nReceived UIH Command with credit"), 0x80); +#endif + } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_RPN_CMD) { // UIH Remote Port Negotiation Command +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nReceived UIH Remote Port Negotiation Command"), 0x80); +#endif + rfcommbuf[0] = BT_RFCOMM_RPN_RSP; // Command + rfcommbuf[1] = l2capinbuf[12]; // Length and shiftet like so: length << 1 | 1 + rfcommbuf[2] = l2capinbuf[13]; // Channel: channel << 1 | 1 + rfcommbuf[3] = l2capinbuf[14]; // Pre difined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM + rfcommbuf[4] = l2capinbuf[15]; // Priority + rfcommbuf[5] = l2capinbuf[16]; // Timer + rfcommbuf[6] = l2capinbuf[17]; // Max Fram Size LSB + rfcommbuf[7] = l2capinbuf[18]; // Max Fram Size MSB + rfcommbuf[8] = l2capinbuf[19]; // MaxRatransm. + rfcommbuf[9] = l2capinbuf[20]; // Number of Frames + sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x0A); // UIH Remote Port Negotiation Response +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nRFCOMM Connection is now established\r\n"), 0x80); +#endif + onInit(); + } +#ifdef EXTRADEBUG + else if(rfcommChannelType != RFCOMM_DISC) { + Notify(PSTR("\r\nUnsupported RFCOMM Data - ChannelType: "), 0x80); + D_PrintHex (rfcommChannelType, 0x80); + Notify(PSTR(" Command: "), 0x80); + D_PrintHex (l2capinbuf[11], 0x80); + } +#endif + } + } +#ifdef EXTRADEBUG + else { + Notify(PSTR("\r\nUnsupported L2CAP Data - Channel ID: "), 0x80); + D_PrintHex (l2capinbuf[7], 0x80); + Notify(PSTR(" "), 0x80); + D_PrintHex (l2capinbuf[6], 0x80); + } +#endif + SDP_task(); + RFCOMM_task(); + } +} + +void SPP::Run() { + if(waitForLastCommand && (millis() - timer) > 100) { // We will only wait 100ms and see if the UIH Remote Port Negotiation Command is send, as some deviced don't send it +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nRFCOMM Connection is now established - Automatic\r\n"), 0x80); +#endif + onInit(); + } + send(); // Send all bytes currently in the buffer +} + +void SPP::onInit() { + creditSent = false; + waitForLastCommand = false; + connected = true; // The RFCOMM channel is now established + sppIndex = 0; + if(pFuncOnInit) + pFuncOnInit(); // Call the user function +}; + +void SPP::SDP_task() { + switch(l2cap_sdp_state) { + case L2CAP_SDP_WAIT: + if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_SDP_REQUEST)) { + l2cap_clear_flag(L2CAP_FLAG_CONNECTION_SDP_REQUEST); // Clear flag +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nSDP Incoming Connection Request"), 0x80); +#endif + pBtd->l2cap_connection_response(hci_handle, identifier, sdp_dcid, sdp_scid, PENDING); + delay(1); + pBtd->l2cap_connection_response(hci_handle, identifier, sdp_dcid, sdp_scid, SUCCESSFUL); + identifier++; + delay(1); + pBtd->l2cap_config_request(hci_handle, identifier, sdp_scid); + l2cap_sdp_state = L2CAP_SDP_SUCCESS; + } else if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_SDP_REQUEST)) { + l2cap_clear_flag(L2CAP_FLAG_DISCONNECT_SDP_REQUEST); // Clear flag + SDPConnected = false; +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nDisconnected SDP Channel"), 0x80); +#endif + pBtd->l2cap_disconnection_response(hci_handle, identifier, sdp_dcid, sdp_scid); + } + break; + case L2CAP_SDP_SUCCESS: + if(l2cap_check_flag(L2CAP_FLAG_CONFIG_SDP_SUCCESS)) { + l2cap_clear_flag(L2CAP_FLAG_CONFIG_SDP_SUCCESS); // Clear flag +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nSDP Successfully Configured"), 0x80); +#endif + firstMessage = true; // Reset bool + SDPConnected = true; + l2cap_sdp_state = L2CAP_SDP_WAIT; + } + break; + + case L2CAP_DISCONNECT_RESPONSE: // This is for both disconnection response from the RFCOMM and SDP channel if they were connected + if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_RESPONSE)) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nDisconnected L2CAP Connection"), 0x80); +#endif + pBtd->hci_disconnect(hci_handle); + hci_handle = -1; // Reset handle + Reset(); + } + break; + } +} + +void SPP::RFCOMM_task() { + switch(l2cap_rfcomm_state) { + case L2CAP_RFCOMM_WAIT: + if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST)) { + l2cap_clear_flag(L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST); // Clear flag +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nRFCOMM Incoming Connection Request"), 0x80); +#endif + pBtd->l2cap_connection_response(hci_handle, identifier, rfcomm_dcid, rfcomm_scid, PENDING); + delay(1); + pBtd->l2cap_connection_response(hci_handle, identifier, rfcomm_dcid, rfcomm_scid, SUCCESSFUL); + identifier++; + delay(1); + pBtd->l2cap_config_request(hci_handle, identifier, rfcomm_scid); + l2cap_rfcomm_state = L2CAP_RFCOMM_SUCCESS; + } else if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST)) { + l2cap_clear_flag(L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST); // Clear flag + RFCOMMConnected = false; + connected = false; +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nDisconnected RFCOMM Channel"), 0x80); +#endif + pBtd->l2cap_disconnection_response(hci_handle, identifier, rfcomm_dcid, rfcomm_scid); + } + break; + case L2CAP_RFCOMM_SUCCESS: + if(l2cap_check_flag(L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS)) { + l2cap_clear_flag(L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS); // Clear flag +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nRFCOMM Successfully Configured"), 0x80); +#endif + rfcommAvailable = 0; // Reset number of bytes available + bytesRead = 0; // Reset number of bytes received + RFCOMMConnected = true; + l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT; + } + break; + } +} +/************************************************************/ +/* SDP Commands */ + +/************************************************************/ +void SPP::SDP_Command(uint8_t* data, uint8_t nbytes) { // See page 223 in the Bluetooth specs + pBtd->L2CAP_Command(hci_handle, data, nbytes, sdp_scid[0], sdp_scid[1]); +} + +void SPP::serviceNotSupported(uint8_t transactionIDHigh, uint8_t transactionIDLow) { // See page 235 in the Bluetooth specs + l2capoutbuf[0] = SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU; + l2capoutbuf[1] = transactionIDHigh; + l2capoutbuf[2] = transactionIDLow; + l2capoutbuf[3] = 0x00; // MSB Parameter Length + l2capoutbuf[4] = 0x05; // LSB Parameter Length = 5 + l2capoutbuf[5] = 0x00; // MSB AttributeListsByteCount + l2capoutbuf[6] = 0x02; // LSB AttributeListsByteCount = 2 + + /* Attribute ID/Value Sequence: */ + l2capoutbuf[7] = 0x35; // Data element sequence - length in next byte + l2capoutbuf[8] = 0x00; // Length = 0 + l2capoutbuf[9] = 0x00; // No continuation state + + SDP_Command(l2capoutbuf, 10); +} + +void SPP::serialPortResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow) { + l2capoutbuf[0] = SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU; + l2capoutbuf[1] = transactionIDHigh; + l2capoutbuf[2] = transactionIDLow; + l2capoutbuf[3] = 0x00; // MSB Parameter Length + l2capoutbuf[4] = 0x2B; // LSB Parameter Length = 43 + l2capoutbuf[5] = 0x00; // MSB AttributeListsByteCount + l2capoutbuf[6] = 0x26; // LSB AttributeListsByteCount = 38 + + /* Attribute ID/Value Sequence: */ + l2capoutbuf[7] = 0x36; // Data element sequence - length in next two bytes + l2capoutbuf[8] = 0x00; // MSB Length + l2capoutbuf[9] = 0x3C; // LSB Length = 60 + + l2capoutbuf[10] = 0x36; // Data element sequence - length in next two bytes + l2capoutbuf[11] = 0x00; // MSB Length + l2capoutbuf[12] = 0x39; // LSB Length = 57 + + l2capoutbuf[13] = 0x09; // Unsigned Integer - length 2 bytes + l2capoutbuf[14] = 0x00; // MSB ServiceRecordHandle + l2capoutbuf[15] = 0x00; // LSB ServiceRecordHandle + l2capoutbuf[16] = 0x0A; // Unsigned int - length 4 bytes + l2capoutbuf[17] = 0x00; // ServiceRecordHandle value - TODO: Is this related to HCI_Handle? + l2capoutbuf[18] = 0x01; + l2capoutbuf[19] = 0x00; + l2capoutbuf[20] = 0x06; + + l2capoutbuf[21] = 0x09; // Unsigned Integer - length 2 bytes + l2capoutbuf[22] = 0x00; // MSB ServiceClassIDList + l2capoutbuf[23] = 0x01; // LSB ServiceClassIDList + l2capoutbuf[24] = 0x35; // Data element sequence - length in next byte + l2capoutbuf[25] = 0x03; // Length = 3 + l2capoutbuf[26] = 0x19; // UUID (universally unique identifier) - length = 2 bytes + l2capoutbuf[27] = 0x11; // MSB SerialPort + l2capoutbuf[28] = 0x01; // LSB SerialPort + + l2capoutbuf[29] = 0x09; // Unsigned Integer - length 2 bytes + l2capoutbuf[30] = 0x00; // MSB ProtocolDescriptorList + l2capoutbuf[31] = 0x04; // LSB ProtocolDescriptorList + l2capoutbuf[32] = 0x35; // Data element sequence - length in next byte + l2capoutbuf[33] = 0x0C; // Length = 12 + + l2capoutbuf[34] = 0x35; // Data element sequence - length in next byte + l2capoutbuf[35] = 0x03; // Length = 3 + l2capoutbuf[36] = 0x19; // UUID (universally unique identifier) - length = 2 bytes + l2capoutbuf[37] = 0x01; // MSB L2CAP + l2capoutbuf[38] = 0x00; // LSB L2CAP + + l2capoutbuf[39] = 0x35; // Data element sequence - length in next byte + l2capoutbuf[40] = 0x05; // Length = 5 + l2capoutbuf[41] = 0x19; // UUID (universally unique identifier) - length = 2 bytes + l2capoutbuf[42] = 0x00; // MSB RFCOMM + l2capoutbuf[43] = 0x03; // LSB RFCOMM + l2capoutbuf[44] = 0x08; // Unsigned Integer - length 1 byte + + l2capoutbuf[45] = 0x02; // ContinuationState - Two more bytes + l2capoutbuf[46] = 0x00; // MSB length + l2capoutbuf[47] = 0x19; // LSB length = 25 more bytes to come + + SDP_Command(l2capoutbuf, 48); +} + +void SPP::serialPortResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow) { + l2capoutbuf[0] = SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU; + l2capoutbuf[1] = transactionIDHigh; + l2capoutbuf[2] = transactionIDLow; + l2capoutbuf[3] = 0x00; // MSB Parameter Length + l2capoutbuf[4] = 0x1C; // LSB Parameter Length = 28 + l2capoutbuf[5] = 0x00; // MSB AttributeListsByteCount + l2capoutbuf[6] = 0x19; // LSB AttributeListsByteCount = 25 + + /* Attribute ID/Value Sequence: */ + l2capoutbuf[7] = 0x01; // Channel 1 - TODO: Try different values, so multiple servers can be used at once + + l2capoutbuf[8] = 0x09; // Unsigned Integer - length 2 bytes + l2capoutbuf[9] = 0x00; // MSB LanguageBaseAttributeIDList + l2capoutbuf[10] = 0x06; // LSB LanguageBaseAttributeIDList + l2capoutbuf[11] = 0x35; // Data element sequence - length in next byte + l2capoutbuf[12] = 0x09; // Length = 9 + + // Identifier representing the natural language = en = English - see: "ISO 639:1988" + l2capoutbuf[13] = 0x09; // Unsigned Integer - length 2 bytes + l2capoutbuf[14] = 0x65; // 'e' + l2capoutbuf[15] = 0x6E; // 'n' + + // "The second element of each triplet contains an identifier that specifies a character encoding used for the language" + // Encoding is set to 106 (UTF-8) - see: http://www.iana.org/assignments/character-sets/character-sets.xhtml + l2capoutbuf[16] = 0x09; // Unsigned Integer - length 2 bytes + l2capoutbuf[17] = 0x00; // MSB of character encoding + l2capoutbuf[18] = 0x6A; // LSB of character encoding (106) + + // Attribute ID that serves as the base attribute ID for the natural language in the service record + // "To facilitate the retrieval of human-readable universal attributes in a principal language, the base attribute ID value for the primary language supported by a service record shall be 0x0100" + l2capoutbuf[19] = 0x09; // Unsigned Integer - length 2 bytes + l2capoutbuf[20] = 0x01; + l2capoutbuf[21] = 0x00; + + l2capoutbuf[22] = 0x09; // Unsigned Integer - length 2 bytes + l2capoutbuf[23] = 0x01; // MSB ServiceDescription + l2capoutbuf[24] = 0x00; // LSB ServiceDescription + + l2capoutbuf[25] = 0x25; // Text string - length in next byte + l2capoutbuf[26] = 0x05; // Name length + l2capoutbuf[27] = 'T'; + l2capoutbuf[28] = 'K'; + l2capoutbuf[29] = 'J'; + l2capoutbuf[30] = 'S'; + l2capoutbuf[31] = 'P'; + l2capoutbuf[32] = 0x00; // No continuation state + + SDP_Command(l2capoutbuf, 33); +} + +void SPP::l2capResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow) { + serialPortResponse1(transactionIDHigh, transactionIDLow); // These has to send all the supported functions, since it only supports virtual serialport it just sends the message again +} + +void SPP::l2capResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow) { + serialPortResponse2(transactionIDHigh, transactionIDLow); // Same data as serialPortResponse2 +} +/************************************************************/ +/* RFCOMM Commands */ + +/************************************************************/ +void SPP::RFCOMM_Command(uint8_t* data, uint8_t nbytes) { + pBtd->L2CAP_Command(hci_handle, data, nbytes, rfcomm_scid[0], rfcomm_scid[1]); +} + +void SPP::sendRfcomm(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t* data, uint8_t length) { + l2capoutbuf[0] = channel | direction | CR | extendAddress; // RFCOMM Address + l2capoutbuf[1] = channelType | pfBit; // RFCOMM Control + l2capoutbuf[2] = length << 1 | 0x01; // Length and format (always 0x01 bytes format) + uint8_t i = 0; + for(; i < length; i++) + l2capoutbuf[i + 3] = data[i]; + l2capoutbuf[i + 3] = calcFcs(l2capoutbuf); +#ifdef EXTRADEBUG + Notify(PSTR(" - RFCOMM Data: "), 0x80); + for(i = 0; i < length + 4; i++) { + D_PrintHex (l2capoutbuf[i], 0x80); + Notify(PSTR(" "), 0x80); + } +#endif + RFCOMM_Command(l2capoutbuf, length + 4); +} + +void SPP::sendRfcommCredit(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t credit) { + l2capoutbuf[0] = channel | direction | CR | extendAddress; // RFCOMM Address + l2capoutbuf[1] = channelType | pfBit; // RFCOMM Control + l2capoutbuf[2] = 0x01; // Length = 0 + l2capoutbuf[3] = credit; // Credit + l2capoutbuf[4] = calcFcs(l2capoutbuf); +#ifdef EXTRADEBUG + Notify(PSTR(" - RFCOMM Credit Data: "), 0x80); + for(uint8_t i = 0; i < 5; i++) { + D_PrintHex (l2capoutbuf[i], 0x80); + Notify(PSTR(" "), 0x80); + } +#endif + RFCOMM_Command(l2capoutbuf, 5); +} + +/* CRC on 2 bytes */ +uint8_t SPP::crc(uint8_t *data) { + return (pgm_read_byte(&rfcomm_crc_table[pgm_read_byte(&rfcomm_crc_table[0xFF ^ data[0]]) ^ data[1]])); +} + +/* Calculate FCS */ +uint8_t SPP::calcFcs(uint8_t *data) { + uint8_t temp = crc(data); + if((data[1] & 0xEF) == RFCOMM_UIH) + return (0xFF - temp); // FCS on 2 bytes + else + return (0xFF - pgm_read_byte(&rfcomm_crc_table[temp ^ data[2]])); // FCS on 3 bytes +} + +/* Check FCS */ +bool SPP::checkFcs(uint8_t *data, uint8_t fcs) { + uint8_t temp = crc(data); + if((data[1] & 0xEF) != RFCOMM_UIH) + temp = pgm_read_byte(&rfcomm_crc_table[temp ^ data[2]]); // FCS on 3 bytes + return (pgm_read_byte(&rfcomm_crc_table[temp ^ fcs]) == 0xCF); +} + +/* Serial commands */ +#if defined(ARDUINO) && ARDUINO >=100 + +size_t SPP::write(uint8_t data) { + return write(&data, 1); +} +#else + +void SPP::write(uint8_t data) { + write(&data, 1); +} +#endif + +#if defined(ARDUINO) && ARDUINO >=100 + +size_t SPP::write(const uint8_t *data, size_t size) { +#else + +void SPP::write(const uint8_t *data, size_t size) { +#endif + for(uint8_t i = 0; i < size; i++) { + if(sppIndex >= sizeof (sppOutputBuffer) / sizeof (sppOutputBuffer[0])) + send(); // Send the current data in the buffer + sppOutputBuffer[sppIndex++] = data[i]; // All the bytes are put into a buffer and then send using the send() function + } +#if defined(ARDUINO) && ARDUINO >=100 + return size; +#endif +} + +void SPP::send() { + if(!connected || !sppIndex) + return; + uint8_t length; // This is the length of the string we are sending + uint8_t offset = 0; // This is used to keep track of where we are in the string + + l2capoutbuf[0] = rfcommChannelConnection | 0 | 0 | extendAddress; // RFCOMM Address + l2capoutbuf[1] = RFCOMM_UIH; // RFCOMM Control + + while(sppIndex) { // We will run this while loop until this variable is 0 + if(sppIndex > (sizeof (l2capoutbuf) - 4)) // Check if the string is larger than the outgoing buffer + length = sizeof (l2capoutbuf) - 4; + else + length = sppIndex; + + l2capoutbuf[2] = length << 1 | 1; // Length + uint8_t i = 0; + for(; i < length; i++) + l2capoutbuf[i + 3] = sppOutputBuffer[i + offset]; + l2capoutbuf[i + 3] = calcFcs(l2capoutbuf); // Calculate checksum + + RFCOMM_Command(l2capoutbuf, length + 4); + + sppIndex -= length; + offset += length; // Increment the offset + } +} + +int SPP::available(void) { + return rfcommAvailable; +}; + +void SPP::discard(void) { + rfcommAvailable = 0; +} + +int SPP::peek(void) { + if(rfcommAvailable == 0) // Don't read if there is nothing in the buffer + return -1; + return rfcommDataBuffer[0]; +} + +int SPP::read(void) { + if(rfcommAvailable == 0) // Don't read if there is nothing in the buffer + return -1; + uint8_t output = rfcommDataBuffer[0]; + for(uint8_t i = 1; i < rfcommAvailable; i++) + rfcommDataBuffer[i - 1] = rfcommDataBuffer[i]; // Shift the buffer one left + rfcommAvailable--; + bytesRead++; + if(bytesRead > (sizeof (rfcommDataBuffer) - 5)) { // We will send the command just before it runs out of credit + bytesRead = 0; + sendRfcommCredit(rfcommChannelConnection, rfcommDirection, 0, RFCOMM_UIH, 0x10, sizeof (rfcommDataBuffer)); // Send more credit +#ifdef EXTRADEBUG + Notify(PSTR("\r\nSent "), 0x80); + Notify((uint8_t)sizeof (rfcommDataBuffer), 0x80); + Notify(PSTR(" more credit"), 0x80); +#endif + } + return output; +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/SPP.h b/lib/usbhost/USB_Host_Shield_2.0/SPP.h new file mode 100644 index 0000000000..233ac611fd --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/SPP.h @@ -0,0 +1,225 @@ +/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. + + This software may be distributed and modified under the terms of the GNU + General Public License version 2 (GPL2) as published by the Free Software + Foundation and appearing in the file GPL2.TXT included in the packaging of + this file. Please note that GPL2 Section 2[b] requires that all works based + on this software must also be made publicly available under the terms of + the GPL2 ("Copyleft"). + + Contact information + ------------------- + + Kristian Lauszus, TKJ Electronics + Web : http://www.tkjelectronics.com + e-mail : kristianl@tkjelectronics.com + */ + +#ifndef _spp_h_ +#define _spp_h_ + +#include "BTD.h" + +/* Used for SDP */ +#define SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST_PDU 0x06 // See the RFCOMM specs +#define SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU 0x07 // See the RFCOMM specs +#define SERIALPORT_UUID 0x1101 // See http://www.bluetooth.org/Technical/AssignedNumbers/service_discovery.htm +#define L2CAP_UUID 0x0100 + +/* Used for RFCOMM */ +#define RFCOMM_SABM 0x2F +#define RFCOMM_UA 0x63 +#define RFCOMM_UIH 0xEF +//#define RFCOMM_DM 0x0F +#define RFCOMM_DISC 0x43 + +#define extendAddress 0x01 // Always 1 + +// Multiplexer message types +#define BT_RFCOMM_PN_CMD 0x83 +#define BT_RFCOMM_PN_RSP 0x81 +#define BT_RFCOMM_MSC_CMD 0xE3 +#define BT_RFCOMM_MSC_RSP 0xE1 +#define BT_RFCOMM_RPN_CMD 0x93 +#define BT_RFCOMM_RPN_RSP 0x91 +/* +#define BT_RFCOMM_TEST_CMD 0x23 +#define BT_RFCOMM_TEST_RSP 0x21 +#define BT_RFCOMM_FCON_CMD 0xA3 +#define BT_RFCOMM_FCON_RSP 0xA1 +#define BT_RFCOMM_FCOFF_CMD 0x63 +#define BT_RFCOMM_FCOFF_RSP 0x61 +#define BT_RFCOMM_RLS_CMD 0x53 +#define BT_RFCOMM_RLS_RSP 0x51 +#define BT_RFCOMM_NSC_RSP 0x11 + */ + +/** + * This BluetoothService class implements the Serial Port Protocol (SPP). + * It inherits the Arduino Stream class. This allows it to use all the standard Arduino print and stream functions. + */ +class SPP : public BluetoothService, public Stream { +public: + /** + * Constructor for the SPP class. + * @param p Pointer to BTD class instance. + * @param name Set the name to BTD#btdName. If argument is omitted, then "Arduino" will be used. + * @param pin Write the pin to BTD#btdPin. If argument is omitted, then "0000" will be used. + */ + SPP(BTD *p, const char *name = "Arduino", const char *pin = "0000"); + + /** @name BluetoothService implementation */ + /** Used this to disconnect the virtual serial port. */ + void disconnect(); + /**@}*/ + + /** + * Used to provide Boolean tests for the class. + * @return Return true if SPP communication is connected. + */ + operator bool() { + return connected; + } + /** Variable used to indicate if the connection is established. */ + bool connected; + + /** @name Serial port profile (SPP) Print functions */ + /** + * Get number of bytes waiting to be read. + * @return Return the number of bytes ready to be read. + */ + int available(void); + + /** Send out all bytes in the buffer. */ + void flush(void) { + send(); + }; + /** + * Used to read the next value in the buffer without advancing to the next one. + * @return Return the byte. Will return -1 if no bytes are available. + */ + int peek(void); + /** + * Used to read the buffer. + * @return Return the byte. Will return -1 if no bytes are available. + */ + int read(void); + +#if defined(ARDUINO) && ARDUINO >=100 + /** + * Writes the byte to send to a buffer. The message is send when either send() or after Usb.Task() is called. + * @param data The byte to write. + * @return Return the number of bytes written. + */ + size_t write(uint8_t data); + /** + * Writes the bytes to send to a buffer. The message is send when either send() or after Usb.Task() is called. + * @param data The data array to send. + * @param size Size of the data. + * @return Return the number of bytes written. + */ + size_t write(const uint8_t* data, size_t size); + /** Pull in write(const char *str) from Print */ + using Print::write; +#else + /** + * Writes the byte to send to a buffer. The message is send when either send() or after Usb.Task() is called. + * @param data The byte to write. + */ + void write(uint8_t data); + /** + * Writes the bytes to send to a buffer. The message is send when either send() or after Usb.Task() is called. + * @param data The data array to send. + * @param size Size of the data. + */ + void write(const uint8_t* data, size_t size); +#endif + + /** Discard all the bytes in the buffer. */ + void discard(void); + /** + * This will send all the bytes in the buffer. + * This is called whenever Usb.Task() is called, + * but can also be called via this function. + */ + void send(void); + /**@}*/ + +protected: + /** @name BluetoothService implementation */ + /** + * Used to pass acldata to the services. + * @param ACLData Incoming acldata. + */ + void ACLData(uint8_t* ACLData); + /** Used to establish the connection automatically. */ + void Run(); + /** Use this to reset the service. */ + void Reset(); + /** + * Called when a device is successfully initialized. + * Use attachOnInit(void (*funcOnInit)(void)) to call your own function. + * This is useful for instance if you want to set the LEDs in a specific way. + */ + void onInit(); + /**@}*/ + +private: + /* Set true when a channel is created */ + bool SDPConnected; + bool RFCOMMConnected; + + /* Variables used by L2CAP state machines */ + uint8_t l2cap_sdp_state; + uint8_t l2cap_rfcomm_state; + + uint8_t l2capoutbuf[BULK_MAXPKTSIZE]; // General purpose buffer for l2cap out data + uint8_t rfcommbuf[10]; // Buffer for RFCOMM Commands + + /* L2CAP Channels */ + uint8_t sdp_scid[2]; // L2CAP source CID for SDP + uint8_t sdp_dcid[2]; // 0x0050 + uint8_t rfcomm_scid[2]; // L2CAP source CID for RFCOMM + uint8_t rfcomm_dcid[2]; // 0x0051 + + /* RFCOMM Variables */ + uint8_t rfcommChannel; + uint8_t rfcommChannelConnection; // This is the channel the SPP channel will be running at + uint8_t rfcommDirection; + uint8_t rfcommCommandResponse; + uint8_t rfcommChannelType; + uint8_t rfcommPfBit; + + uint32_t timer; + bool waitForLastCommand; + bool creditSent; + + uint8_t rfcommDataBuffer[100]; // Create a 100 sized buffer for incoming data + uint8_t sppOutputBuffer[100]; // Create a 100 sized buffer for outgoing SPP data + uint8_t sppIndex; + uint8_t rfcommAvailable; + + bool firstMessage; // Used to see if it's the first SDP request received + uint8_t bytesRead; // Counter to see when it's time to send more credit + + /* State machines */ + void SDP_task(); // SDP state machine + void RFCOMM_task(); // RFCOMM state machine + + /* SDP Commands */ + void SDP_Command(uint8_t *data, uint8_t nbytes); + void serviceNotSupported(uint8_t transactionIDHigh, uint8_t transactionIDLow); + void serialPortResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow); + void serialPortResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow); + void l2capResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow); + void l2capResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow); + + /* RFCOMM Commands */ + void RFCOMM_Command(uint8_t *data, uint8_t nbytes); + void sendRfcomm(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t *data, uint8_t length); + void sendRfcommCredit(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t credit); + uint8_t calcFcs(uint8_t *data); + bool checkFcs(uint8_t *data, uint8_t fcs); + uint8_t crc(uint8_t *data); +}; +#endif diff --git a/lib/usbhost/USB_Host_Shield_2.0/Usb.cpp b/lib/usbhost/USB_Host_Shield_2.0/Usb.cpp new file mode 100644 index 0000000000..14272588a1 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/Usb.cpp @@ -0,0 +1,812 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +/* USB functions */ + +#include "Usb.h" + +static uint8_t usb_error = 0; +static uint8_t usb_task_state; + +/* constructor */ +USB::USB() : bmHubPre(0) { + usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; //set up state machine + init(); +} + +/* Initialize data structures */ +void USB::init() { + //devConfigIndex = 0; + bmHubPre = 0; +} + +uint8_t USB::getUsbTaskState(void) { + return ( usb_task_state); +} + +void USB::setUsbTaskState(uint8_t state) { + usb_task_state = state; +} + +EpInfo* USB::getEpInfoEntry(uint8_t addr, uint8_t ep) { + UsbDevice *p = addrPool.GetUsbDevicePtr(addr); + + if(!p || !p->epinfo) + return NULL; + + EpInfo *pep = p->epinfo; + + for(uint8_t i = 0; i < p->epcount; i++) { + if((pep)->epAddr == ep) + return pep; + + pep++; + } + return NULL; +} + +/* set device table entry */ + +/* each device is different and has different number of endpoints. This function plugs endpoint record structure, defined in application, to devtable */ +uint8_t USB::setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo* eprecord_ptr) { + if(!eprecord_ptr) + return USB_ERROR_INVALID_ARGUMENT; + + UsbDevice *p = addrPool.GetUsbDevicePtr(addr); + + if(!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->address.devAddress = addr; + p->epinfo = eprecord_ptr; + p->epcount = epcount; + + return 0; +} + +uint8_t USB::SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t *nak_limit) { + UsbDevice *p = addrPool.GetUsbDevicePtr(addr); + + if(!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + if(!p->epinfo) + return USB_ERROR_EPINFO_IS_NULL; + + *ppep = getEpInfoEntry(addr, ep); + + if(!*ppep) + return USB_ERROR_EP_NOT_FOUND_IN_TBL; + + *nak_limit = (0x0001UL << (((*ppep)->bmNakPower > USB_NAK_MAX_POWER) ? USB_NAK_MAX_POWER : (*ppep)->bmNakPower)); + (*nak_limit)--; + /* + USBTRACE2("\r\nAddress: ", addr); + USBTRACE2(" EP: ", ep); + USBTRACE2(" NAK Power: ",(*ppep)->bmNakPower); + USBTRACE2(" NAK Limit: ", nak_limit); + USBTRACE("\r\n"); + */ + regWr(rPERADDR, addr); //set peripheral address + + uint8_t mode = regRd(rMODE); + + //Serial.print("\r\nMode: "); + //Serial.println( mode, HEX); + //Serial.print("\r\nLS: "); + //Serial.println(p->lowspeed, HEX); + + + + // Set bmLOWSPEED and bmHUBPRE in case of low-speed device, reset them otherwise + regWr(rMODE, (p->lowspeed) ? mode | bmLOWSPEED | bmHubPre : mode & ~(bmHUBPRE | bmLOWSPEED)); + + return 0; +} + +/* Control transfer. Sets address, endpoint, fills control packet with necessary data, dispatches control packet, and initiates bulk IN transfer, */ +/* depending on request. Actual requests are defined as inlines */ +/* return codes: */ +/* 00 = success */ + +/* 01-0f = non-zero HRSLT */ +uint8_t USB::ctrlReq(uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, + uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, USBReadParser *p) { + bool direction = false; //request direction, IN or OUT + uint8_t rcode; + SETUP_PKT setup_pkt; + + EpInfo *pep = NULL; + uint16_t nak_limit = 0; + + rcode = SetAddress(addr, ep, &pep, &nak_limit); + + if(rcode) + return rcode; + + direction = ((bmReqType & 0x80) > 0); + + /* fill in setup packet */ + setup_pkt.ReqType_u.bmRequestType = bmReqType; + setup_pkt.bRequest = bRequest; + setup_pkt.wVal_u.wValueLo = wValLo; + setup_pkt.wVal_u.wValueHi = wValHi; + setup_pkt.wIndex = wInd; + setup_pkt.wLength = total; + + bytesWr(rSUDFIFO, 8, (uint8_t*) & setup_pkt); //transfer to setup packet FIFO + + rcode = dispatchPkt(tokSETUP, ep, nak_limit); //dispatch packet + + if(rcode) //return HRSLT if not zero + return ( rcode); + + if(dataptr != NULL) //data stage, if present + { + if(direction) //IN transfer + { + uint16_t left = total; + + pep->bmRcvToggle = 1; //bmRCVTOG1; + + while(left) { + // Bytes read into buffer + uint16_t read = nbytes; + //uint16_t read = (leftbmRcvToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1; + continue; + } + + if(rcode) + return rcode; + + // Invoke callback function if inTransfer completed successfully and callback function pointer is specified + if(!rcode && p) + ((USBReadParser*)p)->Parse(read, dataptr, total - left); + + left -= read; + + if(read < nbytes) + break; + } + } else //OUT transfer + { + pep->bmSndToggle = 1; //bmSNDTOG1; + rcode = OutTransfer(pep, nak_limit, nbytes, dataptr); + } + if(rcode) //return error + return ( rcode); + } + // Status stage + return dispatchPkt((direction) ? tokOUTHS : tokINHS, ep, nak_limit); //GET if direction +} + +/* IN transfer to arbitrary endpoint. Assumes PERADDR is set. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */ +/* Keep sending INs and writes data to memory area pointed by 'data' */ + +/* rcode 0 if no errors. rcode 01-0f is relayed from dispatchPkt(). Rcode f0 means RCVDAVIRQ error, + fe USB xfer timeout */ +uint8_t USB::inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t* data) { + EpInfo *pep = NULL; + uint16_t nak_limit = 0; + + uint8_t rcode = SetAddress(addr, ep, &pep, &nak_limit); + + if(rcode) { + USBTRACE3("(USB::InTransfer) SetAddress Failed ", rcode, 0x81); + USBTRACE3("(USB::InTransfer) addr requested ", addr, 0x81); + USBTRACE3("(USB::InTransfer) ep requested ", ep, 0x81); + return rcode; + } + return InTransfer(pep, nak_limit, nbytesptr, data); +} + +uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t* data) { + uint8_t rcode = 0; + uint8_t pktsize; + + uint16_t nbytes = *nbytesptr; + //printf("Requesting %i bytes ", nbytes); + uint8_t maxpktsize = pep->maxPktSize; + + *nbytesptr = 0; + regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value + + // use a 'break' to exit this loop + while(1) { + rcode = dispatchPkt(tokIN, pep->epAddr, nak_limit); //IN packet to EP-'endpoint'. Function takes care of NAKS. + if(rcode == hrTOGERR) { + // yes, we flip it wrong here so that next time it is actually correct! + pep->bmRcvToggle = (regRd(rHRSL) & bmRCVTOGRD) ? 0 : 1; + regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value + continue; + } + if(rcode) { + //printf(">>>>>>>> Problem! dispatchPkt %2.2x\r\n", rcode); + break; //should be 0, indicating ACK. Else return error code. + } + /* check for RCVDAVIRQ and generate error if not present */ + /* the only case when absence of RCVDAVIRQ makes sense is when toggle error occurred. Need to add handling for that */ + if((regRd(rHIRQ) & bmRCVDAVIRQ) == 0) { + //printf(">>>>>>>> Problem! NO RCVDAVIRQ!\r\n"); + rcode = 0xf0; //receive error + break; + } + pktsize = regRd(rRCVBC); //number of received bytes + //printf("Got %i bytes \r\n", pktsize); + // This would be OK, but... + //assert(pktsize <= nbytes); + if(pktsize > nbytes) { + // This can happen. Use of assert on Arduino locks up the Arduino. + // So I will trim the value, and hope for the best. + //printf(">>>>>>>> Problem! Wanted %i bytes but got %i.\r\n", nbytes, pktsize); + pktsize = nbytes; + } + + int16_t mem_left = (int16_t)nbytes - *((int16_t*)nbytesptr); + + if(mem_left < 0) + mem_left = 0; + + data = bytesRd(rRCVFIFO, ((pktsize > mem_left) ? mem_left : pktsize), data); + + regWr(rHIRQ, bmRCVDAVIRQ); // Clear the IRQ & free the buffer + *nbytesptr += pktsize; // add this packet's byte count to total transfer length + + /* The transfer is complete under two conditions: */ + /* 1. The device sent a short packet (L.T. maxPacketSize) */ + /* 2. 'nbytes' have been transferred. */ + if((pktsize < maxpktsize) || (*nbytesptr >= nbytes)) // have we transferred 'nbytes' bytes? + { + // Save toggle value + pep->bmRcvToggle = ((regRd(rHRSL) & bmRCVTOGRD)) ? 1 : 0; + //printf("\r\n"); + rcode = 0; + break; + } // if + } //while( 1 ) + return ( rcode); +} + +/* OUT transfer to arbitrary endpoint. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */ +/* Handles NAK bug per Maxim Application Note 4000 for single buffer transfer */ + +/* rcode 0 if no errors. rcode 01-0f is relayed from HRSL */ +uint8_t USB::outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* data) { + EpInfo *pep = NULL; + uint16_t nak_limit = 0; + + uint8_t rcode = SetAddress(addr, ep, &pep, &nak_limit); + + if(rcode) + return rcode; + + return OutTransfer(pep, nak_limit, nbytes, data); +} + +uint8_t USB::OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8_t *data) { + uint8_t rcode = hrSUCCESS, retry_count; + uint8_t *data_p = data; //local copy of the data pointer + uint16_t bytes_tosend, nak_count; + uint16_t bytes_left = nbytes; + + uint8_t maxpktsize = pep->maxPktSize; + + if(maxpktsize < 1 || maxpktsize > 64) + return USB_ERROR_INVALID_MAX_PKT_SIZE; + + unsigned long timeout = millis() + USB_XFER_TIMEOUT; + + regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value + + while(bytes_left) { + retry_count = 0; + nak_count = 0; + bytes_tosend = (bytes_left >= maxpktsize) ? maxpktsize : bytes_left; + bytesWr(rSNDFIFO, bytes_tosend, data_p); //filling output FIFO + regWr(rSNDBC, bytes_tosend); //set number of bytes + regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet + while(!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ + regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ + rcode = (regRd(rHRSL) & 0x0f); + + while(rcode && ((long)(millis() - timeout) < 0L)) { + switch(rcode) { + case hrNAK: + nak_count++; + if(nak_limit && (nak_count == nak_limit)) + goto breakout; + //return ( rcode); + break; + case hrTIMEOUT: + retry_count++; + if(retry_count == USB_RETRY_LIMIT) + goto breakout; + //return ( rcode); + break; + case hrTOGERR: + // yes, we flip it wrong here so that next time it is actually correct! + pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1; + regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value + break; + default: + goto breakout; + }//switch( rcode + + /* process NAK according to Host out NAK bug */ + regWr(rSNDBC, 0); + regWr(rSNDFIFO, *data_p); + regWr(rSNDBC, bytes_tosend); + regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet + while(!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ + regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ + rcode = (regRd(rHRSL) & 0x0f); + }//while( rcode && .... + bytes_left -= bytes_tosend; + data_p += bytes_tosend; + }//while( bytes_left... +breakout: + + pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 1 : 0; //bmSNDTOG1 : bmSNDTOG0; //update toggle + return ( rcode); //should be 0 in all cases +} +/* dispatch USB packet. Assumes peripheral address is set and relevant buffer is loaded/empty */ +/* If NAK, tries to re-send up to nak_limit times */ +/* If nak_limit == 0, do not count NAKs, exit after timeout */ +/* If bus timeout, re-sends up to USB_RETRY_LIMIT times */ + +/* return codes 0x00-0x0f are HRSLT( 0x00 being success ), 0xff means timeout */ +uint8_t USB::dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit) { + unsigned long timeout = millis() + USB_XFER_TIMEOUT; + uint8_t tmpdata; + uint8_t rcode = hrSUCCESS; + uint8_t retry_count = 0; + uint16_t nak_count = 0; + + while((long)(millis() - timeout) < 0L) { + regWr(rHXFR, (token | ep)); //launch the transfer + rcode = USB_ERROR_TRANSFER_TIMEOUT; + + while((long)(millis() - timeout) < 0L) //wait for transfer completion + { + tmpdata = regRd(rHIRQ); + + if(tmpdata & bmHXFRDNIRQ) { + regWr(rHIRQ, bmHXFRDNIRQ); //clear the interrupt + rcode = 0x00; + break; + }//if( tmpdata & bmHXFRDNIRQ + + }//while ( millis() < timeout + + //if (rcode != 0x00) //exit if timeout + // return ( rcode); + + rcode = (regRd(rHRSL) & 0x0f); //analyze transfer result + + switch(rcode) { + case hrNAK: + nak_count++; + if(nak_limit && (nak_count == nak_limit)) + return (rcode); + break; + case hrTIMEOUT: + retry_count++; + if(retry_count == USB_RETRY_LIMIT) + return (rcode); + break; + default: + return (rcode); + }//switch( rcode + + }//while( timeout > millis() + return ( rcode); +} + +/* USB main task. Performs enumeration/cleanup */ +void USB::Task(void) //USB state machine +{ + uint8_t rcode; + uint8_t tmpdata; + static unsigned long delay = 0; + //USB_DEVICE_DESCRIPTOR buf; + bool lowspeed = false; + + MAX3421E::Task(); + + tmpdata = getVbusState(); + + /* modify USB task state if Vbus changed */ + switch(tmpdata) { + case SE1: //illegal state + usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL; + lowspeed = false; + break; + case SE0: //disconnected + if((usb_task_state & USB_STATE_MASK) != USB_STATE_DETACHED) + usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; + lowspeed = false; + break; + case LSHOST: + + lowspeed = true; + //intentional fallthrough + case FSHOST: //attached + if((usb_task_state & USB_STATE_MASK) == USB_STATE_DETACHED) { + delay = millis() + USB_SETTLE_DELAY; + usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE; + } + break; + }// switch( tmpdata + + for(uint8_t i = 0; i < USB_NUMDEVICES; i++) + if(devConfig[i]) + rcode = devConfig[i]->Poll(); + + switch(usb_task_state) { + case USB_DETACHED_SUBSTATE_INITIALIZE: + init(); + + for(uint8_t i = 0; i < USB_NUMDEVICES; i++) + if(devConfig[i]) + rcode = devConfig[i]->Release(); + + usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE; + break; + case USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE: //just sit here + break; + case USB_DETACHED_SUBSTATE_ILLEGAL: //just sit here + break; + case USB_ATTACHED_SUBSTATE_SETTLE: //settle time for just attached device + if((long)(millis() - delay) >= 0L) + usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE; + else break; // don't fall through + case USB_ATTACHED_SUBSTATE_RESET_DEVICE: + regWr(rHCTL, bmBUSRST); //issue bus reset + usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE; + break; + case USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE: + if((regRd(rHCTL) & bmBUSRST) == 0) { + tmpdata = regRd(rMODE) | bmSOFKAENAB; //start SOF generation + regWr(rMODE, tmpdata); + usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF; + //delay = millis() + 20; //20ms wait after reset per USB spec + } + break; + case USB_ATTACHED_SUBSTATE_WAIT_SOF: //todo: change check order + if(regRd(rHIRQ) & bmFRAMEIRQ) { + //when first SOF received _and_ 20ms has passed we can continue + /* + if (delay < millis()) //20ms passed + usb_task_state = USB_STATE_CONFIGURING; + */ + usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET; + delay = millis() + 20; + } + break; + case USB_ATTACHED_SUBSTATE_WAIT_RESET: + if((long)(millis() - delay) >= 0L) usb_task_state = USB_STATE_CONFIGURING; + else break; // don't fall through + case USB_STATE_CONFIGURING: + + //Serial.print("\r\nConf.LS: "); + //Serial.println(lowspeed, HEX); + + rcode = Configuring(0, 0, lowspeed); + + if(rcode) { + if(rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE) { + usb_error = rcode; + usb_task_state = USB_STATE_ERROR; + } + } else + usb_task_state = USB_STATE_RUNNING; + break; + case USB_STATE_RUNNING: + break; + case USB_STATE_ERROR: + //MAX3421E::Init(); + break; + } // switch( usb_task_state ) +} + +uint8_t USB::DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed) { + //uint8_t buf[12]; + uint8_t rcode; + UsbDevice *p0 = NULL, *p = NULL; + + // Get pointer to pseudo device with address 0 assigned + p0 = addrPool.GetUsbDevicePtr(0); + + if(!p0) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + if(!p0->epinfo) + return USB_ERROR_EPINFO_IS_NULL; + + p0->lowspeed = (lowspeed) ? true : false; + + // Allocate new address according to device class + uint8_t bAddress = addrPool.AllocAddress(parent, false, port); + + if(!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + p = addrPool.GetUsbDevicePtr(bAddress); + + if(!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->lowspeed = lowspeed; + + // Assign new address to the device + rcode = setAddr(0, 0, bAddress); + + if(rcode) { + addrPool.FreeAddress(bAddress); + bAddress = 0; + return rcode; + } + return 0; +}; + +uint8_t USB::AttemptConfig(uint8_t driver, uint8_t parent, uint8_t port, bool lowspeed) { + //printf("AttemptConfig: parent = %i, port = %i\r\n", parent, port); + uint8_t retries = 0; + +again: + uint8_t rcode = devConfig[driver]->ConfigureDevice(parent, port, lowspeed); + if(rcode == USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET) { + if(parent == 0) { + // Send a bus reset on the root interface. + regWr(rHCTL, bmBUSRST); //issue bus reset + delay(102); // delay 102ms, compensate for clock inaccuracy. + } else { + // reset parent port + devConfig[parent]->ResetHubPort(port); + } + } else if(rcode == hrJERR && retries < 3) { // Some devices returns this when plugged in - trying to initialize the device again usually works + delay(100); + retries++; + goto again; + } else if(rcode) + return rcode; + + rcode = devConfig[driver]->Init(parent, port, lowspeed); + if(rcode == hrJERR && retries < 3) { // Some devices returns this when plugged in - trying to initialize the device again usually works + delay(100); + retries++; + goto again; + } + if(rcode) { + // Issue a bus reset, because the device may be in a limbo state + if(parent == 0) { + // Send a bus reset on the root interface. + regWr(rHCTL, bmBUSRST); //issue bus reset + delay(102); // delay 102ms, compensate for clock inaccuracy. + } else { + // reset parent port + devConfig[parent]->ResetHubPort(port); + } + } + return rcode; +} + +/* + * This is broken. We need to enumerate differently. + * It causes major problems with several devices if detected in an unexpected order. + * + * + * Oleg - I wouldn't do anything before the newly connected device is considered sane. + * i.e.(delays are not indicated for brevity): + * 1. reset + * 2. GetDevDescr(); + * 3a. If ACK, continue with allocating address, addressing, etc. + * 3b. Else reset again, count resets, stop at some number (5?). + * 4. When max.number of resets is reached, toggle power/fail + * If desired, this could be modified by performing two resets with GetDevDescr() in the middle - however, from my experience, if a device answers to GDD() + * it doesn't need to be reset again + * New steps proposal: + * 1: get address pool instance. exit on fail + * 2: pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf). exit on fail. + * 3: bus reset, 100ms delay + * 4: set address + * 5: pUsb->setEpInfoEntry(bAddress, 1, epInfo), exit on fail + * 6: while (configurations) { + * for(each configuration) { + * for (each driver) { + * 6a: Ask device if it likes configuration. Returns 0 on OK. + * If successful, the driver configured device. + * The driver now owns the endpoints, and takes over managing them. + * The following will need codes: + * Everything went well, instance consumed, exit with success. + * Instance already in use, ignore it, try next driver. + * Not a supported device, ignore it, try next driver. + * Not a supported configuration for this device, ignore it, try next driver. + * Could not configure device, fatal, exit with fail. + * } + * } + * } + * 7: for(each driver) { + * 7a: Ask device if it knows this VID/PID. Acts exactly like 6a, but using VID/PID + * 8: if we get here, no driver likes the device plugged in, so exit failure. + * + */ +uint8_t USB::Configuring(uint8_t parent, uint8_t port, bool lowspeed) { + //uint8_t bAddress = 0; + //printf("Configuring: parent = %i, port = %i\r\n", parent, port); + uint8_t devConfigIndex; + uint8_t rcode = 0; + uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)]; + USB_DEVICE_DESCRIPTOR *udd = reinterpret_cast(buf); + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + EpInfo epInfo; + + epInfo.epAddr = 0; + epInfo.maxPktSize = 8; + epInfo.epAttribs = 0; + epInfo.bmNakPower = USB_NAK_MAX_POWER; + + //delay(2000); + AddressPool &addrPool = GetAddressPool(); + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); + if(!p) { + //printf("Configuring error: USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL\r\n"); + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + } + + // Save old pointer to EP_RECORD of address 0 + oldep_ptr = p->epinfo; + + // Temporary assign new pointer to epInfo to p->epinfo in order to + // avoid toggle inconsistence + + p->epinfo = &epInfo; + + p->lowspeed = lowspeed; + // Get device descriptor + rcode = getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); + + // Restore p->epinfo + p->epinfo = oldep_ptr; + + if(rcode) { + //printf("Configuring error: Can't get USB_DEVICE_DESCRIPTOR\r\n"); + return rcode; + } + + // to-do? + // Allocate new address according to device class + //bAddress = addrPool.AllocAddress(parent, false, port); + + uint16_t vid = udd->idVendor; + uint16_t pid = udd->idProduct; + uint8_t klass = udd->bDeviceClass; + uint8_t subklass = udd->bDeviceSubClass; + // Attempt to configure if VID/PID or device class matches with a driver + // Qualify with subclass too. + // + // VID/PID & class tests default to false for drivers not yet ported + // subclass defaults to true, so you don't have to define it if you don't have to. + // + for(devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) { + if(!devConfig[devConfigIndex]) continue; // no driver + if(devConfig[devConfigIndex]->GetAddress()) continue; // consumed + if(devConfig[devConfigIndex]->DEVSUBCLASSOK(subklass) && (devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass))) { + rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed); + if(rcode != USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED) + break; + } + } + + if(devConfigIndex < USB_NUMDEVICES) { + return rcode; + } + + + // blindly attempt to configure + for(devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) { + if(!devConfig[devConfigIndex]) continue; + if(devConfig[devConfigIndex]->GetAddress()) continue; // consumed + if(devConfig[devConfigIndex]->DEVSUBCLASSOK(subklass) && (devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass))) continue; // If this is true it means it must have returned USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED above + rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed); + + //printf("ERROR ENUMERATING %2.2x\r\n", rcode); + if(!(rcode == USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED || rcode == USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE)) { + // in case of an error dev_index should be reset to 0 + // in order to start from the very beginning the + // next time the program gets here + //if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE) + // devConfigIndex = 0; + return rcode; + } + } + // if we get here that means that the device class is not supported by any of registered classes + rcode = DefaultAddressing(parent, port, lowspeed); + + return rcode; +} + +uint8_t USB::ReleaseDevice(uint8_t addr) { + if(!addr) + return 0; + + for(uint8_t i = 0; i < USB_NUMDEVICES; i++) { + if(!devConfig[i]) continue; + if(devConfig[i]->GetAddress() == addr) + return devConfig[i]->Release(); + } + return 0; +} + +#if 1 //!defined(USB_METHODS_INLINE) +//get device descriptor + +uint8_t USB::getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr) { + return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, nbytes, dataptr, NULL)); +} +//get configuration descriptor + +uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr) { + return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, nbytes, dataptr, NULL)); +} + +/* Requests Configuration Descriptor. Sends two Get Conf Descr requests. The first one gets the total length of all descriptors, then the second one requests this + total length. The length of the first request can be shorter ( 4 bytes ), however, there are devices which won't work unless this length is set to 9 */ +uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser *p) { + const uint8_t bufSize = 64; + uint8_t buf[bufSize]; + USB_CONFIGURATION_DESCRIPTOR *ucd = reinterpret_cast(buf); + + uint8_t ret = getConfDescr(addr, ep, 9, conf, buf); + + if(ret) + return ret; + + uint16_t total = ucd->wTotalLength; + + //USBTRACE2("\r\ntotal conf.size:", total); + + return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, total, bufSize, buf, p)); +} + +//get string descriptor + +uint8_t USB::getStrDescr(uint8_t addr, uint8_t ep, uint16_t ns, uint8_t index, uint16_t langid, uint8_t* dataptr) { + return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, ns, ns, dataptr, NULL)); +} +//set address + +uint8_t USB::setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr) { + uint8_t rcode = ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL); + //delay(2); //per USB 2.0 sect.9.2.6.3 + delay(300); // Older spec says you should wait at least 200ms + return rcode; + //return ( ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL)); +} +//set configuration + +uint8_t USB::setConf(uint8_t addr, uint8_t ep, uint8_t conf_value) { + return ( ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL)); +} + +#endif // defined(USB_METHODS_INLINE) diff --git a/lib/usbhost/USB_Host_Shield_2.0/Usb.h b/lib/usbhost/USB_Host_Shield_2.0/Usb.h new file mode 100644 index 0000000000..47bd626cce --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/Usb.h @@ -0,0 +1,41 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +/* USB functions */ +#ifndef _usb_h_ +#define _usb_h_ + +// WARNING: Do not change the order of includes, or stuff will break! +#include +#include +#include + +// None of these should ever be included by a driver, or a user's sketch. +#include "settings.h" +#include "printhex.h" +#include "message.h" +#include "hexdump.h" +#include "sink_parser.h" +#include "max3421e.h" +#include "address.h" +#include "avrpins.h" +#include "usb_ch9.h" +#include "usbhost.h" +#include "UsbCore.h" +#include "parsetools.h" +#include "confdescparser.h" + +#endif //_usb_h_ diff --git a/lib/usbhost/USB_Host_Shield_2.0/UsbCore.h b/lib/usbhost/USB_Host_Shield_2.0/UsbCore.h new file mode 100644 index 0000000000..5c6c771017 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/UsbCore.h @@ -0,0 +1,298 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ + +#if !defined(_usb_h_) || defined(USBCORE_H) +#error "Never include UsbCore.h directly; include Usb.h instead" +#else +#define USBCORE_H + +// Not used anymore? If anyone uses this, please let us know so that this may be +// moved to the proper place, settings.h. +//#define USB_METHODS_INLINE + +/* shield pins. First parameter - SS pin, second parameter - INT pin */ +#ifdef BOARD_BLACK_WIDDOW +typedef MAX3421e MAX3421E; // Black Widow +#elif defined(CORE_TEENSY) && (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)) +#if EXT_RAM +typedef MAX3421e MAX3421E; // Teensy++ 2.0 with XMEM2 +#else +typedef MAX3421e MAX3421E; // Teensy++ 1.0 and 2.0 +#endif +#elif defined(BOARD_MEGA_ADK) +typedef MAX3421e MAX3421E; // Arduino Mega ADK +#elif defined(ARDUINO_AVR_BALANDUINO) +typedef MAX3421e MAX3421E; // Balanduino +#elif defined(__ARDUINO_X86__) && PLATFORM_ID == 0x06 +typedef MAX3421e MAX3421E; // The Intel Galileo supports much faster read and write speed at pin 2 and 3 +#else +typedef MAX3421e MAX3421E; // Official Arduinos (UNO, Duemilanove, Mega, 2560, Leonardo, Due etc.), Intel Edison, Intel Galileo 2 or Teensy 2.0 and 3.0 +#endif + +/* Common setup data constant combinations */ +#define bmREQ_GET_DESCR USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE //get descriptor request type +#define bmREQ_SET USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE //set request type for all but 'set feature' and 'set interface' +#define bmREQ_CL_GET_INTF USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE //get interface request type + +// D7 data transfer direction (0 - host-to-device, 1 - device-to-host) +// D6-5 Type (0- standard, 1 - class, 2 - vendor, 3 - reserved) +// D4-0 Recipient (0 - device, 1 - interface, 2 - endpoint, 3 - other, 4..31 - reserved) + +// USB Device Classes +#define USB_CLASS_USE_CLASS_INFO 0x00 // Use Class Info in the Interface Descriptors +#define USB_CLASS_AUDIO 0x01 // Audio +#define USB_CLASS_COM_AND_CDC_CTRL 0x02 // Communications and CDC Control +#define USB_CLASS_HID 0x03 // HID +#define USB_CLASS_PHYSICAL 0x05 // Physical +#define USB_CLASS_IMAGE 0x06 // Image +#define USB_CLASS_PRINTER 0x07 // Printer +#define USB_CLASS_MASS_STORAGE 0x08 // Mass Storage +#define USB_CLASS_HUB 0x09 // Hub +#define USB_CLASS_CDC_DATA 0x0a // CDC-Data +#define USB_CLASS_SMART_CARD 0x0b // Smart-Card +#define USB_CLASS_CONTENT_SECURITY 0x0d // Content Security +#define USB_CLASS_VIDEO 0x0e // Video +#define USB_CLASS_PERSONAL_HEALTH 0x0f // Personal Healthcare +#define USB_CLASS_DIAGNOSTIC_DEVICE 0xdc // Diagnostic Device +#define USB_CLASS_WIRELESS_CTRL 0xe0 // Wireless Controller +#define USB_CLASS_MISC 0xef // Miscellaneous +#define USB_CLASS_APP_SPECIFIC 0xfe // Application Specific +#define USB_CLASS_VENDOR_SPECIFIC 0xff // Vendor Specific + +// Additional Error Codes +#define USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED 0xD1 +#define USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE 0xD2 +#define USB_ERROR_UNABLE_TO_REGISTER_DEVICE_CLASS 0xD3 +#define USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL 0xD4 +#define USB_ERROR_HUB_ADDRESS_OVERFLOW 0xD5 +#define USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL 0xD6 +#define USB_ERROR_EPINFO_IS_NULL 0xD7 +#define USB_ERROR_INVALID_ARGUMENT 0xD8 +#define USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE 0xD9 +#define USB_ERROR_INVALID_MAX_PKT_SIZE 0xDA +#define USB_ERROR_EP_NOT_FOUND_IN_TBL 0xDB +#define USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET 0xE0 +#define USB_ERROR_FailGetDevDescr 0xE1 +#define USB_ERROR_FailSetDevTblEntry 0xE2 +#define USB_ERROR_FailGetConfDescr 0xE3 +#define USB_ERROR_TRANSFER_TIMEOUT 0xFF + +#define USB_XFER_TIMEOUT 5000 // (5000) USB transfer timeout in milliseconds, per section 9.2.6.1 of USB 2.0 spec +//#define USB_NAK_LIMIT 32000 // NAK limit for a transfer. 0 means NAKs are not counted +#define USB_RETRY_LIMIT 3 // 3 retry limit for a transfer +#define USB_SETTLE_DELAY 200 // settle delay in milliseconds + +#define USB_NUMDEVICES 16 //number of USB devices +//#define HUB_MAX_HUBS 7 // maximum number of hubs that can be attached to the host controller +#define HUB_PORT_RESET_DELAY 20 // hub port reset delay 10 ms recomended, can be up to 20 ms + +/* USB state machine states */ +#define USB_STATE_MASK 0xf0 + +#define USB_STATE_DETACHED 0x10 +#define USB_DETACHED_SUBSTATE_INITIALIZE 0x11 +#define USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE 0x12 +#define USB_DETACHED_SUBSTATE_ILLEGAL 0x13 +#define USB_ATTACHED_SUBSTATE_SETTLE 0x20 +#define USB_ATTACHED_SUBSTATE_RESET_DEVICE 0x30 +#define USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE 0x40 +#define USB_ATTACHED_SUBSTATE_WAIT_SOF 0x50 +#define USB_ATTACHED_SUBSTATE_WAIT_RESET 0x51 +#define USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE 0x60 +#define USB_STATE_ADDRESSING 0x70 +#define USB_STATE_CONFIGURING 0x80 +#define USB_STATE_RUNNING 0x90 +#define USB_STATE_ERROR 0xa0 + +class USBDeviceConfig { +public: + + virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed) { + return 0; + } + + virtual uint8_t ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) { + return 0; + } + + virtual uint8_t Release() { + return 0; + } + + virtual uint8_t Poll() { + return 0; + } + + virtual uint8_t GetAddress() { + return 0; + } + + virtual void ResetHubPort(uint8_t port) { + return; + } // Note used for hubs only! + + virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) { + return false; + } + + virtual bool DEVCLASSOK(uint8_t klass) { + return false; + } + + virtual bool DEVSUBCLASSOK(uint8_t subklass) { + return true; + } + +}; + +/* USB Setup Packet Structure */ +typedef struct { + + union { // offset description + uint8_t bmRequestType; // 0 Bit-map of request type + + struct { + uint8_t recipient : 5; // Recipient of the request + uint8_t type : 2; // Type of request + uint8_t direction : 1; // Direction of data X-fer + } __attribute__((packed)); + } ReqType_u; + uint8_t bRequest; // 1 Request + + union { + uint16_t wValue; // 2 Depends on bRequest + + struct { + uint8_t wValueLo; + uint8_t wValueHi; + } __attribute__((packed)); + } wVal_u; + uint16_t wIndex; // 4 Depends on bRequest + uint16_t wLength; // 6 Depends on bRequest +} __attribute__((packed)) SETUP_PKT, *PSETUP_PKT; + + + +// Base class for incoming data parser + +class USBReadParser { +public: + virtual void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset) = 0; +}; + +class USB : public MAX3421E { + AddressPoolImpl addrPool; + USBDeviceConfig* devConfig[USB_NUMDEVICES]; + uint8_t bmHubPre; + +public: + USB(void); + + void SetHubPreMask() { + bmHubPre |= bmHUBPRE; + }; + + void ResetHubPreMask() { + bmHubPre &= (~bmHUBPRE); + }; + + AddressPool& GetAddressPool() { + return (AddressPool&)addrPool; + }; + + uint8_t RegisterDeviceClass(USBDeviceConfig *pdev) { + for(uint8_t i = 0; i < USB_NUMDEVICES; i++) { + if(!devConfig[i]) { + devConfig[i] = pdev; + return 0; + } + } + return USB_ERROR_UNABLE_TO_REGISTER_DEVICE_CLASS; + }; + + void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) { + addrPool.ForEachUsbDevice(pfunc); + }; + uint8_t getUsbTaskState(void); + void setUsbTaskState(uint8_t state); + + EpInfo* getEpInfoEntry(uint8_t addr, uint8_t ep); + uint8_t setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo* eprecord_ptr); + + /* Control requests */ + uint8_t getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr); + uint8_t getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr); + + uint8_t getConfDescr(uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser *p); + + uint8_t getStrDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t index, uint16_t langid, uint8_t* dataptr); + uint8_t setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr); + uint8_t setConf(uint8_t addr, uint8_t ep, uint8_t conf_value); + /**/ + uint8_t ctrlData(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr, bool direction); + uint8_t ctrlStatus(uint8_t ep, bool direction, uint16_t nak_limit); + uint8_t inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t* data); + uint8_t outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* data); + uint8_t dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit); + + void Task(void); + + uint8_t DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed); + uint8_t Configuring(uint8_t parent, uint8_t port, bool lowspeed); + uint8_t ReleaseDevice(uint8_t addr); + + uint8_t ctrlReq(uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, + uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, USBReadParser *p); + +private: + void init(); + uint8_t SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t *nak_limit); + uint8_t OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8_t *data); + uint8_t InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t *data); + uint8_t AttemptConfig(uint8_t driver, uint8_t parent, uint8_t port, bool lowspeed); +}; + +#if 0 //defined(USB_METHODS_INLINE) +//get device descriptor + +inline uint8_t USB::getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr) { + return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, dataptr)); +} +//get configuration descriptor + +inline uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr) { + return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, dataptr)); +} +//get string descriptor + +inline uint8_t USB::getStrDescr(uint8_t addr, uint8_t ep, uint16_t nuint8_ts, uint8_t index, uint16_t langid, uint8_t* dataptr) { + return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, nuint8_ts, dataptr)); +} +//set address + +inline uint8_t USB::setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr) { + return ( ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, NULL)); +} +//set configuration + +inline uint8_t USB::setConf(uint8_t addr, uint8_t ep, uint8_t conf_value) { + return ( ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, NULL)); +} + +#endif // defined(USB_METHODS_INLINE) + +#endif /* USBCORE_H */ diff --git a/lib/usbhost/USB_Host_Shield_2.0/Wii.cpp b/lib/usbhost/USB_Host_Shield_2.0/Wii.cpp new file mode 100644 index 0000000000..4bbf4c91cb --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/Wii.cpp @@ -0,0 +1,1268 @@ +/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. + + This software may be distributed and modified under the terms of the GNU + General Public License version 2 (GPL2) as published by the Free Software + Foundation and appearing in the file GPL2.TXT included in the packaging of + this file. Please note that GPL2 Section 2[b] requires that all works based + on this software must also be made publicly available under the terms of + the GPL2 ("Copyleft"). + + Contact information + ------------------- + + Kristian Lauszus, TKJ Electronics + Web : http://www.tkjelectronics.com + e-mail : kristianl@tkjelectronics.com + + IR camera support added by Allan Glover (adglover9.81@gmail.com) and Kristian Lauszus + */ + +#include "Wii.h" +// To enable serial debugging see "settings.h" +//#define EXTRADEBUG // Uncomment to get even more debugging data +//#define PRINTREPORT // Uncomment to print the report send by the Wii controllers + +const uint8_t WII_LEDS[] PROGMEM = { + 0x00, // OFF + 0x10, // LED1 + 0x20, // LED2 + 0x40, // LED3 + 0x80, // LED4 + + 0x90, // LED5 + 0xA0, // LED6 + 0xC0, // LED7 + 0xD0, // LED8 + 0xE0, // LED9 + 0xF0, // LED10 +}; + +const uint32_t WII_BUTTONS[] PROGMEM = { + 0x00008, // UP + 0x00002, // RIGHT + 0x00004, // DOWN + 0x00001, // LEFT + + 0, // Skip + 0x00010, // PLUS + 0x00100, // TWO + 0x00200, // ONE + + 0x01000, // MINUS + 0x08000, // HOME + 0x10000, // Z + 0x20000, // C + + 0x00400, // B + 0x00800, // A +}; +const uint32_t WII_PROCONTROLLER_BUTTONS[] PROGMEM = { + 0x00100, // UP + 0x00080, // RIGHT + 0x00040, // DOWN + 0x00200, // LEFT + + 0, // Skip + 0x00004, // PLUS + 0x20000, // L3 + 0x10000, // R3 + + 0x00010, // MINUS + 0x00008, // HOME + 0, 0, // Skip + + 0x04000, // B + 0x01000, // A + 0x00800, // X + 0x02000, // Y + + 0x00020, // L + 0x00002, // R + 0x08000, // ZL + 0x00400, // ZR +}; + +WII::WII(BTD *p, bool pair) : +BluetoothService(p) // Pointer to USB class instance - mandatory +{ + pBtd->pairWithWii = pair; + + HIDBuffer[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) + + /* Set device cid for the control and intterrupt channelse - LSB */ + control_dcid[0] = 0x60; // 0x0060 + control_dcid[1] = 0x00; + interrupt_dcid[0] = 0x61; // 0x0061 + interrupt_dcid[1] = 0x00; + + Reset(); +} + +void WII::Reset() { + wiimoteConnected = false; + nunchuckConnected = false; + motionPlusConnected = false; + activateNunchuck = false; + motionValuesReset = false; + activeConnection = false; + motionPlusInside = false; + pBtd->wiiUProController = false; + wiiUProControllerConnected = false; + wiiBalanceBoardConnected = false; + l2cap_event_flag = 0; // Reset flags + l2cap_state = L2CAP_WAIT; +} + +void WII::disconnect() { // Use this void to disconnect any of the controllers + if(!motionPlusInside) { // The old Wiimote needs a delay after the first command or it will automatically reconnect + if(motionPlusConnected) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nDeactivating Motion Plus"), 0x80); +#endif + initExtension1(); // This will disable the Motion Plus extension + } + timer = millis() + 1000; // We have to wait for the message before the rest of the channels can be deactivated + } else + timer = millis(); // Don't wait + // First the HID interrupt channel has to be disconnected, then the HID control channel and finally the HCI connection + pBtd->l2cap_disconnection_request(hci_handle, ++identifier, interrupt_scid, interrupt_dcid); + Reset(); + l2cap_state = L2CAP_INTERRUPT_DISCONNECT; +} + +void WII::ACLData(uint8_t* l2capinbuf) { + if(!pBtd->l2capConnectionClaimed && pBtd->incomingWii && !wiimoteConnected && !activeConnection) { + if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { + if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) { + motionPlusInside = pBtd->motionPlusInside; + pBtd->incomingWii = false; + pBtd->l2capConnectionClaimed = true; // Claim that the incoming connection belongs to this service + activeConnection = true; + hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection + l2cap_state = L2CAP_WAIT; + } + } + } + + if(checkHciHandle(l2capinbuf, hci_handle)) { // acl_handle_ok + if((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001U) { // l2cap_control - Channel ID for ACL-U + if(l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80); + D_PrintHex (l2capinbuf[13], 0x80); + Notify(PSTR(" "), 0x80); + D_PrintHex (l2capinbuf[12], 0x80); + Notify(PSTR(" "), 0x80); + D_PrintHex (l2capinbuf[17], 0x80); + Notify(PSTR(" "), 0x80); + D_PrintHex (l2capinbuf[16], 0x80); + Notify(PSTR(" "), 0x80); + D_PrintHex (l2capinbuf[15], 0x80); + Notify(PSTR(" "), 0x80); + D_PrintHex (l2capinbuf[14], 0x80); +#endif + } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_RESPONSE) { + if(((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) && ((l2capinbuf[18] | (l2capinbuf[19] << 8)) == SUCCESSFUL)) { // Success + if(l2capinbuf[14] == control_dcid[0] && l2capinbuf[15] == control_dcid[1]) { + //Notify(PSTR("\r\nHID Control Connection Complete"), 0x80); + identifier = l2capinbuf[9]; + control_scid[0] = l2capinbuf[12]; + control_scid[1] = l2capinbuf[13]; + l2cap_set_flag(L2CAP_FLAG_CONTROL_CONNECTED); + } else if(l2capinbuf[14] == interrupt_dcid[0] && l2capinbuf[15] == interrupt_dcid[1]) { + //Notify(PSTR("\r\nHID Interrupt Connection Complete"), 0x80); + identifier = l2capinbuf[9]; + interrupt_scid[0] = l2capinbuf[12]; + interrupt_scid[1] = l2capinbuf[13]; + l2cap_set_flag(L2CAP_FLAG_INTERRUPT_CONNECTED); + } + } + } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { +#ifdef EXTRADEBUG + Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80); + D_PrintHex (l2capinbuf[13], 0x80); + Notify(PSTR(" "), 0x80); + D_PrintHex (l2capinbuf[12], 0x80); + Notify(PSTR(" SCID: "), 0x80); + D_PrintHex (l2capinbuf[15], 0x80); + Notify(PSTR(" "), 0x80); + D_PrintHex (l2capinbuf[14], 0x80); + Notify(PSTR(" Identifier: "), 0x80); + D_PrintHex (l2capinbuf[9], 0x80); +#endif + if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) { + identifier = l2capinbuf[9]; + control_scid[0] = l2capinbuf[14]; + control_scid[1] = l2capinbuf[15]; + l2cap_set_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST); + } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_INTR_PSM) { + identifier = l2capinbuf[9]; + interrupt_scid[0] = l2capinbuf[14]; + interrupt_scid[1] = l2capinbuf[15]; + l2cap_set_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST); + } + } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) { + if((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success + if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { + //Notify(PSTR("\r\nHID Control Configuration Complete"), 0x80); + identifier = l2capinbuf[9]; + l2cap_set_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS); + } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { + //Notify(PSTR("\r\nHID Interrupt Configuration Complete"), 0x80); + identifier = l2capinbuf[9]; + l2cap_set_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS); + } + } + } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) { + if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { + //Notify(PSTR("\r\nHID Control Configuration Request"), 0x80); + pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], control_scid); + } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { + //Notify(PSTR("\r\nHID Interrupt Configuration Request"), 0x80); + pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], interrupt_scid); + } + } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) { + if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nDisconnect Request: Control Channel"), 0x80); +#endif + identifier = l2capinbuf[9]; + pBtd->l2cap_disconnection_response(hci_handle, identifier, control_dcid, control_scid); + Reset(); + } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nDisconnect Request: Interrupt Channel"), 0x80); +#endif + identifier = l2capinbuf[9]; + pBtd->l2cap_disconnection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid); + Reset(); + } + } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) { + if(l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) { + //Notify(PSTR("\r\nDisconnect Response: Control Channel"), 0x80); + identifier = l2capinbuf[9]; + l2cap_set_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE); + } else if(l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) { + //Notify(PSTR("\r\nDisconnect Response: Interrupt Channel"), 0x80); + identifier = l2capinbuf[9]; + l2cap_set_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE); + } + } +#ifdef EXTRADEBUG + else { + identifier = l2capinbuf[9]; + Notify(PSTR("\r\nL2CAP Unknown Signaling Command: "), 0x80); + D_PrintHex (l2capinbuf[8], 0x80); + } +#endif + } else if(l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt + //Notify(PSTR("\r\nL2CAP Interrupt"), 0x80); + if(l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT + if((l2capinbuf[9] >= 0x20 && l2capinbuf[9] <= 0x22) || (l2capinbuf[9] >= 0x30 && l2capinbuf[9] <= 0x37) || l2capinbuf[9] == 0x3e || l2capinbuf[9] == 0x3f) { // These reports include the buttons + if((l2capinbuf[9] >= 0x20 && l2capinbuf[9] <= 0x22) || l2capinbuf[9] == 0x31 || l2capinbuf[9] == 0x33) // These reports have no extensions bytes + ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8)); + else if(wiiUProControllerConnected) + ButtonState = (uint32_t)(((~l2capinbuf[23]) & 0xFE) | ((uint16_t)(~l2capinbuf[24]) << 8) | ((uint32_t)((~l2capinbuf[25]) & 0x03) << 16)); + else if(motionPlusConnected) { + if(l2capinbuf[20] & 0x02) // Only update the Wiimote buttons, since the extension bytes are from the Motion Plus + ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8) | ((uint32_t)(ButtonState & 0xFFFF0000))); + else if(nunchuckConnected) // Update if it's a report from the Nunchuck + ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8) | ((uint32_t)((~l2capinbuf[20]) & 0x0C) << 14)); + //else if(classicControllerConnected) // Update if it's a report from the Classic Controller + } else if(nunchuckConnected) // The Nunchuck is directly connected + ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8) | ((uint32_t)((~l2capinbuf[20]) & 0x03) << 16)); + //else if(classicControllerConnected) // The Classic Controller is directly connected + else if(!unknownExtensionConnected) + ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8)); +#ifdef PRINTREPORT + Notify(PSTR("ButtonState: "), 0x80); + D_PrintHex (ButtonState, 0x80); + Notify(PSTR("\r\n"), 0x80); +#endif + if(ButtonState != OldButtonState) { + ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable + OldButtonState = ButtonState; + } + } + if(l2capinbuf[9] == 0x31 || l2capinbuf[9] == 0x33 || l2capinbuf[9] == 0x35 || l2capinbuf[9] == 0x37) { // Read the accelerometer + accXwiimote = ((l2capinbuf[12] << 2) | (l2capinbuf[10] & 0x60 >> 5)) - 500; + accYwiimote = ((l2capinbuf[13] << 2) | (l2capinbuf[11] & 0x20 >> 4)) - 500; + accZwiimote = ((l2capinbuf[14] << 2) | (l2capinbuf[11] & 0x40 >> 5)) - 500; + } + switch(l2capinbuf[9]) { + case 0x20: // Status Information - (a1) 20 BB BB LF 00 00 VV +#ifdef EXTRADEBUG + Notify(PSTR("\r\nStatus report was received"), 0x80); +#endif + wiiState = l2capinbuf[12]; // (0x01: Battery is nearly empty), (0x02: An Extension Controller is connected), (0x04: Speaker enabled), (0x08: IR enabled), (0x10: LED1, 0x20: LED2, 0x40: LED3, 0x80: LED4) + batteryLevel = l2capinbuf[15]; // Update battery level + + if(!checkBatteryLevel) { // If this is true it means that the user must have called getBatteryLevel() + if(l2capinbuf[12] & 0x02) { // Check if a extension is connected +#ifdef DEBUG_USB_HOST + if(!unknownExtensionConnected) + Notify(PSTR("\r\nExtension connected"), 0x80); +#endif + unknownExtensionConnected = true; +#ifdef WIICAMERA + if(!isIRCameraEnabled()) // Don't activate the Motion Plus if we are trying to initialize the IR camera +#endif + setReportMode(false, 0x35); // Also read the extension + } else { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nExtension disconnected"), 0x80); +#endif + if(motionPlusConnected) { +#ifdef DEBUG_USB_HOST + Notify(PSTR(" - from Motion Plus"), 0x80); +#endif + wii_clear_flag(WII_FLAG_NUNCHUCK_CONNECTED); + if(!activateNunchuck) // If it's already trying to initialize the Nunchuck don't set it to false + nunchuckConnected = false; + //else if(classicControllerConnected) + } else if(nunchuckConnected) { +#ifdef DEBUG_USB_HOST + Notify(PSTR(" - Nunchuck"), 0x80); +#endif + nunchuckConnected = false; // It must be the Nunchuck controller then + wii_clear_flag(WII_FLAG_NUNCHUCK_CONNECTED); + onInit(); + setReportMode(false, 0x31); // If there is no extension connected we will read the buttons and accelerometer + } else + setReportMode(false, 0x31); // If there is no extension connected we will read the buttons and accelerometer + } + } + else { +#ifdef EXTRADEBUG + Notify(PSTR("\r\nChecking battery level"), 0x80); +#endif + checkBatteryLevel = false; // Check for extensions by default + } +#ifdef DEBUG_USB_HOST + if(l2capinbuf[12] & 0x01) + Notify(PSTR("\r\nWARNING: Battery is nearly empty"), 0x80); +#endif + + break; + case 0x21: // Read Memory Data + if((l2capinbuf[12] & 0x0F) == 0) { // No error + uint8_t reportLength = (l2capinbuf[12] >> 4) + 1; // // Bit 4-7 is the length - 1 + // See: http://wiibrew.org/wiki/Wiimote/Extension_Controllers + if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x00 && l2capinbuf[20] == 0x00) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nNunchuck connected"), 0x80); +#endif + wii_set_flag(WII_FLAG_NUNCHUCK_CONNECTED); + } else if(l2capinbuf[16] == 0x00 && (l2capinbuf[17] == 0xA6 || l2capinbuf[17] == 0xA4) && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x00 && l2capinbuf[20] == 0x05) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nMotion Plus connected"), 0x80); +#endif + wii_set_flag(WII_FLAG_MOTION_PLUS_CONNECTED); + } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x04 && l2capinbuf[20] == 0x05) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nMotion Plus activated in normal mode"), 0x80); +#endif + motionPlusConnected = true; +#ifdef WIICAMERA + if(!isIRCameraEnabled()) // Don't activate the Motion Plus if we are trying to initialize the IR camera +#endif + setReportMode(false, 0x35); // Also read the extension + } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x05 && l2capinbuf[20] == 0x05) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nMotion Plus activated in Nunchuck pass-through mode"), 0x80); +#endif + activateNunchuck = false; + motionPlusConnected = true; + nunchuckConnected = true; +#ifdef WIICAMERA + if(!isIRCameraEnabled()) // Don't activate the Motion Plus if we are trying to initialize the IR camera +#endif + setReportMode(false, 0x35); // Also read the extension + } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA6 && l2capinbuf[18] == 0x20 && (l2capinbuf[19] == 0x00 || l2capinbuf[19] == 0x04 || l2capinbuf[19] == 0x05 || l2capinbuf[19] == 0x07) && l2capinbuf[20] == 0x05) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nInactive Wii Motion Plus"), 0x80); + Notify(PSTR("\r\nPlease unplug the Motion Plus, disconnect the Wiimote and then replug the Motion Plus Extension"), 0x80); +#endif + stateCounter = 300; // Skip the rest in "WII_CHECK_MOTION_PLUS_STATE" + } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x01 && l2capinbuf[20] == 0x20) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nWii U Pro Controller connected"), 0x80); +#endif + wiiUProControllerConnected = true; + } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x04 && l2capinbuf[20] == 0x02) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nWii Balance Board connected"), 0x80); +#endif + setReportMode(false, 0x32); // Read the Wii Balance Board extension + wii_set_flag(WII_FLAG_CALIBRATE_BALANCE_BOARD); + } + // Wii Balance Board calibration reports (24 bits in total) + else if(l2capinbuf[13] == 0x00 && l2capinbuf[14] == 0x24 && reportLength == 16) { // First 16-bit + for(uint8_t i = 0; i < 2; i++) { + for(uint8_t j = 0; j < 4; j++) + wiiBalanceBoardCal[i][j] = l2capinbuf[16 + 8 * i + 2 * j] | l2capinbuf[15 + 8 * i + 2 * j] << 8; + } + } else if(l2capinbuf[13] == 0x00 && l2capinbuf[14] == 0x34 && reportLength == 8) { // Last 8-bit + for(uint8_t j = 0; j < 4; j++) + wiiBalanceBoardCal[2][j] = l2capinbuf[16 + 2 * j] | l2capinbuf[15 + 2 * j] << 8; +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nWii Balance Board calibration values read successfully"), 0x80); +#endif + wii_clear_flag(WII_FLAG_CALIBRATE_BALANCE_BOARD); + wiiBalanceBoardConnected = true; + } +#ifdef DEBUG_USB_HOST + else { + Notify(PSTR("\r\nUnknown Device: "), 0x80); + D_PrintHex (l2capinbuf[13], 0x80); + D_PrintHex (l2capinbuf[14], 0x80); + Notify(PSTR("\r\nData: "), 0x80); + for(uint8_t i = 0; i < reportLength; i++) { + D_PrintHex (l2capinbuf[15 + i], 0x80); + Notify(PSTR(" "), 0x80); + } + } +#endif + } +#ifdef EXTRADEBUG + else { + Notify(PSTR("\r\nReport Error: "), 0x80); + D_PrintHex (l2capinbuf[13], 0x80); + D_PrintHex (l2capinbuf[14], 0x80); + } +#endif + break; + case 0x22: // Acknowledge output report, return function result +#ifdef DEBUG_USB_HOST + if(l2capinbuf[13] != 0x00) { // Check if there is an error + Notify(PSTR("\r\nCommand failed: "), 0x80); + D_PrintHex (l2capinbuf[12], 0x80); + } +#endif + break; + case 0x30: // Core buttons - (a1) 30 BB BB + break; + case 0x31: // Core Buttons and Accelerometer - (a1) 31 BB BB AA AA AA + break; + case 0x32: // Core Buttons with 8 Extension bytes - (a1) 32 BB BB EE EE EE EE EE EE EE EE + // See: http://wiibrew.org/wiki/Wii_Balance_Board#Data_Format + wiiBalanceBoardRaw[TopRight] = l2capinbuf[13] | l2capinbuf[12] << 8; // Top right + wiiBalanceBoardRaw[BotRight] = l2capinbuf[15] | l2capinbuf[14] << 8; // Bottom right + wiiBalanceBoardRaw[TopLeft] = l2capinbuf[17] | l2capinbuf[16] << 8; // Top left + wiiBalanceBoardRaw[BotLeft] = l2capinbuf[19] | l2capinbuf[18] << 8; // Bottom left + break; + case 0x33: // Core Buttons with Accelerometer and 12 IR bytes - (a1) 33 BB BB AA AA AA II II II II II II II II II II II II +#ifdef WIICAMERA + // Read the IR data + IR_object_x1 = (l2capinbuf[15] | ((uint16_t)(l2capinbuf[17] & 0x30) << 4)); // x position + IR_object_y1 = (l2capinbuf[16] | ((uint16_t)(l2capinbuf[17] & 0xC0) << 2)); // y position + IR_object_s1 = (l2capinbuf[17] & 0x0F); // Size value, 0-15 + + IR_object_x2 = (l2capinbuf[18] | ((uint16_t)(l2capinbuf[20] & 0x30) << 4)); + IR_object_y2 = (l2capinbuf[19] | ((uint16_t)(l2capinbuf[20] & 0xC0) << 2)); + IR_object_s2 = (l2capinbuf[20] & 0x0F); + + IR_object_x3 = (l2capinbuf[21] | ((uint16_t)(l2capinbuf[23] & 0x30) << 4)); + IR_object_y3 = (l2capinbuf[22] | ((uint16_t)(l2capinbuf[23] & 0xC0) << 2)); + IR_object_s3 = (l2capinbuf[23] & 0x0F); + + IR_object_x4 = (l2capinbuf[24] | ((uint16_t)(l2capinbuf[26] & 0x30) << 4)); + IR_object_y4 = (l2capinbuf[25] | ((uint16_t)(l2capinbuf[26] & 0xC0) << 2)); + IR_object_s4 = (l2capinbuf[26] & 0x0F); +#endif + break; + case 0x34: // Core Buttons with 19 Extension bytes - (a1) 34 BB BB EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE + break; + /* 0x3e and 0x3f both give unknown report types when report mode is 0x3e or 0x3f with mode number 0x05 */ + case 0x3E: // Core Buttons with Accelerometer and 32 IR bytes + // (a1) 31 BB BB AA AA AA II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II + // corresponds to output report mode 0x3e + + /**** for reading in full mode: DOES NOT WORK YET ****/ + /* When it works it will also have intensity and bounding box data */ + /* + IR_object_x1 = (l2capinbuf[13] | ((uint16_t)(l2capinbuf[15] & 0x30) << 4)); + IR_object_y1 = (l2capinbuf[14] | ((uint16_t)(l2capinbuf[15] & 0xC0) << 2)); + IR_object_s1 = (l2capinbuf[15] & 0x0F); + */ + break; + case 0x3F: + /* + IR_object_x1 = (l2capinbuf[13] | ((uint16_t)(l2capinbuf[15] & 0x30) << 4)); + IR_object_y1 = (l2capinbuf[14] | ((uint16_t)(l2capinbuf[15] & 0xC0) << 2)); + IR_object_s1 = (l2capinbuf[15] & 0x0F); + */ + break; + case 0x35: // Core Buttons and Accelerometer with 16 Extension Bytes + // (a1) 35 BB BB AA AA AA EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE +#if 1 // Set this to 0 if you don't want to use an extension, this reduceds the size of the library a lot! + if(motionPlusConnected) { + if(l2capinbuf[20] & 0x02) { // Check if it's a report from the Motion controller or the extension + if(motionValuesReset) { // We will only use the values when the gyro value has been set + gyroYawRaw = ((l2capinbuf[15] | ((l2capinbuf[18] & 0xFC) << 6)) - gyroYawZero); + gyroRollRaw = ((l2capinbuf[16] | ((l2capinbuf[19] & 0xFC) << 6)) - gyroRollZero); + gyroPitchRaw = ((l2capinbuf[17] | ((l2capinbuf[20] & 0xFC) << 6)) - gyroPitchZero); + + yawGyroSpeed = (double)gyroYawRaw / ((double)gyroYawZero / yawGyroScale); + rollGyroSpeed = -(double)gyroRollRaw / ((double)gyroRollZero / rollGyroScale); // We invert these values so they will fit the acc values + pitchGyroSpeed = (double)gyroPitchRaw / ((double)gyroPitchZero / pitchGyroScale); + + /* The onboard gyro has two ranges for slow and fast mode */ + if(!(l2capinbuf[18] & 0x02)) // Check if fast mode is used + yawGyroSpeed *= 4.545; + if(!(l2capinbuf[18] & 0x01)) // Check if fast mode is used + pitchGyroSpeed *= 4.545; + if(!(l2capinbuf[19] & 0x02)) // Check if fast mode is used + rollGyroSpeed *= 4.545; + + compPitch = (0.93 * (compPitch + (pitchGyroSpeed * (double)(micros() - timer) / 1000000)))+(0.07 * getWiimotePitch()); // Use a complimentary filter to calculate the angle + compRoll = (0.93 * (compRoll + (rollGyroSpeed * (double)(micros() - timer) / 1000000)))+(0.07 * getWiimoteRoll()); + + gyroYaw += (yawGyroSpeed * ((double)(micros() - timer) / 1000000)); + gyroRoll += (rollGyroSpeed * ((double)(micros() - timer) / 1000000)); + gyroPitch += (pitchGyroSpeed * ((double)(micros() - timer) / 1000000)); + timer = micros(); + /* + // Uncomment these lines to tune the gyro scale variabels + Notify(PSTR("\r\ngyroYaw: "), 0x80); + Notify(gyroYaw, 0x80); + Notify(PSTR("\tgyroRoll: "), 0x80); + Notify(gyroRoll, 0x80); + Notify(PSTR("\tgyroPitch: "), 0x80); + Notify(gyroPitch, 0x80); + */ + /* + Notify(PSTR("\twiimoteRoll: "), 0x80); + Notify(wiimoteRoll, 0x80); + Notify(PSTR("\twiimotePitch: "), 0x80); + Notify(wiimotePitch, 0x80); + */ + } else { + if((micros() - timer) > 1000000) { // Loop for 1 sec before resetting the values +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nThe gyro values has been reset"), 0x80); +#endif + gyroYawZero = (l2capinbuf[15] | ((l2capinbuf[18] & 0xFC) << 6)); + gyroRollZero = (l2capinbuf[16] | ((l2capinbuf[19] & 0xFC) << 6)); + gyroPitchZero = (l2capinbuf[17] | ((l2capinbuf[20] & 0xFC) << 6)); + + rollGyroScale = 500; // You might need to adjust these + pitchGyroScale = 400; + yawGyroScale = 415; + + gyroYaw = 0; + gyroRoll = 0; + gyroPitch = 0; + + motionValuesReset = true; + timer = micros(); + } + } + } else { + if(nunchuckConnected) { + hatValues[HatX] = l2capinbuf[15]; + hatValues[HatY] = l2capinbuf[16]; + accXnunchuck = ((l2capinbuf[17] << 2) | (l2capinbuf[20] & 0x10 >> 3)) - 416; + accYnunchuck = ((l2capinbuf[18] << 2) | (l2capinbuf[20] & 0x20 >> 4)) - 416; + accZnunchuck = (((l2capinbuf[19] & 0xFE) << 2) | (l2capinbuf[20] & 0xC0 >> 5)) - 416; + } + //else if(classicControllerConnected) { } + } + if(l2capinbuf[19] & 0x01) { + if(!extensionConnected) { + extensionConnected = true; + unknownExtensionConnected = true; +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nExtension connected to Motion Plus"), 0x80); +#endif + } + } else { + if(extensionConnected && !unknownExtensionConnected) { + extensionConnected = false; + unknownExtensionConnected = true; +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nExtension disconnected from Motion Plus"), 0x80); +#endif + nunchuckConnected = false; // There is no extension connected to the Motion Plus if this report is sent + } + } + + } else if(nunchuckConnected) { + hatValues[HatX] = l2capinbuf[15]; + hatValues[HatY] = l2capinbuf[16]; + accXnunchuck = ((l2capinbuf[17] << 2) | (l2capinbuf[20] & 0x0C >> 2)) - 416; + accYnunchuck = ((l2capinbuf[18] << 2) | (l2capinbuf[20] & 0x30 >> 4)) - 416; + accZnunchuck = ((l2capinbuf[19] << 2) | (l2capinbuf[20] & 0xC0 >> 6)) - 416; + } else if(wiiUProControllerConnected) { + hatValues[LeftHatX] = (l2capinbuf[15] | l2capinbuf[16] << 8); + hatValues[RightHatX] = (l2capinbuf[17] | l2capinbuf[18] << 8); + hatValues[LeftHatY] = (l2capinbuf[19] | l2capinbuf[20] << 8); + hatValues[RightHatY] = (l2capinbuf[21] | l2capinbuf[22] << 8); + } +#endif + break; +#ifdef DEBUG_USB_HOST + default: + Notify(PSTR("\r\nUnknown Report type: "), 0x80); + D_PrintHex (l2capinbuf[9], 0x80); + break; +#endif + } + } + } + L2CAP_task(); + } +} + +void WII::L2CAP_task() { + switch(l2cap_state) { + /* These states are used if the Wiimote is the host */ + case L2CAP_CONTROL_SUCCESS: + if(l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nHID Control Successfully Configured"), 0x80); +#endif + l2cap_state = L2CAP_INTERRUPT_SETUP; + } + break; + + case L2CAP_INTERRUPT_SETUP: + if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST)) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nHID Interrupt Incoming Connection Request"), 0x80); +#endif + pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, PENDING); + delay(1); + pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, SUCCESSFUL); + identifier++; + delay(1); + pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid); + + l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST; + } + break; + + /* These states are used if the Arduino is the host */ + case L2CAP_CONTROL_CONNECT_REQUEST: + if(l2cap_check_flag(L2CAP_FLAG_CONTROL_CONNECTED)) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nSend HID Control Config Request"), 0x80); +#endif + identifier++; + pBtd->l2cap_config_request(hci_handle, identifier, control_scid); + l2cap_state = L2CAP_CONTROL_CONFIG_REQUEST; + } + break; + + case L2CAP_CONTROL_CONFIG_REQUEST: + if(l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nSend HID Interrupt Connection Request"), 0x80); +#endif + identifier++; + pBtd->l2cap_connection_request(hci_handle, identifier, interrupt_dcid, HID_INTR_PSM); + l2cap_state = L2CAP_INTERRUPT_CONNECT_REQUEST; + } + break; + + case L2CAP_INTERRUPT_CONNECT_REQUEST: + if(l2cap_check_flag(L2CAP_FLAG_INTERRUPT_CONNECTED)) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nSend HID Interrupt Config Request"), 0x80); +#endif + identifier++; + pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid); + l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST; + } + break; + + case L2CAP_INTERRUPT_CONFIG_REQUEST: + if(l2cap_check_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS)) { // Now the HID channels is established +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nHID Channels Established"), 0x80); +#endif + pBtd->connectToWii = false; + pBtd->pairWithWii = false; + stateCounter = 0; + l2cap_state = WII_CHECK_MOTION_PLUS_STATE; + } + break; + + /* The next states are in run() */ + + case L2CAP_INTERRUPT_DISCONNECT: + if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE) && ((long)(millis() - timer) >= 0L)) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nDisconnected Interrupt Channel"), 0x80); +#endif + identifier++; + pBtd->l2cap_disconnection_request(hci_handle, identifier, control_scid, control_dcid); + l2cap_state = L2CAP_CONTROL_DISCONNECT; + } + break; + + case L2CAP_CONTROL_DISCONNECT: + if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE)) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nDisconnected Control Channel"), 0x80); +#endif + pBtd->hci_disconnect(hci_handle); + hci_handle = -1; // Reset handle + l2cap_event_flag = 0; // Reset flags + l2cap_state = L2CAP_WAIT; + } + break; + } +} + +void WII::Run() { + if(l2cap_state == L2CAP_INTERRUPT_DISCONNECT && ((long)(millis() - timer) >= 0L)) + L2CAP_task(); // Call the rest of the disconnection routine after we have waited long enough + + switch(l2cap_state) { + case L2CAP_WAIT: + if(pBtd->connectToWii && !pBtd->l2capConnectionClaimed && !wiimoteConnected && !activeConnection) { + pBtd->l2capConnectionClaimed = true; + activeConnection = true; + motionPlusInside = pBtd->motionPlusInside; +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nSend HID Control Connection Request"), 0x80); +#endif + hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection + l2cap_event_flag = 0; // Reset flags + identifier = 0; + pBtd->l2cap_connection_request(hci_handle, identifier, control_dcid, HID_CTRL_PSM); + l2cap_state = L2CAP_CONTROL_CONNECT_REQUEST; + } else if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST)) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nHID Control Incoming Connection Request"), 0x80); +#endif + pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, PENDING); + delay(1); + pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, SUCCESSFUL); + identifier++; + delay(1); + pBtd->l2cap_config_request(hci_handle, identifier, control_scid); + l2cap_state = L2CAP_CONTROL_SUCCESS; + } + break; + + case WII_CHECK_MOTION_PLUS_STATE: +#ifdef DEBUG_USB_HOST + if(stateCounter == 0) // Only print onnce + Notify(PSTR("\r\nChecking if a Motion Plus is connected"), 0x80); +#endif + stateCounter++; + if(stateCounter % 200 == 0) + checkMotionPresent(); // Check if there is a motion plus connected + if(wii_check_flag(WII_FLAG_MOTION_PLUS_CONNECTED)) { + stateCounter = 0; + l2cap_state = WII_INIT_MOTION_PLUS_STATE; + timer = micros(); + + if(unknownExtensionConnected) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nA extension is also connected"), 0x80); +#endif + activateNunchuck = true; // For we will just set this to true as this the only extension supported so far + } + + } else if(stateCounter == 601) { // We will try three times to check for the motion plus +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nNo Motion Plus was detected"), 0x80); +#endif + stateCounter = 0; + l2cap_state = WII_CHECK_EXTENSION_STATE; + } + break; + + case WII_CHECK_EXTENSION_STATE: // This is used to check if there is anything plugged in to the extension port +#ifdef DEBUG_USB_HOST + if(stateCounter == 0) // Only print onnce + Notify(PSTR("\r\nChecking if there is any extension connected"), 0x80); +#endif + stateCounter++; // We use this counter as there has to be a short delay between the commands + if(stateCounter == 1) + statusRequest(); // See if a new device has connected + if(stateCounter == 100) { + if(unknownExtensionConnected) // Check if there is a extension is connected to the port + initExtension1(); + else + stateCounter = 499; + } else if(stateCounter == 200) + initExtension2(); + else if(stateCounter == 300) { + readExtensionType(); + unknownExtensionConnected = false; + } else if(stateCounter == 400) { + if(wii_check_flag(WII_FLAG_CALIBRATE_BALANCE_BOARD)) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nReading Wii Balance Board calibration values"), 0x80); +#endif + readWiiBalanceBoardCalibration(); + } else + stateCounter = 499; + } else if(stateCounter == 500) { + stateCounter = 0; + l2cap_state = TURN_ON_LED; + } + break; + + case WII_INIT_MOTION_PLUS_STATE: + stateCounter++; + if(stateCounter == 1) + initMotionPlus(); + else if(stateCounter == 100) + activateMotionPlus(); + else if(stateCounter == 200) + readExtensionType(); // Check if it has been activated + else if(stateCounter == 300) { + stateCounter = 0; + unknownExtensionConnected = false; // The motion plus will send a status report when it's activated, we will set this to false so it doesn't reinitialize the Motion Plus + l2cap_state = TURN_ON_LED; + } + break; + + case TURN_ON_LED: + if(wii_check_flag(WII_FLAG_NUNCHUCK_CONNECTED)) + nunchuckConnected = true; + wiimoteConnected = true; + onInit(); + l2cap_state = L2CAP_DONE; + break; + + case L2CAP_DONE: + if(unknownExtensionConnected) { +#ifdef DEBUG_USB_HOST + if(stateCounter == 0) // Only print once + Notify(PSTR("\r\nChecking extension port"), 0x80); +#endif + stateCounter++; // We will use this counter as there has to be a short delay between the commands + if(stateCounter == 50) + statusRequest(); + else if(stateCounter == 100) + initExtension1(); + else if(stateCounter == 150) + if((extensionConnected && motionPlusConnected) || (unknownExtensionConnected && !motionPlusConnected)) + initExtension2(); + else + stateCounter = 299; // There is no extension connected + else if(stateCounter == 200) + readExtensionType(); + else if(stateCounter == 250) { + if(wii_check_flag(WII_FLAG_NUNCHUCK_CONNECTED)) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nNunchuck was reconnected"), 0x80); +#endif + activateNunchuck = true; + nunchuckConnected = true; + } + if(!motionPlusConnected) + stateCounter = 449; + } else if(stateCounter == 300) { + if(motionPlusConnected) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nReactivating the Motion Plus"), 0x80); +#endif + initMotionPlus(); + } else + stateCounter = 449; + } else if(stateCounter == 350) + activateMotionPlus(); + else if(stateCounter == 400) + readExtensionType(); // Check if it has been activated + else if(stateCounter == 450) { + onInit(); + stateCounter = 0; + unknownExtensionConnected = false; + } + } else + stateCounter = 0; + break; + } +} + +/************************************************************/ +/* HID Commands */ +/************************************************************/ + +void WII::HID_Command(uint8_t* data, uint8_t nbytes) { + if(motionPlusInside) + pBtd->L2CAP_Command(hci_handle, data, nbytes, interrupt_scid[0], interrupt_scid[1]); // It's the new Wiimote with the Motion Plus Inside or Wii U Pro controller + else + pBtd->L2CAP_Command(hci_handle, data, nbytes, control_scid[0], control_scid[1]); +} + +void WII::setAllOff() { + HIDBuffer[1] = 0x11; + HIDBuffer[2] = 0x00; + HID_Command(HIDBuffer, 3); +} + +void WII::setRumbleOff() { + HIDBuffer[1] = 0x11; + HIDBuffer[2] &= ~0x01; // Bit 0 control the rumble + HID_Command(HIDBuffer, 3); +} + +void WII::setRumbleOn() { + HIDBuffer[1] = 0x11; + HIDBuffer[2] |= 0x01; // Bit 0 control the rumble + HID_Command(HIDBuffer, 3); +} + +void WII::setRumbleToggle() { + HIDBuffer[1] = 0x11; + HIDBuffer[2] ^= 0x01; // Bit 0 control the rumble + HID_Command(HIDBuffer, 3); +} + +void WII::setLedRaw(uint8_t value) { + HIDBuffer[1] = 0x11; + HIDBuffer[2] = value | (HIDBuffer[2] & 0x01); // Keep the rumble bit + HID_Command(HIDBuffer, 3); +} + +void WII::setLedOff(LEDEnum a) { + HIDBuffer[1] = 0x11; + HIDBuffer[2] &= ~(pgm_read_byte(&WII_LEDS[(uint8_t)a])); + HID_Command(HIDBuffer, 3); +} + +void WII::setLedOn(LEDEnum a) { + if(a == OFF) + setLedRaw(0); + else { + HIDBuffer[1] = 0x11; + HIDBuffer[2] |= pgm_read_byte(&WII_LEDS[(uint8_t)a]); + HID_Command(HIDBuffer, 3); + } +} + +void WII::setLedToggle(LEDEnum a) { + HIDBuffer[1] = 0x11; + HIDBuffer[2] ^= pgm_read_byte(&WII_LEDS[(uint8_t)a]); + HID_Command(HIDBuffer, 3); +} + +void WII::setLedStatus() { + HIDBuffer[1] = 0x11; + HIDBuffer[2] = (HIDBuffer[2] & 0x01); // Keep the rumble bit + if(wiimoteConnected) + HIDBuffer[2] |= 0x10; // If it's connected LED1 will light up + if(motionPlusConnected) + HIDBuffer[2] |= 0x20; // If it's connected LED2 will light up + if(nunchuckConnected) + HIDBuffer[2] |= 0x40; // If it's connected LED3 will light up + + HID_Command(HIDBuffer, 3); +} + +uint8_t WII::getBatteryLevel() { + checkBatteryLevel = true; // This is needed so the library knows that the status response is a response to this function + statusRequest(); // This will update the battery level + return batteryLevel; +}; + +void WII::setReportMode(bool continuous, uint8_t mode) { + uint8_t cmd_buf[4]; + cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) + cmd_buf[1] = 0x12; + if(continuous) + cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Keep the rumble bit + else + cmd_buf[2] = 0x00 | (HIDBuffer[2] & 0x01); // Keep the rumble bit + cmd_buf[3] = mode; + HID_Command(cmd_buf, 4); +} + +void WII::statusRequest() { + uint8_t cmd_buf[3]; + cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) + cmd_buf[1] = 0x15; + cmd_buf[2] = (HIDBuffer[2] & 0x01); // Keep the rumble bit + HID_Command(cmd_buf, 3); +} + +/************************************************************/ +/* Memmory Commands */ +/************************************************************/ + +void WII::writeData(uint32_t offset, uint8_t size, uint8_t* data) { + uint8_t cmd_buf[23]; + cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) + cmd_buf[1] = 0x16; // Write data + cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Write to memory, clear bit 2 to write to EEPROM + cmd_buf[3] = (uint8_t)((offset & 0xFF0000) >> 16); + cmd_buf[4] = (uint8_t)((offset & 0xFF00) >> 8); + cmd_buf[5] = (uint8_t)(offset & 0xFF); + cmd_buf[6] = size; + uint8_t i = 0; + for(; i < size; i++) + cmd_buf[7 + i] = data[i]; + for(; i < 16; i++) // Set the rest to zero + cmd_buf[7 + i] = 0x00; + HID_Command(cmd_buf, 23); +} + +void WII::initExtension1() { + uint8_t buf[1]; + buf[0] = 0x55; + writeData(0xA400F0, 1, buf); +} + +void WII::initExtension2() { + uint8_t buf[1]; + buf[0] = 0x00; + writeData(0xA400FB, 1, buf); +} + +void WII::initMotionPlus() { + uint8_t buf[1]; + buf[0] = 0x55; + writeData(0xA600F0, 1, buf); +} + +void WII::activateMotionPlus() { + uint8_t buf[1]; + if(pBtd->wiiUProController) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nActivating Wii U Pro Controller"), 0x80); +#endif + buf[0] = 0x00; // It seems like you can send anything but 0x04, 0x05, and 0x07 + } else if(activateNunchuck) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nActivating Motion Plus in pass-through mode"), 0x80); +#endif + buf[0] = 0x05; // Activate nunchuck pass-through mode + }//else if(classicControllerConnected && extensionConnected) + //buf[0] = 0x07; + else { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nActivating Motion Plus in normal mode"), 0x80); +#endif + buf[0] = 0x04; // Don't use any extension + } + writeData(0xA600FE, 1, buf); +} + +void WII::readData(uint32_t offset, uint16_t size, bool EEPROM) { + uint8_t cmd_buf[8]; + cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) + cmd_buf[1] = 0x17; // Read data + if(EEPROM) + cmd_buf[2] = 0x00 | (HIDBuffer[2] & 0x01); // Read from EEPROM + else + cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Read from memory + cmd_buf[3] = (uint8_t)((offset & 0xFF0000) >> 16); + cmd_buf[4] = (uint8_t)((offset & 0xFF00) >> 8); + cmd_buf[5] = (uint8_t)(offset & 0xFF); + cmd_buf[6] = (uint8_t)((size & 0xFF00) >> 8); + cmd_buf[7] = (uint8_t)(size & 0xFF); + + HID_Command(cmd_buf, 8); +} + +void WII::readExtensionType() { + readData(0xA400FA, 6, false); +} + +void WII::readCalData() { + readData(0x0016, 8, true); +} + +void WII::checkMotionPresent() { + readData(0xA600FA, 6, false); +} + +void WII::readWiiBalanceBoardCalibration() { + readData(0xA40024, 24, false); +} + +/************************************************************/ +/* WII Commands */ +/************************************************************/ + +bool WII::getButtonPress(ButtonEnum b) { // Return true when a button is pressed + if(wiiUProControllerConnected) + return (ButtonState & pgm_read_dword(&WII_PROCONTROLLER_BUTTONS[(uint8_t)b])); + else + return (ButtonState & pgm_read_dword(&WII_BUTTONS[(uint8_t)b])); +} + +bool WII::getButtonClick(ButtonEnum b) { // Only return true when a button is clicked + uint32_t button; + if(wiiUProControllerConnected) + button = pgm_read_dword(&WII_PROCONTROLLER_BUTTONS[(uint8_t)b]); + else + button = pgm_read_dword(&WII_BUTTONS[(uint8_t)b]); + bool click = (ButtonClickState & button); + ButtonClickState &= ~button; // clear "click" event + return click; +} + +uint8_t WII::getAnalogHat(HatEnum a) { + if(!nunchuckConnected) + return 127; // Return center position + else { + uint8_t output = hatValues[(uint8_t)a]; + if(output == 0xFF || output == 0x00) // The joystick will only read 255 or 0 when the cable is unplugged or initializing, so we will just return the center position + return 127; + else + return output; + } +} + +uint16_t WII::getAnalogHat(AnalogHatEnum a) { + if(!wiiUProControllerConnected) + return 2000; + else { + uint16_t output = hatValues[(uint8_t)a]; + if(output == 0x00) // The joystick will only read 0 when it is first initializing, so we will just return the center position + return 2000; + else + return output; + } +} + +void WII::onInit() { + if(pFuncOnInit) + pFuncOnInit(); // Call the user function + else + setLedStatus(); +} + +/************************************************************/ +/* Wii Balance Board Commands */ +/************************************************************/ + +float WII::getWeight(BalanceBoardEnum pos) { + // Use interpolating between two points - based on: https://github.com/skorokithakis/gr8w8upd8m8/blob/master/gr8w8upd8m8.py + // wiiBalanceBoardCal[pos][0] is calibration values for 0 kg + // wiiBalanceBoardCal[pos][1] is calibration values for 17 kg + // wiiBalanceBoardCal[pos][2] is calibration values for 34 kg + if(wiiBalanceBoardRaw[pos] < wiiBalanceBoardCal[0][pos]) + return 0.0f; // Below 0 kg + else if(wiiBalanceBoardRaw[pos] < wiiBalanceBoardCal[1][pos]) // Between 0 and 17 kg + return 17.0f * (float)(wiiBalanceBoardRaw[pos] - wiiBalanceBoardCal[0][pos]) / (float)(wiiBalanceBoardCal[1][pos] - wiiBalanceBoardCal[0][pos]); + else // More than 17 kg + return 17.0f + 17.0f * (float)(wiiBalanceBoardRaw[pos] - wiiBalanceBoardCal[1][pos]) / (float)(wiiBalanceBoardCal[2][pos] - wiiBalanceBoardCal[1][pos]); +}; + +float WII::getTotalWeight() { + return getWeight(TopRight) + getWeight(BotRight) + getWeight(TopLeft) + getWeight(BotLeft); +}; + +/************************************************************/ +/* The following functions are for the IR camera */ +/************************************************************/ + +#ifdef WIICAMERA + +void WII::IRinitialize() { // Turns on and initialises the IR camera + + enableIRCamera1(); +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nEnable IR Camera1 Complete"), 0x80); +#endif + delay(80); + + enableIRCamera2(); +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nEnable IR Camera2 Complete"), 0x80); +#endif + delay(80); + + write0x08Value(); +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nWrote hex number 0x08"), 0x80); +#endif + delay(80); + + writeSensitivityBlock1(); +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nWrote Sensitivity Block 1"), 0x80); +#endif + delay(80); + + writeSensitivityBlock2(); +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nWrote Sensitivity Block 2"), 0x80); +#endif + delay(80); + + uint8_t mode_num = 0x03; + setWiiModeNumber(mode_num); // Change input for whatever mode you want i.e. 0x01, 0x03, or 0x05 +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nSet Wii Mode Number To 0x"), 0x80); + D_PrintHex (mode_num, 0x80); +#endif + delay(80); + + write0x08Value(); +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nWrote Hex Number 0x08"), 0x80); +#endif + delay(80); + + setReportMode(false, 0x33); + //setReportMode(false, 0x3f); // For full reporting mode, doesn't work yet +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nSet Report Mode to 0x33"), 0x80); +#endif + delay(80); + + statusRequest(); // Used to update wiiState - call isIRCameraEnabled() afterwards to check if it actually worked +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nIR Initialized"), 0x80); +#endif +} + +void WII::enableIRCamera1() { + uint8_t cmd_buf[3]; + cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) + cmd_buf[1] = 0x13; // Output report 13 + cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Keep the rumble bit and sets bit 2 + HID_Command(cmd_buf, 3); +} + +void WII::enableIRCamera2() { + uint8_t cmd_buf[3]; + cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) + cmd_buf[1] = 0x1A; // Output report 1A + cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Keep the rumble bit and sets bit 2 + HID_Command(cmd_buf, 3); +} + +void WII::writeSensitivityBlock1() { + uint8_t buf[9]; + buf[0] = 0x00; + buf[1] = 0x00; + buf[2] = 0x00; + buf[3] = 0x00; + buf[4] = 0x00; + buf[5] = 0x00; + buf[6] = 0x90; + buf[7] = 0x00; + buf[8] = 0x41; + + writeData(0xB00000, 9, buf); +} + +void WII::writeSensitivityBlock2() { + uint8_t buf[2]; + buf[0] = 0x40; + buf[1] = 0x00; + + writeData(0xB0001A, 2, buf); +} + +void WII::write0x08Value() { + uint8_t cmd = 0x08; + writeData(0xb00030, 1, &cmd); +} + +void WII::setWiiModeNumber(uint8_t mode_number) { // mode_number in hex i.e. 0x03 for extended mode + writeData(0xb00033, 1, &mode_number); +} +#endif diff --git a/lib/usbhost/USB_Host_Shield_2.0/Wii.h b/lib/usbhost/USB_Host_Shield_2.0/Wii.h new file mode 100644 index 0000000000..960f2273de --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/Wii.h @@ -0,0 +1,518 @@ +/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. + + This software may be distributed and modified under the terms of the GNU + General Public License version 2 (GPL2) as published by the Free Software + Foundation and appearing in the file GPL2.TXT included in the packaging of + this file. Please note that GPL2 Section 2[b] requires that all works based + on this software must also be made publicly available under the terms of + the GPL2 ("Copyleft"). + + Contact information + ------------------- + + Kristian Lauszus, TKJ Electronics + Web : http://www.tkjelectronics.com + e-mail : kristianl@tkjelectronics.com + + IR camera support added by Allan Glover (adglover9.81@gmail.com) and Kristian Lauszus + */ + +#ifndef _wii_h_ +#define _wii_h_ + +#include "BTD.h" +#include "controllerEnums.h" + +/* Wii event flags */ +#define WII_FLAG_MOTION_PLUS_CONNECTED (1 << 0) +#define WII_FLAG_NUNCHUCK_CONNECTED (1 << 1) +#define WII_FLAG_CALIBRATE_BALANCE_BOARD (1 << 2) + +#define wii_check_flag(flag) (wii_event_flag & (flag)) +#define wii_set_flag(flag) (wii_event_flag |= (flag)) +#define wii_clear_flag(flag) (wii_event_flag &= ~(flag)) + +/** Enum used to read the joystick on the Nunchuck. */ +enum HatEnum { + /** Read the x-axis on the Nunchuck joystick. */ + HatX = 0, + /** Read the y-axis on the Nunchuck joystick. */ + HatY = 1, +}; + +/** Enum used to read the weight on Wii Balance Board. */ +enum BalanceBoardEnum { + TopRight = 0, + BotRight = 1, + TopLeft = 2, + BotLeft = 3, +}; + +/** + * This BluetoothService class implements support for the Wiimote including the Nunchuck and Motion Plus extension. + * + * It also support the Wii U Pro Controller. + */ +class WII : public BluetoothService { +public: + /** + * Constructor for the WII class. + * @param p Pointer to BTD class instance. + * @param pair Set this to true in order to pair with the Wiimote. If the argument is omitted then it won't pair with it. + * One can use ::PAIR to set it to true. + */ + WII(BTD *p, bool pair = false); + + /** @name BluetoothService implementation */ + /** Used this to disconnect any of the controllers. */ + void disconnect(); + /**@}*/ + + /** @name Wii Controller functions */ + /** + * getButtonPress(Button b) will return true as long as the button is held down. + * + * While getButtonClick(Button b) will only return it once. + * + * So you instance if you need to increase a variable once you would use getButtonClick(Button b), + * but if you need to drive a robot forward you would use getButtonPress(Button b). + * @param b ::ButtonEnum to read. + * @return getButtonPress(ButtonEnum b) will return a true as long as a button is held down, while getButtonClick(ButtonEnum b) will return true once for each button press. + */ + bool getButtonPress(ButtonEnum b); + bool getButtonClick(ButtonEnum b); + /**@}*/ + + /** @name Wii Controller functions */ + + /** Call this to start the paring sequence with a controller */ + void pair(void) { + if(pBtd) + pBtd->pairWithWiimote(); + }; + /** + * Used to read the joystick of the Nunchuck. + * @param a Either ::HatX or ::HatY. + * @return Return the analog value in the range from approximately 25-230. + */ + uint8_t getAnalogHat(HatEnum a); + /** + * Used to read the joystick of the Wii U Pro Controller. + * @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY. + * @return Return the analog value in the range from approximately 800-3200. + */ + uint16_t getAnalogHat(AnalogHatEnum a); + + /** + * Pitch calculated from the Wiimote. A complimentary filter is used if the Motion Plus is connected. + * @return Pitch in the range from 0-360. + */ + double getPitch() { + if(motionPlusConnected) + return compPitch; + return getWiimotePitch(); + }; + + /** + * Roll calculated from the Wiimote. A complimentary filter is used if the Motion Plus is connected. + * @return Roll in the range from 0-360. + */ + double getRoll() { + if(motionPlusConnected) + return compRoll; + return getWiimoteRoll(); + }; + + /** + * This is the yaw calculated by the gyro. + * + * NOTE: This angle will drift a lot and is only available if the Motion Plus extension is connected. + * @return The angle calculated using the gyro. + */ + double getYaw() { + return gyroYaw; + }; + + /** Used to set all LEDs and rumble off. */ + void setAllOff(); + /** Turn off rumble. */ + void setRumbleOff(); + /** Turn on rumble. */ + void setRumbleOn(); + /** Toggle rumble. */ + void setRumbleToggle(); + + /** + * Set LED value without using the ::LEDEnum. + * @param value See: ::LEDEnum. + */ + void setLedRaw(uint8_t value); + + /** Turn all LEDs off. */ + void setLedOff() { + setLedRaw(0); + }; + /** + * Turn the specific ::LEDEnum off. + * @param a The ::LEDEnum to turn off. + */ + void setLedOff(LEDEnum a); + /** + * Turn the specific ::LEDEnum on. + * @param a The ::LEDEnum to turn on. + */ + void setLedOn(LEDEnum a); + /** + * Toggle the specific ::LEDEnum. + * @param a The ::LEDEnum to toggle. + */ + void setLedToggle(LEDEnum a); + /** + * This will set the LEDs, so the user can see which connections are active. + * + * The first ::LEDEnum indicate that the Wiimote is connected, + * the second ::LEDEnum indicate indicate that a Motion Plus is also connected + * the third ::LEDEnum will indicate that a Nunchuck controller is also connected. + */ + void setLedStatus(); + + /** + * Return the battery level of the Wiimote. + * @return The battery level in the range 0-255. + */ + uint8_t getBatteryLevel(); + + /** + * Return the Wiimote state. + * @return See: http://wiibrew.org/wiki/Wiimote#0x20:_Status. + */ + uint8_t getWiiState() { + return wiiState; + }; + /**@}*/ + + /**@{*/ + /** Variable used to indicate if a Wiimote is connected. */ + bool wiimoteConnected; + /** Variable used to indicate if a Nunchuck controller is connected. */ + bool nunchuckConnected; + /** Variable used to indicate if a Nunchuck controller is connected. */ + bool motionPlusConnected; + /** Variable used to indicate if a Wii U Pro controller is connected. */ + bool wiiUProControllerConnected; + /** Variable used to indicate if a Wii Balance Board is connected. */ + bool wiiBalanceBoardConnected; + /**@}*/ + + /* IMU Data, might be usefull if you need to do something more advanced than just calculating the angle */ + + /**@{*/ + + /** Pitch and roll calculated from the accelerometer inside the Wiimote. */ + double getWiimotePitch() { + return (atan2(accYwiimote, accZwiimote) + PI) * RAD_TO_DEG; + }; + + double getWiimoteRoll() { + return (atan2(accXwiimote, accZwiimote) + PI) * RAD_TO_DEG; + }; + /**@}*/ + + /**@{*/ + + /** Pitch and roll calculated from the accelerometer inside the Nunchuck. */ + double getNunchuckPitch() { + return (atan2(accYnunchuck, accZnunchuck) + PI) * RAD_TO_DEG; + }; + + double getNunchuckRoll() { + return (atan2(accXnunchuck, accZnunchuck) + PI) * RAD_TO_DEG; + }; + /**@}*/ + + /**@{*/ + /** Accelerometer values used to calculate pitch and roll. */ + int16_t accXwiimote, accYwiimote, accZwiimote; + int16_t accXnunchuck, accYnunchuck, accZnunchuck; + /**@}*/ + + /* Variables for the gyro inside the Motion Plus */ + /** This is the pitch calculated by the gyro - use this to tune WII#pitchGyroScale. */ + double gyroPitch; + /** This is the roll calculated by the gyro - use this to tune WII#rollGyroScale. */ + double gyroRoll; + /** This is the yaw calculated by the gyro - use this to tune WII#yawGyroScale. */ + double gyroYaw; + + /**@{*/ + /** The speed in deg/s from the gyro. */ + double pitchGyroSpeed; + double rollGyroSpeed; + double yawGyroSpeed; + /**@}*/ + + /**@{*/ + /** You might need to fine-tune these values. */ + uint16_t pitchGyroScale; + uint16_t rollGyroScale; + uint16_t yawGyroScale; + /**@}*/ + + /**@{*/ + /** Raw value read directly from the Motion Plus. */ + int16_t gyroYawRaw; + int16_t gyroRollRaw; + int16_t gyroPitchRaw; + /**@}*/ + + /**@{*/ + /** These values are set when the controller is first initialized. */ + int16_t gyroYawZero; + int16_t gyroRollZero; + int16_t gyroPitchZero; + /**@}*/ + + /** @name Wii Balance Board functions */ + + /** + * Used to get the weight at the specific position on the Wii Balance Board. + * @param ::BalanceBoardEnum to read from. + * @return Returns the weight in kg. + */ + float getWeight(BalanceBoardEnum pos); + + /** + * Used to get total weight on the Wii Balance Board. + * @returnReturns the weight in kg. + */ + float getTotalWeight(); + + /** + * Used to get the raw reading at the specific position on the Wii Balance Board. + * @param ::BalanceBoardEnum to read from. + * @return Returns the raw reading. + */ + uint16_t getWeightRaw(BalanceBoardEnum pos) { + return wiiBalanceBoardRaw[pos]; + }; + /**@}*/ + +#ifdef WIICAMERA + /** @name Wiimote IR camera functions + * You will have to set ::ENABLE_WII_IR_CAMERA in settings.h to 1 in order use the IR camera. + */ + /** Initialises the camera as per the steps from: http://wiibrew.org/wiki/Wiimote#IR_Camera */ + void IRinitialize(); + + /** + * IR object 1 x-position read from the Wii IR camera. + * @return The x-position of the object in the range 0-1023. + */ + uint16_t getIRx1() { + return IR_object_x1; + }; + + /** + * IR object 1 y-position read from the Wii IR camera. + * @return The y-position of the object in the range 0-767. + */ + uint16_t getIRy1() { + return IR_object_y1; + }; + + /** + * IR object 1 size read from the Wii IR camera. + * @return The size of the object in the range 0-15. + */ + uint8_t getIRs1() { + return IR_object_s1; + }; + + /** + * IR object 2 x-position read from the Wii IR camera. + * @return The x-position of the object in the range 0-1023. + */ + uint16_t getIRx2() { + return IR_object_x2; + }; + + /** + * IR object 2 y-position read from the Wii IR camera. + * @return The y-position of the object in the range 0-767. + */ + uint16_t getIRy2() { + return IR_object_y2; + }; + + /** + * IR object 2 size read from the Wii IR camera. + * @return The size of the object in the range 0-15. + */ + uint8_t getIRs2() { + return IR_object_s2; + }; + + /** + * IR object 3 x-position read from the Wii IR camera. + * @return The x-position of the object in the range 0-1023. + */ + uint16_t getIRx3() { + return IR_object_x3; + }; + + /** + * IR object 3 y-position read from the Wii IR camera. + * @return The y-position of the object in the range 0-767. + */ + uint16_t getIRy3() { + return IR_object_y3; + }; + + /** + * IR object 3 size read from the Wii IR camera. + * @return The size of the object in the range 0-15. + */ + uint8_t getIRs3() { + return IR_object_s3; + }; + + /** + * IR object 4 x-position read from the Wii IR camera. + * @return The x-position of the object in the range 0-1023. + */ + uint16_t getIRx4() { + return IR_object_x4; + }; + + /** + * IR object 4 y-position read from the Wii IR camera. + * @return The y-position of the object in the range 0-767. + */ + uint16_t getIRy4() { + return IR_object_y4; + }; + + /** + * IR object 4 size read from the Wii IR camera. + * @return The size of the object in the range 0-15. + */ + uint8_t getIRs4() { + return IR_object_s4; + }; + + /** + * Use this to check if the camera is enabled or not. + * If not call WII#IRinitialize to initialize the IR camera. + * @return True if it's enabled, false if not. + */ + bool isIRCameraEnabled() { + return (wiiState & 0x08); + }; + /**@}*/ +#endif + +protected: + /** @name BluetoothService implementation */ + /** + * Used to pass acldata to the services. + * @param ACLData Incoming acldata. + */ + void ACLData(uint8_t* ACLData); + /** Used to run part of the state machine. */ + void Run(); + /** Use this to reset the service. */ + void Reset(); + /** + * Called when the controller is successfully initialized. + * Use attachOnInit(void (*funcOnInit)(void)) to call your own function. + * This is useful for instance if you want to set the LEDs in a specific way. + */ + void onInit(); + /**@}*/ + +private: + + void L2CAP_task(); // L2CAP state machine + + /* Variables filled from HCI event management */ + bool activeConnection; // Used to indicate if it's already has established a connection + + /* Variables used by high level L2CAP task */ + uint8_t l2cap_state; + uint8_t wii_event_flag; // Used for Wii flags + + uint32_t ButtonState; + uint32_t OldButtonState; + uint32_t ButtonClickState; + uint16_t hatValues[4]; + + uint8_t HIDBuffer[3]; // Used to store HID commands + + uint16_t stateCounter; + bool unknownExtensionConnected; + bool extensionConnected; + bool checkBatteryLevel; // Set to true when getBatteryLevel() is called otherwise if should be false + bool motionPlusInside; // True if it's a new Wiimote with the Motion Plus extension build into it + + /* L2CAP Channels */ + uint8_t control_scid[2]; // L2CAP source CID for HID_Control + uint8_t control_dcid[2]; // 0x0060 + uint8_t interrupt_scid[2]; // L2CAP source CID for HID_Interrupt + uint8_t interrupt_dcid[2]; // 0x0061 + + /* HID Commands */ + void HID_Command(uint8_t* data, uint8_t nbytes); + void setReportMode(bool continuous, uint8_t mode); + + void writeData(uint32_t offset, uint8_t size, uint8_t* data); + void initExtension1(); + void initExtension2(); + + void statusRequest(); // Used to update the Wiimote state and battery level + + void readData(uint32_t offset, uint16_t size, bool EEPROM); + void readExtensionType(); + void readCalData(); + void readWiiBalanceBoardCalibration(); // Used by the library to read the Wii Balance Board calibration values + + void checkMotionPresent(); // Used to see if a Motion Plus is connected to the Wiimote + void initMotionPlus(); + void activateMotionPlus(); + + uint16_t wiiBalanceBoardRaw[4]; // Wii Balance Board raw values + uint16_t wiiBalanceBoardCal[3][4]; // Wii Balance Board calibration values + + double compPitch; // Fusioned angle using a complimentary filter if the Motion Plus is connected + double compRoll; // Fusioned angle using a complimentary filter if the Motion Plus is connected + + bool activateNunchuck; + bool motionValuesReset; // This bool is true when the gyro values has been reset + uint32_t timer; + + uint8_t wiiState; // Stores the value in l2capinbuf[12] - (0x01: Battery is nearly empty), (0x02: An Extension Controller is connected), (0x04: Speaker enabled), (0x08: IR enabled), (0x10: LED1, 0x20: LED2, 0x40: LED3, 0x80: LED4) + uint8_t batteryLevel; + +#ifdef WIICAMERA + /* Private function and variables for the readings from the IR Camera */ + void enableIRCamera1(); // Sets bit 2 of output report 13 + void enableIRCamera2(); // Sets bit 2 of output report 1A + void writeSensitivityBlock1(); + void writeSensitivityBlock2(); + void write0x08Value(); + void setWiiModeNumber(uint8_t mode_number); + + uint16_t IR_object_x1; // IR x position 10 bits + uint16_t IR_object_y1; // IR y position 10 bits + uint8_t IR_object_s1; // IR size value + uint16_t IR_object_x2; + uint16_t IR_object_y2; + uint8_t IR_object_s2; + uint16_t IR_object_x3; // IR x position 10 bits + uint16_t IR_object_y3; // IR y position 10 bits + uint8_t IR_object_s3; // IR size value + uint16_t IR_object_x4; + uint16_t IR_object_y4; + uint8_t IR_object_s4; +#endif +}; +#endif diff --git a/lib/usbhost/USB_Host_Shield_2.0/WiiCameraReadme.md b/lib/usbhost/USB_Host_Shield_2.0/WiiCameraReadme.md new file mode 100644 index 0000000000..8577d73fb3 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/WiiCameraReadme.md @@ -0,0 +1,13 @@ +Please see for the complete capabilities of the Wii camera. The IR camera code was written based on the above website and with support from Kristian Lauszus. + +This library is large, if you run into memory problems when uploading to the Arduino, disable serial debugging. + +To enable the IR camera code, simply set ```ENABLE_WII_IR_CAMERA``` to 1 in [settings.h](settings.h). + +This library implements the following settings: + +* Report sensitivity mode: 00 00 00 00 00 00 90 00 41 40 00 Suggested by inio (high sensitivity) +* Data Format: Extended mode (0x03). Full mode is not working yet. The output reports 0x3e and 0x3f need tampering with + * In this mode the camera outputs x and y coordinates and a size dimension for the 4 brightest points. + +Again, read through to get an understanding of the camera and its settings. diff --git a/lib/usbhost/USB_Host_Shield_2.0/XBOXOLD.cpp b/lib/usbhost/USB_Host_Shield_2.0/XBOXOLD.cpp new file mode 100644 index 0000000000..78e6e9a5f5 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/XBOXOLD.cpp @@ -0,0 +1,337 @@ +/* Copyright (C) 2013 Kristian Lauszus, TKJ Electronics. All rights reserved. + + This software may be distributed and modified under the terms of the GNU + General Public License version 2 (GPL2) as published by the Free Software + Foundation and appearing in the file GPL2.TXT included in the packaging of + this file. Please note that GPL2 Section 2[b] requires that all works based + on this software must also be made publicly available under the terms of + the GPL2 ("Copyleft"). + + Contact information + ------------------- + + Kristian Lauszus, TKJ Electronics + Web : http://www.tkjelectronics.com + e-mail : kristianl@tkjelectronics.com + */ + +#include "XBOXOLD.h" +// To enable serial debugging see "settings.h" +//#define EXTRADEBUG // Uncomment to get even more debugging data +//#define PRINTREPORT // Uncomment to print the report send by the Xbox controller + +/** Buttons on the controllers */ +const uint8_t XBOXOLD_BUTTONS[] PROGMEM = { + 0x01, // UP + 0x08, // RIGHT + 0x02, // DOWN + 0x04, // LEFT + + 0x20, // BACK + 0x10, // START + 0x40, // L3 + 0x80, // R3 + + // A, B, X, Y, BLACK, WHITE, L1, and R1 are analog buttons + 4, // BLACK + 5, // WHTIE + 6, // L1 + 7, // R1 + + 1, // B + 0, // A + 2, // X + 3, // Y +}; + +XBOXOLD::XBOXOLD(USB *p) : +pUsb(p), // pointer to USB class instance - mandatory +bAddress(0), // device address - mandatory +bPollEnable(false) { // don't start polling before dongle is connected + for(uint8_t i = 0; i < XBOX_MAX_ENDPOINTS; i++) { + epInfo[i].epAddr = 0; + epInfo[i].maxPktSize = (i) ? 0 : 8; + epInfo[i].epAttribs = 0; + epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; + } + + if(pUsb) // register in USB subsystem + pUsb->RegisterDeviceClass(this); //set devConfig[] entry +} + +uint8_t XBOXOLD::Init(uint8_t parent, uint8_t port, bool lowspeed) { + uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)]; + USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + uint16_t PID; + uint16_t VID; + + // get memory address of USB device address pool + AddressPool &addrPool = pUsb->GetAddressPool(); +#ifdef EXTRADEBUG + Notify(PSTR("\r\nXBOXUSB Init"), 0x80); +#endif + // check if address has already been assigned to an instance + if(bAddress) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nAddress in use"), 0x80); +#endif + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; + } + + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); + + if(!p) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nAddress not found"), 0x80); +#endif + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + } + + if(!p->epinfo) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nepinfo is null"), 0x80); +#endif + return USB_ERROR_EPINFO_IS_NULL; + } + + // Save old pointer to EP_RECORD of address 0 + oldep_ptr = p->epinfo; + + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence + p->epinfo = epInfo; + + p->lowspeed = lowspeed; + + // Get device descriptor + rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data + // Restore p->epinfo + p->epinfo = oldep_ptr; + + if(rcode) + goto FailGetDevDescr; + + VID = udd->idVendor; + PID = udd->idProduct; + + if((VID != XBOX_VID && VID != MADCATZ_VID && VID != JOYTECH_VID) || (PID != XBOX_OLD_PID1 && PID != XBOX_OLD_PID2 && PID != XBOX_OLD_PID3 && PID != XBOX_OLD_PID4)) // Check if VID and PID match + goto FailUnknownDevice; + + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, false, port); + + if(!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + // Extract Max Packet Size from device descriptor + epInfo[0].maxPktSize = udd->bMaxPacketSize0; + + // Assign new address to the device + rcode = pUsb->setAddr(0, 0, bAddress); + if(rcode) { + p->lowspeed = false; + addrPool.FreeAddress(bAddress); + bAddress = 0; +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nsetAddr: "), 0x80); + D_PrintHex (rcode, 0x80); +#endif + return rcode; + } +#ifdef EXTRADEBUG + Notify(PSTR("\r\nAddr: "), 0x80); + D_PrintHex (bAddress, 0x80); +#endif + //delay(300); // Spec says you should wait at least 200ms + + p->lowspeed = false; + + //get pointer to assigned address record + p = addrPool.GetUsbDevicePtr(bAddress); + if(!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->lowspeed = lowspeed; + + // Assign epInfo to epinfo pointer - only EP0 is known + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); + if(rcode) + goto FailSetDevTblEntry; + + /* The application will work in reduced host mode, so we can save program and data + memory space. After verifying the VID we will use known values for the + configuration values for device, interface, endpoints and HID for the XBOX controllers */ + + /* Initialize data structures for endpoints of device */ + epInfo[ XBOX_INPUT_PIPE ].epAddr = 0x01; // XBOX report endpoint + epInfo[ XBOX_INPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; + epInfo[ XBOX_INPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints + epInfo[ XBOX_INPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; + epInfo[ XBOX_INPUT_PIPE ].bmSndToggle = 0; + epInfo[ XBOX_INPUT_PIPE ].bmRcvToggle = 0; + epInfo[ XBOX_OUTPUT_PIPE ].epAddr = 0x02; // XBOX output endpoint + epInfo[ XBOX_OUTPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; + epInfo[ XBOX_OUTPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints + epInfo[ XBOX_OUTPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; + epInfo[ XBOX_OUTPUT_PIPE ].bmSndToggle = 0; + epInfo[ XBOX_OUTPUT_PIPE ].bmRcvToggle = 0; + + rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo); + if(rcode) + goto FailSetDevTblEntry; + + delay(200); // Give time for address change + + rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1); + if(rcode) + goto FailSetConfDescr; + +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nXbox Controller Connected\r\n"), 0x80); +#endif + if(pFuncOnInit) + pFuncOnInit(); // Call the user function + XboxConnected = true; + bPollEnable = true; + return 0; // Successful configuration + + /* Diagnostic messages */ +FailGetDevDescr: +#ifdef DEBUG_USB_HOST + NotifyFailGetDevDescr(); + goto Fail; +#endif + +FailSetDevTblEntry: +#ifdef DEBUG_USB_HOST + NotifyFailSetDevTblEntry(); + goto Fail; +#endif + +FailSetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailSetConfDescr(); +#endif + goto Fail; + +FailUnknownDevice: +#ifdef DEBUG_USB_HOST + NotifyFailUnknownDevice(VID, PID); +#endif + rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + +Fail: +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nXbox Init Failed, error code: "), 0x80); + NotifyFail(rcode); +#endif + Release(); + return rcode; +} + +/* Performs a cleanup after failed Init() attempt */ +uint8_t XBOXOLD::Release() { + XboxConnected = false; + pUsb->GetAddressPool().FreeAddress(bAddress); + bAddress = 0; + bPollEnable = false; + return 0; +} + +uint8_t XBOXOLD::Poll() { + if(!bPollEnable) + return 0; + uint16_t BUFFER_SIZE = EP_MAXPKTSIZE; + pUsb->inTransfer(bAddress, epInfo[ XBOX_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf); // input on endpoint 1 + readReport(); +#ifdef PRINTREPORT + printReport(BUFFER_SIZE); // Uncomment "#define PRINTREPORT" to print the report send by the Xbox controller +#endif + return 0; +} + +void XBOXOLD::readReport() { + ButtonState = readBuf[2]; + + for(uint8_t i = 0; i < sizeof (buttonValues); i++) + buttonValues[i] = readBuf[i + 4]; // A, B, X, Y, BLACK, WHITE, L1, and R1 + + hatValue[LeftHatX] = (int16_t)(((uint16_t)readBuf[12] << 8) | readBuf[13]); + hatValue[LeftHatY] = (int16_t)(((uint16_t)readBuf[14] << 8) | readBuf[15]); + hatValue[RightHatX] = (int16_t)(((uint16_t)readBuf[16] << 8) | readBuf[17]); + hatValue[RightHatY] = (int16_t)(((uint16_t)readBuf[18] << 8) | readBuf[19]); + + //Notify(PSTR("\r\nButtonState"), 0x80); + //PrintHex(ButtonState, 0x80); + + if(ButtonState != OldButtonState || memcmp(buttonValues, oldButtonValues, sizeof (buttonValues)) != 0) { + ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable + OldButtonState = ButtonState; + + for(uint8_t i = 0; i < sizeof (buttonValues); i++) { + if(oldButtonValues[i] == 0 && buttonValues[i] != 0) + buttonClicked[i] = true; // Update A, B, X, Y, BLACK, WHITE, L1, and R1 click state + oldButtonValues[i] = buttonValues[i]; + } + } +} + +void XBOXOLD::printReport(uint16_t length) { //Uncomment "#define PRINTREPORT" to print the report send by the Xbox controller +#ifdef PRINTREPORT + if(readBuf == NULL) + return; + for(uint8_t i = 0; i < length; i++) { + D_PrintHex (readBuf[i], 0x80); + Notify(PSTR(" "), 0x80); + } + Notify(PSTR("\r\n"), 0x80); +#endif +} + +uint8_t XBOXOLD::getButtonPress(ButtonEnum b) { + uint8_t button = pgm_read_byte(&XBOXOLD_BUTTONS[(uint8_t)b]); + if(b == A || b == B || b == X || b == Y || b == BLACK || b == WHITE || b == L1 || b == R1) // A, B, X, Y, BLACK, WHITE, L1, and R1 are analog buttons + return buttonValues[button]; // Analog buttons + return (ButtonState & button); // Digital buttons +} + +bool XBOXOLD::getButtonClick(ButtonEnum b) { + uint8_t button = pgm_read_byte(&XBOXOLD_BUTTONS[(uint8_t)b]); + if(b == A || b == B || b == X || b == Y || b == BLACK || b == WHITE || b == L1 || b == R1) { // A, B, X, Y, BLACK, WHITE, L1, and R1 are analog buttons + if(buttonClicked[button]) { + buttonClicked[button] = false; + return true; + } + return false; + } + + bool click = (ButtonClickState & button); + ButtonClickState &= ~button; // clear "click" event + return click; +} + +int16_t XBOXOLD::getAnalogHat(AnalogHatEnum a) { + return hatValue[a]; +} + +/* Xbox Controller commands */ +void XBOXOLD::XboxCommand(uint8_t* data, uint16_t nbytes) { + //bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x00), Report Type (Output 0x02), interface (0x00), datalength, datalength, data) + pUsb->ctrlReq(bAddress, epInfo[XBOX_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x00, 0x02, 0x00, nbytes, nbytes, data, NULL); +} + +void XBOXOLD::setRumbleOn(uint8_t lValue, uint8_t rValue) { + uint8_t writeBuf[6]; + + writeBuf[0] = 0x00; + writeBuf[1] = 0x06; + writeBuf[2] = 0x00; + writeBuf[3] = rValue; // small weight + writeBuf[4] = 0x00; + writeBuf[5] = lValue; // big weight + + XboxCommand(writeBuf, 6); +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/XBOXOLD.h b/lib/usbhost/USB_Host_Shield_2.0/XBOXOLD.h new file mode 100644 index 0000000000..9a36b5ccac --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/XBOXOLD.h @@ -0,0 +1,185 @@ +/* Copyright (C) 2013 Kristian Lauszus, TKJ Electronics. All rights reserved. + + This software may be distributed and modified under the terms of the GNU + General Public License version 2 (GPL2) as published by the Free Software + Foundation and appearing in the file GPL2.TXT included in the packaging of + this file. Please note that GPL2 Section 2[b] requires that all works based + on this software must also be made publicly available under the terms of + the GPL2 ("Copyleft"). + + Contact information + ------------------- + + Kristian Lauszus, TKJ Electronics + Web : http://www.tkjelectronics.com + e-mail : kristianl@tkjelectronics.com + */ + +#ifndef _xboxold_h_ +#define _xboxold_h_ + +#include "Usb.h" +#include "hid.h" +#include "controllerEnums.h" + +/* Data Xbox taken from descriptors */ +#define EP_MAXPKTSIZE 32 // Max size for data via USB + +/* Names we give to the 3 Xbox pipes */ +#define XBOX_CONTROL_PIPE 0 +#define XBOX_INPUT_PIPE 1 +#define XBOX_OUTPUT_PIPE 2 + +// PID and VID of the different devices +#define XBOX_VID 0x045E // Microsoft Corporation +#define MADCATZ_VID 0x1BAD // For unofficial Mad Catz controllers +#define JOYTECH_VID 0x162E // For unofficial Joytech controllers + +#define XBOX_OLD_PID1 0x0202 // Original Microsoft Xbox controller (US) +#define XBOX_OLD_PID2 0x0285 // Original Microsoft Xbox controller (Japan) +#define XBOX_OLD_PID3 0x0287 // Microsoft Microsoft Xbox Controller S +#define XBOX_OLD_PID4 0x0289 // Smaller Microsoft Xbox controller (US) + +#define XBOX_MAX_ENDPOINTS 3 + +/** This class implements support for a the original Xbox controller via USB. */ +class XBOXOLD : public USBDeviceConfig { +public: + /** + * Constructor for the XBOXOLD class. + * @param pUsb Pointer to USB class instance. + */ + XBOXOLD(USB *pUsb); + + /** @name USBDeviceConfig implementation */ + /** + * Initialize the Xbox Controller. + * @param parent Hub number. + * @param port Port number on the hub. + * @param lowspeed Speed of the device. + * @return 0 on success. + */ + uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + /** + * Release the USB device. + * @return 0 on success. + */ + uint8_t Release(); + /** + * Poll the USB Input endpoins and run the state machines. + * @return 0 on success. + */ + uint8_t Poll(); + + /** + * Get the device address. + * @return The device address. + */ + virtual uint8_t GetAddress() { + return bAddress; + }; + + /** + * Used to check if the controller has been initialized. + * @return True if it's ready. + */ + virtual bool isReady() { + return bPollEnable; + }; + + /** + * Used by the USB core to check what this driver support. + * @param vid The device's VID. + * @param pid The device's PID. + * @return Returns true if the device's VID and PID matches this driver. + */ + virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) { + return ((vid == XBOX_VID || vid == MADCATZ_VID || vid == JOYTECH_VID) && (pid == XBOX_OLD_PID1 || pid == XBOX_OLD_PID2 || pid == XBOX_OLD_PID3 || pid == XBOX_OLD_PID4)); + }; + /**@}*/ + + /** @name Xbox Controller functions */ + /** + * getButtonPress(ButtonEnum b) will return true as long as the button is held down. + * + * While getButtonClick(ButtonEnum b) will only return it once. + * + * So you instance if you need to increase a variable once you would use getButtonClick(ButtonEnum b), + * but if you need to drive a robot forward you would use getButtonPress(ButtonEnum b). + * @param b ::ButtonEnum to read. + * @return getButtonClick(ButtonEnum b) will return a bool, while getButtonPress(ButtonEnum b) will return a byte if reading ::L2 or ::R2. + */ + uint8_t getButtonPress(ButtonEnum b); + bool getButtonClick(ButtonEnum b); + /**@}*/ + + /** @name Xbox Controller functions */ + /** + * Return the analog value from the joysticks on the controller. + * @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY. + * @return Returns a signed 16-bit integer. + */ + int16_t getAnalogHat(AnalogHatEnum a); + + /** Turn rumble off the controller. */ + void setRumbleOff() { + setRumbleOn(0, 0); + }; + /** + * Turn rumble on. + * @param lValue Left motor (big weight) inside the controller. + * @param rValue Right motor (small weight) inside the controller. + */ + void setRumbleOn(uint8_t lValue, uint8_t rValue); + + /** + * Used to call your own function when the controller is successfully initialized. + * @param funcOnInit Function to call. + */ + void attachOnInit(void (*funcOnInit)(void)) { + pFuncOnInit = funcOnInit; + }; + /**@}*/ + + /** True if a Xbox controller is connected. */ + bool XboxConnected; + +protected: + /** Pointer to USB class instance. */ + USB *pUsb; + /** Device address. */ + uint8_t bAddress; + /** Endpoint info structure. */ + EpInfo epInfo[XBOX_MAX_ENDPOINTS]; + +private: + /** + * Called when the controller is successfully initialized. + * Use attachOnInit(void (*funcOnInit)(void)) to call your own function. + * This is useful for instance if you want to set the LEDs in a specific way. + */ + void (*pFuncOnInit)(void); // Pointer to function called in onInit() + + bool bPollEnable; + + /* Variables to store the digital buttons */ + uint8_t ButtonState; + uint8_t OldButtonState; + uint8_t ButtonClickState; + + /* Variables to store the analog buttons */ + uint8_t buttonValues[8]; // A, B, X, Y, BLACK, WHITE, L1, and R1 + uint8_t oldButtonValues[8]; + bool buttonClicked[8]; + + int16_t hatValue[4]; // Joystick values + + uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data + + void readReport(); // Read incoming data + void printReport(uint16_t length); // Print incoming date + + /* Private commands */ + void XboxCommand(uint8_t* data, uint16_t nbytes); +}; +#endif diff --git a/lib/usbhost/USB_Host_Shield_2.0/XBOXONE.cpp b/lib/usbhost/USB_Host_Shield_2.0/XBOXONE.cpp new file mode 100644 index 0000000000..2159c0528b --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/XBOXONE.cpp @@ -0,0 +1,374 @@ +/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. + Copyright (C) 2015 guruthree + + This software may be distributed and modified under the terms of the GNU + General Public License version 2 (GPL2) as published by the Free Software + Foundation and appearing in the file GPL2.TXT included in the packaging of + this file. Please note that GPL2 Section 2[b] requires that all works based + on this software must also be made publicly available under the terms of + the GPL2 ("Copyleft"). + + Contact information + ------------------- + + Kristian Lauszus, TKJ Electronics + Web : http://www.tkjelectronics.com + e-mail : kristianl@tkjelectronics.com + + guruthree + Web : https://github.com/guruthree/ + */ + +#include "XBOXONE.h" +// To enable serial debugging see "settings.h" +//#define EXTRADEBUG // Uncomment to get even more debugging data +//#define PRINTREPORT // Uncomment to print the report send by the Xbox ONE Controller + +XBOXONE::XBOXONE(USB *p) : +pUsb(p), // pointer to USB class instance - mandatory +bAddress(0), // device address - mandatory +bPollEnable(false) { // don't start polling before dongle is connected + for(uint8_t i = 0; i < XBOX_MAX_ENDPOINTS; i++) { + epInfo[i].epAddr = 0; + epInfo[i].maxPktSize = (i) ? 0 : 8; + epInfo[i].epAttribs = 0; + epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; + } + + if(pUsb) // register in USB subsystem + pUsb->RegisterDeviceClass(this); //set devConfig[] entry +} + +uint8_t XBOXONE::Init(uint8_t parent, uint8_t port, bool lowspeed) { + uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)]; + USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + uint16_t PID; + uint16_t VID; + + // get memory address of USB device address pool + AddressPool &addrPool = pUsb->GetAddressPool(); +#ifdef EXTRADEBUG + Notify(PSTR("\r\nXBOXONE Init"), 0x80); +#endif + // check if address has already been assigned to an instance + if(bAddress) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nAddress in use"), 0x80); +#endif + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; + } + + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); + + if(!p) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nAddress not found"), 0x80); +#endif + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + } + + if(!p->epinfo) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nepinfo is null"), 0x80); +#endif + return USB_ERROR_EPINFO_IS_NULL; + } + + // Save old pointer to EP_RECORD of address 0 + oldep_ptr = p->epinfo; + + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence + p->epinfo = epInfo; + + p->lowspeed = lowspeed; + + // Get device descriptor + rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data + // Restore p->epinfo + p->epinfo = oldep_ptr; + + if(rcode) + goto FailGetDevDescr; + + VID = udd->idVendor; + PID = udd->idProduct; + + if(!VIDPIDOK(VID, PID)) // Check VID + goto FailUnknownDevice; + + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, false, port); + + if(!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + // Extract Max Packet Size from device descriptor + epInfo[0].maxPktSize = udd->bMaxPacketSize0; + + // Assign new address to the device + rcode = pUsb->setAddr(0, 0, bAddress); + if(rcode) { + p->lowspeed = false; + addrPool.FreeAddress(bAddress); + bAddress = 0; +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nsetAddr: "), 0x80); + D_PrintHex (rcode, 0x80); +#endif + return rcode; + } +#ifdef EXTRADEBUG + Notify(PSTR("\r\nAddr: "), 0x80); + D_PrintHex (bAddress, 0x80); +#endif + //delay(300); // Spec says you should wait at least 200ms + + p->lowspeed = false; + + //get pointer to assigned address record + p = addrPool.GetUsbDevicePtr(bAddress); + if(!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->lowspeed = lowspeed; + + // Assign epInfo to epinfo pointer - only EP0 is known + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); + if(rcode) + goto FailSetDevTblEntry; + + /* The application will work in reduced host mode, so we can save program and data + memory space. After verifying the VID we will use known values for the + configuration values for device, interface, endpoints and HID for the XBOXONE Controllers */ + + /* Initialize data structures for endpoints of device */ + epInfo[ XBOX_OUTPUT_PIPE ].epAddr = 0x01; // XBOX one output endpoint + epInfo[ XBOX_OUTPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; + epInfo[ XBOX_OUTPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints + epInfo[ XBOX_OUTPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; + epInfo[ XBOX_OUTPUT_PIPE ].bmSndToggle = 0; + epInfo[ XBOX_OUTPUT_PIPE ].bmRcvToggle = 0; + epInfo[ XBOX_INPUT_PIPE ].epAddr = 0x01; // XBOX one input endpoint + epInfo[ XBOX_INPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; + epInfo[ XBOX_INPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints + epInfo[ XBOX_INPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; + epInfo[ XBOX_INPUT_PIPE ].bmSndToggle = 0; + epInfo[ XBOX_INPUT_PIPE ].bmRcvToggle = 0; + + rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo); + if(rcode) + goto FailSetDevTblEntry; + + delay(200); // Give time for address change + + rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1); + if(rcode) + goto FailSetConfDescr; + +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nXbox One Controller Connected\r\n"), 0x80); +#endif + + delay(200); // let things settle + + // initialize the controller for input + writeBuf[0] = 0x05; + writeBuf[1] = 0x20; + rcode = XboxCommand(writeBuf, 2); + if (rcode) + goto Fail; + + onInit(); + XboxOneConnected = true; + bPollEnable = true; + return 0; // Successful configuration + + /* Diagnostic messages */ +FailGetDevDescr: +#ifdef DEBUG_USB_HOST + NotifyFailGetDevDescr(); + goto Fail; +#endif + +FailSetDevTblEntry: +#ifdef DEBUG_USB_HOST + NotifyFailSetDevTblEntry(); + goto Fail; +#endif + +FailSetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailSetConfDescr(); +#endif + goto Fail; + +FailUnknownDevice: +#ifdef DEBUG_USB_HOST + NotifyFailUnknownDevice(VID, PID); +#endif + rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + +Fail: +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nXbox One Init Failed, error code: "), 0x80); + NotifyFail(rcode); +#endif + Release(); + return rcode; +} + +/* Performs a cleanup after failed Init() attempt */ +uint8_t XBOXONE::Release() { + XboxOneConnected = false; + pUsb->GetAddressPool().FreeAddress(bAddress); + bAddress = 0; + bPollEnable = false; +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nXbox One Controller Disconnected\r\n"), 0x80); +#endif + return 0; +} + +uint8_t XBOXONE::Poll() { + if(!bPollEnable) + return 0; + uint16_t BUFFER_SIZE = EP_MAXPKTSIZE; + uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[ XBOX_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf); + if (!rcode) { + readReport(); +#ifdef PRINTREPORT + printReport(); // Uncomment "#define PRINTREPORT" to print the report send by the Xbox ONE Controller +#endif + } +#ifdef DEBUG_USB_HOST + else if (rcode != 0x04) { // not a matter of no update to send + Notify(PSTR("\r\nXbox One Poll Failed, error code: "), 0x80); + NotifyFail(rcode); + } +#endif + return rcode; +} + +void XBOXONE::readReport() { + if(readBuf == NULL) + return; + if(readBuf[0] == 0x07) { + // The XBOX button has a separate message + if(readBuf[4] == 1) + ButtonState |= XBOX_BUTTONS[XBOX]; + else + ButtonState &= ~XBOX_BUTTONS[XBOX]; + } + if(readBuf[0] != 0x20) { // Check if it's the correct report, otherwise return - the controller also sends different status reports +#ifdef EXTRADEBUG + Notify(PSTR("\r\nXbox Poll: "), 0x80); + D_PrintHex (readBuf[0], 0x80); // 0x03 is a heart beat report! +#endif + return; + } + + uint16_t xbox = ButtonState & XBOX_BUTTONS[XBOX]; // Since the XBOX button is separate, save it and add it back in + // xbox button from before, dpad, abxy, start/back, sync, stick click, shoulder buttons + ButtonState = xbox | (((uint16_t)readBuf[5] & 0xF) << 8) | (readBuf[4] & 0xF0) | (((uint16_t)readBuf[4] & 0x0C) << 10) | ((readBuf[4] & 0x01) << 3) | (((uint16_t)readBuf[5] & 0xC0) << 8) | ((readBuf[5] & 0x30) >> 4); + + triggerValue[0] = (uint16_t)(((uint16_t)readBuf[7] << 8) | readBuf[6]); + triggerValue[1] = (uint16_t)(((uint16_t)readBuf[9] << 8) | readBuf[8]); + + hatValue[LeftHatX] = (int16_t)(((uint16_t)readBuf[11] << 8) | readBuf[10]); + hatValue[LeftHatY] = (int16_t)(((uint16_t)readBuf[13] << 8) | readBuf[12]); + hatValue[RightHatX] = (int16_t)(((uint16_t)readBuf[15] << 8) | readBuf[14]); + hatValue[RightHatY] = (int16_t)(((uint16_t)readBuf[17] << 8) | readBuf[16]); + + //Notify(PSTR("\r\nButtonState"), 0x80); + //PrintHex(ButtonState, 0x80); + + if(ButtonState != OldButtonState) { + ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable + OldButtonState = ButtonState; + } + + // Handle click detection for triggers + if(triggerValue[0] != 0 && triggerValueOld[0] == 0) + L2Clicked = true; + triggerValueOld[0] = triggerValue[0]; + if(triggerValue[1] != 0 && triggerValueOld[1] == 0) + R2Clicked = true; + triggerValueOld[1] = triggerValue[1]; +} + +void XBOXONE::printReport() { //Uncomment "#define PRINTREPORT" to print the report send by the Xbox ONE Controller +#ifdef PRINTREPORT + if(readBuf == NULL) + return; + for(uint8_t i = 0; i < XBOX_REPORT_BUFFER_SIZE; i++) { + D_PrintHex (readBuf[i], 0x80); + Notify(PSTR(" "), 0x80); + } + Notify(PSTR("\r\n"), 0x80); +#endif +} + +uint16_t XBOXONE::getButtonPress(ButtonEnum b) { + if(b == L2) // These are analog buttons + return triggerValue[0]; + else if(b == R2) + return triggerValue[1]; + return (bool)(ButtonState & ((uint16_t)pgm_read_word(&XBOX_BUTTONS[(uint8_t)b]))); +} + +bool XBOXONE::getButtonClick(ButtonEnum b) { + if(b == L2) { + if(L2Clicked) { + L2Clicked = false; + return true; + } + return false; + } else if(b == R2) { + if(R2Clicked) { + R2Clicked = false; + return true; + } + return false; + } + uint16_t button = pgm_read_word(&XBOX_BUTTONS[(uint8_t)b]); + bool click = (ButtonClickState & button); + ButtonClickState &= ~button; // clear "click" event + return click; +} + +int16_t XBOXONE::getAnalogHat(AnalogHatEnum a) { + return hatValue[a]; +} + +/* Xbox Controller commands */ +uint8_t XBOXONE::XboxCommand(uint8_t* data, uint16_t nbytes) { + uint8_t rcode = pUsb->outTransfer(bAddress, epInfo[ XBOX_OUTPUT_PIPE ].epAddr, nbytes, data); +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nXboxCommand, Return: "), 0x80); + D_PrintHex (rcode, 0x80); +#endif + return rcode; +} + +void XBOXONE::onInit() { + // a short buzz to show the controller is active + writeBuf[0] = 0x09; + writeBuf[1] = 0x08; + writeBuf[2] = 0x00; + writeBuf[3] = 0x09; + writeBuf[4] = 0x00; + writeBuf[5] = 0x0f; + writeBuf[6] = 0x04; + writeBuf[7] = 0x04; + writeBuf[8] = 0x20; + writeBuf[9] = 0x20; + writeBuf[10] = 0x80; + XboxCommand(writeBuf, 11); + + if(pFuncOnInit) + pFuncOnInit(); // Call the user function +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/XBOXONE.h b/lib/usbhost/USB_Host_Shield_2.0/XBOXONE.h new file mode 100644 index 0000000000..11710fcf1a --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/XBOXONE.h @@ -0,0 +1,172 @@ +/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. + Copyright (C) 2015 guruthree + + This software may be distributed and modified under the terms of the GNU + General Public License version 2 (GPL2) as published by the Free Software + Foundation and appearing in the file GPL2.TXT included in the packaging of + this file. Please note that GPL2 Section 2[b] requires that all works based + on this software must also be made publicly available under the terms of + the GPL2 ("Copyleft"). + + Contact information + ------------------- + + Kristian Lauszus, TKJ Electronics + Web : http://www.tkjelectronics.com + e-mail : kristianl@tkjelectronics.com + + guruthree + Web : https://github.com/guruthree/ + */ + + +#ifndef _xboxone_h_ +#define _xboxone_h_ + +#include "Usb.h" +#include "xboxEnums.h" + +/* Data Xbox ONE taken from descriptors */ +#define EP_MAXPKTSIZE 32 // max size for data via USB + +/* Names we give to the 3 XboxONE pipes */ +#define XBOX_CONTROL_PIPE 0 +#define XBOX_OUTPUT_PIPE 1 +#define XBOX_INPUT_PIPE 2 + +// PID and VID of the different devices +#define XBOX_VID 0x045E // Microsoft Corporation +#define XBOX_ONE_PID 0x02D1 // Microsoft One Wired controller + +#define XBOX_REPORT_BUFFER_SIZE 14 // Size of the input report buffer + +#define XBOX_MAX_ENDPOINTS 3 + +/** This class implements support for a Xbox ONE controller connected via USB. */ +class XBOXONE : public USBDeviceConfig { +public: + /** + * Constructor for the XBOXONE class. + * @param pUsb Pointer to USB class instance. + */ + XBOXONE(USB *pUsb); + + /** @name USBDeviceConfig implementation */ + /** + * Initialize the Xbox Controller. + * @param parent Hub number. + * @param port Port number on the hub. + * @param lowspeed Speed of the device. + * @return 0 on success. + */ + virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + /** + * Release the USB device. + * @return 0 on success. + */ + virtual uint8_t Release(); + /** + * Poll the USB Input endpoins and run the state machines. + * @return 0 on success. + */ + virtual uint8_t Poll(); + + /** + * Get the device address. + * @return The device address. + */ + virtual uint8_t GetAddress() { + return bAddress; + }; + + /** + * Used to check if the controller has been initialized. + * @return True if it's ready. + */ + virtual bool isReady() { + return bPollEnable; + }; + + /** + * Used by the USB core to check what this driver support. + * @param vid The device's VID. + * @param pid The device's PID. + * @return Returns true if the device's VID and PID matches this driver. + */ + virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) { + return (vid == XBOX_VID && pid == XBOX_ONE_PID); + }; + /**@}*/ + + /** @name Xbox Controller functions */ + /** + * getButtonPress(ButtonEnum b) will return true as long as the button is held down. + * + * While getButtonClick(ButtonEnum b) will only return it once. + * + * So you instance if you need to increase a variable once you would use getButtonClick(ButtonEnum b), + * but if you need to drive a robot forward you would use getButtonPress(ButtonEnum b). + * @param b ::ButtonEnum to read. + * @return getButtonClick(ButtonEnum b) will return a bool, while getButtonPress(ButtonEnum b) will return a word if reading ::L2 or ::R2. + */ + uint16_t getButtonPress(ButtonEnum b); + bool getButtonClick(ButtonEnum b); + + /** + * Return the analog value from the joysticks on the controller. + * @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY. + * @return Returns a signed 16-bit integer. + */ + int16_t getAnalogHat(AnalogHatEnum a); + + /** + * Used to call your own function when the controller is successfully initialized. + * @param funcOnInit Function to call. + */ + void attachOnInit(void (*funcOnInit)(void)) { + pFuncOnInit = funcOnInit; + }; + /**@}*/ + + /** True if a Xbox ONE controller is connected. */ + bool XboxOneConnected; + +protected: + /** Pointer to USB class instance. */ + USB *pUsb; + /** Device address. */ + uint8_t bAddress; + /** Endpoint info structure. */ + EpInfo epInfo[XBOX_MAX_ENDPOINTS]; + +private: + /** + * Called when the controller is successfully initialized. + * Use attachOnInit(void (*funcOnInit)(void)) to call your own function. + */ + void onInit(); + void (*pFuncOnInit)(void); // Pointer to function called in onInit() + + bool bPollEnable; + + /* Variables to store the buttons */ + uint16_t ButtonState; + uint16_t OldButtonState; + uint16_t ButtonClickState; + int16_t hatValue[4]; + uint16_t triggerValue[2]; + uint16_t triggerValueOld[2]; + + bool L2Clicked; // These buttons are analog, so we use we use these bools to check if they where clicked or not + bool R2Clicked; + + uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data + uint8_t writeBuf[12]; // General purpose buffer for output data + + void readReport(); // read incoming data + void printReport(); // print incoming date - Uncomment for debugging + + /* Private commands */ + uint8_t XboxCommand(uint8_t* data, uint16_t nbytes); +}; +#endif diff --git a/lib/usbhost/USB_Host_Shield_2.0/XBOXRECV.cpp b/lib/usbhost/USB_Host_Shield_2.0/XBOXRECV.cpp new file mode 100644 index 0000000000..41f1ff5816 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/XBOXRECV.cpp @@ -0,0 +1,583 @@ +/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. + + This software may be distributed and modified under the terms of the GNU + General Public License version 2 (GPL2) as published by the Free Software + Foundation and appearing in the file GPL2.TXT included in the packaging of + this file. Please note that GPL2 Section 2[b] requires that all works based + on this software must also be made publicly available under the terms of + the GPL2 ("Copyleft"). + + Contact information + ------------------- + + Kristian Lauszus, TKJ Electronics + Web : http://www.tkjelectronics.com + e-mail : kristianl@tkjelectronics.com + + getBatteryLevel and checkStatus functions made by timstamp.co.uk found using BusHound from Perisoft.net + */ + +#include "XBOXRECV.h" +// To enable serial debugging see "settings.h" +//#define EXTRADEBUG // Uncomment to get even more debugging data +//#define PRINTREPORT // Uncomment to print the report send by the Xbox 360 Controller + +XBOXRECV::XBOXRECV(USB *p) : +pUsb(p), // pointer to USB class instance - mandatory +bAddress(0), // device address - mandatory +bPollEnable(false) { // don't start polling before dongle is connected + for(uint8_t i = 0; i < XBOX_MAX_ENDPOINTS; i++) { + epInfo[i].epAddr = 0; + epInfo[i].maxPktSize = (i) ? 0 : 8; + epInfo[i].epAttribs = 0; + epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; + } + + if(pUsb) // register in USB subsystem + pUsb->RegisterDeviceClass(this); //set devConfig[] entry +} + +uint8_t XBOXRECV::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) { + const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR); + uint8_t buf[constBufSize]; + USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + uint16_t PID, VID; + + AddressPool &addrPool = pUsb->GetAddressPool(); // Get memory address of USB device address pool +#ifdef EXTRADEBUG + Notify(PSTR("\r\nXBOXRECV Init"), 0x80); +#endif + + if(bAddress) { // Check if address has already been assigned to an instance +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nAddress in use"), 0x80); +#endif + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; + } + + p = addrPool.GetUsbDevicePtr(0); // Get pointer to pseudo device with address 0 assigned + + if(!p) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nAddress not found"), 0x80); +#endif + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + } + + if(!p->epinfo) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nepinfo is null"), 0x80); +#endif + return USB_ERROR_EPINFO_IS_NULL; + } + + oldep_ptr = p->epinfo; // Save old pointer to EP_RECORD of address 0 + p->epinfo = epInfo; // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence + p->lowspeed = lowspeed; + + rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data + + p->epinfo = oldep_ptr; // Restore p->epinfo + + if(rcode) + goto FailGetDevDescr; + + VID = udd->idVendor; + PID = udd->idProduct; + + if((VID != XBOX_VID && VID != MADCATZ_VID && VID != JOYTECH_VID) || (PID != XBOX_WIRELESS_RECEIVER_PID && PID != XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID)) { // Check if it's a Xbox receiver using the Vendor ID and Product ID +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nYou'll need a wireless receiver for this libary to work"), 0x80); +#endif + goto FailUnknownDevice; + } + + bAddress = addrPool.AllocAddress(parent, false, port); // Allocate new address according to device class + + if(!bAddress) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nOut of address space"), 0x80); +#endif + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + } + + epInfo[0].maxPktSize = udd->bMaxPacketSize0; // Extract Max Packet Size from device descriptor + + delay(20); // Wait a little before resetting device + + return USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET; + + /* Diagnostic messages */ +FailGetDevDescr: +#ifdef DEBUG_USB_HOST + NotifyFailGetDevDescr(rcode); +#endif + if(rcode != hrJERR) + rcode = USB_ERROR_FailGetDevDescr; + goto Fail; + +FailUnknownDevice: +#ifdef DEBUG_USB_HOST + NotifyFailUnknownDevice(VID, PID); +#endif + rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + +Fail: +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nXbox 360 Init Failed, error code: "), 0x80); + NotifyFail(rcode); +#endif + Release(); + return rcode; +}; + +uint8_t XBOXRECV::Init(uint8_t parent, uint8_t port, bool lowspeed) { + uint8_t rcode; + + AddressPool &addrPool = pUsb->GetAddressPool(); +#ifdef EXTRADEBUG + Notify(PSTR("\r\nBTD Init"), 0x80); +#endif + UsbDevice *p = addrPool.GetUsbDevicePtr(bAddress); // Get pointer to assigned address record + + if(!p) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nAddress not found"), 0x80); +#endif + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + } + + delay(300); // Assign new address to the device + + rcode = pUsb->setAddr(0, 0, bAddress); // Assign new address to the device + if(rcode) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nsetAddr: "), 0x80); + D_PrintHex (rcode, 0x80); +#endif + p->lowspeed = false; + goto Fail; + } +#ifdef EXTRADEBUG + Notify(PSTR("\r\nAddr: "), 0x80); + D_PrintHex (bAddress, 0x80); +#endif + + p->lowspeed = false; + + p = addrPool.GetUsbDevicePtr(bAddress); // Get pointer to assigned address record + if(!p) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nAddress not found"), 0x80); +#endif + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + } + + p->lowspeed = lowspeed; + + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); // Assign epInfo to epinfo pointer - only EP0 is known + if(rcode) + goto FailSetDevTblEntry; + + /* The application will work in reduced host mode, so we can save program and data + memory space. After verifying the VID we will use known values for the + configuration values for device, interface, endpoints and HID for the XBOX360 Wireless receiver */ + + /* Initialize data structures for endpoints of device */ + epInfo[ XBOX_INPUT_PIPE_1 ].epAddr = 0x01; // XBOX 360 report endpoint - poll interval 1ms + epInfo[ XBOX_INPUT_PIPE_1 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; + epInfo[ XBOX_INPUT_PIPE_1 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints + epInfo[ XBOX_INPUT_PIPE_1 ].maxPktSize = EP_MAXPKTSIZE; + epInfo[ XBOX_INPUT_PIPE_1 ].bmSndToggle = 0; + epInfo[ XBOX_INPUT_PIPE_1 ].bmRcvToggle = 0; + epInfo[ XBOX_OUTPUT_PIPE_1 ].epAddr = 0x01; // XBOX 360 output endpoint - poll interval 8ms + epInfo[ XBOX_OUTPUT_PIPE_1 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; + epInfo[ XBOX_OUTPUT_PIPE_1 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints + epInfo[ XBOX_OUTPUT_PIPE_1 ].maxPktSize = EP_MAXPKTSIZE; + epInfo[ XBOX_OUTPUT_PIPE_1 ].bmSndToggle = 0; + epInfo[ XBOX_OUTPUT_PIPE_1 ].bmRcvToggle = 0; + + epInfo[ XBOX_INPUT_PIPE_2 ].epAddr = 0x03; // XBOX 360 report endpoint - poll interval 1ms + epInfo[ XBOX_INPUT_PIPE_2 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; + epInfo[ XBOX_INPUT_PIPE_2 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints + epInfo[ XBOX_INPUT_PIPE_2 ].maxPktSize = EP_MAXPKTSIZE; + epInfo[ XBOX_INPUT_PIPE_2 ].bmSndToggle = 0; + epInfo[ XBOX_INPUT_PIPE_2 ].bmRcvToggle = 0; + epInfo[ XBOX_OUTPUT_PIPE_2 ].epAddr = 0x03; // XBOX 360 output endpoint - poll interval 8ms + epInfo[ XBOX_OUTPUT_PIPE_2 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; + epInfo[ XBOX_OUTPUT_PIPE_2 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints + epInfo[ XBOX_OUTPUT_PIPE_2 ].maxPktSize = EP_MAXPKTSIZE; + epInfo[ XBOX_OUTPUT_PIPE_2 ].bmSndToggle = 0; + epInfo[ XBOX_OUTPUT_PIPE_2 ].bmRcvToggle = 0; + + epInfo[ XBOX_INPUT_PIPE_3 ].epAddr = 0x05; // XBOX 360 report endpoint - poll interval 1ms + epInfo[ XBOX_INPUT_PIPE_3 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; + epInfo[ XBOX_INPUT_PIPE_3 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints + epInfo[ XBOX_INPUT_PIPE_3 ].maxPktSize = EP_MAXPKTSIZE; + epInfo[ XBOX_INPUT_PIPE_3 ].bmSndToggle = 0; + epInfo[ XBOX_INPUT_PIPE_3 ].bmRcvToggle = 0; + epInfo[ XBOX_OUTPUT_PIPE_3 ].epAddr = 0x05; // XBOX 360 output endpoint - poll interval 8ms + epInfo[ XBOX_OUTPUT_PIPE_3 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; + epInfo[ XBOX_OUTPUT_PIPE_3 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints + epInfo[ XBOX_OUTPUT_PIPE_3 ].maxPktSize = EP_MAXPKTSIZE; + epInfo[ XBOX_OUTPUT_PIPE_3 ].bmSndToggle = 0; + epInfo[ XBOX_OUTPUT_PIPE_3 ].bmRcvToggle = 0; + + epInfo[ XBOX_INPUT_PIPE_4 ].epAddr = 0x07; // XBOX 360 report endpoint - poll interval 1ms + epInfo[ XBOX_INPUT_PIPE_4 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; + epInfo[ XBOX_INPUT_PIPE_4 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints + epInfo[ XBOX_INPUT_PIPE_4 ].maxPktSize = EP_MAXPKTSIZE; + epInfo[ XBOX_INPUT_PIPE_4 ].bmSndToggle = 0; + epInfo[ XBOX_INPUT_PIPE_4 ].bmRcvToggle = 0; + epInfo[ XBOX_OUTPUT_PIPE_4 ].epAddr = 0x07; // XBOX 360 output endpoint - poll interval 8ms + epInfo[ XBOX_OUTPUT_PIPE_4 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; + epInfo[ XBOX_OUTPUT_PIPE_4 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints + epInfo[ XBOX_OUTPUT_PIPE_4 ].maxPktSize = EP_MAXPKTSIZE; + epInfo[ XBOX_OUTPUT_PIPE_4 ].bmSndToggle = 0; + epInfo[ XBOX_OUTPUT_PIPE_4 ].bmRcvToggle = 0; + + rcode = pUsb->setEpInfoEntry(bAddress, 9, epInfo); + if(rcode) + goto FailSetDevTblEntry; + + delay(200); //Give time for address change + + rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1); + if(rcode) + goto FailSetConfDescr; + +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nXbox Wireless Receiver Connected\r\n"), 0x80); +#endif + XboxReceiverConnected = true; + bPollEnable = true; + checkStatusTimer = 0; // Reset timer + return 0; // Successful configuration + + /* Diagnostic messages */ +FailSetDevTblEntry: +#ifdef DEBUG_USB_HOST + NotifyFailSetDevTblEntry(); + goto Fail; +#endif + +FailSetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailSetConfDescr(); +#endif + +Fail: +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nXbox 360 Init Failed, error code: "), 0x80); + NotifyFail(rcode); +#endif + Release(); + return rcode; +} + +/* Performs a cleanup after failed Init() attempt */ +uint8_t XBOXRECV::Release() { + XboxReceiverConnected = false; + for(uint8_t i = 0; i < 4; i++) + Xbox360Connected[i] = 0x00; + pUsb->GetAddressPool().FreeAddress(bAddress); + bAddress = 0; + bPollEnable = false; + return 0; +} + +uint8_t XBOXRECV::Poll() { + if(!bPollEnable) + return 0; + if(!checkStatusTimer || ((millis() - checkStatusTimer) > 3000)) { // Run checkStatus every 3 seconds + checkStatusTimer = millis(); + checkStatus(); + } + + uint8_t inputPipe; + uint16_t bufferSize; + for(uint8_t i = 0; i < 4; i++) { + if(i == 0) + inputPipe = XBOX_INPUT_PIPE_1; + else if(i == 1) + inputPipe = XBOX_INPUT_PIPE_2; + else if(i == 2) + inputPipe = XBOX_INPUT_PIPE_3; + else + inputPipe = XBOX_INPUT_PIPE_4; + + bufferSize = EP_MAXPKTSIZE; // This is the maximum number of bytes we want to receive + pUsb->inTransfer(bAddress, epInfo[ inputPipe ].epAddr, &bufferSize, readBuf); + if(bufferSize > 0) { // The number of received bytes +#ifdef EXTRADEBUG + Notify(PSTR("Bytes Received: "), 0x80); + D_PrintHex (bufferSize, 0x80); + Notify(PSTR("\r\n"), 0x80); +#endif + readReport(i); +#ifdef PRINTREPORT + printReport(i, bufferSize); // Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller +#endif + } + } + return 0; +} + +void XBOXRECV::readReport(uint8_t controller) { + if(readBuf == NULL) + return; + // This report is send when a controller is connected and disconnected + if(readBuf[0] == 0x08 && readBuf[1] != Xbox360Connected[controller]) { + Xbox360Connected[controller] = readBuf[1]; +#ifdef DEBUG_USB_HOST + Notify(PSTR("Controller "), 0x80); + Notify(controller, 0x80); +#endif + if(Xbox360Connected[controller]) { +#ifdef DEBUG_USB_HOST + const char* str = 0; + switch(readBuf[1]) { + case 0x80: str = PSTR(" as controller\r\n"); + break; + case 0x40: str = PSTR(" as headset\r\n"); + break; + case 0xC0: str = PSTR(" as controller+headset\r\n"); + break; + } + Notify(PSTR(": connected"), 0x80); + Notify(str, 0x80); +#endif + onInit(controller); + } +#ifdef DEBUG_USB_HOST + else + Notify(PSTR(": disconnected\r\n"), 0x80); +#endif + return; + } + // Controller status report + if(readBuf[1] == 0x00 && readBuf[3] & 0x13 && readBuf[4] >= 0x22) { + controllerStatus[controller] = ((uint16_t)readBuf[3] << 8) | readBuf[4]; + return; + } + if(readBuf[1] != 0x01) // Check if it's the correct report - the receiver also sends different status reports + return; + + // A controller must be connected if it's sending data + if(!Xbox360Connected[controller]) + Xbox360Connected[controller] |= 0x80; + + ButtonState[controller] = (uint32_t)(readBuf[9] | ((uint16_t)readBuf[8] << 8) | ((uint32_t)readBuf[7] << 16) | ((uint32_t)readBuf[6] << 24)); + + hatValue[controller][LeftHatX] = (int16_t)(((uint16_t)readBuf[11] << 8) | readBuf[10]); + hatValue[controller][LeftHatY] = (int16_t)(((uint16_t)readBuf[13] << 8) | readBuf[12]); + hatValue[controller][RightHatX] = (int16_t)(((uint16_t)readBuf[15] << 8) | readBuf[14]); + hatValue[controller][RightHatY] = (int16_t)(((uint16_t)readBuf[17] << 8) | readBuf[16]); + + //Notify(PSTR("\r\nButtonState: "), 0x80); + //PrintHex(ButtonState[controller], 0x80); + + if(ButtonState[controller] != OldButtonState[controller]) { + buttonStateChanged[controller] = true; + ButtonClickState[controller] = (ButtonState[controller] >> 16) & ((~OldButtonState[controller]) >> 16); // Update click state variable, but don't include the two trigger buttons L2 and R2 + if(((uint8_t)OldButtonState[controller]) == 0 && ((uint8_t)ButtonState[controller]) != 0) // The L2 and R2 buttons are special as they are analog buttons + R2Clicked[controller] = true; + if((uint8_t)(OldButtonState[controller] >> 8) == 0 && (uint8_t)(ButtonState[controller] >> 8) != 0) + L2Clicked[controller] = true; + OldButtonState[controller] = ButtonState[controller]; + } +} + +void XBOXRECV::printReport(uint8_t controller, uint8_t nBytes) { //Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller +#ifdef PRINTREPORT + if(readBuf == NULL) + return; + Notify(PSTR("Controller "), 0x80); + Notify(controller, 0x80); + Notify(PSTR(": "), 0x80); + for(uint8_t i = 0; i < nBytes; i++) { + D_PrintHex (readBuf[i], 0x80); + Notify(PSTR(" "), 0x80); + } + Notify(PSTR("\r\n"), 0x80); +#endif +} + +uint8_t XBOXRECV::getButtonPress(ButtonEnum b, uint8_t controller) { + if(b == L2) // These are analog buttons + return (uint8_t)(ButtonState[controller] >> 8); + else if(b == R2) + return (uint8_t)ButtonState[controller]; + return (bool)(ButtonState[controller] & ((uint32_t)pgm_read_word(&XBOX_BUTTONS[(uint8_t)b]) << 16)); +} + +bool XBOXRECV::getButtonClick(ButtonEnum b, uint8_t controller) { + if(b == L2) { + if(L2Clicked[controller]) { + L2Clicked[controller] = false; + return true; + } + return false; + } else if(b == R2) { + if(R2Clicked[controller]) { + R2Clicked[controller] = false; + return true; + } + return false; + } + uint16_t button = pgm_read_word(&XBOX_BUTTONS[(uint8_t)b]); + bool click = (ButtonClickState[controller] & button); + ButtonClickState[controller] &= ~button; // clear "click" event + return click; +} + +int16_t XBOXRECV::getAnalogHat(AnalogHatEnum a, uint8_t controller) { + return hatValue[controller][a]; +} + +bool XBOXRECV::buttonChanged(uint8_t controller) { + bool state = buttonStateChanged[controller]; + buttonStateChanged[controller] = false; + return state; +} + +/* +ControllerStatus Breakdown +ControllerStatus[controller] & 0x0001 // 0 +ControllerStatus[controller] & 0x0002 // normal batteries, no rechargeable battery pack +ControllerStatus[controller] & 0x0004 // controller starting up / settling +ControllerStatus[controller] & 0x0008 // headset adapter plugged in, but no headphones connected (mute?) +ControllerStatus[controller] & 0x0010 // 0 +ControllerStatus[controller] & 0x0020 // 1 +ControllerStatus[controller] & 0x0040 // battery level (high bit) +ControllerStatus[controller] & 0x0080 // battery level (low bit) +ControllerStatus[controller] & 0x0100 // 1 +ControllerStatus[controller] & 0x0200 // 1 +ControllerStatus[controller] & 0x0400 // headset adapter plugged in +ControllerStatus[controller] & 0x0800 // 0 +ControllerStatus[controller] & 0x1000 // 1 +ControllerStatus[controller] & 0x2000 // 0 +ControllerStatus[controller] & 0x4000 // 0 +ControllerStatus[controller] & 0x8000 // 0 + */ +uint8_t XBOXRECV::getBatteryLevel(uint8_t controller) { + return ((controllerStatus[controller] & 0x00C0) >> 6); +} + +void XBOXRECV::XboxCommand(uint8_t controller, uint8_t* data, uint16_t nbytes) { +#ifdef EXTRADEBUG + uint8_t rcode; +#endif + uint8_t outputPipe; + switch(controller) { + case 0: outputPipe = XBOX_OUTPUT_PIPE_1; + break; + case 1: outputPipe = XBOX_OUTPUT_PIPE_2; + break; + case 2: outputPipe = XBOX_OUTPUT_PIPE_3; + break; + case 3: outputPipe = XBOX_OUTPUT_PIPE_4; + break; + default: + return; + } +#ifdef EXTRADEBUG + rcode = +#endif + pUsb->outTransfer(bAddress, epInfo[ outputPipe ].epAddr, nbytes, data); +#ifdef EXTRADEBUG + if(rcode) + Notify(PSTR("Error sending Xbox message\r\n"), 0x80); +#endif +} + +void XBOXRECV::disconnect(uint8_t controller) { + writeBuf[0] = 0x00; + writeBuf[1] = 0x00; + writeBuf[2] = 0x08; + writeBuf[3] = 0xC0; + + XboxCommand(controller, writeBuf, 4); +} + +void XBOXRECV::setLedRaw(uint8_t value, uint8_t controller) { + writeBuf[0] = 0x00; + writeBuf[1] = 0x00; + writeBuf[2] = 0x08; + writeBuf[3] = value | 0x40; + + XboxCommand(controller, writeBuf, 4); +} + +void XBOXRECV::setLedOn(LEDEnum led, uint8_t controller) { + if(led == OFF) + setLedRaw(0, controller); + else if(led != ALL) // All LEDs can't be on a the same time + setLedRaw(pgm_read_byte(&XBOX_LEDS[(uint8_t)led]) + 4, controller); +} + +void XBOXRECV::setLedBlink(LEDEnum led, uint8_t controller) { + setLedRaw(pgm_read_byte(&XBOX_LEDS[(uint8_t)led]), controller); +} + +void XBOXRECV::setLedMode(LEDModeEnum ledMode, uint8_t controller) { // This function is used to do some speciel LED stuff the controller supports + setLedRaw((uint8_t)ledMode, controller); +} + +/* PC runs this at interval of approx 2 seconds +Thanks to BusHound from Perisoft.net for the Windows USB Analysis output +Found by timstamp.co.uk + */ +void XBOXRECV::checkStatus() { + if(!bPollEnable) + return; + // Get controller info + writeBuf[0] = 0x08; + writeBuf[1] = 0x00; + writeBuf[2] = 0x0f; + writeBuf[3] = 0xc0; + for(uint8_t i = 0; i < 4; i++) { + XboxCommand(i, writeBuf, 4); + } + // Get battery status + writeBuf[0] = 0x00; + writeBuf[1] = 0x00; + writeBuf[2] = 0x00; + writeBuf[3] = 0x40; + for(uint8_t i = 0; i < 4; i++) { + if(Xbox360Connected[i]) + XboxCommand(i, writeBuf, 4); + } +} + +void XBOXRECV::setRumbleOn(uint8_t lValue, uint8_t rValue, uint8_t controller) { + writeBuf[0] = 0x00; + writeBuf[1] = 0x01; + writeBuf[2] = 0x0f; + writeBuf[3] = 0xc0; + writeBuf[4] = 0x00; + writeBuf[5] = lValue; // big weight + writeBuf[6] = rValue; // small weight + + XboxCommand(controller, writeBuf, 7); +} + +void XBOXRECV::onInit(uint8_t controller) { + if(pFuncOnInit) + pFuncOnInit(); // Call the user function + else { + LEDEnum led; + if(controller == 0) + led = LED1; + else if(controller == 1) + led = LED2; + else if(controller == 2) + led = LED3; + else + led = LED4; + setLedOn(led, controller); + } +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/XBOXRECV.h b/lib/usbhost/USB_Host_Shield_2.0/XBOXRECV.h new file mode 100644 index 0000000000..4f9214653c --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/XBOXRECV.h @@ -0,0 +1,276 @@ +/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. + + This software may be distributed and modified under the terms of the GNU + General Public License version 2 (GPL2) as published by the Free Software + Foundation and appearing in the file GPL2.TXT included in the packaging of + this file. Please note that GPL2 Section 2[b] requires that all works based + on this software must also be made publicly available under the terms of + the GPL2 ("Copyleft"). + + Contact information + ------------------- + + Kristian Lauszus, TKJ Electronics + Web : http://www.tkjelectronics.com + e-mail : kristianl@tkjelectronics.com + + getBatteryLevel and checkStatus functions made by timstamp.co.uk found using BusHound from Perisoft.net + */ + +#ifndef _xboxrecv_h_ +#define _xboxrecv_h_ + +#include "Usb.h" +#include "xboxEnums.h" + +/* Data Xbox 360 taken from descriptors */ +#define EP_MAXPKTSIZE 32 // max size for data via USB + +/* Names we give to the 9 Xbox360 pipes */ +#define XBOX_CONTROL_PIPE 0 +#define XBOX_INPUT_PIPE_1 1 +#define XBOX_OUTPUT_PIPE_1 2 +#define XBOX_INPUT_PIPE_2 3 +#define XBOX_OUTPUT_PIPE_2 4 +#define XBOX_INPUT_PIPE_3 5 +#define XBOX_OUTPUT_PIPE_3 6 +#define XBOX_INPUT_PIPE_4 7 +#define XBOX_OUTPUT_PIPE_4 8 + +// PID and VID of the different devices +#define XBOX_VID 0x045E // Microsoft Corporation +#define MADCATZ_VID 0x1BAD // For unofficial Mad Catz receivers +#define JOYTECH_VID 0x162E // For unofficial Joytech controllers + +#define XBOX_WIRELESS_RECEIVER_PID 0x0719 // Microsoft Wireless Gaming Receiver +#define XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID 0x0291 // Third party Wireless Gaming Receiver + +#define XBOX_MAX_ENDPOINTS 9 + +/** + * This class implements support for a Xbox Wireless receiver. + * + * Up to four controllers can connect to one receiver, if more is needed one can use a second receiver via the USBHub class. + */ +class XBOXRECV : public USBDeviceConfig { +public: + /** + * Constructor for the XBOXRECV class. + * @param pUsb Pointer to USB class instance. + */ + XBOXRECV(USB *pUsb); + + /** @name USBDeviceConfig implementation */ + /** + * Address assignment and basic initilization is done here. + * @param parent Hub number. + * @param port Port number on the hub. + * @param lowspeed Speed of the device. + * @return 0 on success. + */ + uint8_t ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed); + /** + * Initialize the Xbox wireless receiver. + * @param parent Hub number. + * @param port Port number on the hub. + * @param lowspeed Speed of the device. + * @return 0 on success. + */ + uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + /** + * Release the USB device. + * @return 0 on success. + */ + uint8_t Release(); + /** + * Poll the USB Input endpoins and run the state machines. + * @return 0 on success. + */ + uint8_t Poll(); + + /** + * Get the device address. + * @return The device address. + */ + virtual uint8_t GetAddress() { + return bAddress; + }; + + /** + * Used to check if the controller has been initialized. + * @return True if it's ready. + */ + virtual bool isReady() { + return bPollEnable; + }; + + /** + * Used by the USB core to check what this driver support. + * @param vid The device's VID. + * @param pid The device's PID. + * @return Returns true if the device's VID and PID matches this driver. + */ + virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) { + return ((vid == XBOX_VID || vid == MADCATZ_VID || vid == JOYTECH_VID) && (pid == XBOX_WIRELESS_RECEIVER_PID || pid == XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID)); + }; + /**@}*/ + + /** @name Xbox Controller functions */ + /** + * getButtonPress(uint8_t controller, ButtonEnum b) will return true as long as the button is held down. + * + * While getButtonClick(uint8_t controller, ButtonEnum b) will only return it once. + * + * So you instance if you need to increase a variable once you would use getButtonClick(uint8_t controller, ButtonEnum b), + * but if you need to drive a robot forward you would use getButtonPress(uint8_t controller, ButtonEnum b). + * @param b ::ButtonEnum to read. + * @param controller The controller to read from. Default to 0. + * @return getButtonClick(uint8_t controller, ButtonEnum b) will return a bool, while getButtonPress(uint8_t controller, ButtonEnum b) will return a byte if reading ::L2 or ::R2. + */ + uint8_t getButtonPress(ButtonEnum b, uint8_t controller = 0); + bool getButtonClick(ButtonEnum b, uint8_t controller = 0); + /**@}*/ + + /** @name Xbox Controller functions */ + /** + * Return the analog value from the joysticks on the controller. + * @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY. + * @param controller The controller to read from. Default to 0. + * @return Returns a signed 16-bit integer. + */ + int16_t getAnalogHat(AnalogHatEnum a, uint8_t controller = 0); + + /** + * Used to disconnect any of the controllers. + * @param controller The controller to disconnect. Default to 0. + */ + void disconnect(uint8_t controller = 0); + + /** + * Turn rumble off and all the LEDs on the specific controller. + * @param controller The controller to write to. Default to 0. + */ + void setAllOff(uint8_t controller = 0) { + setRumbleOn(0, 0, controller); + setLedOff(controller); + }; + + /** + * Turn rumble off the specific controller. + * @param controller The controller to write to. Default to 0. + */ + void setRumbleOff(uint8_t controller = 0) { + setRumbleOn(0, 0, controller); + }; + /** + * Turn rumble on. + * @param lValue Left motor (big weight) inside the controller. + * @param rValue Right motor (small weight) inside the controller. + * @param controller The controller to write to. Default to 0. + */ + void setRumbleOn(uint8_t lValue, uint8_t rValue, uint8_t controller = 0); + /** + * Set LED value. Without using the ::LEDEnum or ::LEDModeEnum. + * @param value See: + * setLedOff(uint8_t controller), setLedOn(uint8_t controller, LED l), + * setLedBlink(uint8_t controller, LED l), and setLedMode(uint8_t controller, LEDMode lm). + * @param controller The controller to write to. Default to 0. + */ + void setLedRaw(uint8_t value, uint8_t controller = 0); + + /** + * Turn all LEDs off the specific controller. + * @param controller The controller to write to. Default to 0. + */ + void setLedOff(uint8_t controller = 0) { + setLedRaw(0, controller); + }; + /** + * Turn on a LED by using ::LEDEnum. + * @param l ::OFF, ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller. + * @param controller The controller to write to. Default to 0. + */ + void setLedOn(LEDEnum l, uint8_t controller = 0); + /** + * Turn on a LED by using ::LEDEnum. + * @param l ::ALL, ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller. + * @param controller The controller to write to. Default to 0. + */ + void setLedBlink(LEDEnum l, uint8_t controller = 0); + /** + * Used to set special LED modes supported by the Xbox controller. + * @param lm See ::LEDModeEnum. + * @param controller The controller to write to. Default to 0. + */ + void setLedMode(LEDModeEnum lm, uint8_t controller = 0); + /** + * Used to get the battery level from the controller. + * @param controller The controller to read from. Default to 0. + * @return Returns the battery level as an integer in the range of 0-3. + */ + uint8_t getBatteryLevel(uint8_t controller = 0); + /** + * Used to check if a button has changed. + * @param controller The controller to read from. Default to 0. + * @return True if a button has changed. + */ + bool buttonChanged(uint8_t controller = 0); + + /** + * Used to call your own function when the controller is successfully initialized. + * @param funcOnInit Function to call. + */ + void attachOnInit(void (*funcOnInit)(void)) { + pFuncOnInit = funcOnInit; + }; + /**@}*/ + + /** True if a wireless receiver is connected. */ + bool XboxReceiverConnected; + /** Variable used to indicate if the XBOX 360 controller is successfully connected. */ + uint8_t Xbox360Connected[4]; + +protected: + /** Pointer to USB class instance. */ + USB *pUsb; + /** Device address. */ + uint8_t bAddress; + /** Endpoint info structure. */ + EpInfo epInfo[XBOX_MAX_ENDPOINTS]; + +private: + /** + * Called when the controller is successfully initialized. + * Use attachOnInit(void (*funcOnInit)(void)) to call your own function. + * This is useful for instance if you want to set the LEDs in a specific way. + * @param controller The initialized controller. + */ + void onInit(uint8_t controller); + void (*pFuncOnInit)(void); // Pointer to function called in onInit() + + bool bPollEnable; + + /* Variables to store the buttons */ + uint32_t ButtonState[4]; + uint32_t OldButtonState[4]; + uint16_t ButtonClickState[4]; + int16_t hatValue[4][4]; + uint16_t controllerStatus[4]; + bool buttonStateChanged[4]; // True if a button has changed + + bool L2Clicked[4]; // These buttons are analog, so we use we use these bools to check if they where clicked or not + bool R2Clicked[4]; + + uint32_t checkStatusTimer; // Timing for checkStatus() signals + + uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data + uint8_t writeBuf[7]; // General purpose buffer for output data + + void readReport(uint8_t controller); // read incoming data + void printReport(uint8_t controller, uint8_t nBytes); // print incoming date - Uncomment for debugging + + /* Private commands */ + void XboxCommand(uint8_t controller, uint8_t* data, uint16_t nbytes); + void checkStatus(); +}; +#endif diff --git a/lib/usbhost/USB_Host_Shield_2.0/XBOXUSB.cpp b/lib/usbhost/USB_Host_Shield_2.0/XBOXUSB.cpp new file mode 100644 index 0000000000..ddece21b45 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/XBOXUSB.cpp @@ -0,0 +1,361 @@ +/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. + + This software may be distributed and modified under the terms of the GNU + General Public License version 2 (GPL2) as published by the Free Software + Foundation and appearing in the file GPL2.TXT included in the packaging of + this file. Please note that GPL2 Section 2[b] requires that all works based + on this software must also be made publicly available under the terms of + the GPL2 ("Copyleft"). + + Contact information + ------------------- + + Kristian Lauszus, TKJ Electronics + Web : http://www.tkjelectronics.com + e-mail : kristianl@tkjelectronics.com + */ + +#include "XBOXUSB.h" +// To enable serial debugging see "settings.h" +//#define EXTRADEBUG // Uncomment to get even more debugging data +//#define PRINTREPORT // Uncomment to print the report send by the Xbox 360 Controller + +XBOXUSB::XBOXUSB(USB *p) : +pUsb(p), // pointer to USB class instance - mandatory +bAddress(0), // device address - mandatory +bPollEnable(false) { // don't start polling before dongle is connected + for(uint8_t i = 0; i < XBOX_MAX_ENDPOINTS; i++) { + epInfo[i].epAddr = 0; + epInfo[i].maxPktSize = (i) ? 0 : 8; + epInfo[i].epAttribs = 0; + epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; + } + + if(pUsb) // register in USB subsystem + pUsb->RegisterDeviceClass(this); //set devConfig[] entry +} + +uint8_t XBOXUSB::Init(uint8_t parent, uint8_t port, bool lowspeed) { + uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)]; + USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + uint16_t PID; + uint16_t VID; + + // get memory address of USB device address pool + AddressPool &addrPool = pUsb->GetAddressPool(); +#ifdef EXTRADEBUG + Notify(PSTR("\r\nXBOXUSB Init"), 0x80); +#endif + // check if address has already been assigned to an instance + if(bAddress) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nAddress in use"), 0x80); +#endif + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; + } + + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); + + if(!p) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nAddress not found"), 0x80); +#endif + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + } + + if(!p->epinfo) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nepinfo is null"), 0x80); +#endif + return USB_ERROR_EPINFO_IS_NULL; + } + + // Save old pointer to EP_RECORD of address 0 + oldep_ptr = p->epinfo; + + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence + p->epinfo = epInfo; + + p->lowspeed = lowspeed; + + // Get device descriptor + rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data + // Restore p->epinfo + p->epinfo = oldep_ptr; + + if(rcode) + goto FailGetDevDescr; + + VID = udd->idVendor; + PID = udd->idProduct; + + if(VID != XBOX_VID && VID != MADCATZ_VID && VID != JOYTECH_VID && VID != GAMESTOP_VID) // Check VID + goto FailUnknownDevice; + if(PID == XBOX_WIRELESS_PID) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nYou have plugged in a wireless Xbox 360 controller - it doesn't support USB communication"), 0x80); +#endif + goto FailUnknownDevice; + } else if(PID == XBOX_WIRELESS_RECEIVER_PID || PID == XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nThis library only supports Xbox 360 controllers via USB"), 0x80); +#endif + goto FailUnknownDevice; + } else if(PID != XBOX_WIRED_PID && PID != MADCATZ_WIRED_PID && PID != GAMESTOP_WIRED_PID && PID != AFTERGLOW_WIRED_PID && PID != JOYTECH_WIRED_PID) // Check PID + goto FailUnknownDevice; + + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, false, port); + + if(!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + // Extract Max Packet Size from device descriptor + epInfo[0].maxPktSize = udd->bMaxPacketSize0; + + // Assign new address to the device + rcode = pUsb->setAddr(0, 0, bAddress); + if(rcode) { + p->lowspeed = false; + addrPool.FreeAddress(bAddress); + bAddress = 0; +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nsetAddr: "), 0x80); + D_PrintHex (rcode, 0x80); +#endif + return rcode; + } +#ifdef EXTRADEBUG + Notify(PSTR("\r\nAddr: "), 0x80); + D_PrintHex (bAddress, 0x80); +#endif + //delay(300); // Spec says you should wait at least 200ms + + p->lowspeed = false; + + //get pointer to assigned address record + p = addrPool.GetUsbDevicePtr(bAddress); + if(!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->lowspeed = lowspeed; + + // Assign epInfo to epinfo pointer - only EP0 is known + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); + if(rcode) + goto FailSetDevTblEntry; + + /* The application will work in reduced host mode, so we can save program and data + memory space. After verifying the VID we will use known values for the + configuration values for device, interface, endpoints and HID for the XBOX360 Controllers */ + + /* Initialize data structures for endpoints of device */ + epInfo[ XBOX_INPUT_PIPE ].epAddr = 0x01; // XBOX 360 report endpoint + epInfo[ XBOX_INPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; + epInfo[ XBOX_INPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints + epInfo[ XBOX_INPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; + epInfo[ XBOX_INPUT_PIPE ].bmSndToggle = 0; + epInfo[ XBOX_INPUT_PIPE ].bmRcvToggle = 0; + epInfo[ XBOX_OUTPUT_PIPE ].epAddr = 0x02; // XBOX 360 output endpoint + epInfo[ XBOX_OUTPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; + epInfo[ XBOX_OUTPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints + epInfo[ XBOX_OUTPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; + epInfo[ XBOX_OUTPUT_PIPE ].bmSndToggle = 0; + epInfo[ XBOX_OUTPUT_PIPE ].bmRcvToggle = 0; + + rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo); + if(rcode) + goto FailSetDevTblEntry; + + delay(200); // Give time for address change + + rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1); + if(rcode) + goto FailSetConfDescr; + +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nXbox 360 Controller Connected\r\n"), 0x80); +#endif + onInit(); + Xbox360Connected = true; + bPollEnable = true; + return 0; // Successful configuration + + /* Diagnostic messages */ +FailGetDevDescr: +#ifdef DEBUG_USB_HOST + NotifyFailGetDevDescr(); + goto Fail; +#endif + +FailSetDevTblEntry: +#ifdef DEBUG_USB_HOST + NotifyFailSetDevTblEntry(); + goto Fail; +#endif + +FailSetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailSetConfDescr(); +#endif + goto Fail; + +FailUnknownDevice: +#ifdef DEBUG_USB_HOST + NotifyFailUnknownDevice(VID, PID); +#endif + rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + +Fail: +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nXbox 360 Init Failed, error code: "), 0x80); + NotifyFail(rcode); +#endif + Release(); + return rcode; +} + +/* Performs a cleanup after failed Init() attempt */ +uint8_t XBOXUSB::Release() { + Xbox360Connected = false; + pUsb->GetAddressPool().FreeAddress(bAddress); + bAddress = 0; + bPollEnable = false; + return 0; +} + +uint8_t XBOXUSB::Poll() { + if(!bPollEnable) + return 0; + uint16_t BUFFER_SIZE = EP_MAXPKTSIZE; + pUsb->inTransfer(bAddress, epInfo[ XBOX_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf); // input on endpoint 1 + readReport(); +#ifdef PRINTREPORT + printReport(); // Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller +#endif + return 0; +} + +void XBOXUSB::readReport() { + if(readBuf == NULL) + return; + if(readBuf[0] != 0x00 || readBuf[1] != 0x14) { // Check if it's the correct report - the controller also sends different status reports + return; + } + + ButtonState = (uint32_t)(readBuf[5] | ((uint16_t)readBuf[4] << 8) | ((uint32_t)readBuf[3] << 16) | ((uint32_t)readBuf[2] << 24)); + + hatValue[LeftHatX] = (int16_t)(((uint16_t)readBuf[7] << 8) | readBuf[6]); + hatValue[LeftHatY] = (int16_t)(((uint16_t)readBuf[9] << 8) | readBuf[8]); + hatValue[RightHatX] = (int16_t)(((uint16_t)readBuf[11] << 8) | readBuf[10]); + hatValue[RightHatY] = (int16_t)(((uint16_t)readBuf[13] << 8) | readBuf[12]); + + //Notify(PSTR("\r\nButtonState"), 0x80); + //PrintHex(ButtonState, 0x80); + + if(ButtonState != OldButtonState) { + ButtonClickState = (ButtonState >> 16) & ((~OldButtonState) >> 16); // Update click state variable, but don't include the two trigger buttons L2 and R2 + if(((uint8_t)OldButtonState) == 0 && ((uint8_t)ButtonState) != 0) // The L2 and R2 buttons are special as they are analog buttons + R2Clicked = true; + if((uint8_t)(OldButtonState >> 8) == 0 && (uint8_t)(ButtonState >> 8) != 0) + L2Clicked = true; + OldButtonState = ButtonState; + } +} + +void XBOXUSB::printReport() { //Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller +#ifdef PRINTREPORT + if(readBuf == NULL) + return; + for(uint8_t i = 0; i < XBOX_REPORT_BUFFER_SIZE; i++) { + D_PrintHex (readBuf[i], 0x80); + Notify(PSTR(" "), 0x80); + } + Notify(PSTR("\r\n"), 0x80); +#endif +} + +uint8_t XBOXUSB::getButtonPress(ButtonEnum b) { + if(b == L2) // These are analog buttons + return (uint8_t)(ButtonState >> 8); + else if(b == R2) + return (uint8_t)ButtonState; + return (bool)(ButtonState & ((uint32_t)pgm_read_word(&XBOX_BUTTONS[(uint8_t)b]) << 16)); +} + +bool XBOXUSB::getButtonClick(ButtonEnum b) { + if(b == L2) { + if(L2Clicked) { + L2Clicked = false; + return true; + } + return false; + } else if(b == R2) { + if(R2Clicked) { + R2Clicked = false; + return true; + } + return false; + } + uint16_t button = pgm_read_word(&XBOX_BUTTONS[(uint8_t)b]); + bool click = (ButtonClickState & button); + ButtonClickState &= ~button; // clear "click" event + return click; +} + +int16_t XBOXUSB::getAnalogHat(AnalogHatEnum a) { + return hatValue[a]; +} + +/* Xbox Controller commands */ +void XBOXUSB::XboxCommand(uint8_t* data, uint16_t nbytes) { + //bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x00), Report Type (Output 0x02), interface (0x00), datalength, datalength, data) + pUsb->ctrlReq(bAddress, epInfo[XBOX_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x00, 0x02, 0x00, nbytes, nbytes, data, NULL); +} + +void XBOXUSB::setLedRaw(uint8_t value) { + writeBuf[0] = 0x01; + writeBuf[1] = 0x03; + writeBuf[2] = value; + + XboxCommand(writeBuf, 3); +} + +void XBOXUSB::setLedOn(LEDEnum led) { + if(led == OFF) + setLedRaw(0); + else if(led != ALL) // All LEDs can't be on a the same time + setLedRaw(pgm_read_byte(&XBOX_LEDS[(uint8_t)led]) + 4); +} + +void XBOXUSB::setLedBlink(LEDEnum led) { + setLedRaw(pgm_read_byte(&XBOX_LEDS[(uint8_t)led])); +} + +void XBOXUSB::setLedMode(LEDModeEnum ledMode) { // This function is used to do some special LED stuff the controller supports + setLedRaw((uint8_t)ledMode); +} + +void XBOXUSB::setRumbleOn(uint8_t lValue, uint8_t rValue) { + writeBuf[0] = 0x00; + writeBuf[1] = 0x08; + writeBuf[2] = 0x00; + writeBuf[3] = lValue; // big weight + writeBuf[4] = rValue; // small weight + writeBuf[5] = 0x00; + writeBuf[6] = 0x00; + writeBuf[7] = 0x00; + + XboxCommand(writeBuf, 8); +} + +void XBOXUSB::onInit() { + if(pFuncOnInit) + pFuncOnInit(); // Call the user function + else + setLedOn(LED1); +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/XBOXUSB.h b/lib/usbhost/USB_Host_Shield_2.0/XBOXUSB.h new file mode 100644 index 0000000000..1ab37851a7 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/XBOXUSB.h @@ -0,0 +1,225 @@ +/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. + + This software may be distributed and modified under the terms of the GNU + General Public License version 2 (GPL2) as published by the Free Software + Foundation and appearing in the file GPL2.TXT included in the packaging of + this file. Please note that GPL2 Section 2[b] requires that all works based + on this software must also be made publicly available under the terms of + the GPL2 ("Copyleft"). + + Contact information + ------------------- + + Kristian Lauszus, TKJ Electronics + Web : http://www.tkjelectronics.com + e-mail : kristianl@tkjelectronics.com + */ + +#ifndef _xboxusb_h_ +#define _xboxusb_h_ + +#include "Usb.h" +#include "hid.h" +#include "xboxEnums.h" + +/* Data Xbox 360 taken from descriptors */ +#define EP_MAXPKTSIZE 32 // max size for data via USB + +/* Names we give to the 3 Xbox360 pipes */ +#define XBOX_CONTROL_PIPE 0 +#define XBOX_INPUT_PIPE 1 +#define XBOX_OUTPUT_PIPE 2 + +// PID and VID of the different devices +#define XBOX_VID 0x045E // Microsoft Corporation +#define MADCATZ_VID 0x1BAD // For unofficial Mad Catz controllers +#define JOYTECH_VID 0x162E // For unofficial Joytech controllers +#define GAMESTOP_VID 0x0E6F // Gamestop controller + +#define XBOX_WIRED_PID 0x028E // Microsoft 360 Wired controller +#define XBOX_WIRELESS_PID 0x028F // Wireless controller only support charging +#define XBOX_WIRELESS_RECEIVER_PID 0x0719 // Microsoft Wireless Gaming Receiver +#define XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID 0x0291 // Third party Wireless Gaming Receiver +#define MADCATZ_WIRED_PID 0xF016 // Mad Catz wired controller +#define JOYTECH_WIRED_PID 0xBEEF // For Joytech wired controller +#define GAMESTOP_WIRED_PID 0x0401 // Gamestop wired controller +#define AFTERGLOW_WIRED_PID 0x0213 // Afterglow wired controller - it uses the same VID as a Gamestop controller + +#define XBOX_REPORT_BUFFER_SIZE 14 // Size of the input report buffer + +#define XBOX_MAX_ENDPOINTS 3 + +/** This class implements support for a Xbox wired controller via USB. */ +class XBOXUSB : public USBDeviceConfig { +public: + /** + * Constructor for the XBOXUSB class. + * @param pUsb Pointer to USB class instance. + */ + XBOXUSB(USB *pUsb); + + /** @name USBDeviceConfig implementation */ + /** + * Initialize the Xbox Controller. + * @param parent Hub number. + * @param port Port number on the hub. + * @param lowspeed Speed of the device. + * @return 0 on success. + */ + uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + /** + * Release the USB device. + * @return 0 on success. + */ + uint8_t Release(); + /** + * Poll the USB Input endpoins and run the state machines. + * @return 0 on success. + */ + uint8_t Poll(); + + /** + * Get the device address. + * @return The device address. + */ + virtual uint8_t GetAddress() { + return bAddress; + }; + + /** + * Used to check if the controller has been initialized. + * @return True if it's ready. + */ + virtual bool isReady() { + return bPollEnable; + }; + + /** + * Used by the USB core to check what this driver support. + * @param vid The device's VID. + * @param pid The device's PID. + * @return Returns true if the device's VID and PID matches this driver. + */ + virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) { + return ((vid == XBOX_VID || vid == MADCATZ_VID || vid == JOYTECH_VID || vid == GAMESTOP_VID) && (pid == XBOX_WIRED_PID || pid == MADCATZ_WIRED_PID || pid == GAMESTOP_WIRED_PID || pid == AFTERGLOW_WIRED_PID || pid == JOYTECH_WIRED_PID)); + }; + /**@}*/ + + /** @name Xbox Controller functions */ + /** + * getButtonPress(ButtonEnum b) will return true as long as the button is held down. + * + * While getButtonClick(ButtonEnum b) will only return it once. + * + * So you instance if you need to increase a variable once you would use getButtonClick(ButtonEnum b), + * but if you need to drive a robot forward you would use getButtonPress(ButtonEnum b). + * @param b ::ButtonEnum to read. + * @return getButtonClick(ButtonEnum b) will return a bool, while getButtonPress(ButtonEnum b) will return a byte if reading ::L2 or ::R2. + */ + uint8_t getButtonPress(ButtonEnum b); + bool getButtonClick(ButtonEnum b); + /**@}*/ + + /** @name Xbox Controller functions */ + /** + * Return the analog value from the joysticks on the controller. + * @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY. + * @return Returns a signed 16-bit integer. + */ + int16_t getAnalogHat(AnalogHatEnum a); + + /** Turn rumble off and all the LEDs on the controller. */ + void setAllOff() { + setRumbleOn(0, 0); + setLedRaw(0); + }; + + /** Turn rumble off the controller. */ + void setRumbleOff() { + setRumbleOn(0, 0); + }; + /** + * Turn rumble on. + * @param lValue Left motor (big weight) inside the controller. + * @param rValue Right motor (small weight) inside the controller. + */ + void setRumbleOn(uint8_t lValue, uint8_t rValue); + /** + * Set LED value. Without using the ::LEDEnum or ::LEDModeEnum. + * @param value See: + * setLedOff(), setLedOn(LEDEnum l), + * setLedBlink(LEDEnum l), and setLedMode(LEDModeEnum lm). + */ + void setLedRaw(uint8_t value); + + /** Turn all LEDs off the controller. */ + void setLedOff() { + setLedRaw(0); + }; + /** + * Turn on a LED by using ::LEDEnum. + * @param l ::OFF, ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller. + */ + void setLedOn(LEDEnum l); + /** + * Turn on a LED by using ::LEDEnum. + * @param l ::ALL, ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller. + */ + void setLedBlink(LEDEnum l); + /** + * Used to set special LED modes supported by the Xbox controller. + * @param lm See ::LEDModeEnum. + */ + void setLedMode(LEDModeEnum lm); + + /** + * Used to call your own function when the controller is successfully initialized. + * @param funcOnInit Function to call. + */ + void attachOnInit(void (*funcOnInit)(void)) { + pFuncOnInit = funcOnInit; + }; + /**@}*/ + + /** True if a Xbox 360 controller is connected. */ + bool Xbox360Connected; + +protected: + /** Pointer to USB class instance. */ + USB *pUsb; + /** Device address. */ + uint8_t bAddress; + /** Endpoint info structure. */ + EpInfo epInfo[XBOX_MAX_ENDPOINTS]; + +private: + /** + * Called when the controller is successfully initialized. + * Use attachOnInit(void (*funcOnInit)(void)) to call your own function. + * This is useful for instance if you want to set the LEDs in a specific way. + */ + void onInit(); + void (*pFuncOnInit)(void); // Pointer to function called in onInit() + + bool bPollEnable; + + /* Variables to store the buttons */ + uint32_t ButtonState; + uint32_t OldButtonState; + uint16_t ButtonClickState; + int16_t hatValue[4]; + uint16_t controllerStatus; + + bool L2Clicked; // These buttons are analog, so we use we use these bools to check if they where clicked or not + bool R2Clicked; + + uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data + uint8_t writeBuf[8]; // General purpose buffer for output data + + void readReport(); // read incoming data + void printReport(); // print incoming date - Uncomment for debugging + + /* Private commands */ + void XboxCommand(uint8_t* data, uint16_t nbytes); +}; +#endif diff --git a/lib/usbhost/USB_Host_Shield_2.0/address.h b/lib/usbhost/USB_Host_Shield_2.0/address.h new file mode 100644 index 0000000000..c3e1b3141f --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/address.h @@ -0,0 +1,282 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ + +#if !defined(_usb_h_) || defined(__ADDRESS_H__) +#error "Never include address.h directly; include Usb.h instead" +#else +#define __ADDRESS_H__ + + + +/* NAK powers. To save space in endpoint data structure, amount of retries before giving up and returning 0x4 is stored in */ +/* bmNakPower as a power of 2. The actual nak_limit is then calculated as nak_limit = ( 2^bmNakPower - 1) */ +#define USB_NAK_MAX_POWER 15 //NAK binary order maximum value +#define USB_NAK_DEFAULT 14 //default 32K-1 NAKs before giving up +#define USB_NAK_NOWAIT 1 //Single NAK stops transfer +#define USB_NAK_NONAK 0 //Do not count NAKs, stop retrying after USB Timeout + +struct EpInfo { + uint8_t epAddr; // Endpoint address + uint8_t maxPktSize; // Maximum packet size + + union { + uint8_t epAttribs; + + struct { + uint8_t bmSndToggle : 1; // Send toggle, when zero bmSNDTOG0, bmSNDTOG1 otherwise + uint8_t bmRcvToggle : 1; // Send toggle, when zero bmRCVTOG0, bmRCVTOG1 otherwise + uint8_t bmNakPower : 6; // Binary order for NAK_LIMIT value + } __attribute__((packed)); + }; +} __attribute__((packed)); + +// 7 6 5 4 3 2 1 0 +// --------------------------------- +// | | H | P | P | P | A | A | A | +// --------------------------------- +// +// H - if 1 the address is a hub address +// P - parent hub address +// A - device address / port number in case of hub +// + +struct UsbDeviceAddress { + + union { + + struct { + uint8_t bmAddress : 3; // device address/port number + uint8_t bmParent : 3; // parent hub address + uint8_t bmHub : 1; // hub flag + uint8_t bmReserved : 1; // reserved, must be zero + } __attribute__((packed)); + uint8_t devAddress; + }; +} __attribute__((packed)); + +#define bmUSB_DEV_ADDR_ADDRESS 0x07 +#define bmUSB_DEV_ADDR_PARENT 0x38 +#define bmUSB_DEV_ADDR_HUB 0x40 + +struct UsbDevice { + EpInfo *epinfo; // endpoint info pointer + UsbDeviceAddress address; + uint8_t epcount; // number of endpoints + bool lowspeed; // indicates if a device is the low speed one + // uint8_t devclass; // device class +} __attribute__((packed)); + +class AddressPool { +public: + virtual UsbDevice* GetUsbDevicePtr(uint8_t addr) = 0; + virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0) = 0; + virtual void FreeAddress(uint8_t addr) = 0; +}; + +typedef void (*UsbDeviceHandleFunc)(UsbDevice *pdev); + +#define ADDR_ERROR_INVALID_INDEX 0xFF +#define ADDR_ERROR_INVALID_ADDRESS 0xFF + +template +class AddressPoolImpl : public AddressPool { + EpInfo dev0ep; //Endpoint data structure used during enumeration for uninitialized device + + uint8_t hubCounter; // hub counter is kept + // in order to avoid hub address duplication + + UsbDevice thePool[MAX_DEVICES_ALLOWED]; + + // Initializes address pool entry + + void InitEntry(uint8_t index) { + thePool[index].address.devAddress = 0; + thePool[index].epcount = 1; + thePool[index].lowspeed = 0; + thePool[index].epinfo = &dev0ep; + }; + + // Returns thePool index for a given address + + uint8_t FindAddressIndex(uint8_t address = 0) { + for(uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) { + if(thePool[i].address.devAddress == address) + return i; + } + return 0; + }; + + // Returns thePool child index for a given parent + + uint8_t FindChildIndex(UsbDeviceAddress addr, uint8_t start = 1) { + for(uint8_t i = (start < 1 || start >= MAX_DEVICES_ALLOWED) ? 1 : start; i < MAX_DEVICES_ALLOWED; i++) { + if(thePool[i].address.bmParent == addr.bmAddress) + return i; + } + return 0; + }; + + // Frees address entry specified by index parameter + + void FreeAddressByIndex(uint8_t index) { + // Zero field is reserved and should not be affected + if(index == 0) + return; + + UsbDeviceAddress uda = thePool[index].address; + // If a hub was switched off all port addresses should be freed + if(uda.bmHub == 1) { + for(uint8_t i = 1; (i = FindChildIndex(uda, i));) + FreeAddressByIndex(i); + + // If the hub had the last allocated address, hubCounter should be decremented + if(hubCounter == uda.bmAddress) + hubCounter--; + } + InitEntry(index); + } + + // Initializes the whole address pool at once + + void InitAllAddresses() { + for(uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) + InitEntry(i); + + hubCounter = 0; + }; + +public: + + AddressPoolImpl() : hubCounter(0) { + // Zero address is reserved + InitEntry(0); + + thePool[0].address.devAddress = 0; + thePool[0].epinfo = &dev0ep; + dev0ep.epAddr = 0; + dev0ep.maxPktSize = 8; + dev0ep.epAttribs = 0; //set DATA0/1 toggles to 0 + dev0ep.bmNakPower = USB_NAK_MAX_POWER; + + InitAllAddresses(); + }; + + // Returns a pointer to a specified address entry + + virtual UsbDevice* GetUsbDevicePtr(uint8_t addr) { + if(!addr) + return thePool; + + uint8_t index = FindAddressIndex(addr); + + return (!index) ? NULL : thePool + index; + }; + + // Performs an operation specified by pfunc for each addressed device + + void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) { + if(!pfunc) + return; + + for(uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) + if(thePool[i].address.devAddress) + pfunc(thePool + i); + }; + + // Allocates new address + + virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0) { + /* if (parent != 0 && port == 0) + USB_HOST_SERIAL.println("PRT:0"); */ + UsbDeviceAddress _parent; + _parent.devAddress = parent; + if(_parent.bmReserved || port > 7) + //if(parent > 127 || port > 7) + return 0; + + if(is_hub && hubCounter == 7) + return 0; + + // finds first empty address entry starting from one + uint8_t index = FindAddressIndex(0); + + if(!index) // if empty entry is not found + return 0; + + if(_parent.devAddress == 0) { + if(is_hub) { + thePool[index].address.devAddress = 0x41; + hubCounter++; + } else + thePool[index].address.devAddress = 1; + + return thePool[index].address.devAddress; + } + + UsbDeviceAddress addr; + addr.devAddress = 0; // Ensure all bits are zero + addr.bmParent = _parent.bmAddress; + if(is_hub) { + addr.bmHub = 1; + addr.bmAddress = ++hubCounter; + } else { + addr.bmHub = 0; + addr.bmAddress = port; + } + thePool[index].address = addr; + /* + USB_HOST_SERIAL.print("Addr:"); + USB_HOST_SERIAL.print(addr.bmHub, HEX); + USB_HOST_SERIAL.print("."); + USB_HOST_SERIAL.print(addr.bmParent, HEX); + USB_HOST_SERIAL.print("."); + USB_HOST_SERIAL.println(addr.bmAddress, HEX); + */ + return thePool[index].address.devAddress; + }; + + // Empties pool entry + + virtual void FreeAddress(uint8_t addr) { + // if the root hub is disconnected all the addresses should be initialized + if(addr == 0x41) { + InitAllAddresses(); + return; + } + uint8_t index = FindAddressIndex(addr); + FreeAddressByIndex(index); + }; + + // Returns number of hubs attached + // It can be rather helpfull to find out if there are hubs attached than getting the exact number of hubs. + //uint8_t GetNumHubs() + //{ + // return hubCounter; + //}; + //uint8_t GetNumDevices() + //{ + // uint8_t counter = 0; + + // for (uint8_t i=1; iRegisterDeviceClass(this); //set devConfig[] entry + } +} + +uint8_t ADK::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) { + return Init(parent, port, lowspeed); // Just call Init. Yes, really! +} + +/* Connection initialization of an Android phone */ +uint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed) { + uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)]; + USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); + uint8_t rcode; + uint8_t num_of_conf; // number of configurations + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + + // get memory address of USB device address pool + AddressPool &addrPool = pUsb->GetAddressPool(); + + USBTRACE("\r\nADK Init"); + + // check if address has already been assigned to an instance + if(bAddress) { + USBTRACE("\r\nAddress in use"); + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; + } + + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); + + if(!p) { + USBTRACE("\r\nAddress not found"); + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + } + + if(!p->epinfo) { + USBTRACE("epinfo is null\r\n"); + return USB_ERROR_EPINFO_IS_NULL; + } + + // Save old pointer to EP_RECORD of address 0 + oldep_ptr = p->epinfo; + + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence + p->epinfo = epInfo; + + p->lowspeed = lowspeed; + + // Get device descriptor + rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); + + // Restore p->epinfo + p->epinfo = oldep_ptr; + + if(rcode) { + goto FailGetDevDescr; + } + + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, false, port); + + // Extract Max Packet Size from device descriptor + epInfo[0].maxPktSize = udd->bMaxPacketSize0; + + // Assign new address to the device + rcode = pUsb->setAddr(0, 0, bAddress); + if(rcode) { + p->lowspeed = false; + addrPool.FreeAddress(bAddress); + bAddress = 0; + //USBTRACE2("setAddr:",rcode); + return rcode; + }//if (rcode... + + //USBTRACE2("\r\nAddr:", bAddress); + // Spec says you should wait at least 200ms. + //delay(300); + + p->lowspeed = false; + + //get pointer to assigned address record + p = addrPool.GetUsbDevicePtr(bAddress); + if(!p) { + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + } + + p->lowspeed = lowspeed; + + // Assign epInfo to epinfo pointer - only EP0 is known + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); + if(rcode) { + goto FailSetDevTblEntry; + } + + //check if ADK device is already in accessory mode; if yes, configure and exit + if(udd->idVendor == ADK_VID && + (udd->idProduct == ADK_PID || udd->idProduct == ADB_PID)) { + USBTRACE("\r\nAcc.mode device detected"); + /* go through configurations, find first bulk-IN, bulk-OUT EP, fill epInfo and quit */ + num_of_conf = udd->bNumConfigurations; + + //USBTRACE2("\r\nNC:",num_of_conf); + for(uint8_t i = 0; i < num_of_conf; i++) { + ConfigDescParser < 0, 0, 0, 0 > confDescrParser(this); + delay(1); + rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); +#if defined(XOOM) + //added by Jaylen Scott Vanorden + if(rcode) { + USBTRACE2("\r\nGot 1st bad code for config: ", rcode); + // Try once more + rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); + } +#endif + if(rcode) { + goto FailGetConfDescr; + } + if(bNumEP > 2) { + break; + } + } // for (uint8_t i=0; isetEpInfoEntry(bAddress, 3, epInfo); + if(rcode) { + goto FailSetDevTblEntry; + } + } + + // Set Configuration Value + rcode = pUsb->setConf(bAddress, 0, bConfNum); + if(rcode) { + goto FailSetConfDescr; + } + /* print endpoint structure */ + /* + USBTRACE("\r\nEndpoint Structure:"); + USBTRACE("\r\nEP0:"); + USBTRACE2("\r\nAddr: ", epInfo[0].epAddr); + USBTRACE2("\r\nMax.pkt.size: ", epInfo[0].maxPktSize); + USBTRACE2("\r\nAttr: ", epInfo[0].epAttribs); + USBTRACE("\r\nEpout:"); + USBTRACE2("\r\nAddr: ", epInfo[epDataOutIndex].epAddr); + USBTRACE2("\r\nMax.pkt.size: ", epInfo[epDataOutIndex].maxPktSize); + USBTRACE2("\r\nAttr: ", epInfo[epDataOutIndex].epAttribs); + USBTRACE("\r\nEpin:"); + USBTRACE2("\r\nAddr: ", epInfo[epDataInIndex].epAddr); + USBTRACE2("\r\nMax.pkt.size: ", epInfo[epDataInIndex].maxPktSize); + USBTRACE2("\r\nAttr: ", epInfo[epDataInIndex].epAttribs); + */ + + USBTRACE("\r\nConfiguration successful"); + ready = true; + return 0; //successful configuration + }//if( buf->idVendor == ADK_VID... + + //probe device - get accessory protocol revision + { + uint16_t adkproto = -1; + delay(1); + rcode = getProto((uint8_t*) & adkproto); +#if defined(XOOM) + //added by Jaylen Scott Vanorden + if(rcode) { + USBTRACE2("\r\nGot 1st bad code for proto: ", rcode); + // Try once more + rcode = getProto((uint8_t*) & adkproto); + } +#endif + if(rcode) { + goto FailGetProto; //init fails + } + USBTRACE2("\r\nADK protocol rev. ", adkproto); + } + + delay(100); + + //sending ID strings + sendStr(ACCESSORY_STRING_MANUFACTURER, manufacturer); + delay(10); + sendStr(ACCESSORY_STRING_MODEL, model); + delay(10); + sendStr(ACCESSORY_STRING_DESCRIPTION, description); + delay(10); + sendStr(ACCESSORY_STRING_VERSION, version); + delay(10); + sendStr(ACCESSORY_STRING_URI, uri); + delay(10); + sendStr(ACCESSORY_STRING_SERIAL, serial); + + delay(100); + + //switch to accessory mode + //the Android phone will reset + rcode = switchAcc(); + if(rcode) { + goto FailSwAcc; //init fails + } + rcode = USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET; + delay(100); // Give Android a chance to do its reset. This is a guess, and possibly could be lower. + goto SwAttempt; //switch to accessory mode attempted + + /* diagnostic messages */ +FailGetDevDescr: +#ifdef DEBUG_USB_HOST + NotifyFailGetDevDescr(rcode); + goto Fail; +#endif + +FailSetDevTblEntry: +#ifdef DEBUG_USB_HOST + NotifyFailSetDevTblEntry(rcode); + goto Fail; +#endif + +FailGetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailGetConfDescr(rcode); + goto Fail; +#endif + +FailSetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailSetConfDescr(rcode); + goto Fail; +#endif + +FailGetProto: +#ifdef DEBUG_USB_HOST + USBTRACE("\r\ngetProto:"); + goto Fail; +#endif + +FailSwAcc: +#ifdef DEBUG_USB_HOST + USBTRACE("\r\nswAcc:"); + goto Fail; +#endif + + //FailOnInit: + // USBTRACE("OnInit:"); + // goto Fail; + // +SwAttempt: +#ifdef DEBUG_USB_HOST + USBTRACE("\r\nAccessory mode switch attempt"); +Fail: +#endif + //USBTRACE2("\r\nADK Init Failed, error code: ", rcode); + //NotifyFail(rcode); + Release(); + return rcode; +} + +/* Extracts bulk-IN and bulk-OUT endpoint information from config descriptor */ +void ADK::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) { + //ErrorMessage(PSTR("Conf.Val"), conf); + //ErrorMessage(PSTR("Iface Num"), iface); + //ErrorMessage(PSTR("Alt.Set"), alt); + + //added by Yuuichi Akagawa + if(bNumEP == 3) { + return; + } + + bConfNum = conf; + + if((pep->bmAttributes & 0x02) == 2) { + uint8_t index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex; + // Fill in the endpoint info structure + epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); + epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; + + bNumEP++; + + //PrintEndpointDescriptor(pep); + } +} + +/* Performs a cleanup after failed Init() attempt */ +uint8_t ADK::Release() { + pUsb->GetAddressPool().FreeAddress(bAddress); + + bNumEP = 1; //must have to be reset to 1 + + bAddress = 0; + ready = false; + return 0; +} + +uint8_t ADK::RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr) { + //USBTRACE2("\r\nAddr: ", bAddress ); + //USBTRACE2("\r\nEP: ",epInfo[epDataInIndex].epAddr); + return pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr); +} + +uint8_t ADK::SndData(uint16_t nbytes, uint8_t *dataptr) { + return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, nbytes, dataptr); +} + +void ADK::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) { + Notify(PSTR("Endpoint descriptor:"), 0x80); + Notify(PSTR("\r\nLength:\t\t"), 0x80); + D_PrintHex (ep_ptr->bLength, 0x80); + Notify(PSTR("\r\nType:\t\t"), 0x80); + D_PrintHex (ep_ptr->bDescriptorType, 0x80); + Notify(PSTR("\r\nAddress:\t"), 0x80); + D_PrintHex (ep_ptr->bEndpointAddress, 0x80); + Notify(PSTR("\r\nAttributes:\t"), 0x80); + D_PrintHex (ep_ptr->bmAttributes, 0x80); + Notify(PSTR("\r\nMaxPktSize:\t"), 0x80); + D_PrintHex (ep_ptr->wMaxPacketSize, 0x80); + Notify(PSTR("\r\nPoll Intrv:\t"), 0x80); + D_PrintHex (ep_ptr->bInterval, 0x80); + Notify(PSTR("\r\n"), 0x80); +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/adk.h b/lib/usbhost/USB_Host_Shield_2.0/adk.h new file mode 100644 index 0000000000..4a2920b88a --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/adk.h @@ -0,0 +1,140 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ + +/* Google ADK interface support header */ + +#if !defined(_ADK_H_) +#define _ADK_H_ + +#include "Usb.h" + +#define ADK_VID 0x18D1 +#define ADK_PID 0x2D00 +#define ADB_PID 0x2D01 + +#define XOOM //enables repeating getProto() and getConf() attempts +//necessary for slow devices such as Motorola XOOM +//defined by default, can be commented out to save memory + +/* requests */ + +#define ADK_GETPROTO 51 //check USB accessory protocol version +#define ADK_SENDSTR 52 //send identifying string +#define ADK_ACCSTART 53 //start device in accessory mode + +#define bmREQ_ADK_GET USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_VENDOR|USB_SETUP_RECIPIENT_DEVICE +#define bmREQ_ADK_SEND USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_VENDOR|USB_SETUP_RECIPIENT_DEVICE + +#define ACCESSORY_STRING_MANUFACTURER 0 +#define ACCESSORY_STRING_MODEL 1 +#define ACCESSORY_STRING_DESCRIPTION 2 +#define ACCESSORY_STRING_VERSION 3 +#define ACCESSORY_STRING_URI 4 +#define ACCESSORY_STRING_SERIAL 5 + +#define ADK_MAX_ENDPOINTS 3 //endpoint 0, bulk_IN, bulk_OUT + +class ADK; + +class ADK : public USBDeviceConfig, public UsbConfigXtracter { +private: + /* ID strings */ + const char* manufacturer; + const char* model; + const char* description; + const char* version; + const char* uri; + const char* serial; + + /* ADK proprietary requests */ + uint8_t getProto(uint8_t* adkproto); + uint8_t sendStr(uint8_t index, const char* str); + uint8_t switchAcc(void); + +protected: + static const uint8_t epDataInIndex; // DataIn endpoint index + static const uint8_t epDataOutIndex; // DataOUT endpoint index + + /* mandatory members */ + USB *pUsb; + uint8_t bAddress; + uint8_t bConfNum; // configuration number + + uint8_t bNumEP; // total number of EP in the configuration + bool ready; + + /* Endpoint data structure */ + EpInfo epInfo[ADK_MAX_ENDPOINTS]; + + void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); + +public: + ADK(USB *pUsb, const char* manufacturer, + const char* model, + const char* description, + const char* version, + const char* uri, + const char* serial); + + // Methods for receiving and sending data + uint8_t RcvData(uint16_t *nbytesptr, uint8_t *dataptr); + uint8_t SndData(uint16_t nbytes, uint8_t *dataptr); + + + // USBDeviceConfig implementation + uint8_t ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed); + uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + uint8_t Release(); + + virtual uint8_t Poll() { + return 0; + }; + + virtual uint8_t GetAddress() { + return bAddress; + }; + + virtual bool isReady() { + return ready; + }; + + virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) { + return (vid == ADK_VID && (pid == ADK_PID || pid == ADB_PID)); + }; + + //UsbConfigXtracter implementation + void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); +}; //class ADK : public USBDeviceConfig ... + +/* get ADK protocol version */ + +/* returns 2 bytes in *adkproto */ +inline uint8_t ADK::getProto(uint8_t* adkproto) { + return ( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_GET, ADK_GETPROTO, 0, 0, 0, 2, 2, adkproto, NULL)); +} + +/* send ADK string */ +inline uint8_t ADK::sendStr(uint8_t index, const char* str) { + return ( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_SEND, ADK_SENDSTR, 0, 0, index, strlen(str) + 1, strlen(str) + 1, (uint8_t*)str, NULL)); +} + +/* switch to accessory mode */ +inline uint8_t ADK::switchAcc(void) { + return ( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_SEND, ADK_ACCSTART, 0, 0, 0, 0, 0, NULL, NULL)); +} + +#endif // _ADK_H_ diff --git a/lib/usbhost/USB_Host_Shield_2.0/avrpins.h b/lib/usbhost/USB_Host_Shield_2.0/avrpins.h new file mode 100644 index 0000000000..4e60e3a229 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/avrpins.h @@ -0,0 +1,1130 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ + +/* derived from Konstantin Chizhov's AVR port templates */ + +#if !defined(_usb_h_) || defined(_avrpins_h_) +#error "Never include avrpins.h directly; include Usb.h instead" +#else +#define _avrpins_h_ + +#if defined(__AVR__) + +// pointers are 16 bits on AVR +#define pgm_read_pointer(p) pgm_read_word(p) + +// Support for these boards needs to be manually activated in settings.h or in a makefile +#if !defined(BOARD_MEGA_ADK) && defined(__AVR_ATmega2560__) && (USE_UHS_MEGA_ADK || defined(ARDUINO_AVR_ADK)) +#define BOARD_MEGA_ADK +#elif !defined(BOARD_BLACK_WIDDOW) && USE_UHS_BLACK_WIDDOW +#define BOARD_BLACK_WIDDOW +#endif + +#ifdef PORTA +#define USE_PORTA +#endif +#ifdef PORTB +#define USE_PORTB +#endif +#ifdef PORTC +#define USE_PORTC +#endif +#ifdef PORTD +#define USE_PORTD +#endif +#ifdef PORTE +#define USE_PORTE +#endif +#ifdef PORTF +#define USE_PORTF +#endif +#ifdef PORTG +#define USE_PORTG +#endif +#ifdef PORTH +#define USE_PORTH +#endif +#ifdef PORTJ +#define USE_PORTJ +#endif +#ifdef PORTK +#define USE_PORTK +#endif +#ifdef PORTL +#define USE_PORTL +#endif +#ifdef PORTQ +#define USE_PORTQ +#endif +#ifdef PORTR +#define USE_PORTR +#endif + +#ifdef TCCR0A +#define USE_TCCR0A +#endif +#ifdef TCCR1A +#define USE_TCCR1A +#endif +#ifdef TCCR2A +#define USE_TCCR2A +#endif + +//Port definitions for AtTiny, AtMega families. + +#define MAKE_PORT(portName, ddrName, pinName, className, ID) \ + class className{\ + public:\ + typedef uint8_t DataT;\ + public:\ + static void Write(DataT value){portName = value;}\ + static void ClearAndSet(DataT clearMask, DataT value){portName = (portName & ~clearMask) | value;}\ + static DataT Read(){return portName;}\ + static void DirWrite(DataT value){ddrName = value;}\ + static DataT DirRead(){return ddrName;}\ + static void Set(DataT value){portName |= value;}\ + static void Clear(DataT value){portName &= ~value;}\ + static void Toggle(DataT value){portName ^= value;}\ + static void DirSet(DataT value){ddrName |= value;}\ + static void DirClear(DataT value){ddrName &= ~value;}\ + static void DirToggle(DataT value){ddrName ^= value;}\ + static DataT PinRead(){return pinName;}\ + enum{Id = ID};\ + enum{Width=sizeof(DataT)*8};\ + }; + +// TCCR registers to set/clear Arduino PWM +#define MAKE_TCCR(TccrName, className) \ + class className{\ + public:\ + typedef uint8_t DataT;\ + public:\ + static void Write(DataT value){TccrName = value;}\ + static void ClearAndSet(DataT clearMask, DataT value){TccrName = (TccrName & ~clearMask) | value;}\ + static DataT Read(){return TccrName;}\ + static void Set(DataT value){TccrName |= value;}\ + static void Clear(DataT value){TccrName &= ~value;}\ + static void Toggle(DataT value){TccrName ^= value;}\ + enum{Width=sizeof(DataT)*8};\ + }; + +#ifdef USE_PORTA + +MAKE_PORT(PORTA, DDRA, PINA, Porta, 'A') +#endif +#ifdef USE_PORTB +MAKE_PORT(PORTB, DDRB, PINB, Portb, 'B') +#endif +#ifdef USE_PORTC +MAKE_PORT(PORTC, DDRC, PINC, Portc, 'C') +#endif +#ifdef USE_PORTD +MAKE_PORT(PORTD, DDRD, PIND, Portd, 'D') +#endif +#ifdef USE_PORTE +MAKE_PORT(PORTE, DDRE, PINE, Porte, 'E') +#endif +#ifdef USE_PORTF +MAKE_PORT(PORTF, DDRF, PINF, Portf, 'F') +#endif +#ifdef USE_PORTG +MAKE_PORT(PORTG, DDRG, PING, Portg, 'G') +#endif +#ifdef USE_PORTH +MAKE_PORT(PORTH, DDRH, PINH, Porth, 'H') +#endif +#ifdef USE_PORTJ +MAKE_PORT(PORTJ, DDRJ, PINJ, Portj, 'J') +#endif +#ifdef USE_PORTK +MAKE_PORT(PORTK, DDRK, PINK, Portk, 'K') +#endif +#ifdef USE_PORTL +MAKE_PORT(PORTL, DDRL, PINL, Portl, 'L') +#endif +#ifdef USE_PORTQ +MAKE_PORT(PORTQ, DDRQ, PINQ, Portq, 'Q') +#endif +#ifdef USE_PORTR +MAKE_PORT(PORTR, DDRR, PINR, Portr, 'R') +#endif + +#ifdef USE_TCCR0A +MAKE_TCCR(TCCR0A, Tccr0a) +#endif +#ifdef USE_TCCR1A +MAKE_TCCR(TCCR1A, Tccr1a) +#endif +#ifdef USE_TCCR2A +MAKE_TCCR(TCCR2A, Tccr2a) +#endif + +// this class represents one pin in a IO port. +// It is fully static. +template +class TPin { + // BOOST_STATIC_ASSERT(PIN < PORT::Width); +public: + typedef PORT Port; + + enum { + Number = PIN + }; + + static void Set() { + PORT::Set(1 << PIN); + } + + static void Set(uint8_t val) { + if(val) + Set(); + else Clear(); + } + + static void SetDir(uint8_t val) { + if(val) + SetDirWrite(); + else SetDirRead(); + } + + static void Clear() { + PORT::Clear(1 << PIN); + } + + static void Toggle() { + PORT::Toggle(1 << PIN); + } + + static void SetDirRead() { + PORT::DirClear(1 << PIN); + } + + static void SetDirWrite() { + PORT::DirSet(1 << PIN); + } + + static uint8_t IsSet() { + return PORT::PinRead() & (uint8_t)(1 << PIN); + } + + static void WaiteForSet() { + while(IsSet() == 0) { + } + } + + static void WaiteForClear() { + while(IsSet()) { + } + } +}; //class TPin... + +// this class represents one bit in TCCR port. +// used to set/clear TCCRx bits +// It is fully static. + +template +class TCom { + // BOOST_STATIC_ASSERT(PIN < PORT::Width); +public: + typedef TCCR Tccr; + + enum { + Com = COM + }; + + static void Set() { + TCCR::Set(1 << COM); + } + + static void Clear() { + TCCR::Clear(1 << COM); + } + + static void Toggle() { + TCCR::Toggle(1 << COM); + } +}; //class TCom... + +//Short pin definitions +#ifdef USE_PORTA +typedef TPin Pa0; +typedef TPin Pa1; +typedef TPin Pa2; +typedef TPin Pa3; +typedef TPin Pa4; +typedef TPin Pa5; +typedef TPin Pa6; +typedef TPin Pa7; +#endif + +#ifdef USE_PORTB +typedef TPin Pb0; +typedef TPin Pb1; +typedef TPin Pb2; +typedef TPin Pb3; +typedef TPin Pb4; +typedef TPin Pb5; +typedef TPin Pb6; +typedef TPin Pb7; +#endif + +#ifdef USE_PORTC +typedef TPin Pc0; +typedef TPin Pc1; +typedef TPin Pc2; +typedef TPin Pc3; +typedef TPin Pc4; +typedef TPin Pc5; +typedef TPin Pc6; +typedef TPin Pc7; +#endif + +#ifdef USE_PORTD +typedef TPin Pd0; +typedef TPin Pd1; +typedef TPin Pd2; +typedef TPin Pd3; +typedef TPin Pd4; +typedef TPin Pd5; +typedef TPin Pd6; +typedef TPin Pd7; +#endif + +#ifdef USE_PORTE +typedef TPin Pe0; +typedef TPin Pe1; +typedef TPin Pe2; +typedef TPin Pe3; +typedef TPin Pe4; +typedef TPin Pe5; +typedef TPin Pe6; +typedef TPin Pe7; +#endif + +#ifdef USE_PORTF +typedef TPin Pf0; +typedef TPin Pf1; +typedef TPin Pf2; +typedef TPin Pf3; +typedef TPin Pf4; +typedef TPin Pf5; +typedef TPin Pf6; +typedef TPin Pf7; +#endif + +#ifdef USE_PORTG +typedef TPin Pg0; +typedef TPin Pg1; +typedef TPin Pg2; +typedef TPin Pg3; +typedef TPin Pg4; +typedef TPin Pg5; +typedef TPin Pg6; +typedef TPin Pg7; +#endif + +#ifdef USE_PORTH +typedef TPin Ph0; +typedef TPin Ph1; +typedef TPin Ph2; +typedef TPin Ph3; +typedef TPin Ph4; +typedef TPin Ph5; +typedef TPin Ph6; +typedef TPin Ph7; +#endif + +#ifdef USE_PORTJ +typedef TPin Pj0; +typedef TPin Pj1; +typedef TPin Pj2; +typedef TPin Pj3; +typedef TPin Pj4; +typedef TPin Pj5; +typedef TPin Pj6; +typedef TPin Pj7; +#endif + +#ifdef USE_PORTK +typedef TPin Pk0; +typedef TPin Pk1; +typedef TPin Pk2; +typedef TPin Pk3; +typedef TPin Pk4; +typedef TPin Pk5; +typedef TPin Pk6; +typedef TPin Pk7; +#endif + +#ifdef USE_PORTL +typedef TPin Pl0; +typedef TPin Pl1; +typedef TPin Pl2; +typedef TPin Pl3; +typedef TPin Pl4; +typedef TPin Pl5; +typedef TPin Pl6; +typedef TPin Pl7; +#endif + +#ifdef USE_PORTQ +typedef TPin Pq0; +typedef TPin Pq1; +typedef TPin Pq2; +typedef TPin Pq3; +typedef TPin Pq4; +typedef TPin Pq5; +typedef TPin Pq6; +typedef TPin Pq7; +#endif + +#ifdef USE_PORTR +typedef TPin Pr0; +typedef TPin Pr1; +typedef TPin Pr2; +typedef TPin Pr3; +typedef TPin Pr4; +typedef TPin Pr5; +typedef TPin Pr6; +typedef TPin Pr7; +#endif + +#ifdef USE_TCCR0A +typedef TCom Tc0a; //P6 +typedef TCom Tc0b; //P5 +#endif + +#ifdef USE_TCCR1A +typedef TCom Tc1a; //P9 +typedef TCom Tc1b; //P10 +#endif + +#ifdef USE_TCCR2A +typedef TCom Tc2a; //P11 +typedef TCom Tc2b; //P3 +#endif + +template +class Tp_Tc { +public: + + static void SetDir(uint8_t val) { + if(val) + SetDirWrite(); + else SetDirRead(); + } + + static void SetDirRead() { + Tp_pin::SetDirRead(); //set pin direction + Tc_bit::Clear(); //disconnect pin from PWM + } + + static void SetDirWrite() { + Tp_pin::SetDirWrite(); + Tc_bit::Clear(); + } +}; + +/* pin definitions for cases where it's necessary to clear compare output mode bits */ + +//typedef Tp_Tc P3; //Arduino pin 3 +//typedef Tp_Tc P5; //Arduino pin 5 +//typedef Tp_Tc P6; //Arduino pin 6 +//typedef Tp_Tc P9; //Arduino pin 9 +//typedef Tp_Tc P10; //Arduino pin 10 +//typedef Tp_Tc P11; //Arduino pin 11 + +/* Arduino pin definitions */ +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +// "Mega" Arduino pin numbers + +#define P0 Pe0 +#define P1 Pe1 +#define P2 Pe4 +#define P3 Pe5 +#define P4 Pg5 +#define P5 Pe3 +#define P6 Ph3 +#define P7 Ph4 + +#define P8 Ph5 +#define P9 Ph6 +#define P10 Pb4 +#define P11 Pb5 +#define P12 Pb6 +#define P13 Pb7 + +#define P14 Pj1 +#define P15 Pj0 +#define P16 Ph1 +#define P17 Ph0 +#define P18 Pd3 +#define P19 Pd2 +#define P20 Pd1 +#define P21 Pd0 + +#define P22 Pa0 +#define P23 Pa1 +#define P24 Pa2 +#define P25 Pa3 +#define P26 Pa4 +#define P27 Pa5 +#define P28 Pa6 +#define P29 Pa7 +#define P30 Pc7 +#define P31 Pc6 +#define P32 Pc5 +#define P33 Pc4 +#define P34 Pc3 +#define P35 Pc2 +#define P36 Pc1 +#define P37 Pc0 + +#define P38 Pd7 +#define P39 Pg2 +#define P40 Pg1 +#define P41 Pg0 +#define P42 Pl7 +#define P43 Pl6 +#define P44 Pl5 +#define P45 Pl4 +#define P46 Pl3 +#define P47 Pl2 +#define P48 Pl1 +#define P49 Pl0 +#define P50 Pb3 +#define P51 Pb2 +#define P52 Pb1 +#define P53 Pb0 + +#ifdef BOARD_MEGA_ADK // These pins are not broken out on the Arduino ADK +#define P54 Pe6 // INT on Arduino ADK +#define P55 Pj2 // MAX_RESET on Arduino ADK +#endif + +// "Mega" pin numbers + +#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) +// "Classic" Arduino pin numbers + +#define P0 Pd0 +#define P1 Pd1 +#define P2 Pd2 +#define P3 Pd3 +#define P4 Pd4 +#define P5 Pd5 +#define P6 Pd6 +#define P7 Pd7 + +#define P8 Pb0 +#define P9 Pb1 +#define P10 Pb2 +#define P11 Pb3 +#define P12 Pb4 +#define P13 Pb5 + +#define P14 Pc0 +#define P15 Pc1 +#define P16 Pc2 +#define P17 Pc3 +#define P18 Pc4 +#define P19 Pc5 + +// "Classic" Arduino pin numbers + +#elif defined(CORE_TEENSY) && defined(__AVR_ATmega32U4__) +// Teensy 2.0 pin numbers +// http://www.pjrc.com/teensy/pinout.html +#define P0 Pb0 +#define P1 Pb1 +#define P2 Pb2 +#define P3 Pb3 +#define P4 Pb7 +#define P5 Pd0 +#define P6 Pd1 +#define P7 Pd2 +#define P8 Pd3 +#define P9 Pc6 +#define P10 Pc7 +#define P11 Pd6 +#define P12 Pd7 +#define P13 Pb4 +#define P14 Pb5 +#define P15 Pb6 +#define P16 Pf7 +#define P17 Pf6 +#define P18 Pf5 +#define P19 Pf4 +#define P20 Pf1 +#define P21 Pf0 +#define P22 Pd4 +#define P23 Pd5 +#define P24 Pe6 +// Teensy 2.0 + +#elif defined(__AVR_ATmega32U4__) +// Arduino Leonardo pin numbers + +#define P0 Pd2 // D0 - PD2 +#define P1 Pd3 // D1 - PD3 +#define P2 Pd1 // D2 - PD1 +#define P3 Pd0 // D3 - PD0 +#define P4 Pd4 // D4 - PD4 +#define P5 Pc6 // D5 - PC6 +#define P6 Pd7 // D6 - PD7 +#define P7 Pe6 // D7 - PE6 + +#define P8 Pb4 // D8 - PB4 +#define P9 Pb5 // D9 - PB5 +#define P10 Pb6 // D10 - PB6 +#define P11 Pb7 // D11 - PB7 +#define P12 Pd6 // D12 - PD6 +#define P13 Pc7 // D13 - PC7 + +#define P14 Pb3 // D14 - MISO - PB3 +#define P15 Pb1 // D15 - SCK - PB1 +#define P16 Pb2 // D16 - MOSI - PB2 +#define P17 Pb0 // D17 - SS - PB0 + +#define P18 Pf7 // D18 - A0 - PF7 +#define P19 Pf6 // D19 - A1 - PF6 +#define P20 Pf5 // D20 - A2 - PF5 +#define P21 Pf4 // D21 - A3 - PF4 +#define P22 Pf1 // D22 - A4 - PF1 +#define P23 Pf0 // D23 - A5 - PF0 + +#define P24 Pd4 // D24 / D4 - A6 - PD4 +#define P25 Pd7 // D25 / D6 - A7 - PD7 +#define P26 Pb4 // D26 / D8 - A8 - PB4 +#define P27 Pb5 // D27 / D9 - A9 - PB5 +#define P28 Pb6 // D28 / D10 - A10 - PB6 +#define P29 Pd6 // D29 / D12 - A11 - PD6 + +// Arduino Leonardo pin numbers + +#elif defined(CORE_TEENSY) && (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)) +// Teensy++ 1.0 and 2.0 pin numbers +// http://www.pjrc.com/teensy/pinout.html +#define P0 Pd0 +#define P1 Pd1 +#define P2 Pd2 +#define P3 Pd3 +#define P4 Pd4 +#define P5 Pd5 +#define P6 Pd6 +#define P7 Pd7 +#define P8 Pe0 +#define P9 Pe1 +#define P10 Pc0 +#define P11 Pc1 +#define P12 Pc2 +#define P13 Pc3 +#define P14 Pc4 +#define P15 Pc5 +#define P16 Pc6 +#define P17 Pc7 +#define P18 Pe6 +#define P19 Pe7 +#define P20 Pb0 +#define P21 Pb1 +#define P22 Pb2 +#define P23 Pb3 +#define P24 Pb4 +#define P25 Pb5 +#define P26 Pb6 +#define P27 Pb7 +#define P28 Pa0 +#define P29 Pa1 +#define P30 Pa2 +#define P31 Pa3 +#define P32 Pa4 +#define P33 Pa5 +#define P34 Pa6 +#define P35 Pa7 +#define P36 Pe4 +#define P37 Pe5 +#define P38 Pf0 +#define P39 Pf1 +#define P40 Pf2 +#define P41 Pf3 +#define P42 Pf4 +#define P43 Pf5 +#define P44 Pf6 +#define P45 Pf7 +// Teensy++ 1.0 and 2.0 + +#elif defined(ARDUINO_AVR_BALANDUINO) && (defined(__AVR_ATmega644__) || defined(__AVR_ATmega1284P__)) +// Balanduino pin numbers +// http://balanduino.net/ +#define P0 Pd0 /* 0 - PD0 */ +#define P1 Pd1 /* 1 - PD1 */ + +#if BALANDUINO_REVISION < 13 + #define P2 Pb2 /* 2 - PB2 */ + #define P3 Pd6 /* 3 - PD6 */ + #define P4 Pd7 /* 4 - PD7 */ + #define P5 Pb3 /* 5 - PB3 */ +#else + #define P2 Pd2 /* 2 - PD2 */ + #define P3 Pd3 /* 3 - PD3 */ + #define P4 Pd6 /* 4 - PD6 */ + #define P5 Pd7 /* 5 - PD7 */ +#endif + +#define P6 Pb4 /* 6 - PB4 */ +#define P7 Pa0 /* 7 - PA0 */ +#define P8 Pa1 /* 8 - PA1 */ +#define P9 Pa2 /* 9 - PA2 */ +#define P10 Pa3 /* 10 - PA3 */ +#define P11 Pa4 /* 11 - PA4 */ +#define P12 Pa5 /* 12 - PA5 */ +#define P13 Pc1 /* 13 - PC1 */ +#define P14 Pc0 /* 14 - PC0 */ + +#if BALANDUINO_REVISION < 13 + #define P15 Pd2 /* 15 - PD2 */ + #define P16 Pd3 /* 16 - PD3 */ +#else + #define P15 Pb2 /* 15 - PB2 */ + #define P16 Pb3 /* 16 - PB2 */ +#endif + +#define P17 Pd4 /* 17 - PD4 */ +#define P18 Pd5 /* 18 - PD5 */ +#define P19 Pc2 /* 19 - PC2 */ +#define P20 Pc3 /* 20 - PC3 */ +#define P21 Pc4 /* 21 - PC4 */ +#define P22 Pc5 /* 22 - PC5 */ +#define P23 Pc6 /* 23 - PC6 */ +#define P24 Pc7 /* 24 - PC7 */ +#define P25 Pb0 /* 25 - PB0 */ +#define P26 Pb1 /* 26 - PB1 */ +#define P27 Pb5 /* 27 - PB5 */ +#define P28 Pb6 /* 28 - PB6 */ +#define P29 Pb7 /* 29 - PB7 */ +#define P30 Pa6 /* 30 - PA6 */ +#define P31 Pa7 /* 31 - PA7 */ +// Balanduino + +#elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) +// Sanguino pin numbers +// Homepage: http://sanguino.cc/hardware +// Hardware add-on: https://github.com/Lauszus/Sanguino +#define P0 Pb0 +#define P1 Pb1 +#define P2 Pb2 +#define P3 Pb3 +#define P4 Pb4 +#define P5 Pb5 +#define P6 Pb6 +#define P7 Pb7 +#define P8 Pd0 +#define P9 Pd1 +#define P10 Pd2 +#define P11 Pd3 +#define P12 Pd4 +#define P13 Pd5 +#define P14 Pd6 +#define P15 Pd7 +#define P16 Pc0 +#define P17 Pc1 +#define P18 Pc2 +#define P19 Pc3 +#define P20 Pc4 +#define P21 Pc5 +#define P22 Pc6 +#define P23 Pc7 +#define P24 Pa0 +#define P25 Pa1 +#define P26 Pa2 +#define P27 Pa3 +#define P28 Pa4 +#define P29 Pa5 +#define P30 Pa6 +#define P31 Pa7 +// Sanguino + +#else +#error "Please define board in avrpins.h" + +#endif // Arduino pin definitions + +#elif defined(__arm__) + +// pointers are 32 bits on ARM +#define pgm_read_pointer(p) pgm_read_dword(p) + +#if defined(CORE_TEENSY) && (defined(__MK20DX128__) || defined(__MK20DX256__)) + +#include "core_pins.h" +#include "avr_emulation.h" + +#define GPIO_BITBAND_ADDR(reg, bit) (((uint32_t)&(reg) - 0x40000000) * 32 + (bit) * 4 + 0x42000000) +#define GPIO_BITBAND_PTR(reg, bit) ((uint8_t *)GPIO_BITBAND_ADDR((reg), (bit))) + +#define MAKE_PIN(className, baseReg, pinNum, configReg) \ +class className { \ +public: \ + static void Set() { \ + *GPIO_BITBAND_PTR(baseReg, pinNum) = 1; \ + } \ + static void Clear() { \ + *GPIO_BITBAND_PTR(baseReg, pinNum) = 0; \ + } \ + static void SetDirRead() { \ + configReg = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); \ + *(GPIO_BITBAND_PTR(baseReg, pinNum) + 640) = 0; \ + } \ + static void SetDirWrite() { \ + configReg = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); \ + *(GPIO_BITBAND_PTR(baseReg, pinNum) + 640) = 1; \ + } \ + static uint8_t IsSet() { \ + return *(GPIO_BITBAND_PTR(baseReg, pinNum) + 512); \ + } \ +}; + +MAKE_PIN(P0, CORE_PIN0_PORTREG, CORE_PIN0_BIT, CORE_PIN0_CONFIG); +MAKE_PIN(P1, CORE_PIN1_PORTREG, CORE_PIN1_BIT, CORE_PIN1_CONFIG); +MAKE_PIN(P2, CORE_PIN2_PORTREG, CORE_PIN2_BIT, CORE_PIN2_CONFIG); +MAKE_PIN(P3, CORE_PIN3_PORTREG, CORE_PIN3_BIT, CORE_PIN3_CONFIG); +MAKE_PIN(P4, CORE_PIN4_PORTREG, CORE_PIN4_BIT, CORE_PIN4_CONFIG); +MAKE_PIN(P5, CORE_PIN5_PORTREG, CORE_PIN5_BIT, CORE_PIN5_CONFIG); +MAKE_PIN(P6, CORE_PIN6_PORTREG, CORE_PIN6_BIT, CORE_PIN6_CONFIG); +MAKE_PIN(P7, CORE_PIN7_PORTREG, CORE_PIN7_BIT, CORE_PIN7_CONFIG); +MAKE_PIN(P8, CORE_PIN8_PORTREG, CORE_PIN8_BIT, CORE_PIN8_CONFIG); +MAKE_PIN(P9, CORE_PIN9_PORTREG, CORE_PIN9_BIT, CORE_PIN9_CONFIG); +MAKE_PIN(P10, CORE_PIN10_PORTREG, CORE_PIN10_BIT, CORE_PIN10_CONFIG); +MAKE_PIN(P11, CORE_PIN11_PORTREG, CORE_PIN11_BIT, CORE_PIN11_CONFIG); +MAKE_PIN(P12, CORE_PIN12_PORTREG, CORE_PIN12_BIT, CORE_PIN12_CONFIG); +MAKE_PIN(P13, CORE_PIN13_PORTREG, CORE_PIN13_BIT, CORE_PIN13_CONFIG); +MAKE_PIN(P14, CORE_PIN14_PORTREG, CORE_PIN14_BIT, CORE_PIN14_CONFIG); +MAKE_PIN(P15, CORE_PIN15_PORTREG, CORE_PIN15_BIT, CORE_PIN15_CONFIG); +MAKE_PIN(P16, CORE_PIN16_PORTREG, CORE_PIN16_BIT, CORE_PIN16_CONFIG); +MAKE_PIN(P17, CORE_PIN17_PORTREG, CORE_PIN17_BIT, CORE_PIN17_CONFIG); +MAKE_PIN(P18, CORE_PIN18_PORTREG, CORE_PIN18_BIT, CORE_PIN18_CONFIG); +MAKE_PIN(P19, CORE_PIN19_PORTREG, CORE_PIN19_BIT, CORE_PIN19_CONFIG); +MAKE_PIN(P20, CORE_PIN20_PORTREG, CORE_PIN20_BIT, CORE_PIN20_CONFIG); +MAKE_PIN(P21, CORE_PIN21_PORTREG, CORE_PIN21_BIT, CORE_PIN21_CONFIG); +MAKE_PIN(P22, CORE_PIN22_PORTREG, CORE_PIN22_BIT, CORE_PIN22_CONFIG); +MAKE_PIN(P23, CORE_PIN23_PORTREG, CORE_PIN23_BIT, CORE_PIN23_CONFIG); +MAKE_PIN(P24, CORE_PIN24_PORTREG, CORE_PIN24_BIT, CORE_PIN24_CONFIG); +MAKE_PIN(P25, CORE_PIN25_PORTREG, CORE_PIN25_BIT, CORE_PIN25_CONFIG); +MAKE_PIN(P26, CORE_PIN26_PORTREG, CORE_PIN26_BIT, CORE_PIN26_CONFIG); +MAKE_PIN(P27, CORE_PIN27_PORTREG, CORE_PIN27_BIT, CORE_PIN27_CONFIG); +MAKE_PIN(P28, CORE_PIN28_PORTREG, CORE_PIN28_BIT, CORE_PIN28_CONFIG); +MAKE_PIN(P29, CORE_PIN29_PORTREG, CORE_PIN29_BIT, CORE_PIN29_CONFIG); +MAKE_PIN(P30, CORE_PIN30_PORTREG, CORE_PIN30_BIT, CORE_PIN30_CONFIG); +MAKE_PIN(P31, CORE_PIN31_PORTREG, CORE_PIN31_BIT, CORE_PIN31_CONFIG); +MAKE_PIN(P32, CORE_PIN32_PORTREG, CORE_PIN32_BIT, CORE_PIN32_CONFIG); +MAKE_PIN(P33, CORE_PIN33_PORTREG, CORE_PIN33_BIT, CORE_PIN33_CONFIG); + +#undef MAKE_PIN + +#elif defined(ARDUINO_SAM_DUE) && defined(__SAM3X8E__) + +// SetDirRead: +// Disable interrupts +// Disable the pull up resistor +// Set to INPUT +// Enable PIO + +// SetDirWrite: +// Disable interrupts +// Disable the pull up resistor +// Set to OUTPUT +// Enable PIO + +#define MAKE_PIN(className, pio, pinMask) \ +class className { \ +public: \ + static void Set() { \ + pio->PIO_SODR = pinMask; \ + } \ + static void Clear() { \ + pio->PIO_CODR = pinMask; \ + } \ + static void SetDirRead() { \ + pio->PIO_IDR = pinMask ; \ + pio->PIO_PUDR = pinMask; \ + pio->PIO_ODR = pinMask; \ + pio->PIO_PER = pinMask; \ + } \ + static void SetDirWrite() { \ + pio->PIO_IDR = pinMask ; \ + pio->PIO_PUDR = pinMask; \ + pio->PIO_OER = pinMask; \ + pio->PIO_PER = pinMask; \ + } \ + static uint8_t IsSet() { \ + return pio->PIO_PDSR & pinMask; \ + } \ +}; + +// See: http://arduino.cc/en/Hacking/PinMappingSAM3X and variant.cpp + +MAKE_PIN(P0, PIOA, PIO_PA8); +MAKE_PIN(P1, PIOA, PIO_PA9); +MAKE_PIN(P2, PIOB, PIO_PB25); +MAKE_PIN(P3, PIOC, PIO_PC28); +MAKE_PIN(P4, PIOC, PIO_PC26); +MAKE_PIN(P5, PIOC, PIO_PC25); +MAKE_PIN(P6, PIOC, PIO_PC24); +MAKE_PIN(P7, PIOC, PIO_PC23); +MAKE_PIN(P8, PIOC, PIO_PC22); +MAKE_PIN(P9, PIOC, PIO_PC21); +MAKE_PIN(P10, PIOC, PIO_PC29); +MAKE_PIN(P11, PIOD, PIO_PD7); +MAKE_PIN(P12, PIOD, PIO_PD8); +MAKE_PIN(P13, PIOB, PIO_PB27); +MAKE_PIN(P14, PIOD, PIO_PD4); +MAKE_PIN(P15, PIOD, PIO_PD5); +MAKE_PIN(P16, PIOA, PIO_PA13); +MAKE_PIN(P17, PIOA, PIO_PA12); +MAKE_PIN(P18, PIOA, PIO_PA11); +MAKE_PIN(P19, PIOA, PIO_PA10); +MAKE_PIN(P20, PIOB, PIO_PB12); +MAKE_PIN(P21, PIOB, PIO_PB13); +MAKE_PIN(P22, PIOB, PIO_PB26); +MAKE_PIN(P23, PIOA, PIO_PA14); +MAKE_PIN(P24, PIOA, PIO_PA15); +MAKE_PIN(P25, PIOD, PIO_PD0); +MAKE_PIN(P26, PIOD, PIO_PD1); +MAKE_PIN(P27, PIOD, PIO_PD2); +MAKE_PIN(P28, PIOD, PIO_PD3); +MAKE_PIN(P29, PIOD, PIO_PD6); +MAKE_PIN(P30, PIOD, PIO_PD9); +MAKE_PIN(P31, PIOA, PIO_PA7); +MAKE_PIN(P32, PIOD, PIO_PD10); +MAKE_PIN(P33, PIOC, PIO_PC1); +MAKE_PIN(P34, PIOC, PIO_PC2); +MAKE_PIN(P35, PIOC, PIO_PC3); +MAKE_PIN(P36, PIOC, PIO_PC4); +MAKE_PIN(P37, PIOC, PIO_PC5); +MAKE_PIN(P38, PIOC, PIO_PC6); +MAKE_PIN(P39, PIOC, PIO_PC7); +MAKE_PIN(P40, PIOC, PIO_PC8); +MAKE_PIN(P41, PIOC, PIO_PC9); +MAKE_PIN(P42, PIOA, PIO_PA19); +MAKE_PIN(P43, PIOA, PIO_PA20); +MAKE_PIN(P44, PIOC, PIO_PC19); +MAKE_PIN(P45, PIOC, PIO_PC18); +MAKE_PIN(P46, PIOC, PIO_PC17); +MAKE_PIN(P47, PIOC, PIO_PC16); +MAKE_PIN(P48, PIOC, PIO_PC15); +MAKE_PIN(P49, PIOC, PIO_PC14); +MAKE_PIN(P50, PIOC, PIO_PC13); +MAKE_PIN(P51, PIOC, PIO_PC12); +MAKE_PIN(P52, PIOB, PIO_PB21); +MAKE_PIN(P53, PIOB, PIO_PB14); +MAKE_PIN(P54, PIOA, PIO_PA16); +MAKE_PIN(P55, PIOA, PIO_PA24); +MAKE_PIN(P56, PIOA, PIO_PA23); +MAKE_PIN(P57, PIOA, PIO_PA22); +MAKE_PIN(P58, PIOA, PIO_PA6); +MAKE_PIN(P59, PIOA, PIO_PA4); +MAKE_PIN(P60, PIOA, PIO_PA3); +MAKE_PIN(P61, PIOA, PIO_PA2); +MAKE_PIN(P62, PIOB, PIO_PB17); +MAKE_PIN(P63, PIOB, PIO_PB18); +MAKE_PIN(P64, PIOB, PIO_PB19); +MAKE_PIN(P65, PIOB, PIO_PB20); +MAKE_PIN(P66, PIOB, PIO_PB15); +MAKE_PIN(P67, PIOB, PIO_PB16); +MAKE_PIN(P68, PIOA, PIO_PA1); +MAKE_PIN(P69, PIOA, PIO_PA0); +MAKE_PIN(P70, PIOA, PIO_PA17); +MAKE_PIN(P71, PIOA, PIO_PA18); +MAKE_PIN(P72, PIOC, PIO_PC30); +MAKE_PIN(P73, PIOA, PIO_PA21); +MAKE_PIN(P74, PIOA, PIO_PA25); // MISO +MAKE_PIN(P75, PIOA, PIO_PA26); // MOSI +MAKE_PIN(P76, PIOA, PIO_PA27); // CLK +MAKE_PIN(P77, PIOA, PIO_PA28); +MAKE_PIN(P78, PIOB, PIO_PB23); // Unconnected + +#undef MAKE_PIN + +#elif defined(RBL_NRF51822) + +#define MAKE_PIN(className, pin) \ +class className { \ +public: \ + static void Set() { \ + nrf_gpio_pin_set(pin); \ + } \ + static void Clear() { \ + nrf_gpio_pin_clear(pin); \ + } \ + static void SetDirRead() { \ + nrf_gpio_cfg_input(pin, NRF_GPIO_PIN_NOPULL); \ + } \ + static void SetDirWrite() { \ + nrf_gpio_cfg_output(pin); \ + } \ + static uint8_t IsSet() { \ + return (uint8_t)nrf_gpio_pin_read(pin); \ + } \ +}; + +// See: pin_transform.c in RBL nRF51822 SDK +MAKE_PIN(P0, Pin_nRF51822_to_Arduino(D0)); +MAKE_PIN(P1, Pin_nRF51822_to_Arduino(D1)); +MAKE_PIN(P2, Pin_nRF51822_to_Arduino(D2)); +MAKE_PIN(P3, Pin_nRF51822_to_Arduino(D3)); +MAKE_PIN(P4, Pin_nRF51822_to_Arduino(D4)); +MAKE_PIN(P5, Pin_nRF51822_to_Arduino(D5)); +MAKE_PIN(P6, Pin_nRF51822_to_Arduino(D6)); +MAKE_PIN(P7, Pin_nRF51822_to_Arduino(D7)); +MAKE_PIN(P8, Pin_nRF51822_to_Arduino(D8)); +MAKE_PIN(P9, Pin_nRF51822_to_Arduino(D9)); // INT +MAKE_PIN(P10, Pin_nRF51822_to_Arduino(D10)); // SS +MAKE_PIN(P11, Pin_nRF51822_to_Arduino(D11)); +MAKE_PIN(P12, Pin_nRF51822_to_Arduino(D12)); +MAKE_PIN(P13, Pin_nRF51822_to_Arduino(D13)); +MAKE_PIN(P14, Pin_nRF51822_to_Arduino(D14)); +MAKE_PIN(P15, Pin_nRF51822_to_Arduino(D15)); +MAKE_PIN(P17, Pin_nRF51822_to_Arduino(D17)); // MISO +MAKE_PIN(P18, Pin_nRF51822_to_Arduino(D18)); // MOSI +MAKE_PIN(P16, Pin_nRF51822_to_Arduino(D16)); // CLK +MAKE_PIN(P19, Pin_nRF51822_to_Arduino(D19)); +MAKE_PIN(P20, Pin_nRF51822_to_Arduino(D20)); +MAKE_PIN(P21, Pin_nRF51822_to_Arduino(D21)); +MAKE_PIN(P22, Pin_nRF51822_to_Arduino(D22)); +MAKE_PIN(P23, Pin_nRF51822_to_Arduino(D23)); +MAKE_PIN(P24, Pin_nRF51822_to_Arduino(D24)); + +#undef MAKE_PIN + +#else +#error "Please define board in avrpins.h" + +#endif + +#elif defined(__ARDUINO_X86__) // Intel Galileo, Intel Galileo 2 and Intel Edison + +#include + +// Pointers are 32 bits on x86 +#define pgm_read_pointer(p) pgm_read_dword(p) + +#if PLATFORM_ID == 0xE1 // Edison platform id +#define pinToFastPin(pin) 1 // As far as I can tell all pins can be used as fast pins +#endif + +// Pin 2 and 3 on the Intel Galileo supports a higher rate, +// so it is recommended to use one of these as the SS pin. + +#define MAKE_PIN(className, pin) \ +class className { \ +public: \ + static void Set() { \ + fastDigitalWrite(pin, HIGH); \ + } \ + static void Clear() { \ + fastDigitalWrite(pin, LOW); \ + } \ + static void SetDirRead() { \ + if (pinToFastPin(pin)) \ + pinMode(pin, INPUT_FAST); \ + else \ + pinMode(pin, INPUT); \ + } \ + static void SetDirWrite() { \ + if (pinToFastPin(pin)) \ + pinMode(pin, OUTPUT_FAST); \ + else \ + pinMode(pin, OUTPUT); \ + } \ + static uint8_t IsSet() { \ + return fastDigitalRead(pin); \ + } \ +}; + +MAKE_PIN(P0, 0); +MAKE_PIN(P1, 1); +MAKE_PIN(P2, 2); +MAKE_PIN(P3, 3); +MAKE_PIN(P4, 4); +MAKE_PIN(P5, 5); +MAKE_PIN(P6, 6); +MAKE_PIN(P7, 7); +MAKE_PIN(P8, 8); +MAKE_PIN(P9, 9); +MAKE_PIN(P10, 10); +MAKE_PIN(P11, 11); +MAKE_PIN(P12, 12); +MAKE_PIN(P13, 13); +MAKE_PIN(P14, 14); // A0 +MAKE_PIN(P15, 15); // A1 +MAKE_PIN(P16, 16); // A2 +MAKE_PIN(P17, 17); // A3 +MAKE_PIN(P18, 18); // A4 +MAKE_PIN(P19, 19); // A5 + +#undef MAKE_PIN + +#elif defined(__MIPSEL__) +// MIPSEL (MIPS architecture using a little endian byte order) + +// MIPS size_t = 4 +#define pgm_read_pointer(p) pgm_read_dword(p) + +#define MAKE_PIN(className, pin) \ +class className { \ +public: \ + static void Set() { \ + digitalWrite(pin, HIGH);\ + } \ + static void Clear() { \ + digitalWrite(pin, LOW); \ + } \ + static void SetDirRead() { \ + pinMode(pin, INPUT); \ + } \ + static void SetDirWrite() { \ + pinMode(pin, OUTPUT); \ + } \ + static uint8_t IsSet() { \ + return digitalRead(pin); \ + } \ +}; + +// 0 .. 13 - Digital pins +MAKE_PIN(P0, 0); // RX +MAKE_PIN(P1, 1); // TX +MAKE_PIN(P2, 2); // +MAKE_PIN(P3, 3); // +MAKE_PIN(P4, 4); // +MAKE_PIN(P5, 5); // +MAKE_PIN(P6, 6); // +MAKE_PIN(P7, 7); // +MAKE_PIN(P8, 8); // +MAKE_PIN(P9, 9); // +MAKE_PIN(P10, 10); // +MAKE_PIN(P11, 11); // +MAKE_PIN(P12, 12); // +MAKE_PIN(P13, 13); // + +#undef MAKE_PIN + +#else +#error "Please define board in avrpins.h" + +#endif + +#endif //_avrpins_h_ diff --git a/lib/usbhost/USB_Host_Shield_2.0/cdc_XR21B1411.cpp b/lib/usbhost/USB_Host_Shield_2.0/cdc_XR21B1411.cpp new file mode 100644 index 0000000000..74df8c3bdd --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/cdc_XR21B1411.cpp @@ -0,0 +1,211 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#include "cdc_XR21B1411.h" + +XR21B1411::XR21B1411(USB *p, CDCAsyncOper *pasync) : +ACM(p, pasync) { + // Is this needed?? + _enhanced_status = enhanced_features(); // Set up features +} + +uint8_t XR21B1411::Init(uint8_t parent, uint8_t port, bool lowspeed) { + const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR); + + uint8_t buf[constBufSize]; + USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); + + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + uint8_t num_of_conf; // number of configurations + + AddressPool &addrPool = pUsb->GetAddressPool(); + + USBTRACE("XR Init\r\n"); + + if(bAddress) + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; + + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); + + if(!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + if(!p->epinfo) { + USBTRACE("epinfo\r\n"); + return USB_ERROR_EPINFO_IS_NULL; + } + + // Save old pointer to EP_RECORD of address 0 + oldep_ptr = p->epinfo; + + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence + p->epinfo = epInfo; + + p->lowspeed = lowspeed; + + // Get device descriptor + rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf); + + // Restore p->epinfo + p->epinfo = oldep_ptr; + + if(rcode) + goto FailGetDevDescr; + + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, false, port); + + if(!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + // Extract Max Packet Size from the device descriptor + epInfo[0].maxPktSize = udd->bMaxPacketSize0; + + // Assign new address to the device + rcode = pUsb->setAddr(0, 0, bAddress); + + if(rcode) { + p->lowspeed = false; + addrPool.FreeAddress(bAddress); + bAddress = 0; + USBTRACE2("setAddr:", rcode); + return rcode; + } + + USBTRACE2("Addr:", bAddress); + + p->lowspeed = false; + + p = addrPool.GetUsbDevicePtr(bAddress); + + if(!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->lowspeed = lowspeed; + + num_of_conf = udd->bNumConfigurations; + + if((((udd->idVendor != 0x2890U) || (udd->idProduct != 0x0201U)) && ((udd->idVendor != 0x04e2U) || (udd->idProduct != 0x1411U)))) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); + + if(rcode) + goto FailSetDevTblEntry; + + USBTRACE2("NC:", num_of_conf); + + for(uint8_t i = 0; i < num_of_conf; i++) { + ConfigDescParser< USB_CLASS_COM_AND_CDC_CTRL, + CDC_SUBCLASS_ACM, + CDC_PROTOCOL_ITU_T_V_250, + CP_MASK_COMPARE_CLASS | + CP_MASK_COMPARE_SUBCLASS | + CP_MASK_COMPARE_PROTOCOL > CdcControlParser(this); + + ConfigDescParser CdcDataParser(this); + + rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcControlParser); + + if(rcode) + goto FailGetConfDescr; + + rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcDataParser); + + if(rcode) + goto FailGetConfDescr; + + if(bNumEP > 1) + break; + } // for + + if(bNumEP < 4) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); + + USBTRACE2("Conf:", bConfNum); + + // Set Configuration Value + rcode = pUsb->setConf(bAddress, 0, bConfNum); + + if(rcode) + goto FailSetConfDescr; + + // Set up features status + _enhanced_status = enhanced_features(); + half_duplex(false); + autoflowRTS(false); + autoflowDSR(false); + autoflowXON(false); + wide(false); // Always false, because this is only available in custom mode. + + rcode = pAsync->OnInit(this); + + if(rcode) + goto FailOnInit; + + USBTRACE("XR configured\r\n"); + + ready = true; + + //bPollEnable = true; + + //USBTRACE("Poll enabled\r\n"); + return 0; + +FailGetDevDescr: +#ifdef DEBUG_USB_HOST + NotifyFailGetDevDescr(); + goto Fail; +#endif + +FailSetDevTblEntry: +#ifdef DEBUG_USB_HOST + NotifyFailSetDevTblEntry(); + goto Fail; +#endif + +FailGetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailGetConfDescr(); + goto Fail; +#endif + +FailSetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailSetConfDescr(); + goto Fail; +#endif + +FailOnInit: +#ifdef DEBUG_USB_HOST + USBTRACE("OnInit:"); +#endif + +#ifdef DEBUG_USB_HOST +Fail: + NotifyFail(rcode); +#endif + Release(); + return rcode; +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/cdc_XR21B1411.h b/lib/usbhost/USB_Host_Shield_2.0/cdc_XR21B1411.h new file mode 100644 index 0000000000..c32627544f --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/cdc_XR21B1411.h @@ -0,0 +1,272 @@ +/* Copyright (C) 2015 Andrew J. Kroll + and + Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#if !defined(__CDC_XR21B1411_H__) +#define __CDC_XR21B1411_H__ + +#include "cdcacm.h" + +#define XR_REG_CUSTOM_DRIVER (0x020DU) // DRIVER SELECT +#define XR_REG_CUSTOM_DRIVER_ACTIVE (0x0001U) // 0: CDC 1: CUSTOM + +#define XR_REG_ACM_FLOW_CTL (0x0216U) // FLOW CONTROL REGISTER CDCACM MODE +#define XR_REG_FLOW_CTL (0x0C06U) // FLOW CONTROL REGISTER CUSTOM MODE +#define XR_REG_FLOW_CTL_HALF_DPLX (0x0008U) // 0:FULL DUPLEX 1:HALF DUPLEX +#define XR_REG_FLOW_CTL_MODE_MASK (0x0007U) // MODE BITMASK +#define XR_REG_FLOW_CTL_NONE (0x0000U) // NO FLOW CONTROL +#define XR_REG_FLOW_CTL_HW (0x0001U) // HARDWARE FLOW CONTROL +#define XR_REG_FLOW_CTL_SW (0x0002U) // SOFTWARE FLOW CONTROL +#define XR_REG_FLOW_CTL_MMMRX (0x0003U) // MULTIDROP RX UPON ADDRESS MATCH +#define XR_REG_FLOW_CTL_MMMRXTX (0x0004U) // MULTIDROP RX/TX UPON ADDRESS MATCH + +#define XR_REG_ACM_GPIO_MODE (0x0217U) // GPIO MODE REGISTER IN CDCACM MODE +#define XR_REG_GPIO_MODE (0x0C0CU) // GPIO MODE REGISTER IN CUSTOM MODE +#define XR_REG_GPIO_MODE_GPIO (0x0000U) // ALL GPIO PINS ACM PROGRAMMABLE +#define XR_REG_GPIO_MODE_FC_RTSCTS (0x0001U) // AUTO RTSCTS HW FC (GPIO 4/5) +#define XR_REG_GPIO_MODE_FC_DTRDSR (0x0002U) // AUTO DTRDSR HW FC (GPIO 2/3) +#define XR_REG_GPIO_MODE_ATE (0x0003U) // AUTO TRANSCEIVER ENABLE DURING TX (GPIO 5) +#define XR_REG_GPIO_MODE_ATE_ADDRESS (0x0004U) // AUTO TRANSCEIVER ENABLE ON ADDRESS MATCH (GPIO 5) + +#define XR_REG_ACM_GPIO_DIR (0x0218U) // GPIO DIRECTION REGISTER CDCACM MODE, 0:IN 1:OUT +#define XR_REG_GPIO_DIR (0x0C0DU) // GPIO DIRECTION REGISTER CUSTOM MODE, 0:IN 1:OUT + +#define XR_REG_ACM_GPIO_INT (0x0219U) // GPIO PIN CHANGE INTERRUPT ENABLE CDCACM MODE, 0: ENABLED 1: DISABLED +#define XR_REG_GPIO_INT (0x0C11U) // GPIO PIN CHANGE INTERRUPT ENABLE CUSTOM MODE, 0: ENABLED 1: DISABLED +#define XR_REG_GPIO_MASK (0x001FU) // GPIO REGISTERS BITMASK + +#define XR_REG_UART_ENABLE (0x0C00U) // UART I/O ENABLE REGISTER +#define XR_REG_UART_ENABLE_RX (0x0002U) // 0:DISABLED 1:ENABLED +#define XR_REG_UART_ENABLE_TX (0x0001U) // 0:DISABLED 1:ENABLED + +#define XR_REG_ERROR_STATUS (0x0C09U) // ERROR STATUS REGISTER +#define XR_REG_ERROR_STATUS_MASK (0x00F8U) // ERROR STATUS BITMASK +#define XR_REG_ERROR_STATUS_ERROR (0x0078U) // ERROR STATUS ERROR BITMASK +#define XR_REG_ERROR_STATUS_BREAK (0x0008U) // BREAK ERROR HAS BEEN DETECTED +#define XR_REG_ERROR_STATUS_FRAME (0x0010U) // FRAMING ERROR HAS BEEN DETECTED +#define XR_REG_ERROR_STATUS_PARITY (0x0020U) // PARITY ERROR HAS BEEN DETECTED +#define XR_REG_ERROR_STATUS_OVERRUN (0x0040U) // RX OVERRUN ERROR HAS BEEN DETECTED +#define XR_REG_ERROR_STATUS_BREAK_STATUS (0x0080U) // BREAK CONDITION IS CURRENTLY BEING DETECTED + +#define XR_REG_TX_BREAK (0x0C0AU) // TRANSMIT BREAK. 0X0001-0XFFE TIME IN MS, 0X0000 STOP, 0X0FFF BREAK ON + +#define XR_REG_XCVR_EN_DELAY (0x0C0BU) // TURN-ARROUND DELAY IN BIT-TIMES 0X0000-0X000F + +#define XR_REG_GPIO_SET (0x0C0EU) // 1:SET GPIO PIN + +#define XR_REG_GPIO_CLR (0x0C0FU) // 1:CLEAR GPIO PIN + +#define XR_REG_GPIO_STATUS (0x0C10U) // READ GPIO PINS + +#define XR_REG_CUSTOMISED_INT (0x0C12U) // 0:STANDARD 1:CUSTOM SEE DATA SHEET + +#define XR_REG_PIN_PULLUP_ENABLE (0x0C14U) // 0:DISABLE 1:ENABLE, BITS 0-5:GPIO, 6:RX 7:TX + +#define XR_REG_PIN_PULLDOWN_ENABLE (0x0C15U) // 0:DISABLE 1:ENABLE, BITS 0-5:GPIO, 6:RX 7:TX + +#define XR_REG_LOOPBACK (0x0C16U) // 0:DISABLE 1:ENABLE, SEE DATA SHEET + +#define XR_REG_RX_FIFO_LATENCY (0x0CC2U) // FIFO LATENCY REGISTER +#define XR_REG_RX_FIFO_LATENCY_ENABLE (0x0001U) // + +#define XR_REG_WIDE_MODE (0x0D02U) +#define XR_REG_WIDE_MODE_ENABLE (0x0001U) + +#define XR_REG_XON_CHAR (0x0C07U) +#define XR_REG_XOFF_CHAR (0x0C08U) + +#define XR_REG_TX_FIFO_RESET (0x0C80U) // 1: RESET, SELF-CLEARING +#define XR_REG_TX_FIFO_COUNT (0x0C81U) // READ-ONLY +#define XR_REG_RX_FIFO_RESET (0x0CC0U) // 1: RESET, SELF-CLEARING +#define XR_REG_RX_FIFO_COUNT (0x0CC1U) // READ-ONLY + +#define XR_WRITE_REQUEST_TYPE (0x40U) + +#define XR_READ_REQUEST_TYPE (0xC0U) + +#define XR_MAX_ENDPOINTS 4 + +class XR21B1411 : public ACM { +protected: + +public: + XR21B1411(USB *pusb, CDCAsyncOper *pasync); + + /** + * Used by the USB core to check what this driver support. + * @param vid The device's VID. + * @param pid The device's PID. + * @return Returns true if the device's VID and PID matches this driver. + */ + virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) { + return (((vid == 0x2890U) && (pid == 0x0201U)) || ((vid == 0x04e2U) && (pid == 0x1411U))); + }; + + uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + + virtual tty_features enhanced_features(void) { + tty_features rv; + rv.enhanced = true; + rv.autoflow_RTS = true; + rv.autoflow_DSR = true; + rv.autoflow_XON = true; + rv.half_duplex = true; + rv.wide = true; + return rv; + }; + + uint8_t read_register(uint16_t reg, uint16_t *val) { + return (pUsb->ctrlReq(bAddress, 0, XR_READ_REQUEST_TYPE, 1, 0, 0, reg, 2, 2, (uint8_t *)val, NULL)); + } + + uint8_t write_register(uint16_t reg, uint16_t val) { + return (pUsb->ctrlReq(bAddress, 0, XR_WRITE_REQUEST_TYPE, 0, BGRAB0(val), BGRAB1(val), reg, 0, 0, NULL, NULL)); + } + + + //////////////////////////////////////////////////////////////////////// + // The following methods set the CDC-ACM defaults. + //////////////////////////////////////////////////////////////////////// + + virtual void autoflowRTS(bool s) { + uint16_t val; + uint8_t rval; + rval = read_register(XR_REG_ACM_FLOW_CTL, &val); + if(!rval) { + if(s) { + val &= XR_REG_FLOW_CTL_HALF_DPLX; + val |= XR_REG_FLOW_CTL_HW; + } else { + val &= XR_REG_FLOW_CTL_HALF_DPLX; + } + rval = write_register(XR_REG_ACM_FLOW_CTL, val); + if(!rval) { + rval = write_register(XR_REG_ACM_GPIO_MODE, XR_REG_GPIO_MODE_GPIO); + if(!rval) { + // ACM commands apply the new settings. + LINE_CODING LCT; + rval = GetLineCoding(&LCT); + if(!rval) { + rval = SetLineCoding(&LCT); + if(!rval) { + _enhanced_status.autoflow_XON = false; + _enhanced_status.autoflow_DSR = false; + _enhanced_status.autoflow_RTS = s; + } + } + } + } + } + }; + + virtual void autoflowDSR(bool s) { + uint16_t val; + uint8_t rval; + rval = read_register(XR_REG_ACM_FLOW_CTL, &val); + if(!rval) { + if(s) { + val &= XR_REG_FLOW_CTL_HALF_DPLX; + val |= XR_REG_FLOW_CTL_HW; + } else { + val &= XR_REG_FLOW_CTL_HALF_DPLX; + } + rval = write_register(XR_REG_ACM_FLOW_CTL, val); + if(!rval) { + if(s) { + rval = write_register(XR_REG_ACM_GPIO_MODE, XR_REG_GPIO_MODE_FC_DTRDSR); + } else { + rval = write_register(XR_REG_ACM_GPIO_MODE, XR_REG_GPIO_MODE_GPIO); + } + if(!rval) { + // ACM commands apply the new settings. + LINE_CODING LCT; + rval = GetLineCoding(&LCT); + if(!rval) { + rval = SetLineCoding(&LCT); + if(!rval) { + _enhanced_status.autoflow_XON = false; + _enhanced_status.autoflow_RTS = false; + _enhanced_status.autoflow_DSR = s; + } + } + } + } + } + }; + + virtual void autoflowXON(bool s) { + // NOTE: hardware defaults to the normal XON/XOFF + uint16_t val; + uint8_t rval; + rval = read_register(XR_REG_ACM_FLOW_CTL, &val); + if(!rval) { + if(s) { + val &= XR_REG_FLOW_CTL_HALF_DPLX; + val |= XR_REG_FLOW_CTL_SW; + } else { + val &= XR_REG_FLOW_CTL_HALF_DPLX; + } + rval = write_register(XR_REG_ACM_FLOW_CTL, val); + if(!rval) { + rval = write_register(XR_REG_ACM_GPIO_MODE, XR_REG_GPIO_MODE_GPIO); + if(!rval) { + // ACM commands apply the new settings. + LINE_CODING LCT; + rval = GetLineCoding(&LCT); + if(!rval) { + rval = SetLineCoding(&LCT); + if(!rval) { + _enhanced_status.autoflow_RTS = false; + _enhanced_status.autoflow_DSR = false; + _enhanced_status.autoflow_XON = s; + } + } + } + } + } + }; + + virtual void half_duplex(bool s) { + uint16_t val; + uint8_t rval; + rval = read_register(XR_REG_ACM_FLOW_CTL, &val); + if(!rval) { + if(s) { + val |= XR_REG_FLOW_CTL_HALF_DPLX; + } else { + val &= XR_REG_FLOW_CTL_MODE_MASK; + } + rval = write_register(XR_REG_ACM_FLOW_CTL, val); + if(!rval) { + // ACM commands apply the new settings. + LINE_CODING LCT; + rval = GetLineCoding(&LCT); + if(!rval) { + rval = SetLineCoding(&LCT); + if(!rval) { + _enhanced_status.half_duplex = s; + } + } + } + } + }; + + + +}; + +#endif // __CDCPROLIFIC_H__ diff --git a/lib/usbhost/USB_Host_Shield_2.0/cdcacm.cpp b/lib/usbhost/USB_Host_Shield_2.0/cdcacm.cpp new file mode 100644 index 0000000000..2cd2c9a82d --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/cdcacm.cpp @@ -0,0 +1,331 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#include "cdcacm.h" + +const uint8_t ACM::epDataInIndex = 1; +const uint8_t ACM::epDataOutIndex = 2; +const uint8_t ACM::epInterruptInIndex = 3; + +ACM::ACM(USB *p, CDCAsyncOper *pasync) : +pUsb(p), +pAsync(pasync), +bAddress(0), +bControlIface(0), +bDataIface(0), +bNumEP(1), +qNextPollTime(0), +bPollEnable(false), +ready(false) { + _enhanced_status = enhanced_features(); // Set up features + for(uint8_t i = 0; i < ACM_MAX_ENDPOINTS; i++) { + epInfo[i].epAddr = 0; + epInfo[i].maxPktSize = (i) ? 0 : 8; + epInfo[i].epAttribs = 0; + epInfo[i].bmNakPower = (i == epDataInIndex) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; + + } + if(pUsb) + pUsb->RegisterDeviceClass(this); +} + +uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed) { + + const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR); + + uint8_t buf[constBufSize]; + USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); + + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + uint8_t num_of_conf; // number of configurations + + AddressPool &addrPool = pUsb->GetAddressPool(); + + USBTRACE("ACM Init\r\n"); + + if(bAddress) + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; + + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); + + if(!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + if(!p->epinfo) { + USBTRACE("epinfo\r\n"); + return USB_ERROR_EPINFO_IS_NULL; + } + + // Save old pointer to EP_RECORD of address 0 + oldep_ptr = p->epinfo; + + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence + p->epinfo = epInfo; + + p->lowspeed = lowspeed; + + // Get device descriptor + rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf); + + // Restore p->epinfo + p->epinfo = oldep_ptr; + + if(rcode) + goto FailGetDevDescr; + + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, false, port); + + if(!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + // Extract Max Packet Size from the device descriptor + epInfo[0].maxPktSize = udd->bMaxPacketSize0; + + // Assign new address to the device + rcode = pUsb->setAddr(0, 0, bAddress); + + if(rcode) { + p->lowspeed = false; + addrPool.FreeAddress(bAddress); + bAddress = 0; + USBTRACE2("setAddr:", rcode); + return rcode; + } + + USBTRACE2("Addr:", bAddress); + + p->lowspeed = false; + + p = addrPool.GetUsbDevicePtr(bAddress); + + if(!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->lowspeed = lowspeed; + + num_of_conf = udd->bNumConfigurations; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); + + if(rcode) + goto FailSetDevTblEntry; + + USBTRACE2("NC:", num_of_conf); + + for(uint8_t i = 0; i < num_of_conf; i++) { + ConfigDescParser< USB_CLASS_COM_AND_CDC_CTRL, + CDC_SUBCLASS_ACM, + CDC_PROTOCOL_ITU_T_V_250, + CP_MASK_COMPARE_CLASS | + CP_MASK_COMPARE_SUBCLASS | + CP_MASK_COMPARE_PROTOCOL > CdcControlParser(this); + + ConfigDescParser CdcDataParser(this); + + rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcControlParser); + + if(rcode) + goto FailGetConfDescr; + + rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcDataParser); + + if(rcode) + goto FailGetConfDescr; + + if(bNumEP > 1) + break; + } // for + + if(bNumEP < 4) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); + + USBTRACE2("Conf:", bConfNum); + + // Set Configuration Value + rcode = pUsb->setConf(bAddress, 0, bConfNum); + + if(rcode) + goto FailSetConfDescr; + + // Set up features status + _enhanced_status = enhanced_features(); + half_duplex(false); + autoflowRTS(false); + autoflowDSR(false); + autoflowXON(false); + wide(false); // Always false, because this is only available in custom mode. + rcode = pAsync->OnInit(this); + + if(rcode) + goto FailOnInit; + + USBTRACE("ACM configured\r\n"); + + ready = true; + + //bPollEnable = true; + + //USBTRACE("Poll enabled\r\n"); + return 0; + +FailGetDevDescr: +#ifdef DEBUG_USB_HOST + NotifyFailGetDevDescr(); + goto Fail; +#endif + +FailSetDevTblEntry: +#ifdef DEBUG_USB_HOST + NotifyFailSetDevTblEntry(); + goto Fail; +#endif + +FailGetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailGetConfDescr(); + goto Fail; +#endif + +FailSetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailSetConfDescr(); + goto Fail; +#endif + +FailOnInit: +#ifdef DEBUG_USB_HOST + USBTRACE("OnInit:"); +#endif + +#ifdef DEBUG_USB_HOST +Fail: + NotifyFail(rcode); +#endif + Release(); + return rcode; +} + +void ACM::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) { + //ErrorMessage (PSTR("Conf.Val"), conf); + //ErrorMessage (PSTR("Iface Num"), iface); + //ErrorMessage (PSTR("Alt.Set"), alt); + + bConfNum = conf; + + uint8_t index; + + if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) + index = epInterruptInIndex; + else + if((pep->bmAttributes & 0x02) == 2) + index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex; + else + return; + + // Fill in the endpoint info structure + epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); + epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; + epInfo[index].epAttribs = 0; + + bNumEP++; + + PrintEndpointDescriptor(pep); +} + +uint8_t ACM::Release() { + ready = false; + pUsb->GetAddressPool().FreeAddress(bAddress); + + bControlIface = 0; + bDataIface = 0; + bNumEP = 1; + + bAddress = 0; + qNextPollTime = 0; + bPollEnable = false; + return 0; +} + +uint8_t ACM::Poll() { + uint8_t rcode = 0; + + if(!bPollEnable) + return 0; + + return rcode; +} + +uint8_t ACM::RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr) { + return pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr); +} + +uint8_t ACM::SndData(uint16_t nbytes, uint8_t *dataptr) { + return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, nbytes, dataptr); +} + +uint8_t ACM::SetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr) { + return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SET_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, nbytes, nbytes, dataptr, NULL)); +} + +uint8_t ACM::GetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr) { + return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCIN, CDC_GET_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, nbytes, nbytes, dataptr, NULL)); +} + +uint8_t ACM::ClearCommFeature(uint16_t fid) { + return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_CLEAR_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, 0, 0, NULL, NULL)); +} + +uint8_t ACM::SetLineCoding(const LINE_CODING *dataptr) { + return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SET_LINE_CODING, 0x00, 0x00, bControlIface, sizeof (LINE_CODING), sizeof (LINE_CODING), (uint8_t*)dataptr, NULL)); +} + +uint8_t ACM::GetLineCoding(LINE_CODING *dataptr) { + return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCIN, CDC_GET_LINE_CODING, 0x00, 0x00, bControlIface, sizeof (LINE_CODING), sizeof (LINE_CODING), (uint8_t*)dataptr, NULL)); +} + +uint8_t ACM::SetControlLineState(uint8_t state) { + return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SET_CONTROL_LINE_STATE, state, 0, bControlIface, 0, 0, NULL, NULL)); +} + +uint8_t ACM::SendBreak(uint16_t duration) { + return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SEND_BREAK, (duration & 0xff), (duration >> 8), bControlIface, 0, 0, NULL, NULL)); +} + +void ACM::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) { + Notify(PSTR("Endpoint descriptor:"), 0x80); + Notify(PSTR("\r\nLength:\t\t"), 0x80); + D_PrintHex (ep_ptr->bLength, 0x80); + Notify(PSTR("\r\nType:\t\t"), 0x80); + D_PrintHex (ep_ptr->bDescriptorType, 0x80); + Notify(PSTR("\r\nAddress:\t"), 0x80); + D_PrintHex (ep_ptr->bEndpointAddress, 0x80); + Notify(PSTR("\r\nAttributes:\t"), 0x80); + D_PrintHex (ep_ptr->bmAttributes, 0x80); + Notify(PSTR("\r\nMaxPktSize:\t"), 0x80); + D_PrintHex (ep_ptr->wMaxPacketSize, 0x80); + Notify(PSTR("\r\nPoll Intrv:\t"), 0x80); + D_PrintHex (ep_ptr->bInterval, 0x80); + Notify(PSTR("\r\n"), 0x80); +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/cdcacm.h b/lib/usbhost/USB_Host_Shield_2.0/cdcacm.h new file mode 100644 index 0000000000..2a38524d8c --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/cdcacm.h @@ -0,0 +1,252 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#if !defined(__CDCACM_H__) +#define __CDCACM_H__ + +#include "Usb.h" + +#define bmREQ_CDCOUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE +#define bmREQ_CDCIN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE + +// CDC Subclass Constants +#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_CAPI 0x05 // CAPI Control Model +#define CDC_SUBCLASS_ETHERNET 0x06 // Ethernet Network Control Model +#define CDC_SUBCLASS_ATM 0x07 // ATM Network Control Model +#define CDC_SUBCLASS_WIRELESS_HANDSET 0x08 // Wireless Handset Control Model +#define CDC_SUBCLASS_DEVICE_MANAGEMENT 0x09 // Device Management +#define CDC_SUBCLASS_MOBILE_DIRECT_LINE 0x0A // Mobile Direct Line Model +#define CDC_SUBCLASS_OBEX 0x0B // OBEX +#define CDC_SUBCLASS_ETHERNET_EMU 0x0C // Ethernet Emulation Model + +// Communication Interface Class Control Protocol Codes +#define CDC_PROTOCOL_ITU_T_V_250 0x01 // AT Commands defined by ITU-T V.250 +#define CDC_PROTOCOL_PCCA_101 0x02 // AT Commands defined by PCCA-101 +#define CDC_PROTOCOL_PCCA_101_O 0x03 // AT Commands defined by PCCA-101 & Annex O +#define CDC_PROTOCOL_GSM_7_07 0x04 // AT Commands defined by GSM 7.07 +#define CDC_PROTOCOL_3GPP_27_07 0x05 // AT Commands defined by 3GPP 27.007 +#define CDC_PROTOCOL_C_S0017_0 0x06 // AT Commands defined by TIA for CDMA +#define CDC_PROTOCOL_USB_EEM 0x07 // Ethernet Emulation Model + +// CDC Commands defined by CDC 1.2 +#define CDC_SEND_ENCAPSULATED_COMMAND 0x00 +#define CDC_GET_ENCAPSULATED_RESPONSE 0x01 + +// CDC Commands defined by PSTN 1.2 +#define CDC_SET_COMM_FEATURE 0x02 +#define CDC_GET_COMM_FEATURE 0x03 +#define CDC_CLEAR_COMM_FEATURE 0x04 +#define CDC_SET_AUX_LINE_STATE 0x10 +#define CDC_SET_HOOK_STATE 0x11 +#define CDC_PULSE_SETUP 0x12 +#define CDC_SEND_PULSE 0x13 +#define CDC_SET_PULSE_TIME 0x14 +#define CDC_RING_AUX_JACK 0x15 +#define CDC_SET_LINE_CODING 0x20 +#define CDC_GET_LINE_CODING 0x21 +#define CDC_SET_CONTROL_LINE_STATE 0x22 +#define CDC_SEND_BREAK 0x23 +#define CDC_SET_RINGER_PARMS 0x30 +#define CDC_GET_RINGER_PARMS 0x31 +#define CDC_SET_OPERATION_PARMS 0x32 +#define CDC_GET_OPERATION_PARMS 0x33 +#define CDC_SET_LINE_PARMS 0x34 +#define CDC_GET_LINE_PARMS 0x35 +#define CDC_DIAL_DIGITS 0x36 + +//Class-Specific Notification Codes +#define NETWORK_CONNECTION 0x00 +#define RESPONSE_AVAILABLE 0x01 +#define AUX_JACK_HOOK_STATE 0x08 +#define RING_DETECT 0x09 +#define SERIAL_STATE 0x20 +#define CALL_STATE_CHANGE 0x28 +#define LINE_STATE_CHANGE 0x29 +#define CONNECTION_SPEED_CHANGE 0x2a + +// CDC Functional Descriptor Structures + +typedef struct { + uint8_t bFunctionLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bmCapabilities; + uint8_t bDataInterface; +} CALL_MGMNT_FUNC_DESCR; + +typedef struct { + uint8_t bFunctionLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bmCapabilities; +} ACM_FUNC_DESCR, DLM_FUNC_DESCR, TEL_OPER_MODES_FUNC_DESCR, +TEL_CALL_STATE_REP_CPBL_FUNC_DESCR; + +typedef struct { + uint8_t bFunctionLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bRingerVolSteps; + uint8_t bNumRingerPatterns; +} TEL_RINGER_FUNC_DESCR; + +typedef struct { + uint32_t dwDTERate; // Data Terminal Rate in bits per second + uint8_t bCharFormat; // 0 - 1 stop bit, 1 - 1.5 stop bits, 2 - 2 stop bits + uint8_t bParityType; // 0 - None, 1 - Odd, 2 - Even, 3 - Mark, 4 - Space + uint8_t bDataBits; // Data bits (5, 6, 7, 8 or 16) +} LINE_CODING; + +typedef struct { + uint8_t bmRequestType; // 0xa1 for class-specific notifications + uint8_t bNotification; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; + uint16_t bmState; //UART state bitmap for SERIAL_STATE, other notifications variable length +} CLASS_NOTIFICATION; + +class ACM; + +class CDCAsyncOper { +public: + + virtual uint8_t OnInit(ACM *pacm) { + return 0; + }; + //virtual void OnDataRcvd(ACM *pacm, uint8_t nbytes, uint8_t *dataptr) = 0; + //virtual void OnDisconnected(ACM *pacm) = 0; +}; + +/** + * This structure is used to report the extended capabilities of the connected device. + * It is also used to report the current status. + * Regular CDC-ACM reports all as false. + */ +typedef struct { + + union { + uint8_t tty; + + struct { + bool enhanced : 1; // Do we have the ability to set/clear any features? + // Status and 8th bit in data stream. + // Presence only indicates feature is available, but this isn't used for CDC-ACM. + bool wide : 1; + bool autoflow_RTS : 1; // Has autoflow on RTS/CTS + bool autoflow_DSR : 1; // Has autoflow on DTR/DSR + bool autoflow_XON : 1; // Has autoflow XON/XOFF + bool half_duplex : 1; // Has half-duplex capability. + } __attribute__((packed)); + }; +} tty_features; + +#define ACM_MAX_ENDPOINTS 4 + +class ACM : public USBDeviceConfig, public UsbConfigXtracter { +protected: + static const uint8_t epDataInIndex; // DataIn endpoint index + static const uint8_t epDataOutIndex; // DataOUT endpoint index + static const uint8_t epInterruptInIndex; // InterruptIN endpoint index + + USB *pUsb; + CDCAsyncOper *pAsync; + uint8_t bAddress; + uint8_t bConfNum; // configuration number + uint8_t bControlIface; // Control interface value + uint8_t bDataIface; // Data interface value + uint8_t bNumEP; // total number of EP in the configuration + uint32_t qNextPollTime; // next poll time + volatile bool bPollEnable; // poll enable flag + volatile bool ready; //device ready indicator + tty_features _enhanced_status; // current status + + EpInfo epInfo[ACM_MAX_ENDPOINTS]; + + void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); + +public: + ACM(USB *pusb, CDCAsyncOper *pasync); + + uint8_t SetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr); + uint8_t GetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr); + uint8_t ClearCommFeature(uint16_t fid); + uint8_t SetLineCoding(const LINE_CODING *dataptr); + uint8_t GetLineCoding(LINE_CODING *dataptr); + uint8_t SetControlLineState(uint8_t state); + uint8_t SendBreak(uint16_t duration); + uint8_t GetNotif(uint16_t *bytes_rcvd, uint8_t *dataptr); + + // Methods for receiving and sending data + uint8_t RcvData(uint16_t *nbytesptr, uint8_t *dataptr); + uint8_t SndData(uint16_t nbytes, uint8_t *dataptr); + + // USBDeviceConfig implementation + uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + uint8_t Release(); + uint8_t Poll(); + + bool available(void) { + return false; + }; + + virtual uint8_t GetAddress() { + return bAddress; + }; + + virtual bool isReady() { + return ready; + }; + + virtual tty_features enhanced_status(void) { + return _enhanced_status; + }; + + virtual tty_features enhanced_features(void) { + tty_features rv; + rv.enhanced = false; + rv.autoflow_RTS = false; + rv.autoflow_DSR = false; + rv.autoflow_XON = false; + rv.half_duplex = false; + rv.wide = false; + return rv; + }; + + virtual void autoflowRTS(bool s) { + }; + + virtual void autoflowDSR(bool s) { + }; + + virtual void autoflowXON(bool s) { + }; + + virtual void half_duplex(bool s) { + }; + + virtual void wide(bool s) { + }; + + // UsbConfigXtracter implementation + void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); +}; + +#endif // __CDCACM_H__ diff --git a/lib/usbhost/USB_Host_Shield_2.0/cdcftdi.cpp b/lib/usbhost/USB_Host_Shield_2.0/cdcftdi.cpp new file mode 100644 index 0000000000..80d21d16ec --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/cdcftdi.cpp @@ -0,0 +1,334 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#include "cdcftdi.h" + +const uint8_t FTDI::epDataInIndex = 1; +const uint8_t FTDI::epDataOutIndex = 2; +const uint8_t FTDI::epInterruptInIndex = 3; + +FTDI::FTDI(USB *p, FTDIAsyncOper *pasync) : +pAsync(pasync), +pUsb(p), +bAddress(0), +bNumEP(1), +wFTDIType(0) { + for(uint8_t i = 0; i < FTDI_MAX_ENDPOINTS; i++) { + epInfo[i].epAddr = 0; + epInfo[i].maxPktSize = (i) ? 0 : 8; + epInfo[i].epAttribs = 0; + epInfo[i].bmNakPower = (i==epDataInIndex) ? USB_NAK_NOWAIT: USB_NAK_MAX_POWER; + } + if(pUsb) + pUsb->RegisterDeviceClass(this); +} + +uint8_t FTDI::Init(uint8_t parent, uint8_t port, bool lowspeed) { + const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR); + + uint8_t buf[constBufSize]; + USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + + uint8_t num_of_conf; // number of configurations + + AddressPool &addrPool = pUsb->GetAddressPool(); + + USBTRACE("FTDI Init\r\n"); + + if(bAddress) + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; + + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); + + if(!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + if(!p->epinfo) { + USBTRACE("epinfo\r\n"); + return USB_ERROR_EPINFO_IS_NULL; + } + + // Save old pointer to EP_RECORD of address 0 + oldep_ptr = p->epinfo; + + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence + p->epinfo = epInfo; + + p->lowspeed = lowspeed; + + // Get device descriptor + rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), buf); + + // Restore p->epinfo + p->epinfo = oldep_ptr; + + if(rcode) + goto FailGetDevDescr; + if(udd->idVendor != FTDI_VID || udd->idProduct != FTDI_PID) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + // Save type of FTDI chip + wFTDIType = udd->bcdDevice; + + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, false, port); + + if(!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + // Extract Max Packet Size from the device descriptor + epInfo[0].maxPktSize = udd->bMaxPacketSize0; + + // Assign new address to the device + rcode = pUsb->setAddr(0, 0, bAddress); + + if(rcode) { + p->lowspeed = false; + addrPool.FreeAddress(bAddress); + bAddress = 0; + USBTRACE2("setAddr:", rcode); + return rcode; + } + + USBTRACE2("Addr:", bAddress); + + p->lowspeed = false; + + p = addrPool.GetUsbDevicePtr(bAddress); + + if(!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->lowspeed = lowspeed; + + num_of_conf = udd->bNumConfigurations; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); + + if(rcode) + goto FailSetDevTblEntry; + + USBTRACE2("NC:", num_of_conf); + + for(uint8_t i = 0; i < num_of_conf; i++) { + HexDumper HexDump; + ConfigDescParser < 0xFF, 0xFF, 0xFF, CP_MASK_COMPARE_ALL> confDescrParser(this); + + rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump); + + if(rcode) + goto FailGetConfDescr; + + rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); + + if(rcode) + goto FailGetConfDescr; + + if(bNumEP > 1) + break; + } // for + + if(bNumEP < 2) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + USBTRACE2("NumEP:", bNumEP); + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); + + USBTRACE2("Conf:", bConfNum); + + // Set Configuration Value + rcode = pUsb->setConf(bAddress, 0, bConfNum); + + if(rcode) + goto FailSetConfDescr; + + rcode = pAsync->OnInit(this); + + if(rcode) + goto FailOnInit; + + USBTRACE("FTDI configured\r\n"); + + bPollEnable = true; + return 0; + +FailGetDevDescr: +#ifdef DEBUG_USB_HOST + NotifyFailGetDevDescr(); + goto Fail; +#endif + +FailSetDevTblEntry: +#ifdef DEBUG_USB_HOST + NotifyFailSetDevTblEntry(); + goto Fail; +#endif + +FailGetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailGetConfDescr(); + goto Fail; +#endif + +FailSetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailSetConfDescr(); + goto Fail; +#endif + +FailOnInit: +#ifdef DEBUG_USB_HOST + USBTRACE("OnInit:"); + +Fail: + NotifyFail(rcode); +#endif + Release(); + return rcode; +} + +void FTDI::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) { + ErrorMessage (PSTR("Conf.Val"), conf); + ErrorMessage (PSTR("Iface Num"), iface); + ErrorMessage (PSTR("Alt.Set"), alt); + + bConfNum = conf; + + uint8_t index; + + if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) + index = epInterruptInIndex; + else + if((pep->bmAttributes & 0x02) == 2) + index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex; + else + return; + + // Fill in the endpoint info structure + epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); + epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; + epInfo[index].epAttribs = 0; + + bNumEP++; + + PrintEndpointDescriptor(pep); +} + +uint8_t FTDI::Release() { + pUsb->GetAddressPool().FreeAddress(bAddress); + + bAddress = 0; + bNumEP = 1; + qNextPollTime = 0; + bPollEnable = false; + return pAsync->OnRelease(this); +} + +uint8_t FTDI::Poll() { + uint8_t rcode = 0; + + //if (!bPollEnable) + // return 0; + + //if (qNextPollTime <= millis()) + //{ + // USB_HOST_SERIAL.println(bAddress, HEX); + + // qNextPollTime = millis() + 100; + //} + return rcode; +} + +uint8_t FTDI::SetBaudRate(uint32_t baud) { + uint16_t baud_value, baud_index = 0; + uint32_t divisor3; + + divisor3 = 48000000 / 2 / baud; // divisor shifted 3 bits to the left + + if(wFTDIType == FT232AM) { + if((divisor3 & 0x7) == 7) + divisor3++; // round x.7/8 up to x+1 + + baud_value = divisor3 >> 3; + divisor3 &= 0x7; + + if(divisor3 == 1) baud_value |= 0xc000; + else // 0.125 + if(divisor3 >= 4) baud_value |= 0x4000; + else // 0.5 + if(divisor3 != 0) baud_value |= 0x8000; // 0.25 + if(baud_value == 1) baud_value = 0; /* special case for maximum baud rate */ + } else { + static const unsigned char divfrac [8] = {0, 3, 2, 0, 1, 1, 2, 3}; + static const unsigned char divindex[8] = {0, 0, 0, 1, 0, 1, 1, 1}; + + baud_value = divisor3 >> 3; + baud_value |= divfrac [divisor3 & 0x7] << 14; + baud_index = divindex[divisor3 & 0x7]; + + /* Deal with special cases for highest baud rates. */ + if(baud_value == 1) baud_value = 0; + else // 1.0 + if(baud_value == 0x4001) baud_value = 1; // 1.5 + } + USBTRACE2("baud_value:", baud_value); + USBTRACE2("baud_index:", baud_index); + return pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_SET_BAUD_RATE, baud_value & 0xff, baud_value >> 8, baud_index, 0, 0, NULL, NULL); +} + +uint8_t FTDI::SetModemControl(uint16_t signal) { + return pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_MODEM_CTRL, signal & 0xff, signal >> 8, 0, 0, 0, NULL, NULL); +} + +uint8_t FTDI::SetFlowControl(uint8_t protocol, uint8_t xon, uint8_t xoff) { + return pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_SET_FLOW_CTRL, xon, xoff, protocol << 8, 0, 0, NULL, NULL); +} + +uint8_t FTDI::SetData(uint16_t databm) { + return pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_SET_DATA, databm & 0xff, databm >> 8, 0, 0, 0, NULL, NULL); +} + +uint8_t FTDI::RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr) { + return pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr); +} + +uint8_t FTDI::SndData(uint16_t nbytes, uint8_t *dataptr) { + return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, nbytes, dataptr); +} + +void FTDI::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) { + Notify(PSTR("Endpoint descriptor:"), 0x80); + Notify(PSTR("\r\nLength:\t\t"), 0x80); + D_PrintHex (ep_ptr->bLength, 0x80); + Notify(PSTR("\r\nType:\t\t"), 0x80); + D_PrintHex (ep_ptr->bDescriptorType, 0x80); + Notify(PSTR("\r\nAddress:\t"), 0x80); + D_PrintHex (ep_ptr->bEndpointAddress, 0x80); + Notify(PSTR("\r\nAttributes:\t"), 0x80); + D_PrintHex (ep_ptr->bmAttributes, 0x80); + Notify(PSTR("\r\nMaxPktSize:\t"), 0x80); + D_PrintHex (ep_ptr->wMaxPacketSize, 0x80); + Notify(PSTR("\r\nPoll Intrv:\t"), 0x80); + D_PrintHex (ep_ptr->bInterval, 0x80); + Notify(PSTR("\r\n"), 0x80); +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/cdcftdi.h b/lib/usbhost/USB_Host_Shield_2.0/cdcftdi.h new file mode 100644 index 0000000000..b731252629 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/cdcftdi.h @@ -0,0 +1,145 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#if !defined(__CDCFTDI_H__) +#define __CDCFTDI_H__ + +#include "Usb.h" + +#define bmREQ_FTDI_OUT 0x40 +#define bmREQ_FTDI_IN 0xc0 + +//#define bmREQ_FTDI_OUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE +//#define bmREQ_FTDI_IN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE + +#define FTDI_VID 0x0403 // FTDI VID +#define FTDI_PID 0x6001 // FTDI PID + +#define FT232AM 0x0200 +#define FT232BM 0x0400 +#define FT2232 0x0500 +#define FT232R 0x0600 + +// Commands +#define FTDI_SIO_RESET 0 /* Reset the port */ +#define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ +#define FTDI_SIO_SET_FLOW_CTRL 2 /* Set flow control register */ +#define FTDI_SIO_SET_BAUD_RATE 3 /* Set baud rate */ +#define FTDI_SIO_SET_DATA 4 /* Set the data characteristics of the port */ +#define FTDI_SIO_GET_MODEM_STATUS 5 /* Retrieve current value of modem status register */ +#define FTDI_SIO_SET_EVENT_CHAR 6 /* Set the event character */ +#define FTDI_SIO_SET_ERROR_CHAR 7 /* Set the error character */ + +#define FTDI_SIO_RESET_SIO 0 +#define FTDI_SIO_RESET_PURGE_RX 1 +#define FTDI_SIO_RESET_PURGE_TX 2 + +#define FTDI_SIO_SET_DATA_PARITY_NONE (0x0 << 8 ) +#define FTDI_SIO_SET_DATA_PARITY_ODD (0x1 << 8 ) +#define FTDI_SIO_SET_DATA_PARITY_EVEN (0x2 << 8 ) +#define FTDI_SIO_SET_DATA_PARITY_MARK (0x3 << 8 ) +#define FTDI_SIO_SET_DATA_PARITY_SPACE (0x4 << 8 ) +#define FTDI_SIO_SET_DATA_STOP_BITS_1 (0x0 << 11) +#define FTDI_SIO_SET_DATA_STOP_BITS_15 (0x1 << 11) +#define FTDI_SIO_SET_DATA_STOP_BITS_2 (0x2 << 11) +#define FTDI_SIO_SET_BREAK (0x1 << 14) + +#define FTDI_SIO_SET_DTR_MASK 0x1 +#define FTDI_SIO_SET_DTR_HIGH ( 1 | ( FTDI_SIO_SET_DTR_MASK << 8)) +#define FTDI_SIO_SET_DTR_LOW ( 0 | ( FTDI_SIO_SET_DTR_MASK << 8)) +#define FTDI_SIO_SET_RTS_MASK 0x2 +#define FTDI_SIO_SET_RTS_HIGH ( 2 | ( FTDI_SIO_SET_RTS_MASK << 8 )) +#define FTDI_SIO_SET_RTS_LOW ( 0 | ( FTDI_SIO_SET_RTS_MASK << 8 )) + +#define FTDI_SIO_DISABLE_FLOW_CTRL 0x0 +#define FTDI_SIO_RTS_CTS_HS (0x1 << 8) +#define FTDI_SIO_DTR_DSR_HS (0x2 << 8) +#define FTDI_SIO_XON_XOFF_HS (0x4 << 8) + +#define FTDI_SIO_CTS_MASK 0x10 +#define FTDI_SIO_DSR_MASK 0x20 +#define FTDI_SIO_RI_MASK 0x40 +#define FTDI_SIO_RLSD_MASK 0x80 + +class FTDI; + +class FTDIAsyncOper { +public: + + virtual uint8_t OnInit(FTDI *pftdi) { + return 0; + }; + + virtual uint8_t OnRelease(FTDI *pftdi) { + return 0; + }; +}; + + +// Only single port chips are currently supported by the library, +// so only three endpoints are allocated. +#define FTDI_MAX_ENDPOINTS 3 + +class FTDI : public USBDeviceConfig, public UsbConfigXtracter { + static const uint8_t epDataInIndex; // DataIn endpoint index + static const uint8_t epDataOutIndex; // DataOUT endpoint index + static const uint8_t epInterruptInIndex; // InterruptIN endpoint index + + FTDIAsyncOper *pAsync; + USB *pUsb; + uint8_t bAddress; + uint8_t bConfNum; // configuration number + uint8_t bNumIface; // number of interfaces in the configuration + uint8_t bNumEP; // total number of EP in the configuration + uint32_t qNextPollTime; // next poll time + bool bPollEnable; // poll enable flag + uint16_t wFTDIType; // Type of FTDI chip + + EpInfo epInfo[FTDI_MAX_ENDPOINTS]; + + void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); + +public: + FTDI(USB *pusb, FTDIAsyncOper *pasync); + + uint8_t SetBaudRate(uint32_t baud); + uint8_t SetModemControl(uint16_t control); + uint8_t SetFlowControl(uint8_t protocol, uint8_t xon = 0x11, uint8_t xoff = 0x13); + uint8_t SetData(uint16_t databm); + + // Methods for recieving and sending data + uint8_t RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr); + uint8_t SndData(uint16_t nbytes, uint8_t *dataptr); + + // USBDeviceConfig implementation + uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + uint8_t Release(); + uint8_t Poll(); + + virtual uint8_t GetAddress() { + return bAddress; + }; + + // UsbConfigXtracter implementation + void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); + + virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) { + return (vid == FTDI_VID && pid == FTDI_PID); + } + +}; + +#endif // __CDCFTDI_H__ diff --git a/lib/usbhost/USB_Host_Shield_2.0/cdcprolific.cpp b/lib/usbhost/USB_Host_Shield_2.0/cdcprolific.cpp new file mode 100644 index 0000000000..eceb1df9f3 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/cdcprolific.cpp @@ -0,0 +1,247 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#include "cdcprolific.h" + +PL2303::PL2303(USB *p, CDCAsyncOper *pasync) : +ACM(p, pasync), +wPLType(0) { +} + +uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) { + const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR); + + uint8_t buf[constBufSize]; + USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + uint8_t num_of_conf; // number of configurations +#ifdef PL2303_COMPAT + enum pl2303_type pltype = unknown; +#endif + + AddressPool &addrPool = pUsb->GetAddressPool(); + + USBTRACE("PL Init\r\n"); + + if(bAddress) + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; + + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); + + if(!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + if(!p->epinfo) { + USBTRACE("epinfo\r\n"); + return USB_ERROR_EPINFO_IS_NULL; + } + + // Save old pointer to EP_RECORD of address 0 + oldep_ptr = p->epinfo; + + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence + p->epinfo = epInfo; + + p->lowspeed = lowspeed; + + // Get device descriptor + rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); + + // Restore p->epinfo + p->epinfo = oldep_ptr; + + if(rcode) + goto FailGetDevDescr; + + if(udd->idVendor != PL_VID && CHECK_PID(udd->idProduct)) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + /* determine chip variant */ +#ifdef PL2303_COMPAT + if(udd->bDeviceClass == 0x02 ) + pltype = type_0; + else if(udd->bMaxPacketSize0 == 0x40 ) + pltype = rev_HX; + else if(udd->bDeviceClass == 0x00) + pltype = type_1; + else if(udd->bDeviceClass == 0xff) + pltype = type_1; +#endif + + // Save type of PL chip + wPLType = udd->bcdDevice; + + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, false, port); + + if(!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + // Extract Max Packet Size from the device descriptor + epInfo[0].maxPktSize = udd->bMaxPacketSize0; + + // Assign new address to the device + rcode = pUsb->setAddr(0, 0, bAddress); + + if(rcode) { + p->lowspeed = false; + addrPool.FreeAddress(bAddress); + bAddress = 0; + USBTRACE2("setAddr:", rcode); + return rcode; + } + + USBTRACE2("Addr:", bAddress); + + p->lowspeed = false; + + p = addrPool.GetUsbDevicePtr(bAddress); + + if(!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->lowspeed = lowspeed; + + num_of_conf = udd->bNumConfigurations; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); + + if(rcode) + goto FailSetDevTblEntry; + + USBTRACE2("NC:", num_of_conf); + + for(uint8_t i = 0; i < num_of_conf; i++) { + HexDumper HexDump; + ConfigDescParser < 0xFF, 0, 0, CP_MASK_COMPARE_CLASS> confDescrParser(this); + + rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump); + + if(rcode) + goto FailGetConfDescr; + + rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); + + if(rcode) + goto FailGetConfDescr; + + if(bNumEP > 1) + break; + } // for + + if(bNumEP < 2) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); + + USBTRACE2("Conf:", bConfNum); + + // Set Configuration Value + rcode = pUsb->setConf(bAddress, 0, bConfNum); + + if(rcode) + goto FailSetConfDescr; + +#ifdef PL2303_COMPAT + /* Shamanic dance - sending Prolific init data as-is */ + vendorRead( 0x84, 0x84, 0, buf ); + vendorWrite( 0x04, 0x04, 0 ); + vendorRead( 0x84, 0x84, 0, buf ); + vendorRead( 0x83, 0x83, 0, buf ); + vendorRead( 0x84, 0x84, 0, buf ); + vendorWrite( 0x04, 0x04, 1 ); + vendorRead( 0x84, 0x84, 0, buf); + vendorRead( 0x83, 0x83, 0, buf); + vendorWrite( 0, 0, 1 ); + vendorWrite( 1, 0, 0 ); + if( pltype == rev_HX ) { + vendorWrite( 2, 0, 0x44 ); + vendorWrite( 0x06, 0x06, 0 ); // From W7 init + } + else { + vendorWrite( 2, 0, 0x24 ); + } + /* Shamanic dance end */ +#endif + /* Calling post-init callback */ + rcode = pAsync->OnInit(this); + + if(rcode) + goto FailOnInit; + + USBTRACE("PL configured\r\n"); + + //bPollEnable = true; + ready = true; + return 0; + +FailGetDevDescr: +#ifdef DEBUG_USB_HOST + NotifyFailGetDevDescr(); + goto Fail; +#endif + +FailSetDevTblEntry: +#ifdef DEBUG_USB_HOST + NotifyFailSetDevTblEntry(); + goto Fail; +#endif + +FailGetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailGetConfDescr(); + goto Fail; +#endif + +FailSetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailSetConfDescr(); + goto Fail; +#endif + +FailOnInit: +#ifdef DEBUG_USB_HOST + USBTRACE("OnInit:"); +#endif + +#ifdef DEBUG_USB_HOST +Fail: + NotifyFail(rcode); +#endif + Release(); + return rcode; +} + +//uint8_t PL::Poll() +//{ +// uint8_t rcode = 0; +// +// //if (!bPollEnable) +// // return 0; +// +// //if (qNextPollTime <= millis()) +// //{ +// // USB_HOST_SERIAL.println(bAddress, HEX); +// +// // qNextPollTime = millis() + 100; +// //} +// return rcode; +//} diff --git a/lib/usbhost/USB_Host_Shield_2.0/cdcprolific.h b/lib/usbhost/USB_Host_Shield_2.0/cdcprolific.h new file mode 100644 index 0000000000..4991466410 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/cdcprolific.h @@ -0,0 +1,159 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#if !defined(__CDCPROLIFIC_H__) +#define __CDCPROLIFIC_H__ + +#include "cdcacm.h" + +//#define PL2303_COMPAT // Uncomment it if you have compatibility problems + +#define PL_VID 0x067B +#define CHECK_PID(pid) ( pid != 0x2303 && pid != 0x0609 ) + +//#define PL_PID 0x0609 + +#define PROLIFIC_REV_H 0x0202 +#define PROLIFIC_REV_X 0x0300 +#define PROLIFIC_REV_HX_CHIP_D 0x0400 +#define PROLIFIC_REV_1 0x0001 + +#define kXOnChar '\x11' +#define kXOffChar '\x13' + +#define SPECIAL_SHIFT (5) +#define SPECIAL_MASK ((1<ctrlReq(bAddress, 0, VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, val_lo, val_hi, index, 1, 1, buf, NULL )); +} + +/* vendor write request */ +inline uint8_t PL2303::vendorWrite( uint8_t val_lo, uint8_t val_hi, uint8_t index ) +{ + return( pUsb->ctrlReq(bAddress, 0, VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, val_lo, val_hi, index, 0, 0, NULL, NULL )); +} +#endif + +#endif // __CDCPROLIFIC_H__ diff --git a/lib/usbhost/USB_Host_Shield_2.0/confdescparser.h b/lib/usbhost/USB_Host_Shield_2.0/confdescparser.h new file mode 100644 index 0000000000..a6806f2ea7 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/confdescparser.h @@ -0,0 +1,213 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#if !defined(_usb_h_) || defined(__CONFDESCPARSER_H__) +#error "Never include confdescparser.h directly; include Usb.h instead" +#else + +#define __CONFDESCPARSER_H__ + +class UsbConfigXtracter { +public: + //virtual void ConfigXtract(const USB_CONFIGURATION_DESCRIPTOR *conf) = 0; + //virtual void InterfaceXtract(uint8_t conf, const USB_INTERFACE_DESCRIPTOR *iface) = 0; + + virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep) { + }; +}; + +#define CP_MASK_COMPARE_CLASS 1 +#define CP_MASK_COMPARE_SUBCLASS 2 +#define CP_MASK_COMPARE_PROTOCOL 4 +#define CP_MASK_COMPARE_ALL 7 + +// Configuration Descriptor Parser Class Template + +template +class ConfigDescParser : public USBReadParser { + UsbConfigXtracter *theXtractor; + MultiValueBuffer theBuffer; + MultiByteValueParser valParser; + ByteSkipper theSkipper; + uint8_t varBuffer[16 /*sizeof(USB_CONFIGURATION_DESCRIPTOR)*/]; + + uint8_t stateParseDescr; // ParseDescriptor state + + uint8_t dscrLen; // Descriptor length + uint8_t dscrType; // Descriptor type + + bool isGoodInterface; // Apropriate interface flag + uint8_t confValue; // Configuration value + uint8_t protoValue; // Protocol value + uint8_t ifaceNumber; // Interface number + uint8_t ifaceAltSet; // Interface alternate settings + + bool UseOr; + bool ParseDescriptor(uint8_t **pp, uint16_t *pcntdn); + void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc); + +public: + + void SetOR(void) { + UseOr = true; + } + ConfigDescParser(UsbConfigXtracter *xtractor); + void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset); +}; + +template +ConfigDescParser::ConfigDescParser(UsbConfigXtracter *xtractor) : +theXtractor(xtractor), +stateParseDescr(0), +dscrLen(0), +dscrType(0), +UseOr(false) { + theBuffer.pValue = varBuffer; + valParser.Initialize(&theBuffer); + theSkipper.Initialize(&theBuffer); +}; + +template +void ConfigDescParser::Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset) { + uint16_t cntdn = (uint16_t)len; + uint8_t *p = (uint8_t*)pbuf; + + while(cntdn) + if(!ParseDescriptor(&p, &cntdn)) + return; +} + +/* Parser for the configuration descriptor. Takes values for class, subclass, protocol fields in interface descriptor and + compare masks for them. When the match is found, calls EndpointXtract passing buffer containing endpoint descriptor */ +template +bool ConfigDescParser::ParseDescriptor(uint8_t **pp, uint16_t *pcntdn) { + USB_CONFIGURATION_DESCRIPTOR* ucd = reinterpret_cast(varBuffer); + USB_INTERFACE_DESCRIPTOR* uid = reinterpret_cast(varBuffer); + switch(stateParseDescr) { + case 0: + theBuffer.valueSize = 2; + valParser.Initialize(&theBuffer); + stateParseDescr = 1; + case 1: + if(!valParser.Parse(pp, pcntdn)) + return false; + dscrLen = *((uint8_t*)theBuffer.pValue); + dscrType = *((uint8_t*)theBuffer.pValue + 1); + stateParseDescr = 2; + case 2: + // This is a sort of hack. Assuming that two bytes are all ready in the buffer + // the pointer is positioned two bytes ahead in order for the rest of descriptor + // to be read right after the size and the type fields. + // This should be used carefully. varBuffer should be used directly to handle data + // in the buffer. + theBuffer.pValue = varBuffer + 2; + stateParseDescr = 3; + case 3: + switch(dscrType) { + case USB_DESCRIPTOR_INTERFACE: + isGoodInterface = false; + case USB_DESCRIPTOR_CONFIGURATION: + theBuffer.valueSize = sizeof (USB_CONFIGURATION_DESCRIPTOR) - 2; + break; + case USB_DESCRIPTOR_ENDPOINT: + theBuffer.valueSize = sizeof (USB_ENDPOINT_DESCRIPTOR) - 2; + break; + case HID_DESCRIPTOR_HID: + theBuffer.valueSize = dscrLen - 2; + break; + } + valParser.Initialize(&theBuffer); + stateParseDescr = 4; + case 4: + switch(dscrType) { + case USB_DESCRIPTOR_CONFIGURATION: + if(!valParser.Parse(pp, pcntdn)) + return false; + confValue = ucd->bConfigurationValue; + break; + case USB_DESCRIPTOR_INTERFACE: + if(!valParser.Parse(pp, pcntdn)) + return false; + if((MASK & CP_MASK_COMPARE_CLASS) && uid->bInterfaceClass != CLASS_ID) + break; + if((MASK & CP_MASK_COMPARE_SUBCLASS) && uid->bInterfaceSubClass != SUBCLASS_ID) + break; + if(UseOr) { + if((!((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol))) + break; + } else { + if((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol != PROTOCOL_ID) + break; + } + isGoodInterface = true; + ifaceNumber = uid->bInterfaceNumber; + ifaceAltSet = uid->bAlternateSetting; + protoValue = uid->bInterfaceProtocol; + break; + case USB_DESCRIPTOR_ENDPOINT: + if(!valParser.Parse(pp, pcntdn)) + return false; + if(isGoodInterface) + if(theXtractor) + theXtractor->EndpointXtract(confValue, ifaceNumber, ifaceAltSet, protoValue, (USB_ENDPOINT_DESCRIPTOR*)varBuffer); + break; + //case HID_DESCRIPTOR_HID: + // if (!valParser.Parse(pp, pcntdn)) + // return false; + // PrintHidDescriptor((const USB_HID_DESCRIPTOR*)varBuffer); + // break; + default: + if(!theSkipper.Skip(pp, pcntdn, dscrLen - 2)) + return false; + } + theBuffer.pValue = varBuffer; + stateParseDescr = 0; + } + return true; +} + +template +void ConfigDescParser::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc) { + Notify(PSTR("\r\n\r\nHID Descriptor:\r\n"), 0x80); + Notify(PSTR("bDescLength:\t\t"), 0x80); + PrintHex (pDesc->bLength, 0x80); + + Notify(PSTR("\r\nbDescriptorType:\t"), 0x80); + PrintHex (pDesc->bDescriptorType, 0x80); + + Notify(PSTR("\r\nbcdHID:\t\t\t"), 0x80); + PrintHex (pDesc->bcdHID, 0x80); + + Notify(PSTR("\r\nbCountryCode:\t\t"), 0x80); + PrintHex (pDesc->bCountryCode, 0x80); + + Notify(PSTR("\r\nbNumDescriptors:\t"), 0x80); + PrintHex (pDesc->bNumDescriptors, 0x80); + + for(uint8_t i = 0; i < pDesc->bNumDescriptors; i++) { + HID_CLASS_DESCRIPTOR_LEN_AND_TYPE *pLT = (HID_CLASS_DESCRIPTOR_LEN_AND_TYPE*)&(pDesc->bDescrType); + + Notify(PSTR("\r\nbDescrType:\t\t"), 0x80); + PrintHex (pLT[i].bDescrType, 0x80); + + Notify(PSTR("\r\nwDescriptorLength:\t"), 0x80); + PrintHex (pLT[i].wDescriptorLength, 0x80); + } + Notify(PSTR("\r\n"), 0x80); +} + + +#endif // __CONFDESCPARSER_H__ diff --git a/lib/usbhost/USB_Host_Shield_2.0/controllerEnums.h b/lib/usbhost/USB_Host_Shield_2.0/controllerEnums.h new file mode 100644 index 0000000000..0169c763c1 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/controllerEnums.h @@ -0,0 +1,204 @@ +/* Copyright (C) 2013 Kristian Lauszus, TKJ Electronics. All rights reserved. + + This software may be distributed and modified under the terms of the GNU + General Public License version 2 (GPL2) as published by the Free Software + Foundation and appearing in the file GPL2.TXT included in the packaging of + this file. Please note that GPL2 Section 2[b] requires that all works based + on this software must also be made publicly available under the terms of + the GPL2 ("Copyleft"). + + Contact information + ------------------- + + Kristian Lauszus, TKJ Electronics + Web : http://www.tkjelectronics.com + e-mail : kristianl@tkjelectronics.com + */ + +#ifndef _controllerenums_h +#define _controllerenums_h + +/** + * This header file is used to store different enums for the controllers, + * This is necessary so all the different libraries can be used at once. + */ + +/** Enum used to turn on the LEDs on the different controllers. */ +enum LEDEnum { + OFF = 0, + LED1 = 1, + LED2 = 2, + LED3 = 3, + LED4 = 4, + + LED5 = 5, + LED6 = 6, + LED7 = 7, + LED8 = 8, + LED9 = 9, + LED10 = 10, + /** Used to blink all LEDs on the Xbox controller */ + ALL = 5, +}; + +/** Used to set the colors of the Move and PS4 controller. */ +enum ColorsEnum { + /** r = 255, g = 0, b = 0 */ + Red = 0xFF0000, + /** r = 0, g = 255, b = 0 */ + Green = 0xFF00, + /** r = 0, g = 0, b = 255 */ + Blue = 0xFF, + + /** r = 255, g = 235, b = 4 */ + Yellow = 0xFFEB04, + /** r = 0, g = 255, b = 255 */ + Lightblue = 0xFFFF, + /** r = 255, g = 0, b = 255 */ + Purble = 0xFF00FF, + + /** r = 255, g = 255, b = 255 */ + White = 0xFFFFFF, + /** r = 0, g = 0, b = 0 */ + Off = 0x00, +}; + +enum RumbleEnum { + RumbleHigh = 0x10, + RumbleLow = 0x20, +}; + +/** This enum is used to read all the different buttons on the different controllers */ +enum ButtonEnum { + /**@{*/ + /** These buttons are available on all the the controllers */ + UP = 0, + RIGHT = 1, + DOWN = 2, + LEFT = 3, + /**@}*/ + + /**@{*/ + /** Wii buttons */ + PLUS = 5, + TWO = 6, + ONE = 7, + MINUS = 8, + HOME = 9, + Z = 10, + C = 11, + B = 12, + A = 13, + /**@}*/ + + /**@{*/ + /** These are only available on the Wii U Pro Controller */ + L = 16, + R = 17, + ZL = 18, + ZR = 19, + /**@}*/ + + /**@{*/ + /** PS3 controllers buttons */ + SELECT = 4, + START = 5, + L3 = 6, + R3 = 7, + + L2 = 8, + R2 = 9, + L1 = 10, + R1 = 11, + TRIANGLE = 12, + CIRCLE = 13, + CROSS = 14, + SQUARE = 15, + + PS = 16, + + MOVE = 17, // Covers 12 bits - we only need to read the top 8 + T = 18, // Covers 12 bits - we only need to read the top 8 + /**@}*/ + + /** PS4 controllers buttons - SHARE and OPTIONS are present instead of SELECT and START */ + SHARE = 4, + OPTIONS = 5, + TOUCHPAD = 17, + /**@}*/ + + /**@{*/ + /** Xbox buttons */ + BACK = 4, + X = 14, + Y = 15, + XBOX = 16, + SYNC = 17, + BLACK = 8, // Available on the original Xbox controller + WHITE = 9, // Available on the original Xbox controller + /**@}*/ + + /** PS Buzz controllers */ + RED = 0, + YELLOW = 1, + GREEN = 2, + ORANGE = 3, + BLUE = 4, + /**@}*/ +}; + +/** Joysticks on the PS3 and Xbox controllers. */ +enum AnalogHatEnum { + /** Left joystick x-axis */ + LeftHatX = 0, + /** Left joystick y-axis */ + LeftHatY = 1, + /** Right joystick x-axis */ + RightHatX = 2, + /** Right joystick y-axis */ + RightHatY = 3, +}; + +/** + * Sensors inside the Sixaxis Dualshock 3, Move controller and PS4 controller. + * Note: that the location is shifted 9 when it's connected via USB on the PS3 controller. + */ +enum SensorEnum { + /** Accelerometer values */ + aX = 50, aY = 52, aZ = 54, + /** Gyro z-axis */ + gZ = 56, + gX, gY, // These are not available on the PS3 controller + + /** Accelerometer x-axis */ + aXmove = 28, + /** Accelerometer z-axis */ + aZmove = 30, + /** Accelerometer y-axis */ + aYmove = 32, + + /** Gyro x-axis */ + gXmove = 40, + /** Gyro z-axis */ + gZmove = 42, + /** Gyro y-axis */ + gYmove = 44, + + /** Temperature sensor */ + tempMove = 46, + + /** Magnetometer x-axis */ + mXmove = 47, + /** Magnetometer z-axis */ + mZmove = 49, + /** Magnetometer y-axis */ + mYmove = 50, +}; + +/** Used to get the angle calculated using the PS3 controller and PS4 controller. */ +enum AngleEnum { + Pitch = 0x01, + Roll = 0x02, +}; + +#endif diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/BTHID.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/BTHID.ino new file mode 100644 index 0000000000..919a56468b --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/BTHID.ino @@ -0,0 +1,55 @@ +/* + Example sketch for the HID Bluetooth library - developed by Kristian Lauszus + For more information visit my blog: http://blog.tkjelectronics.dk/ or + send me an e-mail: kristianl@tkjelectronics.com + */ + +#include +#include +#include "KeyboardParser.h" +#include "MouseParser.h" + +// Satisfy the IDE, which needs to see the include statment in the ino too. +#ifdef dobogusinclude +#include +#include +#endif + +USB Usb; +//USBHub Hub1(&Usb); // Some dongles have a hub inside +BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so + +/* You can create the instance of the class in two ways */ +// This will start an inquiry and then pair with your device - you only have to do this once +// If you are using a Bluetooth keyboard, then you should type in the password on the keypad and then press enter +BTHID bthid(&Btd, PAIR, "0000"); + +// After that you can simply create the instance like so and then press any button on the device +//BTHID hid(&Btd); + +KbdRptParser keyboardPrs; +MouseRptParser mousePrs; + +void setup() { + Serial.begin(115200); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + if (Usb.Init() == -1) { + Serial.print(F("\r\nOSC did not start")); + while (1); // Halt + } + + bthid.SetReportParser(KEYBOARD_PARSER_ID, (HIDReportParser*)&keyboardPrs); + bthid.SetReportParser(MOUSE_PARSER_ID, (HIDReportParser*)&mousePrs); + + // If "Boot Protocol Mode" does not work, then try "Report Protocol Mode" + // If that does not work either, then uncomment PRINTREPORT in BTHID.cpp to see the raw report + bthid.setProtocolMode(HID_BOOT_PROTOCOL); // Boot Protocol Mode + //bthid.setProtocolMode(HID_RPT_PROTOCOL); // Report Protocol Mode + + Serial.print(F("\r\nHID Bluetooth Library Started")); +} +void loop() { + Usb.Task(); +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/KeyboardParser.h b/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/KeyboardParser.h new file mode 100644 index 0000000000..c5394331da --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/KeyboardParser.h @@ -0,0 +1,105 @@ +#ifndef __kbdrptparser_h_ +#define __kbdrptparser_h_ + +class KbdRptParser : public KeyboardReportParser { + protected: + virtual uint8_t HandleLockingKeys(HID *hid, uint8_t key); + virtual void OnControlKeysChanged(uint8_t before, uint8_t after); + virtual void OnKeyDown(uint8_t mod, uint8_t key); + virtual void OnKeyUp(uint8_t mod, uint8_t key); + virtual void OnKeyPressed(uint8_t key); + + private: + void PrintKey(uint8_t mod, uint8_t key); +}; + +uint8_t KbdRptParser::HandleLockingKeys(HID *hid, uint8_t key) { + uint8_t old_keys = kbdLockingKeys.bLeds; + + switch (key) { + case UHS_HID_BOOT_KEY_NUM_LOCK: + Serial.println(F("Num lock")); + kbdLockingKeys.kbdLeds.bmNumLock = ~kbdLockingKeys.kbdLeds.bmNumLock; + break; + case UHS_HID_BOOT_KEY_CAPS_LOCK: + Serial.println(F("Caps lock")); + kbdLockingKeys.kbdLeds.bmCapsLock = ~kbdLockingKeys.kbdLeds.bmCapsLock; + break; + case UHS_HID_BOOT_KEY_SCROLL_LOCK: + Serial.println(F("Scroll lock")); + kbdLockingKeys.kbdLeds.bmScrollLock = ~kbdLockingKeys.kbdLeds.bmScrollLock; + break; + } + + if (old_keys != kbdLockingKeys.bLeds && hid) { + BTHID *pBTHID = reinterpret_cast (hid); // A cast the other way around is done in BTHID.cpp + pBTHID->setLeds(kbdLockingKeys.bLeds); // Update the LEDs on the keyboard + } + + return 0; +}; + +void KbdRptParser::PrintKey(uint8_t m, uint8_t key) { + MODIFIERKEYS mod; + *((uint8_t*)&mod) = m; + Serial.print((mod.bmLeftCtrl == 1) ? F("C") : F(" ")); + Serial.print((mod.bmLeftShift == 1) ? F("S") : F(" ")); + Serial.print((mod.bmLeftAlt == 1) ? F("A") : F(" ")); + Serial.print((mod.bmLeftGUI == 1) ? F("G") : F(" ")); + + Serial.print(F(" >")); + PrintHex(key, 0x80); + Serial.print(F("< ")); + + Serial.print((mod.bmRightCtrl == 1) ? F("C") : F(" ")); + Serial.print((mod.bmRightShift == 1) ? F("S") : F(" ")); + Serial.print((mod.bmRightAlt == 1) ? F("A") : F(" ")); + Serial.println((mod.bmRightGUI == 1) ? F("G") : F(" ")); +}; + +void KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key) { + Serial.print(F("DN ")); + PrintKey(mod, key); + uint8_t c = OemToAscii(mod, key); + + if (c) + OnKeyPressed(c); +}; + +void KbdRptParser::OnControlKeysChanged(uint8_t before, uint8_t after) { + MODIFIERKEYS beforeMod; + *((uint8_t*)&beforeMod) = before; + + MODIFIERKEYS afterMod; + *((uint8_t*)&afterMod) = after; + + if (beforeMod.bmLeftCtrl != afterMod.bmLeftCtrl) + Serial.println(F("LeftCtrl changed")); + if (beforeMod.bmLeftShift != afterMod.bmLeftShift) + Serial.println(F("LeftShift changed")); + if (beforeMod.bmLeftAlt != afterMod.bmLeftAlt) + Serial.println(F("LeftAlt changed")); + if (beforeMod.bmLeftGUI != afterMod.bmLeftGUI) + Serial.println(F("LeftGUI changed")); + + if (beforeMod.bmRightCtrl != afterMod.bmRightCtrl) + Serial.println(F("RightCtrl changed")); + if (beforeMod.bmRightShift != afterMod.bmRightShift) + Serial.println(F("RightShift changed")); + if (beforeMod.bmRightAlt != afterMod.bmRightAlt) + Serial.println(F("RightAlt changed")); + if (beforeMod.bmRightGUI != afterMod.bmRightGUI) + Serial.println(F("RightGUI changed")); +}; + +void KbdRptParser::OnKeyUp(uint8_t mod, uint8_t key) { + Serial.print(F("UP ")); + PrintKey(mod, key); +}; + +void KbdRptParser::OnKeyPressed(uint8_t key) { + Serial.print(F("ASCII: ")); + Serial.println((char)key); +}; + +#endif diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/MouseParser.h b/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/MouseParser.h new file mode 100644 index 0000000000..a9245ded99 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/MouseParser.h @@ -0,0 +1,46 @@ +#ifndef __mouserptparser_h__ +#define __mouserptparser_h__ + +class MouseRptParser : public MouseReportParser { + protected: + virtual void OnMouseMove(MOUSEINFO *mi); + virtual void OnLeftButtonUp(MOUSEINFO *mi); + virtual void OnLeftButtonDown(MOUSEINFO *mi); + virtual void OnRightButtonUp(MOUSEINFO *mi); + virtual void OnRightButtonDown(MOUSEINFO *mi); + virtual void OnMiddleButtonUp(MOUSEINFO *mi); + virtual void OnMiddleButtonDown(MOUSEINFO *mi); +}; + +void MouseRptParser::OnMouseMove(MOUSEINFO *mi) { + Serial.print(F("dx=")); + Serial.print(mi->dX, DEC); + Serial.print(F(" dy=")); + Serial.println(mi->dY, DEC); +}; + +void MouseRptParser::OnLeftButtonUp(MOUSEINFO *mi) { + Serial.println(F("L Butt Up")); +}; + +void MouseRptParser::OnLeftButtonDown(MOUSEINFO *mi) { + Serial.println(F("L Butt Dn")); +}; + +void MouseRptParser::OnRightButtonUp(MOUSEINFO *mi) { + Serial.println(F("R Butt Up")); +}; + +void MouseRptParser::OnRightButtonDown(MOUSEINFO *mi) { + Serial.println(F("R Butt Dn")); +}; + +void MouseRptParser::OnMiddleButtonUp(MOUSEINFO *mi) { + Serial.println(F("M Butt Up")); +}; + +void MouseRptParser::OnMiddleButtonDown(MOUSEINFO *mi) { + Serial.println(F("M Butt Dn")); +}; + +#endif diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/PS3BT/PS3BT.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/PS3BT/PS3BT.ino new file mode 100644 index 0000000000..b896734405 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/PS3BT/PS3BT.ino @@ -0,0 +1,188 @@ +/* + Example sketch for the PS3 Bluetooth library - developed by Kristian Lauszus + For more information visit my blog: http://blog.tkjelectronics.dk/ or + send me an e-mail: kristianl@tkjelectronics.com + */ + +#include +#include + +// Satisfy the IDE, which needs to see the include statment in the ino too. +#ifdef dobogusinclude +#include +#include +#endif + +USB Usb; +//USBHub Hub1(&Usb); // Some dongles have a hub inside + +BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so +/* You can create the instance of the class in two ways */ +PS3BT PS3(&Btd); // This will just create the instance +//PS3BT PS3(&Btd, 0x00, 0x15, 0x83, 0x3D, 0x0A, 0x57); // This will also store the bluetooth address - this can be obtained from the dongle when running the sketch + +bool printTemperature; +bool printAngle; + +void setup() { + Serial.begin(115200); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + if (Usb.Init() == -1) { + Serial.print(F("\r\nOSC did not start")); + while (1); //halt + } + Serial.print(F("\r\nPS3 Bluetooth Library Started")); +} +void loop() { + Usb.Task(); + + if (PS3.PS3Connected || PS3.PS3NavigationConnected) { + if (PS3.getAnalogHat(LeftHatX) > 137 || PS3.getAnalogHat(LeftHatX) < 117 || PS3.getAnalogHat(LeftHatY) > 137 || PS3.getAnalogHat(LeftHatY) < 117 || PS3.getAnalogHat(RightHatX) > 137 || PS3.getAnalogHat(RightHatX) < 117 || PS3.getAnalogHat(RightHatY) > 137 || PS3.getAnalogHat(RightHatY) < 117) { + Serial.print(F("\r\nLeftHatX: ")); + Serial.print(PS3.getAnalogHat(LeftHatX)); + Serial.print(F("\tLeftHatY: ")); + Serial.print(PS3.getAnalogHat(LeftHatY)); + if (PS3.PS3Connected) { // The Navigation controller only have one joystick + Serial.print(F("\tRightHatX: ")); + Serial.print(PS3.getAnalogHat(RightHatX)); + Serial.print(F("\tRightHatY: ")); + Serial.print(PS3.getAnalogHat(RightHatY)); + } + } + + // Analog button values can be read from almost all buttons + if (PS3.getAnalogButton(L2) || PS3.getAnalogButton(R2)) { + Serial.print(F("\r\nL2: ")); + Serial.print(PS3.getAnalogButton(L2)); + if (PS3.PS3Connected) { + Serial.print(F("\tR2: ")); + Serial.print(PS3.getAnalogButton(R2)); + } + } + if (PS3.getButtonClick(PS)) { + Serial.print(F("\r\nPS")); + PS3.disconnect(); + } + else { + if (PS3.getButtonClick(TRIANGLE)) + Serial.print(F("\r\nTraingle")); + if (PS3.getButtonClick(CIRCLE)) + Serial.print(F("\r\nCircle")); + if (PS3.getButtonClick(CROSS)) + Serial.print(F("\r\nCross")); + if (PS3.getButtonClick(SQUARE)) + Serial.print(F("\r\nSquare")); + + if (PS3.getButtonClick(UP)) { + Serial.print(F("\r\nUp")); + if (PS3.PS3Connected) { + PS3.setLedOff(); + PS3.setLedOn(LED4); + } + } + if (PS3.getButtonClick(RIGHT)) { + Serial.print(F("\r\nRight")); + if (PS3.PS3Connected) { + PS3.setLedOff(); + PS3.setLedOn(LED1); + } + } + if (PS3.getButtonClick(DOWN)) { + Serial.print(F("\r\nDown")); + if (PS3.PS3Connected) { + PS3.setLedOff(); + PS3.setLedOn(LED2); + } + } + if (PS3.getButtonClick(LEFT)) { + Serial.print(F("\r\nLeft")); + if (PS3.PS3Connected) { + PS3.setLedOff(); + PS3.setLedOn(LED3); + } + } + + if (PS3.getButtonClick(L1)) + Serial.print(F("\r\nL1")); + if (PS3.getButtonClick(L3)) + Serial.print(F("\r\nL3")); + if (PS3.getButtonClick(R1)) + Serial.print(F("\r\nR1")); + if (PS3.getButtonClick(R3)) + Serial.print(F("\r\nR3")); + + if (PS3.getButtonClick(SELECT)) { + Serial.print(F("\r\nSelect - ")); + PS3.printStatusString(); + } + if (PS3.getButtonClick(START)) { + Serial.print(F("\r\nStart")); + printAngle = !printAngle; + } + } +#if 0 // Set this to 1 in order to see the angle of the controller + if (printAngle) { + Serial.print(F("\r\nPitch: ")); + Serial.print(PS3.getAngle(Pitch)); + Serial.print(F("\tRoll: ")); + Serial.print(PS3.getAngle(Roll)); + } +#endif + } +#if 0 // Set this to 1 in order to enable support for the Playstation Move controller + else if (PS3.PS3MoveConnected) { + if (PS3.getAnalogButton(T)) { + Serial.print(F("\r\nT: ")); + Serial.print(PS3.getAnalogButton(T)); + } + if (PS3.getButtonClick(PS)) { + Serial.print(F("\r\nPS")); + PS3.disconnect(); + } + else { + if (PS3.getButtonClick(SELECT)) { + Serial.print(F("\r\nSelect")); + printTemperature = !printTemperature; + } + if (PS3.getButtonClick(START)) { + Serial.print(F("\r\nStart")); + printAngle = !printAngle; + } + if (PS3.getButtonClick(TRIANGLE)) { + Serial.print(F("\r\nTriangle")); + PS3.moveSetBulb(Red); + } + if (PS3.getButtonClick(CIRCLE)) { + Serial.print(F("\r\nCircle")); + PS3.moveSetBulb(Green); + } + if (PS3.getButtonClick(SQUARE)) { + Serial.print(F("\r\nSquare")); + PS3.moveSetBulb(Blue); + } + if (PS3.getButtonClick(CROSS)) { + Serial.print(F("\r\nCross")); + PS3.moveSetBulb(Yellow); + } + if (PS3.getButtonClick(MOVE)) { + PS3.moveSetBulb(Off); + Serial.print(F("\r\nMove")); + Serial.print(F(" - ")); + PS3.printStatusString(); + } + } + if (printAngle) { + Serial.print(F("\r\nPitch: ")); + Serial.print(PS3.getAngle(Pitch)); + Serial.print(F("\tRoll: ")); + Serial.print(PS3.getAngle(Roll)); + } + else if (printTemperature) { + Serial.print(F("\r\nTemperature: ")); + Serial.print(PS3.getTemperature()); + } + } +#endif +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/PS3Multi/PS3Multi.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/PS3Multi/PS3Multi.ino new file mode 100644 index 0000000000..5ebfd7819c --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/PS3Multi/PS3Multi.ino @@ -0,0 +1,149 @@ +/* + Example sketch for the PS3 Bluetooth library - developed by Kristian Lauszus + This example show how one can use multiple controllers with the library + For more information visit my blog: http://blog.tkjelectronics.dk/ or + send me an e-mail: kristianl@tkjelectronics.com + */ + +#include +#include + +// Satisfy the IDE, which needs to see the include statment in the ino too. +#ifdef dobogusinclude +#include +#include +#endif + +USB Usb; +//USBHub Hub1(&Usb); // Some dongles have a hub inside + +BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so +PS3BT *PS3[2]; // We will use this pointer to store the two instance, you can easily make it larger if you like, but it will use a lot of RAM! +const uint8_t length = sizeof(PS3) / sizeof(PS3[0]); // Get the lenght of the array +bool printAngle[length]; +bool oldControllerState[length]; + +void setup() { + for (uint8_t i = 0; i < length; i++) { + PS3[i] = new PS3BT(&Btd); // Create the instances + PS3[i]->attachOnInit(onInit); // onInit() is called upon a new connection - you can call the function whatever you like + } + + Serial.begin(115200); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + if (Usb.Init() == -1) { + Serial.print(F("\r\nOSC did not start")); + while (1); //halt + } + Serial.print(F("\r\nPS3 Bluetooth Library Started")); +} +void loop() { + Usb.Task(); + + for (uint8_t i = 0; i < length; i++) { + if (PS3[i]->PS3Connected || PS3[i]->PS3NavigationConnected) { + if (PS3[i]->getAnalogHat(LeftHatX) > 137 || PS3[i]->getAnalogHat(LeftHatX) < 117 || PS3[i]->getAnalogHat(LeftHatY) > 137 || PS3[i]->getAnalogHat(LeftHatY) < 117 || PS3[i]->getAnalogHat(RightHatX) > 137 || PS3[i]->getAnalogHat(RightHatX) < 117 || PS3[i]->getAnalogHat(RightHatY) > 137 || PS3[i]->getAnalogHat(RightHatY) < 117) { + Serial.print(F("\r\nLeftHatX: ")); + Serial.print(PS3[i]->getAnalogHat(LeftHatX)); + Serial.print(F("\tLeftHatY: ")); + Serial.print(PS3[i]->getAnalogHat(LeftHatY)); + if (PS3[i]->PS3Connected) { // The Navigation controller only have one joystick + Serial.print(F("\tRightHatX: ")); + Serial.print(PS3[i]->getAnalogHat(RightHatX)); + Serial.print(F("\tRightHatY: ")); + Serial.print(PS3[i]->getAnalogHat(RightHatY)); + } + } + //Analog button values can be read from almost all buttons + if (PS3[i]->getAnalogButton(L2) || PS3[i]->getAnalogButton(R2)) { + Serial.print(F("\r\nL2: ")); + Serial.print(PS3[i]->getAnalogButton(L2)); + if (PS3[i]->PS3Connected) { + Serial.print(F("\tR2: ")); + Serial.print(PS3[i]->getAnalogButton(R2)); + } + } + if (PS3[i]->getButtonClick(PS)) { + Serial.print(F("\r\nPS")); + PS3[i]->disconnect(); + oldControllerState[i] = false; // Reset value + } + else { + if (PS3[i]->getButtonClick(TRIANGLE)) + Serial.print(F("\r\nTraingle")); + if (PS3[i]->getButtonClick(CIRCLE)) + Serial.print(F("\r\nCircle")); + if (PS3[i]->getButtonClick(CROSS)) + Serial.print(F("\r\nCross")); + if (PS3[i]->getButtonClick(SQUARE)) + Serial.print(F("\r\nSquare")); + + if (PS3[i]->getButtonClick(UP)) { + Serial.print(F("\r\nUp")); + if (PS3[i]->PS3Connected) { + PS3[i]->setLedOff(); + PS3[i]->setLedOn(LED4); + } + } + if (PS3[i]->getButtonClick(RIGHT)) { + Serial.print(F("\r\nRight")); + if (PS3[i]->PS3Connected) { + PS3[i]->setLedOff(); + PS3[i]->setLedOn(LED1); + } + } + if (PS3[i]->getButtonClick(DOWN)) { + Serial.print(F("\r\nDown")); + if (PS3[i]->PS3Connected) { + PS3[i]->setLedOff(); + PS3[i]->setLedOn(LED2); + } + } + if (PS3[i]->getButtonClick(LEFT)) { + Serial.print(F("\r\nLeft")); + if (PS3[i]->PS3Connected) { + PS3[i]->setLedOff(); + PS3[i]->setLedOn(LED3); + } + } + + if (PS3[i]->getButtonClick(L1)) + Serial.print(F("\r\nL1")); + if (PS3[i]->getButtonClick(L3)) + Serial.print(F("\r\nL3")); + if (PS3[i]->getButtonClick(R1)) + Serial.print(F("\r\nR1")); + if (PS3[i]->getButtonClick(R3)) + Serial.print(F("\r\nR3")); + + if (PS3[i]->getButtonClick(SELECT)) { + Serial.print(F("\r\nSelect - ")); + PS3[i]->printStatusString(); + } + if (PS3[i]->getButtonClick(START)) { + Serial.print(F("\r\nStart")); + printAngle[i] = !printAngle[i]; + } + } + if (printAngle[i]) { + Serial.print(F("\r\nPitch: ")); + Serial.print(PS3[i]->getAngle(Pitch)); + Serial.print(F("\tRoll: ")); + Serial.print(PS3[i]->getAngle(Roll)); + } + } + /* I have removed the PS3 Move code as an Uno will run out of RAM if it's included */ + //else if(PS3[i]->PS3MoveConnected) { + } +} + +void onInit() { + for (uint8_t i = 0; i < length; i++) { + if ((PS3[i]->PS3Connected || PS3[i]->PS3NavigationConnected) && !oldControllerState[i]) { + oldControllerState[i] = true; // Used to check which is the new controller + PS3[i]->setLedOn((LEDEnum)(i + 1)); // Cast directly to LEDEnum - see: "controllerEnums.h" + } + } +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/PS3SPP/PS3SPP.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/PS3SPP/PS3SPP.ino new file mode 100644 index 0000000000..8f234cbd8d --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/PS3SPP/PS3SPP.ino @@ -0,0 +1,162 @@ +/* + Example sketch for the Bluetooth library - developed by Kristian Lauszus + For more information visit my blog: http://blog.tkjelectronics.dk/ or + send me an e-mail: kristianl@tkjelectronics.com + + This example show how one can combine all the difference Bluetooth services in one single code. + Note: + You will need a Arduino Mega 1280/2560 to run this sketch, + as a normal Arduino (Uno, Duemilanove etc.) doesn't have enough SRAM and FLASH + */ + +#include +#include +#include + +// Satisfy the IDE, which needs to see the include statment in the ino too. +#ifdef dobogusinclude +#include +#include +#endif + +USB Usb; +//USBHub Hub1(&Usb); // Some dongles have a hub inside + +BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so + +/* You can create the instances of the bluetooth services in two ways */ +SPP SerialBT(&Btd); // This will set the name to the defaults: "Arduino" and the pin to "0000" +//SPP SerialBTBT(&Btd,"Lauszus's Arduino","0000"); // You can also set the name and pin like so +PS3BT PS3(&Btd); // This will just create the instance +//PS3BT PS3(&Btd, 0x00, 0x15, 0x83, 0x3D, 0x0A, 0x57); // This will also store the bluetooth address - this can be obtained from the dongle when running the sketch + +bool firstMessage = true; +String output = ""; // We will store the data in this string + +void setup() { + Serial.begin(115200); // This wil lprint the debugging from the libraries +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + if (Usb.Init() == -1) { + Serial.print(F("\r\nOSC did not start")); + while (1); //halt + } + Serial.print(F("\r\nBluetooth Library Started")); + output.reserve(200); // Reserve 200 bytes for the output string +} +void loop() { + Usb.Task(); // The SPP data is actually not send until this is called, one could call SerialBT.send() directly as well + + if (SerialBT.connected) { + if (firstMessage) { + firstMessage = false; + SerialBT.println(F("Hello from Arduino")); // Send welcome message + } + if (Serial.available()) + SerialBT.write(Serial.read()); + if (SerialBT.available()) + Serial.write(SerialBT.read()); + } + else + firstMessage = true; + + if (PS3.PS3Connected || PS3.PS3NavigationConnected) { + output = ""; // Reset output string + if (PS3.getAnalogHat(LeftHatX) > 137 || PS3.getAnalogHat(LeftHatX) < 117 || PS3.getAnalogHat(LeftHatY) > 137 || PS3.getAnalogHat(LeftHatY) < 117 || PS3.getAnalogHat(RightHatX) > 137 || PS3.getAnalogHat(RightHatX) < 117 || PS3.getAnalogHat(RightHatY) > 137 || PS3.getAnalogHat(RightHatY) < 117) { + output += "LeftHatX: "; + output += PS3.getAnalogHat(LeftHatX); + output += "\tLeftHatY: "; + output += PS3.getAnalogHat(LeftHatY); + if (PS3.PS3Connected) { // The Navigation controller only have one joystick + output += "\tRightHatX: "; + output += PS3.getAnalogHat(RightHatX); + output += "\tRightHatY: "; + output += PS3.getAnalogHat(RightHatY); + } + } + //Analog button values can be read from almost all buttons + if (PS3.getAnalogButton(L2) || PS3.getAnalogButton(R2)) { + if (output != "") + output += "\r\n"; + output += "L2: "; + output += PS3.getAnalogButton(L2); + if (PS3.PS3Connected) { + output += "\tR2: "; + output += PS3.getAnalogButton(R2); + } + } + if (output != "") { + Serial.println(output); + if (SerialBT.connected) + SerialBT.println(output); + output = ""; // Reset output string + } + if (PS3.getButtonClick(PS)) { + output += " - PS"; + PS3.disconnect(); + } + else { + if (PS3.getButtonClick(TRIANGLE)) + output += " - Traingle"; + if (PS3.getButtonClick(CIRCLE)) + output += " - Circle"; + if (PS3.getButtonClick(CROSS)) + output += " - Cross"; + if (PS3.getButtonClick(SQUARE)) + output += " - Square"; + + if (PS3.getButtonClick(UP)) { + output += " - Up"; + if (PS3.PS3Connected) { + PS3.setLedOff(); + PS3.setLedOn(LED4); + } + } + if (PS3.getButtonClick(RIGHT)) { + output += " - Right"; + if (PS3.PS3Connected) { + PS3.setLedOff(); + PS3.setLedOn(LED1); + } + } + if (PS3.getButtonClick(DOWN)) { + output += " - Down"; + if (PS3.PS3Connected) { + PS3.setLedOff(); + PS3.setLedOn(LED2); + } + } + if (PS3.getButtonClick(LEFT)) { + output += " - Left"; + if (PS3.PS3Connected) { + PS3.setLedOff(); + PS3.setLedOn(LED3); + } + } + + if (PS3.getButtonClick(L1)) + output += " - L1"; + if (PS3.getButtonClick(L3)) + output += " - L3"; + if (PS3.getButtonClick(R1)) + output += " - R1"; + if (PS3.getButtonClick(R3)) + output += " - R3"; + + if (PS3.getButtonClick(SELECT)) { + output += " - Select"; + } + if (PS3.getButtonClick(START)) + output += " - Start"; + + if (output != "") { + String string = "PS3 Controller" + output; + Serial.println(string); + if (SerialBT.connected) + SerialBT.println(string); + } + } + delay(10); + } +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/PS4BT/PS4BT.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/PS4BT/PS4BT.ino new file mode 100644 index 0000000000..c3ba696bd1 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/PS4BT/PS4BT.ino @@ -0,0 +1,146 @@ +/* + Example sketch for the PS4 Bluetooth library - developed by Kristian Lauszus + For more information visit my blog: http://blog.tkjelectronics.dk/ or + send me an e-mail: kristianl@tkjelectronics.com + */ + +#include +#include + +// Satisfy the IDE, which needs to see the include statment in the ino too. +#ifdef dobogusinclude +#include +#include +#endif + +USB Usb; +//USBHub Hub1(&Usb); // Some dongles have a hub inside +BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so + +/* You can create the instance of the PS4BT class in two ways */ +// This will start an inquiry and then pair with the PS4 controller - you only have to do this once +// You will need to hold down the PS and Share button at the same time, the PS4 controller will then start to blink rapidly indicating that it is in paring mode +PS4BT PS4(&Btd, PAIR); + +// After that you can simply create the instance like so and then press the PS button on the device +//PS4BT PS4(&Btd); + +bool printAngle, printTouch; +uint8_t oldL2Value, oldR2Value; + +void setup() { + Serial.begin(115200); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + if (Usb.Init() == -1) { + Serial.print(F("\r\nOSC did not start")); + while (1); // Halt + } + Serial.print(F("\r\nPS4 Bluetooth Library Started")); +} +void loop() { + Usb.Task(); + + if (PS4.connected()) { + if (PS4.getAnalogHat(LeftHatX) > 137 || PS4.getAnalogHat(LeftHatX) < 117 || PS4.getAnalogHat(LeftHatY) > 137 || PS4.getAnalogHat(LeftHatY) < 117 || PS4.getAnalogHat(RightHatX) > 137 || PS4.getAnalogHat(RightHatX) < 117 || PS4.getAnalogHat(RightHatY) > 137 || PS4.getAnalogHat(RightHatY) < 117) { + Serial.print(F("\r\nLeftHatX: ")); + Serial.print(PS4.getAnalogHat(LeftHatX)); + Serial.print(F("\tLeftHatY: ")); + Serial.print(PS4.getAnalogHat(LeftHatY)); + Serial.print(F("\tRightHatX: ")); + Serial.print(PS4.getAnalogHat(RightHatX)); + Serial.print(F("\tRightHatY: ")); + Serial.print(PS4.getAnalogHat(RightHatY)); + } + + if (PS4.getAnalogButton(L2) || PS4.getAnalogButton(R2)) { // These are the only analog buttons on the PS4 controller + Serial.print(F("\r\nL2: ")); + Serial.print(PS4.getAnalogButton(L2)); + Serial.print(F("\tR2: ")); + Serial.print(PS4.getAnalogButton(R2)); + } + if (PS4.getAnalogButton(L2) != oldL2Value || PS4.getAnalogButton(R2) != oldR2Value) // Only write value if it's different + PS4.setRumbleOn(PS4.getAnalogButton(L2), PS4.getAnalogButton(R2)); + oldL2Value = PS4.getAnalogButton(L2); + oldR2Value = PS4.getAnalogButton(R2); + + if (PS4.getButtonClick(PS)) { + Serial.print(F("\r\nPS")); + PS4.disconnect(); + } + else { + if (PS4.getButtonClick(TRIANGLE)) { + Serial.print(F("\r\nTraingle")); + PS4.setRumbleOn(RumbleLow); + } + if (PS4.getButtonClick(CIRCLE)) { + Serial.print(F("\r\nCircle")); + PS4.setRumbleOn(RumbleHigh); + } + if (PS4.getButtonClick(CROSS)) { + Serial.print(F("\r\nCross")); + PS4.setLedFlash(10, 10); // Set it to blink rapidly + } + if (PS4.getButtonClick(SQUARE)) { + Serial.print(F("\r\nSquare")); + PS4.setLedFlash(0, 0); // Turn off blinking + } + + if (PS4.getButtonClick(UP)) { + Serial.print(F("\r\nUp")); + PS4.setLed(Red); + } if (PS4.getButtonClick(RIGHT)) { + Serial.print(F("\r\nRight")); + PS4.setLed(Blue); + } if (PS4.getButtonClick(DOWN)) { + Serial.print(F("\r\nDown")); + PS4.setLed(Yellow); + } if (PS4.getButtonClick(LEFT)) { + Serial.print(F("\r\nLeft")); + PS4.setLed(Green); + } + + if (PS4.getButtonClick(L1)) + Serial.print(F("\r\nL1")); + if (PS4.getButtonClick(L3)) + Serial.print(F("\r\nL3")); + if (PS4.getButtonClick(R1)) + Serial.print(F("\r\nR1")); + if (PS4.getButtonClick(R3)) + Serial.print(F("\r\nR3")); + + if (PS4.getButtonClick(SHARE)) + Serial.print(F("\r\nShare")); + if (PS4.getButtonClick(OPTIONS)) { + Serial.print(F("\r\nOptions")); + printAngle = !printAngle; + } + if (PS4.getButtonClick(TOUCHPAD)) { + Serial.print(F("\r\nTouchpad")); + printTouch = !printTouch; + } + + if (printAngle) { // Print angle calculated using the accelerometer only + Serial.print(F("\r\nPitch: ")); + Serial.print(PS4.getAngle(Pitch)); + Serial.print(F("\tRoll: ")); + Serial.print(PS4.getAngle(Roll)); + } + + if (printTouch) { // Print the x, y coordinates of the touchpad + if (PS4.isTouching(0) || PS4.isTouching(1)) // Print newline and carriage return if any of the fingers are touching the touchpad + Serial.print(F("\r\n")); + for (uint8_t i = 0; i < 2; i++) { // The touchpad track two fingers + if (PS4.isTouching(i)) { // Print the position of the finger if it is touching the touchpad + Serial.print(F("X")); Serial.print(i + 1); Serial.print(F(": ")); + Serial.print(PS4.getX(i)); + Serial.print(F("\tY")); Serial.print(i + 1); Serial.print(F(": ")); + Serial.print(PS4.getY(i)); + Serial.print(F("\t")); + } + } + } + } + } +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/SPP/SPP.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/SPP/SPP.ino new file mode 100644 index 0000000000..8fb9c4eca2 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/SPP/SPP.ino @@ -0,0 +1,52 @@ +/* + Example sketch for the RFCOMM/SPP Bluetooth library - developed by Kristian Lauszus + For more information visit my blog: http://blog.tkjelectronics.dk/ or + send me an e-mail: kristianl@tkjelectronics.com + */ + +#include +#include + +// Satisfy the IDE, which needs to see the include statment in the ino too. +#ifdef dobogusinclude +#include +#include +#endif + +USB Usb; +//USBHub Hub1(&Usb); // Some dongles have a hub inside + +BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so +/* You can create the instance of the class in two ways */ +SPP SerialBT(&Btd); // This will set the name to the defaults: "Arduino" and the pin to "0000" +//SPP SerialBT(&Btd, "Lauszus's Arduino", "1234"); // You can also set the name and pin like so + +bool firstMessage = true; + +void setup() { + Serial.begin(115200); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + if (Usb.Init() == -1) { + Serial.print(F("\r\nOSC did not start")); + while (1); //halt + } + Serial.print(F("\r\nSPP Bluetooth Library Started")); +} +void loop() { + Usb.Task(); // The SPP data is actually not send until this is called, one could call SerialBT.send() directly as well + + if (SerialBT.connected) { + if (firstMessage) { + firstMessage = false; + SerialBT.println(F("Hello from Arduino")); // Send welcome message + } + if (Serial.available()) + SerialBT.write(Serial.read()); + if (SerialBT.available()) + Serial.write(SerialBT.read()); + } + else + firstMessage = true; +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/SPPMulti/SPPMulti.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/SPPMulti/SPPMulti.ino new file mode 100644 index 0000000000..df521d8e17 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/SPPMulti/SPPMulti.ino @@ -0,0 +1,67 @@ +/* + Example sketch for the RFCOMM/SPP Bluetooth library - developed by Kristian Lauszus + For more information visit my blog: http://blog.tkjelectronics.dk/ or + send me an e-mail: kristianl@tkjelectronics.com + */ + +#include +#include + +// Satisfy IDE, which only needs to see the include statment in the ino. +#ifdef dobogusinclude +#include +#include +#endif + +USB Usb; +//USBHub Hub1(&Usb); // Some dongles have a hub inside + +BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so + +const uint8_t length = 2; // Set the number of instances here +SPP *SerialBT[length]; // We will use this pointer to store the instances, you can easily make it larger if you like, but it will use a lot of RAM! + +bool firstMessage[length] = { true }; // Set all to true + +void setup() { + for (uint8_t i = 0; i < length; i++) + SerialBT[i] = new SPP(&Btd); // This will set the name to the default: "Arduino" and the pin to "0000" for all connections + + Serial.begin(115200); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + if (Usb.Init() == -1) { + Serial.print(F("\r\nOSC did not start")); + while (1); // Halt + } + Serial.print(F("\r\nSPP Bluetooth Library Started")); +} + +void loop() { + Usb.Task(); // The SPP data is actually not send until this is called, one could call SerialBT.send() directly as well + + for (uint8_t i = 0; i < length; i++) { + if (SerialBT[i]->connected) { + if (firstMessage[i]) { + firstMessage[i] = false; + SerialBT[i]->println(F("Hello from Arduino")); // Send welcome message + } + if (SerialBT[i]->available()) + Serial.write(SerialBT[i]->read()); + } + else + firstMessage[i] = true; + } + + // Set the connection you want to send to using the first character + // For instance "0Hello World" would send "Hello World" to connection 0 + if (Serial.available()) { + delay(10); // Wait for the rest of the data to arrive + uint8_t id = Serial.read() - '0'; // Convert from ASCII + if (id < length && SerialBT[id]->connected) { // Make sure that the id is valid and make sure that a device is actually connected + while (Serial.available()) // Check if data is available + SerialBT[id]->write(Serial.read()); // Send the data + } + } +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/Wii/Wii.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/Wii/Wii.ino new file mode 100644 index 0000000000..b193568163 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/Wii/Wii.ino @@ -0,0 +1,118 @@ +/* + Example sketch for the Wiimote Bluetooth library - developed by Kristian Lauszus + For more information visit my blog: http://blog.tkjelectronics.dk/ or + send me an e-mail: kristianl@tkjelectronics.com + */ + +#include +#include + +// Satisfy the IDE, which needs to see the include statment in the ino too. +#ifdef dobogusinclude +#include +#include +#endif + +USB Usb; +//USBHub Hub1(&Usb); // Some dongles have a hub inside + +BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so +/* You can create the instance of the class in two ways */ +WII Wii(&Btd, PAIR); // This will start an inquiry and then pair with your Wiimote - you only have to do this once +//WII Wii(&Btd); // After that you can simply create the instance like so and then press any button on the Wiimote + +bool printAngle; + +void setup() { + Serial.begin(115200); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + if (Usb.Init() == -1) { + Serial.print(F("\r\nOSC did not start")); + while (1); //halt + } + Serial.print(F("\r\nWiimote Bluetooth Library Started")); +} +void loop() { + Usb.Task(); + if (Wii.wiimoteConnected) { + if (Wii.getButtonClick(HOME)) { // You can use getButtonPress to see if the button is held down + Serial.print(F("\r\nHOME")); + Wii.disconnect(); + } + else { + if (Wii.getButtonClick(LEFT)) { + Wii.setLedOff(); + Wii.setLedOn(LED1); + Serial.print(F("\r\nLeft")); + } + if (Wii.getButtonClick(RIGHT)) { + Wii.setLedOff(); + Wii.setLedOn(LED3); + Serial.print(F("\r\nRight")); + } + if (Wii.getButtonClick(DOWN)) { + Wii.setLedOff(); + Wii.setLedOn(LED4); + Serial.print(F("\r\nDown")); + } + if (Wii.getButtonClick(UP)) { + Wii.setLedOff(); + Wii.setLedOn(LED2); + Serial.print(F("\r\nUp")); + } + + if (Wii.getButtonClick(PLUS)) + Serial.print(F("\r\nPlus")); + if (Wii.getButtonClick(MINUS)) + Serial.print(F("\r\nMinus")); + + if (Wii.getButtonClick(ONE)) + Serial.print(F("\r\nOne")); + if (Wii.getButtonClick(TWO)) + Serial.print(F("\r\nTwo")); + + if (Wii.getButtonClick(A)) { + printAngle = !printAngle; + Serial.print(F("\r\nA")); + } + if (Wii.getButtonClick(B)) { + Wii.setRumbleToggle(); + Serial.print(F("\r\nB")); + } + } +#if 0 // Set this to 1 in order to see the angle of the controllers + if (printAngle) { + Serial.print(F("\r\nPitch: ")); + Serial.print(Wii.getPitch()); + Serial.print(F("\tRoll: ")); + Serial.print(Wii.getRoll()); + if (Wii.motionPlusConnected) { + Serial.print(F("\tYaw: ")); + Serial.print(Wii.getYaw()); + } + if (Wii.nunchuckConnected) { + Serial.print(F("\tNunchuck Pitch: ")); + Serial.print(Wii.getNunchuckPitch()); + Serial.print(F("\tNunchuck Roll: ")); + Serial.print(Wii.getNunchuckRoll()); + } + } +#endif + } +#if 0 // Set this to 1 if you are using a Nunchuck controller + if (Wii.nunchuckConnected) { + if (Wii.getButtonClick(Z)) + Serial.print(F("\r\nZ")); + if (Wii.getButtonClick(C)) + Serial.print(F("\r\nC")); + if (Wii.getAnalogHat(HatX) > 137 || Wii.getAnalogHat(HatX) < 117 || Wii.getAnalogHat(HatY) > 137 || Wii.getAnalogHat(HatY) < 117) { + Serial.print(F("\r\nHatX: ")); + Serial.print(Wii.getAnalogHat(HatX)); + Serial.print(F("\tHatY: ")); + Serial.print(Wii.getAnalogHat(HatY)); + } + } +#endif +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/WiiBalanceBoard/WiiBalanceBoard.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/WiiBalanceBoard/WiiBalanceBoard.ino new file mode 100644 index 0000000000..18c5b411ef --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/WiiBalanceBoard/WiiBalanceBoard.ino @@ -0,0 +1,51 @@ +/* + Example sketch for the Wii Balance Board Bluetooth library - developed by Kristian Lauszus + For more information visit my blog: http://blog.tkjelectronics.dk/ or + send me an e-mail: kristianl@tkjelectronics.com + */ + +#include +#include + +// Satisfy the IDE, which needs to see the include statment in the ino too. +#ifdef dobogusinclude +#include +#include +#endif + +USB Usb; +//USBHub Hub1(&Usb); // Some dongles have a hub inside + +BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so +/* You can create the instance of the class in two ways */ +WII Wii(&Btd, PAIR); // This will start an inquiry and then pair with your Wii Balance Board - you only have to do this once +//WII Wii(&Btd); // After that you can simply create the instance like so and then press the power button on the Wii Balance Board + +void setup() { + Serial.begin(115200); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + if (Usb.Init() == -1) { + Serial.print(F("\r\nOSC did not start")); + while (1); //halt + } + Serial.print(F("\r\nWii Balance Board Bluetooth Library Started")); +} +void loop() { + Usb.Task(); + if (Wii.wiiBalanceBoardConnected) { + Serial.print(F("\r\nWeight: ")); + for (uint8_t i = 0; i < 4; i++) { + Serial.print(Wii.getWeight((BalanceBoardEnum)i)); + Serial.print(F("\t")); + } + Serial.print(F("Total Weight: ")); + Serial.print(Wii.getTotalWeight()); + if (Wii.getButtonClick(A)) { + Serial.print(F("\r\nA")); + //Wii.setLedToggle(LED1); // The Wii Balance Board has one LED as well + Wii.disconnect(); + } + } +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/WiiIRCamera/WiiIRCamera.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/WiiIRCamera/WiiIRCamera.ino new file mode 100644 index 0000000000..573b8bd48c --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/WiiIRCamera/WiiIRCamera.ino @@ -0,0 +1,133 @@ +/* +Example sketch for the Wii libary showing the IR camera functionality. This example +is for the Bluetooth Wii library developed for the USB shield from Circuits@Home + +Created by Allan Glover and Kristian Lauszus. +Contact Kristian: http://blog.tkjelectronics.dk/ or send an email at kristianl@tkjelectronics.com. +Contact Allan at adglover9.81@gmail.com + +To test the Wiimote IR camera, you will need access to an IR source. Sunlight will work but is not ideal. +The simpleist solution is to use the Wii sensor bar, i.e. emitter bar, supplied by the Wii system. +Otherwise, wire up a IR LED yourself. +*/ + +#include +#include + +// Satisfy the IDE, which needs to see the include statment in the ino too. +#ifdef dobogusinclude +#include +#include +#endif + +#ifndef WIICAMERA // Used to check if WIICAMERA is defined +#error "Please set ENABLE_WII_IR_CAMERA to 1 in settings.h" +#endif + +USB Usb; +//USBHub Hub1(&Usb); // Some dongles have a hub inside + +BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so +/* You can create the instance of the class in two ways */ +WII Wii(&Btd, PAIR); // This will start an inquiry and then pair with your Wiimote - you only have to do this once +//WII Wii(&Btd); // After the Wiimote pairs once with the line of code above, you can simply create the instance like so and re upload and then press any button on the Wiimote + +bool printAngle; +uint8_t printObjects; + +void setup() { + Serial.begin(115200); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + if (Usb.Init() == -1) { + Serial.print(F("\r\nOSC did not start")); + while (1); //halt + } + Serial.print(F("\r\nWiimote Bluetooth Library Started")); +} + +void loop() { + Usb.Task(); + if (Wii.wiimoteConnected) { + if (Wii.getButtonClick(HOME)) { // You can use getButtonPress to see if the button is held down + Serial.print(F("\r\nHOME")); + Wii.disconnect(); + } + else { + if (Wii.getButtonClick(ONE)) + Wii.IRinitialize(); // Run the initialisation sequence + if (Wii.getButtonClick(MINUS) || Wii.getButtonClick(PLUS)) { + if (!Wii.isIRCameraEnabled()) + Serial.print(F("\r\nEnable IR camera first")); + else { + if (Wii.getButtonPress(MINUS)) { // getButtonClick will only return true once + if (printObjects > 0) + printObjects--; + } + else { + if (printObjects < 4) + printObjects++; + } + Serial.print(F("\r\nTracking ")); + Serial.print(printObjects); + Serial.print(F(" objects")); + } + } + if (Wii.getButtonClick(A)) { + printAngle = !printAngle; + Serial.print(F("\r\nA")); + } + if (Wii.getButtonClick(B)) { + Serial.print(F("\r\nBattery level: ")); + Serial.print(Wii.getBatteryLevel()); // You can get the battery level as well + } + } + if (printObjects > 0) { + if (Wii.getIRx1() != 0x3FF || Wii.getIRy1() != 0x3FF || Wii.getIRs1() != 0) { // Only print if the IR camera is actually seeing something + Serial.print(F("\r\nx1: ")); + Serial.print(Wii.getIRx1()); + Serial.print(F("\ty1: ")); + Serial.print(Wii.getIRy1()); + Serial.print(F("\ts1:")); + Serial.print(Wii.getIRs1()); + } + if (printObjects > 1) { + if (Wii.getIRx2() != 0x3FF || Wii.getIRy2() != 0x3FF || Wii.getIRs2() != 0) { + Serial.print(F("\r\nx2: ")); + Serial.print(Wii.getIRx2()); + Serial.print(F("\ty2: ")); + Serial.print(Wii.getIRy2()); + Serial.print(F("\ts2:")); + Serial.print(Wii.getIRs2()); + } + if (printObjects > 2) { + if (Wii.getIRx3() != 0x3FF || Wii.getIRy3() != 0x3FF || Wii.getIRs3() != 0) { + Serial.print(F("\r\nx3: ")); + Serial.print(Wii.getIRx3()); + Serial.print(F("\ty3: ")); + Serial.print(Wii.getIRy3()); + Serial.print(F("\ts3:")); + Serial.print(Wii.getIRs3()); + } + if (printObjects > 3) { + if (Wii.getIRx4() != 0x3FF || Wii.getIRy4() != 0x3FF || Wii.getIRs4() != 0) { + Serial.print(F("\r\nx4: ")); + Serial.print(Wii.getIRx4()); + Serial.print(F("\ty4: ")); + Serial.print(Wii.getIRy4()); + Serial.print(F("\ts4:")); + Serial.print(Wii.getIRs4()); + } + } + } + } + } + if (printAngle) { // There is no extension bytes available, so the MotionPlus or Nunchuck can't be read + Serial.print(F("\r\nPitch: ")); + Serial.print(Wii.getPitch()); + Serial.print(F("\tRoll: ")); + Serial.print(Wii.getRoll()); + } + } +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/WiiMulti/WiiMulti.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/WiiMulti/WiiMulti.ino new file mode 100644 index 0000000000..07c6f13d2b --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/WiiMulti/WiiMulti.ino @@ -0,0 +1,132 @@ +/* + Example sketch for the Wiimote Bluetooth library - developed by Kristian Lauszus + This example show how one can use multiple controllers with the library + For more information visit my blog: http://blog.tkjelectronics.dk/ or + send me an e-mail: kristianl@tkjelectronics.com + */ + +#include +#include + +// Satisfy the IDE, which needs to see the include statment in the ino too. +#ifdef dobogusinclude +#include +#include +#endif + +USB Usb; +//USBHub Hub1(&Usb); // Some dongles have a hub inside + +BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so +WII *Wii[2]; // We will use this pointer to store the two instance, you can easily make it larger if you like, but it will use a lot of RAM! +const uint8_t length = sizeof(Wii) / sizeof(Wii[0]); // Get the lenght of the array +bool printAngle[length]; +bool oldControllerState[length]; + +void setup() { + for (uint8_t i = 0; i < length; i++) { + Wii[i] = new WII(&Btd); // You will have to pair each controller with the dongle before you can define the instances like so, just add PAIR as the second argument + Wii[i]->attachOnInit(onInit); // onInit() is called upon a new connection - you can call the function whatever you like + } + + Serial.begin(115200); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + if (Usb.Init() == -1) { + Serial.print(F("\r\nOSC did not start")); + while (1); //halt + } + Serial.print(F("\r\nWiimote Bluetooth Library Started")); +} +void loop() { + Usb.Task(); + + for (uint8_t i = 0; i < length; i++) { + if (Wii[i]->wiimoteConnected) { + if (Wii[i]->getButtonClick(HOME)) { // You can use getButtonPress to see if the button is held down + Serial.print(F("\r\nHOME")); + Wii[i]->disconnect(); + oldControllerState[i] = false; // Reset value + } + else { + if (Wii[i]->getButtonClick(LEFT)) { + Wii[i]->setLedOff(); + Wii[i]->setLedOn(LED1); + Serial.print(F("\r\nLeft")); + } + if (Wii[i]->getButtonClick(RIGHT)) { + Wii[i]->setLedOff(); + Wii[i]->setLedOn(LED3); + Serial.print(F("\r\nRight")); + } + if (Wii[i]->getButtonClick(DOWN)) { + Wii[i]->setLedOff(); + Wii[i]->setLedOn(LED4); + Serial.print(F("\r\nDown")); + } + if (Wii[i]->getButtonClick(UP)) { + Wii[i]->setLedOff(); + Wii[i]->setLedOn(LED2); + Serial.print(F("\r\nUp")); + } + + if (Wii[i]->getButtonClick(PLUS)) + Serial.print(F("\r\nPlus")); + if (Wii[i]->getButtonClick(MINUS)) + Serial.print(F("\r\nMinus")); + + if (Wii[i]->getButtonClick(ONE)) + Serial.print(F("\r\nOne")); + if (Wii[i]->getButtonClick(TWO)) + Serial.print(F("\r\nTwo")); + + if (Wii[i]->getButtonClick(A)) { + printAngle[i] = !printAngle[i]; + Serial.print(F("\r\nA")); + } + if (Wii[i]->getButtonClick(B)) { + Wii[i]->setRumbleToggle(); + Serial.print(F("\r\nB")); + } + } + if (printAngle[i]) { + Serial.print(F("\r\nPitch: ")); + Serial.print(Wii[i]->getPitch()); + Serial.print(F("\tRoll: ")); + Serial.print(Wii[i]->getRoll()); + if (Wii[i]->motionPlusConnected) { + Serial.print(F("\tYaw: ")); + Serial.print(Wii[i]->getYaw()); + } + if (Wii[i]->nunchuckConnected) { + Serial.print(F("\tNunchuck Pitch: ")); + Serial.print(Wii[i]->getNunchuckPitch()); + Serial.print(F("\tNunchuck Roll: ")); + Serial.print(Wii[i]->getNunchuckRoll()); + } + } + } + if (Wii[i]->nunchuckConnected) { + if (Wii[i]->getButtonClick(Z)) + Serial.print(F("\r\nZ")); + if (Wii[i]->getButtonClick(C)) + Serial.print(F("\r\nC")); + if (Wii[i]->getAnalogHat(HatX) > 137 || Wii[i]->getAnalogHat(HatX) < 117 || Wii[i]->getAnalogHat(HatY) > 137 || Wii[i]->getAnalogHat(HatY) < 117) { + Serial.print(F("\r\nHatX: ")); + Serial.print(Wii[i]->getAnalogHat(HatX)); + Serial.print(F("\tHatY: ")); + Serial.print(Wii[i]->getAnalogHat(HatY)); + } + } + } +} + +void onInit() { + for (uint8_t i = 0; i < length; i++) { + if (Wii[i]->wiimoteConnected && !oldControllerState[i]) { + oldControllerState[i] = true; // Used to check which is the new controller + Wii[i]->setLedOn((LEDEnum)(i + 1)); // Cast directly to LEDEnum - see: "controllerEnums.h" + } + } +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/WiiUProController/WiiUProController.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/WiiUProController/WiiUProController.ino new file mode 100644 index 0000000000..ab35a27479 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/Bluetooth/WiiUProController/WiiUProController.ino @@ -0,0 +1,104 @@ +/* + Example sketch for the Wiimote Bluetooth library - developed by Kristian Lauszus + For more information visit my blog: http://blog.tkjelectronics.dk/ or + send me an e-mail: kristianl@tkjelectronics.com + */ + +#include +#include + +// Satisfy the IDE, which needs to see the include statment in the ino too. +#ifdef dobogusinclude +#include +#include +#endif + +USB Usb; +//USBHub Hub1(&Usb); // Some dongles have a hub inside + +BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so +/* You can create the instance of the class in two ways */ +WII Wii(&Btd, PAIR); // This will start an inquiry and then pair with your Wiimote - you only have to do this once +//WII Wii(&Btd); // After that you can simply create the instance like so and then press any button on the Wiimote + +void setup() { + Serial.begin(115200); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + if (Usb.Init() == -1) { + Serial.print(F("\r\nOSC did not start")); + while (1); //halt + } + Serial.print(F("\r\nWiimote Bluetooth Library Started")); +} +void loop() { + Usb.Task(); + if (Wii.wiiUProControllerConnected) { + if (Wii.getButtonClick(HOME)) { // You can use getButtonPress to see if the button is held down + Serial.print(F("\r\nHome")); + Wii.disconnect(); + } + else { + if (Wii.getButtonClick(LEFT)) { + Wii.setLedOff(); + Wii.setLedOn(LED1); + Serial.print(F("\r\nLeft")); + } + if (Wii.getButtonClick(RIGHT)) { + Wii.setLedOff(); + Wii.setLedOn(LED3); + Serial.print(F("\r\nRight")); + } + if (Wii.getButtonClick(DOWN)) { + Wii.setLedOff(); + Wii.setLedOn(LED4); + Serial.print(F("\r\nDown")); + } + if (Wii.getButtonClick(UP)) { + Wii.setLedOff(); + Wii.setLedOn(LED2); + Serial.print(F("\r\nUp")); + } + + if (Wii.getButtonClick(PLUS)) + Serial.print(F("\r\nPlus")); + if (Wii.getButtonClick(MINUS)) + Serial.print(F("\r\nMinus")); + + if (Wii.getButtonClick(A)) + Serial.print(F("\r\nA")); + if (Wii.getButtonClick(B)) { + Wii.setRumbleToggle(); + Serial.print(F("\r\nB")); + } + if (Wii.getButtonClick(X)) + Serial.print(F("\r\nX")); + if (Wii.getButtonClick(Y)) + Serial.print(F("\r\nY")); + + if (Wii.getButtonClick(L)) + Serial.print(F("\r\nL")); + if (Wii.getButtonClick(R)) + Serial.print(F("\r\nR")); + if (Wii.getButtonClick(ZL)) + Serial.print(F("\r\nZL")); + if (Wii.getButtonClick(ZR)) + Serial.print(F("\r\nZR")); + if (Wii.getButtonClick(L3)) + Serial.print(F("\r\nL3")); + if (Wii.getButtonClick(R3)) + Serial.print(F("\r\nR3")); + } + if (Wii.getAnalogHat(LeftHatX) > 2200 || Wii.getAnalogHat(LeftHatX) < 1800 || Wii.getAnalogHat(LeftHatY) > 2200 || Wii.getAnalogHat(LeftHatY) < 1800 || Wii.getAnalogHat(RightHatX) > 2200 || Wii.getAnalogHat(RightHatX) < 1800 || Wii.getAnalogHat(RightHatY) > 2200 || Wii.getAnalogHat(RightHatY) < 1800) { + Serial.print(F("\r\nLeftHatX: ")); + Serial.print(Wii.getAnalogHat(LeftHatX)); + Serial.print(F("\tLeftHatY: ")); + Serial.print(Wii.getAnalogHat(LeftHatY)); + Serial.print(F("\tRightHatX: ")); + Serial.print(Wii.getAnalogHat(RightHatX)); + Serial.print(F("\tRightHatY: ")); + Serial.print(Wii.getAnalogHat(RightHatY)); + } + } +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/HID/USBHIDBootKbd/USBHIDBootKbd.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/HID/USBHIDBootKbd/USBHIDBootKbd.ino new file mode 100644 index 0000000000..48b33abfd2 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/HID/USBHIDBootKbd/USBHIDBootKbd.ino @@ -0,0 +1,129 @@ +#include +#include + +// Satisfy the IDE, which needs to see the include statment in the ino too. +#ifdef dobogusinclude +#include +#include +#endif + +class KbdRptParser : public KeyboardReportParser +{ + void PrintKey(uint8_t mod, uint8_t key); + + protected: + void OnControlKeysChanged(uint8_t before, uint8_t after); + + void OnKeyDown (uint8_t mod, uint8_t key); + void OnKeyUp (uint8_t mod, uint8_t key); + void OnKeyPressed(uint8_t key); +}; + +void KbdRptParser::PrintKey(uint8_t m, uint8_t key) +{ + MODIFIERKEYS mod; + *((uint8_t*)&mod) = m; + Serial.print((mod.bmLeftCtrl == 1) ? "C" : " "); + Serial.print((mod.bmLeftShift == 1) ? "S" : " "); + Serial.print((mod.bmLeftAlt == 1) ? "A" : " "); + Serial.print((mod.bmLeftGUI == 1) ? "G" : " "); + + Serial.print(" >"); + PrintHex(key, 0x80); + Serial.print("< "); + + Serial.print((mod.bmRightCtrl == 1) ? "C" : " "); + Serial.print((mod.bmRightShift == 1) ? "S" : " "); + Serial.print((mod.bmRightAlt == 1) ? "A" : " "); + Serial.println((mod.bmRightGUI == 1) ? "G" : " "); +}; + +void KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key) +{ + Serial.print("DN "); + PrintKey(mod, key); + uint8_t c = OemToAscii(mod, key); + + if (c) + OnKeyPressed(c); +} + +void KbdRptParser::OnControlKeysChanged(uint8_t before, uint8_t after) { + + MODIFIERKEYS beforeMod; + *((uint8_t*)&beforeMod) = before; + + MODIFIERKEYS afterMod; + *((uint8_t*)&afterMod) = after; + + if (beforeMod.bmLeftCtrl != afterMod.bmLeftCtrl) { + Serial.println("LeftCtrl changed"); + } + if (beforeMod.bmLeftShift != afterMod.bmLeftShift) { + Serial.println("LeftShift changed"); + } + if (beforeMod.bmLeftAlt != afterMod.bmLeftAlt) { + Serial.println("LeftAlt changed"); + } + if (beforeMod.bmLeftGUI != afterMod.bmLeftGUI) { + Serial.println("LeftGUI changed"); + } + + if (beforeMod.bmRightCtrl != afterMod.bmRightCtrl) { + Serial.println("RightCtrl changed"); + } + if (beforeMod.bmRightShift != afterMod.bmRightShift) { + Serial.println("RightShift changed"); + } + if (beforeMod.bmRightAlt != afterMod.bmRightAlt) { + Serial.println("RightAlt changed"); + } + if (beforeMod.bmRightGUI != afterMod.bmRightGUI) { + Serial.println("RightGUI changed"); + } + +} + +void KbdRptParser::OnKeyUp(uint8_t mod, uint8_t key) +{ + Serial.print("UP "); + PrintKey(mod, key); +} + +void KbdRptParser::OnKeyPressed(uint8_t key) +{ + Serial.print("ASCII: "); + Serial.println((char)key); +}; + +USB Usb; +//USBHub Hub(&Usb); +HIDBoot HidKeyboard(&Usb); + +uint32_t next_time; + +KbdRptParser Prs; + +void setup() +{ + Serial.begin( 115200 ); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + Serial.println("Start"); + + if (Usb.Init() == -1) + Serial.println("OSC did not start."); + + delay( 200 ); + + next_time = millis() + 5000; + + HidKeyboard.SetReportParser(0, (HIDReportParser*)&Prs); +} + +void loop() +{ + Usb.Task(); +} + diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/HID/USBHIDBootKbdAndMouse/USBHIDBootKbdAndMouse.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/HID/USBHIDBootKbdAndMouse/USBHIDBootKbdAndMouse.ino new file mode 100644 index 0000000000..5fc8c96fc9 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/HID/USBHIDBootKbdAndMouse/USBHIDBootKbdAndMouse.ino @@ -0,0 +1,178 @@ +#include +#include + +// Satisfy IDE, which only needs to see the include statment in the ino. +#ifdef dobogusinclude +#include +#include +#endif + +class MouseRptParser : public MouseReportParser +{ + protected: + void OnMouseMove(MOUSEINFO *mi); + void OnLeftButtonUp(MOUSEINFO *mi); + void OnLeftButtonDown(MOUSEINFO *mi); + void OnRightButtonUp(MOUSEINFO *mi); + void OnRightButtonDown(MOUSEINFO *mi); + void OnMiddleButtonUp(MOUSEINFO *mi); + void OnMiddleButtonDown(MOUSEINFO *mi); +}; +void MouseRptParser::OnMouseMove(MOUSEINFO *mi) +{ + Serial.print("dx="); + Serial.print(mi->dX, DEC); + Serial.print(" dy="); + Serial.println(mi->dY, DEC); +}; +void MouseRptParser::OnLeftButtonUp (MOUSEINFO *mi) +{ + Serial.println("L Butt Up"); +}; +void MouseRptParser::OnLeftButtonDown (MOUSEINFO *mi) +{ + Serial.println("L Butt Dn"); +}; +void MouseRptParser::OnRightButtonUp (MOUSEINFO *mi) +{ + Serial.println("R Butt Up"); +}; +void MouseRptParser::OnRightButtonDown (MOUSEINFO *mi) +{ + Serial.println("R Butt Dn"); +}; +void MouseRptParser::OnMiddleButtonUp (MOUSEINFO *mi) +{ + Serial.println("M Butt Up"); +}; +void MouseRptParser::OnMiddleButtonDown (MOUSEINFO *mi) +{ + Serial.println("M Butt Dn"); +}; + +class KbdRptParser : public KeyboardReportParser +{ + void PrintKey(uint8_t mod, uint8_t key); + + protected: + void OnControlKeysChanged(uint8_t before, uint8_t after); + void OnKeyDown (uint8_t mod, uint8_t key); + void OnKeyUp (uint8_t mod, uint8_t key); + void OnKeyPressed(uint8_t key); +}; + +void KbdRptParser::PrintKey(uint8_t m, uint8_t key) +{ + MODIFIERKEYS mod; + *((uint8_t*)&mod) = m; + Serial.print((mod.bmLeftCtrl == 1) ? "C" : " "); + Serial.print((mod.bmLeftShift == 1) ? "S" : " "); + Serial.print((mod.bmLeftAlt == 1) ? "A" : " "); + Serial.print((mod.bmLeftGUI == 1) ? "G" : " "); + + Serial.print(" >"); + PrintHex(key, 0x80); + Serial.print("< "); + + Serial.print((mod.bmRightCtrl == 1) ? "C" : " "); + Serial.print((mod.bmRightShift == 1) ? "S" : " "); + Serial.print((mod.bmRightAlt == 1) ? "A" : " "); + Serial.println((mod.bmRightGUI == 1) ? "G" : " "); +}; + +void KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key) +{ + Serial.print("DN "); + PrintKey(mod, key); + uint8_t c = OemToAscii(mod, key); + + if (c) + OnKeyPressed(c); +} + +void KbdRptParser::OnControlKeysChanged(uint8_t before, uint8_t after) { + + MODIFIERKEYS beforeMod; + *((uint8_t*)&beforeMod) = before; + + MODIFIERKEYS afterMod; + *((uint8_t*)&afterMod) = after; + + if (beforeMod.bmLeftCtrl != afterMod.bmLeftCtrl) { + Serial.println("LeftCtrl changed"); + } + if (beforeMod.bmLeftShift != afterMod.bmLeftShift) { + Serial.println("LeftShift changed"); + } + if (beforeMod.bmLeftAlt != afterMod.bmLeftAlt) { + Serial.println("LeftAlt changed"); + } + if (beforeMod.bmLeftGUI != afterMod.bmLeftGUI) { + Serial.println("LeftGUI changed"); + } + + if (beforeMod.bmRightCtrl != afterMod.bmRightCtrl) { + Serial.println("RightCtrl changed"); + } + if (beforeMod.bmRightShift != afterMod.bmRightShift) { + Serial.println("RightShift changed"); + } + if (beforeMod.bmRightAlt != afterMod.bmRightAlt) { + Serial.println("RightAlt changed"); + } + if (beforeMod.bmRightGUI != afterMod.bmRightGUI) { + Serial.println("RightGUI changed"); + } + +} + +void KbdRptParser::OnKeyUp(uint8_t mod, uint8_t key) +{ + Serial.print("UP "); + PrintKey(mod, key); +} + +void KbdRptParser::OnKeyPressed(uint8_t key) +{ + Serial.print("ASCII: "); + Serial.println((char)key); +}; + +USB Usb; +USBHub Hub(&Usb); + +HIDBoot < HID_PROTOCOL_KEYBOARD | HID_PROTOCOL_MOUSE > HidComposite(&Usb); +HIDBoot HidKeyboard(&Usb); +HIDBoot HidMouse(&Usb); + +//uint32_t next_time; + +KbdRptParser KbdPrs; +MouseRptParser MousePrs; + +void setup() +{ + Serial.begin( 115200 ); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + Serial.println("Start"); + + if (Usb.Init() == -1) + Serial.println("OSC did not start."); + + delay( 200 ); + + //next_time = millis() + 5000; + + HidComposite.SetReportParser(0, (HIDReportParser*)&KbdPrs); + HidComposite.SetReportParser(1, (HIDReportParser*)&MousePrs); + HidKeyboard.SetReportParser(0, (HIDReportParser*)&KbdPrs); + HidMouse.SetReportParser(0, (HIDReportParser*)&MousePrs); +} + +void loop() +{ + Usb.Task(); +} + diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/HID/USBHIDBootMouse/USBHIDBootMouse.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/HID/USBHIDBootMouse/USBHIDBootMouse.ino new file mode 100644 index 0000000000..53102512bd --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/HID/USBHIDBootMouse/USBHIDBootMouse.ino @@ -0,0 +1,83 @@ +#include +#include + +// Satisfy the IDE, which needs to see the include statment in the ino too. +#ifdef dobogusinclude +#include +#include +#endif + +class MouseRptParser : public MouseReportParser +{ +protected: + void OnMouseMove (MOUSEINFO *mi); + void OnLeftButtonUp (MOUSEINFO *mi); + void OnLeftButtonDown (MOUSEINFO *mi); + void OnRightButtonUp (MOUSEINFO *mi); + void OnRightButtonDown (MOUSEINFO *mi); + void OnMiddleButtonUp (MOUSEINFO *mi); + void OnMiddleButtonDown (MOUSEINFO *mi); +}; +void MouseRptParser::OnMouseMove(MOUSEINFO *mi) +{ + Serial.print("dx="); + Serial.print(mi->dX, DEC); + Serial.print(" dy="); + Serial.println(mi->dY, DEC); +}; +void MouseRptParser::OnLeftButtonUp (MOUSEINFO *mi) +{ + Serial.println("L Butt Up"); +}; +void MouseRptParser::OnLeftButtonDown (MOUSEINFO *mi) +{ + Serial.println("L Butt Dn"); +}; +void MouseRptParser::OnRightButtonUp (MOUSEINFO *mi) +{ + Serial.println("R Butt Up"); +}; +void MouseRptParser::OnRightButtonDown (MOUSEINFO *mi) +{ + Serial.println("R Butt Dn"); +}; +void MouseRptParser::OnMiddleButtonUp (MOUSEINFO *mi) +{ + Serial.println("M Butt Up"); +}; +void MouseRptParser::OnMiddleButtonDown (MOUSEINFO *mi) +{ + Serial.println("M Butt Dn"); +}; + +USB Usb; +USBHub Hub(&Usb); +HIDBoot HidMouse(&Usb); + +uint32_t next_time; + +MouseRptParser Prs; + +void setup() +{ + Serial.begin( 115200 ); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + Serial.println("Start"); + + if (Usb.Init() == -1) + Serial.println("OSC did not start."); + + delay( 200 ); + + next_time = millis() + 5000; + + HidMouse.SetReportParser(0,(HIDReportParser*)&Prs); +} + +void loop() +{ + Usb.Task(); +} + diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/USBHIDJoystick.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/USBHIDJoystick.ino new file mode 100644 index 0000000000..956441d67a --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/USBHIDJoystick.ino @@ -0,0 +1,38 @@ +#include +#include +#include + +// Satisfy IDE, which only needs to see the include statment in the ino. +#ifdef dobogusinclude +#include +#include +#endif + +#include "hidjoystickrptparser.h" + +USB Usb; +USBHub Hub(&Usb); +HIDUniversal Hid(&Usb); +JoystickEvents JoyEvents; +JoystickReportParser Joy(&JoyEvents); + +void setup() { + Serial.begin(115200); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + Serial.println("Start"); + + if (Usb.Init() == -1) + Serial.println("OSC did not start."); + + delay(200); + + if (!Hid.SetReportParser(0, &Joy)) + ErrorMessage (PSTR("SetReportParser"), 1); +} + +void loop() { + Usb.Task(); +} + diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/hidjoystickrptparser.cpp b/lib/usbhost/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/hidjoystickrptparser.cpp new file mode 100644 index 0000000000..083b95cac5 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/hidjoystickrptparser.cpp @@ -0,0 +1,84 @@ +#include "hidjoystickrptparser.h" + +JoystickReportParser::JoystickReportParser(JoystickEvents *evt) : +joyEvents(evt), +oldHat(0xDE), +oldButtons(0) { + for (uint8_t i = 0; i < RPT_GEMEPAD_LEN; i++) + oldPad[i] = 0xD; +} + +void JoystickReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) { + bool match = true; + + // Checking if there are changes in report since the method was last called + for (uint8_t i = 0; i < RPT_GEMEPAD_LEN; i++) + if (buf[i] != oldPad[i]) { + match = false; + break; + } + + // Calling Game Pad event handler + if (!match && joyEvents) { + joyEvents->OnGamePadChanged((const GamePadEventData*)buf); + + for (uint8_t i = 0; i < RPT_GEMEPAD_LEN; i++) oldPad[i] = buf[i]; + } + + uint8_t hat = (buf[5] & 0xF); + + // Calling Hat Switch event handler + if (hat != oldHat && joyEvents) { + joyEvents->OnHatSwitch(hat); + oldHat = hat; + } + + uint16_t buttons = (0x0000 | buf[6]); + buttons <<= 4; + buttons |= (buf[5] >> 4); + uint16_t changes = (buttons ^ oldButtons); + + // Calling Button Event Handler for every button changed + if (changes) { + for (uint8_t i = 0; i < 0x0C; i++) { + uint16_t mask = (0x0001 << i); + + if (((mask & changes) > 0) && joyEvents) + if ((buttons & mask) > 0) + joyEvents->OnButtonDn(i + 1); + else + joyEvents->OnButtonUp(i + 1); + } + oldButtons = buttons; + } +} + +void JoystickEvents::OnGamePadChanged(const GamePadEventData *evt) { + Serial.print("X1: "); + PrintHex (evt->X, 0x80); + Serial.print("\tY1: "); + PrintHex (evt->Y, 0x80); + Serial.print("\tX2: "); + PrintHex (evt->Z1, 0x80); + Serial.print("\tY2: "); + PrintHex (evt->Z2, 0x80); + Serial.print("\tRz: "); + PrintHex (evt->Rz, 0x80); + Serial.println(""); +} + +void JoystickEvents::OnHatSwitch(uint8_t hat) { + Serial.print("Hat Switch: "); + PrintHex (hat, 0x80); + Serial.println(""); +} + +void JoystickEvents::OnButtonUp(uint8_t but_id) { + Serial.print("Up: "); + Serial.println(but_id, DEC); +} + +void JoystickEvents::OnButtonDn(uint8_t but_id) { + Serial.print("Dn: "); + Serial.println(but_id, DEC); +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/hidjoystickrptparser.h b/lib/usbhost/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/hidjoystickrptparser.h new file mode 100644 index 0000000000..733b8f8da8 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/hidjoystickrptparser.h @@ -0,0 +1,33 @@ +#if !defined(__HIDJOYSTICKRPTPARSER_H__) +#define __HIDJOYSTICKRPTPARSER_H__ + +#include + +struct GamePadEventData { + uint8_t X, Y, Z1, Z2, Rz; +}; + +class JoystickEvents { +public: + virtual void OnGamePadChanged(const GamePadEventData *evt); + virtual void OnHatSwitch(uint8_t hat); + virtual void OnButtonUp(uint8_t but_id); + virtual void OnButtonDn(uint8_t but_id); +}; + +#define RPT_GEMEPAD_LEN 5 + +class JoystickReportParser : public HIDReportParser { + JoystickEvents *joyEvents; + + uint8_t oldPad[RPT_GEMEPAD_LEN]; + uint8_t oldHat; + uint16_t oldButtons; + +public: + JoystickReportParser(JoystickEvents *evt); + + virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); +}; + +#endif // __HIDJOYSTICKRPTPARSER_H__ diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/HID/USBHID_desc/USBHID_desc.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/HID/USBHID_desc/USBHID_desc.ino new file mode 100644 index 0000000000..85cfc19a2e --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/HID/USBHID_desc/USBHID_desc.ino @@ -0,0 +1,77 @@ +#include +#include +#include +#include +#include "pgmstrings.h" + +// Satisfy the IDE, which needs to see the include statment in the ino too. +#ifdef dobogusinclude +#include +#include +#endif + +class HIDUniversal2 : public HIDUniversal +{ +public: + HIDUniversal2(USB *usb) : HIDUniversal(usb) {}; + +protected: + uint8_t OnInitSuccessful(); +}; + +uint8_t HIDUniversal2::OnInitSuccessful() +{ + uint8_t rcode; + + HexDumper Hex; + ReportDescParser Rpt; + + if ((rcode = GetReportDescr(0, &Hex))) + goto FailGetReportDescr1; + + if ((rcode = GetReportDescr(0, &Rpt))) + goto FailGetReportDescr2; + + return 0; + +FailGetReportDescr1: + USBTRACE("GetReportDescr1:"); + goto Fail; + +FailGetReportDescr2: + USBTRACE("GetReportDescr2:"); + goto Fail; + +Fail: + Serial.println(rcode, HEX); + Release(); + return rcode; +} + +USB Usb; +//USBHub Hub(&Usb); +HIDUniversal2 Hid(&Usb); +UniversalReportParser Uni; + +void setup() +{ + Serial.begin( 115200 ); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + Serial.println("Start"); + + if (Usb.Init() == -1) + Serial.println("OSC did not start."); + + delay( 200 ); + + if (!Hid.SetReportParser(0, &Uni)) + ErrorMessage(PSTR("SetReportParser"), 1 ); +} + +void loop() +{ + Usb.Task(); +} + diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/HID/USBHID_desc/pgmstrings.h b/lib/usbhost/USB_Host_Shield_2.0/examples/HID/USBHID_desc/pgmstrings.h new file mode 100644 index 0000000000..bdb0077ecc --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/HID/USBHID_desc/pgmstrings.h @@ -0,0 +1,52 @@ +#if !defined(__PGMSTRINGS_H__) +#define __PGMSTRINGS_H__ + +#define LOBYTE(x) ((char*)(&(x)))[0] +#define HIBYTE(x) ((char*)(&(x)))[1] +#define BUFSIZE 256 //buffer size + + +/* Print strings in Program Memory */ +const char Gen_Error_str[] PROGMEM = "\r\nRequest error. Error code:\t"; +const char Dev_Header_str[] PROGMEM ="\r\nDevice descriptor: "; +const char Dev_Length_str[] PROGMEM ="\r\nDescriptor Length:\t"; +const char Dev_Type_str[] PROGMEM ="\r\nDescriptor type:\t"; +const char Dev_Version_str[] PROGMEM ="\r\nUSB version:\t\t"; +const char Dev_Class_str[] PROGMEM ="\r\nDevice class:\t\t"; +const char Dev_Subclass_str[] PROGMEM ="\r\nDevice Subclass:\t"; +const char Dev_Protocol_str[] PROGMEM ="\r\nDevice Protocol:\t"; +const char Dev_Pktsize_str[] PROGMEM ="\r\nMax.packet size:\t"; +const char Dev_Vendor_str[] PROGMEM ="\r\nVendor ID:\t\t"; +const char Dev_Product_str[] PROGMEM ="\r\nProduct ID:\t\t"; +const char Dev_Revision_str[] PROGMEM ="\r\nRevision ID:\t\t"; +const char Dev_Mfg_str[] PROGMEM ="\r\nMfg.string index:\t"; +const char Dev_Prod_str[] PROGMEM ="\r\nProd.string index:\t"; +const char Dev_Serial_str[] PROGMEM ="\r\nSerial number index:\t"; +const char Dev_Nconf_str[] PROGMEM ="\r\nNumber of conf.:\t"; +const char Conf_Trunc_str[] PROGMEM ="Total length truncated to 256 bytes"; +const char Conf_Header_str[] PROGMEM ="\r\nConfiguration descriptor:"; +const char Conf_Totlen_str[] PROGMEM ="\r\nTotal length:\t\t"; +const char Conf_Nint_str[] PROGMEM ="\r\nNum.intf:\t\t"; +const char Conf_Value_str[] PROGMEM ="\r\nConf.value:\t\t"; +const char Conf_String_str[] PROGMEM ="\r\nConf.string:\t\t"; +const char Conf_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t"; +const char Conf_Pwr_str[] PROGMEM ="\r\nMax.pwr:\t\t"; +const char Int_Header_str[] PROGMEM ="\r\n\r\nInterface descriptor:"; +const char Int_Number_str[] PROGMEM ="\r\nIntf.number:\t\t"; +const char Int_Alt_str[] PROGMEM ="\r\nAlt.:\t\t\t"; +const char Int_Endpoints_str[] PROGMEM ="\r\nEndpoints:\t\t"; +const char Int_Class_str[] PROGMEM ="\r\nIntf. Class:\t\t"; +const char Int_Subclass_str[] PROGMEM ="\r\nIntf. Subclass:\t\t"; +const char Int_Protocol_str[] PROGMEM ="\r\nIntf. Protocol:\t\t"; +const char Int_String_str[] PROGMEM ="\r\nIntf.string:\t\t"; +const char End_Header_str[] PROGMEM ="\r\n\r\nEndpoint descriptor:"; +const char End_Address_str[] PROGMEM ="\r\nEndpoint address:\t"; +const char End_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t"; +const char End_Pktsize_str[] PROGMEM ="\r\nMax.pkt size:\t\t"; +const char End_Interval_str[] PROGMEM ="\r\nPolling interval:\t"; +const char Unk_Header_str[] PROGMEM = "\r\nUnknown descriptor:"; +const char Unk_Length_str[] PROGMEM ="\r\nLength:\t\t"; +const char Unk_Type_str[] PROGMEM ="\r\nType:\t\t"; +const char Unk_Contents_str[] PROGMEM ="\r\nContents:\t"; + +#endif // __PGMSTRINGS_H__ \ No newline at end of file diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp.ino new file mode 100644 index 0000000000..837d7f5a70 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp.ino @@ -0,0 +1,42 @@ +/* Simplified Logitech Extreme 3D Pro Joystick Report Parser */ + +#include +#include +#include + +#include "le3dp_rptparser.h" + +// Satisfy the IDE, which needs to see the include statment in the ino too. +#ifdef dobogusinclude +#include +#include +#endif + +USB Usb; +USBHub Hub(&Usb); +HIDUniversal Hid(&Usb); +JoystickEvents JoyEvents; +JoystickReportParser Joy(&JoyEvents); + +void setup() +{ + Serial.begin( 115200 ); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + Serial.println("Start"); + + if (Usb.Init() == -1) + Serial.println("OSC did not start."); + + delay( 200 ); + + if (!Hid.SetReportParser(0, &Joy)) + ErrorMessage(PSTR("SetReportParser"), 1 ); +} + +void loop() +{ + Usb.Task(); +} + diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp_rptparser.cpp b/lib/usbhost/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp_rptparser.cpp new file mode 100644 index 0000000000..baece13b2c --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp_rptparser.cpp @@ -0,0 +1,43 @@ +#include "le3dp_rptparser.h" + +JoystickReportParser::JoystickReportParser(JoystickEvents *evt) : + joyEvents(evt) +{} + +void JoystickReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) +{ + bool match = true; + + // Checking if there are changes in report since the method was last called + for (uint8_t i=0; iOnGamePadChanged((const GamePadEventData*)buf); + + for (uint8_t i=0; i(evt->x, 0x80); + Serial.print(" Y: "); + PrintHex(evt->y, 0x80); + Serial.print(" Hat Switch: "); + PrintHex(evt->hat, 0x80); + Serial.print(" Twist: "); + PrintHex(evt->twist, 0x80); + Serial.print(" Slider: "); + PrintHex(evt->slider, 0x80); + Serial.print(" Buttons A: "); + PrintHex(evt->buttons_a, 0x80); + Serial.print(" Buttons B: "); + PrintHex(evt->buttons_b, 0x80); + Serial.println(""); +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp_rptparser.h b/lib/usbhost/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp_rptparser.h new file mode 100644 index 0000000000..2400364e65 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp_rptparser.h @@ -0,0 +1,42 @@ +#if !defined(__HIDJOYSTICKRPTPARSER_H__) +#define __HIDJOYSTICKRPTPARSER_H__ + +#include + +struct GamePadEventData +{ + union { //axes and hut switch + uint32_t axes; + struct { + uint32_t x : 10; + uint32_t y : 10; + uint32_t hat : 4; + uint32_t twist : 8; + }; + }; + uint8_t buttons_a; + uint8_t slider; + uint8_t buttons_b; +}; + +class JoystickEvents +{ +public: + virtual void OnGamePadChanged(const GamePadEventData *evt); +}; + +#define RPT_GAMEPAD_LEN sizeof(GamePadEventData)/sizeof(uint8_t) + +class JoystickReportParser : public HIDReportParser +{ + JoystickEvents *joyEvents; + + uint8_t oldPad[RPT_GAMEPAD_LEN]; + +public: + JoystickReportParser(JoystickEvents *evt); + + virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); +}; + +#endif // __HIDJOYSTICKRPTPARSER_H__ diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/HID/scale/scale.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/HID/scale/scale.ino new file mode 100644 index 0000000000..f26ff964da --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/HID/scale/scale.ino @@ -0,0 +1,51 @@ +/* Digital Scale Output. Written for Stamps.com Model 510 */ +/* 5lb Digital Scale; any HID scale with Usage page 0x8d should work */ + +#include +#include +#include + +#include "scale_rptparser.h" + +// Satisfy the IDE, which needs to see the include statment in the ino too. +#ifdef dobogusinclude +#include +#include +#endif + +USB Usb; +USBHub Hub(&Usb); +HIDUniversal Hid(&Usb); +Max_LCD LCD(&Usb); +ScaleEvents ScaleEvents(&LCD); +ScaleReportParser Scale(&ScaleEvents); + +void setup() +{ + Serial.begin( 115200 ); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + Serial.println("Start"); + + if (Usb.Init() == -1) + Serial.println("OSC did not start."); + + // set up the LCD's number of rows and columns: + LCD.begin(16, 2); + LCD.clear(); + LCD.home(); + LCD.setCursor(0,0); + LCD.write('R'); + + delay( 200 ); + + if (!Hid.SetReportParser(0, &Scale)) + ErrorMessage(PSTR("SetReportParser"), 1 ); +} + +void loop() +{ + Usb.Task(); +} + diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/HID/scale/scale_rptparser.cpp b/lib/usbhost/USB_Host_Shield_2.0/examples/HID/scale/scale_rptparser.cpp new file mode 100644 index 0000000000..01ed980cfb --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/HID/scale/scale_rptparser.cpp @@ -0,0 +1,150 @@ +/* Parser for standard HID scale (usage page 0x8d) data input report (ID 3) */ +#include "scale_rptparser.h" + +const char* UNITS[13] = { + "units", // unknown unit + "mg", // milligram + "g", // gram + "kg", // kilogram + "cd", // carat + "taels", // lian + "gr", // grain + "dwt", // pennyweight + "tonnes", // metric tons + "tons", // avoir ton + "ozt", // troy ounce + "oz", // ounce + "lbs" // pound +}; + +ScaleReportParser::ScaleReportParser(ScaleEvents *evt) : + scaleEvents(evt) +{} + +void ScaleReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) +{ + bool match = true; + + // Checking if there are changes in report since the method was last called + for (uint8_t i=0; iOnScaleChanged((const ScaleEventData*)buf); + + for (uint8_t i=0; iwrite( *str++ ); + + } +} + +void ScaleEvents::OnScaleChanged(const ScaleEventData *evt) +{ + + pLcd->clear(); + pLcd->home(); + pLcd->setCursor(0,0); + + if( evt->reportID != 3 ) { + + const char inv_report[]="Invalid report!"; + + Serial.println(inv_report); + LcdPrint(inv_report); + + return; + + }//if( evt->reportID != 3... + + switch( evt->status ) { + + case REPORT_FAULT: + Serial.println(F("Report fault")); + break; + + case ZEROED: + Serial.println(F("Scale zero set")); + break; + + case WEIGHING: { + + const char progress[] = "Weighing..."; + Serial.println(progress); + LcdPrint(progress); + break; + } + + case WEIGHT_VALID: { + + char buf[10]; + double weight = evt->weight * pow( 10, evt->exp ); + + + + Serial.print(F("Weight: ")); + Serial.print( weight ); + Serial.print(F(" ")); + Serial.println( UNITS[ evt->unit ]); + + LcdPrint("Weight: "); + dtostrf( weight, 4, 2, buf ); + LcdPrint( buf ); + LcdPrint( UNITS[ evt->unit ]); + + break; + + }//case WEIGHT_VALID... + + case WEIGHT_NEGATIVE: { + + const char negweight[] = "Negative weight"; + Serial.println(negweight); + LcdPrint(negweight); + break; + } + + case OVERWEIGHT: { + + const char overweight[] = "Max.weight reached"; + Serial.println(overweight); + LcdPrint( overweight ); + break; + } + + case CALIBRATE_ME: + + Serial.println(F("Scale calibration required")); + break; + + case ZERO_ME: + + Serial.println(F("Scale zeroing required")); + break; + + default: + + Serial.print(F("Undefined status code: ")); + Serial.println( evt->status ); + break; + + }//switch( evt->status... + +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/HID/scale/scale_rptparser.h b/lib/usbhost/USB_Host_Shield_2.0/examples/HID/scale/scale_rptparser.h new file mode 100644 index 0000000000..57fbb033bf --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/HID/scale/scale_rptparser.h @@ -0,0 +1,55 @@ +#if !defined(__SCALERPTPARSER_H__) +#define __SCALERPTPARSER_H__ + +#include +#include + +/* Scale status constants */ +#define REPORT_FAULT 0x01 +#define ZEROED 0x02 +#define WEIGHING 0x03 +#define WEIGHT_VALID 0x04 +#define WEIGHT_NEGATIVE 0x05 +#define OVERWEIGHT 0x06 +#define CALIBRATE_ME 0x07 +#define ZERO_ME 0x08 + +/* input data report */ +struct ScaleEventData +{ + uint8_t reportID; //must be 3 + uint8_t status; + uint8_t unit; + int8_t exp; //scale factor for the weight + uint16_t weight; // +}; + +class ScaleEvents +{ + + Max_LCD* pLcd; + + void LcdPrint( const char* str ); + +public: + + ScaleEvents( Max_LCD* pLCD ); + + virtual void OnScaleChanged(const ScaleEventData *evt); +}; + +#define RPT_SCALE_LEN sizeof(ScaleEventData)/sizeof(uint8_t) + +class ScaleReportParser : public HIDReportParser +{ + ScaleEvents *scaleEvents; + + uint8_t oldScale[RPT_SCALE_LEN]; + +public: + ScaleReportParser(ScaleEvents *evt); + + virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); +}; + +#endif // __SCALERPTPARSER_H__ diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/PS3USB/PS3USB.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/PS3USB/PS3USB.ino new file mode 100644 index 0000000000..a53dcfbe61 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/PS3USB/PS3USB.ino @@ -0,0 +1,148 @@ +/* + Example sketch for the PS3 USB library - developed by Kristian Lauszus + For more information visit my blog: http://blog.tkjelectronics.dk/ or + send me an e-mail: kristianl@tkjelectronics.com + */ + +#include + +// Satisfy the IDE, which needs to see the include statment in the ino too. +#ifdef dobogusinclude +#include +#include +#endif + +USB Usb; +/* You can create the instance of the class in two ways */ +PS3USB PS3(&Usb); // This will just create the instance +//PS3USB PS3(&Usb,0x00,0x15,0x83,0x3D,0x0A,0x57); // This will also store the bluetooth address - this can be obtained from the dongle when running the sketch + +bool printAngle; +uint8_t state = 0; + +void setup() { + Serial.begin(115200); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + if (Usb.Init() == -1) { + Serial.print(F("\r\nOSC did not start")); + while (1); //halt + } + Serial.print(F("\r\nPS3 USB Library Started")); +} +void loop() { + Usb.Task(); + + if (PS3.PS3Connected || PS3.PS3NavigationConnected) { + if (PS3.getAnalogHat(LeftHatX) > 137 || PS3.getAnalogHat(LeftHatX) < 117 || PS3.getAnalogHat(LeftHatY) > 137 || PS3.getAnalogHat(LeftHatY) < 117 || PS3.getAnalogHat(RightHatX) > 137 || PS3.getAnalogHat(RightHatX) < 117 || PS3.getAnalogHat(RightHatY) > 137 || PS3.getAnalogHat(RightHatY) < 117) { + Serial.print(F("\r\nLeftHatX: ")); + Serial.print(PS3.getAnalogHat(LeftHatX)); + Serial.print(F("\tLeftHatY: ")); + Serial.print(PS3.getAnalogHat(LeftHatY)); + if (PS3.PS3Connected) { // The Navigation controller only have one joystick + Serial.print(F("\tRightHatX: ")); + Serial.print(PS3.getAnalogHat(RightHatX)); + Serial.print(F("\tRightHatY: ")); + Serial.print(PS3.getAnalogHat(RightHatY)); + } + } + // Analog button values can be read from almost all buttons + if (PS3.getAnalogButton(L2) || PS3.getAnalogButton(R2)) { + Serial.print(F("\r\nL2: ")); + Serial.print(PS3.getAnalogButton(L2)); + if (!PS3.PS3NavigationConnected) { + Serial.print(F("\tR2: ")); + Serial.print(PS3.getAnalogButton(R2)); + } + } + if (PS3.getButtonClick(PS)) + Serial.print(F("\r\nPS")); + + if (PS3.getButtonClick(TRIANGLE)) + Serial.print(F("\r\nTraingle")); + if (PS3.getButtonClick(CIRCLE)) + Serial.print(F("\r\nCircle")); + if (PS3.getButtonClick(CROSS)) + Serial.print(F("\r\nCross")); + if (PS3.getButtonClick(SQUARE)) + Serial.print(F("\r\nSquare")); + + if (PS3.getButtonClick(UP)) { + Serial.print(F("\r\nUp")); + PS3.setLedOff(); + PS3.setLedOn(LED4); + } + if (PS3.getButtonClick(RIGHT)) { + Serial.print(F("\r\nRight")); + PS3.setLedOff(); + PS3.setLedOn(LED1); + } + if (PS3.getButtonClick(DOWN)) { + Serial.print(F("\r\nDown")); + PS3.setLedOff(); + PS3.setLedOn(LED2); + } + if (PS3.getButtonClick(LEFT)) { + Serial.print(F("\r\nLeft")); + PS3.setLedOff(); + PS3.setLedOn(LED3); + } + + if (PS3.getButtonClick(L1)) + Serial.print(F("\r\nL1")); + if (PS3.getButtonClick(L3)) + Serial.print(F("\r\nL3")); + if (PS3.getButtonClick(R1)) + Serial.print(F("\r\nR1")); + if (PS3.getButtonClick(R3)) + Serial.print(F("\r\nR3")); + + if (PS3.getButtonClick(SELECT)) { + Serial.print(F("\r\nSelect - ")); + PS3.printStatusString(); + } + if (PS3.getButtonClick(START)) { + Serial.print(F("\r\nStart")); + printAngle = !printAngle; + } + if (printAngle) { + Serial.print(F("\r\nPitch: ")); + Serial.print(PS3.getAngle(Pitch)); + Serial.print(F("\tRoll: ")); + Serial.print(PS3.getAngle(Roll)); + } + } + else if (PS3.PS3MoveConnected) { // One can only set the color of the bulb, set the rumble, set and get the bluetooth address and calibrate the magnetometer via USB + if (state == 0) { + PS3.moveSetRumble(0); + PS3.moveSetBulb(Off); + } else if (state == 1) { + PS3.moveSetRumble(75); + PS3.moveSetBulb(Red); + } else if (state == 2) { + PS3.moveSetRumble(125); + PS3.moveSetBulb(Green); + } else if (state == 3) { + PS3.moveSetRumble(150); + PS3.moveSetBulb(Blue); + } else if (state == 4) { + PS3.moveSetRumble(175); + PS3.moveSetBulb(Yellow); + } else if (state == 5) { + PS3.moveSetRumble(200); + PS3.moveSetBulb(Lightblue); + } else if (state == 6) { + PS3.moveSetRumble(225); + PS3.moveSetBulb(Purble); + } else if (state == 7) { + PS3.moveSetRumble(250); + PS3.moveSetBulb(White); + } + + state++; + if (state > 7) + state = 0; + delay(1000); + } +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/PS4USB/PS4USB.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/PS4USB/PS4USB.ino new file mode 100644 index 0000000000..d0d76790ec --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/PS4USB/PS4USB.ino @@ -0,0 +1,133 @@ +/* + Example sketch for the PS4 USB library - developed by Kristian Lauszus + For more information visit my blog: http://blog.tkjelectronics.dk/ or + send me an e-mail: kristianl@tkjelectronics.com + */ + +#include + +// Satisfy the IDE, which needs to see the include statment in the ino too. +#ifdef dobogusinclude +#include +#include +#endif + +USB Usb; +PS4USB PS4(&Usb); + +bool printAngle, printTouch; +uint8_t oldL2Value, oldR2Value; + +void setup() { + Serial.begin(115200); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + if (Usb.Init() == -1) { + Serial.print(F("\r\nOSC did not start")); + while (1); // Halt + } + Serial.print(F("\r\nPS4 USB Library Started")); +} + +void loop() { + Usb.Task(); + + if (PS4.connected()) { + if (PS4.getAnalogHat(LeftHatX) > 137 || PS4.getAnalogHat(LeftHatX) < 117 || PS4.getAnalogHat(LeftHatY) > 137 || PS4.getAnalogHat(LeftHatY) < 117 || PS4.getAnalogHat(RightHatX) > 137 || PS4.getAnalogHat(RightHatX) < 117 || PS4.getAnalogHat(RightHatY) > 137 || PS4.getAnalogHat(RightHatY) < 117) { + Serial.print(F("\r\nLeftHatX: ")); + Serial.print(PS4.getAnalogHat(LeftHatX)); + Serial.print(F("\tLeftHatY: ")); + Serial.print(PS4.getAnalogHat(LeftHatY)); + Serial.print(F("\tRightHatX: ")); + Serial.print(PS4.getAnalogHat(RightHatX)); + Serial.print(F("\tRightHatY: ")); + Serial.print(PS4.getAnalogHat(RightHatY)); + } + + if (PS4.getAnalogButton(L2) || PS4.getAnalogButton(R2)) { // These are the only analog buttons on the PS4 controller + Serial.print(F("\r\nL2: ")); + Serial.print(PS4.getAnalogButton(L2)); + Serial.print(F("\tR2: ")); + Serial.print(PS4.getAnalogButton(R2)); + } + if (PS4.getAnalogButton(L2) != oldL2Value || PS4.getAnalogButton(R2) != oldR2Value) // Only write value if it's different + PS4.setRumbleOn(PS4.getAnalogButton(L2), PS4.getAnalogButton(R2)); + oldL2Value = PS4.getAnalogButton(L2); + oldR2Value = PS4.getAnalogButton(R2); + + if (PS4.getButtonClick(PS)) + Serial.print(F("\r\nPS")); + if (PS4.getButtonClick(TRIANGLE)) { + Serial.print(F("\r\nTraingle")); + PS4.setRumbleOn(RumbleLow); + } + if (PS4.getButtonClick(CIRCLE)) { + Serial.print(F("\r\nCircle")); + PS4.setRumbleOn(RumbleHigh); + } + if (PS4.getButtonClick(CROSS)) { + Serial.print(F("\r\nCross")); + PS4.setLedFlash(10, 10); // Set it to blink rapidly + } + if (PS4.getButtonClick(SQUARE)) { + Serial.print(F("\r\nSquare")); + PS4.setLedFlash(0, 0); // Turn off blinking + } + + if (PS4.getButtonClick(UP)) { + Serial.print(F("\r\nUp")); + PS4.setLed(Red); + } if (PS4.getButtonClick(RIGHT)) { + Serial.print(F("\r\nRight")); + PS4.setLed(Blue); + } if (PS4.getButtonClick(DOWN)) { + Serial.print(F("\r\nDown")); + PS4.setLed(Yellow); + } if (PS4.getButtonClick(LEFT)) { + Serial.print(F("\r\nLeft")); + PS4.setLed(Green); + } + + if (PS4.getButtonClick(L1)) + Serial.print(F("\r\nL1")); + if (PS4.getButtonClick(L3)) + Serial.print(F("\r\nL3")); + if (PS4.getButtonClick(R1)) + Serial.print(F("\r\nR1")); + if (PS4.getButtonClick(R3)) + Serial.print(F("\r\nR3")); + + if (PS4.getButtonClick(SHARE)) + Serial.print(F("\r\nShare")); + if (PS4.getButtonClick(OPTIONS)) { + Serial.print(F("\r\nOptions")); + printAngle = !printAngle; + } + if (PS4.getButtonClick(TOUCHPAD)) { + Serial.print(F("\r\nTouchpad")); + printTouch = !printTouch; + } + + if (printAngle) { // Print angle calculated using the accelerometer only + Serial.print(F("\r\nPitch: ")); + Serial.print(PS4.getAngle(Pitch)); + Serial.print(F("\tRoll: ")); + Serial.print(PS4.getAngle(Roll)); + } + + if (printTouch) { // Print the x, y coordinates of the touchpad + if (PS4.isTouching(0) || PS4.isTouching(1)) // Print newline and carriage return if any of the fingers are touching the touchpad + Serial.print(F("\r\n")); + for (uint8_t i = 0; i < 2; i++) { // The touchpad track two fingers + if (PS4.isTouching(i)) { // Print the position of the finger if it is touching the touchpad + Serial.print(F("X")); Serial.print(i + 1); Serial.print(F(": ")); + Serial.print(PS4.getX(i)); + Serial.print(F("\tY")); Serial.print(i + 1); Serial.print(F(": ")); + Serial.print(PS4.getY(i)); + Serial.print(F("\t")); + } + } + } + } +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/PSBuzz/PSBuzz.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/PSBuzz/PSBuzz.ino new file mode 100644 index 0000000000..6ee462c1eb --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/PSBuzz/PSBuzz.ino @@ -0,0 +1,49 @@ +/* + Example sketch for the Playstation Buzz library - developed by Kristian Lauszus + For more information visit my blog: http://blog.tkjelectronics.dk/ or + send me an e-mail: kristianl@tkjelectronics.com + */ + +#include + +// Satisfy the IDE, which needs to see the include statment in the ino too. +#ifdef dobogusinclude +#include +#include +#endif + +USB Usb; +PSBuzz Buzz(&Usb); + +void setup() { + Serial.begin(115200); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + if (Usb.Init() == -1) { + Serial.print(F("\r\nOSC did not start")); + while (1); // Halt + } + Serial.println(F("\r\nPS Buzz Library Started")); +} + +void loop() { + Usb.Task(); + + if (Buzz.connected()) { + for (uint8_t i = 0; i < 4; i++) { + if (Buzz.getButtonClick(RED, i)) { + Buzz.setLedToggle(i); // Toggle the LED + Serial.println(F("RED")); + } + if (Buzz.getButtonClick(YELLOW, i)) + Serial.println(F("YELLOW")); + if (Buzz.getButtonClick(GREEN, i)) + Serial.println(F("GREEN")); + if (Buzz.getButtonClick(ORANGE, i)) + Serial.println(F("ORANGE")); + if (Buzz.getButtonClick(BLUE, i)) + Serial.println(F("BLUE")); + } + } +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/USB_desc/USB_desc.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/USB_desc/USB_desc.ino new file mode 100644 index 0000000000..acfe57d374 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/USB_desc/USB_desc.ino @@ -0,0 +1,349 @@ +#include + +#include "pgmstrings.h" + +// Satisfy the IDE, which needs to see the include statment in the ino too. +#ifdef dobogusinclude +#include +#include +#endif + +USB Usb; +//USBHub Hub1(&Usb); +//USBHub Hub2(&Usb); +//USBHub Hub3(&Usb); +//USBHub Hub4(&Usb); +//USBHub Hub5(&Usb); +//USBHub Hub6(&Usb); +//USBHub Hub7(&Usb); + +uint32_t next_time; + +void PrintAllAddresses(UsbDevice *pdev) +{ + UsbDeviceAddress adr; + adr.devAddress = pdev->address.devAddress; + Serial.print("\r\nAddr:"); + Serial.print(adr.devAddress, HEX); + Serial.print("("); + Serial.print(adr.bmHub, HEX); + Serial.print("."); + Serial.print(adr.bmParent, HEX); + Serial.print("."); + Serial.print(adr.bmAddress, HEX); + Serial.println(")"); +} + +void PrintAddress(uint8_t addr) +{ + UsbDeviceAddress adr; + adr.devAddress = addr; + Serial.print("\r\nADDR:\t"); + Serial.println(adr.devAddress, HEX); + Serial.print("DEV:\t"); + Serial.println(adr.bmAddress, HEX); + Serial.print("PRNT:\t"); + Serial.println(adr.bmParent, HEX); + Serial.print("HUB:\t"); + Serial.println(adr.bmHub, HEX); +} + +void setup() +{ + Serial.begin( 115200 ); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + Serial.println("Start"); + + if (Usb.Init() == -1) + Serial.println("OSC did not start."); + + delay( 200 ); + + next_time = millis() + 10000; +} + +byte getdevdescr( byte addr, byte &num_conf ); + +void PrintDescriptors(uint8_t addr) +{ + uint8_t rcode = 0; + byte num_conf = 0; + + rcode = getdevdescr( (byte)addr, num_conf ); + if ( rcode ) + { + printProgStr(Gen_Error_str); + print_hex( rcode, 8 ); + } + Serial.print("\r\n"); + + for (int i = 0; i < num_conf; i++) + { + rcode = getconfdescr( addr, i ); // get configuration descriptor + if ( rcode ) + { + printProgStr(Gen_Error_str); + print_hex(rcode, 8); + } + Serial.println("\r\n"); + } +} + +void PrintAllDescriptors(UsbDevice *pdev) +{ + Serial.println("\r\n"); + print_hex(pdev->address.devAddress, 8); + Serial.println("\r\n--"); + PrintDescriptors( pdev->address.devAddress ); +} + +void loop() +{ + Usb.Task(); + + if ( Usb.getUsbTaskState() == USB_STATE_RUNNING ) + { + //if (millis() >= next_time) + { + Usb.ForEachUsbDevice(&PrintAllDescriptors); + Usb.ForEachUsbDevice(&PrintAllAddresses); + + while ( 1 ); //stop + } + } +} + +byte getdevdescr( byte addr, byte &num_conf ) +{ + USB_DEVICE_DESCRIPTOR buf; + byte rcode; + rcode = Usb.getDevDescr( addr, 0, 0x12, ( uint8_t *)&buf ); + if ( rcode ) { + return ( rcode ); + } + printProgStr(Dev_Header_str); + printProgStr(Dev_Length_str); + print_hex( buf.bLength, 8 ); + printProgStr(Dev_Type_str); + print_hex( buf.bDescriptorType, 8 ); + printProgStr(Dev_Version_str); + print_hex( buf.bcdUSB, 16 ); + printProgStr(Dev_Class_str); + print_hex( buf.bDeviceClass, 8 ); + printProgStr(Dev_Subclass_str); + print_hex( buf.bDeviceSubClass, 8 ); + printProgStr(Dev_Protocol_str); + print_hex( buf.bDeviceProtocol, 8 ); + printProgStr(Dev_Pktsize_str); + print_hex( buf.bMaxPacketSize0, 8 ); + printProgStr(Dev_Vendor_str); + print_hex( buf.idVendor, 16 ); + printProgStr(Dev_Product_str); + print_hex( buf.idProduct, 16 ); + printProgStr(Dev_Revision_str); + print_hex( buf.bcdDevice, 16 ); + printProgStr(Dev_Mfg_str); + print_hex( buf.iManufacturer, 8 ); + printProgStr(Dev_Prod_str); + print_hex( buf.iProduct, 8 ); + printProgStr(Dev_Serial_str); + print_hex( buf.iSerialNumber, 8 ); + printProgStr(Dev_Nconf_str); + print_hex( buf.bNumConfigurations, 8 ); + num_conf = buf.bNumConfigurations; + return ( 0 ); +} + +void printhubdescr(uint8_t *descrptr, uint8_t addr) +{ + HubDescriptor *pHub = (HubDescriptor*) descrptr; + uint8_t len = *((uint8_t*)descrptr); + + printProgStr(PSTR("\r\n\r\nHub Descriptor:\r\n")); + printProgStr(PSTR("bDescLength:\t\t")); + Serial.println(pHub->bDescLength, HEX); + + printProgStr(PSTR("bDescriptorType:\t")); + Serial.println(pHub->bDescriptorType, HEX); + + printProgStr(PSTR("bNbrPorts:\t\t")); + Serial.println(pHub->bNbrPorts, HEX); + + printProgStr(PSTR("LogPwrSwitchMode:\t")); + Serial.println(pHub->LogPwrSwitchMode, BIN); + + printProgStr(PSTR("CompoundDevice:\t\t")); + Serial.println(pHub->CompoundDevice, BIN); + + printProgStr(PSTR("OverCurrentProtectMode:\t")); + Serial.println(pHub->OverCurrentProtectMode, BIN); + + printProgStr(PSTR("TTThinkTime:\t\t")); + Serial.println(pHub->TTThinkTime, BIN); + + printProgStr(PSTR("PortIndicatorsSupported:")); + Serial.println(pHub->PortIndicatorsSupported, BIN); + + printProgStr(PSTR("Reserved:\t\t")); + Serial.println(pHub->Reserved, HEX); + + printProgStr(PSTR("bPwrOn2PwrGood:\t\t")); + Serial.println(pHub->bPwrOn2PwrGood, HEX); + + printProgStr(PSTR("bHubContrCurrent:\t")); + Serial.println(pHub->bHubContrCurrent, HEX); + + for (uint8_t i = 7; i < len; i++) + print_hex(descrptr[i], 8); + + //for (uint8_t i=1; i<=pHub->bNbrPorts; i++) + // PrintHubPortStatus(&Usb, addr, i, 1); +} + +byte getconfdescr( byte addr, byte conf ) +{ + uint8_t buf[ BUFSIZE ]; + uint8_t* buf_ptr = buf; + byte rcode; + byte descr_length; + byte descr_type; + unsigned int total_length; + rcode = Usb.getConfDescr( addr, 0, 4, conf, buf ); //get total length + LOBYTE( total_length ) = buf[ 2 ]; + HIBYTE( total_length ) = buf[ 3 ]; + if ( total_length > 256 ) { //check if total length is larger than buffer + printProgStr(Conf_Trunc_str); + total_length = 256; + } + rcode = Usb.getConfDescr( addr, 0, total_length, conf, buf ); //get the whole descriptor + while ( buf_ptr < buf + total_length ) { //parsing descriptors + descr_length = *( buf_ptr ); + descr_type = *( buf_ptr + 1 ); + switch ( descr_type ) { + case ( USB_DESCRIPTOR_CONFIGURATION ): + printconfdescr( buf_ptr ); + break; + case ( USB_DESCRIPTOR_INTERFACE ): + printintfdescr( buf_ptr ); + break; + case ( USB_DESCRIPTOR_ENDPOINT ): + printepdescr( buf_ptr ); + break; + case 0x29: + printhubdescr( buf_ptr, addr ); + break; + default: + printunkdescr( buf_ptr ); + break; + }//switch( descr_type + buf_ptr = ( buf_ptr + descr_length ); //advance buffer pointer + }//while( buf_ptr <=... + return ( rcode ); +} +/* prints hex numbers with leading zeroes */ +// copyright, Peter H Anderson, Baltimore, MD, Nov, '07 +// source: http://www.phanderson.com/arduino/arduino_display.html +void print_hex(int v, int num_places) +{ + int mask = 0, n, num_nibbles, digit; + + for (n = 1; n <= num_places; n++) { + mask = (mask << 1) | 0x0001; + } + v = v & mask; // truncate v to specified number of places + + num_nibbles = num_places / 4; + if ((num_places % 4) != 0) { + ++num_nibbles; + } + do { + digit = ((v >> (num_nibbles - 1) * 4)) & 0x0f; + Serial.print(digit, HEX); + } + while (--num_nibbles); +} +/* function to print configuration descriptor */ +void printconfdescr( uint8_t* descr_ptr ) +{ + USB_CONFIGURATION_DESCRIPTOR* conf_ptr = ( USB_CONFIGURATION_DESCRIPTOR* )descr_ptr; + printProgStr(Conf_Header_str); + printProgStr(Conf_Totlen_str); + print_hex( conf_ptr->wTotalLength, 16 ); + printProgStr(Conf_Nint_str); + print_hex( conf_ptr->bNumInterfaces, 8 ); + printProgStr(Conf_Value_str); + print_hex( conf_ptr->bConfigurationValue, 8 ); + printProgStr(Conf_String_str); + print_hex( conf_ptr->iConfiguration, 8 ); + printProgStr(Conf_Attr_str); + print_hex( conf_ptr->bmAttributes, 8 ); + printProgStr(Conf_Pwr_str); + print_hex( conf_ptr->bMaxPower, 8 ); + return; +} +/* function to print interface descriptor */ +void printintfdescr( uint8_t* descr_ptr ) +{ + USB_INTERFACE_DESCRIPTOR* intf_ptr = ( USB_INTERFACE_DESCRIPTOR* )descr_ptr; + printProgStr(Int_Header_str); + printProgStr(Int_Number_str); + print_hex( intf_ptr->bInterfaceNumber, 8 ); + printProgStr(Int_Alt_str); + print_hex( intf_ptr->bAlternateSetting, 8 ); + printProgStr(Int_Endpoints_str); + print_hex( intf_ptr->bNumEndpoints, 8 ); + printProgStr(Int_Class_str); + print_hex( intf_ptr->bInterfaceClass, 8 ); + printProgStr(Int_Subclass_str); + print_hex( intf_ptr->bInterfaceSubClass, 8 ); + printProgStr(Int_Protocol_str); + print_hex( intf_ptr->bInterfaceProtocol, 8 ); + printProgStr(Int_String_str); + print_hex( intf_ptr->iInterface, 8 ); + return; +} +/* function to print endpoint descriptor */ +void printepdescr( uint8_t* descr_ptr ) +{ + USB_ENDPOINT_DESCRIPTOR* ep_ptr = ( USB_ENDPOINT_DESCRIPTOR* )descr_ptr; + printProgStr(End_Header_str); + printProgStr(End_Address_str); + print_hex( ep_ptr->bEndpointAddress, 8 ); + printProgStr(End_Attr_str); + print_hex( ep_ptr->bmAttributes, 8 ); + printProgStr(End_Pktsize_str); + print_hex( ep_ptr->wMaxPacketSize, 16 ); + printProgStr(End_Interval_str); + print_hex( ep_ptr->bInterval, 8 ); + + return; +} +/*function to print unknown descriptor */ +void printunkdescr( uint8_t* descr_ptr ) +{ + byte length = *descr_ptr; + byte i; + printProgStr(Unk_Header_str); + printProgStr(Unk_Length_str); + print_hex( *descr_ptr, 8 ); + printProgStr(Unk_Type_str); + print_hex( *(descr_ptr + 1 ), 8 ); + printProgStr(Unk_Contents_str); + descr_ptr += 2; + for ( i = 0; i < length; i++ ) { + print_hex( *descr_ptr, 8 ); + descr_ptr++; + } +} + + +/* Print a string from Program Memory directly to save RAM */ +void printProgStr(const char* str) +{ + char c; + if (!str) return; + while ((c = pgm_read_byte(str++))) + Serial.print(c); +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/USB_desc/pgmstrings.h b/lib/usbhost/USB_Host_Shield_2.0/examples/USB_desc/pgmstrings.h new file mode 100644 index 0000000000..bdb0077ecc --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/USB_desc/pgmstrings.h @@ -0,0 +1,52 @@ +#if !defined(__PGMSTRINGS_H__) +#define __PGMSTRINGS_H__ + +#define LOBYTE(x) ((char*)(&(x)))[0] +#define HIBYTE(x) ((char*)(&(x)))[1] +#define BUFSIZE 256 //buffer size + + +/* Print strings in Program Memory */ +const char Gen_Error_str[] PROGMEM = "\r\nRequest error. Error code:\t"; +const char Dev_Header_str[] PROGMEM ="\r\nDevice descriptor: "; +const char Dev_Length_str[] PROGMEM ="\r\nDescriptor Length:\t"; +const char Dev_Type_str[] PROGMEM ="\r\nDescriptor type:\t"; +const char Dev_Version_str[] PROGMEM ="\r\nUSB version:\t\t"; +const char Dev_Class_str[] PROGMEM ="\r\nDevice class:\t\t"; +const char Dev_Subclass_str[] PROGMEM ="\r\nDevice Subclass:\t"; +const char Dev_Protocol_str[] PROGMEM ="\r\nDevice Protocol:\t"; +const char Dev_Pktsize_str[] PROGMEM ="\r\nMax.packet size:\t"; +const char Dev_Vendor_str[] PROGMEM ="\r\nVendor ID:\t\t"; +const char Dev_Product_str[] PROGMEM ="\r\nProduct ID:\t\t"; +const char Dev_Revision_str[] PROGMEM ="\r\nRevision ID:\t\t"; +const char Dev_Mfg_str[] PROGMEM ="\r\nMfg.string index:\t"; +const char Dev_Prod_str[] PROGMEM ="\r\nProd.string index:\t"; +const char Dev_Serial_str[] PROGMEM ="\r\nSerial number index:\t"; +const char Dev_Nconf_str[] PROGMEM ="\r\nNumber of conf.:\t"; +const char Conf_Trunc_str[] PROGMEM ="Total length truncated to 256 bytes"; +const char Conf_Header_str[] PROGMEM ="\r\nConfiguration descriptor:"; +const char Conf_Totlen_str[] PROGMEM ="\r\nTotal length:\t\t"; +const char Conf_Nint_str[] PROGMEM ="\r\nNum.intf:\t\t"; +const char Conf_Value_str[] PROGMEM ="\r\nConf.value:\t\t"; +const char Conf_String_str[] PROGMEM ="\r\nConf.string:\t\t"; +const char Conf_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t"; +const char Conf_Pwr_str[] PROGMEM ="\r\nMax.pwr:\t\t"; +const char Int_Header_str[] PROGMEM ="\r\n\r\nInterface descriptor:"; +const char Int_Number_str[] PROGMEM ="\r\nIntf.number:\t\t"; +const char Int_Alt_str[] PROGMEM ="\r\nAlt.:\t\t\t"; +const char Int_Endpoints_str[] PROGMEM ="\r\nEndpoints:\t\t"; +const char Int_Class_str[] PROGMEM ="\r\nIntf. Class:\t\t"; +const char Int_Subclass_str[] PROGMEM ="\r\nIntf. Subclass:\t\t"; +const char Int_Protocol_str[] PROGMEM ="\r\nIntf. Protocol:\t\t"; +const char Int_String_str[] PROGMEM ="\r\nIntf.string:\t\t"; +const char End_Header_str[] PROGMEM ="\r\n\r\nEndpoint descriptor:"; +const char End_Address_str[] PROGMEM ="\r\nEndpoint address:\t"; +const char End_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t"; +const char End_Pktsize_str[] PROGMEM ="\r\nMax.pkt size:\t\t"; +const char End_Interval_str[] PROGMEM ="\r\nPolling interval:\t"; +const char Unk_Header_str[] PROGMEM = "\r\nUnknown descriptor:"; +const char Unk_Length_str[] PROGMEM ="\r\nLength:\t\t"; +const char Unk_Type_str[] PROGMEM ="\r\nType:\t\t"; +const char Unk_Contents_str[] PROGMEM ="\r\nContents:\t"; + +#endif // __PGMSTRINGS_H__ \ No newline at end of file diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/Xbox/XBOXOLD/XBOXOLD.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/Xbox/XBOXOLD/XBOXOLD.ino new file mode 100644 index 0000000000..64a3ed6120 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/Xbox/XBOXOLD/XBOXOLD.ino @@ -0,0 +1,110 @@ +/* + Example sketch for the original Xbox library - developed by Kristian Lauszus + For more information visit my blog: http://blog.tkjelectronics.dk/ or + send me an e-mail: kristianl@tkjelectronics.com + */ + +#include +#include + +// Satisfy the IDE, which needs to see the include statment in the ino too. +#ifdef dobogusinclude +#include +#include +#endif + +USB Usb; +USBHub Hub1(&Usb); // The controller has a built in hub, so this instance is needed +XBOXOLD Xbox(&Usb); + +void setup() { + Serial.begin(115200); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + if (Usb.Init() == -1) { + Serial.print(F("\r\nOSC did not start")); + while (1); // halt + } + Serial.print(F("\r\nXBOX Library Started")); +} +void loop() { + Usb.Task(); + if (Xbox.XboxConnected) { + if (Xbox.getButtonPress(BLACK) || Xbox.getButtonPress(WHITE)) { + Serial.print("BLACK: "); + Serial.print(Xbox.getButtonPress(BLACK)); + Serial.print("\tWHITE: "); + Serial.println(Xbox.getButtonPress(WHITE)); + Xbox.setRumbleOn(Xbox.getButtonPress(BLACK), Xbox.getButtonPress(WHITE)); + } else + Xbox.setRumbleOn(0, 0); + + if (Xbox.getAnalogHat(LeftHatX) > 7500 || Xbox.getAnalogHat(LeftHatX) < -7500 || Xbox.getAnalogHat(LeftHatY) > 7500 || Xbox.getAnalogHat(LeftHatY) < -7500 || Xbox.getAnalogHat(RightHatX) > 7500 || Xbox.getAnalogHat(RightHatX) < -7500 || Xbox.getAnalogHat(RightHatY) > 7500 || Xbox.getAnalogHat(RightHatY) < -7500) { + if (Xbox.getAnalogHat(LeftHatX) > 7500 || Xbox.getAnalogHat(LeftHatX) < -7500) { + Serial.print(F("LeftHatX: ")); + Serial.print(Xbox.getAnalogHat(LeftHatX)); + Serial.print("\t"); + } + if (Xbox.getAnalogHat(LeftHatY) > 7500 || Xbox.getAnalogHat(LeftHatY) < -7500) { + Serial.print(F("LeftHatY: ")); + Serial.print(Xbox.getAnalogHat(LeftHatY)); + Serial.print("\t"); + } + if (Xbox.getAnalogHat(RightHatX) > 7500 || Xbox.getAnalogHat(RightHatX) < -7500) { + Serial.print(F("RightHatX: ")); + Serial.print(Xbox.getAnalogHat(RightHatX)); + Serial.print("\t"); + } + if (Xbox.getAnalogHat(RightHatY) > 7500 || Xbox.getAnalogHat(RightHatY) < -7500) { + Serial.print(F("RightHatY: ")); + Serial.print(Xbox.getAnalogHat(RightHatY)); + } + Serial.println(); + } + + if (Xbox.getButtonClick(UP)) + Serial.println(F("Up")); + if (Xbox.getButtonClick(DOWN)) + Serial.println(F("Down")); + if (Xbox.getButtonClick(LEFT)) + Serial.println(F("Left")); + if (Xbox.getButtonClick(RIGHT)) + Serial.println(F("Right")); + + if (Xbox.getButtonClick(START)) + Serial.println(F("Start")); + if (Xbox.getButtonClick(BACK)) + Serial.println(F("Back")); + if (Xbox.getButtonClick(L3)) + Serial.println(F("L3")); + if (Xbox.getButtonClick(R3)) + Serial.println(F("R3")); + + if (Xbox.getButtonPress(A)) { + Serial.print(F("A: ")); + Serial.println(Xbox.getButtonPress(A)); + } + if (Xbox.getButtonPress(B)) { + Serial.print(F("B: ")); + Serial.println(Xbox.getButtonPress(B)); + } + if (Xbox.getButtonPress(X)) { + Serial.print(F("X: ")); + Serial.println(Xbox.getButtonPress(X)); + } + if (Xbox.getButtonPress(Y)) { + Serial.print(F("Y: ")); + Serial.println(Xbox.getButtonPress(Y)); + } + if (Xbox.getButtonPress(L1)) { + Serial.print(F("L1: ")); + Serial.println(Xbox.getButtonPress(L1)); + } + if (Xbox.getButtonPress(R1)) { + Serial.print(F("R1: ")); + Serial.println(Xbox.getButtonPress(R1)); + } + } + delay(1); +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/Xbox/XBOXONE/XBOXONE.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/Xbox/XBOXONE/XBOXONE.ino new file mode 100644 index 0000000000..9526f53d19 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/Xbox/XBOXONE/XBOXONE.ino @@ -0,0 +1,106 @@ +/* + Example sketch for the Xbox ONE USB library - by guruthree, based on work by + Kristian Lauszus. + */ + +#include +// Satisfy IDE, which only needs to see the include statment in the ino. +#ifdef dobogusinclude +#include +#endif + +USB Usb; +XBOXONE Xbox(&Usb); + +void setup() { + Serial.begin(115200); + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection + if (Usb.Init() == -1) { + Serial.print(F("\r\nOSC did not start")); + while (1); //halt + } + Serial.print(F("\r\nXBOX USB Library Started")); +} +void loop() { + Usb.Task(); + if (Xbox.XboxOneConnected) { + if (Xbox.getAnalogHat(LeftHatX) > 7500 || Xbox.getAnalogHat(LeftHatX) < -7500 || Xbox.getAnalogHat(LeftHatY) > 7500 || Xbox.getAnalogHat(LeftHatY) < -7500 || Xbox.getAnalogHat(RightHatX) > 7500 || Xbox.getAnalogHat(RightHatX) < -7500 || Xbox.getAnalogHat(RightHatY) > 7500 || Xbox.getAnalogHat(RightHatY) < -7500) { + if (Xbox.getAnalogHat(LeftHatX) > 7500 || Xbox.getAnalogHat(LeftHatX) < -7500) { + Serial.print(F("LeftHatX: ")); + Serial.print(Xbox.getAnalogHat(LeftHatX)); + Serial.print("\t"); + } + if (Xbox.getAnalogHat(LeftHatY) > 7500 || Xbox.getAnalogHat(LeftHatY) < -7500) { + Serial.print(F("LeftHatY: ")); + Serial.print(Xbox.getAnalogHat(LeftHatY)); + Serial.print("\t"); + } + if (Xbox.getAnalogHat(RightHatX) > 7500 || Xbox.getAnalogHat(RightHatX) < -7500) { + Serial.print(F("RightHatX: ")); + Serial.print(Xbox.getAnalogHat(RightHatX)); + Serial.print("\t"); + } + if (Xbox.getAnalogHat(RightHatY) > 7500 || Xbox.getAnalogHat(RightHatY) < -7500) { + Serial.print(F("RightHatY: ")); + Serial.print(Xbox.getAnalogHat(RightHatY)); + } + Serial.println(); + } + + if (Xbox.getButtonPress(L2) > 0 || Xbox.getButtonPress(R2) > 0) { + if (Xbox.getButtonPress(L2) > 0) { + Serial.print(F("L2: ")); + Serial.print(Xbox.getButtonPress(L2)); + Serial.print("\t"); + } + if (Xbox.getButtonPress(R2) > 0) { + Serial.print(F("R2: ")); + Serial.print(Xbox.getButtonPress(R2)); + Serial.print("\t"); + } + Serial.println(); + } + + if (Xbox.getButtonClick(UP)) + Serial.println(F("Up")); + if (Xbox.getButtonClick(DOWN)) + Serial.println(F("Down")); + if (Xbox.getButtonClick(LEFT)) + Serial.println(F("Left")); + if (Xbox.getButtonClick(RIGHT)) + Serial.println(F("Right")); + + if (Xbox.getButtonClick(START)) + Serial.println(F("Start")); + if (Xbox.getButtonClick(BACK)) + Serial.println(F("Back")); + if (Xbox.getButtonClick(XBOX)) + Serial.println(F("Xbox")); + if (Xbox.getButtonClick(SYNC)) + Serial.println(F("Sync")); + + if (Xbox.getButtonClick(L1)) + Serial.println(F("L1")); + if (Xbox.getButtonClick(R1)) + Serial.println(F("R1")); + if (Xbox.getButtonClick(L2)) + Serial.println(F("L2")); + if (Xbox.getButtonClick(R2)) + Serial.println(F("R2")); + if (Xbox.getButtonClick(L3)) + Serial.println(F("L3")); + if (Xbox.getButtonClick(R3)) + Serial.println(F("R3")); + + + if (Xbox.getButtonClick(A)) + Serial.println(F("A")); + if (Xbox.getButtonClick(B)) + Serial.println(F("B")); + if (Xbox.getButtonClick(X)) + Serial.println(F("X")); + if (Xbox.getButtonClick(Y)) + Serial.println(F("Y")); + } + delay(1); +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/Xbox/XBOXRECV/XBOXRECV.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/Xbox/XBOXRECV/XBOXRECV.ino new file mode 100644 index 0000000000..491b287e44 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/Xbox/XBOXRECV/XBOXRECV.ino @@ -0,0 +1,122 @@ +/* + Example sketch for the Xbox Wireless Reciver library - developed by Kristian Lauszus + It supports up to four controllers wirelessly + For more information see the blog post: http://blog.tkjelectronics.dk/2012/12/xbox-360-receiver-added-to-the-usb-host-library/ or + send me an e-mail: kristianl@tkjelectronics.com + */ + +#include + +// Satisfy the IDE, which needs to see the include statment in the ino too. +#ifdef dobogusinclude +#include +#include +#endif + +USB Usb; +XBOXRECV Xbox(&Usb); + +void setup() { + Serial.begin(115200); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + if (Usb.Init() == -1) { + Serial.print(F("\r\nOSC did not start")); + while (1); //halt + } + Serial.print(F("\r\nXbox Wireless Receiver Library Started")); +} +void loop() { + Usb.Task(); + if (Xbox.XboxReceiverConnected) { + for (uint8_t i = 0; i < 4; i++) { + if (Xbox.Xbox360Connected[i]) { + if (Xbox.getButtonPress(L2, i) || Xbox.getButtonPress(R2, i)) { + Serial.print("L2: "); + Serial.print(Xbox.getButtonPress(L2, i)); + Serial.print("\tR2: "); + Serial.println(Xbox.getButtonPress(R2, i)); + Xbox.setRumbleOn(Xbox.getButtonPress(L2, i), Xbox.getButtonPress(R2, i), i); + } + + if (Xbox.getAnalogHat(LeftHatX, i) > 7500 || Xbox.getAnalogHat(LeftHatX, i) < -7500 || Xbox.getAnalogHat(LeftHatY, i) > 7500 || Xbox.getAnalogHat(LeftHatY, i) < -7500 || Xbox.getAnalogHat(RightHatX, i) > 7500 || Xbox.getAnalogHat(RightHatX, i) < -7500 || Xbox.getAnalogHat(RightHatY, i) > 7500 || Xbox.getAnalogHat(RightHatY, i) < -7500) { + if (Xbox.getAnalogHat(LeftHatX, i) > 7500 || Xbox.getAnalogHat(LeftHatX, i) < -7500) { + Serial.print(F("LeftHatX: ")); + Serial.print(Xbox.getAnalogHat(LeftHatX, i)); + Serial.print("\t"); + } + if (Xbox.getAnalogHat(LeftHatY, i) > 7500 || Xbox.getAnalogHat(LeftHatY, i) < -7500) { + Serial.print(F("LeftHatY: ")); + Serial.print(Xbox.getAnalogHat(LeftHatY, i)); + Serial.print("\t"); + } + if (Xbox.getAnalogHat(RightHatX, i) > 7500 || Xbox.getAnalogHat(RightHatX, i) < -7500) { + Serial.print(F("RightHatX: ")); + Serial.print(Xbox.getAnalogHat(RightHatX, i)); + Serial.print("\t"); + } + if (Xbox.getAnalogHat(RightHatY, i) > 7500 || Xbox.getAnalogHat(RightHatY, i) < -7500) { + Serial.print(F("RightHatY: ")); + Serial.print(Xbox.getAnalogHat(RightHatY, i)); + } + Serial.println(); + } + + if (Xbox.getButtonClick(UP, i)) { + Xbox.setLedOn(LED1, i); + Serial.println(F("Up")); + } + if (Xbox.getButtonClick(DOWN, i)) { + Xbox.setLedOn(LED4, i); + Serial.println(F("Down")); + } + if (Xbox.getButtonClick(LEFT, i)) { + Xbox.setLedOn(LED3, i); + Serial.println(F("Left")); + } + if (Xbox.getButtonClick(RIGHT, i)) { + Xbox.setLedOn(LED2, i); + Serial.println(F("Right")); + } + + if (Xbox.getButtonClick(START, i)) { + Xbox.setLedMode(ALTERNATING, i); + Serial.println(F("Start")); + } + if (Xbox.getButtonClick(BACK, i)) { + Xbox.setLedBlink(ALL, i); + Serial.println(F("Back")); + } + if (Xbox.getButtonClick(L3, i)) + Serial.println(F("L3")); + if (Xbox.getButtonClick(R3, i)) + Serial.println(F("R3")); + + if (Xbox.getButtonClick(L1, i)) + Serial.println(F("L1")); + if (Xbox.getButtonClick(R1, i)) + Serial.println(F("R1")); + if (Xbox.getButtonClick(XBOX, i)) { + Xbox.setLedMode(ROTATING, i); + Serial.print(F("Xbox (Battery: ")); + Serial.print(Xbox.getBatteryLevel(i)); // The battery level in the range 0-3 + Serial.println(F(")")); + } + if (Xbox.getButtonClick(SYNC, i)) { + Serial.println(F("Sync")); + Xbox.disconnect(i); + } + + if (Xbox.getButtonClick(A, i)) + Serial.println(F("A")); + if (Xbox.getButtonClick(B, i)) + Serial.println(F("B")); + if (Xbox.getButtonClick(X, i)) + Serial.println(F("X")); + if (Xbox.getButtonClick(Y, i)) + Serial.println(F("Y")); + } + } + } +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/Xbox/XBOXUSB/XBOXUSB.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/Xbox/XBOXUSB/XBOXUSB.ino new file mode 100644 index 0000000000..8a5691c6e1 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/Xbox/XBOXUSB/XBOXUSB.ino @@ -0,0 +1,113 @@ +/* + Example sketch for the Xbox 360 USB library - developed by Kristian Lauszus + For more information visit my blog: http://blog.tkjelectronics.dk/ or + send me an e-mail: kristianl@tkjelectronics.com + */ + +#include + +// Satisfy the IDE, which needs to see the include statment in the ino too. +#ifdef dobogusinclude +#include +#include +#endif + +USB Usb; +XBOXUSB Xbox(&Usb); + +void setup() { + Serial.begin(115200); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + if (Usb.Init() == -1) { + Serial.print(F("\r\nOSC did not start")); + while (1); //halt + } + Serial.print(F("\r\nXBOX USB Library Started")); +} +void loop() { + Usb.Task(); + if (Xbox.Xbox360Connected) { + if (Xbox.getButtonPress(L2) || Xbox.getButtonPress(R2)) { + Serial.print("L2: "); + Serial.print(Xbox.getButtonPress(L2)); + Serial.print("\tR2: "); + Serial.println(Xbox.getButtonPress(R2)); + Xbox.setRumbleOn(Xbox.getButtonPress(L2), Xbox.getButtonPress(R2)); + } else + Xbox.setRumbleOn(0, 0); + + if (Xbox.getAnalogHat(LeftHatX) > 7500 || Xbox.getAnalogHat(LeftHatX) < -7500 || Xbox.getAnalogHat(LeftHatY) > 7500 || Xbox.getAnalogHat(LeftHatY) < -7500 || Xbox.getAnalogHat(RightHatX) > 7500 || Xbox.getAnalogHat(RightHatX) < -7500 || Xbox.getAnalogHat(RightHatY) > 7500 || Xbox.getAnalogHat(RightHatY) < -7500) { + if (Xbox.getAnalogHat(LeftHatX) > 7500 || Xbox.getAnalogHat(LeftHatX) < -7500) { + Serial.print(F("LeftHatX: ")); + Serial.print(Xbox.getAnalogHat(LeftHatX)); + Serial.print("\t"); + } + if (Xbox.getAnalogHat(LeftHatY) > 7500 || Xbox.getAnalogHat(LeftHatY) < -7500) { + Serial.print(F("LeftHatY: ")); + Serial.print(Xbox.getAnalogHat(LeftHatY)); + Serial.print("\t"); + } + if (Xbox.getAnalogHat(RightHatX) > 7500 || Xbox.getAnalogHat(RightHatX) < -7500) { + Serial.print(F("RightHatX: ")); + Serial.print(Xbox.getAnalogHat(RightHatX)); + Serial.print("\t"); + } + if (Xbox.getAnalogHat(RightHatY) > 7500 || Xbox.getAnalogHat(RightHatY) < -7500) { + Serial.print(F("RightHatY: ")); + Serial.print(Xbox.getAnalogHat(RightHatY)); + } + Serial.println(); + } + + if (Xbox.getButtonClick(UP)) { + Xbox.setLedOn(LED1); + Serial.println(F("Up")); + } + if (Xbox.getButtonClick(DOWN)) { + Xbox.setLedOn(LED4); + Serial.println(F("Down")); + } + if (Xbox.getButtonClick(LEFT)) { + Xbox.setLedOn(LED3); + Serial.println(F("Left")); + } + if (Xbox.getButtonClick(RIGHT)) { + Xbox.setLedOn(LED2); + Serial.println(F("Right")); + } + + if (Xbox.getButtonClick(START)) { + Xbox.setLedMode(ALTERNATING); + Serial.println(F("Start")); + } + if (Xbox.getButtonClick(BACK)) { + Xbox.setLedBlink(ALL); + Serial.println(F("Back")); + } + if (Xbox.getButtonClick(L3)) + Serial.println(F("L3")); + if (Xbox.getButtonClick(R3)) + Serial.println(F("R3")); + + if (Xbox.getButtonClick(L1)) + Serial.println(F("L1")); + if (Xbox.getButtonClick(R1)) + Serial.println(F("R1")); + if (Xbox.getButtonClick(XBOX)) { + Xbox.setLedMode(ROTATING); + Serial.println(F("Xbox")); + } + + if (Xbox.getButtonClick(A)) + Serial.println(F("A")); + if (Xbox.getButtonClick(B)) + Serial.println(F("B")); + if (Xbox.getButtonClick(X)) + Serial.println(F("X")); + if (Xbox.getButtonClick(Y)) + Serial.println(F("Y")); + } + delay(1); +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/acm/acm_terminal/acm_terminal.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/acm/acm_terminal/acm_terminal.ino new file mode 100644 index 0000000000..f509cda890 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/acm/acm_terminal/acm_terminal.ino @@ -0,0 +1,100 @@ +#include +#include + +#include "pgmstrings.h" + +// Satisfy the IDE, which needs to see the include statment in the ino too. +#ifdef dobogusinclude +#include +#include +#endif + +class ACMAsyncOper : public CDCAsyncOper +{ +public: + uint8_t OnInit(ACM *pacm); +}; + +uint8_t ACMAsyncOper::OnInit(ACM *pacm) +{ + uint8_t rcode; + // Set DTR = 1 RTS=1 + rcode = pacm->SetControlLineState(3); + + if (rcode) + { + ErrorMessage(PSTR("SetControlLineState"), rcode); + return rcode; + } + + LINE_CODING lc; + lc.dwDTERate = 115200; + lc.bCharFormat = 0; + lc.bParityType = 0; + lc.bDataBits = 8; + + rcode = pacm->SetLineCoding(&lc); + + if (rcode) + ErrorMessage(PSTR("SetLineCoding"), rcode); + + return rcode; +} + +USB Usb; +//USBHub Hub(&Usb); +ACMAsyncOper AsyncOper; +ACM Acm(&Usb, &AsyncOper); + +void setup() +{ + Serial.begin( 115200 ); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + Serial.println("Start"); + + if (Usb.Init() == -1) + Serial.println("OSCOKIRQ failed to assert"); + + delay( 200 ); +} + +void loop() +{ + Usb.Task(); + + if( Acm.isReady()) { + uint8_t rcode; + + /* reading the keyboard */ + if(Serial.available()) { + uint8_t data= Serial.read(); + /* sending to the phone */ + rcode = Acm.SndData(1, &data); + if (rcode) + ErrorMessage(PSTR("SndData"), rcode); + }//if(Serial.available()... + + delay(50); + + /* reading the phone */ + /* buffer size must be greater or equal to max.packet size */ + /* it it set to 64 (largest possible max.packet size) here, can be tuned down + for particular endpoint */ + uint8_t buf[64]; + uint16_t rcvd = 64; + rcode = Acm.RcvData(&rcvd, buf); + if (rcode && rcode != hrNAK) + ErrorMessage(PSTR("Ret"), rcode); + + if( rcvd ) { //more than zero bytes received + for(uint16_t i=0; i < rcvd; i++ ) { + Serial.print((char)buf[i]); //printing on the screen + } + } + delay(10); + }//if( Usb.getUsbTaskState() == USB_STATE_RUNNING.. +} + + diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/acm/acm_terminal/pgmstrings.h b/lib/usbhost/USB_Host_Shield_2.0/examples/acm/acm_terminal/pgmstrings.h new file mode 100644 index 0000000000..bdb0077ecc --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/acm/acm_terminal/pgmstrings.h @@ -0,0 +1,52 @@ +#if !defined(__PGMSTRINGS_H__) +#define __PGMSTRINGS_H__ + +#define LOBYTE(x) ((char*)(&(x)))[0] +#define HIBYTE(x) ((char*)(&(x)))[1] +#define BUFSIZE 256 //buffer size + + +/* Print strings in Program Memory */ +const char Gen_Error_str[] PROGMEM = "\r\nRequest error. Error code:\t"; +const char Dev_Header_str[] PROGMEM ="\r\nDevice descriptor: "; +const char Dev_Length_str[] PROGMEM ="\r\nDescriptor Length:\t"; +const char Dev_Type_str[] PROGMEM ="\r\nDescriptor type:\t"; +const char Dev_Version_str[] PROGMEM ="\r\nUSB version:\t\t"; +const char Dev_Class_str[] PROGMEM ="\r\nDevice class:\t\t"; +const char Dev_Subclass_str[] PROGMEM ="\r\nDevice Subclass:\t"; +const char Dev_Protocol_str[] PROGMEM ="\r\nDevice Protocol:\t"; +const char Dev_Pktsize_str[] PROGMEM ="\r\nMax.packet size:\t"; +const char Dev_Vendor_str[] PROGMEM ="\r\nVendor ID:\t\t"; +const char Dev_Product_str[] PROGMEM ="\r\nProduct ID:\t\t"; +const char Dev_Revision_str[] PROGMEM ="\r\nRevision ID:\t\t"; +const char Dev_Mfg_str[] PROGMEM ="\r\nMfg.string index:\t"; +const char Dev_Prod_str[] PROGMEM ="\r\nProd.string index:\t"; +const char Dev_Serial_str[] PROGMEM ="\r\nSerial number index:\t"; +const char Dev_Nconf_str[] PROGMEM ="\r\nNumber of conf.:\t"; +const char Conf_Trunc_str[] PROGMEM ="Total length truncated to 256 bytes"; +const char Conf_Header_str[] PROGMEM ="\r\nConfiguration descriptor:"; +const char Conf_Totlen_str[] PROGMEM ="\r\nTotal length:\t\t"; +const char Conf_Nint_str[] PROGMEM ="\r\nNum.intf:\t\t"; +const char Conf_Value_str[] PROGMEM ="\r\nConf.value:\t\t"; +const char Conf_String_str[] PROGMEM ="\r\nConf.string:\t\t"; +const char Conf_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t"; +const char Conf_Pwr_str[] PROGMEM ="\r\nMax.pwr:\t\t"; +const char Int_Header_str[] PROGMEM ="\r\n\r\nInterface descriptor:"; +const char Int_Number_str[] PROGMEM ="\r\nIntf.number:\t\t"; +const char Int_Alt_str[] PROGMEM ="\r\nAlt.:\t\t\t"; +const char Int_Endpoints_str[] PROGMEM ="\r\nEndpoints:\t\t"; +const char Int_Class_str[] PROGMEM ="\r\nIntf. Class:\t\t"; +const char Int_Subclass_str[] PROGMEM ="\r\nIntf. Subclass:\t\t"; +const char Int_Protocol_str[] PROGMEM ="\r\nIntf. Protocol:\t\t"; +const char Int_String_str[] PROGMEM ="\r\nIntf.string:\t\t"; +const char End_Header_str[] PROGMEM ="\r\n\r\nEndpoint descriptor:"; +const char End_Address_str[] PROGMEM ="\r\nEndpoint address:\t"; +const char End_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t"; +const char End_Pktsize_str[] PROGMEM ="\r\nMax.pkt size:\t\t"; +const char End_Interval_str[] PROGMEM ="\r\nPolling interval:\t"; +const char Unk_Header_str[] PROGMEM = "\r\nUnknown descriptor:"; +const char Unk_Length_str[] PROGMEM ="\r\nLength:\t\t"; +const char Unk_Type_str[] PROGMEM ="\r\nType:\t\t"; +const char Unk_Contents_str[] PROGMEM ="\r\nContents:\t"; + +#endif // __PGMSTRINGS_H__ \ No newline at end of file diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/adk/ArduinoBlinkLED/ArduinoBlinkLED.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/adk/ArduinoBlinkLED/ArduinoBlinkLED.ino new file mode 100644 index 0000000000..d59b9bb3dc --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/adk/ArduinoBlinkLED/ArduinoBlinkLED.ino @@ -0,0 +1,89 @@ +// The source for the Android application can be found at the following link: https://github.com/Lauszus/ArduinoBlinkLED +// The code for the Android application is heavily based on this guide: http://allaboutee.com/2011/12/31/arduino-adk-board-blink-an-led-with-your-phone-code-and-explanation/ by Miguel +#include + +// +// CAUTION! WARNING! ATTENTION! VORSICHT! ADVARSEL! ¡CUIDADO! ВНИМАНИЕ! +// +// Pin 13 is occupied by the SCK pin on various Arduino boards, +// including Uno, Duemilanove, etc., so use a different pin for those boards. +// +// CAUTION! WARNING! ATTENTION! VORSICHT! ADVARSEL! ¡CUIDADO! ВНИМАНИЕ! +// +#if defined(LED_BUILTIN) +#define LED LED_BUILTIN // Use built in LED +#else +#define LED 9 // Set to something here that makes sense for your board. +#endif + + +// Satisfy IDE, which only needs to see the include statment in the ino. +#ifdef dobogusinclude +#include +#include +#endif + +USB Usb; +ADK adk(&Usb, "TKJElectronics", // Manufacturer Name + "ArduinoBlinkLED", // Model Name + "Example sketch for the USB Host Shield", // Description (user-visible string) + "1.0", // Version + "http://www.tkjelectronics.dk/uploads/ArduinoBlinkLED.apk", // URL (web page to visit if no installed apps support the accessory) + "123456789"); // Serial Number (optional) + +uint32_t timer; +bool connected; + +void setup() { + Serial.begin(115200); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + if (Usb.Init() == -1) { + Serial.print("\r\nOSCOKIRQ failed to assert"); + while (1); // halt + } + pinMode(LED, OUTPUT); + Serial.print("\r\nArduino Blink LED Started"); +} + +void loop() { + Usb.Task(); + + if (adk.isReady()) { + if (!connected) { + connected = true; + Serial.print(F("\r\nConnected to accessory")); + } + + uint8_t msg[1]; + uint16_t len = sizeof(msg); + uint8_t rcode = adk.RcvData(&len, msg); + if (rcode && rcode != hrNAK) { + Serial.print(F("\r\nData rcv: ")); + Serial.print(rcode, HEX); + } else if (len > 0) { + Serial.print(F("\r\nData Packet: ")); + Serial.print(msg[0]); + digitalWrite(LED, msg[0] ? HIGH : LOW); + } + + if (millis() - timer >= 1000) { // Send data every 1s + timer = millis(); + rcode = adk.SndData(sizeof(timer), (uint8_t*)&timer); + if (rcode && rcode != hrNAK) { + Serial.print(F("\r\nData send: ")); + Serial.print(rcode, HEX); + } else if (rcode != hrNAK) { + Serial.print(F("\r\nTimer: ")); + Serial.print(timer); + } + } + } else { + if (connected) { + connected = false; + Serial.print(F("\r\nDisconnected from accessory")); + digitalWrite(LED, LOW); + } + } +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/adk/adk_barcode/adk_barcode.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/adk/adk_barcode/adk_barcode.ino new file mode 100644 index 0000000000..a308ff0f83 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/adk/adk_barcode/adk_barcode.ino @@ -0,0 +1,91 @@ +/**/ +/* A sketch demonstrating data exchange between two USB devices - a HID barcode scanner and ADK-compatible Android phone */ +/**/ +#include +#include +#include + +// Satisfy IDE, which only needs to see the include statment in the ino. +#ifdef dobogusinclude +#include +#include +#endif + +USB Usb; +USBHub Hub1(&Usb); +USBHub Hub2(&Usb); +HIDBoot Keyboard(&Usb); + +ADK adk(&Usb,"Circuits@Home, ltd.", + "USB Host Shield", + "Arduino Terminal for Android", + "1.0", + "http://www.circuitsathome.com", + "0000000000000001"); + + +class KbdRptParser : public KeyboardReportParser +{ + +protected: + void OnKeyDown (uint8_t mod, uint8_t key); + void OnKeyPressed(uint8_t key); +}; + +void KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key) +{ + uint8_t c = OemToAscii(mod, key); + + if (c) + OnKeyPressed(c); +} + +/* what to do when symbol arrives */ +void KbdRptParser::OnKeyPressed(uint8_t key) +{ +const char* new_line = "\n"; +uint8_t rcode; +uint8_t keylcl; + + if( adk.isReady() == false ) { + return; + } + + keylcl = key; + + if( keylcl == 0x13 ) { + rcode = adk.SndData( strlen( new_line ), (uint8_t *)new_line ); + } + else { + rcode = adk.SndData( 1, &keylcl ); + } + + Serial.print((char) keylcl ); + Serial.print(" : "); + Serial.println( keylcl, HEX ); +}; + +KbdRptParser Prs; + +void setup() +{ + Serial.begin(115200); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + Serial.println("\r\nADK demo start"); + + if (Usb.Init() == -1) { + Serial.println("OSCOKIRQ failed to assert"); + while(1); //halt + }//if (Usb.Init() == -1... + + Keyboard.SetReportParser(0, (HIDReportParser*)&Prs); + + delay( 200 ); +} + +void loop() +{ + Usb.Task(); +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/adk/demokit_20/demokit_20.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/adk/demokit_20/demokit_20.ino new file mode 100644 index 0000000000..f65adf57bb --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/adk/demokit_20/demokit_20.ino @@ -0,0 +1,103 @@ +#include +#include + +// Satisfy IDE, which only needs to see the include statment in the ino. +#ifdef dobogusinclude +#include +#include +#endif + +USB Usb; +USBHub hub0(&Usb); +USBHub hub1(&Usb); +ADK adk(&Usb,"Google, Inc.", + "DemoKit", + "DemoKit Arduino Board", + "1.0", + "http://www.android.com", + "0000000012345678"); +uint8_t b, b1; + + +#define LED1_RED 3 +#define BUTTON1 2 + +void init_buttons() +{ + pinMode(BUTTON1, INPUT); + + // enable the internal pullups + digitalWrite(BUTTON1, HIGH); +} + +void init_leds() +{ + digitalWrite(LED1_RED, 0); + + pinMode(LED1_RED, OUTPUT); +} + +void setup() +{ + Serial.begin(115200); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + Serial.println("\r\nADK demo start"); + + if (Usb.Init() == -1) { + Serial.println("OSCOKIRQ failed to assert"); + while(1); //halt + }//if (Usb.Init() == -1... + + + init_leds(); + init_buttons(); + b1 = digitalRead(BUTTON1); +} + +void loop() +{ + uint8_t rcode; + uint8_t msg[3] = { 0x00 }; + Usb.Task(); + + if( adk.isReady() == false ) { + analogWrite(LED1_RED, 255); + return; + } + uint16_t len = sizeof(msg); + + rcode = adk.RcvData(&len, msg); + if( rcode ) { + USBTRACE2("Data rcv. :", rcode ); + } + if(len > 0) { + USBTRACE("\r\nData Packet."); + // assumes only one command per packet + if (msg[0] == 0x2) { + switch( msg[1] ) { + case 0: + analogWrite(LED1_RED, 255 - msg[2]); + break; + }//switch( msg[1]... + }//if (msg[0] == 0x2... + }//if( len > 0... + + msg[0] = 0x1; + + b = digitalRead(BUTTON1); + if (b != b1) { + USBTRACE("\r\nButton state changed"); + msg[1] = 0; + msg[2] = b ? 0 : 1; + rcode = adk.SndData( 3, msg ); + if( rcode ) { + USBTRACE2("Button send: ", rcode ); + } + b1 = b; + }//if (b != b1... + + + delay( 10 ); +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/adk/term_test/term_test.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/adk/term_test/term_test.ino new file mode 100644 index 0000000000..db681c3b50 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/adk/term_test/term_test.ino @@ -0,0 +1,65 @@ +#include +#include + +// Satisfy IDE, which only needs to see the include statment in the ino. +#ifdef dobogusinclude +#include +#include +#endif + +USB Usb; +//USBHub Hub(&Usb); + +ADK adk(&Usb,"Circuits@Home, ltd.", + "USB Host Shield", + "Arduino Terminal for Android", + "1.0", + "http://www.circuitsathome.com", + "0000000000000001"); + +void setup() +{ + Serial.begin(115200); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + Serial.println("\r\nADK demo start"); + + if (Usb.Init() == -1) { + Serial.println("OSCOKIRQ failed to assert"); + while(1); //halt + }//if (Usb.Init() == -1... +} + +void loop() +{ + uint8_t rcode; + uint8_t msg[64] = { 0x00 }; + const char* recv = "Received: "; + + Usb.Task(); + + if( adk.isReady() == false ) { + return; + } + uint16_t len = 64; + + rcode = adk.RcvData(&len, msg); + if( rcode & ( rcode != hrNAK )) { + USBTRACE2("Data rcv. :", rcode ); + } + if(len > 0) { + USBTRACE("\r\nData Packet."); + + for( uint8_t i = 0; i < len; i++ ) { + Serial.print((char)msg[i]); + } + /* sending back what was received */ + rcode = adk.SndData( strlen( recv ), (uint8_t *)recv ); + rcode = adk.SndData( strlen(( char * )msg ), msg ); + + }//if( len > 0 )... + + delay( 1000 ); +} + diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/adk/term_time/term_time.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/adk/term_time/term_time.ino new file mode 100644 index 0000000000..a3f1dbc8cb --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/adk/term_time/term_time.ino @@ -0,0 +1,50 @@ +#include +#include + +// Satisfy IDE, which only needs to see the include statment in the ino. +#ifdef dobogusinclude +#include +#include +#endif + +USB Usb; + +ADK adk(&Usb,"Circuits@Home, ltd.", + "USB Host Shield", + "Arduino Terminal for Android", + "1.0", + "http://www.circuitsathome.com", + "0000000000000001"); + +void setup() +{ + Serial.begin(115200); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + Serial.println("\r\nADK demo start"); + + if (Usb.Init() == -1) { + Serial.println("OSCOKIRQ failed to assert"); + while(1); //halt + }//if (Usb.Init() == -1... +} + +void loop() +{ + uint8_t buf[ 12 ] = { 0 }; //buffer to convert unsigned long to ASCII + const char* sec_ela = " seconds elapsed\r"; + uint8_t rcode; + + Usb.Task(); + if( adk.isReady() == false ) { + return; + } + + ultoa( millis()/1000, (char *)buf, 10 ); + + rcode = adk.SndData( strlen((char *)buf), buf ); + rcode = adk.SndData( strlen( sec_ela), (uint8_t *)sec_ela ); + + delay( 1000 ); +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/board_qc/board_qc.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/board_qc/board_qc.ino new file mode 100644 index 0000000000..573c3ce083 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/board_qc/board_qc.ino @@ -0,0 +1,259 @@ +/* USB Host Shield 2.0 board quality control routine */ +/* To see the output set your terminal speed to 115200 */ +/* for GPIO test to pass you need to connect GPIN0 to GPOUT7, GPIN1 to GPOUT6, etc. */ +/* otherwise press any key after getting GPIO error to complete the test */ +/**/ +#include + +// Satisfy the IDE, which needs to see the include statment in the ino too. +#ifdef dobogusinclude +#include +#include <../../../../hardware/pic32/libraries/SPI/SPI.h> // Hack to use the SPI library +#include // Hack to use the SPI library +#endif + +/* variables */ +uint8_t rcode; +uint8_t usbstate; +uint8_t laststate; +//uint8_t buf[sizeof(USB_DEVICE_DESCRIPTOR)]; +USB_DEVICE_DESCRIPTOR buf; + +/* objects */ +USB Usb; +//USBHub hub(&Usb); + +void setup() { + laststate = 0; + Serial.begin(115200); +#if !defined(__MIPSEL__) + while(!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + E_Notify(PSTR("\r\nCircuits At Home 2011"), 0x80); + E_Notify(PSTR("\r\nUSB Host Shield Quality Control Routine"), 0x80); + /* SPI quick test - check revision register */ + E_Notify(PSTR("\r\nReading REVISION register... Die revision "), 0x80); + Usb.Init(); // Initializes SPI, we don't care about the return value here + { + uint8_t tmpbyte = Usb.regRd(rREVISION); + switch(tmpbyte) { + case( 0x01): //rev.01 + E_Notify(PSTR("01"), 0x80); + break; + case( 0x12): //rev.02 + E_Notify(PSTR("02"), 0x80); + break; + case( 0x13): //rev.03 + E_Notify(PSTR("03"), 0x80); + break; + default: + E_Notify(PSTR("invalid. Value returned: "), 0x80); + print_hex(tmpbyte, 8); + halt55(); + break; + }//switch( tmpbyte... + }//check revision register + /* SPI long test */ + { + E_Notify(PSTR("\r\nSPI long test. Transfers 1MB of data. Each dot is 64K"), 0x80); + uint8_t sample_wr = 0; + uint8_t sample_rd = 0; + uint8_t gpinpol_copy = Usb.regRd(rGPINPOL); + for(uint8_t i = 0; i < 16; i++) { + for(uint16_t j = 0; j < 65535; j++) { + Usb.regWr(rGPINPOL, sample_wr); + sample_rd = Usb.regRd(rGPINPOL); + if(sample_rd != sample_wr) { + E_Notify(PSTR("\r\nTest failed. "), 0x80); + E_Notify(PSTR("Value written: "), 0x80); + print_hex(sample_wr, 8); + E_Notify(PSTR(" read: "), 0x80); + print_hex(sample_rd, 8); + halt55(); + }//if( sample_rd != sample_wr.. + sample_wr++; + }//for( uint16_t j... + E_Notify(PSTR("."), 0x80); + }//for( uint8_t i... + Usb.regWr(rGPINPOL, gpinpol_copy); + E_Notify(PSTR(" SPI long test passed"), 0x80); + }//SPI long test + /* GPIO test */ + /* in order to simplify board layout, GPIN pins on text fixture are connected to GPOUT */ + /* in reverse order, i.e, GPIN0 is connected to GPOUT7, GPIN1 to GPOUT6, etc. */ + { + uint8_t tmpbyte; + E_Notify(PSTR("\r\nGPIO test. Connect GPIN0 to GPOUT7, GPIN1 to GPOUT6, and so on"), 0x80); + for(uint8_t sample_gpio = 0; sample_gpio < 255; sample_gpio++) { + Usb.gpioWr(sample_gpio); + tmpbyte = Usb.gpioRd(); + /* bit reversing code copied vetbatim from http://graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious */ + tmpbyte = ((tmpbyte * 0x0802LU & 0x22110LU) | (tmpbyte * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16; + if(sample_gpio != tmpbyte) { + E_Notify(PSTR("\r\nTest failed. Value written: "), 0x80); + print_hex(sample_gpio, 8); + E_Notify(PSTR(" Value read: "), 0x80); + print_hex(tmpbyte, 8); + E_Notify(PSTR(" "), 0x80); + press_any_key(); + break; + }//if( sample_gpio != tmpbyte... + }//for( uint8_t sample_gpio... + E_Notify(PSTR("\r\nGPIO test passed."), 0x80); + }//GPIO test + /* PLL test. Stops/starts MAX3421E oscillator several times */ + { + E_Notify(PSTR("\r\nPLL test. 100 chip resets will be performed"), 0x80); + /* check current state of the oscillator */ + if(!(Usb.regRd(rUSBIRQ) & bmOSCOKIRQ)) { //wrong state - should be on + E_Notify(PSTR("\r\nCurrent oscillator state unexpected."), 0x80); + press_any_key(); + } + /* Restart oscillator */ + E_Notify(PSTR("\r\nResetting oscillator\r\n"), 0x80); + for(uint16_t i = 0; i < 100; i++) { + E_Notify(PSTR("\rReset number "), 0x80); + Serial.print(i, DEC); + Usb.regWr(rUSBCTL, bmCHIPRES); //reset + if(Usb.regRd(rUSBIRQ) & bmOSCOKIRQ) { //wrong state - should be off + E_Notify(PSTR("\r\nCurrent oscillator state unexpected."), 0x80); + halt55(); + } + Usb.regWr(rUSBCTL, 0x00); //release from reset + uint16_t j = 0; + for(j = 1; j < 65535; j++) { //tracking off to on time + if(Usb.regRd(rUSBIRQ) & bmOSCOKIRQ) { + E_Notify(PSTR(" Time to stabilize - "), 0x80); + Serial.print(j, DEC); + E_Notify(PSTR(" cycles\r\n"), 0x80); + break; + } + }//for( uint16_t j = 0; j < 65535; j++ + if(j == 0) { + E_Notify(PSTR("PLL failed to stabilize"), 0x80); + press_any_key(); + } + }//for( uint8_t i = 0; i < 255; i++ + + }//PLL test + /* initializing USB stack */ + if(Usb.Init() == -1) { + E_Notify(PSTR("\r\nOSCOKIRQ failed to assert"), 0x80); + halt55(); + } + E_Notify(PSTR("\r\nChecking USB device communication.\r\n"), 0x80); +} + +void loop() { + delay(200); + Usb.Task(); + usbstate = Usb.getUsbTaskState(); + if(usbstate != laststate) { + laststate = usbstate; + /**/ + switch(usbstate) { + case( USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE): + E_Notify(PSTR("\r\nWaiting for device..."), 0x80); + break; + case( USB_ATTACHED_SUBSTATE_RESET_DEVICE): + E_Notify(PSTR("\r\nDevice connected. Resetting..."), 0x80); + break; + case( USB_ATTACHED_SUBSTATE_WAIT_SOF): + E_Notify(PSTR("\r\nReset complete. Waiting for the first SOF..."), 0x80); + break; + case( USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE): + E_Notify(PSTR("\r\nSOF generation started. Enumerating device..."), 0x80); + break; + case( USB_STATE_ADDRESSING): + E_Notify(PSTR("\r\nSetting device address..."), 0x80); + break; + case( USB_STATE_RUNNING): + E_Notify(PSTR("\r\nGetting device descriptor"), 0x80); + rcode = Usb.getDevDescr(1, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*) & buf); + + if(rcode) { + E_Notify(PSTR("\r\nError reading device descriptor. Error code "), 0x80); + print_hex(rcode, 8); + } else { + /**/ + E_Notify(PSTR("\r\nDescriptor Length:\t"), 0x80); + print_hex(buf.bLength, 8); + E_Notify(PSTR("\r\nDescriptor type:\t"), 0x80); + print_hex(buf.bDescriptorType, 8); + E_Notify(PSTR("\r\nUSB version:\t\t"), 0x80); + print_hex(buf.bcdUSB, 16); + E_Notify(PSTR("\r\nDevice class:\t\t"), 0x80); + print_hex(buf.bDeviceClass, 8); + E_Notify(PSTR("\r\nDevice Subclass:\t"), 0x80); + print_hex(buf.bDeviceSubClass, 8); + E_Notify(PSTR("\r\nDevice Protocol:\t"), 0x80); + print_hex(buf.bDeviceProtocol, 8); + E_Notify(PSTR("\r\nMax.packet size:\t"), 0x80); + print_hex(buf.bMaxPacketSize0, 8); + E_Notify(PSTR("\r\nVendor ID:\t\t"), 0x80); + print_hex(buf.idVendor, 16); + E_Notify(PSTR("\r\nProduct ID:\t\t"), 0x80); + print_hex(buf.idProduct, 16); + E_Notify(PSTR("\r\nRevision ID:\t\t"), 0x80); + print_hex(buf.bcdDevice, 16); + E_Notify(PSTR("\r\nMfg.string index:\t"), 0x80); + print_hex(buf.iManufacturer, 8); + E_Notify(PSTR("\r\nProd.string index:\t"), 0x80); + print_hex(buf.iProduct, 8); + E_Notify(PSTR("\r\nSerial number index:\t"), 0x80); + print_hex(buf.iSerialNumber, 8); + E_Notify(PSTR("\r\nNumber of conf.:\t"), 0x80); + print_hex(buf.bNumConfigurations, 8); + /**/ + E_Notify(PSTR("\r\n\nAll tests passed. Press RESET to restart test"), 0x80); + while(1); + } + break; + case( USB_STATE_ERROR): + E_Notify(PSTR("\r\nUSB state machine reached error state"), 0x80); + break; + + default: + break; + }//switch( usbstate... + } +}//loop()... + +/* constantly transmits 0x55 via SPI to aid probing */ +void halt55() { + + E_Notify(PSTR("\r\nUnrecoverable error - test halted!!"), 0x80); + E_Notify(PSTR("\r\n0x55 pattern is transmitted via SPI"), 0x80); + E_Notify(PSTR("\r\nPress RESET to restart test"), 0x80); + + while(1) { + Usb.regWr(0x55, 0x55); + } +} + +/* prints hex numbers with leading zeroes */ +void print_hex(int v, int num_places) { + int mask = 0, n, num_nibbles, digit; + + for(n = 1; n <= num_places; n++) { + mask = (mask << 1) | 0x0001; + } + v = v & mask; // truncate v to specified number of places + + num_nibbles = num_places / 4; + if((num_places % 4) != 0) { + ++num_nibbles; + } + do { + digit = ((v >> (num_nibbles - 1) * 4)) & 0x0f; + Serial.print(digit, HEX); + } while(--num_nibbles); +} + +/* prints "Press any key" and returns when key is pressed */ +void press_any_key() { + E_Notify(PSTR("\r\nPress any key to continue..."), 0x80); + while(Serial.available() <= 0); //wait for input + Serial.read(); //empty input buffer + return; +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/cdc_XR21B1411/XR_terminal/XR_terminal.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/cdc_XR21B1411/XR_terminal/XR_terminal.ino new file mode 100644 index 0000000000..0173a08b50 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/cdc_XR21B1411/XR_terminal/XR_terminal.ino @@ -0,0 +1,83 @@ +#include + +// Satisfy IDE, which only needs to see the include statment in the ino. +#ifdef dobogusinclude +#include +#include +#endif + +class ACMAsyncOper : public CDCAsyncOper +{ +public: + uint8_t OnInit(ACM *pacm); +}; + +uint8_t ACMAsyncOper::OnInit(ACM *pacm) +{ + uint8_t rcode; + // Set DTR = 1 RTS=1 + rcode = pacm->SetControlLineState(3); + + if (rcode) + { + ErrorMessage(PSTR("SetControlLineState"), rcode); + return rcode; + } + + LINE_CODING lc; + lc.dwDTERate = 115200; + lc.bCharFormat = 0; + lc.bParityType = 0; + lc.bDataBits = 8; + + rcode = pacm->SetLineCoding(&lc); + + if (rcode) + ErrorMessage(PSTR("SetLineCoding"), rcode); + + return rcode; +} + +USB Usb; +ACMAsyncOper AsyncOper; +XR21B1411 Acm(&Usb, &AsyncOper); + +void setup() { + Serial.begin( 115200 ); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + Serial.println("\r\n\r\nStart"); + + if (Usb.Init() == -1) Serial.println("OSCOKIRQ failed to assert"); +} + +void loop() { + Usb.Task(); + if( Acm.isReady()) { + uint8_t rcode; + uint8_t buf[1]; + uint16_t rcvd = 1; + + /* read keyboard */ + if(Serial.available()) { + uint8_t data = Serial.read(); + /* send */ + rcode = Acm.SndData(1, &data); + if (rcode) + ErrorMessage(PSTR("SndData"), rcode); + } + + /* read XR serial */ + rcode = Acm.RcvData(&rcvd, buf); + if (rcode && rcode != hrNAK) + ErrorMessage(PSTR("Ret"), rcode); + + if( rcvd ) { //more than zero bytes received + for(uint16_t i=0; i < rcvd; i++ ) { + Serial.print((char)buf[i]); + } + } + } +} + diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/ftdi/USBFTDILoopback/USBFTDILoopback.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/ftdi/USBFTDILoopback/USBFTDILoopback.ino new file mode 100644 index 0000000000..5be7adc2f3 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/ftdi/USBFTDILoopback/USBFTDILoopback.ino @@ -0,0 +1,98 @@ +#include +#include + +#include "pgmstrings.h" + +// Satisfy the IDE, which needs to see the include statment in the ino too. +#ifdef dobogusinclude +#include +#include +#endif + +class FTDIAsync : public FTDIAsyncOper +{ +public: + uint8_t OnInit(FTDI *pftdi); +}; + +uint8_t FTDIAsync::OnInit(FTDI *pftdi) +{ + uint8_t rcode = 0; + + rcode = pftdi->SetBaudRate(115200); + + if (rcode) + { + ErrorMessage(PSTR("SetBaudRate"), rcode); + return rcode; + } + rcode = pftdi->SetFlowControl(FTDI_SIO_DISABLE_FLOW_CTRL); + + if (rcode) + ErrorMessage(PSTR("SetFlowControl"), rcode); + + return rcode; +} + +USB Usb; +//USBHub Hub(&Usb); +FTDIAsync FtdiAsync; +FTDI Ftdi(&Usb, &FtdiAsync); + +uint32_t next_time; + +void setup() +{ + Serial.begin( 115200 ); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + Serial.println("Start"); + + if (Usb.Init() == -1) + Serial.println("OSC did not start."); + + delay( 200 ); + + next_time = millis() + 5000; +} + +void loop() +{ + Usb.Task(); + + if( Usb.getUsbTaskState() == USB_STATE_RUNNING ) + { + uint8_t rcode; + char strbuf[] = "DEADBEEF"; + //char strbuf[] = "The quick brown fox jumps over the lazy dog"; + //char strbuf[] = "This string contains 61 character to demonstrate FTDI buffers"; //add one symbol to it to see some garbage + Serial.print("."); + + rcode = Ftdi.SndData(strlen(strbuf), (uint8_t*)strbuf); + + if (rcode) + ErrorMessage(PSTR("SndData"), rcode); + + delay(50); + + uint8_t buf[64]; + + for (uint8_t i=0; i<64; i++) + buf[i] = 0; + + uint16_t rcvd = 64; + rcode = Ftdi.RcvData(&rcvd, buf); + + if (rcode && rcode != hrNAK) + ErrorMessage(PSTR("Ret"), rcode); + + // The device reserves the first two bytes of data + // to contain the current values of the modem and line status registers. + if (rcvd > 2) + Serial.print((char*)(buf+2)); + + delay(10); + } +} + diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/ftdi/USBFTDILoopback/pgmstrings.h b/lib/usbhost/USB_Host_Shield_2.0/examples/ftdi/USBFTDILoopback/pgmstrings.h new file mode 100644 index 0000000000..bdb0077ecc --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/ftdi/USBFTDILoopback/pgmstrings.h @@ -0,0 +1,52 @@ +#if !defined(__PGMSTRINGS_H__) +#define __PGMSTRINGS_H__ + +#define LOBYTE(x) ((char*)(&(x)))[0] +#define HIBYTE(x) ((char*)(&(x)))[1] +#define BUFSIZE 256 //buffer size + + +/* Print strings in Program Memory */ +const char Gen_Error_str[] PROGMEM = "\r\nRequest error. Error code:\t"; +const char Dev_Header_str[] PROGMEM ="\r\nDevice descriptor: "; +const char Dev_Length_str[] PROGMEM ="\r\nDescriptor Length:\t"; +const char Dev_Type_str[] PROGMEM ="\r\nDescriptor type:\t"; +const char Dev_Version_str[] PROGMEM ="\r\nUSB version:\t\t"; +const char Dev_Class_str[] PROGMEM ="\r\nDevice class:\t\t"; +const char Dev_Subclass_str[] PROGMEM ="\r\nDevice Subclass:\t"; +const char Dev_Protocol_str[] PROGMEM ="\r\nDevice Protocol:\t"; +const char Dev_Pktsize_str[] PROGMEM ="\r\nMax.packet size:\t"; +const char Dev_Vendor_str[] PROGMEM ="\r\nVendor ID:\t\t"; +const char Dev_Product_str[] PROGMEM ="\r\nProduct ID:\t\t"; +const char Dev_Revision_str[] PROGMEM ="\r\nRevision ID:\t\t"; +const char Dev_Mfg_str[] PROGMEM ="\r\nMfg.string index:\t"; +const char Dev_Prod_str[] PROGMEM ="\r\nProd.string index:\t"; +const char Dev_Serial_str[] PROGMEM ="\r\nSerial number index:\t"; +const char Dev_Nconf_str[] PROGMEM ="\r\nNumber of conf.:\t"; +const char Conf_Trunc_str[] PROGMEM ="Total length truncated to 256 bytes"; +const char Conf_Header_str[] PROGMEM ="\r\nConfiguration descriptor:"; +const char Conf_Totlen_str[] PROGMEM ="\r\nTotal length:\t\t"; +const char Conf_Nint_str[] PROGMEM ="\r\nNum.intf:\t\t"; +const char Conf_Value_str[] PROGMEM ="\r\nConf.value:\t\t"; +const char Conf_String_str[] PROGMEM ="\r\nConf.string:\t\t"; +const char Conf_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t"; +const char Conf_Pwr_str[] PROGMEM ="\r\nMax.pwr:\t\t"; +const char Int_Header_str[] PROGMEM ="\r\n\r\nInterface descriptor:"; +const char Int_Number_str[] PROGMEM ="\r\nIntf.number:\t\t"; +const char Int_Alt_str[] PROGMEM ="\r\nAlt.:\t\t\t"; +const char Int_Endpoints_str[] PROGMEM ="\r\nEndpoints:\t\t"; +const char Int_Class_str[] PROGMEM ="\r\nIntf. Class:\t\t"; +const char Int_Subclass_str[] PROGMEM ="\r\nIntf. Subclass:\t\t"; +const char Int_Protocol_str[] PROGMEM ="\r\nIntf. Protocol:\t\t"; +const char Int_String_str[] PROGMEM ="\r\nIntf.string:\t\t"; +const char End_Header_str[] PROGMEM ="\r\n\r\nEndpoint descriptor:"; +const char End_Address_str[] PROGMEM ="\r\nEndpoint address:\t"; +const char End_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t"; +const char End_Pktsize_str[] PROGMEM ="\r\nMax.pkt size:\t\t"; +const char End_Interval_str[] PROGMEM ="\r\nPolling interval:\t"; +const char Unk_Header_str[] PROGMEM = "\r\nUnknown descriptor:"; +const char Unk_Length_str[] PROGMEM ="\r\nLength:\t\t"; +const char Unk_Type_str[] PROGMEM ="\r\nType:\t\t"; +const char Unk_Contents_str[] PROGMEM ="\r\nContents:\t"; + +#endif // __PGMSTRINGS_H__ \ No newline at end of file diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/hub_demo/hub_demo.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/hub_demo/hub_demo.ino new file mode 100644 index 0000000000..d8b2d4bb72 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/hub_demo/hub_demo.ino @@ -0,0 +1,345 @@ +#include +#include "pgmstrings.h" + +// Satisfy the IDE, which needs to see the include statment in the ino too. +#ifdef dobogusinclude +#include +#include +#endif + +USB Usb; +USBHub Hub1(&Usb); +USBHub Hub2(&Usb); +USBHub Hub3(&Usb); +USBHub Hub4(&Usb); + +uint32_t next_time; + +void PrintAllAddresses(UsbDevice *pdev) +{ + UsbDeviceAddress adr; + adr.devAddress = pdev->address.devAddress; + Serial.print("\r\nAddr:"); + Serial.print(adr.devAddress, HEX); + Serial.print("("); + Serial.print(adr.bmHub, HEX); + Serial.print("."); + Serial.print(adr.bmParent, HEX); + Serial.print("."); + Serial.print(adr.bmAddress, HEX); + Serial.println(")"); +} + +void PrintAddress(uint8_t addr) +{ + UsbDeviceAddress adr; + adr.devAddress = addr; + Serial.print("\r\nADDR:\t"); + Serial.println(adr.devAddress, HEX); + Serial.print("DEV:\t"); + Serial.println(adr.bmAddress, HEX); + Serial.print("PRNT:\t"); + Serial.println(adr.bmParent, HEX); + Serial.print("HUB:\t"); + Serial.println(adr.bmHub, HEX); +} + +void setup() +{ + Serial.begin( 115200 ); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + Serial.println("Start"); + + if (Usb.Init() == -1) + Serial.println("OSC did not start."); + + delay( 200 ); + + next_time = millis() + 10000; +} + +byte getdevdescr( byte addr, byte &num_conf ); + +void PrintDescriptors(uint8_t addr) +{ + uint8_t rcode = 0; + byte num_conf = 0; + + rcode = getdevdescr( (byte)addr, num_conf ); + if ( rcode ) + { + printProgStr(Gen_Error_str); + print_hex( rcode, 8 ); + } + Serial.print("\r\n"); + + for (int i = 0; i < num_conf; i++) + { + rcode = getconfdescr( addr, i ); // get configuration descriptor + if ( rcode ) + { + printProgStr(Gen_Error_str); + print_hex(rcode, 8); + } + Serial.println("\r\n"); + } +} + +void PrintAllDescriptors(UsbDevice *pdev) +{ + Serial.println("\r\n"); + print_hex(pdev->address.devAddress, 8); + Serial.println("\r\n--"); + PrintDescriptors( pdev->address.devAddress ); +} + +void loop() +{ + Usb.Task(); + + if ( Usb.getUsbTaskState() == USB_STATE_RUNNING ) + { + if ((millis() - next_time) >= 0L) + { + Usb.ForEachUsbDevice(&PrintAllDescriptors); + Usb.ForEachUsbDevice(&PrintAllAddresses); + + while ( 1 ); //stop + } + } +} + +byte getdevdescr( byte addr, byte &num_conf ) +{ + USB_DEVICE_DESCRIPTOR buf; + byte rcode; + rcode = Usb.getDevDescr( addr, 0, 0x12, ( uint8_t *)&buf ); + if ( rcode ) { + return ( rcode ); + } + printProgStr(Dev_Header_str); + printProgStr(Dev_Length_str); + print_hex( buf.bLength, 8 ); + printProgStr(Dev_Type_str); + print_hex( buf.bDescriptorType, 8 ); + printProgStr(Dev_Version_str); + print_hex( buf.bcdUSB, 16 ); + printProgStr(Dev_Class_str); + print_hex( buf.bDeviceClass, 8 ); + printProgStr(Dev_Subclass_str); + print_hex( buf.bDeviceSubClass, 8 ); + printProgStr(Dev_Protocol_str); + print_hex( buf.bDeviceProtocol, 8 ); + printProgStr(Dev_Pktsize_str); + print_hex( buf.bMaxPacketSize0, 8 ); + printProgStr(Dev_Vendor_str); + print_hex( buf.idVendor, 16 ); + printProgStr(Dev_Product_str); + print_hex( buf.idProduct, 16 ); + printProgStr(Dev_Revision_str); + print_hex( buf.bcdDevice, 16 ); + printProgStr(Dev_Mfg_str); + print_hex( buf.iManufacturer, 8 ); + printProgStr(Dev_Prod_str); + print_hex( buf.iProduct, 8 ); + printProgStr(Dev_Serial_str); + print_hex( buf.iSerialNumber, 8 ); + printProgStr(Dev_Nconf_str); + print_hex( buf.bNumConfigurations, 8 ); + num_conf = buf.bNumConfigurations; + return ( 0 ); +} + +void printhubdescr(uint8_t *descrptr, uint8_t addr) +{ + HubDescriptor *pHub = (HubDescriptor*) descrptr; + uint8_t len = *((uint8_t*)descrptr); + + printProgStr(PSTR("\r\n\r\nHub Descriptor:\r\n")); + printProgStr(PSTR("bDescLength:\t\t")); + Serial.println(pHub->bDescLength, HEX); + + printProgStr(PSTR("bDescriptorType:\t")); + Serial.println(pHub->bDescriptorType, HEX); + + printProgStr(PSTR("bNbrPorts:\t\t")); + Serial.println(pHub->bNbrPorts, HEX); + + printProgStr(PSTR("LogPwrSwitchMode:\t")); + Serial.println(pHub->LogPwrSwitchMode, BIN); + + printProgStr(PSTR("CompoundDevice:\t\t")); + Serial.println(pHub->CompoundDevice, BIN); + + printProgStr(PSTR("OverCurrentProtectMode:\t")); + Serial.println(pHub->OverCurrentProtectMode, BIN); + + printProgStr(PSTR("TTThinkTime:\t\t")); + Serial.println(pHub->TTThinkTime, BIN); + + printProgStr(PSTR("PortIndicatorsSupported:")); + Serial.println(pHub->PortIndicatorsSupported, BIN); + + printProgStr(PSTR("Reserved:\t\t")); + Serial.println(pHub->Reserved, HEX); + + printProgStr(PSTR("bPwrOn2PwrGood:\t\t")); + Serial.println(pHub->bPwrOn2PwrGood, HEX); + + printProgStr(PSTR("bHubContrCurrent:\t")); + Serial.println(pHub->bHubContrCurrent, HEX); + + for (uint8_t i = 7; i < len; i++) + print_hex(descrptr[i], 8); + + //for (uint8_t i=1; i<=pHub->bNbrPorts; i++) + // PrintHubPortStatus(&Usb, addr, i, 1); +} + +byte getconfdescr( byte addr, byte conf ) +{ + uint8_t buf[ BUFSIZE ]; + uint8_t* buf_ptr = buf; + byte rcode; + byte descr_length; + byte descr_type; + unsigned int total_length; + rcode = Usb.getConfDescr( addr, 0, 4, conf, buf ); //get total length + LOBYTE( total_length ) = buf[ 2 ]; + HIBYTE( total_length ) = buf[ 3 ]; + if ( total_length > 256 ) { //check if total length is larger than buffer + printProgStr(Conf_Trunc_str); + total_length = 256; + } + rcode = Usb.getConfDescr( addr, 0, total_length, conf, buf ); //get the whole descriptor + while ( buf_ptr < buf + total_length ) { //parsing descriptors + descr_length = *( buf_ptr ); + descr_type = *( buf_ptr + 1 ); + switch ( descr_type ) { + case ( USB_DESCRIPTOR_CONFIGURATION ): + printconfdescr( buf_ptr ); + break; + case ( USB_DESCRIPTOR_INTERFACE ): + printintfdescr( buf_ptr ); + break; + case ( USB_DESCRIPTOR_ENDPOINT ): + printepdescr( buf_ptr ); + break; + case 0x29: + printhubdescr( buf_ptr, addr ); + break; + default: + printunkdescr( buf_ptr ); + break; + }//switch( descr_type + buf_ptr = ( buf_ptr + descr_length ); //advance buffer pointer + }//while( buf_ptr <=... + return ( rcode ); +} +/* prints hex numbers with leading zeroes */ +// copyright, Peter H Anderson, Baltimore, MD, Nov, '07 +// source: http://www.phanderson.com/arduino/arduino_display.html +void print_hex(int v, int num_places) +{ + int mask = 0, n, num_nibbles, digit; + + for (n = 1; n <= num_places; n++) { + mask = (mask << 1) | 0x0001; + } + v = v & mask; // truncate v to specified number of places + + num_nibbles = num_places / 4; + if ((num_places % 4) != 0) { + ++num_nibbles; + } + do { + digit = ((v >> (num_nibbles - 1) * 4)) & 0x0f; + Serial.print(digit, HEX); + } + while (--num_nibbles); +} +/* function to print configuration descriptor */ +void printconfdescr( uint8_t* descr_ptr ) +{ + USB_CONFIGURATION_DESCRIPTOR* conf_ptr = ( USB_CONFIGURATION_DESCRIPTOR* )descr_ptr; + printProgStr(Conf_Header_str); + printProgStr(Conf_Totlen_str); + print_hex( conf_ptr->wTotalLength, 16 ); + printProgStr(Conf_Nint_str); + print_hex( conf_ptr->bNumInterfaces, 8 ); + printProgStr(Conf_Value_str); + print_hex( conf_ptr->bConfigurationValue, 8 ); + printProgStr(Conf_String_str); + print_hex( conf_ptr->iConfiguration, 8 ); + printProgStr(Conf_Attr_str); + print_hex( conf_ptr->bmAttributes, 8 ); + printProgStr(Conf_Pwr_str); + print_hex( conf_ptr->bMaxPower, 8 ); + return; +} +/* function to print interface descriptor */ +void printintfdescr( uint8_t* descr_ptr ) +{ + USB_INTERFACE_DESCRIPTOR* intf_ptr = ( USB_INTERFACE_DESCRIPTOR* )descr_ptr; + printProgStr(Int_Header_str); + printProgStr(Int_Number_str); + print_hex( intf_ptr->bInterfaceNumber, 8 ); + printProgStr(Int_Alt_str); + print_hex( intf_ptr->bAlternateSetting, 8 ); + printProgStr(Int_Endpoints_str); + print_hex( intf_ptr->bNumEndpoints, 8 ); + printProgStr(Int_Class_str); + print_hex( intf_ptr->bInterfaceClass, 8 ); + printProgStr(Int_Subclass_str); + print_hex( intf_ptr->bInterfaceSubClass, 8 ); + printProgStr(Int_Protocol_str); + print_hex( intf_ptr->bInterfaceProtocol, 8 ); + printProgStr(Int_String_str); + print_hex( intf_ptr->iInterface, 8 ); + return; +} +/* function to print endpoint descriptor */ +void printepdescr( uint8_t* descr_ptr ) +{ + USB_ENDPOINT_DESCRIPTOR* ep_ptr = ( USB_ENDPOINT_DESCRIPTOR* )descr_ptr; + printProgStr(End_Header_str); + printProgStr(End_Address_str); + print_hex( ep_ptr->bEndpointAddress, 8 ); + printProgStr(End_Attr_str); + print_hex( ep_ptr->bmAttributes, 8 ); + printProgStr(End_Pktsize_str); + print_hex( ep_ptr->wMaxPacketSize, 16 ); + printProgStr(End_Interval_str); + print_hex( ep_ptr->bInterval, 8 ); + + return; +} +/*function to print unknown descriptor */ +void printunkdescr( uint8_t* descr_ptr ) +{ + byte length = *descr_ptr; + byte i; + printProgStr(Unk_Header_str); + printProgStr(Unk_Length_str); + print_hex( *descr_ptr, 8 ); + printProgStr(Unk_Type_str); + print_hex( *(descr_ptr + 1 ), 8 ); + printProgStr(Unk_Contents_str); + descr_ptr += 2; + for ( i = 0; i < length; i++ ) { + print_hex( *descr_ptr, 8 ); + descr_ptr++; + } +} + + +/* Print a string from Program Memory directly to save RAM */ +void printProgStr(const char* str) +{ + char c; + if (!str) return; + while ((c = pgm_read_byte(str++))) + Serial.print(c); +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/hub_demo/pgmstrings.h b/lib/usbhost/USB_Host_Shield_2.0/examples/hub_demo/pgmstrings.h new file mode 100644 index 0000000000..bdb0077ecc --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/hub_demo/pgmstrings.h @@ -0,0 +1,52 @@ +#if !defined(__PGMSTRINGS_H__) +#define __PGMSTRINGS_H__ + +#define LOBYTE(x) ((char*)(&(x)))[0] +#define HIBYTE(x) ((char*)(&(x)))[1] +#define BUFSIZE 256 //buffer size + + +/* Print strings in Program Memory */ +const char Gen_Error_str[] PROGMEM = "\r\nRequest error. Error code:\t"; +const char Dev_Header_str[] PROGMEM ="\r\nDevice descriptor: "; +const char Dev_Length_str[] PROGMEM ="\r\nDescriptor Length:\t"; +const char Dev_Type_str[] PROGMEM ="\r\nDescriptor type:\t"; +const char Dev_Version_str[] PROGMEM ="\r\nUSB version:\t\t"; +const char Dev_Class_str[] PROGMEM ="\r\nDevice class:\t\t"; +const char Dev_Subclass_str[] PROGMEM ="\r\nDevice Subclass:\t"; +const char Dev_Protocol_str[] PROGMEM ="\r\nDevice Protocol:\t"; +const char Dev_Pktsize_str[] PROGMEM ="\r\nMax.packet size:\t"; +const char Dev_Vendor_str[] PROGMEM ="\r\nVendor ID:\t\t"; +const char Dev_Product_str[] PROGMEM ="\r\nProduct ID:\t\t"; +const char Dev_Revision_str[] PROGMEM ="\r\nRevision ID:\t\t"; +const char Dev_Mfg_str[] PROGMEM ="\r\nMfg.string index:\t"; +const char Dev_Prod_str[] PROGMEM ="\r\nProd.string index:\t"; +const char Dev_Serial_str[] PROGMEM ="\r\nSerial number index:\t"; +const char Dev_Nconf_str[] PROGMEM ="\r\nNumber of conf.:\t"; +const char Conf_Trunc_str[] PROGMEM ="Total length truncated to 256 bytes"; +const char Conf_Header_str[] PROGMEM ="\r\nConfiguration descriptor:"; +const char Conf_Totlen_str[] PROGMEM ="\r\nTotal length:\t\t"; +const char Conf_Nint_str[] PROGMEM ="\r\nNum.intf:\t\t"; +const char Conf_Value_str[] PROGMEM ="\r\nConf.value:\t\t"; +const char Conf_String_str[] PROGMEM ="\r\nConf.string:\t\t"; +const char Conf_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t"; +const char Conf_Pwr_str[] PROGMEM ="\r\nMax.pwr:\t\t"; +const char Int_Header_str[] PROGMEM ="\r\n\r\nInterface descriptor:"; +const char Int_Number_str[] PROGMEM ="\r\nIntf.number:\t\t"; +const char Int_Alt_str[] PROGMEM ="\r\nAlt.:\t\t\t"; +const char Int_Endpoints_str[] PROGMEM ="\r\nEndpoints:\t\t"; +const char Int_Class_str[] PROGMEM ="\r\nIntf. Class:\t\t"; +const char Int_Subclass_str[] PROGMEM ="\r\nIntf. Subclass:\t\t"; +const char Int_Protocol_str[] PROGMEM ="\r\nIntf. Protocol:\t\t"; +const char Int_String_str[] PROGMEM ="\r\nIntf.string:\t\t"; +const char End_Header_str[] PROGMEM ="\r\n\r\nEndpoint descriptor:"; +const char End_Address_str[] PROGMEM ="\r\nEndpoint address:\t"; +const char End_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t"; +const char End_Pktsize_str[] PROGMEM ="\r\nMax.pkt size:\t\t"; +const char End_Interval_str[] PROGMEM ="\r\nPolling interval:\t"; +const char Unk_Header_str[] PROGMEM = "\r\nUnknown descriptor:"; +const char Unk_Length_str[] PROGMEM ="\r\nLength:\t\t"; +const char Unk_Type_str[] PROGMEM ="\r\nType:\t\t"; +const char Unk_Contents_str[] PROGMEM ="\r\nContents:\t"; + +#endif // __PGMSTRINGS_H__ \ No newline at end of file diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/max_LCD/max_LCD.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/max_LCD/max_LCD.ino new file mode 100644 index 0000000000..6603ab90db --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/max_LCD/max_LCD.ino @@ -0,0 +1,29 @@ +// Just a copy of the HelloWorld example bundled with the LiquidCrystal library in the Arduino IDE + +// HD44780 compatible LCD display via MAX3421E GPOUT support header +// pinout: D[4-7] -> GPOUT[4-7], RS-> GPOUT[2], E ->GPOUT[3] + +#include + +// Satisfy IDE, which only needs to see the include statment in the ino. +#ifdef dobogusinclude +#include +#include +#endif + +USB Usb; +Max_LCD lcd(&Usb); + +void setup() { + // Set up the LCD's number of columns and rows: + lcd.begin(16, 2); + // Print a message to the LCD. + lcd.print("Hello, World!"); +} + +void loop() { + // Set the cursor to column 0, line 1 (note: line 1 is the second row, since counting begins with 0): + lcd.setCursor(0, 1); + // Print the number of seconds since reset: + lcd.print(millis() / 1000); +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/pl2303/pl2303_gprs_terminal/pl2303_gprs_terminal.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/pl2303/pl2303_gprs_terminal/pl2303_gprs_terminal.ino new file mode 100644 index 0000000000..7c4c9f6cbe --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/pl2303/pl2303_gprs_terminal/pl2303_gprs_terminal.ino @@ -0,0 +1,101 @@ +/* Arduino terminal for PL2303 USB to serial converter and DealeXtreme GPRS modem. */ +/* USB support */ +#include +/* CDC support */ +#include +#include + +// Satisfy the IDE, which needs to see the include statment in the ino too. +#ifdef dobogusinclude +#include +#include +#endif + +class PLAsyncOper : public CDCAsyncOper +{ +public: + uint8_t OnInit(ACM *pacm); +}; + +uint8_t PLAsyncOper::OnInit(ACM *pacm) +{ + uint8_t rcode; + + // Set DTR = 1 + rcode = pacm->SetControlLineState(1); + + if (rcode) + { + ErrorMessage(PSTR("SetControlLineState"), rcode); + return rcode; + } + + LINE_CODING lc; + //lc.dwDTERate = 9600; + lc.dwDTERate = 115200; + lc.bCharFormat = 0; + lc.bParityType = 0; + lc.bDataBits = 8; + + rcode = pacm->SetLineCoding(&lc); + + if (rcode) + ErrorMessage(PSTR("SetLineCoding"), rcode); + + return rcode; +} +USB Usb; +//USBHub Hub(&Usb); +PLAsyncOper AsyncOper; +PL2303 Pl(&Usb, &AsyncOper); + +void setup() +{ + Serial.begin( 115200 ); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + Serial.println("Start"); + + if (Usb.Init() == -1) + Serial.println("OSCOKIRQ failed to assert"); + + delay( 200 ); +} + +void loop() +{ + Usb.Task(); + + if( Usb.getUsbTaskState() == USB_STATE_RUNNING ) + { + uint8_t rcode; + + /* reading the keyboard */ + if(Serial.available()) { + uint8_t data= Serial.read(); + + /* sending to the phone */ + rcode = Pl.SndData(1, &data); + if (rcode) + ErrorMessage(PSTR("SndData"), rcode); + }//if(Serial.available()... + + /* reading the converter */ + /* buffer size must be greater or equal to max.packet size */ + /* it it set to 64 (largest possible max.packet size) here, can be tuned down + for particular endpoint */ + uint8_t buf[64]; + uint16_t rcvd = 64; + rcode = Pl.RcvData(&rcvd, buf); + if (rcode && rcode != hrNAK) + ErrorMessage(PSTR("Ret"), rcode); + + if( rcvd ) { //more than zero bytes received + for(uint16_t i=0; i < rcvd; i++ ) { + Serial.print((char)buf[i]); //printing on the screen + } + }//if( rcvd ... + }//if( Usb.getUsbTaskState() == USB_STATE_RUNNING.. +} + diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/pl2303/pl2303_gps/pl2303_gps.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/pl2303/pl2303_gps/pl2303_gps.ino new file mode 100644 index 0000000000..e8c8a02230 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/pl2303/pl2303_gps/pl2303_gps.ino @@ -0,0 +1,88 @@ +/* USB Host to PL2303-based USB GPS unit interface */ +/* Navibee GM720 receiver - Sirf Star III */ +/* USB support */ +#include +/* CDC support */ +#include +#include + +// Satisfy the IDE, which needs to see the include statment in the ino too. +#ifdef dobogusinclude +#include +#include +#endif + +class PLAsyncOper : public CDCAsyncOper { +public: + uint8_t OnInit(ACM *pacm); +}; + +uint8_t PLAsyncOper::OnInit(ACM *pacm) { + uint8_t rcode; + + // Set DTR = 1 + rcode = pacm->SetControlLineState(1); + + if(rcode) { + ErrorMessage(PSTR("SetControlLineState"), rcode); + return rcode; + } + + LINE_CODING lc; + lc.dwDTERate = 4800; //default serial speed of GPS unit + lc.bCharFormat = 0; + lc.bParityType = 0; + lc.bDataBits = 8; + + rcode = pacm->SetLineCoding(&lc); + + if(rcode) + ErrorMessage(PSTR("SetLineCoding"), rcode); + + return rcode; +} + +USB Usb; +USBHub Hub(&Usb); +PLAsyncOper AsyncOper; +PL2303 Pl(&Usb, &AsyncOper); +uint32_t read_delay; +#define READ_DELAY 100 + +void setup() { + Serial.begin(115200); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + Serial.println("Start"); + + if(Usb.Init() == -1) + Serial.println("OSCOKIRQ failed to assert"); + + delay(200); +} + +void loop() { + uint8_t rcode; + uint8_t buf[64]; //serial buffer equals Max.packet size of bulk-IN endpoint + uint16_t rcvd = 64; + + Usb.Task(); + + if(Pl.isReady()) { + /* reading the GPS */ + if((long)(millis() - read_delay) >= 0L) { + read_delay += READ_DELAY; + rcode = Pl.RcvData(&rcvd, buf); + if(rcode && rcode != hrNAK) + ErrorMessage(PSTR("Ret"), rcode); + if(rcvd) { //more than zero bytes received + for(uint16_t i = 0; i < rcvd; i++) { + Serial.print((char)buf[i]); //printing on the screen + }//for( uint16_t i=0; i < rcvd; i++... + }//if( rcvd + }//if( read_delay > millis()... + }//if( Usb.getUsbTaskState() == USB_STATE_RUNNING.. +} + + diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/pl2303/pl2303_tinygps/pl2303_tinygps.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/pl2303/pl2303_tinygps/pl2303_tinygps.ino new file mode 100644 index 0000000000..d527eabe00 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/pl2303/pl2303_tinygps/pl2303_tinygps.ino @@ -0,0 +1,217 @@ +/* USB Host to PL2303-based USB GPS unit interface */ +/* Navibee GM720 receiver - Sirf Star III */ +/* Mikal Hart's TinyGPS library */ +/* test_with_gps_device library example modified for PL2302 access */ + +/* USB support */ +#include + +/* CDC support */ +#include +#include + +#include + +// Satisfy the IDE, which needs to see the include statment in the ino too. +#ifdef dobogusinclude +#include +#include +#endif + +/* This sample code demonstrates the normal use of a TinyGPS object. + Modified to be used with USB Host Shield Library r2.0 + and USB Host Shield 2.0 +*/ + +class PLAsyncOper : public CDCAsyncOper +{ +public: + uint8_t OnInit(ACM *pacm); +}; + +uint8_t PLAsyncOper::OnInit(ACM *pacm) +{ + uint8_t rcode; + + // Set DTR = 1 + rcode = pacm->SetControlLineState(1); + + if (rcode) { + ErrorMessage(PSTR("SetControlLineState"), rcode); + return rcode; + } + + LINE_CODING lc; + lc.dwDTERate = 4800; //default serial speed of GPS unit + lc.bCharFormat = 0; + lc.bParityType = 0; + lc.bDataBits = 8; + + rcode = pacm->SetLineCoding(&lc); + + if (rcode) { + ErrorMessage(PSTR("SetLineCoding"), rcode); + } + + return rcode; +} + +USB Usb; +//USBHub Hub(&Usb); +PLAsyncOper AsyncOper; +PL2303 Pl(&Usb, &AsyncOper); +TinyGPS gps; + +void gpsdump(TinyGPS &gps); +bool feedgps(); +void printFloat(double f, int digits = 2); + +void setup() +{ + + Serial.begin(115200); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + + Serial.print("Testing TinyGPS library v. "); Serial.println(TinyGPS::library_version()); + Serial.println("by Mikal Hart"); + Serial.println(); + Serial.print("Sizeof(gpsobject) = "); Serial.println(sizeof(TinyGPS)); + Serial.println(); + /* USB Initialization */ + if (Usb.Init() == -1) { + Serial.println("OSCOKIRQ failed to assert"); + } + + delay( 200 ); +} + +void loop() +{ + Usb.Task(); + + if( Pl.isReady()) { + + bool newdata = false; + unsigned long start = millis(); + + // Every 5 seconds we print an update + while (millis() - start < 5000) { + if( feedgps()) { + newdata = true; + } + }//while (millis()... + + if (newdata) { + Serial.println("Acquired Data"); + Serial.println("-------------"); + gpsdump(gps); + Serial.println("-------------"); + Serial.println(); + }//if( newdata... + }//if( Usb.getUsbTaskState() == USB_STATE_RUNNING... +} + +void printFloat(double number, int digits) +{ + // Handle negative numbers + if (number < 0.0) + { + Serial.print('-'); + number = -number; + } + + // Round correctly so that print(1.999, 2) prints as "2.00" + double rounding = 0.5; + for (uint8_t i=0; i 0) + Serial.print("."); + + // Extract digits from the remainder one at a time + while (digits-- > 0) + { + remainder *= 10.0; + int toPrint = int(remainder); + Serial.print(toPrint); + remainder -= toPrint; + } +} + +void gpsdump(TinyGPS &gps) +{ + long lat, lon; + float flat, flon; + unsigned long age, date, time, chars; + int year; + byte month, day, hour, minute, second, hundredths; + unsigned short sentences, failed; + + gps.get_position(&lat, &lon, &age); + Serial.print("Lat/Long(10^-5 deg): "); Serial.print(lat); Serial.print(", "); Serial.print(lon); + Serial.print(" Fix age: "); Serial.print(age); Serial.println("ms."); + + feedgps(); // If we don't feed the gps during this long routine, we may drop characters and get checksum errors + + gps.f_get_position(&flat, &flon, &age); + Serial.print("Lat/Long(float): "); printFloat(flat, 5); Serial.print(", "); printFloat(flon, 5); + Serial.print(" Fix age: "); Serial.print(age); Serial.println("ms."); + + feedgps(); + + gps.get_datetime(&date, &time, &age); + Serial.print("Date(ddmmyy): "); Serial.print(date); Serial.print(" Time(hhmmsscc): "); Serial.print(time); + Serial.print(" Fix age: "); Serial.print(age); Serial.println("ms."); + + feedgps(); + + gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age); + Serial.print("Date: "); Serial.print(static_cast(month)); Serial.print("/"); Serial.print(static_cast(day)); Serial.print("/"); Serial.print(year); + Serial.print(" Time: "); Serial.print(static_cast(hour)); Serial.print(":"); Serial.print(static_cast(minute)); Serial.print(":"); Serial.print(static_cast(second)); Serial.print("."); Serial.print(static_cast(hundredths)); + Serial.print(" Fix age: "); Serial.print(age); Serial.println("ms."); + + feedgps(); + + Serial.print("Alt(cm): "); Serial.print(gps.altitude()); Serial.print(" Course(10^-2 deg): "); Serial.print(gps.course()); Serial.print(" Speed(10^-2 knots): "); Serial.println(gps.speed()); + Serial.print("Alt(float): "); printFloat(gps.f_altitude()); Serial.print(" Course(float): "); printFloat(gps.f_course()); Serial.println(); + Serial.print("Speed(knots): "); printFloat(gps.f_speed_knots()); Serial.print(" (mph): "); printFloat(gps.f_speed_mph()); + Serial.print(" (mps): "); printFloat(gps.f_speed_mps()); Serial.print(" (kmph): "); printFloat(gps.f_speed_kmph()); Serial.println(); + + feedgps(); + + gps.stats(&chars, &sentences, &failed); + Serial.print("Stats: characters: "); Serial.print(chars); Serial.print(" sentences: "); Serial.print(sentences); Serial.print(" failed checksum: "); Serial.println(failed); +} + +bool feedgps() +{ + uint8_t rcode; + uint8_t buf[64]; //serial buffer equals Max.packet size of bulk-IN endpoint + uint16_t rcvd = 64; + { + /* reading the GPS */ + rcode = Pl.RcvData(&rcvd, buf); + if (rcode && rcode != hrNAK) + ErrorMessage(PSTR("Ret"), rcode); + rcode = false; + if( rcvd ) { //more than zero bytes received + for( uint16_t i=0; i < rcvd; i++ ) { + if( gps.encode((char)buf[i])) { //feed a character to gps object + rcode = true; + }//if( gps.encode(buf[i]... + }//for( uint16_t i=0; i < rcvd; i++... + }//if( rcvd... + } + return( rcode ); +} + diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/pl2303/pl2303_xbee_terminal/pl2303_xbee_terminal.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/pl2303/pl2303_xbee_terminal/pl2303_xbee_terminal.ino new file mode 100644 index 0000000000..67b7dab603 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/pl2303/pl2303_xbee_terminal/pl2303_xbee_terminal.ino @@ -0,0 +1,117 @@ +/* Arduino terminal for PL2303 USB to serial converter and XBee radio. */ +/* Inserts linefeed after carriage return in data sent to and received from Xbee */ +/* USB support */ +#include +/* CDC support */ +#include +#include + +// Satisfy the IDE, which needs to see the include statment in the ino too. +#ifdef dobogusinclude +#include +#include +#endif + +class PLAsyncOper : public CDCAsyncOper +{ +public: + uint8_t OnInit(ACM *pacm); +}; + +uint8_t PLAsyncOper::OnInit(ACM *pacm) +{ + uint8_t rcode; + + // Set DTR = 1 + rcode = pacm->SetControlLineState(1); + + if (rcode) + { + ErrorMessage(PSTR("SetControlLineState"), rcode); + return rcode; + } + + LINE_CODING lc; + lc.dwDTERate = 115200; + lc.bCharFormat = 0; + lc.bParityType = 0; + lc.bDataBits = 8; + + rcode = pacm->SetLineCoding(&lc); + + if (rcode) + ErrorMessage(PSTR("SetLineCoding"), rcode); + + return rcode; +} +USB Usb; +//USBHub Hub(&Usb); +PLAsyncOper AsyncOper; +PL2303 Pl(&Usb, &AsyncOper); + +void setup() +{ + Serial.begin( 115200 ); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + Serial.println("Start"); + + if (Usb.Init() == -1) + Serial.println("OSCOKIRQ failed to assert"); + + delay( 200 ); +} + +void loop() +{ + Usb.Task(); + + if( Usb.getUsbTaskState() == USB_STATE_RUNNING ) + { + uint8_t rcode; + + /* reading the keyboard */ + if(Serial.available()) { + uint8_t data= Serial.read(); + + if ( data == '\r' ) { + Serial.print("\r\n"); //insert linefeed + } + else { + Serial.print( data ); //echo back to the screen + } + + /* sending to the phone */ + rcode = Pl.SndData(1, &data); + if (rcode) + ErrorMessage(PSTR("SndData"), rcode); + }//if(Serial.available()... + + delay(50); + + /* reading the converter */ + /* buffer size must be greater or equal to max.packet size */ + /* it it set to 64 (largest possible max.packet size) here, can be tuned down + for particular endpoint */ + uint8_t buf[64]; + uint16_t rcvd = 64; + rcode = Pl.RcvData(&rcvd, buf); + if (rcode && rcode != hrNAK) + ErrorMessage(PSTR("Ret"), rcode); + + if( rcvd ) { //more than zero bytes received + for(uint16_t i=0; i < rcvd; i++ ) { + if( buf[i] =='\r' ) { + Serial.print("\r\n"); //insert linefeed + } + else { + Serial.print((char)buf[i]); //printing on the screen + } + } + } + delay(10); + }//if( Usb.getUsbTaskState() == USB_STATE_RUNNING.. +} + + diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/testusbhostFAT/Makefile b/lib/usbhost/USB_Host_Shield_2.0/examples/testusbhostFAT/Makefile new file mode 100644 index 0000000000..8a12ddc047 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/testusbhostFAT/Makefile @@ -0,0 +1,64 @@ +# +# These are set for a mega 1280 + quadram plus my serial patch. +# If you lack quadram, or want to disable LFN, just change _FS_TINY=1 _USE_LFN=0 +# +# If your board is a mega 2560 comment out the following two lines +BOARD = mega + +BOARD_SUB = mega.menu.cpu.atmega1280 +PROGRAMMER = arduino + +# ...and then uncomment out the following two lines +#BOARD_SUB = mega.menu.cpu.atmega2560 +#PROGRAMMER = wiring + +#BOARD = teensypp2 +#BOARD = teensy3 +#BOARD = teensy31 + +# set your Arduino tty port here +PORT = /dev/ttyUSB0 + +EXTRA_FLAGS = -D _USE_LFN=3 + +# change to 0 if you have quadram to take advantage of caching FAT +EXTRA_FLAGS += -D _FS_TINY=1 + + +EXTRA_FLAGS += -D _MAX_SS=512 + + +# Don't worry if you don't have external RAM, xmem2 detects this situation. +# You *WILL* be wanting to get some kind of external ram on your mega in order to +# do anything that is intense. +EXTRA_FLAGS += -D EXT_RAM_STACK=1 +EXTRA_FLAGS += -D EXT_RAM_HEAP=1 + + +# These are no longer needed for the demo to work. +# In the event you need more ram, uncomment these 3 lines. +#EXTRA_FLAGS += -D DISABLE_SERIAL1 +#EXTRA_FLAGS += -D DISABLE_SERIAL2 +#EXTRA_FLAGS += -D DISABLE_SERIAL3 + +# +# Advanced debug on Serial3 +# + +# uncomment the next two to enable debug on Serial3 +EXTRA_FLAGS += -D USB_HOST_SERIAL=Serial3 +#EXTRA_FLAGS += -D DEBUG_USB_HOST + +# The following are the libraries used. +LIB_DIRS += ../../ +LIB_DIRS += ../testusbhostFAT/xmem2 +LIB_DIRS += ../testusbhostFAT/generic_storage +LIB_DIRS += ../testusbhostFAT/RTClib +LIB_DIRS += $(ARD_HOME)/libraries/Wire +LIB_DIRS += $(ARD_HOME)/libraries/Wire/utility +LIB_DIRS += $(ARD_HOME)/hardware/arduino/$(BUILD_ARCH)/libraries/Wire +LIB_DIRS += $(ARD_HOME)/hardware/arduino/$(BUILD_ARCH)/libraries/Wire/utility +LIB_DIRS += $(ARD_HOME)/hardware/arduino/$(BUILD_ARCH)/libraries/SPI + +# And finally, the part that brings everything together for you. +include Arduino_Makefile_master/_Makefile.master diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/testusbhostFAT/README.md b/lib/usbhost/USB_Host_Shield_2.0/examples/testusbhostFAT/README.md new file mode 100644 index 0000000000..0f2a734a65 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/testusbhostFAT/README.md @@ -0,0 +1,29 @@ +This small sketch tests the USB host shield mass storage library. + +__Note:__ This will not run a Arduino Uno due to the limited ram available in the ATmega328p. + +The Arduino Mega (ATmega1280) and the Arduino Mega 2560 (ATmega2560) are confirmed to work with this test code. + +To compile this example you will need the following libraries as well: + +* [xmem2](https://github.com/xxxajk/xmem2) +* [generic_storage FATfs](https://github.com/xxxajk/generic_storage) +* [RTClib](https://github.com/xxxajk/RTClib) + +The following shield is recommended for larger projects: . + +You may use the bundled [Makefile](Makefile) to compile the code instead of the Arduino IDE if you have problems or want a smaller binary. The master makefile is bundled as a submodule, but can also be downloaded manually at the following link: . + +To download the USB Host library and all the needed libraries for this test. + +Run the following command in a terminal application: + +``` +git clone --recursive https://github.com/felis/USB_Host_Shield_2.0 +``` + +If you want to update all the submodules run: + +``` +git submodule foreach --recursive git pull origin master +``` diff --git a/lib/usbhost/USB_Host_Shield_2.0/examples/testusbhostFAT/testusbhostFAT.ino b/lib/usbhost/USB_Host_Shield_2.0/examples/testusbhostFAT/testusbhostFAT.ino new file mode 100644 index 0000000000..e8b9cd3592 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/examples/testusbhostFAT/testusbhostFAT.ino @@ -0,0 +1,736 @@ +/* + * Mega + USB storage + optional DS1307 + optional expansion RAM + funky status LED, + * Includes interactive debug level setting, and supports hot-plug. + * + * IMPORTANT! PLEASE USE Arduino 1.0.5 or better! + * Older versions HAVE MAJOR BUGS AND WILL NOT WORK AT ALL! + * Use of gcc-avr and lib-c that is newer than the Arduino version is even better. + * If you experience random crashes, use make. + * The options that the IDE use can generate bad code and cause the AVR to crash. + * + * This sketch requires the following libraries: + * https://github.com/felis/USB_Host_Shield_2.0 Install as 'USB_Host_Shield_2_0' + * https://github.com/xxxajk/xmem2 Install as 'xmem', provides memory services. + * https://github.com/xxxajk/generic_storage provides access to FAT file system. + * https://github.com/xxxajk/RTClib provides access to DS1307, or fake clock. + * + * Optional, to use the Makefile (Recommended! See above!): + * https://github.com/xxxajk/Arduino_Makefile_master + * + */ + +///////////////////////////////////////////////////////////// +// Please Note: // +// This section is for info with the Arduino IDE ONLY. // +// Unfortunately due to short sightedness of the Arduino // +// code team, that you must set the following in the // +// respective libraries. // +// Changing them here will have _NO_ effect! // +///////////////////////////////////////////////////////////// + +// Uncomment to enable debugging +//#define DEBUG_USB_HOST +// This is where stderr/USB debugging goes to +//#define USB_HOST_SERIAL Serial3 + +// If you have external memory, setting this to 0 enables FAT table caches. +// The 0 setting is recommended only if you have external memory. +//#define _FS_TINY 1 + +//#define _USE_LFN 3 +//#define _MAX_SS 512 + + +///////////////////////////////////////////////////////////// +// End of Arduino IDE specific information // +///////////////////////////////////////////////////////////// + +// You can set this to 0 if you are not using a USB hub. +// It will save a little bit of flash and RAM. +// Set to 1 if you want to use a hub. +#define WANT_HUB_TEST 1 + +// this is for XMEM2 +#define EXT_RAM_STACK 1 +#define EXT_RAM_HEAP 1 +#define LOAD_XMEM + +#if defined(CORE_TEENSY) && !defined(_AVR_) +#include +#include +#endif + +#if defined(__AVR__) +#include +#include +#elif defined(ARDUINO_ARCH_SAM) +#include +#endif + +#if WANT_HUB_TEST +#include +#endif +#include +#define LOAD_RTCLIB +#include +#include +#include +#include +#include +#include +#include +#if defined(__AVR__) +static FILE tty_stdio; +static FILE tty_stderr; +volatile uint32_t LEDnext_time; // fade timeout +volatile uint32_t HEAPnext_time; // when to print out next heap report +volatile int brightness = 0; // how bright the LED is +volatile int fadeAmount = 80; // how many points to fade the LED by +#endif + +USB Usb; + +volatile uint8_t current_state = 1; +volatile uint8_t last_state = 0; +volatile bool fatready = false; +volatile bool partsready = false; +volatile bool notified = false; +volatile bool runtest = false; +volatile bool usbon = false; +volatile uint32_t usbon_time; +volatile bool change = false; +volatile bool reportlvl = false; +int cpart = 0; +PCPartition *PT; + +#if WANT_HUB_TEST +#define MAX_HUBS 1 +USBHub *Hubs[MAX_HUBS]; +#endif + +static PFAT *Fats[_VOLUMES]; +static part_t parts[_VOLUMES]; +static storage_t sto[_VOLUMES]; + +/*make sure this is a power of two. */ +#define mbxs 128 +static uint8_t My_Buff_x[mbxs]; /* File read buffer */ + +#if defined(__AVR__) + +#define prescale1 ((1 << WGM12) | (1 << CS10)) +#define prescale8 ((1 << WGM12) | (1 << CS11)) +#define prescale64 ((1 << WGM12) | (1 << CS10) | (1 << CS11)) +#define prescale256 ((1 << WGM12) | (1 << CS12)) +#define prescale1024 ((1 << WGM12) | (1 << CS12) | (1 << CS10)) + +extern "C" { + extern unsigned int freeHeap(); +} +static int tty_stderr_putc(char c, FILE *t) { + USB_HOST_SERIAL.write(c); + return 0; +} + +static int __attribute__((unused)) tty_stderr_flush(FILE *t) { + USB_HOST_SERIAL.flush(); + return 0; +} + +static int tty_std_putc(char c, FILE *t) { + Serial.write(c); + return 0; +} + +static int tty_std_getc(FILE *t) { + while(!Serial.available()); + return Serial.read(); +} + +static int __attribute__((unused)) tty_std_flush(FILE *t) { + Serial.flush(); + return 0; +} + +#else +// Supposedly the DUE has stdio already pointing to serial... +#if !defined(ARDUINO_ARCH_SAM) +// But newlib needs this... +extern "C" { + int _write(int fd, const char *ptr, int len) { + int j; + for(j = 0; j < len; j++) { + if(fd == 1) + Serial.write(*ptr++); + else if(fd == 2) + USB_HOST_SERIAL.write(*ptr++); + } + return len; + } + + int _read(int fd, char *ptr, int len) { + if(len > 0 && fd == 0) { + while(!Serial.available()); + *ptr = Serial.read(); + return 1; + } + return 0; + } + +#include + + int _fstat(int fd, struct stat *st) { + memset(st, 0, sizeof (*st)); + st->st_mode = S_IFCHR; + st->st_blksize = 1024; + return 0; + } + + int _isatty(int fd) { + return (fd < 3) ? 1 : 0; + } +} +#endif // !defined(ARDUINO_ARCH_SAM) +#endif + +void setup() { + bool serr = false; + for(int i = 0; i < _VOLUMES; i++) { + Fats[i] = NULL; + sto[i].private_data = new pvt_t; + ((pvt_t *)sto[i].private_data)->B = 255; // impossible + } + // Set this to higher values to enable more debug information + // minimum 0x00, maximum 0xff + UsbDEBUGlvl = 0x81; + +#if !defined(CORE_TEENSY) && defined(__AVR__) + // make LED pin as an output: + pinMode(LED_BUILTIN, OUTPUT); + pinMode(2, OUTPUT); + // Ensure TX is off + _SFR_BYTE(UCSR0B) &= ~_BV(TXEN0); + // Initialize 'debug' serial port + USB_HOST_SERIAL.begin(115200); + // Do not start primary Serial port if already started. + if(bit_is_clear(UCSR0B, TXEN0)) { + Serial.begin(115200); + serr = true; + } + + + // Blink LED + delay(500); + analogWrite(LED_BUILTIN, 255); + delay(500); + analogWrite(LED_BUILTIN, 0); + delay(500); +#else + while(!Serial); + Serial.begin(115200); // On the Teensy 3.x we get a delay at least! +#endif +#if defined(__AVR__) + // Set up stdio/stderr + tty_stdio.put = tty_std_putc; + tty_stdio.get = tty_std_getc; + tty_stdio.flags = _FDEV_SETUP_RW; + tty_stdio.udata = 0; + + tty_stderr.put = tty_stderr_putc; + tty_stderr.get = NULL; + tty_stderr.flags = _FDEV_SETUP_WRITE; + tty_stderr.udata = 0; + + stdout = &tty_stdio; + stdin = &tty_stdio; + stderr = &tty_stderr; +#endif + printf_P(PSTR("\r\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nStart\r\n")); + printf_P(PSTR("Current UsbDEBUGlvl %02x\r\n"), UsbDEBUGlvl); + printf_P(PSTR("'+' and '-' increase/decrease by 0x01\r\n")); + printf_P(PSTR("'.' and ',' increase/decrease by 0x10\r\n")); + printf_P(PSTR("'t' will run a 10MB write/read test and print out the time it took.\r\n")); + printf_P(PSTR("'e' will toggle vbus off for a few moments.\r\n\r\n")); + printf_P(PSTR("Long filename support: " +#if _USE_LFN + "Enabled" +#else + "Disabled" +#endif + "\r\n")); + if(serr) { + fprintf_P(stderr, PSTR("\r\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nStart\r\n")); + fprintf_P(stderr, PSTR("Current UsbDEBUGlvl %02x\r\n"), UsbDEBUGlvl); + fprintf_P(stderr, PSTR("Long filename support: " +#if _USE_LFN + "Enabled" +#else + "Disabled" +#endif + "\r\n")); + } + +#if !defined(CORE_TEENSY) && defined(__AVR__) + analogWrite(LED_BUILTIN, 255); + delay(500); + analogWrite(LED_BUILTIN, 0); + delay(500); + analogWrite(LED_BUILTIN, 255); + delay(500); + analogWrite(LED_BUILTIN, 0); + delay(500); + analogWrite(LED_BUILTIN, 255); + delay(500); + analogWrite(LED_BUILTIN, 0); + delay(500); + + LEDnext_time = millis() + 1; +#if EXT_RAM + printf_P(PSTR("Total EXT RAM banks %i\r\n"), xmem::getTotalBanks()); +#endif + printf_P(PSTR("Available heap: %u Bytes\r\n"), freeHeap()); + printf_P(PSTR("SP %x\r\n"), (uint8_t *)(SP)); +#endif + + // Even though I'm not going to actually be deleting, + // I want to be able to have slightly more control. + // Besides, it is easier to initialize stuff... +#if WANT_HUB_TEST + for(int i = 0; i < MAX_HUBS; i++) { + Hubs[i] = new USBHub(&Usb); +#if defined(__AVR__) + printf_P(PSTR("Available heap: %u Bytes\r\n"), freeHeap()); +#endif + } +#endif + // Initialize generic storage. This must be done before USB starts. + Init_Generic_Storage(); + + while(Usb.Init(1000) == -1) { + printf_P(PSTR("No USB HOST Shield?\r\n")); + Notify(PSTR("OSC did not start."), 0x40); + } + +#if !defined(CORE_TEENSY) && defined(__AVR__) + cli(); + TCCR3A = 0; + TCCR3B = 0; + // (0.01/(1/((16 *(10^6)) / 8))) - 1 = 19999 + OCR3A = 19999; + TCCR3B |= prescale8; + TIMSK3 |= (1 << OCIE1A); + sei(); + + HEAPnext_time = millis() + 10000; +#endif +#if defined(__AVR__) + HEAPnext_time = millis() + 10000; +#endif +} + +void serialEvent() { + // Adjust UsbDEBUGlvl level on-the-fly. + // + to increase, - to decrease, * to display current level. + // . to increase by 16, , to decrease by 16 + // e to flick VBUS + // * to report debug level + if(Serial.available()) { + int inByte = Serial.read(); + switch(inByte) { + case '+': + if(UsbDEBUGlvl < 0xff) UsbDEBUGlvl++; + reportlvl = true; + break; + case '-': + if(UsbDEBUGlvl > 0x00) UsbDEBUGlvl--; + reportlvl = true; + break; + case '.': + if(UsbDEBUGlvl < 0xf0) UsbDEBUGlvl += 16; + reportlvl = true; + break; + case ',': + if(UsbDEBUGlvl > 0x0f) UsbDEBUGlvl -= 16; + reportlvl = true; + break; + case '*': + reportlvl = true; + break; + case 't': + runtest = true; + break; + case 'e': + change = true; + usbon = false; + break; + } + } +} + +#if !defined(CORE_TEENSY) && defined(__AVR__) +// ALL teensy versions LACK PWM ON LED + +ISR(TIMER3_COMPA_vect) { + if((long)(millis() - LEDnext_time) >= 0L) { + LEDnext_time = millis() + 30; + + // set the brightness of LED + analogWrite(LED_BUILTIN, brightness); + + // change the brightness for next time through the loop: + brightness = brightness + fadeAmount; + + // reverse the direction of the fading at the ends of the fade: + if(brightness <= 0) { + brightness = 0; + fadeAmount = -fadeAmount; + } + if(brightness >= 255) { + brightness = 255; + fadeAmount = -fadeAmount; + } + } +} +#endif + +bool isfat(uint8_t t) { + return (t == 0x01 || t == 0x04 || t == 0x06 || t == 0x0b || t == 0x0c || t == 0x0e || t == 0x1); +} + +void die(FRESULT rc) { + printf_P(PSTR("Failed with rc=%u.\r\n"), rc); + //for (;;); +} + +void loop() { + FIL My_File_Object_x; /* File object */ + +#if defined(__AVR__) + // Print a heap status report about every 10 seconds. + if((long)(millis() - HEAPnext_time) >= 0L) { + if(UsbDEBUGlvl > 0x50) { + printf_P(PSTR("Available heap: %u Bytes\r\n"), freeHeap()); + } + HEAPnext_time = millis() + 10000; + } + TCCR3B = 0; +#endif +#if defined(CORE_TEENSY) + // Teensy suffers here, oh well... + serialEvent(); +#endif + // Horrid! This sort of thing really belongs in an ISR, not here! + // We also will be needing to test each hub port, we don't do this yet! + if(!change && !usbon && (long)(millis() - usbon_time) >= 0L) { + change = true; + usbon = true; + } + + if(change) { + change = false; + if(usbon) { + Usb.vbusPower(vbus_on); + printf_P(PSTR("VBUS on\r\n")); + } else { + Usb.vbusPower(vbus_off); + usbon_time = millis() + 2000; + } + } + Usb.Task(); + current_state = Usb.getUsbTaskState(); + if(current_state != last_state) { + if(UsbDEBUGlvl > 0x50) + printf_P(PSTR("USB state = %x\r\n"), current_state); +#if !defined(CORE_TEENSY) && defined(__AVR__) + if(current_state == USB_STATE_RUNNING) { + fadeAmount = 30; + } +#endif + if(current_state == USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE) { +#if !defined(CORE_TEENSY) && defined(__AVR__) + fadeAmount = 80; +#endif + partsready = false; + for(int i = 0; i < cpart; i++) { + if(Fats[i] != NULL) + delete Fats[i]; + Fats[i] = NULL; + } + fatready = false; + notified = false; + cpart = 0; + } + last_state = current_state; + } + + // only do any of this if usb is on + if(usbon) { + if(partsready && !fatready) { + if(cpart > 0) fatready = true; + } + // This is horrible, and needs to be moved elsewhere! + for(int B = 0; B < MAX_USB_MS_DRIVERS; B++) { + if((!partsready) && (UHS_USB_BulkOnly[B]->GetAddress())) { + + // Build a list. + int ML = UHS_USB_BulkOnly[B]->GetbMaxLUN(); + //printf("MAXLUN = %i\r\n", ML); + ML++; + for(int i = 0; i < ML; i++) { + if(UHS_USB_BulkOnly[B]->LUNIsGood(i)) { + partsready = true; + ((pvt_t *)(sto[i].private_data))->lun = i; + ((pvt_t *)(sto[i].private_data))->B = B; + sto[i].Reads = *UHS_USB_BulkOnly_Read; + sto[i].Writes = *UHS_USB_BulkOnly_Write; + sto[i].Status = *UHS_USB_BulkOnly_Status; + sto[i].Initialize = *UHS_USB_BulkOnly_Initialize; + sto[i].Commit = *UHS_USB_BulkOnly_Commit; + sto[i].TotalSectors = UHS_USB_BulkOnly[B]->GetCapacity(i); + sto[i].SectorSize = UHS_USB_BulkOnly[B]->GetSectorSize(i); + printf_P(PSTR("LUN:\t\t%u\r\n"), i); + printf_P(PSTR("Total Sectors:\t%08lx\t%lu\r\n"), sto[i].TotalSectors, sto[i].TotalSectors); + printf_P(PSTR("Sector Size:\t%04x\t\t%u\r\n"), sto[i].SectorSize, sto[i].SectorSize); + // get the partition data... + PT = new PCPartition; + + if(!PT->Init(&sto[i])) { + part_t *apart; + for(int j = 0; j < 4; j++) { + apart = PT->GetPart(j); + if(apart != NULL && apart->type != 0x00) { + memcpy(&(parts[cpart]), apart, sizeof (part_t)); + printf_P(PSTR("Partition %u type %#02x\r\n"), j, parts[cpart].type); + // for now + if(isfat(parts[cpart].type)) { + Fats[cpart] = new PFAT(&sto[i], cpart, parts[cpart].firstSector); + //int r = Fats[cpart]->Good(); + if(Fats[cpart]->MountStatus()) { + delete Fats[cpart]; + Fats[cpart] = NULL; + } else cpart++; + } + } + } + } else { + // try superblock + Fats[cpart] = new PFAT(&sto[i], cpart, 0); + //int r = Fats[cpart]->Good(); + if(Fats[cpart]->MountStatus()) { + //printf_P(PSTR("Superblock error %x\r\n"), r); + delete Fats[cpart]; + Fats[cpart] = NULL; + } else cpart++; + + } + delete PT; + } else { + sto[i].Writes = NULL; + sto[i].Reads = NULL; + sto[i].Initialize = NULL; + sto[i].TotalSectors = 0UL; + sto[i].SectorSize = 0; + } + } + + } + } + + if(fatready) { + if(Fats[0] != NULL) { + struct Pvt * p; + p = ((struct Pvt *)(Fats[0]->storage->private_data)); + if(!UHS_USB_BulkOnly[p->B]->LUNIsGood(p->lun)) { + // media change +#if !defined(CORE_TEENSY) && defined(__AVR__) + fadeAmount = 80; +#endif + partsready = false; + for(int i = 0; i < cpart; i++) { + if(Fats[i] != NULL) + delete Fats[i]; + Fats[cpart] = NULL; + } + fatready = false; + notified = false; + cpart = 0; + } + + } + } + if(fatready) { + FRESULT rc; /* Result code */ + UINT bw, br, i; + if(!notified) { +#if !defined(CORE_TEENSY) && defined(__AVR__) + fadeAmount = 5; +#endif + notified = true; + FATFS *fs = NULL; + for(int zz = 0; zz < _VOLUMES; zz++) { + if(Fats[zz]->volmap == 0) fs = Fats[zz]->ffs; + } + printf_P(PSTR("\r\nOpen an existing file (message.txt).\r\n")); + rc = f_open(&My_File_Object_x, "0:/MESSAGE.TXT", FA_READ); + if(rc) printf_P(PSTR("Error %i, message.txt not found.\r\n"), rc); + else { + printf_P(PSTR("\r\nType the file content.\r\n")); + for(;;) { + rc = f_read(&My_File_Object_x, My_Buff_x, mbxs, &br); /* Read a chunk of file */ + if(rc || !br) break; /* Error or end of file */ + for(i = 0; i < br; i++) { + /* Type the data */ + if(My_Buff_x[i] == '\n') + Serial.write('\r'); + if(My_Buff_x[i] != '\r') + Serial.write(My_Buff_x[i]); + Serial.flush(); + } + } + if(rc) { + f_close(&My_File_Object_x); + goto out; + } + + printf_P(PSTR("\r\nClose the file.\r\n")); + rc = f_close(&My_File_Object_x); + if(rc) goto out; + } + printf_P(PSTR("\r\nCreate a new file (hello.txt).\r\n")); + rc = f_open(&My_File_Object_x, "0:/Hello.TxT", FA_WRITE | FA_CREATE_ALWAYS); + if(rc) { + die(rc); + goto outdir; + } + printf_P(PSTR("\r\nWrite a text data. (Hello world!)\r\n")); + rc = f_write(&My_File_Object_x, "Hello world!\r\n", 14, &bw); + if(rc) { + goto out; + } + printf_P(PSTR("%u bytes written.\r\n"), bw); + + printf_P(PSTR("\r\nClose the file.\r\n")); + rc = f_close(&My_File_Object_x); + if(rc) { + die(rc); + goto out; + } +outdir:{ +#if _USE_LFN + char lfn[_MAX_LFN + 1]; + FILINFO My_File_Info_Object_x; /* File information object */ + My_File_Info_Object_x.lfname = lfn; +#endif + DIR My_Dir_Object_x; /* Directory object */ + printf_P(PSTR("\r\nOpen root directory.\r\n")); + rc = f_opendir(&My_Dir_Object_x, "0:/"); + if(rc) { + die(rc); + goto out; + } + + printf_P(PSTR("\r\nDirectory listing...\r\n")); +#if defined(__AVR__) + printf_P(PSTR("Available heap: %u Bytes\r\n"), freeHeap()); +#endif + for(;;) { +#if _USE_LFN + My_File_Info_Object_x.lfsize = _MAX_LFN; +#endif + + rc = f_readdir(&My_Dir_Object_x, &My_File_Info_Object_x); /* Read a directory item */ + if(rc || !My_File_Info_Object_x.fname[0]) break; /* Error or end of dir */ + + if(My_File_Info_Object_x.fattrib & AM_DIR) { + Serial.write('d'); + } else { + Serial.write('-'); + } + Serial.write('r'); + + if(My_File_Info_Object_x.fattrib & AM_RDO) { + Serial.write('-'); + } else { + Serial.write('w'); + } + if(My_File_Info_Object_x.fattrib & AM_HID) { + Serial.write('h'); + } else { + Serial.write('-'); + } + + if(My_File_Info_Object_x.fattrib & AM_SYS) { + Serial.write('s'); + } else { + Serial.write('-'); + } + + if(My_File_Info_Object_x.fattrib & AM_ARC) { + Serial.write('a'); + } else { + Serial.write('-'); + } + +#if _USE_LFN + if(*My_File_Info_Object_x.lfname) + printf_P(PSTR(" %8lu %s (%s)\r\n"), My_File_Info_Object_x.fsize, My_File_Info_Object_x.fname, My_File_Info_Object_x.lfname); + else +#endif + printf_P(PSTR(" %8lu %s\r\n"), My_File_Info_Object_x.fsize, &(My_File_Info_Object_x.fname[0])); + } + } +out: + if(rc) die(rc); + + DISK_IOCTL(fs->drv, CTRL_COMMIT, 0); + printf_P(PSTR("\r\nTest completed.\r\n")); + + } + + if(runtest) { + ULONG ii, wt, rt, start, end; + FATFS *fs = NULL; + for(int zz = 0; zz < _VOLUMES; zz++) { + if(Fats[zz]->volmap == 0) fs = Fats[zz]->ffs; + } + runtest = false; + f_unlink("0:/10MB.bin"); + printf_P(PSTR("\r\nCreate a new 10MB test file (10MB.bin).\r\n")); + rc = f_open(&My_File_Object_x, "0:/10MB.bin", FA_WRITE | FA_CREATE_ALWAYS); + if(rc) goto failed; + for(bw = 0; bw < mbxs; bw++) My_Buff_x[bw] = bw & 0xff; + fflush(stdout); + start = millis(); + while(start == millis()); + for(ii = 10485760LU / mbxs; ii > 0LU; ii--) { + rc = f_write(&My_File_Object_x, My_Buff_x, mbxs, &bw); + if(rc || !bw) goto failed; + } + rc = f_close(&My_File_Object_x); + if(rc) goto failed; + end = millis(); + wt = (end - start) - 1; + printf_P(PSTR("Time to write 10485760 bytes: %lu ms (%lu sec) \r\n"), wt, (500 + wt) / 1000UL); + rc = f_open(&My_File_Object_x, "0:/10MB.bin", FA_READ); + fflush(stdout); + start = millis(); + while(start == millis()); + if(rc) goto failed; + for(;;) { + rc = f_read(&My_File_Object_x, My_Buff_x, mbxs, &bw); /* Read a chunk of file */ + if(rc || !bw) break; /* Error or end of file */ + } + end = millis(); + if(rc) goto failed; + rc = f_close(&My_File_Object_x); + if(rc) goto failed; + rt = (end - start) - 1; + printf_P(PSTR("Time to read 10485760 bytes: %lu ms (%lu sec)\r\nDelete test file\r\n"), rt, (500 + rt) / 1000UL); +failed: + if(rc) die(rc); + DISK_IOCTL(fs->drv, CTRL_COMMIT, 0); + printf_P(PSTR("10MB timing test finished.\r\n")); + } + } + } +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/gpl2.txt b/lib/usbhost/USB_Host_Shield_2.0/gpl2.txt new file mode 100644 index 0000000000..5b6e7c66c2 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/gpl2.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/lib/usbhost/USB_Host_Shield_2.0/hexdump.h b/lib/usbhost/USB_Host_Shield_2.0/hexdump.h new file mode 100644 index 0000000000..ffa7248b7d --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/hexdump.h @@ -0,0 +1,61 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#if !defined(_usb_h_) || defined(__HEXDUMP_H__) +#error "Never include hexdump.h directly; include Usb.h instead" +#else +#define __HEXDUMP_H__ + +extern int UsbDEBUGlvl; + +template +class HexDumper : public BASE_CLASS { + uint8_t byteCount; + OFFSET_TYPE byteTotal; + +public: + + HexDumper() : byteCount(0), byteTotal(0) { + }; + + void Initialize() { + byteCount = 0; + byteTotal = 0; + }; + + void Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset); +}; + +template +void HexDumper::Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset) { + if(UsbDEBUGlvl >= 0x80) { // Fully bypass this block of code if we do not debug. + for(LEN_TYPE j = 0; j < len; j++, byteCount++, byteTotal++) { + if(!byteCount) { + PrintHex (byteTotal, 0x80); + E_Notify(PSTR(": "), 0x80); + } + PrintHex (pbuf[j], 0x80); + E_Notify(PSTR(" "), 0x80); + + if(byteCount == 15) { + E_Notify(PSTR("\r\n"), 0x80); + byteCount = 0xFF; + } + } + } +} + +#endif // __HEXDUMP_H__ diff --git a/lib/usbhost/USB_Host_Shield_2.0/hid.cpp b/lib/usbhost/USB_Host_Shield_2.0/hid.cpp new file mode 100644 index 0000000000..e4c7721a3e --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/hid.cpp @@ -0,0 +1,112 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ + +#include "hid.h" + +//get HID report descriptor + +/* WRONG! Endpoint is _ALWAYS_ ZERO for HID! We want the _INTERFACE_ value here! +uint8_t HID::GetReportDescr(uint8_t ep, USBReadParser *parser) { + const uint8_t constBufLen = 64; + uint8_t buf[constBufLen]; + + uint8_t rcode = pUsb->ctrlReq(bAddress, ep, bmREQ_HID_REPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00, + HID_DESCRIPTOR_REPORT, 0x0000, 128, constBufLen, buf, (USBReadParser*)parser); + + //return ((rcode != hrSTALL) ? rcode : 0); + return rcode; +} + */ +uint8_t HID::GetReportDescr(uint16_t wIndex, USBReadParser *parser) { + const uint8_t constBufLen = 64; + uint8_t buf[constBufLen]; + + uint8_t rcode = pUsb->ctrlReq(bAddress, 0x00, bmREQ_HID_REPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00, + HID_DESCRIPTOR_REPORT, wIndex, 128, constBufLen, buf, (USBReadParser*)parser); + + //return ((rcode != hrSTALL) ? rcode : 0); + return rcode; +} + +//uint8_t HID::getHidDescr( uint8_t ep, uint16_t nbytes, uint8_t* dataptr ) +//{ +// return( pUsb->ctrlReq( bAddress, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, HID_DESCRIPTOR_HID, 0x0000, nbytes, dataptr )); +//} + +uint8_t HID::SetReport(uint8_t ep, uint8_t iface, uint8_t report_type, uint8_t report_id, uint16_t nbytes, uint8_t* dataptr) { + return ( pUsb->ctrlReq(bAddress, ep, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, report_id, report_type, iface, nbytes, nbytes, dataptr, NULL)); +} + +uint8_t HID::GetReport(uint8_t ep, uint8_t iface, uint8_t report_type, uint8_t report_id, uint16_t nbytes, uint8_t* dataptr) { + return ( pUsb->ctrlReq(bAddress, ep, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, report_id, report_type, iface, nbytes, nbytes, dataptr, NULL)); +} + +uint8_t HID::GetIdle(uint8_t iface, uint8_t reportID, uint8_t* dataptr) { + return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HID_IN, HID_REQUEST_GET_IDLE, reportID, 0, iface, 0x0001, 0x0001, dataptr, NULL)); +} + +uint8_t HID::SetIdle(uint8_t iface, uint8_t reportID, uint8_t duration) { + return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HID_OUT, HID_REQUEST_SET_IDLE, reportID, duration, iface, 0x0000, 0x0000, NULL, NULL)); +} + +uint8_t HID::SetProtocol(uint8_t iface, uint8_t protocol) { + return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HID_OUT, HID_REQUEST_SET_PROTOCOL, protocol, 0x00, iface, 0x0000, 0x0000, NULL, NULL)); +} + +uint8_t HID::GetProtocol(uint8_t iface, uint8_t* dataptr) { + return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HID_IN, HID_REQUEST_GET_PROTOCOL, 0x00, 0x00, iface, 0x0001, 0x0001, dataptr, NULL)); +} + +void HID::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) { + Notify(PSTR("Endpoint descriptor:"), 0x80); + Notify(PSTR("\r\nLength:\t\t"), 0x80); + D_PrintHex (ep_ptr->bLength, 0x80); + Notify(PSTR("\r\nType:\t\t"), 0x80); + D_PrintHex (ep_ptr->bDescriptorType, 0x80); + Notify(PSTR("\r\nAddress:\t"), 0x80); + D_PrintHex (ep_ptr->bEndpointAddress, 0x80); + Notify(PSTR("\r\nAttributes:\t"), 0x80); + D_PrintHex (ep_ptr->bmAttributes, 0x80); + Notify(PSTR("\r\nMaxPktSize:\t"), 0x80); + D_PrintHex (ep_ptr->wMaxPacketSize, 0x80); + Notify(PSTR("\r\nPoll Intrv:\t"), 0x80); + D_PrintHex (ep_ptr->bInterval, 0x80); +} + +void HID::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc) { + Notify(PSTR("\r\n\r\nHID Descriptor:\r\n"), 0x80); + Notify(PSTR("bDescLength:\t\t"), 0x80); + D_PrintHex (pDesc->bLength, 0x80); + + Notify(PSTR("\r\nbDescriptorType:\t"), 0x80); + D_PrintHex (pDesc->bDescriptorType, 0x80); + + Notify(PSTR("\r\nbcdHID:\t\t\t"), 0x80); + D_PrintHex (pDesc->bcdHID, 0x80); + + Notify(PSTR("\r\nbCountryCode:\t\t"), 0x80); + D_PrintHex (pDesc->bCountryCode, 0x80); + + Notify(PSTR("\r\nbNumDescriptors:\t"), 0x80); + D_PrintHex (pDesc->bNumDescriptors, 0x80); + + Notify(PSTR("\r\nbDescrType:\t\t"), 0x80); + D_PrintHex (pDesc->bDescrType, 0x80); + + Notify(PSTR("\r\nwDescriptorLength:\t"), 0x80); + D_PrintHex (pDesc->wDescriptorLength, 0x80); +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/hid.h b/lib/usbhost/USB_Host_Shield_2.0/hid.h new file mode 100644 index 0000000000..72942ebc92 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/hid.h @@ -0,0 +1,188 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#if !defined(__HID_H__) +#define __HID_H__ + +#include "Usb.h" +#include "hidusagestr.h" + +#define MAX_REPORT_PARSERS 2 +#define HID_MAX_HID_CLASS_DESCRIPTORS 5 + +#define DATA_SIZE_MASK 0x03 +#define TYPE_MASK 0x0C +#define TAG_MASK 0xF0 + +#define DATA_SIZE_0 0x00 +#define DATA_SIZE_1 0x01 +#define DATA_SIZE_2 0x02 +#define DATA_SIZE_4 0x03 + +#define TYPE_MAIN 0x00 +#define TYPE_GLOBAL 0x04 +#define TYPE_LOCAL 0x08 + +#define TAG_MAIN_INPUT 0x80 +#define TAG_MAIN_OUTPUT 0x90 +#define TAG_MAIN_COLLECTION 0xA0 +#define TAG_MAIN_FEATURE 0xB0 +#define TAG_MAIN_ENDCOLLECTION 0xC0 + +#define TAG_GLOBAL_USAGEPAGE 0x00 +#define TAG_GLOBAL_LOGICALMIN 0x10 +#define TAG_GLOBAL_LOGICALMAX 0x20 +#define TAG_GLOBAL_PHYSMIN 0x30 +#define TAG_GLOBAL_PHYSMAX 0x40 +#define TAG_GLOBAL_UNITEXP 0x50 +#define TAG_GLOBAL_UNIT 0x60 +#define TAG_GLOBAL_REPORTSIZE 0x70 +#define TAG_GLOBAL_REPORTID 0x80 +#define TAG_GLOBAL_REPORTCOUNT 0x90 +#define TAG_GLOBAL_PUSH 0xA0 +#define TAG_GLOBAL_POP 0xB0 + +#define TAG_LOCAL_USAGE 0x00 +#define TAG_LOCAL_USAGEMIN 0x10 +#define TAG_LOCAL_USAGEMAX 0x20 + +/* HID requests */ +#define bmREQ_HID_OUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE +#define bmREQ_HID_IN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE +#define bmREQ_HID_REPORT USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_INTERFACE + +/* HID constants. Not part of chapter 9 */ +/* Class-Specific Requests */ +#define HID_REQUEST_GET_REPORT 0x01 +#define HID_REQUEST_GET_IDLE 0x02 +#define HID_REQUEST_GET_PROTOCOL 0x03 +#define HID_REQUEST_SET_REPORT 0x09 +#define HID_REQUEST_SET_IDLE 0x0A +#define HID_REQUEST_SET_PROTOCOL 0x0B + +/* Class Descriptor Types */ +#define HID_DESCRIPTOR_HID 0x21 +#define HID_DESCRIPTOR_REPORT 0x22 +#define HID_DESRIPTOR_PHY 0x23 + +/* Protocol Selection */ +#define HID_BOOT_PROTOCOL 0x00 +#define HID_RPT_PROTOCOL 0x01 + +/* HID Interface Class Code */ +#define HID_INTF 0x03 + +/* HID Interface Class SubClass Codes */ +#define HID_BOOT_INTF_SUBCLASS 0x01 + +/* HID Interface Class Protocol Codes */ +#define HID_PROTOCOL_NONE 0x00 +#define HID_PROTOCOL_KEYBOARD 0x01 +#define HID_PROTOCOL_MOUSE 0x02 + +#define HID_ITEM_TYPE_MAIN 0 +#define HID_ITEM_TYPE_GLOBAL 1 +#define HID_ITEM_TYPE_LOCAL 2 +#define HID_ITEM_TYPE_RESERVED 3 + +#define HID_LONG_ITEM_PREFIX 0xfe // Long item prefix value + +#define bmHID_MAIN_ITEM_TAG 0xfc // Main item tag mask + +#define bmHID_MAIN_ITEM_INPUT 0x80 // Main item Input tag value +#define bmHID_MAIN_ITEM_OUTPUT 0x90 // Main item Output tag value +#define bmHID_MAIN_ITEM_FEATURE 0xb0 // Main item Feature tag value +#define bmHID_MAIN_ITEM_COLLECTION 0xa0 // Main item Collection tag value +#define bmHID_MAIN_ITEM_END_COLLECTION 0xce // Main item End Collection tag value + +#define HID_MAIN_ITEM_COLLECTION_PHYSICAL 0 +#define HID_MAIN_ITEM_COLLECTION_APPLICATION 1 +#define HID_MAIN_ITEM_COLLECTION_LOGICAL 2 +#define HID_MAIN_ITEM_COLLECTION_REPORT 3 +#define HID_MAIN_ITEM_COLLECTION_NAMED_ARRAY 4 +#define HID_MAIN_ITEM_COLLECTION_USAGE_SWITCH 5 +#define HID_MAIN_ITEM_COLLECTION_USAGE_MODIFIER 6 + +struct HidItemPrefix { + uint8_t bSize : 2; + uint8_t bType : 2; + uint8_t bTag : 4; +}; + +struct MainItemIOFeature { + uint8_t bmIsConstantOrData : 1; + uint8_t bmIsArrayOrVariable : 1; + uint8_t bmIsRelativeOrAbsolute : 1; + uint8_t bmIsWrapOrNoWrap : 1; + uint8_t bmIsNonLonearOrLinear : 1; + uint8_t bmIsNoPreferedOrPrefered : 1; + uint8_t bmIsNullOrNoNull : 1; + uint8_t bmIsVolatileOrNonVolatile : 1; +}; + +class HID; + +class HIDReportParser { +public: + virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) = 0; +}; + +class HID : public USBDeviceConfig, public UsbConfigXtracter { +protected: + USB *pUsb; // USB class instance pointer + uint8_t bAddress; // address + +protected: + static const uint8_t epInterruptInIndex = 1; // InterruptIN endpoint index + static const uint8_t epInterruptOutIndex = 2; // InterruptOUT endpoint index + + static const uint8_t maxHidInterfaces = 3; + static const uint8_t maxEpPerInterface = 2; + static const uint8_t totalEndpoints = (maxHidInterfaces * maxEpPerInterface + 1); + + void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); + void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc); + + virtual HIDReportParser* GetReportParser(uint8_t id) { + return NULL; + }; + +public: + + HID(USB *pusb) : pUsb(pusb) { + }; + + const USB* GetUsb() { + return pUsb; + }; + + virtual bool SetReportParser(uint8_t id, HIDReportParser *prs) { + return false; + }; + + uint8_t SetProtocol(uint8_t iface, uint8_t protocol); + uint8_t GetProtocol(uint8_t iface, uint8_t* dataptr); + uint8_t GetIdle(uint8_t iface, uint8_t reportID, uint8_t* dataptr); + uint8_t SetIdle(uint8_t iface, uint8_t reportID, uint8_t duration); + + uint8_t GetReportDescr(uint16_t wIndex, USBReadParser *parser = NULL); + + uint8_t GetHidDescr(uint8_t ep, uint16_t nbytes, uint8_t* dataptr); + uint8_t GetReport(uint8_t ep, uint8_t iface, uint8_t report_type, uint8_t report_id, uint16_t nbytes, uint8_t* dataptr); + uint8_t SetReport(uint8_t ep, uint8_t iface, uint8_t report_type, uint8_t report_id, uint16_t nbytes, uint8_t* dataptr); +}; + +#endif // __HID_H__ diff --git a/lib/usbhost/USB_Host_Shield_2.0/hidboot.cpp b/lib/usbhost/USB_Host_Shield_2.0/hidboot.cpp new file mode 100644 index 0000000000..280b2f9788 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/hidboot.cpp @@ -0,0 +1,201 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#include "hidboot.h" + +void MouseReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) { + MOUSEINFO *pmi = (MOUSEINFO*)buf; + // Future: + // bool event; + +#if 0 + if (prevState.mouseInfo.bmLeftButton == 0 && pmi->bmLeftButton == 1) + OnLeftButtonDown(pmi); + + if (prevState.mouseInfo.bmLeftButton == 1 && pmi->bmLeftButton == 0) + OnLeftButtonUp(pmi); + + if (prevState.mouseInfo.bmRightButton == 0 && pmi->bmRightButton == 1) + OnRightButtonDown(pmi); + + if (prevState.mouseInfo.bmRightButton == 1 && pmi->bmRightButton == 0) + OnRightButtonUp(pmi); + + if (prevState.mouseInfo.bmMiddleButton == 0 && pmi->bmMiddleButton == 1) + OnMiddleButtonDown(pmi); + + if (prevState.mouseInfo.bmMiddleButton == 1 && pmi->bmMiddleButton == 0) + OnMiddleButtonUp(pmi); + + if (prevState.mouseInfo.dX != pmi->dX || prevState.mouseInfo.dY != pmi->dY) + OnMouseMove(pmi); + + if (len > sizeof (MOUSEINFO)) + for (uint8_t i = 0; ibmLeftButton ) { + if(pmi->bmLeftButton) { + OnLeftButtonDown(pmi); + } else { + OnLeftButtonUp(pmi); + } + // Future: + // event = true; + } + + if(prevState.mouseInfo.bmRightButton != pmi->bmRightButton) { + if(pmi->bmRightButton) { + OnRightButtonDown(pmi); + } else { + OnRightButtonUp(pmi); + } + // Future: + // event = true; + } + + if(prevState.mouseInfo.bmMiddleButton != pmi->bmMiddleButton) { + if(pmi->bmMiddleButton) { + OnMiddleButtonDown(pmi); + } else { + OnMiddleButtonUp(pmi); + } + // Future: + // event = true; + } + + // + // Scroll wheel(s), are not part of the spec, but we could support it. + // Logitech wireless keyboard and mouse combo reports scroll wheel in byte 4 + // We wouldn't even need to save this information. + //if(len > 3) { + //} + // + + // Mice only report motion when they actually move! + // Why not just pass the x/y values to simplify things?? + if(pmi->dX || pmi->dY) { + OnMouseMove(pmi); + // Future: + // event = true; + } + + // + // Future: + // Provide a callback that operates on the gathered events from above. + // + // if(event) OnMouse(); + // + + // Only the first byte matters (buttons). We do NOT need to save position info. + prevState.bInfo[0] = buf[0]; +#endif + +}; + +void KeyboardReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) { + // On error - return + if (buf[2] == 1) + return; + + //KBDINFO *pki = (KBDINFO*)buf; + + // provide event for changed control key state + if (prevState.bInfo[0x00] != buf[0x00]) { + OnControlKeysChanged(prevState.bInfo[0x00], buf[0x00]); + } + + for (uint8_t i = 2; i < 8; i++) { + bool down = false; + bool up = false; + + for (uint8_t j = 2; j < 8; j++) { + if (buf[i] == prevState.bInfo[j] && buf[i] != 1) + down = true; + if (buf[j] == prevState.bInfo[i] && prevState.bInfo[i] != 1) + up = true; + } + if (!down) { + HandleLockingKeys(hid, buf[i]); + OnKeyDown(*buf, buf[i]); + } + if (!up) + OnKeyUp(prevState.bInfo[0], prevState.bInfo[i]); + } + for (uint8_t i = 0; i < 8; i++) + prevState.bInfo[i] = buf[i]; +}; + +const uint8_t KeyboardReportParser::numKeys[10] PROGMEM = {'!', '@', '#', '$', '%', '^', '&', '*', '(', ')'}; +const uint8_t KeyboardReportParser::symKeysUp[12] PROGMEM = {'_', '+', '{', '}', '|', '~', ':', '"', '~', '<', '>', '?'}; +const uint8_t KeyboardReportParser::symKeysLo[12] PROGMEM = {'-', '=', '[', ']', '\\', ' ', ';', '\'', '`', ',', '.', '/'}; +const uint8_t KeyboardReportParser::padKeys[5] PROGMEM = {'/', '*', '-', '+', 0x13}; + +uint8_t KeyboardReportParser::OemToAscii(uint8_t mod, uint8_t key) { + uint8_t shift = (mod & 0x22); + + // [a-z] + if (VALUE_WITHIN(key, 0x04, 0x1d)) { + // Upper case letters + if ((kbdLockingKeys.kbdLeds.bmCapsLock == 0 && shift) || + (kbdLockingKeys.kbdLeds.bmCapsLock == 1 && shift == 0)) + return (key - 4 + 'A'); + + // Lower case letters + else + return (key - 4 + 'a'); + }// Numbers + else if (VALUE_WITHIN(key, 0x1e, 0x27)) { + if (shift) + return ((uint8_t)pgm_read_byte(&getNumKeys()[key - 0x1e])); + else + return ((key == UHS_HID_BOOT_KEY_ZERO) ? '0' : key - 0x1e + '1'); + }// Keypad Numbers + else if(VALUE_WITHIN(key, 0x59, 0x61)) { + if(kbdLockingKeys.kbdLeds.bmNumLock == 1) + return (key - 0x59 + '1'); + } else if(VALUE_WITHIN(key, 0x2d, 0x38)) + return ((shift) ? (uint8_t)pgm_read_byte(&getSymKeysUp()[key - 0x2d]) : (uint8_t)pgm_read_byte(&getSymKeysLo()[key - 0x2d])); + else if(VALUE_WITHIN(key, 0x54, 0x58)) + return (uint8_t)pgm_read_byte(&getPadKeys()[key - 0x54]); + else { + switch(key) { + case UHS_HID_BOOT_KEY_SPACE: return (0x20); + case UHS_HID_BOOT_KEY_ENTER: return (0x13); + case UHS_HID_BOOT_KEY_ZERO2: return ((kbdLockingKeys.kbdLeds.bmNumLock == 1) ? '0': 0); + case UHS_HID_BOOT_KEY_PERIOD: return ((kbdLockingKeys.kbdLeds.bmNumLock == 1) ? '.': 0); + } + } + return ( 0); +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/hidboot.h b/lib/usbhost/USB_Host_Shield_2.0/hidboot.h new file mode 100644 index 0000000000..fb63ec5e59 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/hidboot.h @@ -0,0 +1,618 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#if !defined(__HIDBOOT_H__) +#define __HIDBOOT_H__ + +#include "hid.h" + +#define UHS_HID_BOOT_KEY_ZERO 0x27 +#define UHS_HID_BOOT_KEY_ENTER 0x28 +#define UHS_HID_BOOT_KEY_SPACE 0x2c +#define UHS_HID_BOOT_KEY_CAPS_LOCK 0x39 +#define UHS_HID_BOOT_KEY_SCROLL_LOCK 0x47 +#define UHS_HID_BOOT_KEY_NUM_LOCK 0x53 +#define UHS_HID_BOOT_KEY_ZERO2 0x62 +#define UHS_HID_BOOT_KEY_PERIOD 0x63 + +// Don't worry, GCC will optimize the result to a final value. +#define bitsEndpoints(p) ((((p) & HID_PROTOCOL_KEYBOARD)? 2 : 0) | (((p) & HID_PROTOCOL_MOUSE)? 1 : 0)) +#define totalEndpoints(p) ((bitsEndpoints(p) == 3) ? 3 : 2) +#define epMUL(p) ((((p) & HID_PROTOCOL_KEYBOARD)? 1 : 0) + (((p) & HID_PROTOCOL_MOUSE)? 1 : 0)) + +// Already defined in hid.h +// #define HID_MAX_HID_CLASS_DESCRIPTORS 5 + +struct MOUSEINFO { + + struct { + uint8_t bmLeftButton : 1; + uint8_t bmRightButton : 1; + uint8_t bmMiddleButton : 1; + uint8_t bmDummy : 5; + }; + int8_t dX; + int8_t dY; +}; + +class MouseReportParser : public HIDReportParser { + + union { + MOUSEINFO mouseInfo; + uint8_t bInfo[sizeof (MOUSEINFO)]; + } prevState; + +public: + void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); + +protected: + + virtual void OnMouseMove(MOUSEINFO *mi) { + }; + + virtual void OnLeftButtonUp(MOUSEINFO *mi) { + }; + + virtual void OnLeftButtonDown(MOUSEINFO *mi) { + }; + + virtual void OnRightButtonUp(MOUSEINFO *mi) { + }; + + virtual void OnRightButtonDown(MOUSEINFO *mi) { + }; + + virtual void OnMiddleButtonUp(MOUSEINFO *mi) { + }; + + virtual void OnMiddleButtonDown(MOUSEINFO *mi) { + }; +}; + +struct MODIFIERKEYS { + uint8_t bmLeftCtrl : 1; + uint8_t bmLeftShift : 1; + uint8_t bmLeftAlt : 1; + uint8_t bmLeftGUI : 1; + uint8_t bmRightCtrl : 1; + uint8_t bmRightShift : 1; + uint8_t bmRightAlt : 1; + uint8_t bmRightGUI : 1; +}; + +struct KBDINFO { + + struct { + uint8_t bmLeftCtrl : 1; + uint8_t bmLeftShift : 1; + uint8_t bmLeftAlt : 1; + uint8_t bmLeftGUI : 1; + uint8_t bmRightCtrl : 1; + uint8_t bmRightShift : 1; + uint8_t bmRightAlt : 1; + uint8_t bmRightGUI : 1; + }; + uint8_t bReserved; + uint8_t Keys[6]; +}; + +struct KBDLEDS { + uint8_t bmNumLock : 1; + uint8_t bmCapsLock : 1; + uint8_t bmScrollLock : 1; + uint8_t bmCompose : 1; + uint8_t bmKana : 1; + uint8_t bmReserved : 3; +}; + +class KeyboardReportParser : public HIDReportParser { + static const uint8_t numKeys[10]; + static const uint8_t symKeysUp[12]; + static const uint8_t symKeysLo[12]; + static const uint8_t padKeys[5]; + +protected: + + union { + KBDINFO kbdInfo; + uint8_t bInfo[sizeof (KBDINFO)]; + } prevState; + + union { + KBDLEDS kbdLeds; + uint8_t bLeds; + } kbdLockingKeys; + + uint8_t OemToAscii(uint8_t mod, uint8_t key); + +public: + + KeyboardReportParser() { + kbdLockingKeys.bLeds = 0; + }; + + void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); + +protected: + + virtual uint8_t HandleLockingKeys(HID* hid, uint8_t key) { + uint8_t old_keys = kbdLockingKeys.bLeds; + + switch(key) { + case UHS_HID_BOOT_KEY_NUM_LOCK: + kbdLockingKeys.kbdLeds.bmNumLock = ~kbdLockingKeys.kbdLeds.bmNumLock; + break; + case UHS_HID_BOOT_KEY_CAPS_LOCK: + kbdLockingKeys.kbdLeds.bmCapsLock = ~kbdLockingKeys.kbdLeds.bmCapsLock; + break; + case UHS_HID_BOOT_KEY_SCROLL_LOCK: + kbdLockingKeys.kbdLeds.bmScrollLock = ~kbdLockingKeys.kbdLeds.bmScrollLock; + break; + } + + if(old_keys != kbdLockingKeys.bLeds && hid) + return (hid->SetReport(0, 0/*hid->GetIface()*/, 2, 0, 1, &kbdLockingKeys.bLeds)); + + return 0; + }; + + virtual void OnControlKeysChanged(uint8_t before, uint8_t after) { + }; + + virtual void OnKeyDown(uint8_t mod, uint8_t key) { + }; + + virtual void OnKeyUp(uint8_t mod, uint8_t key) { + }; + + virtual const uint8_t *getNumKeys() { + return numKeys; + }; + + virtual const uint8_t *getSymKeysUp() { + return symKeysUp; + }; + + virtual const uint8_t *getSymKeysLo() { + return symKeysLo; + }; + + virtual const uint8_t *getPadKeys() { + return padKeys; + }; +}; + +template +class HIDBoot : public HID //public USBDeviceConfig, public UsbConfigXtracter +{ + EpInfo epInfo[totalEndpoints(BOOT_PROTOCOL)]; + HIDReportParser *pRptParser[epMUL(BOOT_PROTOCOL)]; + + uint8_t bConfNum; // configuration number + uint8_t bIfaceNum; // Interface Number + uint8_t bNumIface; // number of interfaces in the configuration + uint8_t bNumEP; // total number of EP in the configuration + uint32_t qNextPollTime; // next poll time + bool bPollEnable; // poll enable flag + uint8_t bInterval; // largest interval + + void Initialize(); + + virtual HIDReportParser* GetReportParser(uint8_t id) { + return pRptParser[id]; + }; + +public: + HIDBoot(USB *p); + + virtual bool SetReportParser(uint8_t id, HIDReportParser *prs) { + pRptParser[id] = prs; + return true; + }; + + // USBDeviceConfig implementation + uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + uint8_t Release(); + uint8_t Poll(); + + virtual uint8_t GetAddress() { + return bAddress; + }; + + virtual bool isReady() { + return bPollEnable; + }; + + // UsbConfigXtracter implementation + // Method should be defined here if virtual. + virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); + + virtual bool DEVCLASSOK(uint8_t klass) { + return (klass == USB_CLASS_HID); + } + + virtual bool DEVSUBCLASSOK(uint8_t subklass) { + return (subklass == BOOT_PROTOCOL); + } +}; + +template +HIDBoot::HIDBoot(USB *p) : +HID(p), +qNextPollTime(0), +bPollEnable(false) { + Initialize(); + + for(int i = 0; i < epMUL(BOOT_PROTOCOL); i++) { + pRptParser[i] = NULL; + } + if(pUsb) + pUsb->RegisterDeviceClass(this); +} + +template +void HIDBoot::Initialize() { + for(int i = 0; i < totalEndpoints(BOOT_PROTOCOL); i++) { + epInfo[i].epAddr = 0; + epInfo[i].maxPktSize = (i) ? 0 : 8; + epInfo[i].epAttribs = 0; + epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; + } + bNumEP = 1; + bNumIface = 0; + bConfNum = 0; +} + +template +uint8_t HIDBoot::Init(uint8_t parent, uint8_t port, bool lowspeed) { + const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR); + + uint8_t buf[constBufSize]; + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + uint8_t len = 0; + //uint16_t cd_len = 0; + + uint8_t num_of_conf; // number of configurations + //uint8_t num_of_intf; // number of interfaces + + AddressPool &addrPool = pUsb->GetAddressPool(); + + USBTRACE("BM Init\r\n"); + //USBTRACE2("totalEndpoints:", (uint8_t) (totalEndpoints(BOOT_PROTOCOL))); + //USBTRACE2("epMUL:", epMUL(BOOT_PROTOCOL)); + + if(bAddress) + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; + + bInterval = 0; + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); + + if(!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + if(!p->epinfo) { + USBTRACE("epinfo\r\n"); + return USB_ERROR_EPINFO_IS_NULL; + } + + // Save old pointer to EP_RECORD of address 0 + oldep_ptr = p->epinfo; + + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence + p->epinfo = epInfo; + + p->lowspeed = lowspeed; + + // Get device descriptor + rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*)buf); + + if(!rcode) + len = (buf[0] > constBufSize) ? constBufSize : buf[0]; + + if(rcode) { + // Restore p->epinfo + p->epinfo = oldep_ptr; + + goto FailGetDevDescr; + } + + // Restore p->epinfo + p->epinfo = oldep_ptr; + + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, false, port); + + if(!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + // Extract Max Packet Size from the device descriptor + epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; + + // Assign new address to the device + rcode = pUsb->setAddr(0, 0, bAddress); + + if(rcode) { + p->lowspeed = false; + addrPool.FreeAddress(bAddress); + bAddress = 0; + USBTRACE2("setAddr:", rcode); + return rcode; + } + //delay(2); //per USB 2.0 sect.9.2.6.3 + + USBTRACE2("Addr:", bAddress); + + p->lowspeed = false; + + p = addrPool.GetUsbDevicePtr(bAddress); + + if(!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->lowspeed = lowspeed; + + if(len) + rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf); + + if(rcode) + goto FailGetDevDescr; + + num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations; + + USBTRACE2("NC:", num_of_conf); + + // GCC will optimize unused stuff away. + if((BOOT_PROTOCOL & (HID_PROTOCOL_KEYBOARD | HID_PROTOCOL_MOUSE)) == (HID_PROTOCOL_KEYBOARD | HID_PROTOCOL_MOUSE)) { + USBTRACE("HID_PROTOCOL_KEYBOARD AND MOUSE\r\n"); + ConfigDescParser< + USB_CLASS_HID, + HID_BOOT_INTF_SUBCLASS, + HID_PROTOCOL_KEYBOARD | HID_PROTOCOL_MOUSE, + CP_MASK_COMPARE_ALL > confDescrParser(this); + confDescrParser.SetOR(); // Use the OR variant. + for(uint8_t i = 0; i < num_of_conf; i++) { + pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); + if(bNumEP == (uint8_t)(totalEndpoints(BOOT_PROTOCOL))) + break; + } + } else { + // GCC will optimize unused stuff away. + if(BOOT_PROTOCOL & HID_PROTOCOL_KEYBOARD) { + USBTRACE("HID_PROTOCOL_KEYBOARD\r\n"); + for(uint8_t i = 0; i < num_of_conf; i++) { + ConfigDescParser< + USB_CLASS_HID, + HID_BOOT_INTF_SUBCLASS, + HID_PROTOCOL_KEYBOARD, + CP_MASK_COMPARE_ALL> confDescrParserA(this); + + pUsb->getConfDescr(bAddress, 0, i, &confDescrParserA); + if(bNumEP == (uint8_t)(totalEndpoints(BOOT_PROTOCOL))) + break; + } + } + + // GCC will optimize unused stuff away. + if(BOOT_PROTOCOL & HID_PROTOCOL_MOUSE) { + USBTRACE("HID_PROTOCOL_MOUSE\r\n"); + for(uint8_t i = 0; i < num_of_conf; i++) { + ConfigDescParser< + USB_CLASS_HID, + HID_BOOT_INTF_SUBCLASS, + HID_PROTOCOL_MOUSE, + CP_MASK_COMPARE_ALL> confDescrParserB(this); + + pUsb->getConfDescr(bAddress, 0, i, &confDescrParserB); + if(bNumEP == ((uint8_t)(totalEndpoints(BOOT_PROTOCOL)))) + break; + + } + } + } + USBTRACE2("bNumEP:", bNumEP); + + if(bNumEP != (uint8_t)(totalEndpoints(BOOT_PROTOCOL))) { + rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + goto Fail; + } + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); + //USBTRACE2("setEpInfoEntry returned ", rcode); + USBTRACE2("Cnf:", bConfNum); + + delay(1000); + + // Set Configuration Value + rcode = pUsb->setConf(bAddress, 0, bConfNum); + + if(rcode) + goto FailSetConfDescr; + + delay(1000); + + USBTRACE2("bIfaceNum:", bIfaceNum); + USBTRACE2("bNumIface:", bNumIface); + + // Yes, mouse wants SetProtocol and SetIdle too! + for(uint8_t i = 0; i < epMUL(BOOT_PROTOCOL); i++) { + USBTRACE2("\r\nInterface:", i); + rcode = SetProtocol(i, HID_BOOT_PROTOCOL); + if(rcode) goto FailSetProtocol; + USBTRACE2("PROTOCOL SET HID_BOOT rcode:", rcode); + rcode = SetIdle(i, 0, 0); + USBTRACE2("SET_IDLE rcode:", rcode); + // if(rcode) goto FailSetIdle; This can fail. + // Get the RPIPE and just throw it away. + SinkParser sink; + rcode = GetReportDescr(i, &sink); + USBTRACE2("RPIPE rcode:", rcode); + } + + // Get RPIPE and throw it away. + + if(BOOT_PROTOCOL & HID_PROTOCOL_KEYBOARD) { + // Wake keyboard interface by twinkling up to 5 LEDs that are in the spec. + // kana, compose, scroll, caps, num + rcode = 0x20; // Reuse rcode. + while(rcode) { + rcode >>= 1; + // Ignore any error returned, we don't care if LED is not supported + SetReport(0, 0, 2, 0, 1, &rcode); // Eventually becomes zero (All off) + delay(25); + } + } + USBTRACE("BM configured\r\n"); + + bPollEnable = true; + return 0; + +FailGetDevDescr: +#ifdef DEBUG_USB_HOST + NotifyFailGetDevDescr(); + goto Fail; +#endif + + //FailSetDevTblEntry: + //#ifdef DEBUG_USB_HOST + // NotifyFailSetDevTblEntry(); + // goto Fail; + //#endif + + //FailGetConfDescr: + //#ifdef DEBUG_USB_HOST + // NotifyFailGetConfDescr(); + // goto Fail; + //#endif + +FailSetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailSetConfDescr(); + goto Fail; +#endif + +FailSetProtocol: +#ifdef DEBUG_USB_HOST + USBTRACE("SetProto:"); + goto Fail; +#endif + + //FailSetIdle: + //#ifdef DEBUG_USB_HOST + // USBTRACE("SetIdle:"); + //#endif + +Fail: +#ifdef DEBUG_USB_HOST + NotifyFail(rcode); +#endif + Release(); + + return rcode; +} + +template +void HIDBoot::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) { + + // If the first configuration satisfies, the others are not considered. + //if(bNumEP > 1 && conf != bConfNum) + if(bNumEP == totalEndpoints(BOOT_PROTOCOL)) + return; + + bConfNum = conf; + bIfaceNum = iface; + + if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) { + if(pep->bInterval > bInterval) bInterval = pep->bInterval; + + // Fill in the endpoint info structure + epInfo[bNumEP].epAddr = (pep->bEndpointAddress & 0x0F); + epInfo[bNumEP].maxPktSize = (uint8_t)pep->wMaxPacketSize; + epInfo[bNumEP].epAttribs = 0; + epInfo[bNumEP].bmNakPower = USB_NAK_NOWAIT; + bNumEP++; + + } +} + +template +uint8_t HIDBoot::Release() { + pUsb->GetAddressPool().FreeAddress(bAddress); + + bConfNum = 0; + bIfaceNum = 0; + bNumEP = 1; + bAddress = 0; + qNextPollTime = 0; + bPollEnable = false; + + return 0; +} + +template +uint8_t HIDBoot::Poll() { + uint8_t rcode = 0; + + if(bPollEnable && ((long)(millis() - qNextPollTime) >= 0L)) { + + // To-do: optimize manually, using the for loop only if needed. + for(int i = 0; i < epMUL(BOOT_PROTOCOL); i++) { + const uint16_t const_buff_len = 16; + uint8_t buf[const_buff_len]; + + USBTRACE3("(hidboot.h) i=", i, 0x81); + USBTRACE3("(hidboot.h) epInfo[epInterruptInIndex + i].epAddr=", epInfo[epInterruptInIndex + i].epAddr, 0x81); + USBTRACE3("(hidboot.h) epInfo[epInterruptInIndex + i].maxPktSize=", epInfo[epInterruptInIndex + i].maxPktSize, 0x81); + uint16_t read = (uint16_t)epInfo[epInterruptInIndex + i].maxPktSize; + + rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex + i].epAddr, &read, buf); + // SOME buggy dongles report extra keys (like sleep) using a 2 byte packet on the wrong endpoint. + // Since keyboard and mice must report at least 3 bytes, we ignore the extra data. + if(!rcode && read > 2) { + if(pRptParser[i]) + pRptParser[i]->Parse((HID*)this, 0, (uint8_t)read, buf); +#ifdef DEBUG_USB_HOST + // We really don't care about errors and anomalies unless we are debugging. + } else { + if(rcode != hrNAK) { + USBTRACE3("(hidboot.h) Poll:", rcode, 0x81); + } + if(!rcode && read) { + USBTRACE3("(hidboot.h) Strange read count: ", read, 0x80); + USBTRACE3("(hidboot.h) Interface:", i, 0x80); + } + } + + if(!rcode && read && (UsbDEBUGlvl > 0x7f)) { + for(uint8_t i = 0; i < read; i++) { + PrintHex (buf[i], 0x80); + USBTRACE1(" ", 0x80); + } + if(read) + USBTRACE1("\r\n", 0x80); +#endif + } + + } + qNextPollTime = millis() + bInterval; + } + return rcode; +} + +#endif // __HIDBOOTMOUSE_H__ diff --git a/lib/usbhost/USB_Host_Shield_2.0/hidescriptorparser.cpp b/lib/usbhost/USB_Host_Shield_2.0/hidescriptorparser.cpp new file mode 100644 index 0000000000..e4491b4e97 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/hidescriptorparser.cpp @@ -0,0 +1,1588 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ + +#include "hidescriptorparser.h" + +const char * const ReportDescParserBase::usagePageTitles0[] PROGMEM = { + pstrUsagePageGenericDesktopControls, + pstrUsagePageSimulationControls, + pstrUsagePageVRControls, + pstrUsagePageSportControls, + pstrUsagePageGameControls, + pstrUsagePageGenericDeviceControls, + pstrUsagePageKeyboardKeypad, + pstrUsagePageLEDs, + pstrUsagePageButton, + pstrUsagePageOrdinal, + pstrUsagePageTelephone, + pstrUsagePageConsumer, + pstrUsagePageDigitizer, + pstrUsagePagePID, + pstrUsagePageUnicode +}; + +const char * const ReportDescParserBase::usagePageTitles1[] PROGMEM = { + pstrUsagePageBarCodeScanner, + pstrUsagePageScale, + pstrUsagePageMSRDevices, + pstrUsagePagePointOfSale, + pstrUsagePageCameraControl, + pstrUsagePageArcade +}; +const char * const ReportDescParserBase::genDesktopTitles0[] PROGMEM = { + pstrUsagePointer, + pstrUsageMouse, + pstrUsageJoystick, + pstrUsageGamePad, + pstrUsageKeyboard, + pstrUsageKeypad, + pstrUsageMultiAxisController, + pstrUsageTabletPCSystemControls + +}; +const char * const ReportDescParserBase::genDesktopTitles1[] PROGMEM = { + pstrUsageX, + pstrUsageY, + pstrUsageZ, + pstrUsageRx, + pstrUsageRy, + pstrUsageRz, + pstrUsageSlider, + pstrUsageDial, + pstrUsageWheel, + pstrUsageHatSwitch, + pstrUsageCountedBuffer, + pstrUsageByteCount, + pstrUsageMotionWakeup, + pstrUsageStart, + pstrUsageSelect, + pstrUsagePageReserved, + pstrUsageVx, + pstrUsageVy, + pstrUsageVz, + pstrUsageVbrx, + pstrUsageVbry, + pstrUsageVbrz, + pstrUsageVno, + pstrUsageFeatureNotification, + pstrUsageResolutionMultiplier +}; +const char * const ReportDescParserBase::genDesktopTitles2[] PROGMEM = { + pstrUsageSystemControl, + pstrUsageSystemPowerDown, + pstrUsageSystemSleep, + pstrUsageSystemWakeup, + pstrUsageSystemContextMenu, + pstrUsageSystemMainMenu, + pstrUsageSystemAppMenu, + pstrUsageSystemMenuHelp, + pstrUsageSystemMenuExit, + pstrUsageSystemMenuSelect, + pstrUsageSystemMenuRight, + pstrUsageSystemMenuLeft, + pstrUsageSystemMenuUp, + pstrUsageSystemMenuDown, + pstrUsageSystemColdRestart, + pstrUsageSystemWarmRestart, + pstrUsageDPadUp, + pstrUsageDPadDown, + pstrUsageDPadRight, + pstrUsageDPadLeft +}; +const char * const ReportDescParserBase::genDesktopTitles3[] PROGMEM = { + pstrUsageSystemDock, + pstrUsageSystemUndock, + pstrUsageSystemSetup, + pstrUsageSystemBreak, + pstrUsageSystemDebuggerBreak, + pstrUsageApplicationBreak, + pstrUsageApplicationDebuggerBreak, + pstrUsageSystemSpeakerMute, + pstrUsageSystemHibernate +}; +const char * const ReportDescParserBase::genDesktopTitles4[] PROGMEM = { + pstrUsageSystemDisplayInvert, + pstrUsageSystemDisplayInternal, + pstrUsageSystemDisplayExternal, + pstrUsageSystemDisplayBoth, + pstrUsageSystemDisplayDual, + pstrUsageSystemDisplayToggleIntExt, + pstrUsageSystemDisplaySwapPriSec, + pstrUsageSystemDisplayLCDAutoscale +}; +const char * const ReportDescParserBase::simuTitles0[] PROGMEM = { + pstrUsageFlightSimulationDevice, + pstrUsageAutomobileSimulationDevice, + pstrUsageTankSimulationDevice, + pstrUsageSpaceshipSimulationDevice, + pstrUsageSubmarineSimulationDevice, + pstrUsageSailingSimulationDevice, + pstrUsageMotocicleSimulationDevice, + pstrUsageSportsSimulationDevice, + pstrUsageAirplaneSimulationDevice, + pstrUsageHelicopterSimulationDevice, + pstrUsageMagicCarpetSimulationDevice, + pstrUsageBicycleSimulationDevice +}; +const char * const ReportDescParserBase::simuTitles1[] PROGMEM = { + pstrUsageFlightControlStick, + pstrUsageFlightStick, + pstrUsageCyclicControl, + pstrUsageCyclicTrim, + pstrUsageFlightYoke, + pstrUsageTrackControl +}; +const char * const ReportDescParserBase::simuTitles2[] PROGMEM = { + pstrUsageAileron, + pstrUsageAileronTrim, + pstrUsageAntiTorqueControl, + pstrUsageAutopilotEnable, + pstrUsageChaffRelease, + pstrUsageCollectiveControl, + pstrUsageDiveBrake, + pstrUsageElectronicCountermeasures, + pstrUsageElevator, + pstrUsageElevatorTrim, + pstrUsageRudder, + pstrUsageThrottle, + pstrUsageFlightCommunications, + pstrUsageFlareRelease, + pstrUsageLandingGear, + pstrUsageToeBrake, + pstrUsageTrigger, + pstrUsageWeaponsArm, + pstrUsageWeaponsSelect, + pstrUsageWingFlaps, + pstrUsageAccelerator, + pstrUsageBrake, + pstrUsageClutch, + pstrUsageShifter, + pstrUsageSteering, + pstrUsageTurretDirection, + pstrUsageBarrelElevation, + pstrUsageDivePlane, + pstrUsageBallast, + pstrUsageBicycleCrank, + pstrUsageHandleBars, + pstrUsageFrontBrake, + pstrUsageRearBrake +}; +const char * const ReportDescParserBase::vrTitles0[] PROGMEM = { + pstrUsageBelt, + pstrUsageBodySuit, + pstrUsageFlexor, + pstrUsageGlove, + pstrUsageHeadTracker, + pstrUsageHeadMountedDisplay, + pstrUsageHandTracker, + pstrUsageOculometer, + pstrUsageVest, + pstrUsageAnimatronicDevice +}; +const char * const ReportDescParserBase::vrTitles1[] PROGMEM = { + pstrUsageStereoEnable, + pstrUsageDisplayEnable +}; +const char * const ReportDescParserBase::sportsCtrlTitles0[] PROGMEM = { + pstrUsageBaseballBat, + pstrUsageGolfClub, + pstrUsageRowingMachine, + pstrUsageTreadmill +}; +const char * const ReportDescParserBase::sportsCtrlTitles1[] PROGMEM = { + pstrUsageOar, + pstrUsageSlope, + pstrUsageRate, + pstrUsageStickSpeed, + pstrUsageStickFaceAngle, + pstrUsageStickHeelToe, + pstrUsageStickFollowThough, + pstrUsageStickTempo, + pstrUsageStickType, + pstrUsageStickHeight +}; +const char * const ReportDescParserBase::sportsCtrlTitles2[] PROGMEM = { + pstrUsagePutter, + pstrUsage1Iron, + pstrUsage2Iron, + pstrUsage3Iron, + pstrUsage4Iron, + pstrUsage5Iron, + pstrUsage6Iron, + pstrUsage7Iron, + pstrUsage8Iron, + pstrUsage9Iron, + pstrUsage10Iron, + pstrUsage11Iron, + pstrUsageSandWedge, + pstrUsageLoftWedge, + pstrUsagePowerWedge, + pstrUsage1Wood, + pstrUsage3Wood, + pstrUsage5Wood, + pstrUsage7Wood, + pstrUsage9Wood +}; +const char * const ReportDescParserBase::gameTitles0[] PROGMEM = { + pstrUsage3DGameController, + pstrUsagePinballDevice, + pstrUsageGunDevice +}; +const char * const ReportDescParserBase::gameTitles1[] PROGMEM = { + pstrUsagePointOfView, + pstrUsageTurnRightLeft, + pstrUsagePitchForwardBackward, + pstrUsageRollRightLeft, + pstrUsageMoveRightLeft, + pstrUsageMoveForwardBackward, + pstrUsageMoveUpDown, + pstrUsageLeanRightLeft, + pstrUsageLeanForwardBackward, + pstrUsageHeightOfPOV, + pstrUsageFlipper, + pstrUsageSecondaryFlipper, + pstrUsageBump, + pstrUsageNewGame, + pstrUsageShootBall, + pstrUsagePlayer, + pstrUsageGunBolt, + pstrUsageGunClip, + pstrUsageGunSelector, + pstrUsageGunSingleShot, + pstrUsageGunBurst, + pstrUsageGunAutomatic, + pstrUsageGunSafety, + pstrUsageGamepadFireJump, + pstrUsageGamepadTrigger +}; +const char * const ReportDescParserBase::genDevCtrlTitles[] PROGMEM = { + pstrUsageBatteryStrength, + pstrUsageWirelessChannel, + pstrUsageWirelessID, + pstrUsageDiscoverWirelessControl, + pstrUsageSecurityCodeCharEntered, + pstrUsageSecurityCodeCharErased, + pstrUsageSecurityCodeCleared +}; +const char * const ReportDescParserBase::ledTitles[] PROGMEM = { + pstrUsageNumLock, + pstrUsageCapsLock, + pstrUsageScrollLock, + pstrUsageCompose, + pstrUsageKana, + pstrUsagePower, + pstrUsageShift, + pstrUsageDoNotDisturb, + pstrUsageMute, + pstrUsageToneEnable, + pstrUsageHighCutFilter, + pstrUsageLowCutFilter, + pstrUsageEqualizerEnable, + pstrUsageSoundFieldOn, + pstrUsageSurroundOn, + pstrUsageRepeat, + pstrUsageStereo, + pstrUsageSamplingRateDetect, + pstrUsageSpinning, + pstrUsageCAV, + pstrUsageCLV, + pstrUsageRecordingFormatDetect, + pstrUsageOffHook, + pstrUsageRing, + pstrUsageMessageWaiting, + pstrUsageDataMode, + pstrUsageBatteryOperation, + pstrUsageBatteryOK, + pstrUsageBatteryLow, + pstrUsageSpeaker, + pstrUsageHeadSet, + pstrUsageHold, + pstrUsageMicrophone, + pstrUsageCoverage, + pstrUsageNightMode, + pstrUsageSendCalls, + pstrUsageCallPickup, + pstrUsageConference, + pstrUsageStandBy, + pstrUsageCameraOn, + pstrUsageCameraOff, + pstrUsageOnLine, + pstrUsageOffLine, + pstrUsageBusy, + pstrUsageReady, + pstrUsagePaperOut, + pstrUsagePaperJam, + pstrUsageRemote, + pstrUsageForward, + pstrUsageReverse, + pstrUsageStop, + pstrUsageRewind, + pstrUsageFastForward, + pstrUsagePlay, + pstrUsagePause, + pstrUsageRecord, + pstrUsageError, + pstrUsageSelectedIndicator, + pstrUsageInUseIndicator, + pstrUsageMultiModeIndicator, + pstrUsageIndicatorOn, + pstrUsageIndicatorFlash, + pstrUsageIndicatorSlowBlink, + pstrUsageIndicatorFastBlink, + pstrUsageIndicatorOff, + pstrUsageFlashOnTime, + pstrUsageSlowBlinkOnTime, + pstrUsageSlowBlinkOffTime, + pstrUsageFastBlinkOnTime, + pstrUsageFastBlinkOffTime, + pstrUsageIndicatorColor, + pstrUsageIndicatorRed, + pstrUsageIndicatorGreen, + pstrUsageIndicatorAmber, + pstrUsageGenericIndicator, + pstrUsageSystemSuspend, + pstrUsageExternalPowerConnected +}; +const char * const ReportDescParserBase::telTitles0 [] PROGMEM = { + pstrUsagePhone, + pstrUsageAnsweringMachine, + pstrUsageMessageControls, + pstrUsageHandset, + pstrUsageHeadset, + pstrUsageTelephonyKeyPad, + pstrUsageProgrammableButton +}; +const char * const ReportDescParserBase::telTitles1 [] PROGMEM = { + pstrUsageHookSwitch, + pstrUsageFlash, + pstrUsageFeature, + pstrUsageHold, + pstrUsageRedial, + pstrUsageTransfer, + pstrUsageDrop, + pstrUsagePark, + pstrUsageForwardCalls, + pstrUsageAlternateFunction, + pstrUsageLine, + pstrUsageSpeakerPhone, + pstrUsageConference, + pstrUsageRingEnable, + pstrUsageRingSelect, + pstrUsagePhoneMute, + pstrUsageCallerID, + pstrUsageSend +}; +const char * const ReportDescParserBase::telTitles2 [] PROGMEM = { + pstrUsageSpeedDial, + pstrUsageStoreNumber, + pstrUsageRecallNumber, + pstrUsagePhoneDirectory +}; +const char * const ReportDescParserBase::telTitles3 [] PROGMEM = { + pstrUsageVoiceMail, + pstrUsageScreenCalls, + pstrUsageDoNotDisturb, + pstrUsageMessage, + pstrUsageAnswerOnOff +}; +const char * const ReportDescParserBase::telTitles4 [] PROGMEM = { + pstrUsageInsideDialTone, + pstrUsageOutsideDialTone, + pstrUsageInsideRingTone, + pstrUsageOutsideRingTone, + pstrUsagePriorityRingTone, + pstrUsageInsideRingback, + pstrUsagePriorityRingback, + pstrUsageLineBusyTone, + pstrUsageReorderTone, + pstrUsageCallWaitingTone, + pstrUsageConfirmationTone1, + pstrUsageConfirmationTone2, + pstrUsageTonesOff, + pstrUsageOutsideRingback, + pstrUsageRinger +}; +const char * const ReportDescParserBase::telTitles5 [] PROGMEM = { + pstrUsagePhoneKey0, + pstrUsagePhoneKey1, + pstrUsagePhoneKey2, + pstrUsagePhoneKey3, + pstrUsagePhoneKey4, + pstrUsagePhoneKey5, + pstrUsagePhoneKey6, + pstrUsagePhoneKey7, + pstrUsagePhoneKey8, + pstrUsagePhoneKey9, + pstrUsagePhoneKeyStar, + pstrUsagePhoneKeyPound, + pstrUsagePhoneKeyA, + pstrUsagePhoneKeyB, + pstrUsagePhoneKeyC, + pstrUsagePhoneKeyD +}; +const char * const ReportDescParserBase::consTitles0[] PROGMEM = { + pstrUsageConsumerControl, + pstrUsageNumericKeyPad, + pstrUsageProgrammableButton, + pstrUsageMicrophone, + pstrUsageHeadphone, + pstrUsageGraphicEqualizer +}; +const char * const ReportDescParserBase::consTitles1[] PROGMEM = { + pstrUsagePlus10, + pstrUsagePlus100, + pstrUsageAMPM +}; +const char * const ReportDescParserBase::consTitles2[] PROGMEM = { + pstrUsagePower, + pstrUsageReset, + pstrUsageSleep, + pstrUsageSleepAfter, + pstrUsageSleepMode, + pstrUsageIllumination, + pstrUsageFunctionButtons + +}; +const char * const ReportDescParserBase::consTitles3[] PROGMEM = { + pstrUsageMenu, + pstrUsageMenuPick, + pstrUsageMenuUp, + pstrUsageMenuDown, + pstrUsageMenuLeft, + pstrUsageMenuRight, + pstrUsageMenuEscape, + pstrUsageMenuValueIncrease, + pstrUsageMenuValueDecrease +}; +const char * const ReportDescParserBase::consTitles4[] PROGMEM = { + pstrUsageDataOnScreen, + pstrUsageClosedCaption, + pstrUsageClosedCaptionSelect, + pstrUsageVCRTV, + pstrUsageBroadcastMode, + pstrUsageSnapshot, + pstrUsageStill +}; +const char * const ReportDescParserBase::consTitles5[] PROGMEM = { + pstrUsageSelection, + pstrUsageAssignSelection, + pstrUsageModeStep, + pstrUsageRecallLast, + pstrUsageEnterChannel, + pstrUsageOrderMovie, + pstrUsageChannel, + pstrUsageMediaSelection, + pstrUsageMediaSelectComputer, + pstrUsageMediaSelectTV, + pstrUsageMediaSelectWWW, + pstrUsageMediaSelectDVD, + pstrUsageMediaSelectTelephone, + pstrUsageMediaSelectProgramGuide, + pstrUsageMediaSelectVideoPhone, + pstrUsageMediaSelectGames, + pstrUsageMediaSelectMessages, + pstrUsageMediaSelectCD, + pstrUsageMediaSelectVCR, + pstrUsageMediaSelectTuner, + pstrUsageQuit, + pstrUsageHelp, + pstrUsageMediaSelectTape, + pstrUsageMediaSelectCable, + pstrUsageMediaSelectSatellite, + pstrUsageMediaSelectSecurity, + pstrUsageMediaSelectHome, + pstrUsageMediaSelectCall, + pstrUsageChannelIncrement, + pstrUsageChannelDecrement, + pstrUsageMediaSelectSAP, + pstrUsagePageReserved, + pstrUsageVCRPlus, + pstrUsageOnce, + pstrUsageDaily, + pstrUsageWeekly, + pstrUsageMonthly +}; +const char * const ReportDescParserBase::consTitles6[] PROGMEM = { + pstrUsagePlay, + pstrUsagePause, + pstrUsageRecord, + pstrUsageFastForward, + pstrUsageRewind, + pstrUsageScanNextTrack, + pstrUsageScanPreviousTrack, + pstrUsageStop, + pstrUsageEject, + pstrUsageRandomPlay, + pstrUsageSelectDisk, + pstrUsageEnterDisk, + pstrUsageRepeat, + pstrUsageTracking, + pstrUsageTrackNormal, + pstrUsageSlowTracking, + pstrUsageFrameForward, + pstrUsageFrameBackwards, + pstrUsageMark, + pstrUsageClearMark, + pstrUsageRepeatFromMark, + pstrUsageReturnToMark, + pstrUsageSearchMarkForward, + pstrUsageSearchMarkBackwards, + pstrUsageCounterReset, + pstrUsageShowCounter, + pstrUsageTrackingIncrement, + pstrUsageTrackingDecrement, + pstrUsageStopEject, + pstrUsagePlayPause, + pstrUsagePlaySkip +}; +const char * const ReportDescParserBase::consTitles7[] PROGMEM = { + pstrUsageVolume, + pstrUsageBalance, + pstrUsageMute, + pstrUsageBass, + pstrUsageTreble, + pstrUsageBassBoost, + pstrUsageSurroundMode, + pstrUsageLoudness, + pstrUsageMPX, + pstrUsageVolumeIncrement, + pstrUsageVolumeDecrement +}; +const char * const ReportDescParserBase::consTitles8[] PROGMEM = { + pstrUsageSpeedSelect, + pstrUsagePlaybackSpeed, + pstrUsageStandardPlay, + pstrUsageLongPlay, + pstrUsageExtendedPlay, + pstrUsageSlow +}; +const char * const ReportDescParserBase::consTitles9[] PROGMEM = { + pstrUsageFanEnable, + pstrUsageFanSpeed, + pstrUsageLightEnable, + pstrUsageLightIlluminationLevel, + pstrUsageClimateControlEnable, + pstrUsageRoomTemperature, + pstrUsageSecurityEnable, + pstrUsageFireAlarm, + pstrUsagePoliceAlarm, + pstrUsageProximity, + pstrUsageMotion, + pstrUsageDuresAlarm, + pstrUsageHoldupAlarm, + pstrUsageMedicalAlarm +}; +const char * const ReportDescParserBase::consTitlesA[] PROGMEM = { + pstrUsageBalanceRight, + pstrUsageBalanceLeft, + pstrUsageBassIncrement, + pstrUsageBassDecrement, + pstrUsageTrebleIncrement, + pstrUsageTrebleDecrement +}; +const char * const ReportDescParserBase::consTitlesB[] PROGMEM = { + pstrUsageSpeakerSystem, + pstrUsageChannelLeft, + pstrUsageChannelRight, + pstrUsageChannelCenter, + pstrUsageChannelFront, + pstrUsageChannelCenterFront, + pstrUsageChannelSide, + pstrUsageChannelSurround, + pstrUsageChannelLowFreqEnhancement, + pstrUsageChannelTop, + pstrUsageChannelUnknown +}; +const char * const ReportDescParserBase::consTitlesC[] PROGMEM = { + pstrUsageSubChannel, + pstrUsageSubChannelIncrement, + pstrUsageSubChannelDecrement, + pstrUsageAlternateAudioIncrement, + pstrUsageAlternateAudioDecrement +}; +const char * const ReportDescParserBase::consTitlesD[] PROGMEM = { + pstrUsageApplicationLaunchButtons, + pstrUsageALLaunchButtonConfigTool, + pstrUsageALProgrammableButton, + pstrUsageALConsumerControlConfig, + pstrUsageALWordProcessor, + pstrUsageALTextEditor, + pstrUsageALSpreadsheet, + pstrUsageALGraphicsEditor, + pstrUsageALPresentationApp, + pstrUsageALDatabaseApp, + pstrUsageALEmailReader, + pstrUsageALNewsreader, + pstrUsageALVoicemail, + pstrUsageALContactsAddressBook, + pstrUsageALCalendarSchedule, + pstrUsageALTaskProjectManager, + pstrUsageALLogJournalTimecard, + pstrUsageALCheckbookFinance, + pstrUsageALCalculator, + pstrUsageALAVCapturePlayback, + pstrUsageALLocalMachineBrowser, + pstrUsageALLANWANBrow, + pstrUsageALInternetBrowser, + pstrUsageALRemoteNetISPConnect, + pstrUsageALNetworkConference, + pstrUsageALNetworkChat, + pstrUsageALTelephonyDialer, + pstrUsageALLogon, + pstrUsageALLogoff, + pstrUsageALLogonLogoff, + pstrUsageALTermLockScrSav, + pstrUsageALControlPannel, + pstrUsageALCommandLineProcessorRun, + pstrUsageALProcessTaskManager, + pstrUsageALSelectTaskApplication, + pstrUsageALNextTaskApplication, + pstrUsageALPreviousTaskApplication, + pstrUsageALPreemptiveHaltTaskApp, + pstrUsageALIntegratedHelpCenter, + pstrUsageALDocuments, + pstrUsageALThesaurus, + pstrUsageALDictionary, + pstrUsageALDesktop, + pstrUsageALSpellCheck, + pstrUsageALGrammarCheck, + pstrUsageALWirelessStatus, + pstrUsageALKeyboardLayout, + pstrUsageALVirusProtection, + pstrUsageALEncryption, + pstrUsageALScreenSaver, + pstrUsageALAlarms, + pstrUsageALClock, + pstrUsageALFileBrowser, + pstrUsageALPowerStatus, + pstrUsageALImageBrowser, + pstrUsageALAudioBrowser, + pstrUsageALMovieBrowser, + pstrUsageALDigitalRightsManager, + pstrUsageALDigitalWallet, + pstrUsagePageReserved, + pstrUsageALInstantMessaging, + pstrUsageALOEMFeaturesBrowser, + pstrUsageALOEMHelp, + pstrUsageALOnlineCommunity, + pstrUsageALEntertainmentContentBrow, + pstrUsageALOnlineShoppingBrowser, + pstrUsageALSmartCardInfoHelp, + pstrUsageALMarketMonitorFinBrowser, + pstrUsageALCustomCorpNewsBrowser, + pstrUsageALOnlineActivityBrowser, + pstrUsageALResearchSearchBrowser, + pstrUsageALAudioPlayer +}; +const char * const ReportDescParserBase::consTitlesE[] PROGMEM = { + pstrUsageGenericGUIAppControls, + pstrUsageACNew, + pstrUsageACOpen, + pstrUsageACClose, + pstrUsageACExit, + pstrUsageACMaximize, + pstrUsageACMinimize, + pstrUsageACSave, + pstrUsageACPrint, + pstrUsageACProperties, + pstrUsageACUndo, + pstrUsageACCopy, + pstrUsageACCut, + pstrUsageACPaste, + pstrUsageACSelectAll, + pstrUsageACFind, + pstrUsageACFindAndReplace, + pstrUsageACSearch, + pstrUsageACGoto, + pstrUsageACHome, + pstrUsageACBack, + pstrUsageACForward, + pstrUsageACStop, + pstrUsageACRefresh, + pstrUsageACPreviousLink, + pstrUsageACNextLink, + pstrUsageACBookmarks, + pstrUsageACHistory, + pstrUsageACSubscriptions, + pstrUsageACZoomIn, + pstrUsageACZoomOut, + pstrUsageACZoom, + pstrUsageACFullScreenView, + pstrUsageACNormalView, + pstrUsageACViewToggle, + pstrUsageACScrollUp, + pstrUsageACScrollDown, + pstrUsageACScroll, + pstrUsageACPanLeft, + pstrUsageACPanRight, + pstrUsageACPan, + pstrUsageACNewWindow, + pstrUsageACTileHoriz, + pstrUsageACTileVert, + pstrUsageACFormat, + pstrUsageACEdit, + pstrUsageACBold, + pstrUsageACItalics, + pstrUsageACUnderline, + pstrUsageACStrikethrough, + pstrUsageACSubscript, + pstrUsageACSuperscript, + pstrUsageACAllCaps, + pstrUsageACRotate, + pstrUsageACResize, + pstrUsageACFlipHorizontal, + pstrUsageACFlipVertical, + pstrUsageACMirrorHorizontal, + pstrUsageACMirrorVertical, + pstrUsageACFontSelect, + pstrUsageACFontColor, + pstrUsageACFontSize, + pstrUsageACJustifyLeft, + pstrUsageACJustifyCenterH, + pstrUsageACJustifyRight, + pstrUsageACJustifyBlockH, + pstrUsageACJustifyTop, + pstrUsageACJustifyCenterV, + pstrUsageACJustifyBottom, + pstrUsageACJustifyBlockV, + pstrUsageACIndentDecrease, + pstrUsageACIndentIncrease, + pstrUsageACNumberedList, + pstrUsageACRestartNumbering, + pstrUsageACBulletedList, + pstrUsageACPromote, + pstrUsageACDemote, + pstrUsageACYes, + pstrUsageACNo, + pstrUsageACCancel, + pstrUsageACCatalog, + pstrUsageACBuyChkout, + pstrUsageACAddToCart, + pstrUsageACExpand, + pstrUsageACExpandAll, + pstrUsageACCollapse, + pstrUsageACCollapseAll, + pstrUsageACPrintPreview, + pstrUsageACPasteSpecial, + pstrUsageACInsertMode, + pstrUsageACDelete, + pstrUsageACLock, + pstrUsageACUnlock, + pstrUsageACProtect, + pstrUsageACUnprotect, + pstrUsageACAttachComment, + pstrUsageACDeleteComment, + pstrUsageACViewComment, + pstrUsageACSelectWord, + pstrUsageACSelectSentence, + pstrUsageACSelectParagraph, + pstrUsageACSelectColumn, + pstrUsageACSelectRow, + pstrUsageACSelectTable, + pstrUsageACSelectObject, + pstrUsageACRedoRepeat, + pstrUsageACSort, + pstrUsageACSortAscending, + pstrUsageACSortDescending, + pstrUsageACFilter, + pstrUsageACSetClock, + pstrUsageACViewClock, + pstrUsageACSelectTimeZone, + pstrUsageACEditTimeZone, + pstrUsageACSetAlarm, + pstrUsageACClearAlarm, + pstrUsageACSnoozeAlarm, + pstrUsageACResetAlarm, + pstrUsageACSyncronize, + pstrUsageACSendReceive, + pstrUsageACSendTo, + pstrUsageACReply, + pstrUsageACReplyAll, + pstrUsageACForwardMessage, + pstrUsageACSend, + pstrUsageACAttachFile, + pstrUsageACUpload, + pstrUsageACDownload, + pstrUsageACSetBorders, + pstrUsageACInsertRow, + pstrUsageACInsertColumn, + pstrUsageACInsertFile, + pstrUsageACInsertPicture, + pstrUsageACInsertObject, + pstrUsageACInsertSymbol, + pstrUsageACSaveAndClose, + pstrUsageACRename, + pstrUsageACMerge, + pstrUsageACSplit, + pstrUsageACDistributeHorizontaly, + pstrUsageACDistributeVerticaly +}; +const char * const ReportDescParserBase::digitTitles0[] PROGMEM = { + pstrUsageDigitizer, + pstrUsagePen, + pstrUsageLightPen, + pstrUsageTouchScreen, + pstrUsageTouchPad, + pstrUsageWhiteBoard, + pstrUsageCoordinateMeasuringMachine, + pstrUsage3DDigitizer, + pstrUsageStereoPlotter, + pstrUsageArticulatedArm, + pstrUsageArmature, + pstrUsageMultiplePointDigitizer, + pstrUsageFreeSpaceWand +}; +const char * const ReportDescParserBase::digitTitles1[] PROGMEM = { + pstrUsageStylus, + pstrUsagePuck, + pstrUsageFinger + +}; +const char * const ReportDescParserBase::digitTitles2[] PROGMEM = { + pstrUsageTipPressure, + pstrUsageBarrelPressure, + pstrUsageInRange, + pstrUsageTouch, + pstrUsageUntouch, + pstrUsageTap, + pstrUsageQuality, + pstrUsageDataValid, + pstrUsageTransducerIndex, + pstrUsageTabletFunctionKeys, + pstrUsageProgramChangeKeys, + pstrUsageBatteryStrength, + pstrUsageInvert, + pstrUsageXTilt, + pstrUsageYTilt, + pstrUsageAzimuth, + pstrUsageAltitude, + pstrUsageTwist, + pstrUsageTipSwitch, + pstrUsageSecondaryTipSwitch, + pstrUsageBarrelSwitch, + pstrUsageEraser, + pstrUsageTabletPick +}; +const char * const ReportDescParserBase::aplphanumTitles0[] PROGMEM = { + pstrUsageAlphanumericDisplay, + pstrUsageBitmappedDisplay +}; +const char * const ReportDescParserBase::aplphanumTitles1[] PROGMEM = { + pstrUsageDisplayAttributesReport, + pstrUsageASCIICharacterSet, + pstrUsageDataReadBack, + pstrUsageFontReadBack, + pstrUsageDisplayControlReport, + pstrUsageClearDisplay, + pstrUsageDisplayEnable, + pstrUsageScreenSaverDelay, + pstrUsageScreenSaverEnable, + pstrUsageVerticalScroll, + pstrUsageHorizontalScroll, + pstrUsageCharacterReport, + pstrUsageDisplayData, + pstrUsageDisplayStatus, + pstrUsageStatusNotReady, + pstrUsageStatusReady, + pstrUsageErrorNotALoadableCharacter, + pstrUsageErrorFotDataCanNotBeRead, + pstrUsageCursorPositionReport, + pstrUsageRow, + pstrUsageColumn, + pstrUsageRows, + pstrUsageColumns, + pstrUsageCursorPixelPosition, + pstrUsageCursorMode, + pstrUsageCursorEnable, + pstrUsageCursorBlink, + pstrUsageFontReport, + pstrUsageFontData, + pstrUsageCharacterWidth, + pstrUsageCharacterHeight, + pstrUsageCharacterSpacingHorizontal, + pstrUsageCharacterSpacingVertical, + pstrUsageUnicodeCharset, + pstrUsageFont7Segment, + pstrUsage7SegmentDirectMap, + pstrUsageFont14Segment, + pstrUsage14SegmentDirectMap, + pstrUsageDisplayBrightness, + pstrUsageDisplayContrast, + pstrUsageCharacterAttribute, + pstrUsageAttributeReadback, + pstrUsageAttributeData, + pstrUsageCharAttributeEnhance, + pstrUsageCharAttributeUnderline, + pstrUsageCharAttributeBlink +}; +const char * const ReportDescParserBase::aplphanumTitles2[] PROGMEM = { + pstrUsageBitmapSizeX, + pstrUsageBitmapSizeY, + pstrUsagePageReserved, + pstrUsageBitDepthFormat, + pstrUsageDisplayOrientation, + pstrUsagePaletteReport, + pstrUsagePaletteDataSize, + pstrUsagePaletteDataOffset, + pstrUsagePaletteData, + pstrUsageBlitReport, + pstrUsageBlitRectangleX1, + pstrUsageBlitRectangleY1, + pstrUsageBlitRectangleX2, + pstrUsageBlitRectangleY2, + pstrUsageBlitData, + pstrUsageSoftButton, + pstrUsageSoftButtonID, + pstrUsageSoftButtonSide, + pstrUsageSoftButtonOffset1, + pstrUsageSoftButtonOffset2, + pstrUsageSoftButtonReport +}; +const char * const ReportDescParserBase::medInstrTitles0[] PROGMEM = { + pstrUsageVCRAcquisition, + pstrUsageFreezeThaw, + pstrUsageClipStore, + pstrUsageUpdate, + pstrUsageNext, + pstrUsageSave, + pstrUsagePrint, + pstrUsageMicrophoneEnable +}; +const char * const ReportDescParserBase::medInstrTitles1[] PROGMEM = { + pstrUsageCine, + pstrUsageTransmitPower, + pstrUsageVolume, + pstrUsageFocus, + pstrUsageDepth +}; +const char * const ReportDescParserBase::medInstrTitles2[] PROGMEM = { + pstrUsageSoftStepPrimary, + pstrUsageSoftStepSecondary +}; +const char * const ReportDescParserBase::medInstrTitles3[] PROGMEM = { + pstrUsageZoomSelect, + pstrUsageZoomAdjust, + pstrUsageSpectralDopplerModeSelect, + pstrUsageSpectralDopplerModeAdjust, + pstrUsageColorDopplerModeSelect, + pstrUsageColorDopplerModeAdjust, + pstrUsageMotionModeSelect, + pstrUsageMotionModeAdjust, + pstrUsage2DModeSelect, + pstrUsage2DModeAdjust +}; +const char * const ReportDescParserBase::medInstrTitles4[] PROGMEM = { + pstrUsageSoftControlSelect, + pstrUsageSoftControlAdjust +}; + +void ReportDescParserBase::Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset) { + uint16_t cntdn = (uint16_t)len; + uint8_t *p = (uint8_t*)pbuf; + + + totalSize = 0; + + while(cntdn) { + //USB_HOST_SERIAL.println(""); + //PrintHex(offset + len - cntdn); + //USB_HOST_SERIAL.print(":"); + + ParseItem(&p, &cntdn); + + //if (ParseItem(&p, &cntdn)) + // return; + } + //USBTRACE2("Total:", totalSize); +} + +void ReportDescParserBase::PrintValue(uint8_t *p, uint8_t len) { + E_Notify(PSTR("("), 0x80); + for(; len; p++, len--) + PrintHex (*p, 0x80); + E_Notify(PSTR(")"), 0x80); +} + +void ReportDescParserBase::PrintByteValue(uint8_t data) { + E_Notify(PSTR("("), 0x80); + PrintHex (data, 0x80); + E_Notify(PSTR(")"), 0x80); +} + +void ReportDescParserBase::PrintItemTitle(uint8_t prefix) { + switch(prefix & (TYPE_MASK | TAG_MASK)) { + case (TYPE_GLOBAL | TAG_GLOBAL_PUSH): + E_Notify(PSTR("\r\nPush"), 0x80); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_POP): + E_Notify(PSTR("\r\nPop"), 0x80); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_USAGEPAGE): + E_Notify(PSTR("\r\nUsage Page"), 0x80); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMIN): + E_Notify(PSTR("\r\nLogical Min"), 0x80); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMAX): + E_Notify(PSTR("\r\nLogical Max"), 0x80); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMIN): + E_Notify(PSTR("\r\nPhysical Min"), 0x80); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMAX): + E_Notify(PSTR("\r\nPhysical Max"), 0x80); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_UNITEXP): + E_Notify(PSTR("\r\nUnit Exp"), 0x80); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_UNIT): + E_Notify(PSTR("\r\nUnit"), 0x80); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_REPORTSIZE): + E_Notify(PSTR("\r\nReport Size"), 0x80); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_REPORTCOUNT): + E_Notify(PSTR("\r\nReport Count"), 0x80); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_REPORTID): + E_Notify(PSTR("\r\nReport Id"), 0x80); + break; + case (TYPE_LOCAL | TAG_LOCAL_USAGE): + E_Notify(PSTR("\r\nUsage"), 0x80); + break; + case (TYPE_LOCAL | TAG_LOCAL_USAGEMIN): + E_Notify(PSTR("\r\nUsage Min"), 0x80); + break; + case (TYPE_LOCAL | TAG_LOCAL_USAGEMAX): + E_Notify(PSTR("\r\nUsage Max"), 0x80); + break; + case (TYPE_MAIN | TAG_MAIN_COLLECTION): + E_Notify(PSTR("\r\nCollection"), 0x80); + break; + case (TYPE_MAIN | TAG_MAIN_ENDCOLLECTION): + E_Notify(PSTR("\r\nEnd Collection"), 0x80); + break; + case (TYPE_MAIN | TAG_MAIN_INPUT): + E_Notify(PSTR("\r\nInput"), 0x80); + break; + case (TYPE_MAIN | TAG_MAIN_OUTPUT): + E_Notify(PSTR("\r\nOutput"), 0x80); + break; + case (TYPE_MAIN | TAG_MAIN_FEATURE): + E_Notify(PSTR("\r\nFeature"), 0x80); + break; + } // switch (**pp & (TYPE_MASK | TAG_MASK)) +} + +uint8_t ReportDescParserBase::ParseItem(uint8_t **pp, uint16_t *pcntdn) { + //uint8_t ret = enErrorSuccess; + //reinterpret_cast<>(varBuffer); + switch(itemParseState) { + case 0: + if(**pp == HID_LONG_ITEM_PREFIX) + USBTRACE("\r\nLONG\r\n"); + else { + uint8_t size = ((**pp) & DATA_SIZE_MASK); + + itemPrefix = (**pp); + itemSize = 1 + ((size == DATA_SIZE_4) ? 4 : size); + + PrintItemTitle(itemPrefix); + } + (*pp)++; + (*pcntdn)--; + itemSize--; + itemParseState = 1; + + if(!itemSize) + break; + + if(!pcntdn) + return enErrorIncomplete; + case 1: + //USBTRACE2("\r\niSz:",itemSize); + + theBuffer.valueSize = itemSize; + valParser.Initialize(&theBuffer); + itemParseState = 2; + case 2: + if(!valParser.Parse(pp, pcntdn)) + return enErrorIncomplete; + itemParseState = 3; + case 3: + { + uint8_t data = *((uint8_t*)varBuffer); + + switch(itemPrefix & (TYPE_MASK | TAG_MASK)) { + case (TYPE_LOCAL | TAG_LOCAL_USAGE): + if(pfUsage) { + if(theBuffer.valueSize > 1) { + uint16_t* ui16 = reinterpret_cast(varBuffer); + pfUsage(*ui16); + } else + pfUsage(data); + } + break; + case (TYPE_GLOBAL | TAG_GLOBAL_REPORTSIZE): + rptSize = data; + PrintByteValue(data); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_REPORTCOUNT): + rptCount = data; + PrintByteValue(data); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMIN): + case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMAX): + case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMIN): + case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMAX): + case (TYPE_GLOBAL | TAG_GLOBAL_REPORTID): + case (TYPE_LOCAL | TAG_LOCAL_USAGEMIN): + case (TYPE_LOCAL | TAG_LOCAL_USAGEMAX): + case (TYPE_GLOBAL | TAG_GLOBAL_UNITEXP): + case (TYPE_GLOBAL | TAG_GLOBAL_UNIT): + PrintValue(varBuffer, theBuffer.valueSize); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_PUSH): + case (TYPE_GLOBAL | TAG_GLOBAL_POP): + break; + case (TYPE_GLOBAL | TAG_GLOBAL_USAGEPAGE): + SetUsagePage(data); + PrintUsagePage(data); + PrintByteValue(data); + break; + case (TYPE_MAIN | TAG_MAIN_COLLECTION): + case (TYPE_MAIN | TAG_MAIN_ENDCOLLECTION): + switch(data) { + case 0x00: + E_Notify(PSTR(" Physical"), 0x80); + break; + case 0x01: + E_Notify(PSTR(" Application"), 0x80); + break; + case 0x02: + E_Notify(PSTR(" Logical"), 0x80); + break; + case 0x03: + E_Notify(PSTR(" Report"), 0x80); + break; + case 0x04: + E_Notify(PSTR(" Named Array"), 0x80); + break; + case 0x05: + E_Notify(PSTR(" Usage Switch"), 0x80); + break; + case 0x06: + E_Notify(PSTR(" Usage Modifier"), 0x80); + break; + default: + E_Notify(PSTR(" Vendor Defined("), 0x80); + PrintHex (data, 0x80); + E_Notify(PSTR(")"), 0x80); + } + break; + case (TYPE_MAIN | TAG_MAIN_INPUT): + case (TYPE_MAIN | TAG_MAIN_OUTPUT): + case (TYPE_MAIN | TAG_MAIN_FEATURE): + totalSize += (uint16_t)rptSize * (uint16_t)rptCount; + rptSize = 0; + rptCount = 0; + E_Notify(PSTR("("), 0x80); + PrintBin (data, 0x80); + E_Notify(PSTR(")"), 0x80); + break; + } // switch (**pp & (TYPE_MASK | TAG_MASK)) + } + } // switch (itemParseState) + itemParseState = 0; + return enErrorSuccess; +} + +ReportDescParserBase::UsagePageFunc ReportDescParserBase::usagePageFunctions[] /*PROGMEM*/ = { + &ReportDescParserBase::PrintGenericDesktopPageUsage, + &ReportDescParserBase::PrintSimulationControlsPageUsage, + &ReportDescParserBase::PrintVRControlsPageUsage, + &ReportDescParserBase::PrintSportsControlsPageUsage, + &ReportDescParserBase::PrintGameControlsPageUsage, + &ReportDescParserBase::PrintGenericDeviceControlsPageUsage, + NULL, // Keyboard/Keypad + &ReportDescParserBase::PrintLEDPageUsage, + &ReportDescParserBase::PrintButtonPageUsage, + &ReportDescParserBase::PrintOrdinalPageUsage, + &ReportDescParserBase::PrintTelephonyPageUsage, + &ReportDescParserBase::PrintConsumerPageUsage, + &ReportDescParserBase::PrintDigitizerPageUsage, + NULL, // Reserved + NULL, // PID + NULL // Unicode +}; + +void ReportDescParserBase::SetUsagePage(uint16_t page) { + pfUsage = NULL; + + if(VALUE_BETWEEN(page, 0x00, 0x11)) { + pfUsage = (usagePageFunctions[page - 1]); + + } else { + switch(page) { + case 0x14: + pfUsage = &ReportDescParserBase::PrintAlphanumDisplayPageUsage; + break; + case 0x40: + pfUsage = &ReportDescParserBase::PrintMedicalInstrumentPageUsage; + break; + } + } +} + +void ReportDescParserBase::PrintUsagePage(uint16_t page) { + const char * const * w; + E_Notify(pstrSpace, 0x80); + + output_if_between(page, 0x00, 0x11, w, E_Notify, usagePageTitles0, 0x80) + else output_if_between(page, 0x8b, 0x92, w, E_Notify, usagePageTitles1, 0x80) + else if(VALUE_BETWEEN(page, 0x7f, 0x84)) + E_Notify(pstrUsagePageMonitor, 0x80); + else if(VALUE_BETWEEN(page, 0x83, 0x8c)) + E_Notify(pstrUsagePagePower, 0x80); + else if(page > 0xfeff /* && page <= 0xffff */) + E_Notify(pstrUsagePageVendorDefined, 0x80); + else + switch(page) { + case 0x14: + E_Notify(pstrUsagePageAlphaNumericDisplay, 0x80); + break; + case 0x40: + E_Notify(pstrUsagePageMedicalInstruments, 0x80); + break; + default: + E_Notify(pstrUsagePageUndefined, 0x80); + } +} + +void ReportDescParserBase::PrintButtonPageUsage(uint16_t usage) { + E_Notify(pstrSpace, 0x80); + E_Notify(PSTR("Btn"), 0x80); + PrintHex (usage, 0x80); + E_Notify(PSTR("\r\n"), 0x80); + //USB_HOST_SERIAL.print(usage, HEX); +} + +void ReportDescParserBase::PrintOrdinalPageUsage(uint16_t usage) { + E_Notify(pstrSpace, 0x80); + E_Notify(PSTR("Inst"), 0x80); + // Sorry, HEX for now... + PrintHex (usage, 0x80); + E_Notify(PSTR("\r\n"), 0x80); + //USB_HOST_SERIAL.print(usage, DEC); +} + +void ReportDescParserBase::PrintGenericDesktopPageUsage(uint16_t usage) { + const char * const * w; + E_Notify(pstrSpace, 0x80); + + output_if_between(usage, 0x00, 0x0a, w, E_Notify, genDesktopTitles0, 0x80) + else output_if_between(usage, 0x2f, 0x49, w, E_Notify, genDesktopTitles1, 0x80) + else output_if_between(usage, 0x7f, 0x94, w, E_Notify, genDesktopTitles2, 0x80) + else output_if_between(usage, 0x9f, 0xa9, w, E_Notify, genDesktopTitles3, 0x80) + else output_if_between(usage, 0xaf, 0xb8, w, E_Notify, genDesktopTitles4, 0x80) + else E_Notify(pstrUsagePageUndefined, 0x80); +} + +void ReportDescParserBase::PrintSimulationControlsPageUsage(uint16_t usage) { + const char * const * w; + E_Notify(pstrSpace, 0x80); + + output_if_between(usage, 0x00, 0x0d, w, E_Notify, simuTitles0, 0x80) + else output_if_between(usage, 0x1f, 0x26, w, E_Notify, simuTitles1, 0x80) + else output_if_between(usage, 0xaf, 0xd1, w, E_Notify, simuTitles2, 0x80) + else E_Notify(pstrUsagePageUndefined, 0x80); +} + +void ReportDescParserBase::PrintVRControlsPageUsage(uint16_t usage) { + const char * const * w; + E_Notify(pstrSpace, 0x80); + + output_if_between(usage, 0x00, 0x0b, w, E_Notify, vrTitles0, 0x80) + else output_if_between(usage, 0x1f, 0x22, w, E_Notify, vrTitles1, 0x80) + else E_Notify(pstrUsagePageUndefined, 0x80); +} + +void ReportDescParserBase::PrintSportsControlsPageUsage(uint16_t usage) { + const char * const * w; + E_Notify(pstrSpace, 0x80); + + output_if_between(usage, 0x00, 0x05, w, E_Notify, sportsCtrlTitles0, 0x80) + else output_if_between(usage, 0x2f, 0x3a, w, E_Notify, sportsCtrlTitles1, 0x80) + else output_if_between(usage, 0x4f, 0x64, w, E_Notify, sportsCtrlTitles2, 0x80) + else E_Notify(pstrUsagePageUndefined, 0x80); +} + +void ReportDescParserBase::PrintGameControlsPageUsage(uint16_t usage) { + const char * const * w; + E_Notify(pstrSpace, 0x80); + + output_if_between(usage, 0x00, 0x04, w, E_Notify, gameTitles0, 0x80) + else output_if_between(usage, 0x1f, 0x3a, w, E_Notify, gameTitles1, 0x80) + else E_Notify(pstrUsagePageUndefined, 0x80); +} + +void ReportDescParserBase::PrintGenericDeviceControlsPageUsage(uint16_t usage) { + const char * const * w; + E_Notify(pstrSpace, 0x80); + + output_if_between(usage, 0x1f, 0x27, w, E_Notify, genDevCtrlTitles, 0x80) + else E_Notify(pstrUsagePageUndefined, 0x80); +} + +void ReportDescParserBase::PrintLEDPageUsage(uint16_t usage) { + const char * const * w; + E_Notify(pstrSpace, 0x80); + + output_if_between(usage, 0x00, 0x4e, w, E_Notify, ledTitles, 0x80) + else E_Notify(pstrUsagePageUndefined, 0x80); +} + +void ReportDescParserBase::PrintTelephonyPageUsage(uint16_t usage) { + const char * const * w; + E_Notify(pstrSpace, 0x80); + + output_if_between(usage, 0x00, 0x08, w, E_Notify, telTitles0, 0x80) + else output_if_between(usage, 0x1f, 0x32, w, E_Notify, telTitles1, 0x80) + else output_if_between(usage, 0x4f, 0x54, w, E_Notify, telTitles2, 0x80) + else output_if_between(usage, 0x6f, 0x75, w, E_Notify, telTitles3, 0x80) + else output_if_between(usage, 0x8f, 0x9f, w, E_Notify, telTitles4, 0x80) + else output_if_between(usage, 0xaf, 0xc0, w, E_Notify, telTitles5, 0x80) + else E_Notify(pstrUsagePageUndefined, 0x80); +} + +void ReportDescParserBase::PrintConsumerPageUsage(uint16_t usage) { + const char * const * w; + E_Notify(pstrSpace, 0x80); + + output_if_between(usage, 0x00, 0x07, w, E_Notify, consTitles0, 0x80) + else output_if_between(usage, 0x1f, 0x23, w, E_Notify, consTitles1, 0x80) + else output_if_between(usage, 0x2f, 0x37, w, E_Notify, consTitles2, 0x80) + else output_if_between(usage, 0x3f, 0x49, w, E_Notify, consTitles3, 0x80) + else output_if_between(usage, 0x5f, 0x67, w, E_Notify, consTitles4, 0x80) + else output_if_between(usage, 0x7f, 0xa5, w, E_Notify, consTitles5, 0x80) + else output_if_between(usage, 0xaf, 0xcf, w, E_Notify, consTitles6, 0x80) + else output_if_between(usage, 0xdf, 0xeb, w, E_Notify, consTitles7, 0x80) + else output_if_between(usage, 0xef, 0xf6, w, E_Notify, consTitles8, 0x80) + else output_if_between(usage, 0xff, 0x10e, w, E_Notify, consTitles9, 0x80) + else output_if_between(usage, 0x14f, 0x156, w, E_Notify, consTitlesA, 0x80) + else output_if_between(usage, 0x15f, 0x16b, w, E_Notify, consTitlesB, 0x80) + else output_if_between(usage, 0x16f, 0x175, w, E_Notify, consTitlesC, 0x80) + else output_if_between(usage, 0x17f, 0x1c8, w, E_Notify, consTitlesD, 0x80) + else output_if_between(usage, 0x1ff, 0x29d, w, E_Notify, consTitlesE, 0x80) + else E_Notify(pstrUsagePageUndefined, 0x80); +} + +void ReportDescParserBase::PrintDigitizerPageUsage(uint16_t usage) { + const char * const * w; + E_Notify(pstrSpace, 0x80); + + output_if_between(usage, 0x00, 0x0e, w, E_Notify, digitTitles0, 0x80) + else output_if_between(usage, 0x1f, 0x23, w, E_Notify, digitTitles1, 0x80) + else output_if_between(usage, 0x2f, 0x47, w, E_Notify, digitTitles2, 0x80) + else E_Notify(pstrUsagePageUndefined, 0x80); +} + +void ReportDescParserBase::PrintAlphanumDisplayPageUsage(uint16_t usage) { + const char * const * w; + E_Notify(pstrSpace, 0x80); + + output_if_between(usage, 0x00, 0x03, w, E_Notify, aplphanumTitles0, 0x80) + else output_if_between(usage, 0x1f, 0x4e, w, E_Notify, aplphanumTitles1, 0x80) + else output_if_between(usage, 0x7f, 0x96, w, E_Notify, digitTitles2, 0x80) + else E_Notify(pstrUsagePageUndefined, 0x80); +} + +void ReportDescParserBase::PrintMedicalInstrumentPageUsage(uint16_t usage) { + const char * const * w; + E_Notify(pstrSpace, 0x80); + + if(usage == 1) E_Notify(pstrUsageMedicalUltrasound, 0x80); + else if(usage == 0x70) + E_Notify(pstrUsageDepthGainCompensation, 0x80); + else output_if_between(usage, 0x1f, 0x28, w, E_Notify, medInstrTitles0, 0x80) + else output_if_between(usage, 0x3f, 0x45, w, E_Notify, medInstrTitles1, 0x80) + else output_if_between(usage, 0x5f, 0x62, w, E_Notify, medInstrTitles2, 0x80) + else output_if_between(usage, 0x7f, 0x8a, w, E_Notify, medInstrTitles3, 0x80) + else output_if_between(usage, 0x9f, 0xa2, w, E_Notify, medInstrTitles4, 0x80) + else E_Notify(pstrUsagePageUndefined, 0x80); +} + +uint8_t ReportDescParser2::ParseItem(uint8_t **pp, uint16_t *pcntdn) { + //uint8_t ret = enErrorSuccess; + + switch(itemParseState) { + case 0: + if(**pp == HID_LONG_ITEM_PREFIX) + USBTRACE("\r\nLONG\r\n"); + else { + uint8_t size = ((**pp) & DATA_SIZE_MASK); + itemPrefix = (**pp); + itemSize = 1 + ((size == DATA_SIZE_4) ? 4 : size); + } + (*pp)++; + (*pcntdn)--; + itemSize--; + itemParseState = 1; + + if(!itemSize) + break; + + if(!pcntdn) + return enErrorIncomplete; + case 1: + theBuffer.valueSize = itemSize; + valParser.Initialize(&theBuffer); + itemParseState = 2; + case 2: + if(!valParser.Parse(pp, pcntdn)) + return enErrorIncomplete; + itemParseState = 3; + case 3: + { + uint8_t data = *((uint8_t*)varBuffer); + + switch(itemPrefix & (TYPE_MASK | TAG_MASK)) { + case (TYPE_LOCAL | TAG_LOCAL_USAGE): + if(pfUsage) { + if(theBuffer.valueSize > 1) { + uint16_t* ui16 = reinterpret_cast(varBuffer); + pfUsage(*ui16); + } else + pfUsage(data); + } + break; + case (TYPE_GLOBAL | TAG_GLOBAL_REPORTSIZE): + rptSize = data; + break; + case (TYPE_GLOBAL | TAG_GLOBAL_REPORTCOUNT): + rptCount = data; + break; + case (TYPE_GLOBAL | TAG_GLOBAL_REPORTID): + rptId = data; + break; + case (TYPE_LOCAL | TAG_LOCAL_USAGEMIN): + useMin = data; + break; + case (TYPE_LOCAL | TAG_LOCAL_USAGEMAX): + useMax = data; + break; + case (TYPE_GLOBAL | TAG_GLOBAL_USAGEPAGE): + SetUsagePage(data); + break; + case (TYPE_MAIN | TAG_MAIN_OUTPUT): + case (TYPE_MAIN | TAG_MAIN_FEATURE): + rptSize = 0; + rptCount = 0; + useMin = 0; + useMax = 0; + break; + case (TYPE_MAIN | TAG_MAIN_INPUT): + OnInputItem(data); + + totalSize += (uint16_t)rptSize * (uint16_t)rptCount; + + rptSize = 0; + rptCount = 0; + useMin = 0; + useMax = 0; + break; + } // switch (**pp & (TYPE_MASK | TAG_MASK)) + } + } // switch (itemParseState) + itemParseState = 0; + return enErrorSuccess; +} + +void ReportDescParser2::OnInputItem(uint8_t itm) { + uint8_t byte_offset = (totalSize >> 3); // calculate offset to the next unhandled byte i = (int)(totalCount / 8); + uint32_t tmp = (byte_offset << 3); + uint8_t bit_offset = totalSize - tmp; // number of bits in the current byte already handled + uint8_t *p = pBuf + byte_offset; // current byte pointer + + if(bit_offset) + *p >>= bit_offset; + + uint8_t usage = useMin; + + bool print_usemin_usemax = ((useMin < useMax) && ((itm & 3) == 2) && pfUsage) ? true : false; + + uint8_t bits_of_byte = 8; + + // for each field in field array defined by rptCount + for(uint8_t field = 0; field < rptCount; field++, usage++) { + + union { + uint8_t bResult[4]; + uint16_t wResult[2]; + uint32_t dwResult; + } result; + + result.dwResult = 0; + uint8_t mask = 0; + + if(print_usemin_usemax) + pfUsage(usage); + + // bits_left - number of bits in the field(array of fields, depending on Report Count) left to process + // bits_of_byte - number of bits in current byte left to process + // bits_to_copy - number of bits to copy to result buffer + + // for each bit in a field + for(uint8_t bits_left = rptSize, bits_to_copy = 0; bits_left; + bits_left -= bits_to_copy) { + bits_to_copy = (bits_left > bits_of_byte) ? bits_of_byte : bits_left; + + result.dwResult <<= bits_to_copy; // Result buffer is shifted by the number of bits to be copied into it + + uint8_t val = *p; + + val >>= (8 - bits_of_byte); // Shift by the number of bits already processed + + mask = 0; + + for(uint8_t j = bits_to_copy; j; j--) { + mask <<= 1; + mask |= 1; + } + + result.bResult[0] = (result.bResult[0] | (val & mask)); + + bits_of_byte -= bits_to_copy; + + if(bits_of_byte < 1) { + bits_of_byte = 8; + p++; + } + } + PrintByteValue(result.dwResult); + } + E_Notify(PSTR("\r\n"), 0x80); +} + +void UniversalReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) { + ReportDescParser2 prs(len, buf); + + uint8_t ret = hid->GetReportDescr(0, &prs); + + if(ret) + ErrorMessage (PSTR("GetReportDescr-2"), ret); +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/hidescriptorparser.h b/lib/usbhost/USB_Host_Shield_2.0/hidescriptorparser.h new file mode 100644 index 0000000000..f3b496ffa5 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/hidescriptorparser.h @@ -0,0 +1,176 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#if !defined(__HIDDESCRIPTORPARSER_H__) +#define __HIDDESCRIPTORPARSER_H__ + +#include "hid.h" + +class ReportDescParserBase : public USBReadParser { +public: + typedef void (*UsagePageFunc)(uint16_t usage); + + static void PrintGenericDesktopPageUsage(uint16_t usage); + static void PrintSimulationControlsPageUsage(uint16_t usage); + static void PrintVRControlsPageUsage(uint16_t usage); + static void PrintSportsControlsPageUsage(uint16_t usage); + static void PrintGameControlsPageUsage(uint16_t usage); + static void PrintGenericDeviceControlsPageUsage(uint16_t usage); + static void PrintLEDPageUsage(uint16_t usage); + static void PrintButtonPageUsage(uint16_t usage); + static void PrintOrdinalPageUsage(uint16_t usage); + static void PrintTelephonyPageUsage(uint16_t usage); + static void PrintConsumerPageUsage(uint16_t usage); + static void PrintDigitizerPageUsage(uint16_t usage); + static void PrintAlphanumDisplayPageUsage(uint16_t usage); + static void PrintMedicalInstrumentPageUsage(uint16_t usage); + + static void PrintValue(uint8_t *p, uint8_t len); + static void PrintByteValue(uint8_t data); + + static void PrintItemTitle(uint8_t prefix); + + static const char * const usagePageTitles0[]; + static const char * const usagePageTitles1[]; + static const char * const genDesktopTitles0[]; + static const char * const genDesktopTitles1[]; + static const char * const genDesktopTitles2[]; + static const char * const genDesktopTitles3[]; + static const char * const genDesktopTitles4[]; + static const char * const simuTitles0[]; + static const char * const simuTitles1[]; + static const char * const simuTitles2[]; + static const char * const vrTitles0[]; + static const char * const vrTitles1[]; + static const char * const sportsCtrlTitles0[]; + static const char * const sportsCtrlTitles1[]; + static const char * const sportsCtrlTitles2[]; + static const char * const gameTitles0[]; + static const char * const gameTitles1[]; + static const char * const genDevCtrlTitles[]; + static const char * const ledTitles[]; + static const char * const telTitles0[]; + static const char * const telTitles1[]; + static const char * const telTitles2[]; + static const char * const telTitles3[]; + static const char * const telTitles4[]; + static const char * const telTitles5[]; + static const char * const consTitles0[]; + static const char * const consTitles1[]; + static const char * const consTitles2[]; + static const char * const consTitles3[]; + static const char * const consTitles4[]; + static const char * const consTitles5[]; + static const char * const consTitles6[]; + static const char * const consTitles7[]; + static const char * const consTitles8[]; + static const char * const consTitles9[]; + static const char * const consTitlesA[]; + static const char * const consTitlesB[]; + static const char * const consTitlesC[]; + static const char * const consTitlesD[]; + static const char * const consTitlesE[]; + static const char * const digitTitles0[]; + static const char * const digitTitles1[]; + static const char * const digitTitles2[]; + static const char * const aplphanumTitles0[]; + static const char * const aplphanumTitles1[]; + static const char * const aplphanumTitles2[]; + static const char * const medInstrTitles0[]; + static const char * const medInstrTitles1[]; + static const char * const medInstrTitles2[]; + static const char * const medInstrTitles3[]; + static const char * const medInstrTitles4[]; + +protected: + static UsagePageFunc usagePageFunctions[]; + + MultiValueBuffer theBuffer; + MultiByteValueParser valParser; + ByteSkipper theSkipper; + uint8_t varBuffer[sizeof (USB_CONFIGURATION_DESCRIPTOR)]; + + uint8_t itemParseState; // Item parser state variable + uint8_t itemSize; // Item size + uint8_t itemPrefix; // Item prefix (first byte) + uint8_t rptSize; // Report Size + uint8_t rptCount; // Report Count + + uint16_t totalSize; // Report size in bits + + // Method should be defined here if virtual. + virtual uint8_t ParseItem(uint8_t **pp, uint16_t *pcntdn); + + UsagePageFunc pfUsage; + + static void PrintUsagePage(uint16_t page); + void SetUsagePage(uint16_t page); + +public: + + ReportDescParserBase() : + itemParseState(0), + itemSize(0), + itemPrefix(0), + rptSize(0), + rptCount(0), + pfUsage(NULL) { + theBuffer.pValue = varBuffer; + valParser.Initialize(&theBuffer); + theSkipper.Initialize(&theBuffer); + }; + + void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset); + + enum { + enErrorSuccess = 0 + , enErrorIncomplete // value or record is partialy read in buffer + , enErrorBufferTooSmall + }; +}; + +class ReportDescParser : public ReportDescParserBase { +}; + +class ReportDescParser2 : public ReportDescParserBase { + uint8_t rptId; // Report ID + uint8_t useMin; // Usage Minimum + uint8_t useMax; // Usage Maximum + uint8_t fieldCount; // Number of field being currently processed + + void OnInputItem(uint8_t itm); // Method which is called every time Input item is found + + uint8_t *pBuf; // Report buffer pointer + uint8_t bLen; // Report length + +protected: + // Method should be defined here if virtual. + virtual uint8_t ParseItem(uint8_t **pp, uint16_t *pcntdn); + +public: + + ReportDescParser2(uint16_t len, uint8_t *pbuf) : + ReportDescParserBase(), rptId(0), useMin(0), useMax(0), fieldCount(0), pBuf(pbuf), bLen(len) { + }; +}; + +class UniversalReportParser : public HIDReportParser { +public: + // Method should be defined here if virtual. + virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); +}; + +#endif // __HIDDESCRIPTORPARSER_H__ diff --git a/lib/usbhost/USB_Host_Shield_2.0/hiduniversal.cpp b/lib/usbhost/USB_Host_Shield_2.0/hiduniversal.cpp new file mode 100644 index 0000000000..395aa69e34 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/hiduniversal.cpp @@ -0,0 +1,425 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ + +#include "hiduniversal.h" + +HIDUniversal::HIDUniversal(USB *p) : +HID(p), +qNextPollTime(0), +pollInterval(0), +bPollEnable(false), +bHasReportId(false) { + Initialize(); + + if(pUsb) + pUsb->RegisterDeviceClass(this); +} + +uint16_t HIDUniversal::GetHidClassDescrLen(uint8_t type, uint8_t num) { + for(uint8_t i = 0, n = 0; i < HID_MAX_HID_CLASS_DESCRIPTORS; i++) { + if(descrInfo[i].bDescrType == type) { + if(n == num) + return descrInfo[i].wDescriptorLength; + n++; + } + } + return 0; +} + +void HIDUniversal::Initialize() { + for(uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) { + rptParsers[i].rptId = 0; + rptParsers[i].rptParser = NULL; + } + for(uint8_t i = 0; i < HID_MAX_HID_CLASS_DESCRIPTORS; i++) { + descrInfo[i].bDescrType = 0; + descrInfo[i].wDescriptorLength = 0; + } + for(uint8_t i = 0; i < maxHidInterfaces; i++) { + hidInterfaces[i].bmInterface = 0; + hidInterfaces[i].bmProtocol = 0; + + for(uint8_t j = 0; j < maxEpPerInterface; j++) + hidInterfaces[i].epIndex[j] = 0; + } + for(uint8_t i = 0; i < totalEndpoints; i++) { + epInfo[i].epAddr = 0; + epInfo[i].maxPktSize = (i) ? 0 : 8; + epInfo[i].epAttribs = 0; + epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; + } + bNumEP = 1; + bNumIface = 0; + bConfNum = 0; + pollInterval = 0; + + ZeroMemory(constBuffLen, prevBuf); +} + +bool HIDUniversal::SetReportParser(uint8_t id, HIDReportParser *prs) { + for(uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) { + if(rptParsers[i].rptId == 0 && rptParsers[i].rptParser == NULL) { + rptParsers[i].rptId = id; + rptParsers[i].rptParser = prs; + return true; + } + } + return false; +} + +HIDReportParser* HIDUniversal::GetReportParser(uint8_t id) { + if(!bHasReportId) + return ((rptParsers[0].rptParser) ? rptParsers[0].rptParser : NULL); + + for(uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) { + if(rptParsers[i].rptId == id) + return rptParsers[i].rptParser; + } + return NULL; +} + +uint8_t HIDUniversal::Init(uint8_t parent, uint8_t port, bool lowspeed) { + const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR); + + uint8_t buf[constBufSize]; + USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + uint8_t len = 0; + + uint8_t num_of_conf; // number of configurations + //uint8_t num_of_intf; // number of interfaces + + AddressPool &addrPool = pUsb->GetAddressPool(); + + USBTRACE("HU Init\r\n"); + + if(bAddress) + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; + + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); + + if(!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + if(!p->epinfo) { + USBTRACE("epinfo\r\n"); + return USB_ERROR_EPINFO_IS_NULL; + } + + // Save old pointer to EP_RECORD of address 0 + oldep_ptr = p->epinfo; + + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence + p->epinfo = epInfo; + + p->lowspeed = lowspeed; + + // Get device descriptor + rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*)buf); + + if(!rcode) + len = (buf[0] > constBufSize) ? constBufSize : buf[0]; + + if(rcode) { + // Restore p->epinfo + p->epinfo = oldep_ptr; + + goto FailGetDevDescr; + } + + // Restore p->epinfo + p->epinfo = oldep_ptr; + + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, false, port); + + if(!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + // Extract Max Packet Size from the device descriptor + epInfo[0].maxPktSize = udd->bMaxPacketSize0; + + // Assign new address to the device + rcode = pUsb->setAddr(0, 0, bAddress); + + if(rcode) { + p->lowspeed = false; + addrPool.FreeAddress(bAddress); + bAddress = 0; + USBTRACE2("setAddr:", rcode); + return rcode; + } + + //delay(2); //per USB 2.0 sect.9.2.6.3 + + USBTRACE2("Addr:", bAddress); + + p->lowspeed = false; + + p = addrPool.GetUsbDevicePtr(bAddress); + + if(!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->lowspeed = lowspeed; + + if(len) + rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf); + + if(rcode) + goto FailGetDevDescr; + + VID = udd->idVendor; // Can be used by classes that inherits this class to check the VID and PID of the connected device + PID = udd->idProduct; + + num_of_conf = udd->bNumConfigurations; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); + + if(rcode) + goto FailSetDevTblEntry; + + USBTRACE2("NC:", num_of_conf); + + for(uint8_t i = 0; i < num_of_conf; i++) { + //HexDumper HexDump; + ConfigDescParser confDescrParser(this); + + //rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump); + rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); + + if(rcode) + goto FailGetConfDescr; + + if(bNumEP > 1) + break; + } // for + + if(bNumEP < 2) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); + + USBTRACE2("Cnf:", bConfNum); + + // Set Configuration Value + rcode = pUsb->setConf(bAddress, 0, bConfNum); + + if(rcode) + goto FailSetConfDescr; + + for(uint8_t i = 0; i < bNumIface; i++) { + if(hidInterfaces[i].epIndex[epInterruptInIndex] == 0) + continue; + + rcode = SetIdle(hidInterfaces[i].bmInterface, 0, 0); + + if(rcode && rcode != hrSTALL) + goto FailSetIdle; + } + + USBTRACE("HU configured\r\n"); + + OnInitSuccessful(); + + bPollEnable = true; + return 0; + +FailGetDevDescr: +#ifdef DEBUG_USB_HOST + NotifyFailGetDevDescr(); + goto Fail; +#endif + +FailSetDevTblEntry: +#ifdef DEBUG_USB_HOST + NotifyFailSetDevTblEntry(); + goto Fail; +#endif + +FailGetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailGetConfDescr(); + goto Fail; +#endif + +FailSetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailSetConfDescr(); + goto Fail; +#endif + + +FailSetIdle: +#ifdef DEBUG_USB_HOST + USBTRACE("SetIdle:"); +#endif + +#ifdef DEBUG_USB_HOST +Fail: + NotifyFail(rcode); +#endif + Release(); + return rcode; +} + +HIDUniversal::HIDInterface* HIDUniversal::FindInterface(uint8_t iface, uint8_t alt, uint8_t proto) { + for(uint8_t i = 0; i < bNumIface && i < maxHidInterfaces; i++) + if(hidInterfaces[i].bmInterface == iface && hidInterfaces[i].bmAltSet == alt + && hidInterfaces[i].bmProtocol == proto) + return hidInterfaces + i; + return NULL; +} + +void HIDUniversal::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) { + // If the first configuration satisfies, the others are not concidered. + if(bNumEP > 1 && conf != bConfNum) + return; + + //ErrorMessage(PSTR("\r\nConf.Val"), conf); + //ErrorMessage(PSTR("Iface Num"), iface); + //ErrorMessage(PSTR("Alt.Set"), alt); + + bConfNum = conf; + + uint8_t index = 0; + HIDInterface *piface = FindInterface(iface, alt, proto); + + // Fill in interface structure in case of new interface + if(!piface) { + piface = hidInterfaces + bNumIface; + piface->bmInterface = iface; + piface->bmAltSet = alt; + piface->bmProtocol = proto; + bNumIface++; + } + + if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) + index = epInterruptInIndex; + else + index = epInterruptOutIndex; + + if(index) { + // Fill in the endpoint info structure + epInfo[bNumEP].epAddr = (pep->bEndpointAddress & 0x0F); + epInfo[bNumEP].maxPktSize = (uint8_t)pep->wMaxPacketSize; + epInfo[bNumEP].epAttribs = 0; + epInfo[bNumEP].bmNakPower = USB_NAK_NOWAIT; + + // Fill in the endpoint index list + piface->epIndex[index] = bNumEP; //(pep->bEndpointAddress & 0x0F); + + if(pollInterval < pep->bInterval) // Set the polling interval as the largest polling interval obtained from endpoints + pollInterval = pep->bInterval; + + bNumEP++; + } + //PrintEndpointDescriptor(pep); +} + +uint8_t HIDUniversal::Release() { + pUsb->GetAddressPool().FreeAddress(bAddress); + + bNumEP = 1; + bAddress = 0; + qNextPollTime = 0; + bPollEnable = false; + return 0; +} + +bool HIDUniversal::BuffersIdentical(uint8_t len, uint8_t *buf1, uint8_t *buf2) { + for(uint8_t i = 0; i < len; i++) + if(buf1[i] != buf2[i]) + return false; + return true; +} + +void HIDUniversal::ZeroMemory(uint8_t len, uint8_t *buf) { + for(uint8_t i = 0; i < len; i++) + buf[i] = 0; +} + +void HIDUniversal::SaveBuffer(uint8_t len, uint8_t *src, uint8_t *dest) { + for(uint8_t i = 0; i < len; i++) + dest[i] = src[i]; +} + +uint8_t HIDUniversal::Poll() { + uint8_t rcode = 0; + + if(!bPollEnable) + return 0; + + if((long)(millis() - qNextPollTime) >= 0L) { + qNextPollTime = millis() + pollInterval; + + uint8_t buf[constBuffLen]; + + for(uint8_t i = 0; i < bNumIface; i++) { + uint8_t index = hidInterfaces[i].epIndex[epInterruptInIndex]; + uint16_t read = (uint16_t)epInfo[index].maxPktSize; + + ZeroMemory(constBuffLen, buf); + + uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[index].epAddr, &read, buf); + + if(rcode) { + if(rcode != hrNAK) + USBTRACE3("(hiduniversal.h) Poll:", rcode, 0x81); + return rcode; + } + + if(read > constBuffLen) + read = constBuffLen; + + bool identical = BuffersIdentical(read, buf, prevBuf); + + SaveBuffer(read, buf, prevBuf); + + if(identical) + return 0; +#if 0 + Notify(PSTR("\r\nBuf: "), 0x80); + + for(uint8_t i = 0; i < read; i++) { + D_PrintHex (buf[i], 0x80); + Notify(PSTR(" "), 0x80); + } + + Notify(PSTR("\r\n"), 0x80); +#endif + ParseHIDData(this, bHasReportId, (uint8_t)read, buf); + + HIDReportParser *prs = GetReportParser(((bHasReportId) ? *buf : 0)); + + if(prs) + prs->Parse(this, bHasReportId, (uint8_t)read, buf); + } + } + return rcode; +} + +// Send a report to interrupt out endpoint. This is NOT SetReport() request! +uint8_t HIDUniversal::SndRpt(uint16_t nbytes, uint8_t *dataptr) { + return pUsb->outTransfer(bAddress, epInfo[epInterruptOutIndex].epAddr, nbytes, dataptr); +} \ No newline at end of file diff --git a/lib/usbhost/USB_Host_Shield_2.0/hiduniversal.h b/lib/usbhost/USB_Host_Shield_2.0/hiduniversal.h new file mode 100644 index 0000000000..d7af384068 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/hiduniversal.h @@ -0,0 +1,108 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ + +#if !defined(__HIDUNIVERSAL_H__) +#define __HIDUNIVERSAL_H__ + +#include "hid.h" +//#include "hidescriptorparser.h" + +class HIDUniversal : public HID { + + struct ReportParser { + uint8_t rptId; + HIDReportParser *rptParser; + } rptParsers[MAX_REPORT_PARSERS]; + + // HID class specific descriptor type and length info obtained from HID descriptor + HID_CLASS_DESCRIPTOR_LEN_AND_TYPE descrInfo[HID_MAX_HID_CLASS_DESCRIPTORS]; + + // Returns HID class specific descriptor length by its type and order number + uint16_t GetHidClassDescrLen(uint8_t type, uint8_t num); + + struct HIDInterface { + struct { + uint8_t bmInterface : 3; + uint8_t bmAltSet : 3; + uint8_t bmProtocol : 2; + }; + uint8_t epIndex[maxEpPerInterface]; + }; + + uint8_t bConfNum; // configuration number + uint8_t bNumIface; // number of interfaces in the configuration + uint8_t bNumEP; // total number of EP in the configuration + uint32_t qNextPollTime; // next poll time + uint8_t pollInterval; + bool bPollEnable; // poll enable flag + + static const uint16_t constBuffLen = 64; // event buffer length + uint8_t prevBuf[constBuffLen]; // previous event buffer + + void Initialize(); + HIDInterface* FindInterface(uint8_t iface, uint8_t alt, uint8_t proto); + + void ZeroMemory(uint8_t len, uint8_t *buf); + bool BuffersIdentical(uint8_t len, uint8_t *buf1, uint8_t *buf2); + void SaveBuffer(uint8_t len, uint8_t *src, uint8_t *dest); + +protected: + EpInfo epInfo[totalEndpoints]; + HIDInterface hidInterfaces[maxHidInterfaces]; + + bool bHasReportId; + + uint16_t PID, VID; // PID and VID of connected device + + // HID implementation + HIDReportParser* GetReportParser(uint8_t id); + + virtual uint8_t OnInitSuccessful() { + return 0; + }; + + virtual void ParseHIDData(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) { + return; + }; + +public: + HIDUniversal(USB *p); + + // HID implementation + bool SetReportParser(uint8_t id, HIDReportParser *prs); + + // USBDeviceConfig implementation + uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + uint8_t Release(); + uint8_t Poll(); + + virtual uint8_t GetAddress() { + return bAddress; + }; + + virtual bool isReady() { + return bPollEnable; + }; + + // UsbConfigXtracter implementation + void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); + + // Send report - do not mix with SetReport()! + uint8_t SndRpt(uint16_t nbytes, uint8_t *dataptr); +}; + +#endif // __HIDUNIVERSAL_H__ diff --git a/lib/usbhost/USB_Host_Shield_2.0/hidusagestr.h b/lib/usbhost/USB_Host_Shield_2.0/hidusagestr.h new file mode 100644 index 0000000000..5ef48f925b --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/hidusagestr.h @@ -0,0 +1,977 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#if !defined( __HIDUSAGESTR_H__) +#define __HIDUSAGESTR_H__ + +#include "Usb.h" + +const char pstrSpace [] PROGMEM = " "; +const char pstrCRLF [] PROGMEM = "\r\n"; +const char pstrSingleTab [] PROGMEM = "\t"; +const char pstrDoubleTab [] PROGMEM = "\t\t"; +const char pstrTripleTab [] PROGMEM = "\t\t\t"; + +// Usage Page String Titles +const char pstrUsagePageUndefined [] PROGMEM = "Undef"; +const char pstrUsagePageGenericDesktopControls [] PROGMEM = "Gen Desktop Ctrls"; +const char pstrUsagePageSimulationControls [] PROGMEM = "Simu Ctrls"; +const char pstrUsagePageVRControls [] PROGMEM = "VR Ctrls"; +const char pstrUsagePageSportControls [] PROGMEM = "Sport Ctrls"; +const char pstrUsagePageGameControls [] PROGMEM = "Game Ctrls"; +const char pstrUsagePageGenericDeviceControls [] PROGMEM = "Gen Dev Ctrls"; +const char pstrUsagePageKeyboardKeypad [] PROGMEM = "Kbrd/Keypad"; +const char pstrUsagePageLEDs [] PROGMEM = "LEDs"; +const char pstrUsagePageButton [] PROGMEM = "Button"; +const char pstrUsagePageOrdinal [] PROGMEM = "Ordinal"; +const char pstrUsagePageTelephone [] PROGMEM = "Tel"; +const char pstrUsagePageConsumer [] PROGMEM = "Consumer"; +const char pstrUsagePageDigitizer [] PROGMEM = "Digitizer"; +const char pstrUsagePagePID [] PROGMEM = "PID"; +const char pstrUsagePageUnicode [] PROGMEM = "Unicode"; +const char pstrUsagePageAlphaNumericDisplay [] PROGMEM = "Alpha Num Disp"; +const char pstrUsagePageMedicalInstruments [] PROGMEM = "Medical Instr"; +const char pstrUsagePageMonitor [] PROGMEM = "Monitor"; +const char pstrUsagePagePower [] PROGMEM = "Power"; +const char pstrUsagePageBarCodeScanner [] PROGMEM = "Bar Code Scan"; +const char pstrUsagePageScale [] PROGMEM = "Scale"; +const char pstrUsagePageMSRDevices [] PROGMEM = "Magn Stripe Read Dev"; +const char pstrUsagePagePointOfSale [] PROGMEM = "POS"; +const char pstrUsagePageCameraControl [] PROGMEM = "Cam Ctrl"; +const char pstrUsagePageArcade [] PROGMEM = "Arcade"; +const char pstrUsagePageReserved [] PROGMEM = "Reserved"; +const char pstrUsagePageVendorDefined [] PROGMEM = "Vendor Def"; + +// Generic Desktop Controls Page +const char pstrUsagePointer [] PROGMEM = "Pointer"; +const char pstrUsageMouse [] PROGMEM = "Mouse"; +const char pstrUsageJoystick [] PROGMEM = "Joystick"; +const char pstrUsageGamePad [] PROGMEM = "Game Pad"; +const char pstrUsageKeyboard [] PROGMEM = "Kbrd"; +const char pstrUsageKeypad [] PROGMEM = "Keypad"; +const char pstrUsageMultiAxisController [] PROGMEM = "Multi-axis Ctrl"; +const char pstrUsageTabletPCSystemControls [] PROGMEM = "Tablet PC Sys Ctrls"; +const char pstrUsageX [] PROGMEM = "X"; +const char pstrUsageY [] PROGMEM = "Y"; +const char pstrUsageZ [] PROGMEM = "Z"; +const char pstrUsageRx [] PROGMEM = "Rx"; +const char pstrUsageRy [] PROGMEM = "Ry"; +const char pstrUsageRz [] PROGMEM = "Rz"; +const char pstrUsageSlider [] PROGMEM = "Slider"; +const char pstrUsageDial [] PROGMEM = "Dial"; +const char pstrUsageWheel [] PROGMEM = "Wheel"; +const char pstrUsageHatSwitch [] PROGMEM = "Hat Switch"; +const char pstrUsageCountedBuffer [] PROGMEM = "Counted Buf"; +const char pstrUsageByteCount [] PROGMEM = "Byte Count"; +const char pstrUsageMotionWakeup [] PROGMEM = "Motion Wakeup"; +const char pstrUsageStart [] PROGMEM = "Start"; +const char pstrUsageSelect [] PROGMEM = "Sel"; +const char pstrUsageVx [] PROGMEM = "Vx"; +const char pstrUsageVy [] PROGMEM = "Vy"; +const char pstrUsageVz [] PROGMEM = "Vz"; +const char pstrUsageVbrx [] PROGMEM = "Vbrx"; +const char pstrUsageVbry [] PROGMEM = "Vbry"; +const char pstrUsageVbrz [] PROGMEM = "Vbrz"; +const char pstrUsageVno [] PROGMEM = "Vno"; +const char pstrUsageFeatureNotification [] PROGMEM = "Feature Notif"; +const char pstrUsageResolutionMultiplier [] PROGMEM = "Res Mult"; +const char pstrUsageSystemControl [] PROGMEM = "Sys Ctrl"; +const char pstrUsageSystemPowerDown [] PROGMEM = "Sys Pwr Down"; +const char pstrUsageSystemSleep [] PROGMEM = "Sys Sleep"; +const char pstrUsageSystemWakeup [] PROGMEM = "Sys Wakeup"; +const char pstrUsageSystemContextMenu [] PROGMEM = "Sys Context Menu"; +const char pstrUsageSystemMainMenu [] PROGMEM = "Sys Main Menu"; +const char pstrUsageSystemAppMenu [] PROGMEM = "Sys App Menu"; +const char pstrUsageSystemMenuHelp [] PROGMEM = "Sys Menu Help"; +const char pstrUsageSystemMenuExit [] PROGMEM = "Sys Menu Exit"; +const char pstrUsageSystemMenuSelect [] PROGMEM = "Sys Menu Select"; +const char pstrUsageSystemMenuRight [] PROGMEM = "Sys Menu Right"; +const char pstrUsageSystemMenuLeft [] PROGMEM = "Sys Menu Left"; +const char pstrUsageSystemMenuUp [] PROGMEM = "Sys Menu Up"; +const char pstrUsageSystemMenuDown [] PROGMEM = "Sys Menu Down"; +const char pstrUsageSystemColdRestart [] PROGMEM = "Sys Cold Restart"; +const char pstrUsageSystemWarmRestart [] PROGMEM = "Sys Warm Restart"; +const char pstrUsageDPadUp [] PROGMEM = "D-pad Up"; +const char pstrUsageDPadDown [] PROGMEM = "D-pad Down"; +const char pstrUsageDPadRight [] PROGMEM = "D-pad Right"; +const char pstrUsageDPadLeft [] PROGMEM = "D-pad Left"; +const char pstrUsageSystemDock [] PROGMEM = "Sys Dock"; +const char pstrUsageSystemUndock [] PROGMEM = "Sys Undock"; +const char pstrUsageSystemSetup [] PROGMEM = "Sys Setup"; +const char pstrUsageSystemBreak [] PROGMEM = "Sys Break"; +const char pstrUsageSystemDebuggerBreak [] PROGMEM = "Sys Dbg Brk"; +const char pstrUsageApplicationBreak [] PROGMEM = "App Break"; +const char pstrUsageApplicationDebuggerBreak [] PROGMEM = "App Dbg Brk"; +const char pstrUsageSystemSpeakerMute [] PROGMEM = "Sys Spk Mute"; +const char pstrUsageSystemHibernate [] PROGMEM = "Sys Hiber"; +const char pstrUsageSystemDisplayInvert [] PROGMEM = "Sys Disp Inv"; +const char pstrUsageSystemDisplayInternal [] PROGMEM = "Sys Disp Int"; +const char pstrUsageSystemDisplayExternal [] PROGMEM = "Sys Disp Ext"; +const char pstrUsageSystemDisplayBoth [] PROGMEM = "Sys Disp Both"; +const char pstrUsageSystemDisplayDual [] PROGMEM = "Sys Disp Dual"; +const char pstrUsageSystemDisplayToggleIntExt [] PROGMEM = "Sys Disp Tgl Int/Ext"; +const char pstrUsageSystemDisplaySwapPriSec [] PROGMEM = "Sys Disp Swap Pri/Sec"; +const char pstrUsageSystemDisplayLCDAutoscale [] PROGMEM = "Sys Disp LCD Autoscale"; + +// Simulation Controls Page +const char pstrUsageFlightSimulationDevice [] PROGMEM = "Flight Simu Dev"; +const char pstrUsageAutomobileSimulationDevice [] PROGMEM = "Auto Simu Dev"; +const char pstrUsageTankSimulationDevice [] PROGMEM = "Tank Simu Dev"; +const char pstrUsageSpaceshipSimulationDevice [] PROGMEM = "Space Simu Dev"; +const char pstrUsageSubmarineSimulationDevice [] PROGMEM = "Subm Simu Dev"; +const char pstrUsageSailingSimulationDevice [] PROGMEM = "Sail Simu Dev"; +const char pstrUsageMotocicleSimulationDevice [] PROGMEM = "Moto Simu Dev"; +const char pstrUsageSportsSimulationDevice [] PROGMEM = "Sport Simu Dev"; +const char pstrUsageAirplaneSimulationDevice [] PROGMEM = "Airp Simu Dev"; +const char pstrUsageHelicopterSimulationDevice [] PROGMEM = "Heli Simu Dev"; +const char pstrUsageMagicCarpetSimulationDevice [] PROGMEM = "Magic Carpet Simu Dev"; +const char pstrUsageBicycleSimulationDevice [] PROGMEM = "Bike Simu Dev"; +const char pstrUsageFlightControlStick [] PROGMEM = "Flight Ctrl Stick"; +const char pstrUsageFlightStick [] PROGMEM = "Flight Stick"; +const char pstrUsageCyclicControl [] PROGMEM = "Cyclic Ctrl"; +const char pstrUsageCyclicTrim [] PROGMEM = "Cyclic Trim"; +const char pstrUsageFlightYoke [] PROGMEM = "Flight Yoke"; +const char pstrUsageTrackControl [] PROGMEM = "Track Ctrl"; +const char pstrUsageAileron [] PROGMEM = "Aileron"; +const char pstrUsageAileronTrim [] PROGMEM = "Aileron Trim"; +const char pstrUsageAntiTorqueControl [] PROGMEM = "Anti-Torque Ctrl"; +const char pstrUsageAutopilotEnable [] PROGMEM = "Autopilot Enable"; +const char pstrUsageChaffRelease [] PROGMEM = "Chaff Release"; +const char pstrUsageCollectiveControl [] PROGMEM = "Collective Ctrl"; +const char pstrUsageDiveBrake [] PROGMEM = "Dive Brake"; +const char pstrUsageElectronicCountermeasures [] PROGMEM = "El Countermeasures"; +const char pstrUsageElevator [] PROGMEM = "Elevator"; +const char pstrUsageElevatorTrim [] PROGMEM = "Elevator Trim"; +const char pstrUsageRudder [] PROGMEM = "Rudder"; +const char pstrUsageThrottle [] PROGMEM = "Throttle"; +const char pstrUsageFlightCommunications [] PROGMEM = "Flight Comm"; +const char pstrUsageFlareRelease [] PROGMEM = "Flare Release"; +const char pstrUsageLandingGear [] PROGMEM = "Landing Gear"; +const char pstrUsageToeBrake [] PROGMEM = "Toe Brake"; +const char pstrUsageTrigger [] PROGMEM = "Trigger"; +const char pstrUsageWeaponsArm [] PROGMEM = "Weapons Arm"; +const char pstrUsageWeaponsSelect [] PROGMEM = "Weapons Sel"; +const char pstrUsageWingFlaps [] PROGMEM = "Wing Flaps"; +const char pstrUsageAccelerator [] PROGMEM = "Accel"; +const char pstrUsageBrake [] PROGMEM = "Brake"; +const char pstrUsageClutch [] PROGMEM = "Clutch"; +const char pstrUsageShifter [] PROGMEM = "Shifter"; +const char pstrUsageSteering [] PROGMEM = "Steering"; +const char pstrUsageTurretDirection [] PROGMEM = "Turret Dir"; +const char pstrUsageBarrelElevation [] PROGMEM = "Barrel Ele"; +const char pstrUsageDivePlane [] PROGMEM = "Dive Plane"; +const char pstrUsageBallast [] PROGMEM = "Ballast"; +const char pstrUsageBicycleCrank [] PROGMEM = "Bicycle Crank"; +const char pstrUsageHandleBars [] PROGMEM = "Handle Bars"; +const char pstrUsageFrontBrake [] PROGMEM = "Front Brake"; +const char pstrUsageRearBrake [] PROGMEM = "Rear Brake"; + +// VR Controls Page +const char pstrUsageBelt [] PROGMEM = "Belt"; +const char pstrUsageBodySuit [] PROGMEM = "Body Suit"; +const char pstrUsageFlexor [] PROGMEM = "Flexor"; +const char pstrUsageGlove [] PROGMEM = "Glove"; +const char pstrUsageHeadTracker [] PROGMEM = "Head Track"; +const char pstrUsageHeadMountedDisplay [] PROGMEM = "Head Disp"; +const char pstrUsageHandTracker [] PROGMEM = "Hand Track"; +const char pstrUsageOculometer [] PROGMEM = "Oculometer"; +const char pstrUsageVest [] PROGMEM = "Vest"; +const char pstrUsageAnimatronicDevice [] PROGMEM = "Animat Dev"; +const char pstrUsageStereoEnable [] PROGMEM = "Stereo Enbl"; +const char pstrUsageDisplayEnable [] PROGMEM = "Display Enbl"; + +// Sport Controls Page +const char pstrUsageBaseballBat [] PROGMEM = "Baseball Bat"; +const char pstrUsageGolfClub [] PROGMEM = "Golf Club"; +const char pstrUsageRowingMachine [] PROGMEM = "Rowing Mach"; +const char pstrUsageTreadmill [] PROGMEM = "Treadmill"; +const char pstrUsageOar [] PROGMEM = "Oar"; +const char pstrUsageSlope [] PROGMEM = "Slope"; +const char pstrUsageRate [] PROGMEM = "Rate"; +const char pstrUsageStickSpeed [] PROGMEM = "Stick Speed"; +const char pstrUsageStickFaceAngle [] PROGMEM = "Stick Face Ang"; +const char pstrUsageStickHeelToe [] PROGMEM = "Stick Heel/Toe"; +const char pstrUsageStickFollowThough [] PROGMEM = "Stick Flw Thru"; +const char pstrUsageStickTempo [] PROGMEM = "Stick Tempo"; +const char pstrUsageStickType [] PROGMEM = "Stick Type"; +const char pstrUsageStickHeight [] PROGMEM = "Stick Hght"; +const char pstrUsagePutter [] PROGMEM = "Putter"; +const char pstrUsage1Iron [] PROGMEM = "1 Iron"; +const char pstrUsage2Iron [] PROGMEM = "2 Iron"; +const char pstrUsage3Iron [] PROGMEM = "3 Iron"; +const char pstrUsage4Iron [] PROGMEM = "4 Iron"; +const char pstrUsage5Iron [] PROGMEM = "5 Iron"; +const char pstrUsage6Iron [] PROGMEM = "6 Iron"; +const char pstrUsage7Iron [] PROGMEM = "7 Iron"; +const char pstrUsage8Iron [] PROGMEM = "8 Iron"; +const char pstrUsage9Iron [] PROGMEM = "9 Iron"; +const char pstrUsage10Iron [] PROGMEM = "10 Iron"; +const char pstrUsage11Iron [] PROGMEM = "11 Iron"; +const char pstrUsageSandWedge [] PROGMEM = "Sand Wedge"; +const char pstrUsageLoftWedge [] PROGMEM = "Loft Wedge"; +const char pstrUsagePowerWedge [] PROGMEM = "Pwr Wedge"; +const char pstrUsage1Wood [] PROGMEM = "1 Wood"; +const char pstrUsage3Wood [] PROGMEM = "3 Wood"; +const char pstrUsage5Wood [] PROGMEM = "5 Wood"; +const char pstrUsage7Wood [] PROGMEM = "7 Wood"; +const char pstrUsage9Wood [] PROGMEM = "9 Wood"; + +// Game Controls Page +const char pstrUsage3DGameController [] PROGMEM = "3D Game Ctrl"; +const char pstrUsagePinballDevice [] PROGMEM = "Pinball Dev"; +const char pstrUsageGunDevice [] PROGMEM = "Gun Dev"; +const char pstrUsagePointOfView [] PROGMEM = "POV"; +const char pstrUsageTurnRightLeft [] PROGMEM = "Turn Right Left"; +const char pstrUsagePitchForwardBackward [] PROGMEM = "Pitch Fwd/Back"; +const char pstrUsageRollRightLeft [] PROGMEM = "Roll Right/Left"; +const char pstrUsageMoveRightLeft [] PROGMEM = "Move Right/Left"; +const char pstrUsageMoveForwardBackward [] PROGMEM = "Move Fwd/Back"; +const char pstrUsageMoveUpDown [] PROGMEM = "Move Up/Down"; +const char pstrUsageLeanRightLeft [] PROGMEM = "Lean Right/Left"; +const char pstrUsageLeanForwardBackward [] PROGMEM = "Lean Fwd/Back"; +const char pstrUsageHeightOfPOV [] PROGMEM = "Height of POV"; +const char pstrUsageFlipper [] PROGMEM = "Flipper"; +const char pstrUsageSecondaryFlipper [] PROGMEM = "Second Flipper"; +const char pstrUsageBump [] PROGMEM = "Bump"; +const char pstrUsageNewGame [] PROGMEM = "New Game"; +const char pstrUsageShootBall [] PROGMEM = "Shoot Ball"; +const char pstrUsagePlayer [] PROGMEM = "Player"; +const char pstrUsageGunBolt [] PROGMEM = "Gun Bolt"; +const char pstrUsageGunClip [] PROGMEM = "Gun Clip"; +const char pstrUsageGunSelector [] PROGMEM = "Gun Sel"; +const char pstrUsageGunSingleShot [] PROGMEM = "Gun Sngl Shot"; +const char pstrUsageGunBurst [] PROGMEM = "Gun Burst"; +const char pstrUsageGunAutomatic [] PROGMEM = "Gun Auto"; +const char pstrUsageGunSafety [] PROGMEM = "Gun Safety"; +const char pstrUsageGamepadFireJump [] PROGMEM = "Gamepad Fire/Jump"; +const char pstrUsageGamepadTrigger [] PROGMEM = "Gamepad Trig"; + +// Generic Device Controls Page +const char pstrUsageBatteryStrength [] PROGMEM = "Bat Strength"; +const char pstrUsageWirelessChannel [] PROGMEM = "Wireless Ch"; +const char pstrUsageWirelessID [] PROGMEM = "Wireless ID"; +const char pstrUsageDiscoverWirelessControl [] PROGMEM = "Discover Wireless Ctrl"; +const char pstrUsageSecurityCodeCharEntered [] PROGMEM = "Sec Code Char Entrd"; +const char pstrUsageSecurityCodeCharErased [] PROGMEM = "Sec Code Char Erased"; +const char pstrUsageSecurityCodeCleared [] PROGMEM = "Sec Code Cleared"; + +// LED Page +const char pstrUsageNumLock [] PROGMEM = "Num Lock"; +const char pstrUsageCapsLock [] PROGMEM = "Caps Lock"; +const char pstrUsageScrollLock [] PROGMEM = "Scroll Lock"; +const char pstrUsageCompose [] PROGMEM = "Compose"; +const char pstrUsageKana [] PROGMEM = "Kana"; +const char pstrUsagePower [] PROGMEM = "Pwr"; +const char pstrUsageShift [] PROGMEM = "Shift"; +const char pstrUsageDoNotDisturb [] PROGMEM = "DND"; +const char pstrUsageMute [] PROGMEM = "Mute"; +const char pstrUsageToneEnable [] PROGMEM = "Tone Enbl"; +const char pstrUsageHighCutFilter [] PROGMEM = "High Cut Fltr"; +const char pstrUsageLowCutFilter [] PROGMEM = "Low Cut Fltr"; +const char pstrUsageEqualizerEnable [] PROGMEM = "Eq Enbl"; +const char pstrUsageSoundFieldOn [] PROGMEM = "Sound Field On"; +const char pstrUsageSurroundOn [] PROGMEM = "Surround On"; +const char pstrUsageRepeat [] PROGMEM = "Repeat"; +const char pstrUsageStereo [] PROGMEM = "Stereo"; +const char pstrUsageSamplingRateDetect [] PROGMEM = "Smpl Rate Detect"; +const char pstrUsageSpinning [] PROGMEM = "Spinning"; +const char pstrUsageCAV [] PROGMEM = "CAV"; +const char pstrUsageCLV [] PROGMEM = "CLV"; +const char pstrUsageRecordingFormatDetect [] PROGMEM = "Rec Format Detect"; +const char pstrUsageOffHook [] PROGMEM = "Off Hook"; +const char pstrUsageRing [] PROGMEM = "Ring"; +const char pstrUsageMessageWaiting [] PROGMEM = "Msg Wait"; +const char pstrUsageDataMode [] PROGMEM = "Data Mode"; +const char pstrUsageBatteryOperation [] PROGMEM = "Bat Op"; +const char pstrUsageBatteryOK [] PROGMEM = "Bat OK"; +const char pstrUsageBatteryLow [] PROGMEM = "Bat Low"; +const char pstrUsageSpeaker [] PROGMEM = "Speaker"; +const char pstrUsageHeadSet [] PROGMEM = "Head Set"; +const char pstrUsageHold [] PROGMEM = "Hold"; +const char pstrUsageMicrophone [] PROGMEM = "Mic"; +const char pstrUsageCoverage [] PROGMEM = "Coverage"; +const char pstrUsageNightMode [] PROGMEM = "Night Mode"; +const char pstrUsageSendCalls [] PROGMEM = "Send Calls"; +const char pstrUsageCallPickup [] PROGMEM = "Call Pickup"; +const char pstrUsageConference [] PROGMEM = "Conf"; +const char pstrUsageStandBy [] PROGMEM = "Stand-by"; +const char pstrUsageCameraOn [] PROGMEM = "Cam On"; +const char pstrUsageCameraOff [] PROGMEM = "Cam Off"; +const char pstrUsageOnLine [] PROGMEM = "On-Line"; +const char pstrUsageOffLine [] PROGMEM = "Off-Line"; +const char pstrUsageBusy [] PROGMEM = "Busy"; +const char pstrUsageReady [] PROGMEM = "Ready"; +const char pstrUsagePaperOut [] PROGMEM = "Paper Out"; +const char pstrUsagePaperJam [] PROGMEM = "Paper Jam"; +const char pstrUsageRemote [] PROGMEM = "Remote"; +const char pstrUsageForward [] PROGMEM = "Fwd"; +const char pstrUsageReverse [] PROGMEM = "Rev"; +const char pstrUsageStop [] PROGMEM = "Stop"; +const char pstrUsageRewind [] PROGMEM = "Rewind"; +const char pstrUsageFastForward [] PROGMEM = "Fast Fwd"; +const char pstrUsagePlay [] PROGMEM = "Play"; +const char pstrUsagePause [] PROGMEM = "Pause"; +const char pstrUsageRecord [] PROGMEM = "Rec"; +const char pstrUsageError [] PROGMEM = "Error"; +const char pstrUsageSelectedIndicator [] PROGMEM = "Usage Sel Ind"; +const char pstrUsageInUseIndicator [] PROGMEM = "Usage In Use Ind"; +const char pstrUsageMultiModeIndicator [] PROGMEM = "Usage Multi Mode Ind"; +const char pstrUsageIndicatorOn [] PROGMEM = "Ind On"; +const char pstrUsageIndicatorFlash [] PROGMEM = "Ind Flash"; +const char pstrUsageIndicatorSlowBlink [] PROGMEM = "Ind Slow Blk"; +const char pstrUsageIndicatorFastBlink [] PROGMEM = "Ind Fast Blk"; +const char pstrUsageIndicatorOff [] PROGMEM = "Ind Off"; +const char pstrUsageFlashOnTime [] PROGMEM = "Flash On Time"; +const char pstrUsageSlowBlinkOnTime [] PROGMEM = "Slow Blk On Time"; +const char pstrUsageSlowBlinkOffTime [] PROGMEM = "Slow Blk Off Time"; +const char pstrUsageFastBlinkOnTime [] PROGMEM = "Fast Blk On Time"; +const char pstrUsageFastBlinkOffTime [] PROGMEM = "Fast Blk Off Time"; +const char pstrUsageIndicatorColor [] PROGMEM = "Usage Ind Color"; +const char pstrUsageIndicatorRed [] PROGMEM = "Ind Red"; +const char pstrUsageIndicatorGreen [] PROGMEM = "Ind Green"; +const char pstrUsageIndicatorAmber [] PROGMEM = "Ind Amber"; +const char pstrUsageGenericIndicator [] PROGMEM = "Gen Ind"; +const char pstrUsageSystemSuspend [] PROGMEM = "Sys Suspend"; +const char pstrUsageExternalPowerConnected [] PROGMEM = "Ext Pwr Conn"; + +// Telephony Usage Page +const char pstrUsagePhone [] PROGMEM = "Phone"; +const char pstrUsageAnsweringMachine [] PROGMEM = "Answ Mach"; +const char pstrUsageMessageControls [] PROGMEM = "Msg Ctrls"; +const char pstrUsageHandset [] PROGMEM = "Handset"; +const char pstrUsageHeadset [] PROGMEM = "Headset"; +const char pstrUsageTelephonyKeyPad [] PROGMEM = "Tel Key Pad"; +const char pstrUsageProgrammableButton [] PROGMEM = "Prog Button"; +const char pstrUsageHookSwitch [] PROGMEM = "Hook Sw"; +const char pstrUsageFlash [] PROGMEM = "Flash"; +const char pstrUsageFeature [] PROGMEM = "Feature"; +//const char pstrUsageHold [] PROGMEM = "Hold"; +const char pstrUsageRedial [] PROGMEM = "Redial"; +const char pstrUsageTransfer [] PROGMEM = "Transfer"; +const char pstrUsageDrop [] PROGMEM = "Drop"; +const char pstrUsagePark [] PROGMEM = "Park"; +const char pstrUsageForwardCalls [] PROGMEM = "Fwd Calls"; +const char pstrUsageAlternateFunction [] PROGMEM = "Alt Func"; +const char pstrUsageLine [] PROGMEM = "Line"; +const char pstrUsageSpeakerPhone [] PROGMEM = "Spk Phone"; +//const char pstrUsageConference [] PROGMEM = "Conference"; +const char pstrUsageRingEnable [] PROGMEM = "Ring Enbl"; +const char pstrUsageRingSelect [] PROGMEM = "Ring Sel"; +const char pstrUsagePhoneMute [] PROGMEM = "Phone Mute"; +const char pstrUsageCallerID [] PROGMEM = "Caller ID"; +const char pstrUsageSend [] PROGMEM = "Send"; +const char pstrUsageSpeedDial [] PROGMEM = "Speed Dial"; +const char pstrUsageStoreNumber [] PROGMEM = "Store Num"; +const char pstrUsageRecallNumber [] PROGMEM = "Recall Num"; +const char pstrUsagePhoneDirectory [] PROGMEM = "Phone Dir"; +const char pstrUsageVoiceMail [] PROGMEM = "Voice Mail"; +const char pstrUsageScreenCalls [] PROGMEM = "Screen Calls"; +//const char pstrUsageDoNotDisturb [] PROGMEM = "Do Not Disturb"; +const char pstrUsageMessage [] PROGMEM = "Msg"; +const char pstrUsageAnswerOnOff [] PROGMEM = "Answer On/Off"; +const char pstrUsageInsideDialTone [] PROGMEM = "Inside Dial Tone"; +const char pstrUsageOutsideDialTone [] PROGMEM = "Outside Dial Tone"; +const char pstrUsageInsideRingTone [] PROGMEM = "Inside Ring Tone"; +const char pstrUsageOutsideRingTone [] PROGMEM = "Outside Ring Tone"; +const char pstrUsagePriorityRingTone [] PROGMEM = "Prior Ring Tone"; +const char pstrUsageInsideRingback [] PROGMEM = "Inside Ringback"; +const char pstrUsagePriorityRingback [] PROGMEM = "Priority Ringback"; +const char pstrUsageLineBusyTone [] PROGMEM = "Ln Busy Tone"; +const char pstrUsageReorderTone [] PROGMEM = "Reorder Tone"; +const char pstrUsageCallWaitingTone [] PROGMEM = "Call Wait Tone"; +const char pstrUsageConfirmationTone1 [] PROGMEM = "Cnfrm Tone1"; +const char pstrUsageConfirmationTone2 [] PROGMEM = "Cnfrm Tone2"; +const char pstrUsageTonesOff [] PROGMEM = "Tones Off"; +const char pstrUsageOutsideRingback [] PROGMEM = "Outside Ringback"; +const char pstrUsageRinger [] PROGMEM = "Ringer"; +const char pstrUsagePhoneKey0 [] PROGMEM = "0"; +const char pstrUsagePhoneKey1 [] PROGMEM = "1"; +const char pstrUsagePhoneKey2 [] PROGMEM = "2"; +const char pstrUsagePhoneKey3 [] PROGMEM = "3"; +const char pstrUsagePhoneKey4 [] PROGMEM = "4"; +const char pstrUsagePhoneKey5 [] PROGMEM = "5"; +const char pstrUsagePhoneKey6 [] PROGMEM = "6"; +const char pstrUsagePhoneKey7 [] PROGMEM = "7"; +const char pstrUsagePhoneKey8 [] PROGMEM = "8"; +const char pstrUsagePhoneKey9 [] PROGMEM = "9"; +const char pstrUsagePhoneKeyStar [] PROGMEM = "*"; +const char pstrUsagePhoneKeyPound [] PROGMEM = "#"; +const char pstrUsagePhoneKeyA [] PROGMEM = "A"; +const char pstrUsagePhoneKeyB [] PROGMEM = "B"; +const char pstrUsagePhoneKeyC [] PROGMEM = "C"; +const char pstrUsagePhoneKeyD [] PROGMEM = "D"; + +// Consumer Usage Page +const char pstrUsageConsumerControl [] PROGMEM = "Consumer Ctrl"; +const char pstrUsageNumericKeyPad [] PROGMEM = "Num Key Pad"; +//const char pstrUsageProgrammableButton [] PROGMEM = "Prog Btn"; +//const char pstrUsageMicrophone [] PROGMEM = "Mic"; +const char pstrUsageHeadphone [] PROGMEM = "Headphone"; +const char pstrUsageGraphicEqualizer [] PROGMEM = "Graph Eq"; +const char pstrUsagePlus10 [] PROGMEM = "+10"; +const char pstrUsagePlus100 [] PROGMEM = "+100"; +const char pstrUsageAMPM [] PROGMEM = "AM/PM"; +//const char pstrUsagePower [] PROGMEM = "Pwr"; +const char pstrUsageReset [] PROGMEM = "Reset"; +const char pstrUsageSleep [] PROGMEM = "Sleep"; +const char pstrUsageSleepAfter [] PROGMEM = "Sleep After"; +const char pstrUsageSleepMode [] PROGMEM = "Sleep Mode"; +const char pstrUsageIllumination [] PROGMEM = "Illumin"; +const char pstrUsageFunctionButtons [] PROGMEM = "Func Btns"; +const char pstrUsageMenu [] PROGMEM = "Menu"; +const char pstrUsageMenuPick [] PROGMEM = "Menu Pick"; +const char pstrUsageMenuUp [] PROGMEM = "Menu Up"; +const char pstrUsageMenuDown [] PROGMEM = "Menu Down"; +const char pstrUsageMenuLeft [] PROGMEM = "Menu Left"; +const char pstrUsageMenuRight [] PROGMEM = "Menu Right"; +const char pstrUsageMenuEscape [] PROGMEM = "Menu Esc"; +const char pstrUsageMenuValueIncrease [] PROGMEM = "Menu Val Inc"; +const char pstrUsageMenuValueDecrease [] PROGMEM = "Menu Val Dec"; +const char pstrUsageDataOnScreen [] PROGMEM = "Data On Scr"; +const char pstrUsageClosedCaption [] PROGMEM = "Closed Cptn"; +const char pstrUsageClosedCaptionSelect [] PROGMEM = "Closed Cptn Sel"; +const char pstrUsageVCRTV [] PROGMEM = "VCR/TV"; +const char pstrUsageBroadcastMode [] PROGMEM = "Brdcast Mode"; +const char pstrUsageSnapshot [] PROGMEM = "Snapshot"; +const char pstrUsageStill [] PROGMEM = "Still"; +const char pstrUsageSelection [] PROGMEM = "Sel"; +const char pstrUsageAssignSelection [] PROGMEM = "Assign Sel"; +const char pstrUsageModeStep [] PROGMEM = "Mode Step"; +const char pstrUsageRecallLast [] PROGMEM = "Recall Last"; +const char pstrUsageEnterChannel [] PROGMEM = "Entr Channel"; +const char pstrUsageOrderMovie [] PROGMEM = "Ord Movie"; +const char pstrUsageChannel [] PROGMEM = "Channel"; +const char pstrUsageMediaSelection [] PROGMEM = "Med Sel"; +const char pstrUsageMediaSelectComputer [] PROGMEM = "Med Sel Comp"; +const char pstrUsageMediaSelectTV [] PROGMEM = "Med Sel TV"; +const char pstrUsageMediaSelectWWW [] PROGMEM = "Med Sel WWW"; +const char pstrUsageMediaSelectDVD [] PROGMEM = "Med Sel DVD"; +const char pstrUsageMediaSelectTelephone [] PROGMEM = "Med Sel Tel"; +const char pstrUsageMediaSelectProgramGuide [] PROGMEM = "Med Sel PG"; +const char pstrUsageMediaSelectVideoPhone [] PROGMEM = "Med Sel Vid"; +const char pstrUsageMediaSelectGames [] PROGMEM = "Med Sel Games"; +const char pstrUsageMediaSelectMessages [] PROGMEM = "Med Sel Msg"; +const char pstrUsageMediaSelectCD [] PROGMEM = "Med Sel CD"; +const char pstrUsageMediaSelectVCR [] PROGMEM = "Med Sel VCR"; +const char pstrUsageMediaSelectTuner [] PROGMEM = "Med Sel Tuner"; +const char pstrUsageQuit [] PROGMEM = "Quit"; +const char pstrUsageHelp [] PROGMEM = "Help"; +const char pstrUsageMediaSelectTape [] PROGMEM = "Med Sel Tape"; +const char pstrUsageMediaSelectCable [] PROGMEM = "Med Sel Cbl"; +const char pstrUsageMediaSelectSatellite [] PROGMEM = "Med Sel Sat"; +const char pstrUsageMediaSelectSecurity [] PROGMEM = "Med Sel Secur"; +const char pstrUsageMediaSelectHome [] PROGMEM = "Med Sel Home"; +const char pstrUsageMediaSelectCall [] PROGMEM = "Med Sel Call"; +const char pstrUsageChannelIncrement [] PROGMEM = "Ch Inc"; +const char pstrUsageChannelDecrement [] PROGMEM = "Ch Dec"; +const char pstrUsageMediaSelectSAP [] PROGMEM = "Med Sel SAP"; +const char pstrUsageVCRPlus [] PROGMEM = "VCR+"; +const char pstrUsageOnce [] PROGMEM = "Once"; +const char pstrUsageDaily [] PROGMEM = "Daily"; +const char pstrUsageWeekly [] PROGMEM = "Weekly"; +const char pstrUsageMonthly [] PROGMEM = "Monthly"; +//const char pstrUsagePlay [] PROGMEM = "Play"; +//const char pstrUsagePause [] PROGMEM = "Pause"; +//const char pstrUsageRecord [] PROGMEM = "Rec"; +//const char pstrUsageFastForward [] PROGMEM = "FF"; +//const char pstrUsageRewind [] PROGMEM = "Rewind"; +const char pstrUsageScanNextTrack [] PROGMEM = "Next Track"; +const char pstrUsageScanPreviousTrack [] PROGMEM = "Prev Track"; +//const char pstrUsageStop [] PROGMEM = "Stop"; +const char pstrUsageEject [] PROGMEM = "Eject"; +const char pstrUsageRandomPlay [] PROGMEM = "Random"; +const char pstrUsageSelectDisk [] PROGMEM = "Sel Disk"; +const char pstrUsageEnterDisk [] PROGMEM = "Ent Disk"; +//const char pstrUsageRepeat [] PROGMEM = "Repeat"; +const char pstrUsageTracking [] PROGMEM = "Tracking"; +const char pstrUsageTrackNormal [] PROGMEM = "Trk Norm"; +const char pstrUsageSlowTracking [] PROGMEM = "Slow Trk"; +const char pstrUsageFrameForward [] PROGMEM = "Frm Fwd"; +const char pstrUsageFrameBackwards [] PROGMEM = "Frm Back"; +const char pstrUsageMark [] PROGMEM = "Mark"; +const char pstrUsageClearMark [] PROGMEM = "Clr Mark"; +const char pstrUsageRepeatFromMark [] PROGMEM = "Rpt Mark"; +const char pstrUsageReturnToMark [] PROGMEM = "Ret to Mark"; +const char pstrUsageSearchMarkForward [] PROGMEM = "Search Mark Fwd"; +const char pstrUsageSearchMarkBackwards [] PROGMEM = "Search Mark Back"; +const char pstrUsageCounterReset [] PROGMEM = "Counter Reset"; +const char pstrUsageShowCounter [] PROGMEM = "Show Counter"; +const char pstrUsageTrackingIncrement [] PROGMEM = "Track Inc"; +const char pstrUsageTrackingDecrement [] PROGMEM = "Track Dec"; +const char pstrUsageStopEject [] PROGMEM = "Stop/Eject"; +const char pstrUsagePlayPause [] PROGMEM = "Play/Pause"; +const char pstrUsagePlaySkip [] PROGMEM = "Play/Skip"; +const char pstrUsageVolume [] PROGMEM = "Vol"; +const char pstrUsageBalance [] PROGMEM = "Balance"; +//const char pstrUsageMute [] PROGMEM = "Mute"; +const char pstrUsageBass [] PROGMEM = "Bass"; +const char pstrUsageTreble [] PROGMEM = "Treble"; +const char pstrUsageBassBoost [] PROGMEM = "Bass Boost"; +const char pstrUsageSurroundMode [] PROGMEM = "Surround"; +const char pstrUsageLoudness [] PROGMEM = "Loud"; +const char pstrUsageMPX [] PROGMEM = "MPX"; +const char pstrUsageVolumeIncrement [] PROGMEM = "Vol Inc"; +const char pstrUsageVolumeDecrement [] PROGMEM = "Vol Dec"; +const char pstrUsageSpeedSelect [] PROGMEM = "Speed"; +const char pstrUsagePlaybackSpeed [] PROGMEM = "Play Speed"; +const char pstrUsageStandardPlay [] PROGMEM = "Std Play"; +const char pstrUsageLongPlay [] PROGMEM = "Long Play"; +const char pstrUsageExtendedPlay [] PROGMEM = "Ext Play"; +const char pstrUsageSlow [] PROGMEM = "Slow"; +const char pstrUsageFanEnable [] PROGMEM = "Fan Enbl"; +const char pstrUsageFanSpeed [] PROGMEM = "Fan Speed"; +const char pstrUsageLightEnable [] PROGMEM = "Light Enbl"; +const char pstrUsageLightIlluminationLevel [] PROGMEM = "Light Illum Lev"; +const char pstrUsageClimateControlEnable [] PROGMEM = "Climate Enbl"; +const char pstrUsageRoomTemperature [] PROGMEM = "Room Temp"; +const char pstrUsageSecurityEnable [] PROGMEM = "Secur Enbl"; +const char pstrUsageFireAlarm [] PROGMEM = "Fire Alm"; +const char pstrUsagePoliceAlarm [] PROGMEM = "Police Alm"; +const char pstrUsageProximity [] PROGMEM = "Prox"; +const char pstrUsageMotion [] PROGMEM = "Motion"; +const char pstrUsageDuresAlarm [] PROGMEM = "Dures Alm"; +const char pstrUsageHoldupAlarm [] PROGMEM = "Holdup Alm"; +const char pstrUsageMedicalAlarm [] PROGMEM = "Med Alm"; +const char pstrUsageBalanceRight [] PROGMEM = "Balance Right"; +const char pstrUsageBalanceLeft [] PROGMEM = "Balance Left"; +const char pstrUsageBassIncrement [] PROGMEM = "Bass Inc"; +const char pstrUsageBassDecrement [] PROGMEM = "Bass Dec"; +const char pstrUsageTrebleIncrement [] PROGMEM = "Treble Inc"; +const char pstrUsageTrebleDecrement [] PROGMEM = "Treble Dec"; +const char pstrUsageSpeakerSystem [] PROGMEM = "Spk Sys"; +const char pstrUsageChannelLeft [] PROGMEM = "Ch Left"; +const char pstrUsageChannelRight [] PROGMEM = "Ch Right"; +const char pstrUsageChannelCenter [] PROGMEM = "Ch Center"; +const char pstrUsageChannelFront [] PROGMEM = "Ch Front"; +const char pstrUsageChannelCenterFront [] PROGMEM = "Ch Cntr Front"; +const char pstrUsageChannelSide [] PROGMEM = "Ch Side"; +const char pstrUsageChannelSurround [] PROGMEM = "Ch Surround"; +const char pstrUsageChannelLowFreqEnhancement [] PROGMEM = "Ch Low Freq Enh"; +const char pstrUsageChannelTop [] PROGMEM = "Ch Top"; +const char pstrUsageChannelUnknown [] PROGMEM = "Ch Unk"; +const char pstrUsageSubChannel [] PROGMEM = "Sub-ch"; +const char pstrUsageSubChannelIncrement [] PROGMEM = "Sub-ch Inc"; +const char pstrUsageSubChannelDecrement [] PROGMEM = "Sub-ch Dec"; +const char pstrUsageAlternateAudioIncrement [] PROGMEM = "Alt Aud Inc"; +const char pstrUsageAlternateAudioDecrement [] PROGMEM = "Alt Aud Dec"; +const char pstrUsageApplicationLaunchButtons [] PROGMEM = "App Launch Btns"; +const char pstrUsageALLaunchButtonConfigTool [] PROGMEM = "AL Launch Conf Tl"; +const char pstrUsageALProgrammableButton [] PROGMEM = "AL Pgm Btn"; +const char pstrUsageALConsumerControlConfig [] PROGMEM = "AL Cons Ctrl Cfg"; +const char pstrUsageALWordProcessor [] PROGMEM = "AL Word Proc"; +const char pstrUsageALTextEditor [] PROGMEM = "AL Txt Edtr"; +const char pstrUsageALSpreadsheet [] PROGMEM = "AL Sprdsheet"; +const char pstrUsageALGraphicsEditor [] PROGMEM = "AL Graph Edtr"; +const char pstrUsageALPresentationApp [] PROGMEM = "AL Present App"; +const char pstrUsageALDatabaseApp [] PROGMEM = "AL DB App"; +const char pstrUsageALEmailReader [] PROGMEM = "AL E-mail Rdr"; +const char pstrUsageALNewsreader [] PROGMEM = "AL Newsrdr"; +const char pstrUsageALVoicemail [] PROGMEM = "AL Voicemail"; +const char pstrUsageALContactsAddressBook [] PROGMEM = "AL Addr Book"; +const char pstrUsageALCalendarSchedule [] PROGMEM = "AL Clndr/Schdlr"; +const char pstrUsageALTaskProjectManager [] PROGMEM = "AL Task/Prj Mgr"; +const char pstrUsageALLogJournalTimecard [] PROGMEM = "AL Log/Jrnl/Tmcrd"; +const char pstrUsageALCheckbookFinance [] PROGMEM = "AL Chckbook/Fin"; +const char pstrUsageALCalculator [] PROGMEM = "AL Calc"; +const char pstrUsageALAVCapturePlayback [] PROGMEM = "AL A/V Capt/Play"; +const char pstrUsageALLocalMachineBrowser [] PROGMEM = "AL Loc Mach Brow"; +const char pstrUsageALLANWANBrow [] PROGMEM = "AL LAN/WAN Brow"; +const char pstrUsageALInternetBrowser [] PROGMEM = "AL I-net Brow"; +const char pstrUsageALRemoteNetISPConnect [] PROGMEM = "AL Rem Net Con"; +const char pstrUsageALNetworkConference [] PROGMEM = "AL Net Conf"; +const char pstrUsageALNetworkChat [] PROGMEM = "AL Net Chat"; +const char pstrUsageALTelephonyDialer [] PROGMEM = "AL Tel/Dial"; +const char pstrUsageALLogon [] PROGMEM = "AL Logon"; +const char pstrUsageALLogoff [] PROGMEM = "AL Logoff"; +const char pstrUsageALLogonLogoff [] PROGMEM = "AL Logon/Logoff"; +const char pstrUsageALTermLockScrSav [] PROGMEM = "AL Term Lock/Scr Sav"; +const char pstrUsageALControlPannel [] PROGMEM = "AL Ctrl Pan"; +const char pstrUsageALCommandLineProcessorRun [] PROGMEM = "AL Cmd/Run"; +const char pstrUsageALProcessTaskManager [] PROGMEM = "AL Task Mgr"; +const char pstrUsageALSelectTaskApplication [] PROGMEM = "AL Sel App"; +const char pstrUsageALNextTaskApplication [] PROGMEM = "AL Next App"; +const char pstrUsageALPreviousTaskApplication [] PROGMEM = "AL Prev App"; +const char pstrUsageALPreemptiveHaltTaskApp [] PROGMEM = "AL Prmpt Halt App"; +const char pstrUsageALIntegratedHelpCenter [] PROGMEM = "AL Hlp Cntr"; +const char pstrUsageALDocuments [] PROGMEM = "AL Docs"; +const char pstrUsageALThesaurus [] PROGMEM = "AL Thsrs"; +const char pstrUsageALDictionary [] PROGMEM = "AL Dict"; +const char pstrUsageALDesktop [] PROGMEM = "AL Desktop"; +const char pstrUsageALSpellCheck [] PROGMEM = "AL Spell Chk"; +const char pstrUsageALGrammarCheck [] PROGMEM = "AL Gram Chk"; +const char pstrUsageALWirelessStatus [] PROGMEM = "AL Wireless Sts"; +const char pstrUsageALKeyboardLayout [] PROGMEM = "AL Kbd Layout"; +const char pstrUsageALVirusProtection [] PROGMEM = "AL Vir Protect"; +const char pstrUsageALEncryption [] PROGMEM = "AL Encrypt"; +const char pstrUsageALScreenSaver [] PROGMEM = "AL Scr Sav"; +const char pstrUsageALAlarms [] PROGMEM = "AL Alarms"; +const char pstrUsageALClock [] PROGMEM = "AL Clock"; +const char pstrUsageALFileBrowser [] PROGMEM = "AL File Brow"; +const char pstrUsageALPowerStatus [] PROGMEM = "AL Pwr Sts"; +const char pstrUsageALImageBrowser [] PROGMEM = "AL Img Brow"; +const char pstrUsageALAudioBrowser [] PROGMEM = "AL Aud Brow"; +const char pstrUsageALMovieBrowser [] PROGMEM = "AL Mov Brow"; +const char pstrUsageALDigitalRightsManager [] PROGMEM = "AL Dig Rights Mgr"; +const char pstrUsageALDigitalWallet [] PROGMEM = "AL Dig Wallet"; +const char pstrUsageALInstantMessaging [] PROGMEM = "AL Inst Msg"; +const char pstrUsageALOEMFeaturesBrowser [] PROGMEM = "AL OEM Tips Brow"; +const char pstrUsageALOEMHelp [] PROGMEM = "AL OEM Hlp"; +const char pstrUsageALOnlineCommunity [] PROGMEM = "AL Online Com"; +const char pstrUsageALEntertainmentContentBrow [] PROGMEM = "AL Ent Cont Brow"; +const char pstrUsageALOnlineShoppingBrowser [] PROGMEM = "AL Online Shop Brow"; +const char pstrUsageALSmartCardInfoHelp [] PROGMEM = "AL SmartCard Inf"; +const char pstrUsageALMarketMonitorFinBrowser [] PROGMEM = "AL Market Brow"; +const char pstrUsageALCustomCorpNewsBrowser [] PROGMEM = "AL Cust Corp News Brow"; +const char pstrUsageALOnlineActivityBrowser [] PROGMEM = "AL Online Act Brow"; +const char pstrUsageALResearchSearchBrowser [] PROGMEM = "AL Search Brow"; +const char pstrUsageALAudioPlayer [] PROGMEM = "AL Aud Player"; +const char pstrUsageGenericGUIAppControls [] PROGMEM = "Gen GUI App Ctrl"; +const char pstrUsageACNew [] PROGMEM = "AC New"; +const char pstrUsageACOpen [] PROGMEM = "AC Open"; +const char pstrUsageACClose [] PROGMEM = "AC Close"; +const char pstrUsageACExit [] PROGMEM = "AC Exit"; +const char pstrUsageACMaximize [] PROGMEM = "AC Max"; +const char pstrUsageACMinimize [] PROGMEM = "AC Min"; +const char pstrUsageACSave [] PROGMEM = "AC Save"; +const char pstrUsageACPrint [] PROGMEM = "AC Print"; +const char pstrUsageACProperties [] PROGMEM = "AC Prop"; +const char pstrUsageACUndo [] PROGMEM = "AC Undo"; +const char pstrUsageACCopy [] PROGMEM = "AC Copy"; +const char pstrUsageACCut [] PROGMEM = "AC Cut"; +const char pstrUsageACPaste [] PROGMEM = "AC Paste"; +const char pstrUsageACSelectAll [] PROGMEM = "AC Sel All"; +const char pstrUsageACFind [] PROGMEM = "AC Find"; +const char pstrUsageACFindAndReplace [] PROGMEM = "AC Find/Replace"; +const char pstrUsageACSearch [] PROGMEM = "AC Search"; +const char pstrUsageACGoto [] PROGMEM = "AC Goto"; +const char pstrUsageACHome [] PROGMEM = "AC Home"; +const char pstrUsageACBack [] PROGMEM = "AC Back"; +const char pstrUsageACForward [] PROGMEM = "AC Fwd"; +const char pstrUsageACStop [] PROGMEM = "AC Stop"; +const char pstrUsageACRefresh [] PROGMEM = "AC Refresh"; +const char pstrUsageACPreviousLink [] PROGMEM = "AC Prev Link"; +const char pstrUsageACNextLink [] PROGMEM = "AC Next Link"; +const char pstrUsageACBookmarks [] PROGMEM = "AC Bkmarks"; +const char pstrUsageACHistory [] PROGMEM = "AC Hist"; +const char pstrUsageACSubscriptions [] PROGMEM = "AC Subscr"; +const char pstrUsageACZoomIn [] PROGMEM = "AC Zoom In"; +const char pstrUsageACZoomOut [] PROGMEM = "AC Zoom Out"; +const char pstrUsageACZoom [] PROGMEM = "AC Zoom"; +const char pstrUsageACFullScreenView [] PROGMEM = "AC Full Scr"; +const char pstrUsageACNormalView [] PROGMEM = "AC Norm View"; +const char pstrUsageACViewToggle [] PROGMEM = "AC View Tgl"; +const char pstrUsageACScrollUp [] PROGMEM = "AC Scroll Up"; +const char pstrUsageACScrollDown [] PROGMEM = "AC Scroll Down"; +const char pstrUsageACScroll [] PROGMEM = "AC Scroll"; +const char pstrUsageACPanLeft [] PROGMEM = "AC Pan Left"; +const char pstrUsageACPanRight [] PROGMEM = "AC Pan Right"; +const char pstrUsageACPan [] PROGMEM = "AC Pan"; +const char pstrUsageACNewWindow [] PROGMEM = "AC New Wnd"; +const char pstrUsageACTileHoriz [] PROGMEM = "AC Tile Horiz"; +const char pstrUsageACTileVert [] PROGMEM = "AC Tile Vert"; +const char pstrUsageACFormat [] PROGMEM = "AC Frmt"; +const char pstrUsageACEdit [] PROGMEM = "AC Edit"; +const char pstrUsageACBold [] PROGMEM = "AC Bold"; +const char pstrUsageACItalics [] PROGMEM = "AC Ital"; +const char pstrUsageACUnderline [] PROGMEM = "AC Under"; +const char pstrUsageACStrikethrough [] PROGMEM = "AC Strike"; +const char pstrUsageACSubscript [] PROGMEM = "AC Sub"; +const char pstrUsageACSuperscript [] PROGMEM = "AC Super"; +const char pstrUsageACAllCaps [] PROGMEM = "AC All Caps"; +const char pstrUsageACRotate [] PROGMEM = "AC Rotate"; +const char pstrUsageACResize [] PROGMEM = "AC Resize"; +const char pstrUsageACFlipHorizontal [] PROGMEM = "AC Flp H"; +const char pstrUsageACFlipVertical [] PROGMEM = "AC Flp V"; +const char pstrUsageACMirrorHorizontal [] PROGMEM = "AC Mir H"; +const char pstrUsageACMirrorVertical [] PROGMEM = "AC Mir V"; +const char pstrUsageACFontSelect [] PROGMEM = "AC Fnt Sel"; +const char pstrUsageACFontColor [] PROGMEM = "AC Fnt Clr"; +const char pstrUsageACFontSize [] PROGMEM = "AC Fnt Size"; +const char pstrUsageACJustifyLeft [] PROGMEM = "AC Just Left"; +const char pstrUsageACJustifyCenterH [] PROGMEM = "AC Just Cent H"; +const char pstrUsageACJustifyRight [] PROGMEM = "AC Just Right"; +const char pstrUsageACJustifyBlockH [] PROGMEM = "AC Just Block H"; +const char pstrUsageACJustifyTop [] PROGMEM = "AC Just Top"; +const char pstrUsageACJustifyCenterV [] PROGMEM = "AC Just Cent V"; +const char pstrUsageACJustifyBottom [] PROGMEM = "AC Just Bot"; +const char pstrUsageACJustifyBlockV [] PROGMEM = "AC Just Block V"; +const char pstrUsageACIndentDecrease [] PROGMEM = "AC Indent Dec"; +const char pstrUsageACIndentIncrease [] PROGMEM = "AC Indent Inc"; +const char pstrUsageACNumberedList [] PROGMEM = "AC Num List"; +const char pstrUsageACRestartNumbering [] PROGMEM = "AC Res Num"; +const char pstrUsageACBulletedList [] PROGMEM = "AC Blt List"; +const char pstrUsageACPromote [] PROGMEM = "AC Promote"; +const char pstrUsageACDemote [] PROGMEM = "AC Demote"; +const char pstrUsageACYes [] PROGMEM = "AC Yes"; +const char pstrUsageACNo [] PROGMEM = "AC No"; +const char pstrUsageACCancel [] PROGMEM = "AC Cancel"; +const char pstrUsageACCatalog [] PROGMEM = "AC Ctlg"; +const char pstrUsageACBuyChkout [] PROGMEM = "AC Buy"; +const char pstrUsageACAddToCart [] PROGMEM = "AC Add2Cart"; +const char pstrUsageACExpand [] PROGMEM = "AC Xpnd"; +const char pstrUsageACExpandAll [] PROGMEM = "AC Xpand All"; +const char pstrUsageACCollapse [] PROGMEM = "AC Collapse"; +const char pstrUsageACCollapseAll [] PROGMEM = "AC Collapse All"; +const char pstrUsageACPrintPreview [] PROGMEM = "AC Prn Prevw"; +const char pstrUsageACPasteSpecial [] PROGMEM = "AC Paste Spec"; +const char pstrUsageACInsertMode [] PROGMEM = "AC Ins Mode"; +const char pstrUsageACDelete [] PROGMEM = "AC Del"; +const char pstrUsageACLock [] PROGMEM = "AC Lock"; +const char pstrUsageACUnlock [] PROGMEM = "AC Unlock"; +const char pstrUsageACProtect [] PROGMEM = "AC Prot"; +const char pstrUsageACUnprotect [] PROGMEM = "AC Unprot"; +const char pstrUsageACAttachComment [] PROGMEM = "AC Attach Cmnt"; +const char pstrUsageACDeleteComment [] PROGMEM = "AC Del Cmnt"; +const char pstrUsageACViewComment [] PROGMEM = "AC View Cmnt"; +const char pstrUsageACSelectWord [] PROGMEM = "AC Sel Word"; +const char pstrUsageACSelectSentence [] PROGMEM = "AC Sel Sntc"; +const char pstrUsageACSelectParagraph [] PROGMEM = "AC Sel Para"; +const char pstrUsageACSelectColumn [] PROGMEM = "AC Sel Col"; +const char pstrUsageACSelectRow [] PROGMEM = "AC Sel Row"; +const char pstrUsageACSelectTable [] PROGMEM = "AC Sel Tbl"; +const char pstrUsageACSelectObject [] PROGMEM = "AC Sel Obj"; +const char pstrUsageACRedoRepeat [] PROGMEM = "AC Redo"; +const char pstrUsageACSort [] PROGMEM = "AC Sort"; +const char pstrUsageACSortAscending [] PROGMEM = "AC Sort Asc"; +const char pstrUsageACSortDescending [] PROGMEM = "AC Sort Desc"; +const char pstrUsageACFilter [] PROGMEM = "AC Filt"; +const char pstrUsageACSetClock [] PROGMEM = "AC Set Clk"; +const char pstrUsageACViewClock [] PROGMEM = "AC View Clk"; +const char pstrUsageACSelectTimeZone [] PROGMEM = "AC Sel Time Z"; +const char pstrUsageACEditTimeZone [] PROGMEM = "AC Edt Time Z"; +const char pstrUsageACSetAlarm [] PROGMEM = "AC Set Alm"; +const char pstrUsageACClearAlarm [] PROGMEM = "AC Clr Alm"; +const char pstrUsageACSnoozeAlarm [] PROGMEM = "AC Snz Alm"; +const char pstrUsageACResetAlarm [] PROGMEM = "AC Rst Alm"; +const char pstrUsageACSyncronize [] PROGMEM = "AC Sync"; +const char pstrUsageACSendReceive [] PROGMEM = "AC Snd/Rcv"; +const char pstrUsageACSendTo [] PROGMEM = "AC Snd To"; +const char pstrUsageACReply [] PROGMEM = "AC Reply"; +const char pstrUsageACReplyAll [] PROGMEM = "AC Reply All"; +const char pstrUsageACForwardMessage [] PROGMEM = "AC Fwd Msg"; +const char pstrUsageACSend [] PROGMEM = "AC Snd"; +const char pstrUsageACAttachFile [] PROGMEM = "AC Att File"; +const char pstrUsageACUpload [] PROGMEM = "AC Upld"; +const char pstrUsageACDownload [] PROGMEM = "AC Dnld"; +const char pstrUsageACSetBorders [] PROGMEM = "AC Set Brd"; +const char pstrUsageACInsertRow [] PROGMEM = "AC Ins Row"; +const char pstrUsageACInsertColumn [] PROGMEM = "AC Ins Col"; +const char pstrUsageACInsertFile [] PROGMEM = "AC Ins File"; +const char pstrUsageACInsertPicture [] PROGMEM = "AC Ins Pic"; +const char pstrUsageACInsertObject [] PROGMEM = "AC Ins Obj"; +const char pstrUsageACInsertSymbol [] PROGMEM = "AC Ins Sym"; +const char pstrUsageACSaveAndClose [] PROGMEM = "AC Sav&Cls"; +const char pstrUsageACRename [] PROGMEM = "AC Rename"; +const char pstrUsageACMerge [] PROGMEM = "AC Merge"; +const char pstrUsageACSplit [] PROGMEM = "AC Split"; +const char pstrUsageACDistributeHorizontaly [] PROGMEM = "AC Dist Hor"; +const char pstrUsageACDistributeVerticaly [] PROGMEM = "AC Dist Ver"; + +// Digitaizers +const char pstrUsageDigitizer [] PROGMEM = "Digitizer"; +const char pstrUsagePen [] PROGMEM = "Pen"; +const char pstrUsageLightPen [] PROGMEM = "Light Pen"; +const char pstrUsageTouchScreen [] PROGMEM = "Touch Scr"; +const char pstrUsageTouchPad [] PROGMEM = "Touch Pad"; +const char pstrUsageWhiteBoard [] PROGMEM = "White Brd"; +const char pstrUsageCoordinateMeasuringMachine [] PROGMEM = "Coord Meas Mach"; +const char pstrUsage3DDigitizer [] PROGMEM = "3D Dgtz"; +const char pstrUsageStereoPlotter [] PROGMEM = "Stereo Plot"; +const char pstrUsageArticulatedArm [] PROGMEM = "Art Arm"; +const char pstrUsageArmature [] PROGMEM = "Armature"; +const char pstrUsageMultiplePointDigitizer [] PROGMEM = "Multi Point Dgtz"; +const char pstrUsageFreeSpaceWand [] PROGMEM = "Free Space Wand"; +const char pstrUsageStylus [] PROGMEM = "Stylus"; +const char pstrUsagePuck [] PROGMEM = "Puck"; +const char pstrUsageFinger [] PROGMEM = "Finger"; +const char pstrUsageTipPressure [] PROGMEM = "Tip Press"; +const char pstrUsageBarrelPressure [] PROGMEM = "Brl Press"; +const char pstrUsageInRange [] PROGMEM = "In Range"; +const char pstrUsageTouch [] PROGMEM = "Touch"; +const char pstrUsageUntouch [] PROGMEM = "Untouch"; +const char pstrUsageTap [] PROGMEM = "Tap"; +const char pstrUsageQuality [] PROGMEM = "Qlty"; +const char pstrUsageDataValid [] PROGMEM = "Data Valid"; +const char pstrUsageTransducerIndex [] PROGMEM = "Transducer Ind"; +const char pstrUsageTabletFunctionKeys [] PROGMEM = "Tabl Func Keys"; +const char pstrUsageProgramChangeKeys [] PROGMEM = "Pgm Chng Keys"; +//const char pstrUsageBatteryStrength [] PROGMEM = "Bat Strength"; +const char pstrUsageInvert [] PROGMEM = "Invert"; +const char pstrUsageXTilt [] PROGMEM = "X Tilt"; +const char pstrUsageYTilt [] PROGMEM = "Y Tilt"; +const char pstrUsageAzimuth [] PROGMEM = "Azimuth"; +const char pstrUsageAltitude [] PROGMEM = "Altitude"; +const char pstrUsageTwist [] PROGMEM = "Twist"; +const char pstrUsageTipSwitch [] PROGMEM = "Tip Sw"; +const char pstrUsageSecondaryTipSwitch [] PROGMEM = "Scnd Tip Sw"; +const char pstrUsageBarrelSwitch [] PROGMEM = "Brl Sw"; +const char pstrUsageEraser [] PROGMEM = "Eraser"; +const char pstrUsageTabletPick [] PROGMEM = "Tbl Pick"; + +// Alphanumeric Display Page +const char pstrUsageAlphanumericDisplay [] PROGMEM = "Alphanum Disp"; +const char pstrUsageBitmappedDisplay [] PROGMEM = "Bmp Disp"; +const char pstrUsageDisplayAttributesReport [] PROGMEM = "Disp Attr Rpt"; +const char pstrUsageASCIICharacterSet [] PROGMEM = "ASCII chset"; +const char pstrUsageDataReadBack [] PROGMEM = "Data Rd Back"; +const char pstrUsageFontReadBack [] PROGMEM = "Fnt Rd Back"; +const char pstrUsageDisplayControlReport [] PROGMEM = "Disp Ctrl Rpt"; +const char pstrUsageClearDisplay [] PROGMEM = "Clr Disp"; +//const char pstrUsageDisplayEnable [] PROGMEM = "Disp Enbl"; +const char pstrUsageScreenSaverDelay [] PROGMEM = "Scr Sav Delay"; +const char pstrUsageScreenSaverEnable [] PROGMEM = "Scr Sav Enbl"; +const char pstrUsageVerticalScroll [] PROGMEM = "V Scroll"; +const char pstrUsageHorizontalScroll [] PROGMEM = "H Scroll"; +const char pstrUsageCharacterReport [] PROGMEM = "Char Rpt"; +const char pstrUsageDisplayData [] PROGMEM = "Disp Data"; +const char pstrUsageDisplayStatus [] PROGMEM = "Disp Stat"; +const char pstrUsageStatusNotReady [] PROGMEM = "Stat !Ready"; +const char pstrUsageStatusReady [] PROGMEM = "Stat Ready"; +const char pstrUsageErrorNotALoadableCharacter [] PROGMEM = "Err Not Ld Char"; +const char pstrUsageErrorFotDataCanNotBeRead [] PROGMEM = "Fnt Data Rd Err"; +const char pstrUsageCursorPositionReport [] PROGMEM = "Cur Pos Rpt"; +const char pstrUsageRow [] PROGMEM = "Row"; +const char pstrUsageColumn [] PROGMEM = "Col"; +const char pstrUsageRows [] PROGMEM = "Rows"; +const char pstrUsageColumns [] PROGMEM = "Cols"; +const char pstrUsageCursorPixelPosition [] PROGMEM = "Cur Pix Pos"; +const char pstrUsageCursorMode [] PROGMEM = "Cur Mode"; +const char pstrUsageCursorEnable [] PROGMEM = "Cur Enbl"; +const char pstrUsageCursorBlink [] PROGMEM = "Cur Blnk"; +const char pstrUsageFontReport [] PROGMEM = "Fnt Rpt"; +const char pstrUsageFontData [] PROGMEM = "Fnt Data"; +const char pstrUsageCharacterWidth [] PROGMEM = "Char Wdth"; +const char pstrUsageCharacterHeight [] PROGMEM = "Char Hght"; +const char pstrUsageCharacterSpacingHorizontal [] PROGMEM = "Char Space H"; +const char pstrUsageCharacterSpacingVertical [] PROGMEM = "Char Space V"; +const char pstrUsageUnicodeCharset [] PROGMEM = "Unicode Char"; +const char pstrUsageFont7Segment [] PROGMEM = "Fnt 7-seg"; +const char pstrUsage7SegmentDirectMap [] PROGMEM = "7-seg map"; +const char pstrUsageFont14Segment [] PROGMEM = "Fnt 14-seg"; +const char pstrUsage14SegmentDirectMap [] PROGMEM = "14-seg map"; +const char pstrUsageDisplayBrightness [] PROGMEM = "Disp Bright"; +const char pstrUsageDisplayContrast [] PROGMEM = "Disp Cntrst"; +const char pstrUsageCharacterAttribute [] PROGMEM = "Char Attr"; +const char pstrUsageAttributeReadback [] PROGMEM = "Attr Readbk"; +const char pstrUsageAttributeData [] PROGMEM = "Attr Data"; +const char pstrUsageCharAttributeEnhance [] PROGMEM = "Char Attr Enh"; +const char pstrUsageCharAttributeUnderline [] PROGMEM = "Char Attr Undl"; +const char pstrUsageCharAttributeBlink [] PROGMEM = "Char Attr Blnk"; +const char pstrUsageBitmapSizeX [] PROGMEM = "Bmp Size X"; +const char pstrUsageBitmapSizeY [] PROGMEM = "Bmp Size Y"; +const char pstrUsageBitDepthFormat [] PROGMEM = "Bit Dpth Fmt"; +const char pstrUsageDisplayOrientation [] PROGMEM = "Disp Ornt"; +const char pstrUsagePaletteReport [] PROGMEM = "Pal Rpt"; +const char pstrUsagePaletteDataSize [] PROGMEM = "Pal Data Size"; +const char pstrUsagePaletteDataOffset [] PROGMEM = "Pal Data Off"; +const char pstrUsagePaletteData [] PROGMEM = "Pal Data"; +const char pstrUsageBlitReport [] PROGMEM = "Blit Rpt"; +const char pstrUsageBlitRectangleX1 [] PROGMEM = "Blit Rect X1"; +const char pstrUsageBlitRectangleY1 [] PROGMEM = "Blit Rect Y1"; +const char pstrUsageBlitRectangleX2 [] PROGMEM = "Blit Rect X2"; +const char pstrUsageBlitRectangleY2 [] PROGMEM = "Blit Rect Y2"; +const char pstrUsageBlitData [] PROGMEM = "Blit Data"; +const char pstrUsageSoftButton [] PROGMEM = "Soft Btn"; +const char pstrUsageSoftButtonID [] PROGMEM = "Soft Btn ID"; +const char pstrUsageSoftButtonSide [] PROGMEM = "Soft Btn Side"; +const char pstrUsageSoftButtonOffset1 [] PROGMEM = "Soft Btn Off1"; +const char pstrUsageSoftButtonOffset2 [] PROGMEM = "Soft Btn Off2"; +const char pstrUsageSoftButtonReport [] PROGMEM = "Soft Btn Rpt"; + +// Medical Instrument Page +const char pstrUsageMedicalUltrasound [] PROGMEM = "Med Ultrasnd"; +const char pstrUsageVCRAcquisition [] PROGMEM = "VCR/Acq"; +const char pstrUsageFreezeThaw [] PROGMEM = "Freeze"; +const char pstrUsageClipStore [] PROGMEM = "Clip Store"; +const char pstrUsageUpdate [] PROGMEM = "Update"; +const char pstrUsageNext [] PROGMEM = "Next"; +const char pstrUsageSave [] PROGMEM = "Save"; +const char pstrUsagePrint [] PROGMEM = "Print"; +const char pstrUsageMicrophoneEnable [] PROGMEM = "Mic Enbl"; +const char pstrUsageCine [] PROGMEM = "Cine"; +const char pstrUsageTransmitPower [] PROGMEM = "Trans Pwr"; +//const char pstrUsageVolume [] PROGMEM = "Vol"; +const char pstrUsageFocus [] PROGMEM = "Focus"; +const char pstrUsageDepth [] PROGMEM = "Depth"; +const char pstrUsageSoftStepPrimary [] PROGMEM = "Soft Stp-Pri"; +const char pstrUsageSoftStepSecondary [] PROGMEM = "Soft Stp-Sec"; +const char pstrUsageDepthGainCompensation [] PROGMEM = "Dpth Gain Comp"; +const char pstrUsageZoomSelect [] PROGMEM = "Zoom Sel"; +const char pstrUsageZoomAdjust [] PROGMEM = "Zoom Adj"; +const char pstrUsageSpectralDopplerModeSelect [] PROGMEM = "Spec Dop Mode Sel"; +const char pstrUsageSpectralDopplerModeAdjust [] PROGMEM = "Spec Dop Mode Adj"; +const char pstrUsageColorDopplerModeSelect [] PROGMEM = "Color Dop Mode Sel"; +const char pstrUsageColorDopplerModeAdjust [] PROGMEM = "Color Dop Mode Adj"; +const char pstrUsageMotionModeSelect [] PROGMEM = "Motion Mode Sel"; +const char pstrUsageMotionModeAdjust [] PROGMEM = "Motion Mode Adj"; +const char pstrUsage2DModeSelect [] PROGMEM = "2D Mode Sel"; +const char pstrUsage2DModeAdjust [] PROGMEM = "2D Mode Adj"; +const char pstrUsageSoftControlSelect [] PROGMEM = "Soft Ctrl Sel"; +const char pstrUsageSoftControlAdjust [] PROGMEM = "Soft Ctrl Adj"; + +//extern const char *usagePageTitles0[15]; +//const char *usagePageTitles1[]; +//const char *genDesktopTitles0[]; +//const char *genDesktopTitles1[]; +//const char *genDesktopTitles2[]; +//const char *genDesktopTitles3[]; +//const char *genDesktopTitles4[]; +//const char *simuTitles0[]; +//const char *simuTitles1[]; +//const char *simuTitles2[]; +//const char *vrTitles0[]; +//const char *vrTitles1[]; +//const char *sportsCtrlTitles0[]; +//const char *sportsCtrlTitles1[]; +//const char *sportsCtrlTitles2[]; +//const char *gameTitles0[]; +//const char *gameTitles1[]; +//const char *genDevCtrlTitles[]; +//const char *ledTitles[]; +//const char *telTitles0[]; +//const char *telTitles1[]; +//const char *telTitles2[]; +//const char *telTitles3[]; +//const char *telTitles4[]; +//const char *telTitles5[]; +//const char *consTitles0[]; +//const char *consTitles1[]; +//const char *consTitles2[]; +//const char *consTitles3[]; +//const char *consTitles4[]; +//const char *consTitles5[]; +//const char *consTitles6[]; +//const char *consTitles7[]; +//const char *consTitles8[]; +//const char *consTitles9[]; +//const char *consTitlesA[]; +//const char *consTitlesB[]; +//const char *consTitlesC[]; +//const char *consTitlesD[]; +//const char *consTitlesE[]; +//const char *digitTitles0[]; +//const char *digitTitles1[]; +//const char *digitTitles2[]; +//const char *aplphanumTitles0[]; +//const char *aplphanumTitles1[]; +//const char *aplphanumTitles2[]; +//const char *medInstrTitles0[]; +//const char *medInstrTitles1[]; +//const char *medInstrTitles2[]; +//const char *medInstrTitles3[]; +//const char *medInstrTitles4[]; + +#endif //__HIDUSAGESTR_H__ diff --git a/lib/usbhost/USB_Host_Shield_2.0/hidusagetitlearrays.cpp b/lib/usbhost/USB_Host_Shield_2.0/hidusagetitlearrays.cpp new file mode 100644 index 0000000000..ee233002ca --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/hidusagetitlearrays.cpp @@ -0,0 +1,1048 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#if !defined(__HIDUSAGETITLEARRAYS_H__) +#define __HIDUSAGETITLEARRAYS_H__ + +#include "hidusagestr.h" + +// This is here why? + +//const char *usagePageTitles0[] PROGMEM = +//{ +// pstrUsagePageGenericDesktopControls , +// pstrUsagePageSimulationControls , +// pstrUsagePageVRControls , +// pstrUsagePageSportControls , +// pstrUsagePageGameControls , +// pstrUsagePageGenericDeviceControls , +// pstrUsagePageKeyboardKeypad , +// pstrUsagePageLEDs , +// pstrUsagePageButton , +// pstrUsagePageOrdinal , +// pstrUsagePageTelephone , +// pstrUsagePageConsumer , +// pstrUsagePageDigitizer , +// pstrUsagePagePID , +// pstrUsagePageUnicode +//}; +// +//const char *usagePageTitles1[] PROGMEM = +//{ +// pstrUsagePageBarCodeScanner , +// pstrUsagePageScale , +// pstrUsagePageMSRDevices , +// pstrUsagePagePointOfSale , +// pstrUsagePageCameraControl , +// pstrUsagePageArcade +//}; +//const char *genDesktopTitles0[] PROGMEM = +//{ +// pstrUsagePointer , +// pstrUsageMouse , +// pstrUsageJoystick , +// pstrUsageGamePad , +// pstrUsageKeyboard , +// pstrUsageKeypad , +// pstrUsageMultiAxisController , +// pstrUsageTabletPCSystemControls +// +//}; +//const char *genDesktopTitles1[] PROGMEM = +//{ +// pstrUsageX , +// pstrUsageY , +// pstrUsageZ , +// pstrUsageRx , +// pstrUsageRy , +// pstrUsageRz , +// pstrUsageSlider , +// pstrUsageDial , +// pstrUsageWheel , +// pstrUsageHatSwitch , +// pstrUsageCountedBuffer , +// pstrUsageByteCount , +// pstrUsageMotionWakeup , +// pstrUsageStart , +// pstrUsageSelect , +// pstrUsagePageReserved , +// pstrUsageVx , +// pstrUsageVy , +// pstrUsageVz , +// pstrUsageVbrx , +// pstrUsageVbry , +// pstrUsageVbrz , +// pstrUsageVno , +// pstrUsageFeatureNotification , +// pstrUsageResolutionMultiplier +//}; +//const char *genDesktopTitles2[] PROGMEM = +//{ +// pstrUsageSystemControl , +// pstrUsageSystemPowerDown , +// pstrUsageSystemSleep , +// pstrUsageSystemWakeup , +// pstrUsageSystemContextMenu , +// pstrUsageSystemMainMenu , +// pstrUsageSystemAppMenu , +// pstrUsageSystemMenuHelp , +// pstrUsageSystemMenuExit , +// pstrUsageSystemMenuSelect , +// pstrUsageSystemMenuRight , +// pstrUsageSystemMenuLeft , +// pstrUsageSystemMenuUp , +// pstrUsageSystemMenuDown , +// pstrUsageSystemColdRestart , +// pstrUsageSystemWarmRestart , +// pstrUsageDPadUp , +// pstrUsageDPadDown , +// pstrUsageDPadRight , +// pstrUsageDPadLeft +//}; +//const char *genDesktopTitles3[] PROGMEM = +//{ +// pstrUsageSystemDock , +// pstrUsageSystemUndock , +// pstrUsageSystemSetup , +// pstrUsageSystemBreak , +// pstrUsageSystemDebuggerBreak , +// pstrUsageApplicationBreak , +// pstrUsageApplicationDebuggerBreak, +// pstrUsageSystemSpeakerMute , +// pstrUsageSystemHibernate +//}; +//const char *genDesktopTitles4[] PROGMEM = +//{ +// pstrUsageSystemDisplayInvert , +// pstrUsageSystemDisplayInternal , +// pstrUsageSystemDisplayExternal , +// pstrUsageSystemDisplayBoth , +// pstrUsageSystemDisplayDual , +// pstrUsageSystemDisplayToggleIntExt , +// pstrUsageSystemDisplaySwapPriSec , +// pstrUsageSystemDisplayLCDAutoscale +//}; +//const char *simuTitles0[] PROGMEM = +//{ +// pstrUsageFlightSimulationDevice , +// pstrUsageAutomobileSimulationDevice , +// pstrUsageTankSimulationDevice , +// pstrUsageSpaceshipSimulationDevice , +// pstrUsageSubmarineSimulationDevice , +// pstrUsageSailingSimulationDevice , +// pstrUsageMotocicleSimulationDevice , +// pstrUsageSportsSimulationDevice , +// pstrUsageAirplaneSimulationDevice , +// pstrUsageHelicopterSimulationDevice , +// pstrUsageMagicCarpetSimulationDevice, +// pstrUsageBicycleSimulationDevice +//}; +//const char *simuTitles1[] PROGMEM = +//{ +// pstrUsageFlightControlStick , +// pstrUsageFlightStick , +// pstrUsageCyclicControl , +// pstrUsageCyclicTrim , +// pstrUsageFlightYoke , +// pstrUsageTrackControl +//}; +//const char *simuTitles2[] PROGMEM = +//{ +// pstrUsageAileron , +// pstrUsageAileronTrim , +// pstrUsageAntiTorqueControl , +// pstrUsageAutopilotEnable , +// pstrUsageChaffRelease , +// pstrUsageCollectiveControl , +// pstrUsageDiveBrake , +// pstrUsageElectronicCountermeasures , +// pstrUsageElevator , +// pstrUsageElevatorTrim , +// pstrUsageRudder , +// pstrUsageThrottle , +// pstrUsageFlightCommunications , +// pstrUsageFlareRelease , +// pstrUsageLandingGear , +// pstrUsageToeBrake , +// pstrUsageTrigger , +// pstrUsageWeaponsArm , +// pstrUsageWeaponsSelect , +// pstrUsageWingFlaps , +// pstrUsageAccelerator , +// pstrUsageBrake , +// pstrUsageClutch , +// pstrUsageShifter , +// pstrUsageSteering , +// pstrUsageTurretDirection , +// pstrUsageBarrelElevation , +// pstrUsageDivePlane , +// pstrUsageBallast , +// pstrUsageBicycleCrank , +// pstrUsageHandleBars , +// pstrUsageFrontBrake , +// pstrUsageRearBrake +//}; +//const char *vrTitles0[] PROGMEM = +//{ +// pstrUsageBelt , +// pstrUsageBodySuit , +// pstrUsageFlexor , +// pstrUsageGlove , +// pstrUsageHeadTracker , +// pstrUsageHeadMountedDisplay , +// pstrUsageHandTracker , +// pstrUsageOculometer , +// pstrUsageVest , +// pstrUsageAnimatronicDevice +//}; +//const char *vrTitles1[] PROGMEM = +//{ +// pstrUsageStereoEnable , +// pstrUsageDisplayEnable +//}; +//const char *sportsCtrlTitles0[] PROGMEM = +//{ +// pstrUsageBaseballBat , +// pstrUsageGolfClub , +// pstrUsageRowingMachine , +// pstrUsageTreadmill +//}; +//const char *sportsCtrlTitles1[] PROGMEM = +//{ +// pstrUsageOar , +// pstrUsageSlope , +// pstrUsageRate , +// pstrUsageStickSpeed , +// pstrUsageStickFaceAngle , +// pstrUsageStickHeelToe , +// pstrUsageStickFollowThough , +// pstrUsageStickTempo , +// pstrUsageStickType , +// pstrUsageStickHeight +//}; +//const char *sportsCtrlTitles2[] PROGMEM = +//{ +// pstrUsagePutter , +// pstrUsage1Iron , +// pstrUsage2Iron , +// pstrUsage3Iron , +// pstrUsage4Iron , +// pstrUsage5Iron , +// pstrUsage6Iron , +// pstrUsage7Iron , +// pstrUsage8Iron , +// pstrUsage9Iron , +// pstrUsage10Iron , +// pstrUsage11Iron , +// pstrUsageSandWedge , +// pstrUsageLoftWedge , +// pstrUsagePowerWedge , +// pstrUsage1Wood , +// pstrUsage3Wood , +// pstrUsage5Wood , +// pstrUsage7Wood , +// pstrUsage9Wood +//}; +//const char *gameTitles0[] PROGMEM = +//{ +// pstrUsage3DGameController , +// pstrUsagePinballDevice , +// pstrUsageGunDevice +//}; +//const char *gameTitles1[] PROGMEM = +//{ +// pstrUsagePointOfView , +// pstrUsageTurnRightLeft , +// pstrUsagePitchForwardBackward , +// pstrUsageRollRightLeft , +// pstrUsageMoveRightLeft , +// pstrUsageMoveForwardBackward , +// pstrUsageMoveUpDown , +// pstrUsageLeanRightLeft , +// pstrUsageLeanForwardBackward , +// pstrUsageHeightOfPOV , +// pstrUsageFlipper , +// pstrUsageSecondaryFlipper , +// pstrUsageBump , +// pstrUsageNewGame , +// pstrUsageShootBall , +// pstrUsagePlayer , +// pstrUsageGunBolt , +// pstrUsageGunClip , +// pstrUsageGunSelector , +// pstrUsageGunSingleShot , +// pstrUsageGunBurst , +// pstrUsageGunAutomatic , +// pstrUsageGunSafety , +// pstrUsageGamepadFireJump , +// pstrUsageGamepadTrigger +//}; +//const char *genDevCtrlTitles[] PROGMEM = +//{ +// pstrUsageBatteryStrength, +// pstrUsageWirelessChannel, +// pstrUsageWirelessID, +// pstrUsageDiscoverWirelessControl, +// pstrUsageSecurityCodeCharEntered, +// pstrUsageSecurityCodeCharErased, +// pstrUsageSecurityCodeCleared +//}; +//const char *ledTitles[] PROGMEM = +//{ +// pstrUsageNumLock , +// pstrUsageCapsLock , +// pstrUsageScrollLock , +// pstrUsageCompose , +// pstrUsageKana , +// pstrUsagePower , +// pstrUsageShift , +// pstrUsageDoNotDisturb , +// pstrUsageMute , +// pstrUsageToneEnable , +// pstrUsageHighCutFilter , +// pstrUsageLowCutFilter , +// pstrUsageEqualizerEnable , +// pstrUsageSoundFieldOn , +// pstrUsageSurroundOn , +// pstrUsageRepeat , +// pstrUsageStereo , +// pstrUsageSamplingRateDetect , +// pstrUsageSpinning , +// pstrUsageCAV , +// pstrUsageCLV , +// pstrUsageRecordingFormatDetect , +// pstrUsageOffHook , +// pstrUsageRing , +// pstrUsageMessageWaiting , +// pstrUsageDataMode , +// pstrUsageBatteryOperation , +// pstrUsageBatteryOK , +// pstrUsageBatteryLow , +// pstrUsageSpeaker , +// pstrUsageHeadSet , +// pstrUsageHold , +// pstrUsageMicrophone , +// pstrUsageCoverage , +// pstrUsageNightMode , +// pstrUsageSendCalls , +// pstrUsageCallPickup , +// pstrUsageConference , +// pstrUsageStandBy , +// pstrUsageCameraOn , +// pstrUsageCameraOff , +// pstrUsageOnLine , +// pstrUsageOffLine , +// pstrUsageBusy , +// pstrUsageReady , +// pstrUsagePaperOut , +// pstrUsagePaperJam , +// pstrUsageRemote , +// pstrUsageForward , +// pstrUsageReverse , +// pstrUsageStop , +// pstrUsageRewind , +// pstrUsageFastForward , +// pstrUsagePlay , +// pstrUsagePause , +// pstrUsageRecord , +// pstrUsageError , +// pstrUsageSelectedIndicator , +// pstrUsageInUseIndicator , +// pstrUsageMultiModeIndicator , +// pstrUsageIndicatorOn , +// pstrUsageIndicatorFlash , +// pstrUsageIndicatorSlowBlink , +// pstrUsageIndicatorFastBlink , +// pstrUsageIndicatorOff , +// pstrUsageFlashOnTime , +// pstrUsageSlowBlinkOnTime , +// pstrUsageSlowBlinkOffTime , +// pstrUsageFastBlinkOnTime , +// pstrUsageFastBlinkOffTime , +// pstrUsageIndicatorColor , +// pstrUsageIndicatorRed , +// pstrUsageIndicatorGreen , +// pstrUsageIndicatorAmber , +// pstrUsageGenericIndicator , +// pstrUsageSystemSuspend , +// pstrUsageExternalPowerConnected +//}; +//const char *telTitles0 [] PROGMEM = +//{ +// pstrUsagePhone , +// pstrUsageAnsweringMachine , +// pstrUsageMessageControls , +// pstrUsageHandset , +// pstrUsageHeadset , +// pstrUsageTelephonyKeyPad , +// pstrUsageProgrammableButton +//}; +//const char *telTitles1 [] PROGMEM = +//{ +// pstrUsageHookSwitch , +// pstrUsageFlash , +// pstrUsageFeature , +// pstrUsageHold , +// pstrUsageRedial , +// pstrUsageTransfer , +// pstrUsageDrop , +// pstrUsagePark , +// pstrUsageForwardCalls , +// pstrUsageAlternateFunction , +// pstrUsageLine , +// pstrUsageSpeakerPhone , +// pstrUsageConference , +// pstrUsageRingEnable , +// pstrUsageRingSelect , +// pstrUsagePhoneMute , +// pstrUsageCallerID , +// pstrUsageSend +//}; +//const char *telTitles2 [] PROGMEM = +//{ +// pstrUsageSpeedDial , +// pstrUsageStoreNumber , +// pstrUsageRecallNumber , +// pstrUsagePhoneDirectory +//}; +//const char *telTitles3 [] PROGMEM = +//{ +// pstrUsageVoiceMail , +// pstrUsageScreenCalls , +// pstrUsageDoNotDisturb , +// pstrUsageMessage , +// pstrUsageAnswerOnOff +//}; +//const char *telTitles4 [] PROGMEM = +//{ +// pstrUsageInsideDialTone , +// pstrUsageOutsideDialTone , +// pstrUsageInsideRingTone , +// pstrUsageOutsideRingTone , +// pstrUsagePriorityRingTone , +// pstrUsageInsideRingback , +// pstrUsagePriorityRingback , +// pstrUsageLineBusyTone , +// pstrUsageReorderTone , +// pstrUsageCallWaitingTone , +// pstrUsageConfirmationTone1 , +// pstrUsageConfirmationTone2 , +// pstrUsageTonesOff , +// pstrUsageOutsideRingback , +// pstrUsageRinger +//}; +//const char *telTitles5 [] PROGMEM = +//{ +// pstrUsagePhoneKey0 , +// pstrUsagePhoneKey1 , +// pstrUsagePhoneKey2 , +// pstrUsagePhoneKey3 , +// pstrUsagePhoneKey4 , +// pstrUsagePhoneKey5 , +// pstrUsagePhoneKey6 , +// pstrUsagePhoneKey7 , +// pstrUsagePhoneKey8 , +// pstrUsagePhoneKey9 , +// pstrUsagePhoneKeyStar , +// pstrUsagePhoneKeyPound , +// pstrUsagePhoneKeyA , +// pstrUsagePhoneKeyB , +// pstrUsagePhoneKeyC , +// pstrUsagePhoneKeyD +//}; +//const char *consTitles0[] PROGMEM = +//{ +// pstrUsageConsumerControl, +// pstrUsageNumericKeyPad, +// pstrUsageProgrammableButton, +// pstrUsageMicrophone, +// pstrUsageHeadphone, +// pstrUsageGraphicEqualizer +//}; +//const char *consTitles1[] PROGMEM = +//{ +// pstrUsagePlus10 , +// pstrUsagePlus100, +// pstrUsageAMPM +//}; +//const char *consTitles2[] PROGMEM = +//{ +// pstrUsagePower , +// pstrUsageReset , +// pstrUsageSleep , +// pstrUsageSleepAfter , +// pstrUsageSleepMode , +// pstrUsageIllumination , +// pstrUsageFunctionButtons +// +//}; +//const char *consTitles3[] PROGMEM = +//{ +// pstrUsageMenu , +// pstrUsageMenuPick , +// pstrUsageMenuUp , +// pstrUsageMenuDown , +// pstrUsageMenuLeft , +// pstrUsageMenuRight , +// pstrUsageMenuEscape , +// pstrUsageMenuValueIncrease, +// pstrUsageMenuValueDecrease +//}; +//const char *consTitles4[] PROGMEM = +//{ +// pstrUsageDataOnScreen , +// pstrUsageClosedCaption , +// pstrUsageClosedCaptionSelect, +// pstrUsageVCRTV , +// pstrUsageBroadcastMode , +// pstrUsageSnapshot , +// pstrUsageStill +//}; +//const char *consTitles5[] PROGMEM = +//{ +// pstrUsageSelection , +// pstrUsageAssignSelection , +// pstrUsageModeStep , +// pstrUsageRecallLast , +// pstrUsageEnterChannel , +// pstrUsageOrderMovie , +// pstrUsageChannel , +// pstrUsageMediaSelection , +// pstrUsageMediaSelectComputer , +// pstrUsageMediaSelectTV , +// pstrUsageMediaSelectWWW , +// pstrUsageMediaSelectDVD , +// pstrUsageMediaSelectTelephone , +// pstrUsageMediaSelectProgramGuide , +// pstrUsageMediaSelectVideoPhone , +// pstrUsageMediaSelectGames , +// pstrUsageMediaSelectMessages , +// pstrUsageMediaSelectCD , +// pstrUsageMediaSelectVCR , +// pstrUsageMediaSelectTuner , +// pstrUsageQuit , +// pstrUsageHelp , +// pstrUsageMediaSelectTape , +// pstrUsageMediaSelectCable , +// pstrUsageMediaSelectSatellite , +// pstrUsageMediaSelectSecurity , +// pstrUsageMediaSelectHome , +// pstrUsageMediaSelectCall , +// pstrUsageChannelIncrement , +// pstrUsageChannelDecrement , +// pstrUsageMediaSelectSAP , +// pstrUsagePageReserved , +// pstrUsageVCRPlus , +// pstrUsageOnce , +// pstrUsageDaily , +// pstrUsageWeekly , +// pstrUsageMonthly +//}; +//const char *consTitles6[] PROGMEM = +//{ +// pstrUsagePlay , +// pstrUsagePause , +// pstrUsageRecord , +// pstrUsageFastForward , +// pstrUsageRewind , +// pstrUsageScanNextTrack , +// pstrUsageScanPreviousTrack , +// pstrUsageStop , +// pstrUsageEject , +// pstrUsageRandomPlay , +// pstrUsageSelectDisk , +// pstrUsageEnterDisk , +// pstrUsageRepeat , +// pstrUsageTracking , +// pstrUsageTrackNormal , +// pstrUsageSlowTracking , +// pstrUsageFrameForward , +// pstrUsageFrameBackwards , +// pstrUsageMark , +// pstrUsageClearMark , +// pstrUsageRepeatFromMark , +// pstrUsageReturnToMark , +// pstrUsageSearchMarkForward , +// pstrUsageSearchMarkBackwards , +// pstrUsageCounterReset , +// pstrUsageShowCounter , +// pstrUsageTrackingIncrement , +// pstrUsageTrackingDecrement , +// pstrUsageStopEject , +// pstrUsagePlayPause , +// pstrUsagePlaySkip +//}; +//const char *consTitles7[] PROGMEM = +//{ +// pstrUsageVolume , +// pstrUsageBalance , +// pstrUsageMute , +// pstrUsageBass , +// pstrUsageTreble , +// pstrUsageBassBoost , +// pstrUsageSurroundMode , +// pstrUsageLoudness , +// pstrUsageMPX , +// pstrUsageVolumeIncrement , +// pstrUsageVolumeDecrement +//}; +//const char *consTitles8[] PROGMEM = +//{ +// pstrUsageSpeedSelect , +// pstrUsagePlaybackSpeed , +// pstrUsageStandardPlay , +// pstrUsageLongPlay , +// pstrUsageExtendedPlay , +// pstrUsageSlow +//}; +//const char *consTitles9[] PROGMEM = +//{ +// pstrUsageFanEnable , +// pstrUsageFanSpeed , +// pstrUsageLightEnable , +// pstrUsageLightIlluminationLevel , +// pstrUsageClimateControlEnable , +// pstrUsageRoomTemperature , +// pstrUsageSecurityEnable , +// pstrUsageFireAlarm , +// pstrUsagePoliceAlarm , +// pstrUsageProximity , +// pstrUsageMotion , +// pstrUsageDuresAlarm , +// pstrUsageHoldupAlarm , +// pstrUsageMedicalAlarm +//}; +//const char *consTitlesA[] PROGMEM = +//{ +// pstrUsageBalanceRight , +// pstrUsageBalanceLeft , +// pstrUsageBassIncrement , +// pstrUsageBassDecrement , +// pstrUsageTrebleIncrement , +// pstrUsageTrebleDecrement +//}; +//const char *consTitlesB[] PROGMEM = +//{ +// pstrUsageSpeakerSystem , +// pstrUsageChannelLeft , +// pstrUsageChannelRight , +// pstrUsageChannelCenter , +// pstrUsageChannelFront , +// pstrUsageChannelCenterFront , +// pstrUsageChannelSide , +// pstrUsageChannelSurround , +// pstrUsageChannelLowFreqEnhancement , +// pstrUsageChannelTop , +// pstrUsageChannelUnknown +//}; +//const char *consTitlesC[] PROGMEM = +//{ +// pstrUsageSubChannel , +// pstrUsageSubChannelIncrement , +// pstrUsageSubChannelDecrement , +// pstrUsageAlternateAudioIncrement , +// pstrUsageAlternateAudioDecrement +//}; +//const char *consTitlesD[] PROGMEM = +//{ +// pstrUsageApplicationLaunchButtons , +// pstrUsageALLaunchButtonConfigTool , +// pstrUsageALProgrammableButton , +// pstrUsageALConsumerControlConfig , +// pstrUsageALWordProcessor , +// pstrUsageALTextEditor , +// pstrUsageALSpreadsheet , +// pstrUsageALGraphicsEditor , +// pstrUsageALPresentationApp , +// pstrUsageALDatabaseApp , +// pstrUsageALEmailReader , +// pstrUsageALNewsreader , +// pstrUsageALVoicemail , +// pstrUsageALContactsAddressBook , +// pstrUsageALCalendarSchedule , +// pstrUsageALTaskProjectManager , +// pstrUsageALLogJournalTimecard , +// pstrUsageALCheckbookFinance , +// pstrUsageALCalculator , +// pstrUsageALAVCapturePlayback , +// pstrUsageALLocalMachineBrowser , +// pstrUsageALLANWANBrow , +// pstrUsageALInternetBrowser , +// pstrUsageALRemoteNetISPConnect , +// pstrUsageALNetworkConference , +// pstrUsageALNetworkChat , +// pstrUsageALTelephonyDialer , +// pstrUsageALLogon , +// pstrUsageALLogoff , +// pstrUsageALLogonLogoff , +// pstrUsageALTermLockScrSav , +// pstrUsageALControlPannel , +// pstrUsageALCommandLineProcessorRun , +// pstrUsageALProcessTaskManager , +// pstrUsageALSelectTaskApplication , +// pstrUsageALNextTaskApplication , +// pstrUsageALPreviousTaskApplication , +// pstrUsageALPreemptiveHaltTaskApp , +// pstrUsageALIntegratedHelpCenter , +// pstrUsageALDocuments , +// pstrUsageALThesaurus , +// pstrUsageALDictionary , +// pstrUsageALDesktop , +// pstrUsageALSpellCheck , +// pstrUsageALGrammarCheck , +// pstrUsageALWirelessStatus , +// pstrUsageALKeyboardLayout , +// pstrUsageALVirusProtection , +// pstrUsageALEncryption , +// pstrUsageALScreenSaver , +// pstrUsageALAlarms , +// pstrUsageALClock , +// pstrUsageALFileBrowser , +// pstrUsageALPowerStatus , +// pstrUsageALImageBrowser , +// pstrUsageALAudioBrowser , +// pstrUsageALMovieBrowser , +// pstrUsageALDigitalRightsManager , +// pstrUsageALDigitalWallet , +// pstrUsagePageReserved , +// pstrUsageALInstantMessaging , +// pstrUsageALOEMFeaturesBrowser , +// pstrUsageALOEMHelp , +// pstrUsageALOnlineCommunity , +// pstrUsageALEntertainmentContentBrow , +// pstrUsageALOnlineShoppingBrowser , +// pstrUsageALSmartCardInfoHelp , +// pstrUsageALMarketMonitorFinBrowser , +// pstrUsageALCustomCorpNewsBrowser , +// pstrUsageALOnlineActivityBrowser , +// pstrUsageALResearchSearchBrowser , +// pstrUsageALAudioPlayer +//}; +//const char *consTitlesE[] PROGMEM = +//{ +// pstrUsageGenericGUIAppControls , +// pstrUsageACNew , +// pstrUsageACOpen , +// pstrUsageACClose , +// pstrUsageACExit , +// pstrUsageACMaximize , +// pstrUsageACMinimize , +// pstrUsageACSave , +// pstrUsageACPrint , +// pstrUsageACProperties , +// pstrUsageACUndo , +// pstrUsageACCopy , +// pstrUsageACCut , +// pstrUsageACPaste , +// pstrUsageACSelectAll , +// pstrUsageACFind , +// pstrUsageACFindAndReplace , +// pstrUsageACSearch , +// pstrUsageACGoto , +// pstrUsageACHome , +// pstrUsageACBack , +// pstrUsageACForward , +// pstrUsageACStop , +// pstrUsageACRefresh , +// pstrUsageACPreviousLink , +// pstrUsageACNextLink , +// pstrUsageACBookmarks , +// pstrUsageACHistory , +// pstrUsageACSubscriptions , +// pstrUsageACZoomIn , +// pstrUsageACZoomOut , +// pstrUsageACZoom , +// pstrUsageACFullScreenView , +// pstrUsageACNormalView , +// pstrUsageACViewToggle , +// pstrUsageACScrollUp , +// pstrUsageACScrollDown , +// pstrUsageACScroll , +// pstrUsageACPanLeft , +// pstrUsageACPanRight , +// pstrUsageACPan , +// pstrUsageACNewWindow , +// pstrUsageACTileHoriz , +// pstrUsageACTileVert , +// pstrUsageACFormat , +// pstrUsageACEdit , +// pstrUsageACBold , +// pstrUsageACItalics , +// pstrUsageACUnderline , +// pstrUsageACStrikethrough , +// pstrUsageACSubscript , +// pstrUsageACSuperscript , +// pstrUsageACAllCaps , +// pstrUsageACRotate , +// pstrUsageACResize , +// pstrUsageACFlipHorizontal , +// pstrUsageACFlipVertical , +// pstrUsageACMirrorHorizontal , +// pstrUsageACMirrorVertical , +// pstrUsageACFontSelect , +// pstrUsageACFontColor , +// pstrUsageACFontSize , +// pstrUsageACJustifyLeft , +// pstrUsageACJustifyCenterH , +// pstrUsageACJustifyRight , +// pstrUsageACJustifyBlockH , +// pstrUsageACJustifyTop , +// pstrUsageACJustifyCenterV , +// pstrUsageACJustifyBottom , +// pstrUsageACJustifyBlockV , +// pstrUsageACIndentDecrease , +// pstrUsageACIndentIncrease , +// pstrUsageACNumberedList , +// pstrUsageACRestartNumbering , +// pstrUsageACBulletedList , +// pstrUsageACPromote , +// pstrUsageACDemote , +// pstrUsageACYes , +// pstrUsageACNo , +// pstrUsageACCancel , +// pstrUsageACCatalog , +// pstrUsageACBuyChkout , +// pstrUsageACAddToCart , +// pstrUsageACExpand , +// pstrUsageACExpandAll , +// pstrUsageACCollapse , +// pstrUsageACCollapseAll , +// pstrUsageACPrintPreview , +// pstrUsageACPasteSpecial , +// pstrUsageACInsertMode , +// pstrUsageACDelete , +// pstrUsageACLock , +// pstrUsageACUnlock , +// pstrUsageACProtect , +// pstrUsageACUnprotect , +// pstrUsageACAttachComment , +// pstrUsageACDeleteComment , +// pstrUsageACViewComment , +// pstrUsageACSelectWord , +// pstrUsageACSelectSentence , +// pstrUsageACSelectParagraph , +// pstrUsageACSelectColumn , +// pstrUsageACSelectRow , +// pstrUsageACSelectTable , +// pstrUsageACSelectObject , +// pstrUsageACRedoRepeat , +// pstrUsageACSort , +// pstrUsageACSortAscending , +// pstrUsageACSortDescending , +// pstrUsageACFilter , +// pstrUsageACSetClock , +// pstrUsageACViewClock , +// pstrUsageACSelectTimeZone , +// pstrUsageACEditTimeZone , +// pstrUsageACSetAlarm , +// pstrUsageACClearAlarm , +// pstrUsageACSnoozeAlarm , +// pstrUsageACResetAlarm , +// pstrUsageACSyncronize , +// pstrUsageACSendReceive , +// pstrUsageACSendTo , +// pstrUsageACReply , +// pstrUsageACReplyAll , +// pstrUsageACForwardMessage , +// pstrUsageACSend , +// pstrUsageACAttachFile , +// pstrUsageACUpload , +// pstrUsageACDownload , +// pstrUsageACSetBorders , +// pstrUsageACInsertRow , +// pstrUsageACInsertColumn , +// pstrUsageACInsertFile , +// pstrUsageACInsertPicture , +// pstrUsageACInsertObject , +// pstrUsageACInsertSymbol , +// pstrUsageACSaveAndClose , +// pstrUsageACRename , +// pstrUsageACMerge , +// pstrUsageACSplit , +// pstrUsageACDistributeHorizontaly , +// pstrUsageACDistributeVerticaly +//}; +//const char *digitTitles0[] PROGMEM = +//{ +// pstrUsageDigitizer , +// pstrUsagePen , +// pstrUsageLightPen , +// pstrUsageTouchScreen , +// pstrUsageTouchPad , +// pstrUsageWhiteBoard , +// pstrUsageCoordinateMeasuringMachine , +// pstrUsage3DDigitizer , +// pstrUsageStereoPlotter , +// pstrUsageArticulatedArm , +// pstrUsageArmature , +// pstrUsageMultiplePointDigitizer , +// pstrUsageFreeSpaceWand +//}; +//const char *digitTitles1[] PROGMEM = +//{ +// pstrUsageStylus , +// pstrUsagePuck , +// pstrUsageFinger +// +//}; +//const char *digitTitles2[] PROGMEM = +//{ +// pstrUsageTipPressure , +// pstrUsageBarrelPressure , +// pstrUsageInRange , +// pstrUsageTouch , +// pstrUsageUntouch , +// pstrUsageTap , +// pstrUsageQuality , +// pstrUsageDataValid , +// pstrUsageTransducerIndex , +// pstrUsageTabletFunctionKeys , +// pstrUsageProgramChangeKeys , +// pstrUsageBatteryStrength , +// pstrUsageInvert , +// pstrUsageXTilt , +// pstrUsageYTilt , +// pstrUsageAzimuth , +// pstrUsageAltitude , +// pstrUsageTwist , +// pstrUsageTipSwitch , +// pstrUsageSecondaryTipSwitch , +// pstrUsageBarrelSwitch , +// pstrUsageEraser , +// pstrUsageTabletPick +//}; +//const char *aplphanumTitles0[] PROGMEM = +//{ +// pstrUsageAlphanumericDisplay, +// pstrUsageBitmappedDisplay +//}; +//const char *aplphanumTitles1[] PROGMEM = +//{ +// pstrUsageDisplayAttributesReport , +// pstrUsageASCIICharacterSet , +// pstrUsageDataReadBack , +// pstrUsageFontReadBack , +// pstrUsageDisplayControlReport , +// pstrUsageClearDisplay , +// pstrUsageDisplayEnable , +// pstrUsageScreenSaverDelay , +// pstrUsageScreenSaverEnable , +// pstrUsageVerticalScroll , +// pstrUsageHorizontalScroll , +// pstrUsageCharacterReport , +// pstrUsageDisplayData , +// pstrUsageDisplayStatus , +// pstrUsageStatusNotReady , +// pstrUsageStatusReady , +// pstrUsageErrorNotALoadableCharacter , +// pstrUsageErrorFotDataCanNotBeRead , +// pstrUsageCursorPositionReport , +// pstrUsageRow , +// pstrUsageColumn , +// pstrUsageRows , +// pstrUsageColumns , +// pstrUsageCursorPixelPosition , +// pstrUsageCursorMode , +// pstrUsageCursorEnable , +// pstrUsageCursorBlink , +// pstrUsageFontReport , +// pstrUsageFontData , +// pstrUsageCharacterWidth , +// pstrUsageCharacterHeight , +// pstrUsageCharacterSpacingHorizontal , +// pstrUsageCharacterSpacingVertical , +// pstrUsageUnicodeCharset , +// pstrUsageFont7Segment , +// pstrUsage7SegmentDirectMap , +// pstrUsageFont14Segment , +// pstrUsage14SegmentDirectMap , +// pstrUsageDisplayBrightness , +// pstrUsageDisplayContrast , +// pstrUsageCharacterAttribute , +// pstrUsageAttributeReadback , +// pstrUsageAttributeData , +// pstrUsageCharAttributeEnhance , +// pstrUsageCharAttributeUnderline , +// pstrUsageCharAttributeBlink +//}; +//const char *aplphanumTitles2[] PROGMEM = +//{ +// pstrUsageBitmapSizeX , +// pstrUsageBitmapSizeY , +// pstrUsagePageReserved , +// pstrUsageBitDepthFormat , +// pstrUsageDisplayOrientation , +// pstrUsagePaletteReport , +// pstrUsagePaletteDataSize , +// pstrUsagePaletteDataOffset , +// pstrUsagePaletteData , +// pstrUsageBlitReport , +// pstrUsageBlitRectangleX1 , +// pstrUsageBlitRectangleY1 , +// pstrUsageBlitRectangleX2 , +// pstrUsageBlitRectangleY2 , +// pstrUsageBlitData , +// pstrUsageSoftButton , +// pstrUsageSoftButtonID , +// pstrUsageSoftButtonSide , +// pstrUsageSoftButtonOffset1 , +// pstrUsageSoftButtonOffset2 , +// pstrUsageSoftButtonReport +//}; +//const char *medInstrTitles0[] PROGMEM = +//{ +// pstrUsageVCRAcquisition , +// pstrUsageFreezeThaw , +// pstrUsageClipStore , +// pstrUsageUpdate , +// pstrUsageNext , +// pstrUsageSave , +// pstrUsagePrint , +// pstrUsageMicrophoneEnable +//}; +//const char *medInstrTitles1[] PROGMEM = +//{ +// pstrUsageCine , +// pstrUsageTransmitPower , +// pstrUsageVolume , +// pstrUsageFocus , +// pstrUsageDepth +//}; +//const char *medInstrTitles2[] PROGMEM = +//{ +// pstrUsageSoftStepPrimary , +// pstrUsageSoftStepSecondary +//}; +//const char *medInstrTitles3[] PROGMEM = +//{ +// pstrUsageZoomSelect , +// pstrUsageZoomAdjust , +// pstrUsageSpectralDopplerModeSelect , +// pstrUsageSpectralDopplerModeAdjust , +// pstrUsageColorDopplerModeSelect , +// pstrUsageColorDopplerModeAdjust , +// pstrUsageMotionModeSelect , +// pstrUsageMotionModeAdjust , +// pstrUsage2DModeSelect , +// pstrUsage2DModeAdjust +//}; +//const char *medInstrTitles4[] PROGMEM = +//{ +// pstrUsageSoftControlSelect , +// pstrUsageSoftControlAdjust +//}; + +#endif // __HIDUSAGETITLEARRAYS_H__ diff --git a/lib/usbhost/USB_Host_Shield_2.0/keywords.txt b/lib/usbhost/USB_Host_Shield_2.0/keywords.txt new file mode 100644 index 0000000000..f4e19cd133 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/keywords.txt @@ -0,0 +1,371 @@ +#################################################### +# Syntax Coloring Map For USB Library +#################################################### + +#################################################### +# Datatypes (KEYWORD1) +#################################################### + +USB KEYWORD1 +USBHub KEYWORD1 + +#################################################### +# Syntax Coloring Map For BTD (Bluetooth) Library +#################################################### + +#################################################### +# Datatypes (KEYWORD1) +#################################################### + +BTD KEYWORD1 + +#################################################### +# Methods and Functions (KEYWORD2) +#################################################### +Task KEYWORD2 + +#################################################### +# Syntax Coloring Map For PS3/PS4 Bluetooth/USB Library +#################################################### + +#################################################### +# Datatypes (KEYWORD1) +#################################################### + +PS3BT KEYWORD1 +PS3USB KEYWORD1 +PS4BT KEYWORD1 +PS4USB KEYWORD1 + +#################################################### +# Methods and Functions (KEYWORD2) +#################################################### +setBdaddr KEYWORD2 +getBdaddr KEYWORD2 +setMoveBdaddr KEYWORD2 +getMoveBdaddr KEYWORD2 +getMoveCalibration KEYWORD2 + +getButtonPress KEYWORD2 +getButtonClick KEYWORD2 +getAnalogButton KEYWORD2 +getAnalogHat KEYWORD2 +getSensor KEYWORD2 +getAngle KEYWORD2 +get9DOFValues KEYWORD2 +getStatus KEYWORD2 +printStatusString KEYWORD2 +getTemperature KEYWORD2 +disconnect KEYWORD2 + +setAllOff KEYWORD2 +setRumbleOff KEYWORD2 +setRumbleOn KEYWORD2 +setLedOff KEYWORD2 +setLedOn KEYWORD2 +setLedToggle KEYWORD2 +setLedFlash KEYWORD2 +moveSetBulb KEYWORD2 +moveSetRumble KEYWORD2 + +attachOnInit KEYWORD2 + +PS3Connected KEYWORD2 +PS3MoveConnected KEYWORD2 +PS3NavigationConnected KEYWORD2 + +isReady KEYWORD2 +watingForConnection KEYWORD2 + +isTouching KEYWORD2 +getX KEYWORD2 +getY KEYWORD2 +getTouchCounter KEYWORD2 + +getUsbStatus KEYWORD2 +getAudioStatus KEYWORD2 +getMicStatus KEYWORD2 + +#################################################### +# Constants and enums (LITERAL1) +#################################################### +OFF LITERAL1 +LED1 LITERAL1 +LED2 LITERAL1 +LED3 LITERAL1 +LED4 LITERAL1 +LED5 LITERAL1 +LED6 LITERAL1 +LED7 LITERAL1 +LED8 LITERAL1 +LED9 LITERAL1 +LED10 LITERAL1 + +Red LITERAL1 +Green LITERAL1 +Blue LITERAL1 +Yellow LITERAL1 +Lightblue LITERAL1 +Purble LITERAL1 +White LITERAL1 +Off LITERAL1 + +SELECT LITERAL1 +L3 LITERAL1 +R3 LITERAL1 +START LITERAL1 +UP LITERAL1 +RIGHT LITERAL1 +DOWN LITERAL1 +LEFT LITERAL1 +L2 LITERAL1 +R2 LITERAL1 +L1 LITERAL1 +R1 LITERAL1 +TRIANGLE LITERAL1 +CIRCLE LITERAL1 +CROSS LITERAL1 +SQUARE LITERAL1 +PS LITERAL1 +MOVE LITERAL1 +T LITERAL1 + +SHARE LITERAL1 +OPTIONS LITERAL1 +TOUCHPAD LITERAL1 + +LeftHatX LITERAL1 +LeftHatY LITERAL1 +RightHatX LITERAL1 +RightHatY LITERAL1 + +aX LITERAL1 +aY LITERAL1 +aZ LITERAL1 +gX LITERAL1 +gY LITERAL1 +gZ LITERAL1 +aXmove LITERAL1 +aYmove LITERAL1 +aZmove LITERAL1 +gXmove LITERAL1 +gYmove LITERAL1 +gZmove LITERAL1 +tempMove LITERAL1 +mXmove LITERAL1 +mZmove LITERAL1 +mYmove LITERAL1 + +Pitch LITERAL1 +Roll LITERAL1 + +Plugged LITERAL1 +Unplugged LITERAL1 +Charging LITERAL1 +NotCharging LITERAL1 +Shutdown LITERAL1 +Dying LITERAL1 +Low LITERAL1 +High LITERAL1 +Full LITERAL1 +MoveCharging LITERAL1 +MoveNotCharging LITERAL1 +MoveShutdown LITERAL1 +MoveDying LITERAL1 +MoveLow LITERAL1 +MoveHigh LITERAL1 +MoveFull LITERAL1 +CableRumble LITERAL1 +Cable LITERAL1 +BluetoothRumble LITERAL1 +Bluetooth LITERAL1 + +RumbleHigh LITERAL1 +RumbleLow LITERAL1 + +#################################################### +# Syntax Coloring Map For Xbox 360 Libraries +#################################################### + +#################################################### +# Datatypes (KEYWORD1) +#################################################### + +XBOXUSB KEYWORD1 +XBOXONE KEYWORD1 +XBOXOLD KEYWORD1 +XBOXRECV KEYWORD1 + +#################################################### +# Methods and Functions (KEYWORD2) +#################################################### + +setLedRaw KEYWORD2 +setLedBlink KEYWORD2 +setLedMode KEYWORD2 +getBatteryLevel KEYWORD2 +buttonChanged KEYWORD2 + +XboxReceiverConnected KEYWORD2 +Xbox360Connected KEYWORD2 +XboxOneConnected KEYWORD2 + +#################################################### +# Constants and enums (LITERAL1) +#################################################### + +ALL LITERAL1 + +ROTATING LITERAL1 +FASTBLINK LITERAL1 +SLOWBLINK LITERAL1 +ALTERNATING LITERAL1 + +BACK LITERAL1 + +XBOX LITERAL1 +SYNC LITERAL1 + +BLACK LITERAL1 +WHITE LITERAL1 + +A LITERAL1 +B LITERAL1 +X LITERAL1 +Y LITERAL1 + +#################################################### +# Syntax Coloring Map For RFCOMM/SPP Library +#################################################### + +#################################################### +# Datatypes (KEYWORD1) +#################################################### + +SPP KEYWORD1 + +#################################################### +# Methods and Functions (KEYWORD2) +#################################################### + +connected KEYWORD2 +discard KEYWORD2 + +#################################################### +# Syntax Coloring Map For Wiimote Library +#################################################### + +#################################################### +# Datatypes (KEYWORD1) +#################################################### + +WII KEYWORD1 + +#################################################### +# Methods and Functions (KEYWORD2) +#################################################### + +wiimoteConnected KEYWORD2 +nunchuckConnected KEYWORD2 +motionPlusConnected KEYWORD2 +wiiUProControllerConnected KEYWORD2 +wiiBalanceBoardConnected KEYWORD2 +setRumbleToggle KEYWORD2 +getPitch KEYWORD2 +getRoll KEYWORD2 +getYaw KEYWORD2 +getWiimotePitch KEYWORD2 +getWiimoteRoll KEYWORD2 +getNunchuckPitch KEYWORD2 +getNunchuckRoll KEYWORD2 +PAIR KEYWORD2 +statusRequest KEYWORD2 +getBatteryLevel KEYWORD2 +getWiiState KEYWORD2 +getWeight KEYWORD2 +getTotalWeight KEYWORD2 +getWeightRaw KEYWORD2 + +#################################################### +# Constants and enums (LITERAL1) +#################################################### + +PLUS LITERAL1 +MINUS LITERAL1 +ONE LITERAL1 +TWO LITERAL1 +HOME LITERAL1 +Z LITERAL1 +C LITERAL1 +L LITERAL1 +R LITERAL1 +ZL LITERAL1 +ZR LITERAL1 +HatX LITERAL1 +HatY LITERAL1 +TopRight LITERAL1 +BotRight LITERAL1 +TopLeft LITERAL1 +BotLeft LITERAL1 + +#################################################### +# Methods and Functions for the IR Camera +#################################################### + +IRinitialize KEYWORD2 +isIRCameraEnabled KEYWORD2 +getIRx1 KEYWORD2 +getIRy1 KEYWORD2 +getIRs1 KEYWORD2 +getIRx2 KEYWORD2 +getIRy2 KEYWORD2 +getIRs2 KEYWORD2 +getIRx3 KEYWORD2 +getIRy3 KEYWORD2 +getIRs3 KEYWORD2 +getIRx4 KEYWORD2 +getIRy4 KEYWORD2 +getIRs4 KEYWORD2 + +#################################################### +# Syntax Coloring Map For BTHID Library +#################################################### + +#################################################### +# Datatypes (KEYWORD1) +#################################################### + +BTHID KEYWORD1 + +#################################################### +# Methods and Functions (KEYWORD2) +#################################################### +SetReportParser KEYWORD2 +setProtocolMode KEYWORD2 + +#################################################### +# Syntax Coloring Map For PS Buzz Library +#################################################### + +#################################################### +# Datatypes (KEYWORD1) +#################################################### + +PSBuzz KEYWORD1 + +#################################################### +# Methods and Functions (KEYWORD2) +#################################################### + +setLedOnAll KEYWORD2 +setLedOffAll KEYWORD2 + +#################################################### +# Constants and enums (LITERAL1) +#################################################### + +RED LITERAL1 +YELLOW LITERAL1 +GREEN LITERAL1 +ORANGE LITERAL1 +BLUE LITERAL1 diff --git a/lib/usbhost/USB_Host_Shield_2.0/library.json b/lib/usbhost/USB_Host_Shield_2.0/library.json new file mode 100644 index 0000000000..1d649b1e13 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/library.json @@ -0,0 +1,47 @@ +{ + "name": "USB-Host-Shield-20", + "keywords": "usb, host, ftdi, adk, acm, pl2303, hid, bluetooth, spp, ps3, ps4, buzz, xbox, wii, mass storage", + "description": "Revision 2.0 of MAX3421E-based USB Host Shield Library", + "authors": + [ + { + "name": "Oleg Mazurov", + "email": "mazurov@circuitsathome.com", + "url": "http://www.circuitsathome.com", + "maintainer": true + }, + { + "name": "Alexei Glushchenko", + "email": "alex-gl@mail.ru" + }, + { + "name": "Kristian Lauszus", + "email": "kristianl@tkjelectronics.com", + "url": "http://tkjelectronics.com", + "maintainer": true + }, + { + "name": "Andrew Kroll", + "email": "xxxajk@gmail.com", + "maintainer": true + } + ], + "repository": + { + "type": "git", + "url": "https://github.com/felis/USB_Host_Shield_2.0.git" + }, + "examples": + [ + "examples/*/*.ino", + "examples/*/*/*.ino" + ], + "frameworks": "arduino", + "platforms": + [ + "atmelavr", + "teensy", + "atmelsam", + "nordicnrf51" + ] +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/library.properties b/lib/usbhost/USB_Host_Shield_2.0/library.properties new file mode 100644 index 0000000000..7881b05e9d --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/library.properties @@ -0,0 +1,9 @@ +name=USB Host Shield Library 2.0 +version=1.1.0 +author=Oleg Mazurov (Circuits@Home) , Kristian Lauszus (TKJ Electronics) , Andrew Kroll , Alexei Glushchenko (Circuits@Home) +maintainer=Oleg Mazurov (Circuits@Home) , Kristian Lauszus (TKJ Electronics) , Andrew Kroll +sentence=Revision 2.0 of MAX3421E-based USB Host Shield Library. +paragraph=Supports HID devices, FTDI, ADK, ACM, PL2303, Bluetooth HID devices, SPP communication and mass storage devices. Furthermore it supports PS3, PS4, PS Buzz, Wii and Xbox controllers. +category=Other +url=https://github.com/felis/USB_Host_Shield_2.0 +architectures=* \ No newline at end of file diff --git a/lib/usbhost/USB_Host_Shield_2.0/macros.h b/lib/usbhost/USB_Host_Shield_2.0/macros.h new file mode 100644 index 0000000000..e14a711fab --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/macros.h @@ -0,0 +1,82 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ + +#if !defined(_usb_h_) || defined(MACROS_H) +#error "Never include macros.h directly; include Usb.h instead" +#else +#define MACROS_H + +//////////////////////////////////////////////////////////////////////////////// +// HANDY MACROS +//////////////////////////////////////////////////////////////////////////////// + +#define VALUE_BETWEEN(v,l,h) (((v)>(l)) && ((v)<(h))) +#define VALUE_WITHIN(v,l,h) (((v)>=(l)) && ((v)<=(h))) +#define output_pgm_message(wa,fp,mp,el) wa = &mp, fp((char *)pgm_read_pointer(wa), el) +#define output_if_between(v,l,h,wa,fp,mp,el) if(VALUE_BETWEEN(v,l,h)) output_pgm_message(wa,fp,mp[v-(l+1)],el); + +#define SWAP(a, b) (((a) ^= (b)), ((b) ^= (a)), ((a) ^= (b))) +#ifndef __BYTE_GRABBING_DEFINED__ +#define __BYTE_GRABBING_DEFINED__ 1 +#ifdef BROKEN_OPTIMIZER_LITTLE_ENDIAN +// Note: Use this if your compiler generates horrible assembler! +#define BGRAB0(__usi__) (((uint8_t *)&(__usi__))[0]) +#define BGRAB1(__usi__) (((uint8_t *)&(__usi__))[1]) +#define BGRAB2(__usi__) (((uint8_t *)&(__usi__))[2]) +#define BGRAB3(__usi__) (((uint8_t *)&(__usi__))[3]) +#define BGRAB4(__usi__) (((uint8_t *)&(__usi__))[4]) +#define BGRAB5(__usi__) (((uint8_t *)&(__usi__))[5]) +#define BGRAB6(__usi__) (((uint8_t *)&(__usi__))[6]) +#define BGRAB7(__usi__) (((uint8_t *)&(__usi__))[7]) +#else +// Note: The cast alone to uint8_t is actually enough. +// GCC throws out the "& 0xff", and the size is no different. +// Some compilers need it. +#define BGRAB0(__usi__) ((uint8_t)((__usi__) & 0xff )) +#define BGRAB1(__usi__) ((uint8_t)(((__usi__) >> 8) & 0xff)) +#define BGRAB2(__usi__) ((uint8_t)(((__usi__) >> 16) & 0xff)) +#define BGRAB3(__usi__) ((uint8_t)(((__usi__) >> 24) & 0xff)) +#define BGRAB4(__usi__) ((uint8_t)(((__usi__) >> 32) & 0xff)) +#define BGRAB5(__usi__) ((uint8_t)(((__usi__) >> 40) & 0xff)) +#define BGRAB6(__usi__) ((uint8_t)(((__usi__) >> 48) & 0xff)) +#define BGRAB7(__usi__) ((uint8_t)(((__usi__) >> 56) & 0xff)) +#endif +#define BOVER1(__usi__) ((uint16_t)(__usi__) << 8) +#define BOVER2(__usi__) ((uint32_t)(__usi__) << 16) +#define BOVER3(__usi__) ((uint32_t)(__usi__) << 24) +#define BOVER4(__usi__) ((uint64_t)(__usi__) << 32) +#define BOVER5(__usi__) ((uint64_t)(__usi__) << 40) +#define BOVER6(__usi__) ((uint64_t)(__usi__) << 48) +#define BOVER7(__usi__) ((uint64_t)(__usi__) << 56) + +// These are the smallest and fastest ways I have found so far in pure C/C++. +#define BMAKE16(__usc1__,__usc0__) ((uint16_t)((uint16_t)(__usc0__) | (uint16_t)BOVER1(__usc1__))) +#define BMAKE32(__usc3__,__usc2__,__usc1__,__usc0__) ((uint32_t)((uint32_t)(__usc0__) | (uint32_t)BOVER1(__usc1__) | (uint32_t)BOVER2(__usc2__) | (uint32_t)BOVER3(__usc3__))) +#define BMAKE64(__usc7__,__usc6__,__usc5__,__usc4__,__usc3__,__usc2__,__usc1__,__usc0__) ((uint64_t)((uint64_t)__usc0__ | (uint64_t)BOVER1(__usc1__) | (uint64_t)BOVER2(__usc2__) | (uint64_t)BOVER3(__usc3__) | (uint64_t)BOVER4(__usc4__) | (uint64_t)BOVER5(__usc5__) | (uint64_t)BOVER6(__usc6__) | (uint64_t)BOVER1(__usc7__))) +#endif + +/* + * Debug macros: Strings are stored in progmem (flash) instead of RAM. + */ +#define USBTRACE(s) (Notify(PSTR(s), 0x80)) +#define USBTRACE1(s,l) (Notify(PSTR(s), l)) +#define USBTRACE2(s,r) (Notify(PSTR(s), 0x80), D_PrintHex((r), 0x80), Notify(PSTR("\r\n"), 0x80)) +#define USBTRACE3(s,r,l) (Notify(PSTR(s), l), D_PrintHex((r), l), Notify(PSTR("\r\n"), l)) + + +#endif /* MACROS_H */ + diff --git a/lib/usbhost/USB_Host_Shield_2.0/masstorage.cpp b/lib/usbhost/USB_Host_Shield_2.0/masstorage.cpp new file mode 100644 index 0000000000..9299f71a43 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/masstorage.cpp @@ -0,0 +1,1266 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ + +#include "masstorage.h" + +const uint8_t BulkOnly::epDataInIndex = 1; +const uint8_t BulkOnly::epDataOutIndex = 2; +const uint8_t BulkOnly::epInterruptInIndex = 3; + +//////////////////////////////////////////////////////////////////////////////// + +// Interface code + +//////////////////////////////////////////////////////////////////////////////// + +/** + * Get the capacity of the media + * + * @param lun Logical Unit Number + * @return media capacity + */ +uint32_t BulkOnly::GetCapacity(uint8_t lun) { + if(LUNOk[lun]) + return CurrentCapacity[lun]; + return 0LU; +} + +/** + * Get the sector (block) size used on the media + * + * @param lun Logical Unit Number + * @return media sector size + */ +uint16_t BulkOnly::GetSectorSize(uint8_t lun) { + if(LUNOk[lun]) + return CurrentSectorSize[lun]; + return 0U; +} + +/** + * Test if LUN is ready for use + * + * @param lun Logical Unit Number + * @return true if LUN is ready for use + */ +bool BulkOnly::LUNIsGood(uint8_t lun) { + return LUNOk[lun]; +} + +/** + * Test if LUN is write protected + * + * @param lun Logical Unit Number + * @return cached status of write protect switch + */ +bool BulkOnly::WriteProtected(uint8_t lun) { + return WriteOk[lun]; +} + +/** + * Wrap and execute a SCSI CDB with length of 6 + * + * @param cdb CDB to execute + * @param buf_size Size of expected transaction + * @param buf Buffer + * @param dir MASS_CMD_DIR_IN | MASS_CMD_DIR_OUT + * @return + */ +uint8_t BulkOnly::SCSITransaction6(CDB6_t *cdb, uint16_t buf_size, void *buf, uint8_t dir) { + // promote buf_size to 32bits. + CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)buf_size, cdb, dir); + //SetCurLUN(cdb->LUN); + return (HandleSCSIError(Transaction(&cbw, buf_size, buf))); +} + +/** + * Wrap and execute a SCSI CDB with length of 10 + * + * @param cdb CDB to execute + * @param buf_size Size of expected transaction + * @param buf Buffer + * @param dir MASS_CMD_DIR_IN | MASS_CMD_DIR_OUT + * @return + */ +uint8_t BulkOnly::SCSITransaction10(CDB10_t *cdb, uint16_t buf_size, void *buf, uint8_t dir) { + // promote buf_size to 32bits. + CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)buf_size, cdb, dir); + //SetCurLUN(cdb->LUN); + return (HandleSCSIError(Transaction(&cbw, buf_size, buf))); +} + +/** + * Lock or Unlock the tray or door on device. + * Caution: Some devices with buggy firmware will lock up. + * + * @param lun Logical Unit Number + * @param lock 1 to lock, 0 to unlock + * @return + */ +uint8_t BulkOnly::LockMedia(uint8_t lun, uint8_t lock) { + Notify(PSTR("\r\nLockMedia\r\n"), 0x80); + Notify(PSTR("---------\r\n"), 0x80); + + CDB6_t cdb = CDB6_t(SCSI_CMD_PREVENT_REMOVAL, lun, (uint8_t)0, lock); + return SCSITransaction6(&cdb, (uint16_t)0, NULL, (uint8_t)MASS_CMD_DIR_IN); +} + +/** + * Media control, for spindle motor and media tray or door. + * This includes CDROM, TAPE and anything with a media loader. + * + * @param lun Logical Unit Number + * @param ctl 0x00 Stop Motor, 0x01 Start Motor, 0x02 Eject Media, 0x03 Load Media + * @return 0 on success + */ +uint8_t BulkOnly::MediaCTL(uint8_t lun, uint8_t ctl) { + Notify(PSTR("\r\nMediaCTL\r\n"), 0x80); + Notify(PSTR("-----------------\r\n"), 0x80); + + uint8_t rcode = MASS_ERR_UNIT_NOT_READY; + if(bAddress) { + CDB6_t cdb = CDB6_t(SCSI_CMD_START_STOP_UNIT, lun, ctl & 0x03, 0); + rcode = SCSITransaction6(&cdb, (uint16_t)0, NULL, (uint8_t)MASS_CMD_DIR_OUT); + } else { + SetCurLUN(lun); + } + return rcode; +} + +/** + * Read data from media + * + * @param lun Logical Unit Number + * @param addr LBA address on media to read + * @param bsize size of a block (we should probably use the cached size) + * @param blocks how many blocks to read + * @param buf memory that is able to hold the requested data + * @return 0 on success + */ +uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf) { + if(!LUNOk[lun]) return MASS_ERR_NO_MEDIA; + Notify(PSTR("\r\nRead LUN:\t"), 0x80); + D_PrintHex (lun, 0x90); + Notify(PSTR("\r\nLBA:\t\t"), 0x90); + D_PrintHex (addr, 0x90); + Notify(PSTR("\r\nblocks:\t\t"), 0x90); + D_PrintHex (blocks, 0x90); + Notify(PSTR("\r\nblock size:\t"), 0x90); + D_PrintHex (bsize, 0x90); + Notify(PSTR("\r\n---------\r\n"), 0x80); + CDB10_t cdb = CDB10_t(SCSI_CMD_READ_10, lun, blocks, addr); + +again: + uint8_t er = SCSITransaction10(&cdb, ((uint16_t)bsize * blocks), buf, (uint8_t)MASS_CMD_DIR_IN); + + if(er == MASS_ERR_STALL) { + MediaCTL(lun, 1); + delay(150); + if(!TestUnitReady(lun)) goto again; + } + return er; +} + +/** + * Write data to media + * + * @param lun Logical Unit Number + * @param addr LBA address on media to write + * @param bsize size of a block (we should probably use the cached size) + * @param blocks how many blocks to write + * @param buf memory that contains the data to write + * @return 0 on success + */ +uint8_t BulkOnly::Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t * buf) { + if(!LUNOk[lun]) return MASS_ERR_NO_MEDIA; + if(!WriteOk[lun]) return MASS_ERR_WRITE_PROTECTED; + Notify(PSTR("\r\nWrite LUN:\t"), 0x80); + D_PrintHex (lun, 0x90); + Notify(PSTR("\r\nLBA:\t\t"), 0x90); + D_PrintHex (addr, 0x90); + Notify(PSTR("\r\nblocks:\t\t"), 0x90); + D_PrintHex (blocks, 0x90); + Notify(PSTR("\r\nblock size:\t"), 0x90); + D_PrintHex (bsize, 0x90); + Notify(PSTR("\r\n---------\r\n"), 0x80); + CDB10_t cdb = CDB10_t(SCSI_CMD_WRITE_10, lun, blocks, addr); + +again: + uint8_t er = SCSITransaction10(&cdb, ((uint16_t)bsize * blocks), (void*)buf, (uint8_t)MASS_CMD_DIR_OUT); + + if(er == MASS_ERR_WRITE_STALL) { + MediaCTL(lun, 1); + delay(150); + if(!TestUnitReady(lun)) goto again; + } + return er; +} + +// End of user functions, the remaining code below is driver internals. +// Only developer serviceable parts below! + +//////////////////////////////////////////////////////////////////////////////// + +// Main driver code + +//////////////////////////////////////////////////////////////////////////////// + +BulkOnly::BulkOnly(USB *p) : +pUsb(p), +bAddress(0), +bIface(0), +bNumEP(1), +qNextPollTime(0), +bPollEnable(false), +//dCBWTag(0), +bLastUsbError(0) { + ClearAllEP(); + dCBWTag = 0; + if(pUsb) + pUsb->RegisterDeviceClass(this); +} + +/** + * USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET == success + * We need to standardize either the rcode, or change the API to return values + * so a signal that additional actions are required can be produced. + * Some of these codes do exist already. + * + * TECHNICAL: We could do most of this code elsewhere, with the exception of checking the class instance. + * Doing so would save some program memory when using multiple drivers. + * + * @param parent USB address of parent + * @param port address of port on parent + * @param lowspeed true if device is low speed + * @return + */ +uint8_t BulkOnly::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) { + + const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR); + + uint8_t buf[constBufSize]; + USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + USBTRACE("MS ConfigureDevice\r\n"); + ClearAllEP(); + AddressPool &addrPool = pUsb->GetAddressPool(); + + + if(bAddress) + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; + + // + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); + if(!p) { + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + } + + if(!p->epinfo) { + USBTRACE("epinfo\r\n"); + return USB_ERROR_EPINFO_IS_NULL; + } + + // Save old pointer to EP_RECORD of address 0 + oldep_ptr = p->epinfo; + + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence + p->epinfo = epInfo; + + p->lowspeed = lowspeed; + // Get device descriptor + rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf); + + // Restore p->epinfo + p->epinfo = oldep_ptr; + + if(rcode) { + goto FailGetDevDescr; + } + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, false, port); + + if(!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + // Extract Max Packet Size from the device descriptor + epInfo[0].maxPktSize = udd->bMaxPacketSize0; + // Steal and abuse from epInfo structure to save on memory. + epInfo[1].epAddr = udd->bNumConfigurations; + // + return USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET; + +FailGetDevDescr: +#ifdef DEBUG_USB_HOST + NotifyFailGetDevDescr(rcode); +#endif + rcode = USB_ERROR_FailGetDevDescr; + + Release(); + return rcode; +}; + +/** + * + * @param parent (not used) + * @param port (not used) + * @param lowspeed true if device is low speed + * @return 0 for success + */ +uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) { + uint8_t rcode; + uint8_t num_of_conf = epInfo[1].epAddr; // number of configurations + epInfo[1].epAddr = 0; + USBTRACE("MS Init\r\n"); + + AddressPool &addrPool = pUsb->GetAddressPool(); + UsbDevice *p = addrPool.GetUsbDevicePtr(bAddress); + + if(!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + // Assign new address to the device + delay(2000); + rcode = pUsb->setAddr(0, 0, bAddress); + + if(rcode) { + p->lowspeed = false; + addrPool.FreeAddress(bAddress); + bAddress = 0; + USBTRACE2("setAddr:", rcode); + return rcode; + } + + USBTRACE2("Addr:", bAddress); + + p->lowspeed = false; + + p = addrPool.GetUsbDevicePtr(bAddress); + + if(!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->lowspeed = lowspeed; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); + + if(rcode) + goto FailSetDevTblEntry; + + USBTRACE2("NC:", num_of_conf); + + for(uint8_t i = 0; i < num_of_conf; i++) { + ConfigDescParser< USB_CLASS_MASS_STORAGE, + MASS_SUBCLASS_SCSI, + MASS_PROTO_BBB, + CP_MASK_COMPARE_CLASS | + CP_MASK_COMPARE_SUBCLASS | + CP_MASK_COMPARE_PROTOCOL > BulkOnlyParser(this); + + rcode = pUsb->getConfDescr(bAddress, 0, i, &BulkOnlyParser); + + if(rcode) + goto FailGetConfDescr; + + if(bNumEP > 1) + break; + } + + if(bNumEP < 3) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + // Assign epInfo to epinfo pointer + pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); + + USBTRACE2("Conf:", bConfNum); + + // Set Configuration Value + rcode = pUsb->setConf(bAddress, 0, bConfNum); + + if(rcode) + goto FailSetConfDescr; + + //Linux does a 1sec delay after this. + delay(1000); + + rcode = GetMaxLUN(&bMaxLUN); + if(rcode) + goto FailGetMaxLUN; + + if(bMaxLUN >= MASS_MAX_SUPPORTED_LUN) bMaxLUN = MASS_MAX_SUPPORTED_LUN - 1; + ErrorMessage (PSTR("MaxLUN"), bMaxLUN); + + delay(1000); // Delay a bit for slow firmware. + + for(uint8_t lun = 0; lun <= bMaxLUN; lun++) { + InquiryResponse response; + rcode = Inquiry(lun, sizeof (InquiryResponse), (uint8_t*) & response); + if(rcode) { + ErrorMessage (PSTR("Inquiry"), rcode); + } else { +#if 0 + printf("LUN %i `", lun); + uint8_t *buf = response.VendorID; + for(int i = 0; i < 28; i++) printf("%c", buf[i]); + printf("'\r\nQualifier %1.1X ", response.PeripheralQualifier); + printf("Device type %2.2X ", response.DeviceType); + printf("RMB %1.1X ", response.Removable); + printf("SSCS %1.1X ", response.SCCS); + uint8_t sv = response.Version; + printf("SCSI version %2.2X\r\nDevice conforms to ", sv); + switch(sv) { + case 0: + printf("No specific"); + break; + case 1: + printf("ANSI X3.131-1986 (ANSI 1)"); + break; + case 2: + printf("ANSI X3.131-1994 (ANSI 2)"); + break; + case 3: + printf("ANSI INCITS 301-1997 (SPC)"); + break; + case 4: + printf("ANSI INCITS 351-2001 (SPC-2)"); + break; + case 5: + printf("ANSI INCITS 408-2005 (SPC-4)"); + break; + case 6: + printf("T10/1731-D (SPC-4)"); + break; + default: + printf("unknown"); + } + printf(" standards.\r\n"); +#endif + uint8_t tries = 0xf0; + while((rcode = TestUnitReady(lun))) { + if(rcode == 0x08) break; // break on no media, this is OK to do. + // try to lock media and spin up + if(tries < 14) { + LockMedia(lun, 1); + MediaCTL(lun, 1); // I actually have a USB stick that needs this! + } else delay(2 * (tries + 1)); + tries++; + if(!tries) break; + } + if(!rcode) { + delay(1000); + LUNOk[lun] = CheckLUN(lun); + if(!LUNOk[lun]) LUNOk[lun] = CheckLUN(lun); + } + } + } + + + CheckMedia(); + + rcode = OnInit(); + + if(rcode) + goto FailOnInit; + +#ifdef DEBUG_USB_HOST + USBTRACE("MS configured\r\n\r\n"); +#endif + + bPollEnable = true; + + //USBTRACE("Poll enabled\r\n"); + return 0; + +FailSetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailSetConfDescr(); + goto Fail; +#endif + +FailOnInit: +#ifdef DEBUG_USB_HOST + USBTRACE("OnInit:"); + goto Fail; +#endif + +FailGetMaxLUN: +#ifdef DEBUG_USB_HOST + USBTRACE("GetMaxLUN:"); + goto Fail; +#endif + + //#ifdef DEBUG_USB_HOST + //FailInvalidSectorSize: + // USBTRACE("Sector Size is NOT VALID: "); + // goto Fail; + //#endif + +FailSetDevTblEntry: +#ifdef DEBUG_USB_HOST + NotifyFailSetDevTblEntry(); + goto Fail; +#endif + +FailGetConfDescr: +#ifdef DEBUG_USB_HOST + NotifyFailGetConfDescr(); +#endif + +#ifdef DEBUG_USB_HOST +Fail: + NotifyFail(rcode); +#endif + Release(); + return rcode; +} + +/** + * For driver use only. + * + * @param conf + * @param iface + * @param alt + * @param proto + * @param pep + */ +void BulkOnly::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR * pep) { + ErrorMessage (PSTR("Conf.Val"), conf); + ErrorMessage (PSTR("Iface Num"), iface); + ErrorMessage (PSTR("Alt.Set"), alt); + + bConfNum = conf; + + uint8_t index; + +#if 1 + if((pep->bmAttributes & 0x02) == 2) { + index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex; + // Fill in the endpoint info structure + epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); + epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; + epInfo[index].epAttribs = 0; + + bNumEP++; + + PrintEndpointDescriptor(pep); + + } +#else + if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) + index = epInterruptInIndex; + else + if((pep->bmAttributes & 0x02) == 2) + index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex; + else + return; + + // Fill in the endpoint info structure + epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); + epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; + epInfo[index].epAttribs = 0; + + bNumEP++; + + PrintEndpointDescriptor(pep); +#endif +} + +/** + * For driver use only. + * + * @return + */ +uint8_t BulkOnly::Release() { + ClearAllEP(); + pUsb->GetAddressPool().FreeAddress(bAddress); + return 0; +} + +/** + * For driver use only. + * + * @param lun Logical Unit Number + * @return true if LUN is ready for use. + */ +bool BulkOnly::CheckLUN(uint8_t lun) { + uint8_t rcode; + Capacity capacity; + for(uint8_t i = 0; i < 8; i++) capacity.data[i] = 0; + + rcode = ReadCapacity10(lun, (uint8_t*)capacity.data); + if(rcode) { + //printf(">>>>>>>>>>>>>>>>ReadCapacity returned %i\r\n", rcode); + return false; + } + ErrorMessage (PSTR(">>>>>>>>>>>>>>>>CAPACITY OK ON LUN"), lun); + for(uint8_t i = 0; i < 8 /*sizeof (Capacity)*/; i++) + D_PrintHex (capacity.data[i], 0x80); + Notify(PSTR("\r\n\r\n"), 0x80); + // Only 512/1024/2048/4096 are valid values! + uint32_t c = BMAKE32(capacity.data[4], capacity.data[5], capacity.data[6], capacity.data[7]); + if(c != 0x0200LU && c != 0x0400LU && c != 0x0800LU && c != 0x1000LU) { + return false; + } + // Store capacity information. + CurrentSectorSize[lun] = (uint16_t)(c); // & 0xFFFF); + + CurrentCapacity[lun] = BMAKE32(capacity.data[0], capacity.data[1], capacity.data[2], capacity.data[3]) + 1; + if(CurrentCapacity[lun] == /*0xffffffffLU */ 0x01LU || CurrentCapacity[lun] == 0x00LU) { + // Buggy firmware will report 0xffffffff or 0 for no media + if(CurrentCapacity[lun]) + ErrorMessage (PSTR(">>>>>>>>>>>>>>>>BUGGY FIRMWARE. CAPACITY FAIL ON LUN"), lun); + return false; + } + delay(20); + Page3F(lun); + if(!TestUnitReady(lun)) return true; + return false; +} + +/** + * For driver use only. + * + * Scan for media change on all LUNs + */ +void BulkOnly::CheckMedia() { + for(uint8_t lun = 0; lun <= bMaxLUN; lun++) { + if(TestUnitReady(lun)) { + LUNOk[lun] = false; + continue; + } + if(!LUNOk[lun]) + LUNOk[lun] = CheckLUN(lun); + } +#if 0 + printf("}}}}}}}}}}}}}}}}STATUS "); + for(uint8_t lun = 0; lun <= bMaxLUN; lun++) { + if(LUNOk[lun]) + printf("#"); + else printf("."); + } + printf("\r\n"); +#endif + qNextPollTime = millis() + 2000; +} + +/** + * For driver use only. + * + * @return + */ +uint8_t BulkOnly::Poll() { + //uint8_t rcode = 0; + + if(!bPollEnable) + return 0; + + if((long)(millis() - qNextPollTime) >= 0L) { + CheckMedia(); + } + //rcode = 0; + + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// + + +// SCSI code + + +//////////////////////////////////////////////////////////////////////////////// + +/** + * For driver use only. + * + * @param plun + * @return + */ +uint8_t BulkOnly::GetMaxLUN(uint8_t *plun) { + uint8_t ret = pUsb->ctrlReq(bAddress, 0, bmREQ_MASSIN, MASS_REQ_GET_MAX_LUN, 0, 0, bIface, 1, 1, plun, NULL); + + if(ret == hrSTALL) + *plun = 0; + + return 0; +} + +/** + * For driver use only. Used during Driver Init + * + * @param lun Logical Unit Number + * @param bsize + * @param buf + * @return + */ +uint8_t BulkOnly::Inquiry(uint8_t lun, uint16_t bsize, uint8_t *buf) { + Notify(PSTR("\r\nInquiry\r\n"), 0x80); + Notify(PSTR("---------\r\n"), 0x80); + + CDB6_t cdb = CDB6_t(SCSI_CMD_INQUIRY, lun, 0LU, (uint8_t)bsize, 0); + uint8_t rc = SCSITransaction6(&cdb, bsize, buf, (uint8_t)MASS_CMD_DIR_IN); + + return rc; +} + +/** + * For driver use only. + * + * @param lun Logical Unit Number + * @return + */ +uint8_t BulkOnly::TestUnitReady(uint8_t lun) { + //SetCurLUN(lun); + if(!bAddress) + return MASS_ERR_UNIT_NOT_READY; + + Notify(PSTR("\r\nTestUnitReady\r\n"), 0x80); + Notify(PSTR("-----------------\r\n"), 0x80); + + CDB6_t cdb = CDB6_t(SCSI_CMD_TEST_UNIT_READY, lun, (uint8_t)0, 0); + return SCSITransaction6(&cdb, 0, NULL, (uint8_t)MASS_CMD_DIR_IN); + +} + +/** + * For driver use only. + * + * @param lun Logical Unit Number + * @param pc + * @param page + * @param subpage + * @param len + * @param pbuf + * @return + */ +uint8_t BulkOnly::ModeSense6(uint8_t lun, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t len, uint8_t * pbuf) { + Notify(PSTR("\r\rModeSense\r\n"), 0x80); + Notify(PSTR("------------\r\n"), 0x80); + + CDB6_t cdb = CDB6_t(SCSI_CMD_TEST_UNIT_READY, lun, (uint32_t)((((pc << 6) | page) << 8) | subpage), len, 0); + return SCSITransaction6(&cdb, len, pbuf, (uint8_t)MASS_CMD_DIR_IN); +} + +/** + * For driver use only. + * + * @param lun Logical Unit Number + * @param bsize + * @param buf + * @return + */ +uint8_t BulkOnly::ReadCapacity10(uint8_t lun, uint8_t *buf) { + Notify(PSTR("\r\nReadCapacity\r\n"), 0x80); + Notify(PSTR("---------------\r\n"), 0x80); + + CDB10_t cdb = CDB10_t(SCSI_CMD_READ_CAPACITY_10, lun); + return SCSITransaction10(&cdb, 8, buf, (uint8_t)MASS_CMD_DIR_IN); +} + +/** + * For driver use only. + * + * Page 3F contains write protect status. + * + * @param lun Logical Unit Number to test. + * @return Write protect switch status. + */ +uint8_t BulkOnly::Page3F(uint8_t lun) { + uint8_t buf[192]; + for(int i = 0; i < 192; i++) { + buf[i] = 0x00; + } + WriteOk[lun] = true; + uint8_t rc = ModeSense6(lun, 0, 0x3f, 0, 192, buf); + if(!rc) { + WriteOk[lun] = ((buf[2] & 0x80) == 0); + Notify(PSTR("Mode Sense: "), 0x80); + for(int i = 0; i < 4; i++) { + D_PrintHex (buf[i], 0x80); + Notify(PSTR(" "), 0x80); + } + Notify(PSTR("\r\n"), 0x80); + } + return rc; +} + +/** + * For driver use only. + * + * @param lun Logical Unit Number + * @param size + * @param buf + * @return + */ +uint8_t BulkOnly::RequestSense(uint8_t lun, uint16_t size, uint8_t *buf) { + Notify(PSTR("\r\nRequestSense\r\n"), 0x80); + Notify(PSTR("----------------\r\n"), 0x80); + + CDB6_t cdb = CDB6_t(SCSI_CMD_REQUEST_SENSE, lun, 0LU, (uint8_t)size, 0); + CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)size, &cdb, (uint8_t)MASS_CMD_DIR_IN); + //SetCurLUN(lun); + return Transaction(&cbw, size, buf); +} + + +//////////////////////////////////////////////////////////////////////////////// + + +// USB code + + +//////////////////////////////////////////////////////////////////////////////// + +/** + * For driver use only. + * + * @param index + * @return + */ +uint8_t BulkOnly::ClearEpHalt(uint8_t index) { + if(index == 0) + return 0; + + uint8_t ret = 0; + + while((ret = (pUsb->ctrlReq(bAddress, 0, USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT, USB_REQUEST_CLEAR_FEATURE, USB_FEATURE_ENDPOINT_HALT, 0, ((index == epDataInIndex) ? (0x80 | epInfo[index].epAddr) : epInfo[index].epAddr), 0, 0, NULL, NULL)) == 0x01)) + delay(6); + + if(ret) { + ErrorMessage (PSTR("ClearEpHalt"), ret); + ErrorMessage (PSTR("EP"), ((index == epDataInIndex) ? (0x80 | epInfo[index].epAddr) : epInfo[index].epAddr)); + return ret; + } + epInfo[index].bmSndToggle = 0; + epInfo[index].bmRcvToggle = 0; + // epAttribs = 0; + return 0; +} + +/** + * For driver use only. + * + */ +void BulkOnly::Reset() { + while(pUsb->ctrlReq(bAddress, 0, bmREQ_MASSOUT, MASS_REQ_BOMSR, 0, 0, bIface, 0, 0, NULL, NULL) == 0x01) delay(6); +} + +/** + * For driver use only. + * + * @return 0 if successful + */ +uint8_t BulkOnly::ResetRecovery() { + Notify(PSTR("\r\nResetRecovery\r\n"), 0x80); + Notify(PSTR("-----------------\r\n"), 0x80); + + delay(6); + Reset(); + delay(6); + ClearEpHalt(epDataInIndex); + delay(6); + bLastUsbError = ClearEpHalt(epDataOutIndex); + delay(6); + return bLastUsbError; +} + +/** + * For driver use only. + * + * Clear all EP data and clear all LUN status + */ +void BulkOnly::ClearAllEP() { + for(uint8_t i = 0; i < MASS_MAX_ENDPOINTS; i++) { + epInfo[i].epAddr = 0; + epInfo[i].maxPktSize = (i) ? 0 : 8; + epInfo[i].epAttribs = 0; + + epInfo[i].bmNakPower = USB_NAK_DEFAULT; + } + + for(uint8_t i = 0; i < MASS_MAX_SUPPORTED_LUN; i++) { + LUNOk[i] = false; + WriteOk[i] = false; + CurrentCapacity[i] = 0lu; + CurrentSectorSize[i] = 0; + } + + bIface = 0; + bNumEP = 1; + bAddress = 0; + qNextPollTime = 0; + bPollEnable = false; + bLastUsbError = 0; + bMaxLUN = 0; + bTheLUN = 0; +} + +/** + * For driver use only. + * + * @param pcsw + * @param pcbw + * @return + */ +bool BulkOnly::IsValidCSW(CommandStatusWrapper *pcsw, CommandBlockWrapperBase *pcbw) { + if(pcsw->dCSWSignature != MASS_CSW_SIGNATURE) { + Notify(PSTR("CSW:Sig error\r\n"), 0x80); + return false; + } + if(pcsw->dCSWTag != pcbw->dCBWTag) { + Notify(PSTR("CSW:Wrong tag\r\n"), 0x80); + return false; + } + return true; +} + +/** + * For driver use only. + * + * @param error + * @param index + * @return + */ +uint8_t BulkOnly::HandleUsbError(uint8_t error, uint8_t index) { + uint8_t count = 3; + + bLastUsbError = error; + //if (error) + //ClearEpHalt(index); + while(error && count) { + if(error != hrSUCCESS) { + ErrorMessage (PSTR("USB Error"), error); + ErrorMessage (PSTR("Index"), index); + } + switch(error) { + // case hrWRONGPID: + case hrSUCCESS: + return MASS_ERR_SUCCESS; + case hrBUSY: + // SIE is busy, just hang out and try again. + return MASS_ERR_UNIT_BUSY; + case hrTIMEOUT: + case hrJERR: return MASS_ERR_DEVICE_DISCONNECTED; + case hrSTALL: + if(index == 0) + return MASS_ERR_STALL; + ClearEpHalt(index); + if(index != epDataInIndex) + return MASS_ERR_WRITE_STALL; + return MASS_ERR_STALL; + + case hrNAK: + if(index == 0) + return MASS_ERR_UNIT_BUSY; + return MASS_ERR_UNIT_BUSY; + + case hrTOGERR: + // Handle a very super rare corner case, where toggles become de-synched. + // I have only ran into one device that has this firmware bug, and this is + // the only clean way to get back into sync with the buggy device firmware. + // --AJK + if(bAddress && bConfNum) { + error = pUsb->setConf(bAddress, 0, bConfNum); + + if(error) + break; + } + return MASS_ERR_SUCCESS; + default: + ErrorMessage (PSTR("\r\nUSB"), error); + return MASS_ERR_GENERAL_USB_ERROR; + } + count--; + } // while + + return ((error && !count) ? MASS_ERR_GENERAL_USB_ERROR : MASS_ERR_SUCCESS); +} + +#if MS_WANT_PARSER + +uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf) { + return Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf, 0); +} +#endif + +/** + * For driver use only. + * + * @param pcbw + * @param buf_size + * @param buf + * @param flags + * @return + */ +uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf +#if MS_WANT_PARSER + , uint8_t flags +#endif + ) { + +#if MS_WANT_PARSER + uint16_t bytes = (pcbw->dCBWDataTransferLength > buf_size) ? buf_size : pcbw->dCBWDataTransferLength; + printf("Transfersize %i\r\n", bytes); + delay(1000); + + bool callback = (flags & MASS_TRANS_FLG_CALLBACK) == MASS_TRANS_FLG_CALLBACK; +#else + uint16_t bytes = buf_size; +#endif + bool write = (pcbw->bmCBWFlags & MASS_CMD_DIR_IN) != MASS_CMD_DIR_IN; + uint8_t ret = 0; + uint8_t usberr; + CommandStatusWrapper csw; // up here, we allocate ahead to save cpu cycles. + SetCurLUN(pcbw->bmCBWLUN); + ErrorMessage (PSTR("CBW.dCBWTag"), pcbw->dCBWTag); + + while((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw)) == hrBUSY) delay(1); + + ret = HandleUsbError(usberr, epDataOutIndex); + //ret = HandleUsbError(pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw), epDataOutIndex); + if(ret) { + ErrorMessage (PSTR("============================ CBW"), ret); + } else { + if(bytes) { + if(!write) { +#if MS_WANT_PARSER + if(callback) { + uint8_t rbuf[bytes]; + while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, rbuf)) == hrBUSY) delay(1); + if(usberr == hrSUCCESS) ((USBReadParser*)buf)->Parse(bytes, rbuf, 0); + } else { +#endif + while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*)buf)) == hrBUSY) delay(1); +#if MS_WANT_PARSER + + } +#endif + ret = HandleUsbError(usberr, epDataInIndex); + } else { + while((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, bytes, (uint8_t*)buf)) == hrBUSY) delay(1); + ret = HandleUsbError(usberr, epDataOutIndex); + } + if(ret) { + ErrorMessage (PSTR("============================ DAT"), ret); + } + } + } + + { + bytes = sizeof (CommandStatusWrapper); + int tries = 2; + while(tries--) { + while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*) & csw)) == hrBUSY) delay(1); + if(!usberr) break; + ClearEpHalt(epDataInIndex); + if(tries) ResetRecovery(); + } + if(!ret) { + Notify(PSTR("CBW:\t\tOK\r\n"), 0x80); + Notify(PSTR("Data Stage:\tOK\r\n"), 0x80); + } else { + // Throw away csw, IT IS NOT OF ANY USE. + ResetRecovery(); + return ret; + } + ret = HandleUsbError(usberr, epDataInIndex); + if(ret) { + ErrorMessage (PSTR("============================ CSW"), ret); + } + if(usberr == hrSUCCESS) { + if(IsValidCSW(&csw, pcbw)) { + //ErrorMessage (PSTR("CSW.dCBWTag"), csw.dCSWTag); + //ErrorMessage (PSTR("bCSWStatus"), csw.bCSWStatus); + //ErrorMessage (PSTR("dCSWDataResidue"), csw.dCSWDataResidue); + Notify(PSTR("CSW:\t\tOK\r\n\r\n"), 0x80); + return csw.bCSWStatus; + } else { + // NOTE! Sometimes this is caused by the reported residue being wrong. + // Get a different device. It isn't compliant, and should have never passed Q&A. + // I own one... 05e3:0701 Genesys Logic, Inc. USB 2.0 IDE Adapter. + // Other devices that exhibit this behavior exist in the wild too. + // Be sure to check quirks in the Linux source code before reporting a bug. --xxxajk + Notify(PSTR("Invalid CSW\r\n"), 0x80); + ResetRecovery(); + //return MASS_ERR_SUCCESS; + return MASS_ERR_INVALID_CSW; + } + } + } + return ret; +} + +/** + * For driver use only. + * + * @param lun Logical Unit Number + * @return + */ +uint8_t BulkOnly::SetCurLUN(uint8_t lun) { + if(lun > bMaxLUN) + return MASS_ERR_INVALID_LUN; + bTheLUN = lun; + return MASS_ERR_SUCCESS; +}; + +/** + * For driver use only. + * + * @param status + * @return + */ +uint8_t BulkOnly::HandleSCSIError(uint8_t status) { + uint8_t ret = 0; + + switch(status) { + case 0: return MASS_ERR_SUCCESS; + + case 2: + ErrorMessage (PSTR("Phase Error"), status); + ErrorMessage (PSTR("LUN"), bTheLUN); + ResetRecovery(); + return MASS_ERR_GENERAL_SCSI_ERROR; + + case 1: + ErrorMessage (PSTR("SCSI Error"), status); + ErrorMessage (PSTR("LUN"), bTheLUN); + RequestSenseResponce rsp; + + ret = RequestSense(bTheLUN, sizeof (RequestSenseResponce), (uint8_t*) & rsp); + + if(ret) { + return MASS_ERR_GENERAL_SCSI_ERROR; + } + ErrorMessage (PSTR("Response Code"), rsp.bResponseCode); + if(rsp.bResponseCode & 0x80) { + Notify(PSTR("Information field: "), 0x80); + for(int i = 0; i < 4; i++) { + D_PrintHex (rsp.CmdSpecificInformation[i], 0x80); + Notify(PSTR(" "), 0x80); + } + Notify(PSTR("\r\n"), 0x80); + } + ErrorMessage (PSTR("Sense Key"), rsp.bmSenseKey); + ErrorMessage (PSTR("Add Sense Code"), rsp.bAdditionalSenseCode); + ErrorMessage (PSTR("Add Sense Qual"), rsp.bAdditionalSenseQualifier); + // warning, this is not testing ASQ, only SK and ASC. + switch(rsp.bmSenseKey) { + case SCSI_S_UNIT_ATTENTION: + switch(rsp.bAdditionalSenseCode) { + case SCSI_ASC_MEDIA_CHANGED: + return MASS_ERR_MEDIA_CHANGED; + default: + return MASS_ERR_UNIT_NOT_READY; + } + case SCSI_S_NOT_READY: + switch(rsp.bAdditionalSenseCode) { + case SCSI_ASC_MEDIUM_NOT_PRESENT: + return MASS_ERR_NO_MEDIA; + default: + return MASS_ERR_UNIT_NOT_READY; + } + case SCSI_S_ILLEGAL_REQUEST: + switch(rsp.bAdditionalSenseCode) { + case SCSI_ASC_LBA_OUT_OF_RANGE: + return MASS_ERR_BAD_LBA; + default: + return MASS_ERR_CMD_NOT_SUPPORTED; + } + default: + return MASS_ERR_GENERAL_SCSI_ERROR; + } + + // case 4: return MASS_ERR_UNIT_BUSY; // Busy means retry later. + // case 0x05/0x14: we stalled out + // case 0x15/0x16: we naked out. + default: + ErrorMessage (PSTR("Gen SCSI Err"), status); + ErrorMessage (PSTR("LUN"), bTheLUN); + return status; + } // switch +} + + +//////////////////////////////////////////////////////////////////////////////// + + +// Debugging code + + +//////////////////////////////////////////////////////////////////////////////// + +/** + * + * @param ep_ptr + */ +void BulkOnly::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR * ep_ptr) { + Notify(PSTR("Endpoint descriptor:"), 0x80); + Notify(PSTR("\r\nLength:\t\t"), 0x80); + D_PrintHex (ep_ptr->bLength, 0x80); + Notify(PSTR("\r\nType:\t\t"), 0x80); + D_PrintHex (ep_ptr->bDescriptorType, 0x80); + Notify(PSTR("\r\nAddress:\t"), 0x80); + D_PrintHex (ep_ptr->bEndpointAddress, 0x80); + Notify(PSTR("\r\nAttributes:\t"), 0x80); + D_PrintHex (ep_ptr->bmAttributes, 0x80); + Notify(PSTR("\r\nMaxPktSize:\t"), 0x80); + D_PrintHex (ep_ptr->wMaxPacketSize, 0x80); + Notify(PSTR("\r\nPoll Intrv:\t"), 0x80); + D_PrintHex (ep_ptr->bInterval, 0x80); + Notify(PSTR("\r\n"), 0x80); +} + + +//////////////////////////////////////////////////////////////////////////////// + + +// misc/to kill/to-do + + +//////////////////////////////////////////////////////////////////////////////// + +/* We won't be needing this... */ +uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, USBReadParser * prs) { +#if MS_WANT_PARSER + if(!LUNOk[lun]) return MASS_ERR_NO_MEDIA; + Notify(PSTR("\r\nRead (With parser)\r\n"), 0x80); + Notify(PSTR("---------\r\n"), 0x80); + + CommandBlockWrapper cbw = CommandBlockWrapper(); + + cbw.dCBWSignature = MASS_CBW_SIGNATURE; + cbw.dCBWTag = ++dCBWTag; + cbw.dCBWDataTransferLength = ((uint32_t)bsize * blocks); + cbw.bmCBWFlags = MASS_CMD_DIR_IN, + cbw.bmCBWLUN = lun; + cbw.bmCBWCBLength = 10; + + cbw.CBWCB[0] = SCSI_CMD_READ_10; + cbw.CBWCB[8] = blocks; + cbw.CBWCB[2] = ((addr >> 24) & 0xff); + cbw.CBWCB[3] = ((addr >> 16) & 0xff); + cbw.CBWCB[4] = ((addr >> 8) & 0xff); + cbw.CBWCB[5] = (addr & 0xff); + + return HandleSCSIError(Transaction(&cbw, bsize, prs, 1)); +#else + return MASS_ERR_NOT_IMPLEMENTED; +#endif +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/masstorage.h b/lib/usbhost/USB_Host_Shield_2.0/masstorage.h new file mode 100644 index 0000000000..d39fd66f37 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/masstorage.h @@ -0,0 +1,571 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ + +#if !defined(__MASSTORAGE_H__) +#define __MASSTORAGE_H__ + +// Cruft removal, makes driver smaller, faster. +#ifndef MS_WANT_PARSER +#define MS_WANT_PARSER 0 +#endif + +#include "Usb.h" + +#define bmREQ_MASSOUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE +#define bmREQ_MASSIN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE + +// Mass Storage Subclass Constants +#define MASS_SUBCLASS_SCSI_NOT_REPORTED 0x00 // De facto use +#define MASS_SUBCLASS_RBC 0x01 +#define MASS_SUBCLASS_ATAPI 0x02 // MMC-5 (ATAPI) +#define MASS_SUBCLASS_OBSOLETE1 0x03 // Was QIC-157 +#define MASS_SUBCLASS_UFI 0x04 // Specifies how to interface Floppy Disk Drives to USB +#define MASS_SUBCLASS_OBSOLETE2 0x05 // Was SFF-8070i +#define MASS_SUBCLASS_SCSI 0x06 // SCSI Transparent Command Set +#define MASS_SUBCLASS_LSDFS 0x07 // Specifies how host has to negotiate access before trying SCSI +#define MASS_SUBCLASS_IEEE1667 0x08 + +// Mass Storage Class Protocols +#define MASS_PROTO_CBI 0x00 // CBI (with command completion interrupt) +#define MASS_PROTO_CBI_NO_INT 0x01 // CBI (without command completion interrupt) +#define MASS_PROTO_OBSOLETE 0x02 +#define MASS_PROTO_BBB 0x50 // Bulk Only Transport +#define MASS_PROTO_UAS 0x62 + +// Request Codes +#define MASS_REQ_ADSC 0x00 +#define MASS_REQ_GET 0xFC +#define MASS_REQ_PUT 0xFD +#define MASS_REQ_GET_MAX_LUN 0xFE +#define MASS_REQ_BOMSR 0xFF // Bulk-Only Mass Storage Reset + +#define MASS_CBW_SIGNATURE 0x43425355 +#define MASS_CSW_SIGNATURE 0x53425355 + +#define MASS_CMD_DIR_OUT 0 // (0 << 7) +#define MASS_CMD_DIR_IN 0x80 //(1 << 7) + +/* + * Reference documents from T10 (http://www.t10.org) + * SCSI Primary Commands - 3 (SPC-3) + * SCSI Block Commands - 2 (SBC-2) + * Multi-Media Commands - 5 (MMC-5) + */ + +/* Group 1 commands (CDB's here are should all be 6-bytes) */ +#define SCSI_CMD_TEST_UNIT_READY 0x00 +#define SCSI_CMD_REQUEST_SENSE 0x03 +#define SCSI_CMD_FORMAT_UNIT 0x04 +#define SCSI_CMD_READ_6 0x08 +#define SCSI_CMD_WRITE_6 0x0A +#define SCSI_CMD_INQUIRY 0x12 +#define SCSI_CMD_MODE_SELECT_6 0x15 +#define SCSI_CMD_MODE_SENSE_6 0x1A +#define SCSI_CMD_START_STOP_UNIT 0x1B +#define SCSI_CMD_PREVENT_REMOVAL 0x1E +/* Group 2 Commands (CDB's here are 10-bytes) */ +#define SCSI_CMD_READ_FORMAT_CAPACITIES 0x23 +#define SCSI_CMD_READ_CAPACITY_10 0x25 +#define SCSI_CMD_READ_10 0x28 +#define SCSI_CMD_WRITE_10 0x2A +#define SCSI_CMD_SEEK_10 0x2B +#define SCSI_CMD_ERASE_10 0x2C +#define SCSI_CMD_WRITE_AND_VERIFY_10 0x2E +#define SCSI_CMD_VERIFY_10 0x2F +#define SCSI_CMD_SYNCHRONIZE_CACHE 0x35 +#define SCSI_CMD_WRITE_BUFFER 0x3B +#define SCSI_CMD_READ_BUFFER 0x3C +#define SCSI_CMD_READ_SUBCHANNEL 0x42 +#define SCSI_CMD_READ_TOC 0x43 +#define SCSI_CMD_READ_HEADER 0x44 +#define SCSI_CMD_PLAY_AUDIO_10 0x45 +#define SCSI_CMD_GET_CONFIGURATION 0x46 +#define SCSI_CMD_PLAY_AUDIO_MSF 0x47 +#define SCSI_CMD_PLAY_AUDIO_TI 0x48 +#define SCSI_CMD_PLAY_TRACK_REL_10 0x49 +#define SCSI_CMD_GET_EVENT_STATUS 0x4A +#define SCSI_CMD_PAUSE_RESUME 0x4B +#define SCSI_CMD_READ_DISC_INFORMATION 0x51 +#define SCSI_CMD_READ_TRACK_INFORMATION 0x52 +#define SCSI_CMD_RESERVE_TRACK 0x53 +#define SCSI_CMD_SEND_OPC_INFORMATION 0x54 +#define SCSI_CMD_MODE_SELECT_10 0x55 +#define SCSI_CMD_REPAIR_TRACK 0x58 +#define SCSI_CMD_MODE_SENSE_10 0x5A +#define SCSI_CMD_CLOSE_TRACK_SESSION 0x5B +#define SCSI_CMD_READ_BUFFER_CAPACITY 0x5C +#define SCSI_CMD_SEND_CUE_SHEET 0x5D +/* Group 5 Commands (CDB's here are 12-bytes) */ +#define SCSI_CMD_REPORT_LUNS 0xA0 +#define SCSI_CMD_BLANK 0xA1 +#define SCSI_CMD_SECURITY_PROTOCOL_IN 0xA2 +#define SCSI_CMD_SEND_KEY 0xA3 +#define SCSI_CMD_REPORT_KEY 0xA4 +#define SCSI_CMD_PLAY_AUDIO_12 0xA5 +#define SCSI_CMD_LOAD_UNLOAD 0xA6 +#define SCSI_CMD_SET_READ_AHEAD 0xA7 +#define SCSI_CMD_READ_12 0xA8 +#define SCSI_CMD_PLAY_TRACK_REL_12 0xA9 +#define SCSI_CMD_WRITE_12 0xAA +#define SCSI_CMD_READ_MEDIA_SERIAL_12 0xAB +#define SCSI_CMD_GET_PERFORMANCE 0xAC +#define SCSI_CMD_READ_DVD_STRUCTURE 0xAD +#define SCSI_CMD_SECURITY_PROTOCOL_OUT 0xB5 +#define SCSI_CMD_SET_STREAMING 0xB6 +#define SCSI_CMD_READ_MSF 0xB9 +#define SCSI_CMD_SET_SPEED 0xBB +#define SCSI_CMD_MECHANISM_STATUS 0xBD +#define SCSI_CMD_READ_CD 0xBE +#define SCSI_CMD_SEND_DISC_STRUCTURE 0xBF +/* Vendor-unique Commands, included for completeness */ +#define SCSI_CMD_CD_PLAYBACK_STATUS 0xC4 /* SONY unique */ +#define SCSI_CMD_PLAYBACK_CONTROL 0xC9 /* SONY unique */ +#define SCSI_CMD_READ_CDDA 0xD8 /* Vendor unique */ +#define SCSI_CMD_READ_CDXA 0xDB /* Vendor unique */ +#define SCSI_CMD_READ_ALL_SUBCODES 0xDF /* Vendor unique */ + +/* SCSI error codes */ +#define SCSI_S_NOT_READY 0x02 +#define SCSI_S_MEDIUM_ERROR 0x03 +#define SCSI_S_ILLEGAL_REQUEST 0x05 +#define SCSI_S_UNIT_ATTENTION 0x06 +#define SCSI_ASC_LBA_OUT_OF_RANGE 0x21 +#define SCSI_ASC_MEDIA_CHANGED 0x28 +#define SCSI_ASC_MEDIUM_NOT_PRESENT 0x3A + +/* USB error codes */ +#define MASS_ERR_SUCCESS 0x00 +#define MASS_ERR_PHASE_ERROR 0x02 +#define MASS_ERR_UNIT_NOT_READY 0x03 +#define MASS_ERR_UNIT_BUSY 0x04 +#define MASS_ERR_STALL 0x05 +#define MASS_ERR_CMD_NOT_SUPPORTED 0x06 +#define MASS_ERR_INVALID_CSW 0x07 +#define MASS_ERR_NO_MEDIA 0x08 +#define MASS_ERR_BAD_LBA 0x09 +#define MASS_ERR_MEDIA_CHANGED 0x0A +#define MASS_ERR_DEVICE_DISCONNECTED 0x11 +#define MASS_ERR_UNABLE_TO_RECOVER 0x12 // Reset recovery error +#define MASS_ERR_INVALID_LUN 0x13 +#define MASS_ERR_WRITE_STALL 0x14 +#define MASS_ERR_READ_NAKS 0x15 +#define MASS_ERR_WRITE_NAKS 0x16 +#define MASS_ERR_WRITE_PROTECTED 0x17 +#define MASS_ERR_NOT_IMPLEMENTED 0xFD +#define MASS_ERR_GENERAL_SCSI_ERROR 0xFE +#define MASS_ERR_GENERAL_USB_ERROR 0xFF +#define MASS_ERR_USER 0xA0 // For subclasses to define their own error codes + +#define MASS_TRANS_FLG_CALLBACK 0x01 // Callback is involved +#define MASS_TRANS_FLG_NO_STALL_CHECK 0x02 // STALL condition is not checked +#define MASS_TRANS_FLG_NO_PHASE_CHECK 0x04 // PHASE_ERROR is not checked + +#define MASS_MAX_ENDPOINTS 3 + +struct Capacity { + uint8_t data[8]; + //uint32_t dwBlockAddress; + //uint32_t dwBlockLength; +} __attribute__((packed)); + +struct BASICCDB { + uint8_t Opcode; + + unsigned unused : 5; + unsigned LUN : 3; + + uint8_t info[12]; +} __attribute__((packed)); + +typedef BASICCDB BASICCDB_t; + +struct CDB6 { + uint8_t Opcode; + + unsigned LBAMSB : 5; + unsigned LUN : 3; + + uint8_t LBAHB; + uint8_t LBALB; + uint8_t AllocationLength; + uint8_t Control; + +public: + + CDB6(uint8_t _Opcode, uint8_t _LUN, uint32_t LBA, uint8_t _AllocationLength, uint8_t _Control) : + Opcode(_Opcode), LBAMSB(BGRAB2(LBA) & 0x1f), LUN(_LUN), LBAHB(BGRAB1(LBA)), LBALB(BGRAB0(LBA)), + AllocationLength(_AllocationLength), Control(_Control) { + } + + CDB6(uint8_t _Opcode, uint8_t _LUN, uint8_t _AllocationLength, uint8_t _Control) : + Opcode(_Opcode), LBAMSB(0), LUN(_LUN), LBAHB(0), LBALB(0), + AllocationLength(_AllocationLength), Control(_Control) { + } +} __attribute__((packed)); + +typedef CDB6 CDB6_t; + +struct CDB10 { + uint8_t Opcode; + + unsigned Service_Action : 5; + unsigned LUN : 3; + + uint8_t LBA_L_M_MB; + uint8_t LBA_L_M_LB; + uint8_t LBA_L_L_MB; + uint8_t LBA_L_L_LB; + + uint8_t Misc2; + + uint8_t ALC_MB; + uint8_t ALC_LB; + + uint8_t Control; +public: + + CDB10(uint8_t _Opcode, uint8_t _LUN) : + Opcode(_Opcode), Service_Action(0), LUN(_LUN), + LBA_L_M_MB(0), LBA_L_M_LB(0), LBA_L_L_MB(0), LBA_L_L_LB(0), + Misc2(0), ALC_MB(0), ALC_LB(0), Control(0) { + } + + CDB10(uint8_t _Opcode, uint8_t _LUN, uint16_t xflen, uint32_t _LBA) : + Opcode(_Opcode), Service_Action(0), LUN(_LUN), + LBA_L_M_MB(BGRAB3(_LBA)), LBA_L_M_LB(BGRAB2(_LBA)), LBA_L_L_MB(BGRAB1(_LBA)), LBA_L_L_LB(BGRAB0(_LBA)), + Misc2(0), ALC_MB(BGRAB1(xflen)), ALC_LB(BGRAB0(xflen)), Control(0) { + } +} __attribute__((packed)); + +typedef CDB10 CDB10_t; + +struct CDB12 { + uint8_t Opcode; + + unsigned Service_Action : 5; + unsigned Misc : 3; + + uint8_t LBA_L_M_LB; + uint8_t LBA_L_L_MB; + uint8_t LBA_L_L_LB; + + uint8_t ALC_M_LB; + uint8_t ALC_L_MB; + uint8_t ALC_L_LB; + uint8_t Control; +} __attribute__((packed)); + +typedef CDB12 CDB12_t; + +struct CDB_LBA32_16 { + uint8_t Opcode; + + unsigned Service_Action : 5; + unsigned Misc : 3; + + uint8_t LBA_L_M_MB; + uint8_t LBA_L_M_LB; + uint8_t LBA_L_L_MB; + uint8_t LBA_L_L_LB; + + uint8_t A_M_M_MB; + uint8_t A_M_M_LB; + uint8_t A_M_L_MB; + uint8_t A_M_L_LB; + + uint8_t ALC_M_MB; + uint8_t ALC_M_LB; + uint8_t ALC_L_MB; + uint8_t ALC_L_LB; + + uint8_t Misc2; + uint8_t Control; +} __attribute__((packed)); + +struct CDB_LBA64_16 { + uint8_t Opcode; + uint8_t Misc; + + uint8_t LBA_M_M_MB; + uint8_t LBA_M_M_LB; + uint8_t LBA_M_L_MB; + uint8_t LBA_M_L_LB; + + uint8_t LBA_L_M_MB; + uint8_t LBA_L_M_LB; + uint8_t LBA_L_L_MB; + uint8_t LBA_L_L_LB; + + uint8_t ALC_M_MB; + uint8_t ALC_M_LB; + uint8_t ALC_L_MB; + uint8_t ALC_L_LB; + + uint8_t Misc2; + uint8_t Control; +} __attribute__((packed)); + +struct InquiryResponse { + uint8_t DeviceType : 5; + uint8_t PeripheralQualifier : 3; + + unsigned Reserved : 7; + unsigned Removable : 1; + + uint8_t Version; + + unsigned ResponseDataFormat : 4; + unsigned HISUP : 1; + unsigned NormACA : 1; + unsigned TrmTsk : 1; + unsigned AERC : 1; + + uint8_t AdditionalLength; + //uint8_t Reserved3[2]; + + unsigned PROTECT : 1; + unsigned Res : 2; + unsigned ThreePC : 1; + unsigned TPGS : 2; + unsigned ACC : 1; + unsigned SCCS : 1; + + unsigned ADDR16 : 1; + unsigned R1 : 1; + unsigned R2 : 1; + unsigned MCHNGR : 1; + unsigned MULTIP : 1; + unsigned VS : 1; + unsigned ENCSERV : 1; + unsigned BQUE : 1; + + unsigned SoftReset : 1; + unsigned CmdQue : 1; + unsigned Reserved4 : 1; + unsigned Linked : 1; + unsigned Sync : 1; + unsigned WideBus16Bit : 1; + unsigned WideBus32Bit : 1; + unsigned RelAddr : 1; + + uint8_t VendorID[8]; + uint8_t ProductID[16]; + uint8_t RevisionID[4]; +} __attribute__((packed)); + +struct CommandBlockWrapperBase { + uint32_t dCBWSignature; + uint32_t dCBWTag; + uint32_t dCBWDataTransferLength; + uint8_t bmCBWFlags; +public: + + CommandBlockWrapperBase() { + } + + CommandBlockWrapperBase(uint32_t tag, uint32_t xflen, uint8_t flgs) : + dCBWSignature(MASS_CBW_SIGNATURE), dCBWTag(tag), dCBWDataTransferLength(xflen), bmCBWFlags(flgs) { + } +} __attribute__((packed)); + +struct CommandBlockWrapper : public CommandBlockWrapperBase { + + struct { + uint8_t bmCBWLUN : 4; + uint8_t bmReserved1 : 4; + }; + + struct { + uint8_t bmCBWCBLength : 4; + uint8_t bmReserved2 : 4; + }; + + uint8_t CBWCB[16]; + +public: + // All zeroed. + + CommandBlockWrapper() : + CommandBlockWrapperBase(0, 0, 0), bmReserved1(0), bmReserved2(0) { + for(int i = 0; i < 16; i++) CBWCB[i] = 0; + } + + // Generic Wrap, CDB zeroed. + + CommandBlockWrapper(uint32_t tag, uint32_t xflen, uint8_t flgs, uint8_t lu, uint8_t cmdlen, uint8_t cmd) : + CommandBlockWrapperBase(tag, xflen, flgs), + bmCBWLUN(lu), bmReserved1(0), bmCBWCBLength(cmdlen), bmReserved2(0) { + for(int i = 0; i < 16; i++) CBWCB[i] = 0; + // Type punning can cause optimization problems and bugs. + // Using reinterpret_cast to a dreinterpretifferent object is the proper way to do this. + //(((BASICCDB_t *) CBWCB)->LUN) = cmd; + BASICCDB_t *x = reinterpret_cast(CBWCB); + x->LUN = cmd; + } + + // Wrap for CDB of 6 + + CommandBlockWrapper(uint32_t tag, uint32_t xflen, CDB6_t *cdb, uint8_t dir) : + CommandBlockWrapperBase(tag, xflen, dir), + bmCBWLUN(cdb->LUN), bmReserved1(0), bmCBWCBLength(6), bmReserved2(0) { + memcpy(&CBWCB, cdb, 6); + } + // Wrap for CDB of 10 + + CommandBlockWrapper(uint32_t tag, uint32_t xflen, CDB10_t *cdb, uint8_t dir) : + CommandBlockWrapperBase(tag, xflen, dir), + bmCBWLUN(cdb->LUN), bmReserved1(0), bmCBWCBLength(10), bmReserved2(0) { + memcpy(&CBWCB, cdb, 10); + } +} __attribute__((packed)); + +struct CommandStatusWrapper { + uint32_t dCSWSignature; + uint32_t dCSWTag; + uint32_t dCSWDataResidue; + uint8_t bCSWStatus; +} __attribute__((packed)); + +struct RequestSenseResponce { + uint8_t bResponseCode; + uint8_t bSegmentNumber; + + uint8_t bmSenseKey : 4; + uint8_t bmReserved : 1; + uint8_t bmILI : 1; + uint8_t bmEOM : 1; + uint8_t bmFileMark : 1; + + uint8_t Information[4]; + uint8_t bAdditionalLength; + uint8_t CmdSpecificInformation[4]; + uint8_t bAdditionalSenseCode; + uint8_t bAdditionalSenseQualifier; + uint8_t bFieldReplaceableUnitCode; + uint8_t SenseKeySpecific[3]; +} __attribute__((packed)); + +class BulkOnly : public USBDeviceConfig, public UsbConfigXtracter { +protected: + static const uint8_t epDataInIndex; // DataIn endpoint index + static const uint8_t epDataOutIndex; // DataOUT endpoint index + static const uint8_t epInterruptInIndex; // InterruptIN endpoint index + + USB *pUsb; + uint8_t bAddress; + uint8_t bConfNum; // configuration number + uint8_t bIface; // interface value + uint8_t bNumEP; // total number of EP in the configuration + uint32_t qNextPollTime; // next poll time + bool bPollEnable; // poll enable flag + + EpInfo epInfo[MASS_MAX_ENDPOINTS]; + + uint32_t dCBWTag; // Tag + //uint32_t dCBWDataTransferLength; // Data Transfer Length + uint8_t bLastUsbError; // Last USB error + uint8_t bMaxLUN; // Max LUN + uint8_t bTheLUN; // Active LUN + uint32_t CurrentCapacity[MASS_MAX_SUPPORTED_LUN]; // Total sectors + uint16_t CurrentSectorSize[MASS_MAX_SUPPORTED_LUN]; // Sector size, clipped to 16 bits + bool LUNOk[MASS_MAX_SUPPORTED_LUN]; // use this to check for media changes. + bool WriteOk[MASS_MAX_SUPPORTED_LUN]; + void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); + + + // Additional Initialization Method for Subclasses + + virtual uint8_t OnInit() { + return 0; + }; +public: + BulkOnly(USB *p); + + uint8_t GetLastUsbError() { + return bLastUsbError; + }; + + uint8_t GetbMaxLUN() { + return bMaxLUN; // Max LUN + } + + uint8_t GetbTheLUN() { + return bTheLUN; // Active LUN + } + + bool WriteProtected(uint8_t lun); + uint8_t MediaCTL(uint8_t lun, uint8_t ctl); + uint8_t Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf); + uint8_t Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, USBReadParser *prs); + uint8_t Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t *buf); + uint8_t LockMedia(uint8_t lun, uint8_t lock); + + bool LUNIsGood(uint8_t lun); + uint32_t GetCapacity(uint8_t lun); + uint16_t GetSectorSize(uint8_t lun); + + // USBDeviceConfig implementation + uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + uint8_t ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed); + + uint8_t Release(); + uint8_t Poll(); + + virtual uint8_t GetAddress() { + return bAddress; + }; + + // UsbConfigXtracter implementation + void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); + + virtual bool DEVCLASSOK(uint8_t klass) { + return (klass == USB_CLASS_MASS_STORAGE); + } + + uint8_t SCSITransaction6(CDB6_t *cdb, uint16_t buf_size, void *buf, uint8_t dir); + uint8_t SCSITransaction10(CDB10_t *cdb, uint16_t buf_size, void *buf, uint8_t dir); + +private: + uint8_t Inquiry(uint8_t lun, uint16_t size, uint8_t *buf); + uint8_t TestUnitReady(uint8_t lun); + uint8_t RequestSense(uint8_t lun, uint16_t size, uint8_t *buf); + uint8_t ModeSense6(uint8_t lun, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t len, uint8_t *buf); + uint8_t GetMaxLUN(uint8_t *max_lun); + uint8_t SetCurLUN(uint8_t lun); + void Reset(); + uint8_t ResetRecovery(); + uint8_t ReadCapacity10(uint8_t lun, uint8_t *buf); + void ClearAllEP(); + void CheckMedia(); + bool CheckLUN(uint8_t lun); + uint8_t Page3F(uint8_t lun); + bool IsValidCBW(uint8_t size, uint8_t *pcbw); + bool IsMeaningfulCBW(uint8_t size, uint8_t *pcbw); + + bool IsValidCSW(CommandStatusWrapper *pcsw, CommandBlockWrapperBase *pcbw); + + uint8_t ClearEpHalt(uint8_t index); +#if MS_WANT_PARSER + uint8_t Transaction(CommandBlockWrapper *cbw, uint16_t bsize, void *buf, uint8_t flags); +#endif + uint8_t Transaction(CommandBlockWrapper *cbw, uint16_t bsize, void *buf); + uint8_t HandleUsbError(uint8_t error, uint8_t index); + uint8_t HandleSCSIError(uint8_t status); + +}; + +#endif // __MASSTORAGE_H__ diff --git a/lib/usbhost/USB_Host_Shield_2.0/max3421e.h b/lib/usbhost/USB_Host_Shield_2.0/max3421e.h new file mode 100644 index 0000000000..4e45a35e8d --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/max3421e.h @@ -0,0 +1,228 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#if !defined(_usb_h_) || defined(_max3421e_h_) +#error "Never include max3421e.h directly; include Usb.h instead" +#else + +#define _max3421e_h_ + +/* MAX3421E register/bit names and bitmasks */ + +/* Arduino pin definitions */ +/* pin numbers to port numbers */ + +#define SE0 0 +#define SE1 1 +#define FSHOST 2 +#define LSHOST 3 + +/* MAX3421E command byte format: rrrrr0wa where 'r' is register number */ +// +// MAX3421E Registers in HOST mode. +// +#define rRCVFIFO 0x08 //1<<3 +#define rSNDFIFO 0x10 //2<<3 +#define rSUDFIFO 0x20 //4<<3 +#define rRCVBC 0x30 //6<<3 +#define rSNDBC 0x38 //7<<3 + +#define rUSBIRQ 0x68 //13<<3 +/* USBIRQ Bits */ +#define bmVBUSIRQ 0x40 //b6 +#define bmNOVBUSIRQ 0x20 //b5 +#define bmOSCOKIRQ 0x01 //b0 + +#define rUSBIEN 0x70 //14<<3 +/* USBIEN Bits */ +#define bmVBUSIE 0x40 //b6 +#define bmNOVBUSIE 0x20 //b5 +#define bmOSCOKIE 0x01 //b0 + +#define rUSBCTL 0x78 //15<<3 +/* USBCTL Bits */ +#define bmCHIPRES 0x20 //b5 +#define bmPWRDOWN 0x10 //b4 + +#define rCPUCTL 0x80 //16<<3 +/* CPUCTL Bits */ +#define bmPUSLEWID1 0x80 //b7 +#define bmPULSEWID0 0x40 //b6 +#define bmIE 0x01 //b0 + +#define rPINCTL 0x88 //17<<3 +/* PINCTL Bits */ +#define bmFDUPSPI 0x10 //b4 +#define bmINTLEVEL 0x08 //b3 +#define bmPOSINT 0x04 //b2 +#define bmGPXB 0x02 //b1 +#define bmGPXA 0x01 //b0 +// GPX pin selections +#define GPX_OPERATE 0x00 +#define GPX_VBDET 0x01 +#define GPX_BUSACT 0x02 +#define GPX_SOF 0x03 + +#define rREVISION 0x90 //18<<3 + +#define rIOPINS1 0xa0 //20<<3 + +/* IOPINS1 Bits */ +#define bmGPOUT0 0x01 +#define bmGPOUT1 0x02 +#define bmGPOUT2 0x04 +#define bmGPOUT3 0x08 +#define bmGPIN0 0x10 +#define bmGPIN1 0x20 +#define bmGPIN2 0x40 +#define bmGPIN3 0x80 + +#define rIOPINS2 0xa8 //21<<3 +/* IOPINS2 Bits */ +#define bmGPOUT4 0x01 +#define bmGPOUT5 0x02 +#define bmGPOUT6 0x04 +#define bmGPOUT7 0x08 +#define bmGPIN4 0x10 +#define bmGPIN5 0x20 +#define bmGPIN6 0x40 +#define bmGPIN7 0x80 + +#define rGPINIRQ 0xb0 //22<<3 +/* GPINIRQ Bits */ +#define bmGPINIRQ0 0x01 +#define bmGPINIRQ1 0x02 +#define bmGPINIRQ2 0x04 +#define bmGPINIRQ3 0x08 +#define bmGPINIRQ4 0x10 +#define bmGPINIRQ5 0x20 +#define bmGPINIRQ6 0x40 +#define bmGPINIRQ7 0x80 + +#define rGPINIEN 0xb8 //23<<3 +/* GPINIEN Bits */ +#define bmGPINIEN0 0x01 +#define bmGPINIEN1 0x02 +#define bmGPINIEN2 0x04 +#define bmGPINIEN3 0x08 +#define bmGPINIEN4 0x10 +#define bmGPINIEN5 0x20 +#define bmGPINIEN6 0x40 +#define bmGPINIEN7 0x80 + +#define rGPINPOL 0xc0 //24<<3 +/* GPINPOL Bits */ +#define bmGPINPOL0 0x01 +#define bmGPINPOL1 0x02 +#define bmGPINPOL2 0x04 +#define bmGPINPOL3 0x08 +#define bmGPINPOL4 0x10 +#define bmGPINPOL5 0x20 +#define bmGPINPOL6 0x40 +#define bmGPINPOL7 0x80 + +#define rHIRQ 0xc8 //25<<3 +/* HIRQ Bits */ +#define bmBUSEVENTIRQ 0x01 // indicates BUS Reset Done or BUS Resume +#define bmRWUIRQ 0x02 +#define bmRCVDAVIRQ 0x04 +#define bmSNDBAVIRQ 0x08 +#define bmSUSDNIRQ 0x10 +#define bmCONDETIRQ 0x20 +#define bmFRAMEIRQ 0x40 +#define bmHXFRDNIRQ 0x80 + +#define rHIEN 0xd0 //26<<3 + +/* HIEN Bits */ +#define bmBUSEVENTIE 0x01 +#define bmRWUIE 0x02 +#define bmRCVDAVIE 0x04 +#define bmSNDBAVIE 0x08 +#define bmSUSDNIE 0x10 +#define bmCONDETIE 0x20 +#define bmFRAMEIE 0x40 +#define bmHXFRDNIE 0x80 + +#define rMODE 0xd8 //27<<3 + +/* MODE Bits */ +#define bmHOST 0x01 +#define bmLOWSPEED 0x02 +#define bmHUBPRE 0x04 +#define bmSOFKAENAB 0x08 +#define bmSEPIRQ 0x10 +#define bmDELAYISO 0x20 +#define bmDMPULLDN 0x40 +#define bmDPPULLDN 0x80 + +#define rPERADDR 0xe0 //28<<3 + +#define rHCTL 0xe8 //29<<3 +/* HCTL Bits */ +#define bmBUSRST 0x01 +#define bmFRMRST 0x02 +#define bmSAMPLEBUS 0x04 +#define bmSIGRSM 0x08 +#define bmRCVTOG0 0x10 +#define bmRCVTOG1 0x20 +#define bmSNDTOG0 0x40 +#define bmSNDTOG1 0x80 + +#define rHXFR 0xf0 //30<<3 +/* Host transfer token values for writing the HXFR register (R30) */ +/* OR this bit field with the endpoint number in bits 3:0 */ +#define tokSETUP 0x10 // HS=0, ISO=0, OUTNIN=0, SETUP=1 +#define tokIN 0x00 // HS=0, ISO=0, OUTNIN=0, SETUP=0 +#define tokOUT 0x20 // HS=0, ISO=0, OUTNIN=1, SETUP=0 +#define tokINHS 0x80 // HS=1, ISO=0, OUTNIN=0, SETUP=0 +#define tokOUTHS 0xA0 // HS=1, ISO=0, OUTNIN=1, SETUP=0 +#define tokISOIN 0x40 // HS=0, ISO=1, OUTNIN=0, SETUP=0 +#define tokISOOUT 0x60 // HS=0, ISO=1, OUTNIN=1, SETUP=0 + +#define rHRSL 0xf8 //31<<3 + +/* HRSL Bits */ +#define bmRCVTOGRD 0x10 +#define bmSNDTOGRD 0x20 +#define bmKSTATUS 0x40 +#define bmJSTATUS 0x80 +#define bmSE0 0x00 //SE0 - disconnect state +#define bmSE1 0xc0 //SE1 - illegal state + +/* Host error result codes, the 4 LSB's in the HRSL register */ +#define hrSUCCESS 0x00 +#define hrBUSY 0x01 +#define hrBADREQ 0x02 +#define hrUNDEF 0x03 +#define hrNAK 0x04 +#define hrSTALL 0x05 +#define hrTOGERR 0x06 +#define hrWRONGPID 0x07 +#define hrBADBC 0x08 +#define hrPIDERR 0x09 +#define hrPKTERR 0x0A +#define hrCRCERR 0x0B +#define hrKERR 0x0C +#define hrJERR 0x0D +#define hrTIMEOUT 0x0E +#define hrBABBLE 0x0F + +#define MODE_FS_HOST (bmDPPULLDN|bmDMPULLDN|bmHOST|bmSOFKAENAB) +#define MODE_LS_HOST (bmDPPULLDN|bmDMPULLDN|bmHOST|bmLOWSPEED|bmSOFKAENAB) + + +#endif //_max3421e_h_ diff --git a/lib/usbhost/USB_Host_Shield_2.0/max_LCD.cpp b/lib/usbhost/USB_Host_Shield_2.0/max_LCD.cpp new file mode 100644 index 0000000000..f0c64666fa --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/max_LCD.cpp @@ -0,0 +1,255 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#include "max_LCD.h" +#include + +// pin definition and set/clear + +#define RS 0x04 // RS pin +#define E 0x08 // E pin + +#define SET_RS lcdPins |= RS +#define CLR_RS lcdPins &= ~RS +#define SET_E lcdPins |= E +#define CLR_E lcdPins &= ~E + +#define SENDlcdPins() pUsb->gpioWr( lcdPins ) + +#define LCD_sendcmd(a) { CLR_RS; \ + sendbyte(a); \ + } + +#define LCD_sendchar(a) { SET_RS; \ + sendbyte(a); \ + } + +static byte lcdPins; //copy of LCD pins + +Max_LCD::Max_LCD(USB *pusb) : pUsb(pusb) { + lcdPins = 0; +} + +void Max_LCD::init() { + _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS; + + // MAX3421E::gpioWr(0x55); + + begin(16, 1); +} + +void Max_LCD::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) { + if(lines > 1) { + _displayfunction |= LCD_2LINE; + } + _numlines = lines; + _currline = 0; + + // for some 1 line displays you can select a 10 pixel high font + if((dotsize != 0) && (lines == 1)) { + _displayfunction |= LCD_5x10DOTS; + } + + // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION! + // according to datasheet, we need at least 40ms after power rises above 2.7V + // before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50 + delayMicroseconds(50000); + lcdPins = 0x30; + SET_E; + SENDlcdPins(); + CLR_E; + SENDlcdPins(); + delayMicroseconds(10000); // wait min 4.1ms + //second try + SET_E; + SENDlcdPins(); + CLR_E; + SENDlcdPins(); + delayMicroseconds(10000); // wait min 4.1ms + // third go! + SET_E; + SENDlcdPins(); + CLR_E; + SENDlcdPins(); + delayMicroseconds(10000); + // finally, set to 4-bit interface + lcdPins = 0x20; + //SET_RS; + SET_E; + SENDlcdPins(); + //CLR_RS; + CLR_E; + SENDlcdPins(); + delayMicroseconds(10000); + // finally, set # lines, font size, etc. + command(LCD_FUNCTIONSET | _displayfunction); + + // turn the display on with no cursor or blinking default + _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; + display(); + + // clear it off + clear(); + + // Initialize to default text direction (for romance languages) + _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; + // set the entry mode + command(LCD_ENTRYMODESET | _displaymode); +} + +/********** high level commands, for the user! */ +void Max_LCD::clear() { + command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero + delayMicroseconds(2000); // this command takes a long time! +} + +void Max_LCD::home() { + command(LCD_RETURNHOME); // set cursor position to zero + delayMicroseconds(2000); // this command takes a long time! +} + +void Max_LCD::setCursor(uint8_t col, uint8_t row) { + int row_offsets[] = {0x00, 0x40, 0x14, 0x54}; + if(row > _numlines) { + row = _numlines - 1; // we count rows starting w/0 + } + + command(LCD_SETDDRAMADDR | (col + row_offsets[row])); +} + +// Turn the display on/off (quickly) + +void Max_LCD::noDisplay() { + _displaycontrol &= ~LCD_DISPLAYON; + command(LCD_DISPLAYCONTROL | _displaycontrol); +} + +void Max_LCD::display() { + _displaycontrol |= LCD_DISPLAYON; + command(LCD_DISPLAYCONTROL | _displaycontrol); +} + +// Turns the underline cursor on/off + +void Max_LCD::noCursor() { + _displaycontrol &= ~LCD_CURSORON; + command(LCD_DISPLAYCONTROL | _displaycontrol); +} + +void Max_LCD::cursor() { + _displaycontrol |= LCD_CURSORON; + command(LCD_DISPLAYCONTROL | _displaycontrol); +} + + +// Turn on and off the blinking cursor + +void Max_LCD::noBlink() { + _displaycontrol &= ~LCD_BLINKON; + command(LCD_DISPLAYCONTROL | _displaycontrol); +} + +void Max_LCD::blink() { + _displaycontrol |= LCD_BLINKON; + command(LCD_DISPLAYCONTROL | _displaycontrol); +} + +// These commands scroll the display without changing the RAM + +void Max_LCD::scrollDisplayLeft(void) { + command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT); +} + +void Max_LCD::scrollDisplayRight(void) { + command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT); +} + +// This is for text that flows Left to Right + +void Max_LCD::leftToRight(void) { + _displaymode |= LCD_ENTRYLEFT; + command(LCD_ENTRYMODESET | _displaymode); +} + +// This is for text that flows Right to Left + +void Max_LCD::rightToLeft(void) { + _displaymode &= ~LCD_ENTRYLEFT; + command(LCD_ENTRYMODESET | _displaymode); +} + +// This will 'right justify' text from the cursor + +void Max_LCD::autoscroll(void) { + _displaymode |= LCD_ENTRYSHIFTINCREMENT; + command(LCD_ENTRYMODESET | _displaymode); +} + +// This will 'left justify' text from the cursor + +void Max_LCD::noAutoscroll(void) { + _displaymode &= ~LCD_ENTRYSHIFTINCREMENT; + command(LCD_ENTRYMODESET | _displaymode); +} + +// Allows us to fill the first 8 CGRAM locations +// with custom characters + +void Max_LCD::createChar(uint8_t location, uint8_t charmap[]) { + location &= 0x7; // we only have 8 locations 0-7 + command(LCD_SETCGRAMADDR | (location << 3)); + for(int i = 0; i < 8; i++) { + write(charmap[i]); + } +} + +/*********** mid level commands, for sending data/cmds */ + +inline void Max_LCD::command(uint8_t value) { + LCD_sendcmd(value); + delayMicroseconds(100); +} + +#if defined(ARDUINO) && ARDUINO >=100 + +inline size_t Max_LCD::write(uint8_t value) { + LCD_sendchar(value); + return 1; // Assume success +} +#else + +inline void Max_LCD::write(uint8_t value) { + LCD_sendchar(value); +} +#endif + +void Max_LCD::sendbyte(uint8_t val) { + lcdPins &= 0x0f; //prepare place for the upper nibble + lcdPins |= (val & 0xf0); //copy upper nibble to LCD variable + SET_E; //send + SENDlcdPins(); + delayMicroseconds(2); + CLR_E; + delayMicroseconds(2); + SENDlcdPins(); + lcdPins &= 0x0f; //prepare place for the lower nibble + lcdPins |= (val << 4) & 0xf0; //copy lower nibble to LCD variable + SET_E; //send + SENDlcdPins(); + CLR_E; + SENDlcdPins(); + delayMicroseconds(100); +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/max_LCD.h b/lib/usbhost/USB_Host_Shield_2.0/max_LCD.h new file mode 100644 index 0000000000..950c9c5aa3 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/max_LCD.h @@ -0,0 +1,106 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +//HD44780 compatible LCD display via MAX3421E GPOUT support header +//pinout: D[4-7] -> GPOUT[4-7], RS-> GPOUT[2], E ->GPOUT[3] +// + +#ifndef _Max_LCD_h_ +#define _Max_LCD_h_ + +#include "Usb.h" +#include "Print.h" + +// commands +#define LCD_CLEARDISPLAY 0x01 +#define LCD_RETURNHOME 0x02 +#define LCD_ENTRYMODESET 0x04 +#define LCD_DISPLAYCONTROL 0x08 +#define LCD_CURSORSHIFT 0x10 +#define LCD_FUNCTIONSET 0x20 +#define LCD_SETCGRAMADDR 0x40 +#define LCD_SETDDRAMADDR 0x80 + +// flags for display entry mode +#define LCD_ENTRYRIGHT 0x00 +#define LCD_ENTRYLEFT 0x02 +#define LCD_ENTRYSHIFTINCREMENT 0x01 +#define LCD_ENTRYSHIFTDECREMENT 0x00 + +// flags for display on/off control +#define LCD_DISPLAYON 0x04 +#define LCD_DISPLAYOFF 0x00 +#define LCD_CURSORON 0x02 +#define LCD_CURSOROFF 0x00 +#define LCD_BLINKON 0x01 +#define LCD_BLINKOFF 0x00 + +// flags for display/cursor shift +#define LCD_DISPLAYMOVE 0x08 +#define LCD_CURSORMOVE 0x00 +#define LCD_MOVERIGHT 0x04 +#define LCD_MOVELEFT 0x00 + +// flags for function set +#define LCD_8BITMODE 0x10 +#define LCD_4BITMODE 0x00 +#define LCD_2LINE 0x08 +#define LCD_1LINE 0x00 +#define LCD_5x10DOTS 0x04 +#define LCD_5x8DOTS 0x00 + +class Max_LCD : public Print { + USB *pUsb; + +public: + Max_LCD(USB *pusb); + void init(); + void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS); + void clear(); + void home(); + void noDisplay(); + void display(); + void noBlink(); + void blink(); + void noCursor(); + void cursor(); + void scrollDisplayLeft(); + void scrollDisplayRight(); + void leftToRight(); + void rightToLeft(); + void autoscroll(); + void noAutoscroll(); + void createChar(uint8_t, uint8_t[]); + void setCursor(uint8_t, uint8_t); + void command(uint8_t); + +#if defined(ARDUINO) && ARDUINO >=100 + size_t write(uint8_t); + using Print::write; +#else + void write(uint8_t); +#endif + +private: + void sendbyte(uint8_t val); + uint8_t _displayfunction; //tokill + uint8_t _displaycontrol; + uint8_t _displaymode; + uint8_t _initialized; + uint8_t _numlines, _currline; +}; + +#endif diff --git a/lib/usbhost/USB_Host_Shield_2.0/message.cpp b/lib/usbhost/USB_Host_Shield_2.0/message.cpp new file mode 100644 index 0000000000..bdcdd18331 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/message.cpp @@ -0,0 +1,116 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ + +#include "Usb.h" +// 0x80 is the default (i.e. trace) to turn off set this global to something lower. +// this allows for 126 other debugging levels. +// TO-DO: Allow assignment to a different serial port by software +int UsbDEBUGlvl = 0x80; + +void E_Notifyc(char c, int lvl) { + if(UsbDEBUGlvl < lvl) return; +#if defined(ARDUINO) && ARDUINO >=100 + USB_HOST_SERIAL.print(c); +#else + USB_HOST_SERIAL.print(c, BYTE); +#endif + //USB_HOST_SERIAL.flush(); +} + +void E_Notify(char const * msg, int lvl) { + if(UsbDEBUGlvl < lvl) return; + if(!msg) return; + char c; + + while((c = pgm_read_byte(msg++))) E_Notifyc(c, lvl); +} + +void E_NotifyStr(char const * msg, int lvl) { + if(UsbDEBUGlvl < lvl) return; + if(!msg) return; + char c; + + while((c = *msg++)) E_Notifyc(c, lvl); +} + +void E_Notify(uint8_t b, int lvl) { + if(UsbDEBUGlvl < lvl) return; +#if defined(ARDUINO) && ARDUINO >=100 + USB_HOST_SERIAL.print(b); +#else + USB_HOST_SERIAL.print(b, DEC); +#endif + //USB_HOST_SERIAL.flush(); +} + +void E_Notify(double d, int lvl) { + if(UsbDEBUGlvl < lvl) return; + USB_HOST_SERIAL.print(d); + //USB_HOST_SERIAL.flush(); +} + +#ifdef DEBUG_USB_HOST + +void NotifyFailGetDevDescr(void) { + Notify(PSTR("\r\ngetDevDescr "), 0x80); +} + +void NotifyFailSetDevTblEntry(void) { + Notify(PSTR("\r\nsetDevTblEn "), 0x80); +} + +void NotifyFailGetConfDescr(void) { + Notify(PSTR("\r\ngetConf "), 0x80); +} + +void NotifyFailSetConfDescr(void) { + Notify(PSTR("\r\nsetConf "), 0x80); +} + +void NotifyFailGetDevDescr(uint8_t reason) { + NotifyFailGetDevDescr(); + NotifyFail(reason); +} + +void NotifyFailSetDevTblEntry(uint8_t reason) { + NotifyFailSetDevTblEntry(); + NotifyFail(reason); + +} + +void NotifyFailGetConfDescr(uint8_t reason) { + NotifyFailGetConfDescr(); + NotifyFail(reason); +} + +void NotifyFailSetConfDescr(uint8_t reason) { + NotifyFailSetConfDescr(); + NotifyFail(reason); +} + +void NotifyFailUnknownDevice(uint16_t VID, uint16_t PID) { + Notify(PSTR("\r\nUnknown Device Connected - VID: "), 0x80); + D_PrintHex (VID, 0x80); + Notify(PSTR(" PID: "), 0x80); + D_PrintHex (PID, 0x80); +} + +void NotifyFail(uint8_t rcode) { + D_PrintHex (rcode, 0x80); + Notify(PSTR("\r\n"), 0x80); +} +#endif diff --git a/lib/usbhost/USB_Host_Shield_2.0/message.h b/lib/usbhost/USB_Host_Shield_2.0/message.h new file mode 100644 index 0000000000..c26628e7f2 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/message.h @@ -0,0 +1,78 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#if !defined(_usb_h_) || defined(__MESSAGE_H__) +#error "Never include message.h directly; include Usb.h instead" +#else +#define __MESSAGE_H__ + +extern int UsbDEBUGlvl; + +void E_Notify(char const * msg, int lvl); +void E_Notify(uint8_t b, int lvl); +void E_NotifyStr(char const * msg, int lvl); +void E_Notifyc(char c, int lvl); + +#ifdef DEBUG_USB_HOST +#define Notify E_Notify +#define NotifyStr E_NotifyStr +#define Notifyc E_Notifyc +void NotifyFailGetDevDescr(uint8_t reason); +void NotifyFailSetDevTblEntry(uint8_t reason); +void NotifyFailGetConfDescr(uint8_t reason); +void NotifyFailSetConfDescr(uint8_t reason); +void NotifyFailGetDevDescr(void); +void NotifyFailSetDevTblEntry(void); +void NotifyFailGetConfDescr(void); +void NotifyFailSetConfDescr(void); +void NotifyFailUnknownDevice(uint16_t VID, uint16_t PID); +void NotifyFail(uint8_t rcode); +#else +#define Notify(...) ((void)0) +#define NotifyStr(...) ((void)0) +#define Notifyc(...) ((void)0) +#define NotifyFailGetDevDescr(...) ((void)0) +#define NotifyFailSetDevTblEntry(...) ((void)0) +#define NotifyFailGetConfDescr(...) ((void)0) +#define NotifyFailGetDevDescr(...) ((void)0) +#define NotifyFailSetDevTblEntry(...) ((void)0) +#define NotifyFailGetConfDescr(...) ((void)0) +#define NotifyFailSetConfDescr(...) ((void)0) +#define NotifyFailUnknownDevice(...) ((void)0) +#define NotifyFail(...) ((void)0) +#endif + +template +void ErrorMessage(uint8_t level, char const * msg, ERROR_TYPE rcode = 0) { +#ifdef DEBUG_USB_HOST + Notify(msg, level); + Notify(PSTR(": "), level); + D_PrintHex (rcode, level); + Notify(PSTR("\r\n"), level); +#endif +} + +template +void ErrorMessage(char const * msg, ERROR_TYPE rcode = 0) { +#ifdef DEBUG_USB_HOST + Notify(msg, 0x80); + Notify(PSTR(": "), 0x80); + D_PrintHex (rcode, 0x80); + Notify(PSTR("\r\n"), 0x80); +#endif +} + +#endif // __MESSAGE_H__ diff --git a/lib/usbhost/USB_Host_Shield_2.0/parsetools.cpp b/lib/usbhost/USB_Host_Shield_2.0/parsetools.cpp new file mode 100644 index 0000000000..74a8610597 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/parsetools.cpp @@ -0,0 +1,67 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#include "Usb.h" + +bool MultiByteValueParser::Parse(uint8_t **pp, uint16_t *pcntdn) { + if(!pBuf) { + Notify(PSTR("Buffer pointer is NULL!\r\n"), 0x80); + return false; + } + for(; countDown && (*pcntdn); countDown--, (*pcntdn)--, (*pp)++) + pBuf[valueSize - countDown] = (**pp); + + if(countDown) + return false; + + countDown = valueSize; + return true; +} + +bool PTPListParser::Parse(uint8_t **pp, uint16_t *pcntdn, PTP_ARRAY_EL_FUNC pf, const void *me) { + switch(nStage) { + case 0: + pBuf->valueSize = lenSize; + theParser.Initialize(pBuf); + nStage = 1; + + case 1: + if(!theParser.Parse(pp, pcntdn)) + return false; + + arLen = 0; + arLen = (pBuf->valueSize >= 4) ? *((uint32_t*)pBuf->pValue) : (uint32_t)(*((uint16_t*)pBuf->pValue)); + arLenCntdn = arLen; + nStage = 2; + + case 2: + pBuf->valueSize = valSize; + theParser.Initialize(pBuf); + nStage = 3; + + case 3: + for(; arLenCntdn; arLenCntdn--) { + if(!theParser.Parse(pp, pcntdn)) + return false; + + if(pf) + pf(pBuf, (arLen - arLenCntdn), me); + } + + nStage = 0; + } + return true; +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/parsetools.h b/lib/usbhost/USB_Host_Shield_2.0/parsetools.h new file mode 100644 index 0000000000..66e9531c39 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/parsetools.h @@ -0,0 +1,140 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ + +#if !defined(_usb_h_) || defined(__PARSETOOLS_H__) +#error "Never include parsetools.h directly; include Usb.h instead" +#else +#define __PARSETOOLS_H__ + +struct MultiValueBuffer { + uint8_t valueSize; + void *pValue; +} __attribute__((packed)); + +class MultiByteValueParser { + uint8_t * pBuf; + uint8_t countDown; + uint8_t valueSize; + +public: + + MultiByteValueParser() : pBuf(NULL), countDown(0), valueSize(0) { + }; + + const uint8_t* GetBuffer() { + return pBuf; + }; + + void Initialize(MultiValueBuffer * const pbuf) { + pBuf = (uint8_t*)pbuf->pValue; + countDown = valueSize = pbuf->valueSize; + }; + + bool Parse(uint8_t **pp, uint16_t *pcntdn); +}; + +class ByteSkipper { + uint8_t *pBuf; + uint8_t nStage; + uint16_t countDown; + +public: + + ByteSkipper() : pBuf(NULL), nStage(0), countDown(0) { + }; + + void Initialize(MultiValueBuffer *pbuf) { + pBuf = (uint8_t*)pbuf->pValue; + countDown = 0; + }; + + bool Skip(uint8_t **pp, uint16_t *pcntdn, uint16_t bytes_to_skip) { + switch(nStage) { + case 0: + countDown = bytes_to_skip; + nStage++; + case 1: + for(; countDown && (*pcntdn); countDown--, (*pp)++, (*pcntdn)--); + + if(!countDown) + nStage = 0; + }; + return (!countDown); + }; +}; + +// Pointer to a callback function triggered for each element of PTP array when used with PTPArrayParser +typedef void (*PTP_ARRAY_EL_FUNC)(const MultiValueBuffer * const p, uint32_t count, const void *me); + +class PTPListParser { +public: + + enum ParseMode { + modeArray, modeRange/*, modeEnum*/ + }; + +private: + uint8_t nStage; + uint8_t enStage; + + uint32_t arLen; + uint32_t arLenCntdn; + + uint8_t lenSize; // size of the array length field in bytes + uint8_t valSize; // size of the array element in bytes + + MultiValueBuffer *pBuf; + + // The only parser for both size and array element parsing + MultiByteValueParser theParser; + + uint8_t /*ParseMode*/ prsMode; + +public: + + PTPListParser() : + nStage(0), + enStage(0), + arLen(0), + arLenCntdn(0), + lenSize(0), + valSize(0), + pBuf(NULL), + prsMode(modeArray) { + }; + + void Initialize(const uint8_t len_size, const uint8_t val_size, MultiValueBuffer * const p, const uint8_t mode = modeArray) { + pBuf = p; + lenSize = len_size; + valSize = val_size; + prsMode = mode; + + if(prsMode == modeRange) { + arLenCntdn = arLen = 3; + nStage = 2; + } else { + arLenCntdn = arLen = 0; + nStage = 0; + } + enStage = 0; + theParser.Initialize(p); + }; + + bool Parse(uint8_t **pp, uint16_t *pcntdn, PTP_ARRAY_EL_FUNC pf, const void *me = NULL); +}; + +#endif // __PARSETOOLS_H__ diff --git a/lib/usbhost/USB_Host_Shield_2.0/printhex.h b/lib/usbhost/USB_Host_Shield_2.0/printhex.h new file mode 100644 index 0000000000..369d7e1f7e --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/printhex.h @@ -0,0 +1,84 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ + +#if !defined(_usb_h_) || defined(__PRINTHEX_H__) +#error "Never include printhex.h directly; include Usb.h instead" +#else +#define __PRINTHEX_H__ + +void E_Notifyc(char c, int lvl); + +template +void PrintHex(T val, int lvl) { + int num_nibbles = sizeof (T) * 2; + + do { + char v = 48 + (((val >> (num_nibbles - 1) * 4)) & 0x0f); + if(v > 57) v += 7; + E_Notifyc(v, lvl); + } while(--num_nibbles); +} + +template +void PrintBin(T val, int lvl) { + for(T mask = (((T)1) << ((sizeof (T) << 3) - 1)); mask; mask >>= 1) + if(val & mask) + E_Notifyc('1', lvl); + else + E_Notifyc('0', lvl); +} + +template +void SerialPrintHex(T val) { + int num_nibbles = sizeof (T) * 2; + + do { + char v = 48 + (((val >> (num_nibbles - 1) * 4)) & 0x0f); + if(v > 57) v += 7; + USB_HOST_SERIAL.print(v); + } while(--num_nibbles); +} + +template +void PrintHex2(Print *prn, T val) { + T mask = (((T)1) << (((sizeof (T) << 1) - 1) << 2)); + + while(mask > 1) { + if(val < mask) + prn->print("0"); + + mask >>= 4; + } + prn->print((T)val, HEX); +} + +template void D_PrintHex(T val, int lvl) { +#ifdef DEBUG_USB_HOST + PrintHex (val, lvl); +#endif +} + +template +void D_PrintBin(T val, int lvl) { +#ifdef DEBUG_USB_HOST + PrintBin (val, lvl); +#endif +} + + + +#endif // __PRINTHEX_H__ diff --git a/lib/usbhost/USB_Host_Shield_2.0/settings.h b/lib/usbhost/USB_Host_Shield_2.0/settings.h new file mode 100644 index 0000000000..5c060354ba --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/settings.h @@ -0,0 +1,139 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ + +#ifndef USB_HOST_SHIELD_SETTINGS_H +#define USB_HOST_SHIELD_SETTINGS_H +#include "macros.h" + +//////////////////////////////////////////////////////////////////////////////// +// DEBUGGING +//////////////////////////////////////////////////////////////////////////////// + +/* Set this to 1 to activate serial debugging */ +#define ENABLE_UHS_DEBUGGING 0 + +/* This can be used to select which serial port to use for debugging if + * multiple serial ports are available. + * For example Serial3. + */ +#ifndef USB_HOST_SERIAL +#define USB_HOST_SERIAL Serial +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Manual board activation +//////////////////////////////////////////////////////////////////////////////// + +/* Set this to 1 if you are using an Arduino Mega ADK board with MAX3421e built-in */ +#define USE_UHS_MEGA_ADK 0 // If you are using Arduino 1.5.5 or newer there is no need to do this manually + +/* Set this to 1 if you are using a Black Widdow */ +#define USE_UHS_BLACK_WIDDOW 0 + +/* Set this to a one to use the xmem2 lock. This is needed for multitasking and threading */ +#define USE_XMEM_SPI_LOCK 0 + +//////////////////////////////////////////////////////////////////////////////// +// Wii IR camera +//////////////////////////////////////////////////////////////////////////////// + +/* Set this to 1 to activate code for the Wii IR camera */ +#define ENABLE_WII_IR_CAMERA 0 + +//////////////////////////////////////////////////////////////////////////////// +// MASS STORAGE +//////////////////////////////////////////////////////////////////////////////// +// <<<<<<<<<<<<<<<< IMPORTANT >>>>>>>>>>>>>>> +// Set this to 1 to support single LUN devices, and save RAM. -- I.E. thumb drives. +// Each LUN needs ~13 bytes to be able to track the state of each unit. +#ifndef MASS_MAX_SUPPORTED_LUN +#define MASS_MAX_SUPPORTED_LUN 8 +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Set to 1 to use the faster spi4teensy3 driver. +//////////////////////////////////////////////////////////////////////////////// +#ifndef USE_SPI4TEENSY3 +#define USE_SPI4TEENSY3 1 +#endif + +//////////////////////////////////////////////////////////////////////////////// +// AUTOMATIC Settings +//////////////////////////////////////////////////////////////////////////////// + +// No user serviceable parts below this line. +// DO NOT change anything below here unless you are a developer! + +#include "version_helper.h" + +#if defined(__GNUC__) && defined(__AVR__) +#ifndef GCC_VERSION +#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +#endif +#if GCC_VERSION < 40602 // Test for GCC < 4.6.2 +#ifdef PROGMEM +#undef PROGMEM +#define PROGMEM __attribute__((section(".progmem.data"))) // Workaround for http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34734#c4 +#ifdef PSTR +#undef PSTR +#define PSTR(s) (__extension__({static const char __c[] PROGMEM = (s); &__c[0];})) // Copied from pgmspace.h in avr-libc source +#endif +#endif +#endif +#endif + +#if !defined(DEBUG_USB_HOST) && ENABLE_UHS_DEBUGGING +#define DEBUG_USB_HOST +#endif + +#if !defined(WIICAMERA) && ENABLE_WII_IR_CAMERA +#define WIICAMERA +#endif + +// To use some other locking (e.g. freertos), +// define XMEM_ACQUIRE_SPI and XMEM_RELEASE_SPI to point to your lock and unlock. +// NOTE: NO argument is passed. You have to do this within your routine for +// whatever you are using to lock and unlock. +#if !defined(XMEM_ACQUIRE_SPI) +#if USE_XMEM_SPI_LOCK || defined(USE_MULTIPLE_APP_API) +#include +#else +#define XMEM_ACQUIRE_SPI() (void(0)) +#define XMEM_RELEASE_SPI() (void(0)) +#endif +#endif + +#if !defined(EXT_RAM) && defined(EXT_RAM_STACK) || defined(EXT_RAM_HEAP) +#include +#else +#define EXT_RAM 0 +#endif + +#if defined(CORE_TEENSY) && (defined(__MK20DX128__) || defined(__MK20DX256__)) +#define USING_SPI4TEENSY3 USE_SPI4TEENSY3 +#else +#define USING_SPI4TEENSY3 0 +#endif + +#if ((defined(ARDUINO_SAM_DUE) && defined(__SAM3X8E__)) || defined(RBL_NRF51822) || defined(__ARDUINO_X86__) || ARDUINO >= 10600) && !USING_SPI4TEENSY3 +#include // Use the Arduino SPI library for the Arduino Due, RedBearLab nRF51822, Intel Galileo 1 & 2, Intel Edison or if the SPI library with transaction is available +#endif +#if defined(__PIC32MX__) || defined(__PIC32MZ__) +#include <../../../../hardware/pic32/libraries/SPI/SPI.h> // Hack to use the SPI library +#endif + +#endif /* SETTINGS_H */ diff --git a/lib/usbhost/USB_Host_Shield_2.0/sink_parser.h b/lib/usbhost/USB_Host_Shield_2.0/sink_parser.h new file mode 100644 index 0000000000..a23637d2b7 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/sink_parser.h @@ -0,0 +1,41 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#if !defined(_usb_h_) || defined(__SINK_PARSER_H__) +#error "Never include hexdump.h directly; include Usb.h instead" +#else +#define __SINK_PARSER_H__ + +extern int UsbDEBUGlvl; + +// This parser does absolutely nothing with the data, just swallows it. + +template +class SinkParser : public BASE_CLASS { +public: + + SinkParser() { + }; + + void Initialize() { + }; + + void Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset) { + }; +}; + + +#endif // __HEXDUMP_H__ diff --git a/lib/usbhost/USB_Host_Shield_2.0/usb_ch9.h b/lib/usbhost/USB_Host_Shield_2.0/usb_ch9.h new file mode 100644 index 0000000000..18f2d3e2e5 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/usb_ch9.h @@ -0,0 +1,166 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ + +#if !defined(_usb_h_) || defined(_ch9_h_) +#error "Never include usb_ch9.h directly; include Usb.h instead" +#else + +/* USB chapter 9 structures */ +#define _ch9_h_ + +/* Misc.USB constants */ +#define DEV_DESCR_LEN 18 //device descriptor length +#define CONF_DESCR_LEN 9 //configuration descriptor length +#define INTR_DESCR_LEN 9 //interface descriptor length +#define EP_DESCR_LEN 7 //endpoint descriptor length + +/* Standard Device Requests */ + +#define USB_REQUEST_GET_STATUS 0 // Standard Device Request - GET STATUS +#define USB_REQUEST_CLEAR_FEATURE 1 // Standard Device Request - CLEAR FEATURE +#define USB_REQUEST_SET_FEATURE 3 // Standard Device Request - SET FEATURE +#define USB_REQUEST_SET_ADDRESS 5 // Standard Device Request - SET ADDRESS +#define USB_REQUEST_GET_DESCRIPTOR 6 // Standard Device Request - GET DESCRIPTOR +#define USB_REQUEST_SET_DESCRIPTOR 7 // Standard Device Request - SET DESCRIPTOR +#define USB_REQUEST_GET_CONFIGURATION 8 // Standard Device Request - GET CONFIGURATION +#define USB_REQUEST_SET_CONFIGURATION 9 // Standard Device Request - SET CONFIGURATION +#define USB_REQUEST_GET_INTERFACE 10 // Standard Device Request - GET INTERFACE +#define USB_REQUEST_SET_INTERFACE 11 // Standard Device Request - SET INTERFACE +#define USB_REQUEST_SYNCH_FRAME 12 // Standard Device Request - SYNCH FRAME + +#define USB_FEATURE_ENDPOINT_HALT 0 // CLEAR/SET FEATURE - Endpoint Halt +#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 // CLEAR/SET FEATURE - Device remote wake-up +#define USB_FEATURE_TEST_MODE 2 // CLEAR/SET FEATURE - Test mode + +/* Setup Data Constants */ + +#define USB_SETUP_HOST_TO_DEVICE 0x00 // Device Request bmRequestType transfer direction - host to device transfer +#define USB_SETUP_DEVICE_TO_HOST 0x80 // Device Request bmRequestType transfer direction - device to host transfer +#define USB_SETUP_TYPE_STANDARD 0x00 // Device Request bmRequestType type - standard +#define USB_SETUP_TYPE_CLASS 0x20 // Device Request bmRequestType type - class +#define USB_SETUP_TYPE_VENDOR 0x40 // Device Request bmRequestType type - vendor +#define USB_SETUP_RECIPIENT_DEVICE 0x00 // Device Request bmRequestType recipient - device +#define USB_SETUP_RECIPIENT_INTERFACE 0x01 // Device Request bmRequestType recipient - interface +#define USB_SETUP_RECIPIENT_ENDPOINT 0x02 // Device Request bmRequestType recipient - endpoint +#define USB_SETUP_RECIPIENT_OTHER 0x03 // Device Request bmRequestType recipient - other + +/* USB descriptors */ + +#define USB_DESCRIPTOR_DEVICE 0x01 // bDescriptorType for a Device Descriptor. +#define USB_DESCRIPTOR_CONFIGURATION 0x02 // bDescriptorType for a Configuration Descriptor. +#define USB_DESCRIPTOR_STRING 0x03 // bDescriptorType for a String Descriptor. +#define USB_DESCRIPTOR_INTERFACE 0x04 // bDescriptorType for an Interface Descriptor. +#define USB_DESCRIPTOR_ENDPOINT 0x05 // bDescriptorType for an Endpoint Descriptor. +#define USB_DESCRIPTOR_DEVICE_QUALIFIER 0x06 // bDescriptorType for a Device Qualifier. +#define USB_DESCRIPTOR_OTHER_SPEED 0x07 // bDescriptorType for a Other Speed Configuration. +#define USB_DESCRIPTOR_INTERFACE_POWER 0x08 // bDescriptorType for Interface Power. +#define USB_DESCRIPTOR_OTG 0x09 // bDescriptorType for an OTG Descriptor. + +#define HID_DESCRIPTOR_HID 0x21 + + + +/* OTG SET FEATURE Constants */ +#define OTG_FEATURE_B_HNP_ENABLE 3 // SET FEATURE OTG - Enable B device to perform HNP +#define OTG_FEATURE_A_HNP_SUPPORT 4 // SET FEATURE OTG - A device supports HNP +#define OTG_FEATURE_A_ALT_HNP_SUPPORT 5 // SET FEATURE OTG - Another port on the A device supports HNP + +/* USB Endpoint Transfer Types */ +#define USB_TRANSFER_TYPE_CONTROL 0x00 // Endpoint is a control endpoint. +#define USB_TRANSFER_TYPE_ISOCHRONOUS 0x01 // Endpoint is an isochronous endpoint. +#define USB_TRANSFER_TYPE_BULK 0x02 // Endpoint is a bulk endpoint. +#define USB_TRANSFER_TYPE_INTERRUPT 0x03 // Endpoint is an interrupt endpoint. +#define bmUSB_TRANSFER_TYPE 0x03 // bit mask to separate transfer type from ISO attributes + + +/* Standard Feature Selectors for CLEAR_FEATURE Requests */ +#define USB_FEATURE_ENDPOINT_STALL 0 // Endpoint recipient +#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 // Device recipient +#define USB_FEATURE_TEST_MODE 2 // Device recipient + +/* descriptor data structures */ + +/* Device descriptor structure */ +typedef struct { + uint8_t bLength; // Length of this descriptor. + uint8_t bDescriptorType; // DEVICE descriptor type (USB_DESCRIPTOR_DEVICE). + uint16_t bcdUSB; // USB Spec Release Number (BCD). + uint8_t bDeviceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific. + uint8_t bDeviceSubClass; // Subclass code (assigned by the USB-IF). + uint8_t bDeviceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific. + uint8_t bMaxPacketSize0; // Maximum packet size for endpoint 0. + uint16_t idVendor; // Vendor ID (assigned by the USB-IF). + uint16_t idProduct; // Product ID (assigned by the manufacturer). + uint16_t bcdDevice; // Device release number (BCD). + uint8_t iManufacturer; // Index of String Descriptor describing the manufacturer. + uint8_t iProduct; // Index of String Descriptor describing the product. + uint8_t iSerialNumber; // Index of String Descriptor with the device's serial number. + uint8_t bNumConfigurations; // Number of possible configurations. +} __attribute__((packed)) USB_DEVICE_DESCRIPTOR; + +/* Configuration descriptor structure */ +typedef struct { + uint8_t bLength; // Length of this descriptor. + uint8_t bDescriptorType; // CONFIGURATION descriptor type (USB_DESCRIPTOR_CONFIGURATION). + uint16_t wTotalLength; // Total length of all descriptors for this configuration. + uint8_t bNumInterfaces; // Number of interfaces in this configuration. + uint8_t bConfigurationValue; // Value of this configuration (1 based). + uint8_t iConfiguration; // Index of String Descriptor describing the configuration. + uint8_t bmAttributes; // Configuration characteristics. + uint8_t bMaxPower; // Maximum power consumed by this configuration. +} __attribute__((packed)) USB_CONFIGURATION_DESCRIPTOR; + +/* Interface descriptor structure */ +typedef struct { + uint8_t bLength; // Length of this descriptor. + uint8_t bDescriptorType; // INTERFACE descriptor type (USB_DESCRIPTOR_INTERFACE). + uint8_t bInterfaceNumber; // Number of this interface (0 based). + uint8_t bAlternateSetting; // Value of this alternate interface setting. + uint8_t bNumEndpoints; // Number of endpoints in this interface. + uint8_t bInterfaceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific. + uint8_t bInterfaceSubClass; // Subclass code (assigned by the USB-IF). + uint8_t bInterfaceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific. + uint8_t iInterface; // Index of String Descriptor describing the interface. +} __attribute__((packed)) USB_INTERFACE_DESCRIPTOR; + +/* Endpoint descriptor structure */ +typedef struct { + uint8_t bLength; // Length of this descriptor. + uint8_t bDescriptorType; // ENDPOINT descriptor type (USB_DESCRIPTOR_ENDPOINT). + uint8_t bEndpointAddress; // Endpoint address. Bit 7 indicates direction (0=OUT, 1=IN). + uint8_t bmAttributes; // Endpoint transfer type. + uint16_t wMaxPacketSize; // Maximum packet size. + uint8_t bInterval; // Polling interval in frames. +} __attribute__((packed)) USB_ENDPOINT_DESCRIPTOR; + +/* HID descriptor */ +typedef struct { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdHID; // HID class specification release + uint8_t bCountryCode; + uint8_t bNumDescriptors; // Number of additional class specific descriptors + uint8_t bDescrType; // Type of class descriptor + uint16_t wDescriptorLength; // Total size of the Report descriptor +} __attribute__((packed)) USB_HID_DESCRIPTOR; + +typedef struct { + uint8_t bDescrType; // Type of class descriptor + uint16_t wDescriptorLength; // Total size of the Report descriptor +} __attribute__((packed)) HID_CLASS_DESCRIPTOR_LEN_AND_TYPE; + +#endif // _ch9_h_ diff --git a/lib/usbhost/USB_Host_Shield_2.0/usbhost.h b/lib/usbhost/USB_Host_Shield_2.0/usbhost.h new file mode 100644 index 0000000000..eba480e60c --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/usbhost.h @@ -0,0 +1,529 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +/* MAX3421E-based USB Host Library header file */ + + +#if !defined(_usb_h_) || defined(_USBHOST_H_) +#error "Never include usbhost.h directly; include Usb.h instead" +#else +#define _USBHOST_H_ + +#if USING_SPI4TEENSY3 +#include +#include +#endif + +/* SPI initialization */ +template< typename SPI_CLK, typename SPI_MOSI, typename SPI_MISO, typename SPI_SS > class SPi { +public: +#if USING_SPI4TEENSY3 + static void init() { + // spi4teensy3 inits everything for us, except /SS + // CLK, MOSI and MISO are hard coded for now. + // spi4teensy3::init(0,0,0); // full speed, cpol 0, cpha 0 + spi4teensy3::init(); // full speed, cpol 0, cpha 0 + SPI_SS::SetDirWrite(); + SPI_SS::Set(); + } +#elif SPI_HAS_TRANSACTION + static void init() { + SPI.begin(); // The SPI library with transaction will take care of setting up the pins - settings is set in beginTransaction() + } +#elif !defined(SPDR) + static void init() { + SPI_SS::SetDirWrite(); + SPI_SS::Set(); + SPI.begin(); +#if defined(__MIPSEL__) + SPI.setClockDivider(1); +#elif defined(__ARDUINO_X86__) + #ifdef SPI_CLOCK_1M // Hack used to check if setClockSpeed is available + SPI.setClockSpeed(12000000); // The MAX3421E can handle up to 26MHz, but in practice this was the maximum that I could reliably use + #else + SPI.setClockDivider(SPI_CLOCK_DIV2); // This will set the SPI frequency to 8MHz - it could be higher, but it is not supported in the old API + #endif +#else + SPI.setClockDivider(4); // Set speed to 84MHz/4=21MHz - the MAX3421E can handle up to 26MHz +#endif + } +#elif defined(RBL_NRF51822) + static void init() { + SPI_SS::SetDirWrite(); + SPI_SS::Set(); + SPI.begin(); + // SPI.setFrequency(SPI_FREQUENCY_8M); + } +#else + static void init() { + //uint8_t tmp; + SPI_CLK::SetDirWrite(); + SPI_MOSI::SetDirWrite(); + SPI_MISO::SetDirRead(); + SPI_SS::SetDirWrite(); + /* mode 00 (CPOL=0, CPHA=0) master, fclk/2. Mode 11 (CPOL=11, CPHA=11) is also supported by MAX3421E */ + SPCR = 0x50; + SPSR = 0x01; // 0x01 + /**/ + //tmp = SPSR; + //tmp = SPDR; + } +#endif +}; + +/* SPI pin definitions. see avrpins.h */ +#if defined(__AVR_ATmega1280__) || (__AVR_ATmega2560__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) +typedef SPi< Pb1, Pb2, Pb3, Pb0 > spi; +#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) +typedef SPi< Pb5, Pb3, Pb4, Pb2 > spi; +#elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) +typedef SPi< Pb7, Pb5, Pb6, Pb4 > spi; +#elif (defined(CORE_TEENSY) && (defined(__MK20DX128__) || defined(__MK20DX256__))) || defined(__ARDUINO_X86__) || defined(__MIPSEL__) +typedef SPi< P13, P11, P12, P10 > spi; +#elif defined(ARDUINO_SAM_DUE) && defined(__SAM3X8E__) +typedef SPi< P76, P75, P74, P10 > spi; +#elif defined(RBL_NRF51822) +typedef SPi< P16, P18, P17, P10 > spi; +#else +#error "No SPI entry in usbhost.h" +#endif + +typedef enum { + vbus_on = 0, + vbus_off = GPX_VBDET +} VBUS_t; + +template< typename SPI_SS, typename INTR > class MAX3421e /* : public spi */ { + static uint8_t vbusState; + +public: + MAX3421e(); + void regWr(uint8_t reg, uint8_t data); + uint8_t* bytesWr(uint8_t reg, uint8_t nbytes, uint8_t* data_p); + void gpioWr(uint8_t data); + uint8_t regRd(uint8_t reg); + uint8_t* bytesRd(uint8_t reg, uint8_t nbytes, uint8_t* data_p); + uint8_t gpioRd(); + uint16_t reset(); + int8_t Init(); + int8_t Init(int mseconds); + + void vbusPower(VBUS_t state) { + regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL | state)); + } + + uint8_t getVbusState(void) { + return vbusState; + }; + void busprobe(); + uint8_t GpxHandler(); + uint8_t IntHandler(); + uint8_t Task(); +}; + +template< typename SPI_SS, typename INTR > + uint8_t MAX3421e< SPI_SS, INTR >::vbusState = 0; + +/* constructor */ +template< typename SPI_SS, typename INTR > +MAX3421e< SPI_SS, INTR >::MAX3421e() { + // Leaving ADK hardware setup in here, for now. This really belongs with the other parts. +#ifdef BOARD_MEGA_ADK + // For Mega ADK, which has a Max3421e on-board, set MAX_RESET to output mode, and then set it to HIGH + P55::SetDirWrite(); + P55::Set(); +#endif +}; + +/* write single byte into MAX3421 register */ +template< typename SPI_SS, typename INTR > +void MAX3421e< SPI_SS, INTR >::regWr(uint8_t reg, uint8_t data) { + XMEM_ACQUIRE_SPI(); +#if SPI_HAS_TRANSACTION + SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0 +#endif + SPI_SS::Clear(); + +#if USING_SPI4TEENSY3 + uint8_t c[2]; + c[0] = reg | 0x02; + c[1] = data; + spi4teensy3::send(c, 2); +#elif SPI_HAS_TRANSACTION + uint8_t c[2]; + c[0] = reg | 0x02; + c[1] = data; + SPI.transfer(c, 2); +#elif !defined(SPDR) + SPI.transfer(reg | 0x02); + SPI.transfer(data); +#else + SPDR = (reg | 0x02); + while(!(SPSR & (1 << SPIF))); + SPDR = data; + while(!(SPSR & (1 << SPIF))); +#endif + + SPI_SS::Set(); +#if SPI_HAS_TRANSACTION + SPI.endTransaction(); +#endif + XMEM_RELEASE_SPI(); + return; +}; +/* multiple-byte write */ + +/* returns a pointer to memory position after last written */ +template< typename SPI_SS, typename INTR > +uint8_t* MAX3421e< SPI_SS, INTR >::bytesWr(uint8_t reg, uint8_t nbytes, uint8_t* data_p) { + XMEM_ACQUIRE_SPI(); +#if SPI_HAS_TRANSACTION + SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0 +#endif + SPI_SS::Clear(); + +#if USING_SPI4TEENSY3 + spi4teensy3::send(reg | 0x02); + spi4teensy3::send(data_p, nbytes); + data_p += nbytes; +#elif SPI_HAS_TRANSACTION + SPI.transfer(reg | 0x02); + SPI.transfer(data_p, nbytes); + data_p += nbytes; +#elif defined(__ARDUINO_X86__) + SPI.transfer(reg | 0x02); + SPI.transferBuffer(data_p, NULL, nbytes); + data_p += nbytes; +#elif !defined(SPDR) + SPI.transfer(reg | 0x02); + while(nbytes) { + SPI.transfer(*data_p); + nbytes--; + data_p++; // advance data pointer + } +#else + SPDR = (reg | 0x02); //set WR bit and send register number + while(nbytes) { + while(!(SPSR & (1 << SPIF))); //check if previous byte was sent + SPDR = (*data_p); // send next data byte + nbytes--; + data_p++; // advance data pointer + } + while(!(SPSR & (1 << SPIF))); +#endif + + SPI_SS::Set(); +#if SPI_HAS_TRANSACTION + SPI.endTransaction(); +#endif + XMEM_RELEASE_SPI(); + return ( data_p); +} +/* GPIO write */ +/*GPIO byte is split between 2 registers, so two writes are needed to write one byte */ + +/* GPOUT bits are in the low nibble. 0-3 in IOPINS1, 4-7 in IOPINS2 */ +template< typename SPI_SS, typename INTR > +void MAX3421e< SPI_SS, INTR >::gpioWr(uint8_t data) { + regWr(rIOPINS1, data); + data >>= 4; + regWr(rIOPINS2, data); + return; +} + +/* single host register read */ +template< typename SPI_SS, typename INTR > +uint8_t MAX3421e< SPI_SS, INTR >::regRd(uint8_t reg) { + XMEM_ACQUIRE_SPI(); +#if SPI_HAS_TRANSACTION + SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0 +#endif + SPI_SS::Clear(); + +#if USING_SPI4TEENSY3 + spi4teensy3::send(reg); + uint8_t rv = spi4teensy3::receive(); + SPI_SS::Set(); +#elif !defined(SPDR) || SPI_HAS_TRANSACTION + SPI.transfer(reg); + uint8_t rv = SPI.transfer(0); // Send empty byte + SPI_SS::Set(); +#else + SPDR = reg; + while(!(SPSR & (1 << SPIF))); + SPDR = 0; // Send empty byte + while(!(SPSR & (1 << SPIF))); + SPI_SS::Set(); + uint8_t rv = SPDR; +#endif + +#if SPI_HAS_TRANSACTION + SPI.endTransaction(); +#endif + XMEM_RELEASE_SPI(); + return (rv); +} +/* multiple-byte register read */ + +/* returns a pointer to a memory position after last read */ +template< typename SPI_SS, typename INTR > +uint8_t* MAX3421e< SPI_SS, INTR >::bytesRd(uint8_t reg, uint8_t nbytes, uint8_t* data_p) { + XMEM_ACQUIRE_SPI(); +#if SPI_HAS_TRANSACTION + SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0 +#endif + SPI_SS::Clear(); + +#if USING_SPI4TEENSY3 + spi4teensy3::send(reg); + spi4teensy3::receive(data_p, nbytes); + data_p += nbytes; +#elif SPI_HAS_TRANSACTION + SPI.transfer(reg); + memset(data_p, 0, nbytes); // Make sure we send out empty bytes + SPI.transfer(data_p, nbytes); + data_p += nbytes; +#elif defined(__ARDUINO_X86__) + SPI.transfer(reg); + SPI.transferBuffer(NULL, data_p, nbytes); + data_p += nbytes; +#elif !defined(SPDR) + SPI.transfer(reg); + while(nbytes) { + *data_p++ = SPI.transfer(0); + nbytes--; + } +#else + SPDR = reg; + while(!(SPSR & (1 << SPIF))); //wait + while(nbytes) { + SPDR = 0; // Send empty byte + nbytes--; + while(!(SPSR & (1 << SPIF))); +#if 0 + { + *data_p = SPDR; + printf("%2.2x ", *data_p); + } + data_p++; + } + printf("\r\n"); +#else + *data_p++ = SPDR; + } +#endif +#endif + + SPI_SS::Set(); +#if SPI_HAS_TRANSACTION + SPI.endTransaction(); +#endif + XMEM_RELEASE_SPI(); + return ( data_p); +} +/* GPIO read. See gpioWr for explanation */ + +/* GPIN pins are in high nibbles of IOPINS1, IOPINS2 */ +template< typename SPI_SS, typename INTR > +uint8_t MAX3421e< SPI_SS, INTR >::gpioRd() { + uint8_t gpin = 0; + gpin = regRd(rIOPINS2); //pins 4-7 + gpin &= 0xf0; //clean lower nibble + gpin |= (regRd(rIOPINS1) >> 4); //shift low bits and OR with upper from previous operation. + return ( gpin); +} + +/* reset MAX3421E. Returns number of cycles it took for PLL to stabilize after reset + or zero if PLL haven't stabilized in 65535 cycles */ +template< typename SPI_SS, typename INTR > +uint16_t MAX3421e< SPI_SS, INTR >::reset() { + uint16_t i = 0; + regWr(rUSBCTL, bmCHIPRES); + regWr(rUSBCTL, 0x00); + while(++i) { + if((regRd(rUSBIRQ) & bmOSCOKIRQ)) { + break; + } + } + return ( i); +} + +/* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */ +template< typename SPI_SS, typename INTR > +int8_t MAX3421e< SPI_SS, INTR >::Init() { + XMEM_ACQUIRE_SPI(); + // Moved here. + // you really should not init hardware in the constructor when it involves locks. + // Also avoids the vbus flicker issue confusing some devices. + /* pin and peripheral setup */ + SPI_SS::SetDirWrite(); + SPI_SS::Set(); + spi::init(); + INTR::SetDirRead(); + XMEM_RELEASE_SPI(); + /* MAX3421E - full-duplex SPI, level interrupt */ + // GPX pin on. Moved here, otherwise we flicker the vbus. + regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL)); + + if(reset() == 0) { //OSCOKIRQ hasn't asserted in time + return ( -1); + } + + regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST); // set pull-downs, Host + + regWr(rHIEN, bmCONDETIE | bmFRAMEIE); //connection detection + + /* check if device is connected */ + regWr(rHCTL, bmSAMPLEBUS); // sample USB bus + while(!(regRd(rHCTL) & bmSAMPLEBUS)); //wait for sample operation to finish + + busprobe(); //check if anything is connected + + regWr(rHIRQ, bmCONDETIRQ); //clear connection detect interrupt + regWr(rCPUCTL, 0x01); //enable interrupt pin + + return ( 0); +} + +/* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */ +template< typename SPI_SS, typename INTR > +int8_t MAX3421e< SPI_SS, INTR >::Init(int mseconds) { + XMEM_ACQUIRE_SPI(); + // Moved here. + // you really should not init hardware in the constructor when it involves locks. + // Also avoids the vbus flicker issue confusing some devices. + /* pin and peripheral setup */ + SPI_SS::SetDirWrite(); + SPI_SS::Set(); + spi::init(); + INTR::SetDirRead(); + XMEM_RELEASE_SPI(); + /* MAX3421E - full-duplex SPI, level interrupt, vbus off */ + regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL | GPX_VBDET)); + + if(reset() == 0) { //OSCOKIRQ hasn't asserted in time + return ( -1); + } + + // Delay a minimum of 1 second to ensure any capacitors are drained. + // 1 second is required to make sure we do not smoke a Microdrive! + if(mseconds < 1000) mseconds = 1000; + delay(mseconds); + + regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST); // set pull-downs, Host + + regWr(rHIEN, bmCONDETIE | bmFRAMEIE); //connection detection + + /* check if device is connected */ + regWr(rHCTL, bmSAMPLEBUS); // sample USB bus + while(!(regRd(rHCTL) & bmSAMPLEBUS)); //wait for sample operation to finish + + busprobe(); //check if anything is connected + + regWr(rHIRQ, bmCONDETIRQ); //clear connection detect interrupt + regWr(rCPUCTL, 0x01); //enable interrupt pin + + // GPX pin on. This is done here so that busprobe will fail if we have a switch connected. + regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL)); + + return ( 0); +} + +/* probe bus to determine device presence and speed and switch host to this speed */ +template< typename SPI_SS, typename INTR > +void MAX3421e< SPI_SS, INTR >::busprobe() { + uint8_t bus_sample; + bus_sample = regRd(rHRSL); //Get J,K status + bus_sample &= (bmJSTATUS | bmKSTATUS); //zero the rest of the byte + switch(bus_sample) { //start full-speed or low-speed host + case( bmJSTATUS): + if((regRd(rMODE) & bmLOWSPEED) == 0) { + regWr(rMODE, MODE_FS_HOST); //start full-speed host + vbusState = FSHOST; + } else { + regWr(rMODE, MODE_LS_HOST); //start low-speed host + vbusState = LSHOST; + } + break; + case( bmKSTATUS): + if((regRd(rMODE) & bmLOWSPEED) == 0) { + regWr(rMODE, MODE_LS_HOST); //start low-speed host + vbusState = LSHOST; + } else { + regWr(rMODE, MODE_FS_HOST); //start full-speed host + vbusState = FSHOST; + } + break; + case( bmSE1): //illegal state + vbusState = SE1; + break; + case( bmSE0): //disconnected state + regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST | bmSEPIRQ); + vbusState = SE0; + break; + }//end switch( bus_sample ) +} + +/* MAX3421 state change task and interrupt handler */ +template< typename SPI_SS, typename INTR > +uint8_t MAX3421e< SPI_SS, INTR >::Task(void) { + uint8_t rcode = 0; + uint8_t pinvalue; + //USB_HOST_SERIAL.print("Vbus state: "); + //USB_HOST_SERIAL.println( vbusState, HEX ); + pinvalue = INTR::IsSet(); //Read(); + //pinvalue = digitalRead( MAX_INT ); + if(pinvalue == 0) { + rcode = IntHandler(); + } + // pinvalue = digitalRead( MAX_GPX ); + // if( pinvalue == LOW ) { + // GpxHandler(); + // } + // usbSM(); //USB state machine + return ( rcode); +} + +template< typename SPI_SS, typename INTR > +uint8_t MAX3421e< SPI_SS, INTR >::IntHandler() { + uint8_t HIRQ; + uint8_t HIRQ_sendback = 0x00; + HIRQ = regRd(rHIRQ); //determine interrupt source + //if( HIRQ & bmFRAMEIRQ ) { //->1ms SOF interrupt handler + // HIRQ_sendback |= bmFRAMEIRQ; + //}//end FRAMEIRQ handling + if(HIRQ & bmCONDETIRQ) { + busprobe(); + HIRQ_sendback |= bmCONDETIRQ; + } + /* End HIRQ interrupts handling, clear serviced IRQs */ + regWr(rHIRQ, HIRQ_sendback); + return ( HIRQ_sendback); +} +//template< typename SPI_SS, typename INTR > +//uint8_t MAX3421e< SPI_SS, INTR >::GpxHandler() +//{ +// uint8_t GPINIRQ = regRd( rGPINIRQ ); //read GPIN IRQ register +//// if( GPINIRQ & bmGPINIRQ7 ) { //vbus overload +//// vbusPwr( OFF ); //attempt powercycle +//// delay( 1000 ); +//// vbusPwr( ON ); +//// regWr( rGPINIRQ, bmGPINIRQ7 ); +//// } +// return( GPINIRQ ); +//} + +#endif // _USBHOST_H_ diff --git a/lib/usbhost/USB_Host_Shield_2.0/usbhub.cpp b/lib/usbhost/USB_Host_Shield_2.0/usbhub.cpp new file mode 100644 index 0000000000..7fed48e781 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/usbhub.cpp @@ -0,0 +1,425 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#include "usbhub.h" + +bool USBHub::bResetInitiated = false; + +USBHub::USBHub(USB *p) : +pUsb(p), +bAddress(0), +bNbrPorts(0), +//bInitState(0), +qNextPollTime(0), +bPollEnable(false) { + epInfo[0].epAddr = 0; + epInfo[0].maxPktSize = 8; + epInfo[0].epAttribs = 0; + epInfo[0].bmNakPower = USB_NAK_MAX_POWER; + + epInfo[1].epAddr = 1; + epInfo[1].maxPktSize = 8; //kludge + epInfo[1].epAttribs = 0; + epInfo[1].bmNakPower = USB_NAK_NOWAIT; + + if(pUsb) + pUsb->RegisterDeviceClass(this); +} + +uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed) { + uint8_t buf[32]; + USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); + HubDescriptor* hd = reinterpret_cast(buf); + USB_CONFIGURATION_DESCRIPTOR * ucd = reinterpret_cast(buf); + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + uint8_t len = 0; + uint16_t cd_len = 0; + + //USBTRACE("\r\nHub Init Start "); + //D_PrintHex (bInitState, 0x80); + + AddressPool &addrPool = pUsb->GetAddressPool(); + + //switch (bInitState) { + // case 0: + if(bAddress) + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; + + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); + + if(!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + if(!p->epinfo) + return USB_ERROR_EPINFO_IS_NULL; + + // Save old pointer to EP_RECORD of address 0 + oldep_ptr = p->epinfo; + + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence + p->epinfo = epInfo; + + p->lowspeed = lowspeed; + + // Get device descriptor + rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*)buf); + + p->lowspeed = false; + + if(!rcode) + len = (buf[0] > 32) ? 32 : buf[0]; + + if(rcode) { + // Restore p->epinfo + p->epinfo = oldep_ptr; + return rcode; + } + + // Extract device class from device descriptor + // If device class is not a hub return + if(udd->bDeviceClass != 0x09) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, (udd->bDeviceClass == 0x09) ? true : false, port); + + if(!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + // Extract Max Packet Size from the device descriptor + epInfo[0].maxPktSize = udd->bMaxPacketSize0; + + // Assign new address to the device + rcode = pUsb->setAddr(0, 0, bAddress); + + if(rcode) { + // Restore p->epinfo + p->epinfo = oldep_ptr; + addrPool.FreeAddress(bAddress); + bAddress = 0; + return rcode; + } + + //USBTRACE2("\r\nHub address: ", bAddress ); + + // Restore p->epinfo + p->epinfo = oldep_ptr; + + if(len) + rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf); + + if(rcode) + goto FailGetDevDescr; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, 2, epInfo); + + if(rcode) + goto FailSetDevTblEntry; + + // bInitState = 1; + + // case 1: + // Get hub descriptor + rcode = GetHubDescriptor(0, 8, buf); + + if(rcode) + goto FailGetHubDescr; + + // Save number of ports for future use + bNbrPorts = hd->bNbrPorts; + + // bInitState = 2; + + // case 2: + // Read configuration Descriptor in Order To Obtain Proper Configuration Value + rcode = pUsb->getConfDescr(bAddress, 0, 8, 0, buf); + + if(!rcode) { + cd_len = ucd->wTotalLength; + rcode = pUsb->getConfDescr(bAddress, 0, cd_len, 0, buf); + } + if(rcode) + goto FailGetConfDescr; + + // The following code is of no practical use in real life applications. + // It only intended for the usb protocol sniffer to properly parse hub-class requests. + { + uint8_t buf2[24]; + + rcode = pUsb->getConfDescr(bAddress, 0, buf[0], 0, buf2); + + if(rcode) + goto FailGetConfDescr; + } + + // Set Configuration Value + rcode = pUsb->setConf(bAddress, 0, buf[5]); + + if(rcode) + goto FailSetConfDescr; + + // bInitState = 3; + + // case 3: + // Power on all ports + for(uint8_t j = 1; j <= bNbrPorts; j++) + SetPortFeature(HUB_FEATURE_PORT_POWER, j, 0); //HubPortPowerOn(j); + + pUsb->SetHubPreMask(); + bPollEnable = true; + // bInitState = 0; + //} + //bInitState = 0; + //USBTRACE("...OK\r\n"); + return 0; + + // Oleg, No debugging?? -- xxxajk +FailGetDevDescr: + goto Fail; + +FailSetDevTblEntry: + goto Fail; + +FailGetHubDescr: + goto Fail; + +FailGetConfDescr: + goto Fail; + +FailSetConfDescr: + goto Fail; + +Fail: + USBTRACE("...FAIL\r\n"); + return rcode; +} + +uint8_t USBHub::Release() { + pUsb->GetAddressPool().FreeAddress(bAddress); + + if(bAddress == 0x41) + pUsb->SetHubPreMask(); + + bAddress = 0; + bNbrPorts = 0; + qNextPollTime = 0; + bPollEnable = false; + return 0; +} + +uint8_t USBHub::Poll() { + uint8_t rcode = 0; + + if(!bPollEnable) + return 0; + + if(((long)(millis() - qNextPollTime) >= 0L)) { + rcode = CheckHubStatus(); + qNextPollTime = millis() + 100; + } + return rcode; +} + +uint8_t USBHub::CheckHubStatus() { + uint8_t rcode; + uint8_t buf[8]; + uint16_t read = 1; + + rcode = pUsb->inTransfer(bAddress, 1, &read, buf); + + if(rcode) + return rcode; + + //if (buf[0] & 0x01) // Hub Status Change + //{ + // pUsb->PrintHubStatus(addr); + // rcode = GetHubStatus(1, 0, 1, 4, buf); + // if (rcode) + // { + // USB_HOST_SERIAL.print("GetHubStatus Error"); + // USB_HOST_SERIAL.println(rcode, HEX); + // return rcode; + // } + //} + for(uint8_t port = 1, mask = 0x02; port < 8; mask <<= 1, port++) { + if(buf[0] & mask) { + HubEvent evt; + evt.bmEvent = 0; + + rcode = GetPortStatus(port, 4, evt.evtBuff); + + if(rcode) + continue; + + rcode = PortStatusChange(port, evt); + + if(rcode == HUB_ERROR_PORT_HAS_BEEN_RESET) + return 0; + + if(rcode) + return rcode; + } + } // for + + for(uint8_t port = 1; port <= bNbrPorts; port++) { + HubEvent evt; + evt.bmEvent = 0; + + rcode = GetPortStatus(port, 4, evt.evtBuff); + + if(rcode) + continue; + + if((evt.bmStatus & bmHUB_PORT_STATE_CHECK_DISABLED) != bmHUB_PORT_STATE_DISABLED) + continue; + + // Emulate connection event for the port + evt.bmChange |= bmHUB_PORT_STATUS_C_PORT_CONNECTION; + + rcode = PortStatusChange(port, evt); + + if(rcode == HUB_ERROR_PORT_HAS_BEEN_RESET) + return 0; + + if(rcode) + return rcode; + } // for + return 0; +} + +void USBHub::ResetHubPort(uint8_t port) { + HubEvent evt; + evt.bmEvent = 0; + uint8_t rcode; + + ClearPortFeature(HUB_FEATURE_C_PORT_ENABLE, port, 0); + ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0); + SetPortFeature(HUB_FEATURE_PORT_RESET, port, 0); + + + for(int i = 0; i < 3; i++) { + rcode = GetPortStatus(port, 4, evt.evtBuff); + if(rcode) break; // Some kind of error, bail. + if(evt.bmEvent == bmHUB_PORT_EVENT_RESET_COMPLETE || evt.bmEvent == bmHUB_PORT_EVENT_LS_RESET_COMPLETE) { + break; + } + delay(100); // simulate polling. + } + ClearPortFeature(HUB_FEATURE_C_PORT_RESET, port, 0); + ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0); + delay(20); +} + +uint8_t USBHub::PortStatusChange(uint8_t port, HubEvent &evt) { + switch(evt.bmEvent) { + // Device connected event + case bmHUB_PORT_EVENT_CONNECT: + case bmHUB_PORT_EVENT_LS_CONNECT: + if(bResetInitiated) + return 0; + + ClearPortFeature(HUB_FEATURE_C_PORT_ENABLE, port, 0); + ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0); + SetPortFeature(HUB_FEATURE_PORT_RESET, port, 0); + bResetInitiated = true; + return HUB_ERROR_PORT_HAS_BEEN_RESET; + + // Device disconnected event + case bmHUB_PORT_EVENT_DISCONNECT: + ClearPortFeature(HUB_FEATURE_C_PORT_ENABLE, port, 0); + ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0); + bResetInitiated = false; + + UsbDeviceAddress a; + a.devAddress = 0; + a.bmHub = 0; + a.bmParent = bAddress; + a.bmAddress = port; + pUsb->ReleaseDevice(a.devAddress); + return 0; + + // Reset complete event + case bmHUB_PORT_EVENT_RESET_COMPLETE: + case bmHUB_PORT_EVENT_LS_RESET_COMPLETE: + ClearPortFeature(HUB_FEATURE_C_PORT_RESET, port, 0); + ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0); + + delay(20); + + a.devAddress = bAddress; + + pUsb->Configuring(a.bmAddress, port, (evt.bmStatus & bmHUB_PORT_STATUS_PORT_LOW_SPEED)); + bResetInitiated = false; + break; + + } // switch (evt.bmEvent) + return 0; +} + +void PrintHubPortStatus(USBHub *hubptr, uint8_t addr, uint8_t port, bool print_changes) { + uint8_t rcode = 0; + HubEvent evt; + + rcode = hubptr->GetPortStatus(port, 4, evt.evtBuff); + + if(rcode) { + USB_HOST_SERIAL.println("ERROR!"); + return; + } + USB_HOST_SERIAL.print("\r\nPort "); + USB_HOST_SERIAL.println(port, DEC); + + USB_HOST_SERIAL.println("Status"); + USB_HOST_SERIAL.print("CONNECTION:\t"); + USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_CONNECTION) > 0, DEC); + USB_HOST_SERIAL.print("ENABLE:\t\t"); + USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_ENABLE) > 0, DEC); + USB_HOST_SERIAL.print("SUSPEND:\t"); + USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_SUSPEND) > 0, DEC); + USB_HOST_SERIAL.print("OVER_CURRENT:\t"); + USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_OVER_CURRENT) > 0, DEC); + USB_HOST_SERIAL.print("RESET:\t\t"); + USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_RESET) > 0, DEC); + USB_HOST_SERIAL.print("POWER:\t\t"); + USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_POWER) > 0, DEC); + USB_HOST_SERIAL.print("LOW_SPEED:\t"); + USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_LOW_SPEED) > 0, DEC); + USB_HOST_SERIAL.print("HIGH_SPEED:\t"); + USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_HIGH_SPEED) > 0, DEC); + USB_HOST_SERIAL.print("TEST:\t\t"); + USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_TEST) > 0, DEC); + USB_HOST_SERIAL.print("INDICATOR:\t"); + USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_INDICATOR) > 0, DEC); + + if(!print_changes) + return; + + USB_HOST_SERIAL.println("\r\nChange"); + USB_HOST_SERIAL.print("CONNECTION:\t"); + USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_CONNECTION) > 0, DEC); + USB_HOST_SERIAL.print("ENABLE:\t\t"); + USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_ENABLE) > 0, DEC); + USB_HOST_SERIAL.print("SUSPEND:\t"); + USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_SUSPEND) > 0, DEC); + USB_HOST_SERIAL.print("OVER_CURRENT:\t"); + USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_OVER_CURRENT) > 0, DEC); + USB_HOST_SERIAL.print("RESET:\t\t"); + USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_RESET) > 0, DEC); +} diff --git a/lib/usbhost/USB_Host_Shield_2.0/usbhub.h b/lib/usbhost/USB_Host_Shield_2.0/usbhub.h new file mode 100644 index 0000000000..1ac949445a --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/usbhub.h @@ -0,0 +1,252 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#if !defined(__USBHUB_H__) +#define __USBHUB_H__ + +#include "Usb.h" + +#define USB_DESCRIPTOR_HUB 0x09 // Hub descriptor type + +// Hub Requests +#define bmREQ_CLEAR_HUB_FEATURE USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE +#define bmREQ_CLEAR_PORT_FEATURE USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER +#define bmREQ_CLEAR_TT_BUFFER USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER +#define bmREQ_GET_HUB_DESCRIPTOR USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE +#define bmREQ_GET_HUB_STATUS USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE +#define bmREQ_GET_PORT_STATUS USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER +#define bmREQ_RESET_TT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER +#define bmREQ_SET_HUB_DESCRIPTOR USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE +#define bmREQ_SET_HUB_FEATURE USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE +#define bmREQ_SET_PORT_FEATURE USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER +#define bmREQ_GET_TT_STATE USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER +#define bmREQ_STOP_TT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER + +// Hub Class Requests +#define HUB_REQUEST_CLEAR_TT_BUFFER 8 +#define HUB_REQUEST_RESET_TT 9 +#define HUB_REQUEST_GET_TT_STATE 10 +#define HUB_REQUEST_STOP_TT 11 + +// Hub Features +#define HUB_FEATURE_C_HUB_LOCAL_POWER 0 +#define HUB_FEATURE_C_HUB_OVER_CURRENT 1 +#define HUB_FEATURE_PORT_CONNECTION 0 +#define HUB_FEATURE_PORT_ENABLE 1 +#define HUB_FEATURE_PORT_SUSPEND 2 +#define HUB_FEATURE_PORT_OVER_CURRENT 3 +#define HUB_FEATURE_PORT_RESET 4 +#define HUB_FEATURE_PORT_POWER 8 +#define HUB_FEATURE_PORT_LOW_SPEED 9 +#define HUB_FEATURE_C_PORT_CONNECTION 16 +#define HUB_FEATURE_C_PORT_ENABLE 17 +#define HUB_FEATURE_C_PORT_SUSPEND 18 +#define HUB_FEATURE_C_PORT_OVER_CURRENT 19 +#define HUB_FEATURE_C_PORT_RESET 20 +#define HUB_FEATURE_PORT_TEST 21 +#define HUB_FEATURE_PORT_INDICATOR 22 + +// Hub Port Test Modes +#define HUB_PORT_TEST_MODE_J 1 +#define HUB_PORT_TEST_MODE_K 2 +#define HUB_PORT_TEST_MODE_SE0_NAK 3 +#define HUB_PORT_TEST_MODE_PACKET 4 +#define HUB_PORT_TEST_MODE_FORCE_ENABLE 5 + +// Hub Port Indicator Color +#define HUB_PORT_INDICATOR_AUTO 0 +#define HUB_PORT_INDICATOR_AMBER 1 +#define HUB_PORT_INDICATOR_GREEN 2 +#define HUB_PORT_INDICATOR_OFF 3 + +// Hub Port Status Bitmasks +#define bmHUB_PORT_STATUS_PORT_CONNECTION 0x0001 +#define bmHUB_PORT_STATUS_PORT_ENABLE 0x0002 +#define bmHUB_PORT_STATUS_PORT_SUSPEND 0x0004 +#define bmHUB_PORT_STATUS_PORT_OVER_CURRENT 0x0008 +#define bmHUB_PORT_STATUS_PORT_RESET 0x0010 +#define bmHUB_PORT_STATUS_PORT_POWER 0x0100 +#define bmHUB_PORT_STATUS_PORT_LOW_SPEED 0x0200 +#define bmHUB_PORT_STATUS_PORT_HIGH_SPEED 0x0400 +#define bmHUB_PORT_STATUS_PORT_TEST 0x0800 +#define bmHUB_PORT_STATUS_PORT_INDICATOR 0x1000 + +// Hub Port Status Change Bitmasks (used one byte instead of two) +#define bmHUB_PORT_STATUS_C_PORT_CONNECTION 0x0001 +#define bmHUB_PORT_STATUS_C_PORT_ENABLE 0x0002 +#define bmHUB_PORT_STATUS_C_PORT_SUSPEND 0x0004 +#define bmHUB_PORT_STATUS_C_PORT_OVER_CURRENT 0x0008 +#define bmHUB_PORT_STATUS_C_PORT_RESET 0x0010 + +// Hub Status Bitmasks (used one byte instead of two) +#define bmHUB_STATUS_LOCAL_POWER_SOURCE 0x01 +#define bmHUB_STATUS_OVER_CURRENT 0x12 + +// Hub Status Change Bitmasks (used one byte instead of two) +#define bmHUB_STATUS_C_LOCAL_POWER_SOURCE 0x01 +#define bmHUB_STATUS_C_OVER_CURRENT 0x12 + + +// Hub Port Configuring Substates +#define USB_STATE_HUB_PORT_CONFIGURING 0xb0 +#define USB_STATE_HUB_PORT_POWERED_OFF 0xb1 +#define USB_STATE_HUB_PORT_WAIT_FOR_POWER_GOOD 0xb2 +#define USB_STATE_HUB_PORT_DISCONNECTED 0xb3 +#define USB_STATE_HUB_PORT_DISABLED 0xb4 +#define USB_STATE_HUB_PORT_RESETTING 0xb5 +#define USB_STATE_HUB_PORT_ENABLED 0xb6 + +// Additional Error Codes +#define HUB_ERROR_PORT_HAS_BEEN_RESET 0xb1 + +// The bit mask to check for all necessary state bits +#define bmHUB_PORT_STATUS_ALL_MAIN ((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION | bmHUB_PORT_STATUS_C_PORT_ENABLE | bmHUB_PORT_STATUS_C_PORT_SUSPEND | bmHUB_PORT_STATUS_C_PORT_RESET) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_SUSPEND) + +// Bit mask to check for DISABLED state in HubEvent::bmStatus field +#define bmHUB_PORT_STATE_CHECK_DISABLED (0x0000 | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_SUSPEND) + +// Hub Port States +#define bmHUB_PORT_STATE_DISABLED (0x0000 | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_CONNECTION) + +// Hub Port Events +#define bmHUB_PORT_EVENT_CONNECT (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_CONNECTION) +#define bmHUB_PORT_EVENT_DISCONNECT (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION) << 16) | bmHUB_PORT_STATUS_PORT_POWER) +#define bmHUB_PORT_EVENT_RESET_COMPLETE (((0UL | bmHUB_PORT_STATUS_C_PORT_RESET) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION) + +#define bmHUB_PORT_EVENT_LS_CONNECT (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_LOW_SPEED) +#define bmHUB_PORT_EVENT_LS_RESET_COMPLETE (((0UL | bmHUB_PORT_STATUS_C_PORT_RESET) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_LOW_SPEED) +#define bmHUB_PORT_EVENT_LS_PORT_ENABLED (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION | bmHUB_PORT_STATUS_C_PORT_ENABLE) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_LOW_SPEED) + +struct HubDescriptor { + uint8_t bDescLength; // descriptor length + uint8_t bDescriptorType; // descriptor type + uint8_t bNbrPorts; // number of ports a hub equiped with + + struct { + uint16_t LogPwrSwitchMode : 2; + uint16_t CompoundDevice : 1; + uint16_t OverCurrentProtectMode : 2; + uint16_t TTThinkTime : 2; + uint16_t PortIndicatorsSupported : 1; + uint16_t Reserved : 8; + } __attribute__((packed)); + + uint8_t bPwrOn2PwrGood; + uint8_t bHubContrCurrent; +} __attribute__((packed)); + +struct HubEvent { + + union { + + struct { + uint16_t bmStatus; // port status bits + uint16_t bmChange; // port status change bits + } __attribute__((packed)); + uint32_t bmEvent; + uint8_t evtBuff[4]; + }; +} __attribute__((packed)); + +class USBHub : USBDeviceConfig { + static bool bResetInitiated; // True when reset is triggered + + USB *pUsb; // USB class instance pointer + + EpInfo epInfo[2]; // interrupt endpoint info structure + + uint8_t bAddress; // address + uint8_t bNbrPorts; // number of ports + // uint8_t bInitState; // initialization state variable + uint32_t qNextPollTime; // next poll time + bool bPollEnable; // poll enable flag + + uint8_t CheckHubStatus(); + uint8_t PortStatusChange(uint8_t port, HubEvent &evt); + +public: + USBHub(USB *p); + + uint8_t ClearHubFeature(uint8_t fid); + uint8_t ClearPortFeature(uint8_t fid, uint8_t port, uint8_t sel = 0); + uint8_t GetHubDescriptor(uint8_t index, uint16_t nbytes, uint8_t *dataptr); + uint8_t GetHubStatus(uint16_t nbytes, uint8_t* dataptr); + uint8_t GetPortStatus(uint8_t port, uint16_t nbytes, uint8_t* dataptr); + uint8_t SetHubDescriptor(uint8_t port, uint16_t nbytes, uint8_t* dataptr); + uint8_t SetHubFeature(uint8_t fid); + uint8_t SetPortFeature(uint8_t fid, uint8_t port, uint8_t sel = 0); + + void PrintHubStatus(); + + uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + uint8_t Release(); + uint8_t Poll(); + void ResetHubPort(uint8_t port); + + virtual uint8_t GetAddress() { + return bAddress; + }; + + virtual bool DEVCLASSOK(uint8_t klass) { + return (klass == 0x09); + } + +}; + +// Clear Hub Feature + +inline uint8_t USBHub::ClearHubFeature(uint8_t fid) { + return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CLEAR_HUB_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, 0, 0, 0, NULL, NULL)); +} +// Clear Port Feature + +inline uint8_t USBHub::ClearPortFeature(uint8_t fid, uint8_t port, uint8_t sel) { + return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CLEAR_PORT_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, ((0x0000 | port) | (sel << 8)), 0, 0, NULL, NULL)); +} +// Get Hub Descriptor + +inline uint8_t USBHub::GetHubDescriptor(uint8_t index, uint16_t nbytes, uint8_t *dataptr) { + return ( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_HUB_DESCRIPTOR, USB_REQUEST_GET_DESCRIPTOR, index, 0x29, 0, nbytes, nbytes, dataptr, NULL)); +} +// Get Hub Status + +inline uint8_t USBHub::GetHubStatus(uint16_t nbytes, uint8_t* dataptr) { + return ( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_HUB_STATUS, USB_REQUEST_GET_STATUS, 0, 0, 0x0000, nbytes, nbytes, dataptr, NULL)); +} +// Get Port Status + +inline uint8_t USBHub::GetPortStatus(uint8_t port, uint16_t nbytes, uint8_t* dataptr) { + return ( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_PORT_STATUS, USB_REQUEST_GET_STATUS, 0, 0, port, nbytes, nbytes, dataptr, NULL)); +} +// Set Hub Descriptor + +inline uint8_t USBHub::SetHubDescriptor(uint8_t port, uint16_t nbytes, uint8_t* dataptr) { + return ( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_HUB_DESCRIPTOR, USB_REQUEST_SET_DESCRIPTOR, 0, 0, port, nbytes, nbytes, dataptr, NULL)); +} +// Set Hub Feature + +inline uint8_t USBHub::SetHubFeature(uint8_t fid) { + return ( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_HUB_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, 0, 0, 0, NULL, NULL)); +} +// Set Port Feature + +inline uint8_t USBHub::SetPortFeature(uint8_t fid, uint8_t port, uint8_t sel) { + return ( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_PORT_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, (((0x0000 | sel) << 8) | port), 0, 0, NULL, NULL)); +} + +void PrintHubPortStatus(USB *usbptr, uint8_t addr, uint8_t port, bool print_changes = false); + +#endif // __USBHUB_H__ diff --git a/lib/usbhost/USB_Host_Shield_2.0/version_helper.h b/lib/usbhost/USB_Host_Shield_2.0/version_helper.h new file mode 100644 index 0000000000..0cb3b4adc0 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/version_helper.h @@ -0,0 +1,194 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ + +/* + * Universal Arduino(tm) "IDE" fixups. + * Includes fixes for versions as low as 0023, used by Digilent. + */ + +#if defined(ARDUINO) && ARDUINO >=100 +#include +#else +#include +#include +#ifdef __AVR__ +#include +#include +#else +#endif +#endif + +#ifndef __PGMSPACE_H_ +#define __PGMSPACE_H_ 1 + +#include + +#ifndef PROGMEM +#define PROGMEM +#endif +#ifndef PGM_P +#define PGM_P const char * +#endif +#ifndef PSTR +#define PSTR(str) (str) +#endif +#ifndef F +#define F(str) (str) +#endif +#ifndef _SFR_BYTE +#define _SFR_BYTE(n) (n) +#endif + +#ifndef memchr_P +#define memchr_P(str, c, len) memchr((str), (c), (len)) +#endif +#ifndef memcmp_P +#define memcmp_P(a, b, n) memcmp((a), (b), (n)) +#endif +#ifndef memcpy_P +#define memcpy_P(dest, src, num) memcpy((dest), (src), (num)) +#endif +#ifndef memmem_P +#define memmem_P(a, alen, b, blen) memmem((a), (alen), (b), (blen)) +#endif +#ifndef memrchr_P +#define memrchr_P(str, val, len) memrchr((str), (val), (len)) +#endif +#ifndef strcat_P +#define strcat_P(dest, src) strcat((dest), (src)) +#endif +#ifndef strchr_P +#define strchr_P(str, c) strchr((str), (c)) +#endif +#ifndef strchrnul_P +#define strchrnul_P(str, c) strchrnul((str), (c)) +#endif +#ifndef strcmp_P +#define strcmp_P(a, b) strcmp((a), (b)) +#endif +#ifndef strcpy_P +#define strcpy_P(dest, src) strcpy((dest), (src)) +#endif +#ifndef strcasecmp_P +#define strcasecmp_P(a, b) strcasecmp((a), (b)) +#endif +#ifndef strcasestr_P +#define strcasestr_P(a, b) strcasestr((a), (b)) +#endif +#ifndef strlcat_P +#define strlcat_P(dest, src, len) strlcat((dest), (src), (len)) +#endif +#ifndef strlcpy_P +#define strlcpy_P(dest, src, len) strlcpy((dest), (src), (len)) +#endif +#ifndef strlen_P +#define strlen_P(s) strlen((const char *)(s)) +#endif +#ifndef strnlen_P +#define strnlen_P(str, len) strnlen((str), (len)) +#endif +#ifndef strncmp_P +#define strncmp_P(a, b, n) strncmp((a), (b), (n)) +#endif +#ifndef strncasecmp_P +#define strncasecmp_P(a, b, n) strncasecmp((a), (b), (n)) +#endif +#ifndef strncat_P +#define strncat_P(a, b, n) strncat((a), (b), (n)) +#endif +#ifndef strncpy_P +#define strncpy_P(a, b, n) strncmp((a), (b), (n)) +#endif +#ifndef strpbrk_P +#define strpbrk_P(str, chrs) strpbrk((str), (chrs)) +#endif +#ifndef strrchr_P +#define strrchr_P(str, c) strrchr((str), (c)) +#endif +#ifndef strsep_P +#define strsep_P(strp, delim) strsep((strp), (delim)) +#endif +#ifndef strspn_P +#define strspn_P(str, chrs) strspn((str), (chrs)) +#endif +#ifndef strstr_P +#define strstr_P(a, b) strstr((a), (b)) +#endif +#ifndef sprintf_P +#define sprintf_P(s, ...) sprintf((s), __VA_ARGS__) +#endif +#ifndef vfprintf_P +#define vfprintf_P(s, ...) vfprintf((s), __VA_ARGS__) +#endif +#ifndef printf_P +#define printf_P(...) printf(__VA_ARGS__) +#endif +#ifndef snprintf_P +#define snprintf_P(s, n, ...) ((s), (n), __VA_ARGS__) +#endif +#ifndef vsprintf_P +#define vsprintf_P(s, ...) ((s),__VA_ARGS__) +#endif +#ifndef vsnprintf_P +#define vsnprintf_P(s, n, ...) ((s), (n),__VA_ARGS__) +#endif +#ifndef fprintf_P +#define fprintf_P(s, ...) ((s), __VA_ARGS__) +#endif + +#ifndef pgm_read_byte +#define pgm_read_byte(addr) (*(const unsigned char *)(addr)) +#endif +#ifndef pgm_read_word +#define pgm_read_word(addr) (*(const unsigned short *)(addr)) +#endif +#ifndef pgm_read_dword +#define pgm_read_dword(addr) (*(const unsigned long *)(addr)) +#endif +#ifndef pgm_read_float +#define pgm_read_float(addr) (*(const float *)(addr)) +#endif + +#ifndef pgm_read_byte_near +#define pgm_read_byte_near(addr) pgm_read_byte(addr) +#endif +#ifndef pgm_read_word_near +#define pgm_read_word_near(addr) pgm_read_word(addr) +#endif +#ifndef pgm_read_dword_near +#define pgm_read_dword_near(addr) pgm_read_dword(addr) +#endif +#ifndef pgm_read_float_near +#define pgm_read_float_near(addr) pgm_read_float(addr) +#endif +#ifndef pgm_read_byte_far +#define pgm_read_byte_far(addr) pgm_read_byte(addr) +#endif +#ifndef pgm_read_word_far +#define pgm_read_word_far(addr) pgm_read_word(addr) +#endif +#ifndef pgm_read_dword_far +#define pgm_read_dword_far(addr) pgm_read_dword(addr) +#endif +#ifndef pgm_read_float_far +#define pgm_read_float_far(addr) pgm_read_float(addr) +#endif + +#ifndef pgm_read_pointer +#define pgm_read_pointer +#endif +#endif diff --git a/lib/usbhost/USB_Host_Shield_2.0/xboxEnums.h b/lib/usbhost/USB_Host_Shield_2.0/xboxEnums.h new file mode 100644 index 0000000000..84b137bb6e --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/xboxEnums.h @@ -0,0 +1,65 @@ +/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. + + This software may be distributed and modified under the terms of the GNU + General Public License version 2 (GPL2) as published by the Free Software + Foundation and appearing in the file GPL2.TXT included in the packaging of + this file. Please note that GPL2 Section 2[b] requires that all works based + on this software must also be made publicly available under the terms of + the GPL2 ("Copyleft"). + + Contact information + ------------------- + + Kristian Lauszus, TKJ Electronics + Web : http://www.tkjelectronics.com + e-mail : kristianl@tkjelectronics.com + */ + +#ifndef _xboxenums_h +#define _xboxenums_h + +#include "controllerEnums.h" + +/** Enum used to set special LED modes supported by the Xbox controller. */ +enum LEDModeEnum { + ROTATING = 0x0A, + FASTBLINK = 0x0B, + SLOWBLINK = 0x0C, + ALTERNATING = 0x0D, +}; + +/** Used to set the LEDs on the controllers */ +const uint8_t XBOX_LEDS[] PROGMEM = { + 0x00, // OFF + 0x02, // LED1 + 0x03, // LED2 + 0x04, // LED3 + 0x05, // LED4 + 0x01, // ALL - Used to blink all LEDs +}; +/** Buttons on the controllers */ +const uint16_t XBOX_BUTTONS[] PROGMEM = { + 0x0100, // UP + 0x0800, // RIGHT + 0x0200, // DOWN + 0x0400, // LEFT + + 0x2000, // BACK + 0x1000, // START + 0x4000, // L3 + 0x8000, // R3 + + 0, 0, // Skip L2 and R2 as these are analog buttons + 0x0001, // L1 + 0x0002, // R1 + + 0x0020, // B + 0x0010, // A + 0x0040, // X + 0x0080, // Y + + 0x0004, // XBOX + 0x0008, // SYNC +}; + +#endif diff --git a/lib/usbhost/arduino-1.0.1/cores/arduino/Arduino.h b/lib/usbhost/arduino-1.0.1/cores/arduino/Arduino.h new file mode 100644 index 0000000000..830c9952fb --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/cores/arduino/Arduino.h @@ -0,0 +1,215 @@ +#ifndef Arduino_h +#define Arduino_h + +#include +#include +#include + +#include +#include +#include + +#include "binary.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +#define HIGH 0x1 +#define LOW 0x0 + +#define INPUT 0x0 +#define OUTPUT 0x1 +#define INPUT_PULLUP 0x2 + +#define true 0x1 +#define false 0x0 + +#define PI 3.1415926535897932384626433832795 +#define HALF_PI 1.5707963267948966192313216916398 +#define TWO_PI 6.283185307179586476925286766559 +#define DEG_TO_RAD 0.017453292519943295769236907684886 +#define RAD_TO_DEG 57.295779513082320876798154814105 + +#define SERIAL 0x0 +#define DISPLAY 0x1 + +#define LSBFIRST 0 +#define MSBFIRST 1 + +#define CHANGE 1 +#define FALLING 2 +#define RISING 3 + +#if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) +#define DEFAULT 0 +#define EXTERNAL 1 +#define INTERNAL 2 +#else +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1284P__) +#define INTERNAL1V1 2 +#define INTERNAL2V56 3 +#else +#define INTERNAL 3 +#endif +#define DEFAULT 1 +#define EXTERNAL 0 +#endif + +// undefine stdlib's abs if encountered +#ifdef abs +#undef abs +#endif + +#define min(a,b) ((a)<(b)?(a):(b)) +#define max(a,b) ((a)>(b)?(a):(b)) +#define abs(x) ((x)>0?(x):-(x)) +#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt))) +#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5)) +#define radians(deg) ((deg)*DEG_TO_RAD) +#define degrees(rad) ((rad)*RAD_TO_DEG) +#define sq(x) ((x)*(x)) + +#define interrupts() sei() +#define noInterrupts() cli() + +#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L ) +#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() ) +#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() ) + +#define lowByte(w) ((uint8_t) ((w) & 0xff)) +#define highByte(w) ((uint8_t) ((w) >> 8)) + +#define bitRead(value, bit) (((value) >> (bit)) & 0x01) +#define bitSet(value, bit) ((value) |= (1UL << (bit))) +#define bitClear(value, bit) ((value) &= ~(1UL << (bit))) +#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit)) + + +typedef unsigned int word; + +#define bit(b) (1UL << (b)) + +typedef uint8_t boolean; +typedef uint8_t byte; + +void init(void); + +void pinMode(uint8_t, uint8_t); +void digitalWrite(uint8_t, uint8_t); +int digitalRead(uint8_t); +int analogRead(uint8_t); +void analogReference(uint8_t mode); +void analogWrite(uint8_t, int); + +unsigned long millis(void); +unsigned long micros(void); +void delay(unsigned long); +void delayMicroseconds(unsigned int us); +unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout); + +void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val); +uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder); + +void attachInterrupt(uint8_t, void (*)(void), int mode); +void detachInterrupt(uint8_t); + +void setup(void); +void loop(void); + +// Get the bit location within the hardware port of the given virtual pin. +// This comes from the pins_*.c file for the active board configuration. + +#define analogInPinToBit(P) (P) + +// On the ATmega1280, the addresses of some of the port registers are +// greater than 255, so we can't store them in uint8_t's. +extern const uint16_t PROGMEM port_to_mode_PGM[]; +extern const uint16_t PROGMEM port_to_input_PGM[]; +extern const uint16_t PROGMEM port_to_output_PGM[]; + +extern const uint8_t PROGMEM digital_pin_to_port_PGM[]; +// extern const uint8_t PROGMEM digital_pin_to_bit_PGM[]; +extern const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[]; +extern const uint8_t PROGMEM digital_pin_to_timer_PGM[]; + +// Get the bit location within the hardware port of the given virtual pin. +// This comes from the pins_*.c file for the active board configuration. +// +// These perform slightly better as macros compared to inline functions +// +#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) ) +#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) ) +#define digitalPinToTimer(P) ( pgm_read_byte( digital_pin_to_timer_PGM + (P) ) ) +#define analogInPinToBit(P) (P) +#define portOutputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_output_PGM + (P))) ) +#define portInputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_input_PGM + (P))) ) +#define portModeRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_mode_PGM + (P))) ) + +#define NOT_A_PIN 0 +#define NOT_A_PORT 0 + +#ifdef ARDUINO_MAIN +#define PA 1 +#define PB 2 +#define PC 3 +#define PD 4 +#define PE 5 +#define PF 6 +#define PG 7 +#define PH 8 +#define PJ 10 +#define PK 11 +#define PL 12 +#endif + +#define NOT_ON_TIMER 0 +#define TIMER0A 1 +#define TIMER0B 2 +#define TIMER1A 3 +#define TIMER1B 4 +#define TIMER2 5 +#define TIMER2A 6 +#define TIMER2B 7 + +#define TIMER3A 8 +#define TIMER3B 9 +#define TIMER3C 10 +#define TIMER4A 11 +#define TIMER4B 12 +#define TIMER4C 13 +#define TIMER4D 14 +#define TIMER5A 15 +#define TIMER5B 16 +#define TIMER5C 17 + +#ifdef __cplusplus +} // extern "C" +#endif + +#ifdef __cplusplus +#include "WCharacter.h" +#include "WString.h" +#include "HardwareSerial.h" + +uint16_t makeWord(uint16_t w); +uint16_t makeWord(byte h, byte l); + +#define word(...) makeWord(__VA_ARGS__) + +unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L); + +void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0); +void noTone(uint8_t _pin); + +// WMath prototypes +long random(long); +long random(long, long); +void randomSeed(unsigned int); +long map(long, long, long, long, long); + +#endif + +#include "pins_arduino.h" + +#endif diff --git a/lib/usbhost/arduino-1.0.1/cores/arduino/CDC.cpp b/lib/usbhost/arduino-1.0.1/cores/arduino/CDC.cpp new file mode 100644 index 0000000000..1ee3a488a5 --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/cores/arduino/CDC.cpp @@ -0,0 +1,233 @@ + + +/* Copyright (c) 2011, Peter Barrett +** +** Permission to use, copy, modify, and/or distribute this software for +** any purpose with or without fee is hereby granted, provided that the +** above copyright notice and this permission notice appear in all copies. +** +** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR +** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES +** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +** SOFTWARE. +*/ + +#include "Platform.h" +#include "USBAPI.h" +#include + +#if defined(USBCON) +#ifdef CDC_ENABLED + +#if (RAMEND < 1000) +#define SERIAL_BUFFER_SIZE 16 +#else +#define SERIAL_BUFFER_SIZE 64 +#endif + +struct ring_buffer +{ + unsigned char buffer[SERIAL_BUFFER_SIZE]; + volatile int head; + volatile int tail; +}; + +ring_buffer cdc_rx_buffer = { { 0 }, 0, 0}; + +typedef struct +{ + u32 dwDTERate; + u8 bCharFormat; + u8 bParityType; + u8 bDataBits; + u8 lineState; +} LineInfo; + +static volatile LineInfo _usbLineInfo = { 57600, 0x00, 0x00, 0x00, 0x00 }; + +#define WEAK __attribute__ ((weak)) + +extern const CDCDescriptor _cdcInterface PROGMEM; +const CDCDescriptor _cdcInterface = +{ + D_IAD(0,2,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,1), + + // CDC communication interface + D_INTERFACE(CDC_ACM_INTERFACE,1,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,0), + D_CDCCS(CDC_HEADER,0x10,0x01), // Header (1.10 bcd) + D_CDCCS(CDC_CALL_MANAGEMENT,1,1), // Device handles call management (not) + D_CDCCS4(CDC_ABSTRACT_CONTROL_MANAGEMENT,6), // SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE supported + D_CDCCS(CDC_UNION,CDC_ACM_INTERFACE,CDC_DATA_INTERFACE), // Communication interface is master, data interface is slave 0 + D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_ACM),USB_ENDPOINT_TYPE_INTERRUPT,0x10,0x40), + + // CDC data interface + D_INTERFACE(CDC_DATA_INTERFACE,2,CDC_DATA_INTERFACE_CLASS,0,0), + D_ENDPOINT(USB_ENDPOINT_OUT(CDC_ENDPOINT_OUT),USB_ENDPOINT_TYPE_BULK,0x40,0), + D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,0x40,0) +}; + +int WEAK CDC_GetInterface(u8* interfaceNum) +{ + interfaceNum[0] += 2; // uses 2 + return USB_SendControl(TRANSFER_PGM,&_cdcInterface,sizeof(_cdcInterface)); +} + +bool WEAK CDC_Setup(Setup& setup) +{ + u8 r = setup.bRequest; + u8 requestType = setup.bmRequestType; + + if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType) + { + if (CDC_GET_LINE_CODING == r) + { + USB_SendControl(0,(void*)&_usbLineInfo,7); + return true; + } + } + + if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType) + { + if (CDC_SET_LINE_CODING == r) + { + USB_RecvControl((void*)&_usbLineInfo,7); + return true; + } + + if (CDC_SET_CONTROL_LINE_STATE == r) + { + _usbLineInfo.lineState = setup.wValueL; + + // auto-reset into the bootloader is triggered when the port, already + // open at 1200 bps, is closed. this is the signal to start the watchdog + // with a relatively long period so it can finish housekeeping tasks + // like servicing endpoints before the sketch ends + if (1200 == _usbLineInfo.dwDTERate) { + // We check DTR state to determine if host port is open (bit 0 of lineState). + if ((_usbLineInfo.lineState & 0x01) == 0) { + *(uint16_t *)0x0800 = 0x7777; + wdt_enable(WDTO_120MS); + } else { + // Most OSs do some intermediate steps when configuring ports and DTR can + // twiggle more than once before stabilizing. + // To avoid spurious resets we set the watchdog to 250ms and eventually + // cancel if DTR goes back high. + + wdt_disable(); + wdt_reset(); + *(uint16_t *)0x0800 = 0x0; + } + } + return true; + } + } + return false; +} + + +int _serialPeek = -1; +void Serial_::begin(uint16_t baud_count) +{ +} + +void Serial_::end(void) +{ +} + +void Serial_::accept(void) +{ + ring_buffer *buffer = &cdc_rx_buffer; + int c = USB_Recv(CDC_RX); + int i = (unsigned int)(buffer->head+1) % SERIAL_BUFFER_SIZE; + + // if we should be storing the received character into the location + // just before the tail (meaning that the head would advance to the + // current location of the tail), we're about to overflow the buffer + // and so we don't write the character or advance the head. + if (i != buffer->tail) { + buffer->buffer[buffer->head] = c; + buffer->head = i; + } +} + +int Serial_::available(void) +{ + ring_buffer *buffer = &cdc_rx_buffer; + return (unsigned int)(SERIAL_BUFFER_SIZE + buffer->head - buffer->tail) % SERIAL_BUFFER_SIZE; +} + +int Serial_::peek(void) +{ + ring_buffer *buffer = &cdc_rx_buffer; + if (buffer->head == buffer->tail) { + return -1; + } else { + return buffer->buffer[buffer->tail]; + } +} + +int Serial_::read(void) +{ + ring_buffer *buffer = &cdc_rx_buffer; + // if the head isn't ahead of the tail, we don't have any characters + if (buffer->head == buffer->tail) { + return -1; + } else { + unsigned char c = buffer->buffer[buffer->tail]; + buffer->tail = (unsigned int)(buffer->tail + 1) % SERIAL_BUFFER_SIZE; + return c; + } +} + +void Serial_::flush(void) +{ + USB_Flush(CDC_TX); +} + +size_t Serial_::write(uint8_t c) +{ + /* only try to send bytes if the high-level CDC connection itself + is open (not just the pipe) - the OS should set lineState when the port + is opened and clear lineState when the port is closed. + bytes sent before the user opens the connection or after + the connection is closed are lost - just like with a UART. */ + + // TODO - ZE - check behavior on different OSes and test what happens if an + // open connection isn't broken cleanly (cable is yanked out, host dies + // or locks up, or host virtual serial port hangs) + if (_usbLineInfo.lineState > 0) { + int r = USB_Send(CDC_TX,&c,1); + if (r > 0) { + return r; + } else { + setWriteError(); + return 0; + } + } + setWriteError(); + return 0; +} + +// This operator is a convenient way for a sketch to check whether the +// port has actually been configured and opened by the host (as opposed +// to just being connected to the host). It can be used, for example, in +// setup() before printing to ensure that an application on the host is +// actually ready to receive and display the data. +// We add a short delay before returning to fix a bug observed by Federico +// where the port is configured (lineState != 0) but not quite opened. +Serial_::operator bool() { + bool result = false; + if (_usbLineInfo.lineState > 0) + result = true; + delay(10); + return result; +} + +Serial_ Serial; + +#endif +#endif /* if defined(USBCON) */ diff --git a/lib/usbhost/arduino-1.0.1/cores/arduino/Client.h b/lib/usbhost/arduino-1.0.1/cores/arduino/Client.h new file mode 100644 index 0000000000..ea134838a2 --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/cores/arduino/Client.h @@ -0,0 +1,26 @@ +#ifndef client_h +#define client_h +#include "Print.h" +#include "Stream.h" +#include "IPAddress.h" + +class Client : public Stream { + +public: + virtual int connect(IPAddress ip, uint16_t port) =0; + virtual int connect(const char *host, uint16_t port) =0; + virtual size_t write(uint8_t) =0; + virtual size_t write(const uint8_t *buf, size_t size) =0; + virtual int available() = 0; + virtual int read() = 0; + virtual int read(uint8_t *buf, size_t size) = 0; + virtual int peek() = 0; + virtual void flush() = 0; + virtual void stop() = 0; + virtual uint8_t connected() = 0; + virtual operator bool() = 0; +protected: + uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); }; +}; + +#endif diff --git a/lib/usbhost/arduino-1.0.1/cores/arduino/HID.cpp b/lib/usbhost/arduino-1.0.1/cores/arduino/HID.cpp new file mode 100644 index 0000000000..ac63608449 --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/cores/arduino/HID.cpp @@ -0,0 +1,520 @@ + + +/* Copyright (c) 2011, Peter Barrett +** +** Permission to use, copy, modify, and/or distribute this software for +** any purpose with or without fee is hereby granted, provided that the +** above copyright notice and this permission notice appear in all copies. +** +** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR +** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES +** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +** SOFTWARE. +*/ + +#include "Platform.h" +#include "USBAPI.h" +#include "USBDesc.h" + +#if defined(USBCON) +#ifdef HID_ENABLED + +//#define RAWHID_ENABLED + +// Singletons for mouse and keyboard + +Mouse_ Mouse; +Keyboard_ Keyboard; + +//================================================================================ +//================================================================================ + +// HID report descriptor + +#define LSB(_x) ((_x) & 0xFF) +#define MSB(_x) ((_x) >> 8) + +#define RAWHID_USAGE_PAGE 0xFFC0 +#define RAWHID_USAGE 0x0C00 +#define RAWHID_TX_SIZE 64 +#define RAWHID_RX_SIZE 64 + +extern const u8 _hidReportDescriptor[] PROGMEM; +const u8 _hidReportDescriptor[] = { + + // Mouse + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 54 + 0x09, 0x02, // USAGE (Mouse) + 0xa1, 0x01, // COLLECTION (Application) + 0x09, 0x01, // USAGE (Pointer) + 0xa1, 0x00, // COLLECTION (Physical) + 0x85, 0x01, // REPORT_ID (1) + 0x05, 0x09, // USAGE_PAGE (Button) + 0x19, 0x01, // USAGE_MINIMUM (Button 1) + 0x29, 0x03, // USAGE_MAXIMUM (Button 3) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x95, 0x03, // REPORT_COUNT (3) + 0x75, 0x01, // REPORT_SIZE (1) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0x95, 0x01, // REPORT_COUNT (1) + 0x75, 0x05, // REPORT_SIZE (5) + 0x81, 0x03, // INPUT (Cnst,Var,Abs) + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x30, // USAGE (X) + 0x09, 0x31, // USAGE (Y) + 0x09, 0x38, // USAGE (Wheel) + 0x15, 0x81, // LOGICAL_MINIMUM (-127) + 0x25, 0x7f, // LOGICAL_MAXIMUM (127) + 0x75, 0x08, // REPORT_SIZE (8) + 0x95, 0x03, // REPORT_COUNT (3) + 0x81, 0x06, // INPUT (Data,Var,Rel) + 0xc0, // END_COLLECTION + 0xc0, // END_COLLECTION + + // Keyboard + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 47 + 0x09, 0x06, // USAGE (Keyboard) + 0xa1, 0x01, // COLLECTION (Application) + 0x85, 0x02, // REPORT_ID (2) + 0x05, 0x07, // USAGE_PAGE (Keyboard) + + 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl) + 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x75, 0x01, // REPORT_SIZE (1) + + 0x95, 0x08, // REPORT_COUNT (8) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0x95, 0x01, // REPORT_COUNT (1) + 0x75, 0x08, // REPORT_SIZE (8) + 0x81, 0x03, // INPUT (Cnst,Var,Abs) + + 0x95, 0x06, // REPORT_COUNT (6) + 0x75, 0x08, // REPORT_SIZE (8) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x65, // LOGICAL_MAXIMUM (101) + 0x05, 0x07, // USAGE_PAGE (Keyboard) + + 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated)) + 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application) + 0x81, 0x00, // INPUT (Data,Ary,Abs) + 0xc0, // END_COLLECTION + +#if RAWHID_ENABLED + // RAW HID + 0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE), // 30 + 0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE), + + 0xA1, 0x01, // Collection 0x01 + 0x85, 0x03, // REPORT_ID (3) + 0x75, 0x08, // report size = 8 bits + 0x15, 0x00, // logical minimum = 0 + 0x26, 0xFF, 0x00, // logical maximum = 255 + + 0x95, 64, // report count TX + 0x09, 0x01, // usage + 0x81, 0x02, // Input (array) + + 0x95, 64, // report count RX + 0x09, 0x02, // usage + 0x91, 0x02, // Output (array) + 0xC0 // end collection +#endif +}; + +extern const HIDDescriptor _hidInterface PROGMEM; +const HIDDescriptor _hidInterface = +{ + D_INTERFACE(HID_INTERFACE,1,3,0,0), + D_HIDREPORT(sizeof(_hidReportDescriptor)), + D_ENDPOINT(USB_ENDPOINT_IN (HID_ENDPOINT_INT),USB_ENDPOINT_TYPE_INTERRUPT,0x40,0x01) +}; + +//================================================================================ +//================================================================================ +// Driver + +u8 _hid_protocol = 1; +u8 _hid_idle = 1; + +#define WEAK __attribute__ ((weak)) + +int WEAK HID_GetInterface(u8* interfaceNum) +{ + interfaceNum[0] += 1; // uses 1 + return USB_SendControl(TRANSFER_PGM,&_hidInterface,sizeof(_hidInterface)); +} + +int WEAK HID_GetDescriptor(int i) +{ + return USB_SendControl(TRANSFER_PGM,_hidReportDescriptor,sizeof(_hidReportDescriptor)); +} + +void WEAK HID_SendReport(u8 id, const void* data, int len) +{ + USB_Send(HID_TX, &id, 1); + USB_Send(HID_TX | TRANSFER_RELEASE,data,len); +} + +bool WEAK HID_Setup(Setup& setup) +{ + u8 r = setup.bRequest; + u8 requestType = setup.bmRequestType; + if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType) + { + if (HID_GET_REPORT == r) + { + //HID_GetReport(); + return true; + } + if (HID_GET_PROTOCOL == r) + { + //Send8(_hid_protocol); // TODO + return true; + } + } + + if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType) + { + if (HID_SET_PROTOCOL == r) + { + _hid_protocol = setup.wValueL; + return true; + } + + if (HID_SET_IDLE == r) + { + _hid_idle = setup.wValueL; + return true; + } + } + return false; +} + +//================================================================================ +//================================================================================ +// Mouse + +Mouse_::Mouse_(void) : _buttons(0) +{ +} + +void Mouse_::begin(void) +{ +} + +void Mouse_::end(void) +{ +} + +void Mouse_::click(uint8_t b) +{ + _buttons = b; + move(0,0,0); + _buttons = 0; + move(0,0,0); +} + +void Mouse_::move(signed char x, signed char y, signed char wheel) +{ + u8 m[4]; + m[0] = _buttons; + m[1] = x; + m[2] = y; + m[3] = wheel; + HID_SendReport(1,m,4); +} + +void Mouse_::buttons(uint8_t b) +{ + if (b != _buttons) + { + _buttons = b; + move(0,0,0); + } +} + +void Mouse_::press(uint8_t b) +{ + buttons(_buttons | b); +} + +void Mouse_::release(uint8_t b) +{ + buttons(_buttons & ~b); +} + +bool Mouse_::isPressed(uint8_t b) +{ + if ((b & _buttons) > 0) + return true; + return false; +} + +//================================================================================ +//================================================================================ +// Keyboard + +Keyboard_::Keyboard_(void) +{ +} + +void Keyboard_::begin(void) +{ +} + +void Keyboard_::end(void) +{ +} + +void Keyboard_::sendReport(KeyReport* keys) +{ + HID_SendReport(2,keys,sizeof(KeyReport)); +} + +extern +const uint8_t _asciimap[128] PROGMEM; + +#define SHIFT 0x80 +const uint8_t _asciimap[128] = +{ + 0x00, // NUL + 0x00, // SOH + 0x00, // STX + 0x00, // ETX + 0x00, // EOT + 0x00, // ENQ + 0x00, // ACK + 0x00, // BEL + 0x2a, // BS Backspace + 0x2b, // TAB Tab + 0x28, // LF Enter + 0x00, // VT + 0x00, // FF + 0x00, // CR + 0x00, // SO + 0x00, // SI + 0x00, // DEL + 0x00, // DC1 + 0x00, // DC2 + 0x00, // DC3 + 0x00, // DC4 + 0x00, // NAK + 0x00, // SYN + 0x00, // ETB + 0x00, // CAN + 0x00, // EM + 0x00, // SUB + 0x00, // ESC + 0x00, // FS + 0x00, // GS + 0x00, // RS + 0x00, // US + + 0x2c, // ' ' + 0x1e|SHIFT, // ! + 0x34|SHIFT, // " + 0x20|SHIFT, // # + 0x21|SHIFT, // $ + 0x22|SHIFT, // % + 0x24|SHIFT, // & + 0x34, // ' + 0x26|SHIFT, // ( + 0x27|SHIFT, // ) + 0x25|SHIFT, // * + 0x2e|SHIFT, // + + 0x36, // , + 0x2d, // - + 0x37, // . + 0x38, // / + 0x27, // 0 + 0x1e, // 1 + 0x1f, // 2 + 0x20, // 3 + 0x21, // 4 + 0x22, // 5 + 0x23, // 6 + 0x24, // 7 + 0x25, // 8 + 0x26, // 9 + 0x33|SHIFT, // : + 0x33, // ; + 0x36|SHIFT, // < + 0x2e, // = + 0x37|SHIFT, // > + 0x38|SHIFT, // ? + 0x1f|SHIFT, // @ + 0x04|SHIFT, // A + 0x05|SHIFT, // B + 0x06|SHIFT, // C + 0x07|SHIFT, // D + 0x08|SHIFT, // E + 0x09|SHIFT, // F + 0x0a|SHIFT, // G + 0x0b|SHIFT, // H + 0x0c|SHIFT, // I + 0x0d|SHIFT, // J + 0x0e|SHIFT, // K + 0x0f|SHIFT, // L + 0x10|SHIFT, // M + 0x11|SHIFT, // N + 0x12|SHIFT, // O + 0x13|SHIFT, // P + 0x14|SHIFT, // Q + 0x15|SHIFT, // R + 0x16|SHIFT, // S + 0x17|SHIFT, // T + 0x18|SHIFT, // U + 0x19|SHIFT, // V + 0x1a|SHIFT, // W + 0x1b|SHIFT, // X + 0x1c|SHIFT, // Y + 0x1d|SHIFT, // Z + 0x2f, // [ + 0x31, // bslash + 0x30, // ] + 0x23|SHIFT, // ^ + 0x2d|SHIFT, // _ + 0x35, // ` + 0x04, // a + 0x05, // b + 0x06, // c + 0x07, // d + 0x08, // e + 0x09, // f + 0x0a, // g + 0x0b, // h + 0x0c, // i + 0x0d, // j + 0x0e, // k + 0x0f, // l + 0x10, // m + 0x11, // n + 0x12, // o + 0x13, // p + 0x14, // q + 0x15, // r + 0x16, // s + 0x17, // t + 0x18, // u + 0x19, // v + 0x1a, // w + 0x1b, // x + 0x1c, // y + 0x1d, // z + 0x2f|SHIFT, // + 0x31|SHIFT, // | + 0x30|SHIFT, // } + 0x35|SHIFT, // ~ + 0 // DEL +}; + +uint8_t USBPutChar(uint8_t c); + +// press() adds the specified key (printing, non-printing, or modifier) +// to the persistent key report and sends the report. Because of the way +// USB HID works, the host acts like the key remains pressed until we +// call release(), releaseAll(), or otherwise clear the report and resend. +size_t Keyboard_::press(uint8_t k) +{ + uint8_t i; + if (k >= 136) { // it's a non-printing key (not a modifier) + k = k - 136; + } else if (k >= 128) { // it's a modifier key + _keyReport.modifiers |= (1<<(k-128)); + k = 0; + } else { // it's a printing key + k = pgm_read_byte(_asciimap + k); + if (!k) { + setWriteError(); + return 0; + } + if (k & 0x80) { // it's a capital letter or other character reached with shift + _keyReport.modifiers |= 0x02; // the left shift modifier + k &= 0x7F; + } + } + + // Add k to the key report only if it's not already present + // and if there is an empty slot. + if (_keyReport.keys[0] != k && _keyReport.keys[1] != k && + _keyReport.keys[2] != k && _keyReport.keys[3] != k && + _keyReport.keys[4] != k && _keyReport.keys[5] != k) { + + for (i=0; i<6; i++) { + if (_keyReport.keys[i] == 0x00) { + _keyReport.keys[i] = k; + break; + } + } + if (i == 6) { + setWriteError(); + return 0; + } + } + sendReport(&_keyReport); + return 1; +} + +// release() takes the specified key out of the persistent key report and +// sends the report. This tells the OS the key is no longer pressed and that +// it shouldn't be repeated any more. +size_t Keyboard_::release(uint8_t k) +{ + uint8_t i; + if (k >= 136) { // it's a non-printing key (not a modifier) + k = k - 136; + } else if (k >= 128) { // it's a modifier key + _keyReport.modifiers &= ~(1<<(k-128)); + k = 0; + } else { // it's a printing key + k = pgm_read_byte(_asciimap + k); + if (!k) { + return 0; + } + if (k & 0x80) { // it's a capital letter or other character reached with shift + _keyReport.modifiers &= ~(0x02); // the left shift modifier + k &= 0x7F; + } + } + + // Test the key report to see if k is present. Clear it if it exists. + // Check all positions in case the key is present more than once (which it shouldn't be) + for (i=0; i<6; i++) { + if (0 != k && _keyReport.keys[i] == k) { + _keyReport.keys[i] = 0x00; + } + } + + sendReport(&_keyReport); + return 1; +} + +void Keyboard_::releaseAll(void) +{ + _keyReport.keys[0] = 0; + _keyReport.keys[1] = 0; + _keyReport.keys[2] = 0; + _keyReport.keys[3] = 0; + _keyReport.keys[4] = 0; + _keyReport.keys[5] = 0; + _keyReport.modifiers = 0; + sendReport(&_keyReport); +} + +size_t Keyboard_::write(uint8_t c) +{ + uint8_t p = press(c); // Keydown + uint8_t r = release(c); // Keyup + return (p); // just return the result of press() since release() almost always returns 1 +} + +#endif + +#endif /* if defined(USBCON) */ \ No newline at end of file diff --git a/lib/usbhost/arduino-1.0.1/cores/arduino/HardwareSerial.cpp b/lib/usbhost/arduino-1.0.1/cores/arduino/HardwareSerial.cpp new file mode 100644 index 0000000000..f40ddee060 --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/cores/arduino/HardwareSerial.cpp @@ -0,0 +1,428 @@ +/* + HardwareSerial.cpp - Hardware serial library for Wiring + Copyright (c) 2006 Nicholas Zambetti. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Modified 23 November 2006 by David A. Mellis + Modified 28 September 2010 by Mark Sproul +*/ + +#include +#include +#include +#include +#include "Arduino.h" +#include "wiring_private.h" + +// this next line disables the entire HardwareSerial.cpp, +// this is so I can support Attiny series and any other chip without a uart +#if defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(UBRR2H) || defined(UBRR3H) + +#include "HardwareSerial.h" + +// Define constants and variables for buffering incoming serial data. We're +// using a ring buffer (I think), in which head is the index of the location +// to which to write the next incoming character and tail is the index of the +// location from which to read. +#if (RAMEND < 1000) + #define SERIAL_BUFFER_SIZE 16 +#else + #define SERIAL_BUFFER_SIZE 64 +#endif + +struct ring_buffer +{ + unsigned char buffer[SERIAL_BUFFER_SIZE]; + volatile unsigned int head; + volatile unsigned int tail; +}; + +#if defined(USBCON) + ring_buffer rx_buffer = { { 0 }, 0, 0}; + ring_buffer tx_buffer = { { 0 }, 0, 0}; +#endif +#if defined(UBRRH) || defined(UBRR0H) + ring_buffer rx_buffer = { { 0 }, 0, 0 }; + ring_buffer tx_buffer = { { 0 }, 0, 0 }; +#endif +#if defined(UBRR1H) + ring_buffer rx_buffer1 = { { 0 }, 0, 0 }; + ring_buffer tx_buffer1 = { { 0 }, 0, 0 }; +#endif +#if defined(UBRR2H) + ring_buffer rx_buffer2 = { { 0 }, 0, 0 }; + ring_buffer tx_buffer2 = { { 0 }, 0, 0 }; +#endif +#if defined(UBRR3H) + ring_buffer rx_buffer3 = { { 0 }, 0, 0 }; + ring_buffer tx_buffer3 = { { 0 }, 0, 0 }; +#endif + +inline void store_char(unsigned char c, ring_buffer *buffer) +{ + int i = (unsigned int)(buffer->head + 1) % SERIAL_BUFFER_SIZE; + + // if we should be storing the received character into the location + // just before the tail (meaning that the head would advance to the + // current location of the tail), we're about to overflow the buffer + // and so we don't write the character or advance the head. + if (i != buffer->tail) { + buffer->buffer[buffer->head] = c; + buffer->head = i; + } +} + +#if !defined(USART0_RX_vect) && defined(USART1_RX_vect) +// do nothing - on the 32u4 the first USART is USART1 +#else +#if !defined(USART_RX_vect) && !defined(SIG_USART0_RECV) && \ + !defined(SIG_UART0_RECV) && !defined(USART0_RX_vect) && \ + !defined(SIG_UART_RECV) + #error "Don't know what the Data Received vector is called for the first UART" +#else + void serialEvent() __attribute__((weak)); + void serialEvent() {} + #define serialEvent_implemented +#if defined(USART_RX_vect) + SIGNAL(USART_RX_vect) +#elif defined(SIG_USART0_RECV) + SIGNAL(SIG_USART0_RECV) +#elif defined(SIG_UART0_RECV) + SIGNAL(SIG_UART0_RECV) +#elif defined(USART0_RX_vect) + SIGNAL(USART0_RX_vect) +#elif defined(SIG_UART_RECV) + SIGNAL(SIG_UART_RECV) +#endif + { + #if defined(UDR0) + unsigned char c = UDR0; + #elif defined(UDR) + unsigned char c = UDR; + #else + #error UDR not defined + #endif + store_char(c, &rx_buffer); + } +#endif +#endif + +#if defined(USART1_RX_vect) + void serialEvent1() __attribute__((weak)); + void serialEvent1() {} + #define serialEvent1_implemented + SIGNAL(USART1_RX_vect) + { + unsigned char c = UDR1; + store_char(c, &rx_buffer1); + } +#elif defined(SIG_USART1_RECV) + #error SIG_USART1_RECV +#endif + +#if defined(USART2_RX_vect) && defined(UDR2) + void serialEvent2() __attribute__((weak)); + void serialEvent2() {} + #define serialEvent2_implemented + SIGNAL(USART2_RX_vect) + { + unsigned char c = UDR2; + store_char(c, &rx_buffer2); + } +#elif defined(SIG_USART2_RECV) + #error SIG_USART2_RECV +#endif + +#if defined(USART3_RX_vect) && defined(UDR3) + void serialEvent3() __attribute__((weak)); + void serialEvent3() {} + #define serialEvent3_implemented + SIGNAL(USART3_RX_vect) + { + unsigned char c = UDR3; + store_char(c, &rx_buffer3); + } +#elif defined(SIG_USART3_RECV) + #error SIG_USART3_RECV +#endif + +void serialEventRun(void) +{ +#ifdef serialEvent_implemented + if (Serial.available()) serialEvent(); +#endif +#ifdef serialEvent1_implemented + if (Serial1.available()) serialEvent1(); +#endif +#ifdef serialEvent2_implemented + if (Serial2.available()) serialEvent2(); +#endif +#ifdef serialEvent3_implemented + if (Serial3.available()) serialEvent3(); +#endif +} + + +#if !defined(USART0_UDRE_vect) && defined(USART1_UDRE_vect) +// do nothing - on the 32u4 the first USART is USART1 +#else +#if !defined(UART0_UDRE_vect) && !defined(UART_UDRE_vect) && !defined(USART0_UDRE_vect) && !defined(USART_UDRE_vect) + #error "Don't know what the Data Register Empty vector is called for the first UART" +#else +#if defined(UART0_UDRE_vect) +ISR(UART0_UDRE_vect) +#elif defined(UART_UDRE_vect) +ISR(UART_UDRE_vect) +#elif defined(USART0_UDRE_vect) +ISR(USART0_UDRE_vect) +#elif defined(USART_UDRE_vect) +ISR(USART_UDRE_vect) +#endif +{ + if (tx_buffer.head == tx_buffer.tail) { + // Buffer empty, so disable interrupts +#if defined(UCSR0B) + cbi(UCSR0B, UDRIE0); +#else + cbi(UCSRB, UDRIE); +#endif + } + else { + // There is more data in the output buffer. Send the next byte + unsigned char c = tx_buffer.buffer[tx_buffer.tail]; + tx_buffer.tail = (tx_buffer.tail + 1) % SERIAL_BUFFER_SIZE; + + #if defined(UDR0) + UDR0 = c; + #elif defined(UDR) + UDR = c; + #else + #error UDR not defined + #endif + } +} +#endif +#endif + +#ifdef USART1_UDRE_vect +ISR(USART1_UDRE_vect) +{ + if (tx_buffer1.head == tx_buffer1.tail) { + // Buffer empty, so disable interrupts + cbi(UCSR1B, UDRIE1); + } + else { + // There is more data in the output buffer. Send the next byte + unsigned char c = tx_buffer1.buffer[tx_buffer1.tail]; + tx_buffer1.tail = (tx_buffer1.tail + 1) % SERIAL_BUFFER_SIZE; + + UDR1 = c; + } +} +#endif + +#ifdef USART2_UDRE_vect +ISR(USART2_UDRE_vect) +{ + if (tx_buffer2.head == tx_buffer2.tail) { + // Buffer empty, so disable interrupts + cbi(UCSR2B, UDRIE2); + } + else { + // There is more data in the output buffer. Send the next byte + unsigned char c = tx_buffer2.buffer[tx_buffer2.tail]; + tx_buffer2.tail = (tx_buffer2.tail + 1) % SERIAL_BUFFER_SIZE; + + UDR2 = c; + } +} +#endif + +#ifdef USART3_UDRE_vect +ISR(USART3_UDRE_vect) +{ + if (tx_buffer3.head == tx_buffer3.tail) { + // Buffer empty, so disable interrupts + cbi(UCSR3B, UDRIE3); + } + else { + // There is more data in the output buffer. Send the next byte + unsigned char c = tx_buffer3.buffer[tx_buffer3.tail]; + tx_buffer3.tail = (tx_buffer3.tail + 1) % SERIAL_BUFFER_SIZE; + + UDR3 = c; + } +} +#endif + + +// Constructors //////////////////////////////////////////////////////////////// + +HardwareSerial::HardwareSerial(ring_buffer *rx_buffer, ring_buffer *tx_buffer, + volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, + volatile uint8_t *ucsra, volatile uint8_t *ucsrb, + volatile uint8_t *udr, + uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udrie, uint8_t u2x) +{ + _rx_buffer = rx_buffer; + _tx_buffer = tx_buffer; + _ubrrh = ubrrh; + _ubrrl = ubrrl; + _ucsra = ucsra; + _ucsrb = ucsrb; + _udr = udr; + _rxen = rxen; + _txen = txen; + _rxcie = rxcie; + _udrie = udrie; + _u2x = u2x; +} + +// Public Methods ////////////////////////////////////////////////////////////// + +void HardwareSerial::begin(unsigned long baud) +{ + uint16_t baud_setting; + bool use_u2x = true; + +#if F_CPU == 16000000UL + // hardcoded exception for compatibility with the bootloader shipped + // with the Duemilanove and previous boards and the firmware on the 8U2 + // on the Uno and Mega 2560. + if (baud == 57600) { + use_u2x = false; + } +#endif + +try_again: + + if (use_u2x) { + *_ucsra = 1 << _u2x; + baud_setting = (F_CPU / 4 / baud - 1) / 2; + } else { + *_ucsra = 0; + baud_setting = (F_CPU / 8 / baud - 1) / 2; + } + + if ((baud_setting > 4095) && use_u2x) + { + use_u2x = false; + goto try_again; + } + + // assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register) + *_ubrrh = baud_setting >> 8; + *_ubrrl = baud_setting; + + sbi(*_ucsrb, _rxen); + sbi(*_ucsrb, _txen); + sbi(*_ucsrb, _rxcie); + cbi(*_ucsrb, _udrie); +} + +void HardwareSerial::end() +{ + // wait for transmission of outgoing data + while (_tx_buffer->head != _tx_buffer->tail) + ; + + cbi(*_ucsrb, _rxen); + cbi(*_ucsrb, _txen); + cbi(*_ucsrb, _rxcie); + cbi(*_ucsrb, _udrie); + + // clear any received data + _rx_buffer->head = _rx_buffer->tail; +} + +int HardwareSerial::available(void) +{ + return (unsigned int)(SERIAL_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) % SERIAL_BUFFER_SIZE; +} + +int HardwareSerial::peek(void) +{ + if (_rx_buffer->head == _rx_buffer->tail) { + return -1; + } else { + return _rx_buffer->buffer[_rx_buffer->tail]; + } +} + +int HardwareSerial::read(void) +{ + // if the head isn't ahead of the tail, we don't have any characters + if (_rx_buffer->head == _rx_buffer->tail) { + return -1; + } else { + unsigned char c = _rx_buffer->buffer[_rx_buffer->tail]; + _rx_buffer->tail = (unsigned int)(_rx_buffer->tail + 1) % SERIAL_BUFFER_SIZE; + return c; + } +} + +void HardwareSerial::flush() +{ + while (_tx_buffer->head != _tx_buffer->tail) + ; +} + +size_t HardwareSerial::write(uint8_t c) +{ + int i = (_tx_buffer->head + 1) % SERIAL_BUFFER_SIZE; + + // If the output buffer is full, there's nothing for it other than to + // wait for the interrupt handler to empty it a bit + // ???: return 0 here instead? + while (i == _tx_buffer->tail) + ; + + _tx_buffer->buffer[_tx_buffer->head] = c; + _tx_buffer->head = i; + + sbi(*_ucsrb, _udrie); + + return 1; +} + +HardwareSerial::operator bool() { + return true; +} + +// Preinstantiate Objects ////////////////////////////////////////////////////// + +#if defined(UBRRH) && defined(UBRRL) + HardwareSerial Serial(&rx_buffer, &tx_buffer, &UBRRH, &UBRRL, &UCSRA, &UCSRB, &UDR, RXEN, TXEN, RXCIE, UDRIE, U2X); +#elif defined(UBRR0H) && defined(UBRR0L) + HardwareSerial Serial(&rx_buffer, &tx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRIE0, U2X0); +#elif defined(USBCON) + // do nothing - Serial object and buffers are initialized in CDC code +#else + #error no serial port defined (port 0) +#endif + +#if defined(UBRR1H) + HardwareSerial Serial1(&rx_buffer1, &tx_buffer1, &UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UDR1, RXEN1, TXEN1, RXCIE1, UDRIE1, U2X1); +#endif +#if defined(UBRR2H) + HardwareSerial Serial2(&rx_buffer2, &tx_buffer2, &UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UDR2, RXEN2, TXEN2, RXCIE2, UDRIE2, U2X2); +#endif +#if defined(UBRR3H) + HardwareSerial Serial3(&rx_buffer3, &tx_buffer3, &UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UDR3, RXEN3, TXEN3, RXCIE3, UDRIE3, U2X3); +#endif + +#endif // whole file + diff --git a/lib/usbhost/arduino-1.0.1/cores/arduino/HardwareSerial.h b/lib/usbhost/arduino-1.0.1/cores/arduino/HardwareSerial.h new file mode 100644 index 0000000000..bf4924c6d4 --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/cores/arduino/HardwareSerial.h @@ -0,0 +1,81 @@ +/* + HardwareSerial.h - Hardware serial library for Wiring + Copyright (c) 2006 Nicholas Zambetti. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Modified 28 September 2010 by Mark Sproul +*/ + +#ifndef HardwareSerial_h +#define HardwareSerial_h + +#include + +#include "Stream.h" + +struct ring_buffer; + +class HardwareSerial : public Stream +{ + private: + ring_buffer *_rx_buffer; + ring_buffer *_tx_buffer; + volatile uint8_t *_ubrrh; + volatile uint8_t *_ubrrl; + volatile uint8_t *_ucsra; + volatile uint8_t *_ucsrb; + volatile uint8_t *_udr; + uint8_t _rxen; + uint8_t _txen; + uint8_t _rxcie; + uint8_t _udrie; + uint8_t _u2x; + public: + HardwareSerial(ring_buffer *rx_buffer, ring_buffer *tx_buffer, + volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, + volatile uint8_t *ucsra, volatile uint8_t *ucsrb, + volatile uint8_t *udr, + uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udrie, uint8_t u2x); + void begin(unsigned long); + void end(); + virtual int available(void); + virtual int peek(void); + virtual int read(void); + virtual void flush(void); + virtual size_t write(uint8_t); + using Print::write; // pull in write(str) and write(buf, size) from Print + operator bool(); +}; + +#if defined(UBRRH) || defined(UBRR0H) + extern HardwareSerial Serial; +#elif defined(USBCON) + #include "USBAPI.h" +// extern HardwareSerial Serial_; +#endif +#if defined(UBRR1H) + extern HardwareSerial Serial1; +#endif +#if defined(UBRR2H) + extern HardwareSerial Serial2; +#endif +#if defined(UBRR3H) + extern HardwareSerial Serial3; +#endif + +extern void serialEventRun(void) __attribute__((weak)); + +#endif diff --git a/lib/usbhost/arduino-1.0.1/cores/arduino/IPAddress.cpp b/lib/usbhost/arduino-1.0.1/cores/arduino/IPAddress.cpp new file mode 100644 index 0000000000..fe3deb77a2 --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/cores/arduino/IPAddress.cpp @@ -0,0 +1,56 @@ + +#include +#include + +IPAddress::IPAddress() +{ + memset(_address, 0, sizeof(_address)); +} + +IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet) +{ + _address[0] = first_octet; + _address[1] = second_octet; + _address[2] = third_octet; + _address[3] = fourth_octet; +} + +IPAddress::IPAddress(uint32_t address) +{ + memcpy(_address, &address, sizeof(_address)); +} + +IPAddress::IPAddress(const uint8_t *address) +{ + memcpy(_address, address, sizeof(_address)); +} + +IPAddress& IPAddress::operator=(const uint8_t *address) +{ + memcpy(_address, address, sizeof(_address)); + return *this; +} + +IPAddress& IPAddress::operator=(uint32_t address) +{ + memcpy(_address, (const uint8_t *)&address, sizeof(_address)); + return *this; +} + +bool IPAddress::operator==(const uint8_t* addr) +{ + return memcmp(addr, _address, sizeof(_address)) == 0; +} + +size_t IPAddress::printTo(Print& p) const +{ + size_t n = 0; + for (int i =0; i < 3; i++) + { + n += p.print(_address[i], DEC); + n += p.print('.'); + } + n += p.print(_address[3], DEC); + return n; +} + diff --git a/lib/usbhost/arduino-1.0.1/cores/arduino/IPAddress.h b/lib/usbhost/arduino-1.0.1/cores/arduino/IPAddress.h new file mode 100644 index 0000000000..2585aec0e4 --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/cores/arduino/IPAddress.h @@ -0,0 +1,76 @@ +/* + * + * MIT License: + * Copyright (c) 2011 Adrian McEwen + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * adrianm@mcqn.com 1/1/2011 + */ + +#ifndef IPAddress_h +#define IPAddress_h + +#include + +// A class to make it easier to handle and pass around IP addresses + +class IPAddress : public Printable { +private: + uint8_t _address[4]; // IPv4 address + // Access the raw byte array containing the address. Because this returns a pointer + // to the internal structure rather than a copy of the address this function should only + // be used when you know that the usage of the returned uint8_t* will be transient and not + // stored. + uint8_t* raw_address() { return _address; }; + +public: + // Constructors + IPAddress(); + IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet); + IPAddress(uint32_t address); + IPAddress(const uint8_t *address); + + // Overloaded cast operator to allow IPAddress objects to be used where a pointer + // to a four-byte uint8_t array is expected + operator uint32_t() { return *((uint32_t*)_address); }; + bool operator==(const IPAddress& addr) { return (*((uint32_t*)_address)) == (*((uint32_t*)addr._address)); }; + bool operator==(const uint8_t* addr); + + // Overloaded index operator to allow getting and setting individual octets of the address + uint8_t operator[](int index) const { return _address[index]; }; + uint8_t& operator[](int index) { return _address[index]; }; + + // Overloaded copy operators to allow initialisation of IPAddress objects from other types + IPAddress& operator=(const uint8_t *address); + IPAddress& operator=(uint32_t address); + + virtual size_t printTo(Print& p) const; + + friend class EthernetClass; + friend class UDP; + friend class Client; + friend class Server; + friend class DhcpClass; + friend class DNSClient; +}; + +const IPAddress INADDR_NONE(0,0,0,0); + + +#endif diff --git a/lib/usbhost/arduino-1.0.1/cores/arduino/Platform.h b/lib/usbhost/arduino-1.0.1/cores/arduino/Platform.h new file mode 100644 index 0000000000..8b8f742771 --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/cores/arduino/Platform.h @@ -0,0 +1,23 @@ + +#ifndef __PLATFORM_H__ +#define __PLATFORM_H__ + +#include +#include +#include +#include +#include + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned long u32; + +#include "Arduino.h" + +#if defined(USBCON) + #include "USBDesc.h" + #include "USBCore.h" + #include "USBAPI.h" +#endif /* if defined(USBCON) */ + +#endif diff --git a/lib/usbhost/arduino-1.0.1/cores/arduino/Print.cpp b/lib/usbhost/arduino-1.0.1/cores/arduino/Print.cpp new file mode 100644 index 0000000000..e541a6ce71 --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/cores/arduino/Print.cpp @@ -0,0 +1,263 @@ +/* + Print.cpp - Base class that provides print() and println() + Copyright (c) 2008 David A. Mellis. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Modified 23 November 2006 by David A. Mellis + */ + +#include +#include +#include +#include +#include "Arduino.h" + +#include "Print.h" + +// Public Methods ////////////////////////////////////////////////////////////// + +/* default implementation: may be overridden */ +size_t Print::write(const uint8_t *buffer, size_t size) +{ + size_t n = 0; + while (size--) { + n += write(*buffer++); + } + return n; +} + +size_t Print::print(const __FlashStringHelper *ifsh) +{ + const char PROGMEM *p = (const char PROGMEM *)ifsh; + size_t n = 0; + while (1) { + unsigned char c = pgm_read_byte(p++); + if (c == 0) break; + n += write(c); + } + return n; +} + +size_t Print::print(const String &s) +{ + size_t n = 0; + for (uint16_t i = 0; i < s.length(); i++) { + n += write(s[i]); + } + return n; +} + +size_t Print::print(const char str[]) +{ + return write(str); +} + +size_t Print::print(char c) +{ + return write(c); +} + +size_t Print::print(unsigned char b, int base) +{ + return print((unsigned long) b, base); +} + +size_t Print::print(int n, int base) +{ + return print((long) n, base); +} + +size_t Print::print(unsigned int n, int base) +{ + return print((unsigned long) n, base); +} + +size_t Print::print(long n, int base) +{ + if (base == 0) { + return write(n); + } else if (base == 10) { + if (n < 0) { + int t = print('-'); + n = -n; + return printNumber(n, 10) + t; + } + return printNumber(n, 10); + } else { + return printNumber(n, base); + } +} + +size_t Print::print(unsigned long n, int base) +{ + if (base == 0) return write(n); + else return printNumber(n, base); +} + +size_t Print::print(double n, int digits) +{ + return printFloat(n, digits); +} + +size_t Print::println(const __FlashStringHelper *ifsh) +{ + size_t n = print(ifsh); + n += println(); + return n; +} + +size_t Print::print(const Printable& x) +{ + return x.printTo(*this); +} + +size_t Print::println(void) +{ + size_t n = print('\r'); + n += print('\n'); + return n; +} + +size_t Print::println(const String &s) +{ + size_t n = print(s); + n += println(); + return n; +} + +size_t Print::println(const char c[]) +{ + size_t n = print(c); + n += println(); + return n; +} + +size_t Print::println(char c) +{ + size_t n = print(c); + n += println(); + return n; +} + +size_t Print::println(unsigned char b, int base) +{ + size_t n = print(b, base); + n += println(); + return n; +} + +size_t Print::println(int num, int base) +{ + size_t n = print(num, base); + n += println(); + return n; +} + +size_t Print::println(unsigned int num, int base) +{ + size_t n = print(num, base); + n += println(); + return n; +} + +size_t Print::println(long num, int base) +{ + size_t n = print(num, base); + n += println(); + return n; +} + +size_t Print::println(unsigned long num, int base) +{ + size_t n = print(num, base); + n += println(); + return n; +} + +size_t Print::println(double num, int digits) +{ + size_t n = print(num, digits); + n += println(); + return n; +} + +size_t Print::println(const Printable& x) +{ + size_t n = print(x); + n += println(); + return n; +} + +// Private Methods ///////////////////////////////////////////////////////////// + +size_t Print::printNumber(unsigned long n, uint8_t base) { + char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte. + char *str = &buf[sizeof(buf) - 1]; + + *str = '\0'; + + // prevent crash if called with base == 1 + if (base < 2) base = 10; + + do { + unsigned long m = n; + n /= base; + char c = m - base * n; + *--str = c < 10 ? c + '0' : c + 'A' - 10; + } while(n); + + return write(str); +} + +size_t Print::printFloat(double number, uint8_t digits) +{ + size_t n = 0; + + // Handle negative numbers + if (number < 0.0) + { + n += print('-'); + number = -number; + } + + // Round correctly so that print(1.999, 2) prints as "2.00" + double rounding = 0.5; + for (uint8_t i=0; i 0) { + n += print("."); + } + + // Extract digits from the remainder one at a time + while (digits-- > 0) + { + remainder *= 10.0; + int toPrint = int(remainder); + n += print(toPrint); + remainder -= toPrint; + } + + return n; +} diff --git a/lib/usbhost/arduino-1.0.1/cores/arduino/Print.h b/lib/usbhost/arduino-1.0.1/cores/arduino/Print.h new file mode 100644 index 0000000000..1af6b723fc --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/cores/arduino/Print.h @@ -0,0 +1,78 @@ +/* + Print.h - Base class that provides print() and println() + Copyright (c) 2008 David A. Mellis. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef Print_h +#define Print_h + +#include +#include // for size_t + +#include "WString.h" +#include "Printable.h" + +#define DEC 10 +#define HEX 16 +#define OCT 8 +#define BIN 2 + +class Print +{ + private: + int write_error; + size_t printNumber(unsigned long, uint8_t); + size_t printFloat(double, uint8_t); + protected: + void setWriteError(int err = 1) { write_error = err; } + public: + Print() : write_error(0) {} + + int getWriteError() { return write_error; } + void clearWriteError() { setWriteError(0); } + + virtual size_t write(uint8_t) = 0; + size_t write(const char *str) { return write((const uint8_t *)str, strlen(str)); } + virtual size_t write(const uint8_t *buffer, size_t size); + + size_t print(const __FlashStringHelper *); + size_t print(const String &); + size_t print(const char[]); + size_t print(char); + size_t print(unsigned char, int = DEC); + size_t print(int, int = DEC); + size_t print(unsigned int, int = DEC); + size_t print(long, int = DEC); + size_t print(unsigned long, int = DEC); + size_t print(double, int = 2); + size_t print(const Printable&); + + size_t println(const __FlashStringHelper *); + size_t println(const String &s); + size_t println(const char[]); + size_t println(char); + size_t println(unsigned char, int = DEC); + size_t println(int, int = DEC); + size_t println(unsigned int, int = DEC); + size_t println(long, int = DEC); + size_t println(unsigned long, int = DEC); + size_t println(double, int = 2); + size_t println(const Printable&); + size_t println(void); +}; + +#endif diff --git a/lib/usbhost/arduino-1.0.1/cores/arduino/Printable.h b/lib/usbhost/arduino-1.0.1/cores/arduino/Printable.h new file mode 100644 index 0000000000..d03c9af62c --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/cores/arduino/Printable.h @@ -0,0 +1,40 @@ +/* + Printable.h - Interface class that allows printing of complex types + Copyright (c) 2011 Adrian McEwen. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef Printable_h +#define Printable_h + +#include + +class Print; + +/** The Printable class provides a way for new classes to allow themselves to be printed. + By deriving from Printable and implementing the printTo method, it will then be possible + for users to print out instances of this class by passing them into the usual + Print::print and Print::println methods. +*/ + +class Printable +{ + public: + virtual size_t printTo(Print& p) const = 0; +}; + +#endif + diff --git a/lib/usbhost/arduino-1.0.1/cores/arduino/Server.h b/lib/usbhost/arduino-1.0.1/cores/arduino/Server.h new file mode 100644 index 0000000000..9674c76269 --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/cores/arduino/Server.h @@ -0,0 +1,9 @@ +#ifndef server_h +#define server_h + +class Server : public Print { +public: + virtual void begin() =0; +}; + +#endif diff --git a/lib/usbhost/arduino-1.0.1/cores/arduino/Stream.cpp b/lib/usbhost/arduino-1.0.1/cores/arduino/Stream.cpp new file mode 100644 index 0000000000..aafb7fcf97 --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/cores/arduino/Stream.cpp @@ -0,0 +1,270 @@ +/* + Stream.cpp - adds parsing methods to Stream class + Copyright (c) 2008 David A. Mellis. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Created July 2011 + parsing functions based on TextFinder library by Michael Margolis + */ + +#include "Arduino.h" +#include "Stream.h" + +#define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait +#define NO_SKIP_CHAR 1 // a magic char not found in a valid ASCII numeric field + +// private method to read stream with timeout +int Stream::timedRead() +{ + int c; + _startMillis = millis(); + do { + c = read(); + if (c >= 0) return c; + } while(millis() - _startMillis < _timeout); + return -1; // -1 indicates timeout +} + +// private method to peek stream with timeout +int Stream::timedPeek() +{ + int c; + _startMillis = millis(); + do { + c = peek(); + if (c >= 0) return c; + } while(millis() - _startMillis < _timeout); + return -1; // -1 indicates timeout +} + +// returns peek of the next digit in the stream or -1 if timeout +// discards non-numeric characters +int Stream::peekNextDigit() +{ + int c; + while (1) { + c = timedPeek(); + if (c < 0) return c; // timeout + if (c == '-') return c; + if (c >= '0' && c <= '9') return c; + read(); // discard non-numeric + } +} + +// Public Methods +////////////////////////////////////////////////////////////// + +void Stream::setTimeout(unsigned long timeout) // sets the maximum number of milliseconds to wait +{ + _timeout = timeout; +} + + // find returns true if the target string is found +bool Stream::find(char *target) +{ + return findUntil(target, NULL); +} + +// reads data from the stream until the target string of given length is found +// returns true if target string is found, false if timed out +bool Stream::find(char *target, size_t length) +{ + return findUntil(target, length, NULL, 0); +} + +// as find but search ends if the terminator string is found +bool Stream::findUntil(char *target, char *terminator) +{ + return findUntil(target, strlen(target), terminator, strlen(terminator)); +} + +// reads data from the stream until the target string of the given length is found +// search terminated if the terminator string is found +// returns true if target string is found, false if terminated or timed out +bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t termLen) +{ + size_t index = 0; // maximum target string length is 64k bytes! + size_t termIndex = 0; + int c; + + if( *target == 0) + return true; // return true if target is a null string + while( (c = timedRead()) > 0){ + + if(c != target[index]) + index = 0; // reset index if any char does not match + + if( c == target[index]){ + //////Serial.print("found "); Serial.write(c); Serial.print("index now"); Serial.println(index+1); + if(++index >= targetLen){ // return true if all chars in the target match + return true; + } + } + + if(termLen > 0 && c == terminator[termIndex]){ + if(++termIndex >= termLen) + return false; // return false if terminate string found before target string + } + else + termIndex = 0; + } + return false; +} + + +// returns the first valid (long) integer value from the current position. +// initial characters that are not digits (or the minus sign) are skipped +// function is terminated by the first character that is not a digit. +long Stream::parseInt() +{ + return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout) +} + +// as above but a given skipChar is ignored +// this allows format characters (typically commas) in values to be ignored +long Stream::parseInt(char skipChar) +{ + boolean isNegative = false; + long value = 0; + int c; + + c = peekNextDigit(); + // ignore non numeric leading characters + if(c < 0) + return 0; // zero returned if timeout + + do{ + if(c == skipChar) + ; // ignore this charactor + else if(c == '-') + isNegative = true; + else if(c >= '0' && c <= '9') // is c a digit? + value = value * 10 + c - '0'; + read(); // consume the character we got with peek + c = timedPeek(); + } + while( (c >= '0' && c <= '9') || c == skipChar ); + + if(isNegative) + value = -value; + return value; +} + + +// as parseInt but returns a floating point value +float Stream::parseFloat() +{ + return parseFloat(NO_SKIP_CHAR); +} + +// as above but the given skipChar is ignored +// this allows format characters (typically commas) in values to be ignored +float Stream::parseFloat(char skipChar){ + boolean isNegative = false; + boolean isFraction = false; + long value = 0; + char c; + float fraction = 1.0; + + c = peekNextDigit(); + // ignore non numeric leading characters + if(c < 0) + return 0; // zero returned if timeout + + do{ + if(c == skipChar) + ; // ignore + else if(c == '-') + isNegative = true; + else if (c == '.') + isFraction = true; + else if(c >= '0' && c <= '9') { // is c a digit? + value = value * 10 + c - '0'; + if(isFraction) + fraction *= 0.1; + } + read(); // consume the character we got with peek + c = timedPeek(); + } + while( (c >= '0' && c <= '9') || c == '.' || c == skipChar ); + + if(isNegative) + value = -value; + if(isFraction) + return value * fraction; + else + return value; +} + +// read characters from stream into buffer +// terminates if length characters have been read, or timeout (see setTimeout) +// returns the number of characters placed in the buffer +// the buffer is NOT null terminated. +// +size_t Stream::readBytes(char *buffer, size_t length) +{ + size_t count = 0; + while (count < length) { + int c = timedRead(); + if (c < 0) break; + *buffer++ = (char)c; + count++; + } + return count; +} + + +// as readBytes with terminator character +// terminates if length characters have been read, timeout, or if the terminator character detected +// returns the number of characters placed in the buffer (0 means no valid data found) + +size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length) +{ + if (length < 1) return 0; + size_t index = 0; + while (index < length) { + int c = timedRead(); + if (c < 0 || c == terminator) break; + *buffer++ = (char)c; + index++; + } + return index; // return number of characters, not including null terminator +} + +String Stream::readString() +{ + String ret; + int c = timedRead(); + while (c >= 0) + { + ret += (char)c; + c = timedRead(); + } + return ret; +} + +String Stream::readStringUntil(char terminator) +{ + String ret; + int c = timedRead(); + while (c >= 0 && c != terminator) + { + ret += (char)c; + c = timedRead(); + } + return ret; +} + diff --git a/lib/usbhost/arduino-1.0.1/cores/arduino/Stream.h b/lib/usbhost/arduino-1.0.1/cores/arduino/Stream.h new file mode 100644 index 0000000000..58bbf752f3 --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/cores/arduino/Stream.h @@ -0,0 +1,96 @@ +/* + Stream.h - base class for character-based streams. + Copyright (c) 2010 David A. Mellis. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + parsing functions based on TextFinder library by Michael Margolis +*/ + +#ifndef Stream_h +#define Stream_h + +#include +#include "Print.h" + +// compatability macros for testing +/* +#define getInt() parseInt() +#define getInt(skipChar) parseInt(skipchar) +#define getFloat() parseFloat() +#define getFloat(skipChar) parseFloat(skipChar) +#define getString( pre_string, post_string, buffer, length) +readBytesBetween( pre_string, terminator, buffer, length) +*/ + +class Stream : public Print +{ + private: + unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read + unsigned long _startMillis; // used for timeout measurement + int timedRead(); // private method to read stream with timeout + int timedPeek(); // private method to peek stream with timeout + int peekNextDigit(); // returns the next numeric digit in the stream or -1 if timeout + + public: + virtual int available() = 0; + virtual int read() = 0; + virtual int peek() = 0; + virtual void flush() = 0; + + Stream() {_timeout=1000;} + +// parsing methods + + void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second + + bool find(char *target); // reads data from the stream until the target string is found + // returns true if target string is found, false if timed out (see setTimeout) + + bool find(char *target, size_t length); // reads data from the stream until the target string of given length is found + // returns true if target string is found, false if timed out + + bool findUntil(char *target, char *terminator); // as find but search ends if the terminator string is found + + bool findUntil(char *target, size_t targetLen, char *terminate, size_t termLen); // as above but search ends if the terminate string is found + + + long parseInt(); // returns the first valid (long) integer value from the current position. + // initial characters that are not digits (or the minus sign) are skipped + // integer is terminated by the first character that is not a digit. + + float parseFloat(); // float version of parseInt + + size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer + // terminates if length characters have been read or timeout (see setTimeout) + // returns the number of characters placed in the buffer (0 means no valid data found) + + size_t readBytesUntil( char terminator, char *buffer, size_t length); // as readBytes with terminator character + // terminates if length characters have been read, timeout, or if the terminator character detected + // returns the number of characters placed in the buffer (0 means no valid data found) + + // Arduino String functions to be added here + String readString(); + String readStringUntil(char terminator); + + protected: + long parseInt(char skipChar); // as above but the given skipChar is ignored + // as above but the given skipChar is ignored + // this allows format characters (typically commas) in values to be ignored + + float parseFloat(char skipChar); // as above but the given skipChar is ignored +}; + +#endif diff --git a/lib/usbhost/arduino-1.0.1/cores/arduino/Tone.cpp b/lib/usbhost/arduino-1.0.1/cores/arduino/Tone.cpp new file mode 100644 index 0000000000..20eed3f483 --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/cores/arduino/Tone.cpp @@ -0,0 +1,601 @@ +/* Tone.cpp + + A Tone Generator Library + + Written by Brett Hagman + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Version Modified By Date Comments +------- ----------- -------- -------- +0001 B Hagman 09/08/02 Initial coding +0002 B Hagman 09/08/18 Multiple pins +0003 B Hagman 09/08/18 Moved initialization from constructor to begin() +0004 B Hagman 09/09/26 Fixed problems with ATmega8 +0005 B Hagman 09/11/23 Scanned prescalars for best fit on 8 bit timers + 09/11/25 Changed pin toggle method to XOR + 09/11/25 Fixed timer0 from being excluded +0006 D Mellis 09/12/29 Replaced objects with functions +0007 M Sproul 10/08/29 Changed #ifdefs from cpu to register +*************************************************/ + +#include +#include +#include "Arduino.h" +#include "pins_arduino.h" + +#if defined(__AVR_ATmega8__) || defined(__AVR_ATmega128__) +#define TCCR2A TCCR2 +#define TCCR2B TCCR2 +#define COM2A1 COM21 +#define COM2A0 COM20 +#define OCR2A OCR2 +#define TIMSK2 TIMSK +#define OCIE2A OCIE2 +#define TIMER2_COMPA_vect TIMER2_COMP_vect +#define TIMSK1 TIMSK +#endif + +// timerx_toggle_count: +// > 0 - duration specified +// = 0 - stopped +// < 0 - infinitely (until stop() method called, or new play() called) + +#if !defined(__AVR_ATmega8__) +volatile long timer0_toggle_count; +volatile uint8_t *timer0_pin_port; +volatile uint8_t timer0_pin_mask; +#endif + +volatile long timer1_toggle_count; +volatile uint8_t *timer1_pin_port; +volatile uint8_t timer1_pin_mask; +volatile long timer2_toggle_count; +volatile uint8_t *timer2_pin_port; +volatile uint8_t timer2_pin_mask; + +#if defined(TIMSK3) +volatile long timer3_toggle_count; +volatile uint8_t *timer3_pin_port; +volatile uint8_t timer3_pin_mask; +#endif + +#if defined(TIMSK4) +volatile long timer4_toggle_count; +volatile uint8_t *timer4_pin_port; +volatile uint8_t timer4_pin_mask; +#endif + +#if defined(TIMSK5) +volatile long timer5_toggle_count; +volatile uint8_t *timer5_pin_port; +volatile uint8_t timer5_pin_mask; +#endif + + +// MLS: This does not make sense, the 3 options are the same +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) + +#define AVAILABLE_TONE_PINS 1 + +const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 3, 4, 5, 1, 0 */ }; +static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255, 255, 255, 255, 255 */ }; + +#elif defined(__AVR_ATmega8__) + +#define AVAILABLE_TONE_PINS 1 + +const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 1 */ }; +static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255 */ }; + +#else + +#define AVAILABLE_TONE_PINS 1 + +// Leave timer 0 to last. +const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 1, 0 */ }; +static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255, 255 */ }; + +#endif + + + +static int8_t toneBegin(uint8_t _pin) +{ + int8_t _timer = -1; + + // if we're already using the pin, the timer should be configured. + for (int i = 0; i < AVAILABLE_TONE_PINS; i++) { + if (tone_pins[i] == _pin) { + return pgm_read_byte(tone_pin_to_timer_PGM + i); + } + } + + // search for an unused timer. + for (int i = 0; i < AVAILABLE_TONE_PINS; i++) { + if (tone_pins[i] == 255) { + tone_pins[i] = _pin; + _timer = pgm_read_byte(tone_pin_to_timer_PGM + i); + break; + } + } + + if (_timer != -1) + { + // Set timer specific stuff + // All timers in CTC mode + // 8 bit timers will require changing prescalar values, + // whereas 16 bit timers are set to either ck/1 or ck/64 prescalar + switch (_timer) + { + #if defined(TCCR0A) && defined(TCCR0B) + case 0: + // 8 bit timer + TCCR0A = 0; + TCCR0B = 0; + bitWrite(TCCR0A, WGM01, 1); + bitWrite(TCCR0B, CS00, 1); + timer0_pin_port = portOutputRegister(digitalPinToPort(_pin)); + timer0_pin_mask = digitalPinToBitMask(_pin); + break; + #endif + + #if defined(TCCR1A) && defined(TCCR1B) && defined(WGM12) + case 1: + // 16 bit timer + TCCR1A = 0; + TCCR1B = 0; + bitWrite(TCCR1B, WGM12, 1); + bitWrite(TCCR1B, CS10, 1); + timer1_pin_port = portOutputRegister(digitalPinToPort(_pin)); + timer1_pin_mask = digitalPinToBitMask(_pin); + break; + #endif + + #if defined(TCCR2A) && defined(TCCR2B) + case 2: + // 8 bit timer + TCCR2A = 0; + TCCR2B = 0; + bitWrite(TCCR2A, WGM21, 1); + bitWrite(TCCR2B, CS20, 1); + timer2_pin_port = portOutputRegister(digitalPinToPort(_pin)); + timer2_pin_mask = digitalPinToBitMask(_pin); + break; + #endif + + #if defined(TCCR3A) && defined(TCCR3B) && defined(TIMSK3) + case 3: + // 16 bit timer + TCCR3A = 0; + TCCR3B = 0; + bitWrite(TCCR3B, WGM32, 1); + bitWrite(TCCR3B, CS30, 1); + timer3_pin_port = portOutputRegister(digitalPinToPort(_pin)); + timer3_pin_mask = digitalPinToBitMask(_pin); + break; + #endif + + #if defined(TCCR4A) && defined(TCCR4B) && defined(TIMSK4) + case 4: + // 16 bit timer + TCCR4A = 0; + TCCR4B = 0; + #if defined(WGM42) + bitWrite(TCCR4B, WGM42, 1); + #elif defined(CS43) + #warning this may not be correct + // atmega32u4 + bitWrite(TCCR4B, CS43, 1); + #endif + bitWrite(TCCR4B, CS40, 1); + timer4_pin_port = portOutputRegister(digitalPinToPort(_pin)); + timer4_pin_mask = digitalPinToBitMask(_pin); + break; + #endif + + #if defined(TCCR5A) && defined(TCCR5B) && defined(TIMSK5) + case 5: + // 16 bit timer + TCCR5A = 0; + TCCR5B = 0; + bitWrite(TCCR5B, WGM52, 1); + bitWrite(TCCR5B, CS50, 1); + timer5_pin_port = portOutputRegister(digitalPinToPort(_pin)); + timer5_pin_mask = digitalPinToBitMask(_pin); + break; + #endif + } + } + + return _timer; +} + + + +// frequency (in hertz) and duration (in milliseconds). + +void tone(uint8_t _pin, unsigned int frequency, unsigned long duration) +{ + uint8_t prescalarbits = 0b001; + long toggle_count = 0; + uint32_t ocr = 0; + int8_t _timer; + + _timer = toneBegin(_pin); + + if (_timer >= 0) + { + // Set the pinMode as OUTPUT + pinMode(_pin, OUTPUT); + + // if we are using an 8 bit timer, scan through prescalars to find the best fit + if (_timer == 0 || _timer == 2) + { + ocr = F_CPU / frequency / 2 - 1; + prescalarbits = 0b001; // ck/1: same for both timers + if (ocr > 255) + { + ocr = F_CPU / frequency / 2 / 8 - 1; + prescalarbits = 0b010; // ck/8: same for both timers + + if (_timer == 2 && ocr > 255) + { + ocr = F_CPU / frequency / 2 / 32 - 1; + prescalarbits = 0b011; + } + + if (ocr > 255) + { + ocr = F_CPU / frequency / 2 / 64 - 1; + prescalarbits = _timer == 0 ? 0b011 : 0b100; + + if (_timer == 2 && ocr > 255) + { + ocr = F_CPU / frequency / 2 / 128 - 1; + prescalarbits = 0b101; + } + + if (ocr > 255) + { + ocr = F_CPU / frequency / 2 / 256 - 1; + prescalarbits = _timer == 0 ? 0b100 : 0b110; + if (ocr > 255) + { + // can't do any better than /1024 + ocr = F_CPU / frequency / 2 / 1024 - 1; + prescalarbits = _timer == 0 ? 0b101 : 0b111; + } + } + } + } + +#if defined(TCCR0B) + if (_timer == 0) + { + TCCR0B = prescalarbits; + } + else +#endif +#if defined(TCCR2B) + { + TCCR2B = prescalarbits; + } +#else + { + // dummy place holder to make the above ifdefs work + } +#endif + } + else + { + // two choices for the 16 bit timers: ck/1 or ck/64 + ocr = F_CPU / frequency / 2 - 1; + + prescalarbits = 0b001; + if (ocr > 0xffff) + { + ocr = F_CPU / frequency / 2 / 64 - 1; + prescalarbits = 0b011; + } + + if (_timer == 1) + { +#if defined(TCCR1B) + TCCR1B = (TCCR1B & 0b11111000) | prescalarbits; +#endif + } +#if defined(TCCR3B) + else if (_timer == 3) + TCCR3B = (TCCR3B & 0b11111000) | prescalarbits; +#endif +#if defined(TCCR4B) + else if (_timer == 4) + TCCR4B = (TCCR4B & 0b11111000) | prescalarbits; +#endif +#if defined(TCCR5B) + else if (_timer == 5) + TCCR5B = (TCCR5B & 0b11111000) | prescalarbits; +#endif + + } + + + // Calculate the toggle count + if (duration > 0) + { + toggle_count = 2 * frequency * duration / 1000; + } + else + { + toggle_count = -1; + } + + // Set the OCR for the given timer, + // set the toggle count, + // then turn on the interrupts + switch (_timer) + { + +#if defined(OCR0A) && defined(TIMSK0) && defined(OCIE0A) + case 0: + OCR0A = ocr; + timer0_toggle_count = toggle_count; + bitWrite(TIMSK0, OCIE0A, 1); + break; +#endif + + case 1: +#if defined(OCR1A) && defined(TIMSK1) && defined(OCIE1A) + OCR1A = ocr; + timer1_toggle_count = toggle_count; + bitWrite(TIMSK1, OCIE1A, 1); +#elif defined(OCR1A) && defined(TIMSK) && defined(OCIE1A) + // this combination is for at least the ATmega32 + OCR1A = ocr; + timer1_toggle_count = toggle_count; + bitWrite(TIMSK, OCIE1A, 1); +#endif + break; + +#if defined(OCR2A) && defined(TIMSK2) && defined(OCIE2A) + case 2: + OCR2A = ocr; + timer2_toggle_count = toggle_count; + bitWrite(TIMSK2, OCIE2A, 1); + break; +#endif + +#if defined(TIMSK3) + case 3: + OCR3A = ocr; + timer3_toggle_count = toggle_count; + bitWrite(TIMSK3, OCIE3A, 1); + break; +#endif + +#if defined(TIMSK4) + case 4: + OCR4A = ocr; + timer4_toggle_count = toggle_count; + bitWrite(TIMSK4, OCIE4A, 1); + break; +#endif + +#if defined(OCR5A) && defined(TIMSK5) && defined(OCIE5A) + case 5: + OCR5A = ocr; + timer5_toggle_count = toggle_count; + bitWrite(TIMSK5, OCIE5A, 1); + break; +#endif + + } + } +} + + +// XXX: this function only works properly for timer 2 (the only one we use +// currently). for the others, it should end the tone, but won't restore +// proper PWM functionality for the timer. +void disableTimer(uint8_t _timer) +{ + switch (_timer) + { + case 0: + #if defined(TIMSK0) + TIMSK0 = 0; + #elif defined(TIMSK) + TIMSK = 0; // atmega32 + #endif + break; + +#if defined(TIMSK1) && defined(OCIE1A) + case 1: + bitWrite(TIMSK1, OCIE1A, 0); + break; +#endif + + case 2: + #if defined(TIMSK2) && defined(OCIE2A) + bitWrite(TIMSK2, OCIE2A, 0); // disable interrupt + #endif + #if defined(TCCR2A) && defined(WGM20) + TCCR2A = (1 << WGM20); + #endif + #if defined(TCCR2B) && defined(CS22) + TCCR2B = (TCCR2B & 0b11111000) | (1 << CS22); + #endif + #if defined(OCR2A) + OCR2A = 0; + #endif + break; + +#if defined(TIMSK3) + case 3: + TIMSK3 = 0; + break; +#endif + +#if defined(TIMSK4) + case 4: + TIMSK4 = 0; + break; +#endif + +#if defined(TIMSK5) + case 5: + TIMSK5 = 0; + break; +#endif + } +} + + +void noTone(uint8_t _pin) +{ + int8_t _timer = -1; + + for (int i = 0; i < AVAILABLE_TONE_PINS; i++) { + if (tone_pins[i] == _pin) { + _timer = pgm_read_byte(tone_pin_to_timer_PGM + i); + tone_pins[i] = 255; + } + } + + disableTimer(_timer); + + digitalWrite(_pin, 0); +} + +#if 0 +#if !defined(__AVR_ATmega8__) +ISR(TIMER0_COMPA_vect) +{ + if (timer0_toggle_count != 0) + { + // toggle the pin + *timer0_pin_port ^= timer0_pin_mask; + + if (timer0_toggle_count > 0) + timer0_toggle_count--; + } + else + { + disableTimer(0); + *timer0_pin_port &= ~(timer0_pin_mask); // keep pin low after stop + } +} +#endif + + +ISR(TIMER1_COMPA_vect) +{ + if (timer1_toggle_count != 0) + { + // toggle the pin + *timer1_pin_port ^= timer1_pin_mask; + + if (timer1_toggle_count > 0) + timer1_toggle_count--; + } + else + { + disableTimer(1); + *timer1_pin_port &= ~(timer1_pin_mask); // keep pin low after stop + } +} +#endif + + +ISR(TIMER2_COMPA_vect) +{ + + if (timer2_toggle_count != 0) + { + // toggle the pin + *timer2_pin_port ^= timer2_pin_mask; + + if (timer2_toggle_count > 0) + timer2_toggle_count--; + } + else + { + // need to call noTone() so that the tone_pins[] entry is reset, so the + // timer gets initialized next time we call tone(). + // XXX: this assumes timer 2 is always the first one used. + noTone(tone_pins[0]); +// disableTimer(2); +// *timer2_pin_port &= ~(timer2_pin_mask); // keep pin low after stop + } +} + + + +//#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +#if 0 + +ISR(TIMER3_COMPA_vect) +{ + if (timer3_toggle_count != 0) + { + // toggle the pin + *timer3_pin_port ^= timer3_pin_mask; + + if (timer3_toggle_count > 0) + timer3_toggle_count--; + } + else + { + disableTimer(3); + *timer3_pin_port &= ~(timer3_pin_mask); // keep pin low after stop + } +} + +ISR(TIMER4_COMPA_vect) +{ + if (timer4_toggle_count != 0) + { + // toggle the pin + *timer4_pin_port ^= timer4_pin_mask; + + if (timer4_toggle_count > 0) + timer4_toggle_count--; + } + else + { + disableTimer(4); + *timer4_pin_port &= ~(timer4_pin_mask); // keep pin low after stop + } +} + +ISR(TIMER5_COMPA_vect) +{ + if (timer5_toggle_count != 0) + { + // toggle the pin + *timer5_pin_port ^= timer5_pin_mask; + + if (timer5_toggle_count > 0) + timer5_toggle_count--; + } + else + { + disableTimer(5); + *timer5_pin_port &= ~(timer5_pin_mask); // keep pin low after stop + } +} + +#endif diff --git a/lib/usbhost/arduino-1.0.1/cores/arduino/USBAPI.h b/lib/usbhost/arduino-1.0.1/cores/arduino/USBAPI.h new file mode 100644 index 0000000000..d5abdb690d --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/cores/arduino/USBAPI.h @@ -0,0 +1,195 @@ + + +#ifndef __USBAPI__ +#define __USBAPI__ + +#if defined(USBCON) + +//================================================================================ +//================================================================================ +// USB + +class USBDevice_ +{ +public: + USBDevice_(); + bool configured(); + + void attach(); + void detach(); // Serial port goes down too... + void poll(); +}; +extern USBDevice_ USBDevice; + +//================================================================================ +//================================================================================ +// Serial over CDC (Serial1 is the physical port) + +class Serial_ : public Stream +{ +private: + ring_buffer *_cdc_rx_buffer; +public: + void begin(uint16_t baud_count); + void end(void); + + virtual int available(void); + virtual void accept(void); + virtual int peek(void); + virtual int read(void); + virtual void flush(void); + virtual size_t write(uint8_t); + operator bool(); +}; +extern Serial_ Serial; + +//================================================================================ +//================================================================================ +// Mouse + +#define MOUSE_LEFT 1 +#define MOUSE_RIGHT 2 +#define MOUSE_MIDDLE 4 +#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE) + +class Mouse_ +{ +private: + uint8_t _buttons; + void buttons(uint8_t b); +public: + Mouse_(void); + void begin(void); + void end(void); + void click(uint8_t b = MOUSE_LEFT); + void move(signed char x, signed char y, signed char wheel = 0); + void press(uint8_t b = MOUSE_LEFT); // press LEFT by default + void release(uint8_t b = MOUSE_LEFT); // release LEFT by default + bool isPressed(uint8_t b = MOUSE_LEFT); // check LEFT by default +}; +extern Mouse_ Mouse; + +//================================================================================ +//================================================================================ +// Keyboard + +#define KEY_LEFT_CTRL 0x80 +#define KEY_LEFT_SHIFT 0x81 +#define KEY_LEFT_ALT 0x82 +#define KEY_LEFT_GUI 0x83 +#define KEY_RIGHT_CTRL 0x84 +#define KEY_RIGHT_SHIFT 0x85 +#define KEY_RIGHT_ALT 0x86 +#define KEY_RIGHT_GUI 0x87 + +#define KEY_UP_ARROW 0xDA +#define KEY_DOWN_ARROW 0xD9 +#define KEY_LEFT_ARROW 0xD8 +#define KEY_RIGHT_ARROW 0xD7 +#define KEY_BACKSPACE 0xB2 +#define KEY_TAB 0xB3 +#define KEY_RETURN 0xB0 +#define KEY_ESC 0xB1 +#define KEY_INSERT 0xD1 +#define KEY_DELETE 0xD4 +#define KEY_PAGE_UP 0xD3 +#define KEY_PAGE_DOWN 0xD6 +#define KEY_HOME 0xD2 +#define KEY_END 0xD5 +#define KEY_CAPS_LOCK 0xC1 +#define KEY_F1 0xC2 +#define KEY_F2 0xC3 +#define KEY_F3 0xC4 +#define KEY_F4 0xC5 +#define KEY_F5 0xC6 +#define KEY_F6 0xC7 +#define KEY_F7 0xC8 +#define KEY_F8 0xC9 +#define KEY_F9 0xCA +#define KEY_F10 0xCB +#define KEY_F11 0xCC +#define KEY_F12 0xCD + +// Low level key report: up to 6 keys and shift, ctrl etc at once +typedef struct +{ + uint8_t modifiers; + uint8_t reserved; + uint8_t keys[6]; +} KeyReport; + +class Keyboard_ : public Print +{ +private: + KeyReport _keyReport; + void sendReport(KeyReport* keys); +public: + Keyboard_(void); + void begin(void); + void end(void); + virtual size_t write(uint8_t k); + virtual size_t press(uint8_t k); + virtual size_t release(uint8_t k); + virtual void releaseAll(void); +}; +extern Keyboard_ Keyboard; + +//================================================================================ +//================================================================================ +// Low level API + +typedef struct +{ + uint8_t bmRequestType; + uint8_t bRequest; + uint8_t wValueL; + uint8_t wValueH; + uint16_t wIndex; + uint16_t wLength; +} Setup; + +//================================================================================ +//================================================================================ +// HID 'Driver' + +int HID_GetInterface(uint8_t* interfaceNum); +int HID_GetDescriptor(int i); +bool HID_Setup(Setup& setup); +void HID_SendReport(uint8_t id, const void* data, int len); + +//================================================================================ +//================================================================================ +// MSC 'Driver' + +int MSC_GetInterface(uint8_t* interfaceNum); +int MSC_GetDescriptor(int i); +bool MSC_Setup(Setup& setup); +bool MSC_Data(uint8_t rx,uint8_t tx); + +//================================================================================ +//================================================================================ +// CSC 'Driver' + +int CDC_GetInterface(uint8_t* interfaceNum); +int CDC_GetDescriptor(int i); +bool CDC_Setup(Setup& setup); + +//================================================================================ +//================================================================================ + +#define TRANSFER_PGM 0x80 +#define TRANSFER_RELEASE 0x40 +#define TRANSFER_ZERO 0x20 + +int USB_SendControl(uint8_t flags, const void* d, int len); +int USB_RecvControl(void* d, int len); + +uint8_t USB_Available(uint8_t ep); +int USB_Send(uint8_t ep, const void* data, int len); // blocking +int USB_Recv(uint8_t ep, void* data, int len); // non-blocking +int USB_Recv(uint8_t ep); // non-blocking +void USB_Flush(uint8_t ep); + +#endif + +#endif /* if defined(USBCON) */ \ No newline at end of file diff --git a/lib/usbhost/arduino-1.0.1/cores/arduino/USBCore.cpp b/lib/usbhost/arduino-1.0.1/cores/arduino/USBCore.cpp new file mode 100644 index 0000000000..6766be61ab --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/cores/arduino/USBCore.cpp @@ -0,0 +1,672 @@ + + +/* Copyright (c) 2010, Peter Barrett +** +** Permission to use, copy, modify, and/or distribute this software for +** any purpose with or without fee is hereby granted, provided that the +** above copyright notice and this permission notice appear in all copies. +** +** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR +** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES +** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +** SOFTWARE. +*/ + +#include "Platform.h" +#include "USBAPI.h" +#include "USBDesc.h" + +#if defined(USBCON) + +#define EP_TYPE_CONTROL 0x00 +#define EP_TYPE_BULK_IN 0x81 +#define EP_TYPE_BULK_OUT 0x80 +#define EP_TYPE_INTERRUPT_IN 0xC1 +#define EP_TYPE_INTERRUPT_OUT 0xC0 +#define EP_TYPE_ISOCHRONOUS_IN 0x41 +#define EP_TYPE_ISOCHRONOUS_OUT 0x40 + +/** Pulse generation counters to keep track of the number of milliseconds remaining for each pulse type */ +#define TX_RX_LED_PULSE_MS 100 +volatile u8 TxLEDPulse; /**< Milliseconds remaining for data Tx LED pulse */ +volatile u8 RxLEDPulse; /**< Milliseconds remaining for data Rx LED pulse */ + +//================================================================== +//================================================================== + +extern const u16 STRING_LANGUAGE[] PROGMEM; +extern const u16 STRING_IPRODUCT[] PROGMEM; +extern const u16 STRING_IMANUFACTURER[] PROGMEM; +extern const DeviceDescriptor USB_DeviceDescriptor PROGMEM; +extern const DeviceDescriptor USB_DeviceDescriptorA PROGMEM; + +const u16 STRING_LANGUAGE[2] = { + (3<<8) | (2+2), + 0x0409 // English +}; + +const u16 STRING_IPRODUCT[17] = { + (3<<8) | (2+2*16), +#if USB_PID == 0x8036 + 'A','r','d','u','i','n','o',' ','L','e','o','n','a','r','d','o' +#else + 'U','S','B',' ','I','O',' ','B','o','a','r','d',' ',' ',' ',' ' +#endif +}; + +const u16 STRING_IMANUFACTURER[12] = { + (3<<8) | (2+2*11), +#if USB_VID == 0x2341 + 'A','r','d','u','i','n','o',' ','L','L','C' +#else + 'U','n','k','n','o','w','n',' ',' ',' ',' ' +#endif +}; + +#ifdef CDC_ENABLED +#define DEVICE_CLASS 0x02 +#else +#define DEVICE_CLASS 0x00 +#endif + +// DEVICE DESCRIPTOR +const DeviceDescriptor USB_DeviceDescriptor = + D_DEVICE(0x00,0x00,0x00,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1); + +const DeviceDescriptor USB_DeviceDescriptorA = + D_DEVICE(DEVICE_CLASS,0x00,0x00,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1); + +//================================================================== +//================================================================== + +volatile u8 _usbConfiguration = 0; + +static inline void WaitIN(void) +{ + while (!(UEINTX & (1< len) + n = len; + len -= n; + { + LockEP lock(ep); + if (ep & TRANSFER_ZERO) + { + while (n--) + Send8(0); + } + else if (ep & TRANSFER_PGM) + { + while (n--) + Send8(pgm_read_byte(data++)); + } + else + { + while (n--) + Send8(*data++); + } + if (!ReadWriteAllowed() || ((len == 0) && (ep & TRANSFER_RELEASE))) // Release full buffer + ReleaseTX(); + } + } + TXLED1; // light the TX LED + TxLEDPulse = TX_RX_LED_PULSE_MS; + return r; +} + +extern const u8 _initEndpoints[] PROGMEM; +const u8 _initEndpoints[] = +{ + 0, + +#ifdef CDC_ENABLED + EP_TYPE_INTERRUPT_IN, // CDC_ENDPOINT_ACM + EP_TYPE_BULK_OUT, // CDC_ENDPOINT_OUT + EP_TYPE_BULK_IN, // CDC_ENDPOINT_IN +#endif + +#ifdef HID_ENABLED + EP_TYPE_INTERRUPT_IN // HID_ENDPOINT_INT +#endif +}; + +#define EP_SINGLE_64 0x32 // EP0 +#define EP_DOUBLE_64 0x36 // Other endpoints + +static +void InitEP(u8 index, u8 type, u8 size) +{ + UENUM = index; + UECONX = 1; + UECFG0X = type; + UECFG1X = size; +} + +static +void InitEndpoints() +{ + for (u8 i = 1; i < sizeof(_initEndpoints); i++) + { + UENUM = i; + UECONX = 1; + UECFG0X = pgm_read_byte(_initEndpoints+i); + UECFG1X = EP_DOUBLE_64; + } + UERST = 0x7E; // And reset them + UERST = 0; +} + +// Handle CLASS_INTERFACE requests +static +bool ClassInterfaceRequest(Setup& setup) +{ + u8 i = setup.wIndex; + +#ifdef CDC_ENABLED + if (CDC_ACM_INTERFACE == i) + return CDC_Setup(setup); +#endif + +#ifdef HID_ENABLED + if (HID_INTERFACE == i) + return HID_Setup(setup); +#endif + return false; +} + +int _cmark; +int _cend; +void InitControl(int end) +{ + SetEP(0); + _cmark = 0; + _cend = end; +} + +static +bool SendControl(u8 d) +{ + if (_cmark < _cend) + { + if (!WaitForINOrOUT()) + return false; + Send8(d); + if (!((_cmark + 1) & 0x3F)) + ClearIN(); // Fifo is full, release this packet + } + _cmark++; + return true; +}; + +// Clipped by _cmark/_cend +int USB_SendControl(u8 flags, const void* d, int len) +{ + int sent = len; + const u8* data = (const u8*)d; + bool pgm = flags & TRANSFER_PGM; + while (len--) + { + u8 c = pgm ? pgm_read_byte(data++) : *data++; + if (!SendControl(c)) + return -1; + } + return sent; +} + +// Does not timeout or cross fifo boundaries +// Will only work for transfers <= 64 bytes +// TODO +int USB_RecvControl(void* d, int len) +{ + WaitOUT(); + Recv((u8*)d,len); + ClearOUT(); + return len; +} + +int SendInterfaces() +{ + int total = 0; + u8 interfaces = 0; + +#ifdef CDC_ENABLED + total = CDC_GetInterface(&interfaces); +#endif + +#ifdef HID_ENABLED + total += HID_GetInterface(&interfaces); +#endif + + return interfaces; +} + +// Construct a dynamic configuration descriptor +// This really needs dynamic endpoint allocation etc +// TODO +static +bool SendConfiguration(int maxlen) +{ + // Count and measure interfaces + InitControl(0); + int interfaces = SendInterfaces(); + ConfigDescriptor config = D_CONFIG(_cmark + sizeof(ConfigDescriptor),interfaces); + + // Now send them + InitControl(maxlen); + USB_SendControl(0,&config,sizeof(ConfigDescriptor)); + SendInterfaces(); + return true; +} + +u8 _cdcComposite = 0; + +static +bool SendDescriptor(Setup& setup) +{ + u8 t = setup.wValueH; + if (USB_CONFIGURATION_DESCRIPTOR_TYPE == t) + return SendConfiguration(setup.wLength); + + InitControl(setup.wLength); +#ifdef HID_ENABLED + if (HID_REPORT_DESCRIPTOR_TYPE == t) + return HID_GetDescriptor(t); +#endif + + u8 desc_length = 0; + const u8* desc_addr = 0; + if (USB_DEVICE_DESCRIPTOR_TYPE == t) + { + if (setup.wLength == 8) + _cdcComposite = 1; + desc_addr = _cdcComposite ? (const u8*)&USB_DeviceDescriptorA : (const u8*)&USB_DeviceDescriptor; + } + else if (USB_STRING_DESCRIPTOR_TYPE == t) + { + if (setup.wValueL == 0) + desc_addr = (const u8*)&STRING_LANGUAGE; + else if (setup.wValueL == IPRODUCT) + desc_addr = (const u8*)&STRING_IPRODUCT; + else if (setup.wValueL == IMANUFACTURER) + desc_addr = (const u8*)&STRING_IMANUFACTURER; + else + return false; + } + + if (desc_addr == 0) + return false; + if (desc_length == 0) + desc_length = pgm_read_byte(desc_addr); + + USB_SendControl(TRANSFER_PGM,desc_addr,desc_length); + return true; +} + +// Endpoint 0 interrupt +ISR(USB_COM_vect) +{ + SetEP(0); + if (!ReceivedSetupInt()) + return; + + Setup setup; + Recv((u8*)&setup,8); + ClearSetupInt(); + + u8 requestType = setup.bmRequestType; + if (requestType & REQUEST_DEVICETOHOST) + WaitIN(); + else + ClearIN(); + + bool ok = true; + if (REQUEST_STANDARD == (requestType & REQUEST_TYPE)) + { + // Standard Requests + u8 r = setup.bRequest; + if (GET_STATUS == r) + { + Send8(0); // TODO + Send8(0); + } + else if (CLEAR_FEATURE == r) + { + } + else if (SET_FEATURE == r) + { + } + else if (SET_ADDRESS == r) + { + WaitIN(); + UDADDR = setup.wValueL | (1<> 8) & 0xFF) + +#define CDC_V1_10 0x0110 +#define CDC_COMMUNICATION_INTERFACE_CLASS 0x02 + +#define CDC_CALL_MANAGEMENT 0x01 +#define CDC_ABSTRACT_CONTROL_MODEL 0x02 +#define CDC_HEADER 0x00 +#define CDC_ABSTRACT_CONTROL_MANAGEMENT 0x02 +#define CDC_UNION 0x06 +#define CDC_CS_INTERFACE 0x24 +#define CDC_CS_ENDPOINT 0x25 +#define CDC_DATA_INTERFACE_CLASS 0x0A + +#define MSC_SUBCLASS_SCSI 0x06 +#define MSC_PROTOCOL_BULK_ONLY 0x50 + +#define HID_HID_DESCRIPTOR_TYPE 0x21 +#define HID_REPORT_DESCRIPTOR_TYPE 0x22 +#define HID_PHYSICAL_DESCRIPTOR_TYPE 0x23 + + +// Device +typedef struct { + u8 len; // 18 + u8 dtype; // 1 USB_DEVICE_DESCRIPTOR_TYPE + u16 usbVersion; // 0x200 + u8 deviceClass; + u8 deviceSubClass; + u8 deviceProtocol; + u8 packetSize0; // Packet 0 + u16 idVendor; + u16 idProduct; + u16 deviceVersion; // 0x100 + u8 iManufacturer; + u8 iProduct; + u8 iSerialNumber; + u8 bNumConfigurations; +} DeviceDescriptor; + +// Config +typedef struct { + u8 len; // 9 + u8 dtype; // 2 + u16 clen; // total length + u8 numInterfaces; + u8 config; + u8 iconfig; + u8 attributes; + u8 maxPower; +} ConfigDescriptor; + +// String + +// Interface +typedef struct +{ + u8 len; // 9 + u8 dtype; // 4 + u8 number; + u8 alternate; + u8 numEndpoints; + u8 interfaceClass; + u8 interfaceSubClass; + u8 protocol; + u8 iInterface; +} InterfaceDescriptor; + +// Endpoint +typedef struct +{ + u8 len; // 7 + u8 dtype; // 5 + u8 addr; + u8 attr; + u16 packetSize; + u8 interval; +} EndpointDescriptor; + +// Interface Association Descriptor +// Used to bind 2 interfaces together in CDC compostite device +typedef struct +{ + u8 len; // 8 + u8 dtype; // 11 + u8 firstInterface; + u8 interfaceCount; + u8 functionClass; + u8 funtionSubClass; + u8 functionProtocol; + u8 iInterface; +} IADDescriptor; + +// CDC CS interface descriptor +typedef struct +{ + u8 len; // 5 + u8 dtype; // 0x24 + u8 subtype; + u8 d0; + u8 d1; +} CDCCSInterfaceDescriptor; + +typedef struct +{ + u8 len; // 4 + u8 dtype; // 0x24 + u8 subtype; + u8 d0; +} CDCCSInterfaceDescriptor4; + +typedef struct +{ + u8 len; + u8 dtype; // 0x24 + u8 subtype; // 1 + u8 bmCapabilities; + u8 bDataInterface; +} CMFunctionalDescriptor; + +typedef struct +{ + u8 len; + u8 dtype; // 0x24 + u8 subtype; // 1 + u8 bmCapabilities; +} ACMFunctionalDescriptor; + +typedef struct +{ + // IAD + IADDescriptor iad; // Only needed on compound device + + // Control + InterfaceDescriptor cif; // + CDCCSInterfaceDescriptor header; + CMFunctionalDescriptor callManagement; // Call Management + ACMFunctionalDescriptor controlManagement; // ACM + CDCCSInterfaceDescriptor functionalDescriptor; // CDC_UNION + EndpointDescriptor cifin; + + // Data + InterfaceDescriptor dif; + EndpointDescriptor in; + EndpointDescriptor out; +} CDCDescriptor; + +typedef struct +{ + InterfaceDescriptor msc; + EndpointDescriptor in; + EndpointDescriptor out; +} MSCDescriptor; + +typedef struct +{ + u8 len; // 9 + u8 dtype; // 0x21 + u8 addr; + u8 versionL; // 0x101 + u8 versionH; // 0x101 + u8 country; + u8 desctype; // 0x22 report + u8 descLenL; + u8 descLenH; +} HIDDescDescriptor; + +typedef struct +{ + InterfaceDescriptor hid; + HIDDescDescriptor desc; + EndpointDescriptor in; +} HIDDescriptor; + + +#define D_DEVICE(_class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs) \ + { 18, 1, 0x200, _class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs } + +#define D_CONFIG(_totalLength,_interfaces) \ + { 9, 2, _totalLength,_interfaces, 1, 0, USB_CONFIG_BUS_POWERED, USB_CONFIG_POWER_MA(500) } + +#define D_INTERFACE(_n,_numEndpoints,_class,_subClass,_protocol) \ + { 9, 4, _n, 0, _numEndpoints, _class,_subClass, _protocol, 0 } + +#define D_ENDPOINT(_addr,_attr,_packetSize, _interval) \ + { 7, 5, _addr,_attr,_packetSize, _interval } + +#define D_IAD(_firstInterface, _count, _class, _subClass, _protocol) \ + { 8, 11, _firstInterface, _count, _class, _subClass, _protocol, 0 } + +#define D_HIDREPORT(_descriptorLength) \ + { 9, 0x21, 0x1, 0x1, 0, 1, 0x22, _descriptorLength, 0 } + +#define D_CDCCS(_subtype,_d0,_d1) { 5, 0x24, _subtype, _d0, _d1 } +#define D_CDCCS4(_subtype,_d0) { 4, 0x24, _subtype, _d0 } + + +#endif \ No newline at end of file diff --git a/lib/usbhost/arduino-1.0.1/cores/arduino/USBDesc.h b/lib/usbhost/arduino-1.0.1/cores/arduino/USBDesc.h new file mode 100644 index 0000000000..900713e0f9 --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/cores/arduino/USBDesc.h @@ -0,0 +1,63 @@ + + +/* Copyright (c) 2011, Peter Barrett +** +** Permission to use, copy, modify, and/or distribute this software for +** any purpose with or without fee is hereby granted, provided that the +** above copyright notice and this permission notice appear in all copies. +** +** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR +** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES +** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +** SOFTWARE. +*/ + +#define CDC_ENABLED +#define HID_ENABLED + + +#ifdef CDC_ENABLED +#define CDC_INTERFACE_COUNT 2 +#define CDC_ENPOINT_COUNT 3 +#else +#define CDC_INTERFACE_COUNT 0 +#define CDC_ENPOINT_COUNT 0 +#endif + +#ifdef HID_ENABLED +#define HID_INTERFACE_COUNT 1 +#define HID_ENPOINT_COUNT 1 +#else +#define HID_INTERFACE_COUNT 0 +#define HID_ENPOINT_COUNT 0 +#endif + +#define CDC_ACM_INTERFACE 0 // CDC ACM +#define CDC_DATA_INTERFACE 1 // CDC Data +#define CDC_FIRST_ENDPOINT 1 +#define CDC_ENDPOINT_ACM (CDC_FIRST_ENDPOINT) // CDC First +#define CDC_ENDPOINT_OUT (CDC_FIRST_ENDPOINT+1) +#define CDC_ENDPOINT_IN (CDC_FIRST_ENDPOINT+2) + +#define HID_INTERFACE (CDC_ACM_INTERFACE + CDC_INTERFACE_COUNT) // HID Interface +#define HID_FIRST_ENDPOINT (CDC_FIRST_ENDPOINT + CDC_ENPOINT_COUNT) +#define HID_ENDPOINT_INT (HID_FIRST_ENDPOINT) + +#define INTERFACE_COUNT (MSC_INTERFACE + MSC_INTERFACE_COUNT) + +#ifdef CDC_ENABLED +#define CDC_RX CDC_ENDPOINT_OUT +#define CDC_TX CDC_ENDPOINT_IN +#endif + +#ifdef HID_ENABLED +#define HID_TX HID_ENDPOINT_INT +#endif + +#define IMANUFACTURER 1 +#define IPRODUCT 2 + diff --git a/lib/usbhost/arduino-1.0.1/cores/arduino/Udp.h b/lib/usbhost/arduino-1.0.1/cores/arduino/Udp.h new file mode 100644 index 0000000000..dc5644b9df --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/cores/arduino/Udp.h @@ -0,0 +1,88 @@ +/* + * Udp.cpp: Library to send/receive UDP packets. + * + * NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these) + * 1) UDP does not guarantee the order in which assembled UDP packets are received. This + * might not happen often in practice, but in larger network topologies, a UDP + * packet can be received out of sequence. + * 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being + * aware of it. Again, this may not be a concern in practice on small local networks. + * For more information, see http://www.cafeaulait.org/course/week12/35.html + * + * MIT License: + * Copyright (c) 2008 Bjoern Hartmann + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * bjoern@cs.stanford.edu 12/30/2008 + */ + +#ifndef udp_h +#define udp_h + +#include +#include + +class UDP : public Stream { + +public: + virtual uint8_t begin(uint16_t) =0; // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use + virtual void stop() =0; // Finish with the UDP socket + + // Sending UDP packets + + // Start building up a packet to send to the remote host specific in ip and port + // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port + virtual int beginPacket(IPAddress ip, uint16_t port) =0; + // Start building up a packet to send to the remote host specific in host and port + // Returns 1 if successful, 0 if there was a problem resolving the hostname or port + virtual int beginPacket(const char *host, uint16_t port) =0; + // Finish off this packet and send it + // Returns 1 if the packet was sent successfully, 0 if there was an error + virtual int endPacket() =0; + // Write a single byte into the packet + virtual size_t write(uint8_t) =0; + // Write size bytes from buffer into the packet + virtual size_t write(const uint8_t *buffer, size_t size) =0; + + // Start processing the next available incoming packet + // Returns the size of the packet in bytes, or 0 if no packets are available + virtual int parsePacket() =0; + // Number of bytes remaining in the current packet + virtual int available() =0; + // Read a single byte from the current packet + virtual int read() =0; + // Read up to len bytes from the current packet and place them into buffer + // Returns the number of bytes read, or 0 if none are available + virtual int read(unsigned char* buffer, size_t len) =0; + // Read up to len characters from the current packet and place them into buffer + // Returns the number of characters read, or 0 if none are available + virtual int read(char* buffer, size_t len) =0; + // Return the next byte from the current packet without moving on to the next byte + virtual int peek() =0; + virtual void flush() =0; // Finish reading the current packet + + // Return the IP address of the host who sent the current incoming packet + virtual IPAddress remoteIP() =0; + // Return the port of the host who sent the current incoming packet + virtual uint16_t remotePort() =0; +protected: + uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); }; +}; + +#endif diff --git a/lib/usbhost/arduino-1.0.1/cores/arduino/WCharacter.h b/lib/usbhost/arduino-1.0.1/cores/arduino/WCharacter.h new file mode 100644 index 0000000000..79733b50a5 --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/cores/arduino/WCharacter.h @@ -0,0 +1,168 @@ +/* + WCharacter.h - Character utility functions for Wiring & Arduino + Copyright (c) 2010 Hernando Barragan. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef Character_h +#define Character_h + +#include + +// WCharacter.h prototypes +inline boolean isAlphaNumeric(int c) __attribute__((always_inline)); +inline boolean isAlpha(int c) __attribute__((always_inline)); +inline boolean isAscii(int c) __attribute__((always_inline)); +inline boolean isWhitespace(int c) __attribute__((always_inline)); +inline boolean isControl(int c) __attribute__((always_inline)); +inline boolean isDigit(int c) __attribute__((always_inline)); +inline boolean isGraph(int c) __attribute__((always_inline)); +inline boolean isLowerCase(int c) __attribute__((always_inline)); +inline boolean isPrintable(int c) __attribute__((always_inline)); +inline boolean isPunct(int c) __attribute__((always_inline)); +inline boolean isSpace(int c) __attribute__((always_inline)); +inline boolean isUpperCase(int c) __attribute__((always_inline)); +inline boolean isHexadecimalDigit(int c) __attribute__((always_inline)); +inline int toAscii(int c) __attribute__((always_inline)); +inline int toLowerCase(int c) __attribute__((always_inline)); +inline int toUpperCase(int c)__attribute__((always_inline)); + + +// Checks for an alphanumeric character. +// It is equivalent to (isalpha(c) || isdigit(c)). +inline boolean isAlphaNumeric(int c) +{ + return ( isalnum(c) == 0 ? false : true); +} + + +// Checks for an alphabetic character. +// It is equivalent to (isupper(c) || islower(c)). +inline boolean isAlpha(int c) +{ + return ( isalpha(c) == 0 ? false : true); +} + + +// Checks whether c is a 7-bit unsigned char value +// that fits into the ASCII character set. +inline boolean isAscii(int c) +{ + return ( isascii (c) == 0 ? false : true); +} + + +// Checks for a blank character, that is, a space or a tab. +inline boolean isWhitespace(int c) +{ + return ( isblank (c) == 0 ? false : true); +} + + +// Checks for a control character. +inline boolean isControl(int c) +{ + return ( iscntrl (c) == 0 ? false : true); +} + + +// Checks for a digit (0 through 9). +inline boolean isDigit(int c) +{ + return ( isdigit (c) == 0 ? false : true); +} + + +// Checks for any printable character except space. +inline boolean isGraph(int c) +{ + return ( isgraph (c) == 0 ? false : true); +} + + +// Checks for a lower-case character. +inline boolean isLowerCase(int c) +{ + return (islower (c) == 0 ? false : true); +} + + +// Checks for any printable character including space. +inline boolean isPrintable(int c) +{ + return ( isprint (c) == 0 ? false : true); +} + + +// Checks for any printable character which is not a space +// or an alphanumeric character. +inline boolean isPunct(int c) +{ + return ( ispunct (c) == 0 ? false : true); +} + + +// Checks for white-space characters. For the avr-libc library, +// these are: space, formfeed ('\f'), newline ('\n'), carriage +// return ('\r'), horizontal tab ('\t'), and vertical tab ('\v'). +inline boolean isSpace(int c) +{ + return ( isspace (c) == 0 ? false : true); +} + + +// Checks for an uppercase letter. +inline boolean isUpperCase(int c) +{ + return ( isupper (c) == 0 ? false : true); +} + + +// Checks for a hexadecimal digits, i.e. one of 0 1 2 3 4 5 6 7 +// 8 9 a b c d e f A B C D E F. +inline boolean isHexadecimalDigit(int c) +{ + return ( isxdigit (c) == 0 ? false : true); +} + + +// Converts c to a 7-bit unsigned char value that fits into the +// ASCII character set, by clearing the high-order bits. +inline int toAscii(int c) +{ + return toascii (c); +} + + +// Warning: +// Many people will be unhappy if you use this function. +// This function will convert accented letters into random +// characters. + +// Converts the letter c to lower case, if possible. +inline int toLowerCase(int c) +{ + return tolower (c); +} + + +// Converts the letter c to upper case, if possible. +inline int toUpperCase(int c) +{ + return toupper (c); +} + +#endif \ No newline at end of file diff --git a/lib/usbhost/arduino-1.0.1/cores/arduino/WInterrupts.c b/lib/usbhost/arduino-1.0.1/cores/arduino/WInterrupts.c new file mode 100644 index 0000000000..8f3ec847f1 --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/cores/arduino/WInterrupts.c @@ -0,0 +1,298 @@ +/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Part of the Wiring project - http://wiring.uniandes.edu.co + + Copyright (c) 2004-05 Hernando Barragan + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + Modified 24 November 2006 by David A. Mellis + Modified 1 August 2010 by Mark Sproul +*/ + +#include +#include +#include +#include +#include + +#include "wiring_private.h" + +static volatile voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS]; +// volatile static voidFuncPtr twiIntFunc; + +void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) { + if(interruptNum < EXTERNAL_NUM_INTERRUPTS) { + intFunc[interruptNum] = userFunc; + + // Configure the interrupt mode (trigger on low input, any change, rising + // edge, or falling edge). The mode constants were chosen to correspond + // to the configuration bits in the hardware register, so we simply shift + // the mode into place. + + // Enable the interrupt. + + switch (interruptNum) { +#if defined(__AVR_ATmega32U4__) + // I hate doing this, but the register assignment differs between the 1280/2560 + // and the 32U4. Since avrlib defines registers PCMSK1 and PCMSK2 that aren't + // even present on the 32U4 this is the only way to distinguish between them. + case 0: + EICRA = (EICRA & ~((1<= howbig) { + return howsmall; + } + long diff = howbig - howsmall; + return random(diff) + howsmall; +} + +long map(long x, long in_min, long in_max, long out_min, long out_max) +{ + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; +} + +unsigned int makeWord(unsigned int w) { return w; } +unsigned int makeWord(unsigned char h, unsigned char l) { return (h << 8) | l; } \ No newline at end of file diff --git a/lib/usbhost/arduino-1.0.1/cores/arduino/WString.cpp b/lib/usbhost/arduino-1.0.1/cores/arduino/WString.cpp new file mode 100644 index 0000000000..c6839fc0d9 --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/cores/arduino/WString.cpp @@ -0,0 +1,645 @@ +/* + WString.cpp - String library for Wiring & Arduino + ...mostly rewritten by Paul Stoffregen... + Copyright (c) 2009-10 Hernando Barragan. All rights reserved. + Copyright 2011, Paul Stoffregen, paul@pjrc.com + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "WString.h" + + +/*********************************************/ +/* Constructors */ +/*********************************************/ + +String::String(const char *cstr) +{ + init(); + if (cstr) copy(cstr, strlen(cstr)); +} + +String::String(const String &value) +{ + init(); + *this = value; +} + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +String::String(String &&rval) +{ + init(); + move(rval); +} +String::String(StringSumHelper &&rval) +{ + init(); + move(rval); +} +#endif + +String::String(char c) +{ + init(); + char buf[2]; + buf[0] = c; + buf[1] = 0; + *this = buf; +} + +String::String(unsigned char value, unsigned char base) +{ + init(); + char buf[9]; + utoa(value, buf, base); + *this = buf; +} + +String::String(int value, unsigned char base) +{ + init(); + char buf[18]; + itoa(value, buf, base); + *this = buf; +} + +String::String(unsigned int value, unsigned char base) +{ + init(); + char buf[17]; + utoa(value, buf, base); + *this = buf; +} + +String::String(long value, unsigned char base) +{ + init(); + char buf[34]; + ltoa(value, buf, base); + *this = buf; +} + +String::String(unsigned long value, unsigned char base) +{ + init(); + char buf[33]; + ultoa(value, buf, base); + *this = buf; +} + +String::~String() +{ + free(buffer); +} + +/*********************************************/ +/* Memory Management */ +/*********************************************/ + +inline void String::init(void) +{ + buffer = NULL; + capacity = 0; + len = 0; + flags = 0; +} + +void String::invalidate(void) +{ + if (buffer) free(buffer); + buffer = NULL; + capacity = len = 0; +} + +unsigned char String::reserve(unsigned int size) +{ + if (buffer && capacity >= size) return 1; + if (changeBuffer(size)) { + if (len == 0) buffer[0] = 0; + return 1; + } + return 0; +} + +unsigned char String::changeBuffer(unsigned int maxStrLen) +{ + char *newbuffer = (char *)realloc(buffer, maxStrLen + 1); + if (newbuffer) { + buffer = newbuffer; + capacity = maxStrLen; + return 1; + } + return 0; +} + +/*********************************************/ +/* Copy and Move */ +/*********************************************/ + +String & String::copy(const char *cstr, unsigned int length) +{ + if (!reserve(length)) { + invalidate(); + return *this; + } + len = length; + strcpy(buffer, cstr); + return *this; +} + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +void String::move(String &rhs) +{ + if (buffer) { + if (capacity >= rhs.len) { + strcpy(buffer, rhs.buffer); + len = rhs.len; + rhs.len = 0; + return; + } else { + free(buffer); + } + } + buffer = rhs.buffer; + capacity = rhs.capacity; + len = rhs.len; + rhs.buffer = NULL; + rhs.capacity = 0; + rhs.len = 0; +} +#endif + +String & String::operator = (const String &rhs) +{ + if (this == &rhs) return *this; + + if (rhs.buffer) copy(rhs.buffer, rhs.len); + else invalidate(); + + return *this; +} + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +String & String::operator = (String &&rval) +{ + if (this != &rval) move(rval); + return *this; +} + +String & String::operator = (StringSumHelper &&rval) +{ + if (this != &rval) move(rval); + return *this; +} +#endif + +String & String::operator = (const char *cstr) +{ + if (cstr) copy(cstr, strlen(cstr)); + else invalidate(); + + return *this; +} + +/*********************************************/ +/* concat */ +/*********************************************/ + +unsigned char String::concat(const String &s) +{ + return concat(s.buffer, s.len); +} + +unsigned char String::concat(const char *cstr, unsigned int length) +{ + unsigned int newlen = len + length; + if (!cstr) return 0; + if (length == 0) return 1; + if (!reserve(newlen)) return 0; + strcpy(buffer + len, cstr); + len = newlen; + return 1; +} + +unsigned char String::concat(const char *cstr) +{ + if (!cstr) return 0; + return concat(cstr, strlen(cstr)); +} + +unsigned char String::concat(char c) +{ + char buf[2]; + buf[0] = c; + buf[1] = 0; + return concat(buf, 1); +} + +unsigned char String::concat(unsigned char num) +{ + char buf[4]; + itoa(num, buf, 10); + return concat(buf, strlen(buf)); +} + +unsigned char String::concat(int num) +{ + char buf[7]; + itoa(num, buf, 10); + return concat(buf, strlen(buf)); +} + +unsigned char String::concat(unsigned int num) +{ + char buf[6]; + utoa(num, buf, 10); + return concat(buf, strlen(buf)); +} + +unsigned char String::concat(long num) +{ + char buf[12]; + ltoa(num, buf, 10); + return concat(buf, strlen(buf)); +} + +unsigned char String::concat(unsigned long num) +{ + char buf[11]; + ultoa(num, buf, 10); + return concat(buf, strlen(buf)); +} + +/*********************************************/ +/* Concatenate */ +/*********************************************/ + +StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(rhs.buffer, rhs.len)) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr) +{ + StringSumHelper &a = const_cast(lhs); + if (!cstr || !a.concat(cstr, strlen(cstr))) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, char c) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(c)) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(num)) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, int num) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(num)) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(num)) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, long num) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(num)) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(num)) a.invalidate(); + return a; +} + +/*********************************************/ +/* Comparison */ +/*********************************************/ + +int String::compareTo(const String &s) const +{ + if (!buffer || !s.buffer) { + if (s.buffer && s.len > 0) return 0 - *(unsigned char *)s.buffer; + if (buffer && len > 0) return *(unsigned char *)buffer; + return 0; + } + return strcmp(buffer, s.buffer); +} + +unsigned char String::equals(const String &s2) const +{ + return (len == s2.len && compareTo(s2) == 0); +} + +unsigned char String::equals(const char *cstr) const +{ + if (len == 0) return (cstr == NULL || *cstr == 0); + if (cstr == NULL) return buffer[0] == 0; + return strcmp(buffer, cstr) == 0; +} + +unsigned char String::operator<(const String &rhs) const +{ + return compareTo(rhs) < 0; +} + +unsigned char String::operator>(const String &rhs) const +{ + return compareTo(rhs) > 0; +} + +unsigned char String::operator<=(const String &rhs) const +{ + return compareTo(rhs) <= 0; +} + +unsigned char String::operator>=(const String &rhs) const +{ + return compareTo(rhs) >= 0; +} + +unsigned char String::equalsIgnoreCase( const String &s2 ) const +{ + if (this == &s2) return 1; + if (len != s2.len) return 0; + if (len == 0) return 1; + const char *p1 = buffer; + const char *p2 = s2.buffer; + while (*p1) { + if (tolower(*p1++) != tolower(*p2++)) return 0; + } + return 1; +} + +unsigned char String::startsWith( const String &s2 ) const +{ + if (len < s2.len) return 0; + return startsWith(s2, 0); +} + +unsigned char String::startsWith( const String &s2, unsigned int offset ) const +{ + if (offset > len - s2.len || !buffer || !s2.buffer) return 0; + return strncmp( &buffer[offset], s2.buffer, s2.len ) == 0; +} + +unsigned char String::endsWith( const String &s2 ) const +{ + if ( len < s2.len || !buffer || !s2.buffer) return 0; + return strcmp(&buffer[len - s2.len], s2.buffer) == 0; +} + +/*********************************************/ +/* Character Access */ +/*********************************************/ + +char String::charAt(unsigned int loc) const +{ + return operator[](loc); +} + +void String::setCharAt(unsigned int loc, char c) +{ + if (loc < len) buffer[loc] = c; +} + +char & String::operator[](unsigned int index) +{ + static char dummy_writable_char; + if (index >= len || !buffer) { + dummy_writable_char = 0; + return dummy_writable_char; + } + return buffer[index]; +} + +char String::operator[]( unsigned int index ) const +{ + if (index >= len || !buffer) return 0; + return buffer[index]; +} + +void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const +{ + if (!bufsize || !buf) return; + if (index >= len) { + buf[0] = 0; + return; + } + unsigned int n = bufsize - 1; + if (n > len - index) n = len - index; + strncpy((char *)buf, buffer + index, n); + buf[n] = 0; +} + +/*********************************************/ +/* Search */ +/*********************************************/ + +int String::indexOf(char c) const +{ + return indexOf(c, 0); +} + +int String::indexOf( char ch, unsigned int fromIndex ) const +{ + if (fromIndex >= len) return -1; + const char* temp = strchr(buffer + fromIndex, ch); + if (temp == NULL) return -1; + return temp - buffer; +} + +int String::indexOf(const String &s2) const +{ + return indexOf(s2, 0); +} + +int String::indexOf(const String &s2, unsigned int fromIndex) const +{ + if (fromIndex >= len) return -1; + const char *found = strstr(buffer + fromIndex, s2.buffer); + if (found == NULL) return -1; + return found - buffer; +} + +int String::lastIndexOf( char theChar ) const +{ + return lastIndexOf(theChar, len - 1); +} + +int String::lastIndexOf(char ch, unsigned int fromIndex) const +{ + if (fromIndex >= len) return -1; + char tempchar = buffer[fromIndex + 1]; + buffer[fromIndex + 1] = '\0'; + char* temp = strrchr( buffer, ch ); + buffer[fromIndex + 1] = tempchar; + if (temp == NULL) return -1; + return temp - buffer; +} + +int String::lastIndexOf(const String &s2) const +{ + return lastIndexOf(s2, len - s2.len); +} + +int String::lastIndexOf(const String &s2, unsigned int fromIndex) const +{ + if (s2.len == 0 || len == 0 || s2.len > len) return -1; + if (fromIndex >= len) fromIndex = len - 1; + int found = -1; + for (char *p = buffer; p <= buffer + fromIndex; p++) { + p = strstr(p, s2.buffer); + if (!p) break; + if ((unsigned int)(p - buffer) <= fromIndex) found = p - buffer; + } + return found; +} + +String String::substring( unsigned int left ) const +{ + return substring(left, len); +} + +String String::substring(unsigned int left, unsigned int right) const +{ + if (left > right) { + unsigned int temp = right; + right = left; + left = temp; + } + String out; + if (left > len) return out; + if (right > len) right = len; + char temp = buffer[right]; // save the replaced character + buffer[right] = '\0'; + out = buffer + left; // pointer arithmetic + buffer[right] = temp; //restore character + return out; +} + +/*********************************************/ +/* Modification */ +/*********************************************/ + +void String::replace(char find, char replace) +{ + if (!buffer) return; + for (char *p = buffer; *p; p++) { + if (*p == find) *p = replace; + } +} + +void String::replace(const String& find, const String& replace) +{ + if (len == 0 || find.len == 0) return; + int diff = replace.len - find.len; + char *readFrom = buffer; + char *foundAt; + if (diff == 0) { + while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { + memcpy(foundAt, replace.buffer, replace.len); + readFrom = foundAt + replace.len; + } + } else if (diff < 0) { + char *writeTo = buffer; + while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { + unsigned int n = foundAt - readFrom; + memcpy(writeTo, readFrom, n); + writeTo += n; + memcpy(writeTo, replace.buffer, replace.len); + writeTo += replace.len; + readFrom = foundAt + find.len; + len += diff; + } + strcpy(writeTo, readFrom); + } else { + unsigned int size = len; // compute size needed for result + while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { + readFrom = foundAt + find.len; + size += diff; + } + if (size == len) return; + if (size > capacity && !changeBuffer(size)) return; // XXX: tell user! + int index = len - 1; + while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) { + readFrom = buffer + index + find.len; + memmove(readFrom + diff, readFrom, len - (readFrom - buffer)); + len += diff; + buffer[len] = 0; + memcpy(buffer + index, replace.buffer, replace.len); + index--; + } + } +} + +void String::toLowerCase(void) +{ + if (!buffer) return; + for (char *p = buffer; *p; p++) { + *p = tolower(*p); + } +} + +void String::toUpperCase(void) +{ + if (!buffer) return; + for (char *p = buffer; *p; p++) { + *p = toupper(*p); + } +} + +void String::trim(void) +{ + if (!buffer || len == 0) return; + char *begin = buffer; + while (isspace(*begin)) begin++; + char *end = buffer + len - 1; + while (isspace(*end) && end >= begin) end--; + len = end + 1 - begin; + if (begin > buffer) memcpy(buffer, begin, len); + buffer[len] = 0; +} + +/*********************************************/ +/* Parsing / Conversion */ +/*********************************************/ + +long String::toInt(void) const +{ + if (buffer) return atol(buffer); + return 0; +} + + diff --git a/lib/usbhost/arduino-1.0.1/cores/arduino/WString.h b/lib/usbhost/arduino-1.0.1/cores/arduino/WString.h new file mode 100644 index 0000000000..947325e5f5 --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/cores/arduino/WString.h @@ -0,0 +1,205 @@ +/* + WString.h - String library for Wiring & Arduino + ...mostly rewritten by Paul Stoffregen... + Copyright (c) 2009-10 Hernando Barragan. All right reserved. + Copyright 2011, Paul Stoffregen, paul@pjrc.com + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef String_class_h +#define String_class_h +#ifdef __cplusplus + +#include +#include +#include +#include + +// When compiling programs with this class, the following gcc parameters +// dramatically increase performance and memory (RAM) efficiency, typically +// with little or no increase in code size. +// -felide-constructors +// -std=c++0x + +class __FlashStringHelper; +#define F(string_literal) (reinterpret_cast(PSTR(string_literal))) + +// An inherited class for holding the result of a concatenation. These +// result objects are assumed to be writable by subsequent concatenations. +class StringSumHelper; + +// The string class +class String +{ + // use a function pointer to allow for "if (s)" without the + // complications of an operator bool(). for more information, see: + // http://www.artima.com/cppsource/safebool.html + typedef void (String::*StringIfHelperType)() const; + void StringIfHelper() const {} + +public: + // constructors + // creates a copy of the initial value. + // if the initial value is null or invalid, or if memory allocation + // fails, the string will be marked as invalid (i.e. "if (s)" will + // be false). + String(const char *cstr = ""); + String(const String &str); + #ifdef __GXX_EXPERIMENTAL_CXX0X__ + String(String &&rval); + String(StringSumHelper &&rval); + #endif + explicit String(char c); + explicit String(unsigned char, unsigned char base=10); + explicit String(int, unsigned char base=10); + explicit String(unsigned int, unsigned char base=10); + explicit String(long, unsigned char base=10); + explicit String(unsigned long, unsigned char base=10); + ~String(void); + + // memory management + // return true on success, false on failure (in which case, the string + // is left unchanged). reserve(0), if successful, will validate an + // invalid string (i.e., "if (s)" will be true afterwards) + unsigned char reserve(unsigned int size); + inline unsigned int length(void) const {return len;} + + // creates a copy of the assigned value. if the value is null or + // invalid, or if the memory allocation fails, the string will be + // marked as invalid ("if (s)" will be false). + String & operator = (const String &rhs); + String & operator = (const char *cstr); + #ifdef __GXX_EXPERIMENTAL_CXX0X__ + String & operator = (String &&rval); + String & operator = (StringSumHelper &&rval); + #endif + + // concatenate (works w/ built-in types) + + // returns true on success, false on failure (in which case, the string + // is left unchanged). if the argument is null or invalid, the + // concatenation is considered unsucessful. + unsigned char concat(const String &str); + unsigned char concat(const char *cstr); + unsigned char concat(char c); + unsigned char concat(unsigned char c); + unsigned char concat(int num); + unsigned char concat(unsigned int num); + unsigned char concat(long num); + unsigned char concat(unsigned long num); + + // if there's not enough memory for the concatenated value, the string + // will be left unchanged (but this isn't signalled in any way) + String & operator += (const String &rhs) {concat(rhs); return (*this);} + String & operator += (const char *cstr) {concat(cstr); return (*this);} + String & operator += (char c) {concat(c); return (*this);} + String & operator += (unsigned char num) {concat(num); return (*this);} + String & operator += (int num) {concat(num); return (*this);} + String & operator += (unsigned int num) {concat(num); return (*this);} + String & operator += (long num) {concat(num); return (*this);} + String & operator += (unsigned long num) {concat(num); return (*this);} + + friend StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs); + friend StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr); + friend StringSumHelper & operator + (const StringSumHelper &lhs, char c); + friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num); + friend StringSumHelper & operator + (const StringSumHelper &lhs, int num); + friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num); + friend StringSumHelper & operator + (const StringSumHelper &lhs, long num); + friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num); + + // comparison (only works w/ Strings and "strings") + operator StringIfHelperType() const { return buffer ? &String::StringIfHelper : 0; } + int compareTo(const String &s) const; + unsigned char equals(const String &s) const; + unsigned char equals(const char *cstr) const; + unsigned char operator == (const String &rhs) const {return equals(rhs);} + unsigned char operator == (const char *cstr) const {return equals(cstr);} + unsigned char operator != (const String &rhs) const {return !equals(rhs);} + unsigned char operator != (const char *cstr) const {return !equals(cstr);} + unsigned char operator < (const String &rhs) const; + unsigned char operator > (const String &rhs) const; + unsigned char operator <= (const String &rhs) const; + unsigned char operator >= (const String &rhs) const; + unsigned char equalsIgnoreCase(const String &s) const; + unsigned char startsWith( const String &prefix) const; + unsigned char startsWith(const String &prefix, unsigned int offset) const; + unsigned char endsWith(const String &suffix) const; + + // character acccess + char charAt(unsigned int index) const; + void setCharAt(unsigned int index, char c); + char operator [] (unsigned int index) const; + char& operator [] (unsigned int index); + void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index=0) const; + void toCharArray(char *buf, unsigned int bufsize, unsigned int index=0) const + {getBytes((unsigned char *)buf, bufsize, index);} + + // search + int indexOf( char ch ) const; + int indexOf( char ch, unsigned int fromIndex ) const; + int indexOf( const String &str ) const; + int indexOf( const String &str, unsigned int fromIndex ) const; + int lastIndexOf( char ch ) const; + int lastIndexOf( char ch, unsigned int fromIndex ) const; + int lastIndexOf( const String &str ) const; + int lastIndexOf( const String &str, unsigned int fromIndex ) const; + String substring( unsigned int beginIndex ) const; + String substring( unsigned int beginIndex, unsigned int endIndex ) const; + + // modification + void replace(char find, char replace); + void replace(const String& find, const String& replace); + void toLowerCase(void); + void toUpperCase(void); + void trim(void); + + // parsing/conversion + long toInt(void) const; + +protected: + char *buffer; // the actual char array + unsigned int capacity; // the array length minus one (for the '\0') + unsigned int len; // the String length (not counting the '\0') + unsigned char flags; // unused, for future features +protected: + void init(void); + void invalidate(void); + unsigned char changeBuffer(unsigned int maxStrLen); + unsigned char concat(const char *cstr, unsigned int length); + + // copy and move + String & copy(const char *cstr, unsigned int length); + #ifdef __GXX_EXPERIMENTAL_CXX0X__ + void move(String &rhs); + #endif +}; + +class StringSumHelper : public String +{ +public: + StringSumHelper(const String &s) : String(s) {} + StringSumHelper(const char *p) : String(p) {} + StringSumHelper(char c) : String(c) {} + StringSumHelper(unsigned char num) : String(num) {} + StringSumHelper(int num) : String(num) {} + StringSumHelper(unsigned int num) : String(num) {} + StringSumHelper(long num) : String(num) {} + StringSumHelper(unsigned long num) : String(num) {} +}; + +#endif // __cplusplus +#endif // String_class_h diff --git a/lib/usbhost/arduino-1.0.1/cores/arduino/binary.h b/lib/usbhost/arduino-1.0.1/cores/arduino/binary.h new file mode 100644 index 0000000000..af1498033a --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/cores/arduino/binary.h @@ -0,0 +1,515 @@ +#ifndef Binary_h +#define Binary_h + +#define B0 0 +#define B00 0 +#define B000 0 +#define B0000 0 +#define B00000 0 +#define B000000 0 +#define B0000000 0 +#define B00000000 0 +#define B1 1 +#define B01 1 +#define B001 1 +#define B0001 1 +#define B00001 1 +#define B000001 1 +#define B0000001 1 +#define B00000001 1 +#define B10 2 +#define B010 2 +#define B0010 2 +#define B00010 2 +#define B000010 2 +#define B0000010 2 +#define B00000010 2 +#define B11 3 +#define B011 3 +#define B0011 3 +#define B00011 3 +#define B000011 3 +#define B0000011 3 +#define B00000011 3 +#define B100 4 +#define B0100 4 +#define B00100 4 +#define B000100 4 +#define B0000100 4 +#define B00000100 4 +#define B101 5 +#define B0101 5 +#define B00101 5 +#define B000101 5 +#define B0000101 5 +#define B00000101 5 +#define B110 6 +#define B0110 6 +#define B00110 6 +#define B000110 6 +#define B0000110 6 +#define B00000110 6 +#define B111 7 +#define B0111 7 +#define B00111 7 +#define B000111 7 +#define B0000111 7 +#define B00000111 7 +#define B1000 8 +#define B01000 8 +#define B001000 8 +#define B0001000 8 +#define B00001000 8 +#define B1001 9 +#define B01001 9 +#define B001001 9 +#define B0001001 9 +#define B00001001 9 +#define B1010 10 +#define B01010 10 +#define B001010 10 +#define B0001010 10 +#define B00001010 10 +#define B1011 11 +#define B01011 11 +#define B001011 11 +#define B0001011 11 +#define B00001011 11 +#define B1100 12 +#define B01100 12 +#define B001100 12 +#define B0001100 12 +#define B00001100 12 +#define B1101 13 +#define B01101 13 +#define B001101 13 +#define B0001101 13 +#define B00001101 13 +#define B1110 14 +#define B01110 14 +#define B001110 14 +#define B0001110 14 +#define B00001110 14 +#define B1111 15 +#define B01111 15 +#define B001111 15 +#define B0001111 15 +#define B00001111 15 +#define B10000 16 +#define B010000 16 +#define B0010000 16 +#define B00010000 16 +#define B10001 17 +#define B010001 17 +#define B0010001 17 +#define B00010001 17 +#define B10010 18 +#define B010010 18 +#define B0010010 18 +#define B00010010 18 +#define B10011 19 +#define B010011 19 +#define B0010011 19 +#define B00010011 19 +#define B10100 20 +#define B010100 20 +#define B0010100 20 +#define B00010100 20 +#define B10101 21 +#define B010101 21 +#define B0010101 21 +#define B00010101 21 +#define B10110 22 +#define B010110 22 +#define B0010110 22 +#define B00010110 22 +#define B10111 23 +#define B010111 23 +#define B0010111 23 +#define B00010111 23 +#define B11000 24 +#define B011000 24 +#define B0011000 24 +#define B00011000 24 +#define B11001 25 +#define B011001 25 +#define B0011001 25 +#define B00011001 25 +#define B11010 26 +#define B011010 26 +#define B0011010 26 +#define B00011010 26 +#define B11011 27 +#define B011011 27 +#define B0011011 27 +#define B00011011 27 +#define B11100 28 +#define B011100 28 +#define B0011100 28 +#define B00011100 28 +#define B11101 29 +#define B011101 29 +#define B0011101 29 +#define B00011101 29 +#define B11110 30 +#define B011110 30 +#define B0011110 30 +#define B00011110 30 +#define B11111 31 +#define B011111 31 +#define B0011111 31 +#define B00011111 31 +#define B100000 32 +#define B0100000 32 +#define B00100000 32 +#define B100001 33 +#define B0100001 33 +#define B00100001 33 +#define B100010 34 +#define B0100010 34 +#define B00100010 34 +#define B100011 35 +#define B0100011 35 +#define B00100011 35 +#define B100100 36 +#define B0100100 36 +#define B00100100 36 +#define B100101 37 +#define B0100101 37 +#define B00100101 37 +#define B100110 38 +#define B0100110 38 +#define B00100110 38 +#define B100111 39 +#define B0100111 39 +#define B00100111 39 +#define B101000 40 +#define B0101000 40 +#define B00101000 40 +#define B101001 41 +#define B0101001 41 +#define B00101001 41 +#define B101010 42 +#define B0101010 42 +#define B00101010 42 +#define B101011 43 +#define B0101011 43 +#define B00101011 43 +#define B101100 44 +#define B0101100 44 +#define B00101100 44 +#define B101101 45 +#define B0101101 45 +#define B00101101 45 +#define B101110 46 +#define B0101110 46 +#define B00101110 46 +#define B101111 47 +#define B0101111 47 +#define B00101111 47 +#define B110000 48 +#define B0110000 48 +#define B00110000 48 +#define B110001 49 +#define B0110001 49 +#define B00110001 49 +#define B110010 50 +#define B0110010 50 +#define B00110010 50 +#define B110011 51 +#define B0110011 51 +#define B00110011 51 +#define B110100 52 +#define B0110100 52 +#define B00110100 52 +#define B110101 53 +#define B0110101 53 +#define B00110101 53 +#define B110110 54 +#define B0110110 54 +#define B00110110 54 +#define B110111 55 +#define B0110111 55 +#define B00110111 55 +#define B111000 56 +#define B0111000 56 +#define B00111000 56 +#define B111001 57 +#define B0111001 57 +#define B00111001 57 +#define B111010 58 +#define B0111010 58 +#define B00111010 58 +#define B111011 59 +#define B0111011 59 +#define B00111011 59 +#define B111100 60 +#define B0111100 60 +#define B00111100 60 +#define B111101 61 +#define B0111101 61 +#define B00111101 61 +#define B111110 62 +#define B0111110 62 +#define B00111110 62 +#define B111111 63 +#define B0111111 63 +#define B00111111 63 +#define B1000000 64 +#define B01000000 64 +#define B1000001 65 +#define B01000001 65 +#define B1000010 66 +#define B01000010 66 +#define B1000011 67 +#define B01000011 67 +#define B1000100 68 +#define B01000100 68 +#define B1000101 69 +#define B01000101 69 +#define B1000110 70 +#define B01000110 70 +#define B1000111 71 +#define B01000111 71 +#define B1001000 72 +#define B01001000 72 +#define B1001001 73 +#define B01001001 73 +#define B1001010 74 +#define B01001010 74 +#define B1001011 75 +#define B01001011 75 +#define B1001100 76 +#define B01001100 76 +#define B1001101 77 +#define B01001101 77 +#define B1001110 78 +#define B01001110 78 +#define B1001111 79 +#define B01001111 79 +#define B1010000 80 +#define B01010000 80 +#define B1010001 81 +#define B01010001 81 +#define B1010010 82 +#define B01010010 82 +#define B1010011 83 +#define B01010011 83 +#define B1010100 84 +#define B01010100 84 +#define B1010101 85 +#define B01010101 85 +#define B1010110 86 +#define B01010110 86 +#define B1010111 87 +#define B01010111 87 +#define B1011000 88 +#define B01011000 88 +#define B1011001 89 +#define B01011001 89 +#define B1011010 90 +#define B01011010 90 +#define B1011011 91 +#define B01011011 91 +#define B1011100 92 +#define B01011100 92 +#define B1011101 93 +#define B01011101 93 +#define B1011110 94 +#define B01011110 94 +#define B1011111 95 +#define B01011111 95 +#define B1100000 96 +#define B01100000 96 +#define B1100001 97 +#define B01100001 97 +#define B1100010 98 +#define B01100010 98 +#define B1100011 99 +#define B01100011 99 +#define B1100100 100 +#define B01100100 100 +#define B1100101 101 +#define B01100101 101 +#define B1100110 102 +#define B01100110 102 +#define B1100111 103 +#define B01100111 103 +#define B1101000 104 +#define B01101000 104 +#define B1101001 105 +#define B01101001 105 +#define B1101010 106 +#define B01101010 106 +#define B1101011 107 +#define B01101011 107 +#define B1101100 108 +#define B01101100 108 +#define B1101101 109 +#define B01101101 109 +#define B1101110 110 +#define B01101110 110 +#define B1101111 111 +#define B01101111 111 +#define B1110000 112 +#define B01110000 112 +#define B1110001 113 +#define B01110001 113 +#define B1110010 114 +#define B01110010 114 +#define B1110011 115 +#define B01110011 115 +#define B1110100 116 +#define B01110100 116 +#define B1110101 117 +#define B01110101 117 +#define B1110110 118 +#define B01110110 118 +#define B1110111 119 +#define B01110111 119 +#define B1111000 120 +#define B01111000 120 +#define B1111001 121 +#define B01111001 121 +#define B1111010 122 +#define B01111010 122 +#define B1111011 123 +#define B01111011 123 +#define B1111100 124 +#define B01111100 124 +#define B1111101 125 +#define B01111101 125 +#define B1111110 126 +#define B01111110 126 +#define B1111111 127 +#define B01111111 127 +#define B10000000 128 +#define B10000001 129 +#define B10000010 130 +#define B10000011 131 +#define B10000100 132 +#define B10000101 133 +#define B10000110 134 +#define B10000111 135 +#define B10001000 136 +#define B10001001 137 +#define B10001010 138 +#define B10001011 139 +#define B10001100 140 +#define B10001101 141 +#define B10001110 142 +#define B10001111 143 +#define B10010000 144 +#define B10010001 145 +#define B10010010 146 +#define B10010011 147 +#define B10010100 148 +#define B10010101 149 +#define B10010110 150 +#define B10010111 151 +#define B10011000 152 +#define B10011001 153 +#define B10011010 154 +#define B10011011 155 +#define B10011100 156 +#define B10011101 157 +#define B10011110 158 +#define B10011111 159 +#define B10100000 160 +#define B10100001 161 +#define B10100010 162 +#define B10100011 163 +#define B10100100 164 +#define B10100101 165 +#define B10100110 166 +#define B10100111 167 +#define B10101000 168 +#define B10101001 169 +#define B10101010 170 +#define B10101011 171 +#define B10101100 172 +#define B10101101 173 +#define B10101110 174 +#define B10101111 175 +#define B10110000 176 +#define B10110001 177 +#define B10110010 178 +#define B10110011 179 +#define B10110100 180 +#define B10110101 181 +#define B10110110 182 +#define B10110111 183 +#define B10111000 184 +#define B10111001 185 +#define B10111010 186 +#define B10111011 187 +#define B10111100 188 +#define B10111101 189 +#define B10111110 190 +#define B10111111 191 +#define B11000000 192 +#define B11000001 193 +#define B11000010 194 +#define B11000011 195 +#define B11000100 196 +#define B11000101 197 +#define B11000110 198 +#define B11000111 199 +#define B11001000 200 +#define B11001001 201 +#define B11001010 202 +#define B11001011 203 +#define B11001100 204 +#define B11001101 205 +#define B11001110 206 +#define B11001111 207 +#define B11010000 208 +#define B11010001 209 +#define B11010010 210 +#define B11010011 211 +#define B11010100 212 +#define B11010101 213 +#define B11010110 214 +#define B11010111 215 +#define B11011000 216 +#define B11011001 217 +#define B11011010 218 +#define B11011011 219 +#define B11011100 220 +#define B11011101 221 +#define B11011110 222 +#define B11011111 223 +#define B11100000 224 +#define B11100001 225 +#define B11100010 226 +#define B11100011 227 +#define B11100100 228 +#define B11100101 229 +#define B11100110 230 +#define B11100111 231 +#define B11101000 232 +#define B11101001 233 +#define B11101010 234 +#define B11101011 235 +#define B11101100 236 +#define B11101101 237 +#define B11101110 238 +#define B11101111 239 +#define B11110000 240 +#define B11110001 241 +#define B11110010 242 +#define B11110011 243 +#define B11110100 244 +#define B11110101 245 +#define B11110110 246 +#define B11110111 247 +#define B11111000 248 +#define B11111001 249 +#define B11111010 250 +#define B11111011 251 +#define B11111100 252 +#define B11111101 253 +#define B11111110 254 +#define B11111111 255 + +#endif diff --git a/lib/usbhost/arduino-1.0.1/cores/arduino/main.cpp b/lib/usbhost/arduino-1.0.1/cores/arduino/main.cpp new file mode 100644 index 0000000000..3d4e079d2a --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/cores/arduino/main.cpp @@ -0,0 +1,20 @@ +#include + +int main(void) +{ + init(); + +#if defined(USBCON) + USBDevice.attach(); +#endif + + setup(); + + for (;;) { + loop(); + if (serialEventRun) serialEventRun(); + } + + return 0; +} + diff --git a/lib/usbhost/arduino-1.0.1/cores/arduino/new.cpp b/lib/usbhost/arduino-1.0.1/cores/arduino/new.cpp new file mode 100644 index 0000000000..0f6d4220ef --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/cores/arduino/new.cpp @@ -0,0 +1,18 @@ +#include + +void * operator new(size_t size) +{ + return malloc(size); +} + +void operator delete(void * ptr) +{ + free(ptr); +} + +int __cxa_guard_acquire(__guard *g) {return !*(char *)(g);}; +void __cxa_guard_release (__guard *g) {*(char *)g = 1;}; +void __cxa_guard_abort (__guard *) {}; + +void __cxa_pure_virtual(void) {}; + diff --git a/lib/usbhost/arduino-1.0.1/cores/arduino/new.h b/lib/usbhost/arduino-1.0.1/cores/arduino/new.h new file mode 100644 index 0000000000..cd940ce8b2 --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/cores/arduino/new.h @@ -0,0 +1,22 @@ +/* Header to define new/delete operators as they aren't provided by avr-gcc by default + Taken from http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=59453 + */ + +#ifndef NEW_H +#define NEW_H + +#include + +void * operator new(size_t size); +void operator delete(void * ptr); + +__extension__ typedef int __guard __attribute__((mode (__DI__))); + +extern "C" int __cxa_guard_acquire(__guard *); +extern "C" void __cxa_guard_release (__guard *); +extern "C" void __cxa_guard_abort (__guard *); + +extern "C" void __cxa_pure_virtual(void); + +#endif + diff --git a/lib/usbhost/arduino-1.0.1/cores/arduino/wiring.c b/lib/usbhost/arduino-1.0.1/cores/arduino/wiring.c new file mode 100644 index 0000000000..ac8bb6f9b4 --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/cores/arduino/wiring.c @@ -0,0 +1,324 @@ +/* + wiring.c - Partial implementation of the Wiring API for the ATmega8. + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2005-2006 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id$ +*/ + +#include "wiring_private.h" + +// the prescaler is set so that timer0 ticks every 64 clock cycles, and the +// the overflow handler is called every 256 ticks. +#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256)) + +// the whole number of milliseconds per timer0 overflow +#define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000) + +// the fractional number of milliseconds per timer0 overflow. we shift right +// by three to fit these numbers into a byte. (for the clock speeds we care +// about - 8 and 16 MHz - this doesn't lose precision.) +#define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3) +#define FRACT_MAX (1000 >> 3) + +volatile unsigned long timer0_overflow_count = 0; +volatile unsigned long timer0_millis = 0; +static unsigned char timer0_fract = 0; + +#if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) +SIGNAL(TIM0_OVF_vect) +#else +SIGNAL(TIMER0_OVF_vect) +#endif +{ + // copy these to local variables so they can be stored in registers + // (volatile variables must be read from memory on every access) + unsigned long m = timer0_millis; + unsigned char f = timer0_fract; + + m += MILLIS_INC; + f += FRACT_INC; + if (f >= FRACT_MAX) { + f -= FRACT_MAX; + m += 1; + } + + timer0_fract = f; + timer0_millis = m; + timer0_overflow_count++; +} + +unsigned long millis() +{ + unsigned long m; + uint8_t oldSREG = SREG; + + // disable interrupts while we read timer0_millis or we might get an + // inconsistent value (e.g. in the middle of a write to timer0_millis) + cli(); + m = timer0_millis; + SREG = oldSREG; + + return m; +} + +unsigned long micros() { + unsigned long m; + uint8_t oldSREG = SREG, t; + + cli(); + m = timer0_overflow_count; +#if defined(TCNT0) + t = TCNT0; +#elif defined(TCNT0L) + t = TCNT0L; +#else + #error TIMER 0 not defined +#endif + + +#ifdef TIFR0 + if ((TIFR0 & _BV(TOV0)) && (t < 255)) + m++; +#else + if ((TIFR & _BV(TOV0)) && (t < 255)) + m++; +#endif + + SREG = oldSREG; + + return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond()); +} + +void delay(unsigned long ms) +{ + uint16_t start = (uint16_t)micros(); + + while (ms > 0) { + if (((uint16_t)micros() - start) >= 1000) { + ms--; + start += 1000; + } + } +} + +/* Delay for the given number of microseconds. Assumes a 8 or 16 MHz clock. */ +void delayMicroseconds(unsigned int us) +{ + // calling avrlib's delay_us() function with low values (e.g. 1 or + // 2 microseconds) gives delays longer than desired. + //delay_us(us); +#if F_CPU >= 20000000L + // for the 20 MHz clock on rare Arduino boards + + // for a one-microsecond delay, simply wait 2 cycle and return. The overhead + // of the function call yields a delay of exactly a one microsecond. + __asm__ __volatile__ ( + "nop" "\n\t" + "nop"); //just waiting 2 cycle + if (--us == 0) + return; + + // the following loop takes a 1/5 of a microsecond (4 cycles) + // per iteration, so execute it five times for each microsecond of + // delay requested. + us = (us<<2) + us; // x5 us + + // account for the time taken in the preceeding commands. + us -= 2; + +#elif F_CPU >= 16000000L + // for the 16 MHz clock on most Arduino boards + + // for a one-microsecond delay, simply return. the overhead + // of the function call yields a delay of approximately 1 1/8 us. + if (--us == 0) + return; + + // the following loop takes a quarter of a microsecond (4 cycles) + // per iteration, so execute it four times for each microsecond of + // delay requested. + us <<= 2; + + // account for the time taken in the preceeding commands. + us -= 2; +#else + // for the 8 MHz internal clock on the ATmega168 + + // for a one- or two-microsecond delay, simply return. the overhead of + // the function calls takes more than two microseconds. can't just + // subtract two, since us is unsigned; we'd overflow. + if (--us == 0) + return; + if (--us == 0) + return; + + // the following loop takes half of a microsecond (4 cycles) + // per iteration, so execute it twice for each microsecond of + // delay requested. + us <<= 1; + + // partially compensate for the time taken by the preceeding commands. + // we can't subtract any more than this or we'd overflow w/ small delays. + us--; +#endif + + // busy wait + __asm__ __volatile__ ( + "1: sbiw %0,1" "\n\t" // 2 cycles + "brne 1b" : "=w" (us) : "0" (us) // 2 cycles + ); +} + +void init() +{ + // this needs to be called before setup() or some functions won't + // work there + sei(); + + // on the ATmega168, timer 0 is also used for fast hardware pwm + // (using phase-correct PWM would mean that timer 0 overflowed half as often + // resulting in different millis() behavior on the ATmega8 and ATmega168) +#if defined(TCCR0A) && defined(WGM01) + sbi(TCCR0A, WGM01); + sbi(TCCR0A, WGM00); +#endif + + // set timer 0 prescale factor to 64 +#if defined(__AVR_ATmega128__) + // CPU specific: different values for the ATmega128 + sbi(TCCR0, CS02); +#elif defined(TCCR0) && defined(CS01) && defined(CS00) + // this combination is for the standard atmega8 + sbi(TCCR0, CS01); + sbi(TCCR0, CS00); +#elif defined(TCCR0B) && defined(CS01) && defined(CS00) + // this combination is for the standard 168/328/1280/2560 + sbi(TCCR0B, CS01); + sbi(TCCR0B, CS00); +#elif defined(TCCR0A) && defined(CS01) && defined(CS00) + // this combination is for the __AVR_ATmega645__ series + sbi(TCCR0A, CS01); + sbi(TCCR0A, CS00); +#else + #error Timer 0 prescale factor 64 not set correctly +#endif + + // enable timer 0 overflow interrupt +#if defined(TIMSK) && defined(TOIE0) + sbi(TIMSK, TOIE0); +#elif defined(TIMSK0) && defined(TOIE0) + sbi(TIMSK0, TOIE0); +#else + #error Timer 0 overflow interrupt not set correctly +#endif + + // timers 1 and 2 are used for phase-correct hardware pwm + // this is better for motors as it ensures an even waveform + // note, however, that fast pwm mode can achieve a frequency of up + // 8 MHz (with a 16 MHz clock) at 50% duty cycle + +#if defined(TCCR1B) && defined(CS11) && defined(CS10) + TCCR1B = 0; + + // set timer 1 prescale factor to 64 + sbi(TCCR1B, CS11); +#if F_CPU >= 8000000L + sbi(TCCR1B, CS10); +#endif +#elif defined(TCCR1) && defined(CS11) && defined(CS10) + sbi(TCCR1, CS11); +#if F_CPU >= 8000000L + sbi(TCCR1, CS10); +#endif +#endif + // put timer 1 in 8-bit phase correct pwm mode +#if defined(TCCR1A) && defined(WGM10) + sbi(TCCR1A, WGM10); +#elif defined(TCCR1) + #warning this needs to be finished +#endif + + // set timer 2 prescale factor to 64 +#if defined(TCCR2) && defined(CS22) + sbi(TCCR2, CS22); +#elif defined(TCCR2B) && defined(CS22) + sbi(TCCR2B, CS22); +#else + #warning Timer 2 not finished (may not be present on this CPU) +#endif + + // configure timer 2 for phase correct pwm (8-bit) +#if defined(TCCR2) && defined(WGM20) + sbi(TCCR2, WGM20); +#elif defined(TCCR2A) && defined(WGM20) + sbi(TCCR2A, WGM20); +#else + #warning Timer 2 not finished (may not be present on this CPU) +#endif + +#if defined(TCCR3B) && defined(CS31) && defined(WGM30) + sbi(TCCR3B, CS31); // set timer 3 prescale factor to 64 + sbi(TCCR3B, CS30); + sbi(TCCR3A, WGM30); // put timer 3 in 8-bit phase correct pwm mode +#endif + +#if defined(TCCR4A) && defined(TCCR4B) && defined(TCCR4D) /* beginning of timer4 block for 32U4 and similar */ + sbi(TCCR4B, CS42); // set timer4 prescale factor to 64 + sbi(TCCR4B, CS41); + sbi(TCCR4B, CS40); + sbi(TCCR4D, WGM40); // put timer 4 in phase- and frequency-correct PWM mode + sbi(TCCR4A, PWM4A); // enable PWM mode for comparator OCR4A + sbi(TCCR4C, PWM4D); // enable PWM mode for comparator OCR4D +#else /* beginning of timer4 block for ATMEGA1280 and ATMEGA2560 */ +#if defined(TCCR4B) && defined(CS41) && defined(WGM40) + sbi(TCCR4B, CS41); // set timer 4 prescale factor to 64 + sbi(TCCR4B, CS40); + sbi(TCCR4A, WGM40); // put timer 4 in 8-bit phase correct pwm mode +#endif +#endif /* end timer4 block for ATMEGA1280/2560 and similar */ + +#if defined(TCCR5B) && defined(CS51) && defined(WGM50) + sbi(TCCR5B, CS51); // set timer 5 prescale factor to 64 + sbi(TCCR5B, CS50); + sbi(TCCR5A, WGM50); // put timer 5 in 8-bit phase correct pwm mode +#endif + +#if defined(ADCSRA) + // set a2d prescale factor to 128 + // 16 MHz / 128 = 125 KHz, inside the desired 50-200 KHz range. + // XXX: this will not work properly for other clock speeds, and + // this code should use F_CPU to determine the prescale factor. + sbi(ADCSRA, ADPS2); + sbi(ADCSRA, ADPS1); + sbi(ADCSRA, ADPS0); + + // enable a2d conversions + sbi(ADCSRA, ADEN); +#endif + + // the bootloader connects pins 0 and 1 to the USART; disconnect them + // here so they can be used as normal digital i/o; they will be + // reconnected in Serial.begin() +#if defined(UCSRB) + UCSRB = 0; +#elif defined(UCSR0B) + UCSR0B = 0; +#endif +} diff --git a/lib/usbhost/arduino-1.0.1/cores/arduino/wiring_analog.c b/lib/usbhost/arduino-1.0.1/cores/arduino/wiring_analog.c new file mode 100644 index 0000000000..0e9881f6ac --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/cores/arduino/wiring_analog.c @@ -0,0 +1,282 @@ +/* + wiring_analog.c - analog input and output + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2005-2006 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + Modified 28 September 2010 by Mark Sproul + + $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $ +*/ + +#include "wiring_private.h" +#include "pins_arduino.h" + +uint8_t analog_reference = DEFAULT; + +void analogReference(uint8_t mode) +{ + // can't actually set the register here because the default setting + // will connect AVCC and the AREF pin, which would cause a short if + // there's something connected to AREF. + analog_reference = mode; +} + +int analogRead(uint8_t pin) +{ + uint8_t low, high; + +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) + if (pin >= 54) pin -= 54; // allow for channel or pin numbers +#elif defined(__AVR_ATmega32U4__) + if (pin >= 18) pin -= 18; // allow for channel or pin numbers +#elif defined(__AVR_ATmega1284__) + if (pin >= 24) pin -= 24; // allow for channel or pin numbers +#else + if (pin >= 14) pin -= 14; // allow for channel or pin numbers +#endif + +#if defined(__AVR_ATmega32U4__) + pin = analogPinToChannel(pin); + ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((pin >> 3) & 0x01) << MUX5); +#elif defined(ADCSRB) && defined(MUX5) + // the MUX5 bit of ADCSRB selects whether we're reading from channels + // 0 to 7 (MUX5 low) or 8 to 15 (MUX5 high). + ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((pin >> 3) & 0x01) << MUX5); +#endif + + // set the analog reference (high two bits of ADMUX) and select the + // channel (low 4 bits). this also sets ADLAR (left-adjust result) + // to 0 (the default). +#if defined(ADMUX) + ADMUX = (analog_reference << 6) | (pin & 0x07); +#endif + + // without a delay, we seem to read from the wrong channel + //delay(1); + +#if defined(ADCSRA) && defined(ADCL) + // start the conversion + sbi(ADCSRA, ADSC); + + // ADSC is cleared when the conversion finishes + while (bit_is_set(ADCSRA, ADSC)); + + // we have to read ADCL first; doing so locks both ADCL + // and ADCH until ADCH is read. reading ADCL second would + // cause the results of each conversion to be discarded, + // as ADCL and ADCH would be locked when it completed. + low = ADCL; + high = ADCH; +#else + // we dont have an ADC, return 0 + low = 0; + high = 0; +#endif + + // combine the two bytes + return (high << 8) | low; +} + +// Right now, PWM output only works on the pins with +// hardware support. These are defined in the appropriate +// pins_*.c file. For the rest of the pins, we default +// to digital output. +void analogWrite(uint8_t pin, int val) +{ + // We need to make sure the PWM output is enabled for those pins + // that support it, as we turn it off when digitally reading or + // writing with them. Also, make sure the pin is in output mode + // for consistenty with Wiring, which doesn't require a pinMode + // call for the analog output pins. + pinMode(pin, OUTPUT); + if (val == 0) + { + digitalWrite(pin, LOW); + } + else if (val == 255) + { + digitalWrite(pin, HIGH); + } + else + { + switch(digitalPinToTimer(pin)) + { + // XXX fix needed for atmega8 + #if defined(TCCR0) && defined(COM00) && !defined(__AVR_ATmega8__) + case TIMER0A: + // connect pwm to pin on timer 0 + sbi(TCCR0, COM00); + OCR0 = val; // set pwm duty + break; + #endif + + #if defined(TCCR0A) && defined(COM0A1) + case TIMER0A: + // connect pwm to pin on timer 0, channel A + sbi(TCCR0A, COM0A1); + OCR0A = val; // set pwm duty + break; + #endif + + #if defined(TCCR0A) && defined(COM0B1) + case TIMER0B: + // connect pwm to pin on timer 0, channel B + sbi(TCCR0A, COM0B1); + OCR0B = val; // set pwm duty + break; + #endif + + #if defined(TCCR1A) && defined(COM1A1) + case TIMER1A: + // connect pwm to pin on timer 1, channel A + sbi(TCCR1A, COM1A1); + OCR1A = val; // set pwm duty + break; + #endif + + #if defined(TCCR1A) && defined(COM1B1) + case TIMER1B: + // connect pwm to pin on timer 1, channel B + sbi(TCCR1A, COM1B1); + OCR1B = val; // set pwm duty + break; + #endif + + #if defined(TCCR2) && defined(COM21) + case TIMER2: + // connect pwm to pin on timer 2 + sbi(TCCR2, COM21); + OCR2 = val; // set pwm duty + break; + #endif + + #if defined(TCCR2A) && defined(COM2A1) + case TIMER2A: + // connect pwm to pin on timer 2, channel A + sbi(TCCR2A, COM2A1); + OCR2A = val; // set pwm duty + break; + #endif + + #if defined(TCCR2A) && defined(COM2B1) + case TIMER2B: + // connect pwm to pin on timer 2, channel B + sbi(TCCR2A, COM2B1); + OCR2B = val; // set pwm duty + break; + #endif + + #if defined(TCCR3A) && defined(COM3A1) + case TIMER3A: + // connect pwm to pin on timer 3, channel A + sbi(TCCR3A, COM3A1); + OCR3A = val; // set pwm duty + break; + #endif + + #if defined(TCCR3A) && defined(COM3B1) + case TIMER3B: + // connect pwm to pin on timer 3, channel B + sbi(TCCR3A, COM3B1); + OCR3B = val; // set pwm duty + break; + #endif + + #if defined(TCCR3A) && defined(COM3C1) + case TIMER3C: + // connect pwm to pin on timer 3, channel C + sbi(TCCR3A, COM3C1); + OCR3C = val; // set pwm duty + break; + #endif + + #if defined(TCCR4A) + case TIMER4A: + //connect pwm to pin on timer 4, channel A + sbi(TCCR4A, COM4A1); + #if defined(COM4A0) // only used on 32U4 + cbi(TCCR4A, COM4A0); + #endif + OCR4A = val; // set pwm duty + break; + #endif + + #if defined(TCCR4A) && defined(COM4B1) + case TIMER4B: + // connect pwm to pin on timer 4, channel B + sbi(TCCR4A, COM4B1); + OCR4B = val; // set pwm duty + break; + #endif + + #if defined(TCCR4A) && defined(COM4C1) + case TIMER4C: + // connect pwm to pin on timer 4, channel C + sbi(TCCR4A, COM4C1); + OCR4C = val; // set pwm duty + break; + #endif + + #if defined(TCCR4C) && defined(COM4D1) + case TIMER4D: + // connect pwm to pin on timer 4, channel D + sbi(TCCR4C, COM4D1); + #if defined(COM4D0) // only used on 32U4 + cbi(TCCR4C, COM4D0); + #endif + OCR4D = val; // set pwm duty + break; + #endif + + + #if defined(TCCR5A) && defined(COM5A1) + case TIMER5A: + // connect pwm to pin on timer 5, channel A + sbi(TCCR5A, COM5A1); + OCR5A = val; // set pwm duty + break; + #endif + + #if defined(TCCR5A) && defined(COM5B1) + case TIMER5B: + // connect pwm to pin on timer 5, channel B + sbi(TCCR5A, COM5B1); + OCR5B = val; // set pwm duty + break; + #endif + + #if defined(TCCR5A) && defined(COM5C1) + case TIMER5C: + // connect pwm to pin on timer 5, channel C + sbi(TCCR5A, COM5C1); + OCR5C = val; // set pwm duty + break; + #endif + + case NOT_ON_TIMER: + default: + if (val < 128) { + digitalWrite(pin, LOW); + } else { + digitalWrite(pin, HIGH); + } + } + } +} + diff --git a/lib/usbhost/arduino-1.0.1/cores/arduino/wiring_digital.c b/lib/usbhost/arduino-1.0.1/cores/arduino/wiring_digital.c new file mode 100644 index 0000000000..be323b1dfe --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/cores/arduino/wiring_digital.c @@ -0,0 +1,178 @@ +/* + wiring_digital.c - digital input and output functions + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2005-2006 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + Modified 28 September 2010 by Mark Sproul + + $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $ +*/ + +#define ARDUINO_MAIN +#include "wiring_private.h" +#include "pins_arduino.h" + +void pinMode(uint8_t pin, uint8_t mode) +{ + uint8_t bit = digitalPinToBitMask(pin); + uint8_t port = digitalPinToPort(pin); + volatile uint8_t *reg, *out; + + if (port == NOT_A_PIN) return; + + // JWS: can I let the optimizer do this? + reg = portModeRegister(port); + out = portOutputRegister(port); + + if (mode == INPUT) { + uint8_t oldSREG = SREG; + cli(); + *reg &= ~bit; + *out &= ~bit; + SREG = oldSREG; + } else if (mode == INPUT_PULLUP) { + uint8_t oldSREG = SREG; + cli(); + *reg &= ~bit; + *out |= bit; + SREG = oldSREG; + } else { + uint8_t oldSREG = SREG; + cli(); + *reg |= bit; + SREG = oldSREG; + } +} + +// Forcing this inline keeps the callers from having to push their own stuff +// on the stack. It is a good performance win and only takes 1 more byte per +// user than calling. (It will take more bytes on the 168.) +// +// But shouldn't this be moved into pinMode? Seems silly to check and do on +// each digitalread or write. +// +// Mark Sproul: +// - Removed inline. Save 170 bytes on atmega1280 +// - changed to a switch statment; added 32 bytes but much easier to read and maintain. +// - Added more #ifdefs, now compiles for atmega645 +// +//static inline void turnOffPWM(uint8_t timer) __attribute__ ((always_inline)); +//static inline void turnOffPWM(uint8_t timer) +static void turnOffPWM(uint8_t timer) +{ + switch (timer) + { + #if defined(TCCR1A) && defined(COM1A1) + case TIMER1A: cbi(TCCR1A, COM1A1); break; + #endif + #if defined(TCCR1A) && defined(COM1B1) + case TIMER1B: cbi(TCCR1A, COM1B1); break; + #endif + + #if defined(TCCR2) && defined(COM21) + case TIMER2: cbi(TCCR2, COM21); break; + #endif + + #if defined(TCCR0A) && defined(COM0A1) + case TIMER0A: cbi(TCCR0A, COM0A1); break; + #endif + + #if defined(TIMER0B) && defined(COM0B1) + case TIMER0B: cbi(TCCR0A, COM0B1); break; + #endif + #if defined(TCCR2A) && defined(COM2A1) + case TIMER2A: cbi(TCCR2A, COM2A1); break; + #endif + #if defined(TCCR2A) && defined(COM2B1) + case TIMER2B: cbi(TCCR2A, COM2B1); break; + #endif + + #if defined(TCCR3A) && defined(COM3A1) + case TIMER3A: cbi(TCCR3A, COM3A1); break; + #endif + #if defined(TCCR3A) && defined(COM3B1) + case TIMER3B: cbi(TCCR3A, COM3B1); break; + #endif + #if defined(TCCR3A) && defined(COM3C1) + case TIMER3C: cbi(TCCR3A, COM3C1); break; + #endif + + #if defined(TCCR4A) && defined(COM4A1) + case TIMER4A: cbi(TCCR4A, COM4A1); break; + #endif + #if defined(TCCR4A) && defined(COM4B1) + case TIMER4B: cbi(TCCR4A, COM4B1); break; + #endif + #if defined(TCCR4A) && defined(COM4C1) + case TIMER4C: cbi(TCCR4A, COM4C1); break; + #endif + #if defined(TCCR4C) && defined(COM4D1) + case TIMER4D: cbi(TCCR4C, COM4D1); break; + #endif + + #if defined(TCCR5A) + case TIMER5A: cbi(TCCR5A, COM5A1); break; + case TIMER5B: cbi(TCCR5A, COM5B1); break; + case TIMER5C: cbi(TCCR5A, COM5C1); break; + #endif + } +} + +void digitalWrite(uint8_t pin, uint8_t val) +{ + uint8_t timer = digitalPinToTimer(pin); + uint8_t bit = digitalPinToBitMask(pin); + uint8_t port = digitalPinToPort(pin); + volatile uint8_t *out; + + if (port == NOT_A_PIN) return; + + // If the pin that support PWM output, we need to turn it off + // before doing a digital write. + if (timer != NOT_ON_TIMER) turnOffPWM(timer); + + out = portOutputRegister(port); + + uint8_t oldSREG = SREG; + cli(); + + if (val == LOW) { + *out &= ~bit; + } else { + *out |= bit; + } + + SREG = oldSREG; +} + +int digitalRead(uint8_t pin) +{ + uint8_t timer = digitalPinToTimer(pin); + uint8_t bit = digitalPinToBitMask(pin); + uint8_t port = digitalPinToPort(pin); + + if (port == NOT_A_PIN) return LOW; + + // If the pin that support PWM output, we need to turn it off + // before getting a digital reading. + if (timer != NOT_ON_TIMER) turnOffPWM(timer); + + if (*portInputRegister(port) & bit) return HIGH; + return LOW; +} diff --git a/lib/usbhost/arduino-1.0.1/cores/arduino/wiring_private.h b/lib/usbhost/arduino-1.0.1/cores/arduino/wiring_private.h new file mode 100644 index 0000000000..f0ceb0cc4d --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/cores/arduino/wiring_private.h @@ -0,0 +1,69 @@ +/* + wiring_private.h - Internal header file. + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2005-2006 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id: wiring.h 239 2007-01-12 17:58:39Z mellis $ +*/ + +#ifndef WiringPrivate_h +#define WiringPrivate_h + +#include +#include +#include +#include + +#include "Arduino.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +#ifndef cbi +#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) +#endif +#ifndef sbi +#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) +#endif + +#define EXTERNAL_INT_0 0 +#define EXTERNAL_INT_1 1 +#define EXTERNAL_INT_2 2 +#define EXTERNAL_INT_3 3 +#define EXTERNAL_INT_4 4 +#define EXTERNAL_INT_5 5 +#define EXTERNAL_INT_6 6 +#define EXTERNAL_INT_7 7 + +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +#define EXTERNAL_NUM_INTERRUPTS 8 +#elif defined(__AVR_ATmega1284P__) +#define EXTERNAL_NUM_INTERRUPTS 3 +#else +#define EXTERNAL_NUM_INTERRUPTS 2 +#endif + +typedef void (*voidFuncPtr)(void); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/lib/usbhost/arduino-1.0.1/cores/arduino/wiring_pulse.c b/lib/usbhost/arduino-1.0.1/cores/arduino/wiring_pulse.c new file mode 100644 index 0000000000..0d968865d2 --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/cores/arduino/wiring_pulse.c @@ -0,0 +1,69 @@ +/* + wiring_pulse.c - pulseIn() function + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2005-2006 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $ +*/ + +#include "wiring_private.h" +#include "pins_arduino.h" + +/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH + * or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds + * to 3 minutes in length, but must be called at least a few dozen microseconds + * before the start of the pulse. */ +unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout) +{ + // cache the port and bit of the pin in order to speed up the + // pulse width measuring loop and achieve finer resolution. calling + // digitalRead() instead yields much coarser resolution. + uint8_t bit = digitalPinToBitMask(pin); + uint8_t port = digitalPinToPort(pin); + uint8_t stateMask = (state ? bit : 0); + unsigned long width = 0; // keep initialization out of time critical area + + // convert the timeout from microseconds to a number of times through + // the initial loop; it takes 16 clock cycles per iteration. + unsigned long numloops = 0; + unsigned long maxloops = microsecondsToClockCycles(timeout) / 16; + + // wait for any previous pulse to end + while ((*portInputRegister(port) & bit) == stateMask) + if (numloops++ == maxloops) + return 0; + + // wait for the pulse to start + while ((*portInputRegister(port) & bit) != stateMask) + if (numloops++ == maxloops) + return 0; + + // wait for the pulse to stop + while ((*portInputRegister(port) & bit) == stateMask) { + if (numloops++ == maxloops) + return 0; + width++; + } + + // convert the reading to microseconds. The loop has been determined + // to be 20 clock cycles long and have about 16 clocks between the edge + // and the start of the loop. There will be some error introduced by + // the interrupt handlers. + return clockCyclesToMicroseconds(width * 21 + 16); +} diff --git a/lib/usbhost/arduino-1.0.1/cores/arduino/wiring_shift.c b/lib/usbhost/arduino-1.0.1/cores/arduino/wiring_shift.c new file mode 100644 index 0000000000..cfe786758c --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/cores/arduino/wiring_shift.c @@ -0,0 +1,55 @@ +/* + wiring_shift.c - shiftOut() function + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2005-2006 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $ +*/ + +#include "wiring_private.h" + +uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) { + uint8_t value = 0; + uint8_t i; + + for (i = 0; i < 8; ++i) { + digitalWrite(clockPin, HIGH); + if (bitOrder == LSBFIRST) + value |= digitalRead(dataPin) << i; + else + value |= digitalRead(dataPin) << (7 - i); + digitalWrite(clockPin, LOW); + } + return value; +} + +void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val) +{ + uint8_t i; + + for (i = 0; i < 8; i++) { + if (bitOrder == LSBFIRST) + digitalWrite(dataPin, !!(val & (1 << i))); + else + digitalWrite(dataPin, !!(val & (1 << (7 - i)))); + + digitalWrite(clockPin, HIGH); + digitalWrite(clockPin, LOW); + } +} diff --git a/lib/usbhost/arduino-1.0.1/variants/eightanaloginputs/pins_arduino.h b/lib/usbhost/arduino-1.0.1/variants/eightanaloginputs/pins_arduino.h new file mode 100644 index 0000000000..52b37efc40 --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/variants/eightanaloginputs/pins_arduino.h @@ -0,0 +1,27 @@ +/* + pins_arduino.h - Pin definition functions for Arduino + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2007 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id: wiring.h 249 2007-02-03 16:52:51Z mellis $ +*/ + +#include "../standard/pins_arduino.h" +#undef NUM_ANALOG_INPUTS +#define NUM_ANALOG_INPUTS 8 diff --git a/lib/usbhost/arduino-1.0.1/variants/leonardo/pins_arduino.h b/lib/usbhost/arduino-1.0.1/variants/leonardo/pins_arduino.h new file mode 100644 index 0000000000..9f770d6cec --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/variants/leonardo/pins_arduino.h @@ -0,0 +1,256 @@ +/* + pins_arduino.h - Pin definition functions for Arduino + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2007 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id: wiring.h 249 2007-02-03 16:52:51Z mellis $ +*/ + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define TX_RX_LED_INIT DDRD |= (1<<5), DDRB |= (1<<0) +#define TXLED0 PORTD |= (1<<5) +#define TXLED1 PORTD &= ~(1<<5) +#define RXLED0 PORTB |= (1<<0) +#define RXLED1 PORTB &= ~(1<<0) + +static const uint8_t SDA = 2; +static const uint8_t SCL = 3; + +// Map SPI port to 'new' pins D14..D17 +static const uint8_t SS = 17; +static const uint8_t MOSI = 16; +static const uint8_t MISO = 14; +static const uint8_t SCK = 15; + +// Mapping of analog pins as digital I/O +// A6-A11 share with digital pins +static const uint8_t A0 = 18; +static const uint8_t A1 = 19; +static const uint8_t A2 = 20; +static const uint8_t A3 = 21; +static const uint8_t A4 = 22; +static const uint8_t A5 = 23; +static const uint8_t A6 = 24; // D4 +static const uint8_t A7 = 25; // D6 +static const uint8_t A8 = 26; // D8 +static const uint8_t A9 = 27; // D9 +static const uint8_t A10 = 28; // D10 +static const uint8_t A11 = 29; // D12 + +#define digitalPinToPCICR(p) ((((p) >= 8 && (p) <= 11) || ((p) >= 14 && (p) <= 17) || ((p) >= A8 && (p) <= A10)) ? (&PCICR) : ((uint8_t *)0)) +#define digitalPinToPCICRbit(p) 0 +#define digitalPinToPCMSK(p) ((((p) >= 8 && (p) <= 11) || ((p) >= 14 && (p) <= 17) || ((p) >= A8 && (p) <= A10)) ? (&PCMSK0) : ((uint8_t *)0)) +#define digitalPinToPCMSKbit(p) ( ((p) >= 8 && (p) <= 11) ? (p) - 4 : ((p) == 14 ? 3 : ((p) == 15 ? 1 : ((p) == 16 ? 2 : ((p) == 17 ? 0 : (p - A8 + 4)))))) + +// __AVR_ATmega32U4__ has an unusual mapping of pins to channels +extern const uint8_t PROGMEM analog_pin_to_channel_PGM[]; +#define analogPinToChannel(P) ( pgm_read_byte( analog_pin_to_channel_PGM + (P) ) ) + +#ifdef ARDUINO_MAIN + +// On the Arduino board, digital pins are also used +// for the analog output (software PWM). Analog input +// pins are a separate set. + +// ATMEL ATMEGA32U4 / ARDUINO LEONARDO +// +// D0 PD2 RXD1/INT2 +// D1 PD3 TXD1/INT3 +// D2 PD1 SDA SDA/INT1 +// D3# PD0 PWM8/SCL OC0B/SCL/INT0 +// D4 A6 PD4 ADC8 +// D5# PC6 ??? OC3A/#OC4A +// D6# A7 PD7 FastPWM #OC4D/ADC10 +// D7 PE6 INT6/AIN0 +// +// D8 A8 PB4 ADC11/PCINT4 +// D9# A9 PB5 PWM16 OC1A/#OC4B/ADC12/PCINT5 +// D10# A10 PB6 PWM16 OC1B/0c4B/ADC13/PCINT6 +// D11# PB7 PWM8/16 0C0A/OC1C/#RTS/PCINT7 +// D12 A11 PD6 T1/#OC4D/ADC9 +// D13# PC7 PWM10 CLK0/OC4A +// +// A0 D18 PF7 ADC7 +// A1 D19 PF6 ADC6 +// A2 D20 PF5 ADC5 +// A3 D21 PF4 ADC4 +// A4 D22 PF1 ADC1 +// A5 D23 PF0 ADC0 +// +// New pins D14..D17 to map SPI port to digital pins +// +// MISO D14 PB3 MISO,PCINT3 +// SCK D15 PB1 SCK,PCINT1 +// MOSI D16 PB2 MOSI,PCINT2 +// SS D17 PB0 RXLED,SS/PCINT0 +// +// TXLED PD5 +// RXLED PB0 +// HWB PE2 HWB + +// these arrays map port names (e.g. port B) to the +// appropriate addresses for various functions (e.g. reading +// and writing) +const uint16_t PROGMEM port_to_mode_PGM[] = { + NOT_A_PORT, + NOT_A_PORT, + (uint16_t) &DDRB, + (uint16_t) &DDRC, + (uint16_t) &DDRD, + (uint16_t) &DDRE, + (uint16_t) &DDRF, +}; + +const uint16_t PROGMEM port_to_output_PGM[] = { + NOT_A_PORT, + NOT_A_PORT, + (uint16_t) &PORTB, + (uint16_t) &PORTC, + (uint16_t) &PORTD, + (uint16_t) &PORTE, + (uint16_t) &PORTF, +}; + +const uint16_t PROGMEM port_to_input_PGM[] = { + NOT_A_PORT, + NOT_A_PORT, + (uint16_t) &PINB, + (uint16_t) &PINC, + (uint16_t) &PIND, + (uint16_t) &PINE, + (uint16_t) &PINF, +}; + +const uint8_t PROGMEM digital_pin_to_port_PGM[30] = { + PD, // D0 - PD2 + PD, // D1 - PD3 + PD, // D2 - PD1 + PD, // D3 - PD0 + PD, // D4 - PD4 + PC, // D5 - PC6 + PD, // D6 - PD7 + PE, // D7 - PE6 + + PB, // D8 - PB4 + PB, // D9 - PB5 + PB, // D10 - PB6 + PB, // D11 - PB7 + PD, // D12 - PD6 + PC, // D13 - PC7 + + PB, // D14 - MISO - PB3 + PB, // D15 - SCK - PB1 + PB, // D16 - MOSI - PB2 + PB, // D17 - SS - PB0 + + PF, // D18 - A0 - PF7 + PF, // D19 - A1 - PF6 + PF, // D20 - A2 - PF5 + PF, // D21 - A3 - PF4 + PF, // D22 - A4 - PF1 + PF, // D23 - A5 - PF0 + + PD, // D24 / D4 - A6 - PD4 + PD, // D25 / D6 - A7 - PD7 + PB, // D26 / D8 - A8 - PB4 + PB, // D27 / D9 - A9 - PB5 + PB, // D28 / D10 - A10 - PB6 + PD, // D29 / D12 - A11 - PD6 +}; + +const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[30] = { + _BV(2), // D0 - PD2 + _BV(3), // D1 - PD3 + _BV(1), // D2 - PD1 + _BV(0), // D3 - PD0 + _BV(4), // D4 - PD4 + _BV(6), // D5 - PC6 + _BV(7), // D6 - PD7 + _BV(6), // D7 - PE6 + + _BV(4), // D8 - PB4 + _BV(5), // D9 - PB5 + _BV(6), // D10 - PB6 + _BV(7), // D11 - PB7 + _BV(6), // D12 - PD6 + _BV(7), // D13 - PC7 + + _BV(3), // D14 - MISO - PB3 + _BV(1), // D15 - SCK - PB1 + _BV(2), // D16 - MOSI - PB2 + _BV(0), // D17 - SS - PB0 + + _BV(7), // D18 - A0 - PF7 + _BV(6), // D19 - A1 - PF6 + _BV(5), // D20 - A2 - PF5 + _BV(4), // D21 - A3 - PF4 + _BV(1), // D22 - A4 - PF1 + _BV(0), // D23 - A5 - PF0 + + _BV(4), // D24 / D4 - A6 - PD4 + _BV(7), // D25 / D6 - A7 - PD7 + _BV(4), // D26 / D8 - A8 - PB4 + _BV(5), // D27 / D9 - A9 - PB5 + _BV(6), // D28 / D10 - A10 - PB6 + _BV(6), // D29 / D12 - A11 - PD6 +}; + +const uint8_t PROGMEM digital_pin_to_timer_PGM[16] = { + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + TIMER0B, /* 3 */ + NOT_ON_TIMER, + TIMER3A, /* 5 */ + TIMER4D, /* 6 */ + NOT_ON_TIMER, + + NOT_ON_TIMER, + TIMER1A, /* 9 */ + TIMER1B, /* 10 */ + TIMER0A, /* 11 */ + + NOT_ON_TIMER, + TIMER4A, /* 13 */ + + NOT_ON_TIMER, + NOT_ON_TIMER, +}; + +const uint8_t PROGMEM analog_pin_to_channel_PGM[12] = { + 7, // A0 PF7 ADC7 + 6, // A1 PF6 ADC6 + 5, // A2 PF5 ADC5 + 4, // A3 PF4 ADC4 + 1, // A4 PF1 ADC1 + 0, // A5 PF0 ADC0 + 8, // A6 D4 PD4 ADC8 + 10, // A7 D6 PD7 ADC10 + 11, // A8 D8 PB4 ADC11 + 12, // A9 D9 PB5 ADC12 + 13, // A10 D10 PB6 ADC13 + 9 // A11 D12 PD6 ADC9 +}; + +#endif /* ARDUINO_MAIN */ +#endif /* Pins_Arduino_h */ diff --git a/lib/usbhost/arduino-1.0.1/variants/mega/pins_arduino.h b/lib/usbhost/arduino-1.0.1/variants/mega/pins_arduino.h new file mode 100644 index 0000000000..5a9b4cb09b --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/variants/mega/pins_arduino.h @@ -0,0 +1,363 @@ +/* + pins_arduino.h - Pin definition functions for Arduino + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2007 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id: wiring.h 249 2007-02-03 16:52:51Z mellis $ +*/ + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define NUM_DIGITAL_PINS 70 +#define NUM_ANALOG_INPUTS 16 +#define analogInputToDigitalPin(p) ((p < 16) ? (p) + 54 : -1) +#define digitalPinHasPWM(p) (((p) >= 2 && (p) <= 13) || ((p) >= 44 && (p)<= 46)) + +static const uint8_t SS = 53; +static const uint8_t MOSI = 51; +static const uint8_t MISO = 50; +static const uint8_t SCK = 52; + +static const uint8_t SDA = 20; +static const uint8_t SCL = 21; +static const uint8_t LED_BUILTIN = 13; + +static const uint8_t A0 = 54; +static const uint8_t A1 = 55; +static const uint8_t A2 = 56; +static const uint8_t A3 = 57; +static const uint8_t A4 = 58; +static const uint8_t A5 = 59; +static const uint8_t A6 = 60; +static const uint8_t A7 = 61; +static const uint8_t A8 = 62; +static const uint8_t A9 = 63; +static const uint8_t A10 = 64; +static const uint8_t A11 = 65; +static const uint8_t A12 = 66; +static const uint8_t A13 = 67; +static const uint8_t A14 = 68; +static const uint8_t A15 = 69; + +// A majority of the pins are NOT PCINTs, SO BE WARNED (i.e. you cannot use them as receive pins) +// Only pins available for RECEIVE (TRANSMIT can be on any pin): +// (I've deliberately left out pin mapping to the Hardware USARTs - seems senseless to me) +// Pins: 10, 11, 12, 13, 50, 51, 52, 53, 62, 63, 64, 65, 66, 67, 68, 69 + +#define digitalPinToPCICR(p) ( (((p) >= 10) && ((p) <= 13)) || \ + (((p) >= 50) && ((p) <= 53)) || \ + (((p) >= 62) && ((p) <= 69)) ? (&PCICR) : ((uint8_t *)0) ) + +#define digitalPinToPCICRbit(p) ( (((p) >= 10) && ((p) <= 13)) || (((p) >= 50) && ((p) <= 53)) ? 0 : \ + ( (((p) >= 62) && ((p) <= 69)) ? 2 : \ + 0 ) ) + +#define digitalPinToPCMSK(p) ( (((p) >= 10) && ((p) <= 13)) || (((p) >= 50) && ((p) <= 53)) ? (&PCMSK0) : \ + ( (((p) >= 62) && ((p) <= 69)) ? (&PCMSK2) : \ + ((uint8_t *)0) ) ) + +#define digitalPinToPCMSKbit(p) ( (((p) >= 10) && ((p) <= 13)) ? ((p) - 6) : \ + ( ((p) == 50) ? 3 : \ + ( ((p) == 51) ? 2 : \ + ( ((p) == 52) ? 1 : \ + ( ((p) == 53) ? 0 : \ + ( (((p) >= 62) && ((p) <= 69)) ? ((p) - 62) : \ + 0 ) ) ) ) ) ) + +#ifdef ARDUINO_MAIN + +const uint16_t PROGMEM port_to_mode_PGM[] = { + NOT_A_PORT, + (uint16_t) &DDRA, + (uint16_t) &DDRB, + (uint16_t) &DDRC, + (uint16_t) &DDRD, + (uint16_t) &DDRE, + (uint16_t) &DDRF, + (uint16_t) &DDRG, + (uint16_t) &DDRH, + NOT_A_PORT, + (uint16_t) &DDRJ, + (uint16_t) &DDRK, + (uint16_t) &DDRL, +}; + +const uint16_t PROGMEM port_to_output_PGM[] = { + NOT_A_PORT, + (uint16_t) &PORTA, + (uint16_t) &PORTB, + (uint16_t) &PORTC, + (uint16_t) &PORTD, + (uint16_t) &PORTE, + (uint16_t) &PORTF, + (uint16_t) &PORTG, + (uint16_t) &PORTH, + NOT_A_PORT, + (uint16_t) &PORTJ, + (uint16_t) &PORTK, + (uint16_t) &PORTL, +}; + +const uint16_t PROGMEM port_to_input_PGM[] = { + NOT_A_PIN, + (uint16_t) &PINA, + (uint16_t) &PINB, + (uint16_t) &PINC, + (uint16_t) &PIND, + (uint16_t) &PINE, + (uint16_t) &PINF, + (uint16_t) &PING, + (uint16_t) &PINH, + NOT_A_PIN, + (uint16_t) &PINJ, + (uint16_t) &PINK, + (uint16_t) &PINL, +}; + +const uint8_t PROGMEM digital_pin_to_port_PGM[] = { + // PORTLIST + // ------------------------------------------- + PE , // PE 0 ** 0 ** USART0_RX + PE , // PE 1 ** 1 ** USART0_TX + PE , // PE 4 ** 2 ** PWM2 + PE , // PE 5 ** 3 ** PWM3 + PG , // PG 5 ** 4 ** PWM4 + PE , // PE 3 ** 5 ** PWM5 + PH , // PH 3 ** 6 ** PWM6 + PH , // PH 4 ** 7 ** PWM7 + PH , // PH 5 ** 8 ** PWM8 + PH , // PH 6 ** 9 ** PWM9 + PB , // PB 4 ** 10 ** PWM10 + PB , // PB 5 ** 11 ** PWM11 + PB , // PB 6 ** 12 ** PWM12 + PB , // PB 7 ** 13 ** PWM13 + PJ , // PJ 1 ** 14 ** USART3_TX + PJ , // PJ 0 ** 15 ** USART3_RX + PH , // PH 1 ** 16 ** USART2_TX + PH , // PH 0 ** 17 ** USART2_RX + PD , // PD 3 ** 18 ** USART1_TX + PD , // PD 2 ** 19 ** USART1_RX + PD , // PD 1 ** 20 ** I2C_SDA + PD , // PD 0 ** 21 ** I2C_SCL + PA , // PA 0 ** 22 ** D22 + PA , // PA 1 ** 23 ** D23 + PA , // PA 2 ** 24 ** D24 + PA , // PA 3 ** 25 ** D25 + PA , // PA 4 ** 26 ** D26 + PA , // PA 5 ** 27 ** D27 + PA , // PA 6 ** 28 ** D28 + PA , // PA 7 ** 29 ** D29 + PC , // PC 7 ** 30 ** D30 + PC , // PC 6 ** 31 ** D31 + PC , // PC 5 ** 32 ** D32 + PC , // PC 4 ** 33 ** D33 + PC , // PC 3 ** 34 ** D34 + PC , // PC 2 ** 35 ** D35 + PC , // PC 1 ** 36 ** D36 + PC , // PC 0 ** 37 ** D37 + PD , // PD 7 ** 38 ** D38 + PG , // PG 2 ** 39 ** D39 + PG , // PG 1 ** 40 ** D40 + PG , // PG 0 ** 41 ** D41 + PL , // PL 7 ** 42 ** D42 + PL , // PL 6 ** 43 ** D43 + PL , // PL 5 ** 44 ** D44 + PL , // PL 4 ** 45 ** D45 + PL , // PL 3 ** 46 ** D46 + PL , // PL 2 ** 47 ** D47 + PL , // PL 1 ** 48 ** D48 + PL , // PL 0 ** 49 ** D49 + PB , // PB 3 ** 50 ** SPI_MISO + PB , // PB 2 ** 51 ** SPI_MOSI + PB , // PB 1 ** 52 ** SPI_SCK + PB , // PB 0 ** 53 ** SPI_SS + PF , // PF 0 ** 54 ** A0 + PF , // PF 1 ** 55 ** A1 + PF , // PF 2 ** 56 ** A2 + PF , // PF 3 ** 57 ** A3 + PF , // PF 4 ** 58 ** A4 + PF , // PF 5 ** 59 ** A5 + PF , // PF 6 ** 60 ** A6 + PF , // PF 7 ** 61 ** A7 + PK , // PK 0 ** 62 ** A8 + PK , // PK 1 ** 63 ** A9 + PK , // PK 2 ** 64 ** A10 + PK , // PK 3 ** 65 ** A11 + PK , // PK 4 ** 66 ** A12 + PK , // PK 5 ** 67 ** A13 + PK , // PK 6 ** 68 ** A14 + PK , // PK 7 ** 69 ** A15 +}; + +const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = { + // PIN IN PORT + // ------------------------------------------- + _BV( 0 ) , // PE 0 ** 0 ** USART0_RX + _BV( 1 ) , // PE 1 ** 1 ** USART0_TX + _BV( 4 ) , // PE 4 ** 2 ** PWM2 + _BV( 5 ) , // PE 5 ** 3 ** PWM3 + _BV( 5 ) , // PG 5 ** 4 ** PWM4 + _BV( 3 ) , // PE 3 ** 5 ** PWM5 + _BV( 3 ) , // PH 3 ** 6 ** PWM6 + _BV( 4 ) , // PH 4 ** 7 ** PWM7 + _BV( 5 ) , // PH 5 ** 8 ** PWM8 + _BV( 6 ) , // PH 6 ** 9 ** PWM9 + _BV( 4 ) , // PB 4 ** 10 ** PWM10 + _BV( 5 ) , // PB 5 ** 11 ** PWM11 + _BV( 6 ) , // PB 6 ** 12 ** PWM12 + _BV( 7 ) , // PB 7 ** 13 ** PWM13 + _BV( 1 ) , // PJ 1 ** 14 ** USART3_TX + _BV( 0 ) , // PJ 0 ** 15 ** USART3_RX + _BV( 1 ) , // PH 1 ** 16 ** USART2_TX + _BV( 0 ) , // PH 0 ** 17 ** USART2_RX + _BV( 3 ) , // PD 3 ** 18 ** USART1_TX + _BV( 2 ) , // PD 2 ** 19 ** USART1_RX + _BV( 1 ) , // PD 1 ** 20 ** I2C_SDA + _BV( 0 ) , // PD 0 ** 21 ** I2C_SCL + _BV( 0 ) , // PA 0 ** 22 ** D22 + _BV( 1 ) , // PA 1 ** 23 ** D23 + _BV( 2 ) , // PA 2 ** 24 ** D24 + _BV( 3 ) , // PA 3 ** 25 ** D25 + _BV( 4 ) , // PA 4 ** 26 ** D26 + _BV( 5 ) , // PA 5 ** 27 ** D27 + _BV( 6 ) , // PA 6 ** 28 ** D28 + _BV( 7 ) , // PA 7 ** 29 ** D29 + _BV( 7 ) , // PC 7 ** 30 ** D30 + _BV( 6 ) , // PC 6 ** 31 ** D31 + _BV( 5 ) , // PC 5 ** 32 ** D32 + _BV( 4 ) , // PC 4 ** 33 ** D33 + _BV( 3 ) , // PC 3 ** 34 ** D34 + _BV( 2 ) , // PC 2 ** 35 ** D35 + _BV( 1 ) , // PC 1 ** 36 ** D36 + _BV( 0 ) , // PC 0 ** 37 ** D37 + _BV( 7 ) , // PD 7 ** 38 ** D38 + _BV( 2 ) , // PG 2 ** 39 ** D39 + _BV( 1 ) , // PG 1 ** 40 ** D40 + _BV( 0 ) , // PG 0 ** 41 ** D41 + _BV( 7 ) , // PL 7 ** 42 ** D42 + _BV( 6 ) , // PL 6 ** 43 ** D43 + _BV( 5 ) , // PL 5 ** 44 ** D44 + _BV( 4 ) , // PL 4 ** 45 ** D45 + _BV( 3 ) , // PL 3 ** 46 ** D46 + _BV( 2 ) , // PL 2 ** 47 ** D47 + _BV( 1 ) , // PL 1 ** 48 ** D48 + _BV( 0 ) , // PL 0 ** 49 ** D49 + _BV( 3 ) , // PB 3 ** 50 ** SPI_MISO + _BV( 2 ) , // PB 2 ** 51 ** SPI_MOSI + _BV( 1 ) , // PB 1 ** 52 ** SPI_SCK + _BV( 0 ) , // PB 0 ** 53 ** SPI_SS + _BV( 0 ) , // PF 0 ** 54 ** A0 + _BV( 1 ) , // PF 1 ** 55 ** A1 + _BV( 2 ) , // PF 2 ** 56 ** A2 + _BV( 3 ) , // PF 3 ** 57 ** A3 + _BV( 4 ) , // PF 4 ** 58 ** A4 + _BV( 5 ) , // PF 5 ** 59 ** A5 + _BV( 6 ) , // PF 6 ** 60 ** A6 + _BV( 7 ) , // PF 7 ** 61 ** A7 + _BV( 0 ) , // PK 0 ** 62 ** A8 + _BV( 1 ) , // PK 1 ** 63 ** A9 + _BV( 2 ) , // PK 2 ** 64 ** A10 + _BV( 3 ) , // PK 3 ** 65 ** A11 + _BV( 4 ) , // PK 4 ** 66 ** A12 + _BV( 5 ) , // PK 5 ** 67 ** A13 + _BV( 6 ) , // PK 6 ** 68 ** A14 + _BV( 7 ) , // PK 7 ** 69 ** A15 +}; + +const uint8_t PROGMEM digital_pin_to_timer_PGM[] = { + // TIMERS + // ------------------------------------------- + NOT_ON_TIMER , // PE 0 ** 0 ** USART0_RX + NOT_ON_TIMER , // PE 1 ** 1 ** USART0_TX + TIMER3B , // PE 4 ** 2 ** PWM2 + TIMER3C , // PE 5 ** 3 ** PWM3 + TIMER0B , // PG 5 ** 4 ** PWM4 + TIMER3A , // PE 3 ** 5 ** PWM5 + TIMER4A , // PH 3 ** 6 ** PWM6 + TIMER4B , // PH 4 ** 7 ** PWM7 + TIMER4C , // PH 5 ** 8 ** PWM8 + TIMER2B , // PH 6 ** 9 ** PWM9 + TIMER2A , // PB 4 ** 10 ** PWM10 + TIMER1A , // PB 5 ** 11 ** PWM11 + TIMER1B , // PB 6 ** 12 ** PWM12 + TIMER0A , // PB 7 ** 13 ** PWM13 + NOT_ON_TIMER , // PJ 1 ** 14 ** USART3_TX + NOT_ON_TIMER , // PJ 0 ** 15 ** USART3_RX + NOT_ON_TIMER , // PH 1 ** 16 ** USART2_TX + NOT_ON_TIMER , // PH 0 ** 17 ** USART2_RX + NOT_ON_TIMER , // PD 3 ** 18 ** USART1_TX + NOT_ON_TIMER , // PD 2 ** 19 ** USART1_RX + NOT_ON_TIMER , // PD 1 ** 20 ** I2C_SDA + NOT_ON_TIMER , // PD 0 ** 21 ** I2C_SCL + NOT_ON_TIMER , // PA 0 ** 22 ** D22 + NOT_ON_TIMER , // PA 1 ** 23 ** D23 + NOT_ON_TIMER , // PA 2 ** 24 ** D24 + NOT_ON_TIMER , // PA 3 ** 25 ** D25 + NOT_ON_TIMER , // PA 4 ** 26 ** D26 + NOT_ON_TIMER , // PA 5 ** 27 ** D27 + NOT_ON_TIMER , // PA 6 ** 28 ** D28 + NOT_ON_TIMER , // PA 7 ** 29 ** D29 + NOT_ON_TIMER , // PC 7 ** 30 ** D30 + NOT_ON_TIMER , // PC 6 ** 31 ** D31 + NOT_ON_TIMER , // PC 5 ** 32 ** D32 + NOT_ON_TIMER , // PC 4 ** 33 ** D33 + NOT_ON_TIMER , // PC 3 ** 34 ** D34 + NOT_ON_TIMER , // PC 2 ** 35 ** D35 + NOT_ON_TIMER , // PC 1 ** 36 ** D36 + NOT_ON_TIMER , // PC 0 ** 37 ** D37 + NOT_ON_TIMER , // PD 7 ** 38 ** D38 + NOT_ON_TIMER , // PG 2 ** 39 ** D39 + NOT_ON_TIMER , // PG 1 ** 40 ** D40 + NOT_ON_TIMER , // PG 0 ** 41 ** D41 + NOT_ON_TIMER , // PL 7 ** 42 ** D42 + NOT_ON_TIMER , // PL 6 ** 43 ** D43 + TIMER5C , // PL 5 ** 44 ** D44 + TIMER5B , // PL 4 ** 45 ** D45 + TIMER5A , // PL 3 ** 46 ** D46 + NOT_ON_TIMER , // PL 2 ** 47 ** D47 + NOT_ON_TIMER , // PL 1 ** 48 ** D48 + NOT_ON_TIMER , // PL 0 ** 49 ** D49 + NOT_ON_TIMER , // PB 3 ** 50 ** SPI_MISO + NOT_ON_TIMER , // PB 2 ** 51 ** SPI_MOSI + NOT_ON_TIMER , // PB 1 ** 52 ** SPI_SCK + NOT_ON_TIMER , // PB 0 ** 53 ** SPI_SS + NOT_ON_TIMER , // PF 0 ** 54 ** A0 + NOT_ON_TIMER , // PF 1 ** 55 ** A1 + NOT_ON_TIMER , // PF 2 ** 56 ** A2 + NOT_ON_TIMER , // PF 3 ** 57 ** A3 + NOT_ON_TIMER , // PF 4 ** 58 ** A4 + NOT_ON_TIMER , // PF 5 ** 59 ** A5 + NOT_ON_TIMER , // PF 6 ** 60 ** A6 + NOT_ON_TIMER , // PF 7 ** 61 ** A7 + NOT_ON_TIMER , // PK 0 ** 62 ** A8 + NOT_ON_TIMER , // PK 1 ** 63 ** A9 + NOT_ON_TIMER , // PK 2 ** 64 ** A10 + NOT_ON_TIMER , // PK 3 ** 65 ** A11 + NOT_ON_TIMER , // PK 4 ** 66 ** A12 + NOT_ON_TIMER , // PK 5 ** 67 ** A13 + NOT_ON_TIMER , // PK 6 ** 68 ** A14 + NOT_ON_TIMER , // PK 7 ** 69 ** A15 +}; + +#endif + +#endif \ No newline at end of file diff --git a/lib/usbhost/arduino-1.0.1/variants/standard/pins_arduino.h b/lib/usbhost/arduino-1.0.1/variants/standard/pins_arduino.h new file mode 100644 index 0000000000..30b4266306 --- /dev/null +++ b/lib/usbhost/arduino-1.0.1/variants/standard/pins_arduino.h @@ -0,0 +1,218 @@ +/* + pins_arduino.h - Pin definition functions for Arduino + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2007 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id: wiring.h 249 2007-02-03 16:52:51Z mellis $ +*/ + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define NUM_DIGITAL_PINS 20 +#define NUM_ANALOG_INPUTS 6 +#define analogInputToDigitalPin(p) ((p < 6) ? (p) + 14 : -1) + +#if defined(__AVR_ATmega8__) +#define digitalPinHasPWM(p) ((p) == 9 || (p) == 10 || (p) == 11) +#else +#define digitalPinHasPWM(p) ((p) == 3 || (p) == 5 || (p) == 6 || (p) == 9 || (p) == 10 || (p) == 11) +#endif + +static const uint8_t SS = 10; +static const uint8_t MOSI = 11; +static const uint8_t MISO = 12; +static const uint8_t SCK = 13; + +static const uint8_t SDA = 18; +static const uint8_t SCL = 19; +static const uint8_t LED_BUILTIN = 13; + +static const uint8_t A0 = 14; +static const uint8_t A1 = 15; +static const uint8_t A2 = 16; +static const uint8_t A3 = 17; +static const uint8_t A4 = 18; +static const uint8_t A5 = 19; +static const uint8_t A6 = 20; +static const uint8_t A7 = 21; + +#define digitalPinToPCICR(p) (((p) >= 0 && (p) <= 21) ? (&PCICR) : ((uint8_t *)0)) +#define digitalPinToPCICRbit(p) (((p) <= 7) ? 2 : (((p) <= 13) ? 0 : 1)) +#define digitalPinToPCMSK(p) (((p) <= 7) ? (&PCMSK2) : (((p) <= 13) ? (&PCMSK0) : (((p) <= 21) ? (&PCMSK1) : ((uint8_t *)0)))) +#define digitalPinToPCMSKbit(p) (((p) <= 7) ? (p) : (((p) <= 13) ? ((p) - 8) : ((p) - 14))) + +#ifdef ARDUINO_MAIN + +// On the Arduino board, digital pins are also used +// for the analog output (software PWM). Analog input +// pins are a separate set. + +// ATMEL ATMEGA8 & 168 / ARDUINO +// +// +-\/-+ +// PC6 1| |28 PC5 (AI 5) +// (D 0) PD0 2| |27 PC4 (AI 4) +// (D 1) PD1 3| |26 PC3 (AI 3) +// (D 2) PD2 4| |25 PC2 (AI 2) +// PWM+ (D 3) PD3 5| |24 PC1 (AI 1) +// (D 4) PD4 6| |23 PC0 (AI 0) +// VCC 7| |22 GND +// GND 8| |21 AREF +// PB6 9| |20 AVCC +// PB7 10| |19 PB5 (D 13) +// PWM+ (D 5) PD5 11| |18 PB4 (D 12) +// PWM+ (D 6) PD6 12| |17 PB3 (D 11) PWM +// (D 7) PD7 13| |16 PB2 (D 10) PWM +// (D 8) PB0 14| |15 PB1 (D 9) PWM +// +----+ +// +// (PWM+ indicates the additional PWM pins on the ATmega168.) + +// ATMEL ATMEGA1280 / ARDUINO +// +// 0-7 PE0-PE7 works +// 8-13 PB0-PB5 works +// 14-21 PA0-PA7 works +// 22-29 PH0-PH7 works +// 30-35 PG5-PG0 works +// 36-43 PC7-PC0 works +// 44-51 PJ7-PJ0 works +// 52-59 PL7-PL0 works +// 60-67 PD7-PD0 works +// A0-A7 PF0-PF7 +// A8-A15 PK0-PK7 + + +// these arrays map port names (e.g. port B) to the +// appropriate addresses for various functions (e.g. reading +// and writing) +const uint16_t PROGMEM port_to_mode_PGM[] = { + NOT_A_PORT, + NOT_A_PORT, + (uint16_t) &DDRB, + (uint16_t) &DDRC, + (uint16_t) &DDRD, +}; + +const uint16_t PROGMEM port_to_output_PGM[] = { + NOT_A_PORT, + NOT_A_PORT, + (uint16_t) &PORTB, + (uint16_t) &PORTC, + (uint16_t) &PORTD, +}; + +const uint16_t PROGMEM port_to_input_PGM[] = { + NOT_A_PORT, + NOT_A_PORT, + (uint16_t) &PINB, + (uint16_t) &PINC, + (uint16_t) &PIND, +}; + +const uint8_t PROGMEM digital_pin_to_port_PGM[] = { + PD, /* 0 */ + PD, + PD, + PD, + PD, + PD, + PD, + PD, + PB, /* 8 */ + PB, + PB, + PB, + PB, + PB, + PC, /* 14 */ + PC, + PC, + PC, + PC, + PC, +}; + +const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = { + _BV(0), /* 0, port D */ + _BV(1), + _BV(2), + _BV(3), + _BV(4), + _BV(5), + _BV(6), + _BV(7), + _BV(0), /* 8, port B */ + _BV(1), + _BV(2), + _BV(3), + _BV(4), + _BV(5), + _BV(0), /* 14, port C */ + _BV(1), + _BV(2), + _BV(3), + _BV(4), + _BV(5), +}; + +const uint8_t PROGMEM digital_pin_to_timer_PGM[] = { + NOT_ON_TIMER, /* 0 - port D */ + NOT_ON_TIMER, + NOT_ON_TIMER, + // on the ATmega168, digital pin 3 has hardware pwm +#if defined(__AVR_ATmega8__) + NOT_ON_TIMER, +#else + TIMER2B, +#endif + NOT_ON_TIMER, + // on the ATmega168, digital pins 5 and 6 have hardware pwm +#if defined(__AVR_ATmega8__) + NOT_ON_TIMER, + NOT_ON_TIMER, +#else + TIMER0B, + TIMER0A, +#endif + NOT_ON_TIMER, + NOT_ON_TIMER, /* 8 - port B */ + TIMER1A, + TIMER1B, +#if defined(__AVR_ATmega8__) + TIMER2, +#else + TIMER2A, +#endif + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, /* 14 - port C */ + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, +}; + +#endif + +#endif diff --git a/tmk_core/protocol/usb_hid.mk b/tmk_core/protocol/usb_hid.mk index e720080979..c0c157c043 100644 --- a/tmk_core/protocol/usb_hid.mk +++ b/tmk_core/protocol/usb_hid.mk @@ -1,10 +1,10 @@ USB_HID_DIR = protocol/usb_hid - +USB_HOST_LIB_DIR = $(LIB_PATH)/usbhost # # USB Host Shield # -USB_HOST_SHIELD_DIR = $(USB_HID_DIR)/USB_Host_Shield_2.0 +USB_HOST_SHIELD_DIR = $(USB_HOST_LIB_DIR)/USB_Host_Shield_2.0 USB_HOST_SHIELD_SRC = \ $(USB_HOST_SHIELD_DIR)/Usb.cpp \ $(USB_HOST_SHIELD_DIR)/hid.cpp \ @@ -17,7 +17,7 @@ USB_HOST_SHIELD_SRC = \ # # Arduino # -ARDUINO_DIR = $(USB_HID_DIR)/arduino-1.0.1 +ARDUINO_DIR = $(USB_HOST_LIB_DIR)/arduino-1.0.1 ARDUINO_CORES_DIR = $(ARDUINO_DIR)/cores/arduino ARDUINO_CORES_SRC = \ $(ARDUINO_CORES_DIR)/Print.cpp \ @@ -58,13 +58,13 @@ OPT_DEFS += -DARDUINO=101 # Search Path # VPATH += $(TMK_DIR)/$(USB_HID_DIR) -VPATH += $(TMK_DIR)/$(USB_HOST_SHIELD_DIR) +VPATH += $(USB_HOST_SHIELD_DIR) # for #include "Arduino.h" -VPATH += $(TMK_DIR)/$(ARDUINO_CORES_DIR) +VPATH += $(ARDUINO_CORES_DIR) # for #include "pins_arduino.h" -VPATH += $(TMK_DIR)/$(ARDUINO_DIR)/variants/leonardo +VPATH += $(ARDUINO_DIR)/variants/leonardo # ad hoc workaround for compile problem on Windows: # Windows doesn't know difference between common/print.h and arduino/Print.h. diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/.gitattributes b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/.gitattributes deleted file mode 100644 index 6238b035a3..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/.gitattributes +++ /dev/null @@ -1,23 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto -* text eol=lf - -# Custom for Visual Studio -*.cs diff=csharp -*.sln merge=union -*.csproj merge=union -*.vbproj merge=union -*.fsproj merge=union -*.dbproj merge=union - -# Standard to msysgit -*.doc diff=astextplain -*.DOC diff=astextplain -*.docx diff=astextplain -*.DOCX diff=astextplain -*.dot diff=astextplain -*.DOT diff=astextplain -*.pdf diff=astextplain -*.PDF diff=astextplain -*.rtf diff=astextplain -*.RTF diff=astextplain diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/.gitignore b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/.gitignore deleted file mode 100644 index 7e69f457ba..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -*.bak -*.zip -*.rar -build/ \ No newline at end of file diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/.gitmodules b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/.gitmodules deleted file mode 100644 index 32a0783a89..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/.gitmodules +++ /dev/null @@ -1,12 +0,0 @@ -[submodule "examples/testusbhostFAT/generic_storage"] - path = examples/testusbhostFAT/generic_storage - url = https://github.com/xxxajk/generic_storage -[submodule "examples/testusbhostFAT/xmem2"] - path = examples/testusbhostFAT/xmem2 - url = https://github.com/xxxajk/xmem2 -[submodule "examples/testusbhostFAT/Arduino_Makefile_master"] - path = examples/testusbhostFAT/Arduino_Makefile_master - url = https://github.com/xxxajk/Arduino_Makefile_master -[submodule "examples/testusbhostFAT/RTClib"] - path = examples/testusbhostFAT/RTClib - url = https://github.com/xxxajk/RTClib diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/BTD.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/BTD.cpp deleted file mode 100755 index bcfba14b2b..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/BTD.cpp +++ /dev/null @@ -1,1364 +0,0 @@ -/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. - - This software may be distributed and modified under the terms of the GNU - General Public License version 2 (GPL2) as published by the Free Software - Foundation and appearing in the file GPL2.TXT included in the packaging of - this file. Please note that GPL2 Section 2[b] requires that all works based - on this software must also be made publicly available under the terms of - the GPL2 ("Copyleft"). - - Contact information - ------------------- - - Kristian Lauszus, TKJ Electronics - Web : http://www.tkjelectronics.com - e-mail : kristianl@tkjelectronics.com - */ - -#include "BTD.h" -// To enable serial debugging see "settings.h" -//#define EXTRADEBUG // Uncomment to get even more debugging data - -const uint8_t BTD::BTD_CONTROL_PIPE = 0; -const uint8_t BTD::BTD_EVENT_PIPE = 1; -const uint8_t BTD::BTD_DATAIN_PIPE = 2; -const uint8_t BTD::BTD_DATAOUT_PIPE = 3; - -BTD::BTD(USB *p) : -connectToWii(false), -pairWithWii(false), -connectToHIDDevice(false), -pairWithHIDDevice(false), -pUsb(p), // Pointer to USB class instance - mandatory -bAddress(0), // Device address - mandatory -bNumEP(1), // If config descriptor needs to be parsed -qNextPollTime(0), // Reset NextPollTime -pollInterval(0), -bPollEnable(false) // Don't start polling before dongle is connected -{ - for(uint8_t i = 0; i < BTD_NUM_SERVICES; i++) - btService[i] = NULL; - - Initialize(); // Set all variables, endpoint structs etc. to default values - - if(pUsb) // Register in USB subsystem - pUsb->RegisterDeviceClass(this); // Set devConfig[] entry -} - -uint8_t BTD::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) { - const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR); - uint8_t buf[constBufSize]; - USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); - uint8_t rcode; - UsbDevice *p = NULL; - EpInfo *oldep_ptr = NULL; - - Initialize(); // Set all variables, endpoint structs etc. to default values - - AddressPool &addrPool = pUsb->GetAddressPool(); // Get memory address of USB device address pool -#ifdef EXTRADEBUG - Notify(PSTR("\r\nBTD ConfigureDevice"), 0x80); -#endif - - if(bAddress) { // Check if address has already been assigned to an instance -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nAddress in use"), 0x80); -#endif - return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; - } - - p = addrPool.GetUsbDevicePtr(0); // Get pointer to pseudo device with address 0 assigned - if(!p) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nAddress not found"), 0x80); -#endif - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - } - - if(!p->epinfo) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nepinfo is null"), 0x80); -#endif - return USB_ERROR_EPINFO_IS_NULL; - } - - oldep_ptr = p->epinfo; // Save old pointer to EP_RECORD of address 0 - p->epinfo = epInfo; // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence - p->lowspeed = lowspeed; - rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data - - p->epinfo = oldep_ptr; // Restore p->epinfo - - if(rcode) - goto FailGetDevDescr; - - bAddress = addrPool.AllocAddress(parent, false, port); // Allocate new address according to device class - - if(!bAddress) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nOut of address space"), 0x80); -#endif - return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; - } - - epInfo[0].maxPktSize = udd->bMaxPacketSize0; // Extract Max Packet Size from device descriptor - epInfo[1].epAddr = udd->bNumConfigurations; // Steal and abuse from epInfo structure to save memory - - VID = udd->idVendor; - PID = udd->idProduct; - - return USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET; - -FailGetDevDescr: -#ifdef DEBUG_USB_HOST - NotifyFailGetDevDescr(rcode); -#endif - if(rcode != hrJERR) - rcode = USB_ERROR_FailGetDevDescr; - Release(); - return rcode; -}; - -uint8_t BTD::Init(uint8_t parent, uint8_t port, bool lowspeed) { - uint8_t rcode; - uint8_t num_of_conf = epInfo[1].epAddr; // Number of configurations - epInfo[1].epAddr = 0; - - AddressPool &addrPool = pUsb->GetAddressPool(); -#ifdef EXTRADEBUG - Notify(PSTR("\r\nBTD Init"), 0x80); -#endif - UsbDevice *p = addrPool.GetUsbDevicePtr(bAddress); // Get pointer to assigned address record - - if(!p) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nAddress not found"), 0x80); -#endif - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - } - - delay(300); // Assign new address to the device - - rcode = pUsb->setAddr(0, 0, bAddress); // Assign new address to the device - if(rcode) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nsetAddr: "), 0x80); - D_PrintHex (rcode, 0x80); -#endif - p->lowspeed = false; - goto Fail; - } -#ifdef EXTRADEBUG - Notify(PSTR("\r\nAddr: "), 0x80); - D_PrintHex (bAddress, 0x80); -#endif - - p->lowspeed = false; - - p = addrPool.GetUsbDevicePtr(bAddress); // Get pointer to assigned address record - if(!p) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nAddress not found"), 0x80); -#endif - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - } - - p->lowspeed = lowspeed; - - rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); // Assign epInfo to epinfo pointer - only EP0 is known - if(rcode) - goto FailSetDevTblEntry; - - if(VID == PS3_VID && (PID == PS3_PID || PID == PS3NAVIGATION_PID || PID == PS3MOVE_PID)) { - delay(100); - rcode = pUsb->setConf(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, 1); // We only need the Control endpoint, so we don't have to initialize the other endpoints of device - if(rcode) - goto FailSetConfDescr; - -#ifdef DEBUG_USB_HOST - if(PID == PS3_PID || PID == PS3NAVIGATION_PID) { - if(PID == PS3_PID) - Notify(PSTR("\r\nDualshock 3 Controller Connected"), 0x80); - else // It must be a navigation controller - Notify(PSTR("\r\nNavigation Controller Connected"), 0x80); - } else // It must be a Motion controller - Notify(PSTR("\r\nMotion Controller Connected"), 0x80); -#endif - - if(my_bdaddr[0] == 0x00 && my_bdaddr[1] == 0x00 && my_bdaddr[2] == 0x00 && my_bdaddr[3] == 0x00 && my_bdaddr[4] == 0x00 && my_bdaddr[5] == 0x00) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nPlease plug in the dongle before trying to pair with the PS3 Controller\r\nor set the Bluetooth address in the constructor of the PS3BT class"), 0x80); -#endif - } else { - if(PID == PS3_PID || PID == PS3NAVIGATION_PID) - setBdaddr(my_bdaddr); // Set internal Bluetooth address - else - setMoveBdaddr(my_bdaddr); // Set internal Bluetooth address -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nBluetooth Address was set to: "), 0x80); - for(int8_t i = 5; i > 0; i--) { - D_PrintHex (my_bdaddr[i], 0x80); - Notify(PSTR(":"), 0x80); - } - D_PrintHex (my_bdaddr[0], 0x80); -#endif - } - - pUsb->setConf(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, 0); // Reset configuration value - pUsb->setAddr(bAddress, 0, 0); // Reset address - Release(); // Release device - return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; // Return - } else { - // Check if attached device is a Bluetooth dongle and fill endpoint data structure - // First interface in the configuration must have Bluetooth assigned Class/Subclass/Protocol - // And 3 endpoints - interrupt-IN, bulk-IN, bulk-OUT, not necessarily in this order - for(uint8_t i = 0; i < num_of_conf; i++) { - if(VID == IOGEAR_GBU521_VID && PID == IOGEAR_GBU521_PID) { - ConfigDescParser confDescrParser(this); // Needed for the IOGEAR GBU521 - rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); - } else { - ConfigDescParser confDescrParser(this); - rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); - } - if(rcode) // Check error code - goto FailGetConfDescr; - if(bNumEP >= BTD_MAX_ENDPOINTS) // All endpoints extracted - break; - } - - if(bNumEP < BTD_MAX_ENDPOINTS) - goto FailUnknownDevice; - - // Assign epInfo to epinfo pointer - this time all 3 endpoins - rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); - if(rcode) - goto FailSetDevTblEntry; - - // Set Configuration Value - rcode = pUsb->setConf(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, bConfNum); - if(rcode) - goto FailSetConfDescr; - - hci_num_reset_loops = 100; // only loop 100 times before trying to send the hci reset command - hci_counter = 0; - hci_state = HCI_INIT_STATE; - watingForConnection = false; - bPollEnable = true; - -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nBluetooth Dongle Initialized"), 0x80); -#endif - } - return 0; // Successful configuration - - /* Diagnostic messages */ -FailSetDevTblEntry: -#ifdef DEBUG_USB_HOST - NotifyFailSetDevTblEntry(); - goto Fail; -#endif - -FailGetConfDescr: -#ifdef DEBUG_USB_HOST - NotifyFailGetConfDescr(); - goto Fail; -#endif - -FailSetConfDescr: -#ifdef DEBUG_USB_HOST - NotifyFailSetConfDescr(); -#endif - goto Fail; - -FailUnknownDevice: -#ifdef DEBUG_USB_HOST - NotifyFailUnknownDevice(VID, PID); -#endif - pUsb->setAddr(bAddress, 0, 0); // Reset address - rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; -Fail: -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nBTD Init Failed, error code: "), 0x80); - NotifyFail(rcode); -#endif - Release(); - return rcode; -} - -void BTD::Initialize() { - uint8_t i; - for(i = 0; i < BTD_MAX_ENDPOINTS; i++) { - epInfo[i].epAddr = 0; - epInfo[i].maxPktSize = (i) ? 0 : 8; - epInfo[i].epAttribs = 0; - epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; - } - for(i = 0; i < BTD_NUM_SERVICES; i++) { - if(btService[i]) - btService[i]->Reset(); // Reset all Bluetooth services - } - - connectToWii = false; - incomingWii = false; - connectToHIDDevice = false; - incomingHIDDevice = false; - incomingPS4 = false; - bAddress = 0; // Clear device address - bNumEP = 1; // Must have to be reset to 1 - qNextPollTime = 0; // Reset next poll time - pollInterval = 0; - bPollEnable = false; // Don't start polling before dongle is connected -} - -/* Extracts interrupt-IN, bulk-IN, bulk-OUT endpoint information from config descriptor */ -void BTD::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) { - //ErrorMessage(PSTR("Conf.Val"),conf); - //ErrorMessage(PSTR("Iface Num"),iface); - //ErrorMessage(PSTR("Alt.Set"),alt); - - if(alt) // Wrong interface - by BT spec, no alt setting - return; - - bConfNum = conf; - uint8_t index; - - if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) { // Interrupt In endpoint found - index = BTD_EVENT_PIPE; - epInfo[index].bmNakPower = USB_NAK_NOWAIT; - } else { - if((pep->bmAttributes & 0x02) == 2) // Bulk endpoint found - index = ((pep->bEndpointAddress & 0x80) == 0x80) ? BTD_DATAIN_PIPE : BTD_DATAOUT_PIPE; - else - return; - } - - // Fill the rest of endpoint data structure - epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); - epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; -#ifdef EXTRADEBUG - PrintEndpointDescriptor(pep); -#endif - if(pollInterval < pep->bInterval) // Set the polling interval as the largest polling interval obtained from endpoints - pollInterval = pep->bInterval; - bNumEP++; -} - -void BTD::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) { -#ifdef EXTRADEBUG - Notify(PSTR("\r\nEndpoint descriptor:"), 0x80); - Notify(PSTR("\r\nLength:\t\t"), 0x80); - D_PrintHex (ep_ptr->bLength, 0x80); - Notify(PSTR("\r\nType:\t\t"), 0x80); - D_PrintHex (ep_ptr->bDescriptorType, 0x80); - Notify(PSTR("\r\nAddress:\t"), 0x80); - D_PrintHex (ep_ptr->bEndpointAddress, 0x80); - Notify(PSTR("\r\nAttributes:\t"), 0x80); - D_PrintHex (ep_ptr->bmAttributes, 0x80); - Notify(PSTR("\r\nMaxPktSize:\t"), 0x80); - D_PrintHex (ep_ptr->wMaxPacketSize, 0x80); - Notify(PSTR("\r\nPoll Intrv:\t"), 0x80); - D_PrintHex (ep_ptr->bInterval, 0x80); -#endif -} - -/* Performs a cleanup after failed Init() attempt */ -uint8_t BTD::Release() { - Initialize(); // Set all variables, endpoint structs etc. to default values - pUsb->GetAddressPool().FreeAddress(bAddress); - return 0; -} - -uint8_t BTD::Poll() { - if(!bPollEnable) - return 0; - if((long)(millis() - qNextPollTime) >= 0L) { // Don't poll if shorter than polling interval - qNextPollTime = millis() + pollInterval; // Set new poll time - HCI_event_task(); // Poll the HCI event pipe - HCI_task(); // HCI state machine - ACL_event_task(); // Poll the ACL input pipe too - } - return 0; -} - -void BTD::disconnect() { - for(uint8_t i = 0; i < BTD_NUM_SERVICES; i++) - if(btService[i]) - btService[i]->disconnect(); -}; - -void BTD::HCI_event_task() { - uint16_t length = BULK_MAXPKTSIZE; // Request more than 16 bytes anyway, the inTransfer routine will take care of this - uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[ BTD_EVENT_PIPE ].epAddr, &length, hcibuf); // Input on endpoint 1 - - if(!rcode || rcode == hrNAK) { // Check for errors - switch(hcibuf[0]) { // Switch on event type - case EV_COMMAND_COMPLETE: - if(!hcibuf[5]) { // Check if command succeeded - hci_set_flag(HCI_FLAG_CMD_COMPLETE); // Set command complete flag - if((hcibuf[3] == 0x01) && (hcibuf[4] == 0x10)) { // Parameters from read local version information - hci_version = hcibuf[6]; // Used to check if it supports 2.0+EDR - see http://www.bluetooth.org/Technical/AssignedNumbers/hci.htm - hci_set_flag(HCI_FLAG_READ_VERSION); - } else if((hcibuf[3] == 0x09) && (hcibuf[4] == 0x10)) { // Parameters from read local bluetooth address - for(uint8_t i = 0; i < 6; i++) - my_bdaddr[i] = hcibuf[6 + i]; - hci_set_flag(HCI_FLAG_READ_BDADDR); - } - } - break; - - case EV_COMMAND_STATUS: - if(hcibuf[2]) { // Show status on serial if not OK -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nHCI Command Failed: "), 0x80); - D_PrintHex (hcibuf[2], 0x80); -#endif - } - break; - - case EV_INQUIRY_COMPLETE: - if(inquiry_counter >= 5 && (pairWithWii || pairWithHIDDevice)) { - inquiry_counter = 0; -#ifdef DEBUG_USB_HOST - if(pairWithWii) - Notify(PSTR("\r\nCouldn't find Wiimote"), 0x80); - else - Notify(PSTR("\r\nCouldn't find HID device"), 0x80); -#endif - connectToWii = false; - pairWithWii = false; - connectToHIDDevice = false; - pairWithHIDDevice = false; - hci_state = HCI_SCANNING_STATE; - } - inquiry_counter++; - break; - - case EV_INQUIRY_RESULT: - if(hcibuf[2]) { // Check that there is more than zero responses -#ifdef EXTRADEBUG - Notify(PSTR("\r\nNumber of responses: "), 0x80); - Notify(hcibuf[2], 0x80); -#endif - for(uint8_t i = 0; i < hcibuf[2]; i++) { - uint8_t offset = 8 * hcibuf[2] + 3 * i; - - for(uint8_t j = 0; j < 3; j++) - classOfDevice[j] = hcibuf[j + 4 + offset]; - -#ifdef EXTRADEBUG - Notify(PSTR("\r\nClass of device: "), 0x80); - D_PrintHex (classOfDevice[2], 0x80); - Notify(PSTR(" "), 0x80); - D_PrintHex (classOfDevice[1], 0x80); - Notify(PSTR(" "), 0x80); - D_PrintHex (classOfDevice[0], 0x80); -#endif - - if(pairWithWii && classOfDevice[2] == 0x00 && (classOfDevice[1] & 0x05) && (classOfDevice[0] & 0x0C)) { // See http://wiibrew.org/wiki/Wiimote#SDP_information - checkRemoteName = true; // Check remote name to distinguish between the different controllers - - for(uint8_t j = 0; j < 6; j++) - disc_bdaddr[j] = hcibuf[j + 3 + 6 * i]; - - hci_set_flag(HCI_FLAG_DEVICE_FOUND); - break; - } else if(pairWithHIDDevice && (classOfDevice[1] & 0x05) && (classOfDevice[0] & 0xC8)) { // Check if it is a mouse, keyboard or a gamepad - see: http://bluetooth-pentest.narod.ru/software/bluetooth_class_of_device-service_generator.html -#ifdef DEBUG_USB_HOST - if(classOfDevice[0] & 0x80) - Notify(PSTR("\r\nMouse found"), 0x80); - if(classOfDevice[0] & 0x40) - Notify(PSTR("\r\nKeyboard found"), 0x80); - if(classOfDevice[0] & 0x08) - Notify(PSTR("\r\nGamepad found"), 0x80); -#endif - - for(uint8_t j = 0; j < 6; j++) - disc_bdaddr[j] = hcibuf[j + 3 + 6 * i]; - - hci_set_flag(HCI_FLAG_DEVICE_FOUND); - break; - } - } - } - break; - - case EV_CONNECT_COMPLETE: - hci_set_flag(HCI_FLAG_CONNECT_EVENT); - if(!hcibuf[2]) { // Check if connected OK -#ifdef EXTRADEBUG - Notify(PSTR("\r\nConnection established"), 0x80); -#endif - hci_handle = hcibuf[3] | ((hcibuf[4] & 0x0F) << 8); // Store the handle for the ACL connection - hci_set_flag(HCI_FLAG_CONNECT_COMPLETE); // Set connection complete flag - } else { - hci_state = HCI_CHECK_DEVICE_SERVICE; -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nConnection Failed: "), 0x80); - D_PrintHex (hcibuf[2], 0x80); -#endif - } - break; - - case EV_DISCONNECT_COMPLETE: - if(!hcibuf[2]) { // Check if disconnected OK - hci_set_flag(HCI_FLAG_DISCONNECT_COMPLETE); // Set disconnect command complete flag - hci_clear_flag(HCI_FLAG_CONNECT_COMPLETE); // Clear connection complete flag - } - break; - - case EV_REMOTE_NAME_COMPLETE: - if(!hcibuf[2]) { // Check if reading is OK - for(uint8_t i = 0; i < min(sizeof (remote_name), sizeof (hcibuf) - 9); i++) { - remote_name[i] = hcibuf[9 + i]; - if(remote_name[i] == '\0') // End of string - break; - } - // TODO: Altid sæt '\0' i remote name! - hci_set_flag(HCI_FLAG_REMOTE_NAME_COMPLETE); - } - break; - - case EV_INCOMING_CONNECT: - for(uint8_t i = 0; i < 6; i++) - disc_bdaddr[i] = hcibuf[i + 2]; - - for(uint8_t i = 0; i < 3; i++) - classOfDevice[i] = hcibuf[i + 8]; - - if((classOfDevice[1] & 0x05) && (classOfDevice[0] & 0xC8)) { // Check if it is a mouse, keyboard or a gamepad -#ifdef DEBUG_USB_HOST - if(classOfDevice[0] & 0x80) - Notify(PSTR("\r\nMouse is connecting"), 0x80); - if(classOfDevice[0] & 0x40) - Notify(PSTR("\r\nKeyboard is connecting"), 0x80); - if(classOfDevice[0] & 0x08) - Notify(PSTR("\r\nGamepad is connecting"), 0x80); -#endif - incomingHIDDevice = true; - } - -#ifdef EXTRADEBUG - Notify(PSTR("\r\nClass of device: "), 0x80); - D_PrintHex (classOfDevice[2], 0x80); - Notify(PSTR(" "), 0x80); - D_PrintHex (classOfDevice[1], 0x80); - Notify(PSTR(" "), 0x80); - D_PrintHex (classOfDevice[0], 0x80); -#endif - hci_set_flag(HCI_FLAG_INCOMING_REQUEST); - break; - - case EV_PIN_CODE_REQUEST: - if(pairWithWii) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nPairing with Wiimote"), 0x80); -#endif - hci_pin_code_request_reply(); - } else if(btdPin != NULL) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nBluetooth pin is set too: "), 0x80); - NotifyStr(btdPin, 0x80); -#endif - hci_pin_code_request_reply(); - } else { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nNo pin was set"), 0x80); -#endif - hci_pin_code_negative_request_reply(); - } - break; - - case EV_LINK_KEY_REQUEST: -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nReceived Key Request"), 0x80); -#endif - hci_link_key_request_negative_reply(); - break; - - case EV_AUTHENTICATION_COMPLETE: - if(pairWithWii && !connectToWii) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nPairing successful with Wiimote"), 0x80); -#endif - connectToWii = true; // Used to indicate to the Wii service, that it should connect to this device - } else if(pairWithHIDDevice && !connectToHIDDevice) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nPairing successful with HID device"), 0x80); -#endif - connectToHIDDevice = true; // Used to indicate to the BTHID service, that it should connect to this device - } - break; - /* We will just ignore the following events */ - case EV_NUM_COMPLETE_PKT: - case EV_ROLE_CHANGED: - case EV_PAGE_SCAN_REP_MODE: - case EV_LOOPBACK_COMMAND: - case EV_DATA_BUFFER_OVERFLOW: - case EV_CHANGE_CONNECTION_LINK: - case EV_MAX_SLOTS_CHANGE: - case EV_QOS_SETUP_COMPLETE: - case EV_LINK_KEY_NOTIFICATION: - case EV_ENCRYPTION_CHANGE: - case EV_READ_REMOTE_VERSION_INFORMATION_COMPLETE: - break; -#ifdef EXTRADEBUG - default: - if(hcibuf[0] != 0x00) { - Notify(PSTR("\r\nUnmanaged HCI Event: "), 0x80); - D_PrintHex (hcibuf[0], 0x80); - } - break; -#endif - } // Switch - } -#ifdef EXTRADEBUG - else { - Notify(PSTR("\r\nHCI event error: "), 0x80); - D_PrintHex (rcode, 0x80); - } -#endif -} - -/* Poll Bluetooth and print result */ -void BTD::HCI_task() { - switch(hci_state) { - case HCI_INIT_STATE: - hci_counter++; - if(hci_counter > hci_num_reset_loops) { // wait until we have looped x times to clear any old events - hci_reset(); - hci_state = HCI_RESET_STATE; - hci_counter = 0; - } - break; - - case HCI_RESET_STATE: - hci_counter++; - if(hci_check_flag(HCI_FLAG_CMD_COMPLETE)) { - hci_counter = 0; -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nHCI Reset complete"), 0x80); -#endif - hci_state = HCI_CLASS_STATE; - hci_write_class_of_device(); - } else if(hci_counter > hci_num_reset_loops) { - hci_num_reset_loops *= 10; - if(hci_num_reset_loops > 2000) - hci_num_reset_loops = 2000; -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nNo response to HCI Reset"), 0x80); -#endif - hci_state = HCI_INIT_STATE; - hci_counter = 0; - } - break; - - case HCI_CLASS_STATE: - if(hci_check_flag(HCI_FLAG_CMD_COMPLETE)) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nWrite class of device"), 0x80); -#endif - hci_state = HCI_BDADDR_STATE; - hci_read_bdaddr(); - } - break; - - case HCI_BDADDR_STATE: - if(hci_check_flag(HCI_FLAG_READ_BDADDR)) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nLocal Bluetooth Address: "), 0x80); - for(int8_t i = 5; i > 0; i--) { - D_PrintHex (my_bdaddr[i], 0x80); - Notify(PSTR(":"), 0x80); - } - D_PrintHex (my_bdaddr[0], 0x80); -#endif - hci_read_local_version_information(); - hci_state = HCI_LOCAL_VERSION_STATE; - } - break; - - case HCI_LOCAL_VERSION_STATE: // The local version is used by the PS3BT class - if(hci_check_flag(HCI_FLAG_READ_VERSION)) { - if(btdName != NULL) { - hci_set_local_name(btdName); - hci_state = HCI_SET_NAME_STATE; - } else - hci_state = HCI_CHECK_DEVICE_SERVICE; - } - break; - - case HCI_SET_NAME_STATE: - if(hci_check_flag(HCI_FLAG_CMD_COMPLETE)) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nThe name is set to: "), 0x80); - NotifyStr(btdName, 0x80); -#endif - hci_state = HCI_CHECK_DEVICE_SERVICE; - } - break; - - case HCI_CHECK_DEVICE_SERVICE: - if(pairWithHIDDevice || pairWithWii) { // Check if it should try to connect to a Wiimote -#ifdef DEBUG_USB_HOST - if(pairWithWii) - Notify(PSTR("\r\nStarting inquiry\r\nPress 1 & 2 on the Wiimote\r\nOr press the SYNC button if you are using a Wii U Pro Controller or a Wii Balance Board"), 0x80); - else - Notify(PSTR("\r\nPlease enable discovery of your device"), 0x80); -#endif - hci_inquiry(); - hci_state = HCI_INQUIRY_STATE; - } else - hci_state = HCI_SCANNING_STATE; // Don't try to connect to a Wiimote - break; - - case HCI_INQUIRY_STATE: - if(hci_check_flag(HCI_FLAG_DEVICE_FOUND)) { - hci_inquiry_cancel(); // Stop inquiry -#ifdef DEBUG_USB_HOST - if(pairWithWii) - Notify(PSTR("\r\nWiimote found"), 0x80); - else - Notify(PSTR("\r\nHID device found"), 0x80); - - Notify(PSTR("\r\nNow just create the instance like so:"), 0x80); - if(pairWithWii) - Notify(PSTR("\r\nWII Wii(&Btd);"), 0x80); - else - Notify(PSTR("\r\nBTHID bthid(&Btd);"), 0x80); - - Notify(PSTR("\r\nAnd then press any button on the "), 0x80); - if(pairWithWii) - Notify(PSTR("Wiimote"), 0x80); - else - Notify(PSTR("device"), 0x80); -#endif - if(checkRemoteName) { - hci_remote_name(); // We need to know the name to distinguish between the Wiimote, the new Wiimote with Motion Plus inside, a Wii U Pro Controller and a Wii Balance Board - hci_state = HCI_REMOTE_NAME_STATE; - } else - hci_state = HCI_CONNECT_DEVICE_STATE; - } - break; - - case HCI_CONNECT_DEVICE_STATE: - if(hci_check_flag(HCI_FLAG_CMD_COMPLETE)) { -#ifdef DEBUG_USB_HOST - if(pairWithWii) - Notify(PSTR("\r\nConnecting to Wiimote"), 0x80); - else - Notify(PSTR("\r\nConnecting to HID device"), 0x80); -#endif - checkRemoteName = false; - hci_connect(); - hci_state = HCI_CONNECTED_DEVICE_STATE; - } - break; - - case HCI_CONNECTED_DEVICE_STATE: - if(hci_check_flag(HCI_FLAG_CONNECT_EVENT)) { - if(hci_check_flag(HCI_FLAG_CONNECT_COMPLETE)) { -#ifdef DEBUG_USB_HOST - if(pairWithWii) - Notify(PSTR("\r\nConnected to Wiimote"), 0x80); - else - Notify(PSTR("\r\nConnected to HID device"), 0x80); -#endif - hci_authentication_request(); // This will start the pairing with the Wiimote - hci_state = HCI_SCANNING_STATE; - } else { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nTrying to connect one more time..."), 0x80); -#endif - hci_connect(); // Try to connect one more time - } - } - break; - - case HCI_SCANNING_STATE: - if(!connectToWii && !pairWithWii && !connectToHIDDevice && !pairWithHIDDevice) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nWait For Incoming Connection Request"), 0x80); -#endif - hci_write_scan_enable(); - watingForConnection = true; - hci_state = HCI_CONNECT_IN_STATE; - } - break; - - case HCI_CONNECT_IN_STATE: - if(hci_check_flag(HCI_FLAG_INCOMING_REQUEST)) { - watingForConnection = false; -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nIncoming Connection Request"), 0x80); -#endif - hci_remote_name(); - hci_state = HCI_REMOTE_NAME_STATE; - } else if(hci_check_flag(HCI_FLAG_DISCONNECT_COMPLETE)) - hci_state = HCI_DISCONNECT_STATE; - break; - - case HCI_REMOTE_NAME_STATE: - if(hci_check_flag(HCI_FLAG_REMOTE_NAME_COMPLETE)) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nRemote Name: "), 0x80); - for(uint8_t i = 0; i < strlen(remote_name); i++) - Notifyc(remote_name[i], 0x80); -#endif - if(strncmp((const char*)remote_name, "Nintendo", 8) == 0) { - incomingWii = true; - motionPlusInside = false; - wiiUProController = false; - pairWiiUsingSync = false; -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nWiimote is connecting"), 0x80); -#endif - if(strncmp((const char*)remote_name, "Nintendo RVL-CNT-01-TR", 22) == 0) { -#ifdef DEBUG_USB_HOST - Notify(PSTR(" with Motion Plus Inside"), 0x80); -#endif - motionPlusInside = true; - } else if(strncmp((const char*)remote_name, "Nintendo RVL-CNT-01-UC", 22) == 0) { -#ifdef DEBUG_USB_HOST - Notify(PSTR(" - Wii U Pro Controller"), 0x80); -#endif - wiiUProController = motionPlusInside = pairWiiUsingSync = true; - } else if(strncmp((const char*)remote_name, "Nintendo RVL-WBC-01", 19) == 0) { -#ifdef DEBUG_USB_HOST - Notify(PSTR(" - Wii Balance Board"), 0x80); -#endif - pairWiiUsingSync = true; - } - } - if(classOfDevice[2] == 0 && classOfDevice[1] == 0x25 && classOfDevice[0] == 0x08 && strncmp((const char*)remote_name, "Wireless Controller", 19) == 0) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nPS4 controller is connecting"), 0x80); -#endif - incomingPS4 = true; - } - if(pairWithWii && checkRemoteName) - hci_state = HCI_CONNECT_DEVICE_STATE; - else { - hci_accept_connection(); - hci_state = HCI_CONNECTED_STATE; - } - } - break; - - case HCI_CONNECTED_STATE: - if(hci_check_flag(HCI_FLAG_CONNECT_COMPLETE)) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nConnected to Device: "), 0x80); - for(int8_t i = 5; i > 0; i--) { - D_PrintHex (disc_bdaddr[i], 0x80); - Notify(PSTR(":"), 0x80); - } - D_PrintHex (disc_bdaddr[0], 0x80); -#endif - if(incomingPS4) - connectToHIDDevice = true; // We should always connect to the PS4 controller - - // Clear these flags for a new connection - l2capConnectionClaimed = false; - sdpConnectionClaimed = false; - rfcommConnectionClaimed = false; - - hci_event_flag = 0; - hci_state = HCI_DONE_STATE; - } - break; - - case HCI_DONE_STATE: - hci_counter++; - if(hci_counter > 1000) { // Wait until we have looped 1000 times to make sure that the L2CAP connection has been started - hci_counter = 0; - hci_state = HCI_SCANNING_STATE; - } - break; - - case HCI_DISCONNECT_STATE: - if(hci_check_flag(HCI_FLAG_DISCONNECT_COMPLETE)) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nHCI Disconnected from Device"), 0x80); -#endif - hci_event_flag = 0; // Clear all flags - - // Reset all buffers - memset(hcibuf, 0, BULK_MAXPKTSIZE); - memset(l2capinbuf, 0, BULK_MAXPKTSIZE); - - connectToWii = incomingWii = pairWithWii = false; - connectToHIDDevice = incomingHIDDevice = pairWithHIDDevice = checkRemoteName = false; - incomingPS4 = false; - - hci_state = HCI_SCANNING_STATE; - } - break; - default: - break; - } -} - -void BTD::ACL_event_task() { - uint16_t length = BULK_MAXPKTSIZE; - uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[ BTD_DATAIN_PIPE ].epAddr, &length, l2capinbuf); // Input on endpoint 2 - - if(!rcode) { // Check for errors - if(length > 0) { // Check if any data was read - for(uint8_t i = 0; i < BTD_NUM_SERVICES; i++) { - if(btService[i]) - btService[i]->ACLData(l2capinbuf); - } - } - } -#ifdef EXTRADEBUG - else if(rcode != hrNAK) { - Notify(PSTR("\r\nACL data in error: "), 0x80); - D_PrintHex (rcode, 0x80); - } -#endif - for(uint8_t i = 0; i < BTD_NUM_SERVICES; i++) - if(btService[i]) - btService[i]->Run(); -} - -/************************************************************/ -/* HCI Commands */ - -/************************************************************/ -void BTD::HCI_Command(uint8_t* data, uint16_t nbytes) { - hci_clear_flag(HCI_FLAG_CMD_COMPLETE); - pUsb->ctrlReq(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, bmREQ_HCI_OUT, 0x00, 0x00, 0x00, 0x00, nbytes, nbytes, data, NULL); -} - -void BTD::hci_reset() { - hci_event_flag = 0; // Clear all the flags - hcibuf[0] = 0x03; // HCI OCF = 3 - hcibuf[1] = 0x03 << 2; // HCI OGF = 3 - hcibuf[2] = 0x00; - - HCI_Command(hcibuf, 3); -} - -void BTD::hci_write_scan_enable() { - hci_clear_flag(HCI_FLAG_INCOMING_REQUEST); - hcibuf[0] = 0x1A; // HCI OCF = 1A - hcibuf[1] = 0x03 << 2; // HCI OGF = 3 - hcibuf[2] = 0x01; // parameter length = 1 - if(btdName != NULL) - hcibuf[3] = 0x03; // Inquiry Scan enabled. Page Scan enabled. - else - hcibuf[3] = 0x02; // Inquiry Scan disabled. Page Scan enabled. - - HCI_Command(hcibuf, 4); -} - -void BTD::hci_write_scan_disable() { - hcibuf[0] = 0x1A; // HCI OCF = 1A - hcibuf[1] = 0x03 << 2; // HCI OGF = 3 - hcibuf[2] = 0x01; // parameter length = 1 - hcibuf[3] = 0x00; // Inquiry Scan disabled. Page Scan disabled. - - HCI_Command(hcibuf, 4); -} - -void BTD::hci_read_bdaddr() { - hci_clear_flag(HCI_FLAG_READ_BDADDR); - hcibuf[0] = 0x09; // HCI OCF = 9 - hcibuf[1] = 0x04 << 2; // HCI OGF = 4 - hcibuf[2] = 0x00; - - HCI_Command(hcibuf, 3); -} - -void BTD::hci_read_local_version_information() { - hci_clear_flag(HCI_FLAG_READ_VERSION); - hcibuf[0] = 0x01; // HCI OCF = 1 - hcibuf[1] = 0x04 << 2; // HCI OGF = 4 - hcibuf[2] = 0x00; - - HCI_Command(hcibuf, 3); -} - -void BTD::hci_accept_connection() { - hci_clear_flag(HCI_FLAG_CONNECT_COMPLETE); - hcibuf[0] = 0x09; // HCI OCF = 9 - hcibuf[1] = 0x01 << 2; // HCI OGF = 1 - hcibuf[2] = 0x07; // parameter length 7 - hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr - hcibuf[4] = disc_bdaddr[1]; - hcibuf[5] = disc_bdaddr[2]; - hcibuf[6] = disc_bdaddr[3]; - hcibuf[7] = disc_bdaddr[4]; - hcibuf[8] = disc_bdaddr[5]; - hcibuf[9] = 0x00; // Switch role to master - - HCI_Command(hcibuf, 10); -} - -void BTD::hci_remote_name() { - hci_clear_flag(HCI_FLAG_REMOTE_NAME_COMPLETE); - hcibuf[0] = 0x19; // HCI OCF = 19 - hcibuf[1] = 0x01 << 2; // HCI OGF = 1 - hcibuf[2] = 0x0A; // parameter length = 10 - hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr - hcibuf[4] = disc_bdaddr[1]; - hcibuf[5] = disc_bdaddr[2]; - hcibuf[6] = disc_bdaddr[3]; - hcibuf[7] = disc_bdaddr[4]; - hcibuf[8] = disc_bdaddr[5]; - hcibuf[9] = 0x01; // Page Scan Repetition Mode - hcibuf[10] = 0x00; // Reserved - hcibuf[11] = 0x00; // Clock offset - low byte - hcibuf[12] = 0x00; // Clock offset - high byte - - HCI_Command(hcibuf, 13); -} - -void BTD::hci_set_local_name(const char* name) { - hcibuf[0] = 0x13; // HCI OCF = 13 - hcibuf[1] = 0x03 << 2; // HCI OGF = 3 - hcibuf[2] = strlen(name) + 1; // parameter length = the length of the string + end byte - uint8_t i; - for(i = 0; i < strlen(name); i++) - hcibuf[i + 3] = name[i]; - hcibuf[i + 3] = 0x00; // End of string - - HCI_Command(hcibuf, 4 + strlen(name)); -} - -void BTD::hci_inquiry() { - hci_clear_flag(HCI_FLAG_DEVICE_FOUND); - hcibuf[0] = 0x01; - hcibuf[1] = 0x01 << 2; // HCI OGF = 1 - hcibuf[2] = 0x05; // Parameter Total Length = 5 - hcibuf[3] = 0x33; // LAP: Genera/Unlimited Inquiry Access Code (GIAC = 0x9E8B33) - see https://www.bluetooth.org/Technical/AssignedNumbers/baseband.htm - hcibuf[4] = 0x8B; - hcibuf[5] = 0x9E; - hcibuf[6] = 0x30; // Inquiry time = 61.44 sec (maximum) - hcibuf[7] = 0x0A; // 10 number of responses - - HCI_Command(hcibuf, 8); -} - -void BTD::hci_inquiry_cancel() { - hcibuf[0] = 0x02; - hcibuf[1] = 0x01 << 2; // HCI OGF = 1 - hcibuf[2] = 0x00; // Parameter Total Length = 0 - - HCI_Command(hcibuf, 3); -} - -void BTD::hci_connect() { - hci_connect(disc_bdaddr); // Use last discovered device -} - -void BTD::hci_connect(uint8_t *bdaddr) { - hci_clear_flag(HCI_FLAG_CONNECT_COMPLETE | HCI_FLAG_CONNECT_EVENT); - hcibuf[0] = 0x05; - hcibuf[1] = 0x01 << 2; // HCI OGF = 1 - hcibuf[2] = 0x0D; // parameter Total Length = 13 - hcibuf[3] = bdaddr[0]; // 6 octet bdaddr (LSB) - hcibuf[4] = bdaddr[1]; - hcibuf[5] = bdaddr[2]; - hcibuf[6] = bdaddr[3]; - hcibuf[7] = bdaddr[4]; - hcibuf[8] = bdaddr[5]; - hcibuf[9] = 0x18; // DM1 or DH1 may be used - hcibuf[10] = 0xCC; // DM3, DH3, DM5, DH5 may be used - hcibuf[11] = 0x01; // Page repetition mode R1 - hcibuf[12] = 0x00; // Reserved - hcibuf[13] = 0x00; // Clock offset - hcibuf[14] = 0x00; // Invalid clock offset - hcibuf[15] = 0x00; // Do not allow role switch - - HCI_Command(hcibuf, 16); -} - -void BTD::hci_pin_code_request_reply() { - hcibuf[0] = 0x0D; // HCI OCF = 0D - hcibuf[1] = 0x01 << 2; // HCI OGF = 1 - hcibuf[2] = 0x17; // parameter length 23 - hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr - hcibuf[4] = disc_bdaddr[1]; - hcibuf[5] = disc_bdaddr[2]; - hcibuf[6] = disc_bdaddr[3]; - hcibuf[7] = disc_bdaddr[4]; - hcibuf[8] = disc_bdaddr[5]; - if(pairWithWii) { - hcibuf[9] = 6; // Pin length is the length of the Bluetooth address - if(pairWiiUsingSync) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nParing with Wii controller via SYNC"), 0x80); -#endif - for(uint8_t i = 0; i < 6; i++) - hcibuf[10 + i] = my_bdaddr[i]; // The pin is the Bluetooth dongles Bluetooth address backwards - } else { - for(uint8_t i = 0; i < 6; i++) - hcibuf[10 + i] = disc_bdaddr[i]; // The pin is the Wiimote's Bluetooth address backwards - } - for(uint8_t i = 16; i < 26; i++) - hcibuf[i] = 0x00; // The rest should be 0 - } else { - hcibuf[9] = strlen(btdPin); // Length of pin - uint8_t i; - for(i = 0; i < strlen(btdPin); i++) // The maximum size of the pin is 16 - hcibuf[i + 10] = btdPin[i]; - for(; i < 16; i++) - hcibuf[i + 10] = 0x00; // The rest should be 0 - } - - HCI_Command(hcibuf, 26); -} - -void BTD::hci_pin_code_negative_request_reply() { - hcibuf[0] = 0x0E; // HCI OCF = 0E - hcibuf[1] = 0x01 << 2; // HCI OGF = 1 - hcibuf[2] = 0x06; // parameter length 6 - hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr - hcibuf[4] = disc_bdaddr[1]; - hcibuf[5] = disc_bdaddr[2]; - hcibuf[6] = disc_bdaddr[3]; - hcibuf[7] = disc_bdaddr[4]; - hcibuf[8] = disc_bdaddr[5]; - - HCI_Command(hcibuf, 9); -} - -void BTD::hci_link_key_request_negative_reply() { - hcibuf[0] = 0x0C; // HCI OCF = 0C - hcibuf[1] = 0x01 << 2; // HCI OGF = 1 - hcibuf[2] = 0x06; // parameter length 6 - hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr - hcibuf[4] = disc_bdaddr[1]; - hcibuf[5] = disc_bdaddr[2]; - hcibuf[6] = disc_bdaddr[3]; - hcibuf[7] = disc_bdaddr[4]; - hcibuf[8] = disc_bdaddr[5]; - - HCI_Command(hcibuf, 9); -} - -void BTD::hci_authentication_request() { - hcibuf[0] = 0x11; // HCI OCF = 11 - hcibuf[1] = 0x01 << 2; // HCI OGF = 1 - hcibuf[2] = 0x02; // parameter length = 2 - hcibuf[3] = (uint8_t)(hci_handle & 0xFF); //connection handle - low byte - hcibuf[4] = (uint8_t)((hci_handle >> 8) & 0x0F); //connection handle - high byte - - HCI_Command(hcibuf, 5); -} - -void BTD::hci_disconnect(uint16_t handle) { // This is called by the different services - hci_clear_flag(HCI_FLAG_DISCONNECT_COMPLETE); - hcibuf[0] = 0x06; // HCI OCF = 6 - hcibuf[1] = 0x01 << 2; // HCI OGF = 1 - hcibuf[2] = 0x03; // parameter length = 3 - hcibuf[3] = (uint8_t)(handle & 0xFF); //connection handle - low byte - hcibuf[4] = (uint8_t)((handle >> 8) & 0x0F); //connection handle - high byte - hcibuf[5] = 0x13; // reason - - HCI_Command(hcibuf, 6); -} - -void BTD::hci_write_class_of_device() { // See http://bluetooth-pentest.narod.ru/software/bluetooth_class_of_device-service_generator.html - hcibuf[0] = 0x24; // HCI OCF = 24 - hcibuf[1] = 0x03 << 2; // HCI OGF = 3 - hcibuf[2] = 0x03; // parameter length = 3 - hcibuf[3] = 0x04; // Robot - hcibuf[4] = 0x08; // Toy - hcibuf[5] = 0x00; - - HCI_Command(hcibuf, 6); -} -/******************************************************************* - * * - * HCI ACL Data Packet * - * * - * buf[0] buf[1] buf[2] buf[3] - * 0 4 8 11 12 16 24 31 MSB - * .-+-+-+-+-+-+-+-|-+-+-+-|-+-|-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-. - * | HCI Handle |PB |BC | Data Total Length | HCI ACL Data Packet - * .-+-+-+-+-+-+-+-|-+-+-+-|-+-|-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-. - * - * buf[4] buf[5] buf[6] buf[7] - * 0 8 16 31 MSB - * .-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-. - * | Length | Channel ID | Basic L2CAP header - * .-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-. - * - * buf[8] buf[9] buf[10] buf[11] - * 0 8 16 31 MSB - * .-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-. - * | Code | Identifier | Length | Control frame (C-frame) - * .-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-. (signaling packet format) - */ -/************************************************************/ -/* L2CAP Commands */ - -/************************************************************/ -void BTD::L2CAP_Command(uint16_t handle, uint8_t* data, uint8_t nbytes, uint8_t channelLow, uint8_t channelHigh) { - uint8_t buf[8 + nbytes]; - buf[0] = (uint8_t)(handle & 0xff); // HCI handle with PB,BC flag - buf[1] = (uint8_t)(((handle >> 8) & 0x0f) | 0x20); - buf[2] = (uint8_t)((4 + nbytes) & 0xff); // HCI ACL total data length - buf[3] = (uint8_t)((4 + nbytes) >> 8); - buf[4] = (uint8_t)(nbytes & 0xff); // L2CAP header: Length - buf[5] = (uint8_t)(nbytes >> 8); - buf[6] = channelLow; - buf[7] = channelHigh; - - for(uint16_t i = 0; i < nbytes; i++) // L2CAP C-frame - buf[8 + i] = data[i]; - - uint8_t rcode = pUsb->outTransfer(bAddress, epInfo[ BTD_DATAOUT_PIPE ].epAddr, (8 + nbytes), buf); - if(rcode) { - delay(100); // This small delay prevents it from overflowing if it fails -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nError sending L2CAP message: 0x"), 0x80); - D_PrintHex (rcode, 0x80); - Notify(PSTR(" - Channel ID: "), 0x80); - D_PrintHex (channelHigh, 0x80); - Notify(PSTR(" "), 0x80); - D_PrintHex (channelLow, 0x80); -#endif - } -} - -void BTD::l2cap_connection_request(uint16_t handle, uint8_t rxid, uint8_t* scid, uint16_t psm) { - l2capoutbuf[0] = L2CAP_CMD_CONNECTION_REQUEST; // Code - l2capoutbuf[1] = rxid; // Identifier - l2capoutbuf[2] = 0x04; // Length - l2capoutbuf[3] = 0x00; - l2capoutbuf[4] = (uint8_t)(psm & 0xff); // PSM - l2capoutbuf[5] = (uint8_t)(psm >> 8); - l2capoutbuf[6] = scid[0]; // Source CID - l2capoutbuf[7] = scid[1]; - - L2CAP_Command(handle, l2capoutbuf, 8); -} - -void BTD::l2cap_connection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid, uint8_t result) { - l2capoutbuf[0] = L2CAP_CMD_CONNECTION_RESPONSE; // Code - l2capoutbuf[1] = rxid; // Identifier - l2capoutbuf[2] = 0x08; // Length - l2capoutbuf[3] = 0x00; - l2capoutbuf[4] = dcid[0]; // Destination CID - l2capoutbuf[5] = dcid[1]; - l2capoutbuf[6] = scid[0]; // Source CID - l2capoutbuf[7] = scid[1]; - l2capoutbuf[8] = result; // Result: Pending or Success - l2capoutbuf[9] = 0x00; - l2capoutbuf[10] = 0x00; // No further information - l2capoutbuf[11] = 0x00; - - L2CAP_Command(handle, l2capoutbuf, 12); -} - -void BTD::l2cap_config_request(uint16_t handle, uint8_t rxid, uint8_t* dcid) { - l2capoutbuf[0] = L2CAP_CMD_CONFIG_REQUEST; // Code - l2capoutbuf[1] = rxid; // Identifier - l2capoutbuf[2] = 0x08; // Length - l2capoutbuf[3] = 0x00; - l2capoutbuf[4] = dcid[0]; // Destination CID - l2capoutbuf[5] = dcid[1]; - l2capoutbuf[6] = 0x00; // Flags - l2capoutbuf[7] = 0x00; - l2capoutbuf[8] = 0x01; // Config Opt: type = MTU (Maximum Transmission Unit) - Hint - l2capoutbuf[9] = 0x02; // Config Opt: length - l2capoutbuf[10] = 0xFF; // MTU - l2capoutbuf[11] = 0xFF; - - L2CAP_Command(handle, l2capoutbuf, 12); -} - -void BTD::l2cap_config_response(uint16_t handle, uint8_t rxid, uint8_t* scid) { - l2capoutbuf[0] = L2CAP_CMD_CONFIG_RESPONSE; // Code - l2capoutbuf[1] = rxid; // Identifier - l2capoutbuf[2] = 0x0A; // Length - l2capoutbuf[3] = 0x00; - l2capoutbuf[4] = scid[0]; // Source CID - l2capoutbuf[5] = scid[1]; - l2capoutbuf[6] = 0x00; // Flag - l2capoutbuf[7] = 0x00; - l2capoutbuf[8] = 0x00; // Result - l2capoutbuf[9] = 0x00; - l2capoutbuf[10] = 0x01; // Config - l2capoutbuf[11] = 0x02; - l2capoutbuf[12] = 0xA0; - l2capoutbuf[13] = 0x02; - - L2CAP_Command(handle, l2capoutbuf, 14); -} - -void BTD::l2cap_disconnection_request(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid) { - l2capoutbuf[0] = L2CAP_CMD_DISCONNECT_REQUEST; // Code - l2capoutbuf[1] = rxid; // Identifier - l2capoutbuf[2] = 0x04; // Length - l2capoutbuf[3] = 0x00; - l2capoutbuf[4] = dcid[0]; - l2capoutbuf[5] = dcid[1]; - l2capoutbuf[6] = scid[0]; - l2capoutbuf[7] = scid[1]; - - L2CAP_Command(handle, l2capoutbuf, 8); -} - -void BTD::l2cap_disconnection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid) { - l2capoutbuf[0] = L2CAP_CMD_DISCONNECT_RESPONSE; // Code - l2capoutbuf[1] = rxid; // Identifier - l2capoutbuf[2] = 0x04; // Length - l2capoutbuf[3] = 0x00; - l2capoutbuf[4] = dcid[0]; - l2capoutbuf[5] = dcid[1]; - l2capoutbuf[6] = scid[0]; - l2capoutbuf[7] = scid[1]; - - L2CAP_Command(handle, l2capoutbuf, 8); -} - -void BTD::l2cap_information_response(uint16_t handle, uint8_t rxid, uint8_t infoTypeLow, uint8_t infoTypeHigh) { - l2capoutbuf[0] = L2CAP_CMD_INFORMATION_RESPONSE; // Code - l2capoutbuf[1] = rxid; // Identifier - l2capoutbuf[2] = 0x08; // Length - l2capoutbuf[3] = 0x00; - l2capoutbuf[4] = infoTypeLow; - l2capoutbuf[5] = infoTypeHigh; - l2capoutbuf[6] = 0x00; // Result = success - l2capoutbuf[7] = 0x00; // Result = success - l2capoutbuf[8] = 0x00; - l2capoutbuf[9] = 0x00; - l2capoutbuf[10] = 0x00; - l2capoutbuf[11] = 0x00; - - L2CAP_Command(handle, l2capoutbuf, 12); -} - -/* PS3 Commands - only set Bluetooth address is implemented in this library */ -void BTD::setBdaddr(uint8_t* bdaddr) { - /* Set the internal Bluetooth address */ - uint8_t buf[8]; - buf[0] = 0x01; - buf[1] = 0x00; - - for(uint8_t i = 0; i < 6; i++) - buf[i + 2] = bdaddr[5 - i]; // Copy into buffer, has to be written reversed, so it is MSB first - - // bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF5), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data - pUsb->ctrlReq(bAddress, epInfo[BTD_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL); -} - -void BTD::setMoveBdaddr(uint8_t* bdaddr) { - /* Set the internal Bluetooth address */ - uint8_t buf[11]; - buf[0] = 0x05; - buf[7] = 0x10; - buf[8] = 0x01; - buf[9] = 0x02; - buf[10] = 0x12; - - for(uint8_t i = 0; i < 6; i++) - buf[i + 1] = bdaddr[i]; - - // bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x05), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data - pUsb->ctrlReq(bAddress, epInfo[BTD_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x05, 0x03, 0x00, 11, 11, buf, NULL); -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/BTD.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/BTD.h deleted file mode 100755 index 6549c30c98..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/BTD.h +++ /dev/null @@ -1,620 +0,0 @@ -/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. - - This software may be distributed and modified under the terms of the GNU - General Public License version 2 (GPL2) as published by the Free Software - Foundation and appearing in the file GPL2.TXT included in the packaging of - this file. Please note that GPL2 Section 2[b] requires that all works based - on this software must also be made publicly available under the terms of - the GPL2 ("Copyleft"). - - Contact information - ------------------- - - Kristian Lauszus, TKJ Electronics - Web : http://www.tkjelectronics.com - e-mail : kristianl@tkjelectronics.com - */ - -#ifndef _btd_h_ -#define _btd_h_ - -#include "Usb.h" -#include "hid.h" - -//PID and VID of the Sony PS3 devices -#define PS3_VID 0x054C // Sony Corporation -#define PS3_PID 0x0268 // PS3 Controller DualShock 3 -#define PS3NAVIGATION_PID 0x042F // Navigation controller -#define PS3MOVE_PID 0x03D5 // Motion controller - -#define IOGEAR_GBU521_VID 0x0A5C // The IOGEAR GBU521 dongle does not presents itself correctly, so we have to check for it manually -#define IOGEAR_GBU521_PID 0x21E8 - -/* Bluetooth dongle data taken from descriptors */ -#define BULK_MAXPKTSIZE 64 // Max size for ACL data - -// Used in control endpoint header for HCI Commands -#define bmREQ_HCI_OUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE - -/* Bluetooth HCI states for hci_task() */ -#define HCI_INIT_STATE 0 -#define HCI_RESET_STATE 1 -#define HCI_CLASS_STATE 2 -#define HCI_BDADDR_STATE 3 -#define HCI_LOCAL_VERSION_STATE 4 -#define HCI_SET_NAME_STATE 5 -#define HCI_CHECK_DEVICE_SERVICE 6 - -#define HCI_INQUIRY_STATE 7 // These three states are only used if it should pair and connect to a device -#define HCI_CONNECT_DEVICE_STATE 8 -#define HCI_CONNECTED_DEVICE_STATE 9 - -#define HCI_SCANNING_STATE 10 -#define HCI_CONNECT_IN_STATE 11 -#define HCI_REMOTE_NAME_STATE 12 -#define HCI_CONNECTED_STATE 13 -#define HCI_DISABLE_SCAN_STATE 14 -#define HCI_DONE_STATE 15 -#define HCI_DISCONNECT_STATE 16 - -/* HCI event flags*/ -#define HCI_FLAG_CMD_COMPLETE (1UL << 0) -#define HCI_FLAG_CONNECT_COMPLETE (1UL << 1) -#define HCI_FLAG_DISCONNECT_COMPLETE (1UL << 2) -#define HCI_FLAG_REMOTE_NAME_COMPLETE (1UL << 3) -#define HCI_FLAG_INCOMING_REQUEST (1UL << 4) -#define HCI_FLAG_READ_BDADDR (1UL << 5) -#define HCI_FLAG_READ_VERSION (1UL << 6) -#define HCI_FLAG_DEVICE_FOUND (1UL << 7) -#define HCI_FLAG_CONNECT_EVENT (1UL << 8) - -/* Macros for HCI event flag tests */ -#define hci_check_flag(flag) (hci_event_flag & (flag)) -#define hci_set_flag(flag) (hci_event_flag |= (flag)) -#define hci_clear_flag(flag) (hci_event_flag &= ~(flag)) - -/* HCI Events managed */ -#define EV_INQUIRY_COMPLETE 0x01 -#define EV_INQUIRY_RESULT 0x02 -#define EV_CONNECT_COMPLETE 0x03 -#define EV_INCOMING_CONNECT 0x04 -#define EV_DISCONNECT_COMPLETE 0x05 -#define EV_AUTHENTICATION_COMPLETE 0x06 -#define EV_REMOTE_NAME_COMPLETE 0x07 -#define EV_ENCRYPTION_CHANGE 0x08 -#define EV_CHANGE_CONNECTION_LINK 0x09 -#define EV_ROLE_CHANGED 0x12 -#define EV_NUM_COMPLETE_PKT 0x13 -#define EV_PIN_CODE_REQUEST 0x16 -#define EV_LINK_KEY_REQUEST 0x17 -#define EV_LINK_KEY_NOTIFICATION 0x18 -#define EV_DATA_BUFFER_OVERFLOW 0x1A -#define EV_MAX_SLOTS_CHANGE 0x1B -#define EV_READ_REMOTE_VERSION_INFORMATION_COMPLETE 0x0C -#define EV_QOS_SETUP_COMPLETE 0x0D -#define EV_COMMAND_COMPLETE 0x0E -#define EV_COMMAND_STATUS 0x0F -#define EV_LOOPBACK_COMMAND 0x19 -#define EV_PAGE_SCAN_REP_MODE 0x20 - -/* Bluetooth states for the different Bluetooth drivers */ -#define L2CAP_WAIT 0 -#define L2CAP_DONE 1 - -/* Used for HID Control channel */ -#define L2CAP_CONTROL_CONNECT_REQUEST 2 -#define L2CAP_CONTROL_CONFIG_REQUEST 3 -#define L2CAP_CONTROL_SUCCESS 4 -#define L2CAP_CONTROL_DISCONNECT 5 - -/* Used for HID Interrupt channel */ -#define L2CAP_INTERRUPT_SETUP 6 -#define L2CAP_INTERRUPT_CONNECT_REQUEST 7 -#define L2CAP_INTERRUPT_CONFIG_REQUEST 8 -#define L2CAP_INTERRUPT_DISCONNECT 9 - -/* Used for SDP channel */ -#define L2CAP_SDP_WAIT 10 -#define L2CAP_SDP_SUCCESS 11 - -/* Used for RFCOMM channel */ -#define L2CAP_RFCOMM_WAIT 12 -#define L2CAP_RFCOMM_SUCCESS 13 - -#define L2CAP_DISCONNECT_RESPONSE 14 // Used for both SDP and RFCOMM channel - -/* Bluetooth states used by some drivers */ -#define TURN_ON_LED 17 -#define PS3_ENABLE_SIXAXIS 18 -#define WII_CHECK_MOTION_PLUS_STATE 19 -#define WII_CHECK_EXTENSION_STATE 20 -#define WII_INIT_MOTION_PLUS_STATE 21 - -/* L2CAP event flags for HID Control channel */ -#define L2CAP_FLAG_CONNECTION_CONTROL_REQUEST (1UL << 0) -#define L2CAP_FLAG_CONFIG_CONTROL_SUCCESS (1UL << 1) -#define L2CAP_FLAG_CONTROL_CONNECTED (1UL << 2) -#define L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE (1UL << 3) - -/* L2CAP event flags for HID Interrupt channel */ -#define L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST (1UL << 4) -#define L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS (1UL << 5) -#define L2CAP_FLAG_INTERRUPT_CONNECTED (1UL << 6) -#define L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE (1UL << 7) - -/* L2CAP event flags for SDP channel */ -#define L2CAP_FLAG_CONNECTION_SDP_REQUEST (1UL << 8) -#define L2CAP_FLAG_CONFIG_SDP_SUCCESS (1UL << 9) -#define L2CAP_FLAG_DISCONNECT_SDP_REQUEST (1UL << 10) - -/* L2CAP event flags for RFCOMM channel */ -#define L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST (1UL << 11) -#define L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS (1UL << 12) -#define L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST (1UL << 13) - -#define L2CAP_FLAG_DISCONNECT_RESPONSE (1UL << 14) - -/* Macros for L2CAP event flag tests */ -#define l2cap_check_flag(flag) (l2cap_event_flag & (flag)) -#define l2cap_set_flag(flag) (l2cap_event_flag |= (flag)) -#define l2cap_clear_flag(flag) (l2cap_event_flag &= ~(flag)) - -/* L2CAP signaling commands */ -#define L2CAP_CMD_COMMAND_REJECT 0x01 -#define L2CAP_CMD_CONNECTION_REQUEST 0x02 -#define L2CAP_CMD_CONNECTION_RESPONSE 0x03 -#define L2CAP_CMD_CONFIG_REQUEST 0x04 -#define L2CAP_CMD_CONFIG_RESPONSE 0x05 -#define L2CAP_CMD_DISCONNECT_REQUEST 0x06 -#define L2CAP_CMD_DISCONNECT_RESPONSE 0x07 -#define L2CAP_CMD_INFORMATION_REQUEST 0x0A -#define L2CAP_CMD_INFORMATION_RESPONSE 0x0B - -// Used For Connection Response - Remember to Include High Byte -#define PENDING 0x01 -#define SUCCESSFUL 0x00 - -/* Bluetooth L2CAP PSM - see http://www.bluetooth.org/Technical/AssignedNumbers/logical_link.htm */ -#define SDP_PSM 0x01 // Service Discovery Protocol PSM Value -#define RFCOMM_PSM 0x03 // RFCOMM PSM Value -#define HID_CTRL_PSM 0x11 // HID_Control PSM Value -#define HID_INTR_PSM 0x13 // HID_Interrupt PSM Value - -// Used to determine if it is a Bluetooth dongle -#define WI_SUBCLASS_RF 0x01 // RF Controller -#define WI_PROTOCOL_BT 0x01 // Bluetooth Programming Interface - -#define BTD_MAX_ENDPOINTS 4 -#define BTD_NUM_SERVICES 4 // Max number of Bluetooth services - if you need more than 4 simply increase this number - -#define PAIR 1 - -class BluetoothService; - -/** - * The Bluetooth Dongle class will take care of all the USB communication - * and then pass the data to the BluetoothService classes. - */ -class BTD : public USBDeviceConfig, public UsbConfigXtracter { -public: - /** - * Constructor for the BTD class. - * @param p Pointer to USB class instance. - */ - BTD(USB *p); - - /** @name USBDeviceConfig implementation */ - /** - * Address assignment and basic initialization is done here. - * @param parent Hub number. - * @param port Port number on the hub. - * @param lowspeed Speed of the device. - * @return 0 on success. - */ - uint8_t ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed); - /** - * Initialize the Bluetooth dongle. - * @param parent Hub number. - * @param port Port number on the hub. - * @param lowspeed Speed of the device. - * @return 0 on success. - */ - uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); - /** - * Release the USB device. - * @return 0 on success. - */ - uint8_t Release(); - /** - * Poll the USB Input endpoints and run the state machines. - * @return 0 on success. - */ - uint8_t Poll(); - - /** - * Get the device address. - * @return The device address. - */ - virtual uint8_t GetAddress() { - return bAddress; - }; - - /** - * Used to check if the dongle has been initialized. - * @return True if it's ready. - */ - virtual bool isReady() { - return bPollEnable; - }; - - /** - * Used by the USB core to check what this driver support. - * @param klass The device's USB class. - * @return Returns true if the device's USB class matches this driver. - */ - virtual bool DEVCLASSOK(uint8_t klass) { - return (klass == USB_CLASS_WIRELESS_CTRL); - }; - - /** - * Used by the USB core to check what this driver support. - * Used to set the Bluetooth address into the PS3 controllers. - * @param vid The device's VID. - * @param pid The device's PID. - * @return Returns true if the device's VID and PID matches this driver. - */ - virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) { - if(vid == IOGEAR_GBU521_VID && pid == IOGEAR_GBU521_PID) - return true; - if(my_bdaddr[0] != 0x00 || my_bdaddr[1] != 0x00 || my_bdaddr[2] != 0x00 || my_bdaddr[3] != 0x00 || my_bdaddr[4] != 0x00 || my_bdaddr[5] != 0x00) { // Check if Bluetooth address is set - if(vid == PS3_VID && (pid == PS3_PID || pid == PS3NAVIGATION_PID || pid == PS3MOVE_PID)) - return true; - } - return false; - }; - /**@}*/ - - /** @name UsbConfigXtracter implementation */ - /** - * UsbConfigXtracter implementation, used to extract endpoint information. - * @param conf Configuration value. - * @param iface Interface number. - * @param alt Alternate setting. - * @param proto Interface Protocol. - * @param ep Endpoint Descriptor. - */ - void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); - /**@}*/ - - /** Disconnects both the L2CAP Channel and the HCI Connection for all Bluetooth services. */ - void disconnect(); - - /** - * Register Bluetooth dongle members/services. - * @param pService Pointer to BluetoothService class instance. - * @return The service ID on success or -1 on fail. - */ - int8_t registerBluetoothService(BluetoothService *pService) { - for(uint8_t i = 0; i < BTD_NUM_SERVICES; i++) { - if(!btService[i]) { - btService[i] = pService; - return i; // Return ID - } - } - return -1; // Error registering BluetoothService - }; - - /** @name HCI Commands */ - /** - * Used to send a HCI Command. - * @param data Data to send. - * @param nbytes Number of bytes to send. - */ - void HCI_Command(uint8_t* data, uint16_t nbytes); - /** Reset the Bluetooth dongle. */ - void hci_reset(); - /** Read the Bluetooth address of the dongle. */ - void hci_read_bdaddr(); - /** Read the HCI Version of the Bluetooth dongle. */ - void hci_read_local_version_information(); - /** - * Set the local name of the Bluetooth dongle. - * @param name Desired name. - */ - void hci_set_local_name(const char* name); - /** Enable visibility to other Bluetooth devices. */ - void hci_write_scan_enable(); - /** Disable visibility to other Bluetooth devices. */ - void hci_write_scan_disable(); - /** Read the remote devices name. */ - void hci_remote_name(); - /** Accept the connection with the Bluetooth device. */ - void hci_accept_connection(); - /** - * Disconnect the HCI connection. - * @param handle The HCI Handle for the connection. - */ - void hci_disconnect(uint16_t handle); - /** - * Respond with the pin for the connection. - * The pin is automatically set for the Wii library, - * but can be customized for the SPP library. - */ - void hci_pin_code_request_reply(); - /** Respons when no pin was set. */ - void hci_pin_code_negative_request_reply(); - /** - * Command is used to reply to a Link Key Request event from the BR/EDR Controller - * if the Host does not have a stored Link Key for the connection. - */ - void hci_link_key_request_negative_reply(); - /** Used to try to authenticate with the remote device. */ - void hci_authentication_request(); - /** Start a HCI inquiry. */ - void hci_inquiry(); - /** Cancel a HCI inquiry. */ - void hci_inquiry_cancel(); - /** Connect to last device communicated with. */ - void hci_connect(); - /** - * Connect to device. - * @param bdaddr Bluetooth address of the device. - */ - void hci_connect(uint8_t *bdaddr); - /** Used to a set the class of the device. */ - void hci_write_class_of_device(); - /**@}*/ - - /** @name L2CAP Commands */ - /** - * Used to send L2CAP Commands. - * @param handle HCI Handle. - * @param data Data to send. - * @param nbytes Number of bytes to send. - * @param channelLow,channelHigh Low and high byte of channel to send to. - * If argument is omitted then the Standard L2CAP header: Channel ID (0x01) for ACL-U will be used. - */ - void L2CAP_Command(uint16_t handle, uint8_t* data, uint8_t nbytes, uint8_t channelLow = 0x01, uint8_t channelHigh = 0x00); - /** - * L2CAP Connection Request. - * @param handle HCI handle. - * @param rxid Identifier. - * @param scid Source Channel Identifier. - * @param psm Protocol/Service Multiplexer - see: https://www.bluetooth.org/Technical/AssignedNumbers/logical_link.htm. - */ - void l2cap_connection_request(uint16_t handle, uint8_t rxid, uint8_t* scid, uint16_t psm); - /** - * L2CAP Connection Response. - * @param handle HCI handle. - * @param rxid Identifier. - * @param dcid Destination Channel Identifier. - * @param scid Source Channel Identifier. - * @param result Result - First send ::PENDING and then ::SUCCESSFUL. - */ - void l2cap_connection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid, uint8_t result); - /** - * L2CAP Config Request. - * @param handle HCI Handle. - * @param rxid Identifier. - * @param dcid Destination Channel Identifier. - */ - void l2cap_config_request(uint16_t handle, uint8_t rxid, uint8_t* dcid); - /** - * L2CAP Config Response. - * @param handle HCI Handle. - * @param rxid Identifier. - * @param scid Source Channel Identifier. - */ - void l2cap_config_response(uint16_t handle, uint8_t rxid, uint8_t* scid); - /** - * L2CAP Disconnection Request. - * @param handle HCI Handle. - * @param rxid Identifier. - * @param dcid Device Channel Identifier. - * @param scid Source Channel Identifier. - */ - void l2cap_disconnection_request(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid); - /** - * L2CAP Disconnection Response. - * @param handle HCI Handle. - * @param rxid Identifier. - * @param dcid Device Channel Identifier. - * @param scid Source Channel Identifier. - */ - void l2cap_disconnection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid); - /** - * L2CAP Information Response. - * @param handle HCI Handle. - * @param rxid Identifier. - * @param infoTypeLow,infoTypeHigh Infotype. - */ - void l2cap_information_response(uint16_t handle, uint8_t rxid, uint8_t infoTypeLow, uint8_t infoTypeHigh); - /**@}*/ - - /** Use this to see if it is waiting for a incoming connection. */ - bool watingForConnection; - /** This is used by the service to know when to store the device information. */ - bool l2capConnectionClaimed; - /** This is used by the SPP library to claim the current SDP incoming request. */ - bool sdpConnectionClaimed; - /** This is used by the SPP library to claim the current RFCOMM incoming request. */ - bool rfcommConnectionClaimed; - - /** The name you wish to make the dongle show up as. It is set automatically by the SPP library. */ - const char* btdName; - /** The pin you wish to make the dongle use for authentication. It is set automatically by the SPP and BTHID library. */ - const char* btdPin; - - /** The bluetooth dongles Bluetooth address. */ - uint8_t my_bdaddr[6]; - /** HCI handle for the last connection. */ - uint16_t hci_handle; - /** Last incoming devices Bluetooth address. */ - uint8_t disc_bdaddr[6]; - /** First 30 chars of last remote name. */ - char remote_name[30]; - /** - * The supported HCI Version read from the Bluetooth dongle. - * Used by the PS3BT library to check the HCI Version of the Bluetooth dongle, - * it should be at least 3 to work properly with the library. - */ - uint8_t hci_version; - - /** Call this function to pair with a Wiimote */ - void pairWithWiimote() { - pairWithWii = true; - hci_state = HCI_CHECK_DEVICE_SERVICE; - }; - /** Used to only send the ACL data to the Wiimote. */ - bool connectToWii; - /** True if a Wiimote is connecting. */ - bool incomingWii; - /** True when it should pair with a Wiimote. */ - bool pairWithWii; - /** True if it's the new Wiimote with the Motion Plus Inside or a Wii U Pro Controller. */ - bool motionPlusInside; - /** True if it's a Wii U Pro Controller. */ - bool wiiUProController; - - /** Call this function to pair with a Wiimote */ - void pairWithHID() { - pairWithHIDDevice = true; - hci_state = HCI_CHECK_DEVICE_SERVICE; - }; - /** Used to only send the ACL data to the Wiimote. */ - bool connectToHIDDevice; - /** True if a Wiimote is connecting. */ - bool incomingHIDDevice; - /** True when it should pair with a device like a mouse or keyboard. */ - bool pairWithHIDDevice; - - /** - * Read the poll interval taken from the endpoint descriptors. - * @return The poll interval in ms. - */ - uint8_t readPollInterval() { - return pollInterval; - }; - -protected: - /** Pointer to USB class instance. */ - USB *pUsb; - /** Device address. */ - uint8_t bAddress; - /** Endpoint info structure. */ - EpInfo epInfo[BTD_MAX_ENDPOINTS]; - - /** Configuration number. */ - uint8_t bConfNum; - /** Total number of endpoints in the configuration. */ - uint8_t bNumEP; - /** Next poll time based on poll interval taken from the USB descriptor. */ - uint32_t qNextPollTime; - - /** Bluetooth dongle control endpoint. */ - static const uint8_t BTD_CONTROL_PIPE; - /** HCI event endpoint index. */ - static const uint8_t BTD_EVENT_PIPE; - /** ACL In endpoint index. */ - static const uint8_t BTD_DATAIN_PIPE; - /** ACL Out endpoint index. */ - static const uint8_t BTD_DATAOUT_PIPE; - - /** - * Used to print the USB Endpoint Descriptor. - * @param ep_ptr Pointer to USB Endpoint Descriptor. - */ - void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); - -private: - void Initialize(); // Set all variables, endpoint structs etc. to default values - BluetoothService *btService[BTD_NUM_SERVICES]; - - uint16_t PID, VID; // PID and VID of device connected - - uint8_t pollInterval; - bool bPollEnable; - - bool pairWiiUsingSync; // True if paring was done using the Wii SYNC button. - bool checkRemoteName; // Used to check remote device's name before connecting. - bool incomingPS4; // True if a PS4 controller is connecting - uint8_t classOfDevice[3]; // Class of device of last device - - /* Variables used by high level HCI task */ - uint8_t hci_state; // Current state of Bluetooth HCI connection - uint16_t hci_counter; // Counter used for Bluetooth HCI reset loops - uint16_t hci_num_reset_loops; // This value indicate how many times it should read before trying to reset - uint16_t hci_event_flag; // HCI flags of received Bluetooth events - uint8_t inquiry_counter; - - uint8_t hcibuf[BULK_MAXPKTSIZE]; // General purpose buffer for HCI data - uint8_t l2capinbuf[BULK_MAXPKTSIZE]; // General purpose buffer for L2CAP in data - uint8_t l2capoutbuf[14]; // General purpose buffer for L2CAP out data - - /* State machines */ - void HCI_event_task(); // Poll the HCI event pipe - void HCI_task(); // HCI state machine - void ACL_event_task(); // ACL input pipe - - /* Used to set the Bluetooth Address internally to the PS3 Controllers */ - void setBdaddr(uint8_t* BDADDR); - void setMoveBdaddr(uint8_t* BDADDR); -}; - -/** All Bluetooth services should inherit this class. */ -class BluetoothService { -public: - BluetoothService(BTD *p) : pBtd(p) { - if(pBtd) - pBtd->registerBluetoothService(this); // Register it as a Bluetooth service - }; - /** - * Used to pass acldata to the Bluetooth service. - * @param ACLData Pointer to the incoming acldata. - */ - virtual void ACLData(uint8_t* ACLData) = 0; - /** Used to run the different state machines in the Bluetooth service. */ - virtual void Run() = 0; - /** Used to reset the Bluetooth service. */ - virtual void Reset() = 0; - /** Used to disconnect both the L2CAP Channel and the HCI Connection for the Bluetooth service. */ - virtual void disconnect() = 0; - - /** - * Used to call your own function when the device is successfully initialized. - * @param funcOnInit Function to call. - */ - void attachOnInit(void (*funcOnInit)(void)) { - pFuncOnInit = funcOnInit; // TODO: This really belong in a class of it's own as it is repeated several times - }; - -protected: - /** - * Called when a device is successfully initialized. - * Use attachOnInit(void (*funcOnInit)(void)) to call your own function. - * This is useful for instance if you want to set the LEDs in a specific way. - */ - virtual void onInit() = 0; - - /** Used to check if the incoming L2CAP data matches the HCI Handle */ - bool checkHciHandle(uint8_t *buf, uint16_t handle) { - return (buf[0] == (handle & 0xFF)) && (buf[1] == ((handle >> 8) | 0x20)); - } - - /** Pointer to function called in onInit(). */ - void (*pFuncOnInit)(void); - - /** Pointer to BTD instance. */ - BTD *pBtd; - - /** The HCI Handle for the connection. */ - uint16_t hci_handle; - - /** L2CAP flags of received Bluetooth events. */ - uint32_t l2cap_event_flag; - - /** Identifier for L2CAP commands. */ - uint8_t identifier; -}; - -#endif diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/BTHID.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/BTHID.cpp deleted file mode 100644 index bfa9202c39..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/BTHID.cpp +++ /dev/null @@ -1,399 +0,0 @@ -/* Copyright (C) 2013 Kristian Lauszus, TKJ Electronics. All rights reserved. - - This software may be distributed and modified under the terms of the GNU - General Public License version 2 (GPL2) as published by the Free Software - Foundation and appearing in the file GPL2.TXT included in the packaging of - this file. Please note that GPL2 Section 2[b] requires that all works based - on this software must also be made publicly available under the terms of - the GPL2 ("Copyleft"). - - Contact information - ------------------- - - Kristian Lauszus, TKJ Electronics - Web : http://www.tkjelectronics.com - e-mail : kristianl@tkjelectronics.com - */ - -#include "BTHID.h" -// To enable serial debugging see "settings.h" -//#define EXTRADEBUG // Uncomment to get even more debugging data -//#define PRINTREPORT // Uncomment to print the report send by the HID device - -BTHID::BTHID(BTD *p, bool pair, const char *pin) : -BluetoothService(p), // Pointer to USB class instance - mandatory -protocolMode(HID_BOOT_PROTOCOL) { - for(uint8_t i = 0; i < NUM_PARSERS; i++) - pRptParser[i] = NULL; - - pBtd->pairWithHIDDevice = pair; - pBtd->btdPin = pin; - - /* Set device cid for the control and intterrupt channelse - LSB */ - control_dcid[0] = 0x70; // 0x0070 - control_dcid[1] = 0x00; - interrupt_dcid[0] = 0x71; // 0x0071 - interrupt_dcid[1] = 0x00; - - Reset(); -} - -void BTHID::Reset() { - connected = false; - activeConnection = false; - l2cap_event_flag = 0; // Reset flags - l2cap_state = L2CAP_WAIT; - ResetBTHID(); -} - -void BTHID::disconnect() { // Use this void to disconnect the device - // First the HID interrupt channel has to be disconnected, then the HID control channel and finally the HCI connection - pBtd->l2cap_disconnection_request(hci_handle, ++identifier, interrupt_scid, interrupt_dcid); - Reset(); - l2cap_state = L2CAP_INTERRUPT_DISCONNECT; -} - -void BTHID::ACLData(uint8_t* l2capinbuf) { - if(!pBtd->l2capConnectionClaimed && pBtd->incomingHIDDevice && !connected && !activeConnection) { - if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { - if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) { - pBtd->incomingHIDDevice = false; - pBtd->l2capConnectionClaimed = true; // Claim that the incoming connection belongs to this service - activeConnection = true; - hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection - l2cap_state = L2CAP_WAIT; - } - } - } - - if(checkHciHandle(l2capinbuf, hci_handle)) { // acl_handle_ok - if((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001U) { // l2cap_control - Channel ID for ACL-U - if(l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80); - D_PrintHex (l2capinbuf[13], 0x80); - Notify(PSTR(" "), 0x80); - D_PrintHex (l2capinbuf[12], 0x80); - Notify(PSTR(" "), 0x80); - D_PrintHex (l2capinbuf[17], 0x80); - Notify(PSTR(" "), 0x80); - D_PrintHex (l2capinbuf[16], 0x80); - Notify(PSTR(" "), 0x80); - D_PrintHex (l2capinbuf[15], 0x80); - Notify(PSTR(" "), 0x80); - D_PrintHex (l2capinbuf[14], 0x80); -#endif - } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_RESPONSE) { - if(((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) && ((l2capinbuf[18] | (l2capinbuf[19] << 8)) == SUCCESSFUL)) { // Success - if(l2capinbuf[14] == control_dcid[0] && l2capinbuf[15] == control_dcid[1]) { - //Notify(PSTR("\r\nHID Control Connection Complete"), 0x80); - identifier = l2capinbuf[9]; - control_scid[0] = l2capinbuf[12]; - control_scid[1] = l2capinbuf[13]; - l2cap_set_flag(L2CAP_FLAG_CONTROL_CONNECTED); - } else if(l2capinbuf[14] == interrupt_dcid[0] && l2capinbuf[15] == interrupt_dcid[1]) { - //Notify(PSTR("\r\nHID Interrupt Connection Complete"), 0x80); - identifier = l2capinbuf[9]; - interrupt_scid[0] = l2capinbuf[12]; - interrupt_scid[1] = l2capinbuf[13]; - l2cap_set_flag(L2CAP_FLAG_INTERRUPT_CONNECTED); - } - } - } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { -#ifdef EXTRADEBUG - Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80); - D_PrintHex (l2capinbuf[13], 0x80); - Notify(PSTR(" "), 0x80); - D_PrintHex (l2capinbuf[12], 0x80); - Notify(PSTR(" SCID: "), 0x80); - D_PrintHex (l2capinbuf[15], 0x80); - Notify(PSTR(" "), 0x80); - D_PrintHex (l2capinbuf[14], 0x80); - Notify(PSTR(" Identifier: "), 0x80); - D_PrintHex (l2capinbuf[9], 0x80); -#endif - if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) { - identifier = l2capinbuf[9]; - control_scid[0] = l2capinbuf[14]; - control_scid[1] = l2capinbuf[15]; - l2cap_set_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST); - } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_INTR_PSM) { - identifier = l2capinbuf[9]; - interrupt_scid[0] = l2capinbuf[14]; - interrupt_scid[1] = l2capinbuf[15]; - l2cap_set_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST); - } - } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) { - if((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success - if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { - //Notify(PSTR("\r\nHID Control Configuration Complete"), 0x80); - identifier = l2capinbuf[9]; - l2cap_set_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS); - } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { - //Notify(PSTR("\r\nHID Interrupt Configuration Complete"), 0x80); - identifier = l2capinbuf[9]; - l2cap_set_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS); - } - } - } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) { - if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { - //Notify(PSTR("\r\nHID Control Configuration Request"), 0x80); - pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], control_scid); - } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { - //Notify(PSTR("\r\nHID Interrupt Configuration Request"), 0x80); - pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], interrupt_scid); - } - } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) { - if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nDisconnect Request: Control Channel"), 0x80); -#endif - identifier = l2capinbuf[9]; - pBtd->l2cap_disconnection_response(hci_handle, identifier, control_dcid, control_scid); - Reset(); - } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nDisconnect Request: Interrupt Channel"), 0x80); -#endif - identifier = l2capinbuf[9]; - pBtd->l2cap_disconnection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid); - Reset(); - } - } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) { - if(l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) { - //Notify(PSTR("\r\nDisconnect Response: Control Channel"), 0x80); - identifier = l2capinbuf[9]; - l2cap_set_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE); - } else if(l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) { - //Notify(PSTR("\r\nDisconnect Response: Interrupt Channel"), 0x80); - identifier = l2capinbuf[9]; - l2cap_set_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE); - } - } -#ifdef EXTRADEBUG - else { - identifier = l2capinbuf[9]; - Notify(PSTR("\r\nL2CAP Unknown Signaling Command: "), 0x80); - D_PrintHex (l2capinbuf[8], 0x80); - } -#endif - } else if(l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt -#ifdef PRINTREPORT - Notify(PSTR("\r\nL2CAP Interrupt: "), 0x80); - for(uint16_t i = 0; i < ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); i++) { - D_PrintHex (l2capinbuf[i + 8], 0x80); - Notify(PSTR(" "), 0x80); - } -#endif - if(l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT - uint16_t length = ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); - ParseBTHIDData((uint8_t)(length - 1), &l2capinbuf[9]); - - switch(l2capinbuf[9]) { - case 0x01: // Keyboard or Joystick events - if(pRptParser[KEYBOARD_PARSER_ID]) - pRptParser[KEYBOARD_PARSER_ID]->Parse(reinterpret_cast(this), 0, (uint8_t)(length - 2), &l2capinbuf[10]); // Use reinterpret_cast again to extract the instance - break; - - case 0x02: // Mouse events - if(pRptParser[MOUSE_PARSER_ID]) - pRptParser[MOUSE_PARSER_ID]->Parse(reinterpret_cast(this), 0, (uint8_t)(length - 2), &l2capinbuf[10]); // Use reinterpret_cast again to extract the instance - break; -#ifdef EXTRADEBUG - default: - Notify(PSTR("\r\nUnknown Report type: "), 0x80); - D_PrintHex (l2capinbuf[9], 0x80); - break; -#endif - } - } - } else if(l2capinbuf[6] == control_dcid[0] && l2capinbuf[7] == control_dcid[1]) { // l2cap_control -#ifdef PRINTREPORT - Notify(PSTR("\r\nL2CAP Control: "), 0x80); - for(uint16_t i = 0; i < ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); i++) { - D_PrintHex (l2capinbuf[i + 8], 0x80); - Notify(PSTR(" "), 0x80); - } -#endif - } -#ifdef EXTRADEBUG - else { - Notify(PSTR("\r\nUnsupported L2CAP Data - Channel ID: "), 0x80); - D_PrintHex (l2capinbuf[7], 0x80); - Notify(PSTR(" "), 0x80); - D_PrintHex (l2capinbuf[6], 0x80); - - Notify(PSTR("\r\nData: "), 0x80); - Notify(PSTR("\r\n"), 0x80); - for(uint16_t i = 0; i < ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); i++) { - D_PrintHex (l2capinbuf[i + 8], 0x80); - Notify(PSTR(" "), 0x80); - } - } -#endif - L2CAP_task(); - } -} - -void BTHID::L2CAP_task() { - switch(l2cap_state) { - /* These states are used if the HID device is the host */ - case L2CAP_CONTROL_SUCCESS: - if(l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nHID Control Successfully Configured"), 0x80); -#endif - setProtocol(); // Set protocol before establishing HID interrupt channel - l2cap_state = L2CAP_INTERRUPT_SETUP; - } - break; - - case L2CAP_INTERRUPT_SETUP: - if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST)) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nHID Interrupt Incoming Connection Request"), 0x80); -#endif - pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, PENDING); - delay(1); - pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, SUCCESSFUL); - identifier++; - delay(1); - pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid); - - l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST; - } - break; - - /* These states are used if the Arduino is the host */ - case L2CAP_CONTROL_CONNECT_REQUEST: - if(l2cap_check_flag(L2CAP_FLAG_CONTROL_CONNECTED)) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nSend HID Control Config Request"), 0x80); -#endif - identifier++; - pBtd->l2cap_config_request(hci_handle, identifier, control_scid); - l2cap_state = L2CAP_CONTROL_CONFIG_REQUEST; - } - break; - - case L2CAP_CONTROL_CONFIG_REQUEST: - if(l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) { - setProtocol(); // Set protocol before establishing HID interrupt channel - delay(1); // Short delay between commands - just to be sure -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nSend HID Interrupt Connection Request"), 0x80); -#endif - identifier++; - pBtd->l2cap_connection_request(hci_handle, identifier, interrupt_dcid, HID_INTR_PSM); - l2cap_state = L2CAP_INTERRUPT_CONNECT_REQUEST; - } - break; - - case L2CAP_INTERRUPT_CONNECT_REQUEST: - if(l2cap_check_flag(L2CAP_FLAG_INTERRUPT_CONNECTED)) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nSend HID Interrupt Config Request"), 0x80); -#endif - identifier++; - pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid); - l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST; - } - break; - - case L2CAP_INTERRUPT_CONFIG_REQUEST: - if(l2cap_check_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS)) { // Now the HID channels is established -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nHID Channels Established"), 0x80); -#endif - pBtd->connectToHIDDevice = false; - pBtd->pairWithHIDDevice = false; - connected = true; - onInit(); - l2cap_state = L2CAP_DONE; - } - break; - - case L2CAP_DONE: - break; - - case L2CAP_INTERRUPT_DISCONNECT: - if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE)) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nDisconnected Interrupt Channel"), 0x80); -#endif - identifier++; - pBtd->l2cap_disconnection_request(hci_handle, identifier, control_scid, control_dcid); - l2cap_state = L2CAP_CONTROL_DISCONNECT; - } - break; - - case L2CAP_CONTROL_DISCONNECT: - if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE)) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nDisconnected Control Channel"), 0x80); -#endif - pBtd->hci_disconnect(hci_handle); - hci_handle = -1; // Reset handle - l2cap_event_flag = 0; // Reset flags - l2cap_state = L2CAP_WAIT; - } - break; - } -} - -void BTHID::Run() { - switch(l2cap_state) { - case L2CAP_WAIT: - if(pBtd->connectToHIDDevice && !pBtd->l2capConnectionClaimed && !connected && !activeConnection) { - pBtd->l2capConnectionClaimed = true; - activeConnection = true; -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nSend HID Control Connection Request"), 0x80); -#endif - hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection - l2cap_event_flag = 0; // Reset flags - identifier = 0; - pBtd->l2cap_connection_request(hci_handle, identifier, control_dcid, HID_CTRL_PSM); - l2cap_state = L2CAP_CONTROL_CONNECT_REQUEST; - } else if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST)) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nHID Control Incoming Connection Request"), 0x80); -#endif - pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, PENDING); - delay(1); - pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, SUCCESSFUL); - identifier++; - delay(1); - pBtd->l2cap_config_request(hci_handle, identifier, control_scid); - l2cap_state = L2CAP_CONTROL_SUCCESS; - } - break; - } -} - -/************************************************************/ -/* HID Commands */ - -/************************************************************/ -void BTHID::setProtocol() { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nSet protocol mode: "), 0x80); - D_PrintHex (protocolMode, 0x80); -#endif - if (protocolMode != HID_BOOT_PROTOCOL && protocolMode != HID_RPT_PROTOCOL) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nNot a valid protocol mode. Using Boot protocol instead."), 0x80); -#endif - protocolMode = HID_BOOT_PROTOCOL; // Use Boot Protocol by default - } - uint8_t command = 0x70 | protocolMode; // Set Protocol, see Bluetooth HID specs page 33 - pBtd->L2CAP_Command(hci_handle, &command, 1, control_scid[0], control_scid[1]); -} - -void BTHID::setLeds(uint8_t data) { - uint8_t buf[3]; - buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) - buf[1] = 0x01; // Report ID - buf[2] = data; - pBtd->L2CAP_Command(hci_handle, buf, 3, interrupt_scid[0], interrupt_scid[1]); -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/BTHID.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/BTHID.h deleted file mode 100644 index 1a7d8687c7..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/BTHID.h +++ /dev/null @@ -1,155 +0,0 @@ -/* Copyright (C) 2013 Kristian Lauszus, TKJ Electronics. All rights reserved. - - This software may be distributed and modified under the terms of the GNU - General Public License version 2 (GPL2) as published by the Free Software - Foundation and appearing in the file GPL2.TXT included in the packaging of - this file. Please note that GPL2 Section 2[b] requires that all works based - on this software must also be made publicly available under the terms of - the GPL2 ("Copyleft"). - - Contact information - ------------------- - - Kristian Lauszus, TKJ Electronics - Web : http://www.tkjelectronics.com - e-mail : kristianl@tkjelectronics.com - */ - -#ifndef _bthid_h_ -#define _bthid_h_ - -#include "BTD.h" -#include "hidboot.h" - -#define KEYBOARD_PARSER_ID 0 -#define MOUSE_PARSER_ID 1 -#define NUM_PARSERS 2 - -/** This BluetoothService class implements support for Bluetooth HID devices. */ -class BTHID : public BluetoothService { -public: - /** - * Constructor for the BTHID class. - * @param p Pointer to the BTD class instance. - * @param pair Set this to true in order to pair with the device. If the argument is omitted then it will not pair with it. One can use ::PAIR to set it to true. - * @param pin Write the pin to BTD#btdPin. If argument is omitted, then "0000" will be used. - */ - BTHID(BTD *p, bool pair = false, const char *pin = "0000"); - - /** @name BluetoothService implementation */ - /** Used this to disconnect the devices. */ - void disconnect(); - /**@}*/ - - /** - * Get HIDReportParser. - * @param id ID of parser. - * @return Returns the corresponding HIDReportParser. Returns NULL if id is not valid. - */ - HIDReportParser *GetReportParser(uint8_t id) { - if (id >= NUM_PARSERS) - return NULL; - return pRptParser[id]; - }; - - /** - * Set HIDReportParser to be used. - * @param id Id of parser. - * @param prs Pointer to HIDReportParser. - * @return Returns true if the HIDReportParser is set. False otherwise. - */ - bool SetReportParser(uint8_t id, HIDReportParser *prs) { - if (id >= NUM_PARSERS) - return false; - pRptParser[id] = prs; - return true; - }; - - /** - * Set HID protocol mode. - * @param mode HID protocol to use. Either HID_BOOT_PROTOCOL or HID_RPT_PROTOCOL. - */ - void setProtocolMode(uint8_t mode) { - protocolMode = mode; - }; - - /** - * Used to set the leds on a keyboard. - * @param data See KBDLEDS in hidboot.h - */ - void setLeds(uint8_t data); - - /** True if a device is connected */ - bool connected; - - /** Call this to start the paring sequence with a device */ - void pair(void) { - if(pBtd) - pBtd->pairWithHID(); - }; - -protected: - /** @name BluetoothService implementation */ - /** - * Used to pass acldata to the services. - * @param ACLData Incoming acldata. - */ - void ACLData(uint8_t* ACLData); - /** Used to run part of the state machine. */ - void Run(); - /** Use this to reset the service. */ - void Reset(); - /** - * Called when a device is successfully initialized. - * Use attachOnInit(void (*funcOnInit)(void)) to call your own function. - * This is useful for instance if you want to set the LEDs in a specific way. - */ - void onInit() { - if(pFuncOnInit) - pFuncOnInit(); // Call the user function - OnInitBTHID(); - }; - /**@}*/ - - /** @name Overridable functions */ - /** - * Used to parse Bluetooth HID data to any class that inherits this class. - * @param len The length of the incoming data. - * @param buf Pointer to the data buffer. - */ - virtual void ParseBTHIDData(uint8_t len, uint8_t *buf) { - return; - }; - /** Called when a device is connected */ - virtual void OnInitBTHID() { - return; - }; - /** Used to reset any buffers in the class that inherits this */ - virtual void ResetBTHID() { - return; - } - /**@}*/ - - /** L2CAP source CID for HID_Control */ - uint8_t control_scid[2]; - - /** L2CAP source CID for HID_Interrupt */ - uint8_t interrupt_scid[2]; - -private: - HIDReportParser *pRptParser[NUM_PARSERS]; // Pointer to HIDReportParsers. - - /** Set report protocol. */ - void setProtocol(); - uint8_t protocolMode; - - void L2CAP_task(); // L2CAP state machine - - bool activeConnection; // Used to indicate if it already has established a connection - - /* Variables used for L2CAP communication */ - uint8_t control_dcid[2]; // L2CAP device CID for HID_Control - Always 0x0070 - uint8_t interrupt_dcid[2]; // L2CAP device CID for HID_Interrupt - Always 0x0071 - uint8_t l2cap_state; -}; -#endif diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3BT.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3BT.cpp deleted file mode 100644 index 235092e0ac..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3BT.cpp +++ /dev/null @@ -1,634 +0,0 @@ -/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. - - This software may be distributed and modified under the terms of the GNU - General Public License version 2 (GPL2) as published by the Free Software - Foundation and appearing in the file GPL2.TXT included in the packaging of - this file. Please note that GPL2 Section 2[b] requires that all works based - on this software must also be made publicly available under the terms of - the GPL2 ("Copyleft"). - - Contact information - ------------------- - - Kristian Lauszus, TKJ Electronics - Web : http://www.tkjelectronics.com - e-mail : kristianl@tkjelectronics.com - */ - -#include "PS3BT.h" -// To enable serial debugging see "settings.h" -//#define EXTRADEBUG // Uncomment to get even more debugging data -//#define PRINTREPORT // Uncomment to print the report send by the PS3 Controllers - -PS3BT::PS3BT(BTD *p, uint8_t btadr5, uint8_t btadr4, uint8_t btadr3, uint8_t btadr2, uint8_t btadr1, uint8_t btadr0) : -BluetoothService(p) // Pointer to USB class instance - mandatory -{ - pBtd->my_bdaddr[5] = btadr5; // Change to your dongle's Bluetooth address instead - pBtd->my_bdaddr[4] = btadr4; - pBtd->my_bdaddr[3] = btadr3; - pBtd->my_bdaddr[2] = btadr2; - pBtd->my_bdaddr[1] = btadr1; - pBtd->my_bdaddr[0] = btadr0; - - HIDBuffer[0] = 0x52; // HID BT Set_report (0x50) | Report Type (Output 0x02) - HIDBuffer[1] = 0x01; // Report ID - - // Needed for PS3 Move Controller commands to work via bluetooth - HIDMoveBuffer[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) - HIDMoveBuffer[1] = 0x02; // Report ID - - /* Set device cid for the control and intterrupt channelse - LSB */ - control_dcid[0] = 0x40; // 0x0040 - control_dcid[1] = 0x00; - interrupt_dcid[0] = 0x41; // 0x0041 - interrupt_dcid[1] = 0x00; - - Reset(); -} - -bool PS3BT::getButtonPress(ButtonEnum b) { - return (ButtonState & pgm_read_dword(&PS3_BUTTONS[(uint8_t)b])); -} - -bool PS3BT::getButtonClick(ButtonEnum b) { - uint32_t button = pgm_read_dword(&PS3_BUTTONS[(uint8_t)b]); - bool click = (ButtonClickState & button); - ButtonClickState &= ~button; // Clear "click" event - return click; -} - -uint8_t PS3BT::getAnalogButton(ButtonEnum a) { - return (uint8_t)(l2capinbuf[pgm_read_byte(&PS3_ANALOG_BUTTONS[(uint8_t)a])]); -} - -uint8_t PS3BT::getAnalogHat(AnalogHatEnum a) { - return (uint8_t)(l2capinbuf[(uint8_t)a + 15]); -} - -int16_t PS3BT::getSensor(SensorEnum a) { - if(PS3Connected) { - if(a == aX || a == aY || a == aZ || a == gZ) - return ((l2capinbuf[(uint16_t)a] << 8) | l2capinbuf[(uint16_t)a + 1]); - else - return 0; - } else if(PS3MoveConnected) { - if(a == mXmove || a == mYmove) // These are all 12-bits long - return (((l2capinbuf[(uint16_t)a] & 0x0F) << 8) | (l2capinbuf[(uint16_t)a + 1])); - else if(a == mZmove || a == tempMove) // The tempearature is also 12 bits long - return ((l2capinbuf[(uint16_t)a] << 4) | ((l2capinbuf[(uint16_t)a + 1] & 0xF0) >> 4)); - else // aXmove, aYmove, aZmove, gXmove, gYmove and gZmove - return (l2capinbuf[(uint16_t)a] | (l2capinbuf[(uint16_t)a + 1] << 8)); - } else - return 0; -} - -double PS3BT::getAngle(AngleEnum a) { - double accXval, accYval, accZval; - - if(PS3Connected) { - // Data for the Kionix KXPC4 used in the DualShock 3 - const double zeroG = 511.5; // 1.65/3.3*1023 (1.65V) - accXval = -((double)getSensor(aX) - zeroG); - accYval = -((double)getSensor(aY) - zeroG); - accZval = -((double)getSensor(aZ) - zeroG); - } else if(PS3MoveConnected) { - // It's a Kionix KXSC4 inside the Motion controller - const uint16_t zeroG = 0x8000; - accXval = -(int16_t)(getSensor(aXmove) - zeroG); - accYval = (int16_t)(getSensor(aYmove) - zeroG); - accZval = (int16_t)(getSensor(aZmove) - zeroG); - } else - return 0; - - // Convert to 360 degrees resolution - // atan2 outputs the value of -π to π (radians) - // We are then converting it to 0 to 2π and then to degrees - if(a == Pitch) - return (atan2(accYval, accZval) + PI) * RAD_TO_DEG; - else - return (atan2(accXval, accZval) + PI) * RAD_TO_DEG; -} - -double PS3BT::get9DOFValues(SensorEnum a) { // Thanks to Manfred Piendl - if(!PS3MoveConnected) - return 0; - int16_t value = getSensor(a); - if(a == mXmove || a == mYmove || a == mZmove) { - if(value > 2047) - value -= 0x1000; - return (double)value / 3.2; // unit: muT = 10^(-6) Tesla - } else if(a == aXmove || a == aYmove || a == aZmove) { - if(value < 0) - value += 0x8000; - else - value -= 0x8000; - return (double)value / 442.0; // unit: m/(s^2) - } else if(a == gXmove || a == gYmove || a == gZmove) { - if(value < 0) - value += 0x8000; - else - value -= 0x8000; - if(a == gXmove) - return (double)value / 11.6; // unit: deg/s - else if(a == gYmove) - return (double)value / 11.2; // unit: deg/s - else // gZmove - return (double)value / 9.6; // unit: deg/s - } else - return 0; -} - -String PS3BT::getTemperature() { - if(PS3MoveConnected) { - int16_t input = getSensor(tempMove); - - String output = String(input / 100); - output += "."; - if(input % 100 < 10) - output += "0"; - output += String(input % 100); - - return output; - } else - return "Error"; -} - -bool PS3BT::getStatus(StatusEnum c) { - return (l2capinbuf[(uint16_t)c >> 8] == ((uint8_t)c & 0xff)); -} - -void PS3BT::printStatusString() { - char statusOutput[100]; // Max string length plus null character - if(PS3Connected || PS3NavigationConnected) { - strcpy_P(statusOutput, PSTR("ConnectionStatus: ")); - - if(getStatus(Plugged)) strcat_P(statusOutput, PSTR("Plugged")); - else if(getStatus(Unplugged)) strcat_P(statusOutput, PSTR("Unplugged")); - else strcat_P(statusOutput, PSTR("Error")); - - strcat_P(statusOutput, PSTR(" - PowerRating: ")); - - if(getStatus(Charging)) strcat_P(statusOutput, PSTR("Charging")); - else if(getStatus(NotCharging)) strcat_P(statusOutput, PSTR("Not Charging")); - else if(getStatus(Shutdown)) strcat_P(statusOutput, PSTR("Shutdown")); - else if(getStatus(Dying)) strcat_P(statusOutput, PSTR("Dying")); - else if(getStatus(Low)) strcat_P(statusOutput, PSTR("Low")); - else if(getStatus(High)) strcat_P(statusOutput, PSTR("High")); - else if(getStatus(Full)) strcat_P(statusOutput, PSTR("Full")); - else strcat_P(statusOutput, PSTR("Error")); - - strcat_P(statusOutput, PSTR(" - WirelessStatus: ")); - - if(getStatus(CableRumble)) strcat_P(statusOutput, PSTR("Cable - Rumble is on")); - else if(getStatus(Cable)) strcat_P(statusOutput, PSTR("Cable - Rumble is off")); - else if(getStatus(BluetoothRumble)) strcat_P(statusOutput, PSTR("Bluetooth - Rumble is on")); - else if(getStatus(Bluetooth)) strcat_P(statusOutput, PSTR("Bluetooth - Rumble is off")); - else strcat_P(statusOutput, PSTR("Error")); - } else if(PS3MoveConnected) { - strcpy_P(statusOutput, PSTR("PowerRating: ")); - - if(getStatus(MoveCharging)) strcat_P(statusOutput, PSTR("Charging")); - else if(getStatus(MoveNotCharging)) strcat_P(statusOutput, PSTR("Not Charging")); - else if(getStatus(MoveShutdown)) strcat_P(statusOutput, PSTR("Shutdown")); - else if(getStatus(MoveDying)) strcat_P(statusOutput, PSTR("Dying")); - else if(getStatus(MoveLow)) strcat_P(statusOutput, PSTR("Low")); - else if(getStatus(MoveHigh)) strcat_P(statusOutput, PSTR("High")); - else if(getStatus(MoveFull)) strcat_P(statusOutput, PSTR("Full")); - else strcat_P(statusOutput, PSTR("Error")); - } else - strcpy_P(statusOutput, PSTR("Error")); - - USB_HOST_SERIAL.write(statusOutput); -} - -void PS3BT::Reset() { - PS3Connected = false; - PS3MoveConnected = false; - PS3NavigationConnected = false; - activeConnection = false; - l2cap_event_flag = 0; // Reset flags - l2cap_state = L2CAP_WAIT; - - // Needed for PS3 Dualshock Controller commands to work via Bluetooth - for(uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++) - HIDBuffer[i + 2] = pgm_read_byte(&PS3_REPORT_BUFFER[i]); // First two bytes reserved for report type and ID -} - -void PS3BT::disconnect() { // Use this void to disconnect any of the controllers - // First the HID interrupt channel has to be disconnected, then the HID control channel and finally the HCI connection - pBtd->l2cap_disconnection_request(hci_handle, ++identifier, interrupt_scid, interrupt_dcid); - Reset(); - l2cap_state = L2CAP_INTERRUPT_DISCONNECT; -} - -void PS3BT::ACLData(uint8_t* ACLData) { - if(!pBtd->l2capConnectionClaimed && !PS3Connected && !PS3MoveConnected && !PS3NavigationConnected && !activeConnection && !pBtd->connectToWii && !pBtd->incomingWii && !pBtd->pairWithWii) { - if(ACLData[8] == L2CAP_CMD_CONNECTION_REQUEST) { - if((ACLData[12] | (ACLData[13] << 8)) == HID_CTRL_PSM) { - pBtd->l2capConnectionClaimed = true; // Claim that the incoming connection belongs to this service - activeConnection = true; - hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection - l2cap_state = L2CAP_WAIT; - remote_name_first = pBtd->remote_name[0]; // Store the first letter in remote name for the connection -#ifdef DEBUG_USB_HOST - if(pBtd->hci_version < 3) { // Check the HCI Version of the Bluetooth dongle - Notify(PSTR("\r\nYour dongle may not support reading the analog buttons, sensors and status\r\nYour HCI Version is: "), 0x80); - Notify(pBtd->hci_version, 0x80); - Notify(PSTR("\r\nBut should be at least 3\r\nThis means that it doesn't support Bluetooth Version 2.0+EDR"), 0x80); - } -#endif - } - } - } - - if(checkHciHandle(ACLData, hci_handle)) { // acl_handle_ok - memcpy(l2capinbuf, ACLData, BULK_MAXPKTSIZE); - if((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001U) { // l2cap_control - Channel ID for ACL-U - if(l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80); - D_PrintHex (l2capinbuf[13], 0x80); - Notify(PSTR(" "), 0x80); - D_PrintHex (l2capinbuf[12], 0x80); - Notify(PSTR(" Data: "), 0x80); - D_PrintHex (l2capinbuf[17], 0x80); - Notify(PSTR(" "), 0x80); - D_PrintHex (l2capinbuf[16], 0x80); - Notify(PSTR(" "), 0x80); - D_PrintHex (l2capinbuf[15], 0x80); - Notify(PSTR(" "), 0x80); - D_PrintHex (l2capinbuf[14], 0x80); -#endif - } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { -#ifdef EXTRADEBUG - Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80); - D_PrintHex (l2capinbuf[13], 0x80); - Notify(PSTR(" "), 0x80); - D_PrintHex (l2capinbuf[12], 0x80); - Notify(PSTR(" SCID: "), 0x80); - D_PrintHex (l2capinbuf[15], 0x80); - Notify(PSTR(" "), 0x80); - D_PrintHex (l2capinbuf[14], 0x80); - Notify(PSTR(" Identifier: "), 0x80); - D_PrintHex (l2capinbuf[9], 0x80); -#endif - if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) { - identifier = l2capinbuf[9]; - control_scid[0] = l2capinbuf[14]; - control_scid[1] = l2capinbuf[15]; - l2cap_set_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST); - } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_INTR_PSM) { - identifier = l2capinbuf[9]; - interrupt_scid[0] = l2capinbuf[14]; - interrupt_scid[1] = l2capinbuf[15]; - l2cap_set_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST); - } - } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) { - if((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success - if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { - //Notify(PSTR("\r\nHID Control Configuration Complete"), 0x80); - l2cap_set_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS); - } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { - //Notify(PSTR("\r\nHID Interrupt Configuration Complete"), 0x80); - l2cap_set_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS); - } - } - } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) { - if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { - //Notify(PSTR("\r\nHID Control Configuration Request"), 0x80); - pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], control_scid); - } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { - //Notify(PSTR("\r\nHID Interrupt Configuration Request"), 0x80); - pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], interrupt_scid); - } - } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) { - if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nDisconnect Request: Control Channel"), 0x80); -#endif - identifier = l2capinbuf[9]; - pBtd->l2cap_disconnection_response(hci_handle, identifier, control_dcid, control_scid); - Reset(); - } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nDisconnect Request: Interrupt Channel"), 0x80); -#endif - identifier = l2capinbuf[9]; - pBtd->l2cap_disconnection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid); - Reset(); - } - } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) { - if(l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) { - //Notify(PSTR("\r\nDisconnect Response: Control Channel"), 0x80); - identifier = l2capinbuf[9]; - l2cap_set_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE); - } else if(l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) { - //Notify(PSTR("\r\nDisconnect Response: Interrupt Channel"), 0x80); - identifier = l2capinbuf[9]; - l2cap_set_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE); - } - } -#ifdef EXTRADEBUG - else { - Notify(PSTR("\r\nL2CAP Unknown Signaling Command: "), 0x80); - D_PrintHex (l2capinbuf[8], 0x80); - } -#endif - } else if(l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt - //Notify(PSTR("\r\nL2CAP Interrupt"), 0x80); - if(PS3Connected || PS3MoveConnected || PS3NavigationConnected) { - /* Read Report */ - if(l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT - lastMessageTime = millis(); // Store the last message time - - if(PS3Connected || PS3NavigationConnected) - ButtonState = (uint32_t)(l2capinbuf[11] | ((uint16_t)l2capinbuf[12] << 8) | ((uint32_t)l2capinbuf[13] << 16)); - else if(PS3MoveConnected) - ButtonState = (uint32_t)(l2capinbuf[10] | ((uint16_t)l2capinbuf[11] << 8) | ((uint32_t)l2capinbuf[12] << 16)); - - //Notify(PSTR("\r\nButtonState", 0x80); - //PrintHex(ButtonState, 0x80); - - if(ButtonState != OldButtonState) { - ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable - OldButtonState = ButtonState; - } - -#ifdef PRINTREPORT // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers - for(uint8_t i = 10; i < 58; i++) { - D_PrintHex (l2capinbuf[i], 0x80); - Notify(PSTR(" "), 0x80); - } - Notify(PSTR("\r\n"), 0x80); -#endif - } - } - } - L2CAP_task(); - } -} - -void PS3BT::L2CAP_task() { - switch(l2cap_state) { - case L2CAP_WAIT: - if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST)) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nHID Control Incoming Connection Request"), 0x80); -#endif - pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, PENDING); - delay(1); - pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, SUCCESSFUL); - identifier++; - delay(1); - pBtd->l2cap_config_request(hci_handle, identifier, control_scid); - l2cap_state = L2CAP_CONTROL_SUCCESS; - } - break; - - case L2CAP_CONTROL_SUCCESS: - if(l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nHID Control Successfully Configured"), 0x80); -#endif - l2cap_state = L2CAP_INTERRUPT_SETUP; - } - break; - - case L2CAP_INTERRUPT_SETUP: - if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST)) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nHID Interrupt Incoming Connection Request"), 0x80); -#endif - pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, PENDING); - delay(1); - pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, SUCCESSFUL); - identifier++; - delay(1); - pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid); - - l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST; - } - break; - - case L2CAP_INTERRUPT_CONFIG_REQUEST: - if(l2cap_check_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS)) { // Now the HID channels is established -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nHID Interrupt Successfully Configured"), 0x80); -#endif - if(remote_name_first == 'M') { // First letter in Motion Controller ('M') - memset(l2capinbuf, 0, BULK_MAXPKTSIZE); // Reset l2cap in buffer as it sometimes read it as a button has been pressed - l2cap_state = TURN_ON_LED; - } else - l2cap_state = PS3_ENABLE_SIXAXIS; - timer = millis(); - } - break; - - /* These states are handled in Run() */ - - case L2CAP_INTERRUPT_DISCONNECT: - if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE)) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nDisconnected Interrupt Channel"), 0x80); -#endif - identifier++; - pBtd->l2cap_disconnection_request(hci_handle, identifier, control_scid, control_dcid); - l2cap_state = L2CAP_CONTROL_DISCONNECT; - } - break; - - case L2CAP_CONTROL_DISCONNECT: - if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE)) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nDisconnected Control Channel"), 0x80); -#endif - pBtd->hci_disconnect(hci_handle); - hci_handle = -1; // Reset handle - l2cap_event_flag = 0; // Reset flags - l2cap_state = L2CAP_WAIT; - } - break; - } -} - -void PS3BT::Run() { - switch(l2cap_state) { - case PS3_ENABLE_SIXAXIS: - if(millis() - timer > 1000) { // loop 1 second before sending the command - memset(l2capinbuf, 0, BULK_MAXPKTSIZE); // Reset l2cap in buffer as it sometimes read it as a button has been pressed - for(uint8_t i = 15; i < 19; i++) - l2capinbuf[i] = 0x7F; // Set the analog joystick values to center position - enable_sixaxis(); - l2cap_state = TURN_ON_LED; - timer = millis(); - } - break; - - case TURN_ON_LED: - if(millis() - timer > 1000) { // loop 1 second before sending the command - if(remote_name_first == 'P') { // First letter in PLAYSTATION(R)3 Controller ('P') -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nDualshock 3 Controller Enabled\r\n"), 0x80); -#endif - PS3Connected = true; - } else if(remote_name_first == 'N') { // First letter in Navigation Controller ('N') -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nNavigation Controller Enabled\r\n"), 0x80); -#endif - PS3NavigationConnected = true; - } else if(remote_name_first == 'M') { // First letter in Motion Controller ('M') - timer = millis(); -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nMotion Controller Enabled\r\n"), 0x80); -#endif - PS3MoveConnected = true; - } - ButtonState = 0; // Clear all values - OldButtonState = 0; - ButtonClickState = 0; - - onInit(); // Turn on the LED on the controller - l2cap_state = L2CAP_DONE; - } - break; - - case L2CAP_DONE: - if(PS3MoveConnected) { // The Bulb and rumble values, has to be send at approximately every 5th second for it to stay on - if(millis() - timer > 4000) { // Send at least every 4th second - HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE); // The Bulb and rumble values, has to be written again and again, for it to stay turned on - timer = millis(); - } - } - break; - } -} - -/************************************************************/ -/* HID Commands */ -/************************************************************/ - -// Playstation Sixaxis Dualshock and Navigation Controller commands - -void PS3BT::HID_Command(uint8_t* data, uint8_t nbytes) { - if(millis() - timerHID <= 150) // Check if is has been more than 150ms since last command - delay((uint32_t)(150 - (millis() - timerHID))); // There have to be a delay between commands - pBtd->L2CAP_Command(hci_handle, data, nbytes, control_scid[0], control_scid[1]); // Both the Navigation and Dualshock controller sends data via the control channel - timerHID = millis(); -} - -void PS3BT::setAllOff() { - HIDBuffer[3] = 0x00; // Rumble bytes - HIDBuffer[4] = 0x00; - HIDBuffer[5] = 0x00; - HIDBuffer[6] = 0x00; - - HIDBuffer[11] = 0x00; // LED byte - - HID_Command(HIDBuffer, HID_BUFFERSIZE); -} - -void PS3BT::setRumbleOff() { - HIDBuffer[3] = 0x00; - HIDBuffer[4] = 0x00; - HIDBuffer[5] = 0x00; - HIDBuffer[6] = 0x00; - - HID_Command(HIDBuffer, HID_BUFFERSIZE); -} - -void PS3BT::setRumbleOn(RumbleEnum mode) { - uint8_t power[2] = {0xff, 0x00}; // Defaults to RumbleLow - if(mode == RumbleHigh) { - power[0] = 0x00; - power[1] = 0xff; - } - setRumbleOn(0xfe, power[0], 0xfe, power[1]); -} - -void PS3BT::setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower) { - HIDBuffer[3] = rightDuration; - HIDBuffer[4] = rightPower; - HIDBuffer[5] = leftDuration; - HIDBuffer[6] = leftPower; - HID_Command(HIDBuffer, HID_BUFFERSIZE); -} - -void PS3BT::setLedRaw(uint8_t value) { - HIDBuffer[11] = value << 1; - HID_Command(HIDBuffer, HID_BUFFERSIZE); -} - -void PS3BT::setLedOff(LEDEnum a) { - HIDBuffer[11] &= ~((uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1)); - HID_Command(HIDBuffer, HID_BUFFERSIZE); -} - -void PS3BT::setLedOn(LEDEnum a) { - if(a == OFF) - setLedRaw(0); - else { - HIDBuffer[11] |= (uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1); - HID_Command(HIDBuffer, HID_BUFFERSIZE); - } -} - -void PS3BT::setLedToggle(LEDEnum a) { - HIDBuffer[11] ^= (uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1); - HID_Command(HIDBuffer, HID_BUFFERSIZE); -} - -void PS3BT::enable_sixaxis() { // Command used to enable the Dualshock 3 and Navigation controller to send data via Bluetooth - uint8_t cmd_buf[6]; - cmd_buf[0] = 0x53; // HID BT Set_report (0x50) | Report Type (Feature 0x03) - cmd_buf[1] = 0xF4; // Report ID - cmd_buf[2] = 0x42; // Special PS3 Controller enable commands - cmd_buf[3] = 0x03; - cmd_buf[4] = 0x00; - cmd_buf[5] = 0x00; - - HID_Command(cmd_buf, 6); -} - -// Playstation Move Controller commands - -void PS3BT::HIDMove_Command(uint8_t* data, uint8_t nbytes) { - if(millis() - timerHID <= 150)// Check if is has been less than 150ms since last command - delay((uint32_t)(150 - (millis() - timerHID))); // There have to be a delay between commands - pBtd->L2CAP_Command(hci_handle, data, nbytes, interrupt_scid[0], interrupt_scid[1]); // The Move controller sends it's data via the intterrupt channel - timerHID = millis(); -} - -void PS3BT::moveSetBulb(uint8_t r, uint8_t g, uint8_t b) { // Use this to set the Color using RGB values - // Set the Bulb's values into the write buffer - HIDMoveBuffer[3] = r; - HIDMoveBuffer[4] = g; - HIDMoveBuffer[5] = b; - - HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE); -} - -void PS3BT::moveSetBulb(ColorsEnum color) { // Use this to set the Color using the predefined colors in enum - moveSetBulb((uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color)); -} - -void PS3BT::moveSetRumble(uint8_t rumble) { -#ifdef DEBUG_USB_HOST - if(rumble < 64 && rumble != 0) // The rumble value has to at least 64, or approximately 25% (64/255*100) - Notify(PSTR("\r\nThe rumble value has to at least 64, or approximately 25%"), 0x80); -#endif - // Set the rumble value into the write buffer - HIDMoveBuffer[7] = rumble; - - HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE); -} - -void PS3BT::onInit() { - if(pFuncOnInit) - pFuncOnInit(); // Call the user function - else { - if(PS3MoveConnected) - moveSetBulb(Red); - else // Dualshock 3 or Navigation controller - setLedOn(LED1); - } -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3BT.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3BT.h deleted file mode 100644 index c25ac5e59d..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3BT.h +++ /dev/null @@ -1,240 +0,0 @@ -/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. - - This software may be distributed and modified under the terms of the GNU - General Public License version 2 (GPL2) as published by the Free Software - Foundation and appearing in the file GPL2.TXT included in the packaging of - this file. Please note that GPL2 Section 2[b] requires that all works based - on this software must also be made publicly available under the terms of - the GPL2 ("Copyleft"). - - Contact information - ------------------- - - Kristian Lauszus, TKJ Electronics - Web : http://www.tkjelectronics.com - e-mail : kristianl@tkjelectronics.com - */ - -#ifndef _ps3bt_h_ -#define _ps3bt_h_ - -#include "BTD.h" -#include "PS3Enums.h" - -#define HID_BUFFERSIZE 50 // Size of the buffer for the Playstation Motion Controller - -/** - * This BluetoothService class implements support for all the official PS3 Controllers: - * Dualshock 3, Navigation or a Motion controller via Bluetooth. - * - * Information about the protocol can be found at the wiki: https://github.com/felis/USB_Host_Shield_2.0/wiki/PS3-Information. - */ -class PS3BT : public BluetoothService { -public: - /** - * Constructor for the PS3BT class. - * @param pBtd Pointer to BTD class instance. - * @param btadr5,btadr4,btadr3,btadr2,btadr1,btadr0 - * Pass your dongles Bluetooth address into the constructor, - * This will set BTD#my_bdaddr, so you don't have to plug in the dongle before pairing with your controller. - */ - PS3BT(BTD *pBtd, uint8_t btadr5 = 0, uint8_t btadr4 = 0, uint8_t btadr3 = 0, uint8_t btadr2 = 0, uint8_t btadr1 = 0, uint8_t btadr0 = 0); - - /** @name BluetoothService implementation */ - /** Used this to disconnect any of the controllers. */ - void disconnect(); - /**@}*/ - - /** @name PS3 Controller functions */ - /** - * getButtonPress(ButtonEnum b) will return true as long as the button is held down. - * - * While getButtonClick(ButtonEnum b) will only return it once. - * - * So you instance if you need to increase a variable once you would use getButtonClick(ButtonEnum b), - * but if you need to drive a robot forward you would use getButtonPress(ButtonEnum b). - * @param b ::ButtonEnum to read. - * @return getButtonPress(ButtonEnum b) will return a true as long as a button is held down, while getButtonClick(ButtonEnum b) will return true once for each button press. - */ - bool getButtonPress(ButtonEnum b); - bool getButtonClick(ButtonEnum b); - /**@}*/ - /** @name PS3 Controller functions */ - /** - * Used to get the analog value from button presses. - * @param a The ::ButtonEnum to read. - * The supported buttons are: - * ::UP, ::RIGHT, ::DOWN, ::LEFT, ::L1, ::L2, ::R1, ::R2, - * ::TRIANGLE, ::CIRCLE, ::CROSS, ::SQUARE, and ::T. - * @return Analog value in the range of 0-255. - */ - uint8_t getAnalogButton(ButtonEnum a); - /** - * Used to read the analog joystick. - * @param a ::LeftHatX, ::LeftHatY, ::RightHatX, and ::RightHatY. - * @return Return the analog value in the range of 0-255. - */ - uint8_t getAnalogHat(AnalogHatEnum a); - /** - * Used to read the sensors inside the Dualshock 3 and Move controller. - * @param a - * The Dualshock 3 has a 3-axis accelerometer and a 1-axis gyro inside. - * The Move controller has a 3-axis accelerometer, a 3-axis gyro, a 3-axis magnetometer - * and a temperature sensor inside. - * @return Return the raw sensor value. - */ - int16_t getSensor(SensorEnum a); - /** - * Use this to get ::Pitch and ::Roll calculated using the accelerometer. - * @param a Either ::Pitch or ::Roll. - * @return Return the angle in the range of 0-360. - */ - double getAngle(AngleEnum a); - /** - * Read the sensors inside the Move controller. - * @param a ::aXmove, ::aYmove, ::aZmove, ::gXmove, ::gYmove, ::gZmove, ::mXmove, ::mYmove, and ::mXmove. - * @return The value in SI units. - */ - double get9DOFValues(SensorEnum a); - /** - * Get the status from the controller. - * @param c The ::StatusEnum you want to read. - * @return True if correct and false if not. - */ - bool getStatus(StatusEnum c); - /** Read all the available statuses from the controller and prints it as a nice formated string. */ - void printStatusString(); - /** - * Read the temperature from the Move controller. - * @return The temperature in degrees Celsius. - */ - String getTemperature(); - - /** Used to set all LEDs and rumble off. */ - void setAllOff(); - /** Turn off rumble. */ - void setRumbleOff(); - /** - * Turn on rumble. - * @param mode Either ::RumbleHigh or ::RumbleLow. - */ - void setRumbleOn(RumbleEnum mode); - /** - * Turn on rumble using custom duration and power. - * @param rightDuration The duration of the right/low rumble effect. - * @param rightPower The intensity of the right/low rumble effect. - * @param leftDuration The duration of the left/high rumble effect. - * @param leftPower The intensity of the left/high rumble effect. - */ - void setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower); - - /** - * Set LED value without using ::LEDEnum. - * @param value See: ::LEDEnum. - */ - void setLedRaw(uint8_t value); - - /** Turn all LEDs off. */ - void setLedOff() { - setLedRaw(0); - }; - /** - * Turn the specific LED off. - * @param a The ::LEDEnum to turn off. - */ - void setLedOff(LEDEnum a); - /** - * Turn the specific LED on. - * @param a The ::LEDEnum to turn on. - */ - void setLedOn(LEDEnum a); - /** - * Toggle the specific LED. - * @param a The ::LEDEnum to toggle. - */ - void setLedToggle(LEDEnum a); - - /** - * Use this to set the Color using RGB values. - * @param r,g,b RGB value. - */ - void moveSetBulb(uint8_t r, uint8_t g, uint8_t b); - /** - * Use this to set the color using the predefined colors in ::ColorsEnum. - * @param color The desired color. - */ - void moveSetBulb(ColorsEnum color); - /** - * Set the rumble value inside the Move controller. - * @param rumble The desired value in the range from 64-255. - */ - void moveSetRumble(uint8_t rumble); - - /** Used to get the millis() of the last message */ - uint32_t getLastMessageTime() { - return lastMessageTime; - }; - /**@}*/ - - /** Variable used to indicate if the normal Playstation controller is successfully connected. */ - bool PS3Connected; - /** Variable used to indicate if the Move controller is successfully connected. */ - bool PS3MoveConnected; - /** Variable used to indicate if the Navigation controller is successfully connected. */ - bool PS3NavigationConnected; - -protected: - /** @name BluetoothService implementation */ - /** - * Used to pass acldata to the services. - * @param ACLData Incoming acldata. - */ - void ACLData(uint8_t* ACLData); - /** Used to run part of the state machine. */ - void Run(); - /** Use this to reset the service. */ - void Reset(); - /** - * Called when the controller is successfully initialized. - * Use attachOnInit(void (*funcOnInit)(void)) to call your own function. - * This is useful for instance if you want to set the LEDs in a specific way. - */ - void onInit(); - /**@}*/ - -private: - - void L2CAP_task(); // L2CAP state machine - - /* Variables filled from HCI event management */ - char remote_name_first; // First letter in remote name - bool activeConnection; // Used to indicate if it's already has established a connection - - /* Variables used by high level L2CAP task */ - uint8_t l2cap_state; - - uint32_t lastMessageTime; // Variable used to store the millis value of the last message. - - uint32_t ButtonState; - uint32_t OldButtonState; - uint32_t ButtonClickState; - - uint32_t timer; // Timer used to limit time between messages and also used to continuously set PS3 Move controller Bulb and rumble values - uint32_t timerHID; // Timer used see if there has to be a delay before a new HID command - - uint8_t l2capinbuf[BULK_MAXPKTSIZE]; // General purpose buffer for L2CAP in data - uint8_t HIDBuffer[HID_BUFFERSIZE]; // Used to store HID commands - uint8_t HIDMoveBuffer[HID_BUFFERSIZE]; // Used to store HID commands for the Move controller - - /* L2CAP Channels */ - uint8_t control_scid[2]; // L2CAP source CID for HID_Control - uint8_t control_dcid[2]; // 0x0040 - uint8_t interrupt_scid[2]; // L2CAP source CID for HID_Interrupt - uint8_t interrupt_dcid[2]; // 0x0041 - - /* HID Commands */ - void HID_Command(uint8_t* data, uint8_t nbytes); - void HIDMove_Command(uint8_t* data, uint8_t nbytes); - void enable_sixaxis(); // Command used to enable the Dualshock 3 and Navigation controller to send data via Bluetooth -}; -#endif diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3Enums.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3Enums.h deleted file mode 100644 index 77801945f2..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3Enums.h +++ /dev/null @@ -1,141 +0,0 @@ -/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. - - This software may be distributed and modified under the terms of the GNU - General Public License version 2 (GPL2) as published by the Free Software - Foundation and appearing in the file GPL2.TXT included in the packaging of - this file. Please note that GPL2 Section 2[b] requires that all works based - on this software must also be made publicly available under the terms of - the GPL2 ("Copyleft"). - - Contact information - ------------------- - - Kristian Lauszus, TKJ Electronics - Web : http://www.tkjelectronics.com - e-mail : kristianl@tkjelectronics.com - */ - -#ifndef _ps3enums_h -#define _ps3enums_h - -#include "controllerEnums.h" - -/** Size of the output report buffer for the Dualshock and Navigation controllers */ -#define PS3_REPORT_BUFFER_SIZE 48 - -/** Report buffer for all PS3 commands */ -const uint8_t PS3_REPORT_BUFFER[PS3_REPORT_BUFFER_SIZE] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0x27, 0x10, 0x00, 0x32, - 0xff, 0x27, 0x10, 0x00, 0x32, - 0xff, 0x27, 0x10, 0x00, 0x32, - 0xff, 0x27, 0x10, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -/** Size of the output report buffer for the Move Controller */ -#define MOVE_REPORT_BUFFER_SIZE 7 - -/** Used to set the LEDs on the controllers */ -const uint8_t PS3_LEDS[] PROGMEM = { - 0x00, // OFF - 0x01, // LED1 - 0x02, // LED2 - 0x04, // LED3 - 0x08, // LED4 - - 0x09, // LED5 - 0x0A, // LED6 - 0x0C, // LED7 - 0x0D, // LED8 - 0x0E, // LED9 - 0x0F, // LED10 -}; - -/** - * Buttons on the controllers. - * Note: that the location is shifted 9 when it's connected via USB. - */ -const uint32_t PS3_BUTTONS[] PROGMEM = { - 0x10, // UP - 0x20, // RIGHT - 0x40, // DOWN - 0x80, // LEFT - - 0x01, // SELECT - 0x08, // START - 0x02, // L3 - 0x04, // R3 - - 0x0100, // L2 - 0x0200, // R2 - 0x0400, // L1 - 0x0800, // R1 - - 0x1000, // TRIANGLE - 0x2000, // CIRCLE - 0x4000, // CROSS - 0x8000, // SQUARE - - 0x010000, // PS - 0x080000, // MOVE - covers 12 bits - we only need to read the top 8 - 0x100000, // T - covers 12 bits - we only need to read the top 8 -}; - -/** - * Analog buttons on the controllers. - * Note: that the location is shifted 9 when it's connected via USB. - */ -const uint8_t PS3_ANALOG_BUTTONS[] PROGMEM = { - 23, // UP_ANALOG - 24, // RIGHT_ANALOG - 25, // DOWN_ANALOG - 26, // LEFT_ANALOG - 0, 0, 0, 0, // Skip SELECT, L3, R3 and START - - 27, // L2_ANALOG - 28, // R2_ANALOG - 29, // L1_ANALOG - 30, // R1_ANALOG - 31, // TRIANGLE_ANALOG - 32, // CIRCLE_ANALOG - 33, // CROSS_ANALOG - 34, // SQUARE_ANALOG - 0, 0, // Skip PS and MOVE - - // Playstation Move Controller - 15, // T_ANALOG - Both at byte 14 (last reading) and byte 15 (current reading) -}; - -enum StatusEnum { - // Note that the location is shifted 9 when it's connected via USB - // Byte location | bit location - Plugged = (38 << 8) | 0x02, - Unplugged = (38 << 8) | 0x03, - - Charging = (39 << 8) | 0xEE, - NotCharging = (39 << 8) | 0xF1, - Shutdown = (39 << 8) | 0x01, - Dying = (39 << 8) | 0x02, - Low = (39 << 8) | 0x03, - High = (39 << 8) | 0x04, - Full = (39 << 8) | 0x05, - - MoveCharging = (21 << 8) | 0xEE, - MoveNotCharging = (21 << 8) | 0xF1, - MoveShutdown = (21 << 8) | 0x01, - MoveDying = (21 << 8) | 0x02, - MoveLow = (21 << 8) | 0x03, - MoveHigh = (21 << 8) | 0x04, - MoveFull = (21 << 8) | 0x05, - - CableRumble = (40 << 8) | 0x10, // Operating by USB and rumble is turned on - Cable = (40 << 8) | 0x12, // Operating by USB and rumble is turned off - BluetoothRumble = (40 << 8) | 0x14, // Operating by Bluetooth and rumble is turned on - Bluetooth = (40 << 8) | 0x16, // Operating by Bluetooth and rumble is turned off -}; - -#endif diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3USB.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3USB.cpp deleted file mode 100755 index c32175389c..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3USB.cpp +++ /dev/null @@ -1,572 +0,0 @@ -/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. - - This software may be distributed and modified under the terms of the GNU - General Public License version 2 (GPL2) as published by the Free Software - Foundation and appearing in the file GPL2.TXT included in the packaging of - this file. Please note that GPL2 Section 2[b] requires that all works based - on this software must also be made publicly available under the terms of - the GPL2 ("Copyleft"). - - Contact information - ------------------- - - Kristian Lauszus, TKJ Electronics - Web : http://www.tkjelectronics.com - e-mail : kristianl@tkjelectronics.com - */ - -#include "PS3USB.h" -// To enable serial debugging see "settings.h" -//#define EXTRADEBUG // Uncomment to get even more debugging data -//#define PRINTREPORT // Uncomment to print the report send by the PS3 Controllers - -PS3USB::PS3USB(USB *p, uint8_t btadr5, uint8_t btadr4, uint8_t btadr3, uint8_t btadr2, uint8_t btadr1, uint8_t btadr0) : -pUsb(p), // pointer to USB class instance - mandatory -bAddress(0), // device address - mandatory -bPollEnable(false) // don't start polling before dongle is connected -{ - for(uint8_t i = 0; i < PS3_MAX_ENDPOINTS; i++) { - epInfo[i].epAddr = 0; - epInfo[i].maxPktSize = (i) ? 0 : 8; - epInfo[i].epAttribs = 0; - epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; - } - - if(pUsb) // register in USB subsystem - pUsb->RegisterDeviceClass(this); //set devConfig[] entry - - my_bdaddr[5] = btadr5; // Change to your dongle's Bluetooth address instead - my_bdaddr[4] = btadr4; - my_bdaddr[3] = btadr3; - my_bdaddr[2] = btadr2; - my_bdaddr[1] = btadr1; - my_bdaddr[0] = btadr0; -} - -uint8_t PS3USB::Init(uint8_t parent, uint8_t port, bool lowspeed) { - uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)]; - USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); - uint8_t rcode; - UsbDevice *p = NULL; - EpInfo *oldep_ptr = NULL; - uint16_t PID; - uint16_t VID; - - // get memory address of USB device address pool - AddressPool &addrPool = pUsb->GetAddressPool(); -#ifdef EXTRADEBUG - Notify(PSTR("\r\nPS3USB Init"), 0x80); -#endif - // check if address has already been assigned to an instance - if(bAddress) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nAddress in use"), 0x80); -#endif - return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; - } - - // Get pointer to pseudo device with address 0 assigned - p = addrPool.GetUsbDevicePtr(0); - - if(!p) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nAddress not found"), 0x80); -#endif - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - } - - if(!p->epinfo) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nepinfo is null"), 0x80); -#endif - return USB_ERROR_EPINFO_IS_NULL; - } - - // Save old pointer to EP_RECORD of address 0 - oldep_ptr = p->epinfo; - - // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence - p->epinfo = epInfo; - - p->lowspeed = lowspeed; - - // Get device descriptor - rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data - // Restore p->epinfo - p->epinfo = oldep_ptr; - - if(rcode) - goto FailGetDevDescr; - - VID = udd->idVendor; - PID = udd->idProduct; - - if(VID != PS3_VID || (PID != PS3_PID && PID != PS3NAVIGATION_PID && PID != PS3MOVE_PID)) - goto FailUnknownDevice; - - // Allocate new address according to device class - bAddress = addrPool.AllocAddress(parent, false, port); - - if(!bAddress) - return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; - - // Extract Max Packet Size from device descriptor - epInfo[0].maxPktSize = udd->bMaxPacketSize0; - - // Assign new address to the device - rcode = pUsb->setAddr(0, 0, bAddress); - if(rcode) { - p->lowspeed = false; - addrPool.FreeAddress(bAddress); - bAddress = 0; -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nsetAddr: "), 0x80); - D_PrintHex (rcode, 0x80); -#endif - return rcode; - } -#ifdef EXTRADEBUG - Notify(PSTR("\r\nAddr: "), 0x80); - D_PrintHex (bAddress, 0x80); -#endif - //delay(300); // Spec says you should wait at least 200ms - - p->lowspeed = false; - - //get pointer to assigned address record - p = addrPool.GetUsbDevicePtr(bAddress); - if(!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - p->lowspeed = lowspeed; - - // Assign epInfo to epinfo pointer - only EP0 is known - rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); - if(rcode) - goto FailSetDevTblEntry; - - - /* The application will work in reduced host mode, so we can save program and data - memory space. After verifying the PID and VID we will use known values for the - configuration values for device, interface, endpoints and HID for the PS3 Controllers */ - - /* Initialize data structures for endpoints of device */ - epInfo[ PS3_OUTPUT_PIPE ].epAddr = 0x02; // PS3 output endpoint - epInfo[ PS3_OUTPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; - epInfo[ PS3_OUTPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints - epInfo[ PS3_OUTPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; - epInfo[ PS3_OUTPUT_PIPE ].bmSndToggle = 0; - epInfo[ PS3_OUTPUT_PIPE ].bmRcvToggle = 0; - epInfo[ PS3_INPUT_PIPE ].epAddr = 0x01; // PS3 report endpoint - epInfo[ PS3_INPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; - epInfo[ PS3_INPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints - epInfo[ PS3_INPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; - epInfo[ PS3_INPUT_PIPE ].bmSndToggle = 0; - epInfo[ PS3_INPUT_PIPE ].bmRcvToggle = 0; - - rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo); - if(rcode) - goto FailSetDevTblEntry; - - delay(200); //Give time for address change - - rcode = pUsb->setConf(bAddress, epInfo[ PS3_CONTROL_PIPE ].epAddr, 1); - if(rcode) - goto FailSetConfDescr; - - if(PID == PS3_PID || PID == PS3NAVIGATION_PID) { - if(PID == PS3_PID) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nDualshock 3 Controller Connected"), 0x80); -#endif - PS3Connected = true; - } else { // must be a navigation controller -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nNavigation Controller Connected"), 0x80); -#endif - PS3NavigationConnected = true; - } - enable_sixaxis(); // The PS3 controller needs a special command before it starts sending data - - // Needed for PS3 Dualshock and Navigation commands to work - for(uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++) - writeBuf[i] = pgm_read_byte(&PS3_REPORT_BUFFER[i]); - - for(uint8_t i = 6; i < 10; i++) - readBuf[i] = 0x7F; // Set the analog joystick values to center position - } else { // must be a Motion controller -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nMotion Controller Connected"), 0x80); -#endif - PS3MoveConnected = true; - writeBuf[0] = 0x02; // Set report ID, this is needed for Move commands to work - } - if(my_bdaddr[0] != 0x00 || my_bdaddr[1] != 0x00 || my_bdaddr[2] != 0x00 || my_bdaddr[3] != 0x00 || my_bdaddr[4] != 0x00 || my_bdaddr[5] != 0x00) { - if(PS3MoveConnected) - setMoveBdaddr(my_bdaddr); // Set internal Bluetooth address - else - setBdaddr(my_bdaddr); // Set internal Bluetooth address - -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nBluetooth Address was set to: "), 0x80); - for(int8_t i = 5; i > 0; i--) { - D_PrintHex (my_bdaddr[i], 0x80); - Notify(PSTR(":"), 0x80); - } - D_PrintHex (my_bdaddr[0], 0x80); -#endif - } - onInit(); - - bPollEnable = true; - Notify(PSTR("\r\n"), 0x80); - timer = millis(); - return 0; // Successful configuration - - /* Diagnostic messages */ -FailGetDevDescr: -#ifdef DEBUG_USB_HOST - NotifyFailGetDevDescr(); - goto Fail; -#endif - -FailSetDevTblEntry: -#ifdef DEBUG_USB_HOST - NotifyFailSetDevTblEntry(); - goto Fail; -#endif - -FailSetConfDescr: -#ifdef DEBUG_USB_HOST - NotifyFailSetConfDescr(); -#endif - goto Fail; - -FailUnknownDevice: -#ifdef DEBUG_USB_HOST - NotifyFailUnknownDevice(VID, PID); -#endif - rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - -Fail: -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nPS3 Init Failed, error code: "), 0x80); - NotifyFail(rcode); -#endif - Release(); - return rcode; -} - -/* Performs a cleanup after failed Init() attempt */ -uint8_t PS3USB::Release() { - PS3Connected = false; - PS3MoveConnected = false; - PS3NavigationConnected = false; - pUsb->GetAddressPool().FreeAddress(bAddress); - bAddress = 0; - bPollEnable = false; - return 0; -} - -uint8_t PS3USB::Poll() { - if(!bPollEnable) - return 0; - - if(PS3Connected || PS3NavigationConnected) { - uint16_t BUFFER_SIZE = EP_MAXPKTSIZE; - pUsb->inTransfer(bAddress, epInfo[ PS3_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf); // input on endpoint 1 - if(millis() - timer > 100) { // Loop 100ms before processing data - readReport(); -#ifdef PRINTREPORT - printReport(); // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers -#endif - } - } else if(PS3MoveConnected) { // One can only set the color of the bulb, set the rumble, set and get the bluetooth address and calibrate the magnetometer via USB - if(millis() - timer > 4000) { // Send at least every 4th second - Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE); // The Bulb and rumble values, has to be written again and again, for it to stay turned on - timer = millis(); - } - } - return 0; -} - -void PS3USB::readReport() { - ButtonState = (uint32_t)(readBuf[2] | ((uint16_t)readBuf[3] << 8) | ((uint32_t)readBuf[4] << 16)); - - //Notify(PSTR("\r\nButtonState", 0x80); - //PrintHex(ButtonState, 0x80); - - if(ButtonState != OldButtonState) { - ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable - OldButtonState = ButtonState; - } -} - -void PS3USB::printReport() { // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers -#ifdef PRINTREPORT - for(uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++) { - D_PrintHex (readBuf[i], 0x80); - Notify(PSTR(" "), 0x80); - } - Notify(PSTR("\r\n"), 0x80); -#endif -} - -bool PS3USB::getButtonPress(ButtonEnum b) { - return (ButtonState & pgm_read_dword(&PS3_BUTTONS[(uint8_t)b])); -} - -bool PS3USB::getButtonClick(ButtonEnum b) { - uint32_t button = pgm_read_dword(&PS3_BUTTONS[(uint8_t)b]); - bool click = (ButtonClickState & button); - ButtonClickState &= ~button; // Clear "click" event - return click; -} - -uint8_t PS3USB::getAnalogButton(ButtonEnum a) { - return (uint8_t)(readBuf[(pgm_read_byte(&PS3_ANALOG_BUTTONS[(uint8_t)a])) - 9]); -} - -uint8_t PS3USB::getAnalogHat(AnalogHatEnum a) { - return (uint8_t)(readBuf[((uint8_t)a + 6)]); -} - -uint16_t PS3USB::getSensor(SensorEnum a) { - return ((readBuf[((uint16_t)a) - 9] << 8) | readBuf[((uint16_t)a + 1) - 9]); -} - -double PS3USB::getAngle(AngleEnum a) { - if(PS3Connected) { - double accXval; - double accYval; - double accZval; - - // Data for the Kionix KXPC4 used in the DualShock 3 - const double zeroG = 511.5; // 1.65/3.3*1023 (1,65V) - accXval = -((double)getSensor(aX) - zeroG); - accYval = -((double)getSensor(aY) - zeroG); - accZval = -((double)getSensor(aZ) - zeroG); - - // Convert to 360 degrees resolution - // atan2 outputs the value of -π to π (radians) - // We are then converting it to 0 to 2π and then to degrees - if(a == Pitch) - return (atan2(accYval, accZval) + PI) * RAD_TO_DEG; - else - return (atan2(accXval, accZval) + PI) * RAD_TO_DEG; - } else - return 0; -} - -bool PS3USB::getStatus(StatusEnum c) { - return (readBuf[((uint16_t)c >> 8) - 9] == ((uint8_t)c & 0xff)); -} - -void PS3USB::printStatusString() { - char statusOutput[100]; // Max string length plus null character - if(PS3Connected || PS3NavigationConnected) { - strcpy_P(statusOutput, PSTR("ConnectionStatus: ")); - - if(getStatus(Plugged)) strcat_P(statusOutput, PSTR("Plugged")); - else if(getStatus(Unplugged)) strcat_P(statusOutput, PSTR("Unplugged")); - else strcat_P(statusOutput, PSTR("Error")); - - strcat_P(statusOutput, PSTR(" - PowerRating: ")); - - if(getStatus(Charging)) strcat_P(statusOutput, PSTR("Charging")); - else if(getStatus(NotCharging)) strcat_P(statusOutput, PSTR("Not Charging")); - else if(getStatus(Shutdown)) strcat_P(statusOutput, PSTR("Shutdown")); - else if(getStatus(Dying)) strcat_P(statusOutput, PSTR("Dying")); - else if(getStatus(Low)) strcat_P(statusOutput, PSTR("Low")); - else if(getStatus(High)) strcat_P(statusOutput, PSTR("High")); - else if(getStatus(Full)) strcat_P(statusOutput, PSTR("Full")); - else strcat_P(statusOutput, PSTR("Error")); - - strcat_P(statusOutput, PSTR(" - WirelessStatus: ")); - - if(getStatus(CableRumble)) strcat_P(statusOutput, PSTR("Cable - Rumble is on")); - else if(getStatus(Cable)) strcat_P(statusOutput, PSTR("Cable - Rumble is off")); - else if(getStatus(BluetoothRumble)) strcat_P(statusOutput, PSTR("Bluetooth - Rumble is on")); - else if(getStatus(Bluetooth)) strcat_P(statusOutput, PSTR("Bluetooth - Rumble is off")); - else strcat_P(statusOutput, PSTR("Error")); - } else - strcpy_P(statusOutput, PSTR("Error")); - - USB_HOST_SERIAL.write(statusOutput); -} - -/* Playstation Sixaxis Dualshock and Navigation Controller commands */ -void PS3USB::PS3_Command(uint8_t *data, uint16_t nbytes) { - // bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x01), Report Type (Output 0x02), interface (0x00), datalength, datalength, data) - pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x01, 0x02, 0x00, nbytes, nbytes, data, NULL); -} - -void PS3USB::setAllOff() { - for(uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++) - writeBuf[i] = pgm_read_byte(&PS3_REPORT_BUFFER[i]); // Reset buffer - - PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); -} - -void PS3USB::setRumbleOff() { - writeBuf[1] = 0x00; - writeBuf[2] = 0x00; // Low mode off - writeBuf[3] = 0x00; - writeBuf[4] = 0x00; // High mode off - - PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); -} - -void PS3USB::setRumbleOn(RumbleEnum mode) { - if((mode & 0x30) > 0x00) { - uint8_t power[2] = {0xff, 0x00}; // Defaults to RumbleLow - if(mode == RumbleHigh) { - power[0] = 0x00; - power[1] = 0xff; - } - setRumbleOn(0xfe, power[0], 0xfe, power[1]); - } -} - -void PS3USB::setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower) { - writeBuf[1] = rightDuration; - writeBuf[2] = rightPower; - writeBuf[3] = leftDuration; - writeBuf[4] = leftPower; - PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); -} - -void PS3USB::setLedRaw(uint8_t value) { - writeBuf[9] = value << 1; - PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); -} - -void PS3USB::setLedOff(LEDEnum a) { - writeBuf[9] &= ~((uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1)); - PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); -} - -void PS3USB::setLedOn(LEDEnum a) { - if(a == OFF) - setLedRaw(0); - else { - writeBuf[9] |= (uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1); - PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); - } -} - -void PS3USB::setLedToggle(LEDEnum a) { - writeBuf[9] ^= (uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1); - PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); -} - -void PS3USB::setBdaddr(uint8_t *bdaddr) { - /* Set the internal Bluetooth address */ - uint8_t buf[8]; - buf[0] = 0x01; - buf[1] = 0x00; - - for(uint8_t i = 0; i < 6; i++) - buf[i + 2] = bdaddr[5 - i]; // Copy into buffer, has to be written reversed, so it is MSB first - - // bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF5), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data - pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL); -} - -void PS3USB::getBdaddr(uint8_t *bdaddr) { - uint8_t buf[8]; - - // bmRequest = Device to host (0x80) | Class (0x20) | Interface (0x01) = 0xA1, bRequest = Get Report (0x01), Report ID (0xF5), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data - pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL); - - for(uint8_t i = 0; i < 6; i++) - bdaddr[5 - i] = buf[i + 2]; // Copy into buffer reversed, so it is LSB first -} - -void PS3USB::enable_sixaxis() { // Command used to enable the Dualshock 3 and Navigation controller to send data via USB - uint8_t cmd_buf[4]; - cmd_buf[0] = 0x42; // Special PS3 Controller enable commands - cmd_buf[1] = 0x0c; - cmd_buf[2] = 0x00; - cmd_buf[3] = 0x00; - - // bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF4), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data) - pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF4, 0x03, 0x00, 4, 4, cmd_buf, NULL); -} - -/* Playstation Move Controller commands */ -void PS3USB::Move_Command(uint8_t *data, uint16_t nbytes) { - pUsb->outTransfer(bAddress, epInfo[ PS3_OUTPUT_PIPE ].epAddr, nbytes, data); -} - -void PS3USB::moveSetBulb(uint8_t r, uint8_t g, uint8_t b) { // Use this to set the Color using RGB values - // Set the Bulb's values into the write buffer - writeBuf[2] = r; - writeBuf[3] = g; - writeBuf[4] = b; - - Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE); -} - -void PS3USB::moveSetBulb(ColorsEnum color) { // Use this to set the Color using the predefined colors in "enums.h" - moveSetBulb((uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color)); -} - -void PS3USB::moveSetRumble(uint8_t rumble) { -#ifdef DEBUG_USB_HOST - if(rumble < 64 && rumble != 0) // The rumble value has to at least 64, or approximately 25% (64/255*100) - Notify(PSTR("\r\nThe rumble value has to at least 64, or approximately 25%"), 0x80); -#endif - writeBuf[6] = rumble; // Set the rumble value into the write buffer - - Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE); -} - -void PS3USB::setMoveBdaddr(uint8_t *bdaddr) { - /* Set the internal Bluetooth address */ - uint8_t buf[11]; - buf[0] = 0x05; - buf[7] = 0x10; - buf[8] = 0x01; - buf[9] = 0x02; - buf[10] = 0x12; - - for(uint8_t i = 0; i < 6; i++) - buf[i + 1] = bdaddr[i]; - - // bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x05), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data - pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x05, 0x03, 0x00, 11, 11, buf, NULL); -} - -void PS3USB::getMoveBdaddr(uint8_t *bdaddr) { - uint8_t buf[16]; - - // bmRequest = Device to host (0x80) | Class (0x20) | Interface (0x01) = 0xA1, bRequest = Get Report (0x01), Report ID (0x04), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data - pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, 0x04, 0x03, 0x00, 16, 16, buf, NULL); - - for(uint8_t i = 0; i < 6; i++) - bdaddr[i] = buf[10 + i]; -} - -void PS3USB::getMoveCalibration(uint8_t *data) { - uint8_t buf[49]; - - for(uint8_t i = 0; i < 3; i++) { - // bmRequest = Device to host (0x80) | Class (0x20) | Interface (0x01) = 0xA1, bRequest = Get Report (0x01), Report ID (0x10), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data - pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, 0x10, 0x03, 0x00, 49, 49, buf, NULL); - - for(byte j = 0; j < 49; j++) - data[49 * i + j] = buf[j]; - } -} - -void PS3USB::onInit() { - if(pFuncOnInit) - pFuncOnInit(); // Call the user function - else { - if(PS3MoveConnected) - moveSetBulb(Red); - else // Dualshock 3 or Navigation controller - setLedOn(LED1); - } -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3USB.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3USB.h deleted file mode 100644 index 2eba9258cf..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3USB.h +++ /dev/null @@ -1,303 +0,0 @@ -/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. - - This software may be distributed and modified under the terms of the GNU - General Public License version 2 (GPL2) as published by the Free Software - Foundation and appearing in the file GPL2.TXT included in the packaging of - this file. Please note that GPL2 Section 2[b] requires that all works based - on this software must also be made publicly available under the terms of - the GPL2 ("Copyleft"). - - Contact information - ------------------- - - Kristian Lauszus, TKJ Electronics - Web : http://www.tkjelectronics.com - e-mail : kristianl@tkjelectronics.com - */ - -#ifndef _ps3usb_h_ -#define _ps3usb_h_ - -#include "Usb.h" -#include "hid.h" -#include "PS3Enums.h" - -/* PS3 data taken from descriptors */ -#define EP_MAXPKTSIZE 64 // max size for data via USB - -/* Names we give to the 3 ps3 pipes - this is only used for setting the bluetooth address into the ps3 controllers */ -#define PS3_CONTROL_PIPE 0 -#define PS3_OUTPUT_PIPE 1 -#define PS3_INPUT_PIPE 2 - -//PID and VID of the different devices -#define PS3_VID 0x054C // Sony Corporation -#define PS3_PID 0x0268 // PS3 Controller DualShock 3 -#define PS3NAVIGATION_PID 0x042F // Navigation controller -#define PS3MOVE_PID 0x03D5 // Motion controller - -#define PS3_MAX_ENDPOINTS 3 - -/** - * This class implements support for all the official PS3 Controllers: - * Dualshock 3, Navigation or a Motion controller via USB. - * - * One can only set the color of the bulb, set the rumble, set and get the bluetooth address and calibrate the magnetometer via USB on the Move controller. - * - * Information about the protocol can be found at the wiki: https://github.com/felis/USB_Host_Shield_2.0/wiki/PS3-Information. - */ -class PS3USB : public USBDeviceConfig { -public: - /** - * Constructor for the PS3USB class. - * @param pUsb Pointer to USB class instance. - * @param btadr5,btadr4,btadr3,btadr2,btadr1,btadr0 - * Pass your dongles Bluetooth address into the constructor, - * so you are able to pair the controller with a Bluetooth dongle. - */ - PS3USB(USB *pUsb, uint8_t btadr5 = 0, uint8_t btadr4 = 0, uint8_t btadr3 = 0, uint8_t btadr2 = 0, uint8_t btadr1 = 0, uint8_t btadr0 = 0); - - /** @name USBDeviceConfig implementation */ - /** - * Initialize the PS3 Controller. - * @param parent Hub number. - * @param port Port number on the hub. - * @param lowspeed Speed of the device. - * @return 0 on success. - */ - uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); - /** - * Release the USB device. - * @return 0 on success. - */ - uint8_t Release(); - /** - * Poll the USB Input endpoins and run the state machines. - * @return 0 on success. - */ - uint8_t Poll(); - - /** - * Get the device address. - * @return The device address. - */ - virtual uint8_t GetAddress() { - return bAddress; - }; - - /** - * Used to check if the controller has been initialized. - * @return True if it's ready. - */ - virtual bool isReady() { - return bPollEnable; - }; - - /** - * Used by the USB core to check what this driver support. - * @param vid The device's VID. - * @param pid The device's PID. - * @return Returns true if the device's VID and PID matches this driver. - */ - virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) { - return (vid == PS3_VID && (pid == PS3_PID || pid == PS3NAVIGATION_PID || pid == PS3MOVE_PID)); - }; - /**@}*/ - - /** - * Used to set the Bluetooth address inside the Dualshock 3 and Navigation controller. - * Set using LSB first. - * @param bdaddr Your dongles Bluetooth address. - */ - void setBdaddr(uint8_t *bdaddr); - /** - * Used to get the Bluetooth address inside the Dualshock 3 and Navigation controller. - * Will return LSB first. - * @param bdaddr Your dongles Bluetooth address. - */ - void getBdaddr(uint8_t *bdaddr); - - /** - * Used to set the Bluetooth address inside the Move controller. - * Set using LSB first. - * @param bdaddr Your dongles Bluetooth address. - */ - void setMoveBdaddr(uint8_t *bdaddr); - /** - * Used to get the Bluetooth address inside the Move controller. - * Will return LSB first. - * @param bdaddr Your dongles Bluetooth address. - */ - void getMoveBdaddr(uint8_t *bdaddr); - /** - * Used to get the calibration data inside the Move controller. - * @param data Buffer to store data in. Must be at least 147 bytes - */ - void getMoveCalibration(uint8_t *data); - - /** @name PS3 Controller functions */ - /** - * getButtonPress(ButtonEnum b) will return true as long as the button is held down. - * - * While getButtonClick(ButtonEnum b) will only return it once. - * - * So you instance if you need to increase a variable once you would use getButtonClick(ButtonEnum b), - * but if you need to drive a robot forward you would use getButtonPress(ButtonEnum b). - * @param b ::ButtonEnum to read. - * @return getButtonPress(ButtonEnum b) will return a true as long as a button is held down, while getButtonClick(ButtonEnum b) will return true once for each button press. - */ - bool getButtonPress(ButtonEnum b); - bool getButtonClick(ButtonEnum b); - /**@}*/ - /** @name PS3 Controller functions */ - /** - * Used to get the analog value from button presses. - * @param a The ::ButtonEnum to read. - * The supported buttons are: - * ::UP, ::RIGHT, ::DOWN, ::LEFT, ::L1, ::L2, ::R1, ::R2, - * ::TRIANGLE, ::CIRCLE, ::CROSS, ::SQUARE, and ::T. - * @return Analog value in the range of 0-255. - */ - uint8_t getAnalogButton(ButtonEnum a); - /** - * Used to read the analog joystick. - * @param a ::LeftHatX, ::LeftHatY, ::RightHatX, and ::RightHatY. - * @return Return the analog value in the range of 0-255. - */ - uint8_t getAnalogHat(AnalogHatEnum a); - /** - * Used to read the sensors inside the Dualshock 3 controller. - * @param a - * The Dualshock 3 has a 3-axis accelerometer and a 1-axis gyro inside. - * @return Return the raw sensor value. - */ - uint16_t getSensor(SensorEnum a); - /** - * Use this to get ::Pitch and ::Roll calculated using the accelerometer. - * @param a Either ::Pitch or ::Roll. - * @return Return the angle in the range of 0-360. - */ - double getAngle(AngleEnum a); - /** - * Get the ::StatusEnum from the controller. - * @param c The ::StatusEnum you want to read. - * @return True if correct and false if not. - */ - bool getStatus(StatusEnum c); - /** Read all the available statuses from the controller and prints it as a nice formated string. */ - void printStatusString(); - - /** Used to set all LEDs and rumble off. */ - void setAllOff(); - /** Turn off rumble. */ - void setRumbleOff(); - /** - * Turn on rumble. - * @param mode Either ::RumbleHigh or ::RumbleLow. - */ - void setRumbleOn(RumbleEnum mode); - /** - * Turn on rumble using custom duration and power. - * @param rightDuration The duration of the right/low rumble effect. - * @param rightPower The intensity of the right/low rumble effect. - * @param leftDuration The duration of the left/high rumble effect. - * @param leftPower The intensity of the left/high rumble effect. - */ - void setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower); - - /** - * Set LED value without using the ::LEDEnum. - * @param value See: ::LEDEnum. - */ - void setLedRaw(uint8_t value); - - /** Turn all LEDs off. */ - void setLedOff() { - setLedRaw(0); - } - /** - * Turn the specific ::LEDEnum off. - * @param a The ::LEDEnum to turn off. - */ - void setLedOff(LEDEnum a); - /** - * Turn the specific ::LEDEnum on. - * @param a The ::LEDEnum to turn on. - */ - void setLedOn(LEDEnum a); - /** - * Toggle the specific ::LEDEnum. - * @param a The ::LEDEnum to toggle. - */ - void setLedToggle(LEDEnum a); - - /** - * Use this to set the Color using RGB values. - * @param r,g,b RGB value. - */ - void moveSetBulb(uint8_t r, uint8_t g, uint8_t b); - /** - * Use this to set the color using the predefined colors in ::ColorsEnum. - * @param color The desired color. - */ - void moveSetBulb(ColorsEnum color); - /** - * Set the rumble value inside the Move controller. - * @param rumble The desired value in the range from 64-255. - */ - void moveSetRumble(uint8_t rumble); - - /** - * Used to call your own function when the controller is successfully initialized. - * @param funcOnInit Function to call. - */ - void attachOnInit(void (*funcOnInit)(void)) { - pFuncOnInit = funcOnInit; - }; - /**@}*/ - - /** Variable used to indicate if the normal playstation controller is successfully connected. */ - bool PS3Connected; - /** Variable used to indicate if the move controller is successfully connected. */ - bool PS3MoveConnected; - /** Variable used to indicate if the navigation controller is successfully connected. */ - bool PS3NavigationConnected; - -protected: - /** Pointer to USB class instance. */ - USB *pUsb; - /** Device address. */ - uint8_t bAddress; - /** Endpoint info structure. */ - EpInfo epInfo[PS3_MAX_ENDPOINTS]; - -private: - /** - * Called when the controller is successfully initialized. - * Use attachOnInit(void (*funcOnInit)(void)) to call your own function. - * This is useful for instance if you want to set the LEDs in a specific way. - */ - void onInit(); - void (*pFuncOnInit)(void); // Pointer to function called in onInit() - - bool bPollEnable; - - uint32_t timer; // used to continuously set PS3 Move controller Bulb and rumble values - - uint32_t ButtonState; - uint32_t OldButtonState; - uint32_t ButtonClickState; - - uint8_t my_bdaddr[6]; // Change to your dongles Bluetooth address in the constructor - uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data - uint8_t writeBuf[EP_MAXPKTSIZE]; // General purpose buffer for output data - - void readReport(); // read incoming data - void printReport(); // print incoming date - Uncomment for debugging - - /* Private commands */ - void PS3_Command(uint8_t *data, uint16_t nbytes); - void enable_sixaxis(); // Command used to enable the Dualshock 3 and Navigation controller to send data via USB - void Move_Command(uint8_t *data, uint16_t nbytes); -}; -#endif diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS4BT.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS4BT.h deleted file mode 100644 index b7eb4b5a91..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS4BT.h +++ /dev/null @@ -1,121 +0,0 @@ -/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved. - - This software may be distributed and modified under the terms of the GNU - General Public License version 2 (GPL2) as published by the Free Software - Foundation and appearing in the file GPL2.TXT included in the packaging of - this file. Please note that GPL2 Section 2[b] requires that all works based - on this software must also be made publicly available under the terms of - the GPL2 ("Copyleft"). - - Contact information - ------------------- - - Kristian Lauszus, TKJ Electronics - Web : http://www.tkjelectronics.com - e-mail : kristianl@tkjelectronics.com - */ - -#ifndef _ps4bt_h_ -#define _ps4bt_h_ - -#include "BTHID.h" -#include "PS4Parser.h" - -/** - * This class implements support for the PS4 controller via Bluetooth. - * It uses the BTHID class for all the Bluetooth communication. - */ -class PS4BT : public BTHID, public PS4Parser { -public: - /** - * Constructor for the PS4BT class. - * @param p Pointer to the BTD class instance. - * @param pair Set this to true in order to pair with the device. If the argument is omitted then it will not pair with it. One can use ::PAIR to set it to true. - * @param pin Write the pin to BTD#btdPin. If argument is omitted, then "0000" will be used. - */ - PS4BT(BTD *p, bool pair = false, const char *pin = "0000") : - BTHID(p, pair, pin) { - PS4Parser::Reset(); - }; - - /** - * Used to check if a PS4 controller is connected. - * @return Returns true if it is connected. - */ - bool connected() { - return BTHID::connected; - }; - -protected: - /** @name BTHID implementation */ - /** - * Used to parse Bluetooth HID data. - * @param len The length of the incoming data. - * @param buf Pointer to the data buffer. - */ - virtual void ParseBTHIDData(uint8_t len, uint8_t *buf) { - PS4Parser::Parse(len, buf); - }; - - /** - * Called when a device is successfully initialized. - * Use attachOnInit(void (*funcOnInit)(void)) to call your own function. - * This is useful for instance if you want to set the LEDs in a specific way. - */ - virtual void OnInitBTHID() { - PS4Parser::Reset(); - enable_sixaxis(); // Make the controller send out the entire output report - if (pFuncOnInit) - pFuncOnInit(); // Call the user function - else - setLed(Blue); - }; - - /** Used to reset the different buffers to there default values */ - virtual void ResetBTHID() { - PS4Parser::Reset(); - }; - /**@}*/ - - /** @name PS4Parser implementation */ - virtual void sendOutputReport(PS4Output *output) { // Source: https://github.com/chrippa/ds4drv - uint8_t buf[79]; - memset(buf, 0, sizeof(buf)); - - buf[0] = 0x52; // HID BT Set_report (0x50) | Report Type (Output 0x02) - buf[1] = 0x11; // Report ID - buf[2] = 0x80; - buf[4]= 0xFF; - - buf[7] = output->smallRumble; // Small Rumble - buf[8] = output->bigRumble; // Big rumble - - buf[9] = output->r; // Red - buf[10] = output->g; // Green - buf[11] = output->b; // Blue - - buf[12] = output->flashOn; // Time to flash bright (255 = 2.5 seconds) - buf[13] = output->flashOff; // Time to flash dark (255 = 2.5 seconds) - - output->reportChanged = false; - - // The PS4 console actually set the four last bytes to a CRC32 checksum, but it seems like it is actually not needed - - HID_Command(buf, sizeof(buf)); - }; - /**@}*/ - -private: - void enable_sixaxis() { // Command used to make the PS4 controller send out the entire output report - uint8_t buf[2]; - buf[0] = 0x43; // HID BT Get_report (0x40) | Report Type (Feature 0x03) - buf[1] = 0x02; // Report ID - - HID_Command(buf, 2); - }; - - void HID_Command(uint8_t *data, uint8_t nbytes) { - pBtd->L2CAP_Command(hci_handle, data, nbytes, control_scid[0], control_scid[1]); - }; -}; -#endif diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS4Parser.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS4Parser.cpp deleted file mode 100644 index ca6adce403..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS4Parser.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved. - - This software may be distributed and modified under the terms of the GNU - General Public License version 2 (GPL2) as published by the Free Software - Foundation and appearing in the file GPL2.TXT included in the packaging of - this file. Please note that GPL2 Section 2[b] requires that all works based - on this software must also be made publicly available under the terms of - the GPL2 ("Copyleft"). - - Contact information - ------------------- - - Kristian Lauszus, TKJ Electronics - Web : http://www.tkjelectronics.com - e-mail : kristianl@tkjelectronics.com - */ - -#include "PS4Parser.h" - -// To enable serial debugging see "settings.h" -//#define PRINTREPORT // Uncomment to print the report send by the PS4 Controller - -bool PS4Parser::checkDpad(ButtonEnum b) { - switch (b) { - case UP: - return ps4Data.btn.dpad == DPAD_LEFT_UP || ps4Data.btn.dpad == DPAD_UP || ps4Data.btn.dpad == DPAD_UP_RIGHT; - case RIGHT: - return ps4Data.btn.dpad == DPAD_UP_RIGHT || ps4Data.btn.dpad == DPAD_RIGHT || ps4Data.btn.dpad == DPAD_RIGHT_DOWN; - case DOWN: - return ps4Data.btn.dpad == DPAD_RIGHT_DOWN || ps4Data.btn.dpad == DPAD_DOWN || ps4Data.btn.dpad == DPAD_DOWN_LEFT; - case LEFT: - return ps4Data.btn.dpad == DPAD_DOWN_LEFT || ps4Data.btn.dpad == DPAD_LEFT || ps4Data.btn.dpad == DPAD_LEFT_UP; - default: - return false; - } -} - -bool PS4Parser::getButtonPress(ButtonEnum b) { - if (b <= LEFT) // Dpad - return checkDpad(b); - else - return ps4Data.btn.val & (1UL << pgm_read_byte(&PS4_BUTTONS[(uint8_t)b])); -} - -bool PS4Parser::getButtonClick(ButtonEnum b) { - uint32_t mask = 1UL << pgm_read_byte(&PS4_BUTTONS[(uint8_t)b]); - bool click = buttonClickState.val & mask; - buttonClickState.val &= ~mask; // Clear "click" event - return click; -} - -uint8_t PS4Parser::getAnalogButton(ButtonEnum b) { - if (b == L2) // These are the only analog buttons on the controller - return ps4Data.trigger[0]; - else if (b == R2) - return ps4Data.trigger[1]; - return 0; -} - -uint8_t PS4Parser::getAnalogHat(AnalogHatEnum a) { - return ps4Data.hatValue[(uint8_t)a]; -} - -void PS4Parser::Parse(uint8_t len, uint8_t *buf) { - if (len > 1 && buf) { -#ifdef PRINTREPORT - Notify(PSTR("\r\n"), 0x80); - for (uint8_t i = 0; i < len; i++) { - D_PrintHex (buf[i], 0x80); - Notify(PSTR(" "), 0x80); - } -#endif - - if (buf[0] == 0x01) // Check report ID - memcpy(&ps4Data, buf + 1, min((uint8_t)(len - 1), sizeof(ps4Data))); - else if (buf[0] == 0x11) { // This report is send via Bluetooth, it has an offset of 2 compared to the USB data - if (len < 4) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nReport is too short: "), 0x80); - D_PrintHex (len, 0x80); -#endif - return; - } - memcpy(&ps4Data, buf + 3, min((uint8_t)(len - 3), sizeof(ps4Data))); - } else { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nUnknown report id: "), 0x80); - D_PrintHex (buf[0], 0x80); -#endif - return; - } - - if (ps4Data.btn.val != oldButtonState.val) { // Check if anything has changed - buttonClickState.val = ps4Data.btn.val & ~oldButtonState.val; // Update click state variable - oldButtonState.val = ps4Data.btn.val; - - // The DPAD buttons does not set the different bits, but set a value corresponding to the buttons pressed, we will simply set the bits ourself - uint8_t newDpad = 0; - if (checkDpad(UP)) - newDpad |= 1 << UP; - if (checkDpad(RIGHT)) - newDpad |= 1 << RIGHT; - if (checkDpad(DOWN)) - newDpad |= 1 << DOWN; - if (checkDpad(LEFT)) - newDpad |= 1 << LEFT; - if (newDpad != oldDpad) { - buttonClickState.dpad = newDpad & ~oldDpad; // Override values - oldDpad = newDpad; - } - } - } - - if (ps4Output.reportChanged) - sendOutputReport(&ps4Output); // Send output report -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS4Parser.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS4Parser.h deleted file mode 100644 index 51f0806361..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS4Parser.h +++ /dev/null @@ -1,407 +0,0 @@ -/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved. - - This software may be distributed and modified under the terms of the GNU - General Public License version 2 (GPL2) as published by the Free Software - Foundation and appearing in the file GPL2.TXT included in the packaging of - this file. Please note that GPL2 Section 2[b] requires that all works based - on this software must also be made publicly available under the terms of - the GPL2 ("Copyleft"). - - Contact information - ------------------- - - Kristian Lauszus, TKJ Electronics - Web : http://www.tkjelectronics.com - e-mail : kristianl@tkjelectronics.com - */ - -#ifndef _ps4parser_h_ -#define _ps4parser_h_ - -#include "Usb.h" -#include "controllerEnums.h" - -/** Buttons on the controller */ -const uint8_t PS4_BUTTONS[] PROGMEM = { - UP, // UP - RIGHT, // RIGHT - DOWN, // DOWN - LEFT, // LEFT - - 0x0C, // SHARE - 0x0D, // OPTIONS - 0x0E, // L3 - 0x0F, // R3 - - 0x0A, // L2 - 0x0B, // R2 - 0x08, // L1 - 0x09, // R1 - - 0x07, // TRIANGLE - 0x06, // CIRCLE - 0x05, // CROSS - 0x04, // SQUARE - - 0x10, // PS - 0x11, // TOUCHPAD -}; - -union PS4Buttons { - struct { - uint8_t dpad : 4; - uint8_t square : 1; - uint8_t cross : 1; - uint8_t circle : 1; - uint8_t triangle : 1; - - uint8_t l1 : 1; - uint8_t r1 : 1; - uint8_t l2 : 1; - uint8_t r2 : 1; - uint8_t share : 1; - uint8_t options : 1; - uint8_t l3 : 1; - uint8_t r3 : 1; - - uint8_t ps : 1; - uint8_t touchpad : 1; - uint8_t reportCounter : 6; - } __attribute__((packed)); - uint32_t val : 24; -} __attribute__((packed)); - -struct touchpadXY { - uint8_t dummy; // I can not figure out what this data is for, it seems to change randomly, maybe a timestamp? - struct { - uint8_t counter : 7; // Increments every time a finger is touching the touchpad - uint8_t touching : 1; // The top bit is cleared if the finger is touching the touchpad - uint16_t x : 12; - uint16_t y : 12; - } __attribute__((packed)) finger[2]; // 0 = first finger, 1 = second finger -} __attribute__((packed)); - -struct PS4Status { - uint8_t battery : 4; - uint8_t usb : 1; - uint8_t audio : 1; - uint8_t mic : 1; - uint8_t unknown : 1; // Extension port? -} __attribute__((packed)); - -struct PS4Data { - /* Button and joystick values */ - uint8_t hatValue[4]; - PS4Buttons btn; - uint8_t trigger[2]; - - /* Gyro and accelerometer values */ - uint8_t dummy[3]; // First two looks random, while the third one might be some kind of status - it increments once in a while - int16_t gyroY, gyroZ, gyroX; - int16_t accX, accZ, accY; - - uint8_t dummy2[5]; - PS4Status status; - uint8_t dummy3[3]; - - /* The rest is data for the touchpad */ - touchpadXY xy[3]; // It looks like it sends out three coordinates each time, this might be because the microcontroller inside the PS4 controller is much faster than the Bluetooth connection. - // The last data is read from the last position in the array while the oldest measurement is from the first position. - // The first position will also keep it's value after the finger is released, while the other two will set them to zero. - // Note that if you read fast enough from the device, then only the first one will contain any data. - - // The last three bytes are always: 0x00, 0x80, 0x00 -} __attribute__((packed)); - -struct PS4Output { - uint8_t bigRumble, smallRumble; // Rumble - uint8_t r, g, b; // RGB - uint8_t flashOn, flashOff; // Time to flash bright/dark (255 = 2.5 seconds) - bool reportChanged; // The data is send when data is received from the controller -} __attribute__((packed)); - -enum DPADEnum { - DPAD_UP = 0x0, - DPAD_UP_RIGHT = 0x1, - DPAD_RIGHT = 0x2, - DPAD_RIGHT_DOWN = 0x3, - DPAD_DOWN = 0x4, - DPAD_DOWN_LEFT = 0x5, - DPAD_LEFT = 0x6, - DPAD_LEFT_UP = 0x7, - DPAD_OFF = 0x8, -}; - -/** This class parses all the data sent by the PS4 controller */ -class PS4Parser { -public: - /** Constructor for the PS4Parser class. */ - PS4Parser() { - Reset(); - }; - - /** @name PS4 Controller functions */ - /** - * getButtonPress(ButtonEnum b) will return true as long as the button is held down. - * - * While getButtonClick(ButtonEnum b) will only return it once. - * - * So you instance if you need to increase a variable once you would use getButtonClick(ButtonEnum b), - * but if you need to drive a robot forward you would use getButtonPress(ButtonEnum b). - * @param b ::ButtonEnum to read. - * @return getButtonPress(ButtonEnum b) will return a true as long as a button is held down, while getButtonClick(ButtonEnum b) will return true once for each button press. - */ - bool getButtonPress(ButtonEnum b); - bool getButtonClick(ButtonEnum b); - /**@}*/ - /** @name PS4 Controller functions */ - /** - * Used to get the analog value from button presses. - * @param b The ::ButtonEnum to read. - * The supported buttons are: - * ::UP, ::RIGHT, ::DOWN, ::LEFT, ::L1, ::L2, ::R1, ::R2, - * ::TRIANGLE, ::CIRCLE, ::CROSS, ::SQUARE, and ::T. - * @return Analog value in the range of 0-255. - */ - uint8_t getAnalogButton(ButtonEnum b); - - /** - * Used to read the analog joystick. - * @param a ::LeftHatX, ::LeftHatY, ::RightHatX, and ::RightHatY. - * @return Return the analog value in the range of 0-255. - */ - uint8_t getAnalogHat(AnalogHatEnum a); - - /** - * Get the x-coordinate of the touchpad. Position 0 is in the top left. - * @param finger 0 = first finger, 1 = second finger. If omitted, then 0 will be used. - * @param xyId The controller sends out three packets with the same structure. - * The third one will contain the last measure, but if you read from the controller then there is only be data in the first one. - * For that reason it will be set to 0 if the argument is omitted. - * @return Returns the x-coordinate of the finger. - */ - uint16_t getX(uint8_t finger = 0, uint8_t xyId = 0) { - return ps4Data.xy[xyId].finger[finger].x; - }; - - /** - * Get the y-coordinate of the touchpad. Position 0 is in the top left. - * @param finger 0 = first finger, 1 = second finger. If omitted, then 0 will be used. - * @param xyId The controller sends out three packets with the same structure. - * The third one will contain the last measure, but if you read from the controller then there is only be data in the first one. - * For that reason it will be set to 0 if the argument is omitted. - * @return Returns the y-coordinate of the finger. - */ - uint16_t getY(uint8_t finger = 0, uint8_t xyId = 0) { - return ps4Data.xy[xyId].finger[finger].y; - }; - - /** - * Returns whenever the user is toucing the touchpad. - * @param finger 0 = first finger, 1 = second finger. If omitted, then 0 will be used. - * @param xyId The controller sends out three packets with the same structure. - * The third one will contain the last measure, but if you read from the controller then there is only be data in the first one. - * For that reason it will be set to 0 if the argument is omitted. - * @return Returns true if the specific finger is touching the touchpad. - */ - bool isTouching(uint8_t finger = 0, uint8_t xyId = 0) { - return !(ps4Data.xy[xyId].finger[finger].touching); // The bit is cleared when a finger is touching the touchpad - }; - - /** - * This counter increments every time a finger touches the touchpad. - * @param finger 0 = first finger, 1 = second finger. If omitted, then 0 will be used. - * @param xyId The controller sends out three packets with the same structure. - * The third one will contain the last measure, but if you read from the controller then there is only be data in the first one. - * For that reason it will be set to 0 if the argument is omitted. - * @return Return the value of the counter, note that it is only a 7-bit value. - */ - uint8_t getTouchCounter(uint8_t finger = 0, uint8_t xyId = 0) { - return ps4Data.xy[xyId].finger[finger].counter; - }; - - /** - * Get the angle of the controller calculated using the accelerometer. - * @param a Either ::Pitch or ::Roll. - * @return Return the angle in the range of 0-360. - */ - double getAngle(AngleEnum a) { - if (a == Pitch) - return (atan2(ps4Data.accY, ps4Data.accZ) + PI) * RAD_TO_DEG; - else - return (atan2(ps4Data.accX, ps4Data.accZ) + PI) * RAD_TO_DEG; - }; - - /** - * Used to get the raw values from the 3-axis gyroscope and 3-axis accelerometer inside the PS4 controller. - * @param s The sensor to read. - * @return Returns the raw sensor reading. - */ - int16_t getSensor(SensorEnum s) { - switch(s) { - case gX: - return ps4Data.gyroX; - case gY: - return ps4Data.gyroY; - case gZ: - return ps4Data.gyroZ; - case aX: - return ps4Data.accX; - case aY: - return ps4Data.accY; - case aZ: - return ps4Data.accZ; - default: - return 0; - } - }; - - /** - * Return the battery level of the PS4 controller. - * @return The battery level in the range 0-15. - */ - uint8_t getBatteryLevel() { - return ps4Data.status.battery; - }; - - /** - * Use this to check if an USB cable is connected to the PS4 controller. - * @return Returns true if an USB cable is connected. - */ - bool getUsbStatus() { - return ps4Data.status.usb; - }; - - /** - * Use this to check if an audio jack cable is connected to the PS4 controller. - * @return Returns true if an audio jack cable is connected. - */ - bool getAudioStatus() { - return ps4Data.status.audio; - }; - - /** - * Use this to check if a microphone is connected to the PS4 controller. - * @return Returns true if a microphone is connected. - */ - bool getMicStatus() { - return ps4Data.status.mic; - }; - - /** Turn both rumble and the LEDs off. */ - void setAllOff() { - setRumbleOff(); - setLedOff(); - }; - - /** Set rumble off. */ - void setRumbleOff() { - setRumbleOn(0, 0); - }; - - /** - * Turn on rumble. - * @param mode Either ::RumbleHigh or ::RumbleLow. - */ - void setRumbleOn(RumbleEnum mode) { - if (mode == RumbleLow) - setRumbleOn(0x00, 0xFF); - else - setRumbleOn(0xFF, 0x00); - }; - - /** - * Turn on rumble. - * @param bigRumble Value for big motor. - * @param smallRumble Value for small motor. - */ - void setRumbleOn(uint8_t bigRumble, uint8_t smallRumble) { - ps4Output.bigRumble = bigRumble; - ps4Output.smallRumble = smallRumble; - ps4Output.reportChanged = true; - }; - - /** Turn all LEDs off. */ - void setLedOff() { - setLed(0, 0, 0); - }; - - /** - * Use this to set the color using RGB values. - * @param r,g,b RGB value. - */ - void setLed(uint8_t r, uint8_t g, uint8_t b) { - ps4Output.r = r; - ps4Output.g = g; - ps4Output.b = b; - ps4Output.reportChanged = true; - }; - - /** - * Use this to set the color using the predefined colors in ::ColorsEnum. - * @param color The desired color. - */ - void setLed(ColorsEnum color) { - setLed((uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color)); - }; - - /** - * Set the LEDs flash time. - * @param flashOn Time to flash bright (255 = 2.5 seconds). - * @param flashOff Time to flash dark (255 = 2.5 seconds). - */ - void setLedFlash(uint8_t flashOn, uint8_t flashOff) { - ps4Output.flashOn = flashOn; - ps4Output.flashOff = flashOff; - ps4Output.reportChanged = true; - }; - /**@}*/ - -protected: - /** - * Used to parse data sent from the PS4 controller. - * @param len Length of the data. - * @param buf Pointer to the data buffer. - */ - void Parse(uint8_t len, uint8_t *buf); - - /** Used to reset the different buffers to their default values */ - void Reset() { - uint8_t i; - for (i = 0; i < sizeof(ps4Data.hatValue); i++) - ps4Data.hatValue[i] = 127; // Center value - ps4Data.btn.val = 0; - oldButtonState.val = 0; - for (i = 0; i < sizeof(ps4Data.trigger); i++) - ps4Data.trigger[i] = 0; - for (i = 0; i < sizeof(ps4Data.xy)/sizeof(ps4Data.xy[0]); i++) { - for (uint8_t j = 0; j < sizeof(ps4Data.xy[0].finger)/sizeof(ps4Data.xy[0].finger[0]); j++) - ps4Data.xy[i].finger[j].touching = 1; // The bit is cleared if the finger is touching the touchpad - } - - ps4Data.btn.dpad = DPAD_OFF; - oldButtonState.dpad = DPAD_OFF; - buttonClickState.dpad = 0; - oldDpad = 0; - - ps4Output.bigRumble = ps4Output.smallRumble = 0; - ps4Output.r = ps4Output.g = ps4Output.b = 0; - ps4Output.flashOn = ps4Output.flashOff = 0; - ps4Output.reportChanged = false; - }; - - /** - * Send the output to the PS4 controller. This is implemented in PS4BT.h and PS4USB.h. - * @param output Pointer to PS4Output buffer; - */ - virtual void sendOutputReport(PS4Output *output) = 0; - -private: - bool checkDpad(ButtonEnum b); // Used to check PS4 DPAD buttons - - PS4Data ps4Data; - PS4Buttons oldButtonState, buttonClickState; - PS4Output ps4Output; - uint8_t oldDpad; -}; -#endif diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS4USB.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS4USB.h deleted file mode 100644 index b43079a6e9..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS4USB.h +++ /dev/null @@ -1,130 +0,0 @@ -/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved. - - This software may be distributed and modified under the terms of the GNU - General Public License version 2 (GPL2) as published by the Free Software - Foundation and appearing in the file GPL2.TXT included in the packaging of - this file. Please note that GPL2 Section 2[b] requires that all works based - on this software must also be made publicly available under the terms of - the GPL2 ("Copyleft"). - - Contact information - ------------------- - - Kristian Lauszus, TKJ Electronics - Web : http://www.tkjelectronics.com - e-mail : kristianl@tkjelectronics.com - */ - -#ifndef _ps4usb_h_ -#define _ps4usb_h_ - -#include "hiduniversal.h" -#include "PS4Parser.h" - -#define PS4_VID 0x054C // Sony Corporation -#define PS4_PID 0x05C4 // PS4 Controller - -/** - * This class implements support for the PS4 controller via USB. - * It uses the HIDUniversal class for all the USB communication. - */ -class PS4USB : public HIDUniversal, public PS4Parser { -public: - /** - * Constructor for the PS4USB class. - * @param p Pointer to the USB class instance. - */ - PS4USB(USB *p) : - HIDUniversal(p) { - PS4Parser::Reset(); - }; - - /** - * Used to check if a PS4 controller is connected. - * @return Returns true if it is connected. - */ - bool connected() { - return HIDUniversal::isReady() && HIDUniversal::VID == PS4_VID && HIDUniversal::PID == PS4_PID; - }; - - /** - * Used to call your own function when the device is successfully initialized. - * @param funcOnInit Function to call. - */ - void attachOnInit(void (*funcOnInit)(void)) { - pFuncOnInit = funcOnInit; - }; - -protected: - /** @name HIDUniversal implementation */ - /** - * Used to parse USB HID data. - * @param hid Pointer to the HID class. - * @param is_rpt_id Only used for Hubs. - * @param len The length of the incoming data. - * @param buf Pointer to the data buffer. - */ - virtual void ParseHIDData(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) { - if (HIDUniversal::VID == PS4_VID && HIDUniversal::PID == PS4_PID) - PS4Parser::Parse(len, buf); - }; - - /** - * Called when a device is successfully initialized. - * Use attachOnInit(void (*funcOnInit)(void)) to call your own function. - * This is useful for instance if you want to set the LEDs in a specific way. - */ - virtual uint8_t OnInitSuccessful() { - if (HIDUniversal::VID == PS4_VID && HIDUniversal::PID == PS4_PID) { - PS4Parser::Reset(); - if (pFuncOnInit) - pFuncOnInit(); // Call the user function - else - setLed(Blue); - }; - return 0; - }; - /**@}*/ - - /** @name PS4Parser implementation */ - virtual void sendOutputReport(PS4Output *output) { // Source: https://github.com/chrippa/ds4drv - uint8_t buf[32]; - memset(buf, 0, sizeof(buf)); - - buf[0] = 0x05; // Report ID - buf[1]= 0xFF; - - buf[4] = output->smallRumble; // Small Rumble - buf[5] = output->bigRumble; // Big rumble - - buf[6] = output->r; // Red - buf[7] = output->g; // Green - buf[8] = output->b; // Blue - - buf[9] = output->flashOn; // Time to flash bright (255 = 2.5 seconds) - buf[10] = output->flashOff; // Time to flash dark (255 = 2.5 seconds) - - output->reportChanged = false; - - // The PS4 console actually set the four last bytes to a CRC32 checksum, but it seems like it is actually not needed - - pUsb->outTransfer(bAddress, epInfo[ hidInterfaces[0].epIndex[epInterruptOutIndex] ].epAddr, sizeof(buf), buf); - }; - /**@}*/ - - /** @name USBDeviceConfig implementation */ - /** - * Used by the USB core to check what this driver support. - * @param vid The device's VID. - * @param pid The device's PID. - * @return Returns true if the device's VID and PID matches this driver. - */ - virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) { - return (vid == PS4_VID && pid == PS4_PID); - }; - /**@}*/ - -private: - void (*pFuncOnInit)(void); // Pointer to function called in onInit() -}; -#endif diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PSBuzz.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PSBuzz.cpp deleted file mode 100644 index 498164d5a6..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PSBuzz.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved. - - This software may be distributed and modified under the terms of the GNU - General Public License version 2 (GPL2) as published by the Free Software - Foundation and appearing in the file GPL2.TXT included in the packaging of - this file. Please note that GPL2 Section 2[b] requires that all works based - on this software must also be made publicly available under the terms of - the GPL2 ("Copyleft"). - - Contact information - ------------------- - - Kristian Lauszus, TKJ Electronics - Web : http://www.tkjelectronics.com - e-mail : kristianl@tkjelectronics.com - */ - -#include "PSBuzz.h" - -// To enable serial debugging see "settings.h" -//#define PRINTREPORT // Uncomment to print the report send by the PS Buzz Controllers - -void PSBuzz::ParseHIDData(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) { - if (HIDUniversal::VID == PSBUZZ_VID && HIDUniversal::PID == PSBUZZ_PID && len > 2 && buf) { -#ifdef PRINTREPORT - Notify(PSTR("\r\n"), 0x80); - for (uint8_t i = 0; i < len; i++) { - D_PrintHex (buf[i], 0x80); - Notify(PSTR(" "), 0x80); - } -#endif - memcpy(&psbuzzButtons, buf + 2, min((uint8_t)(len - 2), sizeof(psbuzzButtons))); - - if (psbuzzButtons.val != oldButtonState.val) { // Check if anything has changed - buttonClickState.val = psbuzzButtons.val & ~oldButtonState.val; // Update click state variable - oldButtonState.val = psbuzzButtons.val; - } - } -}; - -uint8_t PSBuzz::OnInitSuccessful() { - if (HIDUniversal::VID == PSBUZZ_VID && HIDUniversal::PID == PSBUZZ_PID) { - Reset(); - if (pFuncOnInit) - pFuncOnInit(); // Call the user function - else - setLedOnAll(); // Turn the LED on, on all four controllers - }; - return 0; -}; - -bool PSBuzz::getButtonPress(ButtonEnum b, uint8_t controller) { - return psbuzzButtons.val & (1UL << (b + 5 * controller)); // Each controller uses 5 bits, so the value is shifted 5 for each controller -}; - -bool PSBuzz::getButtonClick(ButtonEnum b, uint8_t controller) { - uint32_t mask = (1UL << (b + 5 * controller)); // Each controller uses 5 bits, so the value is shifted 5 for each controller - bool click = buttonClickState.val & mask; - buttonClickState.val &= ~mask; // Clear "click" event - return click; -}; - -// Source: http://www.developerfusion.com/article/84338/making-usb-c-friendly/ and https://github.com/torvalds/linux/blob/master/drivers/hid/hid-sony.c -void PSBuzz::setLedRaw(bool value, uint8_t controller) { - ledState[controller] = value; // Save value for next time it is called - - uint8_t buf[7]; - buf[0] = 0x00; - buf[1] = ledState[0] ? 0xFF : 0x00; - buf[2] = ledState[1] ? 0xFF : 0x00; - buf[3] = ledState[2] ? 0xFF : 0x00; - buf[4] = ledState[3] ? 0xFF : 0x00; - buf[5] = 0x00; - buf[6] = 0x00; - - PSBuzz_Command(buf, sizeof(buf)); -}; - -void PSBuzz::PSBuzz_Command(uint8_t *data, uint16_t nbytes) { - // bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x00), Report Type (Output 0x02), interface (0x00), datalength, datalength, data) - pUsb->ctrlReq(bAddress, epInfo[0].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x00, 0x02, 0x00, nbytes, nbytes, data, NULL); -}; diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PSBuzz.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PSBuzz.h deleted file mode 100644 index 8880d9e50a..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PSBuzz.h +++ /dev/null @@ -1,185 +0,0 @@ -/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved. - - This software may be distributed and modified under the terms of the GNU - General Public License version 2 (GPL2) as published by the Free Software - Foundation and appearing in the file GPL2.TXT included in the packaging of - this file. Please note that GPL2 Section 2[b] requires that all works based - on this software must also be made publicly available under the terms of - the GPL2 ("Copyleft"). - - Contact information - ------------------- - - Kristian Lauszus, TKJ Electronics - Web : http://www.tkjelectronics.com - e-mail : kristianl@tkjelectronics.com - */ - -#ifndef _psbuzz_h_ -#define _psbuzz_h_ - -#include "hiduniversal.h" -#include "controllerEnums.h" - -#define PSBUZZ_VID 0x054C // Sony Corporation -#define PSBUZZ_PID 0x1000 // PS Buzz Controller - -/** Struct used to easily read the different buttons on the controllers */ -union PSBUZZButtons { - struct { - uint8_t red : 1; - uint8_t yellow : 1; - uint8_t green : 1; - uint8_t orange : 1; - uint8_t blue : 1; - } __attribute__((packed)) btn[4]; - uint32_t val : 20; -} __attribute__((packed)); - -/** - * This class implements support for the PS Buzz controllers via USB. - * It uses the HIDUniversal class for all the USB communication. - */ -class PSBuzz : public HIDUniversal { -public: - /** - * Constructor for the PSBuzz class. - * @param p Pointer to the USB class instance. - */ - PSBuzz(USB *p) : - HIDUniversal(p) { - Reset(); - }; - - /** - * Used to check if a PS Buzz controller is connected. - * @return Returns true if it is connected. - */ - bool connected() { - return HIDUniversal::isReady() && HIDUniversal::VID == PSBUZZ_VID && HIDUniversal::PID == PSBUZZ_PID; - }; - - /** - * Used to call your own function when the device is successfully initialized. - * @param funcOnInit Function to call. - */ - void attachOnInit(void (*funcOnInit)(void)) { - pFuncOnInit = funcOnInit; - }; - - /** @name PS Buzzer Controller functions */ - /** - * getButtonPress(ButtonEnum b) will return true as long as the button is held down. - * - * While getButtonClick(ButtonEnum b) will only return it once. - * - * So you instance if you need to increase a variable once you would use getButtonClick(ButtonEnum b), - * but if you need to drive a robot forward you would use getButtonPress(ButtonEnum b). - * @param b ::ButtonEnum to read. - * @param controller The controller to read from. Default to 0. - * @return getButtonPress(ButtonEnum b) will return a true as long as a button is held down, while getButtonClick(ButtonEnum b) will return true once for each button press. - */ - bool getButtonPress(ButtonEnum b, uint8_t controller = 0); - bool getButtonClick(ButtonEnum b, uint8_t controller = 0); - /**@}*/ - /** @name PS Buzzer Controller functions */ - /** - * Set LED value without using ::LEDEnum. - * @param value See: ::LEDEnum. - */ - /** - * Set LED values directly. - * @param value Used to set whenever the LED should be on or off - * @param controller The controller to control. Defaults to 0. - */ - void setLedRaw(bool value, uint8_t controller = 0); - - /** Turn all LEDs off. */ - void setLedOffAll() { - for (uint8_t i = 1; i < 4; i++) // Skip first as it will be set in setLedRaw - ledState[i] = false; // Just an easy way to set all four off at the same time - setLedRaw(false); // Turn the LED off, on all four controllers - }; - - /** - * Turn the LED off on a specific controller. - * @param controller The controller to turn off. Defaults to 0. - */ - void setLedOff(uint8_t controller = 0) { - setLedRaw(false, controller); - }; - - - /** Turn all LEDs on. */ - void setLedOnAll() { - for (uint8_t i = 1; i < 4; i++) // Skip first as it will be set in setLedRaw - ledState[i] = true; // Just an easy way to set all four off at the same time - setLedRaw(true); // Turn the LED on, on all four controllers - }; - - /** - * Turn the LED on on a specific controller. - * @param controller The controller to turn off. Defaults to 0. - */ - void setLedOn(uint8_t controller = 0) { - setLedRaw(true, controller); - }; - - /** - * Toggle the LED on a specific controller. - * @param controller The controller to turn off. Defaults to 0. - */ - void setLedToggle(uint8_t controller = 0) { - setLedRaw(!ledState[controller], controller); - }; - /**@}*/ - -protected: - /** @name HIDUniversal implementation */ - /** - * Used to parse USB HID data. - * @param hid Pointer to the HID class. - * @param is_rpt_id Only used for Hubs. - * @param len The length of the incoming data. - * @param buf Pointer to the data buffer. - */ - void ParseHIDData(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); - - /** - * Called when a device is successfully initialized. - * Use attachOnInit(void (*funcOnInit)(void)) to call your own function. - * This is useful for instance if you want to set the LEDs in a specific way. - */ - uint8_t OnInitSuccessful(); - /**@}*/ - - /** Used to reset the different buffers to their default values */ - void Reset() { - psbuzzButtons.val = 0; - oldButtonState.val = 0; - buttonClickState.val = 0; - for (uint8_t i = 0; i < sizeof(ledState); i++) - ledState[i] = 0; - }; - - /** @name USBDeviceConfig implementation */ - /** - * Used by the USB core to check what this driver support. - * @param vid The device's VID. - * @param pid The device's PID. - * @return Returns true if the device's VID and PID matches this driver. - */ - virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) { - return (vid == PSBUZZ_VID && pid == PSBUZZ_PID); - }; - /**@}*/ - -private: - void (*pFuncOnInit)(void); // Pointer to function called in onInit() - - void PSBuzz_Command(uint8_t *data, uint16_t nbytes); - - PSBUZZButtons psbuzzButtons, oldButtonState, buttonClickState; - bool ledState[4]; -}; -#endif diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/README.md b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/README.md deleted file mode 100644 index 1eecb78ef2..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/README.md +++ /dev/null @@ -1,351 +0,0 @@ -# USB Host Library Rev.2.0 - -The code is released under the GNU General Public License. -__________ - -# Summary -This is Revision 2.0 of MAX3421E-based USB Host Shield Library for AVR's. - -Project main web site is: . - -Some information can also be found at: . - -The shield can be purchased at the main site: or from [TKJ Electronics](http://tkjelectronics.com/): . - -![USB Host Shield](http://shop.tkjelectronics.dk/images/USB_Host_Shield1.jpg) - -For more information about the hardware see the [Hardware Manual](http://www.circuitsathome.com/usb-host-shield-hardware-manual). - -# Developed By - -* __Oleg Mazurov, Circuits@Home__ - -* __Alexei Glushchenko, Circuits@Home__ - - * Developers of the USB Core, HID, FTDI, ADK, ACM, and PL2303 libraries -* __Kristian Lauszus, TKJ Electronics__ - - * Developer of the [BTD](#bluetooth-libraries), [BTHID](#bthid-library), [SPP](#spp-library), [PS4](#ps4-library), [PS3](#ps3-library), [Wii](#wii-library), [Xbox](#xbox-library), and [PSBuzz](#ps-buzz-library) libraries -* __Andrew Kroll__ - - * Major contributor to mass storage code -* __guruthree__ - * [Xbox ONE](#xbox-one-library) controller support - -# Donate - -Help yourself by helping us support you! Many thousands of hours have been spent developing the USB Host Shield library. Since you find it useful, please consider donating via the button below. Donations will allow us to support you by ensuring hardware that you have can be acquired in order to add support for your microcontroller board. - -PayPal - The safer, easier way to pay online! - -# Table of Contents - -* [How to include the library](#how-to-include-the-library) - * [Arduino Library Manager](#arduino-library-manager) - * [Manual installation](#manual-installation) -* [How to use the library](#how-to-use-the-library) - * [Documentation](#documentation) - * [Enable debugging](#enable-debugging) - * [Boards](#boards) - * [Bluetooth libraries](#bluetooth-libraries) - * [BTHID library](#bthid-library) - * [SPP library](#spp-library) - * [PS4 Library](#ps4-library) - * [PS3 Library](#ps3-library) - * [Xbox Libraries](#xbox-libraries) - * [Xbox library](#xbox-library) - * [Xbox 360 Library](#xbox-360-library) - * [Xbox ONE Library](#xbox-one-library) - * [Wii library](#wii-library) - * [PS Buzz Library](#ps-buzz-library) -* [Interface modifications](#interface-modifications) -* [FAQ](#faq) - -# How to include the library - -### Arduino Library Manager - -First install Arduino IDE version 1.6.2 or newer, then simply use the Arduino Library Manager to install the library. - -Please see the following page for instructions: . - -### Manual installation - -First download the library by clicking on the following link: . - -Then uncompress the zip folder and rename the directory to "USB\_Host\_Shield\_20", as any special characters are not supported by the Arduino IDE. - -Now open up the Arduino IDE and open "File>Preferences". There you will see the location of your sketchbook. Open that directory and create a directory called "libraries" inside that directory. -Now move the "USB\_Host\_Shield\_20" directory to the "libraries" directory. - -The final structure should look like this: - -* Arduino/ - * libraries/ - * USB\_Host\_Shield\_20/ - -Now quit the Arduino IDE and reopen it. - -Now you should be able to go open all the examples codes by navigating to "File>Examples>USB\_Host\_Shield\_20" and then select the example you will like to open. - -For more information visit the following sites: and . - -# How to use the library - -### Documentation - -Documentation for the library can be found at the following link: . - -### Enable debugging - -By default serial debugging is disabled. To turn it on simply change ```ENABLE_UHS_DEBUGGING``` to 1 in [settings.h](settings.h) like so: - -```C++ -#define ENABLE_UHS_DEBUGGING 1 -``` - -### Boards - -Currently the following boards are supported by the library: - -* All official Arduino AVR boards (Uno, Duemilanove, Mega, Mega 2560, Mega ADK, Leonardo etc.) -* Arduino Due, Intel Galileo, Intel Galileo 2, and Intel Edison - * Note that the Intel Galileo uses pin 2 and 3 as INT and SS pin respectively by default, so some modifications to the shield are needed. See the "Interface modifications" section in the [hardware manual](https://www.circuitsathome.com/usb-host-shield-hardware-manual) for more information. -* Teensy (Teensy++ 1.0, Teensy 2.0, Teensy++ 2.0, and Teensy 3.x) - * Note if you are using the Teensy 3.x you should download this SPI library as well: . You should then add ```#include ``` to your .ino file. -* Balanduino -* Sanguino -* Black Widdow -* RedBearLab nRF51822 -* Digilent chipKIT - * Please see: . - -The following boards need to be activated manually in [settings.h](settings.h): - -* Arduino Mega ADK - * If you are using Arduino 1.5.5 or newer there is no need to activate the Arduino Mega ADK manually -* Black Widdow - -Simply set the corresponding value to 1 instead of 0. - -### [Bluetooth libraries](BTD.cpp) - -The [BTD library](BTD.cpp) is a general purpose library for an ordinary Bluetooth dongle. -This library make it easy to add support for different Bluetooth services like a PS3 or a Wii controller or SPP which is a virtual serial port via Bluetooth. -Some different examples can be found in the [example directory](examples/Bluetooth). - -The BTD library also makes it possible to use multiple services at once, the following example sketch is an example of this: -[PS3SPP.ino](examples/Bluetooth/PS3SPP/PS3SPP.ino). - -### [BTHID library](BTHID.cpp) - -The [Bluetooth HID library](BTHID.cpp) allows you to connect HID devices via Bluetooth to the USB Host Shield. - -Currently HID mice and keyboards are supported. - -It uses the standard Boot protocol by default, but it is also able to use the Report protocol as well. You would simply have to call ```setProtocolMode()``` and then parse ```HID_RPT_PROTOCOL``` as an argument. You will then have to modify the parser for your device. See the example: [BTHID.ino](examples/Bluetooth/BTHID/BTHID.ino) for more information. - -The [PS4 library](#ps4-library) also uses this class to handle all Bluetooth communication. - -For information see the following blog post: . - -### [SPP library](SPP.cpp) - -SPP stands for "Serial Port Profile" and is a Bluetooth protocol that implements a virtual comport which allows you to send data back and forth from your computer/phone to your Arduino via Bluetooth. -It has been tested successfully on Windows, Mac OS X, Linux, and Android. - -Take a look at the [SPP.ino](examples/Bluetooth/SPP/SPP.ino) example for more information. - -More information can be found at these blog posts: - -* -* - -To implement the SPP protocol I used a Bluetooth sniffing tool called [PacketLogger](http://www.tkjelectronics.com/uploads/PacketLogger.zip) developed by Apple. -It enables me to see the Bluetooth communication between my Mac and any device. - -### PS4 Library - -The PS4BT library is split up into the [PS4BT](PS4BT.h) and the [PS4USB](PS4USB.h) library. These allow you to use the Sony PS4 controller via Bluetooth and USB. - -The [PS4BT.ino](examples/Bluetooth/PS4BT/PS4BT.ino) and [PS4USB.ino](examples/PS4USB/PS4USB.ino) examples shows how to easily read the buttons, joysticks, touchpad and IMU on the controller via Bluetooth and USB respectively. It is also possible to control the rumble and light on the controller and get the battery level. - -Before you can use the PS4 controller via Bluetooth you will need to pair with it. - -Simply create the PS4BT instance like so: ```PS4BT PS4(&Btd, PAIR);``` and then hold down the Share button and then hold down the PS without releasing the Share button. The PS4 controller will then start to blink rapidly indicating that it is in paring mode. - -It should then automatically pair the dongle with your controller. This only have to be done once. - -For information see the following blog post: . - -Also check out this excellent Wiki by Frank Zhao about the PS4 controller: and this Linux driver: . - -### PS3 Library - -These libraries consist of the [PS3BT](PS3BT.cpp) and [PS3USB](PS3USB.cpp). These libraries allows you to use a Dualshock 3, Navigation or a Motion controller with the USB Host Shield both via Bluetooth and USB. - -In order to use your Playstation controller via Bluetooth you have to set the Bluetooth address of the dongle internally to your PS3 Controller. This can be achieved by first plugging in the Bluetooth dongle and wait a few seconds. Now plug in the controller via USB and wait until the LEDs start to flash. The library has now written the Bluetooth address of the dongle to the PS3 controller. - -Finally simply plug in the Bluetooth dongle again and press PS on the PS3 controller. After a few seconds it should be connected to the dongle and ready to use. - -__Note:__ You will have to plug in the Bluetooth dongle before connecting the controller, as the library needs to read the address of the dongle. Alternatively you could set it in code like so: [PS3BT.ino#L20](examples/Bluetooth/PS3BT/PS3BT.ino#L20). - -For more information about the PS3 protocol see the official wiki: . - -Also take a look at the blog posts: - -* -* -* - -A special thanks go to the following people: - -1. _Richard Ibbotson_ who made this excellent guide: -2. _Tomoyuki Tanaka_ for releasing his code for the Arduino USB Host shield connected to the wiimote: - -Also a big thanks all the people behind these sites about the Motion controller: - -* -* -* -* - -### Xbox Libraries - -The library supports both the original Xbox controller via USB and the Xbox 360 controller both via USB and wirelessly. - -#### Xbox library - -The [XBOXOLD](XBOXOLD.cpp) class implements support for the original Xbox controller via USB. - -All the information are from the following sites: - -* -* -* -* - -#### Xbox 360 Library - -The library support one Xbox 360 via USB or up to four Xbox 360 controllers wirelessly by using a [Xbox 360 wireless receiver](http://blog.tkjelectronics.dk/wp-content/uploads/xbox360-wireless-receiver.jpg). - -To use it via USB use the [XBOXUSB](XBOXUSB.cpp) library or to use it wirelessly use the [XBOXRECV](XBOXRECV.cpp) library. - -__Note that a Wireless controller can NOT be used via USB!__ - -Examples code can be found in the [examples directory](examples/Xbox). - -Also see the following blog posts: - -* -* -* - -All the information regarding the Xbox 360 controller protocol are form these sites: - -* -* -* - -#### Xbox ONE Library - -An Xbox ONE controller is supported via USB in the [XBOXONE](XBOXONE.cpp) class. It is heavily based on the 360 library above. In addition to cross referencing the above, information on the protocol was found at: - -* -* -* - -### [Wii library](Wii.cpp) - -The [Wii](Wii.cpp) library support the Wiimote, but also the Nunchuch and Motion Plus extensions via Bluetooth. The Wii U Pro Controller and Wii Balance Board are also supported via Bluetooth. - -First you have to pair with the controller, this is done automatically by the library if you create the instance like so: - -```C++ -WII Wii(&Btd, PAIR); -``` - -And then press 1 & 2 at once on the Wiimote or the SYNC buttons if you are using a Wii U Pro Controller or a Wii Balance Board. - -After that you can simply create the instance like so: - -```C++ -WII Wii(&Btd); -``` - -Then just press any button on the Wiimote and it will then connect to the dongle. - -Take a look at the example for more information: [Wii.ino](examples/Bluetooth/Wii/Wii.ino). - -Also take a look at the blog post: - -* - -The Wii IR camera can also be used, but you will have to activate the code for it manually as it is quite large. Simply set ```ENABLE_WII_IR_CAMERA``` to 1 in [settings.h](settings.h). - -The [WiiIRCamera.ino](examples/Bluetooth/WiiIRCamera/WiiIRCamera.ino) example shows how it can be used. - -All the information about the Wii controllers are from these sites: - -* -* -* -* -* -* The old library created by _Tomoyuki Tanaka_: also helped a lot. - -### [PS Buzz Library](PSBuzz.cpp) - -This library implements support for the Playstation Buzz controllers via USB. - -It is essentially just a wrapper around the [HIDUniversal](hiduniversal.cpp) which takes care of the initializing and reading of the controllers. The [PSBuzz](PSBuzz.cpp) class simply inherits this and parses the data, so it is easy for users to read the buttons and turn the big red button on the controllers on and off. - -The example [PSBuzz.ino](examples/PSBuzz/PSBuzz.ino) shows how one can do this with just a few lines of code. - -More information about the controller can be found at the following sites: - -* http://www.developerfusion.com/article/84338/making-usb-c-friendly/ -* https://github.com/torvalds/linux/blob/master/drivers/hid/hid-sony.c - -# Interface modifications - -The shield is using SPI for communicating with the MAX3421E USB host controller. It uses the SCK, MISO and MOSI pins via the ICSP on your board. - -Note this means that it uses pin 13, 12, 11 on an Arduino Uno, so these pins can not be used for anything else than SPI communication! - -Furthermore it uses one pin as SS and one INT pin. These are by default located on pin 10 and 9 respectively. They can easily be reconfigured in case you need to use them for something else by cutting the jumper on the shield and then solder a wire from the pad to the new pin. - -After that you need modify the following entry in [UsbCore.h](UsbCore.h): - -```C++ -typedef MAX3421e MAX3421E; -``` - -For instance if you have rerouted SS to pin 7 it should read: - -```C++ -typedef MAX3421e MAX3421E; -``` - -See the "Interface modifications" section in the [hardware manual](https://www.circuitsathome.com/usb-host-shield-hardware-manual) for more information. - -# FAQ - -> When I plug my device into the USB connector nothing happens? - -* Try to connect a external power supply to the Arduino - this solves the problem in most cases. -* You can also use a powered hub between the device and the USB Host Shield. You should then include the USB hub library: ```#include ``` and create the instance like so: ```USBHub Hub1(&Usb);```. - -> When I connecting my PS3 controller I get a output like this: - -``` -Dualshock 3 Controller Enabled - -LeftHatX: 0 LeftHatY: 0 RightHatX: 0 RightHatY: 0 -LeftHatX: 0 LeftHatY: 0 RightHatX: 0 RightHatY: 0 -LeftHatX: 0 LeftHatY: 0 RightHatX: 0 RightHatY: 0 -LeftHatX: 0 LeftHatY: 0 RightHatX: 0 RightHatY: 0 -LeftHatX: 0 LeftHatY: 0 RightHatX: 0 RightHatY: 0 -``` - -* This means that your dongle does not support 2.0+EDR, so you will need another dongle. Please see the following [list](https://github.com/felis/USB_Host_Shield_2.0/wiki/Bluetooth-dongles) for tested working dongles. - -> When compiling I am getting the following error: "fatal error: SPI.h: No such file or directory". - -* Please make sure to include the SPI library like so: ```#include ``` in your .ino file. diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/SPP.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/SPP.cpp deleted file mode 100644 index 0f4ee5e981..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/SPP.cpp +++ /dev/null @@ -1,829 +0,0 @@ -/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. - - This software may be distributed and modified under the terms of the GNU - General Public License version 2 (GPL2) as published by the Free Software - Foundation and appearing in the file GPL2.TXT included in the packaging of - this file. Please note that GPL2 Section 2[b] requires that all works based - on this software must also be made publicly available under the terms of - the GPL2 ("Copyleft"). - - Contact information - ------------------- - - Kristian Lauszus, TKJ Electronics - Web : http://www.tkjelectronics.com - e-mail : kristianl@tkjelectronics.com - */ - -#include "SPP.h" -// To enable serial debugging see "settings.h" -//#define EXTRADEBUG // Uncomment to get even more debugging data -//#define PRINTREPORT // Uncomment to print the report sent to the Arduino - -/* - * CRC (reversed crc) lookup table as calculated by the table generator in ETSI TS 101 369 V6.3.0. - */ -const uint8_t rfcomm_crc_table[256] PROGMEM = {/* reversed, 8-bit, poly=0x07 */ - 0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B, - 0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69, 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67, - 0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D, 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43, - 0x24, 0xB5, 0xC7, 0x56, 0x23, 0xB2, 0xC0, 0x51, 0x2A, 0xBB, 0xC9, 0x58, 0x2D, 0xBC, 0xCE, 0x5F, - 0x70, 0xE1, 0x93, 0x02, 0x77, 0xE6, 0x94, 0x05, 0x7E, 0xEF, 0x9D, 0x0C, 0x79, 0xE8, 0x9A, 0x0B, - 0x6C, 0xFD, 0x8F, 0x1E, 0x6B, 0xFA, 0x88, 0x19, 0x62, 0xF3, 0x81, 0x10, 0x65, 0xF4, 0x86, 0x17, - 0x48, 0xD9, 0xAB, 0x3A, 0x4F, 0xDE, 0xAC, 0x3D, 0x46, 0xD7, 0xA5, 0x34, 0x41, 0xD0, 0xA2, 0x33, - 0x54, 0xC5, 0xB7, 0x26, 0x53, 0xC2, 0xB0, 0x21, 0x5A, 0xCB, 0xB9, 0x28, 0x5D, 0xCC, 0xBE, 0x2F, - 0xE0, 0x71, 0x03, 0x92, 0xE7, 0x76, 0x04, 0x95, 0xEE, 0x7F, 0x0D, 0x9C, 0xE9, 0x78, 0x0A, 0x9B, - 0xFC, 0x6D, 0x1F, 0x8E, 0xFB, 0x6A, 0x18, 0x89, 0xF2, 0x63, 0x11, 0x80, 0xF5, 0x64, 0x16, 0x87, - 0xD8, 0x49, 0x3B, 0xAA, 0xDF, 0x4E, 0x3C, 0xAD, 0xD6, 0x47, 0x35, 0xA4, 0xD1, 0x40, 0x32, 0xA3, - 0xC4, 0x55, 0x27, 0xB6, 0xC3, 0x52, 0x20, 0xB1, 0xCA, 0x5B, 0x29, 0xB8, 0xCD, 0x5C, 0x2E, 0xBF, - 0x90, 0x01, 0x73, 0xE2, 0x97, 0x06, 0x74, 0xE5, 0x9E, 0x0F, 0x7D, 0xEC, 0x99, 0x08, 0x7A, 0xEB, - 0x8C, 0x1D, 0x6F, 0xFE, 0x8B, 0x1A, 0x68, 0xF9, 0x82, 0x13, 0x61, 0xF0, 0x85, 0x14, 0x66, 0xF7, - 0xA8, 0x39, 0x4B, 0xDA, 0xAF, 0x3E, 0x4C, 0xDD, 0xA6, 0x37, 0x45, 0xD4, 0xA1, 0x30, 0x42, 0xD3, - 0xB4, 0x25, 0x57, 0xC6, 0xB3, 0x22, 0x50, 0xC1, 0xBA, 0x2B, 0x59, 0xC8, 0xBD, 0x2C, 0x5E, 0xCF -}; - -SPP::SPP(BTD *p, const char* name, const char* pin) : -BluetoothService(p) // Pointer to BTD class instance - mandatory -{ - pBtd->btdName = name; - pBtd->btdPin = pin; - - /* Set device cid for the SDP and RFCOMM channelse */ - sdp_dcid[0] = 0x50; // 0x0050 - sdp_dcid[1] = 0x00; - rfcomm_dcid[0] = 0x51; // 0x0051 - rfcomm_dcid[1] = 0x00; - - Reset(); -} - -void SPP::Reset() { - connected = false; - RFCOMMConnected = false; - SDPConnected = false; - waitForLastCommand = false; - l2cap_sdp_state = L2CAP_SDP_WAIT; - l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT; - l2cap_event_flag = 0; - sppIndex = 0; - creditSent = false; -} - -void SPP::disconnect() { - connected = false; - // First the two L2CAP channels has to be disconnected and then the HCI connection - if(RFCOMMConnected) - pBtd->l2cap_disconnection_request(hci_handle, ++identifier, rfcomm_scid, rfcomm_dcid); - if(RFCOMMConnected && SDPConnected) - delay(1); // Add delay between commands - if(SDPConnected) - pBtd->l2cap_disconnection_request(hci_handle, ++identifier, sdp_scid, sdp_dcid); - l2cap_sdp_state = L2CAP_DISCONNECT_RESPONSE; -} - -void SPP::ACLData(uint8_t* l2capinbuf) { - if(!connected) { - if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { - if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == SDP_PSM && !pBtd->sdpConnectionClaimed) { - pBtd->sdpConnectionClaimed = true; - hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection - l2cap_sdp_state = L2CAP_SDP_WAIT; // Reset state - } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == RFCOMM_PSM && !pBtd->rfcommConnectionClaimed) { - pBtd->rfcommConnectionClaimed = true; - hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection - l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT; // Reset state - } - } - } - - if(checkHciHandle(l2capinbuf, hci_handle)) { // acl_handle_ok - if((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001U) { // l2cap_control - Channel ID for ACL-U - if(l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80); - D_PrintHex (l2capinbuf[13], 0x80); - Notify(PSTR(" "), 0x80); - D_PrintHex (l2capinbuf[12], 0x80); - Notify(PSTR(" Data: "), 0x80); - D_PrintHex (l2capinbuf[17], 0x80); - Notify(PSTR(" "), 0x80); - D_PrintHex (l2capinbuf[16], 0x80); - Notify(PSTR(" "), 0x80); - D_PrintHex (l2capinbuf[15], 0x80); - Notify(PSTR(" "), 0x80); - D_PrintHex (l2capinbuf[14], 0x80); -#endif - } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { -#ifdef EXTRADEBUG - Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80); - D_PrintHex (l2capinbuf[13], 0x80); - Notify(PSTR(" "), 0x80); - D_PrintHex (l2capinbuf[12], 0x80); - Notify(PSTR(" SCID: "), 0x80); - D_PrintHex (l2capinbuf[15], 0x80); - Notify(PSTR(" "), 0x80); - D_PrintHex (l2capinbuf[14], 0x80); - Notify(PSTR(" Identifier: "), 0x80); - D_PrintHex (l2capinbuf[9], 0x80); -#endif - if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == SDP_PSM) { // It doesn't matter if it receives another reqeust, since it waits for the channel to disconnect in the L2CAP_SDP_DONE state, and the l2cap_event_flag will be cleared if so - identifier = l2capinbuf[9]; - sdp_scid[0] = l2capinbuf[14]; - sdp_scid[1] = l2capinbuf[15]; - l2cap_set_flag(L2CAP_FLAG_CONNECTION_SDP_REQUEST); - } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == RFCOMM_PSM) { // ----- || ----- - identifier = l2capinbuf[9]; - rfcomm_scid[0] = l2capinbuf[14]; - rfcomm_scid[1] = l2capinbuf[15]; - l2cap_set_flag(L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST); - } - } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) { - if((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success - if(l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) { - //Notify(PSTR("\r\nSDP Configuration Complete"), 0x80); - l2cap_set_flag(L2CAP_FLAG_CONFIG_SDP_SUCCESS); - } else if(l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) { - //Notify(PSTR("\r\nRFCOMM Configuration Complete"), 0x80); - l2cap_set_flag(L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS); - } - } - } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) { - if(l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) { - //Notify(PSTR("\r\nSDP Configuration Request"), 0x80); - pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], sdp_scid); - } else if(l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) { - //Notify(PSTR("\r\nRFCOMM Configuration Request"), 0x80); - pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], rfcomm_scid); - } - } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) { - if(l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) { - //Notify(PSTR("\r\nDisconnect Request: SDP Channel"), 0x80); - identifier = l2capinbuf[9]; - l2cap_set_flag(L2CAP_FLAG_DISCONNECT_SDP_REQUEST); - } else if(l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) { - //Notify(PSTR("\r\nDisconnect Request: RFCOMM Channel"), 0x80); - identifier = l2capinbuf[9]; - l2cap_set_flag(L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST); - } - } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) { - if(l2capinbuf[12] == sdp_scid[0] && l2capinbuf[13] == sdp_scid[1]) { - //Notify(PSTR("\r\nDisconnect Response: SDP Channel"), 0x80); - identifier = l2capinbuf[9]; - l2cap_set_flag(L2CAP_FLAG_DISCONNECT_RESPONSE); - } else if(l2capinbuf[12] == rfcomm_scid[0] && l2capinbuf[13] == rfcomm_scid[1]) { - //Notify(PSTR("\r\nDisconnect Response: RFCOMM Channel"), 0x80); - identifier = l2capinbuf[9]; - l2cap_set_flag(L2CAP_FLAG_DISCONNECT_RESPONSE); - } - } else if(l2capinbuf[8] == L2CAP_CMD_INFORMATION_REQUEST) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nInformation request"), 0x80); -#endif - identifier = l2capinbuf[9]; - pBtd->l2cap_information_response(hci_handle, identifier, l2capinbuf[12], l2capinbuf[13]); - } -#ifdef EXTRADEBUG - else { - Notify(PSTR("\r\nL2CAP Unknown Signaling Command: "), 0x80); - D_PrintHex (l2capinbuf[8], 0x80); - } -#endif - } else if(l2capinbuf[6] == sdp_dcid[0] && l2capinbuf[7] == sdp_dcid[1]) { // SDP - if(l2capinbuf[8] == SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST_PDU) { - if(((l2capinbuf[16] << 8 | l2capinbuf[17]) == SERIALPORT_UUID) || ((l2capinbuf[16] << 8 | l2capinbuf[17]) == 0x0000 && (l2capinbuf[18] << 8 | l2capinbuf[19]) == SERIALPORT_UUID)) { // Check if it's sending the full UUID, see: https://www.bluetooth.org/Technical/AssignedNumbers/service_discovery.htm, we will just check the first four bytes - if(firstMessage) { - serialPortResponse1(l2capinbuf[9], l2capinbuf[10]); - firstMessage = false; - } else { - serialPortResponse2(l2capinbuf[9], l2capinbuf[10]); // Serialport continuation state - firstMessage = true; - } - } else if(((l2capinbuf[16] << 8 | l2capinbuf[17]) == L2CAP_UUID) || ((l2capinbuf[16] << 8 | l2capinbuf[17]) == 0x0000 && (l2capinbuf[18] << 8 | l2capinbuf[19]) == L2CAP_UUID)) { - if(firstMessage) { - l2capResponse1(l2capinbuf[9], l2capinbuf[10]); - firstMessage = false; - } else { - l2capResponse2(l2capinbuf[9], l2capinbuf[10]); // L2CAP continuation state - firstMessage = true; - } - } else - serviceNotSupported(l2capinbuf[9], l2capinbuf[10]); // The service is not supported -#ifdef EXTRADEBUG - Notify(PSTR("\r\nUUID: "), 0x80); - uint16_t uuid; - if((l2capinbuf[16] << 8 | l2capinbuf[17]) == 0x0000) // Check if it's sending the UUID as a 128-bit UUID - uuid = (l2capinbuf[18] << 8 | l2capinbuf[19]); - else // Short UUID - uuid = (l2capinbuf[16] << 8 | l2capinbuf[17]); - D_PrintHex (uuid, 0x80); - - Notify(PSTR("\r\nLength: "), 0x80); - uint16_t length = l2capinbuf[11] << 8 | l2capinbuf[12]; - D_PrintHex (length, 0x80); - Notify(PSTR("\r\nData: "), 0x80); - for(uint8_t i = 0; i < length; i++) { - D_PrintHex (l2capinbuf[13 + i], 0x80); - Notify(PSTR(" "), 0x80); - } -#endif - } -#ifdef EXTRADEBUG - else { - Notify(PSTR("\r\nUnknown PDU: "), 0x80); - D_PrintHex (l2capinbuf[8], 0x80); - } -#endif - } else if(l2capinbuf[6] == rfcomm_dcid[0] && l2capinbuf[7] == rfcomm_dcid[1]) { // RFCOMM - rfcommChannel = l2capinbuf[8] & 0xF8; - rfcommDirection = l2capinbuf[8] & 0x04; - rfcommCommandResponse = l2capinbuf[8] & 0x02; - rfcommChannelType = l2capinbuf[9] & 0xEF; - rfcommPfBit = l2capinbuf[9] & 0x10; - - if(rfcommChannel >> 3 != 0x00) - rfcommChannelConnection = rfcommChannel; - -#ifdef EXTRADEBUG - Notify(PSTR("\r\nRFCOMM Channel: "), 0x80); - D_PrintHex (rfcommChannel >> 3, 0x80); - Notify(PSTR(" Direction: "), 0x80); - D_PrintHex (rfcommDirection >> 2, 0x80); - Notify(PSTR(" CommandResponse: "), 0x80); - D_PrintHex (rfcommCommandResponse >> 1, 0x80); - Notify(PSTR(" ChannelType: "), 0x80); - D_PrintHex (rfcommChannelType, 0x80); - Notify(PSTR(" PF_BIT: "), 0x80); - D_PrintHex (rfcommPfBit, 0x80); -#endif - if(rfcommChannelType == RFCOMM_DISC) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nReceived Disconnect RFCOMM Command on channel: "), 0x80); - D_PrintHex (rfcommChannel >> 3, 0x80); -#endif - connected = false; - sendRfcomm(rfcommChannel, rfcommDirection, rfcommCommandResponse, RFCOMM_UA, rfcommPfBit, rfcommbuf, 0x00); // UA Command - } - if(connected) { - /* Read the incoming message */ - if(rfcommChannelType == RFCOMM_UIH && rfcommChannel == rfcommChannelConnection) { - uint8_t length = l2capinbuf[10] >> 1; // Get length - uint8_t offset = l2capinbuf[4] - length - 4; // Check if there is credit - if(checkFcs(&l2capinbuf[8], l2capinbuf[11 + length + offset])) { - uint8_t i = 0; - for(; i < length; i++) { - if(rfcommAvailable + i >= sizeof (rfcommDataBuffer)) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nWarning: Buffer is full!"), 0x80); -#endif - break; - } - rfcommDataBuffer[rfcommAvailable + i] = l2capinbuf[11 + i + offset]; - } - rfcommAvailable += i; -#ifdef EXTRADEBUG - Notify(PSTR("\r\nRFCOMM Data Available: "), 0x80); - Notify(rfcommAvailable, 0x80); - if(offset) { - Notify(PSTR(" - Credit: 0x"), 0x80); - D_PrintHex (l2capinbuf[11], 0x80); - } -#endif - } -#ifdef DEBUG_USB_HOST - else - Notify(PSTR("\r\nError in FCS checksum!"), 0x80); -#endif -#ifdef PRINTREPORT // Uncomment "#define PRINTREPORT" to print the report send to the Arduino via Bluetooth - for(uint8_t i = 0; i < length; i++) - Notifyc(l2capinbuf[i + 11 + offset], 0x80); -#endif - } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_RPN_CMD) { // UIH Remote Port Negotiation Command -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nReceived UIH Remote Port Negotiation Command"), 0x80); -#endif - rfcommbuf[0] = BT_RFCOMM_RPN_RSP; // Command - rfcommbuf[1] = l2capinbuf[12]; // Length and shiftet like so: length << 1 | 1 - rfcommbuf[2] = l2capinbuf[13]; // Channel: channel << 1 | 1 - rfcommbuf[3] = l2capinbuf[14]; // Pre difined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM - rfcommbuf[4] = l2capinbuf[15]; // Priority - rfcommbuf[5] = l2capinbuf[16]; // Timer - rfcommbuf[6] = l2capinbuf[17]; // Max Fram Size LSB - rfcommbuf[7] = l2capinbuf[18]; // Max Fram Size MSB - rfcommbuf[8] = l2capinbuf[19]; // MaxRatransm. - rfcommbuf[9] = l2capinbuf[20]; // Number of Frames - sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x0A); // UIH Remote Port Negotiation Response - } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_MSC_CMD) { // UIH Modem Status Command -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nSend UIH Modem Status Response"), 0x80); -#endif - rfcommbuf[0] = BT_RFCOMM_MSC_RSP; // UIH Modem Status Response - rfcommbuf[1] = 2 << 1 | 1; // Length and shiftet like so: length << 1 | 1 - rfcommbuf[2] = l2capinbuf[13]; // Channel: (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3) - rfcommbuf[3] = l2capinbuf[14]; - sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x04); - } - } else { - if(rfcommChannelType == RFCOMM_SABM) { // SABM Command - this is sent twice: once for channel 0 and then for the channel to establish -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nReceived SABM Command"), 0x80); -#endif - sendRfcomm(rfcommChannel, rfcommDirection, rfcommCommandResponse, RFCOMM_UA, rfcommPfBit, rfcommbuf, 0x00); // UA Command - } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_PN_CMD) { // UIH Parameter Negotiation Command -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nReceived UIH Parameter Negotiation Command"), 0x80); -#endif - rfcommbuf[0] = BT_RFCOMM_PN_RSP; // UIH Parameter Negotiation Response - rfcommbuf[1] = l2capinbuf[12]; // Length and shiftet like so: length << 1 | 1 - rfcommbuf[2] = l2capinbuf[13]; // Channel: channel << 1 | 1 - rfcommbuf[3] = 0xE0; // Pre difined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM - rfcommbuf[4] = 0x00; // Priority - rfcommbuf[5] = 0x00; // Timer - rfcommbuf[6] = BULK_MAXPKTSIZE - 14; // Max Fram Size LSB - set to the size of received data (50) - rfcommbuf[7] = 0x00; // Max Fram Size MSB - rfcommbuf[8] = 0x00; // MaxRatransm. - rfcommbuf[9] = 0x00; // Number of Frames - sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x0A); - } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_MSC_CMD) { // UIH Modem Status Command -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nSend UIH Modem Status Response"), 0x80); -#endif - rfcommbuf[0] = BT_RFCOMM_MSC_RSP; // UIH Modem Status Response - rfcommbuf[1] = 2 << 1 | 1; // Length and shiftet like so: length << 1 | 1 - rfcommbuf[2] = l2capinbuf[13]; // Channel: (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3) - rfcommbuf[3] = l2capinbuf[14]; - sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x04); - - delay(1); -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nSend UIH Modem Status Command"), 0x80); -#endif - rfcommbuf[0] = BT_RFCOMM_MSC_CMD; // UIH Modem Status Command - rfcommbuf[1] = 2 << 1 | 1; // Length and shiftet like so: length << 1 | 1 - rfcommbuf[2] = l2capinbuf[13]; // Channel: (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3) - rfcommbuf[3] = 0x8D; // Can receive frames (YES), Ready to Communicate (YES), Ready to Receive (YES), Incomig Call (NO), Data is Value (YES) - - sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x04); - } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_MSC_RSP) { // UIH Modem Status Response - if(!creditSent) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nSend UIH Command with credit"), 0x80); -#endif - sendRfcommCredit(rfcommChannelConnection, rfcommDirection, 0, RFCOMM_UIH, 0x10, sizeof (rfcommDataBuffer)); // Send credit - creditSent = true; - timer = millis(); - waitForLastCommand = true; - } - } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[10] == 0x01) { // UIH Command with credit -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nReceived UIH Command with credit"), 0x80); -#endif - } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_RPN_CMD) { // UIH Remote Port Negotiation Command -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nReceived UIH Remote Port Negotiation Command"), 0x80); -#endif - rfcommbuf[0] = BT_RFCOMM_RPN_RSP; // Command - rfcommbuf[1] = l2capinbuf[12]; // Length and shiftet like so: length << 1 | 1 - rfcommbuf[2] = l2capinbuf[13]; // Channel: channel << 1 | 1 - rfcommbuf[3] = l2capinbuf[14]; // Pre difined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM - rfcommbuf[4] = l2capinbuf[15]; // Priority - rfcommbuf[5] = l2capinbuf[16]; // Timer - rfcommbuf[6] = l2capinbuf[17]; // Max Fram Size LSB - rfcommbuf[7] = l2capinbuf[18]; // Max Fram Size MSB - rfcommbuf[8] = l2capinbuf[19]; // MaxRatransm. - rfcommbuf[9] = l2capinbuf[20]; // Number of Frames - sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x0A); // UIH Remote Port Negotiation Response -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nRFCOMM Connection is now established\r\n"), 0x80); -#endif - onInit(); - } -#ifdef EXTRADEBUG - else if(rfcommChannelType != RFCOMM_DISC) { - Notify(PSTR("\r\nUnsupported RFCOMM Data - ChannelType: "), 0x80); - D_PrintHex (rfcommChannelType, 0x80); - Notify(PSTR(" Command: "), 0x80); - D_PrintHex (l2capinbuf[11], 0x80); - } -#endif - } - } -#ifdef EXTRADEBUG - else { - Notify(PSTR("\r\nUnsupported L2CAP Data - Channel ID: "), 0x80); - D_PrintHex (l2capinbuf[7], 0x80); - Notify(PSTR(" "), 0x80); - D_PrintHex (l2capinbuf[6], 0x80); - } -#endif - SDP_task(); - RFCOMM_task(); - } -} - -void SPP::Run() { - if(waitForLastCommand && (millis() - timer) > 100) { // We will only wait 100ms and see if the UIH Remote Port Negotiation Command is send, as some deviced don't send it -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nRFCOMM Connection is now established - Automatic\r\n"), 0x80); -#endif - onInit(); - } - send(); // Send all bytes currently in the buffer -} - -void SPP::onInit() { - creditSent = false; - waitForLastCommand = false; - connected = true; // The RFCOMM channel is now established - sppIndex = 0; - if(pFuncOnInit) - pFuncOnInit(); // Call the user function -}; - -void SPP::SDP_task() { - switch(l2cap_sdp_state) { - case L2CAP_SDP_WAIT: - if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_SDP_REQUEST)) { - l2cap_clear_flag(L2CAP_FLAG_CONNECTION_SDP_REQUEST); // Clear flag -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nSDP Incoming Connection Request"), 0x80); -#endif - pBtd->l2cap_connection_response(hci_handle, identifier, sdp_dcid, sdp_scid, PENDING); - delay(1); - pBtd->l2cap_connection_response(hci_handle, identifier, sdp_dcid, sdp_scid, SUCCESSFUL); - identifier++; - delay(1); - pBtd->l2cap_config_request(hci_handle, identifier, sdp_scid); - l2cap_sdp_state = L2CAP_SDP_SUCCESS; - } else if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_SDP_REQUEST)) { - l2cap_clear_flag(L2CAP_FLAG_DISCONNECT_SDP_REQUEST); // Clear flag - SDPConnected = false; -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nDisconnected SDP Channel"), 0x80); -#endif - pBtd->l2cap_disconnection_response(hci_handle, identifier, sdp_dcid, sdp_scid); - } - break; - case L2CAP_SDP_SUCCESS: - if(l2cap_check_flag(L2CAP_FLAG_CONFIG_SDP_SUCCESS)) { - l2cap_clear_flag(L2CAP_FLAG_CONFIG_SDP_SUCCESS); // Clear flag -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nSDP Successfully Configured"), 0x80); -#endif - firstMessage = true; // Reset bool - SDPConnected = true; - l2cap_sdp_state = L2CAP_SDP_WAIT; - } - break; - - case L2CAP_DISCONNECT_RESPONSE: // This is for both disconnection response from the RFCOMM and SDP channel if they were connected - if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_RESPONSE)) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nDisconnected L2CAP Connection"), 0x80); -#endif - pBtd->hci_disconnect(hci_handle); - hci_handle = -1; // Reset handle - Reset(); - } - break; - } -} - -void SPP::RFCOMM_task() { - switch(l2cap_rfcomm_state) { - case L2CAP_RFCOMM_WAIT: - if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST)) { - l2cap_clear_flag(L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST); // Clear flag -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nRFCOMM Incoming Connection Request"), 0x80); -#endif - pBtd->l2cap_connection_response(hci_handle, identifier, rfcomm_dcid, rfcomm_scid, PENDING); - delay(1); - pBtd->l2cap_connection_response(hci_handle, identifier, rfcomm_dcid, rfcomm_scid, SUCCESSFUL); - identifier++; - delay(1); - pBtd->l2cap_config_request(hci_handle, identifier, rfcomm_scid); - l2cap_rfcomm_state = L2CAP_RFCOMM_SUCCESS; - } else if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST)) { - l2cap_clear_flag(L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST); // Clear flag - RFCOMMConnected = false; - connected = false; -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nDisconnected RFCOMM Channel"), 0x80); -#endif - pBtd->l2cap_disconnection_response(hci_handle, identifier, rfcomm_dcid, rfcomm_scid); - } - break; - case L2CAP_RFCOMM_SUCCESS: - if(l2cap_check_flag(L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS)) { - l2cap_clear_flag(L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS); // Clear flag -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nRFCOMM Successfully Configured"), 0x80); -#endif - rfcommAvailable = 0; // Reset number of bytes available - bytesRead = 0; // Reset number of bytes received - RFCOMMConnected = true; - l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT; - } - break; - } -} -/************************************************************/ -/* SDP Commands */ - -/************************************************************/ -void SPP::SDP_Command(uint8_t* data, uint8_t nbytes) { // See page 223 in the Bluetooth specs - pBtd->L2CAP_Command(hci_handle, data, nbytes, sdp_scid[0], sdp_scid[1]); -} - -void SPP::serviceNotSupported(uint8_t transactionIDHigh, uint8_t transactionIDLow) { // See page 235 in the Bluetooth specs - l2capoutbuf[0] = SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU; - l2capoutbuf[1] = transactionIDHigh; - l2capoutbuf[2] = transactionIDLow; - l2capoutbuf[3] = 0x00; // MSB Parameter Length - l2capoutbuf[4] = 0x05; // LSB Parameter Length = 5 - l2capoutbuf[5] = 0x00; // MSB AttributeListsByteCount - l2capoutbuf[6] = 0x02; // LSB AttributeListsByteCount = 2 - - /* Attribute ID/Value Sequence: */ - l2capoutbuf[7] = 0x35; // Data element sequence - length in next byte - l2capoutbuf[8] = 0x00; // Length = 0 - l2capoutbuf[9] = 0x00; // No continuation state - - SDP_Command(l2capoutbuf, 10); -} - -void SPP::serialPortResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow) { - l2capoutbuf[0] = SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU; - l2capoutbuf[1] = transactionIDHigh; - l2capoutbuf[2] = transactionIDLow; - l2capoutbuf[3] = 0x00; // MSB Parameter Length - l2capoutbuf[4] = 0x2B; // LSB Parameter Length = 43 - l2capoutbuf[5] = 0x00; // MSB AttributeListsByteCount - l2capoutbuf[6] = 0x26; // LSB AttributeListsByteCount = 38 - - /* Attribute ID/Value Sequence: */ - l2capoutbuf[7] = 0x36; // Data element sequence - length in next two bytes - l2capoutbuf[8] = 0x00; // MSB Length - l2capoutbuf[9] = 0x3C; // LSB Length = 60 - - l2capoutbuf[10] = 0x36; // Data element sequence - length in next two bytes - l2capoutbuf[11] = 0x00; // MSB Length - l2capoutbuf[12] = 0x39; // LSB Length = 57 - - l2capoutbuf[13] = 0x09; // Unsigned Integer - length 2 bytes - l2capoutbuf[14] = 0x00; // MSB ServiceRecordHandle - l2capoutbuf[15] = 0x00; // LSB ServiceRecordHandle - l2capoutbuf[16] = 0x0A; // Unsigned int - length 4 bytes - l2capoutbuf[17] = 0x00; // ServiceRecordHandle value - TODO: Is this related to HCI_Handle? - l2capoutbuf[18] = 0x01; - l2capoutbuf[19] = 0x00; - l2capoutbuf[20] = 0x06; - - l2capoutbuf[21] = 0x09; // Unsigned Integer - length 2 bytes - l2capoutbuf[22] = 0x00; // MSB ServiceClassIDList - l2capoutbuf[23] = 0x01; // LSB ServiceClassIDList - l2capoutbuf[24] = 0x35; // Data element sequence - length in next byte - l2capoutbuf[25] = 0x03; // Length = 3 - l2capoutbuf[26] = 0x19; // UUID (universally unique identifier) - length = 2 bytes - l2capoutbuf[27] = 0x11; // MSB SerialPort - l2capoutbuf[28] = 0x01; // LSB SerialPort - - l2capoutbuf[29] = 0x09; // Unsigned Integer - length 2 bytes - l2capoutbuf[30] = 0x00; // MSB ProtocolDescriptorList - l2capoutbuf[31] = 0x04; // LSB ProtocolDescriptorList - l2capoutbuf[32] = 0x35; // Data element sequence - length in next byte - l2capoutbuf[33] = 0x0C; // Length = 12 - - l2capoutbuf[34] = 0x35; // Data element sequence - length in next byte - l2capoutbuf[35] = 0x03; // Length = 3 - l2capoutbuf[36] = 0x19; // UUID (universally unique identifier) - length = 2 bytes - l2capoutbuf[37] = 0x01; // MSB L2CAP - l2capoutbuf[38] = 0x00; // LSB L2CAP - - l2capoutbuf[39] = 0x35; // Data element sequence - length in next byte - l2capoutbuf[40] = 0x05; // Length = 5 - l2capoutbuf[41] = 0x19; // UUID (universally unique identifier) - length = 2 bytes - l2capoutbuf[42] = 0x00; // MSB RFCOMM - l2capoutbuf[43] = 0x03; // LSB RFCOMM - l2capoutbuf[44] = 0x08; // Unsigned Integer - length 1 byte - - l2capoutbuf[45] = 0x02; // ContinuationState - Two more bytes - l2capoutbuf[46] = 0x00; // MSB length - l2capoutbuf[47] = 0x19; // LSB length = 25 more bytes to come - - SDP_Command(l2capoutbuf, 48); -} - -void SPP::serialPortResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow) { - l2capoutbuf[0] = SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU; - l2capoutbuf[1] = transactionIDHigh; - l2capoutbuf[2] = transactionIDLow; - l2capoutbuf[3] = 0x00; // MSB Parameter Length - l2capoutbuf[4] = 0x1C; // LSB Parameter Length = 28 - l2capoutbuf[5] = 0x00; // MSB AttributeListsByteCount - l2capoutbuf[6] = 0x19; // LSB AttributeListsByteCount = 25 - - /* Attribute ID/Value Sequence: */ - l2capoutbuf[7] = 0x01; // Channel 1 - TODO: Try different values, so multiple servers can be used at once - - l2capoutbuf[8] = 0x09; // Unsigned Integer - length 2 bytes - l2capoutbuf[9] = 0x00; // MSB LanguageBaseAttributeIDList - l2capoutbuf[10] = 0x06; // LSB LanguageBaseAttributeIDList - l2capoutbuf[11] = 0x35; // Data element sequence - length in next byte - l2capoutbuf[12] = 0x09; // Length = 9 - - // Identifier representing the natural language = en = English - see: "ISO 639:1988" - l2capoutbuf[13] = 0x09; // Unsigned Integer - length 2 bytes - l2capoutbuf[14] = 0x65; // 'e' - l2capoutbuf[15] = 0x6E; // 'n' - - // "The second element of each triplet contains an identifier that specifies a character encoding used for the language" - // Encoding is set to 106 (UTF-8) - see: http://www.iana.org/assignments/character-sets/character-sets.xhtml - l2capoutbuf[16] = 0x09; // Unsigned Integer - length 2 bytes - l2capoutbuf[17] = 0x00; // MSB of character encoding - l2capoutbuf[18] = 0x6A; // LSB of character encoding (106) - - // Attribute ID that serves as the base attribute ID for the natural language in the service record - // "To facilitate the retrieval of human-readable universal attributes in a principal language, the base attribute ID value for the primary language supported by a service record shall be 0x0100" - l2capoutbuf[19] = 0x09; // Unsigned Integer - length 2 bytes - l2capoutbuf[20] = 0x01; - l2capoutbuf[21] = 0x00; - - l2capoutbuf[22] = 0x09; // Unsigned Integer - length 2 bytes - l2capoutbuf[23] = 0x01; // MSB ServiceDescription - l2capoutbuf[24] = 0x00; // LSB ServiceDescription - - l2capoutbuf[25] = 0x25; // Text string - length in next byte - l2capoutbuf[26] = 0x05; // Name length - l2capoutbuf[27] = 'T'; - l2capoutbuf[28] = 'K'; - l2capoutbuf[29] = 'J'; - l2capoutbuf[30] = 'S'; - l2capoutbuf[31] = 'P'; - l2capoutbuf[32] = 0x00; // No continuation state - - SDP_Command(l2capoutbuf, 33); -} - -void SPP::l2capResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow) { - serialPortResponse1(transactionIDHigh, transactionIDLow); // These has to send all the supported functions, since it only supports virtual serialport it just sends the message again -} - -void SPP::l2capResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow) { - serialPortResponse2(transactionIDHigh, transactionIDLow); // Same data as serialPortResponse2 -} -/************************************************************/ -/* RFCOMM Commands */ - -/************************************************************/ -void SPP::RFCOMM_Command(uint8_t* data, uint8_t nbytes) { - pBtd->L2CAP_Command(hci_handle, data, nbytes, rfcomm_scid[0], rfcomm_scid[1]); -} - -void SPP::sendRfcomm(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t* data, uint8_t length) { - l2capoutbuf[0] = channel | direction | CR | extendAddress; // RFCOMM Address - l2capoutbuf[1] = channelType | pfBit; // RFCOMM Control - l2capoutbuf[2] = length << 1 | 0x01; // Length and format (always 0x01 bytes format) - uint8_t i = 0; - for(; i < length; i++) - l2capoutbuf[i + 3] = data[i]; - l2capoutbuf[i + 3] = calcFcs(l2capoutbuf); -#ifdef EXTRADEBUG - Notify(PSTR(" - RFCOMM Data: "), 0x80); - for(i = 0; i < length + 4; i++) { - D_PrintHex (l2capoutbuf[i], 0x80); - Notify(PSTR(" "), 0x80); - } -#endif - RFCOMM_Command(l2capoutbuf, length + 4); -} - -void SPP::sendRfcommCredit(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t credit) { - l2capoutbuf[0] = channel | direction | CR | extendAddress; // RFCOMM Address - l2capoutbuf[1] = channelType | pfBit; // RFCOMM Control - l2capoutbuf[2] = 0x01; // Length = 0 - l2capoutbuf[3] = credit; // Credit - l2capoutbuf[4] = calcFcs(l2capoutbuf); -#ifdef EXTRADEBUG - Notify(PSTR(" - RFCOMM Credit Data: "), 0x80); - for(uint8_t i = 0; i < 5; i++) { - D_PrintHex (l2capoutbuf[i], 0x80); - Notify(PSTR(" "), 0x80); - } -#endif - RFCOMM_Command(l2capoutbuf, 5); -} - -/* CRC on 2 bytes */ -uint8_t SPP::crc(uint8_t *data) { - return (pgm_read_byte(&rfcomm_crc_table[pgm_read_byte(&rfcomm_crc_table[0xFF ^ data[0]]) ^ data[1]])); -} - -/* Calculate FCS */ -uint8_t SPP::calcFcs(uint8_t *data) { - uint8_t temp = crc(data); - if((data[1] & 0xEF) == RFCOMM_UIH) - return (0xFF - temp); // FCS on 2 bytes - else - return (0xFF - pgm_read_byte(&rfcomm_crc_table[temp ^ data[2]])); // FCS on 3 bytes -} - -/* Check FCS */ -bool SPP::checkFcs(uint8_t *data, uint8_t fcs) { - uint8_t temp = crc(data); - if((data[1] & 0xEF) != RFCOMM_UIH) - temp = pgm_read_byte(&rfcomm_crc_table[temp ^ data[2]]); // FCS on 3 bytes - return (pgm_read_byte(&rfcomm_crc_table[temp ^ fcs]) == 0xCF); -} - -/* Serial commands */ -#if defined(ARDUINO) && ARDUINO >=100 - -size_t SPP::write(uint8_t data) { - return write(&data, 1); -} -#else - -void SPP::write(uint8_t data) { - write(&data, 1); -} -#endif - -#if defined(ARDUINO) && ARDUINO >=100 - -size_t SPP::write(const uint8_t *data, size_t size) { -#else - -void SPP::write(const uint8_t *data, size_t size) { -#endif - for(uint8_t i = 0; i < size; i++) { - if(sppIndex >= sizeof (sppOutputBuffer) / sizeof (sppOutputBuffer[0])) - send(); // Send the current data in the buffer - sppOutputBuffer[sppIndex++] = data[i]; // All the bytes are put into a buffer and then send using the send() function - } -#if defined(ARDUINO) && ARDUINO >=100 - return size; -#endif -} - -void SPP::send() { - if(!connected || !sppIndex) - return; - uint8_t length; // This is the length of the string we are sending - uint8_t offset = 0; // This is used to keep track of where we are in the string - - l2capoutbuf[0] = rfcommChannelConnection | 0 | 0 | extendAddress; // RFCOMM Address - l2capoutbuf[1] = RFCOMM_UIH; // RFCOMM Control - - while(sppIndex) { // We will run this while loop until this variable is 0 - if(sppIndex > (sizeof (l2capoutbuf) - 4)) // Check if the string is larger than the outgoing buffer - length = sizeof (l2capoutbuf) - 4; - else - length = sppIndex; - - l2capoutbuf[2] = length << 1 | 1; // Length - uint8_t i = 0; - for(; i < length; i++) - l2capoutbuf[i + 3] = sppOutputBuffer[i + offset]; - l2capoutbuf[i + 3] = calcFcs(l2capoutbuf); // Calculate checksum - - RFCOMM_Command(l2capoutbuf, length + 4); - - sppIndex -= length; - offset += length; // Increment the offset - } -} - -int SPP::available(void) { - return rfcommAvailable; -}; - -void SPP::discard(void) { - rfcommAvailable = 0; -} - -int SPP::peek(void) { - if(rfcommAvailable == 0) // Don't read if there is nothing in the buffer - return -1; - return rfcommDataBuffer[0]; -} - -int SPP::read(void) { - if(rfcommAvailable == 0) // Don't read if there is nothing in the buffer - return -1; - uint8_t output = rfcommDataBuffer[0]; - for(uint8_t i = 1; i < rfcommAvailable; i++) - rfcommDataBuffer[i - 1] = rfcommDataBuffer[i]; // Shift the buffer one left - rfcommAvailable--; - bytesRead++; - if(bytesRead > (sizeof (rfcommDataBuffer) - 5)) { // We will send the command just before it runs out of credit - bytesRead = 0; - sendRfcommCredit(rfcommChannelConnection, rfcommDirection, 0, RFCOMM_UIH, 0x10, sizeof (rfcommDataBuffer)); // Send more credit -#ifdef EXTRADEBUG - Notify(PSTR("\r\nSent "), 0x80); - Notify((uint8_t)sizeof (rfcommDataBuffer), 0x80); - Notify(PSTR(" more credit"), 0x80); -#endif - } - return output; -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/SPP.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/SPP.h deleted file mode 100644 index 233ac611fd..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/SPP.h +++ /dev/null @@ -1,225 +0,0 @@ -/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. - - This software may be distributed and modified under the terms of the GNU - General Public License version 2 (GPL2) as published by the Free Software - Foundation and appearing in the file GPL2.TXT included in the packaging of - this file. Please note that GPL2 Section 2[b] requires that all works based - on this software must also be made publicly available under the terms of - the GPL2 ("Copyleft"). - - Contact information - ------------------- - - Kristian Lauszus, TKJ Electronics - Web : http://www.tkjelectronics.com - e-mail : kristianl@tkjelectronics.com - */ - -#ifndef _spp_h_ -#define _spp_h_ - -#include "BTD.h" - -/* Used for SDP */ -#define SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST_PDU 0x06 // See the RFCOMM specs -#define SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU 0x07 // See the RFCOMM specs -#define SERIALPORT_UUID 0x1101 // See http://www.bluetooth.org/Technical/AssignedNumbers/service_discovery.htm -#define L2CAP_UUID 0x0100 - -/* Used for RFCOMM */ -#define RFCOMM_SABM 0x2F -#define RFCOMM_UA 0x63 -#define RFCOMM_UIH 0xEF -//#define RFCOMM_DM 0x0F -#define RFCOMM_DISC 0x43 - -#define extendAddress 0x01 // Always 1 - -// Multiplexer message types -#define BT_RFCOMM_PN_CMD 0x83 -#define BT_RFCOMM_PN_RSP 0x81 -#define BT_RFCOMM_MSC_CMD 0xE3 -#define BT_RFCOMM_MSC_RSP 0xE1 -#define BT_RFCOMM_RPN_CMD 0x93 -#define BT_RFCOMM_RPN_RSP 0x91 -/* -#define BT_RFCOMM_TEST_CMD 0x23 -#define BT_RFCOMM_TEST_RSP 0x21 -#define BT_RFCOMM_FCON_CMD 0xA3 -#define BT_RFCOMM_FCON_RSP 0xA1 -#define BT_RFCOMM_FCOFF_CMD 0x63 -#define BT_RFCOMM_FCOFF_RSP 0x61 -#define BT_RFCOMM_RLS_CMD 0x53 -#define BT_RFCOMM_RLS_RSP 0x51 -#define BT_RFCOMM_NSC_RSP 0x11 - */ - -/** - * This BluetoothService class implements the Serial Port Protocol (SPP). - * It inherits the Arduino Stream class. This allows it to use all the standard Arduino print and stream functions. - */ -class SPP : public BluetoothService, public Stream { -public: - /** - * Constructor for the SPP class. - * @param p Pointer to BTD class instance. - * @param name Set the name to BTD#btdName. If argument is omitted, then "Arduino" will be used. - * @param pin Write the pin to BTD#btdPin. If argument is omitted, then "0000" will be used. - */ - SPP(BTD *p, const char *name = "Arduino", const char *pin = "0000"); - - /** @name BluetoothService implementation */ - /** Used this to disconnect the virtual serial port. */ - void disconnect(); - /**@}*/ - - /** - * Used to provide Boolean tests for the class. - * @return Return true if SPP communication is connected. - */ - operator bool() { - return connected; - } - /** Variable used to indicate if the connection is established. */ - bool connected; - - /** @name Serial port profile (SPP) Print functions */ - /** - * Get number of bytes waiting to be read. - * @return Return the number of bytes ready to be read. - */ - int available(void); - - /** Send out all bytes in the buffer. */ - void flush(void) { - send(); - }; - /** - * Used to read the next value in the buffer without advancing to the next one. - * @return Return the byte. Will return -1 if no bytes are available. - */ - int peek(void); - /** - * Used to read the buffer. - * @return Return the byte. Will return -1 if no bytes are available. - */ - int read(void); - -#if defined(ARDUINO) && ARDUINO >=100 - /** - * Writes the byte to send to a buffer. The message is send when either send() or after Usb.Task() is called. - * @param data The byte to write. - * @return Return the number of bytes written. - */ - size_t write(uint8_t data); - /** - * Writes the bytes to send to a buffer. The message is send when either send() or after Usb.Task() is called. - * @param data The data array to send. - * @param size Size of the data. - * @return Return the number of bytes written. - */ - size_t write(const uint8_t* data, size_t size); - /** Pull in write(const char *str) from Print */ - using Print::write; -#else - /** - * Writes the byte to send to a buffer. The message is send when either send() or after Usb.Task() is called. - * @param data The byte to write. - */ - void write(uint8_t data); - /** - * Writes the bytes to send to a buffer. The message is send when either send() or after Usb.Task() is called. - * @param data The data array to send. - * @param size Size of the data. - */ - void write(const uint8_t* data, size_t size); -#endif - - /** Discard all the bytes in the buffer. */ - void discard(void); - /** - * This will send all the bytes in the buffer. - * This is called whenever Usb.Task() is called, - * but can also be called via this function. - */ - void send(void); - /**@}*/ - -protected: - /** @name BluetoothService implementation */ - /** - * Used to pass acldata to the services. - * @param ACLData Incoming acldata. - */ - void ACLData(uint8_t* ACLData); - /** Used to establish the connection automatically. */ - void Run(); - /** Use this to reset the service. */ - void Reset(); - /** - * Called when a device is successfully initialized. - * Use attachOnInit(void (*funcOnInit)(void)) to call your own function. - * This is useful for instance if you want to set the LEDs in a specific way. - */ - void onInit(); - /**@}*/ - -private: - /* Set true when a channel is created */ - bool SDPConnected; - bool RFCOMMConnected; - - /* Variables used by L2CAP state machines */ - uint8_t l2cap_sdp_state; - uint8_t l2cap_rfcomm_state; - - uint8_t l2capoutbuf[BULK_MAXPKTSIZE]; // General purpose buffer for l2cap out data - uint8_t rfcommbuf[10]; // Buffer for RFCOMM Commands - - /* L2CAP Channels */ - uint8_t sdp_scid[2]; // L2CAP source CID for SDP - uint8_t sdp_dcid[2]; // 0x0050 - uint8_t rfcomm_scid[2]; // L2CAP source CID for RFCOMM - uint8_t rfcomm_dcid[2]; // 0x0051 - - /* RFCOMM Variables */ - uint8_t rfcommChannel; - uint8_t rfcommChannelConnection; // This is the channel the SPP channel will be running at - uint8_t rfcommDirection; - uint8_t rfcommCommandResponse; - uint8_t rfcommChannelType; - uint8_t rfcommPfBit; - - uint32_t timer; - bool waitForLastCommand; - bool creditSent; - - uint8_t rfcommDataBuffer[100]; // Create a 100 sized buffer for incoming data - uint8_t sppOutputBuffer[100]; // Create a 100 sized buffer for outgoing SPP data - uint8_t sppIndex; - uint8_t rfcommAvailable; - - bool firstMessage; // Used to see if it's the first SDP request received - uint8_t bytesRead; // Counter to see when it's time to send more credit - - /* State machines */ - void SDP_task(); // SDP state machine - void RFCOMM_task(); // RFCOMM state machine - - /* SDP Commands */ - void SDP_Command(uint8_t *data, uint8_t nbytes); - void serviceNotSupported(uint8_t transactionIDHigh, uint8_t transactionIDLow); - void serialPortResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow); - void serialPortResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow); - void l2capResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow); - void l2capResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow); - - /* RFCOMM Commands */ - void RFCOMM_Command(uint8_t *data, uint8_t nbytes); - void sendRfcomm(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t *data, uint8_t length); - void sendRfcommCredit(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t credit); - uint8_t calcFcs(uint8_t *data); - bool checkFcs(uint8_t *data, uint8_t fcs); - uint8_t crc(uint8_t *data); -}; -#endif diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/Usb.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/Usb.cpp deleted file mode 100644 index 14272588a1..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/Usb.cpp +++ /dev/null @@ -1,812 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ -/* USB functions */ - -#include "Usb.h" - -static uint8_t usb_error = 0; -static uint8_t usb_task_state; - -/* constructor */ -USB::USB() : bmHubPre(0) { - usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; //set up state machine - init(); -} - -/* Initialize data structures */ -void USB::init() { - //devConfigIndex = 0; - bmHubPre = 0; -} - -uint8_t USB::getUsbTaskState(void) { - return ( usb_task_state); -} - -void USB::setUsbTaskState(uint8_t state) { - usb_task_state = state; -} - -EpInfo* USB::getEpInfoEntry(uint8_t addr, uint8_t ep) { - UsbDevice *p = addrPool.GetUsbDevicePtr(addr); - - if(!p || !p->epinfo) - return NULL; - - EpInfo *pep = p->epinfo; - - for(uint8_t i = 0; i < p->epcount; i++) { - if((pep)->epAddr == ep) - return pep; - - pep++; - } - return NULL; -} - -/* set device table entry */ - -/* each device is different and has different number of endpoints. This function plugs endpoint record structure, defined in application, to devtable */ -uint8_t USB::setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo* eprecord_ptr) { - if(!eprecord_ptr) - return USB_ERROR_INVALID_ARGUMENT; - - UsbDevice *p = addrPool.GetUsbDevicePtr(addr); - - if(!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - p->address.devAddress = addr; - p->epinfo = eprecord_ptr; - p->epcount = epcount; - - return 0; -} - -uint8_t USB::SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t *nak_limit) { - UsbDevice *p = addrPool.GetUsbDevicePtr(addr); - - if(!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - if(!p->epinfo) - return USB_ERROR_EPINFO_IS_NULL; - - *ppep = getEpInfoEntry(addr, ep); - - if(!*ppep) - return USB_ERROR_EP_NOT_FOUND_IN_TBL; - - *nak_limit = (0x0001UL << (((*ppep)->bmNakPower > USB_NAK_MAX_POWER) ? USB_NAK_MAX_POWER : (*ppep)->bmNakPower)); - (*nak_limit)--; - /* - USBTRACE2("\r\nAddress: ", addr); - USBTRACE2(" EP: ", ep); - USBTRACE2(" NAK Power: ",(*ppep)->bmNakPower); - USBTRACE2(" NAK Limit: ", nak_limit); - USBTRACE("\r\n"); - */ - regWr(rPERADDR, addr); //set peripheral address - - uint8_t mode = regRd(rMODE); - - //Serial.print("\r\nMode: "); - //Serial.println( mode, HEX); - //Serial.print("\r\nLS: "); - //Serial.println(p->lowspeed, HEX); - - - - // Set bmLOWSPEED and bmHUBPRE in case of low-speed device, reset them otherwise - regWr(rMODE, (p->lowspeed) ? mode | bmLOWSPEED | bmHubPre : mode & ~(bmHUBPRE | bmLOWSPEED)); - - return 0; -} - -/* Control transfer. Sets address, endpoint, fills control packet with necessary data, dispatches control packet, and initiates bulk IN transfer, */ -/* depending on request. Actual requests are defined as inlines */ -/* return codes: */ -/* 00 = success */ - -/* 01-0f = non-zero HRSLT */ -uint8_t USB::ctrlReq(uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, - uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, USBReadParser *p) { - bool direction = false; //request direction, IN or OUT - uint8_t rcode; - SETUP_PKT setup_pkt; - - EpInfo *pep = NULL; - uint16_t nak_limit = 0; - - rcode = SetAddress(addr, ep, &pep, &nak_limit); - - if(rcode) - return rcode; - - direction = ((bmReqType & 0x80) > 0); - - /* fill in setup packet */ - setup_pkt.ReqType_u.bmRequestType = bmReqType; - setup_pkt.bRequest = bRequest; - setup_pkt.wVal_u.wValueLo = wValLo; - setup_pkt.wVal_u.wValueHi = wValHi; - setup_pkt.wIndex = wInd; - setup_pkt.wLength = total; - - bytesWr(rSUDFIFO, 8, (uint8_t*) & setup_pkt); //transfer to setup packet FIFO - - rcode = dispatchPkt(tokSETUP, ep, nak_limit); //dispatch packet - - if(rcode) //return HRSLT if not zero - return ( rcode); - - if(dataptr != NULL) //data stage, if present - { - if(direction) //IN transfer - { - uint16_t left = total; - - pep->bmRcvToggle = 1; //bmRCVTOG1; - - while(left) { - // Bytes read into buffer - uint16_t read = nbytes; - //uint16_t read = (leftbmRcvToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1; - continue; - } - - if(rcode) - return rcode; - - // Invoke callback function if inTransfer completed successfully and callback function pointer is specified - if(!rcode && p) - ((USBReadParser*)p)->Parse(read, dataptr, total - left); - - left -= read; - - if(read < nbytes) - break; - } - } else //OUT transfer - { - pep->bmSndToggle = 1; //bmSNDTOG1; - rcode = OutTransfer(pep, nak_limit, nbytes, dataptr); - } - if(rcode) //return error - return ( rcode); - } - // Status stage - return dispatchPkt((direction) ? tokOUTHS : tokINHS, ep, nak_limit); //GET if direction -} - -/* IN transfer to arbitrary endpoint. Assumes PERADDR is set. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */ -/* Keep sending INs and writes data to memory area pointed by 'data' */ - -/* rcode 0 if no errors. rcode 01-0f is relayed from dispatchPkt(). Rcode f0 means RCVDAVIRQ error, - fe USB xfer timeout */ -uint8_t USB::inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t* data) { - EpInfo *pep = NULL; - uint16_t nak_limit = 0; - - uint8_t rcode = SetAddress(addr, ep, &pep, &nak_limit); - - if(rcode) { - USBTRACE3("(USB::InTransfer) SetAddress Failed ", rcode, 0x81); - USBTRACE3("(USB::InTransfer) addr requested ", addr, 0x81); - USBTRACE3("(USB::InTransfer) ep requested ", ep, 0x81); - return rcode; - } - return InTransfer(pep, nak_limit, nbytesptr, data); -} - -uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t* data) { - uint8_t rcode = 0; - uint8_t pktsize; - - uint16_t nbytes = *nbytesptr; - //printf("Requesting %i bytes ", nbytes); - uint8_t maxpktsize = pep->maxPktSize; - - *nbytesptr = 0; - regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value - - // use a 'break' to exit this loop - while(1) { - rcode = dispatchPkt(tokIN, pep->epAddr, nak_limit); //IN packet to EP-'endpoint'. Function takes care of NAKS. - if(rcode == hrTOGERR) { - // yes, we flip it wrong here so that next time it is actually correct! - pep->bmRcvToggle = (regRd(rHRSL) & bmRCVTOGRD) ? 0 : 1; - regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value - continue; - } - if(rcode) { - //printf(">>>>>>>> Problem! dispatchPkt %2.2x\r\n", rcode); - break; //should be 0, indicating ACK. Else return error code. - } - /* check for RCVDAVIRQ and generate error if not present */ - /* the only case when absence of RCVDAVIRQ makes sense is when toggle error occurred. Need to add handling for that */ - if((regRd(rHIRQ) & bmRCVDAVIRQ) == 0) { - //printf(">>>>>>>> Problem! NO RCVDAVIRQ!\r\n"); - rcode = 0xf0; //receive error - break; - } - pktsize = regRd(rRCVBC); //number of received bytes - //printf("Got %i bytes \r\n", pktsize); - // This would be OK, but... - //assert(pktsize <= nbytes); - if(pktsize > nbytes) { - // This can happen. Use of assert on Arduino locks up the Arduino. - // So I will trim the value, and hope for the best. - //printf(">>>>>>>> Problem! Wanted %i bytes but got %i.\r\n", nbytes, pktsize); - pktsize = nbytes; - } - - int16_t mem_left = (int16_t)nbytes - *((int16_t*)nbytesptr); - - if(mem_left < 0) - mem_left = 0; - - data = bytesRd(rRCVFIFO, ((pktsize > mem_left) ? mem_left : pktsize), data); - - regWr(rHIRQ, bmRCVDAVIRQ); // Clear the IRQ & free the buffer - *nbytesptr += pktsize; // add this packet's byte count to total transfer length - - /* The transfer is complete under two conditions: */ - /* 1. The device sent a short packet (L.T. maxPacketSize) */ - /* 2. 'nbytes' have been transferred. */ - if((pktsize < maxpktsize) || (*nbytesptr >= nbytes)) // have we transferred 'nbytes' bytes? - { - // Save toggle value - pep->bmRcvToggle = ((regRd(rHRSL) & bmRCVTOGRD)) ? 1 : 0; - //printf("\r\n"); - rcode = 0; - break; - } // if - } //while( 1 ) - return ( rcode); -} - -/* OUT transfer to arbitrary endpoint. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */ -/* Handles NAK bug per Maxim Application Note 4000 for single buffer transfer */ - -/* rcode 0 if no errors. rcode 01-0f is relayed from HRSL */ -uint8_t USB::outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* data) { - EpInfo *pep = NULL; - uint16_t nak_limit = 0; - - uint8_t rcode = SetAddress(addr, ep, &pep, &nak_limit); - - if(rcode) - return rcode; - - return OutTransfer(pep, nak_limit, nbytes, data); -} - -uint8_t USB::OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8_t *data) { - uint8_t rcode = hrSUCCESS, retry_count; - uint8_t *data_p = data; //local copy of the data pointer - uint16_t bytes_tosend, nak_count; - uint16_t bytes_left = nbytes; - - uint8_t maxpktsize = pep->maxPktSize; - - if(maxpktsize < 1 || maxpktsize > 64) - return USB_ERROR_INVALID_MAX_PKT_SIZE; - - unsigned long timeout = millis() + USB_XFER_TIMEOUT; - - regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value - - while(bytes_left) { - retry_count = 0; - nak_count = 0; - bytes_tosend = (bytes_left >= maxpktsize) ? maxpktsize : bytes_left; - bytesWr(rSNDFIFO, bytes_tosend, data_p); //filling output FIFO - regWr(rSNDBC, bytes_tosend); //set number of bytes - regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet - while(!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ - regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ - rcode = (regRd(rHRSL) & 0x0f); - - while(rcode && ((long)(millis() - timeout) < 0L)) { - switch(rcode) { - case hrNAK: - nak_count++; - if(nak_limit && (nak_count == nak_limit)) - goto breakout; - //return ( rcode); - break; - case hrTIMEOUT: - retry_count++; - if(retry_count == USB_RETRY_LIMIT) - goto breakout; - //return ( rcode); - break; - case hrTOGERR: - // yes, we flip it wrong here so that next time it is actually correct! - pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1; - regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value - break; - default: - goto breakout; - }//switch( rcode - - /* process NAK according to Host out NAK bug */ - regWr(rSNDBC, 0); - regWr(rSNDFIFO, *data_p); - regWr(rSNDBC, bytes_tosend); - regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet - while(!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ - regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ - rcode = (regRd(rHRSL) & 0x0f); - }//while( rcode && .... - bytes_left -= bytes_tosend; - data_p += bytes_tosend; - }//while( bytes_left... -breakout: - - pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 1 : 0; //bmSNDTOG1 : bmSNDTOG0; //update toggle - return ( rcode); //should be 0 in all cases -} -/* dispatch USB packet. Assumes peripheral address is set and relevant buffer is loaded/empty */ -/* If NAK, tries to re-send up to nak_limit times */ -/* If nak_limit == 0, do not count NAKs, exit after timeout */ -/* If bus timeout, re-sends up to USB_RETRY_LIMIT times */ - -/* return codes 0x00-0x0f are HRSLT( 0x00 being success ), 0xff means timeout */ -uint8_t USB::dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit) { - unsigned long timeout = millis() + USB_XFER_TIMEOUT; - uint8_t tmpdata; - uint8_t rcode = hrSUCCESS; - uint8_t retry_count = 0; - uint16_t nak_count = 0; - - while((long)(millis() - timeout) < 0L) { - regWr(rHXFR, (token | ep)); //launch the transfer - rcode = USB_ERROR_TRANSFER_TIMEOUT; - - while((long)(millis() - timeout) < 0L) //wait for transfer completion - { - tmpdata = regRd(rHIRQ); - - if(tmpdata & bmHXFRDNIRQ) { - regWr(rHIRQ, bmHXFRDNIRQ); //clear the interrupt - rcode = 0x00; - break; - }//if( tmpdata & bmHXFRDNIRQ - - }//while ( millis() < timeout - - //if (rcode != 0x00) //exit if timeout - // return ( rcode); - - rcode = (regRd(rHRSL) & 0x0f); //analyze transfer result - - switch(rcode) { - case hrNAK: - nak_count++; - if(nak_limit && (nak_count == nak_limit)) - return (rcode); - break; - case hrTIMEOUT: - retry_count++; - if(retry_count == USB_RETRY_LIMIT) - return (rcode); - break; - default: - return (rcode); - }//switch( rcode - - }//while( timeout > millis() - return ( rcode); -} - -/* USB main task. Performs enumeration/cleanup */ -void USB::Task(void) //USB state machine -{ - uint8_t rcode; - uint8_t tmpdata; - static unsigned long delay = 0; - //USB_DEVICE_DESCRIPTOR buf; - bool lowspeed = false; - - MAX3421E::Task(); - - tmpdata = getVbusState(); - - /* modify USB task state if Vbus changed */ - switch(tmpdata) { - case SE1: //illegal state - usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL; - lowspeed = false; - break; - case SE0: //disconnected - if((usb_task_state & USB_STATE_MASK) != USB_STATE_DETACHED) - usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; - lowspeed = false; - break; - case LSHOST: - - lowspeed = true; - //intentional fallthrough - case FSHOST: //attached - if((usb_task_state & USB_STATE_MASK) == USB_STATE_DETACHED) { - delay = millis() + USB_SETTLE_DELAY; - usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE; - } - break; - }// switch( tmpdata - - for(uint8_t i = 0; i < USB_NUMDEVICES; i++) - if(devConfig[i]) - rcode = devConfig[i]->Poll(); - - switch(usb_task_state) { - case USB_DETACHED_SUBSTATE_INITIALIZE: - init(); - - for(uint8_t i = 0; i < USB_NUMDEVICES; i++) - if(devConfig[i]) - rcode = devConfig[i]->Release(); - - usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE; - break; - case USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE: //just sit here - break; - case USB_DETACHED_SUBSTATE_ILLEGAL: //just sit here - break; - case USB_ATTACHED_SUBSTATE_SETTLE: //settle time for just attached device - if((long)(millis() - delay) >= 0L) - usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE; - else break; // don't fall through - case USB_ATTACHED_SUBSTATE_RESET_DEVICE: - regWr(rHCTL, bmBUSRST); //issue bus reset - usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE; - break; - case USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE: - if((regRd(rHCTL) & bmBUSRST) == 0) { - tmpdata = regRd(rMODE) | bmSOFKAENAB; //start SOF generation - regWr(rMODE, tmpdata); - usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF; - //delay = millis() + 20; //20ms wait after reset per USB spec - } - break; - case USB_ATTACHED_SUBSTATE_WAIT_SOF: //todo: change check order - if(regRd(rHIRQ) & bmFRAMEIRQ) { - //when first SOF received _and_ 20ms has passed we can continue - /* - if (delay < millis()) //20ms passed - usb_task_state = USB_STATE_CONFIGURING; - */ - usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET; - delay = millis() + 20; - } - break; - case USB_ATTACHED_SUBSTATE_WAIT_RESET: - if((long)(millis() - delay) >= 0L) usb_task_state = USB_STATE_CONFIGURING; - else break; // don't fall through - case USB_STATE_CONFIGURING: - - //Serial.print("\r\nConf.LS: "); - //Serial.println(lowspeed, HEX); - - rcode = Configuring(0, 0, lowspeed); - - if(rcode) { - if(rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE) { - usb_error = rcode; - usb_task_state = USB_STATE_ERROR; - } - } else - usb_task_state = USB_STATE_RUNNING; - break; - case USB_STATE_RUNNING: - break; - case USB_STATE_ERROR: - //MAX3421E::Init(); - break; - } // switch( usb_task_state ) -} - -uint8_t USB::DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed) { - //uint8_t buf[12]; - uint8_t rcode; - UsbDevice *p0 = NULL, *p = NULL; - - // Get pointer to pseudo device with address 0 assigned - p0 = addrPool.GetUsbDevicePtr(0); - - if(!p0) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - if(!p0->epinfo) - return USB_ERROR_EPINFO_IS_NULL; - - p0->lowspeed = (lowspeed) ? true : false; - - // Allocate new address according to device class - uint8_t bAddress = addrPool.AllocAddress(parent, false, port); - - if(!bAddress) - return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; - - p = addrPool.GetUsbDevicePtr(bAddress); - - if(!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - p->lowspeed = lowspeed; - - // Assign new address to the device - rcode = setAddr(0, 0, bAddress); - - if(rcode) { - addrPool.FreeAddress(bAddress); - bAddress = 0; - return rcode; - } - return 0; -}; - -uint8_t USB::AttemptConfig(uint8_t driver, uint8_t parent, uint8_t port, bool lowspeed) { - //printf("AttemptConfig: parent = %i, port = %i\r\n", parent, port); - uint8_t retries = 0; - -again: - uint8_t rcode = devConfig[driver]->ConfigureDevice(parent, port, lowspeed); - if(rcode == USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET) { - if(parent == 0) { - // Send a bus reset on the root interface. - regWr(rHCTL, bmBUSRST); //issue bus reset - delay(102); // delay 102ms, compensate for clock inaccuracy. - } else { - // reset parent port - devConfig[parent]->ResetHubPort(port); - } - } else if(rcode == hrJERR && retries < 3) { // Some devices returns this when plugged in - trying to initialize the device again usually works - delay(100); - retries++; - goto again; - } else if(rcode) - return rcode; - - rcode = devConfig[driver]->Init(parent, port, lowspeed); - if(rcode == hrJERR && retries < 3) { // Some devices returns this when plugged in - trying to initialize the device again usually works - delay(100); - retries++; - goto again; - } - if(rcode) { - // Issue a bus reset, because the device may be in a limbo state - if(parent == 0) { - // Send a bus reset on the root interface. - regWr(rHCTL, bmBUSRST); //issue bus reset - delay(102); // delay 102ms, compensate for clock inaccuracy. - } else { - // reset parent port - devConfig[parent]->ResetHubPort(port); - } - } - return rcode; -} - -/* - * This is broken. We need to enumerate differently. - * It causes major problems with several devices if detected in an unexpected order. - * - * - * Oleg - I wouldn't do anything before the newly connected device is considered sane. - * i.e.(delays are not indicated for brevity): - * 1. reset - * 2. GetDevDescr(); - * 3a. If ACK, continue with allocating address, addressing, etc. - * 3b. Else reset again, count resets, stop at some number (5?). - * 4. When max.number of resets is reached, toggle power/fail - * If desired, this could be modified by performing two resets with GetDevDescr() in the middle - however, from my experience, if a device answers to GDD() - * it doesn't need to be reset again - * New steps proposal: - * 1: get address pool instance. exit on fail - * 2: pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf). exit on fail. - * 3: bus reset, 100ms delay - * 4: set address - * 5: pUsb->setEpInfoEntry(bAddress, 1, epInfo), exit on fail - * 6: while (configurations) { - * for(each configuration) { - * for (each driver) { - * 6a: Ask device if it likes configuration. Returns 0 on OK. - * If successful, the driver configured device. - * The driver now owns the endpoints, and takes over managing them. - * The following will need codes: - * Everything went well, instance consumed, exit with success. - * Instance already in use, ignore it, try next driver. - * Not a supported device, ignore it, try next driver. - * Not a supported configuration for this device, ignore it, try next driver. - * Could not configure device, fatal, exit with fail. - * } - * } - * } - * 7: for(each driver) { - * 7a: Ask device if it knows this VID/PID. Acts exactly like 6a, but using VID/PID - * 8: if we get here, no driver likes the device plugged in, so exit failure. - * - */ -uint8_t USB::Configuring(uint8_t parent, uint8_t port, bool lowspeed) { - //uint8_t bAddress = 0; - //printf("Configuring: parent = %i, port = %i\r\n", parent, port); - uint8_t devConfigIndex; - uint8_t rcode = 0; - uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)]; - USB_DEVICE_DESCRIPTOR *udd = reinterpret_cast(buf); - UsbDevice *p = NULL; - EpInfo *oldep_ptr = NULL; - EpInfo epInfo; - - epInfo.epAddr = 0; - epInfo.maxPktSize = 8; - epInfo.epAttribs = 0; - epInfo.bmNakPower = USB_NAK_MAX_POWER; - - //delay(2000); - AddressPool &addrPool = GetAddressPool(); - // Get pointer to pseudo device with address 0 assigned - p = addrPool.GetUsbDevicePtr(0); - if(!p) { - //printf("Configuring error: USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL\r\n"); - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - } - - // Save old pointer to EP_RECORD of address 0 - oldep_ptr = p->epinfo; - - // Temporary assign new pointer to epInfo to p->epinfo in order to - // avoid toggle inconsistence - - p->epinfo = &epInfo; - - p->lowspeed = lowspeed; - // Get device descriptor - rcode = getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); - - // Restore p->epinfo - p->epinfo = oldep_ptr; - - if(rcode) { - //printf("Configuring error: Can't get USB_DEVICE_DESCRIPTOR\r\n"); - return rcode; - } - - // to-do? - // Allocate new address according to device class - //bAddress = addrPool.AllocAddress(parent, false, port); - - uint16_t vid = udd->idVendor; - uint16_t pid = udd->idProduct; - uint8_t klass = udd->bDeviceClass; - uint8_t subklass = udd->bDeviceSubClass; - // Attempt to configure if VID/PID or device class matches with a driver - // Qualify with subclass too. - // - // VID/PID & class tests default to false for drivers not yet ported - // subclass defaults to true, so you don't have to define it if you don't have to. - // - for(devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) { - if(!devConfig[devConfigIndex]) continue; // no driver - if(devConfig[devConfigIndex]->GetAddress()) continue; // consumed - if(devConfig[devConfigIndex]->DEVSUBCLASSOK(subklass) && (devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass))) { - rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed); - if(rcode != USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED) - break; - } - } - - if(devConfigIndex < USB_NUMDEVICES) { - return rcode; - } - - - // blindly attempt to configure - for(devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) { - if(!devConfig[devConfigIndex]) continue; - if(devConfig[devConfigIndex]->GetAddress()) continue; // consumed - if(devConfig[devConfigIndex]->DEVSUBCLASSOK(subklass) && (devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass))) continue; // If this is true it means it must have returned USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED above - rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed); - - //printf("ERROR ENUMERATING %2.2x\r\n", rcode); - if(!(rcode == USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED || rcode == USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE)) { - // in case of an error dev_index should be reset to 0 - // in order to start from the very beginning the - // next time the program gets here - //if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE) - // devConfigIndex = 0; - return rcode; - } - } - // if we get here that means that the device class is not supported by any of registered classes - rcode = DefaultAddressing(parent, port, lowspeed); - - return rcode; -} - -uint8_t USB::ReleaseDevice(uint8_t addr) { - if(!addr) - return 0; - - for(uint8_t i = 0; i < USB_NUMDEVICES; i++) { - if(!devConfig[i]) continue; - if(devConfig[i]->GetAddress() == addr) - return devConfig[i]->Release(); - } - return 0; -} - -#if 1 //!defined(USB_METHODS_INLINE) -//get device descriptor - -uint8_t USB::getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr) { - return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, nbytes, dataptr, NULL)); -} -//get configuration descriptor - -uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr) { - return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, nbytes, dataptr, NULL)); -} - -/* Requests Configuration Descriptor. Sends two Get Conf Descr requests. The first one gets the total length of all descriptors, then the second one requests this - total length. The length of the first request can be shorter ( 4 bytes ), however, there are devices which won't work unless this length is set to 9 */ -uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser *p) { - const uint8_t bufSize = 64; - uint8_t buf[bufSize]; - USB_CONFIGURATION_DESCRIPTOR *ucd = reinterpret_cast(buf); - - uint8_t ret = getConfDescr(addr, ep, 9, conf, buf); - - if(ret) - return ret; - - uint16_t total = ucd->wTotalLength; - - //USBTRACE2("\r\ntotal conf.size:", total); - - return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, total, bufSize, buf, p)); -} - -//get string descriptor - -uint8_t USB::getStrDescr(uint8_t addr, uint8_t ep, uint16_t ns, uint8_t index, uint16_t langid, uint8_t* dataptr) { - return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, ns, ns, dataptr, NULL)); -} -//set address - -uint8_t USB::setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr) { - uint8_t rcode = ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL); - //delay(2); //per USB 2.0 sect.9.2.6.3 - delay(300); // Older spec says you should wait at least 200ms - return rcode; - //return ( ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL)); -} -//set configuration - -uint8_t USB::setConf(uint8_t addr, uint8_t ep, uint8_t conf_value) { - return ( ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL)); -} - -#endif // defined(USB_METHODS_INLINE) diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/Usb.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/Usb.h deleted file mode 100644 index 47bd626cce..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/Usb.h +++ /dev/null @@ -1,41 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ -/* USB functions */ -#ifndef _usb_h_ -#define _usb_h_ - -// WARNING: Do not change the order of includes, or stuff will break! -#include -#include -#include - -// None of these should ever be included by a driver, or a user's sketch. -#include "settings.h" -#include "printhex.h" -#include "message.h" -#include "hexdump.h" -#include "sink_parser.h" -#include "max3421e.h" -#include "address.h" -#include "avrpins.h" -#include "usb_ch9.h" -#include "usbhost.h" -#include "UsbCore.h" -#include "parsetools.h" -#include "confdescparser.h" - -#endif //_usb_h_ diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/UsbCore.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/UsbCore.h deleted file mode 100644 index 5c6c771017..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/UsbCore.h +++ /dev/null @@ -1,298 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ - -#if !defined(_usb_h_) || defined(USBCORE_H) -#error "Never include UsbCore.h directly; include Usb.h instead" -#else -#define USBCORE_H - -// Not used anymore? If anyone uses this, please let us know so that this may be -// moved to the proper place, settings.h. -//#define USB_METHODS_INLINE - -/* shield pins. First parameter - SS pin, second parameter - INT pin */ -#ifdef BOARD_BLACK_WIDDOW -typedef MAX3421e MAX3421E; // Black Widow -#elif defined(CORE_TEENSY) && (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)) -#if EXT_RAM -typedef MAX3421e MAX3421E; // Teensy++ 2.0 with XMEM2 -#else -typedef MAX3421e MAX3421E; // Teensy++ 1.0 and 2.0 -#endif -#elif defined(BOARD_MEGA_ADK) -typedef MAX3421e MAX3421E; // Arduino Mega ADK -#elif defined(ARDUINO_AVR_BALANDUINO) -typedef MAX3421e MAX3421E; // Balanduino -#elif defined(__ARDUINO_X86__) && PLATFORM_ID == 0x06 -typedef MAX3421e MAX3421E; // The Intel Galileo supports much faster read and write speed at pin 2 and 3 -#else -typedef MAX3421e MAX3421E; // Official Arduinos (UNO, Duemilanove, Mega, 2560, Leonardo, Due etc.), Intel Edison, Intel Galileo 2 or Teensy 2.0 and 3.0 -#endif - -/* Common setup data constant combinations */ -#define bmREQ_GET_DESCR USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE //get descriptor request type -#define bmREQ_SET USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE //set request type for all but 'set feature' and 'set interface' -#define bmREQ_CL_GET_INTF USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE //get interface request type - -// D7 data transfer direction (0 - host-to-device, 1 - device-to-host) -// D6-5 Type (0- standard, 1 - class, 2 - vendor, 3 - reserved) -// D4-0 Recipient (0 - device, 1 - interface, 2 - endpoint, 3 - other, 4..31 - reserved) - -// USB Device Classes -#define USB_CLASS_USE_CLASS_INFO 0x00 // Use Class Info in the Interface Descriptors -#define USB_CLASS_AUDIO 0x01 // Audio -#define USB_CLASS_COM_AND_CDC_CTRL 0x02 // Communications and CDC Control -#define USB_CLASS_HID 0x03 // HID -#define USB_CLASS_PHYSICAL 0x05 // Physical -#define USB_CLASS_IMAGE 0x06 // Image -#define USB_CLASS_PRINTER 0x07 // Printer -#define USB_CLASS_MASS_STORAGE 0x08 // Mass Storage -#define USB_CLASS_HUB 0x09 // Hub -#define USB_CLASS_CDC_DATA 0x0a // CDC-Data -#define USB_CLASS_SMART_CARD 0x0b // Smart-Card -#define USB_CLASS_CONTENT_SECURITY 0x0d // Content Security -#define USB_CLASS_VIDEO 0x0e // Video -#define USB_CLASS_PERSONAL_HEALTH 0x0f // Personal Healthcare -#define USB_CLASS_DIAGNOSTIC_DEVICE 0xdc // Diagnostic Device -#define USB_CLASS_WIRELESS_CTRL 0xe0 // Wireless Controller -#define USB_CLASS_MISC 0xef // Miscellaneous -#define USB_CLASS_APP_SPECIFIC 0xfe // Application Specific -#define USB_CLASS_VENDOR_SPECIFIC 0xff // Vendor Specific - -// Additional Error Codes -#define USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED 0xD1 -#define USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE 0xD2 -#define USB_ERROR_UNABLE_TO_REGISTER_DEVICE_CLASS 0xD3 -#define USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL 0xD4 -#define USB_ERROR_HUB_ADDRESS_OVERFLOW 0xD5 -#define USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL 0xD6 -#define USB_ERROR_EPINFO_IS_NULL 0xD7 -#define USB_ERROR_INVALID_ARGUMENT 0xD8 -#define USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE 0xD9 -#define USB_ERROR_INVALID_MAX_PKT_SIZE 0xDA -#define USB_ERROR_EP_NOT_FOUND_IN_TBL 0xDB -#define USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET 0xE0 -#define USB_ERROR_FailGetDevDescr 0xE1 -#define USB_ERROR_FailSetDevTblEntry 0xE2 -#define USB_ERROR_FailGetConfDescr 0xE3 -#define USB_ERROR_TRANSFER_TIMEOUT 0xFF - -#define USB_XFER_TIMEOUT 5000 // (5000) USB transfer timeout in milliseconds, per section 9.2.6.1 of USB 2.0 spec -//#define USB_NAK_LIMIT 32000 // NAK limit for a transfer. 0 means NAKs are not counted -#define USB_RETRY_LIMIT 3 // 3 retry limit for a transfer -#define USB_SETTLE_DELAY 200 // settle delay in milliseconds - -#define USB_NUMDEVICES 16 //number of USB devices -//#define HUB_MAX_HUBS 7 // maximum number of hubs that can be attached to the host controller -#define HUB_PORT_RESET_DELAY 20 // hub port reset delay 10 ms recomended, can be up to 20 ms - -/* USB state machine states */ -#define USB_STATE_MASK 0xf0 - -#define USB_STATE_DETACHED 0x10 -#define USB_DETACHED_SUBSTATE_INITIALIZE 0x11 -#define USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE 0x12 -#define USB_DETACHED_SUBSTATE_ILLEGAL 0x13 -#define USB_ATTACHED_SUBSTATE_SETTLE 0x20 -#define USB_ATTACHED_SUBSTATE_RESET_DEVICE 0x30 -#define USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE 0x40 -#define USB_ATTACHED_SUBSTATE_WAIT_SOF 0x50 -#define USB_ATTACHED_SUBSTATE_WAIT_RESET 0x51 -#define USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE 0x60 -#define USB_STATE_ADDRESSING 0x70 -#define USB_STATE_CONFIGURING 0x80 -#define USB_STATE_RUNNING 0x90 -#define USB_STATE_ERROR 0xa0 - -class USBDeviceConfig { -public: - - virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed) { - return 0; - } - - virtual uint8_t ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) { - return 0; - } - - virtual uint8_t Release() { - return 0; - } - - virtual uint8_t Poll() { - return 0; - } - - virtual uint8_t GetAddress() { - return 0; - } - - virtual void ResetHubPort(uint8_t port) { - return; - } // Note used for hubs only! - - virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) { - return false; - } - - virtual bool DEVCLASSOK(uint8_t klass) { - return false; - } - - virtual bool DEVSUBCLASSOK(uint8_t subklass) { - return true; - } - -}; - -/* USB Setup Packet Structure */ -typedef struct { - - union { // offset description - uint8_t bmRequestType; // 0 Bit-map of request type - - struct { - uint8_t recipient : 5; // Recipient of the request - uint8_t type : 2; // Type of request - uint8_t direction : 1; // Direction of data X-fer - } __attribute__((packed)); - } ReqType_u; - uint8_t bRequest; // 1 Request - - union { - uint16_t wValue; // 2 Depends on bRequest - - struct { - uint8_t wValueLo; - uint8_t wValueHi; - } __attribute__((packed)); - } wVal_u; - uint16_t wIndex; // 4 Depends on bRequest - uint16_t wLength; // 6 Depends on bRequest -} __attribute__((packed)) SETUP_PKT, *PSETUP_PKT; - - - -// Base class for incoming data parser - -class USBReadParser { -public: - virtual void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset) = 0; -}; - -class USB : public MAX3421E { - AddressPoolImpl addrPool; - USBDeviceConfig* devConfig[USB_NUMDEVICES]; - uint8_t bmHubPre; - -public: - USB(void); - - void SetHubPreMask() { - bmHubPre |= bmHUBPRE; - }; - - void ResetHubPreMask() { - bmHubPre &= (~bmHUBPRE); - }; - - AddressPool& GetAddressPool() { - return (AddressPool&)addrPool; - }; - - uint8_t RegisterDeviceClass(USBDeviceConfig *pdev) { - for(uint8_t i = 0; i < USB_NUMDEVICES; i++) { - if(!devConfig[i]) { - devConfig[i] = pdev; - return 0; - } - } - return USB_ERROR_UNABLE_TO_REGISTER_DEVICE_CLASS; - }; - - void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) { - addrPool.ForEachUsbDevice(pfunc); - }; - uint8_t getUsbTaskState(void); - void setUsbTaskState(uint8_t state); - - EpInfo* getEpInfoEntry(uint8_t addr, uint8_t ep); - uint8_t setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo* eprecord_ptr); - - /* Control requests */ - uint8_t getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr); - uint8_t getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr); - - uint8_t getConfDescr(uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser *p); - - uint8_t getStrDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t index, uint16_t langid, uint8_t* dataptr); - uint8_t setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr); - uint8_t setConf(uint8_t addr, uint8_t ep, uint8_t conf_value); - /**/ - uint8_t ctrlData(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr, bool direction); - uint8_t ctrlStatus(uint8_t ep, bool direction, uint16_t nak_limit); - uint8_t inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t* data); - uint8_t outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* data); - uint8_t dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit); - - void Task(void); - - uint8_t DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed); - uint8_t Configuring(uint8_t parent, uint8_t port, bool lowspeed); - uint8_t ReleaseDevice(uint8_t addr); - - uint8_t ctrlReq(uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, - uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, USBReadParser *p); - -private: - void init(); - uint8_t SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t *nak_limit); - uint8_t OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8_t *data); - uint8_t InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t *data); - uint8_t AttemptConfig(uint8_t driver, uint8_t parent, uint8_t port, bool lowspeed); -}; - -#if 0 //defined(USB_METHODS_INLINE) -//get device descriptor - -inline uint8_t USB::getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr) { - return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, dataptr)); -} -//get configuration descriptor - -inline uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr) { - return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, dataptr)); -} -//get string descriptor - -inline uint8_t USB::getStrDescr(uint8_t addr, uint8_t ep, uint16_t nuint8_ts, uint8_t index, uint16_t langid, uint8_t* dataptr) { - return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, nuint8_ts, dataptr)); -} -//set address - -inline uint8_t USB::setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr) { - return ( ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, NULL)); -} -//set configuration - -inline uint8_t USB::setConf(uint8_t addr, uint8_t ep, uint8_t conf_value) { - return ( ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, NULL)); -} - -#endif // defined(USB_METHODS_INLINE) - -#endif /* USBCORE_H */ diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/Wii.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/Wii.cpp deleted file mode 100755 index 4bbf4c91cb..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/Wii.cpp +++ /dev/null @@ -1,1268 +0,0 @@ -/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. - - This software may be distributed and modified under the terms of the GNU - General Public License version 2 (GPL2) as published by the Free Software - Foundation and appearing in the file GPL2.TXT included in the packaging of - this file. Please note that GPL2 Section 2[b] requires that all works based - on this software must also be made publicly available under the terms of - the GPL2 ("Copyleft"). - - Contact information - ------------------- - - Kristian Lauszus, TKJ Electronics - Web : http://www.tkjelectronics.com - e-mail : kristianl@tkjelectronics.com - - IR camera support added by Allan Glover (adglover9.81@gmail.com) and Kristian Lauszus - */ - -#include "Wii.h" -// To enable serial debugging see "settings.h" -//#define EXTRADEBUG // Uncomment to get even more debugging data -//#define PRINTREPORT // Uncomment to print the report send by the Wii controllers - -const uint8_t WII_LEDS[] PROGMEM = { - 0x00, // OFF - 0x10, // LED1 - 0x20, // LED2 - 0x40, // LED3 - 0x80, // LED4 - - 0x90, // LED5 - 0xA0, // LED6 - 0xC0, // LED7 - 0xD0, // LED8 - 0xE0, // LED9 - 0xF0, // LED10 -}; - -const uint32_t WII_BUTTONS[] PROGMEM = { - 0x00008, // UP - 0x00002, // RIGHT - 0x00004, // DOWN - 0x00001, // LEFT - - 0, // Skip - 0x00010, // PLUS - 0x00100, // TWO - 0x00200, // ONE - - 0x01000, // MINUS - 0x08000, // HOME - 0x10000, // Z - 0x20000, // C - - 0x00400, // B - 0x00800, // A -}; -const uint32_t WII_PROCONTROLLER_BUTTONS[] PROGMEM = { - 0x00100, // UP - 0x00080, // RIGHT - 0x00040, // DOWN - 0x00200, // LEFT - - 0, // Skip - 0x00004, // PLUS - 0x20000, // L3 - 0x10000, // R3 - - 0x00010, // MINUS - 0x00008, // HOME - 0, 0, // Skip - - 0x04000, // B - 0x01000, // A - 0x00800, // X - 0x02000, // Y - - 0x00020, // L - 0x00002, // R - 0x08000, // ZL - 0x00400, // ZR -}; - -WII::WII(BTD *p, bool pair) : -BluetoothService(p) // Pointer to USB class instance - mandatory -{ - pBtd->pairWithWii = pair; - - HIDBuffer[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) - - /* Set device cid for the control and intterrupt channelse - LSB */ - control_dcid[0] = 0x60; // 0x0060 - control_dcid[1] = 0x00; - interrupt_dcid[0] = 0x61; // 0x0061 - interrupt_dcid[1] = 0x00; - - Reset(); -} - -void WII::Reset() { - wiimoteConnected = false; - nunchuckConnected = false; - motionPlusConnected = false; - activateNunchuck = false; - motionValuesReset = false; - activeConnection = false; - motionPlusInside = false; - pBtd->wiiUProController = false; - wiiUProControllerConnected = false; - wiiBalanceBoardConnected = false; - l2cap_event_flag = 0; // Reset flags - l2cap_state = L2CAP_WAIT; -} - -void WII::disconnect() { // Use this void to disconnect any of the controllers - if(!motionPlusInside) { // The old Wiimote needs a delay after the first command or it will automatically reconnect - if(motionPlusConnected) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nDeactivating Motion Plus"), 0x80); -#endif - initExtension1(); // This will disable the Motion Plus extension - } - timer = millis() + 1000; // We have to wait for the message before the rest of the channels can be deactivated - } else - timer = millis(); // Don't wait - // First the HID interrupt channel has to be disconnected, then the HID control channel and finally the HCI connection - pBtd->l2cap_disconnection_request(hci_handle, ++identifier, interrupt_scid, interrupt_dcid); - Reset(); - l2cap_state = L2CAP_INTERRUPT_DISCONNECT; -} - -void WII::ACLData(uint8_t* l2capinbuf) { - if(!pBtd->l2capConnectionClaimed && pBtd->incomingWii && !wiimoteConnected && !activeConnection) { - if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { - if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) { - motionPlusInside = pBtd->motionPlusInside; - pBtd->incomingWii = false; - pBtd->l2capConnectionClaimed = true; // Claim that the incoming connection belongs to this service - activeConnection = true; - hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection - l2cap_state = L2CAP_WAIT; - } - } - } - - if(checkHciHandle(l2capinbuf, hci_handle)) { // acl_handle_ok - if((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001U) { // l2cap_control - Channel ID for ACL-U - if(l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80); - D_PrintHex (l2capinbuf[13], 0x80); - Notify(PSTR(" "), 0x80); - D_PrintHex (l2capinbuf[12], 0x80); - Notify(PSTR(" "), 0x80); - D_PrintHex (l2capinbuf[17], 0x80); - Notify(PSTR(" "), 0x80); - D_PrintHex (l2capinbuf[16], 0x80); - Notify(PSTR(" "), 0x80); - D_PrintHex (l2capinbuf[15], 0x80); - Notify(PSTR(" "), 0x80); - D_PrintHex (l2capinbuf[14], 0x80); -#endif - } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_RESPONSE) { - if(((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) && ((l2capinbuf[18] | (l2capinbuf[19] << 8)) == SUCCESSFUL)) { // Success - if(l2capinbuf[14] == control_dcid[0] && l2capinbuf[15] == control_dcid[1]) { - //Notify(PSTR("\r\nHID Control Connection Complete"), 0x80); - identifier = l2capinbuf[9]; - control_scid[0] = l2capinbuf[12]; - control_scid[1] = l2capinbuf[13]; - l2cap_set_flag(L2CAP_FLAG_CONTROL_CONNECTED); - } else if(l2capinbuf[14] == interrupt_dcid[0] && l2capinbuf[15] == interrupt_dcid[1]) { - //Notify(PSTR("\r\nHID Interrupt Connection Complete"), 0x80); - identifier = l2capinbuf[9]; - interrupt_scid[0] = l2capinbuf[12]; - interrupt_scid[1] = l2capinbuf[13]; - l2cap_set_flag(L2CAP_FLAG_INTERRUPT_CONNECTED); - } - } - } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { -#ifdef EXTRADEBUG - Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80); - D_PrintHex (l2capinbuf[13], 0x80); - Notify(PSTR(" "), 0x80); - D_PrintHex (l2capinbuf[12], 0x80); - Notify(PSTR(" SCID: "), 0x80); - D_PrintHex (l2capinbuf[15], 0x80); - Notify(PSTR(" "), 0x80); - D_PrintHex (l2capinbuf[14], 0x80); - Notify(PSTR(" Identifier: "), 0x80); - D_PrintHex (l2capinbuf[9], 0x80); -#endif - if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) { - identifier = l2capinbuf[9]; - control_scid[0] = l2capinbuf[14]; - control_scid[1] = l2capinbuf[15]; - l2cap_set_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST); - } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_INTR_PSM) { - identifier = l2capinbuf[9]; - interrupt_scid[0] = l2capinbuf[14]; - interrupt_scid[1] = l2capinbuf[15]; - l2cap_set_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST); - } - } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) { - if((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success - if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { - //Notify(PSTR("\r\nHID Control Configuration Complete"), 0x80); - identifier = l2capinbuf[9]; - l2cap_set_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS); - } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { - //Notify(PSTR("\r\nHID Interrupt Configuration Complete"), 0x80); - identifier = l2capinbuf[9]; - l2cap_set_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS); - } - } - } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) { - if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { - //Notify(PSTR("\r\nHID Control Configuration Request"), 0x80); - pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], control_scid); - } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { - //Notify(PSTR("\r\nHID Interrupt Configuration Request"), 0x80); - pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], interrupt_scid); - } - } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) { - if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nDisconnect Request: Control Channel"), 0x80); -#endif - identifier = l2capinbuf[9]; - pBtd->l2cap_disconnection_response(hci_handle, identifier, control_dcid, control_scid); - Reset(); - } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nDisconnect Request: Interrupt Channel"), 0x80); -#endif - identifier = l2capinbuf[9]; - pBtd->l2cap_disconnection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid); - Reset(); - } - } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) { - if(l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) { - //Notify(PSTR("\r\nDisconnect Response: Control Channel"), 0x80); - identifier = l2capinbuf[9]; - l2cap_set_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE); - } else if(l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) { - //Notify(PSTR("\r\nDisconnect Response: Interrupt Channel"), 0x80); - identifier = l2capinbuf[9]; - l2cap_set_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE); - } - } -#ifdef EXTRADEBUG - else { - identifier = l2capinbuf[9]; - Notify(PSTR("\r\nL2CAP Unknown Signaling Command: "), 0x80); - D_PrintHex (l2capinbuf[8], 0x80); - } -#endif - } else if(l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt - //Notify(PSTR("\r\nL2CAP Interrupt"), 0x80); - if(l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT - if((l2capinbuf[9] >= 0x20 && l2capinbuf[9] <= 0x22) || (l2capinbuf[9] >= 0x30 && l2capinbuf[9] <= 0x37) || l2capinbuf[9] == 0x3e || l2capinbuf[9] == 0x3f) { // These reports include the buttons - if((l2capinbuf[9] >= 0x20 && l2capinbuf[9] <= 0x22) || l2capinbuf[9] == 0x31 || l2capinbuf[9] == 0x33) // These reports have no extensions bytes - ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8)); - else if(wiiUProControllerConnected) - ButtonState = (uint32_t)(((~l2capinbuf[23]) & 0xFE) | ((uint16_t)(~l2capinbuf[24]) << 8) | ((uint32_t)((~l2capinbuf[25]) & 0x03) << 16)); - else if(motionPlusConnected) { - if(l2capinbuf[20] & 0x02) // Only update the Wiimote buttons, since the extension bytes are from the Motion Plus - ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8) | ((uint32_t)(ButtonState & 0xFFFF0000))); - else if(nunchuckConnected) // Update if it's a report from the Nunchuck - ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8) | ((uint32_t)((~l2capinbuf[20]) & 0x0C) << 14)); - //else if(classicControllerConnected) // Update if it's a report from the Classic Controller - } else if(nunchuckConnected) // The Nunchuck is directly connected - ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8) | ((uint32_t)((~l2capinbuf[20]) & 0x03) << 16)); - //else if(classicControllerConnected) // The Classic Controller is directly connected - else if(!unknownExtensionConnected) - ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8)); -#ifdef PRINTREPORT - Notify(PSTR("ButtonState: "), 0x80); - D_PrintHex (ButtonState, 0x80); - Notify(PSTR("\r\n"), 0x80); -#endif - if(ButtonState != OldButtonState) { - ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable - OldButtonState = ButtonState; - } - } - if(l2capinbuf[9] == 0x31 || l2capinbuf[9] == 0x33 || l2capinbuf[9] == 0x35 || l2capinbuf[9] == 0x37) { // Read the accelerometer - accXwiimote = ((l2capinbuf[12] << 2) | (l2capinbuf[10] & 0x60 >> 5)) - 500; - accYwiimote = ((l2capinbuf[13] << 2) | (l2capinbuf[11] & 0x20 >> 4)) - 500; - accZwiimote = ((l2capinbuf[14] << 2) | (l2capinbuf[11] & 0x40 >> 5)) - 500; - } - switch(l2capinbuf[9]) { - case 0x20: // Status Information - (a1) 20 BB BB LF 00 00 VV -#ifdef EXTRADEBUG - Notify(PSTR("\r\nStatus report was received"), 0x80); -#endif - wiiState = l2capinbuf[12]; // (0x01: Battery is nearly empty), (0x02: An Extension Controller is connected), (0x04: Speaker enabled), (0x08: IR enabled), (0x10: LED1, 0x20: LED2, 0x40: LED3, 0x80: LED4) - batteryLevel = l2capinbuf[15]; // Update battery level - - if(!checkBatteryLevel) { // If this is true it means that the user must have called getBatteryLevel() - if(l2capinbuf[12] & 0x02) { // Check if a extension is connected -#ifdef DEBUG_USB_HOST - if(!unknownExtensionConnected) - Notify(PSTR("\r\nExtension connected"), 0x80); -#endif - unknownExtensionConnected = true; -#ifdef WIICAMERA - if(!isIRCameraEnabled()) // Don't activate the Motion Plus if we are trying to initialize the IR camera -#endif - setReportMode(false, 0x35); // Also read the extension - } else { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nExtension disconnected"), 0x80); -#endif - if(motionPlusConnected) { -#ifdef DEBUG_USB_HOST - Notify(PSTR(" - from Motion Plus"), 0x80); -#endif - wii_clear_flag(WII_FLAG_NUNCHUCK_CONNECTED); - if(!activateNunchuck) // If it's already trying to initialize the Nunchuck don't set it to false - nunchuckConnected = false; - //else if(classicControllerConnected) - } else if(nunchuckConnected) { -#ifdef DEBUG_USB_HOST - Notify(PSTR(" - Nunchuck"), 0x80); -#endif - nunchuckConnected = false; // It must be the Nunchuck controller then - wii_clear_flag(WII_FLAG_NUNCHUCK_CONNECTED); - onInit(); - setReportMode(false, 0x31); // If there is no extension connected we will read the buttons and accelerometer - } else - setReportMode(false, 0x31); // If there is no extension connected we will read the buttons and accelerometer - } - } - else { -#ifdef EXTRADEBUG - Notify(PSTR("\r\nChecking battery level"), 0x80); -#endif - checkBatteryLevel = false; // Check for extensions by default - } -#ifdef DEBUG_USB_HOST - if(l2capinbuf[12] & 0x01) - Notify(PSTR("\r\nWARNING: Battery is nearly empty"), 0x80); -#endif - - break; - case 0x21: // Read Memory Data - if((l2capinbuf[12] & 0x0F) == 0) { // No error - uint8_t reportLength = (l2capinbuf[12] >> 4) + 1; // // Bit 4-7 is the length - 1 - // See: http://wiibrew.org/wiki/Wiimote/Extension_Controllers - if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x00 && l2capinbuf[20] == 0x00) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nNunchuck connected"), 0x80); -#endif - wii_set_flag(WII_FLAG_NUNCHUCK_CONNECTED); - } else if(l2capinbuf[16] == 0x00 && (l2capinbuf[17] == 0xA6 || l2capinbuf[17] == 0xA4) && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x00 && l2capinbuf[20] == 0x05) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nMotion Plus connected"), 0x80); -#endif - wii_set_flag(WII_FLAG_MOTION_PLUS_CONNECTED); - } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x04 && l2capinbuf[20] == 0x05) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nMotion Plus activated in normal mode"), 0x80); -#endif - motionPlusConnected = true; -#ifdef WIICAMERA - if(!isIRCameraEnabled()) // Don't activate the Motion Plus if we are trying to initialize the IR camera -#endif - setReportMode(false, 0x35); // Also read the extension - } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x05 && l2capinbuf[20] == 0x05) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nMotion Plus activated in Nunchuck pass-through mode"), 0x80); -#endif - activateNunchuck = false; - motionPlusConnected = true; - nunchuckConnected = true; -#ifdef WIICAMERA - if(!isIRCameraEnabled()) // Don't activate the Motion Plus if we are trying to initialize the IR camera -#endif - setReportMode(false, 0x35); // Also read the extension - } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA6 && l2capinbuf[18] == 0x20 && (l2capinbuf[19] == 0x00 || l2capinbuf[19] == 0x04 || l2capinbuf[19] == 0x05 || l2capinbuf[19] == 0x07) && l2capinbuf[20] == 0x05) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nInactive Wii Motion Plus"), 0x80); - Notify(PSTR("\r\nPlease unplug the Motion Plus, disconnect the Wiimote and then replug the Motion Plus Extension"), 0x80); -#endif - stateCounter = 300; // Skip the rest in "WII_CHECK_MOTION_PLUS_STATE" - } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x01 && l2capinbuf[20] == 0x20) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nWii U Pro Controller connected"), 0x80); -#endif - wiiUProControllerConnected = true; - } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x04 && l2capinbuf[20] == 0x02) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nWii Balance Board connected"), 0x80); -#endif - setReportMode(false, 0x32); // Read the Wii Balance Board extension - wii_set_flag(WII_FLAG_CALIBRATE_BALANCE_BOARD); - } - // Wii Balance Board calibration reports (24 bits in total) - else if(l2capinbuf[13] == 0x00 && l2capinbuf[14] == 0x24 && reportLength == 16) { // First 16-bit - for(uint8_t i = 0; i < 2; i++) { - for(uint8_t j = 0; j < 4; j++) - wiiBalanceBoardCal[i][j] = l2capinbuf[16 + 8 * i + 2 * j] | l2capinbuf[15 + 8 * i + 2 * j] << 8; - } - } else if(l2capinbuf[13] == 0x00 && l2capinbuf[14] == 0x34 && reportLength == 8) { // Last 8-bit - for(uint8_t j = 0; j < 4; j++) - wiiBalanceBoardCal[2][j] = l2capinbuf[16 + 2 * j] | l2capinbuf[15 + 2 * j] << 8; -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nWii Balance Board calibration values read successfully"), 0x80); -#endif - wii_clear_flag(WII_FLAG_CALIBRATE_BALANCE_BOARD); - wiiBalanceBoardConnected = true; - } -#ifdef DEBUG_USB_HOST - else { - Notify(PSTR("\r\nUnknown Device: "), 0x80); - D_PrintHex (l2capinbuf[13], 0x80); - D_PrintHex (l2capinbuf[14], 0x80); - Notify(PSTR("\r\nData: "), 0x80); - for(uint8_t i = 0; i < reportLength; i++) { - D_PrintHex (l2capinbuf[15 + i], 0x80); - Notify(PSTR(" "), 0x80); - } - } -#endif - } -#ifdef EXTRADEBUG - else { - Notify(PSTR("\r\nReport Error: "), 0x80); - D_PrintHex (l2capinbuf[13], 0x80); - D_PrintHex (l2capinbuf[14], 0x80); - } -#endif - break; - case 0x22: // Acknowledge output report, return function result -#ifdef DEBUG_USB_HOST - if(l2capinbuf[13] != 0x00) { // Check if there is an error - Notify(PSTR("\r\nCommand failed: "), 0x80); - D_PrintHex (l2capinbuf[12], 0x80); - } -#endif - break; - case 0x30: // Core buttons - (a1) 30 BB BB - break; - case 0x31: // Core Buttons and Accelerometer - (a1) 31 BB BB AA AA AA - break; - case 0x32: // Core Buttons with 8 Extension bytes - (a1) 32 BB BB EE EE EE EE EE EE EE EE - // See: http://wiibrew.org/wiki/Wii_Balance_Board#Data_Format - wiiBalanceBoardRaw[TopRight] = l2capinbuf[13] | l2capinbuf[12] << 8; // Top right - wiiBalanceBoardRaw[BotRight] = l2capinbuf[15] | l2capinbuf[14] << 8; // Bottom right - wiiBalanceBoardRaw[TopLeft] = l2capinbuf[17] | l2capinbuf[16] << 8; // Top left - wiiBalanceBoardRaw[BotLeft] = l2capinbuf[19] | l2capinbuf[18] << 8; // Bottom left - break; - case 0x33: // Core Buttons with Accelerometer and 12 IR bytes - (a1) 33 BB BB AA AA AA II II II II II II II II II II II II -#ifdef WIICAMERA - // Read the IR data - IR_object_x1 = (l2capinbuf[15] | ((uint16_t)(l2capinbuf[17] & 0x30) << 4)); // x position - IR_object_y1 = (l2capinbuf[16] | ((uint16_t)(l2capinbuf[17] & 0xC0) << 2)); // y position - IR_object_s1 = (l2capinbuf[17] & 0x0F); // Size value, 0-15 - - IR_object_x2 = (l2capinbuf[18] | ((uint16_t)(l2capinbuf[20] & 0x30) << 4)); - IR_object_y2 = (l2capinbuf[19] | ((uint16_t)(l2capinbuf[20] & 0xC0) << 2)); - IR_object_s2 = (l2capinbuf[20] & 0x0F); - - IR_object_x3 = (l2capinbuf[21] | ((uint16_t)(l2capinbuf[23] & 0x30) << 4)); - IR_object_y3 = (l2capinbuf[22] | ((uint16_t)(l2capinbuf[23] & 0xC0) << 2)); - IR_object_s3 = (l2capinbuf[23] & 0x0F); - - IR_object_x4 = (l2capinbuf[24] | ((uint16_t)(l2capinbuf[26] & 0x30) << 4)); - IR_object_y4 = (l2capinbuf[25] | ((uint16_t)(l2capinbuf[26] & 0xC0) << 2)); - IR_object_s4 = (l2capinbuf[26] & 0x0F); -#endif - break; - case 0x34: // Core Buttons with 19 Extension bytes - (a1) 34 BB BB EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE - break; - /* 0x3e and 0x3f both give unknown report types when report mode is 0x3e or 0x3f with mode number 0x05 */ - case 0x3E: // Core Buttons with Accelerometer and 32 IR bytes - // (a1) 31 BB BB AA AA AA II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II - // corresponds to output report mode 0x3e - - /**** for reading in full mode: DOES NOT WORK YET ****/ - /* When it works it will also have intensity and bounding box data */ - /* - IR_object_x1 = (l2capinbuf[13] | ((uint16_t)(l2capinbuf[15] & 0x30) << 4)); - IR_object_y1 = (l2capinbuf[14] | ((uint16_t)(l2capinbuf[15] & 0xC0) << 2)); - IR_object_s1 = (l2capinbuf[15] & 0x0F); - */ - break; - case 0x3F: - /* - IR_object_x1 = (l2capinbuf[13] | ((uint16_t)(l2capinbuf[15] & 0x30) << 4)); - IR_object_y1 = (l2capinbuf[14] | ((uint16_t)(l2capinbuf[15] & 0xC0) << 2)); - IR_object_s1 = (l2capinbuf[15] & 0x0F); - */ - break; - case 0x35: // Core Buttons and Accelerometer with 16 Extension Bytes - // (a1) 35 BB BB AA AA AA EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE -#if 1 // Set this to 0 if you don't want to use an extension, this reduceds the size of the library a lot! - if(motionPlusConnected) { - if(l2capinbuf[20] & 0x02) { // Check if it's a report from the Motion controller or the extension - if(motionValuesReset) { // We will only use the values when the gyro value has been set - gyroYawRaw = ((l2capinbuf[15] | ((l2capinbuf[18] & 0xFC) << 6)) - gyroYawZero); - gyroRollRaw = ((l2capinbuf[16] | ((l2capinbuf[19] & 0xFC) << 6)) - gyroRollZero); - gyroPitchRaw = ((l2capinbuf[17] | ((l2capinbuf[20] & 0xFC) << 6)) - gyroPitchZero); - - yawGyroSpeed = (double)gyroYawRaw / ((double)gyroYawZero / yawGyroScale); - rollGyroSpeed = -(double)gyroRollRaw / ((double)gyroRollZero / rollGyroScale); // We invert these values so they will fit the acc values - pitchGyroSpeed = (double)gyroPitchRaw / ((double)gyroPitchZero / pitchGyroScale); - - /* The onboard gyro has two ranges for slow and fast mode */ - if(!(l2capinbuf[18] & 0x02)) // Check if fast mode is used - yawGyroSpeed *= 4.545; - if(!(l2capinbuf[18] & 0x01)) // Check if fast mode is used - pitchGyroSpeed *= 4.545; - if(!(l2capinbuf[19] & 0x02)) // Check if fast mode is used - rollGyroSpeed *= 4.545; - - compPitch = (0.93 * (compPitch + (pitchGyroSpeed * (double)(micros() - timer) / 1000000)))+(0.07 * getWiimotePitch()); // Use a complimentary filter to calculate the angle - compRoll = (0.93 * (compRoll + (rollGyroSpeed * (double)(micros() - timer) / 1000000)))+(0.07 * getWiimoteRoll()); - - gyroYaw += (yawGyroSpeed * ((double)(micros() - timer) / 1000000)); - gyroRoll += (rollGyroSpeed * ((double)(micros() - timer) / 1000000)); - gyroPitch += (pitchGyroSpeed * ((double)(micros() - timer) / 1000000)); - timer = micros(); - /* - // Uncomment these lines to tune the gyro scale variabels - Notify(PSTR("\r\ngyroYaw: "), 0x80); - Notify(gyroYaw, 0x80); - Notify(PSTR("\tgyroRoll: "), 0x80); - Notify(gyroRoll, 0x80); - Notify(PSTR("\tgyroPitch: "), 0x80); - Notify(gyroPitch, 0x80); - */ - /* - Notify(PSTR("\twiimoteRoll: "), 0x80); - Notify(wiimoteRoll, 0x80); - Notify(PSTR("\twiimotePitch: "), 0x80); - Notify(wiimotePitch, 0x80); - */ - } else { - if((micros() - timer) > 1000000) { // Loop for 1 sec before resetting the values -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nThe gyro values has been reset"), 0x80); -#endif - gyroYawZero = (l2capinbuf[15] | ((l2capinbuf[18] & 0xFC) << 6)); - gyroRollZero = (l2capinbuf[16] | ((l2capinbuf[19] & 0xFC) << 6)); - gyroPitchZero = (l2capinbuf[17] | ((l2capinbuf[20] & 0xFC) << 6)); - - rollGyroScale = 500; // You might need to adjust these - pitchGyroScale = 400; - yawGyroScale = 415; - - gyroYaw = 0; - gyroRoll = 0; - gyroPitch = 0; - - motionValuesReset = true; - timer = micros(); - } - } - } else { - if(nunchuckConnected) { - hatValues[HatX] = l2capinbuf[15]; - hatValues[HatY] = l2capinbuf[16]; - accXnunchuck = ((l2capinbuf[17] << 2) | (l2capinbuf[20] & 0x10 >> 3)) - 416; - accYnunchuck = ((l2capinbuf[18] << 2) | (l2capinbuf[20] & 0x20 >> 4)) - 416; - accZnunchuck = (((l2capinbuf[19] & 0xFE) << 2) | (l2capinbuf[20] & 0xC0 >> 5)) - 416; - } - //else if(classicControllerConnected) { } - } - if(l2capinbuf[19] & 0x01) { - if(!extensionConnected) { - extensionConnected = true; - unknownExtensionConnected = true; -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nExtension connected to Motion Plus"), 0x80); -#endif - } - } else { - if(extensionConnected && !unknownExtensionConnected) { - extensionConnected = false; - unknownExtensionConnected = true; -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nExtension disconnected from Motion Plus"), 0x80); -#endif - nunchuckConnected = false; // There is no extension connected to the Motion Plus if this report is sent - } - } - - } else if(nunchuckConnected) { - hatValues[HatX] = l2capinbuf[15]; - hatValues[HatY] = l2capinbuf[16]; - accXnunchuck = ((l2capinbuf[17] << 2) | (l2capinbuf[20] & 0x0C >> 2)) - 416; - accYnunchuck = ((l2capinbuf[18] << 2) | (l2capinbuf[20] & 0x30 >> 4)) - 416; - accZnunchuck = ((l2capinbuf[19] << 2) | (l2capinbuf[20] & 0xC0 >> 6)) - 416; - } else if(wiiUProControllerConnected) { - hatValues[LeftHatX] = (l2capinbuf[15] | l2capinbuf[16] << 8); - hatValues[RightHatX] = (l2capinbuf[17] | l2capinbuf[18] << 8); - hatValues[LeftHatY] = (l2capinbuf[19] | l2capinbuf[20] << 8); - hatValues[RightHatY] = (l2capinbuf[21] | l2capinbuf[22] << 8); - } -#endif - break; -#ifdef DEBUG_USB_HOST - default: - Notify(PSTR("\r\nUnknown Report type: "), 0x80); - D_PrintHex (l2capinbuf[9], 0x80); - break; -#endif - } - } - } - L2CAP_task(); - } -} - -void WII::L2CAP_task() { - switch(l2cap_state) { - /* These states are used if the Wiimote is the host */ - case L2CAP_CONTROL_SUCCESS: - if(l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nHID Control Successfully Configured"), 0x80); -#endif - l2cap_state = L2CAP_INTERRUPT_SETUP; - } - break; - - case L2CAP_INTERRUPT_SETUP: - if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST)) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nHID Interrupt Incoming Connection Request"), 0x80); -#endif - pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, PENDING); - delay(1); - pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, SUCCESSFUL); - identifier++; - delay(1); - pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid); - - l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST; - } - break; - - /* These states are used if the Arduino is the host */ - case L2CAP_CONTROL_CONNECT_REQUEST: - if(l2cap_check_flag(L2CAP_FLAG_CONTROL_CONNECTED)) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nSend HID Control Config Request"), 0x80); -#endif - identifier++; - pBtd->l2cap_config_request(hci_handle, identifier, control_scid); - l2cap_state = L2CAP_CONTROL_CONFIG_REQUEST; - } - break; - - case L2CAP_CONTROL_CONFIG_REQUEST: - if(l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nSend HID Interrupt Connection Request"), 0x80); -#endif - identifier++; - pBtd->l2cap_connection_request(hci_handle, identifier, interrupt_dcid, HID_INTR_PSM); - l2cap_state = L2CAP_INTERRUPT_CONNECT_REQUEST; - } - break; - - case L2CAP_INTERRUPT_CONNECT_REQUEST: - if(l2cap_check_flag(L2CAP_FLAG_INTERRUPT_CONNECTED)) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nSend HID Interrupt Config Request"), 0x80); -#endif - identifier++; - pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid); - l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST; - } - break; - - case L2CAP_INTERRUPT_CONFIG_REQUEST: - if(l2cap_check_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS)) { // Now the HID channels is established -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nHID Channels Established"), 0x80); -#endif - pBtd->connectToWii = false; - pBtd->pairWithWii = false; - stateCounter = 0; - l2cap_state = WII_CHECK_MOTION_PLUS_STATE; - } - break; - - /* The next states are in run() */ - - case L2CAP_INTERRUPT_DISCONNECT: - if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE) && ((long)(millis() - timer) >= 0L)) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nDisconnected Interrupt Channel"), 0x80); -#endif - identifier++; - pBtd->l2cap_disconnection_request(hci_handle, identifier, control_scid, control_dcid); - l2cap_state = L2CAP_CONTROL_DISCONNECT; - } - break; - - case L2CAP_CONTROL_DISCONNECT: - if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE)) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nDisconnected Control Channel"), 0x80); -#endif - pBtd->hci_disconnect(hci_handle); - hci_handle = -1; // Reset handle - l2cap_event_flag = 0; // Reset flags - l2cap_state = L2CAP_WAIT; - } - break; - } -} - -void WII::Run() { - if(l2cap_state == L2CAP_INTERRUPT_DISCONNECT && ((long)(millis() - timer) >= 0L)) - L2CAP_task(); // Call the rest of the disconnection routine after we have waited long enough - - switch(l2cap_state) { - case L2CAP_WAIT: - if(pBtd->connectToWii && !pBtd->l2capConnectionClaimed && !wiimoteConnected && !activeConnection) { - pBtd->l2capConnectionClaimed = true; - activeConnection = true; - motionPlusInside = pBtd->motionPlusInside; -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nSend HID Control Connection Request"), 0x80); -#endif - hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection - l2cap_event_flag = 0; // Reset flags - identifier = 0; - pBtd->l2cap_connection_request(hci_handle, identifier, control_dcid, HID_CTRL_PSM); - l2cap_state = L2CAP_CONTROL_CONNECT_REQUEST; - } else if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST)) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nHID Control Incoming Connection Request"), 0x80); -#endif - pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, PENDING); - delay(1); - pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, SUCCESSFUL); - identifier++; - delay(1); - pBtd->l2cap_config_request(hci_handle, identifier, control_scid); - l2cap_state = L2CAP_CONTROL_SUCCESS; - } - break; - - case WII_CHECK_MOTION_PLUS_STATE: -#ifdef DEBUG_USB_HOST - if(stateCounter == 0) // Only print onnce - Notify(PSTR("\r\nChecking if a Motion Plus is connected"), 0x80); -#endif - stateCounter++; - if(stateCounter % 200 == 0) - checkMotionPresent(); // Check if there is a motion plus connected - if(wii_check_flag(WII_FLAG_MOTION_PLUS_CONNECTED)) { - stateCounter = 0; - l2cap_state = WII_INIT_MOTION_PLUS_STATE; - timer = micros(); - - if(unknownExtensionConnected) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nA extension is also connected"), 0x80); -#endif - activateNunchuck = true; // For we will just set this to true as this the only extension supported so far - } - - } else if(stateCounter == 601) { // We will try three times to check for the motion plus -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nNo Motion Plus was detected"), 0x80); -#endif - stateCounter = 0; - l2cap_state = WII_CHECK_EXTENSION_STATE; - } - break; - - case WII_CHECK_EXTENSION_STATE: // This is used to check if there is anything plugged in to the extension port -#ifdef DEBUG_USB_HOST - if(stateCounter == 0) // Only print onnce - Notify(PSTR("\r\nChecking if there is any extension connected"), 0x80); -#endif - stateCounter++; // We use this counter as there has to be a short delay between the commands - if(stateCounter == 1) - statusRequest(); // See if a new device has connected - if(stateCounter == 100) { - if(unknownExtensionConnected) // Check if there is a extension is connected to the port - initExtension1(); - else - stateCounter = 499; - } else if(stateCounter == 200) - initExtension2(); - else if(stateCounter == 300) { - readExtensionType(); - unknownExtensionConnected = false; - } else if(stateCounter == 400) { - if(wii_check_flag(WII_FLAG_CALIBRATE_BALANCE_BOARD)) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nReading Wii Balance Board calibration values"), 0x80); -#endif - readWiiBalanceBoardCalibration(); - } else - stateCounter = 499; - } else if(stateCounter == 500) { - stateCounter = 0; - l2cap_state = TURN_ON_LED; - } - break; - - case WII_INIT_MOTION_PLUS_STATE: - stateCounter++; - if(stateCounter == 1) - initMotionPlus(); - else if(stateCounter == 100) - activateMotionPlus(); - else if(stateCounter == 200) - readExtensionType(); // Check if it has been activated - else if(stateCounter == 300) { - stateCounter = 0; - unknownExtensionConnected = false; // The motion plus will send a status report when it's activated, we will set this to false so it doesn't reinitialize the Motion Plus - l2cap_state = TURN_ON_LED; - } - break; - - case TURN_ON_LED: - if(wii_check_flag(WII_FLAG_NUNCHUCK_CONNECTED)) - nunchuckConnected = true; - wiimoteConnected = true; - onInit(); - l2cap_state = L2CAP_DONE; - break; - - case L2CAP_DONE: - if(unknownExtensionConnected) { -#ifdef DEBUG_USB_HOST - if(stateCounter == 0) // Only print once - Notify(PSTR("\r\nChecking extension port"), 0x80); -#endif - stateCounter++; // We will use this counter as there has to be a short delay between the commands - if(stateCounter == 50) - statusRequest(); - else if(stateCounter == 100) - initExtension1(); - else if(stateCounter == 150) - if((extensionConnected && motionPlusConnected) || (unknownExtensionConnected && !motionPlusConnected)) - initExtension2(); - else - stateCounter = 299; // There is no extension connected - else if(stateCounter == 200) - readExtensionType(); - else if(stateCounter == 250) { - if(wii_check_flag(WII_FLAG_NUNCHUCK_CONNECTED)) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nNunchuck was reconnected"), 0x80); -#endif - activateNunchuck = true; - nunchuckConnected = true; - } - if(!motionPlusConnected) - stateCounter = 449; - } else if(stateCounter == 300) { - if(motionPlusConnected) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nReactivating the Motion Plus"), 0x80); -#endif - initMotionPlus(); - } else - stateCounter = 449; - } else if(stateCounter == 350) - activateMotionPlus(); - else if(stateCounter == 400) - readExtensionType(); // Check if it has been activated - else if(stateCounter == 450) { - onInit(); - stateCounter = 0; - unknownExtensionConnected = false; - } - } else - stateCounter = 0; - break; - } -} - -/************************************************************/ -/* HID Commands */ -/************************************************************/ - -void WII::HID_Command(uint8_t* data, uint8_t nbytes) { - if(motionPlusInside) - pBtd->L2CAP_Command(hci_handle, data, nbytes, interrupt_scid[0], interrupt_scid[1]); // It's the new Wiimote with the Motion Plus Inside or Wii U Pro controller - else - pBtd->L2CAP_Command(hci_handle, data, nbytes, control_scid[0], control_scid[1]); -} - -void WII::setAllOff() { - HIDBuffer[1] = 0x11; - HIDBuffer[2] = 0x00; - HID_Command(HIDBuffer, 3); -} - -void WII::setRumbleOff() { - HIDBuffer[1] = 0x11; - HIDBuffer[2] &= ~0x01; // Bit 0 control the rumble - HID_Command(HIDBuffer, 3); -} - -void WII::setRumbleOn() { - HIDBuffer[1] = 0x11; - HIDBuffer[2] |= 0x01; // Bit 0 control the rumble - HID_Command(HIDBuffer, 3); -} - -void WII::setRumbleToggle() { - HIDBuffer[1] = 0x11; - HIDBuffer[2] ^= 0x01; // Bit 0 control the rumble - HID_Command(HIDBuffer, 3); -} - -void WII::setLedRaw(uint8_t value) { - HIDBuffer[1] = 0x11; - HIDBuffer[2] = value | (HIDBuffer[2] & 0x01); // Keep the rumble bit - HID_Command(HIDBuffer, 3); -} - -void WII::setLedOff(LEDEnum a) { - HIDBuffer[1] = 0x11; - HIDBuffer[2] &= ~(pgm_read_byte(&WII_LEDS[(uint8_t)a])); - HID_Command(HIDBuffer, 3); -} - -void WII::setLedOn(LEDEnum a) { - if(a == OFF) - setLedRaw(0); - else { - HIDBuffer[1] = 0x11; - HIDBuffer[2] |= pgm_read_byte(&WII_LEDS[(uint8_t)a]); - HID_Command(HIDBuffer, 3); - } -} - -void WII::setLedToggle(LEDEnum a) { - HIDBuffer[1] = 0x11; - HIDBuffer[2] ^= pgm_read_byte(&WII_LEDS[(uint8_t)a]); - HID_Command(HIDBuffer, 3); -} - -void WII::setLedStatus() { - HIDBuffer[1] = 0x11; - HIDBuffer[2] = (HIDBuffer[2] & 0x01); // Keep the rumble bit - if(wiimoteConnected) - HIDBuffer[2] |= 0x10; // If it's connected LED1 will light up - if(motionPlusConnected) - HIDBuffer[2] |= 0x20; // If it's connected LED2 will light up - if(nunchuckConnected) - HIDBuffer[2] |= 0x40; // If it's connected LED3 will light up - - HID_Command(HIDBuffer, 3); -} - -uint8_t WII::getBatteryLevel() { - checkBatteryLevel = true; // This is needed so the library knows that the status response is a response to this function - statusRequest(); // This will update the battery level - return batteryLevel; -}; - -void WII::setReportMode(bool continuous, uint8_t mode) { - uint8_t cmd_buf[4]; - cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) - cmd_buf[1] = 0x12; - if(continuous) - cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Keep the rumble bit - else - cmd_buf[2] = 0x00 | (HIDBuffer[2] & 0x01); // Keep the rumble bit - cmd_buf[3] = mode; - HID_Command(cmd_buf, 4); -} - -void WII::statusRequest() { - uint8_t cmd_buf[3]; - cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) - cmd_buf[1] = 0x15; - cmd_buf[2] = (HIDBuffer[2] & 0x01); // Keep the rumble bit - HID_Command(cmd_buf, 3); -} - -/************************************************************/ -/* Memmory Commands */ -/************************************************************/ - -void WII::writeData(uint32_t offset, uint8_t size, uint8_t* data) { - uint8_t cmd_buf[23]; - cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) - cmd_buf[1] = 0x16; // Write data - cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Write to memory, clear bit 2 to write to EEPROM - cmd_buf[3] = (uint8_t)((offset & 0xFF0000) >> 16); - cmd_buf[4] = (uint8_t)((offset & 0xFF00) >> 8); - cmd_buf[5] = (uint8_t)(offset & 0xFF); - cmd_buf[6] = size; - uint8_t i = 0; - for(; i < size; i++) - cmd_buf[7 + i] = data[i]; - for(; i < 16; i++) // Set the rest to zero - cmd_buf[7 + i] = 0x00; - HID_Command(cmd_buf, 23); -} - -void WII::initExtension1() { - uint8_t buf[1]; - buf[0] = 0x55; - writeData(0xA400F0, 1, buf); -} - -void WII::initExtension2() { - uint8_t buf[1]; - buf[0] = 0x00; - writeData(0xA400FB, 1, buf); -} - -void WII::initMotionPlus() { - uint8_t buf[1]; - buf[0] = 0x55; - writeData(0xA600F0, 1, buf); -} - -void WII::activateMotionPlus() { - uint8_t buf[1]; - if(pBtd->wiiUProController) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nActivating Wii U Pro Controller"), 0x80); -#endif - buf[0] = 0x00; // It seems like you can send anything but 0x04, 0x05, and 0x07 - } else if(activateNunchuck) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nActivating Motion Plus in pass-through mode"), 0x80); -#endif - buf[0] = 0x05; // Activate nunchuck pass-through mode - }//else if(classicControllerConnected && extensionConnected) - //buf[0] = 0x07; - else { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nActivating Motion Plus in normal mode"), 0x80); -#endif - buf[0] = 0x04; // Don't use any extension - } - writeData(0xA600FE, 1, buf); -} - -void WII::readData(uint32_t offset, uint16_t size, bool EEPROM) { - uint8_t cmd_buf[8]; - cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) - cmd_buf[1] = 0x17; // Read data - if(EEPROM) - cmd_buf[2] = 0x00 | (HIDBuffer[2] & 0x01); // Read from EEPROM - else - cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Read from memory - cmd_buf[3] = (uint8_t)((offset & 0xFF0000) >> 16); - cmd_buf[4] = (uint8_t)((offset & 0xFF00) >> 8); - cmd_buf[5] = (uint8_t)(offset & 0xFF); - cmd_buf[6] = (uint8_t)((size & 0xFF00) >> 8); - cmd_buf[7] = (uint8_t)(size & 0xFF); - - HID_Command(cmd_buf, 8); -} - -void WII::readExtensionType() { - readData(0xA400FA, 6, false); -} - -void WII::readCalData() { - readData(0x0016, 8, true); -} - -void WII::checkMotionPresent() { - readData(0xA600FA, 6, false); -} - -void WII::readWiiBalanceBoardCalibration() { - readData(0xA40024, 24, false); -} - -/************************************************************/ -/* WII Commands */ -/************************************************************/ - -bool WII::getButtonPress(ButtonEnum b) { // Return true when a button is pressed - if(wiiUProControllerConnected) - return (ButtonState & pgm_read_dword(&WII_PROCONTROLLER_BUTTONS[(uint8_t)b])); - else - return (ButtonState & pgm_read_dword(&WII_BUTTONS[(uint8_t)b])); -} - -bool WII::getButtonClick(ButtonEnum b) { // Only return true when a button is clicked - uint32_t button; - if(wiiUProControllerConnected) - button = pgm_read_dword(&WII_PROCONTROLLER_BUTTONS[(uint8_t)b]); - else - button = pgm_read_dword(&WII_BUTTONS[(uint8_t)b]); - bool click = (ButtonClickState & button); - ButtonClickState &= ~button; // clear "click" event - return click; -} - -uint8_t WII::getAnalogHat(HatEnum a) { - if(!nunchuckConnected) - return 127; // Return center position - else { - uint8_t output = hatValues[(uint8_t)a]; - if(output == 0xFF || output == 0x00) // The joystick will only read 255 or 0 when the cable is unplugged or initializing, so we will just return the center position - return 127; - else - return output; - } -} - -uint16_t WII::getAnalogHat(AnalogHatEnum a) { - if(!wiiUProControllerConnected) - return 2000; - else { - uint16_t output = hatValues[(uint8_t)a]; - if(output == 0x00) // The joystick will only read 0 when it is first initializing, so we will just return the center position - return 2000; - else - return output; - } -} - -void WII::onInit() { - if(pFuncOnInit) - pFuncOnInit(); // Call the user function - else - setLedStatus(); -} - -/************************************************************/ -/* Wii Balance Board Commands */ -/************************************************************/ - -float WII::getWeight(BalanceBoardEnum pos) { - // Use interpolating between two points - based on: https://github.com/skorokithakis/gr8w8upd8m8/blob/master/gr8w8upd8m8.py - // wiiBalanceBoardCal[pos][0] is calibration values for 0 kg - // wiiBalanceBoardCal[pos][1] is calibration values for 17 kg - // wiiBalanceBoardCal[pos][2] is calibration values for 34 kg - if(wiiBalanceBoardRaw[pos] < wiiBalanceBoardCal[0][pos]) - return 0.0f; // Below 0 kg - else if(wiiBalanceBoardRaw[pos] < wiiBalanceBoardCal[1][pos]) // Between 0 and 17 kg - return 17.0f * (float)(wiiBalanceBoardRaw[pos] - wiiBalanceBoardCal[0][pos]) / (float)(wiiBalanceBoardCal[1][pos] - wiiBalanceBoardCal[0][pos]); - else // More than 17 kg - return 17.0f + 17.0f * (float)(wiiBalanceBoardRaw[pos] - wiiBalanceBoardCal[1][pos]) / (float)(wiiBalanceBoardCal[2][pos] - wiiBalanceBoardCal[1][pos]); -}; - -float WII::getTotalWeight() { - return getWeight(TopRight) + getWeight(BotRight) + getWeight(TopLeft) + getWeight(BotLeft); -}; - -/************************************************************/ -/* The following functions are for the IR camera */ -/************************************************************/ - -#ifdef WIICAMERA - -void WII::IRinitialize() { // Turns on and initialises the IR camera - - enableIRCamera1(); -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nEnable IR Camera1 Complete"), 0x80); -#endif - delay(80); - - enableIRCamera2(); -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nEnable IR Camera2 Complete"), 0x80); -#endif - delay(80); - - write0x08Value(); -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nWrote hex number 0x08"), 0x80); -#endif - delay(80); - - writeSensitivityBlock1(); -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nWrote Sensitivity Block 1"), 0x80); -#endif - delay(80); - - writeSensitivityBlock2(); -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nWrote Sensitivity Block 2"), 0x80); -#endif - delay(80); - - uint8_t mode_num = 0x03; - setWiiModeNumber(mode_num); // Change input for whatever mode you want i.e. 0x01, 0x03, or 0x05 -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nSet Wii Mode Number To 0x"), 0x80); - D_PrintHex (mode_num, 0x80); -#endif - delay(80); - - write0x08Value(); -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nWrote Hex Number 0x08"), 0x80); -#endif - delay(80); - - setReportMode(false, 0x33); - //setReportMode(false, 0x3f); // For full reporting mode, doesn't work yet -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nSet Report Mode to 0x33"), 0x80); -#endif - delay(80); - - statusRequest(); // Used to update wiiState - call isIRCameraEnabled() afterwards to check if it actually worked -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nIR Initialized"), 0x80); -#endif -} - -void WII::enableIRCamera1() { - uint8_t cmd_buf[3]; - cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) - cmd_buf[1] = 0x13; // Output report 13 - cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Keep the rumble bit and sets bit 2 - HID_Command(cmd_buf, 3); -} - -void WII::enableIRCamera2() { - uint8_t cmd_buf[3]; - cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) - cmd_buf[1] = 0x1A; // Output report 1A - cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Keep the rumble bit and sets bit 2 - HID_Command(cmd_buf, 3); -} - -void WII::writeSensitivityBlock1() { - uint8_t buf[9]; - buf[0] = 0x00; - buf[1] = 0x00; - buf[2] = 0x00; - buf[3] = 0x00; - buf[4] = 0x00; - buf[5] = 0x00; - buf[6] = 0x90; - buf[7] = 0x00; - buf[8] = 0x41; - - writeData(0xB00000, 9, buf); -} - -void WII::writeSensitivityBlock2() { - uint8_t buf[2]; - buf[0] = 0x40; - buf[1] = 0x00; - - writeData(0xB0001A, 2, buf); -} - -void WII::write0x08Value() { - uint8_t cmd = 0x08; - writeData(0xb00030, 1, &cmd); -} - -void WII::setWiiModeNumber(uint8_t mode_number) { // mode_number in hex i.e. 0x03 for extended mode - writeData(0xb00033, 1, &mode_number); -} -#endif diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/Wii.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/Wii.h deleted file mode 100755 index 960f2273de..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/Wii.h +++ /dev/null @@ -1,518 +0,0 @@ -/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. - - This software may be distributed and modified under the terms of the GNU - General Public License version 2 (GPL2) as published by the Free Software - Foundation and appearing in the file GPL2.TXT included in the packaging of - this file. Please note that GPL2 Section 2[b] requires that all works based - on this software must also be made publicly available under the terms of - the GPL2 ("Copyleft"). - - Contact information - ------------------- - - Kristian Lauszus, TKJ Electronics - Web : http://www.tkjelectronics.com - e-mail : kristianl@tkjelectronics.com - - IR camera support added by Allan Glover (adglover9.81@gmail.com) and Kristian Lauszus - */ - -#ifndef _wii_h_ -#define _wii_h_ - -#include "BTD.h" -#include "controllerEnums.h" - -/* Wii event flags */ -#define WII_FLAG_MOTION_PLUS_CONNECTED (1 << 0) -#define WII_FLAG_NUNCHUCK_CONNECTED (1 << 1) -#define WII_FLAG_CALIBRATE_BALANCE_BOARD (1 << 2) - -#define wii_check_flag(flag) (wii_event_flag & (flag)) -#define wii_set_flag(flag) (wii_event_flag |= (flag)) -#define wii_clear_flag(flag) (wii_event_flag &= ~(flag)) - -/** Enum used to read the joystick on the Nunchuck. */ -enum HatEnum { - /** Read the x-axis on the Nunchuck joystick. */ - HatX = 0, - /** Read the y-axis on the Nunchuck joystick. */ - HatY = 1, -}; - -/** Enum used to read the weight on Wii Balance Board. */ -enum BalanceBoardEnum { - TopRight = 0, - BotRight = 1, - TopLeft = 2, - BotLeft = 3, -}; - -/** - * This BluetoothService class implements support for the Wiimote including the Nunchuck and Motion Plus extension. - * - * It also support the Wii U Pro Controller. - */ -class WII : public BluetoothService { -public: - /** - * Constructor for the WII class. - * @param p Pointer to BTD class instance. - * @param pair Set this to true in order to pair with the Wiimote. If the argument is omitted then it won't pair with it. - * One can use ::PAIR to set it to true. - */ - WII(BTD *p, bool pair = false); - - /** @name BluetoothService implementation */ - /** Used this to disconnect any of the controllers. */ - void disconnect(); - /**@}*/ - - /** @name Wii Controller functions */ - /** - * getButtonPress(Button b) will return true as long as the button is held down. - * - * While getButtonClick(Button b) will only return it once. - * - * So you instance if you need to increase a variable once you would use getButtonClick(Button b), - * but if you need to drive a robot forward you would use getButtonPress(Button b). - * @param b ::ButtonEnum to read. - * @return getButtonPress(ButtonEnum b) will return a true as long as a button is held down, while getButtonClick(ButtonEnum b) will return true once for each button press. - */ - bool getButtonPress(ButtonEnum b); - bool getButtonClick(ButtonEnum b); - /**@}*/ - - /** @name Wii Controller functions */ - - /** Call this to start the paring sequence with a controller */ - void pair(void) { - if(pBtd) - pBtd->pairWithWiimote(); - }; - /** - * Used to read the joystick of the Nunchuck. - * @param a Either ::HatX or ::HatY. - * @return Return the analog value in the range from approximately 25-230. - */ - uint8_t getAnalogHat(HatEnum a); - /** - * Used to read the joystick of the Wii U Pro Controller. - * @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY. - * @return Return the analog value in the range from approximately 800-3200. - */ - uint16_t getAnalogHat(AnalogHatEnum a); - - /** - * Pitch calculated from the Wiimote. A complimentary filter is used if the Motion Plus is connected. - * @return Pitch in the range from 0-360. - */ - double getPitch() { - if(motionPlusConnected) - return compPitch; - return getWiimotePitch(); - }; - - /** - * Roll calculated from the Wiimote. A complimentary filter is used if the Motion Plus is connected. - * @return Roll in the range from 0-360. - */ - double getRoll() { - if(motionPlusConnected) - return compRoll; - return getWiimoteRoll(); - }; - - /** - * This is the yaw calculated by the gyro. - * - * NOTE: This angle will drift a lot and is only available if the Motion Plus extension is connected. - * @return The angle calculated using the gyro. - */ - double getYaw() { - return gyroYaw; - }; - - /** Used to set all LEDs and rumble off. */ - void setAllOff(); - /** Turn off rumble. */ - void setRumbleOff(); - /** Turn on rumble. */ - void setRumbleOn(); - /** Toggle rumble. */ - void setRumbleToggle(); - - /** - * Set LED value without using the ::LEDEnum. - * @param value See: ::LEDEnum. - */ - void setLedRaw(uint8_t value); - - /** Turn all LEDs off. */ - void setLedOff() { - setLedRaw(0); - }; - /** - * Turn the specific ::LEDEnum off. - * @param a The ::LEDEnum to turn off. - */ - void setLedOff(LEDEnum a); - /** - * Turn the specific ::LEDEnum on. - * @param a The ::LEDEnum to turn on. - */ - void setLedOn(LEDEnum a); - /** - * Toggle the specific ::LEDEnum. - * @param a The ::LEDEnum to toggle. - */ - void setLedToggle(LEDEnum a); - /** - * This will set the LEDs, so the user can see which connections are active. - * - * The first ::LEDEnum indicate that the Wiimote is connected, - * the second ::LEDEnum indicate indicate that a Motion Plus is also connected - * the third ::LEDEnum will indicate that a Nunchuck controller is also connected. - */ - void setLedStatus(); - - /** - * Return the battery level of the Wiimote. - * @return The battery level in the range 0-255. - */ - uint8_t getBatteryLevel(); - - /** - * Return the Wiimote state. - * @return See: http://wiibrew.org/wiki/Wiimote#0x20:_Status. - */ - uint8_t getWiiState() { - return wiiState; - }; - /**@}*/ - - /**@{*/ - /** Variable used to indicate if a Wiimote is connected. */ - bool wiimoteConnected; - /** Variable used to indicate if a Nunchuck controller is connected. */ - bool nunchuckConnected; - /** Variable used to indicate if a Nunchuck controller is connected. */ - bool motionPlusConnected; - /** Variable used to indicate if a Wii U Pro controller is connected. */ - bool wiiUProControllerConnected; - /** Variable used to indicate if a Wii Balance Board is connected. */ - bool wiiBalanceBoardConnected; - /**@}*/ - - /* IMU Data, might be usefull if you need to do something more advanced than just calculating the angle */ - - /**@{*/ - - /** Pitch and roll calculated from the accelerometer inside the Wiimote. */ - double getWiimotePitch() { - return (atan2(accYwiimote, accZwiimote) + PI) * RAD_TO_DEG; - }; - - double getWiimoteRoll() { - return (atan2(accXwiimote, accZwiimote) + PI) * RAD_TO_DEG; - }; - /**@}*/ - - /**@{*/ - - /** Pitch and roll calculated from the accelerometer inside the Nunchuck. */ - double getNunchuckPitch() { - return (atan2(accYnunchuck, accZnunchuck) + PI) * RAD_TO_DEG; - }; - - double getNunchuckRoll() { - return (atan2(accXnunchuck, accZnunchuck) + PI) * RAD_TO_DEG; - }; - /**@}*/ - - /**@{*/ - /** Accelerometer values used to calculate pitch and roll. */ - int16_t accXwiimote, accYwiimote, accZwiimote; - int16_t accXnunchuck, accYnunchuck, accZnunchuck; - /**@}*/ - - /* Variables for the gyro inside the Motion Plus */ - /** This is the pitch calculated by the gyro - use this to tune WII#pitchGyroScale. */ - double gyroPitch; - /** This is the roll calculated by the gyro - use this to tune WII#rollGyroScale. */ - double gyroRoll; - /** This is the yaw calculated by the gyro - use this to tune WII#yawGyroScale. */ - double gyroYaw; - - /**@{*/ - /** The speed in deg/s from the gyro. */ - double pitchGyroSpeed; - double rollGyroSpeed; - double yawGyroSpeed; - /**@}*/ - - /**@{*/ - /** You might need to fine-tune these values. */ - uint16_t pitchGyroScale; - uint16_t rollGyroScale; - uint16_t yawGyroScale; - /**@}*/ - - /**@{*/ - /** Raw value read directly from the Motion Plus. */ - int16_t gyroYawRaw; - int16_t gyroRollRaw; - int16_t gyroPitchRaw; - /**@}*/ - - /**@{*/ - /** These values are set when the controller is first initialized. */ - int16_t gyroYawZero; - int16_t gyroRollZero; - int16_t gyroPitchZero; - /**@}*/ - - /** @name Wii Balance Board functions */ - - /** - * Used to get the weight at the specific position on the Wii Balance Board. - * @param ::BalanceBoardEnum to read from. - * @return Returns the weight in kg. - */ - float getWeight(BalanceBoardEnum pos); - - /** - * Used to get total weight on the Wii Balance Board. - * @returnReturns the weight in kg. - */ - float getTotalWeight(); - - /** - * Used to get the raw reading at the specific position on the Wii Balance Board. - * @param ::BalanceBoardEnum to read from. - * @return Returns the raw reading. - */ - uint16_t getWeightRaw(BalanceBoardEnum pos) { - return wiiBalanceBoardRaw[pos]; - }; - /**@}*/ - -#ifdef WIICAMERA - /** @name Wiimote IR camera functions - * You will have to set ::ENABLE_WII_IR_CAMERA in settings.h to 1 in order use the IR camera. - */ - /** Initialises the camera as per the steps from: http://wiibrew.org/wiki/Wiimote#IR_Camera */ - void IRinitialize(); - - /** - * IR object 1 x-position read from the Wii IR camera. - * @return The x-position of the object in the range 0-1023. - */ - uint16_t getIRx1() { - return IR_object_x1; - }; - - /** - * IR object 1 y-position read from the Wii IR camera. - * @return The y-position of the object in the range 0-767. - */ - uint16_t getIRy1() { - return IR_object_y1; - }; - - /** - * IR object 1 size read from the Wii IR camera. - * @return The size of the object in the range 0-15. - */ - uint8_t getIRs1() { - return IR_object_s1; - }; - - /** - * IR object 2 x-position read from the Wii IR camera. - * @return The x-position of the object in the range 0-1023. - */ - uint16_t getIRx2() { - return IR_object_x2; - }; - - /** - * IR object 2 y-position read from the Wii IR camera. - * @return The y-position of the object in the range 0-767. - */ - uint16_t getIRy2() { - return IR_object_y2; - }; - - /** - * IR object 2 size read from the Wii IR camera. - * @return The size of the object in the range 0-15. - */ - uint8_t getIRs2() { - return IR_object_s2; - }; - - /** - * IR object 3 x-position read from the Wii IR camera. - * @return The x-position of the object in the range 0-1023. - */ - uint16_t getIRx3() { - return IR_object_x3; - }; - - /** - * IR object 3 y-position read from the Wii IR camera. - * @return The y-position of the object in the range 0-767. - */ - uint16_t getIRy3() { - return IR_object_y3; - }; - - /** - * IR object 3 size read from the Wii IR camera. - * @return The size of the object in the range 0-15. - */ - uint8_t getIRs3() { - return IR_object_s3; - }; - - /** - * IR object 4 x-position read from the Wii IR camera. - * @return The x-position of the object in the range 0-1023. - */ - uint16_t getIRx4() { - return IR_object_x4; - }; - - /** - * IR object 4 y-position read from the Wii IR camera. - * @return The y-position of the object in the range 0-767. - */ - uint16_t getIRy4() { - return IR_object_y4; - }; - - /** - * IR object 4 size read from the Wii IR camera. - * @return The size of the object in the range 0-15. - */ - uint8_t getIRs4() { - return IR_object_s4; - }; - - /** - * Use this to check if the camera is enabled or not. - * If not call WII#IRinitialize to initialize the IR camera. - * @return True if it's enabled, false if not. - */ - bool isIRCameraEnabled() { - return (wiiState & 0x08); - }; - /**@}*/ -#endif - -protected: - /** @name BluetoothService implementation */ - /** - * Used to pass acldata to the services. - * @param ACLData Incoming acldata. - */ - void ACLData(uint8_t* ACLData); - /** Used to run part of the state machine. */ - void Run(); - /** Use this to reset the service. */ - void Reset(); - /** - * Called when the controller is successfully initialized. - * Use attachOnInit(void (*funcOnInit)(void)) to call your own function. - * This is useful for instance if you want to set the LEDs in a specific way. - */ - void onInit(); - /**@}*/ - -private: - - void L2CAP_task(); // L2CAP state machine - - /* Variables filled from HCI event management */ - bool activeConnection; // Used to indicate if it's already has established a connection - - /* Variables used by high level L2CAP task */ - uint8_t l2cap_state; - uint8_t wii_event_flag; // Used for Wii flags - - uint32_t ButtonState; - uint32_t OldButtonState; - uint32_t ButtonClickState; - uint16_t hatValues[4]; - - uint8_t HIDBuffer[3]; // Used to store HID commands - - uint16_t stateCounter; - bool unknownExtensionConnected; - bool extensionConnected; - bool checkBatteryLevel; // Set to true when getBatteryLevel() is called otherwise if should be false - bool motionPlusInside; // True if it's a new Wiimote with the Motion Plus extension build into it - - /* L2CAP Channels */ - uint8_t control_scid[2]; // L2CAP source CID for HID_Control - uint8_t control_dcid[2]; // 0x0060 - uint8_t interrupt_scid[2]; // L2CAP source CID for HID_Interrupt - uint8_t interrupt_dcid[2]; // 0x0061 - - /* HID Commands */ - void HID_Command(uint8_t* data, uint8_t nbytes); - void setReportMode(bool continuous, uint8_t mode); - - void writeData(uint32_t offset, uint8_t size, uint8_t* data); - void initExtension1(); - void initExtension2(); - - void statusRequest(); // Used to update the Wiimote state and battery level - - void readData(uint32_t offset, uint16_t size, bool EEPROM); - void readExtensionType(); - void readCalData(); - void readWiiBalanceBoardCalibration(); // Used by the library to read the Wii Balance Board calibration values - - void checkMotionPresent(); // Used to see if a Motion Plus is connected to the Wiimote - void initMotionPlus(); - void activateMotionPlus(); - - uint16_t wiiBalanceBoardRaw[4]; // Wii Balance Board raw values - uint16_t wiiBalanceBoardCal[3][4]; // Wii Balance Board calibration values - - double compPitch; // Fusioned angle using a complimentary filter if the Motion Plus is connected - double compRoll; // Fusioned angle using a complimentary filter if the Motion Plus is connected - - bool activateNunchuck; - bool motionValuesReset; // This bool is true when the gyro values has been reset - uint32_t timer; - - uint8_t wiiState; // Stores the value in l2capinbuf[12] - (0x01: Battery is nearly empty), (0x02: An Extension Controller is connected), (0x04: Speaker enabled), (0x08: IR enabled), (0x10: LED1, 0x20: LED2, 0x40: LED3, 0x80: LED4) - uint8_t batteryLevel; - -#ifdef WIICAMERA - /* Private function and variables for the readings from the IR Camera */ - void enableIRCamera1(); // Sets bit 2 of output report 13 - void enableIRCamera2(); // Sets bit 2 of output report 1A - void writeSensitivityBlock1(); - void writeSensitivityBlock2(); - void write0x08Value(); - void setWiiModeNumber(uint8_t mode_number); - - uint16_t IR_object_x1; // IR x position 10 bits - uint16_t IR_object_y1; // IR y position 10 bits - uint8_t IR_object_s1; // IR size value - uint16_t IR_object_x2; - uint16_t IR_object_y2; - uint8_t IR_object_s2; - uint16_t IR_object_x3; // IR x position 10 bits - uint16_t IR_object_y3; // IR y position 10 bits - uint8_t IR_object_s3; // IR size value - uint16_t IR_object_x4; - uint16_t IR_object_y4; - uint8_t IR_object_s4; -#endif -}; -#endif diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/WiiCameraReadme.md b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/WiiCameraReadme.md deleted file mode 100644 index 8577d73fb3..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/WiiCameraReadme.md +++ /dev/null @@ -1,13 +0,0 @@ -Please see for the complete capabilities of the Wii camera. The IR camera code was written based on the above website and with support from Kristian Lauszus. - -This library is large, if you run into memory problems when uploading to the Arduino, disable serial debugging. - -To enable the IR camera code, simply set ```ENABLE_WII_IR_CAMERA``` to 1 in [settings.h](settings.h). - -This library implements the following settings: - -* Report sensitivity mode: 00 00 00 00 00 00 90 00 41 40 00 Suggested by inio (high sensitivity) -* Data Format: Extended mode (0x03). Full mode is not working yet. The output reports 0x3e and 0x3f need tampering with - * In this mode the camera outputs x and y coordinates and a size dimension for the 4 brightest points. - -Again, read through to get an understanding of the camera and its settings. diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXOLD.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXOLD.cpp deleted file mode 100644 index 78e6e9a5f5..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXOLD.cpp +++ /dev/null @@ -1,337 +0,0 @@ -/* Copyright (C) 2013 Kristian Lauszus, TKJ Electronics. All rights reserved. - - This software may be distributed and modified under the terms of the GNU - General Public License version 2 (GPL2) as published by the Free Software - Foundation and appearing in the file GPL2.TXT included in the packaging of - this file. Please note that GPL2 Section 2[b] requires that all works based - on this software must also be made publicly available under the terms of - the GPL2 ("Copyleft"). - - Contact information - ------------------- - - Kristian Lauszus, TKJ Electronics - Web : http://www.tkjelectronics.com - e-mail : kristianl@tkjelectronics.com - */ - -#include "XBOXOLD.h" -// To enable serial debugging see "settings.h" -//#define EXTRADEBUG // Uncomment to get even more debugging data -//#define PRINTREPORT // Uncomment to print the report send by the Xbox controller - -/** Buttons on the controllers */ -const uint8_t XBOXOLD_BUTTONS[] PROGMEM = { - 0x01, // UP - 0x08, // RIGHT - 0x02, // DOWN - 0x04, // LEFT - - 0x20, // BACK - 0x10, // START - 0x40, // L3 - 0x80, // R3 - - // A, B, X, Y, BLACK, WHITE, L1, and R1 are analog buttons - 4, // BLACK - 5, // WHTIE - 6, // L1 - 7, // R1 - - 1, // B - 0, // A - 2, // X - 3, // Y -}; - -XBOXOLD::XBOXOLD(USB *p) : -pUsb(p), // pointer to USB class instance - mandatory -bAddress(0), // device address - mandatory -bPollEnable(false) { // don't start polling before dongle is connected - for(uint8_t i = 0; i < XBOX_MAX_ENDPOINTS; i++) { - epInfo[i].epAddr = 0; - epInfo[i].maxPktSize = (i) ? 0 : 8; - epInfo[i].epAttribs = 0; - epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; - } - - if(pUsb) // register in USB subsystem - pUsb->RegisterDeviceClass(this); //set devConfig[] entry -} - -uint8_t XBOXOLD::Init(uint8_t parent, uint8_t port, bool lowspeed) { - uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)]; - USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); - uint8_t rcode; - UsbDevice *p = NULL; - EpInfo *oldep_ptr = NULL; - uint16_t PID; - uint16_t VID; - - // get memory address of USB device address pool - AddressPool &addrPool = pUsb->GetAddressPool(); -#ifdef EXTRADEBUG - Notify(PSTR("\r\nXBOXUSB Init"), 0x80); -#endif - // check if address has already been assigned to an instance - if(bAddress) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nAddress in use"), 0x80); -#endif - return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; - } - - // Get pointer to pseudo device with address 0 assigned - p = addrPool.GetUsbDevicePtr(0); - - if(!p) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nAddress not found"), 0x80); -#endif - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - } - - if(!p->epinfo) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nepinfo is null"), 0x80); -#endif - return USB_ERROR_EPINFO_IS_NULL; - } - - // Save old pointer to EP_RECORD of address 0 - oldep_ptr = p->epinfo; - - // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence - p->epinfo = epInfo; - - p->lowspeed = lowspeed; - - // Get device descriptor - rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data - // Restore p->epinfo - p->epinfo = oldep_ptr; - - if(rcode) - goto FailGetDevDescr; - - VID = udd->idVendor; - PID = udd->idProduct; - - if((VID != XBOX_VID && VID != MADCATZ_VID && VID != JOYTECH_VID) || (PID != XBOX_OLD_PID1 && PID != XBOX_OLD_PID2 && PID != XBOX_OLD_PID3 && PID != XBOX_OLD_PID4)) // Check if VID and PID match - goto FailUnknownDevice; - - // Allocate new address according to device class - bAddress = addrPool.AllocAddress(parent, false, port); - - if(!bAddress) - return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; - - // Extract Max Packet Size from device descriptor - epInfo[0].maxPktSize = udd->bMaxPacketSize0; - - // Assign new address to the device - rcode = pUsb->setAddr(0, 0, bAddress); - if(rcode) { - p->lowspeed = false; - addrPool.FreeAddress(bAddress); - bAddress = 0; -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nsetAddr: "), 0x80); - D_PrintHex (rcode, 0x80); -#endif - return rcode; - } -#ifdef EXTRADEBUG - Notify(PSTR("\r\nAddr: "), 0x80); - D_PrintHex (bAddress, 0x80); -#endif - //delay(300); // Spec says you should wait at least 200ms - - p->lowspeed = false; - - //get pointer to assigned address record - p = addrPool.GetUsbDevicePtr(bAddress); - if(!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - p->lowspeed = lowspeed; - - // Assign epInfo to epinfo pointer - only EP0 is known - rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); - if(rcode) - goto FailSetDevTblEntry; - - /* The application will work in reduced host mode, so we can save program and data - memory space. After verifying the VID we will use known values for the - configuration values for device, interface, endpoints and HID for the XBOX controllers */ - - /* Initialize data structures for endpoints of device */ - epInfo[ XBOX_INPUT_PIPE ].epAddr = 0x01; // XBOX report endpoint - epInfo[ XBOX_INPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; - epInfo[ XBOX_INPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints - epInfo[ XBOX_INPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; - epInfo[ XBOX_INPUT_PIPE ].bmSndToggle = 0; - epInfo[ XBOX_INPUT_PIPE ].bmRcvToggle = 0; - epInfo[ XBOX_OUTPUT_PIPE ].epAddr = 0x02; // XBOX output endpoint - epInfo[ XBOX_OUTPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; - epInfo[ XBOX_OUTPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints - epInfo[ XBOX_OUTPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; - epInfo[ XBOX_OUTPUT_PIPE ].bmSndToggle = 0; - epInfo[ XBOX_OUTPUT_PIPE ].bmRcvToggle = 0; - - rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo); - if(rcode) - goto FailSetDevTblEntry; - - delay(200); // Give time for address change - - rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1); - if(rcode) - goto FailSetConfDescr; - -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nXbox Controller Connected\r\n"), 0x80); -#endif - if(pFuncOnInit) - pFuncOnInit(); // Call the user function - XboxConnected = true; - bPollEnable = true; - return 0; // Successful configuration - - /* Diagnostic messages */ -FailGetDevDescr: -#ifdef DEBUG_USB_HOST - NotifyFailGetDevDescr(); - goto Fail; -#endif - -FailSetDevTblEntry: -#ifdef DEBUG_USB_HOST - NotifyFailSetDevTblEntry(); - goto Fail; -#endif - -FailSetConfDescr: -#ifdef DEBUG_USB_HOST - NotifyFailSetConfDescr(); -#endif - goto Fail; - -FailUnknownDevice: -#ifdef DEBUG_USB_HOST - NotifyFailUnknownDevice(VID, PID); -#endif - rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - -Fail: -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nXbox Init Failed, error code: "), 0x80); - NotifyFail(rcode); -#endif - Release(); - return rcode; -} - -/* Performs a cleanup after failed Init() attempt */ -uint8_t XBOXOLD::Release() { - XboxConnected = false; - pUsb->GetAddressPool().FreeAddress(bAddress); - bAddress = 0; - bPollEnable = false; - return 0; -} - -uint8_t XBOXOLD::Poll() { - if(!bPollEnable) - return 0; - uint16_t BUFFER_SIZE = EP_MAXPKTSIZE; - pUsb->inTransfer(bAddress, epInfo[ XBOX_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf); // input on endpoint 1 - readReport(); -#ifdef PRINTREPORT - printReport(BUFFER_SIZE); // Uncomment "#define PRINTREPORT" to print the report send by the Xbox controller -#endif - return 0; -} - -void XBOXOLD::readReport() { - ButtonState = readBuf[2]; - - for(uint8_t i = 0; i < sizeof (buttonValues); i++) - buttonValues[i] = readBuf[i + 4]; // A, B, X, Y, BLACK, WHITE, L1, and R1 - - hatValue[LeftHatX] = (int16_t)(((uint16_t)readBuf[12] << 8) | readBuf[13]); - hatValue[LeftHatY] = (int16_t)(((uint16_t)readBuf[14] << 8) | readBuf[15]); - hatValue[RightHatX] = (int16_t)(((uint16_t)readBuf[16] << 8) | readBuf[17]); - hatValue[RightHatY] = (int16_t)(((uint16_t)readBuf[18] << 8) | readBuf[19]); - - //Notify(PSTR("\r\nButtonState"), 0x80); - //PrintHex(ButtonState, 0x80); - - if(ButtonState != OldButtonState || memcmp(buttonValues, oldButtonValues, sizeof (buttonValues)) != 0) { - ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable - OldButtonState = ButtonState; - - for(uint8_t i = 0; i < sizeof (buttonValues); i++) { - if(oldButtonValues[i] == 0 && buttonValues[i] != 0) - buttonClicked[i] = true; // Update A, B, X, Y, BLACK, WHITE, L1, and R1 click state - oldButtonValues[i] = buttonValues[i]; - } - } -} - -void XBOXOLD::printReport(uint16_t length) { //Uncomment "#define PRINTREPORT" to print the report send by the Xbox controller -#ifdef PRINTREPORT - if(readBuf == NULL) - return; - for(uint8_t i = 0; i < length; i++) { - D_PrintHex (readBuf[i], 0x80); - Notify(PSTR(" "), 0x80); - } - Notify(PSTR("\r\n"), 0x80); -#endif -} - -uint8_t XBOXOLD::getButtonPress(ButtonEnum b) { - uint8_t button = pgm_read_byte(&XBOXOLD_BUTTONS[(uint8_t)b]); - if(b == A || b == B || b == X || b == Y || b == BLACK || b == WHITE || b == L1 || b == R1) // A, B, X, Y, BLACK, WHITE, L1, and R1 are analog buttons - return buttonValues[button]; // Analog buttons - return (ButtonState & button); // Digital buttons -} - -bool XBOXOLD::getButtonClick(ButtonEnum b) { - uint8_t button = pgm_read_byte(&XBOXOLD_BUTTONS[(uint8_t)b]); - if(b == A || b == B || b == X || b == Y || b == BLACK || b == WHITE || b == L1 || b == R1) { // A, B, X, Y, BLACK, WHITE, L1, and R1 are analog buttons - if(buttonClicked[button]) { - buttonClicked[button] = false; - return true; - } - return false; - } - - bool click = (ButtonClickState & button); - ButtonClickState &= ~button; // clear "click" event - return click; -} - -int16_t XBOXOLD::getAnalogHat(AnalogHatEnum a) { - return hatValue[a]; -} - -/* Xbox Controller commands */ -void XBOXOLD::XboxCommand(uint8_t* data, uint16_t nbytes) { - //bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x00), Report Type (Output 0x02), interface (0x00), datalength, datalength, data) - pUsb->ctrlReq(bAddress, epInfo[XBOX_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x00, 0x02, 0x00, nbytes, nbytes, data, NULL); -} - -void XBOXOLD::setRumbleOn(uint8_t lValue, uint8_t rValue) { - uint8_t writeBuf[6]; - - writeBuf[0] = 0x00; - writeBuf[1] = 0x06; - writeBuf[2] = 0x00; - writeBuf[3] = rValue; // small weight - writeBuf[4] = 0x00; - writeBuf[5] = lValue; // big weight - - XboxCommand(writeBuf, 6); -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXOLD.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXOLD.h deleted file mode 100644 index 9a36b5ccac..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXOLD.h +++ /dev/null @@ -1,185 +0,0 @@ -/* Copyright (C) 2013 Kristian Lauszus, TKJ Electronics. All rights reserved. - - This software may be distributed and modified under the terms of the GNU - General Public License version 2 (GPL2) as published by the Free Software - Foundation and appearing in the file GPL2.TXT included in the packaging of - this file. Please note that GPL2 Section 2[b] requires that all works based - on this software must also be made publicly available under the terms of - the GPL2 ("Copyleft"). - - Contact information - ------------------- - - Kristian Lauszus, TKJ Electronics - Web : http://www.tkjelectronics.com - e-mail : kristianl@tkjelectronics.com - */ - -#ifndef _xboxold_h_ -#define _xboxold_h_ - -#include "Usb.h" -#include "hid.h" -#include "controllerEnums.h" - -/* Data Xbox taken from descriptors */ -#define EP_MAXPKTSIZE 32 // Max size for data via USB - -/* Names we give to the 3 Xbox pipes */ -#define XBOX_CONTROL_PIPE 0 -#define XBOX_INPUT_PIPE 1 -#define XBOX_OUTPUT_PIPE 2 - -// PID and VID of the different devices -#define XBOX_VID 0x045E // Microsoft Corporation -#define MADCATZ_VID 0x1BAD // For unofficial Mad Catz controllers -#define JOYTECH_VID 0x162E // For unofficial Joytech controllers - -#define XBOX_OLD_PID1 0x0202 // Original Microsoft Xbox controller (US) -#define XBOX_OLD_PID2 0x0285 // Original Microsoft Xbox controller (Japan) -#define XBOX_OLD_PID3 0x0287 // Microsoft Microsoft Xbox Controller S -#define XBOX_OLD_PID4 0x0289 // Smaller Microsoft Xbox controller (US) - -#define XBOX_MAX_ENDPOINTS 3 - -/** This class implements support for a the original Xbox controller via USB. */ -class XBOXOLD : public USBDeviceConfig { -public: - /** - * Constructor for the XBOXOLD class. - * @param pUsb Pointer to USB class instance. - */ - XBOXOLD(USB *pUsb); - - /** @name USBDeviceConfig implementation */ - /** - * Initialize the Xbox Controller. - * @param parent Hub number. - * @param port Port number on the hub. - * @param lowspeed Speed of the device. - * @return 0 on success. - */ - uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); - /** - * Release the USB device. - * @return 0 on success. - */ - uint8_t Release(); - /** - * Poll the USB Input endpoins and run the state machines. - * @return 0 on success. - */ - uint8_t Poll(); - - /** - * Get the device address. - * @return The device address. - */ - virtual uint8_t GetAddress() { - return bAddress; - }; - - /** - * Used to check if the controller has been initialized. - * @return True if it's ready. - */ - virtual bool isReady() { - return bPollEnable; - }; - - /** - * Used by the USB core to check what this driver support. - * @param vid The device's VID. - * @param pid The device's PID. - * @return Returns true if the device's VID and PID matches this driver. - */ - virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) { - return ((vid == XBOX_VID || vid == MADCATZ_VID || vid == JOYTECH_VID) && (pid == XBOX_OLD_PID1 || pid == XBOX_OLD_PID2 || pid == XBOX_OLD_PID3 || pid == XBOX_OLD_PID4)); - }; - /**@}*/ - - /** @name Xbox Controller functions */ - /** - * getButtonPress(ButtonEnum b) will return true as long as the button is held down. - * - * While getButtonClick(ButtonEnum b) will only return it once. - * - * So you instance if you need to increase a variable once you would use getButtonClick(ButtonEnum b), - * but if you need to drive a robot forward you would use getButtonPress(ButtonEnum b). - * @param b ::ButtonEnum to read. - * @return getButtonClick(ButtonEnum b) will return a bool, while getButtonPress(ButtonEnum b) will return a byte if reading ::L2 or ::R2. - */ - uint8_t getButtonPress(ButtonEnum b); - bool getButtonClick(ButtonEnum b); - /**@}*/ - - /** @name Xbox Controller functions */ - /** - * Return the analog value from the joysticks on the controller. - * @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY. - * @return Returns a signed 16-bit integer. - */ - int16_t getAnalogHat(AnalogHatEnum a); - - /** Turn rumble off the controller. */ - void setRumbleOff() { - setRumbleOn(0, 0); - }; - /** - * Turn rumble on. - * @param lValue Left motor (big weight) inside the controller. - * @param rValue Right motor (small weight) inside the controller. - */ - void setRumbleOn(uint8_t lValue, uint8_t rValue); - - /** - * Used to call your own function when the controller is successfully initialized. - * @param funcOnInit Function to call. - */ - void attachOnInit(void (*funcOnInit)(void)) { - pFuncOnInit = funcOnInit; - }; - /**@}*/ - - /** True if a Xbox controller is connected. */ - bool XboxConnected; - -protected: - /** Pointer to USB class instance. */ - USB *pUsb; - /** Device address. */ - uint8_t bAddress; - /** Endpoint info structure. */ - EpInfo epInfo[XBOX_MAX_ENDPOINTS]; - -private: - /** - * Called when the controller is successfully initialized. - * Use attachOnInit(void (*funcOnInit)(void)) to call your own function. - * This is useful for instance if you want to set the LEDs in a specific way. - */ - void (*pFuncOnInit)(void); // Pointer to function called in onInit() - - bool bPollEnable; - - /* Variables to store the digital buttons */ - uint8_t ButtonState; - uint8_t OldButtonState; - uint8_t ButtonClickState; - - /* Variables to store the analog buttons */ - uint8_t buttonValues[8]; // A, B, X, Y, BLACK, WHITE, L1, and R1 - uint8_t oldButtonValues[8]; - bool buttonClicked[8]; - - int16_t hatValue[4]; // Joystick values - - uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data - - void readReport(); // Read incoming data - void printReport(uint16_t length); // Print incoming date - - /* Private commands */ - void XboxCommand(uint8_t* data, uint16_t nbytes); -}; -#endif diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXONE.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXONE.cpp deleted file mode 100644 index 2159c0528b..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXONE.cpp +++ /dev/null @@ -1,374 +0,0 @@ -/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. - Copyright (C) 2015 guruthree - - This software may be distributed and modified under the terms of the GNU - General Public License version 2 (GPL2) as published by the Free Software - Foundation and appearing in the file GPL2.TXT included in the packaging of - this file. Please note that GPL2 Section 2[b] requires that all works based - on this software must also be made publicly available under the terms of - the GPL2 ("Copyleft"). - - Contact information - ------------------- - - Kristian Lauszus, TKJ Electronics - Web : http://www.tkjelectronics.com - e-mail : kristianl@tkjelectronics.com - - guruthree - Web : https://github.com/guruthree/ - */ - -#include "XBOXONE.h" -// To enable serial debugging see "settings.h" -//#define EXTRADEBUG // Uncomment to get even more debugging data -//#define PRINTREPORT // Uncomment to print the report send by the Xbox ONE Controller - -XBOXONE::XBOXONE(USB *p) : -pUsb(p), // pointer to USB class instance - mandatory -bAddress(0), // device address - mandatory -bPollEnable(false) { // don't start polling before dongle is connected - for(uint8_t i = 0; i < XBOX_MAX_ENDPOINTS; i++) { - epInfo[i].epAddr = 0; - epInfo[i].maxPktSize = (i) ? 0 : 8; - epInfo[i].epAttribs = 0; - epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; - } - - if(pUsb) // register in USB subsystem - pUsb->RegisterDeviceClass(this); //set devConfig[] entry -} - -uint8_t XBOXONE::Init(uint8_t parent, uint8_t port, bool lowspeed) { - uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)]; - USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); - uint8_t rcode; - UsbDevice *p = NULL; - EpInfo *oldep_ptr = NULL; - uint16_t PID; - uint16_t VID; - - // get memory address of USB device address pool - AddressPool &addrPool = pUsb->GetAddressPool(); -#ifdef EXTRADEBUG - Notify(PSTR("\r\nXBOXONE Init"), 0x80); -#endif - // check if address has already been assigned to an instance - if(bAddress) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nAddress in use"), 0x80); -#endif - return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; - } - - // Get pointer to pseudo device with address 0 assigned - p = addrPool.GetUsbDevicePtr(0); - - if(!p) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nAddress not found"), 0x80); -#endif - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - } - - if(!p->epinfo) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nepinfo is null"), 0x80); -#endif - return USB_ERROR_EPINFO_IS_NULL; - } - - // Save old pointer to EP_RECORD of address 0 - oldep_ptr = p->epinfo; - - // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence - p->epinfo = epInfo; - - p->lowspeed = lowspeed; - - // Get device descriptor - rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data - // Restore p->epinfo - p->epinfo = oldep_ptr; - - if(rcode) - goto FailGetDevDescr; - - VID = udd->idVendor; - PID = udd->idProduct; - - if(!VIDPIDOK(VID, PID)) // Check VID - goto FailUnknownDevice; - - // Allocate new address according to device class - bAddress = addrPool.AllocAddress(parent, false, port); - - if(!bAddress) - return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; - - // Extract Max Packet Size from device descriptor - epInfo[0].maxPktSize = udd->bMaxPacketSize0; - - // Assign new address to the device - rcode = pUsb->setAddr(0, 0, bAddress); - if(rcode) { - p->lowspeed = false; - addrPool.FreeAddress(bAddress); - bAddress = 0; -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nsetAddr: "), 0x80); - D_PrintHex (rcode, 0x80); -#endif - return rcode; - } -#ifdef EXTRADEBUG - Notify(PSTR("\r\nAddr: "), 0x80); - D_PrintHex (bAddress, 0x80); -#endif - //delay(300); // Spec says you should wait at least 200ms - - p->lowspeed = false; - - //get pointer to assigned address record - p = addrPool.GetUsbDevicePtr(bAddress); - if(!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - p->lowspeed = lowspeed; - - // Assign epInfo to epinfo pointer - only EP0 is known - rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); - if(rcode) - goto FailSetDevTblEntry; - - /* The application will work in reduced host mode, so we can save program and data - memory space. After verifying the VID we will use known values for the - configuration values for device, interface, endpoints and HID for the XBOXONE Controllers */ - - /* Initialize data structures for endpoints of device */ - epInfo[ XBOX_OUTPUT_PIPE ].epAddr = 0x01; // XBOX one output endpoint - epInfo[ XBOX_OUTPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; - epInfo[ XBOX_OUTPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints - epInfo[ XBOX_OUTPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; - epInfo[ XBOX_OUTPUT_PIPE ].bmSndToggle = 0; - epInfo[ XBOX_OUTPUT_PIPE ].bmRcvToggle = 0; - epInfo[ XBOX_INPUT_PIPE ].epAddr = 0x01; // XBOX one input endpoint - epInfo[ XBOX_INPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; - epInfo[ XBOX_INPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints - epInfo[ XBOX_INPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; - epInfo[ XBOX_INPUT_PIPE ].bmSndToggle = 0; - epInfo[ XBOX_INPUT_PIPE ].bmRcvToggle = 0; - - rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo); - if(rcode) - goto FailSetDevTblEntry; - - delay(200); // Give time for address change - - rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1); - if(rcode) - goto FailSetConfDescr; - -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nXbox One Controller Connected\r\n"), 0x80); -#endif - - delay(200); // let things settle - - // initialize the controller for input - writeBuf[0] = 0x05; - writeBuf[1] = 0x20; - rcode = XboxCommand(writeBuf, 2); - if (rcode) - goto Fail; - - onInit(); - XboxOneConnected = true; - bPollEnable = true; - return 0; // Successful configuration - - /* Diagnostic messages */ -FailGetDevDescr: -#ifdef DEBUG_USB_HOST - NotifyFailGetDevDescr(); - goto Fail; -#endif - -FailSetDevTblEntry: -#ifdef DEBUG_USB_HOST - NotifyFailSetDevTblEntry(); - goto Fail; -#endif - -FailSetConfDescr: -#ifdef DEBUG_USB_HOST - NotifyFailSetConfDescr(); -#endif - goto Fail; - -FailUnknownDevice: -#ifdef DEBUG_USB_HOST - NotifyFailUnknownDevice(VID, PID); -#endif - rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - -Fail: -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nXbox One Init Failed, error code: "), 0x80); - NotifyFail(rcode); -#endif - Release(); - return rcode; -} - -/* Performs a cleanup after failed Init() attempt */ -uint8_t XBOXONE::Release() { - XboxOneConnected = false; - pUsb->GetAddressPool().FreeAddress(bAddress); - bAddress = 0; - bPollEnable = false; -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nXbox One Controller Disconnected\r\n"), 0x80); -#endif - return 0; -} - -uint8_t XBOXONE::Poll() { - if(!bPollEnable) - return 0; - uint16_t BUFFER_SIZE = EP_MAXPKTSIZE; - uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[ XBOX_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf); - if (!rcode) { - readReport(); -#ifdef PRINTREPORT - printReport(); // Uncomment "#define PRINTREPORT" to print the report send by the Xbox ONE Controller -#endif - } -#ifdef DEBUG_USB_HOST - else if (rcode != 0x04) { // not a matter of no update to send - Notify(PSTR("\r\nXbox One Poll Failed, error code: "), 0x80); - NotifyFail(rcode); - } -#endif - return rcode; -} - -void XBOXONE::readReport() { - if(readBuf == NULL) - return; - if(readBuf[0] == 0x07) { - // The XBOX button has a separate message - if(readBuf[4] == 1) - ButtonState |= XBOX_BUTTONS[XBOX]; - else - ButtonState &= ~XBOX_BUTTONS[XBOX]; - } - if(readBuf[0] != 0x20) { // Check if it's the correct report, otherwise return - the controller also sends different status reports -#ifdef EXTRADEBUG - Notify(PSTR("\r\nXbox Poll: "), 0x80); - D_PrintHex (readBuf[0], 0x80); // 0x03 is a heart beat report! -#endif - return; - } - - uint16_t xbox = ButtonState & XBOX_BUTTONS[XBOX]; // Since the XBOX button is separate, save it and add it back in - // xbox button from before, dpad, abxy, start/back, sync, stick click, shoulder buttons - ButtonState = xbox | (((uint16_t)readBuf[5] & 0xF) << 8) | (readBuf[4] & 0xF0) | (((uint16_t)readBuf[4] & 0x0C) << 10) | ((readBuf[4] & 0x01) << 3) | (((uint16_t)readBuf[5] & 0xC0) << 8) | ((readBuf[5] & 0x30) >> 4); - - triggerValue[0] = (uint16_t)(((uint16_t)readBuf[7] << 8) | readBuf[6]); - triggerValue[1] = (uint16_t)(((uint16_t)readBuf[9] << 8) | readBuf[8]); - - hatValue[LeftHatX] = (int16_t)(((uint16_t)readBuf[11] << 8) | readBuf[10]); - hatValue[LeftHatY] = (int16_t)(((uint16_t)readBuf[13] << 8) | readBuf[12]); - hatValue[RightHatX] = (int16_t)(((uint16_t)readBuf[15] << 8) | readBuf[14]); - hatValue[RightHatY] = (int16_t)(((uint16_t)readBuf[17] << 8) | readBuf[16]); - - //Notify(PSTR("\r\nButtonState"), 0x80); - //PrintHex(ButtonState, 0x80); - - if(ButtonState != OldButtonState) { - ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable - OldButtonState = ButtonState; - } - - // Handle click detection for triggers - if(triggerValue[0] != 0 && triggerValueOld[0] == 0) - L2Clicked = true; - triggerValueOld[0] = triggerValue[0]; - if(triggerValue[1] != 0 && triggerValueOld[1] == 0) - R2Clicked = true; - triggerValueOld[1] = triggerValue[1]; -} - -void XBOXONE::printReport() { //Uncomment "#define PRINTREPORT" to print the report send by the Xbox ONE Controller -#ifdef PRINTREPORT - if(readBuf == NULL) - return; - for(uint8_t i = 0; i < XBOX_REPORT_BUFFER_SIZE; i++) { - D_PrintHex (readBuf[i], 0x80); - Notify(PSTR(" "), 0x80); - } - Notify(PSTR("\r\n"), 0x80); -#endif -} - -uint16_t XBOXONE::getButtonPress(ButtonEnum b) { - if(b == L2) // These are analog buttons - return triggerValue[0]; - else if(b == R2) - return triggerValue[1]; - return (bool)(ButtonState & ((uint16_t)pgm_read_word(&XBOX_BUTTONS[(uint8_t)b]))); -} - -bool XBOXONE::getButtonClick(ButtonEnum b) { - if(b == L2) { - if(L2Clicked) { - L2Clicked = false; - return true; - } - return false; - } else if(b == R2) { - if(R2Clicked) { - R2Clicked = false; - return true; - } - return false; - } - uint16_t button = pgm_read_word(&XBOX_BUTTONS[(uint8_t)b]); - bool click = (ButtonClickState & button); - ButtonClickState &= ~button; // clear "click" event - return click; -} - -int16_t XBOXONE::getAnalogHat(AnalogHatEnum a) { - return hatValue[a]; -} - -/* Xbox Controller commands */ -uint8_t XBOXONE::XboxCommand(uint8_t* data, uint16_t nbytes) { - uint8_t rcode = pUsb->outTransfer(bAddress, epInfo[ XBOX_OUTPUT_PIPE ].epAddr, nbytes, data); -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nXboxCommand, Return: "), 0x80); - D_PrintHex (rcode, 0x80); -#endif - return rcode; -} - -void XBOXONE::onInit() { - // a short buzz to show the controller is active - writeBuf[0] = 0x09; - writeBuf[1] = 0x08; - writeBuf[2] = 0x00; - writeBuf[3] = 0x09; - writeBuf[4] = 0x00; - writeBuf[5] = 0x0f; - writeBuf[6] = 0x04; - writeBuf[7] = 0x04; - writeBuf[8] = 0x20; - writeBuf[9] = 0x20; - writeBuf[10] = 0x80; - XboxCommand(writeBuf, 11); - - if(pFuncOnInit) - pFuncOnInit(); // Call the user function -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXONE.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXONE.h deleted file mode 100644 index 11710fcf1a..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXONE.h +++ /dev/null @@ -1,172 +0,0 @@ -/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. - Copyright (C) 2015 guruthree - - This software may be distributed and modified under the terms of the GNU - General Public License version 2 (GPL2) as published by the Free Software - Foundation and appearing in the file GPL2.TXT included in the packaging of - this file. Please note that GPL2 Section 2[b] requires that all works based - on this software must also be made publicly available under the terms of - the GPL2 ("Copyleft"). - - Contact information - ------------------- - - Kristian Lauszus, TKJ Electronics - Web : http://www.tkjelectronics.com - e-mail : kristianl@tkjelectronics.com - - guruthree - Web : https://github.com/guruthree/ - */ - - -#ifndef _xboxone_h_ -#define _xboxone_h_ - -#include "Usb.h" -#include "xboxEnums.h" - -/* Data Xbox ONE taken from descriptors */ -#define EP_MAXPKTSIZE 32 // max size for data via USB - -/* Names we give to the 3 XboxONE pipes */ -#define XBOX_CONTROL_PIPE 0 -#define XBOX_OUTPUT_PIPE 1 -#define XBOX_INPUT_PIPE 2 - -// PID and VID of the different devices -#define XBOX_VID 0x045E // Microsoft Corporation -#define XBOX_ONE_PID 0x02D1 // Microsoft One Wired controller - -#define XBOX_REPORT_BUFFER_SIZE 14 // Size of the input report buffer - -#define XBOX_MAX_ENDPOINTS 3 - -/** This class implements support for a Xbox ONE controller connected via USB. */ -class XBOXONE : public USBDeviceConfig { -public: - /** - * Constructor for the XBOXONE class. - * @param pUsb Pointer to USB class instance. - */ - XBOXONE(USB *pUsb); - - /** @name USBDeviceConfig implementation */ - /** - * Initialize the Xbox Controller. - * @param parent Hub number. - * @param port Port number on the hub. - * @param lowspeed Speed of the device. - * @return 0 on success. - */ - virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); - /** - * Release the USB device. - * @return 0 on success. - */ - virtual uint8_t Release(); - /** - * Poll the USB Input endpoins and run the state machines. - * @return 0 on success. - */ - virtual uint8_t Poll(); - - /** - * Get the device address. - * @return The device address. - */ - virtual uint8_t GetAddress() { - return bAddress; - }; - - /** - * Used to check if the controller has been initialized. - * @return True if it's ready. - */ - virtual bool isReady() { - return bPollEnable; - }; - - /** - * Used by the USB core to check what this driver support. - * @param vid The device's VID. - * @param pid The device's PID. - * @return Returns true if the device's VID and PID matches this driver. - */ - virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) { - return (vid == XBOX_VID && pid == XBOX_ONE_PID); - }; - /**@}*/ - - /** @name Xbox Controller functions */ - /** - * getButtonPress(ButtonEnum b) will return true as long as the button is held down. - * - * While getButtonClick(ButtonEnum b) will only return it once. - * - * So you instance if you need to increase a variable once you would use getButtonClick(ButtonEnum b), - * but if you need to drive a robot forward you would use getButtonPress(ButtonEnum b). - * @param b ::ButtonEnum to read. - * @return getButtonClick(ButtonEnum b) will return a bool, while getButtonPress(ButtonEnum b) will return a word if reading ::L2 or ::R2. - */ - uint16_t getButtonPress(ButtonEnum b); - bool getButtonClick(ButtonEnum b); - - /** - * Return the analog value from the joysticks on the controller. - * @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY. - * @return Returns a signed 16-bit integer. - */ - int16_t getAnalogHat(AnalogHatEnum a); - - /** - * Used to call your own function when the controller is successfully initialized. - * @param funcOnInit Function to call. - */ - void attachOnInit(void (*funcOnInit)(void)) { - pFuncOnInit = funcOnInit; - }; - /**@}*/ - - /** True if a Xbox ONE controller is connected. */ - bool XboxOneConnected; - -protected: - /** Pointer to USB class instance. */ - USB *pUsb; - /** Device address. */ - uint8_t bAddress; - /** Endpoint info structure. */ - EpInfo epInfo[XBOX_MAX_ENDPOINTS]; - -private: - /** - * Called when the controller is successfully initialized. - * Use attachOnInit(void (*funcOnInit)(void)) to call your own function. - */ - void onInit(); - void (*pFuncOnInit)(void); // Pointer to function called in onInit() - - bool bPollEnable; - - /* Variables to store the buttons */ - uint16_t ButtonState; - uint16_t OldButtonState; - uint16_t ButtonClickState; - int16_t hatValue[4]; - uint16_t triggerValue[2]; - uint16_t triggerValueOld[2]; - - bool L2Clicked; // These buttons are analog, so we use we use these bools to check if they where clicked or not - bool R2Clicked; - - uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data - uint8_t writeBuf[12]; // General purpose buffer for output data - - void readReport(); // read incoming data - void printReport(); // print incoming date - Uncomment for debugging - - /* Private commands */ - uint8_t XboxCommand(uint8_t* data, uint16_t nbytes); -}; -#endif diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXRECV.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXRECV.cpp deleted file mode 100644 index 41f1ff5816..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXRECV.cpp +++ /dev/null @@ -1,583 +0,0 @@ -/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. - - This software may be distributed and modified under the terms of the GNU - General Public License version 2 (GPL2) as published by the Free Software - Foundation and appearing in the file GPL2.TXT included in the packaging of - this file. Please note that GPL2 Section 2[b] requires that all works based - on this software must also be made publicly available under the terms of - the GPL2 ("Copyleft"). - - Contact information - ------------------- - - Kristian Lauszus, TKJ Electronics - Web : http://www.tkjelectronics.com - e-mail : kristianl@tkjelectronics.com - - getBatteryLevel and checkStatus functions made by timstamp.co.uk found using BusHound from Perisoft.net - */ - -#include "XBOXRECV.h" -// To enable serial debugging see "settings.h" -//#define EXTRADEBUG // Uncomment to get even more debugging data -//#define PRINTREPORT // Uncomment to print the report send by the Xbox 360 Controller - -XBOXRECV::XBOXRECV(USB *p) : -pUsb(p), // pointer to USB class instance - mandatory -bAddress(0), // device address - mandatory -bPollEnable(false) { // don't start polling before dongle is connected - for(uint8_t i = 0; i < XBOX_MAX_ENDPOINTS; i++) { - epInfo[i].epAddr = 0; - epInfo[i].maxPktSize = (i) ? 0 : 8; - epInfo[i].epAttribs = 0; - epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; - } - - if(pUsb) // register in USB subsystem - pUsb->RegisterDeviceClass(this); //set devConfig[] entry -} - -uint8_t XBOXRECV::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) { - const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR); - uint8_t buf[constBufSize]; - USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); - uint8_t rcode; - UsbDevice *p = NULL; - EpInfo *oldep_ptr = NULL; - uint16_t PID, VID; - - AddressPool &addrPool = pUsb->GetAddressPool(); // Get memory address of USB device address pool -#ifdef EXTRADEBUG - Notify(PSTR("\r\nXBOXRECV Init"), 0x80); -#endif - - if(bAddress) { // Check if address has already been assigned to an instance -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nAddress in use"), 0x80); -#endif - return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; - } - - p = addrPool.GetUsbDevicePtr(0); // Get pointer to pseudo device with address 0 assigned - - if(!p) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nAddress not found"), 0x80); -#endif - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - } - - if(!p->epinfo) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nepinfo is null"), 0x80); -#endif - return USB_ERROR_EPINFO_IS_NULL; - } - - oldep_ptr = p->epinfo; // Save old pointer to EP_RECORD of address 0 - p->epinfo = epInfo; // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence - p->lowspeed = lowspeed; - - rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data - - p->epinfo = oldep_ptr; // Restore p->epinfo - - if(rcode) - goto FailGetDevDescr; - - VID = udd->idVendor; - PID = udd->idProduct; - - if((VID != XBOX_VID && VID != MADCATZ_VID && VID != JOYTECH_VID) || (PID != XBOX_WIRELESS_RECEIVER_PID && PID != XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID)) { // Check if it's a Xbox receiver using the Vendor ID and Product ID -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nYou'll need a wireless receiver for this libary to work"), 0x80); -#endif - goto FailUnknownDevice; - } - - bAddress = addrPool.AllocAddress(parent, false, port); // Allocate new address according to device class - - if(!bAddress) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nOut of address space"), 0x80); -#endif - return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; - } - - epInfo[0].maxPktSize = udd->bMaxPacketSize0; // Extract Max Packet Size from device descriptor - - delay(20); // Wait a little before resetting device - - return USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET; - - /* Diagnostic messages */ -FailGetDevDescr: -#ifdef DEBUG_USB_HOST - NotifyFailGetDevDescr(rcode); -#endif - if(rcode != hrJERR) - rcode = USB_ERROR_FailGetDevDescr; - goto Fail; - -FailUnknownDevice: -#ifdef DEBUG_USB_HOST - NotifyFailUnknownDevice(VID, PID); -#endif - rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - -Fail: -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nXbox 360 Init Failed, error code: "), 0x80); - NotifyFail(rcode); -#endif - Release(); - return rcode; -}; - -uint8_t XBOXRECV::Init(uint8_t parent, uint8_t port, bool lowspeed) { - uint8_t rcode; - - AddressPool &addrPool = pUsb->GetAddressPool(); -#ifdef EXTRADEBUG - Notify(PSTR("\r\nBTD Init"), 0x80); -#endif - UsbDevice *p = addrPool.GetUsbDevicePtr(bAddress); // Get pointer to assigned address record - - if(!p) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nAddress not found"), 0x80); -#endif - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - } - - delay(300); // Assign new address to the device - - rcode = pUsb->setAddr(0, 0, bAddress); // Assign new address to the device - if(rcode) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nsetAddr: "), 0x80); - D_PrintHex (rcode, 0x80); -#endif - p->lowspeed = false; - goto Fail; - } -#ifdef EXTRADEBUG - Notify(PSTR("\r\nAddr: "), 0x80); - D_PrintHex (bAddress, 0x80); -#endif - - p->lowspeed = false; - - p = addrPool.GetUsbDevicePtr(bAddress); // Get pointer to assigned address record - if(!p) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nAddress not found"), 0x80); -#endif - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - } - - p->lowspeed = lowspeed; - - rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); // Assign epInfo to epinfo pointer - only EP0 is known - if(rcode) - goto FailSetDevTblEntry; - - /* The application will work in reduced host mode, so we can save program and data - memory space. After verifying the VID we will use known values for the - configuration values for device, interface, endpoints and HID for the XBOX360 Wireless receiver */ - - /* Initialize data structures for endpoints of device */ - epInfo[ XBOX_INPUT_PIPE_1 ].epAddr = 0x01; // XBOX 360 report endpoint - poll interval 1ms - epInfo[ XBOX_INPUT_PIPE_1 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; - epInfo[ XBOX_INPUT_PIPE_1 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints - epInfo[ XBOX_INPUT_PIPE_1 ].maxPktSize = EP_MAXPKTSIZE; - epInfo[ XBOX_INPUT_PIPE_1 ].bmSndToggle = 0; - epInfo[ XBOX_INPUT_PIPE_1 ].bmRcvToggle = 0; - epInfo[ XBOX_OUTPUT_PIPE_1 ].epAddr = 0x01; // XBOX 360 output endpoint - poll interval 8ms - epInfo[ XBOX_OUTPUT_PIPE_1 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; - epInfo[ XBOX_OUTPUT_PIPE_1 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints - epInfo[ XBOX_OUTPUT_PIPE_1 ].maxPktSize = EP_MAXPKTSIZE; - epInfo[ XBOX_OUTPUT_PIPE_1 ].bmSndToggle = 0; - epInfo[ XBOX_OUTPUT_PIPE_1 ].bmRcvToggle = 0; - - epInfo[ XBOX_INPUT_PIPE_2 ].epAddr = 0x03; // XBOX 360 report endpoint - poll interval 1ms - epInfo[ XBOX_INPUT_PIPE_2 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; - epInfo[ XBOX_INPUT_PIPE_2 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints - epInfo[ XBOX_INPUT_PIPE_2 ].maxPktSize = EP_MAXPKTSIZE; - epInfo[ XBOX_INPUT_PIPE_2 ].bmSndToggle = 0; - epInfo[ XBOX_INPUT_PIPE_2 ].bmRcvToggle = 0; - epInfo[ XBOX_OUTPUT_PIPE_2 ].epAddr = 0x03; // XBOX 360 output endpoint - poll interval 8ms - epInfo[ XBOX_OUTPUT_PIPE_2 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; - epInfo[ XBOX_OUTPUT_PIPE_2 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints - epInfo[ XBOX_OUTPUT_PIPE_2 ].maxPktSize = EP_MAXPKTSIZE; - epInfo[ XBOX_OUTPUT_PIPE_2 ].bmSndToggle = 0; - epInfo[ XBOX_OUTPUT_PIPE_2 ].bmRcvToggle = 0; - - epInfo[ XBOX_INPUT_PIPE_3 ].epAddr = 0x05; // XBOX 360 report endpoint - poll interval 1ms - epInfo[ XBOX_INPUT_PIPE_3 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; - epInfo[ XBOX_INPUT_PIPE_3 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints - epInfo[ XBOX_INPUT_PIPE_3 ].maxPktSize = EP_MAXPKTSIZE; - epInfo[ XBOX_INPUT_PIPE_3 ].bmSndToggle = 0; - epInfo[ XBOX_INPUT_PIPE_3 ].bmRcvToggle = 0; - epInfo[ XBOX_OUTPUT_PIPE_3 ].epAddr = 0x05; // XBOX 360 output endpoint - poll interval 8ms - epInfo[ XBOX_OUTPUT_PIPE_3 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; - epInfo[ XBOX_OUTPUT_PIPE_3 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints - epInfo[ XBOX_OUTPUT_PIPE_3 ].maxPktSize = EP_MAXPKTSIZE; - epInfo[ XBOX_OUTPUT_PIPE_3 ].bmSndToggle = 0; - epInfo[ XBOX_OUTPUT_PIPE_3 ].bmRcvToggle = 0; - - epInfo[ XBOX_INPUT_PIPE_4 ].epAddr = 0x07; // XBOX 360 report endpoint - poll interval 1ms - epInfo[ XBOX_INPUT_PIPE_4 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; - epInfo[ XBOX_INPUT_PIPE_4 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints - epInfo[ XBOX_INPUT_PIPE_4 ].maxPktSize = EP_MAXPKTSIZE; - epInfo[ XBOX_INPUT_PIPE_4 ].bmSndToggle = 0; - epInfo[ XBOX_INPUT_PIPE_4 ].bmRcvToggle = 0; - epInfo[ XBOX_OUTPUT_PIPE_4 ].epAddr = 0x07; // XBOX 360 output endpoint - poll interval 8ms - epInfo[ XBOX_OUTPUT_PIPE_4 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; - epInfo[ XBOX_OUTPUT_PIPE_4 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints - epInfo[ XBOX_OUTPUT_PIPE_4 ].maxPktSize = EP_MAXPKTSIZE; - epInfo[ XBOX_OUTPUT_PIPE_4 ].bmSndToggle = 0; - epInfo[ XBOX_OUTPUT_PIPE_4 ].bmRcvToggle = 0; - - rcode = pUsb->setEpInfoEntry(bAddress, 9, epInfo); - if(rcode) - goto FailSetDevTblEntry; - - delay(200); //Give time for address change - - rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1); - if(rcode) - goto FailSetConfDescr; - -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nXbox Wireless Receiver Connected\r\n"), 0x80); -#endif - XboxReceiverConnected = true; - bPollEnable = true; - checkStatusTimer = 0; // Reset timer - return 0; // Successful configuration - - /* Diagnostic messages */ -FailSetDevTblEntry: -#ifdef DEBUG_USB_HOST - NotifyFailSetDevTblEntry(); - goto Fail; -#endif - -FailSetConfDescr: -#ifdef DEBUG_USB_HOST - NotifyFailSetConfDescr(); -#endif - -Fail: -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nXbox 360 Init Failed, error code: "), 0x80); - NotifyFail(rcode); -#endif - Release(); - return rcode; -} - -/* Performs a cleanup after failed Init() attempt */ -uint8_t XBOXRECV::Release() { - XboxReceiverConnected = false; - for(uint8_t i = 0; i < 4; i++) - Xbox360Connected[i] = 0x00; - pUsb->GetAddressPool().FreeAddress(bAddress); - bAddress = 0; - bPollEnable = false; - return 0; -} - -uint8_t XBOXRECV::Poll() { - if(!bPollEnable) - return 0; - if(!checkStatusTimer || ((millis() - checkStatusTimer) > 3000)) { // Run checkStatus every 3 seconds - checkStatusTimer = millis(); - checkStatus(); - } - - uint8_t inputPipe; - uint16_t bufferSize; - for(uint8_t i = 0; i < 4; i++) { - if(i == 0) - inputPipe = XBOX_INPUT_PIPE_1; - else if(i == 1) - inputPipe = XBOX_INPUT_PIPE_2; - else if(i == 2) - inputPipe = XBOX_INPUT_PIPE_3; - else - inputPipe = XBOX_INPUT_PIPE_4; - - bufferSize = EP_MAXPKTSIZE; // This is the maximum number of bytes we want to receive - pUsb->inTransfer(bAddress, epInfo[ inputPipe ].epAddr, &bufferSize, readBuf); - if(bufferSize > 0) { // The number of received bytes -#ifdef EXTRADEBUG - Notify(PSTR("Bytes Received: "), 0x80); - D_PrintHex (bufferSize, 0x80); - Notify(PSTR("\r\n"), 0x80); -#endif - readReport(i); -#ifdef PRINTREPORT - printReport(i, bufferSize); // Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller -#endif - } - } - return 0; -} - -void XBOXRECV::readReport(uint8_t controller) { - if(readBuf == NULL) - return; - // This report is send when a controller is connected and disconnected - if(readBuf[0] == 0x08 && readBuf[1] != Xbox360Connected[controller]) { - Xbox360Connected[controller] = readBuf[1]; -#ifdef DEBUG_USB_HOST - Notify(PSTR("Controller "), 0x80); - Notify(controller, 0x80); -#endif - if(Xbox360Connected[controller]) { -#ifdef DEBUG_USB_HOST - const char* str = 0; - switch(readBuf[1]) { - case 0x80: str = PSTR(" as controller\r\n"); - break; - case 0x40: str = PSTR(" as headset\r\n"); - break; - case 0xC0: str = PSTR(" as controller+headset\r\n"); - break; - } - Notify(PSTR(": connected"), 0x80); - Notify(str, 0x80); -#endif - onInit(controller); - } -#ifdef DEBUG_USB_HOST - else - Notify(PSTR(": disconnected\r\n"), 0x80); -#endif - return; - } - // Controller status report - if(readBuf[1] == 0x00 && readBuf[3] & 0x13 && readBuf[4] >= 0x22) { - controllerStatus[controller] = ((uint16_t)readBuf[3] << 8) | readBuf[4]; - return; - } - if(readBuf[1] != 0x01) // Check if it's the correct report - the receiver also sends different status reports - return; - - // A controller must be connected if it's sending data - if(!Xbox360Connected[controller]) - Xbox360Connected[controller] |= 0x80; - - ButtonState[controller] = (uint32_t)(readBuf[9] | ((uint16_t)readBuf[8] << 8) | ((uint32_t)readBuf[7] << 16) | ((uint32_t)readBuf[6] << 24)); - - hatValue[controller][LeftHatX] = (int16_t)(((uint16_t)readBuf[11] << 8) | readBuf[10]); - hatValue[controller][LeftHatY] = (int16_t)(((uint16_t)readBuf[13] << 8) | readBuf[12]); - hatValue[controller][RightHatX] = (int16_t)(((uint16_t)readBuf[15] << 8) | readBuf[14]); - hatValue[controller][RightHatY] = (int16_t)(((uint16_t)readBuf[17] << 8) | readBuf[16]); - - //Notify(PSTR("\r\nButtonState: "), 0x80); - //PrintHex(ButtonState[controller], 0x80); - - if(ButtonState[controller] != OldButtonState[controller]) { - buttonStateChanged[controller] = true; - ButtonClickState[controller] = (ButtonState[controller] >> 16) & ((~OldButtonState[controller]) >> 16); // Update click state variable, but don't include the two trigger buttons L2 and R2 - if(((uint8_t)OldButtonState[controller]) == 0 && ((uint8_t)ButtonState[controller]) != 0) // The L2 and R2 buttons are special as they are analog buttons - R2Clicked[controller] = true; - if((uint8_t)(OldButtonState[controller] >> 8) == 0 && (uint8_t)(ButtonState[controller] >> 8) != 0) - L2Clicked[controller] = true; - OldButtonState[controller] = ButtonState[controller]; - } -} - -void XBOXRECV::printReport(uint8_t controller, uint8_t nBytes) { //Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller -#ifdef PRINTREPORT - if(readBuf == NULL) - return; - Notify(PSTR("Controller "), 0x80); - Notify(controller, 0x80); - Notify(PSTR(": "), 0x80); - for(uint8_t i = 0; i < nBytes; i++) { - D_PrintHex (readBuf[i], 0x80); - Notify(PSTR(" "), 0x80); - } - Notify(PSTR("\r\n"), 0x80); -#endif -} - -uint8_t XBOXRECV::getButtonPress(ButtonEnum b, uint8_t controller) { - if(b == L2) // These are analog buttons - return (uint8_t)(ButtonState[controller] >> 8); - else if(b == R2) - return (uint8_t)ButtonState[controller]; - return (bool)(ButtonState[controller] & ((uint32_t)pgm_read_word(&XBOX_BUTTONS[(uint8_t)b]) << 16)); -} - -bool XBOXRECV::getButtonClick(ButtonEnum b, uint8_t controller) { - if(b == L2) { - if(L2Clicked[controller]) { - L2Clicked[controller] = false; - return true; - } - return false; - } else if(b == R2) { - if(R2Clicked[controller]) { - R2Clicked[controller] = false; - return true; - } - return false; - } - uint16_t button = pgm_read_word(&XBOX_BUTTONS[(uint8_t)b]); - bool click = (ButtonClickState[controller] & button); - ButtonClickState[controller] &= ~button; // clear "click" event - return click; -} - -int16_t XBOXRECV::getAnalogHat(AnalogHatEnum a, uint8_t controller) { - return hatValue[controller][a]; -} - -bool XBOXRECV::buttonChanged(uint8_t controller) { - bool state = buttonStateChanged[controller]; - buttonStateChanged[controller] = false; - return state; -} - -/* -ControllerStatus Breakdown -ControllerStatus[controller] & 0x0001 // 0 -ControllerStatus[controller] & 0x0002 // normal batteries, no rechargeable battery pack -ControllerStatus[controller] & 0x0004 // controller starting up / settling -ControllerStatus[controller] & 0x0008 // headset adapter plugged in, but no headphones connected (mute?) -ControllerStatus[controller] & 0x0010 // 0 -ControllerStatus[controller] & 0x0020 // 1 -ControllerStatus[controller] & 0x0040 // battery level (high bit) -ControllerStatus[controller] & 0x0080 // battery level (low bit) -ControllerStatus[controller] & 0x0100 // 1 -ControllerStatus[controller] & 0x0200 // 1 -ControllerStatus[controller] & 0x0400 // headset adapter plugged in -ControllerStatus[controller] & 0x0800 // 0 -ControllerStatus[controller] & 0x1000 // 1 -ControllerStatus[controller] & 0x2000 // 0 -ControllerStatus[controller] & 0x4000 // 0 -ControllerStatus[controller] & 0x8000 // 0 - */ -uint8_t XBOXRECV::getBatteryLevel(uint8_t controller) { - return ((controllerStatus[controller] & 0x00C0) >> 6); -} - -void XBOXRECV::XboxCommand(uint8_t controller, uint8_t* data, uint16_t nbytes) { -#ifdef EXTRADEBUG - uint8_t rcode; -#endif - uint8_t outputPipe; - switch(controller) { - case 0: outputPipe = XBOX_OUTPUT_PIPE_1; - break; - case 1: outputPipe = XBOX_OUTPUT_PIPE_2; - break; - case 2: outputPipe = XBOX_OUTPUT_PIPE_3; - break; - case 3: outputPipe = XBOX_OUTPUT_PIPE_4; - break; - default: - return; - } -#ifdef EXTRADEBUG - rcode = -#endif - pUsb->outTransfer(bAddress, epInfo[ outputPipe ].epAddr, nbytes, data); -#ifdef EXTRADEBUG - if(rcode) - Notify(PSTR("Error sending Xbox message\r\n"), 0x80); -#endif -} - -void XBOXRECV::disconnect(uint8_t controller) { - writeBuf[0] = 0x00; - writeBuf[1] = 0x00; - writeBuf[2] = 0x08; - writeBuf[3] = 0xC0; - - XboxCommand(controller, writeBuf, 4); -} - -void XBOXRECV::setLedRaw(uint8_t value, uint8_t controller) { - writeBuf[0] = 0x00; - writeBuf[1] = 0x00; - writeBuf[2] = 0x08; - writeBuf[3] = value | 0x40; - - XboxCommand(controller, writeBuf, 4); -} - -void XBOXRECV::setLedOn(LEDEnum led, uint8_t controller) { - if(led == OFF) - setLedRaw(0, controller); - else if(led != ALL) // All LEDs can't be on a the same time - setLedRaw(pgm_read_byte(&XBOX_LEDS[(uint8_t)led]) + 4, controller); -} - -void XBOXRECV::setLedBlink(LEDEnum led, uint8_t controller) { - setLedRaw(pgm_read_byte(&XBOX_LEDS[(uint8_t)led]), controller); -} - -void XBOXRECV::setLedMode(LEDModeEnum ledMode, uint8_t controller) { // This function is used to do some speciel LED stuff the controller supports - setLedRaw((uint8_t)ledMode, controller); -} - -/* PC runs this at interval of approx 2 seconds -Thanks to BusHound from Perisoft.net for the Windows USB Analysis output -Found by timstamp.co.uk - */ -void XBOXRECV::checkStatus() { - if(!bPollEnable) - return; - // Get controller info - writeBuf[0] = 0x08; - writeBuf[1] = 0x00; - writeBuf[2] = 0x0f; - writeBuf[3] = 0xc0; - for(uint8_t i = 0; i < 4; i++) { - XboxCommand(i, writeBuf, 4); - } - // Get battery status - writeBuf[0] = 0x00; - writeBuf[1] = 0x00; - writeBuf[2] = 0x00; - writeBuf[3] = 0x40; - for(uint8_t i = 0; i < 4; i++) { - if(Xbox360Connected[i]) - XboxCommand(i, writeBuf, 4); - } -} - -void XBOXRECV::setRumbleOn(uint8_t lValue, uint8_t rValue, uint8_t controller) { - writeBuf[0] = 0x00; - writeBuf[1] = 0x01; - writeBuf[2] = 0x0f; - writeBuf[3] = 0xc0; - writeBuf[4] = 0x00; - writeBuf[5] = lValue; // big weight - writeBuf[6] = rValue; // small weight - - XboxCommand(controller, writeBuf, 7); -} - -void XBOXRECV::onInit(uint8_t controller) { - if(pFuncOnInit) - pFuncOnInit(); // Call the user function - else { - LEDEnum led; - if(controller == 0) - led = LED1; - else if(controller == 1) - led = LED2; - else if(controller == 2) - led = LED3; - else - led = LED4; - setLedOn(led, controller); - } -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXRECV.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXRECV.h deleted file mode 100644 index 4f9214653c..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXRECV.h +++ /dev/null @@ -1,276 +0,0 @@ -/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. - - This software may be distributed and modified under the terms of the GNU - General Public License version 2 (GPL2) as published by the Free Software - Foundation and appearing in the file GPL2.TXT included in the packaging of - this file. Please note that GPL2 Section 2[b] requires that all works based - on this software must also be made publicly available under the terms of - the GPL2 ("Copyleft"). - - Contact information - ------------------- - - Kristian Lauszus, TKJ Electronics - Web : http://www.tkjelectronics.com - e-mail : kristianl@tkjelectronics.com - - getBatteryLevel and checkStatus functions made by timstamp.co.uk found using BusHound from Perisoft.net - */ - -#ifndef _xboxrecv_h_ -#define _xboxrecv_h_ - -#include "Usb.h" -#include "xboxEnums.h" - -/* Data Xbox 360 taken from descriptors */ -#define EP_MAXPKTSIZE 32 // max size for data via USB - -/* Names we give to the 9 Xbox360 pipes */ -#define XBOX_CONTROL_PIPE 0 -#define XBOX_INPUT_PIPE_1 1 -#define XBOX_OUTPUT_PIPE_1 2 -#define XBOX_INPUT_PIPE_2 3 -#define XBOX_OUTPUT_PIPE_2 4 -#define XBOX_INPUT_PIPE_3 5 -#define XBOX_OUTPUT_PIPE_3 6 -#define XBOX_INPUT_PIPE_4 7 -#define XBOX_OUTPUT_PIPE_4 8 - -// PID and VID of the different devices -#define XBOX_VID 0x045E // Microsoft Corporation -#define MADCATZ_VID 0x1BAD // For unofficial Mad Catz receivers -#define JOYTECH_VID 0x162E // For unofficial Joytech controllers - -#define XBOX_WIRELESS_RECEIVER_PID 0x0719 // Microsoft Wireless Gaming Receiver -#define XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID 0x0291 // Third party Wireless Gaming Receiver - -#define XBOX_MAX_ENDPOINTS 9 - -/** - * This class implements support for a Xbox Wireless receiver. - * - * Up to four controllers can connect to one receiver, if more is needed one can use a second receiver via the USBHub class. - */ -class XBOXRECV : public USBDeviceConfig { -public: - /** - * Constructor for the XBOXRECV class. - * @param pUsb Pointer to USB class instance. - */ - XBOXRECV(USB *pUsb); - - /** @name USBDeviceConfig implementation */ - /** - * Address assignment and basic initilization is done here. - * @param parent Hub number. - * @param port Port number on the hub. - * @param lowspeed Speed of the device. - * @return 0 on success. - */ - uint8_t ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed); - /** - * Initialize the Xbox wireless receiver. - * @param parent Hub number. - * @param port Port number on the hub. - * @param lowspeed Speed of the device. - * @return 0 on success. - */ - uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); - /** - * Release the USB device. - * @return 0 on success. - */ - uint8_t Release(); - /** - * Poll the USB Input endpoins and run the state machines. - * @return 0 on success. - */ - uint8_t Poll(); - - /** - * Get the device address. - * @return The device address. - */ - virtual uint8_t GetAddress() { - return bAddress; - }; - - /** - * Used to check if the controller has been initialized. - * @return True if it's ready. - */ - virtual bool isReady() { - return bPollEnable; - }; - - /** - * Used by the USB core to check what this driver support. - * @param vid The device's VID. - * @param pid The device's PID. - * @return Returns true if the device's VID and PID matches this driver. - */ - virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) { - return ((vid == XBOX_VID || vid == MADCATZ_VID || vid == JOYTECH_VID) && (pid == XBOX_WIRELESS_RECEIVER_PID || pid == XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID)); - }; - /**@}*/ - - /** @name Xbox Controller functions */ - /** - * getButtonPress(uint8_t controller, ButtonEnum b) will return true as long as the button is held down. - * - * While getButtonClick(uint8_t controller, ButtonEnum b) will only return it once. - * - * So you instance if you need to increase a variable once you would use getButtonClick(uint8_t controller, ButtonEnum b), - * but if you need to drive a robot forward you would use getButtonPress(uint8_t controller, ButtonEnum b). - * @param b ::ButtonEnum to read. - * @param controller The controller to read from. Default to 0. - * @return getButtonClick(uint8_t controller, ButtonEnum b) will return a bool, while getButtonPress(uint8_t controller, ButtonEnum b) will return a byte if reading ::L2 or ::R2. - */ - uint8_t getButtonPress(ButtonEnum b, uint8_t controller = 0); - bool getButtonClick(ButtonEnum b, uint8_t controller = 0); - /**@}*/ - - /** @name Xbox Controller functions */ - /** - * Return the analog value from the joysticks on the controller. - * @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY. - * @param controller The controller to read from. Default to 0. - * @return Returns a signed 16-bit integer. - */ - int16_t getAnalogHat(AnalogHatEnum a, uint8_t controller = 0); - - /** - * Used to disconnect any of the controllers. - * @param controller The controller to disconnect. Default to 0. - */ - void disconnect(uint8_t controller = 0); - - /** - * Turn rumble off and all the LEDs on the specific controller. - * @param controller The controller to write to. Default to 0. - */ - void setAllOff(uint8_t controller = 0) { - setRumbleOn(0, 0, controller); - setLedOff(controller); - }; - - /** - * Turn rumble off the specific controller. - * @param controller The controller to write to. Default to 0. - */ - void setRumbleOff(uint8_t controller = 0) { - setRumbleOn(0, 0, controller); - }; - /** - * Turn rumble on. - * @param lValue Left motor (big weight) inside the controller. - * @param rValue Right motor (small weight) inside the controller. - * @param controller The controller to write to. Default to 0. - */ - void setRumbleOn(uint8_t lValue, uint8_t rValue, uint8_t controller = 0); - /** - * Set LED value. Without using the ::LEDEnum or ::LEDModeEnum. - * @param value See: - * setLedOff(uint8_t controller), setLedOn(uint8_t controller, LED l), - * setLedBlink(uint8_t controller, LED l), and setLedMode(uint8_t controller, LEDMode lm). - * @param controller The controller to write to. Default to 0. - */ - void setLedRaw(uint8_t value, uint8_t controller = 0); - - /** - * Turn all LEDs off the specific controller. - * @param controller The controller to write to. Default to 0. - */ - void setLedOff(uint8_t controller = 0) { - setLedRaw(0, controller); - }; - /** - * Turn on a LED by using ::LEDEnum. - * @param l ::OFF, ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller. - * @param controller The controller to write to. Default to 0. - */ - void setLedOn(LEDEnum l, uint8_t controller = 0); - /** - * Turn on a LED by using ::LEDEnum. - * @param l ::ALL, ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller. - * @param controller The controller to write to. Default to 0. - */ - void setLedBlink(LEDEnum l, uint8_t controller = 0); - /** - * Used to set special LED modes supported by the Xbox controller. - * @param lm See ::LEDModeEnum. - * @param controller The controller to write to. Default to 0. - */ - void setLedMode(LEDModeEnum lm, uint8_t controller = 0); - /** - * Used to get the battery level from the controller. - * @param controller The controller to read from. Default to 0. - * @return Returns the battery level as an integer in the range of 0-3. - */ - uint8_t getBatteryLevel(uint8_t controller = 0); - /** - * Used to check if a button has changed. - * @param controller The controller to read from. Default to 0. - * @return True if a button has changed. - */ - bool buttonChanged(uint8_t controller = 0); - - /** - * Used to call your own function when the controller is successfully initialized. - * @param funcOnInit Function to call. - */ - void attachOnInit(void (*funcOnInit)(void)) { - pFuncOnInit = funcOnInit; - }; - /**@}*/ - - /** True if a wireless receiver is connected. */ - bool XboxReceiverConnected; - /** Variable used to indicate if the XBOX 360 controller is successfully connected. */ - uint8_t Xbox360Connected[4]; - -protected: - /** Pointer to USB class instance. */ - USB *pUsb; - /** Device address. */ - uint8_t bAddress; - /** Endpoint info structure. */ - EpInfo epInfo[XBOX_MAX_ENDPOINTS]; - -private: - /** - * Called when the controller is successfully initialized. - * Use attachOnInit(void (*funcOnInit)(void)) to call your own function. - * This is useful for instance if you want to set the LEDs in a specific way. - * @param controller The initialized controller. - */ - void onInit(uint8_t controller); - void (*pFuncOnInit)(void); // Pointer to function called in onInit() - - bool bPollEnable; - - /* Variables to store the buttons */ - uint32_t ButtonState[4]; - uint32_t OldButtonState[4]; - uint16_t ButtonClickState[4]; - int16_t hatValue[4][4]; - uint16_t controllerStatus[4]; - bool buttonStateChanged[4]; // True if a button has changed - - bool L2Clicked[4]; // These buttons are analog, so we use we use these bools to check if they where clicked or not - bool R2Clicked[4]; - - uint32_t checkStatusTimer; // Timing for checkStatus() signals - - uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data - uint8_t writeBuf[7]; // General purpose buffer for output data - - void readReport(uint8_t controller); // read incoming data - void printReport(uint8_t controller, uint8_t nBytes); // print incoming date - Uncomment for debugging - - /* Private commands */ - void XboxCommand(uint8_t controller, uint8_t* data, uint16_t nbytes); - void checkStatus(); -}; -#endif diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXUSB.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXUSB.cpp deleted file mode 100644 index ddece21b45..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXUSB.cpp +++ /dev/null @@ -1,361 +0,0 @@ -/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. - - This software may be distributed and modified under the terms of the GNU - General Public License version 2 (GPL2) as published by the Free Software - Foundation and appearing in the file GPL2.TXT included in the packaging of - this file. Please note that GPL2 Section 2[b] requires that all works based - on this software must also be made publicly available under the terms of - the GPL2 ("Copyleft"). - - Contact information - ------------------- - - Kristian Lauszus, TKJ Electronics - Web : http://www.tkjelectronics.com - e-mail : kristianl@tkjelectronics.com - */ - -#include "XBOXUSB.h" -// To enable serial debugging see "settings.h" -//#define EXTRADEBUG // Uncomment to get even more debugging data -//#define PRINTREPORT // Uncomment to print the report send by the Xbox 360 Controller - -XBOXUSB::XBOXUSB(USB *p) : -pUsb(p), // pointer to USB class instance - mandatory -bAddress(0), // device address - mandatory -bPollEnable(false) { // don't start polling before dongle is connected - for(uint8_t i = 0; i < XBOX_MAX_ENDPOINTS; i++) { - epInfo[i].epAddr = 0; - epInfo[i].maxPktSize = (i) ? 0 : 8; - epInfo[i].epAttribs = 0; - epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; - } - - if(pUsb) // register in USB subsystem - pUsb->RegisterDeviceClass(this); //set devConfig[] entry -} - -uint8_t XBOXUSB::Init(uint8_t parent, uint8_t port, bool lowspeed) { - uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)]; - USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); - uint8_t rcode; - UsbDevice *p = NULL; - EpInfo *oldep_ptr = NULL; - uint16_t PID; - uint16_t VID; - - // get memory address of USB device address pool - AddressPool &addrPool = pUsb->GetAddressPool(); -#ifdef EXTRADEBUG - Notify(PSTR("\r\nXBOXUSB Init"), 0x80); -#endif - // check if address has already been assigned to an instance - if(bAddress) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nAddress in use"), 0x80); -#endif - return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; - } - - // Get pointer to pseudo device with address 0 assigned - p = addrPool.GetUsbDevicePtr(0); - - if(!p) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nAddress not found"), 0x80); -#endif - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - } - - if(!p->epinfo) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nepinfo is null"), 0x80); -#endif - return USB_ERROR_EPINFO_IS_NULL; - } - - // Save old pointer to EP_RECORD of address 0 - oldep_ptr = p->epinfo; - - // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence - p->epinfo = epInfo; - - p->lowspeed = lowspeed; - - // Get device descriptor - rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data - // Restore p->epinfo - p->epinfo = oldep_ptr; - - if(rcode) - goto FailGetDevDescr; - - VID = udd->idVendor; - PID = udd->idProduct; - - if(VID != XBOX_VID && VID != MADCATZ_VID && VID != JOYTECH_VID && VID != GAMESTOP_VID) // Check VID - goto FailUnknownDevice; - if(PID == XBOX_WIRELESS_PID) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nYou have plugged in a wireless Xbox 360 controller - it doesn't support USB communication"), 0x80); -#endif - goto FailUnknownDevice; - } else if(PID == XBOX_WIRELESS_RECEIVER_PID || PID == XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID) { -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nThis library only supports Xbox 360 controllers via USB"), 0x80); -#endif - goto FailUnknownDevice; - } else if(PID != XBOX_WIRED_PID && PID != MADCATZ_WIRED_PID && PID != GAMESTOP_WIRED_PID && PID != AFTERGLOW_WIRED_PID && PID != JOYTECH_WIRED_PID) // Check PID - goto FailUnknownDevice; - - // Allocate new address according to device class - bAddress = addrPool.AllocAddress(parent, false, port); - - if(!bAddress) - return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; - - // Extract Max Packet Size from device descriptor - epInfo[0].maxPktSize = udd->bMaxPacketSize0; - - // Assign new address to the device - rcode = pUsb->setAddr(0, 0, bAddress); - if(rcode) { - p->lowspeed = false; - addrPool.FreeAddress(bAddress); - bAddress = 0; -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nsetAddr: "), 0x80); - D_PrintHex (rcode, 0x80); -#endif - return rcode; - } -#ifdef EXTRADEBUG - Notify(PSTR("\r\nAddr: "), 0x80); - D_PrintHex (bAddress, 0x80); -#endif - //delay(300); // Spec says you should wait at least 200ms - - p->lowspeed = false; - - //get pointer to assigned address record - p = addrPool.GetUsbDevicePtr(bAddress); - if(!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - p->lowspeed = lowspeed; - - // Assign epInfo to epinfo pointer - only EP0 is known - rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); - if(rcode) - goto FailSetDevTblEntry; - - /* The application will work in reduced host mode, so we can save program and data - memory space. After verifying the VID we will use known values for the - configuration values for device, interface, endpoints and HID for the XBOX360 Controllers */ - - /* Initialize data structures for endpoints of device */ - epInfo[ XBOX_INPUT_PIPE ].epAddr = 0x01; // XBOX 360 report endpoint - epInfo[ XBOX_INPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; - epInfo[ XBOX_INPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints - epInfo[ XBOX_INPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; - epInfo[ XBOX_INPUT_PIPE ].bmSndToggle = 0; - epInfo[ XBOX_INPUT_PIPE ].bmRcvToggle = 0; - epInfo[ XBOX_OUTPUT_PIPE ].epAddr = 0x02; // XBOX 360 output endpoint - epInfo[ XBOX_OUTPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; - epInfo[ XBOX_OUTPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints - epInfo[ XBOX_OUTPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; - epInfo[ XBOX_OUTPUT_PIPE ].bmSndToggle = 0; - epInfo[ XBOX_OUTPUT_PIPE ].bmRcvToggle = 0; - - rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo); - if(rcode) - goto FailSetDevTblEntry; - - delay(200); // Give time for address change - - rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1); - if(rcode) - goto FailSetConfDescr; - -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nXbox 360 Controller Connected\r\n"), 0x80); -#endif - onInit(); - Xbox360Connected = true; - bPollEnable = true; - return 0; // Successful configuration - - /* Diagnostic messages */ -FailGetDevDescr: -#ifdef DEBUG_USB_HOST - NotifyFailGetDevDescr(); - goto Fail; -#endif - -FailSetDevTblEntry: -#ifdef DEBUG_USB_HOST - NotifyFailSetDevTblEntry(); - goto Fail; -#endif - -FailSetConfDescr: -#ifdef DEBUG_USB_HOST - NotifyFailSetConfDescr(); -#endif - goto Fail; - -FailUnknownDevice: -#ifdef DEBUG_USB_HOST - NotifyFailUnknownDevice(VID, PID); -#endif - rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - -Fail: -#ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nXbox 360 Init Failed, error code: "), 0x80); - NotifyFail(rcode); -#endif - Release(); - return rcode; -} - -/* Performs a cleanup after failed Init() attempt */ -uint8_t XBOXUSB::Release() { - Xbox360Connected = false; - pUsb->GetAddressPool().FreeAddress(bAddress); - bAddress = 0; - bPollEnable = false; - return 0; -} - -uint8_t XBOXUSB::Poll() { - if(!bPollEnable) - return 0; - uint16_t BUFFER_SIZE = EP_MAXPKTSIZE; - pUsb->inTransfer(bAddress, epInfo[ XBOX_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf); // input on endpoint 1 - readReport(); -#ifdef PRINTREPORT - printReport(); // Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller -#endif - return 0; -} - -void XBOXUSB::readReport() { - if(readBuf == NULL) - return; - if(readBuf[0] != 0x00 || readBuf[1] != 0x14) { // Check if it's the correct report - the controller also sends different status reports - return; - } - - ButtonState = (uint32_t)(readBuf[5] | ((uint16_t)readBuf[4] << 8) | ((uint32_t)readBuf[3] << 16) | ((uint32_t)readBuf[2] << 24)); - - hatValue[LeftHatX] = (int16_t)(((uint16_t)readBuf[7] << 8) | readBuf[6]); - hatValue[LeftHatY] = (int16_t)(((uint16_t)readBuf[9] << 8) | readBuf[8]); - hatValue[RightHatX] = (int16_t)(((uint16_t)readBuf[11] << 8) | readBuf[10]); - hatValue[RightHatY] = (int16_t)(((uint16_t)readBuf[13] << 8) | readBuf[12]); - - //Notify(PSTR("\r\nButtonState"), 0x80); - //PrintHex(ButtonState, 0x80); - - if(ButtonState != OldButtonState) { - ButtonClickState = (ButtonState >> 16) & ((~OldButtonState) >> 16); // Update click state variable, but don't include the two trigger buttons L2 and R2 - if(((uint8_t)OldButtonState) == 0 && ((uint8_t)ButtonState) != 0) // The L2 and R2 buttons are special as they are analog buttons - R2Clicked = true; - if((uint8_t)(OldButtonState >> 8) == 0 && (uint8_t)(ButtonState >> 8) != 0) - L2Clicked = true; - OldButtonState = ButtonState; - } -} - -void XBOXUSB::printReport() { //Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller -#ifdef PRINTREPORT - if(readBuf == NULL) - return; - for(uint8_t i = 0; i < XBOX_REPORT_BUFFER_SIZE; i++) { - D_PrintHex (readBuf[i], 0x80); - Notify(PSTR(" "), 0x80); - } - Notify(PSTR("\r\n"), 0x80); -#endif -} - -uint8_t XBOXUSB::getButtonPress(ButtonEnum b) { - if(b == L2) // These are analog buttons - return (uint8_t)(ButtonState >> 8); - else if(b == R2) - return (uint8_t)ButtonState; - return (bool)(ButtonState & ((uint32_t)pgm_read_word(&XBOX_BUTTONS[(uint8_t)b]) << 16)); -} - -bool XBOXUSB::getButtonClick(ButtonEnum b) { - if(b == L2) { - if(L2Clicked) { - L2Clicked = false; - return true; - } - return false; - } else if(b == R2) { - if(R2Clicked) { - R2Clicked = false; - return true; - } - return false; - } - uint16_t button = pgm_read_word(&XBOX_BUTTONS[(uint8_t)b]); - bool click = (ButtonClickState & button); - ButtonClickState &= ~button; // clear "click" event - return click; -} - -int16_t XBOXUSB::getAnalogHat(AnalogHatEnum a) { - return hatValue[a]; -} - -/* Xbox Controller commands */ -void XBOXUSB::XboxCommand(uint8_t* data, uint16_t nbytes) { - //bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x00), Report Type (Output 0x02), interface (0x00), datalength, datalength, data) - pUsb->ctrlReq(bAddress, epInfo[XBOX_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x00, 0x02, 0x00, nbytes, nbytes, data, NULL); -} - -void XBOXUSB::setLedRaw(uint8_t value) { - writeBuf[0] = 0x01; - writeBuf[1] = 0x03; - writeBuf[2] = value; - - XboxCommand(writeBuf, 3); -} - -void XBOXUSB::setLedOn(LEDEnum led) { - if(led == OFF) - setLedRaw(0); - else if(led != ALL) // All LEDs can't be on a the same time - setLedRaw(pgm_read_byte(&XBOX_LEDS[(uint8_t)led]) + 4); -} - -void XBOXUSB::setLedBlink(LEDEnum led) { - setLedRaw(pgm_read_byte(&XBOX_LEDS[(uint8_t)led])); -} - -void XBOXUSB::setLedMode(LEDModeEnum ledMode) { // This function is used to do some special LED stuff the controller supports - setLedRaw((uint8_t)ledMode); -} - -void XBOXUSB::setRumbleOn(uint8_t lValue, uint8_t rValue) { - writeBuf[0] = 0x00; - writeBuf[1] = 0x08; - writeBuf[2] = 0x00; - writeBuf[3] = lValue; // big weight - writeBuf[4] = rValue; // small weight - writeBuf[5] = 0x00; - writeBuf[6] = 0x00; - writeBuf[7] = 0x00; - - XboxCommand(writeBuf, 8); -} - -void XBOXUSB::onInit() { - if(pFuncOnInit) - pFuncOnInit(); // Call the user function - else - setLedOn(LED1); -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXUSB.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXUSB.h deleted file mode 100644 index 1ab37851a7..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXUSB.h +++ /dev/null @@ -1,225 +0,0 @@ -/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. - - This software may be distributed and modified under the terms of the GNU - General Public License version 2 (GPL2) as published by the Free Software - Foundation and appearing in the file GPL2.TXT included in the packaging of - this file. Please note that GPL2 Section 2[b] requires that all works based - on this software must also be made publicly available under the terms of - the GPL2 ("Copyleft"). - - Contact information - ------------------- - - Kristian Lauszus, TKJ Electronics - Web : http://www.tkjelectronics.com - e-mail : kristianl@tkjelectronics.com - */ - -#ifndef _xboxusb_h_ -#define _xboxusb_h_ - -#include "Usb.h" -#include "hid.h" -#include "xboxEnums.h" - -/* Data Xbox 360 taken from descriptors */ -#define EP_MAXPKTSIZE 32 // max size for data via USB - -/* Names we give to the 3 Xbox360 pipes */ -#define XBOX_CONTROL_PIPE 0 -#define XBOX_INPUT_PIPE 1 -#define XBOX_OUTPUT_PIPE 2 - -// PID and VID of the different devices -#define XBOX_VID 0x045E // Microsoft Corporation -#define MADCATZ_VID 0x1BAD // For unofficial Mad Catz controllers -#define JOYTECH_VID 0x162E // For unofficial Joytech controllers -#define GAMESTOP_VID 0x0E6F // Gamestop controller - -#define XBOX_WIRED_PID 0x028E // Microsoft 360 Wired controller -#define XBOX_WIRELESS_PID 0x028F // Wireless controller only support charging -#define XBOX_WIRELESS_RECEIVER_PID 0x0719 // Microsoft Wireless Gaming Receiver -#define XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID 0x0291 // Third party Wireless Gaming Receiver -#define MADCATZ_WIRED_PID 0xF016 // Mad Catz wired controller -#define JOYTECH_WIRED_PID 0xBEEF // For Joytech wired controller -#define GAMESTOP_WIRED_PID 0x0401 // Gamestop wired controller -#define AFTERGLOW_WIRED_PID 0x0213 // Afterglow wired controller - it uses the same VID as a Gamestop controller - -#define XBOX_REPORT_BUFFER_SIZE 14 // Size of the input report buffer - -#define XBOX_MAX_ENDPOINTS 3 - -/** This class implements support for a Xbox wired controller via USB. */ -class XBOXUSB : public USBDeviceConfig { -public: - /** - * Constructor for the XBOXUSB class. - * @param pUsb Pointer to USB class instance. - */ - XBOXUSB(USB *pUsb); - - /** @name USBDeviceConfig implementation */ - /** - * Initialize the Xbox Controller. - * @param parent Hub number. - * @param port Port number on the hub. - * @param lowspeed Speed of the device. - * @return 0 on success. - */ - uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); - /** - * Release the USB device. - * @return 0 on success. - */ - uint8_t Release(); - /** - * Poll the USB Input endpoins and run the state machines. - * @return 0 on success. - */ - uint8_t Poll(); - - /** - * Get the device address. - * @return The device address. - */ - virtual uint8_t GetAddress() { - return bAddress; - }; - - /** - * Used to check if the controller has been initialized. - * @return True if it's ready. - */ - virtual bool isReady() { - return bPollEnable; - }; - - /** - * Used by the USB core to check what this driver support. - * @param vid The device's VID. - * @param pid The device's PID. - * @return Returns true if the device's VID and PID matches this driver. - */ - virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) { - return ((vid == XBOX_VID || vid == MADCATZ_VID || vid == JOYTECH_VID || vid == GAMESTOP_VID) && (pid == XBOX_WIRED_PID || pid == MADCATZ_WIRED_PID || pid == GAMESTOP_WIRED_PID || pid == AFTERGLOW_WIRED_PID || pid == JOYTECH_WIRED_PID)); - }; - /**@}*/ - - /** @name Xbox Controller functions */ - /** - * getButtonPress(ButtonEnum b) will return true as long as the button is held down. - * - * While getButtonClick(ButtonEnum b) will only return it once. - * - * So you instance if you need to increase a variable once you would use getButtonClick(ButtonEnum b), - * but if you need to drive a robot forward you would use getButtonPress(ButtonEnum b). - * @param b ::ButtonEnum to read. - * @return getButtonClick(ButtonEnum b) will return a bool, while getButtonPress(ButtonEnum b) will return a byte if reading ::L2 or ::R2. - */ - uint8_t getButtonPress(ButtonEnum b); - bool getButtonClick(ButtonEnum b); - /**@}*/ - - /** @name Xbox Controller functions */ - /** - * Return the analog value from the joysticks on the controller. - * @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY. - * @return Returns a signed 16-bit integer. - */ - int16_t getAnalogHat(AnalogHatEnum a); - - /** Turn rumble off and all the LEDs on the controller. */ - void setAllOff() { - setRumbleOn(0, 0); - setLedRaw(0); - }; - - /** Turn rumble off the controller. */ - void setRumbleOff() { - setRumbleOn(0, 0); - }; - /** - * Turn rumble on. - * @param lValue Left motor (big weight) inside the controller. - * @param rValue Right motor (small weight) inside the controller. - */ - void setRumbleOn(uint8_t lValue, uint8_t rValue); - /** - * Set LED value. Without using the ::LEDEnum or ::LEDModeEnum. - * @param value See: - * setLedOff(), setLedOn(LEDEnum l), - * setLedBlink(LEDEnum l), and setLedMode(LEDModeEnum lm). - */ - void setLedRaw(uint8_t value); - - /** Turn all LEDs off the controller. */ - void setLedOff() { - setLedRaw(0); - }; - /** - * Turn on a LED by using ::LEDEnum. - * @param l ::OFF, ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller. - */ - void setLedOn(LEDEnum l); - /** - * Turn on a LED by using ::LEDEnum. - * @param l ::ALL, ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller. - */ - void setLedBlink(LEDEnum l); - /** - * Used to set special LED modes supported by the Xbox controller. - * @param lm See ::LEDModeEnum. - */ - void setLedMode(LEDModeEnum lm); - - /** - * Used to call your own function when the controller is successfully initialized. - * @param funcOnInit Function to call. - */ - void attachOnInit(void (*funcOnInit)(void)) { - pFuncOnInit = funcOnInit; - }; - /**@}*/ - - /** True if a Xbox 360 controller is connected. */ - bool Xbox360Connected; - -protected: - /** Pointer to USB class instance. */ - USB *pUsb; - /** Device address. */ - uint8_t bAddress; - /** Endpoint info structure. */ - EpInfo epInfo[XBOX_MAX_ENDPOINTS]; - -private: - /** - * Called when the controller is successfully initialized. - * Use attachOnInit(void (*funcOnInit)(void)) to call your own function. - * This is useful for instance if you want to set the LEDs in a specific way. - */ - void onInit(); - void (*pFuncOnInit)(void); // Pointer to function called in onInit() - - bool bPollEnable; - - /* Variables to store the buttons */ - uint32_t ButtonState; - uint32_t OldButtonState; - uint16_t ButtonClickState; - int16_t hatValue[4]; - uint16_t controllerStatus; - - bool L2Clicked; // These buttons are analog, so we use we use these bools to check if they where clicked or not - bool R2Clicked; - - uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data - uint8_t writeBuf[8]; // General purpose buffer for output data - - void readReport(); // read incoming data - void printReport(); // print incoming date - Uncomment for debugging - - /* Private commands */ - void XboxCommand(uint8_t* data, uint16_t nbytes); -}; -#endif diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/address.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/address.h deleted file mode 100644 index c3e1b3141f..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/address.h +++ /dev/null @@ -1,282 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ - -#if !defined(_usb_h_) || defined(__ADDRESS_H__) -#error "Never include address.h directly; include Usb.h instead" -#else -#define __ADDRESS_H__ - - - -/* NAK powers. To save space in endpoint data structure, amount of retries before giving up and returning 0x4 is stored in */ -/* bmNakPower as a power of 2. The actual nak_limit is then calculated as nak_limit = ( 2^bmNakPower - 1) */ -#define USB_NAK_MAX_POWER 15 //NAK binary order maximum value -#define USB_NAK_DEFAULT 14 //default 32K-1 NAKs before giving up -#define USB_NAK_NOWAIT 1 //Single NAK stops transfer -#define USB_NAK_NONAK 0 //Do not count NAKs, stop retrying after USB Timeout - -struct EpInfo { - uint8_t epAddr; // Endpoint address - uint8_t maxPktSize; // Maximum packet size - - union { - uint8_t epAttribs; - - struct { - uint8_t bmSndToggle : 1; // Send toggle, when zero bmSNDTOG0, bmSNDTOG1 otherwise - uint8_t bmRcvToggle : 1; // Send toggle, when zero bmRCVTOG0, bmRCVTOG1 otherwise - uint8_t bmNakPower : 6; // Binary order for NAK_LIMIT value - } __attribute__((packed)); - }; -} __attribute__((packed)); - -// 7 6 5 4 3 2 1 0 -// --------------------------------- -// | | H | P | P | P | A | A | A | -// --------------------------------- -// -// H - if 1 the address is a hub address -// P - parent hub address -// A - device address / port number in case of hub -// - -struct UsbDeviceAddress { - - union { - - struct { - uint8_t bmAddress : 3; // device address/port number - uint8_t bmParent : 3; // parent hub address - uint8_t bmHub : 1; // hub flag - uint8_t bmReserved : 1; // reserved, must be zero - } __attribute__((packed)); - uint8_t devAddress; - }; -} __attribute__((packed)); - -#define bmUSB_DEV_ADDR_ADDRESS 0x07 -#define bmUSB_DEV_ADDR_PARENT 0x38 -#define bmUSB_DEV_ADDR_HUB 0x40 - -struct UsbDevice { - EpInfo *epinfo; // endpoint info pointer - UsbDeviceAddress address; - uint8_t epcount; // number of endpoints - bool lowspeed; // indicates if a device is the low speed one - // uint8_t devclass; // device class -} __attribute__((packed)); - -class AddressPool { -public: - virtual UsbDevice* GetUsbDevicePtr(uint8_t addr) = 0; - virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0) = 0; - virtual void FreeAddress(uint8_t addr) = 0; -}; - -typedef void (*UsbDeviceHandleFunc)(UsbDevice *pdev); - -#define ADDR_ERROR_INVALID_INDEX 0xFF -#define ADDR_ERROR_INVALID_ADDRESS 0xFF - -template -class AddressPoolImpl : public AddressPool { - EpInfo dev0ep; //Endpoint data structure used during enumeration for uninitialized device - - uint8_t hubCounter; // hub counter is kept - // in order to avoid hub address duplication - - UsbDevice thePool[MAX_DEVICES_ALLOWED]; - - // Initializes address pool entry - - void InitEntry(uint8_t index) { - thePool[index].address.devAddress = 0; - thePool[index].epcount = 1; - thePool[index].lowspeed = 0; - thePool[index].epinfo = &dev0ep; - }; - - // Returns thePool index for a given address - - uint8_t FindAddressIndex(uint8_t address = 0) { - for(uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) { - if(thePool[i].address.devAddress == address) - return i; - } - return 0; - }; - - // Returns thePool child index for a given parent - - uint8_t FindChildIndex(UsbDeviceAddress addr, uint8_t start = 1) { - for(uint8_t i = (start < 1 || start >= MAX_DEVICES_ALLOWED) ? 1 : start; i < MAX_DEVICES_ALLOWED; i++) { - if(thePool[i].address.bmParent == addr.bmAddress) - return i; - } - return 0; - }; - - // Frees address entry specified by index parameter - - void FreeAddressByIndex(uint8_t index) { - // Zero field is reserved and should not be affected - if(index == 0) - return; - - UsbDeviceAddress uda = thePool[index].address; - // If a hub was switched off all port addresses should be freed - if(uda.bmHub == 1) { - for(uint8_t i = 1; (i = FindChildIndex(uda, i));) - FreeAddressByIndex(i); - - // If the hub had the last allocated address, hubCounter should be decremented - if(hubCounter == uda.bmAddress) - hubCounter--; - } - InitEntry(index); - } - - // Initializes the whole address pool at once - - void InitAllAddresses() { - for(uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) - InitEntry(i); - - hubCounter = 0; - }; - -public: - - AddressPoolImpl() : hubCounter(0) { - // Zero address is reserved - InitEntry(0); - - thePool[0].address.devAddress = 0; - thePool[0].epinfo = &dev0ep; - dev0ep.epAddr = 0; - dev0ep.maxPktSize = 8; - dev0ep.epAttribs = 0; //set DATA0/1 toggles to 0 - dev0ep.bmNakPower = USB_NAK_MAX_POWER; - - InitAllAddresses(); - }; - - // Returns a pointer to a specified address entry - - virtual UsbDevice* GetUsbDevicePtr(uint8_t addr) { - if(!addr) - return thePool; - - uint8_t index = FindAddressIndex(addr); - - return (!index) ? NULL : thePool + index; - }; - - // Performs an operation specified by pfunc for each addressed device - - void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) { - if(!pfunc) - return; - - for(uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) - if(thePool[i].address.devAddress) - pfunc(thePool + i); - }; - - // Allocates new address - - virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0) { - /* if (parent != 0 && port == 0) - USB_HOST_SERIAL.println("PRT:0"); */ - UsbDeviceAddress _parent; - _parent.devAddress = parent; - if(_parent.bmReserved || port > 7) - //if(parent > 127 || port > 7) - return 0; - - if(is_hub && hubCounter == 7) - return 0; - - // finds first empty address entry starting from one - uint8_t index = FindAddressIndex(0); - - if(!index) // if empty entry is not found - return 0; - - if(_parent.devAddress == 0) { - if(is_hub) { - thePool[index].address.devAddress = 0x41; - hubCounter++; - } else - thePool[index].address.devAddress = 1; - - return thePool[index].address.devAddress; - } - - UsbDeviceAddress addr; - addr.devAddress = 0; // Ensure all bits are zero - addr.bmParent = _parent.bmAddress; - if(is_hub) { - addr.bmHub = 1; - addr.bmAddress = ++hubCounter; - } else { - addr.bmHub = 0; - addr.bmAddress = port; - } - thePool[index].address = addr; - /* - USB_HOST_SERIAL.print("Addr:"); - USB_HOST_SERIAL.print(addr.bmHub, HEX); - USB_HOST_SERIAL.print("."); - USB_HOST_SERIAL.print(addr.bmParent, HEX); - USB_HOST_SERIAL.print("."); - USB_HOST_SERIAL.println(addr.bmAddress, HEX); - */ - return thePool[index].address.devAddress; - }; - - // Empties pool entry - - virtual void FreeAddress(uint8_t addr) { - // if the root hub is disconnected all the addresses should be initialized - if(addr == 0x41) { - InitAllAddresses(); - return; - } - uint8_t index = FindAddressIndex(addr); - FreeAddressByIndex(index); - }; - - // Returns number of hubs attached - // It can be rather helpfull to find out if there are hubs attached than getting the exact number of hubs. - //uint8_t GetNumHubs() - //{ - // return hubCounter; - //}; - //uint8_t GetNumDevices() - //{ - // uint8_t counter = 0; - - // for (uint8_t i=1; iRegisterDeviceClass(this); //set devConfig[] entry - } -} - -uint8_t ADK::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) { - return Init(parent, port, lowspeed); // Just call Init. Yes, really! -} - -/* Connection initialization of an Android phone */ -uint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed) { - uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)]; - USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); - uint8_t rcode; - uint8_t num_of_conf; // number of configurations - UsbDevice *p = NULL; - EpInfo *oldep_ptr = NULL; - - // get memory address of USB device address pool - AddressPool &addrPool = pUsb->GetAddressPool(); - - USBTRACE("\r\nADK Init"); - - // check if address has already been assigned to an instance - if(bAddress) { - USBTRACE("\r\nAddress in use"); - return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; - } - - // Get pointer to pseudo device with address 0 assigned - p = addrPool.GetUsbDevicePtr(0); - - if(!p) { - USBTRACE("\r\nAddress not found"); - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - } - - if(!p->epinfo) { - USBTRACE("epinfo is null\r\n"); - return USB_ERROR_EPINFO_IS_NULL; - } - - // Save old pointer to EP_RECORD of address 0 - oldep_ptr = p->epinfo; - - // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence - p->epinfo = epInfo; - - p->lowspeed = lowspeed; - - // Get device descriptor - rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); - - // Restore p->epinfo - p->epinfo = oldep_ptr; - - if(rcode) { - goto FailGetDevDescr; - } - - // Allocate new address according to device class - bAddress = addrPool.AllocAddress(parent, false, port); - - // Extract Max Packet Size from device descriptor - epInfo[0].maxPktSize = udd->bMaxPacketSize0; - - // Assign new address to the device - rcode = pUsb->setAddr(0, 0, bAddress); - if(rcode) { - p->lowspeed = false; - addrPool.FreeAddress(bAddress); - bAddress = 0; - //USBTRACE2("setAddr:",rcode); - return rcode; - }//if (rcode... - - //USBTRACE2("\r\nAddr:", bAddress); - // Spec says you should wait at least 200ms. - //delay(300); - - p->lowspeed = false; - - //get pointer to assigned address record - p = addrPool.GetUsbDevicePtr(bAddress); - if(!p) { - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - } - - p->lowspeed = lowspeed; - - // Assign epInfo to epinfo pointer - only EP0 is known - rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); - if(rcode) { - goto FailSetDevTblEntry; - } - - //check if ADK device is already in accessory mode; if yes, configure and exit - if(udd->idVendor == ADK_VID && - (udd->idProduct == ADK_PID || udd->idProduct == ADB_PID)) { - USBTRACE("\r\nAcc.mode device detected"); - /* go through configurations, find first bulk-IN, bulk-OUT EP, fill epInfo and quit */ - num_of_conf = udd->bNumConfigurations; - - //USBTRACE2("\r\nNC:",num_of_conf); - for(uint8_t i = 0; i < num_of_conf; i++) { - ConfigDescParser < 0, 0, 0, 0 > confDescrParser(this); - delay(1); - rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); -#if defined(XOOM) - //added by Jaylen Scott Vanorden - if(rcode) { - USBTRACE2("\r\nGot 1st bad code for config: ", rcode); - // Try once more - rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); - } -#endif - if(rcode) { - goto FailGetConfDescr; - } - if(bNumEP > 2) { - break; - } - } // for (uint8_t i=0; isetEpInfoEntry(bAddress, 3, epInfo); - if(rcode) { - goto FailSetDevTblEntry; - } - } - - // Set Configuration Value - rcode = pUsb->setConf(bAddress, 0, bConfNum); - if(rcode) { - goto FailSetConfDescr; - } - /* print endpoint structure */ - /* - USBTRACE("\r\nEndpoint Structure:"); - USBTRACE("\r\nEP0:"); - USBTRACE2("\r\nAddr: ", epInfo[0].epAddr); - USBTRACE2("\r\nMax.pkt.size: ", epInfo[0].maxPktSize); - USBTRACE2("\r\nAttr: ", epInfo[0].epAttribs); - USBTRACE("\r\nEpout:"); - USBTRACE2("\r\nAddr: ", epInfo[epDataOutIndex].epAddr); - USBTRACE2("\r\nMax.pkt.size: ", epInfo[epDataOutIndex].maxPktSize); - USBTRACE2("\r\nAttr: ", epInfo[epDataOutIndex].epAttribs); - USBTRACE("\r\nEpin:"); - USBTRACE2("\r\nAddr: ", epInfo[epDataInIndex].epAddr); - USBTRACE2("\r\nMax.pkt.size: ", epInfo[epDataInIndex].maxPktSize); - USBTRACE2("\r\nAttr: ", epInfo[epDataInIndex].epAttribs); - */ - - USBTRACE("\r\nConfiguration successful"); - ready = true; - return 0; //successful configuration - }//if( buf->idVendor == ADK_VID... - - //probe device - get accessory protocol revision - { - uint16_t adkproto = -1; - delay(1); - rcode = getProto((uint8_t*) & adkproto); -#if defined(XOOM) - //added by Jaylen Scott Vanorden - if(rcode) { - USBTRACE2("\r\nGot 1st bad code for proto: ", rcode); - // Try once more - rcode = getProto((uint8_t*) & adkproto); - } -#endif - if(rcode) { - goto FailGetProto; //init fails - } - USBTRACE2("\r\nADK protocol rev. ", adkproto); - } - - delay(100); - - //sending ID strings - sendStr(ACCESSORY_STRING_MANUFACTURER, manufacturer); - delay(10); - sendStr(ACCESSORY_STRING_MODEL, model); - delay(10); - sendStr(ACCESSORY_STRING_DESCRIPTION, description); - delay(10); - sendStr(ACCESSORY_STRING_VERSION, version); - delay(10); - sendStr(ACCESSORY_STRING_URI, uri); - delay(10); - sendStr(ACCESSORY_STRING_SERIAL, serial); - - delay(100); - - //switch to accessory mode - //the Android phone will reset - rcode = switchAcc(); - if(rcode) { - goto FailSwAcc; //init fails - } - rcode = USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET; - delay(100); // Give Android a chance to do its reset. This is a guess, and possibly could be lower. - goto SwAttempt; //switch to accessory mode attempted - - /* diagnostic messages */ -FailGetDevDescr: -#ifdef DEBUG_USB_HOST - NotifyFailGetDevDescr(rcode); - goto Fail; -#endif - -FailSetDevTblEntry: -#ifdef DEBUG_USB_HOST - NotifyFailSetDevTblEntry(rcode); - goto Fail; -#endif - -FailGetConfDescr: -#ifdef DEBUG_USB_HOST - NotifyFailGetConfDescr(rcode); - goto Fail; -#endif - -FailSetConfDescr: -#ifdef DEBUG_USB_HOST - NotifyFailSetConfDescr(rcode); - goto Fail; -#endif - -FailGetProto: -#ifdef DEBUG_USB_HOST - USBTRACE("\r\ngetProto:"); - goto Fail; -#endif - -FailSwAcc: -#ifdef DEBUG_USB_HOST - USBTRACE("\r\nswAcc:"); - goto Fail; -#endif - - //FailOnInit: - // USBTRACE("OnInit:"); - // goto Fail; - // -SwAttempt: -#ifdef DEBUG_USB_HOST - USBTRACE("\r\nAccessory mode switch attempt"); -Fail: -#endif - //USBTRACE2("\r\nADK Init Failed, error code: ", rcode); - //NotifyFail(rcode); - Release(); - return rcode; -} - -/* Extracts bulk-IN and bulk-OUT endpoint information from config descriptor */ -void ADK::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) { - //ErrorMessage(PSTR("Conf.Val"), conf); - //ErrorMessage(PSTR("Iface Num"), iface); - //ErrorMessage(PSTR("Alt.Set"), alt); - - //added by Yuuichi Akagawa - if(bNumEP == 3) { - return; - } - - bConfNum = conf; - - if((pep->bmAttributes & 0x02) == 2) { - uint8_t index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex; - // Fill in the endpoint info structure - epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); - epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; - - bNumEP++; - - //PrintEndpointDescriptor(pep); - } -} - -/* Performs a cleanup after failed Init() attempt */ -uint8_t ADK::Release() { - pUsb->GetAddressPool().FreeAddress(bAddress); - - bNumEP = 1; //must have to be reset to 1 - - bAddress = 0; - ready = false; - return 0; -} - -uint8_t ADK::RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr) { - //USBTRACE2("\r\nAddr: ", bAddress ); - //USBTRACE2("\r\nEP: ",epInfo[epDataInIndex].epAddr); - return pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr); -} - -uint8_t ADK::SndData(uint16_t nbytes, uint8_t *dataptr) { - return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, nbytes, dataptr); -} - -void ADK::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) { - Notify(PSTR("Endpoint descriptor:"), 0x80); - Notify(PSTR("\r\nLength:\t\t"), 0x80); - D_PrintHex (ep_ptr->bLength, 0x80); - Notify(PSTR("\r\nType:\t\t"), 0x80); - D_PrintHex (ep_ptr->bDescriptorType, 0x80); - Notify(PSTR("\r\nAddress:\t"), 0x80); - D_PrintHex (ep_ptr->bEndpointAddress, 0x80); - Notify(PSTR("\r\nAttributes:\t"), 0x80); - D_PrintHex (ep_ptr->bmAttributes, 0x80); - Notify(PSTR("\r\nMaxPktSize:\t"), 0x80); - D_PrintHex (ep_ptr->wMaxPacketSize, 0x80); - Notify(PSTR("\r\nPoll Intrv:\t"), 0x80); - D_PrintHex (ep_ptr->bInterval, 0x80); - Notify(PSTR("\r\n"), 0x80); -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/adk.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/adk.h deleted file mode 100644 index 4a2920b88a..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/adk.h +++ /dev/null @@ -1,140 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ - -/* Google ADK interface support header */ - -#if !defined(_ADK_H_) -#define _ADK_H_ - -#include "Usb.h" - -#define ADK_VID 0x18D1 -#define ADK_PID 0x2D00 -#define ADB_PID 0x2D01 - -#define XOOM //enables repeating getProto() and getConf() attempts -//necessary for slow devices such as Motorola XOOM -//defined by default, can be commented out to save memory - -/* requests */ - -#define ADK_GETPROTO 51 //check USB accessory protocol version -#define ADK_SENDSTR 52 //send identifying string -#define ADK_ACCSTART 53 //start device in accessory mode - -#define bmREQ_ADK_GET USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_VENDOR|USB_SETUP_RECIPIENT_DEVICE -#define bmREQ_ADK_SEND USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_VENDOR|USB_SETUP_RECIPIENT_DEVICE - -#define ACCESSORY_STRING_MANUFACTURER 0 -#define ACCESSORY_STRING_MODEL 1 -#define ACCESSORY_STRING_DESCRIPTION 2 -#define ACCESSORY_STRING_VERSION 3 -#define ACCESSORY_STRING_URI 4 -#define ACCESSORY_STRING_SERIAL 5 - -#define ADK_MAX_ENDPOINTS 3 //endpoint 0, bulk_IN, bulk_OUT - -class ADK; - -class ADK : public USBDeviceConfig, public UsbConfigXtracter { -private: - /* ID strings */ - const char* manufacturer; - const char* model; - const char* description; - const char* version; - const char* uri; - const char* serial; - - /* ADK proprietary requests */ - uint8_t getProto(uint8_t* adkproto); - uint8_t sendStr(uint8_t index, const char* str); - uint8_t switchAcc(void); - -protected: - static const uint8_t epDataInIndex; // DataIn endpoint index - static const uint8_t epDataOutIndex; // DataOUT endpoint index - - /* mandatory members */ - USB *pUsb; - uint8_t bAddress; - uint8_t bConfNum; // configuration number - - uint8_t bNumEP; // total number of EP in the configuration - bool ready; - - /* Endpoint data structure */ - EpInfo epInfo[ADK_MAX_ENDPOINTS]; - - void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); - -public: - ADK(USB *pUsb, const char* manufacturer, - const char* model, - const char* description, - const char* version, - const char* uri, - const char* serial); - - // Methods for receiving and sending data - uint8_t RcvData(uint16_t *nbytesptr, uint8_t *dataptr); - uint8_t SndData(uint16_t nbytes, uint8_t *dataptr); - - - // USBDeviceConfig implementation - uint8_t ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed); - uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); - uint8_t Release(); - - virtual uint8_t Poll() { - return 0; - }; - - virtual uint8_t GetAddress() { - return bAddress; - }; - - virtual bool isReady() { - return ready; - }; - - virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) { - return (vid == ADK_VID && (pid == ADK_PID || pid == ADB_PID)); - }; - - //UsbConfigXtracter implementation - void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); -}; //class ADK : public USBDeviceConfig ... - -/* get ADK protocol version */ - -/* returns 2 bytes in *adkproto */ -inline uint8_t ADK::getProto(uint8_t* adkproto) { - return ( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_GET, ADK_GETPROTO, 0, 0, 0, 2, 2, adkproto, NULL)); -} - -/* send ADK string */ -inline uint8_t ADK::sendStr(uint8_t index, const char* str) { - return ( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_SEND, ADK_SENDSTR, 0, 0, index, strlen(str) + 1, strlen(str) + 1, (uint8_t*)str, NULL)); -} - -/* switch to accessory mode */ -inline uint8_t ADK::switchAcc(void) { - return ( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_SEND, ADK_ACCSTART, 0, 0, 0, 0, 0, NULL, NULL)); -} - -#endif // _ADK_H_ diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/avrpins.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/avrpins.h deleted file mode 100644 index 4e60e3a229..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/avrpins.h +++ /dev/null @@ -1,1130 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ - -/* derived from Konstantin Chizhov's AVR port templates */ - -#if !defined(_usb_h_) || defined(_avrpins_h_) -#error "Never include avrpins.h directly; include Usb.h instead" -#else -#define _avrpins_h_ - -#if defined(__AVR__) - -// pointers are 16 bits on AVR -#define pgm_read_pointer(p) pgm_read_word(p) - -// Support for these boards needs to be manually activated in settings.h or in a makefile -#if !defined(BOARD_MEGA_ADK) && defined(__AVR_ATmega2560__) && (USE_UHS_MEGA_ADK || defined(ARDUINO_AVR_ADK)) -#define BOARD_MEGA_ADK -#elif !defined(BOARD_BLACK_WIDDOW) && USE_UHS_BLACK_WIDDOW -#define BOARD_BLACK_WIDDOW -#endif - -#ifdef PORTA -#define USE_PORTA -#endif -#ifdef PORTB -#define USE_PORTB -#endif -#ifdef PORTC -#define USE_PORTC -#endif -#ifdef PORTD -#define USE_PORTD -#endif -#ifdef PORTE -#define USE_PORTE -#endif -#ifdef PORTF -#define USE_PORTF -#endif -#ifdef PORTG -#define USE_PORTG -#endif -#ifdef PORTH -#define USE_PORTH -#endif -#ifdef PORTJ -#define USE_PORTJ -#endif -#ifdef PORTK -#define USE_PORTK -#endif -#ifdef PORTL -#define USE_PORTL -#endif -#ifdef PORTQ -#define USE_PORTQ -#endif -#ifdef PORTR -#define USE_PORTR -#endif - -#ifdef TCCR0A -#define USE_TCCR0A -#endif -#ifdef TCCR1A -#define USE_TCCR1A -#endif -#ifdef TCCR2A -#define USE_TCCR2A -#endif - -//Port definitions for AtTiny, AtMega families. - -#define MAKE_PORT(portName, ddrName, pinName, className, ID) \ - class className{\ - public:\ - typedef uint8_t DataT;\ - public:\ - static void Write(DataT value){portName = value;}\ - static void ClearAndSet(DataT clearMask, DataT value){portName = (portName & ~clearMask) | value;}\ - static DataT Read(){return portName;}\ - static void DirWrite(DataT value){ddrName = value;}\ - static DataT DirRead(){return ddrName;}\ - static void Set(DataT value){portName |= value;}\ - static void Clear(DataT value){portName &= ~value;}\ - static void Toggle(DataT value){portName ^= value;}\ - static void DirSet(DataT value){ddrName |= value;}\ - static void DirClear(DataT value){ddrName &= ~value;}\ - static void DirToggle(DataT value){ddrName ^= value;}\ - static DataT PinRead(){return pinName;}\ - enum{Id = ID};\ - enum{Width=sizeof(DataT)*8};\ - }; - -// TCCR registers to set/clear Arduino PWM -#define MAKE_TCCR(TccrName, className) \ - class className{\ - public:\ - typedef uint8_t DataT;\ - public:\ - static void Write(DataT value){TccrName = value;}\ - static void ClearAndSet(DataT clearMask, DataT value){TccrName = (TccrName & ~clearMask) | value;}\ - static DataT Read(){return TccrName;}\ - static void Set(DataT value){TccrName |= value;}\ - static void Clear(DataT value){TccrName &= ~value;}\ - static void Toggle(DataT value){TccrName ^= value;}\ - enum{Width=sizeof(DataT)*8};\ - }; - -#ifdef USE_PORTA - -MAKE_PORT(PORTA, DDRA, PINA, Porta, 'A') -#endif -#ifdef USE_PORTB -MAKE_PORT(PORTB, DDRB, PINB, Portb, 'B') -#endif -#ifdef USE_PORTC -MAKE_PORT(PORTC, DDRC, PINC, Portc, 'C') -#endif -#ifdef USE_PORTD -MAKE_PORT(PORTD, DDRD, PIND, Portd, 'D') -#endif -#ifdef USE_PORTE -MAKE_PORT(PORTE, DDRE, PINE, Porte, 'E') -#endif -#ifdef USE_PORTF -MAKE_PORT(PORTF, DDRF, PINF, Portf, 'F') -#endif -#ifdef USE_PORTG -MAKE_PORT(PORTG, DDRG, PING, Portg, 'G') -#endif -#ifdef USE_PORTH -MAKE_PORT(PORTH, DDRH, PINH, Porth, 'H') -#endif -#ifdef USE_PORTJ -MAKE_PORT(PORTJ, DDRJ, PINJ, Portj, 'J') -#endif -#ifdef USE_PORTK -MAKE_PORT(PORTK, DDRK, PINK, Portk, 'K') -#endif -#ifdef USE_PORTL -MAKE_PORT(PORTL, DDRL, PINL, Portl, 'L') -#endif -#ifdef USE_PORTQ -MAKE_PORT(PORTQ, DDRQ, PINQ, Portq, 'Q') -#endif -#ifdef USE_PORTR -MAKE_PORT(PORTR, DDRR, PINR, Portr, 'R') -#endif - -#ifdef USE_TCCR0A -MAKE_TCCR(TCCR0A, Tccr0a) -#endif -#ifdef USE_TCCR1A -MAKE_TCCR(TCCR1A, Tccr1a) -#endif -#ifdef USE_TCCR2A -MAKE_TCCR(TCCR2A, Tccr2a) -#endif - -// this class represents one pin in a IO port. -// It is fully static. -template -class TPin { - // BOOST_STATIC_ASSERT(PIN < PORT::Width); -public: - typedef PORT Port; - - enum { - Number = PIN - }; - - static void Set() { - PORT::Set(1 << PIN); - } - - static void Set(uint8_t val) { - if(val) - Set(); - else Clear(); - } - - static void SetDir(uint8_t val) { - if(val) - SetDirWrite(); - else SetDirRead(); - } - - static void Clear() { - PORT::Clear(1 << PIN); - } - - static void Toggle() { - PORT::Toggle(1 << PIN); - } - - static void SetDirRead() { - PORT::DirClear(1 << PIN); - } - - static void SetDirWrite() { - PORT::DirSet(1 << PIN); - } - - static uint8_t IsSet() { - return PORT::PinRead() & (uint8_t)(1 << PIN); - } - - static void WaiteForSet() { - while(IsSet() == 0) { - } - } - - static void WaiteForClear() { - while(IsSet()) { - } - } -}; //class TPin... - -// this class represents one bit in TCCR port. -// used to set/clear TCCRx bits -// It is fully static. - -template -class TCom { - // BOOST_STATIC_ASSERT(PIN < PORT::Width); -public: - typedef TCCR Tccr; - - enum { - Com = COM - }; - - static void Set() { - TCCR::Set(1 << COM); - } - - static void Clear() { - TCCR::Clear(1 << COM); - } - - static void Toggle() { - TCCR::Toggle(1 << COM); - } -}; //class TCom... - -//Short pin definitions -#ifdef USE_PORTA -typedef TPin Pa0; -typedef TPin Pa1; -typedef TPin Pa2; -typedef TPin Pa3; -typedef TPin Pa4; -typedef TPin Pa5; -typedef TPin Pa6; -typedef TPin Pa7; -#endif - -#ifdef USE_PORTB -typedef TPin Pb0; -typedef TPin Pb1; -typedef TPin Pb2; -typedef TPin Pb3; -typedef TPin Pb4; -typedef TPin Pb5; -typedef TPin Pb6; -typedef TPin Pb7; -#endif - -#ifdef USE_PORTC -typedef TPin Pc0; -typedef TPin Pc1; -typedef TPin Pc2; -typedef TPin Pc3; -typedef TPin Pc4; -typedef TPin Pc5; -typedef TPin Pc6; -typedef TPin Pc7; -#endif - -#ifdef USE_PORTD -typedef TPin Pd0; -typedef TPin Pd1; -typedef TPin Pd2; -typedef TPin Pd3; -typedef TPin Pd4; -typedef TPin Pd5; -typedef TPin Pd6; -typedef TPin Pd7; -#endif - -#ifdef USE_PORTE -typedef TPin Pe0; -typedef TPin Pe1; -typedef TPin Pe2; -typedef TPin Pe3; -typedef TPin Pe4; -typedef TPin Pe5; -typedef TPin Pe6; -typedef TPin Pe7; -#endif - -#ifdef USE_PORTF -typedef TPin Pf0; -typedef TPin Pf1; -typedef TPin Pf2; -typedef TPin Pf3; -typedef TPin Pf4; -typedef TPin Pf5; -typedef TPin Pf6; -typedef TPin Pf7; -#endif - -#ifdef USE_PORTG -typedef TPin Pg0; -typedef TPin Pg1; -typedef TPin Pg2; -typedef TPin Pg3; -typedef TPin Pg4; -typedef TPin Pg5; -typedef TPin Pg6; -typedef TPin Pg7; -#endif - -#ifdef USE_PORTH -typedef TPin Ph0; -typedef TPin Ph1; -typedef TPin Ph2; -typedef TPin Ph3; -typedef TPin Ph4; -typedef TPin Ph5; -typedef TPin Ph6; -typedef TPin Ph7; -#endif - -#ifdef USE_PORTJ -typedef TPin Pj0; -typedef TPin Pj1; -typedef TPin Pj2; -typedef TPin Pj3; -typedef TPin Pj4; -typedef TPin Pj5; -typedef TPin Pj6; -typedef TPin Pj7; -#endif - -#ifdef USE_PORTK -typedef TPin Pk0; -typedef TPin Pk1; -typedef TPin Pk2; -typedef TPin Pk3; -typedef TPin Pk4; -typedef TPin Pk5; -typedef TPin Pk6; -typedef TPin Pk7; -#endif - -#ifdef USE_PORTL -typedef TPin Pl0; -typedef TPin Pl1; -typedef TPin Pl2; -typedef TPin Pl3; -typedef TPin Pl4; -typedef TPin Pl5; -typedef TPin Pl6; -typedef TPin Pl7; -#endif - -#ifdef USE_PORTQ -typedef TPin Pq0; -typedef TPin Pq1; -typedef TPin Pq2; -typedef TPin Pq3; -typedef TPin Pq4; -typedef TPin Pq5; -typedef TPin Pq6; -typedef TPin Pq7; -#endif - -#ifdef USE_PORTR -typedef TPin Pr0; -typedef TPin Pr1; -typedef TPin Pr2; -typedef TPin Pr3; -typedef TPin Pr4; -typedef TPin Pr5; -typedef TPin Pr6; -typedef TPin Pr7; -#endif - -#ifdef USE_TCCR0A -typedef TCom Tc0a; //P6 -typedef TCom Tc0b; //P5 -#endif - -#ifdef USE_TCCR1A -typedef TCom Tc1a; //P9 -typedef TCom Tc1b; //P10 -#endif - -#ifdef USE_TCCR2A -typedef TCom Tc2a; //P11 -typedef TCom Tc2b; //P3 -#endif - -template -class Tp_Tc { -public: - - static void SetDir(uint8_t val) { - if(val) - SetDirWrite(); - else SetDirRead(); - } - - static void SetDirRead() { - Tp_pin::SetDirRead(); //set pin direction - Tc_bit::Clear(); //disconnect pin from PWM - } - - static void SetDirWrite() { - Tp_pin::SetDirWrite(); - Tc_bit::Clear(); - } -}; - -/* pin definitions for cases where it's necessary to clear compare output mode bits */ - -//typedef Tp_Tc P3; //Arduino pin 3 -//typedef Tp_Tc P5; //Arduino pin 5 -//typedef Tp_Tc P6; //Arduino pin 6 -//typedef Tp_Tc P9; //Arduino pin 9 -//typedef Tp_Tc P10; //Arduino pin 10 -//typedef Tp_Tc P11; //Arduino pin 11 - -/* Arduino pin definitions */ -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) -// "Mega" Arduino pin numbers - -#define P0 Pe0 -#define P1 Pe1 -#define P2 Pe4 -#define P3 Pe5 -#define P4 Pg5 -#define P5 Pe3 -#define P6 Ph3 -#define P7 Ph4 - -#define P8 Ph5 -#define P9 Ph6 -#define P10 Pb4 -#define P11 Pb5 -#define P12 Pb6 -#define P13 Pb7 - -#define P14 Pj1 -#define P15 Pj0 -#define P16 Ph1 -#define P17 Ph0 -#define P18 Pd3 -#define P19 Pd2 -#define P20 Pd1 -#define P21 Pd0 - -#define P22 Pa0 -#define P23 Pa1 -#define P24 Pa2 -#define P25 Pa3 -#define P26 Pa4 -#define P27 Pa5 -#define P28 Pa6 -#define P29 Pa7 -#define P30 Pc7 -#define P31 Pc6 -#define P32 Pc5 -#define P33 Pc4 -#define P34 Pc3 -#define P35 Pc2 -#define P36 Pc1 -#define P37 Pc0 - -#define P38 Pd7 -#define P39 Pg2 -#define P40 Pg1 -#define P41 Pg0 -#define P42 Pl7 -#define P43 Pl6 -#define P44 Pl5 -#define P45 Pl4 -#define P46 Pl3 -#define P47 Pl2 -#define P48 Pl1 -#define P49 Pl0 -#define P50 Pb3 -#define P51 Pb2 -#define P52 Pb1 -#define P53 Pb0 - -#ifdef BOARD_MEGA_ADK // These pins are not broken out on the Arduino ADK -#define P54 Pe6 // INT on Arduino ADK -#define P55 Pj2 // MAX_RESET on Arduino ADK -#endif - -// "Mega" pin numbers - -#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) -// "Classic" Arduino pin numbers - -#define P0 Pd0 -#define P1 Pd1 -#define P2 Pd2 -#define P3 Pd3 -#define P4 Pd4 -#define P5 Pd5 -#define P6 Pd6 -#define P7 Pd7 - -#define P8 Pb0 -#define P9 Pb1 -#define P10 Pb2 -#define P11 Pb3 -#define P12 Pb4 -#define P13 Pb5 - -#define P14 Pc0 -#define P15 Pc1 -#define P16 Pc2 -#define P17 Pc3 -#define P18 Pc4 -#define P19 Pc5 - -// "Classic" Arduino pin numbers - -#elif defined(CORE_TEENSY) && defined(__AVR_ATmega32U4__) -// Teensy 2.0 pin numbers -// http://www.pjrc.com/teensy/pinout.html -#define P0 Pb0 -#define P1 Pb1 -#define P2 Pb2 -#define P3 Pb3 -#define P4 Pb7 -#define P5 Pd0 -#define P6 Pd1 -#define P7 Pd2 -#define P8 Pd3 -#define P9 Pc6 -#define P10 Pc7 -#define P11 Pd6 -#define P12 Pd7 -#define P13 Pb4 -#define P14 Pb5 -#define P15 Pb6 -#define P16 Pf7 -#define P17 Pf6 -#define P18 Pf5 -#define P19 Pf4 -#define P20 Pf1 -#define P21 Pf0 -#define P22 Pd4 -#define P23 Pd5 -#define P24 Pe6 -// Teensy 2.0 - -#elif defined(__AVR_ATmega32U4__) -// Arduino Leonardo pin numbers - -#define P0 Pd2 // D0 - PD2 -#define P1 Pd3 // D1 - PD3 -#define P2 Pd1 // D2 - PD1 -#define P3 Pd0 // D3 - PD0 -#define P4 Pd4 // D4 - PD4 -#define P5 Pc6 // D5 - PC6 -#define P6 Pd7 // D6 - PD7 -#define P7 Pe6 // D7 - PE6 - -#define P8 Pb4 // D8 - PB4 -#define P9 Pb5 // D9 - PB5 -#define P10 Pb6 // D10 - PB6 -#define P11 Pb7 // D11 - PB7 -#define P12 Pd6 // D12 - PD6 -#define P13 Pc7 // D13 - PC7 - -#define P14 Pb3 // D14 - MISO - PB3 -#define P15 Pb1 // D15 - SCK - PB1 -#define P16 Pb2 // D16 - MOSI - PB2 -#define P17 Pb0 // D17 - SS - PB0 - -#define P18 Pf7 // D18 - A0 - PF7 -#define P19 Pf6 // D19 - A1 - PF6 -#define P20 Pf5 // D20 - A2 - PF5 -#define P21 Pf4 // D21 - A3 - PF4 -#define P22 Pf1 // D22 - A4 - PF1 -#define P23 Pf0 // D23 - A5 - PF0 - -#define P24 Pd4 // D24 / D4 - A6 - PD4 -#define P25 Pd7 // D25 / D6 - A7 - PD7 -#define P26 Pb4 // D26 / D8 - A8 - PB4 -#define P27 Pb5 // D27 / D9 - A9 - PB5 -#define P28 Pb6 // D28 / D10 - A10 - PB6 -#define P29 Pd6 // D29 / D12 - A11 - PD6 - -// Arduino Leonardo pin numbers - -#elif defined(CORE_TEENSY) && (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)) -// Teensy++ 1.0 and 2.0 pin numbers -// http://www.pjrc.com/teensy/pinout.html -#define P0 Pd0 -#define P1 Pd1 -#define P2 Pd2 -#define P3 Pd3 -#define P4 Pd4 -#define P5 Pd5 -#define P6 Pd6 -#define P7 Pd7 -#define P8 Pe0 -#define P9 Pe1 -#define P10 Pc0 -#define P11 Pc1 -#define P12 Pc2 -#define P13 Pc3 -#define P14 Pc4 -#define P15 Pc5 -#define P16 Pc6 -#define P17 Pc7 -#define P18 Pe6 -#define P19 Pe7 -#define P20 Pb0 -#define P21 Pb1 -#define P22 Pb2 -#define P23 Pb3 -#define P24 Pb4 -#define P25 Pb5 -#define P26 Pb6 -#define P27 Pb7 -#define P28 Pa0 -#define P29 Pa1 -#define P30 Pa2 -#define P31 Pa3 -#define P32 Pa4 -#define P33 Pa5 -#define P34 Pa6 -#define P35 Pa7 -#define P36 Pe4 -#define P37 Pe5 -#define P38 Pf0 -#define P39 Pf1 -#define P40 Pf2 -#define P41 Pf3 -#define P42 Pf4 -#define P43 Pf5 -#define P44 Pf6 -#define P45 Pf7 -// Teensy++ 1.0 and 2.0 - -#elif defined(ARDUINO_AVR_BALANDUINO) && (defined(__AVR_ATmega644__) || defined(__AVR_ATmega1284P__)) -// Balanduino pin numbers -// http://balanduino.net/ -#define P0 Pd0 /* 0 - PD0 */ -#define P1 Pd1 /* 1 - PD1 */ - -#if BALANDUINO_REVISION < 13 - #define P2 Pb2 /* 2 - PB2 */ - #define P3 Pd6 /* 3 - PD6 */ - #define P4 Pd7 /* 4 - PD7 */ - #define P5 Pb3 /* 5 - PB3 */ -#else - #define P2 Pd2 /* 2 - PD2 */ - #define P3 Pd3 /* 3 - PD3 */ - #define P4 Pd6 /* 4 - PD6 */ - #define P5 Pd7 /* 5 - PD7 */ -#endif - -#define P6 Pb4 /* 6 - PB4 */ -#define P7 Pa0 /* 7 - PA0 */ -#define P8 Pa1 /* 8 - PA1 */ -#define P9 Pa2 /* 9 - PA2 */ -#define P10 Pa3 /* 10 - PA3 */ -#define P11 Pa4 /* 11 - PA4 */ -#define P12 Pa5 /* 12 - PA5 */ -#define P13 Pc1 /* 13 - PC1 */ -#define P14 Pc0 /* 14 - PC0 */ - -#if BALANDUINO_REVISION < 13 - #define P15 Pd2 /* 15 - PD2 */ - #define P16 Pd3 /* 16 - PD3 */ -#else - #define P15 Pb2 /* 15 - PB2 */ - #define P16 Pb3 /* 16 - PB2 */ -#endif - -#define P17 Pd4 /* 17 - PD4 */ -#define P18 Pd5 /* 18 - PD5 */ -#define P19 Pc2 /* 19 - PC2 */ -#define P20 Pc3 /* 20 - PC3 */ -#define P21 Pc4 /* 21 - PC4 */ -#define P22 Pc5 /* 22 - PC5 */ -#define P23 Pc6 /* 23 - PC6 */ -#define P24 Pc7 /* 24 - PC7 */ -#define P25 Pb0 /* 25 - PB0 */ -#define P26 Pb1 /* 26 - PB1 */ -#define P27 Pb5 /* 27 - PB5 */ -#define P28 Pb6 /* 28 - PB6 */ -#define P29 Pb7 /* 29 - PB7 */ -#define P30 Pa6 /* 30 - PA6 */ -#define P31 Pa7 /* 31 - PA7 */ -// Balanduino - -#elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) -// Sanguino pin numbers -// Homepage: http://sanguino.cc/hardware -// Hardware add-on: https://github.com/Lauszus/Sanguino -#define P0 Pb0 -#define P1 Pb1 -#define P2 Pb2 -#define P3 Pb3 -#define P4 Pb4 -#define P5 Pb5 -#define P6 Pb6 -#define P7 Pb7 -#define P8 Pd0 -#define P9 Pd1 -#define P10 Pd2 -#define P11 Pd3 -#define P12 Pd4 -#define P13 Pd5 -#define P14 Pd6 -#define P15 Pd7 -#define P16 Pc0 -#define P17 Pc1 -#define P18 Pc2 -#define P19 Pc3 -#define P20 Pc4 -#define P21 Pc5 -#define P22 Pc6 -#define P23 Pc7 -#define P24 Pa0 -#define P25 Pa1 -#define P26 Pa2 -#define P27 Pa3 -#define P28 Pa4 -#define P29 Pa5 -#define P30 Pa6 -#define P31 Pa7 -// Sanguino - -#else -#error "Please define board in avrpins.h" - -#endif // Arduino pin definitions - -#elif defined(__arm__) - -// pointers are 32 bits on ARM -#define pgm_read_pointer(p) pgm_read_dword(p) - -#if defined(CORE_TEENSY) && (defined(__MK20DX128__) || defined(__MK20DX256__)) - -#include "core_pins.h" -#include "avr_emulation.h" - -#define GPIO_BITBAND_ADDR(reg, bit) (((uint32_t)&(reg) - 0x40000000) * 32 + (bit) * 4 + 0x42000000) -#define GPIO_BITBAND_PTR(reg, bit) ((uint8_t *)GPIO_BITBAND_ADDR((reg), (bit))) - -#define MAKE_PIN(className, baseReg, pinNum, configReg) \ -class className { \ -public: \ - static void Set() { \ - *GPIO_BITBAND_PTR(baseReg, pinNum) = 1; \ - } \ - static void Clear() { \ - *GPIO_BITBAND_PTR(baseReg, pinNum) = 0; \ - } \ - static void SetDirRead() { \ - configReg = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); \ - *(GPIO_BITBAND_PTR(baseReg, pinNum) + 640) = 0; \ - } \ - static void SetDirWrite() { \ - configReg = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); \ - *(GPIO_BITBAND_PTR(baseReg, pinNum) + 640) = 1; \ - } \ - static uint8_t IsSet() { \ - return *(GPIO_BITBAND_PTR(baseReg, pinNum) + 512); \ - } \ -}; - -MAKE_PIN(P0, CORE_PIN0_PORTREG, CORE_PIN0_BIT, CORE_PIN0_CONFIG); -MAKE_PIN(P1, CORE_PIN1_PORTREG, CORE_PIN1_BIT, CORE_PIN1_CONFIG); -MAKE_PIN(P2, CORE_PIN2_PORTREG, CORE_PIN2_BIT, CORE_PIN2_CONFIG); -MAKE_PIN(P3, CORE_PIN3_PORTREG, CORE_PIN3_BIT, CORE_PIN3_CONFIG); -MAKE_PIN(P4, CORE_PIN4_PORTREG, CORE_PIN4_BIT, CORE_PIN4_CONFIG); -MAKE_PIN(P5, CORE_PIN5_PORTREG, CORE_PIN5_BIT, CORE_PIN5_CONFIG); -MAKE_PIN(P6, CORE_PIN6_PORTREG, CORE_PIN6_BIT, CORE_PIN6_CONFIG); -MAKE_PIN(P7, CORE_PIN7_PORTREG, CORE_PIN7_BIT, CORE_PIN7_CONFIG); -MAKE_PIN(P8, CORE_PIN8_PORTREG, CORE_PIN8_BIT, CORE_PIN8_CONFIG); -MAKE_PIN(P9, CORE_PIN9_PORTREG, CORE_PIN9_BIT, CORE_PIN9_CONFIG); -MAKE_PIN(P10, CORE_PIN10_PORTREG, CORE_PIN10_BIT, CORE_PIN10_CONFIG); -MAKE_PIN(P11, CORE_PIN11_PORTREG, CORE_PIN11_BIT, CORE_PIN11_CONFIG); -MAKE_PIN(P12, CORE_PIN12_PORTREG, CORE_PIN12_BIT, CORE_PIN12_CONFIG); -MAKE_PIN(P13, CORE_PIN13_PORTREG, CORE_PIN13_BIT, CORE_PIN13_CONFIG); -MAKE_PIN(P14, CORE_PIN14_PORTREG, CORE_PIN14_BIT, CORE_PIN14_CONFIG); -MAKE_PIN(P15, CORE_PIN15_PORTREG, CORE_PIN15_BIT, CORE_PIN15_CONFIG); -MAKE_PIN(P16, CORE_PIN16_PORTREG, CORE_PIN16_BIT, CORE_PIN16_CONFIG); -MAKE_PIN(P17, CORE_PIN17_PORTREG, CORE_PIN17_BIT, CORE_PIN17_CONFIG); -MAKE_PIN(P18, CORE_PIN18_PORTREG, CORE_PIN18_BIT, CORE_PIN18_CONFIG); -MAKE_PIN(P19, CORE_PIN19_PORTREG, CORE_PIN19_BIT, CORE_PIN19_CONFIG); -MAKE_PIN(P20, CORE_PIN20_PORTREG, CORE_PIN20_BIT, CORE_PIN20_CONFIG); -MAKE_PIN(P21, CORE_PIN21_PORTREG, CORE_PIN21_BIT, CORE_PIN21_CONFIG); -MAKE_PIN(P22, CORE_PIN22_PORTREG, CORE_PIN22_BIT, CORE_PIN22_CONFIG); -MAKE_PIN(P23, CORE_PIN23_PORTREG, CORE_PIN23_BIT, CORE_PIN23_CONFIG); -MAKE_PIN(P24, CORE_PIN24_PORTREG, CORE_PIN24_BIT, CORE_PIN24_CONFIG); -MAKE_PIN(P25, CORE_PIN25_PORTREG, CORE_PIN25_BIT, CORE_PIN25_CONFIG); -MAKE_PIN(P26, CORE_PIN26_PORTREG, CORE_PIN26_BIT, CORE_PIN26_CONFIG); -MAKE_PIN(P27, CORE_PIN27_PORTREG, CORE_PIN27_BIT, CORE_PIN27_CONFIG); -MAKE_PIN(P28, CORE_PIN28_PORTREG, CORE_PIN28_BIT, CORE_PIN28_CONFIG); -MAKE_PIN(P29, CORE_PIN29_PORTREG, CORE_PIN29_BIT, CORE_PIN29_CONFIG); -MAKE_PIN(P30, CORE_PIN30_PORTREG, CORE_PIN30_BIT, CORE_PIN30_CONFIG); -MAKE_PIN(P31, CORE_PIN31_PORTREG, CORE_PIN31_BIT, CORE_PIN31_CONFIG); -MAKE_PIN(P32, CORE_PIN32_PORTREG, CORE_PIN32_BIT, CORE_PIN32_CONFIG); -MAKE_PIN(P33, CORE_PIN33_PORTREG, CORE_PIN33_BIT, CORE_PIN33_CONFIG); - -#undef MAKE_PIN - -#elif defined(ARDUINO_SAM_DUE) && defined(__SAM3X8E__) - -// SetDirRead: -// Disable interrupts -// Disable the pull up resistor -// Set to INPUT -// Enable PIO - -// SetDirWrite: -// Disable interrupts -// Disable the pull up resistor -// Set to OUTPUT -// Enable PIO - -#define MAKE_PIN(className, pio, pinMask) \ -class className { \ -public: \ - static void Set() { \ - pio->PIO_SODR = pinMask; \ - } \ - static void Clear() { \ - pio->PIO_CODR = pinMask; \ - } \ - static void SetDirRead() { \ - pio->PIO_IDR = pinMask ; \ - pio->PIO_PUDR = pinMask; \ - pio->PIO_ODR = pinMask; \ - pio->PIO_PER = pinMask; \ - } \ - static void SetDirWrite() { \ - pio->PIO_IDR = pinMask ; \ - pio->PIO_PUDR = pinMask; \ - pio->PIO_OER = pinMask; \ - pio->PIO_PER = pinMask; \ - } \ - static uint8_t IsSet() { \ - return pio->PIO_PDSR & pinMask; \ - } \ -}; - -// See: http://arduino.cc/en/Hacking/PinMappingSAM3X and variant.cpp - -MAKE_PIN(P0, PIOA, PIO_PA8); -MAKE_PIN(P1, PIOA, PIO_PA9); -MAKE_PIN(P2, PIOB, PIO_PB25); -MAKE_PIN(P3, PIOC, PIO_PC28); -MAKE_PIN(P4, PIOC, PIO_PC26); -MAKE_PIN(P5, PIOC, PIO_PC25); -MAKE_PIN(P6, PIOC, PIO_PC24); -MAKE_PIN(P7, PIOC, PIO_PC23); -MAKE_PIN(P8, PIOC, PIO_PC22); -MAKE_PIN(P9, PIOC, PIO_PC21); -MAKE_PIN(P10, PIOC, PIO_PC29); -MAKE_PIN(P11, PIOD, PIO_PD7); -MAKE_PIN(P12, PIOD, PIO_PD8); -MAKE_PIN(P13, PIOB, PIO_PB27); -MAKE_PIN(P14, PIOD, PIO_PD4); -MAKE_PIN(P15, PIOD, PIO_PD5); -MAKE_PIN(P16, PIOA, PIO_PA13); -MAKE_PIN(P17, PIOA, PIO_PA12); -MAKE_PIN(P18, PIOA, PIO_PA11); -MAKE_PIN(P19, PIOA, PIO_PA10); -MAKE_PIN(P20, PIOB, PIO_PB12); -MAKE_PIN(P21, PIOB, PIO_PB13); -MAKE_PIN(P22, PIOB, PIO_PB26); -MAKE_PIN(P23, PIOA, PIO_PA14); -MAKE_PIN(P24, PIOA, PIO_PA15); -MAKE_PIN(P25, PIOD, PIO_PD0); -MAKE_PIN(P26, PIOD, PIO_PD1); -MAKE_PIN(P27, PIOD, PIO_PD2); -MAKE_PIN(P28, PIOD, PIO_PD3); -MAKE_PIN(P29, PIOD, PIO_PD6); -MAKE_PIN(P30, PIOD, PIO_PD9); -MAKE_PIN(P31, PIOA, PIO_PA7); -MAKE_PIN(P32, PIOD, PIO_PD10); -MAKE_PIN(P33, PIOC, PIO_PC1); -MAKE_PIN(P34, PIOC, PIO_PC2); -MAKE_PIN(P35, PIOC, PIO_PC3); -MAKE_PIN(P36, PIOC, PIO_PC4); -MAKE_PIN(P37, PIOC, PIO_PC5); -MAKE_PIN(P38, PIOC, PIO_PC6); -MAKE_PIN(P39, PIOC, PIO_PC7); -MAKE_PIN(P40, PIOC, PIO_PC8); -MAKE_PIN(P41, PIOC, PIO_PC9); -MAKE_PIN(P42, PIOA, PIO_PA19); -MAKE_PIN(P43, PIOA, PIO_PA20); -MAKE_PIN(P44, PIOC, PIO_PC19); -MAKE_PIN(P45, PIOC, PIO_PC18); -MAKE_PIN(P46, PIOC, PIO_PC17); -MAKE_PIN(P47, PIOC, PIO_PC16); -MAKE_PIN(P48, PIOC, PIO_PC15); -MAKE_PIN(P49, PIOC, PIO_PC14); -MAKE_PIN(P50, PIOC, PIO_PC13); -MAKE_PIN(P51, PIOC, PIO_PC12); -MAKE_PIN(P52, PIOB, PIO_PB21); -MAKE_PIN(P53, PIOB, PIO_PB14); -MAKE_PIN(P54, PIOA, PIO_PA16); -MAKE_PIN(P55, PIOA, PIO_PA24); -MAKE_PIN(P56, PIOA, PIO_PA23); -MAKE_PIN(P57, PIOA, PIO_PA22); -MAKE_PIN(P58, PIOA, PIO_PA6); -MAKE_PIN(P59, PIOA, PIO_PA4); -MAKE_PIN(P60, PIOA, PIO_PA3); -MAKE_PIN(P61, PIOA, PIO_PA2); -MAKE_PIN(P62, PIOB, PIO_PB17); -MAKE_PIN(P63, PIOB, PIO_PB18); -MAKE_PIN(P64, PIOB, PIO_PB19); -MAKE_PIN(P65, PIOB, PIO_PB20); -MAKE_PIN(P66, PIOB, PIO_PB15); -MAKE_PIN(P67, PIOB, PIO_PB16); -MAKE_PIN(P68, PIOA, PIO_PA1); -MAKE_PIN(P69, PIOA, PIO_PA0); -MAKE_PIN(P70, PIOA, PIO_PA17); -MAKE_PIN(P71, PIOA, PIO_PA18); -MAKE_PIN(P72, PIOC, PIO_PC30); -MAKE_PIN(P73, PIOA, PIO_PA21); -MAKE_PIN(P74, PIOA, PIO_PA25); // MISO -MAKE_PIN(P75, PIOA, PIO_PA26); // MOSI -MAKE_PIN(P76, PIOA, PIO_PA27); // CLK -MAKE_PIN(P77, PIOA, PIO_PA28); -MAKE_PIN(P78, PIOB, PIO_PB23); // Unconnected - -#undef MAKE_PIN - -#elif defined(RBL_NRF51822) - -#define MAKE_PIN(className, pin) \ -class className { \ -public: \ - static void Set() { \ - nrf_gpio_pin_set(pin); \ - } \ - static void Clear() { \ - nrf_gpio_pin_clear(pin); \ - } \ - static void SetDirRead() { \ - nrf_gpio_cfg_input(pin, NRF_GPIO_PIN_NOPULL); \ - } \ - static void SetDirWrite() { \ - nrf_gpio_cfg_output(pin); \ - } \ - static uint8_t IsSet() { \ - return (uint8_t)nrf_gpio_pin_read(pin); \ - } \ -}; - -// See: pin_transform.c in RBL nRF51822 SDK -MAKE_PIN(P0, Pin_nRF51822_to_Arduino(D0)); -MAKE_PIN(P1, Pin_nRF51822_to_Arduino(D1)); -MAKE_PIN(P2, Pin_nRF51822_to_Arduino(D2)); -MAKE_PIN(P3, Pin_nRF51822_to_Arduino(D3)); -MAKE_PIN(P4, Pin_nRF51822_to_Arduino(D4)); -MAKE_PIN(P5, Pin_nRF51822_to_Arduino(D5)); -MAKE_PIN(P6, Pin_nRF51822_to_Arduino(D6)); -MAKE_PIN(P7, Pin_nRF51822_to_Arduino(D7)); -MAKE_PIN(P8, Pin_nRF51822_to_Arduino(D8)); -MAKE_PIN(P9, Pin_nRF51822_to_Arduino(D9)); // INT -MAKE_PIN(P10, Pin_nRF51822_to_Arduino(D10)); // SS -MAKE_PIN(P11, Pin_nRF51822_to_Arduino(D11)); -MAKE_PIN(P12, Pin_nRF51822_to_Arduino(D12)); -MAKE_PIN(P13, Pin_nRF51822_to_Arduino(D13)); -MAKE_PIN(P14, Pin_nRF51822_to_Arduino(D14)); -MAKE_PIN(P15, Pin_nRF51822_to_Arduino(D15)); -MAKE_PIN(P17, Pin_nRF51822_to_Arduino(D17)); // MISO -MAKE_PIN(P18, Pin_nRF51822_to_Arduino(D18)); // MOSI -MAKE_PIN(P16, Pin_nRF51822_to_Arduino(D16)); // CLK -MAKE_PIN(P19, Pin_nRF51822_to_Arduino(D19)); -MAKE_PIN(P20, Pin_nRF51822_to_Arduino(D20)); -MAKE_PIN(P21, Pin_nRF51822_to_Arduino(D21)); -MAKE_PIN(P22, Pin_nRF51822_to_Arduino(D22)); -MAKE_PIN(P23, Pin_nRF51822_to_Arduino(D23)); -MAKE_PIN(P24, Pin_nRF51822_to_Arduino(D24)); - -#undef MAKE_PIN - -#else -#error "Please define board in avrpins.h" - -#endif - -#elif defined(__ARDUINO_X86__) // Intel Galileo, Intel Galileo 2 and Intel Edison - -#include - -// Pointers are 32 bits on x86 -#define pgm_read_pointer(p) pgm_read_dword(p) - -#if PLATFORM_ID == 0xE1 // Edison platform id -#define pinToFastPin(pin) 1 // As far as I can tell all pins can be used as fast pins -#endif - -// Pin 2 and 3 on the Intel Galileo supports a higher rate, -// so it is recommended to use one of these as the SS pin. - -#define MAKE_PIN(className, pin) \ -class className { \ -public: \ - static void Set() { \ - fastDigitalWrite(pin, HIGH); \ - } \ - static void Clear() { \ - fastDigitalWrite(pin, LOW); \ - } \ - static void SetDirRead() { \ - if (pinToFastPin(pin)) \ - pinMode(pin, INPUT_FAST); \ - else \ - pinMode(pin, INPUT); \ - } \ - static void SetDirWrite() { \ - if (pinToFastPin(pin)) \ - pinMode(pin, OUTPUT_FAST); \ - else \ - pinMode(pin, OUTPUT); \ - } \ - static uint8_t IsSet() { \ - return fastDigitalRead(pin); \ - } \ -}; - -MAKE_PIN(P0, 0); -MAKE_PIN(P1, 1); -MAKE_PIN(P2, 2); -MAKE_PIN(P3, 3); -MAKE_PIN(P4, 4); -MAKE_PIN(P5, 5); -MAKE_PIN(P6, 6); -MAKE_PIN(P7, 7); -MAKE_PIN(P8, 8); -MAKE_PIN(P9, 9); -MAKE_PIN(P10, 10); -MAKE_PIN(P11, 11); -MAKE_PIN(P12, 12); -MAKE_PIN(P13, 13); -MAKE_PIN(P14, 14); // A0 -MAKE_PIN(P15, 15); // A1 -MAKE_PIN(P16, 16); // A2 -MAKE_PIN(P17, 17); // A3 -MAKE_PIN(P18, 18); // A4 -MAKE_PIN(P19, 19); // A5 - -#undef MAKE_PIN - -#elif defined(__MIPSEL__) -// MIPSEL (MIPS architecture using a little endian byte order) - -// MIPS size_t = 4 -#define pgm_read_pointer(p) pgm_read_dword(p) - -#define MAKE_PIN(className, pin) \ -class className { \ -public: \ - static void Set() { \ - digitalWrite(pin, HIGH);\ - } \ - static void Clear() { \ - digitalWrite(pin, LOW); \ - } \ - static void SetDirRead() { \ - pinMode(pin, INPUT); \ - } \ - static void SetDirWrite() { \ - pinMode(pin, OUTPUT); \ - } \ - static uint8_t IsSet() { \ - return digitalRead(pin); \ - } \ -}; - -// 0 .. 13 - Digital pins -MAKE_PIN(P0, 0); // RX -MAKE_PIN(P1, 1); // TX -MAKE_PIN(P2, 2); // -MAKE_PIN(P3, 3); // -MAKE_PIN(P4, 4); // -MAKE_PIN(P5, 5); // -MAKE_PIN(P6, 6); // -MAKE_PIN(P7, 7); // -MAKE_PIN(P8, 8); // -MAKE_PIN(P9, 9); // -MAKE_PIN(P10, 10); // -MAKE_PIN(P11, 11); // -MAKE_PIN(P12, 12); // -MAKE_PIN(P13, 13); // - -#undef MAKE_PIN - -#else -#error "Please define board in avrpins.h" - -#endif - -#endif //_avrpins_h_ diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdc_XR21B1411.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdc_XR21B1411.cpp deleted file mode 100644 index 74df8c3bdd..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdc_XR21B1411.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ -#include "cdc_XR21B1411.h" - -XR21B1411::XR21B1411(USB *p, CDCAsyncOper *pasync) : -ACM(p, pasync) { - // Is this needed?? - _enhanced_status = enhanced_features(); // Set up features -} - -uint8_t XR21B1411::Init(uint8_t parent, uint8_t port, bool lowspeed) { - const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR); - - uint8_t buf[constBufSize]; - USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); - - uint8_t rcode; - UsbDevice *p = NULL; - EpInfo *oldep_ptr = NULL; - uint8_t num_of_conf; // number of configurations - - AddressPool &addrPool = pUsb->GetAddressPool(); - - USBTRACE("XR Init\r\n"); - - if(bAddress) - return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; - - // Get pointer to pseudo device with address 0 assigned - p = addrPool.GetUsbDevicePtr(0); - - if(!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - if(!p->epinfo) { - USBTRACE("epinfo\r\n"); - return USB_ERROR_EPINFO_IS_NULL; - } - - // Save old pointer to EP_RECORD of address 0 - oldep_ptr = p->epinfo; - - // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence - p->epinfo = epInfo; - - p->lowspeed = lowspeed; - - // Get device descriptor - rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf); - - // Restore p->epinfo - p->epinfo = oldep_ptr; - - if(rcode) - goto FailGetDevDescr; - - // Allocate new address according to device class - bAddress = addrPool.AllocAddress(parent, false, port); - - if(!bAddress) - return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; - - // Extract Max Packet Size from the device descriptor - epInfo[0].maxPktSize = udd->bMaxPacketSize0; - - // Assign new address to the device - rcode = pUsb->setAddr(0, 0, bAddress); - - if(rcode) { - p->lowspeed = false; - addrPool.FreeAddress(bAddress); - bAddress = 0; - USBTRACE2("setAddr:", rcode); - return rcode; - } - - USBTRACE2("Addr:", bAddress); - - p->lowspeed = false; - - p = addrPool.GetUsbDevicePtr(bAddress); - - if(!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - p->lowspeed = lowspeed; - - num_of_conf = udd->bNumConfigurations; - - if((((udd->idVendor != 0x2890U) || (udd->idProduct != 0x0201U)) && ((udd->idVendor != 0x04e2U) || (udd->idProduct != 0x1411U)))) - return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - - // Assign epInfo to epinfo pointer - rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); - - if(rcode) - goto FailSetDevTblEntry; - - USBTRACE2("NC:", num_of_conf); - - for(uint8_t i = 0; i < num_of_conf; i++) { - ConfigDescParser< USB_CLASS_COM_AND_CDC_CTRL, - CDC_SUBCLASS_ACM, - CDC_PROTOCOL_ITU_T_V_250, - CP_MASK_COMPARE_CLASS | - CP_MASK_COMPARE_SUBCLASS | - CP_MASK_COMPARE_PROTOCOL > CdcControlParser(this); - - ConfigDescParser CdcDataParser(this); - - rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcControlParser); - - if(rcode) - goto FailGetConfDescr; - - rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcDataParser); - - if(rcode) - goto FailGetConfDescr; - - if(bNumEP > 1) - break; - } // for - - if(bNumEP < 4) - return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - - // Assign epInfo to epinfo pointer - rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); - - USBTRACE2("Conf:", bConfNum); - - // Set Configuration Value - rcode = pUsb->setConf(bAddress, 0, bConfNum); - - if(rcode) - goto FailSetConfDescr; - - // Set up features status - _enhanced_status = enhanced_features(); - half_duplex(false); - autoflowRTS(false); - autoflowDSR(false); - autoflowXON(false); - wide(false); // Always false, because this is only available in custom mode. - - rcode = pAsync->OnInit(this); - - if(rcode) - goto FailOnInit; - - USBTRACE("XR configured\r\n"); - - ready = true; - - //bPollEnable = true; - - //USBTRACE("Poll enabled\r\n"); - return 0; - -FailGetDevDescr: -#ifdef DEBUG_USB_HOST - NotifyFailGetDevDescr(); - goto Fail; -#endif - -FailSetDevTblEntry: -#ifdef DEBUG_USB_HOST - NotifyFailSetDevTblEntry(); - goto Fail; -#endif - -FailGetConfDescr: -#ifdef DEBUG_USB_HOST - NotifyFailGetConfDescr(); - goto Fail; -#endif - -FailSetConfDescr: -#ifdef DEBUG_USB_HOST - NotifyFailSetConfDescr(); - goto Fail; -#endif - -FailOnInit: -#ifdef DEBUG_USB_HOST - USBTRACE("OnInit:"); -#endif - -#ifdef DEBUG_USB_HOST -Fail: - NotifyFail(rcode); -#endif - Release(); - return rcode; -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdc_XR21B1411.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdc_XR21B1411.h deleted file mode 100644 index c32627544f..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdc_XR21B1411.h +++ /dev/null @@ -1,272 +0,0 @@ -/* Copyright (C) 2015 Andrew J. Kroll - and - Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ -#if !defined(__CDC_XR21B1411_H__) -#define __CDC_XR21B1411_H__ - -#include "cdcacm.h" - -#define XR_REG_CUSTOM_DRIVER (0x020DU) // DRIVER SELECT -#define XR_REG_CUSTOM_DRIVER_ACTIVE (0x0001U) // 0: CDC 1: CUSTOM - -#define XR_REG_ACM_FLOW_CTL (0x0216U) // FLOW CONTROL REGISTER CDCACM MODE -#define XR_REG_FLOW_CTL (0x0C06U) // FLOW CONTROL REGISTER CUSTOM MODE -#define XR_REG_FLOW_CTL_HALF_DPLX (0x0008U) // 0:FULL DUPLEX 1:HALF DUPLEX -#define XR_REG_FLOW_CTL_MODE_MASK (0x0007U) // MODE BITMASK -#define XR_REG_FLOW_CTL_NONE (0x0000U) // NO FLOW CONTROL -#define XR_REG_FLOW_CTL_HW (0x0001U) // HARDWARE FLOW CONTROL -#define XR_REG_FLOW_CTL_SW (0x0002U) // SOFTWARE FLOW CONTROL -#define XR_REG_FLOW_CTL_MMMRX (0x0003U) // MULTIDROP RX UPON ADDRESS MATCH -#define XR_REG_FLOW_CTL_MMMRXTX (0x0004U) // MULTIDROP RX/TX UPON ADDRESS MATCH - -#define XR_REG_ACM_GPIO_MODE (0x0217U) // GPIO MODE REGISTER IN CDCACM MODE -#define XR_REG_GPIO_MODE (0x0C0CU) // GPIO MODE REGISTER IN CUSTOM MODE -#define XR_REG_GPIO_MODE_GPIO (0x0000U) // ALL GPIO PINS ACM PROGRAMMABLE -#define XR_REG_GPIO_MODE_FC_RTSCTS (0x0001U) // AUTO RTSCTS HW FC (GPIO 4/5) -#define XR_REG_GPIO_MODE_FC_DTRDSR (0x0002U) // AUTO DTRDSR HW FC (GPIO 2/3) -#define XR_REG_GPIO_MODE_ATE (0x0003U) // AUTO TRANSCEIVER ENABLE DURING TX (GPIO 5) -#define XR_REG_GPIO_MODE_ATE_ADDRESS (0x0004U) // AUTO TRANSCEIVER ENABLE ON ADDRESS MATCH (GPIO 5) - -#define XR_REG_ACM_GPIO_DIR (0x0218U) // GPIO DIRECTION REGISTER CDCACM MODE, 0:IN 1:OUT -#define XR_REG_GPIO_DIR (0x0C0DU) // GPIO DIRECTION REGISTER CUSTOM MODE, 0:IN 1:OUT - -#define XR_REG_ACM_GPIO_INT (0x0219U) // GPIO PIN CHANGE INTERRUPT ENABLE CDCACM MODE, 0: ENABLED 1: DISABLED -#define XR_REG_GPIO_INT (0x0C11U) // GPIO PIN CHANGE INTERRUPT ENABLE CUSTOM MODE, 0: ENABLED 1: DISABLED -#define XR_REG_GPIO_MASK (0x001FU) // GPIO REGISTERS BITMASK - -#define XR_REG_UART_ENABLE (0x0C00U) // UART I/O ENABLE REGISTER -#define XR_REG_UART_ENABLE_RX (0x0002U) // 0:DISABLED 1:ENABLED -#define XR_REG_UART_ENABLE_TX (0x0001U) // 0:DISABLED 1:ENABLED - -#define XR_REG_ERROR_STATUS (0x0C09U) // ERROR STATUS REGISTER -#define XR_REG_ERROR_STATUS_MASK (0x00F8U) // ERROR STATUS BITMASK -#define XR_REG_ERROR_STATUS_ERROR (0x0078U) // ERROR STATUS ERROR BITMASK -#define XR_REG_ERROR_STATUS_BREAK (0x0008U) // BREAK ERROR HAS BEEN DETECTED -#define XR_REG_ERROR_STATUS_FRAME (0x0010U) // FRAMING ERROR HAS BEEN DETECTED -#define XR_REG_ERROR_STATUS_PARITY (0x0020U) // PARITY ERROR HAS BEEN DETECTED -#define XR_REG_ERROR_STATUS_OVERRUN (0x0040U) // RX OVERRUN ERROR HAS BEEN DETECTED -#define XR_REG_ERROR_STATUS_BREAK_STATUS (0x0080U) // BREAK CONDITION IS CURRENTLY BEING DETECTED - -#define XR_REG_TX_BREAK (0x0C0AU) // TRANSMIT BREAK. 0X0001-0XFFE TIME IN MS, 0X0000 STOP, 0X0FFF BREAK ON - -#define XR_REG_XCVR_EN_DELAY (0x0C0BU) // TURN-ARROUND DELAY IN BIT-TIMES 0X0000-0X000F - -#define XR_REG_GPIO_SET (0x0C0EU) // 1:SET GPIO PIN - -#define XR_REG_GPIO_CLR (0x0C0FU) // 1:CLEAR GPIO PIN - -#define XR_REG_GPIO_STATUS (0x0C10U) // READ GPIO PINS - -#define XR_REG_CUSTOMISED_INT (0x0C12U) // 0:STANDARD 1:CUSTOM SEE DATA SHEET - -#define XR_REG_PIN_PULLUP_ENABLE (0x0C14U) // 0:DISABLE 1:ENABLE, BITS 0-5:GPIO, 6:RX 7:TX - -#define XR_REG_PIN_PULLDOWN_ENABLE (0x0C15U) // 0:DISABLE 1:ENABLE, BITS 0-5:GPIO, 6:RX 7:TX - -#define XR_REG_LOOPBACK (0x0C16U) // 0:DISABLE 1:ENABLE, SEE DATA SHEET - -#define XR_REG_RX_FIFO_LATENCY (0x0CC2U) // FIFO LATENCY REGISTER -#define XR_REG_RX_FIFO_LATENCY_ENABLE (0x0001U) // - -#define XR_REG_WIDE_MODE (0x0D02U) -#define XR_REG_WIDE_MODE_ENABLE (0x0001U) - -#define XR_REG_XON_CHAR (0x0C07U) -#define XR_REG_XOFF_CHAR (0x0C08U) - -#define XR_REG_TX_FIFO_RESET (0x0C80U) // 1: RESET, SELF-CLEARING -#define XR_REG_TX_FIFO_COUNT (0x0C81U) // READ-ONLY -#define XR_REG_RX_FIFO_RESET (0x0CC0U) // 1: RESET, SELF-CLEARING -#define XR_REG_RX_FIFO_COUNT (0x0CC1U) // READ-ONLY - -#define XR_WRITE_REQUEST_TYPE (0x40U) - -#define XR_READ_REQUEST_TYPE (0xC0U) - -#define XR_MAX_ENDPOINTS 4 - -class XR21B1411 : public ACM { -protected: - -public: - XR21B1411(USB *pusb, CDCAsyncOper *pasync); - - /** - * Used by the USB core to check what this driver support. - * @param vid The device's VID. - * @param pid The device's PID. - * @return Returns true if the device's VID and PID matches this driver. - */ - virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) { - return (((vid == 0x2890U) && (pid == 0x0201U)) || ((vid == 0x04e2U) && (pid == 0x1411U))); - }; - - uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); - - virtual tty_features enhanced_features(void) { - tty_features rv; - rv.enhanced = true; - rv.autoflow_RTS = true; - rv.autoflow_DSR = true; - rv.autoflow_XON = true; - rv.half_duplex = true; - rv.wide = true; - return rv; - }; - - uint8_t read_register(uint16_t reg, uint16_t *val) { - return (pUsb->ctrlReq(bAddress, 0, XR_READ_REQUEST_TYPE, 1, 0, 0, reg, 2, 2, (uint8_t *)val, NULL)); - } - - uint8_t write_register(uint16_t reg, uint16_t val) { - return (pUsb->ctrlReq(bAddress, 0, XR_WRITE_REQUEST_TYPE, 0, BGRAB0(val), BGRAB1(val), reg, 0, 0, NULL, NULL)); - } - - - //////////////////////////////////////////////////////////////////////// - // The following methods set the CDC-ACM defaults. - //////////////////////////////////////////////////////////////////////// - - virtual void autoflowRTS(bool s) { - uint16_t val; - uint8_t rval; - rval = read_register(XR_REG_ACM_FLOW_CTL, &val); - if(!rval) { - if(s) { - val &= XR_REG_FLOW_CTL_HALF_DPLX; - val |= XR_REG_FLOW_CTL_HW; - } else { - val &= XR_REG_FLOW_CTL_HALF_DPLX; - } - rval = write_register(XR_REG_ACM_FLOW_CTL, val); - if(!rval) { - rval = write_register(XR_REG_ACM_GPIO_MODE, XR_REG_GPIO_MODE_GPIO); - if(!rval) { - // ACM commands apply the new settings. - LINE_CODING LCT; - rval = GetLineCoding(&LCT); - if(!rval) { - rval = SetLineCoding(&LCT); - if(!rval) { - _enhanced_status.autoflow_XON = false; - _enhanced_status.autoflow_DSR = false; - _enhanced_status.autoflow_RTS = s; - } - } - } - } - } - }; - - virtual void autoflowDSR(bool s) { - uint16_t val; - uint8_t rval; - rval = read_register(XR_REG_ACM_FLOW_CTL, &val); - if(!rval) { - if(s) { - val &= XR_REG_FLOW_CTL_HALF_DPLX; - val |= XR_REG_FLOW_CTL_HW; - } else { - val &= XR_REG_FLOW_CTL_HALF_DPLX; - } - rval = write_register(XR_REG_ACM_FLOW_CTL, val); - if(!rval) { - if(s) { - rval = write_register(XR_REG_ACM_GPIO_MODE, XR_REG_GPIO_MODE_FC_DTRDSR); - } else { - rval = write_register(XR_REG_ACM_GPIO_MODE, XR_REG_GPIO_MODE_GPIO); - } - if(!rval) { - // ACM commands apply the new settings. - LINE_CODING LCT; - rval = GetLineCoding(&LCT); - if(!rval) { - rval = SetLineCoding(&LCT); - if(!rval) { - _enhanced_status.autoflow_XON = false; - _enhanced_status.autoflow_RTS = false; - _enhanced_status.autoflow_DSR = s; - } - } - } - } - } - }; - - virtual void autoflowXON(bool s) { - // NOTE: hardware defaults to the normal XON/XOFF - uint16_t val; - uint8_t rval; - rval = read_register(XR_REG_ACM_FLOW_CTL, &val); - if(!rval) { - if(s) { - val &= XR_REG_FLOW_CTL_HALF_DPLX; - val |= XR_REG_FLOW_CTL_SW; - } else { - val &= XR_REG_FLOW_CTL_HALF_DPLX; - } - rval = write_register(XR_REG_ACM_FLOW_CTL, val); - if(!rval) { - rval = write_register(XR_REG_ACM_GPIO_MODE, XR_REG_GPIO_MODE_GPIO); - if(!rval) { - // ACM commands apply the new settings. - LINE_CODING LCT; - rval = GetLineCoding(&LCT); - if(!rval) { - rval = SetLineCoding(&LCT); - if(!rval) { - _enhanced_status.autoflow_RTS = false; - _enhanced_status.autoflow_DSR = false; - _enhanced_status.autoflow_XON = s; - } - } - } - } - } - }; - - virtual void half_duplex(bool s) { - uint16_t val; - uint8_t rval; - rval = read_register(XR_REG_ACM_FLOW_CTL, &val); - if(!rval) { - if(s) { - val |= XR_REG_FLOW_CTL_HALF_DPLX; - } else { - val &= XR_REG_FLOW_CTL_MODE_MASK; - } - rval = write_register(XR_REG_ACM_FLOW_CTL, val); - if(!rval) { - // ACM commands apply the new settings. - LINE_CODING LCT; - rval = GetLineCoding(&LCT); - if(!rval) { - rval = SetLineCoding(&LCT); - if(!rval) { - _enhanced_status.half_duplex = s; - } - } - } - } - }; - - - -}; - -#endif // __CDCPROLIFIC_H__ diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcacm.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcacm.cpp deleted file mode 100644 index 2cd2c9a82d..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcacm.cpp +++ /dev/null @@ -1,331 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ -#include "cdcacm.h" - -const uint8_t ACM::epDataInIndex = 1; -const uint8_t ACM::epDataOutIndex = 2; -const uint8_t ACM::epInterruptInIndex = 3; - -ACM::ACM(USB *p, CDCAsyncOper *pasync) : -pUsb(p), -pAsync(pasync), -bAddress(0), -bControlIface(0), -bDataIface(0), -bNumEP(1), -qNextPollTime(0), -bPollEnable(false), -ready(false) { - _enhanced_status = enhanced_features(); // Set up features - for(uint8_t i = 0; i < ACM_MAX_ENDPOINTS; i++) { - epInfo[i].epAddr = 0; - epInfo[i].maxPktSize = (i) ? 0 : 8; - epInfo[i].epAttribs = 0; - epInfo[i].bmNakPower = (i == epDataInIndex) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; - - } - if(pUsb) - pUsb->RegisterDeviceClass(this); -} - -uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed) { - - const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR); - - uint8_t buf[constBufSize]; - USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); - - uint8_t rcode; - UsbDevice *p = NULL; - EpInfo *oldep_ptr = NULL; - uint8_t num_of_conf; // number of configurations - - AddressPool &addrPool = pUsb->GetAddressPool(); - - USBTRACE("ACM Init\r\n"); - - if(bAddress) - return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; - - // Get pointer to pseudo device with address 0 assigned - p = addrPool.GetUsbDevicePtr(0); - - if(!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - if(!p->epinfo) { - USBTRACE("epinfo\r\n"); - return USB_ERROR_EPINFO_IS_NULL; - } - - // Save old pointer to EP_RECORD of address 0 - oldep_ptr = p->epinfo; - - // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence - p->epinfo = epInfo; - - p->lowspeed = lowspeed; - - // Get device descriptor - rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf); - - // Restore p->epinfo - p->epinfo = oldep_ptr; - - if(rcode) - goto FailGetDevDescr; - - // Allocate new address according to device class - bAddress = addrPool.AllocAddress(parent, false, port); - - if(!bAddress) - return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; - - // Extract Max Packet Size from the device descriptor - epInfo[0].maxPktSize = udd->bMaxPacketSize0; - - // Assign new address to the device - rcode = pUsb->setAddr(0, 0, bAddress); - - if(rcode) { - p->lowspeed = false; - addrPool.FreeAddress(bAddress); - bAddress = 0; - USBTRACE2("setAddr:", rcode); - return rcode; - } - - USBTRACE2("Addr:", bAddress); - - p->lowspeed = false; - - p = addrPool.GetUsbDevicePtr(bAddress); - - if(!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - p->lowspeed = lowspeed; - - num_of_conf = udd->bNumConfigurations; - - // Assign epInfo to epinfo pointer - rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); - - if(rcode) - goto FailSetDevTblEntry; - - USBTRACE2("NC:", num_of_conf); - - for(uint8_t i = 0; i < num_of_conf; i++) { - ConfigDescParser< USB_CLASS_COM_AND_CDC_CTRL, - CDC_SUBCLASS_ACM, - CDC_PROTOCOL_ITU_T_V_250, - CP_MASK_COMPARE_CLASS | - CP_MASK_COMPARE_SUBCLASS | - CP_MASK_COMPARE_PROTOCOL > CdcControlParser(this); - - ConfigDescParser CdcDataParser(this); - - rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcControlParser); - - if(rcode) - goto FailGetConfDescr; - - rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcDataParser); - - if(rcode) - goto FailGetConfDescr; - - if(bNumEP > 1) - break; - } // for - - if(bNumEP < 4) - return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - - // Assign epInfo to epinfo pointer - rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); - - USBTRACE2("Conf:", bConfNum); - - // Set Configuration Value - rcode = pUsb->setConf(bAddress, 0, bConfNum); - - if(rcode) - goto FailSetConfDescr; - - // Set up features status - _enhanced_status = enhanced_features(); - half_duplex(false); - autoflowRTS(false); - autoflowDSR(false); - autoflowXON(false); - wide(false); // Always false, because this is only available in custom mode. - rcode = pAsync->OnInit(this); - - if(rcode) - goto FailOnInit; - - USBTRACE("ACM configured\r\n"); - - ready = true; - - //bPollEnable = true; - - //USBTRACE("Poll enabled\r\n"); - return 0; - -FailGetDevDescr: -#ifdef DEBUG_USB_HOST - NotifyFailGetDevDescr(); - goto Fail; -#endif - -FailSetDevTblEntry: -#ifdef DEBUG_USB_HOST - NotifyFailSetDevTblEntry(); - goto Fail; -#endif - -FailGetConfDescr: -#ifdef DEBUG_USB_HOST - NotifyFailGetConfDescr(); - goto Fail; -#endif - -FailSetConfDescr: -#ifdef DEBUG_USB_HOST - NotifyFailSetConfDescr(); - goto Fail; -#endif - -FailOnInit: -#ifdef DEBUG_USB_HOST - USBTRACE("OnInit:"); -#endif - -#ifdef DEBUG_USB_HOST -Fail: - NotifyFail(rcode); -#endif - Release(); - return rcode; -} - -void ACM::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) { - //ErrorMessage (PSTR("Conf.Val"), conf); - //ErrorMessage (PSTR("Iface Num"), iface); - //ErrorMessage (PSTR("Alt.Set"), alt); - - bConfNum = conf; - - uint8_t index; - - if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) - index = epInterruptInIndex; - else - if((pep->bmAttributes & 0x02) == 2) - index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex; - else - return; - - // Fill in the endpoint info structure - epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); - epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; - epInfo[index].epAttribs = 0; - - bNumEP++; - - PrintEndpointDescriptor(pep); -} - -uint8_t ACM::Release() { - ready = false; - pUsb->GetAddressPool().FreeAddress(bAddress); - - bControlIface = 0; - bDataIface = 0; - bNumEP = 1; - - bAddress = 0; - qNextPollTime = 0; - bPollEnable = false; - return 0; -} - -uint8_t ACM::Poll() { - uint8_t rcode = 0; - - if(!bPollEnable) - return 0; - - return rcode; -} - -uint8_t ACM::RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr) { - return pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr); -} - -uint8_t ACM::SndData(uint16_t nbytes, uint8_t *dataptr) { - return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, nbytes, dataptr); -} - -uint8_t ACM::SetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr) { - return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SET_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, nbytes, nbytes, dataptr, NULL)); -} - -uint8_t ACM::GetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr) { - return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCIN, CDC_GET_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, nbytes, nbytes, dataptr, NULL)); -} - -uint8_t ACM::ClearCommFeature(uint16_t fid) { - return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_CLEAR_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, 0, 0, NULL, NULL)); -} - -uint8_t ACM::SetLineCoding(const LINE_CODING *dataptr) { - return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SET_LINE_CODING, 0x00, 0x00, bControlIface, sizeof (LINE_CODING), sizeof (LINE_CODING), (uint8_t*)dataptr, NULL)); -} - -uint8_t ACM::GetLineCoding(LINE_CODING *dataptr) { - return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCIN, CDC_GET_LINE_CODING, 0x00, 0x00, bControlIface, sizeof (LINE_CODING), sizeof (LINE_CODING), (uint8_t*)dataptr, NULL)); -} - -uint8_t ACM::SetControlLineState(uint8_t state) { - return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SET_CONTROL_LINE_STATE, state, 0, bControlIface, 0, 0, NULL, NULL)); -} - -uint8_t ACM::SendBreak(uint16_t duration) { - return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SEND_BREAK, (duration & 0xff), (duration >> 8), bControlIface, 0, 0, NULL, NULL)); -} - -void ACM::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) { - Notify(PSTR("Endpoint descriptor:"), 0x80); - Notify(PSTR("\r\nLength:\t\t"), 0x80); - D_PrintHex (ep_ptr->bLength, 0x80); - Notify(PSTR("\r\nType:\t\t"), 0x80); - D_PrintHex (ep_ptr->bDescriptorType, 0x80); - Notify(PSTR("\r\nAddress:\t"), 0x80); - D_PrintHex (ep_ptr->bEndpointAddress, 0x80); - Notify(PSTR("\r\nAttributes:\t"), 0x80); - D_PrintHex (ep_ptr->bmAttributes, 0x80); - Notify(PSTR("\r\nMaxPktSize:\t"), 0x80); - D_PrintHex (ep_ptr->wMaxPacketSize, 0x80); - Notify(PSTR("\r\nPoll Intrv:\t"), 0x80); - D_PrintHex (ep_ptr->bInterval, 0x80); - Notify(PSTR("\r\n"), 0x80); -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcacm.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcacm.h deleted file mode 100644 index 2a38524d8c..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcacm.h +++ /dev/null @@ -1,252 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ -#if !defined(__CDCACM_H__) -#define __CDCACM_H__ - -#include "Usb.h" - -#define bmREQ_CDCOUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE -#define bmREQ_CDCIN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE - -// CDC Subclass Constants -#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_CAPI 0x05 // CAPI Control Model -#define CDC_SUBCLASS_ETHERNET 0x06 // Ethernet Network Control Model -#define CDC_SUBCLASS_ATM 0x07 // ATM Network Control Model -#define CDC_SUBCLASS_WIRELESS_HANDSET 0x08 // Wireless Handset Control Model -#define CDC_SUBCLASS_DEVICE_MANAGEMENT 0x09 // Device Management -#define CDC_SUBCLASS_MOBILE_DIRECT_LINE 0x0A // Mobile Direct Line Model -#define CDC_SUBCLASS_OBEX 0x0B // OBEX -#define CDC_SUBCLASS_ETHERNET_EMU 0x0C // Ethernet Emulation Model - -// Communication Interface Class Control Protocol Codes -#define CDC_PROTOCOL_ITU_T_V_250 0x01 // AT Commands defined by ITU-T V.250 -#define CDC_PROTOCOL_PCCA_101 0x02 // AT Commands defined by PCCA-101 -#define CDC_PROTOCOL_PCCA_101_O 0x03 // AT Commands defined by PCCA-101 & Annex O -#define CDC_PROTOCOL_GSM_7_07 0x04 // AT Commands defined by GSM 7.07 -#define CDC_PROTOCOL_3GPP_27_07 0x05 // AT Commands defined by 3GPP 27.007 -#define CDC_PROTOCOL_C_S0017_0 0x06 // AT Commands defined by TIA for CDMA -#define CDC_PROTOCOL_USB_EEM 0x07 // Ethernet Emulation Model - -// CDC Commands defined by CDC 1.2 -#define CDC_SEND_ENCAPSULATED_COMMAND 0x00 -#define CDC_GET_ENCAPSULATED_RESPONSE 0x01 - -// CDC Commands defined by PSTN 1.2 -#define CDC_SET_COMM_FEATURE 0x02 -#define CDC_GET_COMM_FEATURE 0x03 -#define CDC_CLEAR_COMM_FEATURE 0x04 -#define CDC_SET_AUX_LINE_STATE 0x10 -#define CDC_SET_HOOK_STATE 0x11 -#define CDC_PULSE_SETUP 0x12 -#define CDC_SEND_PULSE 0x13 -#define CDC_SET_PULSE_TIME 0x14 -#define CDC_RING_AUX_JACK 0x15 -#define CDC_SET_LINE_CODING 0x20 -#define CDC_GET_LINE_CODING 0x21 -#define CDC_SET_CONTROL_LINE_STATE 0x22 -#define CDC_SEND_BREAK 0x23 -#define CDC_SET_RINGER_PARMS 0x30 -#define CDC_GET_RINGER_PARMS 0x31 -#define CDC_SET_OPERATION_PARMS 0x32 -#define CDC_GET_OPERATION_PARMS 0x33 -#define CDC_SET_LINE_PARMS 0x34 -#define CDC_GET_LINE_PARMS 0x35 -#define CDC_DIAL_DIGITS 0x36 - -//Class-Specific Notification Codes -#define NETWORK_CONNECTION 0x00 -#define RESPONSE_AVAILABLE 0x01 -#define AUX_JACK_HOOK_STATE 0x08 -#define RING_DETECT 0x09 -#define SERIAL_STATE 0x20 -#define CALL_STATE_CHANGE 0x28 -#define LINE_STATE_CHANGE 0x29 -#define CONNECTION_SPEED_CHANGE 0x2a - -// CDC Functional Descriptor Structures - -typedef struct { - uint8_t bFunctionLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubtype; - uint8_t bmCapabilities; - uint8_t bDataInterface; -} CALL_MGMNT_FUNC_DESCR; - -typedef struct { - uint8_t bFunctionLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubtype; - uint8_t bmCapabilities; -} ACM_FUNC_DESCR, DLM_FUNC_DESCR, TEL_OPER_MODES_FUNC_DESCR, -TEL_CALL_STATE_REP_CPBL_FUNC_DESCR; - -typedef struct { - uint8_t bFunctionLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubtype; - uint8_t bRingerVolSteps; - uint8_t bNumRingerPatterns; -} TEL_RINGER_FUNC_DESCR; - -typedef struct { - uint32_t dwDTERate; // Data Terminal Rate in bits per second - uint8_t bCharFormat; // 0 - 1 stop bit, 1 - 1.5 stop bits, 2 - 2 stop bits - uint8_t bParityType; // 0 - None, 1 - Odd, 2 - Even, 3 - Mark, 4 - Space - uint8_t bDataBits; // Data bits (5, 6, 7, 8 or 16) -} LINE_CODING; - -typedef struct { - uint8_t bmRequestType; // 0xa1 for class-specific notifications - uint8_t bNotification; - uint16_t wValue; - uint16_t wIndex; - uint16_t wLength; - uint16_t bmState; //UART state bitmap for SERIAL_STATE, other notifications variable length -} CLASS_NOTIFICATION; - -class ACM; - -class CDCAsyncOper { -public: - - virtual uint8_t OnInit(ACM *pacm) { - return 0; - }; - //virtual void OnDataRcvd(ACM *pacm, uint8_t nbytes, uint8_t *dataptr) = 0; - //virtual void OnDisconnected(ACM *pacm) = 0; -}; - -/** - * This structure is used to report the extended capabilities of the connected device. - * It is also used to report the current status. - * Regular CDC-ACM reports all as false. - */ -typedef struct { - - union { - uint8_t tty; - - struct { - bool enhanced : 1; // Do we have the ability to set/clear any features? - // Status and 8th bit in data stream. - // Presence only indicates feature is available, but this isn't used for CDC-ACM. - bool wide : 1; - bool autoflow_RTS : 1; // Has autoflow on RTS/CTS - bool autoflow_DSR : 1; // Has autoflow on DTR/DSR - bool autoflow_XON : 1; // Has autoflow XON/XOFF - bool half_duplex : 1; // Has half-duplex capability. - } __attribute__((packed)); - }; -} tty_features; - -#define ACM_MAX_ENDPOINTS 4 - -class ACM : public USBDeviceConfig, public UsbConfigXtracter { -protected: - static const uint8_t epDataInIndex; // DataIn endpoint index - static const uint8_t epDataOutIndex; // DataOUT endpoint index - static const uint8_t epInterruptInIndex; // InterruptIN endpoint index - - USB *pUsb; - CDCAsyncOper *pAsync; - uint8_t bAddress; - uint8_t bConfNum; // configuration number - uint8_t bControlIface; // Control interface value - uint8_t bDataIface; // Data interface value - uint8_t bNumEP; // total number of EP in the configuration - uint32_t qNextPollTime; // next poll time - volatile bool bPollEnable; // poll enable flag - volatile bool ready; //device ready indicator - tty_features _enhanced_status; // current status - - EpInfo epInfo[ACM_MAX_ENDPOINTS]; - - void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); - -public: - ACM(USB *pusb, CDCAsyncOper *pasync); - - uint8_t SetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr); - uint8_t GetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr); - uint8_t ClearCommFeature(uint16_t fid); - uint8_t SetLineCoding(const LINE_CODING *dataptr); - uint8_t GetLineCoding(LINE_CODING *dataptr); - uint8_t SetControlLineState(uint8_t state); - uint8_t SendBreak(uint16_t duration); - uint8_t GetNotif(uint16_t *bytes_rcvd, uint8_t *dataptr); - - // Methods for receiving and sending data - uint8_t RcvData(uint16_t *nbytesptr, uint8_t *dataptr); - uint8_t SndData(uint16_t nbytes, uint8_t *dataptr); - - // USBDeviceConfig implementation - uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); - uint8_t Release(); - uint8_t Poll(); - - bool available(void) { - return false; - }; - - virtual uint8_t GetAddress() { - return bAddress; - }; - - virtual bool isReady() { - return ready; - }; - - virtual tty_features enhanced_status(void) { - return _enhanced_status; - }; - - virtual tty_features enhanced_features(void) { - tty_features rv; - rv.enhanced = false; - rv.autoflow_RTS = false; - rv.autoflow_DSR = false; - rv.autoflow_XON = false; - rv.half_duplex = false; - rv.wide = false; - return rv; - }; - - virtual void autoflowRTS(bool s) { - }; - - virtual void autoflowDSR(bool s) { - }; - - virtual void autoflowXON(bool s) { - }; - - virtual void half_duplex(bool s) { - }; - - virtual void wide(bool s) { - }; - - // UsbConfigXtracter implementation - void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); -}; - -#endif // __CDCACM_H__ diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcftdi.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcftdi.cpp deleted file mode 100644 index 80d21d16ec..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcftdi.cpp +++ /dev/null @@ -1,334 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ -#include "cdcftdi.h" - -const uint8_t FTDI::epDataInIndex = 1; -const uint8_t FTDI::epDataOutIndex = 2; -const uint8_t FTDI::epInterruptInIndex = 3; - -FTDI::FTDI(USB *p, FTDIAsyncOper *pasync) : -pAsync(pasync), -pUsb(p), -bAddress(0), -bNumEP(1), -wFTDIType(0) { - for(uint8_t i = 0; i < FTDI_MAX_ENDPOINTS; i++) { - epInfo[i].epAddr = 0; - epInfo[i].maxPktSize = (i) ? 0 : 8; - epInfo[i].epAttribs = 0; - epInfo[i].bmNakPower = (i==epDataInIndex) ? USB_NAK_NOWAIT: USB_NAK_MAX_POWER; - } - if(pUsb) - pUsb->RegisterDeviceClass(this); -} - -uint8_t FTDI::Init(uint8_t parent, uint8_t port, bool lowspeed) { - const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR); - - uint8_t buf[constBufSize]; - USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); - uint8_t rcode; - UsbDevice *p = NULL; - EpInfo *oldep_ptr = NULL; - - uint8_t num_of_conf; // number of configurations - - AddressPool &addrPool = pUsb->GetAddressPool(); - - USBTRACE("FTDI Init\r\n"); - - if(bAddress) - return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; - - // Get pointer to pseudo device with address 0 assigned - p = addrPool.GetUsbDevicePtr(0); - - if(!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - if(!p->epinfo) { - USBTRACE("epinfo\r\n"); - return USB_ERROR_EPINFO_IS_NULL; - } - - // Save old pointer to EP_RECORD of address 0 - oldep_ptr = p->epinfo; - - // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence - p->epinfo = epInfo; - - p->lowspeed = lowspeed; - - // Get device descriptor - rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), buf); - - // Restore p->epinfo - p->epinfo = oldep_ptr; - - if(rcode) - goto FailGetDevDescr; - if(udd->idVendor != FTDI_VID || udd->idProduct != FTDI_PID) - return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - - // Save type of FTDI chip - wFTDIType = udd->bcdDevice; - - // Allocate new address according to device class - bAddress = addrPool.AllocAddress(parent, false, port); - - if(!bAddress) - return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; - - // Extract Max Packet Size from the device descriptor - epInfo[0].maxPktSize = udd->bMaxPacketSize0; - - // Assign new address to the device - rcode = pUsb->setAddr(0, 0, bAddress); - - if(rcode) { - p->lowspeed = false; - addrPool.FreeAddress(bAddress); - bAddress = 0; - USBTRACE2("setAddr:", rcode); - return rcode; - } - - USBTRACE2("Addr:", bAddress); - - p->lowspeed = false; - - p = addrPool.GetUsbDevicePtr(bAddress); - - if(!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - p->lowspeed = lowspeed; - - num_of_conf = udd->bNumConfigurations; - - // Assign epInfo to epinfo pointer - rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); - - if(rcode) - goto FailSetDevTblEntry; - - USBTRACE2("NC:", num_of_conf); - - for(uint8_t i = 0; i < num_of_conf; i++) { - HexDumper HexDump; - ConfigDescParser < 0xFF, 0xFF, 0xFF, CP_MASK_COMPARE_ALL> confDescrParser(this); - - rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump); - - if(rcode) - goto FailGetConfDescr; - - rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); - - if(rcode) - goto FailGetConfDescr; - - if(bNumEP > 1) - break; - } // for - - if(bNumEP < 2) - return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - - USBTRACE2("NumEP:", bNumEP); - - // Assign epInfo to epinfo pointer - rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); - - USBTRACE2("Conf:", bConfNum); - - // Set Configuration Value - rcode = pUsb->setConf(bAddress, 0, bConfNum); - - if(rcode) - goto FailSetConfDescr; - - rcode = pAsync->OnInit(this); - - if(rcode) - goto FailOnInit; - - USBTRACE("FTDI configured\r\n"); - - bPollEnable = true; - return 0; - -FailGetDevDescr: -#ifdef DEBUG_USB_HOST - NotifyFailGetDevDescr(); - goto Fail; -#endif - -FailSetDevTblEntry: -#ifdef DEBUG_USB_HOST - NotifyFailSetDevTblEntry(); - goto Fail; -#endif - -FailGetConfDescr: -#ifdef DEBUG_USB_HOST - NotifyFailGetConfDescr(); - goto Fail; -#endif - -FailSetConfDescr: -#ifdef DEBUG_USB_HOST - NotifyFailSetConfDescr(); - goto Fail; -#endif - -FailOnInit: -#ifdef DEBUG_USB_HOST - USBTRACE("OnInit:"); - -Fail: - NotifyFail(rcode); -#endif - Release(); - return rcode; -} - -void FTDI::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) { - ErrorMessage (PSTR("Conf.Val"), conf); - ErrorMessage (PSTR("Iface Num"), iface); - ErrorMessage (PSTR("Alt.Set"), alt); - - bConfNum = conf; - - uint8_t index; - - if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) - index = epInterruptInIndex; - else - if((pep->bmAttributes & 0x02) == 2) - index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex; - else - return; - - // Fill in the endpoint info structure - epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); - epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; - epInfo[index].epAttribs = 0; - - bNumEP++; - - PrintEndpointDescriptor(pep); -} - -uint8_t FTDI::Release() { - pUsb->GetAddressPool().FreeAddress(bAddress); - - bAddress = 0; - bNumEP = 1; - qNextPollTime = 0; - bPollEnable = false; - return pAsync->OnRelease(this); -} - -uint8_t FTDI::Poll() { - uint8_t rcode = 0; - - //if (!bPollEnable) - // return 0; - - //if (qNextPollTime <= millis()) - //{ - // USB_HOST_SERIAL.println(bAddress, HEX); - - // qNextPollTime = millis() + 100; - //} - return rcode; -} - -uint8_t FTDI::SetBaudRate(uint32_t baud) { - uint16_t baud_value, baud_index = 0; - uint32_t divisor3; - - divisor3 = 48000000 / 2 / baud; // divisor shifted 3 bits to the left - - if(wFTDIType == FT232AM) { - if((divisor3 & 0x7) == 7) - divisor3++; // round x.7/8 up to x+1 - - baud_value = divisor3 >> 3; - divisor3 &= 0x7; - - if(divisor3 == 1) baud_value |= 0xc000; - else // 0.125 - if(divisor3 >= 4) baud_value |= 0x4000; - else // 0.5 - if(divisor3 != 0) baud_value |= 0x8000; // 0.25 - if(baud_value == 1) baud_value = 0; /* special case for maximum baud rate */ - } else { - static const unsigned char divfrac [8] = {0, 3, 2, 0, 1, 1, 2, 3}; - static const unsigned char divindex[8] = {0, 0, 0, 1, 0, 1, 1, 1}; - - baud_value = divisor3 >> 3; - baud_value |= divfrac [divisor3 & 0x7] << 14; - baud_index = divindex[divisor3 & 0x7]; - - /* Deal with special cases for highest baud rates. */ - if(baud_value == 1) baud_value = 0; - else // 1.0 - if(baud_value == 0x4001) baud_value = 1; // 1.5 - } - USBTRACE2("baud_value:", baud_value); - USBTRACE2("baud_index:", baud_index); - return pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_SET_BAUD_RATE, baud_value & 0xff, baud_value >> 8, baud_index, 0, 0, NULL, NULL); -} - -uint8_t FTDI::SetModemControl(uint16_t signal) { - return pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_MODEM_CTRL, signal & 0xff, signal >> 8, 0, 0, 0, NULL, NULL); -} - -uint8_t FTDI::SetFlowControl(uint8_t protocol, uint8_t xon, uint8_t xoff) { - return pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_SET_FLOW_CTRL, xon, xoff, protocol << 8, 0, 0, NULL, NULL); -} - -uint8_t FTDI::SetData(uint16_t databm) { - return pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_SET_DATA, databm & 0xff, databm >> 8, 0, 0, 0, NULL, NULL); -} - -uint8_t FTDI::RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr) { - return pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr); -} - -uint8_t FTDI::SndData(uint16_t nbytes, uint8_t *dataptr) { - return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, nbytes, dataptr); -} - -void FTDI::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) { - Notify(PSTR("Endpoint descriptor:"), 0x80); - Notify(PSTR("\r\nLength:\t\t"), 0x80); - D_PrintHex (ep_ptr->bLength, 0x80); - Notify(PSTR("\r\nType:\t\t"), 0x80); - D_PrintHex (ep_ptr->bDescriptorType, 0x80); - Notify(PSTR("\r\nAddress:\t"), 0x80); - D_PrintHex (ep_ptr->bEndpointAddress, 0x80); - Notify(PSTR("\r\nAttributes:\t"), 0x80); - D_PrintHex (ep_ptr->bmAttributes, 0x80); - Notify(PSTR("\r\nMaxPktSize:\t"), 0x80); - D_PrintHex (ep_ptr->wMaxPacketSize, 0x80); - Notify(PSTR("\r\nPoll Intrv:\t"), 0x80); - D_PrintHex (ep_ptr->bInterval, 0x80); - Notify(PSTR("\r\n"), 0x80); -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcftdi.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcftdi.h deleted file mode 100644 index b731252629..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcftdi.h +++ /dev/null @@ -1,145 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ -#if !defined(__CDCFTDI_H__) -#define __CDCFTDI_H__ - -#include "Usb.h" - -#define bmREQ_FTDI_OUT 0x40 -#define bmREQ_FTDI_IN 0xc0 - -//#define bmREQ_FTDI_OUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE -//#define bmREQ_FTDI_IN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE - -#define FTDI_VID 0x0403 // FTDI VID -#define FTDI_PID 0x6001 // FTDI PID - -#define FT232AM 0x0200 -#define FT232BM 0x0400 -#define FT2232 0x0500 -#define FT232R 0x0600 - -// Commands -#define FTDI_SIO_RESET 0 /* Reset the port */ -#define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ -#define FTDI_SIO_SET_FLOW_CTRL 2 /* Set flow control register */ -#define FTDI_SIO_SET_BAUD_RATE 3 /* Set baud rate */ -#define FTDI_SIO_SET_DATA 4 /* Set the data characteristics of the port */ -#define FTDI_SIO_GET_MODEM_STATUS 5 /* Retrieve current value of modem status register */ -#define FTDI_SIO_SET_EVENT_CHAR 6 /* Set the event character */ -#define FTDI_SIO_SET_ERROR_CHAR 7 /* Set the error character */ - -#define FTDI_SIO_RESET_SIO 0 -#define FTDI_SIO_RESET_PURGE_RX 1 -#define FTDI_SIO_RESET_PURGE_TX 2 - -#define FTDI_SIO_SET_DATA_PARITY_NONE (0x0 << 8 ) -#define FTDI_SIO_SET_DATA_PARITY_ODD (0x1 << 8 ) -#define FTDI_SIO_SET_DATA_PARITY_EVEN (0x2 << 8 ) -#define FTDI_SIO_SET_DATA_PARITY_MARK (0x3 << 8 ) -#define FTDI_SIO_SET_DATA_PARITY_SPACE (0x4 << 8 ) -#define FTDI_SIO_SET_DATA_STOP_BITS_1 (0x0 << 11) -#define FTDI_SIO_SET_DATA_STOP_BITS_15 (0x1 << 11) -#define FTDI_SIO_SET_DATA_STOP_BITS_2 (0x2 << 11) -#define FTDI_SIO_SET_BREAK (0x1 << 14) - -#define FTDI_SIO_SET_DTR_MASK 0x1 -#define FTDI_SIO_SET_DTR_HIGH ( 1 | ( FTDI_SIO_SET_DTR_MASK << 8)) -#define FTDI_SIO_SET_DTR_LOW ( 0 | ( FTDI_SIO_SET_DTR_MASK << 8)) -#define FTDI_SIO_SET_RTS_MASK 0x2 -#define FTDI_SIO_SET_RTS_HIGH ( 2 | ( FTDI_SIO_SET_RTS_MASK << 8 )) -#define FTDI_SIO_SET_RTS_LOW ( 0 | ( FTDI_SIO_SET_RTS_MASK << 8 )) - -#define FTDI_SIO_DISABLE_FLOW_CTRL 0x0 -#define FTDI_SIO_RTS_CTS_HS (0x1 << 8) -#define FTDI_SIO_DTR_DSR_HS (0x2 << 8) -#define FTDI_SIO_XON_XOFF_HS (0x4 << 8) - -#define FTDI_SIO_CTS_MASK 0x10 -#define FTDI_SIO_DSR_MASK 0x20 -#define FTDI_SIO_RI_MASK 0x40 -#define FTDI_SIO_RLSD_MASK 0x80 - -class FTDI; - -class FTDIAsyncOper { -public: - - virtual uint8_t OnInit(FTDI *pftdi) { - return 0; - }; - - virtual uint8_t OnRelease(FTDI *pftdi) { - return 0; - }; -}; - - -// Only single port chips are currently supported by the library, -// so only three endpoints are allocated. -#define FTDI_MAX_ENDPOINTS 3 - -class FTDI : public USBDeviceConfig, public UsbConfigXtracter { - static const uint8_t epDataInIndex; // DataIn endpoint index - static const uint8_t epDataOutIndex; // DataOUT endpoint index - static const uint8_t epInterruptInIndex; // InterruptIN endpoint index - - FTDIAsyncOper *pAsync; - USB *pUsb; - uint8_t bAddress; - uint8_t bConfNum; // configuration number - uint8_t bNumIface; // number of interfaces in the configuration - uint8_t bNumEP; // total number of EP in the configuration - uint32_t qNextPollTime; // next poll time - bool bPollEnable; // poll enable flag - uint16_t wFTDIType; // Type of FTDI chip - - EpInfo epInfo[FTDI_MAX_ENDPOINTS]; - - void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); - -public: - FTDI(USB *pusb, FTDIAsyncOper *pasync); - - uint8_t SetBaudRate(uint32_t baud); - uint8_t SetModemControl(uint16_t control); - uint8_t SetFlowControl(uint8_t protocol, uint8_t xon = 0x11, uint8_t xoff = 0x13); - uint8_t SetData(uint16_t databm); - - // Methods for recieving and sending data - uint8_t RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr); - uint8_t SndData(uint16_t nbytes, uint8_t *dataptr); - - // USBDeviceConfig implementation - uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); - uint8_t Release(); - uint8_t Poll(); - - virtual uint8_t GetAddress() { - return bAddress; - }; - - // UsbConfigXtracter implementation - void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); - - virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) { - return (vid == FTDI_VID && pid == FTDI_PID); - } - -}; - -#endif // __CDCFTDI_H__ diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcprolific.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcprolific.cpp deleted file mode 100644 index eceb1df9f3..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcprolific.cpp +++ /dev/null @@ -1,247 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ -#include "cdcprolific.h" - -PL2303::PL2303(USB *p, CDCAsyncOper *pasync) : -ACM(p, pasync), -wPLType(0) { -} - -uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) { - const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR); - - uint8_t buf[constBufSize]; - USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); - uint8_t rcode; - UsbDevice *p = NULL; - EpInfo *oldep_ptr = NULL; - uint8_t num_of_conf; // number of configurations -#ifdef PL2303_COMPAT - enum pl2303_type pltype = unknown; -#endif - - AddressPool &addrPool = pUsb->GetAddressPool(); - - USBTRACE("PL Init\r\n"); - - if(bAddress) - return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; - - // Get pointer to pseudo device with address 0 assigned - p = addrPool.GetUsbDevicePtr(0); - - if(!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - if(!p->epinfo) { - USBTRACE("epinfo\r\n"); - return USB_ERROR_EPINFO_IS_NULL; - } - - // Save old pointer to EP_RECORD of address 0 - oldep_ptr = p->epinfo; - - // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence - p->epinfo = epInfo; - - p->lowspeed = lowspeed; - - // Get device descriptor - rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); - - // Restore p->epinfo - p->epinfo = oldep_ptr; - - if(rcode) - goto FailGetDevDescr; - - if(udd->idVendor != PL_VID && CHECK_PID(udd->idProduct)) - return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - - /* determine chip variant */ -#ifdef PL2303_COMPAT - if(udd->bDeviceClass == 0x02 ) - pltype = type_0; - else if(udd->bMaxPacketSize0 == 0x40 ) - pltype = rev_HX; - else if(udd->bDeviceClass == 0x00) - pltype = type_1; - else if(udd->bDeviceClass == 0xff) - pltype = type_1; -#endif - - // Save type of PL chip - wPLType = udd->bcdDevice; - - // Allocate new address according to device class - bAddress = addrPool.AllocAddress(parent, false, port); - - if(!bAddress) - return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; - - // Extract Max Packet Size from the device descriptor - epInfo[0].maxPktSize = udd->bMaxPacketSize0; - - // Assign new address to the device - rcode = pUsb->setAddr(0, 0, bAddress); - - if(rcode) { - p->lowspeed = false; - addrPool.FreeAddress(bAddress); - bAddress = 0; - USBTRACE2("setAddr:", rcode); - return rcode; - } - - USBTRACE2("Addr:", bAddress); - - p->lowspeed = false; - - p = addrPool.GetUsbDevicePtr(bAddress); - - if(!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - p->lowspeed = lowspeed; - - num_of_conf = udd->bNumConfigurations; - - // Assign epInfo to epinfo pointer - rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); - - if(rcode) - goto FailSetDevTblEntry; - - USBTRACE2("NC:", num_of_conf); - - for(uint8_t i = 0; i < num_of_conf; i++) { - HexDumper HexDump; - ConfigDescParser < 0xFF, 0, 0, CP_MASK_COMPARE_CLASS> confDescrParser(this); - - rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump); - - if(rcode) - goto FailGetConfDescr; - - rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); - - if(rcode) - goto FailGetConfDescr; - - if(bNumEP > 1) - break; - } // for - - if(bNumEP < 2) - return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - - // Assign epInfo to epinfo pointer - rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); - - USBTRACE2("Conf:", bConfNum); - - // Set Configuration Value - rcode = pUsb->setConf(bAddress, 0, bConfNum); - - if(rcode) - goto FailSetConfDescr; - -#ifdef PL2303_COMPAT - /* Shamanic dance - sending Prolific init data as-is */ - vendorRead( 0x84, 0x84, 0, buf ); - vendorWrite( 0x04, 0x04, 0 ); - vendorRead( 0x84, 0x84, 0, buf ); - vendorRead( 0x83, 0x83, 0, buf ); - vendorRead( 0x84, 0x84, 0, buf ); - vendorWrite( 0x04, 0x04, 1 ); - vendorRead( 0x84, 0x84, 0, buf); - vendorRead( 0x83, 0x83, 0, buf); - vendorWrite( 0, 0, 1 ); - vendorWrite( 1, 0, 0 ); - if( pltype == rev_HX ) { - vendorWrite( 2, 0, 0x44 ); - vendorWrite( 0x06, 0x06, 0 ); // From W7 init - } - else { - vendorWrite( 2, 0, 0x24 ); - } - /* Shamanic dance end */ -#endif - /* Calling post-init callback */ - rcode = pAsync->OnInit(this); - - if(rcode) - goto FailOnInit; - - USBTRACE("PL configured\r\n"); - - //bPollEnable = true; - ready = true; - return 0; - -FailGetDevDescr: -#ifdef DEBUG_USB_HOST - NotifyFailGetDevDescr(); - goto Fail; -#endif - -FailSetDevTblEntry: -#ifdef DEBUG_USB_HOST - NotifyFailSetDevTblEntry(); - goto Fail; -#endif - -FailGetConfDescr: -#ifdef DEBUG_USB_HOST - NotifyFailGetConfDescr(); - goto Fail; -#endif - -FailSetConfDescr: -#ifdef DEBUG_USB_HOST - NotifyFailSetConfDescr(); - goto Fail; -#endif - -FailOnInit: -#ifdef DEBUG_USB_HOST - USBTRACE("OnInit:"); -#endif - -#ifdef DEBUG_USB_HOST -Fail: - NotifyFail(rcode); -#endif - Release(); - return rcode; -} - -//uint8_t PL::Poll() -//{ -// uint8_t rcode = 0; -// -// //if (!bPollEnable) -// // return 0; -// -// //if (qNextPollTime <= millis()) -// //{ -// // USB_HOST_SERIAL.println(bAddress, HEX); -// -// // qNextPollTime = millis() + 100; -// //} -// return rcode; -//} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcprolific.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcprolific.h deleted file mode 100644 index 4991466410..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcprolific.h +++ /dev/null @@ -1,159 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ -#if !defined(__CDCPROLIFIC_H__) -#define __CDCPROLIFIC_H__ - -#include "cdcacm.h" - -//#define PL2303_COMPAT // Uncomment it if you have compatibility problems - -#define PL_VID 0x067B -#define CHECK_PID(pid) ( pid != 0x2303 && pid != 0x0609 ) - -//#define PL_PID 0x0609 - -#define PROLIFIC_REV_H 0x0202 -#define PROLIFIC_REV_X 0x0300 -#define PROLIFIC_REV_HX_CHIP_D 0x0400 -#define PROLIFIC_REV_1 0x0001 - -#define kXOnChar '\x11' -#define kXOffChar '\x13' - -#define SPECIAL_SHIFT (5) -#define SPECIAL_MASK ((1<ctrlReq(bAddress, 0, VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, val_lo, val_hi, index, 1, 1, buf, NULL )); -} - -/* vendor write request */ -inline uint8_t PL2303::vendorWrite( uint8_t val_lo, uint8_t val_hi, uint8_t index ) -{ - return( pUsb->ctrlReq(bAddress, 0, VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, val_lo, val_hi, index, 0, 0, NULL, NULL )); -} -#endif - -#endif // __CDCPROLIFIC_H__ diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/confdescparser.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/confdescparser.h deleted file mode 100644 index a6806f2ea7..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/confdescparser.h +++ /dev/null @@ -1,213 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ -#if !defined(_usb_h_) || defined(__CONFDESCPARSER_H__) -#error "Never include confdescparser.h directly; include Usb.h instead" -#else - -#define __CONFDESCPARSER_H__ - -class UsbConfigXtracter { -public: - //virtual void ConfigXtract(const USB_CONFIGURATION_DESCRIPTOR *conf) = 0; - //virtual void InterfaceXtract(uint8_t conf, const USB_INTERFACE_DESCRIPTOR *iface) = 0; - - virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep) { - }; -}; - -#define CP_MASK_COMPARE_CLASS 1 -#define CP_MASK_COMPARE_SUBCLASS 2 -#define CP_MASK_COMPARE_PROTOCOL 4 -#define CP_MASK_COMPARE_ALL 7 - -// Configuration Descriptor Parser Class Template - -template -class ConfigDescParser : public USBReadParser { - UsbConfigXtracter *theXtractor; - MultiValueBuffer theBuffer; - MultiByteValueParser valParser; - ByteSkipper theSkipper; - uint8_t varBuffer[16 /*sizeof(USB_CONFIGURATION_DESCRIPTOR)*/]; - - uint8_t stateParseDescr; // ParseDescriptor state - - uint8_t dscrLen; // Descriptor length - uint8_t dscrType; // Descriptor type - - bool isGoodInterface; // Apropriate interface flag - uint8_t confValue; // Configuration value - uint8_t protoValue; // Protocol value - uint8_t ifaceNumber; // Interface number - uint8_t ifaceAltSet; // Interface alternate settings - - bool UseOr; - bool ParseDescriptor(uint8_t **pp, uint16_t *pcntdn); - void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc); - -public: - - void SetOR(void) { - UseOr = true; - } - ConfigDescParser(UsbConfigXtracter *xtractor); - void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset); -}; - -template -ConfigDescParser::ConfigDescParser(UsbConfigXtracter *xtractor) : -theXtractor(xtractor), -stateParseDescr(0), -dscrLen(0), -dscrType(0), -UseOr(false) { - theBuffer.pValue = varBuffer; - valParser.Initialize(&theBuffer); - theSkipper.Initialize(&theBuffer); -}; - -template -void ConfigDescParser::Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset) { - uint16_t cntdn = (uint16_t)len; - uint8_t *p = (uint8_t*)pbuf; - - while(cntdn) - if(!ParseDescriptor(&p, &cntdn)) - return; -} - -/* Parser for the configuration descriptor. Takes values for class, subclass, protocol fields in interface descriptor and - compare masks for them. When the match is found, calls EndpointXtract passing buffer containing endpoint descriptor */ -template -bool ConfigDescParser::ParseDescriptor(uint8_t **pp, uint16_t *pcntdn) { - USB_CONFIGURATION_DESCRIPTOR* ucd = reinterpret_cast(varBuffer); - USB_INTERFACE_DESCRIPTOR* uid = reinterpret_cast(varBuffer); - switch(stateParseDescr) { - case 0: - theBuffer.valueSize = 2; - valParser.Initialize(&theBuffer); - stateParseDescr = 1; - case 1: - if(!valParser.Parse(pp, pcntdn)) - return false; - dscrLen = *((uint8_t*)theBuffer.pValue); - dscrType = *((uint8_t*)theBuffer.pValue + 1); - stateParseDescr = 2; - case 2: - // This is a sort of hack. Assuming that two bytes are all ready in the buffer - // the pointer is positioned two bytes ahead in order for the rest of descriptor - // to be read right after the size and the type fields. - // This should be used carefully. varBuffer should be used directly to handle data - // in the buffer. - theBuffer.pValue = varBuffer + 2; - stateParseDescr = 3; - case 3: - switch(dscrType) { - case USB_DESCRIPTOR_INTERFACE: - isGoodInterface = false; - case USB_DESCRIPTOR_CONFIGURATION: - theBuffer.valueSize = sizeof (USB_CONFIGURATION_DESCRIPTOR) - 2; - break; - case USB_DESCRIPTOR_ENDPOINT: - theBuffer.valueSize = sizeof (USB_ENDPOINT_DESCRIPTOR) - 2; - break; - case HID_DESCRIPTOR_HID: - theBuffer.valueSize = dscrLen - 2; - break; - } - valParser.Initialize(&theBuffer); - stateParseDescr = 4; - case 4: - switch(dscrType) { - case USB_DESCRIPTOR_CONFIGURATION: - if(!valParser.Parse(pp, pcntdn)) - return false; - confValue = ucd->bConfigurationValue; - break; - case USB_DESCRIPTOR_INTERFACE: - if(!valParser.Parse(pp, pcntdn)) - return false; - if((MASK & CP_MASK_COMPARE_CLASS) && uid->bInterfaceClass != CLASS_ID) - break; - if((MASK & CP_MASK_COMPARE_SUBCLASS) && uid->bInterfaceSubClass != SUBCLASS_ID) - break; - if(UseOr) { - if((!((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol))) - break; - } else { - if((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol != PROTOCOL_ID) - break; - } - isGoodInterface = true; - ifaceNumber = uid->bInterfaceNumber; - ifaceAltSet = uid->bAlternateSetting; - protoValue = uid->bInterfaceProtocol; - break; - case USB_DESCRIPTOR_ENDPOINT: - if(!valParser.Parse(pp, pcntdn)) - return false; - if(isGoodInterface) - if(theXtractor) - theXtractor->EndpointXtract(confValue, ifaceNumber, ifaceAltSet, protoValue, (USB_ENDPOINT_DESCRIPTOR*)varBuffer); - break; - //case HID_DESCRIPTOR_HID: - // if (!valParser.Parse(pp, pcntdn)) - // return false; - // PrintHidDescriptor((const USB_HID_DESCRIPTOR*)varBuffer); - // break; - default: - if(!theSkipper.Skip(pp, pcntdn, dscrLen - 2)) - return false; - } - theBuffer.pValue = varBuffer; - stateParseDescr = 0; - } - return true; -} - -template -void ConfigDescParser::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc) { - Notify(PSTR("\r\n\r\nHID Descriptor:\r\n"), 0x80); - Notify(PSTR("bDescLength:\t\t"), 0x80); - PrintHex (pDesc->bLength, 0x80); - - Notify(PSTR("\r\nbDescriptorType:\t"), 0x80); - PrintHex (pDesc->bDescriptorType, 0x80); - - Notify(PSTR("\r\nbcdHID:\t\t\t"), 0x80); - PrintHex (pDesc->bcdHID, 0x80); - - Notify(PSTR("\r\nbCountryCode:\t\t"), 0x80); - PrintHex (pDesc->bCountryCode, 0x80); - - Notify(PSTR("\r\nbNumDescriptors:\t"), 0x80); - PrintHex (pDesc->bNumDescriptors, 0x80); - - for(uint8_t i = 0; i < pDesc->bNumDescriptors; i++) { - HID_CLASS_DESCRIPTOR_LEN_AND_TYPE *pLT = (HID_CLASS_DESCRIPTOR_LEN_AND_TYPE*)&(pDesc->bDescrType); - - Notify(PSTR("\r\nbDescrType:\t\t"), 0x80); - PrintHex (pLT[i].bDescrType, 0x80); - - Notify(PSTR("\r\nwDescriptorLength:\t"), 0x80); - PrintHex (pLT[i].wDescriptorLength, 0x80); - } - Notify(PSTR("\r\n"), 0x80); -} - - -#endif // __CONFDESCPARSER_H__ diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/controllerEnums.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/controllerEnums.h deleted file mode 100644 index 0169c763c1..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/controllerEnums.h +++ /dev/null @@ -1,204 +0,0 @@ -/* Copyright (C) 2013 Kristian Lauszus, TKJ Electronics. All rights reserved. - - This software may be distributed and modified under the terms of the GNU - General Public License version 2 (GPL2) as published by the Free Software - Foundation and appearing in the file GPL2.TXT included in the packaging of - this file. Please note that GPL2 Section 2[b] requires that all works based - on this software must also be made publicly available under the terms of - the GPL2 ("Copyleft"). - - Contact information - ------------------- - - Kristian Lauszus, TKJ Electronics - Web : http://www.tkjelectronics.com - e-mail : kristianl@tkjelectronics.com - */ - -#ifndef _controllerenums_h -#define _controllerenums_h - -/** - * This header file is used to store different enums for the controllers, - * This is necessary so all the different libraries can be used at once. - */ - -/** Enum used to turn on the LEDs on the different controllers. */ -enum LEDEnum { - OFF = 0, - LED1 = 1, - LED2 = 2, - LED3 = 3, - LED4 = 4, - - LED5 = 5, - LED6 = 6, - LED7 = 7, - LED8 = 8, - LED9 = 9, - LED10 = 10, - /** Used to blink all LEDs on the Xbox controller */ - ALL = 5, -}; - -/** Used to set the colors of the Move and PS4 controller. */ -enum ColorsEnum { - /** r = 255, g = 0, b = 0 */ - Red = 0xFF0000, - /** r = 0, g = 255, b = 0 */ - Green = 0xFF00, - /** r = 0, g = 0, b = 255 */ - Blue = 0xFF, - - /** r = 255, g = 235, b = 4 */ - Yellow = 0xFFEB04, - /** r = 0, g = 255, b = 255 */ - Lightblue = 0xFFFF, - /** r = 255, g = 0, b = 255 */ - Purble = 0xFF00FF, - - /** r = 255, g = 255, b = 255 */ - White = 0xFFFFFF, - /** r = 0, g = 0, b = 0 */ - Off = 0x00, -}; - -enum RumbleEnum { - RumbleHigh = 0x10, - RumbleLow = 0x20, -}; - -/** This enum is used to read all the different buttons on the different controllers */ -enum ButtonEnum { - /**@{*/ - /** These buttons are available on all the the controllers */ - UP = 0, - RIGHT = 1, - DOWN = 2, - LEFT = 3, - /**@}*/ - - /**@{*/ - /** Wii buttons */ - PLUS = 5, - TWO = 6, - ONE = 7, - MINUS = 8, - HOME = 9, - Z = 10, - C = 11, - B = 12, - A = 13, - /**@}*/ - - /**@{*/ - /** These are only available on the Wii U Pro Controller */ - L = 16, - R = 17, - ZL = 18, - ZR = 19, - /**@}*/ - - /**@{*/ - /** PS3 controllers buttons */ - SELECT = 4, - START = 5, - L3 = 6, - R3 = 7, - - L2 = 8, - R2 = 9, - L1 = 10, - R1 = 11, - TRIANGLE = 12, - CIRCLE = 13, - CROSS = 14, - SQUARE = 15, - - PS = 16, - - MOVE = 17, // Covers 12 bits - we only need to read the top 8 - T = 18, // Covers 12 bits - we only need to read the top 8 - /**@}*/ - - /** PS4 controllers buttons - SHARE and OPTIONS are present instead of SELECT and START */ - SHARE = 4, - OPTIONS = 5, - TOUCHPAD = 17, - /**@}*/ - - /**@{*/ - /** Xbox buttons */ - BACK = 4, - X = 14, - Y = 15, - XBOX = 16, - SYNC = 17, - BLACK = 8, // Available on the original Xbox controller - WHITE = 9, // Available on the original Xbox controller - /**@}*/ - - /** PS Buzz controllers */ - RED = 0, - YELLOW = 1, - GREEN = 2, - ORANGE = 3, - BLUE = 4, - /**@}*/ -}; - -/** Joysticks on the PS3 and Xbox controllers. */ -enum AnalogHatEnum { - /** Left joystick x-axis */ - LeftHatX = 0, - /** Left joystick y-axis */ - LeftHatY = 1, - /** Right joystick x-axis */ - RightHatX = 2, - /** Right joystick y-axis */ - RightHatY = 3, -}; - -/** - * Sensors inside the Sixaxis Dualshock 3, Move controller and PS4 controller. - * Note: that the location is shifted 9 when it's connected via USB on the PS3 controller. - */ -enum SensorEnum { - /** Accelerometer values */ - aX = 50, aY = 52, aZ = 54, - /** Gyro z-axis */ - gZ = 56, - gX, gY, // These are not available on the PS3 controller - - /** Accelerometer x-axis */ - aXmove = 28, - /** Accelerometer z-axis */ - aZmove = 30, - /** Accelerometer y-axis */ - aYmove = 32, - - /** Gyro x-axis */ - gXmove = 40, - /** Gyro z-axis */ - gZmove = 42, - /** Gyro y-axis */ - gYmove = 44, - - /** Temperature sensor */ - tempMove = 46, - - /** Magnetometer x-axis */ - mXmove = 47, - /** Magnetometer z-axis */ - mZmove = 49, - /** Magnetometer y-axis */ - mYmove = 50, -}; - -/** Used to get the angle calculated using the PS3 controller and PS4 controller. */ -enum AngleEnum { - Pitch = 0x01, - Roll = 0x02, -}; - -#endif diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/BTHID.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/BTHID.ino deleted file mode 100644 index 919a56468b..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/BTHID.ino +++ /dev/null @@ -1,55 +0,0 @@ -/* - Example sketch for the HID Bluetooth library - developed by Kristian Lauszus - For more information visit my blog: http://blog.tkjelectronics.dk/ or - send me an e-mail: kristianl@tkjelectronics.com - */ - -#include -#include -#include "KeyboardParser.h" -#include "MouseParser.h" - -// Satisfy the IDE, which needs to see the include statment in the ino too. -#ifdef dobogusinclude -#include -#include -#endif - -USB Usb; -//USBHub Hub1(&Usb); // Some dongles have a hub inside -BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so - -/* You can create the instance of the class in two ways */ -// This will start an inquiry and then pair with your device - you only have to do this once -// If you are using a Bluetooth keyboard, then you should type in the password on the keypad and then press enter -BTHID bthid(&Btd, PAIR, "0000"); - -// After that you can simply create the instance like so and then press any button on the device -//BTHID hid(&Btd); - -KbdRptParser keyboardPrs; -MouseRptParser mousePrs; - -void setup() { - Serial.begin(115200); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - if (Usb.Init() == -1) { - Serial.print(F("\r\nOSC did not start")); - while (1); // Halt - } - - bthid.SetReportParser(KEYBOARD_PARSER_ID, (HIDReportParser*)&keyboardPrs); - bthid.SetReportParser(MOUSE_PARSER_ID, (HIDReportParser*)&mousePrs); - - // If "Boot Protocol Mode" does not work, then try "Report Protocol Mode" - // If that does not work either, then uncomment PRINTREPORT in BTHID.cpp to see the raw report - bthid.setProtocolMode(HID_BOOT_PROTOCOL); // Boot Protocol Mode - //bthid.setProtocolMode(HID_RPT_PROTOCOL); // Report Protocol Mode - - Serial.print(F("\r\nHID Bluetooth Library Started")); -} -void loop() { - Usb.Task(); -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/KeyboardParser.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/KeyboardParser.h deleted file mode 100644 index c5394331da..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/KeyboardParser.h +++ /dev/null @@ -1,105 +0,0 @@ -#ifndef __kbdrptparser_h_ -#define __kbdrptparser_h_ - -class KbdRptParser : public KeyboardReportParser { - protected: - virtual uint8_t HandleLockingKeys(HID *hid, uint8_t key); - virtual void OnControlKeysChanged(uint8_t before, uint8_t after); - virtual void OnKeyDown(uint8_t mod, uint8_t key); - virtual void OnKeyUp(uint8_t mod, uint8_t key); - virtual void OnKeyPressed(uint8_t key); - - private: - void PrintKey(uint8_t mod, uint8_t key); -}; - -uint8_t KbdRptParser::HandleLockingKeys(HID *hid, uint8_t key) { - uint8_t old_keys = kbdLockingKeys.bLeds; - - switch (key) { - case UHS_HID_BOOT_KEY_NUM_LOCK: - Serial.println(F("Num lock")); - kbdLockingKeys.kbdLeds.bmNumLock = ~kbdLockingKeys.kbdLeds.bmNumLock; - break; - case UHS_HID_BOOT_KEY_CAPS_LOCK: - Serial.println(F("Caps lock")); - kbdLockingKeys.kbdLeds.bmCapsLock = ~kbdLockingKeys.kbdLeds.bmCapsLock; - break; - case UHS_HID_BOOT_KEY_SCROLL_LOCK: - Serial.println(F("Scroll lock")); - kbdLockingKeys.kbdLeds.bmScrollLock = ~kbdLockingKeys.kbdLeds.bmScrollLock; - break; - } - - if (old_keys != kbdLockingKeys.bLeds && hid) { - BTHID *pBTHID = reinterpret_cast (hid); // A cast the other way around is done in BTHID.cpp - pBTHID->setLeds(kbdLockingKeys.bLeds); // Update the LEDs on the keyboard - } - - return 0; -}; - -void KbdRptParser::PrintKey(uint8_t m, uint8_t key) { - MODIFIERKEYS mod; - *((uint8_t*)&mod) = m; - Serial.print((mod.bmLeftCtrl == 1) ? F("C") : F(" ")); - Serial.print((mod.bmLeftShift == 1) ? F("S") : F(" ")); - Serial.print((mod.bmLeftAlt == 1) ? F("A") : F(" ")); - Serial.print((mod.bmLeftGUI == 1) ? F("G") : F(" ")); - - Serial.print(F(" >")); - PrintHex(key, 0x80); - Serial.print(F("< ")); - - Serial.print((mod.bmRightCtrl == 1) ? F("C") : F(" ")); - Serial.print((mod.bmRightShift == 1) ? F("S") : F(" ")); - Serial.print((mod.bmRightAlt == 1) ? F("A") : F(" ")); - Serial.println((mod.bmRightGUI == 1) ? F("G") : F(" ")); -}; - -void KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key) { - Serial.print(F("DN ")); - PrintKey(mod, key); - uint8_t c = OemToAscii(mod, key); - - if (c) - OnKeyPressed(c); -}; - -void KbdRptParser::OnControlKeysChanged(uint8_t before, uint8_t after) { - MODIFIERKEYS beforeMod; - *((uint8_t*)&beforeMod) = before; - - MODIFIERKEYS afterMod; - *((uint8_t*)&afterMod) = after; - - if (beforeMod.bmLeftCtrl != afterMod.bmLeftCtrl) - Serial.println(F("LeftCtrl changed")); - if (beforeMod.bmLeftShift != afterMod.bmLeftShift) - Serial.println(F("LeftShift changed")); - if (beforeMod.bmLeftAlt != afterMod.bmLeftAlt) - Serial.println(F("LeftAlt changed")); - if (beforeMod.bmLeftGUI != afterMod.bmLeftGUI) - Serial.println(F("LeftGUI changed")); - - if (beforeMod.bmRightCtrl != afterMod.bmRightCtrl) - Serial.println(F("RightCtrl changed")); - if (beforeMod.bmRightShift != afterMod.bmRightShift) - Serial.println(F("RightShift changed")); - if (beforeMod.bmRightAlt != afterMod.bmRightAlt) - Serial.println(F("RightAlt changed")); - if (beforeMod.bmRightGUI != afterMod.bmRightGUI) - Serial.println(F("RightGUI changed")); -}; - -void KbdRptParser::OnKeyUp(uint8_t mod, uint8_t key) { - Serial.print(F("UP ")); - PrintKey(mod, key); -}; - -void KbdRptParser::OnKeyPressed(uint8_t key) { - Serial.print(F("ASCII: ")); - Serial.println((char)key); -}; - -#endif diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/MouseParser.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/MouseParser.h deleted file mode 100644 index a9245ded99..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/MouseParser.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef __mouserptparser_h__ -#define __mouserptparser_h__ - -class MouseRptParser : public MouseReportParser { - protected: - virtual void OnMouseMove(MOUSEINFO *mi); - virtual void OnLeftButtonUp(MOUSEINFO *mi); - virtual void OnLeftButtonDown(MOUSEINFO *mi); - virtual void OnRightButtonUp(MOUSEINFO *mi); - virtual void OnRightButtonDown(MOUSEINFO *mi); - virtual void OnMiddleButtonUp(MOUSEINFO *mi); - virtual void OnMiddleButtonDown(MOUSEINFO *mi); -}; - -void MouseRptParser::OnMouseMove(MOUSEINFO *mi) { - Serial.print(F("dx=")); - Serial.print(mi->dX, DEC); - Serial.print(F(" dy=")); - Serial.println(mi->dY, DEC); -}; - -void MouseRptParser::OnLeftButtonUp(MOUSEINFO *mi) { - Serial.println(F("L Butt Up")); -}; - -void MouseRptParser::OnLeftButtonDown(MOUSEINFO *mi) { - Serial.println(F("L Butt Dn")); -}; - -void MouseRptParser::OnRightButtonUp(MOUSEINFO *mi) { - Serial.println(F("R Butt Up")); -}; - -void MouseRptParser::OnRightButtonDown(MOUSEINFO *mi) { - Serial.println(F("R Butt Dn")); -}; - -void MouseRptParser::OnMiddleButtonUp(MOUSEINFO *mi) { - Serial.println(F("M Butt Up")); -}; - -void MouseRptParser::OnMiddleButtonDown(MOUSEINFO *mi) { - Serial.println(F("M Butt Dn")); -}; - -#endif diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/PS3BT/PS3BT.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/PS3BT/PS3BT.ino deleted file mode 100644 index b896734405..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/PS3BT/PS3BT.ino +++ /dev/null @@ -1,188 +0,0 @@ -/* - Example sketch for the PS3 Bluetooth library - developed by Kristian Lauszus - For more information visit my blog: http://blog.tkjelectronics.dk/ or - send me an e-mail: kristianl@tkjelectronics.com - */ - -#include -#include - -// Satisfy the IDE, which needs to see the include statment in the ino too. -#ifdef dobogusinclude -#include -#include -#endif - -USB Usb; -//USBHub Hub1(&Usb); // Some dongles have a hub inside - -BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so -/* You can create the instance of the class in two ways */ -PS3BT PS3(&Btd); // This will just create the instance -//PS3BT PS3(&Btd, 0x00, 0x15, 0x83, 0x3D, 0x0A, 0x57); // This will also store the bluetooth address - this can be obtained from the dongle when running the sketch - -bool printTemperature; -bool printAngle; - -void setup() { - Serial.begin(115200); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - if (Usb.Init() == -1) { - Serial.print(F("\r\nOSC did not start")); - while (1); //halt - } - Serial.print(F("\r\nPS3 Bluetooth Library Started")); -} -void loop() { - Usb.Task(); - - if (PS3.PS3Connected || PS3.PS3NavigationConnected) { - if (PS3.getAnalogHat(LeftHatX) > 137 || PS3.getAnalogHat(LeftHatX) < 117 || PS3.getAnalogHat(LeftHatY) > 137 || PS3.getAnalogHat(LeftHatY) < 117 || PS3.getAnalogHat(RightHatX) > 137 || PS3.getAnalogHat(RightHatX) < 117 || PS3.getAnalogHat(RightHatY) > 137 || PS3.getAnalogHat(RightHatY) < 117) { - Serial.print(F("\r\nLeftHatX: ")); - Serial.print(PS3.getAnalogHat(LeftHatX)); - Serial.print(F("\tLeftHatY: ")); - Serial.print(PS3.getAnalogHat(LeftHatY)); - if (PS3.PS3Connected) { // The Navigation controller only have one joystick - Serial.print(F("\tRightHatX: ")); - Serial.print(PS3.getAnalogHat(RightHatX)); - Serial.print(F("\tRightHatY: ")); - Serial.print(PS3.getAnalogHat(RightHatY)); - } - } - - // Analog button values can be read from almost all buttons - if (PS3.getAnalogButton(L2) || PS3.getAnalogButton(R2)) { - Serial.print(F("\r\nL2: ")); - Serial.print(PS3.getAnalogButton(L2)); - if (PS3.PS3Connected) { - Serial.print(F("\tR2: ")); - Serial.print(PS3.getAnalogButton(R2)); - } - } - if (PS3.getButtonClick(PS)) { - Serial.print(F("\r\nPS")); - PS3.disconnect(); - } - else { - if (PS3.getButtonClick(TRIANGLE)) - Serial.print(F("\r\nTraingle")); - if (PS3.getButtonClick(CIRCLE)) - Serial.print(F("\r\nCircle")); - if (PS3.getButtonClick(CROSS)) - Serial.print(F("\r\nCross")); - if (PS3.getButtonClick(SQUARE)) - Serial.print(F("\r\nSquare")); - - if (PS3.getButtonClick(UP)) { - Serial.print(F("\r\nUp")); - if (PS3.PS3Connected) { - PS3.setLedOff(); - PS3.setLedOn(LED4); - } - } - if (PS3.getButtonClick(RIGHT)) { - Serial.print(F("\r\nRight")); - if (PS3.PS3Connected) { - PS3.setLedOff(); - PS3.setLedOn(LED1); - } - } - if (PS3.getButtonClick(DOWN)) { - Serial.print(F("\r\nDown")); - if (PS3.PS3Connected) { - PS3.setLedOff(); - PS3.setLedOn(LED2); - } - } - if (PS3.getButtonClick(LEFT)) { - Serial.print(F("\r\nLeft")); - if (PS3.PS3Connected) { - PS3.setLedOff(); - PS3.setLedOn(LED3); - } - } - - if (PS3.getButtonClick(L1)) - Serial.print(F("\r\nL1")); - if (PS3.getButtonClick(L3)) - Serial.print(F("\r\nL3")); - if (PS3.getButtonClick(R1)) - Serial.print(F("\r\nR1")); - if (PS3.getButtonClick(R3)) - Serial.print(F("\r\nR3")); - - if (PS3.getButtonClick(SELECT)) { - Serial.print(F("\r\nSelect - ")); - PS3.printStatusString(); - } - if (PS3.getButtonClick(START)) { - Serial.print(F("\r\nStart")); - printAngle = !printAngle; - } - } -#if 0 // Set this to 1 in order to see the angle of the controller - if (printAngle) { - Serial.print(F("\r\nPitch: ")); - Serial.print(PS3.getAngle(Pitch)); - Serial.print(F("\tRoll: ")); - Serial.print(PS3.getAngle(Roll)); - } -#endif - } -#if 0 // Set this to 1 in order to enable support for the Playstation Move controller - else if (PS3.PS3MoveConnected) { - if (PS3.getAnalogButton(T)) { - Serial.print(F("\r\nT: ")); - Serial.print(PS3.getAnalogButton(T)); - } - if (PS3.getButtonClick(PS)) { - Serial.print(F("\r\nPS")); - PS3.disconnect(); - } - else { - if (PS3.getButtonClick(SELECT)) { - Serial.print(F("\r\nSelect")); - printTemperature = !printTemperature; - } - if (PS3.getButtonClick(START)) { - Serial.print(F("\r\nStart")); - printAngle = !printAngle; - } - if (PS3.getButtonClick(TRIANGLE)) { - Serial.print(F("\r\nTriangle")); - PS3.moveSetBulb(Red); - } - if (PS3.getButtonClick(CIRCLE)) { - Serial.print(F("\r\nCircle")); - PS3.moveSetBulb(Green); - } - if (PS3.getButtonClick(SQUARE)) { - Serial.print(F("\r\nSquare")); - PS3.moveSetBulb(Blue); - } - if (PS3.getButtonClick(CROSS)) { - Serial.print(F("\r\nCross")); - PS3.moveSetBulb(Yellow); - } - if (PS3.getButtonClick(MOVE)) { - PS3.moveSetBulb(Off); - Serial.print(F("\r\nMove")); - Serial.print(F(" - ")); - PS3.printStatusString(); - } - } - if (printAngle) { - Serial.print(F("\r\nPitch: ")); - Serial.print(PS3.getAngle(Pitch)); - Serial.print(F("\tRoll: ")); - Serial.print(PS3.getAngle(Roll)); - } - else if (printTemperature) { - Serial.print(F("\r\nTemperature: ")); - Serial.print(PS3.getTemperature()); - } - } -#endif -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/PS3Multi/PS3Multi.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/PS3Multi/PS3Multi.ino deleted file mode 100644 index 5ebfd7819c..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/PS3Multi/PS3Multi.ino +++ /dev/null @@ -1,149 +0,0 @@ -/* - Example sketch for the PS3 Bluetooth library - developed by Kristian Lauszus - This example show how one can use multiple controllers with the library - For more information visit my blog: http://blog.tkjelectronics.dk/ or - send me an e-mail: kristianl@tkjelectronics.com - */ - -#include -#include - -// Satisfy the IDE, which needs to see the include statment in the ino too. -#ifdef dobogusinclude -#include -#include -#endif - -USB Usb; -//USBHub Hub1(&Usb); // Some dongles have a hub inside - -BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so -PS3BT *PS3[2]; // We will use this pointer to store the two instance, you can easily make it larger if you like, but it will use a lot of RAM! -const uint8_t length = sizeof(PS3) / sizeof(PS3[0]); // Get the lenght of the array -bool printAngle[length]; -bool oldControllerState[length]; - -void setup() { - for (uint8_t i = 0; i < length; i++) { - PS3[i] = new PS3BT(&Btd); // Create the instances - PS3[i]->attachOnInit(onInit); // onInit() is called upon a new connection - you can call the function whatever you like - } - - Serial.begin(115200); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - if (Usb.Init() == -1) { - Serial.print(F("\r\nOSC did not start")); - while (1); //halt - } - Serial.print(F("\r\nPS3 Bluetooth Library Started")); -} -void loop() { - Usb.Task(); - - for (uint8_t i = 0; i < length; i++) { - if (PS3[i]->PS3Connected || PS3[i]->PS3NavigationConnected) { - if (PS3[i]->getAnalogHat(LeftHatX) > 137 || PS3[i]->getAnalogHat(LeftHatX) < 117 || PS3[i]->getAnalogHat(LeftHatY) > 137 || PS3[i]->getAnalogHat(LeftHatY) < 117 || PS3[i]->getAnalogHat(RightHatX) > 137 || PS3[i]->getAnalogHat(RightHatX) < 117 || PS3[i]->getAnalogHat(RightHatY) > 137 || PS3[i]->getAnalogHat(RightHatY) < 117) { - Serial.print(F("\r\nLeftHatX: ")); - Serial.print(PS3[i]->getAnalogHat(LeftHatX)); - Serial.print(F("\tLeftHatY: ")); - Serial.print(PS3[i]->getAnalogHat(LeftHatY)); - if (PS3[i]->PS3Connected) { // The Navigation controller only have one joystick - Serial.print(F("\tRightHatX: ")); - Serial.print(PS3[i]->getAnalogHat(RightHatX)); - Serial.print(F("\tRightHatY: ")); - Serial.print(PS3[i]->getAnalogHat(RightHatY)); - } - } - //Analog button values can be read from almost all buttons - if (PS3[i]->getAnalogButton(L2) || PS3[i]->getAnalogButton(R2)) { - Serial.print(F("\r\nL2: ")); - Serial.print(PS3[i]->getAnalogButton(L2)); - if (PS3[i]->PS3Connected) { - Serial.print(F("\tR2: ")); - Serial.print(PS3[i]->getAnalogButton(R2)); - } - } - if (PS3[i]->getButtonClick(PS)) { - Serial.print(F("\r\nPS")); - PS3[i]->disconnect(); - oldControllerState[i] = false; // Reset value - } - else { - if (PS3[i]->getButtonClick(TRIANGLE)) - Serial.print(F("\r\nTraingle")); - if (PS3[i]->getButtonClick(CIRCLE)) - Serial.print(F("\r\nCircle")); - if (PS3[i]->getButtonClick(CROSS)) - Serial.print(F("\r\nCross")); - if (PS3[i]->getButtonClick(SQUARE)) - Serial.print(F("\r\nSquare")); - - if (PS3[i]->getButtonClick(UP)) { - Serial.print(F("\r\nUp")); - if (PS3[i]->PS3Connected) { - PS3[i]->setLedOff(); - PS3[i]->setLedOn(LED4); - } - } - if (PS3[i]->getButtonClick(RIGHT)) { - Serial.print(F("\r\nRight")); - if (PS3[i]->PS3Connected) { - PS3[i]->setLedOff(); - PS3[i]->setLedOn(LED1); - } - } - if (PS3[i]->getButtonClick(DOWN)) { - Serial.print(F("\r\nDown")); - if (PS3[i]->PS3Connected) { - PS3[i]->setLedOff(); - PS3[i]->setLedOn(LED2); - } - } - if (PS3[i]->getButtonClick(LEFT)) { - Serial.print(F("\r\nLeft")); - if (PS3[i]->PS3Connected) { - PS3[i]->setLedOff(); - PS3[i]->setLedOn(LED3); - } - } - - if (PS3[i]->getButtonClick(L1)) - Serial.print(F("\r\nL1")); - if (PS3[i]->getButtonClick(L3)) - Serial.print(F("\r\nL3")); - if (PS3[i]->getButtonClick(R1)) - Serial.print(F("\r\nR1")); - if (PS3[i]->getButtonClick(R3)) - Serial.print(F("\r\nR3")); - - if (PS3[i]->getButtonClick(SELECT)) { - Serial.print(F("\r\nSelect - ")); - PS3[i]->printStatusString(); - } - if (PS3[i]->getButtonClick(START)) { - Serial.print(F("\r\nStart")); - printAngle[i] = !printAngle[i]; - } - } - if (printAngle[i]) { - Serial.print(F("\r\nPitch: ")); - Serial.print(PS3[i]->getAngle(Pitch)); - Serial.print(F("\tRoll: ")); - Serial.print(PS3[i]->getAngle(Roll)); - } - } - /* I have removed the PS3 Move code as an Uno will run out of RAM if it's included */ - //else if(PS3[i]->PS3MoveConnected) { - } -} - -void onInit() { - for (uint8_t i = 0; i < length; i++) { - if ((PS3[i]->PS3Connected || PS3[i]->PS3NavigationConnected) && !oldControllerState[i]) { - oldControllerState[i] = true; // Used to check which is the new controller - PS3[i]->setLedOn((LEDEnum)(i + 1)); // Cast directly to LEDEnum - see: "controllerEnums.h" - } - } -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/PS3SPP/PS3SPP.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/PS3SPP/PS3SPP.ino deleted file mode 100644 index 8f234cbd8d..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/PS3SPP/PS3SPP.ino +++ /dev/null @@ -1,162 +0,0 @@ -/* - Example sketch for the Bluetooth library - developed by Kristian Lauszus - For more information visit my blog: http://blog.tkjelectronics.dk/ or - send me an e-mail: kristianl@tkjelectronics.com - - This example show how one can combine all the difference Bluetooth services in one single code. - Note: - You will need a Arduino Mega 1280/2560 to run this sketch, - as a normal Arduino (Uno, Duemilanove etc.) doesn't have enough SRAM and FLASH - */ - -#include -#include -#include - -// Satisfy the IDE, which needs to see the include statment in the ino too. -#ifdef dobogusinclude -#include -#include -#endif - -USB Usb; -//USBHub Hub1(&Usb); // Some dongles have a hub inside - -BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so - -/* You can create the instances of the bluetooth services in two ways */ -SPP SerialBT(&Btd); // This will set the name to the defaults: "Arduino" and the pin to "0000" -//SPP SerialBTBT(&Btd,"Lauszus's Arduino","0000"); // You can also set the name and pin like so -PS3BT PS3(&Btd); // This will just create the instance -//PS3BT PS3(&Btd, 0x00, 0x15, 0x83, 0x3D, 0x0A, 0x57); // This will also store the bluetooth address - this can be obtained from the dongle when running the sketch - -bool firstMessage = true; -String output = ""; // We will store the data in this string - -void setup() { - Serial.begin(115200); // This wil lprint the debugging from the libraries -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - if (Usb.Init() == -1) { - Serial.print(F("\r\nOSC did not start")); - while (1); //halt - } - Serial.print(F("\r\nBluetooth Library Started")); - output.reserve(200); // Reserve 200 bytes for the output string -} -void loop() { - Usb.Task(); // The SPP data is actually not send until this is called, one could call SerialBT.send() directly as well - - if (SerialBT.connected) { - if (firstMessage) { - firstMessage = false; - SerialBT.println(F("Hello from Arduino")); // Send welcome message - } - if (Serial.available()) - SerialBT.write(Serial.read()); - if (SerialBT.available()) - Serial.write(SerialBT.read()); - } - else - firstMessage = true; - - if (PS3.PS3Connected || PS3.PS3NavigationConnected) { - output = ""; // Reset output string - if (PS3.getAnalogHat(LeftHatX) > 137 || PS3.getAnalogHat(LeftHatX) < 117 || PS3.getAnalogHat(LeftHatY) > 137 || PS3.getAnalogHat(LeftHatY) < 117 || PS3.getAnalogHat(RightHatX) > 137 || PS3.getAnalogHat(RightHatX) < 117 || PS3.getAnalogHat(RightHatY) > 137 || PS3.getAnalogHat(RightHatY) < 117) { - output += "LeftHatX: "; - output += PS3.getAnalogHat(LeftHatX); - output += "\tLeftHatY: "; - output += PS3.getAnalogHat(LeftHatY); - if (PS3.PS3Connected) { // The Navigation controller only have one joystick - output += "\tRightHatX: "; - output += PS3.getAnalogHat(RightHatX); - output += "\tRightHatY: "; - output += PS3.getAnalogHat(RightHatY); - } - } - //Analog button values can be read from almost all buttons - if (PS3.getAnalogButton(L2) || PS3.getAnalogButton(R2)) { - if (output != "") - output += "\r\n"; - output += "L2: "; - output += PS3.getAnalogButton(L2); - if (PS3.PS3Connected) { - output += "\tR2: "; - output += PS3.getAnalogButton(R2); - } - } - if (output != "") { - Serial.println(output); - if (SerialBT.connected) - SerialBT.println(output); - output = ""; // Reset output string - } - if (PS3.getButtonClick(PS)) { - output += " - PS"; - PS3.disconnect(); - } - else { - if (PS3.getButtonClick(TRIANGLE)) - output += " - Traingle"; - if (PS3.getButtonClick(CIRCLE)) - output += " - Circle"; - if (PS3.getButtonClick(CROSS)) - output += " - Cross"; - if (PS3.getButtonClick(SQUARE)) - output += " - Square"; - - if (PS3.getButtonClick(UP)) { - output += " - Up"; - if (PS3.PS3Connected) { - PS3.setLedOff(); - PS3.setLedOn(LED4); - } - } - if (PS3.getButtonClick(RIGHT)) { - output += " - Right"; - if (PS3.PS3Connected) { - PS3.setLedOff(); - PS3.setLedOn(LED1); - } - } - if (PS3.getButtonClick(DOWN)) { - output += " - Down"; - if (PS3.PS3Connected) { - PS3.setLedOff(); - PS3.setLedOn(LED2); - } - } - if (PS3.getButtonClick(LEFT)) { - output += " - Left"; - if (PS3.PS3Connected) { - PS3.setLedOff(); - PS3.setLedOn(LED3); - } - } - - if (PS3.getButtonClick(L1)) - output += " - L1"; - if (PS3.getButtonClick(L3)) - output += " - L3"; - if (PS3.getButtonClick(R1)) - output += " - R1"; - if (PS3.getButtonClick(R3)) - output += " - R3"; - - if (PS3.getButtonClick(SELECT)) { - output += " - Select"; - } - if (PS3.getButtonClick(START)) - output += " - Start"; - - if (output != "") { - String string = "PS3 Controller" + output; - Serial.println(string); - if (SerialBT.connected) - SerialBT.println(string); - } - } - delay(10); - } -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/PS4BT/PS4BT.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/PS4BT/PS4BT.ino deleted file mode 100644 index c3ba696bd1..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/PS4BT/PS4BT.ino +++ /dev/null @@ -1,146 +0,0 @@ -/* - Example sketch for the PS4 Bluetooth library - developed by Kristian Lauszus - For more information visit my blog: http://blog.tkjelectronics.dk/ or - send me an e-mail: kristianl@tkjelectronics.com - */ - -#include -#include - -// Satisfy the IDE, which needs to see the include statment in the ino too. -#ifdef dobogusinclude -#include -#include -#endif - -USB Usb; -//USBHub Hub1(&Usb); // Some dongles have a hub inside -BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so - -/* You can create the instance of the PS4BT class in two ways */ -// This will start an inquiry and then pair with the PS4 controller - you only have to do this once -// You will need to hold down the PS and Share button at the same time, the PS4 controller will then start to blink rapidly indicating that it is in paring mode -PS4BT PS4(&Btd, PAIR); - -// After that you can simply create the instance like so and then press the PS button on the device -//PS4BT PS4(&Btd); - -bool printAngle, printTouch; -uint8_t oldL2Value, oldR2Value; - -void setup() { - Serial.begin(115200); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - if (Usb.Init() == -1) { - Serial.print(F("\r\nOSC did not start")); - while (1); // Halt - } - Serial.print(F("\r\nPS4 Bluetooth Library Started")); -} -void loop() { - Usb.Task(); - - if (PS4.connected()) { - if (PS4.getAnalogHat(LeftHatX) > 137 || PS4.getAnalogHat(LeftHatX) < 117 || PS4.getAnalogHat(LeftHatY) > 137 || PS4.getAnalogHat(LeftHatY) < 117 || PS4.getAnalogHat(RightHatX) > 137 || PS4.getAnalogHat(RightHatX) < 117 || PS4.getAnalogHat(RightHatY) > 137 || PS4.getAnalogHat(RightHatY) < 117) { - Serial.print(F("\r\nLeftHatX: ")); - Serial.print(PS4.getAnalogHat(LeftHatX)); - Serial.print(F("\tLeftHatY: ")); - Serial.print(PS4.getAnalogHat(LeftHatY)); - Serial.print(F("\tRightHatX: ")); - Serial.print(PS4.getAnalogHat(RightHatX)); - Serial.print(F("\tRightHatY: ")); - Serial.print(PS4.getAnalogHat(RightHatY)); - } - - if (PS4.getAnalogButton(L2) || PS4.getAnalogButton(R2)) { // These are the only analog buttons on the PS4 controller - Serial.print(F("\r\nL2: ")); - Serial.print(PS4.getAnalogButton(L2)); - Serial.print(F("\tR2: ")); - Serial.print(PS4.getAnalogButton(R2)); - } - if (PS4.getAnalogButton(L2) != oldL2Value || PS4.getAnalogButton(R2) != oldR2Value) // Only write value if it's different - PS4.setRumbleOn(PS4.getAnalogButton(L2), PS4.getAnalogButton(R2)); - oldL2Value = PS4.getAnalogButton(L2); - oldR2Value = PS4.getAnalogButton(R2); - - if (PS4.getButtonClick(PS)) { - Serial.print(F("\r\nPS")); - PS4.disconnect(); - } - else { - if (PS4.getButtonClick(TRIANGLE)) { - Serial.print(F("\r\nTraingle")); - PS4.setRumbleOn(RumbleLow); - } - if (PS4.getButtonClick(CIRCLE)) { - Serial.print(F("\r\nCircle")); - PS4.setRumbleOn(RumbleHigh); - } - if (PS4.getButtonClick(CROSS)) { - Serial.print(F("\r\nCross")); - PS4.setLedFlash(10, 10); // Set it to blink rapidly - } - if (PS4.getButtonClick(SQUARE)) { - Serial.print(F("\r\nSquare")); - PS4.setLedFlash(0, 0); // Turn off blinking - } - - if (PS4.getButtonClick(UP)) { - Serial.print(F("\r\nUp")); - PS4.setLed(Red); - } if (PS4.getButtonClick(RIGHT)) { - Serial.print(F("\r\nRight")); - PS4.setLed(Blue); - } if (PS4.getButtonClick(DOWN)) { - Serial.print(F("\r\nDown")); - PS4.setLed(Yellow); - } if (PS4.getButtonClick(LEFT)) { - Serial.print(F("\r\nLeft")); - PS4.setLed(Green); - } - - if (PS4.getButtonClick(L1)) - Serial.print(F("\r\nL1")); - if (PS4.getButtonClick(L3)) - Serial.print(F("\r\nL3")); - if (PS4.getButtonClick(R1)) - Serial.print(F("\r\nR1")); - if (PS4.getButtonClick(R3)) - Serial.print(F("\r\nR3")); - - if (PS4.getButtonClick(SHARE)) - Serial.print(F("\r\nShare")); - if (PS4.getButtonClick(OPTIONS)) { - Serial.print(F("\r\nOptions")); - printAngle = !printAngle; - } - if (PS4.getButtonClick(TOUCHPAD)) { - Serial.print(F("\r\nTouchpad")); - printTouch = !printTouch; - } - - if (printAngle) { // Print angle calculated using the accelerometer only - Serial.print(F("\r\nPitch: ")); - Serial.print(PS4.getAngle(Pitch)); - Serial.print(F("\tRoll: ")); - Serial.print(PS4.getAngle(Roll)); - } - - if (printTouch) { // Print the x, y coordinates of the touchpad - if (PS4.isTouching(0) || PS4.isTouching(1)) // Print newline and carriage return if any of the fingers are touching the touchpad - Serial.print(F("\r\n")); - for (uint8_t i = 0; i < 2; i++) { // The touchpad track two fingers - if (PS4.isTouching(i)) { // Print the position of the finger if it is touching the touchpad - Serial.print(F("X")); Serial.print(i + 1); Serial.print(F(": ")); - Serial.print(PS4.getX(i)); - Serial.print(F("\tY")); Serial.print(i + 1); Serial.print(F(": ")); - Serial.print(PS4.getY(i)); - Serial.print(F("\t")); - } - } - } - } - } -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/SPP/SPP.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/SPP/SPP.ino deleted file mode 100644 index 8fb9c4eca2..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/SPP/SPP.ino +++ /dev/null @@ -1,52 +0,0 @@ -/* - Example sketch for the RFCOMM/SPP Bluetooth library - developed by Kristian Lauszus - For more information visit my blog: http://blog.tkjelectronics.dk/ or - send me an e-mail: kristianl@tkjelectronics.com - */ - -#include -#include - -// Satisfy the IDE, which needs to see the include statment in the ino too. -#ifdef dobogusinclude -#include -#include -#endif - -USB Usb; -//USBHub Hub1(&Usb); // Some dongles have a hub inside - -BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so -/* You can create the instance of the class in two ways */ -SPP SerialBT(&Btd); // This will set the name to the defaults: "Arduino" and the pin to "0000" -//SPP SerialBT(&Btd, "Lauszus's Arduino", "1234"); // You can also set the name and pin like so - -bool firstMessage = true; - -void setup() { - Serial.begin(115200); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - if (Usb.Init() == -1) { - Serial.print(F("\r\nOSC did not start")); - while (1); //halt - } - Serial.print(F("\r\nSPP Bluetooth Library Started")); -} -void loop() { - Usb.Task(); // The SPP data is actually not send until this is called, one could call SerialBT.send() directly as well - - if (SerialBT.connected) { - if (firstMessage) { - firstMessage = false; - SerialBT.println(F("Hello from Arduino")); // Send welcome message - } - if (Serial.available()) - SerialBT.write(Serial.read()); - if (SerialBT.available()) - Serial.write(SerialBT.read()); - } - else - firstMessage = true; -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/SPPMulti/SPPMulti.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/SPPMulti/SPPMulti.ino deleted file mode 100644 index df521d8e17..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/SPPMulti/SPPMulti.ino +++ /dev/null @@ -1,67 +0,0 @@ -/* - Example sketch for the RFCOMM/SPP Bluetooth library - developed by Kristian Lauszus - For more information visit my blog: http://blog.tkjelectronics.dk/ or - send me an e-mail: kristianl@tkjelectronics.com - */ - -#include -#include - -// Satisfy IDE, which only needs to see the include statment in the ino. -#ifdef dobogusinclude -#include -#include -#endif - -USB Usb; -//USBHub Hub1(&Usb); // Some dongles have a hub inside - -BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so - -const uint8_t length = 2; // Set the number of instances here -SPP *SerialBT[length]; // We will use this pointer to store the instances, you can easily make it larger if you like, but it will use a lot of RAM! - -bool firstMessage[length] = { true }; // Set all to true - -void setup() { - for (uint8_t i = 0; i < length; i++) - SerialBT[i] = new SPP(&Btd); // This will set the name to the default: "Arduino" and the pin to "0000" for all connections - - Serial.begin(115200); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - if (Usb.Init() == -1) { - Serial.print(F("\r\nOSC did not start")); - while (1); // Halt - } - Serial.print(F("\r\nSPP Bluetooth Library Started")); -} - -void loop() { - Usb.Task(); // The SPP data is actually not send until this is called, one could call SerialBT.send() directly as well - - for (uint8_t i = 0; i < length; i++) { - if (SerialBT[i]->connected) { - if (firstMessage[i]) { - firstMessage[i] = false; - SerialBT[i]->println(F("Hello from Arduino")); // Send welcome message - } - if (SerialBT[i]->available()) - Serial.write(SerialBT[i]->read()); - } - else - firstMessage[i] = true; - } - - // Set the connection you want to send to using the first character - // For instance "0Hello World" would send "Hello World" to connection 0 - if (Serial.available()) { - delay(10); // Wait for the rest of the data to arrive - uint8_t id = Serial.read() - '0'; // Convert from ASCII - if (id < length && SerialBT[id]->connected) { // Make sure that the id is valid and make sure that a device is actually connected - while (Serial.available()) // Check if data is available - SerialBT[id]->write(Serial.read()); // Send the data - } - } -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/Wii/Wii.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/Wii/Wii.ino deleted file mode 100644 index b193568163..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/Wii/Wii.ino +++ /dev/null @@ -1,118 +0,0 @@ -/* - Example sketch for the Wiimote Bluetooth library - developed by Kristian Lauszus - For more information visit my blog: http://blog.tkjelectronics.dk/ or - send me an e-mail: kristianl@tkjelectronics.com - */ - -#include -#include - -// Satisfy the IDE, which needs to see the include statment in the ino too. -#ifdef dobogusinclude -#include -#include -#endif - -USB Usb; -//USBHub Hub1(&Usb); // Some dongles have a hub inside - -BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so -/* You can create the instance of the class in two ways */ -WII Wii(&Btd, PAIR); // This will start an inquiry and then pair with your Wiimote - you only have to do this once -//WII Wii(&Btd); // After that you can simply create the instance like so and then press any button on the Wiimote - -bool printAngle; - -void setup() { - Serial.begin(115200); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - if (Usb.Init() == -1) { - Serial.print(F("\r\nOSC did not start")); - while (1); //halt - } - Serial.print(F("\r\nWiimote Bluetooth Library Started")); -} -void loop() { - Usb.Task(); - if (Wii.wiimoteConnected) { - if (Wii.getButtonClick(HOME)) { // You can use getButtonPress to see if the button is held down - Serial.print(F("\r\nHOME")); - Wii.disconnect(); - } - else { - if (Wii.getButtonClick(LEFT)) { - Wii.setLedOff(); - Wii.setLedOn(LED1); - Serial.print(F("\r\nLeft")); - } - if (Wii.getButtonClick(RIGHT)) { - Wii.setLedOff(); - Wii.setLedOn(LED3); - Serial.print(F("\r\nRight")); - } - if (Wii.getButtonClick(DOWN)) { - Wii.setLedOff(); - Wii.setLedOn(LED4); - Serial.print(F("\r\nDown")); - } - if (Wii.getButtonClick(UP)) { - Wii.setLedOff(); - Wii.setLedOn(LED2); - Serial.print(F("\r\nUp")); - } - - if (Wii.getButtonClick(PLUS)) - Serial.print(F("\r\nPlus")); - if (Wii.getButtonClick(MINUS)) - Serial.print(F("\r\nMinus")); - - if (Wii.getButtonClick(ONE)) - Serial.print(F("\r\nOne")); - if (Wii.getButtonClick(TWO)) - Serial.print(F("\r\nTwo")); - - if (Wii.getButtonClick(A)) { - printAngle = !printAngle; - Serial.print(F("\r\nA")); - } - if (Wii.getButtonClick(B)) { - Wii.setRumbleToggle(); - Serial.print(F("\r\nB")); - } - } -#if 0 // Set this to 1 in order to see the angle of the controllers - if (printAngle) { - Serial.print(F("\r\nPitch: ")); - Serial.print(Wii.getPitch()); - Serial.print(F("\tRoll: ")); - Serial.print(Wii.getRoll()); - if (Wii.motionPlusConnected) { - Serial.print(F("\tYaw: ")); - Serial.print(Wii.getYaw()); - } - if (Wii.nunchuckConnected) { - Serial.print(F("\tNunchuck Pitch: ")); - Serial.print(Wii.getNunchuckPitch()); - Serial.print(F("\tNunchuck Roll: ")); - Serial.print(Wii.getNunchuckRoll()); - } - } -#endif - } -#if 0 // Set this to 1 if you are using a Nunchuck controller - if (Wii.nunchuckConnected) { - if (Wii.getButtonClick(Z)) - Serial.print(F("\r\nZ")); - if (Wii.getButtonClick(C)) - Serial.print(F("\r\nC")); - if (Wii.getAnalogHat(HatX) > 137 || Wii.getAnalogHat(HatX) < 117 || Wii.getAnalogHat(HatY) > 137 || Wii.getAnalogHat(HatY) < 117) { - Serial.print(F("\r\nHatX: ")); - Serial.print(Wii.getAnalogHat(HatX)); - Serial.print(F("\tHatY: ")); - Serial.print(Wii.getAnalogHat(HatY)); - } - } -#endif -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/WiiBalanceBoard/WiiBalanceBoard.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/WiiBalanceBoard/WiiBalanceBoard.ino deleted file mode 100644 index 18c5b411ef..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/WiiBalanceBoard/WiiBalanceBoard.ino +++ /dev/null @@ -1,51 +0,0 @@ -/* - Example sketch for the Wii Balance Board Bluetooth library - developed by Kristian Lauszus - For more information visit my blog: http://blog.tkjelectronics.dk/ or - send me an e-mail: kristianl@tkjelectronics.com - */ - -#include -#include - -// Satisfy the IDE, which needs to see the include statment in the ino too. -#ifdef dobogusinclude -#include -#include -#endif - -USB Usb; -//USBHub Hub1(&Usb); // Some dongles have a hub inside - -BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so -/* You can create the instance of the class in two ways */ -WII Wii(&Btd, PAIR); // This will start an inquiry and then pair with your Wii Balance Board - you only have to do this once -//WII Wii(&Btd); // After that you can simply create the instance like so and then press the power button on the Wii Balance Board - -void setup() { - Serial.begin(115200); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - if (Usb.Init() == -1) { - Serial.print(F("\r\nOSC did not start")); - while (1); //halt - } - Serial.print(F("\r\nWii Balance Board Bluetooth Library Started")); -} -void loop() { - Usb.Task(); - if (Wii.wiiBalanceBoardConnected) { - Serial.print(F("\r\nWeight: ")); - for (uint8_t i = 0; i < 4; i++) { - Serial.print(Wii.getWeight((BalanceBoardEnum)i)); - Serial.print(F("\t")); - } - Serial.print(F("Total Weight: ")); - Serial.print(Wii.getTotalWeight()); - if (Wii.getButtonClick(A)) { - Serial.print(F("\r\nA")); - //Wii.setLedToggle(LED1); // The Wii Balance Board has one LED as well - Wii.disconnect(); - } - } -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/WiiIRCamera/WiiIRCamera.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/WiiIRCamera/WiiIRCamera.ino deleted file mode 100644 index 573b8bd48c..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/WiiIRCamera/WiiIRCamera.ino +++ /dev/null @@ -1,133 +0,0 @@ -/* -Example sketch for the Wii libary showing the IR camera functionality. This example -is for the Bluetooth Wii library developed for the USB shield from Circuits@Home - -Created by Allan Glover and Kristian Lauszus. -Contact Kristian: http://blog.tkjelectronics.dk/ or send an email at kristianl@tkjelectronics.com. -Contact Allan at adglover9.81@gmail.com - -To test the Wiimote IR camera, you will need access to an IR source. Sunlight will work but is not ideal. -The simpleist solution is to use the Wii sensor bar, i.e. emitter bar, supplied by the Wii system. -Otherwise, wire up a IR LED yourself. -*/ - -#include -#include - -// Satisfy the IDE, which needs to see the include statment in the ino too. -#ifdef dobogusinclude -#include -#include -#endif - -#ifndef WIICAMERA // Used to check if WIICAMERA is defined -#error "Please set ENABLE_WII_IR_CAMERA to 1 in settings.h" -#endif - -USB Usb; -//USBHub Hub1(&Usb); // Some dongles have a hub inside - -BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so -/* You can create the instance of the class in two ways */ -WII Wii(&Btd, PAIR); // This will start an inquiry and then pair with your Wiimote - you only have to do this once -//WII Wii(&Btd); // After the Wiimote pairs once with the line of code above, you can simply create the instance like so and re upload and then press any button on the Wiimote - -bool printAngle; -uint8_t printObjects; - -void setup() { - Serial.begin(115200); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - if (Usb.Init() == -1) { - Serial.print(F("\r\nOSC did not start")); - while (1); //halt - } - Serial.print(F("\r\nWiimote Bluetooth Library Started")); -} - -void loop() { - Usb.Task(); - if (Wii.wiimoteConnected) { - if (Wii.getButtonClick(HOME)) { // You can use getButtonPress to see if the button is held down - Serial.print(F("\r\nHOME")); - Wii.disconnect(); - } - else { - if (Wii.getButtonClick(ONE)) - Wii.IRinitialize(); // Run the initialisation sequence - if (Wii.getButtonClick(MINUS) || Wii.getButtonClick(PLUS)) { - if (!Wii.isIRCameraEnabled()) - Serial.print(F("\r\nEnable IR camera first")); - else { - if (Wii.getButtonPress(MINUS)) { // getButtonClick will only return true once - if (printObjects > 0) - printObjects--; - } - else { - if (printObjects < 4) - printObjects++; - } - Serial.print(F("\r\nTracking ")); - Serial.print(printObjects); - Serial.print(F(" objects")); - } - } - if (Wii.getButtonClick(A)) { - printAngle = !printAngle; - Serial.print(F("\r\nA")); - } - if (Wii.getButtonClick(B)) { - Serial.print(F("\r\nBattery level: ")); - Serial.print(Wii.getBatteryLevel()); // You can get the battery level as well - } - } - if (printObjects > 0) { - if (Wii.getIRx1() != 0x3FF || Wii.getIRy1() != 0x3FF || Wii.getIRs1() != 0) { // Only print if the IR camera is actually seeing something - Serial.print(F("\r\nx1: ")); - Serial.print(Wii.getIRx1()); - Serial.print(F("\ty1: ")); - Serial.print(Wii.getIRy1()); - Serial.print(F("\ts1:")); - Serial.print(Wii.getIRs1()); - } - if (printObjects > 1) { - if (Wii.getIRx2() != 0x3FF || Wii.getIRy2() != 0x3FF || Wii.getIRs2() != 0) { - Serial.print(F("\r\nx2: ")); - Serial.print(Wii.getIRx2()); - Serial.print(F("\ty2: ")); - Serial.print(Wii.getIRy2()); - Serial.print(F("\ts2:")); - Serial.print(Wii.getIRs2()); - } - if (printObjects > 2) { - if (Wii.getIRx3() != 0x3FF || Wii.getIRy3() != 0x3FF || Wii.getIRs3() != 0) { - Serial.print(F("\r\nx3: ")); - Serial.print(Wii.getIRx3()); - Serial.print(F("\ty3: ")); - Serial.print(Wii.getIRy3()); - Serial.print(F("\ts3:")); - Serial.print(Wii.getIRs3()); - } - if (printObjects > 3) { - if (Wii.getIRx4() != 0x3FF || Wii.getIRy4() != 0x3FF || Wii.getIRs4() != 0) { - Serial.print(F("\r\nx4: ")); - Serial.print(Wii.getIRx4()); - Serial.print(F("\ty4: ")); - Serial.print(Wii.getIRy4()); - Serial.print(F("\ts4:")); - Serial.print(Wii.getIRs4()); - } - } - } - } - } - if (printAngle) { // There is no extension bytes available, so the MotionPlus or Nunchuck can't be read - Serial.print(F("\r\nPitch: ")); - Serial.print(Wii.getPitch()); - Serial.print(F("\tRoll: ")); - Serial.print(Wii.getRoll()); - } - } -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/WiiMulti/WiiMulti.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/WiiMulti/WiiMulti.ino deleted file mode 100644 index 07c6f13d2b..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/WiiMulti/WiiMulti.ino +++ /dev/null @@ -1,132 +0,0 @@ -/* - Example sketch for the Wiimote Bluetooth library - developed by Kristian Lauszus - This example show how one can use multiple controllers with the library - For more information visit my blog: http://blog.tkjelectronics.dk/ or - send me an e-mail: kristianl@tkjelectronics.com - */ - -#include -#include - -// Satisfy the IDE, which needs to see the include statment in the ino too. -#ifdef dobogusinclude -#include -#include -#endif - -USB Usb; -//USBHub Hub1(&Usb); // Some dongles have a hub inside - -BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so -WII *Wii[2]; // We will use this pointer to store the two instance, you can easily make it larger if you like, but it will use a lot of RAM! -const uint8_t length = sizeof(Wii) / sizeof(Wii[0]); // Get the lenght of the array -bool printAngle[length]; -bool oldControllerState[length]; - -void setup() { - for (uint8_t i = 0; i < length; i++) { - Wii[i] = new WII(&Btd); // You will have to pair each controller with the dongle before you can define the instances like so, just add PAIR as the second argument - Wii[i]->attachOnInit(onInit); // onInit() is called upon a new connection - you can call the function whatever you like - } - - Serial.begin(115200); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - if (Usb.Init() == -1) { - Serial.print(F("\r\nOSC did not start")); - while (1); //halt - } - Serial.print(F("\r\nWiimote Bluetooth Library Started")); -} -void loop() { - Usb.Task(); - - for (uint8_t i = 0; i < length; i++) { - if (Wii[i]->wiimoteConnected) { - if (Wii[i]->getButtonClick(HOME)) { // You can use getButtonPress to see if the button is held down - Serial.print(F("\r\nHOME")); - Wii[i]->disconnect(); - oldControllerState[i] = false; // Reset value - } - else { - if (Wii[i]->getButtonClick(LEFT)) { - Wii[i]->setLedOff(); - Wii[i]->setLedOn(LED1); - Serial.print(F("\r\nLeft")); - } - if (Wii[i]->getButtonClick(RIGHT)) { - Wii[i]->setLedOff(); - Wii[i]->setLedOn(LED3); - Serial.print(F("\r\nRight")); - } - if (Wii[i]->getButtonClick(DOWN)) { - Wii[i]->setLedOff(); - Wii[i]->setLedOn(LED4); - Serial.print(F("\r\nDown")); - } - if (Wii[i]->getButtonClick(UP)) { - Wii[i]->setLedOff(); - Wii[i]->setLedOn(LED2); - Serial.print(F("\r\nUp")); - } - - if (Wii[i]->getButtonClick(PLUS)) - Serial.print(F("\r\nPlus")); - if (Wii[i]->getButtonClick(MINUS)) - Serial.print(F("\r\nMinus")); - - if (Wii[i]->getButtonClick(ONE)) - Serial.print(F("\r\nOne")); - if (Wii[i]->getButtonClick(TWO)) - Serial.print(F("\r\nTwo")); - - if (Wii[i]->getButtonClick(A)) { - printAngle[i] = !printAngle[i]; - Serial.print(F("\r\nA")); - } - if (Wii[i]->getButtonClick(B)) { - Wii[i]->setRumbleToggle(); - Serial.print(F("\r\nB")); - } - } - if (printAngle[i]) { - Serial.print(F("\r\nPitch: ")); - Serial.print(Wii[i]->getPitch()); - Serial.print(F("\tRoll: ")); - Serial.print(Wii[i]->getRoll()); - if (Wii[i]->motionPlusConnected) { - Serial.print(F("\tYaw: ")); - Serial.print(Wii[i]->getYaw()); - } - if (Wii[i]->nunchuckConnected) { - Serial.print(F("\tNunchuck Pitch: ")); - Serial.print(Wii[i]->getNunchuckPitch()); - Serial.print(F("\tNunchuck Roll: ")); - Serial.print(Wii[i]->getNunchuckRoll()); - } - } - } - if (Wii[i]->nunchuckConnected) { - if (Wii[i]->getButtonClick(Z)) - Serial.print(F("\r\nZ")); - if (Wii[i]->getButtonClick(C)) - Serial.print(F("\r\nC")); - if (Wii[i]->getAnalogHat(HatX) > 137 || Wii[i]->getAnalogHat(HatX) < 117 || Wii[i]->getAnalogHat(HatY) > 137 || Wii[i]->getAnalogHat(HatY) < 117) { - Serial.print(F("\r\nHatX: ")); - Serial.print(Wii[i]->getAnalogHat(HatX)); - Serial.print(F("\tHatY: ")); - Serial.print(Wii[i]->getAnalogHat(HatY)); - } - } - } -} - -void onInit() { - for (uint8_t i = 0; i < length; i++) { - if (Wii[i]->wiimoteConnected && !oldControllerState[i]) { - oldControllerState[i] = true; // Used to check which is the new controller - Wii[i]->setLedOn((LEDEnum)(i + 1)); // Cast directly to LEDEnum - see: "controllerEnums.h" - } - } -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/WiiUProController/WiiUProController.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/WiiUProController/WiiUProController.ino deleted file mode 100644 index ab35a27479..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/WiiUProController/WiiUProController.ino +++ /dev/null @@ -1,104 +0,0 @@ -/* - Example sketch for the Wiimote Bluetooth library - developed by Kristian Lauszus - For more information visit my blog: http://blog.tkjelectronics.dk/ or - send me an e-mail: kristianl@tkjelectronics.com - */ - -#include -#include - -// Satisfy the IDE, which needs to see the include statment in the ino too. -#ifdef dobogusinclude -#include -#include -#endif - -USB Usb; -//USBHub Hub1(&Usb); // Some dongles have a hub inside - -BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so -/* You can create the instance of the class in two ways */ -WII Wii(&Btd, PAIR); // This will start an inquiry and then pair with your Wiimote - you only have to do this once -//WII Wii(&Btd); // After that you can simply create the instance like so and then press any button on the Wiimote - -void setup() { - Serial.begin(115200); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - if (Usb.Init() == -1) { - Serial.print(F("\r\nOSC did not start")); - while (1); //halt - } - Serial.print(F("\r\nWiimote Bluetooth Library Started")); -} -void loop() { - Usb.Task(); - if (Wii.wiiUProControllerConnected) { - if (Wii.getButtonClick(HOME)) { // You can use getButtonPress to see if the button is held down - Serial.print(F("\r\nHome")); - Wii.disconnect(); - } - else { - if (Wii.getButtonClick(LEFT)) { - Wii.setLedOff(); - Wii.setLedOn(LED1); - Serial.print(F("\r\nLeft")); - } - if (Wii.getButtonClick(RIGHT)) { - Wii.setLedOff(); - Wii.setLedOn(LED3); - Serial.print(F("\r\nRight")); - } - if (Wii.getButtonClick(DOWN)) { - Wii.setLedOff(); - Wii.setLedOn(LED4); - Serial.print(F("\r\nDown")); - } - if (Wii.getButtonClick(UP)) { - Wii.setLedOff(); - Wii.setLedOn(LED2); - Serial.print(F("\r\nUp")); - } - - if (Wii.getButtonClick(PLUS)) - Serial.print(F("\r\nPlus")); - if (Wii.getButtonClick(MINUS)) - Serial.print(F("\r\nMinus")); - - if (Wii.getButtonClick(A)) - Serial.print(F("\r\nA")); - if (Wii.getButtonClick(B)) { - Wii.setRumbleToggle(); - Serial.print(F("\r\nB")); - } - if (Wii.getButtonClick(X)) - Serial.print(F("\r\nX")); - if (Wii.getButtonClick(Y)) - Serial.print(F("\r\nY")); - - if (Wii.getButtonClick(L)) - Serial.print(F("\r\nL")); - if (Wii.getButtonClick(R)) - Serial.print(F("\r\nR")); - if (Wii.getButtonClick(ZL)) - Serial.print(F("\r\nZL")); - if (Wii.getButtonClick(ZR)) - Serial.print(F("\r\nZR")); - if (Wii.getButtonClick(L3)) - Serial.print(F("\r\nL3")); - if (Wii.getButtonClick(R3)) - Serial.print(F("\r\nR3")); - } - if (Wii.getAnalogHat(LeftHatX) > 2200 || Wii.getAnalogHat(LeftHatX) < 1800 || Wii.getAnalogHat(LeftHatY) > 2200 || Wii.getAnalogHat(LeftHatY) < 1800 || Wii.getAnalogHat(RightHatX) > 2200 || Wii.getAnalogHat(RightHatX) < 1800 || Wii.getAnalogHat(RightHatY) > 2200 || Wii.getAnalogHat(RightHatY) < 1800) { - Serial.print(F("\r\nLeftHatX: ")); - Serial.print(Wii.getAnalogHat(LeftHatX)); - Serial.print(F("\tLeftHatY: ")); - Serial.print(Wii.getAnalogHat(LeftHatY)); - Serial.print(F("\tRightHatX: ")); - Serial.print(Wii.getAnalogHat(RightHatX)); - Serial.print(F("\tRightHatY: ")); - Serial.print(Wii.getAnalogHat(RightHatY)); - } - } -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDBootKbd/USBHIDBootKbd.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDBootKbd/USBHIDBootKbd.ino deleted file mode 100644 index 48b33abfd2..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDBootKbd/USBHIDBootKbd.ino +++ /dev/null @@ -1,129 +0,0 @@ -#include -#include - -// Satisfy the IDE, which needs to see the include statment in the ino too. -#ifdef dobogusinclude -#include -#include -#endif - -class KbdRptParser : public KeyboardReportParser -{ - void PrintKey(uint8_t mod, uint8_t key); - - protected: - void OnControlKeysChanged(uint8_t before, uint8_t after); - - void OnKeyDown (uint8_t mod, uint8_t key); - void OnKeyUp (uint8_t mod, uint8_t key); - void OnKeyPressed(uint8_t key); -}; - -void KbdRptParser::PrintKey(uint8_t m, uint8_t key) -{ - MODIFIERKEYS mod; - *((uint8_t*)&mod) = m; - Serial.print((mod.bmLeftCtrl == 1) ? "C" : " "); - Serial.print((mod.bmLeftShift == 1) ? "S" : " "); - Serial.print((mod.bmLeftAlt == 1) ? "A" : " "); - Serial.print((mod.bmLeftGUI == 1) ? "G" : " "); - - Serial.print(" >"); - PrintHex(key, 0x80); - Serial.print("< "); - - Serial.print((mod.bmRightCtrl == 1) ? "C" : " "); - Serial.print((mod.bmRightShift == 1) ? "S" : " "); - Serial.print((mod.bmRightAlt == 1) ? "A" : " "); - Serial.println((mod.bmRightGUI == 1) ? "G" : " "); -}; - -void KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key) -{ - Serial.print("DN "); - PrintKey(mod, key); - uint8_t c = OemToAscii(mod, key); - - if (c) - OnKeyPressed(c); -} - -void KbdRptParser::OnControlKeysChanged(uint8_t before, uint8_t after) { - - MODIFIERKEYS beforeMod; - *((uint8_t*)&beforeMod) = before; - - MODIFIERKEYS afterMod; - *((uint8_t*)&afterMod) = after; - - if (beforeMod.bmLeftCtrl != afterMod.bmLeftCtrl) { - Serial.println("LeftCtrl changed"); - } - if (beforeMod.bmLeftShift != afterMod.bmLeftShift) { - Serial.println("LeftShift changed"); - } - if (beforeMod.bmLeftAlt != afterMod.bmLeftAlt) { - Serial.println("LeftAlt changed"); - } - if (beforeMod.bmLeftGUI != afterMod.bmLeftGUI) { - Serial.println("LeftGUI changed"); - } - - if (beforeMod.bmRightCtrl != afterMod.bmRightCtrl) { - Serial.println("RightCtrl changed"); - } - if (beforeMod.bmRightShift != afterMod.bmRightShift) { - Serial.println("RightShift changed"); - } - if (beforeMod.bmRightAlt != afterMod.bmRightAlt) { - Serial.println("RightAlt changed"); - } - if (beforeMod.bmRightGUI != afterMod.bmRightGUI) { - Serial.println("RightGUI changed"); - } - -} - -void KbdRptParser::OnKeyUp(uint8_t mod, uint8_t key) -{ - Serial.print("UP "); - PrintKey(mod, key); -} - -void KbdRptParser::OnKeyPressed(uint8_t key) -{ - Serial.print("ASCII: "); - Serial.println((char)key); -}; - -USB Usb; -//USBHub Hub(&Usb); -HIDBoot HidKeyboard(&Usb); - -uint32_t next_time; - -KbdRptParser Prs; - -void setup() -{ - Serial.begin( 115200 ); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - Serial.println("Start"); - - if (Usb.Init() == -1) - Serial.println("OSC did not start."); - - delay( 200 ); - - next_time = millis() + 5000; - - HidKeyboard.SetReportParser(0, (HIDReportParser*)&Prs); -} - -void loop() -{ - Usb.Task(); -} - diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDBootKbdAndMouse/USBHIDBootKbdAndMouse.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDBootKbdAndMouse/USBHIDBootKbdAndMouse.ino deleted file mode 100644 index 5fc8c96fc9..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDBootKbdAndMouse/USBHIDBootKbdAndMouse.ino +++ /dev/null @@ -1,178 +0,0 @@ -#include -#include - -// Satisfy IDE, which only needs to see the include statment in the ino. -#ifdef dobogusinclude -#include -#include -#endif - -class MouseRptParser : public MouseReportParser -{ - protected: - void OnMouseMove(MOUSEINFO *mi); - void OnLeftButtonUp(MOUSEINFO *mi); - void OnLeftButtonDown(MOUSEINFO *mi); - void OnRightButtonUp(MOUSEINFO *mi); - void OnRightButtonDown(MOUSEINFO *mi); - void OnMiddleButtonUp(MOUSEINFO *mi); - void OnMiddleButtonDown(MOUSEINFO *mi); -}; -void MouseRptParser::OnMouseMove(MOUSEINFO *mi) -{ - Serial.print("dx="); - Serial.print(mi->dX, DEC); - Serial.print(" dy="); - Serial.println(mi->dY, DEC); -}; -void MouseRptParser::OnLeftButtonUp (MOUSEINFO *mi) -{ - Serial.println("L Butt Up"); -}; -void MouseRptParser::OnLeftButtonDown (MOUSEINFO *mi) -{ - Serial.println("L Butt Dn"); -}; -void MouseRptParser::OnRightButtonUp (MOUSEINFO *mi) -{ - Serial.println("R Butt Up"); -}; -void MouseRptParser::OnRightButtonDown (MOUSEINFO *mi) -{ - Serial.println("R Butt Dn"); -}; -void MouseRptParser::OnMiddleButtonUp (MOUSEINFO *mi) -{ - Serial.println("M Butt Up"); -}; -void MouseRptParser::OnMiddleButtonDown (MOUSEINFO *mi) -{ - Serial.println("M Butt Dn"); -}; - -class KbdRptParser : public KeyboardReportParser -{ - void PrintKey(uint8_t mod, uint8_t key); - - protected: - void OnControlKeysChanged(uint8_t before, uint8_t after); - void OnKeyDown (uint8_t mod, uint8_t key); - void OnKeyUp (uint8_t mod, uint8_t key); - void OnKeyPressed(uint8_t key); -}; - -void KbdRptParser::PrintKey(uint8_t m, uint8_t key) -{ - MODIFIERKEYS mod; - *((uint8_t*)&mod) = m; - Serial.print((mod.bmLeftCtrl == 1) ? "C" : " "); - Serial.print((mod.bmLeftShift == 1) ? "S" : " "); - Serial.print((mod.bmLeftAlt == 1) ? "A" : " "); - Serial.print((mod.bmLeftGUI == 1) ? "G" : " "); - - Serial.print(" >"); - PrintHex(key, 0x80); - Serial.print("< "); - - Serial.print((mod.bmRightCtrl == 1) ? "C" : " "); - Serial.print((mod.bmRightShift == 1) ? "S" : " "); - Serial.print((mod.bmRightAlt == 1) ? "A" : " "); - Serial.println((mod.bmRightGUI == 1) ? "G" : " "); -}; - -void KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key) -{ - Serial.print("DN "); - PrintKey(mod, key); - uint8_t c = OemToAscii(mod, key); - - if (c) - OnKeyPressed(c); -} - -void KbdRptParser::OnControlKeysChanged(uint8_t before, uint8_t after) { - - MODIFIERKEYS beforeMod; - *((uint8_t*)&beforeMod) = before; - - MODIFIERKEYS afterMod; - *((uint8_t*)&afterMod) = after; - - if (beforeMod.bmLeftCtrl != afterMod.bmLeftCtrl) { - Serial.println("LeftCtrl changed"); - } - if (beforeMod.bmLeftShift != afterMod.bmLeftShift) { - Serial.println("LeftShift changed"); - } - if (beforeMod.bmLeftAlt != afterMod.bmLeftAlt) { - Serial.println("LeftAlt changed"); - } - if (beforeMod.bmLeftGUI != afterMod.bmLeftGUI) { - Serial.println("LeftGUI changed"); - } - - if (beforeMod.bmRightCtrl != afterMod.bmRightCtrl) { - Serial.println("RightCtrl changed"); - } - if (beforeMod.bmRightShift != afterMod.bmRightShift) { - Serial.println("RightShift changed"); - } - if (beforeMod.bmRightAlt != afterMod.bmRightAlt) { - Serial.println("RightAlt changed"); - } - if (beforeMod.bmRightGUI != afterMod.bmRightGUI) { - Serial.println("RightGUI changed"); - } - -} - -void KbdRptParser::OnKeyUp(uint8_t mod, uint8_t key) -{ - Serial.print("UP "); - PrintKey(mod, key); -} - -void KbdRptParser::OnKeyPressed(uint8_t key) -{ - Serial.print("ASCII: "); - Serial.println((char)key); -}; - -USB Usb; -USBHub Hub(&Usb); - -HIDBoot < HID_PROTOCOL_KEYBOARD | HID_PROTOCOL_MOUSE > HidComposite(&Usb); -HIDBoot HidKeyboard(&Usb); -HIDBoot HidMouse(&Usb); - -//uint32_t next_time; - -KbdRptParser KbdPrs; -MouseRptParser MousePrs; - -void setup() -{ - Serial.begin( 115200 ); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - Serial.println("Start"); - - if (Usb.Init() == -1) - Serial.println("OSC did not start."); - - delay( 200 ); - - //next_time = millis() + 5000; - - HidComposite.SetReportParser(0, (HIDReportParser*)&KbdPrs); - HidComposite.SetReportParser(1, (HIDReportParser*)&MousePrs); - HidKeyboard.SetReportParser(0, (HIDReportParser*)&KbdPrs); - HidMouse.SetReportParser(0, (HIDReportParser*)&MousePrs); -} - -void loop() -{ - Usb.Task(); -} - diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDBootMouse/USBHIDBootMouse.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDBootMouse/USBHIDBootMouse.ino deleted file mode 100644 index 53102512bd..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDBootMouse/USBHIDBootMouse.ino +++ /dev/null @@ -1,83 +0,0 @@ -#include -#include - -// Satisfy the IDE, which needs to see the include statment in the ino too. -#ifdef dobogusinclude -#include -#include -#endif - -class MouseRptParser : public MouseReportParser -{ -protected: - void OnMouseMove (MOUSEINFO *mi); - void OnLeftButtonUp (MOUSEINFO *mi); - void OnLeftButtonDown (MOUSEINFO *mi); - void OnRightButtonUp (MOUSEINFO *mi); - void OnRightButtonDown (MOUSEINFO *mi); - void OnMiddleButtonUp (MOUSEINFO *mi); - void OnMiddleButtonDown (MOUSEINFO *mi); -}; -void MouseRptParser::OnMouseMove(MOUSEINFO *mi) -{ - Serial.print("dx="); - Serial.print(mi->dX, DEC); - Serial.print(" dy="); - Serial.println(mi->dY, DEC); -}; -void MouseRptParser::OnLeftButtonUp (MOUSEINFO *mi) -{ - Serial.println("L Butt Up"); -}; -void MouseRptParser::OnLeftButtonDown (MOUSEINFO *mi) -{ - Serial.println("L Butt Dn"); -}; -void MouseRptParser::OnRightButtonUp (MOUSEINFO *mi) -{ - Serial.println("R Butt Up"); -}; -void MouseRptParser::OnRightButtonDown (MOUSEINFO *mi) -{ - Serial.println("R Butt Dn"); -}; -void MouseRptParser::OnMiddleButtonUp (MOUSEINFO *mi) -{ - Serial.println("M Butt Up"); -}; -void MouseRptParser::OnMiddleButtonDown (MOUSEINFO *mi) -{ - Serial.println("M Butt Dn"); -}; - -USB Usb; -USBHub Hub(&Usb); -HIDBoot HidMouse(&Usb); - -uint32_t next_time; - -MouseRptParser Prs; - -void setup() -{ - Serial.begin( 115200 ); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - Serial.println("Start"); - - if (Usb.Init() == -1) - Serial.println("OSC did not start."); - - delay( 200 ); - - next_time = millis() + 5000; - - HidMouse.SetReportParser(0,(HIDReportParser*)&Prs); -} - -void loop() -{ - Usb.Task(); -} - diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/USBHIDJoystick.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/USBHIDJoystick.ino deleted file mode 100644 index 956441d67a..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/USBHIDJoystick.ino +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include -#include - -// Satisfy IDE, which only needs to see the include statment in the ino. -#ifdef dobogusinclude -#include -#include -#endif - -#include "hidjoystickrptparser.h" - -USB Usb; -USBHub Hub(&Usb); -HIDUniversal Hid(&Usb); -JoystickEvents JoyEvents; -JoystickReportParser Joy(&JoyEvents); - -void setup() { - Serial.begin(115200); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - Serial.println("Start"); - - if (Usb.Init() == -1) - Serial.println("OSC did not start."); - - delay(200); - - if (!Hid.SetReportParser(0, &Joy)) - ErrorMessage (PSTR("SetReportParser"), 1); -} - -void loop() { - Usb.Task(); -} - diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/hidjoystickrptparser.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/hidjoystickrptparser.cpp deleted file mode 100644 index 083b95cac5..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/hidjoystickrptparser.cpp +++ /dev/null @@ -1,84 +0,0 @@ -#include "hidjoystickrptparser.h" - -JoystickReportParser::JoystickReportParser(JoystickEvents *evt) : -joyEvents(evt), -oldHat(0xDE), -oldButtons(0) { - for (uint8_t i = 0; i < RPT_GEMEPAD_LEN; i++) - oldPad[i] = 0xD; -} - -void JoystickReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) { - bool match = true; - - // Checking if there are changes in report since the method was last called - for (uint8_t i = 0; i < RPT_GEMEPAD_LEN; i++) - if (buf[i] != oldPad[i]) { - match = false; - break; - } - - // Calling Game Pad event handler - if (!match && joyEvents) { - joyEvents->OnGamePadChanged((const GamePadEventData*)buf); - - for (uint8_t i = 0; i < RPT_GEMEPAD_LEN; i++) oldPad[i] = buf[i]; - } - - uint8_t hat = (buf[5] & 0xF); - - // Calling Hat Switch event handler - if (hat != oldHat && joyEvents) { - joyEvents->OnHatSwitch(hat); - oldHat = hat; - } - - uint16_t buttons = (0x0000 | buf[6]); - buttons <<= 4; - buttons |= (buf[5] >> 4); - uint16_t changes = (buttons ^ oldButtons); - - // Calling Button Event Handler for every button changed - if (changes) { - for (uint8_t i = 0; i < 0x0C; i++) { - uint16_t mask = (0x0001 << i); - - if (((mask & changes) > 0) && joyEvents) - if ((buttons & mask) > 0) - joyEvents->OnButtonDn(i + 1); - else - joyEvents->OnButtonUp(i + 1); - } - oldButtons = buttons; - } -} - -void JoystickEvents::OnGamePadChanged(const GamePadEventData *evt) { - Serial.print("X1: "); - PrintHex (evt->X, 0x80); - Serial.print("\tY1: "); - PrintHex (evt->Y, 0x80); - Serial.print("\tX2: "); - PrintHex (evt->Z1, 0x80); - Serial.print("\tY2: "); - PrintHex (evt->Z2, 0x80); - Serial.print("\tRz: "); - PrintHex (evt->Rz, 0x80); - Serial.println(""); -} - -void JoystickEvents::OnHatSwitch(uint8_t hat) { - Serial.print("Hat Switch: "); - PrintHex (hat, 0x80); - Serial.println(""); -} - -void JoystickEvents::OnButtonUp(uint8_t but_id) { - Serial.print("Up: "); - Serial.println(but_id, DEC); -} - -void JoystickEvents::OnButtonDn(uint8_t but_id) { - Serial.print("Dn: "); - Serial.println(but_id, DEC); -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/hidjoystickrptparser.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/hidjoystickrptparser.h deleted file mode 100644 index 733b8f8da8..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/hidjoystickrptparser.h +++ /dev/null @@ -1,33 +0,0 @@ -#if !defined(__HIDJOYSTICKRPTPARSER_H__) -#define __HIDJOYSTICKRPTPARSER_H__ - -#include - -struct GamePadEventData { - uint8_t X, Y, Z1, Z2, Rz; -}; - -class JoystickEvents { -public: - virtual void OnGamePadChanged(const GamePadEventData *evt); - virtual void OnHatSwitch(uint8_t hat); - virtual void OnButtonUp(uint8_t but_id); - virtual void OnButtonDn(uint8_t but_id); -}; - -#define RPT_GEMEPAD_LEN 5 - -class JoystickReportParser : public HIDReportParser { - JoystickEvents *joyEvents; - - uint8_t oldPad[RPT_GEMEPAD_LEN]; - uint8_t oldHat; - uint16_t oldButtons; - -public: - JoystickReportParser(JoystickEvents *evt); - - virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); -}; - -#endif // __HIDJOYSTICKRPTPARSER_H__ diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHID_desc/USBHID_desc.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHID_desc/USBHID_desc.ino deleted file mode 100644 index 85cfc19a2e..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHID_desc/USBHID_desc.ino +++ /dev/null @@ -1,77 +0,0 @@ -#include -#include -#include -#include -#include "pgmstrings.h" - -// Satisfy the IDE, which needs to see the include statment in the ino too. -#ifdef dobogusinclude -#include -#include -#endif - -class HIDUniversal2 : public HIDUniversal -{ -public: - HIDUniversal2(USB *usb) : HIDUniversal(usb) {}; - -protected: - uint8_t OnInitSuccessful(); -}; - -uint8_t HIDUniversal2::OnInitSuccessful() -{ - uint8_t rcode; - - HexDumper Hex; - ReportDescParser Rpt; - - if ((rcode = GetReportDescr(0, &Hex))) - goto FailGetReportDescr1; - - if ((rcode = GetReportDescr(0, &Rpt))) - goto FailGetReportDescr2; - - return 0; - -FailGetReportDescr1: - USBTRACE("GetReportDescr1:"); - goto Fail; - -FailGetReportDescr2: - USBTRACE("GetReportDescr2:"); - goto Fail; - -Fail: - Serial.println(rcode, HEX); - Release(); - return rcode; -} - -USB Usb; -//USBHub Hub(&Usb); -HIDUniversal2 Hid(&Usb); -UniversalReportParser Uni; - -void setup() -{ - Serial.begin( 115200 ); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - Serial.println("Start"); - - if (Usb.Init() == -1) - Serial.println("OSC did not start."); - - delay( 200 ); - - if (!Hid.SetReportParser(0, &Uni)) - ErrorMessage(PSTR("SetReportParser"), 1 ); -} - -void loop() -{ - Usb.Task(); -} - diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHID_desc/pgmstrings.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHID_desc/pgmstrings.h deleted file mode 100644 index bdb0077ecc..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHID_desc/pgmstrings.h +++ /dev/null @@ -1,52 +0,0 @@ -#if !defined(__PGMSTRINGS_H__) -#define __PGMSTRINGS_H__ - -#define LOBYTE(x) ((char*)(&(x)))[0] -#define HIBYTE(x) ((char*)(&(x)))[1] -#define BUFSIZE 256 //buffer size - - -/* Print strings in Program Memory */ -const char Gen_Error_str[] PROGMEM = "\r\nRequest error. Error code:\t"; -const char Dev_Header_str[] PROGMEM ="\r\nDevice descriptor: "; -const char Dev_Length_str[] PROGMEM ="\r\nDescriptor Length:\t"; -const char Dev_Type_str[] PROGMEM ="\r\nDescriptor type:\t"; -const char Dev_Version_str[] PROGMEM ="\r\nUSB version:\t\t"; -const char Dev_Class_str[] PROGMEM ="\r\nDevice class:\t\t"; -const char Dev_Subclass_str[] PROGMEM ="\r\nDevice Subclass:\t"; -const char Dev_Protocol_str[] PROGMEM ="\r\nDevice Protocol:\t"; -const char Dev_Pktsize_str[] PROGMEM ="\r\nMax.packet size:\t"; -const char Dev_Vendor_str[] PROGMEM ="\r\nVendor ID:\t\t"; -const char Dev_Product_str[] PROGMEM ="\r\nProduct ID:\t\t"; -const char Dev_Revision_str[] PROGMEM ="\r\nRevision ID:\t\t"; -const char Dev_Mfg_str[] PROGMEM ="\r\nMfg.string index:\t"; -const char Dev_Prod_str[] PROGMEM ="\r\nProd.string index:\t"; -const char Dev_Serial_str[] PROGMEM ="\r\nSerial number index:\t"; -const char Dev_Nconf_str[] PROGMEM ="\r\nNumber of conf.:\t"; -const char Conf_Trunc_str[] PROGMEM ="Total length truncated to 256 bytes"; -const char Conf_Header_str[] PROGMEM ="\r\nConfiguration descriptor:"; -const char Conf_Totlen_str[] PROGMEM ="\r\nTotal length:\t\t"; -const char Conf_Nint_str[] PROGMEM ="\r\nNum.intf:\t\t"; -const char Conf_Value_str[] PROGMEM ="\r\nConf.value:\t\t"; -const char Conf_String_str[] PROGMEM ="\r\nConf.string:\t\t"; -const char Conf_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t"; -const char Conf_Pwr_str[] PROGMEM ="\r\nMax.pwr:\t\t"; -const char Int_Header_str[] PROGMEM ="\r\n\r\nInterface descriptor:"; -const char Int_Number_str[] PROGMEM ="\r\nIntf.number:\t\t"; -const char Int_Alt_str[] PROGMEM ="\r\nAlt.:\t\t\t"; -const char Int_Endpoints_str[] PROGMEM ="\r\nEndpoints:\t\t"; -const char Int_Class_str[] PROGMEM ="\r\nIntf. Class:\t\t"; -const char Int_Subclass_str[] PROGMEM ="\r\nIntf. Subclass:\t\t"; -const char Int_Protocol_str[] PROGMEM ="\r\nIntf. Protocol:\t\t"; -const char Int_String_str[] PROGMEM ="\r\nIntf.string:\t\t"; -const char End_Header_str[] PROGMEM ="\r\n\r\nEndpoint descriptor:"; -const char End_Address_str[] PROGMEM ="\r\nEndpoint address:\t"; -const char End_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t"; -const char End_Pktsize_str[] PROGMEM ="\r\nMax.pkt size:\t\t"; -const char End_Interval_str[] PROGMEM ="\r\nPolling interval:\t"; -const char Unk_Header_str[] PROGMEM = "\r\nUnknown descriptor:"; -const char Unk_Length_str[] PROGMEM ="\r\nLength:\t\t"; -const char Unk_Type_str[] PROGMEM ="\r\nType:\t\t"; -const char Unk_Contents_str[] PROGMEM ="\r\nContents:\t"; - -#endif // __PGMSTRINGS_H__ \ No newline at end of file diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp.ino deleted file mode 100644 index 837d7f5a70..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp.ino +++ /dev/null @@ -1,42 +0,0 @@ -/* Simplified Logitech Extreme 3D Pro Joystick Report Parser */ - -#include -#include -#include - -#include "le3dp_rptparser.h" - -// Satisfy the IDE, which needs to see the include statment in the ino too. -#ifdef dobogusinclude -#include -#include -#endif - -USB Usb; -USBHub Hub(&Usb); -HIDUniversal Hid(&Usb); -JoystickEvents JoyEvents; -JoystickReportParser Joy(&JoyEvents); - -void setup() -{ - Serial.begin( 115200 ); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - Serial.println("Start"); - - if (Usb.Init() == -1) - Serial.println("OSC did not start."); - - delay( 200 ); - - if (!Hid.SetReportParser(0, &Joy)) - ErrorMessage(PSTR("SetReportParser"), 1 ); -} - -void loop() -{ - Usb.Task(); -} - diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp_rptparser.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp_rptparser.cpp deleted file mode 100644 index baece13b2c..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp_rptparser.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include "le3dp_rptparser.h" - -JoystickReportParser::JoystickReportParser(JoystickEvents *evt) : - joyEvents(evt) -{} - -void JoystickReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) -{ - bool match = true; - - // Checking if there are changes in report since the method was last called - for (uint8_t i=0; iOnGamePadChanged((const GamePadEventData*)buf); - - for (uint8_t i=0; i(evt->x, 0x80); - Serial.print(" Y: "); - PrintHex(evt->y, 0x80); - Serial.print(" Hat Switch: "); - PrintHex(evt->hat, 0x80); - Serial.print(" Twist: "); - PrintHex(evt->twist, 0x80); - Serial.print(" Slider: "); - PrintHex(evt->slider, 0x80); - Serial.print(" Buttons A: "); - PrintHex(evt->buttons_a, 0x80); - Serial.print(" Buttons B: "); - PrintHex(evt->buttons_b, 0x80); - Serial.println(""); -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp_rptparser.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp_rptparser.h deleted file mode 100644 index 2400364e65..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp_rptparser.h +++ /dev/null @@ -1,42 +0,0 @@ -#if !defined(__HIDJOYSTICKRPTPARSER_H__) -#define __HIDJOYSTICKRPTPARSER_H__ - -#include - -struct GamePadEventData -{ - union { //axes and hut switch - uint32_t axes; - struct { - uint32_t x : 10; - uint32_t y : 10; - uint32_t hat : 4; - uint32_t twist : 8; - }; - }; - uint8_t buttons_a; - uint8_t slider; - uint8_t buttons_b; -}; - -class JoystickEvents -{ -public: - virtual void OnGamePadChanged(const GamePadEventData *evt); -}; - -#define RPT_GAMEPAD_LEN sizeof(GamePadEventData)/sizeof(uint8_t) - -class JoystickReportParser : public HIDReportParser -{ - JoystickEvents *joyEvents; - - uint8_t oldPad[RPT_GAMEPAD_LEN]; - -public: - JoystickReportParser(JoystickEvents *evt); - - virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); -}; - -#endif // __HIDJOYSTICKRPTPARSER_H__ diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/scale/scale.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/scale/scale.ino deleted file mode 100644 index f26ff964da..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/scale/scale.ino +++ /dev/null @@ -1,51 +0,0 @@ -/* Digital Scale Output. Written for Stamps.com Model 510 */ -/* 5lb Digital Scale; any HID scale with Usage page 0x8d should work */ - -#include -#include -#include - -#include "scale_rptparser.h" - -// Satisfy the IDE, which needs to see the include statment in the ino too. -#ifdef dobogusinclude -#include -#include -#endif - -USB Usb; -USBHub Hub(&Usb); -HIDUniversal Hid(&Usb); -Max_LCD LCD(&Usb); -ScaleEvents ScaleEvents(&LCD); -ScaleReportParser Scale(&ScaleEvents); - -void setup() -{ - Serial.begin( 115200 ); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - Serial.println("Start"); - - if (Usb.Init() == -1) - Serial.println("OSC did not start."); - - // set up the LCD's number of rows and columns: - LCD.begin(16, 2); - LCD.clear(); - LCD.home(); - LCD.setCursor(0,0); - LCD.write('R'); - - delay( 200 ); - - if (!Hid.SetReportParser(0, &Scale)) - ErrorMessage(PSTR("SetReportParser"), 1 ); -} - -void loop() -{ - Usb.Task(); -} - diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/scale/scale_rptparser.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/scale/scale_rptparser.cpp deleted file mode 100644 index 01ed980cfb..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/scale/scale_rptparser.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/* Parser for standard HID scale (usage page 0x8d) data input report (ID 3) */ -#include "scale_rptparser.h" - -const char* UNITS[13] = { - "units", // unknown unit - "mg", // milligram - "g", // gram - "kg", // kilogram - "cd", // carat - "taels", // lian - "gr", // grain - "dwt", // pennyweight - "tonnes", // metric tons - "tons", // avoir ton - "ozt", // troy ounce - "oz", // ounce - "lbs" // pound -}; - -ScaleReportParser::ScaleReportParser(ScaleEvents *evt) : - scaleEvents(evt) -{} - -void ScaleReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) -{ - bool match = true; - - // Checking if there are changes in report since the method was last called - for (uint8_t i=0; iOnScaleChanged((const ScaleEventData*)buf); - - for (uint8_t i=0; iwrite( *str++ ); - - } -} - -void ScaleEvents::OnScaleChanged(const ScaleEventData *evt) -{ - - pLcd->clear(); - pLcd->home(); - pLcd->setCursor(0,0); - - if( evt->reportID != 3 ) { - - const char inv_report[]="Invalid report!"; - - Serial.println(inv_report); - LcdPrint(inv_report); - - return; - - }//if( evt->reportID != 3... - - switch( evt->status ) { - - case REPORT_FAULT: - Serial.println(F("Report fault")); - break; - - case ZEROED: - Serial.println(F("Scale zero set")); - break; - - case WEIGHING: { - - const char progress[] = "Weighing..."; - Serial.println(progress); - LcdPrint(progress); - break; - } - - case WEIGHT_VALID: { - - char buf[10]; - double weight = evt->weight * pow( 10, evt->exp ); - - - - Serial.print(F("Weight: ")); - Serial.print( weight ); - Serial.print(F(" ")); - Serial.println( UNITS[ evt->unit ]); - - LcdPrint("Weight: "); - dtostrf( weight, 4, 2, buf ); - LcdPrint( buf ); - LcdPrint( UNITS[ evt->unit ]); - - break; - - }//case WEIGHT_VALID... - - case WEIGHT_NEGATIVE: { - - const char negweight[] = "Negative weight"; - Serial.println(negweight); - LcdPrint(negweight); - break; - } - - case OVERWEIGHT: { - - const char overweight[] = "Max.weight reached"; - Serial.println(overweight); - LcdPrint( overweight ); - break; - } - - case CALIBRATE_ME: - - Serial.println(F("Scale calibration required")); - break; - - case ZERO_ME: - - Serial.println(F("Scale zeroing required")); - break; - - default: - - Serial.print(F("Undefined status code: ")); - Serial.println( evt->status ); - break; - - }//switch( evt->status... - -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/scale/scale_rptparser.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/scale/scale_rptparser.h deleted file mode 100644 index 57fbb033bf..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/scale/scale_rptparser.h +++ /dev/null @@ -1,55 +0,0 @@ -#if !defined(__SCALERPTPARSER_H__) -#define __SCALERPTPARSER_H__ - -#include -#include - -/* Scale status constants */ -#define REPORT_FAULT 0x01 -#define ZEROED 0x02 -#define WEIGHING 0x03 -#define WEIGHT_VALID 0x04 -#define WEIGHT_NEGATIVE 0x05 -#define OVERWEIGHT 0x06 -#define CALIBRATE_ME 0x07 -#define ZERO_ME 0x08 - -/* input data report */ -struct ScaleEventData -{ - uint8_t reportID; //must be 3 - uint8_t status; - uint8_t unit; - int8_t exp; //scale factor for the weight - uint16_t weight; // -}; - -class ScaleEvents -{ - - Max_LCD* pLcd; - - void LcdPrint( const char* str ); - -public: - - ScaleEvents( Max_LCD* pLCD ); - - virtual void OnScaleChanged(const ScaleEventData *evt); -}; - -#define RPT_SCALE_LEN sizeof(ScaleEventData)/sizeof(uint8_t) - -class ScaleReportParser : public HIDReportParser -{ - ScaleEvents *scaleEvents; - - uint8_t oldScale[RPT_SCALE_LEN]; - -public: - ScaleReportParser(ScaleEvents *evt); - - virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); -}; - -#endif // __SCALERPTPARSER_H__ diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/PS3USB/PS3USB.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/PS3USB/PS3USB.ino deleted file mode 100644 index a53dcfbe61..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/PS3USB/PS3USB.ino +++ /dev/null @@ -1,148 +0,0 @@ -/* - Example sketch for the PS3 USB library - developed by Kristian Lauszus - For more information visit my blog: http://blog.tkjelectronics.dk/ or - send me an e-mail: kristianl@tkjelectronics.com - */ - -#include - -// Satisfy the IDE, which needs to see the include statment in the ino too. -#ifdef dobogusinclude -#include -#include -#endif - -USB Usb; -/* You can create the instance of the class in two ways */ -PS3USB PS3(&Usb); // This will just create the instance -//PS3USB PS3(&Usb,0x00,0x15,0x83,0x3D,0x0A,0x57); // This will also store the bluetooth address - this can be obtained from the dongle when running the sketch - -bool printAngle; -uint8_t state = 0; - -void setup() { - Serial.begin(115200); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - if (Usb.Init() == -1) { - Serial.print(F("\r\nOSC did not start")); - while (1); //halt - } - Serial.print(F("\r\nPS3 USB Library Started")); -} -void loop() { - Usb.Task(); - - if (PS3.PS3Connected || PS3.PS3NavigationConnected) { - if (PS3.getAnalogHat(LeftHatX) > 137 || PS3.getAnalogHat(LeftHatX) < 117 || PS3.getAnalogHat(LeftHatY) > 137 || PS3.getAnalogHat(LeftHatY) < 117 || PS3.getAnalogHat(RightHatX) > 137 || PS3.getAnalogHat(RightHatX) < 117 || PS3.getAnalogHat(RightHatY) > 137 || PS3.getAnalogHat(RightHatY) < 117) { - Serial.print(F("\r\nLeftHatX: ")); - Serial.print(PS3.getAnalogHat(LeftHatX)); - Serial.print(F("\tLeftHatY: ")); - Serial.print(PS3.getAnalogHat(LeftHatY)); - if (PS3.PS3Connected) { // The Navigation controller only have one joystick - Serial.print(F("\tRightHatX: ")); - Serial.print(PS3.getAnalogHat(RightHatX)); - Serial.print(F("\tRightHatY: ")); - Serial.print(PS3.getAnalogHat(RightHatY)); - } - } - // Analog button values can be read from almost all buttons - if (PS3.getAnalogButton(L2) || PS3.getAnalogButton(R2)) { - Serial.print(F("\r\nL2: ")); - Serial.print(PS3.getAnalogButton(L2)); - if (!PS3.PS3NavigationConnected) { - Serial.print(F("\tR2: ")); - Serial.print(PS3.getAnalogButton(R2)); - } - } - if (PS3.getButtonClick(PS)) - Serial.print(F("\r\nPS")); - - if (PS3.getButtonClick(TRIANGLE)) - Serial.print(F("\r\nTraingle")); - if (PS3.getButtonClick(CIRCLE)) - Serial.print(F("\r\nCircle")); - if (PS3.getButtonClick(CROSS)) - Serial.print(F("\r\nCross")); - if (PS3.getButtonClick(SQUARE)) - Serial.print(F("\r\nSquare")); - - if (PS3.getButtonClick(UP)) { - Serial.print(F("\r\nUp")); - PS3.setLedOff(); - PS3.setLedOn(LED4); - } - if (PS3.getButtonClick(RIGHT)) { - Serial.print(F("\r\nRight")); - PS3.setLedOff(); - PS3.setLedOn(LED1); - } - if (PS3.getButtonClick(DOWN)) { - Serial.print(F("\r\nDown")); - PS3.setLedOff(); - PS3.setLedOn(LED2); - } - if (PS3.getButtonClick(LEFT)) { - Serial.print(F("\r\nLeft")); - PS3.setLedOff(); - PS3.setLedOn(LED3); - } - - if (PS3.getButtonClick(L1)) - Serial.print(F("\r\nL1")); - if (PS3.getButtonClick(L3)) - Serial.print(F("\r\nL3")); - if (PS3.getButtonClick(R1)) - Serial.print(F("\r\nR1")); - if (PS3.getButtonClick(R3)) - Serial.print(F("\r\nR3")); - - if (PS3.getButtonClick(SELECT)) { - Serial.print(F("\r\nSelect - ")); - PS3.printStatusString(); - } - if (PS3.getButtonClick(START)) { - Serial.print(F("\r\nStart")); - printAngle = !printAngle; - } - if (printAngle) { - Serial.print(F("\r\nPitch: ")); - Serial.print(PS3.getAngle(Pitch)); - Serial.print(F("\tRoll: ")); - Serial.print(PS3.getAngle(Roll)); - } - } - else if (PS3.PS3MoveConnected) { // One can only set the color of the bulb, set the rumble, set and get the bluetooth address and calibrate the magnetometer via USB - if (state == 0) { - PS3.moveSetRumble(0); - PS3.moveSetBulb(Off); - } else if (state == 1) { - PS3.moveSetRumble(75); - PS3.moveSetBulb(Red); - } else if (state == 2) { - PS3.moveSetRumble(125); - PS3.moveSetBulb(Green); - } else if (state == 3) { - PS3.moveSetRumble(150); - PS3.moveSetBulb(Blue); - } else if (state == 4) { - PS3.moveSetRumble(175); - PS3.moveSetBulb(Yellow); - } else if (state == 5) { - PS3.moveSetRumble(200); - PS3.moveSetBulb(Lightblue); - } else if (state == 6) { - PS3.moveSetRumble(225); - PS3.moveSetBulb(Purble); - } else if (state == 7) { - PS3.moveSetRumble(250); - PS3.moveSetBulb(White); - } - - state++; - if (state > 7) - state = 0; - delay(1000); - } -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/PS4USB/PS4USB.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/PS4USB/PS4USB.ino deleted file mode 100644 index d0d76790ec..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/PS4USB/PS4USB.ino +++ /dev/null @@ -1,133 +0,0 @@ -/* - Example sketch for the PS4 USB library - developed by Kristian Lauszus - For more information visit my blog: http://blog.tkjelectronics.dk/ or - send me an e-mail: kristianl@tkjelectronics.com - */ - -#include - -// Satisfy the IDE, which needs to see the include statment in the ino too. -#ifdef dobogusinclude -#include -#include -#endif - -USB Usb; -PS4USB PS4(&Usb); - -bool printAngle, printTouch; -uint8_t oldL2Value, oldR2Value; - -void setup() { - Serial.begin(115200); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - if (Usb.Init() == -1) { - Serial.print(F("\r\nOSC did not start")); - while (1); // Halt - } - Serial.print(F("\r\nPS4 USB Library Started")); -} - -void loop() { - Usb.Task(); - - if (PS4.connected()) { - if (PS4.getAnalogHat(LeftHatX) > 137 || PS4.getAnalogHat(LeftHatX) < 117 || PS4.getAnalogHat(LeftHatY) > 137 || PS4.getAnalogHat(LeftHatY) < 117 || PS4.getAnalogHat(RightHatX) > 137 || PS4.getAnalogHat(RightHatX) < 117 || PS4.getAnalogHat(RightHatY) > 137 || PS4.getAnalogHat(RightHatY) < 117) { - Serial.print(F("\r\nLeftHatX: ")); - Serial.print(PS4.getAnalogHat(LeftHatX)); - Serial.print(F("\tLeftHatY: ")); - Serial.print(PS4.getAnalogHat(LeftHatY)); - Serial.print(F("\tRightHatX: ")); - Serial.print(PS4.getAnalogHat(RightHatX)); - Serial.print(F("\tRightHatY: ")); - Serial.print(PS4.getAnalogHat(RightHatY)); - } - - if (PS4.getAnalogButton(L2) || PS4.getAnalogButton(R2)) { // These are the only analog buttons on the PS4 controller - Serial.print(F("\r\nL2: ")); - Serial.print(PS4.getAnalogButton(L2)); - Serial.print(F("\tR2: ")); - Serial.print(PS4.getAnalogButton(R2)); - } - if (PS4.getAnalogButton(L2) != oldL2Value || PS4.getAnalogButton(R2) != oldR2Value) // Only write value if it's different - PS4.setRumbleOn(PS4.getAnalogButton(L2), PS4.getAnalogButton(R2)); - oldL2Value = PS4.getAnalogButton(L2); - oldR2Value = PS4.getAnalogButton(R2); - - if (PS4.getButtonClick(PS)) - Serial.print(F("\r\nPS")); - if (PS4.getButtonClick(TRIANGLE)) { - Serial.print(F("\r\nTraingle")); - PS4.setRumbleOn(RumbleLow); - } - if (PS4.getButtonClick(CIRCLE)) { - Serial.print(F("\r\nCircle")); - PS4.setRumbleOn(RumbleHigh); - } - if (PS4.getButtonClick(CROSS)) { - Serial.print(F("\r\nCross")); - PS4.setLedFlash(10, 10); // Set it to blink rapidly - } - if (PS4.getButtonClick(SQUARE)) { - Serial.print(F("\r\nSquare")); - PS4.setLedFlash(0, 0); // Turn off blinking - } - - if (PS4.getButtonClick(UP)) { - Serial.print(F("\r\nUp")); - PS4.setLed(Red); - } if (PS4.getButtonClick(RIGHT)) { - Serial.print(F("\r\nRight")); - PS4.setLed(Blue); - } if (PS4.getButtonClick(DOWN)) { - Serial.print(F("\r\nDown")); - PS4.setLed(Yellow); - } if (PS4.getButtonClick(LEFT)) { - Serial.print(F("\r\nLeft")); - PS4.setLed(Green); - } - - if (PS4.getButtonClick(L1)) - Serial.print(F("\r\nL1")); - if (PS4.getButtonClick(L3)) - Serial.print(F("\r\nL3")); - if (PS4.getButtonClick(R1)) - Serial.print(F("\r\nR1")); - if (PS4.getButtonClick(R3)) - Serial.print(F("\r\nR3")); - - if (PS4.getButtonClick(SHARE)) - Serial.print(F("\r\nShare")); - if (PS4.getButtonClick(OPTIONS)) { - Serial.print(F("\r\nOptions")); - printAngle = !printAngle; - } - if (PS4.getButtonClick(TOUCHPAD)) { - Serial.print(F("\r\nTouchpad")); - printTouch = !printTouch; - } - - if (printAngle) { // Print angle calculated using the accelerometer only - Serial.print(F("\r\nPitch: ")); - Serial.print(PS4.getAngle(Pitch)); - Serial.print(F("\tRoll: ")); - Serial.print(PS4.getAngle(Roll)); - } - - if (printTouch) { // Print the x, y coordinates of the touchpad - if (PS4.isTouching(0) || PS4.isTouching(1)) // Print newline and carriage return if any of the fingers are touching the touchpad - Serial.print(F("\r\n")); - for (uint8_t i = 0; i < 2; i++) { // The touchpad track two fingers - if (PS4.isTouching(i)) { // Print the position of the finger if it is touching the touchpad - Serial.print(F("X")); Serial.print(i + 1); Serial.print(F(": ")); - Serial.print(PS4.getX(i)); - Serial.print(F("\tY")); Serial.print(i + 1); Serial.print(F(": ")); - Serial.print(PS4.getY(i)); - Serial.print(F("\t")); - } - } - } - } -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/PSBuzz/PSBuzz.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/PSBuzz/PSBuzz.ino deleted file mode 100644 index 6ee462c1eb..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/PSBuzz/PSBuzz.ino +++ /dev/null @@ -1,49 +0,0 @@ -/* - Example sketch for the Playstation Buzz library - developed by Kristian Lauszus - For more information visit my blog: http://blog.tkjelectronics.dk/ or - send me an e-mail: kristianl@tkjelectronics.com - */ - -#include - -// Satisfy the IDE, which needs to see the include statment in the ino too. -#ifdef dobogusinclude -#include -#include -#endif - -USB Usb; -PSBuzz Buzz(&Usb); - -void setup() { - Serial.begin(115200); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - if (Usb.Init() == -1) { - Serial.print(F("\r\nOSC did not start")); - while (1); // Halt - } - Serial.println(F("\r\nPS Buzz Library Started")); -} - -void loop() { - Usb.Task(); - - if (Buzz.connected()) { - for (uint8_t i = 0; i < 4; i++) { - if (Buzz.getButtonClick(RED, i)) { - Buzz.setLedToggle(i); // Toggle the LED - Serial.println(F("RED")); - } - if (Buzz.getButtonClick(YELLOW, i)) - Serial.println(F("YELLOW")); - if (Buzz.getButtonClick(GREEN, i)) - Serial.println(F("GREEN")); - if (Buzz.getButtonClick(ORANGE, i)) - Serial.println(F("ORANGE")); - if (Buzz.getButtonClick(BLUE, i)) - Serial.println(F("BLUE")); - } - } -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/USB_desc/USB_desc.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/USB_desc/USB_desc.ino deleted file mode 100644 index acfe57d374..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/USB_desc/USB_desc.ino +++ /dev/null @@ -1,349 +0,0 @@ -#include - -#include "pgmstrings.h" - -// Satisfy the IDE, which needs to see the include statment in the ino too. -#ifdef dobogusinclude -#include -#include -#endif - -USB Usb; -//USBHub Hub1(&Usb); -//USBHub Hub2(&Usb); -//USBHub Hub3(&Usb); -//USBHub Hub4(&Usb); -//USBHub Hub5(&Usb); -//USBHub Hub6(&Usb); -//USBHub Hub7(&Usb); - -uint32_t next_time; - -void PrintAllAddresses(UsbDevice *pdev) -{ - UsbDeviceAddress adr; - adr.devAddress = pdev->address.devAddress; - Serial.print("\r\nAddr:"); - Serial.print(adr.devAddress, HEX); - Serial.print("("); - Serial.print(adr.bmHub, HEX); - Serial.print("."); - Serial.print(adr.bmParent, HEX); - Serial.print("."); - Serial.print(adr.bmAddress, HEX); - Serial.println(")"); -} - -void PrintAddress(uint8_t addr) -{ - UsbDeviceAddress adr; - adr.devAddress = addr; - Serial.print("\r\nADDR:\t"); - Serial.println(adr.devAddress, HEX); - Serial.print("DEV:\t"); - Serial.println(adr.bmAddress, HEX); - Serial.print("PRNT:\t"); - Serial.println(adr.bmParent, HEX); - Serial.print("HUB:\t"); - Serial.println(adr.bmHub, HEX); -} - -void setup() -{ - Serial.begin( 115200 ); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - Serial.println("Start"); - - if (Usb.Init() == -1) - Serial.println("OSC did not start."); - - delay( 200 ); - - next_time = millis() + 10000; -} - -byte getdevdescr( byte addr, byte &num_conf ); - -void PrintDescriptors(uint8_t addr) -{ - uint8_t rcode = 0; - byte num_conf = 0; - - rcode = getdevdescr( (byte)addr, num_conf ); - if ( rcode ) - { - printProgStr(Gen_Error_str); - print_hex( rcode, 8 ); - } - Serial.print("\r\n"); - - for (int i = 0; i < num_conf; i++) - { - rcode = getconfdescr( addr, i ); // get configuration descriptor - if ( rcode ) - { - printProgStr(Gen_Error_str); - print_hex(rcode, 8); - } - Serial.println("\r\n"); - } -} - -void PrintAllDescriptors(UsbDevice *pdev) -{ - Serial.println("\r\n"); - print_hex(pdev->address.devAddress, 8); - Serial.println("\r\n--"); - PrintDescriptors( pdev->address.devAddress ); -} - -void loop() -{ - Usb.Task(); - - if ( Usb.getUsbTaskState() == USB_STATE_RUNNING ) - { - //if (millis() >= next_time) - { - Usb.ForEachUsbDevice(&PrintAllDescriptors); - Usb.ForEachUsbDevice(&PrintAllAddresses); - - while ( 1 ); //stop - } - } -} - -byte getdevdescr( byte addr, byte &num_conf ) -{ - USB_DEVICE_DESCRIPTOR buf; - byte rcode; - rcode = Usb.getDevDescr( addr, 0, 0x12, ( uint8_t *)&buf ); - if ( rcode ) { - return ( rcode ); - } - printProgStr(Dev_Header_str); - printProgStr(Dev_Length_str); - print_hex( buf.bLength, 8 ); - printProgStr(Dev_Type_str); - print_hex( buf.bDescriptorType, 8 ); - printProgStr(Dev_Version_str); - print_hex( buf.bcdUSB, 16 ); - printProgStr(Dev_Class_str); - print_hex( buf.bDeviceClass, 8 ); - printProgStr(Dev_Subclass_str); - print_hex( buf.bDeviceSubClass, 8 ); - printProgStr(Dev_Protocol_str); - print_hex( buf.bDeviceProtocol, 8 ); - printProgStr(Dev_Pktsize_str); - print_hex( buf.bMaxPacketSize0, 8 ); - printProgStr(Dev_Vendor_str); - print_hex( buf.idVendor, 16 ); - printProgStr(Dev_Product_str); - print_hex( buf.idProduct, 16 ); - printProgStr(Dev_Revision_str); - print_hex( buf.bcdDevice, 16 ); - printProgStr(Dev_Mfg_str); - print_hex( buf.iManufacturer, 8 ); - printProgStr(Dev_Prod_str); - print_hex( buf.iProduct, 8 ); - printProgStr(Dev_Serial_str); - print_hex( buf.iSerialNumber, 8 ); - printProgStr(Dev_Nconf_str); - print_hex( buf.bNumConfigurations, 8 ); - num_conf = buf.bNumConfigurations; - return ( 0 ); -} - -void printhubdescr(uint8_t *descrptr, uint8_t addr) -{ - HubDescriptor *pHub = (HubDescriptor*) descrptr; - uint8_t len = *((uint8_t*)descrptr); - - printProgStr(PSTR("\r\n\r\nHub Descriptor:\r\n")); - printProgStr(PSTR("bDescLength:\t\t")); - Serial.println(pHub->bDescLength, HEX); - - printProgStr(PSTR("bDescriptorType:\t")); - Serial.println(pHub->bDescriptorType, HEX); - - printProgStr(PSTR("bNbrPorts:\t\t")); - Serial.println(pHub->bNbrPorts, HEX); - - printProgStr(PSTR("LogPwrSwitchMode:\t")); - Serial.println(pHub->LogPwrSwitchMode, BIN); - - printProgStr(PSTR("CompoundDevice:\t\t")); - Serial.println(pHub->CompoundDevice, BIN); - - printProgStr(PSTR("OverCurrentProtectMode:\t")); - Serial.println(pHub->OverCurrentProtectMode, BIN); - - printProgStr(PSTR("TTThinkTime:\t\t")); - Serial.println(pHub->TTThinkTime, BIN); - - printProgStr(PSTR("PortIndicatorsSupported:")); - Serial.println(pHub->PortIndicatorsSupported, BIN); - - printProgStr(PSTR("Reserved:\t\t")); - Serial.println(pHub->Reserved, HEX); - - printProgStr(PSTR("bPwrOn2PwrGood:\t\t")); - Serial.println(pHub->bPwrOn2PwrGood, HEX); - - printProgStr(PSTR("bHubContrCurrent:\t")); - Serial.println(pHub->bHubContrCurrent, HEX); - - for (uint8_t i = 7; i < len; i++) - print_hex(descrptr[i], 8); - - //for (uint8_t i=1; i<=pHub->bNbrPorts; i++) - // PrintHubPortStatus(&Usb, addr, i, 1); -} - -byte getconfdescr( byte addr, byte conf ) -{ - uint8_t buf[ BUFSIZE ]; - uint8_t* buf_ptr = buf; - byte rcode; - byte descr_length; - byte descr_type; - unsigned int total_length; - rcode = Usb.getConfDescr( addr, 0, 4, conf, buf ); //get total length - LOBYTE( total_length ) = buf[ 2 ]; - HIBYTE( total_length ) = buf[ 3 ]; - if ( total_length > 256 ) { //check if total length is larger than buffer - printProgStr(Conf_Trunc_str); - total_length = 256; - } - rcode = Usb.getConfDescr( addr, 0, total_length, conf, buf ); //get the whole descriptor - while ( buf_ptr < buf + total_length ) { //parsing descriptors - descr_length = *( buf_ptr ); - descr_type = *( buf_ptr + 1 ); - switch ( descr_type ) { - case ( USB_DESCRIPTOR_CONFIGURATION ): - printconfdescr( buf_ptr ); - break; - case ( USB_DESCRIPTOR_INTERFACE ): - printintfdescr( buf_ptr ); - break; - case ( USB_DESCRIPTOR_ENDPOINT ): - printepdescr( buf_ptr ); - break; - case 0x29: - printhubdescr( buf_ptr, addr ); - break; - default: - printunkdescr( buf_ptr ); - break; - }//switch( descr_type - buf_ptr = ( buf_ptr + descr_length ); //advance buffer pointer - }//while( buf_ptr <=... - return ( rcode ); -} -/* prints hex numbers with leading zeroes */ -// copyright, Peter H Anderson, Baltimore, MD, Nov, '07 -// source: http://www.phanderson.com/arduino/arduino_display.html -void print_hex(int v, int num_places) -{ - int mask = 0, n, num_nibbles, digit; - - for (n = 1; n <= num_places; n++) { - mask = (mask << 1) | 0x0001; - } - v = v & mask; // truncate v to specified number of places - - num_nibbles = num_places / 4; - if ((num_places % 4) != 0) { - ++num_nibbles; - } - do { - digit = ((v >> (num_nibbles - 1) * 4)) & 0x0f; - Serial.print(digit, HEX); - } - while (--num_nibbles); -} -/* function to print configuration descriptor */ -void printconfdescr( uint8_t* descr_ptr ) -{ - USB_CONFIGURATION_DESCRIPTOR* conf_ptr = ( USB_CONFIGURATION_DESCRIPTOR* )descr_ptr; - printProgStr(Conf_Header_str); - printProgStr(Conf_Totlen_str); - print_hex( conf_ptr->wTotalLength, 16 ); - printProgStr(Conf_Nint_str); - print_hex( conf_ptr->bNumInterfaces, 8 ); - printProgStr(Conf_Value_str); - print_hex( conf_ptr->bConfigurationValue, 8 ); - printProgStr(Conf_String_str); - print_hex( conf_ptr->iConfiguration, 8 ); - printProgStr(Conf_Attr_str); - print_hex( conf_ptr->bmAttributes, 8 ); - printProgStr(Conf_Pwr_str); - print_hex( conf_ptr->bMaxPower, 8 ); - return; -} -/* function to print interface descriptor */ -void printintfdescr( uint8_t* descr_ptr ) -{ - USB_INTERFACE_DESCRIPTOR* intf_ptr = ( USB_INTERFACE_DESCRIPTOR* )descr_ptr; - printProgStr(Int_Header_str); - printProgStr(Int_Number_str); - print_hex( intf_ptr->bInterfaceNumber, 8 ); - printProgStr(Int_Alt_str); - print_hex( intf_ptr->bAlternateSetting, 8 ); - printProgStr(Int_Endpoints_str); - print_hex( intf_ptr->bNumEndpoints, 8 ); - printProgStr(Int_Class_str); - print_hex( intf_ptr->bInterfaceClass, 8 ); - printProgStr(Int_Subclass_str); - print_hex( intf_ptr->bInterfaceSubClass, 8 ); - printProgStr(Int_Protocol_str); - print_hex( intf_ptr->bInterfaceProtocol, 8 ); - printProgStr(Int_String_str); - print_hex( intf_ptr->iInterface, 8 ); - return; -} -/* function to print endpoint descriptor */ -void printepdescr( uint8_t* descr_ptr ) -{ - USB_ENDPOINT_DESCRIPTOR* ep_ptr = ( USB_ENDPOINT_DESCRIPTOR* )descr_ptr; - printProgStr(End_Header_str); - printProgStr(End_Address_str); - print_hex( ep_ptr->bEndpointAddress, 8 ); - printProgStr(End_Attr_str); - print_hex( ep_ptr->bmAttributes, 8 ); - printProgStr(End_Pktsize_str); - print_hex( ep_ptr->wMaxPacketSize, 16 ); - printProgStr(End_Interval_str); - print_hex( ep_ptr->bInterval, 8 ); - - return; -} -/*function to print unknown descriptor */ -void printunkdescr( uint8_t* descr_ptr ) -{ - byte length = *descr_ptr; - byte i; - printProgStr(Unk_Header_str); - printProgStr(Unk_Length_str); - print_hex( *descr_ptr, 8 ); - printProgStr(Unk_Type_str); - print_hex( *(descr_ptr + 1 ), 8 ); - printProgStr(Unk_Contents_str); - descr_ptr += 2; - for ( i = 0; i < length; i++ ) { - print_hex( *descr_ptr, 8 ); - descr_ptr++; - } -} - - -/* Print a string from Program Memory directly to save RAM */ -void printProgStr(const char* str) -{ - char c; - if (!str) return; - while ((c = pgm_read_byte(str++))) - Serial.print(c); -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/USB_desc/pgmstrings.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/USB_desc/pgmstrings.h deleted file mode 100644 index bdb0077ecc..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/USB_desc/pgmstrings.h +++ /dev/null @@ -1,52 +0,0 @@ -#if !defined(__PGMSTRINGS_H__) -#define __PGMSTRINGS_H__ - -#define LOBYTE(x) ((char*)(&(x)))[0] -#define HIBYTE(x) ((char*)(&(x)))[1] -#define BUFSIZE 256 //buffer size - - -/* Print strings in Program Memory */ -const char Gen_Error_str[] PROGMEM = "\r\nRequest error. Error code:\t"; -const char Dev_Header_str[] PROGMEM ="\r\nDevice descriptor: "; -const char Dev_Length_str[] PROGMEM ="\r\nDescriptor Length:\t"; -const char Dev_Type_str[] PROGMEM ="\r\nDescriptor type:\t"; -const char Dev_Version_str[] PROGMEM ="\r\nUSB version:\t\t"; -const char Dev_Class_str[] PROGMEM ="\r\nDevice class:\t\t"; -const char Dev_Subclass_str[] PROGMEM ="\r\nDevice Subclass:\t"; -const char Dev_Protocol_str[] PROGMEM ="\r\nDevice Protocol:\t"; -const char Dev_Pktsize_str[] PROGMEM ="\r\nMax.packet size:\t"; -const char Dev_Vendor_str[] PROGMEM ="\r\nVendor ID:\t\t"; -const char Dev_Product_str[] PROGMEM ="\r\nProduct ID:\t\t"; -const char Dev_Revision_str[] PROGMEM ="\r\nRevision ID:\t\t"; -const char Dev_Mfg_str[] PROGMEM ="\r\nMfg.string index:\t"; -const char Dev_Prod_str[] PROGMEM ="\r\nProd.string index:\t"; -const char Dev_Serial_str[] PROGMEM ="\r\nSerial number index:\t"; -const char Dev_Nconf_str[] PROGMEM ="\r\nNumber of conf.:\t"; -const char Conf_Trunc_str[] PROGMEM ="Total length truncated to 256 bytes"; -const char Conf_Header_str[] PROGMEM ="\r\nConfiguration descriptor:"; -const char Conf_Totlen_str[] PROGMEM ="\r\nTotal length:\t\t"; -const char Conf_Nint_str[] PROGMEM ="\r\nNum.intf:\t\t"; -const char Conf_Value_str[] PROGMEM ="\r\nConf.value:\t\t"; -const char Conf_String_str[] PROGMEM ="\r\nConf.string:\t\t"; -const char Conf_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t"; -const char Conf_Pwr_str[] PROGMEM ="\r\nMax.pwr:\t\t"; -const char Int_Header_str[] PROGMEM ="\r\n\r\nInterface descriptor:"; -const char Int_Number_str[] PROGMEM ="\r\nIntf.number:\t\t"; -const char Int_Alt_str[] PROGMEM ="\r\nAlt.:\t\t\t"; -const char Int_Endpoints_str[] PROGMEM ="\r\nEndpoints:\t\t"; -const char Int_Class_str[] PROGMEM ="\r\nIntf. Class:\t\t"; -const char Int_Subclass_str[] PROGMEM ="\r\nIntf. Subclass:\t\t"; -const char Int_Protocol_str[] PROGMEM ="\r\nIntf. Protocol:\t\t"; -const char Int_String_str[] PROGMEM ="\r\nIntf.string:\t\t"; -const char End_Header_str[] PROGMEM ="\r\n\r\nEndpoint descriptor:"; -const char End_Address_str[] PROGMEM ="\r\nEndpoint address:\t"; -const char End_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t"; -const char End_Pktsize_str[] PROGMEM ="\r\nMax.pkt size:\t\t"; -const char End_Interval_str[] PROGMEM ="\r\nPolling interval:\t"; -const char Unk_Header_str[] PROGMEM = "\r\nUnknown descriptor:"; -const char Unk_Length_str[] PROGMEM ="\r\nLength:\t\t"; -const char Unk_Type_str[] PROGMEM ="\r\nType:\t\t"; -const char Unk_Contents_str[] PROGMEM ="\r\nContents:\t"; - -#endif // __PGMSTRINGS_H__ \ No newline at end of file diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Xbox/XBOXOLD/XBOXOLD.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Xbox/XBOXOLD/XBOXOLD.ino deleted file mode 100644 index 64a3ed6120..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Xbox/XBOXOLD/XBOXOLD.ino +++ /dev/null @@ -1,110 +0,0 @@ -/* - Example sketch for the original Xbox library - developed by Kristian Lauszus - For more information visit my blog: http://blog.tkjelectronics.dk/ or - send me an e-mail: kristianl@tkjelectronics.com - */ - -#include -#include - -// Satisfy the IDE, which needs to see the include statment in the ino too. -#ifdef dobogusinclude -#include -#include -#endif - -USB Usb; -USBHub Hub1(&Usb); // The controller has a built in hub, so this instance is needed -XBOXOLD Xbox(&Usb); - -void setup() { - Serial.begin(115200); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - if (Usb.Init() == -1) { - Serial.print(F("\r\nOSC did not start")); - while (1); // halt - } - Serial.print(F("\r\nXBOX Library Started")); -} -void loop() { - Usb.Task(); - if (Xbox.XboxConnected) { - if (Xbox.getButtonPress(BLACK) || Xbox.getButtonPress(WHITE)) { - Serial.print("BLACK: "); - Serial.print(Xbox.getButtonPress(BLACK)); - Serial.print("\tWHITE: "); - Serial.println(Xbox.getButtonPress(WHITE)); - Xbox.setRumbleOn(Xbox.getButtonPress(BLACK), Xbox.getButtonPress(WHITE)); - } else - Xbox.setRumbleOn(0, 0); - - if (Xbox.getAnalogHat(LeftHatX) > 7500 || Xbox.getAnalogHat(LeftHatX) < -7500 || Xbox.getAnalogHat(LeftHatY) > 7500 || Xbox.getAnalogHat(LeftHatY) < -7500 || Xbox.getAnalogHat(RightHatX) > 7500 || Xbox.getAnalogHat(RightHatX) < -7500 || Xbox.getAnalogHat(RightHatY) > 7500 || Xbox.getAnalogHat(RightHatY) < -7500) { - if (Xbox.getAnalogHat(LeftHatX) > 7500 || Xbox.getAnalogHat(LeftHatX) < -7500) { - Serial.print(F("LeftHatX: ")); - Serial.print(Xbox.getAnalogHat(LeftHatX)); - Serial.print("\t"); - } - if (Xbox.getAnalogHat(LeftHatY) > 7500 || Xbox.getAnalogHat(LeftHatY) < -7500) { - Serial.print(F("LeftHatY: ")); - Serial.print(Xbox.getAnalogHat(LeftHatY)); - Serial.print("\t"); - } - if (Xbox.getAnalogHat(RightHatX) > 7500 || Xbox.getAnalogHat(RightHatX) < -7500) { - Serial.print(F("RightHatX: ")); - Serial.print(Xbox.getAnalogHat(RightHatX)); - Serial.print("\t"); - } - if (Xbox.getAnalogHat(RightHatY) > 7500 || Xbox.getAnalogHat(RightHatY) < -7500) { - Serial.print(F("RightHatY: ")); - Serial.print(Xbox.getAnalogHat(RightHatY)); - } - Serial.println(); - } - - if (Xbox.getButtonClick(UP)) - Serial.println(F("Up")); - if (Xbox.getButtonClick(DOWN)) - Serial.println(F("Down")); - if (Xbox.getButtonClick(LEFT)) - Serial.println(F("Left")); - if (Xbox.getButtonClick(RIGHT)) - Serial.println(F("Right")); - - if (Xbox.getButtonClick(START)) - Serial.println(F("Start")); - if (Xbox.getButtonClick(BACK)) - Serial.println(F("Back")); - if (Xbox.getButtonClick(L3)) - Serial.println(F("L3")); - if (Xbox.getButtonClick(R3)) - Serial.println(F("R3")); - - if (Xbox.getButtonPress(A)) { - Serial.print(F("A: ")); - Serial.println(Xbox.getButtonPress(A)); - } - if (Xbox.getButtonPress(B)) { - Serial.print(F("B: ")); - Serial.println(Xbox.getButtonPress(B)); - } - if (Xbox.getButtonPress(X)) { - Serial.print(F("X: ")); - Serial.println(Xbox.getButtonPress(X)); - } - if (Xbox.getButtonPress(Y)) { - Serial.print(F("Y: ")); - Serial.println(Xbox.getButtonPress(Y)); - } - if (Xbox.getButtonPress(L1)) { - Serial.print(F("L1: ")); - Serial.println(Xbox.getButtonPress(L1)); - } - if (Xbox.getButtonPress(R1)) { - Serial.print(F("R1: ")); - Serial.println(Xbox.getButtonPress(R1)); - } - } - delay(1); -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Xbox/XBOXONE/XBOXONE.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Xbox/XBOXONE/XBOXONE.ino deleted file mode 100644 index 9526f53d19..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Xbox/XBOXONE/XBOXONE.ino +++ /dev/null @@ -1,106 +0,0 @@ -/* - Example sketch for the Xbox ONE USB library - by guruthree, based on work by - Kristian Lauszus. - */ - -#include -// Satisfy IDE, which only needs to see the include statment in the ino. -#ifdef dobogusinclude -#include -#endif - -USB Usb; -XBOXONE Xbox(&Usb); - -void setup() { - Serial.begin(115200); - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection - if (Usb.Init() == -1) { - Serial.print(F("\r\nOSC did not start")); - while (1); //halt - } - Serial.print(F("\r\nXBOX USB Library Started")); -} -void loop() { - Usb.Task(); - if (Xbox.XboxOneConnected) { - if (Xbox.getAnalogHat(LeftHatX) > 7500 || Xbox.getAnalogHat(LeftHatX) < -7500 || Xbox.getAnalogHat(LeftHatY) > 7500 || Xbox.getAnalogHat(LeftHatY) < -7500 || Xbox.getAnalogHat(RightHatX) > 7500 || Xbox.getAnalogHat(RightHatX) < -7500 || Xbox.getAnalogHat(RightHatY) > 7500 || Xbox.getAnalogHat(RightHatY) < -7500) { - if (Xbox.getAnalogHat(LeftHatX) > 7500 || Xbox.getAnalogHat(LeftHatX) < -7500) { - Serial.print(F("LeftHatX: ")); - Serial.print(Xbox.getAnalogHat(LeftHatX)); - Serial.print("\t"); - } - if (Xbox.getAnalogHat(LeftHatY) > 7500 || Xbox.getAnalogHat(LeftHatY) < -7500) { - Serial.print(F("LeftHatY: ")); - Serial.print(Xbox.getAnalogHat(LeftHatY)); - Serial.print("\t"); - } - if (Xbox.getAnalogHat(RightHatX) > 7500 || Xbox.getAnalogHat(RightHatX) < -7500) { - Serial.print(F("RightHatX: ")); - Serial.print(Xbox.getAnalogHat(RightHatX)); - Serial.print("\t"); - } - if (Xbox.getAnalogHat(RightHatY) > 7500 || Xbox.getAnalogHat(RightHatY) < -7500) { - Serial.print(F("RightHatY: ")); - Serial.print(Xbox.getAnalogHat(RightHatY)); - } - Serial.println(); - } - - if (Xbox.getButtonPress(L2) > 0 || Xbox.getButtonPress(R2) > 0) { - if (Xbox.getButtonPress(L2) > 0) { - Serial.print(F("L2: ")); - Serial.print(Xbox.getButtonPress(L2)); - Serial.print("\t"); - } - if (Xbox.getButtonPress(R2) > 0) { - Serial.print(F("R2: ")); - Serial.print(Xbox.getButtonPress(R2)); - Serial.print("\t"); - } - Serial.println(); - } - - if (Xbox.getButtonClick(UP)) - Serial.println(F("Up")); - if (Xbox.getButtonClick(DOWN)) - Serial.println(F("Down")); - if (Xbox.getButtonClick(LEFT)) - Serial.println(F("Left")); - if (Xbox.getButtonClick(RIGHT)) - Serial.println(F("Right")); - - if (Xbox.getButtonClick(START)) - Serial.println(F("Start")); - if (Xbox.getButtonClick(BACK)) - Serial.println(F("Back")); - if (Xbox.getButtonClick(XBOX)) - Serial.println(F("Xbox")); - if (Xbox.getButtonClick(SYNC)) - Serial.println(F("Sync")); - - if (Xbox.getButtonClick(L1)) - Serial.println(F("L1")); - if (Xbox.getButtonClick(R1)) - Serial.println(F("R1")); - if (Xbox.getButtonClick(L2)) - Serial.println(F("L2")); - if (Xbox.getButtonClick(R2)) - Serial.println(F("R2")); - if (Xbox.getButtonClick(L3)) - Serial.println(F("L3")); - if (Xbox.getButtonClick(R3)) - Serial.println(F("R3")); - - - if (Xbox.getButtonClick(A)) - Serial.println(F("A")); - if (Xbox.getButtonClick(B)) - Serial.println(F("B")); - if (Xbox.getButtonClick(X)) - Serial.println(F("X")); - if (Xbox.getButtonClick(Y)) - Serial.println(F("Y")); - } - delay(1); -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Xbox/XBOXRECV/XBOXRECV.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Xbox/XBOXRECV/XBOXRECV.ino deleted file mode 100644 index 491b287e44..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Xbox/XBOXRECV/XBOXRECV.ino +++ /dev/null @@ -1,122 +0,0 @@ -/* - Example sketch for the Xbox Wireless Reciver library - developed by Kristian Lauszus - It supports up to four controllers wirelessly - For more information see the blog post: http://blog.tkjelectronics.dk/2012/12/xbox-360-receiver-added-to-the-usb-host-library/ or - send me an e-mail: kristianl@tkjelectronics.com - */ - -#include - -// Satisfy the IDE, which needs to see the include statment in the ino too. -#ifdef dobogusinclude -#include -#include -#endif - -USB Usb; -XBOXRECV Xbox(&Usb); - -void setup() { - Serial.begin(115200); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - if (Usb.Init() == -1) { - Serial.print(F("\r\nOSC did not start")); - while (1); //halt - } - Serial.print(F("\r\nXbox Wireless Receiver Library Started")); -} -void loop() { - Usb.Task(); - if (Xbox.XboxReceiverConnected) { - for (uint8_t i = 0; i < 4; i++) { - if (Xbox.Xbox360Connected[i]) { - if (Xbox.getButtonPress(L2, i) || Xbox.getButtonPress(R2, i)) { - Serial.print("L2: "); - Serial.print(Xbox.getButtonPress(L2, i)); - Serial.print("\tR2: "); - Serial.println(Xbox.getButtonPress(R2, i)); - Xbox.setRumbleOn(Xbox.getButtonPress(L2, i), Xbox.getButtonPress(R2, i), i); - } - - if (Xbox.getAnalogHat(LeftHatX, i) > 7500 || Xbox.getAnalogHat(LeftHatX, i) < -7500 || Xbox.getAnalogHat(LeftHatY, i) > 7500 || Xbox.getAnalogHat(LeftHatY, i) < -7500 || Xbox.getAnalogHat(RightHatX, i) > 7500 || Xbox.getAnalogHat(RightHatX, i) < -7500 || Xbox.getAnalogHat(RightHatY, i) > 7500 || Xbox.getAnalogHat(RightHatY, i) < -7500) { - if (Xbox.getAnalogHat(LeftHatX, i) > 7500 || Xbox.getAnalogHat(LeftHatX, i) < -7500) { - Serial.print(F("LeftHatX: ")); - Serial.print(Xbox.getAnalogHat(LeftHatX, i)); - Serial.print("\t"); - } - if (Xbox.getAnalogHat(LeftHatY, i) > 7500 || Xbox.getAnalogHat(LeftHatY, i) < -7500) { - Serial.print(F("LeftHatY: ")); - Serial.print(Xbox.getAnalogHat(LeftHatY, i)); - Serial.print("\t"); - } - if (Xbox.getAnalogHat(RightHatX, i) > 7500 || Xbox.getAnalogHat(RightHatX, i) < -7500) { - Serial.print(F("RightHatX: ")); - Serial.print(Xbox.getAnalogHat(RightHatX, i)); - Serial.print("\t"); - } - if (Xbox.getAnalogHat(RightHatY, i) > 7500 || Xbox.getAnalogHat(RightHatY, i) < -7500) { - Serial.print(F("RightHatY: ")); - Serial.print(Xbox.getAnalogHat(RightHatY, i)); - } - Serial.println(); - } - - if (Xbox.getButtonClick(UP, i)) { - Xbox.setLedOn(LED1, i); - Serial.println(F("Up")); - } - if (Xbox.getButtonClick(DOWN, i)) { - Xbox.setLedOn(LED4, i); - Serial.println(F("Down")); - } - if (Xbox.getButtonClick(LEFT, i)) { - Xbox.setLedOn(LED3, i); - Serial.println(F("Left")); - } - if (Xbox.getButtonClick(RIGHT, i)) { - Xbox.setLedOn(LED2, i); - Serial.println(F("Right")); - } - - if (Xbox.getButtonClick(START, i)) { - Xbox.setLedMode(ALTERNATING, i); - Serial.println(F("Start")); - } - if (Xbox.getButtonClick(BACK, i)) { - Xbox.setLedBlink(ALL, i); - Serial.println(F("Back")); - } - if (Xbox.getButtonClick(L3, i)) - Serial.println(F("L3")); - if (Xbox.getButtonClick(R3, i)) - Serial.println(F("R3")); - - if (Xbox.getButtonClick(L1, i)) - Serial.println(F("L1")); - if (Xbox.getButtonClick(R1, i)) - Serial.println(F("R1")); - if (Xbox.getButtonClick(XBOX, i)) { - Xbox.setLedMode(ROTATING, i); - Serial.print(F("Xbox (Battery: ")); - Serial.print(Xbox.getBatteryLevel(i)); // The battery level in the range 0-3 - Serial.println(F(")")); - } - if (Xbox.getButtonClick(SYNC, i)) { - Serial.println(F("Sync")); - Xbox.disconnect(i); - } - - if (Xbox.getButtonClick(A, i)) - Serial.println(F("A")); - if (Xbox.getButtonClick(B, i)) - Serial.println(F("B")); - if (Xbox.getButtonClick(X, i)) - Serial.println(F("X")); - if (Xbox.getButtonClick(Y, i)) - Serial.println(F("Y")); - } - } - } -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Xbox/XBOXUSB/XBOXUSB.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Xbox/XBOXUSB/XBOXUSB.ino deleted file mode 100644 index 8a5691c6e1..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Xbox/XBOXUSB/XBOXUSB.ino +++ /dev/null @@ -1,113 +0,0 @@ -/* - Example sketch for the Xbox 360 USB library - developed by Kristian Lauszus - For more information visit my blog: http://blog.tkjelectronics.dk/ or - send me an e-mail: kristianl@tkjelectronics.com - */ - -#include - -// Satisfy the IDE, which needs to see the include statment in the ino too. -#ifdef dobogusinclude -#include -#include -#endif - -USB Usb; -XBOXUSB Xbox(&Usb); - -void setup() { - Serial.begin(115200); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - if (Usb.Init() == -1) { - Serial.print(F("\r\nOSC did not start")); - while (1); //halt - } - Serial.print(F("\r\nXBOX USB Library Started")); -} -void loop() { - Usb.Task(); - if (Xbox.Xbox360Connected) { - if (Xbox.getButtonPress(L2) || Xbox.getButtonPress(R2)) { - Serial.print("L2: "); - Serial.print(Xbox.getButtonPress(L2)); - Serial.print("\tR2: "); - Serial.println(Xbox.getButtonPress(R2)); - Xbox.setRumbleOn(Xbox.getButtonPress(L2), Xbox.getButtonPress(R2)); - } else - Xbox.setRumbleOn(0, 0); - - if (Xbox.getAnalogHat(LeftHatX) > 7500 || Xbox.getAnalogHat(LeftHatX) < -7500 || Xbox.getAnalogHat(LeftHatY) > 7500 || Xbox.getAnalogHat(LeftHatY) < -7500 || Xbox.getAnalogHat(RightHatX) > 7500 || Xbox.getAnalogHat(RightHatX) < -7500 || Xbox.getAnalogHat(RightHatY) > 7500 || Xbox.getAnalogHat(RightHatY) < -7500) { - if (Xbox.getAnalogHat(LeftHatX) > 7500 || Xbox.getAnalogHat(LeftHatX) < -7500) { - Serial.print(F("LeftHatX: ")); - Serial.print(Xbox.getAnalogHat(LeftHatX)); - Serial.print("\t"); - } - if (Xbox.getAnalogHat(LeftHatY) > 7500 || Xbox.getAnalogHat(LeftHatY) < -7500) { - Serial.print(F("LeftHatY: ")); - Serial.print(Xbox.getAnalogHat(LeftHatY)); - Serial.print("\t"); - } - if (Xbox.getAnalogHat(RightHatX) > 7500 || Xbox.getAnalogHat(RightHatX) < -7500) { - Serial.print(F("RightHatX: ")); - Serial.print(Xbox.getAnalogHat(RightHatX)); - Serial.print("\t"); - } - if (Xbox.getAnalogHat(RightHatY) > 7500 || Xbox.getAnalogHat(RightHatY) < -7500) { - Serial.print(F("RightHatY: ")); - Serial.print(Xbox.getAnalogHat(RightHatY)); - } - Serial.println(); - } - - if (Xbox.getButtonClick(UP)) { - Xbox.setLedOn(LED1); - Serial.println(F("Up")); - } - if (Xbox.getButtonClick(DOWN)) { - Xbox.setLedOn(LED4); - Serial.println(F("Down")); - } - if (Xbox.getButtonClick(LEFT)) { - Xbox.setLedOn(LED3); - Serial.println(F("Left")); - } - if (Xbox.getButtonClick(RIGHT)) { - Xbox.setLedOn(LED2); - Serial.println(F("Right")); - } - - if (Xbox.getButtonClick(START)) { - Xbox.setLedMode(ALTERNATING); - Serial.println(F("Start")); - } - if (Xbox.getButtonClick(BACK)) { - Xbox.setLedBlink(ALL); - Serial.println(F("Back")); - } - if (Xbox.getButtonClick(L3)) - Serial.println(F("L3")); - if (Xbox.getButtonClick(R3)) - Serial.println(F("R3")); - - if (Xbox.getButtonClick(L1)) - Serial.println(F("L1")); - if (Xbox.getButtonClick(R1)) - Serial.println(F("R1")); - if (Xbox.getButtonClick(XBOX)) { - Xbox.setLedMode(ROTATING); - Serial.println(F("Xbox")); - } - - if (Xbox.getButtonClick(A)) - Serial.println(F("A")); - if (Xbox.getButtonClick(B)) - Serial.println(F("B")); - if (Xbox.getButtonClick(X)) - Serial.println(F("X")); - if (Xbox.getButtonClick(Y)) - Serial.println(F("Y")); - } - delay(1); -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/acm/acm_terminal/acm_terminal.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/acm/acm_terminal/acm_terminal.ino deleted file mode 100644 index f509cda890..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/acm/acm_terminal/acm_terminal.ino +++ /dev/null @@ -1,100 +0,0 @@ -#include -#include - -#include "pgmstrings.h" - -// Satisfy the IDE, which needs to see the include statment in the ino too. -#ifdef dobogusinclude -#include -#include -#endif - -class ACMAsyncOper : public CDCAsyncOper -{ -public: - uint8_t OnInit(ACM *pacm); -}; - -uint8_t ACMAsyncOper::OnInit(ACM *pacm) -{ - uint8_t rcode; - // Set DTR = 1 RTS=1 - rcode = pacm->SetControlLineState(3); - - if (rcode) - { - ErrorMessage(PSTR("SetControlLineState"), rcode); - return rcode; - } - - LINE_CODING lc; - lc.dwDTERate = 115200; - lc.bCharFormat = 0; - lc.bParityType = 0; - lc.bDataBits = 8; - - rcode = pacm->SetLineCoding(&lc); - - if (rcode) - ErrorMessage(PSTR("SetLineCoding"), rcode); - - return rcode; -} - -USB Usb; -//USBHub Hub(&Usb); -ACMAsyncOper AsyncOper; -ACM Acm(&Usb, &AsyncOper); - -void setup() -{ - Serial.begin( 115200 ); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - Serial.println("Start"); - - if (Usb.Init() == -1) - Serial.println("OSCOKIRQ failed to assert"); - - delay( 200 ); -} - -void loop() -{ - Usb.Task(); - - if( Acm.isReady()) { - uint8_t rcode; - - /* reading the keyboard */ - if(Serial.available()) { - uint8_t data= Serial.read(); - /* sending to the phone */ - rcode = Acm.SndData(1, &data); - if (rcode) - ErrorMessage(PSTR("SndData"), rcode); - }//if(Serial.available()... - - delay(50); - - /* reading the phone */ - /* buffer size must be greater or equal to max.packet size */ - /* it it set to 64 (largest possible max.packet size) here, can be tuned down - for particular endpoint */ - uint8_t buf[64]; - uint16_t rcvd = 64; - rcode = Acm.RcvData(&rcvd, buf); - if (rcode && rcode != hrNAK) - ErrorMessage(PSTR("Ret"), rcode); - - if( rcvd ) { //more than zero bytes received - for(uint16_t i=0; i < rcvd; i++ ) { - Serial.print((char)buf[i]); //printing on the screen - } - } - delay(10); - }//if( Usb.getUsbTaskState() == USB_STATE_RUNNING.. -} - - diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/acm/acm_terminal/pgmstrings.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/acm/acm_terminal/pgmstrings.h deleted file mode 100644 index bdb0077ecc..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/acm/acm_terminal/pgmstrings.h +++ /dev/null @@ -1,52 +0,0 @@ -#if !defined(__PGMSTRINGS_H__) -#define __PGMSTRINGS_H__ - -#define LOBYTE(x) ((char*)(&(x)))[0] -#define HIBYTE(x) ((char*)(&(x)))[1] -#define BUFSIZE 256 //buffer size - - -/* Print strings in Program Memory */ -const char Gen_Error_str[] PROGMEM = "\r\nRequest error. Error code:\t"; -const char Dev_Header_str[] PROGMEM ="\r\nDevice descriptor: "; -const char Dev_Length_str[] PROGMEM ="\r\nDescriptor Length:\t"; -const char Dev_Type_str[] PROGMEM ="\r\nDescriptor type:\t"; -const char Dev_Version_str[] PROGMEM ="\r\nUSB version:\t\t"; -const char Dev_Class_str[] PROGMEM ="\r\nDevice class:\t\t"; -const char Dev_Subclass_str[] PROGMEM ="\r\nDevice Subclass:\t"; -const char Dev_Protocol_str[] PROGMEM ="\r\nDevice Protocol:\t"; -const char Dev_Pktsize_str[] PROGMEM ="\r\nMax.packet size:\t"; -const char Dev_Vendor_str[] PROGMEM ="\r\nVendor ID:\t\t"; -const char Dev_Product_str[] PROGMEM ="\r\nProduct ID:\t\t"; -const char Dev_Revision_str[] PROGMEM ="\r\nRevision ID:\t\t"; -const char Dev_Mfg_str[] PROGMEM ="\r\nMfg.string index:\t"; -const char Dev_Prod_str[] PROGMEM ="\r\nProd.string index:\t"; -const char Dev_Serial_str[] PROGMEM ="\r\nSerial number index:\t"; -const char Dev_Nconf_str[] PROGMEM ="\r\nNumber of conf.:\t"; -const char Conf_Trunc_str[] PROGMEM ="Total length truncated to 256 bytes"; -const char Conf_Header_str[] PROGMEM ="\r\nConfiguration descriptor:"; -const char Conf_Totlen_str[] PROGMEM ="\r\nTotal length:\t\t"; -const char Conf_Nint_str[] PROGMEM ="\r\nNum.intf:\t\t"; -const char Conf_Value_str[] PROGMEM ="\r\nConf.value:\t\t"; -const char Conf_String_str[] PROGMEM ="\r\nConf.string:\t\t"; -const char Conf_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t"; -const char Conf_Pwr_str[] PROGMEM ="\r\nMax.pwr:\t\t"; -const char Int_Header_str[] PROGMEM ="\r\n\r\nInterface descriptor:"; -const char Int_Number_str[] PROGMEM ="\r\nIntf.number:\t\t"; -const char Int_Alt_str[] PROGMEM ="\r\nAlt.:\t\t\t"; -const char Int_Endpoints_str[] PROGMEM ="\r\nEndpoints:\t\t"; -const char Int_Class_str[] PROGMEM ="\r\nIntf. Class:\t\t"; -const char Int_Subclass_str[] PROGMEM ="\r\nIntf. Subclass:\t\t"; -const char Int_Protocol_str[] PROGMEM ="\r\nIntf. Protocol:\t\t"; -const char Int_String_str[] PROGMEM ="\r\nIntf.string:\t\t"; -const char End_Header_str[] PROGMEM ="\r\n\r\nEndpoint descriptor:"; -const char End_Address_str[] PROGMEM ="\r\nEndpoint address:\t"; -const char End_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t"; -const char End_Pktsize_str[] PROGMEM ="\r\nMax.pkt size:\t\t"; -const char End_Interval_str[] PROGMEM ="\r\nPolling interval:\t"; -const char Unk_Header_str[] PROGMEM = "\r\nUnknown descriptor:"; -const char Unk_Length_str[] PROGMEM ="\r\nLength:\t\t"; -const char Unk_Type_str[] PROGMEM ="\r\nType:\t\t"; -const char Unk_Contents_str[] PROGMEM ="\r\nContents:\t"; - -#endif // __PGMSTRINGS_H__ \ No newline at end of file diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/ArduinoBlinkLED/ArduinoBlinkLED.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/ArduinoBlinkLED/ArduinoBlinkLED.ino deleted file mode 100644 index d59b9bb3dc..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/ArduinoBlinkLED/ArduinoBlinkLED.ino +++ /dev/null @@ -1,89 +0,0 @@ -// The source for the Android application can be found at the following link: https://github.com/Lauszus/ArduinoBlinkLED -// The code for the Android application is heavily based on this guide: http://allaboutee.com/2011/12/31/arduino-adk-board-blink-an-led-with-your-phone-code-and-explanation/ by Miguel -#include - -// -// CAUTION! WARNING! ATTENTION! VORSICHT! ADVARSEL! ¡CUIDADO! ВНИМАНИЕ! -// -// Pin 13 is occupied by the SCK pin on various Arduino boards, -// including Uno, Duemilanove, etc., so use a different pin for those boards. -// -// CAUTION! WARNING! ATTENTION! VORSICHT! ADVARSEL! ¡CUIDADO! ВНИМАНИЕ! -// -#if defined(LED_BUILTIN) -#define LED LED_BUILTIN // Use built in LED -#else -#define LED 9 // Set to something here that makes sense for your board. -#endif - - -// Satisfy IDE, which only needs to see the include statment in the ino. -#ifdef dobogusinclude -#include -#include -#endif - -USB Usb; -ADK adk(&Usb, "TKJElectronics", // Manufacturer Name - "ArduinoBlinkLED", // Model Name - "Example sketch for the USB Host Shield", // Description (user-visible string) - "1.0", // Version - "http://www.tkjelectronics.dk/uploads/ArduinoBlinkLED.apk", // URL (web page to visit if no installed apps support the accessory) - "123456789"); // Serial Number (optional) - -uint32_t timer; -bool connected; - -void setup() { - Serial.begin(115200); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - if (Usb.Init() == -1) { - Serial.print("\r\nOSCOKIRQ failed to assert"); - while (1); // halt - } - pinMode(LED, OUTPUT); - Serial.print("\r\nArduino Blink LED Started"); -} - -void loop() { - Usb.Task(); - - if (adk.isReady()) { - if (!connected) { - connected = true; - Serial.print(F("\r\nConnected to accessory")); - } - - uint8_t msg[1]; - uint16_t len = sizeof(msg); - uint8_t rcode = adk.RcvData(&len, msg); - if (rcode && rcode != hrNAK) { - Serial.print(F("\r\nData rcv: ")); - Serial.print(rcode, HEX); - } else if (len > 0) { - Serial.print(F("\r\nData Packet: ")); - Serial.print(msg[0]); - digitalWrite(LED, msg[0] ? HIGH : LOW); - } - - if (millis() - timer >= 1000) { // Send data every 1s - timer = millis(); - rcode = adk.SndData(sizeof(timer), (uint8_t*)&timer); - if (rcode && rcode != hrNAK) { - Serial.print(F("\r\nData send: ")); - Serial.print(rcode, HEX); - } else if (rcode != hrNAK) { - Serial.print(F("\r\nTimer: ")); - Serial.print(timer); - } - } - } else { - if (connected) { - connected = false; - Serial.print(F("\r\nDisconnected from accessory")); - digitalWrite(LED, LOW); - } - } -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/adk_barcode/adk_barcode.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/adk_barcode/adk_barcode.ino deleted file mode 100644 index a308ff0f83..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/adk_barcode/adk_barcode.ino +++ /dev/null @@ -1,91 +0,0 @@ -/**/ -/* A sketch demonstrating data exchange between two USB devices - a HID barcode scanner and ADK-compatible Android phone */ -/**/ -#include -#include -#include - -// Satisfy IDE, which only needs to see the include statment in the ino. -#ifdef dobogusinclude -#include -#include -#endif - -USB Usb; -USBHub Hub1(&Usb); -USBHub Hub2(&Usb); -HIDBoot Keyboard(&Usb); - -ADK adk(&Usb,"Circuits@Home, ltd.", - "USB Host Shield", - "Arduino Terminal for Android", - "1.0", - "http://www.circuitsathome.com", - "0000000000000001"); - - -class KbdRptParser : public KeyboardReportParser -{ - -protected: - void OnKeyDown (uint8_t mod, uint8_t key); - void OnKeyPressed(uint8_t key); -}; - -void KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key) -{ - uint8_t c = OemToAscii(mod, key); - - if (c) - OnKeyPressed(c); -} - -/* what to do when symbol arrives */ -void KbdRptParser::OnKeyPressed(uint8_t key) -{ -const char* new_line = "\n"; -uint8_t rcode; -uint8_t keylcl; - - if( adk.isReady() == false ) { - return; - } - - keylcl = key; - - if( keylcl == 0x13 ) { - rcode = adk.SndData( strlen( new_line ), (uint8_t *)new_line ); - } - else { - rcode = adk.SndData( 1, &keylcl ); - } - - Serial.print((char) keylcl ); - Serial.print(" : "); - Serial.println( keylcl, HEX ); -}; - -KbdRptParser Prs; - -void setup() -{ - Serial.begin(115200); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - Serial.println("\r\nADK demo start"); - - if (Usb.Init() == -1) { - Serial.println("OSCOKIRQ failed to assert"); - while(1); //halt - }//if (Usb.Init() == -1... - - Keyboard.SetReportParser(0, (HIDReportParser*)&Prs); - - delay( 200 ); -} - -void loop() -{ - Usb.Task(); -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/demokit_20/demokit_20.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/demokit_20/demokit_20.ino deleted file mode 100644 index f65adf57bb..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/demokit_20/demokit_20.ino +++ /dev/null @@ -1,103 +0,0 @@ -#include -#include - -// Satisfy IDE, which only needs to see the include statment in the ino. -#ifdef dobogusinclude -#include -#include -#endif - -USB Usb; -USBHub hub0(&Usb); -USBHub hub1(&Usb); -ADK adk(&Usb,"Google, Inc.", - "DemoKit", - "DemoKit Arduino Board", - "1.0", - "http://www.android.com", - "0000000012345678"); -uint8_t b, b1; - - -#define LED1_RED 3 -#define BUTTON1 2 - -void init_buttons() -{ - pinMode(BUTTON1, INPUT); - - // enable the internal pullups - digitalWrite(BUTTON1, HIGH); -} - -void init_leds() -{ - digitalWrite(LED1_RED, 0); - - pinMode(LED1_RED, OUTPUT); -} - -void setup() -{ - Serial.begin(115200); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - Serial.println("\r\nADK demo start"); - - if (Usb.Init() == -1) { - Serial.println("OSCOKIRQ failed to assert"); - while(1); //halt - }//if (Usb.Init() == -1... - - - init_leds(); - init_buttons(); - b1 = digitalRead(BUTTON1); -} - -void loop() -{ - uint8_t rcode; - uint8_t msg[3] = { 0x00 }; - Usb.Task(); - - if( adk.isReady() == false ) { - analogWrite(LED1_RED, 255); - return; - } - uint16_t len = sizeof(msg); - - rcode = adk.RcvData(&len, msg); - if( rcode ) { - USBTRACE2("Data rcv. :", rcode ); - } - if(len > 0) { - USBTRACE("\r\nData Packet."); - // assumes only one command per packet - if (msg[0] == 0x2) { - switch( msg[1] ) { - case 0: - analogWrite(LED1_RED, 255 - msg[2]); - break; - }//switch( msg[1]... - }//if (msg[0] == 0x2... - }//if( len > 0... - - msg[0] = 0x1; - - b = digitalRead(BUTTON1); - if (b != b1) { - USBTRACE("\r\nButton state changed"); - msg[1] = 0; - msg[2] = b ? 0 : 1; - rcode = adk.SndData( 3, msg ); - if( rcode ) { - USBTRACE2("Button send: ", rcode ); - } - b1 = b; - }//if (b != b1... - - - delay( 10 ); -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/term_test/term_test.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/term_test/term_test.ino deleted file mode 100644 index db681c3b50..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/term_test/term_test.ino +++ /dev/null @@ -1,65 +0,0 @@ -#include -#include - -// Satisfy IDE, which only needs to see the include statment in the ino. -#ifdef dobogusinclude -#include -#include -#endif - -USB Usb; -//USBHub Hub(&Usb); - -ADK adk(&Usb,"Circuits@Home, ltd.", - "USB Host Shield", - "Arduino Terminal for Android", - "1.0", - "http://www.circuitsathome.com", - "0000000000000001"); - -void setup() -{ - Serial.begin(115200); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - Serial.println("\r\nADK demo start"); - - if (Usb.Init() == -1) { - Serial.println("OSCOKIRQ failed to assert"); - while(1); //halt - }//if (Usb.Init() == -1... -} - -void loop() -{ - uint8_t rcode; - uint8_t msg[64] = { 0x00 }; - const char* recv = "Received: "; - - Usb.Task(); - - if( adk.isReady() == false ) { - return; - } - uint16_t len = 64; - - rcode = adk.RcvData(&len, msg); - if( rcode & ( rcode != hrNAK )) { - USBTRACE2("Data rcv. :", rcode ); - } - if(len > 0) { - USBTRACE("\r\nData Packet."); - - for( uint8_t i = 0; i < len; i++ ) { - Serial.print((char)msg[i]); - } - /* sending back what was received */ - rcode = adk.SndData( strlen( recv ), (uint8_t *)recv ); - rcode = adk.SndData( strlen(( char * )msg ), msg ); - - }//if( len > 0 )... - - delay( 1000 ); -} - diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/term_time/term_time.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/term_time/term_time.ino deleted file mode 100644 index a3f1dbc8cb..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/term_time/term_time.ino +++ /dev/null @@ -1,50 +0,0 @@ -#include -#include - -// Satisfy IDE, which only needs to see the include statment in the ino. -#ifdef dobogusinclude -#include -#include -#endif - -USB Usb; - -ADK adk(&Usb,"Circuits@Home, ltd.", - "USB Host Shield", - "Arduino Terminal for Android", - "1.0", - "http://www.circuitsathome.com", - "0000000000000001"); - -void setup() -{ - Serial.begin(115200); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - Serial.println("\r\nADK demo start"); - - if (Usb.Init() == -1) { - Serial.println("OSCOKIRQ failed to assert"); - while(1); //halt - }//if (Usb.Init() == -1... -} - -void loop() -{ - uint8_t buf[ 12 ] = { 0 }; //buffer to convert unsigned long to ASCII - const char* sec_ela = " seconds elapsed\r"; - uint8_t rcode; - - Usb.Task(); - if( adk.isReady() == false ) { - return; - } - - ultoa( millis()/1000, (char *)buf, 10 ); - - rcode = adk.SndData( strlen((char *)buf), buf ); - rcode = adk.SndData( strlen( sec_ela), (uint8_t *)sec_ela ); - - delay( 1000 ); -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/board_qc/board_qc.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/board_qc/board_qc.ino deleted file mode 100644 index 573c3ce083..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/board_qc/board_qc.ino +++ /dev/null @@ -1,259 +0,0 @@ -/* USB Host Shield 2.0 board quality control routine */ -/* To see the output set your terminal speed to 115200 */ -/* for GPIO test to pass you need to connect GPIN0 to GPOUT7, GPIN1 to GPOUT6, etc. */ -/* otherwise press any key after getting GPIO error to complete the test */ -/**/ -#include - -// Satisfy the IDE, which needs to see the include statment in the ino too. -#ifdef dobogusinclude -#include -#include <../../../../hardware/pic32/libraries/SPI/SPI.h> // Hack to use the SPI library -#include // Hack to use the SPI library -#endif - -/* variables */ -uint8_t rcode; -uint8_t usbstate; -uint8_t laststate; -//uint8_t buf[sizeof(USB_DEVICE_DESCRIPTOR)]; -USB_DEVICE_DESCRIPTOR buf; - -/* objects */ -USB Usb; -//USBHub hub(&Usb); - -void setup() { - laststate = 0; - Serial.begin(115200); -#if !defined(__MIPSEL__) - while(!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - E_Notify(PSTR("\r\nCircuits At Home 2011"), 0x80); - E_Notify(PSTR("\r\nUSB Host Shield Quality Control Routine"), 0x80); - /* SPI quick test - check revision register */ - E_Notify(PSTR("\r\nReading REVISION register... Die revision "), 0x80); - Usb.Init(); // Initializes SPI, we don't care about the return value here - { - uint8_t tmpbyte = Usb.regRd(rREVISION); - switch(tmpbyte) { - case( 0x01): //rev.01 - E_Notify(PSTR("01"), 0x80); - break; - case( 0x12): //rev.02 - E_Notify(PSTR("02"), 0x80); - break; - case( 0x13): //rev.03 - E_Notify(PSTR("03"), 0x80); - break; - default: - E_Notify(PSTR("invalid. Value returned: "), 0x80); - print_hex(tmpbyte, 8); - halt55(); - break; - }//switch( tmpbyte... - }//check revision register - /* SPI long test */ - { - E_Notify(PSTR("\r\nSPI long test. Transfers 1MB of data. Each dot is 64K"), 0x80); - uint8_t sample_wr = 0; - uint8_t sample_rd = 0; - uint8_t gpinpol_copy = Usb.regRd(rGPINPOL); - for(uint8_t i = 0; i < 16; i++) { - for(uint16_t j = 0; j < 65535; j++) { - Usb.regWr(rGPINPOL, sample_wr); - sample_rd = Usb.regRd(rGPINPOL); - if(sample_rd != sample_wr) { - E_Notify(PSTR("\r\nTest failed. "), 0x80); - E_Notify(PSTR("Value written: "), 0x80); - print_hex(sample_wr, 8); - E_Notify(PSTR(" read: "), 0x80); - print_hex(sample_rd, 8); - halt55(); - }//if( sample_rd != sample_wr.. - sample_wr++; - }//for( uint16_t j... - E_Notify(PSTR("."), 0x80); - }//for( uint8_t i... - Usb.regWr(rGPINPOL, gpinpol_copy); - E_Notify(PSTR(" SPI long test passed"), 0x80); - }//SPI long test - /* GPIO test */ - /* in order to simplify board layout, GPIN pins on text fixture are connected to GPOUT */ - /* in reverse order, i.e, GPIN0 is connected to GPOUT7, GPIN1 to GPOUT6, etc. */ - { - uint8_t tmpbyte; - E_Notify(PSTR("\r\nGPIO test. Connect GPIN0 to GPOUT7, GPIN1 to GPOUT6, and so on"), 0x80); - for(uint8_t sample_gpio = 0; sample_gpio < 255; sample_gpio++) { - Usb.gpioWr(sample_gpio); - tmpbyte = Usb.gpioRd(); - /* bit reversing code copied vetbatim from http://graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious */ - tmpbyte = ((tmpbyte * 0x0802LU & 0x22110LU) | (tmpbyte * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16; - if(sample_gpio != tmpbyte) { - E_Notify(PSTR("\r\nTest failed. Value written: "), 0x80); - print_hex(sample_gpio, 8); - E_Notify(PSTR(" Value read: "), 0x80); - print_hex(tmpbyte, 8); - E_Notify(PSTR(" "), 0x80); - press_any_key(); - break; - }//if( sample_gpio != tmpbyte... - }//for( uint8_t sample_gpio... - E_Notify(PSTR("\r\nGPIO test passed."), 0x80); - }//GPIO test - /* PLL test. Stops/starts MAX3421E oscillator several times */ - { - E_Notify(PSTR("\r\nPLL test. 100 chip resets will be performed"), 0x80); - /* check current state of the oscillator */ - if(!(Usb.regRd(rUSBIRQ) & bmOSCOKIRQ)) { //wrong state - should be on - E_Notify(PSTR("\r\nCurrent oscillator state unexpected."), 0x80); - press_any_key(); - } - /* Restart oscillator */ - E_Notify(PSTR("\r\nResetting oscillator\r\n"), 0x80); - for(uint16_t i = 0; i < 100; i++) { - E_Notify(PSTR("\rReset number "), 0x80); - Serial.print(i, DEC); - Usb.regWr(rUSBCTL, bmCHIPRES); //reset - if(Usb.regRd(rUSBIRQ) & bmOSCOKIRQ) { //wrong state - should be off - E_Notify(PSTR("\r\nCurrent oscillator state unexpected."), 0x80); - halt55(); - } - Usb.regWr(rUSBCTL, 0x00); //release from reset - uint16_t j = 0; - for(j = 1; j < 65535; j++) { //tracking off to on time - if(Usb.regRd(rUSBIRQ) & bmOSCOKIRQ) { - E_Notify(PSTR(" Time to stabilize - "), 0x80); - Serial.print(j, DEC); - E_Notify(PSTR(" cycles\r\n"), 0x80); - break; - } - }//for( uint16_t j = 0; j < 65535; j++ - if(j == 0) { - E_Notify(PSTR("PLL failed to stabilize"), 0x80); - press_any_key(); - } - }//for( uint8_t i = 0; i < 255; i++ - - }//PLL test - /* initializing USB stack */ - if(Usb.Init() == -1) { - E_Notify(PSTR("\r\nOSCOKIRQ failed to assert"), 0x80); - halt55(); - } - E_Notify(PSTR("\r\nChecking USB device communication.\r\n"), 0x80); -} - -void loop() { - delay(200); - Usb.Task(); - usbstate = Usb.getUsbTaskState(); - if(usbstate != laststate) { - laststate = usbstate; - /**/ - switch(usbstate) { - case( USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE): - E_Notify(PSTR("\r\nWaiting for device..."), 0x80); - break; - case( USB_ATTACHED_SUBSTATE_RESET_DEVICE): - E_Notify(PSTR("\r\nDevice connected. Resetting..."), 0x80); - break; - case( USB_ATTACHED_SUBSTATE_WAIT_SOF): - E_Notify(PSTR("\r\nReset complete. Waiting for the first SOF..."), 0x80); - break; - case( USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE): - E_Notify(PSTR("\r\nSOF generation started. Enumerating device..."), 0x80); - break; - case( USB_STATE_ADDRESSING): - E_Notify(PSTR("\r\nSetting device address..."), 0x80); - break; - case( USB_STATE_RUNNING): - E_Notify(PSTR("\r\nGetting device descriptor"), 0x80); - rcode = Usb.getDevDescr(1, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*) & buf); - - if(rcode) { - E_Notify(PSTR("\r\nError reading device descriptor. Error code "), 0x80); - print_hex(rcode, 8); - } else { - /**/ - E_Notify(PSTR("\r\nDescriptor Length:\t"), 0x80); - print_hex(buf.bLength, 8); - E_Notify(PSTR("\r\nDescriptor type:\t"), 0x80); - print_hex(buf.bDescriptorType, 8); - E_Notify(PSTR("\r\nUSB version:\t\t"), 0x80); - print_hex(buf.bcdUSB, 16); - E_Notify(PSTR("\r\nDevice class:\t\t"), 0x80); - print_hex(buf.bDeviceClass, 8); - E_Notify(PSTR("\r\nDevice Subclass:\t"), 0x80); - print_hex(buf.bDeviceSubClass, 8); - E_Notify(PSTR("\r\nDevice Protocol:\t"), 0x80); - print_hex(buf.bDeviceProtocol, 8); - E_Notify(PSTR("\r\nMax.packet size:\t"), 0x80); - print_hex(buf.bMaxPacketSize0, 8); - E_Notify(PSTR("\r\nVendor ID:\t\t"), 0x80); - print_hex(buf.idVendor, 16); - E_Notify(PSTR("\r\nProduct ID:\t\t"), 0x80); - print_hex(buf.idProduct, 16); - E_Notify(PSTR("\r\nRevision ID:\t\t"), 0x80); - print_hex(buf.bcdDevice, 16); - E_Notify(PSTR("\r\nMfg.string index:\t"), 0x80); - print_hex(buf.iManufacturer, 8); - E_Notify(PSTR("\r\nProd.string index:\t"), 0x80); - print_hex(buf.iProduct, 8); - E_Notify(PSTR("\r\nSerial number index:\t"), 0x80); - print_hex(buf.iSerialNumber, 8); - E_Notify(PSTR("\r\nNumber of conf.:\t"), 0x80); - print_hex(buf.bNumConfigurations, 8); - /**/ - E_Notify(PSTR("\r\n\nAll tests passed. Press RESET to restart test"), 0x80); - while(1); - } - break; - case( USB_STATE_ERROR): - E_Notify(PSTR("\r\nUSB state machine reached error state"), 0x80); - break; - - default: - break; - }//switch( usbstate... - } -}//loop()... - -/* constantly transmits 0x55 via SPI to aid probing */ -void halt55() { - - E_Notify(PSTR("\r\nUnrecoverable error - test halted!!"), 0x80); - E_Notify(PSTR("\r\n0x55 pattern is transmitted via SPI"), 0x80); - E_Notify(PSTR("\r\nPress RESET to restart test"), 0x80); - - while(1) { - Usb.regWr(0x55, 0x55); - } -} - -/* prints hex numbers with leading zeroes */ -void print_hex(int v, int num_places) { - int mask = 0, n, num_nibbles, digit; - - for(n = 1; n <= num_places; n++) { - mask = (mask << 1) | 0x0001; - } - v = v & mask; // truncate v to specified number of places - - num_nibbles = num_places / 4; - if((num_places % 4) != 0) { - ++num_nibbles; - } - do { - digit = ((v >> (num_nibbles - 1) * 4)) & 0x0f; - Serial.print(digit, HEX); - } while(--num_nibbles); -} - -/* prints "Press any key" and returns when key is pressed */ -void press_any_key() { - E_Notify(PSTR("\r\nPress any key to continue..."), 0x80); - while(Serial.available() <= 0); //wait for input - Serial.read(); //empty input buffer - return; -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/cdc_XR21B1411/XR_terminal/XR_terminal.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/cdc_XR21B1411/XR_terminal/XR_terminal.ino deleted file mode 100644 index 0173a08b50..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/cdc_XR21B1411/XR_terminal/XR_terminal.ino +++ /dev/null @@ -1,83 +0,0 @@ -#include - -// Satisfy IDE, which only needs to see the include statment in the ino. -#ifdef dobogusinclude -#include -#include -#endif - -class ACMAsyncOper : public CDCAsyncOper -{ -public: - uint8_t OnInit(ACM *pacm); -}; - -uint8_t ACMAsyncOper::OnInit(ACM *pacm) -{ - uint8_t rcode; - // Set DTR = 1 RTS=1 - rcode = pacm->SetControlLineState(3); - - if (rcode) - { - ErrorMessage(PSTR("SetControlLineState"), rcode); - return rcode; - } - - LINE_CODING lc; - lc.dwDTERate = 115200; - lc.bCharFormat = 0; - lc.bParityType = 0; - lc.bDataBits = 8; - - rcode = pacm->SetLineCoding(&lc); - - if (rcode) - ErrorMessage(PSTR("SetLineCoding"), rcode); - - return rcode; -} - -USB Usb; -ACMAsyncOper AsyncOper; -XR21B1411 Acm(&Usb, &AsyncOper); - -void setup() { - Serial.begin( 115200 ); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - Serial.println("\r\n\r\nStart"); - - if (Usb.Init() == -1) Serial.println("OSCOKIRQ failed to assert"); -} - -void loop() { - Usb.Task(); - if( Acm.isReady()) { - uint8_t rcode; - uint8_t buf[1]; - uint16_t rcvd = 1; - - /* read keyboard */ - if(Serial.available()) { - uint8_t data = Serial.read(); - /* send */ - rcode = Acm.SndData(1, &data); - if (rcode) - ErrorMessage(PSTR("SndData"), rcode); - } - - /* read XR serial */ - rcode = Acm.RcvData(&rcvd, buf); - if (rcode && rcode != hrNAK) - ErrorMessage(PSTR("Ret"), rcode); - - if( rcvd ) { //more than zero bytes received - for(uint16_t i=0; i < rcvd; i++ ) { - Serial.print((char)buf[i]); - } - } - } -} - diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/ftdi/USBFTDILoopback/USBFTDILoopback.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/ftdi/USBFTDILoopback/USBFTDILoopback.ino deleted file mode 100644 index 5be7adc2f3..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/ftdi/USBFTDILoopback/USBFTDILoopback.ino +++ /dev/null @@ -1,98 +0,0 @@ -#include -#include - -#include "pgmstrings.h" - -// Satisfy the IDE, which needs to see the include statment in the ino too. -#ifdef dobogusinclude -#include -#include -#endif - -class FTDIAsync : public FTDIAsyncOper -{ -public: - uint8_t OnInit(FTDI *pftdi); -}; - -uint8_t FTDIAsync::OnInit(FTDI *pftdi) -{ - uint8_t rcode = 0; - - rcode = pftdi->SetBaudRate(115200); - - if (rcode) - { - ErrorMessage(PSTR("SetBaudRate"), rcode); - return rcode; - } - rcode = pftdi->SetFlowControl(FTDI_SIO_DISABLE_FLOW_CTRL); - - if (rcode) - ErrorMessage(PSTR("SetFlowControl"), rcode); - - return rcode; -} - -USB Usb; -//USBHub Hub(&Usb); -FTDIAsync FtdiAsync; -FTDI Ftdi(&Usb, &FtdiAsync); - -uint32_t next_time; - -void setup() -{ - Serial.begin( 115200 ); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - Serial.println("Start"); - - if (Usb.Init() == -1) - Serial.println("OSC did not start."); - - delay( 200 ); - - next_time = millis() + 5000; -} - -void loop() -{ - Usb.Task(); - - if( Usb.getUsbTaskState() == USB_STATE_RUNNING ) - { - uint8_t rcode; - char strbuf[] = "DEADBEEF"; - //char strbuf[] = "The quick brown fox jumps over the lazy dog"; - //char strbuf[] = "This string contains 61 character to demonstrate FTDI buffers"; //add one symbol to it to see some garbage - Serial.print("."); - - rcode = Ftdi.SndData(strlen(strbuf), (uint8_t*)strbuf); - - if (rcode) - ErrorMessage(PSTR("SndData"), rcode); - - delay(50); - - uint8_t buf[64]; - - for (uint8_t i=0; i<64; i++) - buf[i] = 0; - - uint16_t rcvd = 64; - rcode = Ftdi.RcvData(&rcvd, buf); - - if (rcode && rcode != hrNAK) - ErrorMessage(PSTR("Ret"), rcode); - - // The device reserves the first two bytes of data - // to contain the current values of the modem and line status registers. - if (rcvd > 2) - Serial.print((char*)(buf+2)); - - delay(10); - } -} - diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/ftdi/USBFTDILoopback/pgmstrings.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/ftdi/USBFTDILoopback/pgmstrings.h deleted file mode 100644 index bdb0077ecc..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/ftdi/USBFTDILoopback/pgmstrings.h +++ /dev/null @@ -1,52 +0,0 @@ -#if !defined(__PGMSTRINGS_H__) -#define __PGMSTRINGS_H__ - -#define LOBYTE(x) ((char*)(&(x)))[0] -#define HIBYTE(x) ((char*)(&(x)))[1] -#define BUFSIZE 256 //buffer size - - -/* Print strings in Program Memory */ -const char Gen_Error_str[] PROGMEM = "\r\nRequest error. Error code:\t"; -const char Dev_Header_str[] PROGMEM ="\r\nDevice descriptor: "; -const char Dev_Length_str[] PROGMEM ="\r\nDescriptor Length:\t"; -const char Dev_Type_str[] PROGMEM ="\r\nDescriptor type:\t"; -const char Dev_Version_str[] PROGMEM ="\r\nUSB version:\t\t"; -const char Dev_Class_str[] PROGMEM ="\r\nDevice class:\t\t"; -const char Dev_Subclass_str[] PROGMEM ="\r\nDevice Subclass:\t"; -const char Dev_Protocol_str[] PROGMEM ="\r\nDevice Protocol:\t"; -const char Dev_Pktsize_str[] PROGMEM ="\r\nMax.packet size:\t"; -const char Dev_Vendor_str[] PROGMEM ="\r\nVendor ID:\t\t"; -const char Dev_Product_str[] PROGMEM ="\r\nProduct ID:\t\t"; -const char Dev_Revision_str[] PROGMEM ="\r\nRevision ID:\t\t"; -const char Dev_Mfg_str[] PROGMEM ="\r\nMfg.string index:\t"; -const char Dev_Prod_str[] PROGMEM ="\r\nProd.string index:\t"; -const char Dev_Serial_str[] PROGMEM ="\r\nSerial number index:\t"; -const char Dev_Nconf_str[] PROGMEM ="\r\nNumber of conf.:\t"; -const char Conf_Trunc_str[] PROGMEM ="Total length truncated to 256 bytes"; -const char Conf_Header_str[] PROGMEM ="\r\nConfiguration descriptor:"; -const char Conf_Totlen_str[] PROGMEM ="\r\nTotal length:\t\t"; -const char Conf_Nint_str[] PROGMEM ="\r\nNum.intf:\t\t"; -const char Conf_Value_str[] PROGMEM ="\r\nConf.value:\t\t"; -const char Conf_String_str[] PROGMEM ="\r\nConf.string:\t\t"; -const char Conf_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t"; -const char Conf_Pwr_str[] PROGMEM ="\r\nMax.pwr:\t\t"; -const char Int_Header_str[] PROGMEM ="\r\n\r\nInterface descriptor:"; -const char Int_Number_str[] PROGMEM ="\r\nIntf.number:\t\t"; -const char Int_Alt_str[] PROGMEM ="\r\nAlt.:\t\t\t"; -const char Int_Endpoints_str[] PROGMEM ="\r\nEndpoints:\t\t"; -const char Int_Class_str[] PROGMEM ="\r\nIntf. Class:\t\t"; -const char Int_Subclass_str[] PROGMEM ="\r\nIntf. Subclass:\t\t"; -const char Int_Protocol_str[] PROGMEM ="\r\nIntf. Protocol:\t\t"; -const char Int_String_str[] PROGMEM ="\r\nIntf.string:\t\t"; -const char End_Header_str[] PROGMEM ="\r\n\r\nEndpoint descriptor:"; -const char End_Address_str[] PROGMEM ="\r\nEndpoint address:\t"; -const char End_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t"; -const char End_Pktsize_str[] PROGMEM ="\r\nMax.pkt size:\t\t"; -const char End_Interval_str[] PROGMEM ="\r\nPolling interval:\t"; -const char Unk_Header_str[] PROGMEM = "\r\nUnknown descriptor:"; -const char Unk_Length_str[] PROGMEM ="\r\nLength:\t\t"; -const char Unk_Type_str[] PROGMEM ="\r\nType:\t\t"; -const char Unk_Contents_str[] PROGMEM ="\r\nContents:\t"; - -#endif // __PGMSTRINGS_H__ \ No newline at end of file diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/hub_demo/hub_demo.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/hub_demo/hub_demo.ino deleted file mode 100644 index d8b2d4bb72..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/hub_demo/hub_demo.ino +++ /dev/null @@ -1,345 +0,0 @@ -#include -#include "pgmstrings.h" - -// Satisfy the IDE, which needs to see the include statment in the ino too. -#ifdef dobogusinclude -#include -#include -#endif - -USB Usb; -USBHub Hub1(&Usb); -USBHub Hub2(&Usb); -USBHub Hub3(&Usb); -USBHub Hub4(&Usb); - -uint32_t next_time; - -void PrintAllAddresses(UsbDevice *pdev) -{ - UsbDeviceAddress adr; - adr.devAddress = pdev->address.devAddress; - Serial.print("\r\nAddr:"); - Serial.print(adr.devAddress, HEX); - Serial.print("("); - Serial.print(adr.bmHub, HEX); - Serial.print("."); - Serial.print(adr.bmParent, HEX); - Serial.print("."); - Serial.print(adr.bmAddress, HEX); - Serial.println(")"); -} - -void PrintAddress(uint8_t addr) -{ - UsbDeviceAddress adr; - adr.devAddress = addr; - Serial.print("\r\nADDR:\t"); - Serial.println(adr.devAddress, HEX); - Serial.print("DEV:\t"); - Serial.println(adr.bmAddress, HEX); - Serial.print("PRNT:\t"); - Serial.println(adr.bmParent, HEX); - Serial.print("HUB:\t"); - Serial.println(adr.bmHub, HEX); -} - -void setup() -{ - Serial.begin( 115200 ); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - Serial.println("Start"); - - if (Usb.Init() == -1) - Serial.println("OSC did not start."); - - delay( 200 ); - - next_time = millis() + 10000; -} - -byte getdevdescr( byte addr, byte &num_conf ); - -void PrintDescriptors(uint8_t addr) -{ - uint8_t rcode = 0; - byte num_conf = 0; - - rcode = getdevdescr( (byte)addr, num_conf ); - if ( rcode ) - { - printProgStr(Gen_Error_str); - print_hex( rcode, 8 ); - } - Serial.print("\r\n"); - - for (int i = 0; i < num_conf; i++) - { - rcode = getconfdescr( addr, i ); // get configuration descriptor - if ( rcode ) - { - printProgStr(Gen_Error_str); - print_hex(rcode, 8); - } - Serial.println("\r\n"); - } -} - -void PrintAllDescriptors(UsbDevice *pdev) -{ - Serial.println("\r\n"); - print_hex(pdev->address.devAddress, 8); - Serial.println("\r\n--"); - PrintDescriptors( pdev->address.devAddress ); -} - -void loop() -{ - Usb.Task(); - - if ( Usb.getUsbTaskState() == USB_STATE_RUNNING ) - { - if ((millis() - next_time) >= 0L) - { - Usb.ForEachUsbDevice(&PrintAllDescriptors); - Usb.ForEachUsbDevice(&PrintAllAddresses); - - while ( 1 ); //stop - } - } -} - -byte getdevdescr( byte addr, byte &num_conf ) -{ - USB_DEVICE_DESCRIPTOR buf; - byte rcode; - rcode = Usb.getDevDescr( addr, 0, 0x12, ( uint8_t *)&buf ); - if ( rcode ) { - return ( rcode ); - } - printProgStr(Dev_Header_str); - printProgStr(Dev_Length_str); - print_hex( buf.bLength, 8 ); - printProgStr(Dev_Type_str); - print_hex( buf.bDescriptorType, 8 ); - printProgStr(Dev_Version_str); - print_hex( buf.bcdUSB, 16 ); - printProgStr(Dev_Class_str); - print_hex( buf.bDeviceClass, 8 ); - printProgStr(Dev_Subclass_str); - print_hex( buf.bDeviceSubClass, 8 ); - printProgStr(Dev_Protocol_str); - print_hex( buf.bDeviceProtocol, 8 ); - printProgStr(Dev_Pktsize_str); - print_hex( buf.bMaxPacketSize0, 8 ); - printProgStr(Dev_Vendor_str); - print_hex( buf.idVendor, 16 ); - printProgStr(Dev_Product_str); - print_hex( buf.idProduct, 16 ); - printProgStr(Dev_Revision_str); - print_hex( buf.bcdDevice, 16 ); - printProgStr(Dev_Mfg_str); - print_hex( buf.iManufacturer, 8 ); - printProgStr(Dev_Prod_str); - print_hex( buf.iProduct, 8 ); - printProgStr(Dev_Serial_str); - print_hex( buf.iSerialNumber, 8 ); - printProgStr(Dev_Nconf_str); - print_hex( buf.bNumConfigurations, 8 ); - num_conf = buf.bNumConfigurations; - return ( 0 ); -} - -void printhubdescr(uint8_t *descrptr, uint8_t addr) -{ - HubDescriptor *pHub = (HubDescriptor*) descrptr; - uint8_t len = *((uint8_t*)descrptr); - - printProgStr(PSTR("\r\n\r\nHub Descriptor:\r\n")); - printProgStr(PSTR("bDescLength:\t\t")); - Serial.println(pHub->bDescLength, HEX); - - printProgStr(PSTR("bDescriptorType:\t")); - Serial.println(pHub->bDescriptorType, HEX); - - printProgStr(PSTR("bNbrPorts:\t\t")); - Serial.println(pHub->bNbrPorts, HEX); - - printProgStr(PSTR("LogPwrSwitchMode:\t")); - Serial.println(pHub->LogPwrSwitchMode, BIN); - - printProgStr(PSTR("CompoundDevice:\t\t")); - Serial.println(pHub->CompoundDevice, BIN); - - printProgStr(PSTR("OverCurrentProtectMode:\t")); - Serial.println(pHub->OverCurrentProtectMode, BIN); - - printProgStr(PSTR("TTThinkTime:\t\t")); - Serial.println(pHub->TTThinkTime, BIN); - - printProgStr(PSTR("PortIndicatorsSupported:")); - Serial.println(pHub->PortIndicatorsSupported, BIN); - - printProgStr(PSTR("Reserved:\t\t")); - Serial.println(pHub->Reserved, HEX); - - printProgStr(PSTR("bPwrOn2PwrGood:\t\t")); - Serial.println(pHub->bPwrOn2PwrGood, HEX); - - printProgStr(PSTR("bHubContrCurrent:\t")); - Serial.println(pHub->bHubContrCurrent, HEX); - - for (uint8_t i = 7; i < len; i++) - print_hex(descrptr[i], 8); - - //for (uint8_t i=1; i<=pHub->bNbrPorts; i++) - // PrintHubPortStatus(&Usb, addr, i, 1); -} - -byte getconfdescr( byte addr, byte conf ) -{ - uint8_t buf[ BUFSIZE ]; - uint8_t* buf_ptr = buf; - byte rcode; - byte descr_length; - byte descr_type; - unsigned int total_length; - rcode = Usb.getConfDescr( addr, 0, 4, conf, buf ); //get total length - LOBYTE( total_length ) = buf[ 2 ]; - HIBYTE( total_length ) = buf[ 3 ]; - if ( total_length > 256 ) { //check if total length is larger than buffer - printProgStr(Conf_Trunc_str); - total_length = 256; - } - rcode = Usb.getConfDescr( addr, 0, total_length, conf, buf ); //get the whole descriptor - while ( buf_ptr < buf + total_length ) { //parsing descriptors - descr_length = *( buf_ptr ); - descr_type = *( buf_ptr + 1 ); - switch ( descr_type ) { - case ( USB_DESCRIPTOR_CONFIGURATION ): - printconfdescr( buf_ptr ); - break; - case ( USB_DESCRIPTOR_INTERFACE ): - printintfdescr( buf_ptr ); - break; - case ( USB_DESCRIPTOR_ENDPOINT ): - printepdescr( buf_ptr ); - break; - case 0x29: - printhubdescr( buf_ptr, addr ); - break; - default: - printunkdescr( buf_ptr ); - break; - }//switch( descr_type - buf_ptr = ( buf_ptr + descr_length ); //advance buffer pointer - }//while( buf_ptr <=... - return ( rcode ); -} -/* prints hex numbers with leading zeroes */ -// copyright, Peter H Anderson, Baltimore, MD, Nov, '07 -// source: http://www.phanderson.com/arduino/arduino_display.html -void print_hex(int v, int num_places) -{ - int mask = 0, n, num_nibbles, digit; - - for (n = 1; n <= num_places; n++) { - mask = (mask << 1) | 0x0001; - } - v = v & mask; // truncate v to specified number of places - - num_nibbles = num_places / 4; - if ((num_places % 4) != 0) { - ++num_nibbles; - } - do { - digit = ((v >> (num_nibbles - 1) * 4)) & 0x0f; - Serial.print(digit, HEX); - } - while (--num_nibbles); -} -/* function to print configuration descriptor */ -void printconfdescr( uint8_t* descr_ptr ) -{ - USB_CONFIGURATION_DESCRIPTOR* conf_ptr = ( USB_CONFIGURATION_DESCRIPTOR* )descr_ptr; - printProgStr(Conf_Header_str); - printProgStr(Conf_Totlen_str); - print_hex( conf_ptr->wTotalLength, 16 ); - printProgStr(Conf_Nint_str); - print_hex( conf_ptr->bNumInterfaces, 8 ); - printProgStr(Conf_Value_str); - print_hex( conf_ptr->bConfigurationValue, 8 ); - printProgStr(Conf_String_str); - print_hex( conf_ptr->iConfiguration, 8 ); - printProgStr(Conf_Attr_str); - print_hex( conf_ptr->bmAttributes, 8 ); - printProgStr(Conf_Pwr_str); - print_hex( conf_ptr->bMaxPower, 8 ); - return; -} -/* function to print interface descriptor */ -void printintfdescr( uint8_t* descr_ptr ) -{ - USB_INTERFACE_DESCRIPTOR* intf_ptr = ( USB_INTERFACE_DESCRIPTOR* )descr_ptr; - printProgStr(Int_Header_str); - printProgStr(Int_Number_str); - print_hex( intf_ptr->bInterfaceNumber, 8 ); - printProgStr(Int_Alt_str); - print_hex( intf_ptr->bAlternateSetting, 8 ); - printProgStr(Int_Endpoints_str); - print_hex( intf_ptr->bNumEndpoints, 8 ); - printProgStr(Int_Class_str); - print_hex( intf_ptr->bInterfaceClass, 8 ); - printProgStr(Int_Subclass_str); - print_hex( intf_ptr->bInterfaceSubClass, 8 ); - printProgStr(Int_Protocol_str); - print_hex( intf_ptr->bInterfaceProtocol, 8 ); - printProgStr(Int_String_str); - print_hex( intf_ptr->iInterface, 8 ); - return; -} -/* function to print endpoint descriptor */ -void printepdescr( uint8_t* descr_ptr ) -{ - USB_ENDPOINT_DESCRIPTOR* ep_ptr = ( USB_ENDPOINT_DESCRIPTOR* )descr_ptr; - printProgStr(End_Header_str); - printProgStr(End_Address_str); - print_hex( ep_ptr->bEndpointAddress, 8 ); - printProgStr(End_Attr_str); - print_hex( ep_ptr->bmAttributes, 8 ); - printProgStr(End_Pktsize_str); - print_hex( ep_ptr->wMaxPacketSize, 16 ); - printProgStr(End_Interval_str); - print_hex( ep_ptr->bInterval, 8 ); - - return; -} -/*function to print unknown descriptor */ -void printunkdescr( uint8_t* descr_ptr ) -{ - byte length = *descr_ptr; - byte i; - printProgStr(Unk_Header_str); - printProgStr(Unk_Length_str); - print_hex( *descr_ptr, 8 ); - printProgStr(Unk_Type_str); - print_hex( *(descr_ptr + 1 ), 8 ); - printProgStr(Unk_Contents_str); - descr_ptr += 2; - for ( i = 0; i < length; i++ ) { - print_hex( *descr_ptr, 8 ); - descr_ptr++; - } -} - - -/* Print a string from Program Memory directly to save RAM */ -void printProgStr(const char* str) -{ - char c; - if (!str) return; - while ((c = pgm_read_byte(str++))) - Serial.print(c); -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/hub_demo/pgmstrings.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/hub_demo/pgmstrings.h deleted file mode 100644 index bdb0077ecc..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/hub_demo/pgmstrings.h +++ /dev/null @@ -1,52 +0,0 @@ -#if !defined(__PGMSTRINGS_H__) -#define __PGMSTRINGS_H__ - -#define LOBYTE(x) ((char*)(&(x)))[0] -#define HIBYTE(x) ((char*)(&(x)))[1] -#define BUFSIZE 256 //buffer size - - -/* Print strings in Program Memory */ -const char Gen_Error_str[] PROGMEM = "\r\nRequest error. Error code:\t"; -const char Dev_Header_str[] PROGMEM ="\r\nDevice descriptor: "; -const char Dev_Length_str[] PROGMEM ="\r\nDescriptor Length:\t"; -const char Dev_Type_str[] PROGMEM ="\r\nDescriptor type:\t"; -const char Dev_Version_str[] PROGMEM ="\r\nUSB version:\t\t"; -const char Dev_Class_str[] PROGMEM ="\r\nDevice class:\t\t"; -const char Dev_Subclass_str[] PROGMEM ="\r\nDevice Subclass:\t"; -const char Dev_Protocol_str[] PROGMEM ="\r\nDevice Protocol:\t"; -const char Dev_Pktsize_str[] PROGMEM ="\r\nMax.packet size:\t"; -const char Dev_Vendor_str[] PROGMEM ="\r\nVendor ID:\t\t"; -const char Dev_Product_str[] PROGMEM ="\r\nProduct ID:\t\t"; -const char Dev_Revision_str[] PROGMEM ="\r\nRevision ID:\t\t"; -const char Dev_Mfg_str[] PROGMEM ="\r\nMfg.string index:\t"; -const char Dev_Prod_str[] PROGMEM ="\r\nProd.string index:\t"; -const char Dev_Serial_str[] PROGMEM ="\r\nSerial number index:\t"; -const char Dev_Nconf_str[] PROGMEM ="\r\nNumber of conf.:\t"; -const char Conf_Trunc_str[] PROGMEM ="Total length truncated to 256 bytes"; -const char Conf_Header_str[] PROGMEM ="\r\nConfiguration descriptor:"; -const char Conf_Totlen_str[] PROGMEM ="\r\nTotal length:\t\t"; -const char Conf_Nint_str[] PROGMEM ="\r\nNum.intf:\t\t"; -const char Conf_Value_str[] PROGMEM ="\r\nConf.value:\t\t"; -const char Conf_String_str[] PROGMEM ="\r\nConf.string:\t\t"; -const char Conf_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t"; -const char Conf_Pwr_str[] PROGMEM ="\r\nMax.pwr:\t\t"; -const char Int_Header_str[] PROGMEM ="\r\n\r\nInterface descriptor:"; -const char Int_Number_str[] PROGMEM ="\r\nIntf.number:\t\t"; -const char Int_Alt_str[] PROGMEM ="\r\nAlt.:\t\t\t"; -const char Int_Endpoints_str[] PROGMEM ="\r\nEndpoints:\t\t"; -const char Int_Class_str[] PROGMEM ="\r\nIntf. Class:\t\t"; -const char Int_Subclass_str[] PROGMEM ="\r\nIntf. Subclass:\t\t"; -const char Int_Protocol_str[] PROGMEM ="\r\nIntf. Protocol:\t\t"; -const char Int_String_str[] PROGMEM ="\r\nIntf.string:\t\t"; -const char End_Header_str[] PROGMEM ="\r\n\r\nEndpoint descriptor:"; -const char End_Address_str[] PROGMEM ="\r\nEndpoint address:\t"; -const char End_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t"; -const char End_Pktsize_str[] PROGMEM ="\r\nMax.pkt size:\t\t"; -const char End_Interval_str[] PROGMEM ="\r\nPolling interval:\t"; -const char Unk_Header_str[] PROGMEM = "\r\nUnknown descriptor:"; -const char Unk_Length_str[] PROGMEM ="\r\nLength:\t\t"; -const char Unk_Type_str[] PROGMEM ="\r\nType:\t\t"; -const char Unk_Contents_str[] PROGMEM ="\r\nContents:\t"; - -#endif // __PGMSTRINGS_H__ \ No newline at end of file diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/max_LCD/max_LCD.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/max_LCD/max_LCD.ino deleted file mode 100644 index 6603ab90db..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/max_LCD/max_LCD.ino +++ /dev/null @@ -1,29 +0,0 @@ -// Just a copy of the HelloWorld example bundled with the LiquidCrystal library in the Arduino IDE - -// HD44780 compatible LCD display via MAX3421E GPOUT support header -// pinout: D[4-7] -> GPOUT[4-7], RS-> GPOUT[2], E ->GPOUT[3] - -#include - -// Satisfy IDE, which only needs to see the include statment in the ino. -#ifdef dobogusinclude -#include -#include -#endif - -USB Usb; -Max_LCD lcd(&Usb); - -void setup() { - // Set up the LCD's number of columns and rows: - lcd.begin(16, 2); - // Print a message to the LCD. - lcd.print("Hello, World!"); -} - -void loop() { - // Set the cursor to column 0, line 1 (note: line 1 is the second row, since counting begins with 0): - lcd.setCursor(0, 1); - // Print the number of seconds since reset: - lcd.print(millis() / 1000); -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/pl2303/pl2303_gprs_terminal/pl2303_gprs_terminal.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/pl2303/pl2303_gprs_terminal/pl2303_gprs_terminal.ino deleted file mode 100644 index 7c4c9f6cbe..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/pl2303/pl2303_gprs_terminal/pl2303_gprs_terminal.ino +++ /dev/null @@ -1,101 +0,0 @@ -/* Arduino terminal for PL2303 USB to serial converter and DealeXtreme GPRS modem. */ -/* USB support */ -#include -/* CDC support */ -#include -#include - -// Satisfy the IDE, which needs to see the include statment in the ino too. -#ifdef dobogusinclude -#include -#include -#endif - -class PLAsyncOper : public CDCAsyncOper -{ -public: - uint8_t OnInit(ACM *pacm); -}; - -uint8_t PLAsyncOper::OnInit(ACM *pacm) -{ - uint8_t rcode; - - // Set DTR = 1 - rcode = pacm->SetControlLineState(1); - - if (rcode) - { - ErrorMessage(PSTR("SetControlLineState"), rcode); - return rcode; - } - - LINE_CODING lc; - //lc.dwDTERate = 9600; - lc.dwDTERate = 115200; - lc.bCharFormat = 0; - lc.bParityType = 0; - lc.bDataBits = 8; - - rcode = pacm->SetLineCoding(&lc); - - if (rcode) - ErrorMessage(PSTR("SetLineCoding"), rcode); - - return rcode; -} -USB Usb; -//USBHub Hub(&Usb); -PLAsyncOper AsyncOper; -PL2303 Pl(&Usb, &AsyncOper); - -void setup() -{ - Serial.begin( 115200 ); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - Serial.println("Start"); - - if (Usb.Init() == -1) - Serial.println("OSCOKIRQ failed to assert"); - - delay( 200 ); -} - -void loop() -{ - Usb.Task(); - - if( Usb.getUsbTaskState() == USB_STATE_RUNNING ) - { - uint8_t rcode; - - /* reading the keyboard */ - if(Serial.available()) { - uint8_t data= Serial.read(); - - /* sending to the phone */ - rcode = Pl.SndData(1, &data); - if (rcode) - ErrorMessage(PSTR("SndData"), rcode); - }//if(Serial.available()... - - /* reading the converter */ - /* buffer size must be greater or equal to max.packet size */ - /* it it set to 64 (largest possible max.packet size) here, can be tuned down - for particular endpoint */ - uint8_t buf[64]; - uint16_t rcvd = 64; - rcode = Pl.RcvData(&rcvd, buf); - if (rcode && rcode != hrNAK) - ErrorMessage(PSTR("Ret"), rcode); - - if( rcvd ) { //more than zero bytes received - for(uint16_t i=0; i < rcvd; i++ ) { - Serial.print((char)buf[i]); //printing on the screen - } - }//if( rcvd ... - }//if( Usb.getUsbTaskState() == USB_STATE_RUNNING.. -} - diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/pl2303/pl2303_gps/pl2303_gps.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/pl2303/pl2303_gps/pl2303_gps.ino deleted file mode 100644 index e8c8a02230..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/pl2303/pl2303_gps/pl2303_gps.ino +++ /dev/null @@ -1,88 +0,0 @@ -/* USB Host to PL2303-based USB GPS unit interface */ -/* Navibee GM720 receiver - Sirf Star III */ -/* USB support */ -#include -/* CDC support */ -#include -#include - -// Satisfy the IDE, which needs to see the include statment in the ino too. -#ifdef dobogusinclude -#include -#include -#endif - -class PLAsyncOper : public CDCAsyncOper { -public: - uint8_t OnInit(ACM *pacm); -}; - -uint8_t PLAsyncOper::OnInit(ACM *pacm) { - uint8_t rcode; - - // Set DTR = 1 - rcode = pacm->SetControlLineState(1); - - if(rcode) { - ErrorMessage(PSTR("SetControlLineState"), rcode); - return rcode; - } - - LINE_CODING lc; - lc.dwDTERate = 4800; //default serial speed of GPS unit - lc.bCharFormat = 0; - lc.bParityType = 0; - lc.bDataBits = 8; - - rcode = pacm->SetLineCoding(&lc); - - if(rcode) - ErrorMessage(PSTR("SetLineCoding"), rcode); - - return rcode; -} - -USB Usb; -USBHub Hub(&Usb); -PLAsyncOper AsyncOper; -PL2303 Pl(&Usb, &AsyncOper); -uint32_t read_delay; -#define READ_DELAY 100 - -void setup() { - Serial.begin(115200); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - Serial.println("Start"); - - if(Usb.Init() == -1) - Serial.println("OSCOKIRQ failed to assert"); - - delay(200); -} - -void loop() { - uint8_t rcode; - uint8_t buf[64]; //serial buffer equals Max.packet size of bulk-IN endpoint - uint16_t rcvd = 64; - - Usb.Task(); - - if(Pl.isReady()) { - /* reading the GPS */ - if((long)(millis() - read_delay) >= 0L) { - read_delay += READ_DELAY; - rcode = Pl.RcvData(&rcvd, buf); - if(rcode && rcode != hrNAK) - ErrorMessage(PSTR("Ret"), rcode); - if(rcvd) { //more than zero bytes received - for(uint16_t i = 0; i < rcvd; i++) { - Serial.print((char)buf[i]); //printing on the screen - }//for( uint16_t i=0; i < rcvd; i++... - }//if( rcvd - }//if( read_delay > millis()... - }//if( Usb.getUsbTaskState() == USB_STATE_RUNNING.. -} - - diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/pl2303/pl2303_tinygps/pl2303_tinygps.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/pl2303/pl2303_tinygps/pl2303_tinygps.ino deleted file mode 100644 index d527eabe00..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/pl2303/pl2303_tinygps/pl2303_tinygps.ino +++ /dev/null @@ -1,217 +0,0 @@ -/* USB Host to PL2303-based USB GPS unit interface */ -/* Navibee GM720 receiver - Sirf Star III */ -/* Mikal Hart's TinyGPS library */ -/* test_with_gps_device library example modified for PL2302 access */ - -/* USB support */ -#include - -/* CDC support */ -#include -#include - -#include - -// Satisfy the IDE, which needs to see the include statment in the ino too. -#ifdef dobogusinclude -#include -#include -#endif - -/* This sample code demonstrates the normal use of a TinyGPS object. - Modified to be used with USB Host Shield Library r2.0 - and USB Host Shield 2.0 -*/ - -class PLAsyncOper : public CDCAsyncOper -{ -public: - uint8_t OnInit(ACM *pacm); -}; - -uint8_t PLAsyncOper::OnInit(ACM *pacm) -{ - uint8_t rcode; - - // Set DTR = 1 - rcode = pacm->SetControlLineState(1); - - if (rcode) { - ErrorMessage(PSTR("SetControlLineState"), rcode); - return rcode; - } - - LINE_CODING lc; - lc.dwDTERate = 4800; //default serial speed of GPS unit - lc.bCharFormat = 0; - lc.bParityType = 0; - lc.bDataBits = 8; - - rcode = pacm->SetLineCoding(&lc); - - if (rcode) { - ErrorMessage(PSTR("SetLineCoding"), rcode); - } - - return rcode; -} - -USB Usb; -//USBHub Hub(&Usb); -PLAsyncOper AsyncOper; -PL2303 Pl(&Usb, &AsyncOper); -TinyGPS gps; - -void gpsdump(TinyGPS &gps); -bool feedgps(); -void printFloat(double f, int digits = 2); - -void setup() -{ - - Serial.begin(115200); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - - Serial.print("Testing TinyGPS library v. "); Serial.println(TinyGPS::library_version()); - Serial.println("by Mikal Hart"); - Serial.println(); - Serial.print("Sizeof(gpsobject) = "); Serial.println(sizeof(TinyGPS)); - Serial.println(); - /* USB Initialization */ - if (Usb.Init() == -1) { - Serial.println("OSCOKIRQ failed to assert"); - } - - delay( 200 ); -} - -void loop() -{ - Usb.Task(); - - if( Pl.isReady()) { - - bool newdata = false; - unsigned long start = millis(); - - // Every 5 seconds we print an update - while (millis() - start < 5000) { - if( feedgps()) { - newdata = true; - } - }//while (millis()... - - if (newdata) { - Serial.println("Acquired Data"); - Serial.println("-------------"); - gpsdump(gps); - Serial.println("-------------"); - Serial.println(); - }//if( newdata... - }//if( Usb.getUsbTaskState() == USB_STATE_RUNNING... -} - -void printFloat(double number, int digits) -{ - // Handle negative numbers - if (number < 0.0) - { - Serial.print('-'); - number = -number; - } - - // Round correctly so that print(1.999, 2) prints as "2.00" - double rounding = 0.5; - for (uint8_t i=0; i 0) - Serial.print("."); - - // Extract digits from the remainder one at a time - while (digits-- > 0) - { - remainder *= 10.0; - int toPrint = int(remainder); - Serial.print(toPrint); - remainder -= toPrint; - } -} - -void gpsdump(TinyGPS &gps) -{ - long lat, lon; - float flat, flon; - unsigned long age, date, time, chars; - int year; - byte month, day, hour, minute, second, hundredths; - unsigned short sentences, failed; - - gps.get_position(&lat, &lon, &age); - Serial.print("Lat/Long(10^-5 deg): "); Serial.print(lat); Serial.print(", "); Serial.print(lon); - Serial.print(" Fix age: "); Serial.print(age); Serial.println("ms."); - - feedgps(); // If we don't feed the gps during this long routine, we may drop characters and get checksum errors - - gps.f_get_position(&flat, &flon, &age); - Serial.print("Lat/Long(float): "); printFloat(flat, 5); Serial.print(", "); printFloat(flon, 5); - Serial.print(" Fix age: "); Serial.print(age); Serial.println("ms."); - - feedgps(); - - gps.get_datetime(&date, &time, &age); - Serial.print("Date(ddmmyy): "); Serial.print(date); Serial.print(" Time(hhmmsscc): "); Serial.print(time); - Serial.print(" Fix age: "); Serial.print(age); Serial.println("ms."); - - feedgps(); - - gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age); - Serial.print("Date: "); Serial.print(static_cast(month)); Serial.print("/"); Serial.print(static_cast(day)); Serial.print("/"); Serial.print(year); - Serial.print(" Time: "); Serial.print(static_cast(hour)); Serial.print(":"); Serial.print(static_cast(minute)); Serial.print(":"); Serial.print(static_cast(second)); Serial.print("."); Serial.print(static_cast(hundredths)); - Serial.print(" Fix age: "); Serial.print(age); Serial.println("ms."); - - feedgps(); - - Serial.print("Alt(cm): "); Serial.print(gps.altitude()); Serial.print(" Course(10^-2 deg): "); Serial.print(gps.course()); Serial.print(" Speed(10^-2 knots): "); Serial.println(gps.speed()); - Serial.print("Alt(float): "); printFloat(gps.f_altitude()); Serial.print(" Course(float): "); printFloat(gps.f_course()); Serial.println(); - Serial.print("Speed(knots): "); printFloat(gps.f_speed_knots()); Serial.print(" (mph): "); printFloat(gps.f_speed_mph()); - Serial.print(" (mps): "); printFloat(gps.f_speed_mps()); Serial.print(" (kmph): "); printFloat(gps.f_speed_kmph()); Serial.println(); - - feedgps(); - - gps.stats(&chars, &sentences, &failed); - Serial.print("Stats: characters: "); Serial.print(chars); Serial.print(" sentences: "); Serial.print(sentences); Serial.print(" failed checksum: "); Serial.println(failed); -} - -bool feedgps() -{ - uint8_t rcode; - uint8_t buf[64]; //serial buffer equals Max.packet size of bulk-IN endpoint - uint16_t rcvd = 64; - { - /* reading the GPS */ - rcode = Pl.RcvData(&rcvd, buf); - if (rcode && rcode != hrNAK) - ErrorMessage(PSTR("Ret"), rcode); - rcode = false; - if( rcvd ) { //more than zero bytes received - for( uint16_t i=0; i < rcvd; i++ ) { - if( gps.encode((char)buf[i])) { //feed a character to gps object - rcode = true; - }//if( gps.encode(buf[i]... - }//for( uint16_t i=0; i < rcvd; i++... - }//if( rcvd... - } - return( rcode ); -} - diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/pl2303/pl2303_xbee_terminal/pl2303_xbee_terminal.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/pl2303/pl2303_xbee_terminal/pl2303_xbee_terminal.ino deleted file mode 100644 index 67b7dab603..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/pl2303/pl2303_xbee_terminal/pl2303_xbee_terminal.ino +++ /dev/null @@ -1,117 +0,0 @@ -/* Arduino terminal for PL2303 USB to serial converter and XBee radio. */ -/* Inserts linefeed after carriage return in data sent to and received from Xbee */ -/* USB support */ -#include -/* CDC support */ -#include -#include - -// Satisfy the IDE, which needs to see the include statment in the ino too. -#ifdef dobogusinclude -#include -#include -#endif - -class PLAsyncOper : public CDCAsyncOper -{ -public: - uint8_t OnInit(ACM *pacm); -}; - -uint8_t PLAsyncOper::OnInit(ACM *pacm) -{ - uint8_t rcode; - - // Set DTR = 1 - rcode = pacm->SetControlLineState(1); - - if (rcode) - { - ErrorMessage(PSTR("SetControlLineState"), rcode); - return rcode; - } - - LINE_CODING lc; - lc.dwDTERate = 115200; - lc.bCharFormat = 0; - lc.bParityType = 0; - lc.bDataBits = 8; - - rcode = pacm->SetLineCoding(&lc); - - if (rcode) - ErrorMessage(PSTR("SetLineCoding"), rcode); - - return rcode; -} -USB Usb; -//USBHub Hub(&Usb); -PLAsyncOper AsyncOper; -PL2303 Pl(&Usb, &AsyncOper); - -void setup() -{ - Serial.begin( 115200 ); -#if !defined(__MIPSEL__) - while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection -#endif - Serial.println("Start"); - - if (Usb.Init() == -1) - Serial.println("OSCOKIRQ failed to assert"); - - delay( 200 ); -} - -void loop() -{ - Usb.Task(); - - if( Usb.getUsbTaskState() == USB_STATE_RUNNING ) - { - uint8_t rcode; - - /* reading the keyboard */ - if(Serial.available()) { - uint8_t data= Serial.read(); - - if ( data == '\r' ) { - Serial.print("\r\n"); //insert linefeed - } - else { - Serial.print( data ); //echo back to the screen - } - - /* sending to the phone */ - rcode = Pl.SndData(1, &data); - if (rcode) - ErrorMessage(PSTR("SndData"), rcode); - }//if(Serial.available()... - - delay(50); - - /* reading the converter */ - /* buffer size must be greater or equal to max.packet size */ - /* it it set to 64 (largest possible max.packet size) here, can be tuned down - for particular endpoint */ - uint8_t buf[64]; - uint16_t rcvd = 64; - rcode = Pl.RcvData(&rcvd, buf); - if (rcode && rcode != hrNAK) - ErrorMessage(PSTR("Ret"), rcode); - - if( rcvd ) { //more than zero bytes received - for(uint16_t i=0; i < rcvd; i++ ) { - if( buf[i] =='\r' ) { - Serial.print("\r\n"); //insert linefeed - } - else { - Serial.print((char)buf[i]); //printing on the screen - } - } - } - delay(10); - }//if( Usb.getUsbTaskState() == USB_STATE_RUNNING.. -} - - diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/testusbhostFAT/Makefile b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/testusbhostFAT/Makefile deleted file mode 100644 index 8a12ddc047..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/testusbhostFAT/Makefile +++ /dev/null @@ -1,64 +0,0 @@ -# -# These are set for a mega 1280 + quadram plus my serial patch. -# If you lack quadram, or want to disable LFN, just change _FS_TINY=1 _USE_LFN=0 -# -# If your board is a mega 2560 comment out the following two lines -BOARD = mega - -BOARD_SUB = mega.menu.cpu.atmega1280 -PROGRAMMER = arduino - -# ...and then uncomment out the following two lines -#BOARD_SUB = mega.menu.cpu.atmega2560 -#PROGRAMMER = wiring - -#BOARD = teensypp2 -#BOARD = teensy3 -#BOARD = teensy31 - -# set your Arduino tty port here -PORT = /dev/ttyUSB0 - -EXTRA_FLAGS = -D _USE_LFN=3 - -# change to 0 if you have quadram to take advantage of caching FAT -EXTRA_FLAGS += -D _FS_TINY=1 - - -EXTRA_FLAGS += -D _MAX_SS=512 - - -# Don't worry if you don't have external RAM, xmem2 detects this situation. -# You *WILL* be wanting to get some kind of external ram on your mega in order to -# do anything that is intense. -EXTRA_FLAGS += -D EXT_RAM_STACK=1 -EXTRA_FLAGS += -D EXT_RAM_HEAP=1 - - -# These are no longer needed for the demo to work. -# In the event you need more ram, uncomment these 3 lines. -#EXTRA_FLAGS += -D DISABLE_SERIAL1 -#EXTRA_FLAGS += -D DISABLE_SERIAL2 -#EXTRA_FLAGS += -D DISABLE_SERIAL3 - -# -# Advanced debug on Serial3 -# - -# uncomment the next two to enable debug on Serial3 -EXTRA_FLAGS += -D USB_HOST_SERIAL=Serial3 -#EXTRA_FLAGS += -D DEBUG_USB_HOST - -# The following are the libraries used. -LIB_DIRS += ../../ -LIB_DIRS += ../testusbhostFAT/xmem2 -LIB_DIRS += ../testusbhostFAT/generic_storage -LIB_DIRS += ../testusbhostFAT/RTClib -LIB_DIRS += $(ARD_HOME)/libraries/Wire -LIB_DIRS += $(ARD_HOME)/libraries/Wire/utility -LIB_DIRS += $(ARD_HOME)/hardware/arduino/$(BUILD_ARCH)/libraries/Wire -LIB_DIRS += $(ARD_HOME)/hardware/arduino/$(BUILD_ARCH)/libraries/Wire/utility -LIB_DIRS += $(ARD_HOME)/hardware/arduino/$(BUILD_ARCH)/libraries/SPI - -# And finally, the part that brings everything together for you. -include Arduino_Makefile_master/_Makefile.master diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/testusbhostFAT/README.md b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/testusbhostFAT/README.md deleted file mode 100644 index 0f2a734a65..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/testusbhostFAT/README.md +++ /dev/null @@ -1,29 +0,0 @@ -This small sketch tests the USB host shield mass storage library. - -__Note:__ This will not run a Arduino Uno due to the limited ram available in the ATmega328p. - -The Arduino Mega (ATmega1280) and the Arduino Mega 2560 (ATmega2560) are confirmed to work with this test code. - -To compile this example you will need the following libraries as well: - -* [xmem2](https://github.com/xxxajk/xmem2) -* [generic_storage FATfs](https://github.com/xxxajk/generic_storage) -* [RTClib](https://github.com/xxxajk/RTClib) - -The following shield is recommended for larger projects: . - -You may use the bundled [Makefile](Makefile) to compile the code instead of the Arduino IDE if you have problems or want a smaller binary. The master makefile is bundled as a submodule, but can also be downloaded manually at the following link: . - -To download the USB Host library and all the needed libraries for this test. - -Run the following command in a terminal application: - -``` -git clone --recursive https://github.com/felis/USB_Host_Shield_2.0 -``` - -If you want to update all the submodules run: - -``` -git submodule foreach --recursive git pull origin master -``` diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/testusbhostFAT/testusbhostFAT.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/testusbhostFAT/testusbhostFAT.ino deleted file mode 100644 index e8b9cd3592..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/testusbhostFAT/testusbhostFAT.ino +++ /dev/null @@ -1,736 +0,0 @@ -/* - * Mega + USB storage + optional DS1307 + optional expansion RAM + funky status LED, - * Includes interactive debug level setting, and supports hot-plug. - * - * IMPORTANT! PLEASE USE Arduino 1.0.5 or better! - * Older versions HAVE MAJOR BUGS AND WILL NOT WORK AT ALL! - * Use of gcc-avr and lib-c that is newer than the Arduino version is even better. - * If you experience random crashes, use make. - * The options that the IDE use can generate bad code and cause the AVR to crash. - * - * This sketch requires the following libraries: - * https://github.com/felis/USB_Host_Shield_2.0 Install as 'USB_Host_Shield_2_0' - * https://github.com/xxxajk/xmem2 Install as 'xmem', provides memory services. - * https://github.com/xxxajk/generic_storage provides access to FAT file system. - * https://github.com/xxxajk/RTClib provides access to DS1307, or fake clock. - * - * Optional, to use the Makefile (Recommended! See above!): - * https://github.com/xxxajk/Arduino_Makefile_master - * - */ - -///////////////////////////////////////////////////////////// -// Please Note: // -// This section is for info with the Arduino IDE ONLY. // -// Unfortunately due to short sightedness of the Arduino // -// code team, that you must set the following in the // -// respective libraries. // -// Changing them here will have _NO_ effect! // -///////////////////////////////////////////////////////////// - -// Uncomment to enable debugging -//#define DEBUG_USB_HOST -// This is where stderr/USB debugging goes to -//#define USB_HOST_SERIAL Serial3 - -// If you have external memory, setting this to 0 enables FAT table caches. -// The 0 setting is recommended only if you have external memory. -//#define _FS_TINY 1 - -//#define _USE_LFN 3 -//#define _MAX_SS 512 - - -///////////////////////////////////////////////////////////// -// End of Arduino IDE specific information // -///////////////////////////////////////////////////////////// - -// You can set this to 0 if you are not using a USB hub. -// It will save a little bit of flash and RAM. -// Set to 1 if you want to use a hub. -#define WANT_HUB_TEST 1 - -// this is for XMEM2 -#define EXT_RAM_STACK 1 -#define EXT_RAM_HEAP 1 -#define LOAD_XMEM - -#if defined(CORE_TEENSY) && !defined(_AVR_) -#include -#include -#endif - -#if defined(__AVR__) -#include -#include -#elif defined(ARDUINO_ARCH_SAM) -#include -#endif - -#if WANT_HUB_TEST -#include -#endif -#include -#define LOAD_RTCLIB -#include -#include -#include -#include -#include -#include -#include -#if defined(__AVR__) -static FILE tty_stdio; -static FILE tty_stderr; -volatile uint32_t LEDnext_time; // fade timeout -volatile uint32_t HEAPnext_time; // when to print out next heap report -volatile int brightness = 0; // how bright the LED is -volatile int fadeAmount = 80; // how many points to fade the LED by -#endif - -USB Usb; - -volatile uint8_t current_state = 1; -volatile uint8_t last_state = 0; -volatile bool fatready = false; -volatile bool partsready = false; -volatile bool notified = false; -volatile bool runtest = false; -volatile bool usbon = false; -volatile uint32_t usbon_time; -volatile bool change = false; -volatile bool reportlvl = false; -int cpart = 0; -PCPartition *PT; - -#if WANT_HUB_TEST -#define MAX_HUBS 1 -USBHub *Hubs[MAX_HUBS]; -#endif - -static PFAT *Fats[_VOLUMES]; -static part_t parts[_VOLUMES]; -static storage_t sto[_VOLUMES]; - -/*make sure this is a power of two. */ -#define mbxs 128 -static uint8_t My_Buff_x[mbxs]; /* File read buffer */ - -#if defined(__AVR__) - -#define prescale1 ((1 << WGM12) | (1 << CS10)) -#define prescale8 ((1 << WGM12) | (1 << CS11)) -#define prescale64 ((1 << WGM12) | (1 << CS10) | (1 << CS11)) -#define prescale256 ((1 << WGM12) | (1 << CS12)) -#define prescale1024 ((1 << WGM12) | (1 << CS12) | (1 << CS10)) - -extern "C" { - extern unsigned int freeHeap(); -} -static int tty_stderr_putc(char c, FILE *t) { - USB_HOST_SERIAL.write(c); - return 0; -} - -static int __attribute__((unused)) tty_stderr_flush(FILE *t) { - USB_HOST_SERIAL.flush(); - return 0; -} - -static int tty_std_putc(char c, FILE *t) { - Serial.write(c); - return 0; -} - -static int tty_std_getc(FILE *t) { - while(!Serial.available()); - return Serial.read(); -} - -static int __attribute__((unused)) tty_std_flush(FILE *t) { - Serial.flush(); - return 0; -} - -#else -// Supposedly the DUE has stdio already pointing to serial... -#if !defined(ARDUINO_ARCH_SAM) -// But newlib needs this... -extern "C" { - int _write(int fd, const char *ptr, int len) { - int j; - for(j = 0; j < len; j++) { - if(fd == 1) - Serial.write(*ptr++); - else if(fd == 2) - USB_HOST_SERIAL.write(*ptr++); - } - return len; - } - - int _read(int fd, char *ptr, int len) { - if(len > 0 && fd == 0) { - while(!Serial.available()); - *ptr = Serial.read(); - return 1; - } - return 0; - } - -#include - - int _fstat(int fd, struct stat *st) { - memset(st, 0, sizeof (*st)); - st->st_mode = S_IFCHR; - st->st_blksize = 1024; - return 0; - } - - int _isatty(int fd) { - return (fd < 3) ? 1 : 0; - } -} -#endif // !defined(ARDUINO_ARCH_SAM) -#endif - -void setup() { - bool serr = false; - for(int i = 0; i < _VOLUMES; i++) { - Fats[i] = NULL; - sto[i].private_data = new pvt_t; - ((pvt_t *)sto[i].private_data)->B = 255; // impossible - } - // Set this to higher values to enable more debug information - // minimum 0x00, maximum 0xff - UsbDEBUGlvl = 0x81; - -#if !defined(CORE_TEENSY) && defined(__AVR__) - // make LED pin as an output: - pinMode(LED_BUILTIN, OUTPUT); - pinMode(2, OUTPUT); - // Ensure TX is off - _SFR_BYTE(UCSR0B) &= ~_BV(TXEN0); - // Initialize 'debug' serial port - USB_HOST_SERIAL.begin(115200); - // Do not start primary Serial port if already started. - if(bit_is_clear(UCSR0B, TXEN0)) { - Serial.begin(115200); - serr = true; - } - - - // Blink LED - delay(500); - analogWrite(LED_BUILTIN, 255); - delay(500); - analogWrite(LED_BUILTIN, 0); - delay(500); -#else - while(!Serial); - Serial.begin(115200); // On the Teensy 3.x we get a delay at least! -#endif -#if defined(__AVR__) - // Set up stdio/stderr - tty_stdio.put = tty_std_putc; - tty_stdio.get = tty_std_getc; - tty_stdio.flags = _FDEV_SETUP_RW; - tty_stdio.udata = 0; - - tty_stderr.put = tty_stderr_putc; - tty_stderr.get = NULL; - tty_stderr.flags = _FDEV_SETUP_WRITE; - tty_stderr.udata = 0; - - stdout = &tty_stdio; - stdin = &tty_stdio; - stderr = &tty_stderr; -#endif - printf_P(PSTR("\r\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nStart\r\n")); - printf_P(PSTR("Current UsbDEBUGlvl %02x\r\n"), UsbDEBUGlvl); - printf_P(PSTR("'+' and '-' increase/decrease by 0x01\r\n")); - printf_P(PSTR("'.' and ',' increase/decrease by 0x10\r\n")); - printf_P(PSTR("'t' will run a 10MB write/read test and print out the time it took.\r\n")); - printf_P(PSTR("'e' will toggle vbus off for a few moments.\r\n\r\n")); - printf_P(PSTR("Long filename support: " -#if _USE_LFN - "Enabled" -#else - "Disabled" -#endif - "\r\n")); - if(serr) { - fprintf_P(stderr, PSTR("\r\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nStart\r\n")); - fprintf_P(stderr, PSTR("Current UsbDEBUGlvl %02x\r\n"), UsbDEBUGlvl); - fprintf_P(stderr, PSTR("Long filename support: " -#if _USE_LFN - "Enabled" -#else - "Disabled" -#endif - "\r\n")); - } - -#if !defined(CORE_TEENSY) && defined(__AVR__) - analogWrite(LED_BUILTIN, 255); - delay(500); - analogWrite(LED_BUILTIN, 0); - delay(500); - analogWrite(LED_BUILTIN, 255); - delay(500); - analogWrite(LED_BUILTIN, 0); - delay(500); - analogWrite(LED_BUILTIN, 255); - delay(500); - analogWrite(LED_BUILTIN, 0); - delay(500); - - LEDnext_time = millis() + 1; -#if EXT_RAM - printf_P(PSTR("Total EXT RAM banks %i\r\n"), xmem::getTotalBanks()); -#endif - printf_P(PSTR("Available heap: %u Bytes\r\n"), freeHeap()); - printf_P(PSTR("SP %x\r\n"), (uint8_t *)(SP)); -#endif - - // Even though I'm not going to actually be deleting, - // I want to be able to have slightly more control. - // Besides, it is easier to initialize stuff... -#if WANT_HUB_TEST - for(int i = 0; i < MAX_HUBS; i++) { - Hubs[i] = new USBHub(&Usb); -#if defined(__AVR__) - printf_P(PSTR("Available heap: %u Bytes\r\n"), freeHeap()); -#endif - } -#endif - // Initialize generic storage. This must be done before USB starts. - Init_Generic_Storage(); - - while(Usb.Init(1000) == -1) { - printf_P(PSTR("No USB HOST Shield?\r\n")); - Notify(PSTR("OSC did not start."), 0x40); - } - -#if !defined(CORE_TEENSY) && defined(__AVR__) - cli(); - TCCR3A = 0; - TCCR3B = 0; - // (0.01/(1/((16 *(10^6)) / 8))) - 1 = 19999 - OCR3A = 19999; - TCCR3B |= prescale8; - TIMSK3 |= (1 << OCIE1A); - sei(); - - HEAPnext_time = millis() + 10000; -#endif -#if defined(__AVR__) - HEAPnext_time = millis() + 10000; -#endif -} - -void serialEvent() { - // Adjust UsbDEBUGlvl level on-the-fly. - // + to increase, - to decrease, * to display current level. - // . to increase by 16, , to decrease by 16 - // e to flick VBUS - // * to report debug level - if(Serial.available()) { - int inByte = Serial.read(); - switch(inByte) { - case '+': - if(UsbDEBUGlvl < 0xff) UsbDEBUGlvl++; - reportlvl = true; - break; - case '-': - if(UsbDEBUGlvl > 0x00) UsbDEBUGlvl--; - reportlvl = true; - break; - case '.': - if(UsbDEBUGlvl < 0xf0) UsbDEBUGlvl += 16; - reportlvl = true; - break; - case ',': - if(UsbDEBUGlvl > 0x0f) UsbDEBUGlvl -= 16; - reportlvl = true; - break; - case '*': - reportlvl = true; - break; - case 't': - runtest = true; - break; - case 'e': - change = true; - usbon = false; - break; - } - } -} - -#if !defined(CORE_TEENSY) && defined(__AVR__) -// ALL teensy versions LACK PWM ON LED - -ISR(TIMER3_COMPA_vect) { - if((long)(millis() - LEDnext_time) >= 0L) { - LEDnext_time = millis() + 30; - - // set the brightness of LED - analogWrite(LED_BUILTIN, brightness); - - // change the brightness for next time through the loop: - brightness = brightness + fadeAmount; - - // reverse the direction of the fading at the ends of the fade: - if(brightness <= 0) { - brightness = 0; - fadeAmount = -fadeAmount; - } - if(brightness >= 255) { - brightness = 255; - fadeAmount = -fadeAmount; - } - } -} -#endif - -bool isfat(uint8_t t) { - return (t == 0x01 || t == 0x04 || t == 0x06 || t == 0x0b || t == 0x0c || t == 0x0e || t == 0x1); -} - -void die(FRESULT rc) { - printf_P(PSTR("Failed with rc=%u.\r\n"), rc); - //for (;;); -} - -void loop() { - FIL My_File_Object_x; /* File object */ - -#if defined(__AVR__) - // Print a heap status report about every 10 seconds. - if((long)(millis() - HEAPnext_time) >= 0L) { - if(UsbDEBUGlvl > 0x50) { - printf_P(PSTR("Available heap: %u Bytes\r\n"), freeHeap()); - } - HEAPnext_time = millis() + 10000; - } - TCCR3B = 0; -#endif -#if defined(CORE_TEENSY) - // Teensy suffers here, oh well... - serialEvent(); -#endif - // Horrid! This sort of thing really belongs in an ISR, not here! - // We also will be needing to test each hub port, we don't do this yet! - if(!change && !usbon && (long)(millis() - usbon_time) >= 0L) { - change = true; - usbon = true; - } - - if(change) { - change = false; - if(usbon) { - Usb.vbusPower(vbus_on); - printf_P(PSTR("VBUS on\r\n")); - } else { - Usb.vbusPower(vbus_off); - usbon_time = millis() + 2000; - } - } - Usb.Task(); - current_state = Usb.getUsbTaskState(); - if(current_state != last_state) { - if(UsbDEBUGlvl > 0x50) - printf_P(PSTR("USB state = %x\r\n"), current_state); -#if !defined(CORE_TEENSY) && defined(__AVR__) - if(current_state == USB_STATE_RUNNING) { - fadeAmount = 30; - } -#endif - if(current_state == USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE) { -#if !defined(CORE_TEENSY) && defined(__AVR__) - fadeAmount = 80; -#endif - partsready = false; - for(int i = 0; i < cpart; i++) { - if(Fats[i] != NULL) - delete Fats[i]; - Fats[i] = NULL; - } - fatready = false; - notified = false; - cpart = 0; - } - last_state = current_state; - } - - // only do any of this if usb is on - if(usbon) { - if(partsready && !fatready) { - if(cpart > 0) fatready = true; - } - // This is horrible, and needs to be moved elsewhere! - for(int B = 0; B < MAX_USB_MS_DRIVERS; B++) { - if((!partsready) && (UHS_USB_BulkOnly[B]->GetAddress())) { - - // Build a list. - int ML = UHS_USB_BulkOnly[B]->GetbMaxLUN(); - //printf("MAXLUN = %i\r\n", ML); - ML++; - for(int i = 0; i < ML; i++) { - if(UHS_USB_BulkOnly[B]->LUNIsGood(i)) { - partsready = true; - ((pvt_t *)(sto[i].private_data))->lun = i; - ((pvt_t *)(sto[i].private_data))->B = B; - sto[i].Reads = *UHS_USB_BulkOnly_Read; - sto[i].Writes = *UHS_USB_BulkOnly_Write; - sto[i].Status = *UHS_USB_BulkOnly_Status; - sto[i].Initialize = *UHS_USB_BulkOnly_Initialize; - sto[i].Commit = *UHS_USB_BulkOnly_Commit; - sto[i].TotalSectors = UHS_USB_BulkOnly[B]->GetCapacity(i); - sto[i].SectorSize = UHS_USB_BulkOnly[B]->GetSectorSize(i); - printf_P(PSTR("LUN:\t\t%u\r\n"), i); - printf_P(PSTR("Total Sectors:\t%08lx\t%lu\r\n"), sto[i].TotalSectors, sto[i].TotalSectors); - printf_P(PSTR("Sector Size:\t%04x\t\t%u\r\n"), sto[i].SectorSize, sto[i].SectorSize); - // get the partition data... - PT = new PCPartition; - - if(!PT->Init(&sto[i])) { - part_t *apart; - for(int j = 0; j < 4; j++) { - apart = PT->GetPart(j); - if(apart != NULL && apart->type != 0x00) { - memcpy(&(parts[cpart]), apart, sizeof (part_t)); - printf_P(PSTR("Partition %u type %#02x\r\n"), j, parts[cpart].type); - // for now - if(isfat(parts[cpart].type)) { - Fats[cpart] = new PFAT(&sto[i], cpart, parts[cpart].firstSector); - //int r = Fats[cpart]->Good(); - if(Fats[cpart]->MountStatus()) { - delete Fats[cpart]; - Fats[cpart] = NULL; - } else cpart++; - } - } - } - } else { - // try superblock - Fats[cpart] = new PFAT(&sto[i], cpart, 0); - //int r = Fats[cpart]->Good(); - if(Fats[cpart]->MountStatus()) { - //printf_P(PSTR("Superblock error %x\r\n"), r); - delete Fats[cpart]; - Fats[cpart] = NULL; - } else cpart++; - - } - delete PT; - } else { - sto[i].Writes = NULL; - sto[i].Reads = NULL; - sto[i].Initialize = NULL; - sto[i].TotalSectors = 0UL; - sto[i].SectorSize = 0; - } - } - - } - } - - if(fatready) { - if(Fats[0] != NULL) { - struct Pvt * p; - p = ((struct Pvt *)(Fats[0]->storage->private_data)); - if(!UHS_USB_BulkOnly[p->B]->LUNIsGood(p->lun)) { - // media change -#if !defined(CORE_TEENSY) && defined(__AVR__) - fadeAmount = 80; -#endif - partsready = false; - for(int i = 0; i < cpart; i++) { - if(Fats[i] != NULL) - delete Fats[i]; - Fats[cpart] = NULL; - } - fatready = false; - notified = false; - cpart = 0; - } - - } - } - if(fatready) { - FRESULT rc; /* Result code */ - UINT bw, br, i; - if(!notified) { -#if !defined(CORE_TEENSY) && defined(__AVR__) - fadeAmount = 5; -#endif - notified = true; - FATFS *fs = NULL; - for(int zz = 0; zz < _VOLUMES; zz++) { - if(Fats[zz]->volmap == 0) fs = Fats[zz]->ffs; - } - printf_P(PSTR("\r\nOpen an existing file (message.txt).\r\n")); - rc = f_open(&My_File_Object_x, "0:/MESSAGE.TXT", FA_READ); - if(rc) printf_P(PSTR("Error %i, message.txt not found.\r\n"), rc); - else { - printf_P(PSTR("\r\nType the file content.\r\n")); - for(;;) { - rc = f_read(&My_File_Object_x, My_Buff_x, mbxs, &br); /* Read a chunk of file */ - if(rc || !br) break; /* Error or end of file */ - for(i = 0; i < br; i++) { - /* Type the data */ - if(My_Buff_x[i] == '\n') - Serial.write('\r'); - if(My_Buff_x[i] != '\r') - Serial.write(My_Buff_x[i]); - Serial.flush(); - } - } - if(rc) { - f_close(&My_File_Object_x); - goto out; - } - - printf_P(PSTR("\r\nClose the file.\r\n")); - rc = f_close(&My_File_Object_x); - if(rc) goto out; - } - printf_P(PSTR("\r\nCreate a new file (hello.txt).\r\n")); - rc = f_open(&My_File_Object_x, "0:/Hello.TxT", FA_WRITE | FA_CREATE_ALWAYS); - if(rc) { - die(rc); - goto outdir; - } - printf_P(PSTR("\r\nWrite a text data. (Hello world!)\r\n")); - rc = f_write(&My_File_Object_x, "Hello world!\r\n", 14, &bw); - if(rc) { - goto out; - } - printf_P(PSTR("%u bytes written.\r\n"), bw); - - printf_P(PSTR("\r\nClose the file.\r\n")); - rc = f_close(&My_File_Object_x); - if(rc) { - die(rc); - goto out; - } -outdir:{ -#if _USE_LFN - char lfn[_MAX_LFN + 1]; - FILINFO My_File_Info_Object_x; /* File information object */ - My_File_Info_Object_x.lfname = lfn; -#endif - DIR My_Dir_Object_x; /* Directory object */ - printf_P(PSTR("\r\nOpen root directory.\r\n")); - rc = f_opendir(&My_Dir_Object_x, "0:/"); - if(rc) { - die(rc); - goto out; - } - - printf_P(PSTR("\r\nDirectory listing...\r\n")); -#if defined(__AVR__) - printf_P(PSTR("Available heap: %u Bytes\r\n"), freeHeap()); -#endif - for(;;) { -#if _USE_LFN - My_File_Info_Object_x.lfsize = _MAX_LFN; -#endif - - rc = f_readdir(&My_Dir_Object_x, &My_File_Info_Object_x); /* Read a directory item */ - if(rc || !My_File_Info_Object_x.fname[0]) break; /* Error or end of dir */ - - if(My_File_Info_Object_x.fattrib & AM_DIR) { - Serial.write('d'); - } else { - Serial.write('-'); - } - Serial.write('r'); - - if(My_File_Info_Object_x.fattrib & AM_RDO) { - Serial.write('-'); - } else { - Serial.write('w'); - } - if(My_File_Info_Object_x.fattrib & AM_HID) { - Serial.write('h'); - } else { - Serial.write('-'); - } - - if(My_File_Info_Object_x.fattrib & AM_SYS) { - Serial.write('s'); - } else { - Serial.write('-'); - } - - if(My_File_Info_Object_x.fattrib & AM_ARC) { - Serial.write('a'); - } else { - Serial.write('-'); - } - -#if _USE_LFN - if(*My_File_Info_Object_x.lfname) - printf_P(PSTR(" %8lu %s (%s)\r\n"), My_File_Info_Object_x.fsize, My_File_Info_Object_x.fname, My_File_Info_Object_x.lfname); - else -#endif - printf_P(PSTR(" %8lu %s\r\n"), My_File_Info_Object_x.fsize, &(My_File_Info_Object_x.fname[0])); - } - } -out: - if(rc) die(rc); - - DISK_IOCTL(fs->drv, CTRL_COMMIT, 0); - printf_P(PSTR("\r\nTest completed.\r\n")); - - } - - if(runtest) { - ULONG ii, wt, rt, start, end; - FATFS *fs = NULL; - for(int zz = 0; zz < _VOLUMES; zz++) { - if(Fats[zz]->volmap == 0) fs = Fats[zz]->ffs; - } - runtest = false; - f_unlink("0:/10MB.bin"); - printf_P(PSTR("\r\nCreate a new 10MB test file (10MB.bin).\r\n")); - rc = f_open(&My_File_Object_x, "0:/10MB.bin", FA_WRITE | FA_CREATE_ALWAYS); - if(rc) goto failed; - for(bw = 0; bw < mbxs; bw++) My_Buff_x[bw] = bw & 0xff; - fflush(stdout); - start = millis(); - while(start == millis()); - for(ii = 10485760LU / mbxs; ii > 0LU; ii--) { - rc = f_write(&My_File_Object_x, My_Buff_x, mbxs, &bw); - if(rc || !bw) goto failed; - } - rc = f_close(&My_File_Object_x); - if(rc) goto failed; - end = millis(); - wt = (end - start) - 1; - printf_P(PSTR("Time to write 10485760 bytes: %lu ms (%lu sec) \r\n"), wt, (500 + wt) / 1000UL); - rc = f_open(&My_File_Object_x, "0:/10MB.bin", FA_READ); - fflush(stdout); - start = millis(); - while(start == millis()); - if(rc) goto failed; - for(;;) { - rc = f_read(&My_File_Object_x, My_Buff_x, mbxs, &bw); /* Read a chunk of file */ - if(rc || !bw) break; /* Error or end of file */ - } - end = millis(); - if(rc) goto failed; - rc = f_close(&My_File_Object_x); - if(rc) goto failed; - rt = (end - start) - 1; - printf_P(PSTR("Time to read 10485760 bytes: %lu ms (%lu sec)\r\nDelete test file\r\n"), rt, (500 + rt) / 1000UL); -failed: - if(rc) die(rc); - DISK_IOCTL(fs->drv, CTRL_COMMIT, 0); - printf_P(PSTR("10MB timing test finished.\r\n")); - } - } - } -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/gpl2.txt b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/gpl2.txt deleted file mode 100644 index 5b6e7c66c2..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/gpl2.txt +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - 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, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hexdump.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hexdump.h deleted file mode 100644 index ffa7248b7d..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hexdump.h +++ /dev/null @@ -1,61 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ -#if !defined(_usb_h_) || defined(__HEXDUMP_H__) -#error "Never include hexdump.h directly; include Usb.h instead" -#else -#define __HEXDUMP_H__ - -extern int UsbDEBUGlvl; - -template -class HexDumper : public BASE_CLASS { - uint8_t byteCount; - OFFSET_TYPE byteTotal; - -public: - - HexDumper() : byteCount(0), byteTotal(0) { - }; - - void Initialize() { - byteCount = 0; - byteTotal = 0; - }; - - void Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset); -}; - -template -void HexDumper::Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset) { - if(UsbDEBUGlvl >= 0x80) { // Fully bypass this block of code if we do not debug. - for(LEN_TYPE j = 0; j < len; j++, byteCount++, byteTotal++) { - if(!byteCount) { - PrintHex (byteTotal, 0x80); - E_Notify(PSTR(": "), 0x80); - } - PrintHex (pbuf[j], 0x80); - E_Notify(PSTR(" "), 0x80); - - if(byteCount == 15) { - E_Notify(PSTR("\r\n"), 0x80); - byteCount = 0xFF; - } - } - } -} - -#endif // __HEXDUMP_H__ diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hid.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hid.cpp deleted file mode 100644 index e4c7721a3e..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hid.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ - -#include "hid.h" - -//get HID report descriptor - -/* WRONG! Endpoint is _ALWAYS_ ZERO for HID! We want the _INTERFACE_ value here! -uint8_t HID::GetReportDescr(uint8_t ep, USBReadParser *parser) { - const uint8_t constBufLen = 64; - uint8_t buf[constBufLen]; - - uint8_t rcode = pUsb->ctrlReq(bAddress, ep, bmREQ_HID_REPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00, - HID_DESCRIPTOR_REPORT, 0x0000, 128, constBufLen, buf, (USBReadParser*)parser); - - //return ((rcode != hrSTALL) ? rcode : 0); - return rcode; -} - */ -uint8_t HID::GetReportDescr(uint16_t wIndex, USBReadParser *parser) { - const uint8_t constBufLen = 64; - uint8_t buf[constBufLen]; - - uint8_t rcode = pUsb->ctrlReq(bAddress, 0x00, bmREQ_HID_REPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00, - HID_DESCRIPTOR_REPORT, wIndex, 128, constBufLen, buf, (USBReadParser*)parser); - - //return ((rcode != hrSTALL) ? rcode : 0); - return rcode; -} - -//uint8_t HID::getHidDescr( uint8_t ep, uint16_t nbytes, uint8_t* dataptr ) -//{ -// return( pUsb->ctrlReq( bAddress, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, HID_DESCRIPTOR_HID, 0x0000, nbytes, dataptr )); -//} - -uint8_t HID::SetReport(uint8_t ep, uint8_t iface, uint8_t report_type, uint8_t report_id, uint16_t nbytes, uint8_t* dataptr) { - return ( pUsb->ctrlReq(bAddress, ep, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, report_id, report_type, iface, nbytes, nbytes, dataptr, NULL)); -} - -uint8_t HID::GetReport(uint8_t ep, uint8_t iface, uint8_t report_type, uint8_t report_id, uint16_t nbytes, uint8_t* dataptr) { - return ( pUsb->ctrlReq(bAddress, ep, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, report_id, report_type, iface, nbytes, nbytes, dataptr, NULL)); -} - -uint8_t HID::GetIdle(uint8_t iface, uint8_t reportID, uint8_t* dataptr) { - return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HID_IN, HID_REQUEST_GET_IDLE, reportID, 0, iface, 0x0001, 0x0001, dataptr, NULL)); -} - -uint8_t HID::SetIdle(uint8_t iface, uint8_t reportID, uint8_t duration) { - return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HID_OUT, HID_REQUEST_SET_IDLE, reportID, duration, iface, 0x0000, 0x0000, NULL, NULL)); -} - -uint8_t HID::SetProtocol(uint8_t iface, uint8_t protocol) { - return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HID_OUT, HID_REQUEST_SET_PROTOCOL, protocol, 0x00, iface, 0x0000, 0x0000, NULL, NULL)); -} - -uint8_t HID::GetProtocol(uint8_t iface, uint8_t* dataptr) { - return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HID_IN, HID_REQUEST_GET_PROTOCOL, 0x00, 0x00, iface, 0x0001, 0x0001, dataptr, NULL)); -} - -void HID::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) { - Notify(PSTR("Endpoint descriptor:"), 0x80); - Notify(PSTR("\r\nLength:\t\t"), 0x80); - D_PrintHex (ep_ptr->bLength, 0x80); - Notify(PSTR("\r\nType:\t\t"), 0x80); - D_PrintHex (ep_ptr->bDescriptorType, 0x80); - Notify(PSTR("\r\nAddress:\t"), 0x80); - D_PrintHex (ep_ptr->bEndpointAddress, 0x80); - Notify(PSTR("\r\nAttributes:\t"), 0x80); - D_PrintHex (ep_ptr->bmAttributes, 0x80); - Notify(PSTR("\r\nMaxPktSize:\t"), 0x80); - D_PrintHex (ep_ptr->wMaxPacketSize, 0x80); - Notify(PSTR("\r\nPoll Intrv:\t"), 0x80); - D_PrintHex (ep_ptr->bInterval, 0x80); -} - -void HID::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc) { - Notify(PSTR("\r\n\r\nHID Descriptor:\r\n"), 0x80); - Notify(PSTR("bDescLength:\t\t"), 0x80); - D_PrintHex (pDesc->bLength, 0x80); - - Notify(PSTR("\r\nbDescriptorType:\t"), 0x80); - D_PrintHex (pDesc->bDescriptorType, 0x80); - - Notify(PSTR("\r\nbcdHID:\t\t\t"), 0x80); - D_PrintHex (pDesc->bcdHID, 0x80); - - Notify(PSTR("\r\nbCountryCode:\t\t"), 0x80); - D_PrintHex (pDesc->bCountryCode, 0x80); - - Notify(PSTR("\r\nbNumDescriptors:\t"), 0x80); - D_PrintHex (pDesc->bNumDescriptors, 0x80); - - Notify(PSTR("\r\nbDescrType:\t\t"), 0x80); - D_PrintHex (pDesc->bDescrType, 0x80); - - Notify(PSTR("\r\nwDescriptorLength:\t"), 0x80); - D_PrintHex (pDesc->wDescriptorLength, 0x80); -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hid.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hid.h deleted file mode 100644 index 72942ebc92..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hid.h +++ /dev/null @@ -1,188 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ -#if !defined(__HID_H__) -#define __HID_H__ - -#include "Usb.h" -#include "hidusagestr.h" - -#define MAX_REPORT_PARSERS 2 -#define HID_MAX_HID_CLASS_DESCRIPTORS 5 - -#define DATA_SIZE_MASK 0x03 -#define TYPE_MASK 0x0C -#define TAG_MASK 0xF0 - -#define DATA_SIZE_0 0x00 -#define DATA_SIZE_1 0x01 -#define DATA_SIZE_2 0x02 -#define DATA_SIZE_4 0x03 - -#define TYPE_MAIN 0x00 -#define TYPE_GLOBAL 0x04 -#define TYPE_LOCAL 0x08 - -#define TAG_MAIN_INPUT 0x80 -#define TAG_MAIN_OUTPUT 0x90 -#define TAG_MAIN_COLLECTION 0xA0 -#define TAG_MAIN_FEATURE 0xB0 -#define TAG_MAIN_ENDCOLLECTION 0xC0 - -#define TAG_GLOBAL_USAGEPAGE 0x00 -#define TAG_GLOBAL_LOGICALMIN 0x10 -#define TAG_GLOBAL_LOGICALMAX 0x20 -#define TAG_GLOBAL_PHYSMIN 0x30 -#define TAG_GLOBAL_PHYSMAX 0x40 -#define TAG_GLOBAL_UNITEXP 0x50 -#define TAG_GLOBAL_UNIT 0x60 -#define TAG_GLOBAL_REPORTSIZE 0x70 -#define TAG_GLOBAL_REPORTID 0x80 -#define TAG_GLOBAL_REPORTCOUNT 0x90 -#define TAG_GLOBAL_PUSH 0xA0 -#define TAG_GLOBAL_POP 0xB0 - -#define TAG_LOCAL_USAGE 0x00 -#define TAG_LOCAL_USAGEMIN 0x10 -#define TAG_LOCAL_USAGEMAX 0x20 - -/* HID requests */ -#define bmREQ_HID_OUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE -#define bmREQ_HID_IN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE -#define bmREQ_HID_REPORT USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_INTERFACE - -/* HID constants. Not part of chapter 9 */ -/* Class-Specific Requests */ -#define HID_REQUEST_GET_REPORT 0x01 -#define HID_REQUEST_GET_IDLE 0x02 -#define HID_REQUEST_GET_PROTOCOL 0x03 -#define HID_REQUEST_SET_REPORT 0x09 -#define HID_REQUEST_SET_IDLE 0x0A -#define HID_REQUEST_SET_PROTOCOL 0x0B - -/* Class Descriptor Types */ -#define HID_DESCRIPTOR_HID 0x21 -#define HID_DESCRIPTOR_REPORT 0x22 -#define HID_DESRIPTOR_PHY 0x23 - -/* Protocol Selection */ -#define HID_BOOT_PROTOCOL 0x00 -#define HID_RPT_PROTOCOL 0x01 - -/* HID Interface Class Code */ -#define HID_INTF 0x03 - -/* HID Interface Class SubClass Codes */ -#define HID_BOOT_INTF_SUBCLASS 0x01 - -/* HID Interface Class Protocol Codes */ -#define HID_PROTOCOL_NONE 0x00 -#define HID_PROTOCOL_KEYBOARD 0x01 -#define HID_PROTOCOL_MOUSE 0x02 - -#define HID_ITEM_TYPE_MAIN 0 -#define HID_ITEM_TYPE_GLOBAL 1 -#define HID_ITEM_TYPE_LOCAL 2 -#define HID_ITEM_TYPE_RESERVED 3 - -#define HID_LONG_ITEM_PREFIX 0xfe // Long item prefix value - -#define bmHID_MAIN_ITEM_TAG 0xfc // Main item tag mask - -#define bmHID_MAIN_ITEM_INPUT 0x80 // Main item Input tag value -#define bmHID_MAIN_ITEM_OUTPUT 0x90 // Main item Output tag value -#define bmHID_MAIN_ITEM_FEATURE 0xb0 // Main item Feature tag value -#define bmHID_MAIN_ITEM_COLLECTION 0xa0 // Main item Collection tag value -#define bmHID_MAIN_ITEM_END_COLLECTION 0xce // Main item End Collection tag value - -#define HID_MAIN_ITEM_COLLECTION_PHYSICAL 0 -#define HID_MAIN_ITEM_COLLECTION_APPLICATION 1 -#define HID_MAIN_ITEM_COLLECTION_LOGICAL 2 -#define HID_MAIN_ITEM_COLLECTION_REPORT 3 -#define HID_MAIN_ITEM_COLLECTION_NAMED_ARRAY 4 -#define HID_MAIN_ITEM_COLLECTION_USAGE_SWITCH 5 -#define HID_MAIN_ITEM_COLLECTION_USAGE_MODIFIER 6 - -struct HidItemPrefix { - uint8_t bSize : 2; - uint8_t bType : 2; - uint8_t bTag : 4; -}; - -struct MainItemIOFeature { - uint8_t bmIsConstantOrData : 1; - uint8_t bmIsArrayOrVariable : 1; - uint8_t bmIsRelativeOrAbsolute : 1; - uint8_t bmIsWrapOrNoWrap : 1; - uint8_t bmIsNonLonearOrLinear : 1; - uint8_t bmIsNoPreferedOrPrefered : 1; - uint8_t bmIsNullOrNoNull : 1; - uint8_t bmIsVolatileOrNonVolatile : 1; -}; - -class HID; - -class HIDReportParser { -public: - virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) = 0; -}; - -class HID : public USBDeviceConfig, public UsbConfigXtracter { -protected: - USB *pUsb; // USB class instance pointer - uint8_t bAddress; // address - -protected: - static const uint8_t epInterruptInIndex = 1; // InterruptIN endpoint index - static const uint8_t epInterruptOutIndex = 2; // InterruptOUT endpoint index - - static const uint8_t maxHidInterfaces = 3; - static const uint8_t maxEpPerInterface = 2; - static const uint8_t totalEndpoints = (maxHidInterfaces * maxEpPerInterface + 1); - - void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); - void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc); - - virtual HIDReportParser* GetReportParser(uint8_t id) { - return NULL; - }; - -public: - - HID(USB *pusb) : pUsb(pusb) { - }; - - const USB* GetUsb() { - return pUsb; - }; - - virtual bool SetReportParser(uint8_t id, HIDReportParser *prs) { - return false; - }; - - uint8_t SetProtocol(uint8_t iface, uint8_t protocol); - uint8_t GetProtocol(uint8_t iface, uint8_t* dataptr); - uint8_t GetIdle(uint8_t iface, uint8_t reportID, uint8_t* dataptr); - uint8_t SetIdle(uint8_t iface, uint8_t reportID, uint8_t duration); - - uint8_t GetReportDescr(uint16_t wIndex, USBReadParser *parser = NULL); - - uint8_t GetHidDescr(uint8_t ep, uint16_t nbytes, uint8_t* dataptr); - uint8_t GetReport(uint8_t ep, uint8_t iface, uint8_t report_type, uint8_t report_id, uint16_t nbytes, uint8_t* dataptr); - uint8_t SetReport(uint8_t ep, uint8_t iface, uint8_t report_type, uint8_t report_id, uint16_t nbytes, uint8_t* dataptr); -}; - -#endif // __HID_H__ diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidboot.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidboot.cpp deleted file mode 100644 index 280b2f9788..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidboot.cpp +++ /dev/null @@ -1,201 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ -#include "hidboot.h" - -void MouseReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) { - MOUSEINFO *pmi = (MOUSEINFO*)buf; - // Future: - // bool event; - -#if 0 - if (prevState.mouseInfo.bmLeftButton == 0 && pmi->bmLeftButton == 1) - OnLeftButtonDown(pmi); - - if (prevState.mouseInfo.bmLeftButton == 1 && pmi->bmLeftButton == 0) - OnLeftButtonUp(pmi); - - if (prevState.mouseInfo.bmRightButton == 0 && pmi->bmRightButton == 1) - OnRightButtonDown(pmi); - - if (prevState.mouseInfo.bmRightButton == 1 && pmi->bmRightButton == 0) - OnRightButtonUp(pmi); - - if (prevState.mouseInfo.bmMiddleButton == 0 && pmi->bmMiddleButton == 1) - OnMiddleButtonDown(pmi); - - if (prevState.mouseInfo.bmMiddleButton == 1 && pmi->bmMiddleButton == 0) - OnMiddleButtonUp(pmi); - - if (prevState.mouseInfo.dX != pmi->dX || prevState.mouseInfo.dY != pmi->dY) - OnMouseMove(pmi); - - if (len > sizeof (MOUSEINFO)) - for (uint8_t i = 0; ibmLeftButton ) { - if(pmi->bmLeftButton) { - OnLeftButtonDown(pmi); - } else { - OnLeftButtonUp(pmi); - } - // Future: - // event = true; - } - - if(prevState.mouseInfo.bmRightButton != pmi->bmRightButton) { - if(pmi->bmRightButton) { - OnRightButtonDown(pmi); - } else { - OnRightButtonUp(pmi); - } - // Future: - // event = true; - } - - if(prevState.mouseInfo.bmMiddleButton != pmi->bmMiddleButton) { - if(pmi->bmMiddleButton) { - OnMiddleButtonDown(pmi); - } else { - OnMiddleButtonUp(pmi); - } - // Future: - // event = true; - } - - // - // Scroll wheel(s), are not part of the spec, but we could support it. - // Logitech wireless keyboard and mouse combo reports scroll wheel in byte 4 - // We wouldn't even need to save this information. - //if(len > 3) { - //} - // - - // Mice only report motion when they actually move! - // Why not just pass the x/y values to simplify things?? - if(pmi->dX || pmi->dY) { - OnMouseMove(pmi); - // Future: - // event = true; - } - - // - // Future: - // Provide a callback that operates on the gathered events from above. - // - // if(event) OnMouse(); - // - - // Only the first byte matters (buttons). We do NOT need to save position info. - prevState.bInfo[0] = buf[0]; -#endif - -}; - -void KeyboardReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) { - // On error - return - if (buf[2] == 1) - return; - - //KBDINFO *pki = (KBDINFO*)buf; - - // provide event for changed control key state - if (prevState.bInfo[0x00] != buf[0x00]) { - OnControlKeysChanged(prevState.bInfo[0x00], buf[0x00]); - } - - for (uint8_t i = 2; i < 8; i++) { - bool down = false; - bool up = false; - - for (uint8_t j = 2; j < 8; j++) { - if (buf[i] == prevState.bInfo[j] && buf[i] != 1) - down = true; - if (buf[j] == prevState.bInfo[i] && prevState.bInfo[i] != 1) - up = true; - } - if (!down) { - HandleLockingKeys(hid, buf[i]); - OnKeyDown(*buf, buf[i]); - } - if (!up) - OnKeyUp(prevState.bInfo[0], prevState.bInfo[i]); - } - for (uint8_t i = 0; i < 8; i++) - prevState.bInfo[i] = buf[i]; -}; - -const uint8_t KeyboardReportParser::numKeys[10] PROGMEM = {'!', '@', '#', '$', '%', '^', '&', '*', '(', ')'}; -const uint8_t KeyboardReportParser::symKeysUp[12] PROGMEM = {'_', '+', '{', '}', '|', '~', ':', '"', '~', '<', '>', '?'}; -const uint8_t KeyboardReportParser::symKeysLo[12] PROGMEM = {'-', '=', '[', ']', '\\', ' ', ';', '\'', '`', ',', '.', '/'}; -const uint8_t KeyboardReportParser::padKeys[5] PROGMEM = {'/', '*', '-', '+', 0x13}; - -uint8_t KeyboardReportParser::OemToAscii(uint8_t mod, uint8_t key) { - uint8_t shift = (mod & 0x22); - - // [a-z] - if (VALUE_WITHIN(key, 0x04, 0x1d)) { - // Upper case letters - if ((kbdLockingKeys.kbdLeds.bmCapsLock == 0 && shift) || - (kbdLockingKeys.kbdLeds.bmCapsLock == 1 && shift == 0)) - return (key - 4 + 'A'); - - // Lower case letters - else - return (key - 4 + 'a'); - }// Numbers - else if (VALUE_WITHIN(key, 0x1e, 0x27)) { - if (shift) - return ((uint8_t)pgm_read_byte(&getNumKeys()[key - 0x1e])); - else - return ((key == UHS_HID_BOOT_KEY_ZERO) ? '0' : key - 0x1e + '1'); - }// Keypad Numbers - else if(VALUE_WITHIN(key, 0x59, 0x61)) { - if(kbdLockingKeys.kbdLeds.bmNumLock == 1) - return (key - 0x59 + '1'); - } else if(VALUE_WITHIN(key, 0x2d, 0x38)) - return ((shift) ? (uint8_t)pgm_read_byte(&getSymKeysUp()[key - 0x2d]) : (uint8_t)pgm_read_byte(&getSymKeysLo()[key - 0x2d])); - else if(VALUE_WITHIN(key, 0x54, 0x58)) - return (uint8_t)pgm_read_byte(&getPadKeys()[key - 0x54]); - else { - switch(key) { - case UHS_HID_BOOT_KEY_SPACE: return (0x20); - case UHS_HID_BOOT_KEY_ENTER: return (0x13); - case UHS_HID_BOOT_KEY_ZERO2: return ((kbdLockingKeys.kbdLeds.bmNumLock == 1) ? '0': 0); - case UHS_HID_BOOT_KEY_PERIOD: return ((kbdLockingKeys.kbdLeds.bmNumLock == 1) ? '.': 0); - } - } - return ( 0); -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidboot.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidboot.h deleted file mode 100644 index fb63ec5e59..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidboot.h +++ /dev/null @@ -1,618 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ -#if !defined(__HIDBOOT_H__) -#define __HIDBOOT_H__ - -#include "hid.h" - -#define UHS_HID_BOOT_KEY_ZERO 0x27 -#define UHS_HID_BOOT_KEY_ENTER 0x28 -#define UHS_HID_BOOT_KEY_SPACE 0x2c -#define UHS_HID_BOOT_KEY_CAPS_LOCK 0x39 -#define UHS_HID_BOOT_KEY_SCROLL_LOCK 0x47 -#define UHS_HID_BOOT_KEY_NUM_LOCK 0x53 -#define UHS_HID_BOOT_KEY_ZERO2 0x62 -#define UHS_HID_BOOT_KEY_PERIOD 0x63 - -// Don't worry, GCC will optimize the result to a final value. -#define bitsEndpoints(p) ((((p) & HID_PROTOCOL_KEYBOARD)? 2 : 0) | (((p) & HID_PROTOCOL_MOUSE)? 1 : 0)) -#define totalEndpoints(p) ((bitsEndpoints(p) == 3) ? 3 : 2) -#define epMUL(p) ((((p) & HID_PROTOCOL_KEYBOARD)? 1 : 0) + (((p) & HID_PROTOCOL_MOUSE)? 1 : 0)) - -// Already defined in hid.h -// #define HID_MAX_HID_CLASS_DESCRIPTORS 5 - -struct MOUSEINFO { - - struct { - uint8_t bmLeftButton : 1; - uint8_t bmRightButton : 1; - uint8_t bmMiddleButton : 1; - uint8_t bmDummy : 5; - }; - int8_t dX; - int8_t dY; -}; - -class MouseReportParser : public HIDReportParser { - - union { - MOUSEINFO mouseInfo; - uint8_t bInfo[sizeof (MOUSEINFO)]; - } prevState; - -public: - void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); - -protected: - - virtual void OnMouseMove(MOUSEINFO *mi) { - }; - - virtual void OnLeftButtonUp(MOUSEINFO *mi) { - }; - - virtual void OnLeftButtonDown(MOUSEINFO *mi) { - }; - - virtual void OnRightButtonUp(MOUSEINFO *mi) { - }; - - virtual void OnRightButtonDown(MOUSEINFO *mi) { - }; - - virtual void OnMiddleButtonUp(MOUSEINFO *mi) { - }; - - virtual void OnMiddleButtonDown(MOUSEINFO *mi) { - }; -}; - -struct MODIFIERKEYS { - uint8_t bmLeftCtrl : 1; - uint8_t bmLeftShift : 1; - uint8_t bmLeftAlt : 1; - uint8_t bmLeftGUI : 1; - uint8_t bmRightCtrl : 1; - uint8_t bmRightShift : 1; - uint8_t bmRightAlt : 1; - uint8_t bmRightGUI : 1; -}; - -struct KBDINFO { - - struct { - uint8_t bmLeftCtrl : 1; - uint8_t bmLeftShift : 1; - uint8_t bmLeftAlt : 1; - uint8_t bmLeftGUI : 1; - uint8_t bmRightCtrl : 1; - uint8_t bmRightShift : 1; - uint8_t bmRightAlt : 1; - uint8_t bmRightGUI : 1; - }; - uint8_t bReserved; - uint8_t Keys[6]; -}; - -struct KBDLEDS { - uint8_t bmNumLock : 1; - uint8_t bmCapsLock : 1; - uint8_t bmScrollLock : 1; - uint8_t bmCompose : 1; - uint8_t bmKana : 1; - uint8_t bmReserved : 3; -}; - -class KeyboardReportParser : public HIDReportParser { - static const uint8_t numKeys[10]; - static const uint8_t symKeysUp[12]; - static const uint8_t symKeysLo[12]; - static const uint8_t padKeys[5]; - -protected: - - union { - KBDINFO kbdInfo; - uint8_t bInfo[sizeof (KBDINFO)]; - } prevState; - - union { - KBDLEDS kbdLeds; - uint8_t bLeds; - } kbdLockingKeys; - - uint8_t OemToAscii(uint8_t mod, uint8_t key); - -public: - - KeyboardReportParser() { - kbdLockingKeys.bLeds = 0; - }; - - void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); - -protected: - - virtual uint8_t HandleLockingKeys(HID* hid, uint8_t key) { - uint8_t old_keys = kbdLockingKeys.bLeds; - - switch(key) { - case UHS_HID_BOOT_KEY_NUM_LOCK: - kbdLockingKeys.kbdLeds.bmNumLock = ~kbdLockingKeys.kbdLeds.bmNumLock; - break; - case UHS_HID_BOOT_KEY_CAPS_LOCK: - kbdLockingKeys.kbdLeds.bmCapsLock = ~kbdLockingKeys.kbdLeds.bmCapsLock; - break; - case UHS_HID_BOOT_KEY_SCROLL_LOCK: - kbdLockingKeys.kbdLeds.bmScrollLock = ~kbdLockingKeys.kbdLeds.bmScrollLock; - break; - } - - if(old_keys != kbdLockingKeys.bLeds && hid) - return (hid->SetReport(0, 0/*hid->GetIface()*/, 2, 0, 1, &kbdLockingKeys.bLeds)); - - return 0; - }; - - virtual void OnControlKeysChanged(uint8_t before, uint8_t after) { - }; - - virtual void OnKeyDown(uint8_t mod, uint8_t key) { - }; - - virtual void OnKeyUp(uint8_t mod, uint8_t key) { - }; - - virtual const uint8_t *getNumKeys() { - return numKeys; - }; - - virtual const uint8_t *getSymKeysUp() { - return symKeysUp; - }; - - virtual const uint8_t *getSymKeysLo() { - return symKeysLo; - }; - - virtual const uint8_t *getPadKeys() { - return padKeys; - }; -}; - -template -class HIDBoot : public HID //public USBDeviceConfig, public UsbConfigXtracter -{ - EpInfo epInfo[totalEndpoints(BOOT_PROTOCOL)]; - HIDReportParser *pRptParser[epMUL(BOOT_PROTOCOL)]; - - uint8_t bConfNum; // configuration number - uint8_t bIfaceNum; // Interface Number - uint8_t bNumIface; // number of interfaces in the configuration - uint8_t bNumEP; // total number of EP in the configuration - uint32_t qNextPollTime; // next poll time - bool bPollEnable; // poll enable flag - uint8_t bInterval; // largest interval - - void Initialize(); - - virtual HIDReportParser* GetReportParser(uint8_t id) { - return pRptParser[id]; - }; - -public: - HIDBoot(USB *p); - - virtual bool SetReportParser(uint8_t id, HIDReportParser *prs) { - pRptParser[id] = prs; - return true; - }; - - // USBDeviceConfig implementation - uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); - uint8_t Release(); - uint8_t Poll(); - - virtual uint8_t GetAddress() { - return bAddress; - }; - - virtual bool isReady() { - return bPollEnable; - }; - - // UsbConfigXtracter implementation - // Method should be defined here if virtual. - virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); - - virtual bool DEVCLASSOK(uint8_t klass) { - return (klass == USB_CLASS_HID); - } - - virtual bool DEVSUBCLASSOK(uint8_t subklass) { - return (subklass == BOOT_PROTOCOL); - } -}; - -template -HIDBoot::HIDBoot(USB *p) : -HID(p), -qNextPollTime(0), -bPollEnable(false) { - Initialize(); - - for(int i = 0; i < epMUL(BOOT_PROTOCOL); i++) { - pRptParser[i] = NULL; - } - if(pUsb) - pUsb->RegisterDeviceClass(this); -} - -template -void HIDBoot::Initialize() { - for(int i = 0; i < totalEndpoints(BOOT_PROTOCOL); i++) { - epInfo[i].epAddr = 0; - epInfo[i].maxPktSize = (i) ? 0 : 8; - epInfo[i].epAttribs = 0; - epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; - } - bNumEP = 1; - bNumIface = 0; - bConfNum = 0; -} - -template -uint8_t HIDBoot::Init(uint8_t parent, uint8_t port, bool lowspeed) { - const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR); - - uint8_t buf[constBufSize]; - uint8_t rcode; - UsbDevice *p = NULL; - EpInfo *oldep_ptr = NULL; - uint8_t len = 0; - //uint16_t cd_len = 0; - - uint8_t num_of_conf; // number of configurations - //uint8_t num_of_intf; // number of interfaces - - AddressPool &addrPool = pUsb->GetAddressPool(); - - USBTRACE("BM Init\r\n"); - //USBTRACE2("totalEndpoints:", (uint8_t) (totalEndpoints(BOOT_PROTOCOL))); - //USBTRACE2("epMUL:", epMUL(BOOT_PROTOCOL)); - - if(bAddress) - return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; - - bInterval = 0; - // Get pointer to pseudo device with address 0 assigned - p = addrPool.GetUsbDevicePtr(0); - - if(!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - if(!p->epinfo) { - USBTRACE("epinfo\r\n"); - return USB_ERROR_EPINFO_IS_NULL; - } - - // Save old pointer to EP_RECORD of address 0 - oldep_ptr = p->epinfo; - - // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence - p->epinfo = epInfo; - - p->lowspeed = lowspeed; - - // Get device descriptor - rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*)buf); - - if(!rcode) - len = (buf[0] > constBufSize) ? constBufSize : buf[0]; - - if(rcode) { - // Restore p->epinfo - p->epinfo = oldep_ptr; - - goto FailGetDevDescr; - } - - // Restore p->epinfo - p->epinfo = oldep_ptr; - - // Allocate new address according to device class - bAddress = addrPool.AllocAddress(parent, false, port); - - if(!bAddress) - return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; - - // Extract Max Packet Size from the device descriptor - epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; - - // Assign new address to the device - rcode = pUsb->setAddr(0, 0, bAddress); - - if(rcode) { - p->lowspeed = false; - addrPool.FreeAddress(bAddress); - bAddress = 0; - USBTRACE2("setAddr:", rcode); - return rcode; - } - //delay(2); //per USB 2.0 sect.9.2.6.3 - - USBTRACE2("Addr:", bAddress); - - p->lowspeed = false; - - p = addrPool.GetUsbDevicePtr(bAddress); - - if(!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - p->lowspeed = lowspeed; - - if(len) - rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf); - - if(rcode) - goto FailGetDevDescr; - - num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations; - - USBTRACE2("NC:", num_of_conf); - - // GCC will optimize unused stuff away. - if((BOOT_PROTOCOL & (HID_PROTOCOL_KEYBOARD | HID_PROTOCOL_MOUSE)) == (HID_PROTOCOL_KEYBOARD | HID_PROTOCOL_MOUSE)) { - USBTRACE("HID_PROTOCOL_KEYBOARD AND MOUSE\r\n"); - ConfigDescParser< - USB_CLASS_HID, - HID_BOOT_INTF_SUBCLASS, - HID_PROTOCOL_KEYBOARD | HID_PROTOCOL_MOUSE, - CP_MASK_COMPARE_ALL > confDescrParser(this); - confDescrParser.SetOR(); // Use the OR variant. - for(uint8_t i = 0; i < num_of_conf; i++) { - pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); - if(bNumEP == (uint8_t)(totalEndpoints(BOOT_PROTOCOL))) - break; - } - } else { - // GCC will optimize unused stuff away. - if(BOOT_PROTOCOL & HID_PROTOCOL_KEYBOARD) { - USBTRACE("HID_PROTOCOL_KEYBOARD\r\n"); - for(uint8_t i = 0; i < num_of_conf; i++) { - ConfigDescParser< - USB_CLASS_HID, - HID_BOOT_INTF_SUBCLASS, - HID_PROTOCOL_KEYBOARD, - CP_MASK_COMPARE_ALL> confDescrParserA(this); - - pUsb->getConfDescr(bAddress, 0, i, &confDescrParserA); - if(bNumEP == (uint8_t)(totalEndpoints(BOOT_PROTOCOL))) - break; - } - } - - // GCC will optimize unused stuff away. - if(BOOT_PROTOCOL & HID_PROTOCOL_MOUSE) { - USBTRACE("HID_PROTOCOL_MOUSE\r\n"); - for(uint8_t i = 0; i < num_of_conf; i++) { - ConfigDescParser< - USB_CLASS_HID, - HID_BOOT_INTF_SUBCLASS, - HID_PROTOCOL_MOUSE, - CP_MASK_COMPARE_ALL> confDescrParserB(this); - - pUsb->getConfDescr(bAddress, 0, i, &confDescrParserB); - if(bNumEP == ((uint8_t)(totalEndpoints(BOOT_PROTOCOL)))) - break; - - } - } - } - USBTRACE2("bNumEP:", bNumEP); - - if(bNumEP != (uint8_t)(totalEndpoints(BOOT_PROTOCOL))) { - rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - goto Fail; - } - - // Assign epInfo to epinfo pointer - rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); - //USBTRACE2("setEpInfoEntry returned ", rcode); - USBTRACE2("Cnf:", bConfNum); - - delay(1000); - - // Set Configuration Value - rcode = pUsb->setConf(bAddress, 0, bConfNum); - - if(rcode) - goto FailSetConfDescr; - - delay(1000); - - USBTRACE2("bIfaceNum:", bIfaceNum); - USBTRACE2("bNumIface:", bNumIface); - - // Yes, mouse wants SetProtocol and SetIdle too! - for(uint8_t i = 0; i < epMUL(BOOT_PROTOCOL); i++) { - USBTRACE2("\r\nInterface:", i); - rcode = SetProtocol(i, HID_BOOT_PROTOCOL); - if(rcode) goto FailSetProtocol; - USBTRACE2("PROTOCOL SET HID_BOOT rcode:", rcode); - rcode = SetIdle(i, 0, 0); - USBTRACE2("SET_IDLE rcode:", rcode); - // if(rcode) goto FailSetIdle; This can fail. - // Get the RPIPE and just throw it away. - SinkParser sink; - rcode = GetReportDescr(i, &sink); - USBTRACE2("RPIPE rcode:", rcode); - } - - // Get RPIPE and throw it away. - - if(BOOT_PROTOCOL & HID_PROTOCOL_KEYBOARD) { - // Wake keyboard interface by twinkling up to 5 LEDs that are in the spec. - // kana, compose, scroll, caps, num - rcode = 0x20; // Reuse rcode. - while(rcode) { - rcode >>= 1; - // Ignore any error returned, we don't care if LED is not supported - SetReport(0, 0, 2, 0, 1, &rcode); // Eventually becomes zero (All off) - delay(25); - } - } - USBTRACE("BM configured\r\n"); - - bPollEnable = true; - return 0; - -FailGetDevDescr: -#ifdef DEBUG_USB_HOST - NotifyFailGetDevDescr(); - goto Fail; -#endif - - //FailSetDevTblEntry: - //#ifdef DEBUG_USB_HOST - // NotifyFailSetDevTblEntry(); - // goto Fail; - //#endif - - //FailGetConfDescr: - //#ifdef DEBUG_USB_HOST - // NotifyFailGetConfDescr(); - // goto Fail; - //#endif - -FailSetConfDescr: -#ifdef DEBUG_USB_HOST - NotifyFailSetConfDescr(); - goto Fail; -#endif - -FailSetProtocol: -#ifdef DEBUG_USB_HOST - USBTRACE("SetProto:"); - goto Fail; -#endif - - //FailSetIdle: - //#ifdef DEBUG_USB_HOST - // USBTRACE("SetIdle:"); - //#endif - -Fail: -#ifdef DEBUG_USB_HOST - NotifyFail(rcode); -#endif - Release(); - - return rcode; -} - -template -void HIDBoot::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) { - - // If the first configuration satisfies, the others are not considered. - //if(bNumEP > 1 && conf != bConfNum) - if(bNumEP == totalEndpoints(BOOT_PROTOCOL)) - return; - - bConfNum = conf; - bIfaceNum = iface; - - if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) { - if(pep->bInterval > bInterval) bInterval = pep->bInterval; - - // Fill in the endpoint info structure - epInfo[bNumEP].epAddr = (pep->bEndpointAddress & 0x0F); - epInfo[bNumEP].maxPktSize = (uint8_t)pep->wMaxPacketSize; - epInfo[bNumEP].epAttribs = 0; - epInfo[bNumEP].bmNakPower = USB_NAK_NOWAIT; - bNumEP++; - - } -} - -template -uint8_t HIDBoot::Release() { - pUsb->GetAddressPool().FreeAddress(bAddress); - - bConfNum = 0; - bIfaceNum = 0; - bNumEP = 1; - bAddress = 0; - qNextPollTime = 0; - bPollEnable = false; - - return 0; -} - -template -uint8_t HIDBoot::Poll() { - uint8_t rcode = 0; - - if(bPollEnable && ((long)(millis() - qNextPollTime) >= 0L)) { - - // To-do: optimize manually, using the for loop only if needed. - for(int i = 0; i < epMUL(BOOT_PROTOCOL); i++) { - const uint16_t const_buff_len = 16; - uint8_t buf[const_buff_len]; - - USBTRACE3("(hidboot.h) i=", i, 0x81); - USBTRACE3("(hidboot.h) epInfo[epInterruptInIndex + i].epAddr=", epInfo[epInterruptInIndex + i].epAddr, 0x81); - USBTRACE3("(hidboot.h) epInfo[epInterruptInIndex + i].maxPktSize=", epInfo[epInterruptInIndex + i].maxPktSize, 0x81); - uint16_t read = (uint16_t)epInfo[epInterruptInIndex + i].maxPktSize; - - rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex + i].epAddr, &read, buf); - // SOME buggy dongles report extra keys (like sleep) using a 2 byte packet on the wrong endpoint. - // Since keyboard and mice must report at least 3 bytes, we ignore the extra data. - if(!rcode && read > 2) { - if(pRptParser[i]) - pRptParser[i]->Parse((HID*)this, 0, (uint8_t)read, buf); -#ifdef DEBUG_USB_HOST - // We really don't care about errors and anomalies unless we are debugging. - } else { - if(rcode != hrNAK) { - USBTRACE3("(hidboot.h) Poll:", rcode, 0x81); - } - if(!rcode && read) { - USBTRACE3("(hidboot.h) Strange read count: ", read, 0x80); - USBTRACE3("(hidboot.h) Interface:", i, 0x80); - } - } - - if(!rcode && read && (UsbDEBUGlvl > 0x7f)) { - for(uint8_t i = 0; i < read; i++) { - PrintHex (buf[i], 0x80); - USBTRACE1(" ", 0x80); - } - if(read) - USBTRACE1("\r\n", 0x80); -#endif - } - - } - qNextPollTime = millis() + bInterval; - } - return rcode; -} - -#endif // __HIDBOOTMOUSE_H__ diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidescriptorparser.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidescriptorparser.cpp deleted file mode 100644 index e4491b4e97..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidescriptorparser.cpp +++ /dev/null @@ -1,1588 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ - -#include "hidescriptorparser.h" - -const char * const ReportDescParserBase::usagePageTitles0[] PROGMEM = { - pstrUsagePageGenericDesktopControls, - pstrUsagePageSimulationControls, - pstrUsagePageVRControls, - pstrUsagePageSportControls, - pstrUsagePageGameControls, - pstrUsagePageGenericDeviceControls, - pstrUsagePageKeyboardKeypad, - pstrUsagePageLEDs, - pstrUsagePageButton, - pstrUsagePageOrdinal, - pstrUsagePageTelephone, - pstrUsagePageConsumer, - pstrUsagePageDigitizer, - pstrUsagePagePID, - pstrUsagePageUnicode -}; - -const char * const ReportDescParserBase::usagePageTitles1[] PROGMEM = { - pstrUsagePageBarCodeScanner, - pstrUsagePageScale, - pstrUsagePageMSRDevices, - pstrUsagePagePointOfSale, - pstrUsagePageCameraControl, - pstrUsagePageArcade -}; -const char * const ReportDescParserBase::genDesktopTitles0[] PROGMEM = { - pstrUsagePointer, - pstrUsageMouse, - pstrUsageJoystick, - pstrUsageGamePad, - pstrUsageKeyboard, - pstrUsageKeypad, - pstrUsageMultiAxisController, - pstrUsageTabletPCSystemControls - -}; -const char * const ReportDescParserBase::genDesktopTitles1[] PROGMEM = { - pstrUsageX, - pstrUsageY, - pstrUsageZ, - pstrUsageRx, - pstrUsageRy, - pstrUsageRz, - pstrUsageSlider, - pstrUsageDial, - pstrUsageWheel, - pstrUsageHatSwitch, - pstrUsageCountedBuffer, - pstrUsageByteCount, - pstrUsageMotionWakeup, - pstrUsageStart, - pstrUsageSelect, - pstrUsagePageReserved, - pstrUsageVx, - pstrUsageVy, - pstrUsageVz, - pstrUsageVbrx, - pstrUsageVbry, - pstrUsageVbrz, - pstrUsageVno, - pstrUsageFeatureNotification, - pstrUsageResolutionMultiplier -}; -const char * const ReportDescParserBase::genDesktopTitles2[] PROGMEM = { - pstrUsageSystemControl, - pstrUsageSystemPowerDown, - pstrUsageSystemSleep, - pstrUsageSystemWakeup, - pstrUsageSystemContextMenu, - pstrUsageSystemMainMenu, - pstrUsageSystemAppMenu, - pstrUsageSystemMenuHelp, - pstrUsageSystemMenuExit, - pstrUsageSystemMenuSelect, - pstrUsageSystemMenuRight, - pstrUsageSystemMenuLeft, - pstrUsageSystemMenuUp, - pstrUsageSystemMenuDown, - pstrUsageSystemColdRestart, - pstrUsageSystemWarmRestart, - pstrUsageDPadUp, - pstrUsageDPadDown, - pstrUsageDPadRight, - pstrUsageDPadLeft -}; -const char * const ReportDescParserBase::genDesktopTitles3[] PROGMEM = { - pstrUsageSystemDock, - pstrUsageSystemUndock, - pstrUsageSystemSetup, - pstrUsageSystemBreak, - pstrUsageSystemDebuggerBreak, - pstrUsageApplicationBreak, - pstrUsageApplicationDebuggerBreak, - pstrUsageSystemSpeakerMute, - pstrUsageSystemHibernate -}; -const char * const ReportDescParserBase::genDesktopTitles4[] PROGMEM = { - pstrUsageSystemDisplayInvert, - pstrUsageSystemDisplayInternal, - pstrUsageSystemDisplayExternal, - pstrUsageSystemDisplayBoth, - pstrUsageSystemDisplayDual, - pstrUsageSystemDisplayToggleIntExt, - pstrUsageSystemDisplaySwapPriSec, - pstrUsageSystemDisplayLCDAutoscale -}; -const char * const ReportDescParserBase::simuTitles0[] PROGMEM = { - pstrUsageFlightSimulationDevice, - pstrUsageAutomobileSimulationDevice, - pstrUsageTankSimulationDevice, - pstrUsageSpaceshipSimulationDevice, - pstrUsageSubmarineSimulationDevice, - pstrUsageSailingSimulationDevice, - pstrUsageMotocicleSimulationDevice, - pstrUsageSportsSimulationDevice, - pstrUsageAirplaneSimulationDevice, - pstrUsageHelicopterSimulationDevice, - pstrUsageMagicCarpetSimulationDevice, - pstrUsageBicycleSimulationDevice -}; -const char * const ReportDescParserBase::simuTitles1[] PROGMEM = { - pstrUsageFlightControlStick, - pstrUsageFlightStick, - pstrUsageCyclicControl, - pstrUsageCyclicTrim, - pstrUsageFlightYoke, - pstrUsageTrackControl -}; -const char * const ReportDescParserBase::simuTitles2[] PROGMEM = { - pstrUsageAileron, - pstrUsageAileronTrim, - pstrUsageAntiTorqueControl, - pstrUsageAutopilotEnable, - pstrUsageChaffRelease, - pstrUsageCollectiveControl, - pstrUsageDiveBrake, - pstrUsageElectronicCountermeasures, - pstrUsageElevator, - pstrUsageElevatorTrim, - pstrUsageRudder, - pstrUsageThrottle, - pstrUsageFlightCommunications, - pstrUsageFlareRelease, - pstrUsageLandingGear, - pstrUsageToeBrake, - pstrUsageTrigger, - pstrUsageWeaponsArm, - pstrUsageWeaponsSelect, - pstrUsageWingFlaps, - pstrUsageAccelerator, - pstrUsageBrake, - pstrUsageClutch, - pstrUsageShifter, - pstrUsageSteering, - pstrUsageTurretDirection, - pstrUsageBarrelElevation, - pstrUsageDivePlane, - pstrUsageBallast, - pstrUsageBicycleCrank, - pstrUsageHandleBars, - pstrUsageFrontBrake, - pstrUsageRearBrake -}; -const char * const ReportDescParserBase::vrTitles0[] PROGMEM = { - pstrUsageBelt, - pstrUsageBodySuit, - pstrUsageFlexor, - pstrUsageGlove, - pstrUsageHeadTracker, - pstrUsageHeadMountedDisplay, - pstrUsageHandTracker, - pstrUsageOculometer, - pstrUsageVest, - pstrUsageAnimatronicDevice -}; -const char * const ReportDescParserBase::vrTitles1[] PROGMEM = { - pstrUsageStereoEnable, - pstrUsageDisplayEnable -}; -const char * const ReportDescParserBase::sportsCtrlTitles0[] PROGMEM = { - pstrUsageBaseballBat, - pstrUsageGolfClub, - pstrUsageRowingMachine, - pstrUsageTreadmill -}; -const char * const ReportDescParserBase::sportsCtrlTitles1[] PROGMEM = { - pstrUsageOar, - pstrUsageSlope, - pstrUsageRate, - pstrUsageStickSpeed, - pstrUsageStickFaceAngle, - pstrUsageStickHeelToe, - pstrUsageStickFollowThough, - pstrUsageStickTempo, - pstrUsageStickType, - pstrUsageStickHeight -}; -const char * const ReportDescParserBase::sportsCtrlTitles2[] PROGMEM = { - pstrUsagePutter, - pstrUsage1Iron, - pstrUsage2Iron, - pstrUsage3Iron, - pstrUsage4Iron, - pstrUsage5Iron, - pstrUsage6Iron, - pstrUsage7Iron, - pstrUsage8Iron, - pstrUsage9Iron, - pstrUsage10Iron, - pstrUsage11Iron, - pstrUsageSandWedge, - pstrUsageLoftWedge, - pstrUsagePowerWedge, - pstrUsage1Wood, - pstrUsage3Wood, - pstrUsage5Wood, - pstrUsage7Wood, - pstrUsage9Wood -}; -const char * const ReportDescParserBase::gameTitles0[] PROGMEM = { - pstrUsage3DGameController, - pstrUsagePinballDevice, - pstrUsageGunDevice -}; -const char * const ReportDescParserBase::gameTitles1[] PROGMEM = { - pstrUsagePointOfView, - pstrUsageTurnRightLeft, - pstrUsagePitchForwardBackward, - pstrUsageRollRightLeft, - pstrUsageMoveRightLeft, - pstrUsageMoveForwardBackward, - pstrUsageMoveUpDown, - pstrUsageLeanRightLeft, - pstrUsageLeanForwardBackward, - pstrUsageHeightOfPOV, - pstrUsageFlipper, - pstrUsageSecondaryFlipper, - pstrUsageBump, - pstrUsageNewGame, - pstrUsageShootBall, - pstrUsagePlayer, - pstrUsageGunBolt, - pstrUsageGunClip, - pstrUsageGunSelector, - pstrUsageGunSingleShot, - pstrUsageGunBurst, - pstrUsageGunAutomatic, - pstrUsageGunSafety, - pstrUsageGamepadFireJump, - pstrUsageGamepadTrigger -}; -const char * const ReportDescParserBase::genDevCtrlTitles[] PROGMEM = { - pstrUsageBatteryStrength, - pstrUsageWirelessChannel, - pstrUsageWirelessID, - pstrUsageDiscoverWirelessControl, - pstrUsageSecurityCodeCharEntered, - pstrUsageSecurityCodeCharErased, - pstrUsageSecurityCodeCleared -}; -const char * const ReportDescParserBase::ledTitles[] PROGMEM = { - pstrUsageNumLock, - pstrUsageCapsLock, - pstrUsageScrollLock, - pstrUsageCompose, - pstrUsageKana, - pstrUsagePower, - pstrUsageShift, - pstrUsageDoNotDisturb, - pstrUsageMute, - pstrUsageToneEnable, - pstrUsageHighCutFilter, - pstrUsageLowCutFilter, - pstrUsageEqualizerEnable, - pstrUsageSoundFieldOn, - pstrUsageSurroundOn, - pstrUsageRepeat, - pstrUsageStereo, - pstrUsageSamplingRateDetect, - pstrUsageSpinning, - pstrUsageCAV, - pstrUsageCLV, - pstrUsageRecordingFormatDetect, - pstrUsageOffHook, - pstrUsageRing, - pstrUsageMessageWaiting, - pstrUsageDataMode, - pstrUsageBatteryOperation, - pstrUsageBatteryOK, - pstrUsageBatteryLow, - pstrUsageSpeaker, - pstrUsageHeadSet, - pstrUsageHold, - pstrUsageMicrophone, - pstrUsageCoverage, - pstrUsageNightMode, - pstrUsageSendCalls, - pstrUsageCallPickup, - pstrUsageConference, - pstrUsageStandBy, - pstrUsageCameraOn, - pstrUsageCameraOff, - pstrUsageOnLine, - pstrUsageOffLine, - pstrUsageBusy, - pstrUsageReady, - pstrUsagePaperOut, - pstrUsagePaperJam, - pstrUsageRemote, - pstrUsageForward, - pstrUsageReverse, - pstrUsageStop, - pstrUsageRewind, - pstrUsageFastForward, - pstrUsagePlay, - pstrUsagePause, - pstrUsageRecord, - pstrUsageError, - pstrUsageSelectedIndicator, - pstrUsageInUseIndicator, - pstrUsageMultiModeIndicator, - pstrUsageIndicatorOn, - pstrUsageIndicatorFlash, - pstrUsageIndicatorSlowBlink, - pstrUsageIndicatorFastBlink, - pstrUsageIndicatorOff, - pstrUsageFlashOnTime, - pstrUsageSlowBlinkOnTime, - pstrUsageSlowBlinkOffTime, - pstrUsageFastBlinkOnTime, - pstrUsageFastBlinkOffTime, - pstrUsageIndicatorColor, - pstrUsageIndicatorRed, - pstrUsageIndicatorGreen, - pstrUsageIndicatorAmber, - pstrUsageGenericIndicator, - pstrUsageSystemSuspend, - pstrUsageExternalPowerConnected -}; -const char * const ReportDescParserBase::telTitles0 [] PROGMEM = { - pstrUsagePhone, - pstrUsageAnsweringMachine, - pstrUsageMessageControls, - pstrUsageHandset, - pstrUsageHeadset, - pstrUsageTelephonyKeyPad, - pstrUsageProgrammableButton -}; -const char * const ReportDescParserBase::telTitles1 [] PROGMEM = { - pstrUsageHookSwitch, - pstrUsageFlash, - pstrUsageFeature, - pstrUsageHold, - pstrUsageRedial, - pstrUsageTransfer, - pstrUsageDrop, - pstrUsagePark, - pstrUsageForwardCalls, - pstrUsageAlternateFunction, - pstrUsageLine, - pstrUsageSpeakerPhone, - pstrUsageConference, - pstrUsageRingEnable, - pstrUsageRingSelect, - pstrUsagePhoneMute, - pstrUsageCallerID, - pstrUsageSend -}; -const char * const ReportDescParserBase::telTitles2 [] PROGMEM = { - pstrUsageSpeedDial, - pstrUsageStoreNumber, - pstrUsageRecallNumber, - pstrUsagePhoneDirectory -}; -const char * const ReportDescParserBase::telTitles3 [] PROGMEM = { - pstrUsageVoiceMail, - pstrUsageScreenCalls, - pstrUsageDoNotDisturb, - pstrUsageMessage, - pstrUsageAnswerOnOff -}; -const char * const ReportDescParserBase::telTitles4 [] PROGMEM = { - pstrUsageInsideDialTone, - pstrUsageOutsideDialTone, - pstrUsageInsideRingTone, - pstrUsageOutsideRingTone, - pstrUsagePriorityRingTone, - pstrUsageInsideRingback, - pstrUsagePriorityRingback, - pstrUsageLineBusyTone, - pstrUsageReorderTone, - pstrUsageCallWaitingTone, - pstrUsageConfirmationTone1, - pstrUsageConfirmationTone2, - pstrUsageTonesOff, - pstrUsageOutsideRingback, - pstrUsageRinger -}; -const char * const ReportDescParserBase::telTitles5 [] PROGMEM = { - pstrUsagePhoneKey0, - pstrUsagePhoneKey1, - pstrUsagePhoneKey2, - pstrUsagePhoneKey3, - pstrUsagePhoneKey4, - pstrUsagePhoneKey5, - pstrUsagePhoneKey6, - pstrUsagePhoneKey7, - pstrUsagePhoneKey8, - pstrUsagePhoneKey9, - pstrUsagePhoneKeyStar, - pstrUsagePhoneKeyPound, - pstrUsagePhoneKeyA, - pstrUsagePhoneKeyB, - pstrUsagePhoneKeyC, - pstrUsagePhoneKeyD -}; -const char * const ReportDescParserBase::consTitles0[] PROGMEM = { - pstrUsageConsumerControl, - pstrUsageNumericKeyPad, - pstrUsageProgrammableButton, - pstrUsageMicrophone, - pstrUsageHeadphone, - pstrUsageGraphicEqualizer -}; -const char * const ReportDescParserBase::consTitles1[] PROGMEM = { - pstrUsagePlus10, - pstrUsagePlus100, - pstrUsageAMPM -}; -const char * const ReportDescParserBase::consTitles2[] PROGMEM = { - pstrUsagePower, - pstrUsageReset, - pstrUsageSleep, - pstrUsageSleepAfter, - pstrUsageSleepMode, - pstrUsageIllumination, - pstrUsageFunctionButtons - -}; -const char * const ReportDescParserBase::consTitles3[] PROGMEM = { - pstrUsageMenu, - pstrUsageMenuPick, - pstrUsageMenuUp, - pstrUsageMenuDown, - pstrUsageMenuLeft, - pstrUsageMenuRight, - pstrUsageMenuEscape, - pstrUsageMenuValueIncrease, - pstrUsageMenuValueDecrease -}; -const char * const ReportDescParserBase::consTitles4[] PROGMEM = { - pstrUsageDataOnScreen, - pstrUsageClosedCaption, - pstrUsageClosedCaptionSelect, - pstrUsageVCRTV, - pstrUsageBroadcastMode, - pstrUsageSnapshot, - pstrUsageStill -}; -const char * const ReportDescParserBase::consTitles5[] PROGMEM = { - pstrUsageSelection, - pstrUsageAssignSelection, - pstrUsageModeStep, - pstrUsageRecallLast, - pstrUsageEnterChannel, - pstrUsageOrderMovie, - pstrUsageChannel, - pstrUsageMediaSelection, - pstrUsageMediaSelectComputer, - pstrUsageMediaSelectTV, - pstrUsageMediaSelectWWW, - pstrUsageMediaSelectDVD, - pstrUsageMediaSelectTelephone, - pstrUsageMediaSelectProgramGuide, - pstrUsageMediaSelectVideoPhone, - pstrUsageMediaSelectGames, - pstrUsageMediaSelectMessages, - pstrUsageMediaSelectCD, - pstrUsageMediaSelectVCR, - pstrUsageMediaSelectTuner, - pstrUsageQuit, - pstrUsageHelp, - pstrUsageMediaSelectTape, - pstrUsageMediaSelectCable, - pstrUsageMediaSelectSatellite, - pstrUsageMediaSelectSecurity, - pstrUsageMediaSelectHome, - pstrUsageMediaSelectCall, - pstrUsageChannelIncrement, - pstrUsageChannelDecrement, - pstrUsageMediaSelectSAP, - pstrUsagePageReserved, - pstrUsageVCRPlus, - pstrUsageOnce, - pstrUsageDaily, - pstrUsageWeekly, - pstrUsageMonthly -}; -const char * const ReportDescParserBase::consTitles6[] PROGMEM = { - pstrUsagePlay, - pstrUsagePause, - pstrUsageRecord, - pstrUsageFastForward, - pstrUsageRewind, - pstrUsageScanNextTrack, - pstrUsageScanPreviousTrack, - pstrUsageStop, - pstrUsageEject, - pstrUsageRandomPlay, - pstrUsageSelectDisk, - pstrUsageEnterDisk, - pstrUsageRepeat, - pstrUsageTracking, - pstrUsageTrackNormal, - pstrUsageSlowTracking, - pstrUsageFrameForward, - pstrUsageFrameBackwards, - pstrUsageMark, - pstrUsageClearMark, - pstrUsageRepeatFromMark, - pstrUsageReturnToMark, - pstrUsageSearchMarkForward, - pstrUsageSearchMarkBackwards, - pstrUsageCounterReset, - pstrUsageShowCounter, - pstrUsageTrackingIncrement, - pstrUsageTrackingDecrement, - pstrUsageStopEject, - pstrUsagePlayPause, - pstrUsagePlaySkip -}; -const char * const ReportDescParserBase::consTitles7[] PROGMEM = { - pstrUsageVolume, - pstrUsageBalance, - pstrUsageMute, - pstrUsageBass, - pstrUsageTreble, - pstrUsageBassBoost, - pstrUsageSurroundMode, - pstrUsageLoudness, - pstrUsageMPX, - pstrUsageVolumeIncrement, - pstrUsageVolumeDecrement -}; -const char * const ReportDescParserBase::consTitles8[] PROGMEM = { - pstrUsageSpeedSelect, - pstrUsagePlaybackSpeed, - pstrUsageStandardPlay, - pstrUsageLongPlay, - pstrUsageExtendedPlay, - pstrUsageSlow -}; -const char * const ReportDescParserBase::consTitles9[] PROGMEM = { - pstrUsageFanEnable, - pstrUsageFanSpeed, - pstrUsageLightEnable, - pstrUsageLightIlluminationLevel, - pstrUsageClimateControlEnable, - pstrUsageRoomTemperature, - pstrUsageSecurityEnable, - pstrUsageFireAlarm, - pstrUsagePoliceAlarm, - pstrUsageProximity, - pstrUsageMotion, - pstrUsageDuresAlarm, - pstrUsageHoldupAlarm, - pstrUsageMedicalAlarm -}; -const char * const ReportDescParserBase::consTitlesA[] PROGMEM = { - pstrUsageBalanceRight, - pstrUsageBalanceLeft, - pstrUsageBassIncrement, - pstrUsageBassDecrement, - pstrUsageTrebleIncrement, - pstrUsageTrebleDecrement -}; -const char * const ReportDescParserBase::consTitlesB[] PROGMEM = { - pstrUsageSpeakerSystem, - pstrUsageChannelLeft, - pstrUsageChannelRight, - pstrUsageChannelCenter, - pstrUsageChannelFront, - pstrUsageChannelCenterFront, - pstrUsageChannelSide, - pstrUsageChannelSurround, - pstrUsageChannelLowFreqEnhancement, - pstrUsageChannelTop, - pstrUsageChannelUnknown -}; -const char * const ReportDescParserBase::consTitlesC[] PROGMEM = { - pstrUsageSubChannel, - pstrUsageSubChannelIncrement, - pstrUsageSubChannelDecrement, - pstrUsageAlternateAudioIncrement, - pstrUsageAlternateAudioDecrement -}; -const char * const ReportDescParserBase::consTitlesD[] PROGMEM = { - pstrUsageApplicationLaunchButtons, - pstrUsageALLaunchButtonConfigTool, - pstrUsageALProgrammableButton, - pstrUsageALConsumerControlConfig, - pstrUsageALWordProcessor, - pstrUsageALTextEditor, - pstrUsageALSpreadsheet, - pstrUsageALGraphicsEditor, - pstrUsageALPresentationApp, - pstrUsageALDatabaseApp, - pstrUsageALEmailReader, - pstrUsageALNewsreader, - pstrUsageALVoicemail, - pstrUsageALContactsAddressBook, - pstrUsageALCalendarSchedule, - pstrUsageALTaskProjectManager, - pstrUsageALLogJournalTimecard, - pstrUsageALCheckbookFinance, - pstrUsageALCalculator, - pstrUsageALAVCapturePlayback, - pstrUsageALLocalMachineBrowser, - pstrUsageALLANWANBrow, - pstrUsageALInternetBrowser, - pstrUsageALRemoteNetISPConnect, - pstrUsageALNetworkConference, - pstrUsageALNetworkChat, - pstrUsageALTelephonyDialer, - pstrUsageALLogon, - pstrUsageALLogoff, - pstrUsageALLogonLogoff, - pstrUsageALTermLockScrSav, - pstrUsageALControlPannel, - pstrUsageALCommandLineProcessorRun, - pstrUsageALProcessTaskManager, - pstrUsageALSelectTaskApplication, - pstrUsageALNextTaskApplication, - pstrUsageALPreviousTaskApplication, - pstrUsageALPreemptiveHaltTaskApp, - pstrUsageALIntegratedHelpCenter, - pstrUsageALDocuments, - pstrUsageALThesaurus, - pstrUsageALDictionary, - pstrUsageALDesktop, - pstrUsageALSpellCheck, - pstrUsageALGrammarCheck, - pstrUsageALWirelessStatus, - pstrUsageALKeyboardLayout, - pstrUsageALVirusProtection, - pstrUsageALEncryption, - pstrUsageALScreenSaver, - pstrUsageALAlarms, - pstrUsageALClock, - pstrUsageALFileBrowser, - pstrUsageALPowerStatus, - pstrUsageALImageBrowser, - pstrUsageALAudioBrowser, - pstrUsageALMovieBrowser, - pstrUsageALDigitalRightsManager, - pstrUsageALDigitalWallet, - pstrUsagePageReserved, - pstrUsageALInstantMessaging, - pstrUsageALOEMFeaturesBrowser, - pstrUsageALOEMHelp, - pstrUsageALOnlineCommunity, - pstrUsageALEntertainmentContentBrow, - pstrUsageALOnlineShoppingBrowser, - pstrUsageALSmartCardInfoHelp, - pstrUsageALMarketMonitorFinBrowser, - pstrUsageALCustomCorpNewsBrowser, - pstrUsageALOnlineActivityBrowser, - pstrUsageALResearchSearchBrowser, - pstrUsageALAudioPlayer -}; -const char * const ReportDescParserBase::consTitlesE[] PROGMEM = { - pstrUsageGenericGUIAppControls, - pstrUsageACNew, - pstrUsageACOpen, - pstrUsageACClose, - pstrUsageACExit, - pstrUsageACMaximize, - pstrUsageACMinimize, - pstrUsageACSave, - pstrUsageACPrint, - pstrUsageACProperties, - pstrUsageACUndo, - pstrUsageACCopy, - pstrUsageACCut, - pstrUsageACPaste, - pstrUsageACSelectAll, - pstrUsageACFind, - pstrUsageACFindAndReplace, - pstrUsageACSearch, - pstrUsageACGoto, - pstrUsageACHome, - pstrUsageACBack, - pstrUsageACForward, - pstrUsageACStop, - pstrUsageACRefresh, - pstrUsageACPreviousLink, - pstrUsageACNextLink, - pstrUsageACBookmarks, - pstrUsageACHistory, - pstrUsageACSubscriptions, - pstrUsageACZoomIn, - pstrUsageACZoomOut, - pstrUsageACZoom, - pstrUsageACFullScreenView, - pstrUsageACNormalView, - pstrUsageACViewToggle, - pstrUsageACScrollUp, - pstrUsageACScrollDown, - pstrUsageACScroll, - pstrUsageACPanLeft, - pstrUsageACPanRight, - pstrUsageACPan, - pstrUsageACNewWindow, - pstrUsageACTileHoriz, - pstrUsageACTileVert, - pstrUsageACFormat, - pstrUsageACEdit, - pstrUsageACBold, - pstrUsageACItalics, - pstrUsageACUnderline, - pstrUsageACStrikethrough, - pstrUsageACSubscript, - pstrUsageACSuperscript, - pstrUsageACAllCaps, - pstrUsageACRotate, - pstrUsageACResize, - pstrUsageACFlipHorizontal, - pstrUsageACFlipVertical, - pstrUsageACMirrorHorizontal, - pstrUsageACMirrorVertical, - pstrUsageACFontSelect, - pstrUsageACFontColor, - pstrUsageACFontSize, - pstrUsageACJustifyLeft, - pstrUsageACJustifyCenterH, - pstrUsageACJustifyRight, - pstrUsageACJustifyBlockH, - pstrUsageACJustifyTop, - pstrUsageACJustifyCenterV, - pstrUsageACJustifyBottom, - pstrUsageACJustifyBlockV, - pstrUsageACIndentDecrease, - pstrUsageACIndentIncrease, - pstrUsageACNumberedList, - pstrUsageACRestartNumbering, - pstrUsageACBulletedList, - pstrUsageACPromote, - pstrUsageACDemote, - pstrUsageACYes, - pstrUsageACNo, - pstrUsageACCancel, - pstrUsageACCatalog, - pstrUsageACBuyChkout, - pstrUsageACAddToCart, - pstrUsageACExpand, - pstrUsageACExpandAll, - pstrUsageACCollapse, - pstrUsageACCollapseAll, - pstrUsageACPrintPreview, - pstrUsageACPasteSpecial, - pstrUsageACInsertMode, - pstrUsageACDelete, - pstrUsageACLock, - pstrUsageACUnlock, - pstrUsageACProtect, - pstrUsageACUnprotect, - pstrUsageACAttachComment, - pstrUsageACDeleteComment, - pstrUsageACViewComment, - pstrUsageACSelectWord, - pstrUsageACSelectSentence, - pstrUsageACSelectParagraph, - pstrUsageACSelectColumn, - pstrUsageACSelectRow, - pstrUsageACSelectTable, - pstrUsageACSelectObject, - pstrUsageACRedoRepeat, - pstrUsageACSort, - pstrUsageACSortAscending, - pstrUsageACSortDescending, - pstrUsageACFilter, - pstrUsageACSetClock, - pstrUsageACViewClock, - pstrUsageACSelectTimeZone, - pstrUsageACEditTimeZone, - pstrUsageACSetAlarm, - pstrUsageACClearAlarm, - pstrUsageACSnoozeAlarm, - pstrUsageACResetAlarm, - pstrUsageACSyncronize, - pstrUsageACSendReceive, - pstrUsageACSendTo, - pstrUsageACReply, - pstrUsageACReplyAll, - pstrUsageACForwardMessage, - pstrUsageACSend, - pstrUsageACAttachFile, - pstrUsageACUpload, - pstrUsageACDownload, - pstrUsageACSetBorders, - pstrUsageACInsertRow, - pstrUsageACInsertColumn, - pstrUsageACInsertFile, - pstrUsageACInsertPicture, - pstrUsageACInsertObject, - pstrUsageACInsertSymbol, - pstrUsageACSaveAndClose, - pstrUsageACRename, - pstrUsageACMerge, - pstrUsageACSplit, - pstrUsageACDistributeHorizontaly, - pstrUsageACDistributeVerticaly -}; -const char * const ReportDescParserBase::digitTitles0[] PROGMEM = { - pstrUsageDigitizer, - pstrUsagePen, - pstrUsageLightPen, - pstrUsageTouchScreen, - pstrUsageTouchPad, - pstrUsageWhiteBoard, - pstrUsageCoordinateMeasuringMachine, - pstrUsage3DDigitizer, - pstrUsageStereoPlotter, - pstrUsageArticulatedArm, - pstrUsageArmature, - pstrUsageMultiplePointDigitizer, - pstrUsageFreeSpaceWand -}; -const char * const ReportDescParserBase::digitTitles1[] PROGMEM = { - pstrUsageStylus, - pstrUsagePuck, - pstrUsageFinger - -}; -const char * const ReportDescParserBase::digitTitles2[] PROGMEM = { - pstrUsageTipPressure, - pstrUsageBarrelPressure, - pstrUsageInRange, - pstrUsageTouch, - pstrUsageUntouch, - pstrUsageTap, - pstrUsageQuality, - pstrUsageDataValid, - pstrUsageTransducerIndex, - pstrUsageTabletFunctionKeys, - pstrUsageProgramChangeKeys, - pstrUsageBatteryStrength, - pstrUsageInvert, - pstrUsageXTilt, - pstrUsageYTilt, - pstrUsageAzimuth, - pstrUsageAltitude, - pstrUsageTwist, - pstrUsageTipSwitch, - pstrUsageSecondaryTipSwitch, - pstrUsageBarrelSwitch, - pstrUsageEraser, - pstrUsageTabletPick -}; -const char * const ReportDescParserBase::aplphanumTitles0[] PROGMEM = { - pstrUsageAlphanumericDisplay, - pstrUsageBitmappedDisplay -}; -const char * const ReportDescParserBase::aplphanumTitles1[] PROGMEM = { - pstrUsageDisplayAttributesReport, - pstrUsageASCIICharacterSet, - pstrUsageDataReadBack, - pstrUsageFontReadBack, - pstrUsageDisplayControlReport, - pstrUsageClearDisplay, - pstrUsageDisplayEnable, - pstrUsageScreenSaverDelay, - pstrUsageScreenSaverEnable, - pstrUsageVerticalScroll, - pstrUsageHorizontalScroll, - pstrUsageCharacterReport, - pstrUsageDisplayData, - pstrUsageDisplayStatus, - pstrUsageStatusNotReady, - pstrUsageStatusReady, - pstrUsageErrorNotALoadableCharacter, - pstrUsageErrorFotDataCanNotBeRead, - pstrUsageCursorPositionReport, - pstrUsageRow, - pstrUsageColumn, - pstrUsageRows, - pstrUsageColumns, - pstrUsageCursorPixelPosition, - pstrUsageCursorMode, - pstrUsageCursorEnable, - pstrUsageCursorBlink, - pstrUsageFontReport, - pstrUsageFontData, - pstrUsageCharacterWidth, - pstrUsageCharacterHeight, - pstrUsageCharacterSpacingHorizontal, - pstrUsageCharacterSpacingVertical, - pstrUsageUnicodeCharset, - pstrUsageFont7Segment, - pstrUsage7SegmentDirectMap, - pstrUsageFont14Segment, - pstrUsage14SegmentDirectMap, - pstrUsageDisplayBrightness, - pstrUsageDisplayContrast, - pstrUsageCharacterAttribute, - pstrUsageAttributeReadback, - pstrUsageAttributeData, - pstrUsageCharAttributeEnhance, - pstrUsageCharAttributeUnderline, - pstrUsageCharAttributeBlink -}; -const char * const ReportDescParserBase::aplphanumTitles2[] PROGMEM = { - pstrUsageBitmapSizeX, - pstrUsageBitmapSizeY, - pstrUsagePageReserved, - pstrUsageBitDepthFormat, - pstrUsageDisplayOrientation, - pstrUsagePaletteReport, - pstrUsagePaletteDataSize, - pstrUsagePaletteDataOffset, - pstrUsagePaletteData, - pstrUsageBlitReport, - pstrUsageBlitRectangleX1, - pstrUsageBlitRectangleY1, - pstrUsageBlitRectangleX2, - pstrUsageBlitRectangleY2, - pstrUsageBlitData, - pstrUsageSoftButton, - pstrUsageSoftButtonID, - pstrUsageSoftButtonSide, - pstrUsageSoftButtonOffset1, - pstrUsageSoftButtonOffset2, - pstrUsageSoftButtonReport -}; -const char * const ReportDescParserBase::medInstrTitles0[] PROGMEM = { - pstrUsageVCRAcquisition, - pstrUsageFreezeThaw, - pstrUsageClipStore, - pstrUsageUpdate, - pstrUsageNext, - pstrUsageSave, - pstrUsagePrint, - pstrUsageMicrophoneEnable -}; -const char * const ReportDescParserBase::medInstrTitles1[] PROGMEM = { - pstrUsageCine, - pstrUsageTransmitPower, - pstrUsageVolume, - pstrUsageFocus, - pstrUsageDepth -}; -const char * const ReportDescParserBase::medInstrTitles2[] PROGMEM = { - pstrUsageSoftStepPrimary, - pstrUsageSoftStepSecondary -}; -const char * const ReportDescParserBase::medInstrTitles3[] PROGMEM = { - pstrUsageZoomSelect, - pstrUsageZoomAdjust, - pstrUsageSpectralDopplerModeSelect, - pstrUsageSpectralDopplerModeAdjust, - pstrUsageColorDopplerModeSelect, - pstrUsageColorDopplerModeAdjust, - pstrUsageMotionModeSelect, - pstrUsageMotionModeAdjust, - pstrUsage2DModeSelect, - pstrUsage2DModeAdjust -}; -const char * const ReportDescParserBase::medInstrTitles4[] PROGMEM = { - pstrUsageSoftControlSelect, - pstrUsageSoftControlAdjust -}; - -void ReportDescParserBase::Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset) { - uint16_t cntdn = (uint16_t)len; - uint8_t *p = (uint8_t*)pbuf; - - - totalSize = 0; - - while(cntdn) { - //USB_HOST_SERIAL.println(""); - //PrintHex(offset + len - cntdn); - //USB_HOST_SERIAL.print(":"); - - ParseItem(&p, &cntdn); - - //if (ParseItem(&p, &cntdn)) - // return; - } - //USBTRACE2("Total:", totalSize); -} - -void ReportDescParserBase::PrintValue(uint8_t *p, uint8_t len) { - E_Notify(PSTR("("), 0x80); - for(; len; p++, len--) - PrintHex (*p, 0x80); - E_Notify(PSTR(")"), 0x80); -} - -void ReportDescParserBase::PrintByteValue(uint8_t data) { - E_Notify(PSTR("("), 0x80); - PrintHex (data, 0x80); - E_Notify(PSTR(")"), 0x80); -} - -void ReportDescParserBase::PrintItemTitle(uint8_t prefix) { - switch(prefix & (TYPE_MASK | TAG_MASK)) { - case (TYPE_GLOBAL | TAG_GLOBAL_PUSH): - E_Notify(PSTR("\r\nPush"), 0x80); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_POP): - E_Notify(PSTR("\r\nPop"), 0x80); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_USAGEPAGE): - E_Notify(PSTR("\r\nUsage Page"), 0x80); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMIN): - E_Notify(PSTR("\r\nLogical Min"), 0x80); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMAX): - E_Notify(PSTR("\r\nLogical Max"), 0x80); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMIN): - E_Notify(PSTR("\r\nPhysical Min"), 0x80); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMAX): - E_Notify(PSTR("\r\nPhysical Max"), 0x80); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_UNITEXP): - E_Notify(PSTR("\r\nUnit Exp"), 0x80); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_UNIT): - E_Notify(PSTR("\r\nUnit"), 0x80); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_REPORTSIZE): - E_Notify(PSTR("\r\nReport Size"), 0x80); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_REPORTCOUNT): - E_Notify(PSTR("\r\nReport Count"), 0x80); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_REPORTID): - E_Notify(PSTR("\r\nReport Id"), 0x80); - break; - case (TYPE_LOCAL | TAG_LOCAL_USAGE): - E_Notify(PSTR("\r\nUsage"), 0x80); - break; - case (TYPE_LOCAL | TAG_LOCAL_USAGEMIN): - E_Notify(PSTR("\r\nUsage Min"), 0x80); - break; - case (TYPE_LOCAL | TAG_LOCAL_USAGEMAX): - E_Notify(PSTR("\r\nUsage Max"), 0x80); - break; - case (TYPE_MAIN | TAG_MAIN_COLLECTION): - E_Notify(PSTR("\r\nCollection"), 0x80); - break; - case (TYPE_MAIN | TAG_MAIN_ENDCOLLECTION): - E_Notify(PSTR("\r\nEnd Collection"), 0x80); - break; - case (TYPE_MAIN | TAG_MAIN_INPUT): - E_Notify(PSTR("\r\nInput"), 0x80); - break; - case (TYPE_MAIN | TAG_MAIN_OUTPUT): - E_Notify(PSTR("\r\nOutput"), 0x80); - break; - case (TYPE_MAIN | TAG_MAIN_FEATURE): - E_Notify(PSTR("\r\nFeature"), 0x80); - break; - } // switch (**pp & (TYPE_MASK | TAG_MASK)) -} - -uint8_t ReportDescParserBase::ParseItem(uint8_t **pp, uint16_t *pcntdn) { - //uint8_t ret = enErrorSuccess; - //reinterpret_cast<>(varBuffer); - switch(itemParseState) { - case 0: - if(**pp == HID_LONG_ITEM_PREFIX) - USBTRACE("\r\nLONG\r\n"); - else { - uint8_t size = ((**pp) & DATA_SIZE_MASK); - - itemPrefix = (**pp); - itemSize = 1 + ((size == DATA_SIZE_4) ? 4 : size); - - PrintItemTitle(itemPrefix); - } - (*pp)++; - (*pcntdn)--; - itemSize--; - itemParseState = 1; - - if(!itemSize) - break; - - if(!pcntdn) - return enErrorIncomplete; - case 1: - //USBTRACE2("\r\niSz:",itemSize); - - theBuffer.valueSize = itemSize; - valParser.Initialize(&theBuffer); - itemParseState = 2; - case 2: - if(!valParser.Parse(pp, pcntdn)) - return enErrorIncomplete; - itemParseState = 3; - case 3: - { - uint8_t data = *((uint8_t*)varBuffer); - - switch(itemPrefix & (TYPE_MASK | TAG_MASK)) { - case (TYPE_LOCAL | TAG_LOCAL_USAGE): - if(pfUsage) { - if(theBuffer.valueSize > 1) { - uint16_t* ui16 = reinterpret_cast(varBuffer); - pfUsage(*ui16); - } else - pfUsage(data); - } - break; - case (TYPE_GLOBAL | TAG_GLOBAL_REPORTSIZE): - rptSize = data; - PrintByteValue(data); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_REPORTCOUNT): - rptCount = data; - PrintByteValue(data); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMIN): - case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMAX): - case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMIN): - case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMAX): - case (TYPE_GLOBAL | TAG_GLOBAL_REPORTID): - case (TYPE_LOCAL | TAG_LOCAL_USAGEMIN): - case (TYPE_LOCAL | TAG_LOCAL_USAGEMAX): - case (TYPE_GLOBAL | TAG_GLOBAL_UNITEXP): - case (TYPE_GLOBAL | TAG_GLOBAL_UNIT): - PrintValue(varBuffer, theBuffer.valueSize); - break; - case (TYPE_GLOBAL | TAG_GLOBAL_PUSH): - case (TYPE_GLOBAL | TAG_GLOBAL_POP): - break; - case (TYPE_GLOBAL | TAG_GLOBAL_USAGEPAGE): - SetUsagePage(data); - PrintUsagePage(data); - PrintByteValue(data); - break; - case (TYPE_MAIN | TAG_MAIN_COLLECTION): - case (TYPE_MAIN | TAG_MAIN_ENDCOLLECTION): - switch(data) { - case 0x00: - E_Notify(PSTR(" Physical"), 0x80); - break; - case 0x01: - E_Notify(PSTR(" Application"), 0x80); - break; - case 0x02: - E_Notify(PSTR(" Logical"), 0x80); - break; - case 0x03: - E_Notify(PSTR(" Report"), 0x80); - break; - case 0x04: - E_Notify(PSTR(" Named Array"), 0x80); - break; - case 0x05: - E_Notify(PSTR(" Usage Switch"), 0x80); - break; - case 0x06: - E_Notify(PSTR(" Usage Modifier"), 0x80); - break; - default: - E_Notify(PSTR(" Vendor Defined("), 0x80); - PrintHex (data, 0x80); - E_Notify(PSTR(")"), 0x80); - } - break; - case (TYPE_MAIN | TAG_MAIN_INPUT): - case (TYPE_MAIN | TAG_MAIN_OUTPUT): - case (TYPE_MAIN | TAG_MAIN_FEATURE): - totalSize += (uint16_t)rptSize * (uint16_t)rptCount; - rptSize = 0; - rptCount = 0; - E_Notify(PSTR("("), 0x80); - PrintBin (data, 0x80); - E_Notify(PSTR(")"), 0x80); - break; - } // switch (**pp & (TYPE_MASK | TAG_MASK)) - } - } // switch (itemParseState) - itemParseState = 0; - return enErrorSuccess; -} - -ReportDescParserBase::UsagePageFunc ReportDescParserBase::usagePageFunctions[] /*PROGMEM*/ = { - &ReportDescParserBase::PrintGenericDesktopPageUsage, - &ReportDescParserBase::PrintSimulationControlsPageUsage, - &ReportDescParserBase::PrintVRControlsPageUsage, - &ReportDescParserBase::PrintSportsControlsPageUsage, - &ReportDescParserBase::PrintGameControlsPageUsage, - &ReportDescParserBase::PrintGenericDeviceControlsPageUsage, - NULL, // Keyboard/Keypad - &ReportDescParserBase::PrintLEDPageUsage, - &ReportDescParserBase::PrintButtonPageUsage, - &ReportDescParserBase::PrintOrdinalPageUsage, - &ReportDescParserBase::PrintTelephonyPageUsage, - &ReportDescParserBase::PrintConsumerPageUsage, - &ReportDescParserBase::PrintDigitizerPageUsage, - NULL, // Reserved - NULL, // PID - NULL // Unicode -}; - -void ReportDescParserBase::SetUsagePage(uint16_t page) { - pfUsage = NULL; - - if(VALUE_BETWEEN(page, 0x00, 0x11)) { - pfUsage = (usagePageFunctions[page - 1]); - - } else { - switch(page) { - case 0x14: - pfUsage = &ReportDescParserBase::PrintAlphanumDisplayPageUsage; - break; - case 0x40: - pfUsage = &ReportDescParserBase::PrintMedicalInstrumentPageUsage; - break; - } - } -} - -void ReportDescParserBase::PrintUsagePage(uint16_t page) { - const char * const * w; - E_Notify(pstrSpace, 0x80); - - output_if_between(page, 0x00, 0x11, w, E_Notify, usagePageTitles0, 0x80) - else output_if_between(page, 0x8b, 0x92, w, E_Notify, usagePageTitles1, 0x80) - else if(VALUE_BETWEEN(page, 0x7f, 0x84)) - E_Notify(pstrUsagePageMonitor, 0x80); - else if(VALUE_BETWEEN(page, 0x83, 0x8c)) - E_Notify(pstrUsagePagePower, 0x80); - else if(page > 0xfeff /* && page <= 0xffff */) - E_Notify(pstrUsagePageVendorDefined, 0x80); - else - switch(page) { - case 0x14: - E_Notify(pstrUsagePageAlphaNumericDisplay, 0x80); - break; - case 0x40: - E_Notify(pstrUsagePageMedicalInstruments, 0x80); - break; - default: - E_Notify(pstrUsagePageUndefined, 0x80); - } -} - -void ReportDescParserBase::PrintButtonPageUsage(uint16_t usage) { - E_Notify(pstrSpace, 0x80); - E_Notify(PSTR("Btn"), 0x80); - PrintHex (usage, 0x80); - E_Notify(PSTR("\r\n"), 0x80); - //USB_HOST_SERIAL.print(usage, HEX); -} - -void ReportDescParserBase::PrintOrdinalPageUsage(uint16_t usage) { - E_Notify(pstrSpace, 0x80); - E_Notify(PSTR("Inst"), 0x80); - // Sorry, HEX for now... - PrintHex (usage, 0x80); - E_Notify(PSTR("\r\n"), 0x80); - //USB_HOST_SERIAL.print(usage, DEC); -} - -void ReportDescParserBase::PrintGenericDesktopPageUsage(uint16_t usage) { - const char * const * w; - E_Notify(pstrSpace, 0x80); - - output_if_between(usage, 0x00, 0x0a, w, E_Notify, genDesktopTitles0, 0x80) - else output_if_between(usage, 0x2f, 0x49, w, E_Notify, genDesktopTitles1, 0x80) - else output_if_between(usage, 0x7f, 0x94, w, E_Notify, genDesktopTitles2, 0x80) - else output_if_between(usage, 0x9f, 0xa9, w, E_Notify, genDesktopTitles3, 0x80) - else output_if_between(usage, 0xaf, 0xb8, w, E_Notify, genDesktopTitles4, 0x80) - else E_Notify(pstrUsagePageUndefined, 0x80); -} - -void ReportDescParserBase::PrintSimulationControlsPageUsage(uint16_t usage) { - const char * const * w; - E_Notify(pstrSpace, 0x80); - - output_if_between(usage, 0x00, 0x0d, w, E_Notify, simuTitles0, 0x80) - else output_if_between(usage, 0x1f, 0x26, w, E_Notify, simuTitles1, 0x80) - else output_if_between(usage, 0xaf, 0xd1, w, E_Notify, simuTitles2, 0x80) - else E_Notify(pstrUsagePageUndefined, 0x80); -} - -void ReportDescParserBase::PrintVRControlsPageUsage(uint16_t usage) { - const char * const * w; - E_Notify(pstrSpace, 0x80); - - output_if_between(usage, 0x00, 0x0b, w, E_Notify, vrTitles0, 0x80) - else output_if_between(usage, 0x1f, 0x22, w, E_Notify, vrTitles1, 0x80) - else E_Notify(pstrUsagePageUndefined, 0x80); -} - -void ReportDescParserBase::PrintSportsControlsPageUsage(uint16_t usage) { - const char * const * w; - E_Notify(pstrSpace, 0x80); - - output_if_between(usage, 0x00, 0x05, w, E_Notify, sportsCtrlTitles0, 0x80) - else output_if_between(usage, 0x2f, 0x3a, w, E_Notify, sportsCtrlTitles1, 0x80) - else output_if_between(usage, 0x4f, 0x64, w, E_Notify, sportsCtrlTitles2, 0x80) - else E_Notify(pstrUsagePageUndefined, 0x80); -} - -void ReportDescParserBase::PrintGameControlsPageUsage(uint16_t usage) { - const char * const * w; - E_Notify(pstrSpace, 0x80); - - output_if_between(usage, 0x00, 0x04, w, E_Notify, gameTitles0, 0x80) - else output_if_between(usage, 0x1f, 0x3a, w, E_Notify, gameTitles1, 0x80) - else E_Notify(pstrUsagePageUndefined, 0x80); -} - -void ReportDescParserBase::PrintGenericDeviceControlsPageUsage(uint16_t usage) { - const char * const * w; - E_Notify(pstrSpace, 0x80); - - output_if_between(usage, 0x1f, 0x27, w, E_Notify, genDevCtrlTitles, 0x80) - else E_Notify(pstrUsagePageUndefined, 0x80); -} - -void ReportDescParserBase::PrintLEDPageUsage(uint16_t usage) { - const char * const * w; - E_Notify(pstrSpace, 0x80); - - output_if_between(usage, 0x00, 0x4e, w, E_Notify, ledTitles, 0x80) - else E_Notify(pstrUsagePageUndefined, 0x80); -} - -void ReportDescParserBase::PrintTelephonyPageUsage(uint16_t usage) { - const char * const * w; - E_Notify(pstrSpace, 0x80); - - output_if_between(usage, 0x00, 0x08, w, E_Notify, telTitles0, 0x80) - else output_if_between(usage, 0x1f, 0x32, w, E_Notify, telTitles1, 0x80) - else output_if_between(usage, 0x4f, 0x54, w, E_Notify, telTitles2, 0x80) - else output_if_between(usage, 0x6f, 0x75, w, E_Notify, telTitles3, 0x80) - else output_if_between(usage, 0x8f, 0x9f, w, E_Notify, telTitles4, 0x80) - else output_if_between(usage, 0xaf, 0xc0, w, E_Notify, telTitles5, 0x80) - else E_Notify(pstrUsagePageUndefined, 0x80); -} - -void ReportDescParserBase::PrintConsumerPageUsage(uint16_t usage) { - const char * const * w; - E_Notify(pstrSpace, 0x80); - - output_if_between(usage, 0x00, 0x07, w, E_Notify, consTitles0, 0x80) - else output_if_between(usage, 0x1f, 0x23, w, E_Notify, consTitles1, 0x80) - else output_if_between(usage, 0x2f, 0x37, w, E_Notify, consTitles2, 0x80) - else output_if_between(usage, 0x3f, 0x49, w, E_Notify, consTitles3, 0x80) - else output_if_between(usage, 0x5f, 0x67, w, E_Notify, consTitles4, 0x80) - else output_if_between(usage, 0x7f, 0xa5, w, E_Notify, consTitles5, 0x80) - else output_if_between(usage, 0xaf, 0xcf, w, E_Notify, consTitles6, 0x80) - else output_if_between(usage, 0xdf, 0xeb, w, E_Notify, consTitles7, 0x80) - else output_if_between(usage, 0xef, 0xf6, w, E_Notify, consTitles8, 0x80) - else output_if_between(usage, 0xff, 0x10e, w, E_Notify, consTitles9, 0x80) - else output_if_between(usage, 0x14f, 0x156, w, E_Notify, consTitlesA, 0x80) - else output_if_between(usage, 0x15f, 0x16b, w, E_Notify, consTitlesB, 0x80) - else output_if_between(usage, 0x16f, 0x175, w, E_Notify, consTitlesC, 0x80) - else output_if_between(usage, 0x17f, 0x1c8, w, E_Notify, consTitlesD, 0x80) - else output_if_between(usage, 0x1ff, 0x29d, w, E_Notify, consTitlesE, 0x80) - else E_Notify(pstrUsagePageUndefined, 0x80); -} - -void ReportDescParserBase::PrintDigitizerPageUsage(uint16_t usage) { - const char * const * w; - E_Notify(pstrSpace, 0x80); - - output_if_between(usage, 0x00, 0x0e, w, E_Notify, digitTitles0, 0x80) - else output_if_between(usage, 0x1f, 0x23, w, E_Notify, digitTitles1, 0x80) - else output_if_between(usage, 0x2f, 0x47, w, E_Notify, digitTitles2, 0x80) - else E_Notify(pstrUsagePageUndefined, 0x80); -} - -void ReportDescParserBase::PrintAlphanumDisplayPageUsage(uint16_t usage) { - const char * const * w; - E_Notify(pstrSpace, 0x80); - - output_if_between(usage, 0x00, 0x03, w, E_Notify, aplphanumTitles0, 0x80) - else output_if_between(usage, 0x1f, 0x4e, w, E_Notify, aplphanumTitles1, 0x80) - else output_if_between(usage, 0x7f, 0x96, w, E_Notify, digitTitles2, 0x80) - else E_Notify(pstrUsagePageUndefined, 0x80); -} - -void ReportDescParserBase::PrintMedicalInstrumentPageUsage(uint16_t usage) { - const char * const * w; - E_Notify(pstrSpace, 0x80); - - if(usage == 1) E_Notify(pstrUsageMedicalUltrasound, 0x80); - else if(usage == 0x70) - E_Notify(pstrUsageDepthGainCompensation, 0x80); - else output_if_between(usage, 0x1f, 0x28, w, E_Notify, medInstrTitles0, 0x80) - else output_if_between(usage, 0x3f, 0x45, w, E_Notify, medInstrTitles1, 0x80) - else output_if_between(usage, 0x5f, 0x62, w, E_Notify, medInstrTitles2, 0x80) - else output_if_between(usage, 0x7f, 0x8a, w, E_Notify, medInstrTitles3, 0x80) - else output_if_between(usage, 0x9f, 0xa2, w, E_Notify, medInstrTitles4, 0x80) - else E_Notify(pstrUsagePageUndefined, 0x80); -} - -uint8_t ReportDescParser2::ParseItem(uint8_t **pp, uint16_t *pcntdn) { - //uint8_t ret = enErrorSuccess; - - switch(itemParseState) { - case 0: - if(**pp == HID_LONG_ITEM_PREFIX) - USBTRACE("\r\nLONG\r\n"); - else { - uint8_t size = ((**pp) & DATA_SIZE_MASK); - itemPrefix = (**pp); - itemSize = 1 + ((size == DATA_SIZE_4) ? 4 : size); - } - (*pp)++; - (*pcntdn)--; - itemSize--; - itemParseState = 1; - - if(!itemSize) - break; - - if(!pcntdn) - return enErrorIncomplete; - case 1: - theBuffer.valueSize = itemSize; - valParser.Initialize(&theBuffer); - itemParseState = 2; - case 2: - if(!valParser.Parse(pp, pcntdn)) - return enErrorIncomplete; - itemParseState = 3; - case 3: - { - uint8_t data = *((uint8_t*)varBuffer); - - switch(itemPrefix & (TYPE_MASK | TAG_MASK)) { - case (TYPE_LOCAL | TAG_LOCAL_USAGE): - if(pfUsage) { - if(theBuffer.valueSize > 1) { - uint16_t* ui16 = reinterpret_cast(varBuffer); - pfUsage(*ui16); - } else - pfUsage(data); - } - break; - case (TYPE_GLOBAL | TAG_GLOBAL_REPORTSIZE): - rptSize = data; - break; - case (TYPE_GLOBAL | TAG_GLOBAL_REPORTCOUNT): - rptCount = data; - break; - case (TYPE_GLOBAL | TAG_GLOBAL_REPORTID): - rptId = data; - break; - case (TYPE_LOCAL | TAG_LOCAL_USAGEMIN): - useMin = data; - break; - case (TYPE_LOCAL | TAG_LOCAL_USAGEMAX): - useMax = data; - break; - case (TYPE_GLOBAL | TAG_GLOBAL_USAGEPAGE): - SetUsagePage(data); - break; - case (TYPE_MAIN | TAG_MAIN_OUTPUT): - case (TYPE_MAIN | TAG_MAIN_FEATURE): - rptSize = 0; - rptCount = 0; - useMin = 0; - useMax = 0; - break; - case (TYPE_MAIN | TAG_MAIN_INPUT): - OnInputItem(data); - - totalSize += (uint16_t)rptSize * (uint16_t)rptCount; - - rptSize = 0; - rptCount = 0; - useMin = 0; - useMax = 0; - break; - } // switch (**pp & (TYPE_MASK | TAG_MASK)) - } - } // switch (itemParseState) - itemParseState = 0; - return enErrorSuccess; -} - -void ReportDescParser2::OnInputItem(uint8_t itm) { - uint8_t byte_offset = (totalSize >> 3); // calculate offset to the next unhandled byte i = (int)(totalCount / 8); - uint32_t tmp = (byte_offset << 3); - uint8_t bit_offset = totalSize - tmp; // number of bits in the current byte already handled - uint8_t *p = pBuf + byte_offset; // current byte pointer - - if(bit_offset) - *p >>= bit_offset; - - uint8_t usage = useMin; - - bool print_usemin_usemax = ((useMin < useMax) && ((itm & 3) == 2) && pfUsage) ? true : false; - - uint8_t bits_of_byte = 8; - - // for each field in field array defined by rptCount - for(uint8_t field = 0; field < rptCount; field++, usage++) { - - union { - uint8_t bResult[4]; - uint16_t wResult[2]; - uint32_t dwResult; - } result; - - result.dwResult = 0; - uint8_t mask = 0; - - if(print_usemin_usemax) - pfUsage(usage); - - // bits_left - number of bits in the field(array of fields, depending on Report Count) left to process - // bits_of_byte - number of bits in current byte left to process - // bits_to_copy - number of bits to copy to result buffer - - // for each bit in a field - for(uint8_t bits_left = rptSize, bits_to_copy = 0; bits_left; - bits_left -= bits_to_copy) { - bits_to_copy = (bits_left > bits_of_byte) ? bits_of_byte : bits_left; - - result.dwResult <<= bits_to_copy; // Result buffer is shifted by the number of bits to be copied into it - - uint8_t val = *p; - - val >>= (8 - bits_of_byte); // Shift by the number of bits already processed - - mask = 0; - - for(uint8_t j = bits_to_copy; j; j--) { - mask <<= 1; - mask |= 1; - } - - result.bResult[0] = (result.bResult[0] | (val & mask)); - - bits_of_byte -= bits_to_copy; - - if(bits_of_byte < 1) { - bits_of_byte = 8; - p++; - } - } - PrintByteValue(result.dwResult); - } - E_Notify(PSTR("\r\n"), 0x80); -} - -void UniversalReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) { - ReportDescParser2 prs(len, buf); - - uint8_t ret = hid->GetReportDescr(0, &prs); - - if(ret) - ErrorMessage (PSTR("GetReportDescr-2"), ret); -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidescriptorparser.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidescriptorparser.h deleted file mode 100644 index f3b496ffa5..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidescriptorparser.h +++ /dev/null @@ -1,176 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ -#if !defined(__HIDDESCRIPTORPARSER_H__) -#define __HIDDESCRIPTORPARSER_H__ - -#include "hid.h" - -class ReportDescParserBase : public USBReadParser { -public: - typedef void (*UsagePageFunc)(uint16_t usage); - - static void PrintGenericDesktopPageUsage(uint16_t usage); - static void PrintSimulationControlsPageUsage(uint16_t usage); - static void PrintVRControlsPageUsage(uint16_t usage); - static void PrintSportsControlsPageUsage(uint16_t usage); - static void PrintGameControlsPageUsage(uint16_t usage); - static void PrintGenericDeviceControlsPageUsage(uint16_t usage); - static void PrintLEDPageUsage(uint16_t usage); - static void PrintButtonPageUsage(uint16_t usage); - static void PrintOrdinalPageUsage(uint16_t usage); - static void PrintTelephonyPageUsage(uint16_t usage); - static void PrintConsumerPageUsage(uint16_t usage); - static void PrintDigitizerPageUsage(uint16_t usage); - static void PrintAlphanumDisplayPageUsage(uint16_t usage); - static void PrintMedicalInstrumentPageUsage(uint16_t usage); - - static void PrintValue(uint8_t *p, uint8_t len); - static void PrintByteValue(uint8_t data); - - static void PrintItemTitle(uint8_t prefix); - - static const char * const usagePageTitles0[]; - static const char * const usagePageTitles1[]; - static const char * const genDesktopTitles0[]; - static const char * const genDesktopTitles1[]; - static const char * const genDesktopTitles2[]; - static const char * const genDesktopTitles3[]; - static const char * const genDesktopTitles4[]; - static const char * const simuTitles0[]; - static const char * const simuTitles1[]; - static const char * const simuTitles2[]; - static const char * const vrTitles0[]; - static const char * const vrTitles1[]; - static const char * const sportsCtrlTitles0[]; - static const char * const sportsCtrlTitles1[]; - static const char * const sportsCtrlTitles2[]; - static const char * const gameTitles0[]; - static const char * const gameTitles1[]; - static const char * const genDevCtrlTitles[]; - static const char * const ledTitles[]; - static const char * const telTitles0[]; - static const char * const telTitles1[]; - static const char * const telTitles2[]; - static const char * const telTitles3[]; - static const char * const telTitles4[]; - static const char * const telTitles5[]; - static const char * const consTitles0[]; - static const char * const consTitles1[]; - static const char * const consTitles2[]; - static const char * const consTitles3[]; - static const char * const consTitles4[]; - static const char * const consTitles5[]; - static const char * const consTitles6[]; - static const char * const consTitles7[]; - static const char * const consTitles8[]; - static const char * const consTitles9[]; - static const char * const consTitlesA[]; - static const char * const consTitlesB[]; - static const char * const consTitlesC[]; - static const char * const consTitlesD[]; - static const char * const consTitlesE[]; - static const char * const digitTitles0[]; - static const char * const digitTitles1[]; - static const char * const digitTitles2[]; - static const char * const aplphanumTitles0[]; - static const char * const aplphanumTitles1[]; - static const char * const aplphanumTitles2[]; - static const char * const medInstrTitles0[]; - static const char * const medInstrTitles1[]; - static const char * const medInstrTitles2[]; - static const char * const medInstrTitles3[]; - static const char * const medInstrTitles4[]; - -protected: - static UsagePageFunc usagePageFunctions[]; - - MultiValueBuffer theBuffer; - MultiByteValueParser valParser; - ByteSkipper theSkipper; - uint8_t varBuffer[sizeof (USB_CONFIGURATION_DESCRIPTOR)]; - - uint8_t itemParseState; // Item parser state variable - uint8_t itemSize; // Item size - uint8_t itemPrefix; // Item prefix (first byte) - uint8_t rptSize; // Report Size - uint8_t rptCount; // Report Count - - uint16_t totalSize; // Report size in bits - - // Method should be defined here if virtual. - virtual uint8_t ParseItem(uint8_t **pp, uint16_t *pcntdn); - - UsagePageFunc pfUsage; - - static void PrintUsagePage(uint16_t page); - void SetUsagePage(uint16_t page); - -public: - - ReportDescParserBase() : - itemParseState(0), - itemSize(0), - itemPrefix(0), - rptSize(0), - rptCount(0), - pfUsage(NULL) { - theBuffer.pValue = varBuffer; - valParser.Initialize(&theBuffer); - theSkipper.Initialize(&theBuffer); - }; - - void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset); - - enum { - enErrorSuccess = 0 - , enErrorIncomplete // value or record is partialy read in buffer - , enErrorBufferTooSmall - }; -}; - -class ReportDescParser : public ReportDescParserBase { -}; - -class ReportDescParser2 : public ReportDescParserBase { - uint8_t rptId; // Report ID - uint8_t useMin; // Usage Minimum - uint8_t useMax; // Usage Maximum - uint8_t fieldCount; // Number of field being currently processed - - void OnInputItem(uint8_t itm); // Method which is called every time Input item is found - - uint8_t *pBuf; // Report buffer pointer - uint8_t bLen; // Report length - -protected: - // Method should be defined here if virtual. - virtual uint8_t ParseItem(uint8_t **pp, uint16_t *pcntdn); - -public: - - ReportDescParser2(uint16_t len, uint8_t *pbuf) : - ReportDescParserBase(), rptId(0), useMin(0), useMax(0), fieldCount(0), pBuf(pbuf), bLen(len) { - }; -}; - -class UniversalReportParser : public HIDReportParser { -public: - // Method should be defined here if virtual. - virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); -}; - -#endif // __HIDDESCRIPTORPARSER_H__ diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hiduniversal.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hiduniversal.cpp deleted file mode 100644 index 395aa69e34..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hiduniversal.cpp +++ /dev/null @@ -1,425 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ - -#include "hiduniversal.h" - -HIDUniversal::HIDUniversal(USB *p) : -HID(p), -qNextPollTime(0), -pollInterval(0), -bPollEnable(false), -bHasReportId(false) { - Initialize(); - - if(pUsb) - pUsb->RegisterDeviceClass(this); -} - -uint16_t HIDUniversal::GetHidClassDescrLen(uint8_t type, uint8_t num) { - for(uint8_t i = 0, n = 0; i < HID_MAX_HID_CLASS_DESCRIPTORS; i++) { - if(descrInfo[i].bDescrType == type) { - if(n == num) - return descrInfo[i].wDescriptorLength; - n++; - } - } - return 0; -} - -void HIDUniversal::Initialize() { - for(uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) { - rptParsers[i].rptId = 0; - rptParsers[i].rptParser = NULL; - } - for(uint8_t i = 0; i < HID_MAX_HID_CLASS_DESCRIPTORS; i++) { - descrInfo[i].bDescrType = 0; - descrInfo[i].wDescriptorLength = 0; - } - for(uint8_t i = 0; i < maxHidInterfaces; i++) { - hidInterfaces[i].bmInterface = 0; - hidInterfaces[i].bmProtocol = 0; - - for(uint8_t j = 0; j < maxEpPerInterface; j++) - hidInterfaces[i].epIndex[j] = 0; - } - for(uint8_t i = 0; i < totalEndpoints; i++) { - epInfo[i].epAddr = 0; - epInfo[i].maxPktSize = (i) ? 0 : 8; - epInfo[i].epAttribs = 0; - epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; - } - bNumEP = 1; - bNumIface = 0; - bConfNum = 0; - pollInterval = 0; - - ZeroMemory(constBuffLen, prevBuf); -} - -bool HIDUniversal::SetReportParser(uint8_t id, HIDReportParser *prs) { - for(uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) { - if(rptParsers[i].rptId == 0 && rptParsers[i].rptParser == NULL) { - rptParsers[i].rptId = id; - rptParsers[i].rptParser = prs; - return true; - } - } - return false; -} - -HIDReportParser* HIDUniversal::GetReportParser(uint8_t id) { - if(!bHasReportId) - return ((rptParsers[0].rptParser) ? rptParsers[0].rptParser : NULL); - - for(uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) { - if(rptParsers[i].rptId == id) - return rptParsers[i].rptParser; - } - return NULL; -} - -uint8_t HIDUniversal::Init(uint8_t parent, uint8_t port, bool lowspeed) { - const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR); - - uint8_t buf[constBufSize]; - USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); - uint8_t rcode; - UsbDevice *p = NULL; - EpInfo *oldep_ptr = NULL; - uint8_t len = 0; - - uint8_t num_of_conf; // number of configurations - //uint8_t num_of_intf; // number of interfaces - - AddressPool &addrPool = pUsb->GetAddressPool(); - - USBTRACE("HU Init\r\n"); - - if(bAddress) - return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; - - // Get pointer to pseudo device with address 0 assigned - p = addrPool.GetUsbDevicePtr(0); - - if(!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - if(!p->epinfo) { - USBTRACE("epinfo\r\n"); - return USB_ERROR_EPINFO_IS_NULL; - } - - // Save old pointer to EP_RECORD of address 0 - oldep_ptr = p->epinfo; - - // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence - p->epinfo = epInfo; - - p->lowspeed = lowspeed; - - // Get device descriptor - rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*)buf); - - if(!rcode) - len = (buf[0] > constBufSize) ? constBufSize : buf[0]; - - if(rcode) { - // Restore p->epinfo - p->epinfo = oldep_ptr; - - goto FailGetDevDescr; - } - - // Restore p->epinfo - p->epinfo = oldep_ptr; - - // Allocate new address according to device class - bAddress = addrPool.AllocAddress(parent, false, port); - - if(!bAddress) - return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; - - // Extract Max Packet Size from the device descriptor - epInfo[0].maxPktSize = udd->bMaxPacketSize0; - - // Assign new address to the device - rcode = pUsb->setAddr(0, 0, bAddress); - - if(rcode) { - p->lowspeed = false; - addrPool.FreeAddress(bAddress); - bAddress = 0; - USBTRACE2("setAddr:", rcode); - return rcode; - } - - //delay(2); //per USB 2.0 sect.9.2.6.3 - - USBTRACE2("Addr:", bAddress); - - p->lowspeed = false; - - p = addrPool.GetUsbDevicePtr(bAddress); - - if(!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - p->lowspeed = lowspeed; - - if(len) - rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf); - - if(rcode) - goto FailGetDevDescr; - - VID = udd->idVendor; // Can be used by classes that inherits this class to check the VID and PID of the connected device - PID = udd->idProduct; - - num_of_conf = udd->bNumConfigurations; - - // Assign epInfo to epinfo pointer - rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); - - if(rcode) - goto FailSetDevTblEntry; - - USBTRACE2("NC:", num_of_conf); - - for(uint8_t i = 0; i < num_of_conf; i++) { - //HexDumper HexDump; - ConfigDescParser confDescrParser(this); - - //rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump); - rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); - - if(rcode) - goto FailGetConfDescr; - - if(bNumEP > 1) - break; - } // for - - if(bNumEP < 2) - return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - - // Assign epInfo to epinfo pointer - rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); - - USBTRACE2("Cnf:", bConfNum); - - // Set Configuration Value - rcode = pUsb->setConf(bAddress, 0, bConfNum); - - if(rcode) - goto FailSetConfDescr; - - for(uint8_t i = 0; i < bNumIface; i++) { - if(hidInterfaces[i].epIndex[epInterruptInIndex] == 0) - continue; - - rcode = SetIdle(hidInterfaces[i].bmInterface, 0, 0); - - if(rcode && rcode != hrSTALL) - goto FailSetIdle; - } - - USBTRACE("HU configured\r\n"); - - OnInitSuccessful(); - - bPollEnable = true; - return 0; - -FailGetDevDescr: -#ifdef DEBUG_USB_HOST - NotifyFailGetDevDescr(); - goto Fail; -#endif - -FailSetDevTblEntry: -#ifdef DEBUG_USB_HOST - NotifyFailSetDevTblEntry(); - goto Fail; -#endif - -FailGetConfDescr: -#ifdef DEBUG_USB_HOST - NotifyFailGetConfDescr(); - goto Fail; -#endif - -FailSetConfDescr: -#ifdef DEBUG_USB_HOST - NotifyFailSetConfDescr(); - goto Fail; -#endif - - -FailSetIdle: -#ifdef DEBUG_USB_HOST - USBTRACE("SetIdle:"); -#endif - -#ifdef DEBUG_USB_HOST -Fail: - NotifyFail(rcode); -#endif - Release(); - return rcode; -} - -HIDUniversal::HIDInterface* HIDUniversal::FindInterface(uint8_t iface, uint8_t alt, uint8_t proto) { - for(uint8_t i = 0; i < bNumIface && i < maxHidInterfaces; i++) - if(hidInterfaces[i].bmInterface == iface && hidInterfaces[i].bmAltSet == alt - && hidInterfaces[i].bmProtocol == proto) - return hidInterfaces + i; - return NULL; -} - -void HIDUniversal::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) { - // If the first configuration satisfies, the others are not concidered. - if(bNumEP > 1 && conf != bConfNum) - return; - - //ErrorMessage(PSTR("\r\nConf.Val"), conf); - //ErrorMessage(PSTR("Iface Num"), iface); - //ErrorMessage(PSTR("Alt.Set"), alt); - - bConfNum = conf; - - uint8_t index = 0; - HIDInterface *piface = FindInterface(iface, alt, proto); - - // Fill in interface structure in case of new interface - if(!piface) { - piface = hidInterfaces + bNumIface; - piface->bmInterface = iface; - piface->bmAltSet = alt; - piface->bmProtocol = proto; - bNumIface++; - } - - if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) - index = epInterruptInIndex; - else - index = epInterruptOutIndex; - - if(index) { - // Fill in the endpoint info structure - epInfo[bNumEP].epAddr = (pep->bEndpointAddress & 0x0F); - epInfo[bNumEP].maxPktSize = (uint8_t)pep->wMaxPacketSize; - epInfo[bNumEP].epAttribs = 0; - epInfo[bNumEP].bmNakPower = USB_NAK_NOWAIT; - - // Fill in the endpoint index list - piface->epIndex[index] = bNumEP; //(pep->bEndpointAddress & 0x0F); - - if(pollInterval < pep->bInterval) // Set the polling interval as the largest polling interval obtained from endpoints - pollInterval = pep->bInterval; - - bNumEP++; - } - //PrintEndpointDescriptor(pep); -} - -uint8_t HIDUniversal::Release() { - pUsb->GetAddressPool().FreeAddress(bAddress); - - bNumEP = 1; - bAddress = 0; - qNextPollTime = 0; - bPollEnable = false; - return 0; -} - -bool HIDUniversal::BuffersIdentical(uint8_t len, uint8_t *buf1, uint8_t *buf2) { - for(uint8_t i = 0; i < len; i++) - if(buf1[i] != buf2[i]) - return false; - return true; -} - -void HIDUniversal::ZeroMemory(uint8_t len, uint8_t *buf) { - for(uint8_t i = 0; i < len; i++) - buf[i] = 0; -} - -void HIDUniversal::SaveBuffer(uint8_t len, uint8_t *src, uint8_t *dest) { - for(uint8_t i = 0; i < len; i++) - dest[i] = src[i]; -} - -uint8_t HIDUniversal::Poll() { - uint8_t rcode = 0; - - if(!bPollEnable) - return 0; - - if((long)(millis() - qNextPollTime) >= 0L) { - qNextPollTime = millis() + pollInterval; - - uint8_t buf[constBuffLen]; - - for(uint8_t i = 0; i < bNumIface; i++) { - uint8_t index = hidInterfaces[i].epIndex[epInterruptInIndex]; - uint16_t read = (uint16_t)epInfo[index].maxPktSize; - - ZeroMemory(constBuffLen, buf); - - uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[index].epAddr, &read, buf); - - if(rcode) { - if(rcode != hrNAK) - USBTRACE3("(hiduniversal.h) Poll:", rcode, 0x81); - return rcode; - } - - if(read > constBuffLen) - read = constBuffLen; - - bool identical = BuffersIdentical(read, buf, prevBuf); - - SaveBuffer(read, buf, prevBuf); - - if(identical) - return 0; -#if 0 - Notify(PSTR("\r\nBuf: "), 0x80); - - for(uint8_t i = 0; i < read; i++) { - D_PrintHex (buf[i], 0x80); - Notify(PSTR(" "), 0x80); - } - - Notify(PSTR("\r\n"), 0x80); -#endif - ParseHIDData(this, bHasReportId, (uint8_t)read, buf); - - HIDReportParser *prs = GetReportParser(((bHasReportId) ? *buf : 0)); - - if(prs) - prs->Parse(this, bHasReportId, (uint8_t)read, buf); - } - } - return rcode; -} - -// Send a report to interrupt out endpoint. This is NOT SetReport() request! -uint8_t HIDUniversal::SndRpt(uint16_t nbytes, uint8_t *dataptr) { - return pUsb->outTransfer(bAddress, epInfo[epInterruptOutIndex].epAddr, nbytes, dataptr); -} \ No newline at end of file diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hiduniversal.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hiduniversal.h deleted file mode 100644 index d7af384068..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hiduniversal.h +++ /dev/null @@ -1,108 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ - -#if !defined(__HIDUNIVERSAL_H__) -#define __HIDUNIVERSAL_H__ - -#include "hid.h" -//#include "hidescriptorparser.h" - -class HIDUniversal : public HID { - - struct ReportParser { - uint8_t rptId; - HIDReportParser *rptParser; - } rptParsers[MAX_REPORT_PARSERS]; - - // HID class specific descriptor type and length info obtained from HID descriptor - HID_CLASS_DESCRIPTOR_LEN_AND_TYPE descrInfo[HID_MAX_HID_CLASS_DESCRIPTORS]; - - // Returns HID class specific descriptor length by its type and order number - uint16_t GetHidClassDescrLen(uint8_t type, uint8_t num); - - struct HIDInterface { - struct { - uint8_t bmInterface : 3; - uint8_t bmAltSet : 3; - uint8_t bmProtocol : 2; - }; - uint8_t epIndex[maxEpPerInterface]; - }; - - uint8_t bConfNum; // configuration number - uint8_t bNumIface; // number of interfaces in the configuration - uint8_t bNumEP; // total number of EP in the configuration - uint32_t qNextPollTime; // next poll time - uint8_t pollInterval; - bool bPollEnable; // poll enable flag - - static const uint16_t constBuffLen = 64; // event buffer length - uint8_t prevBuf[constBuffLen]; // previous event buffer - - void Initialize(); - HIDInterface* FindInterface(uint8_t iface, uint8_t alt, uint8_t proto); - - void ZeroMemory(uint8_t len, uint8_t *buf); - bool BuffersIdentical(uint8_t len, uint8_t *buf1, uint8_t *buf2); - void SaveBuffer(uint8_t len, uint8_t *src, uint8_t *dest); - -protected: - EpInfo epInfo[totalEndpoints]; - HIDInterface hidInterfaces[maxHidInterfaces]; - - bool bHasReportId; - - uint16_t PID, VID; // PID and VID of connected device - - // HID implementation - HIDReportParser* GetReportParser(uint8_t id); - - virtual uint8_t OnInitSuccessful() { - return 0; - }; - - virtual void ParseHIDData(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) { - return; - }; - -public: - HIDUniversal(USB *p); - - // HID implementation - bool SetReportParser(uint8_t id, HIDReportParser *prs); - - // USBDeviceConfig implementation - uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); - uint8_t Release(); - uint8_t Poll(); - - virtual uint8_t GetAddress() { - return bAddress; - }; - - virtual bool isReady() { - return bPollEnable; - }; - - // UsbConfigXtracter implementation - void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); - - // Send report - do not mix with SetReport()! - uint8_t SndRpt(uint16_t nbytes, uint8_t *dataptr); -}; - -#endif // __HIDUNIVERSAL_H__ diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidusagestr.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidusagestr.h deleted file mode 100644 index 5ef48f925b..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidusagestr.h +++ /dev/null @@ -1,977 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ -#if !defined( __HIDUSAGESTR_H__) -#define __HIDUSAGESTR_H__ - -#include "Usb.h" - -const char pstrSpace [] PROGMEM = " "; -const char pstrCRLF [] PROGMEM = "\r\n"; -const char pstrSingleTab [] PROGMEM = "\t"; -const char pstrDoubleTab [] PROGMEM = "\t\t"; -const char pstrTripleTab [] PROGMEM = "\t\t\t"; - -// Usage Page String Titles -const char pstrUsagePageUndefined [] PROGMEM = "Undef"; -const char pstrUsagePageGenericDesktopControls [] PROGMEM = "Gen Desktop Ctrls"; -const char pstrUsagePageSimulationControls [] PROGMEM = "Simu Ctrls"; -const char pstrUsagePageVRControls [] PROGMEM = "VR Ctrls"; -const char pstrUsagePageSportControls [] PROGMEM = "Sport Ctrls"; -const char pstrUsagePageGameControls [] PROGMEM = "Game Ctrls"; -const char pstrUsagePageGenericDeviceControls [] PROGMEM = "Gen Dev Ctrls"; -const char pstrUsagePageKeyboardKeypad [] PROGMEM = "Kbrd/Keypad"; -const char pstrUsagePageLEDs [] PROGMEM = "LEDs"; -const char pstrUsagePageButton [] PROGMEM = "Button"; -const char pstrUsagePageOrdinal [] PROGMEM = "Ordinal"; -const char pstrUsagePageTelephone [] PROGMEM = "Tel"; -const char pstrUsagePageConsumer [] PROGMEM = "Consumer"; -const char pstrUsagePageDigitizer [] PROGMEM = "Digitizer"; -const char pstrUsagePagePID [] PROGMEM = "PID"; -const char pstrUsagePageUnicode [] PROGMEM = "Unicode"; -const char pstrUsagePageAlphaNumericDisplay [] PROGMEM = "Alpha Num Disp"; -const char pstrUsagePageMedicalInstruments [] PROGMEM = "Medical Instr"; -const char pstrUsagePageMonitor [] PROGMEM = "Monitor"; -const char pstrUsagePagePower [] PROGMEM = "Power"; -const char pstrUsagePageBarCodeScanner [] PROGMEM = "Bar Code Scan"; -const char pstrUsagePageScale [] PROGMEM = "Scale"; -const char pstrUsagePageMSRDevices [] PROGMEM = "Magn Stripe Read Dev"; -const char pstrUsagePagePointOfSale [] PROGMEM = "POS"; -const char pstrUsagePageCameraControl [] PROGMEM = "Cam Ctrl"; -const char pstrUsagePageArcade [] PROGMEM = "Arcade"; -const char pstrUsagePageReserved [] PROGMEM = "Reserved"; -const char pstrUsagePageVendorDefined [] PROGMEM = "Vendor Def"; - -// Generic Desktop Controls Page -const char pstrUsagePointer [] PROGMEM = "Pointer"; -const char pstrUsageMouse [] PROGMEM = "Mouse"; -const char pstrUsageJoystick [] PROGMEM = "Joystick"; -const char pstrUsageGamePad [] PROGMEM = "Game Pad"; -const char pstrUsageKeyboard [] PROGMEM = "Kbrd"; -const char pstrUsageKeypad [] PROGMEM = "Keypad"; -const char pstrUsageMultiAxisController [] PROGMEM = "Multi-axis Ctrl"; -const char pstrUsageTabletPCSystemControls [] PROGMEM = "Tablet PC Sys Ctrls"; -const char pstrUsageX [] PROGMEM = "X"; -const char pstrUsageY [] PROGMEM = "Y"; -const char pstrUsageZ [] PROGMEM = "Z"; -const char pstrUsageRx [] PROGMEM = "Rx"; -const char pstrUsageRy [] PROGMEM = "Ry"; -const char pstrUsageRz [] PROGMEM = "Rz"; -const char pstrUsageSlider [] PROGMEM = "Slider"; -const char pstrUsageDial [] PROGMEM = "Dial"; -const char pstrUsageWheel [] PROGMEM = "Wheel"; -const char pstrUsageHatSwitch [] PROGMEM = "Hat Switch"; -const char pstrUsageCountedBuffer [] PROGMEM = "Counted Buf"; -const char pstrUsageByteCount [] PROGMEM = "Byte Count"; -const char pstrUsageMotionWakeup [] PROGMEM = "Motion Wakeup"; -const char pstrUsageStart [] PROGMEM = "Start"; -const char pstrUsageSelect [] PROGMEM = "Sel"; -const char pstrUsageVx [] PROGMEM = "Vx"; -const char pstrUsageVy [] PROGMEM = "Vy"; -const char pstrUsageVz [] PROGMEM = "Vz"; -const char pstrUsageVbrx [] PROGMEM = "Vbrx"; -const char pstrUsageVbry [] PROGMEM = "Vbry"; -const char pstrUsageVbrz [] PROGMEM = "Vbrz"; -const char pstrUsageVno [] PROGMEM = "Vno"; -const char pstrUsageFeatureNotification [] PROGMEM = "Feature Notif"; -const char pstrUsageResolutionMultiplier [] PROGMEM = "Res Mult"; -const char pstrUsageSystemControl [] PROGMEM = "Sys Ctrl"; -const char pstrUsageSystemPowerDown [] PROGMEM = "Sys Pwr Down"; -const char pstrUsageSystemSleep [] PROGMEM = "Sys Sleep"; -const char pstrUsageSystemWakeup [] PROGMEM = "Sys Wakeup"; -const char pstrUsageSystemContextMenu [] PROGMEM = "Sys Context Menu"; -const char pstrUsageSystemMainMenu [] PROGMEM = "Sys Main Menu"; -const char pstrUsageSystemAppMenu [] PROGMEM = "Sys App Menu"; -const char pstrUsageSystemMenuHelp [] PROGMEM = "Sys Menu Help"; -const char pstrUsageSystemMenuExit [] PROGMEM = "Sys Menu Exit"; -const char pstrUsageSystemMenuSelect [] PROGMEM = "Sys Menu Select"; -const char pstrUsageSystemMenuRight [] PROGMEM = "Sys Menu Right"; -const char pstrUsageSystemMenuLeft [] PROGMEM = "Sys Menu Left"; -const char pstrUsageSystemMenuUp [] PROGMEM = "Sys Menu Up"; -const char pstrUsageSystemMenuDown [] PROGMEM = "Sys Menu Down"; -const char pstrUsageSystemColdRestart [] PROGMEM = "Sys Cold Restart"; -const char pstrUsageSystemWarmRestart [] PROGMEM = "Sys Warm Restart"; -const char pstrUsageDPadUp [] PROGMEM = "D-pad Up"; -const char pstrUsageDPadDown [] PROGMEM = "D-pad Down"; -const char pstrUsageDPadRight [] PROGMEM = "D-pad Right"; -const char pstrUsageDPadLeft [] PROGMEM = "D-pad Left"; -const char pstrUsageSystemDock [] PROGMEM = "Sys Dock"; -const char pstrUsageSystemUndock [] PROGMEM = "Sys Undock"; -const char pstrUsageSystemSetup [] PROGMEM = "Sys Setup"; -const char pstrUsageSystemBreak [] PROGMEM = "Sys Break"; -const char pstrUsageSystemDebuggerBreak [] PROGMEM = "Sys Dbg Brk"; -const char pstrUsageApplicationBreak [] PROGMEM = "App Break"; -const char pstrUsageApplicationDebuggerBreak [] PROGMEM = "App Dbg Brk"; -const char pstrUsageSystemSpeakerMute [] PROGMEM = "Sys Spk Mute"; -const char pstrUsageSystemHibernate [] PROGMEM = "Sys Hiber"; -const char pstrUsageSystemDisplayInvert [] PROGMEM = "Sys Disp Inv"; -const char pstrUsageSystemDisplayInternal [] PROGMEM = "Sys Disp Int"; -const char pstrUsageSystemDisplayExternal [] PROGMEM = "Sys Disp Ext"; -const char pstrUsageSystemDisplayBoth [] PROGMEM = "Sys Disp Both"; -const char pstrUsageSystemDisplayDual [] PROGMEM = "Sys Disp Dual"; -const char pstrUsageSystemDisplayToggleIntExt [] PROGMEM = "Sys Disp Tgl Int/Ext"; -const char pstrUsageSystemDisplaySwapPriSec [] PROGMEM = "Sys Disp Swap Pri/Sec"; -const char pstrUsageSystemDisplayLCDAutoscale [] PROGMEM = "Sys Disp LCD Autoscale"; - -// Simulation Controls Page -const char pstrUsageFlightSimulationDevice [] PROGMEM = "Flight Simu Dev"; -const char pstrUsageAutomobileSimulationDevice [] PROGMEM = "Auto Simu Dev"; -const char pstrUsageTankSimulationDevice [] PROGMEM = "Tank Simu Dev"; -const char pstrUsageSpaceshipSimulationDevice [] PROGMEM = "Space Simu Dev"; -const char pstrUsageSubmarineSimulationDevice [] PROGMEM = "Subm Simu Dev"; -const char pstrUsageSailingSimulationDevice [] PROGMEM = "Sail Simu Dev"; -const char pstrUsageMotocicleSimulationDevice [] PROGMEM = "Moto Simu Dev"; -const char pstrUsageSportsSimulationDevice [] PROGMEM = "Sport Simu Dev"; -const char pstrUsageAirplaneSimulationDevice [] PROGMEM = "Airp Simu Dev"; -const char pstrUsageHelicopterSimulationDevice [] PROGMEM = "Heli Simu Dev"; -const char pstrUsageMagicCarpetSimulationDevice [] PROGMEM = "Magic Carpet Simu Dev"; -const char pstrUsageBicycleSimulationDevice [] PROGMEM = "Bike Simu Dev"; -const char pstrUsageFlightControlStick [] PROGMEM = "Flight Ctrl Stick"; -const char pstrUsageFlightStick [] PROGMEM = "Flight Stick"; -const char pstrUsageCyclicControl [] PROGMEM = "Cyclic Ctrl"; -const char pstrUsageCyclicTrim [] PROGMEM = "Cyclic Trim"; -const char pstrUsageFlightYoke [] PROGMEM = "Flight Yoke"; -const char pstrUsageTrackControl [] PROGMEM = "Track Ctrl"; -const char pstrUsageAileron [] PROGMEM = "Aileron"; -const char pstrUsageAileronTrim [] PROGMEM = "Aileron Trim"; -const char pstrUsageAntiTorqueControl [] PROGMEM = "Anti-Torque Ctrl"; -const char pstrUsageAutopilotEnable [] PROGMEM = "Autopilot Enable"; -const char pstrUsageChaffRelease [] PROGMEM = "Chaff Release"; -const char pstrUsageCollectiveControl [] PROGMEM = "Collective Ctrl"; -const char pstrUsageDiveBrake [] PROGMEM = "Dive Brake"; -const char pstrUsageElectronicCountermeasures [] PROGMEM = "El Countermeasures"; -const char pstrUsageElevator [] PROGMEM = "Elevator"; -const char pstrUsageElevatorTrim [] PROGMEM = "Elevator Trim"; -const char pstrUsageRudder [] PROGMEM = "Rudder"; -const char pstrUsageThrottle [] PROGMEM = "Throttle"; -const char pstrUsageFlightCommunications [] PROGMEM = "Flight Comm"; -const char pstrUsageFlareRelease [] PROGMEM = "Flare Release"; -const char pstrUsageLandingGear [] PROGMEM = "Landing Gear"; -const char pstrUsageToeBrake [] PROGMEM = "Toe Brake"; -const char pstrUsageTrigger [] PROGMEM = "Trigger"; -const char pstrUsageWeaponsArm [] PROGMEM = "Weapons Arm"; -const char pstrUsageWeaponsSelect [] PROGMEM = "Weapons Sel"; -const char pstrUsageWingFlaps [] PROGMEM = "Wing Flaps"; -const char pstrUsageAccelerator [] PROGMEM = "Accel"; -const char pstrUsageBrake [] PROGMEM = "Brake"; -const char pstrUsageClutch [] PROGMEM = "Clutch"; -const char pstrUsageShifter [] PROGMEM = "Shifter"; -const char pstrUsageSteering [] PROGMEM = "Steering"; -const char pstrUsageTurretDirection [] PROGMEM = "Turret Dir"; -const char pstrUsageBarrelElevation [] PROGMEM = "Barrel Ele"; -const char pstrUsageDivePlane [] PROGMEM = "Dive Plane"; -const char pstrUsageBallast [] PROGMEM = "Ballast"; -const char pstrUsageBicycleCrank [] PROGMEM = "Bicycle Crank"; -const char pstrUsageHandleBars [] PROGMEM = "Handle Bars"; -const char pstrUsageFrontBrake [] PROGMEM = "Front Brake"; -const char pstrUsageRearBrake [] PROGMEM = "Rear Brake"; - -// VR Controls Page -const char pstrUsageBelt [] PROGMEM = "Belt"; -const char pstrUsageBodySuit [] PROGMEM = "Body Suit"; -const char pstrUsageFlexor [] PROGMEM = "Flexor"; -const char pstrUsageGlove [] PROGMEM = "Glove"; -const char pstrUsageHeadTracker [] PROGMEM = "Head Track"; -const char pstrUsageHeadMountedDisplay [] PROGMEM = "Head Disp"; -const char pstrUsageHandTracker [] PROGMEM = "Hand Track"; -const char pstrUsageOculometer [] PROGMEM = "Oculometer"; -const char pstrUsageVest [] PROGMEM = "Vest"; -const char pstrUsageAnimatronicDevice [] PROGMEM = "Animat Dev"; -const char pstrUsageStereoEnable [] PROGMEM = "Stereo Enbl"; -const char pstrUsageDisplayEnable [] PROGMEM = "Display Enbl"; - -// Sport Controls Page -const char pstrUsageBaseballBat [] PROGMEM = "Baseball Bat"; -const char pstrUsageGolfClub [] PROGMEM = "Golf Club"; -const char pstrUsageRowingMachine [] PROGMEM = "Rowing Mach"; -const char pstrUsageTreadmill [] PROGMEM = "Treadmill"; -const char pstrUsageOar [] PROGMEM = "Oar"; -const char pstrUsageSlope [] PROGMEM = "Slope"; -const char pstrUsageRate [] PROGMEM = "Rate"; -const char pstrUsageStickSpeed [] PROGMEM = "Stick Speed"; -const char pstrUsageStickFaceAngle [] PROGMEM = "Stick Face Ang"; -const char pstrUsageStickHeelToe [] PROGMEM = "Stick Heel/Toe"; -const char pstrUsageStickFollowThough [] PROGMEM = "Stick Flw Thru"; -const char pstrUsageStickTempo [] PROGMEM = "Stick Tempo"; -const char pstrUsageStickType [] PROGMEM = "Stick Type"; -const char pstrUsageStickHeight [] PROGMEM = "Stick Hght"; -const char pstrUsagePutter [] PROGMEM = "Putter"; -const char pstrUsage1Iron [] PROGMEM = "1 Iron"; -const char pstrUsage2Iron [] PROGMEM = "2 Iron"; -const char pstrUsage3Iron [] PROGMEM = "3 Iron"; -const char pstrUsage4Iron [] PROGMEM = "4 Iron"; -const char pstrUsage5Iron [] PROGMEM = "5 Iron"; -const char pstrUsage6Iron [] PROGMEM = "6 Iron"; -const char pstrUsage7Iron [] PROGMEM = "7 Iron"; -const char pstrUsage8Iron [] PROGMEM = "8 Iron"; -const char pstrUsage9Iron [] PROGMEM = "9 Iron"; -const char pstrUsage10Iron [] PROGMEM = "10 Iron"; -const char pstrUsage11Iron [] PROGMEM = "11 Iron"; -const char pstrUsageSandWedge [] PROGMEM = "Sand Wedge"; -const char pstrUsageLoftWedge [] PROGMEM = "Loft Wedge"; -const char pstrUsagePowerWedge [] PROGMEM = "Pwr Wedge"; -const char pstrUsage1Wood [] PROGMEM = "1 Wood"; -const char pstrUsage3Wood [] PROGMEM = "3 Wood"; -const char pstrUsage5Wood [] PROGMEM = "5 Wood"; -const char pstrUsage7Wood [] PROGMEM = "7 Wood"; -const char pstrUsage9Wood [] PROGMEM = "9 Wood"; - -// Game Controls Page -const char pstrUsage3DGameController [] PROGMEM = "3D Game Ctrl"; -const char pstrUsagePinballDevice [] PROGMEM = "Pinball Dev"; -const char pstrUsageGunDevice [] PROGMEM = "Gun Dev"; -const char pstrUsagePointOfView [] PROGMEM = "POV"; -const char pstrUsageTurnRightLeft [] PROGMEM = "Turn Right Left"; -const char pstrUsagePitchForwardBackward [] PROGMEM = "Pitch Fwd/Back"; -const char pstrUsageRollRightLeft [] PROGMEM = "Roll Right/Left"; -const char pstrUsageMoveRightLeft [] PROGMEM = "Move Right/Left"; -const char pstrUsageMoveForwardBackward [] PROGMEM = "Move Fwd/Back"; -const char pstrUsageMoveUpDown [] PROGMEM = "Move Up/Down"; -const char pstrUsageLeanRightLeft [] PROGMEM = "Lean Right/Left"; -const char pstrUsageLeanForwardBackward [] PROGMEM = "Lean Fwd/Back"; -const char pstrUsageHeightOfPOV [] PROGMEM = "Height of POV"; -const char pstrUsageFlipper [] PROGMEM = "Flipper"; -const char pstrUsageSecondaryFlipper [] PROGMEM = "Second Flipper"; -const char pstrUsageBump [] PROGMEM = "Bump"; -const char pstrUsageNewGame [] PROGMEM = "New Game"; -const char pstrUsageShootBall [] PROGMEM = "Shoot Ball"; -const char pstrUsagePlayer [] PROGMEM = "Player"; -const char pstrUsageGunBolt [] PROGMEM = "Gun Bolt"; -const char pstrUsageGunClip [] PROGMEM = "Gun Clip"; -const char pstrUsageGunSelector [] PROGMEM = "Gun Sel"; -const char pstrUsageGunSingleShot [] PROGMEM = "Gun Sngl Shot"; -const char pstrUsageGunBurst [] PROGMEM = "Gun Burst"; -const char pstrUsageGunAutomatic [] PROGMEM = "Gun Auto"; -const char pstrUsageGunSafety [] PROGMEM = "Gun Safety"; -const char pstrUsageGamepadFireJump [] PROGMEM = "Gamepad Fire/Jump"; -const char pstrUsageGamepadTrigger [] PROGMEM = "Gamepad Trig"; - -// Generic Device Controls Page -const char pstrUsageBatteryStrength [] PROGMEM = "Bat Strength"; -const char pstrUsageWirelessChannel [] PROGMEM = "Wireless Ch"; -const char pstrUsageWirelessID [] PROGMEM = "Wireless ID"; -const char pstrUsageDiscoverWirelessControl [] PROGMEM = "Discover Wireless Ctrl"; -const char pstrUsageSecurityCodeCharEntered [] PROGMEM = "Sec Code Char Entrd"; -const char pstrUsageSecurityCodeCharErased [] PROGMEM = "Sec Code Char Erased"; -const char pstrUsageSecurityCodeCleared [] PROGMEM = "Sec Code Cleared"; - -// LED Page -const char pstrUsageNumLock [] PROGMEM = "Num Lock"; -const char pstrUsageCapsLock [] PROGMEM = "Caps Lock"; -const char pstrUsageScrollLock [] PROGMEM = "Scroll Lock"; -const char pstrUsageCompose [] PROGMEM = "Compose"; -const char pstrUsageKana [] PROGMEM = "Kana"; -const char pstrUsagePower [] PROGMEM = "Pwr"; -const char pstrUsageShift [] PROGMEM = "Shift"; -const char pstrUsageDoNotDisturb [] PROGMEM = "DND"; -const char pstrUsageMute [] PROGMEM = "Mute"; -const char pstrUsageToneEnable [] PROGMEM = "Tone Enbl"; -const char pstrUsageHighCutFilter [] PROGMEM = "High Cut Fltr"; -const char pstrUsageLowCutFilter [] PROGMEM = "Low Cut Fltr"; -const char pstrUsageEqualizerEnable [] PROGMEM = "Eq Enbl"; -const char pstrUsageSoundFieldOn [] PROGMEM = "Sound Field On"; -const char pstrUsageSurroundOn [] PROGMEM = "Surround On"; -const char pstrUsageRepeat [] PROGMEM = "Repeat"; -const char pstrUsageStereo [] PROGMEM = "Stereo"; -const char pstrUsageSamplingRateDetect [] PROGMEM = "Smpl Rate Detect"; -const char pstrUsageSpinning [] PROGMEM = "Spinning"; -const char pstrUsageCAV [] PROGMEM = "CAV"; -const char pstrUsageCLV [] PROGMEM = "CLV"; -const char pstrUsageRecordingFormatDetect [] PROGMEM = "Rec Format Detect"; -const char pstrUsageOffHook [] PROGMEM = "Off Hook"; -const char pstrUsageRing [] PROGMEM = "Ring"; -const char pstrUsageMessageWaiting [] PROGMEM = "Msg Wait"; -const char pstrUsageDataMode [] PROGMEM = "Data Mode"; -const char pstrUsageBatteryOperation [] PROGMEM = "Bat Op"; -const char pstrUsageBatteryOK [] PROGMEM = "Bat OK"; -const char pstrUsageBatteryLow [] PROGMEM = "Bat Low"; -const char pstrUsageSpeaker [] PROGMEM = "Speaker"; -const char pstrUsageHeadSet [] PROGMEM = "Head Set"; -const char pstrUsageHold [] PROGMEM = "Hold"; -const char pstrUsageMicrophone [] PROGMEM = "Mic"; -const char pstrUsageCoverage [] PROGMEM = "Coverage"; -const char pstrUsageNightMode [] PROGMEM = "Night Mode"; -const char pstrUsageSendCalls [] PROGMEM = "Send Calls"; -const char pstrUsageCallPickup [] PROGMEM = "Call Pickup"; -const char pstrUsageConference [] PROGMEM = "Conf"; -const char pstrUsageStandBy [] PROGMEM = "Stand-by"; -const char pstrUsageCameraOn [] PROGMEM = "Cam On"; -const char pstrUsageCameraOff [] PROGMEM = "Cam Off"; -const char pstrUsageOnLine [] PROGMEM = "On-Line"; -const char pstrUsageOffLine [] PROGMEM = "Off-Line"; -const char pstrUsageBusy [] PROGMEM = "Busy"; -const char pstrUsageReady [] PROGMEM = "Ready"; -const char pstrUsagePaperOut [] PROGMEM = "Paper Out"; -const char pstrUsagePaperJam [] PROGMEM = "Paper Jam"; -const char pstrUsageRemote [] PROGMEM = "Remote"; -const char pstrUsageForward [] PROGMEM = "Fwd"; -const char pstrUsageReverse [] PROGMEM = "Rev"; -const char pstrUsageStop [] PROGMEM = "Stop"; -const char pstrUsageRewind [] PROGMEM = "Rewind"; -const char pstrUsageFastForward [] PROGMEM = "Fast Fwd"; -const char pstrUsagePlay [] PROGMEM = "Play"; -const char pstrUsagePause [] PROGMEM = "Pause"; -const char pstrUsageRecord [] PROGMEM = "Rec"; -const char pstrUsageError [] PROGMEM = "Error"; -const char pstrUsageSelectedIndicator [] PROGMEM = "Usage Sel Ind"; -const char pstrUsageInUseIndicator [] PROGMEM = "Usage In Use Ind"; -const char pstrUsageMultiModeIndicator [] PROGMEM = "Usage Multi Mode Ind"; -const char pstrUsageIndicatorOn [] PROGMEM = "Ind On"; -const char pstrUsageIndicatorFlash [] PROGMEM = "Ind Flash"; -const char pstrUsageIndicatorSlowBlink [] PROGMEM = "Ind Slow Blk"; -const char pstrUsageIndicatorFastBlink [] PROGMEM = "Ind Fast Blk"; -const char pstrUsageIndicatorOff [] PROGMEM = "Ind Off"; -const char pstrUsageFlashOnTime [] PROGMEM = "Flash On Time"; -const char pstrUsageSlowBlinkOnTime [] PROGMEM = "Slow Blk On Time"; -const char pstrUsageSlowBlinkOffTime [] PROGMEM = "Slow Blk Off Time"; -const char pstrUsageFastBlinkOnTime [] PROGMEM = "Fast Blk On Time"; -const char pstrUsageFastBlinkOffTime [] PROGMEM = "Fast Blk Off Time"; -const char pstrUsageIndicatorColor [] PROGMEM = "Usage Ind Color"; -const char pstrUsageIndicatorRed [] PROGMEM = "Ind Red"; -const char pstrUsageIndicatorGreen [] PROGMEM = "Ind Green"; -const char pstrUsageIndicatorAmber [] PROGMEM = "Ind Amber"; -const char pstrUsageGenericIndicator [] PROGMEM = "Gen Ind"; -const char pstrUsageSystemSuspend [] PROGMEM = "Sys Suspend"; -const char pstrUsageExternalPowerConnected [] PROGMEM = "Ext Pwr Conn"; - -// Telephony Usage Page -const char pstrUsagePhone [] PROGMEM = "Phone"; -const char pstrUsageAnsweringMachine [] PROGMEM = "Answ Mach"; -const char pstrUsageMessageControls [] PROGMEM = "Msg Ctrls"; -const char pstrUsageHandset [] PROGMEM = "Handset"; -const char pstrUsageHeadset [] PROGMEM = "Headset"; -const char pstrUsageTelephonyKeyPad [] PROGMEM = "Tel Key Pad"; -const char pstrUsageProgrammableButton [] PROGMEM = "Prog Button"; -const char pstrUsageHookSwitch [] PROGMEM = "Hook Sw"; -const char pstrUsageFlash [] PROGMEM = "Flash"; -const char pstrUsageFeature [] PROGMEM = "Feature"; -//const char pstrUsageHold [] PROGMEM = "Hold"; -const char pstrUsageRedial [] PROGMEM = "Redial"; -const char pstrUsageTransfer [] PROGMEM = "Transfer"; -const char pstrUsageDrop [] PROGMEM = "Drop"; -const char pstrUsagePark [] PROGMEM = "Park"; -const char pstrUsageForwardCalls [] PROGMEM = "Fwd Calls"; -const char pstrUsageAlternateFunction [] PROGMEM = "Alt Func"; -const char pstrUsageLine [] PROGMEM = "Line"; -const char pstrUsageSpeakerPhone [] PROGMEM = "Spk Phone"; -//const char pstrUsageConference [] PROGMEM = "Conference"; -const char pstrUsageRingEnable [] PROGMEM = "Ring Enbl"; -const char pstrUsageRingSelect [] PROGMEM = "Ring Sel"; -const char pstrUsagePhoneMute [] PROGMEM = "Phone Mute"; -const char pstrUsageCallerID [] PROGMEM = "Caller ID"; -const char pstrUsageSend [] PROGMEM = "Send"; -const char pstrUsageSpeedDial [] PROGMEM = "Speed Dial"; -const char pstrUsageStoreNumber [] PROGMEM = "Store Num"; -const char pstrUsageRecallNumber [] PROGMEM = "Recall Num"; -const char pstrUsagePhoneDirectory [] PROGMEM = "Phone Dir"; -const char pstrUsageVoiceMail [] PROGMEM = "Voice Mail"; -const char pstrUsageScreenCalls [] PROGMEM = "Screen Calls"; -//const char pstrUsageDoNotDisturb [] PROGMEM = "Do Not Disturb"; -const char pstrUsageMessage [] PROGMEM = "Msg"; -const char pstrUsageAnswerOnOff [] PROGMEM = "Answer On/Off"; -const char pstrUsageInsideDialTone [] PROGMEM = "Inside Dial Tone"; -const char pstrUsageOutsideDialTone [] PROGMEM = "Outside Dial Tone"; -const char pstrUsageInsideRingTone [] PROGMEM = "Inside Ring Tone"; -const char pstrUsageOutsideRingTone [] PROGMEM = "Outside Ring Tone"; -const char pstrUsagePriorityRingTone [] PROGMEM = "Prior Ring Tone"; -const char pstrUsageInsideRingback [] PROGMEM = "Inside Ringback"; -const char pstrUsagePriorityRingback [] PROGMEM = "Priority Ringback"; -const char pstrUsageLineBusyTone [] PROGMEM = "Ln Busy Tone"; -const char pstrUsageReorderTone [] PROGMEM = "Reorder Tone"; -const char pstrUsageCallWaitingTone [] PROGMEM = "Call Wait Tone"; -const char pstrUsageConfirmationTone1 [] PROGMEM = "Cnfrm Tone1"; -const char pstrUsageConfirmationTone2 [] PROGMEM = "Cnfrm Tone2"; -const char pstrUsageTonesOff [] PROGMEM = "Tones Off"; -const char pstrUsageOutsideRingback [] PROGMEM = "Outside Ringback"; -const char pstrUsageRinger [] PROGMEM = "Ringer"; -const char pstrUsagePhoneKey0 [] PROGMEM = "0"; -const char pstrUsagePhoneKey1 [] PROGMEM = "1"; -const char pstrUsagePhoneKey2 [] PROGMEM = "2"; -const char pstrUsagePhoneKey3 [] PROGMEM = "3"; -const char pstrUsagePhoneKey4 [] PROGMEM = "4"; -const char pstrUsagePhoneKey5 [] PROGMEM = "5"; -const char pstrUsagePhoneKey6 [] PROGMEM = "6"; -const char pstrUsagePhoneKey7 [] PROGMEM = "7"; -const char pstrUsagePhoneKey8 [] PROGMEM = "8"; -const char pstrUsagePhoneKey9 [] PROGMEM = "9"; -const char pstrUsagePhoneKeyStar [] PROGMEM = "*"; -const char pstrUsagePhoneKeyPound [] PROGMEM = "#"; -const char pstrUsagePhoneKeyA [] PROGMEM = "A"; -const char pstrUsagePhoneKeyB [] PROGMEM = "B"; -const char pstrUsagePhoneKeyC [] PROGMEM = "C"; -const char pstrUsagePhoneKeyD [] PROGMEM = "D"; - -// Consumer Usage Page -const char pstrUsageConsumerControl [] PROGMEM = "Consumer Ctrl"; -const char pstrUsageNumericKeyPad [] PROGMEM = "Num Key Pad"; -//const char pstrUsageProgrammableButton [] PROGMEM = "Prog Btn"; -//const char pstrUsageMicrophone [] PROGMEM = "Mic"; -const char pstrUsageHeadphone [] PROGMEM = "Headphone"; -const char pstrUsageGraphicEqualizer [] PROGMEM = "Graph Eq"; -const char pstrUsagePlus10 [] PROGMEM = "+10"; -const char pstrUsagePlus100 [] PROGMEM = "+100"; -const char pstrUsageAMPM [] PROGMEM = "AM/PM"; -//const char pstrUsagePower [] PROGMEM = "Pwr"; -const char pstrUsageReset [] PROGMEM = "Reset"; -const char pstrUsageSleep [] PROGMEM = "Sleep"; -const char pstrUsageSleepAfter [] PROGMEM = "Sleep After"; -const char pstrUsageSleepMode [] PROGMEM = "Sleep Mode"; -const char pstrUsageIllumination [] PROGMEM = "Illumin"; -const char pstrUsageFunctionButtons [] PROGMEM = "Func Btns"; -const char pstrUsageMenu [] PROGMEM = "Menu"; -const char pstrUsageMenuPick [] PROGMEM = "Menu Pick"; -const char pstrUsageMenuUp [] PROGMEM = "Menu Up"; -const char pstrUsageMenuDown [] PROGMEM = "Menu Down"; -const char pstrUsageMenuLeft [] PROGMEM = "Menu Left"; -const char pstrUsageMenuRight [] PROGMEM = "Menu Right"; -const char pstrUsageMenuEscape [] PROGMEM = "Menu Esc"; -const char pstrUsageMenuValueIncrease [] PROGMEM = "Menu Val Inc"; -const char pstrUsageMenuValueDecrease [] PROGMEM = "Menu Val Dec"; -const char pstrUsageDataOnScreen [] PROGMEM = "Data On Scr"; -const char pstrUsageClosedCaption [] PROGMEM = "Closed Cptn"; -const char pstrUsageClosedCaptionSelect [] PROGMEM = "Closed Cptn Sel"; -const char pstrUsageVCRTV [] PROGMEM = "VCR/TV"; -const char pstrUsageBroadcastMode [] PROGMEM = "Brdcast Mode"; -const char pstrUsageSnapshot [] PROGMEM = "Snapshot"; -const char pstrUsageStill [] PROGMEM = "Still"; -const char pstrUsageSelection [] PROGMEM = "Sel"; -const char pstrUsageAssignSelection [] PROGMEM = "Assign Sel"; -const char pstrUsageModeStep [] PROGMEM = "Mode Step"; -const char pstrUsageRecallLast [] PROGMEM = "Recall Last"; -const char pstrUsageEnterChannel [] PROGMEM = "Entr Channel"; -const char pstrUsageOrderMovie [] PROGMEM = "Ord Movie"; -const char pstrUsageChannel [] PROGMEM = "Channel"; -const char pstrUsageMediaSelection [] PROGMEM = "Med Sel"; -const char pstrUsageMediaSelectComputer [] PROGMEM = "Med Sel Comp"; -const char pstrUsageMediaSelectTV [] PROGMEM = "Med Sel TV"; -const char pstrUsageMediaSelectWWW [] PROGMEM = "Med Sel WWW"; -const char pstrUsageMediaSelectDVD [] PROGMEM = "Med Sel DVD"; -const char pstrUsageMediaSelectTelephone [] PROGMEM = "Med Sel Tel"; -const char pstrUsageMediaSelectProgramGuide [] PROGMEM = "Med Sel PG"; -const char pstrUsageMediaSelectVideoPhone [] PROGMEM = "Med Sel Vid"; -const char pstrUsageMediaSelectGames [] PROGMEM = "Med Sel Games"; -const char pstrUsageMediaSelectMessages [] PROGMEM = "Med Sel Msg"; -const char pstrUsageMediaSelectCD [] PROGMEM = "Med Sel CD"; -const char pstrUsageMediaSelectVCR [] PROGMEM = "Med Sel VCR"; -const char pstrUsageMediaSelectTuner [] PROGMEM = "Med Sel Tuner"; -const char pstrUsageQuit [] PROGMEM = "Quit"; -const char pstrUsageHelp [] PROGMEM = "Help"; -const char pstrUsageMediaSelectTape [] PROGMEM = "Med Sel Tape"; -const char pstrUsageMediaSelectCable [] PROGMEM = "Med Sel Cbl"; -const char pstrUsageMediaSelectSatellite [] PROGMEM = "Med Sel Sat"; -const char pstrUsageMediaSelectSecurity [] PROGMEM = "Med Sel Secur"; -const char pstrUsageMediaSelectHome [] PROGMEM = "Med Sel Home"; -const char pstrUsageMediaSelectCall [] PROGMEM = "Med Sel Call"; -const char pstrUsageChannelIncrement [] PROGMEM = "Ch Inc"; -const char pstrUsageChannelDecrement [] PROGMEM = "Ch Dec"; -const char pstrUsageMediaSelectSAP [] PROGMEM = "Med Sel SAP"; -const char pstrUsageVCRPlus [] PROGMEM = "VCR+"; -const char pstrUsageOnce [] PROGMEM = "Once"; -const char pstrUsageDaily [] PROGMEM = "Daily"; -const char pstrUsageWeekly [] PROGMEM = "Weekly"; -const char pstrUsageMonthly [] PROGMEM = "Monthly"; -//const char pstrUsagePlay [] PROGMEM = "Play"; -//const char pstrUsagePause [] PROGMEM = "Pause"; -//const char pstrUsageRecord [] PROGMEM = "Rec"; -//const char pstrUsageFastForward [] PROGMEM = "FF"; -//const char pstrUsageRewind [] PROGMEM = "Rewind"; -const char pstrUsageScanNextTrack [] PROGMEM = "Next Track"; -const char pstrUsageScanPreviousTrack [] PROGMEM = "Prev Track"; -//const char pstrUsageStop [] PROGMEM = "Stop"; -const char pstrUsageEject [] PROGMEM = "Eject"; -const char pstrUsageRandomPlay [] PROGMEM = "Random"; -const char pstrUsageSelectDisk [] PROGMEM = "Sel Disk"; -const char pstrUsageEnterDisk [] PROGMEM = "Ent Disk"; -//const char pstrUsageRepeat [] PROGMEM = "Repeat"; -const char pstrUsageTracking [] PROGMEM = "Tracking"; -const char pstrUsageTrackNormal [] PROGMEM = "Trk Norm"; -const char pstrUsageSlowTracking [] PROGMEM = "Slow Trk"; -const char pstrUsageFrameForward [] PROGMEM = "Frm Fwd"; -const char pstrUsageFrameBackwards [] PROGMEM = "Frm Back"; -const char pstrUsageMark [] PROGMEM = "Mark"; -const char pstrUsageClearMark [] PROGMEM = "Clr Mark"; -const char pstrUsageRepeatFromMark [] PROGMEM = "Rpt Mark"; -const char pstrUsageReturnToMark [] PROGMEM = "Ret to Mark"; -const char pstrUsageSearchMarkForward [] PROGMEM = "Search Mark Fwd"; -const char pstrUsageSearchMarkBackwards [] PROGMEM = "Search Mark Back"; -const char pstrUsageCounterReset [] PROGMEM = "Counter Reset"; -const char pstrUsageShowCounter [] PROGMEM = "Show Counter"; -const char pstrUsageTrackingIncrement [] PROGMEM = "Track Inc"; -const char pstrUsageTrackingDecrement [] PROGMEM = "Track Dec"; -const char pstrUsageStopEject [] PROGMEM = "Stop/Eject"; -const char pstrUsagePlayPause [] PROGMEM = "Play/Pause"; -const char pstrUsagePlaySkip [] PROGMEM = "Play/Skip"; -const char pstrUsageVolume [] PROGMEM = "Vol"; -const char pstrUsageBalance [] PROGMEM = "Balance"; -//const char pstrUsageMute [] PROGMEM = "Mute"; -const char pstrUsageBass [] PROGMEM = "Bass"; -const char pstrUsageTreble [] PROGMEM = "Treble"; -const char pstrUsageBassBoost [] PROGMEM = "Bass Boost"; -const char pstrUsageSurroundMode [] PROGMEM = "Surround"; -const char pstrUsageLoudness [] PROGMEM = "Loud"; -const char pstrUsageMPX [] PROGMEM = "MPX"; -const char pstrUsageVolumeIncrement [] PROGMEM = "Vol Inc"; -const char pstrUsageVolumeDecrement [] PROGMEM = "Vol Dec"; -const char pstrUsageSpeedSelect [] PROGMEM = "Speed"; -const char pstrUsagePlaybackSpeed [] PROGMEM = "Play Speed"; -const char pstrUsageStandardPlay [] PROGMEM = "Std Play"; -const char pstrUsageLongPlay [] PROGMEM = "Long Play"; -const char pstrUsageExtendedPlay [] PROGMEM = "Ext Play"; -const char pstrUsageSlow [] PROGMEM = "Slow"; -const char pstrUsageFanEnable [] PROGMEM = "Fan Enbl"; -const char pstrUsageFanSpeed [] PROGMEM = "Fan Speed"; -const char pstrUsageLightEnable [] PROGMEM = "Light Enbl"; -const char pstrUsageLightIlluminationLevel [] PROGMEM = "Light Illum Lev"; -const char pstrUsageClimateControlEnable [] PROGMEM = "Climate Enbl"; -const char pstrUsageRoomTemperature [] PROGMEM = "Room Temp"; -const char pstrUsageSecurityEnable [] PROGMEM = "Secur Enbl"; -const char pstrUsageFireAlarm [] PROGMEM = "Fire Alm"; -const char pstrUsagePoliceAlarm [] PROGMEM = "Police Alm"; -const char pstrUsageProximity [] PROGMEM = "Prox"; -const char pstrUsageMotion [] PROGMEM = "Motion"; -const char pstrUsageDuresAlarm [] PROGMEM = "Dures Alm"; -const char pstrUsageHoldupAlarm [] PROGMEM = "Holdup Alm"; -const char pstrUsageMedicalAlarm [] PROGMEM = "Med Alm"; -const char pstrUsageBalanceRight [] PROGMEM = "Balance Right"; -const char pstrUsageBalanceLeft [] PROGMEM = "Balance Left"; -const char pstrUsageBassIncrement [] PROGMEM = "Bass Inc"; -const char pstrUsageBassDecrement [] PROGMEM = "Bass Dec"; -const char pstrUsageTrebleIncrement [] PROGMEM = "Treble Inc"; -const char pstrUsageTrebleDecrement [] PROGMEM = "Treble Dec"; -const char pstrUsageSpeakerSystem [] PROGMEM = "Spk Sys"; -const char pstrUsageChannelLeft [] PROGMEM = "Ch Left"; -const char pstrUsageChannelRight [] PROGMEM = "Ch Right"; -const char pstrUsageChannelCenter [] PROGMEM = "Ch Center"; -const char pstrUsageChannelFront [] PROGMEM = "Ch Front"; -const char pstrUsageChannelCenterFront [] PROGMEM = "Ch Cntr Front"; -const char pstrUsageChannelSide [] PROGMEM = "Ch Side"; -const char pstrUsageChannelSurround [] PROGMEM = "Ch Surround"; -const char pstrUsageChannelLowFreqEnhancement [] PROGMEM = "Ch Low Freq Enh"; -const char pstrUsageChannelTop [] PROGMEM = "Ch Top"; -const char pstrUsageChannelUnknown [] PROGMEM = "Ch Unk"; -const char pstrUsageSubChannel [] PROGMEM = "Sub-ch"; -const char pstrUsageSubChannelIncrement [] PROGMEM = "Sub-ch Inc"; -const char pstrUsageSubChannelDecrement [] PROGMEM = "Sub-ch Dec"; -const char pstrUsageAlternateAudioIncrement [] PROGMEM = "Alt Aud Inc"; -const char pstrUsageAlternateAudioDecrement [] PROGMEM = "Alt Aud Dec"; -const char pstrUsageApplicationLaunchButtons [] PROGMEM = "App Launch Btns"; -const char pstrUsageALLaunchButtonConfigTool [] PROGMEM = "AL Launch Conf Tl"; -const char pstrUsageALProgrammableButton [] PROGMEM = "AL Pgm Btn"; -const char pstrUsageALConsumerControlConfig [] PROGMEM = "AL Cons Ctrl Cfg"; -const char pstrUsageALWordProcessor [] PROGMEM = "AL Word Proc"; -const char pstrUsageALTextEditor [] PROGMEM = "AL Txt Edtr"; -const char pstrUsageALSpreadsheet [] PROGMEM = "AL Sprdsheet"; -const char pstrUsageALGraphicsEditor [] PROGMEM = "AL Graph Edtr"; -const char pstrUsageALPresentationApp [] PROGMEM = "AL Present App"; -const char pstrUsageALDatabaseApp [] PROGMEM = "AL DB App"; -const char pstrUsageALEmailReader [] PROGMEM = "AL E-mail Rdr"; -const char pstrUsageALNewsreader [] PROGMEM = "AL Newsrdr"; -const char pstrUsageALVoicemail [] PROGMEM = "AL Voicemail"; -const char pstrUsageALContactsAddressBook [] PROGMEM = "AL Addr Book"; -const char pstrUsageALCalendarSchedule [] PROGMEM = "AL Clndr/Schdlr"; -const char pstrUsageALTaskProjectManager [] PROGMEM = "AL Task/Prj Mgr"; -const char pstrUsageALLogJournalTimecard [] PROGMEM = "AL Log/Jrnl/Tmcrd"; -const char pstrUsageALCheckbookFinance [] PROGMEM = "AL Chckbook/Fin"; -const char pstrUsageALCalculator [] PROGMEM = "AL Calc"; -const char pstrUsageALAVCapturePlayback [] PROGMEM = "AL A/V Capt/Play"; -const char pstrUsageALLocalMachineBrowser [] PROGMEM = "AL Loc Mach Brow"; -const char pstrUsageALLANWANBrow [] PROGMEM = "AL LAN/WAN Brow"; -const char pstrUsageALInternetBrowser [] PROGMEM = "AL I-net Brow"; -const char pstrUsageALRemoteNetISPConnect [] PROGMEM = "AL Rem Net Con"; -const char pstrUsageALNetworkConference [] PROGMEM = "AL Net Conf"; -const char pstrUsageALNetworkChat [] PROGMEM = "AL Net Chat"; -const char pstrUsageALTelephonyDialer [] PROGMEM = "AL Tel/Dial"; -const char pstrUsageALLogon [] PROGMEM = "AL Logon"; -const char pstrUsageALLogoff [] PROGMEM = "AL Logoff"; -const char pstrUsageALLogonLogoff [] PROGMEM = "AL Logon/Logoff"; -const char pstrUsageALTermLockScrSav [] PROGMEM = "AL Term Lock/Scr Sav"; -const char pstrUsageALControlPannel [] PROGMEM = "AL Ctrl Pan"; -const char pstrUsageALCommandLineProcessorRun [] PROGMEM = "AL Cmd/Run"; -const char pstrUsageALProcessTaskManager [] PROGMEM = "AL Task Mgr"; -const char pstrUsageALSelectTaskApplication [] PROGMEM = "AL Sel App"; -const char pstrUsageALNextTaskApplication [] PROGMEM = "AL Next App"; -const char pstrUsageALPreviousTaskApplication [] PROGMEM = "AL Prev App"; -const char pstrUsageALPreemptiveHaltTaskApp [] PROGMEM = "AL Prmpt Halt App"; -const char pstrUsageALIntegratedHelpCenter [] PROGMEM = "AL Hlp Cntr"; -const char pstrUsageALDocuments [] PROGMEM = "AL Docs"; -const char pstrUsageALThesaurus [] PROGMEM = "AL Thsrs"; -const char pstrUsageALDictionary [] PROGMEM = "AL Dict"; -const char pstrUsageALDesktop [] PROGMEM = "AL Desktop"; -const char pstrUsageALSpellCheck [] PROGMEM = "AL Spell Chk"; -const char pstrUsageALGrammarCheck [] PROGMEM = "AL Gram Chk"; -const char pstrUsageALWirelessStatus [] PROGMEM = "AL Wireless Sts"; -const char pstrUsageALKeyboardLayout [] PROGMEM = "AL Kbd Layout"; -const char pstrUsageALVirusProtection [] PROGMEM = "AL Vir Protect"; -const char pstrUsageALEncryption [] PROGMEM = "AL Encrypt"; -const char pstrUsageALScreenSaver [] PROGMEM = "AL Scr Sav"; -const char pstrUsageALAlarms [] PROGMEM = "AL Alarms"; -const char pstrUsageALClock [] PROGMEM = "AL Clock"; -const char pstrUsageALFileBrowser [] PROGMEM = "AL File Brow"; -const char pstrUsageALPowerStatus [] PROGMEM = "AL Pwr Sts"; -const char pstrUsageALImageBrowser [] PROGMEM = "AL Img Brow"; -const char pstrUsageALAudioBrowser [] PROGMEM = "AL Aud Brow"; -const char pstrUsageALMovieBrowser [] PROGMEM = "AL Mov Brow"; -const char pstrUsageALDigitalRightsManager [] PROGMEM = "AL Dig Rights Mgr"; -const char pstrUsageALDigitalWallet [] PROGMEM = "AL Dig Wallet"; -const char pstrUsageALInstantMessaging [] PROGMEM = "AL Inst Msg"; -const char pstrUsageALOEMFeaturesBrowser [] PROGMEM = "AL OEM Tips Brow"; -const char pstrUsageALOEMHelp [] PROGMEM = "AL OEM Hlp"; -const char pstrUsageALOnlineCommunity [] PROGMEM = "AL Online Com"; -const char pstrUsageALEntertainmentContentBrow [] PROGMEM = "AL Ent Cont Brow"; -const char pstrUsageALOnlineShoppingBrowser [] PROGMEM = "AL Online Shop Brow"; -const char pstrUsageALSmartCardInfoHelp [] PROGMEM = "AL SmartCard Inf"; -const char pstrUsageALMarketMonitorFinBrowser [] PROGMEM = "AL Market Brow"; -const char pstrUsageALCustomCorpNewsBrowser [] PROGMEM = "AL Cust Corp News Brow"; -const char pstrUsageALOnlineActivityBrowser [] PROGMEM = "AL Online Act Brow"; -const char pstrUsageALResearchSearchBrowser [] PROGMEM = "AL Search Brow"; -const char pstrUsageALAudioPlayer [] PROGMEM = "AL Aud Player"; -const char pstrUsageGenericGUIAppControls [] PROGMEM = "Gen GUI App Ctrl"; -const char pstrUsageACNew [] PROGMEM = "AC New"; -const char pstrUsageACOpen [] PROGMEM = "AC Open"; -const char pstrUsageACClose [] PROGMEM = "AC Close"; -const char pstrUsageACExit [] PROGMEM = "AC Exit"; -const char pstrUsageACMaximize [] PROGMEM = "AC Max"; -const char pstrUsageACMinimize [] PROGMEM = "AC Min"; -const char pstrUsageACSave [] PROGMEM = "AC Save"; -const char pstrUsageACPrint [] PROGMEM = "AC Print"; -const char pstrUsageACProperties [] PROGMEM = "AC Prop"; -const char pstrUsageACUndo [] PROGMEM = "AC Undo"; -const char pstrUsageACCopy [] PROGMEM = "AC Copy"; -const char pstrUsageACCut [] PROGMEM = "AC Cut"; -const char pstrUsageACPaste [] PROGMEM = "AC Paste"; -const char pstrUsageACSelectAll [] PROGMEM = "AC Sel All"; -const char pstrUsageACFind [] PROGMEM = "AC Find"; -const char pstrUsageACFindAndReplace [] PROGMEM = "AC Find/Replace"; -const char pstrUsageACSearch [] PROGMEM = "AC Search"; -const char pstrUsageACGoto [] PROGMEM = "AC Goto"; -const char pstrUsageACHome [] PROGMEM = "AC Home"; -const char pstrUsageACBack [] PROGMEM = "AC Back"; -const char pstrUsageACForward [] PROGMEM = "AC Fwd"; -const char pstrUsageACStop [] PROGMEM = "AC Stop"; -const char pstrUsageACRefresh [] PROGMEM = "AC Refresh"; -const char pstrUsageACPreviousLink [] PROGMEM = "AC Prev Link"; -const char pstrUsageACNextLink [] PROGMEM = "AC Next Link"; -const char pstrUsageACBookmarks [] PROGMEM = "AC Bkmarks"; -const char pstrUsageACHistory [] PROGMEM = "AC Hist"; -const char pstrUsageACSubscriptions [] PROGMEM = "AC Subscr"; -const char pstrUsageACZoomIn [] PROGMEM = "AC Zoom In"; -const char pstrUsageACZoomOut [] PROGMEM = "AC Zoom Out"; -const char pstrUsageACZoom [] PROGMEM = "AC Zoom"; -const char pstrUsageACFullScreenView [] PROGMEM = "AC Full Scr"; -const char pstrUsageACNormalView [] PROGMEM = "AC Norm View"; -const char pstrUsageACViewToggle [] PROGMEM = "AC View Tgl"; -const char pstrUsageACScrollUp [] PROGMEM = "AC Scroll Up"; -const char pstrUsageACScrollDown [] PROGMEM = "AC Scroll Down"; -const char pstrUsageACScroll [] PROGMEM = "AC Scroll"; -const char pstrUsageACPanLeft [] PROGMEM = "AC Pan Left"; -const char pstrUsageACPanRight [] PROGMEM = "AC Pan Right"; -const char pstrUsageACPan [] PROGMEM = "AC Pan"; -const char pstrUsageACNewWindow [] PROGMEM = "AC New Wnd"; -const char pstrUsageACTileHoriz [] PROGMEM = "AC Tile Horiz"; -const char pstrUsageACTileVert [] PROGMEM = "AC Tile Vert"; -const char pstrUsageACFormat [] PROGMEM = "AC Frmt"; -const char pstrUsageACEdit [] PROGMEM = "AC Edit"; -const char pstrUsageACBold [] PROGMEM = "AC Bold"; -const char pstrUsageACItalics [] PROGMEM = "AC Ital"; -const char pstrUsageACUnderline [] PROGMEM = "AC Under"; -const char pstrUsageACStrikethrough [] PROGMEM = "AC Strike"; -const char pstrUsageACSubscript [] PROGMEM = "AC Sub"; -const char pstrUsageACSuperscript [] PROGMEM = "AC Super"; -const char pstrUsageACAllCaps [] PROGMEM = "AC All Caps"; -const char pstrUsageACRotate [] PROGMEM = "AC Rotate"; -const char pstrUsageACResize [] PROGMEM = "AC Resize"; -const char pstrUsageACFlipHorizontal [] PROGMEM = "AC Flp H"; -const char pstrUsageACFlipVertical [] PROGMEM = "AC Flp V"; -const char pstrUsageACMirrorHorizontal [] PROGMEM = "AC Mir H"; -const char pstrUsageACMirrorVertical [] PROGMEM = "AC Mir V"; -const char pstrUsageACFontSelect [] PROGMEM = "AC Fnt Sel"; -const char pstrUsageACFontColor [] PROGMEM = "AC Fnt Clr"; -const char pstrUsageACFontSize [] PROGMEM = "AC Fnt Size"; -const char pstrUsageACJustifyLeft [] PROGMEM = "AC Just Left"; -const char pstrUsageACJustifyCenterH [] PROGMEM = "AC Just Cent H"; -const char pstrUsageACJustifyRight [] PROGMEM = "AC Just Right"; -const char pstrUsageACJustifyBlockH [] PROGMEM = "AC Just Block H"; -const char pstrUsageACJustifyTop [] PROGMEM = "AC Just Top"; -const char pstrUsageACJustifyCenterV [] PROGMEM = "AC Just Cent V"; -const char pstrUsageACJustifyBottom [] PROGMEM = "AC Just Bot"; -const char pstrUsageACJustifyBlockV [] PROGMEM = "AC Just Block V"; -const char pstrUsageACIndentDecrease [] PROGMEM = "AC Indent Dec"; -const char pstrUsageACIndentIncrease [] PROGMEM = "AC Indent Inc"; -const char pstrUsageACNumberedList [] PROGMEM = "AC Num List"; -const char pstrUsageACRestartNumbering [] PROGMEM = "AC Res Num"; -const char pstrUsageACBulletedList [] PROGMEM = "AC Blt List"; -const char pstrUsageACPromote [] PROGMEM = "AC Promote"; -const char pstrUsageACDemote [] PROGMEM = "AC Demote"; -const char pstrUsageACYes [] PROGMEM = "AC Yes"; -const char pstrUsageACNo [] PROGMEM = "AC No"; -const char pstrUsageACCancel [] PROGMEM = "AC Cancel"; -const char pstrUsageACCatalog [] PROGMEM = "AC Ctlg"; -const char pstrUsageACBuyChkout [] PROGMEM = "AC Buy"; -const char pstrUsageACAddToCart [] PROGMEM = "AC Add2Cart"; -const char pstrUsageACExpand [] PROGMEM = "AC Xpnd"; -const char pstrUsageACExpandAll [] PROGMEM = "AC Xpand All"; -const char pstrUsageACCollapse [] PROGMEM = "AC Collapse"; -const char pstrUsageACCollapseAll [] PROGMEM = "AC Collapse All"; -const char pstrUsageACPrintPreview [] PROGMEM = "AC Prn Prevw"; -const char pstrUsageACPasteSpecial [] PROGMEM = "AC Paste Spec"; -const char pstrUsageACInsertMode [] PROGMEM = "AC Ins Mode"; -const char pstrUsageACDelete [] PROGMEM = "AC Del"; -const char pstrUsageACLock [] PROGMEM = "AC Lock"; -const char pstrUsageACUnlock [] PROGMEM = "AC Unlock"; -const char pstrUsageACProtect [] PROGMEM = "AC Prot"; -const char pstrUsageACUnprotect [] PROGMEM = "AC Unprot"; -const char pstrUsageACAttachComment [] PROGMEM = "AC Attach Cmnt"; -const char pstrUsageACDeleteComment [] PROGMEM = "AC Del Cmnt"; -const char pstrUsageACViewComment [] PROGMEM = "AC View Cmnt"; -const char pstrUsageACSelectWord [] PROGMEM = "AC Sel Word"; -const char pstrUsageACSelectSentence [] PROGMEM = "AC Sel Sntc"; -const char pstrUsageACSelectParagraph [] PROGMEM = "AC Sel Para"; -const char pstrUsageACSelectColumn [] PROGMEM = "AC Sel Col"; -const char pstrUsageACSelectRow [] PROGMEM = "AC Sel Row"; -const char pstrUsageACSelectTable [] PROGMEM = "AC Sel Tbl"; -const char pstrUsageACSelectObject [] PROGMEM = "AC Sel Obj"; -const char pstrUsageACRedoRepeat [] PROGMEM = "AC Redo"; -const char pstrUsageACSort [] PROGMEM = "AC Sort"; -const char pstrUsageACSortAscending [] PROGMEM = "AC Sort Asc"; -const char pstrUsageACSortDescending [] PROGMEM = "AC Sort Desc"; -const char pstrUsageACFilter [] PROGMEM = "AC Filt"; -const char pstrUsageACSetClock [] PROGMEM = "AC Set Clk"; -const char pstrUsageACViewClock [] PROGMEM = "AC View Clk"; -const char pstrUsageACSelectTimeZone [] PROGMEM = "AC Sel Time Z"; -const char pstrUsageACEditTimeZone [] PROGMEM = "AC Edt Time Z"; -const char pstrUsageACSetAlarm [] PROGMEM = "AC Set Alm"; -const char pstrUsageACClearAlarm [] PROGMEM = "AC Clr Alm"; -const char pstrUsageACSnoozeAlarm [] PROGMEM = "AC Snz Alm"; -const char pstrUsageACResetAlarm [] PROGMEM = "AC Rst Alm"; -const char pstrUsageACSyncronize [] PROGMEM = "AC Sync"; -const char pstrUsageACSendReceive [] PROGMEM = "AC Snd/Rcv"; -const char pstrUsageACSendTo [] PROGMEM = "AC Snd To"; -const char pstrUsageACReply [] PROGMEM = "AC Reply"; -const char pstrUsageACReplyAll [] PROGMEM = "AC Reply All"; -const char pstrUsageACForwardMessage [] PROGMEM = "AC Fwd Msg"; -const char pstrUsageACSend [] PROGMEM = "AC Snd"; -const char pstrUsageACAttachFile [] PROGMEM = "AC Att File"; -const char pstrUsageACUpload [] PROGMEM = "AC Upld"; -const char pstrUsageACDownload [] PROGMEM = "AC Dnld"; -const char pstrUsageACSetBorders [] PROGMEM = "AC Set Brd"; -const char pstrUsageACInsertRow [] PROGMEM = "AC Ins Row"; -const char pstrUsageACInsertColumn [] PROGMEM = "AC Ins Col"; -const char pstrUsageACInsertFile [] PROGMEM = "AC Ins File"; -const char pstrUsageACInsertPicture [] PROGMEM = "AC Ins Pic"; -const char pstrUsageACInsertObject [] PROGMEM = "AC Ins Obj"; -const char pstrUsageACInsertSymbol [] PROGMEM = "AC Ins Sym"; -const char pstrUsageACSaveAndClose [] PROGMEM = "AC Sav&Cls"; -const char pstrUsageACRename [] PROGMEM = "AC Rename"; -const char pstrUsageACMerge [] PROGMEM = "AC Merge"; -const char pstrUsageACSplit [] PROGMEM = "AC Split"; -const char pstrUsageACDistributeHorizontaly [] PROGMEM = "AC Dist Hor"; -const char pstrUsageACDistributeVerticaly [] PROGMEM = "AC Dist Ver"; - -// Digitaizers -const char pstrUsageDigitizer [] PROGMEM = "Digitizer"; -const char pstrUsagePen [] PROGMEM = "Pen"; -const char pstrUsageLightPen [] PROGMEM = "Light Pen"; -const char pstrUsageTouchScreen [] PROGMEM = "Touch Scr"; -const char pstrUsageTouchPad [] PROGMEM = "Touch Pad"; -const char pstrUsageWhiteBoard [] PROGMEM = "White Brd"; -const char pstrUsageCoordinateMeasuringMachine [] PROGMEM = "Coord Meas Mach"; -const char pstrUsage3DDigitizer [] PROGMEM = "3D Dgtz"; -const char pstrUsageStereoPlotter [] PROGMEM = "Stereo Plot"; -const char pstrUsageArticulatedArm [] PROGMEM = "Art Arm"; -const char pstrUsageArmature [] PROGMEM = "Armature"; -const char pstrUsageMultiplePointDigitizer [] PROGMEM = "Multi Point Dgtz"; -const char pstrUsageFreeSpaceWand [] PROGMEM = "Free Space Wand"; -const char pstrUsageStylus [] PROGMEM = "Stylus"; -const char pstrUsagePuck [] PROGMEM = "Puck"; -const char pstrUsageFinger [] PROGMEM = "Finger"; -const char pstrUsageTipPressure [] PROGMEM = "Tip Press"; -const char pstrUsageBarrelPressure [] PROGMEM = "Brl Press"; -const char pstrUsageInRange [] PROGMEM = "In Range"; -const char pstrUsageTouch [] PROGMEM = "Touch"; -const char pstrUsageUntouch [] PROGMEM = "Untouch"; -const char pstrUsageTap [] PROGMEM = "Tap"; -const char pstrUsageQuality [] PROGMEM = "Qlty"; -const char pstrUsageDataValid [] PROGMEM = "Data Valid"; -const char pstrUsageTransducerIndex [] PROGMEM = "Transducer Ind"; -const char pstrUsageTabletFunctionKeys [] PROGMEM = "Tabl Func Keys"; -const char pstrUsageProgramChangeKeys [] PROGMEM = "Pgm Chng Keys"; -//const char pstrUsageBatteryStrength [] PROGMEM = "Bat Strength"; -const char pstrUsageInvert [] PROGMEM = "Invert"; -const char pstrUsageXTilt [] PROGMEM = "X Tilt"; -const char pstrUsageYTilt [] PROGMEM = "Y Tilt"; -const char pstrUsageAzimuth [] PROGMEM = "Azimuth"; -const char pstrUsageAltitude [] PROGMEM = "Altitude"; -const char pstrUsageTwist [] PROGMEM = "Twist"; -const char pstrUsageTipSwitch [] PROGMEM = "Tip Sw"; -const char pstrUsageSecondaryTipSwitch [] PROGMEM = "Scnd Tip Sw"; -const char pstrUsageBarrelSwitch [] PROGMEM = "Brl Sw"; -const char pstrUsageEraser [] PROGMEM = "Eraser"; -const char pstrUsageTabletPick [] PROGMEM = "Tbl Pick"; - -// Alphanumeric Display Page -const char pstrUsageAlphanumericDisplay [] PROGMEM = "Alphanum Disp"; -const char pstrUsageBitmappedDisplay [] PROGMEM = "Bmp Disp"; -const char pstrUsageDisplayAttributesReport [] PROGMEM = "Disp Attr Rpt"; -const char pstrUsageASCIICharacterSet [] PROGMEM = "ASCII chset"; -const char pstrUsageDataReadBack [] PROGMEM = "Data Rd Back"; -const char pstrUsageFontReadBack [] PROGMEM = "Fnt Rd Back"; -const char pstrUsageDisplayControlReport [] PROGMEM = "Disp Ctrl Rpt"; -const char pstrUsageClearDisplay [] PROGMEM = "Clr Disp"; -//const char pstrUsageDisplayEnable [] PROGMEM = "Disp Enbl"; -const char pstrUsageScreenSaverDelay [] PROGMEM = "Scr Sav Delay"; -const char pstrUsageScreenSaverEnable [] PROGMEM = "Scr Sav Enbl"; -const char pstrUsageVerticalScroll [] PROGMEM = "V Scroll"; -const char pstrUsageHorizontalScroll [] PROGMEM = "H Scroll"; -const char pstrUsageCharacterReport [] PROGMEM = "Char Rpt"; -const char pstrUsageDisplayData [] PROGMEM = "Disp Data"; -const char pstrUsageDisplayStatus [] PROGMEM = "Disp Stat"; -const char pstrUsageStatusNotReady [] PROGMEM = "Stat !Ready"; -const char pstrUsageStatusReady [] PROGMEM = "Stat Ready"; -const char pstrUsageErrorNotALoadableCharacter [] PROGMEM = "Err Not Ld Char"; -const char pstrUsageErrorFotDataCanNotBeRead [] PROGMEM = "Fnt Data Rd Err"; -const char pstrUsageCursorPositionReport [] PROGMEM = "Cur Pos Rpt"; -const char pstrUsageRow [] PROGMEM = "Row"; -const char pstrUsageColumn [] PROGMEM = "Col"; -const char pstrUsageRows [] PROGMEM = "Rows"; -const char pstrUsageColumns [] PROGMEM = "Cols"; -const char pstrUsageCursorPixelPosition [] PROGMEM = "Cur Pix Pos"; -const char pstrUsageCursorMode [] PROGMEM = "Cur Mode"; -const char pstrUsageCursorEnable [] PROGMEM = "Cur Enbl"; -const char pstrUsageCursorBlink [] PROGMEM = "Cur Blnk"; -const char pstrUsageFontReport [] PROGMEM = "Fnt Rpt"; -const char pstrUsageFontData [] PROGMEM = "Fnt Data"; -const char pstrUsageCharacterWidth [] PROGMEM = "Char Wdth"; -const char pstrUsageCharacterHeight [] PROGMEM = "Char Hght"; -const char pstrUsageCharacterSpacingHorizontal [] PROGMEM = "Char Space H"; -const char pstrUsageCharacterSpacingVertical [] PROGMEM = "Char Space V"; -const char pstrUsageUnicodeCharset [] PROGMEM = "Unicode Char"; -const char pstrUsageFont7Segment [] PROGMEM = "Fnt 7-seg"; -const char pstrUsage7SegmentDirectMap [] PROGMEM = "7-seg map"; -const char pstrUsageFont14Segment [] PROGMEM = "Fnt 14-seg"; -const char pstrUsage14SegmentDirectMap [] PROGMEM = "14-seg map"; -const char pstrUsageDisplayBrightness [] PROGMEM = "Disp Bright"; -const char pstrUsageDisplayContrast [] PROGMEM = "Disp Cntrst"; -const char pstrUsageCharacterAttribute [] PROGMEM = "Char Attr"; -const char pstrUsageAttributeReadback [] PROGMEM = "Attr Readbk"; -const char pstrUsageAttributeData [] PROGMEM = "Attr Data"; -const char pstrUsageCharAttributeEnhance [] PROGMEM = "Char Attr Enh"; -const char pstrUsageCharAttributeUnderline [] PROGMEM = "Char Attr Undl"; -const char pstrUsageCharAttributeBlink [] PROGMEM = "Char Attr Blnk"; -const char pstrUsageBitmapSizeX [] PROGMEM = "Bmp Size X"; -const char pstrUsageBitmapSizeY [] PROGMEM = "Bmp Size Y"; -const char pstrUsageBitDepthFormat [] PROGMEM = "Bit Dpth Fmt"; -const char pstrUsageDisplayOrientation [] PROGMEM = "Disp Ornt"; -const char pstrUsagePaletteReport [] PROGMEM = "Pal Rpt"; -const char pstrUsagePaletteDataSize [] PROGMEM = "Pal Data Size"; -const char pstrUsagePaletteDataOffset [] PROGMEM = "Pal Data Off"; -const char pstrUsagePaletteData [] PROGMEM = "Pal Data"; -const char pstrUsageBlitReport [] PROGMEM = "Blit Rpt"; -const char pstrUsageBlitRectangleX1 [] PROGMEM = "Blit Rect X1"; -const char pstrUsageBlitRectangleY1 [] PROGMEM = "Blit Rect Y1"; -const char pstrUsageBlitRectangleX2 [] PROGMEM = "Blit Rect X2"; -const char pstrUsageBlitRectangleY2 [] PROGMEM = "Blit Rect Y2"; -const char pstrUsageBlitData [] PROGMEM = "Blit Data"; -const char pstrUsageSoftButton [] PROGMEM = "Soft Btn"; -const char pstrUsageSoftButtonID [] PROGMEM = "Soft Btn ID"; -const char pstrUsageSoftButtonSide [] PROGMEM = "Soft Btn Side"; -const char pstrUsageSoftButtonOffset1 [] PROGMEM = "Soft Btn Off1"; -const char pstrUsageSoftButtonOffset2 [] PROGMEM = "Soft Btn Off2"; -const char pstrUsageSoftButtonReport [] PROGMEM = "Soft Btn Rpt"; - -// Medical Instrument Page -const char pstrUsageMedicalUltrasound [] PROGMEM = "Med Ultrasnd"; -const char pstrUsageVCRAcquisition [] PROGMEM = "VCR/Acq"; -const char pstrUsageFreezeThaw [] PROGMEM = "Freeze"; -const char pstrUsageClipStore [] PROGMEM = "Clip Store"; -const char pstrUsageUpdate [] PROGMEM = "Update"; -const char pstrUsageNext [] PROGMEM = "Next"; -const char pstrUsageSave [] PROGMEM = "Save"; -const char pstrUsagePrint [] PROGMEM = "Print"; -const char pstrUsageMicrophoneEnable [] PROGMEM = "Mic Enbl"; -const char pstrUsageCine [] PROGMEM = "Cine"; -const char pstrUsageTransmitPower [] PROGMEM = "Trans Pwr"; -//const char pstrUsageVolume [] PROGMEM = "Vol"; -const char pstrUsageFocus [] PROGMEM = "Focus"; -const char pstrUsageDepth [] PROGMEM = "Depth"; -const char pstrUsageSoftStepPrimary [] PROGMEM = "Soft Stp-Pri"; -const char pstrUsageSoftStepSecondary [] PROGMEM = "Soft Stp-Sec"; -const char pstrUsageDepthGainCompensation [] PROGMEM = "Dpth Gain Comp"; -const char pstrUsageZoomSelect [] PROGMEM = "Zoom Sel"; -const char pstrUsageZoomAdjust [] PROGMEM = "Zoom Adj"; -const char pstrUsageSpectralDopplerModeSelect [] PROGMEM = "Spec Dop Mode Sel"; -const char pstrUsageSpectralDopplerModeAdjust [] PROGMEM = "Spec Dop Mode Adj"; -const char pstrUsageColorDopplerModeSelect [] PROGMEM = "Color Dop Mode Sel"; -const char pstrUsageColorDopplerModeAdjust [] PROGMEM = "Color Dop Mode Adj"; -const char pstrUsageMotionModeSelect [] PROGMEM = "Motion Mode Sel"; -const char pstrUsageMotionModeAdjust [] PROGMEM = "Motion Mode Adj"; -const char pstrUsage2DModeSelect [] PROGMEM = "2D Mode Sel"; -const char pstrUsage2DModeAdjust [] PROGMEM = "2D Mode Adj"; -const char pstrUsageSoftControlSelect [] PROGMEM = "Soft Ctrl Sel"; -const char pstrUsageSoftControlAdjust [] PROGMEM = "Soft Ctrl Adj"; - -//extern const char *usagePageTitles0[15]; -//const char *usagePageTitles1[]; -//const char *genDesktopTitles0[]; -//const char *genDesktopTitles1[]; -//const char *genDesktopTitles2[]; -//const char *genDesktopTitles3[]; -//const char *genDesktopTitles4[]; -//const char *simuTitles0[]; -//const char *simuTitles1[]; -//const char *simuTitles2[]; -//const char *vrTitles0[]; -//const char *vrTitles1[]; -//const char *sportsCtrlTitles0[]; -//const char *sportsCtrlTitles1[]; -//const char *sportsCtrlTitles2[]; -//const char *gameTitles0[]; -//const char *gameTitles1[]; -//const char *genDevCtrlTitles[]; -//const char *ledTitles[]; -//const char *telTitles0[]; -//const char *telTitles1[]; -//const char *telTitles2[]; -//const char *telTitles3[]; -//const char *telTitles4[]; -//const char *telTitles5[]; -//const char *consTitles0[]; -//const char *consTitles1[]; -//const char *consTitles2[]; -//const char *consTitles3[]; -//const char *consTitles4[]; -//const char *consTitles5[]; -//const char *consTitles6[]; -//const char *consTitles7[]; -//const char *consTitles8[]; -//const char *consTitles9[]; -//const char *consTitlesA[]; -//const char *consTitlesB[]; -//const char *consTitlesC[]; -//const char *consTitlesD[]; -//const char *consTitlesE[]; -//const char *digitTitles0[]; -//const char *digitTitles1[]; -//const char *digitTitles2[]; -//const char *aplphanumTitles0[]; -//const char *aplphanumTitles1[]; -//const char *aplphanumTitles2[]; -//const char *medInstrTitles0[]; -//const char *medInstrTitles1[]; -//const char *medInstrTitles2[]; -//const char *medInstrTitles3[]; -//const char *medInstrTitles4[]; - -#endif //__HIDUSAGESTR_H__ diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidusagetitlearrays.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidusagetitlearrays.cpp deleted file mode 100644 index ee233002ca..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidusagetitlearrays.cpp +++ /dev/null @@ -1,1048 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ -#if !defined(__HIDUSAGETITLEARRAYS_H__) -#define __HIDUSAGETITLEARRAYS_H__ - -#include "hidusagestr.h" - -// This is here why? - -//const char *usagePageTitles0[] PROGMEM = -//{ -// pstrUsagePageGenericDesktopControls , -// pstrUsagePageSimulationControls , -// pstrUsagePageVRControls , -// pstrUsagePageSportControls , -// pstrUsagePageGameControls , -// pstrUsagePageGenericDeviceControls , -// pstrUsagePageKeyboardKeypad , -// pstrUsagePageLEDs , -// pstrUsagePageButton , -// pstrUsagePageOrdinal , -// pstrUsagePageTelephone , -// pstrUsagePageConsumer , -// pstrUsagePageDigitizer , -// pstrUsagePagePID , -// pstrUsagePageUnicode -//}; -// -//const char *usagePageTitles1[] PROGMEM = -//{ -// pstrUsagePageBarCodeScanner , -// pstrUsagePageScale , -// pstrUsagePageMSRDevices , -// pstrUsagePagePointOfSale , -// pstrUsagePageCameraControl , -// pstrUsagePageArcade -//}; -//const char *genDesktopTitles0[] PROGMEM = -//{ -// pstrUsagePointer , -// pstrUsageMouse , -// pstrUsageJoystick , -// pstrUsageGamePad , -// pstrUsageKeyboard , -// pstrUsageKeypad , -// pstrUsageMultiAxisController , -// pstrUsageTabletPCSystemControls -// -//}; -//const char *genDesktopTitles1[] PROGMEM = -//{ -// pstrUsageX , -// pstrUsageY , -// pstrUsageZ , -// pstrUsageRx , -// pstrUsageRy , -// pstrUsageRz , -// pstrUsageSlider , -// pstrUsageDial , -// pstrUsageWheel , -// pstrUsageHatSwitch , -// pstrUsageCountedBuffer , -// pstrUsageByteCount , -// pstrUsageMotionWakeup , -// pstrUsageStart , -// pstrUsageSelect , -// pstrUsagePageReserved , -// pstrUsageVx , -// pstrUsageVy , -// pstrUsageVz , -// pstrUsageVbrx , -// pstrUsageVbry , -// pstrUsageVbrz , -// pstrUsageVno , -// pstrUsageFeatureNotification , -// pstrUsageResolutionMultiplier -//}; -//const char *genDesktopTitles2[] PROGMEM = -//{ -// pstrUsageSystemControl , -// pstrUsageSystemPowerDown , -// pstrUsageSystemSleep , -// pstrUsageSystemWakeup , -// pstrUsageSystemContextMenu , -// pstrUsageSystemMainMenu , -// pstrUsageSystemAppMenu , -// pstrUsageSystemMenuHelp , -// pstrUsageSystemMenuExit , -// pstrUsageSystemMenuSelect , -// pstrUsageSystemMenuRight , -// pstrUsageSystemMenuLeft , -// pstrUsageSystemMenuUp , -// pstrUsageSystemMenuDown , -// pstrUsageSystemColdRestart , -// pstrUsageSystemWarmRestart , -// pstrUsageDPadUp , -// pstrUsageDPadDown , -// pstrUsageDPadRight , -// pstrUsageDPadLeft -//}; -//const char *genDesktopTitles3[] PROGMEM = -//{ -// pstrUsageSystemDock , -// pstrUsageSystemUndock , -// pstrUsageSystemSetup , -// pstrUsageSystemBreak , -// pstrUsageSystemDebuggerBreak , -// pstrUsageApplicationBreak , -// pstrUsageApplicationDebuggerBreak, -// pstrUsageSystemSpeakerMute , -// pstrUsageSystemHibernate -//}; -//const char *genDesktopTitles4[] PROGMEM = -//{ -// pstrUsageSystemDisplayInvert , -// pstrUsageSystemDisplayInternal , -// pstrUsageSystemDisplayExternal , -// pstrUsageSystemDisplayBoth , -// pstrUsageSystemDisplayDual , -// pstrUsageSystemDisplayToggleIntExt , -// pstrUsageSystemDisplaySwapPriSec , -// pstrUsageSystemDisplayLCDAutoscale -//}; -//const char *simuTitles0[] PROGMEM = -//{ -// pstrUsageFlightSimulationDevice , -// pstrUsageAutomobileSimulationDevice , -// pstrUsageTankSimulationDevice , -// pstrUsageSpaceshipSimulationDevice , -// pstrUsageSubmarineSimulationDevice , -// pstrUsageSailingSimulationDevice , -// pstrUsageMotocicleSimulationDevice , -// pstrUsageSportsSimulationDevice , -// pstrUsageAirplaneSimulationDevice , -// pstrUsageHelicopterSimulationDevice , -// pstrUsageMagicCarpetSimulationDevice, -// pstrUsageBicycleSimulationDevice -//}; -//const char *simuTitles1[] PROGMEM = -//{ -// pstrUsageFlightControlStick , -// pstrUsageFlightStick , -// pstrUsageCyclicControl , -// pstrUsageCyclicTrim , -// pstrUsageFlightYoke , -// pstrUsageTrackControl -//}; -//const char *simuTitles2[] PROGMEM = -//{ -// pstrUsageAileron , -// pstrUsageAileronTrim , -// pstrUsageAntiTorqueControl , -// pstrUsageAutopilotEnable , -// pstrUsageChaffRelease , -// pstrUsageCollectiveControl , -// pstrUsageDiveBrake , -// pstrUsageElectronicCountermeasures , -// pstrUsageElevator , -// pstrUsageElevatorTrim , -// pstrUsageRudder , -// pstrUsageThrottle , -// pstrUsageFlightCommunications , -// pstrUsageFlareRelease , -// pstrUsageLandingGear , -// pstrUsageToeBrake , -// pstrUsageTrigger , -// pstrUsageWeaponsArm , -// pstrUsageWeaponsSelect , -// pstrUsageWingFlaps , -// pstrUsageAccelerator , -// pstrUsageBrake , -// pstrUsageClutch , -// pstrUsageShifter , -// pstrUsageSteering , -// pstrUsageTurretDirection , -// pstrUsageBarrelElevation , -// pstrUsageDivePlane , -// pstrUsageBallast , -// pstrUsageBicycleCrank , -// pstrUsageHandleBars , -// pstrUsageFrontBrake , -// pstrUsageRearBrake -//}; -//const char *vrTitles0[] PROGMEM = -//{ -// pstrUsageBelt , -// pstrUsageBodySuit , -// pstrUsageFlexor , -// pstrUsageGlove , -// pstrUsageHeadTracker , -// pstrUsageHeadMountedDisplay , -// pstrUsageHandTracker , -// pstrUsageOculometer , -// pstrUsageVest , -// pstrUsageAnimatronicDevice -//}; -//const char *vrTitles1[] PROGMEM = -//{ -// pstrUsageStereoEnable , -// pstrUsageDisplayEnable -//}; -//const char *sportsCtrlTitles0[] PROGMEM = -//{ -// pstrUsageBaseballBat , -// pstrUsageGolfClub , -// pstrUsageRowingMachine , -// pstrUsageTreadmill -//}; -//const char *sportsCtrlTitles1[] PROGMEM = -//{ -// pstrUsageOar , -// pstrUsageSlope , -// pstrUsageRate , -// pstrUsageStickSpeed , -// pstrUsageStickFaceAngle , -// pstrUsageStickHeelToe , -// pstrUsageStickFollowThough , -// pstrUsageStickTempo , -// pstrUsageStickType , -// pstrUsageStickHeight -//}; -//const char *sportsCtrlTitles2[] PROGMEM = -//{ -// pstrUsagePutter , -// pstrUsage1Iron , -// pstrUsage2Iron , -// pstrUsage3Iron , -// pstrUsage4Iron , -// pstrUsage5Iron , -// pstrUsage6Iron , -// pstrUsage7Iron , -// pstrUsage8Iron , -// pstrUsage9Iron , -// pstrUsage10Iron , -// pstrUsage11Iron , -// pstrUsageSandWedge , -// pstrUsageLoftWedge , -// pstrUsagePowerWedge , -// pstrUsage1Wood , -// pstrUsage3Wood , -// pstrUsage5Wood , -// pstrUsage7Wood , -// pstrUsage9Wood -//}; -//const char *gameTitles0[] PROGMEM = -//{ -// pstrUsage3DGameController , -// pstrUsagePinballDevice , -// pstrUsageGunDevice -//}; -//const char *gameTitles1[] PROGMEM = -//{ -// pstrUsagePointOfView , -// pstrUsageTurnRightLeft , -// pstrUsagePitchForwardBackward , -// pstrUsageRollRightLeft , -// pstrUsageMoveRightLeft , -// pstrUsageMoveForwardBackward , -// pstrUsageMoveUpDown , -// pstrUsageLeanRightLeft , -// pstrUsageLeanForwardBackward , -// pstrUsageHeightOfPOV , -// pstrUsageFlipper , -// pstrUsageSecondaryFlipper , -// pstrUsageBump , -// pstrUsageNewGame , -// pstrUsageShootBall , -// pstrUsagePlayer , -// pstrUsageGunBolt , -// pstrUsageGunClip , -// pstrUsageGunSelector , -// pstrUsageGunSingleShot , -// pstrUsageGunBurst , -// pstrUsageGunAutomatic , -// pstrUsageGunSafety , -// pstrUsageGamepadFireJump , -// pstrUsageGamepadTrigger -//}; -//const char *genDevCtrlTitles[] PROGMEM = -//{ -// pstrUsageBatteryStrength, -// pstrUsageWirelessChannel, -// pstrUsageWirelessID, -// pstrUsageDiscoverWirelessControl, -// pstrUsageSecurityCodeCharEntered, -// pstrUsageSecurityCodeCharErased, -// pstrUsageSecurityCodeCleared -//}; -//const char *ledTitles[] PROGMEM = -//{ -// pstrUsageNumLock , -// pstrUsageCapsLock , -// pstrUsageScrollLock , -// pstrUsageCompose , -// pstrUsageKana , -// pstrUsagePower , -// pstrUsageShift , -// pstrUsageDoNotDisturb , -// pstrUsageMute , -// pstrUsageToneEnable , -// pstrUsageHighCutFilter , -// pstrUsageLowCutFilter , -// pstrUsageEqualizerEnable , -// pstrUsageSoundFieldOn , -// pstrUsageSurroundOn , -// pstrUsageRepeat , -// pstrUsageStereo , -// pstrUsageSamplingRateDetect , -// pstrUsageSpinning , -// pstrUsageCAV , -// pstrUsageCLV , -// pstrUsageRecordingFormatDetect , -// pstrUsageOffHook , -// pstrUsageRing , -// pstrUsageMessageWaiting , -// pstrUsageDataMode , -// pstrUsageBatteryOperation , -// pstrUsageBatteryOK , -// pstrUsageBatteryLow , -// pstrUsageSpeaker , -// pstrUsageHeadSet , -// pstrUsageHold , -// pstrUsageMicrophone , -// pstrUsageCoverage , -// pstrUsageNightMode , -// pstrUsageSendCalls , -// pstrUsageCallPickup , -// pstrUsageConference , -// pstrUsageStandBy , -// pstrUsageCameraOn , -// pstrUsageCameraOff , -// pstrUsageOnLine , -// pstrUsageOffLine , -// pstrUsageBusy , -// pstrUsageReady , -// pstrUsagePaperOut , -// pstrUsagePaperJam , -// pstrUsageRemote , -// pstrUsageForward , -// pstrUsageReverse , -// pstrUsageStop , -// pstrUsageRewind , -// pstrUsageFastForward , -// pstrUsagePlay , -// pstrUsagePause , -// pstrUsageRecord , -// pstrUsageError , -// pstrUsageSelectedIndicator , -// pstrUsageInUseIndicator , -// pstrUsageMultiModeIndicator , -// pstrUsageIndicatorOn , -// pstrUsageIndicatorFlash , -// pstrUsageIndicatorSlowBlink , -// pstrUsageIndicatorFastBlink , -// pstrUsageIndicatorOff , -// pstrUsageFlashOnTime , -// pstrUsageSlowBlinkOnTime , -// pstrUsageSlowBlinkOffTime , -// pstrUsageFastBlinkOnTime , -// pstrUsageFastBlinkOffTime , -// pstrUsageIndicatorColor , -// pstrUsageIndicatorRed , -// pstrUsageIndicatorGreen , -// pstrUsageIndicatorAmber , -// pstrUsageGenericIndicator , -// pstrUsageSystemSuspend , -// pstrUsageExternalPowerConnected -//}; -//const char *telTitles0 [] PROGMEM = -//{ -// pstrUsagePhone , -// pstrUsageAnsweringMachine , -// pstrUsageMessageControls , -// pstrUsageHandset , -// pstrUsageHeadset , -// pstrUsageTelephonyKeyPad , -// pstrUsageProgrammableButton -//}; -//const char *telTitles1 [] PROGMEM = -//{ -// pstrUsageHookSwitch , -// pstrUsageFlash , -// pstrUsageFeature , -// pstrUsageHold , -// pstrUsageRedial , -// pstrUsageTransfer , -// pstrUsageDrop , -// pstrUsagePark , -// pstrUsageForwardCalls , -// pstrUsageAlternateFunction , -// pstrUsageLine , -// pstrUsageSpeakerPhone , -// pstrUsageConference , -// pstrUsageRingEnable , -// pstrUsageRingSelect , -// pstrUsagePhoneMute , -// pstrUsageCallerID , -// pstrUsageSend -//}; -//const char *telTitles2 [] PROGMEM = -//{ -// pstrUsageSpeedDial , -// pstrUsageStoreNumber , -// pstrUsageRecallNumber , -// pstrUsagePhoneDirectory -//}; -//const char *telTitles3 [] PROGMEM = -//{ -// pstrUsageVoiceMail , -// pstrUsageScreenCalls , -// pstrUsageDoNotDisturb , -// pstrUsageMessage , -// pstrUsageAnswerOnOff -//}; -//const char *telTitles4 [] PROGMEM = -//{ -// pstrUsageInsideDialTone , -// pstrUsageOutsideDialTone , -// pstrUsageInsideRingTone , -// pstrUsageOutsideRingTone , -// pstrUsagePriorityRingTone , -// pstrUsageInsideRingback , -// pstrUsagePriorityRingback , -// pstrUsageLineBusyTone , -// pstrUsageReorderTone , -// pstrUsageCallWaitingTone , -// pstrUsageConfirmationTone1 , -// pstrUsageConfirmationTone2 , -// pstrUsageTonesOff , -// pstrUsageOutsideRingback , -// pstrUsageRinger -//}; -//const char *telTitles5 [] PROGMEM = -//{ -// pstrUsagePhoneKey0 , -// pstrUsagePhoneKey1 , -// pstrUsagePhoneKey2 , -// pstrUsagePhoneKey3 , -// pstrUsagePhoneKey4 , -// pstrUsagePhoneKey5 , -// pstrUsagePhoneKey6 , -// pstrUsagePhoneKey7 , -// pstrUsagePhoneKey8 , -// pstrUsagePhoneKey9 , -// pstrUsagePhoneKeyStar , -// pstrUsagePhoneKeyPound , -// pstrUsagePhoneKeyA , -// pstrUsagePhoneKeyB , -// pstrUsagePhoneKeyC , -// pstrUsagePhoneKeyD -//}; -//const char *consTitles0[] PROGMEM = -//{ -// pstrUsageConsumerControl, -// pstrUsageNumericKeyPad, -// pstrUsageProgrammableButton, -// pstrUsageMicrophone, -// pstrUsageHeadphone, -// pstrUsageGraphicEqualizer -//}; -//const char *consTitles1[] PROGMEM = -//{ -// pstrUsagePlus10 , -// pstrUsagePlus100, -// pstrUsageAMPM -//}; -//const char *consTitles2[] PROGMEM = -//{ -// pstrUsagePower , -// pstrUsageReset , -// pstrUsageSleep , -// pstrUsageSleepAfter , -// pstrUsageSleepMode , -// pstrUsageIllumination , -// pstrUsageFunctionButtons -// -//}; -//const char *consTitles3[] PROGMEM = -//{ -// pstrUsageMenu , -// pstrUsageMenuPick , -// pstrUsageMenuUp , -// pstrUsageMenuDown , -// pstrUsageMenuLeft , -// pstrUsageMenuRight , -// pstrUsageMenuEscape , -// pstrUsageMenuValueIncrease, -// pstrUsageMenuValueDecrease -//}; -//const char *consTitles4[] PROGMEM = -//{ -// pstrUsageDataOnScreen , -// pstrUsageClosedCaption , -// pstrUsageClosedCaptionSelect, -// pstrUsageVCRTV , -// pstrUsageBroadcastMode , -// pstrUsageSnapshot , -// pstrUsageStill -//}; -//const char *consTitles5[] PROGMEM = -//{ -// pstrUsageSelection , -// pstrUsageAssignSelection , -// pstrUsageModeStep , -// pstrUsageRecallLast , -// pstrUsageEnterChannel , -// pstrUsageOrderMovie , -// pstrUsageChannel , -// pstrUsageMediaSelection , -// pstrUsageMediaSelectComputer , -// pstrUsageMediaSelectTV , -// pstrUsageMediaSelectWWW , -// pstrUsageMediaSelectDVD , -// pstrUsageMediaSelectTelephone , -// pstrUsageMediaSelectProgramGuide , -// pstrUsageMediaSelectVideoPhone , -// pstrUsageMediaSelectGames , -// pstrUsageMediaSelectMessages , -// pstrUsageMediaSelectCD , -// pstrUsageMediaSelectVCR , -// pstrUsageMediaSelectTuner , -// pstrUsageQuit , -// pstrUsageHelp , -// pstrUsageMediaSelectTape , -// pstrUsageMediaSelectCable , -// pstrUsageMediaSelectSatellite , -// pstrUsageMediaSelectSecurity , -// pstrUsageMediaSelectHome , -// pstrUsageMediaSelectCall , -// pstrUsageChannelIncrement , -// pstrUsageChannelDecrement , -// pstrUsageMediaSelectSAP , -// pstrUsagePageReserved , -// pstrUsageVCRPlus , -// pstrUsageOnce , -// pstrUsageDaily , -// pstrUsageWeekly , -// pstrUsageMonthly -//}; -//const char *consTitles6[] PROGMEM = -//{ -// pstrUsagePlay , -// pstrUsagePause , -// pstrUsageRecord , -// pstrUsageFastForward , -// pstrUsageRewind , -// pstrUsageScanNextTrack , -// pstrUsageScanPreviousTrack , -// pstrUsageStop , -// pstrUsageEject , -// pstrUsageRandomPlay , -// pstrUsageSelectDisk , -// pstrUsageEnterDisk , -// pstrUsageRepeat , -// pstrUsageTracking , -// pstrUsageTrackNormal , -// pstrUsageSlowTracking , -// pstrUsageFrameForward , -// pstrUsageFrameBackwards , -// pstrUsageMark , -// pstrUsageClearMark , -// pstrUsageRepeatFromMark , -// pstrUsageReturnToMark , -// pstrUsageSearchMarkForward , -// pstrUsageSearchMarkBackwards , -// pstrUsageCounterReset , -// pstrUsageShowCounter , -// pstrUsageTrackingIncrement , -// pstrUsageTrackingDecrement , -// pstrUsageStopEject , -// pstrUsagePlayPause , -// pstrUsagePlaySkip -//}; -//const char *consTitles7[] PROGMEM = -//{ -// pstrUsageVolume , -// pstrUsageBalance , -// pstrUsageMute , -// pstrUsageBass , -// pstrUsageTreble , -// pstrUsageBassBoost , -// pstrUsageSurroundMode , -// pstrUsageLoudness , -// pstrUsageMPX , -// pstrUsageVolumeIncrement , -// pstrUsageVolumeDecrement -//}; -//const char *consTitles8[] PROGMEM = -//{ -// pstrUsageSpeedSelect , -// pstrUsagePlaybackSpeed , -// pstrUsageStandardPlay , -// pstrUsageLongPlay , -// pstrUsageExtendedPlay , -// pstrUsageSlow -//}; -//const char *consTitles9[] PROGMEM = -//{ -// pstrUsageFanEnable , -// pstrUsageFanSpeed , -// pstrUsageLightEnable , -// pstrUsageLightIlluminationLevel , -// pstrUsageClimateControlEnable , -// pstrUsageRoomTemperature , -// pstrUsageSecurityEnable , -// pstrUsageFireAlarm , -// pstrUsagePoliceAlarm , -// pstrUsageProximity , -// pstrUsageMotion , -// pstrUsageDuresAlarm , -// pstrUsageHoldupAlarm , -// pstrUsageMedicalAlarm -//}; -//const char *consTitlesA[] PROGMEM = -//{ -// pstrUsageBalanceRight , -// pstrUsageBalanceLeft , -// pstrUsageBassIncrement , -// pstrUsageBassDecrement , -// pstrUsageTrebleIncrement , -// pstrUsageTrebleDecrement -//}; -//const char *consTitlesB[] PROGMEM = -//{ -// pstrUsageSpeakerSystem , -// pstrUsageChannelLeft , -// pstrUsageChannelRight , -// pstrUsageChannelCenter , -// pstrUsageChannelFront , -// pstrUsageChannelCenterFront , -// pstrUsageChannelSide , -// pstrUsageChannelSurround , -// pstrUsageChannelLowFreqEnhancement , -// pstrUsageChannelTop , -// pstrUsageChannelUnknown -//}; -//const char *consTitlesC[] PROGMEM = -//{ -// pstrUsageSubChannel , -// pstrUsageSubChannelIncrement , -// pstrUsageSubChannelDecrement , -// pstrUsageAlternateAudioIncrement , -// pstrUsageAlternateAudioDecrement -//}; -//const char *consTitlesD[] PROGMEM = -//{ -// pstrUsageApplicationLaunchButtons , -// pstrUsageALLaunchButtonConfigTool , -// pstrUsageALProgrammableButton , -// pstrUsageALConsumerControlConfig , -// pstrUsageALWordProcessor , -// pstrUsageALTextEditor , -// pstrUsageALSpreadsheet , -// pstrUsageALGraphicsEditor , -// pstrUsageALPresentationApp , -// pstrUsageALDatabaseApp , -// pstrUsageALEmailReader , -// pstrUsageALNewsreader , -// pstrUsageALVoicemail , -// pstrUsageALContactsAddressBook , -// pstrUsageALCalendarSchedule , -// pstrUsageALTaskProjectManager , -// pstrUsageALLogJournalTimecard , -// pstrUsageALCheckbookFinance , -// pstrUsageALCalculator , -// pstrUsageALAVCapturePlayback , -// pstrUsageALLocalMachineBrowser , -// pstrUsageALLANWANBrow , -// pstrUsageALInternetBrowser , -// pstrUsageALRemoteNetISPConnect , -// pstrUsageALNetworkConference , -// pstrUsageALNetworkChat , -// pstrUsageALTelephonyDialer , -// pstrUsageALLogon , -// pstrUsageALLogoff , -// pstrUsageALLogonLogoff , -// pstrUsageALTermLockScrSav , -// pstrUsageALControlPannel , -// pstrUsageALCommandLineProcessorRun , -// pstrUsageALProcessTaskManager , -// pstrUsageALSelectTaskApplication , -// pstrUsageALNextTaskApplication , -// pstrUsageALPreviousTaskApplication , -// pstrUsageALPreemptiveHaltTaskApp , -// pstrUsageALIntegratedHelpCenter , -// pstrUsageALDocuments , -// pstrUsageALThesaurus , -// pstrUsageALDictionary , -// pstrUsageALDesktop , -// pstrUsageALSpellCheck , -// pstrUsageALGrammarCheck , -// pstrUsageALWirelessStatus , -// pstrUsageALKeyboardLayout , -// pstrUsageALVirusProtection , -// pstrUsageALEncryption , -// pstrUsageALScreenSaver , -// pstrUsageALAlarms , -// pstrUsageALClock , -// pstrUsageALFileBrowser , -// pstrUsageALPowerStatus , -// pstrUsageALImageBrowser , -// pstrUsageALAudioBrowser , -// pstrUsageALMovieBrowser , -// pstrUsageALDigitalRightsManager , -// pstrUsageALDigitalWallet , -// pstrUsagePageReserved , -// pstrUsageALInstantMessaging , -// pstrUsageALOEMFeaturesBrowser , -// pstrUsageALOEMHelp , -// pstrUsageALOnlineCommunity , -// pstrUsageALEntertainmentContentBrow , -// pstrUsageALOnlineShoppingBrowser , -// pstrUsageALSmartCardInfoHelp , -// pstrUsageALMarketMonitorFinBrowser , -// pstrUsageALCustomCorpNewsBrowser , -// pstrUsageALOnlineActivityBrowser , -// pstrUsageALResearchSearchBrowser , -// pstrUsageALAudioPlayer -//}; -//const char *consTitlesE[] PROGMEM = -//{ -// pstrUsageGenericGUIAppControls , -// pstrUsageACNew , -// pstrUsageACOpen , -// pstrUsageACClose , -// pstrUsageACExit , -// pstrUsageACMaximize , -// pstrUsageACMinimize , -// pstrUsageACSave , -// pstrUsageACPrint , -// pstrUsageACProperties , -// pstrUsageACUndo , -// pstrUsageACCopy , -// pstrUsageACCut , -// pstrUsageACPaste , -// pstrUsageACSelectAll , -// pstrUsageACFind , -// pstrUsageACFindAndReplace , -// pstrUsageACSearch , -// pstrUsageACGoto , -// pstrUsageACHome , -// pstrUsageACBack , -// pstrUsageACForward , -// pstrUsageACStop , -// pstrUsageACRefresh , -// pstrUsageACPreviousLink , -// pstrUsageACNextLink , -// pstrUsageACBookmarks , -// pstrUsageACHistory , -// pstrUsageACSubscriptions , -// pstrUsageACZoomIn , -// pstrUsageACZoomOut , -// pstrUsageACZoom , -// pstrUsageACFullScreenView , -// pstrUsageACNormalView , -// pstrUsageACViewToggle , -// pstrUsageACScrollUp , -// pstrUsageACScrollDown , -// pstrUsageACScroll , -// pstrUsageACPanLeft , -// pstrUsageACPanRight , -// pstrUsageACPan , -// pstrUsageACNewWindow , -// pstrUsageACTileHoriz , -// pstrUsageACTileVert , -// pstrUsageACFormat , -// pstrUsageACEdit , -// pstrUsageACBold , -// pstrUsageACItalics , -// pstrUsageACUnderline , -// pstrUsageACStrikethrough , -// pstrUsageACSubscript , -// pstrUsageACSuperscript , -// pstrUsageACAllCaps , -// pstrUsageACRotate , -// pstrUsageACResize , -// pstrUsageACFlipHorizontal , -// pstrUsageACFlipVertical , -// pstrUsageACMirrorHorizontal , -// pstrUsageACMirrorVertical , -// pstrUsageACFontSelect , -// pstrUsageACFontColor , -// pstrUsageACFontSize , -// pstrUsageACJustifyLeft , -// pstrUsageACJustifyCenterH , -// pstrUsageACJustifyRight , -// pstrUsageACJustifyBlockH , -// pstrUsageACJustifyTop , -// pstrUsageACJustifyCenterV , -// pstrUsageACJustifyBottom , -// pstrUsageACJustifyBlockV , -// pstrUsageACIndentDecrease , -// pstrUsageACIndentIncrease , -// pstrUsageACNumberedList , -// pstrUsageACRestartNumbering , -// pstrUsageACBulletedList , -// pstrUsageACPromote , -// pstrUsageACDemote , -// pstrUsageACYes , -// pstrUsageACNo , -// pstrUsageACCancel , -// pstrUsageACCatalog , -// pstrUsageACBuyChkout , -// pstrUsageACAddToCart , -// pstrUsageACExpand , -// pstrUsageACExpandAll , -// pstrUsageACCollapse , -// pstrUsageACCollapseAll , -// pstrUsageACPrintPreview , -// pstrUsageACPasteSpecial , -// pstrUsageACInsertMode , -// pstrUsageACDelete , -// pstrUsageACLock , -// pstrUsageACUnlock , -// pstrUsageACProtect , -// pstrUsageACUnprotect , -// pstrUsageACAttachComment , -// pstrUsageACDeleteComment , -// pstrUsageACViewComment , -// pstrUsageACSelectWord , -// pstrUsageACSelectSentence , -// pstrUsageACSelectParagraph , -// pstrUsageACSelectColumn , -// pstrUsageACSelectRow , -// pstrUsageACSelectTable , -// pstrUsageACSelectObject , -// pstrUsageACRedoRepeat , -// pstrUsageACSort , -// pstrUsageACSortAscending , -// pstrUsageACSortDescending , -// pstrUsageACFilter , -// pstrUsageACSetClock , -// pstrUsageACViewClock , -// pstrUsageACSelectTimeZone , -// pstrUsageACEditTimeZone , -// pstrUsageACSetAlarm , -// pstrUsageACClearAlarm , -// pstrUsageACSnoozeAlarm , -// pstrUsageACResetAlarm , -// pstrUsageACSyncronize , -// pstrUsageACSendReceive , -// pstrUsageACSendTo , -// pstrUsageACReply , -// pstrUsageACReplyAll , -// pstrUsageACForwardMessage , -// pstrUsageACSend , -// pstrUsageACAttachFile , -// pstrUsageACUpload , -// pstrUsageACDownload , -// pstrUsageACSetBorders , -// pstrUsageACInsertRow , -// pstrUsageACInsertColumn , -// pstrUsageACInsertFile , -// pstrUsageACInsertPicture , -// pstrUsageACInsertObject , -// pstrUsageACInsertSymbol , -// pstrUsageACSaveAndClose , -// pstrUsageACRename , -// pstrUsageACMerge , -// pstrUsageACSplit , -// pstrUsageACDistributeHorizontaly , -// pstrUsageACDistributeVerticaly -//}; -//const char *digitTitles0[] PROGMEM = -//{ -// pstrUsageDigitizer , -// pstrUsagePen , -// pstrUsageLightPen , -// pstrUsageTouchScreen , -// pstrUsageTouchPad , -// pstrUsageWhiteBoard , -// pstrUsageCoordinateMeasuringMachine , -// pstrUsage3DDigitizer , -// pstrUsageStereoPlotter , -// pstrUsageArticulatedArm , -// pstrUsageArmature , -// pstrUsageMultiplePointDigitizer , -// pstrUsageFreeSpaceWand -//}; -//const char *digitTitles1[] PROGMEM = -//{ -// pstrUsageStylus , -// pstrUsagePuck , -// pstrUsageFinger -// -//}; -//const char *digitTitles2[] PROGMEM = -//{ -// pstrUsageTipPressure , -// pstrUsageBarrelPressure , -// pstrUsageInRange , -// pstrUsageTouch , -// pstrUsageUntouch , -// pstrUsageTap , -// pstrUsageQuality , -// pstrUsageDataValid , -// pstrUsageTransducerIndex , -// pstrUsageTabletFunctionKeys , -// pstrUsageProgramChangeKeys , -// pstrUsageBatteryStrength , -// pstrUsageInvert , -// pstrUsageXTilt , -// pstrUsageYTilt , -// pstrUsageAzimuth , -// pstrUsageAltitude , -// pstrUsageTwist , -// pstrUsageTipSwitch , -// pstrUsageSecondaryTipSwitch , -// pstrUsageBarrelSwitch , -// pstrUsageEraser , -// pstrUsageTabletPick -//}; -//const char *aplphanumTitles0[] PROGMEM = -//{ -// pstrUsageAlphanumericDisplay, -// pstrUsageBitmappedDisplay -//}; -//const char *aplphanumTitles1[] PROGMEM = -//{ -// pstrUsageDisplayAttributesReport , -// pstrUsageASCIICharacterSet , -// pstrUsageDataReadBack , -// pstrUsageFontReadBack , -// pstrUsageDisplayControlReport , -// pstrUsageClearDisplay , -// pstrUsageDisplayEnable , -// pstrUsageScreenSaverDelay , -// pstrUsageScreenSaverEnable , -// pstrUsageVerticalScroll , -// pstrUsageHorizontalScroll , -// pstrUsageCharacterReport , -// pstrUsageDisplayData , -// pstrUsageDisplayStatus , -// pstrUsageStatusNotReady , -// pstrUsageStatusReady , -// pstrUsageErrorNotALoadableCharacter , -// pstrUsageErrorFotDataCanNotBeRead , -// pstrUsageCursorPositionReport , -// pstrUsageRow , -// pstrUsageColumn , -// pstrUsageRows , -// pstrUsageColumns , -// pstrUsageCursorPixelPosition , -// pstrUsageCursorMode , -// pstrUsageCursorEnable , -// pstrUsageCursorBlink , -// pstrUsageFontReport , -// pstrUsageFontData , -// pstrUsageCharacterWidth , -// pstrUsageCharacterHeight , -// pstrUsageCharacterSpacingHorizontal , -// pstrUsageCharacterSpacingVertical , -// pstrUsageUnicodeCharset , -// pstrUsageFont7Segment , -// pstrUsage7SegmentDirectMap , -// pstrUsageFont14Segment , -// pstrUsage14SegmentDirectMap , -// pstrUsageDisplayBrightness , -// pstrUsageDisplayContrast , -// pstrUsageCharacterAttribute , -// pstrUsageAttributeReadback , -// pstrUsageAttributeData , -// pstrUsageCharAttributeEnhance , -// pstrUsageCharAttributeUnderline , -// pstrUsageCharAttributeBlink -//}; -//const char *aplphanumTitles2[] PROGMEM = -//{ -// pstrUsageBitmapSizeX , -// pstrUsageBitmapSizeY , -// pstrUsagePageReserved , -// pstrUsageBitDepthFormat , -// pstrUsageDisplayOrientation , -// pstrUsagePaletteReport , -// pstrUsagePaletteDataSize , -// pstrUsagePaletteDataOffset , -// pstrUsagePaletteData , -// pstrUsageBlitReport , -// pstrUsageBlitRectangleX1 , -// pstrUsageBlitRectangleY1 , -// pstrUsageBlitRectangleX2 , -// pstrUsageBlitRectangleY2 , -// pstrUsageBlitData , -// pstrUsageSoftButton , -// pstrUsageSoftButtonID , -// pstrUsageSoftButtonSide , -// pstrUsageSoftButtonOffset1 , -// pstrUsageSoftButtonOffset2 , -// pstrUsageSoftButtonReport -//}; -//const char *medInstrTitles0[] PROGMEM = -//{ -// pstrUsageVCRAcquisition , -// pstrUsageFreezeThaw , -// pstrUsageClipStore , -// pstrUsageUpdate , -// pstrUsageNext , -// pstrUsageSave , -// pstrUsagePrint , -// pstrUsageMicrophoneEnable -//}; -//const char *medInstrTitles1[] PROGMEM = -//{ -// pstrUsageCine , -// pstrUsageTransmitPower , -// pstrUsageVolume , -// pstrUsageFocus , -// pstrUsageDepth -//}; -//const char *medInstrTitles2[] PROGMEM = -//{ -// pstrUsageSoftStepPrimary , -// pstrUsageSoftStepSecondary -//}; -//const char *medInstrTitles3[] PROGMEM = -//{ -// pstrUsageZoomSelect , -// pstrUsageZoomAdjust , -// pstrUsageSpectralDopplerModeSelect , -// pstrUsageSpectralDopplerModeAdjust , -// pstrUsageColorDopplerModeSelect , -// pstrUsageColorDopplerModeAdjust , -// pstrUsageMotionModeSelect , -// pstrUsageMotionModeAdjust , -// pstrUsage2DModeSelect , -// pstrUsage2DModeAdjust -//}; -//const char *medInstrTitles4[] PROGMEM = -//{ -// pstrUsageSoftControlSelect , -// pstrUsageSoftControlAdjust -//}; - -#endif // __HIDUSAGETITLEARRAYS_H__ diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/keywords.txt b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/keywords.txt deleted file mode 100644 index f4e19cd133..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/keywords.txt +++ /dev/null @@ -1,371 +0,0 @@ -#################################################### -# Syntax Coloring Map For USB Library -#################################################### - -#################################################### -# Datatypes (KEYWORD1) -#################################################### - -USB KEYWORD1 -USBHub KEYWORD1 - -#################################################### -# Syntax Coloring Map For BTD (Bluetooth) Library -#################################################### - -#################################################### -# Datatypes (KEYWORD1) -#################################################### - -BTD KEYWORD1 - -#################################################### -# Methods and Functions (KEYWORD2) -#################################################### -Task KEYWORD2 - -#################################################### -# Syntax Coloring Map For PS3/PS4 Bluetooth/USB Library -#################################################### - -#################################################### -# Datatypes (KEYWORD1) -#################################################### - -PS3BT KEYWORD1 -PS3USB KEYWORD1 -PS4BT KEYWORD1 -PS4USB KEYWORD1 - -#################################################### -# Methods and Functions (KEYWORD2) -#################################################### -setBdaddr KEYWORD2 -getBdaddr KEYWORD2 -setMoveBdaddr KEYWORD2 -getMoveBdaddr KEYWORD2 -getMoveCalibration KEYWORD2 - -getButtonPress KEYWORD2 -getButtonClick KEYWORD2 -getAnalogButton KEYWORD2 -getAnalogHat KEYWORD2 -getSensor KEYWORD2 -getAngle KEYWORD2 -get9DOFValues KEYWORD2 -getStatus KEYWORD2 -printStatusString KEYWORD2 -getTemperature KEYWORD2 -disconnect KEYWORD2 - -setAllOff KEYWORD2 -setRumbleOff KEYWORD2 -setRumbleOn KEYWORD2 -setLedOff KEYWORD2 -setLedOn KEYWORD2 -setLedToggle KEYWORD2 -setLedFlash KEYWORD2 -moveSetBulb KEYWORD2 -moveSetRumble KEYWORD2 - -attachOnInit KEYWORD2 - -PS3Connected KEYWORD2 -PS3MoveConnected KEYWORD2 -PS3NavigationConnected KEYWORD2 - -isReady KEYWORD2 -watingForConnection KEYWORD2 - -isTouching KEYWORD2 -getX KEYWORD2 -getY KEYWORD2 -getTouchCounter KEYWORD2 - -getUsbStatus KEYWORD2 -getAudioStatus KEYWORD2 -getMicStatus KEYWORD2 - -#################################################### -# Constants and enums (LITERAL1) -#################################################### -OFF LITERAL1 -LED1 LITERAL1 -LED2 LITERAL1 -LED3 LITERAL1 -LED4 LITERAL1 -LED5 LITERAL1 -LED6 LITERAL1 -LED7 LITERAL1 -LED8 LITERAL1 -LED9 LITERAL1 -LED10 LITERAL1 - -Red LITERAL1 -Green LITERAL1 -Blue LITERAL1 -Yellow LITERAL1 -Lightblue LITERAL1 -Purble LITERAL1 -White LITERAL1 -Off LITERAL1 - -SELECT LITERAL1 -L3 LITERAL1 -R3 LITERAL1 -START LITERAL1 -UP LITERAL1 -RIGHT LITERAL1 -DOWN LITERAL1 -LEFT LITERAL1 -L2 LITERAL1 -R2 LITERAL1 -L1 LITERAL1 -R1 LITERAL1 -TRIANGLE LITERAL1 -CIRCLE LITERAL1 -CROSS LITERAL1 -SQUARE LITERAL1 -PS LITERAL1 -MOVE LITERAL1 -T LITERAL1 - -SHARE LITERAL1 -OPTIONS LITERAL1 -TOUCHPAD LITERAL1 - -LeftHatX LITERAL1 -LeftHatY LITERAL1 -RightHatX LITERAL1 -RightHatY LITERAL1 - -aX LITERAL1 -aY LITERAL1 -aZ LITERAL1 -gX LITERAL1 -gY LITERAL1 -gZ LITERAL1 -aXmove LITERAL1 -aYmove LITERAL1 -aZmove LITERAL1 -gXmove LITERAL1 -gYmove LITERAL1 -gZmove LITERAL1 -tempMove LITERAL1 -mXmove LITERAL1 -mZmove LITERAL1 -mYmove LITERAL1 - -Pitch LITERAL1 -Roll LITERAL1 - -Plugged LITERAL1 -Unplugged LITERAL1 -Charging LITERAL1 -NotCharging LITERAL1 -Shutdown LITERAL1 -Dying LITERAL1 -Low LITERAL1 -High LITERAL1 -Full LITERAL1 -MoveCharging LITERAL1 -MoveNotCharging LITERAL1 -MoveShutdown LITERAL1 -MoveDying LITERAL1 -MoveLow LITERAL1 -MoveHigh LITERAL1 -MoveFull LITERAL1 -CableRumble LITERAL1 -Cable LITERAL1 -BluetoothRumble LITERAL1 -Bluetooth LITERAL1 - -RumbleHigh LITERAL1 -RumbleLow LITERAL1 - -#################################################### -# Syntax Coloring Map For Xbox 360 Libraries -#################################################### - -#################################################### -# Datatypes (KEYWORD1) -#################################################### - -XBOXUSB KEYWORD1 -XBOXONE KEYWORD1 -XBOXOLD KEYWORD1 -XBOXRECV KEYWORD1 - -#################################################### -# Methods and Functions (KEYWORD2) -#################################################### - -setLedRaw KEYWORD2 -setLedBlink KEYWORD2 -setLedMode KEYWORD2 -getBatteryLevel KEYWORD2 -buttonChanged KEYWORD2 - -XboxReceiverConnected KEYWORD2 -Xbox360Connected KEYWORD2 -XboxOneConnected KEYWORD2 - -#################################################### -# Constants and enums (LITERAL1) -#################################################### - -ALL LITERAL1 - -ROTATING LITERAL1 -FASTBLINK LITERAL1 -SLOWBLINK LITERAL1 -ALTERNATING LITERAL1 - -BACK LITERAL1 - -XBOX LITERAL1 -SYNC LITERAL1 - -BLACK LITERAL1 -WHITE LITERAL1 - -A LITERAL1 -B LITERAL1 -X LITERAL1 -Y LITERAL1 - -#################################################### -# Syntax Coloring Map For RFCOMM/SPP Library -#################################################### - -#################################################### -# Datatypes (KEYWORD1) -#################################################### - -SPP KEYWORD1 - -#################################################### -# Methods and Functions (KEYWORD2) -#################################################### - -connected KEYWORD2 -discard KEYWORD2 - -#################################################### -# Syntax Coloring Map For Wiimote Library -#################################################### - -#################################################### -# Datatypes (KEYWORD1) -#################################################### - -WII KEYWORD1 - -#################################################### -# Methods and Functions (KEYWORD2) -#################################################### - -wiimoteConnected KEYWORD2 -nunchuckConnected KEYWORD2 -motionPlusConnected KEYWORD2 -wiiUProControllerConnected KEYWORD2 -wiiBalanceBoardConnected KEYWORD2 -setRumbleToggle KEYWORD2 -getPitch KEYWORD2 -getRoll KEYWORD2 -getYaw KEYWORD2 -getWiimotePitch KEYWORD2 -getWiimoteRoll KEYWORD2 -getNunchuckPitch KEYWORD2 -getNunchuckRoll KEYWORD2 -PAIR KEYWORD2 -statusRequest KEYWORD2 -getBatteryLevel KEYWORD2 -getWiiState KEYWORD2 -getWeight KEYWORD2 -getTotalWeight KEYWORD2 -getWeightRaw KEYWORD2 - -#################################################### -# Constants and enums (LITERAL1) -#################################################### - -PLUS LITERAL1 -MINUS LITERAL1 -ONE LITERAL1 -TWO LITERAL1 -HOME LITERAL1 -Z LITERAL1 -C LITERAL1 -L LITERAL1 -R LITERAL1 -ZL LITERAL1 -ZR LITERAL1 -HatX LITERAL1 -HatY LITERAL1 -TopRight LITERAL1 -BotRight LITERAL1 -TopLeft LITERAL1 -BotLeft LITERAL1 - -#################################################### -# Methods and Functions for the IR Camera -#################################################### - -IRinitialize KEYWORD2 -isIRCameraEnabled KEYWORD2 -getIRx1 KEYWORD2 -getIRy1 KEYWORD2 -getIRs1 KEYWORD2 -getIRx2 KEYWORD2 -getIRy2 KEYWORD2 -getIRs2 KEYWORD2 -getIRx3 KEYWORD2 -getIRy3 KEYWORD2 -getIRs3 KEYWORD2 -getIRx4 KEYWORD2 -getIRy4 KEYWORD2 -getIRs4 KEYWORD2 - -#################################################### -# Syntax Coloring Map For BTHID Library -#################################################### - -#################################################### -# Datatypes (KEYWORD1) -#################################################### - -BTHID KEYWORD1 - -#################################################### -# Methods and Functions (KEYWORD2) -#################################################### -SetReportParser KEYWORD2 -setProtocolMode KEYWORD2 - -#################################################### -# Syntax Coloring Map For PS Buzz Library -#################################################### - -#################################################### -# Datatypes (KEYWORD1) -#################################################### - -PSBuzz KEYWORD1 - -#################################################### -# Methods and Functions (KEYWORD2) -#################################################### - -setLedOnAll KEYWORD2 -setLedOffAll KEYWORD2 - -#################################################### -# Constants and enums (LITERAL1) -#################################################### - -RED LITERAL1 -YELLOW LITERAL1 -GREEN LITERAL1 -ORANGE LITERAL1 -BLUE LITERAL1 diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/library.json b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/library.json deleted file mode 100644 index 1d649b1e13..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/library.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "name": "USB-Host-Shield-20", - "keywords": "usb, host, ftdi, adk, acm, pl2303, hid, bluetooth, spp, ps3, ps4, buzz, xbox, wii, mass storage", - "description": "Revision 2.0 of MAX3421E-based USB Host Shield Library", - "authors": - [ - { - "name": "Oleg Mazurov", - "email": "mazurov@circuitsathome.com", - "url": "http://www.circuitsathome.com", - "maintainer": true - }, - { - "name": "Alexei Glushchenko", - "email": "alex-gl@mail.ru" - }, - { - "name": "Kristian Lauszus", - "email": "kristianl@tkjelectronics.com", - "url": "http://tkjelectronics.com", - "maintainer": true - }, - { - "name": "Andrew Kroll", - "email": "xxxajk@gmail.com", - "maintainer": true - } - ], - "repository": - { - "type": "git", - "url": "https://github.com/felis/USB_Host_Shield_2.0.git" - }, - "examples": - [ - "examples/*/*.ino", - "examples/*/*/*.ino" - ], - "frameworks": "arduino", - "platforms": - [ - "atmelavr", - "teensy", - "atmelsam", - "nordicnrf51" - ] -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/library.properties b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/library.properties deleted file mode 100644 index 7881b05e9d..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/library.properties +++ /dev/null @@ -1,9 +0,0 @@ -name=USB Host Shield Library 2.0 -version=1.1.0 -author=Oleg Mazurov (Circuits@Home) , Kristian Lauszus (TKJ Electronics) , Andrew Kroll , Alexei Glushchenko (Circuits@Home) -maintainer=Oleg Mazurov (Circuits@Home) , Kristian Lauszus (TKJ Electronics) , Andrew Kroll -sentence=Revision 2.0 of MAX3421E-based USB Host Shield Library. -paragraph=Supports HID devices, FTDI, ADK, ACM, PL2303, Bluetooth HID devices, SPP communication and mass storage devices. Furthermore it supports PS3, PS4, PS Buzz, Wii and Xbox controllers. -category=Other -url=https://github.com/felis/USB_Host_Shield_2.0 -architectures=* \ No newline at end of file diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/macros.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/macros.h deleted file mode 100644 index e14a711fab..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/macros.h +++ /dev/null @@ -1,82 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ - -#if !defined(_usb_h_) || defined(MACROS_H) -#error "Never include macros.h directly; include Usb.h instead" -#else -#define MACROS_H - -//////////////////////////////////////////////////////////////////////////////// -// HANDY MACROS -//////////////////////////////////////////////////////////////////////////////// - -#define VALUE_BETWEEN(v,l,h) (((v)>(l)) && ((v)<(h))) -#define VALUE_WITHIN(v,l,h) (((v)>=(l)) && ((v)<=(h))) -#define output_pgm_message(wa,fp,mp,el) wa = &mp, fp((char *)pgm_read_pointer(wa), el) -#define output_if_between(v,l,h,wa,fp,mp,el) if(VALUE_BETWEEN(v,l,h)) output_pgm_message(wa,fp,mp[v-(l+1)],el); - -#define SWAP(a, b) (((a) ^= (b)), ((b) ^= (a)), ((a) ^= (b))) -#ifndef __BYTE_GRABBING_DEFINED__ -#define __BYTE_GRABBING_DEFINED__ 1 -#ifdef BROKEN_OPTIMIZER_LITTLE_ENDIAN -// Note: Use this if your compiler generates horrible assembler! -#define BGRAB0(__usi__) (((uint8_t *)&(__usi__))[0]) -#define BGRAB1(__usi__) (((uint8_t *)&(__usi__))[1]) -#define BGRAB2(__usi__) (((uint8_t *)&(__usi__))[2]) -#define BGRAB3(__usi__) (((uint8_t *)&(__usi__))[3]) -#define BGRAB4(__usi__) (((uint8_t *)&(__usi__))[4]) -#define BGRAB5(__usi__) (((uint8_t *)&(__usi__))[5]) -#define BGRAB6(__usi__) (((uint8_t *)&(__usi__))[6]) -#define BGRAB7(__usi__) (((uint8_t *)&(__usi__))[7]) -#else -// Note: The cast alone to uint8_t is actually enough. -// GCC throws out the "& 0xff", and the size is no different. -// Some compilers need it. -#define BGRAB0(__usi__) ((uint8_t)((__usi__) & 0xff )) -#define BGRAB1(__usi__) ((uint8_t)(((__usi__) >> 8) & 0xff)) -#define BGRAB2(__usi__) ((uint8_t)(((__usi__) >> 16) & 0xff)) -#define BGRAB3(__usi__) ((uint8_t)(((__usi__) >> 24) & 0xff)) -#define BGRAB4(__usi__) ((uint8_t)(((__usi__) >> 32) & 0xff)) -#define BGRAB5(__usi__) ((uint8_t)(((__usi__) >> 40) & 0xff)) -#define BGRAB6(__usi__) ((uint8_t)(((__usi__) >> 48) & 0xff)) -#define BGRAB7(__usi__) ((uint8_t)(((__usi__) >> 56) & 0xff)) -#endif -#define BOVER1(__usi__) ((uint16_t)(__usi__) << 8) -#define BOVER2(__usi__) ((uint32_t)(__usi__) << 16) -#define BOVER3(__usi__) ((uint32_t)(__usi__) << 24) -#define BOVER4(__usi__) ((uint64_t)(__usi__) << 32) -#define BOVER5(__usi__) ((uint64_t)(__usi__) << 40) -#define BOVER6(__usi__) ((uint64_t)(__usi__) << 48) -#define BOVER7(__usi__) ((uint64_t)(__usi__) << 56) - -// These are the smallest and fastest ways I have found so far in pure C/C++. -#define BMAKE16(__usc1__,__usc0__) ((uint16_t)((uint16_t)(__usc0__) | (uint16_t)BOVER1(__usc1__))) -#define BMAKE32(__usc3__,__usc2__,__usc1__,__usc0__) ((uint32_t)((uint32_t)(__usc0__) | (uint32_t)BOVER1(__usc1__) | (uint32_t)BOVER2(__usc2__) | (uint32_t)BOVER3(__usc3__))) -#define BMAKE64(__usc7__,__usc6__,__usc5__,__usc4__,__usc3__,__usc2__,__usc1__,__usc0__) ((uint64_t)((uint64_t)__usc0__ | (uint64_t)BOVER1(__usc1__) | (uint64_t)BOVER2(__usc2__) | (uint64_t)BOVER3(__usc3__) | (uint64_t)BOVER4(__usc4__) | (uint64_t)BOVER5(__usc5__) | (uint64_t)BOVER6(__usc6__) | (uint64_t)BOVER1(__usc7__))) -#endif - -/* - * Debug macros: Strings are stored in progmem (flash) instead of RAM. - */ -#define USBTRACE(s) (Notify(PSTR(s), 0x80)) -#define USBTRACE1(s,l) (Notify(PSTR(s), l)) -#define USBTRACE2(s,r) (Notify(PSTR(s), 0x80), D_PrintHex((r), 0x80), Notify(PSTR("\r\n"), 0x80)) -#define USBTRACE3(s,r,l) (Notify(PSTR(s), l), D_PrintHex((r), l), Notify(PSTR("\r\n"), l)) - - -#endif /* MACROS_H */ - diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/masstorage.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/masstorage.cpp deleted file mode 100644 index 9299f71a43..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/masstorage.cpp +++ /dev/null @@ -1,1266 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ - -#include "masstorage.h" - -const uint8_t BulkOnly::epDataInIndex = 1; -const uint8_t BulkOnly::epDataOutIndex = 2; -const uint8_t BulkOnly::epInterruptInIndex = 3; - -//////////////////////////////////////////////////////////////////////////////// - -// Interface code - -//////////////////////////////////////////////////////////////////////////////// - -/** - * Get the capacity of the media - * - * @param lun Logical Unit Number - * @return media capacity - */ -uint32_t BulkOnly::GetCapacity(uint8_t lun) { - if(LUNOk[lun]) - return CurrentCapacity[lun]; - return 0LU; -} - -/** - * Get the sector (block) size used on the media - * - * @param lun Logical Unit Number - * @return media sector size - */ -uint16_t BulkOnly::GetSectorSize(uint8_t lun) { - if(LUNOk[lun]) - return CurrentSectorSize[lun]; - return 0U; -} - -/** - * Test if LUN is ready for use - * - * @param lun Logical Unit Number - * @return true if LUN is ready for use - */ -bool BulkOnly::LUNIsGood(uint8_t lun) { - return LUNOk[lun]; -} - -/** - * Test if LUN is write protected - * - * @param lun Logical Unit Number - * @return cached status of write protect switch - */ -bool BulkOnly::WriteProtected(uint8_t lun) { - return WriteOk[lun]; -} - -/** - * Wrap and execute a SCSI CDB with length of 6 - * - * @param cdb CDB to execute - * @param buf_size Size of expected transaction - * @param buf Buffer - * @param dir MASS_CMD_DIR_IN | MASS_CMD_DIR_OUT - * @return - */ -uint8_t BulkOnly::SCSITransaction6(CDB6_t *cdb, uint16_t buf_size, void *buf, uint8_t dir) { - // promote buf_size to 32bits. - CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)buf_size, cdb, dir); - //SetCurLUN(cdb->LUN); - return (HandleSCSIError(Transaction(&cbw, buf_size, buf))); -} - -/** - * Wrap and execute a SCSI CDB with length of 10 - * - * @param cdb CDB to execute - * @param buf_size Size of expected transaction - * @param buf Buffer - * @param dir MASS_CMD_DIR_IN | MASS_CMD_DIR_OUT - * @return - */ -uint8_t BulkOnly::SCSITransaction10(CDB10_t *cdb, uint16_t buf_size, void *buf, uint8_t dir) { - // promote buf_size to 32bits. - CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)buf_size, cdb, dir); - //SetCurLUN(cdb->LUN); - return (HandleSCSIError(Transaction(&cbw, buf_size, buf))); -} - -/** - * Lock or Unlock the tray or door on device. - * Caution: Some devices with buggy firmware will lock up. - * - * @param lun Logical Unit Number - * @param lock 1 to lock, 0 to unlock - * @return - */ -uint8_t BulkOnly::LockMedia(uint8_t lun, uint8_t lock) { - Notify(PSTR("\r\nLockMedia\r\n"), 0x80); - Notify(PSTR("---------\r\n"), 0x80); - - CDB6_t cdb = CDB6_t(SCSI_CMD_PREVENT_REMOVAL, lun, (uint8_t)0, lock); - return SCSITransaction6(&cdb, (uint16_t)0, NULL, (uint8_t)MASS_CMD_DIR_IN); -} - -/** - * Media control, for spindle motor and media tray or door. - * This includes CDROM, TAPE and anything with a media loader. - * - * @param lun Logical Unit Number - * @param ctl 0x00 Stop Motor, 0x01 Start Motor, 0x02 Eject Media, 0x03 Load Media - * @return 0 on success - */ -uint8_t BulkOnly::MediaCTL(uint8_t lun, uint8_t ctl) { - Notify(PSTR("\r\nMediaCTL\r\n"), 0x80); - Notify(PSTR("-----------------\r\n"), 0x80); - - uint8_t rcode = MASS_ERR_UNIT_NOT_READY; - if(bAddress) { - CDB6_t cdb = CDB6_t(SCSI_CMD_START_STOP_UNIT, lun, ctl & 0x03, 0); - rcode = SCSITransaction6(&cdb, (uint16_t)0, NULL, (uint8_t)MASS_CMD_DIR_OUT); - } else { - SetCurLUN(lun); - } - return rcode; -} - -/** - * Read data from media - * - * @param lun Logical Unit Number - * @param addr LBA address on media to read - * @param bsize size of a block (we should probably use the cached size) - * @param blocks how many blocks to read - * @param buf memory that is able to hold the requested data - * @return 0 on success - */ -uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf) { - if(!LUNOk[lun]) return MASS_ERR_NO_MEDIA; - Notify(PSTR("\r\nRead LUN:\t"), 0x80); - D_PrintHex (lun, 0x90); - Notify(PSTR("\r\nLBA:\t\t"), 0x90); - D_PrintHex (addr, 0x90); - Notify(PSTR("\r\nblocks:\t\t"), 0x90); - D_PrintHex (blocks, 0x90); - Notify(PSTR("\r\nblock size:\t"), 0x90); - D_PrintHex (bsize, 0x90); - Notify(PSTR("\r\n---------\r\n"), 0x80); - CDB10_t cdb = CDB10_t(SCSI_CMD_READ_10, lun, blocks, addr); - -again: - uint8_t er = SCSITransaction10(&cdb, ((uint16_t)bsize * blocks), buf, (uint8_t)MASS_CMD_DIR_IN); - - if(er == MASS_ERR_STALL) { - MediaCTL(lun, 1); - delay(150); - if(!TestUnitReady(lun)) goto again; - } - return er; -} - -/** - * Write data to media - * - * @param lun Logical Unit Number - * @param addr LBA address on media to write - * @param bsize size of a block (we should probably use the cached size) - * @param blocks how many blocks to write - * @param buf memory that contains the data to write - * @return 0 on success - */ -uint8_t BulkOnly::Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t * buf) { - if(!LUNOk[lun]) return MASS_ERR_NO_MEDIA; - if(!WriteOk[lun]) return MASS_ERR_WRITE_PROTECTED; - Notify(PSTR("\r\nWrite LUN:\t"), 0x80); - D_PrintHex (lun, 0x90); - Notify(PSTR("\r\nLBA:\t\t"), 0x90); - D_PrintHex (addr, 0x90); - Notify(PSTR("\r\nblocks:\t\t"), 0x90); - D_PrintHex (blocks, 0x90); - Notify(PSTR("\r\nblock size:\t"), 0x90); - D_PrintHex (bsize, 0x90); - Notify(PSTR("\r\n---------\r\n"), 0x80); - CDB10_t cdb = CDB10_t(SCSI_CMD_WRITE_10, lun, blocks, addr); - -again: - uint8_t er = SCSITransaction10(&cdb, ((uint16_t)bsize * blocks), (void*)buf, (uint8_t)MASS_CMD_DIR_OUT); - - if(er == MASS_ERR_WRITE_STALL) { - MediaCTL(lun, 1); - delay(150); - if(!TestUnitReady(lun)) goto again; - } - return er; -} - -// End of user functions, the remaining code below is driver internals. -// Only developer serviceable parts below! - -//////////////////////////////////////////////////////////////////////////////// - -// Main driver code - -//////////////////////////////////////////////////////////////////////////////// - -BulkOnly::BulkOnly(USB *p) : -pUsb(p), -bAddress(0), -bIface(0), -bNumEP(1), -qNextPollTime(0), -bPollEnable(false), -//dCBWTag(0), -bLastUsbError(0) { - ClearAllEP(); - dCBWTag = 0; - if(pUsb) - pUsb->RegisterDeviceClass(this); -} - -/** - * USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET == success - * We need to standardize either the rcode, or change the API to return values - * so a signal that additional actions are required can be produced. - * Some of these codes do exist already. - * - * TECHNICAL: We could do most of this code elsewhere, with the exception of checking the class instance. - * Doing so would save some program memory when using multiple drivers. - * - * @param parent USB address of parent - * @param port address of port on parent - * @param lowspeed true if device is low speed - * @return - */ -uint8_t BulkOnly::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) { - - const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR); - - uint8_t buf[constBufSize]; - USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); - uint8_t rcode; - UsbDevice *p = NULL; - EpInfo *oldep_ptr = NULL; - USBTRACE("MS ConfigureDevice\r\n"); - ClearAllEP(); - AddressPool &addrPool = pUsb->GetAddressPool(); - - - if(bAddress) - return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; - - // - // Get pointer to pseudo device with address 0 assigned - p = addrPool.GetUsbDevicePtr(0); - if(!p) { - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - } - - if(!p->epinfo) { - USBTRACE("epinfo\r\n"); - return USB_ERROR_EPINFO_IS_NULL; - } - - // Save old pointer to EP_RECORD of address 0 - oldep_ptr = p->epinfo; - - // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence - p->epinfo = epInfo; - - p->lowspeed = lowspeed; - // Get device descriptor - rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf); - - // Restore p->epinfo - p->epinfo = oldep_ptr; - - if(rcode) { - goto FailGetDevDescr; - } - // Allocate new address according to device class - bAddress = addrPool.AllocAddress(parent, false, port); - - if(!bAddress) - return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; - - // Extract Max Packet Size from the device descriptor - epInfo[0].maxPktSize = udd->bMaxPacketSize0; - // Steal and abuse from epInfo structure to save on memory. - epInfo[1].epAddr = udd->bNumConfigurations; - // - return USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET; - -FailGetDevDescr: -#ifdef DEBUG_USB_HOST - NotifyFailGetDevDescr(rcode); -#endif - rcode = USB_ERROR_FailGetDevDescr; - - Release(); - return rcode; -}; - -/** - * - * @param parent (not used) - * @param port (not used) - * @param lowspeed true if device is low speed - * @return 0 for success - */ -uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) { - uint8_t rcode; - uint8_t num_of_conf = epInfo[1].epAddr; // number of configurations - epInfo[1].epAddr = 0; - USBTRACE("MS Init\r\n"); - - AddressPool &addrPool = pUsb->GetAddressPool(); - UsbDevice *p = addrPool.GetUsbDevicePtr(bAddress); - - if(!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - // Assign new address to the device - delay(2000); - rcode = pUsb->setAddr(0, 0, bAddress); - - if(rcode) { - p->lowspeed = false; - addrPool.FreeAddress(bAddress); - bAddress = 0; - USBTRACE2("setAddr:", rcode); - return rcode; - } - - USBTRACE2("Addr:", bAddress); - - p->lowspeed = false; - - p = addrPool.GetUsbDevicePtr(bAddress); - - if(!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - p->lowspeed = lowspeed; - - // Assign epInfo to epinfo pointer - rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); - - if(rcode) - goto FailSetDevTblEntry; - - USBTRACE2("NC:", num_of_conf); - - for(uint8_t i = 0; i < num_of_conf; i++) { - ConfigDescParser< USB_CLASS_MASS_STORAGE, - MASS_SUBCLASS_SCSI, - MASS_PROTO_BBB, - CP_MASK_COMPARE_CLASS | - CP_MASK_COMPARE_SUBCLASS | - CP_MASK_COMPARE_PROTOCOL > BulkOnlyParser(this); - - rcode = pUsb->getConfDescr(bAddress, 0, i, &BulkOnlyParser); - - if(rcode) - goto FailGetConfDescr; - - if(bNumEP > 1) - break; - } - - if(bNumEP < 3) - return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - - // Assign epInfo to epinfo pointer - pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); - - USBTRACE2("Conf:", bConfNum); - - // Set Configuration Value - rcode = pUsb->setConf(bAddress, 0, bConfNum); - - if(rcode) - goto FailSetConfDescr; - - //Linux does a 1sec delay after this. - delay(1000); - - rcode = GetMaxLUN(&bMaxLUN); - if(rcode) - goto FailGetMaxLUN; - - if(bMaxLUN >= MASS_MAX_SUPPORTED_LUN) bMaxLUN = MASS_MAX_SUPPORTED_LUN - 1; - ErrorMessage (PSTR("MaxLUN"), bMaxLUN); - - delay(1000); // Delay a bit for slow firmware. - - for(uint8_t lun = 0; lun <= bMaxLUN; lun++) { - InquiryResponse response; - rcode = Inquiry(lun, sizeof (InquiryResponse), (uint8_t*) & response); - if(rcode) { - ErrorMessage (PSTR("Inquiry"), rcode); - } else { -#if 0 - printf("LUN %i `", lun); - uint8_t *buf = response.VendorID; - for(int i = 0; i < 28; i++) printf("%c", buf[i]); - printf("'\r\nQualifier %1.1X ", response.PeripheralQualifier); - printf("Device type %2.2X ", response.DeviceType); - printf("RMB %1.1X ", response.Removable); - printf("SSCS %1.1X ", response.SCCS); - uint8_t sv = response.Version; - printf("SCSI version %2.2X\r\nDevice conforms to ", sv); - switch(sv) { - case 0: - printf("No specific"); - break; - case 1: - printf("ANSI X3.131-1986 (ANSI 1)"); - break; - case 2: - printf("ANSI X3.131-1994 (ANSI 2)"); - break; - case 3: - printf("ANSI INCITS 301-1997 (SPC)"); - break; - case 4: - printf("ANSI INCITS 351-2001 (SPC-2)"); - break; - case 5: - printf("ANSI INCITS 408-2005 (SPC-4)"); - break; - case 6: - printf("T10/1731-D (SPC-4)"); - break; - default: - printf("unknown"); - } - printf(" standards.\r\n"); -#endif - uint8_t tries = 0xf0; - while((rcode = TestUnitReady(lun))) { - if(rcode == 0x08) break; // break on no media, this is OK to do. - // try to lock media and spin up - if(tries < 14) { - LockMedia(lun, 1); - MediaCTL(lun, 1); // I actually have a USB stick that needs this! - } else delay(2 * (tries + 1)); - tries++; - if(!tries) break; - } - if(!rcode) { - delay(1000); - LUNOk[lun] = CheckLUN(lun); - if(!LUNOk[lun]) LUNOk[lun] = CheckLUN(lun); - } - } - } - - - CheckMedia(); - - rcode = OnInit(); - - if(rcode) - goto FailOnInit; - -#ifdef DEBUG_USB_HOST - USBTRACE("MS configured\r\n\r\n"); -#endif - - bPollEnable = true; - - //USBTRACE("Poll enabled\r\n"); - return 0; - -FailSetConfDescr: -#ifdef DEBUG_USB_HOST - NotifyFailSetConfDescr(); - goto Fail; -#endif - -FailOnInit: -#ifdef DEBUG_USB_HOST - USBTRACE("OnInit:"); - goto Fail; -#endif - -FailGetMaxLUN: -#ifdef DEBUG_USB_HOST - USBTRACE("GetMaxLUN:"); - goto Fail; -#endif - - //#ifdef DEBUG_USB_HOST - //FailInvalidSectorSize: - // USBTRACE("Sector Size is NOT VALID: "); - // goto Fail; - //#endif - -FailSetDevTblEntry: -#ifdef DEBUG_USB_HOST - NotifyFailSetDevTblEntry(); - goto Fail; -#endif - -FailGetConfDescr: -#ifdef DEBUG_USB_HOST - NotifyFailGetConfDescr(); -#endif - -#ifdef DEBUG_USB_HOST -Fail: - NotifyFail(rcode); -#endif - Release(); - return rcode; -} - -/** - * For driver use only. - * - * @param conf - * @param iface - * @param alt - * @param proto - * @param pep - */ -void BulkOnly::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR * pep) { - ErrorMessage (PSTR("Conf.Val"), conf); - ErrorMessage (PSTR("Iface Num"), iface); - ErrorMessage (PSTR("Alt.Set"), alt); - - bConfNum = conf; - - uint8_t index; - -#if 1 - if((pep->bmAttributes & 0x02) == 2) { - index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex; - // Fill in the endpoint info structure - epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); - epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; - epInfo[index].epAttribs = 0; - - bNumEP++; - - PrintEndpointDescriptor(pep); - - } -#else - if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) - index = epInterruptInIndex; - else - if((pep->bmAttributes & 0x02) == 2) - index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex; - else - return; - - // Fill in the endpoint info structure - epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); - epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; - epInfo[index].epAttribs = 0; - - bNumEP++; - - PrintEndpointDescriptor(pep); -#endif -} - -/** - * For driver use only. - * - * @return - */ -uint8_t BulkOnly::Release() { - ClearAllEP(); - pUsb->GetAddressPool().FreeAddress(bAddress); - return 0; -} - -/** - * For driver use only. - * - * @param lun Logical Unit Number - * @return true if LUN is ready for use. - */ -bool BulkOnly::CheckLUN(uint8_t lun) { - uint8_t rcode; - Capacity capacity; - for(uint8_t i = 0; i < 8; i++) capacity.data[i] = 0; - - rcode = ReadCapacity10(lun, (uint8_t*)capacity.data); - if(rcode) { - //printf(">>>>>>>>>>>>>>>>ReadCapacity returned %i\r\n", rcode); - return false; - } - ErrorMessage (PSTR(">>>>>>>>>>>>>>>>CAPACITY OK ON LUN"), lun); - for(uint8_t i = 0; i < 8 /*sizeof (Capacity)*/; i++) - D_PrintHex (capacity.data[i], 0x80); - Notify(PSTR("\r\n\r\n"), 0x80); - // Only 512/1024/2048/4096 are valid values! - uint32_t c = BMAKE32(capacity.data[4], capacity.data[5], capacity.data[6], capacity.data[7]); - if(c != 0x0200LU && c != 0x0400LU && c != 0x0800LU && c != 0x1000LU) { - return false; - } - // Store capacity information. - CurrentSectorSize[lun] = (uint16_t)(c); // & 0xFFFF); - - CurrentCapacity[lun] = BMAKE32(capacity.data[0], capacity.data[1], capacity.data[2], capacity.data[3]) + 1; - if(CurrentCapacity[lun] == /*0xffffffffLU */ 0x01LU || CurrentCapacity[lun] == 0x00LU) { - // Buggy firmware will report 0xffffffff or 0 for no media - if(CurrentCapacity[lun]) - ErrorMessage (PSTR(">>>>>>>>>>>>>>>>BUGGY FIRMWARE. CAPACITY FAIL ON LUN"), lun); - return false; - } - delay(20); - Page3F(lun); - if(!TestUnitReady(lun)) return true; - return false; -} - -/** - * For driver use only. - * - * Scan for media change on all LUNs - */ -void BulkOnly::CheckMedia() { - for(uint8_t lun = 0; lun <= bMaxLUN; lun++) { - if(TestUnitReady(lun)) { - LUNOk[lun] = false; - continue; - } - if(!LUNOk[lun]) - LUNOk[lun] = CheckLUN(lun); - } -#if 0 - printf("}}}}}}}}}}}}}}}}STATUS "); - for(uint8_t lun = 0; lun <= bMaxLUN; lun++) { - if(LUNOk[lun]) - printf("#"); - else printf("."); - } - printf("\r\n"); -#endif - qNextPollTime = millis() + 2000; -} - -/** - * For driver use only. - * - * @return - */ -uint8_t BulkOnly::Poll() { - //uint8_t rcode = 0; - - if(!bPollEnable) - return 0; - - if((long)(millis() - qNextPollTime) >= 0L) { - CheckMedia(); - } - //rcode = 0; - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// - - -// SCSI code - - -//////////////////////////////////////////////////////////////////////////////// - -/** - * For driver use only. - * - * @param plun - * @return - */ -uint8_t BulkOnly::GetMaxLUN(uint8_t *plun) { - uint8_t ret = pUsb->ctrlReq(bAddress, 0, bmREQ_MASSIN, MASS_REQ_GET_MAX_LUN, 0, 0, bIface, 1, 1, plun, NULL); - - if(ret == hrSTALL) - *plun = 0; - - return 0; -} - -/** - * For driver use only. Used during Driver Init - * - * @param lun Logical Unit Number - * @param bsize - * @param buf - * @return - */ -uint8_t BulkOnly::Inquiry(uint8_t lun, uint16_t bsize, uint8_t *buf) { - Notify(PSTR("\r\nInquiry\r\n"), 0x80); - Notify(PSTR("---------\r\n"), 0x80); - - CDB6_t cdb = CDB6_t(SCSI_CMD_INQUIRY, lun, 0LU, (uint8_t)bsize, 0); - uint8_t rc = SCSITransaction6(&cdb, bsize, buf, (uint8_t)MASS_CMD_DIR_IN); - - return rc; -} - -/** - * For driver use only. - * - * @param lun Logical Unit Number - * @return - */ -uint8_t BulkOnly::TestUnitReady(uint8_t lun) { - //SetCurLUN(lun); - if(!bAddress) - return MASS_ERR_UNIT_NOT_READY; - - Notify(PSTR("\r\nTestUnitReady\r\n"), 0x80); - Notify(PSTR("-----------------\r\n"), 0x80); - - CDB6_t cdb = CDB6_t(SCSI_CMD_TEST_UNIT_READY, lun, (uint8_t)0, 0); - return SCSITransaction6(&cdb, 0, NULL, (uint8_t)MASS_CMD_DIR_IN); - -} - -/** - * For driver use only. - * - * @param lun Logical Unit Number - * @param pc - * @param page - * @param subpage - * @param len - * @param pbuf - * @return - */ -uint8_t BulkOnly::ModeSense6(uint8_t lun, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t len, uint8_t * pbuf) { - Notify(PSTR("\r\rModeSense\r\n"), 0x80); - Notify(PSTR("------------\r\n"), 0x80); - - CDB6_t cdb = CDB6_t(SCSI_CMD_TEST_UNIT_READY, lun, (uint32_t)((((pc << 6) | page) << 8) | subpage), len, 0); - return SCSITransaction6(&cdb, len, pbuf, (uint8_t)MASS_CMD_DIR_IN); -} - -/** - * For driver use only. - * - * @param lun Logical Unit Number - * @param bsize - * @param buf - * @return - */ -uint8_t BulkOnly::ReadCapacity10(uint8_t lun, uint8_t *buf) { - Notify(PSTR("\r\nReadCapacity\r\n"), 0x80); - Notify(PSTR("---------------\r\n"), 0x80); - - CDB10_t cdb = CDB10_t(SCSI_CMD_READ_CAPACITY_10, lun); - return SCSITransaction10(&cdb, 8, buf, (uint8_t)MASS_CMD_DIR_IN); -} - -/** - * For driver use only. - * - * Page 3F contains write protect status. - * - * @param lun Logical Unit Number to test. - * @return Write protect switch status. - */ -uint8_t BulkOnly::Page3F(uint8_t lun) { - uint8_t buf[192]; - for(int i = 0; i < 192; i++) { - buf[i] = 0x00; - } - WriteOk[lun] = true; - uint8_t rc = ModeSense6(lun, 0, 0x3f, 0, 192, buf); - if(!rc) { - WriteOk[lun] = ((buf[2] & 0x80) == 0); - Notify(PSTR("Mode Sense: "), 0x80); - for(int i = 0; i < 4; i++) { - D_PrintHex (buf[i], 0x80); - Notify(PSTR(" "), 0x80); - } - Notify(PSTR("\r\n"), 0x80); - } - return rc; -} - -/** - * For driver use only. - * - * @param lun Logical Unit Number - * @param size - * @param buf - * @return - */ -uint8_t BulkOnly::RequestSense(uint8_t lun, uint16_t size, uint8_t *buf) { - Notify(PSTR("\r\nRequestSense\r\n"), 0x80); - Notify(PSTR("----------------\r\n"), 0x80); - - CDB6_t cdb = CDB6_t(SCSI_CMD_REQUEST_SENSE, lun, 0LU, (uint8_t)size, 0); - CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)size, &cdb, (uint8_t)MASS_CMD_DIR_IN); - //SetCurLUN(lun); - return Transaction(&cbw, size, buf); -} - - -//////////////////////////////////////////////////////////////////////////////// - - -// USB code - - -//////////////////////////////////////////////////////////////////////////////// - -/** - * For driver use only. - * - * @param index - * @return - */ -uint8_t BulkOnly::ClearEpHalt(uint8_t index) { - if(index == 0) - return 0; - - uint8_t ret = 0; - - while((ret = (pUsb->ctrlReq(bAddress, 0, USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT, USB_REQUEST_CLEAR_FEATURE, USB_FEATURE_ENDPOINT_HALT, 0, ((index == epDataInIndex) ? (0x80 | epInfo[index].epAddr) : epInfo[index].epAddr), 0, 0, NULL, NULL)) == 0x01)) - delay(6); - - if(ret) { - ErrorMessage (PSTR("ClearEpHalt"), ret); - ErrorMessage (PSTR("EP"), ((index == epDataInIndex) ? (0x80 | epInfo[index].epAddr) : epInfo[index].epAddr)); - return ret; - } - epInfo[index].bmSndToggle = 0; - epInfo[index].bmRcvToggle = 0; - // epAttribs = 0; - return 0; -} - -/** - * For driver use only. - * - */ -void BulkOnly::Reset() { - while(pUsb->ctrlReq(bAddress, 0, bmREQ_MASSOUT, MASS_REQ_BOMSR, 0, 0, bIface, 0, 0, NULL, NULL) == 0x01) delay(6); -} - -/** - * For driver use only. - * - * @return 0 if successful - */ -uint8_t BulkOnly::ResetRecovery() { - Notify(PSTR("\r\nResetRecovery\r\n"), 0x80); - Notify(PSTR("-----------------\r\n"), 0x80); - - delay(6); - Reset(); - delay(6); - ClearEpHalt(epDataInIndex); - delay(6); - bLastUsbError = ClearEpHalt(epDataOutIndex); - delay(6); - return bLastUsbError; -} - -/** - * For driver use only. - * - * Clear all EP data and clear all LUN status - */ -void BulkOnly::ClearAllEP() { - for(uint8_t i = 0; i < MASS_MAX_ENDPOINTS; i++) { - epInfo[i].epAddr = 0; - epInfo[i].maxPktSize = (i) ? 0 : 8; - epInfo[i].epAttribs = 0; - - epInfo[i].bmNakPower = USB_NAK_DEFAULT; - } - - for(uint8_t i = 0; i < MASS_MAX_SUPPORTED_LUN; i++) { - LUNOk[i] = false; - WriteOk[i] = false; - CurrentCapacity[i] = 0lu; - CurrentSectorSize[i] = 0; - } - - bIface = 0; - bNumEP = 1; - bAddress = 0; - qNextPollTime = 0; - bPollEnable = false; - bLastUsbError = 0; - bMaxLUN = 0; - bTheLUN = 0; -} - -/** - * For driver use only. - * - * @param pcsw - * @param pcbw - * @return - */ -bool BulkOnly::IsValidCSW(CommandStatusWrapper *pcsw, CommandBlockWrapperBase *pcbw) { - if(pcsw->dCSWSignature != MASS_CSW_SIGNATURE) { - Notify(PSTR("CSW:Sig error\r\n"), 0x80); - return false; - } - if(pcsw->dCSWTag != pcbw->dCBWTag) { - Notify(PSTR("CSW:Wrong tag\r\n"), 0x80); - return false; - } - return true; -} - -/** - * For driver use only. - * - * @param error - * @param index - * @return - */ -uint8_t BulkOnly::HandleUsbError(uint8_t error, uint8_t index) { - uint8_t count = 3; - - bLastUsbError = error; - //if (error) - //ClearEpHalt(index); - while(error && count) { - if(error != hrSUCCESS) { - ErrorMessage (PSTR("USB Error"), error); - ErrorMessage (PSTR("Index"), index); - } - switch(error) { - // case hrWRONGPID: - case hrSUCCESS: - return MASS_ERR_SUCCESS; - case hrBUSY: - // SIE is busy, just hang out and try again. - return MASS_ERR_UNIT_BUSY; - case hrTIMEOUT: - case hrJERR: return MASS_ERR_DEVICE_DISCONNECTED; - case hrSTALL: - if(index == 0) - return MASS_ERR_STALL; - ClearEpHalt(index); - if(index != epDataInIndex) - return MASS_ERR_WRITE_STALL; - return MASS_ERR_STALL; - - case hrNAK: - if(index == 0) - return MASS_ERR_UNIT_BUSY; - return MASS_ERR_UNIT_BUSY; - - case hrTOGERR: - // Handle a very super rare corner case, where toggles become de-synched. - // I have only ran into one device that has this firmware bug, and this is - // the only clean way to get back into sync with the buggy device firmware. - // --AJK - if(bAddress && bConfNum) { - error = pUsb->setConf(bAddress, 0, bConfNum); - - if(error) - break; - } - return MASS_ERR_SUCCESS; - default: - ErrorMessage (PSTR("\r\nUSB"), error); - return MASS_ERR_GENERAL_USB_ERROR; - } - count--; - } // while - - return ((error && !count) ? MASS_ERR_GENERAL_USB_ERROR : MASS_ERR_SUCCESS); -} - -#if MS_WANT_PARSER - -uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf) { - return Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf, 0); -} -#endif - -/** - * For driver use only. - * - * @param pcbw - * @param buf_size - * @param buf - * @param flags - * @return - */ -uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf -#if MS_WANT_PARSER - , uint8_t flags -#endif - ) { - -#if MS_WANT_PARSER - uint16_t bytes = (pcbw->dCBWDataTransferLength > buf_size) ? buf_size : pcbw->dCBWDataTransferLength; - printf("Transfersize %i\r\n", bytes); - delay(1000); - - bool callback = (flags & MASS_TRANS_FLG_CALLBACK) == MASS_TRANS_FLG_CALLBACK; -#else - uint16_t bytes = buf_size; -#endif - bool write = (pcbw->bmCBWFlags & MASS_CMD_DIR_IN) != MASS_CMD_DIR_IN; - uint8_t ret = 0; - uint8_t usberr; - CommandStatusWrapper csw; // up here, we allocate ahead to save cpu cycles. - SetCurLUN(pcbw->bmCBWLUN); - ErrorMessage (PSTR("CBW.dCBWTag"), pcbw->dCBWTag); - - while((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw)) == hrBUSY) delay(1); - - ret = HandleUsbError(usberr, epDataOutIndex); - //ret = HandleUsbError(pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw), epDataOutIndex); - if(ret) { - ErrorMessage (PSTR("============================ CBW"), ret); - } else { - if(bytes) { - if(!write) { -#if MS_WANT_PARSER - if(callback) { - uint8_t rbuf[bytes]; - while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, rbuf)) == hrBUSY) delay(1); - if(usberr == hrSUCCESS) ((USBReadParser*)buf)->Parse(bytes, rbuf, 0); - } else { -#endif - while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*)buf)) == hrBUSY) delay(1); -#if MS_WANT_PARSER - - } -#endif - ret = HandleUsbError(usberr, epDataInIndex); - } else { - while((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, bytes, (uint8_t*)buf)) == hrBUSY) delay(1); - ret = HandleUsbError(usberr, epDataOutIndex); - } - if(ret) { - ErrorMessage (PSTR("============================ DAT"), ret); - } - } - } - - { - bytes = sizeof (CommandStatusWrapper); - int tries = 2; - while(tries--) { - while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*) & csw)) == hrBUSY) delay(1); - if(!usberr) break; - ClearEpHalt(epDataInIndex); - if(tries) ResetRecovery(); - } - if(!ret) { - Notify(PSTR("CBW:\t\tOK\r\n"), 0x80); - Notify(PSTR("Data Stage:\tOK\r\n"), 0x80); - } else { - // Throw away csw, IT IS NOT OF ANY USE. - ResetRecovery(); - return ret; - } - ret = HandleUsbError(usberr, epDataInIndex); - if(ret) { - ErrorMessage (PSTR("============================ CSW"), ret); - } - if(usberr == hrSUCCESS) { - if(IsValidCSW(&csw, pcbw)) { - //ErrorMessage (PSTR("CSW.dCBWTag"), csw.dCSWTag); - //ErrorMessage (PSTR("bCSWStatus"), csw.bCSWStatus); - //ErrorMessage (PSTR("dCSWDataResidue"), csw.dCSWDataResidue); - Notify(PSTR("CSW:\t\tOK\r\n\r\n"), 0x80); - return csw.bCSWStatus; - } else { - // NOTE! Sometimes this is caused by the reported residue being wrong. - // Get a different device. It isn't compliant, and should have never passed Q&A. - // I own one... 05e3:0701 Genesys Logic, Inc. USB 2.0 IDE Adapter. - // Other devices that exhibit this behavior exist in the wild too. - // Be sure to check quirks in the Linux source code before reporting a bug. --xxxajk - Notify(PSTR("Invalid CSW\r\n"), 0x80); - ResetRecovery(); - //return MASS_ERR_SUCCESS; - return MASS_ERR_INVALID_CSW; - } - } - } - return ret; -} - -/** - * For driver use only. - * - * @param lun Logical Unit Number - * @return - */ -uint8_t BulkOnly::SetCurLUN(uint8_t lun) { - if(lun > bMaxLUN) - return MASS_ERR_INVALID_LUN; - bTheLUN = lun; - return MASS_ERR_SUCCESS; -}; - -/** - * For driver use only. - * - * @param status - * @return - */ -uint8_t BulkOnly::HandleSCSIError(uint8_t status) { - uint8_t ret = 0; - - switch(status) { - case 0: return MASS_ERR_SUCCESS; - - case 2: - ErrorMessage (PSTR("Phase Error"), status); - ErrorMessage (PSTR("LUN"), bTheLUN); - ResetRecovery(); - return MASS_ERR_GENERAL_SCSI_ERROR; - - case 1: - ErrorMessage (PSTR("SCSI Error"), status); - ErrorMessage (PSTR("LUN"), bTheLUN); - RequestSenseResponce rsp; - - ret = RequestSense(bTheLUN, sizeof (RequestSenseResponce), (uint8_t*) & rsp); - - if(ret) { - return MASS_ERR_GENERAL_SCSI_ERROR; - } - ErrorMessage (PSTR("Response Code"), rsp.bResponseCode); - if(rsp.bResponseCode & 0x80) { - Notify(PSTR("Information field: "), 0x80); - for(int i = 0; i < 4; i++) { - D_PrintHex (rsp.CmdSpecificInformation[i], 0x80); - Notify(PSTR(" "), 0x80); - } - Notify(PSTR("\r\n"), 0x80); - } - ErrorMessage (PSTR("Sense Key"), rsp.bmSenseKey); - ErrorMessage (PSTR("Add Sense Code"), rsp.bAdditionalSenseCode); - ErrorMessage (PSTR("Add Sense Qual"), rsp.bAdditionalSenseQualifier); - // warning, this is not testing ASQ, only SK and ASC. - switch(rsp.bmSenseKey) { - case SCSI_S_UNIT_ATTENTION: - switch(rsp.bAdditionalSenseCode) { - case SCSI_ASC_MEDIA_CHANGED: - return MASS_ERR_MEDIA_CHANGED; - default: - return MASS_ERR_UNIT_NOT_READY; - } - case SCSI_S_NOT_READY: - switch(rsp.bAdditionalSenseCode) { - case SCSI_ASC_MEDIUM_NOT_PRESENT: - return MASS_ERR_NO_MEDIA; - default: - return MASS_ERR_UNIT_NOT_READY; - } - case SCSI_S_ILLEGAL_REQUEST: - switch(rsp.bAdditionalSenseCode) { - case SCSI_ASC_LBA_OUT_OF_RANGE: - return MASS_ERR_BAD_LBA; - default: - return MASS_ERR_CMD_NOT_SUPPORTED; - } - default: - return MASS_ERR_GENERAL_SCSI_ERROR; - } - - // case 4: return MASS_ERR_UNIT_BUSY; // Busy means retry later. - // case 0x05/0x14: we stalled out - // case 0x15/0x16: we naked out. - default: - ErrorMessage (PSTR("Gen SCSI Err"), status); - ErrorMessage (PSTR("LUN"), bTheLUN); - return status; - } // switch -} - - -//////////////////////////////////////////////////////////////////////////////// - - -// Debugging code - - -//////////////////////////////////////////////////////////////////////////////// - -/** - * - * @param ep_ptr - */ -void BulkOnly::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR * ep_ptr) { - Notify(PSTR("Endpoint descriptor:"), 0x80); - Notify(PSTR("\r\nLength:\t\t"), 0x80); - D_PrintHex (ep_ptr->bLength, 0x80); - Notify(PSTR("\r\nType:\t\t"), 0x80); - D_PrintHex (ep_ptr->bDescriptorType, 0x80); - Notify(PSTR("\r\nAddress:\t"), 0x80); - D_PrintHex (ep_ptr->bEndpointAddress, 0x80); - Notify(PSTR("\r\nAttributes:\t"), 0x80); - D_PrintHex (ep_ptr->bmAttributes, 0x80); - Notify(PSTR("\r\nMaxPktSize:\t"), 0x80); - D_PrintHex (ep_ptr->wMaxPacketSize, 0x80); - Notify(PSTR("\r\nPoll Intrv:\t"), 0x80); - D_PrintHex (ep_ptr->bInterval, 0x80); - Notify(PSTR("\r\n"), 0x80); -} - - -//////////////////////////////////////////////////////////////////////////////// - - -// misc/to kill/to-do - - -//////////////////////////////////////////////////////////////////////////////// - -/* We won't be needing this... */ -uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, USBReadParser * prs) { -#if MS_WANT_PARSER - if(!LUNOk[lun]) return MASS_ERR_NO_MEDIA; - Notify(PSTR("\r\nRead (With parser)\r\n"), 0x80); - Notify(PSTR("---------\r\n"), 0x80); - - CommandBlockWrapper cbw = CommandBlockWrapper(); - - cbw.dCBWSignature = MASS_CBW_SIGNATURE; - cbw.dCBWTag = ++dCBWTag; - cbw.dCBWDataTransferLength = ((uint32_t)bsize * blocks); - cbw.bmCBWFlags = MASS_CMD_DIR_IN, - cbw.bmCBWLUN = lun; - cbw.bmCBWCBLength = 10; - - cbw.CBWCB[0] = SCSI_CMD_READ_10; - cbw.CBWCB[8] = blocks; - cbw.CBWCB[2] = ((addr >> 24) & 0xff); - cbw.CBWCB[3] = ((addr >> 16) & 0xff); - cbw.CBWCB[4] = ((addr >> 8) & 0xff); - cbw.CBWCB[5] = (addr & 0xff); - - return HandleSCSIError(Transaction(&cbw, bsize, prs, 1)); -#else - return MASS_ERR_NOT_IMPLEMENTED; -#endif -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/masstorage.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/masstorage.h deleted file mode 100644 index d39fd66f37..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/masstorage.h +++ /dev/null @@ -1,571 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ - -#if !defined(__MASSTORAGE_H__) -#define __MASSTORAGE_H__ - -// Cruft removal, makes driver smaller, faster. -#ifndef MS_WANT_PARSER -#define MS_WANT_PARSER 0 -#endif - -#include "Usb.h" - -#define bmREQ_MASSOUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE -#define bmREQ_MASSIN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE - -// Mass Storage Subclass Constants -#define MASS_SUBCLASS_SCSI_NOT_REPORTED 0x00 // De facto use -#define MASS_SUBCLASS_RBC 0x01 -#define MASS_SUBCLASS_ATAPI 0x02 // MMC-5 (ATAPI) -#define MASS_SUBCLASS_OBSOLETE1 0x03 // Was QIC-157 -#define MASS_SUBCLASS_UFI 0x04 // Specifies how to interface Floppy Disk Drives to USB -#define MASS_SUBCLASS_OBSOLETE2 0x05 // Was SFF-8070i -#define MASS_SUBCLASS_SCSI 0x06 // SCSI Transparent Command Set -#define MASS_SUBCLASS_LSDFS 0x07 // Specifies how host has to negotiate access before trying SCSI -#define MASS_SUBCLASS_IEEE1667 0x08 - -// Mass Storage Class Protocols -#define MASS_PROTO_CBI 0x00 // CBI (with command completion interrupt) -#define MASS_PROTO_CBI_NO_INT 0x01 // CBI (without command completion interrupt) -#define MASS_PROTO_OBSOLETE 0x02 -#define MASS_PROTO_BBB 0x50 // Bulk Only Transport -#define MASS_PROTO_UAS 0x62 - -// Request Codes -#define MASS_REQ_ADSC 0x00 -#define MASS_REQ_GET 0xFC -#define MASS_REQ_PUT 0xFD -#define MASS_REQ_GET_MAX_LUN 0xFE -#define MASS_REQ_BOMSR 0xFF // Bulk-Only Mass Storage Reset - -#define MASS_CBW_SIGNATURE 0x43425355 -#define MASS_CSW_SIGNATURE 0x53425355 - -#define MASS_CMD_DIR_OUT 0 // (0 << 7) -#define MASS_CMD_DIR_IN 0x80 //(1 << 7) - -/* - * Reference documents from T10 (http://www.t10.org) - * SCSI Primary Commands - 3 (SPC-3) - * SCSI Block Commands - 2 (SBC-2) - * Multi-Media Commands - 5 (MMC-5) - */ - -/* Group 1 commands (CDB's here are should all be 6-bytes) */ -#define SCSI_CMD_TEST_UNIT_READY 0x00 -#define SCSI_CMD_REQUEST_SENSE 0x03 -#define SCSI_CMD_FORMAT_UNIT 0x04 -#define SCSI_CMD_READ_6 0x08 -#define SCSI_CMD_WRITE_6 0x0A -#define SCSI_CMD_INQUIRY 0x12 -#define SCSI_CMD_MODE_SELECT_6 0x15 -#define SCSI_CMD_MODE_SENSE_6 0x1A -#define SCSI_CMD_START_STOP_UNIT 0x1B -#define SCSI_CMD_PREVENT_REMOVAL 0x1E -/* Group 2 Commands (CDB's here are 10-bytes) */ -#define SCSI_CMD_READ_FORMAT_CAPACITIES 0x23 -#define SCSI_CMD_READ_CAPACITY_10 0x25 -#define SCSI_CMD_READ_10 0x28 -#define SCSI_CMD_WRITE_10 0x2A -#define SCSI_CMD_SEEK_10 0x2B -#define SCSI_CMD_ERASE_10 0x2C -#define SCSI_CMD_WRITE_AND_VERIFY_10 0x2E -#define SCSI_CMD_VERIFY_10 0x2F -#define SCSI_CMD_SYNCHRONIZE_CACHE 0x35 -#define SCSI_CMD_WRITE_BUFFER 0x3B -#define SCSI_CMD_READ_BUFFER 0x3C -#define SCSI_CMD_READ_SUBCHANNEL 0x42 -#define SCSI_CMD_READ_TOC 0x43 -#define SCSI_CMD_READ_HEADER 0x44 -#define SCSI_CMD_PLAY_AUDIO_10 0x45 -#define SCSI_CMD_GET_CONFIGURATION 0x46 -#define SCSI_CMD_PLAY_AUDIO_MSF 0x47 -#define SCSI_CMD_PLAY_AUDIO_TI 0x48 -#define SCSI_CMD_PLAY_TRACK_REL_10 0x49 -#define SCSI_CMD_GET_EVENT_STATUS 0x4A -#define SCSI_CMD_PAUSE_RESUME 0x4B -#define SCSI_CMD_READ_DISC_INFORMATION 0x51 -#define SCSI_CMD_READ_TRACK_INFORMATION 0x52 -#define SCSI_CMD_RESERVE_TRACK 0x53 -#define SCSI_CMD_SEND_OPC_INFORMATION 0x54 -#define SCSI_CMD_MODE_SELECT_10 0x55 -#define SCSI_CMD_REPAIR_TRACK 0x58 -#define SCSI_CMD_MODE_SENSE_10 0x5A -#define SCSI_CMD_CLOSE_TRACK_SESSION 0x5B -#define SCSI_CMD_READ_BUFFER_CAPACITY 0x5C -#define SCSI_CMD_SEND_CUE_SHEET 0x5D -/* Group 5 Commands (CDB's here are 12-bytes) */ -#define SCSI_CMD_REPORT_LUNS 0xA0 -#define SCSI_CMD_BLANK 0xA1 -#define SCSI_CMD_SECURITY_PROTOCOL_IN 0xA2 -#define SCSI_CMD_SEND_KEY 0xA3 -#define SCSI_CMD_REPORT_KEY 0xA4 -#define SCSI_CMD_PLAY_AUDIO_12 0xA5 -#define SCSI_CMD_LOAD_UNLOAD 0xA6 -#define SCSI_CMD_SET_READ_AHEAD 0xA7 -#define SCSI_CMD_READ_12 0xA8 -#define SCSI_CMD_PLAY_TRACK_REL_12 0xA9 -#define SCSI_CMD_WRITE_12 0xAA -#define SCSI_CMD_READ_MEDIA_SERIAL_12 0xAB -#define SCSI_CMD_GET_PERFORMANCE 0xAC -#define SCSI_CMD_READ_DVD_STRUCTURE 0xAD -#define SCSI_CMD_SECURITY_PROTOCOL_OUT 0xB5 -#define SCSI_CMD_SET_STREAMING 0xB6 -#define SCSI_CMD_READ_MSF 0xB9 -#define SCSI_CMD_SET_SPEED 0xBB -#define SCSI_CMD_MECHANISM_STATUS 0xBD -#define SCSI_CMD_READ_CD 0xBE -#define SCSI_CMD_SEND_DISC_STRUCTURE 0xBF -/* Vendor-unique Commands, included for completeness */ -#define SCSI_CMD_CD_PLAYBACK_STATUS 0xC4 /* SONY unique */ -#define SCSI_CMD_PLAYBACK_CONTROL 0xC9 /* SONY unique */ -#define SCSI_CMD_READ_CDDA 0xD8 /* Vendor unique */ -#define SCSI_CMD_READ_CDXA 0xDB /* Vendor unique */ -#define SCSI_CMD_READ_ALL_SUBCODES 0xDF /* Vendor unique */ - -/* SCSI error codes */ -#define SCSI_S_NOT_READY 0x02 -#define SCSI_S_MEDIUM_ERROR 0x03 -#define SCSI_S_ILLEGAL_REQUEST 0x05 -#define SCSI_S_UNIT_ATTENTION 0x06 -#define SCSI_ASC_LBA_OUT_OF_RANGE 0x21 -#define SCSI_ASC_MEDIA_CHANGED 0x28 -#define SCSI_ASC_MEDIUM_NOT_PRESENT 0x3A - -/* USB error codes */ -#define MASS_ERR_SUCCESS 0x00 -#define MASS_ERR_PHASE_ERROR 0x02 -#define MASS_ERR_UNIT_NOT_READY 0x03 -#define MASS_ERR_UNIT_BUSY 0x04 -#define MASS_ERR_STALL 0x05 -#define MASS_ERR_CMD_NOT_SUPPORTED 0x06 -#define MASS_ERR_INVALID_CSW 0x07 -#define MASS_ERR_NO_MEDIA 0x08 -#define MASS_ERR_BAD_LBA 0x09 -#define MASS_ERR_MEDIA_CHANGED 0x0A -#define MASS_ERR_DEVICE_DISCONNECTED 0x11 -#define MASS_ERR_UNABLE_TO_RECOVER 0x12 // Reset recovery error -#define MASS_ERR_INVALID_LUN 0x13 -#define MASS_ERR_WRITE_STALL 0x14 -#define MASS_ERR_READ_NAKS 0x15 -#define MASS_ERR_WRITE_NAKS 0x16 -#define MASS_ERR_WRITE_PROTECTED 0x17 -#define MASS_ERR_NOT_IMPLEMENTED 0xFD -#define MASS_ERR_GENERAL_SCSI_ERROR 0xFE -#define MASS_ERR_GENERAL_USB_ERROR 0xFF -#define MASS_ERR_USER 0xA0 // For subclasses to define their own error codes - -#define MASS_TRANS_FLG_CALLBACK 0x01 // Callback is involved -#define MASS_TRANS_FLG_NO_STALL_CHECK 0x02 // STALL condition is not checked -#define MASS_TRANS_FLG_NO_PHASE_CHECK 0x04 // PHASE_ERROR is not checked - -#define MASS_MAX_ENDPOINTS 3 - -struct Capacity { - uint8_t data[8]; - //uint32_t dwBlockAddress; - //uint32_t dwBlockLength; -} __attribute__((packed)); - -struct BASICCDB { - uint8_t Opcode; - - unsigned unused : 5; - unsigned LUN : 3; - - uint8_t info[12]; -} __attribute__((packed)); - -typedef BASICCDB BASICCDB_t; - -struct CDB6 { - uint8_t Opcode; - - unsigned LBAMSB : 5; - unsigned LUN : 3; - - uint8_t LBAHB; - uint8_t LBALB; - uint8_t AllocationLength; - uint8_t Control; - -public: - - CDB6(uint8_t _Opcode, uint8_t _LUN, uint32_t LBA, uint8_t _AllocationLength, uint8_t _Control) : - Opcode(_Opcode), LBAMSB(BGRAB2(LBA) & 0x1f), LUN(_LUN), LBAHB(BGRAB1(LBA)), LBALB(BGRAB0(LBA)), - AllocationLength(_AllocationLength), Control(_Control) { - } - - CDB6(uint8_t _Opcode, uint8_t _LUN, uint8_t _AllocationLength, uint8_t _Control) : - Opcode(_Opcode), LBAMSB(0), LUN(_LUN), LBAHB(0), LBALB(0), - AllocationLength(_AllocationLength), Control(_Control) { - } -} __attribute__((packed)); - -typedef CDB6 CDB6_t; - -struct CDB10 { - uint8_t Opcode; - - unsigned Service_Action : 5; - unsigned LUN : 3; - - uint8_t LBA_L_M_MB; - uint8_t LBA_L_M_LB; - uint8_t LBA_L_L_MB; - uint8_t LBA_L_L_LB; - - uint8_t Misc2; - - uint8_t ALC_MB; - uint8_t ALC_LB; - - uint8_t Control; -public: - - CDB10(uint8_t _Opcode, uint8_t _LUN) : - Opcode(_Opcode), Service_Action(0), LUN(_LUN), - LBA_L_M_MB(0), LBA_L_M_LB(0), LBA_L_L_MB(0), LBA_L_L_LB(0), - Misc2(0), ALC_MB(0), ALC_LB(0), Control(0) { - } - - CDB10(uint8_t _Opcode, uint8_t _LUN, uint16_t xflen, uint32_t _LBA) : - Opcode(_Opcode), Service_Action(0), LUN(_LUN), - LBA_L_M_MB(BGRAB3(_LBA)), LBA_L_M_LB(BGRAB2(_LBA)), LBA_L_L_MB(BGRAB1(_LBA)), LBA_L_L_LB(BGRAB0(_LBA)), - Misc2(0), ALC_MB(BGRAB1(xflen)), ALC_LB(BGRAB0(xflen)), Control(0) { - } -} __attribute__((packed)); - -typedef CDB10 CDB10_t; - -struct CDB12 { - uint8_t Opcode; - - unsigned Service_Action : 5; - unsigned Misc : 3; - - uint8_t LBA_L_M_LB; - uint8_t LBA_L_L_MB; - uint8_t LBA_L_L_LB; - - uint8_t ALC_M_LB; - uint8_t ALC_L_MB; - uint8_t ALC_L_LB; - uint8_t Control; -} __attribute__((packed)); - -typedef CDB12 CDB12_t; - -struct CDB_LBA32_16 { - uint8_t Opcode; - - unsigned Service_Action : 5; - unsigned Misc : 3; - - uint8_t LBA_L_M_MB; - uint8_t LBA_L_M_LB; - uint8_t LBA_L_L_MB; - uint8_t LBA_L_L_LB; - - uint8_t A_M_M_MB; - uint8_t A_M_M_LB; - uint8_t A_M_L_MB; - uint8_t A_M_L_LB; - - uint8_t ALC_M_MB; - uint8_t ALC_M_LB; - uint8_t ALC_L_MB; - uint8_t ALC_L_LB; - - uint8_t Misc2; - uint8_t Control; -} __attribute__((packed)); - -struct CDB_LBA64_16 { - uint8_t Opcode; - uint8_t Misc; - - uint8_t LBA_M_M_MB; - uint8_t LBA_M_M_LB; - uint8_t LBA_M_L_MB; - uint8_t LBA_M_L_LB; - - uint8_t LBA_L_M_MB; - uint8_t LBA_L_M_LB; - uint8_t LBA_L_L_MB; - uint8_t LBA_L_L_LB; - - uint8_t ALC_M_MB; - uint8_t ALC_M_LB; - uint8_t ALC_L_MB; - uint8_t ALC_L_LB; - - uint8_t Misc2; - uint8_t Control; -} __attribute__((packed)); - -struct InquiryResponse { - uint8_t DeviceType : 5; - uint8_t PeripheralQualifier : 3; - - unsigned Reserved : 7; - unsigned Removable : 1; - - uint8_t Version; - - unsigned ResponseDataFormat : 4; - unsigned HISUP : 1; - unsigned NormACA : 1; - unsigned TrmTsk : 1; - unsigned AERC : 1; - - uint8_t AdditionalLength; - //uint8_t Reserved3[2]; - - unsigned PROTECT : 1; - unsigned Res : 2; - unsigned ThreePC : 1; - unsigned TPGS : 2; - unsigned ACC : 1; - unsigned SCCS : 1; - - unsigned ADDR16 : 1; - unsigned R1 : 1; - unsigned R2 : 1; - unsigned MCHNGR : 1; - unsigned MULTIP : 1; - unsigned VS : 1; - unsigned ENCSERV : 1; - unsigned BQUE : 1; - - unsigned SoftReset : 1; - unsigned CmdQue : 1; - unsigned Reserved4 : 1; - unsigned Linked : 1; - unsigned Sync : 1; - unsigned WideBus16Bit : 1; - unsigned WideBus32Bit : 1; - unsigned RelAddr : 1; - - uint8_t VendorID[8]; - uint8_t ProductID[16]; - uint8_t RevisionID[4]; -} __attribute__((packed)); - -struct CommandBlockWrapperBase { - uint32_t dCBWSignature; - uint32_t dCBWTag; - uint32_t dCBWDataTransferLength; - uint8_t bmCBWFlags; -public: - - CommandBlockWrapperBase() { - } - - CommandBlockWrapperBase(uint32_t tag, uint32_t xflen, uint8_t flgs) : - dCBWSignature(MASS_CBW_SIGNATURE), dCBWTag(tag), dCBWDataTransferLength(xflen), bmCBWFlags(flgs) { - } -} __attribute__((packed)); - -struct CommandBlockWrapper : public CommandBlockWrapperBase { - - struct { - uint8_t bmCBWLUN : 4; - uint8_t bmReserved1 : 4; - }; - - struct { - uint8_t bmCBWCBLength : 4; - uint8_t bmReserved2 : 4; - }; - - uint8_t CBWCB[16]; - -public: - // All zeroed. - - CommandBlockWrapper() : - CommandBlockWrapperBase(0, 0, 0), bmReserved1(0), bmReserved2(0) { - for(int i = 0; i < 16; i++) CBWCB[i] = 0; - } - - // Generic Wrap, CDB zeroed. - - CommandBlockWrapper(uint32_t tag, uint32_t xflen, uint8_t flgs, uint8_t lu, uint8_t cmdlen, uint8_t cmd) : - CommandBlockWrapperBase(tag, xflen, flgs), - bmCBWLUN(lu), bmReserved1(0), bmCBWCBLength(cmdlen), bmReserved2(0) { - for(int i = 0; i < 16; i++) CBWCB[i] = 0; - // Type punning can cause optimization problems and bugs. - // Using reinterpret_cast to a dreinterpretifferent object is the proper way to do this. - //(((BASICCDB_t *) CBWCB)->LUN) = cmd; - BASICCDB_t *x = reinterpret_cast(CBWCB); - x->LUN = cmd; - } - - // Wrap for CDB of 6 - - CommandBlockWrapper(uint32_t tag, uint32_t xflen, CDB6_t *cdb, uint8_t dir) : - CommandBlockWrapperBase(tag, xflen, dir), - bmCBWLUN(cdb->LUN), bmReserved1(0), bmCBWCBLength(6), bmReserved2(0) { - memcpy(&CBWCB, cdb, 6); - } - // Wrap for CDB of 10 - - CommandBlockWrapper(uint32_t tag, uint32_t xflen, CDB10_t *cdb, uint8_t dir) : - CommandBlockWrapperBase(tag, xflen, dir), - bmCBWLUN(cdb->LUN), bmReserved1(0), bmCBWCBLength(10), bmReserved2(0) { - memcpy(&CBWCB, cdb, 10); - } -} __attribute__((packed)); - -struct CommandStatusWrapper { - uint32_t dCSWSignature; - uint32_t dCSWTag; - uint32_t dCSWDataResidue; - uint8_t bCSWStatus; -} __attribute__((packed)); - -struct RequestSenseResponce { - uint8_t bResponseCode; - uint8_t bSegmentNumber; - - uint8_t bmSenseKey : 4; - uint8_t bmReserved : 1; - uint8_t bmILI : 1; - uint8_t bmEOM : 1; - uint8_t bmFileMark : 1; - - uint8_t Information[4]; - uint8_t bAdditionalLength; - uint8_t CmdSpecificInformation[4]; - uint8_t bAdditionalSenseCode; - uint8_t bAdditionalSenseQualifier; - uint8_t bFieldReplaceableUnitCode; - uint8_t SenseKeySpecific[3]; -} __attribute__((packed)); - -class BulkOnly : public USBDeviceConfig, public UsbConfigXtracter { -protected: - static const uint8_t epDataInIndex; // DataIn endpoint index - static const uint8_t epDataOutIndex; // DataOUT endpoint index - static const uint8_t epInterruptInIndex; // InterruptIN endpoint index - - USB *pUsb; - uint8_t bAddress; - uint8_t bConfNum; // configuration number - uint8_t bIface; // interface value - uint8_t bNumEP; // total number of EP in the configuration - uint32_t qNextPollTime; // next poll time - bool bPollEnable; // poll enable flag - - EpInfo epInfo[MASS_MAX_ENDPOINTS]; - - uint32_t dCBWTag; // Tag - //uint32_t dCBWDataTransferLength; // Data Transfer Length - uint8_t bLastUsbError; // Last USB error - uint8_t bMaxLUN; // Max LUN - uint8_t bTheLUN; // Active LUN - uint32_t CurrentCapacity[MASS_MAX_SUPPORTED_LUN]; // Total sectors - uint16_t CurrentSectorSize[MASS_MAX_SUPPORTED_LUN]; // Sector size, clipped to 16 bits - bool LUNOk[MASS_MAX_SUPPORTED_LUN]; // use this to check for media changes. - bool WriteOk[MASS_MAX_SUPPORTED_LUN]; - void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); - - - // Additional Initialization Method for Subclasses - - virtual uint8_t OnInit() { - return 0; - }; -public: - BulkOnly(USB *p); - - uint8_t GetLastUsbError() { - return bLastUsbError; - }; - - uint8_t GetbMaxLUN() { - return bMaxLUN; // Max LUN - } - - uint8_t GetbTheLUN() { - return bTheLUN; // Active LUN - } - - bool WriteProtected(uint8_t lun); - uint8_t MediaCTL(uint8_t lun, uint8_t ctl); - uint8_t Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf); - uint8_t Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, USBReadParser *prs); - uint8_t Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t *buf); - uint8_t LockMedia(uint8_t lun, uint8_t lock); - - bool LUNIsGood(uint8_t lun); - uint32_t GetCapacity(uint8_t lun); - uint16_t GetSectorSize(uint8_t lun); - - // USBDeviceConfig implementation - uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); - uint8_t ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed); - - uint8_t Release(); - uint8_t Poll(); - - virtual uint8_t GetAddress() { - return bAddress; - }; - - // UsbConfigXtracter implementation - void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); - - virtual bool DEVCLASSOK(uint8_t klass) { - return (klass == USB_CLASS_MASS_STORAGE); - } - - uint8_t SCSITransaction6(CDB6_t *cdb, uint16_t buf_size, void *buf, uint8_t dir); - uint8_t SCSITransaction10(CDB10_t *cdb, uint16_t buf_size, void *buf, uint8_t dir); - -private: - uint8_t Inquiry(uint8_t lun, uint16_t size, uint8_t *buf); - uint8_t TestUnitReady(uint8_t lun); - uint8_t RequestSense(uint8_t lun, uint16_t size, uint8_t *buf); - uint8_t ModeSense6(uint8_t lun, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t len, uint8_t *buf); - uint8_t GetMaxLUN(uint8_t *max_lun); - uint8_t SetCurLUN(uint8_t lun); - void Reset(); - uint8_t ResetRecovery(); - uint8_t ReadCapacity10(uint8_t lun, uint8_t *buf); - void ClearAllEP(); - void CheckMedia(); - bool CheckLUN(uint8_t lun); - uint8_t Page3F(uint8_t lun); - bool IsValidCBW(uint8_t size, uint8_t *pcbw); - bool IsMeaningfulCBW(uint8_t size, uint8_t *pcbw); - - bool IsValidCSW(CommandStatusWrapper *pcsw, CommandBlockWrapperBase *pcbw); - - uint8_t ClearEpHalt(uint8_t index); -#if MS_WANT_PARSER - uint8_t Transaction(CommandBlockWrapper *cbw, uint16_t bsize, void *buf, uint8_t flags); -#endif - uint8_t Transaction(CommandBlockWrapper *cbw, uint16_t bsize, void *buf); - uint8_t HandleUsbError(uint8_t error, uint8_t index); - uint8_t HandleSCSIError(uint8_t status); - -}; - -#endif // __MASSTORAGE_H__ diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/max3421e.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/max3421e.h deleted file mode 100644 index 4e45a35e8d..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/max3421e.h +++ /dev/null @@ -1,228 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ -#if !defined(_usb_h_) || defined(_max3421e_h_) -#error "Never include max3421e.h directly; include Usb.h instead" -#else - -#define _max3421e_h_ - -/* MAX3421E register/bit names and bitmasks */ - -/* Arduino pin definitions */ -/* pin numbers to port numbers */ - -#define SE0 0 -#define SE1 1 -#define FSHOST 2 -#define LSHOST 3 - -/* MAX3421E command byte format: rrrrr0wa where 'r' is register number */ -// -// MAX3421E Registers in HOST mode. -// -#define rRCVFIFO 0x08 //1<<3 -#define rSNDFIFO 0x10 //2<<3 -#define rSUDFIFO 0x20 //4<<3 -#define rRCVBC 0x30 //6<<3 -#define rSNDBC 0x38 //7<<3 - -#define rUSBIRQ 0x68 //13<<3 -/* USBIRQ Bits */ -#define bmVBUSIRQ 0x40 //b6 -#define bmNOVBUSIRQ 0x20 //b5 -#define bmOSCOKIRQ 0x01 //b0 - -#define rUSBIEN 0x70 //14<<3 -/* USBIEN Bits */ -#define bmVBUSIE 0x40 //b6 -#define bmNOVBUSIE 0x20 //b5 -#define bmOSCOKIE 0x01 //b0 - -#define rUSBCTL 0x78 //15<<3 -/* USBCTL Bits */ -#define bmCHIPRES 0x20 //b5 -#define bmPWRDOWN 0x10 //b4 - -#define rCPUCTL 0x80 //16<<3 -/* CPUCTL Bits */ -#define bmPUSLEWID1 0x80 //b7 -#define bmPULSEWID0 0x40 //b6 -#define bmIE 0x01 //b0 - -#define rPINCTL 0x88 //17<<3 -/* PINCTL Bits */ -#define bmFDUPSPI 0x10 //b4 -#define bmINTLEVEL 0x08 //b3 -#define bmPOSINT 0x04 //b2 -#define bmGPXB 0x02 //b1 -#define bmGPXA 0x01 //b0 -// GPX pin selections -#define GPX_OPERATE 0x00 -#define GPX_VBDET 0x01 -#define GPX_BUSACT 0x02 -#define GPX_SOF 0x03 - -#define rREVISION 0x90 //18<<3 - -#define rIOPINS1 0xa0 //20<<3 - -/* IOPINS1 Bits */ -#define bmGPOUT0 0x01 -#define bmGPOUT1 0x02 -#define bmGPOUT2 0x04 -#define bmGPOUT3 0x08 -#define bmGPIN0 0x10 -#define bmGPIN1 0x20 -#define bmGPIN2 0x40 -#define bmGPIN3 0x80 - -#define rIOPINS2 0xa8 //21<<3 -/* IOPINS2 Bits */ -#define bmGPOUT4 0x01 -#define bmGPOUT5 0x02 -#define bmGPOUT6 0x04 -#define bmGPOUT7 0x08 -#define bmGPIN4 0x10 -#define bmGPIN5 0x20 -#define bmGPIN6 0x40 -#define bmGPIN7 0x80 - -#define rGPINIRQ 0xb0 //22<<3 -/* GPINIRQ Bits */ -#define bmGPINIRQ0 0x01 -#define bmGPINIRQ1 0x02 -#define bmGPINIRQ2 0x04 -#define bmGPINIRQ3 0x08 -#define bmGPINIRQ4 0x10 -#define bmGPINIRQ5 0x20 -#define bmGPINIRQ6 0x40 -#define bmGPINIRQ7 0x80 - -#define rGPINIEN 0xb8 //23<<3 -/* GPINIEN Bits */ -#define bmGPINIEN0 0x01 -#define bmGPINIEN1 0x02 -#define bmGPINIEN2 0x04 -#define bmGPINIEN3 0x08 -#define bmGPINIEN4 0x10 -#define bmGPINIEN5 0x20 -#define bmGPINIEN6 0x40 -#define bmGPINIEN7 0x80 - -#define rGPINPOL 0xc0 //24<<3 -/* GPINPOL Bits */ -#define bmGPINPOL0 0x01 -#define bmGPINPOL1 0x02 -#define bmGPINPOL2 0x04 -#define bmGPINPOL3 0x08 -#define bmGPINPOL4 0x10 -#define bmGPINPOL5 0x20 -#define bmGPINPOL6 0x40 -#define bmGPINPOL7 0x80 - -#define rHIRQ 0xc8 //25<<3 -/* HIRQ Bits */ -#define bmBUSEVENTIRQ 0x01 // indicates BUS Reset Done or BUS Resume -#define bmRWUIRQ 0x02 -#define bmRCVDAVIRQ 0x04 -#define bmSNDBAVIRQ 0x08 -#define bmSUSDNIRQ 0x10 -#define bmCONDETIRQ 0x20 -#define bmFRAMEIRQ 0x40 -#define bmHXFRDNIRQ 0x80 - -#define rHIEN 0xd0 //26<<3 - -/* HIEN Bits */ -#define bmBUSEVENTIE 0x01 -#define bmRWUIE 0x02 -#define bmRCVDAVIE 0x04 -#define bmSNDBAVIE 0x08 -#define bmSUSDNIE 0x10 -#define bmCONDETIE 0x20 -#define bmFRAMEIE 0x40 -#define bmHXFRDNIE 0x80 - -#define rMODE 0xd8 //27<<3 - -/* MODE Bits */ -#define bmHOST 0x01 -#define bmLOWSPEED 0x02 -#define bmHUBPRE 0x04 -#define bmSOFKAENAB 0x08 -#define bmSEPIRQ 0x10 -#define bmDELAYISO 0x20 -#define bmDMPULLDN 0x40 -#define bmDPPULLDN 0x80 - -#define rPERADDR 0xe0 //28<<3 - -#define rHCTL 0xe8 //29<<3 -/* HCTL Bits */ -#define bmBUSRST 0x01 -#define bmFRMRST 0x02 -#define bmSAMPLEBUS 0x04 -#define bmSIGRSM 0x08 -#define bmRCVTOG0 0x10 -#define bmRCVTOG1 0x20 -#define bmSNDTOG0 0x40 -#define bmSNDTOG1 0x80 - -#define rHXFR 0xf0 //30<<3 -/* Host transfer token values for writing the HXFR register (R30) */ -/* OR this bit field with the endpoint number in bits 3:0 */ -#define tokSETUP 0x10 // HS=0, ISO=0, OUTNIN=0, SETUP=1 -#define tokIN 0x00 // HS=0, ISO=0, OUTNIN=0, SETUP=0 -#define tokOUT 0x20 // HS=0, ISO=0, OUTNIN=1, SETUP=0 -#define tokINHS 0x80 // HS=1, ISO=0, OUTNIN=0, SETUP=0 -#define tokOUTHS 0xA0 // HS=1, ISO=0, OUTNIN=1, SETUP=0 -#define tokISOIN 0x40 // HS=0, ISO=1, OUTNIN=0, SETUP=0 -#define tokISOOUT 0x60 // HS=0, ISO=1, OUTNIN=1, SETUP=0 - -#define rHRSL 0xf8 //31<<3 - -/* HRSL Bits */ -#define bmRCVTOGRD 0x10 -#define bmSNDTOGRD 0x20 -#define bmKSTATUS 0x40 -#define bmJSTATUS 0x80 -#define bmSE0 0x00 //SE0 - disconnect state -#define bmSE1 0xc0 //SE1 - illegal state - -/* Host error result codes, the 4 LSB's in the HRSL register */ -#define hrSUCCESS 0x00 -#define hrBUSY 0x01 -#define hrBADREQ 0x02 -#define hrUNDEF 0x03 -#define hrNAK 0x04 -#define hrSTALL 0x05 -#define hrTOGERR 0x06 -#define hrWRONGPID 0x07 -#define hrBADBC 0x08 -#define hrPIDERR 0x09 -#define hrPKTERR 0x0A -#define hrCRCERR 0x0B -#define hrKERR 0x0C -#define hrJERR 0x0D -#define hrTIMEOUT 0x0E -#define hrBABBLE 0x0F - -#define MODE_FS_HOST (bmDPPULLDN|bmDMPULLDN|bmHOST|bmSOFKAENAB) -#define MODE_LS_HOST (bmDPPULLDN|bmDMPULLDN|bmHOST|bmLOWSPEED|bmSOFKAENAB) - - -#endif //_max3421e_h_ diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/max_LCD.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/max_LCD.cpp deleted file mode 100644 index f0c64666fa..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/max_LCD.cpp +++ /dev/null @@ -1,255 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ -#include "max_LCD.h" -#include - -// pin definition and set/clear - -#define RS 0x04 // RS pin -#define E 0x08 // E pin - -#define SET_RS lcdPins |= RS -#define CLR_RS lcdPins &= ~RS -#define SET_E lcdPins |= E -#define CLR_E lcdPins &= ~E - -#define SENDlcdPins() pUsb->gpioWr( lcdPins ) - -#define LCD_sendcmd(a) { CLR_RS; \ - sendbyte(a); \ - } - -#define LCD_sendchar(a) { SET_RS; \ - sendbyte(a); \ - } - -static byte lcdPins; //copy of LCD pins - -Max_LCD::Max_LCD(USB *pusb) : pUsb(pusb) { - lcdPins = 0; -} - -void Max_LCD::init() { - _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS; - - // MAX3421E::gpioWr(0x55); - - begin(16, 1); -} - -void Max_LCD::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) { - if(lines > 1) { - _displayfunction |= LCD_2LINE; - } - _numlines = lines; - _currline = 0; - - // for some 1 line displays you can select a 10 pixel high font - if((dotsize != 0) && (lines == 1)) { - _displayfunction |= LCD_5x10DOTS; - } - - // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION! - // according to datasheet, we need at least 40ms after power rises above 2.7V - // before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50 - delayMicroseconds(50000); - lcdPins = 0x30; - SET_E; - SENDlcdPins(); - CLR_E; - SENDlcdPins(); - delayMicroseconds(10000); // wait min 4.1ms - //second try - SET_E; - SENDlcdPins(); - CLR_E; - SENDlcdPins(); - delayMicroseconds(10000); // wait min 4.1ms - // third go! - SET_E; - SENDlcdPins(); - CLR_E; - SENDlcdPins(); - delayMicroseconds(10000); - // finally, set to 4-bit interface - lcdPins = 0x20; - //SET_RS; - SET_E; - SENDlcdPins(); - //CLR_RS; - CLR_E; - SENDlcdPins(); - delayMicroseconds(10000); - // finally, set # lines, font size, etc. - command(LCD_FUNCTIONSET | _displayfunction); - - // turn the display on with no cursor or blinking default - _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; - display(); - - // clear it off - clear(); - - // Initialize to default text direction (for romance languages) - _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; - // set the entry mode - command(LCD_ENTRYMODESET | _displaymode); -} - -/********** high level commands, for the user! */ -void Max_LCD::clear() { - command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero - delayMicroseconds(2000); // this command takes a long time! -} - -void Max_LCD::home() { - command(LCD_RETURNHOME); // set cursor position to zero - delayMicroseconds(2000); // this command takes a long time! -} - -void Max_LCD::setCursor(uint8_t col, uint8_t row) { - int row_offsets[] = {0x00, 0x40, 0x14, 0x54}; - if(row > _numlines) { - row = _numlines - 1; // we count rows starting w/0 - } - - command(LCD_SETDDRAMADDR | (col + row_offsets[row])); -} - -// Turn the display on/off (quickly) - -void Max_LCD::noDisplay() { - _displaycontrol &= ~LCD_DISPLAYON; - command(LCD_DISPLAYCONTROL | _displaycontrol); -} - -void Max_LCD::display() { - _displaycontrol |= LCD_DISPLAYON; - command(LCD_DISPLAYCONTROL | _displaycontrol); -} - -// Turns the underline cursor on/off - -void Max_LCD::noCursor() { - _displaycontrol &= ~LCD_CURSORON; - command(LCD_DISPLAYCONTROL | _displaycontrol); -} - -void Max_LCD::cursor() { - _displaycontrol |= LCD_CURSORON; - command(LCD_DISPLAYCONTROL | _displaycontrol); -} - - -// Turn on and off the blinking cursor - -void Max_LCD::noBlink() { - _displaycontrol &= ~LCD_BLINKON; - command(LCD_DISPLAYCONTROL | _displaycontrol); -} - -void Max_LCD::blink() { - _displaycontrol |= LCD_BLINKON; - command(LCD_DISPLAYCONTROL | _displaycontrol); -} - -// These commands scroll the display without changing the RAM - -void Max_LCD::scrollDisplayLeft(void) { - command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT); -} - -void Max_LCD::scrollDisplayRight(void) { - command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT); -} - -// This is for text that flows Left to Right - -void Max_LCD::leftToRight(void) { - _displaymode |= LCD_ENTRYLEFT; - command(LCD_ENTRYMODESET | _displaymode); -} - -// This is for text that flows Right to Left - -void Max_LCD::rightToLeft(void) { - _displaymode &= ~LCD_ENTRYLEFT; - command(LCD_ENTRYMODESET | _displaymode); -} - -// This will 'right justify' text from the cursor - -void Max_LCD::autoscroll(void) { - _displaymode |= LCD_ENTRYSHIFTINCREMENT; - command(LCD_ENTRYMODESET | _displaymode); -} - -// This will 'left justify' text from the cursor - -void Max_LCD::noAutoscroll(void) { - _displaymode &= ~LCD_ENTRYSHIFTINCREMENT; - command(LCD_ENTRYMODESET | _displaymode); -} - -// Allows us to fill the first 8 CGRAM locations -// with custom characters - -void Max_LCD::createChar(uint8_t location, uint8_t charmap[]) { - location &= 0x7; // we only have 8 locations 0-7 - command(LCD_SETCGRAMADDR | (location << 3)); - for(int i = 0; i < 8; i++) { - write(charmap[i]); - } -} - -/*********** mid level commands, for sending data/cmds */ - -inline void Max_LCD::command(uint8_t value) { - LCD_sendcmd(value); - delayMicroseconds(100); -} - -#if defined(ARDUINO) && ARDUINO >=100 - -inline size_t Max_LCD::write(uint8_t value) { - LCD_sendchar(value); - return 1; // Assume success -} -#else - -inline void Max_LCD::write(uint8_t value) { - LCD_sendchar(value); -} -#endif - -void Max_LCD::sendbyte(uint8_t val) { - lcdPins &= 0x0f; //prepare place for the upper nibble - lcdPins |= (val & 0xf0); //copy upper nibble to LCD variable - SET_E; //send - SENDlcdPins(); - delayMicroseconds(2); - CLR_E; - delayMicroseconds(2); - SENDlcdPins(); - lcdPins &= 0x0f; //prepare place for the lower nibble - lcdPins |= (val << 4) & 0xf0; //copy lower nibble to LCD variable - SET_E; //send - SENDlcdPins(); - CLR_E; - SENDlcdPins(); - delayMicroseconds(100); -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/max_LCD.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/max_LCD.h deleted file mode 100644 index 950c9c5aa3..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/max_LCD.h +++ /dev/null @@ -1,106 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ -//HD44780 compatible LCD display via MAX3421E GPOUT support header -//pinout: D[4-7] -> GPOUT[4-7], RS-> GPOUT[2], E ->GPOUT[3] -// - -#ifndef _Max_LCD_h_ -#define _Max_LCD_h_ - -#include "Usb.h" -#include "Print.h" - -// commands -#define LCD_CLEARDISPLAY 0x01 -#define LCD_RETURNHOME 0x02 -#define LCD_ENTRYMODESET 0x04 -#define LCD_DISPLAYCONTROL 0x08 -#define LCD_CURSORSHIFT 0x10 -#define LCD_FUNCTIONSET 0x20 -#define LCD_SETCGRAMADDR 0x40 -#define LCD_SETDDRAMADDR 0x80 - -// flags for display entry mode -#define LCD_ENTRYRIGHT 0x00 -#define LCD_ENTRYLEFT 0x02 -#define LCD_ENTRYSHIFTINCREMENT 0x01 -#define LCD_ENTRYSHIFTDECREMENT 0x00 - -// flags for display on/off control -#define LCD_DISPLAYON 0x04 -#define LCD_DISPLAYOFF 0x00 -#define LCD_CURSORON 0x02 -#define LCD_CURSOROFF 0x00 -#define LCD_BLINKON 0x01 -#define LCD_BLINKOFF 0x00 - -// flags for display/cursor shift -#define LCD_DISPLAYMOVE 0x08 -#define LCD_CURSORMOVE 0x00 -#define LCD_MOVERIGHT 0x04 -#define LCD_MOVELEFT 0x00 - -// flags for function set -#define LCD_8BITMODE 0x10 -#define LCD_4BITMODE 0x00 -#define LCD_2LINE 0x08 -#define LCD_1LINE 0x00 -#define LCD_5x10DOTS 0x04 -#define LCD_5x8DOTS 0x00 - -class Max_LCD : public Print { - USB *pUsb; - -public: - Max_LCD(USB *pusb); - void init(); - void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS); - void clear(); - void home(); - void noDisplay(); - void display(); - void noBlink(); - void blink(); - void noCursor(); - void cursor(); - void scrollDisplayLeft(); - void scrollDisplayRight(); - void leftToRight(); - void rightToLeft(); - void autoscroll(); - void noAutoscroll(); - void createChar(uint8_t, uint8_t[]); - void setCursor(uint8_t, uint8_t); - void command(uint8_t); - -#if defined(ARDUINO) && ARDUINO >=100 - size_t write(uint8_t); - using Print::write; -#else - void write(uint8_t); -#endif - -private: - void sendbyte(uint8_t val); - uint8_t _displayfunction; //tokill - uint8_t _displaycontrol; - uint8_t _displaymode; - uint8_t _initialized; - uint8_t _numlines, _currline; -}; - -#endif diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/message.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/message.cpp deleted file mode 100644 index bdcdd18331..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/message.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ - -#include "Usb.h" -// 0x80 is the default (i.e. trace) to turn off set this global to something lower. -// this allows for 126 other debugging levels. -// TO-DO: Allow assignment to a different serial port by software -int UsbDEBUGlvl = 0x80; - -void E_Notifyc(char c, int lvl) { - if(UsbDEBUGlvl < lvl) return; -#if defined(ARDUINO) && ARDUINO >=100 - USB_HOST_SERIAL.print(c); -#else - USB_HOST_SERIAL.print(c, BYTE); -#endif - //USB_HOST_SERIAL.flush(); -} - -void E_Notify(char const * msg, int lvl) { - if(UsbDEBUGlvl < lvl) return; - if(!msg) return; - char c; - - while((c = pgm_read_byte(msg++))) E_Notifyc(c, lvl); -} - -void E_NotifyStr(char const * msg, int lvl) { - if(UsbDEBUGlvl < lvl) return; - if(!msg) return; - char c; - - while((c = *msg++)) E_Notifyc(c, lvl); -} - -void E_Notify(uint8_t b, int lvl) { - if(UsbDEBUGlvl < lvl) return; -#if defined(ARDUINO) && ARDUINO >=100 - USB_HOST_SERIAL.print(b); -#else - USB_HOST_SERIAL.print(b, DEC); -#endif - //USB_HOST_SERIAL.flush(); -} - -void E_Notify(double d, int lvl) { - if(UsbDEBUGlvl < lvl) return; - USB_HOST_SERIAL.print(d); - //USB_HOST_SERIAL.flush(); -} - -#ifdef DEBUG_USB_HOST - -void NotifyFailGetDevDescr(void) { - Notify(PSTR("\r\ngetDevDescr "), 0x80); -} - -void NotifyFailSetDevTblEntry(void) { - Notify(PSTR("\r\nsetDevTblEn "), 0x80); -} - -void NotifyFailGetConfDescr(void) { - Notify(PSTR("\r\ngetConf "), 0x80); -} - -void NotifyFailSetConfDescr(void) { - Notify(PSTR("\r\nsetConf "), 0x80); -} - -void NotifyFailGetDevDescr(uint8_t reason) { - NotifyFailGetDevDescr(); - NotifyFail(reason); -} - -void NotifyFailSetDevTblEntry(uint8_t reason) { - NotifyFailSetDevTblEntry(); - NotifyFail(reason); - -} - -void NotifyFailGetConfDescr(uint8_t reason) { - NotifyFailGetConfDescr(); - NotifyFail(reason); -} - -void NotifyFailSetConfDescr(uint8_t reason) { - NotifyFailSetConfDescr(); - NotifyFail(reason); -} - -void NotifyFailUnknownDevice(uint16_t VID, uint16_t PID) { - Notify(PSTR("\r\nUnknown Device Connected - VID: "), 0x80); - D_PrintHex (VID, 0x80); - Notify(PSTR(" PID: "), 0x80); - D_PrintHex (PID, 0x80); -} - -void NotifyFail(uint8_t rcode) { - D_PrintHex (rcode, 0x80); - Notify(PSTR("\r\n"), 0x80); -} -#endif diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/message.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/message.h deleted file mode 100644 index c26628e7f2..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/message.h +++ /dev/null @@ -1,78 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ -#if !defined(_usb_h_) || defined(__MESSAGE_H__) -#error "Never include message.h directly; include Usb.h instead" -#else -#define __MESSAGE_H__ - -extern int UsbDEBUGlvl; - -void E_Notify(char const * msg, int lvl); -void E_Notify(uint8_t b, int lvl); -void E_NotifyStr(char const * msg, int lvl); -void E_Notifyc(char c, int lvl); - -#ifdef DEBUG_USB_HOST -#define Notify E_Notify -#define NotifyStr E_NotifyStr -#define Notifyc E_Notifyc -void NotifyFailGetDevDescr(uint8_t reason); -void NotifyFailSetDevTblEntry(uint8_t reason); -void NotifyFailGetConfDescr(uint8_t reason); -void NotifyFailSetConfDescr(uint8_t reason); -void NotifyFailGetDevDescr(void); -void NotifyFailSetDevTblEntry(void); -void NotifyFailGetConfDescr(void); -void NotifyFailSetConfDescr(void); -void NotifyFailUnknownDevice(uint16_t VID, uint16_t PID); -void NotifyFail(uint8_t rcode); -#else -#define Notify(...) ((void)0) -#define NotifyStr(...) ((void)0) -#define Notifyc(...) ((void)0) -#define NotifyFailGetDevDescr(...) ((void)0) -#define NotifyFailSetDevTblEntry(...) ((void)0) -#define NotifyFailGetConfDescr(...) ((void)0) -#define NotifyFailGetDevDescr(...) ((void)0) -#define NotifyFailSetDevTblEntry(...) ((void)0) -#define NotifyFailGetConfDescr(...) ((void)0) -#define NotifyFailSetConfDescr(...) ((void)0) -#define NotifyFailUnknownDevice(...) ((void)0) -#define NotifyFail(...) ((void)0) -#endif - -template -void ErrorMessage(uint8_t level, char const * msg, ERROR_TYPE rcode = 0) { -#ifdef DEBUG_USB_HOST - Notify(msg, level); - Notify(PSTR(": "), level); - D_PrintHex (rcode, level); - Notify(PSTR("\r\n"), level); -#endif -} - -template -void ErrorMessage(char const * msg, ERROR_TYPE rcode = 0) { -#ifdef DEBUG_USB_HOST - Notify(msg, 0x80); - Notify(PSTR(": "), 0x80); - D_PrintHex (rcode, 0x80); - Notify(PSTR("\r\n"), 0x80); -#endif -} - -#endif // __MESSAGE_H__ diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/parsetools.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/parsetools.cpp deleted file mode 100644 index 74a8610597..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/parsetools.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ -#include "Usb.h" - -bool MultiByteValueParser::Parse(uint8_t **pp, uint16_t *pcntdn) { - if(!pBuf) { - Notify(PSTR("Buffer pointer is NULL!\r\n"), 0x80); - return false; - } - for(; countDown && (*pcntdn); countDown--, (*pcntdn)--, (*pp)++) - pBuf[valueSize - countDown] = (**pp); - - if(countDown) - return false; - - countDown = valueSize; - return true; -} - -bool PTPListParser::Parse(uint8_t **pp, uint16_t *pcntdn, PTP_ARRAY_EL_FUNC pf, const void *me) { - switch(nStage) { - case 0: - pBuf->valueSize = lenSize; - theParser.Initialize(pBuf); - nStage = 1; - - case 1: - if(!theParser.Parse(pp, pcntdn)) - return false; - - arLen = 0; - arLen = (pBuf->valueSize >= 4) ? *((uint32_t*)pBuf->pValue) : (uint32_t)(*((uint16_t*)pBuf->pValue)); - arLenCntdn = arLen; - nStage = 2; - - case 2: - pBuf->valueSize = valSize; - theParser.Initialize(pBuf); - nStage = 3; - - case 3: - for(; arLenCntdn; arLenCntdn--) { - if(!theParser.Parse(pp, pcntdn)) - return false; - - if(pf) - pf(pBuf, (arLen - arLenCntdn), me); - } - - nStage = 0; - } - return true; -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/parsetools.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/parsetools.h deleted file mode 100644 index 66e9531c39..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/parsetools.h +++ /dev/null @@ -1,140 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ - -#if !defined(_usb_h_) || defined(__PARSETOOLS_H__) -#error "Never include parsetools.h directly; include Usb.h instead" -#else -#define __PARSETOOLS_H__ - -struct MultiValueBuffer { - uint8_t valueSize; - void *pValue; -} __attribute__((packed)); - -class MultiByteValueParser { - uint8_t * pBuf; - uint8_t countDown; - uint8_t valueSize; - -public: - - MultiByteValueParser() : pBuf(NULL), countDown(0), valueSize(0) { - }; - - const uint8_t* GetBuffer() { - return pBuf; - }; - - void Initialize(MultiValueBuffer * const pbuf) { - pBuf = (uint8_t*)pbuf->pValue; - countDown = valueSize = pbuf->valueSize; - }; - - bool Parse(uint8_t **pp, uint16_t *pcntdn); -}; - -class ByteSkipper { - uint8_t *pBuf; - uint8_t nStage; - uint16_t countDown; - -public: - - ByteSkipper() : pBuf(NULL), nStage(0), countDown(0) { - }; - - void Initialize(MultiValueBuffer *pbuf) { - pBuf = (uint8_t*)pbuf->pValue; - countDown = 0; - }; - - bool Skip(uint8_t **pp, uint16_t *pcntdn, uint16_t bytes_to_skip) { - switch(nStage) { - case 0: - countDown = bytes_to_skip; - nStage++; - case 1: - for(; countDown && (*pcntdn); countDown--, (*pp)++, (*pcntdn)--); - - if(!countDown) - nStage = 0; - }; - return (!countDown); - }; -}; - -// Pointer to a callback function triggered for each element of PTP array when used with PTPArrayParser -typedef void (*PTP_ARRAY_EL_FUNC)(const MultiValueBuffer * const p, uint32_t count, const void *me); - -class PTPListParser { -public: - - enum ParseMode { - modeArray, modeRange/*, modeEnum*/ - }; - -private: - uint8_t nStage; - uint8_t enStage; - - uint32_t arLen; - uint32_t arLenCntdn; - - uint8_t lenSize; // size of the array length field in bytes - uint8_t valSize; // size of the array element in bytes - - MultiValueBuffer *pBuf; - - // The only parser for both size and array element parsing - MultiByteValueParser theParser; - - uint8_t /*ParseMode*/ prsMode; - -public: - - PTPListParser() : - nStage(0), - enStage(0), - arLen(0), - arLenCntdn(0), - lenSize(0), - valSize(0), - pBuf(NULL), - prsMode(modeArray) { - }; - - void Initialize(const uint8_t len_size, const uint8_t val_size, MultiValueBuffer * const p, const uint8_t mode = modeArray) { - pBuf = p; - lenSize = len_size; - valSize = val_size; - prsMode = mode; - - if(prsMode == modeRange) { - arLenCntdn = arLen = 3; - nStage = 2; - } else { - arLenCntdn = arLen = 0; - nStage = 0; - } - enStage = 0; - theParser.Initialize(p); - }; - - bool Parse(uint8_t **pp, uint16_t *pcntdn, PTP_ARRAY_EL_FUNC pf, const void *me = NULL); -}; - -#endif // __PARSETOOLS_H__ diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/printhex.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/printhex.h deleted file mode 100644 index 369d7e1f7e..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/printhex.h +++ /dev/null @@ -1,84 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ - -#if !defined(_usb_h_) || defined(__PRINTHEX_H__) -#error "Never include printhex.h directly; include Usb.h instead" -#else -#define __PRINTHEX_H__ - -void E_Notifyc(char c, int lvl); - -template -void PrintHex(T val, int lvl) { - int num_nibbles = sizeof (T) * 2; - - do { - char v = 48 + (((val >> (num_nibbles - 1) * 4)) & 0x0f); - if(v > 57) v += 7; - E_Notifyc(v, lvl); - } while(--num_nibbles); -} - -template -void PrintBin(T val, int lvl) { - for(T mask = (((T)1) << ((sizeof (T) << 3) - 1)); mask; mask >>= 1) - if(val & mask) - E_Notifyc('1', lvl); - else - E_Notifyc('0', lvl); -} - -template -void SerialPrintHex(T val) { - int num_nibbles = sizeof (T) * 2; - - do { - char v = 48 + (((val >> (num_nibbles - 1) * 4)) & 0x0f); - if(v > 57) v += 7; - USB_HOST_SERIAL.print(v); - } while(--num_nibbles); -} - -template -void PrintHex2(Print *prn, T val) { - T mask = (((T)1) << (((sizeof (T) << 1) - 1) << 2)); - - while(mask > 1) { - if(val < mask) - prn->print("0"); - - mask >>= 4; - } - prn->print((T)val, HEX); -} - -template void D_PrintHex(T val, int lvl) { -#ifdef DEBUG_USB_HOST - PrintHex (val, lvl); -#endif -} - -template -void D_PrintBin(T val, int lvl) { -#ifdef DEBUG_USB_HOST - PrintBin (val, lvl); -#endif -} - - - -#endif // __PRINTHEX_H__ diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/settings.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/settings.h deleted file mode 100644 index 5c060354ba..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/settings.h +++ /dev/null @@ -1,139 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ - -#ifndef USB_HOST_SHIELD_SETTINGS_H -#define USB_HOST_SHIELD_SETTINGS_H -#include "macros.h" - -//////////////////////////////////////////////////////////////////////////////// -// DEBUGGING -//////////////////////////////////////////////////////////////////////////////// - -/* Set this to 1 to activate serial debugging */ -#define ENABLE_UHS_DEBUGGING 0 - -/* This can be used to select which serial port to use for debugging if - * multiple serial ports are available. - * For example Serial3. - */ -#ifndef USB_HOST_SERIAL -#define USB_HOST_SERIAL Serial -#endif - -//////////////////////////////////////////////////////////////////////////////// -// Manual board activation -//////////////////////////////////////////////////////////////////////////////// - -/* Set this to 1 if you are using an Arduino Mega ADK board with MAX3421e built-in */ -#define USE_UHS_MEGA_ADK 0 // If you are using Arduino 1.5.5 or newer there is no need to do this manually - -/* Set this to 1 if you are using a Black Widdow */ -#define USE_UHS_BLACK_WIDDOW 0 - -/* Set this to a one to use the xmem2 lock. This is needed for multitasking and threading */ -#define USE_XMEM_SPI_LOCK 0 - -//////////////////////////////////////////////////////////////////////////////// -// Wii IR camera -//////////////////////////////////////////////////////////////////////////////// - -/* Set this to 1 to activate code for the Wii IR camera */ -#define ENABLE_WII_IR_CAMERA 0 - -//////////////////////////////////////////////////////////////////////////////// -// MASS STORAGE -//////////////////////////////////////////////////////////////////////////////// -// <<<<<<<<<<<<<<<< IMPORTANT >>>>>>>>>>>>>>> -// Set this to 1 to support single LUN devices, and save RAM. -- I.E. thumb drives. -// Each LUN needs ~13 bytes to be able to track the state of each unit. -#ifndef MASS_MAX_SUPPORTED_LUN -#define MASS_MAX_SUPPORTED_LUN 8 -#endif - -//////////////////////////////////////////////////////////////////////////////// -// Set to 1 to use the faster spi4teensy3 driver. -//////////////////////////////////////////////////////////////////////////////// -#ifndef USE_SPI4TEENSY3 -#define USE_SPI4TEENSY3 1 -#endif - -//////////////////////////////////////////////////////////////////////////////// -// AUTOMATIC Settings -//////////////////////////////////////////////////////////////////////////////// - -// No user serviceable parts below this line. -// DO NOT change anything below here unless you are a developer! - -#include "version_helper.h" - -#if defined(__GNUC__) && defined(__AVR__) -#ifndef GCC_VERSION -#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) -#endif -#if GCC_VERSION < 40602 // Test for GCC < 4.6.2 -#ifdef PROGMEM -#undef PROGMEM -#define PROGMEM __attribute__((section(".progmem.data"))) // Workaround for http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34734#c4 -#ifdef PSTR -#undef PSTR -#define PSTR(s) (__extension__({static const char __c[] PROGMEM = (s); &__c[0];})) // Copied from pgmspace.h in avr-libc source -#endif -#endif -#endif -#endif - -#if !defined(DEBUG_USB_HOST) && ENABLE_UHS_DEBUGGING -#define DEBUG_USB_HOST -#endif - -#if !defined(WIICAMERA) && ENABLE_WII_IR_CAMERA -#define WIICAMERA -#endif - -// To use some other locking (e.g. freertos), -// define XMEM_ACQUIRE_SPI and XMEM_RELEASE_SPI to point to your lock and unlock. -// NOTE: NO argument is passed. You have to do this within your routine for -// whatever you are using to lock and unlock. -#if !defined(XMEM_ACQUIRE_SPI) -#if USE_XMEM_SPI_LOCK || defined(USE_MULTIPLE_APP_API) -#include -#else -#define XMEM_ACQUIRE_SPI() (void(0)) -#define XMEM_RELEASE_SPI() (void(0)) -#endif -#endif - -#if !defined(EXT_RAM) && defined(EXT_RAM_STACK) || defined(EXT_RAM_HEAP) -#include -#else -#define EXT_RAM 0 -#endif - -#if defined(CORE_TEENSY) && (defined(__MK20DX128__) || defined(__MK20DX256__)) -#define USING_SPI4TEENSY3 USE_SPI4TEENSY3 -#else -#define USING_SPI4TEENSY3 0 -#endif - -#if ((defined(ARDUINO_SAM_DUE) && defined(__SAM3X8E__)) || defined(RBL_NRF51822) || defined(__ARDUINO_X86__) || ARDUINO >= 10600) && !USING_SPI4TEENSY3 -#include // Use the Arduino SPI library for the Arduino Due, RedBearLab nRF51822, Intel Galileo 1 & 2, Intel Edison or if the SPI library with transaction is available -#endif -#if defined(__PIC32MX__) || defined(__PIC32MZ__) -#include <../../../../hardware/pic32/libraries/SPI/SPI.h> // Hack to use the SPI library -#endif - -#endif /* SETTINGS_H */ diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/sink_parser.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/sink_parser.h deleted file mode 100644 index a23637d2b7..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/sink_parser.h +++ /dev/null @@ -1,41 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ -#if !defined(_usb_h_) || defined(__SINK_PARSER_H__) -#error "Never include hexdump.h directly; include Usb.h instead" -#else -#define __SINK_PARSER_H__ - -extern int UsbDEBUGlvl; - -// This parser does absolutely nothing with the data, just swallows it. - -template -class SinkParser : public BASE_CLASS { -public: - - SinkParser() { - }; - - void Initialize() { - }; - - void Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset) { - }; -}; - - -#endif // __HEXDUMP_H__ diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/usb_ch9.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/usb_ch9.h deleted file mode 100644 index 18f2d3e2e5..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/usb_ch9.h +++ /dev/null @@ -1,166 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ - -#if !defined(_usb_h_) || defined(_ch9_h_) -#error "Never include usb_ch9.h directly; include Usb.h instead" -#else - -/* USB chapter 9 structures */ -#define _ch9_h_ - -/* Misc.USB constants */ -#define DEV_DESCR_LEN 18 //device descriptor length -#define CONF_DESCR_LEN 9 //configuration descriptor length -#define INTR_DESCR_LEN 9 //interface descriptor length -#define EP_DESCR_LEN 7 //endpoint descriptor length - -/* Standard Device Requests */ - -#define USB_REQUEST_GET_STATUS 0 // Standard Device Request - GET STATUS -#define USB_REQUEST_CLEAR_FEATURE 1 // Standard Device Request - CLEAR FEATURE -#define USB_REQUEST_SET_FEATURE 3 // Standard Device Request - SET FEATURE -#define USB_REQUEST_SET_ADDRESS 5 // Standard Device Request - SET ADDRESS -#define USB_REQUEST_GET_DESCRIPTOR 6 // Standard Device Request - GET DESCRIPTOR -#define USB_REQUEST_SET_DESCRIPTOR 7 // Standard Device Request - SET DESCRIPTOR -#define USB_REQUEST_GET_CONFIGURATION 8 // Standard Device Request - GET CONFIGURATION -#define USB_REQUEST_SET_CONFIGURATION 9 // Standard Device Request - SET CONFIGURATION -#define USB_REQUEST_GET_INTERFACE 10 // Standard Device Request - GET INTERFACE -#define USB_REQUEST_SET_INTERFACE 11 // Standard Device Request - SET INTERFACE -#define USB_REQUEST_SYNCH_FRAME 12 // Standard Device Request - SYNCH FRAME - -#define USB_FEATURE_ENDPOINT_HALT 0 // CLEAR/SET FEATURE - Endpoint Halt -#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 // CLEAR/SET FEATURE - Device remote wake-up -#define USB_FEATURE_TEST_MODE 2 // CLEAR/SET FEATURE - Test mode - -/* Setup Data Constants */ - -#define USB_SETUP_HOST_TO_DEVICE 0x00 // Device Request bmRequestType transfer direction - host to device transfer -#define USB_SETUP_DEVICE_TO_HOST 0x80 // Device Request bmRequestType transfer direction - device to host transfer -#define USB_SETUP_TYPE_STANDARD 0x00 // Device Request bmRequestType type - standard -#define USB_SETUP_TYPE_CLASS 0x20 // Device Request bmRequestType type - class -#define USB_SETUP_TYPE_VENDOR 0x40 // Device Request bmRequestType type - vendor -#define USB_SETUP_RECIPIENT_DEVICE 0x00 // Device Request bmRequestType recipient - device -#define USB_SETUP_RECIPIENT_INTERFACE 0x01 // Device Request bmRequestType recipient - interface -#define USB_SETUP_RECIPIENT_ENDPOINT 0x02 // Device Request bmRequestType recipient - endpoint -#define USB_SETUP_RECIPIENT_OTHER 0x03 // Device Request bmRequestType recipient - other - -/* USB descriptors */ - -#define USB_DESCRIPTOR_DEVICE 0x01 // bDescriptorType for a Device Descriptor. -#define USB_DESCRIPTOR_CONFIGURATION 0x02 // bDescriptorType for a Configuration Descriptor. -#define USB_DESCRIPTOR_STRING 0x03 // bDescriptorType for a String Descriptor. -#define USB_DESCRIPTOR_INTERFACE 0x04 // bDescriptorType for an Interface Descriptor. -#define USB_DESCRIPTOR_ENDPOINT 0x05 // bDescriptorType for an Endpoint Descriptor. -#define USB_DESCRIPTOR_DEVICE_QUALIFIER 0x06 // bDescriptorType for a Device Qualifier. -#define USB_DESCRIPTOR_OTHER_SPEED 0x07 // bDescriptorType for a Other Speed Configuration. -#define USB_DESCRIPTOR_INTERFACE_POWER 0x08 // bDescriptorType for Interface Power. -#define USB_DESCRIPTOR_OTG 0x09 // bDescriptorType for an OTG Descriptor. - -#define HID_DESCRIPTOR_HID 0x21 - - - -/* OTG SET FEATURE Constants */ -#define OTG_FEATURE_B_HNP_ENABLE 3 // SET FEATURE OTG - Enable B device to perform HNP -#define OTG_FEATURE_A_HNP_SUPPORT 4 // SET FEATURE OTG - A device supports HNP -#define OTG_FEATURE_A_ALT_HNP_SUPPORT 5 // SET FEATURE OTG - Another port on the A device supports HNP - -/* USB Endpoint Transfer Types */ -#define USB_TRANSFER_TYPE_CONTROL 0x00 // Endpoint is a control endpoint. -#define USB_TRANSFER_TYPE_ISOCHRONOUS 0x01 // Endpoint is an isochronous endpoint. -#define USB_TRANSFER_TYPE_BULK 0x02 // Endpoint is a bulk endpoint. -#define USB_TRANSFER_TYPE_INTERRUPT 0x03 // Endpoint is an interrupt endpoint. -#define bmUSB_TRANSFER_TYPE 0x03 // bit mask to separate transfer type from ISO attributes - - -/* Standard Feature Selectors for CLEAR_FEATURE Requests */ -#define USB_FEATURE_ENDPOINT_STALL 0 // Endpoint recipient -#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 // Device recipient -#define USB_FEATURE_TEST_MODE 2 // Device recipient - -/* descriptor data structures */ - -/* Device descriptor structure */ -typedef struct { - uint8_t bLength; // Length of this descriptor. - uint8_t bDescriptorType; // DEVICE descriptor type (USB_DESCRIPTOR_DEVICE). - uint16_t bcdUSB; // USB Spec Release Number (BCD). - uint8_t bDeviceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific. - uint8_t bDeviceSubClass; // Subclass code (assigned by the USB-IF). - uint8_t bDeviceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific. - uint8_t bMaxPacketSize0; // Maximum packet size for endpoint 0. - uint16_t idVendor; // Vendor ID (assigned by the USB-IF). - uint16_t idProduct; // Product ID (assigned by the manufacturer). - uint16_t bcdDevice; // Device release number (BCD). - uint8_t iManufacturer; // Index of String Descriptor describing the manufacturer. - uint8_t iProduct; // Index of String Descriptor describing the product. - uint8_t iSerialNumber; // Index of String Descriptor with the device's serial number. - uint8_t bNumConfigurations; // Number of possible configurations. -} __attribute__((packed)) USB_DEVICE_DESCRIPTOR; - -/* Configuration descriptor structure */ -typedef struct { - uint8_t bLength; // Length of this descriptor. - uint8_t bDescriptorType; // CONFIGURATION descriptor type (USB_DESCRIPTOR_CONFIGURATION). - uint16_t wTotalLength; // Total length of all descriptors for this configuration. - uint8_t bNumInterfaces; // Number of interfaces in this configuration. - uint8_t bConfigurationValue; // Value of this configuration (1 based). - uint8_t iConfiguration; // Index of String Descriptor describing the configuration. - uint8_t bmAttributes; // Configuration characteristics. - uint8_t bMaxPower; // Maximum power consumed by this configuration. -} __attribute__((packed)) USB_CONFIGURATION_DESCRIPTOR; - -/* Interface descriptor structure */ -typedef struct { - uint8_t bLength; // Length of this descriptor. - uint8_t bDescriptorType; // INTERFACE descriptor type (USB_DESCRIPTOR_INTERFACE). - uint8_t bInterfaceNumber; // Number of this interface (0 based). - uint8_t bAlternateSetting; // Value of this alternate interface setting. - uint8_t bNumEndpoints; // Number of endpoints in this interface. - uint8_t bInterfaceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific. - uint8_t bInterfaceSubClass; // Subclass code (assigned by the USB-IF). - uint8_t bInterfaceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific. - uint8_t iInterface; // Index of String Descriptor describing the interface. -} __attribute__((packed)) USB_INTERFACE_DESCRIPTOR; - -/* Endpoint descriptor structure */ -typedef struct { - uint8_t bLength; // Length of this descriptor. - uint8_t bDescriptorType; // ENDPOINT descriptor type (USB_DESCRIPTOR_ENDPOINT). - uint8_t bEndpointAddress; // Endpoint address. Bit 7 indicates direction (0=OUT, 1=IN). - uint8_t bmAttributes; // Endpoint transfer type. - uint16_t wMaxPacketSize; // Maximum packet size. - uint8_t bInterval; // Polling interval in frames. -} __attribute__((packed)) USB_ENDPOINT_DESCRIPTOR; - -/* HID descriptor */ -typedef struct { - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t bcdHID; // HID class specification release - uint8_t bCountryCode; - uint8_t bNumDescriptors; // Number of additional class specific descriptors - uint8_t bDescrType; // Type of class descriptor - uint16_t wDescriptorLength; // Total size of the Report descriptor -} __attribute__((packed)) USB_HID_DESCRIPTOR; - -typedef struct { - uint8_t bDescrType; // Type of class descriptor - uint16_t wDescriptorLength; // Total size of the Report descriptor -} __attribute__((packed)) HID_CLASS_DESCRIPTOR_LEN_AND_TYPE; - -#endif // _ch9_h_ diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/usbhost.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/usbhost.h deleted file mode 100644 index eba480e60c..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/usbhost.h +++ /dev/null @@ -1,529 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ -/* MAX3421E-based USB Host Library header file */ - - -#if !defined(_usb_h_) || defined(_USBHOST_H_) -#error "Never include usbhost.h directly; include Usb.h instead" -#else -#define _USBHOST_H_ - -#if USING_SPI4TEENSY3 -#include -#include -#endif - -/* SPI initialization */ -template< typename SPI_CLK, typename SPI_MOSI, typename SPI_MISO, typename SPI_SS > class SPi { -public: -#if USING_SPI4TEENSY3 - static void init() { - // spi4teensy3 inits everything for us, except /SS - // CLK, MOSI and MISO are hard coded for now. - // spi4teensy3::init(0,0,0); // full speed, cpol 0, cpha 0 - spi4teensy3::init(); // full speed, cpol 0, cpha 0 - SPI_SS::SetDirWrite(); - SPI_SS::Set(); - } -#elif SPI_HAS_TRANSACTION - static void init() { - SPI.begin(); // The SPI library with transaction will take care of setting up the pins - settings is set in beginTransaction() - } -#elif !defined(SPDR) - static void init() { - SPI_SS::SetDirWrite(); - SPI_SS::Set(); - SPI.begin(); -#if defined(__MIPSEL__) - SPI.setClockDivider(1); -#elif defined(__ARDUINO_X86__) - #ifdef SPI_CLOCK_1M // Hack used to check if setClockSpeed is available - SPI.setClockSpeed(12000000); // The MAX3421E can handle up to 26MHz, but in practice this was the maximum that I could reliably use - #else - SPI.setClockDivider(SPI_CLOCK_DIV2); // This will set the SPI frequency to 8MHz - it could be higher, but it is not supported in the old API - #endif -#else - SPI.setClockDivider(4); // Set speed to 84MHz/4=21MHz - the MAX3421E can handle up to 26MHz -#endif - } -#elif defined(RBL_NRF51822) - static void init() { - SPI_SS::SetDirWrite(); - SPI_SS::Set(); - SPI.begin(); - // SPI.setFrequency(SPI_FREQUENCY_8M); - } -#else - static void init() { - //uint8_t tmp; - SPI_CLK::SetDirWrite(); - SPI_MOSI::SetDirWrite(); - SPI_MISO::SetDirRead(); - SPI_SS::SetDirWrite(); - /* mode 00 (CPOL=0, CPHA=0) master, fclk/2. Mode 11 (CPOL=11, CPHA=11) is also supported by MAX3421E */ - SPCR = 0x50; - SPSR = 0x01; // 0x01 - /**/ - //tmp = SPSR; - //tmp = SPDR; - } -#endif -}; - -/* SPI pin definitions. see avrpins.h */ -#if defined(__AVR_ATmega1280__) || (__AVR_ATmega2560__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) -typedef SPi< Pb1, Pb2, Pb3, Pb0 > spi; -#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) -typedef SPi< Pb5, Pb3, Pb4, Pb2 > spi; -#elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) -typedef SPi< Pb7, Pb5, Pb6, Pb4 > spi; -#elif (defined(CORE_TEENSY) && (defined(__MK20DX128__) || defined(__MK20DX256__))) || defined(__ARDUINO_X86__) || defined(__MIPSEL__) -typedef SPi< P13, P11, P12, P10 > spi; -#elif defined(ARDUINO_SAM_DUE) && defined(__SAM3X8E__) -typedef SPi< P76, P75, P74, P10 > spi; -#elif defined(RBL_NRF51822) -typedef SPi< P16, P18, P17, P10 > spi; -#else -#error "No SPI entry in usbhost.h" -#endif - -typedef enum { - vbus_on = 0, - vbus_off = GPX_VBDET -} VBUS_t; - -template< typename SPI_SS, typename INTR > class MAX3421e /* : public spi */ { - static uint8_t vbusState; - -public: - MAX3421e(); - void regWr(uint8_t reg, uint8_t data); - uint8_t* bytesWr(uint8_t reg, uint8_t nbytes, uint8_t* data_p); - void gpioWr(uint8_t data); - uint8_t regRd(uint8_t reg); - uint8_t* bytesRd(uint8_t reg, uint8_t nbytes, uint8_t* data_p); - uint8_t gpioRd(); - uint16_t reset(); - int8_t Init(); - int8_t Init(int mseconds); - - void vbusPower(VBUS_t state) { - regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL | state)); - } - - uint8_t getVbusState(void) { - return vbusState; - }; - void busprobe(); - uint8_t GpxHandler(); - uint8_t IntHandler(); - uint8_t Task(); -}; - -template< typename SPI_SS, typename INTR > - uint8_t MAX3421e< SPI_SS, INTR >::vbusState = 0; - -/* constructor */ -template< typename SPI_SS, typename INTR > -MAX3421e< SPI_SS, INTR >::MAX3421e() { - // Leaving ADK hardware setup in here, for now. This really belongs with the other parts. -#ifdef BOARD_MEGA_ADK - // For Mega ADK, which has a Max3421e on-board, set MAX_RESET to output mode, and then set it to HIGH - P55::SetDirWrite(); - P55::Set(); -#endif -}; - -/* write single byte into MAX3421 register */ -template< typename SPI_SS, typename INTR > -void MAX3421e< SPI_SS, INTR >::regWr(uint8_t reg, uint8_t data) { - XMEM_ACQUIRE_SPI(); -#if SPI_HAS_TRANSACTION - SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0 -#endif - SPI_SS::Clear(); - -#if USING_SPI4TEENSY3 - uint8_t c[2]; - c[0] = reg | 0x02; - c[1] = data; - spi4teensy3::send(c, 2); -#elif SPI_HAS_TRANSACTION - uint8_t c[2]; - c[0] = reg | 0x02; - c[1] = data; - SPI.transfer(c, 2); -#elif !defined(SPDR) - SPI.transfer(reg | 0x02); - SPI.transfer(data); -#else - SPDR = (reg | 0x02); - while(!(SPSR & (1 << SPIF))); - SPDR = data; - while(!(SPSR & (1 << SPIF))); -#endif - - SPI_SS::Set(); -#if SPI_HAS_TRANSACTION - SPI.endTransaction(); -#endif - XMEM_RELEASE_SPI(); - return; -}; -/* multiple-byte write */ - -/* returns a pointer to memory position after last written */ -template< typename SPI_SS, typename INTR > -uint8_t* MAX3421e< SPI_SS, INTR >::bytesWr(uint8_t reg, uint8_t nbytes, uint8_t* data_p) { - XMEM_ACQUIRE_SPI(); -#if SPI_HAS_TRANSACTION - SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0 -#endif - SPI_SS::Clear(); - -#if USING_SPI4TEENSY3 - spi4teensy3::send(reg | 0x02); - spi4teensy3::send(data_p, nbytes); - data_p += nbytes; -#elif SPI_HAS_TRANSACTION - SPI.transfer(reg | 0x02); - SPI.transfer(data_p, nbytes); - data_p += nbytes; -#elif defined(__ARDUINO_X86__) - SPI.transfer(reg | 0x02); - SPI.transferBuffer(data_p, NULL, nbytes); - data_p += nbytes; -#elif !defined(SPDR) - SPI.transfer(reg | 0x02); - while(nbytes) { - SPI.transfer(*data_p); - nbytes--; - data_p++; // advance data pointer - } -#else - SPDR = (reg | 0x02); //set WR bit and send register number - while(nbytes) { - while(!(SPSR & (1 << SPIF))); //check if previous byte was sent - SPDR = (*data_p); // send next data byte - nbytes--; - data_p++; // advance data pointer - } - while(!(SPSR & (1 << SPIF))); -#endif - - SPI_SS::Set(); -#if SPI_HAS_TRANSACTION - SPI.endTransaction(); -#endif - XMEM_RELEASE_SPI(); - return ( data_p); -} -/* GPIO write */ -/*GPIO byte is split between 2 registers, so two writes are needed to write one byte */ - -/* GPOUT bits are in the low nibble. 0-3 in IOPINS1, 4-7 in IOPINS2 */ -template< typename SPI_SS, typename INTR > -void MAX3421e< SPI_SS, INTR >::gpioWr(uint8_t data) { - regWr(rIOPINS1, data); - data >>= 4; - regWr(rIOPINS2, data); - return; -} - -/* single host register read */ -template< typename SPI_SS, typename INTR > -uint8_t MAX3421e< SPI_SS, INTR >::regRd(uint8_t reg) { - XMEM_ACQUIRE_SPI(); -#if SPI_HAS_TRANSACTION - SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0 -#endif - SPI_SS::Clear(); - -#if USING_SPI4TEENSY3 - spi4teensy3::send(reg); - uint8_t rv = spi4teensy3::receive(); - SPI_SS::Set(); -#elif !defined(SPDR) || SPI_HAS_TRANSACTION - SPI.transfer(reg); - uint8_t rv = SPI.transfer(0); // Send empty byte - SPI_SS::Set(); -#else - SPDR = reg; - while(!(SPSR & (1 << SPIF))); - SPDR = 0; // Send empty byte - while(!(SPSR & (1 << SPIF))); - SPI_SS::Set(); - uint8_t rv = SPDR; -#endif - -#if SPI_HAS_TRANSACTION - SPI.endTransaction(); -#endif - XMEM_RELEASE_SPI(); - return (rv); -} -/* multiple-byte register read */ - -/* returns a pointer to a memory position after last read */ -template< typename SPI_SS, typename INTR > -uint8_t* MAX3421e< SPI_SS, INTR >::bytesRd(uint8_t reg, uint8_t nbytes, uint8_t* data_p) { - XMEM_ACQUIRE_SPI(); -#if SPI_HAS_TRANSACTION - SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0 -#endif - SPI_SS::Clear(); - -#if USING_SPI4TEENSY3 - spi4teensy3::send(reg); - spi4teensy3::receive(data_p, nbytes); - data_p += nbytes; -#elif SPI_HAS_TRANSACTION - SPI.transfer(reg); - memset(data_p, 0, nbytes); // Make sure we send out empty bytes - SPI.transfer(data_p, nbytes); - data_p += nbytes; -#elif defined(__ARDUINO_X86__) - SPI.transfer(reg); - SPI.transferBuffer(NULL, data_p, nbytes); - data_p += nbytes; -#elif !defined(SPDR) - SPI.transfer(reg); - while(nbytes) { - *data_p++ = SPI.transfer(0); - nbytes--; - } -#else - SPDR = reg; - while(!(SPSR & (1 << SPIF))); //wait - while(nbytes) { - SPDR = 0; // Send empty byte - nbytes--; - while(!(SPSR & (1 << SPIF))); -#if 0 - { - *data_p = SPDR; - printf("%2.2x ", *data_p); - } - data_p++; - } - printf("\r\n"); -#else - *data_p++ = SPDR; - } -#endif -#endif - - SPI_SS::Set(); -#if SPI_HAS_TRANSACTION - SPI.endTransaction(); -#endif - XMEM_RELEASE_SPI(); - return ( data_p); -} -/* GPIO read. See gpioWr for explanation */ - -/* GPIN pins are in high nibbles of IOPINS1, IOPINS2 */ -template< typename SPI_SS, typename INTR > -uint8_t MAX3421e< SPI_SS, INTR >::gpioRd() { - uint8_t gpin = 0; - gpin = regRd(rIOPINS2); //pins 4-7 - gpin &= 0xf0; //clean lower nibble - gpin |= (regRd(rIOPINS1) >> 4); //shift low bits and OR with upper from previous operation. - return ( gpin); -} - -/* reset MAX3421E. Returns number of cycles it took for PLL to stabilize after reset - or zero if PLL haven't stabilized in 65535 cycles */ -template< typename SPI_SS, typename INTR > -uint16_t MAX3421e< SPI_SS, INTR >::reset() { - uint16_t i = 0; - regWr(rUSBCTL, bmCHIPRES); - regWr(rUSBCTL, 0x00); - while(++i) { - if((regRd(rUSBIRQ) & bmOSCOKIRQ)) { - break; - } - } - return ( i); -} - -/* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */ -template< typename SPI_SS, typename INTR > -int8_t MAX3421e< SPI_SS, INTR >::Init() { - XMEM_ACQUIRE_SPI(); - // Moved here. - // you really should not init hardware in the constructor when it involves locks. - // Also avoids the vbus flicker issue confusing some devices. - /* pin and peripheral setup */ - SPI_SS::SetDirWrite(); - SPI_SS::Set(); - spi::init(); - INTR::SetDirRead(); - XMEM_RELEASE_SPI(); - /* MAX3421E - full-duplex SPI, level interrupt */ - // GPX pin on. Moved here, otherwise we flicker the vbus. - regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL)); - - if(reset() == 0) { //OSCOKIRQ hasn't asserted in time - return ( -1); - } - - regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST); // set pull-downs, Host - - regWr(rHIEN, bmCONDETIE | bmFRAMEIE); //connection detection - - /* check if device is connected */ - regWr(rHCTL, bmSAMPLEBUS); // sample USB bus - while(!(regRd(rHCTL) & bmSAMPLEBUS)); //wait for sample operation to finish - - busprobe(); //check if anything is connected - - regWr(rHIRQ, bmCONDETIRQ); //clear connection detect interrupt - regWr(rCPUCTL, 0x01); //enable interrupt pin - - return ( 0); -} - -/* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */ -template< typename SPI_SS, typename INTR > -int8_t MAX3421e< SPI_SS, INTR >::Init(int mseconds) { - XMEM_ACQUIRE_SPI(); - // Moved here. - // you really should not init hardware in the constructor when it involves locks. - // Also avoids the vbus flicker issue confusing some devices. - /* pin and peripheral setup */ - SPI_SS::SetDirWrite(); - SPI_SS::Set(); - spi::init(); - INTR::SetDirRead(); - XMEM_RELEASE_SPI(); - /* MAX3421E - full-duplex SPI, level interrupt, vbus off */ - regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL | GPX_VBDET)); - - if(reset() == 0) { //OSCOKIRQ hasn't asserted in time - return ( -1); - } - - // Delay a minimum of 1 second to ensure any capacitors are drained. - // 1 second is required to make sure we do not smoke a Microdrive! - if(mseconds < 1000) mseconds = 1000; - delay(mseconds); - - regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST); // set pull-downs, Host - - regWr(rHIEN, bmCONDETIE | bmFRAMEIE); //connection detection - - /* check if device is connected */ - regWr(rHCTL, bmSAMPLEBUS); // sample USB bus - while(!(regRd(rHCTL) & bmSAMPLEBUS)); //wait for sample operation to finish - - busprobe(); //check if anything is connected - - regWr(rHIRQ, bmCONDETIRQ); //clear connection detect interrupt - regWr(rCPUCTL, 0x01); //enable interrupt pin - - // GPX pin on. This is done here so that busprobe will fail if we have a switch connected. - regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL)); - - return ( 0); -} - -/* probe bus to determine device presence and speed and switch host to this speed */ -template< typename SPI_SS, typename INTR > -void MAX3421e< SPI_SS, INTR >::busprobe() { - uint8_t bus_sample; - bus_sample = regRd(rHRSL); //Get J,K status - bus_sample &= (bmJSTATUS | bmKSTATUS); //zero the rest of the byte - switch(bus_sample) { //start full-speed or low-speed host - case( bmJSTATUS): - if((regRd(rMODE) & bmLOWSPEED) == 0) { - regWr(rMODE, MODE_FS_HOST); //start full-speed host - vbusState = FSHOST; - } else { - regWr(rMODE, MODE_LS_HOST); //start low-speed host - vbusState = LSHOST; - } - break; - case( bmKSTATUS): - if((regRd(rMODE) & bmLOWSPEED) == 0) { - regWr(rMODE, MODE_LS_HOST); //start low-speed host - vbusState = LSHOST; - } else { - regWr(rMODE, MODE_FS_HOST); //start full-speed host - vbusState = FSHOST; - } - break; - case( bmSE1): //illegal state - vbusState = SE1; - break; - case( bmSE0): //disconnected state - regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST | bmSEPIRQ); - vbusState = SE0; - break; - }//end switch( bus_sample ) -} - -/* MAX3421 state change task and interrupt handler */ -template< typename SPI_SS, typename INTR > -uint8_t MAX3421e< SPI_SS, INTR >::Task(void) { - uint8_t rcode = 0; - uint8_t pinvalue; - //USB_HOST_SERIAL.print("Vbus state: "); - //USB_HOST_SERIAL.println( vbusState, HEX ); - pinvalue = INTR::IsSet(); //Read(); - //pinvalue = digitalRead( MAX_INT ); - if(pinvalue == 0) { - rcode = IntHandler(); - } - // pinvalue = digitalRead( MAX_GPX ); - // if( pinvalue == LOW ) { - // GpxHandler(); - // } - // usbSM(); //USB state machine - return ( rcode); -} - -template< typename SPI_SS, typename INTR > -uint8_t MAX3421e< SPI_SS, INTR >::IntHandler() { - uint8_t HIRQ; - uint8_t HIRQ_sendback = 0x00; - HIRQ = regRd(rHIRQ); //determine interrupt source - //if( HIRQ & bmFRAMEIRQ ) { //->1ms SOF interrupt handler - // HIRQ_sendback |= bmFRAMEIRQ; - //}//end FRAMEIRQ handling - if(HIRQ & bmCONDETIRQ) { - busprobe(); - HIRQ_sendback |= bmCONDETIRQ; - } - /* End HIRQ interrupts handling, clear serviced IRQs */ - regWr(rHIRQ, HIRQ_sendback); - return ( HIRQ_sendback); -} -//template< typename SPI_SS, typename INTR > -//uint8_t MAX3421e< SPI_SS, INTR >::GpxHandler() -//{ -// uint8_t GPINIRQ = regRd( rGPINIRQ ); //read GPIN IRQ register -//// if( GPINIRQ & bmGPINIRQ7 ) { //vbus overload -//// vbusPwr( OFF ); //attempt powercycle -//// delay( 1000 ); -//// vbusPwr( ON ); -//// regWr( rGPINIRQ, bmGPINIRQ7 ); -//// } -// return( GPINIRQ ); -//} - -#endif // _USBHOST_H_ diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/usbhub.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/usbhub.cpp deleted file mode 100644 index 7fed48e781..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/usbhub.cpp +++ /dev/null @@ -1,425 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ -#include "usbhub.h" - -bool USBHub::bResetInitiated = false; - -USBHub::USBHub(USB *p) : -pUsb(p), -bAddress(0), -bNbrPorts(0), -//bInitState(0), -qNextPollTime(0), -bPollEnable(false) { - epInfo[0].epAddr = 0; - epInfo[0].maxPktSize = 8; - epInfo[0].epAttribs = 0; - epInfo[0].bmNakPower = USB_NAK_MAX_POWER; - - epInfo[1].epAddr = 1; - epInfo[1].maxPktSize = 8; //kludge - epInfo[1].epAttribs = 0; - epInfo[1].bmNakPower = USB_NAK_NOWAIT; - - if(pUsb) - pUsb->RegisterDeviceClass(this); -} - -uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed) { - uint8_t buf[32]; - USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast(buf); - HubDescriptor* hd = reinterpret_cast(buf); - USB_CONFIGURATION_DESCRIPTOR * ucd = reinterpret_cast(buf); - uint8_t rcode; - UsbDevice *p = NULL; - EpInfo *oldep_ptr = NULL; - uint8_t len = 0; - uint16_t cd_len = 0; - - //USBTRACE("\r\nHub Init Start "); - //D_PrintHex (bInitState, 0x80); - - AddressPool &addrPool = pUsb->GetAddressPool(); - - //switch (bInitState) { - // case 0: - if(bAddress) - return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; - - // Get pointer to pseudo device with address 0 assigned - p = addrPool.GetUsbDevicePtr(0); - - if(!p) - return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; - - if(!p->epinfo) - return USB_ERROR_EPINFO_IS_NULL; - - // Save old pointer to EP_RECORD of address 0 - oldep_ptr = p->epinfo; - - // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence - p->epinfo = epInfo; - - p->lowspeed = lowspeed; - - // Get device descriptor - rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*)buf); - - p->lowspeed = false; - - if(!rcode) - len = (buf[0] > 32) ? 32 : buf[0]; - - if(rcode) { - // Restore p->epinfo - p->epinfo = oldep_ptr; - return rcode; - } - - // Extract device class from device descriptor - // If device class is not a hub return - if(udd->bDeviceClass != 0x09) - return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - - // Allocate new address according to device class - bAddress = addrPool.AllocAddress(parent, (udd->bDeviceClass == 0x09) ? true : false, port); - - if(!bAddress) - return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; - - // Extract Max Packet Size from the device descriptor - epInfo[0].maxPktSize = udd->bMaxPacketSize0; - - // Assign new address to the device - rcode = pUsb->setAddr(0, 0, bAddress); - - if(rcode) { - // Restore p->epinfo - p->epinfo = oldep_ptr; - addrPool.FreeAddress(bAddress); - bAddress = 0; - return rcode; - } - - //USBTRACE2("\r\nHub address: ", bAddress ); - - // Restore p->epinfo - p->epinfo = oldep_ptr; - - if(len) - rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf); - - if(rcode) - goto FailGetDevDescr; - - // Assign epInfo to epinfo pointer - rcode = pUsb->setEpInfoEntry(bAddress, 2, epInfo); - - if(rcode) - goto FailSetDevTblEntry; - - // bInitState = 1; - - // case 1: - // Get hub descriptor - rcode = GetHubDescriptor(0, 8, buf); - - if(rcode) - goto FailGetHubDescr; - - // Save number of ports for future use - bNbrPorts = hd->bNbrPorts; - - // bInitState = 2; - - // case 2: - // Read configuration Descriptor in Order To Obtain Proper Configuration Value - rcode = pUsb->getConfDescr(bAddress, 0, 8, 0, buf); - - if(!rcode) { - cd_len = ucd->wTotalLength; - rcode = pUsb->getConfDescr(bAddress, 0, cd_len, 0, buf); - } - if(rcode) - goto FailGetConfDescr; - - // The following code is of no practical use in real life applications. - // It only intended for the usb protocol sniffer to properly parse hub-class requests. - { - uint8_t buf2[24]; - - rcode = pUsb->getConfDescr(bAddress, 0, buf[0], 0, buf2); - - if(rcode) - goto FailGetConfDescr; - } - - // Set Configuration Value - rcode = pUsb->setConf(bAddress, 0, buf[5]); - - if(rcode) - goto FailSetConfDescr; - - // bInitState = 3; - - // case 3: - // Power on all ports - for(uint8_t j = 1; j <= bNbrPorts; j++) - SetPortFeature(HUB_FEATURE_PORT_POWER, j, 0); //HubPortPowerOn(j); - - pUsb->SetHubPreMask(); - bPollEnable = true; - // bInitState = 0; - //} - //bInitState = 0; - //USBTRACE("...OK\r\n"); - return 0; - - // Oleg, No debugging?? -- xxxajk -FailGetDevDescr: - goto Fail; - -FailSetDevTblEntry: - goto Fail; - -FailGetHubDescr: - goto Fail; - -FailGetConfDescr: - goto Fail; - -FailSetConfDescr: - goto Fail; - -Fail: - USBTRACE("...FAIL\r\n"); - return rcode; -} - -uint8_t USBHub::Release() { - pUsb->GetAddressPool().FreeAddress(bAddress); - - if(bAddress == 0x41) - pUsb->SetHubPreMask(); - - bAddress = 0; - bNbrPorts = 0; - qNextPollTime = 0; - bPollEnable = false; - return 0; -} - -uint8_t USBHub::Poll() { - uint8_t rcode = 0; - - if(!bPollEnable) - return 0; - - if(((long)(millis() - qNextPollTime) >= 0L)) { - rcode = CheckHubStatus(); - qNextPollTime = millis() + 100; - } - return rcode; -} - -uint8_t USBHub::CheckHubStatus() { - uint8_t rcode; - uint8_t buf[8]; - uint16_t read = 1; - - rcode = pUsb->inTransfer(bAddress, 1, &read, buf); - - if(rcode) - return rcode; - - //if (buf[0] & 0x01) // Hub Status Change - //{ - // pUsb->PrintHubStatus(addr); - // rcode = GetHubStatus(1, 0, 1, 4, buf); - // if (rcode) - // { - // USB_HOST_SERIAL.print("GetHubStatus Error"); - // USB_HOST_SERIAL.println(rcode, HEX); - // return rcode; - // } - //} - for(uint8_t port = 1, mask = 0x02; port < 8; mask <<= 1, port++) { - if(buf[0] & mask) { - HubEvent evt; - evt.bmEvent = 0; - - rcode = GetPortStatus(port, 4, evt.evtBuff); - - if(rcode) - continue; - - rcode = PortStatusChange(port, evt); - - if(rcode == HUB_ERROR_PORT_HAS_BEEN_RESET) - return 0; - - if(rcode) - return rcode; - } - } // for - - for(uint8_t port = 1; port <= bNbrPorts; port++) { - HubEvent evt; - evt.bmEvent = 0; - - rcode = GetPortStatus(port, 4, evt.evtBuff); - - if(rcode) - continue; - - if((evt.bmStatus & bmHUB_PORT_STATE_CHECK_DISABLED) != bmHUB_PORT_STATE_DISABLED) - continue; - - // Emulate connection event for the port - evt.bmChange |= bmHUB_PORT_STATUS_C_PORT_CONNECTION; - - rcode = PortStatusChange(port, evt); - - if(rcode == HUB_ERROR_PORT_HAS_BEEN_RESET) - return 0; - - if(rcode) - return rcode; - } // for - return 0; -} - -void USBHub::ResetHubPort(uint8_t port) { - HubEvent evt; - evt.bmEvent = 0; - uint8_t rcode; - - ClearPortFeature(HUB_FEATURE_C_PORT_ENABLE, port, 0); - ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0); - SetPortFeature(HUB_FEATURE_PORT_RESET, port, 0); - - - for(int i = 0; i < 3; i++) { - rcode = GetPortStatus(port, 4, evt.evtBuff); - if(rcode) break; // Some kind of error, bail. - if(evt.bmEvent == bmHUB_PORT_EVENT_RESET_COMPLETE || evt.bmEvent == bmHUB_PORT_EVENT_LS_RESET_COMPLETE) { - break; - } - delay(100); // simulate polling. - } - ClearPortFeature(HUB_FEATURE_C_PORT_RESET, port, 0); - ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0); - delay(20); -} - -uint8_t USBHub::PortStatusChange(uint8_t port, HubEvent &evt) { - switch(evt.bmEvent) { - // Device connected event - case bmHUB_PORT_EVENT_CONNECT: - case bmHUB_PORT_EVENT_LS_CONNECT: - if(bResetInitiated) - return 0; - - ClearPortFeature(HUB_FEATURE_C_PORT_ENABLE, port, 0); - ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0); - SetPortFeature(HUB_FEATURE_PORT_RESET, port, 0); - bResetInitiated = true; - return HUB_ERROR_PORT_HAS_BEEN_RESET; - - // Device disconnected event - case bmHUB_PORT_EVENT_DISCONNECT: - ClearPortFeature(HUB_FEATURE_C_PORT_ENABLE, port, 0); - ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0); - bResetInitiated = false; - - UsbDeviceAddress a; - a.devAddress = 0; - a.bmHub = 0; - a.bmParent = bAddress; - a.bmAddress = port; - pUsb->ReleaseDevice(a.devAddress); - return 0; - - // Reset complete event - case bmHUB_PORT_EVENT_RESET_COMPLETE: - case bmHUB_PORT_EVENT_LS_RESET_COMPLETE: - ClearPortFeature(HUB_FEATURE_C_PORT_RESET, port, 0); - ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0); - - delay(20); - - a.devAddress = bAddress; - - pUsb->Configuring(a.bmAddress, port, (evt.bmStatus & bmHUB_PORT_STATUS_PORT_LOW_SPEED)); - bResetInitiated = false; - break; - - } // switch (evt.bmEvent) - return 0; -} - -void PrintHubPortStatus(USBHub *hubptr, uint8_t addr, uint8_t port, bool print_changes) { - uint8_t rcode = 0; - HubEvent evt; - - rcode = hubptr->GetPortStatus(port, 4, evt.evtBuff); - - if(rcode) { - USB_HOST_SERIAL.println("ERROR!"); - return; - } - USB_HOST_SERIAL.print("\r\nPort "); - USB_HOST_SERIAL.println(port, DEC); - - USB_HOST_SERIAL.println("Status"); - USB_HOST_SERIAL.print("CONNECTION:\t"); - USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_CONNECTION) > 0, DEC); - USB_HOST_SERIAL.print("ENABLE:\t\t"); - USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_ENABLE) > 0, DEC); - USB_HOST_SERIAL.print("SUSPEND:\t"); - USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_SUSPEND) > 0, DEC); - USB_HOST_SERIAL.print("OVER_CURRENT:\t"); - USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_OVER_CURRENT) > 0, DEC); - USB_HOST_SERIAL.print("RESET:\t\t"); - USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_RESET) > 0, DEC); - USB_HOST_SERIAL.print("POWER:\t\t"); - USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_POWER) > 0, DEC); - USB_HOST_SERIAL.print("LOW_SPEED:\t"); - USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_LOW_SPEED) > 0, DEC); - USB_HOST_SERIAL.print("HIGH_SPEED:\t"); - USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_HIGH_SPEED) > 0, DEC); - USB_HOST_SERIAL.print("TEST:\t\t"); - USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_TEST) > 0, DEC); - USB_HOST_SERIAL.print("INDICATOR:\t"); - USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_INDICATOR) > 0, DEC); - - if(!print_changes) - return; - - USB_HOST_SERIAL.println("\r\nChange"); - USB_HOST_SERIAL.print("CONNECTION:\t"); - USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_CONNECTION) > 0, DEC); - USB_HOST_SERIAL.print("ENABLE:\t\t"); - USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_ENABLE) > 0, DEC); - USB_HOST_SERIAL.print("SUSPEND:\t"); - USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_SUSPEND) > 0, DEC); - USB_HOST_SERIAL.print("OVER_CURRENT:\t"); - USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_OVER_CURRENT) > 0, DEC); - USB_HOST_SERIAL.print("RESET:\t\t"); - USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_RESET) > 0, DEC); -} diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/usbhub.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/usbhub.h deleted file mode 100644 index 1ac949445a..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/usbhub.h +++ /dev/null @@ -1,252 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ -#if !defined(__USBHUB_H__) -#define __USBHUB_H__ - -#include "Usb.h" - -#define USB_DESCRIPTOR_HUB 0x09 // Hub descriptor type - -// Hub Requests -#define bmREQ_CLEAR_HUB_FEATURE USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE -#define bmREQ_CLEAR_PORT_FEATURE USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER -#define bmREQ_CLEAR_TT_BUFFER USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER -#define bmREQ_GET_HUB_DESCRIPTOR USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE -#define bmREQ_GET_HUB_STATUS USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE -#define bmREQ_GET_PORT_STATUS USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER -#define bmREQ_RESET_TT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER -#define bmREQ_SET_HUB_DESCRIPTOR USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE -#define bmREQ_SET_HUB_FEATURE USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE -#define bmREQ_SET_PORT_FEATURE USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER -#define bmREQ_GET_TT_STATE USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER -#define bmREQ_STOP_TT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER - -// Hub Class Requests -#define HUB_REQUEST_CLEAR_TT_BUFFER 8 -#define HUB_REQUEST_RESET_TT 9 -#define HUB_REQUEST_GET_TT_STATE 10 -#define HUB_REQUEST_STOP_TT 11 - -// Hub Features -#define HUB_FEATURE_C_HUB_LOCAL_POWER 0 -#define HUB_FEATURE_C_HUB_OVER_CURRENT 1 -#define HUB_FEATURE_PORT_CONNECTION 0 -#define HUB_FEATURE_PORT_ENABLE 1 -#define HUB_FEATURE_PORT_SUSPEND 2 -#define HUB_FEATURE_PORT_OVER_CURRENT 3 -#define HUB_FEATURE_PORT_RESET 4 -#define HUB_FEATURE_PORT_POWER 8 -#define HUB_FEATURE_PORT_LOW_SPEED 9 -#define HUB_FEATURE_C_PORT_CONNECTION 16 -#define HUB_FEATURE_C_PORT_ENABLE 17 -#define HUB_FEATURE_C_PORT_SUSPEND 18 -#define HUB_FEATURE_C_PORT_OVER_CURRENT 19 -#define HUB_FEATURE_C_PORT_RESET 20 -#define HUB_FEATURE_PORT_TEST 21 -#define HUB_FEATURE_PORT_INDICATOR 22 - -// Hub Port Test Modes -#define HUB_PORT_TEST_MODE_J 1 -#define HUB_PORT_TEST_MODE_K 2 -#define HUB_PORT_TEST_MODE_SE0_NAK 3 -#define HUB_PORT_TEST_MODE_PACKET 4 -#define HUB_PORT_TEST_MODE_FORCE_ENABLE 5 - -// Hub Port Indicator Color -#define HUB_PORT_INDICATOR_AUTO 0 -#define HUB_PORT_INDICATOR_AMBER 1 -#define HUB_PORT_INDICATOR_GREEN 2 -#define HUB_PORT_INDICATOR_OFF 3 - -// Hub Port Status Bitmasks -#define bmHUB_PORT_STATUS_PORT_CONNECTION 0x0001 -#define bmHUB_PORT_STATUS_PORT_ENABLE 0x0002 -#define bmHUB_PORT_STATUS_PORT_SUSPEND 0x0004 -#define bmHUB_PORT_STATUS_PORT_OVER_CURRENT 0x0008 -#define bmHUB_PORT_STATUS_PORT_RESET 0x0010 -#define bmHUB_PORT_STATUS_PORT_POWER 0x0100 -#define bmHUB_PORT_STATUS_PORT_LOW_SPEED 0x0200 -#define bmHUB_PORT_STATUS_PORT_HIGH_SPEED 0x0400 -#define bmHUB_PORT_STATUS_PORT_TEST 0x0800 -#define bmHUB_PORT_STATUS_PORT_INDICATOR 0x1000 - -// Hub Port Status Change Bitmasks (used one byte instead of two) -#define bmHUB_PORT_STATUS_C_PORT_CONNECTION 0x0001 -#define bmHUB_PORT_STATUS_C_PORT_ENABLE 0x0002 -#define bmHUB_PORT_STATUS_C_PORT_SUSPEND 0x0004 -#define bmHUB_PORT_STATUS_C_PORT_OVER_CURRENT 0x0008 -#define bmHUB_PORT_STATUS_C_PORT_RESET 0x0010 - -// Hub Status Bitmasks (used one byte instead of two) -#define bmHUB_STATUS_LOCAL_POWER_SOURCE 0x01 -#define bmHUB_STATUS_OVER_CURRENT 0x12 - -// Hub Status Change Bitmasks (used one byte instead of two) -#define bmHUB_STATUS_C_LOCAL_POWER_SOURCE 0x01 -#define bmHUB_STATUS_C_OVER_CURRENT 0x12 - - -// Hub Port Configuring Substates -#define USB_STATE_HUB_PORT_CONFIGURING 0xb0 -#define USB_STATE_HUB_PORT_POWERED_OFF 0xb1 -#define USB_STATE_HUB_PORT_WAIT_FOR_POWER_GOOD 0xb2 -#define USB_STATE_HUB_PORT_DISCONNECTED 0xb3 -#define USB_STATE_HUB_PORT_DISABLED 0xb4 -#define USB_STATE_HUB_PORT_RESETTING 0xb5 -#define USB_STATE_HUB_PORT_ENABLED 0xb6 - -// Additional Error Codes -#define HUB_ERROR_PORT_HAS_BEEN_RESET 0xb1 - -// The bit mask to check for all necessary state bits -#define bmHUB_PORT_STATUS_ALL_MAIN ((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION | bmHUB_PORT_STATUS_C_PORT_ENABLE | bmHUB_PORT_STATUS_C_PORT_SUSPEND | bmHUB_PORT_STATUS_C_PORT_RESET) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_SUSPEND) - -// Bit mask to check for DISABLED state in HubEvent::bmStatus field -#define bmHUB_PORT_STATE_CHECK_DISABLED (0x0000 | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_SUSPEND) - -// Hub Port States -#define bmHUB_PORT_STATE_DISABLED (0x0000 | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_CONNECTION) - -// Hub Port Events -#define bmHUB_PORT_EVENT_CONNECT (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_CONNECTION) -#define bmHUB_PORT_EVENT_DISCONNECT (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION) << 16) | bmHUB_PORT_STATUS_PORT_POWER) -#define bmHUB_PORT_EVENT_RESET_COMPLETE (((0UL | bmHUB_PORT_STATUS_C_PORT_RESET) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION) - -#define bmHUB_PORT_EVENT_LS_CONNECT (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_LOW_SPEED) -#define bmHUB_PORT_EVENT_LS_RESET_COMPLETE (((0UL | bmHUB_PORT_STATUS_C_PORT_RESET) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_LOW_SPEED) -#define bmHUB_PORT_EVENT_LS_PORT_ENABLED (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION | bmHUB_PORT_STATUS_C_PORT_ENABLE) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_LOW_SPEED) - -struct HubDescriptor { - uint8_t bDescLength; // descriptor length - uint8_t bDescriptorType; // descriptor type - uint8_t bNbrPorts; // number of ports a hub equiped with - - struct { - uint16_t LogPwrSwitchMode : 2; - uint16_t CompoundDevice : 1; - uint16_t OverCurrentProtectMode : 2; - uint16_t TTThinkTime : 2; - uint16_t PortIndicatorsSupported : 1; - uint16_t Reserved : 8; - } __attribute__((packed)); - - uint8_t bPwrOn2PwrGood; - uint8_t bHubContrCurrent; -} __attribute__((packed)); - -struct HubEvent { - - union { - - struct { - uint16_t bmStatus; // port status bits - uint16_t bmChange; // port status change bits - } __attribute__((packed)); - uint32_t bmEvent; - uint8_t evtBuff[4]; - }; -} __attribute__((packed)); - -class USBHub : USBDeviceConfig { - static bool bResetInitiated; // True when reset is triggered - - USB *pUsb; // USB class instance pointer - - EpInfo epInfo[2]; // interrupt endpoint info structure - - uint8_t bAddress; // address - uint8_t bNbrPorts; // number of ports - // uint8_t bInitState; // initialization state variable - uint32_t qNextPollTime; // next poll time - bool bPollEnable; // poll enable flag - - uint8_t CheckHubStatus(); - uint8_t PortStatusChange(uint8_t port, HubEvent &evt); - -public: - USBHub(USB *p); - - uint8_t ClearHubFeature(uint8_t fid); - uint8_t ClearPortFeature(uint8_t fid, uint8_t port, uint8_t sel = 0); - uint8_t GetHubDescriptor(uint8_t index, uint16_t nbytes, uint8_t *dataptr); - uint8_t GetHubStatus(uint16_t nbytes, uint8_t* dataptr); - uint8_t GetPortStatus(uint8_t port, uint16_t nbytes, uint8_t* dataptr); - uint8_t SetHubDescriptor(uint8_t port, uint16_t nbytes, uint8_t* dataptr); - uint8_t SetHubFeature(uint8_t fid); - uint8_t SetPortFeature(uint8_t fid, uint8_t port, uint8_t sel = 0); - - void PrintHubStatus(); - - uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); - uint8_t Release(); - uint8_t Poll(); - void ResetHubPort(uint8_t port); - - virtual uint8_t GetAddress() { - return bAddress; - }; - - virtual bool DEVCLASSOK(uint8_t klass) { - return (klass == 0x09); - } - -}; - -// Clear Hub Feature - -inline uint8_t USBHub::ClearHubFeature(uint8_t fid) { - return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CLEAR_HUB_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, 0, 0, 0, NULL, NULL)); -} -// Clear Port Feature - -inline uint8_t USBHub::ClearPortFeature(uint8_t fid, uint8_t port, uint8_t sel) { - return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CLEAR_PORT_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, ((0x0000 | port) | (sel << 8)), 0, 0, NULL, NULL)); -} -// Get Hub Descriptor - -inline uint8_t USBHub::GetHubDescriptor(uint8_t index, uint16_t nbytes, uint8_t *dataptr) { - return ( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_HUB_DESCRIPTOR, USB_REQUEST_GET_DESCRIPTOR, index, 0x29, 0, nbytes, nbytes, dataptr, NULL)); -} -// Get Hub Status - -inline uint8_t USBHub::GetHubStatus(uint16_t nbytes, uint8_t* dataptr) { - return ( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_HUB_STATUS, USB_REQUEST_GET_STATUS, 0, 0, 0x0000, nbytes, nbytes, dataptr, NULL)); -} -// Get Port Status - -inline uint8_t USBHub::GetPortStatus(uint8_t port, uint16_t nbytes, uint8_t* dataptr) { - return ( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_PORT_STATUS, USB_REQUEST_GET_STATUS, 0, 0, port, nbytes, nbytes, dataptr, NULL)); -} -// Set Hub Descriptor - -inline uint8_t USBHub::SetHubDescriptor(uint8_t port, uint16_t nbytes, uint8_t* dataptr) { - return ( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_HUB_DESCRIPTOR, USB_REQUEST_SET_DESCRIPTOR, 0, 0, port, nbytes, nbytes, dataptr, NULL)); -} -// Set Hub Feature - -inline uint8_t USBHub::SetHubFeature(uint8_t fid) { - return ( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_HUB_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, 0, 0, 0, NULL, NULL)); -} -// Set Port Feature - -inline uint8_t USBHub::SetPortFeature(uint8_t fid, uint8_t port, uint8_t sel) { - return ( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_PORT_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, (((0x0000 | sel) << 8) | port), 0, 0, NULL, NULL)); -} - -void PrintHubPortStatus(USB *usbptr, uint8_t addr, uint8_t port, bool print_changes = false); - -#endif // __USBHUB_H__ diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/version_helper.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/version_helper.h deleted file mode 100644 index 0cb3b4adc0..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/version_helper.h +++ /dev/null @@ -1,194 +0,0 @@ -/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as published by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : http://www.circuitsathome.com -e-mail : support@circuitsathome.com - */ - -/* - * Universal Arduino(tm) "IDE" fixups. - * Includes fixes for versions as low as 0023, used by Digilent. - */ - -#if defined(ARDUINO) && ARDUINO >=100 -#include -#else -#include -#include -#ifdef __AVR__ -#include -#include -#else -#endif -#endif - -#ifndef __PGMSPACE_H_ -#define __PGMSPACE_H_ 1 - -#include - -#ifndef PROGMEM -#define PROGMEM -#endif -#ifndef PGM_P -#define PGM_P const char * -#endif -#ifndef PSTR -#define PSTR(str) (str) -#endif -#ifndef F -#define F(str) (str) -#endif -#ifndef _SFR_BYTE -#define _SFR_BYTE(n) (n) -#endif - -#ifndef memchr_P -#define memchr_P(str, c, len) memchr((str), (c), (len)) -#endif -#ifndef memcmp_P -#define memcmp_P(a, b, n) memcmp((a), (b), (n)) -#endif -#ifndef memcpy_P -#define memcpy_P(dest, src, num) memcpy((dest), (src), (num)) -#endif -#ifndef memmem_P -#define memmem_P(a, alen, b, blen) memmem((a), (alen), (b), (blen)) -#endif -#ifndef memrchr_P -#define memrchr_P(str, val, len) memrchr((str), (val), (len)) -#endif -#ifndef strcat_P -#define strcat_P(dest, src) strcat((dest), (src)) -#endif -#ifndef strchr_P -#define strchr_P(str, c) strchr((str), (c)) -#endif -#ifndef strchrnul_P -#define strchrnul_P(str, c) strchrnul((str), (c)) -#endif -#ifndef strcmp_P -#define strcmp_P(a, b) strcmp((a), (b)) -#endif -#ifndef strcpy_P -#define strcpy_P(dest, src) strcpy((dest), (src)) -#endif -#ifndef strcasecmp_P -#define strcasecmp_P(a, b) strcasecmp((a), (b)) -#endif -#ifndef strcasestr_P -#define strcasestr_P(a, b) strcasestr((a), (b)) -#endif -#ifndef strlcat_P -#define strlcat_P(dest, src, len) strlcat((dest), (src), (len)) -#endif -#ifndef strlcpy_P -#define strlcpy_P(dest, src, len) strlcpy((dest), (src), (len)) -#endif -#ifndef strlen_P -#define strlen_P(s) strlen((const char *)(s)) -#endif -#ifndef strnlen_P -#define strnlen_P(str, len) strnlen((str), (len)) -#endif -#ifndef strncmp_P -#define strncmp_P(a, b, n) strncmp((a), (b), (n)) -#endif -#ifndef strncasecmp_P -#define strncasecmp_P(a, b, n) strncasecmp((a), (b), (n)) -#endif -#ifndef strncat_P -#define strncat_P(a, b, n) strncat((a), (b), (n)) -#endif -#ifndef strncpy_P -#define strncpy_P(a, b, n) strncmp((a), (b), (n)) -#endif -#ifndef strpbrk_P -#define strpbrk_P(str, chrs) strpbrk((str), (chrs)) -#endif -#ifndef strrchr_P -#define strrchr_P(str, c) strrchr((str), (c)) -#endif -#ifndef strsep_P -#define strsep_P(strp, delim) strsep((strp), (delim)) -#endif -#ifndef strspn_P -#define strspn_P(str, chrs) strspn((str), (chrs)) -#endif -#ifndef strstr_P -#define strstr_P(a, b) strstr((a), (b)) -#endif -#ifndef sprintf_P -#define sprintf_P(s, ...) sprintf((s), __VA_ARGS__) -#endif -#ifndef vfprintf_P -#define vfprintf_P(s, ...) vfprintf((s), __VA_ARGS__) -#endif -#ifndef printf_P -#define printf_P(...) printf(__VA_ARGS__) -#endif -#ifndef snprintf_P -#define snprintf_P(s, n, ...) ((s), (n), __VA_ARGS__) -#endif -#ifndef vsprintf_P -#define vsprintf_P(s, ...) ((s),__VA_ARGS__) -#endif -#ifndef vsnprintf_P -#define vsnprintf_P(s, n, ...) ((s), (n),__VA_ARGS__) -#endif -#ifndef fprintf_P -#define fprintf_P(s, ...) ((s), __VA_ARGS__) -#endif - -#ifndef pgm_read_byte -#define pgm_read_byte(addr) (*(const unsigned char *)(addr)) -#endif -#ifndef pgm_read_word -#define pgm_read_word(addr) (*(const unsigned short *)(addr)) -#endif -#ifndef pgm_read_dword -#define pgm_read_dword(addr) (*(const unsigned long *)(addr)) -#endif -#ifndef pgm_read_float -#define pgm_read_float(addr) (*(const float *)(addr)) -#endif - -#ifndef pgm_read_byte_near -#define pgm_read_byte_near(addr) pgm_read_byte(addr) -#endif -#ifndef pgm_read_word_near -#define pgm_read_word_near(addr) pgm_read_word(addr) -#endif -#ifndef pgm_read_dword_near -#define pgm_read_dword_near(addr) pgm_read_dword(addr) -#endif -#ifndef pgm_read_float_near -#define pgm_read_float_near(addr) pgm_read_float(addr) -#endif -#ifndef pgm_read_byte_far -#define pgm_read_byte_far(addr) pgm_read_byte(addr) -#endif -#ifndef pgm_read_word_far -#define pgm_read_word_far(addr) pgm_read_word(addr) -#endif -#ifndef pgm_read_dword_far -#define pgm_read_dword_far(addr) pgm_read_dword(addr) -#endif -#ifndef pgm_read_float_far -#define pgm_read_float_far(addr) pgm_read_float(addr) -#endif - -#ifndef pgm_read_pointer -#define pgm_read_pointer -#endif -#endif diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/xboxEnums.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/xboxEnums.h deleted file mode 100644 index 84b137bb6e..0000000000 --- a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/xboxEnums.h +++ /dev/null @@ -1,65 +0,0 @@ -/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. - - This software may be distributed and modified under the terms of the GNU - General Public License version 2 (GPL2) as published by the Free Software - Foundation and appearing in the file GPL2.TXT included in the packaging of - this file. Please note that GPL2 Section 2[b] requires that all works based - on this software must also be made publicly available under the terms of - the GPL2 ("Copyleft"). - - Contact information - ------------------- - - Kristian Lauszus, TKJ Electronics - Web : http://www.tkjelectronics.com - e-mail : kristianl@tkjelectronics.com - */ - -#ifndef _xboxenums_h -#define _xboxenums_h - -#include "controllerEnums.h" - -/** Enum used to set special LED modes supported by the Xbox controller. */ -enum LEDModeEnum { - ROTATING = 0x0A, - FASTBLINK = 0x0B, - SLOWBLINK = 0x0C, - ALTERNATING = 0x0D, -}; - -/** Used to set the LEDs on the controllers */ -const uint8_t XBOX_LEDS[] PROGMEM = { - 0x00, // OFF - 0x02, // LED1 - 0x03, // LED2 - 0x04, // LED3 - 0x05, // LED4 - 0x01, // ALL - Used to blink all LEDs -}; -/** Buttons on the controllers */ -const uint16_t XBOX_BUTTONS[] PROGMEM = { - 0x0100, // UP - 0x0800, // RIGHT - 0x0200, // DOWN - 0x0400, // LEFT - - 0x2000, // BACK - 0x1000, // START - 0x4000, // L3 - 0x8000, // R3 - - 0, 0, // Skip L2 and R2 as these are analog buttons - 0x0001, // L1 - 0x0002, // R1 - - 0x0020, // B - 0x0010, // A - 0x0040, // X - 0x0080, // Y - - 0x0004, // XBOX - 0x0008, // SYNC -}; - -#endif diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Arduino.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Arduino.h deleted file mode 100644 index 830c9952fb..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Arduino.h +++ /dev/null @@ -1,215 +0,0 @@ -#ifndef Arduino_h -#define Arduino_h - -#include -#include -#include - -#include -#include -#include - -#include "binary.h" - -#ifdef __cplusplus -extern "C"{ -#endif - -#define HIGH 0x1 -#define LOW 0x0 - -#define INPUT 0x0 -#define OUTPUT 0x1 -#define INPUT_PULLUP 0x2 - -#define true 0x1 -#define false 0x0 - -#define PI 3.1415926535897932384626433832795 -#define HALF_PI 1.5707963267948966192313216916398 -#define TWO_PI 6.283185307179586476925286766559 -#define DEG_TO_RAD 0.017453292519943295769236907684886 -#define RAD_TO_DEG 57.295779513082320876798154814105 - -#define SERIAL 0x0 -#define DISPLAY 0x1 - -#define LSBFIRST 0 -#define MSBFIRST 1 - -#define CHANGE 1 -#define FALLING 2 -#define RISING 3 - -#if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) -#define DEFAULT 0 -#define EXTERNAL 1 -#define INTERNAL 2 -#else -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1284P__) -#define INTERNAL1V1 2 -#define INTERNAL2V56 3 -#else -#define INTERNAL 3 -#endif -#define DEFAULT 1 -#define EXTERNAL 0 -#endif - -// undefine stdlib's abs if encountered -#ifdef abs -#undef abs -#endif - -#define min(a,b) ((a)<(b)?(a):(b)) -#define max(a,b) ((a)>(b)?(a):(b)) -#define abs(x) ((x)>0?(x):-(x)) -#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt))) -#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5)) -#define radians(deg) ((deg)*DEG_TO_RAD) -#define degrees(rad) ((rad)*RAD_TO_DEG) -#define sq(x) ((x)*(x)) - -#define interrupts() sei() -#define noInterrupts() cli() - -#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L ) -#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() ) -#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() ) - -#define lowByte(w) ((uint8_t) ((w) & 0xff)) -#define highByte(w) ((uint8_t) ((w) >> 8)) - -#define bitRead(value, bit) (((value) >> (bit)) & 0x01) -#define bitSet(value, bit) ((value) |= (1UL << (bit))) -#define bitClear(value, bit) ((value) &= ~(1UL << (bit))) -#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit)) - - -typedef unsigned int word; - -#define bit(b) (1UL << (b)) - -typedef uint8_t boolean; -typedef uint8_t byte; - -void init(void); - -void pinMode(uint8_t, uint8_t); -void digitalWrite(uint8_t, uint8_t); -int digitalRead(uint8_t); -int analogRead(uint8_t); -void analogReference(uint8_t mode); -void analogWrite(uint8_t, int); - -unsigned long millis(void); -unsigned long micros(void); -void delay(unsigned long); -void delayMicroseconds(unsigned int us); -unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout); - -void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val); -uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder); - -void attachInterrupt(uint8_t, void (*)(void), int mode); -void detachInterrupt(uint8_t); - -void setup(void); -void loop(void); - -// Get the bit location within the hardware port of the given virtual pin. -// This comes from the pins_*.c file for the active board configuration. - -#define analogInPinToBit(P) (P) - -// On the ATmega1280, the addresses of some of the port registers are -// greater than 255, so we can't store them in uint8_t's. -extern const uint16_t PROGMEM port_to_mode_PGM[]; -extern const uint16_t PROGMEM port_to_input_PGM[]; -extern const uint16_t PROGMEM port_to_output_PGM[]; - -extern const uint8_t PROGMEM digital_pin_to_port_PGM[]; -// extern const uint8_t PROGMEM digital_pin_to_bit_PGM[]; -extern const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[]; -extern const uint8_t PROGMEM digital_pin_to_timer_PGM[]; - -// Get the bit location within the hardware port of the given virtual pin. -// This comes from the pins_*.c file for the active board configuration. -// -// These perform slightly better as macros compared to inline functions -// -#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) ) -#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) ) -#define digitalPinToTimer(P) ( pgm_read_byte( digital_pin_to_timer_PGM + (P) ) ) -#define analogInPinToBit(P) (P) -#define portOutputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_output_PGM + (P))) ) -#define portInputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_input_PGM + (P))) ) -#define portModeRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_mode_PGM + (P))) ) - -#define NOT_A_PIN 0 -#define NOT_A_PORT 0 - -#ifdef ARDUINO_MAIN -#define PA 1 -#define PB 2 -#define PC 3 -#define PD 4 -#define PE 5 -#define PF 6 -#define PG 7 -#define PH 8 -#define PJ 10 -#define PK 11 -#define PL 12 -#endif - -#define NOT_ON_TIMER 0 -#define TIMER0A 1 -#define TIMER0B 2 -#define TIMER1A 3 -#define TIMER1B 4 -#define TIMER2 5 -#define TIMER2A 6 -#define TIMER2B 7 - -#define TIMER3A 8 -#define TIMER3B 9 -#define TIMER3C 10 -#define TIMER4A 11 -#define TIMER4B 12 -#define TIMER4C 13 -#define TIMER4D 14 -#define TIMER5A 15 -#define TIMER5B 16 -#define TIMER5C 17 - -#ifdef __cplusplus -} // extern "C" -#endif - -#ifdef __cplusplus -#include "WCharacter.h" -#include "WString.h" -#include "HardwareSerial.h" - -uint16_t makeWord(uint16_t w); -uint16_t makeWord(byte h, byte l); - -#define word(...) makeWord(__VA_ARGS__) - -unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L); - -void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0); -void noTone(uint8_t _pin); - -// WMath prototypes -long random(long); -long random(long, long); -void randomSeed(unsigned int); -long map(long, long, long, long, long); - -#endif - -#include "pins_arduino.h" - -#endif diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/CDC.cpp b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/CDC.cpp deleted file mode 100644 index 1ee3a488a5..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/CDC.cpp +++ /dev/null @@ -1,233 +0,0 @@ - - -/* Copyright (c) 2011, Peter Barrett -** -** Permission to use, copy, modify, and/or distribute this software for -** any purpose with or without fee is hereby granted, provided that the -** above copyright notice and this permission notice appear in all copies. -** -** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL -** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR -** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES -** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -** SOFTWARE. -*/ - -#include "Platform.h" -#include "USBAPI.h" -#include - -#if defined(USBCON) -#ifdef CDC_ENABLED - -#if (RAMEND < 1000) -#define SERIAL_BUFFER_SIZE 16 -#else -#define SERIAL_BUFFER_SIZE 64 -#endif - -struct ring_buffer -{ - unsigned char buffer[SERIAL_BUFFER_SIZE]; - volatile int head; - volatile int tail; -}; - -ring_buffer cdc_rx_buffer = { { 0 }, 0, 0}; - -typedef struct -{ - u32 dwDTERate; - u8 bCharFormat; - u8 bParityType; - u8 bDataBits; - u8 lineState; -} LineInfo; - -static volatile LineInfo _usbLineInfo = { 57600, 0x00, 0x00, 0x00, 0x00 }; - -#define WEAK __attribute__ ((weak)) - -extern const CDCDescriptor _cdcInterface PROGMEM; -const CDCDescriptor _cdcInterface = -{ - D_IAD(0,2,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,1), - - // CDC communication interface - D_INTERFACE(CDC_ACM_INTERFACE,1,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,0), - D_CDCCS(CDC_HEADER,0x10,0x01), // Header (1.10 bcd) - D_CDCCS(CDC_CALL_MANAGEMENT,1,1), // Device handles call management (not) - D_CDCCS4(CDC_ABSTRACT_CONTROL_MANAGEMENT,6), // SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE supported - D_CDCCS(CDC_UNION,CDC_ACM_INTERFACE,CDC_DATA_INTERFACE), // Communication interface is master, data interface is slave 0 - D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_ACM),USB_ENDPOINT_TYPE_INTERRUPT,0x10,0x40), - - // CDC data interface - D_INTERFACE(CDC_DATA_INTERFACE,2,CDC_DATA_INTERFACE_CLASS,0,0), - D_ENDPOINT(USB_ENDPOINT_OUT(CDC_ENDPOINT_OUT),USB_ENDPOINT_TYPE_BULK,0x40,0), - D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,0x40,0) -}; - -int WEAK CDC_GetInterface(u8* interfaceNum) -{ - interfaceNum[0] += 2; // uses 2 - return USB_SendControl(TRANSFER_PGM,&_cdcInterface,sizeof(_cdcInterface)); -} - -bool WEAK CDC_Setup(Setup& setup) -{ - u8 r = setup.bRequest; - u8 requestType = setup.bmRequestType; - - if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType) - { - if (CDC_GET_LINE_CODING == r) - { - USB_SendControl(0,(void*)&_usbLineInfo,7); - return true; - } - } - - if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType) - { - if (CDC_SET_LINE_CODING == r) - { - USB_RecvControl((void*)&_usbLineInfo,7); - return true; - } - - if (CDC_SET_CONTROL_LINE_STATE == r) - { - _usbLineInfo.lineState = setup.wValueL; - - // auto-reset into the bootloader is triggered when the port, already - // open at 1200 bps, is closed. this is the signal to start the watchdog - // with a relatively long period so it can finish housekeeping tasks - // like servicing endpoints before the sketch ends - if (1200 == _usbLineInfo.dwDTERate) { - // We check DTR state to determine if host port is open (bit 0 of lineState). - if ((_usbLineInfo.lineState & 0x01) == 0) { - *(uint16_t *)0x0800 = 0x7777; - wdt_enable(WDTO_120MS); - } else { - // Most OSs do some intermediate steps when configuring ports and DTR can - // twiggle more than once before stabilizing. - // To avoid spurious resets we set the watchdog to 250ms and eventually - // cancel if DTR goes back high. - - wdt_disable(); - wdt_reset(); - *(uint16_t *)0x0800 = 0x0; - } - } - return true; - } - } - return false; -} - - -int _serialPeek = -1; -void Serial_::begin(uint16_t baud_count) -{ -} - -void Serial_::end(void) -{ -} - -void Serial_::accept(void) -{ - ring_buffer *buffer = &cdc_rx_buffer; - int c = USB_Recv(CDC_RX); - int i = (unsigned int)(buffer->head+1) % SERIAL_BUFFER_SIZE; - - // if we should be storing the received character into the location - // just before the tail (meaning that the head would advance to the - // current location of the tail), we're about to overflow the buffer - // and so we don't write the character or advance the head. - if (i != buffer->tail) { - buffer->buffer[buffer->head] = c; - buffer->head = i; - } -} - -int Serial_::available(void) -{ - ring_buffer *buffer = &cdc_rx_buffer; - return (unsigned int)(SERIAL_BUFFER_SIZE + buffer->head - buffer->tail) % SERIAL_BUFFER_SIZE; -} - -int Serial_::peek(void) -{ - ring_buffer *buffer = &cdc_rx_buffer; - if (buffer->head == buffer->tail) { - return -1; - } else { - return buffer->buffer[buffer->tail]; - } -} - -int Serial_::read(void) -{ - ring_buffer *buffer = &cdc_rx_buffer; - // if the head isn't ahead of the tail, we don't have any characters - if (buffer->head == buffer->tail) { - return -1; - } else { - unsigned char c = buffer->buffer[buffer->tail]; - buffer->tail = (unsigned int)(buffer->tail + 1) % SERIAL_BUFFER_SIZE; - return c; - } -} - -void Serial_::flush(void) -{ - USB_Flush(CDC_TX); -} - -size_t Serial_::write(uint8_t c) -{ - /* only try to send bytes if the high-level CDC connection itself - is open (not just the pipe) - the OS should set lineState when the port - is opened and clear lineState when the port is closed. - bytes sent before the user opens the connection or after - the connection is closed are lost - just like with a UART. */ - - // TODO - ZE - check behavior on different OSes and test what happens if an - // open connection isn't broken cleanly (cable is yanked out, host dies - // or locks up, or host virtual serial port hangs) - if (_usbLineInfo.lineState > 0) { - int r = USB_Send(CDC_TX,&c,1); - if (r > 0) { - return r; - } else { - setWriteError(); - return 0; - } - } - setWriteError(); - return 0; -} - -// This operator is a convenient way for a sketch to check whether the -// port has actually been configured and opened by the host (as opposed -// to just being connected to the host). It can be used, for example, in -// setup() before printing to ensure that an application on the host is -// actually ready to receive and display the data. -// We add a short delay before returning to fix a bug observed by Federico -// where the port is configured (lineState != 0) but not quite opened. -Serial_::operator bool() { - bool result = false; - if (_usbLineInfo.lineState > 0) - result = true; - delay(10); - return result; -} - -Serial_ Serial; - -#endif -#endif /* if defined(USBCON) */ diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Client.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Client.h deleted file mode 100644 index ea134838a2..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Client.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef client_h -#define client_h -#include "Print.h" -#include "Stream.h" -#include "IPAddress.h" - -class Client : public Stream { - -public: - virtual int connect(IPAddress ip, uint16_t port) =0; - virtual int connect(const char *host, uint16_t port) =0; - virtual size_t write(uint8_t) =0; - virtual size_t write(const uint8_t *buf, size_t size) =0; - virtual int available() = 0; - virtual int read() = 0; - virtual int read(uint8_t *buf, size_t size) = 0; - virtual int peek() = 0; - virtual void flush() = 0; - virtual void stop() = 0; - virtual uint8_t connected() = 0; - virtual operator bool() = 0; -protected: - uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); }; -}; - -#endif diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/HID.cpp b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/HID.cpp deleted file mode 100644 index ac63608449..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/HID.cpp +++ /dev/null @@ -1,520 +0,0 @@ - - -/* Copyright (c) 2011, Peter Barrett -** -** Permission to use, copy, modify, and/or distribute this software for -** any purpose with or without fee is hereby granted, provided that the -** above copyright notice and this permission notice appear in all copies. -** -** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL -** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR -** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES -** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -** SOFTWARE. -*/ - -#include "Platform.h" -#include "USBAPI.h" -#include "USBDesc.h" - -#if defined(USBCON) -#ifdef HID_ENABLED - -//#define RAWHID_ENABLED - -// Singletons for mouse and keyboard - -Mouse_ Mouse; -Keyboard_ Keyboard; - -//================================================================================ -//================================================================================ - -// HID report descriptor - -#define LSB(_x) ((_x) & 0xFF) -#define MSB(_x) ((_x) >> 8) - -#define RAWHID_USAGE_PAGE 0xFFC0 -#define RAWHID_USAGE 0x0C00 -#define RAWHID_TX_SIZE 64 -#define RAWHID_RX_SIZE 64 - -extern const u8 _hidReportDescriptor[] PROGMEM; -const u8 _hidReportDescriptor[] = { - - // Mouse - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 54 - 0x09, 0x02, // USAGE (Mouse) - 0xa1, 0x01, // COLLECTION (Application) - 0x09, 0x01, // USAGE (Pointer) - 0xa1, 0x00, // COLLECTION (Physical) - 0x85, 0x01, // REPORT_ID (1) - 0x05, 0x09, // USAGE_PAGE (Button) - 0x19, 0x01, // USAGE_MINIMUM (Button 1) - 0x29, 0x03, // USAGE_MAXIMUM (Button 3) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x25, 0x01, // LOGICAL_MAXIMUM (1) - 0x95, 0x03, // REPORT_COUNT (3) - 0x75, 0x01, // REPORT_SIZE (1) - 0x81, 0x02, // INPUT (Data,Var,Abs) - 0x95, 0x01, // REPORT_COUNT (1) - 0x75, 0x05, // REPORT_SIZE (5) - 0x81, 0x03, // INPUT (Cnst,Var,Abs) - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0x09, 0x30, // USAGE (X) - 0x09, 0x31, // USAGE (Y) - 0x09, 0x38, // USAGE (Wheel) - 0x15, 0x81, // LOGICAL_MINIMUM (-127) - 0x25, 0x7f, // LOGICAL_MAXIMUM (127) - 0x75, 0x08, // REPORT_SIZE (8) - 0x95, 0x03, // REPORT_COUNT (3) - 0x81, 0x06, // INPUT (Data,Var,Rel) - 0xc0, // END_COLLECTION - 0xc0, // END_COLLECTION - - // Keyboard - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 47 - 0x09, 0x06, // USAGE (Keyboard) - 0xa1, 0x01, // COLLECTION (Application) - 0x85, 0x02, // REPORT_ID (2) - 0x05, 0x07, // USAGE_PAGE (Keyboard) - - 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl) - 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x25, 0x01, // LOGICAL_MAXIMUM (1) - 0x75, 0x01, // REPORT_SIZE (1) - - 0x95, 0x08, // REPORT_COUNT (8) - 0x81, 0x02, // INPUT (Data,Var,Abs) - 0x95, 0x01, // REPORT_COUNT (1) - 0x75, 0x08, // REPORT_SIZE (8) - 0x81, 0x03, // INPUT (Cnst,Var,Abs) - - 0x95, 0x06, // REPORT_COUNT (6) - 0x75, 0x08, // REPORT_SIZE (8) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x25, 0x65, // LOGICAL_MAXIMUM (101) - 0x05, 0x07, // USAGE_PAGE (Keyboard) - - 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated)) - 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application) - 0x81, 0x00, // INPUT (Data,Ary,Abs) - 0xc0, // END_COLLECTION - -#if RAWHID_ENABLED - // RAW HID - 0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE), // 30 - 0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE), - - 0xA1, 0x01, // Collection 0x01 - 0x85, 0x03, // REPORT_ID (3) - 0x75, 0x08, // report size = 8 bits - 0x15, 0x00, // logical minimum = 0 - 0x26, 0xFF, 0x00, // logical maximum = 255 - - 0x95, 64, // report count TX - 0x09, 0x01, // usage - 0x81, 0x02, // Input (array) - - 0x95, 64, // report count RX - 0x09, 0x02, // usage - 0x91, 0x02, // Output (array) - 0xC0 // end collection -#endif -}; - -extern const HIDDescriptor _hidInterface PROGMEM; -const HIDDescriptor _hidInterface = -{ - D_INTERFACE(HID_INTERFACE,1,3,0,0), - D_HIDREPORT(sizeof(_hidReportDescriptor)), - D_ENDPOINT(USB_ENDPOINT_IN (HID_ENDPOINT_INT),USB_ENDPOINT_TYPE_INTERRUPT,0x40,0x01) -}; - -//================================================================================ -//================================================================================ -// Driver - -u8 _hid_protocol = 1; -u8 _hid_idle = 1; - -#define WEAK __attribute__ ((weak)) - -int WEAK HID_GetInterface(u8* interfaceNum) -{ - interfaceNum[0] += 1; // uses 1 - return USB_SendControl(TRANSFER_PGM,&_hidInterface,sizeof(_hidInterface)); -} - -int WEAK HID_GetDescriptor(int i) -{ - return USB_SendControl(TRANSFER_PGM,_hidReportDescriptor,sizeof(_hidReportDescriptor)); -} - -void WEAK HID_SendReport(u8 id, const void* data, int len) -{ - USB_Send(HID_TX, &id, 1); - USB_Send(HID_TX | TRANSFER_RELEASE,data,len); -} - -bool WEAK HID_Setup(Setup& setup) -{ - u8 r = setup.bRequest; - u8 requestType = setup.bmRequestType; - if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType) - { - if (HID_GET_REPORT == r) - { - //HID_GetReport(); - return true; - } - if (HID_GET_PROTOCOL == r) - { - //Send8(_hid_protocol); // TODO - return true; - } - } - - if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType) - { - if (HID_SET_PROTOCOL == r) - { - _hid_protocol = setup.wValueL; - return true; - } - - if (HID_SET_IDLE == r) - { - _hid_idle = setup.wValueL; - return true; - } - } - return false; -} - -//================================================================================ -//================================================================================ -// Mouse - -Mouse_::Mouse_(void) : _buttons(0) -{ -} - -void Mouse_::begin(void) -{ -} - -void Mouse_::end(void) -{ -} - -void Mouse_::click(uint8_t b) -{ - _buttons = b; - move(0,0,0); - _buttons = 0; - move(0,0,0); -} - -void Mouse_::move(signed char x, signed char y, signed char wheel) -{ - u8 m[4]; - m[0] = _buttons; - m[1] = x; - m[2] = y; - m[3] = wheel; - HID_SendReport(1,m,4); -} - -void Mouse_::buttons(uint8_t b) -{ - if (b != _buttons) - { - _buttons = b; - move(0,0,0); - } -} - -void Mouse_::press(uint8_t b) -{ - buttons(_buttons | b); -} - -void Mouse_::release(uint8_t b) -{ - buttons(_buttons & ~b); -} - -bool Mouse_::isPressed(uint8_t b) -{ - if ((b & _buttons) > 0) - return true; - return false; -} - -//================================================================================ -//================================================================================ -// Keyboard - -Keyboard_::Keyboard_(void) -{ -} - -void Keyboard_::begin(void) -{ -} - -void Keyboard_::end(void) -{ -} - -void Keyboard_::sendReport(KeyReport* keys) -{ - HID_SendReport(2,keys,sizeof(KeyReport)); -} - -extern -const uint8_t _asciimap[128] PROGMEM; - -#define SHIFT 0x80 -const uint8_t _asciimap[128] = -{ - 0x00, // NUL - 0x00, // SOH - 0x00, // STX - 0x00, // ETX - 0x00, // EOT - 0x00, // ENQ - 0x00, // ACK - 0x00, // BEL - 0x2a, // BS Backspace - 0x2b, // TAB Tab - 0x28, // LF Enter - 0x00, // VT - 0x00, // FF - 0x00, // CR - 0x00, // SO - 0x00, // SI - 0x00, // DEL - 0x00, // DC1 - 0x00, // DC2 - 0x00, // DC3 - 0x00, // DC4 - 0x00, // NAK - 0x00, // SYN - 0x00, // ETB - 0x00, // CAN - 0x00, // EM - 0x00, // SUB - 0x00, // ESC - 0x00, // FS - 0x00, // GS - 0x00, // RS - 0x00, // US - - 0x2c, // ' ' - 0x1e|SHIFT, // ! - 0x34|SHIFT, // " - 0x20|SHIFT, // # - 0x21|SHIFT, // $ - 0x22|SHIFT, // % - 0x24|SHIFT, // & - 0x34, // ' - 0x26|SHIFT, // ( - 0x27|SHIFT, // ) - 0x25|SHIFT, // * - 0x2e|SHIFT, // + - 0x36, // , - 0x2d, // - - 0x37, // . - 0x38, // / - 0x27, // 0 - 0x1e, // 1 - 0x1f, // 2 - 0x20, // 3 - 0x21, // 4 - 0x22, // 5 - 0x23, // 6 - 0x24, // 7 - 0x25, // 8 - 0x26, // 9 - 0x33|SHIFT, // : - 0x33, // ; - 0x36|SHIFT, // < - 0x2e, // = - 0x37|SHIFT, // > - 0x38|SHIFT, // ? - 0x1f|SHIFT, // @ - 0x04|SHIFT, // A - 0x05|SHIFT, // B - 0x06|SHIFT, // C - 0x07|SHIFT, // D - 0x08|SHIFT, // E - 0x09|SHIFT, // F - 0x0a|SHIFT, // G - 0x0b|SHIFT, // H - 0x0c|SHIFT, // I - 0x0d|SHIFT, // J - 0x0e|SHIFT, // K - 0x0f|SHIFT, // L - 0x10|SHIFT, // M - 0x11|SHIFT, // N - 0x12|SHIFT, // O - 0x13|SHIFT, // P - 0x14|SHIFT, // Q - 0x15|SHIFT, // R - 0x16|SHIFT, // S - 0x17|SHIFT, // T - 0x18|SHIFT, // U - 0x19|SHIFT, // V - 0x1a|SHIFT, // W - 0x1b|SHIFT, // X - 0x1c|SHIFT, // Y - 0x1d|SHIFT, // Z - 0x2f, // [ - 0x31, // bslash - 0x30, // ] - 0x23|SHIFT, // ^ - 0x2d|SHIFT, // _ - 0x35, // ` - 0x04, // a - 0x05, // b - 0x06, // c - 0x07, // d - 0x08, // e - 0x09, // f - 0x0a, // g - 0x0b, // h - 0x0c, // i - 0x0d, // j - 0x0e, // k - 0x0f, // l - 0x10, // m - 0x11, // n - 0x12, // o - 0x13, // p - 0x14, // q - 0x15, // r - 0x16, // s - 0x17, // t - 0x18, // u - 0x19, // v - 0x1a, // w - 0x1b, // x - 0x1c, // y - 0x1d, // z - 0x2f|SHIFT, // - 0x31|SHIFT, // | - 0x30|SHIFT, // } - 0x35|SHIFT, // ~ - 0 // DEL -}; - -uint8_t USBPutChar(uint8_t c); - -// press() adds the specified key (printing, non-printing, or modifier) -// to the persistent key report and sends the report. Because of the way -// USB HID works, the host acts like the key remains pressed until we -// call release(), releaseAll(), or otherwise clear the report and resend. -size_t Keyboard_::press(uint8_t k) -{ - uint8_t i; - if (k >= 136) { // it's a non-printing key (not a modifier) - k = k - 136; - } else if (k >= 128) { // it's a modifier key - _keyReport.modifiers |= (1<<(k-128)); - k = 0; - } else { // it's a printing key - k = pgm_read_byte(_asciimap + k); - if (!k) { - setWriteError(); - return 0; - } - if (k & 0x80) { // it's a capital letter or other character reached with shift - _keyReport.modifiers |= 0x02; // the left shift modifier - k &= 0x7F; - } - } - - // Add k to the key report only if it's not already present - // and if there is an empty slot. - if (_keyReport.keys[0] != k && _keyReport.keys[1] != k && - _keyReport.keys[2] != k && _keyReport.keys[3] != k && - _keyReport.keys[4] != k && _keyReport.keys[5] != k) { - - for (i=0; i<6; i++) { - if (_keyReport.keys[i] == 0x00) { - _keyReport.keys[i] = k; - break; - } - } - if (i == 6) { - setWriteError(); - return 0; - } - } - sendReport(&_keyReport); - return 1; -} - -// release() takes the specified key out of the persistent key report and -// sends the report. This tells the OS the key is no longer pressed and that -// it shouldn't be repeated any more. -size_t Keyboard_::release(uint8_t k) -{ - uint8_t i; - if (k >= 136) { // it's a non-printing key (not a modifier) - k = k - 136; - } else if (k >= 128) { // it's a modifier key - _keyReport.modifiers &= ~(1<<(k-128)); - k = 0; - } else { // it's a printing key - k = pgm_read_byte(_asciimap + k); - if (!k) { - return 0; - } - if (k & 0x80) { // it's a capital letter or other character reached with shift - _keyReport.modifiers &= ~(0x02); // the left shift modifier - k &= 0x7F; - } - } - - // Test the key report to see if k is present. Clear it if it exists. - // Check all positions in case the key is present more than once (which it shouldn't be) - for (i=0; i<6; i++) { - if (0 != k && _keyReport.keys[i] == k) { - _keyReport.keys[i] = 0x00; - } - } - - sendReport(&_keyReport); - return 1; -} - -void Keyboard_::releaseAll(void) -{ - _keyReport.keys[0] = 0; - _keyReport.keys[1] = 0; - _keyReport.keys[2] = 0; - _keyReport.keys[3] = 0; - _keyReport.keys[4] = 0; - _keyReport.keys[5] = 0; - _keyReport.modifiers = 0; - sendReport(&_keyReport); -} - -size_t Keyboard_::write(uint8_t c) -{ - uint8_t p = press(c); // Keydown - uint8_t r = release(c); // Keyup - return (p); // just return the result of press() since release() almost always returns 1 -} - -#endif - -#endif /* if defined(USBCON) */ \ No newline at end of file diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/HardwareSerial.cpp b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/HardwareSerial.cpp deleted file mode 100644 index f40ddee060..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/HardwareSerial.cpp +++ /dev/null @@ -1,428 +0,0 @@ -/* - HardwareSerial.cpp - Hardware serial library for Wiring - Copyright (c) 2006 Nicholas Zambetti. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - Modified 23 November 2006 by David A. Mellis - Modified 28 September 2010 by Mark Sproul -*/ - -#include -#include -#include -#include -#include "Arduino.h" -#include "wiring_private.h" - -// this next line disables the entire HardwareSerial.cpp, -// this is so I can support Attiny series and any other chip without a uart -#if defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(UBRR2H) || defined(UBRR3H) - -#include "HardwareSerial.h" - -// Define constants and variables for buffering incoming serial data. We're -// using a ring buffer (I think), in which head is the index of the location -// to which to write the next incoming character and tail is the index of the -// location from which to read. -#if (RAMEND < 1000) - #define SERIAL_BUFFER_SIZE 16 -#else - #define SERIAL_BUFFER_SIZE 64 -#endif - -struct ring_buffer -{ - unsigned char buffer[SERIAL_BUFFER_SIZE]; - volatile unsigned int head; - volatile unsigned int tail; -}; - -#if defined(USBCON) - ring_buffer rx_buffer = { { 0 }, 0, 0}; - ring_buffer tx_buffer = { { 0 }, 0, 0}; -#endif -#if defined(UBRRH) || defined(UBRR0H) - ring_buffer rx_buffer = { { 0 }, 0, 0 }; - ring_buffer tx_buffer = { { 0 }, 0, 0 }; -#endif -#if defined(UBRR1H) - ring_buffer rx_buffer1 = { { 0 }, 0, 0 }; - ring_buffer tx_buffer1 = { { 0 }, 0, 0 }; -#endif -#if defined(UBRR2H) - ring_buffer rx_buffer2 = { { 0 }, 0, 0 }; - ring_buffer tx_buffer2 = { { 0 }, 0, 0 }; -#endif -#if defined(UBRR3H) - ring_buffer rx_buffer3 = { { 0 }, 0, 0 }; - ring_buffer tx_buffer3 = { { 0 }, 0, 0 }; -#endif - -inline void store_char(unsigned char c, ring_buffer *buffer) -{ - int i = (unsigned int)(buffer->head + 1) % SERIAL_BUFFER_SIZE; - - // if we should be storing the received character into the location - // just before the tail (meaning that the head would advance to the - // current location of the tail), we're about to overflow the buffer - // and so we don't write the character or advance the head. - if (i != buffer->tail) { - buffer->buffer[buffer->head] = c; - buffer->head = i; - } -} - -#if !defined(USART0_RX_vect) && defined(USART1_RX_vect) -// do nothing - on the 32u4 the first USART is USART1 -#else -#if !defined(USART_RX_vect) && !defined(SIG_USART0_RECV) && \ - !defined(SIG_UART0_RECV) && !defined(USART0_RX_vect) && \ - !defined(SIG_UART_RECV) - #error "Don't know what the Data Received vector is called for the first UART" -#else - void serialEvent() __attribute__((weak)); - void serialEvent() {} - #define serialEvent_implemented -#if defined(USART_RX_vect) - SIGNAL(USART_RX_vect) -#elif defined(SIG_USART0_RECV) - SIGNAL(SIG_USART0_RECV) -#elif defined(SIG_UART0_RECV) - SIGNAL(SIG_UART0_RECV) -#elif defined(USART0_RX_vect) - SIGNAL(USART0_RX_vect) -#elif defined(SIG_UART_RECV) - SIGNAL(SIG_UART_RECV) -#endif - { - #if defined(UDR0) - unsigned char c = UDR0; - #elif defined(UDR) - unsigned char c = UDR; - #else - #error UDR not defined - #endif - store_char(c, &rx_buffer); - } -#endif -#endif - -#if defined(USART1_RX_vect) - void serialEvent1() __attribute__((weak)); - void serialEvent1() {} - #define serialEvent1_implemented - SIGNAL(USART1_RX_vect) - { - unsigned char c = UDR1; - store_char(c, &rx_buffer1); - } -#elif defined(SIG_USART1_RECV) - #error SIG_USART1_RECV -#endif - -#if defined(USART2_RX_vect) && defined(UDR2) - void serialEvent2() __attribute__((weak)); - void serialEvent2() {} - #define serialEvent2_implemented - SIGNAL(USART2_RX_vect) - { - unsigned char c = UDR2; - store_char(c, &rx_buffer2); - } -#elif defined(SIG_USART2_RECV) - #error SIG_USART2_RECV -#endif - -#if defined(USART3_RX_vect) && defined(UDR3) - void serialEvent3() __attribute__((weak)); - void serialEvent3() {} - #define serialEvent3_implemented - SIGNAL(USART3_RX_vect) - { - unsigned char c = UDR3; - store_char(c, &rx_buffer3); - } -#elif defined(SIG_USART3_RECV) - #error SIG_USART3_RECV -#endif - -void serialEventRun(void) -{ -#ifdef serialEvent_implemented - if (Serial.available()) serialEvent(); -#endif -#ifdef serialEvent1_implemented - if (Serial1.available()) serialEvent1(); -#endif -#ifdef serialEvent2_implemented - if (Serial2.available()) serialEvent2(); -#endif -#ifdef serialEvent3_implemented - if (Serial3.available()) serialEvent3(); -#endif -} - - -#if !defined(USART0_UDRE_vect) && defined(USART1_UDRE_vect) -// do nothing - on the 32u4 the first USART is USART1 -#else -#if !defined(UART0_UDRE_vect) && !defined(UART_UDRE_vect) && !defined(USART0_UDRE_vect) && !defined(USART_UDRE_vect) - #error "Don't know what the Data Register Empty vector is called for the first UART" -#else -#if defined(UART0_UDRE_vect) -ISR(UART0_UDRE_vect) -#elif defined(UART_UDRE_vect) -ISR(UART_UDRE_vect) -#elif defined(USART0_UDRE_vect) -ISR(USART0_UDRE_vect) -#elif defined(USART_UDRE_vect) -ISR(USART_UDRE_vect) -#endif -{ - if (tx_buffer.head == tx_buffer.tail) { - // Buffer empty, so disable interrupts -#if defined(UCSR0B) - cbi(UCSR0B, UDRIE0); -#else - cbi(UCSRB, UDRIE); -#endif - } - else { - // There is more data in the output buffer. Send the next byte - unsigned char c = tx_buffer.buffer[tx_buffer.tail]; - tx_buffer.tail = (tx_buffer.tail + 1) % SERIAL_BUFFER_SIZE; - - #if defined(UDR0) - UDR0 = c; - #elif defined(UDR) - UDR = c; - #else - #error UDR not defined - #endif - } -} -#endif -#endif - -#ifdef USART1_UDRE_vect -ISR(USART1_UDRE_vect) -{ - if (tx_buffer1.head == tx_buffer1.tail) { - // Buffer empty, so disable interrupts - cbi(UCSR1B, UDRIE1); - } - else { - // There is more data in the output buffer. Send the next byte - unsigned char c = tx_buffer1.buffer[tx_buffer1.tail]; - tx_buffer1.tail = (tx_buffer1.tail + 1) % SERIAL_BUFFER_SIZE; - - UDR1 = c; - } -} -#endif - -#ifdef USART2_UDRE_vect -ISR(USART2_UDRE_vect) -{ - if (tx_buffer2.head == tx_buffer2.tail) { - // Buffer empty, so disable interrupts - cbi(UCSR2B, UDRIE2); - } - else { - // There is more data in the output buffer. Send the next byte - unsigned char c = tx_buffer2.buffer[tx_buffer2.tail]; - tx_buffer2.tail = (tx_buffer2.tail + 1) % SERIAL_BUFFER_SIZE; - - UDR2 = c; - } -} -#endif - -#ifdef USART3_UDRE_vect -ISR(USART3_UDRE_vect) -{ - if (tx_buffer3.head == tx_buffer3.tail) { - // Buffer empty, so disable interrupts - cbi(UCSR3B, UDRIE3); - } - else { - // There is more data in the output buffer. Send the next byte - unsigned char c = tx_buffer3.buffer[tx_buffer3.tail]; - tx_buffer3.tail = (tx_buffer3.tail + 1) % SERIAL_BUFFER_SIZE; - - UDR3 = c; - } -} -#endif - - -// Constructors //////////////////////////////////////////////////////////////// - -HardwareSerial::HardwareSerial(ring_buffer *rx_buffer, ring_buffer *tx_buffer, - volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, - volatile uint8_t *ucsra, volatile uint8_t *ucsrb, - volatile uint8_t *udr, - uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udrie, uint8_t u2x) -{ - _rx_buffer = rx_buffer; - _tx_buffer = tx_buffer; - _ubrrh = ubrrh; - _ubrrl = ubrrl; - _ucsra = ucsra; - _ucsrb = ucsrb; - _udr = udr; - _rxen = rxen; - _txen = txen; - _rxcie = rxcie; - _udrie = udrie; - _u2x = u2x; -} - -// Public Methods ////////////////////////////////////////////////////////////// - -void HardwareSerial::begin(unsigned long baud) -{ - uint16_t baud_setting; - bool use_u2x = true; - -#if F_CPU == 16000000UL - // hardcoded exception for compatibility with the bootloader shipped - // with the Duemilanove and previous boards and the firmware on the 8U2 - // on the Uno and Mega 2560. - if (baud == 57600) { - use_u2x = false; - } -#endif - -try_again: - - if (use_u2x) { - *_ucsra = 1 << _u2x; - baud_setting = (F_CPU / 4 / baud - 1) / 2; - } else { - *_ucsra = 0; - baud_setting = (F_CPU / 8 / baud - 1) / 2; - } - - if ((baud_setting > 4095) && use_u2x) - { - use_u2x = false; - goto try_again; - } - - // assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register) - *_ubrrh = baud_setting >> 8; - *_ubrrl = baud_setting; - - sbi(*_ucsrb, _rxen); - sbi(*_ucsrb, _txen); - sbi(*_ucsrb, _rxcie); - cbi(*_ucsrb, _udrie); -} - -void HardwareSerial::end() -{ - // wait for transmission of outgoing data - while (_tx_buffer->head != _tx_buffer->tail) - ; - - cbi(*_ucsrb, _rxen); - cbi(*_ucsrb, _txen); - cbi(*_ucsrb, _rxcie); - cbi(*_ucsrb, _udrie); - - // clear any received data - _rx_buffer->head = _rx_buffer->tail; -} - -int HardwareSerial::available(void) -{ - return (unsigned int)(SERIAL_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) % SERIAL_BUFFER_SIZE; -} - -int HardwareSerial::peek(void) -{ - if (_rx_buffer->head == _rx_buffer->tail) { - return -1; - } else { - return _rx_buffer->buffer[_rx_buffer->tail]; - } -} - -int HardwareSerial::read(void) -{ - // if the head isn't ahead of the tail, we don't have any characters - if (_rx_buffer->head == _rx_buffer->tail) { - return -1; - } else { - unsigned char c = _rx_buffer->buffer[_rx_buffer->tail]; - _rx_buffer->tail = (unsigned int)(_rx_buffer->tail + 1) % SERIAL_BUFFER_SIZE; - return c; - } -} - -void HardwareSerial::flush() -{ - while (_tx_buffer->head != _tx_buffer->tail) - ; -} - -size_t HardwareSerial::write(uint8_t c) -{ - int i = (_tx_buffer->head + 1) % SERIAL_BUFFER_SIZE; - - // If the output buffer is full, there's nothing for it other than to - // wait for the interrupt handler to empty it a bit - // ???: return 0 here instead? - while (i == _tx_buffer->tail) - ; - - _tx_buffer->buffer[_tx_buffer->head] = c; - _tx_buffer->head = i; - - sbi(*_ucsrb, _udrie); - - return 1; -} - -HardwareSerial::operator bool() { - return true; -} - -// Preinstantiate Objects ////////////////////////////////////////////////////// - -#if defined(UBRRH) && defined(UBRRL) - HardwareSerial Serial(&rx_buffer, &tx_buffer, &UBRRH, &UBRRL, &UCSRA, &UCSRB, &UDR, RXEN, TXEN, RXCIE, UDRIE, U2X); -#elif defined(UBRR0H) && defined(UBRR0L) - HardwareSerial Serial(&rx_buffer, &tx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRIE0, U2X0); -#elif defined(USBCON) - // do nothing - Serial object and buffers are initialized in CDC code -#else - #error no serial port defined (port 0) -#endif - -#if defined(UBRR1H) - HardwareSerial Serial1(&rx_buffer1, &tx_buffer1, &UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UDR1, RXEN1, TXEN1, RXCIE1, UDRIE1, U2X1); -#endif -#if defined(UBRR2H) - HardwareSerial Serial2(&rx_buffer2, &tx_buffer2, &UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UDR2, RXEN2, TXEN2, RXCIE2, UDRIE2, U2X2); -#endif -#if defined(UBRR3H) - HardwareSerial Serial3(&rx_buffer3, &tx_buffer3, &UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UDR3, RXEN3, TXEN3, RXCIE3, UDRIE3, U2X3); -#endif - -#endif // whole file - diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/HardwareSerial.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/HardwareSerial.h deleted file mode 100644 index bf4924c6d4..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/HardwareSerial.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - HardwareSerial.h - Hardware serial library for Wiring - Copyright (c) 2006 Nicholas Zambetti. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - Modified 28 September 2010 by Mark Sproul -*/ - -#ifndef HardwareSerial_h -#define HardwareSerial_h - -#include - -#include "Stream.h" - -struct ring_buffer; - -class HardwareSerial : public Stream -{ - private: - ring_buffer *_rx_buffer; - ring_buffer *_tx_buffer; - volatile uint8_t *_ubrrh; - volatile uint8_t *_ubrrl; - volatile uint8_t *_ucsra; - volatile uint8_t *_ucsrb; - volatile uint8_t *_udr; - uint8_t _rxen; - uint8_t _txen; - uint8_t _rxcie; - uint8_t _udrie; - uint8_t _u2x; - public: - HardwareSerial(ring_buffer *rx_buffer, ring_buffer *tx_buffer, - volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, - volatile uint8_t *ucsra, volatile uint8_t *ucsrb, - volatile uint8_t *udr, - uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udrie, uint8_t u2x); - void begin(unsigned long); - void end(); - virtual int available(void); - virtual int peek(void); - virtual int read(void); - virtual void flush(void); - virtual size_t write(uint8_t); - using Print::write; // pull in write(str) and write(buf, size) from Print - operator bool(); -}; - -#if defined(UBRRH) || defined(UBRR0H) - extern HardwareSerial Serial; -#elif defined(USBCON) - #include "USBAPI.h" -// extern HardwareSerial Serial_; -#endif -#if defined(UBRR1H) - extern HardwareSerial Serial1; -#endif -#if defined(UBRR2H) - extern HardwareSerial Serial2; -#endif -#if defined(UBRR3H) - extern HardwareSerial Serial3; -#endif - -extern void serialEventRun(void) __attribute__((weak)); - -#endif diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/IPAddress.cpp b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/IPAddress.cpp deleted file mode 100644 index fe3deb77a2..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/IPAddress.cpp +++ /dev/null @@ -1,56 +0,0 @@ - -#include -#include - -IPAddress::IPAddress() -{ - memset(_address, 0, sizeof(_address)); -} - -IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet) -{ - _address[0] = first_octet; - _address[1] = second_octet; - _address[2] = third_octet; - _address[3] = fourth_octet; -} - -IPAddress::IPAddress(uint32_t address) -{ - memcpy(_address, &address, sizeof(_address)); -} - -IPAddress::IPAddress(const uint8_t *address) -{ - memcpy(_address, address, sizeof(_address)); -} - -IPAddress& IPAddress::operator=(const uint8_t *address) -{ - memcpy(_address, address, sizeof(_address)); - return *this; -} - -IPAddress& IPAddress::operator=(uint32_t address) -{ - memcpy(_address, (const uint8_t *)&address, sizeof(_address)); - return *this; -} - -bool IPAddress::operator==(const uint8_t* addr) -{ - return memcmp(addr, _address, sizeof(_address)) == 0; -} - -size_t IPAddress::printTo(Print& p) const -{ - size_t n = 0; - for (int i =0; i < 3; i++) - { - n += p.print(_address[i], DEC); - n += p.print('.'); - } - n += p.print(_address[3], DEC); - return n; -} - diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/IPAddress.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/IPAddress.h deleted file mode 100644 index 2585aec0e4..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/IPAddress.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * - * MIT License: - * Copyright (c) 2011 Adrian McEwen - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * adrianm@mcqn.com 1/1/2011 - */ - -#ifndef IPAddress_h -#define IPAddress_h - -#include - -// A class to make it easier to handle and pass around IP addresses - -class IPAddress : public Printable { -private: - uint8_t _address[4]; // IPv4 address - // Access the raw byte array containing the address. Because this returns a pointer - // to the internal structure rather than a copy of the address this function should only - // be used when you know that the usage of the returned uint8_t* will be transient and not - // stored. - uint8_t* raw_address() { return _address; }; - -public: - // Constructors - IPAddress(); - IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet); - IPAddress(uint32_t address); - IPAddress(const uint8_t *address); - - // Overloaded cast operator to allow IPAddress objects to be used where a pointer - // to a four-byte uint8_t array is expected - operator uint32_t() { return *((uint32_t*)_address); }; - bool operator==(const IPAddress& addr) { return (*((uint32_t*)_address)) == (*((uint32_t*)addr._address)); }; - bool operator==(const uint8_t* addr); - - // Overloaded index operator to allow getting and setting individual octets of the address - uint8_t operator[](int index) const { return _address[index]; }; - uint8_t& operator[](int index) { return _address[index]; }; - - // Overloaded copy operators to allow initialisation of IPAddress objects from other types - IPAddress& operator=(const uint8_t *address); - IPAddress& operator=(uint32_t address); - - virtual size_t printTo(Print& p) const; - - friend class EthernetClass; - friend class UDP; - friend class Client; - friend class Server; - friend class DhcpClass; - friend class DNSClient; -}; - -const IPAddress INADDR_NONE(0,0,0,0); - - -#endif diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Platform.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Platform.h deleted file mode 100644 index 8b8f742771..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Platform.h +++ /dev/null @@ -1,23 +0,0 @@ - -#ifndef __PLATFORM_H__ -#define __PLATFORM_H__ - -#include -#include -#include -#include -#include - -typedef unsigned char u8; -typedef unsigned short u16; -typedef unsigned long u32; - -#include "Arduino.h" - -#if defined(USBCON) - #include "USBDesc.h" - #include "USBCore.h" - #include "USBAPI.h" -#endif /* if defined(USBCON) */ - -#endif diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Print.cpp b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Print.cpp deleted file mode 100644 index e541a6ce71..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Print.cpp +++ /dev/null @@ -1,263 +0,0 @@ -/* - Print.cpp - Base class that provides print() and println() - Copyright (c) 2008 David A. Mellis. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - Modified 23 November 2006 by David A. Mellis - */ - -#include -#include -#include -#include -#include "Arduino.h" - -#include "Print.h" - -// Public Methods ////////////////////////////////////////////////////////////// - -/* default implementation: may be overridden */ -size_t Print::write(const uint8_t *buffer, size_t size) -{ - size_t n = 0; - while (size--) { - n += write(*buffer++); - } - return n; -} - -size_t Print::print(const __FlashStringHelper *ifsh) -{ - const char PROGMEM *p = (const char PROGMEM *)ifsh; - size_t n = 0; - while (1) { - unsigned char c = pgm_read_byte(p++); - if (c == 0) break; - n += write(c); - } - return n; -} - -size_t Print::print(const String &s) -{ - size_t n = 0; - for (uint16_t i = 0; i < s.length(); i++) { - n += write(s[i]); - } - return n; -} - -size_t Print::print(const char str[]) -{ - return write(str); -} - -size_t Print::print(char c) -{ - return write(c); -} - -size_t Print::print(unsigned char b, int base) -{ - return print((unsigned long) b, base); -} - -size_t Print::print(int n, int base) -{ - return print((long) n, base); -} - -size_t Print::print(unsigned int n, int base) -{ - return print((unsigned long) n, base); -} - -size_t Print::print(long n, int base) -{ - if (base == 0) { - return write(n); - } else if (base == 10) { - if (n < 0) { - int t = print('-'); - n = -n; - return printNumber(n, 10) + t; - } - return printNumber(n, 10); - } else { - return printNumber(n, base); - } -} - -size_t Print::print(unsigned long n, int base) -{ - if (base == 0) return write(n); - else return printNumber(n, base); -} - -size_t Print::print(double n, int digits) -{ - return printFloat(n, digits); -} - -size_t Print::println(const __FlashStringHelper *ifsh) -{ - size_t n = print(ifsh); - n += println(); - return n; -} - -size_t Print::print(const Printable& x) -{ - return x.printTo(*this); -} - -size_t Print::println(void) -{ - size_t n = print('\r'); - n += print('\n'); - return n; -} - -size_t Print::println(const String &s) -{ - size_t n = print(s); - n += println(); - return n; -} - -size_t Print::println(const char c[]) -{ - size_t n = print(c); - n += println(); - return n; -} - -size_t Print::println(char c) -{ - size_t n = print(c); - n += println(); - return n; -} - -size_t Print::println(unsigned char b, int base) -{ - size_t n = print(b, base); - n += println(); - return n; -} - -size_t Print::println(int num, int base) -{ - size_t n = print(num, base); - n += println(); - return n; -} - -size_t Print::println(unsigned int num, int base) -{ - size_t n = print(num, base); - n += println(); - return n; -} - -size_t Print::println(long num, int base) -{ - size_t n = print(num, base); - n += println(); - return n; -} - -size_t Print::println(unsigned long num, int base) -{ - size_t n = print(num, base); - n += println(); - return n; -} - -size_t Print::println(double num, int digits) -{ - size_t n = print(num, digits); - n += println(); - return n; -} - -size_t Print::println(const Printable& x) -{ - size_t n = print(x); - n += println(); - return n; -} - -// Private Methods ///////////////////////////////////////////////////////////// - -size_t Print::printNumber(unsigned long n, uint8_t base) { - char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte. - char *str = &buf[sizeof(buf) - 1]; - - *str = '\0'; - - // prevent crash if called with base == 1 - if (base < 2) base = 10; - - do { - unsigned long m = n; - n /= base; - char c = m - base * n; - *--str = c < 10 ? c + '0' : c + 'A' - 10; - } while(n); - - return write(str); -} - -size_t Print::printFloat(double number, uint8_t digits) -{ - size_t n = 0; - - // Handle negative numbers - if (number < 0.0) - { - n += print('-'); - number = -number; - } - - // Round correctly so that print(1.999, 2) prints as "2.00" - double rounding = 0.5; - for (uint8_t i=0; i 0) { - n += print("."); - } - - // Extract digits from the remainder one at a time - while (digits-- > 0) - { - remainder *= 10.0; - int toPrint = int(remainder); - n += print(toPrint); - remainder -= toPrint; - } - - return n; -} diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Print.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Print.h deleted file mode 100644 index 1af6b723fc..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Print.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - Print.h - Base class that provides print() and println() - Copyright (c) 2008 David A. Mellis. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef Print_h -#define Print_h - -#include -#include // for size_t - -#include "WString.h" -#include "Printable.h" - -#define DEC 10 -#define HEX 16 -#define OCT 8 -#define BIN 2 - -class Print -{ - private: - int write_error; - size_t printNumber(unsigned long, uint8_t); - size_t printFloat(double, uint8_t); - protected: - void setWriteError(int err = 1) { write_error = err; } - public: - Print() : write_error(0) {} - - int getWriteError() { return write_error; } - void clearWriteError() { setWriteError(0); } - - virtual size_t write(uint8_t) = 0; - size_t write(const char *str) { return write((const uint8_t *)str, strlen(str)); } - virtual size_t write(const uint8_t *buffer, size_t size); - - size_t print(const __FlashStringHelper *); - size_t print(const String &); - size_t print(const char[]); - size_t print(char); - size_t print(unsigned char, int = DEC); - size_t print(int, int = DEC); - size_t print(unsigned int, int = DEC); - size_t print(long, int = DEC); - size_t print(unsigned long, int = DEC); - size_t print(double, int = 2); - size_t print(const Printable&); - - size_t println(const __FlashStringHelper *); - size_t println(const String &s); - size_t println(const char[]); - size_t println(char); - size_t println(unsigned char, int = DEC); - size_t println(int, int = DEC); - size_t println(unsigned int, int = DEC); - size_t println(long, int = DEC); - size_t println(unsigned long, int = DEC); - size_t println(double, int = 2); - size_t println(const Printable&); - size_t println(void); -}; - -#endif diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Printable.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Printable.h deleted file mode 100644 index d03c9af62c..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Printable.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - Printable.h - Interface class that allows printing of complex types - Copyright (c) 2011 Adrian McEwen. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef Printable_h -#define Printable_h - -#include - -class Print; - -/** The Printable class provides a way for new classes to allow themselves to be printed. - By deriving from Printable and implementing the printTo method, it will then be possible - for users to print out instances of this class by passing them into the usual - Print::print and Print::println methods. -*/ - -class Printable -{ - public: - virtual size_t printTo(Print& p) const = 0; -}; - -#endif - diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Server.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Server.h deleted file mode 100644 index 9674c76269..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Server.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef server_h -#define server_h - -class Server : public Print { -public: - virtual void begin() =0; -}; - -#endif diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Stream.cpp b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Stream.cpp deleted file mode 100644 index aafb7fcf97..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Stream.cpp +++ /dev/null @@ -1,270 +0,0 @@ -/* - Stream.cpp - adds parsing methods to Stream class - Copyright (c) 2008 David A. Mellis. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - Created July 2011 - parsing functions based on TextFinder library by Michael Margolis - */ - -#include "Arduino.h" -#include "Stream.h" - -#define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait -#define NO_SKIP_CHAR 1 // a magic char not found in a valid ASCII numeric field - -// private method to read stream with timeout -int Stream::timedRead() -{ - int c; - _startMillis = millis(); - do { - c = read(); - if (c >= 0) return c; - } while(millis() - _startMillis < _timeout); - return -1; // -1 indicates timeout -} - -// private method to peek stream with timeout -int Stream::timedPeek() -{ - int c; - _startMillis = millis(); - do { - c = peek(); - if (c >= 0) return c; - } while(millis() - _startMillis < _timeout); - return -1; // -1 indicates timeout -} - -// returns peek of the next digit in the stream or -1 if timeout -// discards non-numeric characters -int Stream::peekNextDigit() -{ - int c; - while (1) { - c = timedPeek(); - if (c < 0) return c; // timeout - if (c == '-') return c; - if (c >= '0' && c <= '9') return c; - read(); // discard non-numeric - } -} - -// Public Methods -////////////////////////////////////////////////////////////// - -void Stream::setTimeout(unsigned long timeout) // sets the maximum number of milliseconds to wait -{ - _timeout = timeout; -} - - // find returns true if the target string is found -bool Stream::find(char *target) -{ - return findUntil(target, NULL); -} - -// reads data from the stream until the target string of given length is found -// returns true if target string is found, false if timed out -bool Stream::find(char *target, size_t length) -{ - return findUntil(target, length, NULL, 0); -} - -// as find but search ends if the terminator string is found -bool Stream::findUntil(char *target, char *terminator) -{ - return findUntil(target, strlen(target), terminator, strlen(terminator)); -} - -// reads data from the stream until the target string of the given length is found -// search terminated if the terminator string is found -// returns true if target string is found, false if terminated or timed out -bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t termLen) -{ - size_t index = 0; // maximum target string length is 64k bytes! - size_t termIndex = 0; - int c; - - if( *target == 0) - return true; // return true if target is a null string - while( (c = timedRead()) > 0){ - - if(c != target[index]) - index = 0; // reset index if any char does not match - - if( c == target[index]){ - //////Serial.print("found "); Serial.write(c); Serial.print("index now"); Serial.println(index+1); - if(++index >= targetLen){ // return true if all chars in the target match - return true; - } - } - - if(termLen > 0 && c == terminator[termIndex]){ - if(++termIndex >= termLen) - return false; // return false if terminate string found before target string - } - else - termIndex = 0; - } - return false; -} - - -// returns the first valid (long) integer value from the current position. -// initial characters that are not digits (or the minus sign) are skipped -// function is terminated by the first character that is not a digit. -long Stream::parseInt() -{ - return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout) -} - -// as above but a given skipChar is ignored -// this allows format characters (typically commas) in values to be ignored -long Stream::parseInt(char skipChar) -{ - boolean isNegative = false; - long value = 0; - int c; - - c = peekNextDigit(); - // ignore non numeric leading characters - if(c < 0) - return 0; // zero returned if timeout - - do{ - if(c == skipChar) - ; // ignore this charactor - else if(c == '-') - isNegative = true; - else if(c >= '0' && c <= '9') // is c a digit? - value = value * 10 + c - '0'; - read(); // consume the character we got with peek - c = timedPeek(); - } - while( (c >= '0' && c <= '9') || c == skipChar ); - - if(isNegative) - value = -value; - return value; -} - - -// as parseInt but returns a floating point value -float Stream::parseFloat() -{ - return parseFloat(NO_SKIP_CHAR); -} - -// as above but the given skipChar is ignored -// this allows format characters (typically commas) in values to be ignored -float Stream::parseFloat(char skipChar){ - boolean isNegative = false; - boolean isFraction = false; - long value = 0; - char c; - float fraction = 1.0; - - c = peekNextDigit(); - // ignore non numeric leading characters - if(c < 0) - return 0; // zero returned if timeout - - do{ - if(c == skipChar) - ; // ignore - else if(c == '-') - isNegative = true; - else if (c == '.') - isFraction = true; - else if(c >= '0' && c <= '9') { // is c a digit? - value = value * 10 + c - '0'; - if(isFraction) - fraction *= 0.1; - } - read(); // consume the character we got with peek - c = timedPeek(); - } - while( (c >= '0' && c <= '9') || c == '.' || c == skipChar ); - - if(isNegative) - value = -value; - if(isFraction) - return value * fraction; - else - return value; -} - -// read characters from stream into buffer -// terminates if length characters have been read, or timeout (see setTimeout) -// returns the number of characters placed in the buffer -// the buffer is NOT null terminated. -// -size_t Stream::readBytes(char *buffer, size_t length) -{ - size_t count = 0; - while (count < length) { - int c = timedRead(); - if (c < 0) break; - *buffer++ = (char)c; - count++; - } - return count; -} - - -// as readBytes with terminator character -// terminates if length characters have been read, timeout, or if the terminator character detected -// returns the number of characters placed in the buffer (0 means no valid data found) - -size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length) -{ - if (length < 1) return 0; - size_t index = 0; - while (index < length) { - int c = timedRead(); - if (c < 0 || c == terminator) break; - *buffer++ = (char)c; - index++; - } - return index; // return number of characters, not including null terminator -} - -String Stream::readString() -{ - String ret; - int c = timedRead(); - while (c >= 0) - { - ret += (char)c; - c = timedRead(); - } - return ret; -} - -String Stream::readStringUntil(char terminator) -{ - String ret; - int c = timedRead(); - while (c >= 0 && c != terminator) - { - ret += (char)c; - c = timedRead(); - } - return ret; -} - diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Stream.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Stream.h deleted file mode 100644 index 58bbf752f3..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Stream.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - Stream.h - base class for character-based streams. - Copyright (c) 2010 David A. Mellis. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - parsing functions based on TextFinder library by Michael Margolis -*/ - -#ifndef Stream_h -#define Stream_h - -#include -#include "Print.h" - -// compatability macros for testing -/* -#define getInt() parseInt() -#define getInt(skipChar) parseInt(skipchar) -#define getFloat() parseFloat() -#define getFloat(skipChar) parseFloat(skipChar) -#define getString( pre_string, post_string, buffer, length) -readBytesBetween( pre_string, terminator, buffer, length) -*/ - -class Stream : public Print -{ - private: - unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read - unsigned long _startMillis; // used for timeout measurement - int timedRead(); // private method to read stream with timeout - int timedPeek(); // private method to peek stream with timeout - int peekNextDigit(); // returns the next numeric digit in the stream or -1 if timeout - - public: - virtual int available() = 0; - virtual int read() = 0; - virtual int peek() = 0; - virtual void flush() = 0; - - Stream() {_timeout=1000;} - -// parsing methods - - void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second - - bool find(char *target); // reads data from the stream until the target string is found - // returns true if target string is found, false if timed out (see setTimeout) - - bool find(char *target, size_t length); // reads data from the stream until the target string of given length is found - // returns true if target string is found, false if timed out - - bool findUntil(char *target, char *terminator); // as find but search ends if the terminator string is found - - bool findUntil(char *target, size_t targetLen, char *terminate, size_t termLen); // as above but search ends if the terminate string is found - - - long parseInt(); // returns the first valid (long) integer value from the current position. - // initial characters that are not digits (or the minus sign) are skipped - // integer is terminated by the first character that is not a digit. - - float parseFloat(); // float version of parseInt - - size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer - // terminates if length characters have been read or timeout (see setTimeout) - // returns the number of characters placed in the buffer (0 means no valid data found) - - size_t readBytesUntil( char terminator, char *buffer, size_t length); // as readBytes with terminator character - // terminates if length characters have been read, timeout, or if the terminator character detected - // returns the number of characters placed in the buffer (0 means no valid data found) - - // Arduino String functions to be added here - String readString(); - String readStringUntil(char terminator); - - protected: - long parseInt(char skipChar); // as above but the given skipChar is ignored - // as above but the given skipChar is ignored - // this allows format characters (typically commas) in values to be ignored - - float parseFloat(char skipChar); // as above but the given skipChar is ignored -}; - -#endif diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Tone.cpp b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Tone.cpp deleted file mode 100644 index 20eed3f483..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Tone.cpp +++ /dev/null @@ -1,601 +0,0 @@ -/* Tone.cpp - - A Tone Generator Library - - Written by Brett Hagman - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -Version Modified By Date Comments -------- ----------- -------- -------- -0001 B Hagman 09/08/02 Initial coding -0002 B Hagman 09/08/18 Multiple pins -0003 B Hagman 09/08/18 Moved initialization from constructor to begin() -0004 B Hagman 09/09/26 Fixed problems with ATmega8 -0005 B Hagman 09/11/23 Scanned prescalars for best fit on 8 bit timers - 09/11/25 Changed pin toggle method to XOR - 09/11/25 Fixed timer0 from being excluded -0006 D Mellis 09/12/29 Replaced objects with functions -0007 M Sproul 10/08/29 Changed #ifdefs from cpu to register -*************************************************/ - -#include -#include -#include "Arduino.h" -#include "pins_arduino.h" - -#if defined(__AVR_ATmega8__) || defined(__AVR_ATmega128__) -#define TCCR2A TCCR2 -#define TCCR2B TCCR2 -#define COM2A1 COM21 -#define COM2A0 COM20 -#define OCR2A OCR2 -#define TIMSK2 TIMSK -#define OCIE2A OCIE2 -#define TIMER2_COMPA_vect TIMER2_COMP_vect -#define TIMSK1 TIMSK -#endif - -// timerx_toggle_count: -// > 0 - duration specified -// = 0 - stopped -// < 0 - infinitely (until stop() method called, or new play() called) - -#if !defined(__AVR_ATmega8__) -volatile long timer0_toggle_count; -volatile uint8_t *timer0_pin_port; -volatile uint8_t timer0_pin_mask; -#endif - -volatile long timer1_toggle_count; -volatile uint8_t *timer1_pin_port; -volatile uint8_t timer1_pin_mask; -volatile long timer2_toggle_count; -volatile uint8_t *timer2_pin_port; -volatile uint8_t timer2_pin_mask; - -#if defined(TIMSK3) -volatile long timer3_toggle_count; -volatile uint8_t *timer3_pin_port; -volatile uint8_t timer3_pin_mask; -#endif - -#if defined(TIMSK4) -volatile long timer4_toggle_count; -volatile uint8_t *timer4_pin_port; -volatile uint8_t timer4_pin_mask; -#endif - -#if defined(TIMSK5) -volatile long timer5_toggle_count; -volatile uint8_t *timer5_pin_port; -volatile uint8_t timer5_pin_mask; -#endif - - -// MLS: This does not make sense, the 3 options are the same -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) - -#define AVAILABLE_TONE_PINS 1 - -const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 3, 4, 5, 1, 0 */ }; -static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255, 255, 255, 255, 255 */ }; - -#elif defined(__AVR_ATmega8__) - -#define AVAILABLE_TONE_PINS 1 - -const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 1 */ }; -static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255 */ }; - -#else - -#define AVAILABLE_TONE_PINS 1 - -// Leave timer 0 to last. -const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 1, 0 */ }; -static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255, 255 */ }; - -#endif - - - -static int8_t toneBegin(uint8_t _pin) -{ - int8_t _timer = -1; - - // if we're already using the pin, the timer should be configured. - for (int i = 0; i < AVAILABLE_TONE_PINS; i++) { - if (tone_pins[i] == _pin) { - return pgm_read_byte(tone_pin_to_timer_PGM + i); - } - } - - // search for an unused timer. - for (int i = 0; i < AVAILABLE_TONE_PINS; i++) { - if (tone_pins[i] == 255) { - tone_pins[i] = _pin; - _timer = pgm_read_byte(tone_pin_to_timer_PGM + i); - break; - } - } - - if (_timer != -1) - { - // Set timer specific stuff - // All timers in CTC mode - // 8 bit timers will require changing prescalar values, - // whereas 16 bit timers are set to either ck/1 or ck/64 prescalar - switch (_timer) - { - #if defined(TCCR0A) && defined(TCCR0B) - case 0: - // 8 bit timer - TCCR0A = 0; - TCCR0B = 0; - bitWrite(TCCR0A, WGM01, 1); - bitWrite(TCCR0B, CS00, 1); - timer0_pin_port = portOutputRegister(digitalPinToPort(_pin)); - timer0_pin_mask = digitalPinToBitMask(_pin); - break; - #endif - - #if defined(TCCR1A) && defined(TCCR1B) && defined(WGM12) - case 1: - // 16 bit timer - TCCR1A = 0; - TCCR1B = 0; - bitWrite(TCCR1B, WGM12, 1); - bitWrite(TCCR1B, CS10, 1); - timer1_pin_port = portOutputRegister(digitalPinToPort(_pin)); - timer1_pin_mask = digitalPinToBitMask(_pin); - break; - #endif - - #if defined(TCCR2A) && defined(TCCR2B) - case 2: - // 8 bit timer - TCCR2A = 0; - TCCR2B = 0; - bitWrite(TCCR2A, WGM21, 1); - bitWrite(TCCR2B, CS20, 1); - timer2_pin_port = portOutputRegister(digitalPinToPort(_pin)); - timer2_pin_mask = digitalPinToBitMask(_pin); - break; - #endif - - #if defined(TCCR3A) && defined(TCCR3B) && defined(TIMSK3) - case 3: - // 16 bit timer - TCCR3A = 0; - TCCR3B = 0; - bitWrite(TCCR3B, WGM32, 1); - bitWrite(TCCR3B, CS30, 1); - timer3_pin_port = portOutputRegister(digitalPinToPort(_pin)); - timer3_pin_mask = digitalPinToBitMask(_pin); - break; - #endif - - #if defined(TCCR4A) && defined(TCCR4B) && defined(TIMSK4) - case 4: - // 16 bit timer - TCCR4A = 0; - TCCR4B = 0; - #if defined(WGM42) - bitWrite(TCCR4B, WGM42, 1); - #elif defined(CS43) - #warning this may not be correct - // atmega32u4 - bitWrite(TCCR4B, CS43, 1); - #endif - bitWrite(TCCR4B, CS40, 1); - timer4_pin_port = portOutputRegister(digitalPinToPort(_pin)); - timer4_pin_mask = digitalPinToBitMask(_pin); - break; - #endif - - #if defined(TCCR5A) && defined(TCCR5B) && defined(TIMSK5) - case 5: - // 16 bit timer - TCCR5A = 0; - TCCR5B = 0; - bitWrite(TCCR5B, WGM52, 1); - bitWrite(TCCR5B, CS50, 1); - timer5_pin_port = portOutputRegister(digitalPinToPort(_pin)); - timer5_pin_mask = digitalPinToBitMask(_pin); - break; - #endif - } - } - - return _timer; -} - - - -// frequency (in hertz) and duration (in milliseconds). - -void tone(uint8_t _pin, unsigned int frequency, unsigned long duration) -{ - uint8_t prescalarbits = 0b001; - long toggle_count = 0; - uint32_t ocr = 0; - int8_t _timer; - - _timer = toneBegin(_pin); - - if (_timer >= 0) - { - // Set the pinMode as OUTPUT - pinMode(_pin, OUTPUT); - - // if we are using an 8 bit timer, scan through prescalars to find the best fit - if (_timer == 0 || _timer == 2) - { - ocr = F_CPU / frequency / 2 - 1; - prescalarbits = 0b001; // ck/1: same for both timers - if (ocr > 255) - { - ocr = F_CPU / frequency / 2 / 8 - 1; - prescalarbits = 0b010; // ck/8: same for both timers - - if (_timer == 2 && ocr > 255) - { - ocr = F_CPU / frequency / 2 / 32 - 1; - prescalarbits = 0b011; - } - - if (ocr > 255) - { - ocr = F_CPU / frequency / 2 / 64 - 1; - prescalarbits = _timer == 0 ? 0b011 : 0b100; - - if (_timer == 2 && ocr > 255) - { - ocr = F_CPU / frequency / 2 / 128 - 1; - prescalarbits = 0b101; - } - - if (ocr > 255) - { - ocr = F_CPU / frequency / 2 / 256 - 1; - prescalarbits = _timer == 0 ? 0b100 : 0b110; - if (ocr > 255) - { - // can't do any better than /1024 - ocr = F_CPU / frequency / 2 / 1024 - 1; - prescalarbits = _timer == 0 ? 0b101 : 0b111; - } - } - } - } - -#if defined(TCCR0B) - if (_timer == 0) - { - TCCR0B = prescalarbits; - } - else -#endif -#if defined(TCCR2B) - { - TCCR2B = prescalarbits; - } -#else - { - // dummy place holder to make the above ifdefs work - } -#endif - } - else - { - // two choices for the 16 bit timers: ck/1 or ck/64 - ocr = F_CPU / frequency / 2 - 1; - - prescalarbits = 0b001; - if (ocr > 0xffff) - { - ocr = F_CPU / frequency / 2 / 64 - 1; - prescalarbits = 0b011; - } - - if (_timer == 1) - { -#if defined(TCCR1B) - TCCR1B = (TCCR1B & 0b11111000) | prescalarbits; -#endif - } -#if defined(TCCR3B) - else if (_timer == 3) - TCCR3B = (TCCR3B & 0b11111000) | prescalarbits; -#endif -#if defined(TCCR4B) - else if (_timer == 4) - TCCR4B = (TCCR4B & 0b11111000) | prescalarbits; -#endif -#if defined(TCCR5B) - else if (_timer == 5) - TCCR5B = (TCCR5B & 0b11111000) | prescalarbits; -#endif - - } - - - // Calculate the toggle count - if (duration > 0) - { - toggle_count = 2 * frequency * duration / 1000; - } - else - { - toggle_count = -1; - } - - // Set the OCR for the given timer, - // set the toggle count, - // then turn on the interrupts - switch (_timer) - { - -#if defined(OCR0A) && defined(TIMSK0) && defined(OCIE0A) - case 0: - OCR0A = ocr; - timer0_toggle_count = toggle_count; - bitWrite(TIMSK0, OCIE0A, 1); - break; -#endif - - case 1: -#if defined(OCR1A) && defined(TIMSK1) && defined(OCIE1A) - OCR1A = ocr; - timer1_toggle_count = toggle_count; - bitWrite(TIMSK1, OCIE1A, 1); -#elif defined(OCR1A) && defined(TIMSK) && defined(OCIE1A) - // this combination is for at least the ATmega32 - OCR1A = ocr; - timer1_toggle_count = toggle_count; - bitWrite(TIMSK, OCIE1A, 1); -#endif - break; - -#if defined(OCR2A) && defined(TIMSK2) && defined(OCIE2A) - case 2: - OCR2A = ocr; - timer2_toggle_count = toggle_count; - bitWrite(TIMSK2, OCIE2A, 1); - break; -#endif - -#if defined(TIMSK3) - case 3: - OCR3A = ocr; - timer3_toggle_count = toggle_count; - bitWrite(TIMSK3, OCIE3A, 1); - break; -#endif - -#if defined(TIMSK4) - case 4: - OCR4A = ocr; - timer4_toggle_count = toggle_count; - bitWrite(TIMSK4, OCIE4A, 1); - break; -#endif - -#if defined(OCR5A) && defined(TIMSK5) && defined(OCIE5A) - case 5: - OCR5A = ocr; - timer5_toggle_count = toggle_count; - bitWrite(TIMSK5, OCIE5A, 1); - break; -#endif - - } - } -} - - -// XXX: this function only works properly for timer 2 (the only one we use -// currently). for the others, it should end the tone, but won't restore -// proper PWM functionality for the timer. -void disableTimer(uint8_t _timer) -{ - switch (_timer) - { - case 0: - #if defined(TIMSK0) - TIMSK0 = 0; - #elif defined(TIMSK) - TIMSK = 0; // atmega32 - #endif - break; - -#if defined(TIMSK1) && defined(OCIE1A) - case 1: - bitWrite(TIMSK1, OCIE1A, 0); - break; -#endif - - case 2: - #if defined(TIMSK2) && defined(OCIE2A) - bitWrite(TIMSK2, OCIE2A, 0); // disable interrupt - #endif - #if defined(TCCR2A) && defined(WGM20) - TCCR2A = (1 << WGM20); - #endif - #if defined(TCCR2B) && defined(CS22) - TCCR2B = (TCCR2B & 0b11111000) | (1 << CS22); - #endif - #if defined(OCR2A) - OCR2A = 0; - #endif - break; - -#if defined(TIMSK3) - case 3: - TIMSK3 = 0; - break; -#endif - -#if defined(TIMSK4) - case 4: - TIMSK4 = 0; - break; -#endif - -#if defined(TIMSK5) - case 5: - TIMSK5 = 0; - break; -#endif - } -} - - -void noTone(uint8_t _pin) -{ - int8_t _timer = -1; - - for (int i = 0; i < AVAILABLE_TONE_PINS; i++) { - if (tone_pins[i] == _pin) { - _timer = pgm_read_byte(tone_pin_to_timer_PGM + i); - tone_pins[i] = 255; - } - } - - disableTimer(_timer); - - digitalWrite(_pin, 0); -} - -#if 0 -#if !defined(__AVR_ATmega8__) -ISR(TIMER0_COMPA_vect) -{ - if (timer0_toggle_count != 0) - { - // toggle the pin - *timer0_pin_port ^= timer0_pin_mask; - - if (timer0_toggle_count > 0) - timer0_toggle_count--; - } - else - { - disableTimer(0); - *timer0_pin_port &= ~(timer0_pin_mask); // keep pin low after stop - } -} -#endif - - -ISR(TIMER1_COMPA_vect) -{ - if (timer1_toggle_count != 0) - { - // toggle the pin - *timer1_pin_port ^= timer1_pin_mask; - - if (timer1_toggle_count > 0) - timer1_toggle_count--; - } - else - { - disableTimer(1); - *timer1_pin_port &= ~(timer1_pin_mask); // keep pin low after stop - } -} -#endif - - -ISR(TIMER2_COMPA_vect) -{ - - if (timer2_toggle_count != 0) - { - // toggle the pin - *timer2_pin_port ^= timer2_pin_mask; - - if (timer2_toggle_count > 0) - timer2_toggle_count--; - } - else - { - // need to call noTone() so that the tone_pins[] entry is reset, so the - // timer gets initialized next time we call tone(). - // XXX: this assumes timer 2 is always the first one used. - noTone(tone_pins[0]); -// disableTimer(2); -// *timer2_pin_port &= ~(timer2_pin_mask); // keep pin low after stop - } -} - - - -//#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) -#if 0 - -ISR(TIMER3_COMPA_vect) -{ - if (timer3_toggle_count != 0) - { - // toggle the pin - *timer3_pin_port ^= timer3_pin_mask; - - if (timer3_toggle_count > 0) - timer3_toggle_count--; - } - else - { - disableTimer(3); - *timer3_pin_port &= ~(timer3_pin_mask); // keep pin low after stop - } -} - -ISR(TIMER4_COMPA_vect) -{ - if (timer4_toggle_count != 0) - { - // toggle the pin - *timer4_pin_port ^= timer4_pin_mask; - - if (timer4_toggle_count > 0) - timer4_toggle_count--; - } - else - { - disableTimer(4); - *timer4_pin_port &= ~(timer4_pin_mask); // keep pin low after stop - } -} - -ISR(TIMER5_COMPA_vect) -{ - if (timer5_toggle_count != 0) - { - // toggle the pin - *timer5_pin_port ^= timer5_pin_mask; - - if (timer5_toggle_count > 0) - timer5_toggle_count--; - } - else - { - disableTimer(5); - *timer5_pin_port &= ~(timer5_pin_mask); // keep pin low after stop - } -} - -#endif diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/USBAPI.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/USBAPI.h deleted file mode 100644 index d5abdb690d..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/USBAPI.h +++ /dev/null @@ -1,195 +0,0 @@ - - -#ifndef __USBAPI__ -#define __USBAPI__ - -#if defined(USBCON) - -//================================================================================ -//================================================================================ -// USB - -class USBDevice_ -{ -public: - USBDevice_(); - bool configured(); - - void attach(); - void detach(); // Serial port goes down too... - void poll(); -}; -extern USBDevice_ USBDevice; - -//================================================================================ -//================================================================================ -// Serial over CDC (Serial1 is the physical port) - -class Serial_ : public Stream -{ -private: - ring_buffer *_cdc_rx_buffer; -public: - void begin(uint16_t baud_count); - void end(void); - - virtual int available(void); - virtual void accept(void); - virtual int peek(void); - virtual int read(void); - virtual void flush(void); - virtual size_t write(uint8_t); - operator bool(); -}; -extern Serial_ Serial; - -//================================================================================ -//================================================================================ -// Mouse - -#define MOUSE_LEFT 1 -#define MOUSE_RIGHT 2 -#define MOUSE_MIDDLE 4 -#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE) - -class Mouse_ -{ -private: - uint8_t _buttons; - void buttons(uint8_t b); -public: - Mouse_(void); - void begin(void); - void end(void); - void click(uint8_t b = MOUSE_LEFT); - void move(signed char x, signed char y, signed char wheel = 0); - void press(uint8_t b = MOUSE_LEFT); // press LEFT by default - void release(uint8_t b = MOUSE_LEFT); // release LEFT by default - bool isPressed(uint8_t b = MOUSE_LEFT); // check LEFT by default -}; -extern Mouse_ Mouse; - -//================================================================================ -//================================================================================ -// Keyboard - -#define KEY_LEFT_CTRL 0x80 -#define KEY_LEFT_SHIFT 0x81 -#define KEY_LEFT_ALT 0x82 -#define KEY_LEFT_GUI 0x83 -#define KEY_RIGHT_CTRL 0x84 -#define KEY_RIGHT_SHIFT 0x85 -#define KEY_RIGHT_ALT 0x86 -#define KEY_RIGHT_GUI 0x87 - -#define KEY_UP_ARROW 0xDA -#define KEY_DOWN_ARROW 0xD9 -#define KEY_LEFT_ARROW 0xD8 -#define KEY_RIGHT_ARROW 0xD7 -#define KEY_BACKSPACE 0xB2 -#define KEY_TAB 0xB3 -#define KEY_RETURN 0xB0 -#define KEY_ESC 0xB1 -#define KEY_INSERT 0xD1 -#define KEY_DELETE 0xD4 -#define KEY_PAGE_UP 0xD3 -#define KEY_PAGE_DOWN 0xD6 -#define KEY_HOME 0xD2 -#define KEY_END 0xD5 -#define KEY_CAPS_LOCK 0xC1 -#define KEY_F1 0xC2 -#define KEY_F2 0xC3 -#define KEY_F3 0xC4 -#define KEY_F4 0xC5 -#define KEY_F5 0xC6 -#define KEY_F6 0xC7 -#define KEY_F7 0xC8 -#define KEY_F8 0xC9 -#define KEY_F9 0xCA -#define KEY_F10 0xCB -#define KEY_F11 0xCC -#define KEY_F12 0xCD - -// Low level key report: up to 6 keys and shift, ctrl etc at once -typedef struct -{ - uint8_t modifiers; - uint8_t reserved; - uint8_t keys[6]; -} KeyReport; - -class Keyboard_ : public Print -{ -private: - KeyReport _keyReport; - void sendReport(KeyReport* keys); -public: - Keyboard_(void); - void begin(void); - void end(void); - virtual size_t write(uint8_t k); - virtual size_t press(uint8_t k); - virtual size_t release(uint8_t k); - virtual void releaseAll(void); -}; -extern Keyboard_ Keyboard; - -//================================================================================ -//================================================================================ -// Low level API - -typedef struct -{ - uint8_t bmRequestType; - uint8_t bRequest; - uint8_t wValueL; - uint8_t wValueH; - uint16_t wIndex; - uint16_t wLength; -} Setup; - -//================================================================================ -//================================================================================ -// HID 'Driver' - -int HID_GetInterface(uint8_t* interfaceNum); -int HID_GetDescriptor(int i); -bool HID_Setup(Setup& setup); -void HID_SendReport(uint8_t id, const void* data, int len); - -//================================================================================ -//================================================================================ -// MSC 'Driver' - -int MSC_GetInterface(uint8_t* interfaceNum); -int MSC_GetDescriptor(int i); -bool MSC_Setup(Setup& setup); -bool MSC_Data(uint8_t rx,uint8_t tx); - -//================================================================================ -//================================================================================ -// CSC 'Driver' - -int CDC_GetInterface(uint8_t* interfaceNum); -int CDC_GetDescriptor(int i); -bool CDC_Setup(Setup& setup); - -//================================================================================ -//================================================================================ - -#define TRANSFER_PGM 0x80 -#define TRANSFER_RELEASE 0x40 -#define TRANSFER_ZERO 0x20 - -int USB_SendControl(uint8_t flags, const void* d, int len); -int USB_RecvControl(void* d, int len); - -uint8_t USB_Available(uint8_t ep); -int USB_Send(uint8_t ep, const void* data, int len); // blocking -int USB_Recv(uint8_t ep, void* data, int len); // non-blocking -int USB_Recv(uint8_t ep); // non-blocking -void USB_Flush(uint8_t ep); - -#endif - -#endif /* if defined(USBCON) */ \ No newline at end of file diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/USBCore.cpp b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/USBCore.cpp deleted file mode 100644 index 6766be61ab..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/USBCore.cpp +++ /dev/null @@ -1,672 +0,0 @@ - - -/* Copyright (c) 2010, Peter Barrett -** -** Permission to use, copy, modify, and/or distribute this software for -** any purpose with or without fee is hereby granted, provided that the -** above copyright notice and this permission notice appear in all copies. -** -** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL -** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR -** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES -** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -** SOFTWARE. -*/ - -#include "Platform.h" -#include "USBAPI.h" -#include "USBDesc.h" - -#if defined(USBCON) - -#define EP_TYPE_CONTROL 0x00 -#define EP_TYPE_BULK_IN 0x81 -#define EP_TYPE_BULK_OUT 0x80 -#define EP_TYPE_INTERRUPT_IN 0xC1 -#define EP_TYPE_INTERRUPT_OUT 0xC0 -#define EP_TYPE_ISOCHRONOUS_IN 0x41 -#define EP_TYPE_ISOCHRONOUS_OUT 0x40 - -/** Pulse generation counters to keep track of the number of milliseconds remaining for each pulse type */ -#define TX_RX_LED_PULSE_MS 100 -volatile u8 TxLEDPulse; /**< Milliseconds remaining for data Tx LED pulse */ -volatile u8 RxLEDPulse; /**< Milliseconds remaining for data Rx LED pulse */ - -//================================================================== -//================================================================== - -extern const u16 STRING_LANGUAGE[] PROGMEM; -extern const u16 STRING_IPRODUCT[] PROGMEM; -extern const u16 STRING_IMANUFACTURER[] PROGMEM; -extern const DeviceDescriptor USB_DeviceDescriptor PROGMEM; -extern const DeviceDescriptor USB_DeviceDescriptorA PROGMEM; - -const u16 STRING_LANGUAGE[2] = { - (3<<8) | (2+2), - 0x0409 // English -}; - -const u16 STRING_IPRODUCT[17] = { - (3<<8) | (2+2*16), -#if USB_PID == 0x8036 - 'A','r','d','u','i','n','o',' ','L','e','o','n','a','r','d','o' -#else - 'U','S','B',' ','I','O',' ','B','o','a','r','d',' ',' ',' ',' ' -#endif -}; - -const u16 STRING_IMANUFACTURER[12] = { - (3<<8) | (2+2*11), -#if USB_VID == 0x2341 - 'A','r','d','u','i','n','o',' ','L','L','C' -#else - 'U','n','k','n','o','w','n',' ',' ',' ',' ' -#endif -}; - -#ifdef CDC_ENABLED -#define DEVICE_CLASS 0x02 -#else -#define DEVICE_CLASS 0x00 -#endif - -// DEVICE DESCRIPTOR -const DeviceDescriptor USB_DeviceDescriptor = - D_DEVICE(0x00,0x00,0x00,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1); - -const DeviceDescriptor USB_DeviceDescriptorA = - D_DEVICE(DEVICE_CLASS,0x00,0x00,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1); - -//================================================================== -//================================================================== - -volatile u8 _usbConfiguration = 0; - -static inline void WaitIN(void) -{ - while (!(UEINTX & (1< len) - n = len; - len -= n; - { - LockEP lock(ep); - if (ep & TRANSFER_ZERO) - { - while (n--) - Send8(0); - } - else if (ep & TRANSFER_PGM) - { - while (n--) - Send8(pgm_read_byte(data++)); - } - else - { - while (n--) - Send8(*data++); - } - if (!ReadWriteAllowed() || ((len == 0) && (ep & TRANSFER_RELEASE))) // Release full buffer - ReleaseTX(); - } - } - TXLED1; // light the TX LED - TxLEDPulse = TX_RX_LED_PULSE_MS; - return r; -} - -extern const u8 _initEndpoints[] PROGMEM; -const u8 _initEndpoints[] = -{ - 0, - -#ifdef CDC_ENABLED - EP_TYPE_INTERRUPT_IN, // CDC_ENDPOINT_ACM - EP_TYPE_BULK_OUT, // CDC_ENDPOINT_OUT - EP_TYPE_BULK_IN, // CDC_ENDPOINT_IN -#endif - -#ifdef HID_ENABLED - EP_TYPE_INTERRUPT_IN // HID_ENDPOINT_INT -#endif -}; - -#define EP_SINGLE_64 0x32 // EP0 -#define EP_DOUBLE_64 0x36 // Other endpoints - -static -void InitEP(u8 index, u8 type, u8 size) -{ - UENUM = index; - UECONX = 1; - UECFG0X = type; - UECFG1X = size; -} - -static -void InitEndpoints() -{ - for (u8 i = 1; i < sizeof(_initEndpoints); i++) - { - UENUM = i; - UECONX = 1; - UECFG0X = pgm_read_byte(_initEndpoints+i); - UECFG1X = EP_DOUBLE_64; - } - UERST = 0x7E; // And reset them - UERST = 0; -} - -// Handle CLASS_INTERFACE requests -static -bool ClassInterfaceRequest(Setup& setup) -{ - u8 i = setup.wIndex; - -#ifdef CDC_ENABLED - if (CDC_ACM_INTERFACE == i) - return CDC_Setup(setup); -#endif - -#ifdef HID_ENABLED - if (HID_INTERFACE == i) - return HID_Setup(setup); -#endif - return false; -} - -int _cmark; -int _cend; -void InitControl(int end) -{ - SetEP(0); - _cmark = 0; - _cend = end; -} - -static -bool SendControl(u8 d) -{ - if (_cmark < _cend) - { - if (!WaitForINOrOUT()) - return false; - Send8(d); - if (!((_cmark + 1) & 0x3F)) - ClearIN(); // Fifo is full, release this packet - } - _cmark++; - return true; -}; - -// Clipped by _cmark/_cend -int USB_SendControl(u8 flags, const void* d, int len) -{ - int sent = len; - const u8* data = (const u8*)d; - bool pgm = flags & TRANSFER_PGM; - while (len--) - { - u8 c = pgm ? pgm_read_byte(data++) : *data++; - if (!SendControl(c)) - return -1; - } - return sent; -} - -// Does not timeout or cross fifo boundaries -// Will only work for transfers <= 64 bytes -// TODO -int USB_RecvControl(void* d, int len) -{ - WaitOUT(); - Recv((u8*)d,len); - ClearOUT(); - return len; -} - -int SendInterfaces() -{ - int total = 0; - u8 interfaces = 0; - -#ifdef CDC_ENABLED - total = CDC_GetInterface(&interfaces); -#endif - -#ifdef HID_ENABLED - total += HID_GetInterface(&interfaces); -#endif - - return interfaces; -} - -// Construct a dynamic configuration descriptor -// This really needs dynamic endpoint allocation etc -// TODO -static -bool SendConfiguration(int maxlen) -{ - // Count and measure interfaces - InitControl(0); - int interfaces = SendInterfaces(); - ConfigDescriptor config = D_CONFIG(_cmark + sizeof(ConfigDescriptor),interfaces); - - // Now send them - InitControl(maxlen); - USB_SendControl(0,&config,sizeof(ConfigDescriptor)); - SendInterfaces(); - return true; -} - -u8 _cdcComposite = 0; - -static -bool SendDescriptor(Setup& setup) -{ - u8 t = setup.wValueH; - if (USB_CONFIGURATION_DESCRIPTOR_TYPE == t) - return SendConfiguration(setup.wLength); - - InitControl(setup.wLength); -#ifdef HID_ENABLED - if (HID_REPORT_DESCRIPTOR_TYPE == t) - return HID_GetDescriptor(t); -#endif - - u8 desc_length = 0; - const u8* desc_addr = 0; - if (USB_DEVICE_DESCRIPTOR_TYPE == t) - { - if (setup.wLength == 8) - _cdcComposite = 1; - desc_addr = _cdcComposite ? (const u8*)&USB_DeviceDescriptorA : (const u8*)&USB_DeviceDescriptor; - } - else if (USB_STRING_DESCRIPTOR_TYPE == t) - { - if (setup.wValueL == 0) - desc_addr = (const u8*)&STRING_LANGUAGE; - else if (setup.wValueL == IPRODUCT) - desc_addr = (const u8*)&STRING_IPRODUCT; - else if (setup.wValueL == IMANUFACTURER) - desc_addr = (const u8*)&STRING_IMANUFACTURER; - else - return false; - } - - if (desc_addr == 0) - return false; - if (desc_length == 0) - desc_length = pgm_read_byte(desc_addr); - - USB_SendControl(TRANSFER_PGM,desc_addr,desc_length); - return true; -} - -// Endpoint 0 interrupt -ISR(USB_COM_vect) -{ - SetEP(0); - if (!ReceivedSetupInt()) - return; - - Setup setup; - Recv((u8*)&setup,8); - ClearSetupInt(); - - u8 requestType = setup.bmRequestType; - if (requestType & REQUEST_DEVICETOHOST) - WaitIN(); - else - ClearIN(); - - bool ok = true; - if (REQUEST_STANDARD == (requestType & REQUEST_TYPE)) - { - // Standard Requests - u8 r = setup.bRequest; - if (GET_STATUS == r) - { - Send8(0); // TODO - Send8(0); - } - else if (CLEAR_FEATURE == r) - { - } - else if (SET_FEATURE == r) - { - } - else if (SET_ADDRESS == r) - { - WaitIN(); - UDADDR = setup.wValueL | (1<> 8) & 0xFF) - -#define CDC_V1_10 0x0110 -#define CDC_COMMUNICATION_INTERFACE_CLASS 0x02 - -#define CDC_CALL_MANAGEMENT 0x01 -#define CDC_ABSTRACT_CONTROL_MODEL 0x02 -#define CDC_HEADER 0x00 -#define CDC_ABSTRACT_CONTROL_MANAGEMENT 0x02 -#define CDC_UNION 0x06 -#define CDC_CS_INTERFACE 0x24 -#define CDC_CS_ENDPOINT 0x25 -#define CDC_DATA_INTERFACE_CLASS 0x0A - -#define MSC_SUBCLASS_SCSI 0x06 -#define MSC_PROTOCOL_BULK_ONLY 0x50 - -#define HID_HID_DESCRIPTOR_TYPE 0x21 -#define HID_REPORT_DESCRIPTOR_TYPE 0x22 -#define HID_PHYSICAL_DESCRIPTOR_TYPE 0x23 - - -// Device -typedef struct { - u8 len; // 18 - u8 dtype; // 1 USB_DEVICE_DESCRIPTOR_TYPE - u16 usbVersion; // 0x200 - u8 deviceClass; - u8 deviceSubClass; - u8 deviceProtocol; - u8 packetSize0; // Packet 0 - u16 idVendor; - u16 idProduct; - u16 deviceVersion; // 0x100 - u8 iManufacturer; - u8 iProduct; - u8 iSerialNumber; - u8 bNumConfigurations; -} DeviceDescriptor; - -// Config -typedef struct { - u8 len; // 9 - u8 dtype; // 2 - u16 clen; // total length - u8 numInterfaces; - u8 config; - u8 iconfig; - u8 attributes; - u8 maxPower; -} ConfigDescriptor; - -// String - -// Interface -typedef struct -{ - u8 len; // 9 - u8 dtype; // 4 - u8 number; - u8 alternate; - u8 numEndpoints; - u8 interfaceClass; - u8 interfaceSubClass; - u8 protocol; - u8 iInterface; -} InterfaceDescriptor; - -// Endpoint -typedef struct -{ - u8 len; // 7 - u8 dtype; // 5 - u8 addr; - u8 attr; - u16 packetSize; - u8 interval; -} EndpointDescriptor; - -// Interface Association Descriptor -// Used to bind 2 interfaces together in CDC compostite device -typedef struct -{ - u8 len; // 8 - u8 dtype; // 11 - u8 firstInterface; - u8 interfaceCount; - u8 functionClass; - u8 funtionSubClass; - u8 functionProtocol; - u8 iInterface; -} IADDescriptor; - -// CDC CS interface descriptor -typedef struct -{ - u8 len; // 5 - u8 dtype; // 0x24 - u8 subtype; - u8 d0; - u8 d1; -} CDCCSInterfaceDescriptor; - -typedef struct -{ - u8 len; // 4 - u8 dtype; // 0x24 - u8 subtype; - u8 d0; -} CDCCSInterfaceDescriptor4; - -typedef struct -{ - u8 len; - u8 dtype; // 0x24 - u8 subtype; // 1 - u8 bmCapabilities; - u8 bDataInterface; -} CMFunctionalDescriptor; - -typedef struct -{ - u8 len; - u8 dtype; // 0x24 - u8 subtype; // 1 - u8 bmCapabilities; -} ACMFunctionalDescriptor; - -typedef struct -{ - // IAD - IADDescriptor iad; // Only needed on compound device - - // Control - InterfaceDescriptor cif; // - CDCCSInterfaceDescriptor header; - CMFunctionalDescriptor callManagement; // Call Management - ACMFunctionalDescriptor controlManagement; // ACM - CDCCSInterfaceDescriptor functionalDescriptor; // CDC_UNION - EndpointDescriptor cifin; - - // Data - InterfaceDescriptor dif; - EndpointDescriptor in; - EndpointDescriptor out; -} CDCDescriptor; - -typedef struct -{ - InterfaceDescriptor msc; - EndpointDescriptor in; - EndpointDescriptor out; -} MSCDescriptor; - -typedef struct -{ - u8 len; // 9 - u8 dtype; // 0x21 - u8 addr; - u8 versionL; // 0x101 - u8 versionH; // 0x101 - u8 country; - u8 desctype; // 0x22 report - u8 descLenL; - u8 descLenH; -} HIDDescDescriptor; - -typedef struct -{ - InterfaceDescriptor hid; - HIDDescDescriptor desc; - EndpointDescriptor in; -} HIDDescriptor; - - -#define D_DEVICE(_class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs) \ - { 18, 1, 0x200, _class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs } - -#define D_CONFIG(_totalLength,_interfaces) \ - { 9, 2, _totalLength,_interfaces, 1, 0, USB_CONFIG_BUS_POWERED, USB_CONFIG_POWER_MA(500) } - -#define D_INTERFACE(_n,_numEndpoints,_class,_subClass,_protocol) \ - { 9, 4, _n, 0, _numEndpoints, _class,_subClass, _protocol, 0 } - -#define D_ENDPOINT(_addr,_attr,_packetSize, _interval) \ - { 7, 5, _addr,_attr,_packetSize, _interval } - -#define D_IAD(_firstInterface, _count, _class, _subClass, _protocol) \ - { 8, 11, _firstInterface, _count, _class, _subClass, _protocol, 0 } - -#define D_HIDREPORT(_descriptorLength) \ - { 9, 0x21, 0x1, 0x1, 0, 1, 0x22, _descriptorLength, 0 } - -#define D_CDCCS(_subtype,_d0,_d1) { 5, 0x24, _subtype, _d0, _d1 } -#define D_CDCCS4(_subtype,_d0) { 4, 0x24, _subtype, _d0 } - - -#endif \ No newline at end of file diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/USBDesc.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/USBDesc.h deleted file mode 100644 index 900713e0f9..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/USBDesc.h +++ /dev/null @@ -1,63 +0,0 @@ - - -/* Copyright (c) 2011, Peter Barrett -** -** Permission to use, copy, modify, and/or distribute this software for -** any purpose with or without fee is hereby granted, provided that the -** above copyright notice and this permission notice appear in all copies. -** -** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL -** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR -** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES -** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -** SOFTWARE. -*/ - -#define CDC_ENABLED -#define HID_ENABLED - - -#ifdef CDC_ENABLED -#define CDC_INTERFACE_COUNT 2 -#define CDC_ENPOINT_COUNT 3 -#else -#define CDC_INTERFACE_COUNT 0 -#define CDC_ENPOINT_COUNT 0 -#endif - -#ifdef HID_ENABLED -#define HID_INTERFACE_COUNT 1 -#define HID_ENPOINT_COUNT 1 -#else -#define HID_INTERFACE_COUNT 0 -#define HID_ENPOINT_COUNT 0 -#endif - -#define CDC_ACM_INTERFACE 0 // CDC ACM -#define CDC_DATA_INTERFACE 1 // CDC Data -#define CDC_FIRST_ENDPOINT 1 -#define CDC_ENDPOINT_ACM (CDC_FIRST_ENDPOINT) // CDC First -#define CDC_ENDPOINT_OUT (CDC_FIRST_ENDPOINT+1) -#define CDC_ENDPOINT_IN (CDC_FIRST_ENDPOINT+2) - -#define HID_INTERFACE (CDC_ACM_INTERFACE + CDC_INTERFACE_COUNT) // HID Interface -#define HID_FIRST_ENDPOINT (CDC_FIRST_ENDPOINT + CDC_ENPOINT_COUNT) -#define HID_ENDPOINT_INT (HID_FIRST_ENDPOINT) - -#define INTERFACE_COUNT (MSC_INTERFACE + MSC_INTERFACE_COUNT) - -#ifdef CDC_ENABLED -#define CDC_RX CDC_ENDPOINT_OUT -#define CDC_TX CDC_ENDPOINT_IN -#endif - -#ifdef HID_ENABLED -#define HID_TX HID_ENDPOINT_INT -#endif - -#define IMANUFACTURER 1 -#define IPRODUCT 2 - diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Udp.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Udp.h deleted file mode 100644 index dc5644b9df..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Udp.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Udp.cpp: Library to send/receive UDP packets. - * - * NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these) - * 1) UDP does not guarantee the order in which assembled UDP packets are received. This - * might not happen often in practice, but in larger network topologies, a UDP - * packet can be received out of sequence. - * 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being - * aware of it. Again, this may not be a concern in practice on small local networks. - * For more information, see http://www.cafeaulait.org/course/week12/35.html - * - * MIT License: - * Copyright (c) 2008 Bjoern Hartmann - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * bjoern@cs.stanford.edu 12/30/2008 - */ - -#ifndef udp_h -#define udp_h - -#include -#include - -class UDP : public Stream { - -public: - virtual uint8_t begin(uint16_t) =0; // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use - virtual void stop() =0; // Finish with the UDP socket - - // Sending UDP packets - - // Start building up a packet to send to the remote host specific in ip and port - // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port - virtual int beginPacket(IPAddress ip, uint16_t port) =0; - // Start building up a packet to send to the remote host specific in host and port - // Returns 1 if successful, 0 if there was a problem resolving the hostname or port - virtual int beginPacket(const char *host, uint16_t port) =0; - // Finish off this packet and send it - // Returns 1 if the packet was sent successfully, 0 if there was an error - virtual int endPacket() =0; - // Write a single byte into the packet - virtual size_t write(uint8_t) =0; - // Write size bytes from buffer into the packet - virtual size_t write(const uint8_t *buffer, size_t size) =0; - - // Start processing the next available incoming packet - // Returns the size of the packet in bytes, or 0 if no packets are available - virtual int parsePacket() =0; - // Number of bytes remaining in the current packet - virtual int available() =0; - // Read a single byte from the current packet - virtual int read() =0; - // Read up to len bytes from the current packet and place them into buffer - // Returns the number of bytes read, or 0 if none are available - virtual int read(unsigned char* buffer, size_t len) =0; - // Read up to len characters from the current packet and place them into buffer - // Returns the number of characters read, or 0 if none are available - virtual int read(char* buffer, size_t len) =0; - // Return the next byte from the current packet without moving on to the next byte - virtual int peek() =0; - virtual void flush() =0; // Finish reading the current packet - - // Return the IP address of the host who sent the current incoming packet - virtual IPAddress remoteIP() =0; - // Return the port of the host who sent the current incoming packet - virtual uint16_t remotePort() =0; -protected: - uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); }; -}; - -#endif diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WCharacter.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WCharacter.h deleted file mode 100644 index 79733b50a5..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WCharacter.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - WCharacter.h - Character utility functions for Wiring & Arduino - Copyright (c) 2010 Hernando Barragan. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef Character_h -#define Character_h - -#include - -// WCharacter.h prototypes -inline boolean isAlphaNumeric(int c) __attribute__((always_inline)); -inline boolean isAlpha(int c) __attribute__((always_inline)); -inline boolean isAscii(int c) __attribute__((always_inline)); -inline boolean isWhitespace(int c) __attribute__((always_inline)); -inline boolean isControl(int c) __attribute__((always_inline)); -inline boolean isDigit(int c) __attribute__((always_inline)); -inline boolean isGraph(int c) __attribute__((always_inline)); -inline boolean isLowerCase(int c) __attribute__((always_inline)); -inline boolean isPrintable(int c) __attribute__((always_inline)); -inline boolean isPunct(int c) __attribute__((always_inline)); -inline boolean isSpace(int c) __attribute__((always_inline)); -inline boolean isUpperCase(int c) __attribute__((always_inline)); -inline boolean isHexadecimalDigit(int c) __attribute__((always_inline)); -inline int toAscii(int c) __attribute__((always_inline)); -inline int toLowerCase(int c) __attribute__((always_inline)); -inline int toUpperCase(int c)__attribute__((always_inline)); - - -// Checks for an alphanumeric character. -// It is equivalent to (isalpha(c) || isdigit(c)). -inline boolean isAlphaNumeric(int c) -{ - return ( isalnum(c) == 0 ? false : true); -} - - -// Checks for an alphabetic character. -// It is equivalent to (isupper(c) || islower(c)). -inline boolean isAlpha(int c) -{ - return ( isalpha(c) == 0 ? false : true); -} - - -// Checks whether c is a 7-bit unsigned char value -// that fits into the ASCII character set. -inline boolean isAscii(int c) -{ - return ( isascii (c) == 0 ? false : true); -} - - -// Checks for a blank character, that is, a space or a tab. -inline boolean isWhitespace(int c) -{ - return ( isblank (c) == 0 ? false : true); -} - - -// Checks for a control character. -inline boolean isControl(int c) -{ - return ( iscntrl (c) == 0 ? false : true); -} - - -// Checks for a digit (0 through 9). -inline boolean isDigit(int c) -{ - return ( isdigit (c) == 0 ? false : true); -} - - -// Checks for any printable character except space. -inline boolean isGraph(int c) -{ - return ( isgraph (c) == 0 ? false : true); -} - - -// Checks for a lower-case character. -inline boolean isLowerCase(int c) -{ - return (islower (c) == 0 ? false : true); -} - - -// Checks for any printable character including space. -inline boolean isPrintable(int c) -{ - return ( isprint (c) == 0 ? false : true); -} - - -// Checks for any printable character which is not a space -// or an alphanumeric character. -inline boolean isPunct(int c) -{ - return ( ispunct (c) == 0 ? false : true); -} - - -// Checks for white-space characters. For the avr-libc library, -// these are: space, formfeed ('\f'), newline ('\n'), carriage -// return ('\r'), horizontal tab ('\t'), and vertical tab ('\v'). -inline boolean isSpace(int c) -{ - return ( isspace (c) == 0 ? false : true); -} - - -// Checks for an uppercase letter. -inline boolean isUpperCase(int c) -{ - return ( isupper (c) == 0 ? false : true); -} - - -// Checks for a hexadecimal digits, i.e. one of 0 1 2 3 4 5 6 7 -// 8 9 a b c d e f A B C D E F. -inline boolean isHexadecimalDigit(int c) -{ - return ( isxdigit (c) == 0 ? false : true); -} - - -// Converts c to a 7-bit unsigned char value that fits into the -// ASCII character set, by clearing the high-order bits. -inline int toAscii(int c) -{ - return toascii (c); -} - - -// Warning: -// Many people will be unhappy if you use this function. -// This function will convert accented letters into random -// characters. - -// Converts the letter c to lower case, if possible. -inline int toLowerCase(int c) -{ - return tolower (c); -} - - -// Converts the letter c to upper case, if possible. -inline int toUpperCase(int c) -{ - return toupper (c); -} - -#endif \ No newline at end of file diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WInterrupts.c b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WInterrupts.c deleted file mode 100644 index 8f3ec847f1..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WInterrupts.c +++ /dev/null @@ -1,298 +0,0 @@ -/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Wiring project - http://wiring.uniandes.edu.co - - Copyright (c) 2004-05 Hernando Barragan - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - - Modified 24 November 2006 by David A. Mellis - Modified 1 August 2010 by Mark Sproul -*/ - -#include -#include -#include -#include -#include - -#include "wiring_private.h" - -static volatile voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS]; -// volatile static voidFuncPtr twiIntFunc; - -void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) { - if(interruptNum < EXTERNAL_NUM_INTERRUPTS) { - intFunc[interruptNum] = userFunc; - - // Configure the interrupt mode (trigger on low input, any change, rising - // edge, or falling edge). The mode constants were chosen to correspond - // to the configuration bits in the hardware register, so we simply shift - // the mode into place. - - // Enable the interrupt. - - switch (interruptNum) { -#if defined(__AVR_ATmega32U4__) - // I hate doing this, but the register assignment differs between the 1280/2560 - // and the 32U4. Since avrlib defines registers PCMSK1 and PCMSK2 that aren't - // even present on the 32U4 this is the only way to distinguish between them. - case 0: - EICRA = (EICRA & ~((1<= howbig) { - return howsmall; - } - long diff = howbig - howsmall; - return random(diff) + howsmall; -} - -long map(long x, long in_min, long in_max, long out_min, long out_max) -{ - return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; -} - -unsigned int makeWord(unsigned int w) { return w; } -unsigned int makeWord(unsigned char h, unsigned char l) { return (h << 8) | l; } \ No newline at end of file diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WString.cpp b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WString.cpp deleted file mode 100644 index c6839fc0d9..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WString.cpp +++ /dev/null @@ -1,645 +0,0 @@ -/* - WString.cpp - String library for Wiring & Arduino - ...mostly rewritten by Paul Stoffregen... - Copyright (c) 2009-10 Hernando Barragan. All rights reserved. - Copyright 2011, Paul Stoffregen, paul@pjrc.com - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#include "WString.h" - - -/*********************************************/ -/* Constructors */ -/*********************************************/ - -String::String(const char *cstr) -{ - init(); - if (cstr) copy(cstr, strlen(cstr)); -} - -String::String(const String &value) -{ - init(); - *this = value; -} - -#ifdef __GXX_EXPERIMENTAL_CXX0X__ -String::String(String &&rval) -{ - init(); - move(rval); -} -String::String(StringSumHelper &&rval) -{ - init(); - move(rval); -} -#endif - -String::String(char c) -{ - init(); - char buf[2]; - buf[0] = c; - buf[1] = 0; - *this = buf; -} - -String::String(unsigned char value, unsigned char base) -{ - init(); - char buf[9]; - utoa(value, buf, base); - *this = buf; -} - -String::String(int value, unsigned char base) -{ - init(); - char buf[18]; - itoa(value, buf, base); - *this = buf; -} - -String::String(unsigned int value, unsigned char base) -{ - init(); - char buf[17]; - utoa(value, buf, base); - *this = buf; -} - -String::String(long value, unsigned char base) -{ - init(); - char buf[34]; - ltoa(value, buf, base); - *this = buf; -} - -String::String(unsigned long value, unsigned char base) -{ - init(); - char buf[33]; - ultoa(value, buf, base); - *this = buf; -} - -String::~String() -{ - free(buffer); -} - -/*********************************************/ -/* Memory Management */ -/*********************************************/ - -inline void String::init(void) -{ - buffer = NULL; - capacity = 0; - len = 0; - flags = 0; -} - -void String::invalidate(void) -{ - if (buffer) free(buffer); - buffer = NULL; - capacity = len = 0; -} - -unsigned char String::reserve(unsigned int size) -{ - if (buffer && capacity >= size) return 1; - if (changeBuffer(size)) { - if (len == 0) buffer[0] = 0; - return 1; - } - return 0; -} - -unsigned char String::changeBuffer(unsigned int maxStrLen) -{ - char *newbuffer = (char *)realloc(buffer, maxStrLen + 1); - if (newbuffer) { - buffer = newbuffer; - capacity = maxStrLen; - return 1; - } - return 0; -} - -/*********************************************/ -/* Copy and Move */ -/*********************************************/ - -String & String::copy(const char *cstr, unsigned int length) -{ - if (!reserve(length)) { - invalidate(); - return *this; - } - len = length; - strcpy(buffer, cstr); - return *this; -} - -#ifdef __GXX_EXPERIMENTAL_CXX0X__ -void String::move(String &rhs) -{ - if (buffer) { - if (capacity >= rhs.len) { - strcpy(buffer, rhs.buffer); - len = rhs.len; - rhs.len = 0; - return; - } else { - free(buffer); - } - } - buffer = rhs.buffer; - capacity = rhs.capacity; - len = rhs.len; - rhs.buffer = NULL; - rhs.capacity = 0; - rhs.len = 0; -} -#endif - -String & String::operator = (const String &rhs) -{ - if (this == &rhs) return *this; - - if (rhs.buffer) copy(rhs.buffer, rhs.len); - else invalidate(); - - return *this; -} - -#ifdef __GXX_EXPERIMENTAL_CXX0X__ -String & String::operator = (String &&rval) -{ - if (this != &rval) move(rval); - return *this; -} - -String & String::operator = (StringSumHelper &&rval) -{ - if (this != &rval) move(rval); - return *this; -} -#endif - -String & String::operator = (const char *cstr) -{ - if (cstr) copy(cstr, strlen(cstr)); - else invalidate(); - - return *this; -} - -/*********************************************/ -/* concat */ -/*********************************************/ - -unsigned char String::concat(const String &s) -{ - return concat(s.buffer, s.len); -} - -unsigned char String::concat(const char *cstr, unsigned int length) -{ - unsigned int newlen = len + length; - if (!cstr) return 0; - if (length == 0) return 1; - if (!reserve(newlen)) return 0; - strcpy(buffer + len, cstr); - len = newlen; - return 1; -} - -unsigned char String::concat(const char *cstr) -{ - if (!cstr) return 0; - return concat(cstr, strlen(cstr)); -} - -unsigned char String::concat(char c) -{ - char buf[2]; - buf[0] = c; - buf[1] = 0; - return concat(buf, 1); -} - -unsigned char String::concat(unsigned char num) -{ - char buf[4]; - itoa(num, buf, 10); - return concat(buf, strlen(buf)); -} - -unsigned char String::concat(int num) -{ - char buf[7]; - itoa(num, buf, 10); - return concat(buf, strlen(buf)); -} - -unsigned char String::concat(unsigned int num) -{ - char buf[6]; - utoa(num, buf, 10); - return concat(buf, strlen(buf)); -} - -unsigned char String::concat(long num) -{ - char buf[12]; - ltoa(num, buf, 10); - return concat(buf, strlen(buf)); -} - -unsigned char String::concat(unsigned long num) -{ - char buf[11]; - ultoa(num, buf, 10); - return concat(buf, strlen(buf)); -} - -/*********************************************/ -/* Concatenate */ -/*********************************************/ - -StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(rhs.buffer, rhs.len)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr) -{ - StringSumHelper &a = const_cast(lhs); - if (!cstr || !a.concat(cstr, strlen(cstr))) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, char c) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(c)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, int num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, long num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -/*********************************************/ -/* Comparison */ -/*********************************************/ - -int String::compareTo(const String &s) const -{ - if (!buffer || !s.buffer) { - if (s.buffer && s.len > 0) return 0 - *(unsigned char *)s.buffer; - if (buffer && len > 0) return *(unsigned char *)buffer; - return 0; - } - return strcmp(buffer, s.buffer); -} - -unsigned char String::equals(const String &s2) const -{ - return (len == s2.len && compareTo(s2) == 0); -} - -unsigned char String::equals(const char *cstr) const -{ - if (len == 0) return (cstr == NULL || *cstr == 0); - if (cstr == NULL) return buffer[0] == 0; - return strcmp(buffer, cstr) == 0; -} - -unsigned char String::operator<(const String &rhs) const -{ - return compareTo(rhs) < 0; -} - -unsigned char String::operator>(const String &rhs) const -{ - return compareTo(rhs) > 0; -} - -unsigned char String::operator<=(const String &rhs) const -{ - return compareTo(rhs) <= 0; -} - -unsigned char String::operator>=(const String &rhs) const -{ - return compareTo(rhs) >= 0; -} - -unsigned char String::equalsIgnoreCase( const String &s2 ) const -{ - if (this == &s2) return 1; - if (len != s2.len) return 0; - if (len == 0) return 1; - const char *p1 = buffer; - const char *p2 = s2.buffer; - while (*p1) { - if (tolower(*p1++) != tolower(*p2++)) return 0; - } - return 1; -} - -unsigned char String::startsWith( const String &s2 ) const -{ - if (len < s2.len) return 0; - return startsWith(s2, 0); -} - -unsigned char String::startsWith( const String &s2, unsigned int offset ) const -{ - if (offset > len - s2.len || !buffer || !s2.buffer) return 0; - return strncmp( &buffer[offset], s2.buffer, s2.len ) == 0; -} - -unsigned char String::endsWith( const String &s2 ) const -{ - if ( len < s2.len || !buffer || !s2.buffer) return 0; - return strcmp(&buffer[len - s2.len], s2.buffer) == 0; -} - -/*********************************************/ -/* Character Access */ -/*********************************************/ - -char String::charAt(unsigned int loc) const -{ - return operator[](loc); -} - -void String::setCharAt(unsigned int loc, char c) -{ - if (loc < len) buffer[loc] = c; -} - -char & String::operator[](unsigned int index) -{ - static char dummy_writable_char; - if (index >= len || !buffer) { - dummy_writable_char = 0; - return dummy_writable_char; - } - return buffer[index]; -} - -char String::operator[]( unsigned int index ) const -{ - if (index >= len || !buffer) return 0; - return buffer[index]; -} - -void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const -{ - if (!bufsize || !buf) return; - if (index >= len) { - buf[0] = 0; - return; - } - unsigned int n = bufsize - 1; - if (n > len - index) n = len - index; - strncpy((char *)buf, buffer + index, n); - buf[n] = 0; -} - -/*********************************************/ -/* Search */ -/*********************************************/ - -int String::indexOf(char c) const -{ - return indexOf(c, 0); -} - -int String::indexOf( char ch, unsigned int fromIndex ) const -{ - if (fromIndex >= len) return -1; - const char* temp = strchr(buffer + fromIndex, ch); - if (temp == NULL) return -1; - return temp - buffer; -} - -int String::indexOf(const String &s2) const -{ - return indexOf(s2, 0); -} - -int String::indexOf(const String &s2, unsigned int fromIndex) const -{ - if (fromIndex >= len) return -1; - const char *found = strstr(buffer + fromIndex, s2.buffer); - if (found == NULL) return -1; - return found - buffer; -} - -int String::lastIndexOf( char theChar ) const -{ - return lastIndexOf(theChar, len - 1); -} - -int String::lastIndexOf(char ch, unsigned int fromIndex) const -{ - if (fromIndex >= len) return -1; - char tempchar = buffer[fromIndex + 1]; - buffer[fromIndex + 1] = '\0'; - char* temp = strrchr( buffer, ch ); - buffer[fromIndex + 1] = tempchar; - if (temp == NULL) return -1; - return temp - buffer; -} - -int String::lastIndexOf(const String &s2) const -{ - return lastIndexOf(s2, len - s2.len); -} - -int String::lastIndexOf(const String &s2, unsigned int fromIndex) const -{ - if (s2.len == 0 || len == 0 || s2.len > len) return -1; - if (fromIndex >= len) fromIndex = len - 1; - int found = -1; - for (char *p = buffer; p <= buffer + fromIndex; p++) { - p = strstr(p, s2.buffer); - if (!p) break; - if ((unsigned int)(p - buffer) <= fromIndex) found = p - buffer; - } - return found; -} - -String String::substring( unsigned int left ) const -{ - return substring(left, len); -} - -String String::substring(unsigned int left, unsigned int right) const -{ - if (left > right) { - unsigned int temp = right; - right = left; - left = temp; - } - String out; - if (left > len) return out; - if (right > len) right = len; - char temp = buffer[right]; // save the replaced character - buffer[right] = '\0'; - out = buffer + left; // pointer arithmetic - buffer[right] = temp; //restore character - return out; -} - -/*********************************************/ -/* Modification */ -/*********************************************/ - -void String::replace(char find, char replace) -{ - if (!buffer) return; - for (char *p = buffer; *p; p++) { - if (*p == find) *p = replace; - } -} - -void String::replace(const String& find, const String& replace) -{ - if (len == 0 || find.len == 0) return; - int diff = replace.len - find.len; - char *readFrom = buffer; - char *foundAt; - if (diff == 0) { - while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { - memcpy(foundAt, replace.buffer, replace.len); - readFrom = foundAt + replace.len; - } - } else if (diff < 0) { - char *writeTo = buffer; - while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { - unsigned int n = foundAt - readFrom; - memcpy(writeTo, readFrom, n); - writeTo += n; - memcpy(writeTo, replace.buffer, replace.len); - writeTo += replace.len; - readFrom = foundAt + find.len; - len += diff; - } - strcpy(writeTo, readFrom); - } else { - unsigned int size = len; // compute size needed for result - while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { - readFrom = foundAt + find.len; - size += diff; - } - if (size == len) return; - if (size > capacity && !changeBuffer(size)) return; // XXX: tell user! - int index = len - 1; - while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) { - readFrom = buffer + index + find.len; - memmove(readFrom + diff, readFrom, len - (readFrom - buffer)); - len += diff; - buffer[len] = 0; - memcpy(buffer + index, replace.buffer, replace.len); - index--; - } - } -} - -void String::toLowerCase(void) -{ - if (!buffer) return; - for (char *p = buffer; *p; p++) { - *p = tolower(*p); - } -} - -void String::toUpperCase(void) -{ - if (!buffer) return; - for (char *p = buffer; *p; p++) { - *p = toupper(*p); - } -} - -void String::trim(void) -{ - if (!buffer || len == 0) return; - char *begin = buffer; - while (isspace(*begin)) begin++; - char *end = buffer + len - 1; - while (isspace(*end) && end >= begin) end--; - len = end + 1 - begin; - if (begin > buffer) memcpy(buffer, begin, len); - buffer[len] = 0; -} - -/*********************************************/ -/* Parsing / Conversion */ -/*********************************************/ - -long String::toInt(void) const -{ - if (buffer) return atol(buffer); - return 0; -} - - diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WString.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WString.h deleted file mode 100644 index 947325e5f5..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WString.h +++ /dev/null @@ -1,205 +0,0 @@ -/* - WString.h - String library for Wiring & Arduino - ...mostly rewritten by Paul Stoffregen... - Copyright (c) 2009-10 Hernando Barragan. All right reserved. - Copyright 2011, Paul Stoffregen, paul@pjrc.com - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef String_class_h -#define String_class_h -#ifdef __cplusplus - -#include -#include -#include -#include - -// When compiling programs with this class, the following gcc parameters -// dramatically increase performance and memory (RAM) efficiency, typically -// with little or no increase in code size. -// -felide-constructors -// -std=c++0x - -class __FlashStringHelper; -#define F(string_literal) (reinterpret_cast(PSTR(string_literal))) - -// An inherited class for holding the result of a concatenation. These -// result objects are assumed to be writable by subsequent concatenations. -class StringSumHelper; - -// The string class -class String -{ - // use a function pointer to allow for "if (s)" without the - // complications of an operator bool(). for more information, see: - // http://www.artima.com/cppsource/safebool.html - typedef void (String::*StringIfHelperType)() const; - void StringIfHelper() const {} - -public: - // constructors - // creates a copy of the initial value. - // if the initial value is null or invalid, or if memory allocation - // fails, the string will be marked as invalid (i.e. "if (s)" will - // be false). - String(const char *cstr = ""); - String(const String &str); - #ifdef __GXX_EXPERIMENTAL_CXX0X__ - String(String &&rval); - String(StringSumHelper &&rval); - #endif - explicit String(char c); - explicit String(unsigned char, unsigned char base=10); - explicit String(int, unsigned char base=10); - explicit String(unsigned int, unsigned char base=10); - explicit String(long, unsigned char base=10); - explicit String(unsigned long, unsigned char base=10); - ~String(void); - - // memory management - // return true on success, false on failure (in which case, the string - // is left unchanged). reserve(0), if successful, will validate an - // invalid string (i.e., "if (s)" will be true afterwards) - unsigned char reserve(unsigned int size); - inline unsigned int length(void) const {return len;} - - // creates a copy of the assigned value. if the value is null or - // invalid, or if the memory allocation fails, the string will be - // marked as invalid ("if (s)" will be false). - String & operator = (const String &rhs); - String & operator = (const char *cstr); - #ifdef __GXX_EXPERIMENTAL_CXX0X__ - String & operator = (String &&rval); - String & operator = (StringSumHelper &&rval); - #endif - - // concatenate (works w/ built-in types) - - // returns true on success, false on failure (in which case, the string - // is left unchanged). if the argument is null or invalid, the - // concatenation is considered unsucessful. - unsigned char concat(const String &str); - unsigned char concat(const char *cstr); - unsigned char concat(char c); - unsigned char concat(unsigned char c); - unsigned char concat(int num); - unsigned char concat(unsigned int num); - unsigned char concat(long num); - unsigned char concat(unsigned long num); - - // if there's not enough memory for the concatenated value, the string - // will be left unchanged (but this isn't signalled in any way) - String & operator += (const String &rhs) {concat(rhs); return (*this);} - String & operator += (const char *cstr) {concat(cstr); return (*this);} - String & operator += (char c) {concat(c); return (*this);} - String & operator += (unsigned char num) {concat(num); return (*this);} - String & operator += (int num) {concat(num); return (*this);} - String & operator += (unsigned int num) {concat(num); return (*this);} - String & operator += (long num) {concat(num); return (*this);} - String & operator += (unsigned long num) {concat(num); return (*this);} - - friend StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs); - friend StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr); - friend StringSumHelper & operator + (const StringSumHelper &lhs, char c); - friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num); - friend StringSumHelper & operator + (const StringSumHelper &lhs, int num); - friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num); - friend StringSumHelper & operator + (const StringSumHelper &lhs, long num); - friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num); - - // comparison (only works w/ Strings and "strings") - operator StringIfHelperType() const { return buffer ? &String::StringIfHelper : 0; } - int compareTo(const String &s) const; - unsigned char equals(const String &s) const; - unsigned char equals(const char *cstr) const; - unsigned char operator == (const String &rhs) const {return equals(rhs);} - unsigned char operator == (const char *cstr) const {return equals(cstr);} - unsigned char operator != (const String &rhs) const {return !equals(rhs);} - unsigned char operator != (const char *cstr) const {return !equals(cstr);} - unsigned char operator < (const String &rhs) const; - unsigned char operator > (const String &rhs) const; - unsigned char operator <= (const String &rhs) const; - unsigned char operator >= (const String &rhs) const; - unsigned char equalsIgnoreCase(const String &s) const; - unsigned char startsWith( const String &prefix) const; - unsigned char startsWith(const String &prefix, unsigned int offset) const; - unsigned char endsWith(const String &suffix) const; - - // character acccess - char charAt(unsigned int index) const; - void setCharAt(unsigned int index, char c); - char operator [] (unsigned int index) const; - char& operator [] (unsigned int index); - void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index=0) const; - void toCharArray(char *buf, unsigned int bufsize, unsigned int index=0) const - {getBytes((unsigned char *)buf, bufsize, index);} - - // search - int indexOf( char ch ) const; - int indexOf( char ch, unsigned int fromIndex ) const; - int indexOf( const String &str ) const; - int indexOf( const String &str, unsigned int fromIndex ) const; - int lastIndexOf( char ch ) const; - int lastIndexOf( char ch, unsigned int fromIndex ) const; - int lastIndexOf( const String &str ) const; - int lastIndexOf( const String &str, unsigned int fromIndex ) const; - String substring( unsigned int beginIndex ) const; - String substring( unsigned int beginIndex, unsigned int endIndex ) const; - - // modification - void replace(char find, char replace); - void replace(const String& find, const String& replace); - void toLowerCase(void); - void toUpperCase(void); - void trim(void); - - // parsing/conversion - long toInt(void) const; - -protected: - char *buffer; // the actual char array - unsigned int capacity; // the array length minus one (for the '\0') - unsigned int len; // the String length (not counting the '\0') - unsigned char flags; // unused, for future features -protected: - void init(void); - void invalidate(void); - unsigned char changeBuffer(unsigned int maxStrLen); - unsigned char concat(const char *cstr, unsigned int length); - - // copy and move - String & copy(const char *cstr, unsigned int length); - #ifdef __GXX_EXPERIMENTAL_CXX0X__ - void move(String &rhs); - #endif -}; - -class StringSumHelper : public String -{ -public: - StringSumHelper(const String &s) : String(s) {} - StringSumHelper(const char *p) : String(p) {} - StringSumHelper(char c) : String(c) {} - StringSumHelper(unsigned char num) : String(num) {} - StringSumHelper(int num) : String(num) {} - StringSumHelper(unsigned int num) : String(num) {} - StringSumHelper(long num) : String(num) {} - StringSumHelper(unsigned long num) : String(num) {} -}; - -#endif // __cplusplus -#endif // String_class_h diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/binary.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/binary.h deleted file mode 100644 index af1498033a..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/binary.h +++ /dev/null @@ -1,515 +0,0 @@ -#ifndef Binary_h -#define Binary_h - -#define B0 0 -#define B00 0 -#define B000 0 -#define B0000 0 -#define B00000 0 -#define B000000 0 -#define B0000000 0 -#define B00000000 0 -#define B1 1 -#define B01 1 -#define B001 1 -#define B0001 1 -#define B00001 1 -#define B000001 1 -#define B0000001 1 -#define B00000001 1 -#define B10 2 -#define B010 2 -#define B0010 2 -#define B00010 2 -#define B000010 2 -#define B0000010 2 -#define B00000010 2 -#define B11 3 -#define B011 3 -#define B0011 3 -#define B00011 3 -#define B000011 3 -#define B0000011 3 -#define B00000011 3 -#define B100 4 -#define B0100 4 -#define B00100 4 -#define B000100 4 -#define B0000100 4 -#define B00000100 4 -#define B101 5 -#define B0101 5 -#define B00101 5 -#define B000101 5 -#define B0000101 5 -#define B00000101 5 -#define B110 6 -#define B0110 6 -#define B00110 6 -#define B000110 6 -#define B0000110 6 -#define B00000110 6 -#define B111 7 -#define B0111 7 -#define B00111 7 -#define B000111 7 -#define B0000111 7 -#define B00000111 7 -#define B1000 8 -#define B01000 8 -#define B001000 8 -#define B0001000 8 -#define B00001000 8 -#define B1001 9 -#define B01001 9 -#define B001001 9 -#define B0001001 9 -#define B00001001 9 -#define B1010 10 -#define B01010 10 -#define B001010 10 -#define B0001010 10 -#define B00001010 10 -#define B1011 11 -#define B01011 11 -#define B001011 11 -#define B0001011 11 -#define B00001011 11 -#define B1100 12 -#define B01100 12 -#define B001100 12 -#define B0001100 12 -#define B00001100 12 -#define B1101 13 -#define B01101 13 -#define B001101 13 -#define B0001101 13 -#define B00001101 13 -#define B1110 14 -#define B01110 14 -#define B001110 14 -#define B0001110 14 -#define B00001110 14 -#define B1111 15 -#define B01111 15 -#define B001111 15 -#define B0001111 15 -#define B00001111 15 -#define B10000 16 -#define B010000 16 -#define B0010000 16 -#define B00010000 16 -#define B10001 17 -#define B010001 17 -#define B0010001 17 -#define B00010001 17 -#define B10010 18 -#define B010010 18 -#define B0010010 18 -#define B00010010 18 -#define B10011 19 -#define B010011 19 -#define B0010011 19 -#define B00010011 19 -#define B10100 20 -#define B010100 20 -#define B0010100 20 -#define B00010100 20 -#define B10101 21 -#define B010101 21 -#define B0010101 21 -#define B00010101 21 -#define B10110 22 -#define B010110 22 -#define B0010110 22 -#define B00010110 22 -#define B10111 23 -#define B010111 23 -#define B0010111 23 -#define B00010111 23 -#define B11000 24 -#define B011000 24 -#define B0011000 24 -#define B00011000 24 -#define B11001 25 -#define B011001 25 -#define B0011001 25 -#define B00011001 25 -#define B11010 26 -#define B011010 26 -#define B0011010 26 -#define B00011010 26 -#define B11011 27 -#define B011011 27 -#define B0011011 27 -#define B00011011 27 -#define B11100 28 -#define B011100 28 -#define B0011100 28 -#define B00011100 28 -#define B11101 29 -#define B011101 29 -#define B0011101 29 -#define B00011101 29 -#define B11110 30 -#define B011110 30 -#define B0011110 30 -#define B00011110 30 -#define B11111 31 -#define B011111 31 -#define B0011111 31 -#define B00011111 31 -#define B100000 32 -#define B0100000 32 -#define B00100000 32 -#define B100001 33 -#define B0100001 33 -#define B00100001 33 -#define B100010 34 -#define B0100010 34 -#define B00100010 34 -#define B100011 35 -#define B0100011 35 -#define B00100011 35 -#define B100100 36 -#define B0100100 36 -#define B00100100 36 -#define B100101 37 -#define B0100101 37 -#define B00100101 37 -#define B100110 38 -#define B0100110 38 -#define B00100110 38 -#define B100111 39 -#define B0100111 39 -#define B00100111 39 -#define B101000 40 -#define B0101000 40 -#define B00101000 40 -#define B101001 41 -#define B0101001 41 -#define B00101001 41 -#define B101010 42 -#define B0101010 42 -#define B00101010 42 -#define B101011 43 -#define B0101011 43 -#define B00101011 43 -#define B101100 44 -#define B0101100 44 -#define B00101100 44 -#define B101101 45 -#define B0101101 45 -#define B00101101 45 -#define B101110 46 -#define B0101110 46 -#define B00101110 46 -#define B101111 47 -#define B0101111 47 -#define B00101111 47 -#define B110000 48 -#define B0110000 48 -#define B00110000 48 -#define B110001 49 -#define B0110001 49 -#define B00110001 49 -#define B110010 50 -#define B0110010 50 -#define B00110010 50 -#define B110011 51 -#define B0110011 51 -#define B00110011 51 -#define B110100 52 -#define B0110100 52 -#define B00110100 52 -#define B110101 53 -#define B0110101 53 -#define B00110101 53 -#define B110110 54 -#define B0110110 54 -#define B00110110 54 -#define B110111 55 -#define B0110111 55 -#define B00110111 55 -#define B111000 56 -#define B0111000 56 -#define B00111000 56 -#define B111001 57 -#define B0111001 57 -#define B00111001 57 -#define B111010 58 -#define B0111010 58 -#define B00111010 58 -#define B111011 59 -#define B0111011 59 -#define B00111011 59 -#define B111100 60 -#define B0111100 60 -#define B00111100 60 -#define B111101 61 -#define B0111101 61 -#define B00111101 61 -#define B111110 62 -#define B0111110 62 -#define B00111110 62 -#define B111111 63 -#define B0111111 63 -#define B00111111 63 -#define B1000000 64 -#define B01000000 64 -#define B1000001 65 -#define B01000001 65 -#define B1000010 66 -#define B01000010 66 -#define B1000011 67 -#define B01000011 67 -#define B1000100 68 -#define B01000100 68 -#define B1000101 69 -#define B01000101 69 -#define B1000110 70 -#define B01000110 70 -#define B1000111 71 -#define B01000111 71 -#define B1001000 72 -#define B01001000 72 -#define B1001001 73 -#define B01001001 73 -#define B1001010 74 -#define B01001010 74 -#define B1001011 75 -#define B01001011 75 -#define B1001100 76 -#define B01001100 76 -#define B1001101 77 -#define B01001101 77 -#define B1001110 78 -#define B01001110 78 -#define B1001111 79 -#define B01001111 79 -#define B1010000 80 -#define B01010000 80 -#define B1010001 81 -#define B01010001 81 -#define B1010010 82 -#define B01010010 82 -#define B1010011 83 -#define B01010011 83 -#define B1010100 84 -#define B01010100 84 -#define B1010101 85 -#define B01010101 85 -#define B1010110 86 -#define B01010110 86 -#define B1010111 87 -#define B01010111 87 -#define B1011000 88 -#define B01011000 88 -#define B1011001 89 -#define B01011001 89 -#define B1011010 90 -#define B01011010 90 -#define B1011011 91 -#define B01011011 91 -#define B1011100 92 -#define B01011100 92 -#define B1011101 93 -#define B01011101 93 -#define B1011110 94 -#define B01011110 94 -#define B1011111 95 -#define B01011111 95 -#define B1100000 96 -#define B01100000 96 -#define B1100001 97 -#define B01100001 97 -#define B1100010 98 -#define B01100010 98 -#define B1100011 99 -#define B01100011 99 -#define B1100100 100 -#define B01100100 100 -#define B1100101 101 -#define B01100101 101 -#define B1100110 102 -#define B01100110 102 -#define B1100111 103 -#define B01100111 103 -#define B1101000 104 -#define B01101000 104 -#define B1101001 105 -#define B01101001 105 -#define B1101010 106 -#define B01101010 106 -#define B1101011 107 -#define B01101011 107 -#define B1101100 108 -#define B01101100 108 -#define B1101101 109 -#define B01101101 109 -#define B1101110 110 -#define B01101110 110 -#define B1101111 111 -#define B01101111 111 -#define B1110000 112 -#define B01110000 112 -#define B1110001 113 -#define B01110001 113 -#define B1110010 114 -#define B01110010 114 -#define B1110011 115 -#define B01110011 115 -#define B1110100 116 -#define B01110100 116 -#define B1110101 117 -#define B01110101 117 -#define B1110110 118 -#define B01110110 118 -#define B1110111 119 -#define B01110111 119 -#define B1111000 120 -#define B01111000 120 -#define B1111001 121 -#define B01111001 121 -#define B1111010 122 -#define B01111010 122 -#define B1111011 123 -#define B01111011 123 -#define B1111100 124 -#define B01111100 124 -#define B1111101 125 -#define B01111101 125 -#define B1111110 126 -#define B01111110 126 -#define B1111111 127 -#define B01111111 127 -#define B10000000 128 -#define B10000001 129 -#define B10000010 130 -#define B10000011 131 -#define B10000100 132 -#define B10000101 133 -#define B10000110 134 -#define B10000111 135 -#define B10001000 136 -#define B10001001 137 -#define B10001010 138 -#define B10001011 139 -#define B10001100 140 -#define B10001101 141 -#define B10001110 142 -#define B10001111 143 -#define B10010000 144 -#define B10010001 145 -#define B10010010 146 -#define B10010011 147 -#define B10010100 148 -#define B10010101 149 -#define B10010110 150 -#define B10010111 151 -#define B10011000 152 -#define B10011001 153 -#define B10011010 154 -#define B10011011 155 -#define B10011100 156 -#define B10011101 157 -#define B10011110 158 -#define B10011111 159 -#define B10100000 160 -#define B10100001 161 -#define B10100010 162 -#define B10100011 163 -#define B10100100 164 -#define B10100101 165 -#define B10100110 166 -#define B10100111 167 -#define B10101000 168 -#define B10101001 169 -#define B10101010 170 -#define B10101011 171 -#define B10101100 172 -#define B10101101 173 -#define B10101110 174 -#define B10101111 175 -#define B10110000 176 -#define B10110001 177 -#define B10110010 178 -#define B10110011 179 -#define B10110100 180 -#define B10110101 181 -#define B10110110 182 -#define B10110111 183 -#define B10111000 184 -#define B10111001 185 -#define B10111010 186 -#define B10111011 187 -#define B10111100 188 -#define B10111101 189 -#define B10111110 190 -#define B10111111 191 -#define B11000000 192 -#define B11000001 193 -#define B11000010 194 -#define B11000011 195 -#define B11000100 196 -#define B11000101 197 -#define B11000110 198 -#define B11000111 199 -#define B11001000 200 -#define B11001001 201 -#define B11001010 202 -#define B11001011 203 -#define B11001100 204 -#define B11001101 205 -#define B11001110 206 -#define B11001111 207 -#define B11010000 208 -#define B11010001 209 -#define B11010010 210 -#define B11010011 211 -#define B11010100 212 -#define B11010101 213 -#define B11010110 214 -#define B11010111 215 -#define B11011000 216 -#define B11011001 217 -#define B11011010 218 -#define B11011011 219 -#define B11011100 220 -#define B11011101 221 -#define B11011110 222 -#define B11011111 223 -#define B11100000 224 -#define B11100001 225 -#define B11100010 226 -#define B11100011 227 -#define B11100100 228 -#define B11100101 229 -#define B11100110 230 -#define B11100111 231 -#define B11101000 232 -#define B11101001 233 -#define B11101010 234 -#define B11101011 235 -#define B11101100 236 -#define B11101101 237 -#define B11101110 238 -#define B11101111 239 -#define B11110000 240 -#define B11110001 241 -#define B11110010 242 -#define B11110011 243 -#define B11110100 244 -#define B11110101 245 -#define B11110110 246 -#define B11110111 247 -#define B11111000 248 -#define B11111001 249 -#define B11111010 250 -#define B11111011 251 -#define B11111100 252 -#define B11111101 253 -#define B11111110 254 -#define B11111111 255 - -#endif diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/main.cpp b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/main.cpp deleted file mode 100644 index 3d4e079d2a..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/main.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include - -int main(void) -{ - init(); - -#if defined(USBCON) - USBDevice.attach(); -#endif - - setup(); - - for (;;) { - loop(); - if (serialEventRun) serialEventRun(); - } - - return 0; -} - diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/new.cpp b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/new.cpp deleted file mode 100644 index 0f6d4220ef..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/new.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include - -void * operator new(size_t size) -{ - return malloc(size); -} - -void operator delete(void * ptr) -{ - free(ptr); -} - -int __cxa_guard_acquire(__guard *g) {return !*(char *)(g);}; -void __cxa_guard_release (__guard *g) {*(char *)g = 1;}; -void __cxa_guard_abort (__guard *) {}; - -void __cxa_pure_virtual(void) {}; - diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/new.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/new.h deleted file mode 100644 index cd940ce8b2..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/new.h +++ /dev/null @@ -1,22 +0,0 @@ -/* Header to define new/delete operators as they aren't provided by avr-gcc by default - Taken from http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=59453 - */ - -#ifndef NEW_H -#define NEW_H - -#include - -void * operator new(size_t size); -void operator delete(void * ptr); - -__extension__ typedef int __guard __attribute__((mode (__DI__))); - -extern "C" int __cxa_guard_acquire(__guard *); -extern "C" void __cxa_guard_release (__guard *); -extern "C" void __cxa_guard_abort (__guard *); - -extern "C" void __cxa_pure_virtual(void); - -#endif - diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring.c b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring.c deleted file mode 100644 index ac8bb6f9b4..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring.c +++ /dev/null @@ -1,324 +0,0 @@ -/* - wiring.c - Partial implementation of the Wiring API for the ATmega8. - Part of Arduino - http://www.arduino.cc/ - - Copyright (c) 2005-2006 David A. Mellis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - - $Id$ -*/ - -#include "wiring_private.h" - -// the prescaler is set so that timer0 ticks every 64 clock cycles, and the -// the overflow handler is called every 256 ticks. -#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256)) - -// the whole number of milliseconds per timer0 overflow -#define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000) - -// the fractional number of milliseconds per timer0 overflow. we shift right -// by three to fit these numbers into a byte. (for the clock speeds we care -// about - 8 and 16 MHz - this doesn't lose precision.) -#define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3) -#define FRACT_MAX (1000 >> 3) - -volatile unsigned long timer0_overflow_count = 0; -volatile unsigned long timer0_millis = 0; -static unsigned char timer0_fract = 0; - -#if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) -SIGNAL(TIM0_OVF_vect) -#else -SIGNAL(TIMER0_OVF_vect) -#endif -{ - // copy these to local variables so they can be stored in registers - // (volatile variables must be read from memory on every access) - unsigned long m = timer0_millis; - unsigned char f = timer0_fract; - - m += MILLIS_INC; - f += FRACT_INC; - if (f >= FRACT_MAX) { - f -= FRACT_MAX; - m += 1; - } - - timer0_fract = f; - timer0_millis = m; - timer0_overflow_count++; -} - -unsigned long millis() -{ - unsigned long m; - uint8_t oldSREG = SREG; - - // disable interrupts while we read timer0_millis or we might get an - // inconsistent value (e.g. in the middle of a write to timer0_millis) - cli(); - m = timer0_millis; - SREG = oldSREG; - - return m; -} - -unsigned long micros() { - unsigned long m; - uint8_t oldSREG = SREG, t; - - cli(); - m = timer0_overflow_count; -#if defined(TCNT0) - t = TCNT0; -#elif defined(TCNT0L) - t = TCNT0L; -#else - #error TIMER 0 not defined -#endif - - -#ifdef TIFR0 - if ((TIFR0 & _BV(TOV0)) && (t < 255)) - m++; -#else - if ((TIFR & _BV(TOV0)) && (t < 255)) - m++; -#endif - - SREG = oldSREG; - - return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond()); -} - -void delay(unsigned long ms) -{ - uint16_t start = (uint16_t)micros(); - - while (ms > 0) { - if (((uint16_t)micros() - start) >= 1000) { - ms--; - start += 1000; - } - } -} - -/* Delay for the given number of microseconds. Assumes a 8 or 16 MHz clock. */ -void delayMicroseconds(unsigned int us) -{ - // calling avrlib's delay_us() function with low values (e.g. 1 or - // 2 microseconds) gives delays longer than desired. - //delay_us(us); -#if F_CPU >= 20000000L - // for the 20 MHz clock on rare Arduino boards - - // for a one-microsecond delay, simply wait 2 cycle and return. The overhead - // of the function call yields a delay of exactly a one microsecond. - __asm__ __volatile__ ( - "nop" "\n\t" - "nop"); //just waiting 2 cycle - if (--us == 0) - return; - - // the following loop takes a 1/5 of a microsecond (4 cycles) - // per iteration, so execute it five times for each microsecond of - // delay requested. - us = (us<<2) + us; // x5 us - - // account for the time taken in the preceeding commands. - us -= 2; - -#elif F_CPU >= 16000000L - // for the 16 MHz clock on most Arduino boards - - // for a one-microsecond delay, simply return. the overhead - // of the function call yields a delay of approximately 1 1/8 us. - if (--us == 0) - return; - - // the following loop takes a quarter of a microsecond (4 cycles) - // per iteration, so execute it four times for each microsecond of - // delay requested. - us <<= 2; - - // account for the time taken in the preceeding commands. - us -= 2; -#else - // for the 8 MHz internal clock on the ATmega168 - - // for a one- or two-microsecond delay, simply return. the overhead of - // the function calls takes more than two microseconds. can't just - // subtract two, since us is unsigned; we'd overflow. - if (--us == 0) - return; - if (--us == 0) - return; - - // the following loop takes half of a microsecond (4 cycles) - // per iteration, so execute it twice for each microsecond of - // delay requested. - us <<= 1; - - // partially compensate for the time taken by the preceeding commands. - // we can't subtract any more than this or we'd overflow w/ small delays. - us--; -#endif - - // busy wait - __asm__ __volatile__ ( - "1: sbiw %0,1" "\n\t" // 2 cycles - "brne 1b" : "=w" (us) : "0" (us) // 2 cycles - ); -} - -void init() -{ - // this needs to be called before setup() or some functions won't - // work there - sei(); - - // on the ATmega168, timer 0 is also used for fast hardware pwm - // (using phase-correct PWM would mean that timer 0 overflowed half as often - // resulting in different millis() behavior on the ATmega8 and ATmega168) -#if defined(TCCR0A) && defined(WGM01) - sbi(TCCR0A, WGM01); - sbi(TCCR0A, WGM00); -#endif - - // set timer 0 prescale factor to 64 -#if defined(__AVR_ATmega128__) - // CPU specific: different values for the ATmega128 - sbi(TCCR0, CS02); -#elif defined(TCCR0) && defined(CS01) && defined(CS00) - // this combination is for the standard atmega8 - sbi(TCCR0, CS01); - sbi(TCCR0, CS00); -#elif defined(TCCR0B) && defined(CS01) && defined(CS00) - // this combination is for the standard 168/328/1280/2560 - sbi(TCCR0B, CS01); - sbi(TCCR0B, CS00); -#elif defined(TCCR0A) && defined(CS01) && defined(CS00) - // this combination is for the __AVR_ATmega645__ series - sbi(TCCR0A, CS01); - sbi(TCCR0A, CS00); -#else - #error Timer 0 prescale factor 64 not set correctly -#endif - - // enable timer 0 overflow interrupt -#if defined(TIMSK) && defined(TOIE0) - sbi(TIMSK, TOIE0); -#elif defined(TIMSK0) && defined(TOIE0) - sbi(TIMSK0, TOIE0); -#else - #error Timer 0 overflow interrupt not set correctly -#endif - - // timers 1 and 2 are used for phase-correct hardware pwm - // this is better for motors as it ensures an even waveform - // note, however, that fast pwm mode can achieve a frequency of up - // 8 MHz (with a 16 MHz clock) at 50% duty cycle - -#if defined(TCCR1B) && defined(CS11) && defined(CS10) - TCCR1B = 0; - - // set timer 1 prescale factor to 64 - sbi(TCCR1B, CS11); -#if F_CPU >= 8000000L - sbi(TCCR1B, CS10); -#endif -#elif defined(TCCR1) && defined(CS11) && defined(CS10) - sbi(TCCR1, CS11); -#if F_CPU >= 8000000L - sbi(TCCR1, CS10); -#endif -#endif - // put timer 1 in 8-bit phase correct pwm mode -#if defined(TCCR1A) && defined(WGM10) - sbi(TCCR1A, WGM10); -#elif defined(TCCR1) - #warning this needs to be finished -#endif - - // set timer 2 prescale factor to 64 -#if defined(TCCR2) && defined(CS22) - sbi(TCCR2, CS22); -#elif defined(TCCR2B) && defined(CS22) - sbi(TCCR2B, CS22); -#else - #warning Timer 2 not finished (may not be present on this CPU) -#endif - - // configure timer 2 for phase correct pwm (8-bit) -#if defined(TCCR2) && defined(WGM20) - sbi(TCCR2, WGM20); -#elif defined(TCCR2A) && defined(WGM20) - sbi(TCCR2A, WGM20); -#else - #warning Timer 2 not finished (may not be present on this CPU) -#endif - -#if defined(TCCR3B) && defined(CS31) && defined(WGM30) - sbi(TCCR3B, CS31); // set timer 3 prescale factor to 64 - sbi(TCCR3B, CS30); - sbi(TCCR3A, WGM30); // put timer 3 in 8-bit phase correct pwm mode -#endif - -#if defined(TCCR4A) && defined(TCCR4B) && defined(TCCR4D) /* beginning of timer4 block for 32U4 and similar */ - sbi(TCCR4B, CS42); // set timer4 prescale factor to 64 - sbi(TCCR4B, CS41); - sbi(TCCR4B, CS40); - sbi(TCCR4D, WGM40); // put timer 4 in phase- and frequency-correct PWM mode - sbi(TCCR4A, PWM4A); // enable PWM mode for comparator OCR4A - sbi(TCCR4C, PWM4D); // enable PWM mode for comparator OCR4D -#else /* beginning of timer4 block for ATMEGA1280 and ATMEGA2560 */ -#if defined(TCCR4B) && defined(CS41) && defined(WGM40) - sbi(TCCR4B, CS41); // set timer 4 prescale factor to 64 - sbi(TCCR4B, CS40); - sbi(TCCR4A, WGM40); // put timer 4 in 8-bit phase correct pwm mode -#endif -#endif /* end timer4 block for ATMEGA1280/2560 and similar */ - -#if defined(TCCR5B) && defined(CS51) && defined(WGM50) - sbi(TCCR5B, CS51); // set timer 5 prescale factor to 64 - sbi(TCCR5B, CS50); - sbi(TCCR5A, WGM50); // put timer 5 in 8-bit phase correct pwm mode -#endif - -#if defined(ADCSRA) - // set a2d prescale factor to 128 - // 16 MHz / 128 = 125 KHz, inside the desired 50-200 KHz range. - // XXX: this will not work properly for other clock speeds, and - // this code should use F_CPU to determine the prescale factor. - sbi(ADCSRA, ADPS2); - sbi(ADCSRA, ADPS1); - sbi(ADCSRA, ADPS0); - - // enable a2d conversions - sbi(ADCSRA, ADEN); -#endif - - // the bootloader connects pins 0 and 1 to the USART; disconnect them - // here so they can be used as normal digital i/o; they will be - // reconnected in Serial.begin() -#if defined(UCSRB) - UCSRB = 0; -#elif defined(UCSR0B) - UCSR0B = 0; -#endif -} diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_analog.c b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_analog.c deleted file mode 100644 index 0e9881f6ac..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_analog.c +++ /dev/null @@ -1,282 +0,0 @@ -/* - wiring_analog.c - analog input and output - Part of Arduino - http://www.arduino.cc/ - - Copyright (c) 2005-2006 David A. Mellis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - - Modified 28 September 2010 by Mark Sproul - - $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $ -*/ - -#include "wiring_private.h" -#include "pins_arduino.h" - -uint8_t analog_reference = DEFAULT; - -void analogReference(uint8_t mode) -{ - // can't actually set the register here because the default setting - // will connect AVCC and the AREF pin, which would cause a short if - // there's something connected to AREF. - analog_reference = mode; -} - -int analogRead(uint8_t pin) -{ - uint8_t low, high; - -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) - if (pin >= 54) pin -= 54; // allow for channel or pin numbers -#elif defined(__AVR_ATmega32U4__) - if (pin >= 18) pin -= 18; // allow for channel or pin numbers -#elif defined(__AVR_ATmega1284__) - if (pin >= 24) pin -= 24; // allow for channel or pin numbers -#else - if (pin >= 14) pin -= 14; // allow for channel or pin numbers -#endif - -#if defined(__AVR_ATmega32U4__) - pin = analogPinToChannel(pin); - ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((pin >> 3) & 0x01) << MUX5); -#elif defined(ADCSRB) && defined(MUX5) - // the MUX5 bit of ADCSRB selects whether we're reading from channels - // 0 to 7 (MUX5 low) or 8 to 15 (MUX5 high). - ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((pin >> 3) & 0x01) << MUX5); -#endif - - // set the analog reference (high two bits of ADMUX) and select the - // channel (low 4 bits). this also sets ADLAR (left-adjust result) - // to 0 (the default). -#if defined(ADMUX) - ADMUX = (analog_reference << 6) | (pin & 0x07); -#endif - - // without a delay, we seem to read from the wrong channel - //delay(1); - -#if defined(ADCSRA) && defined(ADCL) - // start the conversion - sbi(ADCSRA, ADSC); - - // ADSC is cleared when the conversion finishes - while (bit_is_set(ADCSRA, ADSC)); - - // we have to read ADCL first; doing so locks both ADCL - // and ADCH until ADCH is read. reading ADCL second would - // cause the results of each conversion to be discarded, - // as ADCL and ADCH would be locked when it completed. - low = ADCL; - high = ADCH; -#else - // we dont have an ADC, return 0 - low = 0; - high = 0; -#endif - - // combine the two bytes - return (high << 8) | low; -} - -// Right now, PWM output only works on the pins with -// hardware support. These are defined in the appropriate -// pins_*.c file. For the rest of the pins, we default -// to digital output. -void analogWrite(uint8_t pin, int val) -{ - // We need to make sure the PWM output is enabled for those pins - // that support it, as we turn it off when digitally reading or - // writing with them. Also, make sure the pin is in output mode - // for consistenty with Wiring, which doesn't require a pinMode - // call for the analog output pins. - pinMode(pin, OUTPUT); - if (val == 0) - { - digitalWrite(pin, LOW); - } - else if (val == 255) - { - digitalWrite(pin, HIGH); - } - else - { - switch(digitalPinToTimer(pin)) - { - // XXX fix needed for atmega8 - #if defined(TCCR0) && defined(COM00) && !defined(__AVR_ATmega8__) - case TIMER0A: - // connect pwm to pin on timer 0 - sbi(TCCR0, COM00); - OCR0 = val; // set pwm duty - break; - #endif - - #if defined(TCCR0A) && defined(COM0A1) - case TIMER0A: - // connect pwm to pin on timer 0, channel A - sbi(TCCR0A, COM0A1); - OCR0A = val; // set pwm duty - break; - #endif - - #if defined(TCCR0A) && defined(COM0B1) - case TIMER0B: - // connect pwm to pin on timer 0, channel B - sbi(TCCR0A, COM0B1); - OCR0B = val; // set pwm duty - break; - #endif - - #if defined(TCCR1A) && defined(COM1A1) - case TIMER1A: - // connect pwm to pin on timer 1, channel A - sbi(TCCR1A, COM1A1); - OCR1A = val; // set pwm duty - break; - #endif - - #if defined(TCCR1A) && defined(COM1B1) - case TIMER1B: - // connect pwm to pin on timer 1, channel B - sbi(TCCR1A, COM1B1); - OCR1B = val; // set pwm duty - break; - #endif - - #if defined(TCCR2) && defined(COM21) - case TIMER2: - // connect pwm to pin on timer 2 - sbi(TCCR2, COM21); - OCR2 = val; // set pwm duty - break; - #endif - - #if defined(TCCR2A) && defined(COM2A1) - case TIMER2A: - // connect pwm to pin on timer 2, channel A - sbi(TCCR2A, COM2A1); - OCR2A = val; // set pwm duty - break; - #endif - - #if defined(TCCR2A) && defined(COM2B1) - case TIMER2B: - // connect pwm to pin on timer 2, channel B - sbi(TCCR2A, COM2B1); - OCR2B = val; // set pwm duty - break; - #endif - - #if defined(TCCR3A) && defined(COM3A1) - case TIMER3A: - // connect pwm to pin on timer 3, channel A - sbi(TCCR3A, COM3A1); - OCR3A = val; // set pwm duty - break; - #endif - - #if defined(TCCR3A) && defined(COM3B1) - case TIMER3B: - // connect pwm to pin on timer 3, channel B - sbi(TCCR3A, COM3B1); - OCR3B = val; // set pwm duty - break; - #endif - - #if defined(TCCR3A) && defined(COM3C1) - case TIMER3C: - // connect pwm to pin on timer 3, channel C - sbi(TCCR3A, COM3C1); - OCR3C = val; // set pwm duty - break; - #endif - - #if defined(TCCR4A) - case TIMER4A: - //connect pwm to pin on timer 4, channel A - sbi(TCCR4A, COM4A1); - #if defined(COM4A0) // only used on 32U4 - cbi(TCCR4A, COM4A0); - #endif - OCR4A = val; // set pwm duty - break; - #endif - - #if defined(TCCR4A) && defined(COM4B1) - case TIMER4B: - // connect pwm to pin on timer 4, channel B - sbi(TCCR4A, COM4B1); - OCR4B = val; // set pwm duty - break; - #endif - - #if defined(TCCR4A) && defined(COM4C1) - case TIMER4C: - // connect pwm to pin on timer 4, channel C - sbi(TCCR4A, COM4C1); - OCR4C = val; // set pwm duty - break; - #endif - - #if defined(TCCR4C) && defined(COM4D1) - case TIMER4D: - // connect pwm to pin on timer 4, channel D - sbi(TCCR4C, COM4D1); - #if defined(COM4D0) // only used on 32U4 - cbi(TCCR4C, COM4D0); - #endif - OCR4D = val; // set pwm duty - break; - #endif - - - #if defined(TCCR5A) && defined(COM5A1) - case TIMER5A: - // connect pwm to pin on timer 5, channel A - sbi(TCCR5A, COM5A1); - OCR5A = val; // set pwm duty - break; - #endif - - #if defined(TCCR5A) && defined(COM5B1) - case TIMER5B: - // connect pwm to pin on timer 5, channel B - sbi(TCCR5A, COM5B1); - OCR5B = val; // set pwm duty - break; - #endif - - #if defined(TCCR5A) && defined(COM5C1) - case TIMER5C: - // connect pwm to pin on timer 5, channel C - sbi(TCCR5A, COM5C1); - OCR5C = val; // set pwm duty - break; - #endif - - case NOT_ON_TIMER: - default: - if (val < 128) { - digitalWrite(pin, LOW); - } else { - digitalWrite(pin, HIGH); - } - } - } -} - diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_digital.c b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_digital.c deleted file mode 100644 index be323b1dfe..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_digital.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - wiring_digital.c - digital input and output functions - Part of Arduino - http://www.arduino.cc/ - - Copyright (c) 2005-2006 David A. Mellis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - - Modified 28 September 2010 by Mark Sproul - - $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $ -*/ - -#define ARDUINO_MAIN -#include "wiring_private.h" -#include "pins_arduino.h" - -void pinMode(uint8_t pin, uint8_t mode) -{ - uint8_t bit = digitalPinToBitMask(pin); - uint8_t port = digitalPinToPort(pin); - volatile uint8_t *reg, *out; - - if (port == NOT_A_PIN) return; - - // JWS: can I let the optimizer do this? - reg = portModeRegister(port); - out = portOutputRegister(port); - - if (mode == INPUT) { - uint8_t oldSREG = SREG; - cli(); - *reg &= ~bit; - *out &= ~bit; - SREG = oldSREG; - } else if (mode == INPUT_PULLUP) { - uint8_t oldSREG = SREG; - cli(); - *reg &= ~bit; - *out |= bit; - SREG = oldSREG; - } else { - uint8_t oldSREG = SREG; - cli(); - *reg |= bit; - SREG = oldSREG; - } -} - -// Forcing this inline keeps the callers from having to push their own stuff -// on the stack. It is a good performance win and only takes 1 more byte per -// user than calling. (It will take more bytes on the 168.) -// -// But shouldn't this be moved into pinMode? Seems silly to check and do on -// each digitalread or write. -// -// Mark Sproul: -// - Removed inline. Save 170 bytes on atmega1280 -// - changed to a switch statment; added 32 bytes but much easier to read and maintain. -// - Added more #ifdefs, now compiles for atmega645 -// -//static inline void turnOffPWM(uint8_t timer) __attribute__ ((always_inline)); -//static inline void turnOffPWM(uint8_t timer) -static void turnOffPWM(uint8_t timer) -{ - switch (timer) - { - #if defined(TCCR1A) && defined(COM1A1) - case TIMER1A: cbi(TCCR1A, COM1A1); break; - #endif - #if defined(TCCR1A) && defined(COM1B1) - case TIMER1B: cbi(TCCR1A, COM1B1); break; - #endif - - #if defined(TCCR2) && defined(COM21) - case TIMER2: cbi(TCCR2, COM21); break; - #endif - - #if defined(TCCR0A) && defined(COM0A1) - case TIMER0A: cbi(TCCR0A, COM0A1); break; - #endif - - #if defined(TIMER0B) && defined(COM0B1) - case TIMER0B: cbi(TCCR0A, COM0B1); break; - #endif - #if defined(TCCR2A) && defined(COM2A1) - case TIMER2A: cbi(TCCR2A, COM2A1); break; - #endif - #if defined(TCCR2A) && defined(COM2B1) - case TIMER2B: cbi(TCCR2A, COM2B1); break; - #endif - - #if defined(TCCR3A) && defined(COM3A1) - case TIMER3A: cbi(TCCR3A, COM3A1); break; - #endif - #if defined(TCCR3A) && defined(COM3B1) - case TIMER3B: cbi(TCCR3A, COM3B1); break; - #endif - #if defined(TCCR3A) && defined(COM3C1) - case TIMER3C: cbi(TCCR3A, COM3C1); break; - #endif - - #if defined(TCCR4A) && defined(COM4A1) - case TIMER4A: cbi(TCCR4A, COM4A1); break; - #endif - #if defined(TCCR4A) && defined(COM4B1) - case TIMER4B: cbi(TCCR4A, COM4B1); break; - #endif - #if defined(TCCR4A) && defined(COM4C1) - case TIMER4C: cbi(TCCR4A, COM4C1); break; - #endif - #if defined(TCCR4C) && defined(COM4D1) - case TIMER4D: cbi(TCCR4C, COM4D1); break; - #endif - - #if defined(TCCR5A) - case TIMER5A: cbi(TCCR5A, COM5A1); break; - case TIMER5B: cbi(TCCR5A, COM5B1); break; - case TIMER5C: cbi(TCCR5A, COM5C1); break; - #endif - } -} - -void digitalWrite(uint8_t pin, uint8_t val) -{ - uint8_t timer = digitalPinToTimer(pin); - uint8_t bit = digitalPinToBitMask(pin); - uint8_t port = digitalPinToPort(pin); - volatile uint8_t *out; - - if (port == NOT_A_PIN) return; - - // If the pin that support PWM output, we need to turn it off - // before doing a digital write. - if (timer != NOT_ON_TIMER) turnOffPWM(timer); - - out = portOutputRegister(port); - - uint8_t oldSREG = SREG; - cli(); - - if (val == LOW) { - *out &= ~bit; - } else { - *out |= bit; - } - - SREG = oldSREG; -} - -int digitalRead(uint8_t pin) -{ - uint8_t timer = digitalPinToTimer(pin); - uint8_t bit = digitalPinToBitMask(pin); - uint8_t port = digitalPinToPort(pin); - - if (port == NOT_A_PIN) return LOW; - - // If the pin that support PWM output, we need to turn it off - // before getting a digital reading. - if (timer != NOT_ON_TIMER) turnOffPWM(timer); - - if (*portInputRegister(port) & bit) return HIGH; - return LOW; -} diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_private.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_private.h deleted file mode 100644 index f0ceb0cc4d..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_private.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - wiring_private.h - Internal header file. - Part of Arduino - http://www.arduino.cc/ - - Copyright (c) 2005-2006 David A. Mellis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - - $Id: wiring.h 239 2007-01-12 17:58:39Z mellis $ -*/ - -#ifndef WiringPrivate_h -#define WiringPrivate_h - -#include -#include -#include -#include - -#include "Arduino.h" - -#ifdef __cplusplus -extern "C"{ -#endif - -#ifndef cbi -#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) -#endif -#ifndef sbi -#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) -#endif - -#define EXTERNAL_INT_0 0 -#define EXTERNAL_INT_1 1 -#define EXTERNAL_INT_2 2 -#define EXTERNAL_INT_3 3 -#define EXTERNAL_INT_4 4 -#define EXTERNAL_INT_5 5 -#define EXTERNAL_INT_6 6 -#define EXTERNAL_INT_7 7 - -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) -#define EXTERNAL_NUM_INTERRUPTS 8 -#elif defined(__AVR_ATmega1284P__) -#define EXTERNAL_NUM_INTERRUPTS 3 -#else -#define EXTERNAL_NUM_INTERRUPTS 2 -#endif - -typedef void (*voidFuncPtr)(void); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_pulse.c b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_pulse.c deleted file mode 100644 index 0d968865d2..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_pulse.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - wiring_pulse.c - pulseIn() function - Part of Arduino - http://www.arduino.cc/ - - Copyright (c) 2005-2006 David A. Mellis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - - $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $ -*/ - -#include "wiring_private.h" -#include "pins_arduino.h" - -/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH - * or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds - * to 3 minutes in length, but must be called at least a few dozen microseconds - * before the start of the pulse. */ -unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout) -{ - // cache the port and bit of the pin in order to speed up the - // pulse width measuring loop and achieve finer resolution. calling - // digitalRead() instead yields much coarser resolution. - uint8_t bit = digitalPinToBitMask(pin); - uint8_t port = digitalPinToPort(pin); - uint8_t stateMask = (state ? bit : 0); - unsigned long width = 0; // keep initialization out of time critical area - - // convert the timeout from microseconds to a number of times through - // the initial loop; it takes 16 clock cycles per iteration. - unsigned long numloops = 0; - unsigned long maxloops = microsecondsToClockCycles(timeout) / 16; - - // wait for any previous pulse to end - while ((*portInputRegister(port) & bit) == stateMask) - if (numloops++ == maxloops) - return 0; - - // wait for the pulse to start - while ((*portInputRegister(port) & bit) != stateMask) - if (numloops++ == maxloops) - return 0; - - // wait for the pulse to stop - while ((*portInputRegister(port) & bit) == stateMask) { - if (numloops++ == maxloops) - return 0; - width++; - } - - // convert the reading to microseconds. The loop has been determined - // to be 20 clock cycles long and have about 16 clocks between the edge - // and the start of the loop. There will be some error introduced by - // the interrupt handlers. - return clockCyclesToMicroseconds(width * 21 + 16); -} diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_shift.c b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_shift.c deleted file mode 100644 index cfe786758c..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_shift.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - wiring_shift.c - shiftOut() function - Part of Arduino - http://www.arduino.cc/ - - Copyright (c) 2005-2006 David A. Mellis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - - $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $ -*/ - -#include "wiring_private.h" - -uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) { - uint8_t value = 0; - uint8_t i; - - for (i = 0; i < 8; ++i) { - digitalWrite(clockPin, HIGH); - if (bitOrder == LSBFIRST) - value |= digitalRead(dataPin) << i; - else - value |= digitalRead(dataPin) << (7 - i); - digitalWrite(clockPin, LOW); - } - return value; -} - -void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val) -{ - uint8_t i; - - for (i = 0; i < 8; i++) { - if (bitOrder == LSBFIRST) - digitalWrite(dataPin, !!(val & (1 << i))); - else - digitalWrite(dataPin, !!(val & (1 << (7 - i)))); - - digitalWrite(clockPin, HIGH); - digitalWrite(clockPin, LOW); - } -} diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/variants/eightanaloginputs/pins_arduino.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/variants/eightanaloginputs/pins_arduino.h deleted file mode 100644 index 52b37efc40..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/variants/eightanaloginputs/pins_arduino.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - pins_arduino.h - Pin definition functions for Arduino - Part of Arduino - http://www.arduino.cc/ - - Copyright (c) 2007 David A. Mellis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - - $Id: wiring.h 249 2007-02-03 16:52:51Z mellis $ -*/ - -#include "../standard/pins_arduino.h" -#undef NUM_ANALOG_INPUTS -#define NUM_ANALOG_INPUTS 8 diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/variants/leonardo/pins_arduino.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/variants/leonardo/pins_arduino.h deleted file mode 100644 index 9f770d6cec..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/variants/leonardo/pins_arduino.h +++ /dev/null @@ -1,256 +0,0 @@ -/* - pins_arduino.h - Pin definition functions for Arduino - Part of Arduino - http://www.arduino.cc/ - - Copyright (c) 2007 David A. Mellis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - - $Id: wiring.h 249 2007-02-03 16:52:51Z mellis $ -*/ - -#ifndef Pins_Arduino_h -#define Pins_Arduino_h - -#include - -#define TX_RX_LED_INIT DDRD |= (1<<5), DDRB |= (1<<0) -#define TXLED0 PORTD |= (1<<5) -#define TXLED1 PORTD &= ~(1<<5) -#define RXLED0 PORTB |= (1<<0) -#define RXLED1 PORTB &= ~(1<<0) - -static const uint8_t SDA = 2; -static const uint8_t SCL = 3; - -// Map SPI port to 'new' pins D14..D17 -static const uint8_t SS = 17; -static const uint8_t MOSI = 16; -static const uint8_t MISO = 14; -static const uint8_t SCK = 15; - -// Mapping of analog pins as digital I/O -// A6-A11 share with digital pins -static const uint8_t A0 = 18; -static const uint8_t A1 = 19; -static const uint8_t A2 = 20; -static const uint8_t A3 = 21; -static const uint8_t A4 = 22; -static const uint8_t A5 = 23; -static const uint8_t A6 = 24; // D4 -static const uint8_t A7 = 25; // D6 -static const uint8_t A8 = 26; // D8 -static const uint8_t A9 = 27; // D9 -static const uint8_t A10 = 28; // D10 -static const uint8_t A11 = 29; // D12 - -#define digitalPinToPCICR(p) ((((p) >= 8 && (p) <= 11) || ((p) >= 14 && (p) <= 17) || ((p) >= A8 && (p) <= A10)) ? (&PCICR) : ((uint8_t *)0)) -#define digitalPinToPCICRbit(p) 0 -#define digitalPinToPCMSK(p) ((((p) >= 8 && (p) <= 11) || ((p) >= 14 && (p) <= 17) || ((p) >= A8 && (p) <= A10)) ? (&PCMSK0) : ((uint8_t *)0)) -#define digitalPinToPCMSKbit(p) ( ((p) >= 8 && (p) <= 11) ? (p) - 4 : ((p) == 14 ? 3 : ((p) == 15 ? 1 : ((p) == 16 ? 2 : ((p) == 17 ? 0 : (p - A8 + 4)))))) - -// __AVR_ATmega32U4__ has an unusual mapping of pins to channels -extern const uint8_t PROGMEM analog_pin_to_channel_PGM[]; -#define analogPinToChannel(P) ( pgm_read_byte( analog_pin_to_channel_PGM + (P) ) ) - -#ifdef ARDUINO_MAIN - -// On the Arduino board, digital pins are also used -// for the analog output (software PWM). Analog input -// pins are a separate set. - -// ATMEL ATMEGA32U4 / ARDUINO LEONARDO -// -// D0 PD2 RXD1/INT2 -// D1 PD3 TXD1/INT3 -// D2 PD1 SDA SDA/INT1 -// D3# PD0 PWM8/SCL OC0B/SCL/INT0 -// D4 A6 PD4 ADC8 -// D5# PC6 ??? OC3A/#OC4A -// D6# A7 PD7 FastPWM #OC4D/ADC10 -// D7 PE6 INT6/AIN0 -// -// D8 A8 PB4 ADC11/PCINT4 -// D9# A9 PB5 PWM16 OC1A/#OC4B/ADC12/PCINT5 -// D10# A10 PB6 PWM16 OC1B/0c4B/ADC13/PCINT6 -// D11# PB7 PWM8/16 0C0A/OC1C/#RTS/PCINT7 -// D12 A11 PD6 T1/#OC4D/ADC9 -// D13# PC7 PWM10 CLK0/OC4A -// -// A0 D18 PF7 ADC7 -// A1 D19 PF6 ADC6 -// A2 D20 PF5 ADC5 -// A3 D21 PF4 ADC4 -// A4 D22 PF1 ADC1 -// A5 D23 PF0 ADC0 -// -// New pins D14..D17 to map SPI port to digital pins -// -// MISO D14 PB3 MISO,PCINT3 -// SCK D15 PB1 SCK,PCINT1 -// MOSI D16 PB2 MOSI,PCINT2 -// SS D17 PB0 RXLED,SS/PCINT0 -// -// TXLED PD5 -// RXLED PB0 -// HWB PE2 HWB - -// these arrays map port names (e.g. port B) to the -// appropriate addresses for various functions (e.g. reading -// and writing) -const uint16_t PROGMEM port_to_mode_PGM[] = { - NOT_A_PORT, - NOT_A_PORT, - (uint16_t) &DDRB, - (uint16_t) &DDRC, - (uint16_t) &DDRD, - (uint16_t) &DDRE, - (uint16_t) &DDRF, -}; - -const uint16_t PROGMEM port_to_output_PGM[] = { - NOT_A_PORT, - NOT_A_PORT, - (uint16_t) &PORTB, - (uint16_t) &PORTC, - (uint16_t) &PORTD, - (uint16_t) &PORTE, - (uint16_t) &PORTF, -}; - -const uint16_t PROGMEM port_to_input_PGM[] = { - NOT_A_PORT, - NOT_A_PORT, - (uint16_t) &PINB, - (uint16_t) &PINC, - (uint16_t) &PIND, - (uint16_t) &PINE, - (uint16_t) &PINF, -}; - -const uint8_t PROGMEM digital_pin_to_port_PGM[30] = { - PD, // D0 - PD2 - PD, // D1 - PD3 - PD, // D2 - PD1 - PD, // D3 - PD0 - PD, // D4 - PD4 - PC, // D5 - PC6 - PD, // D6 - PD7 - PE, // D7 - PE6 - - PB, // D8 - PB4 - PB, // D9 - PB5 - PB, // D10 - PB6 - PB, // D11 - PB7 - PD, // D12 - PD6 - PC, // D13 - PC7 - - PB, // D14 - MISO - PB3 - PB, // D15 - SCK - PB1 - PB, // D16 - MOSI - PB2 - PB, // D17 - SS - PB0 - - PF, // D18 - A0 - PF7 - PF, // D19 - A1 - PF6 - PF, // D20 - A2 - PF5 - PF, // D21 - A3 - PF4 - PF, // D22 - A4 - PF1 - PF, // D23 - A5 - PF0 - - PD, // D24 / D4 - A6 - PD4 - PD, // D25 / D6 - A7 - PD7 - PB, // D26 / D8 - A8 - PB4 - PB, // D27 / D9 - A9 - PB5 - PB, // D28 / D10 - A10 - PB6 - PD, // D29 / D12 - A11 - PD6 -}; - -const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[30] = { - _BV(2), // D0 - PD2 - _BV(3), // D1 - PD3 - _BV(1), // D2 - PD1 - _BV(0), // D3 - PD0 - _BV(4), // D4 - PD4 - _BV(6), // D5 - PC6 - _BV(7), // D6 - PD7 - _BV(6), // D7 - PE6 - - _BV(4), // D8 - PB4 - _BV(5), // D9 - PB5 - _BV(6), // D10 - PB6 - _BV(7), // D11 - PB7 - _BV(6), // D12 - PD6 - _BV(7), // D13 - PC7 - - _BV(3), // D14 - MISO - PB3 - _BV(1), // D15 - SCK - PB1 - _BV(2), // D16 - MOSI - PB2 - _BV(0), // D17 - SS - PB0 - - _BV(7), // D18 - A0 - PF7 - _BV(6), // D19 - A1 - PF6 - _BV(5), // D20 - A2 - PF5 - _BV(4), // D21 - A3 - PF4 - _BV(1), // D22 - A4 - PF1 - _BV(0), // D23 - A5 - PF0 - - _BV(4), // D24 / D4 - A6 - PD4 - _BV(7), // D25 / D6 - A7 - PD7 - _BV(4), // D26 / D8 - A8 - PB4 - _BV(5), // D27 / D9 - A9 - PB5 - _BV(6), // D28 / D10 - A10 - PB6 - _BV(6), // D29 / D12 - A11 - PD6 -}; - -const uint8_t PROGMEM digital_pin_to_timer_PGM[16] = { - NOT_ON_TIMER, - NOT_ON_TIMER, - NOT_ON_TIMER, - TIMER0B, /* 3 */ - NOT_ON_TIMER, - TIMER3A, /* 5 */ - TIMER4D, /* 6 */ - NOT_ON_TIMER, - - NOT_ON_TIMER, - TIMER1A, /* 9 */ - TIMER1B, /* 10 */ - TIMER0A, /* 11 */ - - NOT_ON_TIMER, - TIMER4A, /* 13 */ - - NOT_ON_TIMER, - NOT_ON_TIMER, -}; - -const uint8_t PROGMEM analog_pin_to_channel_PGM[12] = { - 7, // A0 PF7 ADC7 - 6, // A1 PF6 ADC6 - 5, // A2 PF5 ADC5 - 4, // A3 PF4 ADC4 - 1, // A4 PF1 ADC1 - 0, // A5 PF0 ADC0 - 8, // A6 D4 PD4 ADC8 - 10, // A7 D6 PD7 ADC10 - 11, // A8 D8 PB4 ADC11 - 12, // A9 D9 PB5 ADC12 - 13, // A10 D10 PB6 ADC13 - 9 // A11 D12 PD6 ADC9 -}; - -#endif /* ARDUINO_MAIN */ -#endif /* Pins_Arduino_h */ diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/variants/mega/pins_arduino.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/variants/mega/pins_arduino.h deleted file mode 100644 index 5a9b4cb09b..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/variants/mega/pins_arduino.h +++ /dev/null @@ -1,363 +0,0 @@ -/* - pins_arduino.h - Pin definition functions for Arduino - Part of Arduino - http://www.arduino.cc/ - - Copyright (c) 2007 David A. Mellis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - - $Id: wiring.h 249 2007-02-03 16:52:51Z mellis $ -*/ - -#ifndef Pins_Arduino_h -#define Pins_Arduino_h - -#include - -#define NUM_DIGITAL_PINS 70 -#define NUM_ANALOG_INPUTS 16 -#define analogInputToDigitalPin(p) ((p < 16) ? (p) + 54 : -1) -#define digitalPinHasPWM(p) (((p) >= 2 && (p) <= 13) || ((p) >= 44 && (p)<= 46)) - -static const uint8_t SS = 53; -static const uint8_t MOSI = 51; -static const uint8_t MISO = 50; -static const uint8_t SCK = 52; - -static const uint8_t SDA = 20; -static const uint8_t SCL = 21; -static const uint8_t LED_BUILTIN = 13; - -static const uint8_t A0 = 54; -static const uint8_t A1 = 55; -static const uint8_t A2 = 56; -static const uint8_t A3 = 57; -static const uint8_t A4 = 58; -static const uint8_t A5 = 59; -static const uint8_t A6 = 60; -static const uint8_t A7 = 61; -static const uint8_t A8 = 62; -static const uint8_t A9 = 63; -static const uint8_t A10 = 64; -static const uint8_t A11 = 65; -static const uint8_t A12 = 66; -static const uint8_t A13 = 67; -static const uint8_t A14 = 68; -static const uint8_t A15 = 69; - -// A majority of the pins are NOT PCINTs, SO BE WARNED (i.e. you cannot use them as receive pins) -// Only pins available for RECEIVE (TRANSMIT can be on any pin): -// (I've deliberately left out pin mapping to the Hardware USARTs - seems senseless to me) -// Pins: 10, 11, 12, 13, 50, 51, 52, 53, 62, 63, 64, 65, 66, 67, 68, 69 - -#define digitalPinToPCICR(p) ( (((p) >= 10) && ((p) <= 13)) || \ - (((p) >= 50) && ((p) <= 53)) || \ - (((p) >= 62) && ((p) <= 69)) ? (&PCICR) : ((uint8_t *)0) ) - -#define digitalPinToPCICRbit(p) ( (((p) >= 10) && ((p) <= 13)) || (((p) >= 50) && ((p) <= 53)) ? 0 : \ - ( (((p) >= 62) && ((p) <= 69)) ? 2 : \ - 0 ) ) - -#define digitalPinToPCMSK(p) ( (((p) >= 10) && ((p) <= 13)) || (((p) >= 50) && ((p) <= 53)) ? (&PCMSK0) : \ - ( (((p) >= 62) && ((p) <= 69)) ? (&PCMSK2) : \ - ((uint8_t *)0) ) ) - -#define digitalPinToPCMSKbit(p) ( (((p) >= 10) && ((p) <= 13)) ? ((p) - 6) : \ - ( ((p) == 50) ? 3 : \ - ( ((p) == 51) ? 2 : \ - ( ((p) == 52) ? 1 : \ - ( ((p) == 53) ? 0 : \ - ( (((p) >= 62) && ((p) <= 69)) ? ((p) - 62) : \ - 0 ) ) ) ) ) ) - -#ifdef ARDUINO_MAIN - -const uint16_t PROGMEM port_to_mode_PGM[] = { - NOT_A_PORT, - (uint16_t) &DDRA, - (uint16_t) &DDRB, - (uint16_t) &DDRC, - (uint16_t) &DDRD, - (uint16_t) &DDRE, - (uint16_t) &DDRF, - (uint16_t) &DDRG, - (uint16_t) &DDRH, - NOT_A_PORT, - (uint16_t) &DDRJ, - (uint16_t) &DDRK, - (uint16_t) &DDRL, -}; - -const uint16_t PROGMEM port_to_output_PGM[] = { - NOT_A_PORT, - (uint16_t) &PORTA, - (uint16_t) &PORTB, - (uint16_t) &PORTC, - (uint16_t) &PORTD, - (uint16_t) &PORTE, - (uint16_t) &PORTF, - (uint16_t) &PORTG, - (uint16_t) &PORTH, - NOT_A_PORT, - (uint16_t) &PORTJ, - (uint16_t) &PORTK, - (uint16_t) &PORTL, -}; - -const uint16_t PROGMEM port_to_input_PGM[] = { - NOT_A_PIN, - (uint16_t) &PINA, - (uint16_t) &PINB, - (uint16_t) &PINC, - (uint16_t) &PIND, - (uint16_t) &PINE, - (uint16_t) &PINF, - (uint16_t) &PING, - (uint16_t) &PINH, - NOT_A_PIN, - (uint16_t) &PINJ, - (uint16_t) &PINK, - (uint16_t) &PINL, -}; - -const uint8_t PROGMEM digital_pin_to_port_PGM[] = { - // PORTLIST - // ------------------------------------------- - PE , // PE 0 ** 0 ** USART0_RX - PE , // PE 1 ** 1 ** USART0_TX - PE , // PE 4 ** 2 ** PWM2 - PE , // PE 5 ** 3 ** PWM3 - PG , // PG 5 ** 4 ** PWM4 - PE , // PE 3 ** 5 ** PWM5 - PH , // PH 3 ** 6 ** PWM6 - PH , // PH 4 ** 7 ** PWM7 - PH , // PH 5 ** 8 ** PWM8 - PH , // PH 6 ** 9 ** PWM9 - PB , // PB 4 ** 10 ** PWM10 - PB , // PB 5 ** 11 ** PWM11 - PB , // PB 6 ** 12 ** PWM12 - PB , // PB 7 ** 13 ** PWM13 - PJ , // PJ 1 ** 14 ** USART3_TX - PJ , // PJ 0 ** 15 ** USART3_RX - PH , // PH 1 ** 16 ** USART2_TX - PH , // PH 0 ** 17 ** USART2_RX - PD , // PD 3 ** 18 ** USART1_TX - PD , // PD 2 ** 19 ** USART1_RX - PD , // PD 1 ** 20 ** I2C_SDA - PD , // PD 0 ** 21 ** I2C_SCL - PA , // PA 0 ** 22 ** D22 - PA , // PA 1 ** 23 ** D23 - PA , // PA 2 ** 24 ** D24 - PA , // PA 3 ** 25 ** D25 - PA , // PA 4 ** 26 ** D26 - PA , // PA 5 ** 27 ** D27 - PA , // PA 6 ** 28 ** D28 - PA , // PA 7 ** 29 ** D29 - PC , // PC 7 ** 30 ** D30 - PC , // PC 6 ** 31 ** D31 - PC , // PC 5 ** 32 ** D32 - PC , // PC 4 ** 33 ** D33 - PC , // PC 3 ** 34 ** D34 - PC , // PC 2 ** 35 ** D35 - PC , // PC 1 ** 36 ** D36 - PC , // PC 0 ** 37 ** D37 - PD , // PD 7 ** 38 ** D38 - PG , // PG 2 ** 39 ** D39 - PG , // PG 1 ** 40 ** D40 - PG , // PG 0 ** 41 ** D41 - PL , // PL 7 ** 42 ** D42 - PL , // PL 6 ** 43 ** D43 - PL , // PL 5 ** 44 ** D44 - PL , // PL 4 ** 45 ** D45 - PL , // PL 3 ** 46 ** D46 - PL , // PL 2 ** 47 ** D47 - PL , // PL 1 ** 48 ** D48 - PL , // PL 0 ** 49 ** D49 - PB , // PB 3 ** 50 ** SPI_MISO - PB , // PB 2 ** 51 ** SPI_MOSI - PB , // PB 1 ** 52 ** SPI_SCK - PB , // PB 0 ** 53 ** SPI_SS - PF , // PF 0 ** 54 ** A0 - PF , // PF 1 ** 55 ** A1 - PF , // PF 2 ** 56 ** A2 - PF , // PF 3 ** 57 ** A3 - PF , // PF 4 ** 58 ** A4 - PF , // PF 5 ** 59 ** A5 - PF , // PF 6 ** 60 ** A6 - PF , // PF 7 ** 61 ** A7 - PK , // PK 0 ** 62 ** A8 - PK , // PK 1 ** 63 ** A9 - PK , // PK 2 ** 64 ** A10 - PK , // PK 3 ** 65 ** A11 - PK , // PK 4 ** 66 ** A12 - PK , // PK 5 ** 67 ** A13 - PK , // PK 6 ** 68 ** A14 - PK , // PK 7 ** 69 ** A15 -}; - -const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = { - // PIN IN PORT - // ------------------------------------------- - _BV( 0 ) , // PE 0 ** 0 ** USART0_RX - _BV( 1 ) , // PE 1 ** 1 ** USART0_TX - _BV( 4 ) , // PE 4 ** 2 ** PWM2 - _BV( 5 ) , // PE 5 ** 3 ** PWM3 - _BV( 5 ) , // PG 5 ** 4 ** PWM4 - _BV( 3 ) , // PE 3 ** 5 ** PWM5 - _BV( 3 ) , // PH 3 ** 6 ** PWM6 - _BV( 4 ) , // PH 4 ** 7 ** PWM7 - _BV( 5 ) , // PH 5 ** 8 ** PWM8 - _BV( 6 ) , // PH 6 ** 9 ** PWM9 - _BV( 4 ) , // PB 4 ** 10 ** PWM10 - _BV( 5 ) , // PB 5 ** 11 ** PWM11 - _BV( 6 ) , // PB 6 ** 12 ** PWM12 - _BV( 7 ) , // PB 7 ** 13 ** PWM13 - _BV( 1 ) , // PJ 1 ** 14 ** USART3_TX - _BV( 0 ) , // PJ 0 ** 15 ** USART3_RX - _BV( 1 ) , // PH 1 ** 16 ** USART2_TX - _BV( 0 ) , // PH 0 ** 17 ** USART2_RX - _BV( 3 ) , // PD 3 ** 18 ** USART1_TX - _BV( 2 ) , // PD 2 ** 19 ** USART1_RX - _BV( 1 ) , // PD 1 ** 20 ** I2C_SDA - _BV( 0 ) , // PD 0 ** 21 ** I2C_SCL - _BV( 0 ) , // PA 0 ** 22 ** D22 - _BV( 1 ) , // PA 1 ** 23 ** D23 - _BV( 2 ) , // PA 2 ** 24 ** D24 - _BV( 3 ) , // PA 3 ** 25 ** D25 - _BV( 4 ) , // PA 4 ** 26 ** D26 - _BV( 5 ) , // PA 5 ** 27 ** D27 - _BV( 6 ) , // PA 6 ** 28 ** D28 - _BV( 7 ) , // PA 7 ** 29 ** D29 - _BV( 7 ) , // PC 7 ** 30 ** D30 - _BV( 6 ) , // PC 6 ** 31 ** D31 - _BV( 5 ) , // PC 5 ** 32 ** D32 - _BV( 4 ) , // PC 4 ** 33 ** D33 - _BV( 3 ) , // PC 3 ** 34 ** D34 - _BV( 2 ) , // PC 2 ** 35 ** D35 - _BV( 1 ) , // PC 1 ** 36 ** D36 - _BV( 0 ) , // PC 0 ** 37 ** D37 - _BV( 7 ) , // PD 7 ** 38 ** D38 - _BV( 2 ) , // PG 2 ** 39 ** D39 - _BV( 1 ) , // PG 1 ** 40 ** D40 - _BV( 0 ) , // PG 0 ** 41 ** D41 - _BV( 7 ) , // PL 7 ** 42 ** D42 - _BV( 6 ) , // PL 6 ** 43 ** D43 - _BV( 5 ) , // PL 5 ** 44 ** D44 - _BV( 4 ) , // PL 4 ** 45 ** D45 - _BV( 3 ) , // PL 3 ** 46 ** D46 - _BV( 2 ) , // PL 2 ** 47 ** D47 - _BV( 1 ) , // PL 1 ** 48 ** D48 - _BV( 0 ) , // PL 0 ** 49 ** D49 - _BV( 3 ) , // PB 3 ** 50 ** SPI_MISO - _BV( 2 ) , // PB 2 ** 51 ** SPI_MOSI - _BV( 1 ) , // PB 1 ** 52 ** SPI_SCK - _BV( 0 ) , // PB 0 ** 53 ** SPI_SS - _BV( 0 ) , // PF 0 ** 54 ** A0 - _BV( 1 ) , // PF 1 ** 55 ** A1 - _BV( 2 ) , // PF 2 ** 56 ** A2 - _BV( 3 ) , // PF 3 ** 57 ** A3 - _BV( 4 ) , // PF 4 ** 58 ** A4 - _BV( 5 ) , // PF 5 ** 59 ** A5 - _BV( 6 ) , // PF 6 ** 60 ** A6 - _BV( 7 ) , // PF 7 ** 61 ** A7 - _BV( 0 ) , // PK 0 ** 62 ** A8 - _BV( 1 ) , // PK 1 ** 63 ** A9 - _BV( 2 ) , // PK 2 ** 64 ** A10 - _BV( 3 ) , // PK 3 ** 65 ** A11 - _BV( 4 ) , // PK 4 ** 66 ** A12 - _BV( 5 ) , // PK 5 ** 67 ** A13 - _BV( 6 ) , // PK 6 ** 68 ** A14 - _BV( 7 ) , // PK 7 ** 69 ** A15 -}; - -const uint8_t PROGMEM digital_pin_to_timer_PGM[] = { - // TIMERS - // ------------------------------------------- - NOT_ON_TIMER , // PE 0 ** 0 ** USART0_RX - NOT_ON_TIMER , // PE 1 ** 1 ** USART0_TX - TIMER3B , // PE 4 ** 2 ** PWM2 - TIMER3C , // PE 5 ** 3 ** PWM3 - TIMER0B , // PG 5 ** 4 ** PWM4 - TIMER3A , // PE 3 ** 5 ** PWM5 - TIMER4A , // PH 3 ** 6 ** PWM6 - TIMER4B , // PH 4 ** 7 ** PWM7 - TIMER4C , // PH 5 ** 8 ** PWM8 - TIMER2B , // PH 6 ** 9 ** PWM9 - TIMER2A , // PB 4 ** 10 ** PWM10 - TIMER1A , // PB 5 ** 11 ** PWM11 - TIMER1B , // PB 6 ** 12 ** PWM12 - TIMER0A , // PB 7 ** 13 ** PWM13 - NOT_ON_TIMER , // PJ 1 ** 14 ** USART3_TX - NOT_ON_TIMER , // PJ 0 ** 15 ** USART3_RX - NOT_ON_TIMER , // PH 1 ** 16 ** USART2_TX - NOT_ON_TIMER , // PH 0 ** 17 ** USART2_RX - NOT_ON_TIMER , // PD 3 ** 18 ** USART1_TX - NOT_ON_TIMER , // PD 2 ** 19 ** USART1_RX - NOT_ON_TIMER , // PD 1 ** 20 ** I2C_SDA - NOT_ON_TIMER , // PD 0 ** 21 ** I2C_SCL - NOT_ON_TIMER , // PA 0 ** 22 ** D22 - NOT_ON_TIMER , // PA 1 ** 23 ** D23 - NOT_ON_TIMER , // PA 2 ** 24 ** D24 - NOT_ON_TIMER , // PA 3 ** 25 ** D25 - NOT_ON_TIMER , // PA 4 ** 26 ** D26 - NOT_ON_TIMER , // PA 5 ** 27 ** D27 - NOT_ON_TIMER , // PA 6 ** 28 ** D28 - NOT_ON_TIMER , // PA 7 ** 29 ** D29 - NOT_ON_TIMER , // PC 7 ** 30 ** D30 - NOT_ON_TIMER , // PC 6 ** 31 ** D31 - NOT_ON_TIMER , // PC 5 ** 32 ** D32 - NOT_ON_TIMER , // PC 4 ** 33 ** D33 - NOT_ON_TIMER , // PC 3 ** 34 ** D34 - NOT_ON_TIMER , // PC 2 ** 35 ** D35 - NOT_ON_TIMER , // PC 1 ** 36 ** D36 - NOT_ON_TIMER , // PC 0 ** 37 ** D37 - NOT_ON_TIMER , // PD 7 ** 38 ** D38 - NOT_ON_TIMER , // PG 2 ** 39 ** D39 - NOT_ON_TIMER , // PG 1 ** 40 ** D40 - NOT_ON_TIMER , // PG 0 ** 41 ** D41 - NOT_ON_TIMER , // PL 7 ** 42 ** D42 - NOT_ON_TIMER , // PL 6 ** 43 ** D43 - TIMER5C , // PL 5 ** 44 ** D44 - TIMER5B , // PL 4 ** 45 ** D45 - TIMER5A , // PL 3 ** 46 ** D46 - NOT_ON_TIMER , // PL 2 ** 47 ** D47 - NOT_ON_TIMER , // PL 1 ** 48 ** D48 - NOT_ON_TIMER , // PL 0 ** 49 ** D49 - NOT_ON_TIMER , // PB 3 ** 50 ** SPI_MISO - NOT_ON_TIMER , // PB 2 ** 51 ** SPI_MOSI - NOT_ON_TIMER , // PB 1 ** 52 ** SPI_SCK - NOT_ON_TIMER , // PB 0 ** 53 ** SPI_SS - NOT_ON_TIMER , // PF 0 ** 54 ** A0 - NOT_ON_TIMER , // PF 1 ** 55 ** A1 - NOT_ON_TIMER , // PF 2 ** 56 ** A2 - NOT_ON_TIMER , // PF 3 ** 57 ** A3 - NOT_ON_TIMER , // PF 4 ** 58 ** A4 - NOT_ON_TIMER , // PF 5 ** 59 ** A5 - NOT_ON_TIMER , // PF 6 ** 60 ** A6 - NOT_ON_TIMER , // PF 7 ** 61 ** A7 - NOT_ON_TIMER , // PK 0 ** 62 ** A8 - NOT_ON_TIMER , // PK 1 ** 63 ** A9 - NOT_ON_TIMER , // PK 2 ** 64 ** A10 - NOT_ON_TIMER , // PK 3 ** 65 ** A11 - NOT_ON_TIMER , // PK 4 ** 66 ** A12 - NOT_ON_TIMER , // PK 5 ** 67 ** A13 - NOT_ON_TIMER , // PK 6 ** 68 ** A14 - NOT_ON_TIMER , // PK 7 ** 69 ** A15 -}; - -#endif - -#endif \ No newline at end of file diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/variants/standard/pins_arduino.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/variants/standard/pins_arduino.h deleted file mode 100644 index 30b4266306..0000000000 --- a/tmk_core/protocol/usb_hid/arduino-1.0.1/variants/standard/pins_arduino.h +++ /dev/null @@ -1,218 +0,0 @@ -/* - pins_arduino.h - Pin definition functions for Arduino - Part of Arduino - http://www.arduino.cc/ - - Copyright (c) 2007 David A. Mellis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - - $Id: wiring.h 249 2007-02-03 16:52:51Z mellis $ -*/ - -#ifndef Pins_Arduino_h -#define Pins_Arduino_h - -#include - -#define NUM_DIGITAL_PINS 20 -#define NUM_ANALOG_INPUTS 6 -#define analogInputToDigitalPin(p) ((p < 6) ? (p) + 14 : -1) - -#if defined(__AVR_ATmega8__) -#define digitalPinHasPWM(p) ((p) == 9 || (p) == 10 || (p) == 11) -#else -#define digitalPinHasPWM(p) ((p) == 3 || (p) == 5 || (p) == 6 || (p) == 9 || (p) == 10 || (p) == 11) -#endif - -static const uint8_t SS = 10; -static const uint8_t MOSI = 11; -static const uint8_t MISO = 12; -static const uint8_t SCK = 13; - -static const uint8_t SDA = 18; -static const uint8_t SCL = 19; -static const uint8_t LED_BUILTIN = 13; - -static const uint8_t A0 = 14; -static const uint8_t A1 = 15; -static const uint8_t A2 = 16; -static const uint8_t A3 = 17; -static const uint8_t A4 = 18; -static const uint8_t A5 = 19; -static const uint8_t A6 = 20; -static const uint8_t A7 = 21; - -#define digitalPinToPCICR(p) (((p) >= 0 && (p) <= 21) ? (&PCICR) : ((uint8_t *)0)) -#define digitalPinToPCICRbit(p) (((p) <= 7) ? 2 : (((p) <= 13) ? 0 : 1)) -#define digitalPinToPCMSK(p) (((p) <= 7) ? (&PCMSK2) : (((p) <= 13) ? (&PCMSK0) : (((p) <= 21) ? (&PCMSK1) : ((uint8_t *)0)))) -#define digitalPinToPCMSKbit(p) (((p) <= 7) ? (p) : (((p) <= 13) ? ((p) - 8) : ((p) - 14))) - -#ifdef ARDUINO_MAIN - -// On the Arduino board, digital pins are also used -// for the analog output (software PWM). Analog input -// pins are a separate set. - -// ATMEL ATMEGA8 & 168 / ARDUINO -// -// +-\/-+ -// PC6 1| |28 PC5 (AI 5) -// (D 0) PD0 2| |27 PC4 (AI 4) -// (D 1) PD1 3| |26 PC3 (AI 3) -// (D 2) PD2 4| |25 PC2 (AI 2) -// PWM+ (D 3) PD3 5| |24 PC1 (AI 1) -// (D 4) PD4 6| |23 PC0 (AI 0) -// VCC 7| |22 GND -// GND 8| |21 AREF -// PB6 9| |20 AVCC -// PB7 10| |19 PB5 (D 13) -// PWM+ (D 5) PD5 11| |18 PB4 (D 12) -// PWM+ (D 6) PD6 12| |17 PB3 (D 11) PWM -// (D 7) PD7 13| |16 PB2 (D 10) PWM -// (D 8) PB0 14| |15 PB1 (D 9) PWM -// +----+ -// -// (PWM+ indicates the additional PWM pins on the ATmega168.) - -// ATMEL ATMEGA1280 / ARDUINO -// -// 0-7 PE0-PE7 works -// 8-13 PB0-PB5 works -// 14-21 PA0-PA7 works -// 22-29 PH0-PH7 works -// 30-35 PG5-PG0 works -// 36-43 PC7-PC0 works -// 44-51 PJ7-PJ0 works -// 52-59 PL7-PL0 works -// 60-67 PD7-PD0 works -// A0-A7 PF0-PF7 -// A8-A15 PK0-PK7 - - -// these arrays map port names (e.g. port B) to the -// appropriate addresses for various functions (e.g. reading -// and writing) -const uint16_t PROGMEM port_to_mode_PGM[] = { - NOT_A_PORT, - NOT_A_PORT, - (uint16_t) &DDRB, - (uint16_t) &DDRC, - (uint16_t) &DDRD, -}; - -const uint16_t PROGMEM port_to_output_PGM[] = { - NOT_A_PORT, - NOT_A_PORT, - (uint16_t) &PORTB, - (uint16_t) &PORTC, - (uint16_t) &PORTD, -}; - -const uint16_t PROGMEM port_to_input_PGM[] = { - NOT_A_PORT, - NOT_A_PORT, - (uint16_t) &PINB, - (uint16_t) &PINC, - (uint16_t) &PIND, -}; - -const uint8_t PROGMEM digital_pin_to_port_PGM[] = { - PD, /* 0 */ - PD, - PD, - PD, - PD, - PD, - PD, - PD, - PB, /* 8 */ - PB, - PB, - PB, - PB, - PB, - PC, /* 14 */ - PC, - PC, - PC, - PC, - PC, -}; - -const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = { - _BV(0), /* 0, port D */ - _BV(1), - _BV(2), - _BV(3), - _BV(4), - _BV(5), - _BV(6), - _BV(7), - _BV(0), /* 8, port B */ - _BV(1), - _BV(2), - _BV(3), - _BV(4), - _BV(5), - _BV(0), /* 14, port C */ - _BV(1), - _BV(2), - _BV(3), - _BV(4), - _BV(5), -}; - -const uint8_t PROGMEM digital_pin_to_timer_PGM[] = { - NOT_ON_TIMER, /* 0 - port D */ - NOT_ON_TIMER, - NOT_ON_TIMER, - // on the ATmega168, digital pin 3 has hardware pwm -#if defined(__AVR_ATmega8__) - NOT_ON_TIMER, -#else - TIMER2B, -#endif - NOT_ON_TIMER, - // on the ATmega168, digital pins 5 and 6 have hardware pwm -#if defined(__AVR_ATmega8__) - NOT_ON_TIMER, - NOT_ON_TIMER, -#else - TIMER0B, - TIMER0A, -#endif - NOT_ON_TIMER, - NOT_ON_TIMER, /* 8 - port B */ - TIMER1A, - TIMER1B, -#if defined(__AVR_ATmega8__) - TIMER2, -#else - TIMER2A, -#endif - NOT_ON_TIMER, - NOT_ON_TIMER, - NOT_ON_TIMER, - NOT_ON_TIMER, /* 14 - port C */ - NOT_ON_TIMER, - NOT_ON_TIMER, - NOT_ON_TIMER, - NOT_ON_TIMER, -}; - -#endif - -#endif -- cgit v1.2.3 From 0a1bf7f6aa6e44557041e03f6e58df5a180c6d79 Mon Sep 17 00:00:00 2001 From: Simon Arlott Date: Fri, 20 Aug 2021 00:31:23 +0100 Subject: Support using a timer for wait_us() on ChibiOS-based boards (#12211) * Support using a timer for wait_us() on ChibiOS-based boards (#12198) There are spare GPT timers that can be used to get a more accurate wait_ms() time. This is required for the matrix scan unselect delay (30µs) to be shorter than the system tick rate of 100µs. This is limited to the maximum GPT duration of 65535 so values above that will automatically use the previous implementation based on the system tick. Using a specific timer means it can't be shared by another thread at the same time so when wait_us() is called from anything other than the main thread it will use the system tick implementation too. * Update tmk_core/common/chibios/wait.c * Update tmk_core/common/chibios/wait.c Co-authored-by: Joel Challis --- tmk_core/chibios.mk | 3 +- tmk_core/common/chibios/_wait.c | 89 ++++++++++++++++++++++++++++++++++++++++ tmk_core/common/chibios/_wait.h | 24 ++++++----- tmk_core/common/chibios/wait.c | 90 ++++++++++------------------------------- 4 files changed, 127 insertions(+), 79 deletions(-) create mode 100644 tmk_core/common/chibios/_wait.c (limited to 'tmk_core') diff --git a/tmk_core/chibios.mk b/tmk_core/chibios.mk index 7962516a0a..18839710be 100644 --- a/tmk_core/chibios.mk +++ b/tmk_core/chibios.mk @@ -211,7 +211,8 @@ CHIBISRC = $(STARTUPSRC) \ $(BOARDSRC) \ $(STREAMSSRC) \ $(CHIBIOS)/os/various/syscalls.c \ - $(PLATFORM_COMMON_DIR)/syscall-fallbacks.c + $(PLATFORM_COMMON_DIR)/syscall-fallbacks.c \ + $(PLATFORM_COMMON_DIR)/wait.c # Ensure the ASM files are not subjected to LTO -- it'll strip out interrupt handlers otherwise. QUANTUM_LIB_SRC += $(STARTUPASM) $(PORTASM) $(OSALASM) $(PLATFORMASM) diff --git a/tmk_core/common/chibios/_wait.c b/tmk_core/common/chibios/_wait.c new file mode 100644 index 0000000000..1fbea2dd5e --- /dev/null +++ b/tmk_core/common/chibios/_wait.c @@ -0,0 +1,89 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __OPTIMIZE__ +# pragma message "Compiler optimizations disabled; wait_cpuclock() won't work as designed" +#endif + +#define CLOCK_DELAY_NOP8 "nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t" + +__attribute__((always_inline)) static inline void wait_cpuclock(unsigned int n) { /* n: 1..135 */ + /* The argument n must be a constant expression. + * That way, compiler optimization will remove unnecessary code. */ + if (n < 1) { + return; + } + if (n > 8) { + unsigned int n8 = n / 8; + n = n - n8 * 8; + switch (n8) { + case 16: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 15: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 14: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 13: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 12: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 11: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 10: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 9: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 8: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 7: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 6: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 5: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 4: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 3: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 2: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 1: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 0: + break; + } + } + switch (n) { + case 8: + asm volatile("nop" ::: "memory"); + case 7: + asm volatile("nop" ::: "memory"); + case 6: + asm volatile("nop" ::: "memory"); + case 5: + asm volatile("nop" ::: "memory"); + case 4: + asm volatile("nop" ::: "memory"); + case 3: + asm volatile("nop" ::: "memory"); + case 2: + asm volatile("nop" ::: "memory"); + case 1: + asm volatile("nop" ::: "memory"); + case 0: + break; + } +} diff --git a/tmk_core/common/chibios/_wait.h b/tmk_core/common/chibios/_wait.h index 5bface53e1..4a5172536b 100644 --- a/tmk_core/common/chibios/_wait.h +++ b/tmk_core/common/chibios/_wait.h @@ -16,6 +16,7 @@ #pragma once #include +#include /* chThdSleepX of zero maps to infinite - so we map to a tiny delay to still yield */ #define wait_ms(ms) \ @@ -26,14 +27,19 @@ chThdSleepMicroseconds(1); \ } \ } while (0) -#define wait_us(us) \ - do { \ - if (us != 0) { \ - chThdSleepMicroseconds(us); \ - } else { \ - chThdSleepMicroseconds(1); \ - } \ - } while (0) + +#ifdef WAIT_US_TIMER +void wait_us(uint16_t duration); +#else +# define wait_us(us) \ + do { \ + if (us != 0) { \ + chThdSleepMicroseconds(us); \ + } else { \ + chThdSleepMicroseconds(1); \ + } \ + } while (0) +#endif /* For GPIOs on ARM-based MCUs, the input pins are sampled by the clock of the bus * to which the GPIO is connected. @@ -46,7 +52,7 @@ * (A fairly large value of 0.25 microseconds is set.) */ -#include "wait.c" +#include "_wait.c" #ifndef GPIO_INPUT_PIN_DELAY # define GPIO_INPUT_PIN_DELAY (STM32_SYSCLK / 1000000L / 4) diff --git a/tmk_core/common/chibios/wait.c b/tmk_core/common/chibios/wait.c index c6270fd95e..56fd6ffcec 100644 --- a/tmk_core/common/chibios/wait.c +++ b/tmk_core/common/chibios/wait.c @@ -14,76 +14,28 @@ * along with this program. If not, see . */ -#ifndef __OPTIMIZE__ -# pragma message "Compiler optimizations disabled; wait_cpuclock() won't work as designed" -#endif +#include +#include -#define CLOCK_DELAY_NOP8 "nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t" +#include "_wait.h" -__attribute__((always_inline)) static inline void wait_cpuclock(unsigned int n) { /* n: 1..135 */ - /* The argument n must be a constant expression. - * That way, compiler optimization will remove unnecessary code. */ - if (n < 1) { - return; - } - if (n > 8) { - unsigned int n8 = n / 8; - n = n - n8 * 8; - switch (n8) { - case 16: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 15: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 14: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 13: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 12: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 11: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 10: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 9: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 8: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 7: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 6: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 5: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 4: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 3: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 2: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 1: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 0: - break; - } +#ifdef WAIT_US_TIMER +void wait_us(uint16_t duration) { + static const GPTConfig gpt_cfg = {1000000, NULL, 0, 0}; /* 1MHz timer, no callback */ + + if (duration == 0) { + duration = 1; } - switch (n) { - case 8: - asm volatile("nop" ::: "memory"); - case 7: - asm volatile("nop" ::: "memory"); - case 6: - asm volatile("nop" ::: "memory"); - case 5: - asm volatile("nop" ::: "memory"); - case 4: - asm volatile("nop" ::: "memory"); - case 3: - asm volatile("nop" ::: "memory"); - case 2: - asm volatile("nop" ::: "memory"); - case 1: - asm volatile("nop" ::: "memory"); - case 0: - break; + + /* + * Only use this timer on the main thread; + * other threads need to use their own timer. + */ + if (chThdGetSelfX() == &ch.mainthread && duration < (1ULL << (sizeof(gptcnt_t) * 8))) { + gptStart(&WAIT_US_TIMER, &gpt_cfg); + gptPolledDelay(&WAIT_US_TIMER, duration); + } else { + chThdSleepMicroseconds(duration); } -} \ No newline at end of file +} +#endif -- cgit v1.2.3 From c70abc8d047319830e369ae4e14cd43bae3bd3b8 Mon Sep 17 00:00:00 2001 From: Nick Brassel Date: Sun, 22 Aug 2021 13:49:33 +1000 Subject: Warn when building a board that uses arm_atsam (#10904) * Add deprecation warning during build when building a board that uses arm_atsam. * Rewording. * Wording. * Fixup.--- tmk_core/arm_atsam.mk | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'tmk_core') diff --git a/tmk_core/arm_atsam.mk b/tmk_core/arm_atsam.mk index e9bdc2c3c1..b29de9132b 100644 --- a/tmk_core/arm_atsam.mk +++ b/tmk_core/arm_atsam.mk @@ -50,6 +50,17 @@ MCUFLAGS += -D__$(ARM_ATSAM)__ # For a directory that has spaces, enclose it in quotes. EXTRALIBDIRS = +cpfirmware: warn-arm_atsam +.INTERMEDIATE: warn-arm_atsam +warn-arm_atsam: $(FIRMWARE_FORMAT) + $(info @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@) + $(info This MCU support package has a lack of support from the upstream provider (Massdrop).) + $(info There are currently questions about valid licensing, and at this stage it's likely) + $(info their boards and supporting code will be removed from QMK in the near future. Please) + $(info contact Massdrop for support, and encourage them to align their future board design) + $(info choices to gain proper license compatibility with QMK.) + $(info @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@) + # Convert hex to bin. bin: $(BUILD_DIR)/$(TARGET).hex $(OBJCOPY) -Iihex -Obinary $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin -- cgit v1.2.3 From 9af069ecf354b97b3456e856fbf8e22822efeb18 Mon Sep 17 00:00:00 2001 From: Dasky Date: Mon, 23 Aug 2021 00:31:38 +0100 Subject: Fix typo (#14118) --- tmk_core/protocol/lufa/lufa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tmk_core') diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c index e638dbc0fb..4e17834be9 100644 --- a/tmk_core/protocol/lufa/lufa.c +++ b/tmk_core/protocol/lufa/lufa.c @@ -312,7 +312,7 @@ static void Console_Task(void) { void send_joystick_packet(joystick_t *joystick) { uint8_t timeout = 255; - static joystick_report_t; + static joystick_report_t r; r = (joystick_report_t) { # if JOYSTICK_AXES_COUNT > 0 .axes = -- cgit v1.2.3 From e756a21636149ad47c19c659d04be93cf3071dab Mon Sep 17 00:00:00 2001 From: Donald Kjer Date: Mon, 23 Aug 2021 15:15:34 -0700 Subject: eeprom_stm32: implement high density wear leveling (#12567) * eeprom_stm32: implement wear leveling Update EECONFIG_MAGIC_NUMBER eeprom_stm32: check emulated eeprom size is large enough * eeprom_stm32: Increasing simulated EEPROM density on stm32 * Adding utility script to decode emulated eeprom * Adding unit tests * Applying qmk cformat changes * cleaned up flash mocking * Fix for stm32eeprom_parser.py checking via signature with wrong base * Fix for nk65 keyboard Co-authored-by: Ilya Zhuravlev Co-authored-by: zvecr --- build_test.mk | 1 + keyboards/nk65/config.h | 3 + quantum/eeconfig.h | 2 +- testlist.mk | 1 + tmk_core/common/chibios/eeprom_stm32.c | 802 ++++++++++++++++++++++++---- tmk_core/common/chibios/eeprom_stm32.h | 61 +-- tmk_core/common/chibios/flash_stm32.h | 7 +- tmk_core/common/test/eeprom_stm32_tests.cpp | 438 +++++++++++++++ tmk_core/common/test/flash_stm32_mock.c | 50 ++ tmk_core/common/test/rules.mk | 23 + tmk_core/common/test/testlist.mk | 1 + util/stm32eeprom_parser.py | 317 +++++++++++ 12 files changed, 1529 insertions(+), 177 deletions(-) create mode 100644 tmk_core/common/test/eeprom_stm32_tests.cpp create mode 100644 tmk_core/common/test/flash_stm32_mock.c create mode 100644 tmk_core/common/test/rules.mk create mode 100644 tmk_core/common/test/testlist.mk create mode 100755 util/stm32eeprom_parser.py (limited to 'tmk_core') diff --git a/build_test.mk b/build_test.mk index b6b8782174..037577bf90 100644 --- a/build_test.mk +++ b/build_test.mk @@ -56,6 +56,7 @@ include $(TMK_PATH)/common.mk include $(QUANTUM_PATH)/debounce/tests/rules.mk include $(QUANTUM_PATH)/sequencer/tests/rules.mk include $(QUANTUM_PATH)/serial_link/tests/rules.mk +include $(TMK_PATH)/common/test/rules.mk ifneq ($(filter $(FULL_TESTS),$(TEST)),) include build_full_test.mk endif diff --git a/keyboards/nk65/config.h b/keyboards/nk65/config.h index fa14e9ffbf..a178307cc0 100755 --- a/keyboards/nk65/config.h +++ b/keyboards/nk65/config.h @@ -148,6 +148,9 @@ along with this program. If not, see . * both 128kb and 256kb versions of F303. * Register 0x1FFFF7CC holds the size of the flash memory. */ +#ifndef FLASHSIZE_BASE +# define FLASHSIZE_BASE ((uint32_t)0x1FFFF7CCU) /*!< FLASH Size register base address */ +#endif #define EEPROM_START_ADDRESS #define FEE_MCU_FLASH_SIZE \ ({ \ diff --git a/quantum/eeconfig.h b/quantum/eeconfig.h index a88071729d..bd39971b2c 100644 --- a/quantum/eeconfig.h +++ b/quantum/eeconfig.h @@ -21,7 +21,7 @@ along with this program. If not, see . #include #ifndef EECONFIG_MAGIC_NUMBER -# define EECONFIG_MAGIC_NUMBER (uint16_t)0xFEEA // When changing, decrement this value to avoid future re-init issues +# define EECONFIG_MAGIC_NUMBER (uint16_t)0xFEE9 // When changing, decrement this value to avoid future re-init issues #endif #define EECONFIG_MAGIC_NUMBER_OFF (uint16_t)0xFFFF diff --git a/testlist.mk b/testlist.mk index d256f4c815..b66b93d295 100644 --- a/testlist.mk +++ b/testlist.mk @@ -4,6 +4,7 @@ FULL_TESTS := $(TEST_LIST) include $(ROOT_DIR)/quantum/debounce/tests/testlist.mk include $(ROOT_DIR)/quantum/sequencer/tests/testlist.mk include $(ROOT_DIR)/quantum/serial_link/tests/testlist.mk +include $(ROOT_DIR)/tmk_core/common/test/testlist.mk define VALIDATE_TEST_LIST ifneq ($1,) diff --git a/tmk_core/common/chibios/eeprom_stm32.c b/tmk_core/common/chibios/eeprom_stm32.c index ea51989728..5bf852fde1 100644 --- a/tmk_core/common/chibios/eeprom_stm32.c +++ b/tmk_core/common/chibios/eeprom_stm32.c @@ -14,185 +14,751 @@ * Artur F. * * Modifications for QMK and STM32F303 by Yiancar + * Modifications to add flash wear leveling by Ilya Zhuravlev + * Modifications to increase flash density by Don Kjer */ #include -#include +#include +#include "debug.h" #include "eeprom_stm32.h" -/***************************************************************************** - * Allows to use the internal flash to store non volatile data. To initialize - * the functionality use the EEPROM_Init() function. Be sure that by reprogramming - * of the controller just affected pages will be deleted. In other case the non - * volatile data will be lost. - ******************************************************************************/ +#include "flash_stm32.h" + +/* + * We emulate eeprom by writing a snapshot compacted view of eeprom contents, + * followed by a write log of any change since that snapshot: + * + * === SIMULATED EEPROM CONTENTS === + * + * ┌─ Compacted ┬ Write Log ─┐ + * │............│[BYTE][BYTE]│ + * │FFFF....FFFF│[WRD0][WRD1]│ + * │FFFFFFFFFFFF│[WORD][NEXT]│ + * │....FFFFFFFF│[BYTE][WRD0]│ + * ├────────────┼────────────┤ + * └──PAGE_BASE │ │ + * PAGE_LAST─┴─WRITE_BASE │ + * WRITE_LAST ┘ + * + * Compacted contents are the 1's complement of the actual EEPROM contents. + * e.g. An 'FFFF' represents a '0000' value. + * + * The size of the 'compacted' area is equal to the size of the 'emulated' eeprom. + * The size of the compacted-area and write log are configurable, and the combined + * size of Compacted + WriteLog is a multiple FEE_PAGE_SIZE, which is MCU dependent. + * Simulated Eeprom contents are located at the end of available flash space. + * + * The following configuration defines can be set: + * + * FEE_DENSITY_PAGES # Total number of pages to use for eeprom simulation (Compact + Write log) + * FEE_DENSITY_BYTES # Size of simulated eeprom. (Defaults to half the space allocated by FEE_DENSITY_PAGES) + * NOTE: The current implementation does not include page swapping, + * and FEE_DENSITY_BYTES will consume that amount of RAM as a cached view of actual EEPROM contents. + * + * The maximum size of FEE_DENSITY_BYTES is currently 16384. The write log size equals + * FEE_DENSITY_PAGES * FEE_PAGE_SIZE - FEE_DENSITY_BYTES. + * The larger the write log, the less frequently the compacted area needs to be rewritten. + * + * + * *** General Algorithm *** + * + * During initialization: + * The contents of the Compacted-flash area are loaded and the 1's complement value + * is cached into memory (e.g. 0xFFFF in Flash represents 0x0000 in cache). + * Write log entries are processed until a 0xFFFF is reached. + * Each log entry updates a byte or word in the cache. + * + * During reads: + * EEPROM contents are given back directly from the cache in memory. + * + * During writes: + * The contents of the cache is updated first. + * If the Compacted-flash area corresponding to the write address is unprogrammed, the 1's complement of the value is written directly into Compacted-flash + * Otherwise: + * If the write log is full, erase both the Compacted-flash area and the Write log, then write cached contents to the Compacted-flash area. + * Otherwise a Write log entry is constructed and appended to the next free position in the Write log. + * + * + * *** Write Log Structure *** + * + * Write log entries allow for optimized byte writes to addresses below 128. Writing 0 or 1 words are also optimized when word-aligned. + * + * === WRITE LOG ENTRY FORMATS === + * + * ╔═══ Byte-Entry ══╗ + * ║0XXXXXXX║YYYYYYYY║ + * ║ └──┬──┘║└──┬───┘║ + * ║ Address║ Value ║ + * ╚════════╩════════╝ + * 0 <= Address < 0x80 (128) + * + * ╔ Word-Encoded 0 ╗ + * ║100XXXXXXXXXXXXX║ + * ║ │└─────┬─────┘║ + * ║ │Address >> 1 ║ + * ║ └── Value: 0 ║ + * ╚════════════════╝ + * 0 <= Address <= 0x3FFE (16382) + * + * ╔ Word-Encoded 1 ╗ + * ║101XXXXXXXXXXXXX║ + * ║ │└─────┬─────┘║ + * ║ │Address >> 1 ║ + * ║ └── Value: 1 ║ + * ╚════════════════╝ + * 0 <= Address <= 0x3FFE (16382) + * + * ╔═══ Reserved ═══╗ + * ║110XXXXXXXXXXXXX║ + * ╚════════════════╝ + * + * ╔═══════════ Word-Next ═══════════╗ + * ║111XXXXXXXXXXXXX║YYYYYYYYYYYYYYYY║ + * ║ └─────┬─────┘║└───────┬──────┘║ + * ║(Address-128)>>1║ ~Value ║ + * ╚════════════════╩════════════════╝ + * ( 0 <= Address < 0x0080 (128): Reserved) + * 0x80 <= Address <= 0x3FFE (16382) + * + * Write Log entry ranges: + * 0x0000 ... 0x7FFF - Byte-Entry; address is (Entry & 0x7F00) >> 4; value is (Entry & 0xFF) + * 0x8000 ... 0x9FFF - Word-Encoded 0; address is (Entry & 0x1FFF) << 1; value is 0 + * 0xA000 ... 0xBFFF - Word-Encoded 1; address is (Entry & 0x1FFF) << 1; value is 1 + * 0xC000 ... 0xDFFF - Reserved + * 0xE000 ... 0xFFBF - Word-Next; address is (Entry & 0x1FFF) << 1 + 0x80; value is ~(Next_Entry) + * 0xFFC0 ... 0xFFFE - Reserved + * 0xFFFF - Unprogrammed + * + */ -/* Private macro -------------------------------------------------------------*/ -/* Private variables ---------------------------------------------------------*/ -/* Functions -----------------------------------------------------------------*/ +/* These bits are used for optimizing encoding of bytes, 0 and 1 */ +#define FEE_WORD_ENCODING 0x8000 +#define FEE_VALUE_NEXT 0x6000 +#define FEE_VALUE_RESERVED 0x4000 +#define FEE_VALUE_ENCODED 0x2000 +#define FEE_BYTE_RANGE 0x80 + +// 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 +#elif defined(EEPROM_EMU_STM32F072xB) +# define MCU_STM32F072CB +#elif defined(EEPROM_EMU_STM32F042x6) +# define MCU_STM32F042K6 +#elif !defined(FEE_PAGE_SIZE) || !defined(FEE_DENSITY_PAGES) || !defined(FEE_MCU_FLASH_SIZE) +# error "not implemented." +#endif + +#if !defined(FEE_PAGE_SIZE) || !defined(FEE_DENSITY_PAGES) +# if defined(MCU_STM32F103RB) || defined(MCU_STM32F042K6) +# ifndef FEE_PAGE_SIZE +# define FEE_PAGE_SIZE 0x400 // Page size = 1KByte +# endif +# ifndef FEE_DENSITY_PAGES +# define FEE_DENSITY_PAGES 2 // How many pages are used +# endif +# elif defined(MCU_STM32F103ZE) || defined(MCU_STM32F103RE) || defined(MCU_STM32F103RD) || defined(MCU_STM32F303CC) || defined(MCU_STM32F072CB) +# ifndef FEE_PAGE_SIZE +# define FEE_PAGE_SIZE 0x800 // Page size = 2KByte +# endif +# ifndef FEE_DENSITY_PAGES +# define FEE_DENSITY_PAGES 4 // How many pages are used +# endif +# else +# error "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)." +# endif +#endif + +#ifndef FEE_MCU_FLASH_SIZE +# if defined(MCU_STM32F103RB) || defined(MCU_STM32F072CB) +# define FEE_MCU_FLASH_SIZE 128 // Size in Kb +# elif defined(MCU_STM32F042K6) +# define FEE_MCU_FLASH_SIZE 32 // Size in Kb +# elif defined(MCU_STM32F103ZE) || defined(MCU_STM32F103RE) +# define FEE_MCU_FLASH_SIZE 512 // Size in Kb +# elif defined(MCU_STM32F103RD) +# define FEE_MCU_FLASH_SIZE 384 // Size in Kb +# elif defined(MCU_STM32F303CC) +# define FEE_MCU_FLASH_SIZE 256 // Size in Kb +# else +# error "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)." +# endif +#endif + +#define FEE_XSTR(x) FEE_STR(x) +#define FEE_STR(x) #x + +/* Size of combined compacted eeprom and write log pages */ +#define FEE_DENSITY_MAX_SIZE (FEE_DENSITY_PAGES * FEE_PAGE_SIZE) +/* Addressable range 16KByte: 0 <-> (0x1FFF << 1) */ +#define FEE_ADDRESS_MAX_SIZE 0x4000 + +#ifndef EEPROM_START_ADDRESS /* *TODO: Get rid of this check */ +# if FEE_DENSITY_MAX_SIZE > (FEE_MCU_FLASH_SIZE * 1024) +# pragma message FEE_XSTR(FEE_DENSITY_MAX_SIZE) " > " FEE_XSTR(FEE_MCU_FLASH_SIZE * 1024) +# error emulated eeprom: FEE_DENSITY_PAGES is greater than available flash size +# endif +#endif + +/* Size of emulated eeprom */ +#ifdef FEE_DENSITY_BYTES +# if (FEE_DENSITY_BYTES > FEE_DENSITY_MAX_SIZE) +# pragma message FEE_XSTR(FEE_DENSITY_BYTES) " > " FEE_XSTR(FEE_DENSITY_MAX_SIZE) +# error emulated eeprom: FEE_DENSITY_BYTES exceeds FEE_DENSITY_MAX_SIZE +# endif +# if (FEE_DENSITY_BYTES == FEE_DENSITY_MAX_SIZE) +# pragma message FEE_XSTR(FEE_DENSITY_BYTES) " == " FEE_XSTR(FEE_DENSITY_MAX_SIZE) +# warning emulated eeprom: FEE_DENSITY_BYTES leaves no room for a write log. This will greatly increase the flash wear rate! +# endif +# if FEE_DENSITY_BYTES > FEE_ADDRESS_MAX_SIZE +# pragma message FEE_XSTR(FEE_DENSITY_BYTES) " > " FEE_XSTR(FEE_ADDRESS_MAX_SIZE) +# error emulated eeprom: FEE_DENSITY_BYTES is greater than FEE_ADDRESS_MAX_SIZE allows +# endif +# if ((FEE_DENSITY_BYTES) % 2) == 1 +# error emulated eeprom: FEE_DENSITY_BYTES must be even +# endif +#else +/* Default to half of allocated space used for emulated eeprom, half for write log */ +# define FEE_DENSITY_BYTES (FEE_DENSITY_PAGES * FEE_PAGE_SIZE / 2) +#endif + +/* Size of write log */ +#define FEE_WRITE_LOG_BYTES (FEE_DENSITY_PAGES * FEE_PAGE_SIZE - FEE_DENSITY_BYTES) + +/* Start of the emulated eeprom compacted flash area */ +#ifndef FEE_FLASH_BASE +# define FEE_FLASH_BASE 0x8000000 +#endif +#define FEE_PAGE_BASE_ADDRESS ((uintptr_t)(FEE_FLASH_BASE) + FEE_MCU_FLASH_SIZE * 1024 - FEE_WRITE_LOG_BYTES - FEE_DENSITY_BYTES) +/* End of the emulated eeprom compacted flash area */ +#define FEE_PAGE_LAST_ADDRESS (FEE_PAGE_BASE_ADDRESS + FEE_DENSITY_BYTES) +/* Start of the emulated eeprom write log */ +#define FEE_WRITE_LOG_BASE_ADDRESS FEE_PAGE_LAST_ADDRESS +/* End of the emulated eeprom write log */ +#define FEE_WRITE_LOG_LAST_ADDRESS (FEE_WRITE_LOG_BASE_ADDRESS + FEE_WRITE_LOG_BYTES) + +/* Flash word value after erase */ +#define FEE_EMPTY_WORD ((uint16_t)0xFFFF) + +#if defined(DYNAMIC_KEYMAP_EEPROM_MAX_ADDR) && (DYNAMIC_KEYMAP_EEPROM_MAX_ADDR >= FEE_DENSITY_BYTES) +# error emulated eeprom: DYNAMIC_KEYMAP_EEPROM_MAX_ADDR is greater than the FEE_DENSITY_BYTES available +#endif + +/* In-memory contents of emulated eeprom for faster access */ +/* *TODO: Implement page swapping */ +static uint16_t WordBuf[FEE_DENSITY_BYTES / 2]; +static uint8_t *DataBuf = (uint8_t *)WordBuf; + +/* Pointer to the first available slot within the write log */ +static uint16_t *empty_slot; + +// #define DEBUG_EEPROM_OUTPUT + +/* + * Debug print utils + */ + +#if defined(DEBUG_EEPROM_OUTPUT) + +# define debug_eeprom debug_enable +# define eeprom_println(s) println(s) +# define eeprom_printf(fmt, ...) xprintf(fmt, ##__VA_ARGS__); + +#else /* NO_DEBUG */ + +# define debug_eeprom false +# define eeprom_println(s) +# define eeprom_printf(fmt, ...) + +#endif /* NO_DEBUG */ + +void print_eeprom(void) { +#ifndef NO_DEBUG + int empty_rows = 0; + for (uint16_t i = 0; i < FEE_DENSITY_BYTES; i++) { + if (i % 16 == 0) { + if (i >= FEE_DENSITY_BYTES - 16) { + /* Make sure we display the last row */ + empty_rows = 0; + } + /* Check if this row is uninitialized */ + ++empty_rows; + for (uint16_t j = 0; j < 16; j++) { + if (DataBuf[i + j]) { + empty_rows = 0; + break; + } + } + if (empty_rows > 1) { + /* Repeat empty row */ + if (empty_rows == 2) { + /* Only display the first repeat empty row */ + println("*"); + } + i += 15; + continue; + } + xprintf("%04x", i); + } + if (i % 8 == 0) print(" "); + + xprintf(" %02x", DataBuf[i]); + if ((i + 1) % 16 == 0) { + println(""); + } + } +#endif +} -uint8_t DataBuf[FEE_PAGE_SIZE]; -/***************************************************************************** - * Delete Flash Space used for user Data, deletes the whole space between - * RW_PAGE_BASE_ADDRESS and the last uC Flash Page - ******************************************************************************/ uint16_t EEPROM_Init(void) { - // unlock flash - FLASH_Unlock(); + /* Load emulated eeprom contents from compacted flash into memory */ + uint16_t *src = (uint16_t *)FEE_PAGE_BASE_ADDRESS; + uint16_t *dest = (uint16_t *)DataBuf; + for (; src < (uint16_t *)FEE_PAGE_LAST_ADDRESS; ++src, ++dest) { + *dest = ~*src; + } + + if (debug_eeprom) { + println("EEPROM_Init Compacted Pages:"); + print_eeprom(); + println("EEPROM_Init Write Log:"); + } + + /* Replay write log */ + uint16_t *log_addr; + for (log_addr = (uint16_t *)FEE_WRITE_LOG_BASE_ADDRESS; log_addr < (uint16_t *)FEE_WRITE_LOG_LAST_ADDRESS; ++log_addr) { + uint16_t address = *log_addr; + if (address == FEE_EMPTY_WORD) { + break; + } + /* Check for lowest 128-bytes optimization */ + if (!(address & FEE_WORD_ENCODING)) { + uint8_t bvalue = (uint8_t)address; + address >>= 8; + DataBuf[address] = bvalue; + eeprom_printf("DataBuf[0x%02x] = 0x%02x;\n", address, bvalue); + } else { + uint16_t wvalue; + /* Check if value is in next word */ + if ((address & FEE_VALUE_NEXT) == FEE_VALUE_NEXT) { + /* Read value from next word */ + if (++log_addr >= (uint16_t *)FEE_WRITE_LOG_LAST_ADDRESS) { + break; + } + wvalue = ~*log_addr; + if (!wvalue) { + eeprom_printf("Incomplete write at log_addr: 0x%04x;\n", (uint32_t)log_addr); + /* Possibly incomplete write. Ignore and continue */ + continue; + } + address &= 0x1FFF; + address <<= 1; + /* Writes to addresses less than 128 are byte log entries */ + address += FEE_BYTE_RANGE; + } else { + /* Reserved for future use */ + if (address & FEE_VALUE_RESERVED) { + eeprom_printf("Reserved encoded value at log_addr: 0x%04x;\n", (uint32_t)log_addr); + continue; + } + /* Optimization for 0 or 1 values. */ + wvalue = (address & FEE_VALUE_ENCODED) >> 13; + address &= 0x1FFF; + address <<= 1; + } + if (address < FEE_DENSITY_BYTES) { + eeprom_printf("DataBuf[0x%04x] = 0x%04x;\n", address, wvalue); + *(uint16_t *)(&DataBuf[address]) = wvalue; + } else { + eeprom_printf("DataBuf[0x%04x] cannot be set to 0x%04x [BAD ADDRESS]\n", address, wvalue); + } + } + } - // Clear Flags - // FLASH_ClearFlag(FLASH_SR_EOP|FLASH_SR_PGERR|FLASH_SR_WRPERR); + empty_slot = log_addr; + + if (debug_eeprom) { + println("EEPROM_Init Final DataBuf:"); + print_eeprom(); + } return FEE_DENSITY_BYTES; } -/***************************************************************************** - * Erase the whole reserved Flash Space used for user Data - ******************************************************************************/ -void EEPROM_Erase(void) { - int page_num = 0; - // delete all pages from specified start page to the last page - do { +/* Clear flash contents (doesn't touch in-memory DataBuf) */ +static void eeprom_clear(void) { + FLASH_Unlock(); + + for (uint16_t page_num = 0; page_num < FEE_DENSITY_PAGES; ++page_num) { + eeprom_printf("FLASH_ErasePage(0x%04x)\n", (uint32_t)(FEE_PAGE_BASE_ADDRESS + (page_num * FEE_PAGE_SIZE))); FLASH_ErasePage(FEE_PAGE_BASE_ADDRESS + (page_num * FEE_PAGE_SIZE)); - page_num++; - } while (page_num < FEE_DENSITY_PAGES); + } + + FLASH_Lock(); + + empty_slot = (uint16_t *)FEE_WRITE_LOG_BASE_ADDRESS; + eeprom_printf("eeprom_clear empty_slot: 0x%08x\n", (uint32_t)empty_slot); } -/***************************************************************************** - * Writes once data byte to flash on specified address. If a byte is already - * written, the whole page must be copied to a buffer, the byte changed and - * the manipulated buffer written after PageErase. - *******************************************************************************/ -uint16_t EEPROM_WriteDataByte(uint16_t Address, uint8_t DataByte) { - FLASH_Status FlashStatus = FLASH_COMPLETE; - uint32_t page; - int i; +/* Erase emulated eeprom */ +void EEPROM_Erase(void) { + eeprom_println("EEPROM_Erase"); + /* Erase compacted pages and write log */ + eeprom_clear(); + /* re-initialize to reset DataBuf */ + EEPROM_Init(); +} - // exit if desired address is above the limit (e.G. under 2048 Bytes for 4 pages) - if (Address > FEE_DENSITY_BYTES) { - return 0; +/* Compact write log */ +static uint8_t eeprom_compact(void) { + /* Erase compacted pages and write log */ + eeprom_clear(); + + FLASH_Unlock(); + + FLASH_Status final_status = FLASH_COMPLETE; + + /* Write emulated eeprom contents from memory to compacted flash */ + uint16_t *src = (uint16_t *)DataBuf; + uintptr_t dest = FEE_PAGE_BASE_ADDRESS; + uint16_t value; + for (; dest < FEE_PAGE_LAST_ADDRESS; ++src, dest += 2) { + value = *src; + if (value) { + eeprom_printf("FLASH_ProgramHalfWord(0x%04x, 0x%04x)\n", (uint32_t)dest, ~value); + FLASH_Status status = FLASH_ProgramHalfWord(dest, ~value); + if (status != FLASH_COMPLETE) final_status = status; + } } - // calculate which page is affected (Pagenum1/Pagenum2...PagenumN) - page = FEE_ADDR_OFFSET(Address) / FEE_PAGE_SIZE; + FLASH_Lock(); - // if current data is 0xFF, the byte is empty, just overwrite with the new one - if ((*(__IO uint16_t *)(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address))) == FEE_EMPTY_WORD) { - FlashStatus = FLASH_ProgramHalfWord(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address), (uint16_t)(0x00FF & DataByte)); + if (debug_eeprom) { + println("eeprom_compacted:"); + print_eeprom(); + } + + return final_status; +} + +static uint8_t eeprom_write_direct_entry(uint16_t Address) { + /* Check if we can just write this directly to the compacted flash area */ + uintptr_t directAddress = FEE_PAGE_BASE_ADDRESS + (Address & 0xFFFE); + if (*(uint16_t *)directAddress == FEE_EMPTY_WORD) { + /* Write the value directly to the compacted area without a log entry */ + uint16_t value = ~*(uint16_t *)(&DataBuf[Address & 0xFFFE]); + /* Early exit if a write isn't needed */ + if (value == FEE_EMPTY_WORD) return FLASH_COMPLETE; + + FLASH_Unlock(); + + eeprom_printf("FLASH_ProgramHalfWord(0x%08x, 0x%04x) [DIRECT]\n", (uint32_t)directAddress, value); + FLASH_Status status = FLASH_ProgramHalfWord(directAddress, value); + + FLASH_Lock(); + return status; + } + return 0; +} + +static uint8_t eeprom_write_log_word_entry(uint16_t Address) { + FLASH_Status final_status = FLASH_COMPLETE; + + uint16_t value = *(uint16_t *)(&DataBuf[Address]); + eeprom_printf("eeprom_write_log_word_entry(0x%04x): 0x%04x\n", Address, value); + + /* MSB signifies the lowest 128-byte optimization is not in effect */ + uint16_t encoding = FEE_WORD_ENCODING; + uint8_t entry_size; + if (value <= 1) { + encoding |= value << 13; + entry_size = 2; } else { - // Copy Page to a buffer - memcpy(DataBuf, (uint8_t *)FEE_PAGE_BASE_ADDRESS + (page * FEE_PAGE_SIZE), FEE_PAGE_SIZE); // !!! Calculate base address for the desired page + encoding |= FEE_VALUE_NEXT; + entry_size = 4; + /* Writes to addresses less than 128 are byte log entries */ + Address -= FEE_BYTE_RANGE; + } + + /* if we can't find an empty spot, we must compact emulated eeprom */ + if (empty_slot > (uint16_t *)(FEE_WRITE_LOG_LAST_ADDRESS - entry_size)) { + /* compact the write log into the compacted flash area */ + return eeprom_compact(); + } + + /* Word log writes should be word-aligned. Take back a bit */ + Address >>= 1; + Address |= encoding; + + /* ok we found a place let's write our data */ + FLASH_Unlock(); + + /* address */ + eeprom_printf("FLASH_ProgramHalfWord(0x%08x, 0x%04x)\n", (uint32_t)empty_slot, Address); + final_status = FLASH_ProgramHalfWord((uintptr_t)empty_slot++, Address); + + /* value */ + if (encoding == (FEE_WORD_ENCODING | FEE_VALUE_NEXT)) { + eeprom_printf("FLASH_ProgramHalfWord(0x%08x, 0x%04x)\n", (uint32_t)empty_slot, ~value); + FLASH_Status status = FLASH_ProgramHalfWord((uintptr_t)empty_slot++, ~value); + if (status != FLASH_COMPLETE) final_status = status; + } + + FLASH_Lock(); - // check if new data is differ to current data, return if not, proceed if yes - if (DataByte == *(__IO uint8_t *)(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address))) { - return 0; + return final_status; +} + +static uint8_t eeprom_write_log_byte_entry(uint16_t Address) { + eeprom_printf("eeprom_write_log_byte_entry(0x%04x): 0x%02x\n", Address, DataBuf[Address]); + + /* if couldn't find an empty spot, we must compact emulated eeprom */ + if (empty_slot >= (uint16_t *)FEE_WRITE_LOG_LAST_ADDRESS) { + /* compact the write log into the compacted flash area */ + return eeprom_compact(); + } + + /* ok we found a place let's write our data */ + FLASH_Unlock(); + + /* Pack address and value into the same word */ + uint16_t value = (Address << 8) | DataBuf[Address]; + + /* write to flash */ + eeprom_printf("FLASH_ProgramHalfWord(0x%08x, 0x%04x)\n", (uint32_t)empty_slot, value); + FLASH_Status status = FLASH_ProgramHalfWord((uintptr_t)empty_slot++, value); + + FLASH_Lock(); + + return status; +} + +uint8_t EEPROM_WriteDataByte(uint16_t Address, uint8_t DataByte) { + /* if the address is out-of-bounds, do nothing */ + if (Address >= FEE_DENSITY_BYTES) { + eeprom_printf("EEPROM_WriteDataByte(0x%04x, 0x%02x) [BAD ADDRESS]\n", Address, DataByte); + return FLASH_BAD_ADDRESS; + } + + /* if the value is the same, don't bother writing it */ + if (DataBuf[Address] == DataByte) { + eeprom_printf("EEPROM_WriteDataByte(0x%04x, 0x%02x) [SKIP SAME]\n", Address, DataByte); + return 0; + } + + /* keep DataBuf cache in sync */ + DataBuf[Address] = DataByte; + eeprom_printf("EEPROM_WriteDataByte DataBuf[0x%04x] = 0x%02x\n", Address, DataBuf[Address]); + + /* perform the write into flash memory */ + /* First, attempt to write directly into the compacted flash area */ + FLASH_Status status = eeprom_write_direct_entry(Address); + if (!status) { + /* Otherwise append to the write log */ + if (Address < FEE_BYTE_RANGE) { + status = eeprom_write_log_byte_entry(Address); + } else { + status = eeprom_write_log_word_entry(Address & 0xFFFE); } + } + if (status != 0 && status != FLASH_COMPLETE) { + eeprom_printf("EEPROM_WriteDataByte [STATUS == %d]\n", status); + } + return status; +} - // manipulate desired data byte in temp data array if new byte is differ to the current - DataBuf[FEE_ADDR_OFFSET(Address) % FEE_PAGE_SIZE] = DataByte; +uint8_t EEPROM_WriteDataWord(uint16_t Address, uint16_t DataWord) { + /* if the address is out-of-bounds, do nothing */ + if (Address >= FEE_DENSITY_BYTES) { + eeprom_printf("EEPROM_WriteDataWord(0x%04x, 0x%04x) [BAD ADDRESS]\n", Address, DataWord); + return FLASH_BAD_ADDRESS; + } - // Erase Page - FlashStatus = FLASH_ErasePage(FEE_PAGE_BASE_ADDRESS + (page * FEE_PAGE_SIZE)); + /* Check for word alignment */ + FLASH_Status final_status = FLASH_COMPLETE; + if (Address % 2) { + final_status = EEPROM_WriteDataByte(Address, DataWord); + FLASH_Status status = EEPROM_WriteDataByte(Address + 1, DataWord >> 8); + if (status != FLASH_COMPLETE) final_status = status; + if (final_status != 0 && final_status != FLASH_COMPLETE) { + eeprom_printf("EEPROM_WriteDataWord [STATUS == %d]\n", final_status); + } + return final_status; + } + + /* if the value is the same, don't bother writing it */ + uint16_t oldValue = *(uint16_t *)(&DataBuf[Address]); + if (oldValue == DataWord) { + eeprom_printf("EEPROM_WriteDataWord(0x%04x, 0x%04x) [SKIP SAME]\n", Address, DataWord); + return 0; + } + + /* keep DataBuf cache in sync */ + *(uint16_t *)(&DataBuf[Address]) = DataWord; + eeprom_printf("EEPROM_WriteDataWord DataBuf[0x%04x] = 0x%04x\n", Address, *(uint16_t *)(&DataBuf[Address])); - // Write new data (whole page) to flash if data has been changed - for (i = 0; i < (FEE_PAGE_SIZE / 2); i++) { - if ((__IO uint16_t)(0xFF00 | DataBuf[FEE_ADDR_OFFSET(i)]) != 0xFFFF) { - FlashStatus = FLASH_ProgramHalfWord((FEE_PAGE_BASE_ADDRESS + (page * FEE_PAGE_SIZE)) + (i * 2), (uint16_t)(0xFF00 | DataBuf[FEE_ADDR_OFFSET(i)])); + /* perform the write into flash memory */ + /* First, attempt to write directly into the compacted flash area */ + final_status = eeprom_write_direct_entry(Address); + if (!final_status) { + /* Otherwise append to the write log */ + /* Check if we need to fall back to byte write */ + if (Address < FEE_BYTE_RANGE) { + final_status = FLASH_COMPLETE; + /* Only write a byte if it has changed */ + if ((uint8_t)oldValue != (uint8_t)DataWord) { + final_status = eeprom_write_log_byte_entry(Address); } + FLASH_Status status = FLASH_COMPLETE; + /* Only write a byte if it has changed */ + if ((oldValue >> 8) != (DataWord >> 8)) { + status = eeprom_write_log_byte_entry(Address + 1); + } + if (status != FLASH_COMPLETE) final_status = status; + } else { + final_status = eeprom_write_log_word_entry(Address); } } - return FlashStatus; + if (final_status != 0 && final_status != FLASH_COMPLETE) { + eeprom_printf("EEPROM_WriteDataWord [STATUS == %d]\n", final_status); + } + return final_status; } -/***************************************************************************** - * Read once data byte from a specified address. - *******************************************************************************/ + uint8_t EEPROM_ReadDataByte(uint16_t Address) { uint8_t DataByte = 0xFF; - // Get Byte from specified address - DataByte = (*(__IO uint8_t *)(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address))); + if (Address < FEE_DENSITY_BYTES) { + DataByte = DataBuf[Address]; + } + + eeprom_printf("EEPROM_ReadDataByte(0x%04x): 0x%02x\n", Address, DataByte); return DataByte; } +uint16_t EEPROM_ReadDataWord(uint16_t Address) { + uint16_t DataWord = 0xFFFF; + + if (Address < FEE_DENSITY_BYTES - 1) { + /* Check word alignment */ + if (Address % 2) { + DataWord = DataBuf[Address] | (DataBuf[Address + 1] << 8); + } else { + DataWord = *(uint16_t *)(&DataBuf[Address]); + } + } + + eeprom_printf("EEPROM_ReadDataWord(0x%04x): 0x%04x\n", Address, DataWord); + + return DataWord; +} + /***************************************************************************** * Wrap library in AVR style functions. *******************************************************************************/ -uint8_t eeprom_read_byte(const uint8_t *Address) { - const uint16_t p = (const uint32_t)Address; - return EEPROM_ReadDataByte(p); -} +uint8_t eeprom_read_byte(const uint8_t *Address) { return EEPROM_ReadDataByte((const uintptr_t)Address); } -void eeprom_write_byte(uint8_t *Address, uint8_t Value) { - uint16_t p = (uint32_t)Address; - EEPROM_WriteDataByte(p, Value); -} +void eeprom_write_byte(uint8_t *Address, uint8_t Value) { EEPROM_WriteDataByte((uintptr_t)Address, Value); } -void eeprom_update_byte(uint8_t *Address, uint8_t Value) { - uint16_t p = (uint32_t)Address; - EEPROM_WriteDataByte(p, Value); -} +void eeprom_update_byte(uint8_t *Address, uint8_t Value) { EEPROM_WriteDataByte((uintptr_t)Address, Value); } -uint16_t eeprom_read_word(const uint16_t *Address) { - const uint16_t p = (const uint32_t)Address; - return EEPROM_ReadDataByte(p) | (EEPROM_ReadDataByte(p + 1) << 8); -} +uint16_t eeprom_read_word(const uint16_t *Address) { return EEPROM_ReadDataWord((const uintptr_t)Address); } -void eeprom_write_word(uint16_t *Address, uint16_t Value) { - uint16_t p = (uint32_t)Address; - EEPROM_WriteDataByte(p, (uint8_t)Value); - EEPROM_WriteDataByte(p + 1, (uint8_t)(Value >> 8)); -} +void eeprom_write_word(uint16_t *Address, uint16_t Value) { EEPROM_WriteDataWord((uintptr_t)Address, Value); } -void eeprom_update_word(uint16_t *Address, uint16_t Value) { - uint16_t p = (uint32_t)Address; - EEPROM_WriteDataByte(p, (uint8_t)Value); - EEPROM_WriteDataByte(p + 1, (uint8_t)(Value >> 8)); -} +void eeprom_update_word(uint16_t *Address, uint16_t Value) { EEPROM_WriteDataWord((uintptr_t)Address, Value); } uint32_t eeprom_read_dword(const uint32_t *Address) { - const uint16_t p = (const uint32_t)Address; - return EEPROM_ReadDataByte(p) | (EEPROM_ReadDataByte(p + 1) << 8) | (EEPROM_ReadDataByte(p + 2) << 16) | (EEPROM_ReadDataByte(p + 3) << 24); + const uint16_t p = (const uintptr_t)Address; + /* Check word alignment */ + if (p % 2) { + /* Not aligned */ + return (uint32_t)EEPROM_ReadDataByte(p) | (uint32_t)(EEPROM_ReadDataWord(p + 1) << 8) | (uint32_t)(EEPROM_ReadDataByte(p + 3) << 24); + } else { + /* Aligned */ + return EEPROM_ReadDataWord(p) | (EEPROM_ReadDataWord(p + 2) << 16); + } } void eeprom_write_dword(uint32_t *Address, uint32_t Value) { - uint16_t p = (const uint32_t)Address; - EEPROM_WriteDataByte(p, (uint8_t)Value); - EEPROM_WriteDataByte(p + 1, (uint8_t)(Value >> 8)); - EEPROM_WriteDataByte(p + 2, (uint8_t)(Value >> 16)); - EEPROM_WriteDataByte(p + 3, (uint8_t)(Value >> 24)); -} - -void eeprom_update_dword(uint32_t *Address, uint32_t Value) { - uint16_t p = (const uint32_t)Address; - uint32_t existingValue = EEPROM_ReadDataByte(p) | (EEPROM_ReadDataByte(p + 1) << 8) | (EEPROM_ReadDataByte(p + 2) << 16) | (EEPROM_ReadDataByte(p + 3) << 24); - if (Value != existingValue) { + uint16_t p = (const uintptr_t)Address; + /* Check word alignment */ + if (p % 2) { + /* Not aligned */ EEPROM_WriteDataByte(p, (uint8_t)Value); - EEPROM_WriteDataByte(p + 1, (uint8_t)(Value >> 8)); - EEPROM_WriteDataByte(p + 2, (uint8_t)(Value >> 16)); + EEPROM_WriteDataWord(p + 1, (uint16_t)(Value >> 8)); EEPROM_WriteDataByte(p + 3, (uint8_t)(Value >> 24)); + } else { + /* Aligned */ + EEPROM_WriteDataWord(p, (uint16_t)Value); + EEPROM_WriteDataWord(p + 2, (uint16_t)(Value >> 16)); } } +void eeprom_update_dword(uint32_t *Address, uint32_t Value) { eeprom_write_dword(Address, Value); } + void eeprom_read_block(void *buf, const void *addr, size_t len) { - const uint8_t *p = (const uint8_t *)addr; + const uint8_t *src = (const uint8_t *)addr; uint8_t * dest = (uint8_t *)buf; - while (len--) { - *dest++ = eeprom_read_byte(p++); + + /* Check word alignment */ + if (len && (uintptr_t)src % 2) { + /* Read the unaligned first byte */ + *dest++ = eeprom_read_byte(src++); + --len; + } + + uint16_t value; + bool aligned = ((uintptr_t)dest % 2 == 0); + while (len > 1) { + value = eeprom_read_word((uint16_t *)src); + if (aligned) { + *(uint16_t *)dest = value; + dest += 2; + } else { + *dest++ = value; + *dest++ = value >> 8; + } + src += 2; + len -= 2; + } + if (len) { + *dest = eeprom_read_byte(src); } } void eeprom_write_block(const void *buf, void *addr, size_t len) { - uint8_t * p = (uint8_t *)addr; - const uint8_t *src = (const uint8_t *)buf; - while (len--) { - eeprom_write_byte(p++, *src++); + uint8_t * dest = (uint8_t *)addr; + const uint8_t *src = (const uint8_t *)buf; + + /* Check word alignment */ + if (len && (uintptr_t)dest % 2) { + /* Write the unaligned first byte */ + eeprom_write_byte(dest++, *src++); + --len; } -} -void eeprom_update_block(const void *buf, void *addr, size_t len) { - uint8_t * p = (uint8_t *)addr; - const uint8_t *src = (const uint8_t *)buf; - while (len--) { - eeprom_write_byte(p++, *src++); + uint16_t value; + bool aligned = ((uintptr_t)src % 2 == 0); + while (len > 1) { + if (aligned) { + value = *(uint16_t *)src; + } else { + value = *(uint8_t *)src | (*(uint8_t *)(src + 1) << 8); + } + eeprom_write_word((uint16_t *)dest, value); + dest += 2; + src += 2; + len -= 2; + } + + if (len) { + eeprom_write_byte(dest, *src); } } + +void eeprom_update_block(const void *buf, void *addr, size_t len) { eeprom_write_block(buf, addr, len); } diff --git a/tmk_core/common/chibios/eeprom_stm32.h b/tmk_core/common/chibios/eeprom_stm32.h index 4dac7c1b59..8fcfb556b8 100644 --- a/tmk_core/common/chibios/eeprom_stm32.h +++ b/tmk_core/common/chibios/eeprom_stm32.h @@ -23,62 +23,11 @@ #pragma once -#include -#include -#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 -#elif defined(EEPROM_EMU_STM32F072xB) -# define MCU_STM32F072CB -#elif defined(EEPROM_EMU_STM32F042x6) -# define MCU_STM32F042K6 -#else -# error "not implemented." -#endif - -#ifndef EEPROM_PAGE_SIZE -# if defined(MCU_STM32F103RB) || defined(MCU_STM32F042K6) -# define FEE_PAGE_SIZE (uint16_t)0x400 // Page size = 1KByte -# define FEE_DENSITY_PAGES 2 // How many pages are used -# elif defined(MCU_STM32F103ZE) || defined(MCU_STM32F103RE) || defined(MCU_STM32F103RD) || defined(MCU_STM32F303CC) || defined(MCU_STM32F072CB) -# define FEE_PAGE_SIZE (uint16_t)0x800 // Page size = 2KByte -# define FEE_DENSITY_PAGES 4 // How many pages are used -# 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) || defined(MCU_STM32F072CB) -# define FEE_MCU_FLASH_SIZE 128 // Size in Kb -# elif defined(MCU_STM32F042K6) -# define FEE_MCU_FLASH_SIZE 32 // Size in Kb -# elif defined(MCU_STM32F103ZE) || defined(MCU_STM32F103RE) -# define FEE_MCU_FLASH_SIZE 512 // Size in Kb -# elif defined(MCU_STM32F103RD) -# define FEE_MCU_FLASH_SIZE 384 // Size in Kb -# elif defined(MCU_STM32F303CC) -# define FEE_MCU_FLASH_SIZE 256 // Size in Kb -# else -# error "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)." -# endif -#endif - -// DONT CHANGE -// Choose location for the first EEPROM Page address on the top of flash -#define FEE_PAGE_BASE_ADDRESS ((uint32_t)(0x8000000 + FEE_MCU_FLASH_SIZE * 1024 - FEE_DENSITY_PAGES * FEE_PAGE_SIZE)) -#define FEE_DENSITY_BYTES ((FEE_PAGE_SIZE / 2) * FEE_DENSITY_PAGES - 1) -#define FEE_LAST_PAGE_ADDRESS (FEE_PAGE_BASE_ADDRESS + (FEE_PAGE_SIZE * FEE_DENSITY_PAGES)) -#define FEE_EMPTY_WORD ((uint16_t)0xFFFF) -#define FEE_ADDR_OFFSET(Address) (Address * 2) // 1Byte per Word will be saved to preserve Flash - -// Use this function to initialize the functionality uint16_t EEPROM_Init(void); void EEPROM_Erase(void); -uint16_t EEPROM_WriteDataByte(uint16_t Address, uint8_t DataByte); +uint8_t EEPROM_WriteDataByte(uint16_t Address, uint8_t DataByte); +uint8_t EEPROM_WriteDataWord(uint16_t Address, uint16_t DataWord); uint8_t EEPROM_ReadDataByte(uint16_t Address); +uint16_t EEPROM_ReadDataWord(uint16_t Address); + +void print_eeprom(void); diff --git a/tmk_core/common/chibios/flash_stm32.h b/tmk_core/common/chibios/flash_stm32.h index 90d5bff47e..9c6a7cc50f 100644 --- a/tmk_core/common/chibios/flash_stm32.h +++ b/tmk_core/common/chibios/flash_stm32.h @@ -22,8 +22,11 @@ extern "C" { #endif -#include -#include +#include + +#ifdef FLASH_STM32_MOCKED +extern uint8_t FlashBuf[MOCK_FLASH_SIZE]; +#endif typedef enum { FLASH_BUSY = 1, FLASH_ERROR_PG, FLASH_ERROR_WRP, FLASH_ERROR_OPT, FLASH_COMPLETE, FLASH_TIMEOUT, FLASH_BAD_ADDRESS } FLASH_Status; diff --git a/tmk_core/common/test/eeprom_stm32_tests.cpp b/tmk_core/common/test/eeprom_stm32_tests.cpp new file mode 100644 index 0000000000..aa84492b87 --- /dev/null +++ b/tmk_core/common/test/eeprom_stm32_tests.cpp @@ -0,0 +1,438 @@ +/* Copyright 2021 by Don Kjer + * + * 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 . + */ + +#include "gtest/gtest.h" + +extern "C" { +#include "flash_stm32.h" +#include "eeprom_stm32.h" +#include "eeprom.h" +} + +/* Mock Flash Parameters: + * + * === Large Layout === + * flash size: 65536 + * page size: 2048 + * density pages: 16 + * Simulated EEPROM size: 16384 + * + * FlashBuf Layout: + * [Unused | Compact | Write Log ] + * [0......|32768......|49152......65535] + * + * === Tiny Layout === + * flash size: 1024 + * page size: 512 + * density pages: 1 + * Simulated EEPROM size: 256 + * + * FlashBuf Layout: + * [Unused | Compact | Write Log ] + * [0......|512......|768......1023] + * + */ + +#define EEPROM_SIZE (FEE_PAGE_SIZE * FEE_DENSITY_PAGES / 2) +#define LOG_SIZE EEPROM_SIZE +#define LOG_BASE (MOCK_FLASH_SIZE - LOG_SIZE) +#define EEPROM_BASE (LOG_BASE - EEPROM_SIZE) + +/* Log encoding helpers */ +#define BYTE_VALUE(addr, value) (((addr) << 8) | (value)) +#define WORD_ZERO(addr) (0x8000 | ((addr) >> 1)) +#define WORD_ONE(addr) (0xA000 | ((addr) >> 1)) +#define WORD_NEXT(addr) (0xE000 | (((addr)-0x80) >> 1)) + +class EepromStm32Test : public testing::Test { + public: + EepromStm32Test() {} + ~EepromStm32Test() {} + + protected: + void SetUp() override { EEPROM_Erase(); } + + void TearDown() override { +#ifdef EEPROM_DEBUG + dumpEepromDataBuf(); +#endif + } +}; + +TEST_F(EepromStm32Test, TestErase) { + EEPROM_WriteDataByte(0, 0x42); + EEPROM_Erase(); + EXPECT_EQ(EEPROM_ReadDataByte(0), 0); + EXPECT_EQ(EEPROM_ReadDataByte(1), 0); +} + +TEST_F(EepromStm32Test, TestReadGarbage) { + uint8_t garbage = 0x3c; + for (int i = 0; i < MOCK_FLASH_SIZE; ++i) { + garbage ^= 0xa3; + garbage += i; + FlashBuf[i] = garbage; + } + EEPROM_Init(); // Just verify we don't crash +} + +TEST_F(EepromStm32Test, TestWriteBadAddress) { + EXPECT_EQ(EEPROM_WriteDataByte(EEPROM_SIZE, 0x42), FLASH_BAD_ADDRESS); + EXPECT_EQ(EEPROM_WriteDataWord(EEPROM_SIZE - 1, 0xbeef), FLASH_BAD_ADDRESS); + EXPECT_EQ(EEPROM_WriteDataWord(EEPROM_SIZE, 0xbeef), FLASH_BAD_ADDRESS); +} + +TEST_F(EepromStm32Test, TestReadBadAddress) { + EXPECT_EQ(EEPROM_ReadDataByte(EEPROM_SIZE), 0xFF); + EXPECT_EQ(EEPROM_ReadDataWord(EEPROM_SIZE - 1), 0xFFFF); + EXPECT_EQ(EEPROM_ReadDataWord(EEPROM_SIZE), 0xFFFF); + EXPECT_EQ(eeprom_read_dword((uint32_t*)(EEPROM_SIZE - 4)), 0); + EXPECT_EQ(eeprom_read_dword((uint32_t*)(EEPROM_SIZE - 3)), 0xFF000000); + EXPECT_EQ(eeprom_read_dword((uint32_t*)EEPROM_SIZE), 0xFFFFFFFF); +} + +TEST_F(EepromStm32Test, TestReadByte) { + /* Direct compacted-area baseline: Address < 0x80 */ + FlashBuf[EEPROM_BASE + 2] = ~0xef; + FlashBuf[EEPROM_BASE + 3] = ~0xbe; + /* Direct compacted-area baseline: Address >= 0x80 */ + FlashBuf[EEPROM_BASE + EEPROM_SIZE - 2] = ~0x78; + FlashBuf[EEPROM_BASE + EEPROM_SIZE - 1] = ~0x56; + /* Check values */ + EEPROM_Init(); + EXPECT_EQ(EEPROM_ReadDataByte(2), 0xef); + EXPECT_EQ(EEPROM_ReadDataByte(3), 0xbe); + EXPECT_EQ(EEPROM_ReadDataByte(EEPROM_SIZE - 2), 0x78); + EXPECT_EQ(EEPROM_ReadDataByte(EEPROM_SIZE - 1), 0x56); + /* Write Log byte value */ + FlashBuf[LOG_BASE] = 0x65; + FlashBuf[LOG_BASE + 1] = 3; + /* Write Log word value */ + *(uint16_t*)&FlashBuf[LOG_BASE + 2] = WORD_NEXT(EEPROM_SIZE - 2); + *(uint16_t*)&FlashBuf[LOG_BASE + 4] = ~0x9abc; + /* Check values */ + EEPROM_Init(); + EXPECT_EQ(EEPROM_ReadDataByte(2), 0xef); + EXPECT_EQ(EEPROM_ReadDataByte(3), 0x65); + EXPECT_EQ(EEPROM_ReadDataByte(EEPROM_SIZE - 2), 0xbc); + EXPECT_EQ(EEPROM_ReadDataByte(EEPROM_SIZE - 1), 0x9a); +} + +TEST_F(EepromStm32Test, TestWriteByte) { + /* Direct compacted-area baseline: Address < 0x80 */ + EEPROM_WriteDataByte(2, 0xef); + EEPROM_WriteDataByte(3, 0xbe); + /* Direct compacted-area baseline: Address >= 0x80 */ + EEPROM_WriteDataByte(EEPROM_SIZE - 2, 0x78); + EEPROM_WriteDataByte(EEPROM_SIZE - 1, 0x56); + /* Check values */ + /* First write in each aligned word should have been direct */ + EXPECT_EQ(FlashBuf[EEPROM_BASE + 2], (uint8_t)~0xef); + EXPECT_EQ(FlashBuf[EEPROM_BASE + EEPROM_SIZE - 2], (uint8_t)~0x78); + + /* Second write per aligned word requires a log entry */ + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE], BYTE_VALUE(3, 0xbe)); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 2], WORD_NEXT(EEPROM_SIZE - 1)); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 4], (uint16_t)~0x5678); +} + +TEST_F(EepromStm32Test, TestByteRoundTrip) { + /* Direct compacted-area: Address < 0x80 */ + EEPROM_WriteDataWord(0, 0xdead); + EEPROM_WriteDataByte(2, 0xef); + EEPROM_WriteDataByte(3, 0xbe); + /* Direct compacted-area: Address >= 0x80 */ + EEPROM_WriteDataByte(EEPROM_SIZE - 2, 0x78); + EEPROM_WriteDataByte(EEPROM_SIZE - 1, 0x56); + /* Check values */ + EEPROM_Init(); + EXPECT_EQ(EEPROM_ReadDataByte(0), 0xad); + EXPECT_EQ(EEPROM_ReadDataByte(1), 0xde); + EXPECT_EQ(EEPROM_ReadDataByte(2), 0xef); + EXPECT_EQ(EEPROM_ReadDataByte(3), 0xbe); + EXPECT_EQ(EEPROM_ReadDataByte(EEPROM_SIZE - 2), 0x78); + EXPECT_EQ(EEPROM_ReadDataByte(EEPROM_SIZE - 1), 0x56); + /* Write log entries */ + EEPROM_WriteDataByte(2, 0x80); + EEPROM_WriteDataByte(EEPROM_SIZE - 2, 0x3c); + /* Check values */ + EEPROM_Init(); + EXPECT_EQ(EEPROM_ReadDataByte(2), 0x80); + EXPECT_EQ(EEPROM_ReadDataByte(3), 0xbe); + EXPECT_EQ(EEPROM_ReadDataByte(EEPROM_SIZE - 2), 0x3c); + EXPECT_EQ(EEPROM_ReadDataByte(EEPROM_SIZE - 1), 0x56); +} + +TEST_F(EepromStm32Test, TestReadWord) { + /* Direct compacted-area baseline: Address < 0x80 */ + FlashBuf[EEPROM_BASE + 0] = ~0xad; + FlashBuf[EEPROM_BASE + 1] = ~0xde; + /* Direct compacted-area baseline: Address >= 0x80 */ + FlashBuf[EEPROM_BASE + 200] = ~0xcd; + FlashBuf[EEPROM_BASE + 201] = ~0xab; + FlashBuf[EEPROM_BASE + EEPROM_SIZE - 4] = ~0x34; + FlashBuf[EEPROM_BASE + EEPROM_SIZE - 3] = ~0x12; + FlashBuf[EEPROM_BASE + EEPROM_SIZE - 2] = ~0x78; + FlashBuf[EEPROM_BASE + EEPROM_SIZE - 1] = ~0x56; + /* Check values */ + EEPROM_Init(); + EXPECT_EQ(EEPROM_ReadDataWord(0), 0xdead); + EXPECT_EQ(EEPROM_ReadDataWord(200), 0xabcd); + EXPECT_EQ(EEPROM_ReadDataWord(EEPROM_SIZE - 4), 0x1234); + EXPECT_EQ(EEPROM_ReadDataWord(EEPROM_SIZE - 2), 0x5678); + /* Write Log word zero-encoded */ + *(uint16_t*)&FlashBuf[LOG_BASE] = WORD_ZERO(200); + /* Write Log word one-encoded */ + *(uint16_t*)&FlashBuf[LOG_BASE + 2] = WORD_ONE(EEPROM_SIZE - 4); + /* Write Log word value */ + *(uint16_t*)&FlashBuf[LOG_BASE + 4] = WORD_NEXT(EEPROM_SIZE - 2); + *(uint16_t*)&FlashBuf[LOG_BASE + 6] = ~0x9abc; + /* Check values */ + EEPROM_Init(); + EXPECT_EQ(EEPROM_ReadDataWord(200), 0); + EXPECT_EQ(EEPROM_ReadDataWord(EEPROM_SIZE - 4), 1); + EXPECT_EQ(EEPROM_ReadDataWord(EEPROM_SIZE - 2), 0x9abc); +} + +TEST_F(EepromStm32Test, TestWriteWord) { + /* Direct compacted-area: Address < 0x80 */ + EEPROM_WriteDataWord(0, 0xdead); // Aligned + EEPROM_WriteDataWord(3, 0xbeef); // Unaligned + /* Direct compacted-area: Address >= 0x80 */ + EEPROM_WriteDataWord(200, 0xabcd); // Aligned + EEPROM_WriteDataWord(203, 0x9876); // Unaligned + EEPROM_WriteDataWord(EEPROM_SIZE - 4, 0x1234); + EEPROM_WriteDataWord(EEPROM_SIZE - 2, 0x5678); + /* Write Log word zero-encoded */ + EEPROM_WriteDataWord(EEPROM_SIZE - 4, 0); + /* Write Log word one-encoded */ + EEPROM_WriteDataWord(EEPROM_SIZE - 2, 1); + /* Write Log word value aligned */ + EEPROM_WriteDataWord(200, 0x4321); // Aligned + /* Write Log word value unaligned */ + EEPROM_WriteDataByte(202, 0x3c); // Set neighboring byte + EEPROM_WriteDataWord(203, 0xcdef); // Unaligned + /* Check values */ + /* Direct compacted-area */ + EXPECT_EQ(*(uint16_t*)&FlashBuf[EEPROM_BASE], (uint16_t)~0xdead); + EXPECT_EQ(*(uint16_t*)&FlashBuf[EEPROM_BASE + 3], (uint16_t)~0xbeef); + EXPECT_EQ(*(uint16_t*)&FlashBuf[EEPROM_BASE + 200], (uint16_t)~0xabcd); + EXPECT_EQ(FlashBuf[EEPROM_BASE + 203], (uint8_t)~0x76); + EXPECT_EQ(FlashBuf[EEPROM_BASE + 204], (uint8_t)~0x98); + EXPECT_EQ(*(uint16_t*)&FlashBuf[EEPROM_BASE + EEPROM_SIZE - 4], (uint16_t)~0x1234); + EXPECT_EQ(*(uint16_t*)&FlashBuf[EEPROM_BASE + EEPROM_SIZE - 2], (uint16_t)~0x5678); + /* Write Log word zero-encoded */ + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE], WORD_ZERO(EEPROM_SIZE - 4)); + /* Write Log word one-encoded */ + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 2], WORD_ONE(EEPROM_SIZE - 2)); + /* Write Log word value aligned */ + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 4], WORD_NEXT(200)); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 6], (uint16_t)~0x4321); + /* Write Log word value unaligned */ + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 8], WORD_NEXT(202)); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 10], (uint16_t)~0x763c); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 12], WORD_NEXT(202)); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 14], (uint16_t)~0xef3c); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 16], WORD_NEXT(204)); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 18], (uint16_t)~0x00cd); +} + +TEST_F(EepromStm32Test, TestWordRoundTrip) { + /* Direct compacted-area: Address < 0x80 */ + EEPROM_WriteDataWord(0, 0xdead); // Aligned + EEPROM_WriteDataWord(3, 0xbeef); // Unaligned + /* Direct compacted-area: Address >= 0x80 */ + EEPROM_WriteDataWord(200, 0xabcd); // Aligned + EEPROM_WriteDataWord(203, 0x9876); // Unaligned + EEPROM_WriteDataWord(EEPROM_SIZE - 4, 0x1234); + EEPROM_WriteDataWord(EEPROM_SIZE - 2, 0x5678); + /* Check values */ + EEPROM_Init(); + EXPECT_EQ(EEPROM_ReadDataWord(0), 0xdead); + EXPECT_EQ(EEPROM_ReadDataWord(3), 0xbeef); + EXPECT_EQ(EEPROM_ReadDataWord(200), 0xabcd); + EXPECT_EQ(EEPROM_ReadDataWord(203), 0x9876); + EXPECT_EQ(EEPROM_ReadDataWord(EEPROM_SIZE - 4), 0x1234); + EXPECT_EQ(EEPROM_ReadDataWord(EEPROM_SIZE - 2), 0x5678); + + /* Write Log word zero-encoded */ + EEPROM_WriteDataWord(EEPROM_SIZE - 4, 0); + /* Write Log word one-encoded */ + EEPROM_WriteDataWord(EEPROM_SIZE - 2, 1); + /* Write Log word value aligned */ + EEPROM_WriteDataWord(200, 0x4321); // Aligned + /* Write Log word value unaligned */ + EEPROM_WriteDataByte(202, 0x3c); // Set neighboring byte + EEPROM_WriteDataWord(203, 0xcdef); // Unaligned + /* Check values */ + EEPROM_Init(); + EXPECT_EQ(EEPROM_ReadDataWord(200), 0x4321); + EXPECT_EQ(EEPROM_ReadDataByte(202), 0x3c); + EXPECT_EQ(EEPROM_ReadDataWord(203), 0xcdef); + EXPECT_EQ(EEPROM_ReadDataWord(EEPROM_SIZE - 4), 0); + EXPECT_EQ(EEPROM_ReadDataWord(EEPROM_SIZE - 2), 1); +} + +TEST_F(EepromStm32Test, TestByteWordBoundary) { + /* Direct compacted-area write */ + EEPROM_WriteDataWord(0x7e, 0xdead); + EEPROM_WriteDataWord(0x80, 0xbeef); + /* Byte log entry */ + EEPROM_WriteDataByte(0x7f, 0x3c); + /* Word log entry */ + EEPROM_WriteDataByte(0x80, 0x18); + /* Check values */ + EEPROM_Init(); + EXPECT_EQ(EEPROM_ReadDataWord(0x7e), 0x3cad); + EXPECT_EQ(EEPROM_ReadDataWord(0x80), 0xbe18); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE], BYTE_VALUE(0x7f, 0x3c)); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 2], WORD_NEXT(0x80)); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 4], (uint16_t)~0xbe18); + /* Byte log entries */ + EEPROM_WriteDataWord(0x7e, 0xcafe); + /* Check values */ + EEPROM_Init(); + EXPECT_EQ(EEPROM_ReadDataWord(0x7e), 0xcafe); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 6], BYTE_VALUE(0x7e, 0xfe)); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 8], BYTE_VALUE(0x7f, 0xca)); + /* Byte and Word log entries */ + EEPROM_WriteDataWord(0x7f, 0xba5e); + /* Check values */ + EEPROM_Init(); + EXPECT_EQ(EEPROM_ReadDataWord(0x7f), 0xba5e); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 10], BYTE_VALUE(0x7f, 0x5e)); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 12], WORD_NEXT(0x80)); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 14], (uint16_t)~0xbeba); + /* Word log entry */ + EEPROM_WriteDataWord(0x80, 0xf00d); + /* Check values */ + EEPROM_Init(); + EXPECT_EQ(EEPROM_ReadDataWord(0x80), 0xf00d); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 16], WORD_NEXT(0x80)); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + 18], (uint16_t)~0xf00d); +} + +TEST_F(EepromStm32Test, TestDWordRoundTrip) { + /* Direct compacted-area: Address < 0x80 */ + eeprom_write_dword((uint32_t*)0, 0xdeadbeef); // Aligned + eeprom_write_dword((uint32_t*)9, 0x12345678); // Unaligned + /* Direct compacted-area: Address >= 0x80 */ + eeprom_write_dword((uint32_t*)200, 0xfacef00d); + eeprom_write_dword((uint32_t*)(EEPROM_SIZE - 4), 0xba5eba11); // Aligned + eeprom_write_dword((uint32_t*)(EEPROM_SIZE - 9), 0xcafed00d); // Unaligned + /* Check direct values */ + EEPROM_Init(); + EXPECT_EQ(eeprom_read_dword((uint32_t*)0), 0xdeadbeef); + EXPECT_EQ(eeprom_read_dword((uint32_t*)9), 0x12345678); + EXPECT_EQ(eeprom_read_dword((uint32_t*)200), 0xfacef00d); + EXPECT_EQ(eeprom_read_dword((uint32_t*)(EEPROM_SIZE - 4)), 0xba5eba11); // Aligned + EXPECT_EQ(eeprom_read_dword((uint32_t*)(EEPROM_SIZE - 9)), 0xcafed00d); // Unaligned + /* Write Log byte encoded */ + eeprom_write_dword((uint32_t*)0, 0xdecafbad); + eeprom_write_dword((uint32_t*)9, 0x87654321); + /* Write Log word encoded */ + eeprom_write_dword((uint32_t*)200, 1); + /* Write Log word value aligned */ + eeprom_write_dword((uint32_t*)(EEPROM_SIZE - 4), 0xdeadc0de); // Aligned + eeprom_write_dword((uint32_t*)(EEPROM_SIZE - 9), 0x6789abcd); // Unaligned + /* Check log values */ + EEPROM_Init(); + EXPECT_EQ(eeprom_read_dword((uint32_t*)0), 0xdecafbad); + EXPECT_EQ(eeprom_read_dword((uint32_t*)9), 0x87654321); + EXPECT_EQ(eeprom_read_dword((uint32_t*)200), 1); + EXPECT_EQ(eeprom_read_dword((uint32_t*)(EEPROM_SIZE - 4)), 0xdeadc0de); // Aligned + EXPECT_EQ(eeprom_read_dword((uint32_t*)(EEPROM_SIZE - 9)), 0x6789abcd); // Unaligned +} + +TEST_F(EepromStm32Test, TestBlockRoundTrip) { + char src0[] = "0123456789abcdef"; + void* src1 = (void*)&src0[1]; + /* Various alignments of src & dst, Address < 0x80 */ + eeprom_write_block(src0, (void*)0, sizeof(src0)); + eeprom_write_block(src0, (void*)21, sizeof(src0)); + eeprom_write_block(src1, (void*)40, sizeof(src0) - 1); + eeprom_write_block(src1, (void*)61, sizeof(src0) - 1); + /* Various alignments of src & dst, Address >= 0x80 */ + eeprom_write_block(src0, (void*)140, sizeof(src0)); + eeprom_write_block(src0, (void*)161, sizeof(src0)); + eeprom_write_block(src1, (void*)180, sizeof(src0) - 1); + eeprom_write_block(src1, (void*)201, sizeof(src0) - 1); + + /* Check values */ + EEPROM_Init(); + + char dstBuf[256] = {0}; + char* dst0a = (char*)dstBuf; + char* dst0b = (char*)&dstBuf[20]; + char* dst1a = (char*)&dstBuf[41]; + char* dst1b = (char*)&dstBuf[61]; + char* dst0c = (char*)&dstBuf[80]; + char* dst0d = (char*)&dstBuf[100]; + char* dst1c = (char*)&dstBuf[121]; + char* dst1d = (char*)&dstBuf[141]; + eeprom_read_block((void*)dst0a, (void*)0, sizeof(src0)); + eeprom_read_block((void*)dst0b, (void*)21, sizeof(src0)); + eeprom_read_block((void*)dst1a, (void*)40, sizeof(src0) - 1); + eeprom_read_block((void*)dst1b, (void*)61, sizeof(src0) - 1); + eeprom_read_block((void*)dst0c, (void*)140, sizeof(src0)); + eeprom_read_block((void*)dst0d, (void*)161, sizeof(src0)); + eeprom_read_block((void*)dst1c, (void*)180, sizeof(src0) - 1); + eeprom_read_block((void*)dst1d, (void*)201, sizeof(src0) - 1); + EXPECT_EQ(strcmp((char*)src0, dst0a), 0); + EXPECT_EQ(strcmp((char*)src0, dst0b), 0); + EXPECT_EQ(strcmp((char*)src0, dst0c), 0); + EXPECT_EQ(strcmp((char*)src0, dst0d), 0); + EXPECT_EQ(strcmp((char*)src1, dst1a), 0); + EXPECT_EQ(strcmp((char*)src1, dst1b), 0); + EXPECT_EQ(strcmp((char*)src1, dst1c), 0); + EXPECT_EQ(strcmp((char*)src1, dst1d), 0); +} + +TEST_F(EepromStm32Test, TestCompaction) { + /* Direct writes */ + eeprom_write_dword((uint32_t*)0, 0xdeadbeef); + eeprom_write_byte((uint8_t*)4, 0x3c); + eeprom_write_word((uint16_t*)6, 0xd00d); + eeprom_write_dword((uint32_t*)150, 0xcafef00d); + eeprom_write_dword((uint32_t*)200, 0x12345678); + /* Fill write log entries */ + uint32_t i; + uint32_t val = 0xd8453c6b; + for (i = 0; i < (LOG_SIZE / (sizeof(uint32_t) * 2)); i++) { + val ^= 0x593ca5b3; + val += i; + eeprom_write_dword((uint32_t*)200, val); + } + /* Check values pre-compaction */ + EEPROM_Init(); + EXPECT_EQ(eeprom_read_dword((uint32_t*)0), 0xdeadbeef); + EXPECT_EQ(eeprom_read_byte((uint8_t*)4), 0x3c); + EXPECT_EQ(eeprom_read_word((uint16_t*)6), 0xd00d); + EXPECT_EQ(eeprom_read_dword((uint32_t*)150), 0xcafef00d); + EXPECT_EQ(eeprom_read_dword((uint32_t*)200), val); + EXPECT_NE(*(uint16_t*)&FlashBuf[LOG_BASE], 0xFFFF); + EXPECT_NE(*(uint16_t*)&FlashBuf[LOG_BASE + LOG_SIZE - 2], 0xFFFF); + /* Run compaction */ + eeprom_write_byte((uint8_t*)4, 0x1f); + EEPROM_Init(); + EXPECT_EQ(eeprom_read_dword((uint32_t*)0), 0xdeadbeef); + EXPECT_EQ(eeprom_read_byte((uint8_t*)4), 0x1f); + EXPECT_EQ(eeprom_read_word((uint16_t*)6), 0xd00d); + EXPECT_EQ(eeprom_read_dword((uint32_t*)150), 0xcafef00d); + EXPECT_EQ(eeprom_read_dword((uint32_t*)200), val); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE], 0xFFFF); + EXPECT_EQ(*(uint16_t*)&FlashBuf[LOG_BASE + LOG_SIZE - 2], 0xFFFF); +} diff --git a/tmk_core/common/test/flash_stm32_mock.c b/tmk_core/common/test/flash_stm32_mock.c new file mode 100644 index 0000000000..1b81d81f9a --- /dev/null +++ b/tmk_core/common/test/flash_stm32_mock.c @@ -0,0 +1,50 @@ +/* Copyright 2021 by Don Kjer + * + * 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 . + */ + +#include +#include +#include "flash_stm32.h" + +uint8_t FlashBuf[MOCK_FLASH_SIZE] = {0}; + +static bool flash_locked = true; + +FLASH_Status FLASH_ErasePage(uint32_t Page_Address) { + if (flash_locked) return FLASH_ERROR_WRP; + Page_Address -= (uintptr_t)FlashBuf; + Page_Address -= (Page_Address % FEE_PAGE_SIZE); + if (Page_Address >= MOCK_FLASH_SIZE) return FLASH_BAD_ADDRESS; + memset(&FlashBuf[Page_Address], '\xff', FEE_PAGE_SIZE); + return FLASH_COMPLETE; +} + +FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data) { + if (flash_locked) return FLASH_ERROR_WRP; + Address -= (uintptr_t)FlashBuf; + if (Address >= MOCK_FLASH_SIZE) return FLASH_BAD_ADDRESS; + uint16_t oldData = *(uint16_t*)&FlashBuf[Address]; + if (oldData == 0xFFFF || Data == 0) { + *(uint16_t*)&FlashBuf[Address] = Data; + return FLASH_COMPLETE; + } else { + return FLASH_ERROR_PG; + } +} + +FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout) { return FLASH_COMPLETE; } +void FLASH_Unlock(void) { flash_locked = false; } +void FLASH_Lock(void) { flash_locked = true; } +void FLASH_ClearFlag(uint32_t FLASH_FLAG) {} diff --git a/tmk_core/common/test/rules.mk b/tmk_core/common/test/rules.mk new file mode 100644 index 0000000000..e47e5880c5 --- /dev/null +++ b/tmk_core/common/test/rules.mk @@ -0,0 +1,23 @@ +eeprom_stm32_DEFS := -DFLASH_STM32_MOCKED -DNO_PRINT -DFEE_FLASH_BASE=FlashBuf +eeprom_stm32_tiny_DEFS := $(eeprom_stm32_DEFS) \ + -DFEE_MCU_FLASH_SIZE=1 \ + -DMOCK_FLASH_SIZE=1024 \ + -DFEE_PAGE_SIZE=512 \ + -DFEE_DENSITY_PAGES=1 +eeprom_stm32_large_DEFS := $(eeprom_stm32_DEFS) \ + -DFEE_MCU_FLASH_SIZE=64 \ + -DMOCK_FLASH_SIZE=65536 \ + -DFEE_PAGE_SIZE=2048 \ + -DFEE_DENSITY_PAGES=16 + +eeprom_stm32_INC := \ + $(TMK_PATH)/common/chibios/ +eeprom_stm32_tiny_INC := $(eeprom_stm32_INC) +eeprom_stm32_large_INC := $(eeprom_stm32_INC) + +eeprom_stm32_SRC := \ + $(TMK_PATH)/common/test/eeprom_stm32_tests.cpp \ + $(TMK_PATH)/common/test/flash_stm32_mock.c \ + $(TMK_PATH)/common/chibios/eeprom_stm32.c +eeprom_stm32_tiny_SRC := $(eeprom_stm32_SRC) +eeprom_stm32_large_SRC := $(eeprom_stm32_SRC) diff --git a/tmk_core/common/test/testlist.mk b/tmk_core/common/test/testlist.mk new file mode 100644 index 0000000000..51a9638bb9 --- /dev/null +++ b/tmk_core/common/test/testlist.mk @@ -0,0 +1 @@ +TEST_LIST += eeprom_stm32_tiny eeprom_stm32_large diff --git a/util/stm32eeprom_parser.py b/util/stm32eeprom_parser.py new file mode 100755 index 0000000000..b124f713d5 --- /dev/null +++ b/util/stm32eeprom_parser.py @@ -0,0 +1,317 @@ +#!/usr/bin/env python +# +# Copyright 2021 Don Kjer +# +# 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 . +# + +from __future__ import print_function + +import argparse +from struct import pack, unpack +import os, sys + +MAGIC_FEEA = '\xea\xff\xfe\xff' + +MAGIC_FEE9 = '\x16\x01' +EMPTY_WORD = '\xff\xff' +WORD_ENCODING = 0x8000 +VALUE_NEXT = 0x6000 +VALUE_RESERVED = 0x4000 +VALUE_ENCODED = 0x2000 +BYTE_RANGE = 0x80 + +CHUNK_SIZE = 1024 + +STRUCT_FMTS = { + 1: 'B', + 2: 'H', + 4: 'I' +} +PRINTABLE='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ ' + +EECONFIG_V1 = [ + ("MAGIC", 0, 2), + ("DEBUG", 2, 1), + ("DEFAULT_LAYER", 3, 1), + ("KEYMAP", 4, 1), + ("MOUSEKEY_ACCEL", 5, 1), + ("BACKLIGHT", 6, 1), + ("AUDIO", 7, 1), + ("RGBLIGHT", 8, 4), + ("UNICODEMODE", 12, 1), + ("STENOMODE", 13, 1), + ("HANDEDNESS", 14, 1), + ("KEYBOARD", 15, 4), + ("USER", 19, 4), + ("VELOCIKEY", 23, 1), + ("HAPTIC", 24, 4), + ("MATRIX", 28, 4), + ("MATRIX_EXTENDED", 32, 2), + ("KEYMAP_UPPER_BYTE", 34, 1), +] +VIABASE_V1 = 35 + +VERBOSE = False + +def parseArgs(): + parser = argparse.ArgumentParser(description='Decode an STM32 emulated eeprom dump') + parser.add_argument('-s', '--size', type=int, + help='Size of the emulated eeprom (default: input_size / 2)') + parser.add_argument('-o', '--output', help='File to write decoded eeprom to') + parser.add_argument('-y', '--layout-options-size', type=int, + help='VIA layout options size (default: 1)', default=1) + parser.add_argument('-t', '--custom-config-size', type=int, + help='VIA custom config size (default: 0)', default=0) + parser.add_argument('-l', '--layers', type=int, + help='VIA keyboard layers (default: 4)', default=4) + parser.add_argument('-r', '--rows', type=int, help='VIA matrix rows') + parser.add_argument('-c', '--cols', type=int, help='VIA matrix columns') + parser.add_argument('-m', '--macros', type=int, + help='VIA macro count (default: 16)', default=16) + parser.add_argument('-C', '--canonical', action='store_true', + help='Canonical hex+ASCII display.') + parser.add_argument('-v', '--verbose', action='store_true', help='Verbose output') + parser.add_argument('input', help='Raw contents of the STM32 flash area used to emulate eeprom') + return parser.parse_args() + + +def decodeEepromFEEA(in_file, size): + decoded=size*[None] + pos = 0 + while True: + chunk = in_file.read(CHUNK_SIZE) + for i in range(0, len(chunk), 2): + decoded[pos] = unpack('B', chunk[i])[0] + pos += 1 + if pos >= size: + break + + if len(chunk) < CHUNK_SIZE or pos >= size: + break + return decoded + +def decodeEepromFEE9(in_file, size): + decoded=size*[None] + pos = 0 + # Read compacted flash + while True: + read_size = min(size - pos, CHUNK_SIZE) + chunk = in_file.read(read_size) + for i in range(len(chunk)): + decoded[pos] = unpack('B', chunk[i])[0] ^ 0xFF + pos += 1 + if pos >= size: + break + + if len(chunk) < read_size or pos >= size: + break + if VERBOSE: + print("COMPACTED EEPROM:") + dumpBinary(decoded, True) + print("WRITE LOG:") + # Read write log + while True: + entry = in_file.read(2) + if len(entry) < 2: + print("Partial log address at position 0x%04x" % pos, file=sys.stderr) + break + pos += 2 + + if entry == EMPTY_WORD: + break + + be_entry = unpack('>H', entry)[0] + entry = unpack('H', entry)[0] + if not (entry & WORD_ENCODING): + address = entry >> 8 + decoded[address] = entry & 0xFF + if VERBOSE: + print("[0x%04x]: BYTE 0x%02x = 0x%02x" % (be_entry, address, decoded[address])) + else: + if (entry & VALUE_NEXT) == VALUE_NEXT: + # Read next word as value + value = in_file.read(2) + if len(value) < 2: + print("Partial log value at position 0x%04x" % pos, file=sys.stderr) + break + pos += 2 + address = entry & 0x1FFF + address <<= 1 + address += BYTE_RANGE + decoded[address] = unpack('B', value[0])[0] ^ 0xFF + decoded[address+1] = unpack('B', value[1])[0] ^ 0xFF + be_value = unpack('>H', value)[0] + if VERBOSE: + print("[0x%04x 0x%04x]: WORD 0x%04x = 0x%02x%02x" % (be_entry, be_value, address, decoded[address+1], decoded[address])) + else: + # Reserved for future use + if entry & VALUE_RESERVED: + if VERBOSE: + print("[0x%04x]: RESERVED 0x%04x" % (be_entry, address)) + continue + address = entry & 0x1FFF + address <<= 1 + decoded[address] = (entry & VALUE_ENCODED) >> 13 + decoded[address+1] = 0 + if VERBOSE: + print("[0x%04x]: ENCODED 0x%04x = 0x%02x%02x" % (be_entry, address, decoded[address+1], decoded[address])) + + return decoded + +def dumpBinary(data, canonical): + def display(pos, row): + print("%04x" % pos, end='') + for i in range(len(row)): + if i % 8 == 0: + print(" ", end='') + char = row[i] + if char is None: + print(" ", end='') + else: + print(" %02x" % row[i], end='') + if canonical: + print(" |", end='') + for i in range(len(row)): + char = row[i] + if char is None: + char = " " + else: + char = chr(char) + if char not in PRINTABLE: + char = "." + print(char, end='') + print("|", end='') + + print("") + + size = len(data) + empty_rows = 0 + prev_row = '' + first_repeat = True + for pos in range(0, size, 16): + row=data[pos:pos+16] + row[len(row):16] = (16-len(row))*[None] + if row == prev_row: + if first_repeat: + print("*") + first_repeat = False + else: + first_repeat = True + display(pos, row) + prev_row = row + print("%04x" % (pos+16)) + +def dumpEeconfig(data, eeconfig): + print("EECONFIG:") + for (name, pos, length) in eeconfig: + fmt = STRUCT_FMTS[length] + value = unpack(fmt, ''.join([chr(x) for x in data[pos:pos+length]]))[0] + print(("%%04x %%s = 0x%%0%dx" % (length * 2)) % (pos, name, value)) + +def dumpVia(data, base, layers, cols, rows, macros, + layout_options_size, custom_config_size): + magicYear = data[base + 0] + magicMonth = data[base + 1] + magicDay = data[base + 2] + # Sanity check + if not 10 <= magicYear <= 0x99 or \ + not 0 <= magicMonth <= 0x12 or \ + not 0 <= magicDay <= 0x31: + print("ERROR: VIA Signature is not valid; Year:%x, Month:%x, Day:%x" % (magicYear, magicMonth, magicDay)) + return + if cols is None or rows is None: + print("ERROR: VIA dump requires specifying --rows and --cols", file=sys.stderr) + return 2 + print("VIA:") + # Decode magic + print("%04x MAGIC = 20%02x-%02x-%02x" % (base, magicYear, magicMonth, magicDay)) + # Decode layout options + options = 0 + pos = base + 3 + for i in range(base+3, base+3+layout_options_size): + options = options << 8 + options |= data[i] + print(("%%04x LAYOUT_OPTIONS = 0x%%0%dx" % (layout_options_size * 2)) % (pos, options)) + pos += layout_options_size + custom_config_size + # Decode keycodes + keymap_size = layers * rows * cols * 2 + if (pos + keymap_size) >= (len(data) - 1): + print("ERROR: VIA keymap requires %d bytes, but only %d available" % (keymap_size, len(data) - pos)) + return 3 + for layer in range(layers): + print("%s LAYER %d %s" % ('-'*int(cols*2.5), layer, '-'*int(cols*2.5))) + for row in range(rows): + print("%04x | " % pos, end='') + for col in range(cols): + keycode = (data[pos] << 8) | (data[pos+1]) + print(" %04x" % keycode, end='') + pos += 2 + print("") + # Decode macros + for macro_num in range(macros): + macro = "" + macro_pos = pos + while pos < len(data): + char = chr(data[pos]) + pos += 1 + if char == '\x00': + print("%04x MACRO[%d] = '%s'" % (macro_pos, macro_num, macro)) + break + else: + macro += char + return 0 + + +def decodeSTM32Eeprom(input, canonical, size=None, output=None, **kwargs): + input_size = os.path.getsize(input) + if size is None: + size = input_size >> 1 + + # Read the first few bytes to check magic signature + with open(input, 'rb') as in_file: + magic=in_file.read(4) + in_file.seek(0) + + if magic == MAGIC_FEEA: + decoded = decodeEepromFEEA(in_file, size) + eeconfig = EECONFIG_V1 + via_base = VIABASE_V1 + elif magic[:2] == MAGIC_FEE9: + decoded = decodeEepromFEE9(in_file, size) + eeconfig = EECONFIG_V1 + via_base = VIABASE_V1 + else: + print("Unknown magic signature: %s" % " ".join(["0x%02x" % ord(x) for x in magic]), file=sys.stderr) + return 1 + + if output is not None: + with open(output, 'wb') as out_file: + out_file.write(pack('%dB' % len(decoded), *decoded)) + print("DECODED EEPROM:") + dumpBinary(decoded, canonical) + dumpEeconfig(decoded, eeconfig) + if kwargs['rows'] is not None and kwargs['cols'] is not None: + return dumpVia(decoded, via_base, **kwargs) + + return 0 + +def main(): + global VERBOSE + kwargs = vars(parseArgs()) + VERBOSE = kwargs.pop('verbose') + return decodeSTM32Eeprom(**kwargs) + +if __name__ == '__main__': + sys.exit(main()) -- cgit v1.2.3 From 6fd20acf4be76e7a2bd82d3dfd0a9bcca8c507eb Mon Sep 17 00:00:00 2001 From: Drashna Jaelre Date: Mon, 23 Aug 2021 18:40:24 -0700 Subject: Fix Mouse Shared EP functionality (#14136) Specifically, if you enable the shared endpoint for mouse reports (or keyboard, which force enables it for mouse), and you don't have mousekeys enabled, it does not properly enable shared mouse EP for pointing device (which uses mouse reports). This cause it to error out in compiling. This fixes up some of the logic to ensure that all use cases are supported, and consolidates some of the code.--- common_features.mk | 4 ++-- tmk_core/common.mk | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'tmk_core') diff --git a/common_features.mk b/common_features.mk index 09217c4698..3acc5307ac 100644 --- a/common_features.mk +++ b/common_features.mk @@ -117,13 +117,13 @@ endif ifeq ($(strip $(MOUSEKEY_ENABLE)), yes) OPT_DEFS += -DMOUSEKEY_ENABLE - OPT_DEFS += -DMOUSE_ENABLE + MOUSE_ENABLE := yes SRC += $(QUANTUM_DIR)/mousekey.c endif ifeq ($(strip $(POINTING_DEVICE_ENABLE)), yes) OPT_DEFS += -DPOINTING_DEVICE_ENABLE - OPT_DEFS += -DMOUSE_ENABLE + MOUSE_ENABLE := yes SRC += $(QUANTUM_DIR)/pointing_device.c endif diff --git a/tmk_core/common.mk b/tmk_core/common.mk index 69d27e6c0b..7f74200590 100644 --- a/tmk_core/common.mk +++ b/tmk_core/common.mk @@ -25,7 +25,8 @@ ifeq ($(strip $(KEYBOARD_SHARED_EP)), yes) MOUSE_SHARED_EP = yes endif -ifeq ($(strip $(MOUSEKEY_ENABLE)), yes) +ifeq ($(strip $(MOUSE_ENABLE)), yes) + OPT_DEFS += -DMOUSE_ENABLE ifeq ($(strip $(MOUSE_SHARED_EP)), yes) TMK_COMMON_DEFS += -DMOUSE_SHARED_EP SHARED_EP_ENABLE = yes -- cgit v1.2.3 From c9c60d227e38abdf08ca86bcdad3a0cac2579e3f Mon Sep 17 00:00:00 2001 From: Takeshi ISHII Date: Tue, 24 Aug 2021 22:34:24 +0900 Subject: add wait_cpuclock() macro for AVR and CPU_CLOCK macro (#12755) --- tmk_core/common/avr/_wait.h | 4 +++- tmk_core/common/chibios/_wait.h | 9 +++++---- 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'tmk_core') diff --git a/tmk_core/common/avr/_wait.h b/tmk_core/common/avr/_wait.h index ae1a25131a..683db6ae57 100644 --- a/tmk_core/common/avr/_wait.h +++ b/tmk_core/common/avr/_wait.h @@ -37,6 +37,8 @@ } \ } \ } while (0) +#define wait_cpuclock(n) __builtin_avr_delay_cycles(n) +#define CPU_CLOCK F_CPU /* The AVR series GPIOs have a one clock read delay for changes in the digital input signal. * But here's more margin to make it two clocks. */ @@ -44,4 +46,4 @@ # define GPIO_INPUT_PIN_DELAY 2 #endif -#define waitInputPinDelay() __builtin_avr_delay_cycles(GPIO_INPUT_PIN_DELAY) +#define waitInputPinDelay() wait_cpuclock(GPIO_INPUT_PIN_DELAY) diff --git a/tmk_core/common/chibios/_wait.h b/tmk_core/common/chibios/_wait.h index 4a5172536b..b740afbd24 100644 --- a/tmk_core/common/chibios/_wait.h +++ b/tmk_core/common/chibios/_wait.h @@ -41,6 +41,10 @@ void wait_us(uint16_t duration); } while (0) #endif +#include "_wait.c" + +#define CPU_CLOCK STM32_SYSCLK + /* For GPIOs on ARM-based MCUs, the input pins are sampled by the clock of the bus * to which the GPIO is connected. * The connected buses differ depending on the various series of MCUs. @@ -51,11 +55,8 @@ void wait_us(uint16_t duration); * If the GPIO_INPUT_PIN_DELAY macro is not defined, the following default values will be used. * (A fairly large value of 0.25 microseconds is set.) */ - -#include "_wait.c" - #ifndef GPIO_INPUT_PIN_DELAY -# define GPIO_INPUT_PIN_DELAY (STM32_SYSCLK / 1000000L / 4) +# define GPIO_INPUT_PIN_DELAY (CPU_CLOCK / 1000000L / 4) #endif #define waitInputPinDelay() wait_cpuclock(GPIO_INPUT_PIN_DELAY) -- cgit v1.2.3