From e5595cfdce11fb2f7a0d4e10809376014556131e Mon Sep 17 00:00:00 2001 From: "bsongis@gmail.com" Date: Mon, 24 Jun 2013 10:17:25 +0000 Subject: [PATCH] [Taranis] DSM2 BIND code --- src/gui/menu_model.cpp | 21 ++++++++---- src/gui/view_main.cpp | 2 +- src/opentx.cpp | 11 ++++--- src/opentx.h | 8 +++-- src/protocols/dsm2_arm.cpp | 62 +++++++++++++++++------------------- src/protocols/pulses_arm.cpp | 14 ++++++++ src/protocols/pulses_avr.cpp | 42 ++++++++---------------- 7 files changed, 86 insertions(+), 74 deletions(-) diff --git a/src/gui/menu_model.cpp b/src/gui/menu_model.cpp index c23ba0d1a..2cd993059 100644 --- a/src/gui/menu_model.cpp +++ b/src/gui/menu_model.cpp @@ -928,7 +928,7 @@ void menuModelSetup(uint8_t event) #define MODEL_SETUP_MAX_LINES (1+ITEM_MODEL_SETUP_MAX) bool CURSOR_ON_CELL = (m_posHorz >= 0); - MENU_TAB({ 0, 0, CASE_PCBTARANIS(0) 2, IF_PERSISTENT_TIMERS(0) 0, 0, 2, IF_PERSISTENT_TIMERS(0) 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, NAVIGATION_LINE_BY_LINE|(NUM_STICKS+NUM_POTS+NUM_ROTARY_ENCODERS-1), LABEL(InternalModule), 0, IF_PORT1_ON(1), IF_PORT1_ON(2), IF_PORT1_ON(FAILSAFE_ROWS(0)), LABEL(ExternalModule), (g_model.externalModule==MODULE_TYPE_XJT || IS_MODULE_DSM2(EXTERNAL_MODULE)) ? (uint8_t)1 : (uint8_t)0, PORT2_CHANNELS_ROWS(), (IS_MODULE_PPM(1) || IS_MODULE_XJT(1)) ? (uint8_t)2 : (IS_MODULE_DSM2(1) ? (uint8_t)1 : HIDDEN_ROW), IF_PORT2_XJT(FAILSAFE_ROWS(1)), LABEL(Trainer), 0, TRAINER_CHANNELS_ROWS(), IF_TRAINER_ON(2)}); + MENU_TAB({ 0, 0, CASE_PCBTARANIS(0) 2, IF_PERSISTENT_TIMERS(0) 0, 0, 2, IF_PERSISTENT_TIMERS(0) 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, NAVIGATION_LINE_BY_LINE|(NUM_STICKS+NUM_POTS+NUM_ROTARY_ENCODERS-1), LABEL(InternalModule), 0, IF_PORT1_ON(1), IF_PORT1_ON(2), IF_PORT1_ON(FAILSAFE_ROWS(0)), LABEL(ExternalModule), (g_model.externalModule==MODULE_TYPE_XJT || IS_MODULE_DSM2(EXTERNAL_MODULE)) ? (uint8_t)1 : (uint8_t)0, PORT2_CHANNELS_ROWS(), (IS_MODULE_PPM(1) || IS_MODULE_XJT(1) || IS_MODULE_DSM2(1)) ? (uint8_t)2 : HIDDEN_ROW, IF_PORT2_XJT(FAILSAFE_ROWS(1)), LABEL(Trainer), 0, TRAINER_CHANNELS_ROWS(), IF_TRAINER_ON(2)}); #elif defined(CPUM64) #define CURSOR_ON_CELL (true) #define MODEL_SETUP_MAX_LINES ((IS_PPM_PROTOCOL(protocol)||IS_DSM2_PROTOCOL(protocol)||IS_PXX_PROTOCOL(protocol)) ? 1+ITEM_MODEL_SETUP_MAX : ITEM_MODEL_SETUP_MAX) @@ -945,7 +945,7 @@ void menuModelSetup(uint8_t event) if (!MENU_CHECK(menuTabModel, e_ModelSetup, MODEL_SETUP_MAX_LINES)) { #if defined(DSM2) - s_rangecheck_mode = false; + dsm2Flag = 0; #endif #if defined(PCBTARANIS) pxxFlag[INTERNAL_MODULE] = 0; @@ -1293,9 +1293,9 @@ void menuModelSetup(uint8_t event) if (editMode==0 && event==EVT_KEY_BREAK(KEY_ENTER)) checkModelIdUnique(g_eeGeneral.currModel); } + lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+3*FW, y, STR_MODULE_BIND, m_posHorz==1 ? attr : 0); + lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+10*FW, y, STR_MODULE_RANGE, m_posHorz==2 ? attr : 0); if (IS_MODULE_XJT(moduleIdx)) { - lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+3*FW, y, STR_MODULE_BIND, m_posHorz==1 ? attr : 0); - lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+10*FW, y, STR_MODULE_RANGE, m_posHorz==2 ? attr : 0); uint8_t newFlag = 0; if (attr && m_posHorz>0 && s_editMode>0) { if (m_posHorz == 1) @@ -1308,8 +1308,15 @@ void menuModelSetup(uint8_t event) } #if defined(DSM2) else { - lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+3*FW, y, STR_MODULE_RANGE, m_posHorz==1 ? attr : 0); - s_rangecheck_mode = (attr && m_posHorz>0 && editMode>0); // [MENU] key toggles range check mode + uint8_t newFlag = 0; + if (attr && m_posHorz>0 && s_editMode>0) { + if (m_posHorz == 1) + newFlag = DSM2_BIND_FLAG; + else if (m_posHorz == 2) { + newFlag = DSM2_RANGECHECK_FLAG; + } + } + dsm2Flag = newFlag; } #endif } @@ -1541,7 +1548,7 @@ void menuModelSetup(uint8_t event) #if defined(DSM2) if (IS_DSM2_PROTOCOL(protocol)) { lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+4*FW, y, STR_MODULE_RANGE, m_posHorz!=0 ? attr : 0); - s_rangecheck_mode = (attr && m_posHorz>0 && editMode>0); // [MENU] key toggles range check mode + dsm2Flag = (attr && m_posHorz>0 && editMode>0) ? DSM2_RANGE_CHECK_FLAG : 0; // [MENU] key toggles range check mode } #endif } diff --git a/src/gui/view_main.cpp b/src/gui/view_main.cpp index 817acf0d4..2f3e7c7a2 100644 --- a/src/gui/view_main.cpp +++ b/src/gui/view_main.cpp @@ -838,7 +838,7 @@ void menuMainView(uint8_t event) #endif #if defined(DSM2) - if (s_bind_mode) // Issue 98 + if (dsm2Flag == DSM2_BIND_FLAG) // Issue 98 lcd_putsAtt(15*FW, 0, PSTR("BIND"), 0); #endif } diff --git a/src/opentx.cpp b/src/opentx.cpp index 942d4fbb0..37bcbfaa9 100644 --- a/src/opentx.cpp +++ b/src/opentx.cpp @@ -124,10 +124,11 @@ audioQueue audio; #if defined(DSM2) // TODO move elsewhere -bool s_bind_mode = false; -bool s_rangecheck_mode = false; +uint8_t dsm2Flag = 0; +#if !defined(PCBTARANIS) uint8_t s_bind_allowed = 255; #endif +#endif uint8_t heartbeat; @@ -3449,21 +3450,23 @@ void doMixerCalculations() #if defined(DSM2) static uint8_t count_dsm_range = 0; - if (s_rangecheck_mode) + if (dsm2Flag & (DSM2_BIND_FLAG | DSM2_RANGECHECK_FLAG)) { if (++count_dsm_range >= 200) { AUDIO_PLAY(AU_FRSKY_CHEEP); count_dsm_range = 0; + } } #endif #if defined(PXX) static uint8_t count_pxx = 0; for (uint8_t i = 0; i < NUM_MODULES; i++) { - if((pxxFlag[i] & PXX_SEND_RANGECHECK) || (pxxFlag[i] & PXX_SEND_RXNUM)) + if (pxxFlag[i] & (PXX_SEND_RANGECHECK | PXX_SEND_RXNUM)) { if (++count_pxx >= 250) { AUDIO_PLAY(AU_FRSKY_CHEEP); count_pxx = 0; } + } } #endif diff --git a/src/opentx.h b/src/opentx.h index b78e92970..006772eed 100644 --- a/src/opentx.h +++ b/src/opentx.h @@ -463,11 +463,15 @@ enum EnumKeys { #define LOAD_MODEL_BITMAP() #endif +// TODO elsewhere ... #if defined(DSM2) - extern bool s_bind_mode; - extern bool s_rangecheck_mode; + #define DSM2_BIND_FLAG 0x80 + #define DSM2_RANGECHECK_FLAG 0x20 + extern uint8_t dsm2Flag; +#if !defined(PCBTARANIS) extern uint8_t s_bind_allowed; #endif +#endif #if defined(CPUARM) #define IS_PPM_PROTOCOL(protocol) (protocol==PROTO_PPM) diff --git a/src/protocols/dsm2_arm.cpp b/src/protocols/dsm2_arm.cpp index 7c5d0b622..2bd7a7fad 100644 --- a/src/protocols/dsm2_arm.cpp +++ b/src/protocols/dsm2_arm.cpp @@ -37,8 +37,9 @@ #include "../opentx.h" #if defined(PCBTARANIS) -uint16_t dsm2Stream[400]; // Likely more than we need +uint16_t dsm2Stream[400]; // Likely more than we need uint16_t *dsm2StreamPtr; +uint16_t dsm2Value; #else uint8_t dsm2Stream[64]; // Likely more than we need uint8_t *dsm2StreamPtr; @@ -47,17 +48,14 @@ uint8_t dsm2SerialBitCount; #endif // DSM2 control bits -#define DSM2_CHANS 6 -#define BIND_BIT 0x80 -#define RANGECHECK_BIT 0x20 -#define FRANCE_BIT 0x10 -#define DSMX_BIT 0x08 -#define BAD_DATA 0x47 +#define DSM2_CHANS 6 +#define FRANCE_BIT 0x10 +#define DSMX_BIT 0x08 +#define BAD_DATA 0x47 -#define BITLEN_DSM2 (8*2) //125000 Baud => 8uS per bit +#define BITLEN_DSM2 (8*2) //125000 Baud => 8uS per bit #if defined(PCBTARANIS) -uint16_t dsm2Value; void _send_1(uint8_t v) { dsm2Value += v; @@ -74,16 +72,17 @@ void sendByteDsm2(uint8_t b) //max 10changes 0 10 10 10 10 1 len += BITLEN_DSM2; } else { - _send_1(len-1); + _send_1(nlev ? len-5 : len+3); len = BITLEN_DSM2; lev = nlev; } b = (b>>1) | 0x80; //shift in stop bit } - _send_1(len+BITLEN_DSM2-1); // 2 stop bits + _send_1(len+BITLEN_DSM2+3); // 2 stop bits } void putDsm2Flush() { + dsm2StreamPtr--; //remove last stopbits and *dsm2StreamPtr++ = 44010; // Past the 44000 of the ARR } #else @@ -134,29 +133,28 @@ void setupPulsesDSM2(unsigned int port) dsm2StreamPtr = dsm2Stream; - // If more channels needed make sure the pulses union/array is large enough - if (dsmDat[0] & BAD_DATA) //first time through, setup header - { - switch(s_current_protocol[port]) - { - case PROTO_DSM2_LP45: - dsmDat[0] = 0x80; - break; - case PROTO_DSM2_DSM2: - dsmDat[0] = 0x90; - break; - default: - dsmDat[0] = 0x98; //dsmx, bind mode - break; - } + switch(s_current_protocol[port]) { + case PROTO_DSM2_LP45: + dsmDat[0] = 0x00; + break; + case PROTO_DSM2_DSM2: + dsmDat[0] = 0x10; + break; + default: // DSMX + dsmDat[0] = 0x18; + break; } - if ((dsmDat[0] & BIND_BIT) && (!switchState(SW_DSM2_BIND))) - dsmDat[0] &= ~BIND_BIT; // clear bind bit if trainer not pulled - if ((!(dsmDat[0] & BIND_BIT)) && s_rangecheck_mode) - dsmDat[0] |= RANGECHECK_BIT; // range check function + +#if !defined(PCBTARANIS) + if (s_bind_allowed) s_bind_allowed--; + if (s_bind_allowed && switchState(SW_DSM2_BIND)) + dsm2Flag = DSM2_BIND_FLAG; else - dsmDat[0] &= ~RANGECHECK_BIT; - dsmDat[1] = g_model.header.modelId; //DSM2 Header second byte for model match + dsm2Flag &= ~DSM2_BIND_FLAG; +#endif + + dsmDat[0] |= dsm2Flag; + dsmDat[1] = g_model.header.modelId; // DSM2 Header second byte for model match for (int i=0; i>5)+512, 1023); diff --git a/src/protocols/pulses_arm.cpp b/src/protocols/pulses_arm.cpp index 4fe850e79..32cd5ec33 100644 --- a/src/protocols/pulses_arm.cpp +++ b/src/protocols/pulses_arm.cpp @@ -63,6 +63,20 @@ void setupPulses(unsigned int port) #if defined(DSM2) case MODULE_TYPE_DSM2: required_protocol = limit(DSM2_PROTO_LP45, PROTO_DSM2_LP45+g_model.moduleData[EXTERNAL_MODULE].rfProtocol, DSM2_PROTO_DSMX); + // The module is set to OFF during one second before BIND start + { + static tmr10ms_t bindStartTime = 0; + if (dsm2Flag == DSM2_BIND_FLAG) { + if (bindStartTime == 0) bindStartTime = get_tmr10ms(); + if ((tmr10ms_t)(get_tmr10ms() - bindStartTime) < 100) { + required_protocol = PROTO_NONE; + break; + } + } + else { + bindStartTime = 0; + } + } break; #endif default: diff --git a/src/protocols/pulses_avr.cpp b/src/protocols/pulses_avr.cpp index 7113b99c0..4cda7f0a1 100644 --- a/src/protocols/pulses_avr.cpp +++ b/src/protocols/pulses_avr.cpp @@ -42,8 +42,6 @@ uint16_t nextMixerEndTime = 0; #if defined(DSM2) // DSM2 control bits #define DSM2_CHANS 6 -#define BIND_BIT 0x80 -#define RANGECHECK_BIT 0x20 #define FRANCE_BIT 0x10 #define DSMX_BIT 0x08 #define BAD_DATA 0x47 @@ -394,23 +392,17 @@ FORCEINLINE void setupPulsesDSM2() *ptr = 0x18; break; } + if (s_bind_allowed) s_bind_allowed--; if (s_bind_allowed && switchState(SW_DSM2_BIND)) - { - s_bind_mode = true; - *ptr |= BIND_BIT; - } - else if (s_rangecheck_mode) - { - *ptr |= RANGECHECK_BIT; - } + dsm2Flag = DSM2_BIND_FLAG; else - s_bind_mode = false; - ++ptr; + dsm2Flag &= ~DSM2_BIND_FLAG; + *ptr++ |= dsm2Flag; *ptr++ = g_model.header.modelId; - for (uint8_t i=0; i>5)+512,1023); *ptr++ = (i<<2) | ((pulse>>8)&0x03); // encoded channel + upper 2 bits pulse width *ptr++ = pulse & 0xff; // low byte @@ -487,7 +479,7 @@ void sendByteDsm2(uint8_t b) //max 10changes 0 10 10 10 10 1 // NOTE: This has now been tested as NOT required on the stock board, with the ATmega64A chip. _send_1(nlev ? len-5 : len+3); #else - _send_1(len -1); + _send_1(len-1); #endif len = BITLEN_DSM2; lev = nlev; @@ -510,33 +502,27 @@ void setupPulsesDSM2() pulses2MHzWPtr = pulses2MHz; // If more channels needed make sure the pulses union/array is large enough - switch (s_current_protocol[0]) - { + switch (s_current_protocol[0]) { case PROTO_DSM2_LP45: dsmDat[0] = 0x00; break; case PROTO_DSM2_DSM2: dsmDat[0] = 0x10; break; - default: // DSMX bind mode + default: // DSMX dsmDat[0] = 0x18; break; } if (s_bind_allowed) s_bind_allowed--; - if (s_bind_allowed && switchState(SW_TRN)) - { - s_bind_mode = true; - dsmDat[0] |= BIND_BIT; - } - else if (s_rangecheck_mode) - { - dsmDat[0] |= RANGECHECK_BIT; - } + if (s_bind_allowed && switchState(SW_DSM2_BIND)) + dsm2Flag = DSM2_BIND_FLAG; else - s_bind_mode = false; + dsm2Flag &= ~DSM2_BIND_FLAG; + dsmDat[0] |= dsm2Flag; dsmDat[1] = g_model.header.modelId; // DSM2 Header second byte for model match + for (uint8_t i=0; i>5)+512, 1023); dsmDat[2+2*i] = (i<<2) | ((pulse>>8)&0x03); // encoded channel + upper 2 bits pulse width