2011-07-20 15:32:52 +00:00
/*
Copyright 2011 Jun Wako < wakojun @ gmail . com >
This program is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
2011-01-02 14:52:13 +00:00
# include <stdint.h>
# include <util/delay.h>
2012-10-09 05:36:13 +00:00
# include "keycode.h"
2011-02-10 06:51:30 +00:00
# include "host.h"
# include "timer.h"
# include "print.h"
# include "debug.h"
2011-01-02 14:52:13 +00:00
# include "mousekey.h"
2011-02-10 06:51:30 +00:00
2011-01-02 14:52:13 +00:00
static uint8_t mousekey_repeat = 0 ;
2012-10-16 18:27:25 +00:00
static uint8_t mousekey_accel = 0 ;
2011-01-02 14:52:13 +00:00
2011-02-10 06:51:30 +00:00
static void mousekey_debug ( void ) ;
2011-01-02 14:52:13 +00:00
/*
2012-10-10 06:31:00 +00:00
* Mouse keys acceleration algorithm
* http : //en.wikipedia.org/wiki/Mouse_keys
*
* speed = delta * max_speed * ( repeat / time_to_max ) * * ( ( 1000 + curve ) / 1000 )
2011-01-02 14:52:13 +00:00
*/
2012-10-10 06:31:00 +00:00
/* milliseconds between the initial key press and first repeated motion event (0-2550) */
2012-10-16 18:27:25 +00:00
uint8_t mk_delay = MOUSEKEY_DELAY / 10 ;
2012-10-10 06:31:00 +00:00
/* milliseconds between repeated motion events (0-255) */
2012-10-16 18:27:25 +00:00
uint8_t mk_interval = MOUSEKEY_INTERVAL ;
2012-10-10 06:31:00 +00:00
/* steady speed (in action_delta units) applied each event (0-255) */
2012-10-16 18:27:25 +00:00
uint8_t mk_max_speed = MOUSEKEY_MAX_SPEED ;
2012-10-10 06:31:00 +00:00
/* number of events (count) accelerating to steady speed (0-255) */
2012-10-16 18:27:25 +00:00
uint8_t mk_time_to_max = MOUSEKEY_TIME_TO_MAX ;
2012-10-10 06:31:00 +00:00
/* ramp used to reach maximum pointer speed (NOT SUPPORTED) */
2012-10-16 18:27:25 +00:00
//int8_t mk_curve = 0;
/* wheel params */
uint8_t mk_wheel_max_speed = MOUSEKEY_WHEEL_MAX_SPEED ;
uint8_t mk_wheel_time_to_max = MOUSEKEY_WHEEL_TIME_TO_MAX ;
2012-10-05 17:23:12 +00:00
2012-10-10 06:31:00 +00:00
static uint16_t last_timer = 0 ;
2011-02-12 15:15:51 +00:00
2011-01-02 14:52:13 +00:00
2012-10-10 06:31:00 +00:00
static uint8_t move_unit ( void )
2011-01-02 14:52:13 +00:00
{
2012-10-10 06:31:00 +00:00
uint16_t unit ;
2012-10-16 18:27:25 +00:00
if ( mousekey_accel & ( 1 < < 0 ) ) {
unit = ( MOUSEKEY_MOVE_DELTA * mk_max_speed ) / 4 ;
} else if ( mousekey_accel & ( 1 < < 1 ) ) {
unit = ( MOUSEKEY_MOVE_DELTA * mk_max_speed ) / 2 ;
} else if ( mousekey_accel & ( 1 < < 2 ) ) {
unit = ( MOUSEKEY_MOVE_DELTA * mk_max_speed ) ;
} else if ( mousekey_repeat = = 0 ) {
unit = MOUSEKEY_MOVE_DELTA ;
} else if ( mousekey_repeat > = mk_time_to_max ) {
2012-10-10 06:31:00 +00:00
unit = MOUSEKEY_MOVE_DELTA * mk_max_speed ;
} else {
unit = ( MOUSEKEY_MOVE_DELTA * mk_max_speed * mousekey_repeat ) / mk_time_to_max ;
}
2012-10-16 18:27:25 +00:00
return ( unit > MOUSEKEY_MOVE_MAX ? MOUSEKEY_MOVE_MAX : ( unit = = 0 ? 1 : unit ) ) ;
2011-01-02 14:52:13 +00:00
}
2012-10-10 06:31:00 +00:00
static uint8_t wheel_unit ( void )
2012-10-10 02:06:47 +00:00
{
2012-10-10 06:31:00 +00:00
uint16_t unit ;
2012-10-16 18:27:25 +00:00
if ( mousekey_accel & ( 1 < < 0 ) ) {
unit = ( MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed ) / 4 ;
} else if ( mousekey_accel & ( 1 < < 1 ) ) {
unit = ( MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed ) / 2 ;
} else if ( mousekey_accel & ( 1 < < 2 ) ) {
unit = ( MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed ) ;
} else if ( mousekey_repeat = = 0 ) {
unit = MOUSEKEY_WHEEL_DELTA ;
2012-10-21 11:12:11 +00:00
} else if ( mousekey_repeat > = mk_wheel_time_to_max ) {
2012-10-10 06:31:00 +00:00
unit = MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed ;
} else {
2012-10-16 02:20:49 +00:00
unit = ( MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed * mousekey_repeat ) / mk_wheel_time_to_max ;
2012-10-10 06:31:00 +00:00
}
2012-10-16 18:27:25 +00:00
return ( unit > MOUSEKEY_WHEEL_MAX ? MOUSEKEY_WHEEL_MAX : ( unit = = 0 ? 1 : unit ) ) ;
2012-10-10 02:06:47 +00:00
}
2012-10-05 17:23:12 +00:00
void mousekey_task ( void )
2011-01-02 14:52:13 +00:00
{
2012-10-10 06:31:00 +00:00
if ( timer_elapsed ( last_timer ) < ( mousekey_repeat ? mk_interval : mk_delay * 10 ) )
2011-02-10 06:51:30 +00:00
return ;
2012-10-11 19:46:37 +00:00
if ( mouse_report . x = = 0 & & mouse_report . y = = 0 & & mouse_report . v = = 0 & & mouse_report . h = = 0 )
2012-10-05 17:23:12 +00:00
return ;
2011-02-10 06:51:30 +00:00
2012-10-05 17:23:12 +00:00
if ( mousekey_repeat ! = UINT8_MAX )
2011-02-12 15:15:51 +00:00
mousekey_repeat + + ;
2012-10-05 17:23:12 +00:00
2012-10-11 19:46:37 +00:00
if ( mouse_report . x > 0 ) mouse_report . x = move_unit ( ) ;
if ( mouse_report . x < 0 ) mouse_report . x = move_unit ( ) * - 1 ;
if ( mouse_report . y > 0 ) mouse_report . y = move_unit ( ) ;
if ( mouse_report . y < 0 ) mouse_report . y = move_unit ( ) * - 1 ;
2011-02-12 15:15:51 +00:00
2012-10-16 18:27:25 +00:00
/* diagonal move [1/sqrt(2) = 0.7] */
2012-10-11 19:46:37 +00:00
if ( mouse_report . x & & mouse_report . y ) {
mouse_report . x * = 0.7 ;
mouse_report . y * = 0.7 ;
2011-02-10 06:51:30 +00:00
}
2012-10-11 19:46:37 +00:00
if ( mouse_report . v > 0 ) mouse_report . v = wheel_unit ( ) ;
if ( mouse_report . v < 0 ) mouse_report . v = wheel_unit ( ) * - 1 ;
if ( mouse_report . h > 0 ) mouse_report . h = wheel_unit ( ) ;
if ( mouse_report . h < 0 ) mouse_report . h = wheel_unit ( ) * - 1 ;
2012-10-05 17:23:12 +00:00
mousekey_send ( ) ;
}
void mousekey_on ( uint8_t code )
{
2012-10-16 18:27:25 +00:00
if ( code = = KC_MS_UP ) mouse_report . y = move_unit ( ) * - 1 ;
else if ( code = = KC_MS_DOWN ) mouse_report . y = move_unit ( ) ;
else if ( code = = KC_MS_LEFT ) mouse_report . x = move_unit ( ) * - 1 ;
else if ( code = = KC_MS_RIGHT ) mouse_report . x = move_unit ( ) ;
else if ( code = = KC_MS_WH_UP ) mouse_report . v = wheel_unit ( ) ;
else if ( code = = KC_MS_WH_DOWN ) mouse_report . v = wheel_unit ( ) * - 1 ;
else if ( code = = KC_MS_WH_LEFT ) mouse_report . h = wheel_unit ( ) * - 1 ;
else if ( code = = KC_MS_WH_RIGHT ) mouse_report . h = wheel_unit ( ) ;
2012-10-11 19:46:37 +00:00
else if ( code = = KC_MS_BTN1 ) mouse_report . buttons | = MOUSE_BTN1 ;
else if ( code = = KC_MS_BTN2 ) mouse_report . buttons | = MOUSE_BTN2 ;
else if ( code = = KC_MS_BTN3 ) mouse_report . buttons | = MOUSE_BTN3 ;
else if ( code = = KC_MS_BTN4 ) mouse_report . buttons | = MOUSE_BTN4 ;
else if ( code = = KC_MS_BTN5 ) mouse_report . buttons | = MOUSE_BTN5 ;
2012-10-16 18:27:25 +00:00
else if ( code = = KC_MS_ACCEL0 ) mousekey_accel | = ( 1 < < 0 ) ;
else if ( code = = KC_MS_ACCEL1 ) mousekey_accel | = ( 1 < < 1 ) ;
else if ( code = = KC_MS_ACCEL2 ) mousekey_accel | = ( 1 < < 2 ) ;
2012-10-05 17:23:12 +00:00
}
void mousekey_off ( uint8_t code )
{
2012-10-11 19:46:37 +00:00
if ( code = = KC_MS_UP & & mouse_report . y < 0 ) mouse_report . y = 0 ;
else if ( code = = KC_MS_DOWN & & mouse_report . y > 0 ) mouse_report . y = 0 ;
else if ( code = = KC_MS_LEFT & & mouse_report . x < 0 ) mouse_report . x = 0 ;
else if ( code = = KC_MS_RIGHT & & mouse_report . x > 0 ) mouse_report . x = 0 ;
else if ( code = = KC_MS_WH_UP & & mouse_report . v > 0 ) mouse_report . v = 0 ;
else if ( code = = KC_MS_WH_DOWN & & mouse_report . v < 0 ) mouse_report . v = 0 ;
else if ( code = = KC_MS_WH_LEFT & & mouse_report . h < 0 ) mouse_report . h = 0 ;
else if ( code = = KC_MS_WH_RIGHT & & mouse_report . h > 0 ) mouse_report . h = 0 ;
else if ( code = = KC_MS_BTN1 ) mouse_report . buttons & = ~ MOUSE_BTN1 ;
else if ( code = = KC_MS_BTN2 ) mouse_report . buttons & = ~ MOUSE_BTN2 ;
else if ( code = = KC_MS_BTN3 ) mouse_report . buttons & = ~ MOUSE_BTN3 ;
else if ( code = = KC_MS_BTN4 ) mouse_report . buttons & = ~ MOUSE_BTN4 ;
else if ( code = = KC_MS_BTN5 ) mouse_report . buttons & = ~ MOUSE_BTN5 ;
2012-10-16 18:27:25 +00:00
else if ( code = = KC_MS_ACCEL0 ) mousekey_accel & = ~ ( 1 < < 0 ) ;
else if ( code = = KC_MS_ACCEL1 ) mousekey_accel & = ~ ( 1 < < 1 ) ;
else if ( code = = KC_MS_ACCEL2 ) mousekey_accel & = ~ ( 1 < < 2 ) ;
2012-10-11 19:46:37 +00:00
if ( mouse_report . x = = 0 & & mouse_report . y = = 0 & & mouse_report . v = = 0 & & mouse_report . h = = 0 )
2012-10-05 17:23:12 +00:00
mousekey_repeat = 0 ;
}
void mousekey_send ( void )
{
2011-02-10 06:51:30 +00:00
mousekey_debug ( ) ;
2012-10-11 19:46:37 +00:00
host_mouse_send ( & mouse_report ) ;
2011-02-10 06:51:30 +00:00
last_timer = timer_read ( ) ;
}
2012-10-05 17:23:12 +00:00
void mousekey_clear ( void )
2011-02-10 06:51:30 +00:00
{
2012-10-11 19:46:37 +00:00
mouse_report = ( report_mouse_t ) { } ;
2012-10-16 18:27:25 +00:00
mousekey_repeat = 0 ;
mousekey_accel = 0 ;
2011-02-10 06:51:30 +00:00
}
static void mousekey_debug ( void )
{
if ( ! debug_mouse ) return ;
2012-10-16 18:27:25 +00:00
print ( " mousekey [btn|x y v h](rep/acl): [ " ) ;
2012-10-11 19:46:37 +00:00
phex ( mouse_report . buttons ) ; print ( " | " ) ;
2012-10-24 18:28:25 +00:00
print_decs ( mouse_report . x ) ; print ( " " ) ;
print_decs ( mouse_report . y ) ; print ( " " ) ;
print_decs ( mouse_report . v ) ; print ( " " ) ;
print_decs ( mouse_report . h ) ; print ( " ]( " ) ;
print_dec ( mousekey_repeat ) ; print ( " / " ) ;
print_dec ( mousekey_accel ) ; print ( " ) \n " ) ;
2011-01-02 14:52:13 +00:00
}