ELRS SPI Fix eeprom write and reboot for msp over telemetry
[betaflight.git] / src / main / rx / rx_spi.c
blob5080d428a1dc829cb2e6da7ff7e89b333a7b3c4f
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/>.
21 #include <stdbool.h>
22 #include <stdint.h>
24 #include "platform.h"
26 #ifdef USE_RX_SPI
28 #include "build/build_config.h"
30 #include "common/utils.h"
32 #include "config/config.h"
33 #include "config/feature.h"
35 #include "drivers/io.h"
36 #include "drivers/rx/rx_spi.h"
37 #include "drivers/rx/rx_nrf24l01.h"
39 #include "fc/dispatch.h"
41 #include "pg/rx_spi.h"
43 #include "rx/rx_spi.h"
44 #include "rx/cc2500_frsky_common.h"
45 #include "rx/cc2500_redpine.h"
46 #include "rx/nrf24_cx10.h"
47 #include "rx/nrf24_syma.h"
48 #include "rx/nrf24_v202.h"
49 #include "rx/nrf24_h8_3d.h"
50 #include "rx/nrf24_inav.h"
51 #include "rx/nrf24_kn.h"
52 #include "rx/a7105_flysky.h"
53 #include "rx/cc2500_sfhss.h"
54 #include "rx/cyrf6936_spektrum.h"
55 #include "rx/expresslrs.h"
57 uint16_t rxSpiRcData[MAX_SUPPORTED_RC_CHANNEL_COUNT];
58 STATIC_UNIT_TESTED uint8_t rxSpiPayload[RX_SPI_MAX_PAYLOAD_SIZE];
59 STATIC_UNIT_TESTED uint8_t rxSpiNewPacketAvailable; // set true when a new packet is received
61 static void nullProtocolStop(void) {}
63 typedef bool (*protocolInitFnPtr)(const rxSpiConfig_t *rxSpiConfig, rxRuntimeState_t *rxRuntimeState, rxSpiExtiConfig_t *extiConfig);
64 typedef rx_spi_received_e (*protocolDataReceivedFnPtr)(uint8_t *payload);
65 typedef rx_spi_received_e (*protocolProcessFrameFnPtr)(uint8_t *payload);
66 typedef void (*protocolSetRcDataFromPayloadFnPtr)(uint16_t *rcData, const uint8_t *payload);
67 typedef void (*protocolStopFnPtr)(void);
69 static protocolInitFnPtr protocolInit;
70 static protocolDataReceivedFnPtr protocolDataReceived;
71 static protocolProcessFrameFnPtr protocolProcessFrame;
72 static protocolSetRcDataFromPayloadFnPtr protocolSetRcDataFromPayload;
73 static protocolStopFnPtr protocolStop = nullProtocolStop;
75 static rxSpiExtiConfig_t extiConfig = {
76 .ioConfig = IOCFG_IN_FLOATING,
77 .trigger = BETAFLIGHT_EXTI_TRIGGER_RISING,
80 STATIC_UNIT_TESTED float rxSpiReadRawRC(const rxRuntimeState_t *rxRuntimeState, uint8_t channel)
82 STATIC_ASSERT(NRF24L01_MAX_PAYLOAD_SIZE <= RX_SPI_MAX_PAYLOAD_SIZE, NRF24L01_MAX_PAYLOAD_SIZE_larger_than_RX_SPI_MAX_PAYLOAD_SIZE);
84 if (channel >= rxRuntimeState->channelCount) {
85 return 0;
87 if (rxSpiNewPacketAvailable) {
88 protocolSetRcDataFromPayload(rxSpiRcData, rxSpiPayload);
89 rxSpiNewPacketAvailable = false;
91 return rxSpiRcData[channel];
94 STATIC_UNIT_TESTED bool rxSpiSetProtocol(rx_spi_protocol_e protocol)
96 switch (protocol) {
97 #ifdef USE_RX_V202
98 case RX_SPI_NRF24_V202_250K:
99 case RX_SPI_NRF24_V202_1M:
100 protocolInit = v202Nrf24Init;
101 protocolDataReceived = v202Nrf24DataReceived;
102 protocolSetRcDataFromPayload = v202Nrf24SetRcDataFromPayload;
103 break;
104 #endif
105 #ifdef USE_RX_SYMA
106 case RX_SPI_NRF24_SYMA_X:
107 case RX_SPI_NRF24_SYMA_X5C:
108 protocolInit = symaNrf24Init;
109 protocolDataReceived = symaNrf24DataReceived;
110 protocolSetRcDataFromPayload = symaNrf24SetRcDataFromPayload;
111 break;
112 #endif
113 #ifdef USE_RX_CX10
114 case RX_SPI_NRF24_CX10:
115 case RX_SPI_NRF24_CX10A:
116 protocolInit = cx10Nrf24Init;
117 protocolDataReceived = cx10Nrf24DataReceived;
118 protocolSetRcDataFromPayload = cx10Nrf24SetRcDataFromPayload;
119 break;
120 #endif
121 #ifdef USE_RX_H8_3D
122 case RX_SPI_NRF24_H8_3D:
123 protocolInit = h8_3dNrf24Init;
124 protocolDataReceived = h8_3dNrf24DataReceived;
125 protocolSetRcDataFromPayload = h8_3dNrf24SetRcDataFromPayload;
126 break;
127 #endif
128 #ifdef USE_RX_KN
129 case RX_SPI_NRF24_KN:
130 protocolInit = knNrf24Init;
131 protocolDataReceived = knNrf24DataReceived;
132 protocolSetRcDataFromPayload = knNrf24SetRcDataFromPayload;
133 break;
134 #endif
135 #ifdef USE_RX_INAV
136 case RX_SPI_NRF24_INAV:
137 protocolInit = inavNrf24Init;
138 protocolDataReceived = inavNrf24DataReceived;
139 protocolSetRcDataFromPayload = inavNrf24SetRcDataFromPayload;
140 break;
141 #endif
142 #if defined(USE_RX_FRSKY_SPI)
143 #if defined(USE_RX_FRSKY_SPI_D)
144 case RX_SPI_FRSKY_D:
145 #endif
146 #if defined(USE_RX_FRSKY_SPI_X)
147 case RX_SPI_FRSKY_X:
148 case RX_SPI_FRSKY_X_LBT:
149 case RX_SPI_FRSKY_X_V2:
150 case RX_SPI_FRSKY_X_LBT_V2:
151 protocolInit = frSkySpiInit;
152 protocolDataReceived = frSkySpiDataReceived;
153 protocolSetRcDataFromPayload = frSkySpiSetRcData;
154 protocolProcessFrame = frSkySpiProcessFrame;
155 break;
156 #endif
157 #if defined(USE_RX_REDPINE_SPI)
158 case RX_SPI_REDPINE:
159 protocolInit = redpineSpiInit;
160 protocolDataReceived = redpineSpiDataReceived;
161 protocolSetRcDataFromPayload = redpineSetRcData;
162 break;
163 #endif
165 #endif // USE_RX_FRSKY_SPI
166 #ifdef USE_RX_FLYSKY
167 case RX_SPI_A7105_FLYSKY:
168 case RX_SPI_A7105_FLYSKY_2A:
169 protocolInit = flySkyInit;
170 protocolDataReceived = flySkyDataReceived;
171 protocolSetRcDataFromPayload = flySkySetRcDataFromPayload;
172 break;
173 #endif
174 #ifdef USE_RX_SFHSS_SPI
175 case RX_SPI_SFHSS:
176 protocolInit = sfhssSpiInit;
177 protocolDataReceived = sfhssSpiDataReceived;
178 protocolSetRcDataFromPayload = sfhssSpiSetRcData;
179 break;
180 #endif
181 #ifdef USE_RX_SPEKTRUM
182 case RX_SPI_CYRF6936_DSM:
183 protocolInit = spektrumSpiInit;
184 protocolDataReceived = spektrumSpiDataReceived;
185 protocolSetRcDataFromPayload = spektrumSpiSetRcDataFromPayload;
186 break;
187 #endif
188 #ifdef USE_RX_EXPRESSLRS
189 case RX_SPI_EXPRESSLRS:
190 protocolInit = expressLrsSpiInit;
191 protocolDataReceived = expressLrsDataReceived;
192 protocolSetRcDataFromPayload = expressLrsSetRcDataFromPayload;
193 protocolStop = expressLrsStop;
194 break;
195 #endif
196 default:
197 return false;
200 return true;
203 /* Called by scheduler immediately after real-time tasks
204 * Returns true if the RX has received new data.
206 static uint8_t rxSpiFrameStatus(rxRuntimeState_t *rxRuntimeState)
208 UNUSED(rxRuntimeState);
210 uint8_t status = RX_FRAME_PENDING;
212 rx_spi_received_e result = protocolDataReceived(rxSpiPayload);
214 if (result & RX_SPI_RECEIVED_DATA) {
215 rxSpiNewPacketAvailable = true;
216 status = RX_FRAME_COMPLETE;
219 if (result & RX_SPI_ROCESSING_REQUIRED) {
220 status |= RX_FRAME_PROCESSING_REQUIRED;
223 return status;
225 /* Called from updateRx in rx.c, updateRx called from taskUpdateRxCheck.
226 * If taskUpdateRxCheck returns true, then taskUpdateRxMain will shortly be called.
229 static bool rxSpiProcessFrame(const rxRuntimeState_t *rxRuntimeState)
231 UNUSED(rxRuntimeState);
233 if (protocolProcessFrame) {
234 rx_spi_received_e result = protocolProcessFrame(rxSpiPayload);
236 if (result & RX_SPI_RECEIVED_DATA) {
237 rxSpiNewPacketAvailable = true;
240 if (result & RX_SPI_ROCESSING_REQUIRED) {
241 return false;
245 return true;
249 * Set and initialize the RX protocol
251 bool rxSpiInit(const rxSpiConfig_t *rxSpiConfig, rxRuntimeState_t *rxRuntimeState)
253 bool ret = false;
255 if (!rxSpiDeviceInit(rxSpiConfig)) {
256 return false;
259 if (!rxSpiSetProtocol(rxSpiConfig->rx_spi_protocol)) {
260 return false;
263 ret = protocolInit(rxSpiConfig, rxRuntimeState, &extiConfig);
265 if (rxSpiExtiConfigured()) {
266 rxSpiExtiInit(extiConfig.ioConfig, extiConfig.trigger);
268 rxRuntimeState->rcFrameTimeUsFn = rxSpiGetLastExtiTimeUs;
271 rxSpiNewPacketAvailable = false;
272 rxRuntimeState->rxRefreshRate = 20000;
274 rxRuntimeState->rcReadRawFn = rxSpiReadRawRC;
275 rxRuntimeState->rcFrameStatusFn = rxSpiFrameStatus;
276 rxRuntimeState->rcProcessFrameFn = rxSpiProcessFrame;
278 dispatchEnable();
280 return ret;
283 void rxSpiEnableExti(void)
285 rxSpiExtiInit(extiConfig.ioConfig, extiConfig.trigger);
288 void rxSpiStop(void)
290 protocolStop();
293 #endif