diff --git a/AVR8_Burn-O-Mat_2_1_2_setup.exe b/AVR8_Burn-O-Mat_2_1_2_setup.exe
new file mode 100644
index 0000000..5f9e431
Binary files /dev/null and b/AVR8_Burn-O-Mat_2_1_2_setup.exe differ
diff --git a/Multiprotocol/A7105_joysway.ino b/Multiprotocol/A7105_joysway.ino
new file mode 100644
index 0000000..b153c79
--- /dev/null
+++ b/Multiprotocol/A7105_joysway.ino
@@ -0,0 +1,164 @@
+/*
+ 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.
+
+ Deviation 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 Deviation. If not, see .
+ */
+
+#if defined JOYSWAY_A7105_INO
+#include "iface_a7105.h"
+
+
+#define EVEN_ODD 0x00
+//#define EVEN_ODD 0x01
+static const uint8_t A7105_regs[] = {
+ 0x00, 0x62, -1, 0x0f, 0x00, -1 , -1 , 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0xf5, 0x00, 0x15,
+ 0x9e, 0x4b, 0x00, 0x03, 0x56, 0x2b, 0x12, 0x4a, 0x02, 0x80, 0x80, 0x00, 0x0e, 0x91, 0x03, 0x0f,
+ 0x16, 0x2a, 0x00, -1, -1, -1, 0x3a, 0x06, 0x1f, 0x47, 0x80, 0x01, 0x05, 0x45, 0x18, 0x00,
+ 0x01, 0x0f, 0x00
+};
+
+static uint8_t next_ch;
+
+static int joysway_init()
+{
+ int i;
+ uint8_t if_calibration1;
+ //uint8_t vco_calibration0;
+ //uint8_t vco_calibration1;
+
+ counter = 0;
+ next_ch = 0x30;
+
+ for (i = 0; i < 0x33; i++)
+ if((uint8_t)A7105_regs[i] != -1)
+ A7105_WriteReg(i, A7105_regs[i]);
+ A7105_WriteID(0x5475c52a);
+
+ A7105_Strobe(A7105_PLL);
+
+ //IF Filter Bank Calibration
+ A7105_WriteReg(0x02, 1);
+ A7105_ReadReg(0x02);
+ uint32_t ms = micros();
+ while(micros() - ms < 500) {
+ if(! A7105_ReadReg(0x02))
+ break;
+ }
+ if (micros() - ms >= 500)
+ return 0;
+ A7105_Strobe(A7105_STANDBY);
+ if_calibration1 = A7105_ReadReg(0x22);
+ if(if_calibration1 & A7105_MASK_FBCF) {
+ //Calibration failed...what do we do?
+ return 0;
+ }
+
+ //VCO Current Calibration
+ A7105_WriteReg(0x24, 0x13); //Recomended calibration from A7105 Datasheet
+ A7105_WriteReg(0x25, 0x09); //Recomended calibration from A7105 Datasheet
+
+ A7105_WriteID(MProtocol_id_master);
+ A7105_Strobe(A7105_PLL);
+ A7105_WriteReg(0x02, 1);
+ ms = micros();
+ while(micros() - ms < 500) {
+ if(! A7105_ReadReg(0x02))
+ break;
+ }
+ if (micros() - ms >= 500)
+ return 0;
+ A7105_Strobe(A7105_STANDBY);
+ if_calibration1 = A7105_ReadReg(0x22);
+ if(if_calibration1 & A7105_MASK_FBCF) {
+ //Calibration failed...what do we do?
+ return 0;
+ }
+ A7105_WriteReg(0x24, 0x13); //Recomended calibration from A7105 Datasheet
+ A7105_WriteReg(0x25, 0x09); //Recomended calibration from A7105 Datasheet
+
+ A7105_SetTxRxMode(TX_EN);
+ A7105_SetPower();
+
+ A7105_Strobe(A7105_STANDBY);
+ return 1;
+}
+
+static void joysway_build_packet()
+{
+ int i;
+ //-100% =~ 0x03e8
+ //+100% =~ 0x07ca
+ //Calculate:
+ //Center = 0x5d9
+ //1 % = 5
+ packet[0] = counter == 0 ? 0xdd : 0xff;
+ packet[1] = (MProtocol_id_master >> 24) & 0xff;
+ packet[2] = (MProtocol_id_master >> 16) & 0xff;
+ packet[3] = (MProtocol_id_master >> 8) & 0xff;
+ packet[4] = (MProtocol_id_master >> 0) & 0xff;
+ packet[5] = 0x00;
+ static const int chmap[4] = {6, 7, 10, 11};
+ for (i = 0; i < 4; i++) {
+// if (i >= Model.num_channels) { packet[chmap[i]] = 0x64; continue; }
+ uint32_t value = (uint32_t)Servo_data[i] * 0x66 / PPM_MAX + 0x66;
+ if (value < 0) { value = 0; }
+ if (value > 0xff) { value = 0xff; }
+ packet[chmap[i]] = value;
+ }
+ packet[8] = 0x64;
+ packet[9] = 0x64;
+ packet[12] = 0x64;
+ packet[13] = 0x64;
+ packet[14] = counter == 0 ? 0x30 : 0xaa;
+ uint8_t value = 0;
+ for (int i = 0; i < 15; i++) { value += packet[i]; }
+ packet[15] = value;
+}
+
+static uint16_t joysway_cb()
+{
+ uint8_t ch;
+ if (counter == 254) {
+ counter = 0;
+ A7105_WriteID(0x5475c52a);
+ ch = 0x0a;
+ } else if (counter == 2) {
+ A7105_WriteID(MProtocol_id_master);
+ ch = 0x30;
+ } else {
+ if ((counter & 0x01) ^ EVEN_ODD) {
+ ch = 0x30;
+ } else {
+ ch = next_ch;
+ }
+ }
+ if (! ((counter & 0x01) ^ EVEN_ODD)) {
+ next_ch++;
+ if (next_ch == 0x45)
+ next_ch = 0x30;
+ }
+ joysway_build_packet();
+ A7105_Strobe(A7105_STANDBY);
+ A7105_WriteData(16, ch);
+ counter++;
+ return 6000;
+}
+
+static uint16_t JOYSWAY_Setup() {
+ while(1) {
+ A7105_Reset();
+ if (joysway_init())
+ break;
+ }
+ return 2400;
+}
+#endif
diff --git a/Multiprotocol/CYRF6936_SPI.ino b/Multiprotocol/CYRF6936_SPI.ino
index 9880233..3985acb 100644
--- a/Multiprotocol/CYRF6936_SPI.ino
+++ b/Multiprotocol/CYRF6936_SPI.ino
@@ -215,11 +215,10 @@ static void CYRF_StartReceive()
CYRF_ReadRegisterMulti(CYRF_21_RX_BUFFER, dpbuffer, 0x10);
}
*/
-/*static void CYRF_ReadDataPacketLen(uint8_t dpbuffer[], uint8_t length)
+static void CYRF_ReadDataPacketLen(uint8_t dpbuffer[], uint8_t length)
{
ReadRegisterMulti(CYRF_21_RX_BUFFER, dpbuffer, length);
}
-*/
static void CYRF_WriteDataPacketLen(const uint8_t dpbuffer[], uint8_t len)
{
CYRF_WriteRegister(CYRF_01_TX_LENGTH, len);
diff --git a/Multiprotocol/CYRF6936_j6pro.ino b/Multiprotocol/CYRF6936_j6pro.ino
new file mode 100644
index 0000000..623ae5f
--- /dev/null
+++ b/Multiprotocol/CYRF6936_j6pro.ino
@@ -0,0 +1,277 @@
+/*
+ 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.
+
+ Deviation 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 Deviation. If not, see .
+ */
+
+#if defined(J6PRO_CYRF6936_INO)
+#include "iface_cyrf6936.h"
+
+#define NUM_WAIT_LOOPS (100 / 5) //each loop is ~5us. Do not wait more than 100us
+
+//For Debug
+//#define NO_SCRAMBLE
+
+enum J6ProState {
+ J6PRO_BIND,
+ J6PRO_BIND_01,
+ J6PRO_BIND_03_START,
+ J6PRO_BIND_03_CHECK,
+ J6PRO_BIND_05_1,
+ J6PRO_BIND_05_2,
+ J6PRO_BIND_05_3,
+ J6PRO_BIND_05_4,
+ J6PRO_BIND_05_5,
+ J6PRO_BIND_05_6,
+ J6PRO_CHANSEL,
+ J6PRO_CHAN_1,
+ J6PRO_CHAN_2,
+ J6PRO_CHAN_3,
+ J6PRO_CHAN_4,
+};
+
+static const uint8_t J6Pro_sopcodes[][8] = {
+ /* Note these are in order transmitted (LSB 1st) */
+ {0x3C, 0x37, 0xCC, 0x91, 0xE2, 0xF8, 0xCC, 0x91},
+ {0x9B, 0xC5, 0xA1, 0x0F, 0xAD, 0x39, 0xA2, 0x0F},
+ {0xEF, 0x64, 0xB0, 0x2A, 0xD2, 0x8F, 0xB1, 0x2A},
+ {0x66, 0xCD, 0x7C, 0x50, 0xDD, 0x26, 0x7C, 0x50},
+ {0x5C, 0xE1, 0xF6, 0x44, 0xAD, 0x16, 0xF6, 0x44},
+ {0x5A, 0xCC, 0xAE, 0x46, 0xB6, 0x31, 0xAE, 0x46},
+ {0xA1, 0x78, 0xDC, 0x3C, 0x9E, 0x82, 0xDC, 0x3C},
+ {0xB9, 0x8E, 0x19, 0x74, 0x6F, 0x65, 0x18, 0x74},
+ {0xDF, 0xB1, 0xC0, 0x49, 0x62, 0xDF, 0xC1, 0x49},
+ {0x97, 0xE5, 0x14, 0x72, 0x7F, 0x1A, 0x14, 0x72},
+ {0x82, 0xC7, 0x90, 0x36, 0x21, 0x03, 0xFF, 0x17},
+ {0xE2, 0xF8, 0xCC, 0x91, 0x3C, 0x37, 0xCC, 0x91}, //Note: the '03' was '9E' in the Cypress recommended table
+ {0xAD, 0x39, 0xA2, 0x0F, 0x9B, 0xC5, 0xA1, 0x0F}, //The following are the same as the 1st 8 above,
+ {0xD2, 0x8F, 0xB1, 0x2A, 0xEF, 0x64, 0xB0, 0x2A}, //but with the upper and lower word swapped
+ {0xDD, 0x26, 0x7C, 0x50, 0x66, 0xCD, 0x7C, 0x50},
+ {0xAD, 0x16, 0xF6, 0x44, 0x5C, 0xE1, 0xF6, 0x44},
+ {0xB6, 0x31, 0xAE, 0x46, 0x5A, 0xCC, 0xAE, 0x46},
+ {0x9E, 0x82, 0xDC, 0x3C, 0xA1, 0x78, 0xDC, 0x3C},
+ {0x6F, 0x65, 0x18, 0x74, 0xB9, 0x8E, 0x19, 0x74},
+};
+const uint8_t bind_sop_code[] = {0x62, 0xdf, 0xc1, 0x49, 0xdf, 0xb1, 0xc0, 0x49};
+const uint8_t data_code[] = {0x02, 0xf9, 0x93, 0x97, 0x02, 0xfa, 0x5c, 0xe3, 0x01, 0x2b, 0xf1, 0xdb, 0x01, 0x32, 0xbe, 0x6f};
+
+static uint8_t stateJ6P;
+static uint8_t radio_ch[4];
+static uint8_t num_channels;
+
+void J6Pro_build_bind_packet()
+{
+ packet[0] = 0x01; //Packet type
+ packet[1] = 0x01; //FIXME: What is this? Model number maybe?
+ packet[2] = 0x56; //FIXME: What is this?
+ packet[3] = cyrfmfg_id[0];
+ packet[4] = cyrfmfg_id[1];
+ packet[5] = cyrfmfg_id[2];
+ packet[6] = cyrfmfg_id[3];
+ packet[7] = cyrfmfg_id[4];
+ packet[8] = cyrfmfg_id[5];
+}
+void J6Pro_build_data_packet()
+{
+ uint8_t i;
+ uint32_t upperbits = 0;
+ packet[0] = 0xaa; //FIXME what is this?
+ for (i = 0; i < 12; i++) {
+ if (i >= num_channels) {
+ packet[i+1] = 0xff;
+ continue;
+ }
+ uint32_t value = (uint32_t)Servo_data[i] * 0x200 / PPM_MAX + 0x200;
+ if (value < 0)
+ value = 0;
+ if (value > 0x3ff)
+ value = 0x3ff;
+ packet[i+1] = value & 0xff;
+ upperbits |= (value >> 8) << (i * 2);
+ }
+ packet[13] = upperbits & 0xff;
+ packet[14] = (upperbits >> 8) & 0xff;
+ packet[15] = (upperbits >> 16) & 0xff;
+}
+
+static void J6Pro_cyrf_init()
+{
+ /* Initialise CYRF chip */
+ CYRF_WriteRegister(CYRF_28_CLK_EN, 0x02);
+ CYRF_WriteRegister(CYRF_32_AUTO_CAL_TIME, 0x3c);
+ CYRF_WriteRegister(CYRF_35_AUTOCAL_OFFSET, 0x14);
+ CYRF_WriteRegister(CYRF_1C_TX_OFFSET_MSB, 0x05);
+ CYRF_WriteRegister(CYRF_1B_TX_OFFSET_LSB, 0x55);
+ CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x25);
+ CYRF_WriteRegister(CYRF_03_TX_CFG, 0x05 | CYRF_BIND_POWER);
+ CYRF_WriteRegister(CYRF_06_RX_CFG, 0x8a);
+ CYRF_WriteRegister(CYRF_03_TX_CFG, 0x28 | CYRF_BIND_POWER);
+ CYRF_WriteRegister(CYRF_12_DATA64_THOLD, 0x0e);
+ CYRF_WriteRegister(CYRF_10_FRAMING_CFG, 0xee);
+ CYRF_WriteRegister(CYRF_1F_TX_OVERRIDE, 0x00);
+ CYRF_WriteRegister(CYRF_1E_RX_OVERRIDE, 0x00);
+ CYRF_ConfigDataCode(data_code, 16);
+ CYRF_WritePreamble(0x023333);
+}
+static void J6Pro_cyrf_bindinit()
+{
+/* Use when binding */
+ //0.060470# 03 2f
+ CYRF_WriteRegister(CYRF_03_TX_CFG, 0x28 | 0x07); //Use max power for binding in case there is no telem module
+
+ CYRF_ConfigRFChannel(0x52);
+ CYRF_ConfigSOPCode(bind_sop_code);
+ CYRF_ConfigCRCSeed(0x0000);
+ CYRF_WriteRegister(CYRF_06_RX_CFG, 0x4a);
+ CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x83);
+ //0.061511# 13 20
+
+ CYRF_ConfigRFChannel(0x52);
+ //0.062684# 0f 05
+ CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x25);
+ //0.062792# 0f 05
+ CYRF_WriteRegister(CYRF_02_TX_CTRL, 0x40);
+ J6Pro_build_bind_packet(); //01 01 e9 49 ec a9 c4 c1 ff
+ //CYRF_WriteDataPacketLen(packet, 0x09);
+}
+static void J6Pro_cyrf_datainit()
+{
+/* Use when already bound */
+ //0.094007# 0f 05
+ uint8_t sop_idx = (0xff & (cyrfmfg_id[0] + cyrfmfg_id[1] + cyrfmfg_id[2] + cyrfmfg_id[3] - cyrfmfg_id[5])) % 19;
+ uint16_t crc = (0xff & (cyrfmfg_id[1] - cyrfmfg_id[4] + cyrfmfg_id[5])) |
+ ((0xff & (cyrfmfg_id[2] + cyrfmfg_id[3] - cyrfmfg_id[4] + cyrfmfg_id[5])) << 8);
+ CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x25);
+ CYRF_ConfigSOPCode(J6Pro_sopcodes[sop_idx]);
+ CYRF_ConfigCRCSeed(crc);
+}
+
+static void J6Pro_set_radio_channels()
+{
+ //FIXME: Query free channels
+ //lowest channel is 0x08, upper channel is 0x4d?
+ CYRF_FindBestChannels(radio_ch, 3, 5, 8, 77);
+ radio_ch[3] = radio_ch[0];
+}
+
+static uint16_t j6pro_cb()
+{
+ switch(stateJ6P) {
+ case J6PRO_BIND:
+ J6Pro_cyrf_bindinit();
+ stateJ6P = J6PRO_BIND_01;
+ //no break because we want to send the 1st bind packet now
+ case J6PRO_BIND_01:
+ CYRF_ConfigRFChannel(0x52);
+ CYRF_SetTxRxMode(TX_EN);
+ //0.062684# 0f 05
+ CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x25);
+ //0.062684# 0f 05
+ CYRF_WriteDataPacketLen(packet, 0x09);
+ stateJ6P = J6PRO_BIND_03_START;
+ return 3000; //3msec
+ case J6PRO_BIND_03_START:
+ {
+ int i = 0;
+ while (! (CYRF_ReadRegister(0x04) & 0x06))
+ if(++i > NUM_WAIT_LOOPS)
+ break;
+ }
+ CYRF_ConfigRFChannel(0x53);
+ CYRF_SetTxRxMode(RX_EN);
+ CYRF_WriteRegister(CYRF_06_RX_CFG, 0x4a);
+ CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x83);
+ stateJ6P = J6PRO_BIND_03_CHECK;
+ return 30000; //30msec
+ case J6PRO_BIND_03_CHECK:
+ {
+ uint8_t rx = CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS);
+ if((rx & 0x1a) == 0x1a) {
+ rx = CYRF_ReadRegister(CYRF_0A_RX_LENGTH);
+ if(rx == 0x0f) {
+ rx = CYRF_ReadRegister(CYRF_09_RX_COUNT);
+ if(rx == 0x0f) {
+ //Expected and actual length are both 15
+ CYRF_ReadDataPacketLen(packet, rx);
+ if (packet[0] == 0x03 &&
+ packet[3] == cyrfmfg_id[0] &&
+ packet[4] == cyrfmfg_id[1] &&
+ packet[5] == cyrfmfg_id[2] &&
+ packet[6] == cyrfmfg_id[3] &&
+ packet[7] == cyrfmfg_id[4] &&
+ packet[8] == cyrfmfg_id[5])
+ {
+ //Send back Ack
+ packet[0] = 0x05;
+ CYRF_ConfigRFChannel(0x54);
+ CYRF_SetTxRxMode(TX_EN);
+ stateJ6P = J6PRO_BIND_05_1;
+ return 2000; //2msec
+ }
+ }
+ }
+ }
+ stateJ6P = J6PRO_BIND_01;
+ return 500;
+ }
+ case J6PRO_BIND_05_1:
+ case J6PRO_BIND_05_2:
+ case J6PRO_BIND_05_3:
+ case J6PRO_BIND_05_4:
+ case J6PRO_BIND_05_5:
+ case J6PRO_BIND_05_6:
+ CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x25);
+ CYRF_WriteDataPacketLen(packet, 0x0f);
+ stateJ6P = stateJ6P + 1;
+ return 4600; //4.6msec
+ case J6PRO_CHANSEL:
+ BIND_DONE;
+ J6Pro_set_radio_channels();
+ J6Pro_cyrf_datainit();
+ stateJ6P = J6PRO_CHAN_1;
+ case J6PRO_CHAN_1:
+ //Keep transmit power updated
+ CYRF_SetPower(CYRF_HIGH_POWER);
+ J6Pro_build_data_packet();
+ //return 3400;
+ case J6PRO_CHAN_2:
+ //return 3500;
+ case J6PRO_CHAN_3:
+ //return 3750
+ case J6PRO_CHAN_4:
+ CYRF_ConfigRFChannel(radio_ch[stateJ6P - J6PRO_CHAN_1]);
+ CYRF_SetTxRxMode(TX_EN);
+ CYRF_WriteDataPacket(packet);
+ if (stateJ6P == J6PRO_CHAN_4) {
+ stateJ6P = J6PRO_CHAN_1;
+ return 13900;
+ }
+ stateJ6P = stateJ6P + 1;
+ return 3550;
+ }
+ return 0;
+}
+
+static uint16_t j6pro_setup()
+{
+ CYRF_Reset();
+ J6Pro_cyrf_init();
+ num_channels = 8;
+ if (IS_AUTOBIND_FLAG_on) {
+ stateJ6P = J6PRO_BIND;
+ BIND_IN_PROGRESS;
+ } else {
+ stateJ6P = J6PRO_CHANSEL;
+ }
+ return 2400;
+}
+#endif
diff --git a/Multiprotocol/Cyrf6936_wk2x01.ino b/Multiprotocol/Cyrf6936_wk2x01.ino
new file mode 100644
index 0000000..363dd61
--- /dev/null
+++ b/Multiprotocol/Cyrf6936_wk2x01.ino
@@ -0,0 +1,449 @@
+/*
+ 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.
+ Deviation 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 Deviation. If not, see .
+ */
+#if defined(WK2x01_CYRF6936_INO)
+#include "iface_cyrf6936.h"
+
+#define PKTS_PER_CHANNEL 4
+
+//Fewer bind packets in the emulator so we can get right to the important bits
+#define WK_BIND_COUNT 2980
+
+#define NUM_WAIT_LOOPS (100 / 5) //each loop is ~5us. Do not wait more than 100us
+
+
+#define WK_BIND 0
+#define WK_BOUND_1 1
+#define WK_BOUND_2 2
+#define WK_BOUND_3 3
+#define WK_BOUND_4 4
+#define WK_BOUND_5 5
+#define WK_BOUND_6 6
+#define WK_BOUND_7 7
+#define WK_BOUND_8 8
+
+static const uint8_t sopcode[8] = {
+ /* Note these are in order transmitted (LSB 1st) */
+ 0xDF,0xB1,0xC0,0x49,0x62,0xDF,0xC1,0x49 //0x49C1DF6249C0B1DF
+};
+static const uint8_t fail_map[8] = {2, 1, 0, 3, 4, 5, 6, 7};
+
+static uint8_t wk_pkt_num;
+static u8 *radio_ch_ptr;
+static uint16_t WK_BIND_COUNTer;
+static uint8_t last_beacon;
+/*
+static const char * const wk2601_opts[] = {
+ _tr_noop("Chan mode"), _tr_noop("5+1"), _tr_noop("Heli"), _tr_noop("6+1"), NULL,
+ _tr_noop("COL Inv"), _tr_noop("Normal"), _tr_noop("Inverted"), NULL,
+ _tr_noop("COL Limit"), "-100", "100", NULL,
+ NULL
+};
+*/
+#define WK2601_OPT_CHANMODE 0
+#define WK2601_OPT_PIT_INV 1
+#define WK2601_OPT_PIT_LIMIT 2
+#define LAST_PROTO_OPT 3
+
+static void add_pkt_crc(uint8_t init) {
+ uint8_t add = init;
+ uint8_t xou = init;
+ int i;
+ for (i = 0; i < 14; i++) { add += packet[i]; xou ^= packet[i]; }
+ packet[14] = xou;
+ packet[15] = add & 0xff;
+}
+static const char init_2801[] = {0xc5, 0x34, 0x60, 0x00, 0x25};
+static const char init_2601[] = {0xb9, 0x45, 0xb0, 0xf1, 0x3a};
+static const char init_2401[] = {0xa5, 0x23, 0xd0, 0xf0, 0x00};
+static void build_bind_pkt(const char *init) {
+ packet[0] = init[0];
+ packet[1] = init[1];
+ packet[2] = rx_tx_addr[0];
+ packet[3] = rx_tx_addr[1];
+ packet[4] = init[2];
+ packet[5] = rx_tx_addr[2];
+ packet[6] = 0xff;
+ packet[7] = 0x00;
+ packet[8] = 0x00;
+ packet[9] = 0x32;
+ if (sub_protocol == WK2401) { packet[10] = 0x10 | ((fixed_id >> 0) & 0x0e); }
+ else { packet[10] = (fixed_id >> 0) & 0xff; }
+ packet[11] = (fixed_id >> 8) & 0xff;
+ packet[12] = ((fixed_id >> 12) & 0xf0) | wk_pkt_num;
+ packet[13] = init[3];
+ add_pkt_crc(init[4]);
+}
+
+static uint16_t get_channel(uint8_t ch, uint32_t scale, uint32_t center, uint32_t range) {
+ uint32_t value = (uint32_t)Servo_data[ch] * scale / PPM_MAX + center;
+ if (value < center - range) { value = center - range; }
+ if (value > center + range) { value = center + range; }
+ return value;
+}
+
+static void build_data_pkt_2401() {
+ uint8_t i;
+ uint16_t msb = 0;
+ uint8_t offset = 0;
+ for (i = 0; i < 4; i++) {
+ if (i == 2) { offset = 1; }
+ uint16_t value = get_channel(i, 0x800, 0, 0xA00); //12 bits, allow value to go to 125%
+ uint16_t base = abs(value) >> 2; //10 bits is the base value
+ uint16_t trim = abs(value) & 0x03; //lowest 2 bits represent trim
+ if (base >= 0x200) { //if value is > 100%, remainder goes to trim
+ trim = 4 *(base - 0x200);
+ base = 0x1ff;
+ }
+ base = (value >= 0) ? 0x200 + base : 0x200 - base;
+ trim = (value >= 0) ? 0x200 + trim : 0x200 - trim;
+
+ packet[2*i+offset] = base & 0xff;
+ packet[2*i+offset+1] = trim & 0xff;
+ msb = (msb << 4) | ((base >> 6) & 0x0c) | ((trim >> 8) & 0x03);
+ }
+ packet[4] = msb >> 8; //Ele/Ail MSB
+ packet[9] = msb & 0xff; //Thr/Rud MSB
+ packet[10] = 0xe0 | ((fixed_id >> 0) & 0x0e);
+ packet[11] = (fixed_id >> 8) & 0xff;
+ packet[12] = ((fixed_id >> 12) & 0xf0) | wk_pkt_num;
+ packet[13] = 0xf0; //FIXME - What is this?
+ add_pkt_crc(0x00);
+}
+
+#define PCT(pct, max) (((max) * (pct) + 1L) / 1000)
+#define MAXTHR 426 //Measured to provide equal value at +/-0
+static void channels_6plus1_2601(int frame, int *_v1, int *_v2) {
+ uint16_t thr = get_channel(2, 1000, 0, 1000);
+ int v1;
+ int thr_rev = 0, pitch_rev = 0;
+ if(thr > 0) {
+ if(thr >= 780) { //78%
+ v1 = 0; //thr = 60% * (x - 78%) / 22% + 40%
+ thr = PCT(1000-MAXTHR,512) * (thr-PCT(780,1000)) / PCT(220,1000) + PCT(MAXTHR,512);
+ } else {
+ v1 = 1023 - 1023 * thr / 780;
+ thr = PCT(MAXTHR, 512); //40%
+ }
+ }
+ else {
+ thr = -thr;
+ thr_rev = 1;
+ if(thr >= 780) { //78%
+ v1 = 1023; //thr = 60% * (x - 78%) / 22% + 40%
+ thr = PCT(1000-MAXTHR,512) * (thr-PCT(780,1000)) / PCT(220,1000) + PCT(MAXTHR,512);
+ if (thr >= 512) { thr = 511; }
+ }
+ else {
+ v1 = 1023 * thr / 780;
+ thr = PCT(MAXTHR, 512); //40%
+ }
+ }
+ if (thr >= 512) { thr = 511; }
+ packet[2] = thr & 0xff;
+ packet[4] = (packet[4] & 0xF3) | ((thr >> 6) & 0x04);
+
+ uint16_t pitch= get_channel(5, 0x400, 0, 0x400);
+ if (pitch < 0) {
+ pitch_rev = 1;
+ pitch = -pitch;
+ }
+ if (frame == 1) {
+ //Pitch curve and range
+ if (thr > PCT(MAXTHR, 512)) { *_v2 = pitch - pitch * 16 * (thr - PCT(MAXTHR, 512)) / PCT(1000 - MAXTHR, 512) / 100; }
+ else { *_v2 = pitch; }
+ *_v1 = 0;
+ }
+ else if (frame == 2) {
+ //Throttle curve & Expo
+ *_v1 = v1;
+ *_v2 = 512;
+ }
+ packet[7] = (thr_rev << 5) | (pitch_rev << 2); //reverse bits
+ packet[8] = 0;
+}
+
+static void channels_5plus1_2601(int frame, int *v1, int *v2) {
+ (void)v1;
+ //Zero out pitch, provide ail, ele, thr, rud, gyr + gear
+ if (frame == 1) { *v2 = 0; } //Pitch curve and range
+ packet[7] = 0;
+ packet[8] = 0;
+}
+static void channels_heli_2601(int frame, int *v1, int *v2) {
+ (void)frame;
+ //pitch is controlled by rx
+ //we can only control fmode, pit-reverse and pit/thr rate
+ int pit_rev = 0;
+ if (Model.proto_opts[WK2601_OPT_PIT_INV]) { pit_rev = 1; }
+ uint16_t pit_rate = get_channel(5, 0x400, 0, 0x400);
+ int fmode = 1;
+ if (pit_rate < 0) { pit_rate = -pit_rate; fmode = 0; }
+ if (frame == 1) {
+ //Pitch curve and range
+ *v1 = pit_rate;
+ *v2 = Model.proto_opts[WK2601_OPT_PIT_LIMIT] * 0x400 / 100 + 0x400;
+ }
+ packet[7] = (pit_rev << 2); //reverse bits
+ packet[8] = fmode ? 0x02 : 0x00;
+}
+
+static void build_data_pkt_2601() {
+ uint8_t i;
+ uint8_t msb = 0;
+ uint8_t frame = (wk_pkt_num % 3);
+ for (i = 0; i < 4; i++) {
+ uint16_t value = get_channel(i, 0x190, 0, 0x1FF);
+ uint16_t mag = value < 0 ? -value : value;
+ packet[i] = mag & 0xff;
+ msb = (msb << 2) | ((mag >> 8) & 0x01) | (value < 0 ? 0x02 : 0x00);
+ }
+ packet[4] = msb;
+ int v1 = 0x200, v2 = 0x200;
+ if (frame == 0) {
+ //Gyro & Rudder mix
+ v1 = get_channel(6, 0x200, 0x200, 0x200);
+ v2 = 0;
+ }
+ if (Model.proto_opts[WK2601_OPT_CHANMODE] == 1) { channels_heli_2601(frame, &v1, &v2); }
+ else if (Model.proto_opts[WK2601_OPT_CHANMODE] == 2) { channels_6plus1_2601(frame, &v1, &v2); }
+ else { channels_5plus1_2601(frame, &v1, &v2); }
+ if (v1 > 1023) { v1 = 1023; }
+ if (v2 > 1023) { v2 = 1023; }
+ packet[5] = v2 & 0xff;
+ packet[6] = v1 & 0xff;
+ //packet[7] handled by channel code
+ packet[8] |= (get_channel(4, 0x190, 0, 0x1FF) > 0 ? 1 : 0);
+ packet[9] = ((v1 >> 4) & 0x30) | ((v2 >> 2) & 0xc0) | 0x04 | frame;
+ packet[10] = (fixed_id >> 0) & 0xff;
+ packet[11] = (fixed_id >> 8) & 0xff;
+ packet[12] = ((fixed_id >> 12) & 0xf0) | wk_pkt_num;
+ packet[13] = 0xff;
+
+ add_pkt_crc(0x3A);
+}
+
+static void build_data_pkt_2801() {
+ uint8_t i;
+ uint16_t msb = 0;
+ uint8_t offset = 0;
+ uint8_t sign = 0;
+ for (i = 0; i < 8; i++) {
+ if (i == 4) { offset = 1; }
+ uint16_t value = get_channel(i, 0x190, 0, 0x3FF);
+ uint16_t mag = value < 0 ? -value : value;
+ packet[i+offset] = mag & 0xff;
+ msb = (msb << 2) | ((mag >> 8) & 0x03);
+ if (value < 0) { sign |= 1 << i; }
+ }
+ packet[4] = msb >> 8;
+ packet[9] = msb & 0xff;
+ packet[10] = (fixed_id >> 0) & 0xff;
+ packet[11] = (fixed_id >> 8) & 0xff;
+ packet[12] = ((fixed_id >> 12) & 0xf0) | wk_pkt_num;
+ packet[13] = sign;
+ add_pkt_crc(0x25);
+}
+
+static void build_beacon_pkt_2801() {
+ last_beacon ^= 1;
+ uint8_t i;
+ uint8_t en = 0;
+ uint8_t bind_state;
+ if (WK_BIND_COUNTer) { bind_state = 0xe4; }
+ else { bind_state = 0x1b; }
+ for (i = 0; i < 4; i++) {
+/* if (Model.limits[fail_map[i + last_beacon * 4]].flags & CH_FAILSAFE_EN) {
+ uint32_t value = Model.limits[fail_map[i + last_beacon * 4]].failsafe + 128;
+ if (value > 255) { value = 255; }
+ if (value < 0) { value = 0; }
+ packet[i+1] = value;
+ en |= 1 << i;
+ } else
+*/ { packet[i+1] = 0; }
+ }
+ packet[0] = en;
+ packet[5] = packet[4];
+ packet[4] = last_beacon << 6;
+ packet[6] = rx_tx_addr[0];
+ packet[7] = rx_tx_addr[1];
+ packet[8] = rx_tx_addr[2];
+ packet[9] = bind_state;
+ packet[10] = (fixed_id >> 0) & 0xff;
+ packet[11] = (fixed_id >> 8) & 0xff;
+ packet[12] = ((fixed_id >> 12) & 0xf0) | wk_pkt_num;
+ packet[13] = 0x00; //Does this matter? in the docs it is the same as the data packet
+ add_pkt_crc(0x1C);
+}
+
+static void wk2x01_cyrf_init() {
+ /* Initialise CYRF chip */
+ CYRF_WriteRegister(CYRF_03_TX_CFG, 0x28 | CYRF_HIGH_POWER);
+ CYRF_WriteRegister(CYRF_06_RX_CFG, 0x4A);
+ CYRF_WriteRegister(CYRF_0B_PWR_CTRL, 0x00);
+ CYRF_WriteRegister(CYRF_0C_XTAL_CTRL, 0xC0);
+ CYRF_WriteRegister(CYRF_0D_IO_CFG, 0x04);
+ CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x2C);
+ CYRF_WriteRegister(CYRF_10_FRAMING_CFG, 0xEE);
+ CYRF_WriteRegister(CYRF_1B_TX_OFFSET_LSB, 0x55);
+ CYRF_WriteRegister(CYRF_1C_TX_OFFSET_MSB, 0x05);
+ CYRF_WriteRegister(CYRF_1D_MODE_OVERRIDE, 0x18);
+ CYRF_WriteRegister(CYRF_32_AUTO_CAL_TIME, 0x3C);
+ CYRF_WriteRegister(CYRF_35_AUTOCAL_OFFSET, 0x14);
+ CYRF_WriteRegister(CYRF_1E_RX_OVERRIDE, 0x90);
+ CYRF_WriteRegister(CYRF_1F_TX_OVERRIDE, 0x00);
+ CYRF_WriteRegister(CYRF_01_TX_LENGTH, 0x10);
+ CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x2C);
+ CYRF_WriteRegister(CYRF_28_CLK_EN, 0x02);
+ CYRF_WriteRegister(CYRF_27_CLK_OVERRIDE, 0x02);
+ CYRF_ConfigSOPCode(sopcode);
+ CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x28);
+ CYRF_WriteRegister(CYRF_1E_RX_OVERRIDE, 0x10);
+ CYRF_WriteRegister(CYRF_0E_GPIO_CTRL, 0x20);
+ CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x2C);
+}
+
+void WK_BuildPacket_2801() {
+ switch(phase) {
+ case WK_BIND:
+ build_bind_pkt(init_2801);
+// if ((--WK_BIND_COUNTer == 0) || PROTOCOL_SticksMoved(0)) {
+ if ((--WK_BIND_COUNTer == 0)) {
+ WK_BIND_COUNTer = 0;
+ BIND_DONE;
+ phase = WK_BOUND_1;
+ }
+ break;
+ case WK_BOUND_1:
+ case WK_BOUND_2:
+ case WK_BOUND_3:
+ case WK_BOUND_4:
+ case WK_BOUND_5:
+ case WK_BOUND_6:
+ case WK_BOUND_7:
+ build_data_pkt_2801();
+ phase++;
+ break;
+ case WK_BOUND_8:
+ build_beacon_pkt_2801();
+ phase = WK_BOUND_1;
+ if (WK_BIND_COUNTer) {
+ WK_BIND_COUNTer--;
+ if (WK_BIND_COUNTer == 0) { BIND_DONE; }
+ }
+ break;
+ }
+ wk_pkt_num = (wk_pkt_num + 1) % 12;
+}
+
+void WK_BuildPacket_2601() {
+ if (WK_BIND_COUNTer) {
+ WK_BIND_COUNTer--;
+ build_bind_pkt(init_2601);
+ if ((WK_BIND_COUNTer == 0)) {
+ WK_BIND_COUNTer = 0;
+ BIND_DONE;
+ }
+ }
+ else { build_data_pkt_2601(); }
+ wk_pkt_num = (wk_pkt_num + 1) % 12;
+}
+
+void WK_BuildPacket_2401() {
+ if (WK_BIND_COUNTer) {
+ WK_BIND_COUNTer--;
+ build_bind_pkt(init_2401);
+ if ((WK_BIND_COUNTer == 0)) {
+ WK_BIND_COUNTer = 0;
+ BIND_DONE;
+ }
+ }
+ else { build_data_pkt_2401(); }
+ wk_pkt_num = (wk_pkt_num + 1) % 12;
+}
+
+static uint16_t wk_cb() {
+ if (packet_sent == 0) {
+ packet_sent = 1;
+ if(sub_protocol == WK2801) { WK_BuildPacket_2801(); }
+ else if(sub_protocol == WK2601) { WK_BuildPacket_2601(); }
+ else if(sub_protocol == WK2401) { WK_BuildPacket_2401(); }
+ CYRF_WriteDataPacket(packet);
+ return 1600;
+ }
+ packet_sent = 0;
+ int i = 0;
+ while (! (CYRF_ReadRegister(0x04) & 0x02)) { if(++i > NUM_WAIT_LOOPS) { break; } }
+ if((wk_pkt_num & 0x03) == 0) {
+ radio_ch_ptr = radio_ch_ptr == &rx_tx_addr[2] ? rx_tx_addr : radio_ch_ptr + 1;
+ CYRF_ConfigRFChannel(*radio_ch_ptr);
+ //Keep transmit power updated
+ CYRF_WriteRegister(CYRF_03_TX_CFG, 0x28 | CYRF_HIGH_POWER);
+ }
+ return 1200;
+}
+
+static void wk_bind() {
+ if((sub_protocol != WK2801)) { return; }
+ fixed_id = ((MProtocol_id_master << 2) & 0x0ffc00) | ((MProtocol_id_master >> 10) & 0x000300) | ((MProtocol_id_master) & 0x0000ff);
+ WK_BIND_COUNTer = WK_BIND_COUNT / 8 + 1;
+ BIND_IN_PROGRESS;
+}
+
+static uint16_t wk_setup() {
+ CYRF_Reset();
+ wk2x01_cyrf_init();
+ CYRF_SetTxRxMode(TX_EN);
+ CYRF_FindBestChannels(rx_tx_addr, 3, 4, 4, 80);
+
+ radio_ch_ptr = rx_tx_addr;
+ CYRF_ConfigRFChannel(*radio_ch_ptr);
+
+ wk_pkt_num = 0;
+ packet_sent = 0;
+ last_beacon = 0;
+ fixed_id = ((MProtocol_id_master << 2) & 0x0ffc00) | ((MProtocol_id_master >> 10) & 0x000300) | ((MProtocol_id_master) & 0x0000ff);
+ if (sub_protocol == WK2401) { fixed_id |= 0x01; } //Fixed ID must be odd for 2401
+ if(sub_protocol != WK2801) {
+ WK_BIND_COUNTer = WK_BIND_COUNT;
+ phase = WK_BIND;
+ BIND_IN_PROGRESS;
+ }
+ else {
+ phase = WK_BOUND_1;
+ WK_BIND_COUNTer = 0;
+ }
+ CYRF_ConfigRFChannel(*radio_ch_ptr);
+ return 2800;
+}
+/*
+const void *WK2x01_Cmds(enum ProtoCmds cmd) {
+ switch(cmd) {
+ case PROTOCMD_INIT: initialize(); return 0;
+ case PROTOCMD_DEINIT: return 0;
+ case PROTOCMD_CHECK_AUTOBIND:
+ return (Model.protocol == WK2801 && Model.fixed_id) ? 0 : (void *)1L;
+ case PROTOCMD_BIND: wk_bind(); return 0;
+ case PROTOCMD_DEFAULT_NUMCHAN: return (Model.protocol == WK2801)
+ ? (void *)8L
+ : (Model.protocol == WK2601)
+ ? (void *)6L
+ : (void *)4L;
+ case PROTOCMD_NUMCHAN: return (Model.protocol == WK2801)
+ ? (void *)8L
+ : (Model.protocol == WK2601)
+ ? (void *)7L
+ : (void *)4L;
+ case PROTOCMD_GETOPTIONS:
+ if(Model.protocol == WK2601)
+ return wk2601_opts;
+ break;
+ case PROTOCMD_TELEMETRYSTATE: return (void *)(long)PROTO_TELEM_UNSUPPORTED;
+ default: break;
+ }
+ return 0;
+}
+*/
+#endif
diff --git a/Multiprotocol/DSM2_cyrf6936.ino b/Multiprotocol/DSM2_cyrf6936.ino
index e6769a6..928d24e 100644
--- a/Multiprotocol/DSM2_cyrf6936.ino
+++ b/Multiprotocol/DSM2_cyrf6936.ino
@@ -42,8 +42,7 @@ enum {
DSM2_CH2_READ_B = BIND_COUNT1 + 10,
};
-
-const uint8_t pncodes[5][9][8] = {
+const uint8_t PROGMEM pncodes[5][9][8] = {
/* Note these are in order transmitted (LSB 1st) */
{ /* Row 0 */
/* Col 0 */ {0x03, 0xBC, 0x6E, 0x8A, 0xEF, 0xBD, 0xFE, 0xF8},
@@ -102,6 +101,12 @@ const uint8_t pncodes[5][9][8] = {
},
};
+static void __attribute__((unused)) read_code(uint8_t *buf, uint8_t row, uint8_t col, uint8_t len)
+{
+ for(uint8_t i=0;i.
- */
+/* **************************
+ * By Midelic on RCGroups *
+ **************************
+ 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 .
+*/
#if defined(FRSKYX_CC2500_INO)
+
+ #include "iface_cc2500.h"
+
+ uint8_t chanskip;
+ uint8_t calData[48][3];
+ uint8_t channr;
+ uint8_t pass_ = 1 ;
+ uint8_t counter_rst;
+ uint8_t ctr;
+ uint8_t FS_flag=0;
+ // uint8_t ptr[4]={0x01,0x12,0x23,0x30};
+ //uint8_t ptr[4]={0x00,0x11,0x22,0x33};
+
+ const PROGMEM uint8_t hop_data[]={
+ 0x02, 0xD4, 0xBB, 0xA2, 0x89,
+ 0x70, 0x57, 0x3E, 0x25, 0x0C,
+ 0xDE, 0xC5, 0xAC, 0x93, 0x7A,
+ 0x61, 0x48, 0x2F, 0x16, 0xE8,
+ 0xCF, 0xB6, 0x9D, 0x84, 0x6B,
+ 0x52, 0x39, 0x20, 0x07, 0xD9,
+ 0xC0, 0xA7, 0x8E, 0x75, 0x5C,
+ 0x43, 0x2A, 0x11, 0xE3, 0xCA,
+ 0xB1, 0x98, 0x7F, 0x66, 0x4D,
+ 0x34, 0x1B, 0x00, 0x1D, 0x03
+ };
-#include "iface_cc2500.h"
+ uint8_t hop(uint8_t byte)
+ {
+ return pgm_read_byte_near(&hop_data[byte]);
+ }
+ uint16_t initFrSkyX()
+ {
+ while(!chanskip)
+ {
+ randomSeed((uint32_t)analogRead(A6) << 10 | analogRead(A7));
+ chanskip=random(0xfefefefe)%47;
+ }
+ while((chanskip-ctr)%4)
+ ctr=(ctr+1)%4;
+
+ counter_rst=(chanskip-ctr)>>2;
+ //for test***************
+ //rx_tx_addr[3]=0xB3;
+ //rx_tx_addr[2]=0xFD;
+ //************************
+ frskyX_init();
+ //
+ if(IS_AUTOBIND_FLAG_on)
+ {
+ state = FRSKY_BIND;
+ initialize_data(1);
+ }
+ else
+ {
+ state = FRSKY_DATA1;
+ initialize_data(0);
+ }
+ return 10000;
+ }
+
+ uint16_t ReadFrSkyX()
+ {
+ switch(state)
+ {
+ default:
+ set_start(47);
+ CC2500_SetPower();
+ cc2500_strobe(CC2500_SFRX);
+ //
+ frskyX_build_bind_packet();
+ cc2500_strobe(CC2500_SIDLE);
+ cc2500_writeFifo(packet, packet[0]+1);
+ state++;
+ return 9000;
+ case FRSKY_BIND_DONE:
+ initialize_data(0);
+ channr=0;
+ BIND_DONE;
+ state++;
+ break;
+ case FRSKY_DATA1:
+ LED_ON;
+ CC2500_SetTxRxMode(TX_EN);
+ set_start(channr);
+ CC2500_SetPower();
+ cc2500_strobe(CC2500_SFRX);
+ channr = (channr+chanskip)%47;
+ cc2500_strobe(CC2500_SIDLE);
+ cc2500_writeFifo(packet, packet[0]+1);
+ //
+ frskyX_data_frame();
+ state++;
+ return 5500;
+ case FRSKY_DATA2:
+ CC2500_SetTxRxMode(RX_EN);
+ cc2500_strobe(CC2500_SIDLE);
+ state++;
+ return 200;
+ case FRSKY_DATA3:
+ cc2500_strobe(CC2500_SRX);
+ state++;
+ return 3000;
+ case FRSKY_DATA4:
+ len = cc2500_readReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
+ if (len &&(len>8) & 0x0F)|(chan_1 << 4)));
+ packet[9+i+2]=crc_Byte(chan_1>>4);
+ }
+ //packet[21]=crc_Byte(0x08);//first
+ packet[21]=crc_Byte(0x80);//??? when received first telemetry frame is changed to 0x80
+ //packet[21]=crc_Byte(ptr[p]);//???
+ //p=(p+1)%4;//repeating 4 bytes sequence pattern every 4th frame.
+
+ pass_=lpass+1;
+
+ for (uint8_t i=22;i<28;i++)
+ packet[i]=crc_Byte(0);
+
+ packet[28]=highByte(crc);
+ packet[29]=lowByte(crc);
+ }
-#endif
+ uint16_t scaleForPXX( uint8_t i )
+ { //mapped 860,2140(125%) range to 64,1984(PXX values);
+ return (uint16_t)(((Servo_data[i]-PPM_MIN)*3)>>1)+64;
+ }
+
+ uint8_t crc_Byte( uint8_t byte )
+ {
+ crc = (crc<<8) ^ pgm_read_word(&CRCTable[((uint8_t)(crc>>8) ^ byte) & 0xFF]);
+ return byte;
+ }
+#endif
\ No newline at end of file
diff --git a/Multiprotocol/FrSky_cc2500.ino b/Multiprotocol/FrSky_cc2500.ino
index dae03c7..f3c6d3c 100644
--- a/Multiprotocol/FrSky_cc2500.ino
+++ b/Multiprotocol/FrSky_cc2500.ino
@@ -20,7 +20,6 @@
//##########Variables########
//uint32_t state;
//uint8_t len;
-uint8_t telemetry_counter=0;
/*
enum {
@@ -128,8 +127,6 @@ static void __attribute__((unused)) frsky2way_build_bind_packet()
packet[17] = 0x01;
}
-
-
static void __attribute__((unused)) frsky2way_data_frame()
{//pachet[4] is telemetry user frame counter(hub)
//11 d7 2d 22 00 01 c9 c9 ca ca 88 88 ca ca c9 ca 88 88
@@ -138,7 +135,11 @@ static void __attribute__((unused)) frsky2way_data_frame()
packet[1] = rx_tx_addr[3];
packet[2] = rx_tx_addr[2];
packet[3] = counter;//
- packet[4]=telemetry_counter;
+ #if defined TELEMETRY
+ packet[4] = telemetry_counter;
+ #else
+ packet[4] = 0x00;
+ #endif
packet[5] = 0x01;
//
diff --git a/Multiprotocol/MT99xx_nrf24l01.ino b/Multiprotocol/MT99xx_nrf24l01.ino
index ab4c825..5e719ed 100644
--- a/Multiprotocol/MT99xx_nrf24l01.ino
+++ b/Multiprotocol/MT99xx_nrf24l01.ino
@@ -37,29 +37,16 @@ enum{
FLAG_MT_FLIP = 0x80,
};
-enum{
- // flags going to ?????? (Yi Zhan i6S)ROLL
- BLABLA,
-};
-
enum {
MT99XX_INIT = 0,
MT99XX_BIND,
MT99XX_DATA
};
-static uint8_t __attribute__((unused)) MT99XX_calcChecksum()
-{
- uint8_t result=checksum_offset;
- for(uint8_t i=0; i<8; i++)
- result += packet[i];
- return result;
-}
-
static void __attribute__((unused)) MT99XX_send_packet()
{
- static const uint8_t yz_p4_seq[] = {0xa0, 0x20, 0x60};
- static const uint8_t mys_byte[] = {
+ const uint8_t yz_p4_seq[] = {0xa0, 0x20, 0x60};
+ const uint8_t mys_byte[] = {
0x01, 0x11, 0x02, 0x12, 0x03, 0x13, 0x04, 0x14,
0x05, 0x15, 0x06, 0x16, 0x07, 0x17, 0x00, 0x10
};
@@ -71,8 +58,8 @@ static void __attribute__((unused)) MT99XX_send_packet()
packet[1] = convert_channel_8b_scale(RUDDER ,0x00,0xE1); // rudder
packet[2] = convert_channel_8b_scale(AILERON ,0x00,0xE1); // aileron
packet[3] = convert_channel_8b_scale(ELEVATOR,0x00,0xE1); // elevator
- packet[4] = convert_channel_8b_scale(AUX5,0x00,0x3F); // pitch trim (0x3f-0x20-0x00)
- packet[5] = convert_channel_8b_scale(AUX6,0x00,0x3F); // roll trim (0x00-0x20-0x3f)
+ packet[4] = 0x20; // pitch trim (0x3f-0x20-0x00)
+ packet[5] = 0x20; // roll trim (0x00-0x20-0x3f)
packet[6] = GET_FLAG( Servo_AUX1, FLAG_MT_FLIP )
| GET_FLAG( Servo_AUX3, FLAG_MT_SNAPSHOT )
| GET_FLAG( Servo_AUX4, FLAG_MT_VIDEO );
@@ -84,7 +71,10 @@ static void __attribute__((unused)) MT99XX_send_packet()
// low nibble: index in chan list ?
// high nibble: 0->start from start of list, 1->start from end of list ?
packet[7] = mys_byte[hopping_frequency_no];
- packet[8] = MT99XX_calcChecksum();
+ uint8_t result=checksum_offset;
+ for(uint8_t i=0; i<8; i++)
+ result += packet[i];
+ packet[8] = result;
}
else
{ // YZ
@@ -100,8 +90,12 @@ static void __attribute__((unused)) MT99XX_send_packet()
packet_count=0;
}
packet[4] = yz_p4_seq[yz_seq_num];
- packet[5] = 0x02; // expert ? (0=unarmed, 1=normal)
- packet[6] = 0x80;
+ packet[5] = 0x02 // expert ? (0=unarmed, 1=normal)
+ | GET_FLAG(Servo_AUX4, 0x10) //VIDEO
+ | GET_FLAG(Servo_AUX1, 0x80) //FLIP
+ | GET_FLAG(Servo_AUX5, 0x04) //HEADLESS
+ | GET_FLAG(Servo_AUX3, 0x20); //SNAPSHOT
+ packet[6] = GET_FLAG(Servo_AUX2, 0x80); //LED
packet[7] = packet[0];
for(uint8_t idx = 1; idx < MT99XX_PACKET_SIZE-2; idx++)
packet[7] += packet[idx];
@@ -138,7 +132,10 @@ static void __attribute__((unused)) MT99XX_init()
else
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_SetPower();
- XN297_SetTXAddr((uint8_t *)"\0xCC\0xCC\0xCC\0xCC\0xCC", 5);
+
+ XN297_Configure(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP) | (sub_protocol == YZ ? BV(XN297_UNSCRAMBLED):0) );
+
+ XN297_SetTXAddr((uint8_t *)"\xCC\xCC\xCC\xCC\xCC", 5);
}
static void __attribute__((unused)) MT99XX_initialize_txid()
@@ -190,7 +187,7 @@ uint16_t initMT99XX(void)
BIND_IN_PROGRESS; // autobind protocol
bind_counter = MT99XX_BIND_COUNT;
- memcpy(hopping_frequency,"\0x02\0x48\0x0C\0x3e\0x16\0x34\0x20\0x2A,\0x2A\0x20\0x34\0x16\0x3e\0x0c\0x48\0x02",16);
+ memcpy(hopping_frequency,"\x02\x48\x0C\x3e\x16\x34\x20\x2A\x2A\x20\x34\x16\x3e\x0c\x48\x02",16);
MT99XX_initialize_txid();
MT99XX_init();
@@ -210,11 +207,11 @@ uint16_t initMT99XX(void)
packet[2] = 0x05;
packet[3] = 0x06;
}
- packet[4] = rx_tx_addr[0]; // 1th byte for data state tx address
- packet[5] = rx_tx_addr[1]; // 2th byte for data state tx address (always 0x00 on Yi Zhan ?)
- packet[6] = 0x00; // 3th byte for data state tx address (always 0x00 ?)
+ packet[4] = rx_tx_addr[0]; // 1st byte for data state tx address
+ packet[5] = rx_tx_addr[1]; // 2nd byte for data state tx address (always 0x00 on Yi Zhan ?)
+ packet[6] = 0x00; // 3rd byte for data state tx address (always 0x00 ?)
packet[7] = checksum_offset; // checksum offset
- packet[8] = 0xAA; // fixed
+ packet[8] = 0xAA; // fixed
packet_count=0;
return MT99XX_INITIAL_WAIT+MT99XX_PACKET_PERIOD_MT;
}
diff --git a/Multiprotocol/Multiprotocol.ino b/Multiprotocol/Multiprotocol.ino
index e9fa9e6..46f6697 100644
--- a/Multiprotocol/Multiprotocol.ino
+++ b/Multiprotocol/Multiprotocol.ino
@@ -1,6 +1,7 @@
/*********************************************************
Multiprotocol Tx code
by Midelic and Pascal Langer(hpnuts)
+ fork by Tipouic
http://www.rcgroups.com/forums/showthread.php?t=2165676
https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/edit/master/README.md
@@ -29,7 +30,6 @@
#include "_Config.h"
//Global constants/variables
-
uint32_t MProtocol_id;//tx id,
uint32_t MProtocol_id_master;
uint32_t Model_fixed_id=0;
@@ -48,7 +48,7 @@ uint8_t Servo_AUX;
// PPM variable
volatile uint16_t PPM_data[NUM_CHN];
-// NRF variables
+// Protocol variables
uint8_t rx_tx_addr[5];
uint8_t phase;
uint16_t bind_counter;
@@ -65,6 +65,7 @@ uint8_t hopping_frequency_no=0;
uint8_t rf_ch_num;
uint8_t throttle, rudder, elevator, aileron;
uint8_t flags;
+uint16_t crc;
//
uint32_t state;
uint8_t len;
@@ -100,6 +101,7 @@ uint8_t pktt[MAX_PKT];//telemetry receiving packets
int16_t RSSI_dBm;
//const uint8_t RSSI_offset=72;//69 71.72 values db
uint8_t telemetry_link=0;
+ uint8_t telemetry_counter=0;
#endif
// Callback
@@ -313,6 +315,49 @@ static void protocol_init()
switch(cur_protocol[0]&0x1F) // Init the requested protocol
{
+#if defined(HM830_NRF24L01_INO)
+ case MODE_HM830:
+ next_callback=HM830_setup();
+ remote_callback = HM830_callback;
+ break;
+#endif
+#if defined(CFlie_NRF24L01_INO)
+ case MODE_CFLIE:
+ next_callback=Cflie_setup();
+ remote_callback = cflie_callback;
+ break;
+#endif
+#if defined(JOYSWAY_A7105_INO)
+ case MODE_JOYSWAY:
+ next_callback=JOYSWAY_Setup();
+ remote_callback = joysway_cb;
+ break;
+#endif
+#if defined(H377_NRF24L01_INO)
+ case MODE_H377:
+ next_callback=h377_setup();
+ remote_callback = h377_cb;
+ break;
+#endif
+#if defined(J6PRO_CYRF6936_INO)
+ case MODE_J6PRO:
+ next_callback=j6pro_setup();
+ remote_callback = j6pro_cb;
+ break;
+#endif
+#if defined(WK2x01_CYRF6936_INO)
+ case MODE_WK2x01:
+ next_callback=wk_setup();
+ remote_callback = wk_cb;
+ break;
+#endif
+#if defined(FY326_NRF24L01_INO)
+ case MODE_FY326:
+ next_callback=FY326_setup();
+ remote_callback = fy326_callback;
+ break;
+#endif
+
#if defined(FLYSKY_A7105_INO)
case MODE_FLYSKY:
CTRL1_off; //antenna RF1
diff --git a/Multiprotocol/NRF24l01_SPI.ino b/Multiprotocol/NRF24l01_SPI.ino
index c14f5d5..cec1439 100644
--- a/Multiprotocol/NRF24l01_SPI.ino
+++ b/Multiprotocol/NRF24l01_SPI.ino
@@ -257,6 +257,7 @@ uint8_t NRF24L01_packet_ack()
///////////////
// XN297 emulation layer
+uint8_t xn297_scramble_enabled;
uint8_t xn297_addr_len;
uint8_t xn297_tx_addr[5];
uint8_t xn297_rx_addr[5];
@@ -269,9 +270,16 @@ static const uint8_t xn297_scramble[] = {
0x1b, 0x5d, 0x19, 0x10, 0x24, 0xd3, 0xdc, 0x3f,
0x8e, 0xc5, 0x2f};
-static const uint16_t xn297_crc_xorout[] = {
- 0x0000, 0x3448, 0x9BA7, 0x8BBB, 0x85E1, 0x3E8C, // 1st entry is missing, probably never needed
- 0x451E, 0x18E6, 0x6B24, 0xE7AB, 0x3828, 0x814B, // it's used for 3-byte address w/ 0 byte payload only
+const uint16_t PROGMEM xn297_crc_xorout[] = {
+ 0x0000, 0x3d5f, 0xa6f1, 0x3a23, 0xaa16, 0x1caf,
+ 0x62b2, 0xe0eb, 0x0821, 0xbe07, 0x5f1a, 0xaf15,
+ 0x4f0a, 0xad24, 0x5e48, 0xed34, 0x068c, 0xf2c9,
+ 0x1852, 0xdf36, 0x129d, 0xb17c, 0xd5f5, 0x70d7,
+ 0xb798, 0x5133, 0x67db, 0xd94e};
+
+const uint16_t PROGMEM xn297_crc_xorout_scrambled[] = {
+ 0x0000, 0x3448, 0x9BA7, 0x8BBB, 0x85E1, 0x3E8C,
+ 0x451E, 0x18E6, 0x6B24, 0xE7AB, 0x3828, 0x814B,
0xD461, 0xF494, 0x2503, 0x691D, 0xFE8B, 0x9BA7,
0x8B17, 0x2920, 0x8B5F, 0x61B1, 0xD391, 0x7401,
0x2138, 0x129F, 0xB3A0, 0x2988};
@@ -327,16 +335,21 @@ void XN297_SetRXAddr(const uint8_t* addr, uint8_t len)
memcpy(buf, addr, len);
memcpy(xn297_rx_addr, addr, len);
for (uint8_t i = 0; i < xn297_addr_len; ++i)
- buf[i] = xn297_rx_addr[i] ^ xn297_scramble[xn297_addr_len-i-1];
+ {
+ buf[i] = xn297_rx_addr[i];
+ if(xn297_scramble_enabled)
+ buf[i] ^= xn297_scramble[xn297_addr_len-i-1];
+ }
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, len-2);
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, buf, 5);
}
-void XN297_Configure(uint8_t flags)
+void XN297_Configure(uint16_t flags)
{
+ xn297_scramble_enabled = !(flags & BV(XN297_UNSCRAMBLED));
xn297_crc = !!(flags & BV(NRF24L01_00_EN_CRC));
flags &= ~(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO));
- NRF24L01_WriteReg(NRF24L01_00_CONFIG, flags);
+ NRF24L01_WriteReg(NRF24L01_00_CONFIG, flags & 0xFF);
}
void XN297_WritePayload(uint8_t* msg, uint8_t len)
@@ -352,12 +365,20 @@ void XN297_WritePayload(uint8_t* msg, uint8_t len)
buf[last++] = 0x55;
}
for (uint8_t i = 0; i < xn297_addr_len; ++i)
- buf[last++] = xn297_tx_addr[xn297_addr_len-i-1] ^ xn297_scramble[i];
-
- for (uint8_t i = 0; i < len; ++i) {
+ {
+ buf[last] = xn297_tx_addr[xn297_addr_len-i-1];
+ if(xn297_scramble_enabled)
+ buf[last] ^= xn297_scramble[i];
+ last++;
+ }
+ for (uint8_t i = 0; i < len; ++i)
+ {
// bit-reverse bytes in packet
uint8_t b_out = bit_reverse(msg[i]);
- buf[last++] = b_out ^ xn297_scramble[xn297_addr_len+i];
+ buf[last] = b_out;
+ if(xn297_scramble_enabled)
+ buf[last] ^= xn297_scramble[xn297_addr_len+i];
+ last++;
}
if (xn297_crc)
{
@@ -365,7 +386,10 @@ void XN297_WritePayload(uint8_t* msg, uint8_t len)
uint16_t crc = 0xb5d2;
for (uint8_t i = offset; i < last; ++i)
crc = crc16_update(crc, buf[i]);
- crc ^= xn297_crc_xorout[xn297_addr_len - 3 + len];
+ if(xn297_scramble_enabled)
+ crc ^= pgm_read_word(&xn297_crc_xorout_scrambled[xn297_addr_len - 3 + len]);
+ else
+ crc ^= pgm_read_word(&xn297_crc_xorout[xn297_addr_len - 3 + len]);
buf[last++] = crc >> 8;
buf[last++] = crc & 0xff;
}
@@ -374,9 +398,14 @@ void XN297_WritePayload(uint8_t* msg, uint8_t len)
void XN297_ReadPayload(uint8_t* msg, uint8_t len)
{
+ // TODO: if xn297_crc==1, check CRC before filling *msg
NRF24L01_ReadPayload(msg, len);
for(uint8_t i=0; i.
+ */
+
+/* NB: Not implemented
+ Uncomment define below to enable telemetry. Also add CFlie protocol to TELEMETRY_SetTypeByProtocol to set type to DSM.
+#define CFLIE_TELEMETRY
+ */
+
+
+#if defined(CFlie_NRF24L01_INO)
+#include "iface_nrf24l01.h"
+
+#define BIND_COUNT 60
+
+// Address size
+#define TX_ADDR_SIZE 5
+
+// Timeout for callback in uSec, 10ms=10000us for Crazyflie
+#define PACKET_PERIOD 10000
+
+
+// For code readability
+enum {
+ CHANNEL1 = 0,
+ CHANNEL2,
+ CHANNEL3,
+ CHANNEL4,
+ CHANNEL5,
+ CHANNEL6,
+ CHANNEL7,
+ CHANNEL8,
+ CHANNEL9,
+ CHANNEL10
+};
+
+#define PAYLOADSIZE 8 // receive data pipes set to this size, but unused
+#define MAX_PACKET_SIZE 9 // YD717 packets have 8-byte payload, Syma X4 is 9
+
+//static uint8_t packet[MAX_PACKET_SIZE];
+
+static uint8_t data_rate, rf_channel;
+
+enum {
+ CFLIE_INIT_SEARCH = 0,
+ CFLIE_INIT_DATA,
+ CFLIE_SEARCH,
+ CFLIE_DATA
+};
+
+#ifdef CFLIE_TELEMETRY
+static const char * const cflie_opts[] = {
+ _tr_noop("Telemetry"), _tr_noop("Off"), _tr_noop("On"), NULL,
+ NULL
+};
+enum {
+ PROTOOPTS_TELEMETRY = 0,
+ LAST_PROTO_OPT,
+};
+ctassert(LAST_PROTO_OPT <= NUM_PROTO_OPTS, too_many_protocol_opts);
+
+#define TELEM_OFF 0
+#define TELEM_ON 1
+#endif
+
+#define PACKET_CHKTIME 500 // time to wait if packet not yet acknowledged or timed out
+
+static uint16_t dbg_cnt = 0;
+static uint8_t packet_ack() {
+ if (++dbg_cnt > 50) { dbg_cnt = 0; }
+ switch (NRF24L01_ReadReg(NRF24L01_07_STATUS) & (BV(NRF24L01_07_TX_DS) | BV(NRF24L01_07_MAX_RT))) {
+ case BV(NRF24L01_07_TX_DS):
+ return PKT_ACKED;
+ case BV(NRF24L01_07_MAX_RT):
+ return PKT_TIMEOUT;
+ }
+ return PKT_PENDING;
+}
+
+static void set_rate_channel(uint8_t rate, uint8_t channel) {
+ NRF24L01_WriteReg(NRF24L01_05_RF_CH, channel); // Defined by model id
+ NRF24L01_SetBitrate(rate); // Defined by model id
+}
+
+static void send_search_packet() {
+ uint8_t buf[1];
+ buf[0] = 0xff;
+ // clear packet status bits and TX FIFO
+ NRF24L01_WriteReg(NRF24L01_07_STATUS, (BV(NRF24L01_07_TX_DS) | BV(NRF24L01_07_MAX_RT)));
+ NRF24L01_FlushTx();
+
+ if (rf_channel++ > 125) {
+ rf_channel = 0;
+ switch(data_rate) {
+ case NRF24L01_BR_250K:
+ data_rate = NRF24L01_BR_1M;
+ break;
+ case NRF24L01_BR_1M:
+ data_rate = NRF24L01_BR_2M;
+ break;
+ case NRF24L01_BR_2M:
+ data_rate = NRF24L01_BR_250K;
+ break;
+ }
+ }
+
+ set_rate_channel(data_rate, rf_channel);
+
+ NRF24L01_WritePayload(buf, sizeof(buf));
+
+ ++packet_counter;
+}
+
+// Frac 16.16
+#define FRAC_MANTISSA 16
+#define FRAC_SCALE (1 << FRAC_MANTISSA)
+
+// Convert fractional 16.16 to float32
+static void frac2float(uint32_t n, float* res) {
+ if (n == 0) {
+ *res = 0.0;
+ return;
+ }
+ uint32_t m = n < 0 ? -n : n;
+ int i;
+ for (i = (31-FRAC_MANTISSA); (m & 0x80000000) == 0; i--, m <<= 1) ;
+ m <<= 1; // Clear implicit leftmost 1
+ m >>= 9;
+ uint32_t e = 127 + i;
+ if (n < 0) m |= 0x80000000;
+ m |= e << 23;
+ *((uint32_t *) res) = m;
+}
+
+static void send_cmd_packet() {
+ // Commander packet, 15 bytes
+ uint8_t buf[15];
+ float x_roll, x_pitch, yaw;
+
+ // Channels in AETR order
+
+ // Roll, aka aileron, float +- 50.0 in degrees
+ // float roll = -(float) Servo_data[AILERON]*50.0/10000;
+ uint32_t f_roll = -Servo_data[AILERON] * FRAC_SCALE / (10000 / 50);
+
+ // Pitch, aka elevator, float +- 50.0 degrees
+ //float pitch = -(float) Servo_data[ELEVATOR]*50.0/10000;
+ uint32_t f_pitch = -Servo_data[ELEVATOR] * FRAC_SCALE / (10000 / 50);
+
+ // Thrust, aka throttle 0..65535, working range 5535..65535
+ // No space for overshoot here, hard limit Channel3 by -10000..10000
+ uint32_t ch = Servo_data[THROTTLE];
+ if (ch < PPM_MIN) {
+ ch = PPM_MIN;
+ } else if (ch > PPM_MAX) {
+ ch = PPM_MAX;
+ }
+ uint16_t thrust = ch*3L + 35535L;
+
+ // Yaw, aka rudder, float +- 400.0 deg/s
+ // float yaw = -(float) Servo_data[RUDDER]*400.0/10000;
+ uint32_t f_yaw = - Servo_data[RUDDER] * FRAC_SCALE / (10000 / 400);
+ frac2float(f_yaw, &yaw);
+
+ // Convert + to X. 181 / 256 = 0.70703125 ~= sqrt(2) / 2
+ uint32_t f_x_roll = (f_roll + f_pitch) * 181 / 256;
+ frac2float(f_x_roll, &x_roll);
+ uint32_t f_x_pitch = (f_pitch - f_roll) * 181 / 256;
+ frac2float(f_x_pitch, &x_pitch);
+
+ int bufptr = 0;
+ buf[bufptr++] = 0x30; // Commander packet to channel 0
+ memcpy(&buf[bufptr], (char*) &x_roll, 4); bufptr += 4;
+ memcpy(&buf[bufptr], (char*) &x_pitch, 4); bufptr += 4;
+ memcpy(&buf[bufptr], (char*) &yaw, 4); bufptr += 4;
+ memcpy(&buf[bufptr], (char*) &thrust, 2); bufptr += 2;
+
+
+ // clear packet status bits and TX FIFO
+ NRF24L01_WriteReg(NRF24L01_07_STATUS, (BV(NRF24L01_07_TX_DS) | BV(NRF24L01_07_MAX_RT)));
+ NRF24L01_FlushTx();
+
+ NRF24L01_WritePayload(buf, sizeof(buf));
+
+ ++packet_counter;
+
+ NRF24L01_SetPower();
+}
+
+static int cflie_init() {
+ NRF24L01_Initialize();
+
+ // CRC, radio on
+ NRF24L01_SetTxRxMode(TX_EN);
+ NRF24L01_WriteReg(NRF24L01_00_CONFIG, BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP));
+ // NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowledgement
+ NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x01); // Auto Acknowledgement for data pipe 0
+ NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0
+ NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, TX_ADDR_SIZE-2); // 5-byte RX/TX address
+ NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x13); // 3 retransmits, 500us delay
+
+ NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_channel); // Defined by model id
+ NRF24L01_SetBitrate(data_rate); // Defined by model id
+
+ NRF24L01_SetPower();
+ NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
+
+ NRF24L01_WriteReg(NRF24L01_17_FIFO_STATUS, 0x00); // Just in case, no real bits to write here
+
+ // this sequence necessary for module from stock tx
+ NRF24L01_ReadReg(NRF24L01_1D_FEATURE);
+ NRF24L01_Activate(0x73); // Activate feature register
+ NRF24L01_ReadReg(NRF24L01_1D_FEATURE);
+
+ NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x01); // Enable Dynamic Payload Length on pipe 0
+ NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x06); // Enable Dynamic Payload Length, enable Payload with ACK
+
+
+ // NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_tx_addr, TX_ADDR_SIZE);
+ NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, TX_ADDR_SIZE);
+
+ NRF24L01_Activate(0x53); // switch bank back
+
+ // 50ms delay in callback
+ return 50000;
+}
+
+
+#ifdef CFLIE_TELEMETRY
+static void update_telemetry() {
+ static uint8_t frameloss = 0;
+
+ frameloss += NRF24L01_ReadReg(NRF24L01_08_OBSERVE_TX) >> 4;
+ NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_channel); // reset packet loss counter
+
+ Telemetry.p.dsm.flog.frameloss = frameloss;
+// Telemetry.p.dsm.flog.volt[0] = read battery voltage from ack payload
+ TELEMETRY_SetUpdated(TELEM_DSM_FLOG_FRAMELOSS);
+}
+#endif
+
+
+static uint16_t cflie_callback() {
+ switch (phase) {
+ case CFLIE_INIT_SEARCH:
+ send_search_packet();
+ phase = CFLIE_SEARCH;
+ break;
+ case CFLIE_INIT_DATA:
+ send_cmd_packet();
+ phase = CFLIE_DATA;
+ break;
+ case CFLIE_SEARCH:
+ switch (packet_ack()) {
+ case PKT_PENDING:
+ return PACKET_CHKTIME; // packet send not yet complete
+ case PKT_ACKED:
+ phase = CFLIE_DATA;
+ BIND_DONE;
+ break;
+ case PKT_TIMEOUT:
+ send_search_packet();
+ counter = BIND_COUNT;
+ }
+ break;
+ case CFLIE_DATA:
+ #ifdef CFLIE_TELEMETRY
+ update_telemetry();
+ #endif
+ if (packet_ack() == PKT_PENDING)
+ return PACKET_CHKTIME; // packet send not yet complete
+ send_cmd_packet();
+ break;
+ }
+ return PACKET_PERIOD; // Packet at standard protocol interval
+}
+
+
+// Generate address to use from TX id and manufacturer id (STM32 unique id)
+static uint8_t initialize_rx_tx_addr() {
+ rx_tx_addr[0] =
+ rx_tx_addr[1] =
+ rx_tx_addr[2] =
+ rx_tx_addr[3] =
+ rx_tx_addr[4] = 0xE7; // CFlie uses fixed address
+
+ data_rate = NRF24L01_BR_250K;
+ rf_channel = 0;
+ return CFLIE_INIT_SEARCH;
+ // return CFLIE_INIT_DATA;
+}
+
+static uint16_t Cflie_setup() {
+ phase = initialize_rx_tx_addr();
+ packet_counter = 0;
+
+ int delay = cflie_init();
+
+ #ifdef CFLIE_TELEMETRY
+ memset(&Telemetry, 0, sizeof(Telemetry));
+ TELEMETRY_SetType(TELEM_DSM);
+ #endif
+ if (phase == CFLIE_INIT_SEARCH) { BIND_IN_PROGRESS; }
+ return delay;
+}
+
+#endif
diff --git a/Multiprotocol/Nrf24l01_fy326.ino b/Multiprotocol/Nrf24l01_fy326.ino
new file mode 100644
index 0000000..5fe0a92
--- /dev/null
+++ b/Multiprotocol/Nrf24l01_fy326.ino
@@ -0,0 +1,234 @@
+/*
+ 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.
+
+ Deviation 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 Deviation. If not, see .
+ */
+
+
+#if defined(FY326_NRF24L01_INO)
+#include "iface_nrf24l01.h"
+
+#define INITIAL_WAIT 500
+#define FY326_PERIOD 1500 // Timeout for callback in uSec
+#define FY326_CHKTIME 300 // Time to wait if packet not yet received or sent
+#define FY326_SIZE 15
+#define FY326_BIND_COUNT 16
+
+
+static const char * const fy326_opts[] = {
+ _tr_noop("Expert"), _tr_noop("On"), _tr_noop("Off"), NULL,
+ NULL
+};
+#define EXPERT_ON 0
+#define EXPERT_OFF 1
+
+#define CHANNEL_FLIP AUX1
+#define CHANNEL_HEADLESS AUX2
+#define CHANNEL_RTH AUX3
+#define CHANNEL_CALIBRATE AUX4
+
+static uint8_t tx_power;
+static uint8_t packet[FY326_SIZE];
+
+// frequency channel management
+#define RF_BIND_CHANNEL 0x17
+#define NUM_RF_CHANNELS 5
+static uint8_t current_chan;
+static uint8_t rf_chans[NUM_RF_CHANNELS];
+static uint8_t txid[5];
+static uint8_t rxid;
+
+enum {
+ FY326_INIT1 = 0,
+ FY326_BIND1,
+ FY326_BIND2,
+ FY326_DATA
+};
+
+// Bit vector from bit position
+#define BV(bit) (1 << bit)
+
+#define CHAN_RANGE (CHAN_MAX_VALUE - CHAN_MIN_VALUE)
+static uint8_t scale_channel(uint8_t ch, uint8_t destMin, uint8_t destMax)
+{
+ uint32_t chanval = Channels[ch];
+ uint32_t range = destMax - destMin;
+
+ if (chanval < CHAN_MIN_VALUE) chanval = CHAN_MIN_VALUE;
+ else if (chanval > CHAN_MAX_VALUE) chanval = CHAN_MAX_VALUE;
+ return (range * (chanval - CHAN_MIN_VALUE)) / CHAN_RANGE + destMin;
+}
+
+#define GET_FLAG(ch, mask) (Channels[ch] > 0 ? mask : 0)
+#define CHAN_TO_TRIM(chanval) ((uint8_t)(((uint16_t)chanval/10)-10)) // scale to [-10,10]. [-20,20] caused problems.
+static void send_packet(uint8_t bind)
+{
+ packet[0] = txid[3];
+ if (bind) {
+ packet[1] = 0x55;
+ } else {
+ packet[1] = GET_FLAG(CHANNEL_HEADLESS, 0x80)
+ | GET_FLAG(CHANNEL_RTH, 0x40)
+ | GET_FLAG(CHANNEL_FLIP, 0x02)
+ | GET_FLAG(CHANNEL_CALIBRATE, 0x01)
+ | (Model.proto_opts[PROTOOPTS_EXPERT] == EXPERT_ON ? 4 : 0);
+ }
+ packet[2] = 200 - scale_channel(AILERON, 0, 200); // aileron
+ packet[3] = scale_channel(ELEVATOR, 0, 200); // elevator
+ packet[4] = 200 - scale_channel(RUDDER, 0, 200); // rudder
+ packet[5] = scale_channel(THROTTLE, 0, 200); // throttle
+ packet[6] = txid[0];
+ packet[7] = txid[1];
+ packet[8] = txid[2];
+ packet[9] = CHAN_TO_TRIM(packet[2]); // aileron_trim;
+ packet[10] = CHAN_TO_TRIM(packet[3]); // elevator_trim;
+ packet[11] = CHAN_TO_TRIM(packet[4]); // rudder_trim;
+ packet[12] = 0; // throttle_trim;
+ packet[13] = rxid;
+ packet[14] = txid[4];
+
+ if (bind) {
+ NRF24L01_WriteReg(NRF24L01_05_RF_CH, RF_BIND_CHANNEL);
+ } else {
+ NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_chans[current_chan++]);
+ current_chan %= NUM_RF_CHANNELS;
+ }
+
+ // clear packet status bits and TX FIFO
+ NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
+ NRF24L01_FlushTx();
+
+ NRF24L01_WritePayload(packet, FY326_SIZE);
+
+ // Check and adjust transmission power. We do this after
+ // transmission to not bother with timeout after power
+ // settings change - we have plenty of time until next
+ // packet.
+ if (tx_power != Model.tx_power) {
+ //Keep transmit power updated
+ tx_power = Model.tx_power;
+ NRF24L01_SetPower(tx_power);
+ }
+}
+
+static void fy326_init()
+{
+ const uint8_t rx_tx_addr[] = {0x15, 0x59, 0x23, 0xc6, 0x29};
+
+ NRF24L01_Initialize();
+ NRF24L01_SetTxRxMode(TX_EN);
+ NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x01); // Three-byte rx/tx address
+ NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, sizeof(rx_tx_addr));
+ NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_tx_addr, sizeof(rx_tx_addr));
+ NRF24L01_FlushTx();
+ NRF24L01_FlushRx();
+ NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
+ NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
+ NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
+ NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, FY326_SIZE);
+ NRF24L01_WriteReg(NRF24L01_05_RF_CH, RF_BIND_CHANNEL);
+ NRF24L01_SetBitrate(NRF24L01_BR_250K);
+ NRF24L01_SetPower(Model.tx_power);
+
+ NRF24L01_Activate(0x73);
+ NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x3f);
+ NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x07);
+}
+
+static uint16_t fy326_callback()
+{
+ switch (phase) {
+ case FY326_INIT1:
+ MUSIC_Play(MUSIC_TELEMALARM1);
+ bind_counter = FY326_BIND_COUNT;
+ phase = FY326_BIND2;
+ send_packet(1);
+ return FY326_CHKTIME;
+ break;
+
+ case FY326_BIND1:
+#ifdef EMULATOR
+ if (1) {
+ packet[13] = 0x7e;
+#else
+ if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & BV(NRF24L01_07_RX_DR)) { // RX fifo data ready
+ NRF24L01_ReadPayload(packet, FY326_SIZE);
+#endif
+ rxid = packet[13];
+ txid[0] = 0xaa;
+ NRF24L01_SetTxRxMode(TXRX_OFF);
+ NRF24L01_SetTxRxMode(TX_EN);
+ PROTOCOL_SetBindState(0);
+ MUSIC_Play(MUSIC_DONE_BINDING);
+ phase = FY326_DATA;
+ } else if (bind_counter-- == 0) {
+ bind_counter = FY326_BIND_COUNT;
+ NRF24L01_SetTxRxMode(TXRX_OFF);
+ NRF24L01_SetTxRxMode(TX_EN);
+ send_packet(1);
+ phase = FY326_BIND2;
+ return FY326_CHKTIME;
+ }
+ break;
+
+ case FY326_BIND2:
+#ifdef EMULATOR
+ if (1) {
+#else
+ if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & BV(NRF24L01_07_TX_DS)) { // TX data sent
+#endif
+ // switch to RX mode
+ NRF24L01_SetTxRxMode(TXRX_OFF);
+ NRF24L01_FlushRx();
+ NRF24L01_SetTxRxMode(RX_EN);
+ phase = FY326_BIND1;
+ } else {
+ return FY326_CHKTIME;
+ }
+ break;
+
+ case FY326_DATA:
+ send_packet(0);
+ break;
+ }
+ return FY326_PERIOD;
+}
+
+// Generate address to use from TX id and manufacturer id (STM32 unique id)
+static void fy_txid()
+{
+ txid[0] = (MProtocol_id_master >> 24) & 0xFF;
+ txid[1] = ((MProtocol_id_master >> 16) & 0xFF);
+ txid[2] = (MProtocol_id_master >> 8) & 0xFF;
+ txid[3] = MProtocol_id_master & 0xFF;
+ for (uint8_t i = 0; i < sizeof(MProtocol_id_master); ++i) rand32_r(&MProtocol_id_master, 0);
+ txid[4] = MProtocol_id_master & 0xFF;
+
+ rf_chans[0] = txid[0] & 0x0F;
+ rf_chans[1] = 0x10 + (txid[0] >> 4);
+ rf_chans[2] = 0x20 + (txid[1] & 0x0F);
+ rf_chans[3] = 0x30 + (txid[1] >> 4);
+ rf_chans[4] = 0x40 + (txid[2] >> 4);
+}
+
+static uint16_t FY326_setup()
+{
+ BIND_IN_PROGRESS;
+ tx_power = Model.tx_power;
+ rxid = 0xaa;
+ phase = FY326_INIT1;
+ bind_counter = FY326_BIND_COUNT;
+ fy_txid();
+ fy326_init();
+ return INITIAL_WAIT;
+}
+#endif
diff --git a/Multiprotocol/Nrf24l01_h377.ino b/Multiprotocol/Nrf24l01_h377.ino
new file mode 100644
index 0000000..e8feaf3
--- /dev/null
+++ b/Multiprotocol/Nrf24l01_h377.ino
@@ -0,0 +1,210 @@
+/*
+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.
+
+Deviation 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 Deviation. If not, see .
+*/
+
+#if defined (H377_NRF24L01_INO)
+#include "iface_nrf24l01.h"
+
+#define BIND_COUNT 800
+
+
+#define TXID_H377_SIZE 5
+
+#define FREQUENCE_NUM_H377 20
+#define SET_NUM_H377 9
+// available frequency must be in between 2402 and 2477
+
+static uint8_t binding_ch=0x50;
+static uint8_t hopping_frequency_data[SET_NUM_H377] = {0x1c,0x1b,0x1d,0x11,0x0e,0x0d,0x01,0x1d,0x15};
+
+static const uint8_t binding_adr_rf[5]={0x32,0xaa,0x45,0x45,0x78};
+
+static uint8_t rf_adr_buf[5];
+static uint8_t rf_adr_buf_data[SET_NUM_H377][5] = {
+ {0xad,0x9a,0xa6,0x69,0xb2},//ansheng
+ {0x92,0x9a,0x9d,0x69,0x99},//dc59
+ {0x92,0xb2,0x9d,0x69,0x9a},//small two
+ {0xad,0x9a,0x5a,0x69,0x96},//james_1
+ {0x95,0x9a,0x52,0x69,0x99},//james_2
+ {0x52,0x52,0x52,0x69,0xb9},//james_3
+ {0x52,0x52,0x52,0x52,0x55},//small two_1
+ {0x92,0xB2,0x9D,0x69,0x9A},//small two_2
+ {0x96,0x9A,0x45,0x69,0xB2}//small two_3
+};
+
+static uint8_t bind_buf_array[10];
+static uint8_t bind_buf_array_data[SET_NUM_H377][4] = {
+ {0xcf,0x1c,0x19,0x1a},
+ {0xff,0x48,0x19,0x19},
+ {0xf3,0x4d,0x19,0x19},
+ {0x9e,0x1f,0x19,0x19},
+ {0x8d,0x3d,0x19,0x19},
+ {0xbd,0x23,0x19,0x19},
+ {0xF3,0x28,0x19,0x19},
+ {0xF3,0x4D,0x19,0x19},
+ {0x82,0x8D,0x19,0x19}
+};
+
+
+static unsigned int ch_data[8];
+static uint8_t payload[10];
+static uint8_t counter1ms;
+
+static int select_ch_id = 0;
+
+static void h377_binding_packet(void) { //bind_buf_array
+ uint8_t i;
+ counter1ms = 0;
+ hopping_frequency_no = 0;
+
+ for(i=0;i<5;i++)
+ bind_buf_array[i] = rf_adr_buf[i];
+
+ bind_buf_array[5] = hopping_frequency[0];
+
+ for(i=0;i<4;i++)
+ bind_buf_array[i+6] = bind_buf_array_data[select_ch_id][i];
+}
+
+static void h377_init() {
+ NRF24L01_Initialize();
+
+ NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable p0 rx
+ NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknoledgement
+ NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rf_adr_buf, 5);
+ NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rf_adr_buf, 5);
+ NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, 10); // payload size = 10
+ //NRF24L01_WriteReg(NRF24L01_05_RF_CH, 81); // binding packet must be set in channel 81
+ NRF24L01_WriteReg(NRF24L01_05_RF_CH, binding_ch); // binding packet must be set in channel 81
+
+ // 2-bytes CRC, radio off
+ NRF24L01_SetTxRxMode(TX_EN);
+ NRF24L01_WriteReg(NRF24L01_00_CONFIG, BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP));
+ NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address (byte -2)
+ NRF24L01_SetBitrate(0); // 1Mbps
+ NRF24L01_SetPower();
+ NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
+}
+
+// H377 channel sequence: AILE ELEV THRO RUDD GEAR PITH, channel data value is from 0 to 1000
+static void h377_ch_data() {
+ uint32_t temp;
+ uint8_t i;
+ for (i = 0; i< 8; i++) {
+ temp = (uint32_t)Servo_data[i] * 450/PPM_MAX + 500; // max/min servo range is +-125%
+ if (i == 2) // It is clear that h377's thro stick is made reversely, so I adjust it here on purpose
+ temp = 1000 -temp;
+ //if (i == 0) // It is clear that h377's thro stick is made reversely, so I adjust it here on purpose
+ // temp = 1000 -temp;
+ //if (i == 1) // It is clear that h377's thro stick is made reversely, so I adjust it here on purpose
+ // temp = 1000 -temp;
+ if (temp < 0)
+ ch_data[i] = 0;
+ else if (temp > 1000)
+ ch_data[i] = 1000;
+ else
+ ch_data[i] = (unsigned int)temp;
+ payload[i] = (uint8_t)ch_data[i];
+ }
+ payload[8] = (uint8_t)((ch_data[0]>>8)&0x0003);
+ payload[8] |= (uint8_t)((ch_data[1]>>6)&0x000c);
+ payload[8] |= (uint8_t)((ch_data[2]>>4)&0x0030);
+ payload[8] |= (uint8_t)((ch_data[3]>>2)&0x00c0);
+
+ payload[9] = (uint8_t)((ch_data[4]>>8)&0x0003);
+ payload[9] |= (uint8_t)((ch_data[5]>>6)&0x000c);
+ payload[9] |= (uint8_t)((ch_data[6]>>4)&0x0030);
+ payload[9] |= (uint8_t)((ch_data[7]>>2)&0x00c0);
+}
+
+static uint16_t h377_cb() {
+ counter1ms++;
+ if(counter1ms==1) { NRF24L01_FlushTx(); }
+ //-------------------------
+ else if(counter1ms==2) {
+ if (counter>0) {
+ NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t *)binding_adr_rf, 5);
+ NRF24L01_WriteReg(NRF24L01_05_RF_CH, binding_ch);
+ }
+ }
+ else if(counter1ms==3) {
+ if (counter >0) {
+ counter--;
+ if (! counter) { BIND_DONE; } // binding finished, change tx add
+ NRF24L01_WritePayload(bind_buf_array,10);
+ }
+ }
+ else if (counter1ms==4) { if (counter > 0) { NRF24L01_FlushTx(); }}
+ //-------------------------
+ else if(counter1ms==5) { NRF24L01_SetPower(); }
+ //-------------------------
+ else if (counter1ms == 6) {
+ NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rf_adr_buf, 5);
+ NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
+ hopping_frequency_no++;
+ if (hopping_frequency_no >= FREQUENCE_NUM_H377) { hopping_frequency_no = 0; }
+ }
+ else if (counter1ms == 7) { h377_ch_data(); }
+ else if(counter1ms>8) {
+ counter1ms = 0;
+ NRF24L01_WritePayload(payload,10);
+ }
+ return 1000; // send 1 binding packet and 1 data packet per 9ms
+}
+
+// Linear feedback shift register with 32-bit Xilinx polinomial x^32 + x^22 + x^2 + x + 1
+static const uint32_t LFSR_FEEDBACK = 0x80200003ul;
+static const uint32_t LFSR_INTAP = 32-1;
+
+static void update_lfsr(uint32_t *lfsr, uint8_t b) {
+ for (int i = 0; i < 8; ++i) {
+ *lfsr = (*lfsr >> 1) ^ ((-(*lfsr & 1u) & LFSR_FEEDBACK) ^ ~((uint32_t)(b & 1) << LFSR_INTAP));
+ b >>= 1;
+ }
+}
+
+// Generate internal id from TX id and manufacturer id (STM32 unique id)
+
+
+static void H377_tx_id() {
+ for(int i=0;i<5;i++)
+ rf_adr_buf[i] = rf_adr_buf_data[select_ch_id][i];
+
+ hopping_frequency[0] = hopping_frequency_data[select_ch_id];
+
+ for (int i = 1; i < FREQUENCE_NUM_H377; i++) {
+ hopping_frequency[i] = hopping_frequency[i-1] + 3;
+ }
+}
+
+
+
+static uint16_t h377_setup() {
+ select_ch_id = MProtocol_id_master%SET_NUM_H377;
+
+ H377_tx_id();//rf_adr_buf hopping_frequency
+
+ h377_binding_packet();//bind_buf_array (rf_adr_buf hopping_frequency)
+
+ h377_init();
+
+ if(IS_AUTOBIND_FLAG_on) {
+ counter = BIND_COUNT;
+ BIND_IN_PROGRESS;
+ }
+ else { counter = 0; }
+
+ return 1000;
+}
+#endif
diff --git a/Multiprotocol/Nrf24l01_hm830.ino b/Multiprotocol/Nrf24l01_hm830.ino
new file mode 100644
index 0000000..bb30d3a
--- /dev/null
+++ b/Multiprotocol/Nrf24l01_hm830.ino
@@ -0,0 +1,267 @@
+/*
+ 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.
+ Deviation 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 Deviation. If not, see .
+ */
+
+/* This protocol is for the HM Hobby HM830 RC Paper Airplane
+ Protocol spec:
+ Channel data:
+ AA BB CC DD EE FF GG
+ AA : Throttle Min=0x00 max =0x64
+ BB :
+ bit 0,1,2: Left/Right magnitude, bit 5 Polarity (set = right)
+ bit 6: Accelerate
+ bit 7: Right button (also the ABC Button)
+ CC : bit 0 seems to be impacted by the Right button
+ DD
+ EE
+ FF : Trim (bit 0-5: Magnitude, bit 6 polarity (set = right)
+ GG : Checksum (CRC8 on bytes AA-FF), init = 0xa5, poly = 0x01
+*/
+
+#ifdef HM830_NRF24L01_INO
+
+#include "iface_nrf24l01.h"
+
+enum {
+ HM830_BIND1A = 0,
+ HM830_BIND2A,
+ HM830_BIND3A,
+ HM830_BIND4A,
+ HM830_BIND5A,
+ HM830_BIND6A,
+ HM830_BIND7A,
+ HM830_DATA1,
+ HM830_DATA2,
+ HM830_DATA3,
+ HM830_DATA4,
+ HM830_DATA5,
+ HM830_DATA6,
+ HM830_DATA7,
+ HM830_BIND1B = 0x80,
+ HM830_BIND2B,
+ HM830_BIND3B,
+ HM830_BIND4B,
+ HM830_BIND5B,
+ HM830_BIND6B,
+ HM830_BIND7B,
+};
+
+static uint8_t init_vals_hm830[][2] = {
+ {NRF24L01_17_FIFO_STATUS, 0x00},
+ {NRF24L01_16_RX_PW_P5, 0x07},
+ {NRF24L01_15_RX_PW_P4, 0x07},
+ {NRF24L01_14_RX_PW_P3, 0x07},
+ {NRF24L01_13_RX_PW_P2, 0x07},
+ {NRF24L01_12_RX_PW_P1, 0x07},
+ {NRF24L01_11_RX_PW_P0, 0x07},
+ {NRF24L01_0F_RX_ADDR_P5, 0xC6},
+ {NRF24L01_0E_RX_ADDR_P4, 0xC5},
+ {NRF24L01_0D_RX_ADDR_P3, 0xC4},
+ {NRF24L01_0C_RX_ADDR_P2, 0xC3},
+ {NRF24L01_09_CD, 0x00},
+ {NRF24L01_08_OBSERVE_TX, 0x00},
+ {NRF24L01_07_STATUS, 0x07},
+// {NRF24L01_06_RF_SETUP, 0x07},
+ {NRF24L01_05_RF_CH, 0x18},
+ {NRF24L01_04_SETUP_RETR, 0x3F},
+ {NRF24L01_03_SETUP_AW, 0x03},
+ {NRF24L01_02_EN_RXADDR, 0x3F},
+ {NRF24L01_01_EN_AA, 0x3F},
+ {NRF24L01_00_CONFIG, 0x0E},
+};
+
+static uint8_t count;
+static uint8_t rf_ch[] = {0x08, 0x35, 0x12, 0x3f, 0x1c, 0x49, 0x26};
+static uint8_t bind_addr[] = {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xc2};
+
+static uint8_t crc8(uint32_t result, uint8_t *data, int len) {
+ int polynomial = 0x01;
+ for(int i = 0; i < len; i++) {
+ result = result ^ data[i];
+ for(int j = 0; j < 8; j++) {
+ if(result & 0x80) { result = (result << 1) ^ polynomial; }
+ else { result = result << 1; }
+ }
+ }
+ return result & 0xff;
+}
+
+static void HM830_init() {
+ NRF24L01_Initialize();
+ for (uint32_t i = 0; i < sizeof(init_vals_hm830) / sizeof(init_vals_hm830[0]); i++) { NRF24L01_WriteReg(init_vals_hm830[i][0], init_vals_hm830[i][1]); }
+
+ NRF24L01_SetTxRxMode(TX_EN);
+ NRF24L01_SetBitrate(0);
+ NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, bind_addr, 5);
+ NRF24L01_WriteRegisterMulti(NRF24L01_0B_RX_ADDR_P1, bind_addr+1, 5);
+ NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, bind_addr, 5);
+ NRF24L01_Activate(0x73); //Enable FEATURE
+ NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x07);
+ NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x3F);
+ //NRF24L01_ReadReg(NRF24L01_07_STATUS) ==> 0x07
+
+ NRF24L01_Activate(0x53); // switch bank back
+
+ NRF24L01_FlushTx();
+ //NRF24L01_ReadReg(NRF24L01_07_STATUS) ==> 0x0e
+ NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x0e);
+ //NRF24L01_ReadReg(NRF24L01_00_CONFIG); ==> 0x0e
+ NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0e);
+ NRF24L01_ReadReg(NRF24L01_01_EN_AA); // No Auto Acknoledgement
+}
+
+static void build_bind_packet_hm830() {
+ for(int i = 0; i < 6; i++) { packet[i] = rx_tx_addr[i]; }
+ packet[6] = crc8(0xa5, packet, 6);
+}
+
+static void build_data_packet() {
+ uint8_t ail_sign = 0, trim_sign = 0;
+
+ throttle = (uint32_t)Servo_data[THROTTLE] * 50 / PPM_MAX + 50;
+ if (throttle < 0) { throttle = 0; }
+
+ aileron = (uint32_t)Servo_data[AILERON] * 8 / PPM_MAX;
+ if (aileron < 0) { aileron = -aileron; ail_sign = 1; }
+ if (aileron > 7) { aileron = 7; }
+
+ uint8_t turbo = (uint32_t)Servo_data[ELEVATOR] > 0 ? 1 : 0;
+
+ uint8_t trim = ((uint32_t)Servo_data[RUDDER] * 0x1f / PPM_MAX);
+ if (trim < 0) { trim = -trim; trim_sign = 1; }
+ if (trim > 0x1f) { trim = 0x1f; }
+
+ uint8_t rbutton = (uint32_t)Servo_data[4] > 0 ? 1 : 0;
+ packet[0] = throttle;
+ packet[1] = aileron;
+ if (ail_sign) { packet[1] |= 0x20; }
+ if (turbo) { packet[1] |= 0x40; }
+ if (rbutton) { packet[1] |= 0x80; }
+ packet[5] = trim;
+ if (trim_sign) { packet[5] |= 0x20;}
+ packet[6] = crc8(0xa5, packet, 6);
+}
+
+static void send_packet_hm830() {
+ NRF24L01_ReadReg(NRF24L01_17_FIFO_STATUS);
+ NRF24L01_WritePayload(packet, 7);
+}
+
+static uint16_t handle_binding() {
+ uint8_t status = NRF24L01_ReadReg(NRF24L01_07_STATUS);
+ if (status & 0x20) {
+ //Binding complete
+ phase = HM830_DATA1 + ((phase&0x7F)-HM830_BIND1A);
+ count = 0;
+ NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_tx_addr, 5);
+ NRF24L01_WriteRegisterMulti(NRF24L01_0B_RX_ADDR_P1, rx_tx_addr+1, 5);
+ NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, 5);
+ NRF24L01_FlushTx();
+ build_data_packet();
+ uint8_t rb = NRF24L01_ReadReg(NRF24L01_07_STATUS); //==> 0x0E
+ NRF24L01_WriteReg(NRF24L01_07_STATUS, rb);
+ rb = NRF24L01_ReadReg(NRF24L01_00_CONFIG); //==> 0x0E
+ NRF24L01_WriteReg(NRF24L01_00_CONFIG, rb);
+ send_packet_hm830();
+ return 14000;
+ }
+ switch (phase) {
+ case HM830_BIND1A:
+ //Look for a Rx that is already bound
+ NRF24L01_SetPower();
+ NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_tx_addr, 5);
+ NRF24L01_WriteRegisterMulti(NRF24L01_0B_RX_ADDR_P1, rx_tx_addr+1, 5);
+ NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, 5);
+ NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_ch[0]);
+ build_bind_packet_hm830();
+ break;
+ case HM830_BIND1B:
+ //Look for a Rx that is not yet bound
+ NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, bind_addr, 5);
+ NRF24L01_WriteRegisterMulti(NRF24L01_0B_RX_ADDR_P1, bind_addr+1, 5);
+ NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, bind_addr, 5);
+ NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_ch[0]);
+ break;
+ case HM830_BIND2A:
+ case HM830_BIND3A:
+ case HM830_BIND4A:
+ case HM830_BIND5A:
+ case HM830_BIND6A:
+ case HM830_BIND7A:
+ case HM830_BIND2B:
+ case HM830_BIND3B:
+ case HM830_BIND4B:
+ case HM830_BIND5B:
+ case HM830_BIND6B:
+ case HM830_BIND7B:
+ NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_ch[(phase&0x7F)-HM830_BIND1A]);
+ break;
+ }
+ NRF24L01_FlushTx();
+ uint8_t rb = NRF24L01_ReadReg(NRF24L01_07_STATUS); //==> 0x0E
+ NRF24L01_WriteReg(NRF24L01_07_STATUS, rb);
+ rb = NRF24L01_ReadReg(NRF24L01_00_CONFIG); //==> 0x0E
+ NRF24L01_WriteReg(NRF24L01_00_CONFIG, rb);
+ send_packet_hm830();
+ phase++;
+ if (phase == HM830_BIND7B+1) { phase = HM830_BIND1A; }
+ else if (phase == HM830_BIND7A+1) { phase = HM830_BIND1B; }
+ return 20000;
+}
+
+static uint16_t handle_data() {
+ uint8_t status = NRF24L01_ReadReg(NRF24L01_07_STATUS);
+ if (count <= 0 || !(status & 0x20)) {
+ if(count < 0 || ! (status & 0x20)) {
+ count = 0;
+ //We didn't get a response on this channel, try the next one
+ phase++;
+ if (phase-HM830_DATA1 > 6) { phase = HM830_DATA1; }
+
+ NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_ch[0]);
+ NRF24L01_FlushTx();
+ build_data_packet();
+ uint8_t rb = NRF24L01_ReadReg(NRF24L01_07_STATUS); //==> 0x0E
+ NRF24L01_WriteReg(NRF24L01_07_STATUS, rb);
+ rb = NRF24L01_ReadReg(NRF24L01_00_CONFIG); //==> 0x0E
+ NRF24L01_WriteReg(NRF24L01_00_CONFIG, rb);
+ send_packet_hm830();
+ return 14000;
+ }
+ }
+ build_data_packet();
+ count++;
+ if(count == 98) {
+ count = -1;
+ NRF24L01_SetPower();
+ }
+ uint8_t rb = NRF24L01_ReadReg(NRF24L01_07_STATUS); //==> 0x0E
+ NRF24L01_WriteReg(NRF24L01_07_STATUS, rb);
+ rb = NRF24L01_ReadReg(NRF24L01_00_CONFIG); //==> 0x0E
+ NRF24L01_WriteReg(NRF24L01_00_CONFIG, rb);
+ send_packet_hm830();
+ return 20000;
+}
+
+
+
+static uint16_t HM830_callback() {
+ if ((phase & 0x7F) < HM830_DATA1) { return handle_binding(); }
+ else { return handle_data(); }
+}
+
+
+static uint32_t HM830_setup(){
+ count = 0;
+ // initialize_tx_id
+
+ rx_tx_addr[4] = 0xee;
+ rx_tx_addr[5] = 0xc2;
+ HM830_init();
+ phase = HM830_BIND1A;
+
+ return 500;
+}
+#endif
\ No newline at end of file
diff --git a/Multiprotocol/Telemetry.ino b/Multiprotocol/Telemetry.ino
index 39555d7..50553b4 100644
--- a/Multiprotocol/Telemetry.ino
+++ b/Multiprotocol/Telemetry.ino
@@ -1,166 +1,337 @@
//*************************************
// FrSky Telemetry serial code *
-// By Midelic on RCG *
+// By Midelic on RCGroups *
//*************************************
#if defined TELEMETRY
-
-#define USER_MAX_BYTES 6
-#define MAX_PKTX 10
-uint8_t frame[18];
-uint8_t pass = 0;
-uint8_t index;
-uint8_t prev_index;
-uint8_t pktx[MAX_PKTX];
-
-void frskySendStuffed()
-{
- Serial_write(0x7E);
- for (uint8_t i = 0; i < 9; i++)
+ #if defined FRSKYX_CC2500_INO
+ #define SPORT_TELEMETRY
+ #endif
+ #if defined FRSKY_CC2500_INO
+ #define HUB_TELEMETRY
+ #endif
+ #if defined SPORT_TELEMETRY
+ #define SPORT_TELEMETRY
+ #define SPORT_TIME 12000
+ uint32_t last=0;
+ uint8_t sport_counter=0;
+ uint8_t RxBt=0;
+ uint8_t rssi;
+ uint8_t ADC2;
+ #endif
+ #if defined HUB_TELEMETRY
+ #define MAX_PKTX 10
+ uint8_t pktx[MAX_PKTX];
+ uint8_t index;
+ uint8_t prev_index;
+ uint8_t pass = 0;
+ #endif
+ #define USER_MAX_BYTES 6
+ uint8_t frame[18];
+
+ void frskySendStuffed()
{
-
- if ((frame[i] == 0x7e) || (frame[i] == 0x7d))
+ Serial_write(0x7E);
+ for (uint8_t i = 0; i < 9; i++)
{
- Serial_write(0x7D);
- frame[i] ^= 0x20;
+ if ((frame[i] == 0x7e) || (frame[i] == 0x7d))
+ {
+ Serial_write(0x7D);
+ frame[i] ^= 0x20;
+ }
+ Serial_write(frame[i]);
}
- Serial_write(frame[i]);
+ Serial_write(0x7E);
}
- Serial_write(0x7E);
-}
-
-void compute_RSSIdbm(){
- RSSI_dBm = (((uint16_t)(pktt[len-2])*18)>>5);
- if(pktt[len-2] >=128)
- RSSI_dBm -= 82;
- else
- RSSI_dBm += 65;
-}
-
-void frsky_check_telemetry(uint8_t *pkt,uint8_t len)
-{
- if(pkt[1] != rx_tx_addr[3] || pkt[2] != rx_tx_addr[2] || len != pkt[0] + 3)
- {//only packets with the required id and packet length
- for(uint8_t i=3;i<6;i++)
- pktt[i]=0;
- return;
- }
- else
- {
- for (uint8_t i=3;i0)
- telemetry_counter=(telemetry_counter+1)%32;
- }
-}
-
-void frsky_link_frame()
-{
- frame[0] = 0xFE;
- if ((cur_protocol[0]&0x1F)==MODE_FRSKY)
- {
- compute_RSSIdbm();
- frame[1] = pktt[3];
- frame[2] = pktt[4];
- frame[3] = (uint8_t)RSSI_dBm;
- frame[4] = pktt[5]*2;
- }
- else
- if ((cur_protocol[0]&0x1F)==MODE_HUBSAN)
- {
- frame[1] = v_lipo*2; //v_lipo; common 0x2A=42/10=4.2V
- frame[2] = frame[1];
- frame[3] = 0x00;
- frame[4] = (uint8_t)RSSI_dBm;
- }
- frame[5] = frame[6] = frame[7] = frame[8] = 0;
- frskySendStuffed();
-}
-
-#if defined HUB_TELEMETRY
-void frsky_user_frame()
-{
- uint8_t indexx = 0, c=0, j=8, n=0, i;
-
- if(pktt[6]>0 && pktt[6]<=MAX_PKTX)
- {//only valid hub frames
- frame[0] = 0xFD;
- frame[1] = 0;
- frame[2] = pktt[7];
+
+ void compute_RSSIdbm(){
- switch(pass)
- {
- case 0:
- indexx=pktt[6];
- for(i=0;i>5);
+ if(pktt[len-2] >=128)
+ RSSI_dBm -= 82;
+ else
+ RSSI_dBm += 65;
+ }
+
+ void frsky_check_telemetry(uint8_t *pkt,uint8_t len)
+ {
+ if(pkt[1] != rx_tx_addr[3] || pkt[2] != rx_tx_addr[2] || len != pkt[0] + 3)
+ {//only packets with the required id and packet length
+ for(uint8_t i=3;i<6;i++)
+ pktt[i]=0;
return;
- frame[1] = index;
+ }
+ else
+ {
+ for (uint8_t i=3;i0)
+ telemetry_counter=(telemetry_counter+1)%32;
+ }
+ }
+
+ void frsky_link_frame()
+ {
+ frame[0] = 0xFE;
+ if ((cur_protocol[0]&0x1F)==MODE_FRSKY)
+ {
+ compute_RSSIdbm();
+ frame[1] = pktt[3];
+ frame[2] = pktt[4];
+ frame[3] = (uint8_t)RSSI_dBm;
+ frame[4] = pktt[5]*2;
+ }
+ else
+ if ((cur_protocol[0]&0x1F)==MODE_HUBSAN)
+ {
+ frame[1] = v_lipo*2; //v_lipo; common 0x2A=42/10=4.2V
+ frame[2] = frame[1];
+ frame[3] = 0x00;
+ frame[4] = (uint8_t)RSSI_dBm;
+ }
+ frame[5] = frame[6] = frame[7] = frame[8] = 0;
frskySendStuffed();
}
- else
- pass=0;
-}
-#endif
-
-void frskyUpdate()
-{
- if(telemetry_link)
- {
- frsky_link_frame();
- telemetry_link=0;
- return;
- }
+
#if defined HUB_TELEMETRY
- if(!telemetry_link && (cur_protocol[0]&0x1F) != MODE_HUBSAN )
- frsky_user_frame();
+ void frsky_user_frame()
+ {
+ uint8_t indexx = 0, c=0, j=8, n=0, i;
+
+ if(pktt[6]>0 && pktt[6]<=MAX_PKTX)
+ {//only valid hub frames
+ frame[0] = 0xFD;
+ frame[1] = 0;
+ frame[2] = pktt[7];
+
+ switch(pass)
+ {
+ case 0:
+ indexx=pktt[6];
+ for(i=0;i0)
+ {
+ crc_s += p[i]; //0-1FF
+ crc_s += crc_s >> 8; //0-100
+ crc_s &= 0x00ff;
+ }
+ }
+ }
+
+ void sportIdle()
+ {
+ Serial_write(0x7e);
+ }
+ void sportSendFrame()
+ {
+ //at the moment only SWR RSSI,RxBt and A2.
+ sport_counter = (sport_counter + 1) %9;
+
+ for (uint8_t i=5;i<8;i++)
+ frame[i]=0;
+
+ switch (sport_counter)
+ {
+ case 0: // SWR
+ frame[0] = 0x98;
+ frame[1] = 0x10;
+ frame[2] = 0x05;
+ frame[3] = 0xf1;
+ frame[4] = 0x20;//dummy values if swr 20230f00
+ frame[5] = 0x23;
+ frame[6] = 0x0F;
+ frame[7] = 0x00;
+ break;
+ case 1: // RSSI
+ frame[0] = 0x98;
+ frame[1] = 0x10;
+ frame[2] = 0x01;
+ frame[3] = 0xf1;
+ frame[4] = rssi;
+ break;
+ case 2: //BATT
+ frame[0] = 0x98;
+ frame[1] = 0x10;
+ frame[2] = 0x04;
+ frame[3] = 0xf1;
+ frame[4] = RxBt;//a1;
+ break;
+ case 3: //ADC2(A2)
+ frame[0] = 0x1A;
+ frame[1] = 0x10;
+ frame[2] = 0x03;
+ frame[3] = 0xf1;
+ frame[4] = ADC2;//a2;;
+ break;
+ default:
+ sportIdle();
+ return;
+ }
+ sportSend(frame);
+ }
+
+ void process_sport_data()//only for ADC2
+ {
+ uint8_t j=7;
+ if(pktt[6]>0 && pktt[6]<=USER_MAX_BYTES)
+ {
+ for(uint8_t i=0;i<6;i++)
+ if(pktt[j++]==0x03)
+ if(pktt[j]==0xF1)
+ {
+ ADC2=pktt[j+1];
+ break;
+ }
+ pktt[6]=0;//new frame
+ }
+ }
+ #endif
+
+
+ void frskyUpdate()
+ {
+ if(telemetry_link && (cur_protocol[0]&0x1F) != MODE_FRSKYX )
+ {
+ frsky_link_frame();
+ telemetry_link=0;
+ return;
+ }
+ #if defined HUB_TELEMETRY
+ if(!telemetry_link && (cur_protocol[0]&0x1F) != MODE_HUBSAN && (cur_protocol[0]&0x1F) != MODE_FRSKYX)
+ {
+ frsky_user_frame();
+ return;
+ }
+ #endif
+ #if defined SPORT_TELEMETRY
+ if ((cur_protocol[0]&0x1F)==MODE_FRSKYX)
+ {
+ if(telemetry_link)
+ {
+ process_sport_data();
+ if(pktt[4]>0x36)
+ rssi=pktt[4]/2;
+ else
+ RxBt=pktt[4];
+ telemetry_link=0;
+ }
+ uint32_t now = micros();
+ if ((now - last) > SPORT_TIME)
+ {
+ sportSendFrame();
+ last = now;
+ }
+ }
+ #endif
+ }
+
#endif
\ No newline at end of file
diff --git a/Multiprotocol/_Config.h b/Multiprotocol/_Config.h
index f0b4e61..6c28b62 100644
--- a/Multiprotocol/_Config.h
+++ b/Multiprotocol/_Config.h
@@ -24,7 +24,6 @@
//Uncomment to enable telemetry
#define TELEMETRY
-#define HUB_TELEMETRY
//Uncomment to enable potar select
@@ -34,29 +33,48 @@
#define POTAR_SELECT_M AILERON
+//Comment if a module is not installed
+#define A7105_INSTALLED
+#define CYRF6936_INSTALLED
+//#define CC2500_INSTALLED
+#define NFR24L01_INSTALLED
+
//Comment a protocol to exclude it from compilation
-//A7105 protocols
-#define FLYSKY_A7105_INO
-#define HUBSAN_A7105_INO
-//CYRF6936 protocols
-#define DEVO_CYRF6936_INO
-#define DSM2_CYRF6936_INO
-//CC2500 protocols
-#define FRSKY_CC2500_INO
-//#define FRSKYX_CC2500_INO
-//NFR24L01 protocols
-#define BAYANG_NRF24L01_INO
-#define CG023_NRF24L01_INO
-#define CX10_NRF24L01_INO
-#define ESKY_NRF24L01_INO
-#define HISKY_NRF24L01_INO
-#define KN_NRF24L01_INO
-#define SLT_NRF24L01_INO
-#define SYMAX_NRF24L01_INO
-#define V2X2_NRF24L01_INO
-#define YD717_NRF24L01_INO
-#define MT99XX_NRF24L01_INO
-#define MJXQ_NRF24L01_INO
+#ifdef A7105_INSTALLED
+ #define JOYSWAY_A7105_INO
+
+ #define FLYSKY_A7105_INO
+ #define HUBSAN_A7105_INO
+#endif
+#ifdef CYRF6936_INSTALLED
+ #define J6PRO_CYRF6936_INO
+// #define WK2x01_CYRF6936_INO
+
+ #define DEVO_CYRF6936_INO
+ #define DSM2_CYRF6936_INO
+#endif
+#ifdef CC2500_INSTALLED
+ #define FRSKY_CC2500_INO
+ #define FRSKYX_CC2500_INO
+#endif
+#ifdef NFR24L01_INSTALLED
+ #define HM830_NRF24L01_INO
+ #define CFlie_NRF24L01_INO
+ #define H377_NRF24L01_INO
+
+ #define BAYANG_NRF24L01_INO
+ #define CG023_NRF24L01_INO
+ #define CX10_NRF24L01_INO
+ #define ESKY_NRF24L01_INO
+ #define HISKY_NRF24L01_INO
+ #define KN_NRF24L01_INO
+ #define SLT_NRF24L01_INO
+ #define SYMAX_NRF24L01_INO
+ #define V2X2_NRF24L01_INO
+ #define YD717_NRF24L01_INO
+ #define MT99XX_NRF24L01_INO
+ #define MJXQ_NRF24L01_INO
+#endif
//Update this table to set which protocol and all associated settings are called for the corresponding dial number
static const PPM_Parameters PPM_prot[15]=
@@ -215,7 +233,7 @@ Option value between 0 and 255. 0xD7 or 0x00 for Frsky fine tuning.
RUDDER,
};
#endif
-enum chan_order{
+enum chan_orders{
AUX1 =4,
AUX2,
AUX3,
diff --git a/Multiprotocol/iface_nrf24l01.h b/Multiprotocol/iface_nrf24l01.h
index 1acf438..92ff9e1 100644
--- a/Multiprotocol/iface_nrf24l01.h
+++ b/Multiprotocol/iface_nrf24l01.h
@@ -102,18 +102,7 @@ enum {
#define REUSE_TX_PL 0xE3
//#define NOP 0xFF
-/*
-void NRF24L01_Initialize();
-byte NRF24L01_WriteReg(byte reg, byte data);
-byte NRF24L01_WriteRegisterMulti(byte reg, byte data[], byte length);
-byte NRF24L01_WritePayload(byte *data, byte len);
-byte NRF24L01_ReadReg(byte reg);
-byte NRF24L01_ReadRegisterMulti(byte reg, byte data[], byte length);
-byte NRF24L01_ReadPayload(byte *data, byte len);
+// XN297 emulation layer
+#define XN297_UNSCRAMBLED 8
-byte NRF24L01_FlushTx();
-byte NRF24L01_FlushRx();
-byte NRF24L01_Activate(byte code);
-
-*/
#endif
\ No newline at end of file
diff --git a/Multiprotocol/multiprotocol.h b/Multiprotocol/multiprotocol.h
index dcbbfbd..42ab887 100644
--- a/Multiprotocol/multiprotocol.h
+++ b/Multiprotocol/multiprotocol.h
@@ -15,7 +15,7 @@
// Check selected board type
#ifndef ARDUINO_AVR_PRO
- #error You must select the board type "Arduino Pro or Pro Mini"
+// #error You must select the board type "Arduino Pro or Pro Mini"
#endif
#if F_CPU != 16000000L || not defined(__AVR_ATmega328P__)
#error You must select the processor type "ATmega328(5V, 16MHz)"
@@ -26,6 +26,14 @@
//******************
enum PROTOCOLS
{
+ MODE_HM830=40, // =>NRF24L01
+ MODE_CFLIE=41, // =>NRF24L01
+ MODE_JOYSWAY = 42, // =>A7105
+ MODE_J6PRO = 43, // =>CYRF6936
+ MODE_H377=44, // =>NRF24L01
+ MODE_WK2x01 = 45, // =>CYRF6936
+ MODE_FY326=46, // =>NRF24L01
+
MODE_SERIAL = 0, // Serial commands
MODE_FLYSKY = 1, // =>A7105
MODE_HUBSAN = 2, // =>A7105
@@ -110,6 +118,12 @@ enum MJXQ
X800 = 2,
H26D = 3
};
+enum WK2X01
+{
+ WK2801 = 0,
+ WK2601 = 1,
+ WK2401 = 2
+};
#define NONE 0
#define P_HIGH 1
diff --git a/README.md b/README.md
index a4686c6..169902f 100644
--- a/README.md
+++ b/README.md
@@ -26,3 +26,45 @@ Notes:
- For serial, the dial switch is not needed and the bind button optionnal
- Ajout d'un switch + transistor sur le TX

+
+
+#Protocoles ajoutés mais non testés (Issue de Deviation)
+##CYRF6936 RF Module
+###J6PRO
+CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
+---|---|---|---|---|---|---|---|---|---|---|---
+CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
+
+###WK2x01
+En cours ...
+
+##A7105 RF Module
+###Joysway
+CH1|CH2|CH3|CH4
+---|---|---|---
+A|E|T|R
+
+##NRF24L01 RF Module
+###CFLIE
+Modele: CrazyFlie Nano quad
+CH1|CH2|CH3|CH4
+---|---|---|---
+A|E|T|R
+
+###Fy326
+Autobind
+CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
+---|---|---|---|---|---|---|---
+A|E|T|R|FLIP|HEADLESS|RTH|Calibrate
+
+###H377
+CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
+---|---|---|---|---|---|---|---
+A|E|T|R|CH5|CH6|CH7|CH8
+
+###HM830
+Modele: HM Hobby HM830 RC Paper Airplane
+CH1|CH2|CH3|CH4|CH5
+---|---|---|---
+A|Turbo|T|Trim|Bouton ???
+
diff --git a/sync.ffs_db b/sync.ffs_db
index b007d39..af956ef 100644
Binary files a/sync.ffs_db and b/sync.ffs_db differ
diff --git a/taranis_switches.png b/taranis_switches.png
new file mode 100644
index 0000000..d1645d2
Binary files /dev/null and b/taranis_switches.png differ