I wrote a driver for the PIM447 trackball in polling-mode, and now I’d like to rewrite it in interrupt-mode. Sadly, it turns out the INT signal toggles during I2C transactions (whatever the value of “INT_OUT” bit in REG_INT). See first capture below.
Also, even without touching the ball, the INT signal falls (which means new data are supposed to be available, which is not the case) a couple of milliseconds after registers are read, just as if the interruption was not cleared. See second capture below.
I took a look at the official driver, but despite having the “interrupt” keyword used here and there, it actually polls the INT signal; it doesn’t use it as a trigger (comments are mine):
while not trackball.get_interrupt():
time.sleep(0.001)
[...]
def get_interrupt(self):
if self._interrupt_pin is not None:
return GPIO.input(self._interrupt_pin) == 0 # poll pin level
else: # or
value = self.i2c_rdwr([REG_INT], 1)[0] # poll register value
return value & MSK_INT_TRIGGERED
In order to write an interrupt-mode driver I need a clean INT signal. Please, could you tell me:
how not to get the INT signal toggling during I2C transactions?
how not to get the INT signal falling even when no new data are available?
Were you able to get the clean INT signal? It seems like the hardware has issues because I’ve tried multiple software paths to do it. Namely, the following were tried in the interrupt handler:
Reading the left, right, up, down, and button registers alone.
Reading the Interrupt register alone.
Reading from 2 and 3, in either orders of one before and after the other.
Disabling Interrupt, then reading the 5 sensor values followed by the re-enabling of the Interrupt did not work either. From the status of the register, it can be seen that the bit zero of the Interrupt register (supposedly the bit that indicates an interrupt was generated), did not go high during such repeated interrupt reads, but did get set to 1 when the trackball had actual motion. This indicates to me this bit does as it says, but the hardware is still toggling interrupt line for some reason without any motion on the trackball.
Bump! I would love to use one of these on a wireless build I’m working on but would need it not to straight up eat the battery… Any official answer for these questions?
Another bump, I’d also like to make use of this module for a new wireless build, and I’d love to be able to use the trackball without it churning through the battery. Hopefully we can get an official response soon?
i received a new trackball with updated firmware and it seems like the interupt part is fixed , i tested on qmk by adding this code and then testing on old and new version
#define PIMORONI_TRACKBALL_REG_INT 0xF9
void pimoroni_trackball_set_interupt(void) {
uint8_t value = 0;
__attribute__((unused)) i2c_status_t status = i2c_readReg(PIMORONI_TRACKBALL_ADDRESS << 1, PIMORONI_TRACKBALL_REG_INT, &value, sizeof(uint8_t), PIMORONI_TRACKBALL_TIMEOUT);
uint8_t MSK_INT_OUT_EN = 0b00000010;
value &= ~MSK_INT_OUT_EN;
value |= MSK_INT_OUT_EN;
i2c_writeReg(PIMORONI_TRACKBALL_ADDRESS << 1, PIMORONI_TRACKBALL_REG_INT, &value, sizeof(uint8_t), PIMORONI_TRACKBALL_TIMEOUT);
}
for people interested, flashing from linux is also possible from a virtual machine (win 11 guest on vmware), the steps are :
ask pimoroni support for the firmware
acquire a nuvoton programmer , i used the cheapest one (13 Euro) on ali express named : NuMicro ICP programmer Nu-Link Nu Link Nuvoton ICP emulator downloader support online/offline programming M0/M4 series chips