Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
cc2500_frsky_x.c
Go to the documentation of this file.
1#include "cc2500_compat.h"
2
4#include "cc2500_settings.h"
6#include "cc2500_common.h"
9#include "cc2500_frsky_x.h"
10#include "cc2500_smartport.h"
11
12#define UNUSED(x) (void)(x)
13
14// betaflight/src/main/rx/cc2500_frsky_x.c @ e78f976
15/*
16 * This file is part of Cleanflight and Betaflight.
17 *
18 * Cleanflight and Betaflight are free software. You can redistribute
19 * this software and/or modify this software under the terms of the
20 * GNU General Public License as published by the Free Software
21 * Foundation, either version 3 of the License, or (at your option)
22 * any later version.
23 *
24 * Cleanflight and Betaflight are distributed in the hope that they
25 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
26 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
27 * See the GNU General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * along with this software.
31 *
32 * If not, see <http://www.gnu.org/licenses/>.
33 */
34
35#include <string.h>
36
37//#include "platform.h"
38
39#ifdef USE_RX_FRSKY_SPI_X
40
41//#include "build/build_config.h"
42//#include "build/debug.h"
43//
44//#include "common/maths.h"
45//#include "common/utils.h"
46//
47//#include "config/feature.h"
48//
49//#include "drivers/adc.h"
50//#include "drivers/rx/rx_cc2500.h"
51//#include "drivers/io.h"
52//#include "drivers/io_def.h"
53//#include "drivers/io_types.h"
54//#include "drivers/resource.h"
55//#include "drivers/system.h"
56//#include "drivers/time.h"
57//
58//#include "fc/config.h"
59//
60//#include "pg/rx.h"
61//#include "pg/rx_spi.h"
62//#include "pg/rx_spi_cc2500.h"
63//
64//#include "rx/rx_spi_common.h"
65//#include "rx/cc2500_common.h"
66//#include "rx/cc2500_frsky_common.h"
67//#include "rx/cc2500_frsky_shared.h"
68//
69//#include "sensors/battery.h"
70//
71//#include "telemetry/smartport.h"
72//
73//#include "cc2500_frsky_x.h"
74
75const uint16_t crcTable[] = {
76 0x0000,0x1189,0x2312,0x329b,0x4624,0x57ad,0x6536,0x74bf,
77 0x8c48,0x9dc1,0xaf5a,0xbed3,0xca6c,0xdbe5,0xe97e,0xf8f7,
78 0x1081,0x0108,0x3393,0x221a,0x56a5,0x472c,0x75b7,0x643e,
79 0x9cc9,0x8d40,0xbfdb,0xae52,0xdaed,0xcb64,0xf9ff,0xe876,
80 0x2102,0x308b,0x0210,0x1399,0x6726,0x76af,0x4434,0x55bd,
81 0xad4a,0xbcc3,0x8e58,0x9fd1,0xeb6e,0xfae7,0xc87c,0xd9f5,
82 0x3183,0x200a,0x1291,0x0318,0x77a7,0x662e,0x54b5,0x453c,
83 0xbdcb,0xac42,0x9ed9,0x8f50,0xfbef,0xea66,0xd8fd,0xc974,
84 0x4204,0x538d,0x6116,0x709f,0x0420,0x15a9,0x2732,0x36bb,
85 0xce4c,0xdfc5,0xed5e,0xfcd7,0x8868,0x99e1,0xab7a,0xbaf3,
86 0x5285,0x430c,0x7197,0x601e,0x14a1,0x0528,0x37b3,0x263a,
87 0xdecd,0xcf44,0xfddf,0xec56,0x98e9,0x8960,0xbbfb,0xaa72,
88 0x6306,0x728f,0x4014,0x519d,0x2522,0x34ab,0x0630,0x17b9,
89 0xef4e,0xfec7,0xcc5c,0xddd5,0xa96a,0xb8e3,0x8a78,0x9bf1,
90 0x7387,0x620e,0x5095,0x411c,0x35a3,0x242a,0x16b1,0x0738,
91 0xffcf,0xee46,0xdcdd,0xcd54,0xb9eb,0xa862,0x9af9,0x8b70,
92 0x8408,0x9581,0xa71a,0xb693,0xc22c,0xd3a5,0xe13e,0xf0b7,
93 0x0840,0x19c9,0x2b52,0x3adb,0x4e64,0x5fed,0x6d76,0x7cff,
94 0x9489,0x8500,0xb79b,0xa612,0xd2ad,0xc324,0xf1bf,0xe036,
95 0x18c1,0x0948,0x3bd3,0x2a5a,0x5ee5,0x4f6c,0x7df7,0x6c7e,
96 0xa50a,0xb483,0x8618,0x9791,0xe32e,0xf2a7,0xc03c,0xd1b5,
97 0x2942,0x38cb,0x0a50,0x1bd9,0x6f66,0x7eef,0x4c74,0x5dfd,
98 0xb58b,0xa402,0x9699,0x8710,0xf3af,0xe226,0xd0bd,0xc134,
99 0x39c3,0x284a,0x1ad1,0x0b58,0x7fe7,0x6e6e,0x5cf5,0x4d7c,
100 0xc60c,0xd785,0xe51e,0xf497,0x8028,0x91a1,0xa33a,0xb2b3,
101 0x4a44,0x5bcd,0x6956,0x78df,0x0c60,0x1de9,0x2f72,0x3efb,
102 0xd68d,0xc704,0xf59f,0xe416,0x90a9,0x8120,0xb3bb,0xa232,
103 0x5ac5,0x4b4c,0x79d7,0x685e,0x1ce1,0x0d68,0x3ff3,0x2e7a,
104 0xe70e,0xf687,0xc41c,0xd595,0xa12a,0xb0a3,0x8238,0x93b1,
105 0x6b46,0x7acf,0x4854,0x59dd,0x2d62,0x3ceb,0x0e70,0x1ff9,
106 0xf78f,0xe606,0xd49d,0xc514,0xb1ab,0xa022,0x92b9,0x8330,
107 0x7bc7,0x6a4e,0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0x0f78
108};
109
110#define TELEMETRY_OUT_BUFFER_SIZE 64
111
112#define TELEMETRY_SEQUENCE_LENGTH 4
113
114#define A1_CONST_X 50
115
117 unsigned int packetSequenceId: 2;
118 unsigned int unused: 1;
119 unsigned int initRequest: 1;
120 unsigned int ackSequenceId: 2;
121 unsigned int retransmissionRequested: 1;
122 unsigned int initResponse: 1;
124
129
130#define SEQUENCE_MARKER_REMOTE_PART 0xf0
131
132#define TELEMETRY_DATA_SIZE 5
133
138
143
144#define TELEMETRY_FRAME_SIZE sizeof(telemetryData_t)
145
153
154#if defined(USE_RX_FRSKY_SPI_TELEMETRY)
156#endif
157
159
161
162#if defined(USE_RX_FRSKY_SPI_TELEMETRY)
163static uint8_t frame[20];
164
165#if defined(USE_TELEMETRY_SMARTPORT)
167
169
170static bool telemetryEnabled = false;
171
174#endif
175#endif // USE_RX_FRSKY_SPI_TELEMETRY
176
179
180static uint16_t calculateCrc(const uint8_t *data, uint8_t len) {
181 uint16_t crc = 0;
182 for (unsigned i = 0; i < len; i++) {
183 crc = (crc << 8) ^ (crcTable[((uint8_t)(crc >> 8) ^ *data++) & 0xFF]);
184 }
185 return crc;
186}
187
188#if defined(USE_RX_FRSKY_SPI_TELEMETRY)
189#if defined(USE_TELEMETRY_SMARTPORT)
191{
192 static uint8_t telemetryOutReader = 0;
193
194 uint8_t index;
195 for (index = 0; index < TELEMETRY_DATA_SIZE; index++) { // max 5 bytes in a frame
196 if (telemetryOutReader == telemetryOutWriter){ // no new data
197 break;
198 }
201 }
202
203 return index;
204}
205#endif
206
208{
209 static uint8_t localPacketId;
210
211 static bool evenRun = false;
212
213 frame[0] = 0x0E;//length
216 frame[3] = packet[3];
217
218 if (evenRun) {
219 frame[4] = (uint8_t)cc2500getRssiDbm() | 0x80;
220 } else {
222 switch (rxCc2500SpiConfig()->a1Source) {
225 break;
227 a1Value = (uint8_t)((adcGetChannel(ADC_EXTERNAL1) & 0xfe0) >> 5);
228 break;
230 a1Value = A1_CONST_X & 0x7f;
231 break;
232 }
233 frame[4] = a1Value;
234 }
235 evenRun = !evenRun;
236
239 if (inFrameMarker->data.initRequest) { // check syncronization at startup ok if not no sport telemetry
240 outFrameMarker-> raw = 0;
242 outFrameMarker->data.initResponse = 1;
243
244 localPacketId = 0;
245 } else {
246 if (inFrameMarker->data.retransmissionRequested) {
247 uint8_t retransmissionFrameId = inFrameMarker->data.ackSequenceId;
249 outFrameMarker->data.packetSequenceId = retransmissionFrameId;
250
252 } else {
253 uint8_t localAckId = inFrameMarker->data.ackSequenceId;
256 outFrameMarker->data.packetSequenceId = localPacketId;
257
260
262 }
263 }
264 }
265
266 uint16_t lcrc = calculateCrc(&frame[3], 10);
267 frame[13]=lcrc>>8;
268 frame[14]=lcrc;
269}
270
271static bool frSkyXCheckQueueEmpty(void)
272{
273 return true;
274}
275
276#if defined(USE_TELEMETRY_SMARTPORT)
288
300#endif
301#endif // USE_RX_FRSKY_SPI_TELEMETRY
302
303
305{
306 uint16_t c[8];
307 // ignore failsafe packet
308 if (packet[7] != 0) {
309 return;
310 }
311 c[0] = (uint16_t)((packet[10] << 8) & 0xF00) | packet[9];
312 c[1] = (uint16_t)((packet[11] << 4) & 0xFF0) | (packet[10] >> 4);
313 c[2] = (uint16_t)((packet[13] << 8) & 0xF00) | packet[12];
314 c[3] = (uint16_t)((packet[14] << 4) & 0xFF0) | (packet[13] >> 4);
315 c[4] = (uint16_t)((packet[16] << 8) & 0xF00) | packet[15];
316 c[5] = (uint16_t)((packet[17] << 4) & 0xFF0) | (packet[16] >> 4);
317 c[6] = (uint16_t)((packet[19] << 8) & 0xF00) | packet[18];
318 c[7] = (uint16_t)((packet[20] << 4) & 0xFF0) | (packet[19] >> 4);
319
320 for (unsigned i = 0; i < 8; i++) {
321 const bool channelIsShifted = c[i] & 0x800;
322 const uint16_t channelValue = c[i] & 0x7FF;
323 rcData[channelIsShifted ? i + 8 : i] = ((channelValue - 64) * 2 + 860 * 3) / 3;
324 }
325}
326
328{
330 if ((lcrc >> 8) == packet[packetLength - 4] && (lcrc & 0x00FF) == packet[packetLength - 3] &&
331 (packet[0] == packetLength - 3) &&
332 (packet[1] == rxCc2500SpiConfig()->bindTxId[0]) &&
333 (packet[2] == rxCc2500SpiConfig()->bindTxId[1]) &&
334 (rxCc2500SpiConfig()->rxNum == 0 || packet[6] == 0 || packet[6] == rxCc2500SpiConfig()->rxNum)) {
335 return true;
336 }
337 return false;
338}
339
341{
342 static unsigned receiveTelemetryRetryCount = 0;
343 static bool skipChannels = true;
344
345 static uint8_t remoteAckId = 0;
346
347 static timeUs_t packetTimerUs;
348
349 static bool frameReceived;
351 static uint8_t channelsToSkip = 1;
352 static uint32_t packetErrors = 0;
353
354#if defined(USE_RX_FRSKY_SPI_TELEMETRY)
355 static bool telemetryReceived = false;
356#endif
357
359
360 switch (*protocolState) {
361 case STATE_STARTING:
362 listLength = 47;
363 initialiseData(false);
365 nextChannel(1);
367 break;
368 case STATE_UPDATE:
371 frameReceived = false; // again set for receive
372 receiveDelayUs = 5300;
373 if (rxSpiCheckBindRequested(false)) {
374 packetTimerUs = 0;
375 timeoutUs = 50;
376 missingPackets = 0;
378
379 break;
380 }
381
383 // here FS code could be
384 case STATE_DATA:
385 if (cc2500getGdo() && (frameReceived == false)){
387 if (ccLen >= packetLength) {
389 if (isValidPacket(packet)) {
390 missingPackets = 0;
391 timeoutUs = 1;
392 receiveDelayUs = 0;
393 rxSpiLedOn();
394 if (skipChannels) {
395 channelsToSkip = packet[5] << 2;
396 if (packet[4] >= listLength) {
397 if (packet[4] < (64 + listLength)) {
398 channelsToSkip += 1;
399 } else if (packet[4] < (128 + listLength)) {
400 channelsToSkip += 2;
401 } else if (packet[4] < (192 + listLength)) {
402 channelsToSkip += 3;
403 }
404 }
405 telemetryReceived = true; // now telemetry can be sent
406 skipChannels = false;
407 }
409
411
415
420 if (!telemetryRxBuffer[remoteToAckId].needsProcessing) {
423
425
426 break;
427 }
428
430 }
431 }
432
435
438 while (telemetryRxBuffer[remoteToAckId].needsProcessing && remoteToAckId != remoteAckId) {
441 }
444 }
445
447#if defined(USE_RX_FRSKY_SPI_TELEMETRY) && defined(USE_TELEMETRY_SMARTPORT)
450#endif
452 for (unsigned i = 0; i < TELEMETRY_SEQUENCE_LENGTH; i++) {
454 }
455
457 }
458
460 frameReceived = true; // no need to process frame again.
461 }
462 if (!frameReceived) {
463 packetErrors++;
466 }
467 }
468 }
469 if (telemetryReceived) {
470 if (cmpTimeUs(micros(), packetTimerUs) > receiveDelayUs) { // if received or not received in this time sent telemetry data
473 }
474 }
477
479 nextChannel(1);
482 }
483 if (frameReceived) {
485 }
486
487 break;
488#ifdef USE_RX_FRSKY_SPI_TELEMETRY
489 case STATE_TELEMETRY:
490 if (cmpTimeUs(micros(), packetTimerUs) >= receiveDelayUs + telemetryDelayUs) { // if received or not received in this time sent telemetry data
495#if defined(USE_RX_CC2500_SPI_PA_LNA)
497#endif
499 cc2500WriteFifo(frame, frame[0] + 1);
500
501#if defined(USE_TELEMETRY_SMARTPORT)
502 if (telemetryEnabled) {
504 }
505#endif
507 }
508
509 break;
510#endif // USE_RX_FRSKY_SPI_TELEMETRY
511 case STATE_RESUME:
512 if (cmpTimeUs(micros(), packetTimerUs) > receiveDelayUs + 3700) {
514 receiveDelayUs = 5300;
515 frameReceived = false; // again set for receive
518#ifdef USE_RX_CC2500_SPI_PA_LNA
520#if defined(USE_RX_CC2500_SPI_DIVERSITY)
521 if (missingPackets >= 2) {
523 }
524#endif
525#endif // USE_RX_CC2500_SPI_PA_LNA
527 timeoutUs = 50;
528 skipChannels = true;
529 telemetryReceived = false;
531 break;
532 }
536 }
537 break;
538 }
539
540 return ret;
541}
542
543#if defined(USE_RX_FRSKY_SPI_TELEMETRY) && defined(USE_TELEMETRY_SMARTPORT)
545{
546 static timeMs_t pollingTimeMs = 0;
547
548 UNUSED(packet);
549
550 bool clearToSend = false;
551 timeMs_t now = millis();
552 smartPortPayload_t *payload = NULL;
553 if ((now - pollingTimeMs) > 24) {
555
556 clearToSend = true;
557 } else {
558 while (telemetryRxBuffer[remoteToProcessId].needsProcessing && !payload) {
563
564 if (!telemetryRxBuffer[remoteToProcessId].needsProcessing) {
565 break;
566 }
567 }
568
569 while (remoteToProcessIndex < telemetryRxBuffer[remoteToProcessId].data.dataLength && !payload) {
572 }
573 }
574 }
575
577
579}
580#endif
581
583{
584 switch(spiProtocol) {
585 case RX_SPI_FRSKY_X:
586 packetLength = 32;
587 telemetryDelayUs = 400;
588 break;
590 packetLength = 35;
591 telemetryDelayUs = 1400;
592 break;
593 default:
594 break;
595 }
596#if defined(USE_TELEMETRY_SMARTPORT)
599 }
600#endif
601}
602
603#endif
void cc2500ReadFifo(uint8_t *dpbuffer, uint8_t len)
Definition cc2500.c:174
uint8_t cc2500ReadReg(uint8_t reg)
Definition cc2500.c:199
void cc2500WriteFifo(uint8_t *dpbuffer, uint8_t len)
Definition cc2500.c:180
void cc2500Strobe(uint8_t address)
Definition cc2500.c:204
void cc2500SetPower(uint8_t power)
Definition cc2500.c:211
#define CC2500_SIDLE
Definition cc2500.h:155
#define CC2500_SFRX
Definition cc2500.h:161
#define CC2500_SRX
Definition cc2500.h:148
#define CC2500_READ_BURST
Definition cc2500.h:137
@ CC2500_3B_RXBYTES
Definition cc2500.h:125
bool cc2500getGdo(void)
void cc2500setRssiDbm(uint8_t value)
uint16_t cc2500getRssiDbm(void)
#define adcGetChannel(channel)
#define FALLTHROUGH
#define ADC_EXTERNAL1
#define featureIsEnabled(mask)
uint32_t timeMs_t
#define delayMicroseconds(us)
int32_t timeDelta_t
#define DEBUG_SET(...)
#define getLegacyBatteryVoltage()
static timeDelta_t cmpTimeUs(timeUs_t a, timeUs_t b)
uint32_t timeUs_t
@ FEATURE_TELEMETRY
#define millis()
#define micros()
timeDelta_t timeoutUs
uint32_t missingPackets
uint8_t listLength
void nextChannel(uint8_t skip)
void initialiseData(bool inBindState)
static uint8_t protocolState
static rx_spi_protocol_e spiProtocol
#define MAX_MISSING_PKT
@ STATE_DATA
@ STATE_TELEMETRY
@ STATE_INIT
@ STATE_STARTING
@ STATE_RESUME
@ STATE_UPDATE
#define DEBUG_DATA_MISSING_PACKETS
#define SYNC_DELAY_MAX
#define DEBUG_DATA_BAD_FRAME
void frSkyXInit(const rx_spi_protocol_e spiProtocol)
const uint16_t crcTable[]
telemetryData_t data
#define TELEMETRY_SEQUENCE_LENGTH
struct telemetryBuffer_s telemetryBuffer_t
#define SEQUENCE_MARKER_REMOTE_PART
static uint8_t frame[20]
#define TELEMETRY_FRAME_SIZE
static void frSkyXTelemetrySendByte(uint8_t c)
static uint16_t telemetryDelayUs
static bool telemetryEnabled
static telemetrySequenceMarker_t responseToSend
telemetrySequenceMarkerData_t data
static telemetryData_t telemetryTxBuffer[TELEMETRY_SEQUENCE_LENGTH]
static telemetryBuffer_t telemetryRxBuffer[TELEMETRY_SEQUENCE_LENGTH]
telemetryData_t data
struct telemetrySequenceMarkerData_s telemetrySequenceMarkerData_t
static uint16_t calculateCrc(const uint8_t *data, uint8_t len)
struct telemetryPayload_s telemetryPayload_t
static uint8_t remoteToProcessIndex
#define A1_CONST_X
#define UNUSED(x)
static uint8_t packetLength
telemetrySequenceMarker_t sequence
struct telemetryData_s telemetryData_t
rx_spi_received_e frSkyXHandlePacket(uint8_t *const packet, uint8_t *const protocolState)
static void buildTelemetryFrame(uint8_t *packet)
static uint8_t telemetryOutBuffer[TELEMETRY_OUT_BUFFER_SIZE]
static uint8_t appendSmartPortData(uint8_t *buf)
rx_spi_received_e frSkyXProcessFrame(uint8_t *const packet)
#define TELEMETRY_DATA_SIZE
bool isValidPacket(const uint8_t *packet)
static uint8_t telemetryOutWriter
static void frSkyXTelemetryWriteFrame(const smartPortPayload_t *payload)
#define TELEMETRY_OUT_BUFFER_SIZE
void frSkyXSetRcData(uint16_t *rcData, const uint8_t *packet)
static bool frSkyXCheckQueueEmpty(void)
static uint8_t remoteToProcessId
uint8_t data[TELEMETRY_DATA_SIZE]
union telemetrySequenceMarker_s telemetrySequenceMarker_t
void setRssiDirect(uint16_t newRssi, rssiSource_e source)
Definition cc2500_rx.c:700
int16_t rcData[MAX_SUPPORTED_RC_CHANNEL_COUNT]
Definition cc2500_rx.c:118
@ RSSI_SOURCE_RX_PROTOCOL
Definition cc2500_rx.h:158
rx_spi_protocol_e
@ RX_SPI_FRSKY_X
@ RX_SPI_FRSKY_X_LBT
rx_spi_received_e
@ RX_SPI_RECEIVED_NONE
@ RX_SPI_ROCESSING_REQUIRED
@ RX_SPI_RECEIVED_DATA
void rxSpiLedOn(void)
void rxSpiLedToggle(void)
bool rxSpiCheckBindRequested(bool reset)
const rxCc2500SpiConfig_t * rxCc2500SpiConfig(void)
@ FRSKY_SPI_A1_SOURCE_CONST
@ FRSKY_SPI_A1_SOURCE_VBAT
@ FRSKY_SPI_A1_SOURCE_EXTADC
bool initSmartPortTelemetryExternal(smartPortWriteFrameFn *smartPortWriteFrameExternal)
smartPortPayload_t * smartPortDataReceive(uint16_t c, bool *clearToSend, smartPortCheckQueueEmptyFn *checkQueueEmpty, bool useChecksum)
void processSmartPortTelemetry(smartPortPayload_t *payload, volatile bool *clearToSend, const timeUs_t *requestTimeout)
@ FSSP_DLE_XOR
@ FSSP_SENSOR_ID1
@ FSSP_DLE
@ FSSP_START_STOP
struct smartPortPayload_s smartPortPayload_t
uint16_t foo
Definition main_demo5.c:58
unsigned short uint16_t
Typedef defining 16 bit unsigned short type.
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.