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)
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/>.
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
) {
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
)
98 case RX_SPI_NRF24_V202_250K
:
99 case RX_SPI_NRF24_V202_1M
:
100 protocolInit
= v202Nrf24Init
;
101 protocolDataReceived
= v202Nrf24DataReceived
;
102 protocolSetRcDataFromPayload
= v202Nrf24SetRcDataFromPayload
;
106 case RX_SPI_NRF24_SYMA_X
:
107 case RX_SPI_NRF24_SYMA_X5C
:
108 protocolInit
= symaNrf24Init
;
109 protocolDataReceived
= symaNrf24DataReceived
;
110 protocolSetRcDataFromPayload
= symaNrf24SetRcDataFromPayload
;
114 case RX_SPI_NRF24_CX10
:
115 case RX_SPI_NRF24_CX10A
:
116 protocolInit
= cx10Nrf24Init
;
117 protocolDataReceived
= cx10Nrf24DataReceived
;
118 protocolSetRcDataFromPayload
= cx10Nrf24SetRcDataFromPayload
;
122 case RX_SPI_NRF24_H8_3D
:
123 protocolInit
= h8_3dNrf24Init
;
124 protocolDataReceived
= h8_3dNrf24DataReceived
;
125 protocolSetRcDataFromPayload
= h8_3dNrf24SetRcDataFromPayload
;
129 case RX_SPI_NRF24_KN
:
130 protocolInit
= knNrf24Init
;
131 protocolDataReceived
= knNrf24DataReceived
;
132 protocolSetRcDataFromPayload
= knNrf24SetRcDataFromPayload
;
136 case RX_SPI_NRF24_INAV
:
137 protocolInit
= inavNrf24Init
;
138 protocolDataReceived
= inavNrf24DataReceived
;
139 protocolSetRcDataFromPayload
= inavNrf24SetRcDataFromPayload
;
142 #if defined(USE_RX_FRSKY_SPI)
143 #if defined(USE_RX_FRSKY_SPI_D)
146 #if defined(USE_RX_FRSKY_SPI_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
;
157 #if defined(USE_RX_REDPINE_SPI)
159 protocolInit
= redpineSpiInit
;
160 protocolDataReceived
= redpineSpiDataReceived
;
161 protocolSetRcDataFromPayload
= redpineSetRcData
;
165 #endif // USE_RX_FRSKY_SPI
167 case RX_SPI_A7105_FLYSKY
:
168 case RX_SPI_A7105_FLYSKY_2A
:
169 protocolInit
= flySkyInit
;
170 protocolDataReceived
= flySkyDataReceived
;
171 protocolSetRcDataFromPayload
= flySkySetRcDataFromPayload
;
174 #ifdef USE_RX_SFHSS_SPI
176 protocolInit
= sfhssSpiInit
;
177 protocolDataReceived
= sfhssSpiDataReceived
;
178 protocolSetRcDataFromPayload
= sfhssSpiSetRcData
;
181 #ifdef USE_RX_SPEKTRUM
182 case RX_SPI_CYRF6936_DSM
:
183 protocolInit
= spektrumSpiInit
;
184 protocolDataReceived
= spektrumSpiDataReceived
;
185 protocolSetRcDataFromPayload
= spektrumSpiSetRcDataFromPayload
;
188 #ifdef USE_RX_EXPRESSLRS
189 case RX_SPI_EXPRESSLRS
:
190 protocolInit
= expressLrsSpiInit
;
191 protocolDataReceived
= expressLrsDataReceived
;
192 protocolSetRcDataFromPayload
= expressLrsSetRcDataFromPayload
;
193 protocolStop
= expressLrsStop
;
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
;
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
) {
249 * Set and initialize the RX protocol
251 bool rxSpiInit(const rxSpiConfig_t
*rxSpiConfig
, rxRuntimeState_t
*rxRuntimeState
)
255 if (!rxSpiDeviceInit(rxSpiConfig
)) {
259 if (!rxSpiSetProtocol(rxSpiConfig
->rx_spi_protocol
)) {
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
;
283 void rxSpiEnableExti(void)
285 rxSpiExtiInit(extiConfig
.ioConfig
, extiConfig
.trigger
);