New SPI API supporting DMA
[betaflight.git] / src / main / telemetry / ibus.c
blob9f1c8171664bf1913b3144d66cff2784f4e951f4
1 /*
2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
8 * any later version.
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
22 * FlySky iBus telemetry implementation by CraigJPerry.
23 * Unit tests and some additions by Unitware
25 * Many thanks to Dave Borthwick's iBus telemetry dongle converter for
26 * PIC 12F1572 (also distributed under GPLv3) which was referenced to
27 * clarify the protocol.
30 #include <stdbool.h>
31 #include <stdint.h>
32 #include <string.h>
34 #include "platform.h"
36 #if defined(USE_TELEMETRY_IBUS)
38 #include "common/axis.h"
40 #include "common/utils.h"
42 #include "pg/pg.h"
43 #include "pg/pg_ids.h"
45 #include "drivers/accgyro/accgyro.h"
46 #include "drivers/sensor.h"
47 #include "drivers/serial.h"
49 #include "fc/rc_controls.h"
51 #include "io/serial.h"
53 #include "sensors/acceleration.h"
54 #include "sensors/battery.h"
55 #include "sensors/barometer.h"
56 #include "sensors/gyro.h"
57 #include "sensors/sensors.h"
59 #include "scheduler/scheduler.h"
61 #include "telemetry/ibus.h"
62 #include "telemetry/ibus_shared.h"
63 #include "telemetry/telemetry.h"
66 #define IBUS_TASK_PERIOD_US (1000)
68 #define IBUS_UART_MODE (MODE_RXTX)
69 #define IBUS_BAUDRATE (115200)
70 #define IBUS_CYCLE_TIME_MS (8)
72 #define IBUS_MIN_LEN (2 + IBUS_CHECKSUM_SIZE)
73 #define IBUS_MAX_TX_LEN (6)
74 #define IBUS_MAX_RX_LEN (4)
75 #define IBUS_RX_BUF_LEN (IBUS_MAX_RX_LEN)
78 static serialPort_t *ibusSerialPort = NULL;
79 static const serialPortConfig_t *ibusSerialPortConfig;
81 /* The sent bytes will be echoed back since Tx and Rx are wired together, this counter
82 * will keep track of how many rx chars that shall be discarded */
83 static uint8_t outboundBytesToIgnoreOnRxCount = 0;
85 static bool ibusTelemetryEnabled = false;
86 static portSharing_e ibusPortSharing;
88 static uint8_t ibusReceiveBuffer[IBUS_RX_BUF_LEN] = { 0x0 };
92 static void pushOntoTail(uint8_t buffer[IBUS_MIN_LEN], size_t bufferLength, uint8_t value)
94 memmove(buffer, buffer + 1, bufferLength - 1);
95 ibusReceiveBuffer[bufferLength - 1] = value;
99 void initIbusTelemetry(void)
101 ibusSerialPortConfig = findSerialPortConfig(FUNCTION_TELEMETRY_IBUS);
102 ibusPortSharing = determinePortSharing(ibusSerialPortConfig, FUNCTION_TELEMETRY_IBUS);
103 ibusTelemetryEnabled = false;
107 void handleIbusTelemetry(void)
109 if (!ibusTelemetryEnabled) {
110 return;
113 while (serialRxBytesWaiting(ibusSerialPort) > 0) {
114 uint8_t c = serialRead(ibusSerialPort);
116 if (outboundBytesToIgnoreOnRxCount) {
117 outboundBytesToIgnoreOnRxCount--;
118 continue;
121 pushOntoTail(ibusReceiveBuffer, IBUS_RX_BUF_LEN, c);
123 if (isChecksumOkIa6b(ibusReceiveBuffer, IBUS_RX_BUF_LEN)) {
124 outboundBytesToIgnoreOnRxCount += respondToIbusRequest(ibusReceiveBuffer);
130 bool checkIbusTelemetryState(void)
132 bool newTelemetryEnabledValue = telemetryDetermineEnabledState(ibusPortSharing);
134 if (newTelemetryEnabledValue == ibusTelemetryEnabled) {
135 return false;
138 if (newTelemetryEnabledValue) {
139 rescheduleTask(TASK_TELEMETRY, IBUS_TASK_PERIOD_US);
140 configureIbusTelemetryPort();
141 } else {
142 freeIbusTelemetryPort();
145 return true;
149 void configureIbusTelemetryPort(void)
151 if (!ibusSerialPortConfig) {
152 return;
155 if (isSerialPortShared(ibusSerialPortConfig, FUNCTION_RX_SERIAL, FUNCTION_TELEMETRY_IBUS)) {
156 // serialRx will open port and handle telemetry
157 return;
160 ibusSerialPort = openSerialPort(ibusSerialPortConfig->identifier, FUNCTION_TELEMETRY_IBUS, NULL, NULL, IBUS_BAUDRATE, IBUS_UART_MODE, SERIAL_BIDIR | (telemetryConfig()->telemetry_inverted ? SERIAL_INVERTED : SERIAL_NOT_INVERTED));
162 if (!ibusSerialPort) {
163 return;
166 initSharedIbusTelemetry(ibusSerialPort);
167 ibusTelemetryEnabled = true;
168 outboundBytesToIgnoreOnRxCount = 0;
172 void freeIbusTelemetryPort(void)
174 closeSerialPort(ibusSerialPort);
175 ibusSerialPort = NULL;
176 ibusTelemetryEnabled = false;
179 #endif