summaryrefslogtreecommitdiff
path: root/driver/accelgyro_icm_common.h
blob: 8cf3b1e41d8ea930865a3a6fd7c0b7ae685921d2 (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
/* Copyright 2020 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

/* ICM accelerometer and gyroscope common definitions for Chrome EC */

#ifndef __CROS_EC_ACCELGYRO_ICM_COMMON_H
#define __CROS_EC_ACCELGYRO_ICM_COMMON_H

#include "accelgyro.h"
#include "hwtimer.h"
#include "timer.h"

#if !defined(CONFIG_ACCELGYRO_ICM_COMM_SPI) && \
	!defined(CONFIG_ACCELGYRO_ICM_COMM_I2C)
#error "ICM must use either SPI or I2C communication"
#endif

#ifdef CONFIG_ACCEL_FIFO
/* reserve maximum 4 samples of 16 bytes */
#define ICM_FIFO_BUFFER	64
#else
#define ICM_FIFO_BUFFER	0
#endif

struct icm_drv_data_t {
	struct accelgyro_saved_data_t saved_data[2];
	struct motion_sensor_t *accel;
	struct motion_sensor_t *gyro;
	uint32_t stabilize_ts[2];
	uint8_t bank;
	uint8_t fifo_en;
	uint8_t fifo_buffer[ICM_FIFO_BUFFER] __aligned(sizeof(long));
};

#define ICM_GET_DATA(_s) \
	((struct icm_drv_data_t *)(_s)->drv_data)
#define ICM_GET_SAVED_DATA(_s) \
	(&ICM_GET_DATA(_s)->saved_data[(_s)->type])

/*
 * Virtual register address is 16 bits:
 * - 8 bits MSB coding bank number
 * - 8 bits LSB coding physical address
 */
#define ICM426XX_REG_GET_BANK(_r)	(((_r) & 0xFF00) >> 8)
#define ICM426XX_REG_GET_ADDR(_r)	((_r) & 0x00FF)

/* Sensor resolution in number of bits */
#define ICM_RESOLUTION		16

/**
 * sign_extend - sign extend a standard int value using the given sign-bit
 * @value: value to sign extend
 * @index: 0 based bit index to sign bit
 */
static inline int sign_extend(int value, int index)
{
	int shift = (sizeof(int) * 8) - index - 1;

	return (int)(value << shift) >> shift;
}

/**
 * Read 8 bits register
 */
int icm_read8(const struct motion_sensor_t *s, const int reg, int *data_ptr);

/**
 * Write 8 bits register
 */
int icm_write8(const struct motion_sensor_t *s, const int reg, int data);

/**
 * Read 16 bits register
 */
int icm_read16(const struct motion_sensor_t *s, const int reg, int *data_ptr);

/**
 * Write 16 bits register
 */
int icm_write16(const struct motion_sensor_t *s, const int reg, int data);

/**
 * Read n bytes
 */
int icm_read_n(const struct motion_sensor_t *s, const int reg,
	       uint8_t *data_ptr, const int len);

int icm_field_update8(const struct motion_sensor_t *s, const int reg,
		      const uint8_t field_mask, const uint8_t set_value);

int icm_get_resolution(const struct motion_sensor_t *s);

int icm_get_range(const struct motion_sensor_t *s);

int icm_get_data_rate(const struct motion_sensor_t *s);

int icm_set_scale(const struct motion_sensor_t *s, const uint16_t *scale,
		  int16_t temp);

int icm_get_scale(const struct motion_sensor_t *s, uint16_t *scale,
		  int16_t *temp);

ssize_t icm_fifo_decode_packet(const void *packet, const uint8_t **accel,
		const uint8_t **gyro);

static inline void icm_set_stabilize_ts(const struct motion_sensor_t *s,
					uint32_t delay)
{
	struct icm_drv_data_t *st = ICM_GET_DATA(s);
	uint32_t stabilize_ts;

	stabilize_ts = __hw_clock_source_read() + delay;
	/* prevent 0 value used for disabling time checking */
	st->stabilize_ts[s->type] = stabilize_ts | 1;
}

static inline void icm_reset_stabilize_ts(const struct motion_sensor_t *s)
{
	struct icm_drv_data_t *st = ICM_GET_DATA(s);

	st->stabilize_ts[s->type] = 0;
}

static inline
int32_t icm_get_sensor_stabilized(const struct motion_sensor_t *s,
				  uint32_t ts)
{
	struct icm_drv_data_t *st = ICM_GET_DATA(s);
	uint32_t stabilize_ts = st->stabilize_ts[s->type];

	if (stabilize_ts == 0)
		return 0;

	return time_until(ts, stabilize_ts);
}

#endif	/* __CROS_EC_ACCELGYRO_ICM_COMMON_H */