summaryrefslogtreecommitdiffstats
path: root/drivers/sensors/pmw33xx_common.h
blob: b30ee3d59667e96332b9cc053c3d8bb74834e96a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
// Copyright 2022 Pablo Martinez (@elpekenin)
// Copyright 2022 Daniel Kao (dkao)
// 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

#include "keyboard.h"
#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

#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.
#endif

// Support single and plural spellings
#ifndef PMW33XX_CS_PINS
#    ifndef PMW33XX_CS_PIN
#        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
#    else
#        define PMW33XX_CS_PINS \
            { PMW33XX_CS_PIN }
#    endif
#endif

// 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))

#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);