Compare commits

...

1 Commits

Author SHA1 Message Date
Arne Schwabe fe72bb028c First version of multi module support for Taranis
Since DSM2 uses the same framing/serial protocol (Serial with 125k)
the multi module code heavily reuses that code and depends on it being enabled.

This first version only implements the protocol on the taranis.

Telemetry code is currently untested.
2016-01-04 17:44:00 +01:00
13 changed files with 416 additions and 36 deletions
+2 -1
View File
@@ -382,7 +382,7 @@ if(ARCH STREQUAL ARM)
set(TARGET_SRC ${TARGET_SRC} haptic_driver.cpp)
endif()
add_definitions(-DCPUARM)
add_definitions(-DFRSKY -DFRSKY_SPORT -DFRSKY_HUB -DGPS -DPXX -DDSM2)
add_definitions(-DFRSKY -DFRSKY_SPORT -DFRSKY_HUB -DGPS -DPXX -DDSM2 -DMULTIMODULE)
include_directories(targets/${TARGET_DIR} ${THIRDPARTY_DIR})
include_directories(${COOS_DIR} ${COOS_DIR}/kernel ${COOS_DIR}/portable)
foreach(LANGUAGE cz de en es fr it pt sk se pl hu) # TODO add nl
@@ -442,6 +442,7 @@ if(ARCH STREQUAL ARM)
ppm_arm.cpp
pxx_arm.cpp
dsm2_arm.cpp
multi_arm.cpp
crossfire.cpp
)
else()
+11
View File
@@ -230,6 +230,10 @@ PXX = NO
# Values = NO, SERIAL, PPM
DSM2 = NO
# Multimodule support
# https://github.com/pascallanger/DIY-Multiprotocol-TX-Module
MULTIMODULE = NO
# HUBSAN protocol
# Values = NO, YES
HUBSAN = NO
@@ -1056,6 +1060,9 @@ ifeq ($(PCB), TARANIS)
ifeq ($(DSM2), PPM)
CPPSRC += pulses/dsm2_arm.cpp
endif
ifeq ($(MULTIMODULE), YES)
CPPSRC += pulses/multi_arm.cpp
endif
ifeq ($(HUBSAN), YES)
CPPDEFS += -DHUBSAN
CPPSRC += pulses/hubsan.cpp
@@ -1670,6 +1677,10 @@ ifeq ($(DSM2), PPM)
CPPDEFS += -DDSM2 -DDSM2_PPM
endif
ifeq ($(MULTIMODULE), YES)
CPPDEFS += -DMULTIMODULE
endif
ifeq ($(TX_CADDY), YES)
CPPDEFS += -DTX_CADDY
endif
+71 -8
View File
@@ -190,12 +190,18 @@ int getSwitchWarningsCount()
#define IS_D8_RX(x) (g_model.moduleData[x].rfProtocol == RF_PROTO_D8)
#define IF_EXTERNAL_MODULE_XJT(x) (IS_MODULE_XJT(EXTERNAL_MODULE) ? (uint8_t)x : HIDDEN_ROW)
#define INTERNAL_MODULE_CHANNELS_ROWS IF_INTERNAL_MODULE_ON(1)
#define EXTERNAL_MODULE_CHANNELS_ROWS IF_EXTERNAL_MODULE_ON((IS_MODULE_DSM2(EXTERNAL_MODULE) || IS_MODULE_CROSSFIRE(EXTERNAL_MODULE)) ? (uint8_t)0 : (uint8_t)1)
#define EXTERNAL_MODULE_CHANNELS_ROWS IF_EXTERNAL_MODULE_ON((IS_MODULE_DSM2(EXTERNAL_MODULE) || IS_MODULE_CROSSFIRE(EXTERNAL_MODULE) || IS_MODULE_MULTIMODULE(EXTERNAL_MODULE)) ? (uint8_t)0 : (uint8_t)1)
#define TRAINER_CHANNELS_ROWS() IF_TRAINER_ON(1)
#define PORT_CHANNELS_ROWS(x) (x==INTERNAL_MODULE ? INTERNAL_MODULE_CHANNELS_ROWS : (x==EXTERNAL_MODULE ? EXTERNAL_MODULE_CHANNELS_ROWS : TRAINER_CHANNELS_ROWS()))
#define FAILSAFE_ROWS(x) (HAS_RF_PROTOCOL_FAILSAFE(g_model.moduleData[x].rfProtocol) ? (g_model.moduleData[x].failsafeMode==FAILSAFE_CUSTOM ? (uint8_t)1 : (uint8_t)0) : HIDDEN_ROW)
#define TIMER_ROWS 2|NAVIGATION_LINE_BY_LINE, 0, CASE_PERSISTENT_TIMERS(0) 0, 0
#define EXTERNAL_MODULE_MODE_ROWS (IS_MODULE_XJT(EXTERNAL_MODULE) || IS_MODULE_DSM2(EXTERNAL_MODULE)) ? (uint8_t)1 : (uint8_t)0
#if defined(MULTIMODULE)
#define MULTIMODULE_MODE_ROWS(x) (g_model.moduleData[x].rfProtocol == MM_RF_PROTO_HISKY || g_model.moduleData[x].rfProtocol == MM_RF_PROTO_DSM2 || g_model.moduleData[x].rfProtocol == MM_RF_PROTO_SYMAX || g_model.moduleData[x].rfProtocol == MM_RF_PROTO_CG023 || g_model.moduleData[x].rfProtocol == MM_RF_PROTO_CX10 || g_model.moduleData[x].rfProtocol == MM_RF_PROTO_FLYSKY || g_model.moduleData[x].rfProtocol == MM_RF_PROTO_YD717) ? (uint8_t)2 : (uint8_t)1
#else
#define MULTIMODULE_MODE_ROWS(x) (uint8_t)0
#endif
#define EXTERNAL_MODULE_MODE_ROWS (IS_MODULE_XJT(EXTERNAL_MODULE) || IS_MODULE_DSM2(EXTERNAL_MODULE)) ? (uint8_t)1 : IS_MODULE_MULTIMODULE(EXTERNAL_MODULE) ? MULTIMODULE_MODE_ROWS(EXTERNAL_MODULE) : (uint8_t)0
#if TIMERS == 1
#define TIMERS_ROWS TIMER_ROWS
#elif TIMERS == 2
@@ -226,9 +232,9 @@ void menuModelSetup(uint8_t event)
IF_INTERNAL_MODULE_ON(IS_MODULE_XJT(INTERNAL_MODULE) ? (HAS_RF_PROTOCOL_MODELINDEX(g_model.moduleData[INTERNAL_MODULE].rfProtocol) ? (uint8_t)2 : (uint8_t)1) : (IS_MODULE_PPM(INTERNAL_MODULE) ? (uint8_t)1 : HIDDEN_ROW)),
IF_INTERNAL_MODULE_ON((IS_MODULE_XJT(INTERNAL_MODULE)) ? FAILSAFE_ROWS(INTERNAL_MODULE) : HIDDEN_ROW),
LABEL(ExternalModule),
(IS_MODULE_XJT(EXTERNAL_MODULE) || IS_MODULE_DSM2(EXTERNAL_MODULE)) ? (uint8_t)1 : (uint8_t)0,
(IS_MODULE_XJT(EXTERNAL_MODULE) || IS_MODULE_DSM2(EXTERNAL_MODULE) || IS_MODULE_MULTIMODULE(EXTERNALE_MODULE)) ? (uint8_t)1 : (uint8_t)0,
EXTERNAL_MODULE_CHANNELS_ROWS,
(IS_MODULE_XJT(EXTERNAL_MODULE) && !HAS_RF_PROTOCOL_MODELINDEX(g_model.moduleData[EXTERNAL_MODULE].rfProtocol)) ? (uint8_t)1 : (IS_MODULE_PPM(EXTERNAL_MODULE) || IS_MODULE_XJT(EXTERNAL_MODULE) || IS_MODULE_DSM2(EXTERNAL_MODULE)) ? (uint8_t)2 : HIDDEN_ROW,
(IS_MODULE_XJT(EXTERNAL_MODULE) && !HAS_RF_PROTOCOL_FAILSAFE(g_model.moduleData[EXTERNAL_MODULE].rfProtocol)) ? (uint8_t)1 : (IS_MODULE_PPM(EXTERNAL_MODULE) || IS_MODULE_XJT(EXTERNAL_MODULE) || IS_MODULE_DSM2(EXTERNAL_MODULE) || IS_MODULE_MULTIMODULE(EXTERNAL_MODULE)) ? (uint8_t)2 : HIDDEN_ROW,
IF_EXTERNAL_MODULE_XJT(FAILSAFE_ROWS(EXTERNAL_MODULE)),
LABEL(Trainer), 0, TRAINER_CHANNELS_ROWS(), IF_TRAINER_ON(2)});
#else
@@ -242,7 +248,7 @@ void menuModelSetup(uint8_t event)
LABEL(ExternalModule),
EXTERNAL_MODULE_MODE_ROWS,
EXTERNAL_MODULE_CHANNELS_ROWS,
(IS_MODULE_XJT(EXTERNAL_MODULE) && !HAS_RF_PROTOCOL_MODELINDEX(g_model.moduleData[EXTERNAL_MODULE].rfProtocol)) ? (uint8_t)1 : (IS_MODULE_PPM(EXTERNAL_MODULE) || IS_MODULE_XJT(EXTERNAL_MODULE) || IS_MODULE_DSM2(EXTERNAL_MODULE)) ? (uint8_t)2 : HIDDEN_ROW,
(IS_MODULE_XJT(EXTERNAL_MODULE) && !HAS_RF_PROTOCOL_FAILSAFE(g_model.moduleData[EXTERNAL_MODULE].rfProtocol)) ? (uint8_t)1 : (IS_MODULE_PPM(EXTERNAL_MODULE) || IS_MODULE_XJT(EXTERNAL_MODULE) || IS_MODULE_DSM2(EXTERNAL_MODULE) || IS_MODULE_MULTIMODULE(EXTERNAL_MODULE)) ? (uint8_t)2 : HIDDEN_ROW,
IF_EXTERNAL_MODULE_XJT(FAILSAFE_ROWS(EXTERNAL_MODULE)),
LABEL(Trainer), 0, TRAINER_CHANNELS_ROWS(), IF_TRAINER_ON(2)});
#endif
@@ -663,6 +669,35 @@ void menuModelSetup(uint8_t event)
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN+5*FW, y, STR_XJT_PROTOCOLS, 1+g_model.moduleData[EXTERNAL_MODULE].rfProtocol, menuHorizontalPosition==1 ? attr : 0);
else if (IS_MODULE_DSM2(EXTERNAL_MODULE))
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN+5*FW, y, STR_DSM_PROTOCOLS, g_model.moduleData[EXTERNAL_MODULE].rfProtocol, menuHorizontalPosition==1 ? attr : 0);
#if defined(MULTIMODULE)
else if (IS_MODULE_MULTIMODULE(EXTERNAL_MODULE)) {
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN+5*FW, y, STR_MULTI_PROTOCOLS, g_model.moduleData[EXTERNAL_MODULE].rfProtocol+8, menuHorizontalPosition==1 ? attr : 0);
switch(g_model.moduleData[EXTERNAL_MODULE].rfProtocol) {
case MM_RF_PROTO_FLYSKY:
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN+11*FW, y, STR_SUBTYPE_FLYSKY, g_model.moduleData[EXTERNAL_MODULE].subType, menuHorizontalPosition==2 ? attr : 0);
break;
case MM_RF_PROTO_HISKY:
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN+10*FW, y, STR_SUBTYPE_HISKY, g_model.moduleData[EXTERNAL_MODULE].subType, menuHorizontalPosition==2 ? attr : 0);
break;
case MM_RF_PROTO_DSM2:
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN+10*FW, y, STR_DSM_PROTOCOLS, g_model.moduleData[EXTERNAL_MODULE].subType+1, menuHorizontalPosition==2 ? attr : 0);
break;
case MM_RF_PROTO_YD717:
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN+10*FW, y, STR_SUBTYPE_YD717, g_model.moduleData[EXTERNAL_MODULE].subType, menuHorizontalPosition==2 ? attr : 0);
break;
case MM_RF_PROTO_SYMAX:
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN+11*FW, y, STR_SUBTYPE_SYMAX, g_model.moduleData[EXTERNAL_MODULE].subType, menuHorizontalPosition==2 ? attr : 0);
break;
case MM_RF_PROTO_CX10:
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN+10*FW, y, STR_SUBTYPE_CX10, g_model.moduleData[EXTERNAL_MODULE].subType, menuHorizontalPosition==2 ? attr : 0);
break;
case MM_RF_PROTO_CG023:
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN+10*FW, y, STR_SUBTYPE_CG023, g_model.moduleData[EXTERNAL_MODULE].subType, menuHorizontalPosition==2 ? attr : 0);
break;
}
}
#endif
if (attr && s_editMode>0) {
switch (menuHorizontalPosition) {
case 0:
@@ -676,12 +711,38 @@ void menuModelSetup(uint8_t event)
case 1:
if (IS_MODULE_DSM2(EXTERNAL_MODULE))
CHECK_INCDEC_MODELVAR(event, g_model.moduleData[EXTERNAL_MODULE].rfProtocol, DSM2_PROTO_LP45, DSM2_PROTO_DSMX);
else if (IS_MODULE_MULTIMODULE(EXTERNAL_MODULE)) {
CHECK_INCDEC_MODELVAR(event, g_model.moduleData[EXTERNAL_MODULE].rfProtocol, MM_RF_PROTO_FIRST, MM_RF_PROTO_LAST);
if (checkIncDec_Ret)
g_model.moduleData[EXTERNAL_MODULE].subType=0;
}
else
g_model.moduleData[EXTERNAL_MODULE].rfProtocol = checkIncDec(event, g_model.moduleData[EXTERNAL_MODULE].rfProtocol, RF_PROTO_X16, RF_PROTO_LAST, EE_MODEL, isRfProtocolAvailable);
if (checkIncDec_Ret) {
g_model.moduleData[EXTERNAL_MODULE].channelsStart = 0;
g_model.moduleData[EXTERNAL_MODULE].channelsCount = 0;
}
break;
#if defined(MULTIMODULE)
case 2:
switch (g_model.moduleData[EXTERNAL_MODULE].rfProtocol) {
case MM_RF_PROTO_HISKY:
case MM_RF_PROTO_DSM2:
case MM_RF_PROTO_SYMAX:
case MM_RF_PROTO_CG023:
CHECK_INCDEC_MODELVAR(event, g_model.moduleData[EXTERNAL_MODULE].subType, 0, 1);
break;
case MM_RF_PROTO_CX10:
CHECK_INCDEC_MODELVAR(event, g_model.moduleData[EXTERNAL_MODULE].subType, 0, 2);
break;
case MM_RF_PROTO_FLYSKY:
CHECK_INCDEC_MODELVAR(event, g_model.moduleData[EXTERNAL_MODULE].subType, 0, 3);
break;
case MM_RF_PROTO_YD717:
CHECK_INCDEC_MODELVAR(event, g_model.moduleData[EXTERNAL_MODULE].subType, 0, 4);
break;
}
#endif
}
}
break;
@@ -725,7 +786,7 @@ void menuModelSetup(uint8_t event)
}
break;
}
case ITEM_MODEL_INTERNAL_MODULE_BIND:
case ITEM_MODEL_EXTERNAL_MODULE_BIND:
case ITEM_MODEL_TRAINER_SETTINGS:
@@ -765,11 +826,13 @@ void menuModelSetup(uint8_t event)
else {
lcd_putsLeft(y, STR_RXNUM);
}
if (IS_MODULE_XJT(moduleIdx) || IS_MODULE_DSM2(moduleIdx)) {
if (IS_MODULE_XJT(moduleIdx) || IS_MODULE_DSM2(moduleIdx) || IS_MODULE_MULTIMODULE(moduleIdx)) {
if (xOffsetBind) lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, g_model.header.modelId[moduleIdx], (l_posHorz==0 ? attr : 0) | LEADING0|LEFT, 2);
if (attr && l_posHorz==0) {
if (s_editMode>0) {
CHECK_INCDEC_MODELVAR_ZERO(event, g_model.header.modelId[moduleIdx], IS_MODULE_DSM2(moduleIdx) ? 20 : 63);
CHECK_INCDEC_MODELVAR_ZERO(event, g_model.header.modelId[moduleIdx],
IS_MODULE_DSM2(moduleIdx) ? 20 :
IS_MODULE_MULTIMODULE(moduleIdx) ? 15 : 63);
if (checkIncDec_Ret) {
modelHeaders[g_eeGeneral.currModel].modelId[moduleIdx] = g_model.header.modelId[moduleIdx];
}
+29 -1
View File
@@ -489,7 +489,8 @@ PACK(typedef struct {
int8_t rfProtocol:4;
uint8_t channelsStart;
int8_t channelsCount; // 0=8 channels
uint8_t failsafeMode:7;
uint8_t failsafeMode:4;
uint8_t subType:3;
uint8_t invertedSerial:1; // telemetry serial inverted from standard
int16_t failsafeChannels[NUM_CHNOUT];
int8_t ppmDelay:6;
@@ -2171,6 +2172,9 @@ enum Protocols {
#if defined(CROSSFIRE)
PROTO_CROSSFIRE,
#endif
#if defined(MULTIMODULE)
PROTO_MULTIMODULE,
#endif
#if defined(IRPROTOS)
// we will need 4 bytes for proto :(
PROTO_SILV,
@@ -2199,6 +2203,27 @@ enum DSM2Protocols {
DSM2_PROTO_DSMX,
};
// rfProtcol is currently a signed int
enum MultiModuleRFProtocols {
MM_RF_PROTO_FLYSKY=-8,
MM_RF_PROTO_FIRST=MM_RF_PROTO_FLYSKY,
MM_RF_PROTO_HUBSAN,
MM_RF_PROTO_FRSKY_D8,
MM_RF_PROTO_HISKY,
MM_RF_PROTO_V2X2,
MM_RF_PROTO_DSM2,
MM_RF_PROTO_DEVO,
MM_RF_PROTO_YD717,
MM_RF_PROTO_V977,
MM_RF_PROTO_SYMAX,
MM_RF_PROTO_SLT,
MM_RF_PROTO_CX10,
MM_RF_PROTO_CG023,
MM_RF_PROTO_BAYANG,
MM_RF_PROTO_LAST= MM_RF_PROTO_BAYANG
};
enum ModuleTypes {
MODULE_TYPE_NONE = 0,
MODULE_TYPE_PPM,
@@ -2208,6 +2233,9 @@ enum ModuleTypes {
#endif
#if defined(CROSSFIRE)
MODULE_TYPE_CROSSFIRE,
#endif
#if defined(MULTIMODULE)
MODULE_TYPE_MULTIMODULE,
#endif
MODULE_TYPE_COUNT
};
+5
View File
@@ -471,6 +471,11 @@
#else
#define IS_MODULE_CROSSFIRE(idx) (false)
#endif
#if defined(MULTIMODULE)
#define IS_MODULE_MULTIMODULE(idx) (idx==EXTERNAL_MODULE && g_model.moduleData[EXTERNAL_MODULE].type==MODULE_TYPE_MULTIMODULE)
#else
#define IS_MODULE_MULTIMODULE(idx) (false)
#endif
#if defined(TARANIS_INTERNAL_PPM)
#define MAX_INTERNAL_MODULE_CHANNELS() ((g_model.moduleData[INTERNAL_MODULE].type == MODULE_TYPE_XJT) ? maxChannelsXJT[1+g_model.moduleData[0].rfProtocol] : maxChannelsModules[g_model.moduleData[INTERNAL_MODULE].type])
#else
+181
View File
@@ -0,0 +1,181 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program 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.
*/
#include "../opentx.h"
// MULTI protocol definition (from mbtx:radio/er9x/src/pulses.cpp)
/*
Serial: 125000 Baud 8n1 _ xxxx xxxx - ---
Channels:
Nbr=8
10bits=0..1023
0 -125%
96 -100%
512 0%
928 +100%
1023 +125%
Stream[0] = sub_protocol|BindBit|RangeCheckBit|AutoBindBit;
sub_protocol is 0..31 (bits 0..4)
=> Reserved 0
Flysky 1
Hubsan 2
Frsky 3
Hisky 4
V2x2 5
DSM2 6
Devo 7
YD717 8
KN 9
SymaX 10
SLT 11
CX10 12
CG023 13
Bayang 14
BindBit=> 0x80 1=Bind/0=No
AutoBindBit=> 0x40 1=Yes /0=No
RangeCheck=> 0x20 1=Yes /0=No
Stream[1] = RxNum | Power | Type;
RxNum value is 0..15 (bits 0..3)
Type is 0..7 <<4 (bit 4..6)
sub_protocol==Flysky
Flysky 0
V9x9 1
V6x6 2
V912 3
sub_protocol==Hisky
Hisky 0
HK310 1
sub_protocol==DSM2
DSM2 0
DSMX 1
sub_protocol==YD717
YD717 0
SKYWLKR 1
SYMAX2 2
XINXUN 3
NIHUI 4
sub_protocol==SYMAX
SYMAX 0
SYMAX5C 1
sub_protocol==CX10
CX10_GREEN 0
CX10_BLUE 1 // also compatible with CX10-A, CX12
DM007 2
sub_protocol==CG023
CG023 0
YD829 1
Power value => 0x80 0=High/1=Low
Stream[2] = option_protocol;
option_protocol value is -127..127
Stream[i+3] = lowByte(channel[i]) // with i[0..7]
Stream[11] = highByte(channel[0])<<6 | highByte(channel[1])<<4 | highByte(channel[2])<<2 | highByte(channel[3])
Stream[12] = highByte(channel[4])<<6 | highByte(channel[5])<<4 | highByte(channel[6])<<2 | highByte(channel[7])
Stream[13] = lowByte(CRC16(Stream[0..12])
*/
/* Lenght 3 (header) + 8 (channel low bytes) + 2 (channel high bits) + 1 (crc) */
#define MULTI_CHANS 8
#define MULTI_FRAME_LENGTH 2+MULTI_CHANS+2+1
/* The protocol is heavily inspired by the DSM2 protocol, so reuse some the definitions where they are identical */
#define MULTI_SEND_BIND (1 << 7)
#define MULTI_SEND_RANGECHECK (1 << 5)
void sendByteMulti(uint8_t b)
{
sendByteDsm2(b);
}
extern const uint16_t CRCTable[];
inline void sendByteMultiCRC(uint16_t & crcsum, uint8_t b)
{
crcsum = (crcsum << 8) ^ (CRCTable[((crcsum>>8)^b) & 0xff]);
sendByteMulti(b);
}
// This is the data stream to send, prepare after 19.5 mS
// Send after 22.5 mS
//static uint8_t *Dsm2_pulsePtr = pulses2MHz.pbyte ;
void setupPulsesMultimodule(unsigned int port)
{
uint16_t crcsum =0;
#if defined(PCBSKY9X)
modulePulsesData[EXTERNAL_MODULE].dsm2.serialByte = 0 ;
modulePulsesData[EXTERNAL_MODULE].dsm2.serialBitCount = 0 ;
#else
modulePulsesData[EXTERNAL_MODULE].dsm2.value = 0;
modulePulsesData[EXTERNAL_MODULE].dsm2.index = 1;
#endif
modulePulsesData[EXTERNAL_MODULE].dsm2.ptr = modulePulsesData[EXTERNAL_MODULE].dsm2.pulses;
#if defined(PCBTARANIS)
modulePulsesData[EXTERNAL_MODULE].dsm2.value = 100;
*modulePulsesData[EXTERNAL_MODULE].dsm2.ptr++ = modulePulsesData[EXTERNAL_MODULE].dsm2.value;
#endif
uint8_t protoByte=0;
if (moduleFlag[port] == MODULE_BIND)
protoByte |= MULTI_SEND_BIND;
else if (moduleFlag[port] == MODULE_RANGECHECK)
protoByte |= MULTI_SEND_RANGECHECK;
// rfProtocol = -8..7 => 1..15
protoByte |= ((g_model.moduleData[port].rfProtocol+9) & 0xf);
sendByteMultiCRC(crcsum, protoByte);
// power always set to high (0 << 7)
int subtype = g_model.moduleData[port].subType;
sendByteMultiCRC(crcsum, (g_model.header.modelId[port] & 0x0f)
| (0 << 7) | ((subtype & 0x7) << 4));
//TODO: option_protocol, use same default as multi module
int8_t option_protocol=0xd7;
sendByteMultiCRC (crcsum, option_protocol);
uint16_t highbits=0;
for (int i=0; i<MULTI_CHANS; i++) {
int channel = g_model.moduleData[port].channelsStart+i;
int value = channelOutputs[channel] + 2*PPM_CH_CENTER(channel) - 2*PPM_CENTER;
uint16_t pulse = limit(0, ((value*13)>>5)+512, 1023);
sendByteMultiCRC(crcsum,pulse & 0xff);
highbits = (highbits << 2) | ( (pulse >> 8) & 0x03);
}
// Send high bits
sendByteMultiCRC(crcsum, (highbits >> 8) & 0xff);
sendByteMultiCRC(crcsum, highbits & 0xff);
//send CRC
sendByteMulti(crcsum & 0xff);
putDsm2Flush();
}
+10
View File
@@ -68,6 +68,16 @@ enum ModuleFlag
#define IS_DSM2_SERIAL_PROTOCOL(protocol) (0)
#endif
#if defined(MULTIMODULE)
#define IS_MULTIMODULE_PROTOCOL(protocol) (protocol==PROTO_MULTIMODULE)
#if !defined(DSM2)
#error You need to enable DSM2 = PPM for MULTIMODULE support
#endif
#else
#define IS_MULTIMODULE_PROTOCOL(protocol) (0)
#endif
#if defined(CPUARM)
#include "pulses_arm.h"
#else
+20
View File
@@ -64,6 +64,11 @@ void setupPulses(unsigned int port)
case MODULE_TYPE_XJT:
required_protocol = PROTO_PXX;
break;
#if defined(MULTIMODULE)
case MODULE_TYPE_MULTIMODULE:
required_protocol = PROTO_MULTIMODULE;
break;
#endif
#if defined(PCBTARANIS) && defined(DSM2)
case MODULE_TYPE_DSM2:
required_protocol = limit<uint8_t>(PROTO_DSM2_LP45, PROTO_DSM2_LP45+g_model.moduleData[EXTERNAL_MODULE].rfProtocol, PROTO_DSM2_DSMX);
@@ -123,6 +128,11 @@ void setupPulses(unsigned int port)
case PROTO_CROSSFIRE:
disable_crossfire(port);
break;
#endif
#if defined(MULTIMODULE)
case PROTO_MULTIMODULE:
disable_dsm2(port);
break;
#endif
case PROTO_PPM:
disable_ppm(port);
@@ -149,6 +159,11 @@ void setupPulses(unsigned int port)
case PROTO_CROSSFIRE:
init_crossfire(port);
break;
#endif
#if defined(MULTIMODULE)
case PROTO_MULTIMODULE:
init_dsm2(port);
break;
#endif
case PROTO_PPM:
init_ppm(port);
@@ -182,6 +197,11 @@ void setupPulses(unsigned int port)
}
break;
}
#endif
#if defined(MULTIMODULE)
case PROTO_MULTIMODULE:
setupPulsesDSM2(port);
break;
#endif
case PROTO_PPM:
setupPulsesPPM(port);
+26 -24
View File
@@ -1,23 +1,23 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program 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.
*/
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program 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.
*/
#include "../../opentx.h"
void setupPulses(unsigned int port);
@@ -32,7 +32,7 @@ static void intmodulePxxStop( void ) ;
#endif
static void extmodulePxxStart( void ) ;
static void extmodulePxxStop( void ) ;
#if defined(DSM2)
#if defined(DSM2) || defined(MULTIMODULE)
static void extmoduleDsm2Start( void ) ;
static void extmoduleDsm2Stop( void ) ;
#endif
@@ -61,7 +61,7 @@ void disable_pxx(uint32_t port)
extmodulePxxStop() ;
}
#if defined(DSM2)
#if defined(DSM2) || defined(MULTIMODULE)
void init_dsm2(uint32_t port)
{
if (port == EXTERNAL_MODULE) {
@@ -472,7 +472,7 @@ static void extmodulePxxStop()
}
}
#if defined(DSM2)
#if defined(DSM2) || defined(MULTIMODULE)
static void extmoduleDsm2Start()
{
EXTERNAL_MODULE_ON();
@@ -596,7 +596,9 @@ extern "C" void TIM8_CC_IRQHandler()
EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE ; // Enable this interrupt
}
#if defined(DSM2)
else if (s_current_protocol[EXTERNAL_MODULE] >= PROTO_DSM2_LP45 && s_current_protocol[EXTERNAL_MODULE] <= PROTO_DSM2_DSMX) {
else if ((s_current_protocol[EXTERNAL_MODULE] >= PROTO_DSM2_LP45 && s_current_protocol[EXTERNAL_MODULE] <= PROTO_DSM2_DSMX) || IS_MULTIMODULE_PROTOCOL (s_current_protocol[EXTERNAL_MODULE]))
{
DMA2_Stream2->CR &= ~DMA_SxCR_EN ; // Disable DMA
DMA2->LIFCR = DMA_LIFCR_CTCIF2 | DMA_LIFCR_CHTIF2 | DMA_LIFCR_CTEIF2 | DMA_LIFCR_CDMEIF2 | DMA_LIFCR_CFEIF2 ; // Write ones to clear bits
DMA2_Stream2->M0AR = CONVERT_PTR_UINT(&modulePulsesData[EXTERNAL_MODULE].dsm2.pulses[1]);
+4
View File
@@ -542,6 +542,10 @@ void processSerialData(uint8_t data);
#if defined(CROSSFIRE)
if (g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_CROSSFIRE)
return PROTOCOL_PULSES_CROSSFIRE;
#endif
#ifdef MULTIMODULE
else if (g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_MULTIMODULE)
return PROTOCOL_FRSKY_D;
#endif
if (g_model.moduleData[INTERNAL_MODULE].rfProtocol == RF_PROTO_OFF && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_PPM)
return g_model.telemetryProtocol;
+9
View File
@@ -107,6 +107,15 @@ const pm_char STR_OPEN9X[] PROGMEM =
ISTR(TARANIS_PROTOCOLS)
ISTR(XJT_PROTOCOLS)
ISTR(DSM_PROTOCOLS)
#if defined(MULTIMODULE)
ISTR(MULTI_PROTOCOLS)
ISTR(SUBTYPE_FLYSKY)
ISTR(SUBTYPE_HISKY)
ISTR(SUBTYPE_YD717)
ISTR(SUBTYPE_SYMAX)
ISTR(SUBTYPE_CX10)
ISTR(SUBTYPE_CG023)
#endif
ISTR(VOLTSRC)
ISTR(CURVE_TYPES)
ISTR(VSENSORTYPES)
+23
View File
@@ -183,7 +183,18 @@ extern const pm_char STR_OPEN9X[];
#define OFS_TARANIS_PROTOCOLS (OFS_VTRAINERMODES + sizeof(TR_VTRAINERMODES))
#define OFS_XJT_PROTOCOLS (OFS_TARANIS_PROTOCOLS + sizeof(TR_TARANIS_PROTOCOLS))
#define OFS_DSM_PROTOCOLS (OFS_XJT_PROTOCOLS + sizeof(TR_XJT_PROTOCOLS))
#if defined(MULTIMODULE)
#define OFS_MULTI_PROTOCOLS (OFS_DSM_PROTOCOLS + sizeof(TR_DSM_PROTOCOLS))
#define OFS_SUBTYPE_FLYSKY (OFS_MULTI_PROTOCOLS + sizeof(TR_MULTI_PROTOCOLS))
#define OFS_SUBTYPE_HISKY (OFS_SUBTYPE_FLYSKY + sizeof(TR_SUBTYPE_FLYSKY))
#define OFS_SUBTYPE_YD717 (OFS_SUBTYPE_HISKY + sizeof(TR_SUBTYPE_HISKY))
#define OFS_SUBTYPE_SYMAX (OFS_SUBTYPE_YD717 + sizeof(TR_SUBTYPE_YD717))
#define OFS_SUBTYPE_CX10 (OFS_SUBTYPE_SYMAX + sizeof(TR_SUBTYPE_SYMAX))
#define OFS_SUBTYPE_CG023 (OFS_SUBTYPE_CX10 + sizeof(TR_SUBTYPE_CX10))
#define OFS_VOLTSRC (OFS_SUBTYPE_CG023 + sizeof(TR_SUBTYPE_CG023))
#else
#define OFS_VOLTSRC (OFS_DSM_PROTOCOLS + sizeof(TR_DSM_PROTOCOLS))
#endif
#define OFS_CURVE_TYPES (OFS_VOLTSRC + sizeof(TR_VOLTSRC))
#define OFS_VSENSORTYPES (OFS_CURVE_TYPES + sizeof(TR_CURVE_TYPES))
#define OFS_VFORMULAS (OFS_VSENSORTYPES + sizeof(TR_VSENSORTYPES))
@@ -298,6 +309,15 @@ extern const pm_char STR_OPEN9X[];
#define STR_TARANIS_PROTOCOLS (STR_OPEN9X + OFS_TARANIS_PROTOCOLS)
#define STR_XJT_PROTOCOLS (STR_OPEN9X + OFS_XJT_PROTOCOLS)
#define STR_DSM_PROTOCOLS (STR_OPEN9X + OFS_DSM_PROTOCOLS)
#if defined(MULTIMODULE)
#define STR_MULTI_PROTOCOLS (STR_OPEN9X + OFS_MULTI_PROTOCOLS)
#define STR_SUBTYPE_FLYSKY (STR_OPEN9X + OFS_SUBTYPE_FLYSKY)
#define STR_SUBTYPE_HISKY (STR_OPEN9X + OFS_SUBTYPE_HISKY)
#define STR_SUBTYPE_YD717 (STR_OPEN9X + OFS_SUBTYPE_YD717)
#define STR_SUBTYPE_SYMAX (STR_OPEN9X + OFS_SUBTYPE_SYMAX)
#define STR_SUBTYPE_CX10 (STR_OPEN9X + OFS_SUBTYPE_CX10)
#define STR_SUBTYPE_CG023 (STR_OPEN9X + OFS_SUBTYPE_CG023)
#endif
#define STR_CURVE_TYPES (STR_OPEN9X + OFS_CURVE_TYPES)
#define STR_VSENSORTYPES (STR_OPEN9X + OFS_VSENSORTYPES)
#define STR_VFORMULAS (STR_OPEN9X + OFS_VFORMULAS)
@@ -524,6 +544,9 @@ extern const pm_char STR_GF[];
extern const pm_char STR_FAS_OFFSET[];
#endif
#if defined(MULTIMODULE)
extern const pm_char STR_MULTI_OPT[];
#endif
#if defined(DSM2) || defined(PXX)
extern const pm_char STR_RXNUM[];
#endif
+25 -2
View File
@@ -104,7 +104,7 @@
#define TR_COUNTRYCODES TR("US""JP""EU", "America""Japan\0 ""Europe\0")
#define LEN_TARANIS_PROTOCOLS "\004"
#define TR_TARANIS_PROTOCOLS "OFF\0""PPM\0""XJT\0""DSM2""CRSF"
#define TR_TARANIS_PROTOCOLS "OFF\0""PPM\0""XJT\0""DSM2""CRSF""MULT"
#define LEN_XJT_PROTOCOLS "\004"
#define TR_XJT_PROTOCOLS "OFF\0""D16\0""D8\0 ""LR12"
@@ -112,6 +112,29 @@
#define LEN_DSM_PROTOCOLS "\004"
#define TR_DSM_PROTOCOLS "LP45""DSM2""DSMX"
#define LEN_MULTI_PROTOCOLS "\006"
#define TR_MULTI_PROTOCOLS "FlySky""Hubsan""D8\0 ""Hisky\0""V2x2\0 ""DSM2\0 ""Devo\0 ""YD717\0""KN\0 ""SymaX\0""SLT\0 ""CX10\0 ""CG023\0""Bayang"
#define LEN_SUBTYPE_FLYSKY "\004"
#define TR_SUBTYPE_FLYSKY "Std\0""V9x9""V6x6""V912"
#define LEN_SUBTYPE_HISKY "\005"
#define TR_SUBTYPE_HISKY "HiSky""HK310"
// SUBTYPE FOR DSMX use TR_DSM_PROTOCOLS with offset +1 instead
#define LEN_SUBTYPE_YD717 "\007"
#define TR_SUBTYPE_YD717 "YD717\0 ""SKYWLKR""SYMAX2\0""XINXUN\0""NIHUI\0 "
#define LEN_SUBTYPE_SYMAX "\007"
#define TR_SUBTYPE_SYMAX "Std\0 ""5c"
#define LEN_SUBTYPE_CX10 "\005"
#define TR_SUBTYPE_CX10 "Green""Blue\0""DM007"
#define LEN_SUBTYPE_CG023 "\005"
#define TR_SUBTYPE_CG023 "CG023""YD829"
#define LEN_VTRIMINC TR("\006", "\013")
#define TR_VTRIMINC TR("Expo\0 ""ExFine""Fine\0 ""Medium""Coarse", "Exponential""Extra Fine\0""Fine\0 ""Medium\0 ""Coarse\0 ")
@@ -796,7 +819,6 @@
#define TR_MENUINPUTS "STICKS"
#define TR_MENULIMITS "SERVOS"
#endif
#define TR_MENUCURVES "CURVES"
#define TR_MENUCURVE "CURVE"
#define TR_MENULOGICALSWITCH "LOGICAL SWITCH"
@@ -813,6 +835,7 @@
#else
#define TR_RXNUM "RxNum"
#endif
#define TR_MULTI_OPT INDENT "Protocol Opt."
#define TR_SYNCMENU "[Sync]"
#define TR_LIMIT INDENT "Limit"
#define TR_MINRSSI "Min Rssi"