diff options
Diffstat (limited to 'tmk_core')
| -rw-r--r-- | tmk_core/chibios.mk | 4 | ||||
| -rw-r--r-- | tmk_core/common.mk | 1 | ||||
| -rw-r--r-- | tmk_core/common/avr/bootloader.c | 10 | ||||
| -rw-r--r-- | tmk_core/common/keyboard.c | 37 | ||||
| -rw-r--r-- | tmk_core/common/keyboard.h | 9 | ||||
| -rw-r--r-- | tmk_core/common/matrix.h | 3 | ||||
| -rw-r--r-- | tmk_core/common/mousekey.c | 80 | ||||
| -rw-r--r-- | tmk_core/common/mousekey.h | 43 | ||||
| -rw-r--r-- | tmk_core/common/sync_timer.c | 58 | ||||
| -rw-r--r-- | tmk_core/common/sync_timer.h | 54 | ||||
| -rw-r--r-- | tmk_core/common/wait.h | 79 | ||||
| -rw-r--r-- | tmk_core/protocol/adb.c | 256 | ||||
| -rw-r--r-- | tmk_core/protocol/adb.h | 58 | ||||
| -rw-r--r-- | tmk_core/protocol/arm_atsam/i2c_master.c | 3 | ||||
| -rw-r--r-- | tmk_core/protocol/arm_atsam/i2c_master.h | 4 | ||||
| -rw-r--r-- | tmk_core/protocol/arm_atsam/main_arm_atsam.c | 3 | 
16 files changed, 593 insertions, 109 deletions
| diff --git a/tmk_core/chibios.mk b/tmk_core/chibios.mk index e94e935ebb..40595a1e3b 100644 --- a/tmk_core/chibios.mk +++ b/tmk_core/chibios.mk @@ -71,6 +71,9 @@ else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/$(BOARD)/board/board.mk)","      BOARD_PATH = $(TOP_DIR)/platforms/chibios/$(BOARD)      BOARD_MK += $(TOP_DIR)/platforms/chibios/$(BOARD)/board/board.mk      KEYBOARD_PATHS += $(BOARD_PATH)/configs +    ifneq ("$(wildcard $(BOARD_PATH)/rules.mk)","") +        include $(BOARD_PATH)/rules.mk +    endif  endif  ifeq ("$(wildcard $(BOARD_MK))","") @@ -309,6 +312,7 @@ LDFLAGS += -mno-thumb-interwork -mthumb  LDSYMBOLS =,--defsym=__process_stack_size__=$(USE_PROCESS_STACKSIZE)  LDSYMBOLS :=$(LDSYMBOLS),--defsym=__main_stack_size__=$(USE_EXCEPTIONS_STACKSIZE)  LDFLAGS += -Wl,--script=$(LDSCRIPT)$(LDSYMBOLS) +LDFLAGS += --specs=nano.specs  OPT_DEFS += -DPROTOCOL_CHIBIOS diff --git a/tmk_core/common.mk b/tmk_core/common.mk index fdf2aa0972..05839824c0 100644 --- a/tmk_core/common.mk +++ b/tmk_core/common.mk @@ -18,6 +18,7 @@ TMK_COMMON_SRC +=	$(COMMON_DIR)/host.c \  	$(COMMON_DIR)/report.c \  	$(PLATFORM_COMMON_DIR)/suspend.c \  	$(PLATFORM_COMMON_DIR)/timer.c \ +	$(COMMON_DIR)/sync_timer.c \  	$(PLATFORM_COMMON_DIR)/bootloader.c \  ifeq ($(PLATFORM),AVR) diff --git a/tmk_core/common/avr/bootloader.c b/tmk_core/common/avr/bootloader.c index a1db55da93..4e3a27022d 100644 --- a/tmk_core/common/avr/bootloader.c +++ b/tmk_core/common/avr/bootloader.c @@ -77,7 +77,7 @@ uint32_t reset_key __attribute__((section(".noinit,\"aw\",@nobits;")));   *   * FIXME: needs doc   */ -void bootloader_jump(void) { +__attribute__((weak)) void bootloader_jump(void) {  #if !defined(BOOTLOADER_SIZE)      uint8_t high_fuse = boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS); @@ -237,13 +237,13 @@ void bootloader_jump(void) {                   "bootloader_startup_loop%=:         \n\t"                   "rjmp bootloader_startup_loop%=     \n\t"                   : -                 : [mcucsrio] "I"(_SFR_IO_ADDR(MCUCSR)), +                 : [ mcucsrio ] "I"(_SFR_IO_ADDR(MCUCSR)),  #    if (FLASHEND > 131071) -                   [ramendhi] "M"(((RAMEND - 2) >> 8) & 0xff), [ramendlo] "M"(((RAMEND - 2) >> 0) & 0xff), [bootaddrhi] "M"((((FLASH_SIZE - BOOTLOADER_SIZE) >> 1) >> 16) & 0xff), +                   [ ramendhi ] "M"(((RAMEND - 2) >> 8) & 0xff), [ ramendlo ] "M"(((RAMEND - 2) >> 0) & 0xff), [ bootaddrhi ] "M"((((FLASH_SIZE - BOOTLOADER_SIZE) >> 1) >> 16) & 0xff),  #    else -                   [ramendhi] "M"(((RAMEND - 1) >> 8) & 0xff), [ramendlo] "M"(((RAMEND - 1) >> 0) & 0xff), +                   [ ramendhi ] "M"(((RAMEND - 1) >> 8) & 0xff), [ ramendlo ] "M"(((RAMEND - 1) >> 0) & 0xff),  #    endif -                   [bootaddrme] "M"((((FLASH_SIZE - BOOTLOADER_SIZE) >> 1) >> 8) & 0xff), [bootaddrlo] "M"((((FLASH_SIZE - BOOTLOADER_SIZE) >> 1) >> 0) & 0xff)); +                   [ bootaddrme ] "M"((((FLASH_SIZE - BOOTLOADER_SIZE) >> 1) >> 8) & 0xff), [ bootaddrlo ] "M"((((FLASH_SIZE - BOOTLOADER_SIZE) >> 1) >> 0) & 0xff));  #else  // Assume remaining boards are DFU, even if the flag isn't set diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c index 8c7bdc8b55..0ca4546128 100644 --- a/tmk_core/common/keyboard.c +++ b/tmk_core/common/keyboard.c @@ -23,6 +23,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #include "led.h"  #include "keycode.h"  #include "timer.h" +#include "sync_timer.h"  #include "print.h"  #include "debug.h"  #include "command.h" @@ -96,6 +97,20 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #    include "dip_switch.h"  #endif +static uint32_t last_input_modification_time = 0; +uint32_t        last_input_activity_time(void) { return last_input_modification_time; } +uint32_t        last_input_activity_elapsed(void) { return timer_elapsed32(last_input_modification_time); } + +static uint32_t last_matrix_modification_time = 0; +uint32_t        last_matrix_activity_time(void) { return last_matrix_modification_time; } +uint32_t        last_matrix_activity_elapsed(void) { return timer_elapsed32(last_matrix_modification_time); } +void            last_matrix_activity_trigger(void) { last_matrix_modification_time = last_input_modification_time = timer_read32(); } + +static uint32_t last_encoder_modification_time = 0; +uint32_t        last_encoder_activity_time(void) { return last_encoder_modification_time; } +uint32_t        last_encoder_activity_elapsed(void) { return timer_elapsed32(last_encoder_modification_time); } +void            last_encoder_activity_trigger(void) { last_encoder_modification_time = last_input_modification_time = timer_read32(); } +  // Only enable this if console is enabled to print to  #if defined(DEBUG_MATRIX_SCAN_RATE) && defined(CONSOLE_ENABLE)  static uint32_t matrix_timer      = 0; @@ -255,6 +270,7 @@ __attribute__((weak)) void housekeeping_task_user(void) {}   */  void keyboard_init(void) {      timer_init(); +    sync_timer_init();      matrix_init();  #ifdef VIA_ENABLE      via_init(); @@ -332,15 +348,15 @@ void keyboard_task(void) {  #ifdef QMK_KEYS_PER_SCAN      uint8_t keys_processed = 0;  #endif +#ifdef ENCODER_ENABLE +    bool encoders_changed = false; +#endif      housekeeping_task_kb();      housekeeping_task_user(); -#if defined(OLED_DRIVER_ENABLE) && !defined(OLED_DISABLE_TIMEOUT) -    uint8_t ret = matrix_scan(); -#else -    matrix_scan(); -#endif +    uint8_t matrix_changed = matrix_scan(); +    if (matrix_changed) last_matrix_activity_trigger();      if (should_process_keypress()) {          for (uint8_t r = 0; r < MATRIX_ROWS; r++) { @@ -396,7 +412,8 @@ MATRIX_LOOP_END:  #endif  #ifdef ENCODER_ENABLE -    encoder_read(); +    encoders_changed = encoder_read(); +    if (encoders_changed) last_encoder_activity_trigger();  #endif  #ifdef QWIIC_ENABLE @@ -406,8 +423,12 @@ MATRIX_LOOP_END:  #ifdef OLED_DRIVER_ENABLE      oled_task();  #    ifndef OLED_DISABLE_TIMEOUT -    // Wake up oled if user is using those fabulous keys! -    if (ret) oled_on(); +    // Wake up oled if user is using those fabulous keys or spinning those encoders! +#        ifdef ENCODER_ENABLE +    if (matrix_changed || encoders_changed) oled_on(); +#        else +    if (matrix_changed) oled_on(); +#        endif  #    endif  #endif diff --git a/tmk_core/common/keyboard.h b/tmk_core/common/keyboard.h index d04e685cdb..88b3896e9e 100644 --- a/tmk_core/common/keyboard.h +++ b/tmk_core/common/keyboard.h @@ -73,6 +73,15 @@ void keyboard_post_init_user(void);  void housekeeping_task_kb(void);  void housekeeping_task_user(void); +uint32_t last_input_activity_time(void);     // Timestamp of the last matrix or encoder activity +uint32_t last_input_activity_elapsed(void);  // Number of milliseconds since the last matrix or encoder activity + +uint32_t last_matrix_activity_time(void);     // Timestamp of the last matrix activity +uint32_t last_matrix_activity_elapsed(void);  // Number of milliseconds since the last matrix activity + +uint32_t last_encoder_activity_time(void);     // Timestamp of the last encoder activity +uint32_t last_encoder_activity_elapsed(void);  // Number of milliseconds since the last encoder activity +  #ifdef __cplusplus  }  #endif diff --git a/tmk_core/common/matrix.h b/tmk_core/common/matrix.h index b570227a31..ce57010a47 100644 --- a/tmk_core/common/matrix.h +++ b/tmk_core/common/matrix.h @@ -55,6 +55,9 @@ matrix_row_t matrix_get_row(uint8_t row);  /* print matrix for debug */  void matrix_print(void);  /* delay between changing matrix pin state and reading values */ +void matrix_output_select_delay(void); +void matrix_output_unselect_delay(void); +/* only for backwards compatibility. delay between changing matrix pin state and reading values */  void matrix_io_delay(void);  /* power control */ diff --git a/tmk_core/common/mousekey.c b/tmk_core/common/mousekey.c index ef18bcf1a8..6c9df67236 100644 --- a/tmk_core/common/mousekey.c +++ b/tmk_core/common/mousekey.c @@ -36,6 +36,9 @@ static void           mousekey_debug(void);  static uint8_t        mousekey_accel        = 0;  static uint8_t        mousekey_repeat       = 0;  static uint8_t        mousekey_wheel_repeat = 0; +#ifdef MK_KINETIC_SPEED +static uint16_t mouse_timer = 0; +#endif  #ifndef MK_3_SPEED @@ -43,7 +46,7 @@ static uint16_t last_timer_c = 0;  static uint16_t last_timer_w = 0;  /* - * Mouse keys  acceleration algorithm + * Mouse keys acceleration algorithm   *  http://en.wikipedia.org/wiki/Mouse_keys   *   *  speed = delta * max_speed * (repeat / time_to_max)**((1000+curve)/1000) @@ -105,6 +108,65 @@ static uint8_t wheel_unit(void) {  }  #    else /* #ifndef MK_COMBINED */ +#        ifndef MK_KINETIC_SPEED + +/* + * Kinetic movement  acceleration algorithm + * + *  current speed = I + A * T/50 + A * 0.5 * T^2 | maximum B + * + * T: time since the mouse movement started + * E: mouse events per second (set through MOUSEKEY_INTERVAL, UHK sends 250, the + *    pro micro on my Signum 3.0 sends only 125!) + * I: initial speed at time 0 + * A: acceleration + * B: base mouse travel speed + */ +const uint16_t mk_accelerated_speed = MOUSEKEY_ACCELERATED_SPEED; +const uint16_t mk_base_speed        = MOUSEKEY_BASE_SPEED; +const uint16_t mk_decelerated_speed = MOUSEKEY_DECELERATED_SPEED; +const uint16_t mk_initial_speed     = MOUSEKEY_INITIAL_SPEED; + +static uint8_t move_unit(void) { +    float speed = mk_initial_speed; + +    if (mousekey_accel & ((1 << 0) | (1 << 2))) { +        speed = mousekey_accel & (1 << 2) ? mk_accelerated_speed : mk_decelerated_speed; +    } else if (mousekey_repeat && mouse_timer) { +        const float time_elapsed = timer_elapsed(mouse_timer) / 50; +        speed                    = mk_initial_speed + MOUSEKEY_MOVE_DELTA * time_elapsed + MOUSEKEY_MOVE_DELTA * 0.5 * time_elapsed * time_elapsed; + +        speed = speed > mk_base_speed ? mk_base_speed : speed; +    } + +    /* convert speed to USB mouse speed 1 to 127 */ +    speed = (uint8_t)(speed / (1000.0f / mk_interval)); +    speed = speed < 1 ? 1 : speed; + +    return speed > MOUSEKEY_MOVE_MAX ? MOUSEKEY_MOVE_MAX : speed; +} + +float mk_wheel_interval = 1000.0f / MOUSEKEY_WHEEL_INITIAL_MOVEMENTS; + +static uint8_t wheel_unit(void) { +    float speed = MOUSEKEY_WHEEL_INITIAL_MOVEMENTS; + +    if (mousekey_accel & ((1 << 0) | (1 << 2))) { +        speed = mousekey_accel & (1 << 2) ? MOUSEKEY_WHEEL_ACCELERATED_MOVEMENTS : MOUSEKEY_WHEEL_DECELERATED_MOVEMENTS; +    } else if (mousekey_repeat && mouse_timer) { +        if (mk_wheel_interval != MOUSEKEY_WHEEL_BASE_MOVEMENTS) { +            const float time_elapsed = timer_elapsed(mouse_timer) / 50; +            speed                    = MOUSEKEY_WHEEL_INITIAL_MOVEMENTS + 1 * time_elapsed + 1 * 0.5 * time_elapsed * time_elapsed; +        } +        speed = speed > MOUSEKEY_WHEEL_BASE_MOVEMENTS ? MOUSEKEY_WHEEL_BASE_MOVEMENTS : speed; +    } + +    mk_wheel_interval = 1000.0f / speed; + +    return 1; +} + +#        else /* #ifndef MK_KINETIC_SPEED */  static uint8_t move_unit(void) {      uint16_t unit; @@ -142,7 +204,8 @@ static uint8_t wheel_unit(void) {      return (unit > MOUSEKEY_WHEEL_MAX ? MOUSEKEY_WHEEL_MAX : (unit == 0 ? 1 : unit));  } -#    endif /* #ifndef MK_COMBINED */ +#        endif /* #ifndef MK_KINETIC_SPEED */ +#    endif     /* #ifndef MK_COMBINED */  void mousekey_task(void) {      // report cursor and scroll movement independently @@ -193,6 +256,12 @@ void mousekey_task(void) {  }  void mousekey_on(uint8_t code) { +#    ifdef MK_KINETIC_SPEED +    if (mouse_timer == 0) { +        mouse_timer = timer_read(); +    } +#    endif /* #ifdef MK_KINETIC_SPEED */ +      if (code == KC_MS_UP)          mouse_report.y = move_unit() * -1;      else if (code == KC_MS_DOWN) @@ -260,7 +329,12 @@ void mousekey_off(uint8_t code) {          mousekey_accel &= ~(1 << 1);      else if (code == KC_MS_ACCEL2)          mousekey_accel &= ~(1 << 2); -    if (mouse_report.x == 0 && mouse_report.y == 0) mousekey_repeat = 0; +    if (mouse_report.x == 0 && mouse_report.y == 0) { +        mousekey_repeat = 0; +#    ifdef MK_KINETIC_SPEED +        mouse_timer = 0; +#    endif /* #ifdef MK_KINETIC_SPEED */ +    }      if (mouse_report.v == 0 && mouse_report.h == 0) mousekey_wheel_repeat = 0;  } diff --git a/tmk_core/common/mousekey.h b/tmk_core/common/mousekey.h index 300d262f5d..52b8fe10e1 100644 --- a/tmk_core/common/mousekey.h +++ b/tmk_core/common/mousekey.h @@ -36,16 +36,28 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #    endif  #    ifndef MOUSEKEY_MOVE_DELTA -#        define MOUSEKEY_MOVE_DELTA 5 +#        ifndef MK_KINETIC_SPEED +#            define MOUSEKEY_MOVE_DELTA 5 +#        else +#            define MOUSEKEY_MOVE_DELTA 25 +#        endif  #    endif  #    ifndef MOUSEKEY_WHEEL_DELTA  #        define MOUSEKEY_WHEEL_DELTA 1  #    endif  #    ifndef MOUSEKEY_DELAY -#        define MOUSEKEY_DELAY 300 +#        ifndef MK_KINETIC_SPEED +#            define MOUSEKEY_DELAY 300 +#        else +#            define MOUSEKEY_DELAY 8 +#        endif  #    endif  #    ifndef MOUSEKEY_INTERVAL -#        define MOUSEKEY_INTERVAL 50 +#        ifndef MK_KINETIC_SPEED +#            define MOUSEKEY_INTERVAL 50 +#        else +#            define MOUSEKEY_INTERVAL 8 +#        endif  #    endif  #    ifndef MOUSEKEY_MAX_SPEED  #        define MOUSEKEY_MAX_SPEED 10 @@ -66,6 +78,31 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #        define MOUSEKEY_WHEEL_TIME_TO_MAX 40  #    endif +#    ifndef MOUSEKEY_INITIAL_SPEED +#        define MOUSEKEY_INITIAL_SPEED 100 +#    endif +#    ifndef MOUSEKEY_BASE_SPEED +#        define MOUSEKEY_BASE_SPEED 1000 +#    endif +#    ifndef MOUSEKEY_DECELERATED_SPEED +#        define MOUSEKEY_DECELERATED_SPEED 400 +#    endif +#    ifndef MOUSEKEY_ACCELERATED_SPEED +#        define MOUSEKEY_ACCELERATED_SPEED 3000 +#    endif +#    ifndef MOUSEKEY_WHEEL_INITIAL_MOVEMENTS +#        define MOUSEKEY_WHEEL_INITIAL_MOVEMENTS 16 +#    endif +#    ifndef MOUSEKEY_WHEEL_BASE_MOVEMENTS +#        define MOUSEKEY_WHEEL_BASE_MOVEMENTS 32 +#    endif +#    ifndef MOUSEKEY_WHEEL_ACCELERATED_MOVEMENTS +#        define MOUSEKEY_WHEEL_ACCELERATED_MOVEMENTS 48 +#    endif +#    ifndef MOUSEKEY_WHEEL_DECELERATED_MOVEMENTS +#        define MOUSEKEY_WHEEL_DECELERATED_MOVEMENTS 8 +#    endif +  #else /* #ifndef MK_3_SPEED */  #    ifndef MK_C_OFFSET_UNMOD diff --git a/tmk_core/common/sync_timer.c b/tmk_core/common/sync_timer.c new file mode 100644 index 0000000000..de24b463b6 --- /dev/null +++ b/tmk_core/common/sync_timer.c @@ -0,0 +1,58 @@ +/* +Copyright (C) 2020 Ryan Caltabiano <https://github.com/XScorpion2> + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +If you happen to meet one of the copyright holders in a bar you are obligated +to buy them one pint of beer. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#include "sync_timer.h" +#include "keyboard.h" + +#if defined(SPLIT_KEYBOARD) && !defined(DISABLE_SYNC_TIMER) +volatile int32_t sync_timer_ms; + +void sync_timer_init(void) { sync_timer_ms = 0; } + +void sync_timer_update(uint32_t time) { +    if (is_keyboard_master()) return; +    sync_timer_ms = time - timer_read32(); +} + +uint16_t sync_timer_read(void) { +    if (is_keyboard_master()) return timer_read(); +    return sync_timer_read32(); +} + +uint32_t sync_timer_read32(void) { +    if (is_keyboard_master()) return timer_read32(); +    return sync_timer_ms + timer_read32(); +} + +uint16_t sync_timer_elapsed(uint16_t last) { +    if (is_keyboard_master()) return timer_elapsed(last); +    return TIMER_DIFF_16(sync_timer_read(), last); +} + +uint32_t sync_timer_elapsed32(uint32_t last) { +    if (is_keyboard_master()) return timer_elapsed32(last); +    return TIMER_DIFF_32(sync_timer_read32(), last); +} +#endif diff --git a/tmk_core/common/sync_timer.h b/tmk_core/common/sync_timer.h new file mode 100644 index 0000000000..9ddef45bb2 --- /dev/null +++ b/tmk_core/common/sync_timer.h @@ -0,0 +1,54 @@ +/* +Copyright (C) 2020 Ryan Caltabiano <https://github.com/XScorpion2> + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +If you happen to meet one of the copyright holders in a bar you are obligated +to buy them one pint of beer. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#pragma once + +#include <stdint.h> +#include "timer.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(SPLIT_KEYBOARD) && !defined(DISABLE_SYNC_TIMER) +void     sync_timer_init(void); +void     sync_timer_update(uint32_t time); +uint16_t sync_timer_read(void); +uint32_t sync_timer_read32(void); +uint16_t sync_timer_elapsed(uint16_t last); +uint32_t sync_timer_elapsed32(uint32_t last); +#else +#    define sync_timer_init() +#    define sync_timer_clear() +#    define sync_timer_update(t) +#    define sync_timer_read() timer_read() +#    define sync_timer_read32() timer_read32() +#    define sync_timer_elapsed(t) timer_elapsed(t) +#    define sync_timer_elapsed32(t) timer_elapsed32(t) +#endif + +#ifdef __cplusplus +} +#endif diff --git a/tmk_core/common/wait.h b/tmk_core/common/wait.h index 89128e9daf..28224fe3aa 100644 --- a/tmk_core/common/wait.h +++ b/tmk_core/common/wait.h @@ -6,10 +6,89 @@  extern "C" {  #endif +#if defined(__ARMEL__) || defined(__ARMEB__) +#    ifndef __OPTIMIZE__ +#        pragma message "Compiler optimizations disabled; wait_cpuclock() won't work as designed" +#    endif + +#    define wait_cpuclock(x) wait_cpuclock_allnop(x) + +#    define CLOCK_DELAY_NOP8 "nop\n\t nop\n\t nop\n\t nop\n\t   nop\n\t nop\n\t nop\n\t nop\n\t" + +__attribute__((always_inline)) static inline void wait_cpuclock_allnop(unsigned int n) { /* n: 1..135 */ +    /* The argument n must be a constant expression. +     * That way, compiler optimization will remove unnecessary code. */ +    if (n < 1) { +        return; +    } +    if (n > 8) { +        unsigned int n8 = n / 8; +        n               = n - n8 * 8; +        switch (n8) { +            case 16: +                asm volatile(CLOCK_DELAY_NOP8::: "memory"); +            case 15: +                asm volatile(CLOCK_DELAY_NOP8::: "memory"); +            case 14: +                asm volatile(CLOCK_DELAY_NOP8::: "memory"); +            case 13: +                asm volatile(CLOCK_DELAY_NOP8::: "memory"); +            case 12: +                asm volatile(CLOCK_DELAY_NOP8::: "memory"); +            case 11: +                asm volatile(CLOCK_DELAY_NOP8::: "memory"); +            case 10: +                asm volatile(CLOCK_DELAY_NOP8::: "memory"); +            case 9: +                asm volatile(CLOCK_DELAY_NOP8::: "memory"); +            case 8: +                asm volatile(CLOCK_DELAY_NOP8::: "memory"); +            case 7: +                asm volatile(CLOCK_DELAY_NOP8::: "memory"); +            case 6: +                asm volatile(CLOCK_DELAY_NOP8::: "memory"); +            case 5: +                asm volatile(CLOCK_DELAY_NOP8::: "memory"); +            case 4: +                asm volatile(CLOCK_DELAY_NOP8::: "memory"); +            case 3: +                asm volatile(CLOCK_DELAY_NOP8::: "memory"); +            case 2: +                asm volatile(CLOCK_DELAY_NOP8::: "memory"); +            case 1: +                asm volatile(CLOCK_DELAY_NOP8::: "memory"); +            case 0: +                break; +        } +    } +    switch (n) { +        case 8: +            asm volatile("nop" ::: "memory"); +        case 7: +            asm volatile("nop" ::: "memory"); +        case 6: +            asm volatile("nop" ::: "memory"); +        case 5: +            asm volatile("nop" ::: "memory"); +        case 4: +            asm volatile("nop" ::: "memory"); +        case 3: +            asm volatile("nop" ::: "memory"); +        case 2: +            asm volatile("nop" ::: "memory"); +        case 1: +            asm volatile("nop" ::: "memory"); +        case 0: +            break; +    } +} +#endif +  #if defined(__AVR__)  #    include <util/delay.h>  #    define wait_ms(ms) _delay_ms(ms)  #    define wait_us(us) _delay_us(us) +#    define wait_cpuclock(x) __builtin_avr_delay_cycles(x)  #elif defined PROTOCOL_CHIBIOS  #    include <ch.h>  #    define wait_ms(ms)                     \ diff --git a/tmk_core/protocol/adb.c b/tmk_core/protocol/adb.c index a23c919619..367f1b09fa 100644 --- a/tmk_core/protocol/adb.c +++ b/tmk_core/protocol/adb.c @@ -1,5 +1,5 @@  /* -Copyright 2011 Jun WAKO <wakojun@gmail.com> +Copyright 2011-19 Jun WAKO <wakojun@gmail.com>  Copyright 2013 Shay Green <gblargg@gmail.com>  This software is licensed with a Modified BSD License. @@ -41,6 +41,7 @@ POSSIBILITY OF SUCH DAMAGE.  #include <avr/io.h>  #include <avr/interrupt.h>  #include "adb.h" +#include "print.h"  // GCC doesn't inline functions normally  #define data_lo() (ADB_DDR |= (1 << ADB_DATA_BIT)) @@ -59,7 +60,6 @@ static inline void     place_bit1(void);  static inline void     send_byte(uint8_t data);  static inline uint16_t wait_data_lo(uint16_t us);  static inline uint16_t wait_data_hi(uint16_t us); -static inline uint16_t adb_host_dev_recv(uint8_t device);  void adb_host_init(void) {      ADB_PORT &= ~(1 << ADB_DATA_BIT); @@ -81,119 +81,164 @@ bool adb_host_psw(void) { return psw_in(); }   * <http://geekhack.org/index.php?topic=14290.msg1068919#msg1068919>   * <http://geekhack.org/index.php?topic=14290.msg1070139#msg1070139>   */ - -// ADB Bit Cells -// -// bit cell time: 70-130us -// low part of bit0: 60-70% of bit cell -// low part of bit1: 30-40% of bit cell -// -//    bit cell time         70us        130us -//    -------------------------------------------- -//    low  part of bit0     42-49       78-91 -//    high part of bit0     21-28       39-52 -//    low  part of bit1     21-28       39-52 -//    high part of bit1     42-49       78-91 -// -// -// bit0: -//    70us bit cell: -//      ____________~~~~~~ -//      42-49        21-28 -// -//    130us bit cell: -//      ____________~~~~~~ -//      78-91        39-52 -// -// bit1: -//    70us bit cell: -//      ______~~~~~~~~~~~~ -//      21-28        42-49 -// -//    130us bit cell: -//      ______~~~~~~~~~~~~ -//      39-52        78-91 -// -// [from Apple IIgs Hardware Reference Second Edition] - -enum { ADDR_KEYB = 0x20, ADDR_MOUSE = 0x30 }; - -uint16_t adb_host_kbd_recv(void) { return adb_host_dev_recv(ADDR_KEYB); } +uint16_t adb_host_kbd_recv(void) { return adb_host_talk(ADB_ADDR_KEYBOARD, ADB_REG_0); }  #ifdef ADB_MOUSE_ENABLE -void adb_mouse_init(void) { return; } +__attribute__((weak)) void adb_mouse_init(void) { return; } + +__attribute__((weak)) void adb_mouse_task(void) { return; } -uint16_t adb_host_mouse_recv(void) { return adb_host_dev_recv(ADDR_MOUSE); } +uint16_t adb_host_mouse_recv(void) { return adb_host_talk(ADB_ADDR_MOUSE, ADB_REG_0); }  #endif -static inline uint16_t adb_host_dev_recv(uint8_t device) { -    uint16_t data = 0; +// This sends Talk command to read data from register and returns length of the data. +uint8_t adb_host_talk_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len) { +    for (int8_t i = 0; i < len; i++) buf[i] = 0; +      cli();      attention(); -    send_byte(device | 0x0C);  // Addr:Keyboard(0010)/Mouse(0011), Cmd:Talk(11), Register0(00) -    place_bit0();              // Stopbit(0) +    send_byte((addr << 4) | ADB_CMD_TALK | reg); +    place_bit0();  // Stopbit(0) +    // TODO: Service Request(Srq): +    // Device holds low part of comannd stopbit for 140-260us +    // +    // Command: +    // ......._     ______________________    ___ ............_     ------- +    //         |   |                      |  |   |             |   | +    // Command |   |                      |  |   | Data bytes  |   | +    // ........|___|  |     140-260       |__|   |_............|___| +    //         |stop0 | Tlt Stop-to-Start |start1|             |stop0 | +    // +    // Command without data: +    // ......._     __________________________ +    //         |   | +    // Command |   | +    // ........|___|  |     140-260       | +    //         |stop0 | Tlt Stop-to-Start | +    // +    // Service Request: +    // ......._                     ______    ___ ............_     ------- +    //         |     140-260       |      |  |   |             |   | +    // Command |  Service Request  |      |  |   | Data bytes  |   | +    // ........|___________________|      |__|   |_............|___| +    //         |stop0 |                   |start1|             |stop0 | +    // ......._                     __________ +    //         |     140-260       | +    // Command |  Service Request  | +    // ........|___________________| +    //         |stop0 | +    // This can be happened? +    // ......._     ______________________    ___ ............_                   ----- +    //         |   |                      |  |   |             |    140-260      | +    // Command |   |                      |  |   | Data bytes  | Service Request | +    // ........|___|  |     140-260       |__|   |_............|_________________| +    //         |stop0 | Tlt Stop-to-Start |start1|             |stop0 | +    // +    // "Service requests are issued by the devices during a very specific time at the +    // end of the reception of the command packet. +    // If a device in need of service issues a service request, it must do so within +    // the 65 µs of the Stop Bit’s low time and maintain the line low for a total of 300 µs." +    // +    // "A device sends a Service Request signal by holding the bus low during the low +    // portion of the stop bit of any command or data transaction. The device must lengthen +    // the stop by a minimum of 140 J.lS beyond its normal duration, as shown in Figure 8-15." +    // http://ww1.microchip.com/downloads/en/AppNotes/00591b.pdf      if (!wait_data_hi(500)) {  // Service Request(310us Adjustable Keyboard): just ignored +        xprintf("R");          sei(); -        return -30;  // something wrong +        return 0;      }      if (!wait_data_lo(500)) {  // Tlt/Stop to Start(140-260us)          sei(); -        return 0;  // No data to send +        return 0;  // No data from device(not error); +    } + +    // start bit(1) +    if (!wait_data_hi(40)) { +        xprintf("S"); +        sei(); +        return 0; +    } +    if (!wait_data_lo(100)) { +        xprintf("s"); +        sei(); +        return 0;      } -    uint8_t n = 17;  // start bit + 16 data bits +    uint8_t n = 0;  // bit count      do { +        // +        // |<- bit_cell_max(130) ->| +        // |        |<-   lo     ->| +        // |        |       |<-hi->| +        //           _______ +        // |        |       | +        // | 130-lo | lo-hi | +        // |________|       | +        //          uint8_t lo = (uint8_t)wait_data_hi(130); -        if (!lo) goto error; +        if (!lo) goto error;  // no more bit or after stop bit          uint8_t hi = (uint8_t)wait_data_lo(lo); -        if (!hi) goto error; +        if (!hi) goto error;  // stop bit extedned by Srq? -        hi = lo - hi; -        lo = 130 - lo; +        if (n / 8 >= len) continue;  // can't store in buf -        data <<= 1; -        if (lo < hi) { -            data |= 1; -        } else if (n == 17) { -            sei(); -            return -20; +        buf[n / 8] <<= 1; +        if ((130 - lo) < (lo - hi)) { +            buf[n / 8] |= 1;          } -    } while (--n); - -    // Stop bit can't be checked normally since it could have service request lenghtening -    // and its high state never goes low. -    if (!wait_data_hi(351) || wait_data_lo(91)) { -        sei(); -        return -21; -    } -    sei(); -    return data; +    } while (++n);  error:      sei(); -    return -n; +    return n / 8;  } -void adb_host_listen(uint8_t cmd, uint8_t data_h, uint8_t data_l) { +uint16_t adb_host_talk(uint8_t addr, uint8_t reg) { +    uint8_t len; +    uint8_t buf[8]; +    len = adb_host_talk_buf(addr, reg, buf, 8); +    if (len != 2) return 0; +    return (buf[0] << 8 | buf[1]); +} + +void adb_host_listen_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len) {      cli();      attention(); -    send_byte(cmd); -    place_bit0();    // Stopbit(0) +    send_byte((addr << 4) | ADB_CMD_LISTEN | reg); +    place_bit0();  // Stopbit(0) +    // TODO: Service Request      _delay_us(200);  // Tlt/Stop to Start      place_bit1();    // Startbit(1) -    send_byte(data_h); -    send_byte(data_l); +    for (int8_t i = 0; i < len; i++) { +        send_byte(buf[i]); +        // xprintf("%02X ", buf[i]); +    }      place_bit0();  // Stopbit(0);      sei();  } +void adb_host_listen(uint8_t addr, uint8_t reg, uint8_t data_h, uint8_t data_l) { +    uint8_t buf[2] = {data_h, data_l}; +    adb_host_listen_buf(addr, reg, buf, 2); +} + +void adb_host_flush(uint8_t addr) { +    cli(); +    attention(); +    send_byte((addr << 4) | ADB_CMD_FLUSH); +    place_bit0();    // Stopbit(0) +    _delay_us(200);  // Tlt/Stop to Start +    sei(); +} +  // send state of LEDs  void adb_host_kbd_led(uint8_t led) { -    // Addr:Keyboard(0010), Cmd:Listen(10), Register2(10) -    // send upper byte (not used) -    // send lower byte (bit2: ScrollLock, bit1: CapsLock, bit0: -    adb_host_listen(0x2A, 0, led & 0x07); +    // Listen Register2 +    //  upper byte: not used +    //  lower byte: bit2=ScrollLock, bit1=CapsLock, bit0=NumLock +    adb_host_listen(ADB_ADDR_KEYBOARD, ADB_REG_2, 0, led & 0x07);  }  #ifdef ADB_PSW_BIT @@ -327,7 +372,7 @@ Commands      bits                commands      ------------------------------------------------------ -    - - - - 0 0 0 0     Send Request(reset all devices) +    - - - - 0 0 0 0     Send Reset(reset all devices)      A A A A 0 0 0 1     Flush(reset a device)      - - - - 0 0 1 0     Reserved      - - - - 0 0 1 1     Reserved @@ -435,5 +480,56 @@ Keyboard LEDs & state of keys(Register2)       | +-----------------------------   Delete       +-------------------------------   Reserved +Address, Handler ID and bits(Register3) +    1514131211 . . 8 7 . . . . . . 0 +     | | | | | | | | | | | | | | | | +     | | | | | | | | +-+-+-+-+-+-+-+-   Handler ID +     | | | | +-+-+-+-----------------   Address +     | | | +-------------------------   0 +     | | +---------------------------   Service request enable(1 = enabled) +     | +-----------------------------   Exceptional event(alwyas 1 if not used) +     +-------------------------------   0 + +ADB Bit Cells +    bit cell time: 70-130us +    low part of bit0: 60-70% of bit cell +    low part of bit1: 30-40% of bit cell + +       bit cell time         70us        130us +       -------------------------------------------- +       low  part of bit0     42-49       78-91 +       high part of bit0     21-28       39-52 +       low  part of bit1     21-28       39-52 +       high part of bit1     42-49       78-91 + + +    bit0: +       70us bit cell: +         ____________~~~~~~ +         42-49        21-28 + +       130us bit cell: +         ____________~~~~~~ +         78-91        39-52 + +    bit1: +       70us bit cell: +         ______~~~~~~~~~~~~ +         21-28        42-49 + +       130us bit cell: +         ______~~~~~~~~~~~~ +         39-52        78-91 + +    [from Apple IIgs Hardware Reference Second Edition] + +Keyboard Handle ID +    Apple Standard Keyboard M0116:      0x01 +    Apple Extended Keyboard M0115:      0x02 +    Apple Extended Keyboard II M3501:   0x02 +    Apple Adjustable Keybaord:          0x10 + +    http://lxr.free-electrons.com/source/drivers/macintosh/adbhid.c?v=4.4#L802 +  END_OF_ADB  */ diff --git a/tmk_core/protocol/adb.h b/tmk_core/protocol/adb.h index 34cbcf7691..fe8becc2d5 100644 --- a/tmk_core/protocol/adb.h +++ b/tmk_core/protocol/adb.h @@ -1,5 +1,5 @@  /* -Copyright 2011 Jun WAKO <wakojun@gmail.com> +Copyright 2011-19 Jun WAKO <wakojun@gmail.com>  This software is licensed with a Modified BSD License.  All of this is supposed to be Free Software, Open Source, DFSG-free, @@ -47,12 +47,60 @@ POSSIBILITY OF SUCH DAMAGE.  #define ADB_POWER 0x7F  #define ADB_CAPS 0x39 +/* ADB commands */ +// Default Address +#define ADB_ADDR_0 0 +#define ADB_ADDR_DONGLE 1 +#define ADB_ADDR_KEYBOARD 2 +#define ADB_ADDR_MOUSE 3 +#define ADB_ADDR_TABLET 4 +#define ADB_ADDR_APPLIANCE 7 +#define ADB_ADDR_8 8 +#define ADB_ADDR_9 9 +#define ADB_ADDR_10 10 +#define ADB_ADDR_11 11 +#define ADB_ADDR_12 12 +#define ADB_ADDR_13 13 +#define ADB_ADDR_14 14 +#define ADB_ADDR_15 15 +// for temporary purpose, do not use for polling +#define ADB_ADDR_TMP 15 +#define ADB_ADDR_MOUSE_POLL 10 +// Command Type +#define ADB_CMD_RESET 0 +#define ADB_CMD_FLUSH 1 +#define ADB_CMD_LISTEN 8 +#define ADB_CMD_TALK 12 +// Register +#define ADB_REG_0 0 +#define ADB_REG_1 1 +#define ADB_REG_2 2 +#define ADB_REG_3 3 + +/* ADB keyboard handler id */ +#define ADB_HANDLER_STD 0x01        /* IIGS, M0116 */ +#define ADB_HANDLER_AEK 0x02        /* M0115, M3501 */ +#define ADB_HANDLER_AEK_RMOD 0x03   /* M0115, M3501, alternate mode enableing right modifiers */ +#define ADB_HANDLER_STD_ISO 0x04    /* M0118, ISO swapping keys */ +#define ADB_HANDLER_AEK_ISO 0x05    /* M0115, M3501, ISO swapping keys */ +#define ADB_HANDLER_M1242_ANSI 0x10 /* Adjustable keyboard */ +#define ADB_HANDLER_CLASSIC1_MOUSE 0x01 +#define ADB_HANDLER_CLASSIC2_MOUSE 0x02 +#define ADB_HANDLER_EXTENDED_MOUSE 0x04 +#define ADB_HANDLER_TURBO_MOUSE 0x32 +  // ADB host  void     adb_host_init(void);  bool     adb_host_psw(void); +uint16_t adb_host_talk(uint8_t addr, uint8_t reg); +uint8_t  adb_host_talk_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len); +void     adb_host_listen(uint8_t addr, uint8_t reg, uint8_t data_h, uint8_t data_l); +void     adb_host_listen_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len); +void     adb_host_flush(uint8_t addr); +void     adb_host_kbd_led(uint8_t led);  uint16_t adb_host_kbd_recv(void);  uint16_t adb_host_mouse_recv(void); -void     adb_host_listen(uint8_t cmd, uint8_t data_h, uint8_t data_l); -void     adb_host_kbd_led(uint8_t led); -void     adb_mouse_task(void); -void     adb_mouse_init(void); + +// ADB Mouse +void adb_mouse_task(void); +void adb_mouse_init(void); diff --git a/tmk_core/protocol/arm_atsam/i2c_master.c b/tmk_core/protocol/arm_atsam/i2c_master.c index d3319ab447..dda2f85b00 100644 --- a/tmk_core/protocol/arm_atsam/i2c_master.c +++ b/tmk_core/protocol/arm_atsam/i2c_master.c @@ -28,6 +28,9 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #    define I2C_LED_USE_DMA 1  // Set 1 to use background DMA transfers for leds, Set 0 to use inline software transfers +DmacDescriptor dmac_desc; +DmacDescriptor dmac_desc_wb; +  static uint8_t i2c_led_q[I2C_Q_SIZE];  // I2C queue circular buffer  static uint8_t i2c_led_q_s;            // Start of circular buffer  static uint8_t i2c_led_q_e;            // End of circular buffer diff --git a/tmk_core/protocol/arm_atsam/i2c_master.h b/tmk_core/protocol/arm_atsam/i2c_master.h index 44dbdfbffa..68773f213f 100644 --- a/tmk_core/protocol/arm_atsam/i2c_master.h +++ b/tmk_core/protocol/arm_atsam/i2c_master.h @@ -24,8 +24,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #    include "issi3733_driver.h"  #    include "config.h" -__attribute__((__aligned__(16))) DmacDescriptor dmac_desc; -__attribute__((__aligned__(16))) DmacDescriptor dmac_desc_wb; +extern __attribute__((__aligned__(16))) DmacDescriptor dmac_desc; +extern __attribute__((__aligned__(16))) DmacDescriptor dmac_desc_wb;  uint8_t I2C3733_Init_Control(void);  uint8_t I2C3733_Init_Drivers(void); diff --git a/tmk_core/protocol/arm_atsam/main_arm_atsam.c b/tmk_core/protocol/arm_atsam/main_arm_atsam.c index e10be52fb8..a3d1f34496 100644 --- a/tmk_core/protocol/arm_atsam/main_arm_atsam.c +++ b/tmk_core/protocol/arm_atsam/main_arm_atsam.c @@ -306,9 +306,6 @@ int main(void) {          }  #endif  // CONSOLE_ENABLE -        // Run housekeeping -        housekeeping_task_kb(); -        housekeeping_task_user();      }      return 1; | 
