summaryrefslogtreecommitdiff
path: root/prilohy/nrfdemo_source/src/bme680/bme680_spi.c
blob: 54840a7be82b7da26d8c9b3f23904a9ac3818449 (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
/*
 * Copyright (c) 2016, 2017 Intel Corporation
 * Copyright (c) 2017 IpTronix S.r.l.
 * Copyright (c) 2021 Nordic Semiconductor ASA
 * Copyright (c) 2022, Leonard Pollak
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/*
 * Bus-specific functionality for BME680s accessed via SPI.
 */

#include <zephyr/logging/log.h>
#include "bme680.h"

#if BME680_BUS_SPI

LOG_MODULE_DECLARE(bme680, CONFIG_SENSOR_LOG_LEVEL);

static int bme680_bus_check_spi(const union bme680_bus *bus)
{
	return spi_is_ready_dt(&bus->spi) ? 0 : -ENODEV;
}

static inline int bme680_set_mem_page(const struct device *dev, uint8_t addr)
{
	const struct bme680_config *config = dev->config;
	struct bme680_data *data = dev->data;
	uint8_t page = (addr > 0x7f) ? 0U : 1U;
	int err = 0;

	if (data->mem_page != page) {
		uint8_t buf[2];

		struct spi_buf tx_buf = {
			.buf = &buf[0],
			.len = 1,
		};
		const struct spi_buf_set tx = {
			.buffers = &tx_buf,
			.count = 1,
		};

		const struct spi_buf rx_buf[] = {
			{ .buf = NULL, .len = 1 },
			{ .buf = &buf[1], .len = 1 },
		};
		const struct spi_buf_set rx = {
			.buffers = rx_buf,
			.count = ARRAY_SIZE(rx_buf),
		};

		buf[0] = BME680_REG_STATUS | BME680_SPI_READ_BIT;
		err = spi_transceive_dt(&config->bus.spi, &tx, &rx);
		if (err < 0) {
			return err;
		}

		if (data->mem_page == 1U) {
			buf[1] &= ~BME680_SPI_MEM_PAGE_MSK;
		} else {
			buf[1] |= BME680_SPI_MEM_PAGE_MSK;
		}

		buf[0] = BME680_REG_STATUS & BME680_SPI_WRITE_MSK;
		tx_buf.len = 2;
		err = spi_write_dt(&config->bus.spi, &tx);
		if (err < 0) {
			return err;
		}

		data->mem_page = page;
	}

	return err;
}

static int bme680_reg_write_spi(const struct device *dev,
				uint8_t reg, uint8_t val)
{
	const struct bme680_config *config = dev->config;
	int err;
	uint8_t cmd[] = { reg & BME680_SPI_WRITE_MSK, val };
	const struct spi_buf tx_buf = {
		.buf = cmd,
		.len = sizeof(cmd)
	};
	const struct spi_buf_set tx = {
		.buffers = &tx_buf,
		.count = 1
	};

	err = bme680_set_mem_page(dev, reg);
	if (err) {
		return err;
	}

	err = spi_write_dt(&config->bus.spi, &tx);

	return err;
}

static int bme680_reg_read_spi(const struct device *dev,
			       uint8_t start, uint8_t *buf, int size)
{
	const struct bme680_config *config = dev->config;
	int err;
	uint8_t addr;
	const struct spi_buf tx_buf = {
		.buf = &addr,
		.len = 1
	};
	const struct spi_buf_set tx = {
		.buffers = &tx_buf,
		.count = 1
	};
	struct spi_buf rx_buf[2];
	const struct spi_buf_set rx = {
		.buffers = rx_buf,
		.count = ARRAY_SIZE(rx_buf)
	};

	rx_buf[0].buf = NULL;
	rx_buf[0].len = 1;

	addr = start | BME680_SPI_READ_BIT;
	rx_buf[1].buf = buf;
	rx_buf[1].len = size;

	err = bme680_set_mem_page(dev, start);
	if (err) {
		return err;
	}

	err = spi_transceive_dt(&config->bus.spi, &tx, &rx);

	return err;
}

const struct bme680_bus_io bme680_bus_io_spi = {
	.check = bme680_bus_check_spi,
	.read = bme680_reg_read_spi,
	.write = bme680_reg_write_spi,
};
#endif /* BME680_BUS_SPI */