Preserve resolution of RC input
[betaflight.git] / src / main / rx / rx_spi.c
blobc72def494098d78c2cc74b6d499421aa4b168268
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"
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 typedef bool (*protocolInitFnPtr)(const rxSpiConfig_t *rxSpiConfig, rxRuntimeState_t *rxRuntimeState, rxSpiExtiConfig_t *extiConfig);
61 typedef rx_spi_received_e (*protocolDataReceivedFnPtr)(uint8_t *payload);
62 typedef rx_spi_received_e (*protocolProcessFrameFnPtr)(uint8_t *payload);
63 typedef void (*protocolSetRcDataFromPayloadFnPtr)(uint16_t *rcData, const uint8_t *payload);
65 static protocolInitFnPtr protocolInit;
66 static protocolDataReceivedFnPtr protocolDataReceived;
67 static protocolProcessFrameFnPtr protocolProcessFrame;
68 static protocolSetRcDataFromPayloadFnPtr protocolSetRcDataFromPayload;
70 STATIC_UNIT_TESTED float rxSpiReadRawRC(const rxRuntimeState_t *rxRuntimeState, uint8_t channel)
72 STATIC_ASSERT(NRF24L01_MAX_PAYLOAD_SIZE <= RX_SPI_MAX_PAYLOAD_SIZE, NRF24L01_MAX_PAYLOAD_SIZE_larger_than_RX_SPI_MAX_PAYLOAD_SIZE);
74 if (channel >= rxRuntimeState->channelCount) {
75 return 0;
77 if (rxSpiNewPacketAvailable) {
78 protocolSetRcDataFromPayload(rxSpiRcData, rxSpiPayload);
79 rxSpiNewPacketAvailable = false;
81 return rxSpiRcData[channel];
84 STATIC_UNIT_TESTED bool rxSpiSetProtocol(rx_spi_protocol_e protocol)
86 switch (protocol) {
87 #ifdef USE_RX_V202
88 case RX_SPI_NRF24_V202_250K:
89 case RX_SPI_NRF24_V202_1M:
90 protocolInit = v202Nrf24Init;
91 protocolDataReceived = v202Nrf24DataReceived;
92 protocolSetRcDataFromPayload = v202Nrf24SetRcDataFromPayload;
93 break;
94 #endif
95 #ifdef USE_RX_SYMA
96 case RX_SPI_NRF24_SYMA_X:
97 case RX_SPI_NRF24_SYMA_X5C:
98 protocolInit = symaNrf24Init;
99 protocolDataReceived = symaNrf24DataReceived;
100 protocolSetRcDataFromPayload = symaNrf24SetRcDataFromPayload;
101 break;
102 #endif
103 #ifdef USE_RX_CX10
104 case RX_SPI_NRF24_CX10:
105 case RX_SPI_NRF24_CX10A:
106 protocolInit = cx10Nrf24Init;
107 protocolDataReceived = cx10Nrf24DataReceived;
108 protocolSetRcDataFromPayload = cx10Nrf24SetRcDataFromPayload;
109 break;
110 #endif
111 #ifdef USE_RX_H8_3D
112 case RX_SPI_NRF24_H8_3D:
113 protocolInit = h8_3dNrf24Init;
114 protocolDataReceived = h8_3dNrf24DataReceived;
115 protocolSetRcDataFromPayload = h8_3dNrf24SetRcDataFromPayload;
116 break;
117 #endif
118 #ifdef USE_RX_KN
119 case RX_SPI_NRF24_KN:
120 protocolInit = knNrf24Init;
121 protocolDataReceived = knNrf24DataReceived;
122 protocolSetRcDataFromPayload = knNrf24SetRcDataFromPayload;
123 break;
124 #endif
125 #ifdef USE_RX_INAV
126 case RX_SPI_NRF24_INAV:
127 protocolInit = inavNrf24Init;
128 protocolDataReceived = inavNrf24DataReceived;
129 protocolSetRcDataFromPayload = inavNrf24SetRcDataFromPayload;
130 break;
131 #endif
132 #if defined(USE_RX_FRSKY_SPI)
133 #if defined(USE_RX_FRSKY_SPI_D)
134 case RX_SPI_FRSKY_D:
135 #endif
136 #if defined(USE_RX_FRSKY_SPI_X)
137 case RX_SPI_FRSKY_X:
138 case RX_SPI_FRSKY_X_LBT:
139 case RX_SPI_FRSKY_X_V2:
140 case RX_SPI_FRSKY_X_LBT_V2:
141 protocolInit = frSkySpiInit;
142 protocolDataReceived = frSkySpiDataReceived;
143 protocolSetRcDataFromPayload = frSkySpiSetRcData;
144 protocolProcessFrame = frSkySpiProcessFrame;
145 break;
146 #endif
147 #if defined(USE_RX_REDPINE_SPI)
148 case RX_SPI_REDPINE:
149 protocolInit = redpineSpiInit;
150 protocolDataReceived = redpineSpiDataReceived;
151 protocolSetRcDataFromPayload = redpineSetRcData;
152 break;
153 #endif
155 #endif // USE_RX_FRSKY_SPI
156 #ifdef USE_RX_FLYSKY
157 case RX_SPI_A7105_FLYSKY:
158 case RX_SPI_A7105_FLYSKY_2A:
159 protocolInit = flySkyInit;
160 protocolDataReceived = flySkyDataReceived;
161 protocolSetRcDataFromPayload = flySkySetRcDataFromPayload;
162 break;
163 #endif
164 #ifdef USE_RX_SFHSS_SPI
165 case RX_SPI_SFHSS:
166 protocolInit = sfhssSpiInit;
167 protocolDataReceived = sfhssSpiDataReceived;
168 protocolSetRcDataFromPayload = sfhssSpiSetRcData;
169 break;
170 #endif
171 #ifdef USE_RX_SPEKTRUM
172 case RX_SPI_CYRF6936_DSM:
173 protocolInit = spektrumSpiInit;
174 protocolDataReceived = spektrumSpiDataReceived;
175 protocolSetRcDataFromPayload = spektrumSpiSetRcDataFromPayload;
176 break;
177 #endif
178 default:
179 return false;
182 return true;
186 * Returns true if the RX has received new data.
187 * Called from updateRx in rx.c, updateRx called from taskUpdateRxCheck.
188 * If taskUpdateRxCheck returns true, then taskUpdateRxMain will shortly be called.
190 static uint8_t rxSpiFrameStatus(rxRuntimeState_t *rxRuntimeState)
192 UNUSED(rxRuntimeState);
194 uint8_t status = RX_FRAME_PENDING;
196 rx_spi_received_e result = protocolDataReceived(rxSpiPayload);
198 if (result & RX_SPI_RECEIVED_DATA) {
199 rxSpiNewPacketAvailable = true;
200 status = RX_FRAME_COMPLETE;
203 if (result & RX_SPI_ROCESSING_REQUIRED) {
204 status |= RX_FRAME_PROCESSING_REQUIRED;
207 return status;
210 static bool rxSpiProcessFrame(const rxRuntimeState_t *rxRuntimeState)
212 UNUSED(rxRuntimeState);
214 if (protocolProcessFrame) {
215 rx_spi_received_e result = protocolProcessFrame(rxSpiPayload);
217 if (result & RX_SPI_RECEIVED_DATA) {
218 rxSpiNewPacketAvailable = true;
221 if (result & RX_SPI_ROCESSING_REQUIRED) {
222 return false;
226 return true;
230 * Set and initialize the RX protocol
232 bool rxSpiInit(const rxSpiConfig_t *rxSpiConfig, rxRuntimeState_t *rxRuntimeState)
234 bool ret = false;
236 if (!rxSpiDeviceInit(rxSpiConfig)) {
237 return false;
240 if (!rxSpiSetProtocol(rxSpiConfig->rx_spi_protocol)) {
241 return false;
244 rxSpiExtiConfig_t extiConfig = {
245 .ioConfig = IOCFG_IN_FLOATING,
246 .trigger = BETAFLIGHT_EXTI_TRIGGER_RISING,
249 ret = protocolInit(rxSpiConfig, rxRuntimeState, &extiConfig);
251 if (rxSpiExtiConfigured()) {
252 rxSpiExtiInit(extiConfig.ioConfig, extiConfig.trigger);
254 rxRuntimeState->rcFrameTimeUsFn = rxSpiGetLastExtiTimeUs;
257 rxSpiNewPacketAvailable = false;
258 rxRuntimeState->rxRefreshRate = 20000;
260 rxRuntimeState->rcReadRawFn = rxSpiReadRawRC;
261 rxRuntimeState->rcFrameStatusFn = rxSpiFrameStatus;
262 rxRuntimeState->rcProcessFrameFn = rxSpiProcessFrame;
264 return ret;
266 #endif