Create release.yml
[betaflight.git] / src / main / rx / rx_spi.c
blobd58f0b035d4ef354245acf71e3298c6540d5411b
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/feature.h"
34 #include "drivers/io.h"
35 #include "drivers/rx/rx_spi.h"
36 #include "drivers/rx/rx_nrf24l01.h"
38 #include "config/config.h"
40 #include "pg/rx_spi.h"
42 #include "rx/rx_spi.h"
43 #include "rx/cc2500_frsky_common.h"
44 #include "rx/cc2500_redpine.h"
45 #include "rx/nrf24_cx10.h"
46 #include "rx/nrf24_syma.h"
47 #include "rx/nrf24_v202.h"
48 #include "rx/nrf24_h8_3d.h"
49 #include "rx/nrf24_inav.h"
50 #include "rx/nrf24_kn.h"
51 #include "rx/a7105_flysky.h"
52 #include "rx/cc2500_sfhss.h"
53 #include "rx/cyrf6936_spektrum.h"
54 #include "rx/expresslrs.h"
56 uint16_t rxSpiRcData[MAX_SUPPORTED_RC_CHANNEL_COUNT];
57 STATIC_UNIT_TESTED uint8_t rxSpiPayload[RX_SPI_MAX_PAYLOAD_SIZE];
58 STATIC_UNIT_TESTED uint8_t rxSpiNewPacketAvailable; // set true when a new packet is received
60 static void nullProtocolStop(void) {}
62 typedef bool (*protocolInitFnPtr)(const rxSpiConfig_t *rxSpiConfig, rxRuntimeState_t *rxRuntimeState, rxSpiExtiConfig_t *extiConfig);
63 typedef rx_spi_received_e (*protocolDataReceivedFnPtr)(uint8_t *payload);
64 typedef rx_spi_received_e (*protocolProcessFrameFnPtr)(uint8_t *payload);
65 typedef void (*protocolSetRcDataFromPayloadFnPtr)(uint16_t *rcData, const uint8_t *payload);
66 typedef void (*protocolStopFnPtr)(void);
68 static protocolInitFnPtr protocolInit;
69 static protocolDataReceivedFnPtr protocolDataReceived;
70 static protocolProcessFrameFnPtr protocolProcessFrame;
71 static protocolSetRcDataFromPayloadFnPtr protocolSetRcDataFromPayload;
72 static protocolStopFnPtr protocolStop = nullProtocolStop;
74 static rxSpiExtiConfig_t extiConfig = {
75 .ioConfig = IOCFG_IN_FLOATING,
76 .trigger = BETAFLIGHT_EXTI_TRIGGER_RISING,
79 STATIC_UNIT_TESTED float rxSpiReadRawRC(const rxRuntimeState_t *rxRuntimeState, uint8_t channel)
81 STATIC_ASSERT(NRF24L01_MAX_PAYLOAD_SIZE <= RX_SPI_MAX_PAYLOAD_SIZE, NRF24L01_MAX_PAYLOAD_SIZE_larger_than_RX_SPI_MAX_PAYLOAD_SIZE);
83 if (channel >= rxRuntimeState->channelCount) {
84 return 0;
86 if (rxSpiNewPacketAvailable) {
87 protocolSetRcDataFromPayload(rxSpiRcData, rxSpiPayload);
88 rxSpiNewPacketAvailable = false;
90 return rxSpiRcData[channel];
93 STATIC_UNIT_TESTED bool rxSpiSetProtocol(rx_spi_protocol_e protocol)
95 switch (protocol) {
96 #ifdef USE_RX_V202
97 case RX_SPI_NRF24_V202_250K:
98 case RX_SPI_NRF24_V202_1M:
99 protocolInit = v202Nrf24Init;
100 protocolDataReceived = v202Nrf24DataReceived;
101 protocolSetRcDataFromPayload = v202Nrf24SetRcDataFromPayload;
102 break;
103 #endif
104 #ifdef USE_RX_SYMA
105 case RX_SPI_NRF24_SYMA_X:
106 case RX_SPI_NRF24_SYMA_X5C:
107 protocolInit = symaNrf24Init;
108 protocolDataReceived = symaNrf24DataReceived;
109 protocolSetRcDataFromPayload = symaNrf24SetRcDataFromPayload;
110 break;
111 #endif
112 #ifdef USE_RX_CX10
113 case RX_SPI_NRF24_CX10:
114 case RX_SPI_NRF24_CX10A:
115 protocolInit = cx10Nrf24Init;
116 protocolDataReceived = cx10Nrf24DataReceived;
117 protocolSetRcDataFromPayload = cx10Nrf24SetRcDataFromPayload;
118 break;
119 #endif
120 #ifdef USE_RX_H8_3D
121 case RX_SPI_NRF24_H8_3D:
122 protocolInit = h8_3dNrf24Init;
123 protocolDataReceived = h8_3dNrf24DataReceived;
124 protocolSetRcDataFromPayload = h8_3dNrf24SetRcDataFromPayload;
125 break;
126 #endif
127 #ifdef USE_RX_KN
128 case RX_SPI_NRF24_KN:
129 protocolInit = knNrf24Init;
130 protocolDataReceived = knNrf24DataReceived;
131 protocolSetRcDataFromPayload = knNrf24SetRcDataFromPayload;
132 break;
133 #endif
134 #ifdef USE_RX_INAV
135 case RX_SPI_NRF24_INAV:
136 protocolInit = inavNrf24Init;
137 protocolDataReceived = inavNrf24DataReceived;
138 protocolSetRcDataFromPayload = inavNrf24SetRcDataFromPayload;
139 break;
140 #endif
141 #if defined(USE_RX_FRSKY_SPI)
142 #if defined(USE_RX_FRSKY_SPI_D)
143 case RX_SPI_FRSKY_D:
144 #endif
145 #if defined(USE_RX_FRSKY_SPI_X)
146 case RX_SPI_FRSKY_X:
147 case RX_SPI_FRSKY_X_LBT:
148 case RX_SPI_FRSKY_X_V2:
149 case RX_SPI_FRSKY_X_LBT_V2:
150 protocolInit = frSkySpiInit;
151 protocolDataReceived = frSkySpiDataReceived;
152 protocolSetRcDataFromPayload = frSkySpiSetRcData;
153 protocolProcessFrame = frSkySpiProcessFrame;
154 break;
155 #endif
156 #if defined(USE_RX_REDPINE_SPI)
157 case RX_SPI_REDPINE:
158 protocolInit = redpineSpiInit;
159 protocolDataReceived = redpineSpiDataReceived;
160 protocolSetRcDataFromPayload = redpineSetRcData;
161 break;
162 #endif
164 #endif // USE_RX_FRSKY_SPI
165 #ifdef USE_RX_FLYSKY
166 case RX_SPI_A7105_FLYSKY:
167 case RX_SPI_A7105_FLYSKY_2A:
168 protocolInit = flySkyInit;
169 protocolDataReceived = flySkyDataReceived;
170 protocolSetRcDataFromPayload = flySkySetRcDataFromPayload;
171 break;
172 #endif
173 #ifdef USE_RX_SFHSS_SPI
174 case RX_SPI_SFHSS:
175 protocolInit = sfhssSpiInit;
176 protocolDataReceived = sfhssSpiDataReceived;
177 protocolSetRcDataFromPayload = sfhssSpiSetRcData;
178 break;
179 #endif
180 #ifdef USE_RX_SPEKTRUM
181 case RX_SPI_CYRF6936_DSM:
182 protocolInit = spektrumSpiInit;
183 protocolDataReceived = spektrumSpiDataReceived;
184 protocolSetRcDataFromPayload = spektrumSpiSetRcDataFromPayload;
185 break;
186 #endif
187 #ifdef USE_RX_EXPRESSLRS
188 case RX_SPI_EXPRESSLRS:
189 protocolInit = expressLrsSpiInit;
190 protocolDataReceived = expressLrsDataReceived;
191 protocolSetRcDataFromPayload = expressLrsSetRcDataFromPayload;
192 protocolStop = expressLrsStop;
193 break;
194 #endif
195 default:
196 return false;
199 return true;
202 /* Called by scheduler immediately after real-time tasks
203 * Returns true if the RX has received new data.
205 static uint8_t rxSpiFrameStatus(rxRuntimeState_t *rxRuntimeState)
207 UNUSED(rxRuntimeState);
209 uint8_t status = RX_FRAME_PENDING;
211 rx_spi_received_e result = protocolDataReceived(rxSpiPayload);
213 if (result & RX_SPI_RECEIVED_DATA) {
214 rxSpiNewPacketAvailable = true;
215 status = RX_FRAME_COMPLETE;
218 if (result & RX_SPI_ROCESSING_REQUIRED) {
219 status |= RX_FRAME_PROCESSING_REQUIRED;
222 return status;
224 /* Called from updateRx in rx.c, updateRx called from taskUpdateRxCheck.
225 * If taskUpdateRxCheck returns true, then taskUpdateRxMain will shortly be called.
228 static bool rxSpiProcessFrame(const rxRuntimeState_t *rxRuntimeState)
230 UNUSED(rxRuntimeState);
232 if (protocolProcessFrame) {
233 rx_spi_received_e result = protocolProcessFrame(rxSpiPayload);
235 if (result & RX_SPI_RECEIVED_DATA) {
236 rxSpiNewPacketAvailable = true;
239 if (result & RX_SPI_ROCESSING_REQUIRED) {
240 return false;
244 return true;
248 * Set and initialize the RX protocol
250 bool rxSpiInit(const rxSpiConfig_t *rxSpiConfig, rxRuntimeState_t *rxRuntimeState)
252 bool ret = false;
254 if (!rxSpiDeviceInit(rxSpiConfig)) {
255 return false;
258 if (!rxSpiSetProtocol(rxSpiConfig->rx_spi_protocol)) {
259 return false;
262 ret = protocolInit(rxSpiConfig, rxRuntimeState, &extiConfig);
264 if (rxSpiExtiConfigured()) {
265 rxSpiExtiInit(extiConfig.ioConfig, extiConfig.trigger);
267 rxRuntimeState->rcFrameTimeUsFn = rxSpiGetLastExtiTimeUs;
270 rxSpiNewPacketAvailable = false;
271 rxRuntimeState->rxRefreshRate = 20000;
273 rxRuntimeState->rcReadRawFn = rxSpiReadRawRC;
274 rxRuntimeState->rcFrameStatusFn = rxSpiFrameStatus;
275 rxRuntimeState->rcProcessFrameFn = rxSpiProcessFrame;
277 return ret;
280 void rxSpiEnableExti(void)
282 rxSpiExtiInit(extiConfig.ioConfig, extiConfig.trigger);
285 void rxSpiStop(void)
287 protocolStop();
290 #endif