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