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

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