├── FlyskyTransmitter.cpp ├── FlyskyTransmitter.h ├── LICENSE ├── README.md ├── a7105.cpp ├── a7105.h ├── config.h ├── examples └── FlyskyTest │ └── FlyskyTest.ino ├── model.cpp ├── model.h └── printf.h /FlyskyTransmitter.cpp: -------------------------------------------------------------------------------- 1 | // BOF preprocessor bug prevent - insert me on top of your arduino-code 2 | #if 1 3 | __asm volatile ("nop"); 4 | #endif 5 | 6 | /* 7 | This project is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Deviation is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with Deviation. If not, see . 19 | */ 20 | #include 21 | #if defined (__SAM3X8E__) 22 | //#include 23 | #elif defined (__AVR_ATmega2560__ ) 24 | //#include 25 | #else 26 | #include 27 | #endif 28 | 29 | #include "a7105.h" 30 | #include "config.h" 31 | #include "model.h" 32 | 33 | #ifdef MODULAR 34 | //Allows the linker to properly relocate 35 | #define FLYSKY_Cmds PROTO_Cmds 36 | #pragma long_calls 37 | #endif 38 | 39 | 40 | 41 | #ifdef MODULAR 42 | #pragma long_calls_off 43 | extern unsigned _data_loadaddr; 44 | const unsigned long protocol_type = (unsigned long)&_data_loadaddr; 45 | #endif 46 | 47 | 48 | //Fewer bind packets in the emulator so we can get right to the important bits 49 | #ifdef EMULATOR 50 | #define BIND_COUNT 3 51 | #else 52 | #define BIND_COUNT 2500 53 | #endif 54 | /* 55 | static const char * const flysky_opts[] = { 56 | "WLToys V9x9", _tr_noop("Off"), _tr_noop("On"), NULL, 57 | NULL 58 | };*/ 59 | #define WLTOYS_ON 1 60 | #define WLTOYS_OFF 0 61 | enum { 62 | PROTOOPTS_WLTOYS = 0, 63 | }; 64 | static const u8 A7105_regs[] = { 65 | -1, 0x42, 0x00, 0x14, 0x00, -1 , -1 , 0x00, 0x00, 0x00, 0x00, 0x01, 0x21, 0x05, 0x00, 0x50, 66 | 0x9e, 0x4b, 0x00, 0x02, 0x16, 0x2b, 0x12, 0x00, 0x62, 0x80, 0x80, 0x00, 0x0a, 0x32, 0xc3, 0x0f, 67 | 0x13, 0xc3, 0x00, -1, 0x00, 0x00, 0x3b, 0x00, 0x17, 0x47, 0x80, 0x03, 0x01, 0x45, 0x18, 0x00, 68 | 0x01, 0x0f, -1, 69 | }; 70 | static const u8 tx_channels[16][16] = { 71 | {0x0a, 0x5a, 0x14, 0x64, 0x1e, 0x6e, 0x28, 0x78, 0x32, 0x82, 0x3c, 0x8c, 0x46, 0x96, 0x50, 0xa0}, 72 | {0xa0, 0x50, 0x96, 0x46, 0x8c, 0x3c, 0x82, 0x32, 0x78, 0x28, 0x6e, 0x1e, 0x64, 0x14, 0x5a, 0x0a}, 73 | {0x0a, 0x5a, 0x50, 0xa0, 0x14, 0x64, 0x46, 0x96, 0x1e, 0x6e, 0x3c, 0x8c, 0x28, 0x78, 0x32, 0x82}, 74 | {0x82, 0x32, 0x78, 0x28, 0x8c, 0x3c, 0x6e, 0x1e, 0x96, 0x46, 0x64, 0x14, 0xa0, 0x50, 0x5a, 0x0a}, 75 | {0x28, 0x78, 0x0a, 0x5a, 0x50, 0xa0, 0x14, 0x64, 0x1e, 0x6e, 0x3c, 0x8c, 0x32, 0x82, 0x46, 0x96}, 76 | {0x96, 0x46, 0x82, 0x32, 0x8c, 0x3c, 0x6e, 0x1e, 0x64, 0x14, 0xa0, 0x50, 0x5a, 0x0a, 0x78, 0x28}, 77 | {0x50, 0xa0, 0x28, 0x78, 0x0a, 0x5a, 0x1e, 0x6e, 0x3c, 0x8c, 0x32, 0x82, 0x46, 0x96, 0x14, 0x64}, 78 | {0x64, 0x14, 0x96, 0x46, 0x82, 0x32, 0x8c, 0x3c, 0x6e, 0x1e, 0x5a, 0x0a, 0x78, 0x28, 0xa0, 0x50}, 79 | {0x50, 0xa0, 0x46, 0x96, 0x3c, 0x8c, 0x28, 0x78, 0x0a, 0x5a, 0x32, 0x82, 0x1e, 0x6e, 0x14, 0x64}, 80 | {0x64, 0x14, 0x6e, 0x1e, 0x82, 0x32, 0x5a, 0x0a, 0x78, 0x28, 0x8c, 0x3c, 0x96, 0x46, 0xa0, 0x50}, 81 | {0x46, 0x96, 0x3c, 0x8c, 0x50, 0xa0, 0x28, 0x78, 0x0a, 0x5a, 0x1e, 0x6e, 0x32, 0x82, 0x14, 0x64}, 82 | {0x64, 0x14, 0x82, 0x32, 0x6e, 0x1e, 0x5a, 0x0a, 0x78, 0x28, 0xa0, 0x50, 0x8c, 0x3c, 0x96, 0x46}, 83 | {0x46, 0x96, 0x0a, 0x5a, 0x3c, 0x8c, 0x14, 0x64, 0x50, 0xa0, 0x28, 0x78, 0x1e, 0x6e, 0x32, 0x82}, 84 | {0x82, 0x32, 0x6e, 0x1e, 0x78, 0x28, 0xa0, 0x50, 0x64, 0x14, 0x8c, 0x3c, 0x5a, 0x0a, 0x96, 0x46}, 85 | {0x46, 0x96, 0x0a, 0x5a, 0x50, 0xa0, 0x3c, 0x8c, 0x28, 0x78, 0x1e, 0x6e, 0x32, 0x82, 0x14, 0x64}, 86 | {0x64, 0x14, 0x82, 0x32, 0x6e, 0x1e, 0x78, 0x28, 0x8c, 0x3c, 0xa0, 0x50, 0x5a, 0x0a, 0x96, 0x46}, 87 | }; 88 | static u32 id; 89 | //static const u8 id[] = { 0x02, 0x00, 0x00, 0x70 }; 90 | static u8 chanrow; 91 | static u8 chancol; 92 | static u8 chanoffset; 93 | static u8 packet[21]; 94 | static u16 counter; 95 | 96 | //The folloiwng code came from: http://notabs.org/winzipcrc/winzipcrc.c 97 | // C99 winzip crc function, by Scott Duplichan 98 | //We could use the internal CRC implementation in the STM32, but this is really small 99 | //and perfomrance isn't really an issue 100 | static u32 Crc(const void *buffer, u32 size) 101 | { 102 | u32 crc = ~0; 103 | const u8 *position = (u8 *)buffer; 104 | 105 | while (size--) 106 | { 107 | int bit; 108 | crc ^= *position++; 109 | for (bit = 0; bit < 8; bit++) 110 | { 111 | s32 out = crc & 1; 112 | crc >>= 1; 113 | crc ^= -out & 0xEDB88320; 114 | } 115 | } 116 | return ~crc; 117 | } 118 | 119 | static u8 proto_state; 120 | static u32 bind_time; 121 | #define PROTO_DEINIT 0x00 122 | #define PROTO_INIT 0x01 123 | #define PROTO_READY 0x02 124 | #define PROTO_BINDING 0x04 125 | #define PROTO_BINDDLG 0x08 126 | #define PROTO_MODULEDLG 0x10 127 | 128 | static void PROTOCOL_SetBindState(u32 msec) 129 | { 130 | if (msec) { 131 | if (msec == 0xFFFFFFFF) 132 | bind_time = msec; 133 | else 134 | bind_time = millis() + msec; 135 | proto_state |= PROTO_BINDING; 136 | //PROTOCOL_SticksMoved(1); //Initialize Stick position 137 | } else { 138 | proto_state &= ~PROTO_BINDING; 139 | } 140 | } 141 | 142 | 143 | 144 | 145 | // Channels should be volatile: 146 | // This array is written from the main event loop 147 | // and read from an interrupt service routine. 148 | // volatile makes sure, each access to the array 149 | // will be an actual access to the memory location 150 | // an element is stored in. 151 | // If it is omitted, the optimizer might create a 152 | // 'short cut', removing seemingly unneccessary memory accesses, 153 | // and thereby preventing the propagation of an update from 154 | // the main loop to the interrupt routine (since the optimizer 155 | // has no clue about interrupts) 156 | 157 | volatile s16 Channels[NUM_OUT_CHANNELS]; 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | static int flysky_init() 167 | { 168 | int i; 169 | u8 if_calibration1; 170 | u8 vco_calibration0; 171 | u8 vco_calibration1; 172 | u8 vco_read; 173 | 174 | A7105_WriteID(0x5475c52a); 175 | for (i = 0; i < 0x33; i++) 176 | if((s8)A7105_regs[i] != -1) 177 | A7105_WriteReg(i, A7105_regs[i]); 178 | 179 | A7105_Strobe(A7105_STANDBY); 180 | 181 | // vco_read = A7105_ReadReg(0x00); 182 | // printf("%d vco_read=%d\n", __LINE__, vco_read); 183 | 184 | //IF Filter Bank Calibration 185 | A7105_WriteReg(0x02, 1); 186 | u32 ms = millis(); 187 | while(millis() - ms < 500) { 188 | if(! A7105_ReadReg(0x02)) 189 | break; 190 | } 191 | if (millis() - ms >= 500) { 192 | printf("flysky_init() - failed! (%d)\n", __LINE__); 193 | return 0; 194 | } 195 | if_calibration1 = A7105_ReadReg(0x22); 196 | if(if_calibration1 & A7105_MASK_FBCF) { 197 | //Calibration failed...what do we do? 198 | printf("flysky_init() - failed! (%d)\n", __LINE__); 199 | return 0; 200 | } 201 | 202 | //VCO Current Calibration 203 | A7105_WriteReg(0x24, 0x13); //Recomended calibration from A7105 Datasheet 204 | 205 | //VCO Bank Calibration 206 | A7105_WriteReg(0x26, 0x3b); //Recomended limits from A7105 Datasheet 207 | 208 | //VCO Bank Calibrate channel 0? 209 | //Set Channel 210 | A7105_WriteReg(0x0f, 0); //Should we choose a different channel? 211 | //VCO Calibration 212 | A7105_WriteReg(0x02, 2); 213 | ms = millis(); 214 | while(millis() - ms < 500) { 215 | if(! A7105_ReadReg(0x02)) 216 | break; 217 | } 218 | if (millis() - ms >= 500) { 219 | printf("flysky_init() - failed! (%d)\n", __LINE__); 220 | return 0; 221 | } 222 | vco_calibration0 = A7105_ReadReg(0x25); 223 | if (vco_calibration0 & A7105_MASK_VBCF) { 224 | //Calibration failed...what do we do? 225 | printf("flysky_init() - failed! (%d)\n", __LINE__); 226 | return 0; 227 | } 228 | 229 | //Calibrate channel 0xa0? 230 | //Set Channel 231 | A7105_WriteReg(0x0f, 0xa0); //Should we choose a different channel? 232 | //VCO Calibration 233 | A7105_WriteReg(0x02, 2); 234 | ms = millis(); 235 | while(millis() - ms < 500) { 236 | if(! A7105_ReadReg(A7105_02_CALC)) 237 | break; 238 | } 239 | if (millis() - ms >= 500) { 240 | printf("flysky_init() - failed! (%d)\n", __LINE__); 241 | return 0; 242 | } 243 | vco_calibration1 = A7105_ReadReg(0x25); 244 | if (vco_calibration1 & A7105_MASK_VBCF) { 245 | //Calibration failed...what do we do? 246 | printf("flysky_init() - failed! (%d)\n", __LINE__); 247 | return 0; 248 | } 249 | 250 | //Reset VCO Band calibration 251 | A7105_WriteReg(0x25, 0x08); 252 | 253 | A7105_SetTxRxMode(TX_EN); 254 | A7105_SetPower(Model.tx_power); 255 | 256 | A7105_Strobe(A7105_STANDBY); 257 | 258 | printf("flysky_init() - OK!\n"); 259 | return 1; 260 | } 261 | 262 | 263 | // 05 AA 5C 29 00 90 or 05 55 5C 29 00 90 264 | // F1 E7 DC 05 265 | // 48 94 F4 05 266 | // 95 FD E8 03 267 | // 98 EB DC 05 268 | // BD 19 EA 02 269 | // FE 0F FF 0F 270 | // 33 8C 19 00 271 | // EA B2 00 00 272 | // pause 273 | // 0F 01 0F 91 274 | 275 | 276 | 277 | // Roll | Pitch | Throttle| Yaw | Data 4 | Data 5 | Data 6 | Data 7 278 | // Data 0 | Data 1 | Data 2 | Data 3 | Data 4 | Data 5 | Data 6 | Data 7 279 | // 280 | // Idle DC 05 F4 05 E8 03 79 05 E0 02 36 00 19 00 00 00 281 | // Idle DC 05 F4 05 E8 03 79 05 DA 02 FE 0F 19 00 00 00 (left button 1) 282 | // Idle DC 05 F4 05 E8 03 47 05 DB 02 36 00 19 00 00 00 (left button 2) 283 | // Idle DC 05 F4 05 E8 03 47 05 DA 02 3C 00 19 00 00 00 (right button 1) 284 | // Idle DC 05 F4 05 E8 03 47 05 DA 02 3C 00 19 00 00 00 (right button 2) 285 | // Yaw Left DC 05 F4 05 E8 03 DC 05 DD 02 27 00 19 00 00 00 286 | // Yaw Left DC 05 F4 05 E8 03 79 05 E1 02 3C 00 19 00 00 00 287 | // Yaw Right DC 05 F4 05 E8 03 DC 05 E3 02 3C 00 19 00 00 00 288 | // Pitch Back DC 05 57 06 E8 03 79 05 DF 02 FF 0F 19 00 00 00 289 | // Pitch Forw DC 05 91 05 E8 03 79 05 DF 02 FE 0F 19 00 00 00 290 | // Roll Right 3F 06 F4 05 E8 03 79 05 DE 02 FE 0F 19 00 00 00 291 | // Roll Left 79 05 F4 05 E8 03 79 05 DE 02 FE 0F 19 00 00 00 292 | 293 | 294 | static void flysky_build_packet(u8 init) 295 | { 296 | int i; 297 | //-100% =~ 0x03e8 298 | //+100% =~ 0x07ca 299 | //Calculate: 300 | //Center = 0x5d9 301 | //1 % = 5 302 | packet[0] = init ? 0xaa : 0x55; 303 | packet[1] = (id >> 0) & 0xff; 304 | packet[2] = (id >> 8) & 0xff; 305 | packet[3] = (id >> 16) & 0xff; 306 | packet[4] = (id >> 24) & 0xff; 307 | for (i = 0; i < 8; i++) { 308 | if (i > Model.num_channels) { 309 | packet[5 + i*2] = 0; 310 | packet[6 + i*2] = 0; 311 | continue; 312 | } 313 | // s32 value = (s32)Channels[i] * 0x1f1 / CHAN_MAX_VALUE + 0x5d9; 314 | 315 | s32 value = 0; 316 | switch (i) { 317 | case 0: 318 | case 3: 319 | value = (s32)Channels[i] * 0x1f1 / CHAN_MAX_VALUE + 0x5dc; 320 | break; 321 | case 1: 322 | value = (s32)Channels[i] * 0x1f1 / CHAN_MAX_VALUE + 0x5f4; 323 | break; 324 | case 2: 325 | value = (s32)Channels[i] * 0x1f1 / CHAN_MAX_VALUE + 0x3e8; 326 | } 327 | if (value < 0) 328 | value = 0; 329 | packet[5 + i*2] = value & 0xff; 330 | packet[6 + i*2] = (value >> 8) & 0xff; 331 | } 332 | // if (Model.proto_opts[PROTOOPTS_WLTOYS] == WLTOYS_ON) { 333 | if(Channels[4] > 0) 334 | packet[12] |= 0x20; 335 | if(Channels[5] > 0) 336 | packet[10] |= 0x40; 337 | if(Channels[6] > 0) 338 | packet[10] |= 0x80; 339 | if(Channels[7] > 0) 340 | packet[12] |= 0x10; 341 | 342 | //} 343 | } 344 | 345 | 346 | //static u16 flysky_cb() 347 | static void flysky_cb() 348 | { 349 | if (counter) { 350 | flysky_build_packet(1); 351 | A7105_WriteData(packet, 21, 1); 352 | counter--; 353 | if (! counter) 354 | PROTOCOL_SetBindState(0); 355 | } else { 356 | flysky_build_packet(0); 357 | A7105_WriteData(packet, 21, tx_channels[chanrow][chancol]-chanoffset); 358 | chancol = (chancol + 1) % 16; 359 | if (! chancol) //Keep transmit power updated 360 | A7105_SetPower(Model.tx_power); 361 | } 362 | //return 1460; 363 | } 364 | 365 | static void initialize(u8 bind) { 366 | 367 | while(1) { 368 | //A7105_Reset(); 369 | if (flysky_init()) 370 | break; 371 | } 372 | if (Model.fixed_id) { 373 | id = Model.fixed_id; 374 | } else { 375 | //id = (Crc(&Model, sizeof(Model)) + Crc(&Transmitter, sizeof(Transmitter))) % 999999; 376 | id = rand(); 377 | } 378 | chanrow = id % 16; 379 | chancol = 0; 380 | chanoffset = (id & 0xff) / 16; 381 | if (bind || ! Model.fixed_id) { 382 | counter = BIND_COUNT; 383 | PROTOCOL_SetBindState(2500 * 1460 / 1000); //msec 384 | } else { 385 | counter = 0; 386 | } 387 | //CLOCK_StartTimer(2400, flysky_cb); 388 | #if defined (__arm__) && defined (__SAM3X8E__) 389 | Timer3.attachInterrupt(flysky_cb).start(1250); //2400 390 | #elif defined (__AVR_ATmega328P__) 391 | Timer1.attachInterrupt(flysky_cb, 1250); 392 | #else 393 | Timer3.attachInterrupt(flysky_cb, 1250); 394 | #endif 395 | 396 | printf("Init ok session id=0x%x channel=0x%x\n", id, chanrow); 397 | } 398 | 399 | 400 | const void *FLYSKY_Cmds(enum ProtoCmds cmd) 401 | { 402 | switch(cmd) { 403 | case PROTOCMD_INIT: initialize(0); return 0; 404 | case PROTOCMD_DEINIT: 405 | case PROTOCMD_RESET: 406 | //CLOCK_StopTimer(); 407 | #if defined (__AVR_ATmega328P__) 408 | Timer1.detachInterrupt(); 409 | #else 410 | Timer3.detachInterrupt(); 411 | #endif 412 | 413 | return (void *)(A7105_Reset() ? 1L : -1L); 414 | case PROTOCMD_CHECK_AUTOBIND: return Model.fixed_id ? 0 : (void *)1L; 415 | case PROTOCMD_BIND: initialize(1); return 0; 416 | case PROTOCMD_NUMCHAN: return (void *)8L; 417 | case PROTOCMD_DEFAULT_NUMCHAN: return (void *)8L; 418 | case PROTOCMD_CURRENT_ID: return (void *)((unsigned long)id); 419 | // case PROTOCMD_GETOPTIONS: 420 | // return flysky_opts; 421 | case PROTOCMD_TELEMETRYSTATE: return (void *)(long)PROTO_TELEM_UNSUPPORTED; 422 | default: break; 423 | } 424 | return 0; 425 | } 426 | -------------------------------------------------------------------------------- /FlyskyTransmitter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * V9x9protocol.h 3 | * 4 | * Created: 18/07/2014 23:03:43 5 | * Author: Miro 6 | */ 7 | 8 | 9 | #ifndef V9X9PROTOCOL_H_ 10 | #define V9X9PROTOCOL_H_ 11 | 12 | extern volatile s16 Channels[NUM_OUT_CHANNELS]; 13 | 14 | void *FLYSKY_Cmds(enum ProtoCmds cmd); 15 | 16 | 17 | #endif /* V9X9PROTOCOL_H_ */ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | flysky-arduino-transmitter 2 | ========================== 3 | 4 | Control WLToys V911/V929/V939/V949/V959 Quad Copters with Arduino 5 | -------------------------------------------------------------------------------- /a7105.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "config.h" 4 | #include "a7105.h" 5 | 6 | #define CS_PIN 8//53 //10 7 | 8 | #define CS_HI() digitalWrite(CS_PIN, HIGH); 9 | #define CS_LO() digitalWrite(CS_PIN, LOW); 10 | 11 | void A7105_WriteReg(u8 address, u8 data) 12 | { 13 | CS_LO(); 14 | SPI.transfer(address); // spi_xfer(SPI2, address); 15 | SPI.transfer(data); // spi_xfer(SPI2, data); 16 | CS_HI(); 17 | } 18 | 19 | u8 A7105_ReadReg(u8 address) 20 | { 21 | u8 data; 22 | int i; 23 | CS_LO(); 24 | // Bits A7-A0 make up the first u8. 25 | // Bit A7 = 1 == Strobe. A7 = 0 == access register. 26 | // Bit a6 = 1 == read. a6 = 0 == write. 27 | // bits 0-5 = address. Assuming address < 64 the below says we want to read an address. 28 | SPI.transfer(0x40 | address); //spi_xfer(SPI2, 0x40 | address); 29 | data = SPI.transfer(0); 30 | CS_HI(); 31 | // Serial.print(address); Serial.print(" "); Serial.println(data); 32 | return data; 33 | // Not necessary because we expect SPI class to handle this? 34 | // /* Wait for tx completion before spi shutdown */ 35 | // while(!(SPI_SR(SPI2) & SPI_SR_TXE)) 36 | // ; 37 | // while((SPI_SR(SPI2) & SPI_SR_BSY)) 38 | // ; 39 | 40 | // spi_disable(SPI2); 41 | // spi_set_bidirectional_receive_only_mode(SPI2); 42 | // */ 43 | // /* Force read from SPI_DR to ensure RXNE is clear (probably not needed) */ 44 | // volatile u8 x = SPI_DR(SPI2); 45 | // (void)x; 46 | // spi_enable(SPI2); //This starts the data read 47 | // for(i = 0; i < 20; i++) //Wait > 1 SPI clock (but less than 8). clock is 4.5MHz 48 | // asm volatile ("nop"); 49 | // ; 50 | // spi_disable(SPI2); //This ends the read window 51 | // data = spi_read(SPI2); 52 | // CS_HI(); 53 | // spi_set_unidirectional_mode(SPI2); 54 | // spi_enable(SPI2); 55 | // return data; 56 | } 57 | 58 | void A7105_Setup() { 59 | pinMode(CS_PIN, OUTPUT); 60 | SPI.begin(); 61 | SPI.setDataMode(SPI_MODE0); 62 | // SPI.setClockDivider(10); 63 | SPI.setBitOrder(MSBFIRST); 64 | // set gpio1 to SDO (MISO) by writing to reg GIO1S 65 | A7105_WriteReg(0x0b,0x06); // 0b0110 66 | } 67 | 68 | 69 | void A7105_WriteData(u8 *dpbuffer, u8 len, u8 channel) 70 | { 71 | int i; 72 | CS_LO(); 73 | SPI.transfer(A7105_RST_WRPTR); //reset write FIFO PTR 74 | SPI.transfer(0x05); // FIFO DATA register - about to send data to put into FIFO 75 | for (i = 0; i < len; i++) 76 | SPI.transfer(dpbuffer[i]); // send some data 77 | CS_HI(); 78 | 79 | // set the channel 80 | A7105_WriteReg(0x0F, channel); 81 | 82 | CS_LO(); 83 | SPI.transfer(A7105_TX); // strobe command to actually transmit the daat 84 | CS_HI(); 85 | } 86 | 87 | void A7105_ReadData(u8 *dpbuffer, u8 len) 88 | { 89 | A7105_Strobe(A7105_RST_RDPTR); //A7105_RST_RDPTR 90 | for(int i = 0; i < len; i++) { 91 | dpbuffer[i] = A7105_ReadReg(0x05); 92 | } 93 | 94 | return; 95 | } 96 | 97 | void A7105_SetTxRxMode(enum TXRX_State mode) 98 | { 99 | if(mode == TX_EN) { 100 | A7105_WriteReg(A7105_0B_GPIO1_PIN1, 0x33); 101 | A7105_WriteReg(A7105_0C_GPIO2_PIN_II, 0x31); 102 | } else if (mode == RX_EN) { 103 | A7105_WriteReg(A7105_0B_GPIO1_PIN1, 0x31); 104 | A7105_WriteReg(A7105_0C_GPIO2_PIN_II, 0x33); 105 | } else { 106 | //The A7105 seems to some with a cross-wired power-amp (A7700) 107 | //On the XL7105-D03, TX_EN -> RXSW and RX_EN -> TXSW 108 | //This means that sleep mode is wired as RX_EN = 1 and TX_EN = 1 109 | //If there are other amps in use, we'll need to fix this 110 | A7105_WriteReg(A7105_0B_GPIO1_PIN1, 0x33); 111 | A7105_WriteReg(A7105_0C_GPIO2_PIN_II, 0x33); 112 | } 113 | } 114 | 115 | 116 | int A7105_Reset() 117 | { 118 | A7105_WriteReg(0x00, 0x00); 119 | delay(1); 120 | //Set both GPIO as output and low 121 | A7105_SetTxRxMode(TXRX_OFF); 122 | int result = A7105_ReadReg(0x10) == 0x9E; 123 | A7105_Strobe(A7105_STANDBY); 124 | return result; 125 | 126 | } 127 | 128 | void A7105_WriteID(unsigned long id) 129 | { 130 | CS_LO(); 131 | SPI.transfer(0x06); 132 | SPI.transfer((id >> 24) & 0xFF); 133 | SPI.transfer((id >> 16) & 0xFF); 134 | SPI.transfer((id >> 8) & 0xFF); 135 | SPI.transfer((id >> 0) & 0xFF); 136 | CS_HI(); 137 | } 138 | 139 | void A7105_SetPower(int power) 140 | { 141 | /* 142 | Power amp is ~+16dBm so: 143 | TXPOWER_100uW = -23dBm == PAC=0 TBG=0 144 | TXPOWER_300uW = -20dBm == PAC=0 TBG=1 145 | TXPOWER_1mW = -16dBm == PAC=0 TBG=2 146 | TXPOWER_3mW = -11dBm == PAC=0 TBG=4 147 | TXPOWER_10mW = -6dBm == PAC=1 TBG=5 148 | TXPOWER_30mW = 0dBm == PAC=2 TBG=7 149 | TXPOWER_100mW = 1dBm == PAC=3 TBG=7 150 | TXPOWER_150mW = 1dBm == PAC=3 TBG=7 151 | */ 152 | u8 pac, tbg; 153 | switch(power) { 154 | case 0: pac = 0; tbg = 0; break; 155 | case 1: pac = 0; tbg = 1; break; 156 | case 2: pac = 0; tbg = 2; break; 157 | case 3: pac = 0; tbg = 4; break; 158 | case 4: pac = 1; tbg = 5; break; 159 | case 5: pac = 2; tbg = 7; break; 160 | case 6: pac = 3; tbg = 7; break; 161 | case 7: pac = 3; tbg = 7; break; 162 | default: pac = 0; tbg = 0; break; 163 | }; 164 | A7105_WriteReg(0x28, (pac << 3) | tbg); 165 | } 166 | 167 | void A7105_Strobe(enum A7105_State state) 168 | { 169 | CS_LO(); 170 | SPI.transfer(state); 171 | CS_HI(); 172 | } 173 | -------------------------------------------------------------------------------- /a7105.h: -------------------------------------------------------------------------------- 1 | #ifndef _IFACE_A7105_H_ 2 | #define _IFACE_A7105_H_ 3 | 4 | #include "config.h" 5 | 6 | enum A7105_State { 7 | A7105_SLEEP = 0x80, 8 | A7105_IDLE = 0x90, 9 | A7105_STANDBY = 0xA0, 10 | A7105_PLL = 0xB0, 11 | A7105_RX = 0xC0, 12 | A7105_TX = 0xD0, 13 | A7105_RST_WRPTR = 0xE0, 14 | A7105_RST_RDPTR = 0xF0, 15 | }; 16 | 17 | enum { 18 | A7105_00_MODE = 0x00, 19 | A7105_01_MODE_CONTROL = 0x01, 20 | A7105_02_CALC = 0x02, 21 | A7105_03_FIFOI = 0x03, 22 | A7105_04_FIFOII = 0x04, 23 | A7105_05_FIFO_DATA = 0x05, 24 | A7105_06_ID_DATA = 0x06, 25 | A7105_07_RC_OSC_I = 0x07, 26 | A7105_08_RC_OSC_II = 0x08, 27 | A7105_09_RC_OSC_III = 0x09, 28 | A7105_0A_CK0_PIN = 0x0A, 29 | A7105_0B_GPIO1_PIN1 = 0x0B, 30 | A7105_0C_GPIO2_PIN_II = 0x0C, 31 | A7105_0D_CLOCK = 0x0D, 32 | A7105_0E_DATA_RATE = 0x0E, 33 | A7105_0F_PLL_I = 0x0F, 34 | A7105_10_PLL_II = 0x10, 35 | A7105_11_PLL_III = 0x11, 36 | A7105_12_PLL_IV = 0x12, 37 | A7105_13_PLL_V = 0x13, 38 | A7105_14_TX_I = 0x14, 39 | A7105_15_TX_II = 0x15, 40 | A7105_16_DELAY_I = 0x16, 41 | A7105_17_DELAY_II = 0x17, 42 | A7105_18_RX = 0x18, 43 | A7105_19_RX_GAIN_I = 0x19, 44 | A7105_1A_RX_GAIN_II = 0x1A, 45 | A7105_1B_RX_GAIN_III = 0x1B, 46 | A7105_1C_RX_GAIN_IV = 0x1C, 47 | A7105_1D_RSSI_THOLD = 0x1D, 48 | A7105_1E_ADC = 0x1E, 49 | A7105_1F_CODE_I = 0x1F, 50 | A7105_20_CODE_II = 0x20, 51 | A7105_21_CODE_III = 0x21, 52 | A7105_22_IF_CALIB_I = 0x22, 53 | A7105_23_IF_CALIB_II = 0x23, 54 | A7105_24_VCO_CURCAL = 0x24, 55 | A7105_25_VCO_SBCAL_I = 0x25, 56 | A7105_26_VCO_SBCAL_II = 0x26, 57 | A7105_27_BATTERY_DET = 0x27, 58 | A7105_28_TX_TEST = 0x28, 59 | A7105_29_RX_DEM_TEST_I = 0x29, 60 | A7105_2A_RX_DEM_TEST_II = 0x2A, 61 | A7105_2B_CPC = 0x2B, 62 | A7105_2C_XTAL_TEST = 0x2C, 63 | A7105_2D_PLL_TEST = 0x2D, 64 | A7105_2E_VCO_TEST_I = 0x2E, 65 | A7105_2F_VCO_TEST_II = 0x2F, 66 | A7105_30_IFAT = 0x30, 67 | A7105_31_RSCALE = 0x31, 68 | A7105_32_FILTER_TEST = 0x32, 69 | }; 70 | #define A7105_0F_CHANNEL A7105_0F_PLL_I 71 | 72 | enum A7105_MASK { 73 | A7105_MASK_FBCF = 1 << 4, 74 | A7105_MASK_VBCF = 1 << 3, 75 | }; 76 | 77 | void A7105_Initialize(); 78 | void A7105_Setup(); 79 | void A7105_WriteReg(u8 addr, u8 value); 80 | void A7105_WriteData(u8 *dpbuffer, u8 len, u8 channel); 81 | void A7105_ReadData(u8 *dpbuffer, u8 len); 82 | u8 A7105_ReadReg(u8 addr); 83 | void A7105_SetTxRxMode(enum TXRX_State mode); 84 | int A7105_Reset(); 85 | void A7105_WriteID(u32 id); 86 | void A7105_Strobe(enum A7105_State); 87 | void A7105_SetPower(int power); 88 | 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /config.h: -------------------------------------------------------------------------------- 1 | #ifndef _IFACE_CONFIG_H_ 2 | #define _IFACE_CONFIG_H_ 3 | 4 | #include 5 | 6 | 7 | 8 | #define NUM_TX_INPUTS 6 9 | #define NUM_INPUTS (NUM_TX_INPUTS) 10 | #define NUM_TX_BUTTONS 2 11 | 12 | #define NUM_OUT_CHANNELS 12 13 | #define NUM_VIRT_CHANNELS 10 14 | #define CHAN_MULTIPLIER 100 15 | #define CHAN_MAX_VALUE (100 * CHAN_MULTIPLIER) 16 | 17 | #define NUM_TRIMS 10 18 | #define NUM_TOGGLES 4 19 | #define MAX_POINTS 13 20 | #define NUM_MIXERS ((NUM_OUT_CHANNELS + NUM_VIRT_CHANNELS) * 4) 21 | 22 | #define MAX_PPM_IN_CHANNELS 8 23 | 24 | #define NUM_CHANNELS (NUM_OUT_CHANNELS + NUM_VIRT_CHANNELS) 25 | #define NUM_SOURCES (NUM_INPUTS + NUM_CHANNELS + MAX_PPM_IN_CHANNELS) 26 | 27 | #define TELEM_NUM_ALARMS 6 28 | 29 | typedef int8_t s8; 30 | typedef int16_t s16; 31 | typedef int32_t s32; 32 | typedef uint8_t u8; 33 | typedef uint16_t u16; 34 | typedef uint32_t u32; 35 | typedef uint64_t u64; 36 | 37 | 38 | 39 | 40 | typedef enum { 41 | MIXER_ADVANCED = 0, 42 | MIXER_STANDARD, 43 | MIXER_ALL, 44 | } MixerMode; 45 | 46 | enum TxPower { 47 | TXPOWER_100uW, 48 | TXPOWER_300uW, 49 | TXPOWER_1mW, 50 | TXPOWER_3mW, 51 | TXPOWER_10mW, 52 | TXPOWER_30mW, 53 | TXPOWER_100mW, 54 | TXPOWER_150mW, 55 | TXPOWER_LAST, 56 | }; 57 | 58 | enum ModelType { 59 | MODELTYPE_HELI, 60 | MODELTYPE_PLANE, 61 | MODELTYPE_LAST, 62 | }; 63 | 64 | 65 | enum ProtoCmds { 66 | PROTOCMD_INIT, 67 | PROTOCMD_DEINIT, 68 | PROTOCMD_BIND, 69 | PROTOCMD_CHECK_AUTOBIND, 70 | PROTOCMD_NUMCHAN, 71 | PROTOCMD_DEFAULT_NUMCHAN, 72 | PROTOCMD_CURRENT_ID, 73 | PROTOCMD_SET_TXPOWER, 74 | PROTOCMD_GETOPTIONS, 75 | PROTOCMD_SETOPTIONS, 76 | PROTOCMD_TELEMETRYSTATE, 77 | PROTOCMD_RESET, 78 | }; 79 | 80 | 81 | enum TXRX_State { 82 | TXRX_OFF, 83 | TX_EN, 84 | RX_EN, 85 | }; 86 | 87 | enum { 88 | PROTO_TELEM_UNSUPPORTED = -1, 89 | PROTO_TELEM_OFF = 0, 90 | PROTO_TELEM_ON = 1, 91 | }; 92 | 93 | 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /examples/FlyskyTest/FlyskyTest.ino: -------------------------------------------------------------------------------- 1 | // BOF preprocessor bug prevent - insert me on top of your arduino-code 2 | #if 1 3 | __asm volatile ("nop"); 4 | #endif 5 | 6 | #include 7 | #if defined(__SAM3X8E__) 8 | //#include 9 | #elif defined(__AVR_ATmega2560__ ) 10 | //#include 11 | #else 12 | #include 13 | #endif 14 | 15 | #include 16 | #include "a7105.h" 17 | #include "printf.h" 18 | #include "FlyskyTransmitter.h" 19 | 20 | void setup() { 21 | 22 | 23 | Serial.begin(115200); 24 | 25 | #if !defined (__arm__) && !defined (__SAM3X8E__) 26 | printf_begin(); 27 | #endif 28 | 29 | /* pinMode(41, OUTPUT); 30 | digitalWrite(41, HIGH); 31 | delay(50); 32 | digitalWrite(41, LOW); 33 | */ 34 | 35 | A7105_Setup(); //A7105_Reset(); 36 | 37 | printf("Initializing Timer...\n"); 38 | 39 | #if defined (__AVR_ATmega2560__ ) 40 | Timer3.initialize(); 41 | #else if defined (__AVR_ATmega328P__) 42 | Timer1.initialize(); 43 | #endif 44 | 45 | // Set all channels to zero 46 | for (uint8_t i=0 ; i < NUM_OUT_CHANNELS; i++) { 47 | Channels[i] = 0; 48 | } 49 | 50 | //A7105_WriteReg(0x00, 0x00); 51 | 52 | 53 | printf("PROTOCMD_INIT...\n"); 54 | FLYSKY_Cmds(PROTOCMD_BIND); 55 | 56 | } 57 | 58 | 59 | 60 | 61 | void loop() { 62 | /*A7105_WriteReg(0x00, 0x00); 63 | delay(1); 64 | */ 65 | uint8_t chan; 66 | uint16_t val; 67 | 68 | while (1) { 69 | 70 | printf("Read value ( ): "); 71 | 72 | while (!Serial.available()) { 73 | delay(100); 74 | } 75 | 76 | chan = Serial.parseInt(); 77 | 78 | if (Serial.read() != ' ') { 79 | while (Serial.available()) Serial.read(); 80 | continue; 81 | } 82 | 83 | val = Serial.parseInt(); 84 | 85 | printf ("Channel %d, value %d\n", chan, val); 86 | 87 | if (chan < NUM_OUT_CHANNELS) 88 | Channels[chan] = val; 89 | } 90 | } 91 | 92 | -------------------------------------------------------------------------------- /model.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "model.h" 4 | 5 | const struct ModelDescriptor Model = { 6 | "V929", 7 | 4, 8 | 0x9000295C, 9 | TXPOWER_10mW 10 | 11 | 12 | }; -------------------------------------------------------------------------------- /model.h: -------------------------------------------------------------------------------- 1 | #define NUM_TRIM_ELEMS 6 2 | #define NUM_BOX_ELEMS 8 3 | #define NUM_BAR_ELEMS 8 4 | #define NUM_TOGGLE_ELEMS 4 5 | 6 | #ifndef _MODEL_H_ 7 | #define _MODEL_H_ 8 | #include 9 | #include "config.h" 10 | 11 | 12 | /* INI file consts */ 13 | /*const char *MODEL_NAME; 14 | const char *MODEL_ICON; 15 | const char *MODEL_TYPE; 16 | const char *MODEL_TEMPLATE;*/ 17 | #define UNKNOWN_ICON "media/noicon.bmp" 18 | 19 | //This cannot be computed, and must be manually updated 20 | #define NUM_PROTO_OPTS 4 21 | #define VIRT_NAME_LEN 10 22 | 23 | 24 | struct ModelDescriptor { 25 | char name[24]; 26 | //char icon[24]; 27 | //enum ModelType type; 28 | //enum Protocols protocol; 29 | //s16 proto_opts[NUM_PROTO_OPTS]; 30 | u8 num_channels; 31 | //u8 num_ppmin; 32 | //u16 ppmin_centerpw; 33 | //u16 ppmin_deltapw; 34 | //u8 train_sw; 35 | //s8 ppm_map[MAX_PPM_IN_CHANNELS]; 36 | u32 fixed_id; 37 | enum TxPower tx_power; 38 | //enum SwashType swash_type; 39 | //u8 swash_invert; 40 | //u8 swashmix[3]; 41 | //struct Trim trims[NUM_TRIMS]; 42 | //struct Mixer mixers[NUM_MIXERS]; 43 | //struct Limit limits[NUM_OUT_CHANNELS]; 44 | //char virtname[NUM_VIRT_CHANNELS][VIRT_NAME_LEN]; 45 | // struct Timer timer[NUM_TIMERS]; 46 | //u8 templates[NUM_CHANNELS]; 47 | //struct PageCfg2 pagecfg2; 48 | //u8 safety[NUM_SOURCES+1]; 49 | //u8 telem_alarm[TELEM_NUM_ALARMS]; 50 | //u16 telem_alarm_val[TELEM_NUM_ALARMS]; 51 | //u8 telem_flags; 52 | //MixerMode mixer_mode; 53 | //u32 permanent_timer; 54 | #if HAS_DATALOG 55 | //struct datalog datalog; 56 | #endif 57 | }; 58 | extern const struct ModelDescriptor Model; 59 | 60 | 61 | #endif -------------------------------------------------------------------------------- /printf.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 J. Coliz 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | version 2 as published by the Free Software Foundation. 7 | */ 8 | 9 | /** 10 | * @file printf.h 11 | * 12 | * Setup necessary to direct stdout to the Arduino Serial library, which 13 | * enables 'printf' 14 | */ 15 | 16 | #ifndef __PRINTF_H__ 17 | #define __PRINTF_H__ 18 | 19 | #ifdef ARDUINO 20 | 21 | 22 | #if defined (__SAM3X8E__) 23 | 24 | #include 25 | void p(char *fmt, ... ){ 26 | char buf[128]; // resulting string limited to 128 chars 27 | va_list args; 28 | va_start (args, fmt ); 29 | vsnprintf(buf, 128, fmt, args); 30 | va_end (args); 31 | Serial.print(buf); 32 | } 33 | 34 | 35 | void p(const __FlashStringHelper *fmt, ... ){ 36 | char buf[128]; // resulting string limited to 128 chars 37 | va_list args; 38 | va_start (args, fmt); 39 | #ifdef __AVR__ 40 | vsnprintf_P(buf, sizeof(buf), (const char *)fmt, args); // progmem for AVR 41 | #else 42 | vsnprintf(buf, sizeof(buf), (const char *)fmt, args); // for the rest of the world 43 | #endif 44 | va_end(args); 45 | Serial.print(buf); 46 | } 47 | 48 | #define printf p 49 | 50 | #else 51 | 52 | int serial_putc( char c, FILE * ) 53 | { 54 | Serial.write( c ); 55 | 56 | return c; 57 | } 58 | 59 | void printf_begin(void) 60 | { 61 | fdevopen( &serial_putc, 0 ); 62 | } 63 | 64 | #endif 65 | 66 | #else 67 | #error This example is only for use on Arduino. 68 | #endif // ARDUINO 69 | 70 | #endif // __PRINTF_H__ 71 | --------------------------------------------------------------------------------