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

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