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

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