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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. /*
  2. * FrSky RX 2-way protocol
  3. */
  4. #include <stdint.h>
  5. #include <avr/io.h>
  6. #include <avr/interrupt.h>
  7. #include <avr/eeprom.h>
  8. #include "cc2500.h"
  9. #include "spi.h"
  10. #include "timer.h"
  11. // ----------------------------------------------------------------------------
  12. //#define DEBUG
  13. //#define DEBUG_RSSI
  14. //#define DEBUG0
  15. //#define DEBUG1
  16. //#define DEBUG2
  17. //#define DEBUG3
  18. //#define DEBUG4
  19. //#define DEBUG5
  20. //#define RSSI_OVER_PPM 7
  21. #define FAILSAFE
  22. // Used for RSSI_OVER_PPM
  23. int rssi;
  24. const int rssi_offset = 71;
  25. const int rssi_min = -103;
  26. const int rssi_max = -96;
  27. #define chanel_number 8 //set the number of chanels
  28. #define SEEK_CHANSKIP 13
  29. #define MAX_MISSING_PKT 20
  30. #define FAILSAFE_MISSING_PKT 170
  31. #define PPM_FrLen 22500
  32. #define PPM_PulseLen 300
  33. #define default_servo_value 1500
  34. #define onState 0 //set polarity of the pulses: 1 is positive, 0 is negative
  35. #define sigPin 10
  36. #define bind_pin A0 //C0 bind plug also servo8
  37. #define TRUE 1
  38. #define FALSE 0
  39. // Globals:
  40. static uint8_t ccData[27];
  41. static uint8_t ccLen;
  42. static uint8_t packet = FALSE;
  43. static uint8_t channr = 0;
  44. static uint8_t missingPackets = 0;
  45. uint8_t hopData[60];
  46. uint8_t listLength;
  47. uint8_t txid[2];
  48. static uint8_t counter = 0;
  49. volatile uint16_t Servo_data[10] = {1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500};
  50. volatile int ppm[chanel_number];
  51. volatile uint8_t failed = FALSE;
  52. int count = 0;
  53. uint16_t c[8];
  54. void getBind(void);
  55. void Store_bind(void);
  56. void updateRSSI(void);
  57. void loop(void);
  58. void nextChannel(uint8_t skip);
  59. void tuning(void);
  60. // ----------------------------------------------------------------------------
  61. static void initialize(uint8_t bind);
  62. static void binding(void);
  63. void rxInit(void) {
  64. initialize(1); // binding
  65. binding();
  66. initialize(0); // data
  67. cc2500WriteReg(CC2500_0A_CHANNR, hopData[channr]);//0A-hop
  68. cc2500WriteReg(CC2500_23_FSCAL3, 0x89); //23-89
  69. cc2500Strobe(CC2500_SRX);
  70. }
  71. static void initialize(uint8_t bind) {
  72. cc2500ResetChip();
  73. cc2500WriteReg(CC2500_02_IOCFG0, 0x01); // RX complete interrupt(GDO0)
  74. cc2500WriteReg(CC2500_17_MCSM1, 0x0C);
  75. cc2500WriteReg(CC2500_18_MCSM0, 0x18);
  76. cc2500WriteReg(CC2500_06_PKTLEN, 0x19); // Leave room for appended status bytes
  77. cc2500WriteReg(CC2500_08_PKTCTRL0, 0x05);
  78. cc2500WriteReg(CC2500_3E_PATABLE, 0xFF);
  79. cc2500WriteReg(CC2500_0B_FSCTRL1, 0x08);
  80. cc2500WriteReg(CC2500_0C_FSCTRL0, 0x00);
  81. cc2500WriteReg(CC2500_0D_FREQ2, 0x5C);
  82. cc2500WriteReg(CC2500_0E_FREQ1, 0x76);
  83. cc2500WriteReg(CC2500_0F_FREQ0, 0x27);
  84. cc2500WriteReg(CC2500_10_MDMCFG4, 0xAA);
  85. cc2500WriteReg(CC2500_11_MDMCFG3, 0x39);
  86. cc2500WriteReg(CC2500_12_MDMCFG2, 0x11);
  87. cc2500WriteReg(CC2500_13_MDMCFG1, 0x23);
  88. cc2500WriteReg(CC2500_14_MDMCFG0, 0x7A);
  89. cc2500WriteReg(CC2500_15_DEVIATN, 0x42);
  90. cc2500WriteReg(CC2500_19_FOCCFG, 0x16);
  91. cc2500WriteReg(CC2500_1A_BSCFG, 0x6C);
  92. cc2500WriteReg(CC2500_1B_AGCCTRL2, 0x03);
  93. cc2500WriteReg(CC2500_1C_AGCCTRL1, 0x40);
  94. cc2500WriteReg(CC2500_1D_AGCCTRL0, 0x91);
  95. cc2500WriteReg(CC2500_21_FREND1, 0x56);
  96. cc2500WriteReg(CC2500_22_FREND0, 0x10);
  97. cc2500WriteReg(CC2500_23_FSCAL3, 0xA9);
  98. cc2500WriteReg(CC2500_24_FSCAL2, 0x05);
  99. cc2500WriteReg(CC2500_25_FSCAL1, 0x00);
  100. cc2500WriteReg(CC2500_26_FSCAL0, 0x11);
  101. cc2500WriteReg(CC2500_29_FSTEST, 0x59);
  102. cc2500WriteReg(CC2500_2C_TEST2, 0x88);
  103. cc2500WriteReg(CC2500_2D_TEST1, 0x31);
  104. cc2500WriteReg(CC2500_2E_TEST0, 0x0B);
  105. cc2500WriteReg(CC2500_03_FIFOTHR, 0x0F);
  106. cc2500WriteReg(CC2500_09_ADDR, bind ? 0x03 : txid[0]);
  107. cc2500Strobe(CC2500_SIDLE); // Go to idle...
  108. // hack: Append status, filter by address, auto-flush on bad crc, PQT=0
  109. cc2500WriteReg(CC2500_07_PKTCTRL1, 0x0D);
  110. //cc2500WriteReg(CC2500_0C_FSCTRL0, 0); // Frequency offset
  111. cc2500WriteReg(CC2500_0C_FSCTRL0, bind ? 0x00 : count); // Frequency offset hack
  112. cc2500WriteReg(CC2500_0A_CHANNR, 0x00);
  113. }
  114. static void binding(void) {
  115. uint8_t jumper2 = 0; //bind_jumper();
  116. while (1) {
  117. if (jumper2 == 0) {
  118. // bind complete or no bind
  119. uint8_t adr = 100;
  120. for (uint8_t i = 0; i < 2; i++) {
  121. txid[i] = eeprom_read_byte(adr + i);
  122. }
  123. if ((txid[0] == 0xff) && (txid[1] == 0xff)) {
  124. // No valid txid, forcing bind
  125. jumper2 = 1;
  126. continue;
  127. }
  128. for (uint8_t i = 0; i < sizeof(hopData); i++) {
  129. hopData[i] = eeprom_read_byte(adr + 10 + i);
  130. }
  131. listLength = eeprom_read_byte(adr + 100);
  132. count = eeprom_read_byte(adr + 101);
  133. break;
  134. } else {
  135. tuning();
  136. //count=0xC8;//for test
  137. cc2500WriteReg(CC2500_0C_FSCTRL0, count);
  138. int adr = 100;
  139. eeprom_write_byte(adr + 101, count);
  140. getBind();
  141. // TODO reset?!
  142. while (1) { }
  143. }
  144. }
  145. }
  146. // ----------------------------------------------------------------------------
  147. // Receives complete bind setup
  148. void getBind(void)
  149. {
  150. cc2500Strobe(CC2500_SRX);//enter in rx mode
  151. listLength = 0;
  152. uint8_t eol = FALSE;
  153. // len|bind |tx id|idx|h0|h1|h2|h3|h4|00|00|00|00|00|00|01
  154. // Start by getting bind packet 0 and the txid
  155. // 0 1 2 txid0(3) txid1()4 5 6 7 8 9 10 11 12 13 14 15 16 17
  156. //ccdata //11 03 01 d7 2d 00 00 1e 3c 5b 78 00 00 00 00 00 00 01
  157. //11 03 01 19 3e 00 02 8e 2f bb 5c 00 00 00 00 00 00 01
  158. while (1) {
  159. if (GDO_1) {
  160. ccLen = cc2500ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
  161. if (ccLen) {
  162. cc2500ReadFifo((uint8_t *)ccData, ccLen);
  163. if (ccData[ccLen - 1] & 0x80) {
  164. if (ccData[2] == 0x01) {
  165. if (ccData[5] == 0x00) {
  166. txid[0] = ccData[3];
  167. txid[1] = ccData[4];
  168. for (uint8_t n = 0; n < 5; n++) {
  169. hopData[ccData[5] + n] = ccData[6 + n];
  170. }
  171. break;
  172. }
  173. }
  174. }
  175. }
  176. }
  177. }
  178. #if defined(DEBUG)
  179. Serial.print(txid[0], HEX);
  180. Serial.println(txid[1], HEX);
  181. #endif
  182. for (uint8_t bindIdx = 0x05; bindIdx <= 120; bindIdx += 5) {
  183. while (1) {
  184. if (GDO_1) {
  185. ccLen = cc2500ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
  186. if (ccLen) {
  187. cc2500ReadFifo((uint8_t *)ccData, ccLen);
  188. if (ccData[ccLen - 1] & 0x80) {
  189. if (ccData[2] == 0x01) {
  190. #if DEBUG3
  191. Serial.print("ccLen = ");
  192. Serial.println(ccLen);
  193. #endif
  194. if ((ccData[3] == txid[0]) && (ccData[4] == txid[1])) {
  195. #if DEBUG3
  196. Serial.print("ccData[5] = ");
  197. Serial.println(ccData[5]);
  198. Serial.print("bindIdx = ");
  199. Serial.println(bindIdx);
  200. #endif
  201. if (ccData[5] == bindIdx) {
  202. for (uint8_t n = 0; n < 5; n++) {
  203. #if DEBUG3
  204. Serial.print("ccData[6 + n] = ");
  205. Serial.println(ccData[6 + n]);
  206. Serial.print("ccData[ccLen - 3] = ");
  207. Serial.println(ccData[ccLen - 3]);
  208. #endif
  209. //if (ccData[6 + n] == ccData[ccLen - 3]) {
  210. if (ccData[6 + n] <= 3) {
  211. eol = TRUE;
  212. #if defined(DEBUG)
  213. Serial.print("listLength: ");
  214. Serial.println(listLength);
  215. #endif
  216. listLength = ccData[5] + n;
  217. break;
  218. }
  219. hopData[ccData[5] + n] = ccData[6 + n];
  220. }
  221. break;
  222. }
  223. }
  224. }
  225. }
  226. }
  227. }
  228. }
  229. #if defined(DEBUG)
  230. Serial.println(bindIdx / 5);
  231. #endif
  232. if (eol) break; // End of list found, stop!
  233. }
  234. #if defined(DEBUG)
  235. listLength = 47;
  236. Serial.println("jumpIdx list: ");
  237. for (uint8_t jumpIdx = 0; jumpIdx < (listLength); jumpIdx++) {
  238. Serial.print(" ");
  239. Serial.print(hopData[jumpIdx], HEX);
  240. Serial.print(" ");
  241. }
  242. Serial.println(" ");
  243. #endif
  244. Store_bind();
  245. cc2500Strobe(CC2500_SIDLE); // Back to idle
  246. }
  247. void Store_bind()
  248. {
  249. uint8_t i;
  250. int adr = 100;
  251. for (i = 0; i < 2; i++) {
  252. eeprom_write_byte(adr + i, txid[i]);
  253. }
  254. for (i = 0; i < sizeof(hopData); i++) {
  255. eeprom_write_byte(adr + 10 + i, hopData[i]);
  256. }
  257. eeprom_write_byte(adr + 100, listLength);
  258. }
  259. void updateRSSI() {
  260. #if defined(RSSI_OVER_PPM)
  261. int rssi_dec = cc2500ReadReg(CC2500_34_RSSI | CC2500_READ_BURST);
  262. if (rssi_dec < 128) {
  263. rssi = ((rssi_dec / 2) - rssi_offset) & 0x7f;
  264. } else {
  265. rssi = (((rssi_dec - 256) / 2)) - rssi_offset;
  266. }
  267. #if defined(DEBUG_RSSI2)
  268. Serial.print(millis());
  269. Serial.print("\t");
  270. Serial.println(rssi);
  271. #endif
  272. rssi = constrain(rssi, rssi_min, rssi_max);
  273. #endif
  274. }
  275. void loop()
  276. {
  277. time_t time = timerGet();
  278. #if defined(FAILSAFE)
  279. if (missingPackets > FAILSAFE_MISSING_PKT) {
  280. failed = TRUE;
  281. missingPackets = 0;
  282. }
  283. #endif
  284. while (1) {
  285. if ((timerGet() - time) > 9) {
  286. missingPackets++;
  287. cc2500Strobe(CC2500_SIDLE);
  288. if (missingPackets > MAX_MISSING_PKT) {
  289. nextChannel(SEEK_CHANSKIP);
  290. counter++;
  291. //if (counter > (MAX_MISSING_PKT << 1)) LED_ON;
  292. if (counter == (MAX_MISSING_PKT << 2)) counter = 0;
  293. break;
  294. } else
  295. nextChannel(1);
  296. break;
  297. }
  298. if (GDO_1) {
  299. ccLen = cc2500ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
  300. if (ccLen > 20)
  301. ccLen = 20;//
  302. if (ccLen) {
  303. cc2500ReadFifo((uint8_t *)ccData, ccLen);
  304. if (ccData[ccLen - 1] & 0x80) { // Only if correct CRC
  305. missingPackets = 0;
  306. if (ccData[0] == 0x11) { // Correct length
  307. if ((ccData[1] == txid[0]) && (ccData[2] == txid[1])) { // Only if correct txid
  308. packet = TRUE;
  309. //sei();
  310. updateRSSI();
  311. cc2500Strobe(CC2500_SIDLE);
  312. nextChannel(1);
  313. failed = FALSE;
  314. break;
  315. }
  316. }
  317. }
  318. }
  319. }
  320. }
  321. if (packet == TRUE) {
  322. packet = FALSE;
  323. //cli();
  324. c[0] = (uint16_t)(ccData[10] & 0x0F) << 8 | ccData[6];
  325. c[1] = (uint16_t)(ccData[10] & 0xF0) << 4 | ccData[7];
  326. c[2] = (uint16_t)(ccData[11] & 0x0F) << 8 | ccData[8];
  327. c[3] = (uint16_t)(ccData[11] & 0xF0) << 4 | ccData[9];
  328. c[4] = (uint16_t)(ccData[16] & 0x0F) << 8 | ccData[12];
  329. c[5] = (uint16_t)(ccData[16] & 0xF0) << 4 | ccData[13];
  330. c[6] = (uint16_t)(ccData[17] & 0x0F) << 8 | ccData[14];
  331. c[7] = (uint16_t)(ccData[17] & 0xF0) << 4 | ccData[15];
  332. //sei();
  333. for (int i = 0; i < 8; i++) {
  334. Servo_data[i] = 0.67 * c[i];
  335. if (Servo_data[i] < 900) { //added new
  336. Servo_data[i] = 1500; //added new
  337. Servo_data[2] = 1000;
  338. }
  339. ppm[i] = Servo_data[i];
  340. }
  341. #if defined(RSSI_OVER_PPM)
  342. ppm[RSSI_OVER_PPM] = map(rssi, rssi_min, rssi_max, 1000, 2000);
  343. #endif
  344. #if defined(DEBUG5)
  345. //Serial.println(rssi);
  346. #endif
  347. #if defined(DEBUG0)
  348. for (int i = 0; i < 8; i++) {
  349. Serial.print(" ");
  350. Serial.print(Servo_data[i]);
  351. Serial.print(" ");
  352. }
  353. Serial.println(" ");
  354. #endif
  355. }
  356. cc2500Strobe(CC2500_SRX);
  357. }
  358. void nextChannel(uint8_t skip)
  359. {
  360. channr += skip;//
  361. if (channr >= listLength) channr -= listLength;
  362. cc2500WriteReg(CC2500_0A_CHANNR, hopData[channr]);
  363. cc2500WriteReg(CC2500_23_FSCAL3, 0x89);
  364. }
  365. void tuning()
  366. {
  367. cc2500Strobe(CC2500_SRX);//enter in rx mode
  368. int count1 = 0;
  369. while (1) {
  370. count1++;
  371. if (count >= 250) {
  372. count = 0;
  373. }
  374. if (count1 > 3000) {
  375. count1 = 0;
  376. cc2500WriteReg(CC2500_0C_FSCTRL0, count); // Frequency offset hack
  377. count = count + 10;
  378. //cc2500Strobe(CC2500_SRX);//enter in rx mode
  379. }
  380. if (GDO_1) {
  381. ccLen = cc2500ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
  382. if (ccLen) {
  383. cc2500ReadFifo((uint8_t *)ccData, ccLen);
  384. if (ccData[ccLen - 1] & 0x80) {
  385. if (ccData[2] == 0x01) {
  386. if (ccData[5] == 0x00) {
  387. break;
  388. }
  389. }
  390. }
  391. }
  392. }
  393. }
  394. #if defined(DEBUG1)
  395. Serial.println(count, HEX);
  396. #endif
  397. }