323 lines
8.2 KiB
Arduino
Raw Normal View History

2015-12-30 01:41:12 +01:00
/*
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,
2015-12-30 01:41:12 +01:00
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/
// Compatible with EAchine H8 mini, H10, BayangToys X6/X7/X9, JJRC JJ850 ...
// Last sync with hexfet new_protocols/bayang_nrf24l01.c dated 2015-12-22
2015-12-30 01:41:12 +01:00
#if defined(BAYANG_NRF24L01_INO)
#include "iface_nrf24l01.h"
#define BAYANG_BIND_COUNT 1000
#define BAYANG_PACKET_PERIOD 1000
2015-12-30 01:41:12 +01:00
#define BAYANG_INITIAL_WAIT 500
#define BAYANG_PACKET_SIZE 15
#define BAYANG_RF_NUM_CHANNELS 4
#define BAYANG_RF_BIND_CHANNEL 0
2017-11-20 16:01:12 +01:00
#define BAYANG_RF_BIND_CHANNEL_X16_AH 10
2015-12-30 01:41:12 +01:00
#define BAYANG_ADDRESS_LENGTH 5
enum BAYANG_FLAGS {
2017-11-20 16:01:12 +01:00
// flags going to packet[2]
BAYANG_FLAG_RTH = 0x01,
BAYANG_FLAG_HEADLESS = 0x02,
BAYANG_FLAG_FLIP = 0x08,
BAYANG_FLAG_VIDEO = 0x10,
BAYANG_FLAG_PICTURE = 0x20,
// flags going to packet[3]
BAYANG_FLAG_INVERTED = 0x80, // inverted flight on Floureon H101
BAYANG_FLAG_TAKE_OFF = 0x20, // take off / landing on X16 AH
BAYANG_FLAG_EMG_STOP = 0x04,
2015-12-30 01:41:12 +01:00
};
static void __attribute__((unused)) BAYANG_send_packet(uint8_t bind)
2015-12-30 01:41:12 +01:00
{
uint8_t i;
if (bind)
{
#ifdef BAYANG_HUB_TELEMETRY
if(option)
packet[0]= 0xA3; // telemetry is enabled
else
#endif
packet[0]= 0xA4;
2015-12-30 01:41:12 +01:00
for(i=0;i<5;i++)
packet[i+1]=rx_tx_addr[i];
for(i=0;i<4;i++)
packet[i+6]=hopping_frequency[i];
2017-11-20 16:01:12 +01:00
switch (sub_protocol)
{
case X16_AH:
packet[10] = 0x00;
packet[11] = 0x00;
break;
case IRDRONE:
packet[10] = 0x30;
packet[11] = 0x01;
break;
2017-11-20 16:01:12 +01:00
default:
packet[10] = rx_tx_addr[0]; // txid[0]
packet[11] = rx_tx_addr[1]; // txid[1]
break;
}
2015-12-30 01:41:12 +01:00
}
else
{
uint16_t val;
2017-12-01 15:02:24 +01:00
uint8_t dyntrim = 1;
switch (sub_protocol)
{
2017-11-20 16:01:12 +01:00
case X16_AH:
case IRDRONE:
2017-11-20 16:01:12 +01:00
packet[0] = 0xA6;
break;
default:
packet[0] = 0xA5;
break;
}
2015-12-30 01:41:12 +01:00
packet[1] = 0xFA; // normal mode is 0xf7, expert 0xfa
//Flags packet[2]
packet[2] = 0x00;
if(Servo_AUX1)
packet[2] = BAYANG_FLAG_FLIP;
if(Servo_AUX2)
2015-12-30 01:41:12 +01:00
packet[2] |= BAYANG_FLAG_RTH;
if(Servo_AUX3)
packet[2] |= BAYANG_FLAG_PICTURE;
if(Servo_AUX4)
packet[2] |= BAYANG_FLAG_VIDEO;
if(Servo_AUX5)
2017-12-01 15:02:24 +01:00
{
packet[2] |= BAYANG_FLAG_HEADLESS;
2017-12-01 15:02:24 +01:00
dyntrim = 0;
}
//Flags packet[3]
2015-12-30 01:41:12 +01:00
packet[3] = 0x00;
if(Servo_AUX6)
packet[3] = BAYANG_FLAG_INVERTED;
2017-11-20 16:01:12 +01:00
if(Servo_AUX7)
2017-12-01 15:02:24 +01:00
dyntrim = 0;
if(Servo_AUX8)
2017-12-01 15:02:24 +01:00
packet[3] |= BAYANG_FLAG_TAKE_OFF;
if(Servo_AUX9)
packet[3] |= BAYANG_FLAG_EMG_STOP;
2015-12-30 01:41:12 +01:00
//Aileron
val = convert_channel_10b(AILERON);
2017-12-01 15:02:24 +01:00
packet[4] = (val>>8) + (dyntrim ? ((val>>2) & 0xFC) : 0x7C);
2015-12-30 01:41:12 +01:00
packet[5] = val & 0xFF;
//Elevator
val = convert_channel_10b(ELEVATOR);
2017-12-01 15:02:24 +01:00
packet[6] = (val>>8) + (dyntrim ? ((val>>2) & 0xFC) : 0x7C);
2015-12-30 01:41:12 +01:00
packet[7] = val & 0xFF;
//Throttle
val = convert_channel_10b(THROTTLE);
packet[8] = (val>>8) + 0x7C;
packet[9] = val & 0xFF;
//Rudder
val = convert_channel_10b(RUDDER);
2017-12-01 15:02:24 +01:00
packet[10] = (val>>8) + (dyntrim ? ((val>>2) & 0xFC) : 0x7C);
2015-12-30 01:41:12 +01:00
packet[11] = val & 0xFF;
}
2017-11-20 16:01:12 +01:00
switch (sub_protocol)
{
case H8S3D:
packet[12] = rx_tx_addr[2]; // txid[2]
packet[13] = 0x34;
break;
case X16_AH:
packet[12] = 0;
packet[13] = 0;
break;
case IRDRONE:
packet[12] = 0xE0;
packet[13] = 0x2E;
break;
2017-11-20 16:01:12 +01:00
default:
packet[12] = rx_tx_addr[2]; // txid[2]
packet[13] = 0x0A;
break;
}
2015-12-30 01:41:12 +01:00
packet[14] = 0;
2017-11-20 16:01:12 +01:00
for (uint8_t i=0; i < BAYANG_PACKET_SIZE-1; i++)
2015-12-30 01:41:12 +01:00
packet[14] += packet[i];
NRF24L01_WriteReg(NRF24L01_05_RF_CH, bind ? rf_ch_num:hopping_frequency[hopping_frequency_no++]);
2015-12-30 01:41:12 +01:00
hopping_frequency_no%=BAYANG_RF_NUM_CHANNELS;
2015-12-30 01:41:12 +01:00
// clear packet status bits and TX FIFO
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
2015-12-30 01:41:12 +01:00
XN297_WritePayload(packet, BAYANG_PACKET_SIZE);
2017-11-20 16:01:12 +01:00
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_SetTxRxMode(TX_EN);
// Power on, TX mode, 2byte CRC
// Why CRC0? xn297 does not interpret it - either 16-bit CRC or nothing
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
#ifdef BAYANG_HUB_TELEMETRY
2017-11-20 16:01:12 +01:00
if (option)
{ // switch radio to rx as soon as packet is sent
2017-11-20 16:01:12 +01:00
while (!(NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_TX_DS)));
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x03);
}
#endif
2015-12-30 01:41:12 +01:00
NRF24L01_SetPower(); // Set tx_power
}
#ifdef BAYANG_HUB_TELEMETRY
static void __attribute__((unused)) BAYANG_check_rx(void)
{
if (NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
{ // data received from model
XN297_ReadPayload(packet, BAYANG_PACKET_SIZE);
NRF24L01_WriteReg(NRF24L01_07_STATUS, 255);
NRF24L01_FlushRx();
uint8_t check = packet[0];
for (uint8_t i=1; i < BAYANG_PACKET_SIZE-1; i++)
check += packet[i];
// decode data , check sum is ok as well, since there is no crc
if (packet[0] == 0x85 && packet[14] == check)
{
// uncompensated battery volts*100/2
v_lipo1 = (packet[3]<<7) + (packet[4]>>2);
// compensated battery volts*100/2
v_lipo2 = (packet[5]<<7) + (packet[6]>>2);
// reception in packets / sec
RX_RSSI = packet[7];
//Flags
//uint8_t flags = packet[3] >> 3;
// battery low: flags & 1
telemetry_counter++;
if(telemetry_lost==0)
telemetry_link=1;
}
}
}
#endif
static void __attribute__((unused)) BAYANG_init()
2015-12-30 01:41:12 +01:00
{
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
XN297_SetTXAddr((uint8_t *)"\x00\x00\x00\x00\x00", BAYANG_ADDRESS_LENGTH);
NRF24L01_FlushTx();
NRF24L01_FlushRx();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
2017-11-20 16:01:12 +01:00
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, BAYANG_PACKET_SIZE);
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // No retransmits
2017-11-20 16:01:12 +01:00
NRF24L01_SetPower();
NRF24L01_Activate(0x73); // Activate feature register
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
2017-11-20 16:01:12 +01:00
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x01);
NRF24L01_Activate(0x73);
switch (sub_protocol)
{
case X16_AH:
case IRDRONE:
rf_ch_num = BAYANG_RF_BIND_CHANNEL_X16_AH;
break;
default:
rf_ch_num = BAYANG_RF_BIND_CHANNEL;
break;
}
2015-12-30 01:41:12 +01:00
}
uint16_t BAYANG_callback()
{
if(IS_BIND_DONE_on)
{
if(packet_count==0)
BAYANG_send_packet(0);
packet_count++;
#ifdef BAYANG_HUB_TELEMETRY
if (option)
{ // telemetry is enabled
state++;
if (state > 1000)
{
//calculate telemetry reception packet rate - packets per 1000ms
TX_RSSI = telemetry_counter;
telemetry_counter = 0;
state = 0;
telemetry_lost=0;
}
if (packet_count > 1)
BAYANG_check_rx();
packet_count %= 5;
}
else
#endif
packet_count%=2;
}
else
2015-12-30 01:41:12 +01:00
{
if (bind_counter == 0)
{
XN297_SetTXAddr(rx_tx_addr, BAYANG_ADDRESS_LENGTH);
#ifdef BAYANG_HUB_TELEMETRY
XN297_SetRXAddr(rx_tx_addr, BAYANG_ADDRESS_LENGTH);
#endif
BIND_DONE;
}
else
{
if(packet_count==0)
BAYANG_send_packet(1);
packet_count++;
packet_count%=4;
bind_counter--;
}
2015-12-30 01:41:12 +01:00
}
return BAYANG_PACKET_PERIOD;
}
static void __attribute__((unused)) BAYANG_initialize_txid()
2015-12-30 01:41:12 +01:00
{
//Could be using txid[0..2] but using rx_tx_addr everywhere instead...
hopping_frequency[0]=0;
hopping_frequency[1]=(rx_tx_addr[3]&0x1F)+0x10;
hopping_frequency[2]=hopping_frequency[1]+0x20;
hopping_frequency[3]=hopping_frequency[2]+0x20;
2015-12-30 01:41:12 +01:00
hopping_frequency_no=0;
}
uint16_t initBAYANG(void)
{
BIND_IN_PROGRESS; // autobind protocol
bind_counter = BAYANG_BIND_COUNT;
BAYANG_initialize_txid();
BAYANG_init();
packet_count=0;
2017-11-20 16:01:12 +01:00
#ifdef BAYANG_HUB_TELEMETRY
init_frskyd_link_telemetry();
telemetry_lost=1; // do not send telemetry to TX right away until we have a TX_RSSI value to prevent warning message...
#endif
2015-12-30 01:41:12 +01:00
return BAYANG_INITIAL_WAIT+BAYANG_PACKET_PERIOD;
}
#endif