-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
add: Cirque Pinnacle trackpad driver #1116
base: main
Are you sure you want to change the base?
Conversation
For transparency, I've been using this driver on my Fusion board for a while, and it seems to work fine for the most part, but sometimes it can cause weird bugs. I'm only starting to debug this, and I have no idea why (so it could be related to my driver or not) but when it happens it just messes up the screen and the system freezes. |
Okay, so this is weird... Cirque has some interesting data format for the relative mode (which is all I use; see page 10). It would be helpful if others can help me see if there's some interpretation problem here or it's just cirque being weird. So sometimes the driver will output some spuriously large data, and here's some of the instances.
|
@crides Sure seems to be at the "transition point" from positive to negative values for the delta. Is there a moment when the sign bit and the value are "out of sync" perhaps? |
Hmm that is very likely.. But the datasheet/comm format doesn't specify anything at all about syncing data, and I'm assuming auto-inc reads should make sure that it doesn't read across update epochs. Seems like something worth asking Cirque sales |
I am building a ffkb with a Nice!nano and a Cirque trackpad, so I could help trying this out - if I could just get a few pointers on how to get started. :) |
@MikaelElkiaer Do you have any specific directions you want to look at? If you just wanna use it you should just merge this PR, the mouse PR, and then some version of the example "configuration" code linked in the start. Look around at the configs in the |
Yeah, I just wanted to try it out and use it. |
No, as I mentioned in the PR this is the _driver_ PROn Jun 6, 2022 12:54, Mikael Elkiær ***@***.***> wrote:
@MikaelElkiaer Do you have any specific directions you want to look at? If you just wanna use it you should just merge this PR, the mouse PR, and then some version of the example "configuration" code linked in the start. Look around at the configs in the fusion board.
Yeah, I just wanted to try it out and use it.
So this branch is not built on top of the mouse changes?
Thanks for some useful info.
—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you were mentioned.Message ID: ***@***.***>
|
@crides The fetching is incorrect in your case. The sign is not in the data[1] and data[2] it's in data[0]. So: if ((data[0] & 0x10) && data[1] != 0) {
xDelta = -((int16_t)256 - (int16_t)(data[1]));
} else {
xDelta = data[1];
}
if ((data[0] & 0x20) && data[2] != 0) {
yDelta = ((int16_t)256 - (int16_t)(data[2]));
} else {
yDelta = -((int16_t)data[2]);
}
wheelCount = ((int8_t*)data)[3]; |
I know that. The problem is that the sign bits and the data bytes may not be synced, and cause weird problems. I've contacted cirque about it, never got a response |
Weird, I'm running relative mode on QMK (just got it merged into develop) and I don't seem to have this problem. (The code above is taken from my test code not QMK, just to be on safe side in terms of licensing, I ported it to QMK afterwards). Maybe try running QMK to compare results (might be some HW issue). Also there is SW_DR bit, maybe it's worth checking it after hardware pin is asserted. I have the trackpad connected via I2C, so that is another variable. |
Also maybe I'm missing something in the code, but the SW_DR flag in REG 0x02 should be cleared after every packet read. |
I'm not sure why one would clear DR when the trigger is not set, cuz the DR status is not used anyway |
From the spec:
So my understanding is that SW_DR flag is set by the chip when data is available, this causes HW_DR to be asserted. To clear HW_DR you need to clear both SW_CC and SW_DR flags. I do not have a pin available for use with HW_DR, so I'm using SW_DR to check for data, and then clear it after each read. I'm saying that this might be the cause for out-of-sync data. |
Added the I2C part of the driver. Both the I2C and SPI versions use the same devicetree |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the driver work! A few comments/questions for a first pass.
menuconfig PINNACLE | ||
bool "PINNACLE Incremental Encoder Sensor" | ||
depends on GPIO | ||
depends on SPI |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
depends on SPI | |
depends on SPI || I2C |
# Copyright (c) 2022 The ZMK Contributors | ||
# SPDX-License-Identifier: MIT | ||
|
||
menuconfig PINNACLE |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally the folder/file naming should match the Kconfig naming... Which is the authoritative/canonical name for this hardware?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure, which is why it's inconsistent. The manufacturer is Cirque, the product is called Glide Point (circle trackpad; though nobody seems to refer it by that name), and the ASIC used on the version sold at Mouser is Pinnacle. There are newer versions of the ASIC, not sure if they are sold in a complete product (so I'm not sure if Glide Point is specific enough, if we want to settle on a name).
#endif | ||
}; | ||
|
||
DEVICE_DT_INST_DEFINE(0, pinnacle_init, device_pm_control_nop, &pinnacle_data, &pinnacle_config, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, &pinnacle_driver_api); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want to assume from the get go that we only want to support one instance of this driver?
Seems like a bit of a risk.
|
||
#include <init.h> | ||
#include <drivers/sensor.h> | ||
#include <zmk/sensors.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey, I'm curious, how do you compile it when zmk
includes are not included in the CMakeLists?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you clarify your problem? I'm having trouble understanding
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I'm trying to compile with rebased main the compiler fails to find zmk/sensors.h
include. And I was wondering if it's the case for you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Absolutely not. I'm guessing you somehow have a ZMK version that's way too old, or maybe the CMake stuff got messed up somehow?
static void pinnacle_work_cb(struct k_work *work) { | ||
struct pinnacle_data *data = CONTAINER_OF(work, struct pinnacle_data, work); | ||
pinnacle_int_cb(data->dev); | ||
pinnacle_write(dev, PINNACLE_STATUS1, 0); // Clear SW_DR |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pinnacle_write(dev, PINNACLE_STATUS1, 0); // Clear SW_DR | |
pinnacle_write(data->dev, PINNACLE_STATUS1, 0); // Clear SW_DR |
f12d626
to
ecf60a3
Compare
1e61854
to
4dcb5f1
Compare
4dcb5f1
to
52b43a7
Compare
Did some progress again. Now it fails when linking. And different errors when building the left side and right side. On the left side I have absolutely no clue what might go wrong. On the right side I have at least a problem description which would suggest, that the mouse code is not incorporated. Which might even be true on the peripheral side?!? Any ideas would be nice. Here's the failed build. Thanks! Edit: Just saw that the zmk-only build was green. :) Edit 2: I fixed the right build by disabling the stuff in config. Still left with the problem on the left side... |
The right side problems are easy, either the mouse stuff wasn't merged properly, or you didn't enable the mouse driver. For the left side, I don't have any ideas, and you'll have to consult the ZMK/zephyr servers |
After many hours searching I could fix it with this. Coming from the Java world I have no idea how this can compile but then fail linking... Now have to add the actual trackpad... :) |
Oh, because all of the initialization code in zephyr is stored in order of the priority in the binary. The macros just generate linker sections |
After everything out of the way I was able to install the firmware. Already fixed the wrong i2c address but still init fails:
I know the trackpad is working with an Elite-C on QMK. Shy question: Was this tested with I2C? I can only find working SPI code... Or what am I missing? Also checked QMK code which looks similar to this... Will dig deeper tomorrow. Thanks! |
Not sure what's happening, but given that this is the first I2C call, it's likely that there's some problem on your bus. I would check that there's pullup on the bus, you didn't swap
Valid question. Not me. I think 1 or 2 people on the ZMK discord tested and had success with it
|
Yeah, I know it is working because of the tests with an Elite-C MCU and QMK. Sure, I meant in the open wild. I can see the I2C code in the driver. Will investigate further. Thanks! |
After a lot of debugging and some help from SplitKB Discord I had external power turned off. :( So now I know I2C is working also tested with an OLED on ZMK on the keyboard. I now get a new error for the first call to I2C
But still the same problem. Any idea what could be wrong? Edit |
As a follow up I tried to write the reset command to every I2C address on the bus in this commit but it can't do it anywhere. So something seams to be off unfortunately. |
I don't remember the address needs to be shifted. Also I can't really help much without an oscilloscope Just checking: have you desoldered |
Yes, i switched to I2C and 5V. For anybody interested here's a great resource explaining it. Although I just soldered everything to the test pads without adapter PCB. It works fine in QMK. I can't see anything on my oscilloscope. I ordered a logic analyzer from Aliexpress. This means a 2+ weeks break from the project... I read the I2C Cirque documentation a lot and can't figure out the START command in the code. Just the STOP as a flag. But I guess this is done deeper in the I2C driver... I think without logic analyzer I am blind atm. :( |
As far as I remember ZMK has some issues with reinitializing I2C after sleep (this might have been fixed) and when the ext power is toggled. So you need to make sure that the ext power is ON on startup. I would try first on the master side with USB plugged in, that might save you some debugging time. |
@FearlessSpiff if you're still having issues, you could just post a scope screenshot here. If it proves to be too complex to debug, we could move to some other channel to debug and summarize back here |
Thanks. Long time since I worked with these things. I just can't capture the start. And then it's just 5V... |
I think it should be pretty clear then. Check that it's powered and the pins are indeed wired correctly |
Unfortunately it is. I can just switch the MCU to the Elite-C with QMK and everything works. |
Oh, I only have 3.3V on the trackpad. Shouldn't this be 5V? Have to check it... Edit I guess this is it! I desoldered R7 and R8 to make it 5V and the N!N is only 3.3V. Good thing I have another Cirque lying around... |
@FearlessSpiff I think on 3.3V MCUs you need to leave the 5V resistors (R7, R8) on the trackpad. It depends on the board you are using, AFAIR splitkb ones connect 3.3V to I2C connector, but you can add a wire connecting it to power for LEDs. Check on their discord/schematic docs |
Finally it is initalizing! Thanks to everybody! I am now at the next problem by not beeing able to set a trigger. I changed
I can't find much in the docu, neither when googling for examples. Any idea? Thanks! |
PINNACLE_TRIGGER_NONE is probably what you are looking for. And then probably some task to fetch data. |
AFAIK |
Btw, I now logged the errorcode when calling |
When |
Thanks. I get it now. I guess I will need to create a thread and poll the sensor there. Or check schematics of my Aurora and maybe add a DR line somewhere. What advantages would it have to have a DR line? Is this just better for battery-life and that's it? |
Does anyone know what has to be done to get this done on a theoretical level, considering the new ZMK firmware structure? My ZMK config for reference: https://github.com/FrostKiwi/zmk-config |
I merged this PR into The firmware builds successfully without the driver being included: https://github.com/FrostKiwi/zmk-config/actions/runs/11378828087 but fails with the driver being included via /tmp/zmk-config/zmk/app/module/drivers/sensor/pinnacle/pinnacle.c:3:10: fatal error: init.h: No such file or directory
3 | #include <init.h>
| ^~~~~~~~ I have a Kyria rev3, nice!nano2, Cirque trackpad on both sites hooked up to i2c.
|
You should try using https://github.com/petejohanson/cirque-input-module (which is a module) along with either #2027 or #2477. I am not sure if the current state of this PR is compatible with these two, but I am sure that you need one of those branches for the Cirque to work. |
@caksoylar Ohh, I never knew of this module system! So the way I understand is: Go with #2027 as the base, it's only 2 months behind Include the module. This seems easy and I can follow. But how do you glue it together?
Looking at the source code of #2027 and seeing |
I think Pete summarized these two PRs pretty well in the latter's description:
You can see an example I2C usage (with 2027) here, there is an SPI version there as well. (
As an aside, I'd recommend you join the ZMK Discord which has a dedicated channel for pointing devices experimentation. It is difficult to do back-and-forth here for providing any sort of help with experimental features. |
This adds the driver for Cirque Pinnacle trackpads. Note this is only the driver, support for fetching the data and binding behaviours to it should be added later as it depends on reworking the sensor subsystem.
The driver uses only the SPI/I2C bus and the
dr
data ready pin if available.The implementation of the driver follows the Cirque documentation. While the docs mentions using the sleep mode with high SPI speeds can be a problem, this is not observed in reality (I'm using a SPI clock of 10MHz).
Usage example: https://github.com/crides/zmk/blob/fusion-led-c-config/app/boards/arm/fusion/trackpad.c