@@ -122,6 +122,7 @@ def __init__(self, dr_pin=None):
122
122
raise OSError ("Cirque Pinnacle ASIC not responding" )
123
123
124
124
# init internal attributes w/ factory defaults after power-on-reset
125
+ self ._hco = bool (self ._rap_read (0x1F )) # is hardware custom configured?
125
126
self ._sys_config = 0 # ignoring read-only reset flag (bit 0)
126
127
self ._feed_config1 = 1 # enables feed & sets to relative mode
127
128
self ._feed_config2 = 2 # disables taps in relative mode
@@ -237,25 +238,36 @@ def data_mode(self, mode):
237
238
# now configure the AnyMeas mode to default values
238
239
self .anymeas_mode_config ()
239
240
240
- def relative_mode_config (self , rotate90 = False , disable_taps = True ):
241
+ @property
242
+ def hard_configured (self ):
243
+ """This `bool` attribute provides insight to applications about factory
244
+ customized hardware configuration. see note about product labeling in
245
+ `Model Labeling Scheme <index.html#model-labeling-scheme>`_. (read only)"""
246
+ return self ._hco
247
+
248
+ def relative_mode_config (self , rotate90 = False , glide_extend = True ,
249
+ secondary_tap = True , taps = False , intellimouse = False ):
241
250
"""Set the configuration register for features specific to relative mode (AKA mouse mode)
242
- data reporting. (write only)
243
-
244
- This function only applies to Relative mode, otherwise if `data_mode` is set to
245
- :attr:`~circuitpython_cirque_pinnacle.DataModes.ANYMEAS` or
246
- :attr:`~circuitpython_cirque_pinnacle.DataModes.ABSOLUTE`, then this function will take
247
- no affect until `data_mode` is set to
248
- :attr:`~circuitpython_cirque_pinnacle.DataModes.RELATIVE`.
251
+ data reporting.
249
252
250
253
:param bool rotate90: Specifies if the axis data is altered for 90 degree rotation before
251
- reporting it. Default is `False`.
252
- :param bool disable_taps: Specifies if all taps should be reported (`False`) or not
253
- (`True`). Default is `True`. Only button 1 (left mouse button) is emulated with a tap
254
- and will be reflected in the button data portion of the data reports.
254
+ reporting it (essentially swaps the axis data). Default is `False`.
255
+ :param bool glide_extend: A patended feature that allows the user to glide their finger off
256
+ the edge of the sensor and continue gesture with the touch event. Default is `True`.
257
+ This feature is only available if `hard_configured` is `False`.
258
+ :param bool secondary_tap: Specifies if tapping in the top-left corner (depending on
259
+ orientation) triggers the secondary button data. Defaults to `True`. This feature is
260
+ only available if `hard_configured` is `False`.
261
+ :param bool taps: Specifies if all taps should be reported (`True`) or not
262
+ (`False`). Default is `True`. This affects ``secondary_tap`` option as well. The
263
+ primary button (left mouse button) is emulated with a tap.
264
+ :param bool intellimouse: Specifies if the data reported includes a byte about scroll data.
265
+ Default is `False`. Because this flag is specific to scroll data, this feature is only
266
+ available if `hard_configured` is `False`.
255
267
"""
256
- self ._feed_config2 = rotate90 << 7 | disable_taps << 1
257
- if self . data_mode == DataModes . RELATIVE :
258
- self ._rap_write (PINNACLE_FEED_CONFIG2 , self ._feed_config2 )
268
+ self ._feed_config2 = rotate90 << 7 | ( not glide_extend ) << 4 | (
269
+ not secondary_tap ) << 2 | ( not taps ) << 1 | intellimouse
270
+ self ._rap_write (PINNACLE_FEED_CONFIG2 , self ._feed_config2 )
259
271
260
272
def absolute_mode_config (self , z_idle_count = 30 , invert_x = False , invert_y = False ):
261
273
"""Set the configuration settings specific to Absolute mode (reports axis positions).
@@ -300,45 +312,64 @@ def report(self, only_new=True):
300
312
301
313
.. list-table::
302
314
:header-rows: 1
303
- :widths: 2, 8, 8
315
+ :widths: 1, 5, 5
304
316
305
317
* - Index
306
- - Relative (Mouse) mode as a `bytearray`
307
- - Absolute Mode as a `list`
318
+ - Relative (Mouse) mode
319
+
320
+ as a `bytearray`
321
+ - Absolute Mode
322
+
323
+ as a `list`
308
324
* - 0
309
- - "Button Data"
310
- - "Button Data"
325
+ - Button Data [1]_
326
+
327
+ one unsigned byte
328
+ - Button Data [1]_
329
+
330
+ one unsigned byte
311
331
* - 1
312
- - "change in x-axis"
313
- - "x-axis Position"
332
+ - change in x-axis [2]_
333
+
334
+ -128 |LessEq| X |LessEq| 127
335
+ - x-axis Position
336
+
337
+ 128 |LessEq| X |LessEq| 1920
314
338
* - 2
315
- - "change in y-axis"
316
- - "y-axis Position"
317
- * - 3
318
- - "change in scroll wheel"
319
- - "z-axis Position"
339
+ - change in y-axis [2]_
320
340
321
- .. important:: The axis data reported in Relative/Mouse mode is in two's
322
- comliment form. Use Python's :py:func:`struct.unpack()` to convert the
323
- data into integer form (see `Simple Test example <examples.html#simple-test>`_
324
- for how to use this function).
341
+ -128 |LessEq| Y |LessEq| 127
342
+ - y-axis Position
325
343
326
- The axis data reported in Absolute mode is always positive as the
327
- xy-plane's origin is located to the top-left, unless ``invert_x`` or ``invert_y``
328
- parameters to `absolute_mode_config()` are manipulated to change the perspective
329
- location of the origin.
344
+ 64 |LessEq| Y |LessEq| 1472
345
+ * - 3
346
+ - change in scroll wheel
330
347
331
- :Button Data: The returned button data is a byte in which each bit represents a button
332
- The bit to button order is as follows:
348
+ -128 |LessEq| Y |LessEq| 127 [3]_
349
+ - z-axis Position
333
350
334
- 0. [LSB] Button 1 (thought of as Left button in Relative/Mouse mode).
335
- If taps are enabled in Relative/Mouse mode, a single tap will be reflected here
336
- 1. Button 2 (thought of as Right button in Relative/Mouse mode)
337
- 2. Button 3 (thought of as Middle or scroll wheel button in Relative/Mouse mode)
351
+ .. [1] The returned button data is a byte in which each bit represents a button.
352
+ The bit to button order is as follows:
338
353
339
- .. note:: In Relative/Mouse mode, the scroll wheel data is a zero-value byte as the
354
+ 0. [LSB] Button 1 (thought of as Left button in Relative/Mouse mode). If taps
355
+ are enabled using `relative_mode_config()`, a single tap will be reflected here.
356
+ 1. Button 2 (thought of as Right button in Relative/Mouse mode)
357
+ 2. Button 3 (thought of as Middle or scroll wheel button in Relative/Mouse mode)
358
+ .. [2] The axis data reported in Relative/Mouse mode is in two's
359
+ comliment form. Use Python's :py:func:`struct.unpack()` to convert the
360
+ data into integer form (see `Simple Test example <examples.html#simple-test>`_
361
+ for how to use this function).
362
+
363
+ The axis data reported in Absolute mode is always positive as the
364
+ xy-plane's origin is located to the top-left, unless ``invert_x`` or ``invert_y``
365
+ parameters to `absolute_mode_config()` are manipulated to change the perspective
366
+ location of the origin.
367
+ .. [3] In Relative/Mouse mode the scroll wheel data is only reported if the
368
+ ``intellimouse`` parameter is passed as `True` to `relative_mode_config()`.
369
+ Otherwise this is an empty byte as the
340
370
returned `bytearray` follows the buffer structure of a mouse HID report (see
341
371
`USB Mouse example <examples.html#usb-mouse-example>`_).
372
+ .. |LessEq| unicode:: U+2264
342
373
"""
343
374
if self ._mode == DataModes .ANYMEAS :
344
375
return None
@@ -356,11 +387,19 @@ def report(self, only_new=True):
356
387
((temp [4 ] & 0x0F ) << 8 ) | temp [2 ], # x
357
388
((temp [4 ] & 0xF0 ) << 4 ) | temp [3 ], # y
358
389
temp [5 ] & 0x3F ] # z
390
+ # datasheet recommends clipping for reliability
391
+ return_vals [1 ] = min (128 , max (1920 , return_vals [1 ]))
392
+ return_vals [2 ] = min (64 , max (1472 , return_vals [2 ]))
359
393
elif self .data_mode == DataModes .RELATIVE : # if in relative mode
394
+ is_intellimouse = self ._feed_config2 & 1
360
395
# get relative data packets
361
- temp = self ._rap_read_bytes (PINNACLE_PACKET_BYTE_0 , 3 )
362
- # convrert to bytearray & append empty byte to suite mouse HID reports
363
- return_vals = bytearray ([temp [0 ] & 7 , temp [1 ], temp [2 ], 0 ])
396
+ temp = self ._rap_read_bytes (
397
+ PINNACLE_PACKET_BYTE_0 , 3 + is_intellimouse )
398
+ return_vals = bytearray ([temp [0 ] & 7 , temp [1 ], temp [2 ]])
399
+ if is_intellimouse : # scroll wheel data is captured
400
+ return_vals += bytes ([temp [3 ]])
401
+ else : # append empty byte to suite mouse HID reports
402
+ return_vals += b'\x00 '
364
403
# clear flags despite if data is fresh or not (faster & reliable)
365
404
self .clear_flags ()
366
405
return return_vals
0 commit comments