diff --git a/Multiprotocol/BUGSMINI_nrf24l01.ino b/Multiprotocol/BUGSMINI_nrf24l01.ino
new file mode 100644
index 0000000..170ef46
--- /dev/null
+++ b/Multiprotocol/BUGSMINI_nrf24l01.ino
@@ -0,0 +1,364 @@
+/*
+ This project is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Multiprotocol is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Multiprotocol. If not, see .
+ */
+// compatible with MJX Bugs 3 Mini and Bugs 3H
+
+#if defined(BUGSMINI_NRF24L01_INO)
+
+#include "iface_nrf24l01.h"
+
+#define BUGSMINI_INITIAL_WAIT 500
+#define BUGSMINI_PACKET_INTERVAL 6840
+#define BUGSMINI_WRITE_WAIT 2000
+#define BUGSMINI_TX_PAYLOAD_SIZE 24
+#define BUGSMINI_RX_PAYLOAD_SIZE 16
+#define BUGSMINI_NUM_RF_CHANNELS 15
+#define BUGSMINI_ADDRESS_SIZE 5
+
+static uint8_t BUGSMINI_armed, BUGSMINI_arm_flags;
+static uint8_t BUGSMINI_arm_channel_previous;
+static uint8_t BUGSMINI_txid[3];
+static uint8_t BUGSMINI_txhash;
+
+enum {
+ BUGSMINI_BIND1,
+ BUGSMINI_BIND2,
+ BUGSMINI_DATA1,
+ BUGSMINI_DATA2
+};
+
+#define BUGSMINI_CH_SW_ARM CH5_SW
+#define BUGSMINI_CH_SW_ANGLE CH6_SW
+#define BUGSMINI_CH_SW_FLIP CH7_SW
+#define BUGSMINI_CH_SW_PICTURE CH8_SW
+#define BUGSMINI_CH_SW_VIDEO CH9_SW
+#define BUGSMINI_CH_SW_LED CH10_SW
+
+// flags packet[12]
+#define BUGSMINI_FLAG_FLIP 0x08 // automatic flip
+#define BUGSMINI_FLAG_MODE 0x04 // low/high speed select (set is high speed)
+#define BUGSMINI_FLAG_VIDEO 0x02 // toggle video
+#define BUGSMINI_FLAG_PICTURE 0x01 // toggle picture
+
+// flags packet[13]
+#define BUGSMINI_FLAG_LED 0x80 // enable LEDs
+#define BUGSMINI_FLAG_ARM 0x40 // arm (toggle to turn on motors)
+#define BUGSMINI_FLAG_DISARM 0x20 // disarm (toggle to turn off motors)
+#define BUGSMINI_FLAG_ANGLE 0x02 // angle/acro mode (set is angle mode)
+
+static void __attribute__((unused)) BUGSMINI_init()
+{
+ NRF24L01_Initialize();
+ NRF24L01_SetTxRxMode(TX_EN);
+ NRF24L01_FlushTx();
+ NRF24L01_FlushRx();
+ NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
+ NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
+ NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
+ NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, BUGSMINI_RX_PAYLOAD_SIZE); // bytes of data payload for rx pipe 1
+ NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, 0x07);
+ NRF24L01_SetBitrate(NRF24L01_BR_1M);
+ NRF24L01_SetPower();
+ NRF24L01_Activate(0x73); // Activate feature register
+ NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
+ NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x00); // Set feature bits on
+}
+
+static void __attribute__((unused)) BUGSMINI_check_arming()
+{
+ uint8_t arm_channel = BUGSMINI_CH_SW_ARM;
+
+ if (arm_channel != BUGSMINI_arm_channel_previous)
+ {
+ BUGSMINI_arm_channel_previous = arm_channel;
+ if (arm_channel)
+ {
+ BUGSMINI_armed = 1;
+ BUGSMINI_arm_flags ^= BUGSMINI_FLAG_ARM;
+ }
+ else
+ {
+ BUGSMINI_armed = 0;
+ BUGSMINI_arm_flags ^= BUGSMINI_FLAG_DISARM;
+ }
+ }
+}
+
+static void __attribute__((unused)) BUGSMINI_send_packet(uint8_t bind)
+{
+ BUGSMINI_check_arming(); // sets globals arm_flags and armed
+
+ uint16_t aileron = convert_channel_16b_limit(AILERON,500,0);
+ uint16_t elevator = convert_channel_16b_limit(ELEVATOR,0,500);
+ uint16_t throttle = BUGSMINI_armed ? convert_channel_16b_limit(THROTTLE,0,500) : 0;
+ uint16_t rudder = convert_channel_16b_limit(RUDDER,500,0);
+
+ packet[1] = BUGSMINI_txid[0];
+ packet[2] = BUGSMINI_txid[1];
+ packet[3] = BUGSMINI_txid[2];
+ if(bind)
+ {
+ packet[4] = 0x00;
+ packet[5] = 0x7d;
+ packet[6] = 0x7d;
+ packet[7] = 0x7d;
+ packet[8] = 0x20;
+ packet[9] = 0x20;
+ packet[10]= 0x20;
+ packet[11]= 0x40;
+ packet[12]^= 0x40; // alternating freq hopping flag
+ packet[13]= 0x60;
+ packet[14]= 0x00;
+ packet[15]= 0x00;
+ }
+ else
+ {
+ packet[4] = throttle >> 1;
+ packet[5] = rudder >> 1;
+ packet[6] = elevator >> 1;
+ packet[7] = aileron >> 1;
+ packet[8] = 0x20 | (aileron << 7);
+ packet[9] = 0x20 | (elevator << 7);
+ packet[10]= 0x20 | (rudder << 7);
+ packet[11]= 0x40 | (throttle << 7);
+ packet[12]= 0x80 | (packet[12] ^ 0x40) // bugs 3 H doesn't have 0x80 ?
+ | BUGSMINI_FLAG_MODE
+ | GET_FLAG(BUGSMINI_CH_SW_PICTURE, BUGSMINI_FLAG_PICTURE)
+ | GET_FLAG(BUGSMINI_CH_SW_VIDEO, BUGSMINI_FLAG_VIDEO);
+ if(BUGSMINI_armed)
+ packet[12] |= GET_FLAG(BUGSMINI_CH_SW_FLIP, BUGSMINI_FLAG_FLIP);
+ packet[13] = BUGSMINI_arm_flags
+ | GET_FLAG(BUGSMINI_CH_SW_LED, BUGSMINI_FLAG_LED)
+ | GET_FLAG(BUGSMINI_CH_SW_ANGLE, BUGSMINI_FLAG_ANGLE);
+
+ packet[14] = 0;
+ packet[15] = 0; // 0x53 on bugs 3 H ?
+ }
+ uint8_t checksum = 0x6d;
+ for(uint8_t i=1; i < BUGSMINI_TX_PAYLOAD_SIZE; i++)
+ checksum ^= packet[i];
+ packet[0] = checksum;
+
+ if(!(packet[12]&0x40))
+ {
+ hopping_frequency_no++;
+ if(hopping_frequency_no >= BUGSMINI_NUM_RF_CHANNELS)
+ hopping_frequency_no = 0;
+ NRF24L01_WriteReg(NRF24L01_05_RF_CH, bind ? hopping_frequency[hopping_frequency_no+BUGSMINI_NUM_RF_CHANNELS] : hopping_frequency[hopping_frequency_no]);
+ }
+
+ // Power on, TX mode, 2byte CRC
+ XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
+ NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
+ NRF24L01_FlushTx();
+ XN297_WritePayload(packet, BUGSMINI_TX_PAYLOAD_SIZE);
+ NRF24L01_SetPower();
+}
+
+// compute final address for the rxid received during bind
+// thanks to Pascal for the function!
+const uint8_t PROGMEM BUGSMINI_end []= {
+ 0x2d,0x9e ,0x95,0xa4 ,0x9c,0x5c ,0xb4,0xa6 ,0xa9,0xce ,0x56,0x2b ,0x3e,0x73 ,0xb8,0x95 ,0x6a,0x82,
+ 0x94,0x37 ,0x3d,0x5a ,0x4b,0xb2 ,0x69,0x49 ,0xc2,0x24 ,0x6b,0x3d ,0x23,0xc6 ,0x9e,0xa3 ,0xa4,0x98,
+ 0x5c,0x9e ,0xa6,0x52 ,0xce,0x76 ,0x2b,0x4b ,0x73,0x3a };
+static void __attribute__((unused)) BUGSMINI_make_address()
+{
+ uint8_t start, length, index;
+
+ //read rxid
+ uint8_t base_adr=BUGSMINI_EEPROM_OFFSET+RX_num*2;
+ uint8_t rxid_high = eeprom_read_byte((EE_ADDR)(base_adr+0));
+ uint8_t rxid_low = eeprom_read_byte((EE_ADDR)(base_adr+1));
+
+ if(rxid_high==0x00 || rxid_high==0xFF)
+ rx_tx_addr[0]=0x52;
+ else
+ rx_tx_addr[0]=rxid_high;
+
+ rx_tx_addr[1]=BUGSMINI_txhash;
+
+ if(rxid_low==0x00 || rxid_low==0xFF)
+ rx_tx_addr[2]=0x66;
+ else
+ rx_tx_addr[2]=rxid_low;
+
+ for(uint8_t end_idx=0;end_idx<23;end_idx++)
+ {
+ //calculate sequence start
+ if(end_idx<=7)
+ start=end_idx;
+ else
+ start=(end_idx-7)*16+7;
+ //calculate sequence length
+ if(end_idx>6)
+ {
+ if(end_idx>15)
+ length=(23-end_idx)<<1;
+ else
+ length=16;
+ }
+ else
+ length=(end_idx+1)<<1;
+ //calculate first index
+ index=start-rxid_high;
+ //scan for a possible match using the current end
+ for(uint8_t i=0;i read only 12 bytes to not overwrite channel change flag
+ XN297_ReadPayload(packet, 12);
+ BUGSMINI_update_telemetry();
+ }
+ NRF24L01_SetTxRxMode(TXRX_OFF);
+ NRF24L01_SetTxRxMode(TX_EN);
+ BUGSMINI_send_packet(0);
+ phase = BUGSMINI_DATA2;
+ return BUGSMINI_WRITE_WAIT;
+ case BUGSMINI_DATA2:
+ // switch to RX mode
+ NRF24L01_SetTxRxMode(TXRX_OFF);
+ NRF24L01_SetTxRxMode(RX_EN);
+ NRF24L01_FlushRx();
+ XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO)
+ | _BV(NRF24L01_00_PWR_UP) | _BV(NRF24L01_00_PRIM_RX));
+ phase = BUGSMINI_DATA1;
+ return BUGSMINI_PACKET_INTERVAL - BUGSMINI_WRITE_WAIT;
+ }
+ return BUGSMINI_PACKET_INTERVAL;
+}
+
+#define BUGSMINI_NUM_TX_RF_MAPS 4
+// haven't figured out BUGSMINI_txid<-->rf channel mapping yet
+const uint8_t PROGMEM BUGSMINI_RF_chans[BUGSMINI_NUM_TX_RF_MAPS][BUGSMINI_NUM_RF_CHANNELS] = {
+ {0x22,0x2f,0x3a,0x14,0x20,0x2d,0x38,0x18,0x26,0x32,0x11,0x1d,0x29,0x35,0x17},
+ {0x3d,0x34,0x2b,0x22,0x19,0x40,0x37,0x2e,0x25,0x1c,0x3a,0x31,0x28,0x1f,0x16},
+ {0x12,0x20,0x2f,0x1a,0x28,0x38,0x14,0x23,0x32,0x1c,0x2c,0x3b,0x17,0x26,0x34},
+ {0x13,0x25,0x37,0x1F,0x31,0x17,0x28,0x3A,0x1C,0x2E,0x22,0x33,0x19,0x2B,0x3D} };
+const uint8_t PROGMEM BUGSMINI_bind_chans[BUGSMINI_NUM_RF_CHANNELS] = {
+ 0x1A,0x23,0x2C,0x35,0x3E,0x17,0x20,0x29,0x32,0x3B,0x14,0x1D,0x26,0x2F,0x38}; // bugs 3 mini bind channels
+const uint8_t PROGMEM BUGSMINI_tx_id[BUGSMINI_NUM_TX_RF_MAPS][3] = {
+ {0xA8,0xE6,0x32},
+ {0xdd,0xab,0xfd},
+ {0x90,0x9e,0x4a},
+ {0x20,0x28,0xBA} };
+const uint8_t PROGMEM BUGSMINI_tx_hash[BUGSMINI_NUM_TX_RF_MAPS] = { // 2nd byte of final address
+ 0x6c,0x9e,0x3d,0xb3};
+
+static void __attribute__((unused)) BUGSMINI_initialize_txid()
+{
+ // load hopping_frequency with tx channels in low part and bind channels in high part
+ for(uint8_t i=0; iCC2500
PROTO_WFLY = 40, // =>CYRF6936
PROTO_BUGS = 41, // =>A7105
+ PROTO_BUGSMINI = 42, // =>NRF24L01
PROTO_TEST = 63, // =>NRF24L01
};
@@ -516,9 +517,10 @@ enum {
#define EEPROM_BANK_OFFSET 15 // Current bank number (1 byte)
#define EEPROM_ID_VALID_OFFSET 20 // 1 byte flag that ID is valid
#define MODELMODE_EEPROM_OFFSET 30 // Autobind mode, 1 byte per model, end is 30+16=46
-#define AFHDS2A_EEPROM_OFFSET 50 // RX ID, 4 byte per model id, end is 50+64=114
-#define BUGS_EEPROM_OFFSET 114 // RX ID, 4 byte per model id, end is 114+64=178
-//#define CONFIG_EEPROM_OFFSET 178 // Current configuration of the multimodule
+#define AFHDS2A_EEPROM_OFFSET 50 // RX ID, 4 bytes per model id, end is 50+64=114
+#define BUGS_EEPROM_OFFSET 114 // TX ID, 4 bytes per model id, end is 114+64=178
+#define BUGSMINI_EEPROM_OFFSET 178 // RX ID, 2 bytes per model id, end is 178+32=210
+//#define CONFIG_EEPROM_OFFSET 210 // Current configuration of the multimodule
//****************************************
//*** MULTI protocol serial definition ***
@@ -578,6 +580,7 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
Hitec 39
WFLY 40
BUGS 41
+ BUGSMINI 42
BindBit=> 0x80 1=Bind/0=No
AutoBindBit=> 0x40 1=Yes /0=No
RangeCheck=> 0x20 1=Yes /0=No
diff --git a/Multiprotocol/Multiprotocol.ino b/Multiprotocol/Multiprotocol.ino
index 1234f5a..d74a131 100644
--- a/Multiprotocol/Multiprotocol.ino
+++ b/Multiprotocol/Multiprotocol.ino
@@ -614,7 +614,7 @@ uint8_t Update_All()
update_led_status();
#if defined(TELEMETRY)
#if ( !( defined(MULTI_TELEMETRY) || defined(MULTI_STATUS) ) )
- if( (protocol==PROTO_FRSKYD) || (protocol==PROTO_BAYANG) || (protocol==PROTO_BUGS) || (protocol==PROTO_HUBSAN) || (protocol==PROTO_BUGS) || (protocol==PROTO_AFHDS2A) || (protocol==PROTO_FRSKYX) || (protocol==PROTO_DSM) || (protocol==PROTO_CABELL) || (protocol==PROTO_HITEC))
+ if( (protocol==PROTO_FRSKYD) || (protocol==PROTO_BAYANG) || (protocol==PROTO_BUGS) || (protocol==PROTO_BUGSMINI) || (protocol==PROTO_HUBSAN) || (protocol==PROTO_AFHDS2A) || (protocol==PROTO_FRSKYX) || (protocol==PROTO_DSM) || (protocol==PROTO_CABELL) || (protocol==PROTO_HITEC))
#endif
TelemetryUpdate();
#endif
@@ -1187,6 +1187,12 @@ static void protocol_init()
remote_callback = cflie_callback;
break;
#endif
+ #if defined(BUGSMINI_NRF24L01_INO)
+ case PROTO_BUGSMINI:
+ next_callback=initBUGSMINI();
+ remote_callback = BUGSMINI_callback;
+ break;
+ #endif
#if defined(TEST_NRF24L01_INO)
case PROTO_TEST:
next_callback=initTest();
@@ -1582,7 +1588,7 @@ void pollBoot()
#if defined(TELEMETRY)
void PPM_Telemetry_serial_init()
{
- if( (protocol==PROTO_FRSKYD) || (protocol==PROTO_HUBSAN) || (protocol==PROTO_AFHDS2A) || (protocol==PROTO_BAYANG) || (protocol==PROTO_CABELL) || (protocol==PROTO_HITEC) || (protocol==PROTO_BUGS))
+ if( (protocol==PROTO_FRSKYD) || (protocol==PROTO_HUBSAN) || (protocol==PROTO_AFHDS2A) || (protocol==PROTO_BAYANG) || (protocol==PROTO_CABELL) || (protocol==PROTO_HITEC) || (protocol==PROTO_BUGS) || (protocol==PROTO_BUGSMINI))
initTXSerial( SPEED_9600 ) ;
if(protocol==PROTO_FRSKYX)
initTXSerial( SPEED_57600 ) ;
diff --git a/Multiprotocol/Telemetry.ino b/Multiprotocol/Telemetry.ino
index a879719..2d15684 100644
--- a/Multiprotocol/Telemetry.ino
+++ b/Multiprotocol/Telemetry.ino
@@ -367,7 +367,7 @@ void frsky_link_frame()
telemetry_link |= 2 ; // Send hub if available
}
else
- if (protocol==PROTO_HUBSAN||protocol==PROTO_AFHDS2A||protocol==PROTO_BAYANG||protocol==PROTO_CABELL||protocol==PROTO_HITEC||protocol==PROTO_BUGS)
+ if (protocol==PROTO_HUBSAN||protocol==PROTO_AFHDS2A||protocol==PROTO_BAYANG||protocol==PROTO_CABELL||protocol==PROTO_HITEC||protocol==PROTO_BUGS||protocol==PROTO_BUGSMINI)
{
frame[1] = v_lipo1;
frame[2] = v_lipo2;
@@ -997,7 +997,7 @@ void TelemetryUpdate()
#endif
if((telemetry_link & 1 )&& protocol != PROTO_FRSKYX)
- { // FrSkyD + Hubsan + AFHDS2A + Bayang + Cabell + Hitec + Bugs
+ { // FrSkyD + Hubsan + AFHDS2A + Bayang + Cabell + Hitec + Bugs + BugsMini
frsky_link_frame();
return;
}
diff --git a/Multiprotocol/Validate.h b/Multiprotocol/Validate.h
index 4d21bd5..c18b023 100644
--- a/Multiprotocol/Validate.h
+++ b/Multiprotocol/Validate.h
@@ -180,6 +180,7 @@
#undef ESKY150_NRF24L01_INO
#undef H8_3D_NRF24L01_INO
#undef CFLIE_NRF24L01_INO
+ #undef BUGSMINI_NRF24L01_INO
#endif
//Make sure telemetry is selected correctly
@@ -206,6 +207,9 @@
#if not defined(BAYANG_NRF24L01_INO)
#undef BAYANG_HUB_TELEMETRY
#endif
+ #if not ( defined(BUGS_A7105_INO) || defined(BUGSMINI_NRF24L01_INO) )
+ #undef BUGS_HUB_TELEMETRY
+ #endif
#if not defined(CABELL_NRF24L01_INO)
#undef CABELL_HUB_TELEMETRY
#endif
diff --git a/Multiprotocol/_Config.h b/Multiprotocol/_Config.h
index 38a2bf7..6a8d910 100644
--- a/Multiprotocol/_Config.h
+++ b/Multiprotocol/_Config.h
@@ -171,6 +171,7 @@
//The protocols below need a NRF24L01 to be installed
#define ASSAN_NRF24L01_INO
#define BAYANG_NRF24L01_INO
+#define BUGSMINI_NRF24L01_INO
#define CABELL_NRF24L01_INO
#define CFLIE_NRF24L01_INO
#define CG023_NRF24L01_INO
@@ -562,6 +563,8 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
NONE
PROTO_BUGS
NONE
+ PROTO_BUGSMINI
+ NONE
PROTO_SLT
SLT_V1
SLT_V2