mirror of
https://github.com/pascallanger/DIY-Multiprotocol-TX-Module.git
synced 2025-12-14 03:23:15 +00:00
Merge remote-tracking branch 'refs/remotes/pascallanger/master' into benlye-multi-new
This commit is contained in:
442
Multiprotocol/CABELL_nrf224l01.ino
Normal file
442
Multiprotocol/CABELL_nrf224l01.ino
Normal file
@@ -0,0 +1,442 @@
|
||||
/*
|
||||
Protocol by Dennis Cabell, 2017
|
||||
KE8FZX
|
||||
|
||||
To use this software, you must adhere to the license terms described below, and assume all responsibility for the use
|
||||
of the software. The user is responsible for all consequences or damage that may result from using this software.
|
||||
The user is responsible for ensuring that the hardware used to run this software complies with local regulations and that
|
||||
any radio signal generated or received from use of this software is legal for that user to generate. The author(s) of this software
|
||||
assume no liability whatsoever. The author(s) of this software is not responsible for legal or civil consequences of
|
||||
using this software, including, but not limited to, any damages cause by lost control of a vehicle using this software.
|
||||
If this software is copied or modified, this disclaimer must accompany all copies.
|
||||
|
||||
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/>.
|
||||
*/
|
||||
|
||||
// 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_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_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
|
||||
|
||||
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,
|
||||
normalWithTelemetry = 3,
|
||||
telemetryResponse = 4,
|
||||
unBind = 127
|
||||
} RxMode;
|
||||
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
|
||||
* 1 (01) = SUM PPM on channel 1 pin
|
||||
* 2 (10) = Future use. Reserved for SBUS output
|
||||
* 3 (11) = Unused
|
||||
* 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
|
||||
} 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
|
||||
if(prevChannel>(seqArraySize * 5))
|
||||
prevChannel=seqArraySize * 5; // Constrain the values just in case something bogus was sent in.
|
||||
|
||||
uint8_t currBand = prevChannel / seqArraySize;
|
||||
uint8_t nextBand = (currBand + 3) % 5;
|
||||
|
||||
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 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;
|
||||
}
|
||||
|
||||
// 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 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;
|
||||
|
||||
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);
|
||||
|
||||
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
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
TxPacket.checkSum_MSB = checkSum >> 8;
|
||||
TxPacket.checkSum_LSB = checkSum & 0x00FF;
|
||||
|
||||
// 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.
|
||||
*/
|
||||
uint8_t i; //iterator counts numChannels
|
||||
uint64_t indexOfNextSequenceValue;
|
||||
uint64_t numChannelsFactorial=1;
|
||||
uint8_t sequenceValue;
|
||||
|
||||
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
|
||||
|
||||
//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;
|
||||
|
||||
// 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
|
||||
|
||||
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;
|
||||
|
||||
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
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
static void CABELL_SetPower() // This over-ride the standard Set Power to allow an flag in option to indicate max power setting
|
||||
// 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();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
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;
|
||||
}
|
||||
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 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;
|
||||
|
||||
return packet_period;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -63,7 +63,7 @@ static void __attribute__((unused)) DEVO_add_pkt_suffix()
|
||||
BIND_SET_PULLUP; // set pullup
|
||||
if(IS_BIND_BUTTON_on)
|
||||
{
|
||||
eeprom_write_byte((EE_ADDR)(30+mode_select),0x01); // Set fixed id mode for the current model
|
||||
eeprom_write_byte((EE_ADDR)(MODELMODE_EEPROM_OFFSET+mode_select),0x01); // Set fixed id mode for the current model
|
||||
option=1;
|
||||
}
|
||||
BIND_SET_OUTPUT;
|
||||
|
||||
@@ -31,3 +31,4 @@
|
||||
31,Q303,Q303,CX35,CX10D,CX10WD
|
||||
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 25
|
||||
#define VERSION_PATCH_LEVEL 30
|
||||
//******************
|
||||
// Protocols
|
||||
//******************
|
||||
@@ -59,6 +59,7 @@ enum PROTOCOLS
|
||||
MODE_Q303 = 31, // =>NRF24L01
|
||||
MODE_GW008 = 32, // =>NRF24L01
|
||||
MODE_DM002 = 33, // =>NRF24L01
|
||||
MODE_CABELL = 34, // =>NRF24L01
|
||||
};
|
||||
|
||||
enum Flysky
|
||||
@@ -196,6 +197,13 @@ enum Q303
|
||||
CX10D = 2,
|
||||
CX10WD = 3,
|
||||
};
|
||||
enum CABELL
|
||||
{
|
||||
CABELL_V3 = 0,
|
||||
CABELL_V3_TELEMETRY = 1,
|
||||
CABELL_SET_FAIL_SAFE= 6,
|
||||
CABELL_UNBIND = 7,
|
||||
};
|
||||
|
||||
#define NONE 0
|
||||
#define P_HIGH 1
|
||||
@@ -216,14 +224,29 @@ struct PPM_Parameters
|
||||
// Telemetry
|
||||
|
||||
enum MultiPacketTypes {
|
||||
MULTI_TELEMETRY_STATUS = 1,
|
||||
MULTI_TELEMETRY_SPORT = 2,
|
||||
MULTI_TELEMETRY_HUB = 3,
|
||||
MULTI_TELEMETRY_DSM = 4,
|
||||
MULTI_TELEMETRY_DSMBIND = 5,
|
||||
MULTI_TELEMETRY_AFHDS2A = 6,
|
||||
MULTI_TELEMETRY_STATUS = 1,
|
||||
MULTI_TELEMETRY_SPORT = 2,
|
||||
MULTI_TELEMETRY_HUB = 3,
|
||||
MULTI_TELEMETRY_DSM = 4,
|
||||
MULTI_TELEMETRY_DSMBIND = 5,
|
||||
MULTI_TELEMETRY_AFHDS2A = 6,
|
||||
MULTI_TELEMETRY_INPUTSYNC=8,
|
||||
MULTI_COMMAND_CONFIG = 0x80,
|
||||
MULTI_COMMAND_FAILSAFE =0x81,
|
||||
};
|
||||
|
||||
enum FailSafeMode {
|
||||
FAILSAFE_NOTSET = 0,
|
||||
FAILSAFE_HOLD = 1,
|
||||
FAILSAFE_CUSTOM = 2,
|
||||
FAILSAFE_NOPULSES = 3,
|
||||
FAILSAFE_RECEIVER = 4,
|
||||
// Use during update so we can get away with only one copy of Failsafe channels
|
||||
FAILSEFASE_INVALID = 0xfe
|
||||
};
|
||||
|
||||
#define FAILSAFE_CHANNEL_HOLD 0
|
||||
#define FAILSAFE_CHANNEL_NOPULSES 2047
|
||||
|
||||
// Macros
|
||||
#define NOP() __asm__ __volatile__("nop")
|
||||
@@ -298,6 +321,23 @@ enum MultiPacketTypes {
|
||||
#define IS_WAIT_BIND_on ( ( protocol_flags2 & _BV(7) ) !=0 )
|
||||
#define IS_WAIT_BIND_off ( ( protocol_flags2 & _BV(7) ) ==0 )
|
||||
|
||||
//Configuration
|
||||
#define IS_TELEMTRY_INVERSION_ON (multi_config & 0x01)
|
||||
#define IS_MULTI_TELEMETRY_ON (multi_config & 0x02)
|
||||
#define IS_EXTRA_TELEMETRY_ON (multi_config & 0x04)
|
||||
|
||||
// Failsafe
|
||||
#define failsafeToPPM(i) (Failsafe_data[i]* 5/8+860)
|
||||
#define isNormalFailsafeChanel(i) (Failsafe_data[i] != FAILSAFE_CHANNEL_HOLD && Failsafe_data[i] != FAILSAFE_CHANNEL_NOPULSES)
|
||||
|
||||
|
||||
//Status messages
|
||||
#if defined(STM32_BOARD) && defined (SERIAL_DEBUG)
|
||||
#define debug(msg, ...) {char buf[64]; sprintf(buf, msg "\r\n", ##__VA_ARGS__); for(int i=0;buf[i] !=0; i++) StatusSerial_write(buf[i]);}
|
||||
#else
|
||||
#define debug(...)
|
||||
#undef SERIAL_DEBUG
|
||||
#endif
|
||||
|
||||
//********************
|
||||
//*** Blink timing ***
|
||||
@@ -435,6 +475,14 @@ enum {
|
||||
#define SPEED_57600 2
|
||||
#define SPEED_125K 3
|
||||
|
||||
/** EEPROM Layout */
|
||||
#define EEPROM_ID_OFFSET 10 // Module ID (4 bytes)
|
||||
#define EEPROM_ID_VALID_OFFSET 20 // 1 byte flag that ID is valid
|
||||
#define MODELMODE_EEPROM_OFFSET 30 // Autobind mode, 1 byte per model, end is 46
|
||||
#define AFHDS2A_EEPROM_OFFSET 50 // RX ID, 4 byte per model id, end is 114
|
||||
#define CONFIG_EEPROM_OFFSET 120 // Current configuration of the multimodule
|
||||
|
||||
|
||||
//****************************************
|
||||
//*** MULTI protocol serial definition ***
|
||||
//****************************************
|
||||
@@ -483,6 +531,7 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
||||
Q303 31
|
||||
GW008 32
|
||||
DM002 33
|
||||
CABELL 34
|
||||
BindBit=> 0x80 1=Bind/0=No
|
||||
AutoBindBit=> 0x40 1=Yes /0=No
|
||||
RangeCheck=> 0x20 1=Yes /0=No
|
||||
@@ -585,6 +634,11 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
||||
CX35 1
|
||||
CX10D 2
|
||||
CX10WD 3
|
||||
sub_protocol==CABELL
|
||||
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;
|
||||
@@ -623,7 +677,7 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
||||
version of multi code, should be displayed as major.minor.revision.patchlevel
|
||||
*/
|
||||
/*
|
||||
Multiprotocol telemetry definition for OpenTX
|
||||
Multiprotocol telemetry/command definition for OpenTX
|
||||
Based on #define MULTI_TELEMETRY enables OpenTX to get the multimodule status and select the correct telemetry type automatically.
|
||||
|
||||
Serial: 100000 Baud 8e2 (same as input)
|
||||
@@ -643,6 +697,8 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
||||
|
||||
[4-xx] data
|
||||
|
||||
Commands from TX to multi cannot be longer than 22 bytes (RXLen -4byte header)
|
||||
|
||||
Type = 0x01 Multimodule Status:
|
||||
[4] Flags
|
||||
0x01 = Input signal detected
|
||||
@@ -672,12 +728,53 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
||||
Type 0x05 DSM bind data
|
||||
data[0-16] DSM bind data
|
||||
|
||||
technically DSM bind data is only 10 bytes but multi send 16
|
||||
like with telemtry, check length field)
|
||||
technically DSM bind data is only 10 bytes but multi sends 16
|
||||
like with telemtery, check length field)
|
||||
|
||||
Type 0x06 Flysky AFHDS2 telemetry data
|
||||
length: 29
|
||||
data[0] = RSSI value
|
||||
data[1-28] telemetry data
|
||||
|
||||
|
||||
Type 0x08 Input synchronisation
|
||||
Informs the TX about desired rate and current delay
|
||||
length: 4
|
||||
data[0-1] Desired refresh rate in µs
|
||||
data[2-3] Time (µs) between last serial servo input received and servo input needed (lateness), TX should adjust its
|
||||
sending time to minimise this value.
|
||||
data[4] Interval of this message in ms
|
||||
data[5] Input delay target in 10µs
|
||||
|
||||
Note that there are protocols (AFHDS2A) that have a refresh rate that is smaller than the maximum achievable
|
||||
refresh rate via the serial protocol, in this case, the TX should double the rate and also subract this
|
||||
refresh rate from the input lag if the input lag is more than the desired refresh rate.
|
||||
|
||||
The remote should try to get to zero of (inputdelay+target*10).
|
||||
|
||||
Commands from TX to module use values > 127 for command type
|
||||
|
||||
Type 0x80 Module Configuration
|
||||
This sent from the TX to Multi to configure inversion and multi telemetry type
|
||||
length: 1
|
||||
data[0] flags
|
||||
0x01 Telemetry inversion (1 = inverted)
|
||||
0x02 Use Multi telemetry protocol (if 0 use multi status)
|
||||
0x04 Send extra telemetry (type 0x08) to allow input synchronisation
|
||||
|
||||
|
||||
Type 0x81 Failsafe data
|
||||
length: 23
|
||||
data[0] Failsafe mode:
|
||||
0 - Failsafe not set
|
||||
1 - Failsafe hold, keep last received values
|
||||
2 - Failsafe custom, use the values from the channels
|
||||
3 - Failsafe nopulses, stop sending pulses from the receiver
|
||||
4 - Failsafe receiver, use receiver stored values
|
||||
|
||||
Many of these many modes don't work with all protocols, fallback to best
|
||||
available method
|
||||
data[1-22] Failsafe data, encoded like normal channel data, with the expection
|
||||
that 0 means hold for that channel and 2047 means no pulses
|
||||
|
||||
*/
|
||||
|
||||
@@ -21,20 +21,23 @@
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
//#define DEBUG_TX
|
||||
//#define USE_MY_CONFIG
|
||||
#ifdef ARDUINO_AVR_XMEGA32D4
|
||||
#include "MultiOrange.h"
|
||||
//#define SERIAL_DEBUG // Only for STM32_BOARD on usart1
|
||||
|
||||
#define USE_MY_CONFIG
|
||||
|
||||
#ifdef __arm__// Let's automatically select the board if arm is selected
|
||||
#define STM32_BOARD
|
||||
#endif
|
||||
#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
|
||||
#endif
|
||||
|
||||
//Personal config file
|
||||
#if defined USE_MY_CONFIG
|
||||
@@ -58,6 +61,9 @@
|
||||
void ISR_COMPB();
|
||||
extern "C"
|
||||
{
|
||||
#ifdef SERIAL_DEBUG
|
||||
void __irq_usart1(void);
|
||||
#endif
|
||||
void __irq_usart2(void);
|
||||
void __irq_usart3(void);
|
||||
}
|
||||
@@ -184,6 +190,11 @@ uint8_t pkt[MAX_PKT];//telemetry receiving packets
|
||||
volatile uint8_t tx_head=0;
|
||||
volatile uint8_t tx_tail=0;
|
||||
#endif // BASH_SERIAL
|
||||
#ifdef SERIAL_DEBUG
|
||||
volatile uint8_t tx_debug_buff[TXBUFFER_SIZE];
|
||||
volatile uint8_t tx_debug_head=0;
|
||||
volatile uint8_t tx_debug_tail=0;
|
||||
#endif // SERIAL_DEBUG
|
||||
uint8_t v_lipo1;
|
||||
uint8_t v_lipo2;
|
||||
uint8_t RX_RSSI;
|
||||
@@ -193,7 +204,7 @@ uint8_t pkt[MAX_PKT];//telemetry receiving packets
|
||||
uint8_t telemetry_link=0;
|
||||
uint8_t telemetry_counter=0;
|
||||
uint8_t telemetry_lost;
|
||||
#endif
|
||||
#endif // TELEMETRY
|
||||
|
||||
// Callback
|
||||
typedef uint16_t (*void_function_t) (void);//pointer to a function with no parameters which return an uint16_t integer
|
||||
@@ -202,6 +213,13 @@ void_function_t remote_callback = 0;
|
||||
// Init
|
||||
void setup()
|
||||
{
|
||||
// Setup diagnostic uart before anything else
|
||||
#ifdef SERIAL_DEBUG
|
||||
usart1_begin(115200,SERIAL_8N1);
|
||||
tx_debug_resume();
|
||||
debug("Multiprotocol version: %d.%d.%d.%d", VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_PATCH_LEVEL);
|
||||
#endif
|
||||
|
||||
// General pinout
|
||||
#ifdef ORANGE_TX
|
||||
//XMEGA
|
||||
@@ -227,14 +245,15 @@ void setup()
|
||||
pinMode(CC25_CSN_pin,OUTPUT);
|
||||
pinMode(NRF_CSN_pin,OUTPUT);
|
||||
pinMode(CYRF_CSN_pin,OUTPUT);
|
||||
pinMode(SPI_CSN_pin,OUTPUT);
|
||||
pinMode(CYRF_RST_pin,OUTPUT);
|
||||
pinMode(PE1_pin,OUTPUT);
|
||||
pinMode(PE2_pin,OUTPUT);
|
||||
pinMode(TX_INV_pin,OUTPUT);
|
||||
pinMode(RX_INV_pin,OUTPUT);
|
||||
#if defined TELEMETRY
|
||||
pinMode(TX_INV_pin,OUTPUT);
|
||||
pinMode(RX_INV_pin,OUTPUT);
|
||||
#if defined INVERT_SERIAL
|
||||
TX_INV_on;//activated inverter for both serial TX and RX signals
|
||||
TX_INV_on; //activate inverter for both serial TX and RX signals
|
||||
RX_INV_on;
|
||||
#else
|
||||
TX_INV_off;
|
||||
@@ -287,7 +306,7 @@ void setup()
|
||||
// Timer1 config
|
||||
TCCR1A = 0;
|
||||
TCCR1B = (1 << CS11); //prescaler8, set timer1 to increment every 0.5us(16Mhz) and start timer
|
||||
|
||||
|
||||
// Random
|
||||
random_init();
|
||||
#endif
|
||||
@@ -341,6 +360,7 @@ void setup()
|
||||
((MODE_DIAL3_ipr & _BV(MODE_DIAL3_pin)) ? 0 : 4) +
|
||||
((MODE_DIAL4_ipr & _BV(MODE_DIAL4_pin)) ? 0 : 8);
|
||||
#endif
|
||||
debug("Mode switch reads as %d", mode_select);
|
||||
|
||||
// Update LED
|
||||
LED_off;
|
||||
@@ -360,6 +380,8 @@ void setup()
|
||||
|
||||
// Read or create protocol id
|
||||
MProtocol_id_master=random_id(10,false);
|
||||
|
||||
debug("Module Id: %lx", MProtocol_id_master);
|
||||
|
||||
#ifdef ENABLE_PPM
|
||||
//Protocol and interrupts initialization
|
||||
@@ -415,6 +437,7 @@ void setup()
|
||||
#endif //ENABLE_SERIAL
|
||||
}
|
||||
servo_mid=servo_min_100+servo_max_100; //In fact 2* mid_value
|
||||
debug("init complete");
|
||||
}
|
||||
|
||||
// Main
|
||||
@@ -539,7 +562,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) )
|
||||
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
|
||||
@@ -678,6 +701,18 @@ inline void tx_resume()
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SERIAL_DEBUG
|
||||
inline void tx_debug_resume()
|
||||
{
|
||||
USART1_BASE->CR1 |= USART_CR1_TXEIE;
|
||||
}
|
||||
|
||||
inline void tx_debug_pause()
|
||||
{
|
||||
USART1_BASE->CR1 &= ~ USART_CR1_TXEIE;
|
||||
}
|
||||
#endif // SERIAL_DEBUG
|
||||
|
||||
#ifdef STM32_BOARD
|
||||
void start_timer2()
|
||||
{
|
||||
@@ -764,7 +799,7 @@ static void protocol_init()
|
||||
#if defined(HUBSAN_A7105_INO)
|
||||
case MODE_HUBSAN:
|
||||
PE1_off; //antenna RF1
|
||||
if(IS_BIND_BUTTON_FLAG_on) random_id(10,true); // Generate new ID if bind button is pressed.
|
||||
if(IS_BIND_BUTTON_FLAG_on) random_id(EEPROM_ID_OFFSET,true); // Generate new ID if bind button is pressed.
|
||||
next_callback = initHubsan();
|
||||
remote_callback = ReadHubsan;
|
||||
break;
|
||||
@@ -820,12 +855,12 @@ static void protocol_init()
|
||||
{
|
||||
if(IS_BIND_BUTTON_FLAG_on)
|
||||
{
|
||||
eeprom_write_byte((EE_ADDR)(30+mode_select),0x00); // reset to autobind mode for the current model
|
||||
eeprom_write_byte((EE_ADDR)(MODELMODE_EEPROM_OFFSET+mode_select),0x00); // reset to autobind mode for the current model
|
||||
option=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
option=eeprom_read_byte((EE_ADDR)(30+mode_select)); // load previous mode: autobind or fixed id
|
||||
option=eeprom_read_byte((EE_ADDR)(MODELMODE_EEPROM_OFFSET+mode_select)); // load previous mode: autobind or fixed id
|
||||
if(option!=1) option=0; // if not fixed id mode then it should be autobind
|
||||
}
|
||||
}
|
||||
@@ -842,12 +877,12 @@ static void protocol_init()
|
||||
{
|
||||
if(IS_BIND_BUTTON_FLAG_on)
|
||||
{
|
||||
eeprom_write_byte((EE_ADDR)(30+mode_select),0x00); // reset to autobind mode for the current model
|
||||
eeprom_write_byte((EE_ADDR)(MODELMODE_EEPROM_OFFSET+mode_select),0x00); // reset to autobind mode for the current model
|
||||
option=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
option=eeprom_read_byte((EE_ADDR)(30+mode_select)); // load previous mode: autobind or fixed id
|
||||
option=eeprom_read_byte((EE_ADDR)(MODELMODE_EEPROM_OFFSET+mode_select)); // load previous mode: autobind or fixed id
|
||||
if(option!=1) option=0; // if not fixed id mode then it should be autobind
|
||||
}
|
||||
}
|
||||
@@ -988,6 +1023,12 @@ static void protocol_init()
|
||||
remote_callback = DM002_callback;
|
||||
break;
|
||||
#endif
|
||||
#if defined(CABELL_NRF24L01_INO)
|
||||
case MODE_CABELL:
|
||||
next_callback=initCABELL();
|
||||
remote_callback = CABELL_callback;
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -1045,6 +1086,7 @@ void update_serial_data()
|
||||
protocol=(rx_ok_buff[0]==0x55?0:32) + (rx_ok_buff[1]&0x1F); //protocol no (0-63) bits 4-6 of buff[1] and bit 0 of buf[0]
|
||||
sub_protocol=(rx_ok_buff[2]>>4)& 0x07; //subprotocol no (0-7) bits 4-6
|
||||
RX_num=rx_ok_buff[2]& 0x0F; // rx_num bits 0---3
|
||||
debug("New protocol selected: %d, sub proto %d, rxnum %d", protocol, sub_protocol, RX_num);
|
||||
}
|
||||
else
|
||||
if( ((rx_ok_buff[1]&0x80)!=0) && ((cur_protocol[1]&0x80)==0) ) // Bind flag has been set
|
||||
@@ -1064,7 +1106,7 @@ void update_serial_data()
|
||||
//store current protocol values
|
||||
for(uint8_t i=0;i<3;i++)
|
||||
cur_protocol[i] = rx_ok_buff[i];
|
||||
|
||||
|
||||
// decode channel values
|
||||
volatile uint8_t *p=rx_ok_buff+3;
|
||||
uint8_t dec=-3;
|
||||
@@ -1310,7 +1352,7 @@ void pollBoot()
|
||||
#if defined(TELEMETRY)
|
||||
void PPM_Telemetry_serial_init()
|
||||
{
|
||||
if( (protocol==MODE_FRSKYD) || (protocol==MODE_HUBSAN) || (protocol==MODE_AFHDS2A) || (protocol==MODE_BAYANG) )
|
||||
if( (protocol==MODE_FRSKYD) || (protocol==MODE_HUBSAN) || (protocol==MODE_AFHDS2A) || (protocol==MODE_BAYANG) || (protocol==MODE_CABELL) )
|
||||
initTXSerial( SPEED_9600 ) ;
|
||||
if(protocol==MODE_FRSKYX)
|
||||
initTXSerial( SPEED_57600 ) ;
|
||||
@@ -1357,7 +1399,7 @@ static uint32_t random_id(uint16_t address, uint8_t create_new)
|
||||
{
|
||||
id<<=8;
|
||||
id|=eeprom_read_byte((EE_ADDR)address+i-1);
|
||||
}
|
||||
}
|
||||
if(id!=0x2AD141A7) //ID with seed=0
|
||||
return id;
|
||||
}
|
||||
@@ -1373,7 +1415,7 @@ static uint32_t random_id(uint16_t address, uint8_t create_new)
|
||||
{
|
||||
eeprom_write_byte((EE_ADDR)address+i,id);
|
||||
id>>=8;
|
||||
}
|
||||
}
|
||||
eeprom_write_byte((EE_ADDR)(address+10),0xf0);//write bind flag in eeprom.
|
||||
return id;
|
||||
#else
|
||||
|
||||
@@ -209,14 +209,14 @@
|
||||
#endif
|
||||
#else //STM32_BOARD
|
||||
#define BIND_pin PA0
|
||||
#define LED_pin PA1
|
||||
#define LED_pin PA1
|
||||
//
|
||||
#define PPM_pin PA8 //PPM 5V tolerant
|
||||
#define PPM_pin PA8 //PPM 5V tolerant
|
||||
//
|
||||
#define S1_pin PA4 //Dial switch pins
|
||||
#define S2_pin PA5
|
||||
#define S1_pin PA4 //Dial switch pins
|
||||
#define S2_pin PA5
|
||||
#define S3_pin PA6
|
||||
#define S4_pin PA7
|
||||
#define S4_pin PA7
|
||||
//
|
||||
#define PE1_pin PB4 //PE1
|
||||
#define PE2_pin PB5 //PE2
|
||||
@@ -226,10 +226,11 @@
|
||||
#define CYRF_RST_pin PB8 //CYRF RESET
|
||||
#define A7105_CSN_pin PB9 //A7105
|
||||
#define CYRF_CSN_pin PB12 //CYRF CSN
|
||||
#define SPI_CSN_pin PA15
|
||||
//SPI pins
|
||||
#define SCK_pin PB13 //SCK
|
||||
#define SDO_pin PB14 //MISO
|
||||
#define SDI_pin PB15 //MOSI
|
||||
#define SDI_pin PB15 //MOSI
|
||||
//
|
||||
#define TX_INV_pin PB3
|
||||
#define RX_INV_pin PB1
|
||||
@@ -240,40 +241,43 @@
|
||||
#define PE2_on digitalWrite(PE2_pin,HIGH)
|
||||
#define PE2_off digitalWrite(PE2_pin,LOW)
|
||||
|
||||
#define A7105_CSN_on digitalWrite(A7105_CSN_pin,HIGH)
|
||||
#define A7105_CSN_off digitalWrite(A7105_CSN_pin,LOW)
|
||||
#define A7105_CSN_on digitalWrite(A7105_CSN_pin,HIGH)
|
||||
#define A7105_CSN_off digitalWrite(A7105_CSN_pin,LOW)
|
||||
|
||||
#define NRF_CE_on
|
||||
#define NRF_CE_off
|
||||
|
||||
#define SCK_on digitalWrite(SCK_pin,HIGH)
|
||||
#define SCK_off digitalWrite(SCK_pin,LOW)
|
||||
#define SCK_on digitalWrite(SCK_pin,HIGH)
|
||||
#define SCK_off digitalWrite(SCK_pin,LOW)
|
||||
|
||||
#define SDI_on digitalWrite(SDI_pin,HIGH)
|
||||
#define SDI_off digitalWrite(SDI_pin,LOW)
|
||||
#define SDI_on digitalWrite(SDI_pin,HIGH)
|
||||
#define SDI_off digitalWrite(SDI_pin,LOW)
|
||||
|
||||
#define SDI_1 (digitalRead(SDI_pin)==HIGH)
|
||||
#define SDI_0 (digitalRead(SDI_pin)==LOW)
|
||||
#define SDI_1 (digitalRead(SDI_pin)==HIGH)
|
||||
#define SDI_0 (digitalRead(SDI_pin)==LOW)
|
||||
|
||||
#define CC25_CSN_on digitalWrite(CC25_CSN_pin,HIGH)
|
||||
#define CC25_CSN_off digitalWrite(CC25_CSN_pin,LOW)
|
||||
#define CC25_CSN_on digitalWrite(CC25_CSN_pin,HIGH)
|
||||
#define CC25_CSN_off digitalWrite(CC25_CSN_pin,LOW)
|
||||
|
||||
#define NRF_CSN_on digitalWrite(NRF_CSN_pin,HIGH)
|
||||
#define NRF_CSN_off digitalWrite(NRF_CSN_pin,LOW)
|
||||
#define NRF_CSN_on digitalWrite(NRF_CSN_pin,HIGH)
|
||||
#define NRF_CSN_off digitalWrite(NRF_CSN_pin,LOW)
|
||||
|
||||
#define CYRF_CSN_on digitalWrite(CYRF_CSN_pin,HIGH)
|
||||
#define CYRF_CSN_on digitalWrite(CYRF_CSN_pin,HIGH)
|
||||
#define CYRF_CSN_off digitalWrite(CYRF_CSN_pin,LOW)
|
||||
|
||||
#define CYRF_RST_HI digitalWrite(CYRF_RST_pin,HIGH) //reset cyrf
|
||||
#define SPI_CSN_on digitalWrite(SPI_CSN_pin,HIGH)
|
||||
#define SPI_CSN_off digitalWrite(SPI_CSN_pin,LOW)
|
||||
|
||||
#define CYRF_RST_HI digitalWrite(CYRF_RST_pin,HIGH) //reset cyrf
|
||||
#define CYRF_RST_LO digitalWrite(CYRF_RST_pin,LOW) //
|
||||
|
||||
#define SDO_1 (digitalRead(SDO_pin)==HIGH)
|
||||
#define SDO_0 (digitalRead(SDO_pin)==LOW)
|
||||
#define SDO_1 (digitalRead(SDO_pin)==HIGH)
|
||||
#define SDO_0 (digitalRead(SDO_pin)==LOW)
|
||||
|
||||
#define TX_INV_on digitalWrite(TX_INV_pin,HIGH)
|
||||
#define TX_INV_on digitalWrite(TX_INV_pin,HIGH)
|
||||
#define TX_INV_off digitalWrite(TX_INV_pin,LOW)
|
||||
|
||||
#define RX_INV_on digitalWrite(RX_INV_pin,HIGH)
|
||||
#define RX_INV_on digitalWrite(RX_INV_pin,HIGH)
|
||||
#define RX_INV_off digitalWrite(RX_INV_pin,LOW)
|
||||
|
||||
#define LED_on digitalWrite(LED_pin,HIGH)
|
||||
|
||||
@@ -127,25 +127,55 @@ static void __attribute__((unused)) SFHSS_calc_next_chan()
|
||||
// Values grow down and to the right.
|
||||
static void __attribute__((unused)) SFHSS_build_data_packet()
|
||||
{
|
||||
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&1) command|=0x08; // Transmit lower and upper channels twice in a row
|
||||
if((counter&0x3FE)==0x3FE)
|
||||
{
|
||||
command|=0x04; // Transmit failsafe data every 7s
|
||||
counter&=0x3FF; // Reset counter
|
||||
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
|
||||
uint8_t ch_offset = ((command&0x08) >> 1) + ((command&0x04)<<1); // CH1..CH8 when failsafe is off, CH9..CH16 when failsafe is on
|
||||
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);
|
||||
counter&=0x3FF; // Reset failsafe counter
|
||||
if(counter&1) command|=0x08; // Transmit lower and upper channels twice in a row
|
||||
|
||||
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
|
||||
@@ -154,8 +184,8 @@ static void __attribute__((unused)) SFHSS_build_data_packet()
|
||||
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] = rx_tx_addr[2]; // ID?
|
||||
packet[4] = rx_tx_addr[3]; // ID?
|
||||
packet[3] = 0x00; // unknown but prevents some receivers to bind if not 0
|
||||
packet[4] = 0x00; // unknown but prevents some receivers to bind if not 0
|
||||
packet[5] = (rf_ch_num << 3) | ((ch1 >> 9) & 0x07);
|
||||
packet[6] = (ch1 >> 1);
|
||||
packet[7] = (ch1 << 7) | ((ch2 >> 5) & 0x7F );
|
||||
@@ -194,7 +224,7 @@ uint16_t ReadSFHSS()
|
||||
|
||||
/* Work cycle: 6.8ms */
|
||||
#define SFHSS_PACKET_PERIOD 6800
|
||||
#define SFHSS_DATA2_TIMING 1630 // original 1650
|
||||
#define SFHSS_DATA2_TIMING 1625 // 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();
|
||||
@@ -225,7 +255,7 @@ static void __attribute__((unused)) SFHSS_get_tx_id()
|
||||
uint8_t run_count = 0;
|
||||
// add guard for bit count
|
||||
fixed_id = 1 ^ (MProtocol_id & 1);
|
||||
for (uint8_t i = 0; i < 32; ++i)
|
||||
for (uint8_t i = 0; i < 16; ++i)
|
||||
{
|
||||
fixed_id = (fixed_id << 1) | (MProtocol_id & 1);
|
||||
MProtocol_id >>= 1;
|
||||
@@ -242,10 +272,8 @@ static void __attribute__((unused)) SFHSS_get_tx_id()
|
||||
run_count = 0;
|
||||
}
|
||||
// fixed_id = 0xBC11;
|
||||
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;
|
||||
rx_tx_addr[0] = fixed_id >> 8;
|
||||
rx_tx_addr[1] = fixed_id >> 0;
|
||||
}
|
||||
|
||||
uint16_t initSFHSS()
|
||||
|
||||
@@ -81,7 +81,7 @@ static void __attribute__((unused)) SYMAX_read_controls()
|
||||
if (Servo_AUX5)
|
||||
{
|
||||
flags |= SYMAX_FLAG_HEADLESS;
|
||||
flags &= ~SYMAX_XTRM_RATES; // Extended rates & headless incompatible
|
||||
flags &= ~SYMAX_XTRM_RATES; // Extended rates & headless incompatible
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ static void __attribute__((unused)) SYMAX_build_packet(uint8_t bind)
|
||||
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
|
||||
{ // use trims to extend controls
|
||||
packet[5] |= elevator >> 2;
|
||||
packet[6] |= rudder >> 2;
|
||||
packet[7] |= aileron >> 2;
|
||||
|
||||
@@ -20,54 +20,47 @@
|
||||
uint8_t RetrySequence ;
|
||||
|
||||
#if ( defined(MULTI_TELEMETRY) || defined(MULTI_STATUS) )
|
||||
#define MULTI_TIME 500 //in ms
|
||||
#define MULTI_TIME 500 //in ms
|
||||
#define INPUT_SYNC_TIME 100 //in ms
|
||||
#define INPUT_ADDITIONAL_DELAY 100 // in 10µs, 100 => 1000 µs
|
||||
uint32_t lastMulti = 0;
|
||||
#endif
|
||||
#endif // MULTI_TELEMETRY/MULTI_STATUS
|
||||
|
||||
#if defined SPORT_TELEMETRY
|
||||
#define SPORT_TIME 12000 //12ms
|
||||
#define SPORT_TIME 12000 //12ms
|
||||
#define FRSKY_SPORT_PACKET_SIZE 8
|
||||
#define FX_BUFFERS 4
|
||||
uint32_t last = 0;
|
||||
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] ;
|
||||
//} ;
|
||||
uint8_t pktx1[FRSKY_SPORT_PACKET_SIZE*FX_BUFFERS];
|
||||
|
||||
// Store for out of sequence packet
|
||||
//struct t_fx_rx_packet FrskyxRxTelemetry ;
|
||||
// Store for out of sequence packet
|
||||
uint8_t FrskyxRxTelemetryValidSequence ;
|
||||
struct t_fx_rx_frame
|
||||
{
|
||||
uint8_t valid ;
|
||||
uint8_t count ;
|
||||
uint8_t payload[6] ;
|
||||
} ;
|
||||
|
||||
uint8_t FrskyxRxTelemetryValidSequence ;
|
||||
// Store for FrskyX telemetry
|
||||
struct t_fx_rx_frame FrskyxRxFrames[4] ;
|
||||
uint8_t NextFxFrameToForward ;
|
||||
#endif // SPORT_TELEMETRY
|
||||
|
||||
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
|
||||
uint8_t prev_index;
|
||||
#endif
|
||||
#endif // HUB_TELEMETRY
|
||||
|
||||
#define START_STOP 0x7e
|
||||
#define BYTESTUFF 0x7d
|
||||
#define STUFF_MASK 0x20
|
||||
#define START_STOP 0x7e
|
||||
#define BYTESTUFF 0x7d
|
||||
#define STUFF_MASK 0x20
|
||||
#define MAX_PKTX 10
|
||||
uint8_t pktx[MAX_PKTX];
|
||||
uint8_t indx;
|
||||
uint8_t frame[18];
|
||||
|
||||
#if ( defined(MULTI_TELEMETRY) || defined(MULTI_STATUS) )
|
||||
@@ -85,30 +78,30 @@ static void multi_send_header(uint8_t type, uint8_t len)
|
||||
|
||||
static void multi_send_status()
|
||||
{
|
||||
multi_send_header(MULTI_TELEMETRY_STATUS, 5);
|
||||
multi_send_header(MULTI_TELEMETRY_STATUS, 5);
|
||||
|
||||
// Build flags
|
||||
uint8_t flags=0;
|
||||
if (IS_INPUT_SIGNAL_on)
|
||||
flags |= 0x01;
|
||||
if (mode_select==MODE_SERIAL)
|
||||
flags |= 0x02;
|
||||
if (remote_callback != 0)
|
||||
{
|
||||
flags |= 0x04;
|
||||
// Build flags
|
||||
uint8_t flags=0;
|
||||
if (IS_INPUT_SIGNAL_on)
|
||||
flags |= 0x01;
|
||||
if (mode_select==MODE_SERIAL)
|
||||
flags |= 0x02;
|
||||
if (remote_callback != 0)
|
||||
{
|
||||
flags |= 0x04;
|
||||
if (IS_WAIT_BIND_on)
|
||||
flags |= 0x10;
|
||||
else
|
||||
if (!IS_BIND_DONE_on)
|
||||
flags |= 0x08;
|
||||
}
|
||||
Serial_write(flags);
|
||||
Serial_write(flags);
|
||||
|
||||
// Version number example: 1.1.6.1
|
||||
Serial_write(VERSION_MAJOR);
|
||||
Serial_write(VERSION_MINOR);
|
||||
Serial_write(VERSION_REVISION);
|
||||
Serial_write(VERSION_PATCH_LEVEL);
|
||||
// Version number example: 1.1.6.1
|
||||
Serial_write(VERSION_MAJOR);
|
||||
Serial_write(VERSION_MINOR);
|
||||
Serial_write(VERSION_REVISION);
|
||||
Serial_write(VERSION_PATCH_LEVEL);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -156,9 +149,9 @@ static void multi_send_status()
|
||||
#ifdef MULTI_TELEMETRY
|
||||
static void multi_send_frskyhub()
|
||||
{
|
||||
multi_send_header(MULTI_TELEMETRY_HUB, 9);
|
||||
for (uint8_t i = 0; i < 9; i++)
|
||||
Serial_write(frame[i]);
|
||||
multi_send_header(MULTI_TELEMETRY_HUB, 9);
|
||||
for (uint8_t i = 0; i < 9; i++)
|
||||
Serial_write(frame[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -169,8 +162,8 @@ void frskySendStuffed()
|
||||
{
|
||||
if ((frame[i] == START_STOP) || (frame[i] == BYTESTUFF))
|
||||
{
|
||||
Serial_write(BYTESTUFF);
|
||||
frame[i] ^= STUFF_MASK;
|
||||
Serial_write(BYTESTUFF);
|
||||
frame[i] ^= STUFF_MASK;
|
||||
}
|
||||
Serial_write(frame[i]);
|
||||
}
|
||||
@@ -181,12 +174,8 @@ void frsky_check_telemetry(uint8_t *pkt,uint8_t len)
|
||||
{
|
||||
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
|
||||
RSSI_dBm = (((uint16_t)(pktt[len-2])*18)>>4);
|
||||
if(pktt[len-2] >=128) RSSI_dBm -= 164;
|
||||
else RSSI_dBm += 130;*/
|
||||
TX_RSSI = pkt[len-2];
|
||||
if(TX_RSSI >=128)
|
||||
TX_RSSI -= 128;
|
||||
@@ -204,12 +193,8 @@ void frsky_check_telemetry(uint8_t *pkt,uint8_t len)
|
||||
{
|
||||
uint8_t topBit = 0 ;
|
||||
if ( telemetry_counter & 0x80 )
|
||||
{
|
||||
if ( ( telemetry_counter & 0x1F ) != RetrySequence )
|
||||
{
|
||||
topBit = 0x80 ;
|
||||
}
|
||||
}
|
||||
telemetry_counter = ( (telemetry_counter+1)%32 ) | topBit ; // Request next telemetry frame
|
||||
}
|
||||
else
|
||||
@@ -222,28 +207,14 @@ void frsky_check_telemetry(uint8_t *pkt,uint8_t len)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pktt[6]=0; // Discard packet
|
||||
}
|
||||
//
|
||||
#if defined SPORT_TELEMETRY && defined FRSKYX_CC2500_INO
|
||||
telemetry_lost=0;
|
||||
if (protocol==MODE_FRSKYX)
|
||||
{
|
||||
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]) )
|
||||
{
|
||||
// Check if in sequence
|
||||
@@ -267,18 +238,12 @@ void frsky_check_telemetry(uint8_t *pkt,uint8_t len)
|
||||
{
|
||||
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 )
|
||||
@@ -287,24 +252,16 @@ void frsky_check_telemetry(uint8_t *pkt,uint8_t len)
|
||||
FrskyxRxTelemetryValidSequence &= 0x7F ;
|
||||
}
|
||||
|
||||
// if ( FrskyxRxTelemetry.validSequence & 0x80 )
|
||||
// {
|
||||
// FrX_receive_seq = ( FrskyxRxTelemetry.validSequence + 1 ) & 3 ;
|
||||
|
||||
// FrskyxRxTelemetry.validSequence &= 0x7F ;
|
||||
|
||||
// }
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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
|
||||
// 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 ) )
|
||||
{
|
||||
@@ -319,55 +276,18 @@ void frsky_check_telemetry(uint8_t *pkt,uint8_t len)
|
||||
}
|
||||
}
|
||||
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
|
||||
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
|
||||
}
|
||||
@@ -397,7 +317,7 @@ void frsky_link_frame()
|
||||
telemetry_link |= 2 ; // Send hub if available
|
||||
}
|
||||
else
|
||||
if (protocol==MODE_HUBSAN||protocol==MODE_AFHDS2A||protocol==MODE_BAYANG)
|
||||
if (protocol==MODE_HUBSAN||protocol==MODE_AFHDS2A||protocol==MODE_BAYANG||protocol==MODE_CABELL)
|
||||
{
|
||||
frame[1] = v_lipo1;
|
||||
frame[2] = v_lipo2;
|
||||
@@ -446,7 +366,7 @@ void frsky_user_frame()
|
||||
}
|
||||
else
|
||||
telemetry_link=0;
|
||||
}
|
||||
}
|
||||
/*
|
||||
HuB RX packets.
|
||||
pkt[6]|(counter++)|00 01 02 03 04 05 06 07 08 09
|
||||
@@ -514,23 +434,19 @@ pkt[6]|(counter++)|00 01 02 03 04 05 06 07 08 09
|
||||
|
||||
*/
|
||||
|
||||
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
|
||||
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 } ;
|
||||
void sportSend(uint8_t *p)
|
||||
{
|
||||
multi_send_header(MULTI_TELEMETRY_SPORT, 9);
|
||||
uint16_t crc_s = 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++)
|
||||
{
|
||||
@@ -540,8 +456,8 @@ const uint8_t PROGMEM Indices[] = { 0x00, 0xA1, 0x22, 0x83, 0xE4, 0x45,
|
||||
|
||||
if (i>0)
|
||||
{
|
||||
crc_s += p[i]; //0-1FF
|
||||
crc_s += crc_s >> 8; //0-100
|
||||
crc_s += p[i]; //0-1FF
|
||||
crc_s += crc_s >> 8; //0-100
|
||||
crc_s &= 0x00ff;
|
||||
}
|
||||
}
|
||||
@@ -661,7 +577,7 @@ void proces_sport_data(uint8_t data)
|
||||
pass = 1;
|
||||
break;
|
||||
}
|
||||
if(data == BYTESTUFF)//if they are stuffed
|
||||
if(data == BYTESTUFF) //if they are stuffed
|
||||
pass=2;
|
||||
else
|
||||
if (indx < MAX_PKTX)
|
||||
@@ -680,9 +596,7 @@ void proces_sport_data(uint8_t data)
|
||||
uint8_t dest = sport * FRSKY_SPORT_PACKET_SIZE ;
|
||||
uint8_t i ;
|
||||
for ( i = 0 ; i < FRSKY_SPORT_PACKET_SIZE ; i += 1 )
|
||||
{
|
||||
pktx1[dest++] = pktx[i] ; // Triple buffer
|
||||
}
|
||||
sport += 1 ;//ok to send
|
||||
}
|
||||
// else
|
||||
@@ -704,10 +618,9 @@ void TelemetryUpdate()
|
||||
h = SerialControl.head ;
|
||||
t = SerialControl.tail ;
|
||||
if ( h >= t )
|
||||
t += 192 - h ;
|
||||
t += TXBUFFER_SIZE - h ;
|
||||
else
|
||||
t -= h ;
|
||||
// if ( t < 32 )
|
||||
if ( t < 64 )
|
||||
{
|
||||
return ;
|
||||
@@ -741,9 +654,6 @@ 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 ;
|
||||
@@ -763,40 +673,12 @@ void TelemetryUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
// 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 ( 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();
|
||||
@@ -810,7 +692,7 @@ void TelemetryUpdate()
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif // SPORT_TELEMETRY
|
||||
|
||||
#if defined DSM_TELEMETRY
|
||||
if(telemetry_link && protocol == MODE_DSM)
|
||||
@@ -820,17 +702,17 @@ void TelemetryUpdate()
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if defined AFHDS2A_FW_TELEMETRY
|
||||
if(telemetry_link == 2 && protocol == MODE_AFHDS2A)
|
||||
#if defined AFHDS2A_FW_TELEMETRY
|
||||
if(telemetry_link == 2 && protocol == MODE_AFHDS2A)
|
||||
{
|
||||
AFHDSA_short_frame();
|
||||
telemetry_link=0;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if((telemetry_link & 1 )&& protocol != MODE_FRSKYX)
|
||||
{ // FrSkyD + Hubsan + AFHDS2A + Bayang
|
||||
{ // FrSkyD + Hubsan + AFHDS2A + Bayang + Cabell
|
||||
frsky_link_frame();
|
||||
return;
|
||||
}
|
||||
@@ -850,6 +732,19 @@ void TelemetryUpdate()
|
||||
/**************************/
|
||||
/**************************/
|
||||
|
||||
#ifdef SERIAL_DEBUG
|
||||
void StatusSerial_write(uint8_t data)
|
||||
{
|
||||
uint8_t nextHead ;
|
||||
nextHead = tx_debug_head + 1 ;
|
||||
if ( nextHead >= TXBUFFER_SIZE )
|
||||
nextHead = 0 ;
|
||||
tx_debug_buff[nextHead]=data;
|
||||
tx_debug_head = nextHead ;
|
||||
tx_debug_resume();
|
||||
}
|
||||
#endif // SERIAL_DEBUG
|
||||
|
||||
#ifndef BASH_SERIAL
|
||||
// Routines for normal serial output
|
||||
void Serial_write(uint8_t data)
|
||||
@@ -969,11 +864,34 @@ void TelemetryUpdate()
|
||||
#endif
|
||||
}
|
||||
#ifdef STM32_BOARD
|
||||
#if defined(SERIAL_DEBUG)
|
||||
void __irq_usart1()
|
||||
{ // Transmit interrupt
|
||||
if(USART1_BASE->SR & USART_SR_TXE)
|
||||
{
|
||||
if(tx_debug_head!=tx_debug_tail)
|
||||
{
|
||||
if(++tx_debug_tail>=TXBUFFER_SIZE) //head
|
||||
tx_debug_tail=0;
|
||||
USART1_BASE->DR=tx_debug_buff[tx_debug_tail]; //clears TXE bit
|
||||
}
|
||||
if (tx_debug_tail == tx_debug_head)
|
||||
tx_debug_pause(); // Check if all data is transmitted . if yes disable transmitter UDRE interrupt
|
||||
}
|
||||
}
|
||||
void usart1_begin(uint32_t baud,uint32_t config )
|
||||
{
|
||||
usart_init(USART1);
|
||||
usart_config_gpios_async(USART1,GPIOA,PIN_MAP[PA10].gpio_bit,GPIOA,PIN_MAP[PA9].gpio_bit,config);
|
||||
usart_set_baud_rate(USART1, STM32_PCLK1, baud);
|
||||
usart_enable(USART1);
|
||||
}
|
||||
#endif
|
||||
void usart2_begin(uint32_t baud,uint32_t config )
|
||||
{
|
||||
usart_init(USART2);
|
||||
usart_config_gpios_async(USART2,GPIOA,PIN_MAP[PA3].gpio_bit,GPIOA,PIN_MAP[PA2].gpio_bit,config);
|
||||
usart_set_baud_rate(USART2, STM32_PCLK1, baud);//
|
||||
usart_set_baud_rate(USART2, STM32_PCLK1, baud);
|
||||
usart_enable(USART2);
|
||||
}
|
||||
void usart3_begin(uint32_t baud,uint32_t config )
|
||||
@@ -1056,7 +974,9 @@ void Serial_write( uint8_t byte )
|
||||
#ifdef INVERT_SERIAL
|
||||
byte |= 1 ; // Start bit
|
||||
#endif
|
||||
uint8_t next = (SerialControl.head + 2) & 0x7f ;
|
||||
uint8_t next = SerialControl.head + 2;
|
||||
if(next>=TXBUFFER_SIZE)
|
||||
next=0;
|
||||
if ( next != SerialControl.tail )
|
||||
{
|
||||
SerialControl.data[SerialControl.head] = byte ;
|
||||
@@ -1120,9 +1040,7 @@ ISR(TIMER0_COMPA_vect)
|
||||
GPIOR1 = 3 ;
|
||||
}
|
||||
else
|
||||
{
|
||||
OCR0A += 20 ;
|
||||
}
|
||||
}
|
||||
|
||||
ISR(TIMER0_COMPB_vect)
|
||||
@@ -1150,12 +1068,9 @@ ISR(TIMER0_COMPB_vect)
|
||||
{
|
||||
GPIOR0 = ptr->data[ptr->tail] ;
|
||||
GPIOR2 = ptr->data[ptr->tail+1] ;
|
||||
uint8_t nextTail ;
|
||||
nextTail = ptr->tail + 2 ;
|
||||
if ( nextTail > 192 )
|
||||
{
|
||||
uint8_t nextTail = ptr->tail + 2 ;
|
||||
if ( nextTail >= TXBUFFER_SIZE )
|
||||
nextTail = 0 ;
|
||||
}
|
||||
ptr->tail = nextTail ;
|
||||
GPIOR1 = 8 ;
|
||||
OCR0A = OCR0B + 40 ;
|
||||
@@ -1170,44 +1085,36 @@ ISR(TIMER0_COMPB_vect)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
OCR0B += 20 ;
|
||||
}
|
||||
}
|
||||
|
||||
ISR(TIMER0_OVF_vect)
|
||||
{
|
||||
uint8_t byte ;
|
||||
if ( GPIOR1 > 2 )
|
||||
{
|
||||
byte = GPIOR0 ;
|
||||
}
|
||||
else
|
||||
{
|
||||
byte = GPIOR2 ;
|
||||
}
|
||||
if ( byte & 0x01 )
|
||||
SERIAL_TX_on;
|
||||
else
|
||||
SERIAL_TX_off;
|
||||
byte /= 2 ; // Generates shorter code than byte >>= 1
|
||||
if ( GPIOR1 > 2 )
|
||||
{
|
||||
GPIOR0 = byte ;
|
||||
}
|
||||
else
|
||||
{
|
||||
GPIOR2 = byte ;
|
||||
}
|
||||
if ( --GPIOR1 == 0 )
|
||||
{
|
||||
// prepare next byte
|
||||
{ // prepare next byte
|
||||
volatile struct t_serial_bash *ptr = &SerialControl ;
|
||||
if ( ptr->head != ptr->tail )
|
||||
{
|
||||
GPIOR0 = ptr->data[ptr->tail] ;
|
||||
GPIOR2 = ptr->data[ptr->tail+1] ;
|
||||
ptr->tail = ( ptr->tail + 2 ) & 0x7F ;
|
||||
uint8_t nextTail = ptr->tail + 2 ;
|
||||
if ( nextTail >= TXBUFFER_SIZE )
|
||||
nextTail = 0 ;
|
||||
ptr->tail = nextTail ;
|
||||
GPIOR1 = 10 ;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -79,6 +79,7 @@
|
||||
#undef Q303_NRF24L01_INO
|
||||
#undef GW008_NRF24L01_INO
|
||||
#undef DM002_NRF24L01_INO
|
||||
#undef CABELL_NRF24L01_INO
|
||||
#endif
|
||||
|
||||
//Make sure telemetry is selected correctly
|
||||
@@ -87,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
|
||||
@@ -100,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
|
||||
@@ -116,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
|
||||
|
||||
@@ -294,7 +294,7 @@ static void __attribute__((unused)) WK_build_beacon_pkt_2801()
|
||||
BIND_SET_PULLUP; // set pullup
|
||||
if(IS_BIND_BUTTON_on)
|
||||
{
|
||||
eeprom_write_byte((EE_ADDR)(30+mode_select),0x01); // Set fixed id mode for the current model
|
||||
eeprom_write_byte((EE_ADDR)(MODELMODE_EEPROM_OFFSET+mode_select),0x01); // Set fixed id mode for the current model
|
||||
option=1;
|
||||
}
|
||||
BIND_SET_OUTPUT;
|
||||
|
||||
@@ -139,10 +139,16 @@
|
||||
//#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
|
||||
/*
|
||||
@@ -208,7 +214,7 @@ const int8_t AFHDS2AFailsafe[14]= {
|
||||
//#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 ***/
|
||||
@@ -401,6 +407,11 @@ const PPM_Parameters PPM_prot[15]= {
|
||||
NONE
|
||||
MODE_DM002
|
||||
NONE
|
||||
MODE_CABELL
|
||||
CABELL_V3
|
||||
CABELL_V3_TELEMETRY
|
||||
CABELL_SET_FAIL_SAFE
|
||||
CABELL_UNBIND
|
||||
*/
|
||||
|
||||
// RX_Num is used for model match. Using RX_Num values different for each receiver will prevent starting a model with the false config loaded...
|
||||
|
||||
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