Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 40 additions & 4 deletions Multiprotocol/FX_nrf24l01.ino
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ Multiprotocol is distributed in the hope that it will be useful,
#define FX_QF012_PACKET_PERIOD 12194
#define FX_QF012_RX_PAYLOAD_SIZE 3

#define FX_BM26_BIND_CHANNEL 40
#define FX_BM26_PACKET_PERIOD 14066

//#define FORCE_FX620_ID
//#define FORCE_FX9630_ID
//#define FORCE_QIDI_ID
Expand Down Expand Up @@ -90,6 +93,12 @@ static void __attribute__((unused)) FX_send_packet()
packet[1] = convert_channel_8b(AILERON);
packet[2] = 0xFF - convert_channel_8b(ELEVATOR);
packet[3] = convert_channel_8b(RUDDER);
if ( sub_protocol == FX_BM26 ) // BM26 Ail, Elev, Rud range between 0x00-0x3F-0x7F
{
packet[1] >>= 1;
packet[2] >>= 1;
packet[3] >>= 1;
}
val = trim_ch==0 ? 0x20 : (convert_channel_8b(trim_ch + CH6) >> 2); // no trim on Throttle
packet[4] = val; // Trim for channel x 0C..20..34
packet[5] = (trim_ch << 4) // channel x << 4
Expand All @@ -103,6 +112,22 @@ static void __attribute__((unused)) FX_send_packet()
else if (sub_protocol == FX_QF012)
packet[5] |= GET_FLAG(CH7_SW, 0x40) // QF012 invert flight
| GET_FLAG(CH8_SW, 0x80); // QF012 Restore fine tunning midpoint
else if ( sub_protocol == FX_BM26 )
{
if ( packet_count == 0 || packet_count > 3 ) {
packet[5] = 0x00;
packet_count = 0;
}
else packet[5] += 0x40;
packet_count++;
// BM26 P51=>0:beginner(6G), 1:mid(3D), 2:expert(Gyro off)
packet[5] |= (Channel_data[CH6] < CHANNEL_MIN_COMMAND ? 0x08 : (Channel_data[CH6] > CHANNEL_MAX_COMMAND ? 0x0C : 0x0A));

packet[6] = (Channel_data[CH5] > CHANNEL_MAX_COMMAND ? 0x20 : 0x00 ) // 6G Roll
| (Channel_data[CH7] > CHANNEL_MAX_COMMAND ? 0x00 : 0x08 ) // Light control switch, default on
| (Channel_data[CH8] > CHANNEL_MAX_COMMAND ? 0x00 : 0x10 ) // Turn signal switch, default on
| (Channel_data[CH9] > CHANNEL_MAX_COMMAND ? 0x01 : 0x00 ); // Gyro Calibration
}
}
else // FX816 & FX620
{
Expand Down Expand Up @@ -164,6 +189,8 @@ static void __attribute__((unused)) FX_send_packet()
val = val ^ 0xFF;
packet[last_packet_idx]=val;

if ( IS_BIND_IN_PROGRESS && sub_protocol == FX_BM26 ) packet[7] = packet[6];

//Debug
#if 0
for(uint8_t i=0;i<packet_length;i++)
Expand Down Expand Up @@ -194,6 +221,13 @@ static void __attribute__((unused)) FX_RF_init()
packet_period = FX620_BIND_PACKET_PERIOD;
packet_length = FX620_PAYLOAD_SIZE;
}
else if (sub_protocol == FX_BM26)
{
XN297_SetTXAddr((uint8_t *)"\x12\x34\x10\x10", 4);
XN297_RFChannel(FX_BM26_BIND_CHANNEL);
packet_period = FX_BM26_PACKET_PERIOD;
packet_length = FX9630_PAYLOAD_SIZE;
}
else // FX9630 & FX_Q560 & FX_QF012
{
XN297_SetTXAddr((uint8_t *)"\x56\x78\x90\x12", 4);
Expand Down Expand Up @@ -229,7 +263,7 @@ static void __attribute__((unused)) FX_initialize_txid()
else // FX9630 & FX_Q560 & FX_QF012
{
//??? Need to find out how the first RF channel is calculated ???
hopping_frequency[0] = 0x13;
hopping_frequency[0] = sub_protocol == FX_BM26? 0x0C : 0x13;
//Other 2 RF channels are sent during the bind phase so they can be whatever
hopping_frequency[1] = RX_num & 0x0F + 0x1A;
hopping_frequency[2] = rx_tx_addr[3] & 0x0F + 0x38;
Expand All @@ -245,7 +279,8 @@ static void __attribute__((unused)) FX_initialize_txid()
//memcpy(rx_tx_addr,(uint8_t*)"\x38\xC7\x6D\x8D", 4);
//memcpy(hopping_frequency,"\x0D\x20\x3A", FX9630_NUM_CHANNELS);
#endif
}
// BM26 rx_tx_addr: "\x17\x03\x00\x00", hopping_frequency: 0x0C,0x30,0x43(12,48,67)
}
}

uint16_t FX_callback()
Expand Down Expand Up @@ -288,9 +323,9 @@ uint16_t FX_callback()
debug("RX");
if(XN297_ReadPayload(packet_in, FX_QF012_RX_PAYLOAD_SIZE))
{//Good CRC
//packets: A5 00 11 -> A5 01 11
telemetry_link = 1;
v_lipo1 = packet_in[1] ? 60:81; // low voltage 3.7V
if ( sub_protocol == FX_BM26 ) v_lipo1 = packet_in[0] < packet_in[2]? 60:81; // packets: AA 00 55 -> 55 00 AA
else v_lipo1 = packet_in[1] ? 60:81; //packets: A5 00 11 -> A5 01 11 // low voltage 3.7V
#if 0
for(uint8_t i=0; i < FX_QF012_RX_PAYLOAD_SIZE; i++)
debug(" %02X", packet_in[i]);
Expand Down Expand Up @@ -328,6 +363,7 @@ void FX_init()
FX_RF_init();
hopping_frequency_no = 0;
bind_counter=FX_BIND_COUNT;
packet_count = 0;
#ifdef FX_HUB_TELEMETRY
RX_RSSI = 100; // Dummy value
phase = FX_DATA;
Expand Down
3 changes: 2 additions & 1 deletion Multiprotocol/Multi.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
55,Frsky_RX,Multi,CloneTX,EraseTX,CPPM
56,AFHDS2A_RX,Multi,CPPM
57,HoTT,Sync,No_Sync
58,FX,816,620,9630,Q560,QF012
58,FX,816,620,9630,Q560,QF012,BM26
59,Bayang_RX,Multi,CPPM
60,Pelikan,Pro,Lite,SCX24
61,EazyRC
Expand Down Expand Up @@ -102,3 +102,4 @@
104,KAMTOM
105,Shenqi2
106,WL91x

4 changes: 2 additions & 2 deletions Multiprotocol/Multi_Protos.ino
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ const char STR_SUBTYPE_JJRC345[] = "\x08""JJRC345\0""SkyTmblr";
const char STR_SUBTYPE_MOULDKG[] = "\x05""A4444""D4444""A664\0";
const char STR_SUBTYPE_KF606[] = "\x06""KF606\0""MIG320""ZCZ50\0";
const char STR_SUBTYPE_E129[] = "\x04""E129""C186";
const char STR_SUBTYPE_FX[] = "\x05""816\0 ""620\0 ""9630\0""Q560\0""QF012";
const char STR_SUBTYPE_FX[] = "\x05""816\0 ""620\0 ""9630\0""Q560\0""QF012""BM26\0";
const char STR_SUBTYPE_SGF22[] = "\x04""F22\0""F22S""J20\0""CX10";
const char STR_SUBTYPE_JIABAILE[] = "\x04""Std\0""Gyro";
#define NO_SUBTYPE nullptr
Expand Down Expand Up @@ -345,7 +345,7 @@ const mm_protocol_definition multi_protocols[] = {
{PROTO_FUTABA, STR_FUTABA, STR_SUBTYPE_FUTABA, 1, OPTION_RFTUNE, 1, 1, SW_CC2500, SFHSS_init, SFHSS_callback },
#endif
#if defined(FX_NRF24L01_INO)
{PROTO_FX, STR_FX, STR_SUBTYPE_FX, 5, OPTION_NONE, 0, 0, SW_NRF, FX_init, FX_callback },
{PROTO_FX, STR_FX, STR_SUBTYPE_FX, 6, OPTION_NONE, 0, 0, SW_NRF, FX_init, FX_callback },
#endif
#if defined(FY326_NRF24L01_INO)
{PROTO_FY326, STR_FY326, STR_SUBTYPE_FY326, 2, OPTION_NONE, 0, 0, SW_NRF, FY326_init, FY326_callback },
Expand Down
1 change: 1 addition & 0 deletions Multiprotocol/Multiprotocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,7 @@ enum FX
FX9630 = 2,
FX_Q560 = 3,
FX_QF012 = 4,
FX_BM26 = 5,
};
enum SGF22
{
Expand Down
4 changes: 3 additions & 1 deletion Multiprotocol/XK2_ccnrf.ino
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ static void __attribute__((unused)) XK2_send_packet()
packet[5] |= 0x10; //Gyro off (senior mode)
else if(Channel_data[CH6] > CHANNEL_MIN_COMMAND)
packet[5] |= 0x08; //3D
packet[5] |= GET_FLAG(CH9_SW, 0x04) ; //SkyViper Vector stunt flag
//SkyViper Vector: Telemetry A1 value is changed from 8.4v to 7.1v when the battery voltage is less than 3.3v
//Requiest telemetry flag
packet[6] = 0x01;
//RXID checksum
Expand Down Expand Up @@ -428,4 +430,4 @@ P[6] = 00 telemetry nok
01 telemetry ok but sometimes switch to 1 also when telemetry is nok...
P[7] = C8 -> sum RX_ID[0..2]
P[8] = sum P[0..7] + TX_ID[0] - TX_ID[1] + TX_ID[2] + 21 +10
*/
*/
1 change: 1 addition & 0 deletions Multiprotocol/_Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,7 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
FX9630
Q560
QF012
BM26
PROTO_FY326
FY326
FY319
Expand Down
21 changes: 17 additions & 4 deletions Protocols_Details.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ CFlie|AIR|38|CFlie||||||||NRF24L01|
[FrskyX2](Protocols_Details.md#FRSKYX2---64)||64|CH_16|CH_8|EU_16|EU_8|Cloned|Cloned_8|||CC2500|
[Frsky_RX](Protocols_Details.md#FRSKY_RX---55)||55|Multi|CloneTX|EraseTX|CPPM|||||CC2500|
[Futaba/SFHSS](Protocols_Details.md#Futaba---21)||21|SFHSS||||||||CC2500|
[FX](Protocols_Details.md#FX---58)||28|816|620|9630|Q560|QF012||||NRF24L01|
[FX](Protocols_Details.md#FX---58)||28|816|620|9630|Q560|QF012|BM26|||NRF24L01|
[FY326](Protocols_Details.md#FY326---20)||20|FY326|FY319|||||||NRF24L01|
[GD00X](Protocols_Details.md#GD00X---47)||47|GD_V1*|GD_V2*|||||||NRF24L01|XN297L
[GW008](Protocols_Details.md#GW008---32)||32|||||||||NRF24L01|XN297
Expand Down Expand Up @@ -1574,9 +1574,9 @@ If a CC2500 is installed it will be used for this sub protocol. Option in this c

If only a NRF24L01 is installed then this sub protocol might be problematic because it is using the xn297L emulation with a transmission speed of 250kbps which doesn't work very well with every NRF24L01, this is an hardware issue with the authenticity and accuracy of the components.

CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
A|E|T|R|Rate|Mode|Hover|Light
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|Rate|Mode|Hover|Light|Stunt

The plane does not need to be bound each time if it is powered on **after** the radio/protocol is on.

Expand All @@ -1586,6 +1586,8 @@ The rudder trim is driven from the rudder channel to increase the range (Origina

Mode: -100%=6G, 0%=3D, +100%=Gyro off (Senior mode)

CH9 - Stunt is for SkyViper Vector.

### Sub_protocol X4 - *0*
Transmitter: XK X4-A160, X5S, model: XK A160S, XK A280, XK A300

Expand Down Expand Up @@ -1890,6 +1892,17 @@ Gyro: -100%=6G, 0%=3D+Gyro, +100%=3D

Reset: Restore fine tunning midpoint

### Sub_protocol BM26 - *5*
Model: BM26 P51

Telemetry supported. The plane sends a battery status of good->empty which is visible in A1 (good=4.2V->empty=3.1V) and RSSI gets a dummy value of 100.

CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP|GYRO|Light Switch|Turning Light switch|Gyro Calibration

Gyro: -100%=6G, 0%=3D+Gyro, +100%=3D

## FY326 - *20*

### Sub_protocol FY326 - *0*
Expand Down