From 30f513d586b77345cf75d990e0b8199be7f1d6fc Mon Sep 17 00:00:00 2001 From: bsongis Date: Fri, 20 Jan 2012 18:23:17 +0000 Subject: [PATCH] DSM2 (ppm mode) pulled from er9x --- src/model_menus.cpp | 27 ++++++++++++---- src/myeeprom.h | 6 ++++ src/o9xstrings.cpp | 3 ++ src/o9xstrings.h | 16 +++++++++- src/pulses.cpp | 74 +++++++++++++++++++++++++++++++------------ src/translations/en.h | 3 ++ src/translations/fr.h | 3 ++ 7 files changed, 104 insertions(+), 28 deletions(-) diff --git a/src/model_menus.cpp b/src/model_menus.cpp index 1c5080d5e..5c8ef702a 100644 --- a/src/model_menus.cpp +++ b/src/model_menus.cpp @@ -387,7 +387,7 @@ void EditName(uint8_t x, uint8_t y, char *name, uint8_t size, uint8_t event, boo void menuProcModel(uint8_t event) { lcd_outdezNAtt(7*FW,0,g_eeGeneral.currModel+1,INVERS+LEADING0,2); - MENU(STR_MENUSETUP, menuTabModel, e_Model, (g_model.protocol ? 10 : 11), {0,sizeof(g_model.name)-1,2,2,0,0,0,0,6,2,1}); + MENU(STR_MENUSETUP, menuTabModel, e_Model, (g_model.protocol==PROTO_PPM ? 12 : 11), {0,sizeof(g_model.name)-1,2,2,0,0,0,0,0,6,2,1}); uint8_t sub = m_posVert; uint8_t y = 1*FH; @@ -491,24 +491,39 @@ void menuProcModel(uint8_t event) lcd_puts_P(0, y, STR_PROTO); lcd_putsnAtt(PARAM_OFS, y, STR_VPROTOS+LEN_VPROTOS*g_model.protocol, LEN_VPROTOS, (sub==subN && m_posHorz==0 ? (s_editMode>0 ? BLINK : INVERS):0)); - if(!g_model.protocol) { + if (!g_model.protocol) { lcd_putsnAtt(PARAM_OFS+4*FW, y, STR_NCHANNELS+LEN_NCHANNELS*(g_model.ppmNCH+2), LEN_NCHANNELS, ((sub==subN && m_posHorz==1) ? ((s_editMode>0) ? BLINK : INVERS) : 0)); lcd_puts_P(PARAM_OFS+11*FW, y, PSTR("u")); lcd_outdezAtt(PARAM_OFS+11*FW, y, (g_model.ppmDelay*50)+300, ((sub==subN && m_posHorz==2) ? ((s_editMode>0) ? BLINK : INVERS) : 0)); } +#ifdef DSM2 + // TODO optimize that? + else if (g_model.protocol == PROTO_DSM2) { + if (m_posHorz > 1) m_posHorz = 1; + int8_t x; + x = g_model.ppmNCH; + if ( x < 0 ) x = 0; + if ( x > 2 ) x = 2; + g_model.ppmNCH = x; + lcd_putsnAtt(PARAM_OFS+5*FW, y, STR_DSM2MODE+LEN_DSM2MODE*x, LEN_DSM2MODE, (sub==subN && m_posHorz==1 ? ((s_editMode>0) ? BLINK : INVERS) : 0)); + } +#endif else if (sub==subN) { m_posHorz = 0; } - if (sub==subN && (s_editMode>0 || p1valdiff || g_model.protocol) ) { + if (sub==subN && (s_editMode>0 || p1valdiff || (g_model.protocol!=0 && g_model.protocol!=PROTO_DSM2))) { // TODO avoid DSM2 when not defined switch (m_posHorz) { case 0: CHECK_INCDEC_MODELVAR(event,g_model.protocol,0,PROT_MAX); break; case 1: - CHECK_INCDEC_MODELVAR(event,g_model.ppmNCH,-2,4); + if (g_model.protocol == PROTO_DSM2) // TODO avoid DSM2 when not defined + CHECK_INCDEC_MODELVAR(event, g_model.ppmNCH, 0, 2); + else + CHECK_INCDEC_MODELVAR(event, g_model.ppmNCH, -2, 4); break; case 2: - CHECK_INCDEC_MODELVAR(event,g_model.ppmDelay,-4,10); + CHECK_INCDEC_MODELVAR(event, g_model.ppmDelay, -4, 10); break; } } @@ -516,7 +531,7 @@ void menuProcModel(uint8_t event) }subN++; if(s_pgOfs0 ? BLINK : INVERS) : 0) | PREC1|LEFT); diff --git a/src/myeeprom.h b/src/myeeprom.h index 6492edbc2..b3e8e01f8 100644 --- a/src/myeeprom.h +++ b/src/myeeprom.h @@ -255,6 +255,12 @@ PACK(typedef struct t_TimerData { uint16_t val; }) TimerData; +#ifdef DSM2 +#define LPXDSM2 0 +#define DSM2only 1 +#define DSM2_DSMX 2 +#endif + PACK(typedef struct t_ModelData { char name[10]; // 10 must be first for eeLoadModelName TimerData timer1; // TODO timers array diff --git a/src/o9xstrings.cpp b/src/o9xstrings.cpp index e6a054d62..6592f096a 100644 --- a/src/o9xstrings.cpp +++ b/src/o9xstrings.cpp @@ -38,6 +38,9 @@ const prog_char APM STR_OPEN9X[] = TR_VSWITCHES TR_VSRCRAW TR_VTMRMODES +#if defined(DSM2) + TR_DSM2MODE +#endif #if defined(PCBV3) TR_RE1RE2 TR_DATETIME diff --git a/src/o9xstrings.h b/src/o9xstrings.h index 0fc58bc66..8db0b7d3a 100644 --- a/src/o9xstrings.h +++ b/src/o9xstrings.h @@ -60,8 +60,14 @@ extern const PROGMEM char STR_OPEN9X[]; #define OFS_VSWITCHES (OFS_VKEYS + PSIZE(TR_VKEYS)) #define OFS_VSRCRAW (OFS_VSWITCHES + PSIZE(TR_VSWITCHES)) #define OFS_VTMRMODES (OFS_VSRCRAW + PSIZE(TR_VSRCRAW)) +#if defined(DSM2) +#define OFS_DSM2MODE (OFS_VTMRMODES + PSIZE(TR_VTMRMODES)) +#define OFS_ENDDSM2 (OFS_DSM2MODE + PSIZE(TR_DSM2MODE)) +#else +#define OFS_ENDDSM2 (OFS_VTMRMODES + PSIZE(TR_VTMRMODES)) +#endif #if defined(PCBV3) -#define OFS_RE1RE2 (OFS_VTMRMODES + PSIZE(TR_VTMRMODES)) +#define OFS_RE1RE2 (OFS_ENDDSM2) #define OFS_DATETIME (OFS_RE1RE2 + PSIZE(TR_RE1RE2)) #endif @@ -87,6 +93,7 @@ extern const PROGMEM char STR_OPEN9X[]; #define STR_VMLTPX2 (STR_OPEN9X + OFS_VMLTPX2) #define STR_VCSWFUNC (STR_OPEN9X + OFS_VCSWFUNC) #define STR_VFSWFUNC (STR_OPEN9X + OFS_VFSWFUNC) + #ifdef FRSKY #define STR_VTELEMUNIT (STR_OPEN9X + OFS_VTELEMUNIT) #define STR_VALARM (STR_OPEN9X + OFS_VALARM) @@ -94,17 +101,24 @@ extern const PROGMEM char STR_OPEN9X[]; #define STR_VTELPROTO (STR_OPEN9X + OFS_VTELPROTO) #define STR_TELEMCHNS (STR_OPEN9X + OFS_TELEMCHNS) #endif + #ifdef TEMPLATES #define STR_VTEMPLATES (STR_OPEN9X + OFS_VTEMPLATES) #endif + #ifdef HELI #define STR_VSWASHTYPE (STR_OPEN9X + OFS_VSWASHTYPE) #endif + #define STR_VKEYS (STR_OPEN9X + OFS_VKEYS) #define STR_VSWITCHES (STR_OPEN9X + OFS_VSWITCHES) #define STR_VSRCRAW (STR_OPEN9X + OFS_VSRCRAW) #define STR_VTMRMODES (STR_OPEN9X + OFS_VTMRMODES) +#if defined(DSM2) +#define STR_DSM2MODE (STR_OPEN9X + OFS_DSM2MODE) +#endif + #if defined(PCBV3) #define STR_RE1RE2 (STR_OPEN9X + OFS_RE1RE2) #define STR_DATETIME (STR_OPEN9X + OFS_DATETIME) diff --git a/src/pulses.cpp b/src/pulses.cpp index df7c8a229..773111607 100644 --- a/src/pulses.cpp +++ b/src/pulses.cpp @@ -21,6 +21,15 @@ #include "open9x.h" +#ifdef DSM2 +#define DSM2_CHANS 6 +#define BIND_BIT 0x80 +#define RANGECHECK_BIT 0x20 +#define FRANCE_BIT 0x10 +#define DSMX_BIT 0x08 +#define BAD_DATA 0x47 +#endif + #if defined(DSM2_PPM) || defined(PXX) uint8_t s_current_protocol = 255; #endif @@ -248,11 +257,9 @@ normal: */ -#define DSM2_CHANS 6 - FORCEINLINE void setupPulsesDsm2() { - *pulses2MHzWPtr++ = (isFunctionActive(FUNC_MODELMATCH) ? 0x80 : 0x00); + *pulses2MHzWPtr++ = (isFunctionActive(FUNC_MODELMATCH) ? BIND_BIT : 0x00); *pulses2MHzWPtr++ = g_eeGeneral.currModel; for (uint8_t i=0; i>1)+512, 1023); @@ -300,34 +307,59 @@ void DSM2_Init(void) #endif #if defined(DSM2_PPM) -static uint8_t *Dsm2_pulsePtr = (uint8_t *)pulses2MHz; -void setupPulsesDsm2(uint8_t chns) +static uint8_t *pulses2MHzDSM2WPtr = (uint8_t *)pulses2MHz; +static uint8_t *pulses2MHzDSM2RPtr = (uint8_t *)pulses2MHz; +inline void _send_1(uint8_t v) { - static uint8_t dsmDat[2+6*2]= {0xFF,0x00, 0x00,0xAA, 0x05,0xFF, 0x09,0xFF, 0x0D,0xFF, 0x13,0x54, 0x14,0xAA}; + *pulses2MHzDSM2WPtr++ = v; +} + +#define BITLEN_DSM2 (8*2) //125000 Baud +void sendByteDsm2(uint8_t b) //max 10changes 0 10 10 10 10 1 +{ + bool lev = 0; + uint8_t len = BITLEN_DSM2; //max val: 9*16 < 256 + for( uint8_t i=0; i<=8; i++){ //8Bits + Stop=1 + bool nlev = b & 1; //lsb first + if(lev == nlev){ + len += BITLEN_DSM2; + }else{ + _send_1(len -1); + len = BITLEN_DSM2; + lev = nlev; + } + b = (b>>1) | 0x80; //shift in stop bit + } + _send_1(len+BITLEN_DSM2-1); // 2 stop bits +} + +void setupPulsesDsm2() +{ + static uint8_t dsmDat[2+6*2] = {0xFF,0x00, 0x00,0xAA, 0x05,0xFF, 0x09,0xFF, 0x0D,0xFF, 0x13,0x54, 0x14,0xAA}; uint8_t counter; // If more channels needed make sure the pulses union/array is large enough - if (dsmDat[0] & BadData) //first time through, setup header + if (dsmDat[0] & BAD_DATA) // first time through, setup header { switch(g_model.ppmNCH) { case LPXDSM2: - dsmDat[0]= 0x80; + dsmDat[0] = BIND_BIT; break; case DSM2only: - dsmDat[0]=0x90; + dsmDat[0] = 0x90; break; default: - dsmDat[0]=0x98; //dsmx, bind mode + dsmDat[0] = 0x98; // DSMX bind mode break; } } - if ((dsmDat[0]&BindBit)&&(!keyState(SW_Trainer))) dsmDat[0]&=~BindBit; //clear bind bit if trainer not pulled - if ((!(dsmDat[0]&BindBit))&&getSwitch(MAX_DRSWITCH-1,0,0)) dsmDat[0]|=RangeCheckBit; //range check function + if ((dsmDat[0] & BIND_BIT) && (!isFunctionActive(FUNC_MODELMATCH))) dsmDat[0] &= ~BIND_BIT; //clear bind bit if trainer not pulled + // TODO add a function key for that: if ((!(dsmDat[0] & BIND_BIT)) && isFunctionActive(FUNC_RANGECHECK)) dsmDat[0] |= RANGECHECK_BIT; //range check function - else dsmDat[0]&=~RangeCheckBit; - dsmDat[1]=g_eeGeneral.currModel+1; //DSM2 Header second byte for model match - for(uint8_t i=0; i>1)+512,1023); dsmDat[2+2*i] = (i<<2) | ((pulse>>8)&0x03); @@ -338,12 +370,11 @@ void setupPulsesDsm2(uint8_t chns) { sendByteDsm2(dsmDat[counter]); } - pulses2MHzptr-=1; //remove last stopbits and + pulses2MHzDSM2WPtr -= 1; //remove last stopbits and _send_1( 255 ); //prolong them _send_1(0); //end of pulse stream - Dsm2_pulsePtr = pulses2MHz.pbyte; + pulses2MHzDSM2RPtr = (uint8_t *)pulses2MHz; } - #endif #if defined(SILVER) || defined(CTP1009) @@ -545,6 +576,7 @@ void setupPulses() } #endif + // TODO these 2 lines could be avoided when protocol is DSM2 (PPM output) pulses2MHzWPtr = pulses2MHz; pulses2MHzRPtr = pulses2MHz; @@ -567,7 +599,7 @@ void setupPulses() setupPulsesPXX(); break; #endif -#ifdef DSM2_SERIAL +#ifdef DSM2 case PROTO_DSM2: sei(); setupPulsesDsm2(); @@ -585,10 +617,10 @@ ISR(TIMER1_CAPT_vect) // 2MHz pulse generation { uint8_t x ; PORTB ^= (1< 200) PORTB |= (1<