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

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