mirror of
https://github.com/pascallanger/DIY-Multiprotocol-TX-Module.git
synced 2025-02-04 22:28:12 +00:00
984aa3f413
- Change how PPM is handled with a resolution of 2048 and scaled to match serial input range. PPM is now fully scaled for all protocols which was not the case before. If you are using PPM, you might have to adjust the end points depending on the protocols. - Change all range conversions to use 2048 where possible - Updated all protocols with new range functions - Protocols which are taking advantage of 2048 are Assan, FrSky V/D/X, DSM, Devo, WK2x01 - Renamed AUX xto CHx for code readbility
264 lines
7.2 KiB
C++
264 lines
7.2 KiB
C++
/*
|
|
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/>.
|
|
*/
|
|
// Last sync with hexfet new_protocols/hisky_nrf24l01.c dated 2015-03-27
|
|
|
|
#if defined(HISKY_NRF24L01_INO)
|
|
|
|
#include "iface_nrf24l01.h"
|
|
|
|
#define HISKY_BIND_COUNT 1000
|
|
#define HISKY_TXID_SIZE 5
|
|
#define HISKY_FREQUENCE_NUM 20
|
|
//
|
|
uint8_t bind_buf_arry[4][10];
|
|
|
|
// HiSky protocol uses TX id as an address for nRF24L01, and uses frequency hopping sequence
|
|
// which does not depend on this id and is passed explicitly in binding sequence. So we are free
|
|
// to generate this sequence as we wish. It should be in the range [02..77]
|
|
static void __attribute__((unused)) calc_fh_channels()
|
|
{
|
|
uint8_t idx = 0;
|
|
uint32_t rnd = MProtocol_id;
|
|
|
|
while (idx < HISKY_FREQUENCE_NUM)
|
|
{
|
|
uint8_t i;
|
|
uint8_t count_2_26 = 0, count_27_50 = 0, count_51_74 = 0;
|
|
|
|
rnd = rnd * 0x0019660D + 0x3C6EF35F; // Randomization
|
|
// Use least-significant byte. 73 is prime, so channels 76..77 are unused
|
|
uint8_t next_ch = ((rnd >> 8) % 73) + 2;
|
|
// Keep the distance 2 between the channels - either odd or even
|
|
if (((next_ch ^ (uint8_t)rx_tx_addr[3]) & 0x01 )== 0)
|
|
continue;
|
|
// Check that it's not duplicated and spread uniformly
|
|
for (i = 0; i < idx; i++) {
|
|
if(hopping_frequency[i] == next_ch)
|
|
break;
|
|
if(hopping_frequency[i] <= 26)
|
|
count_2_26++;
|
|
else if (hopping_frequency[i] <= 50)
|
|
count_27_50++;
|
|
else
|
|
count_51_74++;
|
|
}
|
|
if (i != idx)
|
|
continue;
|
|
if ( (next_ch <= 26 && count_2_26 < 8) || (next_ch >= 27 && next_ch <= 50 && count_27_50 < 8) || (next_ch >= 51 && count_51_74 < 8) )
|
|
hopping_frequency[idx++] = next_ch;//find hopping frequency
|
|
}
|
|
}
|
|
|
|
static void __attribute__((unused)) build_binding_packet(void)
|
|
{
|
|
uint8_t i;
|
|
uint16_t sum=0;
|
|
uint8_t sum_l,sum_h;
|
|
|
|
for(i=0;i<5;i++)
|
|
sum += rx_tx_addr[i];
|
|
|
|
sum_l = (uint8_t)sum;//low byte
|
|
sum >>= 8;
|
|
sum_h = (uint8_t)sum;//high bye
|
|
|
|
bind_buf_arry[0][0] = 0xff;
|
|
bind_buf_arry[0][1] = 0xaa;
|
|
bind_buf_arry[0][2] = 0x55;
|
|
|
|
for(i=3;i<8;i++)
|
|
bind_buf_arry[0][i] = rx_tx_addr[i-3];
|
|
|
|
for(i=1;i<4;i++)
|
|
{
|
|
bind_buf_arry[i][0] = sum_l;
|
|
bind_buf_arry[i][1] = sum_h;
|
|
bind_buf_arry[i][2] = i-1;
|
|
}
|
|
|
|
for(i=0;i<7;i++)
|
|
{ bind_buf_arry[1][i+3] = hopping_frequency[i];
|
|
bind_buf_arry[2][i+3] = hopping_frequency[i+7];
|
|
bind_buf_arry[3][i+3] = hopping_frequency[i+14];
|
|
}
|
|
}
|
|
|
|
static void __attribute__((unused)) hisky_init()
|
|
{
|
|
NRF24L01_Initialize();
|
|
|
|
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowledgement
|
|
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable p0 rx
|
|
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address (byte -2)
|
|
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 81); // binding packet must be set in channel 81
|
|
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_tx_addr, 5);
|
|
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, 5);
|
|
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, 10); // payload size = 10
|
|
if(sub_protocol==HK310)
|
|
NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250Kbps
|
|
else
|
|
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
|
|
NRF24L01_SetPower(); // Set power
|
|
NRF24L01_SetTxRxMode(TX_EN); // TX mode, 2-bytes CRC, radio on
|
|
}
|
|
|
|
// HiSky channel sequence: AILE ELEV THRO RUDD GEAR PITCH, channel data value is from 0 to 1000
|
|
// Channel 7 - Gyro mode, 0 - 6 axis, 3 - 3 axis
|
|
static void __attribute__((unused)) build_ch_data()
|
|
{
|
|
uint16_t temp;
|
|
uint8_t i,j;
|
|
for (i = 0; i< 8; i++) {
|
|
j=CH_AETR[i];
|
|
temp=convert_channel_16b_limit(j,0,1000);
|
|
if (j == THROTTLE) // It is clear that hisky's throttle stick is made reversely, so I adjust it here on purpose
|
|
temp = 1000 -temp;
|
|
if (j == CH7)
|
|
temp = temp < 400 ? 0 : 3; // Gyro mode, 0 - 6 axis, 3 - 3 axis
|
|
packet[i] = (uint8_t)(temp&0xFF);
|
|
packet[i<4?8:9]>>=2;
|
|
packet[i<4?8:9]|=(temp>>2)&0xc0;
|
|
}
|
|
}
|
|
|
|
uint16_t hisky_cb()
|
|
{
|
|
phase++;
|
|
if(sub_protocol==HK310)
|
|
switch(phase)
|
|
{
|
|
case 1:
|
|
NRF24L01_SetPower();
|
|
phase=2;
|
|
break;
|
|
case 3:
|
|
if (! bind_counter)
|
|
NRF24L01_WritePayload(packet,10); // 2 packets per 5ms
|
|
break;
|
|
case 4:
|
|
phase=6;
|
|
break;
|
|
case 7: // build packet
|
|
#ifdef FAILSAFE_ENABLE
|
|
if(IS_FAILSAFE_VALUES_on && hopping_frequency_no==0)
|
|
{ // send failsafe every 100ms
|
|
convert_failsafe_HK310(RUDDER, &packet[0],&packet[1]);
|
|
convert_failsafe_HK310(THROTTLE,&packet[2],&packet[3]);
|
|
convert_failsafe_HK310(CH5, &packet[4],&packet[5]);
|
|
packet[7]=0xAA;
|
|
packet[8]=0x5A;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
convert_channel_HK310(RUDDER, &packet[0],&packet[1]);
|
|
convert_channel_HK310(THROTTLE,&packet[2],&packet[3]);
|
|
convert_channel_HK310(CH5, &packet[4],&packet[5]);
|
|
packet[7]=0x55;
|
|
packet[8]=0x67;
|
|
}
|
|
phase=8;
|
|
break;
|
|
}
|
|
switch(phase)
|
|
{
|
|
case 1:
|
|
NRF24L01_FlushTx();
|
|
break;
|
|
case 2:
|
|
if (bind_counter != 0)
|
|
{
|
|
//Set TX id and channel for bind packet
|
|
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t *)"\x12\x23\x23\x45\x78", 5);
|
|
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 81);
|
|
}
|
|
break;
|
|
case 3:
|
|
if (bind_counter != 0)
|
|
{
|
|
bind_counter--;//
|
|
if (! bind_counter) //Binding complete
|
|
BIND_DONE;//
|
|
//Send bind packet
|
|
NRF24L01_WritePayload(bind_buf_arry[binding_idx],10);
|
|
binding_idx++;
|
|
if (binding_idx >= 4)
|
|
binding_idx = 0;
|
|
}
|
|
break;
|
|
case 4:
|
|
if (bind_counter != 0)
|
|
NRF24L01_FlushTx();
|
|
break;
|
|
case 5:
|
|
//Set TX power
|
|
NRF24L01_SetPower();
|
|
break;
|
|
case 6:
|
|
//Set TX id and channel for normal packet
|
|
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, 5);
|
|
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
|
|
hopping_frequency_no++;
|
|
if (hopping_frequency_no >= HISKY_FREQUENCE_NUM)
|
|
hopping_frequency_no = 0;
|
|
break;
|
|
case 7:
|
|
//Build normal packet
|
|
build_ch_data();
|
|
break;
|
|
case 8:
|
|
break;
|
|
default:
|
|
//Send normal packet
|
|
phase = 0;
|
|
NRF24L01_WritePayload(packet,10);
|
|
break;
|
|
}
|
|
return 1000; // send 1 binding packet and 1 data packet per 9ms
|
|
}
|
|
|
|
static void __attribute__((unused)) initialize_tx_id()
|
|
{
|
|
//Generate frequency hopping table
|
|
if(sub_protocol==HK310)
|
|
{
|
|
// for HiSky surface protocol, the transmitter always generates hop channels in sequential order.
|
|
// The transmitter only generates the first hop channel between 0 and 49. So the channel range is from 0 to 69.
|
|
hopping_frequency_no=rx_tx_addr[0]%50;
|
|
for(uint8_t i=0;i<HISKY_FREQUENCE_NUM;i++)
|
|
hopping_frequency[i]=hopping_frequency_no++; // Sequential order hop channels...
|
|
}
|
|
else
|
|
calc_fh_channels();
|
|
}
|
|
|
|
uint16_t initHiSky()
|
|
{
|
|
initialize_tx_id();
|
|
build_binding_packet();
|
|
hisky_init();
|
|
phase = 0;
|
|
hopping_frequency_no = 0;
|
|
binding_idx = 0;
|
|
|
|
if(IS_BIND_IN_PROGRESS)
|
|
bind_counter = HISKY_BIND_COUNT;
|
|
else
|
|
bind_counter = 0;
|
|
return 1000;
|
|
}
|
|
|
|
#endif
|