summaryrefslogtreecommitdiff
path: root/driver/als_bh1730.c
blob: 0f96680471f001a84d7e45a915b325d7223d6491 (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
173
174
175
/* Copyright 2017 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.
 *
 * Rohm BH1730 Ambient light sensor driver
 */

#include "accelgyro.h"
#include "config.h"
#include "console.h"
#include "driver/als_bh1730.h"
#include "i2c.h"

#define CPRINTS(format, args...) cprints(CC_MOTION_SENSE, format, ## args)
#define CPRINTF(format, args...) cprintf(CC_MOTION_SENSE, format, ## args)

/**
 * Convert BH1730 data0, data1 to lux
 */
static int bh1730_convert_to_lux(uint32_t data0_1)
{
	int lux;
	uint16_t data0 = 0x0000ffff & data0_1;
	uint16_t data1 = data0_1 >> 16;
	uint32_t d0_1k = data0 * 1000;
	uint32_t d1_1k = data1 * 1000;
	uint32_t d_temp = d1_1k / d0_1k;
	uint32_t d_lux;

	if (data0 == 0)
		return 0;

	if(d_temp < BH1730_LUXTH1_1K) {
		d0_1k = BH1730_LUXTH1_D0_1K * data0;
		d1_1k = BH1730_LUXTH1_D1_1K * data1;
	} else if(d_temp < BH1730_LUXTH2_1K) {
		d0_1k = BH1730_LUXTH2_D0_1K * data0;
		d1_1k = BH1730_LUXTH2_D1_1K * data1;
	} else if(d_temp < BH1730_LUXTH3_1K) {
		d0_1k = BH1730_LUXTH3_D0_1K * data0;
		d1_1k = BH1730_LUXTH3_D1_1K * data1;
	} else if(d_temp < BH1730_LUXTH4_1K) {
		d0_1k = BH1730_LUXTH4_D0_1K * data0;
		d1_1k = BH1730_LUXTH4_D1_1K * data1;
	} else
		return 0;

	d_lux = (d0_1k - d1_1k) / BH1730_GAIN_DIV;
	d_lux *= 100;
	lux = d_lux / ITIME_MS_X_1K;

	return lux;
}

/**
 * Read BH1730 light sensor data.
 */
static int bh1730_read_lux(const struct motion_sensor_t *s, intv3_t v)
{
	struct bh1730_drv_data_t *drv_data = BH1730_GET_DATA(s);
	int ret;
	int data0_1;

	/* read data0 and data1 from sensor */
	ret = i2c_read32(s->port, s->addr, BH1730_DATA0LOW, &data0_1);
	if (ret != EC_SUCCESS) {
		CPRINTF("bh1730_read_lux - fail %d\n", ret);
		return ret;
	}

	/* convert sensor data0 and data1 to lux */
	v[0] = bh1730_convert_to_lux(data0_1);
	v[1] = 0;
	v[2] = 0;

	/*
	 * Return an error when nothing change to prevent filling the
	 * fifo with useless data.
	 */
	if (v[0] == drv_data->last_value)
		return EC_ERROR_UNCHANGED;
	else
		return EC_SUCCESS;
}

static int bh1730_set_range(const struct motion_sensor_t *s, int range,
			     int rnd)
{
	return EC_SUCCESS;
}

static int bh1730_get_range(const struct motion_sensor_t *s)
{
	return 1;
}

static int bh1730_set_data_rate(const struct motion_sensor_t *s,
				int rate, int roundup)
{
	struct bh1730_drv_data_t *drv_data = BH1730_GET_DATA(s);

	/* now only one rate supported */
	drv_data->rate = BH1730_10000_MHZ;

	return EC_SUCCESS;
}

static int bh1730_get_data_rate(const struct motion_sensor_t *s)
{
	struct bh1730_drv_data_t *drv_data = BH1730_GET_DATA(s);

	return drv_data->rate;
}

static int bh1730_set_offset(const struct motion_sensor_t *s,
			const int16_t *offset,
			int16_t    temp)
{
	return EC_SUCCESS;
}

static int bh1730_get_offset(const struct motion_sensor_t *s,
			int16_t   *offset,
			int16_t    *temp)
{
	*offset = 0;

	return EC_SUCCESS;
}

/**
 * Initialise BH1730 Ambient light sensor.
 */
static int bh1730_init(const struct motion_sensor_t *s)
{
	int ret;

	/* power and measurement bit high */
	ret = i2c_write8(s->port, s->addr,
			BH1730_CONTROL,
			BH1730_CONTROL_POWER_ENABLE|BH1730_CONTROL_ADC_EN_ENABLE);

	if (ret != EC_SUCCESS) {
		CPRINTF("bh1730_init_sensor - enable fail %d\n", ret);
		return ret;
	}

	/* set timing */
	ret = i2c_write8(s->port, s->addr, BH1730_TIMING, BH1730_CONF_ITIME);
	if (ret != EC_SUCCESS) {
		CPRINTF("bh1730_init_sensor - time fail %d\n", ret);
		return ret;
	}
	/* set ADC gain */
	ret = i2c_write8(s->port, s->addr, BH1730_GAIN, BH1730_CONF_GAIN);

	if (ret != EC_SUCCESS) {
		CPRINTF("bh1730_init_sensor - gain fail %d\n", ret);
		return ret;
	}

	return sensor_init_done(s);
}

const struct accelgyro_drv bh1730_drv = {
	.init = bh1730_init,
	.read = bh1730_read_lux,
	.set_range = bh1730_set_range,
	.get_range = bh1730_get_range,
	.set_offset = bh1730_set_offset,
	.get_offset = bh1730_get_offset,
	.set_data_rate = bh1730_set_data_rate,
	.get_data_rate = bh1730_get_data_rate,
};