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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913
  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. if (frequencyOffsetTimer > 3000) {
  239. frequencyOffsetTimer = 0;
  240. //cc2500WriteReg(CC2500_0C_FSCTRL0, frequencyOffsetHack);
  241. //frequencyOffsetHack += 10;
  242. //cc2500Strobe(CC2500_SRX); // enter in rx mode
  243. }
  244. if (GDO_1) {
  245. ccLen = cc2500ReadReg(CC2500_3B_RXBYTES) & 0x7F;
  246. if (ccLen) {
  247. cc2500ReadFifo(ccData, ccLen);
  248. #ifdef DEBUG_PACKET_DUMP_TUNE
  249. debugWrite("RX: Tune Packet Dump (");
  250. debugUnsigned8(ccLen);
  251. debugWrite("):\n");
  252. for (uint8_t i = 0; i < ccLen; i++) {
  253. debugWrite("0x");
  254. debugHex(ccData[i]);
  255. if (i < (ccLen - 1)) {
  256. debugWrite(" ");
  257. } else {
  258. debugWrite("\n");
  259. }
  260. }
  261. #endif
  262. if ((ccData[ccLen - 1] & CC2500_LQI_CRC_OK_BM)
  263. && (ccData[2] == 0x01)
  264. && (ccData[5] == 0x00)) {
  265. #ifdef DEBUG_MESSAGES
  266. debugWrite("RX: Tune: finished at: ");
  267. debugUnsigned8(frequencyOffsetHack);
  268. debugWrite("!\n");
  269. #endif
  270. #ifdef DEBUG_SINGLE_CHARACTER_MESSAGES
  271. debugChar('t');
  272. #endif
  273. break;
  274. } else {
  275. #ifdef DEBUG_ERROR_MESSAGES
  276. if (!(ccData[ccLen - 1] & CC2500_LQI_CRC_OK_BM)) {
  277. debugWrite("RX: Tune: invalid CRC!\n");
  278. }
  279. if (ccData[2] != 0x01) {
  280. debugWrite("RX: Tune: invalid data[2]: ");
  281. debugUnsigned8(ccData[2]);
  282. debugWrite(" != ");
  283. debugUnsigned8(0x01);
  284. debugWrite("\n");
  285. }
  286. if (ccData[5] != 0x00) {
  287. debugWrite("RX: Tune: invalid data[5]: ");
  288. debugUnsigned8(ccData[5]);
  289. debugWrite(" != ");
  290. debugUnsigned8(0x00);
  291. debugWrite("\n");
  292. }
  293. #endif
  294. #ifdef DEBUG_SINGLE_CHARACTER_MESSAGES
  295. debugChar('u');
  296. #endif
  297. }
  298. }
  299. }
  300. #if defined(__AVR__)
  301. wdt_reset();
  302. #endif
  303. #ifdef DEBUG_UART_MENU
  304. uartMenu();
  305. #endif
  306. }
  307. }
  308. static void performBind(void) {
  309. cc2500Strobe(CC2500_SRX); // enter in rx mode
  310. while (1) {
  311. if (GDO_1) {
  312. ccLen = cc2500ReadReg(CC2500_3B_RXBYTES) & 0x7F;
  313. if (ccLen) {
  314. cc2500ReadFifo(ccData, ccLen);
  315. #ifdef DEBUG_PACKET_DUMP_BIND
  316. debugWrite("RX: Bind Packet Dump (");
  317. debugUnsigned8(ccLen);
  318. debugWrite("):\n");
  319. for (uint8_t i = 0; i < ccLen; i++) {
  320. debugWrite("0x");
  321. debugHex(ccData[i]);
  322. if (i < (ccLen - 1)) {
  323. debugWrite(" ");
  324. } else {
  325. debugWrite("\n");
  326. }
  327. }
  328. #endif
  329. if ((ccData[ccLen - 1] & CC2500_LQI_CRC_OK_BM)
  330. && (ccData[2] == 0x01)
  331. && (ccData[5] == 0x00)) {
  332. txid[0] = ccData[3];
  333. txid[1] = ccData[4];
  334. #ifdef DEBUG_MESSAGES
  335. debugWrite("RX: Bind: got txid: 0x");
  336. debugHex(txid[0]);
  337. debugWrite(" 0x");
  338. debugHex(txid[1]);
  339. debugWrite("\n");
  340. #endif
  341. #ifdef DEBUG_HOP_DATA
  342. debugWrite("RX: Bind: got hop list:\n");
  343. #endif
  344. for (uint8_t n = 0; n < 5; n++) {
  345. hopData[ccData[5] + n] = ccData[6 + n];
  346. #ifdef DEBUG_HOP_DATA
  347. debugUnsigned8(ccData[5] + n);
  348. debugWrite(": ");
  349. debugUnsigned8(ccData[6 + n]);
  350. debugWrite("\n");
  351. #endif
  352. }
  353. #ifdef DEBUG_SINGLE_CHARACTER_MESSAGES
  354. debugChar('b');
  355. #endif
  356. break;
  357. } else {
  358. #ifdef DEBUG_ERROR_MESSAGES
  359. if (!(ccData[ccLen - 1] & CC2500_LQI_CRC_OK_BM)) {
  360. debugWrite("RX: Bind: invalid CRC!\n");
  361. }
  362. if (ccData[2] != 0x01) {
  363. debugWrite("RX: Bind: invalid data[2]: ");
  364. debugUnsigned8(ccData[2]);
  365. debugWrite(" != ");
  366. debugUnsigned8(0x01);
  367. debugWrite("\n");
  368. }
  369. if (ccData[5] != 0x00) {
  370. debugWrite("RX: Bind: invalid data[5]: ");
  371. debugUnsigned8(ccData[5]);
  372. debugWrite(" != ");
  373. debugUnsigned8(0x00);
  374. debugWrite("\n");
  375. }
  376. #endif
  377. #ifdef DEBUG_SINGLE_CHARACTER_MESSAGES
  378. debugChar('c');
  379. #endif
  380. }
  381. }
  382. }
  383. #if defined(__AVR__)
  384. wdt_reset();
  385. #endif
  386. #ifdef DEBUG_UART_MENU
  387. uartMenu();
  388. #endif
  389. }
  390. #ifdef DEBUG_MESSAGES
  391. debugWrite("RX: got hop data, reading list...\n");
  392. #endif
  393. listLength = 0;
  394. uint8_t eol = 0;
  395. for (uint8_t bindIdx = 0x05; bindIdx <= 120; bindIdx += 5) {
  396. while (1) {
  397. if (GDO_1) {
  398. ccLen = cc2500ReadReg(CC2500_3B_RXBYTES) & 0x7F;
  399. if (ccLen) {
  400. cc2500ReadFifo(ccData, ccLen);
  401. #ifdef DEBUG_PACKET_DUMP_LIST
  402. debugWrite("RX: List Packet Dump (");
  403. debugUnsigned8(ccLen);
  404. debugWrite("):\n");
  405. for (uint8_t i = 0; i < ccLen; i++) {
  406. debugWrite("0x");
  407. debugHex(ccData[i]);
  408. if (i < (ccLen - 1)) {
  409. debugWrite(" ");
  410. } else {
  411. debugWrite("\n");
  412. }
  413. }
  414. #endif
  415. if ((ccData[ccLen - 1] & CC2500_LQI_CRC_OK_BM)
  416. && (ccData[2] == 0x01)
  417. && (ccData[3] == txid[0])
  418. && (ccData[4] == txid[1])
  419. && (ccData[5] == bindIdx)) {
  420. #ifdef DEBUG_HOP_DATA
  421. debugWrite("RX: List: got hop list:\n");
  422. #endif
  423. for (uint8_t n = 0; n < 5; n++) {
  424. //if (ccData[6 + n] == ccData[ccLen - 3]) {
  425. if (ccData[6 + n] <= 3) {
  426. #ifdef DEBUG_HOP_DATA
  427. debugWrite("End of List!\n");
  428. #endif
  429. eol = 1;
  430. listLength = ccData[5] + n;
  431. break;
  432. }
  433. hopData[ccData[5] + n] = ccData[6 + n];
  434. #ifdef DEBUG_HOP_DATA
  435. debugUnsigned8(ccData[5] + n);
  436. debugWrite(": ");
  437. debugUnsigned8(ccData[6 + n]);
  438. debugWrite("\n");
  439. #endif
  440. }
  441. #ifdef DEBUG_ERROR_MESSAGES
  442. if (!(ccData[ccLen - 1] & CC2500_LQI_CRC_OK_BM)) {
  443. debugWrite("RX: List: invalid CRC!\n");
  444. }
  445. if (ccData[2] != 0x01) {
  446. debugWrite("RX: List: invalid data[2]: ");
  447. debugUnsigned8(ccData[2]);
  448. debugWrite(" != ");
  449. debugUnsigned8(0x01);
  450. debugWrite("\n");
  451. }
  452. if (ccData[3] != txid[0]) {
  453. debugWrite("RX: List: invalid data[3]: ");
  454. debugUnsigned8(ccData[3]);
  455. debugWrite(" != ");
  456. debugUnsigned8(txid[0]);
  457. debugWrite("\n");
  458. }
  459. if (ccData[4] != txid[1]) {
  460. debugWrite("RX: List: invalid data[4]: ");
  461. debugUnsigned8(ccData[4]);
  462. debugWrite(" != ");
  463. debugUnsigned8(txid[1]);
  464. debugWrite("\n");
  465. }
  466. if (ccData[5] != bindIdx) {
  467. debugWrite("RX: List: invalid data[5]: ");
  468. debugUnsigned8(ccData[5]);
  469. debugWrite(" != ");
  470. debugUnsigned8(bindIdx);
  471. debugWrite("\n");
  472. }
  473. #endif
  474. #ifdef DEBUG_SINGLE_CHARACTER_MESSAGES
  475. debugChar('l');
  476. #endif
  477. break;
  478. } else {
  479. #ifdef DEBUG_SINGLE_CHARACTER_MESSAGES
  480. debugChar('m');
  481. #endif
  482. }
  483. }
  484. }
  485. #if defined(__AVR__)
  486. wdt_reset();
  487. #endif
  488. #ifdef DEBUG_UART_MENU
  489. uartMenu();
  490. #endif
  491. }
  492. if (eol) {
  493. break; // End of list found, stop!
  494. }
  495. }
  496. #ifdef DEBUG_MESSAGES
  497. debugWrite("RX: binding finished!\n");
  498. #endif
  499. writeBindingData();
  500. cc2500Strobe(CC2500_SIDLE); // Back to idle
  501. }
  502. static void nextChannel(uint8_t skip) {
  503. channr += skip;
  504. if (channr >= listLength) {
  505. channr -= listLength;
  506. }
  507. cc2500WriteReg(CC2500_0A_CHANNR, hopData[channr]);
  508. cc2500WriteReg(CC2500_23_FSCAL3, 0x89);
  509. }
  510. #ifndef ALWAYS_PERFORM_BINDING
  511. static void readBindingData() {
  512. #ifdef DEBUG_EEPROM_DATA_READ
  513. debugWrite("RX: Read EEPROM TXID: ");
  514. #endif
  515. for (uint8_t i = 0; i < 2; i++) {
  516. txid[i] = eeprom_read_byte(EEPROM_BASE_ADDRESS + i);
  517. #ifdef DEBUG_EEPROM_DATA_READ
  518. debugWrite("0x");
  519. debugHex(txid[i]);
  520. debugWrite(" ");
  521. #endif
  522. }
  523. #ifdef DEBUG_EEPROM_DATA_READ
  524. debugWrite("\n");
  525. #endif
  526. #ifdef DEBUG_EEPROM_DATA_READ
  527. debugWrite("RX: Read EEPROM Hop Data (");
  528. debugUnsigned8(HOP_DATA_LENGTH);
  529. debugWrite(")\n");
  530. #endif
  531. for (uint8_t i = 0; i < HOP_DATA_LENGTH; i++) {
  532. hopData[i] = eeprom_read_byte(EEPROM_BASE_ADDRESS + 10 + i);
  533. #ifdef DEBUG_EEPROM_DATA_READ
  534. debugWrite("0x");
  535. debugHex(hopData[i]);
  536. debugWrite(" ");
  537. #endif
  538. }
  539. #ifdef DEBUG_EEPROM_DATA_READ
  540. debugWrite("\n");
  541. #endif
  542. listLength = eeprom_read_byte(EEPROM_BASE_ADDRESS + 100);
  543. frequencyOffsetHack = eeprom_read_byte(EEPROM_BASE_ADDRESS + 101);
  544. #ifdef DEBUG_EEPROM_DATA_READ
  545. debugWrite("RX: Read EEPROM List Length: ");
  546. debugUnsigned8(listLength);
  547. debugWrite("\nRX: Read EEPROM Frequency Offset Hack: ");
  548. debugUnsigned8(frequencyOffsetHack);
  549. debugWrite("\n");
  550. #endif
  551. }
  552. #endif
  553. static void writeBindingData() {
  554. #ifdef DEBUG_EEPROM_DATA_WRITE
  555. debugWrite("RX: Write EEPROM TXID: ");
  556. #endif
  557. for (uint8_t i = 0; i < 2; i++) {
  558. #ifndef DISABLE_REAL_EEPROM_WRITE
  559. eeprom_write_byte(EEPROM_BASE_ADDRESS + i, txid[i]);
  560. #endif
  561. #ifdef DEBUG_EEPROM_DATA_WRITE
  562. debugWrite("0x");
  563. debugHex(txid[i]);
  564. debugWrite(" ");
  565. #endif
  566. }
  567. #ifdef DEBUG_EEPROM_DATA_WRITE
  568. debugWrite("\n");
  569. #endif
  570. #ifdef DEBUG_EEPROM_DATA_WRITE
  571. debugWrite("RX: Write EEPROM Hop Data (");
  572. debugUnsigned8(HOP_DATA_LENGTH);
  573. debugWrite(")\n");
  574. #endif
  575. for (uint8_t i = 0; i < HOP_DATA_LENGTH; i++) {
  576. #ifndef DISABLE_REAL_EEPROM_WRITE
  577. eeprom_write_byte(EEPROM_BASE_ADDRESS + 10 + i, hopData[i]);
  578. #endif
  579. #ifdef DEBUG_EEPROM_DATA_WRITE
  580. debugWrite("0x");
  581. debugHex(hopData[i]);
  582. debugWrite(" ");
  583. #endif
  584. }
  585. #ifdef DEBUG_EEPROM_DATA_WRITE
  586. debugWrite("\n");
  587. #endif
  588. #ifndef DISABLE_REAL_EEPROM_WRITE
  589. eeprom_write_byte(EEPROM_BASE_ADDRESS + 100, listLength);
  590. #endif
  591. #ifdef DEBUG_EEPROM_DATA_WRITE
  592. debugWrite("RX: Write EEPROM List Length: ");
  593. debugUnsigned8(listLength);
  594. debugWrite("\n");
  595. #endif
  596. }
  597. void rxReceivePacket() {
  598. time_t time = timerGet();
  599. #if defined(DEBUG_MISSING_PACKETS) || defined(DEBUG_SINGLE_CHARACTER_MESSAGES)
  600. static uint8_t packetMissingNotification = 0;
  601. #endif
  602. if (missingPackets > FAILSAFE_MISSING_PACKET) {
  603. failed = 1;
  604. missingPackets = 0;
  605. }
  606. while (1) {
  607. if ((timerGet() - time) > MISSING_PACKET_DELAY) {
  608. missingPackets++;
  609. cc2500Strobe(CC2500_SIDLE);
  610. if (missingPackets > MAX_MISSING_PACKET) {
  611. nextChannel(SEEK_CHANNEL_SKIP);
  612. counter++;
  613. if (counter > (MAX_MISSING_PACKET << 1)) {
  614. #ifdef DEBUG_MISSING_PACKETS
  615. if (packetMissingNotification < 1) {
  616. debugWrite("RX: missing packet notification!\n");
  617. packetMissingNotification = 1;
  618. }
  619. #endif
  620. #ifdef DEBUG_SINGLE_CHARACTER_MESSAGES
  621. if (packetMissingNotification < 1) {
  622. debugChar('1');
  623. packetMissingNotification = 1;
  624. }
  625. #endif
  626. }
  627. if (counter == (MAX_MISSING_PACKET << 2)) {
  628. #ifdef DEBUG_MISSING_PACKETS
  629. if (packetMissingNotification < 2) {
  630. debugWrite("RX: missing packet notification 2!\n");
  631. packetMissingNotification = 2;
  632. }
  633. #endif
  634. #ifdef DEBUG_SINGLE_CHARACTER_MESSAGES
  635. if (packetMissingNotification < 2) {
  636. debugChar('2');
  637. packetMissingNotification = 2;
  638. }
  639. #endif
  640. counter = 0;
  641. }
  642. } else {
  643. nextChannel(1);
  644. }
  645. break;
  646. }
  647. if (GDO_1) {
  648. ccLen = cc2500ReadReg(CC2500_3B_RXBYTES) & 0x7F;
  649. if (ccLen > 20) {
  650. #ifdef DEBUG_ERROR_MESSAGES
  651. debugWrite("RX: packet too long: ");
  652. debugUnsigned8(ccLen);
  653. debugWrite("\n");
  654. #endif
  655. ccLen = 20;
  656. }
  657. if (ccLen) {
  658. cc2500ReadFifo((uint8_t *)ccData, ccLen);
  659. if (ccData[ccLen - 1] & CC2500_LQI_CRC_OK_BM) { // Only if correct CRC
  660. #ifdef DEBUG_PACKET_DUMP
  661. debugWrite("RX: Packet Dump (");
  662. debugUnsigned8(ccLen);
  663. debugWrite("):\n");
  664. for (uint8_t i = 0; i < ccLen; i++) {
  665. debugWrite("0x");
  666. debugHex(ccData[i]);
  667. if (i < (ccLen - 1)) {
  668. debugWrite(" ");
  669. } else {
  670. debugWrite("\n");
  671. }
  672. }
  673. #endif
  674. missingPackets = 0;
  675. if ((ccData[0] == FRSKY_PACKET_LENGTH) // Correct length
  676. && (ccData[1] == txid[0]) // Correct txid
  677. && (ccData[2] == txid[1])) {
  678. #if defined(DEBUG_MISSING_PACKETS) || defined(DEBUG_SINGLE_CHARACTER_MESSAGES)
  679. packetMissingNotification = 0;
  680. #endif
  681. packet = 1;
  682. #ifdef RSSI_OVER_PPM
  683. int rssi_dec = cc2500ReadReg(CC2500_34_RSSI);
  684. if (rssi_dec < 128) {
  685. rssi = ((rssi_dec / 2) - RSSI_OFFSET) & 0x7f;
  686. } else {
  687. rssi = (((rssi_dec - 256) / 2)) - RSSI_OFFSET;
  688. }
  689. rssi = constrain(rssi, RSSI_MIN, RSSI_MAX);
  690. #endif
  691. cc2500Strobe(CC2500_SIDLE);
  692. nextChannel(1);
  693. failed = 0;
  694. break;
  695. } else {
  696. #ifdef DEBUG_ERROR_MESSAGES
  697. if (ccData[0] != FRSKY_PACKET_LENGTH) {
  698. debugWrite("RX: invalid packet length: ");
  699. debugUnsigned8(ccData[0]);
  700. debugWrite(" != ");
  701. debugUnsigned8(FRSKY_PACKET_LENGTH);
  702. debugWrite("\n");
  703. }
  704. if (ccData[1] != txid[0]) {
  705. debugWrite("RX: invalid txid[0]: ");
  706. debugUnsigned8(ccData[1]);
  707. debugWrite(" != ");
  708. debugUnsigned8(txid[0]);
  709. debugWrite("\n");
  710. }
  711. if (ccData[2] == txid[1]) {
  712. debugWrite("RX: invalid txid[1]: ");
  713. debugUnsigned8(ccData[2]);
  714. debugWrite(" != ");
  715. debugUnsigned8(txid[1]);
  716. debugWrite("\n");
  717. }
  718. #endif
  719. #ifdef DEBUG_SINGLE_CHARACTER_MESSAGES
  720. debugChar('r');
  721. #endif
  722. }
  723. } else {
  724. #ifdef DEBUG_ERROR_MESSAGES
  725. debugWrite("RX: invalid CRC!\n");
  726. #endif
  727. #ifdef DEBUG_SINGLE_CHARACTER_MESSAGES
  728. debugChar('q');
  729. #endif
  730. }
  731. }
  732. }
  733. #if defined(__AVR__)
  734. wdt_reset();
  735. #endif
  736. #ifdef DEBUG_UART_MENU
  737. uartMenu();
  738. #endif
  739. }
  740. if (packet != 0) {
  741. packet = 0;
  742. c[0] = (uint16_t)(ccData[10] & 0x0F) << 8 | ccData[6];
  743. c[1] = (uint16_t)(ccData[10] & 0xF0) << 4 | ccData[7];
  744. c[2] = (uint16_t)(ccData[11] & 0x0F) << 8 | ccData[8];
  745. c[3] = (uint16_t)(ccData[11] & 0xF0) << 4 | ccData[9];
  746. c[4] = (uint16_t)(ccData[16] & 0x0F) << 8 | ccData[12];
  747. c[5] = (uint16_t)(ccData[16] & 0xF0) << 4 | ccData[13];
  748. c[6] = (uint16_t)(ccData[17] & 0x0F) << 8 | ccData[14];
  749. c[7] = (uint16_t)(ccData[17] & 0xF0) << 4 | ccData[15];
  750. for (int i = 0; i < CHANNELS; i++) {
  751. ppmBuffer[i] = (uint16_t)((uint32_t)(c[i]) * PPM_SCALE);
  752. if (ppmBuffer[i] < FAILSAFE_INVALID_VALUE_MINIMUM) {
  753. #ifdef FAILSAFE_INVALID_VALUE
  754. ppmBuffer[i] = FAILSAFE_INVALID_VALUE;
  755. #else
  756. ppmBuffer[i] = FAILSAFE_INVALID_VALUE_MINIMUM;
  757. #endif
  758. }
  759. if (ppmBuffer[i] > FAILSAFE_INVALID_VALUE_MAXIMUM) {
  760. #ifdef FAILSAFE_INVALID_VALUE
  761. ppmBuffer[i] = FAILSAFE_INVALID_VALUE;
  762. #else
  763. ppmBuffer[i] = FAILSAFE_INVALID_VALUE_MAXIMUM;
  764. #endif
  765. }
  766. }
  767. #ifdef RSSI_OVER_PPM
  768. ppmBuffer[RSSI_OVER_PPM] = map(rssi, RSSI_MIN, RSSI_MAX, PPM_MIN, PPM_MAX);
  769. #endif
  770. #ifdef DEBUG_PPM_VALUES
  771. debugWrite("RX: got packet @ ");
  772. debugUnsigned64(timerGet() / 1000);
  773. debugWrite("s:\n");
  774. for (uint8_t i = 0; i < CHANNELS; i++) {
  775. debugUnsigned8(i);
  776. debugWrite(": ");
  777. debugUnsigned16(ppmBuffer[i]);
  778. debugWrite(" - ");
  779. debugUnsigned16(c[i]);
  780. debugWrite("\n");
  781. }
  782. #endif
  783. #ifdef DEBUG_SINGLE_CHARACTER_MESSAGES
  784. debugChar('p');
  785. #endif
  786. cppmCopy(ppmBuffer);
  787. }
  788. cc2500Strobe(CC2500_SRX);
  789. }
  790. #ifdef RSSI_OVER_PPM
  791. static long map(long x, long in_min, long in_max, long out_min, long out_max) {
  792. return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
  793. }
  794. static long constrain(long x, long min, long max) {
  795. if (x < min) {
  796. x = min;
  797. }
  798. if (x > max) {
  799. x = max;
  800. }
  801. return x;
  802. }
  803. #endif