[Core] Split support for pointing devices. (#15304)
* Draft implementation * formatting * fix combined buttons * remove pimoroni throttle * sync pointing on a throttle loop with checksum * no longer used * doh Co-authored-by: Drashna Jaelre <drashna@live.com> * switch pimoroni to a cpi equivalent * add cpi support * allow user modification of seperate mouse reports * a little tidy up * add *_RIGHT defines. * docs * doxygen comments * basic changelog * clean up pimoroni * small doc fixes * Update docs/feature_pointing_device.md Co-authored-by: Drashna Jaelre <drashna@live.com> * performance tweak if side has usb * Don't run init funtions on wrong side * renamed some variables for consistency * fix pimoroni typos * Clamp instead of OR * Promote combined values to uint16_t * Update pointing_device.c Co-authored-by: Drashna Jaelre <drashna@live.com> Co-authored-by: Nick Brassel <nick@tzarc.org>
This commit is contained in:
		
							parent
							
								
									76a673233c
								
							
						
					
					
						commit
						7f7364c559
					
				
					 11 changed files with 625 additions and 65 deletions
				
			
		| 
						 | 
				
			
			@ -18,24 +18,105 @@
 | 
			
		|||
 | 
			
		||||
#include "pointing_device.h"
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "timer.h"
 | 
			
		||||
#ifdef MOUSEKEY_ENABLE
 | 
			
		||||
#    include "mousekey.h"
 | 
			
		||||
#endif
 | 
			
		||||
#if (defined(POINTING_DEVICE_ROTATION_90) + defined(POINTING_DEVICE_ROTATION_180) + defined(POINTING_DEVICE_ROTATION_270)) > 1
 | 
			
		||||
#    error More than one rotation selected.  This is not supported.
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(SPLIT_POINTING_ENABLE)
 | 
			
		||||
#    include "transactions.h"
 | 
			
		||||
#    include "keyboard.h"
 | 
			
		||||
 | 
			
		||||
static report_mouse_t mouseReport = {};
 | 
			
		||||
report_mouse_t shared_mouse_report = {};
 | 
			
		||||
uint16_t       shared_cpi          = 0;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Sets the shared mouse report used be pointing device task
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE : Only available when using SPLIT_POINTING_ENABLE
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] new_mouse_report report_mouse_t
 | 
			
		||||
 */
 | 
			
		||||
void pointing_device_set_shared_report(report_mouse_t new_mouse_report) { shared_mouse_report = new_mouse_report; }
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Gets current pointing device CPI if supported
 | 
			
		||||
 *
 | 
			
		||||
 * Gets current cpi of the shared report and returns it as uint16_t
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE : Only available when using SPLIT_POINTING_ENABLE
 | 
			
		||||
 *
 | 
			
		||||
 * @return cpi value as uint16_t
 | 
			
		||||
 */
 | 
			
		||||
uint16_t pointing_device_get_shared_cpi(void) { return shared_cpi; }
 | 
			
		||||
 | 
			
		||||
#    if defined(POINTING_DEVICE_LEFT)
 | 
			
		||||
#        define POINTING_DEVICE_THIS_SIDE is_keyboard_left()
 | 
			
		||||
#    elif defined(POINTING_DEVICE_RIGHT)
 | 
			
		||||
#        define POINTING_DEVICE_THIS_SIDE !is_keyboard_left()
 | 
			
		||||
#    elif defined(POINTING_DEVICE_COMBINED)
 | 
			
		||||
#        define POINTING_DEVICE_THIS_SIDE true
 | 
			
		||||
#    endif
 | 
			
		||||
 | 
			
		||||
#endif  // defined(SPLIT_POINTING_ENABLE)
 | 
			
		||||
 | 
			
		||||
static report_mouse_t local_mouse_report = {};
 | 
			
		||||
 | 
			
		||||
extern const pointing_device_driver_t pointing_device_driver;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Compares 2 mouse reports for difference and returns result
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] new report_mouse_t
 | 
			
		||||
 * @param[in] old report_mouse_t
 | 
			
		||||
 * @return bool result
 | 
			
		||||
 */
 | 
			
		||||
__attribute__((weak)) bool has_mouse_report_changed(report_mouse_t new, report_mouse_t old) { return memcmp(&new, &old, sizeof(new)); }
 | 
			
		||||
 | 
			
		||||
__attribute__((weak)) void           pointing_device_init_kb(void) {}
 | 
			
		||||
__attribute__((weak)) void           pointing_device_init_user(void) {}
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Keyboard level code pointing device initialisation
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
__attribute__((weak)) void pointing_device_init_kb(void) {}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief User level code pointing device initialisation
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
__attribute__((weak)) void pointing_device_init_user(void) {}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Weak function allowing for keyboard level mouse report modification
 | 
			
		||||
 *
 | 
			
		||||
 * Takes report_mouse_t struct allowing modification at keyboard level then returns report_mouse_t.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] mouse_report report_mouse_t
 | 
			
		||||
 * @return report_mouse_t
 | 
			
		||||
 */
 | 
			
		||||
__attribute__((weak)) report_mouse_t pointing_device_task_kb(report_mouse_t mouse_report) { return pointing_device_task_user(mouse_report); }
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Weak function allowing for user level mouse report modification
 | 
			
		||||
 *
 | 
			
		||||
 * Takes report_mouse_t struct allowing modification at user level then returns report_mouse_t.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] mouse_report report_mouse_t
 | 
			
		||||
 * @return report_mouse_t
 | 
			
		||||
 */
 | 
			
		||||
__attribute__((weak)) report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) { return mouse_report; }
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Handles pointing device buttons
 | 
			
		||||
 *
 | 
			
		||||
 * Returns modified button bitmask using bool pressed and selected pointing_device_buttons_t button in uint8_t buttons bitmask.
 | 
			
		||||
 *
 | 
			
		||||
 * @param buttons[in] uint8_t bitmask
 | 
			
		||||
 * @param pressed[in] bool
 | 
			
		||||
 * @param button[in] pointing_device_buttons_t value
 | 
			
		||||
 * @return Modified uint8_t bitmask buttons
 | 
			
		||||
 */
 | 
			
		||||
__attribute__((weak)) uint8_t pointing_device_handle_buttons(uint8_t buttons, bool pressed, pointing_device_buttons_t button) {
 | 
			
		||||
    if (pressed) {
 | 
			
		||||
        buttons |= 1 << (button);
 | 
			
		||||
| 
						 | 
				
			
			@ -45,7 +126,17 @@ __attribute__((weak)) uint8_t pointing_device_handle_buttons(uint8_t buttons, bo
 | 
			
		|||
    return buttons;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Initialises pointing device
 | 
			
		||||
 *
 | 
			
		||||
 * Initialises pointing device, perform driver init and optional keyboard/user level code.
 | 
			
		||||
 */
 | 
			
		||||
__attribute__((weak)) void pointing_device_init(void) {
 | 
			
		||||
#if defined(SPLIT_POINTING_ENABLE)
 | 
			
		||||
    if (!(POINTING_DEVICE_THIS_SIDE)) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
    pointing_device_driver.init();
 | 
			
		||||
#ifdef POINTING_DEVICE_MOTION_PIN
 | 
			
		||||
    setPinInputHigh(POINTING_DEVICE_MOTION_PIN);
 | 
			
		||||
| 
						 | 
				
			
			@ -54,67 +145,299 @@ __attribute__((weak)) void pointing_device_init(void) {
 | 
			
		|||
    pointing_device_init_user();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Sends processed mouse report to host
 | 
			
		||||
 *
 | 
			
		||||
 * This sends the mouse report generated by pointing_device_task if changed since the last report. Once send zeros mouse report except buttons.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
__attribute__((weak)) void pointing_device_send(void) {
 | 
			
		||||
    static report_mouse_t old_report = {};
 | 
			
		||||
 | 
			
		||||
    // If you need to do other things, like debugging, this is the place to do it.
 | 
			
		||||
    if (has_mouse_report_changed(mouseReport, old_report)) {
 | 
			
		||||
        host_mouse_send(&mouseReport);
 | 
			
		||||
    if (has_mouse_report_changed(local_mouse_report, old_report)) {
 | 
			
		||||
        host_mouse_send(&local_mouse_report);
 | 
			
		||||
    }
 | 
			
		||||
    // send it and 0 it out except for buttons, so those stay until they are explicity over-ridden using update_pointing_device
 | 
			
		||||
    mouseReport.x = 0;
 | 
			
		||||
    mouseReport.y = 0;
 | 
			
		||||
    mouseReport.v = 0;
 | 
			
		||||
    mouseReport.h = 0;
 | 
			
		||||
    local_mouse_report.x = 0;
 | 
			
		||||
    local_mouse_report.y = 0;
 | 
			
		||||
    local_mouse_report.v = 0;
 | 
			
		||||
    local_mouse_report.h = 0;
 | 
			
		||||
 | 
			
		||||
    memcpy(&old_report, &mouseReport, sizeof(mouseReport));
 | 
			
		||||
    memcpy(&old_report, &local_mouse_report, sizeof(local_mouse_report));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__((weak)) void pointing_device_task(void) {
 | 
			
		||||
    // Gather report info
 | 
			
		||||
#ifdef POINTING_DEVICE_MOTION_PIN
 | 
			
		||||
    if (!readPin(POINTING_DEVICE_MOTION_PIN))
 | 
			
		||||
#endif
 | 
			
		||||
        mouseReport = pointing_device_driver.get_report(mouseReport);
 | 
			
		||||
 | 
			
		||||
        // Support rotation of the sensor data
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Adjust mouse report by any optional common pointing configuration defines
 | 
			
		||||
 *
 | 
			
		||||
 * This applies rotation or inversion to the mouse report as selected by the pointing device common configuration defines.
 | 
			
		||||
 *
 | 
			
		||||
 * @param mouse_report[in] takes a report_mouse_t to be adjusted
 | 
			
		||||
 * @return report_mouse_t with adjusted values
 | 
			
		||||
 */
 | 
			
		||||
report_mouse_t pointing_device_adjust_by_defines(report_mouse_t mouse_report) {
 | 
			
		||||
    // Support rotation of the sensor data
 | 
			
		||||
#if defined(POINTING_DEVICE_ROTATION_90) || defined(POINTING_DEVICE_ROTATION_180) || defined(POINTING_DEVICE_ROTATION_270)
 | 
			
		||||
    int8_t x = mouseReport.x, y = mouseReport.y;
 | 
			
		||||
    int8_t x = mouse_report.x, y = mouse_report.y;
 | 
			
		||||
#    if defined(POINTING_DEVICE_ROTATION_90)
 | 
			
		||||
    mouseReport.x = y;
 | 
			
		||||
    mouseReport.y = -x;
 | 
			
		||||
    mouse_report.x = y;
 | 
			
		||||
    mouse_report.y = -x;
 | 
			
		||||
#    elif defined(POINTING_DEVICE_ROTATION_180)
 | 
			
		||||
    mouseReport.x = -x;
 | 
			
		||||
    mouseReport.y = -y;
 | 
			
		||||
    mouse_report.x = -x;
 | 
			
		||||
    mouse_report.y = -y;
 | 
			
		||||
#    elif defined(POINTING_DEVICE_ROTATION_270)
 | 
			
		||||
    mouseReport.x = -y;
 | 
			
		||||
    mouseReport.y = x;
 | 
			
		||||
    mouse_report.x = -y;
 | 
			
		||||
    mouse_report.y = x;
 | 
			
		||||
#    else
 | 
			
		||||
#        error "How the heck did you get here?!"
 | 
			
		||||
#    endif
 | 
			
		||||
#endif
 | 
			
		||||
    // Support Inverting the X and Y Axises
 | 
			
		||||
#if defined(POINTING_DEVICE_INVERT_X)
 | 
			
		||||
    mouseReport.x = -mouseReport.x;
 | 
			
		||||
    mouse_report.x = -mouse_report.x;
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(POINTING_DEVICE_INVERT_Y)
 | 
			
		||||
    mouseReport.y = -mouseReport.y;
 | 
			
		||||
    mouse_report.y = -mouse_report.y;
 | 
			
		||||
#endif
 | 
			
		||||
    return mouse_report;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Retrieves and processes pointing device data.
 | 
			
		||||
 *
 | 
			
		||||
 * This function is part of the keyboard loop and retrieves the mouse report from the pointing device driver.
 | 
			
		||||
 * It applies any optional configuration e.g. rotation or axis inversion and then initiates a send.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
__attribute__((weak)) void pointing_device_task(void) {
 | 
			
		||||
#if defined(SPLIT_POINTING_ENABLE)
 | 
			
		||||
    // Don't poll the target side pointing device.
 | 
			
		||||
    if (!is_keyboard_master()) {
 | 
			
		||||
        return;
 | 
			
		||||
    };
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(POINTING_DEVICE_TASK_THROTTLE_MS)
 | 
			
		||||
    static uint32_t last_exec = 0;
 | 
			
		||||
    if (timer_elapsed32(last_exec) < POINTING_DEVICE_TASK_THROTTLE_MS) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    last_exec = timer_read32();
 | 
			
		||||
#else
 | 
			
		||||
#    if defined(SPLIT_POINTING_ENABLE)
 | 
			
		||||
#        pragma message("It's recommended you enable a throttle when sharing pointing devices.")
 | 
			
		||||
#    endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    // Gather report info
 | 
			
		||||
#ifdef POINTING_DEVICE_MOTION_PIN
 | 
			
		||||
#    if defined(SPLIT_POINTING_ENABLE)
 | 
			
		||||
#        error POINTING_DEVICE_MOTION_PIN not supported when sharing the pointing device report between sides.
 | 
			
		||||
#    endif
 | 
			
		||||
    if (!readPin(POINTING_DEVICE_MOTION_PIN))
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(SPLIT_POINTING_ENABLE)
 | 
			
		||||
#    if defined(POINTING_DEVICE_COMBINED)
 | 
			
		||||
        static uint8_t old_buttons = 0;
 | 
			
		||||
    local_mouse_report.buttons = old_buttons;
 | 
			
		||||
    local_mouse_report         = pointing_device_driver.get_report(local_mouse_report);
 | 
			
		||||
    old_buttons                = local_mouse_report.buttons;
 | 
			
		||||
#    elif defined(POINTING_DEVICE_LEFT) || defined(POINTING_DEVICE_RIGHT)
 | 
			
		||||
        local_mouse_report = POINTING_DEVICE_THIS_SIDE ? pointing_device_driver.get_report(local_mouse_report) : shared_mouse_report;
 | 
			
		||||
#    else
 | 
			
		||||
#        error "You need to define the side(s) the pointing device is on. POINTING_DEVICE_COMBINED / POINTING_DEVICE_LEFT / POINTING_DEVICE_RIGHT"
 | 
			
		||||
#    endif
 | 
			
		||||
#else
 | 
			
		||||
    local_mouse_report = pointing_device_driver.get_report(local_mouse_report);
 | 
			
		||||
#endif  // defined(SPLIT_POINTING_ENABLE)
 | 
			
		||||
 | 
			
		||||
    // allow kb to intercept and modify report
 | 
			
		||||
    mouseReport = pointing_device_task_kb(mouseReport);
 | 
			
		||||
#if defined(SPLIT_POINTING_ENABLE) && defined(POINTING_DEVICE_COMBINED)
 | 
			
		||||
    if (is_keyboard_left()) {
 | 
			
		||||
        local_mouse_report  = pointing_device_adjust_by_defines(local_mouse_report);
 | 
			
		||||
        shared_mouse_report = pointing_device_adjust_by_defines_right(shared_mouse_report);
 | 
			
		||||
    } else {
 | 
			
		||||
        local_mouse_report  = pointing_device_adjust_by_defines_right(local_mouse_report);
 | 
			
		||||
        shared_mouse_report = pointing_device_adjust_by_defines(shared_mouse_report);
 | 
			
		||||
    }
 | 
			
		||||
    local_mouse_report = is_keyboard_left() ? pointing_device_task_combined_kb(local_mouse_report, shared_mouse_report) : pointing_device_task_combined_kb(shared_mouse_report, local_mouse_report);
 | 
			
		||||
#else
 | 
			
		||||
    local_mouse_report = pointing_device_adjust_by_defines(local_mouse_report);
 | 
			
		||||
    local_mouse_report = pointing_device_task_kb(local_mouse_report);
 | 
			
		||||
#endif
 | 
			
		||||
    // combine with mouse report to ensure that the combined is sent correctly
 | 
			
		||||
#ifdef MOUSEKEY_ENABLE
 | 
			
		||||
    report_mouse_t mousekey_report = mousekey_get_report();
 | 
			
		||||
    mouseReport.buttons            = mouseReport.buttons | mousekey_report.buttons;
 | 
			
		||||
    local_mouse_report.buttons     = local_mouse_report.buttons | mousekey_report.buttons;
 | 
			
		||||
#endif
 | 
			
		||||
    pointing_device_send();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
report_mouse_t pointing_device_get_report(void) { return mouseReport; }
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Gets current mouse report used by pointing device task
 | 
			
		||||
 *
 | 
			
		||||
 * @return report_mouse_t
 | 
			
		||||
 */
 | 
			
		||||
report_mouse_t pointing_device_get_report(void) { return local_mouse_report; }
 | 
			
		||||
 | 
			
		||||
void pointing_device_set_report(report_mouse_t newMouseReport) { mouseReport = newMouseReport; }
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Sets mouse report used be pointing device task
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] new_mouse_report
 | 
			
		||||
 */
 | 
			
		||||
void pointing_device_set_report(report_mouse_t new_mouse_report) { local_mouse_report = new_mouse_report; }
 | 
			
		||||
 | 
			
		||||
uint16_t pointing_device_get_cpi(void) { return pointing_device_driver.get_cpi(); }
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Gets current pointing device CPI if supported
 | 
			
		||||
 *
 | 
			
		||||
 * Gets current cpi from pointing device driver if supported and returns it as uint16_t
 | 
			
		||||
 *
 | 
			
		||||
 * @return cpi value as uint16_t
 | 
			
		||||
 */
 | 
			
		||||
uint16_t pointing_device_get_cpi(void) {
 | 
			
		||||
#if defined(SPLIT_POINTING_ENABLE)
 | 
			
		||||
    return POINTING_DEVICE_THIS_SIDE ? pointing_device_driver.get_cpi() : shared_cpi;
 | 
			
		||||
#else
 | 
			
		||||
    return pointing_device_driver.get_cpi();
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void pointing_device_set_cpi(uint16_t cpi) { pointing_device_driver.set_cpi(cpi); }
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Set pointing device CPI if supported
 | 
			
		||||
 *
 | 
			
		||||
 * Takes a uint16_t value to set pointing device cpi if supported by driver.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] cpi uint16_t value.
 | 
			
		||||
 */
 | 
			
		||||
void pointing_device_set_cpi(uint16_t cpi) {
 | 
			
		||||
#if defined(SPLIT_POINTING_ENABLE)
 | 
			
		||||
    if (POINTING_DEVICE_THIS_SIDE) {
 | 
			
		||||
        pointing_device_driver.set_cpi(cpi);
 | 
			
		||||
    } else {
 | 
			
		||||
        shared_cpi = cpi;
 | 
			
		||||
    }
 | 
			
		||||
#else
 | 
			
		||||
    pointing_device_driver.set_cpi(cpi);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(SPLIT_POINTING_ENABLE) && defined(POINTING_DEVICE_COMBINED)
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Set pointing device CPI if supported
 | 
			
		||||
 *
 | 
			
		||||
 * Takes a bool and uint16_t and allows setting cpi for a single side when using 2 pointing devices with a split keyboard.
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: Only available when using SPLIT_POINTING_ENABLE and POINTING_DEVICE_COMBINED
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] left true = left, false = right.
 | 
			
		||||
 * @param[in] cpi uint16_t value.
 | 
			
		||||
 */
 | 
			
		||||
void pointing_device_set_cpi_on_side(bool left, uint16_t cpi) {
 | 
			
		||||
    bool local = (is_keyboard_left() & left) ? true : false;
 | 
			
		||||
    if (local) {
 | 
			
		||||
        pointing_device_driver.set_cpi(cpi);
 | 
			
		||||
    } else {
 | 
			
		||||
        shared_cpi = cpi;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief clamps int16_t to int8_t
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] int16_t value
 | 
			
		||||
 * @return int8_t clamped value
 | 
			
		||||
 */
 | 
			
		||||
static inline int8_t pointing_device_movement_clamp(int16_t value) {
 | 
			
		||||
    if (value < INT8_MIN) {
 | 
			
		||||
        return INT8_MIN;
 | 
			
		||||
    } else if (value > INT8_MAX) {
 | 
			
		||||
        return INT8_MAX;
 | 
			
		||||
    } else {
 | 
			
		||||
        return value;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief combines 2 mouse reports and returns 2
 | 
			
		||||
 *
 | 
			
		||||
 * Combines 2 report_mouse_t structs, clamping movement values to int8_t and ignores report_id then returns the resulting report_mouse_t struct.
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: Only available when using SPLIT_POINTING_ENABLE and POINTING_DEVICE_COMBINED
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] left_report left report_mouse_t
 | 
			
		||||
 * @param[in] right_report right report_mouse_t
 | 
			
		||||
 * @return combined report_mouse_t of left_report and right_report
 | 
			
		||||
 */
 | 
			
		||||
report_mouse_t pointing_device_combine_reports(report_mouse_t left_report, report_mouse_t right_report) {
 | 
			
		||||
    left_report.x = pointing_device_movement_clamp((int16_t)left_report.x + right_report.x);
 | 
			
		||||
    left_report.y = pointing_device_movement_clamp((int16_t)left_report.y + right_report.y);
 | 
			
		||||
    left_report.h = pointing_device_movement_clamp((int16_t)left_report.h + right_report.h);
 | 
			
		||||
    left_report.v = pointing_device_movement_clamp((int16_t)left_report.v + right_report.v);
 | 
			
		||||
    left_report.buttons |= right_report.buttons;
 | 
			
		||||
    return left_report;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Adjust mouse report by any optional right pointing configuration defines
 | 
			
		||||
 *
 | 
			
		||||
 * This applies rotation or inversion to the mouse report as selected by the pointing device common configuration defines.
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: Only available when using SPLIT_POINTING_ENABLE and POINTING_DEVICE_COMBINED
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] mouse_report report_mouse_t to be adjusted
 | 
			
		||||
 * @return report_mouse_t with adjusted values
 | 
			
		||||
 */
 | 
			
		||||
report_mouse_t pointing_device_adjust_by_defines_right(report_mouse_t mouse_report) {
 | 
			
		||||
    // Support rotation of the sensor data
 | 
			
		||||
#    if defined(POINTING_DEVICE_ROTATION_90_RIGHT) || defined(POINTING_DEVICE_ROTATION_RIGHT) || defined(POINTING_DEVICE_ROTATION_RIGHT)
 | 
			
		||||
    int8_t x = mouse_report.x, y = mouse_report.y;
 | 
			
		||||
#        if defined(POINTING_DEVICE_ROTATION_90_RIGHT)
 | 
			
		||||
    mouse_report.x = y;
 | 
			
		||||
    mouse_report.y = -x;
 | 
			
		||||
#        elif defined(POINTING_DEVICE_ROTATION_180_RIGHT)
 | 
			
		||||
    mouse_report.x = -x;
 | 
			
		||||
    mouse_report.y = -y;
 | 
			
		||||
#        elif defined(POINTING_DEVICE_ROTATION_270_RIGHT)
 | 
			
		||||
    mouse_report.x = -y;
 | 
			
		||||
    mouse_report.y = x;
 | 
			
		||||
#        else
 | 
			
		||||
#            error "How the heck did you get here?!"
 | 
			
		||||
#        endif
 | 
			
		||||
#    endif
 | 
			
		||||
    // Support Inverting the X and Y Axises
 | 
			
		||||
#    if defined(POINTING_DEVICE_INVERT_X_RIGHT)
 | 
			
		||||
    mouse_report.x = -mouse_report.x;
 | 
			
		||||
#    endif
 | 
			
		||||
#    if defined(POINTING_DEVICE_INVERT_Y_RIGHT)
 | 
			
		||||
    mouse_report.y = -mouse_report.y;
 | 
			
		||||
#    endif
 | 
			
		||||
    return mouse_report;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Weak function allowing for keyboard level mouse report modification
 | 
			
		||||
 *
 | 
			
		||||
 * Takes 2 report_mouse_t structs allowing individual modification of sides at keyboard level then returns pointing_device_task_combined_user.
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: Only available when using SPLIT_POINTING_ENABLE and POINTING_DEVICE_COMBINED
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] left_report report_mouse_t
 | 
			
		||||
 * @param[in] right_report report_mouse_t
 | 
			
		||||
 * @return pointing_device_task_combined_user(left_report, right_report) by default
 | 
			
		||||
 */
 | 
			
		||||
__attribute__((weak)) report_mouse_t pointing_device_task_combined_kb(report_mouse_t left_report, report_mouse_t right_report) { return pointing_device_task_combined_user(left_report, right_report); }
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Weak function allowing for user level mouse report modification
 | 
			
		||||
 *
 | 
			
		||||
 * Takes 2 report_mouse_t structs allowing individual modification of sides at user level then returns pointing_device_combine_reports.
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: Only available when using SPLIT_POINTING_ENABLE and POINTING_DEVICE_COMBINED
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] left_report report_mouse_t
 | 
			
		||||
 * @param[in] right_report report_mouse_t
 | 
			
		||||
 * @return pointing_device_combine_reports(left_report, right_report) by default
 | 
			
		||||
 */
 | 
			
		||||
__attribute__((weak)) report_mouse_t pointing_device_task_combined_user(report_mouse_t left_report, report_mouse_t right_report) { return pointing_device_combine_reports(left_report, right_report); }
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -86,3 +86,16 @@ void           pointing_device_init_user(void);
 | 
			
		|||
report_mouse_t pointing_device_task_kb(report_mouse_t mouse_report);
 | 
			
		||||
report_mouse_t pointing_device_task_user(report_mouse_t mouse_report);
 | 
			
		||||
uint8_t        pointing_device_handle_buttons(uint8_t buttons, bool pressed, pointing_device_buttons_t button);
 | 
			
		||||
report_mouse_t pointing_device_adjust_by_defines(report_mouse_t mouse_report);
 | 
			
		||||
 | 
			
		||||
#if defined(SPLIT_POINTING_ENABLE)
 | 
			
		||||
void     pointing_device_set_shared_report(report_mouse_t report);
 | 
			
		||||
uint16_t pointing_device_get_shared_cpi(void);
 | 
			
		||||
#    if defined(POINTING_DEVICE_COMBINED)
 | 
			
		||||
void           pointing_device_set_cpi_on_side(bool left, uint16_t cpi);
 | 
			
		||||
report_mouse_t pointing_device_combine_reports(report_mouse_t left_report, report_mouse_t right_report);
 | 
			
		||||
report_mouse_t pointing_device_task_combined_kb(report_mouse_t left_report, report_mouse_t right_report);
 | 
			
		||||
report_mouse_t pointing_device_task_combined_user(report_mouse_t left_report, report_mouse_t right_report);
 | 
			
		||||
report_mouse_t pointing_device_adjust_by_defines_right(report_mouse_t mouse_report);
 | 
			
		||||
#    endif //defined(POINTING_DEVICE_COMBINED)
 | 
			
		||||
#endif //defined(SPLIT_POINTING_ENABLE)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -165,14 +165,13 @@ const pointing_device_driver_t pointing_device_driver = {
 | 
			
		|||
// clang-format on
 | 
			
		||||
 | 
			
		||||
#elif defined(POINTING_DEVICE_DRIVER_pimoroni_trackball)
 | 
			
		||||
report_mouse_t pimorono_trackball_get_report(report_mouse_t mouse_report) {
 | 
			
		||||
    static fast_timer_t throttle      = 0;
 | 
			
		||||
    static uint16_t     debounce      = 0;
 | 
			
		||||
    static uint8_t      error_count   = 0;
 | 
			
		||||
    pimoroni_data_t     pimoroni_data = {0};
 | 
			
		||||
    static int16_t      x_offset = 0, y_offset = 0;
 | 
			
		||||
report_mouse_t pimoroni_trackball_get_report(report_mouse_t mouse_report) {
 | 
			
		||||
    static uint16_t debounce      = 0;
 | 
			
		||||
    static uint8_t  error_count   = 0;
 | 
			
		||||
    pimoroni_data_t pimoroni_data = {0};
 | 
			
		||||
    static int16_t  x_offset = 0, y_offset = 0;
 | 
			
		||||
 | 
			
		||||
    if (error_count < PIMORONI_TRACKBALL_ERROR_COUNT && timer_elapsed_fast(throttle) >= PIMORONI_TRACKBALL_INTERVAL_MS) {
 | 
			
		||||
    if (error_count < PIMORONI_TRACKBALL_ERROR_COUNT) {
 | 
			
		||||
        i2c_status_t status = read_pimoroni_trackball(&pimoroni_data);
 | 
			
		||||
 | 
			
		||||
        if (status == I2C_STATUS_SUCCESS) {
 | 
			
		||||
| 
						 | 
				
			
			@ -195,17 +194,16 @@ report_mouse_t pimorono_trackball_get_report(report_mouse_t mouse_report) {
 | 
			
		|||
        } else {
 | 
			
		||||
            error_count++;
 | 
			
		||||
        }
 | 
			
		||||
        throttle = timer_read_fast();
 | 
			
		||||
    }
 | 
			
		||||
    return mouse_report;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// clang-format off
 | 
			
		||||
const pointing_device_driver_t pointing_device_driver = {
 | 
			
		||||
    .init       = pimironi_trackball_device_init,
 | 
			
		||||
    .get_report = pimorono_trackball_get_report,
 | 
			
		||||
    .set_cpi    = NULL,
 | 
			
		||||
    .get_cpi    = NULL
 | 
			
		||||
    .init       = pimoroni_trackball_device_init,
 | 
			
		||||
    .get_report = pimoroni_trackball_get_report,
 | 
			
		||||
    .set_cpi    = pimoroni_trackball_set_cpi,
 | 
			
		||||
    .get_cpi    = pimoroni_trackball_get_cpi
 | 
			
		||||
};
 | 
			
		||||
// clang-format on
 | 
			
		||||
#elif defined(POINTING_DEVICE_DRIVER_pmw3360)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -78,6 +78,12 @@ enum serial_transaction_id {
 | 
			
		|||
    PUT_ST7565,
 | 
			
		||||
#endif  // defined(ST7565_ENABLE) && defined(SPLIT_ST7565_ENABLE)
 | 
			
		||||
 | 
			
		||||
#if defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE)
 | 
			
		||||
    GET_POINTING_CHECKSUM,
 | 
			
		||||
    GET_POINTING_DATA,
 | 
			
		||||
    PUT_POINTING_CPI,
 | 
			
		||||
#endif  // defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE)
 | 
			
		||||
 | 
			
		||||
#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
 | 
			
		||||
    PUT_RPC_INFO,
 | 
			
		||||
    PUT_RPC_REQ_DATA,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -578,6 +578,82 @@ static void st7565_handlers_slave(matrix_row_t master_matrix[], matrix_row_t sla
 | 
			
		|||
 | 
			
		||||
#endif  // defined(ST7565_ENABLE) && defined(SPLIT_ST7565_ENABLE)
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////
 | 
			
		||||
// POINTING
 | 
			
		||||
 | 
			
		||||
#if defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE)
 | 
			
		||||
 | 
			
		||||
static bool pointing_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
 | 
			
		||||
#    if defined(POINTING_DEVICE_LEFT)
 | 
			
		||||
    if (is_keyboard_left()) {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
#    elif defined(POINTING_DEVICE_RIGHT)
 | 
			
		||||
    if (!is_keyboard_left()) {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
#    endif
 | 
			
		||||
    static uint32_t last_update = 0;
 | 
			
		||||
    static uint16_t last_cpi    = 0;
 | 
			
		||||
    report_mouse_t  temp_state;
 | 
			
		||||
    uint16_t        temp_cpi;
 | 
			
		||||
    bool            okay = read_if_checksum_mismatch(GET_POINTING_CHECKSUM, GET_POINTING_DATA, &last_update, &temp_state, &split_shmem->pointing.report, sizeof(temp_state));
 | 
			
		||||
    if (okay) pointing_device_set_shared_report(temp_state);
 | 
			
		||||
    temp_cpi = pointing_device_get_shared_cpi();
 | 
			
		||||
    if (temp_cpi && memcmp(&last_cpi, &temp_cpi, sizeof(temp_cpi)) != 0) {
 | 
			
		||||
        memcpy(&split_shmem->pointing.cpi, &temp_cpi, sizeof(temp_cpi));
 | 
			
		||||
        okay = transport_write(PUT_POINTING_CPI, &split_shmem->pointing.cpi, sizeof(split_shmem->pointing.cpi));
 | 
			
		||||
        if (okay) {
 | 
			
		||||
            last_cpi = temp_cpi;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return okay;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern const pointing_device_driver_t pointing_device_driver;
 | 
			
		||||
 | 
			
		||||
static void pointing_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
 | 
			
		||||
#    if defined(POINTING_DEVICE_LEFT)
 | 
			
		||||
    if (!is_keyboard_left()) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
#    elif defined(POINTING_DEVICE_RIGHT)
 | 
			
		||||
    if (is_keyboard_left()) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
#    endif
 | 
			
		||||
    report_mouse_t temp_report;
 | 
			
		||||
    uint16_t       temp_cpi;
 | 
			
		||||
#    ifdef POINTING_DEVICE_TASK_THROTTLE_MS
 | 
			
		||||
    static uint32_t last_exec = 0;
 | 
			
		||||
    if (timer_elapsed32(last_exec) < POINTING_DEVICE_TASK_THROTTLE_MS) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    last_exec = timer_read32();
 | 
			
		||||
#    endif
 | 
			
		||||
    temp_cpi = pointing_device_driver.get_cpi();
 | 
			
		||||
    if (split_shmem->pointing.cpi && memcmp(&split_shmem->pointing.cpi, &temp_cpi, sizeof(temp_cpi)) != 0) {
 | 
			
		||||
        pointing_device_driver.set_cpi(split_shmem->pointing.cpi);
 | 
			
		||||
    }
 | 
			
		||||
    memset(&temp_report, 0, sizeof(temp_report));
 | 
			
		||||
    temp_report = pointing_device_driver.get_report(temp_report);
 | 
			
		||||
    memcpy(&split_shmem->pointing.report, &temp_report, sizeof(temp_report));
 | 
			
		||||
    // Now update the checksum given that the pointing has been written to
 | 
			
		||||
    split_shmem->pointing.checksum = crc8(&temp_report, sizeof(temp_report));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#    define TRANSACTIONS_POINTING_MASTER() TRANSACTION_HANDLER_MASTER(pointing)
 | 
			
		||||
#    define TRANSACTIONS_POINTING_SLAVE() TRANSACTION_HANDLER_SLAVE(pointing)
 | 
			
		||||
#    define TRANSACTIONS_POINTING_REGISTRATIONS [GET_POINTING_CHECKSUM] = trans_target2initiator_initializer(pointing.checksum), [GET_POINTING_DATA] = trans_target2initiator_initializer(pointing.report), [PUT_POINTING_CPI] = trans_initiator2target_initializer(pointing.cpi),
 | 
			
		||||
 | 
			
		||||
#else  // defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE)
 | 
			
		||||
 | 
			
		||||
#    define TRANSACTIONS_POINTING_MASTER()
 | 
			
		||||
#    define TRANSACTIONS_POINTING_SLAVE()
 | 
			
		||||
#    define TRANSACTIONS_POINTING_REGISTRATIONS
 | 
			
		||||
 | 
			
		||||
#endif  // defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE)
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
uint8_t                  dummy;
 | 
			
		||||
| 
						 | 
				
			
			@ -604,6 +680,7 @@ split_transaction_desc_t split_transaction_table[NUM_TOTAL_TRANSACTIONS] = {
 | 
			
		|||
    TRANSACTIONS_WPM_REGISTRATIONS
 | 
			
		||||
    TRANSACTIONS_OLED_REGISTRATIONS
 | 
			
		||||
    TRANSACTIONS_ST7565_REGISTRATIONS
 | 
			
		||||
    TRANSACTIONS_POINTING_REGISTRATIONS
 | 
			
		||||
// clang-format on
 | 
			
		||||
 | 
			
		||||
#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
 | 
			
		||||
| 
						 | 
				
			
			@ -629,6 +706,7 @@ bool transactions_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix
 | 
			
		|||
    TRANSACTIONS_WPM_MASTER();
 | 
			
		||||
    TRANSACTIONS_OLED_MASTER();
 | 
			
		||||
    TRANSACTIONS_ST7565_MASTER();
 | 
			
		||||
    TRANSACTIONS_POINTING_MASTER();
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -647,6 +725,7 @@ void transactions_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[
 | 
			
		|||
    TRANSACTIONS_WPM_SLAVE();
 | 
			
		||||
    TRANSACTIONS_OLED_SLAVE();
 | 
			
		||||
    TRANSACTIONS_ST7565_SLAVE();
 | 
			
		||||
    TRANSACTIONS_POINTING_SLAVE();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -106,6 +106,15 @@ typedef struct _split_mods_sync_t {
 | 
			
		|||
} split_mods_sync_t;
 | 
			
		||||
#endif  // SPLIT_MODS_ENABLE
 | 
			
		||||
 | 
			
		||||
#if defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE)
 | 
			
		||||
#    include "pointing_device.h"
 | 
			
		||||
typedef struct _split_slave_pointing_sync_t {
 | 
			
		||||
    uint8_t        checksum;
 | 
			
		||||
    report_mouse_t report;
 | 
			
		||||
    uint16_t       cpi;
 | 
			
		||||
} split_slave_pointing_sync_t;
 | 
			
		||||
#endif  // defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE)
 | 
			
		||||
 | 
			
		||||
#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
 | 
			
		||||
typedef struct _rpc_sync_info_t {
 | 
			
		||||
    int8_t  transaction_id;
 | 
			
		||||
| 
						 | 
				
			
			@ -173,6 +182,10 @@ typedef struct _split_shared_memory_t {
 | 
			
		|||
    uint8_t current_st7565_state;
 | 
			
		||||
#endif  // ST7565_ENABLE(OLED_ENABLE) && defined(SPLIT_ST7565_ENABLE)
 | 
			
		||||
 | 
			
		||||
#if defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE)
 | 
			
		||||
    split_slave_pointing_sync_t pointing;
 | 
			
		||||
#endif  // defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_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];
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue