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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  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 TRUE 1
  13. #define FALSE 0
  14. #define CHANNELS 8
  15. #define PPM_MIN 1000
  16. #define PPM_MAX 2000
  17. #define RSSI_OVER_PPM 7
  18. #define HOP_DATA_LENGTH 60
  19. #define EEPROM_BASE_ADDRESS 100
  20. #define MISSING_PACKET_DELAY 9
  21. #define SEEK_CHANNEL_SKIP 13
  22. #define MAX_MISSING_PACKET 20
  23. #define FAILSAFE_MISSING_PACKET 170
  24. static uint8_t ccData[27];
  25. static uint8_t ccLen;
  26. static uint8_t packet = FALSE;
  27. static uint8_t channr = 0;
  28. static uint8_t missingPackets = 0;
  29. uint8_t hopData[HOP_DATA_LENGTH];
  30. uint8_t listLength;
  31. uint8_t txid[2];
  32. static uint8_t counter = 0;
  33. volatile uint8_t failed = FALSE;
  34. int count = 0;
  35. uint16_t c[8];
  36. int rssi;
  37. const int rssi_offset = 71;
  38. const int rssi_min = -103;
  39. const int rssi_max = -96;
  40. void getBind(void);
  41. void loop(void);
  42. void tuning(void);
  43. // ----------------------------------------------------------------------------
  44. static uint16_t ppmBuffer[CHANNELS];
  45. static long map(long x, long in_min, long in_max, long out_min, long out_max);
  46. static long constrain(long x, long min, long max);
  47. static void initialize(uint8_t bind);
  48. static void binding(void);
  49. static void nextChannel(uint8_t skip);
  50. static void readBindingData(void);
  51. static void writeBindingData(void);
  52. void rxInit(void) {
  53. initialize(1); // binding
  54. binding();
  55. initialize(0); // data
  56. cc2500WriteReg(CC2500_0A_CHANNR, hopData[channr]);//0A-hop
  57. cc2500WriteReg(CC2500_23_FSCAL3, 0x89); //23-89
  58. cc2500Strobe(CC2500_SRX);
  59. }
  60. static long map(long x, long in_min, long in_max, long out_min, long out_max) {
  61. return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
  62. }
  63. static long constrain(long x, long min, long max) {
  64. if (x < min) {
  65. x = min;
  66. }
  67. if (x > max) {
  68. x = max;
  69. }
  70. return x;
  71. }
  72. static void initialize(uint8_t bind) {
  73. cc2500ResetChip();
  74. cc2500WriteReg(CC2500_02_IOCFG0, 0x01); // RX complete interrupt(GDO0)
  75. cc2500WriteReg(CC2500_17_MCSM1, 0x0C);
  76. cc2500WriteReg(CC2500_18_MCSM0, 0x18);
  77. cc2500WriteReg(CC2500_06_PKTLEN, 0x19); // Leave room for appended status bytes
  78. cc2500WriteReg(CC2500_08_PKTCTRL0, 0x05);
  79. cc2500WriteReg(CC2500_3E_PATABLE, 0xFF);
  80. cc2500WriteReg(CC2500_0B_FSCTRL1, 0x08);
  81. cc2500WriteReg(CC2500_0C_FSCTRL0, 0x00);
  82. cc2500WriteReg(CC2500_0D_FREQ2, 0x5C);
  83. cc2500WriteReg(CC2500_0E_FREQ1, 0x76);
  84. cc2500WriteReg(CC2500_0F_FREQ0, 0x27);
  85. cc2500WriteReg(CC2500_10_MDMCFG4, 0xAA);
  86. cc2500WriteReg(CC2500_11_MDMCFG3, 0x39);
  87. cc2500WriteReg(CC2500_12_MDMCFG2, 0x11);
  88. cc2500WriteReg(CC2500_13_MDMCFG1, 0x23);
  89. cc2500WriteReg(CC2500_14_MDMCFG0, 0x7A);
  90. cc2500WriteReg(CC2500_15_DEVIATN, 0x42);
  91. cc2500WriteReg(CC2500_19_FOCCFG, 0x16);
  92. cc2500WriteReg(CC2500_1A_BSCFG, 0x6C);
  93. cc2500WriteReg(CC2500_1B_AGCCTRL2, 0x03);
  94. cc2500WriteReg(CC2500_1C_AGCCTRL1, 0x40);
  95. cc2500WriteReg(CC2500_1D_AGCCTRL0, 0x91);
  96. cc2500WriteReg(CC2500_21_FREND1, 0x56);
  97. cc2500WriteReg(CC2500_22_FREND0, 0x10);
  98. cc2500WriteReg(CC2500_23_FSCAL3, 0xA9);
  99. cc2500WriteReg(CC2500_24_FSCAL2, 0x05);
  100. cc2500WriteReg(CC2500_25_FSCAL1, 0x00);
  101. cc2500WriteReg(CC2500_26_FSCAL0, 0x11);
  102. cc2500WriteReg(CC2500_29_FSTEST, 0x59);
  103. cc2500WriteReg(CC2500_2C_TEST2, 0x88);
  104. cc2500WriteReg(CC2500_2D_TEST1, 0x31);
  105. cc2500WriteReg(CC2500_2E_TEST0, 0x0B);
  106. cc2500WriteReg(CC2500_03_FIFOTHR, 0x0F);
  107. cc2500WriteReg(CC2500_09_ADDR, bind ? 0x03 : txid[0]);
  108. cc2500Strobe(CC2500_SIDLE); // Go to idle...
  109. // hack: Append status, filter by address, auto-flush on bad crc, PQT=0
  110. cc2500WriteReg(CC2500_07_PKTCTRL1, 0x0D);
  111. //cc2500WriteReg(CC2500_0C_FSCTRL0, 0); // Frequency offset
  112. cc2500WriteReg(CC2500_0C_FSCTRL0, bind ? 0x00 : count); // Frequency offset hack
  113. cc2500WriteReg(CC2500_0A_CHANNR, 0x00);
  114. }
  115. static void binding(void) {
  116. uint8_t jumper2 = 0; //bind_jumper();
  117. while (1) {
  118. if (jumper2 == 0) {
  119. // bind complete or no bind
  120. readBindingData();
  121. if ((txid[0] == 0xff) && (txid[1] == 0xff)) {
  122. // No valid txid, forcing bind
  123. jumper2 = 1;
  124. continue;
  125. }
  126. break;
  127. } else {
  128. tuning();
  129. //count=0xC8;//for test
  130. cc2500WriteReg(CC2500_0C_FSCTRL0, count);
  131. eeprom_write_byte(EEPROM_BASE_ADDRESS + 101, count);
  132. getBind();
  133. // TODO reset?!
  134. while (1) { }
  135. }
  136. }
  137. }
  138. static void nextChannel(uint8_t skip) {
  139. channr += skip;
  140. if (channr >= listLength) {
  141. channr -= listLength;
  142. }
  143. cc2500WriteReg(CC2500_0A_CHANNR, hopData[channr]);
  144. cc2500WriteReg(CC2500_23_FSCAL3, 0x89);
  145. }
  146. static void readBindingData() {
  147. for (uint8_t i = 0; i < 2; i++) {
  148. txid[i] = eeprom_read_byte(EEPROM_BASE_ADDRESS + i);
  149. }
  150. for (uint8_t i = 0; i < HOP_DATA_LENGTH; i++) {
  151. hopData[i] = eeprom_read_byte(EEPROM_BASE_ADDRESS + 10 + i);
  152. }
  153. listLength = eeprom_read_byte(EEPROM_BASE_ADDRESS + 100);
  154. count = eeprom_read_byte(EEPROM_BASE_ADDRESS + 101);
  155. }
  156. static void writeBindingData() {
  157. for (uint8_t i = 0; i < 2; i++) {
  158. eeprom_write_byte(EEPROM_BASE_ADDRESS + i, txid[i]);
  159. }
  160. for (uint8_t i = 0; i < HOP_DATA_LENGTH; i++) {
  161. eeprom_write_byte(EEPROM_BASE_ADDRESS + 10 + i, hopData[i]);
  162. }
  163. eeprom_write_byte(EEPROM_BASE_ADDRESS + 100, listLength);
  164. }
  165. // ----------------------------------------------------------------------------
  166. // Receives complete bind setup
  167. void getBind(void) {
  168. cc2500Strobe(CC2500_SRX); // enter in rx mode
  169. while (1) {
  170. if (GDO_1) {
  171. ccLen = cc2500ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
  172. if (ccLen) {
  173. cc2500ReadFifo((uint8_t *)ccData, ccLen);
  174. if ((ccData[ccLen - 1] & 0x80)
  175. && (ccData[2] == 0x01)
  176. && (ccData[5] == 0x00)) {
  177. txid[0] = ccData[3];
  178. txid[1] = ccData[4];
  179. for (uint8_t n = 0; n < 5; n++) {
  180. hopData[ccData[5] + n] = ccData[6 + n];
  181. }
  182. break;
  183. }
  184. }
  185. }
  186. }
  187. listLength = 0;
  188. uint8_t eol = FALSE;
  189. for (uint8_t bindIdx = 0x05; bindIdx <= 120; bindIdx += 5) {
  190. while (1) {
  191. if (GDO_1) {
  192. ccLen = cc2500ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
  193. if (ccLen) {
  194. cc2500ReadFifo((uint8_t *)ccData, ccLen);
  195. if ((ccData[ccLen - 1] & 0x80)
  196. && (ccData[2] == 0x01)
  197. && (ccData[3] == txid[0])
  198. && (ccData[4] == txid[1])
  199. && (ccData[5] == bindIdx)) {
  200. for (uint8_t n = 0; n < 5; n++) {
  201. //if (ccData[6 + n] == ccData[ccLen - 3]) {
  202. if (ccData[6 + n] <= 3) {
  203. eol = TRUE;
  204. listLength = ccData[5] + n;
  205. break;
  206. }
  207. hopData[ccData[5] + n] = ccData[6 + n];
  208. }
  209. break;
  210. }
  211. }
  212. }
  213. }
  214. if (eol) {
  215. break; // End of list found, stop!
  216. }
  217. }
  218. writeBindingData();
  219. cc2500Strobe(CC2500_SIDLE); // Back to idle
  220. }
  221. void loop() {
  222. time_t time = timerGet();
  223. if (missingPackets > FAILSAFE_MISSING_PACKET) {
  224. failed = TRUE;
  225. missingPackets = 0;
  226. }
  227. while (1) {
  228. if ((timerGet() - time) > MISSING_PACKET_DELAY) {
  229. missingPackets++;
  230. cc2500Strobe(CC2500_SIDLE);
  231. if (missingPackets > MAX_MISSING_PACKET) {
  232. nextChannel(SEEK_CHANNEL_SKIP);
  233. counter++;
  234. //if (counter > (MAX_MISSING_PACKET << 1)) LED_ON;
  235. if (counter == (MAX_MISSING_PACKET << 2)) counter = 0;
  236. break;
  237. } else
  238. nextChannel(1);
  239. break;
  240. }
  241. if (GDO_1) {
  242. ccLen = cc2500ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
  243. if (ccLen > 20)
  244. ccLen = 20;
  245. if (ccLen) {
  246. cc2500ReadFifo((uint8_t *)ccData, ccLen);
  247. if (ccData[ccLen - 1] & 0x80) { // Only if correct CRC
  248. missingPackets = 0;
  249. if (ccData[0] == 0x11) { // Correct length
  250. if ((ccData[1] == txid[0]) && (ccData[2] == txid[1])) { // Only if correct txid
  251. packet = TRUE;
  252. //sei();
  253. #ifdef RSSI_OVER_PPM
  254. int rssi_dec = cc2500ReadReg(CC2500_34_RSSI | CC2500_READ_BURST);
  255. if (rssi_dec < 128) {
  256. rssi = ((rssi_dec / 2) - rssi_offset) & 0x7f;
  257. } else {
  258. rssi = (((rssi_dec - 256) / 2)) - rssi_offset;
  259. }
  260. rssi = constrain(rssi, rssi_min, rssi_max);
  261. #endif
  262. cc2500Strobe(CC2500_SIDLE);
  263. nextChannel(1);
  264. failed = FALSE;
  265. break;
  266. }
  267. }
  268. }
  269. }
  270. }
  271. }
  272. if (packet == TRUE) {
  273. packet = FALSE;
  274. //cli();
  275. c[0] = (uint16_t)(ccData[10] & 0x0F) << 8 | ccData[6];
  276. c[1] = (uint16_t)(ccData[10] & 0xF0) << 4 | ccData[7];
  277. c[2] = (uint16_t)(ccData[11] & 0x0F) << 8 | ccData[8];
  278. c[3] = (uint16_t)(ccData[11] & 0xF0) << 4 | ccData[9];
  279. c[4] = (uint16_t)(ccData[16] & 0x0F) << 8 | ccData[12];
  280. c[5] = (uint16_t)(ccData[16] & 0xF0) << 4 | ccData[13];
  281. c[6] = (uint16_t)(ccData[17] & 0x0F) << 8 | ccData[14];
  282. c[7] = (uint16_t)(ccData[17] & 0xF0) << 4 | ccData[15];
  283. //sei();
  284. for (int i = 0; i < CHANNELS; i++) {
  285. ppmBuffer[i] = 0.67 * c[i];
  286. /*
  287. if (ppmBuffer[i] < 900) {
  288. ppmBuffer[i] = 1500;
  289. //ppmBuffer[2] = 1000;
  290. }
  291. */
  292. }
  293. #ifdef RSSI_OVER_PPM
  294. ppmBuffer[RSSI_OVER_PPM] = map(rssi, rssi_min, rssi_max, PPM_MIN, PPM_MAX);
  295. #endif
  296. }
  297. cc2500Strobe(CC2500_SRX);
  298. }
  299. void tuning() {
  300. cc2500Strobe(CC2500_SRX); // enter in rx mode
  301. int count1 = 0;
  302. while (1) {
  303. count1++;
  304. if (count >= 250) {
  305. count = 0;
  306. }
  307. if (count1 > 3000) {
  308. count1 = 0;
  309. cc2500WriteReg(CC2500_0C_FSCTRL0, count); // Frequency offset hack
  310. count = count + 10;
  311. //cc2500Strobe(CC2500_SRX);// enter in rx mode
  312. }
  313. if (GDO_1) {
  314. ccLen = cc2500ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
  315. if (ccLen) {
  316. cc2500ReadFifo((uint8_t *)ccData, ccLen);
  317. if (ccData[ccLen - 1] & 0x80) {
  318. if (ccData[2] == 0x01) {
  319. if (ccData[5] == 0x00) {
  320. break;
  321. }
  322. }
  323. }
  324. }
  325. }
  326. }
  327. }