Skip to content

Commit

Permalink
Introduce mouse velocity vector
Browse files Browse the repository at this point in the history
For more smooth movement, let the firmware
calculate x,y movement over timer based
on a velocity vector given to a newly
introduced velocityXY GATT characteristic
  • Loading branch information
larsgk committed Feb 3, 2023
1 parent 5ad3b66 commit 5cabb7e
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 22 deletions.
64 changes: 56 additions & 8 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@
* SPDX-License-Identifier: Apache-2.0
*/

#include <zephyr.h>
#include <zephyr/kernel.h>

#include <usb/usb_device.h>
#include <usb/class/usb_hid.h>
#include <zephyr/usb/usb_device.h>
#include <zephyr/usb/class/usb_hid.h>

#include <bluetooth/bluetooth.h>
#include <bluetooth/conn.h>
#include <bluetooth/gatt.h>
#include <bluetooth/hci.h>
#include <bluetooth/uuid.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/gatt.h>
#include <zephyr/bluetooth/hci.h>
#include <zephyr/bluetooth/uuid.h>

#include "simplems.h"

Expand Down Expand Up @@ -82,8 +82,52 @@ static void sm_buttons_cb(uint8_t buttons)
}
}

// Velocity is ~ *2 px/s
static int32_t _dx;
static int32_t _dy;
static int16_t _vx;
static int16_t _vy;

static void sm_velocity_xy_cb(int16_t vx, int16_t vy) {
printk("Velocity (x,y) = (%d, %d)\n", vx, vy);

_vx = vx;
_vy = vy;
}

#define ABS(x) (x > 0 ? x : -x)

static int16_t overflow(uint32_t *delta, uint16_t velocity)
{
int16_t overflow;
*delta += velocity;

overflow = *delta / 256;

*delta = *delta % 0xff;

return overflow;
}

void apply_velocity(struct k_timer *dummy)
{
int8_t mx;
int8_t my;

mx = (int8_t)overflow(&_dx, _vx);
my = (int8_t)overflow(&_dy, _vy);

if (mx || my) {
sm_move_xy_cb(mx, my);
}
}

K_TIMER_DEFINE(velocity_timer, apply_velocity, NULL);


struct bt_simple_mouse_cb sm_cbs = {
.move_xy = sm_move_xy_cb,
.velocity_xy = sm_velocity_xy_cb,
.buttons = sm_buttons_cb,
};

Expand All @@ -110,12 +154,16 @@ static void connected(struct bt_conn *conn, uint8_t err)
printk("Connection failed (err 0x%02x)\n", err);
} else {
printk("Connected\n");
_dx = 0;
_dy = 0;
k_timer_start(&velocity_timer, K_MSEC(8), K_MSEC(8));
}
}

static void disconnected(struct bt_conn *conn, uint8_t reason)
{
printk("Disconnected (reason 0x%02x)\n", reason);
k_timer_stop(&velocity_timer);
}

BT_CONN_CB_DEFINE(conn_callbacks) = {
Expand Down
48 changes: 39 additions & 9 deletions src/simplems.c
Original file line number Diff line number Diff line change
@@ -1,28 +1,32 @@
#include <zephyr/types.h>
#include <stddef.h>
#include <string.h>
#include <errno.h>
#include <zephyr.h>
#include <init.h>
#include <zephyr/kernel.h>
#include <zephyr/init.h>
#include <zephyr/types.h>

#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/conn.h>
#include <bluetooth/uuid.h>
#include <bluetooth/gatt.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/hci.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/uuid.h>
#include <zephyr/bluetooth/gatt.h>

#include "simplems.h"

static struct bt_uuid_128 simplems_uuid = BT_UUID_INIT_128(
BT_UUID_SIMPLE_MOUSE_SERVICE);

// 0x56beb2d8, 0x64eb, 0x4e33, 0x96d4, 0xe3f394041d0b (svc)
// 0x83986548, 0x8703, 0x4272, 0xa124, 0x84abb9d03217 (xy)
// 0x83986548, 0x8703, 0x4272, 0xa124, 0x84abb9d03217 (move xy)
// 0x3cabb56e, 0x27a7, 0x45fa, 0x996a, 0x582f581d6aa3 (velocity xy)
// 0x5062c9c1, 0xca09, 0x47f9, 0x84f6, 0x725ef8091bf9 (btn)

static const struct bt_uuid_128 simplems_move_xy_uuid = BT_UUID_INIT_128(
BT_UUID_128_ENCODE(0x83986548, 0x8703, 0x4272, 0xa124, 0x84abb9d03217));

static const struct bt_uuid_128 simplems_velocity_xy_uuid = BT_UUID_INIT_128(
BT_UUID_128_ENCODE(0x3cabb56e, 0x27a7, 0x45fa, 0x996a, 0x582f581d6aa3));

static const struct bt_uuid_128 simplems_buttons_uuid = BT_UUID_INIT_128(
BT_UUID_128_ENCODE(0x5062c9c1, 0xca09, 0x47f9, 0x84f6, 0x725ef8091bf9));

Expand Down Expand Up @@ -56,6 +60,28 @@ static ssize_t write_move_xy(struct bt_conn *conn,
return len;
}

static ssize_t write_velocity_xy(struct bt_conn *conn,
const struct bt_gatt_attr *attr,
const void *buf, uint16_t len,
uint16_t offset, uint8_t flags)
{
int16_t val[2];

if (offset != 0) {
return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
} else if (len != sizeof(val)) {
return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
}

(void)memcpy(&val, buf, len);

if (sm_cbs->velocity_xy) {
sm_cbs->velocity_xy(val[0], val[1]);
}

return len;
}

static ssize_t write_buttons(struct bt_conn *conn,
const struct bt_gatt_attr *attr,
const void *buf, uint16_t len,
Expand Down Expand Up @@ -85,6 +111,10 @@ BT_GATT_SERVICE_DEFINE(sm_svc,
BT_GATT_PERM_WRITE,
NULL, write_move_xy, NULL),
BT_GATT_CUD("Move XY", BT_GATT_PERM_READ),
BT_GATT_CHARACTERISTIC(&simplems_velocity_xy_uuid.uuid, BT_GATT_CHRC_WRITE,
BT_GATT_PERM_WRITE,
NULL, write_velocity_xy, NULL),
BT_GATT_CUD("Velocity XY", BT_GATT_PERM_READ),
BT_GATT_CHARACTERISTIC(&simplems_buttons_uuid.uuid, BT_GATT_CHRC_WRITE,
BT_GATT_PERM_WRITE,
NULL, write_buttons, NULL),
Expand Down
7 changes: 5 additions & 2 deletions src/simplems.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,20 @@ extern "C" {

// 56beb2d8-64eb-4e33-96d4-e3f394041d0b (service)
// 83986548-8703-4272-a124-84abb9d03217 (move x & y)
// 3cabb56e-27a7-45fa-996a-582f581d6aa3 (velocity x & y)
// 5062c9c1-ca09-47f9-84f6-725ef8091bf9 (buttons)

#define BT_UUID_SIMPLE_MOUSE_SERVICE \
BT_UUID_128_ENCODE(0x56beb2d8, 0x64eb, 0x4e33, 0x96d4, 0xe3f394041d0b)

typedef void (*simple_mouse_move_xy_cb)(int8_t distx, int8_t disty);
typedef void (*simple_mouse_velocity_xy_cb)(int16_t vx, int16_t vy);
typedef void (*simple_mouse_buttons_cb)(uint8_t buttons);

struct bt_simple_mouse_cb {
simple_mouse_move_xy_cb move_xy;
simple_mouse_buttons_cb buttons;
simple_mouse_move_xy_cb move_xy;
simple_mouse_velocity_xy_cb velocity_xy;
simple_mouse_buttons_cb buttons;
};

void bt_simple_mouse_register_cb(struct bt_simple_mouse_cb *cb);
Expand Down
18 changes: 16 additions & 2 deletions web/main-app.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import { MultiJoystick } from './multi-joystick.js';
import { SimpleDriver } from './simple-driver.js';

const _use_velocity = false;

const template = document.createElement('template');
template.innerHTML = `
<style>
Expand Down Expand Up @@ -168,14 +170,26 @@ export class MainApp extends HTMLElement {
this.#initButtonHandlers();

this.#joystick = this.shadowRoot.querySelector('multi-joystick');
this.#joystick.addEventListener('move', e => this.#lastpos = e.detail.pos);

if (_use_velocity) {
this.#joystick.addEventListener('move', e => {
this.#lastpos = e.detail.pos;
if (this.#lastpos) {
SimpleDriver.velocity(this.#lastpos.x*2000, this.#lastpos.y*2000);
} else {
SimpleDriver.velocity(0, 0);
}
});
} else {
this.#joystick.addEventListener('move', e => this.#lastpos = e.detail.pos);
setInterval(this.doMove, 100);
}

this.#connectbtn.addEventListener('click', this.toggleConnection);

SimpleDriver.addEventListener('connect', this.handleConnect);
SimpleDriver.addEventListener('disconnect', this.handleDisconnect);

setInterval(this.doMove, 100);
}

// TODO: Cleanup
Expand Down
13 changes: 12 additions & 1 deletion web/simple-driver.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

const SimpleMouseLinkUUID = '56beb2d8-64eb-4e33-96d4-e3f394041d0b';
const SimpleMouseMoveXYUUID = '83986548-8703-4272-a124-84abb9d03217';
const SimpleMouseVelocityXYUUID = '3cabb56e-27a7-45fa-996a-582f581d6aa3';
const SimpleMouseButtonsUUID = '5062c9c1-ca09-47f9-84f6-725ef8091bf9';

const cap_val = (val) => {
Expand All @@ -31,7 +32,16 @@ export const SimpleDriver = new class extends EventTarget {
const xx = cap_val(x);
const yy = cap_val(y);
console.log("Mouse move:", xx, yy)
if (xx || yy) this.#writeFuncs.move_xy.writeValue(new Uint8Array([xx, yy]));
if (xx || yy) this.#writeFuncs.move_xy.writeValue(new Int8Array([xx, yy]));
}
}

velocity(x, y) {
if (this.#writeFuncs.velocity_xy) {
const xx = Math.round(x);
const yy = Math.round(y);
console.log("Mouse velocity:", xx, yy)
this.#writeFuncs.velocity_xy.writeValue(new Int16Array([xx, yy]));
}
}

Expand All @@ -46,6 +56,7 @@ export const SimpleDriver = new class extends EventTarget {
async fetchWriteCharacteristics(server) {
const service = await server.getPrimaryService(SimpleMouseLinkUUID);
this.#writeFuncs.move_xy = await service.getCharacteristic(SimpleMouseMoveXYUUID);
this.#writeFuncs.velocity_xy = await service.getCharacteristic(SimpleMouseVelocityXYUUID);
this.#writeFuncs.buttons = await service.getCharacteristic(SimpleMouseButtonsUUID);
}

Expand Down

0 comments on commit 5cabb7e

Please sign in to comment.