Blackbox device type 'file' (SITL) considered working when file handler is available
[inav.git] / src / main / drivers / bus.h
blob6c2cedaff0228e2b9c8e64aa80d68e298296c7db
1 /*
2 * This file is part of INAV.
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
6 * You can obtain one at http://mozilla.org/MPL/2.0/.
8 * Alternatively, the contents of this file may be used under the terms
9 * of the GNU General Public License Version 3, as described below:
11 * This file is free software: you may copy, redistribute and/or modify
12 * it under the terms of the GNU General Public License as published by the
13 * Free Software Foundation, either version 3 of the License, or (at your
14 * option) any later version.
16 * This file is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
19 * Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see http://www.gnu.org/licenses/.
25 #pragma once
27 #include <stdbool.h>
28 #include <stdint.h>
30 #include "platform.h"
32 #include "drivers/resource.h"
33 #include "drivers/bus_i2c.h"
34 #include "drivers/bus_spi.h"
36 // FIXME: Hack until we rework SPI driver
37 #define BUS_SPI1 SPIDEV_1
38 #define BUS_SPI2 SPIDEV_2
39 #define BUS_SPI3 SPIDEV_3
40 #define BUS_SPI4 SPIDEV_4
42 #define BUS_I2C1 I2CDEV_1
43 #define BUS_I2C2 I2CDEV_2
44 #define BUS_I2C3 I2CDEV_3
45 #define BUS_I2C4 I2CDEV_4
46 #define BUS_I2C_EMULATED I2CINVALID
48 #define BUS_SCRATCHPAD_MEMORY_SIZE (20)
50 typedef enum {
51 BUS_SPEED_INITIALIZATION = 0,
52 BUS_SPEED_SLOW = 1,
53 BUS_SPEED_STANDARD = 2,
54 BUS_SPEED_FAST = 3,
55 BUS_SPEED_ULTRAFAST = 4
56 } busSpeed_e;
58 typedef enum {
59 BUSTYPE_ANY = 0,
60 BUSTYPE_NONE = 0,
61 BUSTYPE_I2C = 1,
62 BUSTYPE_SPI = 2,
63 BUSTYPE_SDIO = 3,
64 } busType_e;
66 typedef enum {
67 BUSINDEX_1 = 0,
68 BUSINDEX_2 = 1,
69 BUSINDEX_3 = 2,
70 BUSINDEX_4 = 3
71 } busIndex_e;
73 /* Ultimately all hardware descriptors will go to target definition files.
74 * Driver code will merely query for it's HW descriptor and initialize it */
75 typedef enum {
76 DEVHW_NONE = 0,
78 /* Combined ACC/GYRO chips */
79 DEVHW_MPU6000,
80 DEVHW_MPU6500,
81 DEVHW_BMI160,
82 DEVHW_BMI088_GYRO,
83 DEVHW_BMI088_ACC,
84 DEVHW_ICM20689,
85 DEVHW_ICM42605,
86 DEVHW_BMI270,
87 DEVHW_LSM6D,
88 /* Combined ACC/GYRO/MAG chips */
89 DEVHW_MPU9250,
91 /* Barometer chips */
92 DEVHW_BMP085,
93 DEVHW_BMP280,
94 DEVHW_MS5611,
95 DEVHW_MS5607,
96 DEVHW_LPS25H,
97 DEVHW_SPL06,
98 DEVHW_BMP388,
99 DEVHW_DPS310,
100 DEVHW_B2SMPB,
102 /* Compass chips */
103 DEVHW_HMC5883,
104 DEVHW_AK8963,
105 DEVHW_AK8975,
106 DEVHW_IST8310_0,
107 DEVHW_IST8310_1,
108 DEVHW_IST8308,
109 DEVHW_QMC5883,
110 DEVHW_MAG3110,
111 DEVHW_LIS3MDL,
112 DEVHW_RM3100,
113 DEVHW_VCM5883,
114 DEVHW_MLX90393,
116 /* Temp sensor chips */
117 DEVHW_LM75_0,
118 DEVHW_LM75_1,
119 DEVHW_LM75_2,
120 DEVHW_LM75_3,
121 DEVHW_LM75_4,
122 DEVHW_LM75_5,
123 DEVHW_LM75_6,
124 DEVHW_LM75_7,
126 /* 1-wire interface chips */
127 DEVHW_DS2482,
129 /* OSD chips */
130 DEVHW_MAX7456,
132 /* Rangefinder modules */
133 DEVHW_SRF10,
134 DEVHW_VL53L0X,
135 DEVHW_VL53L1X,
136 DEVHW_US42,
137 DEVHW_TOF10120_I2C,
138 DEVHW_TERARANGER_EVO_I2C,
140 /* Other hardware */
141 DEVHW_MS4525, // Pitot meter
142 DEVHW_DLVR, // Pitot meter
143 DEVHW_M25P16, // SPI NOR flash
144 DEVHW_W25N01G, // SPI 128MB flash
145 DEVHW_UG2864, // I2C OLED display
146 DEVHW_SDCARD, // Generic SD-Card
147 DEVHW_IRLOCK, // IR-Lock visual positioning hardware
148 DEVHW_PCF8574, // 8-bit I/O expander
149 } devHardwareType_e;
151 typedef enum {
152 DEVFLAGS_NONE = 0,
153 DEVFLAGS_USE_RAW_REGISTERS = (1 << 0), // Don't manipulate MSB for R/W selection (SPI), allow using 0xFF register to raw i2c reads/writes
155 // SPI-only
156 DEVFLAGS_USE_MANUAL_DEVICE_SELECT = (1 << 1), // (SPI only) Don't automatically select/deselect device
157 DEVFLAGS_SPI_MODE_0 = (1 << 2), // (SPI only) Use CPOL=0/CPHA=0 (if unset MODE3 is used - CPOL=1/CPHA=1)
158 } deviceFlags_e;
160 typedef struct busDeviceDescriptor_s {
161 void * devicePtr;
162 busType_e busType;
163 devHardwareType_e devHwType;
164 uint8_t flags;
165 uint8_t tag;
166 uint8_t param; // Driver-specific parameter
167 union {
168 #ifdef USE_SPI
169 struct {
170 SPIDevice spiBus;
171 ioTag_t csnPin;
172 } spi;
173 #endif
174 #ifdef USE_I2C
175 struct {
176 I2CDevice i2cBus;
177 uint8_t address;
178 } i2c;
179 #endif
180 } busdev;
181 ioTag_t irqPin;
182 } busDeviceDescriptor_t;
184 typedef struct busDevice_s {
185 const busDeviceDescriptor_t * descriptorPtr;
186 busType_e busType; // Copy of busType to avoid additional pointer dereferencing
187 uint32_t flags; // Copy of flags
188 uint32_t param; // Copy of param
189 union {
190 #ifdef USE_SPI
191 struct {
192 SPIDevice spiBus; // SPI bus ID
193 IO_t csnPin; // IO for CS# pin
194 } spi;
195 #endif
196 #ifdef USE_I2C
197 struct {
198 I2CDevice i2cBus; // I2C bus ID
199 uint8_t address; // I2C bus device address
200 } i2c;
201 #endif
202 } busdev;
203 IO_t irqPin; // Device IRQ pin. Bus system will only assign IO_t object to this var. Initialization is up to device driver
204 uint32_t * scratchpad; // Memory where device driver can store persistent data. Zeroed out when initializing the device
205 // for the first time. Useful when once device is shared between several sensors
206 // (like MPU/ICM acc-gyro sensors)
207 } busDevice_t;
209 #ifdef __APPLE__
210 extern const busDeviceDescriptor_t __busdev_registry_start[] __asm("section$start$__DATA$__busdev_registry");
211 extern const busDeviceDescriptor_t __busdev_registry_end[] __asm("section$end$__DATA$__busdev_registry");
212 #define BUSDEV_REGISTER_ATTRIBUTES __attribute__ ((section("__DATA,__busdev_registry"), used, aligned(4)))
213 #else
214 extern const busDeviceDescriptor_t __busdev_registry_start[];
215 extern const busDeviceDescriptor_t __busdev_registry_end[];
216 #define BUSDEV_REGISTER_ATTRIBUTES __attribute__ ((section(".busdev_registry"), used, aligned(4)))
217 #endif
219 #ifdef USE_SPI
220 #define BUSDEV_REGISTER_SPI_F(_name, _devHw, _spiBus, _csnPin, _irqPin, _tag, _flags, _param) \
221 extern const busDeviceDescriptor_t _name ## _registry; \
222 static busDevice_t _name ## _memory; \
223 const busDeviceDescriptor_t _name ## _registry BUSDEV_REGISTER_ATTRIBUTES = { \
224 .devicePtr = (void *) & _name ## _memory, \
225 .busType = BUSTYPE_SPI, \
226 .devHwType = _devHw, \
227 .flags = _flags, \
228 .tag = _tag, \
229 .param = _param, \
230 .busdev.spi = { \
231 .spiBus = _spiBus, \
232 .csnPin = IO_TAG(_csnPin) \
233 }, \
234 .irqPin = IO_TAG(_irqPin) \
235 }; \
236 struct _dummy \
237 /**/
239 #define BUSDEV_REGISTER_SPI(_name, _devHw, _spiBus, _csnPin, _irqPin, _flags, _param) \
240 BUSDEV_REGISTER_SPI_F(_name, _devHw, _spiBus, _csnPin, _irqPin, 0, _flags, _param)
242 #define BUSDEV_REGISTER_SPI_TAG(_name, _devHw, _spiBus, _csnPin, _irqPin, _tag, _flags, _param) \
243 BUSDEV_REGISTER_SPI_F(_name, _devHw, _spiBus, _csnPin, _irqPin, _tag, _flags, _param)
244 #else
245 #define BUSDEV_REGISTER_SPI(_name, _devHw, _spiBus, _csnPin, _irqPin, _flags, _param) // NO-OP
246 #define BUSDEV_REGISTER_SPI_TAG(_name, _devHw, _spiBus, _csnPin, _irqPin, _tag, _flags, _param) // NO-OP
247 #endif
249 #ifdef USE_I2C
250 #define BUSDEV_REGISTER_I2C_F(_name, _devHw, _i2cBus, _devAddr, _irqPin, _tag, _flags, _param) \
251 extern const busDeviceDescriptor_t _name ## _registry; \
252 static busDevice_t _name ## _memory; \
253 const busDeviceDescriptor_t _name ## _registry BUSDEV_REGISTER_ATTRIBUTES = { \
254 .devicePtr = (void *) & _name ## _memory, \
255 .busType = BUSTYPE_I2C, \
256 .devHwType = _devHw, \
257 .flags = _flags, \
258 .tag = _tag, \
259 .param = _param, \
260 .busdev.i2c = { \
261 .i2cBus = _i2cBus, \
262 .address = _devAddr \
263 }, \
264 .irqPin = IO_TAG(_irqPin) \
265 }; \
266 struct _dummy \
267 /**/
269 #define BUSDEV_REGISTER_I2C(_name, _devHw, _i2cBus, _devAddr, _irqPin, _flags, _param) \
270 BUSDEV_REGISTER_I2C_F(_name, _devHw, _i2cBus, _devAddr, _irqPin, 0, _flags, _param)
272 #define BUSDEV_REGISTER_I2C_TAG(_name, _devHw, _i2cBus, _devAddr, _irqPin, _tag, _flags, _param)\
273 BUSDEV_REGISTER_I2C_F(_name, _devHw, _i2cBus, _devAddr, _irqPin, _tag, _flags, _param)
274 #else
275 #define BUSDEV_REGISTER_I2C(_name, _devHw, _i2cBus, _devAddr, _irqPin, _flags, _param) // NO-OP
276 #define BUSDEV_REGISTER_I2C_TAG(_name, _devHw, _i2cBus, _devAddr, _irqPin, _tag, _flags, _param) // NO-OP
277 #endif
279 // busTransfer and busTransferMultiple are supported only on full-duplex SPI bus
280 typedef struct busTransferDescriptor_s {
281 uint8_t * rxBuf;
282 const uint8_t * txBuf;
283 uint32_t length;
284 } busTransferDescriptor_t;
286 /* Internal abstraction function */
287 bool i2cBusWriteBuffer(const busDevice_t * dev, uint8_t reg, const uint8_t * data, uint8_t length);
288 bool i2cBusWriteRegister(const busDevice_t * dev, uint8_t reg, uint8_t data);
289 bool i2cBusReadBuffer(const busDevice_t * dev, uint8_t reg, uint8_t * data, uint8_t length);
290 bool i2cBusReadRegister(const busDevice_t * dev, uint8_t reg, uint8_t * data);
291 bool i2cBusBusy(const busDevice_t *dev, bool *error);
293 bool spiBusInitHost(const busDevice_t * dev);
294 bool spiBusIsBusy(const busDevice_t * dev);
295 void spiBusSetSpeed(const busDevice_t * dev, busSpeed_e speed);
296 bool spiBusTransfer(const busDevice_t * dev, uint8_t * rxBuf, const uint8_t * txBuf, int length);
297 bool spiBusTransferMultiple(const busDevice_t * dev, busTransferDescriptor_t * dsc, int count);
298 bool spiBusWriteBuffer(const busDevice_t * dev, uint8_t reg, const uint8_t * data, uint8_t length);
299 bool spiBusWriteRegister(const busDevice_t * dev, uint8_t reg, uint8_t data);
300 bool spiBusReadBuffer(const busDevice_t * dev, uint8_t reg, uint8_t * data, uint8_t length);
301 bool spiBusReadRegister(const busDevice_t * dev, uint8_t reg, uint8_t * data);
302 void spiBusSelectDevice(const busDevice_t * dev);
303 void spiBusDeselectDevice(const busDevice_t * dev);
305 /* Pre-initialize all known device descriptors to make sure hardware state is consistent and known
306 * Initialize bus hardware */
307 void busInit(void);
309 /* Finds a device in registry. First matching device is returned. Also performs the low-level initialization of the hardware (CS line for SPI) */
310 busDevice_t * busDeviceInit(busType_e bus, devHardwareType_e hw, uint8_t tag, resourceOwner_e owner);
311 busDevice_t * busDeviceOpen(busType_e bus, devHardwareType_e hw, uint8_t tag);
312 void busDeviceDeInit(busDevice_t * dev);
314 uint32_t busDeviceReadScratchpad(const busDevice_t * dev);
315 void busDeviceWriteScratchpad(busDevice_t * dev, uint32_t value);
316 void * busDeviceGetScratchpadMemory(const busDevice_t * dev);
318 void busSetSpeed(const busDevice_t * dev, busSpeed_e speed);
320 /* Select/Deselect device will allow code to do something during device transfer or do transfer in chunks over some time */
321 void busSelectDevice(const busDevice_t * dev);
322 void busDeselectDevice(const busDevice_t * dev);
324 bool busWriteBuf(const busDevice_t * busdev, uint8_t reg, const uint8_t * data, uint8_t length);
325 bool busReadBuf(const busDevice_t * busdev, uint8_t reg, uint8_t * data, uint8_t length);
326 bool busRead(const busDevice_t * busdev, uint8_t reg, uint8_t * data);
327 bool busWrite(const busDevice_t * busdev, uint8_t reg, uint8_t data);
329 bool busTransfer(const busDevice_t * dev, uint8_t * rxBuf, const uint8_t * txBuf, int length);
330 bool busTransferMultiple(const busDevice_t * dev, busTransferDescriptor_t * buffers, int count);
332 bool busIsBusy(const busDevice_t * dev);