• Main Page
  • Data Structures
  • Files

frames.c

Go to the documentation of this file.
00001 
00002 /*
00003  * This file is part of Titan2Reader
00004  *
00005  * Copyright (C) 2006, Sebastien Judenherc <sebastien.judenherc@agecodagis.com>
00006  *
00007  * This program is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
00020  * USA
00021  *
00022  */
00023 
00024 #include <stdlib.h>
00025 #include <stdio.h>
00026 #include <time.h>
00027 #include <ctype.h>
00028 #include <math.h>
00029 #include <errno.h>
00030 #include <unistd.h>
00031 #include <string.h>
00032 #include <sys/types.h>
00033 #include <sys/stat.h>
00034 #include <fcntl.h>
00035 
00036 #include "common.h"
00037 
00039 int streamChange=1;
00040 
00044 char * ClockStateName(int state)
00045 {
00046         static char tmp[25];
00047         switch (state)
00048         {
00049                 case 0:
00050                         return(strcpy(tmp,"free"));
00051                 case 1:
00052                         return(strcpy(tmp,"lock_frequency"));
00053                 case 2:
00054                         return(strcpy(tmp,"lock_phase"));
00055                 case 3:
00056                         return(strcpy(tmp,"lock_common_phase"));
00057         }
00058         // this is 'default:'
00059         sprintf(tmp,"unknown%d\n",state);
00060         return(tmp);
00061 }
00062 
00066 char * ADCName(int id)
00067 {
00068         switch (id)
00069         {
00070                 case CS5323:
00071                         return("CS5323");
00072                 case AD7710:
00073                         return("AD7710");
00074                 case HI7190:
00075                         return("HI7190");
00076                 case CS5321:
00077                         return("CS5321");
00078                 case ADS1251:
00079                         return("ADS1251");
00080         }
00081         // this is the 'default' case:
00082         return("N/A");
00083 }
00084 
00089 char * StrTimeNS(struct Titan2TimeType *t)
00090 {
00091         static char s[128];
00092         struct tm tm;
00093         time_t T;
00094         T=t->usecond>>32;
00095         memcpy(&tm,gmtime(&T),sizeof(struct tm));
00096         strftime(s,127,"%Y.%m.%d-%H.%M.%S",&tm);
00097         return(s);
00098 }
00099 
00104 char * StrTime(struct Titan2TimeType *t)
00105 {
00106         static char s[128];
00107         struct tm tm;
00108         time_t T;
00109         T=t->usecond>>32;
00110         memcpy(&tm,gmtime(&T),sizeof(struct tm));
00111         strftime(s,127,"%Y.%m.%d-%H.%M.%S",&tm);
00112         sprintf(s+19,".%06d",(int)(1.e6*US2S*(double)(t->usecond-((t->usecond>>32)<<32))));
00113         return(s);
00114 }
00115 
00120 char * StrFrame(const unsigned char *frame)
00121 {
00122         static char sf[80];
00123         sprintf(sf,"%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
00124                         0xff&frame[0],0xff&frame[1],0xff&frame[2],0xff&frame[3],
00125                         0xff&frame[4],0xff&frame[5],0xff&frame[6],0xff&frame[7],
00126                         0xff&frame[8],0xff&frame[9],0xff&frame[10],0xff&frame[11]);
00127         return(sf);
00128 }
00129 
00130 char *MediumErrorStr(int s)
00131 {
00132         static char state[255];
00133         if (s==0)
00134         {
00135                 return("NoError");
00136         }
00137         else
00138         {
00139                 strcpy(state,"");
00140         }
00141         if (s&(1<<0)) strcat(state," TimeOut");
00142         if (s&(1<<1)) strcat(state," LinkSCSI");
00143         if (s&(1<<2)) strcat(state," LowBatt");
00144         if (s&(1<<3)) strcat(state," UnexpectedSCSIAnswer");
00145         if (s&(1<<4)) strcat(state," LoadingError");
00146         if (s&(1<<5)) strcat(state," MediumFull");
00147         if (s&(1<<6)) strcat(state," Unknown");
00148         if (s&(1<<7)) strcat(state," NoMedium");
00149         return(state);
00150 }
00151 
00152 char *FlushStateStr(int s)
00153 {
00154         switch (s)
00155         {
00156                 case 0:
00157                         return("NotRunning");
00158                 case 1:
00159                         return("LoadingMedium");
00160                 case 2:
00161                         return("SeekingEnd");
00162                 case 3:
00163                         return("WritingData");
00164                 case 4:
00165                         return("Rewinding");
00166                 case 5:
00167                         return("WritingIndex");
00168                 case 6:
00169                         return("UnloadingMedium");
00170         }
00171         return("Unknown");
00172 }
00173 
00174 static float _abs(float x)
00175 {
00176         return((x>0.)?x:-x);
00177 }
00178 
00180 float InfoSamplingRate(struct HWConfigType *hw,int ch)
00181 {
00182         switch (ch)
00183         {
00184                 case 0:
00185                 case 1:
00186                         return((hw->info20.samplingSet==160)?20.00:31.25)*
00187                                 (float)(1<<hw->info03[ch].srCode);
00188                 case 2:
00189                 case 3:
00190                         return(InfoSamplingRate(hw,ch-2)/
00191                                         (float)(1<<hw->info03[ch].srCode));
00192         }
00193         // this is the 'default' case:
00194         return(-1.0);
00195 }
00196 
00198 float KSta2Time(struct HWConfigType *hw,int ch)
00199 {
00200         double K=-1./(log(1.-((double)hw->info03[ch].sta/(double)(1<<23))));
00201         double F=InfoSamplingRate(hw,ch);
00202         if (fabs(F)>0.001)
00203         {
00204                 return(K/F);
00205         }
00206         else
00207         {
00208                 return(-1.);
00209         }
00210 }
00211 
00213 float KLta2Time(struct HWConfigType *hw,int ch)
00214 {
00215         double K=-1./(log(1.-((double)hw->info03[ch].lta/(double)(1<<23))));
00216         double F=InfoSamplingRate(hw,ch);
00217         if (fabs(F)>0.001)
00218         {
00219                 return(K/F);
00220         }
00221         else
00222         {
00223                 return(-1.);
00224         }
00225 }
00226 
00231 int SelectMatch(char *in, char *stream)
00232 {
00233         int i,j,sign;
00234         PrintDebug("testing '%s' against '%s'\n",in,stream);
00235         if (stream[0]=='!')
00236         {
00237                 j=1;
00238                 sign=-1;
00239         }
00240         else
00241         {
00242                 j=0;
00243                 sign=1;
00244         }
00245         for (i=0; (j<strlen(stream)&&(i<strlen(in))); j++,i++)
00246         {
00247                 if (stream[j]==',')
00248                 {
00249                         break;
00250                 }
00251                 if (stream[j]=='?')
00252                 {
00253                         continue;
00254                 }
00255                 if (in[i]!=stream[j])
00256                 {
00257                         sign=0;
00258                         break;
00259                 }
00260         }
00261         PrintDebug("result is %d\n",sign);
00262         return(sign);
00263 }
00264 
00267 int64_t Stream2Channel(void)
00268 {
00269         int64_t mask=0;
00270         int i;
00271         char *stream;
00272         stream=streamList;
00273         do
00274         {
00275                 for (i=0; i<MAX_OSIRIS_CHANNEL; i++)
00276                 {
00277                         switch (SelectMatch(HWConfig.channelName[i],stream))
00278                         {
00279                                 case 0:
00280                                         break;
00281                                 case 1:
00282                                         mask|=(1LL<<i);
00283                                         break;
00284                                 case -1:
00285                                         mask &= ~(1LL<<i);
00286                                         break;
00287                         }
00288                 }
00289                 // seek the next stream
00290                 do
00291                 {
00292                         stream++;
00293                 } while ((*stream!=',')&&(*stream!=0));
00294                 if (*stream==',')
00295                 {
00296                         stream++;
00297                 }
00298                 // stop if the eand of the stream list is reached
00299         } while (*stream!=0);
00300         PrintDebug("new mask: %#0Lx\n",mask);
00301         return(mask);
00302 }
00303 
00304 void ChangeStreamConfig(void)
00305 {
00306         streamChange=1;
00307 }
00308 
00311 int CheckDiffConfig(void)
00312 {
00313         float delta;
00314         int i;
00315         if (fastSeek)
00316         {
00317                 streamChange=1;
00318                 return(0);
00319         }
00320         // first the changes that trigger an emergency flush:
00321         // fieldIdent (stationname)
00322         // serial number (owner)
00323         // ...
00324         if (oldHWConfig.rebootTime.usecond!=HWConfig.rebootTime.usecond)
00325         {
00326                 streamChange=1;
00327                 LogPrint("StationBoot %d\n",(int)(HWConfig.rebootTime.usecond>>32));
00328                 PrintLog("station reboot: %s\n",StrTimeNS(&(HWConfig.rebootTime)));
00329         }
00330         if (oldHWConfig.resetTime.usecond!=HWConfig.resetTime.usecond)
00331         {
00332                 streamChange=1;
00333                 LogPrint("TimeReset %d\n",(int)(HWConfig.resetTime.usecond>>32));
00334                 PrintLog("station time set: %s\n",StrTimeNS(&(HWConfig.resetTime)));
00335         }
00336         if ((strcmp(oldHWConfig.fieldIdent,HWConfig.fieldIdent))||
00337             (strcmp(oldHWConfig.serialNumber,HWConfig.serialNumber))||
00338             (strcmp(oldHWConfig.softwareRealease,HWConfig.softwareRealease)))
00339         {
00340                 streamChange=1;
00341                 PrintLog("NAME='%s' S/N='%s'\n",HWConfig.fieldIdent,HWConfig.serialNumber);
00342                 LogPrint("StationName %s\n", HWConfig.fieldIdent);
00343                 LogPrint("SerialNumber %s\n", HWConfig.serialNumber);
00344                 LogPrint("SoftwareRelease %s\n", HWConfig.softwareRealease);
00345                 // flush all the tasks and close all the output files
00346                 // only if the old ifnormation were defined
00347                 if ((strcmp(DEFAULT_STATION,oldHWConfig.fieldIdent))&&
00348                                 (strcmp(DEFAULT_SERIAL,oldHWConfig.serialNumber)))
00349                 {
00350                         // if the stationname was forced, then we should ignore the serial number
00351                         if (strlen(manualStationName)==0)
00352                         {
00353                                 PrintLog("digitizer change detected\n");
00354                                 globalStationChange=1;
00355                         }
00356                 }
00357 
00358         }
00359         if ((memcmp(&(HWConfig.digitizer),
00360                                 &(oldHWConfig.digitizer),
00361                                 sizeof(struct DigitizerType)))
00362                 && (HWConfig.digitizer.adcFrequency>0))
00363         {
00364                 streamChange=1;
00365                 LogPrint("Freq0 %d Decim0 %d Len0 %d ADCId %d Len1 %d Delay %.6f\n",
00366                                 HWConfig.digitizer.adcFrequency,
00367                                 HWConfig.digitizer.adcDecimation,
00368                                 HWConfig.digitizer.adcDecimationLength,
00369                                 HWConfig.digitizer.adcId,
00370                                 HWConfig.digitizer.secondDecimationLength,
00371                                 HWConfig.digitizer.adcDelay);
00372         }
00373 
00374         for (i=0; i<MAX_OSIRIS_CHANNEL; i++)
00375         {
00376                 if (
00377                                 (strcmp(HWConfig.channelName[i],oldHWConfig.channelName[i]))||
00378                                 (strcmp(HWConfig.locationName[i],oldHWConfig.locationName[i]))||
00379                                 (HWConfig.srExp[i].npts!=oldHWConfig.srExp[i].npts)||
00380                                 (HWConfig.srObs[i].npts!=oldHWConfig.srObs[i].npts)
00381                                 )
00382                 {
00383                         streamChange=1;
00384                         if (HWConfig.srObs[i].npts==0)
00385                         {
00386                                 continue;
00387                         }
00388                         LogPrint("ChannelName %02d  %s:%s.%s.%s\n",
00389                                         i,
00390                                         HWConfig.networkName,
00391                                         HWConfig.fieldIdent,
00392                                         HWConfig.channelName[i],
00393                                         HWConfig.locationName[i]);
00394                 }
00395         }
00396         for (i=0; i<MAX_OSIRIS_CHANNEL; i++)
00397         {
00398                 if (oldHWConfig.HPFilter[i]!=HWConfig.HPFilter[i])
00399                 {
00400                         streamChange=1;
00401                         LogPrint("HPFilterPeriod%d %d\n",
00402                                         i,HWConfig.HPFilter[i]);
00403                 }
00404                 if (oldHWConfig.srExp[i].npts!=HWConfig.srExp[i].npts)
00405                 {
00406                         streamChange=1;
00407                         if (
00408                                         (HWConfig.srExp[i].npts!=0)&&
00409                                         (HWConfig.srExp[i].div!=0)
00410                                         )
00411                         {
00412                                 PrintLog("%s channel %d %.2fHz\n",
00413                                                 "INFO",
00414                                                 i,
00415                                                 (double)HWConfig.srExp[i].base/
00416                                                 (double)HWConfig.srExp[i].div);
00417                                 LogPrint("FSChannel%d %.6f\n",
00418                                                 i,
00419                                                 (double)HWConfig.srExp[i].base/
00420                                                 (double)HWConfig.srExp[i].div,
00421                                                 i);
00422                                 if (HWConfig.srExp[i].div==0)
00423                                 {
00424                                         PrintError("div=0 !\n");
00425                                 }
00426                                 if (HWConfig.srExp[i].base==0)
00427                                 {
00428                                         PrintError("base=0 !\n");
00429                                 }
00430                         }
00431                 }
00432         }
00433 
00434         if (logInfo)
00435         {
00436                 if (HWConfig.formatVersion<2)
00437                 {
00438                         if (memcmp(&oldHWConfig.info5,&HWConfig.info5,sizeof(struct info5_t)))
00439                         {
00440                                 LogPrint("PreEvent(s) %d PostEvent(s) %d EndDuration(s) %d\n",
00441                                                 HWConfig.info5.preEvent,
00442                                                 HWConfig.info5.postEvent,
00443                                                 HWConfig.info5.endDuration);
00444                                 LogPrint("EndMode %s/LTA0 CyclePolicy %s\n",
00445                                                 (HWConfig.info5.endDurationMode&1)?"LTA":"STA",
00446                                                 (HWConfig.info5.cycles&0)?"cycle":"stop");
00447                                 LogPrint("Gain %d\n",1<<HWConfig.info5.gain);
00448 
00449                         }
00450                         if (memcmp(&oldHWConfig.info15,&HWConfig.info15,sizeof(struct info15_t)))
00451                         {
00452                                 LogPrint("TimeReset %d [%.19s]\n",
00453                                                 HWConfig.info15.time,
00454                                                 time2str((double)HWConfig.info15.time));
00455                                 LogPrint("PulseLength(ms) %d ValidIf %s PPM %d Reboot %s\n",
00456                                                 HWConfig.info15.pulseLength,
00457                                                 (HWConfig.info15.pulseTest)?"longer":"shorter",
00458                                                 HWConfig.info15.PPM,
00459                                                 HWConfig.info15.reboot?"yes":"no");
00460                         }
00461                         for (i=0; i<4; i++)
00462                         {
00463                                 if (memcmp(&(oldHWConfig.info03[i]),&(HWConfig.info03[i]),
00464                                                         sizeof(struct info0_3_t)))
00465                                 {
00466                                         LogPrint("Triplet %d sta %.1f lta %.1f FS %.04f Thr %.1f ON %d OFFSET %d\n",
00467                                                         i,
00468                                                         KSta2Time(&HWConfig,i),
00469                                                         KLta2Time(&HWConfig,i),
00470                                                         InfoSamplingRate(&HWConfig,i),
00471                                                         0.5*(float)(HWConfig.info03[i].threshold),
00472                                                         HWConfig.info03[i].active,
00473                                                         HWConfig.info03[i].offset);
00474                                 }
00475                         }
00476                         if (oldHWConfig.info19.lostFlushMediumError!=HWConfig.info19.lostFlushMediumError)
00477                         {
00478                                 LogPrint("LostFlushMediumError %d\n",HWConfig.info19.lostFlushMediumError);
00479                         }
00480                         if (oldHWConfig.info18.lostFlushLowBatt!=HWConfig.info18.lostFlushLowBatt)
00481                         {
00482                                 LogPrint("LostFlushLowBatt %d\n",HWConfig.info18.lostFlushLowBatt);
00483                         }
00484                         if (oldHWConfig.info19.flashCycles!=HWConfig.info19.flashCycles)
00485                         {
00486                                 LogPrint("FlashCycles %d\n",HWConfig.info19.flashCycles);
00487                         }
00488                         if (oldHWConfig.info19.flushState!=HWConfig.info19.flushState)
00489                         {
00490                                 LogPrint("FlushState %s\n",FlushStateStr(HWConfig.info19.flushState));
00491                         }
00492                         if (oldHWConfig.info19.triggerInProcess!=HWConfig.info19.triggerInProcess)
00493                         {
00494                                 LogPrint("TriggerInProcess %s\n",(HWConfig.info19.triggerInProcess)?"yes":"no");
00495                         }
00496                         if (oldHWConfig.info19.mediumError!=HWConfig.info19.mediumError)
00497                         {
00498                                 LogPrint("MEDIUMERROR %s\n",MediumErrorStr(HWConfig.info19.mediumError));
00499                         }
00500                         if (oldHWConfig.info19.flushRunning!=HWConfig.info19.flushRunning)
00501                         {
00502                                 LogPrint("FlushRunning %d\n",HWConfig.info19.flushRunning);
00503                         }
00504                         if ((oldHWConfig.info18.detections!=HWConfig.info18.detections)&&
00505                                         (HWConfig.info18.detections!=65535))
00506                         {
00507                                 LogPrint("Detections %d\n", HWConfig.info18.detections);
00508                         }
00509                         if (memcmp(&oldHWConfig.info20,&HWConfig.info20,sizeof(struct info20_t)))
00510                         {
00511                                 LogPrint("ADCNumber %d ADCId %d ADCName %s SamplingSet %d\n",
00512                                                 HWConfig.info20.channels,
00513                                                 HWConfig.info20.ADCType,
00514                                                 ADCName(HWConfig.info20.ADCType),
00515                                                 HWConfig.info20.samplingSet);
00516                                 LogPrint("RecordingMode %s RecordingTarget %s ContinuousGPS %s\n",
00517                                                 (HWConfig.info20.recordingMode)?"continuous":"trigger",
00518                                                 (HWConfig.info20.recordingMedium)?"disk":"DAT",
00519                                                 (HWConfig.info20.continuousGPS)?"yes":"no");
00520                                 LogPrint("FlashCapacity(MB) %d StorageCapacity(2+GB) %s\n",
00521                                                 HWConfig.info20.flashSize,
00522                                                 (HWConfig.info20.mediumSize)?"yes":"no");
00523                                 LogPrint("TimeKeeper %s ParallelLink %s AUXChannels %s RadioMode %s\n",
00524                                                 HWConfig.info20.timeKeeper?"yes":"no",
00525                                                 HWConfig.info20.parallelLink?"yes":"no",
00526                                                 HWConfig.info20.auxPresent?"yes":"no",
00527                                                 HWConfig.info20.radioMode?"yes":"no");
00528                         }
00529                 }
00530                 if (oldHWConfig.info19.flashBytes!=HWConfig.info19.flashBytes)
00531                 {
00532                         LogPrint("FlashBytes %d\n",HWConfig.info19.flashBytes);
00533                 }
00534                 if (
00535                                 (HWConfig.tune.clockMode!=oldHWConfig.tune.clockMode)||
00536                                 (HWConfig.tune.clockState!=oldHWConfig.tune.clockState)||
00537                                 (HWConfig.tune.step!=oldHWConfig.tune.step)||
00538                                 (HWConfig.tune.phase!=oldHWConfig.tune.phase)||
00539                                 (HWConfig.tune.drift!=oldHWConfig.tune.drift)
00540                                 )
00541                 {
00542                         LogPrint("ClockMode %s ClockState %s\n",
00543                                         ClockStateName(HWConfig.tune.clockMode),
00544                                         ClockStateName(HWConfig.tune.clockState));
00545                         LogPrint("ClockStep %d Phase(us) %.0f Drift(ppm) %.3f\n",
00546                                         HWConfig.tune.step,
00547                                         HWConfig.tune.phase,
00548                                         HWConfig.tune.drift);
00549                 }
00550 
00551                 if (_abs(oldHWConfig.info18.batteryVoltage-HWConfig.info18.batteryVoltage)>0.05)
00552                 {
00553                         LogPrint("Vbatt %.2f\n",HWConfig.info18.batteryVoltage);
00554                 }
00555                 if (oldHWConfig.info18.mediaBytes!=HWConfig.info18.mediaBytes)
00556                 {
00557                         LogPrint("HardDiskData(MB) %ld\n",
00558                                         HWConfig.info18.mediaBytes);
00559                 }
00560                 delta=0;
00561                 delta+=_abs(oldHWConfig.avgPos.lat-HWConfig.avgPos.lat);
00562                 delta+=_abs(oldHWConfig.avgPos.lon-HWConfig.avgPos.lon);
00563                 delta+=_abs(oldHWConfig.avgPos.elev-HWConfig.avgPos.elev)/500;
00564                 if (delta>0.0001)
00565                 {
00566                         LogPrint("AvgLat %.6f AvgLon %.6f AvgElev %.0f\n",
00567                                         HWConfig.avgPos.lat,
00568                                         HWConfig.avgPos.lon,
00569                                         HWConfig.avgPos.elev);
00570                 }
00571                 delta=0;
00572                 delta+=_abs(oldHWConfig.instantPos.lat-HWConfig.instantPos.lat);
00573                 delta+=_abs(oldHWConfig.instantPos.lon-HWConfig.instantPos.lon);
00574                 delta+=_abs(oldHWConfig.instantPos.elev-HWConfig.instantPos.elev)/500;
00575                 delta+=abs(oldHWConfig.satelliteNumber-HWConfig.satelliteNumber)/10;
00576                 if (delta>0.0001)
00577                 {
00578                         LogPrint("InstLat %.6f InstLon %.6f InstElev %.0f NSat %d\n",
00579                                         HWConfig.instantPos.lat,
00580                                         HWConfig.instantPos.lon,
00581                                         HWConfig.instantPos.elev,
00582                                         HWConfig.satelliteNumber);
00583                 }
00584                 delta=0;
00585                 delta+=_abs(HWConfig.LSB-oldHWConfig.LSB);
00586                 delta+=_abs(HWConfig.impedance-oldHWConfig.impedance);
00587                 delta+=_abs(HWConfig.gain[0]-oldHWConfig.gain[0]);
00588                 delta+=_abs(HWConfig.gain[1]-oldHWConfig.gain[1]);
00589                 delta+=_abs(HWConfig.gain[2]-oldHWConfig.gain[2]);
00590                 delta+=_abs(HWConfig.gain[3]-oldHWConfig.gain[3]);
00591                 if ((delta>1.)&&(HWConfig.LSB>0.0))
00592                 {
00593                         streamChange=1;
00594                         if (HWConfig.gain[1]!=HWConfig.gain[0])
00595                         {
00596                                 LogPrint("LSB(nV) %.1f InputImp(kOhm) %.1f G0 1 G1 %d G2 %d G3 %d\n",
00597                                                 HWConfig.LSB,
00598                                                 HWConfig.impedance/1000.,
00599                                                 HWConfig.gain[1],
00600                                                 HWConfig.gain[2],
00601                                                 HWConfig.gain[3]);
00602                         }
00603                         else
00604                         {
00605                                 LogPrint("LSB(nV) %.1f InputImp(kOhm) %.1f\n",
00606                                                 HWConfig.LSB,
00607                                                 HWConfig.impedance/1000.);
00608                         }
00609                 }
00610 
00611                 if (
00612                                 (
00613                                  (HWConfig.formatVersion!=oldHWConfig.formatVersion)||
00614                                  (HWConfig.formatMajor!=oldHWConfig.formatMajor)||
00615                                  (HWConfig.formatMinor!=oldHWConfig.formatMinor)
00616                                  ) && (HWConfig.formatVersion>=0)
00617                                 )