mirror of
https://github.com/pascallanger/DIY-Multiprotocol-TX-Module.git
synced 2025-07-13 02:07:53 +00:00
Merge branch 'master' into bayang-analog-aux
This commit is contained in:
commit
e2eb074c18
97
.travis.yml
Normal file
97
.travis.yml
Normal file
@ -0,0 +1,97 @@
|
||||
dist: trusty
|
||||
sudo: true
|
||||
#
|
||||
language: c
|
||||
#
|
||||
env:
|
||||
global:
|
||||
- IDE_VERSION=1.8.1
|
||||
matrix:
|
||||
- BOARD="multi4in1:STM32F1:multistm32f103c:upload_method=serialMethod"
|
||||
- BOARD="multi4in1:STM32F1:multistm32f103c:upload_method=TxFlashMethod"
|
||||
- BOARD="multi4in1:avr:multixmega32d4"
|
||||
- BOARD="multi4in1:avr:multiatmega328p:bootloader=none"
|
||||
- BOARD="multi4in1:avr:multiatmega328p:bootloader=optiboot"
|
||||
#
|
||||
notifications:
|
||||
email: false
|
||||
#
|
||||
before_install:
|
||||
#
|
||||
# Fetch the tag information for the current branch
|
||||
- git fetch origin --tags
|
||||
#
|
||||
# Publish the buildroot script folder
|
||||
- chmod +x ${TRAVIS_BUILD_DIR}/buildroot/bin/*
|
||||
- export PATH=${TRAVIS_BUILD_DIR}/buildroot/bin/:${PATH}
|
||||
#
|
||||
# Install Arduino IDE
|
||||
- wget http://downloads.arduino.cc/arduino-$IDE_VERSION-linux64.tar.xz
|
||||
- tar xf arduino-$IDE_VERSION-linux64.tar.xz
|
||||
- mv arduino-$IDE_VERSION $HOME/arduino-ide
|
||||
- export PATH=$PATH:$HOME/arduino-ide
|
||||
# Set the Multi boards package URL
|
||||
- arduino --pref "boardsmanager.additional.urls=https://raw.githubusercontent.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/master/package_multi_4in1_board_index.json" --save-prefs
|
||||
#
|
||||
- if [[ "$BOARD" =~ "multi4in1:STM32F1:" ]]; then
|
||||
arduino --install-boards multi4in1:STM32F1;
|
||||
fi
|
||||
#
|
||||
- if [[ "$BOARD" =~ "multi4in1:avr:" ]]; then
|
||||
arduino --install-boards multi4in1:avr;
|
||||
fi
|
||||
#
|
||||
- buildMulti() { arduino --verify --board $BOARD Multiprotocol/Multiprotocol.ino; }
|
||||
- buildProtocol() { opt_disable $ALL_PROTOCOLS; opt_enable $1; buildMulti; }
|
||||
- buildEachProtocol() { exitcode=0; for PROTOCOL in $ALL_PROTOCOLS ; do echo Building $PROTOCOL; buildProtocol $PROTOCOL; if [ $? -ne 0 ]; then exitcode=1; fi; echo; done; return $exitcode; }
|
||||
#
|
||||
install: true
|
||||
before_script:
|
||||
#
|
||||
# Change current working directory to the build dir
|
||||
- cd ${TRAVIS_BUILD_DIR}
|
||||
# Log the initial Multi config
|
||||
- cat Multiprotocol/_Config.h
|
||||
# Derive the Multi protocols from the Multi source
|
||||
- A7105_PROTOCOLS=$(sed -n 's/[\/\/]*[[:blank:]]*#define[[:blank:]]*\([[:alnum:]_]*_A7105_INO\)\(.*\)/\1/p' Multiprotocol/_Config.h)
|
||||
- CC2500_PROTOCOLS=$(sed -n 's/[\/\/]*[[:blank:]]*#define[[:blank:]]*\([[:alnum:]_]*_CC2500_INO\)\(.*\)/\1/p' Multiprotocol/_Config.h)
|
||||
- CYRF6936_PROTOCOLS=$(sed -n 's/[\/\/]*[[:blank:]]*#define[[:blank:]]*\([[:alnum:]_]*_CYRF6936_INO\)\(.*\)/\1/p' Multiprotocol/_Config.h)
|
||||
- NRF24L01_PROTOCOLS=$(sed -n 's/[\/\/]*[[:blank:]]*#define[[:blank:]]*\([[:alnum:]_]*_NRF24L01_INO\)\(.*\)/\1/p' Multiprotocol/_Config.h)
|
||||
- if [[ "$BOARD" =~ "multi4in1:avr:multixmega32d4" ]]; then
|
||||
ALL_PROTOCOLS=$(echo $CYRF6936_PROTOCOLS);
|
||||
else
|
||||
ALL_PROTOCOLS=$(echo $A7105_PROTOCOLS $CC2500_PROTOCOLS $CYRF6936_PROTOCOLS $NRF24L01_PROTOCOLS);
|
||||
fi
|
||||
- echo $ALL_PROTOCOLS
|
||||
#
|
||||
# Enable CHECK_FOR_BOOTLOADER when needed
|
||||
- if [[ "$BOARD" =~ ":upload_method=TxFlashMethod" ]] || [[ "$BOARD" =~ ":bootloader=optiboot" ]]; then
|
||||
opt_enable CHECK_FOR_BOOTLOADER;
|
||||
fi
|
||||
#
|
||||
# Trim the build down for the Atmega328p board
|
||||
- if [[ "$BOARD" =~ "multi4in1:avr:multiatmega328p:" ]]; then
|
||||
opt_disable $ALL_PROTOCOLS;
|
||||
opt_enable FRSKYX_CC2500_INO AFHDS2A_A7105_INO MJXQ_NRF24L01_INO DSM_CYRF6936_INO;
|
||||
fi
|
||||
#
|
||||
script:
|
||||
# Build with all protocols enabled for STM32; a subset of protocols for Atmega
|
||||
- buildMulti
|
||||
#
|
||||
# Serial only
|
||||
- opt_disable ENABLE_PPM
|
||||
- opt_enable ENABLE_SERIAL
|
||||
- buildMulti
|
||||
#
|
||||
# PPM only
|
||||
- opt_enable ENABLE_PPM
|
||||
- opt_disable ENABLE_SERIAL
|
||||
- buildMulti
|
||||
#
|
||||
# Re-enable PPM and serial
|
||||
- opt_enable ENABLE_SERIAL
|
||||
- opt_enable ENABLE_PPM
|
||||
#
|
||||
# Build each protocol individually
|
||||
- buildEachProtocol
|
@ -77,6 +77,24 @@
|
||||
],
|
||||
"toolsDependencies": []
|
||||
},
|
||||
{
|
||||
"name": "Multi 4-in-1 AVR Boards",
|
||||
"architecture": "avr",
|
||||
"version": "1.0.4",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_avr_board_v1.0.4.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_avr_board_v1.0.4.tar.gz",
|
||||
"checksum": "SHA-256:6c51a4eb09bcd074cc651dab3f2356ea3afd358f6330aba0d8bdfaa75f718dbb",
|
||||
"size": "167975",
|
||||
"boards": [
|
||||
{"name": "Multi 4-in-1 (Atmega328p, 3.3V, 16MHz)"},
|
||||
{"name": "Multi 4-in-1 (OrangeRX)"}
|
||||
],
|
||||
"toolsDependencies": []
|
||||
},
|
||||
{
|
||||
"name": "Multi 4-in-1 STM32 Board",
|
||||
"architecture": "STM32F1",
|
||||
@ -266,6 +284,48 @@
|
||||
"version": "4.8.3-2014q1"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Multi 4-in-1 STM32 Board",
|
||||
"architecture": "STM32F1",
|
||||
"version": "1.0.9",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.0.9.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_stm32_board_v1.0.9.tar.gz",
|
||||
"checksum": "SHA-256:c3621d1cf6580ca5c943a67dc14dc15a60e2797a4b985548abe1919486bf4a8b",
|
||||
"size": "10324251",
|
||||
"boards": [{
|
||||
"name": "Multi 4-in-1 (STM32F103C)"
|
||||
}],
|
||||
"toolsDependencies": [{
|
||||
"packager": "arduino",
|
||||
"name": "arm-none-eabi-gcc",
|
||||
"version": "4.8.3-2014q1"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Multi 4-in-1 STM32 Board",
|
||||
"architecture": "STM32F1",
|
||||
"version": "1.1.0",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.1.0.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_stm32_board_v1.1.0.tar.gz",
|
||||
"checksum": "SHA-256:919ece2021757686e6892679956dcb8a01c9308a152167d61d9204656b4ed7ee",
|
||||
"size": "10333612",
|
||||
"boards": [{
|
||||
"name": "Multi 4-in-1 (STM32F103C)"
|
||||
}],
|
||||
"toolsDependencies": [{
|
||||
"packager": "arduino",
|
||||
"name": "arm-none-eabi-gcc",
|
||||
"version": "4.8.3-2014q1"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Multi 4-in-1 OrangeRX Board - DEPRECATED, USE MULTI 4-IN-1 AVR BOARDS PACKAGE INSTEAD",
|
||||
"architecture": "orangerx",
|
||||
|
@ -182,6 +182,11 @@ void A7105_AdjustLOBaseFreq(uint8_t cmd)
|
||||
offset=(int16_t)FORCE_HUBSAN_TUNING;
|
||||
#endif
|
||||
break;
|
||||
case PROTO_BUGS:
|
||||
#ifdef FORCE_HUBSAN_TUNING
|
||||
offset=(int16_t)FORCE_HUBSAN_TUNING;
|
||||
#endif
|
||||
break;
|
||||
case PROTO_FLYSKY:
|
||||
#ifdef FORCE_FLYSKY_TUNING
|
||||
offset=(int16_t)FORCE_FLYSKY_TUNING;
|
||||
@ -222,21 +227,40 @@ void A7105_AdjustLOBaseFreq(uint8_t cmd)
|
||||
//debugln("Channel: %d, offset: %d, bip: %2x, bfp: %4x", Channel_data[14], offset, bip, bfp);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) A7105_SetVCOBand(uint8_t vb1, uint8_t vb2)
|
||||
{ // Set calibration band value to best match
|
||||
uint8_t diff1, diff2;
|
||||
|
||||
if (vb1 >= 4)
|
||||
diff1 = vb1 - 4;
|
||||
else
|
||||
diff1 = 4 - vb1;
|
||||
|
||||
if (vb2 >= 4)
|
||||
diff2 = vb2 - 4;
|
||||
else
|
||||
diff2 = 4 - vb2;
|
||||
|
||||
if (diff1 == diff2 || diff1 > diff2)
|
||||
A7105_WriteReg(A7105_25_VCO_SBCAL_I, vb1 | 0x08);
|
||||
else
|
||||
A7105_WriteReg(A7105_25_VCO_SBCAL_I, vb2 | 0x08);
|
||||
}
|
||||
|
||||
#ifdef HUBSAN_A7105_INO
|
||||
const uint8_t PROGMEM HUBSAN_A7105_regs[] = {
|
||||
0xFF, 0x63, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF ,0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x05, 0x04, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x2B, 0xFF, 0xFF, 0x62, 0x80, 0xFF, 0xFF, 0x0A, 0xFF, 0xFF, 0x07,
|
||||
0x17, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x47, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF
|
||||
0xFF, 0x63, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF ,0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x05, 0x04, 0xFF, // 00 - 0f
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x2B, 0xFF, 0xFF, 0x62, 0x80, 0xFF, 0xFF, 0x0A, 0xFF, 0xFF, 0x07, // 10 - 1f
|
||||
0x17, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x47, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 20 - 2f
|
||||
0xFF, 0xFF // 30 - 31
|
||||
};
|
||||
#endif
|
||||
#ifdef FLYSKY_A7105_INO
|
||||
const uint8_t PROGMEM FLYSKY_A7105_regs[] = {
|
||||
0xff, 0x42, 0x00, 0x14, 0x00, 0xff, 0xff ,0x00, 0x00, 0x00, 0x00, 0x01, 0x21, 0x05, 0x00, 0x50,
|
||||
0x9e, 0x4b, 0x00, 0x02, 0x16, 0x2b, 0x12, 0x00, 0x62, 0x80, 0x80, 0x00, 0x0a, 0x32, 0xc3, 0x0f,
|
||||
0x13, 0xc3, 0x00, 0xff, 0x00, 0x00, 0x3b, 0x00, 0x17, 0x47, 0x80, 0x03, 0x01, 0x45, 0x18, 0x00,
|
||||
0x01, 0x0f
|
||||
0xff, 0x42, 0x00, 0x14, 0x00, 0xff, 0xff ,0x00, 0x00, 0x00, 0x00, 0x01, 0x21, 0x05, 0x00, 0x50, // 00 - 0f
|
||||
0x9e, 0x4b, 0x00, 0x02, 0x16, 0x2b, 0x12, 0x00, 0x62, 0x80, 0x80, 0x00, 0x0a, 0x32, 0xc3, 0x0f, // 10 - 1f
|
||||
0x13, 0xc3, 0x00, 0xff, 0x00, 0x00, 0x3b, 0x00, 0x17, 0x47, 0x80, 0x03, 0x01, 0x45, 0x18, 0x00, // 20 - 2f
|
||||
0x01, 0x0f // 30 - 31
|
||||
};
|
||||
#endif
|
||||
#ifdef AFHDS2A_A7105_INO
|
||||
@ -247,13 +271,27 @@ const uint8_t PROGMEM AFHDS2A_A7105_regs[] = {
|
||||
0x01, 0x0f // 30 - 31
|
||||
};
|
||||
#endif
|
||||
#ifdef BUGS_A7105_INO
|
||||
const uint8_t PROGMEM BUGS_A7105_regs[] = {
|
||||
0xFF, 0x42, 0x00, 0x15, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x05, 0x01, 0x50, // 00 - 0f
|
||||
0x9e, 0x4b, 0x00, 0x02, 0x16, 0x2b, 0x12, 0x40, 0x62, 0x80, 0x80, 0x00, 0x0a, 0x32, 0xc3, 0x0f, // 10 - 1f
|
||||
0x16, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x3b, 0x00, 0x0b, 0x47, 0x80, 0x03, 0x01, 0x45, 0x18, 0x00, // 20 - 2f
|
||||
0x01, 0x0f // 30 - 31
|
||||
};
|
||||
#endif
|
||||
|
||||
#define ID_NORMAL 0x55201041
|
||||
#define ID_PLUS 0xAA201041
|
||||
void A7105_Init(void)
|
||||
{
|
||||
uint8_t *A7105_Regs=0;
|
||||
uint8_t vco_calibration0, vco_calibration1;
|
||||
|
||||
#ifdef BUGS_A7105_INO
|
||||
if(protocol==PROTO_BUGS)
|
||||
A7105_Regs=(uint8_t*)BUGS_A7105_regs;
|
||||
else
|
||||
#endif
|
||||
#ifdef HUBSAN_A7105_INO
|
||||
if(protocol==PROTO_HUBSAN)
|
||||
{
|
||||
@ -310,17 +348,19 @@ void A7105_Init(void)
|
||||
A7105_WriteReg(A7105_0F_CHANNEL, 0);
|
||||
A7105_WriteReg(A7105_02_CALC,2);
|
||||
while(A7105_ReadReg(A7105_02_CALC)); // Wait for calibration to end
|
||||
// A7105_ReadReg(A7105_25_VCO_SBCAL_I);
|
||||
vco_calibration0 = A7105_ReadReg(A7105_25_VCO_SBCAL_I);
|
||||
|
||||
//VCO Bank Calibrate channel A0
|
||||
A7105_WriteReg(A7105_0F_CHANNEL, 0xa0);
|
||||
A7105_WriteReg(A7105_02_CALC, 2);
|
||||
while(A7105_ReadReg(A7105_02_CALC)); // Wait for calibration to end
|
||||
// A7105_ReadReg(A7105_25_VCO_SBCAL_I);
|
||||
vco_calibration1 = A7105_ReadReg(A7105_25_VCO_SBCAL_I);
|
||||
|
||||
//Reset VCO Band calibration
|
||||
if(protocol==PROTO_BUGS)
|
||||
A7105_SetVCOBand(vco_calibration0 & 0x07, vco_calibration1 & 0x07); // Set calibration band value to best match
|
||||
else
|
||||
if(protocol!=PROTO_HUBSAN)
|
||||
A7105_WriteReg(A7105_25_VCO_SBCAL_I,protocol==PROTO_FLYSKY?0x08:0x0A);
|
||||
A7105_WriteReg(A7105_25_VCO_SBCAL_I,protocol==PROTO_FLYSKY?0x08:0x0A); //Reset VCO Band calibration
|
||||
|
||||
A7105_SetTxRxMode(TX_EN);
|
||||
A7105_SetPower();
|
||||
|
@ -86,9 +86,14 @@ enum{
|
||||
|
||||
static void AFHDS2A_update_telemetry()
|
||||
{
|
||||
// Read TX RSSI
|
||||
int16_t temp=256-(A7105_ReadReg(A7105_1D_RSSI_THOLD)*8)/5; // value from A7105 is between 8 for maximum signal strength to 160 or less
|
||||
if(temp<0) temp=0;
|
||||
else if(temp>255) temp=255;
|
||||
TX_RSSI=temp;
|
||||
// AA | TXID | rx_id | sensor id | sensor # | value 16 bit big endian | sensor id ......
|
||||
// max 7 sensors per packet
|
||||
#ifdef AFHDS2A_FW_TELEMETRY
|
||||
#ifdef AFHDS2A_FW_TELEMETRY
|
||||
if (option & 0x80)
|
||||
{
|
||||
// forward telemetry to TX, skip rx and tx id to save space
|
||||
@ -99,8 +104,8 @@ static void AFHDS2A_update_telemetry()
|
||||
telemetry_link=2;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#ifdef AFHDS2A_HUB_TELEMETRY
|
||||
#endif
|
||||
#ifdef AFHDS2A_HUB_TELEMETRY
|
||||
for(uint8_t sensor=0; sensor<7; sensor++)
|
||||
{
|
||||
// Send FrSkyD telemetry to TX
|
||||
@ -129,7 +134,7 @@ static void AFHDS2A_update_telemetry()
|
||||
break;*/
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -169,6 +174,7 @@ static void AFHDS2A_build_bind_packet()
|
||||
|
||||
static void AFHDS2A_build_packet(uint8_t type)
|
||||
{
|
||||
uint16_t val;
|
||||
memcpy( &packet[1], rx_tx_addr, 4);
|
||||
memcpy( &packet[5], rx_id, 4);
|
||||
switch(type)
|
||||
@ -181,6 +187,12 @@ static void AFHDS2A_build_packet(uint8_t type)
|
||||
packet[9 + ch*2] = channelMicros&0xFF;
|
||||
packet[10 + ch*2] = (channelMicros>>8)&0xFF;
|
||||
}
|
||||
#ifdef AFHDS2A_LQI_CH
|
||||
// override channel with LQI
|
||||
val = 2000 - 10*RX_LQI;
|
||||
packet[9+((AFHDS2A_LQI_CH-1)*2)] = val & 0xff;
|
||||
packet[10+((AFHDS2A_LQI_CH-1)*2)] = (val >> 8) & 0xff;
|
||||
#endif
|
||||
break;
|
||||
case AFHDS2A_PACKET_FAILSAFE:
|
||||
packet[0] = 0x56;
|
||||
@ -206,10 +218,10 @@ static void AFHDS2A_build_packet(uint8_t type)
|
||||
packet[0] = 0xaa;
|
||||
packet[9] = 0xfd;
|
||||
packet[10]= 0xff;
|
||||
uint16_t val_hz=5*(option & 0x7f)+50; // option value should be between 0 and 70 which gives a value between 50 and 400Hz
|
||||
if(val_hz<50 || val_hz>400) val_hz=50; // default is 50Hz
|
||||
packet[11]= val_hz;
|
||||
packet[12]= val_hz >> 8;
|
||||
val=5*(option & 0x7f)+50; // option value should be between 0 and 70 which gives a value between 50 and 400Hz
|
||||
if(val<50 || val>400) val=50; // default is 50Hz
|
||||
packet[11]= val;
|
||||
packet[12]= val >> 8;
|
||||
if(sub_protocol == PPM_IBUS || sub_protocol == PPM_SBUS)
|
||||
packet[13] = 0x01; // PPM output enabled
|
||||
else
|
||||
@ -324,17 +336,20 @@ uint16_t ReadAFHDS2A()
|
||||
{
|
||||
if(packet[9] == 0xfc)
|
||||
packet_type=AFHDS2A_PACKET_SETTINGS; // RX is asking for settings
|
||||
#if defined(AFHDS2A_FW_TELEMETRY) || defined(AFHDS2A_HUB_TELEMETRY)
|
||||
else
|
||||
{
|
||||
// Read TX RSSI
|
||||
int16_t temp=256-(A7105_ReadReg(A7105_1D_RSSI_THOLD)*8)/5; // value from A7105 is between 8 for maximum signal strength to 160 or less
|
||||
if(temp<0) temp=0;
|
||||
else if(temp>255) temp=255;
|
||||
TX_RSSI=temp;
|
||||
AFHDS2A_update_telemetry();
|
||||
#ifdef AFHDS2A_LQI_CH
|
||||
for(uint8_t sensor=0; sensor<7; sensor++)
|
||||
{//read LQI value for RX output
|
||||
uint8_t index = 9+(4*sensor);
|
||||
if(packet[index]==AFHDS2A_SENSOR_RX_ERR_RATE)
|
||||
RX_LQI=packet[index+2];
|
||||
}
|
||||
#endif
|
||||
#if defined(AFHDS2A_FW_TELEMETRY) || defined(AFHDS2A_HUB_TELEMETRY)
|
||||
AFHDS2A_update_telemetry();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
packet_counter++;
|
||||
|
365
Multiprotocol/BUGSMINI_nrf24l01.ino
Normal file
365
Multiprotocol/BUGSMINI_nrf24l01.ino
Normal file
@ -0,0 +1,365 @@
|
||||
/*
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// 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_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 != arm_channel_previous)
|
||||
{
|
||||
arm_channel_previous = arm_channel;
|
||||
if (arm_channel)
|
||||
{
|
||||
armed = 1;
|
||||
arm_flags ^= BUGSMINI_FLAG_ARM;
|
||||
}
|
||||
else
|
||||
{
|
||||
armed = 0;
|
||||
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 = 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(armed)
|
||||
packet[12] |= GET_FLAG(BUGSMINI_CH_SW_FLIP, BUGSMINI_FLAG_FLIP);
|
||||
packet[13] = 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<length;i++)
|
||||
{
|
||||
if(index==rxid_low)
|
||||
{ //match found
|
||||
rx_tx_addr[3]=pgm_read_byte_near( &BUGSMINI_end[end_idx<<1] );
|
||||
rx_tx_addr[4]=pgm_read_byte_near( &BUGSMINI_end[(end_idx<<1)+1] );
|
||||
return;
|
||||
}
|
||||
index+=i&1?7:8; //increment index
|
||||
}
|
||||
}
|
||||
// Something wrong happened if we arrive here....
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) BUGSMINI_update_telemetry()
|
||||
{
|
||||
#if defined(BUGS_HUB_TELEMETRY)
|
||||
uint8_t checksum = 0x6d;
|
||||
for(uint8_t i=1; i<12; i++)
|
||||
checksum += packet[i];
|
||||
if(packet[0] == checksum)
|
||||
{
|
||||
RX_RSSI = packet[3];
|
||||
if(packet[11] & 0x80)
|
||||
v_lipo1 = 0xff; // Ok
|
||||
else if(packet[11] & 0x40)
|
||||
v_lipo1 = 0x80; // Warning
|
||||
else
|
||||
v_lipo1 = 0x00; // Critical
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
uint16_t BUGSMINI_callback()
|
||||
{
|
||||
uint8_t base_adr;
|
||||
switch(phase)
|
||||
{
|
||||
case BUGSMINI_BIND1:
|
||||
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
|
||||
{ // RX fifo data ready
|
||||
XN297_ReadPayload(packet, BUGSMINI_RX_PAYLOAD_SIZE);
|
||||
base_adr=BUGSMINI_EEPROM_OFFSET+RX_num*2;
|
||||
eeprom_write_byte((EE_ADDR)(base_adr+0),packet[1]); // Save rxid in EEPROM
|
||||
eeprom_write_byte((EE_ADDR)(base_adr+1),packet[2]); // Save rxid in EEPROM
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
BUGSMINI_make_address();
|
||||
XN297_SetTXAddr(rx_tx_addr, 5);
|
||||
XN297_SetRXAddr(rx_tx_addr, 5);
|
||||
phase = BUGSMINI_DATA1;
|
||||
BIND_DONE;
|
||||
return BUGSMINI_PACKET_INTERVAL;
|
||||
}
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
BUGSMINI_send_packet(1);
|
||||
phase = BUGSMINI_BIND2;
|
||||
return BUGSMINI_WRITE_WAIT;
|
||||
case BUGSMINI_BIND2:
|
||||
// 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_BIND1;
|
||||
return BUGSMINI_PACKET_INTERVAL - BUGSMINI_WRITE_WAIT;
|
||||
case BUGSMINI_DATA1:
|
||||
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
|
||||
{ // RX fifo data ready => 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; i<BUGSMINI_NUM_RF_CHANNELS;i++)
|
||||
{
|
||||
hopping_frequency[i]=pgm_read_byte_near( &BUGSMINI_RF_chans[rx_tx_addr[3]%BUGSMINI_NUM_TX_RF_MAPS][i] );
|
||||
hopping_frequency[i+BUGSMINI_NUM_RF_CHANNELS]=pgm_read_byte_near( &BUGSMINI_bind_chans[i] );
|
||||
}
|
||||
// load txid
|
||||
for(uint8_t i=0; i<sizeof(BUGSMINI_txid);i++)
|
||||
BUGSMINI_txid[i]=pgm_read_byte_near( &BUGSMINI_tx_id[rx_tx_addr[3]%BUGSMINI_NUM_TX_RF_MAPS][i] );
|
||||
//load tx_hash
|
||||
BUGSMINI_txhash = pgm_read_byte_near( &BUGSMINI_tx_hash[rx_tx_addr[3]%BUGSMINI_NUM_TX_RF_MAPS] );
|
||||
}
|
||||
|
||||
uint16_t initBUGSMINI()
|
||||
{
|
||||
BUGSMINI_initialize_txid();
|
||||
memset(packet, (uint8_t)0, BUGSMINI_TX_PAYLOAD_SIZE);
|
||||
BUGSMINI_init();
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
XN297_SetTXAddr((const uint8_t*)"mjxRC", 5);
|
||||
XN297_SetRXAddr((const uint8_t*)"mjxRC", 5);
|
||||
phase = BUGSMINI_BIND1;
|
||||
}
|
||||
else
|
||||
{
|
||||
BUGSMINI_make_address();
|
||||
XN297_SetTXAddr(rx_tx_addr, 5);
|
||||
XN297_SetRXAddr(rx_tx_addr, 5);
|
||||
phase = BUGSMINI_DATA1;
|
||||
}
|
||||
armed = 0;
|
||||
arm_flags = BUGSMINI_FLAG_DISARM; // initial value from captures
|
||||
arm_channel_previous = BUGSMINI_CH_SW_ARM;
|
||||
#ifdef BUGS_HUB_TELEMETRY
|
||||
init_frskyd_link_telemetry();
|
||||
#endif
|
||||
return BUGSMINI_INITIAL_WAIT;
|
||||
}
|
||||
|
||||
#endif
|
@ -38,7 +38,7 @@ enum BAYANG_FLAGS {
|
||||
// flags going to packet[3]
|
||||
BAYANG_FLAG_INVERTED = 0x80, // inverted flight on Floureon H101
|
||||
BAYANG_FLAG_TAKE_OFF = 0x20, // take off / landing on X16 AH
|
||||
BAYANG_FLAG_EMG_STOP = 0x04,
|
||||
BAYANG_FLAG_EMG_STOP = 0x04|0x08, // 0x08 for VISUO XS809H-W-HD-G
|
||||
};
|
||||
|
||||
enum BAYANG_OPTION_FLAGS {
|
||||
|
467
Multiprotocol/Bugs_a7105.ino
Normal file
467
Multiprotocol/Bugs_a7105.ino
Normal file
@ -0,0 +1,467 @@
|
||||
/*
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef BUGS_A7105_INO
|
||||
|
||||
//////////// rxid -> radioid algorithm //////////////////////////////
|
||||
// Hex digit 1 is periodic with length 2, and hex digit 2 is periodic
|
||||
// with length 16. However, storing the byte of those 2 digits
|
||||
// instead of manipulating bits results simpler code and smaller binary.
|
||||
const uint8_t PROGMEM BUGS_most_popular_67_cycle[]= {
|
||||
0x34, 0xc5, 0x6a, 0xb4, 0x29, 0xd5, 0x2c, 0xd3, 0x91, 0xb3, 0x6c, 0x49,
|
||||
0x52, 0x9c, 0x4d, 0x65, 0xc3, 0x4a, 0x5b, 0xd6, 0x92, 0x6d, 0x94, 0xa6,
|
||||
0x55, 0xcd, 0x2b, 0x9a, 0x36, 0x95, 0x4b, 0xd4, 0x35, 0x8d, 0x96, 0xb2,
|
||||
0xa3 };
|
||||
|
||||
static uint8_t __attribute__((unused)) BUGS_most_popular_67(uint8_t i)
|
||||
{
|
||||
uint8_t ii;
|
||||
if (i == 0)
|
||||
return 0xd2;
|
||||
else if (i == 1)
|
||||
return 0xda;
|
||||
else if (i % 16 < 2)
|
||||
{
|
||||
ii = 2 * (i / 16) + i % 16 - 2;
|
||||
if (ii % 2 == 0)
|
||||
ii += 7;
|
||||
}
|
||||
else
|
||||
ii=2 * (i / 16) + (i % 16 - 2) % 7;
|
||||
return pgm_read_byte_near( &BUGS_most_popular_67_cycle[ii]);
|
||||
}
|
||||
|
||||
static uint8_t __attribute__((unused)) BUGS_most_popular_45(uint8_t i)
|
||||
{
|
||||
if (i == 0)
|
||||
return 0xa3;
|
||||
else if (i == 1)
|
||||
return 0x86;
|
||||
else
|
||||
{
|
||||
if (i % 8 == 1)
|
||||
i -= 8;
|
||||
else
|
||||
i--;
|
||||
return BUGS_most_popular_67(i);
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t __attribute__((unused)) BUGS_most_popular_23(uint8_t i)
|
||||
{
|
||||
if (i == 0)
|
||||
return 0xb2;
|
||||
else if (i == 1)
|
||||
return 0xcb;
|
||||
else
|
||||
{
|
||||
if (i % 8 == 1)
|
||||
i -= 8;
|
||||
else
|
||||
i--;
|
||||
return BUGS_most_popular_45(i);
|
||||
}
|
||||
}
|
||||
|
||||
const uint8_t PROGMEM BUGS_most_popular_01[] = {
|
||||
0x52, 0xac, 0x59, 0xa4, 0x53, 0xab, 0x57, 0xa9,
|
||||
0x56, 0xa5, 0x5b, 0xa7, 0x5d, 0xa6, 0x58, 0xad};
|
||||
|
||||
static uint32_t __attribute__((unused)) BUGS_most_popular(uint8_t i)
|
||||
{
|
||||
i += !(i <= 127);
|
||||
uint8_t mp01=pgm_read_byte_near( &BUGS_most_popular_01[i % 16] );
|
||||
return (uint32_t) mp01 << 24 |
|
||||
(uint32_t) BUGS_most_popular_23(i) << 16 |
|
||||
(uint32_t) BUGS_most_popular_45(i) << 8 |
|
||||
BUGS_most_popular_67(i);
|
||||
}
|
||||
|
||||
static uint32_t __attribute__((unused)) BUGS_second_most_popular(uint8_t i)
|
||||
{
|
||||
if (i < 127)
|
||||
return BUGS_most_popular(i + 1);
|
||||
else if (i > 128)
|
||||
return BUGS_most_popular(i - 1);
|
||||
else
|
||||
return 0x52d6926d;
|
||||
}
|
||||
|
||||
// The 22 irregular values do not match the above periodicities. They might be
|
||||
// errors from the readout, but let us try them here as long as it is not
|
||||
// proven.
|
||||
#define BUGS_NBR_IRREGULAR 22
|
||||
const uint16_t PROGMEM BUGS_irregular_keys[BUGS_NBR_IRREGULAR] = {
|
||||
1131, 1287, 2842, 4668, 5311, 11594, 13122, 13813,
|
||||
20655, 22975, 25007, 25068, 28252, 33309, 35364, 35765,
|
||||
37731, 40296, 43668, 46540, 49868, 65535 };
|
||||
|
||||
const uint32_t PROGMEM BUGS_irregular_values[BUGS_NBR_IRREGULAR] = {
|
||||
0x52d6926d, 0xa586da34, 0x5329d52c, 0xa66c4952,
|
||||
0x536c4952, 0x524a5bd6, 0x534d65c3, 0xa9d391b3,
|
||||
0x5249529c, 0xa555cd2b, 0xac9a3695, 0x58d391b3,
|
||||
0xa791b36c, 0x53926d94, 0xa7926d94, 0xa72cd391,
|
||||
0xa9b429d5, 0x5629d52c, 0xad2b9a36, 0xa74d65c3,
|
||||
0x526d94a6, 0xad96b2a3 };
|
||||
|
||||
static uint32_t __attribute__((unused)) BUGS_is_irregular(uint16_t i)
|
||||
{
|
||||
for (uint8_t j = 0; j < BUGS_NBR_IRREGULAR; ++j)
|
||||
if (pgm_read_word_near( &BUGS_irregular_keys[j]) == i)
|
||||
return pgm_read_dword_near( &BUGS_irregular_values[j]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t __attribute__((unused)) BUGS_rxid_to_radioid(uint16_t rxid)
|
||||
{
|
||||
uint8_t block = rxid / 256;
|
||||
uint8_t second_seq_size;
|
||||
bool use_most_popular;
|
||||
|
||||
if (rxid < 32768)
|
||||
{
|
||||
second_seq_size = 128 - block;
|
||||
use_most_popular = rxid % 256 >= second_seq_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
second_seq_size = block - 127;
|
||||
use_most_popular = 255 - rxid % 256 >= second_seq_size;
|
||||
}
|
||||
uint32_t v = BUGS_is_irregular(rxid);
|
||||
if (!v)
|
||||
{
|
||||
if (use_most_popular)
|
||||
v = BUGS_most_popular(rxid % 255);
|
||||
else
|
||||
v = BUGS_second_most_popular(rxid % 255);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
//////////// rxid -> radioid algorithm //////////////////////////////
|
||||
|
||||
// For code readability
|
||||
#define BUGS_CH_SW_ARM CH5_SW
|
||||
#define BUGS_CH_SW_ANGLE CH6_SW
|
||||
#define BUGS_CH_SW_FLIP CH7_SW
|
||||
#define BUGS_CH_SW_PICTURE CH8_SW
|
||||
#define BUGS_CH_SW_VIDEO CH9_SW
|
||||
#define BUGS_CH_SW_LED CH10_SW
|
||||
|
||||
// flags packet byte 4
|
||||
#define BUGS_FLAG_FLIP 0x08 // automatic flip
|
||||
#define BUGS_FLAG_MODE 0x04 // low/high speed select (set is high speed)
|
||||
#define BUGS_FLAG_VIDEO 0x02 // toggle video
|
||||
#define BUGS_FLAG_PICTURE 0x01 // toggle picture
|
||||
|
||||
// flags packet byte 5
|
||||
#define BUGS_FLAG_LED 0x80 // enable LEDs
|
||||
#define BUGS_FLAG_ARM 0x40 // arm (toggle to turn on motors)
|
||||
#define BUGS_FLAG_DISARM 0x20 // disarm (toggle to turn off motors)
|
||||
#define BUGS_FLAG_ANGLE 0x04 // angle/acro mode (set is angle mode)
|
||||
|
||||
#define BUGS_PACKET_SIZE 22
|
||||
#define BUGS_NUM_RFCHAN 16
|
||||
|
||||
enum {
|
||||
BUGS_BIND_1,
|
||||
BUGS_BIND_2,
|
||||
BUGS_BIND_3,
|
||||
BUGS_DATA_1,
|
||||
BUGS_DATA_2,
|
||||
BUGS_DATA_3,
|
||||
};
|
||||
|
||||
static void __attribute__((unused)) BUGS_check_arming()
|
||||
{
|
||||
uint8_t arm_channel = BUGS_CH_SW_ARM;
|
||||
|
||||
if (arm_channel != arm_channel_previous)
|
||||
{
|
||||
arm_channel_previous = arm_channel;
|
||||
if (arm_channel)
|
||||
{
|
||||
armed = 1;
|
||||
arm_flags ^= BUGS_FLAG_ARM;
|
||||
}
|
||||
else
|
||||
{
|
||||
armed = 0;
|
||||
arm_flags ^= BUGS_FLAG_DISARM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) BUGS_build_packet(uint8_t bind)
|
||||
{
|
||||
uint8_t force_values = bind | !armed;
|
||||
uint8_t change_channel = ((packet_count & 0x1) << 6);
|
||||
uint16_t aileron = convert_channel_16b_limit(AILERON,800,0);
|
||||
uint16_t elevator = convert_channel_16b_limit(ELEVATOR,800,0);
|
||||
uint16_t throttle = convert_channel_16b_limit(THROTTLE,0,800);
|
||||
uint16_t rudder = convert_channel_16b_limit(RUDDER,800,0);
|
||||
|
||||
memset(packet, 0, BUGS_PACKET_SIZE);
|
||||
packet[1] = 0x76; // txid (rx uses to know hopping frequencies)
|
||||
packet[2] = 0x71;
|
||||
packet[3] = 0x94;
|
||||
|
||||
BUGS_check_arming(); // sets globals arm_flags and armed
|
||||
if(bind)
|
||||
{
|
||||
packet[4] = change_channel | 0x80;
|
||||
packet[5] = 0x02 | arm_flags
|
||||
| GET_FLAG(BUGS_CH_SW_ANGLE, BUGS_FLAG_ANGLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
packet[4] = change_channel | BUGS_FLAG_MODE
|
||||
| GET_FLAG(BUGS_CH_SW_FLIP, BUGS_FLAG_FLIP)
|
||||
| GET_FLAG(BUGS_CH_SW_PICTURE, BUGS_FLAG_PICTURE)
|
||||
| GET_FLAG(BUGS_CH_SW_VIDEO, BUGS_FLAG_VIDEO);
|
||||
packet[5] = 0x02 | arm_flags
|
||||
| GET_FLAG(BUGS_CH_SW_ANGLE, BUGS_FLAG_ANGLE)
|
||||
| GET_FLAG(BUGS_CH_SW_LED, BUGS_FLAG_LED);
|
||||
}
|
||||
|
||||
packet[6] = force_values ? 100 : (aileron >> 2);
|
||||
packet[7] = force_values ? 100 : (elevator >> 2);
|
||||
packet[8] = force_values ? 0 : (throttle >> 2);
|
||||
packet[9] = force_values ? 100 : (rudder >> 2);
|
||||
packet[10] = 100;
|
||||
packet[11] = 100;
|
||||
packet[12] = 100;
|
||||
packet[13] = 100;
|
||||
|
||||
packet[14] = ((aileron << 6) & 0xc0)
|
||||
| ((elevator << 4) & 0x30)
|
||||
| ((throttle << 2) & 0x0c)
|
||||
| ((rudder ) & 0x03);
|
||||
|
||||
// packet[15] = 0;
|
||||
|
||||
// driven trims
|
||||
packet[16] = aileron / 8 + 14;
|
||||
packet[17] = elevator / 8 + 14;
|
||||
packet[18] = 64;
|
||||
packet[19] = rudder / 8 + 14;
|
||||
|
||||
// packet[20] = 0;
|
||||
// packet[21] = 0;
|
||||
|
||||
uint8_t check = 0x6d;
|
||||
for (uint8_t i=1; i < BUGS_PACKET_SIZE; i++)
|
||||
check ^= packet[i];
|
||||
packet[0] = check;
|
||||
}
|
||||
|
||||
const uint8_t PROGMEM BUGS_hop []= {
|
||||
0x1d, 0x3b, 0x4d, 0x29, 0x11, 0x2d, 0x0b, 0x3d, 0x59, 0x48, 0x17, 0x41, 0x23, 0x4e, 0x2a, 0x63, // bind phase ID=0xac59a453
|
||||
0x4b, 0x19, 0x35, 0x1e, 0x63, 0x0f, 0x45, 0x21, 0x51, 0x3a, 0x5d, 0x25, 0x0a, 0x44, 0x61, 0x27, // data phase ID=0xA4C56AB4 for txid 767194 if rx responds C6 BB 57 7F 00 00 00 00 00 00 FF 87 40 00 00 00
|
||||
};
|
||||
|
||||
static void __attribute__((unused))BUGS_set_radio_data()
|
||||
{ // captured radio data for bugs rx/tx version A2
|
||||
// it appears that the hopping frequencies are determined by the txid
|
||||
// and the data phase radio id is determined by the first 2 bytes of the
|
||||
// rx bind packet
|
||||
uint8_t offset=0;
|
||||
uint32_t radio_id=0xac59a453; // bind phase ID=0xac59a453
|
||||
|
||||
if(IS_BIND_DONE)
|
||||
{
|
||||
offset=BUGS_NUM_RFCHAN;
|
||||
// Read radio_id from EEPROM
|
||||
radio_id=0;
|
||||
uint8_t base_adr=BUGS_EEPROM_OFFSET+RX_num*4;
|
||||
for(uint8_t i=0; i<4; i++)
|
||||
radio_id|=eeprom_read_byte((EE_ADDR)(base_adr+i))<<(i*8);
|
||||
}
|
||||
A7105_WriteID(radio_id);
|
||||
|
||||
for(uint8_t i=0; i<BUGS_NUM_RFCHAN;i++)
|
||||
hopping_frequency[i]=pgm_read_byte_near( &BUGS_hop[i+offset] );
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) BUGS_increment_counts()
|
||||
{ // this logic works with the use of packet_count in BUGS_build_packet
|
||||
// to properly indicate channel changes to rx
|
||||
packet_count += 1;
|
||||
if ((packet_count & 1) == 0)
|
||||
{
|
||||
hopping_frequency_no += 1;
|
||||
hopping_frequency_no %= BUGS_NUM_RFCHAN;
|
||||
}
|
||||
}
|
||||
|
||||
#define BUGS_PACKET_PERIOD 6100
|
||||
#define BUGS_DELAY_TX 2000
|
||||
#define BUGS_DELAY_POST_RX 1500
|
||||
#define BUGS_DELAY_BIND_RST 200
|
||||
|
||||
// FIFO config is one less than desired value
|
||||
#define BUGS_FIFO_SIZE_RX 15
|
||||
#define BUGS_FIFO_SIZE_TX 21
|
||||
uint16_t ReadBUGS(void)
|
||||
{
|
||||
uint8_t mode, base_adr;
|
||||
uint16_t rxid;
|
||||
uint32_t radio_id;
|
||||
uint16_t start;
|
||||
|
||||
// keep frequency tuning updated
|
||||
#ifndef FORCE_FLYSKY_TUNING
|
||||
A7105_AdjustLOBaseFreq(1);
|
||||
#endif
|
||||
|
||||
switch(phase)
|
||||
{
|
||||
case BUGS_BIND_1:
|
||||
BUGS_build_packet(1);
|
||||
A7105_Strobe(A7105_STANDBY);
|
||||
A7105_WriteReg(A7105_03_FIFOI, BUGS_FIFO_SIZE_TX);
|
||||
A7105_WriteData(BUGS_PACKET_SIZE, hopping_frequency[hopping_frequency_no]);
|
||||
phase = BUGS_BIND_2;
|
||||
packet_period = BUGS_DELAY_TX;
|
||||
break;
|
||||
|
||||
case BUGS_BIND_2:
|
||||
//Wait for TX completion
|
||||
start=micros();
|
||||
while ((uint16_t)micros()-start < 500) // Wait max 500µs, using serial+telemetry exit in about 60µs
|
||||
if(!(A7105_ReadReg(A7105_00_MODE) & 0x01))
|
||||
break;
|
||||
A7105_SetTxRxMode(RX_EN);
|
||||
A7105_WriteReg(A7105_0F_PLL_I, hopping_frequency[hopping_frequency_no] - 2);
|
||||
A7105_WriteReg(A7105_03_FIFOI, BUGS_FIFO_SIZE_RX);
|
||||
A7105_Strobe(A7105_RX);
|
||||
|
||||
BUGS_increment_counts();
|
||||
phase = BUGS_BIND_3;
|
||||
packet_period = BUGS_PACKET_PERIOD-BUGS_DELAY_TX-BUGS_DELAY_POST_RX;
|
||||
break;
|
||||
|
||||
case BUGS_BIND_3:
|
||||
mode = A7105_ReadReg(A7105_00_MODE);
|
||||
A7105_Strobe(A7105_STANDBY);
|
||||
A7105_SetTxRxMode(TX_EN);
|
||||
if (mode & 0x01)
|
||||
{
|
||||
phase = BUGS_BIND_1;
|
||||
packet_period = BUGS_DELAY_BIND_RST; // No received data so restart binding procedure.
|
||||
break;
|
||||
}
|
||||
A7105_ReadData(16);
|
||||
if ((packet[0] + packet[1] + packet[2] + packet[3]) == 0)
|
||||
{
|
||||
phase = BUGS_BIND_1;
|
||||
packet_period = BUGS_DELAY_BIND_RST; // No received data so restart binding procedure.
|
||||
break;
|
||||
}
|
||||
A7105_Strobe(A7105_STANDBY);
|
||||
BIND_DONE;
|
||||
// set radio_id
|
||||
rxid = (packet[1] << 8) + packet[2];
|
||||
radio_id = BUGS_rxid_to_radioid(rxid);
|
||||
base_adr=BUGS_EEPROM_OFFSET+RX_num*4;
|
||||
for(uint8_t i=0; i<4; i++)
|
||||
eeprom_write_byte((EE_ADDR)(base_adr+i),radio_id>>(i*8)); // Save radio_id in EEPROM
|
||||
BUGS_set_radio_data();
|
||||
phase = BUGS_DATA_1;
|
||||
packet_count = 0;
|
||||
hopping_frequency_no = 0;
|
||||
packet_period = BUGS_DELAY_POST_RX;
|
||||
break;
|
||||
|
||||
case BUGS_DATA_1:
|
||||
A7105_SetPower();
|
||||
BUGS_build_packet(0);
|
||||
A7105_WriteReg(A7105_03_FIFOI, BUGS_FIFO_SIZE_TX);
|
||||
A7105_WriteData(BUGS_PACKET_SIZE, hopping_frequency[hopping_frequency_no]);
|
||||
phase = BUGS_DATA_2;
|
||||
packet_period = BUGS_DELAY_TX;
|
||||
break;
|
||||
|
||||
case BUGS_DATA_2:
|
||||
//Wait for TX completion
|
||||
start=micros();
|
||||
while ((uint16_t)micros()-start < 500) // Wait max 500µs, using serial+telemetry exit in about 60µs
|
||||
if(!(A7105_ReadReg(A7105_00_MODE) & 0x01))
|
||||
break;
|
||||
A7105_SetTxRxMode(RX_EN);
|
||||
A7105_WriteReg(A7105_0F_PLL_I, hopping_frequency[hopping_frequency_no] - 2);
|
||||
A7105_WriteReg(A7105_03_FIFOI, BUGS_FIFO_SIZE_RX);
|
||||
A7105_Strobe(A7105_RX);
|
||||
|
||||
BUGS_increment_counts();
|
||||
phase = BUGS_DATA_3;
|
||||
packet_period = BUGS_PACKET_PERIOD-BUGS_DELAY_TX-BUGS_DELAY_POST_RX;
|
||||
break;
|
||||
|
||||
case BUGS_DATA_3:
|
||||
mode = A7105_ReadReg(A7105_00_MODE);
|
||||
A7105_Strobe(A7105_STANDBY);
|
||||
A7105_SetTxRxMode(TX_EN);
|
||||
if (!(mode & 0x01))
|
||||
{
|
||||
A7105_ReadData(16);
|
||||
#if defined(BUGS_HUB_TELEMETRY)
|
||||
v_lipo1=packet[10] == 0xff ? 0xff : 0x00; // Voltage in this case is only an alert on level good or bad.
|
||||
RX_RSSI=packet[3];
|
||||
// Read TX RSSI
|
||||
int16_t temp=256-(A7105_ReadReg(A7105_1D_RSSI_THOLD)*8)/5; // Value from A7105 is between 8 for maximum signal strength to 160 or less
|
||||
if(temp<0) temp=0;
|
||||
else if(temp>255) temp=255;
|
||||
TX_RSSI=temp;
|
||||
telemetry_link=1;
|
||||
#endif
|
||||
}
|
||||
phase = BUGS_DATA_1;
|
||||
packet_period = BUGS_DELAY_POST_RX;
|
||||
break;
|
||||
}
|
||||
return packet_period;
|
||||
}
|
||||
|
||||
uint16_t initBUGS(void)
|
||||
{
|
||||
uint32_t radio_id=0;
|
||||
uint8_t base_adr=BUGS_EEPROM_OFFSET+RX_num*4;
|
||||
for(uint8_t i=0; i<4; i++)
|
||||
radio_id|=eeprom_read_byte((EE_ADDR)(base_adr+i))<<(i*8);
|
||||
if(radio_id==0xffffffff)
|
||||
BIND_IN_PROGRESS;
|
||||
|
||||
BUGS_set_radio_data();
|
||||
if (IS_BIND_IN_PROGRESS)
|
||||
phase = BUGS_BIND_1;
|
||||
else
|
||||
phase = BUGS_DATA_1;
|
||||
|
||||
A7105_Init();
|
||||
|
||||
hopping_frequency_no = 0;
|
||||
packet_count = 0;
|
||||
armed = 0;
|
||||
arm_flags = BUGS_FLAG_DISARM; // initial value from captures
|
||||
arm_channel_previous = BUGS_CH_SW_ARM;
|
||||
#ifdef BUGS_HUB_TELEMETRY
|
||||
init_frskyd_link_telemetry();
|
||||
#endif
|
||||
|
||||
return 10000;
|
||||
}
|
||||
|
||||
#endif
|
@ -259,6 +259,7 @@ static void __attribute__((unused)) CX10_initialize_txid()
|
||||
|
||||
uint16_t initCX10(void)
|
||||
{
|
||||
BIND_IN_PROGRESS; // autobind protocol
|
||||
if(sub_protocol==CX10_BLUE)
|
||||
{
|
||||
packet_length = CX10A_PACKET_SIZE;
|
||||
@ -282,7 +283,6 @@ uint16_t initCX10(void)
|
||||
}
|
||||
CX10_initialize_txid();
|
||||
CX10_init();
|
||||
BIND_IN_PROGRESS; // autobind protocol
|
||||
return CX10_INITIAL_WAIT+packet_period;
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ enum {
|
||||
uint8_t sop_col;
|
||||
uint8_t DSM_num_ch=0;
|
||||
uint8_t ch_map[14];
|
||||
const uint8_t PROGMEM ch_map_progmem[][14] = {
|
||||
const uint8_t PROGMEM DSM_ch_map_progmem[][14] = {
|
||||
//22+11ms for 4..7 channels
|
||||
{1, 0, 2, 3, 0xff, 0xff, 0xff, 1, 0, 2, 3, 0xff, 0xff, 0xff}, //4ch - Guess
|
||||
{1, 0, 2, 3, 4, 0xff, 0xff, 1, 0, 2, 3, 4, 0xff, 0xff}, //5ch - Guess
|
||||
@ -62,7 +62,7 @@ const uint8_t PROGMEM ch_map_progmem[][14] = {
|
||||
{1, 5, 2, 3, 4, 8, 9, 1, 5, 2, 3, 0, 7, 6 }, //10ch - DX18
|
||||
};
|
||||
|
||||
const uint8_t PROGMEM pncodes[5][8][8] = {
|
||||
const uint8_t PROGMEM DSM_pncodes[5][8][8] = {
|
||||
/* Note these are in order transmitted (LSB 1st) */
|
||||
{ /* Row 0 */
|
||||
/* Col 0 */ {0x03, 0xBC, 0x6E, 0x8A, 0xEF, 0xBD, 0xFE, 0xF8},
|
||||
@ -123,18 +123,18 @@ const uint8_t PROGMEM pncodes[5][8][8] = {
|
||||
},
|
||||
};
|
||||
|
||||
static void __attribute__((unused)) read_code(uint8_t *buf, uint8_t row, uint8_t col, uint8_t len)
|
||||
static void __attribute__((unused)) DSM_read_code(uint8_t *buf, uint8_t row, uint8_t col, uint8_t len)
|
||||
{
|
||||
for(uint8_t i=0;i<len;i++)
|
||||
buf[i]=pgm_read_byte_near( &pncodes[row][col][i] );
|
||||
buf[i]=pgm_read_byte_near( &DSM_pncodes[row][col][i] );
|
||||
}
|
||||
|
||||
static uint8_t __attribute__((unused)) get_pn_row(uint8_t channel)
|
||||
static uint8_t __attribute__((unused)) DSM_get_pn_row(uint8_t channel)
|
||||
{
|
||||
return ((sub_protocol == DSMX_11 || sub_protocol == DSMX_22 )? (channel - 2) % 5 : channel % 5);
|
||||
}
|
||||
|
||||
const uint8_t PROGMEM init_vals[][2] = {
|
||||
const uint8_t PROGMEM DSM_init_vals[][2] = {
|
||||
{CYRF_02_TX_CTRL, 0x00}, // All TX interrupt disabled
|
||||
{CYRF_05_RX_CTRL, 0x00}, // All RX interrupt disabled
|
||||
{CYRF_28_CLK_EN, 0x02}, // Force receive clock enable
|
||||
@ -154,7 +154,7 @@ const uint8_t PROGMEM init_vals[][2] = {
|
||||
{CYRF_1E_RX_OVERRIDE, 0x14}, // Disable RX CRC, Force receive data rate, use RX synthesizer
|
||||
};
|
||||
|
||||
const uint8_t PROGMEM data_vals[][2] = {
|
||||
const uint8_t PROGMEM DSM_data_vals[][2] = {
|
||||
{CYRF_29_RX_ABORT, 0x20}, // Abort RX operation in case we are coming from bind
|
||||
{CYRF_0F_XACT_CFG, 0x24}, // Force Idle
|
||||
{CYRF_29_RX_ABORT, 0x00}, // Clear abort RX
|
||||
@ -166,8 +166,8 @@ const uint8_t PROGMEM data_vals[][2] = {
|
||||
|
||||
static void __attribute__((unused)) DSM_cyrf_config()
|
||||
{
|
||||
for(uint8_t i = 0; i < sizeof(init_vals) / 2; i++)
|
||||
CYRF_WriteRegister(pgm_read_byte_near(&init_vals[i][0]), pgm_read_byte_near(&init_vals[i][1]));
|
||||
for(uint8_t i = 0; i < sizeof(DSM_init_vals) / 2; i++)
|
||||
CYRF_WriteRegister(pgm_read_byte_near(&DSM_init_vals[i][0]), pgm_read_byte_near(&DSM_init_vals[i][1]));
|
||||
CYRF_WritePreamble(0x333304);
|
||||
CYRF_ConfigRFChannel(0x61);
|
||||
}
|
||||
@ -221,8 +221,8 @@ static void __attribute__((unused)) DSM_initialize_bind_phase()
|
||||
|
||||
static void __attribute__((unused)) DSM_cyrf_configdata()
|
||||
{
|
||||
for(uint8_t i = 0; i < sizeof(data_vals) / 2; i++)
|
||||
CYRF_WriteRegister(pgm_read_byte_near(&data_vals[i][0]), pgm_read_byte_near(&data_vals[i][1]));
|
||||
for(uint8_t i = 0; i < sizeof(DSM_data_vals) / 2; i++)
|
||||
CYRF_WriteRegister(pgm_read_byte_near(&DSM_data_vals[i][0]), pgm_read_byte_near(&DSM_data_vals[i][1]));
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) DSM_update_channels()
|
||||
@ -240,7 +240,7 @@ static void __attribute__((unused)) DSM_update_channels()
|
||||
if(DSM_num_ch>7 && DSM_num_ch<11 && (sub_protocol==DSM2_11 || sub_protocol==DSMX_11))
|
||||
idx+=5; // In 11ms mode change index only for channels 8..10
|
||||
for(uint8_t i=0;i<14;i++)
|
||||
ch_map[i]=pgm_read_byte_near(&ch_map_progmem[idx][i]);
|
||||
ch_map[i]=pgm_read_byte_near(&DSM_ch_map_progmem[idx][i]);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) DSM_build_data_packet(uint8_t upper)
|
||||
@ -262,7 +262,9 @@ static void __attribute__((unused)) DSM_build_data_packet(uint8_t upper)
|
||||
if(sub_protocol==DSM2_22)
|
||||
bits=10; // Only DSM_22 is using a resolution of 1024
|
||||
}
|
||||
|
||||
#ifdef DSM_THROTTLE_KILL_CH
|
||||
uint16_t kill_ch=Channel_data[DSM_THROTTLE_KILL_CH-1];
|
||||
#endif
|
||||
for (uint8_t i = 0; i < 7; i++)
|
||||
{
|
||||
uint8_t idx = ch_map[(upper?7:0) + i];//1,5,2,3,0,4
|
||||
@ -271,6 +273,17 @@ static void __attribute__((unused)) DSM_build_data_packet(uint8_t upper)
|
||||
{
|
||||
/* Spektrum own remotes transmit normal values during bind and actually use this (e.g. Nano CP X) to
|
||||
select the transmitter mode (e.g. computer vs non-computer radio), so always send normal output */
|
||||
#ifdef DSM_THROTTLE_KILL_CH
|
||||
if(CH_TAER[idx]==THROTTLE && kill_ch<=604)
|
||||
{//Activate throttle kill only if DSM_THROTTLE_KILL_CH below -50%
|
||||
if(kill_ch<CHANNEL_MIN_100) // restrict val to 0...400
|
||||
kill_ch=0;
|
||||
else
|
||||
kill_ch-=CHANNEL_MIN_100;
|
||||
value=(kill_ch*21)/25; // kill channel -100%->904us ... -50%->1100us *0x150/400
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef DSM_MAX_THROW
|
||||
value=Channel_data[CH_TAER[idx]]; // -100%..+100% => 1024..1976us and -125%..+125% => 904..2096us based on Redcon 6 channel DSM2 RX
|
||||
#else
|
||||
@ -294,12 +307,12 @@ static void __attribute__((unused)) DSM_set_sop_data_crc()
|
||||
else
|
||||
CYRF_ConfigCRCSeed(~crc); //CH1
|
||||
|
||||
uint8_t pn_row = get_pn_row(hopping_frequency[hopping_frequency_no]);
|
||||
uint8_t pn_row = DSM_get_pn_row(hopping_frequency[hopping_frequency_no]);
|
||||
uint8_t code[16];
|
||||
read_code(code,pn_row,sop_col,8); // pn_row between 0 and 4, sop_col between 1 and 7
|
||||
DSM_read_code(code,pn_row,sop_col,8); // pn_row between 0 and 4, sop_col between 1 and 7
|
||||
CYRF_ConfigSOPCode(code);
|
||||
read_code(code,pn_row,7 - sop_col,8); // 7-sop_col between 0 and 6
|
||||
read_code(code+8,pn_row,7 - sop_col + 1,8); // 7-sop_col+1 between 1 and 7
|
||||
DSM_read_code(code,pn_row,7 - sop_col,8); // 7-sop_col between 0 and 6
|
||||
DSM_read_code(code+8,pn_row,7 - sop_col + 1,8); // 7-sop_col+1 between 1 and 7
|
||||
CYRF_ConfigDataCode(code, 16);
|
||||
|
||||
CYRF_ConfigRFChannel(hopping_frequency[hopping_frequency_no]);
|
||||
@ -536,7 +549,7 @@ uint16_t initDsm()
|
||||
cyrfmfg_id[3]^=RX_num;
|
||||
//Calc sop_col
|
||||
sop_col = (cyrfmfg_id[0] + cyrfmfg_id[1] + cyrfmfg_id[2] + 2) & 0x07;
|
||||
//Fix for OrangeRX using wrong pncodes by preventing access to "Col 8"
|
||||
//Fix for OrangeRX using wrong DSM_pncodes by preventing access to "Col 8"
|
||||
if(sop_col==0)
|
||||
{
|
||||
cyrfmfg_id[rx_tx_addr[0]%3]^=0x01; //Change a bit so sop_col will be different from 0
|
||||
|
244
Multiprotocol/E01X_nrf24l01.ino
Normal file
244
Multiprotocol/E01X_nrf24l01.ino
Normal file
@ -0,0 +1,244 @@
|
||||
/*
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// compatible with E012 and E015
|
||||
|
||||
#if defined(E01X_NRF24L01_INO)
|
||||
|
||||
#include "iface_nrf24l01.h"
|
||||
|
||||
//Protocols constants
|
||||
#define E01X_BIND_COUNT 500
|
||||
#define E01X_INITIAL_WAIT 500
|
||||
#define E01X_ADDRESS_LENGTH 5
|
||||
|
||||
#define E012_PACKET_PERIOD 4525
|
||||
#define E012_RF_BIND_CHANNEL 0x3c
|
||||
#define E012_NUM_RF_CHANNELS 4
|
||||
#define E012_PACKET_SIZE 15
|
||||
|
||||
#define E015_PACKET_PERIOD 4500 // stock Tx=9000, but let's send more packets ...
|
||||
#define E015_RF_CHANNEL 0x2d // 2445 MHz
|
||||
#define E015_PACKET_SIZE 10
|
||||
#define E015_BIND_PACKET_SIZE 9
|
||||
|
||||
//Channels
|
||||
#define E01X_ARM_SW CH5_SW
|
||||
#define E01X_FLIP_SW CH6_SW
|
||||
#define E01X_LED_SW CH7_SW
|
||||
#define E01X_HEADLESS_SW CH8_SW
|
||||
#define E01X_RTH_SW CH9_SW
|
||||
|
||||
// E012 flags packet[1]
|
||||
#define E012_FLAG_FLIP 0x40
|
||||
#define E012_FLAG_HEADLESS 0x10
|
||||
#define E012_FLAG_RTH 0x04
|
||||
// E012 flags packet[7]
|
||||
#define E012_FLAG_EXPERT 0x02
|
||||
|
||||
// E015 flags packet[6]
|
||||
#define E015_FLAG_DISARM 0x80
|
||||
#define E015_FLAG_ARM 0x40
|
||||
// E015 flags packet[7]
|
||||
#define E015_FLAG_FLIP 0x80
|
||||
#define E015_FLAG_HEADLESS 0x10
|
||||
#define E015_FLAG_RTH 0x08
|
||||
#define E015_FLAG_LED 0x04
|
||||
#define E015_FLAG_EXPERT 0x02
|
||||
#define E015_FLAG_INTERMEDIATE 0x01
|
||||
|
||||
static void __attribute__((unused)) E015_check_arming()
|
||||
{
|
||||
uint8_t arm_channel = E01X_ARM_SW;
|
||||
|
||||
if (arm_channel != arm_channel_previous)
|
||||
{
|
||||
arm_channel_previous = arm_channel;
|
||||
if (arm_channel)
|
||||
{
|
||||
armed = 1;
|
||||
arm_flags ^= E015_FLAG_ARM;
|
||||
}
|
||||
else
|
||||
{
|
||||
armed = 0;
|
||||
arm_flags ^= E015_FLAG_DISARM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) E01X_send_packet(uint8_t bind)
|
||||
{
|
||||
if(sub_protocol==E012)
|
||||
{
|
||||
packet_length=E012_PACKET_SIZE;
|
||||
packet[0] = rx_tx_addr[1];
|
||||
if(bind)
|
||||
{
|
||||
packet[1] = 0xaa;
|
||||
memcpy(&packet[2], hopping_frequency, E012_NUM_RF_CHANNELS);
|
||||
memcpy(&packet[6], rx_tx_addr, E01X_ADDRESS_LENGTH);
|
||||
rf_ch_num=E012_RF_BIND_CHANNEL;
|
||||
}
|
||||
else
|
||||
{
|
||||
packet[1] = 0x01
|
||||
| GET_FLAG(E01X_RTH_SW, E012_FLAG_RTH)
|
||||
| GET_FLAG(E01X_HEADLESS_SW, E012_FLAG_HEADLESS)
|
||||
| GET_FLAG(E01X_FLIP_SW, E012_FLAG_FLIP);
|
||||
packet[2] = convert_channel_16b_limit(AILERON, 0xc8, 0x00); // aileron
|
||||
packet[3] = convert_channel_16b_limit(ELEVATOR, 0x00, 0xc8); // elevator
|
||||
packet[4] = convert_channel_16b_limit(RUDDER, 0xc8, 0x00); // rudder
|
||||
packet[5] = convert_channel_16b_limit(THROTTLE, 0x00, 0xc8); // throttle
|
||||
packet[6] = 0xaa;
|
||||
packet[7] = E012_FLAG_EXPERT; // rate (0-2)
|
||||
packet[8] = 0x00;
|
||||
packet[9] = 0x00;
|
||||
packet[10]= 0x00;
|
||||
rf_ch_num=hopping_frequency[hopping_frequency_no++];
|
||||
hopping_frequency_no %= E012_NUM_RF_CHANNELS;
|
||||
}
|
||||
packet[11] = 0x00;
|
||||
packet[12] = 0x00;
|
||||
packet[13] = 0x56;
|
||||
packet[14] = rx_tx_addr[2];
|
||||
}
|
||||
else
|
||||
{ // E015
|
||||
if(bind)
|
||||
{
|
||||
packet[0] = 0x18;
|
||||
packet[1] = 0x04;
|
||||
packet[2] = 0x06;
|
||||
// data phase address
|
||||
memcpy(&packet[3], rx_tx_addr, E01X_ADDRESS_LENGTH);
|
||||
// checksum
|
||||
packet[8] = packet[3];
|
||||
for(uint8_t i=4; i<8; i++)
|
||||
packet[8] += packet[i];
|
||||
packet_length=E015_BIND_PACKET_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
E015_check_arming();
|
||||
packet[0] = convert_channel_16b_limit(THROTTLE, 0, 225); // throttle
|
||||
packet[1] = convert_channel_16b_limit(RUDDER, 225, 0); // rudder
|
||||
packet[2] = convert_channel_16b_limit(AILERON, 0, 225); // aileron
|
||||
packet[3] = convert_channel_16b_limit(ELEVATOR, 225, 0); // elevator
|
||||
packet[4] = 0x20; // elevator trim
|
||||
packet[5] = 0x20; // aileron trim
|
||||
packet[6] = arm_flags;
|
||||
packet[7] = E015_FLAG_EXPERT
|
||||
| GET_FLAG(E01X_FLIP_SW, E015_FLAG_FLIP)
|
||||
| GET_FLAG(E01X_LED_SW, E015_FLAG_LED)
|
||||
| GET_FLAG(E01X_HEADLESS_SW,E015_FLAG_HEADLESS)
|
||||
| GET_FLAG(E01X_RTH_SW, E015_FLAG_RTH);
|
||||
packet[8] = 0;
|
||||
// checksum
|
||||
packet[9] = packet[0];
|
||||
for(uint8_t i=1; i<9; i++)
|
||||
packet[9] += packet[i];
|
||||
packet_length=E015_PACKET_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
// Power on, TX mode, CRC enabled
|
||||
HS6200_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_ch_num);
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
||||
NRF24L01_FlushTx();
|
||||
|
||||
HS6200_WritePayload(packet, packet_length);
|
||||
|
||||
// Check and adjust transmission power. We do this after
|
||||
// transmission to not bother with timeout after power
|
||||
// settings change - we have plenty of time until next
|
||||
// packet.
|
||||
NRF24L01_SetPower();
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) E01X_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
if(sub_protocol==E012)
|
||||
HS6200_SetTXAddr((uint8_t *)"\x55\x42\x9C\x8F\xC9", E01X_ADDRESS_LENGTH);
|
||||
else // E015
|
||||
HS6200_SetTXAddr((uint8_t *)"\x62\x54\x79\x38\x53", E01X_ADDRESS_LENGTH);
|
||||
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_03_SETUP_AW, 0x03);
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1 Mbps
|
||||
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, 0x01); // Set feature bits on
|
||||
NRF24L01_Activate(0x73);
|
||||
}
|
||||
|
||||
uint16_t E01X_callback()
|
||||
{
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
if (bind_counter == 0)
|
||||
{
|
||||
HS6200_SetTXAddr(rx_tx_addr, 5);
|
||||
BIND_DONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
E01X_send_packet(1);
|
||||
bind_counter--;
|
||||
}
|
||||
}
|
||||
else
|
||||
E01X_send_packet(0);
|
||||
return packet_period;
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) E012_initialize_txid()
|
||||
{
|
||||
// rf channels
|
||||
uint32_t lfsr=random(0xfefefefe);
|
||||
for(uint8_t i=0; i<E012_NUM_RF_CHANNELS; i++)
|
||||
hopping_frequency[i] = 0x10 + (((lfsr >> (i*8)) & 0xff) % 0x32);
|
||||
}
|
||||
|
||||
uint16_t initE01X()
|
||||
{
|
||||
BIND_IN_PROGRESS;
|
||||
if(sub_protocol==E012)
|
||||
{
|
||||
E012_initialize_txid();
|
||||
packet_period=E012_PACKET_PERIOD;
|
||||
}
|
||||
else
|
||||
{ // E015
|
||||
packet_period=E015_PACKET_PERIOD;
|
||||
rf_ch_num=E015_RF_CHANNEL;
|
||||
armed = 0;
|
||||
arm_flags = 0;
|
||||
arm_channel_previous = E01X_ARM_SW;
|
||||
}
|
||||
E01X_init();
|
||||
bind_counter = E01X_BIND_COUNT;
|
||||
hopping_frequency_no = 0;
|
||||
return E01X_INITIAL_WAIT;
|
||||
}
|
||||
|
||||
#endif
|
@ -30,7 +30,7 @@ static void __attribute__((unused)) ESKY_set_data_address()
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, 4);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) ESKY_init(uint8_t bind)
|
||||
static void __attribute__((unused)) ESKY_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
|
||||
@ -38,7 +38,7 @@ static void __attribute__((unused)) ESKY_init(uint8_t bind)
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO));
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowledgement
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0
|
||||
if (bind)
|
||||
if (IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x01); // 3-byte RX/TX address for bind packets
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t*)"\x00\x00\x00", 3);
|
||||
@ -63,7 +63,6 @@ static void __attribute__((unused)) ESKY_init(uint8_t bind)
|
||||
static void __attribute__((unused)) ESKY_init2()
|
||||
{
|
||||
NRF24L01_FlushTx();
|
||||
packet_sent = 0;
|
||||
hopping_frequency_no = 0;
|
||||
uint16_t channel_ord = rx_tx_addr[0] % 74;
|
||||
hopping_frequency[12] = 10 + (uint8_t)channel_ord; //channel_code
|
||||
@ -116,14 +115,12 @@ static void __attribute__((unused)) ESKY_send_packet(uint8_t bind)
|
||||
// Each data packet is repeated 3 times on one channel, and 3 times on another channel
|
||||
// For arithmetic simplicity, channels are repeated in rf_channels array
|
||||
if (hopping_frequency_no == 0)
|
||||
{
|
||||
for (uint8_t i = 0; i < 6; i++)
|
||||
{
|
||||
uint16_t val=convert_channel_ppm(CH_AETR[i]);
|
||||
packet[i*2] = val>>8; //high byte of servo timing(1000-2000us)
|
||||
packet[i*2+1] = val&0xFF; //low byte of servo timing(1000-2000us)
|
||||
}
|
||||
}
|
||||
rf_ch = hopping_frequency[hopping_frequency_no];
|
||||
packet[12] = hopping_frequency[hopping_frequency_no+6]; // end_bytes
|
||||
hopping_frequency_no++;
|
||||
@ -132,23 +129,15 @@ static void __attribute__((unused)) ESKY_send_packet(uint8_t bind)
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_ch);
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_WritePayload(packet, ESKY_PAYLOAD_SIZE);
|
||||
packet_sent = 1;
|
||||
if (! rf_ch_num)
|
||||
NRF24L01_SetPower(); //Keep transmit power updated
|
||||
}
|
||||
|
||||
uint16_t ESKY_callback()
|
||||
{
|
||||
if(IS_BIND_DONE)
|
||||
{
|
||||
if (packet_sent && NRF24L01_packet_ack() != PKT_ACKED)
|
||||
return ESKY_PACKET_CHKTIME;
|
||||
ESKY_send_packet(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (packet_sent && NRF24L01_packet_ack() != PKT_ACKED)
|
||||
return ESKY_PACKET_CHKTIME;
|
||||
ESKY_send_packet(1);
|
||||
if (--bind_counter == 0)
|
||||
{
|
||||
@ -162,8 +151,9 @@ uint16_t ESKY_callback()
|
||||
uint16_t initESKY(void)
|
||||
{
|
||||
bind_counter = ESKY_BIND_COUNT;
|
||||
rx_tx_addr[2] = rx_tx_addr[3]; // Model match
|
||||
rx_tx_addr[3] = 0xBB;
|
||||
ESKY_init(IS_BIND_IN_PROGRESS);
|
||||
ESKY_init();
|
||||
ESKY_init2();
|
||||
return 50000;
|
||||
}
|
||||
|
116
Multiprotocol/GD00X_nrf24l01.ino
Normal file
116
Multiprotocol/GD00X_nrf24l01.ino
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// Compatible with GD005 C-17 and GD006 DA62 planes.
|
||||
|
||||
#if defined(GD00X_NRF24L01_INO)
|
||||
|
||||
#include "iface_nrf24l01.h"
|
||||
|
||||
//#define FORCE_GD00X_ORIGINAL_ID
|
||||
|
||||
#define GD00X_INITIAL_WAIT 500
|
||||
#define GD00X_PACKET_PERIOD 3500
|
||||
#define GD00X_RF_BIND_CHANNEL 2
|
||||
#define GD00X_PAYLOAD_SIZE 15
|
||||
#define GD00X_BIND_COUNT 857 //3sec
|
||||
|
||||
// flags going to packet[11]
|
||||
#define GD00X_FLAG_DR 0x08
|
||||
#define GD00X_FLAG_LIGHT 0x04
|
||||
|
||||
static void __attribute__((unused)) GD00X_send_packet()
|
||||
{
|
||||
packet[0] = IS_BIND_IN_PROGRESS?0xAA:0x55;
|
||||
memcpy(packet+1,rx_tx_addr,4);
|
||||
uint16_t channel=convert_channel_ppm(AILERON);
|
||||
packet[5 ] = channel;
|
||||
packet[6 ] = channel>>8;
|
||||
channel=convert_channel_ppm(THROTTLE);
|
||||
packet[7 ] = channel;
|
||||
packet[8 ] = channel>>8;
|
||||
channel=convert_channel_ppm(CH5); // TRIM
|
||||
packet[9 ] = channel;
|
||||
packet[10] = channel>>8;
|
||||
packet[11] = GD00X_FLAG_DR // Force high rate
|
||||
| GET_FLAG(CH6_SW, GD00X_FLAG_LIGHT);
|
||||
packet[12] = 0x00;
|
||||
packet[13] = 0x00;
|
||||
packet[14] = 0x00;
|
||||
|
||||
// Power on, TX mode, CRC enabled
|
||||
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
|
||||
if(IS_BIND_DONE)
|
||||
{
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no++]);
|
||||
hopping_frequency_no &= 3; // 4 RF channels
|
||||
}
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
||||
NRF24L01_FlushTx();
|
||||
XN297_WritePayload(packet, GD00X_PAYLOAD_SIZE);
|
||||
|
||||
NRF24L01_SetPower(); // Set tx_power
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) GD00X_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
XN297_SetTXAddr((uint8_t*)"\xcc\xcc\xcc\xcc\xcc", 5);
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, GD00X_RF_BIND_CHANNEL); // Bind channel
|
||||
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_SetBitrate(NRF24L01_BR_250K); // 250Kbps
|
||||
NRF24L01_SetPower();
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) GD00X_initialize_txid()
|
||||
{
|
||||
uint8_t start=76+(rx_tx_addr[0]&0x03);
|
||||
for(uint8_t i=0; i<4;i++)
|
||||
hopping_frequency[i]=start-(i<<1);
|
||||
#ifdef FORCE_GD00X_ORIGINAL_ID
|
||||
rx_tx_addr[0]=0x1F; // or 0xA5 or 0x26
|
||||
rx_tx_addr[1]=0x39; // or 0x37 or 0x35
|
||||
rx_tx_addr[2]=0x12; // Constant on 3 TXs
|
||||
rx_tx_addr[3]=0x13; // Constant on 3 TXs
|
||||
for(uint8_t i=0; i<4;i++)
|
||||
hopping_frequency[i]=79-(i<<1); // or 77 or 78
|
||||
#endif
|
||||
}
|
||||
|
||||
uint16_t GD00X_callback()
|
||||
{
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
if(--bind_counter==0)
|
||||
BIND_DONE;
|
||||
GD00X_send_packet();
|
||||
return GD00X_PACKET_PERIOD;
|
||||
}
|
||||
|
||||
uint16_t initGD00X()
|
||||
{
|
||||
BIND_IN_PROGRESS; // autobind protocol
|
||||
GD00X_initialize_txid();
|
||||
GD00X_init();
|
||||
hopping_frequency_no = 0;
|
||||
bind_counter=GD00X_BIND_COUNT;
|
||||
return GD00X_INITIAL_WAIT;
|
||||
}
|
||||
|
||||
#endif
|
@ -32,7 +32,7 @@ enum {
|
||||
GW008_DATA
|
||||
};
|
||||
|
||||
static void __attribute__((unused)) send_packet(uint8_t bind)
|
||||
static void __attribute__((unused)) GW008_send_packet(uint8_t bind)
|
||||
{
|
||||
packet[0] = rx_tx_addr[0];
|
||||
if(bind)
|
||||
@ -123,7 +123,7 @@ uint16_t GW008_callback()
|
||||
{
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
send_packet(1);
|
||||
GW008_send_packet(1);
|
||||
phase = GW008_BIND2;
|
||||
return 300;
|
||||
}
|
||||
@ -139,7 +139,7 @@ uint16_t GW008_callback()
|
||||
return 5000;
|
||||
break;
|
||||
case GW008_DATA:
|
||||
send_packet(0);
|
||||
GW008_send_packet(0);
|
||||
break;
|
||||
}
|
||||
return GW008_PACKET_PERIOD;
|
||||
|
@ -49,12 +49,19 @@ enum{
|
||||
// flags going to packet[9] (H501S)
|
||||
FLAG_H501_VIDEO = 0x01,
|
||||
FLAG_H501_LED = 0x04,
|
||||
FLAG_H122D_FLIP = 0x08, //H122D
|
||||
FLAG_H501_RTH = 0x20,
|
||||
FLAG_H501_HEADLESS1 = 0x40,
|
||||
FLAG_H501_GPS_HOLD = 0x80,
|
||||
};
|
||||
|
||||
enum{
|
||||
enum{
|
||||
// flags going to packet[11] (H122D & H123D)
|
||||
FLAG_H123D_FMODES = 0x03, //H123D 3 FMODES: Sport mode 1, Sport mode 2, Acro
|
||||
FLAG_H122D_OSD = 0x20, //H122D OSD
|
||||
};
|
||||
|
||||
enum{
|
||||
// flags going to packet[13] (H501S)
|
||||
FLAG_H501_SNAPSHOT = 0x01,
|
||||
FLAG_H501_HEADLESS2 = 0x02,
|
||||
@ -203,12 +210,25 @@ static void __attribute__((unused)) hubsan_build_packet()
|
||||
packet[9] = 0x02
|
||||
| GET_FLAG(CH6_SW, FLAG_H501_LED)
|
||||
| GET_FLAG(CH8_SW, FLAG_H501_VIDEO)
|
||||
| GET_FLAG(CH12_SW, FLAG_H122D_FLIP) // H122D specific -> flip
|
||||
| GET_FLAG(CH5_SW, FLAG_H501_RTH)
|
||||
| GET_FLAG(CH11_SW, FLAG_H501_GPS_HOLD)
|
||||
| GET_FLAG(CH10_SW, FLAG_H501_GPS_HOLD)
|
||||
| GET_FLAG(CH9_SW, FLAG_H501_HEADLESS1);
|
||||
//packet[10]= 0x1A;
|
||||
packet[13] = GET_FLAG(CH10_SW, FLAG_H501_HEADLESS2)
|
||||
| GET_FLAG(CH12_SW, FLAG_H501_ALT_HOLD)
|
||||
|
||||
//packet[11] content 0x00 is default
|
||||
//H123D specific -> Flight modes
|
||||
packet[11] = 0x41; // Sport mode 1
|
||||
if(Channel_data[CH13]>CHANNEL_MAX_COMMAND)
|
||||
packet[11]=0x43; // Acro
|
||||
else if(Channel_data[CH13]>CHANNEL_MIN_COMMAND)
|
||||
packet[11]=0x42; // Sport mode 2
|
||||
//H122D specific -> OSD but useless...
|
||||
//packet[11]|= 0x80
|
||||
// | GET_FLAG(CHXX_SW,FLAG_H122D_OSD);
|
||||
|
||||
packet[13] = GET_FLAG(CH9_SW, FLAG_H501_HEADLESS2)
|
||||
| GET_FLAG(CH11_SW, FLAG_H501_ALT_HOLD)
|
||||
| GET_FLAG(CH7_SW, FLAG_H501_SNAPSHOT);
|
||||
}
|
||||
else
|
||||
|
@ -8,7 +8,7 @@
|
||||
8,YD717,YD717,SKYWLKR,SYMAX4,XINXUN,NIHUI
|
||||
9,KN,WLTOYS,FEILUN
|
||||
10,SymaX,SYMAX,SYMAX5C
|
||||
11,SLT,SLT,VISTA
|
||||
11,SLT,SLT_V1,SLT_V2,Q100,Q200,MR100
|
||||
12,CX10,GREEN,BLUE,DM007,---,J3015_1,J3015_2,MK33041
|
||||
13,CG023,CG023,YD829
|
||||
14,Bayang,Bayang,H8S3D,X16_AH,IRDRONE
|
||||
@ -38,3 +38,11 @@
|
||||
38,CFlie
|
||||
39,Hitec,OPT_FW,OPT_HUB,MINIMA
|
||||
40,WFLY
|
||||
41,BUGS
|
||||
42,BUGSMINI
|
||||
43,Traxxas
|
||||
44,NCC1701
|
||||
45,E01X,E012,E015
|
||||
46,V911S
|
||||
47,GD00X
|
||||
63,Test
|
||||
|
@ -18,8 +18,8 @@
|
||||
//******************
|
||||
#define VERSION_MAJOR 1
|
||||
#define VERSION_MINOR 2
|
||||
#define VERSION_REVISION 0
|
||||
#define VERSION_PATCH_LEVEL 32
|
||||
#define VERSION_REVISION 1
|
||||
#define VERSION_PATCH_LEVEL 23
|
||||
|
||||
//******************
|
||||
// Protocols
|
||||
@ -67,6 +67,14 @@ enum PROTOCOLS
|
||||
PROTO_CFLIE = 38, // =>NRF24L01
|
||||
PROTO_HITEC = 39, // =>CC2500
|
||||
PROTO_WFLY = 40, // =>CYRF6936
|
||||
PROTO_BUGS = 41, // =>A7105
|
||||
PROTO_BUGSMINI = 42, // =>NRF24L01
|
||||
PROTO_TRAXXAS = 43, // =>CYRF6936
|
||||
PROTO_NCC1701 = 44, // =>NRF24L01
|
||||
PROTO_E01X = 45, // =>NRF24L01
|
||||
PROTO_V911S = 46, // =>NRF24L01
|
||||
PROTO_GD00X = 47, // =>NRF24L01
|
||||
PROTO_TEST = 63, // =>NRF24L01
|
||||
};
|
||||
|
||||
enum Flysky
|
||||
@ -75,7 +83,7 @@ enum Flysky
|
||||
V9X9 = 1,
|
||||
V6X6 = 2,
|
||||
V912 = 3,
|
||||
CX20 = 4
|
||||
CX20 = 4,
|
||||
};
|
||||
enum Hubsan
|
||||
{
|
||||
@ -93,7 +101,7 @@ enum AFHDS2A
|
||||
enum Hisky
|
||||
{
|
||||
Hisky = 0,
|
||||
HK310 = 1
|
||||
HK310 = 1,
|
||||
};
|
||||
enum DSM
|
||||
{
|
||||
@ -101,7 +109,7 @@ enum DSM
|
||||
DSM2_11 = 1,
|
||||
DSMX_22 = 2,
|
||||
DSMX_11 = 3,
|
||||
DSM_AUTO = 4
|
||||
DSM_AUTO = 4,
|
||||
};
|
||||
enum YD717
|
||||
{
|
||||
@ -109,22 +117,25 @@ enum YD717
|
||||
SKYWLKR = 1,
|
||||
SYMAX4 = 2,
|
||||
XINXUN = 3,
|
||||
NIHUI = 4
|
||||
NIHUI = 4,
|
||||
};
|
||||
enum KN
|
||||
{
|
||||
WLTOYS = 0,
|
||||
FEILUN = 1
|
||||
FEILUN = 1,
|
||||
};
|
||||
enum SYMAX
|
||||
{
|
||||
SYMAX = 0,
|
||||
SYMAX5C = 1
|
||||
SYMAX5C = 1,
|
||||
};
|
||||
enum SLT
|
||||
{
|
||||
SLT = 0,
|
||||
VISTA = 1
|
||||
SLT_V1 = 0,
|
||||
SLT_V2 = 1,
|
||||
Q100 = 2,
|
||||
Q200 = 3,
|
||||
MR100 = 4,
|
||||
};
|
||||
enum CX10
|
||||
{
|
||||
@ -162,7 +173,7 @@ enum MT99XX
|
||||
H7 = 1,
|
||||
YZ = 2,
|
||||
LS = 3,
|
||||
FY805 = 4
|
||||
FY805 = 4,
|
||||
};
|
||||
enum MJXQ
|
||||
{
|
||||
@ -185,7 +196,7 @@ enum HONTAI
|
||||
HONTAI = 0,
|
||||
JJRCX1 = 1,
|
||||
X5C1 = 2,
|
||||
FQ777_951 =3
|
||||
FQ777_951 =3,
|
||||
};
|
||||
enum V2X2
|
||||
{
|
||||
@ -239,6 +250,11 @@ enum HITEC
|
||||
OPT_HUB = 1,
|
||||
MINIMA = 2,
|
||||
};
|
||||
enum E01X
|
||||
{
|
||||
E012 = 0,
|
||||
E015 = 1,
|
||||
};
|
||||
|
||||
#define NONE 0
|
||||
#define P_HIGH 1
|
||||
@ -355,12 +371,13 @@ enum MultiPacketTypes
|
||||
//********************
|
||||
#if defined(STM32_BOARD) && defined (DEBUG_SERIAL)
|
||||
uint16_t debug_time=0;
|
||||
#define debug(msg, ...) {char buf[64]; sprintf(buf, msg, ##__VA_ARGS__); Serial.write(buf);}
|
||||
#define debugln(msg, ...) {char buf[64]; sprintf(buf, msg "\r\n", ##__VA_ARGS__); Serial.write(buf);}
|
||||
#define debug_time(msg) { uint16_t debug_time_TCNT1=TCNT1; debug_time=debug_time_TCNT1-debug_time; debugln(msg "%u", debug_time); debug_time=debug_time_TCNT1; }
|
||||
#define debug(msg, ...) {char debug_buf[64]; sprintf(debug_buf, msg, ##__VA_ARGS__); Serial.write(debug_buf);}
|
||||
#define debugln(msg, ...) {char debug_buf[64]; sprintf(debug_buf, msg "\r\n", ##__VA_ARGS__); Serial.write(debug_buf);}
|
||||
#define debug_time(msg) { uint16_t debug_time_TCNT1=TCNT1; debug_time=debug_time_TCNT1-debug_time; debug(msg "%u", debug_time>>1); debug_time=debug_time_TCNT1; }
|
||||
#else
|
||||
#define debug(...) { }
|
||||
#define debugln(...) { }
|
||||
#define debug_time(...) { }
|
||||
#undef DEBUG_SERIAL
|
||||
#endif
|
||||
|
||||
@ -510,9 +527,11 @@ enum {
|
||||
#define EEPROM_ID_OFFSET 10 // Module ID (4 bytes)
|
||||
#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 46
|
||||
#define AFHDS2A_EEPROM_OFFSET 50 // RX ID, 4 byte per model id, end is 114
|
||||
#define CONFIG_EEPROM_OFFSET 120 // Current configuration of the multimodule
|
||||
#define MODELMODE_EEPROM_OFFSET 30 // Autobind mode, 1 byte per model, end is 30+16=46
|
||||
#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 ***
|
||||
@ -571,6 +590,13 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
||||
CFlie 38
|
||||
Hitec 39
|
||||
WFLY 40
|
||||
BUGS 41
|
||||
BUGSMINI 42
|
||||
TRAXXAS 43
|
||||
NCC1701 44
|
||||
E01X 45
|
||||
V911S 46
|
||||
GD00X 47
|
||||
BindBit=> 0x80 1=Bind/0=No
|
||||
AutoBindBit=> 0x40 1=Yes /0=No
|
||||
RangeCheck=> 0x20 1=Yes /0=No
|
||||
@ -620,9 +646,6 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
||||
Q222 0
|
||||
Q242 1
|
||||
Q282 2
|
||||
sub_protocol==SLT
|
||||
SLT 0
|
||||
VISTA 1
|
||||
sub_protocol==CG023
|
||||
CG023 0
|
||||
YD829 1
|
||||
@ -695,6 +718,15 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
||||
OPT_FW 0
|
||||
OPT_HUB 1
|
||||
MINIMA 2
|
||||
sub_protocol==SLT
|
||||
SLT_V1 0
|
||||
SLT_V2 1
|
||||
Q100 2
|
||||
Q200 3
|
||||
MR100 4
|
||||
sub_protocol==E01X
|
||||
E012 0
|
||||
E015 1
|
||||
|
||||
Power value => 0x80 0=High/1=Low
|
||||
Stream[3] = option_protocol;
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
//#define DEBUG_PIN // Use pin TX for AVR and SPI_CS for STM32 => DEBUG_PIN_on, DEBUG_PIN_off, DEBUG_PIN_toggle
|
||||
//#define DEBUG_SERIAL // Only for STM32_BOARD compiled with Upload method "Serial"->usart1, "STM32duino bootloader"->USB serial
|
||||
//#define DEBUG_SERIAL // Only for STM32_BOARD, compiled with Upload method "Serial"->usart1, "STM32duino bootloader"->USB serial
|
||||
|
||||
#ifdef __arm__ // Let's automatically select the board if arm is selected
|
||||
#define STM32_BOARD
|
||||
@ -89,7 +89,7 @@ uint8_t Channel_AUX;
|
||||
// Protocol variables
|
||||
uint8_t cyrfmfg_id[6];//for dsm2 and devo
|
||||
uint8_t rx_tx_addr[5];
|
||||
uint8_t rx_id[4];
|
||||
uint8_t rx_id[5];
|
||||
uint8_t phase;
|
||||
uint16_t bind_counter;
|
||||
uint8_t bind_phase;
|
||||
@ -110,8 +110,9 @@ uint16_t seed;
|
||||
uint16_t failsafe_count;
|
||||
uint16_t state;
|
||||
uint8_t len;
|
||||
uint8_t armed, arm_flags, arm_channel_previous;
|
||||
|
||||
#if defined(FRSKYX_CC2500_INO) || defined(SFHSS_CC2500_INO)
|
||||
#if defined(FRSKYX_CC2500_INO) || defined(SFHSS_CC2500_INO) || defined(HITEC_CC2500_INO)
|
||||
uint8_t calData[48];
|
||||
#endif
|
||||
|
||||
@ -404,11 +405,16 @@ void setup()
|
||||
//Protocol and interrupts initialization
|
||||
if(mode_select != MODE_SERIAL)
|
||||
{ // PPM
|
||||
uint8_t line=bank*14+mode_select-1;
|
||||
protocol = PPM_prot[line].protocol;
|
||||
#ifndef MY_PPM_PROT
|
||||
const PPM_Parameters *PPM_prot_line=&PPM_prot[bank*14+mode_select-1];
|
||||
#else
|
||||
const PPM_Parameters *PPM_prot_line=&My_PPM_prot[bank*14+mode_select-1];
|
||||
#endif
|
||||
|
||||
protocol = PPM_prot_line->protocol;
|
||||
cur_protocol[1] = protocol;
|
||||
sub_protocol = PPM_prot[line].sub_proto;
|
||||
RX_num = PPM_prot[line].rx_num;
|
||||
sub_protocol = PPM_prot_line->sub_proto;
|
||||
RX_num = PPM_prot_line->rx_num;
|
||||
|
||||
//Forced frequency tuning values for CC2500 protocols
|
||||
#if defined(FORCE_FRSKYD_TUNING) && defined(FRSKYD_CC2500_INO)
|
||||
@ -441,15 +447,14 @@ void setup()
|
||||
option = FORCE_HITEC_TUNING; // Use config-defined tuning value for HITEC
|
||||
else
|
||||
#endif
|
||||
option = PPM_prot[line].option; // Use radio-defined option value
|
||||
option = PPM_prot_line->option; // Use radio-defined option value
|
||||
|
||||
if(PPM_prot[line].power) POWER_FLAG_on;
|
||||
if(PPM_prot[line].autobind)
|
||||
if(PPM_prot_line->power) POWER_FLAG_on;
|
||||
if(PPM_prot_line->autobind)
|
||||
{
|
||||
AUTOBIND_FLAG_on;
|
||||
BIND_IN_PROGRESS; // Force a bind at protocol startup
|
||||
}
|
||||
line++;
|
||||
|
||||
protocol_init();
|
||||
|
||||
@ -614,7 +619,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_HUBSAN) || (protocol==PROTO_AFHDS2A) || (protocol==PROTO_FRSKYX) || (protocol==PROTO_DSM) || (protocol==PROTO_CABELL) || (protocol==PROTO_HITEC))
|
||||
if( (protocol==PROTO_FRSKYD) || (protocol==PROTO_BAYANG) || (protocol==PROTO_NCC1701) || (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
|
||||
@ -651,7 +656,7 @@ static void update_channels_aux(void)
|
||||
{
|
||||
//Reverse channels direction
|
||||
#ifdef REVERSE_AILERON
|
||||
reverse_channel(AILREON);
|
||||
reverse_channel(AILERON);
|
||||
#endif
|
||||
#ifdef REVERSE_ELEVATOR
|
||||
reverse_channel(ELEVATOR);
|
||||
@ -915,6 +920,13 @@ static void protocol_init()
|
||||
remote_callback = ReadHubsan;
|
||||
break;
|
||||
#endif
|
||||
#if defined(BUGS_A7105_INO)
|
||||
case PROTO_BUGS:
|
||||
PE1_off; //antenna RF1
|
||||
next_callback = initBUGS();
|
||||
remote_callback = ReadBUGS;
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef CC2500_INSTALLED
|
||||
#if defined(FRSKYD_CC2500_INO)
|
||||
@ -1180,6 +1192,42 @@ 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(NCC1701_NRF24L01_INO)
|
||||
case PROTO_NCC1701:
|
||||
next_callback=initNCC();
|
||||
remote_callback = NCC_callback;
|
||||
break;
|
||||
#endif
|
||||
#if defined(E01X_NRF24L01_INO)
|
||||
case PROTO_E01X:
|
||||
next_callback=initE01X();
|
||||
remote_callback = E01X_callback;
|
||||
break;
|
||||
#endif
|
||||
#if defined(V911S_NRF24L01_INO)
|
||||
case PROTO_V911S:
|
||||
next_callback=initV911S();
|
||||
remote_callback = V911S_callback;
|
||||
break;
|
||||
#endif
|
||||
#if defined(GD00X_NRF24L01_INO)
|
||||
case PROTO_GD00X:
|
||||
next_callback=initGD00X();
|
||||
remote_callback = GD00X_callback;
|
||||
break;
|
||||
#endif
|
||||
#if defined(TEST_NRF24L01_INO)
|
||||
case PROTO_TEST:
|
||||
next_callback=initTest();
|
||||
remote_callback = Test_callback;
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -1569,7 +1617,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) )
|
||||
if( (protocol==PROTO_FRSKYD) || (protocol==PROTO_HUBSAN) || (protocol==PROTO_AFHDS2A) || (protocol==PROTO_BAYANG)|| (protocol==PROTO_NCC1701) || (protocol==PROTO_CABELL) || (protocol==PROTO_HITEC) || (protocol==PROTO_BUGS) || (protocol==PROTO_BUGSMINI))
|
||||
initTXSerial( SPEED_9600 ) ;
|
||||
if(protocol==PROTO_FRSKYX)
|
||||
initTXSerial( SPEED_57600 ) ;
|
||||
|
277
Multiprotocol/NCC1701_nrf24l01.ino
Normal file
277
Multiprotocol/NCC1701_nrf24l01.ino
Normal file
@ -0,0 +1,277 @@
|
||||
/*
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if defined(NCC1701_NRF24L01_INO)
|
||||
|
||||
#include "iface_nrf24l01.h"
|
||||
|
||||
#define NCC_WRITE_WAIT 2000
|
||||
#define NCC_PACKET_INTERVAL 10333
|
||||
#define NCC_TX_PACKET_LEN 16
|
||||
#define NCC_RX_PACKET_LEN 13
|
||||
|
||||
enum {
|
||||
NCC_BIND_TX1=0,
|
||||
NCC_BIND_RX1,
|
||||
NCC_BIND_TX2,
|
||||
NCC_BIND_RX2,
|
||||
NCC_TX3,
|
||||
NCC_RX3,
|
||||
};
|
||||
|
||||
static void __attribute__((unused)) NCC_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t*)"\xE7\xE7\xC7\xD7\x67",5);
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t*)"\xE7\xE7\xC7\xD7\x67",5);
|
||||
|
||||
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 Acknowledgment on all data pipes
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, NCC_RX_PACKET_LEN); // Enable rx pipe 0
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_250K); // NRF24L01_BR_1M, NRF24L01_BR_2M, NRF24L01_BR_250K
|
||||
NRF24L01_SetPower();
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, (0 << NRF24L01_00_EN_CRC) // switch to TX mode and disable CRC
|
||||
| (1 << NRF24L01_00_CRCO)
|
||||
| (1 << NRF24L01_00_PWR_UP)
|
||||
| (0 << NRF24L01_00_PRIM_RX));
|
||||
}
|
||||
|
||||
const uint8_t NCC_xor[]={0x80, 0x44, 0x64, 0x75, 0x6C, 0x71, 0x2A, 0x36, 0x7C, 0xF1, 0x6E, 0x52, 0x09, 0x9D};
|
||||
static void __attribute__((unused)) NCC_Crypt_Packet()
|
||||
{
|
||||
uint16_t crc=0;
|
||||
for(uint8_t i=0; i< NCC_TX_PACKET_LEN-2; i++)
|
||||
{
|
||||
packet[i]^=NCC_xor[i];
|
||||
crc=crc16_update(crc, packet[i], 8);
|
||||
}
|
||||
crc^=0x60DE;
|
||||
packet[NCC_TX_PACKET_LEN-2]=crc>>8;
|
||||
packet[NCC_TX_PACKET_LEN-1]=crc;
|
||||
}
|
||||
static boolean __attribute__((unused)) NCC_Decrypt_Packet()
|
||||
{
|
||||
uint16_t crc=0;
|
||||
debug("RX: ");
|
||||
for(uint8_t i=0; i< NCC_RX_PACKET_LEN-2; i++)
|
||||
{
|
||||
crc=crc16_update(crc, packet[i], 8);
|
||||
packet[i]^=NCC_xor[i];
|
||||
debug("%02X ",packet[i]);
|
||||
}
|
||||
crc^=0xA950;
|
||||
if( (crc>>8)==packet[NCC_RX_PACKET_LEN-2] && (crc&0xFF)==packet[NCC_RX_PACKET_LEN-1] )
|
||||
{// CRC match
|
||||
debugln("OK");
|
||||
return true;
|
||||
}
|
||||
debugln("NOK");
|
||||
return false;
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) NCC_Write_Packet()
|
||||
{
|
||||
packet[0]=0xAA;
|
||||
packet[1]=rx_tx_addr[0];
|
||||
packet[2]=rx_tx_addr[1];
|
||||
packet[3]=rx_id[0];
|
||||
packet[4]=rx_id[1];
|
||||
packet[5]=convert_channel_8b(THROTTLE)>>2; // 00-3D
|
||||
packet[6]=convert_channel_8b(ELEVATOR); // original: 61-80-9F but works with 00-80-FF
|
||||
packet[7]=convert_channel_8b(AILERON ); // original: 61-80-9F but works with 00-80-FF
|
||||
packet[8]=convert_channel_8b(RUDDER ); // original: 61-80-9F but works with 00-80-FF
|
||||
packet[9]=rx_id[2];
|
||||
packet[10]=rx_id[3];
|
||||
packet[11]=rx_id[4];
|
||||
packet[12]=GET_FLAG(CH5_SW, 0x02); // Warp:0x00 -> 0x02
|
||||
packet[13]=packet[5]+packet[6]+packet[7]+packet[8]+packet[12];
|
||||
if(phase==NCC_BIND_TX1)
|
||||
{
|
||||
packet[0]=0xBB;
|
||||
packet[5]=0x01;
|
||||
packet[6]=rx_tx_addr[2];
|
||||
memset((void *)(packet+7),0x55,7);
|
||||
hopping_frequency_no^=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
hopping_frequency_no++;
|
||||
if(hopping_frequency_no>2) hopping_frequency_no=0;
|
||||
}
|
||||
// change frequency
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
|
||||
// switch to TX mode and disable CRC
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, (0 << NRF24L01_00_EN_CRC)
|
||||
| (1 << NRF24L01_00_CRCO)
|
||||
| (1 << NRF24L01_00_PWR_UP)
|
||||
| (0 << NRF24L01_00_PRIM_RX));
|
||||
// clear packet status bits and TX FIFO
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
||||
NRF24L01_FlushTx();
|
||||
// send packet
|
||||
NCC_Crypt_Packet();
|
||||
NRF24L01_WritePayload(packet,NCC_TX_PACKET_LEN);
|
||||
NRF24L01_SetPower();
|
||||
}
|
||||
|
||||
uint16_t NCC_callback()
|
||||
{
|
||||
switch(phase)
|
||||
{
|
||||
case NCC_BIND_TX1:
|
||||
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
|
||||
{ // RX fifo data ready
|
||||
NRF24L01_ReadPayload(packet, NCC_RX_PACKET_LEN);
|
||||
if(NCC_Decrypt_Packet() && packet[1]==rx_tx_addr[0] && packet[2]==rx_tx_addr[1])
|
||||
|
||||
{
|
||||
rx_id[0]=packet[3];
|
||||
rx_id[1]=packet[4];
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
phase=NCC_BIND_TX2;
|
||||
return NCC_PACKET_INTERVAL;
|
||||
}
|
||||
}
|
||||
NCC_Write_Packet();
|
||||
phase = NCC_BIND_RX1;
|
||||
return NCC_WRITE_WAIT;
|
||||
case NCC_BIND_RX1:
|
||||
// switch to RX mode and disable CRC
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
NRF24L01_SetTxRxMode(RX_EN);
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, (0 << NRF24L01_00_EN_CRC)
|
||||
| (1 << NRF24L01_00_CRCO)
|
||||
| (1 << NRF24L01_00_PWR_UP)
|
||||
| (1 << NRF24L01_00_PRIM_RX));
|
||||
NRF24L01_FlushRx();
|
||||
phase = NCC_BIND_TX1;
|
||||
return NCC_PACKET_INTERVAL - NCC_WRITE_WAIT;
|
||||
case NCC_BIND_TX2:
|
||||
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
|
||||
{ // RX fifo data ready
|
||||
NRF24L01_ReadPayload(packet, NCC_RX_PACKET_LEN);
|
||||
if(NCC_Decrypt_Packet() && packet[1]==rx_tx_addr[0] && packet[2]==rx_tx_addr[1] && packet[3]==rx_id[0] && packet[4]==rx_id[1])
|
||||
{
|
||||
rx_id[2]=packet[8];
|
||||
rx_id[3]=packet[9];
|
||||
rx_id[4]=packet[10];
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
BIND_DONE;
|
||||
phase=NCC_TX3;
|
||||
return NCC_PACKET_INTERVAL;
|
||||
}
|
||||
}
|
||||
NCC_Write_Packet();
|
||||
phase = NCC_BIND_RX2;
|
||||
return NCC_WRITE_WAIT;
|
||||
case NCC_BIND_RX2:
|
||||
// switch to RX mode and disable CRC
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
NRF24L01_SetTxRxMode(RX_EN);
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, (0 << NRF24L01_00_EN_CRC)
|
||||
| (1 << NRF24L01_00_CRCO)
|
||||
| (1 << NRF24L01_00_PWR_UP)
|
||||
| (1 << NRF24L01_00_PRIM_RX));
|
||||
NRF24L01_FlushRx();
|
||||
phase = NCC_BIND_TX2;
|
||||
return NCC_PACKET_INTERVAL - NCC_WRITE_WAIT;
|
||||
case NCC_TX3:
|
||||
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
|
||||
{ // RX fifo data ready
|
||||
NRF24L01_ReadPayload(packet, NCC_RX_PACKET_LEN);
|
||||
if(NCC_Decrypt_Packet() && packet[1]==rx_tx_addr[0] && packet[2]==rx_tx_addr[1] && packet[3]==rx_id[0] && packet[4]==rx_id[1])
|
||||
{
|
||||
//Telemetry
|
||||
//packet[5] and packet[7] roll angle
|
||||
//packet[6] crash detect: 0x00 no crash, 0x02 crash
|
||||
#ifdef NCC1701_HUB_TELEMETRY
|
||||
v_lipo1 = packet[6]?0xFF:0x00; // Crash indication
|
||||
v_lipo2 = 0x00;
|
||||
RX_RSSI = 0x7F; // Dummy RSSI
|
||||
TX_RSSI = 0x7F; // Dummy RSSI
|
||||
telemetry_link=1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
NCC_Write_Packet();
|
||||
phase = NCC_RX3;
|
||||
return NCC_WRITE_WAIT;
|
||||
case NCC_RX3:
|
||||
// switch to RX mode and disable CRC
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
NRF24L01_SetTxRxMode(RX_EN);
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, (0 << NRF24L01_00_EN_CRC)
|
||||
| (1 << NRF24L01_00_CRCO)
|
||||
| (1 << NRF24L01_00_PWR_UP)
|
||||
| (1 << NRF24L01_00_PRIM_RX));
|
||||
NRF24L01_FlushRx();
|
||||
phase = NCC_TX3;
|
||||
return NCC_PACKET_INTERVAL - NCC_WRITE_WAIT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint8_t PROGMEM NCC_TX_DATA[][6]= {
|
||||
{ 0x6D, 0x97, 0x04, 0x48, 0x43, 0x26 },
|
||||
{ 0x35, 0x4B, 0x80, 0x44, 0x4C, 0x0B },
|
||||
{ 0x50, 0xE2, 0x32, 0x2D, 0x4B, 0x0A },
|
||||
{ 0xBF, 0x34, 0xF3, 0x45, 0x4D, 0x0D },
|
||||
{ 0xDD, 0x7D, 0x5A, 0x46, 0x28, 0x23 },
|
||||
{ 0xED, 0x19, 0x06, 0x2C, 0x4A, 0x09 },
|
||||
{ 0xE9, 0xA8, 0x91, 0x2B, 0x49, 0x07 },
|
||||
{ 0x66, 0x17, 0x7D, 0x48, 0x43, 0x26 },
|
||||
{ 0xC2, 0x93, 0x55, 0x44, 0x4C, 0x0B },
|
||||
};
|
||||
|
||||
uint16_t initNCC(void)
|
||||
{
|
||||
BIND_IN_PROGRESS; // autobind protocol
|
||||
|
||||
// Load TX data
|
||||
uint8_t rand=rx_tx_addr[3]%9;
|
||||
for(uint8_t i=0; i<3; i++)
|
||||
{
|
||||
rx_tx_addr[i]=pgm_read_byte_near(&NCC_TX_DATA[rand][i]);
|
||||
hopping_frequency[i]=pgm_read_byte_near(&NCC_TX_DATA[rand][i+3]);
|
||||
}
|
||||
|
||||
// RX data is acquired during bind
|
||||
rx_id[0]=0x00;
|
||||
rx_id[1]=0x00;
|
||||
rx_id[2]=0x20;
|
||||
rx_id[3]=0x20;
|
||||
rx_id[4]=0x20;
|
||||
|
||||
hopping_frequency[4]=0x08; // bind channel 1
|
||||
hopping_frequency[5]=0x2A; // bind channel 2
|
||||
hopping_frequency_no=4; // start with bind
|
||||
NCC_init();
|
||||
phase=NCC_BIND_TX1;
|
||||
#ifdef NCC1701_HUB_TELEMETRY
|
||||
init_frskyd_link_telemetry();
|
||||
#endif
|
||||
return 10000;
|
||||
}
|
||||
|
||||
#endif
|
@ -457,16 +457,46 @@ void XN297_WriteEnhancedPayload(uint8_t* msg, uint8_t len, uint8_t noack, uint16
|
||||
pid=0;
|
||||
}
|
||||
|
||||
void XN297_ReadPayload(uint8_t* msg, uint8_t len)
|
||||
{
|
||||
// TODO: if xn297_crc==1, check CRC before filling *msg
|
||||
NRF24L01_ReadPayload(msg, len);
|
||||
boolean XN297_ReadPayload(uint8_t* msg, uint8_t len)
|
||||
{ //!!! Don't forget if using CRC to do a +2 on any of the used NRF24L01_11_RX_PW_Px !!!
|
||||
uint8_t buf[32];
|
||||
if (xn297_crc)
|
||||
NRF24L01_ReadPayload(buf, len+2); // Read payload + CRC
|
||||
else
|
||||
NRF24L01_ReadPayload(buf, len);
|
||||
// Decode payload
|
||||
for(uint8_t i=0; i<len; i++)
|
||||
{
|
||||
uint8_t b_in=buf[i];
|
||||
if(xn297_scramble_enabled)
|
||||
msg[i] ^= xn297_scramble[i+xn297_addr_len];
|
||||
msg[i] = bit_reverse(msg[i]);
|
||||
b_in ^= xn297_scramble[i+xn297_addr_len];
|
||||
msg[i] = bit_reverse(b_in);
|
||||
}
|
||||
if (!xn297_crc)
|
||||
return true; // No CRC so OK by default...
|
||||
|
||||
// Calculate CRC
|
||||
uint16_t crc = 0xb5d2;
|
||||
//process address
|
||||
for (uint8_t i = 0; i < xn297_addr_len; ++i)
|
||||
{
|
||||
uint8_t b_in=xn297_tx_addr[xn297_addr_len-i-1];
|
||||
if(xn297_scramble_enabled)
|
||||
b_in ^= xn297_scramble[i];
|
||||
crc = crc16_update(crc, b_in, 8);
|
||||
}
|
||||
//process payload
|
||||
for (uint8_t i = 0; i < len; ++i)
|
||||
crc = crc16_update(crc, buf[i], 8);
|
||||
//xorout
|
||||
if(xn297_scramble_enabled)
|
||||
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled[xn297_addr_len - 3 + len]);
|
||||
else
|
||||
crc ^= pgm_read_word(&xn297_crc_xorout[xn297_addr_len - 3 + len]);
|
||||
//test
|
||||
if( (crc >> 8) == buf[len] && (crc & 0xff) == buf[len+1])
|
||||
return true; // CRC OK
|
||||
return false; // CRC NOK
|
||||
}
|
||||
|
||||
uint8_t XN297_ReadEnhancedPayload(uint8_t* msg, uint8_t len)
|
||||
@ -490,6 +520,111 @@ uint8_t XN297_ReadEnhancedPayload(uint8_t* msg, uint8_t len)
|
||||
|
||||
// End of XN297 emulation
|
||||
|
||||
//
|
||||
// HS6200 emulation layer
|
||||
///////////////////////////
|
||||
static uint8_t hs6200_crc;
|
||||
static uint16_t hs6200_crc_init;
|
||||
static uint8_t hs6200_tx_addr[5];
|
||||
static uint8_t hs6200_address_length;
|
||||
|
||||
static const uint8_t hs6200_scramble[] = {
|
||||
0x80,0xf5,0x3b,0x0d,0x6d,0x2a,0xf9,0xbc,
|
||||
0x51,0x8e,0x4c,0xfd,0xc1,0x65,0xd0 }; // todo: find all 32 bytes ...
|
||||
|
||||
void HS6200_SetTXAddr(const uint8_t* addr, uint8_t len)
|
||||
{
|
||||
if(len < 4)
|
||||
len = 4;
|
||||
else if(len > 5)
|
||||
len = 5;
|
||||
|
||||
// use nrf24 address field as a longer preamble
|
||||
if(addr[len-1] & 0x80)
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t*)"\x55\x55\x55\x55\x55", 5);
|
||||
else
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t*)"\xaa\xaa\xaa\xaa\xaa", 5);
|
||||
|
||||
// precompute address crc
|
||||
hs6200_crc_init = 0xffff;
|
||||
for(int i=0; i<len; i++)
|
||||
hs6200_crc_init = crc16_update(hs6200_crc_init, addr[len-1-i], 8);
|
||||
memcpy(hs6200_tx_addr, addr, len);
|
||||
hs6200_address_length = len;
|
||||
}
|
||||
|
||||
static uint16_t hs6200_calc_crc(uint8_t* msg, uint8_t len)
|
||||
{
|
||||
uint8_t pos;
|
||||
uint16_t crc = hs6200_crc_init;
|
||||
|
||||
// pcf + payload
|
||||
for(pos=0; pos < len-1; pos++)
|
||||
crc = crc16_update(crc, msg[pos], 8);
|
||||
// last byte (1 bit only)
|
||||
if(len > 0)
|
||||
crc = crc16_update(crc, msg[pos+1], 1);
|
||||
return crc;
|
||||
}
|
||||
|
||||
void HS6200_Configure(uint8_t flags)
|
||||
{
|
||||
hs6200_crc = !!(flags & _BV(NRF24L01_00_EN_CRC));
|
||||
flags &= ~(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO));
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, flags & 0xff);
|
||||
}
|
||||
|
||||
void HS6200_WritePayload(uint8_t* msg, uint8_t len)
|
||||
{
|
||||
uint8_t payload[32];
|
||||
const uint8_t no_ack = 1; // never ask for an ack
|
||||
static uint8_t pid;
|
||||
uint8_t pos = 0;
|
||||
|
||||
if(len > sizeof(hs6200_scramble))
|
||||
len = sizeof(hs6200_scramble);
|
||||
|
||||
// address
|
||||
for(int i=hs6200_address_length-1; i>=0; i--)
|
||||
payload[pos++] = hs6200_tx_addr[i];
|
||||
|
||||
// guard bytes
|
||||
payload[pos++] = hs6200_tx_addr[0];
|
||||
payload[pos++] = hs6200_tx_addr[0];
|
||||
|
||||
// packet control field
|
||||
payload[pos++] = ((len & 0x3f) << 2) | (pid & 0x03);
|
||||
payload[pos] = (no_ack & 0x01) << 7;
|
||||
pid++;
|
||||
|
||||
// scrambled payload
|
||||
if(len > 0)
|
||||
{
|
||||
payload[pos++] |= (msg[0] ^ hs6200_scramble[0]) >> 1;
|
||||
for(uint8_t i=1; i<len; i++)
|
||||
payload[pos++] = ((msg[i-1] ^ hs6200_scramble[i-1]) << 7) | ((msg[i] ^ hs6200_scramble[i]) >> 1);
|
||||
payload[pos] = (msg[len-1] ^ hs6200_scramble[len-1]) << 7;
|
||||
}
|
||||
|
||||
// crc
|
||||
if(hs6200_crc)
|
||||
{
|
||||
uint16_t crc = hs6200_calc_crc(&payload[hs6200_address_length+2], len+2);
|
||||
uint8_t hcrc = crc >> 8;
|
||||
uint8_t lcrc = crc & 0xff;
|
||||
payload[pos++] |= (hcrc >> 1);
|
||||
payload[pos++] = (hcrc << 7) | (lcrc >> 1);
|
||||
payload[pos++] = lcrc << 7;
|
||||
}
|
||||
|
||||
NRF24L01_WritePayload(payload, pos);
|
||||
delayMicroseconds(option);
|
||||
NRF24L01_WritePayload(payload, pos);
|
||||
}
|
||||
//
|
||||
// End of HS6200 emulation
|
||||
////////////////////////////
|
||||
|
||||
///////////////
|
||||
// LT8900 emulation layer
|
||||
uint8_t LT8900_buffer[64];
|
||||
|
@ -18,17 +18,37 @@
|
||||
|
||||
#include "iface_nrf24l01.h"
|
||||
|
||||
//#define SLT_Q200_FORCE_ID
|
||||
|
||||
// For code readability
|
||||
#define SLT_PAYLOADSIZE 7
|
||||
#define SLT_PAYLOADSIZE_V1 7
|
||||
#define SLT_PAYLOADSIZE_V2 11
|
||||
#define SLT_NFREQCHANNELS 15
|
||||
#define SLT_TXID_SIZE 4
|
||||
|
||||
enum{
|
||||
// flags going to packet[6] (Q200)
|
||||
FLAG_Q200_FMODE = 0x20,
|
||||
FLAG_Q200_VIDON = 0x10,
|
||||
FLAG_Q200_FLIP = 0x08,
|
||||
FLAG_Q200_VIDOFF= 0x04,
|
||||
};
|
||||
|
||||
enum{
|
||||
// flags going to packet[6] (MR100 & Q100)
|
||||
FLAG_MR100_FMODE = 0x20,
|
||||
FLAG_MR100_FLIP = 0x04,
|
||||
FLAG_MR100_VIDEO = 0x02,
|
||||
FLAG_MR100_PICTURE = 0x01,
|
||||
};
|
||||
|
||||
enum {
|
||||
SLT_BUILD=0,
|
||||
SLT_DATA1,
|
||||
SLT_DATA2,
|
||||
SLT_DATA3,
|
||||
SLT_BIND
|
||||
SLT_BIND1,
|
||||
SLT_BIND2
|
||||
};
|
||||
|
||||
static void __attribute__((unused)) SLT_init()
|
||||
@ -43,7 +63,10 @@ static void __attribute__((unused)) SLT_init()
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, 4); // bytes of data payload for pipe 1
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_250K); // 256kbps
|
||||
NRF24L01_SetPower();
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t*)"\xC3\xC3\xAA\x55", 4);
|
||||
if(sub_protocol==SLT_V1)
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t*)"\xC3\xC3\xAA\x55", SLT_TXID_SIZE);
|
||||
else // V2
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t*)"\x7E\xB8\x63\xA9", SLT_TXID_SIZE);
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, SLT_TXID_SIZE);
|
||||
NRF24L01_FlushTx();
|
||||
@ -61,13 +84,17 @@ static void __attribute__((unused)) SLT_set_freq(void)
|
||||
hopping_frequency[i*4 + 0] = (rx_tx_addr[i] & 0x3f) + base;
|
||||
hopping_frequency[i*4 + 1] = (rx_tx_addr[i] >> 2) + base;
|
||||
hopping_frequency[i*4 + 2] = (rx_tx_addr[i] >> 4) + (rx_tx_addr[next_i] & 0x03)*0x10 + base;
|
||||
if (i*4 + 3 < SLT_NFREQCHANNELS) // guard for 16 channel
|
||||
hopping_frequency[i*4 + 3] = (rx_tx_addr[i] >> 6) + (rx_tx_addr[next_i] & 0x0f)*0x04 + base;
|
||||
}
|
||||
|
||||
// unique
|
||||
// Unique freq
|
||||
uint8_t max_freq=0x50; //V1 and V2
|
||||
if(sub_protocol==Q200)
|
||||
max_freq=45;
|
||||
for (uint8_t i = 0; i < SLT_NFREQCHANNELS; ++i)
|
||||
{
|
||||
if(sub_protocol==Q200 && hopping_frequency[i] >= max_freq)
|
||||
hopping_frequency[i] = hopping_frequency[i] - max_freq + 0x03;
|
||||
uint8_t done = 0;
|
||||
while (!done)
|
||||
{
|
||||
@ -77,8 +104,8 @@ static void __attribute__((unused)) SLT_set_freq(void)
|
||||
{
|
||||
done = 0;
|
||||
hopping_frequency[i] += 7;
|
||||
if (hopping_frequency[i] >= 0x50)
|
||||
hopping_frequency[i] = hopping_frequency[i] - 0x50 + 0x03;
|
||||
if (hopping_frequency[i] >= max_freq)
|
||||
hopping_frequency[i] = hopping_frequency[i] - max_freq + 0x03;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -91,18 +118,19 @@ static void __attribute__((unused)) SLT_wait_radio()
|
||||
packet_sent = 0;
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) SLT_send_data(uint8_t *data, uint8_t len)
|
||||
static void __attribute__((unused)) SLT_send_packet(uint8_t len)
|
||||
{
|
||||
SLT_wait_radio();
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, _BV(NRF24L01_07_TX_DS) | _BV(NRF24L01_07_RX_DR) | _BV(NRF24L01_07_MAX_RT));
|
||||
NRF24L01_WritePayload(data, len);
|
||||
//NRF24L01_PulseCE();
|
||||
NRF24L01_WritePayload(packet, len);
|
||||
packet_sent = 1;
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) SLT_build_packet()
|
||||
{
|
||||
static uint8_t calib_counter=0;
|
||||
|
||||
// Set radio channel - once per packet batch
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
|
||||
if (++hopping_frequency_no >= SLT_NFREQCHANNELS)
|
||||
@ -113,6 +141,8 @@ static void __attribute__((unused)) SLT_build_packet()
|
||||
for (uint8_t i = 0; i < 4; ++i)
|
||||
{
|
||||
uint16_t v = convert_channel_10b(CH_AETR[i]);
|
||||
if(sub_protocol>SLT_V2 && (CH_AETR[i]==THROTTLE || CH_AETR[i]==ELEVATOR) )
|
||||
v=1023-v; // reverse throttle and elevator channels for Q100/Q200/MR100 protocols
|
||||
packet[i] = v;
|
||||
e = (e >> 2) | (uint8_t) ((v >> 2) & 0xC0);
|
||||
}
|
||||
@ -121,6 +151,33 @@ static void __attribute__((unused)) SLT_build_packet()
|
||||
// 8-bit channels
|
||||
packet[5] = convert_channel_8b(CH5);
|
||||
packet[6] = convert_channel_8b(CH6);
|
||||
if(sub_protocol!=SLT_V1)
|
||||
{
|
||||
if(sub_protocol==Q200)
|
||||
packet[6] = GET_FLAG(CH9_SW , FLAG_Q200_FMODE)
|
||||
|GET_FLAG(CH10_SW, FLAG_Q200_FLIP)
|
||||
|GET_FLAG(CH11_SW, FLAG_Q200_VIDON)
|
||||
|GET_FLAG(CH12_SW, FLAG_Q200_VIDOFF);
|
||||
else if(sub_protocol==MR100 || sub_protocol==Q100)
|
||||
packet[6] = GET_FLAG(CH9_SW , FLAG_MR100_FMODE)
|
||||
|GET_FLAG(CH10_SW, FLAG_MR100_FLIP)
|
||||
|GET_FLAG(CH11_SW, FLAG_MR100_VIDEO) // Does not exist on the Q100 but...
|
||||
|GET_FLAG(CH12_SW, FLAG_MR100_PICTURE); // Does not exist on the Q100 but...
|
||||
packet[7]=convert_channel_8b(CH7);
|
||||
packet[8]=convert_channel_8b(CH8);
|
||||
packet[9]=0xAA; //normal mode for Q100/Q200, unknown for V2/MR100
|
||||
packet[10]=0x00; //normal mode for Q100/Q200, unknown for V2/MR100
|
||||
if((sub_protocol==Q100 || sub_protocol==Q200) && CH13_SW)
|
||||
{//Calibrate
|
||||
packet[9]=0x77; //enter calibration
|
||||
if(calib_counter>=20 && calib_counter<=25) // 7 packets for Q100 / 3 packets for Q200
|
||||
packet[10]=0x20; //launch calibration
|
||||
calib_counter++;
|
||||
if(calib_counter>250) calib_counter=250;
|
||||
}
|
||||
else
|
||||
calib_counter=0;
|
||||
}
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) SLT_send_bind_packet()
|
||||
@ -132,14 +189,25 @@ static void __attribute__((unused)) SLT_send_bind_packet()
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t *)"\x7E\xB8\x63\xA9", SLT_TXID_SIZE);
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x50);
|
||||
SLT_send_data(rx_tx_addr, SLT_TXID_SIZE);
|
||||
memcpy((void*)packet,(void*)rx_tx_addr,SLT_TXID_SIZE);
|
||||
if(phase==SLT_BIND2)
|
||||
SLT_send_packet(SLT_TXID_SIZE);
|
||||
else // SLT_BIND1
|
||||
SLT_send_packet(SLT_PAYLOADSIZE_V2);
|
||||
|
||||
SLT_wait_radio(); //Wait until the packet's sent before changing TX address!
|
||||
|
||||
NRF24L01_SetPower(); //Change power back to normal level
|
||||
if(phase==SLT_BIND2) // after V1 bind and V2 second bind packet
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, SLT_TXID_SIZE);
|
||||
}
|
||||
|
||||
#define SLT_TIMING_BUILD 1000
|
||||
#define SLT_V1_TIMING_PACKET 1000
|
||||
#define SLT_V2_TIMING_PACKET 2042
|
||||
#define SLT_V1_TIMING_BIND2 1000
|
||||
#define SLT_V2_TIMING_BIND1 6507
|
||||
#define SLT_V2_TIMING_BIND2 2112
|
||||
uint16_t SLT_callback()
|
||||
{
|
||||
switch (phase)
|
||||
@ -147,33 +215,59 @@ uint16_t SLT_callback()
|
||||
case SLT_BUILD:
|
||||
SLT_build_packet();
|
||||
phase++;
|
||||
return 1000;
|
||||
return SLT_TIMING_BUILD;
|
||||
case SLT_DATA1:
|
||||
SLT_send_data(packet, SLT_PAYLOADSIZE);
|
||||
phase++;
|
||||
return 1000;
|
||||
case SLT_DATA2:
|
||||
SLT_send_data(packet, SLT_PAYLOADSIZE);
|
||||
phase++;
|
||||
return 1000;
|
||||
case SLT_DATA3:
|
||||
SLT_send_data(packet, SLT_PAYLOADSIZE);
|
||||
if (++packet_count >= 100)
|
||||
if(sub_protocol==SLT_V1)
|
||||
{
|
||||
SLT_send_packet(SLT_PAYLOADSIZE_V1);
|
||||
return SLT_V1_TIMING_PACKET;
|
||||
}
|
||||
else //V2
|
||||
{
|
||||
SLT_send_packet(SLT_PAYLOADSIZE_V2);
|
||||
return SLT_V2_TIMING_PACKET;
|
||||
}
|
||||
case SLT_DATA3:
|
||||
if(sub_protocol==SLT_V1)
|
||||
SLT_send_packet(SLT_PAYLOADSIZE_V1);
|
||||
else //V2
|
||||
SLT_send_packet(SLT_PAYLOADSIZE_V2);
|
||||
if (++packet_count >= 100)
|
||||
{// Send bind packet
|
||||
packet_count = 0;
|
||||
phase++;
|
||||
return 1000;
|
||||
if(sub_protocol==SLT_V1)
|
||||
{
|
||||
phase=SLT_BIND2;
|
||||
return SLT_V1_TIMING_BIND2;
|
||||
}
|
||||
else //V2
|
||||
{
|
||||
phase=SLT_BIND1;
|
||||
return SLT_V2_TIMING_BIND1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
{// Continue to send normal packets
|
||||
NRF24L01_SetPower(); // Set tx_power
|
||||
phase = SLT_BUILD;
|
||||
return 19000;
|
||||
if(sub_protocol==SLT_V1)
|
||||
return 20000-SLT_TIMING_BUILD;
|
||||
else //V2
|
||||
return 13730-SLT_TIMING_BUILD;
|
||||
}
|
||||
case SLT_BIND:
|
||||
case SLT_BIND1:
|
||||
SLT_send_bind_packet();
|
||||
phase++;
|
||||
return SLT_V2_TIMING_BIND2;
|
||||
case SLT_BIND2:
|
||||
SLT_send_bind_packet();
|
||||
phase = SLT_BUILD;
|
||||
return 18000;
|
||||
if(sub_protocol==SLT_V1)
|
||||
return 20000-SLT_TIMING_BUILD-SLT_V1_TIMING_BIND2;
|
||||
else //V2
|
||||
return 13730-SLT_TIMING_BUILD-SLT_V2_TIMING_BIND1-SLT_V2_TIMING_BIND2;
|
||||
}
|
||||
return 19000;
|
||||
}
|
||||
@ -183,9 +277,18 @@ uint16_t initSLT()
|
||||
packet_count = 0;
|
||||
packet_sent = 0;
|
||||
hopping_frequency_no = 0;
|
||||
if(sub_protocol==Q200)
|
||||
{ //Q200: Force high part of the ID otherwise it won't bind
|
||||
rx_tx_addr[0]=0x01;
|
||||
rx_tx_addr[1]=0x02;
|
||||
#ifdef SLT_Q200_FORCE_ID // ID taken from TX dumps
|
||||
rx_tx_addr[0]=0x01;rx_tx_addr[1]=0x02;rx_tx_addr[2]=0x6A;rx_tx_addr[3]=0x31;
|
||||
/* rx_tx_addr[0]=0x01;rx_tx_addr[1]=0x02;rx_tx_addr[2]=0x0B;rx_tx_addr[3]=0x57;*/
|
||||
#endif
|
||||
}
|
||||
SLT_set_freq();
|
||||
SLT_init();
|
||||
phase = SLT_BIND;
|
||||
phase = SLT_BUILD;
|
||||
return 50000;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
if (protocol==PROTO_HUBSAN||protocol==PROTO_AFHDS2A||protocol==PROTO_BAYANG||protocol==PROTO_NCC1701||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
|
||||
{ // FrSkyD + Hubsan + AFHDS2A + Bayang + Cabell + Hitec + Bugs + BugsMini + NCC1701
|
||||
frsky_link_frame();
|
||||
return;
|
||||
}
|
||||
|
175
Multiprotocol/V911S_nrf24l01.ino
Normal file
175
Multiprotocol/V911S_nrf24l01.ino
Normal file
@ -0,0 +1,175 @@
|
||||
/*
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// compatible with V911S
|
||||
|
||||
#if defined(V911S_NRF24L01_INO)
|
||||
|
||||
#include "iface_nrf24l01.h"
|
||||
|
||||
//#define V911S_ORIGINAL_ID
|
||||
|
||||
#define V911S_PACKET_PERIOD 5000
|
||||
#define V911S_BIND_PACKET_PERIOD 3300
|
||||
#define V911S_INITIAL_WAIT 500
|
||||
#define V911S_PACKET_SIZE 16
|
||||
#define V911S_RF_BIND_CHANNEL 35
|
||||
#define V911S_NUM_RF_CHANNELS 8
|
||||
#define V911S_BIND_COUNT 200
|
||||
|
||||
// flags going to packet[1]
|
||||
#define V911S_FLAG_EXPERT 0x04
|
||||
// flags going to packet[2]
|
||||
#define V911S_FLAG_CALIB 0x01
|
||||
|
||||
static void __attribute__((unused)) V911S_send_packet(uint8_t bind)
|
||||
{
|
||||
if(bind)
|
||||
{
|
||||
packet[0] = 0x42;
|
||||
packet[1] = 0x4E;
|
||||
packet[2] = 0x44;
|
||||
for(uint8_t i=0;i<5;i++)
|
||||
packet[i+3] = rx_tx_addr[i];
|
||||
for(uint8_t i=0;i<8;i++)
|
||||
packet[i+8] = hopping_frequency[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t channel=hopping_frequency_no;
|
||||
if(rf_ch_num&1)
|
||||
{
|
||||
if((hopping_frequency_no&1)==0)
|
||||
channel+=8;
|
||||
channel>>=1;
|
||||
}
|
||||
if(rf_ch_num&2)
|
||||
channel=7-channel;
|
||||
packet[ 0]=(rf_ch_num<<3)|channel;
|
||||
packet[ 1]=V911S_FLAG_EXPERT; // short press on left button
|
||||
packet[ 2]=GET_FLAG(CH5_SW,V911S_FLAG_CALIB); // long press on right button
|
||||
memset(packet+3,0x00,14);
|
||||
//packet[3..6]=trims TAER signed
|
||||
uint16_t ch=convert_channel_16b_limit(THROTTLE ,0,0x7FF);
|
||||
packet[ 7] = ch;
|
||||
packet[ 8] = ch>>8;
|
||||
ch=convert_channel_16b_limit(AILERON ,0x7FF,0);
|
||||
packet[ 8]|= ch<<3;
|
||||
packet[ 9] = ch>>5;
|
||||
ch=convert_channel_16b_limit(ELEVATOR,0,0x7FF);
|
||||
packet[10] = ch;
|
||||
packet[11] = ch>>8;
|
||||
ch=convert_channel_16b_limit(RUDDER ,0x7FF,0);
|
||||
packet[11]|= ch<<3;
|
||||
packet[12] = ch>>5;
|
||||
}
|
||||
|
||||
// Power on, TX mode, 2byte CRC
|
||||
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
|
||||
if (!bind)
|
||||
{
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[channel]);
|
||||
hopping_frequency_no++;
|
||||
hopping_frequency_no&=7; // 8 RF channels
|
||||
}
|
||||
// clear packet status bits and TX FIFO
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
||||
NRF24L01_FlushTx();
|
||||
XN297_WritePayload(packet, V911S_PACKET_SIZE);
|
||||
|
||||
NRF24L01_SetPower(); // Set tx_power
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) V911S_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
XN297_SetTXAddr((uint8_t *)"\x4B\x4E\x42\x4E\x44", 5); // Bind address
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, V911S_RF_BIND_CHANNEL); // Bind channel
|
||||
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_SetBitrate(NRF24L01_BR_250K); // 250Kbps
|
||||
NRF24L01_SetPower();
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) V911S_initialize_txid()
|
||||
{
|
||||
//channels
|
||||
uint8_t offset=rx_tx_addr[3]%5; // 0-4
|
||||
for(uint8_t i=0;i<V911S_NUM_RF_CHANNELS;i++)
|
||||
hopping_frequency[i]=0x10+i*5+offset;
|
||||
if(!offset) hopping_frequency[0]++;
|
||||
|
||||
// channels order
|
||||
rf_ch_num=random(0xfefefefe)&0x03; // 0-3
|
||||
}
|
||||
|
||||
uint16_t V911S_callback()
|
||||
{
|
||||
if(IS_BIND_DONE)
|
||||
V911S_send_packet(0);
|
||||
else
|
||||
{
|
||||
if (bind_counter == 0)
|
||||
{
|
||||
BIND_DONE;
|
||||
XN297_SetTXAddr(rx_tx_addr, 5);
|
||||
packet_period=V911S_PACKET_PERIOD;
|
||||
}
|
||||
else
|
||||
{
|
||||
V911S_send_packet(1);
|
||||
bind_counter--;
|
||||
if(bind_counter==100) // same as original TX...
|
||||
packet_period=V911S_BIND_PACKET_PERIOD*3;
|
||||
}
|
||||
}
|
||||
return packet_period;
|
||||
}
|
||||
|
||||
uint16_t initV911S(void)
|
||||
{
|
||||
V911S_initialize_txid();
|
||||
#ifdef V911S_ORIGINAL_ID
|
||||
rx_tx_addr[0]=0xA5;
|
||||
rx_tx_addr[1]=0xFF;
|
||||
rx_tx_addr[2]=0x70;
|
||||
rx_tx_addr[3]=0x8D;
|
||||
rx_tx_addr[4]=0x76;
|
||||
for(uint8_t i=0;i<V911S_NUM_RF_CHANNELS;i++)
|
||||
hopping_frequency[i]=0x10+i*5;
|
||||
hopping_frequency[0]++;
|
||||
rf_ch_num=0;
|
||||
#endif
|
||||
|
||||
V911S_init();
|
||||
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
bind_counter = V911S_BIND_COUNT;
|
||||
packet_period= V911S_BIND_PACKET_PERIOD;
|
||||
}
|
||||
else
|
||||
{
|
||||
XN297_SetTXAddr(rx_tx_addr, 5);
|
||||
packet_period= V911S_PACKET_PERIOD;
|
||||
}
|
||||
hopping_frequency_no=0;
|
||||
return V911S_INITIAL_WAIT;
|
||||
}
|
||||
|
||||
#endif
|
@ -138,6 +138,7 @@
|
||||
#undef FLYSKY_A7105_INO
|
||||
#undef HUBSAN_A7105_INO
|
||||
#undef AFHDS2A_A7105_INO
|
||||
#undef BUGS_A7105_INO
|
||||
#endif
|
||||
#ifndef CYRF6936_INSTALLED
|
||||
#undef DEVO_CYRF6936_INO
|
||||
@ -145,6 +146,7 @@
|
||||
#undef J6PRO_CYRF6936_INO
|
||||
#undef WFLY_CYRF6936_INO
|
||||
#undef WK2x01_CYRF6936_INO
|
||||
#undef TRAXXAS_CYRF6936_INO
|
||||
#endif
|
||||
#ifndef CC2500_INSTALLED
|
||||
#undef FRSKYD_CC2500_INO
|
||||
@ -174,11 +176,16 @@
|
||||
#undef HONTAI_NRF24L01_INO
|
||||
#undef Q303_NRF24L01_INO
|
||||
#undef GW008_NRF24L01_INO
|
||||
#undef GD00X_NRF24L01_INO
|
||||
#undef DM002_NRF24L01_INO
|
||||
#undef CABELL_NRF24L01_INO
|
||||
#undef ESKY150_NRF24L01_INO
|
||||
#undef H8_3D_NRF24L01_INO
|
||||
#undef CFLIE_NRF24L01_INO
|
||||
#undef BUGSMINI_NRF24L01_INO
|
||||
#undef NCC1701_NRF24L01_INO
|
||||
#undef E01X_NRF24L01_INO
|
||||
#undef V911S_NRF24L01_INO
|
||||
#endif
|
||||
|
||||
//Make sure telemetry is selected correctly
|
||||
@ -191,6 +198,8 @@
|
||||
#undef BAYANG_HUB_TELEMETRY
|
||||
#undef CABELL_HUB_TELEMETRY
|
||||
#undef HUBSAN_HUB_TELEMETRY
|
||||
#undef BUGS_HUB_TELEMETRY
|
||||
#undef NCC1701_HUB_TELEMETRY
|
||||
#undef HUB_TELEMETRY
|
||||
#undef SPORT_TELEMETRY
|
||||
#undef SPORT_POLLING
|
||||
@ -204,6 +213,12 @@
|
||||
#if not defined(BAYANG_NRF24L01_INO)
|
||||
#undef BAYANG_HUB_TELEMETRY
|
||||
#endif
|
||||
#if not defined(NCC1701_NRF24L01_INO)
|
||||
#undef NCC1701_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
|
||||
@ -234,7 +249,7 @@
|
||||
#if not defined(DSM_CYRF6936_INO)
|
||||
#undef DSM_TELEMETRY
|
||||
#endif
|
||||
#if not defined(DSM_TELEMETRY) && not defined(SPORT_TELEMETRY) && not defined(HUB_TELEMETRY) && not defined(HUBSAN_HUB_TELEMETRY) && not defined(BAYANG_HUB_TELEMETRY) && not defined(CABELL_HUB_TELEMETRY) && not defined(AFHDS2A_HUB_TELEMETRY) && not defined(AFHDS2A_FW_TELEMETRY) && not defined(MULTI_TELEMETRY) && not defined(MULTI_STATUS) && not defined(HITEC_HUB_TELEMETRY) && not defined(HITEC_FW_TELEMETRY)
|
||||
#if not defined(DSM_TELEMETRY) && not defined(SPORT_TELEMETRY) && not defined(HUB_TELEMETRY) && not defined(HUBSAN_HUB_TELEMETRY) && not defined(BUGS_HUB_TELEMETRY) && not defined(NCC1701_HUB_TELEMETRY) && not defined(BAYANG_HUB_TELEMETRY) && not defined(CABELL_HUB_TELEMETRY) && not defined(AFHDS2A_HUB_TELEMETRY) && not defined(AFHDS2A_FW_TELEMETRY) && not defined(MULTI_TELEMETRY) && not defined(MULTI_STATUS) && not defined(HITEC_HUB_TELEMETRY) && not defined(HITEC_FW_TELEMETRY)
|
||||
#undef TELEMETRY
|
||||
#undef INVERT_TELEMETRY
|
||||
#undef SPORT_POLLING
|
||||
@ -258,6 +273,24 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(DSM_THROTTLE_KILL_CH)
|
||||
#if DSM_THROTTLE_KILL_CH<4
|
||||
#error DSM_THROTTLE_KILL_CH must be above 4.
|
||||
#endif
|
||||
#if DSM_THROTTLE_KILL_CH>16
|
||||
#error DSM_THROTTLE_KILL_CH must be below or equal to 16.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(AFHDS2A_LQI_CH)
|
||||
#if AFHDS2A_LQI_CH<4
|
||||
#error AFHDS2A_LQI_CH must be above 4.
|
||||
#endif
|
||||
#if AFHDS2A_LQI_CH>14
|
||||
#error AFHDS2A_LQI_CH must be below or equal to 14.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if MIN_PPM_CHANNELS>16
|
||||
#error MIN_PPM_CHANNELS must be below or equal to 16. The default for this value is 4.
|
||||
#endif
|
||||
|
@ -57,7 +57,7 @@ const uint8_t PROGMEM WFLY_init_vals[][2] = {
|
||||
|
||||
static void __attribute__((unused)) WFLY_cyrf_bind_config()
|
||||
{
|
||||
for(uint8_t i = 0; i < sizeof(init_vals) / 2; i++)
|
||||
for(uint8_t i = 0; i < sizeof(WFLY_init_vals) / 2; i++)
|
||||
CYRF_WriteRegister(pgm_read_byte_near(&WFLY_init_vals[i][0]), pgm_read_byte_near(&WFLY_init_vals[i][1]));
|
||||
|
||||
CYRF_PROGMEM_ConfigSOPCode(WFLY_sop_bind);
|
||||
@ -67,7 +67,7 @@ static void __attribute__((unused)) WFLY_cyrf_bind_config()
|
||||
|
||||
static void __attribute__((unused)) WFLY_cyrf_data_config()
|
||||
{
|
||||
for(uint8_t i = 0; i < (sizeof(init_vals) / 2)-3; i++)
|
||||
for(uint8_t i = 0; i < (sizeof(WFLY_init_vals) / 2)-3; i++)
|
||||
CYRF_WriteRegister(pgm_read_byte_near(&WFLY_init_vals[i][0]), pgm_read_byte_near(&WFLY_init_vals[i][1]));
|
||||
|
||||
//CYRF_WriteRegister(CYRF_1E_RX_OVERRIDE, 0x08); // Do not accept CRC with 0 seed but not needed since the RX is not sending any data...
|
||||
|
@ -49,24 +49,19 @@
|
||||
//#define REVERSE_THROTTLE
|
||||
//#define REVERSE_RUDDER
|
||||
|
||||
//DSM protocol is using by default the Spektrum throw of 1100..1900us @100% and 1000..2000us @125%.
|
||||
//For more throw, 1024..1976us @100% and 904..2096us @125%, remove the "//" on the line below. Be aware that too much throw can damage some UMX servos. To achieve standard throw in this mode use a channel weight of 84%.
|
||||
//#define DSM_MAX_THROW
|
||||
|
||||
/*************************/
|
||||
/*** BIND FROM CHANNEL ***/
|
||||
/*************************/
|
||||
/*****************/
|
||||
/*** AUTO BIND ***/ // Also referred as "Bind on powerup"
|
||||
/*****************/
|
||||
//Bind from channel enables you to bind when a specified channel is going from low to high. This feature is only active
|
||||
// if you specify AUTOBIND in PPM mode or set AutoBind to YES for serial mode. It also requires that the throttle channel is low.
|
||||
|
||||
//Comment to globaly disable the bind feature from a channel.
|
||||
#define ENABLE_BIND_CH
|
||||
|
||||
//Set the channel number used for bind. Default is 16.
|
||||
#define BIND_CH 16
|
||||
|
||||
//Comment to disable the wait for bind feature. This feature will not activate the selected
|
||||
// protocol unless a bind is requested using bind from channel or the GUI "Bind" button.
|
||||
//Comment to disable the wait for bind feature. If Autobind is enabled in the model config, this feature will not activate
|
||||
// the selected protocol unless a bind is requested using bind from channel or the GUI "Bind" button.
|
||||
//The goal is to prevent binding other people's model when powering up the TX, changing model or scanning through protocols.
|
||||
#define WAIT_FOR_BIND
|
||||
|
||||
@ -75,7 +70,7 @@
|
||||
/*** RF CHIPS ***/
|
||||
/****************/
|
||||
//There are 4 RF components supported. If one of them is not installed you must comment it using "//".
|
||||
//If a chip is not installed all associated protocols are disabled.
|
||||
//If a chip is not installed all associated protocols are automatically disabled.
|
||||
//4-in-1 modules have all RF chips installed
|
||||
//!!!If a RF chip is present it MUST be marked as installed!!! or weird things will happen you have been warned.
|
||||
#define A7105_INSTALLED
|
||||
@ -112,6 +107,7 @@
|
||||
//#define FORCE_FLYSKY_TUNING 0
|
||||
//#define FORCE_HUBSAN_TUNING 0
|
||||
//#define FORCE_AFHDS2A_TUNING 0
|
||||
//#define FORCE_BUGS_TUNING 0
|
||||
|
||||
/** Low Power **/
|
||||
//Low power is reducing the transmit power of the multi module. This setting is configurable per model in PPM (table below) or Serial mode (radio GUI).
|
||||
@ -151,6 +147,7 @@
|
||||
#define AFHDS2A_A7105_INO
|
||||
#define FLYSKY_A7105_INO
|
||||
#define HUBSAN_A7105_INO
|
||||
#define BUGS_A7105_INO
|
||||
|
||||
//The protocols below need a CYRF6936 to be installed
|
||||
#define DEVO_CYRF6936_INO
|
||||
@ -158,6 +155,7 @@
|
||||
#define J6PRO_CYRF6936_INO
|
||||
#define WFLY_CYRF6936_INO
|
||||
#define WK2x01_CYRF6936_INO
|
||||
//#define TRAXXAS_CYRF6936_INO
|
||||
|
||||
//The protocols below need a CC2500 to be installed
|
||||
#define CORONA_CC2500_INO
|
||||
@ -170,15 +168,18 @@
|
||||
//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
|
||||
#define CX10_NRF24L01_INO // Include Q2X2 protocol
|
||||
#define CX10_NRF24L01_INO //Include Q2X2 protocol
|
||||
#define DM002_NRF24L01_INO
|
||||
#define E01X_NRF24L01_INO
|
||||
#define ESKY_NRF24L01_INO
|
||||
#define ESKY150_NRF24L01_INO
|
||||
#define FQ777_NRF24L01_INO
|
||||
#define FY326_NRF24L01_INO
|
||||
#define GD00X_NRF24L01_INO
|
||||
#define GW008_NRF24L01_INO
|
||||
#define HISKY_NRF24L01_INO
|
||||
#define HONTAI_NRF24L01_INO
|
||||
@ -186,14 +187,37 @@
|
||||
#define KN_NRF24L01_INO
|
||||
#define MJXQ_NRF24L01_INO
|
||||
#define MT99XX_NRF24L01_INO
|
||||
#define NCC1701_NRF24L01_INO
|
||||
#define Q303_NRF24L01_INO
|
||||
#define SHENQI_NRF24L01_INO
|
||||
#define SLT_NRF24L01_INO
|
||||
#define SYMAX_NRF24L01_INO
|
||||
#define V2X2_NRF24L01_INO
|
||||
#define V911S_NRF24L01_INO
|
||||
#define YD717_NRF24L01_INO
|
||||
|
||||
|
||||
/***************************/
|
||||
/*** PROTOCOLS SETTINGS ***/
|
||||
/***************************/
|
||||
|
||||
//DSM specific settings
|
||||
//---------------------
|
||||
//The DSM protocol is using by default the Spektrum throw of 1100..1900us @100% and 1000..2000us @125%.
|
||||
// For more throw, 1024..1976us @100% and 904..2096us @125%, remove the "//" on the line below. Be aware that too much throw can damage some UMX servos. To achieve standard throw in this mode use a channel weight of 84%.
|
||||
//#define DSM_MAX_THROW
|
||||
//Some models (X-Vert, Blade 230S...) require a special value to instant stop the motor(s).
|
||||
// You can disable this feature by adding "//" on the line below. You have to specify which channel (15 by default) will be used to kill the throttle channel.
|
||||
// If the channel 15 is above -50% the throttle is untouched but if it is between -50% and -100%, the throttle output will be forced between -100% and -150%.
|
||||
// For example, a value of -80% applied on channel 15 will instantly kill the motors on the X-Vert.
|
||||
#define DSM_THROTTLE_KILL_CH 15
|
||||
|
||||
//AFHDS2A specific settings
|
||||
//-------------------------
|
||||
//When enabled (remove the "//"), the below setting makes LQI (Link Quality Indicator) available on one of the RX ouput channel (5-14).
|
||||
//#define AFHDS2A_LQI_CH 14
|
||||
|
||||
|
||||
/**************************/
|
||||
/*** FAILSAFE SETTINGS ***/
|
||||
/**************************/
|
||||
@ -207,7 +231,7 @@
|
||||
//Value between -125% and +125%. Default -100.
|
||||
#define FAILSAFE_THROTTLE_LOW -100
|
||||
|
||||
//The radio using serial protocol can set failsafe data (ersky9x only for now).
|
||||
//The radio using serial protocol can set failsafe data.
|
||||
// Two options are available:
|
||||
// a. replace the default failsafe data with serial failsafe data when they are received.
|
||||
// b. wait for the radio to provide failsafe before sending it. Enable advanced settings like "FAILSAFE NOT SET" or "FAILSAFE RX".
|
||||
@ -247,7 +271,9 @@
|
||||
#define AFHDS2A_HUB_TELEMETRY // Use FrSkyD Hub format to send basic telemetry to TX like er9x
|
||||
#define HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
||||
#define BAYANG_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
||||
#define BUGS_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
||||
#define HUBSAN_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
||||
#define NCC1701_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
||||
#define CABELL_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
||||
#define HITEC_HUB_TELEMETRY // Use FrSkyD Hub format to send basic telemetry to the radios which can decode it like er9x, ersky9x and OpenTX
|
||||
#define HITEC_FW_TELEMETRY // Under development: Forward received telemetry packets to be decoded by ersky9x and OpenTX
|
||||
@ -255,6 +281,7 @@
|
||||
//SPORT_POLLING is an implementation of the same polling routine as XJT module for sport telemetry bidirectional communication.
|
||||
//This is useful for passing sport control frames from TX to RX(ex: changing Betaflight PID or VTX channels on the fly using LUA scripts with OpentX).
|
||||
//Using this feature requires to uncomment INVERT_TELEMETRY as this TX output on telemetry pin only inverted signal.
|
||||
//!!!! This is a work in progress!!! Do not enable unless you want to test and report
|
||||
//#define SPORT_POLLING
|
||||
|
||||
|
||||
@ -263,7 +290,7 @@
|
||||
/****************************/
|
||||
//In this section you can configure the serial mode.
|
||||
//The serial mode enables full editing of all the parameters in the GUI of the radio. It is enabled by placing the rotary switch on position 0.
|
||||
//This is available natively for ER9X and ERSKY9X. It is available for OpenTX on Taranis with a special version.
|
||||
//This is available natively for ER9X, ERSKY9X and OpenTX.
|
||||
|
||||
//If you do not plan to use the Serial mode comment this line using "//" to save Flash space
|
||||
#define ENABLE_SERIAL
|
||||
@ -331,11 +358,11 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
|
||||
/* 6 */ {PROTO_AFHDS2A, PWM_IBUS , 2 , P_HIGH , NO_AUTOBIND , 0 }, // RX number 4
|
||||
/* 7 */ {PROTO_AFHDS2A, PWM_IBUS , 3 , P_HIGH , NO_AUTOBIND , 0 }, // RX number 5
|
||||
/* 8 */ {PROTO_SFHSS, H107 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 9 */ {PROTO_FRSKYV, 0 , 0 , P_HIGH , NO_AUTOBIND , 40 }, // option=fine freq tuning
|
||||
/* 10 */ {PROTO_FRSKYD, 0 , 0 , P_HIGH , NO_AUTOBIND , 40 }, // option=fine freq tuning
|
||||
/* 9 */ {PROTO_FRSKYV, NONE , 0 , P_HIGH , NO_AUTOBIND , 40 }, // option=fine freq tuning
|
||||
/* 10 */ {PROTO_FRSKYD, NONE , 0 , P_HIGH , NO_AUTOBIND , 40 }, // option=fine freq tuning
|
||||
/* 11 */ {PROTO_FRSKYX, CH_16 , 0 , P_HIGH , NO_AUTOBIND , 40 }, // option=fine freq tuning
|
||||
/* 12 */ {PROTO_FRSKYX, EU_16 , 0 , P_HIGH , NO_AUTOBIND , 40 }, // option=fine freq tuning
|
||||
/* 13 */ {PROTO_DEVO , 0 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 13 */ {PROTO_DEVO , NONE , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 14 */ {PROTO_WK2x01, WK2801 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
#endif
|
||||
#if NBR_BANKS > 1
|
||||
@ -349,21 +376,21 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
|
||||
/* 6 */ {PROTO_DSM , DSM2_22 , 0 , P_HIGH , NO_AUTOBIND , 8 }, // option=number of channels
|
||||
/* 7 */ {PROTO_DSM , DSMX_11 , 0 , P_HIGH , NO_AUTOBIND , 8 }, // option=number of channels
|
||||
/* 8 */ {PROTO_DSM , DSMX_22 , 0 , P_HIGH , NO_AUTOBIND , 8 }, // option=number of channels
|
||||
/* 9 */ {PROTO_SLT , 0 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 9 */ {PROTO_SLT , SLT_V1 , 0 , P_HIGH , NO_AUTOBIND , 6 },
|
||||
/* 10 */ {PROTO_HUBSAN, H107 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 11 */ {PROTO_HUBSAN, H301 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 12 */ {PROTO_HUBSAN, H501 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 13 */ {PROTO_HISKY , Hisky , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 14 */ {PROTO_V2X2 , 0 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 13 */ {PROTO_HISKY, Hisky , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 14 */ {PROTO_V2X2 , NONE , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
#endif
|
||||
#if NBR_BANKS > 2
|
||||
//****************************** BANK 3 ******************************
|
||||
// Switch Protocol Sub protocol RX_Num Power Auto Bind Option
|
||||
/* 1 */ {PROTO_ESKY , 0 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 2 */ {PROTO_ESKY150, 0 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 3 */ {PROTO_ASSAN, 0 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 1 */ {PROTO_ESKY , NONE , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 2 */ {PROTO_ESKY150, NONE , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 3 */ {PROTO_ASSAN, NONE , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 4 */ {PROTO_CORONA, COR_V2 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 5 */ {PROTO_SYMAX , SYMAX , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 5 */ {PROTO_SYMAX, SYMAX , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 6 */ {PROTO_KN , WLTOYS , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 7 */ {PROTO_BAYANG, BAYANG , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 8 */ {PROTO_BAYANG, H8S3D , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
@ -406,159 +433,11 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
|
||||
/* 9 */ {PROTO_Q2X2 , Q282 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 10 */ {PROTO_CG023, CG023 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 11 */ {PROTO_CG023, YD829 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 12 */ {PROTO_FQ777, 0 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 12 */ {PROTO_FQ777, NONE , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 13 */ {PROTO_YD717, YD717 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 14 */ {PROTO_MT99XX, MT99 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
#endif
|
||||
};
|
||||
/* Available protocols and associated sub protocols to pick and choose from
|
||||
PROTO_FLYSKY
|
||||
Flysky
|
||||
V9X9
|
||||
V6X6
|
||||
V912
|
||||
CX20
|
||||
PROTO_HUBSAN
|
||||
H107
|
||||
H301
|
||||
H501
|
||||
PROTO_FRSKYV
|
||||
NONE
|
||||
PROTO_FRSKYD
|
||||
NONE
|
||||
PROTO_FRSKYX
|
||||
CH_16
|
||||
CH_8
|
||||
EU_16
|
||||
EU_8
|
||||
PROTO_HISKY
|
||||
Hisky
|
||||
HK310
|
||||
PROTO_V2X2
|
||||
V2X2
|
||||
JXD506
|
||||
PROTO_DSM
|
||||
DSM2_22
|
||||
DSM2_11
|
||||
DSMX_22
|
||||
DSMX_11
|
||||
PROTO_DEVO
|
||||
NONE
|
||||
PROTO_YD717
|
||||
YD717
|
||||
SKYWLKR
|
||||
SYMAX4
|
||||
XINXUN
|
||||
NIHUI
|
||||
PROTO_KN
|
||||
WLTOYS
|
||||
FEILUN
|
||||
PROTO_SYMAX
|
||||
SYMAX
|
||||
SYMAX5C
|
||||
PROTO_SLT
|
||||
NONE
|
||||
PROTO_CX10
|
||||
CX10_GREEN
|
||||
CX10_BLUE
|
||||
DM007
|
||||
JC3015_1
|
||||
JC3015_2
|
||||
MK33041
|
||||
PROTO_Q2X2
|
||||
Q222
|
||||
Q242
|
||||
Q282
|
||||
PROTO_SLT
|
||||
SLT
|
||||
VISTA
|
||||
PROTO_CG023
|
||||
CG023
|
||||
YD829
|
||||
PROTO_BAYANG
|
||||
BAYANG
|
||||
H8S3D
|
||||
X16_AH
|
||||
IRDRONE
|
||||
PROTO_ESKY
|
||||
NONE
|
||||
PROTO_MT99XX
|
||||
MT99
|
||||
H7
|
||||
YZ
|
||||
LS
|
||||
FY805
|
||||
PROTO_MJXQ
|
||||
WLH08
|
||||
X600
|
||||
X800
|
||||
H26D
|
||||
E010
|
||||
H26WH
|
||||
PROTO_SHENQI
|
||||
NONE
|
||||
PROTO_FY326
|
||||
FY326
|
||||
FY319
|
||||
PROTO_SFHSS
|
||||
NONE
|
||||
PROTO_J6PRO
|
||||
NONE
|
||||
PROTO_FQ777
|
||||
NONE
|
||||
PROTO_ASSAN
|
||||
NONE
|
||||
PROTO_HONTAI
|
||||
HONTAI
|
||||
JJRCX1
|
||||
X5C1
|
||||
FQ777_951
|
||||
PROTO_AFHDS2A
|
||||
PWM_IBUS
|
||||
PPM_IBUS
|
||||
PWM_SBUS
|
||||
PPM_SBUS
|
||||
PROTO_WK2x01
|
||||
WK2801
|
||||
WK2401
|
||||
W6_5_1
|
||||
W6_6_1
|
||||
W6_HEL
|
||||
W6_HEL_I
|
||||
PROTO_Q303
|
||||
Q303
|
||||
CX35
|
||||
CX10D
|
||||
CX10WD
|
||||
PROTO_GW008
|
||||
NONE
|
||||
PROTO_DM002
|
||||
NONE
|
||||
PROTO_CABELL
|
||||
CABELL_V3
|
||||
CABELL_V3_TELEMETRY
|
||||
CABELL_SET_FAIL_SAFE
|
||||
CABELL_UNBIND
|
||||
PROTO_ESKY150
|
||||
PROTO_H8_3D
|
||||
H8_3D
|
||||
H20H
|
||||
H20MINI
|
||||
H30MINI
|
||||
PROTO_CORONA
|
||||
COR_V1
|
||||
COR_V2
|
||||
FD_V3
|
||||
PROTO_CFLIE
|
||||
NONE
|
||||
PROTO_HITEC
|
||||
OPT_FW
|
||||
OPT_HUB
|
||||
MINIMA
|
||||
PROTO_WFLY
|
||||
NONE
|
||||
*/
|
||||
|
||||
// RX_Num is used for TX & RX match. Using different RX_Num values for each receiver will prevent starting a model with the false config loaded...
|
||||
// RX_Num value is between 0 and 15.
|
||||
|
||||
@ -572,3 +451,168 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
|
||||
|
||||
// Option: the value is between -128 and +127.
|
||||
// The option value is only valid for some protocols, read this page for more information: https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/blob/master/Protocols_Details.md
|
||||
|
||||
/* Available protocols and associated sub protocols to pick and choose from (Listed in alphabetical order)
|
||||
PROTO_AFHDS2A
|
||||
PWM_IBUS
|
||||
PPM_IBUS
|
||||
PWM_SBUS
|
||||
PPM_SBUS
|
||||
PROTO_ASSAN
|
||||
NONE
|
||||
PROTO_BAYANG
|
||||
BAYANG
|
||||
H8S3D
|
||||
X16_AH
|
||||
IRDRONE
|
||||
PROTO_BUGS
|
||||
NONE
|
||||
PROTO_BUGSMINI
|
||||
NONE
|
||||
PROTO_CABELL
|
||||
CABELL_V3
|
||||
CABELL_V3_TELEMETRY
|
||||
CABELL_SET_FAIL_SAFE
|
||||
CABELL_UNBIND
|
||||
PROTO_CFLIE
|
||||
NONE
|
||||
PROTO_CG023
|
||||
CG023
|
||||
YD829
|
||||
PROTO_CORONA
|
||||
COR_V1
|
||||
COR_V2
|
||||
FD_V3
|
||||
PROTO_CX10
|
||||
CX10_GREEN
|
||||
CX10_BLUE
|
||||
DM007
|
||||
JC3015_1
|
||||
JC3015_2
|
||||
MK33041
|
||||
PROTO_DEVO
|
||||
NONE
|
||||
PROTO_DM002
|
||||
NONE
|
||||
PROTO_DSM
|
||||
DSM2_22
|
||||
DSM2_11
|
||||
DSMX_22
|
||||
DSMX_11
|
||||
PROTO_E01X
|
||||
E012
|
||||
E015
|
||||
PROTO_ESKY
|
||||
NONE
|
||||
PROTO_ESKY150
|
||||
NONE
|
||||
PROTO_FLYSKY
|
||||
Flysky
|
||||
V9X9
|
||||
V6X6
|
||||
V912
|
||||
CX20
|
||||
PROTO_FQ777
|
||||
NONE
|
||||
PROTO_FRSKYD
|
||||
NONE
|
||||
PROTO_FRSKYV
|
||||
NONE
|
||||
PROTO_FRSKYX
|
||||
CH_16
|
||||
CH_8
|
||||
EU_16
|
||||
EU_8
|
||||
PROTO_FY326
|
||||
FY326
|
||||
FY319
|
||||
PROTO_GD00X
|
||||
NONE
|
||||
PROTO_GW008
|
||||
NONE
|
||||
PROTO_H8_3D
|
||||
H8_3D
|
||||
H20H
|
||||
H20MINI
|
||||
H30MINI
|
||||
PROTO_HISKY
|
||||
Hisky
|
||||
HK310
|
||||
PROTO_HITEC
|
||||
OPT_FW
|
||||
OPT_HUB
|
||||
MINIMA
|
||||
PROTO_HONTAI
|
||||
HONTAI
|
||||
JJRCX1
|
||||
X5C1
|
||||
FQ777_951
|
||||
PROTO_HUBSAN
|
||||
H107
|
||||
H301
|
||||
H501
|
||||
PROTO_J6PRO
|
||||
NONE
|
||||
PROTO_KN
|
||||
WLTOYS
|
||||
FEILUN
|
||||
PROTO_MJXQ
|
||||
WLH08
|
||||
X600
|
||||
X800
|
||||
H26D
|
||||
E010
|
||||
H26WH
|
||||
PROTO_MT99XX
|
||||
MT99
|
||||
H7
|
||||
YZ
|
||||
LS
|
||||
FY805
|
||||
PROTO_NCC1701
|
||||
NONE
|
||||
PROTO_Q2X2
|
||||
Q222
|
||||
Q242
|
||||
Q282
|
||||
PROTO_Q303
|
||||
Q303
|
||||
CX35
|
||||
CX10D
|
||||
CX10WD
|
||||
PROTO_SFHSS
|
||||
NONE
|
||||
PROTO_SHENQI
|
||||
NONE
|
||||
PROTO_SLT
|
||||
SLT_V1
|
||||
SLT_V2
|
||||
Q100
|
||||
Q200
|
||||
MR100
|
||||
PROTO_SYMAX
|
||||
SYMAX
|
||||
SYMAX5C
|
||||
PROTO_TRAXXAS
|
||||
NONE
|
||||
PROTO_V2X2
|
||||
V2X2
|
||||
JXD506
|
||||
PROTO_V911S
|
||||
NONE
|
||||
PROTO_WFLY
|
||||
NONE
|
||||
PROTO_WK2x01
|
||||
WK2801
|
||||
WK2401
|
||||
W6_5_1
|
||||
W6_6_1
|
||||
W6_HEL
|
||||
W6_HEL_I
|
||||
PROTO_YD717
|
||||
YD717
|
||||
SKYWLKR
|
||||
SYMAX4
|
||||
XINXUN
|
||||
NIHUI
|
||||
*/
|
||||
|
@ -9,7 +9,7 @@
|
||||
// For example you can also define multiple module configurations, uncomment the one you want to compile for:
|
||||
#define Module_1
|
||||
//#define Module_2
|
||||
//#define Module_2
|
||||
//#define Module_3
|
||||
//#define Module_4
|
||||
|
||||
//Example on how to force the "Flash from TX" feature for all modules
|
||||
@ -53,7 +53,27 @@
|
||||
#define MULTI_TELEMETRY
|
||||
|
||||
#elif defined Module_4
|
||||
//Example of a module which will be PPM only
|
||||
//Example of a module which will be PPM only with a different protocol table
|
||||
#undef ENABLE_SERIAL
|
||||
|
||||
#undef NBR_BANKS
|
||||
#define NBR_BANKS 1 // redefine the number of banks
|
||||
#define MY_PPM_PROT // Use the bellow protocol list
|
||||
const PPM_Parameters My_PPM_prot[14*NBR_BANKS]={
|
||||
//****************************** BANK 1 ******************************
|
||||
// Switch Protocol Sub protocol RX_Num Power Auto Bind Option
|
||||
/* 1 */ {PROTO_KN , WLTOYS , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 2 */ {PROTO_FLYSKY, Flysky , 0 , P_HIGH , AUTOBIND , 0 },
|
||||
/* 3 */ {PROTO_AFHDS2A, PWM_IBUS , 1 , P_HIGH , NO_AUTOBIND , 0 }, // RX number 1
|
||||
/* 4 */ {PROTO_AFHDS2A, PWM_IBUS , 2 , P_HIGH , NO_AUTOBIND , 0 }, // RX number 2
|
||||
/* 5 */ {PROTO_AFHDS2A, PWM_IBUS , 3 , P_HIGH , NO_AUTOBIND , 0 }, // RX number 3
|
||||
/* 6 */ {PROTO_AFHDS2A, PWM_IBUS , 2 , P_HIGH , NO_AUTOBIND , 0 }, // RX number 4
|
||||
/* 7 */ {PROTO_AFHDS2A, PWM_IBUS , 3 , P_HIGH , NO_AUTOBIND , 0 }, // RX number 5
|
||||
/* 8 */ {PROTO_SFHSS, H107 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 9 */ {PROTO_FRSKYV, NONE , 0 , P_HIGH , NO_AUTOBIND , 40 }, // option=fine freq tuning
|
||||
/* 10 */ {PROTO_FRSKYD, NONE , 0 , P_HIGH , NO_AUTOBIND , 40 }, // option=fine freq tuning
|
||||
/* 11 */ {PROTO_FRSKYX, CH_16 , 0 , P_HIGH , NO_AUTOBIND , 40 }, // option=fine freq tuning
|
||||
/* 12 */ {PROTO_FRSKYX, EU_16 , 0 , P_HIGH , NO_AUTOBIND , 40 }, // option=fine freq tuning
|
||||
/* 13 */ {PROTO_DEVO , NONE , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 14 */ {PROTO_WK2x01, WK2801 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
};
|
||||
#endif
|
||||
|
@ -55,6 +55,66 @@ Notes:
|
||||
## Serial mode
|
||||
Serial mode is selected by placing the rotary switch to position 0 before power on of the radio.
|
||||
|
||||
You've upgraded the module but the radio does not display the name of the protocol you are loking for:
|
||||
* ersky9x:
|
||||
- Place the file [Multi.txt](https://raw.githubusercontent.com/pascallanger/DIY-Multiprotocol-TX-Module/master/Multiprotocol/Multi.txt) (which is part of the MPM source files) on the root of your SD card.
|
||||
- If the entry still does not appear or is broken, [upgrade](https://openrcforums.com/forum/viewtopic.php?f=7&t=4676) to version R222d2 or newer.
|
||||
* OpenTX:
|
||||
- Upgrade to the latest version of OpenTX.
|
||||
- If still not listed, use the Custom entry along with the protocol and sub_protocol values indicated by the italic numbers under each protocol. You'll find a summary of the protocols and numbers to use in table below.
|
||||
|
||||
# Available Protocol Table of Contents (Listed Alphabetically)
|
||||
|
||||
Protocol Name|Protocol Number|Sub_Proto 0|Sub_Proto 1|Sub_Proto 2|Sub_Proto 3|Sub_Proto 4|Sub_Proto 5|Sub_Proto 6|Sub_Proto 7|RF Module
|
||||
---|---|---|---|---|---|---|---|---|---|---
|
||||
[Assan](Protocols_Details.md#ASSAN---24)|24|ASSAN||||||||NRF24L01
|
||||
[Bayang](Protocols_Details.md#BAYANG---14)|14|Bayang|H8S3D|X16_AH|IRDRONE|||||NRF24L01
|
||||
[Bugs](Protocols_Details.md#BUGS---41)|41|BUGS||||||||A7105
|
||||
[BugsMini](Protocols_Details.md#BUGSMINI---42)|42|BUGSMINI||||||||NRF24L01
|
||||
[Cabell](Protocols_Details.md#Cabell---34)|34|Cabell_V3|C_TELEM|-|-|-|-|F_SAFE|UNBIND|NRF24L01
|
||||
CFlie|38|CFlie||||||||NRF24L01
|
||||
[CG023](Protocols_Details.md#CG023---13)|13|CG023|YD829|||||||NRF24L01
|
||||
[Corona](Protocols_Details.md#CORONA---37)|37|COR_V1|COR_V2|FD_V3||||||CC2500
|
||||
[CX10](Protocols_Details.md#CX10---12)|12|GREEN|BLUE|DM007|-|J3015_1|J3015_2|MK33041||NRF24L01
|
||||
[Devo](Protocols_Details.md#DEVO---7)|7|Devo||||||||CYRF6936
|
||||
[DM002](Protocols_Details.md#DM002---33)|33|DM002||||||||NRF24L01
|
||||
[DSM](Protocols_Details.md#DSM---6)|6|DSM2-22|DSM2-11|DSMX-22|DSMX-11|AUTO||||CYRF6936
|
||||
[E01X](Protocols_Details.md#E01X---45)|45|E012|E015|||||||NRF24L01
|
||||
[ESky](Protocols_Details.md#ESKY---16)|16|ESky||||||||NRF24L01
|
||||
[ESky150](Protocols_Details.md#ESKY150---35)|35|ESKY150||||||||NRF24L01
|
||||
[Flysky](Protocols_Details.md#FLYSKY---1)|1|Flysky|V9x9|V6x6|V912|CX20||||A7105
|
||||
[Flysky AFHDS2A](Protocols_Details.md#FLYSKY-AFHDS2A---28)|28|PWM_IBUS|PPM_IBUS|PWM_SBUS|PPM_SBUS|||||A7105
|
||||
[FQ777](Protocols_Details.md#FQ777---23)|23|FQ777||||||||NRF24L01
|
||||
[FrskyD](Protocols_Details.md#FRSKYD---3)|3|FrskyD||||||||CC2500
|
||||
[FrskyV](Protocols_Details.md#FRSKYV---25)|25|FrskyV||||||||CC2500
|
||||
[FrskyX](Protocols_Details.md#FRSKYX---15)|15|CH_16|CH_8|EU_16|EU_8|||||CC2500
|
||||
[FY326](Protocols_Details.md#FY326---20)|20|FY326|FY319|||||||NRF24L01
|
||||
[GD00X](Protocols_Details.md#GD00X---47)|47|GD00X||||||||NRF24L01
|
||||
[GW008](Protocols_Details.md#GW008---32)|32|GW008||||||||NRF24L01
|
||||
[H8_3D](Protocols_Details.md#H8_3D---36)|36|H8_3D|H20H|H20Mini|H30Mini|||||NRF24L01
|
||||
[Hisky](Protocols_Details.md#HISKY---4)|4|Hisky|HK310|||||||NRF24L01
|
||||
[Hitec](Protocols_Details.md#HITEC---39)|39|OPT_FW|OPT_HUB|MINIMA||||||CC2500
|
||||
[Hontai](Protocols_Details.md#HONTAI---26)|26|HONTAI|JJRCX1|X5C1|FQ777_951|||||NRF24L01
|
||||
[Hubsan](Protocols_Details.md#HUBSAN---2)|2|H107|H301|H501||||||A7105
|
||||
[J6Pro](Protocols_Details.md#J6Pro---22)|22|J6PRO||||||||CYRF6936
|
||||
[KN](Protocols_Details.md#KN---9)|9|WLTOYS|FEILUN|||||||NRF24L01
|
||||
[MJXq](Protocols_Details.md#MJXQ---18)|18|WLH08|X600|X800|H26D|E010|H26WH|||NRF24L01
|
||||
[MT99xx](Protocols_Details.md#MT99XX---17)|17|MT|H7|YZ|LS|FY805||||NRF24L01
|
||||
[NCC1701](Protocols_Details.md#NCC1701---44)|44|NCC1701||||||||NRF24L01
|
||||
[OpenLRS](Protocols_Details.md#OpenLRS---27)|27|||||||||None
|
||||
[Q2X2](Protocols_Details.md#Q2X2---29)|29|Q222|Q242|Q282||||||NRF24L01
|
||||
[Q303](Protocols_Details.md#Q303---31)|31|Q303|CX35|CX10D|CX10WD|||||NRF24L01
|
||||
[SFHSS](Protocols_Details.md#SFHSS---21)|21|SFHSS||||||||CC2500
|
||||
[Shenqi](Protocols_Details.md#Shenqi---19)|19|Shenqi||||||||NRF24L01
|
||||
[SLT](Protocols_Details.md#SLT---11)|11|SLT_V1|SLT_V2|Q100|Q200|MR100||||NRF24L01
|
||||
[SymaX](Protocols_Details.md#Symax---10)|10|SYMAX|SYMAX5C|||||||NRF24L01
|
||||
Traxxas|43|Traxxas||||||||NRF24L01
|
||||
[V2x2](Protocols_Details.md#V2X2---5)|5|V2x2|JXD506|||||||NRF24L01
|
||||
[V911S](Protocols_Details.md#V911S---46)|46|V911S||||||||NRF24L01
|
||||
[WFly](Protocols_Details.md#WFLY---40)|40|WFLY||||||||CYRF6936
|
||||
[WK2x01](Protocols_Details.md#WK2X01---30)|30|WK2801|WK2401|W6_5_1|W6_6_1|W6_HEL|W6_HEL_I|||CYRF6936
|
||||
[YD717](Protocols_Details.md#YD717---8)|8|YD717|SKYWLKR|SYMAX4|XINXUN|NIHUI||||NRF24L01
|
||||
|
||||
# A7105 RF Module
|
||||
|
||||
## FLYSKY - *1*
|
||||
@ -102,11 +162,13 @@ Option is used to change the servo refresh rate. A value of 0 gives 50Hz (min),
|
||||
|
||||
If telemetry is incomplete (missing RX RSSI for example), it means that you have to upgrade your RX firmware to version 1.6 or later. You can do it from an original Flysky TX or using a STLink like explained in [this tutorial](https://www.rcgroups.com/forums/showthread.php?2677694-How-to-upgrade-Flysky-Turnigy-iA6B-RX-to-firmware-1-6-with-a-ST-Link).
|
||||
|
||||
AFHDS2A_LQI_CH is a feature which is disabled by defaut in the _config.h file. When enabled, it makes LQI (Link Quality Indicator) available on one of the RX ouput channel (5-14).
|
||||
|
||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14
|
||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---
|
||||
A|E|T|R|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14
|
||||
|
||||
Note that the RX ouput will be AETR.
|
||||
Note that the RX ouput will be AETR whatever the input channel order is.
|
||||
|
||||
### Sub_protocol PWM_IBUS - *0*
|
||||
### Sub_protocol PPM_IBUS - *1*
|
||||
@ -135,12 +197,29 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
|
||||
---|---|---|---|---|---|---|---
|
||||
A|E|T|R|RTH|LIGHT|STAB|VIDEO
|
||||
|
||||
### Sub_protocol H501 - *1*
|
||||
Models: Hubsan H501S
|
||||
### Sub_protocol H501 - *2*
|
||||
Models: Hubsan H501S, H122D, H123D
|
||||
|
||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
|
||||
---|---|---|---|---|---|---|---|---|---|---|---
|
||||
A|E|T|R|RTH|LIGHT|PICTURE|VIDEO|HEADLESS1|HEADLESS2|GPS_HOLD|ALT_HOLD
|
||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13
|
||||
---|---|---|---|---|---|---|---|---|----|----|----|----
|
||||
A|E|T|R|RTH|LIGHT|PICTURE|VIDEO|HEADLESS|GPS_HOLD|ALT_HOLD|FLIP|FMODES
|
||||
|
||||
H122D: FLIP
|
||||
|
||||
H123D: FMODES -> -100%=Sport mode 1,0%=Sport mode 2,+100%=Acro
|
||||
|
||||
## BUGS - *41*
|
||||
Models: MJX Bugs 3, 6 and 8
|
||||
|
||||
Telemetry enabled for RX & TX RSSI, Battery voltage good/bad
|
||||
|
||||
**RX_Num is used to give a number to a given model. You must use a different RX_Num per MJX Bugs. A maximum of 16 Bugs are supported.**
|
||||
|
||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10
|
||||
---|---|---|---|---|---|---|---|---|---
|
||||
A|E|T|R|ARM|ANGLE|FLIP|PICTURE|VIDEO|LED
|
||||
|
||||
ANGLE: angle is +100%, acro is -100%
|
||||
|
||||
***
|
||||
# CC2500 RF Module
|
||||
@ -176,8 +255,9 @@ To bind V2 RXs you must follow the below procedure (original):
|
||||
### Sub_protocol FD_V3 - *2*
|
||||
FlyDream RXs like IS-4R and IS-4R0
|
||||
|
||||
## FRSKYV = FrSky 1 way - *25*
|
||||
## FRSKYV - *25*
|
||||
Models: FrSky receivers V8R4, V8R7 and V8FR.
|
||||
- FrSkyV = FrSky 1 way
|
||||
|
||||
Extended limits supported
|
||||
|
||||
@ -389,15 +469,16 @@ Telemetry enabled for TSSI and plugins
|
||||
|
||||
option=number of channels from 4 to 12. An invalid option value will end up with 6 channels.
|
||||
|
||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
|
||||
---|---|---|---|---|---|---|---|---|----|----|----
|
||||
A|E|T|R|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
|
||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|----|----|CH15
|
||||
---|---|---|---|---|---|---|---|---|----|----|----|----|----|----
|
||||
A|E|T|R|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|----|----|TH_KILL
|
||||
|
||||
Notes:
|
||||
- model/type/number of channels indicated on the RX can be different from what the RX is in fact wanting to see. So don't hesitate to test different combinations until you have something working. Using Auto is the best way to find these settings.
|
||||
- RX output will match the Spektrum standard TAER independently of the input configuration AETR, RETA...
|
||||
- RX output will match the Spektrum standard throw (1500µs +/- 400µs -> 1100..1900µs) for a 100% input. This is true for both Serial and PPM input. For PPM, make sure the end points PPM_MIN_100 and PPM_MAX_100 in _config.h are matching your TX ouput. The maximum ouput is 1000..2000µs based on an input of 125%.
|
||||
- If you want to override the above and get maximum throw (old way) uncomment in _config.h the line #define DSM_FULL_THROW . In this mode to achieve standard throw use a channel weight of 84%.
|
||||
- If you want to override the above and get maximum throw (old way) uncomment in _config.h the line #define DSM_MAX_THROW . In this mode to achieve standard throw use a channel weight of 84%.
|
||||
- TH_KILL is a feature which is enabled on channel 15 by default (can be disabled/changed) in the _config.h file. Some models (X-Vert, Blade 230S...) require a special position to instant stop the motor(s). If the channel 15 is above -50% the throttle is untouched but if it is between -50% and -100%, the throttle output will be forced between -100% and -150%. For example, a value of -80% applied on channel 15 will instantly kill the motors on the X-Vert.
|
||||
|
||||
### Sub_protocol DSM2_22 - *0*
|
||||
DSM2, Resolution 1024, refresh rate 22ms
|
||||
@ -478,6 +559,19 @@ CH12|CH13
|
||||
----|----
|
||||
TAKE_OFF|EMG_STOP
|
||||
|
||||
## BUGSMINI - *42*
|
||||
Models: MJX Bugs 3 Mini and 3H
|
||||
|
||||
Telemetry enabled for RX RSSI, Battery voltage good/warning/bad
|
||||
|
||||
**RX_Num is used to give a number to a given model. You must use a different RX_Num per MJX Bugs Mini. A maximum of 16 Bugs Mini are supported.**
|
||||
|
||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10
|
||||
---|---|---|---|---|---|---|---|---|---
|
||||
A|E|T|R|ARM|ANGLE|FLIP|PICTURE|VIDEO|LED
|
||||
|
||||
ANGLE: angle is +100%, acro is -100%
|
||||
|
||||
## Cabell - *34*
|
||||
Homegrown protocol with variable number of channels (4-16) and telemetry (RSSI, V1, V2).
|
||||
|
||||
@ -574,6 +668,23 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11
|
||||
---|---|---|---|---|---|---|---|---|----|----
|
||||
A|E|T|R|FLIP|LED|CAMERA1|CAMERA2|HEADLESS|RTH|RATE_LOW
|
||||
|
||||
## E01X - *45*
|
||||
Autobind protocol
|
||||
|
||||
### Sub_protocol E012 - *0*
|
||||
Models: Eachine E012
|
||||
|
||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
|
||||
---|---|---|---|---|---|---|---|---
|
||||
A|E|T|R||FLIP||HEADLESS|RTH
|
||||
|
||||
### Sub_protocol E015 - *1*
|
||||
Models: Eachine E015
|
||||
|
||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
|
||||
---|---|---|---|---|---|---|---|---
|
||||
A|E|T|R|ARM|FLIP|LED|HEADLESS|RTH
|
||||
|
||||
## ESKY - *16*
|
||||
|
||||
CH1|CH2|CH3|CH4|CH5|CH6
|
||||
@ -604,6 +715,13 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
|
||||
---|---|---|---|---|---|---|---
|
||||
A|E|T|R|FLIP|RTH|HEADLESS|EXPERT
|
||||
|
||||
## GD00X - *47*
|
||||
Model: GD005 C-17 Transport and GD006 DA62
|
||||
|
||||
CH1|CH2|CH3|CH4|CH5|CH6
|
||||
---|---|---|---|---|---
|
||||
A||T||TRIM|LED
|
||||
|
||||
## GW008 - *32*
|
||||
Model: Global Drone GW008 from Banggood
|
||||
|
||||
@ -743,6 +861,19 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
|
||||
---|---|---|---|---|---|---|---|---
|
||||
A|E|T|R|FLIP||||HEADLESS
|
||||
|
||||
## NCC1701 - *44*
|
||||
Model: Air Hogs Star Trek USS Enterprise NCC-1701-A
|
||||
|
||||
Autobind protocol
|
||||
|
||||
Telemetry: RSSI is a dummy value. A1 voltage is dummy but used for crash detection. In case of a crash event A1>0V, you can assign a sound to be played on the TX in that case (siren on the original transmitter).
|
||||
|
||||
Only 9 IDs available, cycle through them using RX_Num.
|
||||
|
||||
CH1|CH2|CH3|CH4|CH5
|
||||
---|---|---|---|---
|
||||
A|E|T|R|Warp
|
||||
|
||||
## Q2X2 - *29*
|
||||
### Sub_protocol Q222 - *0*
|
||||
Models: Q222 v1 and V686 v2
|
||||
@ -807,10 +938,75 @@ Throttle +100%=full forward,0%=stop,-100%=full backward.
|
||||
## SLT - *11*
|
||||
Autobind protocol
|
||||
|
||||
### Sub_protocol V1 - *0*
|
||||
|
||||
CH1|CH2|CH3|CH4|CH5|CH6
|
||||
---|---|---|---|---|---
|
||||
A|E|T|R|GEAR|PITCH
|
||||
|
||||
### Sub_protocol V2 - *1*
|
||||
|
||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
|
||||
---|---|---|---|---|---|---|---
|
||||
A|E|T|R|CH5|CH6|CH7|CH8
|
||||
|
||||
### Sub_protocol Q100 - *2*
|
||||
Models: Dromida Ominus UAV
|
||||
|
||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13
|
||||
---|---|---|---|---|---|---|---|---|---|---|---|---
|
||||
A|E|T|R|RATES|-|CH7|CH8|MODE|FLIP|-|-|CALIB
|
||||
|
||||
RATES takes any value between -50..+50%: -50%=min rates, 0%=mid rates (stock setting), +50%=max rates
|
||||
|
||||
CH7 and CH8 have no visible effect
|
||||
|
||||
MODE: -100% level, +100% acro
|
||||
|
||||
FLIP: sets model into flip mode for approx 5 seconds at each throw of switch (rear red LED goes out while active) -100%..+100% or +100%..-100%
|
||||
|
||||
CALIB: -100% normal mode, +100% gyro calibration
|
||||
|
||||
### Sub_protocol Q200 - *3*
|
||||
Model: Dromida Ominus Quadcopter FPV, the Nine Eagles - FENG FPV and may be others
|
||||
|
||||
Dromida Ominus FPV channels mapping:
|
||||
|
||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13
|
||||
---|---|---|---|---|---|---|---|---|---|---|---|---
|
||||
A|E|T|R|RATES|-|CH7|CH8|MODE|FLIP|VID_ON|VID_OFF|CALIB
|
||||
|
||||
FENG FPV: channels mapping:
|
||||
|
||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13
|
||||
---|---|---|---|---|---|---|---|---|---|---|---|---
|
||||
A|E|T|R|RATES|-|CH7|CH8|FLIP|MODE|VID_ON|VID_OFF|CALIB
|
||||
|
||||
RATES takes any value between -50..+50%: -50%=min rates, 0%=mid rates (stock setting), +50%=max rates
|
||||
|
||||
CH7 and CH8 have no visible effect
|
||||
|
||||
MODE: -100% level, +100% acro
|
||||
|
||||
FLIP: sets model into flip mode for approx 5 seconds at each throw of switch (rear red LED goes out while active) -100%..+100% or +100%..-100%
|
||||
|
||||
CALIB: -100% normal mode, +100% gyro calibration
|
||||
|
||||
### Sub_protocol MR100 - *4*
|
||||
Models: Vista UAV, FPV, FPV v2
|
||||
|
||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
|
||||
---|---|---|---|---|---|---|---|---|---|---|---
|
||||
A|E|T|R|RATES|-|CH7|CH8|MODE|FLIP|VIDEO|PICTURE
|
||||
|
||||
RATES takes any value between -50..+50%: -50%=min rates, 0%=mid rates (stock setting), +50%=max rates
|
||||
|
||||
CH7 and CH8 have no visible effect
|
||||
|
||||
FLIP: sets model into flip mode for approx 5 seconds at each throw of switch (rear red LED goes out while active) -100%..+100% or +100%..-100%
|
||||
|
||||
MODE: -100% level, +100% acro
|
||||
|
||||
## Symax - *10*
|
||||
Autobind protocol
|
||||
|
||||
@ -845,6 +1041,13 @@ CH10|CH11|CH12
|
||||
---|---|---
|
||||
Start/Stop|EMERGENCY|CAMERA_UP/DN
|
||||
|
||||
## V911S - *46*
|
||||
Model: WLtoys V911S
|
||||
|
||||
CH1|CH2|CH3|CH4|CH5
|
||||
---|---|---|---|---
|
||||
A|E|T|R|CALIB
|
||||
|
||||
## YD717 - *8*
|
||||
Autobind protocol
|
||||
|
||||
@ -858,3 +1061,8 @@ A|E|T|R|FLIP|LIGHT|PICTURE|VIDEO|HEADLESS
|
||||
### Sub_protocol XINXUN - *3*
|
||||
### Sub_protocol NIHUI - *4*
|
||||
Same channels assignement as above.
|
||||
|
||||
# OpenLRS module
|
||||
|
||||
## OpenLRS - *27*
|
||||
This is a reservation for OpenLRSng which is using Multi's serial protocol for their modules: https://openlrsng.org/. On the Multi side there is no protocol affected on 27 so it's just ignored.
|
||||
|
19
README.md
19
README.md
@ -3,7 +3,7 @@
|
||||
|
||||
The **Multiprotocol Tx Module** (or **MULTI-Module**) is a 2.4GHz transmitter module which enables almost any transmitter to control many different receivers and models, including many popular helicopters, planes, quadcopters, and miniquads.
|
||||
|
||||
The source code is partly based on the [Deviation TX project](http://www.deviationtx.com), thanks to all the developers for their great job on protocols.
|
||||
The main forum for protocol requests and questions is on [RCGroups.com](https://www.rcgroups.com/forums/showthread.php?2165676-DIY-Multiprotocol-TX-Module/page10000).
|
||||
|
||||
If you like this project and want to support further development please consider making a [donation](docs/Donations.md).
|
||||
|
||||
@ -17,6 +17,13 @@ If you like this project and want to support further development please consider
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## Development status
|
||||
|
||||
Current Multiprotocol code check status: [](https://travis-ci.org/pascallanger/DIY-Multiprotocol-TX-Module)
|
||||
|
||||
Current Multiprotocol boards check status: [](https://travis-ci.org/pascallanger/DIY-Multiprotocol-TX-Module-Boards)
|
||||
|
||||
|
||||
## Quicklinks
|
||||
* [Download latest releases of the firmware](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/releases) and [instructions to upload .hex files](docs/Advanced_Manually_Setting_ATmega328_Fuses.md)
|
||||
* [Forum on rcgroups](http://www.rcgroups.com/forums/showthread.php?t=2165676)
|
||||
@ -120,12 +127,14 @@ Visit the [Troubleshooting](docs/Troubleshooting.md) page. Please bear in mind
|
||||
# A final word
|
||||
A very big thanks to all the people who have shared their time so graciously to create this great project. If you come across them on RC Groups, please be kind and show appreciation. In no particular order:
|
||||
* Pascal Langer (rcgroups: hpnuts)
|
||||
* Ben Lye (rcgroups: benzo99)
|
||||
* Midelic (rcgroups: midelic)
|
||||
* Mike Blandford (rcgroups: Mike Blandford)
|
||||
* PhracturedBlue – from Deviation-tx
|
||||
* goebish – from Deviation-tx
|
||||
* victzh – from Deviation-tx
|
||||
* hexfet – from Deviation-tx
|
||||
* schwabe - from OpenTX
|
||||
* PhracturedBlue – from [Deviation TX project](http://www.deviationtx.com)
|
||||
* goebish – from [Deviation TX project](http://www.deviationtx.com)
|
||||
* victzh – from [Deviation TX project](http://www.deviationtx.com)
|
||||
* hexfet – from [Deviation TX project](http://www.deviationtx.com)
|
||||
|
||||
Your help would be greatly appreciated. If protocol reverse-engineering and dev is not your thing then any help with testing and contributing to the documentation would be amazing. Given the number of different Tx/module hardware/RF module/protocol/model combinations the process of testing and documenting is a major bottleneck for the developers. Anything you can do to help will free them up to do even greater things.
|
||||
|
||||
|
3
buildroot/bin/opt_add
Executable file
3
buildroot/bin/opt_add
Executable file
@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
eval "echo \"#define ${1} ${2}\" >>Multiprotocol/_Config.h"
|
7
buildroot/bin/opt_disable
Executable file
7
buildroot/bin/opt_disable
Executable file
@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
SED=$(which gsed || which sed)
|
||||
|
||||
for opt in "$@" ; do
|
||||
eval "${SED} -i 's/^\([[:blank:]]*\)\(#define[[:blank:]]*\b${opt}\b\)/\1\/\/\2/g' Multiprotocol/_Config.h"
|
||||
done
|
7
buildroot/bin/opt_enable
Executable file
7
buildroot/bin/opt_enable
Executable file
@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
SED=$(which gsed || which sed)
|
||||
|
||||
for opt in "$@" ; do
|
||||
eval "${SED} -i 's/\/\{2,\}[[:blank:]]*\(#define[[:blank:]]*\b${opt}\b\)/\1/g' Multiprotocol/_Config.h"
|
||||
done
|
5
buildroot/bin/opt_set
Executable file
5
buildroot/bin/opt_set
Executable file
@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
SED=$(which gsed || which sed)
|
||||
|
||||
eval "${SED} -i 's/\(#define \b${1}\b\).*$/\1 ${2}/g' Multiprotocol/_Config.h"
|
@ -6,3 +6,6 @@ It is possible to access the telemetry stream coming from the receiver through t
|
||||
|
||||
# Manually setting fuses on ATmega328
|
||||
This document describes a relatively simple process to set the fuses on ATmega328. See the [Advanced Manually Setting ATmega328 Fuses](Advanced_Manually_Setting_ATmega328_Fuses.md) page for more details.
|
||||
|
||||
# EEPROM Backup and Restore
|
||||
This document describes how to back up and restore the EEPROM for both Atmega328p and STM32 MULTI-modules. This can be useful if cloning a module, or to preserve settings. See the [MULTI-Module EEPROM](EEPROM.md) page for more details.
|
||||
|
@ -113,7 +113,7 @@ The bootloader only needs to be burned once, unless you decide to switch from on
|
||||
|
||||
There are two bootloader options:
|
||||
* **'No bootloader'** maximises flash space for protocols
|
||||
* **'Flash from TX'** (highly recommended) installs a small (512 byte) bootloader which allows flashing the module firmware using from a radio running ersky9x
|
||||
* **'Flash from TX'** installs a small (512 byte) bootloader which allows flashing the module firmware using from a radio running ersky9x
|
||||
|
||||
**Note:** 'Burning the bootloader' is necessary even if the 'No bootloader' option is selected, as it sets the fuses on the AVR module. This only needs to be once (unless you decide to change your bootloader choice later)
|
||||
|
||||
@ -122,17 +122,15 @@ There are two bootloader options:
|
||||
|
||||
### Upload the firmware
|
||||
You are now ready to upload the firmware to the multiprotocol module. There are two methods for uploading the firmware:
|
||||
* **Flash from TX** uses the maintenance mode in radios running ersky9x to upload the firmware
|
||||
* **Flash from TX** - uses the bootloader mode of radios running ersky9x or OpenTX to upload the firmware. The radio needs to run the latest bootloader with the Flash Multi app.
|
||||
* **Upload using Arduino IDE** uses the Arduino IDE and the USBasp programmer to upload the firmware
|
||||
|
||||
**Note:** 'Flash from TX' is only available with radios running ersky9x r221e2 or newer.
|
||||
|
||||
#### Flash from TX
|
||||
1. The MPM module must have the 'Flash from TX' bootloader installed
|
||||
1. In the Arduino IDE click **Sketch -> Export compiled Binary**, or press **Ctrl+Alt+S**
|
||||
1. Locate the file named **multifw.hex** in the **Multiprotocol** folder
|
||||
1. Locate the file named **multi-avr-x.x.x.x.hex** in the **Multiprotocol source folder** (x.x.x.x is the multi version)
|
||||
1. Follow the instructions [here](/docs/Flash_from_Tx.md) to upload the firmware using your radio
|
||||
|
||||
You can disconnect the programmer now as it is not needed any more.
|
||||
1. Once the previous step is completed your module is ready to be used
|
||||
|
||||
#### Upload using Arduino IDE
|
||||
**Note:** If you have burned the 'Upload from TX' bootloader and you then upload firmware to your module using **Upload Using Programmer**, you will erase the bootloader. That's just the way the Arduino IDE works - avrdude will erase the entire flash memory prior to writing the new code, *including the bootloader*, and the upload will not put it back. If this happens you can [burn it again](#burn-bootloader-and-set-fuses).
|
||||
|
@ -60,6 +60,7 @@ The 4-pin header needs to be soldered onto the board as indicated by the red rec
|
||||
|
||||
### Configure the Arduino IDE
|
||||
1. Under **Tools -> Board** select **Multi 4-in-1 (STM32FC103)**
|
||||
1. Under **Tools -> Upload method** select **Auto Detect (USB or Serial)** <- more details on this subject later on
|
||||
1. Under **Tools -> Programmer** select **stm32flash (FTDI)**
|
||||
|
||||
## Configure the firmware
|
||||
@ -67,7 +68,7 @@ The STM32 module has more than enough flash space for all the available protocol
|
||||
|
||||
You can still disable protocols if you wish, and you may also enable or disable other optional Multiprotocol features.
|
||||
## Verify the firmware
|
||||
To check that the program will compile correctly and fit in the Atmega click **Sketch -> Verify/Compile**, or press **Ctrl+R**.
|
||||
To check that the program will compile correctly and fit in the STM32 click **Sketch -> Verify/Compile**, or press **Ctrl+R**.
|
||||
|
||||
If there are errors, carefully read it, go to the line number indicated and correct your typo.
|
||||
|
||||
@ -86,14 +87,14 @@ STM modules, until now, do not come with a preloaded bootloader which makes the
|
||||
The latest Jumper 4-in-1 modules come with a USB port but it's in fact a built in FTDI appearing on the computer as a CP2102 serial device. You should use the method **Upload via Serial inc. Bootloader** instead of Upload via USB. 'Flash from TX' is supported once the bootloader is installed.
|
||||
|
||||
### Select an Upload Method
|
||||
There are three methods to upload firmware to an STM32 module:
|
||||
* **Flash from TX** - highly recommended, uses maintenance mode in radios running ersky9x or OpenTX to upload the firmware
|
||||
* **Upload via USB** - uses the USB port on the module
|
||||
* **Upload via Serial inc. Bootloader (FTDI)** - uses the serial interface on the module via a USB-to-TTL adapter
|
||||
There are a total of five firmware upload methods to an STM32 module:
|
||||
* **Flash from TX** - uses the bootloader mode of radios running ersky9x or OpenTX to upload the firmware. The radio needs to run the latest bootloader with the Multi Flash app.
|
||||
* **Auto Detect (USB or Serial)** - Detects automatically if the upload method is USB or Serial. You need to configure the correct COM port in the IDE which is created when plugging the module.
|
||||
* **Upload via USB** - uses the USB upload method through the USB plug of the module. It requires the presence of a bootloader in the module.
|
||||
* **Upload via Serial inc. Bootloader (FTDI)** - uses the serial interface of the module via a USB-to-TTL adapter to install the bootloader and firmware.
|
||||
* **Upload via Serial (FTDI)** - uses the serial interface of the module via a USB-to-TTL adapter to install the firmware.
|
||||
|
||||
**Note:** 'Flash from TX' is available with radios supporting ersky9x or OpenTX and running the latest bootloader with the Multi Flash app.
|
||||
|
||||
**Flash from TX** is highly recommended if your transmitter supports it, **Upload via USB** is recommended for all others. **Upload via Serial inc. Bootloader** can be used if your module does not have a USB port and your transmitter does not run ersky9x or OpenTX.
|
||||
You will most likely use only once on a brand new module the **Upload via Serial inc. Bootloader (FTDI)** method to load the bootloader+firmware. Any successive updates will be done using either **Auto Detect (USB or Serial)** or **Flash from TX** depending on your preference.
|
||||
|
||||
1. Under **Tools -> Upload Method** select an upload method
|
||||
|
||||
@ -132,6 +133,7 @@ In order to flash the bootloader the **BOOT0** jumper must be installed connecti
|
||||
1. Verify that you have selected the upload method **Upload via Serial inc. Bootloader (FTDI)** under **Tools -> Upload Method**
|
||||
1. Verify that you have selected **stm32flash (FTDI)** as the programmer under **Tools -> Programmer**
|
||||
1. Verify that the USB-to-TTL adapter is correctly connected to your module and you have selected the correct port under **Tools -> Port**
|
||||
1. In the Arduino IDE click **Sketch -> Upload**, or press **Ctrl+U**
|
||||
|
||||
Output will look similar to this:
|
||||
```
|
||||
@ -167,14 +169,18 @@ Assuming the process is successful:
|
||||
1. Power off the transmitter
|
||||
1. Remove the **BOOT0** jumper
|
||||
1. Disconnect the USB-to-TTL adapter
|
||||
1. Your module is ready to use, enjoy!!!
|
||||
|
||||
## Flash from TX
|
||||
1. The MPM module must have a recent bootloader installed
|
||||
1. Click **Tools -> Upload method -> Flash from TX**
|
||||
1. Click **Sketch -> Export compiled Binary**, or press **Ctrl+Alt+S**
|
||||
1. Locate the file named **multifw.bin** in the **Multiprotocol** folder
|
||||
1. Locate the file named **multi-stm-x.x.x.x.bin** in the **Multiprotocol source folder** folder (x.x.x.x is the multi version)
|
||||
1. Follow the instructions [here](/docs/Flash_from_Tx.md) to upload the firmware using your radio
|
||||
1. Once done your module is ready to be used
|
||||
|
||||
## Upload via USB
|
||||
In order for the module to be correctly identified in Windows it is necessary to install drivers. This only needs to be done once.
|
||||
In order for the module to be correctly identified it is necessary and only once to do some operations based on your operating system.
|
||||
|
||||
### Install the Maple USB drivers
|
||||
##### Windows 7 or newer:
|
||||
@ -228,14 +234,12 @@ After adding yourself to the groups as above and installing and running the udev
|
||||
**Note:** Some modules require external power in order for the USB port to work. If your module does not power on with USB power alone, install it in the transmitter and switch the transmitter on. It is generally safe for the module to recieve power from both USB and the transmitter.
|
||||
|
||||
1. Connect the USB cable to the Multiprotocol module
|
||||
1. Verify that a Maple device appears (**Maple DFU** for a module with only a bootloader, **Maple Serial** for a module with a bootloader and firmware)
|
||||
1. On Windows look for the USB device in the Windows Device Manager
|
||||
1. On Mac OSX look in the System Information which is accessed by holding option and selecting the first item under the Apple Menu. Select the USB list on the left and look for the USB device.
|
||||
1. On Linux execute the command ```lsusb``` and examine the output.
|
||||
1. select the correct COM port, which should be labelled **COMx (Multi 4-in-1 (STM32F103CB))**. If the device is in "DFU" mode, the module COM port will not appear, select any available COM port to continue the upload procedure.
|
||||
<p align="center"><img src="images/maple-serial-port-select.jpg"/></p>
|
||||
1. Click **Tools -> Upload method -> Auto Detect (USB or Serial)**
|
||||
1. Select the correct COM port **Tools -> Port**, which should be labelled **COMx (Multi 4-in-1 (STM32F103CB))**.<p align="center"><img src="images/maple-serial-port-select.jpg"/></p>
|
||||
1. In the Arduino IDE click **Sketch -> Upload**, or press **Ctrl+U**
|
||||
|
||||
**Note:** If the module appears as a **Maple DFU** for a module with only a bootloader, **Maple Serial** for a module with a bootloader and firmware then follow the same process by selecting any available COM port (you must select one, if you don't have one appearing plug any device that will create a com port (an Arduino board for example)).
|
||||
|
||||
You should see output similar to this:
|
||||
```
|
||||
Sketch uses 68564 bytes (52%) of program storage space. Maximum is 131072 bytes.
|
||||
@ -265,7 +269,7 @@ Resetting USB to switch back to runtime mode
|
||||
error resetting after download: usb_reset: could not reset device, win error: The system cannot find the file specified.
|
||||
```
|
||||
|
||||
**Note:** The line `Reset via USB Serial Failed! Did you select the right serial port?` is expected because the uploader initially looks for a Maple Serial device, which isn't yet available, before failing back to Maple DFU. That error only appears the first time and won't appear when re-flashing firmware. The final line warning, stating that the device could not be reset, is also expected.
|
||||
**Note:** The line `Reset via USB Serial Failed! Did you select the right serial port?` or a warning line stating that the device could not be reset is **not a problem**.
|
||||
|
||||
## Flashing pre-compiled binaries
|
||||
Pre-compiled binaries are available [here](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/releases).
|
||||
|
255
docs/EEPROM.md
Normal file
255
docs/EEPROM.md
Normal file
@ -0,0 +1,255 @@
|
||||
# Multi-Module EEPROM
|
||||
|
||||
The EEPROM is used to store the Multiprotocol Modules's global ID as well as details of bound receivers for certain protocols (AFHDS2A, Bugs, Devo, Walkera).
|
||||
|
||||
On an Atmega328p module the EEPROM is a dedicated and persistent data store, separate from the 32KB of flash memory. On the STM32 module there is no dedicated EEPROM, so EEPROM functionality is emulated in the last 2KB of flash memory.
|
||||
|
||||
This makes it relatively easy for the STM32 EEPROM data to be accidentally erased.
|
||||
|
||||
If the EEPROM is erased a new global ID will be generated (random for Atmega modules; the MCU UUID for STM32 modules) and models will need to be re-bound.
|
||||
|
||||
Backups of the EEPROM data can be made so that configuration such as module ID and bound receivers can be moved between modules.
|
||||
|
||||
**Note:** Backups can only restored to a module with same MCU type - i.e. an Atmega backup cannot be restored to an STM32 module.
|
||||
|
||||
The remainder of this doc is separated into sections for the STM32 and Atmega328p modules.
|
||||
|
||||
## STM32 Module
|
||||
The EEPROM data is stored in the last 2KB of flash memory. It is read using stm32flash with the module in BOOT0 mode.
|
||||
#### Tools Needed
|
||||
* stm32flash (Download: [Windows](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/source/stm32/tools/win/stm32flash.exe), [Linux 32-bit](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/source/stm32/tools/linux/stm32flash/stm32flash), [Linux 64-bit](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/source/stm32/tools/linux64/stm32flash/stm32flash), [macOS](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/source/stm32/tools/macosx/stm32flash/stm32flash))
|
||||
* Working USB-to-Serial (FTDI) adapter
|
||||
|
||||
#### Preparation
|
||||
Ensure that the `BOOT0` jumper is installed and the module is connected via a USB-to-Serial adapter.
|
||||
|
||||
### Backing up the STM32 EEPROM
|
||||
The syntax of the backup command is:
|
||||
`stm32flash -r [file name] -S 0x801F800:2048 [serial port]`
|
||||
|
||||
The `-S 0x801F800:2048` option tells stm32flash to read 2048 bytes starting at 0x801F800.
|
||||
|
||||
Windows example:
|
||||
|
||||
`stm32flash.exe -r C:\Temp\eeprom.bin -S 0x801F800:2048 COM4`
|
||||
|
||||
Linux and macOS example:
|
||||
|
||||
`stm32flash -r /tmp/eeprom.bin -S 0x801F800:2048 /dev/ttyUSB0`
|
||||
|
||||
Output will look similar to this:
|
||||
```
|
||||
stm32flash 0.4
|
||||
|
||||
http://stm32flash.googlecode.com/
|
||||
|
||||
Interface serial_w32: 57600 8E1
|
||||
Version : 0x22
|
||||
Option 1 : 0x00
|
||||
Option 2 : 0x00
|
||||
Device ID : 0x0410 (Medium-density)
|
||||
- RAM : 20KiB (512b reserved by bootloader)
|
||||
- Flash : 128KiB (sector size: 4x1024)
|
||||
- Option RAM : 16b
|
||||
- System RAM : 2KiB
|
||||
Memory read
|
||||
Read address 0x08020000 (100.00%) Done.
|
||||
```
|
||||
### Restoring the STM32 EEPROM
|
||||
The syntax of the restore command is:
|
||||
`stm32flash -w [file name] -e 0 -v -S 0x801F800:2048 [serial port]`
|
||||
|
||||
Again, the `-S 0x801F800:2048` option tells stm32flash to write 2048 bytes starting at 0x801F800. Additionally `-e 0` tells the tool not to erase any other blocks, which will preserve the rest of the data in the module's memory.
|
||||
|
||||
Windows example:
|
||||
|
||||
`stm32flash.exe -w C:\Temp\eeprom.bin -e 0 -v -S 0x801F800:2048 COM4`
|
||||
|
||||
Linux and macOS example:
|
||||
|
||||
`stm32flash -w /tmp/eeprom.bin -e 0 -v -S 0x801F800:2048 /dev/ttyUSB0`
|
||||
|
||||
Output will look similar to this:
|
||||
```
|
||||
stm32flash 0.4
|
||||
|
||||
http://stm32flash.googlecode.com/
|
||||
|
||||
Interface serial_w32: 57600 8E1
|
||||
Version : 0x22
|
||||
Option 1 : 0x00
|
||||
Option 2 : 0x00
|
||||
Device ID : 0x0410 (Medium-density)
|
||||
- RAM : 20KiB (512b reserved by bootloader)
|
||||
- Flash : 128KiB (sector size: 4x1024)
|
||||
- Option RAM : 16b
|
||||
- System RAM : 2KiB
|
||||
Write to memory
|
||||
Wrote and verified address 0x08020000 (100.00%) Done.
|
||||
```
|
||||
|
||||
### Erasing the STM32 EEPROM
|
||||
The syntax of the erase command is:
|
||||
`stm32flash -o -S 0x801F800:2048 [serial port]`
|
||||
|
||||
Again, the `-S 0x801F800:2048` option tells stm32flash to erase 2048 bytes starting at 0x801F800.
|
||||
|
||||
Windows example:
|
||||
|
||||
`stm32flash.exe -o -S 0x801F800:2048 COM4`
|
||||
|
||||
Linux and macOS example:
|
||||
|
||||
`stm32flash -o -S 0x801F800:2048 /dev/ttyUSB0`
|
||||
|
||||
Output will look similar to this:
|
||||
```
|
||||
stm32flash 0.4
|
||||
|
||||
http://stm32flash.googlecode.com/
|
||||
|
||||
Interface serial_w32: 57600 8E1
|
||||
Version : 0x22
|
||||
Option 1 : 0x00
|
||||
Option 2 : 0x00
|
||||
Device ID : 0x0410 (Medium-density)
|
||||
- RAM : 20KiB (512b reserved by bootloader)
|
||||
- Flash : 128KiB (sector size: 4x1024)
|
||||
- Option RAM : 16b
|
||||
- System RAM : 2KiB
|
||||
Erasing flash
|
||||
```
|
||||
|
||||
## Atmega328p Module
|
||||
The EEPROM on the Atmega328p module is a dedicated 1KB data space, separate from the main flash memory.
|
||||
|
||||
By default the EEPROM would be erased every time the module is flashed, but we configure the `EESAVE` bit so that the EEPROM is not erased during flashes. This is one reason why it is crucial to set the 'fuses' on a new module using the **Burn Bootloader** command in the Arduino IDE, as described in the [documentation](Compiling.md#burn-bootloader-and-set-fuses).
|
||||
|
||||
The module's EEPROM can be read, written, and erased using the avrdude tool.
|
||||
|
||||
#### Tools needed
|
||||
* A USBasp device, or another Arduino programmed to function as a USBasp
|
||||
* avrdude - installed as part of the Arduino IDE installation, or [downloaded separately](http://savannah.nongnu.org/projects/avrdude)
|
||||
|
||||
With a default Arduino IDE installation, the path to avrdude will be:
|
||||
* Windows - `C:\Program Files (x86)\Arduino\hardware\tools\avr\bin\avrdude.exe`
|
||||
* Linux - `[Arduino IDE path]/hardware/tools/avr/bin/avrdude`
|
||||
* macOS - TBD
|
||||
|
||||
You will also need to know the path to the avrdude configuration file. Default locations are:
|
||||
* Windows - `C:\Program Files (x86)\Arduino\hardware\tools\avr\etc\avrdude.conf`
|
||||
* Linux - `[Arduino IDE path]/hardware/tools/avr/etc/avrdude.conf`
|
||||
* macOS - TBD
|
||||
|
||||
#### Preparation
|
||||
Connect the module using the USBasp.
|
||||
|
||||
### Backing up the Atmega328p EEPROM
|
||||
The syntax of the backup command is:
|
||||
`avrdude -C [config file] -c usbasp -p atmega328p -U eeprom:r:[filename]:i`
|
||||
|
||||
Windows example:
|
||||
|
||||
`"C:\Program Files (x86)\Arduino\hardware\tools\avr\bin\avrdude.exe" -C "C:\Program Files (x86)\Arduino\hardware\tools\avr\etc\avrdude.conf" -c usbasp -p atmega328p -U eeprom:r:C:\Temp\eeprom.hex:i`
|
||||
|
||||
Linux and macOS example:
|
||||
|
||||
`~/Downloads/arduino-1.8.5/hardware/tools/avr/bin/avrdude -C ~/Downloads/arduino-1.8.5/hardware/tools/avr/etc/avrdude.conf -c usbasp -p atmega328p -U eeprom:r:/tmp/eeprom.hex:i`
|
||||
|
||||
Output will look similar to this:
|
||||
```
|
||||
avrdude.exe: AVR device initialized and ready to accept instructions
|
||||
|
||||
Reading | ################################################## | 100% 0.10s
|
||||
|
||||
avrdude.exe: Device signature = 0x1e950f (probably m328p)
|
||||
avrdude.exe: reading eeprom memory:
|
||||
|
||||
Reading | ################################################## | 100% 7.51s
|
||||
|
||||
avrdude.exe: writing output file "C:\Temp\eeprom.hex"
|
||||
|
||||
avrdude.exe: safemode: Fuses OK (E:FD, H:D6, L:FF)
|
||||
|
||||
avrdude.exe done. Thank you.
|
||||
```
|
||||
### Restoring the Atmega328p EEPROM
|
||||
The syntax of the restore command is:
|
||||
`avrdude -C [config file] -c usbasp -p atmega328p -U eeprom:w:[filename]:i`
|
||||
|
||||
Windows example:
|
||||
|
||||
`"C:\Program Files (x86)\Arduino\hardware\tools\avr\bin\avrdude.exe" -C "C:\Program Files (x86)\Arduino\hardware\tools\avr\etc\avrdude.conf" -c usbasp -p atmega328p -U eeprom:w:C:\Temp\eeprom.hex:i`
|
||||
|
||||
Linux and macOS example:
|
||||
|
||||
`~/Downloads/arduino-1.8.5/hardware/tools/avr/bin/avrdude -C ~/Downloads/arduino-1.8.5/hardware/tools/avr/etc/avrdude.conf -c usbasp -p atmega328p -U eeprom:w:/tmp/eeprom.hex:i`
|
||||
|
||||
Output will look similar to this:
|
||||
```
|
||||
avrdude.exe: AVR device initialized and ready to accept instructions
|
||||
|
||||
Reading | ################################################## | 100% 0.04s
|
||||
|
||||
avrdude.exe: Device signature = 0x1e950f (probably m328p)
|
||||
avrdude.exe: reading input file "C:\Temp\eeprom.hex"
|
||||
avrdude.exe: writing eeprom (1024 bytes):
|
||||
|
||||
Writing | ################################################## | 100% 17.17s
|
||||
|
||||
avrdude.exe: 1024 bytes of eeprom written
|
||||
avrdude.exe: verifying eeprom memory against C:\Temp\eeprom.hex:
|
||||
avrdude.exe: load data eeprom data from input file C:\Temp\eeprom.hex:
|
||||
avrdude.exe: input file C:\Temp\eeprom.hex contains 1024 bytes
|
||||
avrdude.exe: reading on-chip eeprom data:
|
||||
|
||||
Reading | ################################################## | 100% 6.51s
|
||||
|
||||
avrdude.exe: verifying ...
|
||||
avrdude.exe: 1024 bytes of eeprom verified
|
||||
|
||||
avrdude.exe: safemode: Fuses OK (E:FD, H:D6, L:FF)
|
||||
|
||||
avrdude.exe done. Thank you.
|
||||
```
|
||||
|
||||
### Erasing the Atmega328p EEPROM
|
||||
It's not possible to simply erase the EEPROM so instead we write a file which overwrites all of the content with `0xFF`. Download the 'erase.hex' file [here](https://raw.githubusercontent.com/pascallanger/DIY-Multiprotocol-TX-Module/master/docs/erase.hex).
|
||||
|
||||
The syntax of the 'erase' command is the same as the restore command.
|
||||
|
||||
Windows example:
|
||||
|
||||
`"C:\Program Files (x86)\Arduino\hardware\tools\avr\bin\avrdude.exe" -C "C:\Program Files (x86)\Arduino\hardware\tools\avr\etc\avrdude.conf" -c usbasp -p atmega328p -U eeprom:w:C:\Temp\erase.hex:i`
|
||||
|
||||
Linux and macOS example:
|
||||
|
||||
`~/Downloads/arduino-1.8.5/hardware/tools/avr/bin/avrdude -C ~/Downloads/arduino-1.8.5/hardware/tools/avr/etc/avrdude.conf -c usbasp -p atmega328p -U eeprom:r:/tmp/erase.hex:i`
|
||||
|
||||
Output will look similar to this:
|
||||
```
|
||||
avrdude.exe: AVR device initialized and ready to accept instructions
|
||||
|
||||
Reading | ################################################## | 100% 0.04s
|
||||
|
||||
avrdude.exe: Device signature = 0x1e950f (probably m328p)
|
||||
avrdude.exe: reading input file "C:\Temp\erase.hex"
|
||||
avrdude.exe: writing eeprom (1024 bytes):
|
||||
|
||||
Writing | ################################################## | 100% 17.17s
|
||||
|
||||
avrdude.exe: 1024 bytes of eeprom written
|
||||
avrdude.exe: verifying eeprom memory against C:\Temp\erase.hex:
|
||||
avrdude.exe: load data eeprom data from input file C:\Temp\erase.hex:
|
||||
avrdude.exe: input file C:\Temp\erase.hex contains 1024 bytes
|
||||
avrdude.exe: reading on-chip eeprom data:
|
||||
|
||||
Reading | ################################################## | 100% 6.51s
|
||||
|
||||
avrdude.exe: verifying ...
|
||||
avrdude.exe: 1024 bytes of eeprom verified
|
||||
|
||||
avrdude.exe: safemode: Fuses OK (E:FD, H:D6, L:FF)
|
||||
|
||||
avrdude.exe done. Thank you.
|
||||
```
|
@ -1,33 +1,61 @@
|
||||
# Flashing from the Transmitter
|
||||
|
||||
For radios running ersky9x r221e2 or newer, there is an option to flash a precompiled firmware file to the multiprotocol module using the transmitter's Maintenance Mode.
|
||||
For radios running ersky9x and OpenTX, there is an option to flash a precompiled firmware file to the multiprotocol module using the transmitter's Bootloader mode.
|
||||
|
||||
## Tools required
|
||||
* A compatible transmitter running ersky9x r221e2, or newer
|
||||
* A compatible transmitter running an ersky9x bootloader v2.9 or newer. This is true for both OpenTX and ersky9x.
|
||||
* A precompiled multiprotocol firmware file (.hex for Atmega328p or .bin for STM32)
|
||||
* A **Flash from TX** bootloader installed on the multiprotocol module
|
||||
* A **Flash from TX** bootloader installed on an Atmega328p or STM32 multiprotocol module
|
||||
* A means to get the firmware file onto the transmitter's SD card
|
||||
|
||||
Consult the [ersky9x site](http://www.er9x.com/) to see if your transmitter is compatible.
|
||||
## Radio bootloader and apps
|
||||
|
||||
The transmitter firmware can be downloaded from the [ersky9x test firmware page](http://openrcforums.com/forum/viewtopic.php?f=7&t=4676).
|
||||
### How to check the bootloader version
|
||||
1. Push both horizontals trims inwards (close to each others) while powering on the radio
|
||||
1. The screen title should indicate `Boot Loader V2.9Ready` or newer<p align="center"><img src="images/Bootloader.jpg" height=200/></p>
|
||||
1. Launch the `FlashMulti_xxx.app` app from the `Run App` menu
|
||||
1. The App version at the bottom right of the screen should be `28.Aug.18` or newer<p align="center"><img src="images/FlashMulti.jpg" height=200/></p>
|
||||
1. If everything is correct you are ready to upgrade the Multimodule firmware
|
||||
|
||||
## Procedure
|
||||
### Upgrade the bootloader and install app(s)
|
||||
1. Download the latest zip file of the [ersky9x firmware](https://openrcforums.com/forum/viewtopic.php?f=7&t=4676)
|
||||
1. Extract the .bin file corresponding to your radio in your SD card `\FIRMWARE` directory
|
||||
1. Download the latest [Flash Multiprotocol Module app](http://www.er9x.com/Ersky9xapps.html) for your radio
|
||||
1. Copy the .app file in a folder called `APPS` at the root of the SD card (if the directory does not exist create it)
|
||||
1. For ersky9x
|
||||
1. Power on the radio in `MAINTENANCE` mode while pushing both horizontals trims outwards (away from each others)
|
||||
1. Select `Update Bootloader`
|
||||
1. Select the ersky9x firmware matching your radio
|
||||
1. Long press it and select `Flash bootloader`
|
||||
1. For OpenTX
|
||||
1. Boot the radio normaly
|
||||
1. Go in the `RADIO SETUP` menu page 2 called `SD-HC CARD`
|
||||
1. Open the `FIRMWARE` directory
|
||||
1. Select the ersky9x firmware matching your radio
|
||||
1. Long press it and select `Flash bootloader`
|
||||
1. Check by rebooting the radio in bootloader mode that everything is [ok](###-How-to-check-the-bootloader-version)
|
||||
|
||||
**Note**: For OpenTX radio, this bootloader is an upgraded version of the existing bootloader shipped with OpenTX. It's providing you the exact same level of default features while adding more through apps. You can go back and forth between the 2 bootloaders without an issue.
|
||||
|
||||
## Multimodule upgrade procedure
|
||||
1. Either:
|
||||
1. Connect the transmitter using a USB cable and power it on, or
|
||||
1. Remove the SD card from the transmitter and mount it using a suitable reader
|
||||
1. Copy the pre-compiled firmware file into the **\firmware** folder of the SD card (create the folder if it does not exist)
|
||||
1. Copy the pre-compiled firmware file into the `\FIRMWARE` folder of the SD card (create the folder if it does not exist)
|
||||
1. Power the transmitter off and remove the USB cable or put the SD card back in the transmitter
|
||||
1. Enter the transmitter's Maintenance Menu by powering it on with the outer buttons of the two horizontal trims held down
|
||||
1. Select **Update Multi**,
|
||||
1. Push both horizontals trims inwards (close to each others) while powering on the radio
|
||||
1. The screen title should indicate `Boot Loader V2.9Ready` or newer
|
||||
1. Launch the `FlashMulti_xxx.app` app from the `Run App` menu
|
||||
1. Choose the appropriate file type
|
||||
1. **HEX** to update an Atmega328p module
|
||||
1. **BIN** to update an STM32 module
|
||||
1. Select **Update**
|
||||
1. `HEX` to update an Atmega328p module
|
||||
1. `BIN` to update an STM32 module
|
||||
1. Select `Update`
|
||||
1. Choose the firmware file to flash, long press to select it
|
||||
1. Long press again to flash the selected file to the module
|
||||
1. When flashing has finished, long press EXIT to reboot in normal mode
|
||||
|
||||
When flashing has finished, long press EXIT to reboot in normal mode.
|
||||
|
||||
## Troubleshooting
|
||||
TBD
|
||||
### Troubleshooting
|
||||
1. If the flashing procedure fails try to redo the process with `Invert Com Port` enabled
|
||||
1. Make sure to have the latest bootloader on the MPM module before attempting to Flash from the TX:
|
||||
1. For an Atmega328p module use the bootloader bundled with the `Multi 4-in1 AVR board 1.0.3` or later
|
||||
1. For a STM32 module use the bootloader bundled with the `Multi 4-in1 STM32 board 1.0.9` or later
|
||||
|
33
docs/erase.hex
Normal file
33
docs/erase.hex
Normal file
@ -0,0 +1,33 @@
|
||||
:20000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00
|
||||
:20002000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0
|
||||
:20004000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0
|
||||
:20006000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA0
|
||||
:20008000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80
|
||||
:2000A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF60
|
||||
:2000C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF40
|
||||
:2000E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF20
|
||||
:20010000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
|
||||
:20012000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDF
|
||||
:20014000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBF
|
||||
:20016000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9F
|
||||
:20018000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F
|
||||
:2001A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5F
|
||||
:2001C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F
|
||||
:2001E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1F
|
||||
:20020000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE
|
||||
:20022000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDE
|
||||
:20024000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBE
|
||||
:20026000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9E
|
||||
:20028000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7E
|
||||
:2002A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5E
|
||||
:2002C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3E
|
||||
:2002E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1E
|
||||
:20030000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD
|
||||
:20032000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDD
|
||||
:20034000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBD
|
||||
:20036000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9D
|
||||
:20038000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7D
|
||||
:2003A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D
|
||||
:2003C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3D
|
||||
:2003E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1D
|
||||
:00000001FF
|
BIN
docs/images/Bootloader.jpg
Normal file
BIN
docs/images/Bootloader.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 260 KiB |
BIN
docs/images/FlashMulti.jpg
Normal file
BIN
docs/images/FlashMulti.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 320 KiB |
Loading…
x
Reference in New Issue
Block a user