2022-12-10 03:18:40 +01:00
// Copyright 2022 Pablo Martinez (@elpekenin)
2022-07-16 11:33:18 +02:00
// Copyright 2022 Daniel Kao (dkao)
2022-07-14 11:50:00 +02:00
// Copyright 2022 Stefan Kerkmann (KarlK90)
// Copyright 2022 Ulrich Spörlein (@uqs)
// Copyright 2021 Alabastard (@Alabastard-64)
// Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
// Copyright 2019 Sunjun Kim
// Copyright 2020 Ploopy Corporation
// SPDX-License-Identifier: GPL-2.0-or-later
# pragma once
2023-07-09 12:03:50 +02:00
# include "keyboard.h"
2022-07-14 11:50:00 +02:00
# include <stdint.h>
# include "spi_master.h"
# include "util.h"
# if defined(POINTING_DEVICE_DRIVER_pmw3360)
# include "pmw3360.h"
# elif defined(POINTING_DEVICE_DRIVER_pmw3389)
# include "pmw3389.h"
# endif
typedef struct __attribute__ ( ( packed ) ) {
union {
struct {
bool capture_from_raw_data : 1 ; // FRAME_RData_1st
uint8_t operation_mode : 2 ; // OP_MODE
bool is_lifted : 1 ; // Lift_stat
bool raw_data_grab_is_raw_data : 1 ; // RData_1st
uint8_t _reserved : 2 ; // 1 + Reserved
bool is_motion : 1 ; // MOT
} b ;
uint8_t w ;
} motion ;
uint8_t observation ;
int16_t delta_x ; // displacement on x directions. Unit: Count. (CPI * Count = Inch value)
int16_t delta_y ; // displacement on y directions.
} pmw33xx_report_t ;
_Static_assert ( sizeof ( pmw33xx_report_t ) = = 6 , " pmw33xx_report_t must be 6 bytes in size " ) ;
_Static_assert ( sizeof ( ( pmw33xx_report_t ) { 0 } . motion ) = = 1 , " pmw33xx_report_t.motion must be 1 byte in size " ) ;
# if !defined(PMW33XX_CLOCK_SPEED)
# define PMW33XX_CLOCK_SPEED 2000000
# endif
# if !defined(PMW33XX_SPI_DIVISOR)
# ifdef __AVR__
# define PMW33XX_SPI_DIVISOR (F_CPU / PMW33XX_CLOCK_SPEED)
# else
# define PMW33XX_SPI_DIVISOR 64
# endif
# endif
# if !defined(PMW33XX_LIFTOFF_DISTANCE)
# define PMW33XX_LIFTOFF_DISTANCE 0x02
# endif
# if !defined(ROTATIONAL_TRANSFORM_ANGLE)
# define ROTATIONAL_TRANSFORM_ANGLE 0x00
# endif
2022-07-16 11:33:18 +02:00
2022-07-17 21:08:55 +02:00
# if ROTATIONAL_TRANSFORM_ANGLE > 127 || ROTATIONAL_TRANSFORM_ANGLE < (-127)
# error ROTATIONAL_TRANSFORM_ANGLE has to be in the range of + / - 127 for all PMW33XX sensors.
2022-07-16 11:33:18 +02:00
# endif
2022-07-14 11:50:00 +02:00
// Support single and plural spellings
# ifndef PMW33XX_CS_PINS
# ifndef PMW33XX_CS_PIN
2022-08-13 01:22:34 +02:00
# ifdef POINTING_DEVICE_CS_PIN
# define PMW33XX_CS_PIN POINTING_DEVICE_CS_PIN
# define PMW33XX_CS_PINS \
{ PMW33XX_CS_PIN }
# else
# error "No chip select pin defined -- missing PMW33XX_CS_PIN or PMW33XX_CS_PINS"
# endif
2022-07-14 11:50:00 +02:00
# else
# define PMW33XX_CS_PINS \
{ PMW33XX_CS_PIN }
# endif
# endif
2022-12-10 03:18:40 +01:00
// Support single spelling and default to be the same as left side
# if !defined(PMW33XX_CS_PINS_RIGHT)
# if !defined(PMW33XX_CS_PIN_RIGHT)
# define PMW33XX_CS_PIN_RIGHT PMW33XX_CS_PIN
# endif
# define PMW33XX_CS_PINS_RIGHT \
{ PMW33XX_CS_PIN_RIGHT }
# endif
// Defines so the old variable names are swapped by the appropiate value on each half
# define cs_pins (is_keyboard_left() ? cs_pins_left : cs_pins_right)
# define in_burst (is_keyboard_left() ? in_burst_left : in_burst_right)
# define pmw33xx_number_of_sensors (is_keyboard_left() ? ARRAY_SIZE((pin_t[])PMW33XX_CS_PINS) : ARRAY_SIZE((pin_t[])PMW33XX_CS_PINS_RIGHT))
2022-07-14 11:50:00 +02:00
# if PMW33XX_CPI > PMW33XX_CPI_MAX || PMW33XX_CPI < PMW33XX_CPI_MIN || (PMW33XX_CPI % PMW33XX_CPI_STEP) != 0U
# pragma message "PMW33XX_CPI has to be in the range of " STR(PMW33XX_CPI_MAX) "-" STR(PMW33XX_CPI_MIN) " in increments of " STR(PMW33XX_CPI_STEP) ". But it is " STR(PMW33XX_CPI) "."
# error Use correct PMW33XX_CPI value.
# endif
# define CONSTRAIN(amt, low, high) ((amt) < (low) ? (low) : ((amt) > (high) ? (high) : (amt)))
/**
* @ brief Initializes the given sensor so it is in a working state and ready to
* be polled for data .
*
* @ param sensor Index of the sensors chip select pin
* @ return true Initialization was a success
* @ return false Initialization failed , do not proceed operation
*/
bool __attribute__ ( ( cold ) ) pmw33xx_init ( uint8_t sensor ) ;
/**
* @ brief Gets the currently set CPI value from the sensor . CPI is often
* refereed to as the sensors sensitivity .
*
* @ param sensor Index of the sensors chip select pin
* @ return uint16_t Current CPI value of the sensor
*/
uint16_t pmw33xx_get_cpi ( uint8_t sensor ) ;
/**
* @ brief Sets the given CPI value for the given PMW33XX sensor . CIP is often
* refereed to as the sensors sensitivity . Values outside of the allow range are
* constrained into legal values .
*
* @ param sensor Index of the sensors chip select pin
* @ param cpi CPI value to set , legal range depends on the PMW sensor type
*/
void pmw33xx_set_cpi ( uint8_t sensor , uint16_t cpi ) ;
/**
* @ brief Sets the given CPI value to all registered PMW33XX sensors . CPI is
* often refereed to as the sensors sensitivity . Values outside of the allow
* range are constrained into legal values .
*
* @ param sensor Index of the sensors chip select pin
* @ param cpi CPI value to set , legal range depends on the PMW sensor type
*/
void pmw33xx_set_cpi_all_sensors ( uint16_t cpi ) ;
/**
* @ brief Reads and clears the current delta , and motion register values on the
* given sensor .
*
* @ param sensor Index of the sensors chip select pin
* @ return pmw33xx_report_t Current values of the sensor , if errors occurred all
* fields are set to zero
*/
pmw33xx_report_t pmw33xx_read_burst ( uint8_t sensor ) ;
/**
* @ brief Read one byte of data from the given register on the sensor
*
* @ param sensor Index of the sensors chip select pin
* @ param reg_addr Register address to read from
* @ return uint8_t
*/
uint8_t pmw33xx_read ( uint8_t sensor , uint8_t reg_addr ) ;
/**
* @ brief Writes one byte of data to the given register on the sensor
*
* @ param sensor Index of the sensors chip select pin
* @ param reg_addr Registers address to write to
* @ param data Data to write to the register
* @ return true Write was a success
* @ return false Write failed , do not proceed operation
*/
bool pmw33xx_write ( uint8_t sensor , uint8_t reg_addr , uint8_t data ) ;