aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--int33.h36
-rw-r--r--mousetsr.c53
-rw-r--r--mousetsr.h6
-rw-r--r--mousmain.c6
-rw-r--r--moustest.c39
-rw-r--r--utils.h19
6 files changed, 131 insertions, 28 deletions
diff --git a/int33.h b/int33.h
index df870be..f9191ce 100644
--- a/int33.h
+++ b/int33.h
@@ -114,12 +114,38 @@ enum INT33_API {
INT33_SAVE_MOUSE_STATUS = 0x16,
INT33_LOAD_MOUSE_STATUS = 0x17,
- /** Sets both speed and speed-doubling threshold in one call.
- * @param bx horizontal speed, cx vertical speed
- * @param dx doubling threshold (mickeys per second). */
+ /** Sets both sensitivity and speed-doubling threshold in one call.
+ * @param bx horizontal sensitivity, cx vertical sensitivity
+ * these are values from 5..100.
+ * @param dx speed doubling threshold (mickeys per second?).
+ * Unlike set_mouse_speed, this value is persistent, and survives a reset.
+ * MS doesn't define what "sensitivity" means here, however MSD does print
+ * a table of common sensitivity values and their equivalent "factor",
+ * which is applied to the mouse deltas:
+ * 100 - 3.5 (i.e. mouse is 3.5x faster)
+ * 95 - 3.25
+ * 90 - 3
+ * 85 - 2.75
+ * 80 - 2.5
+ * 75 - 2.25
+ * 70 - 2
+ * 65 - 1.75
+ * 60 - 1.5
+ * 55 - 1.25
+ * 50 - 1 (default value, mouse is 1x)
+ * 45 - 0.875
+ * 40 - 0.75
+ * 35 - 0.625
+ * 30 - 0.5
+ * 25 - 0.375
+ * 20 - 0.25
+ * 15 - 0.125
+ * 10 - 0.062
+ * 5 - 0.031 (MSD prints 0.31 though? looks buggy as hell).
+ * @todo verify if the doubling threshold here is in the same units. */
INT33_SET_MOUSE_SENSITIVITY = 0x1A,
- /** Gets current speed and speed-doubling threshold.
- * @return bx horizontal speed, cx vertical speed
+ /** Gets current sensitivity and speed-doubling threshold.
+ * @return bx horizontal sensitivity, cx vertical sensitivity
* @return dx doubling threshold (mickeys per second). */
INT33_GET_MOUSE_SENSITIVITY = 0x1B,
diff --git a/mousetsr.c b/mousetsr.c
index 16c84df..f5caf59 100644
--- a/mousetsr.c
+++ b/mousetsr.c
@@ -60,6 +60,30 @@ static void bound_position_to_window(void)
if (data.pos.y > data.max.y) data.pos.y = data.max.y;
}
+/** Apply sensitivity to a raw mouse delta.
+ * @param sens value [5..100] given to set_mouse_sensitivity.
+ * @param x mouse delta in mickeys
+ * @return mouse delta scaled by sensitivity
+ *
+ * Note this is not acceleration, we are still multiplying the delta by a
+ * linear factor supposedly derived from the sensivitity [5..100] value.
+ * Every mouse driver seems to use their own formula for computing this factor.
+ * I am going with f(x) = x(x+32)/4096 since it looks round and fits decently,
+ * even with integer math (we don't divide by 4096 until after multiplying by delta).
+ * @see INT33_SET_MOUSE_SENSITIVITY for what the factor should look like. */
+int16_t apply_sensitivity(int16_t x, uint8_t sens)
+{
+ uint16_t factor = (sens * (sens + 32));
+#if 1
+ // use shift by 12 rather than divide by 4096
+ // unsigned math, otherwise negative values would round down when shifted
+ uint16_t scaled = scaleu_shift(abs(x), 12 /*4096*/, factor);
+ return x < 0 ? -scaled : scaled;
+#else
+ return scalei(x, 4096, factor);
+#endif
+}
+
/** Constraints coordinate value to the desired granularity,
* which must be a power of two. */
static inline int16_t snap_to_grid(int16_t val, int16_t granularity)
@@ -646,6 +670,10 @@ static void handle_mouse_event(uint16_t buttons, bool absolute, int x, int y, ch
}
data.total_motion += ax * ax + ay * ay;
+ // Apply sensitivity now, since unlike acceleration/speed, it affects the raw mickey counters
+ x = apply_sensitivity(x, data.sensitivity_x);
+ y = apply_sensitivity(y, data.sensitivity_y);
+
// Update the raw mickey counters
data.delta.x += x;
data.delta.y += y;
@@ -654,11 +682,11 @@ static void handle_mouse_event(uint16_t buttons, bool absolute, int x, int y, ch
data.abs_pos.x = -1;
data.abs_pos.y = -1;
- // Convert mickeys into pixels, applying speed, sensitivity and acceleration
+ // Convert mickeys into pixels, applying speed and acceleration
// If more than the double speed threshold has been moved in the last second,
// double the speed
- if (data.cur_speed > data.doubleSpeedThreshold * data.doubleSpeedThreshold) {
+ if (data.cur_speed > data.double_speed_threshold * data.double_speed_threshold) {
x *= 2;
y *= 2;
}
@@ -1172,7 +1200,7 @@ static void reset_mouse_settings()
data.mickeysPerLine.x = 8;
data.mickeysPerLine.y = 16;
- data.doubleSpeedThreshold = 64;
+ data.double_speed_threshold = 64;
data.min.x = 0;
data.max.x = data.screen_max.x;
data.min.y = 0;
@@ -1185,6 +1213,10 @@ static void reset_mouse_settings()
data.cursor_hotspot.y = 0;
memcpy(data.cursor_graphic, default_cursor_graphic, sizeof(data.cursor_graphic));
+ // Sensitivity is persisted through resets, but ensure we init it with 50 if 0.
+ if (data.sensitivity_x == 0) data.sensitivity_x = 50;
+ if (data.sensitivity_y == 0) data.sensitivity_y = 50;
+
refresh_cursor(); // This will hide the cursor and update data.cursor_visible
}
@@ -1414,7 +1446,7 @@ static void int33_handler(union INTPACK r)
break;
case INT33_SET_SPEED_DOUBLE_THRESHOLD:
dprintf("Mouse set speed double threshold=%d\n", r.w.dx);
- data.doubleSpeedThreshold = r.w.dx;
+ data.double_speed_threshold = r.w.dx;
break;
case INT33_EXCHANGE_EVENT_HANDLER:
dputs("Mouse exchange event handler");
@@ -1446,15 +1478,14 @@ static void int33_handler(union INTPACK r)
case INT33_SET_MOUSE_SENSITIVITY:
dprintf("Mouse set sensitivity x=%d y=%d threshold=%d\n",
r.w.bx, r.w.cx, r.w.dx);
- // TODO According to cutemouse, sensitivity != mickeysPerLine
- data.mickeysPerLine.x = r.w.bx;
- data.mickeysPerLine.y = r.w.cx;
- data.doubleSpeedThreshold = r.w.dx;
+ data.sensitivity_x = BOUND(r.w.bx, 1, 100);
+ data.sensitivity_y = BOUND(r.w.cx, 1, 100);
+ data.double_speed_threshold = r.w.dx;
break;
case INT33_GET_MOUSE_SENSITIVITY:
- r.w.bx = data.mickeysPerLine.x;
- r.w.cx = data.mickeysPerLine.y;
- r.w.dx = data.doubleSpeedThreshold;
+ r.w.bx = data.sensitivity_x;
+ r.w.cx = data.sensitivity_y;
+ r.w.dx = data.double_speed_threshold;
break;
case INT33_RESET_SETTINGS:
dputs("Mouse reset settings");
diff --git a/mousetsr.h b/mousetsr.h
index 9b8fdf8..93503c5 100644
--- a/mousetsr.h
+++ b/mousetsr.h
@@ -161,8 +161,12 @@ typedef struct tsrdata {
// Current mouse settings
/** Mouse speed, in mickeys per "line" (aka 8 pixels). */
struct point mickeysPerLine;
+ /** Mouse sensitivity, in 1..100. */
+ uint8_t sensitivity_x, sensitivity_y;
+ /** Mouse sensitivity factor, precalculated. */
+ struct point sensitivity_factor;
/** Mouse acceleration "double-speed threshold", in mickeys per second. */
- uint16_t doubleSpeedThreshold;
+ uint16_t double_speed_threshold;
/** Current window min coordinates. */
struct point min;
/** Current window max coordinates. */
diff --git a/mousmain.c b/mousmain.c
index 24801b7..dcc9de9 100644
--- a/mousmain.c
+++ b/mousmain.c
@@ -354,8 +354,8 @@ static int configure_driver_serial(LPTSRDATA data, int port, unsigned iobase)
serial_set_modem_control(iobase, SERIAL_MCR_DTR | SERIAL_MCR_RTS);
dputs("DTR ON, RTS ON");
- // Wait up to 10 ticks (550ms) for the mouse to send something we understand
- for (delay = 10; delay > 0; delay--) {
+ // Wait up to 11 ticks (~600ms) for the mouse to send something we understand
+ for (delay = 11; delay > 0; delay--) {
while (serial_data_ready(iobase)) {
uint8_t car = serial_read_data(iobase);
@@ -429,7 +429,7 @@ static int configure_driver_serial(LPTSRDATA data, int port, unsigned iobase)
}
#endif
-/// Auto-configure the TSR. Try to detect which mouse we have connected and enable all possible integrations.
+/// Configure the TSR. Try to detect which mouse we have connected and enable all possible integrations.
static int configure_driver(LPTSRDATA data, unsigned num_ports, int ports[])
{
int errs[MAX_PORTS+1] = {0};
diff --git a/moustest.c b/moustest.c
index 3270c9c..0d71921 100644
--- a/moustest.c
+++ b/moustest.c
@@ -142,7 +142,7 @@ void gui_draw_title()
const int cols = vidconf.numtextcols;
gui_draw_textwindow(1, 1, 1, cols, GUI_COLOR_BAR);
- gui_print(GUI_COLOR_BAR, "MOUSTEST ESC to exit, 'm'ode, 'r'eset, 's'how, 'h'ide, s'p'eed");
+ gui_print(GUI_COLOR_BAR, "MOUSTEST ESC to exit, 'm'ode, 'r'eset, 's'how, 'h'ide, s'p'eed, sensi't'");
}
void gui_draw_status()
@@ -585,6 +585,35 @@ void mouse_report()
void mouse_speed()
{
+ uint16_t speed_x = 8, speed_y = 16;
+ bool update = false;
+ char buffer[16] = {'\0'};
+ int ret;
+
+ console_printf("X speed [default=8] ? ");
+ ret = console_getline(buffer, sizeof(buffer)-1);
+ if (ret > 0) {
+ speed_x = atoi(buffer);
+ update = true;
+ }
+
+ console_printf("Y speed [default=16] ? ");
+ ret = console_getline(buffer, sizeof(buffer)-1);
+ if (ret > 0) {
+ speed_y = atoi(buffer);
+ update = true;
+ }
+
+ if (update) {
+ int33_set_mouse_speed(speed_x, speed_y);
+ console_printf("Values updated: %u %u\n", speed_x, speed_y);
+ } else {
+ console_printf("No values changed\n");
+ }
+}
+
+void mouse_sensitivity()
+{
uint16_t speed_x, speed_y, double_speed_threshold;
bool update = false;
char buffer[16] = {'\0'};
@@ -592,14 +621,14 @@ void mouse_speed()
int33_get_sensitivity(&speed_x, &speed_y, &double_speed_threshold);
- console_printf("X speed [default=8, current=%u] ? ", speed_x);
+ console_printf("X sensitivity [default=50, current=%u] ? ", speed_x);
ret = console_getline(buffer, sizeof(buffer)-1);
if (ret > 0) {
speed_x = atoi(buffer);
update = true;
}
- console_printf("Y speed [default=16, current=%u] ? ", speed_y);
+ console_printf("Y sensitivity [default=50, current=%u] ? ", speed_y);
ret = console_getline(buffer, sizeof(buffer)-1);
if (ret > 0) {
speed_y = atoi(buffer);
@@ -797,6 +826,10 @@ int main(int argc, const char *argv[])
break;
case 'p':
mouse_speed();
+ break;
+ case 't':
+ mouse_sensitivity();
+ break;
case 'd':
mouse_debug();
break;
diff --git a/utils.h b/utils.h
index 9b9db2a..e1258c9 100644
--- a/utils.h
+++ b/utils.h
@@ -60,7 +60,17 @@ static unsigned scaleu(unsigned x, unsigned srcmax, unsigned dstmax);
"div bx" /* ax = dx:ax / srcmax */\
__parm [ax] [bx] [cx] \
__value [ax] \
- __modify [ax dx]
+ __modify exact [ax dx]
+
+/** Map x linearly from range [0, srcmax] to [0, 2^dstmax].
+ * Equivalent to above, but uses shift instead of division. */
+static unsigned scaleu_shift(unsigned x, unsigned char srcmax, unsigned dstmax);
+#pragma aux scaleu_shift = \
+ "mul dx" /* dx:ax = x * dstmax */ \
+ "shrd ax, dx, cl" /* ax = dx:ax / 2^srcmax */ \
+ __parm [ax] [cl] [dx] \
+ __value [ax] \
+ __modify exact [ax dx]
/** Map x linearly from range [0, srcmax] to [0, dstmax].
* Equivalent of (x * dstmax) / srcmax but with 32-bit signed precision. */
@@ -70,12 +80,11 @@ static int scalei(int x, int srcmax, int dstmax);
"idiv bx" /* ax = dx:ax / srcmax */ \
__parm [ax] [bx] [cx] \
__value [ax] \
- __modify [ax dx]
+ __modify exact [ax dx]
/** Map x linearly from range [0, srcmax] to [0, dstmax].
- * Equivalent of (x * dstmax) / srcmax but with 32-bit signed precision.
- * Division remainder is returned in rem, which should be reused
- * in future calls to reduce rounding error. */
+ * Equivalent to scalei, but the division remainder is returned in rem,
+ * which can be reused in future calls to reduce rounding error. */
static int scalei_rem(int x, int srcmax, int dstmax, short *rem);
#pragma aux scalei_rem = \
"imul cx" /* dx:ax = x * dstmax */ \