Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement relative mode for Cirque trackpad #17760

Merged
merged 1 commit into from
Jul 30, 2022

Conversation

drzony
Copy link
Contributor

@drzony drzony commented Jul 23, 2022

Implement relative mode for Cirque trackpad

Description

Cirque can work in absolute or relative mode, they differ in features. Give user a choice to use one of them. Also relative mode saves a lot of space.

Types of Changes

  • Core
  • Bugfix
  • New feature
  • Enhancement/optimization
  • Keyboard (addition or update)
  • Keymap/layout/userspace (addition or update)
  • Documentation

Checklist

  • My code follows the code style of this project: C, Python
  • I have read the PR Checklist document and have made the appropriate changes.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • I have tested the changes and verified that they work and don't break anything (as well as I can manage).

@drashna drashna requested a review from a team July 24, 2022 03:43
Copy link
Contributor

@dkao dkao left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does not work with #define MOUSE_EXTENDED_REPORT.

| -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | ------------- |
| `CIRQUE_PINNACLE_SIDE_SCROLL_ENABLE` | (Optional) Enable side scroll. Touch originating on right side can trigger vertical scroll (IntelliSense trackpad style). | _not defined_ |
| `CIRQUE_PINNACLE_TAP_ENABLE` | (Optional) Enable tap to "left click". Works on both sides of a split keyboard. | _not defined_ |
| `CIRQUE_PINNACLE_SECONDARY_TAP_ENABLE` | (Optional) Tap in upper right corner of the trackpad will result in "right click". `CIRQUE_PINNACLE_TAP_ENABLE` must be enabled. | _not defined_ |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do side scroll and secondary tap work on circular trackpads? I wasn't able to trigger these.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, they should both work. Secondary tap is a bit awkward, since you need to exactly hit the "sweet spot"

drivers/sensors/cirque_pinnacle.c Outdated Show resolved Hide resolved
Comment on lines 236 to 262
// FeedConfig2 (Feature flags for Relative Mode Only)
uint8_t feedconfig2 = HOSTREG__FEEDCONFIG2__GLIDE_EXTEND_DISABLE | HOSTREG__FEEDCONFIG2__INTELLIMOUSE_MODE;
# if !defined(CIRQUE_PINNACLE_TAP_ENABLE)
feedconfig2 |= HOSTREG__FEEDCONFIG2__ALL_TAP_DISABLE;
# endif
# if !defined(CIRQUE_PINNACLE_SECONDARY_TAP_ENABLE)
feedconfig2 |= HOSTREG__FEEDCONFIG2__SECONDARY_TAP_DISABLE;
# endif
# if !defined(CIRQUE_PINNACLE_SIDE_SCROLL_ENABLE)
feedconfig2 |= HOSTREG__FEEDCONFIG2__SCROLL_DISABLE;
# endif
RAP_Write(HOSTREG__FEEDCONFIG2, feedconfig2);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any way these can be made runtime configurable? Use case maybe one hand relative mode, one hand absolute mode.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would require a full rework of the trackpad code + it would discard the "FW size" benefit for relative mode. In the case you provided I think it's better to use absolute on both halves.

drivers/sensors/cirque_pinnacle.c Outdated Show resolved Hide resolved
drivers/sensors/cirque_pinnacle.c Show resolved Hide resolved
Comment on lines +45 to +49
# define CIRQUE_PINNACLE_X_RANGE 256
# define CIRQUE_PINNACLE_Y_RANGE 256
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this line up with the

Resolution 245 x 1/2 cpi

mentioned under PS/2 mode? Or is CPI intended to be an arbitrary scale for relative mode?

I was thinking cirque_pinnacle_get_cpi() and cirque_pinnacle_set_cpi() need to be overridden for relative mode.

Copy link
Contributor Author

@drzony drzony Jul 25, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Scale is arbitrary, there is no mention of how this is scaled in datasheet. The scale is probably the same as in absolute mode, however the range is not. One idea is to add some conversion in cirque_pinnacle_*_cpi() to something like:

if (some_value < cpi < some_other_value) {
  scale = 1;
} else if (...) {
  scale = 2;
}

And then in scale_data just do xTemp = coordinates->xDelta * scale

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was messing around with that 245 x 1/2 number from the PS/2 portion of the spec and can't get it to make sense....
It's not the same as absolute mode either from what I can tell. I give up.

Do you want to just do something like this in pointing_device_drivers.c:

#    if CIRQUE_PINNACLE_POSITION_MODE
uint16_t cirque_pinnacle_get_cpi(void) {
    return CIRQUE_PINNACLE_PX_TO_INCH(cirque_pinnacle_get_scale());
}
void cirque_pinnacle_set_cpi(uint16_t cpi) {
    cirque_pinnacle_set_scale(CIRQUE_PINNACLE_INCH_TO_PX(cpi));
}
#    endif

// clang-format off
const pointing_device_driver_t pointing_device_driver = {
    .init       = cirque_pinnacle_init,
    .get_report = cirque_pinnacle_get_report,
#    if CIRQUE_PINNACLE_POSITION_MODE
    .set_cpi    = cirque_pinnacle_set_cpi,
    .get_cpi    = cirque_pinnacle_get_cpi,
#    else
    .set_cpi    = cirque_pinnacle_set_scale,
    .get_cpi    = cirque_pinnacle_get_scale
#    endif
};

Empirically it gives sensitivity in a similar ballpark to the absolute mode scaling, and saves a bit more space.
Maybe split the relative mode and absolute mode driver into two sections divided by one #if CIRQUE_PINNACLE_POSITION_MODE, with a separate much more concise definition of cirque_pinnacle_get_report() for relative mode?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On PS/2 mode trackpad has a Set Resolution and Set Scaling commands. I think the 245 x 1/2 cpi is somehow relative to the values set there. Maybe they are available in extended registers, but there is zero documentation for them.

quantum/pointing_device/pointing_device_drivers.c Outdated Show resolved Hide resolved
quantum/pointing_device/pointing_device_drivers.c Outdated Show resolved Hide resolved
@drzony drzony force-pushed the feature/cirque-relative-mode branch from 6ab7d4e to c5047a0 Compare July 26, 2022 08:33
@drzony
Copy link
Contributor Author

drzony commented Jul 26, 2022

Squashed all the fixups

Comment on lines 181 to 182
mouse_report.x = report_x;
mouse_report.y = report_y;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something happened here to the mouse_report update for absolute mode.
Please restore and rebase, thanks!

@drzony drzony force-pushed the feature/cirque-relative-mode branch from c5047a0 to 60456c1 Compare July 27, 2022 06:30
@drashna
Copy link
Member

drashna commented Jul 27, 2022

This has some merge conflicts.

@drzony drzony force-pushed the feature/cirque-relative-mode branch from 60456c1 to e801722 Compare July 27, 2022 19:30
@drzony
Copy link
Contributor Author

drzony commented Jul 28, 2022

Rebased

Copy link
Contributor

@dkao dkao left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Looks good.
I still can't get secondary tap and side scroll to work at all on my TM040040. Wondering if it's only supported on certain models or possibly certain revisions. Might be a good thing to mention in the docs?
Also it could be nice to implement functions like cirque_pinnacle_enable_tap(), cirque_pinnacle_enable_secondary_tap(), cirque_pinnacle_enable_side_scroll() if someone wants to disable the features only on certain layers.

@drzony
Copy link
Contributor Author

drzony commented Jul 29, 2022

It's working on my TM040040. My config:

#define SPLIT_POINTING_ENABLE
#define POINTING_DEVICE_RIGHT
#define CIRQUE_PINNACLE_POSITION_MODE CIRQUE_PINNACLE_RELATIVE_MODE
#define CIRQUE_PINNACLE_TAP_ENABLE
#define CIRQUE_PINNACLE_SECONDARY_TAP_ENABLE
#define CIRQUE_PINNACLE_SIDE_SCROLL_ENABLE

Right click is on the top-right edge (half of my finger needs to be outside of the trackpad)
The scroll starts about 0.5cm from the right edge (up-down movement).

As for the functions I would leave them for another PR

@drashna
Copy link
Member

drashna commented Jul 29, 2022

The side scroll feels like it should be a generic option.

And the right click does too, to a lesser degree.

And I can confirm that the code appears to work in both modes, and with both features.

@drashna
Copy link
Member

drashna commented Jul 29, 2022

Right click is on the top-right edge (half of my finger needs to be outside of the trackpad)

I found this to be the case too. Would be worth noting in the docs.

@drzony
Copy link
Contributor Author

drzony commented Jul 29, 2022

@drashna
Something like:

#define POINTING_DEVICE_LEFT_CLICK_ENABLE // instead of CIRQUE_PINNACLE_TAP_ENABLE, if not defined disable button reporting for pimoroni also
#define POINTING_DEVICE_RIGHT_CLICK_ENABLE // instead of CIRQUE_PINNACLE_SECONDARY_TAP_ENABLE
#define POINTING_DEVICE_SCROLL_ENABLE // This would enable circular scroll on absolute and side scroll on relative

?

@drzony drzony force-pushed the feature/cirque-relative-mode branch from e801722 to 8ca7ab2 Compare July 29, 2022 07:49
@drzony
Copy link
Contributor Author

drzony commented Jul 29, 2022

Updated docs with secondary tap info and flash difference amount

@drashna
Copy link
Member

drashna commented Jul 29, 2022

Yeah. Though, POINTING_DEVICE_GESTURES_* would probably be better, since we already have one define doing that.
https://qmk.github.io/qmk_docs_devel/#/feature_pointing_device?id=common-configuration

Though, I do mean something more in line with:
https://github.com/qmk/qmk_firmware/blob/develop/quantum/pointing_device/pointing_device_gestures.c

Namely, if it can be handled in a generic fashion, it should be. That way, as other sensors are added, they can take advantage of the features, right away.

If that can't be done, then no worries. It looks like the secondary tap is hardware dependent. Though, the generic define for the scrolling may be the best way to go. Not 100% sure, though.

@drzony drzony force-pushed the feature/cirque-relative-mode branch from 8ca7ab2 to 97e3fcf Compare July 29, 2022 09:03
@drzony
Copy link
Contributor Author

drzony commented Jul 29, 2022

Added POINTING_DEVICE_GESTURES_SCROLL_ENABLE

@drashna drashna merged commit 0b726a4 into qmk:develop Jul 30, 2022
nolanseaton pushed a commit to nolanseaton/qmk_firmware that referenced this pull request Jan 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants