Naze32 clone with Frysky receiver
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

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