mirror of
https://github.com/iNavFlight/inav.git
synced 2025-07-24 16:55:29 +03:00
Tidy up of all nrf24 protocols.
This commit is contained in:
parent
04205e2cda
commit
dda73ff689
9 changed files with 580 additions and 306 deletions
2
Makefile
2
Makefile
|
@ -405,6 +405,8 @@ COMMON_SRC = \
|
|||
drivers/pwm_mapping.c \
|
||||
drivers/pwm_output.c \
|
||||
drivers/pwm_rx.c \
|
||||
drivers/rx_nrf24l01.c \
|
||||
drivers/rx_xn297.c \
|
||||
drivers/serial.c \
|
||||
drivers/serial_uart.c \
|
||||
drivers/sound_beeper.c \
|
||||
|
|
|
@ -383,6 +383,7 @@ static const char * const lookupTableSerialRX[] = {
|
|||
#endif
|
||||
|
||||
#ifdef USE_RX_NRF24
|
||||
// sync with nrf24_protocol_t
|
||||
static const char * const lookupTableNRF24RX[] = {
|
||||
"V202_250K",
|
||||
"V202_1M",
|
||||
|
@ -391,6 +392,7 @@ static const char * const lookupTableNRF24RX[] = {
|
|||
"CX10",
|
||||
"CX10A",
|
||||
"H8_3D",
|
||||
"H8_3D_DEV",
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ typedef enum {
|
|||
NRF24RX_CX10,
|
||||
NRF24RX_CX10A,
|
||||
NRF24RX_H8_3D,
|
||||
NRF24RX_H8_3D_DEVIATION,
|
||||
NRF24RX_PROTOCOL_COUNT
|
||||
} nrf24_protocol_t;
|
||||
|
||||
|
@ -61,6 +62,13 @@ typedef enum {
|
|||
NRF24_AUX14
|
||||
} nrf24_AETR_t;
|
||||
|
||||
// RC channels as used by deviation
|
||||
#define RC_CHANNEL_RATE NRF24_AUX1
|
||||
#define RC_CHANNEL_FLIP NRF24_AUX2
|
||||
#define RC_CHANNEL_PICTURE NRF24_AUX3
|
||||
#define RC_CHANNEL_VIDEO NRF24_AUX4
|
||||
#define RC_CHANNEL_HEADLESS NRF24_AUX5
|
||||
#define RC_CHANNEL_RTH NRF24_AUX6
|
||||
|
||||
bool rxNrf24DataReceived(void);
|
||||
bool rxNrf24Init(nfr24l01_spi_type_e spiType, const rxConfig_t *rxConfig, rxRuntimeConfig_t *rxRuntimeConfig, rcReadRawDataPtr *callback);
|
||||
|
|
|
@ -54,12 +54,13 @@
|
|||
* hops between 4 channels that are set from the txId sent in the bind packet
|
||||
*/
|
||||
|
||||
#define CX10_RC_CHANNEL_COUNT 9
|
||||
#define RC_CHANNEL_COUNT 9
|
||||
|
||||
#define CX10_PROTOCOL_PAYLOAD_SIZE 15
|
||||
#define CX10A_PROTOCOL_PAYLOAD_SIZE 19
|
||||
|
||||
#define CX10_RF_BIND_CHANNEL 0x02
|
||||
enum {
|
||||
RATE_LOW = 0,
|
||||
RATE_MID = 1,
|
||||
RATE_HIGH= 2,
|
||||
};
|
||||
|
||||
#define FLAG_FLIP 0x10 // goes to rudder channel
|
||||
// flags1
|
||||
|
@ -79,10 +80,10 @@ typedef enum {
|
|||
|
||||
STATIC_UNIT_TESTED protocol_state_t protocolState;
|
||||
|
||||
|
||||
|
||||
#define ACK_TO_SEND_COUNT 8
|
||||
#define CX10_PROTOCOL_PAYLOAD_SIZE 15
|
||||
#define CX10A_PROTOCOL_PAYLOAD_SIZE 19
|
||||
static uint8_t payloadSize;
|
||||
#define ACK_TO_SEND_COUNT 8
|
||||
|
||||
#define RX_TX_ADDR_LEN 5
|
||||
//STATIC_UNIT_TESTED uint8_t rxTxAddr[RX_TX_ADDR_LEN] = {0xcc, 0xcc, 0xcc, 0xcc, 0xcc};
|
||||
|
@ -91,46 +92,20 @@ STATIC_UNIT_TESTED uint8_t rxAddr[RX_TX_ADDR_LEN] = {0x49, 0x26, 0x87, 0x7d, 0x2
|
|||
#define TX_ID_LEN 4
|
||||
STATIC_UNIT_TESTED uint8_t txId[TX_ID_LEN];
|
||||
|
||||
STATIC_UNIT_TESTED uint8_t cx10RfChannelIndex = 0;
|
||||
#define CX10_RF_BIND_CHANNEL 0x02
|
||||
#define RF_CHANNEL_COUNT 4
|
||||
STATIC_UNIT_TESTED uint8_t cx10RfChannelIndex = 0;
|
||||
STATIC_UNIT_TESTED uint8_t cx10RfChannels[RF_CHANNEL_COUNT]; // channels are set using txId from bind packet
|
||||
|
||||
static uint32_t timeOfLastHop;
|
||||
static const uint32_t hopTimeout = 5000; // 5ms
|
||||
|
||||
void cx10Nrf24Init(nrf24_protocol_t protocol)
|
||||
{
|
||||
cx10Protocol = protocol;
|
||||
protocolState = STATE_BIND;
|
||||
payloadSize = (protocol == NRF24RX_CX10) ? CX10_PROTOCOL_PAYLOAD_SIZE : CX10A_PROTOCOL_PAYLOAD_SIZE;
|
||||
|
||||
NRF24L01_Initialize(0); // sets PWR_UP, no CRC
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0);
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, BV(NRF24L01_02_EN_RXADDR_ERX_P0)); // Enable data pipe 0 only
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, NRF24L01_03_SETUP_AW_5BYTES); // 5-byte RX/TX address
|
||||
NRF24L01_SetChannel(CX10_RF_BIND_CHANNEL);
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, NRF24L01_06_RF_SETUP_RF_DR_1Mbps | NRF24L01_06_RF_SETUP_RF_PWR_n12dbm);
|
||||
// RX_ADDR for pipes P2 to P5 are left at default values
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, txAddr, RX_TX_ADDR_LEN);
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rxAddr, RX_TX_ADDR_LEN);
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_08_OBSERVE_TX, 0x00);
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, payloadSize + 2); // payload + 2 bytes CRC
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
|
||||
|
||||
NRF24L01_SetRxMode(); // enter receive mode to start listening for packets
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if it is a bind packet.
|
||||
*/
|
||||
STATIC_UNIT_TESTED bool cx10CheckBindPacket(const uint8_t *packet)
|
||||
{
|
||||
const bool bindPacket = (packet[0] == 0xaa);
|
||||
const bool bindPacket = (packet[0] == 0xaa); // 10101010
|
||||
if (bindPacket) {
|
||||
txId[0] = packet[1];
|
||||
txId[1] = packet[2];
|
||||
|
@ -157,22 +132,22 @@ void cx10SetRcDataFromPayload(uint16_t *rcData, const uint8_t *payload)
|
|||
rcData[NRF24_YAW] = cx10ConvertToPwmUnsigned(&payload[11 + offset]); // rudder
|
||||
const uint8_t flags1 = payload[13 + offset];
|
||||
const uint8_t rate = flags1 & FLAG_MODE_MASK; // takes values 0, 1, 2
|
||||
if (rate == 0) {
|
||||
rcData[NRF24_AUX1] = PWM_RANGE_MIN;
|
||||
} else if (rate == 1) {
|
||||
rcData[NRF24_AUX1] = PWM_RANGE_MIDDLE;
|
||||
if (rate == RATE_LOW) {
|
||||
rcData[RC_CHANNEL_RATE] = PWM_RANGE_MIN;
|
||||
} else if (rate == RATE_MID) {
|
||||
rcData[RC_CHANNEL_RATE] = PWM_RANGE_MIDDLE;
|
||||
} else {
|
||||
rcData[NRF24_AUX1] = PWM_RANGE_MAX;
|
||||
rcData[RC_CHANNEL_RATE] = PWM_RANGE_MAX;
|
||||
}
|
||||
// flip flag is in YAW byte
|
||||
rcData[NRF24_AUX2] = payload[12 + offset] & FLAG_FLIP ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
rcData[RC_CHANNEL_FLIP] = payload[12 + offset] & FLAG_FLIP ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
const uint8_t flags2 = payload[14 + offset];
|
||||
rcData[NRF24_AUX3] = flags2 & FLAG_PICTURE ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
rcData[NRF24_AUX4] = flags2 & FLAG_VIDEO ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
rcData[NRF24_AUX5] = flags1 & FLAG_HEADLESS ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
rcData[RC_CHANNEL_PICTURE] = flags2 & FLAG_PICTURE ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
rcData[RC_CHANNEL_VIDEO] = flags2 & FLAG_VIDEO ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
rcData[RC_CHANNEL_HEADLESS] = flags1 & FLAG_HEADLESS ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
}
|
||||
|
||||
static void hopToNextChannel(void)
|
||||
static void cx10HopToNextChannel(void)
|
||||
{
|
||||
++cx10RfChannelIndex;
|
||||
if (cx10RfChannelIndex >= RF_CHANNEL_COUNT) {
|
||||
|
@ -182,7 +157,7 @@ static void hopToNextChannel(void)
|
|||
}
|
||||
|
||||
// The hopping channels are determined by the txId
|
||||
STATIC_UNIT_TESTED void setHoppingChannels(const uint8_t* txId)
|
||||
STATIC_UNIT_TESTED void cx10SetHoppingChannels(const uint8_t* txId)
|
||||
{
|
||||
cx10RfChannelIndex = 0;
|
||||
cx10RfChannels[0] = 0x03 + (txId[0] & 0x0F);
|
||||
|
@ -209,7 +184,7 @@ nrf24_received_t cx10DataReceived(uint8_t *payload)
|
|||
const bool bindPacket = cx10CheckBindPacket(payload);
|
||||
if (bindPacket) {
|
||||
// set the hopping channels as determined by the txId received in the bind packet
|
||||
setHoppingChannels(txId);
|
||||
cx10SetHoppingChannels(txId);
|
||||
ret = NRF24_RECEIVED_BIND;
|
||||
protocolState = STATE_ACK;
|
||||
ackCount = 0;
|
||||
|
@ -259,21 +234,48 @@ nrf24_received_t cx10DataReceived(uint8_t *payload)
|
|||
// read the payload, processing of payload is deferred
|
||||
if (NRF24L01_ReadPayloadIfAvailable(payload, payloadSize + 2)) {
|
||||
XN297_UnscramblePayload(payload, payloadSize + 2);
|
||||
hopToNextChannel();
|
||||
cx10HopToNextChannel();
|
||||
timeOfLastHop = timeNowUs;
|
||||
ret = NRF24_RECEIVED_DATA;
|
||||
}
|
||||
if (timeNowUs > timeOfLastHop + hopTimeout) {
|
||||
hopToNextChannel();
|
||||
cx10HopToNextChannel();
|
||||
timeOfLastHop = timeNowUs;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void cx10Nrf24Init(nrf24_protocol_t protocol)
|
||||
{
|
||||
cx10Protocol = protocol;
|
||||
protocolState = STATE_BIND;
|
||||
payloadSize = (protocol == NRF24RX_CX10) ? CX10_PROTOCOL_PAYLOAD_SIZE : CX10A_PROTOCOL_PAYLOAD_SIZE;
|
||||
|
||||
NRF24L01_Initialize(0); // sets PWR_UP, no CRC
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0);
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, BV(NRF24L01_02_EN_RXADDR_ERX_P0)); // Enable data pipe 0 only
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, NRF24L01_03_SETUP_AW_5BYTES); // 5-byte RX/TX address
|
||||
NRF24L01_SetChannel(CX10_RF_BIND_CHANNEL);
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, NRF24L01_06_RF_SETUP_RF_DR_1Mbps | NRF24L01_06_RF_SETUP_RF_PWR_n12dbm);
|
||||
// RX_ADDR for pipes P2 to P5 are left at default values
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, txAddr, RX_TX_ADDR_LEN);
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rxAddr, RX_TX_ADDR_LEN);
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_08_OBSERVE_TX, 0x00);
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, payloadSize + 2); // payload + 2 bytes CRC
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
|
||||
|
||||
NRF24L01_SetRxMode(); // enter receive mode to start listening for packets
|
||||
}
|
||||
|
||||
void cx10Init(const rxConfig_t *rxConfig, rxRuntimeConfig_t *rxRuntimeConfig)
|
||||
{
|
||||
rxRuntimeConfig->channelCount = CX10_RC_CHANNEL_COUNT;
|
||||
rxRuntimeConfig->channelCount = RC_CHANNEL_COUNT;
|
||||
cx10Nrf24Init((nrf24_protocol_t)rxConfig->nrf24rx_protocol);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -56,11 +56,7 @@
|
|||
* hops between 4 channels generated from txId received in bind packets
|
||||
*
|
||||
*/
|
||||
#define H8_3D_RC_CHANNEL_COUNT 14
|
||||
|
||||
#define H8_3D_X_PROTOCOL_PAYLOAD_SIZE 20
|
||||
|
||||
#define H8_3D_RF_CHANNEL_COUNT 4
|
||||
#define RC_CHANNEL_COUNT 14
|
||||
|
||||
#define FLAG_FLIP 0x01
|
||||
#define FLAG_RATE_MID 0x02
|
||||
|
@ -72,6 +68,8 @@
|
|||
#define FLAG_CAMERA_UP 0x04 // on payload[18]
|
||||
#define FLAG_CAMERA_DOWN 0x08 // on payload[18]
|
||||
|
||||
STATIC_UNIT_TESTED nrf24_protocol_t h8_3dProtocol;
|
||||
|
||||
typedef enum {
|
||||
STATE_BIND = 0,
|
||||
STATE_DATA
|
||||
|
@ -79,6 +77,7 @@ typedef enum {
|
|||
|
||||
STATIC_UNIT_TESTED protocol_state_t protocolState;
|
||||
|
||||
#define H8_3D_PROTOCOL_PAYLOAD_SIZE 20
|
||||
STATIC_UNIT_TESTED uint8_t payloadSize;
|
||||
|
||||
#define RX_TX_ADDR_LEN 5
|
||||
|
@ -88,8 +87,9 @@ STATIC_UNIT_TESTED uint8_t rxTxAddrXN297[RX_TX_ADDR_LEN] = {0x41, 0xbd, 0x42, 0x
|
|||
STATIC_UNIT_TESTED uint8_t txId[TX_ID_LEN];
|
||||
|
||||
// radio channels for frequency hopping
|
||||
STATIC_UNIT_TESTED uint8_t h8_3dRfChannelIndex;
|
||||
#define H8_3D_RF_CHANNEL_COUNT 4
|
||||
STATIC_UNIT_TESTED uint8_t h8_3dRfChannelCount = H8_3D_RF_CHANNEL_COUNT;
|
||||
STATIC_UNIT_TESTED uint8_t h8_3dRfChannelIndex;
|
||||
STATIC_UNIT_TESTED uint8_t h8_3dRfChannels[H8_3D_RF_CHANNEL_COUNT];
|
||||
#define H8_3D_RF_BIND_CHANNEL_START 0x06
|
||||
#define H8_3D_RF_BIND_CHANNEL_END 0x26
|
||||
|
@ -99,37 +99,6 @@ STATIC_UNIT_TESTED uint8_t h8_3dRfChannels[H8_3D_RF_CHANNEL_COUNT];
|
|||
static uint32_t hopTimeout = BIND_HOP_TIMEOUT;
|
||||
static uint32_t timeOfLastHop;
|
||||
|
||||
void h8_3dSetBound(const uint8_t* txId);
|
||||
|
||||
void h8_3dNrf24Init(nrf24_protocol_t protocol, const uint8_t* nrf24_id)
|
||||
{
|
||||
UNUSED(protocol);
|
||||
protocolState = STATE_BIND;
|
||||
|
||||
NRF24L01_Initialize(0); // sets PWR_UP, no CRC
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0); // No auto acknowledgment
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, BV(NRF24L01_02_EN_RXADDR_ERX_P0));
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, NRF24L01_03_SETUP_AW_5BYTES); // 5-byte RX/TX address
|
||||
NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, NRF24L01_06_RF_SETUP_RF_DR_1Mbps | NRF24L01_06_RF_SETUP_RF_PWR_n12dbm);
|
||||
// RX_ADDR for pipes P1-P5 are left at default values
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rxTxAddrXN297, RX_TX_ADDR_LEN);
|
||||
if ((nrf24_id[0] | nrf24_id[1] | nrf24_id[2] | nrf24_id[3]) == 0) {
|
||||
h8_3dRfChannelIndex = H8_3D_RF_BIND_CHANNEL_START;
|
||||
NRF24L01_SetChannel(H8_3D_RF_BIND_CHANNEL_START);
|
||||
} else {
|
||||
h8_3dSetBound(nrf24_id);
|
||||
}
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_08_OBSERVE_TX, 0x00);
|
||||
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
|
||||
|
||||
payloadSize = H8_3D_X_PROTOCOL_PAYLOAD_SIZE + 2; // payload + 2 bytes CRC
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, payloadSize); // payload + 2 bytes CRC
|
||||
|
||||
NRF24L01_SetRxMode(); // enter receive mode to start listening for packets
|
||||
}
|
||||
|
||||
STATIC_UNIT_TESTED bool h8_3dCheckBindPacket(const uint8_t *payload)
|
||||
{
|
||||
bool bindPacket = false;
|
||||
|
@ -164,12 +133,19 @@ void h8_3dSetRcDataFromPayload(uint16_t *rcData, const uint8_t *payload)
|
|||
const uint8_t flags = payload[17];
|
||||
const uint8_t flags2 = payload[18];
|
||||
if (flags & FLAG_RATE_HIGH) {
|
||||
rcData[NRF24_AUX1] = PWM_RANGE_MAX;
|
||||
rcData[RC_CHANNEL_RATE] = PWM_RANGE_MAX;
|
||||
} else if (flags & FLAG_RATE_MID) {
|
||||
rcData[NRF24_AUX1] = PWM_RANGE_MIDDLE;
|
||||
rcData[RC_CHANNEL_RATE] = PWM_RANGE_MIDDLE;
|
||||
} else {
|
||||
rcData[NRF24_AUX1] = PWM_RANGE_MIN;
|
||||
rcData[RC_CHANNEL_RATE] = PWM_RANGE_MIN;
|
||||
}
|
||||
|
||||
rcData[RC_CHANNEL_FLIP] = flags & FLAG_FLIP ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
rcData[RC_CHANNEL_PICTURE] = flags2 & FLAG_PICTURE ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
rcData[RC_CHANNEL_VIDEO] = flags2 & FLAG_VIDEO ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
rcData[RC_CHANNEL_HEADLESS] = flags & FLAG_HEADLESS ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
rcData[RC_CHANNEL_RTH] = flags & FLAG_RTH ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
|
||||
if (flags2 & FLAG_CAMERA_UP) {
|
||||
rcData[NRF24_AUX7] = PWM_RANGE_MAX;
|
||||
} else if (flags2 & FLAG_CAMERA_DOWN) {
|
||||
|
@ -177,17 +153,12 @@ void h8_3dSetRcDataFromPayload(uint16_t *rcData, const uint8_t *payload)
|
|||
} else {
|
||||
rcData[NRF24_AUX7] = PWM_RANGE_MIDDLE;
|
||||
}
|
||||
rcData[NRF24_AUX2] = flags & FLAG_FLIP ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
rcData[NRF24_AUX3] = flags2 & FLAG_PICTURE ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
rcData[NRF24_AUX4] = flags2 & FLAG_VIDEO ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
rcData[NRF24_AUX5] = flags & FLAG_HEADLESS ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
rcData[NRF24_AUX6] = flags & FLAG_RTH ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
rcData[NRF24_AUX8] = h8_3dConvertToPwm(payload[14], 0x10, 0x30);
|
||||
rcData[NRF24_AUX9] = h8_3dConvertToPwm(payload[15], 0x30, 0x10);
|
||||
rcData[NRF24_AUX10] = h8_3dConvertToPwm(payload[16], 0x10, 0x30);
|
||||
}
|
||||
|
||||
static void hopToNextChannel(void)
|
||||
static void h8_3dHopToNextChannel(void)
|
||||
{
|
||||
++h8_3dRfChannelIndex;
|
||||
if (protocolState == STATE_BIND) {
|
||||
|
@ -206,23 +177,24 @@ static void hopToNextChannel(void)
|
|||
// The hopping channels are determined by the txId
|
||||
void h8_3dSetHoppingChannels(const uint8_t* txId)
|
||||
{
|
||||
h8_3dRfChannels[0] = 0x06 + ((txId[0]>>4) +(txId[0] & 0x0f)) % 0x0f;
|
||||
h8_3dRfChannels[1] = 0x15 + ((txId[1]>>4) +(txId[1] & 0x0f)) % 0x0f;
|
||||
// Kludge to allow bugged deviation TX H8_3D implementation to work
|
||||
//h8_3dRfChannels[2] = 0x24 + ((txId[2]>>4) +(txId[2] & 0x0f)) % 0x0f;
|
||||
//h8_3dRfChannels[3] = 0x33 + ((txId[3]>>4) +(txId[3] & 0x0f)) % 0x0f;
|
||||
h8_3dRfChannels[2] = 0x06 + ((txId[0]>>8) +(txId[0] & 0x0f)) % 0x0f;
|
||||
h8_3dRfChannels[3] = 0x15 + ((txId[1]>>8) +(txId[1] & 0x0f)) % 0x0f;
|
||||
const int bitShift = h8_3dProtocol == NRF24RX_H8_3D_DEVIATION ? 8 : 4;
|
||||
h8_3dRfChannels[0] = 0x06 + ((txId[0]>>bitShift) +(txId[0] & 0x0f)) % 0x0f;
|
||||
h8_3dRfChannels[1] = 0x15 + ((txId[1]>>bitShift) +(txId[1] & 0x0f)) % 0x0f;
|
||||
h8_3dRfChannels[2] = 0x24 + ((txId[2]>>bitShift) +(txId[2] & 0x0f)) % 0x0f;
|
||||
h8_3dRfChannels[3] = 0x33 + ((txId[3]>>bitShift) +(txId[3] & 0x0f)) % 0x0f;
|
||||
}
|
||||
|
||||
void h8_3dSetBound(const uint8_t* txId)
|
||||
{
|
||||
h8_3dSetHoppingChannels(txId);
|
||||
protocolState = STATE_DATA;
|
||||
h8_3dSetHoppingChannels(txId);
|
||||
hopTimeout = DATA_HOP_TIMEOUT;
|
||||
timeOfLastHop = micros();
|
||||
h8_3dRfChannelIndex = 0;
|
||||
NRF24L01_SetChannel(h8_3dRfChannels[0]);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called periodically by the scheduler.
|
||||
* Returns NRF24L01_RECEIVED_DATA if a data packet was received.
|
||||
|
@ -230,11 +202,6 @@ void h8_3dSetBound(const uint8_t* txId)
|
|||
nrf24_received_t h8_3dDataReceived(uint8_t *payload)
|
||||
{
|
||||
nrf24_received_t ret = NRF24_RECEIVED_NONE;
|
||||
const uint32_t timeNow = micros();
|
||||
if (timeNow > timeOfLastHop + hopTimeout) {
|
||||
hopToNextChannel();
|
||||
timeOfLastHop = timeNow;
|
||||
}
|
||||
switch (protocolState) {
|
||||
case STATE_BIND:
|
||||
if (NRF24L01_ReadPayloadIfAvailable(payload, payloadSize)) {
|
||||
|
@ -250,18 +217,50 @@ nrf24_received_t h8_3dDataReceived(uint8_t *payload)
|
|||
// read the payload, processing of payload is deferred
|
||||
if (NRF24L01_ReadPayloadIfAvailable(payload, payloadSize)) {
|
||||
XN297_UnscramblePayload(payload, payloadSize);
|
||||
hopToNextChannel();
|
||||
timeOfLastHop = timeNow;
|
||||
ret = NRF24_RECEIVED_DATA;
|
||||
}
|
||||
break;
|
||||
}
|
||||
const uint32_t timeNowUs = micros();
|
||||
if ((ret == NRF24_RECEIVED_DATA) || (timeNowUs > timeOfLastHop + hopTimeout)) {
|
||||
h8_3dHopToNextChannel();
|
||||
timeOfLastHop = timeNowUs;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void h8_3dNrf24Init(nrf24_protocol_t protocol, const uint8_t* nrf24_id)
|
||||
{
|
||||
h8_3dProtocol = protocol;
|
||||
protocolState = STATE_BIND;
|
||||
|
||||
NRF24L01_Initialize(0); // sets PWR_UP, no CRC
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0); // No auto acknowledgment
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, BV(NRF24L01_02_EN_RXADDR_ERX_P0));
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, NRF24L01_03_SETUP_AW_5BYTES); // 5-byte RX/TX address
|
||||
NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, NRF24L01_06_RF_SETUP_RF_DR_1Mbps | NRF24L01_06_RF_SETUP_RF_PWR_n12dbm);
|
||||
// RX_ADDR for pipes P1-P5 are left at default values
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rxTxAddrXN297, RX_TX_ADDR_LEN);
|
||||
if ((nrf24_id[0] | nrf24_id[1] | nrf24_id[2] | nrf24_id[3]) == 0) {
|
||||
h8_3dRfChannelIndex = H8_3D_RF_BIND_CHANNEL_START;
|
||||
NRF24L01_SetChannel(H8_3D_RF_BIND_CHANNEL_START);
|
||||
} else {
|
||||
h8_3dSetBound(nrf24_id);
|
||||
}
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_08_OBSERVE_TX, 0x00);
|
||||
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
|
||||
|
||||
payloadSize = H8_3D_PROTOCOL_PAYLOAD_SIZE + 2; // payload + 2 bytes CRC
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, payloadSize); // payload + 2 bytes CRC
|
||||
|
||||
NRF24L01_SetRxMode(); // enter receive mode to start listening for packets
|
||||
}
|
||||
|
||||
void h8_3dInit(const rxConfig_t *rxConfig, rxRuntimeConfig_t *rxRuntimeConfig)
|
||||
{
|
||||
rxRuntimeConfig->channelCount = H8_3D_RC_CHANNEL_COUNT;
|
||||
rxRuntimeConfig->channelCount = RC_CHANNEL_COUNT;
|
||||
h8_3dNrf24Init((nrf24_protocol_t)rxConfig->nrf24rx_protocol, rxConfig->nrf24rx_id);
|
||||
}
|
||||
#endif
|
||||
|
|
250
src/main/rx/nrf24_ref.c
Normal file
250
src/main/rx/nrf24_ref.c
Normal file
|
@ -0,0 +1,250 @@
|
|||
/*
|
||||
* This file is part of Cleanflight.
|
||||
*
|
||||
* Cleanflight 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.
|
||||
*
|
||||
* Cleanflight 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 Cleanflight. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "platform.h"
|
||||
#include "build_config.h"
|
||||
|
||||
#ifdef USE_RX_REF
|
||||
|
||||
#include "drivers/rx_nrf24l01.h"
|
||||
#include "drivers/system.h"
|
||||
|
||||
#include "rx/nrf24.h"
|
||||
//#include "rx/nrf24_ref.h"
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Reference Protocol
|
||||
* No auto acknowledgment
|
||||
* Data rate is 250Kbps - lower data rate for better reliability and range
|
||||
* Payload size is 16, static, small payload is read more quickly (marginal benefit)
|
||||
*
|
||||
* Bind Phase
|
||||
* uses address {0x4b,0x5c,0x6d,0x7e,0x8f}
|
||||
* uses channel 0x4c
|
||||
*
|
||||
* Data Phase
|
||||
* uses address received in bind packet
|
||||
* hops between 4 channels generated from address received in bind packet
|
||||
*/
|
||||
|
||||
#define RC_CHANNEL_COUNT 16
|
||||
|
||||
enum {
|
||||
RATE_LOW = 0,
|
||||
RATE_MID = 1,
|
||||
RATE_HIGH = 2,
|
||||
};
|
||||
|
||||
enum {
|
||||
FLAG_FLIP = 0x01,
|
||||
FLAG_PICTURE = 0x02,
|
||||
FLAG_VIDEO = 0x04,
|
||||
FLAG_RTH = 0x08,
|
||||
FLAG_HEADLESS = 0x10,
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
STATE_BIND = 0,
|
||||
STATE_DATA
|
||||
} protocol_state_t;
|
||||
|
||||
STATIC_UNIT_TESTED protocol_state_t protocolState;
|
||||
|
||||
#define REF_PROTOCOL_PAYLOAD_SIZE 16
|
||||
STATIC_UNIT_TESTED const uint8_t payloadSize = REF_PROTOCOL_PAYLOAD_SIZE;
|
||||
|
||||
#define RX_TX_ADDR_LEN 5
|
||||
// set rxTxAddr to the bind values
|
||||
STATIC_UNIT_TESTED uint8_t rxTxAddr[RX_TX_ADDR_LEN] = {0x4b,0x5c,0x6d,0x7e,0x8f};
|
||||
|
||||
// radio channels for frequency hopping
|
||||
#define REF_RF_CHANNEL_COUNT 4
|
||||
STATIC_UNIT_TESTED const uint8_t refRfChannelCount = REF_RF_CHANNEL_COUNT;
|
||||
STATIC_UNIT_TESTED uint8_t refRfChannelIndex;
|
||||
STATIC_UNIT_TESTED uint8_t refRfChannels[REF_RF_CHANNEL_COUNT];
|
||||
#define REF_RF_BIND_CHANNEL 0x4c
|
||||
|
||||
//static uint32_t packetCount = 0;
|
||||
static uint32_t timeOfLastHop;
|
||||
static const uint32_t hopTimeout = 5000; // 5ms
|
||||
|
||||
STATIC_UNIT_TESTED bool refCheckBindPacket(const uint8_t *payload)
|
||||
{
|
||||
bool bindPacket = false;
|
||||
if (payload[0] == 0xae && payload[1] == 0xc9) {
|
||||
bindPacket = true;
|
||||
rxTxAddr[0] = payload[2];
|
||||
rxTxAddr[1] = payload[3];
|
||||
rxTxAddr[2] = payload[4];
|
||||
rxTxAddr[3] = payload[5];
|
||||
rxTxAddr[4] = payload[6];
|
||||
}
|
||||
return bindPacket;
|
||||
}
|
||||
|
||||
void refSetRcDataFromPayload(uint16_t *rcData, const uint8_t *payload)
|
||||
{
|
||||
// the AETR channels have 10 bit resolution
|
||||
uint8_t lowBits = payload[6]; // least significant bits for AETR
|
||||
rcData[NRF24_ROLL] = PWM_RANGE_MIN + ((payload[2] << 2) | (lowBits & 0x03)); // Aileron
|
||||
lowBits >>= 2;
|
||||
rcData[NRF24_PITCH] = PWM_RANGE_MIN + ((payload[3] << 2) | (lowBits & 0x03)); // Elevator
|
||||
lowBits >>= 2;
|
||||
rcData[NRF24_THROTTLE] = PWM_RANGE_MIN + ((payload[4] << 2) | (lowBits & 0x03)); // Throttle
|
||||
lowBits >>= 2;
|
||||
rcData[NRF24_YAW] = PWM_RANGE_MIN + ((payload[5] << 2) | (lowBits & 0x03)); // Rudder
|
||||
|
||||
// channel AUX1 is used for rate, as per the deviation convention
|
||||
const uint8_t rate = payload[7];
|
||||
if (rate == RATE_HIGH) {
|
||||
rcData[RC_CHANNEL_RATE] = PWM_RANGE_MAX;
|
||||
} else if (rate == RATE_MID) {
|
||||
rcData[RC_CHANNEL_RATE] = PWM_RANGE_MIDDLE;
|
||||
} else {
|
||||
rcData[RC_CHANNEL_RATE] = PWM_RANGE_MIN;
|
||||
}
|
||||
|
||||
// channels AUX2 to AUX7 use the deviation convention
|
||||
const uint8_t flags = payload[8];
|
||||
rcData[RC_CHANNEL_FLIP]= (flags & FLAG_FLIP) ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
rcData[RC_CHANNEL_PICTURE]= (flags & FLAG_PICTURE) ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
rcData[RC_CHANNEL_VIDEO]= (flags & FLAG_VIDEO) ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
rcData[RC_CHANNEL_HEADLESS]= (flags & FLAG_HEADLESS) ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
rcData[RC_CHANNEL_RTH]= (flags & FLAG_RTH) ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
|
||||
// channels AUX7 to AUX10 have 10 bit resolution
|
||||
lowBits = payload[13]; // least significant bits for AUX7 to AUX10
|
||||
rcData[NRF24_AUX7] = PWM_RANGE_MIN + ((payload[9] << 2) | (lowBits & 0x03));
|
||||
lowBits >>= 2;
|
||||
rcData[NRF24_AUX8] = PWM_RANGE_MIN + ((payload[10] << 2) | (lowBits & 0x03));
|
||||
lowBits >>= 2;
|
||||
rcData[NRF24_AUX9] = PWM_RANGE_MIN + ((payload[11] << 2) | (lowBits & 0x03));
|
||||
lowBits >>= 2;
|
||||
rcData[NRF24_AUX10] = PWM_RANGE_MIN + ((payload[12] << 2) | (lowBits & 0x03));
|
||||
lowBits >>= 2;
|
||||
|
||||
// channels AUX11 and AUX12 have 8 bit resolution
|
||||
rcData[NRF24_AUX11] = PWM_RANGE_MIN + (payload[14] << 2);
|
||||
rcData[NRF24_AUX12] = PWM_RANGE_MIN + (payload[15] << 2);
|
||||
}
|
||||
|
||||
static void refHopToNextChannel(void)
|
||||
{
|
||||
++refRfChannelIndex;
|
||||
if (refRfChannelIndex >= refRfChannelCount) {
|
||||
refRfChannelIndex = 0;
|
||||
}
|
||||
NRF24L01_SetChannel(refRfChannels[refRfChannelIndex]);
|
||||
}
|
||||
|
||||
// The hopping channels are determined by the low bits of rxTxAddr
|
||||
STATIC_UNIT_TESTED void refSetHoppingChannels(uint32_t addr)
|
||||
{
|
||||
addr = addr & 0x1f;
|
||||
const uint32_t inc = (addr << 24) | (addr << 16) | (addr << 8) | addr;
|
||||
uint32_t * const prfChannels = (uint32_t *)refRfChannels;
|
||||
*prfChannels = 0x10314259 + inc;
|
||||
}
|
||||
|
||||
void refSetBound(const uint8_t* rxTxAddr)
|
||||
{
|
||||
protocolState = STATE_DATA;
|
||||
refSetHoppingChannels(rxTxAddr[0]);
|
||||
timeOfLastHop = micros();
|
||||
refRfChannelIndex = 0;
|
||||
NRF24L01_SetChannel(refRfChannels[0]);
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rxTxAddr, RX_TX_ADDR_LEN);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called periodically by the scheduler.
|
||||
* Returns NRF24L01_RECEIVED_DATA if a data packet was received.
|
||||
*/
|
||||
nrf24_received_t refDataReceived(uint8_t *payload)
|
||||
{
|
||||
nrf24_received_t ret = NRF24_RECEIVED_NONE;
|
||||
uint32_t timeNowUs;
|
||||
switch (protocolState) {
|
||||
case STATE_BIND:
|
||||
if (NRF24L01_ReadPayloadIfAvailable(payload, payloadSize)) {
|
||||
const bool bindPacket = refCheckBindPacket(payload);
|
||||
if (bindPacket) {
|
||||
ret = NRF24_RECEIVED_BIND;
|
||||
// got a bind packet, so set the hopping channels and the rxTxAddr and start listening for data
|
||||
refSetBound(rxTxAddr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case STATE_DATA:
|
||||
timeNowUs = micros();
|
||||
// read the payload, processing of payload is deferred
|
||||
if (NRF24L01_ReadPayloadIfAvailable(payload, payloadSize)) {
|
||||
ret = NRF24_RECEIVED_DATA;
|
||||
}
|
||||
if ((ret == NRF24_RECEIVED_DATA) || (timeNowUs > timeOfLastHop + hopTimeout)) {
|
||||
refHopToNextChannel();
|
||||
timeOfLastHop = timeNowUs;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void refNrf24Init(nrf24_protocol_t protocol, const uint8_t* nrf24_id)
|
||||
{
|
||||
UNUSED(protocol);
|
||||
|
||||
NRF24L01_Initialize(BV(NRF24L01_00_CONFIG_EN_CRC) | BV( NRF24L01_00_CONFIG_CRCO)); // sets PWR_UP, EN_CRC, CRCO - 2 byte CRC
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No auto acknowledgment
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, BV(NRF24L01_02_EN_RXADDR_ERX_P0));
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, NRF24L01_03_SETUP_AW_5BYTES); // 5-byte RX/TX address
|
||||
if ((nrf24_id[0] | nrf24_id[1] | nrf24_id[2] | nrf24_id[3] | nrf24_id[4]) == 0) {
|
||||
protocolState = STATE_BIND;
|
||||
NRF24L01_SetChannel(REF_RF_BIND_CHANNEL);
|
||||
} else {
|
||||
rxTxAddr[0] = nrf24_id[0];
|
||||
rxTxAddr[1] = nrf24_id[1];
|
||||
rxTxAddr[2] = nrf24_id[2];
|
||||
rxTxAddr[3] = nrf24_id[3];
|
||||
rxTxAddr[4] = nrf24_id[4];
|
||||
refSetBound(nrf24_id);
|
||||
}
|
||||
NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, NRF24L01_06_RF_SETUP_RF_DR_250Kbps | NRF24L01_06_RF_SETUP_RF_PWR_n12dbm);
|
||||
// RX_ADDR for pipes P1-P5 are left at default values
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rxTxAddr, RX_TX_ADDR_LEN);
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_08_OBSERVE_TX, 0x00);
|
||||
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, payloadSize);
|
||||
NRF24L01_SetRxMode(); // enter receive mode to start listening for packets
|
||||
}
|
||||
|
||||
void refInit(const rxConfig_t *rxConfig, rxRuntimeConfig_t *rxRuntimeConfig)
|
||||
{
|
||||
rxRuntimeConfig->channelCount = RC_CHANNEL_COUNT;
|
||||
refNrf24Init((nrf24_protocol_t)rxConfig->nrf24rx_protocol, rxConfig->nrf24rx_id);
|
||||
}
|
||||
#endif
|
||||
|
|
@ -66,26 +66,23 @@
|
|||
* (common channels between both phases are: 0x27, 0x39, 0x24, 0x22, 0x2d)
|
||||
*/
|
||||
|
||||
#define SYMA_RC_CHANNEL_COUNT 9
|
||||
#define RC_CHANNEL_COUNT 9
|
||||
|
||||
#define SYMA_X_PROTOCOL_PAYLOAD_SIZE 10
|
||||
#define SYMA_X5C_PROTOCOL_PAYLOAD_SIZE 16
|
||||
enum {
|
||||
RATE_LOW = 0,
|
||||
RATE_MID = 1,
|
||||
RATE_HIGH= 2,
|
||||
};
|
||||
|
||||
#define SYMA_X_RF_BIND_CHANNEL 8
|
||||
#define SYMA_X_RF_CHANNEL_COUNT 4
|
||||
#define FLAG_PICTURE 0x40
|
||||
#define FLAG_VIDEO 0x80
|
||||
#define FLAG_FLIP 0x40
|
||||
#define FLAG_HEADLESS 0x80
|
||||
|
||||
#define SYMA_X5C_RF_BIND_CHANNEL_COUNT 16
|
||||
#define SYMA_X5C_RF_CHANNEL_COUNT 15
|
||||
|
||||
#define FLAG_PICTURE 0x40
|
||||
#define FLAG_VIDEO 0x80
|
||||
#define FLAG_FLIP 0x40
|
||||
#define FLAG_HEADLESS 0x80
|
||||
|
||||
#define FLAG_FLIP_X5C 0x01
|
||||
#define FLAG_FLIP_X5C 0x01
|
||||
#define FLAG_PICTURE_X5C 0x08
|
||||
#define FLAG_VIDEO_X5C 0x10
|
||||
#define FLAG_RATE_X5C 0x04
|
||||
#define FLAG_VIDEO_X5C 0x10
|
||||
#define FLAG_RATE_X5C 0x04
|
||||
|
||||
STATIC_UNIT_TESTED nrf24_protocol_t symaProtocol;
|
||||
|
||||
|
@ -97,6 +94,8 @@ typedef enum {
|
|||
STATIC_UNIT_TESTED protocol_state_t protocolState;
|
||||
|
||||
// X11, X12, X5C-1 have 10-byte payload, X5C has 16-byte payload
|
||||
#define SYMA_X_PROTOCOL_PAYLOAD_SIZE 10
|
||||
#define SYMA_X5C_PROTOCOL_PAYLOAD_SIZE 16
|
||||
STATIC_UNIT_TESTED uint8_t payloadSize;
|
||||
|
||||
#define RX_TX_ADDR_LEN 5
|
||||
|
@ -105,16 +104,170 @@ STATIC_UNIT_TESTED uint8_t rxTxAddr[RX_TX_ADDR_LEN] = {0xab, 0xac, 0xad, 0xae, 0
|
|||
STATIC_UNIT_TESTED const uint8_t rxTxAddrX5C[RX_TX_ADDR_LEN] = {0x6d, 0x6a, 0x73, 0x73, 0x73}; // X5C uses same address for bind and data
|
||||
|
||||
// radio channels for frequency hopping
|
||||
static int packetCount = 0;
|
||||
STATIC_UNIT_TESTED uint8_t symaRfChannelIndex = 0;
|
||||
#define SYMA_X_RF_BIND_CHANNEL 8
|
||||
#define SYMA_X_RF_CHANNEL_COUNT 4
|
||||
#define SYMA_X5C_RF_BIND_CHANNEL_COUNT 16
|
||||
#define SYMA_X5C_RF_CHANNEL_COUNT 15
|
||||
|
||||
STATIC_UNIT_TESTED uint8_t symaRfChannelCount = SYMA_X_RF_CHANNEL_COUNT;
|
||||
STATIC_UNIT_TESTED uint8_t symaRfChannelIndex = 0;
|
||||
// set rfChannels to SymaX bind channels, reserve enough space for SymaX5C channels
|
||||
STATIC_UNIT_TESTED uint8_t symaRfChannels[SYMA_X5C_RF_BIND_CHANNEL_COUNT] = {0x4b, 0x30, 0x40, 0x20};
|
||||
STATIC_UNIT_TESTED const uint8_t symaRfChannelsX5C[SYMA_X5C_RF_CHANNEL_COUNT] = {0x1d, 0x2f, 0x26, 0x3d, 0x15, 0x2b, 0x25, 0x24, 0x27, 0x2c, 0x1c, 0x3e, 0x39, 0x2d, 0x22};
|
||||
|
||||
static uint32_t packetCount = 0;
|
||||
static uint32_t timeOfLastHop;
|
||||
static uint32_t hopTimeout = 10000; // 10ms
|
||||
|
||||
STATIC_UNIT_TESTED bool symaCheckBindPacket(const uint8_t *packet)
|
||||
{
|
||||
bool bindPacket = false;
|
||||
if (symaProtocol == NRF24RX_SYMA_X) {
|
||||
if ((packet[5] == 0xaa) && (packet[6] == 0xaa) && (packet[7] == 0xaa)) {
|
||||
bindPacket = true;
|
||||
rxTxAddr[4] = packet[0];
|
||||
rxTxAddr[3] = packet[1];
|
||||
rxTxAddr[2] = packet[2];
|
||||
rxTxAddr[1] = packet[3];
|
||||
rxTxAddr[0] = packet[4];
|
||||
}
|
||||
} else {
|
||||
if ((packet[0] == 0) && (packet[1] == 0) && (packet[14] == 0xc0) && (packet[15] == 0x17)) {
|
||||
bindPacket = true;
|
||||
}
|
||||
}
|
||||
return bindPacket;
|
||||
}
|
||||
|
||||
STATIC_UNIT_TESTED uint16_t symaConvertToPwmUnsigned(uint8_t val)
|
||||
{
|
||||
uint32_t ret = val;
|
||||
ret = ret * (PWM_RANGE_MAX - PWM_RANGE_MIN) / UINT8_MAX + PWM_RANGE_MIN;
|
||||
return (uint16_t)ret;
|
||||
}
|
||||
|
||||
STATIC_UNIT_TESTED uint16_t symaConvertToPwmSigned(uint8_t val)
|
||||
{
|
||||
int32_t ret = val & 0x7f;
|
||||
ret = (ret * (PWM_RANGE_MAX - PWM_RANGE_MIN)) / (2 * INT8_MAX);
|
||||
if (val & 0x80) {// sign bit set
|
||||
ret = -ret;
|
||||
}
|
||||
return (uint16_t)(PWM_RANGE_MIDDLE + ret);
|
||||
}
|
||||
|
||||
void symaSetRcDataFromPayload(uint16_t *rcData, const uint8_t *packet)
|
||||
{
|
||||
rcData[NRF24_THROTTLE] = symaConvertToPwmUnsigned(packet[0]); // throttle
|
||||
rcData[NRF24_ROLL] = symaConvertToPwmSigned(packet[3]); // aileron
|
||||
if (symaProtocol == NRF24RX_SYMA_X) {
|
||||
rcData[NRF24_PITCH] = symaConvertToPwmSigned(packet[1]); // elevator
|
||||
rcData[NRF24_YAW] = symaConvertToPwmSigned(packet[2]); // rudder
|
||||
const uint8_t rate = (packet[5] & 0xc0) >> 6;
|
||||
if (rate == RATE_LOW) {
|
||||
rcData[RC_CHANNEL_RATE] = PWM_RANGE_MIN;
|
||||
} else if (rate == RATE_MID) {
|
||||
rcData[RC_CHANNEL_RATE] = PWM_RANGE_MIDDLE;
|
||||
} else {
|
||||
rcData[RC_CHANNEL_RATE] = PWM_RANGE_MAX;
|
||||
}
|
||||
rcData[RC_CHANNEL_FLIP] = packet[6] & FLAG_FLIP ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
rcData[RC_CHANNEL_PICTURE] = packet[4] & FLAG_PICTURE ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
rcData[RC_CHANNEL_VIDEO] = packet[4] & FLAG_VIDEO ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
rcData[RC_CHANNEL_HEADLESS] = packet[14] & FLAG_HEADLESS ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
} else {
|
||||
rcData[NRF24_PITCH] = symaConvertToPwmSigned(packet[2]); // elevator
|
||||
rcData[NRF24_YAW] = symaConvertToPwmSigned(packet[1]); // rudder
|
||||
const uint8_t flags = packet[14];
|
||||
rcData[RC_CHANNEL_RATE] = flags & FLAG_RATE_X5C ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
rcData[RC_CHANNEL_FLIP] = flags & FLAG_FLIP_X5C ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
rcData[RC_CHANNEL_PICTURE] = flags & FLAG_PICTURE_X5C ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
rcData[RC_CHANNEL_VIDEO] = flags & FLAG_VIDEO_X5C ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
}
|
||||
}
|
||||
|
||||
static void symaHopToNextChannel(void)
|
||||
{
|
||||
// hop channel every second packet
|
||||
++packetCount;
|
||||
if ((packetCount & 0x01) == 0) {
|
||||
++symaRfChannelIndex;
|
||||
if (symaRfChannelIndex >= symaRfChannelCount) {
|
||||
symaRfChannelIndex = 0;
|
||||
}
|
||||
}
|
||||
NRF24L01_SetChannel(symaRfChannels[symaRfChannelIndex]);
|
||||
}
|
||||
|
||||
// The SymaX hopping channels are determined by the low bits of rxTxAddress
|
||||
void setSymaXHoppingChannels(uint32_t addr)
|
||||
{
|
||||
addr = addr & 0x1f;
|
||||
if (addr == 0x06) {
|
||||
addr = 0x07;
|
||||
}
|
||||
const uint32_t inc = (addr << 24) | (addr << 16) | (addr << 8) | addr;
|
||||
uint32_t * const prfChannels = (uint32_t *)symaRfChannels;
|
||||
if (addr == 0x16) {
|
||||
*prfChannels = 0x28481131;
|
||||
} else if (addr == 0x1e) {
|
||||
*prfChannels = 0x38184121;
|
||||
} else if (addr < 0x10) {
|
||||
*prfChannels = 0x3A2A1A0A + inc;
|
||||
} else if (addr < 0x18) {
|
||||
*prfChannels = 0x1231FA1A + inc;
|
||||
} else {
|
||||
*prfChannels = 0x19FA2202 + inc;
|
||||
}
|
||||
}
|
||||
|
||||
void symaSetBound(const uint8_t* rxTxAddr)
|
||||
{
|
||||
protocolState = STATE_DATA;
|
||||
// using protocol NRF24L01_SYMA_X, since NRF24L01_SYMA_X5C went straight into data mode
|
||||
// set the hopping channels as determined by the rxTxAddr received in the bind packet
|
||||
setSymaXHoppingChannels(rxTxAddr[0]);
|
||||
timeOfLastHop = micros();
|
||||
packetCount = 0;
|
||||
// set the NRF24 to use the rxTxAddr received in the bind packet
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rxTxAddr, RX_TX_ADDR_LEN);
|
||||
symaRfChannelIndex = 0;
|
||||
NRF24L01_SetChannel(symaRfChannels[0]);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called periodically by the scheduler.
|
||||
* Returns NRF24_RECEIVED_DATA if a data packet was received.
|
||||
*/
|
||||
nrf24_received_t symaDataReceived(uint8_t *payload)
|
||||
{
|
||||
nrf24_received_t ret = NRF24_RECEIVED_NONE;
|
||||
uint32_t timeNowUs;
|
||||
switch (protocolState) {
|
||||
case STATE_BIND:
|
||||
if (NRF24L01_ReadPayloadIfAvailable(payload, payloadSize)) {
|
||||
const bool bindPacket = symaCheckBindPacket(payload);
|
||||
if (bindPacket) {
|
||||
ret = NRF24_RECEIVED_BIND;
|
||||
symaSetBound(rxTxAddr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case STATE_DATA:
|
||||
// read the payload, processing of payload is deferred
|
||||
if (NRF24L01_ReadPayloadIfAvailable(payload, payloadSize)) {
|
||||
ret = NRF24_RECEIVED_DATA;
|
||||
}
|
||||
timeNowUs = micros();
|
||||
if ((ret == NRF24_RECEIVED_DATA) || (timeNowUs > timeOfLastHop + hopTimeout)) {
|
||||
symaHopToNextChannel();
|
||||
timeOfLastHop = timeNowUs;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void symaNrf24Init(nrf24_protocol_t protocol)
|
||||
{
|
||||
symaProtocol = protocol;
|
||||
|
@ -149,152 +302,9 @@ void symaNrf24Init(nrf24_protocol_t protocol)
|
|||
NRF24L01_SetRxMode(); // enter receive mode to start listening for packets
|
||||
}
|
||||
|
||||
STATIC_UNIT_TESTED uint16_t symaConvertToPwmUnsigned(uint8_t val)
|
||||
{
|
||||
uint32_t ret = val;
|
||||
ret = ret * (PWM_RANGE_MAX - PWM_RANGE_MIN) / UINT8_MAX + PWM_RANGE_MIN;
|
||||
return (uint16_t)ret;
|
||||
}
|
||||
|
||||
STATIC_UNIT_TESTED uint16_t symaConvertToPwmSigned(uint8_t val)
|
||||
{
|
||||
int32_t ret = val & 0x7f;
|
||||
ret = (ret * (PWM_RANGE_MAX - PWM_RANGE_MIN)) / (2 * INT8_MAX);
|
||||
if (val & 0x80) {// sign bit set
|
||||
ret = -ret;
|
||||
}
|
||||
return (uint16_t)(PWM_RANGE_MIDDLE + ret);
|
||||
}
|
||||
|
||||
STATIC_UNIT_TESTED bool symaCheckBindPacket(const uint8_t *packet)
|
||||
{
|
||||
bool bindPacket = false;
|
||||
if (symaProtocol == NRF24RX_SYMA_X) {
|
||||
if ((packet[5] == 0xaa) && (packet[6] == 0xaa) && (packet[7] == 0xaa)) {
|
||||
bindPacket = true;
|
||||
rxTxAddr[4] = packet[0];
|
||||
rxTxAddr[3] = packet[1];
|
||||
rxTxAddr[2] = packet[2];
|
||||
rxTxAddr[1] = packet[3];
|
||||
rxTxAddr[0] = packet[4];
|
||||
}
|
||||
} else {
|
||||
if ((packet[0] == 0) && (packet[1] == 0) && (packet[14] == 0xc0) && (packet[15] == 0x17)) {
|
||||
bindPacket = true;
|
||||
}
|
||||
}
|
||||
return bindPacket;
|
||||
}
|
||||
|
||||
void symaSetRcDataFromPayload(uint16_t *rcData, const uint8_t *packet)
|
||||
{
|
||||
rcData[NRF24_THROTTLE] = symaConvertToPwmUnsigned(packet[0]); // throttle
|
||||
rcData[NRF24_ROLL] = symaConvertToPwmSigned(packet[3]); // aileron
|
||||
if (symaProtocol == NRF24RX_SYMA_X) {
|
||||
rcData[NRF24_PITCH] = symaConvertToPwmSigned(packet[1]); // elevator
|
||||
rcData[NRF24_YAW] = symaConvertToPwmSigned(packet[2]); // rudder
|
||||
const uint8_t rate = (packet[5] & 0xc0) >> 6; // takes values 0, 1, 2
|
||||
if (rate == 0) {
|
||||
rcData[NRF24_AUX1] = PWM_RANGE_MIN;
|
||||
} else if (rate == 1) {
|
||||
rcData[NRF24_AUX1] = PWM_RANGE_MIDDLE;
|
||||
} else {
|
||||
rcData[NRF24_AUX1] = PWM_RANGE_MAX;
|
||||
}
|
||||
rcData[NRF24_AUX2] = packet[6] & FLAG_FLIP ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
rcData[NRF24_AUX3] = packet[4] & FLAG_PICTURE ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
rcData[NRF24_AUX4] = packet[4] & FLAG_VIDEO ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
rcData[NRF24_AUX5] = packet[14] & FLAG_HEADLESS ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
} else {
|
||||
rcData[NRF24_PITCH] = symaConvertToPwmSigned(packet[2]); // elevator
|
||||
rcData[NRF24_YAW] = symaConvertToPwmSigned(packet[1]); // rudder
|
||||
const uint8_t flags = packet[14];
|
||||
rcData[NRF24_AUX1] = flags & FLAG_RATE_X5C ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
rcData[NRF24_AUX2] = flags & FLAG_FLIP_X5C ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
rcData[NRF24_AUX3] = flags & FLAG_PICTURE_X5C ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
rcData[NRF24_AUX4] = flags & FLAG_VIDEO_X5C ? PWM_RANGE_MAX : PWM_RANGE_MIN;
|
||||
}
|
||||
}
|
||||
|
||||
static void hopToNextChannel(void)
|
||||
{
|
||||
// hop channel every second packet
|
||||
++packetCount;
|
||||
if ((packetCount & 0x01) == 0) {
|
||||
++symaRfChannelIndex;
|
||||
if (symaRfChannelIndex >= symaRfChannelCount) {
|
||||
symaRfChannelIndex = 0;
|
||||
}
|
||||
}
|
||||
NRF24L01_SetChannel(symaRfChannels[symaRfChannelIndex]);
|
||||
}
|
||||
|
||||
// The SymaX hopping channels are determined by the low bits of rxTxAddress
|
||||
void setSymaXHoppingChannels(uint32_t addr)
|
||||
{
|
||||
addr = addr & 0x1f;
|
||||
if (addr == 0x06) {
|
||||
addr = 0x07;
|
||||
}
|
||||
const uint32_t inc = (addr << 24) | (addr << 16) | (addr << 8) | addr;
|
||||
uint32_t * const prfChannels = (uint32_t *)symaRfChannels;
|
||||
if (addr == 0x16) {
|
||||
*prfChannels = 0x28481131;
|
||||
} else if (addr == 0x1e) {
|
||||
*prfChannels = 0x38184121;
|
||||
} else if (addr < 0x10) {
|
||||
*prfChannels = 0x3A2A1A0A + inc;
|
||||
} else if (addr < 0x18) {
|
||||
*prfChannels = 0x1231FA1A + inc;
|
||||
} else {
|
||||
*prfChannels = 0x19FA2202 + inc;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called periodically by the scheduler.
|
||||
* Returns NRF24_RECEIVED_DATA if a data packet was received.
|
||||
*/
|
||||
nrf24_received_t symaDataReceived(uint8_t *payload)
|
||||
{
|
||||
nrf24_received_t ret = NRF24_RECEIVED_NONE;
|
||||
switch (protocolState) {
|
||||
case STATE_BIND:
|
||||
if (NRF24L01_ReadPayloadIfAvailable(payload, payloadSize)) {
|
||||
const bool bindPacket = symaCheckBindPacket(payload);
|
||||
if (bindPacket) {
|
||||
ret = NRF24_RECEIVED_BIND;
|
||||
protocolState = STATE_DATA;
|
||||
// using protocol NRF24L01_SYMA_X, since NRF24L01_SYMA_X5C went straight into data mode
|
||||
// set the hopping channels as determined by the rxTxAddr received in the bind packet
|
||||
setSymaXHoppingChannels(rxTxAddr[0]);
|
||||
// set the NRF24 to use the rxTxAddr received in the bind packet
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rxTxAddr, RX_TX_ADDR_LEN);
|
||||
packetCount = 0;
|
||||
symaRfChannelIndex = 0;
|
||||
NRF24L01_SetChannel(symaRfChannels[0]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case STATE_DATA:
|
||||
// read the payload, processing of payload is deferred
|
||||
if (NRF24L01_ReadPayloadIfAvailable(payload, payloadSize)) {
|
||||
hopToNextChannel();
|
||||
timeOfLastHop = micros();
|
||||
ret = NRF24_RECEIVED_DATA;
|
||||
}
|
||||
if (micros() > timeOfLastHop + hopTimeout) {
|
||||
hopToNextChannel();
|
||||
timeOfLastHop = micros();
|
||||
}
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void symaInit(const rxConfig_t *rxConfig, rxRuntimeConfig_t *rxRuntimeConfig)
|
||||
{
|
||||
rxRuntimeConfig->channelCount = SYMA_RC_CHANNEL_COUNT;
|
||||
rxRuntimeConfig->channelCount = RC_CHANNEL_COUNT;
|
||||
symaNrf24Init((nrf24_protocol_t)rxConfig->nrf24rx_protocol);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -116,37 +116,6 @@ static void switch_channel(void)
|
|||
if (++rf_ch_num >= V2X2_NFREQCHANNELS) rf_ch_num = 0;
|
||||
}
|
||||
|
||||
void v202Nrf24Init(nrf24_protocol_t protocol)
|
||||
{
|
||||
NRF24L01_Initialize(BV(NRF24L01_00_CONFIG_EN_CRC) | BV(NRF24L01_00_CONFIG_CRCO)); // 2-bytes CRC
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowledgment
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, BV(NRF24L01_02_EN_RXADDR_ERX_P0)); // Enable data pipe 0
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, NRF24L01_03_SETUP_AW_5BYTES); // 5-byte RX/TX address
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0xFF); // 4ms retransmit t/o, 15 tries
|
||||
if (protocol == NRF24RX_V202_250K) {
|
||||
NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, NRF24L01_06_RF_SETUP_RF_DR_250Kbps | NRF24L01_06_RF_SETUP_RF_PWR_n12dbm);
|
||||
} else {
|
||||
NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, NRF24L01_06_RF_SETUP_RF_DR_1Mbps | NRF24L01_06_RF_SETUP_RF_PWR_n12dbm);
|
||||
}
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, BV(NRF24L01_07_STATUS_RX_DR) | BV(NRF24L01_07_STATUS_TX_DS) | BV(NRF24L01_07_STATUS_MAX_RT)); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, V2X2_PAYLOAD_SIZE); // bytes of data payload for pipe 0
|
||||
NRF24L01_WriteReg(NRF24L01_17_FIFO_STATUS, 0x00); // Just in case, no real bits to write here
|
||||
#define RX_TX_ADDR_LEN 5
|
||||
const uint8_t rx_tx_addr[RX_TX_ADDR_LEN] = {0x66, 0x88, 0x68, 0x68, 0x68};
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_tx_addr, RX_TX_ADDR_LEN);
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, RX_TX_ADDR_LEN);
|
||||
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
|
||||
rf_ch_num = 0;
|
||||
bind_phase = PHASE_NOT_BOUND;
|
||||
prepare_to_bind();
|
||||
switch_channel();
|
||||
NRF24L01_SetRxMode(); // enter receive mode to start listening for packets
|
||||
}
|
||||
|
||||
void v2x2_set_tx_id(uint8_t *id)
|
||||
{
|
||||
uint8_t sum;
|
||||
|
@ -249,6 +218,37 @@ nrf24_received_t v202DataReceived(uint8_t *packet)
|
|||
return readrx(packet);
|
||||
}
|
||||
|
||||
void v202Nrf24Init(nrf24_protocol_t protocol)
|
||||
{
|
||||
NRF24L01_Initialize(BV(NRF24L01_00_CONFIG_EN_CRC) | BV(NRF24L01_00_CONFIG_CRCO)); // 2-bytes CRC
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowledgment
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, BV(NRF24L01_02_EN_RXADDR_ERX_P0)); // Enable data pipe 0
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, NRF24L01_03_SETUP_AW_5BYTES); // 5-byte RX/TX address
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0xFF); // 4ms retransmit t/o, 15 tries
|
||||
if (protocol == NRF24RX_V202_250K) {
|
||||
NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, NRF24L01_06_RF_SETUP_RF_DR_250Kbps | NRF24L01_06_RF_SETUP_RF_PWR_n12dbm);
|
||||
} else {
|
||||
NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, NRF24L01_06_RF_SETUP_RF_DR_1Mbps | NRF24L01_06_RF_SETUP_RF_PWR_n12dbm);
|
||||
}
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, BV(NRF24L01_07_STATUS_RX_DR) | BV(NRF24L01_07_STATUS_TX_DS) | BV(NRF24L01_07_STATUS_MAX_RT)); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, V2X2_PAYLOAD_SIZE); // bytes of data payload for pipe 0
|
||||
NRF24L01_WriteReg(NRF24L01_17_FIFO_STATUS, 0x00); // Just in case, no real bits to write here
|
||||
#define RX_TX_ADDR_LEN 5
|
||||
const uint8_t rx_tx_addr[RX_TX_ADDR_LEN] = {0x66, 0x88, 0x68, 0x68, 0x68};
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_tx_addr, RX_TX_ADDR_LEN);
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, RX_TX_ADDR_LEN);
|
||||
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
|
||||
rf_ch_num = 0;
|
||||
bind_phase = PHASE_NOT_BOUND;
|
||||
prepare_to_bind();
|
||||
switch_channel();
|
||||
NRF24L01_SetRxMode(); // enter receive mode to start listening for packets
|
||||
}
|
||||
|
||||
void v202Init(const rxConfig_t *rxConfig, rxRuntimeConfig_t *rxRuntimeConfig)
|
||||
{
|
||||
rxRuntimeConfig->channelCount = V2X2_RC_CHANNEL_COUNT;
|
||||
|
|
|
@ -103,6 +103,7 @@
|
|||
#define USE_RX_V202
|
||||
#define USE_RX_CX10
|
||||
#define USE_RX_H8_3D
|
||||
#define USE_RX_REF
|
||||
#endif
|
||||
//#define NRF24_DEFAULT_PROTOCOL NRF24RX_SYMA_X5C
|
||||
//#define NRF24_DEFAULT_PROTOCOL NRF24RX_V202_1M
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue