2 This project is free software: you can redistribute it and/or modify
3 it under the terms of the GNU General Public License as published by
4 the Free Software Foundation, either version 3 of the License, or
5 (at your option) any later version.
7 Multiprotocol is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
12 You should have received a copy of the GNU General Public License
13 along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
16 #if defined(WFLY2_A7105_INO)
18 #include "iface_a7105.h"
20 //#define WFLY2_FORCE_ID
22 //WFLY2 constants & variables
23 #define WFLY2_BIND_COUNT 2777 // abort bind after 10sec
24 #define WFLY2_PACKET_SIZE 32
32 static void __attribute__((unused)) WFLY2_build_packet()
34 static uint16_t pseudo=0;
37 if(IS_BIND_IN_PROGRESS && bind_counter)
43 A7105_WriteID(MProtocol_id);
48 memset(packet,0x00,WFLY2_PACKET_SIZE);
50 if(IS_BIND_IN_PROGRESS)
53 packet[0] = 0x0F; // Bind packet
56 packet[1] = rx_tx_addr[3];
57 packet[2] = rx_tx_addr[2];
58 packet[3] = rx_tx_addr[1];
59 //packet[4] = 0x00; // Should be rx_tx_addr[0]&0x0F but bind is already using 0x00 so ....
65 rf_ch_num = (hopping_frequency_no<<1)+0x08;
66 packet[6] = rf_ch_num;
67 hopping_frequency_no++;
68 if(hopping_frequency_no > 0x17) hopping_frequency_no=0x00;
75 uint16_t high_bit=(pseudo & 0x8000) ^ 0x8000; // toggle 0x8000 every other line
77 if( (pseudo & 0x8000) || pseudo == 0 ) pseudo ^= 0x8A87; // Randomisation, pseudo==0 is a guess but would give the start value seen on the dump when P[2]P[1]=0 at init and will prevent a lock up
78 pseudo |= high_bit; // include toggle
80 packet[2] = pseudo>>8;
83 int8_t prev = rf_ch_num & 0x1F;
84 rf_ch_num = (pseudo ^ (pseudo >> 7));
85 rf_ch_num = ((rf_ch_num>>1)&0x08) | (rf_ch_num & 0x47);
86 rf_ch_num = ((rf_ch_num>>2)&0x10) | (rf_ch_num & 0x1F);
87 rf_ch_num ^= rx_tx_addr[3] & 0x1F;
88 if(abs((int8_t)rf_ch_num-prev) <= 9)
98 packet[3] = rx_tx_addr[3];
99 packet[4] = rx_tx_addr[2] & 0x03;
102 if(prev_option!=option)
103 {//Set the RX PPM/WBUS on change
104 packet[0] = 0x05; //PPM/WBUS packet
107 packet[6] = 0x01; // PPM
109 packet[6] = 0x00; // WBUS
110 prev_option = option;
113 {//Normal or Failsafe packets
116 //packet[0] = 0x00; // Normal packet
118 #ifdef FAILSAFE_ENABLE
119 #define WFLY2_NUM_FS_PKTS 2 //the original TX sends 4 but that's not needed...
120 if(IS_FAILSAFE_VALUES_on && packet_sent >= WFLY2_NUM_FS_PKTS) //Failsafe packet arrived from radio
121 packet_sent = 0; // send FS config packets
123 if(packet_sent < WFLY2_NUM_FS_PKTS)
124 {// Send failsafe packets
125 packet[0] = 0x01; //Failsafe packet
126 packet[5] = 0x08 | packet_sent;
127 /*if(packet_sent > 1) // needed when more than 2 FS packets are sent
129 packet[5] |= 0x50; // all channels in failsafe
130 packet[6] = 0x55; // all channels in failsafe
135 for(uint8_t i = 0; i < 6; i++)
138 if(Failsafe_data[i+packet_sent*6] == FAILSAFE_CHANNEL_NOPULSES) //no pulse value = 2
140 else if(Failsafe_data[i+packet_sent*6] != FAILSAFE_CHANNEL_HOLD) //hold value = 0
141 val |= 0x40; //fs value = 1
142 //debug("ch%d=%04X, val=%02X | ",i+1+packet_sent*6, Failsafe_data[i+packet_sent*6],val);
150 //debugln("5=%02X, 6=%02X", packet[5], packet[6]);
154 //10 channels -100%=0x2C1...0%=0x800...+100%=0xD3F
155 for(uint8_t i = 0; i < 5; i++)
157 uint16_t temp=convert_channel_16b_nolimit(i*2 , 0x2C1, 0xD3F, IS_FAILSAFE_VALUES_on);
158 packet[5 + offset + i*3] = temp&0xFF; // low byte
159 packet[7 + offset + i*3] = (temp>>8)&0x0F; // high byte
160 temp=convert_channel_16b_nolimit(i*2+1, 0x2C1, 0xD3F, IS_FAILSAFE_VALUES_on);
161 packet[6 + offset + i*3] = temp&0xFF; // low byte
162 packet[7 + offset + i*3] |= (temp>>4)&0xF0; // high byte
165 #ifdef FAILSAFE_ENABLE
166 if(packet_sent >= WFLY2_NUM_FS_PKTS)
170 //Unknown bytes 20+offset..31
176 debug("ch=%02X,%02X P=",rf_ch_num,(rf_ch_num<<1)+0x10);
177 for(uint8_t i=0; i<WFLY2_PACKET_SIZE; i++)
178 debug("%02X ", packet[i]);
183 #ifdef WFLY2_HUB_TELEMETRY
184 static void __attribute__((unused)) WFLY2_Send_Telemetry()
186 //Incoming packet values
187 v_lipo1=packet[3]<<1; // RX_batt *10 in V
188 v_lipo2=packet[5]<<1; // Ext_batt*10 in V
189 RX_RSSI=(255-packet[7])>>1; // Looks to be the RX RSSI value direct from A7105
192 TX_RSSI=255-A7105_ReadReg(A7105_1D_RSSI_THOLD);
194 telemetry_counter++; // LQI counter
200 telemetry_counter = 100;
205 #define WFLY2_PACKET_PERIOD 3600 //3600
206 #define WFLY2_BUFFER_TIME 1500 //1500
207 #define WFLY2_WRITE_TIME 800 //942
209 uint16_t WFLY2_callback()
214 #ifndef FORCE_WFLY2_TUNING
215 A7105_AdjustLOBaseFreq(1);
221 telemetry_set_input_sync(WFLY2_PACKET_PERIOD);
224 WFLY2_build_packet();
226 //Fill the TX buffer without sending
227 A7105_WriteData(WFLY2_PACKET_SIZE,0);
229 #ifdef WFLY2_HUB_TELEMETRY
232 if(packet_count>=100)
235 TX_LQI=telemetry_counter;
236 if(telemetry_counter==0)
238 telemetry_counter = 0;
242 phase++; // WFLY2_PLL_TX
243 return WFLY2_BUFFER_TIME;
247 status=A7105_ReadReg(A7105_00_MODE);
248 //debugln("S:%02X", status);
251 A7105_Strobe(A7105_PLL);
253 //Read incoming packet even if bad/not present to not change too much the TX timing, might want to reorg the code...
254 A7105_ReadData(WFLY2_PACKET_SIZE);
257 if((status & 0x21)==0)
258 { // Packet received and CRC OK
262 for(uint8_t i=0; i<WFLY2_PACKET_SIZE-20; i++) // Can't send the full telemetry at full speed
263 debug(" %02X", packet[i]);
267 if(IS_BIND_IN_PROGRESS)
269 if(packet[0]==0x0F && packet[1]==rx_tx_addr[3] && packet[2]==rx_tx_addr[2] && packet[3]==rx_tx_addr[1] && packet[4]==0x00)
271 bind_counter=1; // End bind
272 debugln("Bind done");
273 //packet[5..7] contains the RXID
276 #ifdef WFLY2_HUB_TELEMETRY
278 if(packet[0]==0 && packet[1]==rx_tx_addr[3] && packet[2]==(rx_tx_addr[2] & 0x03))
279 {//Packet match the ID
280 WFLY2_Send_Telemetry(); // Packet looks good do send telem to the radio
286 A7105_WriteReg(A7105_0F_PLL_I, (rf_ch_num<<1)+0x10);
290 A7105_SetTxRxMode(TX_EN);
291 A7105_Strobe(A7105_TX);
294 return WFLY2_WRITE_TIME;
297 //Wait for TX completion
299 while ((uint16_t)((uint16_t)micros()-start) < 700) // Wait max 700µs
300 if(!(A7105_ReadReg(A7105_00_MODE) & 0x01))
304 A7105_SetTxRxMode(RX_EN);
305 A7105_Strobe(A7105_RX);
308 return WFLY2_PACKET_PERIOD-WFLY2_WRITE_TIME-WFLY2_BUFFER_TIME;
310 return WFLY2_PACKET_PERIOD; // never reached, please the compiler
317 #ifdef WFLY2_FORCE_ID
318 MProtocol_id = 0x50002313; //Richard
319 //MProtocol_id = 0x50000223; //Pascal
321 MProtocol_id &= 0x00FFFFFF; // Since the bind ID starts with 50, let's keep only the last 3 bytes of the ID
322 MProtocol_id |= 0x50000000; // As recommended on the A7105 datasheet
323 set_rx_tx_addr(MProtocol_id); // Update the ID
325 if(IS_BIND_IN_PROGRESS)
326 A7105_WriteID(0x50FFFFFE); // Bind ID
328 A7105_WriteID(MProtocol_id);
330 hopping_frequency_no=0;
332 bind_counter = WFLY2_BIND_COUNT;
335 #ifdef WFLY2_HUB_TELEMETRY