Naze32 clone with Frysky receiver
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

rx.c 20KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685
  1. /*
  2. * FrSky RX 2-way protocol
  3. */
  4. #ifdef DEBUG
  5. //#define DEBUG_TEST_PART_VERSION
  6. //#define DEBUG_EEPROM_DATA_READ
  7. //#define DEBUG_MISSING_PACKETS
  8. //#define DEBUG_PACKET_DUMP
  9. //#define DEBUG_PACKET_DUMP_TUNE
  10. //#define DEBUG_PACKET_DUMP_BIND
  11. //#define DEBUG_PACKET_DUMP_LIST
  12. //#define DEBUG_PPM_VALUES
  13. //#define DEBUG_ERROR_MESSAGES
  14. #define DEBUG_PACKET_DOT
  15. #endif
  16. #include <stdint.h>
  17. #include <avr/io.h>
  18. #include <avr/interrupt.h>
  19. #include <avr/eeprom.h>
  20. #include <avr/wdt.h>
  21. #include "cc2500.h"
  22. #include "cppm.h"
  23. #include "spi.h"
  24. #include "timer.h"
  25. #include "rx.h"
  26. #include "main.h"
  27. #define CHANNELS 8
  28. #define PPM_MIN 1000
  29. #define PPM_MAX 2000
  30. #define HOP_DATA_LENGTH 60
  31. #define EEPROM_BASE_ADDRESS 100
  32. #define MISSING_PACKET_DELAY 9
  33. #define SEEK_CHANNEL_SKIP 13
  34. #define MAX_MISSING_PACKET 20
  35. #define FAILSAFE_MISSING_PACKET 170
  36. //#define FAILSAFE_INVALID_VALUE 850
  37. #define FAILSAFE_INVALID_VALUE_MINIMUM 900
  38. #define FAILSAFE_INVALID_VALUE_MAXIMUM 2100
  39. //#define RSSI_OVER_PPM 7
  40. #define RSSI_OFFSET 71
  41. #define RSSI_MIN -103
  42. #define RSSI_MAX -96
  43. #define PPM_SCALE 2 / 3
  44. #define FRSKY_PACKET_LENGTH 0x11
  45. #define FREQ_ORIGINAL
  46. //#define FREQUENCY_SCAN
  47. // Original 0x5C 0x76 0x27
  48. #define FREQ_SCAN_START_2 0x5C
  49. #define FREQ_SCAN_START_1 0x76
  50. #define FREQ_SCAN_START_0 0x00
  51. uint8_t ccData[27];
  52. uint8_t ccLen;
  53. uint8_t packet = 0;
  54. uint8_t channr = 0;
  55. uint8_t missingPackets = 0;
  56. uint8_t hopData[HOP_DATA_LENGTH];
  57. uint8_t listLength;
  58. uint8_t txid[2];
  59. uint8_t counter = 0;
  60. uint8_t failed = 0;
  61. uint8_t frequencyOffsetHack = 0;
  62. uint16_t c[CHANNELS];
  63. #ifdef FREQUENCY_SCAN
  64. uint8_t freq2 = FREQ_SCAN_START_2;
  65. uint8_t freq1 = FREQ_SCAN_START_1;
  66. uint8_t freq0 = FREQ_SCAN_START_0;
  67. #endif
  68. static uint16_t ppmBuffer[CHANNELS];
  69. #ifdef RSSI_OVER_PPM
  70. static int rssi;
  71. static long map(long x, long in_min, long in_max, long out_min, long out_max);
  72. static long constrain(long x, long min, long max);
  73. #endif
  74. static void initialize(uint8_t bind);
  75. static void binding(void);
  76. static void tuning(void);
  77. static void performBind(void);
  78. static void nextChannel(uint8_t skip);
  79. static void readBindingData(void);
  80. static void writeBindingData(void);
  81. void rxInit(void) {
  82. GDO_dir;
  83. debugWrite("RX: initializing\n");
  84. initialize(1); // binding
  85. debugWrite("RX: binding\n");
  86. binding();
  87. debugWrite("RX: receiving\n");
  88. initialize(0); // data
  89. cc2500WriteReg(CC2500_0A_CHANNR, hopData[channr]);// 0A - hop
  90. cc2500WriteReg(CC2500_23_FSCAL3, 0x89); // 23 - 89
  91. cc2500Strobe(CC2500_SRX);
  92. }
  93. static void initialize(uint8_t bind) {
  94. cc2500ResetChip();
  95. cc2500WriteReg(CC2500_02_IOCFG0, 0x01); // RX complete interrupt(GDO0)
  96. cc2500WriteReg(CC2500_17_MCSM1, 0x0F);
  97. cc2500WriteReg(CC2500_18_MCSM0, 0x18);
  98. cc2500WriteReg(CC2500_06_PKTLEN, 0x19); // Leave room for appended status bytes
  99. cc2500WriteReg(CC2500_08_PKTCTRL0, 0x05);
  100. cc2500WriteReg(CC2500_3E_PATABLE, 0xFF);
  101. cc2500WriteReg(CC2500_0B_FSCTRL1, 0x08);
  102. cc2500WriteReg(CC2500_0C_FSCTRL0, 0x00);
  103. #ifdef FREQ_ORIGINAL
  104. /*
  105. * According to the internet, these are the default FrSky
  106. * FREQ values (0x5C7627) which should equal 2.404GHz.
  107. * The datasheet mentions Fcarrier = Fxosc * FREQ / 2^16
  108. * Therefore, FrSky seems to be using 26MHz too.
  109. */
  110. cc2500WriteReg(CC2500_0D_FREQ2, 0x5C);
  111. cc2500WriteReg(CC2500_0E_FREQ1, 0x76);
  112. cc2500WriteReg(CC2500_0F_FREQ0, 0x27);
  113. #else
  114. cc2500WriteReg(CC2500_0D_FREQ2, FREQ_SCAN_START_2);
  115. cc2500WriteReg(CC2500_0E_FREQ1, FREQ_SCAN_START_1);
  116. cc2500WriteReg(CC2500_0F_FREQ0, FREQ_SCAN_START_0);
  117. #endif
  118. cc2500WriteReg(CC2500_10_MDMCFG4, 0xAA);
  119. cc2500WriteReg(CC2500_11_MDMCFG3, 0x39);
  120. cc2500WriteReg(CC2500_12_MDMCFG2, 0x11);
  121. cc2500WriteReg(CC2500_13_MDMCFG1, 0x23);
  122. cc2500WriteReg(CC2500_14_MDMCFG0, 0x7A);
  123. cc2500WriteReg(CC2500_15_DEVIATN, 0x42);
  124. cc2500WriteReg(CC2500_19_FOCCFG, 0x16);
  125. cc2500WriteReg(CC2500_1A_BSCFG, 0x6C);
  126. cc2500WriteReg(CC2500_1B_AGCCTRL2, 0x03);
  127. cc2500WriteReg(CC2500_1C_AGCCTRL1, 0x40);
  128. cc2500WriteReg(CC2500_1D_AGCCTRL0, 0x91);
  129. cc2500WriteReg(CC2500_21_FREND1, 0x56);
  130. cc2500WriteReg(CC2500_22_FREND0, 0x10);
  131. cc2500WriteReg(CC2500_23_FSCAL3, 0xA9);
  132. cc2500WriteReg(CC2500_24_FSCAL2, 0x05);
  133. cc2500WriteReg(CC2500_25_FSCAL1, 0x00);
  134. cc2500WriteReg(CC2500_26_FSCAL0, 0x11);
  135. //cc2500WriteReg(CC2500_29_FSTEST, 0x59);
  136. //cc2500WriteReg(CC2500_2C_TEST2, 0x88);
  137. //cc2500WriteReg(CC2500_2D_TEST1, 0x31);
  138. //cc2500WriteReg(CC2500_2E_TEST0, 0x0B);
  139. //cc2500WriteReg(CC2500_03_FIFOTHR, 0x0F); // 0x07?
  140. cc2500WriteReg(CC2500_09_ADDR, bind ? 0x03 : txid[0]);
  141. //cc2500WriteReg(CC2500_09_ADDR, bind ? 0x00 : txid[0]);
  142. debugWrite("CC2500: Entering IDLE mode...\n");
  143. cc2500Strobe(CC2500_SIDLE); // Go to idle...
  144. #ifdef DEBUG_TEST_PART_VERSION
  145. uint8_t part = cc2500ReadReg(CC2500_30_PARTNUM);
  146. uint8_t version = cc2500ReadReg(CC2500_31_VERSION);
  147. debugWrite("CC2500: Part Number: 0x");
  148. debugHex(part);
  149. debugWrite("\nCC2500: Version: 0x");
  150. debugHex(version);
  151. debugWrite("\n");
  152. if ((part != 0x80) || (version != 0x03)) {
  153. debugWrite("INVALID CC2500 STATUS! IT MAY BE DEAD!\n");
  154. }
  155. #endif
  156. // hack: Append status, filter by address, auto-flush on bad crc, PQT=0
  157. cc2500WriteReg(CC2500_07_PKTCTRL1, 0x0D);
  158. //cc2500WriteReg(CC2500_0C_FSCTRL0, 0); // Frequency offset
  159. cc2500WriteReg(CC2500_0C_FSCTRL0, bind ? 0x00 : frequencyOffsetHack);
  160. cc2500WriteReg(CC2500_0A_CHANNR, 0x00);
  161. }
  162. static void binding(void) {
  163. readBindingData();
  164. if ((txid[0] != 0xff) || (txid[1] != 0xff)) {
  165. // valid binding data found
  166. debugWrite("RX: found data in EEPROM!\n");
  167. return;
  168. }
  169. debugWrite("RX: no stored data, tuning...\n");
  170. // No valid txid, forcing bind
  171. tuning();
  172. //frequencyOffsetHack = 0xC8; // for test
  173. cc2500WriteReg(CC2500_0C_FSCTRL0, frequencyOffsetHack);
  174. eeprom_write_byte(EEPROM_BASE_ADDRESS + 101, frequencyOffsetHack);
  175. debugWrite("RX: tuned, binding...\n");
  176. performBind();
  177. }
  178. static void tuning() {
  179. cc2500Strobe(CC2500_SRX); // enter in rx mode
  180. uint16_t frequencyOffsetTimer = 0;
  181. while (1) {
  182. frequencyOffsetTimer++;
  183. if (frequencyOffsetTimer > 3000) {
  184. frequencyOffsetTimer = 0;
  185. cc2500WriteReg(CC2500_0C_FSCTRL0, frequencyOffsetHack);
  186. if (frequencyOffsetHack <= 250) {
  187. frequencyOffsetHack += 5;
  188. } else {
  189. frequencyOffsetHack = 0;
  190. #ifdef FREQUENCY_SCAN
  191. if (freq0 < 255) {
  192. freq0++;
  193. } else {
  194. freq0 = 0;
  195. if (freq1 < 255) {
  196. freq1++;
  197. } else {
  198. freq1 = 0;
  199. if (freq2 < 255) {
  200. freq2++;
  201. } else {
  202. freq2 = 0;
  203. }
  204. }
  205. }
  206. debugWrite("0x");
  207. debugHex(freq2);
  208. debugHex(freq1);
  209. debugHex(freq0);
  210. debugWrite("\n");
  211. cc2500WriteReg(CC2500_0D_FREQ2, freq2);
  212. cc2500WriteReg(CC2500_0E_FREQ1, freq1);
  213. cc2500WriteReg(CC2500_0F_FREQ0, freq0);
  214. #endif
  215. }
  216. //cc2500Strobe(CC2500_SRX); // enter in rx mode
  217. }
  218. if (GDO_1) {
  219. ccLen = cc2500ReadReg(CC2500_3B_RXBYTES) & 0x7F;
  220. if (ccLen) {
  221. cc2500ReadFifo(ccData, ccLen);
  222. #ifdef DEBUG_PACKET_DUMP_TUNE
  223. debugWrite("RX: Tune Packet Dump (");
  224. serialWriteUnsigned8(0, ccLen);
  225. debugWrite("):\n");
  226. for (uint8_t i = 0; i < ccLen; i++) {
  227. debugWrite("0x")
  228. serialWriteHex(0, ccData[i]);
  229. if (i < (ccLen - 1)) {
  230. debugWrite(" ");
  231. } else {
  232. debugWrite("\n");
  233. }
  234. }
  235. #endif
  236. if ((ccData[ccLen - 1] & 0x80)
  237. && (ccData[2] == 0x01)
  238. && (ccData[5] == 0x00)) {
  239. break;
  240. }
  241. }
  242. }
  243. wdt_reset();
  244. #ifdef DEBUG_UART_MENU
  245. uartMenu();
  246. #endif
  247. }
  248. }
  249. static void performBind(void) {
  250. cc2500Strobe(CC2500_SRX); // enter in rx mode
  251. while (1) {
  252. if (GDO_1) {
  253. ccLen = cc2500ReadReg(CC2500_3B_RXBYTES) & 0x7F;
  254. if (ccLen) {
  255. cc2500ReadFifo(ccData, ccLen);
  256. #ifdef DEBUG_PACKET_DUMP_BIND
  257. debugWrite("RX: Bind Packet Dump (");
  258. serialWriteUnsigned8(0, ccLen);
  259. debugWrite("):\n");
  260. for (uint8_t i = 0; i < ccLen; i++) {
  261. debugWrite("0x")
  262. serialWriteHex(0, ccData[i]);
  263. if (i < (ccLen - 1)) {
  264. debugWrite(" ");
  265. } else {
  266. debugWrite("\n");
  267. }
  268. }
  269. #endif
  270. if ((ccData[ccLen - 1] & 0x80)
  271. && (ccData[2] == 0x01)
  272. && (ccData[5] == 0x00)) {
  273. txid[0] = ccData[3];
  274. txid[1] = ccData[4];
  275. for (uint8_t n = 0; n < 5; n++) {
  276. hopData[ccData[5] + n] = ccData[6 + n];
  277. }
  278. break;
  279. }
  280. }
  281. }
  282. wdt_reset();
  283. #ifdef DEBUG_UART_MENU
  284. uartMenu();
  285. #endif
  286. }
  287. debugWrite("RX: got hop data, reading list...\n");
  288. listLength = 0;
  289. uint8_t eol = 0;
  290. for (uint8_t bindIdx = 0x05; bindIdx <= 120; bindIdx += 5) {
  291. while (1) {
  292. if (GDO_1) {
  293. ccLen = cc2500ReadReg(CC2500_3B_RXBYTES) & 0x7F;
  294. if (ccLen) {
  295. cc2500ReadFifo(ccData, ccLen);
  296. #ifdef DEBUG_PACKET_DUMP_LIST
  297. debugWrite("RX: List Packet Dump (");
  298. serialWriteUnsigned8(0, ccLen);
  299. debugWrite("):\n");
  300. for (uint8_t i = 0; i < ccLen; i++) {
  301. debugWrite("0x")
  302. serialWriteHex(0, ccData[i]);
  303. if (i < (ccLen - 1)) {
  304. debugWrite(" ");
  305. } else {
  306. debugWrite("\n");
  307. }
  308. }
  309. #endif
  310. if ((ccData[ccLen - 1] & 0x80)
  311. && (ccData[2] == 0x01)
  312. && (ccData[3] == txid[0])
  313. && (ccData[4] == txid[1])
  314. && (ccData[5] == bindIdx)) {
  315. for (uint8_t n = 0; n < 5; n++) {
  316. //if (ccData[6 + n] == ccData[ccLen - 3]) {
  317. if (ccData[6 + n] <= 3) {
  318. eol = 1;
  319. listLength = ccData[5] + n;
  320. break;
  321. }
  322. hopData[ccData[5] + n] = ccData[6 + n];
  323. }
  324. break;
  325. }
  326. }
  327. }
  328. wdt_reset();
  329. #ifdef DEBUG_UART_MENU
  330. uartMenu();
  331. #endif
  332. }
  333. if (eol) {
  334. break; // End of list found, stop!
  335. }
  336. }
  337. debugWrite("RX: binding finished!\n");
  338. writeBindingData();
  339. cc2500Strobe(CC2500_SIDLE); // Back to idle
  340. }
  341. static void nextChannel(uint8_t skip) {
  342. channr += skip;
  343. if (channr >= listLength) {
  344. channr -= listLength;
  345. }
  346. cc2500WriteReg(CC2500_0A_CHANNR, hopData[channr]);
  347. cc2500WriteReg(CC2500_23_FSCAL3, 0x89);
  348. }
  349. static void readBindingData() {
  350. #ifdef DEBUG_EEPROM_DATA_READ
  351. debugWrite("RX: EEPROM TXID: ");
  352. #endif
  353. for (uint8_t i = 0; i < 2; i++) {
  354. txid[i] = eeprom_read_byte(EEPROM_BASE_ADDRESS + i);
  355. #ifdef DEBUG_EEPROM_DATA_READ
  356. debugWrite("0x")
  357. serialWriteHex(0, txid[i]);
  358. debugWrite(" ");
  359. #endif
  360. }
  361. #ifdef DEBUG_EEPROM_DATA_READ
  362. debugWrite("\n");
  363. #endif
  364. #ifdef DEBUG_EEPROM_DATA_READ
  365. debugWrite("RX: EEPROM Hop Data (");
  366. serialWriteUnsigned8(0, HOP_DATA_LENGTH);
  367. debugWrite(")\n");
  368. #endif
  369. for (uint8_t i = 0; i < HOP_DATA_LENGTH; i++) {
  370. hopData[i] = eeprom_read_byte(EEPROM_BASE_ADDRESS + 10 + i);
  371. #ifdef DEBUG_EEPROM_DATA_READ
  372. debugWrite("0x")
  373. serialWriteHex(0, hopData[i]);
  374. debugWrite(" ");
  375. #endif
  376. }
  377. #ifdef DEBUG_EEPROM_DATA_READ
  378. debugWrite("\n");
  379. #endif
  380. listLength = eeprom_read_byte(EEPROM_BASE_ADDRESS + 100);
  381. frequencyOffsetHack = eeprom_read_byte(EEPROM_BASE_ADDRESS + 101);
  382. #ifdef DEBUG_EEPROM_DATA_READ
  383. debugWrite("RX: EEPROM List Length: ");
  384. serialWriteUnsigned8(0, listLength);
  385. debugWrite("\nRX: EEPROM Frequency Offset Hack: ");
  386. serialWriteUnsigned8(0, frequencyOffsetHack);
  387. debugWrite("\n");
  388. #endif
  389. }
  390. static void writeBindingData() {
  391. for (uint8_t i = 0; i < 2; i++) {
  392. eeprom_write_byte(EEPROM_BASE_ADDRESS + i, txid[i]);
  393. }
  394. for (uint8_t i = 0; i < HOP_DATA_LENGTH; i++) {
  395. eeprom_write_byte(EEPROM_BASE_ADDRESS + 10 + i, hopData[i]);
  396. }
  397. eeprom_write_byte(EEPROM_BASE_ADDRESS + 100, listLength);
  398. }
  399. void rxReceivePacket() {
  400. time_t time = timerGet();
  401. #ifdef DEBUG_MISSING_PACKETS
  402. static uint8_t packetMissingNotification = 0;
  403. #endif
  404. if (missingPackets > FAILSAFE_MISSING_PACKET) {
  405. failed = 1;
  406. missingPackets = 0;
  407. }
  408. while (1) {
  409. if ((timerGet() - time) > MISSING_PACKET_DELAY) {
  410. missingPackets++;
  411. cc2500Strobe(CC2500_SIDLE);
  412. if (missingPackets > MAX_MISSING_PACKET) {
  413. nextChannel(SEEK_CHANNEL_SKIP);
  414. counter++;
  415. if (counter > (MAX_MISSING_PACKET << 1)) {
  416. #ifdef DEBUG_MISSING_PACKETS
  417. if (packetMissingNotification < 1) {
  418. debugWrite("RX: missing packet notification!\n");
  419. packetMissingNotification = 1;
  420. }
  421. #endif
  422. }
  423. if (counter == (MAX_MISSING_PACKET << 2)) {
  424. #ifdef DEBUG_MISSING_PACKETS
  425. if (packetMissingNotification < 2) {
  426. debugWrite("RX: missing packet notification 2!\n");
  427. packetMissingNotification = 2;
  428. }
  429. #endif
  430. counter = 0;
  431. }
  432. } else {
  433. nextChannel(1);
  434. }
  435. break;
  436. }
  437. if (GDO_1) {
  438. ccLen = cc2500ReadReg(CC2500_3B_RXBYTES) & 0x7F;
  439. if (ccLen > 20) {
  440. #ifdef DEBUG_ERROR_MESSAGES
  441. debugWrite("RX: packet too long: ");
  442. serialWriteUnsigned8(0, ccLen);
  443. debugWrite("\n");
  444. #endif
  445. ccLen = 20;
  446. }
  447. if (ccLen) {
  448. cc2500ReadFifo((uint8_t *)ccData, ccLen);
  449. if (ccData[ccLen - 1] & CC2500_LQI_CRC_OK_BM) { // Only if correct CRC
  450. #ifdef DEBUG_PACKET_DUMP
  451. debugWrite("RX: Packet Dump (");
  452. serialWriteUnsigned8(0, ccLen);
  453. debugWrite("):\n");
  454. for (uint8_t i = 0; i < ccLen; i++) {
  455. debugWrite("0x")
  456. serialWriteHex(0, ccData[i]);
  457. if (i < (ccLen - 1)) {
  458. debugWrite(" ");
  459. } else {
  460. debugWrite("\n");
  461. }
  462. }
  463. #endif
  464. missingPackets = 0;
  465. if ((ccData[0] == FRSKY_PACKET_LENGTH) // Correct length
  466. && (ccData[1] == txid[0]) // Correct txid
  467. && (ccData[2] == txid[1])) {
  468. #ifdef DEBUG_MISSING_PACKETS
  469. packetMissingNotification = 0;
  470. #endif
  471. packet = 1;
  472. #ifdef RSSI_OVER_PPM
  473. int rssi_dec = cc2500ReadReg(CC2500_34_RSSI);
  474. if (rssi_dec < 128) {
  475. rssi = ((rssi_dec / 2) - RSSI_OFFSET) & 0x7f;
  476. } else {
  477. rssi = (((rssi_dec - 256) / 2)) - RSSI_OFFSET;
  478. }
  479. rssi = constrain(rssi, RSSI_MIN, RSSI_MAX);
  480. #endif
  481. cc2500Strobe(CC2500_SIDLE);
  482. nextChannel(1);
  483. failed = 0;
  484. break;
  485. } else {
  486. #ifdef DEBUG_ERROR_MESSAGES
  487. if (ccData[0] != FRSKY_PACKET_LENGTH) {
  488. debugWrite("RX: invalid packet length: ");
  489. serialWriteUnsigned8(0, ccData[0]);
  490. debugWrite(" != ");
  491. serialWriteUnsigned8(0, FRSKY_PACKET_LENGTH);
  492. debugWrite("\n");
  493. }
  494. if (ccData[1] != txid[0]) {
  495. debugWrite("RX: invalid txid[0]: ");
  496. serialWriteUnsigned8(0, ccData[1]);
  497. debugWrite(" != ");
  498. serialWriteUnsigned8(0, txid[0]);
  499. debugWrite("\n");
  500. }
  501. if (ccData[2] == txid[1]) {
  502. debugWrite("RX: invalid txid[1]: ");
  503. serialWriteUnsigned8(0, ccData[2]);
  504. debugWrite(" != ");
  505. serialWriteUnsigned8(0, txid[1]);
  506. debugWrite("\n");
  507. }
  508. #endif
  509. }
  510. } else {
  511. #ifdef DEBUG_ERROR_MESSAGES
  512. debugWrite("RX: invalid CRC!\n");
  513. #endif
  514. }
  515. }
  516. }
  517. wdt_reset();
  518. #ifdef DEBUG_UART_MENU
  519. uartMenu();
  520. #endif
  521. }
  522. if (packet != 0) {
  523. packet = 0;
  524. c[0] = (uint16_t)(ccData[10] & 0x0F) << 8 | ccData[6];
  525. c[1] = (uint16_t)(ccData[10] & 0xF0) << 4 | ccData[7];
  526. c[2] = (uint16_t)(ccData[11] & 0x0F) << 8 | ccData[8];
  527. c[3] = (uint16_t)(ccData[11] & 0xF0) << 4 | ccData[9];
  528. c[4] = (uint16_t)(ccData[16] & 0x0F) << 8 | ccData[12];
  529. c[5] = (uint16_t)(ccData[16] & 0xF0) << 4 | ccData[13];
  530. c[6] = (uint16_t)(ccData[17] & 0x0F) << 8 | ccData[14];
  531. c[7] = (uint16_t)(ccData[17] & 0xF0) << 4 | ccData[15];
  532. for (int i = 0; i < CHANNELS; i++) {
  533. ppmBuffer[i] = (uint16_t)((uint32_t)(c[i]) * PPM_SCALE);
  534. if (ppmBuffer[i] < FAILSAFE_INVALID_VALUE_MINIMUM) {
  535. #ifdef FAILSAFE_INVALID_VALUE
  536. ppmBuffer[i] = FAILSAFE_INVALID_VALUE;
  537. #else
  538. ppmBuffer[i] = FAILSAFE_INVALID_VALUE_MINIMUM;
  539. #endif
  540. }
  541. if (ppmBuffer[i] > FAILSAFE_INVALID_VALUE_MAXIMUM) {
  542. #ifdef FAILSAFE_INVALID_VALUE
  543. ppmBuffer[i] = FAILSAFE_INVALID_VALUE;
  544. #else
  545. ppmBuffer[i] = FAILSAFE_INVALID_VALUE_MAXIMUM;
  546. #endif
  547. }
  548. }
  549. #ifdef RSSI_OVER_PPM
  550. ppmBuffer[RSSI_OVER_PPM] = map(rssi, RSSI_MIN, RSSI_MAX, PPM_MIN, PPM_MAX);
  551. #endif
  552. #ifdef DEBUG_PPM_VALUES
  553. debugWrite("RX: got packet @ ");
  554. serialWriteUnsigned64(0, timerGet() / 1000);
  555. debugWrite("s:\n");
  556. for (uint8_t i = 0; i < CHANNELS; i++) {
  557. serialWriteUnsigned8(0, i);
  558. debugWrite(": ");
  559. serialWriteUnsigned16(0, ppmBuffer[i]);
  560. debugWrite(" - ");
  561. serialWriteUnsigned16(0, c[i]);
  562. debugWrite("\n");
  563. }
  564. #endif
  565. #ifdef DEBUG_PACKET_DOT
  566. serialWrite(0, '.');
  567. #endif
  568. cppmCopy(ppmBuffer);
  569. }
  570. cc2500Strobe(CC2500_SRX);
  571. }
  572. #ifdef RSSI_OVER_PPM
  573. static long map(long x, long in_min, long in_max, long out_min, long out_max) {
  574. return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
  575. }
  576. static long constrain(long x, long min, long max) {
  577. if (x < min) {
  578. x = min;
  579. }
  580. if (x > max) {
  581. x = max;
  582. }
  583. return x;
  584. }
  585. #endif