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