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 27KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914
  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_EEPROM_DATA_WRITE
  8. //#define DEBUG_MISSING_PACKETS
  9. //#define DEBUG_PACKET_DUMP
  10. //#define DEBUG_PACKET_DUMP_TUNE
  11. //#define DEBUG_PACKET_DUMP_BIND
  12. //#define DEBUG_PACKET_DUMP_LIST
  13. //#define DEBUG_PPM_VALUES
  14. //#define DEBUG_ERROR_MESSAGES
  15. //#define DEBUG_MESSAGES
  16. //#define DEBUG_HOP_DATA
  17. #define DEBUG_SINGLE_CHARACTER_MESSAGES
  18. #define ALWAYS_PERFORM_BINDING
  19. #define DISABLE_REAL_EEPROM_WRITE
  20. #endif
  21. #include <stdint.h>
  22. #if defined(__AVR__)
  23. #include <avr/eeprom.h>
  24. #include <avr/wdt.h>
  25. #endif
  26. #include "cc2500.h"
  27. #include "cppm.h"
  28. #include "spi.h"
  29. #include "timer.h"
  30. #include "rx.h"
  31. #include "main.h"
  32. #define CHANNELS 8
  33. #define HOP_DATA_LENGTH 60
  34. #define EEPROM_BASE_ADDRESS 100
  35. #define MISSING_PACKET_DELAY 8999
  36. #define SEEK_CHANNEL_SKIP 13
  37. #define MAX_MISSING_PACKET 20
  38. #define FAILSAFE_MISSING_PACKET 170
  39. #define FAILSAFE_INVALID_VALUE 850
  40. #define FAILSAFE_INVALID_VALUE_MINIMUM 900
  41. #define FAILSAFE_INVALID_VALUE_MAXIMUM 2100
  42. //#define RSSI_OVER_PPM 7
  43. #define RSSI_OFFSET 71
  44. #define RSSI_MIN -103
  45. #define RSSI_MAX -96
  46. #define PPM_MIN 1000
  47. #define PPM_MAX 2000
  48. #define PPM_SCALE 2 / 3
  49. #define FRSKY_PACKET_LENGTH 0x11
  50. #define FREQ_ORIGINAL
  51. //#define FREQUENCY_SCAN
  52. // Original 0x5C 0x76 0x27
  53. #define FREQ_SCAN_START_2 0x5C
  54. #define FREQ_SCAN_START_1 0x76
  55. #define FREQ_SCAN_START_0 0x00
  56. uint8_t ccData[100]; // was 27, led to buffer overruns?!
  57. uint8_t ccLen;
  58. uint8_t packet = 0;
  59. uint8_t channr = 0;
  60. uint8_t missingPackets = 0;
  61. uint8_t hopData[HOP_DATA_LENGTH];
  62. uint8_t listLength;
  63. uint8_t txid[2];
  64. uint8_t counter = 0;
  65. uint8_t failed = 0;
  66. uint16_t frequencyOffsetHack = 0;
  67. uint16_t c[CHANNELS];
  68. #ifdef FREQUENCY_SCAN
  69. uint8_t freq2 = FREQ_SCAN_START_2;
  70. uint8_t freq1 = FREQ_SCAN_START_1;
  71. uint8_t freq0 = FREQ_SCAN_START_0;
  72. #endif
  73. static uint16_t ppmBuffer[CHANNELS];
  74. #ifdef RSSI_OVER_PPM
  75. static int rssi;
  76. static long map(long x, long in_min, long in_max, long out_min, long out_max);
  77. static long constrain(long x, long min, long max);
  78. #endif
  79. static void initialize(uint8_t bind);
  80. static void binding(void);
  81. static void tuning(void);
  82. static void performBind(void);
  83. static void nextChannel(uint8_t skip);
  84. static void writeBindingData(void);
  85. #ifndef ALWAYS_PERFORM_BINDING
  86. static void readBindingData(void);
  87. #endif
  88. void rxInit(void) {
  89. GDO_dir;
  90. #ifdef DEBUG_MESSAGES
  91. debugWrite("RX: initializing\n");
  92. #endif
  93. initialize(1); // binding
  94. #ifdef DEBUG_MESSAGES
  95. debugWrite("RX: binding\n");
  96. #endif
  97. binding();
  98. #ifdef DEBUG_MESSAGES
  99. debugWrite("RX: receiving\n");
  100. #endif
  101. initialize(0); // data
  102. cc2500WriteReg(CC2500_0A_CHANNR, hopData[channr]);// 0A - hop
  103. cc2500WriteReg(CC2500_23_FSCAL3, 0x89); // 23 - 89
  104. cc2500Strobe(CC2500_SRX);
  105. }
  106. static void initialize(uint8_t bind) {
  107. cc2500ResetChip();
  108. cc2500WriteReg(CC2500_02_IOCFG0, 0x01); // RX complete interrupt(GDO0)
  109. cc2500WriteReg(CC2500_17_MCSM1, 0x0F);
  110. cc2500WriteReg(CC2500_18_MCSM0, 0x18);
  111. cc2500WriteReg(CC2500_06_PKTLEN, 0x19); // Leave room for appended status bytes
  112. cc2500WriteReg(CC2500_08_PKTCTRL0, 0x05);
  113. cc2500WriteReg(CC2500_3E_PATABLE, 0xFF);
  114. cc2500WriteReg(CC2500_0B_FSCTRL1, 0x08);
  115. cc2500WriteReg(CC2500_0C_FSCTRL0, 0x00);
  116. #ifdef FREQ_ORIGINAL
  117. /*
  118. * According to the internet, these are the default FrSky
  119. * FREQ values (0x5C7627) which should equal 2.404GHz.
  120. * The datasheet mentions Fcarrier = Fxosc * FREQ / 2^16
  121. * Therefore, FrSky seems to be using 26MHz too.
  122. */
  123. cc2500WriteReg(CC2500_0D_FREQ2, 0x5C);
  124. cc2500WriteReg(CC2500_0E_FREQ1, 0x76);
  125. cc2500WriteReg(CC2500_0F_FREQ0, 0x27);
  126. #else
  127. cc2500WriteReg(CC2500_0D_FREQ2, FREQ_SCAN_START_2);
  128. cc2500WriteReg(CC2500_0E_FREQ1, FREQ_SCAN_START_1);
  129. cc2500WriteReg(CC2500_0F_FREQ0, FREQ_SCAN_START_0);
  130. #endif
  131. cc2500WriteReg(CC2500_10_MDMCFG4, 0xAA);
  132. cc2500WriteReg(CC2500_11_MDMCFG3, 0x39);
  133. cc2500WriteReg(CC2500_12_MDMCFG2, 0x11);
  134. cc2500WriteReg(CC2500_13_MDMCFG1, 0x23);
  135. cc2500WriteReg(CC2500_14_MDMCFG0, 0x7A);
  136. cc2500WriteReg(CC2500_15_DEVIATN, 0x42);
  137. cc2500WriteReg(CC2500_19_FOCCFG, 0x16);
  138. cc2500WriteReg(CC2500_1A_BSCFG, 0x6C);
  139. cc2500WriteReg(CC2500_1B_AGCCTRL2, 0x03);
  140. cc2500WriteReg(CC2500_1C_AGCCTRL1, 0x40);
  141. cc2500WriteReg(CC2500_1D_AGCCTRL0, 0x91);
  142. cc2500WriteReg(CC2500_21_FREND1, 0x56);
  143. cc2500WriteReg(CC2500_22_FREND0, 0x10);
  144. cc2500WriteReg(CC2500_23_FSCAL3, 0xA9);
  145. cc2500WriteReg(CC2500_24_FSCAL2, 0x05);
  146. cc2500WriteReg(CC2500_25_FSCAL1, 0x00);
  147. cc2500WriteReg(CC2500_26_FSCAL0, 0x11);
  148. //cc2500WriteReg(CC2500_29_FSTEST, 0x59);
  149. //cc2500WriteReg(CC2500_2C_TEST2, 0x88);
  150. //cc2500WriteReg(CC2500_2D_TEST1, 0x31);
  151. //cc2500WriteReg(CC2500_2E_TEST0, 0x0B);
  152. //cc2500WriteReg(CC2500_03_FIFOTHR, 0x0F); // 0x07?
  153. cc2500WriteReg(CC2500_09_ADDR, bind ? 0x03 : txid[0]);
  154. #ifdef DEBUG_MESSAGES
  155. debugWrite("CC2500: Entering IDLE mode...\n");
  156. #endif
  157. cc2500Strobe(CC2500_SIDLE); // Go to idle...
  158. #ifdef DEBUG_TEST_PART_VERSION
  159. uint8_t part = cc2500ReadReg(CC2500_30_PARTNUM);
  160. uint8_t version = cc2500ReadReg(CC2500_31_VERSION);
  161. debugWrite("CC2500: Part Number: 0x");
  162. debugHex(part);
  163. debugWrite("\nCC2500: Version: 0x");
  164. debugHex(version);
  165. debugWrite("\n");
  166. if ((part != 0x80) || (version != 0x03)) {
  167. debugWrite("INVALID CC2500 STATUS! IT MAY BE DEAD!\n");
  168. }
  169. #endif
  170. // hack: Append status, filter by address, auto-flush on bad crc, PQT=0
  171. cc2500WriteReg(CC2500_07_PKTCTRL1, 0x0D);
  172. //cc2500WriteReg(CC2500_0C_FSCTRL0, 0); // Frequency offset
  173. cc2500WriteReg(CC2500_0C_FSCTRL0, bind ? 0x00 : frequencyOffsetHack);
  174. cc2500WriteReg(CC2500_0A_CHANNR, 0x00);
  175. }
  176. static void binding(void) {
  177. #ifndef ALWAYS_PERFORM_BINDING
  178. readBindingData();
  179. if ((txid[0] != 0xff) || (txid[1] != 0xff)) {
  180. // valid binding data found
  181. debugWrite("RX: found data in EEPROM!\n");
  182. return;
  183. }
  184. #endif
  185. #ifdef DEBUG_MESSAGES
  186. debugWrite("RX: no stored data, tuning...\n");
  187. #endif
  188. // No valid txid, forcing bind
  189. tuning();
  190. //frequencyOffsetHack = 0xC8; // for test
  191. cc2500WriteReg(CC2500_0C_FSCTRL0, frequencyOffsetHack);
  192. #ifndef DISABLE_REAL_EEPROM_WRITE
  193. eeprom_write_byte(EEPROM_BASE_ADDRESS + 101, frequencyOffsetHack);
  194. #endif
  195. #ifdef DEBUG_EEPROM_DATA_WRITE
  196. debugWrite("RX: Write EEPROM Frequency Offset Hack: ");
  197. debugUnsigned8(frequencyOffsetHack);
  198. debugWrite("\n");
  199. #endif
  200. #ifdef DEBUG_MESSAGES
  201. debugWrite("RX: tuned, binding...\n");
  202. #endif
  203. performBind();
  204. }
  205. static void tuning() {
  206. cc2500Strobe(CC2500_SRX); // enter in rx mode
  207. uint16_t frequencyOffsetTimer = 0;
  208. while (1) {
  209. frequencyOffsetTimer++;
  210. if (frequencyOffsetHack >= 250) {
  211. frequencyOffsetHack = 0;
  212. #ifdef FREQUENCY_SCAN
  213. if (freq0 < 255) {
  214. freq0++;
  215. } else {
  216. freq0 = 0;
  217. if (freq1 < 255) {
  218. freq1++;
  219. } else {
  220. freq1 = 0;
  221. if (freq2 < 255) {
  222. freq2++;
  223. } else {
  224. freq2 = 0;
  225. }
  226. }
  227. }
  228. debugWrite("0x");
  229. debugHex(freq2);
  230. debugHex(freq1);
  231. debugHex(freq0);
  232. debugWrite("\n");
  233. cc2500WriteReg(CC2500_0D_FREQ2, freq2);
  234. cc2500WriteReg(CC2500_0E_FREQ1, freq1);
  235. cc2500WriteReg(CC2500_0F_FREQ0, freq0);
  236. #endif
  237. }
  238. // TODO use timer here?
  239. if (frequencyOffsetTimer > 3000) {
  240. frequencyOffsetTimer = 0;
  241. //cc2500WriteReg(CC2500_0C_FSCTRL0, frequencyOffsetHack);
  242. //frequencyOffsetHack += 10;
  243. //cc2500Strobe(CC2500_SRX); // enter in rx mode
  244. }
  245. if (GDO_1) {
  246. ccLen = cc2500ReadReg(CC2500_3B_RXBYTES) & 0x7F;
  247. if (ccLen) {
  248. cc2500ReadFifo(ccData, ccLen);
  249. #ifdef DEBUG_PACKET_DUMP_TUNE
  250. debugWrite("RX: Tune Packet Dump (");
  251. debugUnsigned8(ccLen);
  252. debugWrite("):\n");
  253. for (uint8_t i = 0; i < ccLen; i++) {
  254. debugWrite("0x");
  255. debugHex(ccData[i]);
  256. if (i < (ccLen - 1)) {
  257. debugWrite(" ");
  258. } else {
  259. debugWrite("\n");
  260. }
  261. }
  262. #endif
  263. if ((ccData[ccLen - 1] & CC2500_LQI_CRC_OK_BM)
  264. && (ccData[2] == 0x01)
  265. && (ccData[5] == 0x00)) {
  266. #ifdef DEBUG_MESSAGES
  267. debugWrite("RX: Tune: finished at: ");
  268. debugUnsigned8(frequencyOffsetHack);
  269. debugWrite("!\n");
  270. #endif
  271. #ifdef DEBUG_SINGLE_CHARACTER_MESSAGES
  272. debugChar('t');
  273. #endif
  274. break;
  275. } else {
  276. #ifdef DEBUG_ERROR_MESSAGES
  277. if (!(ccData[ccLen - 1] & CC2500_LQI_CRC_OK_BM)) {
  278. debugWrite("RX: Tune: invalid CRC!\n");
  279. }
  280. if (ccData[2] != 0x01) {
  281. debugWrite("RX: Tune: invalid data[2]: ");
  282. debugUnsigned8(ccData[2]);
  283. debugWrite(" != ");
  284. debugUnsigned8(0x01);
  285. debugWrite("\n");
  286. }
  287. if (ccData[5] != 0x00) {
  288. debugWrite("RX: Tune: invalid data[5]: ");
  289. debugUnsigned8(ccData[5]);
  290. debugWrite(" != ");
  291. debugUnsigned8(0x00);
  292. debugWrite("\n");
  293. }
  294. #endif
  295. #ifdef DEBUG_SINGLE_CHARACTER_MESSAGES
  296. debugChar('u');
  297. #endif
  298. }
  299. }
  300. }
  301. #if defined(__AVR__)
  302. wdt_reset();
  303. #endif
  304. #ifdef DEBUG_UART_MENU
  305. uartMenu();
  306. #endif
  307. }
  308. }
  309. static void performBind(void) {
  310. cc2500Strobe(CC2500_SRX); // enter in rx mode
  311. while (1) {
  312. if (GDO_1) {
  313. ccLen = cc2500ReadReg(CC2500_3B_RXBYTES) & 0x7F;
  314. if (ccLen) {
  315. cc2500ReadFifo(ccData, ccLen);
  316. #ifdef DEBUG_PACKET_DUMP_BIND
  317. debugWrite("RX: Bind Packet Dump (");
  318. debugUnsigned8(ccLen);
  319. debugWrite("):\n");
  320. for (uint8_t i = 0; i < ccLen; i++) {
  321. debugWrite("0x");
  322. debugHex(ccData[i]);
  323. if (i < (ccLen - 1)) {
  324. debugWrite(" ");
  325. } else {
  326. debugWrite("\n");
  327. }
  328. }
  329. #endif
  330. if ((ccData[ccLen - 1] & CC2500_LQI_CRC_OK_BM)
  331. && (ccData[2] == 0x01)
  332. && (ccData[5] == 0x00)) {
  333. txid[0] = ccData[3];
  334. txid[1] = ccData[4];
  335. #ifdef DEBUG_MESSAGES
  336. debugWrite("RX: Bind: got txid: 0x");
  337. debugHex(txid[0]);
  338. debugWrite(" 0x");
  339. debugHex(txid[1]);
  340. debugWrite("\n");
  341. #endif
  342. #ifdef DEBUG_HOP_DATA
  343. debugWrite("RX: Bind: got hop list:\n");
  344. #endif
  345. for (uint8_t n = 0; n < 5; n++) {
  346. hopData[ccData[5] + n] = ccData[6 + n];
  347. #ifdef DEBUG_HOP_DATA
  348. debugUnsigned8(ccData[5] + n);
  349. debugWrite(": ");
  350. debugUnsigned8(ccData[6 + n]);
  351. debugWrite("\n");
  352. #endif
  353. }
  354. #ifdef DEBUG_SINGLE_CHARACTER_MESSAGES
  355. debugChar('b');
  356. #endif
  357. break;
  358. } else {
  359. #ifdef DEBUG_ERROR_MESSAGES
  360. if (!(ccData[ccLen - 1] & CC2500_LQI_CRC_OK_BM)) {
  361. debugWrite("RX: Bind: invalid CRC!\n");
  362. }
  363. if (ccData[2] != 0x01) {
  364. debugWrite("RX: Bind: invalid data[2]: ");
  365. debugUnsigned8(ccData[2]);
  366. debugWrite(" != ");
  367. debugUnsigned8(0x01);
  368. debugWrite("\n");
  369. }
  370. if (ccData[5] != 0x00) {
  371. debugWrite("RX: Bind: invalid data[5]: ");
  372. debugUnsigned8(ccData[5]);
  373. debugWrite(" != ");
  374. debugUnsigned8(0x00);
  375. debugWrite("\n");
  376. }
  377. #endif
  378. #ifdef DEBUG_SINGLE_CHARACTER_MESSAGES
  379. debugChar('c');
  380. #endif
  381. }
  382. }
  383. }
  384. #if defined(__AVR__)
  385. wdt_reset();
  386. #endif
  387. #ifdef DEBUG_UART_MENU
  388. uartMenu();
  389. #endif
  390. }
  391. #ifdef DEBUG_MESSAGES
  392. debugWrite("RX: got hop data, reading list...\n");
  393. #endif
  394. listLength = 0;
  395. uint8_t eol = 0;
  396. for (uint8_t bindIdx = 0x05; bindIdx <= 120; bindIdx += 5) {
  397. while (1) {
  398. if (GDO_1) {
  399. ccLen = cc2500ReadReg(CC2500_3B_RXBYTES) & 0x7F;
  400. if (ccLen) {
  401. cc2500ReadFifo(ccData, ccLen);
  402. #ifdef DEBUG_PACKET_DUMP_LIST
  403. debugWrite("RX: List Packet Dump (");
  404. debugUnsigned8(ccLen);
  405. debugWrite("):\n");
  406. for (uint8_t i = 0; i < ccLen; i++) {
  407. debugWrite("0x");
  408. debugHex(ccData[i]);
  409. if (i < (ccLen - 1)) {
  410. debugWrite(" ");
  411. } else {
  412. debugWrite("\n");
  413. }
  414. }
  415. #endif
  416. if ((ccData[ccLen - 1] & CC2500_LQI_CRC_OK_BM)
  417. && (ccData[2] == 0x01)
  418. && (ccData[3] == txid[0])
  419. && (ccData[4] == txid[1])
  420. && (ccData[5] == bindIdx)) {
  421. #ifdef DEBUG_HOP_DATA
  422. debugWrite("RX: List: got hop list:\n");
  423. #endif
  424. for (uint8_t n = 0; n < 5; n++) {
  425. //if (ccData[6 + n] == ccData[ccLen - 3]) {
  426. if (ccData[6 + n] <= 3) {
  427. #ifdef DEBUG_HOP_DATA
  428. debugWrite("End of List!\n");
  429. #endif
  430. eol = 1;
  431. listLength = ccData[5] + n;
  432. break;
  433. }
  434. hopData[ccData[5] + n] = ccData[6 + n];
  435. #ifdef DEBUG_HOP_DATA
  436. debugUnsigned8(ccData[5] + n);
  437. debugWrite(": ");
  438. debugUnsigned8(ccData[6 + n]);
  439. debugWrite("\n");
  440. #endif
  441. }
  442. #ifdef DEBUG_SINGLE_CHARACTER_MESSAGES
  443. debugChar('l');
  444. #endif
  445. break;
  446. } else {
  447. #ifdef DEBUG_ERROR_MESSAGES
  448. if (!(ccData[ccLen - 1] & CC2500_LQI_CRC_OK_BM)) {
  449. debugWrite("RX: List: invalid CRC!\n");
  450. }
  451. if (ccData[2] != 0x01) {
  452. debugWrite("RX: List: invalid data[2]: ");
  453. debugUnsigned8(ccData[2]);
  454. debugWrite(" != ");
  455. debugUnsigned8(0x01);
  456. debugWrite("\n");
  457. }
  458. if (ccData[3] != txid[0]) {
  459. debugWrite("RX: List: invalid data[3]: ");
  460. debugUnsigned8(ccData[3]);
  461. debugWrite(" != ");
  462. debugUnsigned8(txid[0]);
  463. debugWrite("\n");
  464. }
  465. if (ccData[4] != txid[1]) {
  466. debugWrite("RX: List: invalid data[4]: ");
  467. debugUnsigned8(ccData[4]);
  468. debugWrite(" != ");
  469. debugUnsigned8(txid[1]);
  470. debugWrite("\n");
  471. }
  472. if (ccData[5] != bindIdx) {
  473. debugWrite("RX: List: invalid data[5]: ");
  474. debugUnsigned8(ccData[5]);
  475. debugWrite(" != ");
  476. debugUnsigned8(bindIdx);
  477. debugWrite("\n");
  478. }
  479. #endif
  480. #ifdef DEBUG_SINGLE_CHARACTER_MESSAGES
  481. debugChar('m');
  482. #endif
  483. }
  484. }
  485. }
  486. #if defined(__AVR__)
  487. wdt_reset();
  488. #endif
  489. #ifdef DEBUG_UART_MENU
  490. uartMenu();
  491. #endif
  492. }
  493. if (eol) {
  494. break; // End of list found, stop!
  495. }
  496. }
  497. #ifdef DEBUG_MESSAGES
  498. debugWrite("RX: binding finished!\n");
  499. #endif
  500. writeBindingData();
  501. cc2500Strobe(CC2500_SIDLE); // Back to idle
  502. }
  503. static void nextChannel(uint8_t skip) {
  504. channr += skip;
  505. if (channr >= listLength) {
  506. channr -= listLength;
  507. }
  508. cc2500WriteReg(CC2500_0A_CHANNR, hopData[channr]);
  509. cc2500WriteReg(CC2500_23_FSCAL3, 0x89);
  510. }
  511. #ifndef ALWAYS_PERFORM_BINDING
  512. static void readBindingData() {
  513. #ifdef DEBUG_EEPROM_DATA_READ
  514. debugWrite("RX: Read EEPROM TXID: ");
  515. #endif
  516. for (uint8_t i = 0; i < 2; i++) {
  517. txid[i] = eeprom_read_byte(EEPROM_BASE_ADDRESS + i);
  518. #ifdef DEBUG_EEPROM_DATA_READ
  519. debugWrite("0x");
  520. debugHex(txid[i]);
  521. debugWrite(" ");
  522. #endif
  523. }
  524. #ifdef DEBUG_EEPROM_DATA_READ
  525. debugWrite("\n");
  526. #endif
  527. #ifdef DEBUG_EEPROM_DATA_READ
  528. debugWrite("RX: Read EEPROM Hop Data (");
  529. debugUnsigned8(HOP_DATA_LENGTH);
  530. debugWrite(")\n");
  531. #endif
  532. for (uint8_t i = 0; i < HOP_DATA_LENGTH; i++) {
  533. hopData[i] = eeprom_read_byte(EEPROM_BASE_ADDRESS + 10 + i);
  534. #ifdef DEBUG_EEPROM_DATA_READ
  535. debugWrite("0x");
  536. debugHex(hopData[i]);
  537. debugWrite(" ");
  538. #endif
  539. }
  540. #ifdef DEBUG_EEPROM_DATA_READ
  541. debugWrite("\n");
  542. #endif
  543. listLength = eeprom_read_byte(EEPROM_BASE_ADDRESS + 100);
  544. frequencyOffsetHack = eeprom_read_byte(EEPROM_BASE_ADDRESS + 101);
  545. #ifdef DEBUG_EEPROM_DATA_READ
  546. debugWrite("RX: Read EEPROM List Length: ");
  547. debugUnsigned8(listLength);
  548. debugWrite("\nRX: Read EEPROM Frequency Offset Hack: ");
  549. debugUnsigned8(frequencyOffsetHack);
  550. debugWrite("\n");
  551. #endif
  552. }
  553. #endif
  554. static void writeBindingData() {
  555. #ifdef DEBUG_EEPROM_DATA_WRITE
  556. debugWrite("RX: Write EEPROM TXID: ");
  557. #endif
  558. for (uint8_t i = 0; i < 2; i++) {
  559. #ifndef DISABLE_REAL_EEPROM_WRITE
  560. eeprom_write_byte(EEPROM_BASE_ADDRESS + i, txid[i]);
  561. #endif
  562. #ifdef DEBUG_EEPROM_DATA_WRITE
  563. debugWrite("0x");
  564. debugHex(txid[i]);
  565. debugWrite(" ");
  566. #endif
  567. }
  568. #ifdef DEBUG_EEPROM_DATA_WRITE
  569. debugWrite("\n");
  570. #endif
  571. #ifdef DEBUG_EEPROM_DATA_WRITE
  572. debugWrite("RX: Write EEPROM Hop Data (");
  573. debugUnsigned8(HOP_DATA_LENGTH);
  574. debugWrite(")\n");
  575. #endif
  576. for (uint8_t i = 0; i < HOP_DATA_LENGTH; i++) {
  577. #ifndef DISABLE_REAL_EEPROM_WRITE
  578. eeprom_write_byte(EEPROM_BASE_ADDRESS + 10 + i, hopData[i]);
  579. #endif
  580. #ifdef DEBUG_EEPROM_DATA_WRITE
  581. debugWrite("0x");
  582. debugHex(hopData[i]);
  583. debugWrite(" ");
  584. #endif
  585. }
  586. #ifdef DEBUG_EEPROM_DATA_WRITE
  587. debugWrite("\n");
  588. #endif
  589. #ifndef DISABLE_REAL_EEPROM_WRITE
  590. eeprom_write_byte(EEPROM_BASE_ADDRESS + 100, listLength);
  591. #endif
  592. #ifdef DEBUG_EEPROM_DATA_WRITE
  593. debugWrite("RX: Write EEPROM List Length: ");
  594. debugUnsigned8(listLength);
  595. debugWrite("\n");
  596. #endif
  597. }
  598. void rxReceivePacket() {
  599. time_t time = timerGet();
  600. #if defined(DEBUG_MISSING_PACKETS) || defined(DEBUG_SINGLE_CHARACTER_MESSAGES)
  601. static uint8_t packetMissingNotification = 0;
  602. #endif
  603. if (missingPackets > FAILSAFE_MISSING_PACKET) {
  604. failed = 1;
  605. missingPackets = 0;
  606. }
  607. while (1) {
  608. if ((timerGet() - time) > MISSING_PACKET_DELAY) {
  609. missingPackets++;
  610. cc2500Strobe(CC2500_SIDLE);
  611. if (missingPackets > MAX_MISSING_PACKET) {
  612. nextChannel(SEEK_CHANNEL_SKIP);
  613. counter++;
  614. if (counter > (MAX_MISSING_PACKET << 1)) {
  615. #ifdef DEBUG_MISSING_PACKETS
  616. if (packetMissingNotification < 1) {
  617. debugWrite("RX: missing packet notification!\n");
  618. packetMissingNotification = 1;
  619. }
  620. #endif
  621. #ifdef DEBUG_SINGLE_CHARACTER_MESSAGES
  622. if (packetMissingNotification < 1) {
  623. debugChar('1');
  624. packetMissingNotification = 1;
  625. }
  626. #endif
  627. }
  628. if (counter == (MAX_MISSING_PACKET << 2)) {
  629. #ifdef DEBUG_MISSING_PACKETS
  630. if (packetMissingNotification < 2) {
  631. debugWrite("RX: missing packet notification 2!\n");
  632. packetMissingNotification = 2;
  633. }
  634. #endif
  635. #ifdef DEBUG_SINGLE_CHARACTER_MESSAGES
  636. if (packetMissingNotification < 2) {
  637. debugChar('2');
  638. packetMissingNotification = 2;
  639. }
  640. #endif
  641. counter = 0;
  642. }
  643. } else {
  644. nextChannel(1);
  645. }
  646. break;
  647. }
  648. if (GDO_1) {
  649. ccLen = cc2500ReadReg(CC2500_3B_RXBYTES) & 0x7F;
  650. if (ccLen > 20) {
  651. #ifdef DEBUG_ERROR_MESSAGES
  652. debugWrite("RX: packet too long: ");
  653. debugUnsigned8(ccLen);
  654. debugWrite("\n");
  655. #endif
  656. ccLen = 20;
  657. }
  658. if (ccLen) {
  659. cc2500ReadFifo((uint8_t *)ccData, ccLen);
  660. if (ccData[ccLen - 1] & CC2500_LQI_CRC_OK_BM) { // Only if correct CRC
  661. #ifdef DEBUG_PACKET_DUMP
  662. debugWrite("RX: Packet Dump (");
  663. debugUnsigned8(ccLen);
  664. debugWrite("):\n");
  665. for (uint8_t i = 0; i < ccLen; i++) {
  666. debugWrite("0x");
  667. debugHex(ccData[i]);
  668. if (i < (ccLen - 1)) {
  669. debugWrite(" ");
  670. } else {
  671. debugWrite("\n");
  672. }
  673. }
  674. #endif
  675. missingPackets = 0;
  676. if ((ccData[0] == FRSKY_PACKET_LENGTH) // Correct length
  677. && (ccData[1] == txid[0]) // Correct txid
  678. && (ccData[2] == txid[1])) {
  679. #if defined(DEBUG_MISSING_PACKETS) || defined(DEBUG_SINGLE_CHARACTER_MESSAGES)
  680. packetMissingNotification = 0;
  681. #endif
  682. packet = 1;
  683. #ifdef RSSI_OVER_PPM
  684. int rssi_dec = cc2500ReadReg(CC2500_34_RSSI);
  685. if (rssi_dec < 128) {
  686. rssi = ((rssi_dec / 2) - RSSI_OFFSET) & 0x7f;
  687. } else {
  688. rssi = (((rssi_dec - 256) / 2)) - RSSI_OFFSET;
  689. }
  690. rssi = constrain(rssi, RSSI_MIN, RSSI_MAX);
  691. #endif
  692. cc2500Strobe(CC2500_SIDLE);
  693. nextChannel(1);
  694. failed = 0;
  695. break;
  696. } else {
  697. #ifdef DEBUG_ERROR_MESSAGES
  698. if (ccData[0] != FRSKY_PACKET_LENGTH) {
  699. debugWrite("RX: invalid packet length: ");
  700. debugUnsigned8(ccData[0]);
  701. debugWrite(" != ");
  702. debugUnsigned8(FRSKY_PACKET_LENGTH);
  703. debugWrite("\n");
  704. }
  705. if (ccData[1] != txid[0]) {
  706. debugWrite("RX: invalid txid[0]: ");
  707. debugUnsigned8(ccData[1]);
  708. debugWrite(" != ");
  709. debugUnsigned8(txid[0]);
  710. debugWrite("\n");
  711. }
  712. if (ccData[2] == txid[1]) {
  713. debugWrite("RX: invalid txid[1]: ");
  714. debugUnsigned8(ccData[2]);
  715. debugWrite(" != ");
  716. debugUnsigned8(txid[1]);
  717. debugWrite("\n");
  718. }
  719. #endif
  720. #ifdef DEBUG_SINGLE_CHARACTER_MESSAGES
  721. debugChar('r');
  722. #endif
  723. }
  724. } else {
  725. #ifdef DEBUG_ERROR_MESSAGES
  726. debugWrite("RX: invalid CRC!\n");
  727. #endif
  728. #ifdef DEBUG_SINGLE_CHARACTER_MESSAGES
  729. debugChar('q');
  730. #endif
  731. }
  732. }
  733. }
  734. #if defined(__AVR__)
  735. wdt_reset();
  736. #endif
  737. #ifdef DEBUG_UART_MENU
  738. uartMenu();
  739. #endif
  740. }
  741. if (packet != 0) {
  742. packet = 0;
  743. c[0] = (uint16_t)(ccData[10] & 0x0F) << 8 | ccData[6];
  744. c[1] = (uint16_t)(ccData[10] & 0xF0) << 4 | ccData[7];
  745. c[2] = (uint16_t)(ccData[11] & 0x0F) << 8 | ccData[8];
  746. c[3] = (uint16_t)(ccData[11] & 0xF0) << 4 | ccData[9];
  747. c[4] = (uint16_t)(ccData[16] & 0x0F) << 8 | ccData[12];
  748. c[5] = (uint16_t)(ccData[16] & 0xF0) << 4 | ccData[13];
  749. c[6] = (uint16_t)(ccData[17] & 0x0F) << 8 | ccData[14];
  750. c[7] = (uint16_t)(ccData[17] & 0xF0) << 4 | ccData[15];
  751. for (int i = 0; i < CHANNELS; i++) {
  752. ppmBuffer[i] = (uint16_t)((uint32_t)(c[i]) * PPM_SCALE);
  753. if (ppmBuffer[i] < FAILSAFE_INVALID_VALUE_MINIMUM) {
  754. #ifdef FAILSAFE_INVALID_VALUE
  755. ppmBuffer[i] = FAILSAFE_INVALID_VALUE;
  756. #else
  757. ppmBuffer[i] = FAILSAFE_INVALID_VALUE_MINIMUM;
  758. #endif
  759. }
  760. if (ppmBuffer[i] > FAILSAFE_INVALID_VALUE_MAXIMUM) {
  761. #ifdef FAILSAFE_INVALID_VALUE
  762. ppmBuffer[i] = FAILSAFE_INVALID_VALUE;
  763. #else
  764. ppmBuffer[i] = FAILSAFE_INVALID_VALUE_MAXIMUM;
  765. #endif
  766. }
  767. }
  768. #ifdef RSSI_OVER_PPM
  769. ppmBuffer[RSSI_OVER_PPM] = map(rssi, RSSI_MIN, RSSI_MAX, PPM_MIN, PPM_MAX);
  770. #endif
  771. #ifdef DEBUG_PPM_VALUES
  772. debugWrite("RX: got packet @ ");
  773. debugUnsigned64(timerGet() / 1000000);
  774. debugWrite("s:\n");
  775. for (uint8_t i = 0; i < CHANNELS; i++) {
  776. debugUnsigned8(i);
  777. debugWrite(": ");
  778. debugUnsigned16(ppmBuffer[i]);
  779. debugWrite(" - ");
  780. debugUnsigned16(c[i]);
  781. debugWrite("\n");
  782. }
  783. #endif
  784. #ifdef DEBUG_SINGLE_CHARACTER_MESSAGES
  785. debugChar('p');
  786. #endif
  787. cppmCopy(ppmBuffer);
  788. }
  789. cc2500Strobe(CC2500_SRX);
  790. }
  791. #ifdef RSSI_OVER_PPM
  792. static long map(long x, long in_min, long in_max, long out_min, long out_max) {
  793. return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
  794. }
  795. static long constrain(long x, long min, long max) {
  796. if (x < min) {
  797. x = min;
  798. }
  799. if (x > max) {
  800. x = max;
  801. }
  802. return x;
  803. }
  804. #endif