Add EzTune to the settings.yaml
[inav.git] / src / main / drivers / bus.c
blobf06e847d572c50471037d4153d3400666ad39865
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 #include <string.h>
27 #include "platform.h"
28 #include "build/debug.h"
30 #include "common/memory.h"
32 #include "drivers/bus.h"
33 #include "drivers/io.h"
35 #define BUSDEV_MAX_DEVICES 16
37 #ifdef USE_SPI
38 static void busDevPreInit_SPI(const busDeviceDescriptor_t * descriptor)
40 // Pre-initialize SPI device chip-select line to input with weak pull-up
41 IO_t io = IOGetByTag(descriptor->busdev.spi.csnPin);
42 if (io) {
43 IOInit(io, OWNER_SPI_PREINIT, RESOURCE_SPI_CS, 0);
44 IOConfigGPIO(io, IOCFG_IPU);
47 #endif
49 static void busDevPreInit(const busDeviceDescriptor_t * descriptor)
51 switch (descriptor->busType) {
52 default:
53 case BUSTYPE_NONE:
54 break;
56 case BUSTYPE_I2C:
57 break;
59 case BUSTYPE_SPI:
60 #ifdef USE_SPI
61 busDevPreInit_SPI(descriptor);
62 #endif
63 break;
67 void busInit(void)
69 /* Pre-initialize bus devices */
70 for (const busDeviceDescriptor_t * descriptor = __busdev_registry_start; (descriptor) < __busdev_registry_end; descriptor++) {
71 busDevPreInit(descriptor);
75 #ifdef USE_I2C
76 static bool busDevInit_I2C(busDevice_t * dev, const busDeviceDescriptor_t * descriptor)
78 dev->busType = descriptor->busType;
79 dev->irqPin = IOGetByTag(descriptor->irqPin);
80 dev->busdev.i2c.i2cBus = descriptor->busdev.i2c.i2cBus;
81 dev->busdev.i2c.address = descriptor->busdev.i2c.address;
82 return true;
84 #endif
86 #ifdef USE_SPI
87 static bool busDevInit_SPI(busDevice_t * dev, const busDeviceDescriptor_t * descriptor, resourceOwner_e owner)
89 dev->busType = descriptor->busType;
90 dev->irqPin = IOGetByTag(descriptor->irqPin);
91 dev->busdev.spi.spiBus = descriptor->busdev.spi.spiBus;
92 dev->busdev.spi.csnPin = IOGetByTag(descriptor->busdev.spi.csnPin);
94 if (dev->busdev.spi.csnPin && spiBusInitHost(dev)) {
95 // Init CSN pin
96 IOInit(dev->busdev.spi.csnPin, owner, RESOURCE_SPI_CS, 0);
97 IOConfigGPIO(dev->busdev.spi.csnPin, SPI_IO_CS_CFG);
98 IOHi(dev->busdev.spi.csnPin);
99 return true;
102 return false;
104 #endif
106 void busDeviceDeInit(busDevice_t * dev)
108 busDevPreInit(dev->descriptorPtr);
109 dev->descriptorPtr = NULL;
110 dev->busType = BUSTYPE_NONE;
113 busDevice_t * busDeviceInit(busType_e bus, devHardwareType_e hw, uint8_t tag, resourceOwner_e owner)
115 UNUSED(owner);
117 for (const busDeviceDescriptor_t * descriptor = __busdev_registry_start; (descriptor) < __busdev_registry_end; descriptor++) {
118 if (hw == descriptor->devHwType && (bus == descriptor->busType || bus == BUSTYPE_ANY) && (tag == descriptor->tag)) {
119 // We have a candidate - initialize device context memory
120 busDevice_t * dev = descriptor->devicePtr;
121 if (dev) {
122 memset(dev, 0, sizeof(busDevice_t));
124 dev->descriptorPtr = descriptor;
125 dev->busType = descriptor->busType;
126 dev->flags = descriptor->flags;
127 dev->param = descriptor->param;
129 switch (descriptor->busType) {
130 default:
131 case BUSTYPE_NONE:
132 return NULL;
134 case BUSTYPE_I2C:
135 #ifdef USE_I2C
136 if (!busDevInit_I2C(dev, descriptor)) {
137 busDeviceDeInit(dev);
138 return NULL;
140 break;
141 #else
142 busDeviceDeInit(dev);
143 return NULL;
144 #endif
146 case BUSTYPE_SPI:
147 #ifdef USE_SPI
148 if (!busDevInit_SPI(dev, descriptor, owner)) {
149 busDeviceDeInit(dev);
150 return NULL;
152 break;
153 #else
154 busDeviceDeInit(dev);
155 return NULL;
156 #endif
159 return dev;
161 else {
162 return NULL;
167 return NULL;
170 busDevice_t * busDeviceOpen(busType_e bus, devHardwareType_e hw, uint8_t tag)
172 for (const busDeviceDescriptor_t * descriptor = __busdev_registry_start; (descriptor) < __busdev_registry_end; descriptor++) {
173 if (hw == descriptor->devHwType && (bus == descriptor->busType || bus == BUSTYPE_ANY) && (tag == descriptor->tag)) {
174 // Found a hardware descriptor. Now check if device context is valid
175 busDevice_t * dev = descriptor->devicePtr;
176 if (dev->busType == descriptor->busType && dev->descriptorPtr == descriptor) {
177 return dev;
182 return NULL;
185 void busSetSpeed(const busDevice_t * dev, busSpeed_e speed)
187 UNUSED(speed);
189 switch (dev->busType) {
190 default:
191 case BUSTYPE_NONE:
192 // Not available
193 break;
194 case BUSTYPE_SPI:
195 #ifdef USE_SPI
196 spiBusSetSpeed(dev, speed);
197 #endif
198 break;
199 case BUSTYPE_I2C:
200 // Do nothing for I2C
201 break;
205 uint32_t busDeviceReadScratchpad(const busDevice_t * dev)
207 uint32_t * mem = busDeviceGetScratchpadMemory(dev);
208 return (mem != NULL) ? mem[0] : 0;
211 void busDeviceWriteScratchpad(busDevice_t * dev, uint32_t value)
213 uint32_t * mem = busDeviceGetScratchpadMemory(dev);
215 if (mem != NULL) {
216 mem[0] = value;
220 void * busDeviceGetScratchpadMemory(const busDevice_t * dev)
222 if (dev->scratchpad == NULL) {
223 ((busDevice_t *)dev)->scratchpad = memAllocate(BUS_SCRATCHPAD_MEMORY_SIZE, OWNER_SYSTEM);
226 return (void *)dev->scratchpad;
229 bool busTransfer(const busDevice_t * dev, uint8_t * rxBuf, const uint8_t * txBuf, int length)
231 #ifdef USE_SPI
232 return spiBusTransfer(dev, rxBuf, txBuf, length);
233 #else
234 UNUSED(dev);
235 UNUSED(rxBuf);
236 UNUSED(txBuf);
237 UNUSED(length);
238 #endif
240 return false;
243 bool busTransferMultiple(const busDevice_t * dev, busTransferDescriptor_t * dsc, int count)
245 #ifdef USE_SPI
246 // busTransfer function is only supported on SPI bus
247 if (dev->busType == BUSTYPE_SPI) {
248 return spiBusTransferMultiple(dev, dsc, count);
250 #else
251 UNUSED(dev);
252 UNUSED(dsc);
253 UNUSED(count);
254 #endif
256 return false;
259 bool busWriteBuf(const busDevice_t * dev, uint8_t reg, const uint8_t * data, uint8_t length)
261 switch (dev->busType) {
262 case BUSTYPE_SPI:
263 #ifdef USE_SPI
264 if (dev->flags & DEVFLAGS_USE_RAW_REGISTERS) {
265 return spiBusWriteBuffer(dev, reg, data, length);
267 else {
268 return spiBusWriteBuffer(dev, reg | 0x80, data, length);
270 #else
271 return false;
272 #endif
274 case BUSTYPE_I2C:
275 #ifdef USE_I2C
276 return i2cBusWriteBuffer(dev, reg, data, length);
277 #else
278 return false;
279 #endif
281 default:
282 return false;
286 bool busWrite(const busDevice_t * dev, uint8_t reg, uint8_t data)
288 switch (dev->busType) {
289 case BUSTYPE_SPI:
290 #ifdef USE_SPI
291 if (dev->flags & DEVFLAGS_USE_RAW_REGISTERS) {
292 return spiBusWriteRegister(dev, reg, data);
294 else {
295 return spiBusWriteRegister(dev, reg & 0x7F, data);
297 #else
298 return false;
299 #endif
301 case BUSTYPE_I2C:
302 #ifdef USE_I2C
303 return i2cBusWriteRegister(dev, reg, data);
304 #else
305 return false;
306 #endif
308 default:
309 return false;
313 bool busReadBuf(const busDevice_t * dev, uint8_t reg, uint8_t * data, uint8_t length)
315 switch (dev->busType) {
316 case BUSTYPE_SPI:
317 #ifdef USE_SPI
318 if (dev->flags & DEVFLAGS_USE_RAW_REGISTERS) {
319 return spiBusReadBuffer(dev, reg, data, length);
321 else {
322 return spiBusReadBuffer(dev, reg | 0x80, data, length);
324 #else
325 return false;
326 #endif
328 case BUSTYPE_I2C:
329 #ifdef USE_I2C
330 return i2cBusReadBuffer(dev, reg, data, length);
331 #else
332 return false;
333 #endif
335 default:
336 return false;
340 bool busRead(const busDevice_t * dev, uint8_t reg, uint8_t * data)
342 switch (dev->busType) {
343 case BUSTYPE_SPI:
344 #ifdef USE_SPI
345 if (dev->flags & DEVFLAGS_USE_RAW_REGISTERS) {
346 return spiBusReadRegister(dev, reg, data);
348 else {
349 return spiBusReadRegister(dev, reg | 0x80, data);
351 #else
352 return false;
353 #endif
355 case BUSTYPE_I2C:
356 #ifdef USE_I2C
357 return i2cBusReadRegister(dev, reg, data);
358 #else
359 return false;
360 #endif
361 default:
362 return false;
366 void busSelectDevice(const busDevice_t * dev)
368 #ifdef USE_SPI
369 if (dev->busType == BUSTYPE_SPI && (dev->flags & DEVFLAGS_USE_MANUAL_DEVICE_SELECT)) {
370 spiBusSelectDevice(dev);
372 #else
373 UNUSED(dev);
374 #endif
377 void busDeselectDevice(const busDevice_t * dev)
379 #ifdef USE_SPI
380 if (dev->busType == BUSTYPE_SPI && (dev->flags & DEVFLAGS_USE_MANUAL_DEVICE_SELECT)) {
381 spiBusDeselectDevice(dev);
383 #else
384 UNUSED(dev);
385 #endif
388 bool busIsBusy(const busDevice_t * dev)
390 switch (dev->busType) {
391 case BUSTYPE_SPI:
392 #ifdef USE_SPI
393 return spiBusIsBusy(dev);
394 #else
395 UNUSED(dev);
396 return false;
397 #endif
398 case BUSTYPE_I2C:
399 // Not implemented for I2C, respond as always free
400 return false;
402 default:
403 return false;