Exemple #1
0
void eeReadAll()
{
//	txmit('a') ;
  if(!ee32LoadGeneral() )
  {
//	txmit('b') ;
		
    alert((char const *)PSTR(STR_BAD_EEPROM), true);
    g_eeGeneral.contrast = 18 ;
    message(PSTR(STR_EE_FORMAT));
    generalDefault();

    modelDefault(0);
    
		STORE_GENERALVARS;
    STORE_MODELVARS;        
  }
	else
	{
  	ee32LoadModel(g_eeGeneral.currModel);
	}

	// Now update the trainer values if necessary.
  uint32_t i ;
	for ( i = 0 ; i < 4 ; i += 1 )
	{
		if ( g_eeGeneral.trainer.mix[i].swtch != -16 )
		{
			g_eeGeneral.exTrainer[i].swtch = g_eeGeneral.trainer.mix[i].swtch ;
			g_eeGeneral.exTrainer[i].studWeight = g_eeGeneral.trainer.mix[i].studWeight * 13 / 4 ;
			g_eeGeneral.trainer.mix[i].swtch = -16 ;
			STORE_GENERALVARS ;
		}
	}
}
Exemple #2
0
void eeLoadModel(uint8_t id)
{
  if(id<MAX_MODELS)
  {
    theFile.openRlc(FILE_MODEL(id));
    uint16_t sz = theFile.readRlc((uint8_t*)&g_model, sizeof(g_model));

#ifdef SIMU
    if (sz > 0 && sz != sizeof(g_model)) {
      printf("Model data read=%d bytes vs %d bytes\n", sz, (int)sizeof(ModelData));
    }
#endif

    if (sz < 730/*sizeof(last compatible eeprom)*/) {
      modelDefault(id);
      eeCheck(true);
    }

    resetTimer1();
    resetTimer2();
    resetProto();
#ifdef TELEMLOGS
    initTelemLog();
#endif
  }
}
Exemple #3
0
TEST(Trims, invertedThrottlePlusThrottleTrim)
{
  MODEL_RESET();
  modelDefault(0);
  g_model.throttleReversed = 1;
  g_model.thrTrim = 1;
  // stick max + trim max
  anaInValues[THR_STICK] = +1024;
  setTrimValue(0, THR_STICK, TRIM_MAX);
  evalMixes(1);
  EXPECT_EQ(channelOutputs[2], -1024);
  // stick max + trim mid
  anaInValues[THR_STICK] = +1024;
  setTrimValue(0, THR_STICK, 0);
  evalMixes(1);
  EXPECT_EQ(channelOutputs[2], -1024+250);
  // stick max + trim min
  anaInValues[THR_STICK] = +1024;
  setTrimValue(0, THR_STICK, TRIM_MIN);
  evalMixes(1);
  EXPECT_EQ(channelOutputs[2], -1024+500);
  // stick min + trim max
  anaInValues[THR_STICK] = -1024;
  setTrimValue(0, THR_STICK, TRIM_MAX);
  evalMixes(1);
  EXPECT_EQ(channelOutputs[2], +1024);
  // stick min + trim min
  anaInValues[THR_STICK] = -1024;
  setTrimValue(0, THR_STICK, TRIM_MIN);
  evalMixes(1);
  EXPECT_EQ(channelOutputs[2], +1024);

  // now the same tests with extended Trims
  g_model.extendedTrims = 1;
  // stick max + trim max
  anaInValues[THR_STICK] = +1024;
  setTrimValue(0, THR_STICK, TRIM_EXTENDED_MAX);
  evalMixes(1);
  EXPECT_EQ(channelOutputs[2], -1024);
  // stick max + trim mid
  anaInValues[THR_STICK] = +1024;
  setTrimValue(0, THR_STICK, 0);
  evalMixes(1);
  EXPECT_EQ(channelOutputs[2], -1024+1000);
  // stick max + trim min
  anaInValues[THR_STICK] = +1024;
  setTrimValue(0, THR_STICK, TRIM_EXTENDED_MIN);
  evalMixes(1);
  EXPECT_EQ(channelOutputs[2], -1024+2000);
  // stick min + trim max
  anaInValues[THR_STICK] = -1024;
  setTrimValue(0, THR_STICK, TRIM_EXTENDED_MAX);
  evalMixes(1);
  EXPECT_EQ(channelOutputs[2], +1024);
  // stick min + trim min
  anaInValues[THR_STICK] = -1024;
  setTrimValue(0, THR_STICK, TRIM_EXTENDED_MIN);
  evalMixes(1);
  EXPECT_EQ(channelOutputs[2], +1024);
}
Exemple #4
0
TEST(Trims, InstantTrim)
{
  MODEL_RESET();
  modelDefault(0);
  anaInValues[AIL_STICK] = 50;
  instantTrim();
  EXPECT_EQ(25, getTrimValue(0, AIL_STICK));
}
Exemple #5
0
void eeLoadModel(uint8_t id)
{
  if (id<MAX_MODELS) {

#if defined(SDCARD)
    closeLogs();
#endif

    if (pulsesStarted()) {
      pausePulses();
    }

    pauseMixerCalculations();

    uint32_t size = loadModel(id);

#if defined(SIMU)
    if (sizeof(uint16_t) + sizeof(g_model) > EEPROM_ZONE_SIZE)
      TRACE("Model data size can't exceed %d bytes (%d bytes)", int(EEPROM_ZONE_SIZE-sizeof(uint16_t)), (int)sizeof(g_model));
    if (size > 0 && size != sizeof(g_model))
      TRACE("Model data read=%d bytes vs %d bytes\n", size, (int)sizeof(ModelData));
#endif

    if (size < EEPROM_BUFFER_SIZE) { // if not loaded a fair amount
      modelDefault(id) ;
      eeCheck(true);
    }

    AUDIO_FLUSH();
    flightReset();
    logicalSwitchesReset();

    if (pulsesStarted()) {
      checkAll();
      resumePulses();
    }

    customFunctionsReset();

    restoreTimers();

    resumeMixerCalculations();
    // TODO pulses should be started after mixer calculations ...

#if defined(FRSKY)
    frskySendAlarms();
#endif

#if defined(SDCARD)
    referenceModelAudioFiles();
#endif

    LOAD_MODEL_BITMAP();
    SEND_FAILSAFE_1S();
    PLAY_MODEL_NAME();
  }
}
Exemple #6
0
TEST(Trims, CopySticksToOffset)
{
  MODEL_RESET();
  modelDefault(0);
  anaInValues[ELE_STICK] = -100;
  perMain();
  copySticksToOffset(1);
  EXPECT_EQ(g_model.limitData[1].offset, -97);
}
Exemple #7
0
TEST(Trims, CopySticksToOffset)
{
  MODEL_RESET();
  modelDefault(0);
  anaInValues[ELE_STICK] = -100;
#if defined(CPUARM)
  doMixerCalculations();
#else
  perMain();
#endif
  copySticksToOffset(1);
  EXPECT_EQ(g_model.limitData[1].offset, -97);
}
Exemple #8
0
TEST(Trims, CopyTrimsToOffset)
{
  MODEL_RESET();
  modelDefault(0);
  setTrimValue(0, ELE_STICK, -100); // -100 on elevator
  evalFunctions(); // it disables all safety channels
  copyTrimsToOffset(1);
  EXPECT_EQ(getTrimValue(0, ELE_STICK), -100); // unchanged
#if defined(CPUARM)
  EXPECT_EQ(g_model.limitData[1].offset, -195);
#else
  EXPECT_EQ(g_model.limitData[1].offset, -200);
#endif
}
Exemple #9
0
TEST(Trims, InstantTrimNegativeCurve)
{
  MODEL_RESET();
  modelDefault(0);
  ExpoData *expo = expoAddress(AIL_STICK);
  expo->curve.type = CURVE_REF_CUSTOM;
  expo->curve.value = 1;
  g_model.points[0] = -100;
  g_model.points[1] = -75;
  g_model.points[2] = -50;
  g_model.points[3] = -25;
  g_model.points[4] = 0;
  anaInValues[AIL_STICK] = 512;
  instantTrim();
  EXPECT_EQ(128, getTrimValue(0, AIL_STICK));
}
Exemple #10
0
void eeErase(bool warn)
{
  generalDefault();
  modelDefault(0);

  if (warn) {
    ALERT(STR_EEPROMWARN, STR_BADEEPROMDATA, AU_BAD_EEPROM);
  }

  MESSAGE(STR_EEPROMWARN, STR_EEPROMFORMATTING, NULL, AU_EEPROM_FORMATTING);

  eepromFormat();
  eeDirty(EE_GENERAL);
  eeDirty(EE_MODEL);
  eeCheck(true);
}
Exemple #11
0
TEST(getSwitch, inputWithTrim)
{
  MODEL_RESET();
  modelDefault(0);
  MIXER_RESET();

  g_model.logicalSw[0] = { LS_FUNC_VPOS, MIXSRC_FIRST_INPUT, 0, 0 };

  doMixerCalculations();
  evalLogicalSwitches();
  EXPECT_EQ(getSwitch(SWSRC_SW1), false);

  setTrimValue(0, 0, 32);
  doMixerCalculations();
  evalLogicalSwitches();
  EXPECT_EQ(getSwitch(SWSRC_SW1), true);
}
Exemple #12
0
TEST(evalLogicalSwitches, playFile)
{
  SYSTEM_RESET();
  MODEL_RESET();
  modelDefault(0);
  MIXER_RESET();

  extern uint64_t sdAvailableLogicalSwitchAudioFiles;
  sdAvailableLogicalSwitchAudioFiles = 0xffffffffffffffff;
  char filename[AUDIO_FILENAME_MAXLEN+1];
  isAudioFileReferenced((LOGICAL_SWITCH_AUDIO_CATEGORY << 24) + (0 << 16) + AUDIO_EVENT_OFF, filename);
  EXPECT_EQ(strcmp(filename, "/SOUNDS/en/MODEL01/L1-off.wav"), 0);
  isAudioFileReferenced((LOGICAL_SWITCH_AUDIO_CATEGORY << 24) + (0 << 16) + AUDIO_EVENT_ON, filename);
  EXPECT_EQ(strcmp(filename, "/SOUNDS/en/MODEL01/L1-on.wav"), 0);
  isAudioFileReferenced((LOGICAL_SWITCH_AUDIO_CATEGORY << 24) + (31 << 16) + AUDIO_EVENT_OFF, filename);
  EXPECT_EQ(strcmp(filename, "/SOUNDS/en/MODEL01/L32-off.wav"), 0);
  isAudioFileReferenced((LOGICAL_SWITCH_AUDIO_CATEGORY << 24) + (31 << 16) + AUDIO_EVENT_ON, filename);
  EXPECT_EQ(strcmp(filename, "/SOUNDS/en/MODEL01/L32-on.wav"), 0);
}
Exemple #13
0
void eeReadAll()
{
  if(!EeFsOpen()  || 
     EeFsck() < 0 || 
     !eeLoadGeneral()
  )
  {
#ifdef SIM
    printf("bad eeprom contents\n");
#else
    alert(PSTR("Bad EEprom Data"));
#endif
    EeFsFormat();
    generalDefault();
    theFile.writeRlc2(FILE_GENERAL,FILE_TYP_GENERAL,(uint8_t*)&g_eeGeneral, 
                     sizeof(g_eeGeneral),200);

    modelDefault(0);
    theFile.writeRlc2(FILE_MODEL(0),FILE_TYP_MODEL,(uint8_t*)&g_model, 
                     sizeof(g_model),200);
  }
  eeLoadModel(g_eeGeneral.currModel);
}
Exemple #14
0
void eeReadAll()
{
  if(!EeFsOpen() ||
     EeFsck() < 0 ||
     !eeLoadGeneral()
  )
  {
    alert(PSTR("Bad EEprom Data"), true);
    message(PSTR("EEPROM Formatting"));
    EeFsFormat();
    //alert(PSTR("format ok"));
    generalDefault();
    //alert(PSTR("default ok"));

    theFile.writeRlc(FILE_GENERAL, FILE_TYP_GENERAL,(uint8_t*)&g_eeGeneral,sizeof(EEGeneral), true);

    modelDefault(0);
    //alert(PSTR("modef ok"));
    theFile.writeRlc(FILE_MODEL(0), FILE_TYP_MODEL, (uint8_t*)&g_model, sizeof(g_model), true);
    //alert(PSTR("modwrite ok"));
  }

  eeLoadModel(g_eeGeneral.currModel);
}
Exemple #15
0
void eeReadAll()
{
  fill_file_index() ;

  if (!eeLoadGeneral() )
  {
    generalDefault();
    modelDefault(0);

    ALERT(STR_EEPROMWARN, STR_BADEEPROMDATA, AU_BAD_EEPROM);

    MESSAGE(STR_EEPROMWARN, STR_EEPROMFORMATTING, NULL, AU_EEPROM_FORMATTING);

    /* we remove all models */
    for (uint32_t i=0; i<MAX_MODELS; i++)
      eeDeleteModel(i);

    eeDirty(EE_GENERAL);
    eeDirty(EE_MODEL);
  }
  else {
    eeLoadModelHeaders() ;
  }

  // TODO common!
  stickMode = g_eeGeneral.stickMode;

#if defined(CPUARM)
  for (uint8_t i=0; languagePacks[i]!=NULL; i++) {
    if (!strncmp(g_eeGeneral.ttsLanguage, languagePacks[i]->id, 2)) {
      currentLanguagePackIdx = i;
      currentLanguagePack = languagePacks[i];
    }
  }
#endif
}
Exemple #16
0
void eeLoadModel(uint8_t id)
{
  if (id<MAX_MODELS) {

#if defined(SDCARD)
    closeLogs();
#endif

    if (pulsesStarted()) {
      pausePulses();
    }

    pauseMixerCalculations();

    uint16_t size = File_system[id+1].size ;

    memset(&g_model, 0, sizeof(g_model));

#if defined(SIMU)
    if (sizeof(struct t_eeprom_header) + sizeof(g_model) > 4096)
      TRACE("Model data size can't exceed %d bytes (%d bytes)", int(4096-sizeof(struct t_eeprom_header)), (int)sizeof(g_model));
    else if (size > 0 && size != sizeof(g_model))
      TRACE("Model data read=%d bytes vs %d bytes\n", size, (int)sizeof(ModelData));
#endif

    if (size > sizeof(g_model)) {
      size = sizeof(g_model) ;
    }

    if(size < 256) { // if not loaded a fair amount
      modelDefault(id) ;
      eeCheck(true);
    }
    else {
      read32_eeprom_data((File_system[id+1].block_no << 12) + sizeof(struct t_eeprom_header), (uint8_t *)&g_model, size) ;
    }

    AUDIO_FLUSH();
    flightReset();
    logicalSwitchesReset();

    if (pulsesStarted()) {
      checkAll();
      resumePulses();
    }

    activeFnSwitches = 0;
    activeFunctions = 0;
    memclear(lastFunctionTime, sizeof(lastFunctionTime));

    restoreTimers();

    resumeMixerCalculations();
    // TODO pulses should be started after mixer calculations ...

#if defined(FRSKY)
    frskySendAlarms();
#endif

#if defined(CPUARM) && defined(SDCARD)
    referenceModelAudioFiles();
#endif

    LOAD_MODEL_BITMAP();

    SEND_FAILSAFE_1S();
  }
}
Exemple #17
0
TEST(Trims, invertedThrottlePlusthrottleTrimWithZeroWeightOnThrottle)
{
  MODEL_RESET();
  modelDefault(0);
  g_model.throttleReversed = 1;
  g_model.thrTrim = 1;
#if defined(PCBTARANIS)
  // the input already exists
  ExpoData *expo = expoAddress(THR_STICK);
#else
  ExpoData *expo = expoAddress(0);
  expo->mode = 3;
  expo->chn = THR_STICK;
#endif
  expo->weight = 0;
  // stick max + trim max
  anaInValues[THR_STICK] = +1024;
  setTrimValue(0, THR_STICK, TRIM_MAX);
  evalMixes(1);
  EXPECT_EQ(channelOutputs[2], 0);
  // stick max + trim mid
  anaInValues[THR_STICK] = +1024;
  setTrimValue(0, THR_STICK, 0);
  evalMixes(1);
  EXPECT_LE(abs(channelOutputs[2] - 125), 1);
  // stick max + trim min
  anaInValues[THR_STICK] = +1024;
  setTrimValue(0, THR_STICK, TRIM_MIN);
  evalMixes(1);
  EXPECT_EQ(channelOutputs[2], 250);
  // stick min + trim max
  anaInValues[THR_STICK] = -1024;
  setTrimValue(0, THR_STICK, TRIM_MAX);
  evalMixes(1);
  EXPECT_EQ(channelOutputs[2], 0);
  // stick min + trim mid
  anaInValues[THR_STICK] = -1024;
  setTrimValue(0, THR_STICK, 0);
  evalMixes(1);
  EXPECT_LE(abs(channelOutputs[2] - 125), 1);
  // stick min + trim min
  anaInValues[THR_STICK] = -1024;
  setTrimValue(0, THR_STICK, TRIM_MIN);
  evalMixes(1);
  EXPECT_EQ(channelOutputs[2], 250);

  // now some tests with extended Trims
  g_model.extendedTrims = 1;
  // trim min + various stick positions = should always be same value
  setTrimValue(0, THR_STICK, TRIM_EXTENDED_MIN);
  anaInValues[THR_STICK] = -1024;
  evalMixes(1);
  EXPECT_EQ(channelOutputs[2], 1000);
  anaInValues[THR_STICK] = -300;
  evalMixes(1);
  EXPECT_EQ(channelOutputs[2], 1000);
  anaInValues[THR_STICK] = +300;
  evalMixes(1);
  EXPECT_EQ(channelOutputs[2], 1000);
  anaInValues[THR_STICK] = +1024;
  evalMixes(1);
  EXPECT_EQ(channelOutputs[2], 1000);

  // trim max + various stick positions = should always be same value
  setTrimValue(0, THR_STICK, TRIM_EXTENDED_MAX);
  anaInValues[THR_STICK] = -1024;
  evalMixes(1);
  EXPECT_EQ(channelOutputs[2], 0);
  anaInValues[THR_STICK] = -300;
  evalMixes(1);
  EXPECT_EQ(channelOutputs[2], 0);
  anaInValues[THR_STICK] = +300;
  evalMixes(1);
  EXPECT_EQ(channelOutputs[2], 0);
  anaInValues[THR_STICK] = +1024;
  evalMixes(1);
  EXPECT_EQ(channelOutputs[2], 0);
}
Exemple #18
0
void eeLoadModel(uint8_t id)
{
  if(id>=MAX_MODELS) return; //paranoia

  theFile.openRd(FILE_MODEL(id));
  uint16_t sz = 0;
  if(theFile.readRlc2((uint8_t*)&g_model,sizeof(g_model.name)+1) == (sizeof(g_model.name)+1)){
    theFile.openRd(FILE_MODEL(id));
    if(g_model.mdVers < MDVERS192){
      sz = theFile.readRlc1((uint8_t*)&g_model, sizeof(g_model)); 
    }else{
      sz = theFile.readRlc2((uint8_t*)&g_model, sizeof(g_model)); 
    }
  }

// #if 0
//   if( sz == sizeof(ModelData_r0) ){
//     printf("converting model data t0 r84\n");
//     char* pSrc = ((char*)&g_model) + sizeof(ModelData_r0); //Pointers behind the end
//     char* pDst = ((char*)&g_model) + sizeof(ModelData_r84);
//     ModelData_r84 *model84 = (ModelData_r84*)&g_model;
// #define sizeof84(memb) sizeof(((ModelData_r84*)0)->memb)
//     fullCopy(sizeof84(trimData)+sizeof84(curves9)+sizeof84(curves5));
// 
//     partCopy(sizeof84(mixData), sizeof(MixData_r0)*20);
// 
//     for(uint8_t i=0; i<DIM(model84->expoData); i++){
//       partCopy(sizeof(ExpoData_r84), sizeof(ExpoData_r0));
//     }
//     sz = sizeof(ModelData_r84);
//     model84->mdVers = MDVERS84;
//   }
// #endif  
  if( sz == sizeof(ModelData_r84) && g_model.mdVers == MDVERS84) {
    printf("converting model data from r84 to r143\n");
    ModelData_r84  *model84  = (ModelData_r84*)&g_model;
    ModelData_r143 *model143 = (ModelData_r143*)&g_model;
    for(int8_t i=3; i>=0; i--){
      int16_t val = trimExp2(model84->trimData[i].trim) + model84->trimData[i].trimDef_lt133;
      model143->trimData[i].itrim = trimRevert2(val);
      model143->trimData[i].tmode = 0;
    }
    memmove(&model143->curves5, &model84->curves5, sizeof(model84->curves5)+sizeof(model84->curves9));
    memset(model143->curves3, 0, sizeof(model143->curves3));
    model143->curves3[0][2] =  100;
    model143->curves3[2][0] =  100;
    model143->curves3[2][2] =  100;
    model143->curves3[1][0] = -100;
    sz = sizeof(ModelData_r143);
    model84->mdVers = MDVERS143;
  }
  if( sz == sizeof(ModelData_r143) && g_model.mdVers == MDVERS143) {
    printf("converting model data from r143 to r167\n");
    ModelData_r143 *model143 = (ModelData_r143*)&g_model;
    ModelData_r167 *model167 = (ModelData_r167*)&g_model;
    for(int8_t i=0; i<NUM_CHNOUT; i++){
      int8_t v = model143->limitData[i].min-100;
      model167->limitData[i].min   = add7Bit(val2idx50_150(v),40);
      model167->limitData[i].scale = 0;
      v = model143->limitData[i].max+100;
      model167->limitData[i].max   = add7Bit(val2idx50_150(v),-40);
      model167->limitData[i].binSwtch = 0;
    }
    model143->mdVers = MDVERS167;
  }
  if( sz == sizeof(ModelData_r167) && g_model.mdVers == MDVERS167) {
    printf("converting model data from r167 to r171\n");
    ModelData_r167 *model167 = (ModelData_r167*)&g_model;
    ModelData_r171 *model171 = (ModelData_r171*)&g_model;
    ExpoData_r84   *hlpExp   = (ExpoData_r84*) 
      ((char*)&model171->expoTab
       +sizeof(model171->expoTab)
       -sizeof(model167->expoData));
    // old:20B new:45B
    // move old to end
    // clr unused start 25B
    // interpret old to new <= 3*8=24B
    // clr old at end 20B
    //
    memmove(hlpExp, 
	    &model167->expoData,
	    sizeof(ModelData_r167)-offsetof(ModelData_r167,expoData));
    memset(model171->expoTab, 0, 
	   sizeof(model171->expoTab)
	   -sizeof(model167->expoData));
    
    for(int8_t i=0,j=0; i<4; i++){
      if(hlpExp[i].expNorm || hlpExp[i].expNormWeight){
        model171->expoTab[j].drSw    = hlpExp[i].drSw ? -hlpExp[i].drSw : 0;
        model171->expoTab[j].chn     = convertMode(i);
        model171->expoTab[j].mode3   = EM_BOTH;
        model171->expoTab[j].exp5    = val2idx15_100(hlpExp[i].expNorm);
        model171->expoTab[j].weight6 =val2idx30_100(hlpExp[i].expNormWeight+100);
        j++;
      }

      if(hlpExp[i].drSw && (hlpExp[i].expDr || hlpExp[i].expSwWeight)){
	model171->expoTab[j].drSw    = hlpExp[i].drSw;
	model171->expoTab[j].chn     = convertMode(i);
	model171->expoTab[j].mode3   = EM_BOTH;
	model171->expoTab[j].exp5    = val2idx15_100(hlpExp[i].expDr);
	model171->expoTab[j].weight6 =val2idx30_100(hlpExp[i].expSwWeight+100);
        j++;
      }
    }
    memset(hlpExp, 0, sizeof(model167->expoData));
    sz = sizeof(ModelData_r171);

    for(uint8_t i=0;i<MAX_MIXERS;i++){
      MixData_r0 &md = model171->mixData[i];
      if(md.destCh==0) break;
      md.srcRaw = convertMode(md.srcRaw-1)+1;
    }
    if(g_eeGeneral.stickMode & 1)
      memswap(&model171->trimData[1],
              &model171->trimData[2],sizeof(model171->trimData[1]));
    if(g_eeGeneral.stickMode & 2)
      memswap(&model171->trimData[0],
              &model171->trimData[3],sizeof(model171->trimData[0]));

    model167->mdVers = MDVERS171;
  }
  if( sz == sizeof(ModelData_r171) && g_model.mdVers == MDVERS171) {
    printf("converting model data from r171 to r192\n");
    ModelData_r171 *model171 = (ModelData_r171*)&g_model;
    ModelData_r192 *model192 = (ModelData_r192*)&g_model;
    memmove(&model192->curves3, 
	    &model171->curves3,
	    sizeof(ModelData_r171)-offsetof(ModelData_r171,curves3));
    for(uint8_t i=MAX_MIXERS;i>0;){i--;
      MixData_r0   &md0   = model171->mixData[i];
      MixData_r192 &md192 = model192->mixData[i];
      uint8_t dc=md0.destCh;
      if(dc==0){
	memset(&md192,0,5);
	continue;
      }
      memmove(&md192.weight,&md0.weight,3);
      //                       0  1   2   3   4  5  6  7   8   9
      uint8_t sr=md0.srcRaw; //0 RUD ELE THR AIL P1 P2 P3 MAX FUL X1-4
      memset(&md192,0,2);
      md192.destCh =dc;
      if(sr>4){
	if(sr<=9) md192.switchMode=1; //P1-3, FUL I=-1
	if(sr==8) md192.switchMode=2; //MAX I=0
	if(sr==9) sr=8; //FUL->MAX
        if(sr>9)  sr+=8;//space for ch1-ch8
        if(sr>7)  sr+=3;//space for p1-3
      }
      md192.srcRaw =sr-1; //now start with 0
      if(md192.weight<0 && md192.curve){
        md192.weight   = -md192.weight;
        md192.curveNeg = 1;
      }
    }
    
    sz = sizeof(ModelData_r192);
    model171->mdVers = MDVERS192;
  }
  if( sz == sizeof(ModelData_r192) && g_model.mdVers == MDVERS192) {
    printf("converting model data from r192 to r204\n");
    ModelData_r192 *model192 = (ModelData_r192*)&g_model;
    ModelData_r204 *model204 = (ModelData_r204*)&g_model;
    memmove(&model204->trimData,&model192->trimData,sizeof(model192->trimData));
    memset(model204->switchTab,0,sizeof(model204->switchTab));
    model204->trimData[0].tmode=0;
    model204->trimData[1].tmode=0;
    model204->trimData[2].tmode=0;
    model204->trimData[3].tmode=0;
    sz = sizeof(ModelData_r204);
    model204->mdVers = MDVERS204;
  }
  if( sz == sizeof(ModelData_TOP) && g_model.mdVers == MDVERS_TOP) {
    return;
  }

  printf("bad model%d data using default\n",id+1);
  modelDefault(id);

}