mirror of
https://github.com/pascallanger/DIY-Multiprotocol-TX-Module.git
synced 2026-02-04 22:43:15 +00:00
Merge remote-tracking branch 'refs/remotes/pascallanger/master'
# Conflicts: all resolved by taking the master's code since all changes were already taken into master # Multiprotocol/CABELL_nrf224l01.ino # Multiprotocol/Multiprotocol.h # Multiprotocol/Multiprotocol.ino # Multiprotocol/NRF24l01_SPI.ino # Multiprotocol/Validate.h # Multiprotocol/_Config.h
This commit is contained in:
@@ -179,12 +179,26 @@ static void AFHDS2A_build_packet(uint8_t type)
|
||||
packet[0] = 0x56;
|
||||
for(uint8_t ch=0; ch<14; ch++)
|
||||
{
|
||||
/*if((Model.limits[ch].flags & CH_FAILSAFE_EN))
|
||||
#ifdef AFHDS2A_FAILSAFE
|
||||
int8_t failsafe = AFHDS2AFailsafe[ch];
|
||||
//
|
||||
if(failsafe != -1)
|
||||
{
|
||||
packet[9 + ch*2] = Servo_data[CH_AETR[ch]] & 0xff;
|
||||
packet[10+ ch*2] = (Servo_data[CH_AETR[ch]] >> 8) & 0xff;
|
||||
//
|
||||
if (failsafe > AFHDS2AFailsafeMAX)
|
||||
failsafe = AFHDS2AFailsafeMAX;
|
||||
//
|
||||
if (failsafe < AFHDS2AFailsafeMIN)
|
||||
failsafe = AFHDS2AFailsafeMIN;
|
||||
//
|
||||
double scale = (float)failsafe/(float)100;
|
||||
int16_t failsafeMicros = 1500 + ((float)512 * scale);
|
||||
//
|
||||
packet[9 + ch*2] = failsafeMicros & 0xff;
|
||||
packet[10+ ch*2] = ( failsafeMicros >> 8) & 0xff;
|
||||
}
|
||||
else*/
|
||||
else
|
||||
#endif
|
||||
{
|
||||
packet[9 + ch*2] = 0xff;
|
||||
packet[10+ ch*2] = 0xff;
|
||||
@@ -260,6 +274,7 @@ uint16_t ReadAFHDS2A()
|
||||
while ((uint16_t)micros()-start < 700) // Wait max 700µs, using serial+telemetry exit in about 120µs
|
||||
if(!(A7105_ReadReg(A7105_00_MODE) & 0x01))
|
||||
break;
|
||||
A7105_SetPower();
|
||||
A7105_SetTxRxMode(TXRX_OFF); // Turn LNA off since we are in near range and we want to prevent swamping
|
||||
A7105_Strobe(A7105_RX);
|
||||
phase &= ~AFHDS2A_WAIT_WRITE;
|
||||
@@ -325,6 +340,7 @@ uint16_t ReadAFHDS2A()
|
||||
while ((uint16_t)micros()-start < 700) // Wait max 700µs, using serial+telemetry exit in about 120µs
|
||||
if(!(A7105_ReadReg(A7105_00_MODE) & 0x01))
|
||||
break;
|
||||
A7105_SetPower();
|
||||
A7105_SetTxRxMode(RX_EN);
|
||||
A7105_Strobe(A7105_RX);
|
||||
phase &= ~AFHDS2A_WAIT_WRITE;
|
||||
|
||||
@@ -53,7 +53,11 @@ void ASSAN_send_packet()
|
||||
uint16_t temp;
|
||||
for(uint8_t i=0;i<8;i++)
|
||||
{
|
||||
temp=Servo_data[i]<<3;
|
||||
if(mode_select != MODE_SERIAL) // If in PPM mode extend the output to 1000...2000µs
|
||||
temp=convert_channel_16b_nolim(i,1000,2000);
|
||||
else
|
||||
temp=Servo_data[i];
|
||||
temp<<=3;
|
||||
packet[2*i]=temp>>8;
|
||||
packet[2*i+1]=temp;
|
||||
}
|
||||
|
||||
@@ -25,19 +25,22 @@ Multiprotocol is distributed in the hope that it will be useful,
|
||||
#define BAYANG_PACKET_SIZE 15
|
||||
#define BAYANG_RF_NUM_CHANNELS 4
|
||||
#define BAYANG_RF_BIND_CHANNEL 0
|
||||
#define BAYANG_RF_BIND_CHANNEL_X16_AH 10
|
||||
#define BAYANG_ADDRESS_LENGTH 5
|
||||
|
||||
enum BAYANG_FLAGS {
|
||||
// flags going to packet[2]
|
||||
BAYANG_FLAG_RTH = 0x01,
|
||||
BAYANG_FLAG_HEADLESS = 0x02,
|
||||
BAYANG_FLAG_FLIP = 0x08,
|
||||
BAYANG_FLAG_VIDEO = 0x10,
|
||||
BAYANG_FLAG_PICTURE = 0x20,
|
||||
// flags going to packet[3]
|
||||
BAYANG_FLAG_INVERTED = 0x80 // inverted flight on Floureon H101
|
||||
// flags going to packet[2]
|
||||
BAYANG_FLAG_RTH = 0x01,
|
||||
BAYANG_FLAG_HEADLESS = 0x02,
|
||||
BAYANG_FLAG_FLIP = 0x08,
|
||||
BAYANG_FLAG_VIDEO = 0x10,
|
||||
BAYANG_FLAG_PICTURE = 0x20,
|
||||
// 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
|
||||
};
|
||||
|
||||
uint8_t bayang_bind_chan;
|
||||
static void __attribute__((unused)) BAYANG_send_packet(uint8_t bind)
|
||||
{
|
||||
uint8_t i;
|
||||
@@ -53,13 +56,29 @@ static void __attribute__((unused)) BAYANG_send_packet(uint8_t bind)
|
||||
packet[i+1]=rx_tx_addr[i];
|
||||
for(i=0;i<4;i++)
|
||||
packet[i+6]=hopping_frequency[i];
|
||||
packet[10] = rx_tx_addr[0]; // txid[0]
|
||||
packet[11] = rx_tx_addr[1]; // txid[1]
|
||||
switch (sub_protocol)
|
||||
{
|
||||
case X16_AH:
|
||||
packet[10] = 0x00;
|
||||
packet[11] = 0x00;
|
||||
break;
|
||||
default:
|
||||
packet[10] = rx_tx_addr[0]; // txid[0]
|
||||
packet[11] = rx_tx_addr[1]; // txid[1]
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16_t val;
|
||||
packet[0] = 0xA5;
|
||||
switch (sub_protocol) {
|
||||
case X16_AH:
|
||||
packet[0] = 0xA6;
|
||||
break;
|
||||
default:
|
||||
packet[0] = 0xA5;
|
||||
break;
|
||||
}
|
||||
packet[1] = 0xFA; // normal mode is 0xf7, expert 0xfa
|
||||
|
||||
//Flags packet[2]
|
||||
@@ -78,7 +97,8 @@ static void __attribute__((unused)) BAYANG_send_packet(uint8_t bind)
|
||||
packet[3] = 0x00;
|
||||
if(Servo_AUX6)
|
||||
packet[3] = BAYANG_FLAG_INVERTED;
|
||||
|
||||
if(Servo_AUX7)
|
||||
packet[3] |= BAYANG_FLAG_TAKE_OFF;
|
||||
//Aileron
|
||||
val = convert_channel_10b(AILERON);
|
||||
packet[4] = (val>>8) + ((val>>2) & 0xFC);
|
||||
@@ -96,13 +116,26 @@ static void __attribute__((unused)) BAYANG_send_packet(uint8_t bind)
|
||||
packet[10] = (val>>8) + (val>>2 & 0xFC);
|
||||
packet[11] = val & 0xFF;
|
||||
}
|
||||
packet[12] = rx_tx_addr[2]; // txid[2]
|
||||
packet[13] = sub_protocol==H8S3D?0x34:0x0A;
|
||||
switch (sub_protocol)
|
||||
{
|
||||
case H8S3D:
|
||||
packet[12] = rx_tx_addr[2]; // txid[2]
|
||||
packet[13] = 0x34;
|
||||
break;
|
||||
case X16_AH:
|
||||
packet[12] = 0;
|
||||
packet[13] = 0;
|
||||
break;
|
||||
default:
|
||||
packet[12] = rx_tx_addr[2]; // txid[2]
|
||||
packet[13] = 0x0A;
|
||||
break;
|
||||
}
|
||||
packet[14] = 0;
|
||||
for (uint8_t i=0; i < BAYANG_PACKET_SIZE-1; i++)
|
||||
for (uint8_t i=0; i < BAYANG_PACKET_SIZE-1; i++)
|
||||
packet[14] += packet[i];
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, bind ? BAYANG_RF_BIND_CHANNEL:hopping_frequency[hopping_frequency_no++]);
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, bind ? bayang_bind_chan:hopping_frequency[hopping_frequency_no++]);
|
||||
hopping_frequency_no%=BAYANG_RF_NUM_CHANNELS;
|
||||
|
||||
// clear packet status bits and TX FIFO
|
||||
@@ -111,17 +144,16 @@ static void __attribute__((unused)) BAYANG_send_packet(uint8_t bind)
|
||||
|
||||
XN297_WritePayload(packet, BAYANG_PACKET_SIZE);
|
||||
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
|
||||
// Power on, TX mode, 2byte CRC
|
||||
// Why CRC0? xn297 does not interpret it - either 16-bit CRC or nothing
|
||||
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
|
||||
|
||||
#ifdef BAYANG_HUB_TELEMETRY
|
||||
if (option)
|
||||
if (option)
|
||||
{ // switch radio to rx as soon as packet is sent
|
||||
|
||||
while (!(NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_TX_DS)));
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x03);
|
||||
}
|
||||
@@ -131,7 +163,7 @@ static void __attribute__((unused)) BAYANG_send_packet(uint8_t bind)
|
||||
}
|
||||
|
||||
#ifdef BAYANG_HUB_TELEMETRY
|
||||
static void __attribute__((unused)) check_rx(void)
|
||||
static void __attribute__((unused)) BAYANG_check_rx(void)
|
||||
{
|
||||
if (NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
|
||||
{ // data received from model
|
||||
@@ -171,16 +203,16 @@ static void __attribute__((unused)) BAYANG_init()
|
||||
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
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, BAYANG_PACKET_SIZE);
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
|
||||
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);
|
||||
NRF24L01_Activate(0x73);
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, BAYANG_PACKET_SIZE);
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
|
||||
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);
|
||||
NRF24L01_Activate(0x73);
|
||||
}
|
||||
|
||||
uint16_t BAYANG_callback()
|
||||
@@ -204,7 +236,7 @@ uint16_t BAYANG_callback()
|
||||
}
|
||||
|
||||
if (packet_count > 1)
|
||||
check_rx();
|
||||
BAYANG_check_rx();
|
||||
|
||||
packet_count %= 5;
|
||||
}
|
||||
@@ -251,10 +283,18 @@ uint16_t initBAYANG(void)
|
||||
BAYANG_initialize_txid();
|
||||
BAYANG_init();
|
||||
packet_count=0;
|
||||
#ifdef BAYANG_HUB_TELEMETRY
|
||||
init_frskyd_link_telemetry();
|
||||
telemetry_lost=1; // do not send telemetry to TX right away until we have a TX_RSSI value to prevent warning message...
|
||||
#endif
|
||||
switch (sub_protocol) {
|
||||
case X16_AH:
|
||||
bayang_bind_chan = BAYANG_RF_BIND_CHANNEL_X16_AH;
|
||||
break;
|
||||
default:
|
||||
bayang_bind_chan = BAYANG_RF_BIND_CHANNEL;
|
||||
break;
|
||||
}
|
||||
#ifdef BAYANG_HUB_TELEMETRY
|
||||
init_frskyd_link_telemetry();
|
||||
telemetry_lost=1; // do not send telemetry to TX right away until we have a TX_RSSI value to prevent warning message...
|
||||
#endif
|
||||
return BAYANG_INITIAL_WAIT+BAYANG_PACKET_PERIOD;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,33 +24,34 @@ Multiprotocol is distributed in the hope that it will be useful,
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// The Receiver for this protocol is available at: https://github.com/soligen2010/RC_RX_CABELL_V3_FHSS
|
||||
|
||||
// The Receiver for this protocol is available at: https://github.com/soligen2010/RC_RX_CABELL_V3_FHSS
|
||||
|
||||
#if defined(CABELL_NRF24L01_INO)
|
||||
|
||||
#include "iface_nrf24l01.h"
|
||||
|
||||
#define CABELL_BIND_COUNT 2000 // At least 2000 so that if TX toggles the serial bind flag then bind mode is never exited
|
||||
#define CABELL_PACKET_PERIOD 3000 // Do not set too low or else next packet may not be finished transmitting before the channel is changed next time around
|
||||
#define CABELL_BIND_COUNT 2000 // At least 2000 so that if TX toggles the serial bind flag then bind mode is never exited
|
||||
#define CABELL_PACKET_PERIOD 3000 // Do not set too low or else next packet may not be finished transmitting before the channel is changed next time around
|
||||
|
||||
#define CABELL_NUM_CHANNELS 16 // The maximum number of RC channels that can be sent in one packet
|
||||
#define CABELL_MIN_CHANNELS 4 // The minimum number of channels that must be included in a packet, the number of channels cannot be reduced any further than this
|
||||
#define CABELL_PAYLOAD_BYTES 24 // 12 bits per value * 16 channels
|
||||
#define CABELL_NUM_CHANNELS 16 // The maximum number of RC channels that can be sent in one packet
|
||||
#define CABELL_MIN_CHANNELS 4 // The minimum number of channels that must be included in a packet, the number of channels cannot be reduced any further than this
|
||||
#define CABELL_PAYLOAD_BYTES 24 // 12 bits per value * 16 channels
|
||||
|
||||
#define CABELL_RADIO_CHANNELS 9 // This is 1/5 of the total number of radio channels used for FHSS
|
||||
#define CABELL_RADIO_MIN_CHANNEL_NUM 3 // Channel 0 is right on the boarder of allowed frequency range, so move up to avoid bleeding over
|
||||
#define CABELL_TELEMETRY_PACKET_LENGTH 4
|
||||
#define CABELL_RADIO_CHANNELS 9 // This is 1/5 of the total number of radio channels used for FHSS
|
||||
#define CABELL_RADIO_MIN_CHANNEL_NUM 3 // Channel 0 is right on the boarder of allowed frequency range, so move up to avoid bleeding over
|
||||
#define CABELL_TELEMETRY_PACKET_LENGTH 4
|
||||
|
||||
#define CABELL_BIND_RADIO_ADDR 0xA4B7C123F7LL
|
||||
#define CABELL_BIND_RADIO_ADDR 0xA4B7C123F7LL
|
||||
|
||||
#define CABELL_OPTION_MASK_CHANNEL_REDUCTION 0x0F
|
||||
#define CABELL_OPTION_MASK_RECIEVER_OUTPUT_MODE 0x30
|
||||
#define CABELL_OPTION_SHIFT_RECIEVER_OUTPUT_MODE 4
|
||||
#define CABELL_OPTION_MASK_MAX_POWER_OVERRIDE 0x40
|
||||
#define CABELL_OPTION_MASK_CHANNEL_REDUCTION 0x0F
|
||||
#define CABELL_OPTION_MASK_RECIEVER_OUTPUT_MODE 0x30
|
||||
#define CABELL_OPTION_SHIFT_RECIEVER_OUTPUT_MODE 4
|
||||
#define CABELL_OPTION_MASK_MAX_POWER_OVERRIDE 0x40
|
||||
|
||||
typedef struct {
|
||||
enum RxMode_t : uint8_t { // Note bit 8 is used to indicate if the packet is the first of 2 on the channel. Mask out this bit before using the enum
|
||||
typedef struct
|
||||
{
|
||||
enum RxMode_t : uint8_t
|
||||
{ // Note bit 8 is used to indicate if the packet is the first of 2 on the channel. Mask out this bit before using the enum
|
||||
normal = 0,
|
||||
bind = 1,
|
||||
setFailSafe = 2,
|
||||
@@ -58,8 +59,8 @@ typedef struct {
|
||||
telemetryResponse = 4,
|
||||
unBind = 127
|
||||
} RxMode;
|
||||
uint8_t reserved = 0;
|
||||
uint8_t option;
|
||||
uint8_t reserved = 0;
|
||||
uint8_t option;
|
||||
/* mask 0x0F : Channel reduction. The number of channels to not send (subtracted from the 16 max channels) at least 4 are always sent
|
||||
* mask 0x30>>4 : Receiver output mode
|
||||
* 0 (00) = Single PPM on individual pins for each channel
|
||||
@@ -69,293 +70,315 @@ typedef struct {
|
||||
* mask 0x40>>6 Contains max power override flag for Multi-protocol TX module. Also sent to RX
|
||||
* mask 0x80>>7 Unused
|
||||
*/
|
||||
uint8_t modelNum;
|
||||
uint8_t checkSum_LSB;
|
||||
uint8_t checkSum_MSB;
|
||||
uint8_t payloadValue [CABELL_PAYLOAD_BYTES] = {0}; //12 bits per channel value, unsigned
|
||||
uint8_t modelNum;
|
||||
uint8_t checkSum_LSB;
|
||||
uint8_t checkSum_MSB;
|
||||
uint8_t payloadValue [CABELL_PAYLOAD_BYTES] = {0}; //12 bits per channel value, unsigned
|
||||
} CABELL_RxTxPacket_t;
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
static uint8_t __attribute__((unused)) CABELL_getNextChannel (uint8_t seqArray[], uint8_t seqArraySize, uint8_t prevChannel) {
|
||||
/* Possible channels are in 5 bands, each band comprised of seqArraySize channels
|
||||
* seqArray contains seqArraySize elements in the relative order in which we should progress through the band
|
||||
*
|
||||
* Each time the channel is changes, bands change in a way so that the next channel will be in a
|
||||
* different non-adjacent band. Both the band changes and the index in seqArray is incremented.
|
||||
*/
|
||||
prevChannel -= CABELL_RADIO_MIN_CHANNEL_NUM; // Subtract CABELL_RADIO_MIN_CHANNEL_NUM because it was added to the return value
|
||||
prevChannel = constrain(prevChannel,0,(seqArraySize * 5) ); // Constrain the values just in case something bogus was sent in.
|
||||
|
||||
uint8_t currBand = prevChannel / seqArraySize;
|
||||
uint8_t nextBand = (currBand + 3) % 5;
|
||||
static uint8_t __attribute__((unused)) CABELL_getNextChannel (uint8_t seqArray[], uint8_t seqArraySize, uint8_t prevChannel)
|
||||
{
|
||||
/* Possible channels are in 5 bands, each band comprised of seqArraySize channels
|
||||
* seqArray contains seqArraySize elements in the relative order in which we should progress through the band
|
||||
*
|
||||
* Each time the channel is changes, bands change in a way so that the next channel will be in a
|
||||
* different non-adjacent band. Both the band changes and the index in seqArray is incremented.
|
||||
*/
|
||||
prevChannel -= CABELL_RADIO_MIN_CHANNEL_NUM; // Subtract CABELL_RADIO_MIN_CHANNEL_NUM because it was added to the return value
|
||||
if(prevChannel>(seqArraySize * 5))
|
||||
prevChannel=seqArraySize * 5; // Constrain the values just in case something bogus was sent in.
|
||||
|
||||
uint8_t prevChannalSeqArrayValue = prevChannel % seqArraySize;
|
||||
uint8_t prevChannalSeqArrayPosition = 0;
|
||||
for (int x = 0; x < seqArraySize; x++) { // Find the position of the previous channel in the array
|
||||
if (seqArray[x] == prevChannalSeqArrayValue) {
|
||||
prevChannalSeqArrayPosition = x;
|
||||
}
|
||||
}
|
||||
uint8_t nextChannalSeqArrayPosition = prevChannalSeqArrayPosition + 1;
|
||||
if (nextChannalSeqArrayPosition >= seqArraySize) nextChannalSeqArrayPosition = 0;
|
||||
uint8_t currBand = prevChannel / seqArraySize;
|
||||
uint8_t nextBand = (currBand + 3) % 5;
|
||||
|
||||
return (seqArraySize * nextBand) + seqArray[nextChannalSeqArrayPosition] + CABELL_RADIO_MIN_CHANNEL_NUM; // Add CABELL_RADIO_MIN_CHANNEL_NUM so we dont use channel 0 as it may bleed below 2.400 GHz
|
||||
uint8_t prevChannalSeqArrayValue = prevChannel % seqArraySize;
|
||||
uint8_t prevChannalSeqArrayPosition = 0;
|
||||
for (int x = 0; x < seqArraySize; x++)
|
||||
{ // Find the position of the previous channel in the array
|
||||
if (seqArray[x] == prevChannalSeqArrayValue)
|
||||
prevChannalSeqArrayPosition = x;
|
||||
}
|
||||
uint8_t nextChannalSeqArrayPosition = prevChannalSeqArrayPosition + 1;
|
||||
if (nextChannalSeqArrayPosition >= seqArraySize)
|
||||
nextChannalSeqArrayPosition = 0;
|
||||
|
||||
return (seqArraySize * nextBand) + seqArray[nextChannalSeqArrayPosition] + CABELL_RADIO_MIN_CHANNEL_NUM; // Add CABELL_RADIO_MIN_CHANNEL_NUM so we dont use channel 0 as it may bleed below 2.400 GHz
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
#if defined TELEMETRY
|
||||
#if defined CABELL_HUB_TELEMETRY
|
||||
static void __attribute__((unused)) CABELL_get_telemetry()
|
||||
{
|
||||
// calculate TX rssi based on past 250 expected telemetry packets. Cannot use full second count because telemetry_counter is not large enough
|
||||
state++;
|
||||
if (state > 250)
|
||||
{
|
||||
TX_RSSI = telemetry_counter;
|
||||
telemetry_counter = 0;
|
||||
state = 0;
|
||||
telemetry_lost=0;
|
||||
}
|
||||
// calculate TX rssi based on past 250 expected telemetry packets. Cannot use full second count because telemetry_counter is not large enough
|
||||
state++;
|
||||
if (state > 250)
|
||||
{
|
||||
TX_RSSI = telemetry_counter;
|
||||
telemetry_counter = 0;
|
||||
state = 0;
|
||||
telemetry_lost=0;
|
||||
}
|
||||
|
||||
// Process incoming telemetry packet of it was received
|
||||
if (NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR)) { // data received from model
|
||||
NRF24L01_ReadPayload(packet, CABELL_TELEMETRY_PACKET_LENGTH);
|
||||
if ((packet[0] & 0x7F) == CABELL_RxTxPacket_t::RxMode_t::telemetryResponse) // ignore high order bit in compare because it toggles with each packet
|
||||
{
|
||||
RX_RSSI = packet[1]; // Packet rate 0 to 255 where 255 is 100% packet rate
|
||||
v_lipo1 = packet[2]; // Directly from analog input of receiver, but reduced to 8-bit depth (0 to 255). Scaling depends on the input to the analog pin of the receiver.
|
||||
v_lipo2 = packet[3]; // Directly from analog input of receiver, but reduced to 8-bit depth (0 to 255). Scaling depends on the input to the analog pin of the receiver.
|
||||
telemetry_counter++;
|
||||
if(telemetry_lost==0) telemetry_link=1;
|
||||
}
|
||||
} else {
|
||||
// If no telemetry packet was received then delay by the typical telemetry packet processing time
|
||||
// This is done to try to keep the sendPacket process timing more consistent. Since the SPI payload read takes some time
|
||||
delayMicroseconds(50);
|
||||
}
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
NRF24L01_FlushRx();
|
||||
// Process incoming telemetry packet of it was received
|
||||
if (NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
|
||||
{ // data received from model
|
||||
NRF24L01_ReadPayload(packet, CABELL_TELEMETRY_PACKET_LENGTH);
|
||||
if ((packet[0] & 0x7F) == CABELL_RxTxPacket_t::RxMode_t::telemetryResponse) // ignore high order bit in compare because it toggles with each packet
|
||||
{
|
||||
RX_RSSI = packet[1]; // Packet rate 0 to 255 where 255 is 100% packet rate
|
||||
v_lipo1 = packet[2]; // Directly from analog input of receiver, but reduced to 8-bit depth (0 to 255). Scaling depends on the input to the analog pin of the receiver.
|
||||
v_lipo2 = packet[3]; // Directly from analog input of receiver, but reduced to 8-bit depth (0 to 255). Scaling depends on the input to the analog pin of the receiver.
|
||||
telemetry_counter++;
|
||||
if(telemetry_lost==0)
|
||||
telemetry_link=1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If no telemetry packet was received then delay by the typical telemetry packet processing time
|
||||
// This is done to try to keep the sendPacket process timing more consistent. Since the SPI payload read takes some time
|
||||
delayMicroseconds(50);
|
||||
}
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
NRF24L01_FlushRx();
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
static void __attribute__((unused)) CABELL_send_packet(uint8_t bindMode)
|
||||
{
|
||||
#if defined TELEMETRY
|
||||
if (!bindMode && (sub_protocol == CABELL_V3_TELEMETRY)) { // check for incoming packet and switch radio back to TX mode if we were listening for telemetry
|
||||
CABELL_get_telemetry();
|
||||
}
|
||||
#endif
|
||||
#if defined CABELL_HUB_TELEMETRY
|
||||
if (!bindMode && (sub_protocol == CABELL_V3_TELEMETRY)) // check for incoming packet and switch radio back to TX mode if we were listening for telemetry
|
||||
CABELL_get_telemetry();
|
||||
#endif
|
||||
|
||||
CABELL_RxTxPacket_t TxPacket;
|
||||
CABELL_RxTxPacket_t TxPacket;
|
||||
|
||||
uint8_t channelReduction = constrain((option & CABELL_OPTION_MASK_CHANNEL_REDUCTION),0,CABELL_NUM_CHANNELS-CABELL_MIN_CHANNELS); // Max 12 - cannot reduce below 4 channels
|
||||
if (bindMode) {
|
||||
channelReduction = 0; // Send full packet to bind as higher channels will contain bind info
|
||||
}
|
||||
uint8_t packetSize = sizeof(TxPacket) - ((((channelReduction - (channelReduction%2))/ 2)) * 3); // reduce 3 bytes per 2 channels, but not last channel if it is odd
|
||||
uint8_t maxPayloadValueIndex = sizeof(TxPacket.payloadValue) - (sizeof(TxPacket) - packetSize);
|
||||
uint8_t channelReduction = constrain((option & CABELL_OPTION_MASK_CHANNEL_REDUCTION),0,CABELL_NUM_CHANNELS-CABELL_MIN_CHANNELS); // Max 12 - cannot reduce below 4 channels
|
||||
if (bindMode)
|
||||
channelReduction = 0; // Send full packet to bind as higher channels will contain bind info
|
||||
|
||||
if ((sub_protocol == CABELL_UNBIND) && !bindMode) {
|
||||
TxPacket.RxMode = CABELL_RxTxPacket_t::RxMode_t::unBind;
|
||||
TxPacket.option = option;
|
||||
} else {
|
||||
if (sub_protocol == CABELL_SET_FAIL_SAFE && !bindMode) {
|
||||
TxPacket.RxMode = CABELL_RxTxPacket_t::RxMode_t::setFailSafe;
|
||||
} else {
|
||||
if (bindMode) {
|
||||
TxPacket.RxMode = CABELL_RxTxPacket_t::RxMode_t::bind;
|
||||
} else {
|
||||
switch (sub_protocol) {
|
||||
case CABELL_V3_TELEMETRY : TxPacket.RxMode = CABELL_RxTxPacket_t::RxMode_t::normalWithTelemetry;
|
||||
break;
|
||||
|
||||
default : TxPacket.RxMode = CABELL_RxTxPacket_t::RxMode_t::normal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
TxPacket.option = (bindMode) ? (option & (~CABELL_OPTION_MASK_CHANNEL_REDUCTION)) : option; //remove channel reduction if in bind mode
|
||||
}
|
||||
TxPacket.reserved = 0;
|
||||
TxPacket.modelNum = RX_num;
|
||||
uint16_t checkSum = TxPacket.modelNum + TxPacket.option + TxPacket.RxMode + TxPacket.reserved; // Start Calculate checksum
|
||||
uint8_t packetSize = sizeof(TxPacket) - ((((channelReduction - (channelReduction%2))/ 2)) * 3); // reduce 3 bytes per 2 channels, but not last channel if it is odd
|
||||
uint8_t maxPayloadValueIndex = sizeof(TxPacket.payloadValue) - (sizeof(TxPacket) - packetSize);
|
||||
|
||||
int adjusted_x;
|
||||
int payloadIndex = 0;
|
||||
uint16_t holdValue;
|
||||
|
||||
for (int x = 0;(x < CABELL_NUM_CHANNELS - channelReduction); x++) {
|
||||
switch (x) {
|
||||
case 0 : adjusted_x = ELEVATOR; break;
|
||||
case 1 : adjusted_x = AILERON; break;
|
||||
case 2 : adjusted_x = RUDDER; break;
|
||||
case 3 : adjusted_x = THROTTLE; break;
|
||||
default : adjusted_x = x; break;
|
||||
}
|
||||
holdValue = map(limit_channel_100(adjusted_x),servo_min_100,servo_max_100,1000,2000); // valid channel values are 1000 to 2000
|
||||
if (bindMode) {
|
||||
switch (adjusted_x) {
|
||||
case THROTTLE : holdValue = 1000; break; // always set throttle to off when binding for safety
|
||||
//tx address sent for bind
|
||||
case 11 : holdValue = 1000 + rx_tx_addr[0]; break;
|
||||
case 12 : holdValue = 1000 + rx_tx_addr[1]; break;
|
||||
case 13 : holdValue = 1000 + rx_tx_addr[2]; break;
|
||||
case 14 : holdValue = 1000 + rx_tx_addr[3]; break;
|
||||
case 15 : holdValue = 1000 + rx_tx_addr[4]; break;
|
||||
}
|
||||
}
|
||||
if ((sub_protocol == CABELL_UNBIND) && !bindMode)
|
||||
{
|
||||
TxPacket.RxMode = CABELL_RxTxPacket_t::RxMode_t::unBind;
|
||||
TxPacket.option = option;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sub_protocol == CABELL_SET_FAIL_SAFE && !bindMode)
|
||||
TxPacket.RxMode = CABELL_RxTxPacket_t::RxMode_t::setFailSafe;
|
||||
else
|
||||
{
|
||||
if (bindMode)
|
||||
TxPacket.RxMode = CABELL_RxTxPacket_t::RxMode_t::bind;
|
||||
else
|
||||
{
|
||||
switch (sub_protocol)
|
||||
{
|
||||
case CABELL_V3_TELEMETRY:
|
||||
TxPacket.RxMode = CABELL_RxTxPacket_t::RxMode_t::normalWithTelemetry;
|
||||
break;
|
||||
default:
|
||||
TxPacket.RxMode = CABELL_RxTxPacket_t::RxMode_t::normal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
TxPacket.option = (bindMode) ? (option & (~CABELL_OPTION_MASK_CHANNEL_REDUCTION)) : option; //remove channel reduction if in bind mode
|
||||
}
|
||||
TxPacket.reserved = 0;
|
||||
TxPacket.modelNum = RX_num;
|
||||
uint16_t checkSum = TxPacket.modelNum + TxPacket.option + TxPacket.RxMode + TxPacket.reserved; // Start Calculate checksum
|
||||
|
||||
// use 12 bits per value
|
||||
if (x % 2) { //output channel number is ODD
|
||||
holdValue = holdValue<<4;
|
||||
payloadIndex--;
|
||||
} else {
|
||||
holdValue &= 0x0FFF;
|
||||
}
|
||||
TxPacket.payloadValue[payloadIndex] |= (uint8_t)(holdValue & 0x00FF);
|
||||
payloadIndex++;
|
||||
TxPacket.payloadValue[payloadIndex] |= (uint8_t)((holdValue>>8) & 0x00FF);
|
||||
payloadIndex++;
|
||||
}
|
||||
|
||||
for(int x = 0; x < maxPayloadValueIndex ; x++) {
|
||||
checkSum += TxPacket.payloadValue[x]; // Finish Calculate checksum
|
||||
}
|
||||
int adjusted_x;
|
||||
int payloadIndex = 0;
|
||||
uint16_t holdValue;
|
||||
|
||||
TxPacket.checkSum_MSB = checkSum >> 8;
|
||||
TxPacket.checkSum_LSB = checkSum & 0x00FF;
|
||||
for (int x = 0;(x < CABELL_NUM_CHANNELS - channelReduction); x++)
|
||||
{
|
||||
switch (x)
|
||||
{
|
||||
case 0 : adjusted_x = ELEVATOR; break;
|
||||
case 1 : adjusted_x = AILERON; break;
|
||||
case 2 : adjusted_x = RUDDER; break;
|
||||
case 3 : adjusted_x = THROTTLE; break;
|
||||
default : adjusted_x = x; break;
|
||||
}
|
||||
holdValue = map(limit_channel_100(adjusted_x),servo_min_100,servo_max_100,1000,2000); // valid channel values are 1000 to 2000
|
||||
if (bindMode)
|
||||
{
|
||||
switch (adjusted_x)
|
||||
{
|
||||
case THROTTLE : holdValue = 1000; break; // always set throttle to off when binding for safety
|
||||
//tx address sent for bind
|
||||
case 11 : holdValue = 1000 + rx_tx_addr[0]; break;
|
||||
case 12 : holdValue = 1000 + rx_tx_addr[1]; break;
|
||||
case 13 : holdValue = 1000 + rx_tx_addr[2]; break;
|
||||
case 14 : holdValue = 1000 + rx_tx_addr[3]; break;
|
||||
case 15 : holdValue = 1000 + rx_tx_addr[4]; break;
|
||||
}
|
||||
}
|
||||
|
||||
// Set channel for next transmission
|
||||
rf_ch_num = CABELL_getNextChannel (hopping_frequency,CABELL_RADIO_CHANNELS, rf_ch_num);
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH,rf_ch_num);
|
||||
// use 12 bits per value
|
||||
if (x % 2)
|
||||
{ //output channel number is ODD
|
||||
holdValue = holdValue<<4;
|
||||
payloadIndex--;
|
||||
}
|
||||
else
|
||||
holdValue &= 0x0FFF;
|
||||
TxPacket.payloadValue[payloadIndex] |= (uint8_t)(holdValue & 0x00FF);
|
||||
payloadIndex++;
|
||||
TxPacket.payloadValue[payloadIndex] |= (uint8_t)((holdValue>>8) & 0x00FF);
|
||||
payloadIndex++;
|
||||
}
|
||||
|
||||
//NRF24L01_FlushTx(); //just in case things got hung up
|
||||
//NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
||||
|
||||
uint8_t* p = reinterpret_cast<uint8_t*>(&TxPacket.RxMode);
|
||||
*p &= 0x7F; // Make sure 8th bit is clear
|
||||
*p |= (packet_count++)<<7; // This causes the 8th bit of the first byte to toggle with each xmit so consecutive payloads are not identical.
|
||||
// This is a work around for a reported bug in clone NRF24L01 chips that mis-took this case for a re-transmit of the same packet.
|
||||
for(int x = 0; x < maxPayloadValueIndex ; x++)
|
||||
checkSum += TxPacket.payloadValue[x]; // Finish Calculate checksum
|
||||
|
||||
CABELL_SetPower();
|
||||
NRF24L01_WritePayload((uint8_t*)&TxPacket, packetSize);
|
||||
TxPacket.checkSum_MSB = checkSum >> 8;
|
||||
TxPacket.checkSum_LSB = checkSum & 0x00FF;
|
||||
|
||||
#if defined TELEMETRY
|
||||
if (!bindMode && (sub_protocol == CABELL_V3_TELEMETRY)) { // switch radio to rx as soon as packet is sent
|
||||
// calculate transmit time based on packet size and data rate of 1MB per sec
|
||||
// This is done because polling the status register during xmit caused issues.
|
||||
// bits = packst_size * 8 + 73 bits overhead
|
||||
// at 250 Kbs per sec, one bit is 4 uS
|
||||
// then add 140 uS which is 130 uS to begin the xmit and 10 uS fudge factor
|
||||
delayMicroseconds(((((unsigned long)packetSize * 8ul) + 73ul) * 4ul) + 140ul) ;
|
||||
packet_period = CABELL_PACKET_PERIOD + (constrain(((int16_t)(CABELL_NUM_CHANNELS - channelReduction) - (int16_t)6 ),(int16_t)0 ,(int16_t)10 ) * (int16_t)100); // increase packet period by 100 us for each channel over 6
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0F); // RX mode with 16 bit CRC
|
||||
} else
|
||||
#endif
|
||||
packet_period = CABELL_PACKET_PERIOD; // Standard packet period when not in telemetry mode.
|
||||
// Set channel for next transmission
|
||||
rf_ch_num = CABELL_getNextChannel (hopping_frequency,CABELL_RADIO_CHANNELS, rf_ch_num);
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH,rf_ch_num);
|
||||
|
||||
//NRF24L01_FlushTx(); //just in case things got hung up
|
||||
//NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
||||
|
||||
uint8_t* p = reinterpret_cast<uint8_t*>(&TxPacket.RxMode);
|
||||
*p &= 0x7F; // Make sure 8th bit is clear
|
||||
*p |= (packet_count++)<<7; // This causes the 8th bit of the first byte to toggle with each xmit so consecutive payloads are not identical.
|
||||
// This is a work around for a reported bug in clone NRF24L01 chips that mis-took this case for a re-transmit of the same packet.
|
||||
|
||||
CABELL_SetPower();
|
||||
NRF24L01_WritePayload((uint8_t*)&TxPacket, packetSize);
|
||||
|
||||
#if defined CABELL_HUB_TELEMETRY
|
||||
if (!bindMode && (sub_protocol == CABELL_V3_TELEMETRY))
|
||||
{ // switch radio to rx as soon as packet is sent
|
||||
// calculate transmit time based on packet size and data rate of 1MB per sec
|
||||
// This is done because polling the status register during xmit caused issues.
|
||||
// bits = packst_size * 8 + 73 bits overhead
|
||||
// at 250 Kbs per sec, one bit is 4 uS
|
||||
// then add 140 uS which is 130 uS to begin the xmit and 10 uS fudge factor
|
||||
delayMicroseconds(((((unsigned long)packetSize * 8ul) + 73ul) * 4ul) + 140ul) ;
|
||||
packet_period = CABELL_PACKET_PERIOD + (constrain(((int16_t)(CABELL_NUM_CHANNELS - channelReduction) - (int16_t)6 ),(int16_t)0 ,(int16_t)10 ) * (int16_t)100); // increase packet period by 100 us for each channel over 6
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0F); // RX mode with 16 bit CRC
|
||||
}
|
||||
else
|
||||
#endif
|
||||
packet_period = CABELL_PACKET_PERIOD; // Standard packet period when not in telemetry mode.
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
static void __attribute__((unused)) CABELL_getChannelSequence (uint8_t outArray[], uint8_t numChannels, uint64_t permutation) {
|
||||
/* This procedure initializes an array with the sequence progression of channels.
|
||||
* This is not the actual channels itself, but the sequence base to be used within bands of
|
||||
* channels.
|
||||
*
|
||||
* There are numChannels! permutations for arranging the channels
|
||||
* one of these permutations will be calculated based on the permutation input
|
||||
* permutation should be between 1 and numChannels! but the routine will constrain it
|
||||
* if these bounds are exceeded. Typically the radio's unique TX ID should be used.
|
||||
*
|
||||
* The maximum numChannels is 20. Anything larger than this will cause the uint64_t
|
||||
* variables to overflow, yielding unknown results (possibly infinite loop?). Therefor
|
||||
* this routine constrains the value.
|
||||
*/
|
||||
uint64_t i; //iterator counts numChannels
|
||||
uint64_t indexOfNextSequenceValue;
|
||||
uint64_t numChannelsFactorial=1;
|
||||
uint8_t sequenceValue;
|
||||
static void __attribute__((unused)) CABELL_getChannelSequence (uint8_t outArray[], uint8_t numChannels, uint64_t permutation)
|
||||
{
|
||||
/* This procedure initializes an array with the sequence progression of channels.
|
||||
* This is not the actual channels itself, but the sequence base to be used within bands of
|
||||
* channels.
|
||||
*
|
||||
* There are numChannels! permutations for arranging the channels
|
||||
* one of these permutations will be calculated based on the permutation input
|
||||
* permutation should be between 1 and numChannels! but the routine will constrain it
|
||||
* if these bounds are exceeded. Typically the radio's unique TX ID should be used.
|
||||
*
|
||||
* The maximum numChannels is 20. Anything larger than this will cause the uint64_t
|
||||
* variables to overflow, yielding unknown results (possibly infinite loop?). Therefor
|
||||
* this routine constrains the value.
|
||||
*/
|
||||
uint8_t i; //iterator counts numChannels
|
||||
uint64_t indexOfNextSequenceValue;
|
||||
uint64_t numChannelsFactorial=1;
|
||||
uint8_t sequenceValue;
|
||||
|
||||
numChannels = constrain(numChannels,1,20);
|
||||
numChannels = constrain(numChannels,1,20);
|
||||
|
||||
for (i = 1; i <= numChannels;i++) {
|
||||
numChannelsFactorial *= i; // Calculate n!
|
||||
outArray[i-1] = i-1; // Initialize array with the sequence
|
||||
}
|
||||
|
||||
permutation = (permutation % numChannelsFactorial) + 1; // permutation must be between 1 and n! or this algorithm will infinite loop
|
||||
for (i = 1; i <= numChannels;i++)
|
||||
{
|
||||
numChannelsFactorial *= i; // Calculate n!
|
||||
outArray[i-1] = i-1; // Initialize array with the sequence
|
||||
}
|
||||
|
||||
//Rearrange the array elements based on the permutation selected
|
||||
for (i=0, permutation--; i<numChannels; i++ ) {
|
||||
numChannelsFactorial /= ((uint64_t)numChannels)-i;
|
||||
indexOfNextSequenceValue = i+(permutation/numChannelsFactorial);
|
||||
permutation %= numChannelsFactorial;
|
||||
|
||||
//Copy the value in the selected array position
|
||||
sequenceValue = outArray[indexOfNextSequenceValue];
|
||||
|
||||
//Shift the unused elements in the array to make room to move in the one just selected
|
||||
for( ; indexOfNextSequenceValue > i; indexOfNextSequenceValue--) {
|
||||
outArray[indexOfNextSequenceValue] = outArray[indexOfNextSequenceValue-1];
|
||||
}
|
||||
// Copy the selected value into it's new array slot
|
||||
outArray[i] = sequenceValue;
|
||||
}
|
||||
permutation = (permutation % numChannelsFactorial) + 1; // permutation must be between 1 and n! or this algorithm will infinite loop
|
||||
|
||||
//Rearrange the array elements based on the permutation selected
|
||||
for (i=0, permutation--; i<numChannels; i++ )
|
||||
{
|
||||
numChannelsFactorial /= ((uint64_t)numChannels)-i;
|
||||
indexOfNextSequenceValue = i+(permutation/numChannelsFactorial);
|
||||
permutation %= numChannelsFactorial;
|
||||
|
||||
//Copy the value in the selected array position
|
||||
sequenceValue = outArray[indexOfNextSequenceValue];
|
||||
|
||||
//Shift the unused elements in the array to make room to move in the one just selected
|
||||
for( ; indexOfNextSequenceValue > i; indexOfNextSequenceValue--)
|
||||
outArray[indexOfNextSequenceValue] = outArray[indexOfNextSequenceValue-1];
|
||||
|
||||
// Copy the selected value into it's new array slot
|
||||
outArray[i] = sequenceValue;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
static void __attribute__((unused)) CABELL_setAddress()
|
||||
{
|
||||
uint64_t CABELL_addr;
|
||||
uint64_t CABELL_addr;
|
||||
|
||||
// Serial.print("NORM ID: ");Serial.print((uint32_t)(CABELL_normal_addr>>32)); Serial.print(" ");Serial.println((uint32_t)((CABELL_normal_addr<<32)>>32));
|
||||
// Serial.print("NORM ID: ");Serial.print((uint32_t)(CABELL_normal_addr>>32)); Serial.print(" ");Serial.println((uint32_t)((CABELL_normal_addr<<32)>>32));
|
||||
|
||||
if (IS_BIND_DONE_on) {
|
||||
CABELL_addr = (((uint64_t)rx_tx_addr[0]) << 32) +
|
||||
(((uint64_t)rx_tx_addr[1]) << 24) +
|
||||
(((uint64_t)rx_tx_addr[2]) << 16) +
|
||||
(((uint64_t)rx_tx_addr[3]) << 8) +
|
||||
(((uint64_t)rx_tx_addr[4])); // Address to use after binding
|
||||
}
|
||||
else {
|
||||
CABELL_addr = CABELL_BIND_RADIO_ADDR; //static addr for binding
|
||||
}
|
||||
if (IS_BIND_DONE_on)
|
||||
{
|
||||
CABELL_addr = (((uint64_t)rx_tx_addr[0]) << 32) +
|
||||
(((uint64_t)rx_tx_addr[1]) << 24) +
|
||||
(((uint64_t)rx_tx_addr[2]) << 16) +
|
||||
(((uint64_t)rx_tx_addr[3]) << 8) +
|
||||
(((uint64_t)rx_tx_addr[4])); // Address to use after binding
|
||||
}
|
||||
else
|
||||
CABELL_addr = CABELL_BIND_RADIO_ADDR; // Static addr for binding
|
||||
|
||||
CABELL_getChannelSequence(hopping_frequency,CABELL_RADIO_CHANNELS,CABELL_addr); // Get the sequence for hopping through channels
|
||||
rf_ch_num = CABELL_RADIO_MIN_CHANNEL_NUM; // initialize the channel sequence
|
||||
|
||||
packet_count=0;
|
||||
CABELL_getChannelSequence(hopping_frequency,CABELL_RADIO_CHANNELS,CABELL_addr); // Get the sequence for hopping through channels
|
||||
rf_ch_num = CABELL_RADIO_MIN_CHANNEL_NUM; // Initialize the channel sequence
|
||||
|
||||
uint64_t CABELL_Telemetry_addr = ~CABELL_addr; // Invert bits for reading so that telemetry packets have a different address.
|
||||
packet_count=0;
|
||||
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, reinterpret_cast<uint8_t*>(&CABELL_Telemetry_addr), 5);
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0B_RX_ADDR_P1, reinterpret_cast<uint8_t*>(&CABELL_Telemetry_addr), 5);
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, reinterpret_cast<uint8_t*>(&CABELL_addr), 5);
|
||||
uint64_t CABELL_Telemetry_addr = ~CABELL_addr; // Invert bits for reading so that telemetry packets have a different address.
|
||||
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, reinterpret_cast<uint8_t*>(&CABELL_Telemetry_addr), 5);
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0B_RX_ADDR_P1, reinterpret_cast<uint8_t*>(&CABELL_Telemetry_addr), 5);
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, reinterpret_cast<uint8_t*>(&CABELL_addr), 5);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
static void __attribute__((unused)) CABELL_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
CABELL_SetPower();
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_250K); // slower data rate gives better range/reliability
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowledgment on all data pipes
|
||||
NRF24L01_SetTxRxMode(TX_EN); //Power up and 16 bit CRC
|
||||
NRF24L01_Initialize();
|
||||
CABELL_SetPower();
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_250K); // slower data rate gives better range/reliability
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowledgment on all data pipes
|
||||
NRF24L01_SetTxRxMode(TX_EN); //Power up and 16 bit CRC
|
||||
|
||||
CABELL_setAddress();
|
||||
CABELL_setAddress();
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01);
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, 0x20); // 32 byte packet length
|
||||
NRF24L01_WriteReg(NRF24L01_12_RX_PW_P1, 0x20); // 32 byte packet length
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03);
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x5F); // no retransmits
|
||||
NRF24L01_Activate(0x73); // Activate feature register
|
||||
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x3F); // Enable dynamic payload length on all pipes
|
||||
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x04); // Enable dynamic Payload Length
|
||||
NRF24L01_Activate(0x73);
|
||||
prev_power = NRF_POWER_0;
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01);
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, 0x20); // 32 byte packet length
|
||||
NRF24L01_WriteReg(NRF24L01_12_RX_PW_P1, 0x20); // 32 byte packet length
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03);
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x5F); // no retransmits
|
||||
NRF24L01_Activate(0x73); // Activate feature register
|
||||
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x3F); // Enable dynamic payload length on all pipes
|
||||
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x04); // Enable dynamic Payload Length
|
||||
NRF24L01_Activate(0x73);
|
||||
prev_power = NRF_POWER_0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
@@ -363,63 +386,57 @@ static void CABELL_SetPower() // This over-ride the standard Set Power to all
|
||||
// Note that on many modules max power may actually be worse than the normal high power setting
|
||||
// test and only use max if it helps the range
|
||||
{
|
||||
if(IS_BIND_DONE_on && !IS_RANGE_FLAG_on && ((option & CABELL_OPTION_MASK_MAX_POWER_OVERRIDE) != 0)) { // If we are not in range or bind mode and power setting override is in effect, then set max power, else standard power logic
|
||||
if(prev_power != NRF_POWER_3) // prev_power is global variable for NRF24L01; NRF_POWER_3 is max power
|
||||
{
|
||||
uint8_t rf_setup = NRF24L01_ReadReg(NRF24L01_06_RF_SETUP);
|
||||
rf_setup = (rf_setup & 0xF9) | (NRF_POWER_3 << 1);
|
||||
NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, rf_setup);
|
||||
prev_power=NRF_POWER_3;
|
||||
}
|
||||
}
|
||||
else {
|
||||
NRF24L01_SetPower();
|
||||
}
|
||||
if(IS_BIND_DONE_on && !IS_RANGE_FLAG_on && ((option & CABELL_OPTION_MASK_MAX_POWER_OVERRIDE) != 0))
|
||||
{ // If we are not in range or bind mode and power setting override is in effect, then set max power, else standard power logic
|
||||
if(prev_power != NRF_POWER_3) // prev_power is global variable for NRF24L01; NRF_POWER_3 is max power
|
||||
{
|
||||
uint8_t rf_setup = NRF24L01_ReadReg(NRF24L01_06_RF_SETUP);
|
||||
rf_setup = (rf_setup & 0xF9) | (NRF_POWER_3 << 1);
|
||||
NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, rf_setup);
|
||||
prev_power=NRF_POWER_3;
|
||||
}
|
||||
}
|
||||
else
|
||||
NRF24L01_SetPower();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
uint16_t CABELL_callback()
|
||||
{
|
||||
|
||||
if (IS_BIND_DONE_on) {
|
||||
CABELL_send_packet(0); // packet_period is set/adjusted in CABELL_send_packet
|
||||
return packet_period;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bind_counter == 0)
|
||||
{
|
||||
BIND_DONE;
|
||||
CABELL_init(); // non-bind address
|
||||
}
|
||||
else
|
||||
{
|
||||
CABELL_send_packet(1);
|
||||
bind_counter--;
|
||||
}
|
||||
return CABELL_PACKET_PERIOD;
|
||||
}
|
||||
if (IS_BIND_DONE_on)
|
||||
{
|
||||
CABELL_send_packet(0); // packet_period is set/adjusted in CABELL_send_packet
|
||||
return packet_period;
|
||||
}
|
||||
if (bind_counter == 0)
|
||||
{
|
||||
BIND_DONE;
|
||||
CABELL_init(); // non-bind address
|
||||
}
|
||||
else
|
||||
{
|
||||
CABELL_send_packet(1);
|
||||
bind_counter--;
|
||||
}
|
||||
return CABELL_PACKET_PERIOD;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
uint16_t initCABELL(void)
|
||||
{
|
||||
if (IS_BIND_DONE_on) {
|
||||
bind_counter = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
bind_counter = CABELL_BIND_COUNT;
|
||||
}
|
||||
CABELL_init();
|
||||
#if defined TELEMETRY
|
||||
init_frskyd_link_telemetry();
|
||||
telemetry_lost=1; // do not send telemetry to TX right away until we have a TX_RSSI value to prevent warning message...
|
||||
#endif
|
||||
if (IS_BIND_DONE_on)
|
||||
bind_counter = 0;
|
||||
else
|
||||
bind_counter = CABELL_BIND_COUNT;
|
||||
CABELL_init();
|
||||
#if defined CABELL_HUB_TELEMETRY
|
||||
init_frskyd_link_telemetry();
|
||||
telemetry_lost=1; // do not send telemetry to TX right away until we have a TX_RSSI value to prevent warning message...
|
||||
#endif
|
||||
|
||||
packet_period = CABELL_PACKET_PERIOD;
|
||||
packet_period = CABELL_PACKET_PERIOD;
|
||||
|
||||
return packet_period;
|
||||
return packet_period;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -78,6 +78,7 @@ uint8_t CYRF_Reset()
|
||||
*/
|
||||
void CYRF_GetMfgData(uint8_t data[])
|
||||
{
|
||||
#ifndef FORCE_CYRF_ID
|
||||
/* Fuses power on */
|
||||
CYRF_WriteRegister(CYRF_25_MFG_ID, 0xFF);
|
||||
|
||||
@@ -85,6 +86,9 @@ void CYRF_GetMfgData(uint8_t data[])
|
||||
|
||||
/* Fuses power off */
|
||||
CYRF_WriteRegister(CYRF_25_MFG_ID, 0x00);
|
||||
#else
|
||||
memcpy(data,FORCE_CYRF_ID,6);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
157
Multiprotocol/DM002_nrf24l01.ino
Normal file
157
Multiprotocol/DM002_nrf24l01.ino
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
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 DM002
|
||||
|
||||
#if defined(DM002_NRF24L01_INO)
|
||||
|
||||
#include "iface_nrf24l01.h"
|
||||
|
||||
#define DM002_PACKET_PERIOD 6100 // Timeout for callback in uSec
|
||||
#define DM002_INITIAL_WAIT 500
|
||||
#define DM002_PACKET_SIZE 12 // packets have 12-byte payload
|
||||
#define DM002_RF_BIND_CHANNEL 0x27
|
||||
#define DM002_BIND_COUNT 655 // 4 seconds
|
||||
|
||||
|
||||
enum DM002_FLAGS {
|
||||
// flags going to packet[9]
|
||||
DM002_FLAG_FLIP = 0x01,
|
||||
DM002_FLAG_LED = 0x02,
|
||||
DM002_FLAG_MEDIUM = 0x04,
|
||||
DM002_FLAG_HIGH = 0x08,
|
||||
DM002_FLAG_RTH = 0x10,
|
||||
DM002_FLAG_HEADLESS = 0x20,
|
||||
DM002_FLAG_CAMERA1 = 0x40,
|
||||
DM002_FLAG_CAMERA2 = 0x80,
|
||||
};
|
||||
|
||||
static void __attribute__((unused)) DM002_send_packet(uint8_t bind)
|
||||
{
|
||||
memcpy(packet+5,(uint8_t *)"\x00\x7F\x7F\x7F\x00\x00\x00",7);
|
||||
if(bind)
|
||||
{
|
||||
packet[0] = 0xAA;
|
||||
packet[1] = rx_tx_addr[0];
|
||||
packet[2] = rx_tx_addr[1];
|
||||
packet[3] = rx_tx_addr[2];
|
||||
packet[4] = rx_tx_addr[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
packet[0]=0x55;
|
||||
// Throttle : 0 .. 200
|
||||
packet[1]=convert_channel_8b_scale(THROTTLE,0,200);
|
||||
// Other channels min 0x57, mid 0x7F, max 0xA7
|
||||
packet[2] = convert_channel_8b_scale(RUDDER,0x57,0xA7);
|
||||
packet[3] = convert_channel_8b_scale(AILERON, 0x57,0xA7);
|
||||
packet[4] = convert_channel_8b_scale(ELEVATOR, 0xA7, 0x57);
|
||||
// Features
|
||||
packet[9] = GET_FLAG(Servo_AUX1,DM002_FLAG_FLIP)
|
||||
| GET_FLAG(!Servo_AUX2,DM002_FLAG_LED)
|
||||
| GET_FLAG(Servo_AUX3,DM002_FLAG_CAMERA1)
|
||||
| GET_FLAG(Servo_AUX4,DM002_FLAG_CAMERA2)
|
||||
| GET_FLAG(Servo_AUX5,DM002_FLAG_HEADLESS)
|
||||
| GET_FLAG(Servo_AUX6,DM002_FLAG_RTH)
|
||||
| GET_FLAG(!Servo_AUX7,DM002_FLAG_HIGH);
|
||||
// Packet counter
|
||||
if(packet_count&0x03)
|
||||
{
|
||||
packet_count++;
|
||||
hopping_frequency_no++;
|
||||
hopping_frequency_no&=4;
|
||||
}
|
||||
packet_count&=0x0F;
|
||||
packet[10] = packet_count;
|
||||
packet_count++;
|
||||
}
|
||||
//CRC
|
||||
for(uint8_t i=0;i<DM002_PACKET_SIZE-1;i++)
|
||||
packet[11]+=packet[i];
|
||||
|
||||
// Power on, TX mode, 2byte CRC
|
||||
// Why CRC0? xn297 does not interpret it - either 16-bit CRC or nothing
|
||||
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
|
||||
if (bind)
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, DM002_RF_BIND_CHANNEL);
|
||||
else
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
|
||||
// clear packet status bits and TX FIFO
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
||||
NRF24L01_FlushTx();
|
||||
XN297_WritePayload(packet, DM002_PACKET_SIZE);
|
||||
|
||||
NRF24L01_SetPower(); // Set tx_power
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) DM002_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
XN297_SetTXAddr((uint8_t *)"\x26\xA8\x67\x35\xCC", 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 Acknowldgement on all data pipes
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
|
||||
NRF24L01_SetPower();
|
||||
}
|
||||
|
||||
uint16_t DM002_callback()
|
||||
{
|
||||
if(IS_BIND_DONE_on)
|
||||
DM002_send_packet(0);
|
||||
else
|
||||
{
|
||||
if (bind_counter == 0)
|
||||
{
|
||||
BIND_DONE;
|
||||
XN297_SetTXAddr(rx_tx_addr, 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
DM002_send_packet(1);
|
||||
bind_counter--;
|
||||
}
|
||||
}
|
||||
return DM002_PACKET_PERIOD;
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) DM002_initialize_txid()
|
||||
{
|
||||
// Only 2 IDs/RFs are available, RX_NUM is used to switch between them
|
||||
if(rx_tx_addr[3]&1)
|
||||
{
|
||||
memcpy(hopping_frequency,(uint8_t *)"\x34\x39\x43\x48",4);
|
||||
memcpy(rx_tx_addr,(uint8_t *)"\x47\x93\x00\x00\xD5",5);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(hopping_frequency,(uint8_t *)"\x35\x39\x3B\x3D",4);
|
||||
memcpy(rx_tx_addr,(uint8_t *)"\xAC\xA1\x00\x00\xD5",5);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t initDM002(void)
|
||||
{
|
||||
BIND_IN_PROGRESS; // autobind protocol
|
||||
bind_counter = DM002_BIND_COUNT;
|
||||
DM002_initialize_txid();
|
||||
DM002_init();
|
||||
return DM002_INITIAL_WAIT;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -273,14 +273,10 @@ static void __attribute__((unused)) DSM_build_data_packet(uint8_t upper)
|
||||
uint16_t value = 0xffff;;
|
||||
if (idx != 0xff)
|
||||
{
|
||||
if (!IS_BIND_DONE_on)
|
||||
{ // Failsafe position during binding
|
||||
value=max/2; //all channels to middle
|
||||
if(idx==0)
|
||||
value=1; //except throttle
|
||||
}
|
||||
else
|
||||
value=map(Servo_data[CH_TAER[idx]],servo_min_125,servo_max_125,0,max);
|
||||
/* 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 end normal output */
|
||||
value=map(Servo_data[CH_TAER[idx]],servo_min_125,servo_max_125,0,max);
|
||||
value |= (upper && i==0 ? 0x8000 : 0) | (idx << bits);
|
||||
}
|
||||
packet[i*2+2] = (value >> 8) & 0xff;
|
||||
@@ -582,4 +578,4 @@ uint16_t initDsm()
|
||||
return 10000;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -133,7 +133,7 @@ static void __attribute__((unused)) flysky_build_packet(uint8_t init)
|
||||
{
|
||||
uint8_t i;
|
||||
//servodata timing range for flysky.
|
||||
////-100% =~ 0x03e8//=1000us(min)
|
||||
//-100% =~ 0x03e8//=1000us(min)
|
||||
//+100% =~ 0x07ca//=1994us(max)
|
||||
//Center = 0x5d9//=1497us(center)
|
||||
//channel order AIL;ELE;THR;RUD;AUX1;AUX2;AUX3;AUX4
|
||||
@@ -147,6 +147,8 @@ static void __attribute__((unused)) flysky_build_packet(uint8_t init)
|
||||
uint16_t temp=Servo_data[CH_AETR[i]];
|
||||
if(sub_protocol == CX20 && CH_AETR[i] == ELEVATOR)
|
||||
temp=servo_mid-temp; //reverse channel
|
||||
if(mode_select != MODE_SERIAL) //if in PPM mode extend the output to 1000...2000µs
|
||||
temp=map(temp,servo_min_100,servo_max_100,1000,2000);
|
||||
packet[5 + i*2]=temp&0xFF; //low byte of servo timing(1000-2000us)
|
||||
packet[6 + i*2]=(temp>>8)&0xFF; //high byte of servo timing(1000-2000us)
|
||||
}
|
||||
|
||||
@@ -21,8 +21,11 @@
|
||||
#include "iface_cc2500.h"
|
||||
|
||||
uint8_t chanskip;
|
||||
uint8_t seq_last_sent;
|
||||
uint8_t seq_last_rcvd;
|
||||
//uint8_t seq_last_sent;
|
||||
//uint8_t seq_last_rcvd;
|
||||
|
||||
uint8_t FrX_send_seq ;
|
||||
uint8_t FrX_receive_seq ;
|
||||
|
||||
static void __attribute__((unused)) set_start(uint8_t ch )
|
||||
{
|
||||
@@ -151,11 +154,7 @@ static void __attribute__((unused)) frskyX_data_frame()
|
||||
packet[9+i+2]=chan_1>>4;
|
||||
}
|
||||
|
||||
packet[21] = seq_last_sent << 4 | seq_last_rcvd;//8 at start
|
||||
if (seq_last_sent < 0x08 && seq_last_rcvd < 8)
|
||||
seq_last_sent = (seq_last_sent + 1) % 4;
|
||||
else if (seq_last_rcvd == 0x00)
|
||||
seq_last_sent = 1;
|
||||
packet[21] = (FrX_receive_seq << 4) | FrX_send_seq ;//8 at start
|
||||
|
||||
if(sub_protocol & 1 )// in X8 mode send only 8ch every 9ms
|
||||
lpass = 0 ;
|
||||
@@ -208,9 +207,9 @@ uint16_t ReadFrSkyX()
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
CC2500_WriteData(packet, packet[0]+1);
|
||||
//
|
||||
frskyX_data_frame();
|
||||
// frskyX_data_frame();
|
||||
state++;
|
||||
return 5500;
|
||||
return 5200;
|
||||
case FRSKY_DATA2:
|
||||
CC2500_SetTxRxMode(RX_EN);
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
@@ -219,7 +218,7 @@ uint16_t ReadFrSkyX()
|
||||
case FRSKY_DATA3:
|
||||
CC2500_Strobe(CC2500_SRX);
|
||||
state++;
|
||||
return 3000;
|
||||
return 3100;
|
||||
case FRSKY_DATA4:
|
||||
len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
|
||||
if (len && (len<=(0x0E + 3))) //Telemetry frame is 17
|
||||
@@ -238,8 +237,10 @@ uint16_t ReadFrSkyX()
|
||||
// restart sequence on missed packet - might need count or timeout instead of one missed
|
||||
if(packet_count>100)
|
||||
{//~1sec
|
||||
seq_last_sent = 0;
|
||||
seq_last_rcvd = 8;
|
||||
// seq_last_sent = 0;
|
||||
// seq_last_rcvd = 8;
|
||||
FrX_send_seq = 0x08 ;
|
||||
// FrX_receive_seq = 0 ;
|
||||
packet_count=0;
|
||||
#if defined TELEMETRY
|
||||
telemetry_lost=1;
|
||||
@@ -247,8 +248,13 @@ uint16_t ReadFrSkyX()
|
||||
}
|
||||
CC2500_Strobe(CC2500_SFRX); //flush the RXFIFO
|
||||
}
|
||||
frskyX_data_frame();
|
||||
if ( FrX_send_seq != 0x08 )
|
||||
{
|
||||
FrX_send_seq = ( FrX_send_seq + 1 ) & 0x03 ;
|
||||
}
|
||||
state = FRSKY_DATA1;
|
||||
return 300;
|
||||
return 500;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -277,8 +283,10 @@ uint16_t initFrSkyX()
|
||||
state = FRSKY_DATA1;
|
||||
initialize_data(0);
|
||||
}
|
||||
seq_last_sent = 0;
|
||||
seq_last_rcvd = 8;
|
||||
// seq_last_sent = 0;
|
||||
// seq_last_rcvd = 8;
|
||||
FrX_send_seq = 0x08 ;
|
||||
FrX_receive_seq = 0 ;
|
||||
return 10000;
|
||||
}
|
||||
#endif
|
||||
@@ -11,7 +11,7 @@
|
||||
11,SLT,SLT,VISTA
|
||||
12,CX10,GREEN,BLUE,DM007,---,J3015_1,J3015_2,MK33041
|
||||
13,CG023,CG023,YD829,H8_3D
|
||||
14,Bayang,Bayang,H8S3D
|
||||
14,Bayang,Bayang,H8S3D,X16_AH
|
||||
15,FrskyX,CH_16,CH_8,EU_16,EU_8
|
||||
16,ESky
|
||||
17,MT99xx,MT,H7,YZ,LS,FY805
|
||||
@@ -29,4 +29,6 @@
|
||||
29,Q2X2,Q222,Q242,Q282
|
||||
30,WK2x01,WK2801,WK2401,W6_5_1,W6_6_1,W6_HEL,W6_HEL_I
|
||||
31,Q303,Q303,CX35,CX10D,CX10WD
|
||||
32,GW008
|
||||
32,GW008
|
||||
33,DM002
|
||||
34,CABELL,CAB_V3,C_TELEM,-,-,-,-,F_SAFE,UNBIND
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#define VERSION_MAJOR 1
|
||||
#define VERSION_MINOR 1
|
||||
#define VERSION_REVISION 6
|
||||
#define VERSION_PATCH_LEVEL 20
|
||||
#define VERSION_PATCH_LEVEL 29
|
||||
//******************
|
||||
// Protocols
|
||||
//******************
|
||||
@@ -58,6 +58,7 @@ enum PROTOCOLS
|
||||
MODE_WK2x01 = 30, // =>CYRF6936
|
||||
MODE_Q303 = 31, // =>NRF24L01
|
||||
MODE_GW008 = 32, // =>NRF24L01
|
||||
MODE_DM002 = 33, // =>NRF24L01
|
||||
MODE_CABELL = 34, // =>NRF24L01
|
||||
};
|
||||
|
||||
@@ -136,7 +137,8 @@ enum CG023
|
||||
enum BAYANG
|
||||
{
|
||||
BAYANG = 0,
|
||||
H8S3D = 1
|
||||
H8S3D = 1,
|
||||
X16_AH = 2,
|
||||
};
|
||||
enum MT99XX
|
||||
{
|
||||
@@ -197,10 +199,10 @@ enum Q303
|
||||
};
|
||||
enum CABELL
|
||||
{
|
||||
CABELL_V3 = 0,
|
||||
CABELL_V3_TELEMETRY = 1,
|
||||
CABELL_SET_FAIL_SAFE = 6,
|
||||
CABELL_UNBIND = 7
|
||||
CABELL_V3 = 0,
|
||||
CABELL_V3_TELEMETRY = 1,
|
||||
CABELL_SET_FAIL_SAFE= 6,
|
||||
CABELL_UNBIND = 7,
|
||||
};
|
||||
|
||||
#define NONE 0
|
||||
@@ -400,7 +402,7 @@ enum CC2500_POWER
|
||||
CC2500_POWER_16 = 0xFE, // 0dbm
|
||||
CC2500_POWER_17 = 0xFF // +1dbm
|
||||
};
|
||||
#define CC2500_HIGH_POWER CC2500_POWER_16
|
||||
#define CC2500_HIGH_POWER CC2500_POWER_17
|
||||
#define CC2500_LOW_POWER CC2500_POWER_13
|
||||
#define CC2500_RANGE_POWER CC2500_POWER_1
|
||||
#define CC2500_BIND_POWER CC2500_POWER_1
|
||||
@@ -488,7 +490,8 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
||||
WK2x01 30
|
||||
Q303 31
|
||||
GW008 32
|
||||
CABELL 33
|
||||
DM002 33
|
||||
CABELL 34
|
||||
BindBit=> 0x80 1=Bind/0=No
|
||||
AutoBindBit=> 0x40 1=Yes /0=No
|
||||
RangeCheck=> 0x20 1=Yes /0=No
|
||||
@@ -544,6 +547,7 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
||||
sub_protocol==BAYANG
|
||||
BAYANG 0
|
||||
H8S3D 1
|
||||
X16_AH 2
|
||||
sub_protocol==MT99XX
|
||||
MT99 0
|
||||
H7 1
|
||||
@@ -591,10 +595,10 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
||||
CX10D 2
|
||||
CX10WD 3
|
||||
sub_protocol==CABELL
|
||||
CABELL_V3 0,
|
||||
CABELL_V3_TELEMETRY 1,
|
||||
CABELL_SET_FAIL_SAFE 6,
|
||||
CABELL_UNBIND 7
|
||||
CABELL_V3 0
|
||||
CABELL_V3_TELEMETRY 1
|
||||
CABELL_SET_FAIL_SAFE 6
|
||||
CABELL_UNBIND 7
|
||||
|
||||
Power value => 0x80 0=High/1=Low
|
||||
Stream[3] = option_protocol;
|
||||
@@ -690,4 +694,4 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
||||
data[0] = RSSI value
|
||||
data[1-28] telemetry data
|
||||
|
||||
*/
|
||||
*/
|
||||
@@ -22,13 +22,25 @@
|
||||
*/
|
||||
#include <avr/pgmspace.h>
|
||||
//#define DEBUG_TX
|
||||
#define USE_MY_CONFIG
|
||||
#ifdef ARDUINO_AVR_XMEGA32D4
|
||||
#include "MultiOrange.h"
|
||||
#endif
|
||||
#include "Multiprotocol.h"
|
||||
|
||||
//Multiprotocol module configuration file
|
||||
#include "_Config.h"
|
||||
// Let's automatically select the board
|
||||
// if arm is selected
|
||||
#ifdef __arm__
|
||||
#define STM32_BOARD // Let's automatically select this board if arm is selected since this is the only one for now...
|
||||
#define STM32_BOARD
|
||||
#endif
|
||||
|
||||
//Personal config file
|
||||
#if defined USE_MY_CONFIG
|
||||
#include "_MyConfig.h"
|
||||
#endif
|
||||
|
||||
#include "Pins.h"
|
||||
#include "TX_Def.h"
|
||||
#include "Validate.h"
|
||||
@@ -97,6 +109,18 @@ uint8_t RX_num;
|
||||
uint8_t calData[48];
|
||||
#endif
|
||||
|
||||
#ifdef CHECK_FOR_BOOTLOADER
|
||||
uint8_t BootTimer ;
|
||||
uint8_t BootState ;
|
||||
uint8_t NotBootChecking ;
|
||||
uint8_t BootCount ;
|
||||
|
||||
#define BOOT_WAIT_30_IDLE 0
|
||||
#define BOOT_WAIT_30_DATA 1
|
||||
#define BOOT_WAIT_20 2
|
||||
#define BOOT_READY 3
|
||||
#endif
|
||||
|
||||
//Channel mapping for protocols
|
||||
const uint8_t CH_AETR[]={AILERON, ELEVATOR, THROTTLE, RUDDER, AUX1, AUX2, AUX3, AUX4, AUX5, AUX6, AUX7, AUX8, AUX9, AUX10};
|
||||
const uint8_t CH_TAER[]={THROTTLE, AILERON, ELEVATOR, RUDDER, AUX1, AUX2, AUX3, AUX4, AUX5, AUX6, AUX7, AUX8};
|
||||
@@ -145,7 +169,7 @@ uint8_t pkt[MAX_PKT];//telemetry receiving packets
|
||||
uint8_t pktt[MAX_PKT];//telemetry receiving packets
|
||||
#ifdef BASH_SERIAL
|
||||
// For bit-bashed serial output
|
||||
#define TXBUFFER_SIZE 128
|
||||
#define TXBUFFER_SIZE 192
|
||||
volatile struct t_serial_bash
|
||||
{
|
||||
uint8_t head ;
|
||||
@@ -155,7 +179,7 @@ uint8_t pkt[MAX_PKT];//telemetry receiving packets
|
||||
uint8_t speed ;
|
||||
} SerialControl ;
|
||||
#else
|
||||
#define TXBUFFER_SIZE 64
|
||||
#define TXBUFFER_SIZE 96
|
||||
volatile uint8_t tx_buff[TXBUFFER_SIZE];
|
||||
volatile uint8_t tx_head=0;
|
||||
volatile uint8_t tx_tail=0;
|
||||
@@ -198,6 +222,7 @@ void setup()
|
||||
TCC1.CTRLA = 0x0B ; // Event3 (prescale of 16)
|
||||
#elif defined STM32_BOARD
|
||||
//STM32
|
||||
afio_cfg_debug_ports(AFIO_DEBUG_NONE);
|
||||
pinMode(A7105_CSN_pin,OUTPUT);
|
||||
pinMode(CC25_CSN_pin,OUTPUT);
|
||||
pinMode(NRF_CSN_pin,OUTPUT);
|
||||
@@ -382,7 +407,11 @@ void setup()
|
||||
protocol=0;
|
||||
servo_max_100=SERIAL_MAX_100; servo_min_100=SERIAL_MIN_100;
|
||||
servo_max_125=SERIAL_MAX_125; servo_min_125=SERIAL_MIN_125;
|
||||
Mprotocol_serial_init(); // Configure serial and enable RX interrupt
|
||||
#ifdef CHECK_FOR_BOOTLOADER
|
||||
Mprotocol_serial_init(1); // Configure serial and enable RX interrupt
|
||||
#else
|
||||
Mprotocol_serial_init(); // Configure serial and enable RX interrupt
|
||||
#endif
|
||||
#endif //ENABLE_SERIAL
|
||||
}
|
||||
servo_mid=servo_min_100+servo_max_100; //In fact 2* mid_value
|
||||
@@ -475,6 +504,11 @@ void loop()
|
||||
uint8_t Update_All()
|
||||
{
|
||||
#ifdef ENABLE_SERIAL
|
||||
#ifdef CHECK_FOR_BOOTLOADER
|
||||
if ( (mode_select==MODE_SERIAL) && (NotBootChecking == 0) )
|
||||
pollBoot() ;
|
||||
else
|
||||
#endif
|
||||
if(mode_select==MODE_SERIAL && IS_RX_FLAG_on) // Serial mode and something has been received
|
||||
{
|
||||
update_serial_data(); // Update protocol and data
|
||||
@@ -505,7 +539,7 @@ uint8_t Update_All()
|
||||
update_led_status();
|
||||
#if defined(TELEMETRY)
|
||||
#if ( !( defined(MULTI_TELEMETRY) || defined(MULTI_STATUS) ) )
|
||||
if((protocol==MODE_FRSKYD) || (protocol==MODE_BAYANG) || (protocol==MODE_HUBSAN) || (protocol==MODE_AFHDS2A) || (protocol==MODE_FRSKYX) || (protocol==MODE_DSM) || (protocol==MODE_CABELL) )
|
||||
if( (protocol==MODE_FRSKYD) || (protocol==MODE_BAYANG) || (protocol==MODE_HUBSAN) || (protocol==MODE_AFHDS2A) || (protocol==MODE_FRSKYX) || (protocol==MODE_DSM) || (protocol==MODE_CABELL) )
|
||||
#endif
|
||||
TelemetryUpdate();
|
||||
#endif
|
||||
@@ -948,6 +982,12 @@ static void protocol_init()
|
||||
remote_callback = GW008_callback;
|
||||
break;
|
||||
#endif
|
||||
#if defined(DM002_NRF24L01_INO)
|
||||
case MODE_DM002:
|
||||
next_callback=initDM002();
|
||||
remote_callback = DM002_callback;
|
||||
break;
|
||||
#endif
|
||||
#if defined(CABELL_NRF24L01_INO)
|
||||
case MODE_CABELL:
|
||||
next_callback=initCABELL();
|
||||
@@ -1083,7 +1123,11 @@ void modules_reset()
|
||||
prev_power=0xFD; // unused power value
|
||||
}
|
||||
|
||||
void Mprotocol_serial_init()
|
||||
#ifdef CHECK_FOR_BOOTLOADER
|
||||
void Mprotocol_serial_init( uint8_t boot )
|
||||
#else
|
||||
void Mprotocol_serial_init()
|
||||
#endif
|
||||
{
|
||||
#ifdef ORANGE_TX
|
||||
PORTC.OUTSET = 0x08 ;
|
||||
@@ -1093,18 +1137,41 @@ void Mprotocol_serial_init()
|
||||
USARTC0.BAUDCTRLB = 0 ;
|
||||
|
||||
USARTC0.CTRLB = 0x18 ;
|
||||
USARTC0.CTRLA = (USARTC0.CTRLA & 0xCF) | 0x10 ;
|
||||
USARTC0.CTRLA = (USARTC0.CTRLA & 0xCC) | 0x11 ;
|
||||
USARTC0.CTRLC = 0x2B ;
|
||||
UDR0 ;
|
||||
#ifdef INVERT_SERIAL
|
||||
PORTC.PIN3CTRL |= 0x40 ;
|
||||
#endif
|
||||
#ifdef CHECK_FOR_BOOTLOADER
|
||||
if ( boot )
|
||||
{
|
||||
USARTC0.BAUDCTRLB = 0 ;
|
||||
USARTC0.BAUDCTRLA = 33 ; // 57600
|
||||
USARTC0.CTRLA = (USARTC0.CTRLA & 0xC0) ;
|
||||
USARTC0.CTRLC = 0x03 ; // 8 bit, no parity, 1 stop
|
||||
USARTC0.CTRLB = 0x18 ; // Enable Tx and Rx
|
||||
PORTC.PIN3CTRL &= ~0x40 ;
|
||||
}
|
||||
#endif // CHECK_FOR_BOOTLOADER
|
||||
#elif defined STM32_BOARD
|
||||
usart2_begin(100000,SERIAL_8E2);
|
||||
#ifdef CHECK_FOR_BOOTLOADER
|
||||
if ( boot )
|
||||
{
|
||||
usart2_begin(57600,SERIAL_8N1);
|
||||
USART2_BASE->CR1 &= ~USART_CR1_RXNEIE ;
|
||||
(void)UDR0 ;
|
||||
}
|
||||
else
|
||||
#endif // CHECK_FOR_BOOTLOADER
|
||||
{
|
||||
usart2_begin(100000,SERIAL_8E2);
|
||||
USART2_BASE->CR1 |= USART_CR1_PCE_BIT;
|
||||
}
|
||||
usart3_begin(100000,SERIAL_8E2);
|
||||
USART2_BASE->CR1 |= USART_CR1_PCE_BIT;
|
||||
USART3_BASE->CR1 &= ~ USART_CR1_RE;//disable
|
||||
USART2_BASE->CR1 &= ~ USART_CR1_TE;//disable transmit
|
||||
|
||||
USART3_BASE->CR1 &= ~ USART_CR1_RE; //disable
|
||||
USART2_BASE->CR1 &= ~ USART_CR1_TE; //disable transmit
|
||||
#else
|
||||
//ATMEGA328p
|
||||
#include <util/setbaud.h>
|
||||
@@ -1113,7 +1180,7 @@ void Mprotocol_serial_init()
|
||||
UCSR0A = 0 ; // Clear X2 bit
|
||||
//Set frame format to 8 data bits, even parity, 2 stop bits
|
||||
UCSR0C = _BV(UPM01)|_BV(USBS0)|_BV(UCSZ01)|_BV(UCSZ00);
|
||||
while ( UCSR0A & (1 << RXC0) )//flush receive buffer
|
||||
while ( UCSR0A & (1 << RXC0) ) //flush receive buffer
|
||||
UDR0;
|
||||
//enable reception and RC complete interrupt
|
||||
UCSR0B = _BV(RXEN0)|_BV(RXCIE0);//rx enable and interrupt
|
||||
@@ -1122,9 +1189,130 @@ void Mprotocol_serial_init()
|
||||
initTXSerial( SPEED_100K ) ;
|
||||
#endif //TELEMETRY
|
||||
#endif //DEBUG_TX
|
||||
#ifdef CHECK_FOR_BOOTLOADER
|
||||
if ( boot )
|
||||
{
|
||||
UBRR0H = 0;
|
||||
UBRR0L = 33; // 57600
|
||||
UCSR0C &= ~_BV(UPM01); // No parity
|
||||
UCSR0B &= ~_BV(RXCIE0); // No rx interrupt
|
||||
UCSR0A |= _BV(U2X0); // Double speed mode USART0
|
||||
}
|
||||
#endif // CHECK_FOR_BOOTLOADER
|
||||
#endif //ORANGE_TX
|
||||
}
|
||||
|
||||
#ifdef CHECK_FOR_BOOTLOADER
|
||||
void pollBoot()
|
||||
{
|
||||
uint8_t rxchar ;
|
||||
uint8_t lState = BootState ;
|
||||
uint8_t millisTime = millis(); // Call this once only
|
||||
|
||||
#ifdef ORANGE_TX
|
||||
if ( USARTC0.STATUS & USART_RXCIF_bm )
|
||||
#elif defined STM32_BOARD
|
||||
if ( USART2_BASE->SR & USART_SR_RXNE )
|
||||
#else
|
||||
if ( UCSR0A & ( 1 << RXC0 ) )
|
||||
#endif
|
||||
{
|
||||
rxchar = UDR0 ;
|
||||
BootCount += 1 ;
|
||||
if ( ( lState == BOOT_WAIT_30_IDLE ) || ( lState == BOOT_WAIT_30_DATA ) )
|
||||
{
|
||||
if ( lState == BOOT_WAIT_30_IDLE ) // Waiting for 0x30
|
||||
BootTimer = millisTime ; // Start timeout
|
||||
if ( rxchar == 0x30 )
|
||||
lState = BOOT_WAIT_20 ;
|
||||
else
|
||||
lState = BOOT_WAIT_30_DATA ;
|
||||
}
|
||||
else
|
||||
if ( lState == BOOT_WAIT_20 && rxchar == 0x20 ) // Waiting for 0x20
|
||||
lState = BOOT_READY ;
|
||||
}
|
||||
else // No byte received
|
||||
{
|
||||
if ( lState != BOOT_WAIT_30_IDLE ) // Something received
|
||||
{
|
||||
uint8_t time = millisTime - BootTimer ;
|
||||
if ( time > 5 )
|
||||
{
|
||||
#ifdef STM32_BOARD
|
||||
if ( BootCount > 4 )
|
||||
#else
|
||||
if ( BootCount > 2 )
|
||||
#endif
|
||||
{ // Run normally
|
||||
NotBootChecking = 0xFF ;
|
||||
Mprotocol_serial_init( 0 ) ;
|
||||
}
|
||||
else if ( lState == BOOT_READY )
|
||||
{
|
||||
#ifdef STM32_BOARD
|
||||
#define SCS_BASE (0xE000E000) /*!< System Control Space Base Address */
|
||||
#define SCB_BASE (SCS_BASE + 0x0D00) /*!< System Control Block Base Address */
|
||||
#define SCB ((SCB_Type *) SCB_BASE) /*!< SCB configuration struct */
|
||||
#define __I volatile /*!< defines 'read only' permissions */
|
||||
#define __IO volatile /*!< defines 'read / write' permissions */
|
||||
typedef struct
|
||||
{
|
||||
__I uint32_t CPUID; /*!< Offset: 0x00 CPU ID Base Register */
|
||||
__IO uint32_t ICSR; /*!< Offset: 0x04 Interrupt Control State Register */
|
||||
__IO uint32_t VTOR; /*!< Offset: 0x08 Vector Table Offset Register */
|
||||
__IO uint32_t AIRCR; /*!< Offset: 0x0C Application Interrupt / Reset Control Register */
|
||||
__IO uint32_t SCR; /*!< Offset: 0x10 System Control Register */
|
||||
__IO uint32_t CCR; /*!< Offset: 0x14 Configuration Control Register */
|
||||
__IO uint8_t SHP[12]; /*!< Offset: 0x18 System Handlers Priority Registers (4-7, 8-11, 12-15) */
|
||||
__IO uint32_t SHCSR; /*!< Offset: 0x24 System Handler Control and State Register */
|
||||
__IO uint32_t CFSR; /*!< Offset: 0x28 Configurable Fault Status Register */
|
||||
__IO uint32_t HFSR; /*!< Offset: 0x2C Hard Fault Status Register */
|
||||
__IO uint32_t DFSR; /*!< Offset: 0x30 Debug Fault Status Register */
|
||||
__IO uint32_t MMFAR; /*!< Offset: 0x34 Mem Manage Address Register */
|
||||
__IO uint32_t BFAR; /*!< Offset: 0x38 Bus Fault Address Register */
|
||||
__IO uint32_t AFSR; /*!< Offset: 0x3C Auxiliary Fault Status Register */
|
||||
__I uint32_t PFR[2]; /*!< Offset: 0x40 Processor Feature Register */
|
||||
__I uint32_t DFR; /*!< Offset: 0x48 Debug Feature Register */
|
||||
__I uint32_t ADR; /*!< Offset: 0x4C Auxiliary Feature Register */
|
||||
__I uint32_t MMFR[4]; /*!< Offset: 0x50 Memory Model Feature Register */
|
||||
__I uint32_t ISAR[5]; /*!< Offset: 0x60 ISA Feature Register */
|
||||
} SCB_Type;
|
||||
#define SCB_AIRCR_VECTKEY_Pos 16 /*!< SCB AIRCR: VECTKEY Position */
|
||||
#define SCB_AIRCR_SYSRESETREQ_Pos 2 /*!< SCB AIRCR: SYSRESETREQ Position */
|
||||
#define SCB_AIRCR_PRIGROUP_Pos 8 /*!< SCB AIRCR: PRIGROUP Position */
|
||||
#define SCB_AIRCR_PRIGROUP_Msk (7ul << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */
|
||||
#define SCB_AIRCR_SYSRESETREQ_Msk (1ul << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */
|
||||
|
||||
// NVIC_SystemReset
|
||||
SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) |
|
||||
(SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
|
||||
SCB_AIRCR_SYSRESETREQ_Msk); /* Keep priority group unchanged */
|
||||
asm("dsb");
|
||||
while(1); /* wait until reset */
|
||||
#else
|
||||
cli(); // Disable global int due to RW of 16 bits registers
|
||||
void (*p)();
|
||||
#ifndef ORANGE_TX
|
||||
p = (void (*)())0x3F00 ; // Word address (0x7E00 byte)
|
||||
#else
|
||||
p = (void (*)())0x4000 ; // Word address (0x8000 byte)
|
||||
#endif
|
||||
(*p)() ; // go to boot
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
lState = BOOT_WAIT_30_IDLE ;
|
||||
BootCount = 0 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BootState = lState ;
|
||||
}
|
||||
#endif //CHECK_FOR_BOOTLOADER
|
||||
|
||||
#if defined(TELEMETRY)
|
||||
void PPM_Telemetry_serial_init()
|
||||
{
|
||||
@@ -1164,35 +1352,41 @@ static uint32_t random_value(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
static uint32_t random_id(uint16_t adress, uint8_t create_new)
|
||||
static uint32_t random_id(uint16_t address, uint8_t create_new)
|
||||
{
|
||||
uint32_t id=0;
|
||||
#ifndef FORCE_GLOBAL_ID
|
||||
uint32_t id=0;
|
||||
|
||||
if(eeprom_read_byte((EE_ADDR)(adress+10))==0xf0 && !create_new)
|
||||
{ // TXID exists in EEPROM
|
||||
for(uint8_t i=4;i>0;i--)
|
||||
if(eeprom_read_byte((EE_ADDR)(address+10))==0xf0 && !create_new)
|
||||
{ // TXID exists in EEPROM
|
||||
for(uint8_t i=4;i>0;i--)
|
||||
{
|
||||
id<<=8;
|
||||
id|=eeprom_read_byte((EE_ADDR)address+i-1);
|
||||
}
|
||||
if(id!=0x2AD141A7) //ID with seed=0
|
||||
return id;
|
||||
}
|
||||
// Generate a random ID
|
||||
#if defined STM32_BOARD
|
||||
#define STM32_UUID ((uint32_t *)0x1FFFF7E8)
|
||||
if (!create_new)
|
||||
id = STM32_UUID[0] ^ STM32_UUID[1] ^ STM32_UUID[2];
|
||||
#else
|
||||
id = random(0xfefefefe) + ((uint32_t)random(0xfefefefe) << 16);
|
||||
#endif
|
||||
for(uint8_t i=0;i<4;i++)
|
||||
{
|
||||
id<<=8;
|
||||
id|=eeprom_read_byte((EE_ADDR)adress+i-1);
|
||||
eeprom_write_byte((EE_ADDR)address+i,id);
|
||||
id>>=8;
|
||||
}
|
||||
if(id!=0x2AD141A7) //ID with seed=0
|
||||
return id;
|
||||
}
|
||||
// Generate a random ID
|
||||
#if defined STM32_BOARD
|
||||
#define STM32_UUID ((uint32_t *)0x1FFFF7E8)
|
||||
if (!create_new)
|
||||
id = STM32_UUID[0] ^ STM32_UUID[1] ^ STM32_UUID[2];
|
||||
eeprom_write_byte((EE_ADDR)(address+10),0xf0);//write bind flag in eeprom.
|
||||
return id;
|
||||
#else
|
||||
id = random(0xfefefefe) + ((uint32_t)random(0xfefefefe) << 16);
|
||||
(void)address;
|
||||
(void)create_new;
|
||||
return FORCE_GLOBAL_ID;
|
||||
#endif
|
||||
for(uint8_t i=0;i<4;i++)
|
||||
{
|
||||
eeprom_write_byte((EE_ADDR)adress+i,id);
|
||||
id>>=8;
|
||||
}
|
||||
eeprom_write_byte((EE_ADDR)(adress+10),0xf0);//write bind flag in eeprom.
|
||||
return id;
|
||||
}
|
||||
|
||||
/**************************/
|
||||
@@ -1369,4 +1563,4 @@ static uint32_t random_id(uint16_t adress, uint8_t create_new)
|
||||
WDTCSR = 0; // Disable Watchdog interrupt
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -27,6 +27,7 @@ uint8_t rf_setup;
|
||||
void NRF24L01_Initialize()
|
||||
{
|
||||
rf_setup = 0x09;
|
||||
prev_power = 0x00; // Make sure prev_power is inline with current power
|
||||
XN297_SetScrambledMode(XN297_SCRAMBLED);
|
||||
}
|
||||
|
||||
@@ -133,8 +134,8 @@ void NRF24L01_SetBitrate(uint8_t bitrate)
|
||||
|
||||
// Bit 0 goes to RF_DR_HIGH, bit 1 - to RF_DR_LOW
|
||||
rf_setup = (rf_setup & 0xD7) | ((bitrate & 0x02) << 4) | ((bitrate & 0x01) << 3);
|
||||
NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, rf_setup);
|
||||
prev_power = NRF_POWER_0; // Power setting was just reset. This will get updated in the next call to SetPower
|
||||
prev_power=(rf_setup>>1)&0x03; // Make sure prev_power is inline with current power
|
||||
NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, rf_setup);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -168,9 +169,9 @@ void NRF24L01_SetPower()
|
||||
#endif
|
||||
if(IS_RANGE_FLAG_on)
|
||||
power=NRF_POWER_0;
|
||||
rf_setup = (rf_setup & 0xF9) | (power << 1);
|
||||
if(prev_power != power)
|
||||
{
|
||||
rf_setup = (rf_setup & 0xF9) | (power << 1);
|
||||
NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, rf_setup);
|
||||
prev_power=power;
|
||||
}
|
||||
@@ -682,4 +683,4 @@ void LT8900_WritePayload(uint8_t* msg, uint8_t len)
|
||||
NRF24L01_WritePayload(LT8900_buffer+LT8900_buffer_start,pos_final+pos-LT8900_buffer_start);
|
||||
}
|
||||
// End of LT8900 emulation
|
||||
#endif
|
||||
#endif
|
||||
@@ -23,14 +23,14 @@
|
||||
#define SFHSS_PACKET_LEN 13
|
||||
#define SFHSS_TX_ID_LEN 2
|
||||
|
||||
uint8_t fhss_code; // 0-27
|
||||
uint8_t fhss_code=0; // 0-27
|
||||
|
||||
enum {
|
||||
SFHSS_START = 0x00,
|
||||
SFHSS_CAL = 0x01,
|
||||
SFHSS_DATA1 = 0x02, // do not change this value
|
||||
SFHSS_DATA2 = 0x0B, // do not change this value
|
||||
SFHSS_TUNE = 0x0F
|
||||
SFHSS_DATA1 = 0x02,
|
||||
SFHSS_DATA2 = 0x03,
|
||||
SFHSS_TUNE = 0x04
|
||||
};
|
||||
|
||||
#define SFHSS_FREQ0_VAL 0xC4
|
||||
@@ -122,58 +122,78 @@ static void __attribute__((unused)) SFHSS_calc_next_chan()
|
||||
}
|
||||
}
|
||||
|
||||
/*// Channel values are 10-bit values between 86 and 906, 496 is the middle.
|
||||
// Values grow down and to the right.
|
||||
static void __attribute__((unused)) SFHSS_build_data_packet()
|
||||
{
|
||||
#define spacer1 0x02
|
||||
#define spacer2 (spacer1 << 4)
|
||||
uint8_t ch_offset = phase == SFHSS_DATA1 ? 0 : 4;
|
||||
uint16_t ch1 = convert_channel_16b_nolim(CH_AETR[ch_offset+0],86,906);
|
||||
uint16_t ch2 = convert_channel_16b_nolim(CH_AETR[ch_offset+1],86,906);
|
||||
uint16_t ch3 = convert_channel_16b_nolim(CH_AETR[ch_offset+2],86,906);
|
||||
uint16_t ch4 = convert_channel_16b_nolim(CH_AETR[ch_offset+3],86,906);
|
||||
|
||||
packet[0] = 0x81; // can be 80 or 81 for Orange, only 81 for XK
|
||||
packet[1] = rx_tx_addr[0];
|
||||
packet[2] = rx_tx_addr[1];
|
||||
packet[3] = 0;
|
||||
packet[4] = 0;
|
||||
packet[5] = (rf_ch_num << 3) | spacer1 | ((ch1 >> 9) & 0x01);
|
||||
packet[6] = (ch1 >> 1);
|
||||
packet[7] = (ch1 << 7) | spacer2 | ((ch2 >> 5) & 0x1F);
|
||||
packet[8] = (ch2 << 3) | spacer1 | ((ch3 >> 9) & 0x01);
|
||||
packet[9] = (ch3 >> 1);
|
||||
packet[10] = (ch3 << 7) | spacer2 | ((ch4 >> 5) & 0x1F);
|
||||
packet[11] = (ch4 << 3) | ((fhss_code >> 2) & 0x07);
|
||||
packet[12] = (fhss_code << 6) | phase;
|
||||
}
|
||||
*/
|
||||
|
||||
// Channel values are 12-bit values between 1020 and 2020, 1520 is the middle.
|
||||
// Futaba @140% is 2070...1520...970
|
||||
// Values grow down and to the right.
|
||||
static void __attribute__((unused)) SFHSS_build_data_packet()
|
||||
{
|
||||
uint8_t ch_offset = phase == SFHSS_DATA1 ? 0 : 4;
|
||||
uint16_t ch1 = convert_channel_16b_nolim(CH_AETR[ch_offset+0],2020,1020);
|
||||
uint16_t ch2 = convert_channel_16b_nolim(CH_AETR[ch_offset+1],2020,1020);
|
||||
uint16_t ch3 = convert_channel_16b_nolim(CH_AETR[ch_offset+2],2020,1020);
|
||||
uint16_t ch4 = convert_channel_16b_nolim(CH_AETR[ch_offset+3],2020,1020);
|
||||
uint16_t ch1,ch2,ch3,ch4;
|
||||
// command.bit0 is the packet number indicator: =0 -> SFHSS_DATA1, =1 -> SFHSS_DATA2
|
||||
// command.bit1 is unknown but seems to be linked to the payload[0].bit0 but more dumps are needed: payload[0]=0x82 -> =0, payload[0]=0x81 -> =1
|
||||
// command.bit2 is the failsafe transmission indicator: =0 -> normal data, =1->failsafe data
|
||||
// command.bit3 is the channels indicator: =0 -> CH1-4, =1 -> CH5-8
|
||||
|
||||
//Coding below matches the Futaba T8J transmission scheme DATA1->CH1-4, DATA2->CH5-8, DATA1->CH5-8, DATA2->CH1-4,...
|
||||
// XK, T10J and TM-FH are different with a classic DATA1->CH1-4, DATA2->CH5-8,...
|
||||
//Failsafe is sent twice every couple of seconds (unknown but >5s)
|
||||
|
||||
uint8_t command= (phase == SFHSS_DATA1) ? 0 : 1; // Building packet for Data1 or Data2
|
||||
counter+=command;
|
||||
if( (counter&0x3FC) == 0x3FC )
|
||||
{ // Transmit failsafe data twice every 7s
|
||||
if( ((counter&1)^(command&1)) == 0 )
|
||||
command|=0x04; // Failsafe
|
||||
}
|
||||
else
|
||||
command|=0x02; // Assuming packet[0] == 0x81
|
||||
counter&=0x3FF; // Reset failsafe counter
|
||||
if(counter&1) command|=0x08; // Transmit lower and upper channels twice in a row
|
||||
|
||||
packet[0] = 0x81; // can be 80 or 81 for Orange, only 81 for XK
|
||||
uint8_t ch_offset = ((command&0x08) >> 1) | ((command&0x04) << 1); // CH1..CH4 or CH5..CH8, if failsafe CH9..CH12 or CH13..CH16
|
||||
ch1 = convert_channel_16b_nolim(CH_AETR[ch_offset+0],2020,1020);
|
||||
ch2 = convert_channel_16b_nolim(CH_AETR[ch_offset+1],2020,1020);
|
||||
ch3 = convert_channel_16b_nolim(CH_AETR[ch_offset+2],2020,1020);
|
||||
ch4 = convert_channel_16b_nolim(CH_AETR[ch_offset+3],2020,1020);
|
||||
|
||||
if(command&0x04)
|
||||
{ //Failsafe data are:
|
||||
// 0 to 1023 -> no output on channel
|
||||
// 1024-2047 -> hold output on channel
|
||||
// 2048-4095 -> channel_output=(data&0x3FF)*5/4+880 in µs
|
||||
// Notes:
|
||||
// 2048-2559 -> does not look valid since it only covers the range from 1520µs to 2160µs
|
||||
// 2560-3583 -> valid for any channel values from 880µs to 2160µs
|
||||
// 3584-4095 -> looks to be used for the throttle channel with values ranging from 880µs to 1520µs
|
||||
#ifdef SFHSS_FAILSAFE_CH9_16
|
||||
ch1=((5360-ch1)<<2)/5; //((1520*2-ch1)<<2)/5+1856;
|
||||
ch2=((5360-ch2)<<2)/5;
|
||||
ch3=((5360-ch3)<<2)/5;
|
||||
if((command&0x08)==0 && ch3<3072) // Throttle
|
||||
ch3+=1024;
|
||||
ch4=((5360-ch4)<<2)/5;
|
||||
#else
|
||||
ch1=1024;ch2=1024;ch4=1024; // All channels hold their positions
|
||||
ch3=((command&0x08)==0)?3664:1024; // except throttle value set to 980µs
|
||||
#endif
|
||||
}
|
||||
|
||||
// XK [0]=0x81 [3]=0x00 [4]=0x00
|
||||
// T8J [0]=0x81 [3]=0x42 [4]=0x07
|
||||
// T10J [0]=0x81 [3]=0x0F [4]=0x09
|
||||
// TM-FH [0]=0x82 [3]=0x9A [4]=0x06
|
||||
packet[0] = 0x81; // can be 80 or 81 for Orange, only 81 for XK
|
||||
packet[1] = rx_tx_addr[0];
|
||||
packet[2] = rx_tx_addr[1];
|
||||
packet[3] = 0x0f; //10J
|
||||
packet[4] = 0x09; //10J
|
||||
packet[3] = rx_tx_addr[2]; // ID?
|
||||
packet[4] = rx_tx_addr[3]; // ID?
|
||||
packet[5] = (rf_ch_num << 3) | ((ch1 >> 9) & 0x07);
|
||||
packet[6] = (ch1 >> 1);
|
||||
packet[7] = (ch1 << 7) | ((ch2 >> 5) & 0x7F );
|
||||
packet[8] = (ch2 << 3) | ((ch3 >> 9) & 0x07);
|
||||
packet[8] = (ch2 << 3) | ((ch3 >> 9) & 0x07 );
|
||||
packet[9] = (ch3 >> 1);
|
||||
packet[10] = (ch3 << 7) | ((ch4 >> 5) & 0x7F );
|
||||
packet[11] = (ch4 << 3) | ((fhss_code >> 2) & 0x07 );
|
||||
packet[12] = (fhss_code << 6) | phase;
|
||||
packet[12] = (fhss_code << 6) | command;
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) SFHSS_send_packet()
|
||||
@@ -197,28 +217,31 @@ uint16_t ReadSFHSS()
|
||||
else
|
||||
{
|
||||
rf_ch_num = 0;
|
||||
counter = 0;
|
||||
phase = SFHSS_DATA1;
|
||||
}
|
||||
return 2000;
|
||||
|
||||
/* Work cycle, 6.8ms, second packet 1.65ms after first */
|
||||
/* Work cycle: 6.8ms */
|
||||
#define SFHSS_PACKET_PERIOD 6800
|
||||
#define SFHSS_DATA2_TIMING 1630 // Adjust this value between 1600 and 1650 if your RX(s) are not operating properly
|
||||
case SFHSS_DATA1:
|
||||
SFHSS_build_data_packet();
|
||||
SFHSS_send_packet();
|
||||
phase = SFHSS_DATA2;
|
||||
return 1650;
|
||||
return SFHSS_DATA2_TIMING; // original 1650
|
||||
case SFHSS_DATA2:
|
||||
SFHSS_build_data_packet();
|
||||
SFHSS_send_packet();
|
||||
SFHSS_calc_next_chan();
|
||||
phase = SFHSS_TUNE;
|
||||
return 2000;
|
||||
return (SFHSS_PACKET_PERIOD -2000 -SFHSS_DATA2_TIMING); // original 2000
|
||||
case SFHSS_TUNE:
|
||||
phase = SFHSS_DATA1;
|
||||
SFHSS_tune_freq();
|
||||
SFHSS_tune_chan_fast();
|
||||
CC2500_SetPower();
|
||||
return 3150;
|
||||
return 2000; // original 3150
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -226,13 +249,13 @@ uint16_t ReadSFHSS()
|
||||
// Generate internal id
|
||||
static void __attribute__((unused)) SFHSS_get_tx_id()
|
||||
{
|
||||
uint32_t fixed_id;
|
||||
// Some receivers (Orange) behaves better if they tuned to id that has
|
||||
// no more than 6 consecutive zeros and ones
|
||||
uint32_t fixed_id;
|
||||
uint8_t run_count = 0;
|
||||
// add guard for bit count
|
||||
fixed_id = 1 ^ (MProtocol_id & 1);
|
||||
for (uint8_t i = 0; i < 16; ++i)
|
||||
for (uint8_t i = 0; i < 32; ++i)
|
||||
{
|
||||
fixed_id = (fixed_id << 1) | (MProtocol_id & 1);
|
||||
MProtocol_id >>= 1;
|
||||
@@ -249,8 +272,10 @@ static void __attribute__((unused)) SFHSS_get_tx_id()
|
||||
run_count = 0;
|
||||
}
|
||||
// fixed_id = 0xBC11;
|
||||
rx_tx_addr[0] = fixed_id >> 8;
|
||||
rx_tx_addr[1] = fixed_id;
|
||||
rx_tx_addr[0] = fixed_id >> 24;
|
||||
rx_tx_addr[1] = fixed_id >> 16;
|
||||
rx_tx_addr[2] = fixed_id >> 8;
|
||||
rx_tx_addr[3] = fixed_id >> 0;
|
||||
}
|
||||
|
||||
uint16_t initSFHSS()
|
||||
@@ -258,7 +283,7 @@ uint16_t initSFHSS()
|
||||
BIND_DONE; // Not a TX bind protocol
|
||||
SFHSS_get_tx_id();
|
||||
|
||||
fhss_code=rx_tx_addr[2]%28; // Initialize it to random 0-27 inclusive
|
||||
fhss_code=random(0xfefefefe)%28; // Initialize it to random 0-27 inclusive
|
||||
|
||||
SFHSS_rf_init();
|
||||
phase = SFHSS_START;
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// compatible with Syma X5C-1, X11, X11C, X12 and for sub protocol X5C Syma X5C (original), X2
|
||||
// Last sync with hexfet new_protocols/cx10_nrf24l01.c dated 2015-09-28
|
||||
|
||||
#if defined(SYMAX_NRF24L01_INO)
|
||||
|
||||
@@ -30,6 +29,7 @@
|
||||
#define SYMAX_FLAG_VIDEO 0x02
|
||||
#define SYMAX_FLAG_PICTURE 0x04
|
||||
#define SYMAX_FLAG_HEADLESS 0x08
|
||||
#define SYMAX_XTRM_RATES 0x10
|
||||
|
||||
#define SYMAX_PAYLOADSIZE 10 // receive data pipes set to this size, but unused
|
||||
#define SYMAX_MAX_PACKET_LENGTH 16 // X11,X12,X5C-1 10-byte, X5C 16-byte
|
||||
@@ -58,6 +58,7 @@ static void __attribute__((unused)) SYMAX_read_controls()
|
||||
{
|
||||
// Protocol is registered AETRF, that is
|
||||
// Aileron is channel 1, Elevator - 2, Throttle - 3, Rudder - 4, Flip control - 5
|
||||
// Extended (trim-added) Rates - 6, Photo - 7, Video - 8, Headless - 9
|
||||
aileron = convert_channel_s8b(AILERON);
|
||||
elevator = convert_channel_s8b(ELEVATOR);
|
||||
throttle = convert_channel_8b(THROTTLE);
|
||||
@@ -67,6 +68,9 @@ static void __attribute__((unused)) SYMAX_read_controls()
|
||||
// Channel 5
|
||||
if (Servo_AUX1)
|
||||
flags = SYMAX_FLAG_FLIP;
|
||||
// Channel 6
|
||||
if (Servo_AUX2)
|
||||
flags |= SYMAX_XTRM_RATES;
|
||||
// Channel 7
|
||||
if (Servo_AUX3)
|
||||
flags |= SYMAX_FLAG_PICTURE;
|
||||
@@ -75,7 +79,10 @@ static void __attribute__((unused)) SYMAX_read_controls()
|
||||
flags |= SYMAX_FLAG_VIDEO;
|
||||
// Channel 9
|
||||
if (Servo_AUX5)
|
||||
{
|
||||
flags |= SYMAX_FLAG_HEADLESS;
|
||||
flags &= ~SYMAX_XTRM_RATES; // Extended rates & headless incompatible
|
||||
}
|
||||
}
|
||||
|
||||
#define X5C_CHAN2TRIM(X) ((((X) & 0x80 ? 0xff - (X) : 0x80 + (X)) >> 2) + 0x20)
|
||||
@@ -98,9 +105,18 @@ static void __attribute__((unused)) SYMAX_build_packet_x5c(uint8_t bind)
|
||||
packet[1] = rudder;
|
||||
packet[2] = elevator ^ 0x80; // reversed from default
|
||||
packet[3] = aileron;
|
||||
packet[4] = X5C_CHAN2TRIM(rudder ^ 0x80);// drive trims for extra control range
|
||||
packet[5] = X5C_CHAN2TRIM(elevator);
|
||||
packet[6] = X5C_CHAN2TRIM(aileron ^ 0x80);
|
||||
if (flags & SYMAX_XTRM_RATES)
|
||||
{ // drive trims for extra control range
|
||||
packet[4] = X5C_CHAN2TRIM(rudder ^ 0x80);
|
||||
packet[5] = X5C_CHAN2TRIM(elevator);
|
||||
packet[6] = X5C_CHAN2TRIM(aileron ^ 0x80);
|
||||
}
|
||||
else
|
||||
{
|
||||
packet[4] = 0x00;
|
||||
packet[5] = 0x00;
|
||||
packet[6] = 0x00;
|
||||
}
|
||||
packet[7] = 0xae;
|
||||
packet[8] = 0xa9;
|
||||
packet[9] = 0x00;
|
||||
@@ -138,9 +154,15 @@ static void __attribute__((unused)) SYMAX_build_packet(uint8_t bind)
|
||||
packet[2] = rudder;
|
||||
packet[3] = aileron;
|
||||
packet[4] = (flags & SYMAX_FLAG_VIDEO ? 0x80 : 0x00) | (flags & SYMAX_FLAG_PICTURE ? 0x40 : 0x00);
|
||||
packet[5] = (elevator >> 2) | 0xc0; //always high rates (bit 7 is rate control)
|
||||
packet[6] = (rudder >> 2) | (flags & SYMAX_FLAG_FLIP ? 0x40 : 0x00);
|
||||
packet[7] = (aileron >> 2) | (flags & SYMAX_FLAG_HEADLESS ? 0x80 : 0x00);
|
||||
packet[5] = 0xc0; //always high rates (bit 7 is rate control)
|
||||
packet[6] = flags & SYMAX_FLAG_FLIP ? 0x40 : 0x00;
|
||||
packet[7] = flags & SYMAX_FLAG_HEADLESS ? 0x80 : 0x00;
|
||||
if (flags & SYMAX_XTRM_RATES)
|
||||
{ // use trims to extend controls
|
||||
packet[5] |= elevator >> 2;
|
||||
packet[6] |= rudder >> 2;
|
||||
packet[7] |= aileron >> 2;
|
||||
}
|
||||
packet[8] = 0x00;
|
||||
}
|
||||
packet[9] = SYMAX_checksum(packet);
|
||||
|
||||
@@ -31,6 +31,34 @@ uint8_t RetrySequence ;
|
||||
uint8_t sport_counter=0;
|
||||
uint8_t RxBt = 0;
|
||||
uint8_t sport = 0;
|
||||
#define MAX_PKTX 10
|
||||
#define FX_BUFFERS 4
|
||||
uint8_t pktx[MAX_PKTX];
|
||||
uint8_t pktx1[FRSKY_SPORT_PACKET_SIZE*FX_BUFFERS];
|
||||
uint8_t indx;
|
||||
//struct t_fx_rx_packet
|
||||
//{
|
||||
// uint8_t validSequence ;
|
||||
// uint8_t count ;
|
||||
// uint8_t payload[6] ;
|
||||
//} ;
|
||||
|
||||
// Store for out of sequence packet
|
||||
//struct t_fx_rx_packet FrskyxRxTelemetry ;
|
||||
|
||||
uint8_t FrskyxRxTelemetryValidSequence ;
|
||||
|
||||
struct t_fx_rx_frame
|
||||
{
|
||||
uint8_t valid ;
|
||||
uint8_t count ;
|
||||
uint8_t payload[6] ;
|
||||
} ;
|
||||
|
||||
// Store for FrskyX telemetry
|
||||
struct t_fx_rx_frame FrskyxRxFrames[4] ;
|
||||
uint8_t NextFxFrameToForward ;
|
||||
|
||||
#endif
|
||||
#if defined HUB_TELEMETRY
|
||||
#define USER_MAX_BYTES 6
|
||||
@@ -40,10 +68,6 @@ uint8_t RetrySequence ;
|
||||
#define START_STOP 0x7e
|
||||
#define BYTESTUFF 0x7d
|
||||
#define STUFF_MASK 0x20
|
||||
#define MAX_PKTX 10
|
||||
uint8_t pktx[MAX_PKTX];
|
||||
uint8_t pktx1[MAX_PKTX];
|
||||
uint8_t indx;
|
||||
uint8_t frame[18];
|
||||
|
||||
#if ( defined(MULTI_TELEMETRY) || defined(MULTI_STATUS) )
|
||||
@@ -155,7 +179,8 @@ void frskySendStuffed()
|
||||
|
||||
void frsky_check_telemetry(uint8_t *pkt,uint8_t len)
|
||||
{
|
||||
if(pkt[1] == rx_tx_addr[3] && pkt[2] == rx_tx_addr[2] && len ==(pkt[0] + 3))
|
||||
uint8_t clen = pkt[0] + 3 ;
|
||||
if(pkt[1] == rx_tx_addr[3] && pkt[2] == rx_tx_addr[2] && len == clen )
|
||||
{
|
||||
telemetry_link|=1; // Telemetry data is available
|
||||
/*previous version
|
||||
@@ -205,19 +230,144 @@ void frsky_check_telemetry(uint8_t *pkt,uint8_t len)
|
||||
telemetry_lost=0;
|
||||
if (protocol==MODE_FRSKYX)
|
||||
{
|
||||
if ((pktt[5] >> 4 & 0x0f) == 0x08)
|
||||
{
|
||||
seq_last_sent = 8;
|
||||
seq_last_rcvd = 0;
|
||||
pass=0;
|
||||
}
|
||||
else
|
||||
uint16_t lcrc = crc_x(&pkt[3], len-7 ) ;
|
||||
// if ( ( sub_protocol & 2 ) == 0 )
|
||||
// {
|
||||
// if ( ( (lcrc >> 8) == pkt[len-4]) && ( (lcrc & 0x00FF ) == pkt[len-3]) )
|
||||
// {
|
||||
// lcrc = 0 ;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// lcrc = 1 ;
|
||||
// }
|
||||
// }
|
||||
// if ( lcrc == 0 )
|
||||
|
||||
if ( ( (lcrc >> 8) == pkt[len-4]) && ( (lcrc & 0x00FF ) == pkt[len-3]) )
|
||||
{
|
||||
if ((pktt[5] >> 4 & 0x03) == (seq_last_rcvd + 1) % 4)
|
||||
seq_last_rcvd = (seq_last_rcvd + 1) % 4;
|
||||
// Check if in sequence
|
||||
if ( (pkt[5] & 0x0F) == 0x08 )
|
||||
{
|
||||
FrX_receive_seq = 0x08 ;
|
||||
NextFxFrameToForward = 0 ;
|
||||
FrskyxRxFrames[0].valid = 0 ;
|
||||
FrskyxRxFrames[1].valid = 0 ;
|
||||
FrskyxRxFrames[2].valid = 0 ;
|
||||
FrskyxRxFrames[3].valid = 0 ;
|
||||
}
|
||||
else if ( (pkt[5] & 0x03) == (FrX_receive_seq & 0x03 ) )
|
||||
{
|
||||
// OK to process
|
||||
struct t_fx_rx_frame *p ;
|
||||
uint8_t count ;
|
||||
p = &FrskyxRxFrames[FrX_receive_seq & 3] ;
|
||||
count = pkt[6] ;
|
||||
if ( count <= 6 )
|
||||
{
|
||||
p->count = count ;
|
||||
for ( uint8_t i = 0 ; i < count ; i += 1 )
|
||||
{
|
||||
p->payload[i] = pkt[i+7] ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
p->count = 0 ;
|
||||
}
|
||||
p->valid = 1 ;
|
||||
|
||||
|
||||
|
||||
FrX_receive_seq = ( FrX_receive_seq + 1 ) & 0x03 ;
|
||||
|
||||
if ( FrskyxRxTelemetryValidSequence & 0x80 )
|
||||
{
|
||||
FrX_receive_seq = ( FrskyxRxTelemetryValidSequence + 1 ) & 3 ;
|
||||
FrskyxRxTelemetryValidSequence &= 0x7F ;
|
||||
}
|
||||
|
||||
// if ( FrskyxRxTelemetry.validSequence & 0x80 )
|
||||
// {
|
||||
// FrX_receive_seq = ( FrskyxRxTelemetry.validSequence + 1 ) & 3 ;
|
||||
|
||||
// FrskyxRxTelemetry.validSequence &= 0x7F ;
|
||||
|
||||
// }
|
||||
}
|
||||
else
|
||||
pass=0;//reset if sequence wrong
|
||||
{
|
||||
// Save and request correct packet
|
||||
// struct t_fx_rx_packet *p ;
|
||||
struct t_fx_rx_frame *q ;
|
||||
uint8_t count ;
|
||||
// pkt[4] RSSI
|
||||
// pkt[5] sequence control
|
||||
// pkt[6] payload count
|
||||
// pkt[7-12] payload
|
||||
pktt[6] = 0 ; // Don't process
|
||||
if ( (pkt[5] & 0x03) == ( ( FrX_receive_seq +1 ) & 3 ) )
|
||||
{
|
||||
q = &FrskyxRxFrames[(pkt[5] & 0x03)] ;
|
||||
count = pkt[6] ;
|
||||
if ( count <= 6 )
|
||||
{
|
||||
q->count = count ;
|
||||
for ( uint8_t i = 0 ; i < count ; i += 1 )
|
||||
{
|
||||
q->payload[i] = pkt[i+7] ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
q->count = 0 ;
|
||||
}
|
||||
q->valid = 1 ;
|
||||
|
||||
FrskyxRxTelemetryValidSequence = 0x80 | ( pkt[5] & 0x03 ) ;
|
||||
}
|
||||
|
||||
|
||||
// p = &FrskyxRxTelemetry ;
|
||||
// count = pkt[6] ;
|
||||
// if ( count <= 6 )
|
||||
// {
|
||||
// p->count = count ;
|
||||
// for ( uint8_t i = 0 ; i < count ; i += 1 )
|
||||
// {
|
||||
// p->payload[i] = pkt[i+7] ;
|
||||
// }
|
||||
// p->validSequence = 0x80 | ( pkt[5] & 0x03 ) ;
|
||||
// }
|
||||
FrX_receive_seq = ( FrX_receive_seq & 0x03 ) | 0x04 ; // Request re-transmission
|
||||
}
|
||||
|
||||
if (((pktt[5] >> 4) & 0x0f) == 0x08)
|
||||
{
|
||||
FrX_send_seq = 0 ;
|
||||
// FrX_receive_seq = 0x08 ;
|
||||
}
|
||||
}
|
||||
|
||||
// packet[21] = (FrX_receive_seq << 4) | FrX_send_seq ;//8 at start
|
||||
// if ( FrX_send_seq != 0x08 )
|
||||
// {
|
||||
// FrX_send_seq = ( FrX_send_seq + 1 ) & 0x03 ;
|
||||
// }
|
||||
|
||||
// if ((pktt[5] >> 4 & 0x0f) == 0x08)
|
||||
// {
|
||||
// seq_last_sent = 8;
|
||||
// seq_last_rcvd = 0;
|
||||
// pass=0;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if ((pktt[5] >> 4 & 0x03) == (seq_last_rcvd + 1) % 4)
|
||||
// seq_last_rcvd = (seq_last_rcvd + 1) % 4;
|
||||
// else
|
||||
// pass=0;//reset if sequence wrong
|
||||
// }
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -363,12 +513,25 @@ pkt[6]|(counter++)|00 01 02 03 04 05 06 07 08 09
|
||||
0x34 0x0A 0xC3 0x56 0xF3
|
||||
|
||||
*/
|
||||
|
||||
const uint8_t PROGMEM Indices[] = { 0x00, 0xA1, 0x22, 0x83, 0xE4, 0x45,
|
||||
0xC6, 0x67, 0x48, 0xE9, 0x6A, 0xCB,
|
||||
0xAC, 0x0D, 0x8E, 0x2F, 0xD0, 0x71,
|
||||
0xF2, 0x53, 0x34, 0x95, 0x16, 0xB7,
|
||||
0x98, 0x39, 0xBA, 0x1B } ;
|
||||
|
||||
|
||||
#ifdef MULTI_TELEMETRY
|
||||
void sportSend(uint8_t *p)
|
||||
{
|
||||
multi_send_header(MULTI_TELEMETRY_SPORT, 9);
|
||||
uint16_t crc_s = 0;
|
||||
Serial_write(p[0]) ;
|
||||
uint8_t x = p[0] ;
|
||||
if ( x <= 0x1B )
|
||||
{
|
||||
x = pgm_read_byte_near( &Indices[x] ) ;
|
||||
}
|
||||
Serial_write(x) ;
|
||||
for (uint8_t i = 1; i < 9; i++)
|
||||
{
|
||||
if (i == 8)
|
||||
@@ -462,7 +625,13 @@ void sportSendFrame()
|
||||
{
|
||||
for (i=0;i<FRSKY_SPORT_PACKET_SIZE;i++)
|
||||
frame[i]=pktx1[i];
|
||||
sport=0;
|
||||
sport -= 1 ;
|
||||
if ( sport )
|
||||
{
|
||||
uint8_t j = sport * FRSKY_SPORT_PACKET_SIZE ;
|
||||
for (i=0;i<j;i++)
|
||||
pktx1[i] = pktx1[i+FRSKY_SPORT_PACKET_SIZE] ;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
@@ -506,19 +675,20 @@ void proces_sport_data(uint8_t data)
|
||||
} // end switch
|
||||
if (indx >= FRSKY_SPORT_PACKET_SIZE)
|
||||
{//8 bytes no crc
|
||||
if ( sport )
|
||||
{
|
||||
// overrun!
|
||||
}
|
||||
else
|
||||
if ( sport < FX_BUFFERS )
|
||||
{
|
||||
uint8_t dest = sport * FRSKY_SPORT_PACKET_SIZE ;
|
||||
uint8_t i ;
|
||||
for ( i = 0 ; i < FRSKY_SPORT_PACKET_SIZE ; i += 1 )
|
||||
{
|
||||
pktx1[i] = pktx[i] ; // Double buffer
|
||||
pktx1[dest++] = pktx[i] ; // Triple buffer
|
||||
}
|
||||
sport = 1;//ok to send
|
||||
sport += 1 ;//ok to send
|
||||
}
|
||||
// else
|
||||
// {
|
||||
// // Overrun
|
||||
// }
|
||||
pass = 0;//reset
|
||||
}
|
||||
}
|
||||
@@ -534,11 +704,14 @@ void TelemetryUpdate()
|
||||
h = SerialControl.head ;
|
||||
t = SerialControl.tail ;
|
||||
if ( h >= t )
|
||||
t += 128 - h ;
|
||||
t += 192 - h ;
|
||||
else
|
||||
t -= h ;
|
||||
// if ( t < 32 )
|
||||
if ( t < 64 )
|
||||
{
|
||||
return ;
|
||||
}
|
||||
#else
|
||||
uint8_t h ;
|
||||
uint8_t t ;
|
||||
@@ -549,7 +722,9 @@ void TelemetryUpdate()
|
||||
else
|
||||
t -= h ;
|
||||
if ( t < 32 )
|
||||
{
|
||||
return ;
|
||||
}
|
||||
#endif
|
||||
#if ( defined(MULTI_TELEMETRY) || defined(MULTI_STATUS) )
|
||||
{
|
||||
@@ -566,15 +741,62 @@ void TelemetryUpdate()
|
||||
#if defined SPORT_TELEMETRY
|
||||
if (protocol==MODE_FRSKYX)
|
||||
{ // FrSkyX
|
||||
// struct t_fx_rx_frame *p ;
|
||||
// uint8_t count ;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
struct t_fx_rx_frame *p ;
|
||||
uint8_t count ;
|
||||
p = &FrskyxRxFrames[NextFxFrameToForward] ;
|
||||
if ( p->valid )
|
||||
{
|
||||
count = p->count ;
|
||||
for (uint8_t i=0; i < count ; i++)
|
||||
proces_sport_data(p->payload[i]) ;
|
||||
p->valid = 0 ; // Sent on
|
||||
NextFxFrameToForward = ( NextFxFrameToForward + 1 ) & 3 ;
|
||||
}
|
||||
else
|
||||
{
|
||||
break ;
|
||||
}
|
||||
}
|
||||
|
||||
// p = &FrskyxRxFrames[NextFxFrameToForward] ;
|
||||
// if ( p->valid )
|
||||
// {
|
||||
// count = p->count ;
|
||||
// for (uint8_t i=0; i < count ; i++)
|
||||
// proces_sport_data(p->payload[i]) ;
|
||||
// p->valid = 0 ; // Sent on
|
||||
// NextFxFrameToForward = ( NextFxFrameToForward + 1 ) & 3 ;
|
||||
// }
|
||||
|
||||
if(telemetry_link)
|
||||
{
|
||||
if(pktt[4] & 0x80)
|
||||
RX_RSSI=pktt[4] & 0x7F ;
|
||||
else
|
||||
RxBt = (pktt[4]<<1) + 1 ;
|
||||
if(pktt[6] && pktt[6]<=6)
|
||||
for (uint8_t i=0; i < pktt[6]; i++)
|
||||
proces_sport_data(pktt[7+i]);
|
||||
|
||||
// if(pktt[6] && pktt[6]<=6)
|
||||
// {
|
||||
// for (uint8_t i=0; i < pktt[6]; i++)
|
||||
// proces_sport_data(pktt[7+i]);
|
||||
// if ( FrskyxRxTelemetry.validSequence & 0x80 )
|
||||
// {
|
||||
// // Process out of sequence packet
|
||||
// for (uint8_t i=0; i < FrskyxRxTelemetry.count ; i++)
|
||||
// {
|
||||
// proces_sport_data( FrskyxRxTelemetry.payload[i] ) ;
|
||||
// }
|
||||
//// FrX_receive_seq = ( FrskyxRxTelemetry.validSequence + 1 ) & 3 ;
|
||||
// FrskyxRxTelemetry.validSequence = 0 ;
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
telemetry_link=0;
|
||||
}
|
||||
uint32_t now = micros();
|
||||
@@ -928,7 +1150,13 @@ ISR(TIMER0_COMPB_vect)
|
||||
{
|
||||
GPIOR0 = ptr->data[ptr->tail] ;
|
||||
GPIOR2 = ptr->data[ptr->tail+1] ;
|
||||
ptr->tail = ( ptr->tail + 2 ) & 0x7F ;
|
||||
uint8_t nextTail ;
|
||||
nextTail = ptr->tail + 2 ;
|
||||
if ( nextTail > 192 )
|
||||
{
|
||||
nextTail = 0 ;
|
||||
}
|
||||
ptr->tail = nextTail ;
|
||||
GPIOR1 = 8 ;
|
||||
OCR0A = OCR0B + 40 ;
|
||||
OCR0B = OCR0A + 8 * 20 ;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#endif
|
||||
#if not defined (ORANGE_TX) && not defined (STM32_BOARD)
|
||||
//Atmega328p
|
||||
#if not defined(ARDUINO_AVR_PRO) && not defined(ARDUINO_AVR_MINI) && not defined(ARDUINO_AVR_NANO)
|
||||
#if not defined(ARDUINO_AVR_PRO) && not defined(ARDUINO_MULTI_NO_BOOT) && not defined(ARDUINO_MULTI_FLASH_FROM_TX) && not defined(ARDUINO_AVR_MINI) && not defined(ARDUINO_AVR_NANO)
|
||||
#error You must select one of these boards: "Multi 4-in-1", "Arduino Pro or Pro Mini" or "Arduino Mini"
|
||||
#endif
|
||||
#if F_CPU != 16000000L || not defined(__AVR_ATmega328P__)
|
||||
@@ -18,6 +18,14 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//Change/Force configuration for the bootloader option
|
||||
#if defined ARDUINO_MULTI_FLASH_FROM_TX
|
||||
#define CHECK_FOR_BOOTLOADER
|
||||
#endif
|
||||
#if defined ARDUINO_MULTI_NO_BOOT
|
||||
#undef CHECK_FOR_BOOTLOADER
|
||||
#endif
|
||||
|
||||
//Change/Force configuration if OrangeTX
|
||||
#ifdef ORANGE_TX
|
||||
#undef ENABLE_PPM // Disable PPM for OrangeTX module
|
||||
@@ -70,6 +78,7 @@
|
||||
#undef HONTAI_NRF24L01_INO
|
||||
#undef Q303_NRF24L01_INO
|
||||
#undef GW008_NRF24L01_INO
|
||||
#undef DM002_NRF24L01_INO
|
||||
#undef CABELL_NRF24L01_INO
|
||||
#endif
|
||||
|
||||
@@ -79,6 +88,7 @@
|
||||
#undef AFHDS2A_FW_TELEMETRY
|
||||
#undef AFHDS2A_HUB_TELEMETRY
|
||||
#undef BAYANG_HUB_TELEMETRY
|
||||
#undef CABELL_HUB_TELEMETRY
|
||||
#undef HUBSAN_HUB_TELEMETRY
|
||||
#undef HUB_TELEMETRY
|
||||
#undef SPORT_TELEMETRY
|
||||
@@ -92,6 +102,9 @@
|
||||
#if not defined(BAYANG_NRF24L01_INO)
|
||||
#undef BAYANG_HUB_TELEMETRY
|
||||
#endif
|
||||
#if not defined(CABELL_NRF24L01_INO)
|
||||
#undef CABELL_HUB_TELEMETRY
|
||||
#endif
|
||||
#if not defined(HUBSAN_A7105_INO)
|
||||
#undef HUBSAN_HUB_TELEMETRY
|
||||
#endif
|
||||
@@ -108,7 +121,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(AFHDS2A_HUB_TELEMETRY) && not defined(AFHDS2A_FW_TELEMETRY) && not defined(MULTI_TELEMETRY) && not defined(MULTI_STATUS)
|
||||
#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)
|
||||
#undef TELEMETRY
|
||||
#undef INVERT_TELEMETRY
|
||||
#endif
|
||||
@@ -142,4 +155,4 @@
|
||||
#endif
|
||||
#if MAX_PPM_CHANNELS>16
|
||||
#error MAX_PPM_CHANNELS must be below or equal to 16. The default for this value is 16.
|
||||
#endif
|
||||
#endif
|
||||
@@ -49,6 +49,13 @@
|
||||
//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
|
||||
|
||||
/*************************/
|
||||
/*** BOOTLOADER USE ***/
|
||||
/*************************/
|
||||
//Allow flashing multimodule directly with TX(erky9x or opentx modified firmwares)
|
||||
//Check https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/tree/master/BootLoaders
|
||||
//To enable this feature remove the "//" on the next line. It is automatically enabled/disabled when you use the AVR Multi boards.
|
||||
//#define CHECK_FOR_BOOTLOADER
|
||||
|
||||
/****************/
|
||||
/*** RF CHIPS ***/
|
||||
@@ -71,6 +78,22 @@
|
||||
//#define NRF24L01_ENABLE_LOW_POWER
|
||||
|
||||
|
||||
/*****************/
|
||||
/*** GLOBAL ID ***/
|
||||
/*****************/
|
||||
//A global ID is used by most protocols to bind and retain the bind to models. To prevent duplicate IDs, it is automatically
|
||||
// generated using a random 32 bits number the first time the eeprom is initialized.
|
||||
//If you have 2 Multi modules which you want to share the same ID so you can use either to control the same RC model
|
||||
// then you can force the ID to a certain known value using the lines below.
|
||||
//Default is commented, you should uncoment only for test purpose or if you know exactly what you are doing!!!
|
||||
//#define FORCE_GLOBAL_ID 0x12345678
|
||||
|
||||
//Protocols using the CYRF6936 (DSM, Devo, Walkera...) are using the CYRF ID instead which should prevent duplicated IDs.
|
||||
//If you have 2 Multi modules which you want to share the same ID so you can use either to control the same RC model
|
||||
// then you can force the ID to a certain known value using the lines below.
|
||||
//Default is commented, you should uncoment only for test purpose or if you know exactly what you are doing!!!
|
||||
//#define FORCE_CYRF_ID "\x12\x34\x56\x78\x9A\xBC"
|
||||
|
||||
/****************************/
|
||||
/*** PROTOCOLS TO INCLUDE ***/
|
||||
/****************************/
|
||||
@@ -113,10 +136,51 @@
|
||||
#define FQ777_NRF24L01_INO
|
||||
#define ASSAN_NRF24L01_INO
|
||||
#define HONTAI_NRF24L01_INO
|
||||
#define Q303_NRF24L01_INO
|
||||
#define GW008_NRF24L01_INO
|
||||
#define Q303_NRF24L01_INO
|
||||
#define GW008_NRF24L01_INO
|
||||
#define DM002_NRF24L01_INO
|
||||
#define CABELL_NRF24L01_INO
|
||||
|
||||
/**************************/
|
||||
/*** FAILSAFE SETTINGS ***/
|
||||
/**************************/
|
||||
//SHFSS failsafe is by default set to all channels hold their positions except throttle forced to low (980µs)
|
||||
//You can uncomment the setting below to use channels 9(1) to 16(8) instead
|
||||
//#define SFHSS_FAILSAFE_CH9_16
|
||||
|
||||
#define AFHDS2A_FAILSAFE
|
||||
#ifdef AFHDS2A_FAILSAFE
|
||||
/*
|
||||
Failsafe Min/Max values 962 <-> 2038
|
||||
*/
|
||||
const int8_t AFHDS2AFailsafeMIN = -105;
|
||||
const int8_t AFHDS2AFailsafeMAX = 105;
|
||||
//
|
||||
const int8_t AFHDS2AFailsafe[14]= {
|
||||
/*
|
||||
Failsafe examples
|
||||
988 <-> 2012µs -100% = 988 = 1500 + (2012-988)/2 * (-100/100) = 1500 - 512 = 988
|
||||
988 <-> 2012µs 0% = 1500 = 1500 + (2012-988)/2 * ( 0/100) = 1500 + 0 = 1500
|
||||
988 <-> 2012µs 100% = 2012 = 1500 + (2012-988)/2 * ( 100/100) = 1500 + 512 = 2012
|
||||
988 <-> 2012µs -105% = 962 = 1500 + (2012-988)/2 * (-105/100) = 1500 - 538 = 962
|
||||
*/
|
||||
/* ch 1 */ -1,
|
||||
/* ch 2 */ -1,
|
||||
/* ch 3 */ -105,
|
||||
/* ch 4 */ -1,
|
||||
/* ch 5 */ -1,
|
||||
/* ch 6 */ -1,
|
||||
/* ch 7 */ -1,
|
||||
/* ch 8 */ -1,
|
||||
/* ch 9 */ -1,
|
||||
/* ch 10 */ -1,
|
||||
/* ch 11 */ -1,
|
||||
/* ch 12 */ -1,
|
||||
/* ch 13 */ -1,
|
||||
/* ch 14 */ -1
|
||||
};
|
||||
#endif
|
||||
|
||||
/**************************/
|
||||
/*** TELEMETRY SETTINGS ***/
|
||||
/**************************/
|
||||
@@ -149,7 +213,7 @@
|
||||
#define AFHDS2A_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 HUBSAN_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
||||
|
||||
#define CABELL_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
||||
|
||||
/****************************/
|
||||
/*** SERIAL MODE SETTINGS ***/
|
||||
@@ -161,7 +225,6 @@
|
||||
//If you do not plan to use the Serial mode comment this line using "//" to save Flash space
|
||||
#define ENABLE_SERIAL
|
||||
|
||||
|
||||
/*************************/
|
||||
/*** PPM MODE SETTINGS ***/
|
||||
/*************************/
|
||||
@@ -211,8 +274,8 @@ const PPM_Parameters PPM_prot[15]= {
|
||||
/* 3 */ {MODE_FRSKYD, 0 , 0 , P_HIGH , NO_AUTOBIND , 40 }, // option=fine freq tuning
|
||||
/* 4 */ {MODE_HISKY , Hisky , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 5 */ {MODE_V2X2 , 0 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 6 */ {MODE_DSM , DSM2_22 , 0 , P_HIGH , NO_AUTOBIND , 6 }, // option=number of channels
|
||||
/* 7 */ {MODE_DEVO , 0 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 6 */ {MODE_DSM , DSMX_11 , 0 , P_HIGH , NO_AUTOBIND , 6 }, // option=number of channels
|
||||
/* 7 */ {MODE_DSM , DSM2_22 , 0 , P_HIGH , NO_AUTOBIND , 6 },
|
||||
/* 8 */ {MODE_YD717 , YD717 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 9 */ {MODE_KN , WLTOYS , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 10 */ {MODE_SYMAX , SYMAX , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
@@ -288,6 +351,7 @@ const PPM_Parameters PPM_prot[15]= {
|
||||
MODE_BAYANG
|
||||
BAYANG
|
||||
H8S3D
|
||||
X16_AH
|
||||
MODE_ESKY
|
||||
NONE
|
||||
MODE_MT99XX
|
||||
@@ -340,6 +404,8 @@ const PPM_Parameters PPM_prot[15]= {
|
||||
CX10WD
|
||||
MODE_GW008
|
||||
NONE
|
||||
MODE_DM002
|
||||
NONE
|
||||
MODE_CABELL
|
||||
CABELL_V3
|
||||
CABELL_V3_TELEMETRY
|
||||
|
||||
24
Multiprotocol/_MyConfig.h
Normal file
24
Multiprotocol/_MyConfig.h
Normal file
@@ -0,0 +1,24 @@
|
||||
//#define FORCE_GLOBAL_ID 0x12345678
|
||||
|
||||
#if not defined STM32_BOARD
|
||||
// #undef AFHDS2A_A7105_INO
|
||||
|
||||
// #undef DEVO_CYRF6936_INO
|
||||
// #undef J6PRO_CYRF6936_INO
|
||||
// #undef WK2x01_CYRF6936_INO
|
||||
|
||||
// #undef FRSKYV_CC2500_INO
|
||||
// #undef FRSKYX_CC2500_INO
|
||||
|
||||
// #undef KN_NRF24L01_INO
|
||||
// #undef SLT_NRF24L01_INO
|
||||
|
||||
// #undef FY326_NRF24L01_INO
|
||||
// #undef FQ777_NRF24L01_INO
|
||||
// #undef ASSAN_NRF24L01_INO
|
||||
// #undef HONTAI_NRF24L01_INO
|
||||
// #undef Q303_NRF24L01_INO
|
||||
// #undef GW008_NRF24L01_INO
|
||||
// #undef DM002_NRF24L01_INO
|
||||
// #undef CABELL_NRF24L01_INO
|
||||
#endif
|
||||
Reference in New Issue
Block a user