Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

Subsystems.cpp

Go to the documentation of this file.
00001 /*
00002  * Subsystems.cpp
00003  *
00004  * Part of Fly! Legacy project
00005  *
00006  * Copyright 2003 Chris Wallace
00007  *
00008  * Fly! Legacy is free software; you can redistribute it and/or modify
00009  *   it under the terms of the GNU General Public License as published by
00010  *   the Free Software Foundation; either version 2 of the License, or
00011  *   (at your option) any later version.
00012  *
00013  * Fly! Legacy is distributed in the hope that it will be useful,
00014  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  *   GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  *   along with Fly! Legacy; if not, write to the Free Software
00020  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  */
00023 
00035 #include "../Include/Subsystems.h"
00036 #include "../Include/Utility.h"
00037 #include "../Include/Database.h"
00038 #include "../Include/Ui.h"
00039 #include "../Include/Globals.h"
00040 
00041 using namespace std;
00042 
00043 
00044 //
00045 // CSubsystem
00046 //
00047 
00048 CSubsystem::CSubsystem (void)
00049 {
00050   TypeIs (SUBSYSTEM_BASE);
00051   unId = 0;
00052   timK = 1.0f;
00053   ratK = 1.0f;
00054   indn = 0;
00055   indnTarget = 0;
00056   indnMode = INDN_NONE;
00057   strcpy (fWAV, "");
00058 
00059   uNum = 1;
00060   gNum = 1;
00061   hwId = HW_STATE;
00062 }
00063 
00064 CSubsystem::~CSubsystem (void)
00065 {
00066 }
00067 
00068 int CSubsystem::Read (SStream *stream, Tag tag)
00069 {
00070   int rc = TAG_IGNORED;
00071 
00072   switch (tag) {
00073   case 'unId':
00074     // Unique ID
00075     ReadTag (&unId, stream);
00076     TagToString (unId_string, unId);
00077     rc = TAG_READ;
00078     break;
00079 
00080   case 'timK':
00081     // Exponential time constant
00082     ReadFloat (&timK, stream);
00083     indnMode = INDN_LINEAR;
00084     rc = TAG_READ;
00085     break;
00086 
00087   case 'ratK':
00088     // Linear time constant
00089     ReadFloat (&ratK, stream);
00090     indnMode = INDN_EXPONENTIAL;
00091     rc = TAG_READ;
00092     break;
00093 
00094   case 'indn':
00095     // Initial indication value
00096     ReadFloat (&indn, stream);
00097     rc = TAG_READ;
00098     break;
00099 
00100   case 'fWAV':
00101     // Triggered sound effect filename
00102     ReadString (fWAV, 64, stream);
00103     rc = TAG_READ;
00104     break;
00105 
00106   case 'uNum':
00107     // DEPRECATED = Unit number
00108     ReadUInt (&uNum, stream);
00109     rc = TAG_READ;
00110     break;
00111 
00112   case 'hwId':
00113     // DEPRECATED - Hardware type
00114     {
00115       char s[64];
00116       ReadString (s, 64, stream);
00117       if (stricmp (s, "UNKNOWN") == 0) {
00118         hwId = HW_UNKNOWN;
00119       } else if (stricmp (s, "BUS") == 0) {
00120         hwId = HW_BUS;
00121       } else if (stricmp (s, "SWITCH") == 0) {
00122         hwId = HW_SWITCH;
00123       } else if (stricmp (s, "LIGHT") == 0) {
00124         hwId = HW_LIGHT;
00125       } else if (stricmp (s, "FUSE") == 0) {
00126         hwId = HW_FUSE;
00127       } else if (stricmp (s, "STATE") == 0) {
00128         hwId = HW_STATE;
00129       } else if (stricmp (s, "GAUGE") == 0) {
00130         hwId = HW_GAUGE;
00131       } else if (stricmp (s, "CIRCUIT") == 0) {
00132         hwId = HW_CIRCUIT;
00133       } else if (stricmp (s, "RADIO") == 0) {
00134         hwId = HW_RADIO;
00135       } else if (stricmp (s, "FLAP") == 0) {
00136         hwId = HW_FLAP;
00137       } else if (stricmp (s, "HILIFT") == 0) {
00138         hwId = HW_HILIFT;
00139       } else if (stricmp (s, "GEAR") == 0) {
00140         hwId = HW_GEAR;
00141       } else if (stricmp (s, "BATTERY") == 0) {
00142         hwId = HW_BATTERY;
00143       } else if (stricmp (s, "ALTERNATOR") == 0) {
00144         hwId = HW_ALTERNATOR;
00145       } else if (stricmp (s, "ANNUNCIATOR") == 0) {
00146         hwId = HW_ANNUNCIATOR;
00147       } else if (stricmp (s, "GENERATOR") == 0) {
00148         hwId = HW_GENERATOR;
00149       } else if (stricmp (s, "CONTACTOR") == 0) {
00150         hwId = HW_CONTACTOR;
00151       } else if (stricmp (s, "SOUNDFX") == 0) {
00152         hwId = HW_SOUNDFX;
00153       } else if (stricmp (s, "FLASHER") == 0) {
00154         hwId = HW_FLASHER;
00155       } else if (stricmp (s, "INVERTER") == 0) {
00156         hwId = HW_INVERTER;
00157       } else if (stricmp (s, "UNITLESS") == 0) {
00158         hwId = HW_UNITLESS;
00159       } else if (stricmp (s, "UNBENT") == 0) {
00160         hwId = HW_UNBENT;
00161       } else if (stricmp (s, "SCALE") == 0) {
00162         hwId = HW_SCALE;
00163       } else {
00164         globals->logWarning->Write ("CDependent::Read : Unknown HW type %s", s);
00165       }
00166     }   
00167     rc = TAG_READ;
00168     break;
00169   }
00170 
00171   if (rc != TAG_READ) {
00172     // Tag was not processed by this object, it is unrecognized
00173     char s[16];
00174     TagToString (s, tag);
00175     globals->logWarning->Write ("Subsystem '%s' : Unknown READ tag <%s>", type_string, s);
00176   }
00177 
00178   return rc;
00179 }
00180 
00181 
00182 void CSubsystem::ReadFinished (void)
00183 {
00184 }
00185 
00186 
00187 void CSubsystem::Write (SStream *stream)
00188 {
00189 
00190 }
00191 
00192 void CSubsystem::Prepare (void)
00193 {
00194 
00195 }
00196 
00197 void CSubsystem::TypeIs (Tag t)
00198 {
00199   // Set subsystem type and convert to string (useful when debugging)
00200   type = t;
00201   TagToString (type_string, type);
00202 
00203   // Initialize unique subsystem ID to subsystem type
00204   // This should be overridden with a <unid> tag in the subsystem definition
00205   unId = type;
00206   TagToString (unId_string, unId);
00207 }
00208 
00209 bool CSubsystem::IsType (Tag t)
00210 {
00211   return (type == t);
00212 }
00213 
00214 
00215 void CSubsystem::Alias (Tag tag, Tag alias)
00216 {
00217   aliasList[alias] = tag;
00218 }
00219 
00220 
00221 bool CSubsystem::MsgForMe (SMessage *msg)
00222 {
00223   bool rc = false;
00224 
00225   if (msg) {
00226     bool matchGroup = (msg->group == unId);
00227     bool hwNull     = (msg->user.u.hw == HW_UNKNOWN);
00228     bool hwMatch    = (msg->user.u.hw == (unsigned int) hwId);
00229     bool unitNull   = (msg->user.u.unit == 0);
00230     bool unitMatch  = (msg->user.u.unit == uNum);
00231 
00232     rc = matchGroup && (hwNull || hwMatch) && (unitNull || unitMatch);
00233   }
00234 
00235   return rc;
00236 }
00237 
00238 
00239 //
00240 // CSubsystem supports the following messages:
00241 //
00242 // GETDATA:
00243 //  indn - Indication value (float)
00244 //
00245 // SETDATA:
00246 //  indn - Indication value (float)
00247 //
00248 EMessageResult CSubsystem::ReceiveMessage (SMessage *msg)
00249 {
00250   EMessageResult rc = MSG_IGNORED;
00251 
00252   Tag dtag = msg->user.u.datatag;
00253 
00254   // Check to see if the requested tag is an alias
00255   map<Tag,Tag>::iterator i = aliasList.find(dtag);
00256   if (i != aliasList.end()) {
00257     // Replace aliased datatag with original tag
00258     dtag = i->second;
00259   }
00260 
00261   if (msg) {
00262     // Verify that message is for this object
00263     if (msg->group == unId) {
00264       switch (msg->id) {
00265       case MSG_GETDATA:
00266         switch (dtag) {
00267         case 0:
00268         case 'indn':
00269           msg->dataType = TYPE_REAL;
00270           msg->realData = indn;
00271           msg->result = rc = MSG_PROCESSED;
00272           break;
00273         }
00274         break;
00275 
00276       case MSG_SETDATA:
00277         switch (dtag) {
00278         case 0:
00279         case 'indn':
00280           if (msg->dataType == TYPE_REAL) {
00281             indnTarget = msg->realData;
00282             msg->result = rc = MSG_PROCESSED;
00283           }
00284           break;
00285         }
00286         break;
00287       }
00288     }
00289   }
00290 
00291   return rc;
00292 }
00293 
00294 void CSubsystem::TimeSlice (float dT)
00295 {
00296   // Update actual indication
00297   switch (indnMode) {
00298   case INDN_NONE:
00299     // Actual value tracks target value with no time lag
00300     indn = indnTarget;
00301     break;
00302 
00303   case INDN_LINEAR:
00304     // Use ratK (in seconds) as linear coefficient
00305     indn += (indnTarget - indn) * (dT / ratK);
00306     break;
00307 
00308   case INDN_EXPONENTIAL:
00309     // Use timK (in seconds) as exponential coeffiecient
00310     indn += (indnTarget - indn) * (1.0f - exp(-dT / timK));
00311     break;
00312   }
00313 }
00314 
00315 void CSubsystem::Print (FILE *f)
00316 {
00317   fprintf (f, "CSubsystem:\n");
00318   fprintf (f, "  type=%s\tunId=%s\thw=", type_string, unId_string);
00319   switch (hwId) {
00320   case HW_UNKNOWN:
00321     fprintf (f, "UNKNOWN\n");
00322     break;
00323 
00324   case HW_BUS:
00325     fprintf (f, "BUS\n");
00326     break;
00327 
00328   case HW_SWITCH:
00329     fprintf (f, "SWITCH\n");
00330     break;
00331 
00332   case HW_LIGHT:
00333     fprintf (f, "LIGHT\n");
00334     break;
00335 
00336   case HW_FUSE:
00337     fprintf (f, "FUSE\n");
00338     break;
00339 
00340   case HW_STATE:
00341     fprintf (f, "STATE\n");
00342     break;
00343 
00344   case HW_GAUGE:
00345     fprintf (f, "GAUGE\n");
00346     break;
00347 
00348   case HW_OTHER:
00349     fprintf (f, "OTHER\n");
00350     break;
00351 
00352   case HW_CIRCUIT:
00353     fprintf (f, "CIRCUIT\n");
00354     break;
00355 
00356   case HW_FLAP:
00357     fprintf (f, "FLAP\n");
00358     break;
00359 
00360   case HW_HILIFT:
00361     fprintf (f, "HILIFT\n");
00362     break;
00363 
00364   case HW_GEAR:
00365     fprintf (f, "GEAR\n");
00366     break;
00367 
00368   case HW_BATTERY:
00369     fprintf (f, "BATTERY\n");
00370     break;
00371 
00372   case HW_ALTERNATOR:
00373     fprintf (f, "ALTERNATOR\n");
00374     break;
00375 
00376   case HW_GENERATOR:
00377     fprintf (f, "GENERATOR\n");
00378     break;
00379 
00380   case HW_CONTACTOR:
00381     fprintf (f, "CONTACTOR\n");
00382     break;
00383 
00384   case HW_SOUNDFX:
00385     fprintf (f, "SOUNDFX\n");
00386     break;
00387 
00388   case HW_FLASHER:
00389     fprintf (f, "FLASHER\n");
00390     break;
00391 
00392   case HW_INVERTER:
00393     fprintf (f, "INVERTER\n");
00394     break;
00395 
00396   case HW_UNITLESS:
00397     fprintf (f, "UNITLESS\n");
00398     break;
00399 
00400   case HW_UNBENT:
00401     fprintf (f, "UNBENT\n");
00402     break;
00403 
00404   case HW_SCALE:
00405     fprintf (f, "SCALE\n");
00406     break;
00407 
00408   case HW_RADIO:
00409     fprintf (f, "RADIO\n");
00410     break;
00411 
00412   case HW_ANNUNCIATOR:
00413     fprintf (f, "ANNUNCIATOR\n");
00414     break;
00415   }
00416   fprintf (f, "  unit=%d\tgNum=%d\n", uNum, gNum);
00417   fprintf (f, "  timK = %f\tratK=%f\n", timK, ratK);
00418   fprintf (f, "  indn = %f\tindnTarget=%f\n", indn, indnTarget);
00419 }
00420 
00421 //
00422 // CDependent
00423 //
00424 
00425 CDependent::CDependent (void)
00426 {
00427   // Initialize read datatags
00428   st8t = -1;              // Invalid state
00429   stat = false;
00430   offV = 0;
00431   mode = DEPENDENCY_OR;
00432   volt = 0;
00433   load = 0;
00434   mVlt = 0;
00435   freQ = 0;
00436 
00437   // Initialize real-time electrical states
00438   state = 0;
00439   active = false;
00440   voltage = 0;
00441   current = 0;
00442   frequency = 0;
00443 
00444   // Proxy messaging
00445   memset (&pxy1, 0, sizeof(SMessage));
00446   memset (&pxy0, 0, sizeof(SMessage));
00447   rise = 1.0f;
00448   fall = 0.0f;
00449   memset (&mPol, 0, sizeof(SMessage));
00450   mAll = false;
00451   poll = POLL_NEVER;
00452 }
00453 
00454 CDependent::~CDependent (void)
00455 {
00456 }
00457 
00458 int CDependent::Read (SStream *stream, Tag tag)
00459 {
00460   int rc = TAG_IGNORED;
00461   SMessage msg;
00462   memset (&msg, 0, sizeof(SMessage));
00463 
00464   switch (tag) {
00465   case 'volt':
00466     // Circuit voltage
00467     ReadFloat (&volt, stream);
00468     rc = TAG_READ;
00469     break;
00470 
00471   case 'mVlt':
00472     // Circuit maximum voltage
00473     ReadFloat (&mVlt, stream);
00474     rc = TAG_READ;
00475     break;
00476 
00477   case 'load':
00478     // Circuit load
00479     ReadFloat (&load, stream);
00480     rc = TAG_READ;
00481     break;
00482 
00483   case 'freQ':
00484     // AC current frequency
00485     ReadFloat (&freQ, stream);
00486     rc = TAG_READ;
00487     break;
00488 
00489   case 'eBus':
00490     // Logical connection to dependency with HW type BUS
00491     {
00492       ReadTag ((unsigned long*)(&msg.group), stream);
00493       msg.id = MSG_GETDATA;
00494       msg.user.u.datatag = 'st8t';
00495       msg.user.u.hw = HW_BUS;
00496       dpnd.push_back (msg);
00497     }
00498     rc = TAG_READ;
00499     break;
00500 
00501   case 'fuse':
00502     // Logical connection to dependency with HW type FUSE
00503     {
00504       ReadTag ((unsigned long*)(&msg.group), stream);
00505       msg.id = MSG_GETDATA;
00506       msg.user.u.datatag = 'st8t';
00507       msg.user.u.hw = HW_FUSE;
00508       dpnd.push_back (msg);
00509     }
00510     rc = TAG_READ;
00511     break;
00512 
00513   case 'swch':
00514     // Logical connection to dependency with HW type SWITCH
00515     {
00516       ReadTag ((unsigned long*)(&msg.group), stream);
00517       msg.id = MSG_GETDATA;
00518       msg.user.u.datatag = 'st8t';
00519       msg.user.u.hw = HW_SWITCH;
00520       dpnd.push_back (msg);
00521     }
00522     rc = TAG_READ;
00523     break;
00524 
00525   case 'lite':
00526     // Logical connection to dependency with HW type LIGHT
00527     {
00528       ReadTag ((unsigned long*)(&msg.group), stream);
00529       msg.id = MSG_GETDATA;
00530       msg.user.u.datatag = 'st8t';
00531       msg.user.u.hw = HW_LIGHT;
00532       dpnd.push_back (msg);
00533     }
00534     rc = TAG_READ;
00535     break;
00536 
00537   case 'annr':
00538     // Logical connection to dependency with HW type ANNOUNCER
00539     {
00540       ReadTag ((unsigned long*)(&msg.group), stream);
00541       msg.id = MSG_GETDATA;
00542       msg.user.u.datatag = 'st8t';
00543       msg.user.u.hw = HW_ANNUNCIATOR;
00544       dpnd.push_back (msg);
00545     }
00546     rc = TAG_READ;
00547     break;
00548 
00549   case 'bool':
00550     // Logical connection to dependency with HW type STATE
00551     {
00552       ReadTag ((unsigned long*)(&msg.group), stream);
00553       msg.id = MSG_GETDATA;
00554       msg.user.u.datatag = 'st8t';
00555       msg.user.u.hw = HW_STATE;
00556       dpnd.push_back (msg);
00557     }
00558     rc = TAG_READ;
00559     break;
00560 
00561   case 'cntr':
00562     // Logical connection to dependency with HW type CONTACTOR
00563     {
00564       ReadTag ((unsigned long*)(&msg.group), stream);
00565       msg.id = MSG_GETDATA;
00566       msg.user.u.datatag = 'st8t';
00567       msg.user.u.hw = HW_CONTACTOR;
00568       dpnd.push_back (msg);
00569     }
00570     rc = TAG_READ;
00571     break;
00572 
00573   case 'flsh':
00574     // Logical connection to dependency with HW type FLASHER
00575     {
00576       ReadTag ((unsigned long*)(&msg.group), stream);
00577       msg.id = MSG_GETDATA;
00578       msg.user.u.datatag = 'st8t';
00579       msg.user.u.hw = HW_FLASHER;
00580       dpnd.push_back (msg);
00581     }
00582     rc = TAG_READ;
00583     break;
00584 
00585   case 'batt':
00586     // Logical connection to dependency with HW type BATTERY
00587     rc = TAG_READ;
00588     {
00589       ReadTag ((unsigned long*)(&msg.group), stream);
00590       msg.id = MSG_GETDATA;
00591       msg.user.u.datatag = 'st8t';
00592       msg.user.u.hw = HW_BATTERY;
00593       dpnd.push_back (msg);
00594     }
00595     break;
00596 
00597   case 'altr':
00598     // Logical connection to dependency with HW type ALTERNATOR
00599     {
00600       ReadTag ((unsigned long*)(&msg.group), stream);
00601       msg.id = MSG_GETDATA;
00602       msg.user.u.datatag = 'st8t';
00603       msg.user.u.hw = HW_ALTERNATOR;
00604       dpnd.push_back (msg);
00605     }
00606     rc = TAG_READ;
00607     break;
00608 
00609   case 'nvrt':
00610     // Logical connection to dependency with HW type INVERTER
00611     {
00612       ReadTag ((unsigned long*)(&msg.group), stream);
00613       msg.id = MSG_GETDATA;
00614       msg.user.u.datatag = 'st8t';
00615       msg.user.u.hw = HW_INVERTER;
00616       dpnd.push_back (msg);
00617     }
00618     rc = TAG_READ;
00619     break;
00620 
00621   case 'st8t':
00622     // Default state
00623     ReadInt (&st8t, stream);
00624     rc = TAG_READ;
00625     break;
00626 
00627   case 'stat':
00628     // Default activity state is ON
00629     stat = true;
00630     rc = TAG_READ;
00631     break;
00632 
00633   case '_AND':
00634     // Combine dependencies in AND function
00635     mode = DEPENDENCY_AND;
00636     rc = TAG_READ;
00637     break;
00638 
00639   case '_OR_':
00640     // Combine dependencies in an OR function
00641     mode = DEPENDENCY_OR;
00642     rc = TAG_READ;
00643     break;
00644 
00645   case 'pxy1':
00646     // Rising edge proxy message
00647     ReadMessage (&pxy1, stream);
00648     rc = TAG_READ;
00649     break;
00650 
00651   case 'rise':
00652     // Rising edge proxy value
00653     ReadFloat (&rise, stream);
00654     rc = TAG_READ;
00655     break;
00656 
00657   case 'pxy0':
00658     // Falling edge proxy message
00659     ReadMessage (&pxy0, stream);
00660     rc = TAG_READ;
00661     break;
00662 
00663   case 'fall':
00664     // Falling edge proxy value
00665     ReadFloat (&fall, stream);
00666     rc = TAG_READ;
00667     break;
00668 
00669   case 'mPol':
00670     // Polling message
00671     ReadMessage (&mPol, stream);
00672     rc = TAG_READ;
00673     break;
00674 
00675   case 'mAll':
00676     // Create all three proxy messages
00677     mAll = true;
00678     rc = TAG_READ;
00679     break;
00680 
00681   case 'tPol':
00682     // Polling method
00683     {
00684       char s[64];
00685       ReadString (s, 64, stream);
00686       globals->logWarning->Write ("CDependent::Read : Unknown polling method %s", s);
00687     }
00688     rc = TAG_READ;
00689     break;
00690 
00691   case 'offV':
00692     // Indication value when inactive
00693     ReadFloat (&offV, stream);
00694     rc = TAG_READ;
00695     break;
00696   }
00697 
00698   if (rc != TAG_READ) {
00699     // See if the tag can be processed by the parent class type
00700     rc = CSubsystem::Read (stream, tag);
00701   }
00702 
00703   return rc;
00704 }
00705 
00706 
00707 void CDependent::ReadFinished (void)
00708 {
00709   CSubsystem::ReadFinished ();
00710 
00711   // Determine initial state controller state for this dependent.
00712   // For most dependents, the state controller defaults to always ON such
00713   //   that the activity state is determined solely by dependencies.  The
00714   //   exception is if the hardware type is SWITCH.  These default to off,
00715   //   under the assumption that the associated gauge will set the correct
00716   //   state through messaging.
00717   int init_state = 1;
00718   if (hwId == HW_SWITCH) {
00719     init_state = 0;
00720   }
00721 
00722   // Override initial state if the READ tag was specified
00723   if (st8t != -1) {
00724     init_state = st8t;
00725   }
00726 
00727   // Assign initial state
00728   state = init_state;
00729 }
00730 
00731 
00732 void CDependent::Write (SStream *stream)
00733 {
00734 }
00735 
00736 
00737 int CDependent::NumDependencies (void)
00738 {
00739   return dpnd.size();
00740 }
00741 
00742 //
00743 // CDependent supports the following messages:
00744 //
00745 // GETDATA:
00746 //  stat - State (int)
00747 //
00748 // SETDATA:
00749 //  stat - State (int)
00750 //
00751 EMessageResult CDependent::ReceiveMessage (SMessage *msg)
00752 {
00753   EMessageResult rc = MSG_IGNORED;
00754 
00755   if (MsgForMe (msg)) {
00756     switch (msg->id) {
00757     case MSG_GETDATA:
00758       switch (msg->user.u.datatag) {
00759       case 0:
00760       case 'st8t':
00761       case 'stat':
00762         msg->dataType = TYPE_INT;
00763         msg->intData = state;
00764         msg->result = rc = MSG_PROCESSED;
00765         break;
00766 
00767       case 'actv':
00768         msg->dataType = TYPE_INT;
00769         msg->intData = (int)active;
00770         msg->result = rc = MSG_PROCESSED;
00771         break;
00772       }
00773       break;
00774 
00775     case MSG_SETDATA:
00776       switch (msg->user.u.datatag) {
00777       case 0:
00778       case 'st8t':
00779       case 'stat':
00780         if (msg->dataType == TYPE_INT) {
00781           state = msg->intData;
00782           msg->result = rc = MSG_PROCESSED;
00783         }
00784         break;
00785       }
00786       break;
00787     }
00788 
00789     if (rc == MSG_IGNORED) {
00790       // See if the message can be processed by the parent class
00791       rc = CSubsystem::ReceiveMessage (msg);
00792     }
00793   }
00794 
00795   return rc;
00796 }
00797 
00798 void CDependent::SetEvaluated (EEvalState eval)
00799 {
00800   evaluated = eval;
00801 }
00802 
00803 void CDependent::TimeSlice (float dT)
00804 {
00805   /*
00806    * First check our state controller, if the state is off (zero) then there is
00807    *   no need to check dependencies
00808    */
00809   active = (state != 0);
00810 
00811   // Return immediately if the subsytem state controller indicates it is off, or
00812   //  if there are no dependencies to check
00813   if (!active || (NumDependencies() == 0)) return;
00814 
00815   /*
00816    *  Before polling dependencies, ensure that they have all been updated
00817    *    for this timeslice.
00818    */
00819   switch (evaluated) {
00820   case EVAL_UNKNOWN:
00821     // This is the first call to TimeSlice for this dependent subsystem
00822     {
00823       // Set our evaluation status to in-progress prior to timeslicing our
00824       //   dependencies.  If our own method gets called again then this
00825       //   will indicate a dependency loop
00826       evaluated = EVAL_INPROGRESS;
00827 
00828       vector<SMessage>::iterator i;
00829       for (i=dpnd.begin(); i!=dpnd.end(); i++) {
00830         if (i->receiver == 0) {
00835           SendMessage (&(*i));
00836           if (i->receiver != 0) {
00837             // Receiver is valid
00838             CDependent *d = (CDependent *)(i->receiver);
00839             d->TimeSlice (dT);
00840           }
00841         }
00842       }
00843 
00844       // All dependents have been timesliced, set our state to complete
00845       evaluated = EVAL_COMPLETE;
00846     }
00847     break;
00848 
00849   case EVAL_INPROGRESS:
00850     // This indicates a dependency loop...I would have considered this a fatal
00851     //   error, but there are default aircraft (e.g. Flyhawk) with dependency
00852     //   loops.  For now, just return and allow the calls to unwind back to
00853     //   the dependency.
00854     return;
00855 //    gtfo ("CDependent : Dependency loop, type='%4s' unId='%4s'", type_string, unId_string);
00856     break;
00857 
00858   case EVAL_COMPLETE:
00859     // This dependency has already been completely evaluated, return to avoid
00860     //   multiple timeslicing
00861     return;
00862     break;
00863   }
00864 
00865   /*
00866    * Get the aggregated activity state from all dependencies
00867    */
00868   // Initialize activity
00869   active = false;
00870   switch (mode) {
00871   case DEPENDENCY_AND:
00872     // Default state is on; if any dependencies are off then state will be off
00873     active = true;
00874     break;
00875 
00876   case DEPENDENCY_OR:
00877     // Default is off; if any dependencies are on then state will be on
00878     active = false;
00879     break;
00880   }
00881 
00882   // Update new state based on dependencies
00883   vector<SMessage>::iterator i;
00884   for (i=dpnd.begin(); i!=dpnd.end(); i++) {
00885     i->user.u.datatag = 'actv';
00886     bool pollActive = true;
00887     if (SendMessage (&(*i)) == MSG_PROCESSED) {
00888       // Message was processed
00889       pollActive = (i->intData != 0);
00890     }
00891 
00892     // Update new activity state
00893     switch (mode) {
00894     case DEPENDENCY_AND:
00895       active &= pollActive;
00896       break;
00897 
00898     case DEPENDENCY_OR:
00899       active |= pollActive;
00900       break;
00901     }
00902   }
00903 
00904   // Update electrical parameters
00905   if (active) {
00906     // Voltage is highest voltage of all dependents, clamped to maximum mVlt
00907     float v = volt;
00909     if (v > mVlt) v = mVlt;
00910     voltage = v;
00911 
00912     // Current is sum of current from all dependents
00913     current = load;
00914 
00915     // Frequency is highest frequency of all dependents
00916     frequency = freQ;
00917   } else {
00918     // Dependent is inactive
00919     voltage = offV;
00920     current = 0;
00921     frequency = 0;
00922   }
00923 
00924   // If state has changed, send any proxy messages
00925 
00926   // Call parent class timeslice method
00927   CSubsystem::TimeSlice (dT);
00928 }
00929 
00930 void CDependent::Print (FILE *f)
00931 {
00932   CSubsystem::Print (f);
00933 
00934   fprintf (f, "CDependent:\n");
00935   fprintf (f, "  Read tags:\n");
00936   fprintf (f, "    st8t=%d\tstat=%s\n", st8t, (stat ? "true" : "false"));
00937   fprintf (f, "    volt=%f\tload=%f\tfreq=%f\n", volt, load, freQ);
00938   fprintf (f, "    offV=%f\tmVlt=%f\n", offV, mVlt);
00939   fprintf (f, "  Realtime:\n");
00940   fprintf (f, "    volt=%f\tload=%f\tfreq=%f\n", voltage, current, frequency);
00941   fprintf (f, "    active=%s\tstate=%d\n", (active ? "true" : "false"), state);
00942   fprintf (f, "  Dependencies (%d):\n", dpnd.size());
00946 }
00947 
00948 
00949 //
00950 // CAnnouncement
00951 //
00952 
00953 CAnnouncement::CAnnouncement (void)
00954 {
00955   type = SUBSYSTEM_ANNOUNCEMENT;
00956   TagToString (type_string, type);
00957 }
00958 
00959 
00960 //
00961 // CGenericMonitor
00962 //
00963 
00964 CGenericMonitor::CGenericMonitor (void)
00965 {
00966   type = SUBSYSTEM_GENERIC_MONITOR;
00967   TagToString (type_string, type);
00968 
00969   memset (&mVal, 0, sizeof(SMessage));
00970   mode = MONITOR_LT;
00971   comp = 0;
00972 }
00973 
00974 
00975 int CGenericMonitor::Read (SStream *stream, Tag tag)
00976 {
00977   int rc = TAG_IGNORED;
00978 
00979   switch (tag) {
00980   case 'mVal':
00981     // Value message
00982     ReadMessage (&mVal, stream);
00983     rc = TAG_READ;
00984     break;
00985 
00986   case '.LT.':
00987     // Monitor for less than the comparison value
00988     mode = MONITOR_LT;
00989     rc = TAG_READ;
00990     break;
00991 
00992   case '.GT.':
00993     // Monitor for greater than the comparison value
00994     mode = MONITOR_GT;
00995     rc = TAG_READ;
00996     break;
00997 
00998   case '.GE.':
00999     // Monitor for greater than or equal to the comparison value
01000     mode = MONITOR_GE;
01001     rc = TAG_READ;
01002     break;
01003 
01004   case '.LE.':
01005     // Monitor for less than or equal to the comparison value
01006     mode = MONITOR_LE;
01007     rc = TAG_READ;
01008     break;
01009 
01010   case 'comp':
01011     // Comparison value
01012     ReadFloat (&comp, stream);
01013     rc = TAG_READ;
01014     break;
01015   }
01016 
01017   if (rc != TAG_READ) {
01018     // See if the tag can be processed by the parent class type
01019     rc = CDependent::Read (stream, tag);
01020   }
01021 
01022   if (rc != TAG_READ) {
01023     // Tag could not be processed
01024     char s[16];
01025     TagToString (s, tag);
01026     globals->logWarning->Write ("CGenericMonitor::Read : Unrecognized tag <%s>", s);
01027   }
01028 
01029   return rc;
01030 }
01031 
01032 
01033 //
01034 // CGenericMonitor messages:
01035 //
01036 // GETDATA:
01037 //  comp - Comparison value       REAL
01038 //  mode - Comparison mode        INT
01039 //  mVal - Poll message for comparison  VOID (SMessage*)
01040 //
01041 // SETDATA:
01042 //  comp - Comparison value
01043 //
01044 EMessageResult CGenericMonitor::ReceiveMessage (SMessage *msg)
01045 {
01046   EMessageResult rc = MSG_IGNORED;
01047 
01048   if (MsgForMe (msg)) {
01049     switch (msg->id) {
01050     case MSG_GETDATA:
01051       switch (msg->user.u.datatag) {
01052       case 'comp':
01053         msg->dataType = TYPE_REAL;
01054         msg->realData = comp;
01055         msg->result = rc = MSG_PROCESSED;
01056         break;
01057       case 'mode':
01058         msg->dataType = TYPE_INT;
01059         msg->intData = mode;
01060         msg->result = rc = MSG_PROCESSED;
01061         break;
01062       case 'mVal':
01063         msg->dataType = TYPE_VOID;
01064         msg->voidData = (void*)(&mVal);
01065         msg->result = rc = MSG_PROCESSED;
01066         break;
01067       }
01068       break;
01069 
01070     case MSG_SETDATA:
01071       switch (msg->user.u.datatag) {
01072       case 'comp':
01073         if (msg->dataType == TYPE_REAL) {
01074           comp = msg->realData;
01075           msg->result = rc = MSG_PROCESSED;
01076         }
01077         break;
01078       }
01079       break;
01080 
01081     }
01082 
01083     if (rc == MSG_IGNORED) {
01084       // See if the message can be processed by the parent class
01085       rc = CDependent::ReceiveMessage (msg);
01086     }
01087   }
01088 
01089   return rc;
01090 }
01091 
01092 
01093 void CGenericMonitor::TimeSlice (float dT)
01094 {
01095   // Initialized state to 'off' in case poll message is not processed
01096   stat = false;
01097 
01098   // Get value for comparison
01099   float poll = 0.0f;
01100   mVal.id = MSG_GETDATA;
01101   SendMessage (&mVal);
01102   if (mVal.result == MSG_PROCESSED) {
01103     // Poll message was successfully processed
01104     switch (mVal.dataType) {
01105     case TYPE_INT:
01106       poll = (float)mVal.intData;
01107       break;
01108     case TYPE_REAL:
01109       poll = mVal.realData;
01110       break;
01111     default:
01112       // Invalid poll data type
01113       gtfo ("CGenericMonitor : Invalid data type from polled subsystem : %d",
01114         mVal.dataType);
01115     }
01116 
01117     // Set state based on comparison
01118     switch (mode) {
01119     case MONITOR_LT:
01120       stat = (poll < comp);
01121       break;
01122 
01123     case MONITOR_GT:
01124       stat = (poll > comp);
01125       break;
01126 
01127     case MONITOR_LE:
01128       stat = (poll <= comp);
01129       break;
01130 
01131     case MONITOR_GE:
01132       stat = (poll >= comp);
01133       break;
01134     }
01135   }
01136 }
01137 
01138 
01139 //
01140 // CGenericIndicator
01141 //
01142 
01143 CGenericIndicator::CGenericIndicator (void)
01144 {
01145   type = SUBSYSTEM_GENERIC_INDICATOR;
01146   TagToString (type_string, type);
01147 
01148   memset (&mVal, 0, sizeof(SMessage));
01149   alia = 0;
01150 }
01151 
01152 
01153 int CGenericIndicator::Read (SStream *stream, Tag tag)
01154 {
01155   int rc = TAG_IGNORED;
01156 
01157   switch (tag) {
01158   case 'mVal':
01159     // Value message
01160     ReadMessage (&mVal, stream);
01161     rc = TAG_READ;
01162     break;
01163 
01164   case 'alia':
01165     // Alias value datatag
01166     ReadTag (&alia, stream);
01167     rc = TAG_READ;
01168     break;
01169   }
01170 
01171   if (rc != TAG_READ) {
01172     // See if the tag can be processed by the parent class type
01173     rc = CDependent::Read (stream, tag);
01174   }
01175 
01176   if (rc != TAG_READ) {
01177     // Tag could not be processed
01178     char s[16];
01179     TagToString (s, tag);
01180     globals->logWarning->Write ("CGenericIndicator::Read : Unrecognized tag <%s>", s);
01181   }
01182 
01183   return rc;
01184 }
01185 
01186 
01187 void CGenericIndicator::ReadFinished (void)
01188 {
01189   // Fill in common fields of monitor message
01190   mVal.id = MSG_GETDATA;
01191 
01192   CDependent::ReadFinished ();
01193 }
01194 
01195 
01196 EMessageResult CGenericIndicator::ReceiveMessage (SMessage *msg)
01197 {
01198   EMessageResult rc = MSG_IGNORED;
01199 
01200   if (MsgForMe (msg)) {
01201     switch (msg->id) {
01202     case MSG_GETDATA:
01203       // Get indication value from monitored subsystem
01204       SendMessage (&mVal);
01205       switch (mVal.dataType) {
01206       case TYPE_INT:
01207         msg->dataType = TYPE_INT;
01208         msg->intData = mVal.intData;
01209         rc = MSG_PROCESSED;
01210         break;
01211       case TYPE_REAL:
01212         msg->dataType = TYPE_REAL;
01213         msg->realData = mVal.realData;
01214         rc = MSG_PROCESSED;
01215         break;
01216       default:
01217         // Invalid message data type
01218         gtfo ("CGenericIndicator : Invalid data type from monitored subsystem : %d", msg->dataType);
01219       }
01220     }
01221 
01222     if (rc == MSG_IGNORED) {
01223       // See if the message can be processed by the parent class
01224       rc = CDependent::ReceiveMessage (msg);
01225     }
01226   }
01227 
01228   return rc;
01229 }
01230 
01231 
01232 //
01233 // CHistory
01234 //
01235 
01236 CHistory::CHistory (void)
01237 {
01238   TypeIs (SUBSYSTEM_HISTORY);
01239 }
01240 
01241 
01242 //
01243 // CPneumaticPump
01244 //
01245 CPneumaticPump::CPneumaticPump (void)
01246 {
01247   TypeIs (SUBSYSTEM_PNEUMATIC_PUMP);
01248 
01249   suct = 0.0;
01250 };
01251 
01252 
01253 int CPneumaticPump::Read (SStream *stream, Tag tag)
01254 {
01255   int rc = TAG_IGNORED;
01256 
01257   switch (tag) {
01258   case 'suct':
01259     // Suction value
01260     ReadFloat (&suct, stream);
01261     rc = TAG_READ;
01262     break;
01263   }
01264 
01265   if (rc != TAG_READ) {
01266     // See if the tag can be processed by the parent class type
01267     rc = CDependent::Read (stream, tag);
01268   }
01269 
01270   if (rc != TAG_READ) {
01271     // Tag could not be processed
01272     char s[16];
01273     TagToString (s, tag);
01274     globals->logWarning->Write ("CPneumaticPump::Read : Unrecognized tag <%s>", s);
01275   }
01276 
01277   return rc;
01278 }
01279 
01280 
01281 EMessageResult CPneumaticPump::ReceiveMessage (SMessage *msg)
01282 {
01283   EMessageResult rc = MSG_IGNORED;
01284 
01285   if (MsgForMe (msg)) {
01286     switch (msg->id) {
01287     case MSG_GETDATA:
01288       switch (msg->user.u.datatag) {
01289       case 'inop':
01290         msg->dataType = TYPE_INT;
01291         msg->intData = (stat == 0);
01292         msg->result = rc = MSG_PROCESSED;
01293         break;
01294       }
01295     }
01296 
01297     if (rc == MSG_IGNORED) {
01298       // See if the message can be processed by the parent class
01299       rc = CDependent::ReceiveMessage (msg);
01300     }
01301   }
01302 
01303   return rc;
01304 }
01305 
01306 
01307 //
01308 // CEmergencyLocator
01309 //
01310 CEmergencyLocator::CEmergencyLocator (void)
01311 {
01312   TypeIs (SUBSYSTEM_EMERGENCY_LOCATOR);
01313 
01314   gLim = 1.0;
01315 }
01316 
01317 int CEmergencyLocator::Read (SStream *stream, Tag tag)
01318 {
01319   int rc = TAG_IGNORED;
01320 
01321   switch (tag) {
01322   case 'gLim':
01323     // G-load activation
01324     ReadFloat (&gLim, stream);
01325     rc = TAG_READ;
01326     break;
01327   }
01328 
01329   if (rc != TAG_READ) {
01330     // See if the tag can be processed by the parent class type
01331     rc = CDependent::Read (stream, tag);
01332   }
01333 
01334   if (rc != TAG_READ) {
01335     // Tag could not be processed
01336     char s[16];
01337     TagToString (s, tag);
01338     globals->logWarning->Write ("CEmergencyLocator::Read : Unrecognized tag <%s>", s);
01339   }
01340 
01341   return rc;
01342 }
01343 
01344 
01345 //
01346 // CExteriorLight
01347 //
01348 CExteriorLight::CExteriorLight (void)
01349 {
01350   TypeIs (SUBSYSTEM_EXTERIOR_LIGHT);
01351 
01352   LMid = 0;
01353 }
01354 
01355 
01356 int CExteriorLight::Read (SStream *stream, Tag tag)
01357 {
01358   int rc = TAG_IGNORED;
01359 
01360   switch (tag) {
01361   case 'LMid':
01362     // Light model ID (part name in external model that displays this light)
01363     ReadTag (&LMid, stream);
01364     rc = TAG_READ;
01365     break;
01366   }
01367 
01368   if (rc != TAG_READ) {
01369     // See if the tag can be processed by the parent class type
01370     rc = CDependent::Read (stream, tag);
01371   }
01372 
01373   if (rc != TAG_READ) {
01374     // Tag could not be processed
01375     char s[16];
01376     TagToString (s, tag);
01377     globals->logWarning->Write ("CExteriorLight::Read : Unrecognized tag <%s>", s);
01378   }
01379 
01380   return rc;
01381 }
01382 
01383 
01384 //
01385 // CPitotStaticSwitch
01386 //
01387 CPitotStaticSwitch::CPitotStaticSwitch (void)
01388 {
01389   TypeIs (SUBSYSTEM_PITOT_STATIC_SWITCH);
01390 
01391   nSystems = 0;
01392   system = NULL;
01393 }
01394 
01395 CPitotStaticSwitch::~CPitotStaticSwitch (void)
01396 {
01397   delete[] system;
01398 }
01399 
01400 int CPitotStaticSwitch::Read (SStream *stream, Tag tag)
01401 {
01402   int rc = TAG_IGNORED;
01403 
01404   switch (tag) {
01405   case 'aray':
01406     {
01407       // Array of systems
01408       ReadInt (&nSystems, stream);
01409       system = new int[nSystems];
01410       for (int i=0; i<nSystems; i++) {
01411         ReadInt (&system[i], stream);
01412       }
01413     }
01414     rc = TAG_READ;
01415     break;
01416   }
01417 
01418   if (rc != TAG_READ) {
01419     // See if the tag can be processed by the parent class type
01420     rc = CDependent::Read (stream, tag);
01421   }
01422 
01423   if (rc != TAG_READ) {
01424     // Tag could not be processed
01425     char s[16];
01426     TagToString (s, tag);
01427     globals->logWarning->Write ("CPitotStaticSwitch::Read : Unrecognized tag <%s>", s);
01428   }
01429 
01430   return rc;
01431 }
01432 
01433 
01434 //
01435 // CPitotHeatSwitch
01436 //
01437 CPitotHeatSwitch::CPitotHeatSwitch (void)
01438 {
01439   TypeIs (SUBSYSTEM_PITOT_HEAT_SWITCH);
01440 }
01441 
01442 
01443 //
01444 // CStaticSourceSwitch
01445 //
01446 CStaticSourceSwitch::CStaticSourceSwitch (void)
01447 {
01448   TypeIs (SUBSYSTEM_STATIC_SOURCE_SWITCH);
01449 
01450   // Special case if the unique ID is not specified
01451   unId = SUBSYSTEM_STATIC_SOURCE_SWITCH;
01452   TagToString (unId_string, unId);
01453 
01454   // Default hardware type for this subsystem is SWITCH
01455   hwId = HW_SWITCH;
01456 }
01457 
01458 
01459 //
01460 // CAnnunciatorLight
01461 //
01462 CAnnunciatorLight::CAnnunciatorLight (void)
01463 {
01464   TypeIs (SUBSYSTEM_ANNUNCIATOR_LIGHT);
01465 
01466   blnk = 0;
01467   blpp = 0;
01468 }
01469 
01470 int CAnnunciatorLight::Read (SStream *stream, Tag tag)
01471 {
01472   int rc = TAG_IGNORED;
01473 
01474   switch (tag) {
01475   case 'blnk':
01476     // Blink period (sec);
01477     ReadFloat (&blnk, stream);
01478     rc = TAG_READ;
01479     break;
01480 
01481   case 'blpp':
01482     // Blink period
01483     ReadFloat (&blnk, stream);
01484     rc = TAG_READ;
01485     break;
01486   }
01487 
01488   if (rc != TAG_READ) {
01489     // See if the tag can be processed by the parent class type
01490     rc = CDependent::Read (stream, tag);
01491   }
01492 
01493   if (rc != TAG_READ) {
01494     // Tag could not be processed
01495     char s[16];
01496     TagToString (s, tag);
01497     globals->logWarning->Write ("CAnnunciatorLight::Read : Unrecognized tag <%s>", s);
01498   }
01499 
01500   return rc;
01501 }
01502 
01503 
01504 //
01505 // CStallWarning
01506 //
01507 CStallWarning::CStallWarning (void)
01508 {
01509   TypeIs (SUBSYSTEM_STALL_WARNING);
01510 
01511   strcpy (wing, "");
01512 }
01513 
01514 
01515 int CStallWarning::Read (SStream *stream, Tag tag)
01516 {
01517   int rc = TAG_IGNORED;
01518 
01519   switch (tag) {
01520   case 'wing':
01521     // Wing section name
01522     ReadString (wing, 64, stream);
01523     rc = TAG_READ;
01524     break;
01525   }
01526 
01527   if (rc != TAG_READ) {
01528     // See if the tag can be processed by the parent class type
01529     rc = CDependent::Read (stream, tag);
01530   }
01531 
01532   if (rc != TAG_READ) {
01533     // Tag could not be processed
01534     char s[16];
01535     TagToString (s, tag);
01536     globals->logWarning->Write ("CAnnunciatorLight::Read : Unrecognized tag <%s>", s);
01537   }
01538 
01539   return rc;
01540 }
01541 
01542 
01543 //
01544 // CLightSettingState
01545 //
01546 CLightSettingState::CLightSettingState (void)
01547 {
01548   TypeIs (SUBSYSTEM_LIGHT_SETTING_STATE);
01549 
01550   levl = 1.0f;
01551 }
01552 
01553 
01554 int CLightSettingState::Read (SStream *stream, Tag tag)
01555 {
01556   int rc = TAG_IGNORED;
01557 
01558   switch (tag) {
01559   case 'levl':
01560     // Default light level
01561     ReadFloat (&levl, stream);
01562     rc = TAG_READ;
01563     break;
01564   }
01565 
01566   if (rc != TAG_READ) {
01567     // See if the tag can be processed by the parent class type
01568     rc = CDependent::Read (stream, tag);
01569   }
01570 
01571   if (rc != TAG_READ) {
01572     // Tag could not be processed
01573     char s[16];
01574     TagToString (s, tag);
01575     globals->logWarning->Write ("CLightSettingState::Read : Unrecognized tag <%s>", s);
01576   }
01577 
01578   return rc;
01579 }
01580 
01581 
01582 //
01583 // CSwitchSet
01584 //
01585 CSwitchSet::CSwitchSet (void)
01586 {
01587   TypeIs (SUBSYSTEM_SWITCH_SET);
01588 
01589   sync = false;
01590   LAND = false;
01591   TAXI = false;
01592   NAVI = false;
01593 }
01594 
01595 CSwitchSet::~CSwitchSet (void)
01596 {
01597 }
01598 
01599 int CSwitchSet::Read (SStream *stream, Tag tag)
01600 {
01601   int rc = TAG_IGNORED;
01602   SMessage msg;
01603   memset (&msg, 0, sizeof(SMessage));
01604 
01605   switch (tag) {
01606   case 'smsg':
01607     {
01608       // Switch message
01609       ReadMessage (&msg, stream);
01610       smsg.push_back (msg);
01611     }
01612     rc = TAG_READ;
01613     break;
01614 
01615   case 'sync':
01616     sync = true;
01617     rc = TAG_READ;
01618     break;
01619 
01620   case 'LAND':
01621     LAND = true;
01622     rc = TAG_READ;
01623     break;
01624 
01625   case 'TAXI':
01626     TAXI = true;
01627     rc = TAG_READ;
01628     break;
01629 
01630   case 'NAVI':
01631     NAVI = true;
01632     rc = TAG_READ;
01633     break;
01634   }
01635 
01636   if (rc != TAG_READ) {
01637     // See if the tag can be processed by the parent class type
01638     rc = CDependent::Read (stream, tag);
01639   }
01640 
01641   if (rc != TAG_READ) {
01642     // Tag could not be processed
01643     char s[16];
01644     TagToString (s, tag);
01645     globals->logWarning->Write ("CSwitchSet::Read : Unrecognized tag <%s>", s);
01646   }
01647 
01648   return rc;
01649 }
01650 
01651 
01652 //
01653 // CRotaryIgnitionSwitch
01654 //
01655 CRotaryIgnitionSwitch::CRotaryIgnitionSwitch (void)
01656 {
01657   TypeIs (SUBSYSTEM_ROTARY_IGNITION_SWITCH);
01658 }
01659 
01660 
01661 //
01662 // CBattery
01663 //
01664 CBattery::CBattery (void)
01665 {
01666   TypeIs (SUBSYSTEM_BATTERY);
01667   hwId = HW_BATTERY;
01668 
01669   life = 0;
01670 }
01671 
01672 
01673 int CBattery::Read (SStream *stream, Tag tag)
01674 {
01675   int rc = TAG_IGNORED;
01676 
01677   switch (tag) {
01678   case 'life':
01679     // Battery capacity (amp-hours);
01680     ReadFloat (&life, stream);
01681     rc = TAG_READ;
01682     break;
01683   }
01684 
01685   if (rc != TAG_READ) {
01686     // See if the tag can be processed by the parent class type
01687     rc = CDependent::Read (stream, tag);
01688   }
01689 
01690   if (rc != TAG_READ) {
01691     // Tag could not be processed
01692     char s[16];
01693     TagToString (s, tag);
01694     globals->logWarning->Write ("CBattery::Read : Unrecognized tag <%s>", s);
01695   }
01696 
01697   return rc;
01698 }
01699 
01700 //
01701 // CAlternator
01702 //
01703 CAlternator::CAlternator (void)
01704 {
01705   TypeIs (SUBSYSTEM_ALTERNATOR);
01706   hwId = HW_ALTERNATOR;
01707 
01708   mxld = 0;
01709   loRg = 0;
01710 }
01711 
01712 
01713 int CAlternator::Read (SStream *stream, Tag tag)
01714 {
01715   int rc = TAG_IGNORED;
01716 
01717   switch (tag) {
01718   case 'mxld':
01719     // Maximum load (amps)
01720     ReadFloat (&mxld, stream);
01721     rc = TAG_READ;
01722     break;
01723 
01724   case 'loRg':
01725     // Minimum RPM regulatable
01726     ReadFloat (&loRg, stream);
01727     rc = TAG_READ;
01728     break;
01729   }
01730 
01731   if (rc != TAG_READ) {
01732     // See if the tag can be processed by the parent class type
01733     rc = CDependent::Read (stream, tag);
01734   }
01735 
01736   if (rc != TAG_READ) {
01737     // Tag could not be processed
01738     char s[16];
01739     TagToString (s, tag);
01740     globals->logWarning->Write ("CAlternator::Read : Unrecognized tag <%s>", s);
01741   }
01742 
01743   return rc;
01744 }
01745 
01746 EMessageResult CAlternator::ReceiveMessage (SMessage *msg)
01747 {
01748   EMessageResult rc = MSG_IGNORED;
01749 
01750   if (rc == MSG_IGNORED) {
01751     // See if the message can be processed by the parent class
01752     rc = CDependent::ReceiveMessage (msg);
01753   }
01754 
01755   return rc;
01756 }
01757 
01758 
01759 
01760 // *
01761 // * Gauge subsystems
01762 // *
01763 
01764 //
01765 // CPitotStaticSubsystem
01766 //
01767 CPitotStaticSubsystem::CPitotStaticSubsystem (void)
01768 {
01769   TypeIs (SUBSYSTEM_PITOT_STATIC_SUBS);
01770 
01771   gNum = 0;
01772 }
01773 
01774 
01775 int CPitotStaticSubsystem::Read (SStream *stream, Tag tag)
01776 {
01777   int rc = TAG_IGNORED;
01778 
01779   switch (tag) {
01780   case 'gNum':
01781     // Port group number
01782     ReadInt (&gNum, stream);
01783     rc = TAG_READ;
01784     break;
01785   }
01786 
01787   if (rc != TAG_READ) {
01788     // See if the tag can be processed by the parent class type
01789     rc = CDependent::Read (stream, tag);
01790   }
01791 
01792   if (rc != TAG_READ) {
01793     // Tag could not be processed
01794     char s[16];
01795     TagToString (s, tag);
01796     globals->logWarning->Write ("CPitotStaticSubsystem::Read : Unrecognized tag <%s>", s);
01797   }
01798 
01799   return rc;
01800 }
01801 
01802 
01803 
01804 
01805 //
01806 // CAltimeter
01807 //
01808 CAltimeter::CAltimeter (void)
01809 {
01810   TypeIs (SUBSYSTEM_ALTIMETER);
01811 }
01812 
01813 
01814 int CAltimeter::Read (SStream *stream, Tag tag)
01815 {
01816   int rc = TAG_IGNORED;
01817 
01818   if (rc != TAG_READ) {
01819     // See if the tag can be processed by the parent class type
01820     rc = CPitotStaticSubsystem::Read (stream, tag);
01821   }
01822 
01823   if (rc != TAG_READ) {
01824     // Tag could not be processed
01825     char s[16];
01826     TagToString (s, tag);
01827     globals->logWarning->Write ("CAltimeter::Read : Unrecognized tag <%s>", s);
01828   }
01829 
01830   return rc;
01831 }
01832 
01833 
01834 EMessageResult CAltimeter::ReceiveMessage (SMessage *msg)
01835 {
01836   EMessageResult rc = MSG_IGNORED;
01837 
01838   if (MsgForMe (msg)) {
01839     switch (msg->id) {
01840     case MSG_GETDATA:
01841       switch (msg->user.u.datatag) {
01842       case 'alti':
01843         msg->dataType = TYPE_REAL;
01844         msg->realData = indn;
01845         msg->result = rc = MSG_PROCESSED;
01846         break;
01847       }
01848       break;
01849 
01850     case MSG_SETDATA:
01851       switch (msg->user.u.datatag) {
01852       case 'alti':
01853         if (msg->dataType == TYPE_REAL) {
01854           indnTarget = msg->realData;
01855           msg->result = rc = MSG_PROCESSED;
01856         }
01857         break;
01858       }
01859       break;
01860     }
01861 
01862     if (rc == MSG_IGNORED) {
01863       // See if the message can be processed by the parent class
01864       rc = CPitotStaticSubsystem::ReceiveMessage (msg);
01865     }
01866   }
01867 
01868   return rc;
01869 }
01870 
01871 
01872 
01873 //
01874 // CVerticalSpeedIndicator
01875 //
01876 CVerticalSpeedIndicator::CVerticalSpeedIndicator (void)
01877 {
01878   char *mark1 = new char[32];
01879   strcpy (mark1, "vsiconst start");
01880   TypeIs (SUBSYSTEM_VERTICAL_SPEED);
01881   char *mark2 = new char[32];
01882   strcpy (mark2, "vsiconst end");
01883 }
01884 
01885 
01886 int CVerticalSpeedIndicator::Read (SStream *stream, Tag tag)
01887 {
01888   int rc = TAG_IGNORED;
01889 
01890   if (rc != TAG_READ) {
01891     // See if the tag can be processed by the parent class type
01892     rc = CPitotStaticSubsystem::Read (stream, tag);
01893   }
01894 
01895   if (rc != TAG_READ) {
01896     // Tag could not be processed
01897     char s[16];
01898     TagToString (s, tag);
01899     globals->logWarning->Write ("CVerticalSpeedIndicator::Read : Unrecognized tag <%s>", s);
01900   }
01901 
01902   return rc;
01903 }
01904 
01905 
01906 EMessageResult CVerticalSpeedIndicator::ReceiveMessage (SMessage *msg)
01907 {
01908   EMessageResult rc = MSG_IGNORED;
01909 
01910   if (MsgForMe (msg)) {
01911     switch (msg->id) {
01912     case MSG_GETDATA:
01913       switch (msg->user.u.datatag) {
01914       case 'vsi_':
01915         msg->dataType = TYPE_REAL;
01916         msg->realData = indn;
01917         msg->result = rc = MSG_PROCESSED;
01918         break;
01919       }
01920       break;
01921 
01922     case MSG_SETDATA:
01923       switch (msg->user.u.datatag) {
01924       case 'vsi_':
01925         if (msg->dataType == TYPE_REAL) {
01926           indnTarget = msg->realData;
01927           msg->result = rc = MSG_PROCESSED;
01928         }
01929         break;
01930       }
01931       break;
01932     }
01933 
01934     if (rc == MSG_IGNORED) {
01935       // See if the message can be processed by the parent class
01936       rc = CPitotStaticSubsystem::ReceiveMessage (msg);
01937     }
01938   }
01939 
01940   return rc;
01941 }
01942 
01943 
01944 
01945 //
01946 // CAirspeedIndicator
01947 //
01948 CAirspeedIndicator::CAirspeedIndicator (void)
01949 {
01950   TypeIs (SUBSYSTEM_AIRSPEED);
01951 }
01952 
01953 
01954 int CAirspeedIndicator::Read (SStream *stream, Tag tag)
01955 {
01956   int rc = TAG_IGNORED;
01957 
01958   if (rc != TAG_READ) {
01959     // See if the tag can be processed by the parent class type
01960     rc = CPitotStaticSubsystem::Read (stream, tag);
01961   }
01962 
01963   if (rc != TAG_READ) {
01964     // Tag could not be processed
01965     char s[16];
01966     TagToString (s, tag);
01967     globals->logWarning->Write ("CAirspeedIndicator::Read : Unrecognized tag <%s>", s);
01968   }
01969 
01970   return rc;
01971 }
01972 
01973 
01974 EMessageResult CAirspeedIndicator::ReceiveMessage (SMessage *msg)
01975 {
01976   EMessageResult rc = MSG_IGNORED;
01977 
01978   if (MsgForMe (msg)) {
01979     switch (msg->id) {
01980     case MSG_GETDATA:
01981       switch (msg->user.u.datatag) {
01982       case 'sped':
01983         msg->dataType = TYPE_REAL;
01984         msg->realData = indn;
01985         msg->result = rc = MSG_PROCESSED;
01986         break;
01987       }
01988       break;
01989 
01990     case MSG_SETDATA:
01991       switch (msg->user.u.datatag) {
01992       case 'sped':
01993         if (msg->dataType == TYPE_REAL) {
01994           indnTarget = msg->realData;
01995           msg->result = rc = MSG_PROCESSED;
01996         }
01997         break;
01998       }
01999       break;
02000     }
02001 
02002     if (rc == MSG_IGNORED) {
02003       // See if the message can be processed by the parent class
02004       rc = CPitotStaticSubsystem::ReceiveMessage (msg);
02005     }
02006   }
02007 
02008   return rc;
02009 }
02010 
02011 
02012 //
02013 // CPneumaticSubsystem
02014 //
02015 CPneumaticSubsystem::CPneumaticSubsystem (void)
02016 {
02017   TypeIs (SUBSYSTEM_PNEUMATIC);
02018 }
02019 
02020 CPneumaticSubsystem::~CPneumaticSubsystem (void)
02021 {
02022 }
02023 
02024 int CPneumaticSubsystem::Read (SStream *stream, Tag tag)
02025 {
02026   int rc = TAG_IGNORED;
02027   SMessage msg;
02028   memset (&msg, 0, sizeof(SMessage));
02029 
02030   switch (tag) {
02031   case 'mPmp':
02032     {
02033       // Pneumatic pump message
02034       ReadMessage (&msg, stream);
02035       mPmp.push_back (msg);
02036     }
02037     rc = TAG_READ;
02038     break;
02039   }
02040 
02041   if (rc != TAG_READ) {
02042     // See if the tag can be processed by the parent class type
02043     rc = CDependent::Read (stream, tag);
02044   }
02045 
02046   if (rc != TAG_READ) {
02047     // Tag could not be processed
02048     char s[16];
02049     TagToString (s, tag);
02050     globals->logWarning->Write ("CPitotStaticSubsystem::Read : Unrecognized tag <%s>", s);
02051   }
02052 
02053   return rc;
02054 }
02055 
02056 
02057 //
02058 // CAttitudeIndicator
02059 //
02060 CAttitudeIndicator::CAttitudeIndicator (void)
02061 {
02062   TypeIs (SUBSYSTEM_ATTITUDE);
02063 
02064   prat = 1.0;
02065 }
02066 
02067 
02068 int CAttitudeIndicator::Read (SStream *stream, Tag tag)
02069 {
02070   int rc = TAG_IGNORED;
02071 
02072   switch (tag) {
02073   case 'prat':
02074     // Precession rate
02075     ReadFloat (&prat, stream);
02076     rc = TAG_READ;
02077     break;
02078   }
02079 
02080   if (rc != TAG_READ) {
02081     // See if the tag can be processed by the parent class type
02082     rc = CPneumaticSubsystem::Read (stream, tag);
02083   }
02084 
02085   if (rc != TAG_READ) {
02086     // Tag could not be processed
02087     char s[16];
02088     TagToString (s, tag);
02089     globals->logWarning->Write ("CAttitudeIndicator::Read : Unrecognized tag <%s>", s);
02090   }
02091 
02092   return rc;
02093 }
02094 
02095 
02097 
02098 EMessageResult CAttitudeIndicator::ReceiveMessage (SMessage *msg)
02099 {
02100   EMessageResult rc = MSG_IGNORED;
02101 
02102   if (MsgForMe (msg)) {
02103     switch (msg->id) {
02104     case MSG_GETDATA:
02105       switch (msg->user.u.datatag) {
02106       case 'atti':
02107         msg->dataType = TYPE_REAL;
02108         msg->realData = indn;
02109         msg->result = rc = MSG_PROCESSED;
02110         break;
02111       }
02112       break;
02113 
02114     case MSG_SETDATA:
02115       switch (msg->user.u.datatag) {
02116       case 'atti':
02117         if (msg->dataType == TYPE_REAL) {
02118           indnTarget = msg->realData;
02119           msg->result = rc = MSG_PROCESSED;
02120         }
02121         break;
02122       }
02123       break;
02124     }
02125 
02126     if (rc == MSG_IGNORED) {
02127       // See if the message can be processed by the parent class
02128       rc = CPneumaticSubsystem::ReceiveMessage (msg);
02129     }
02130   }
02131 
02132   return rc;
02133 }
02134 
02135 //
02136 // CDirectionalGyro
02137 //
02138 CDirectionalGyro::CDirectionalGyro (void)
02139 {
02140   TypeIs (SUBSYSTEM_DIRECTIONAL_GYRO);
02141 
02142   step = 1.0f;
02143 }
02144 
02145 
02146 int CDirectionalGyro::Read (SStream *stream, Tag tag)
02147 {
02148   int rc = TAG_IGNORED;
02149 
02150   switch (tag) {
02151   case 'step':
02152     // Autopilot bug step size
02153     ReadFloat (&step, stream);
02154     rc = TAG_READ;
02155     break;
02156   }
02157 
02158   if (rc != TAG_READ) {
02159     // See if the tag can be processed by the parent class type
02160     rc = CPneumaticSubsystem::Read (stream, tag);
02161   }
02162 
02163   if (rc != TAG_READ) {
02164     // Tag could not be processed
02165     char s[16];
02166     TagToString (s, tag);
02167     globals->logWarning->Write ("CDirectionalGyro::Read : Unrecognized tag <%s>", s);
02168   }
02169 
02170   return rc;
02171 }
02172 
02173 
02174 EMessageResult CDirectionalGyro::ReceiveMessage (SMessage *msg)
02175 {
02176   EMessageResult rc = MSG_IGNORED;
02177 
02178   if (MsgForMe (msg)) {
02179     switch (msg->id) {
02180     case MSG_GETDATA:
02181       switch (msg->user.u.datatag) {
02182       case 'yaw_':
02183         msg->dataType = TYPE_REAL;
02184         msg->realData = indn;
02185         msg->result = rc = MSG_PROCESSED;
02186         break;
02187       }
02188       break;
02189 
02190     case MSG_SETDATA:
02191       switch (msg->user.u.datatag) {
02192       case 'yaw_':
02193         if (msg->dataType == TYPE_REAL) {
02194           indnTarget = msg->realData;
02195           msg->result = rc = MSG_PROCESSED;
02196         }
02197         break;
02198       }
02199       break;
02200     }
02201 
02202     if (rc == MSG_IGNORED) {
02203       // See if the message can be processed by the parent class
02204       rc = CPneumaticSubsystem::ReceiveMessage (msg);
02205     }
02206   }
02207 
02208   return rc;
02209 }
02210 
02211 
02212 //
02213 // CVacuumIndicator
02214 //
02215 CVacuumIndicator::CVacuumIndicator (void)
02216 {
02217   TypeIs (SUBSYSTEM_VACUUM_INDICATOR);
02218 }
02219 
02220 
02221 int CVacuumIndicator::Read (SStream *stream, Tag tag)
02222 {
02223   int rc = TAG_IGNORED;
02224 
02225   if (rc != TAG_READ) {
02226     // See if the tag can be processed by the parent class type
02227     rc = CPneumaticSubsystem::Read (stream, tag);
02228   }
02229 
02230   if (rc != TAG_READ) {
02231     // Tag could not be processed
02232     char s[16];
02233     TagToString (s, tag);
02234     globals->logWarning->Write ("CVacuumIndicator::Read : Unrecognized tag <%s>", s);
02235   }
02236 
02237   return rc;
02238 }
02239 
02240 
02241 //
02242 // CTurnCoordinator
02243 //
02244 CTurnCoordinator::CTurnCoordinator (void)
02245 {
02246   TypeIs (SUBSYSTEM_TURN_COORDINATOR);
02247 
02248   tilt = 0;
02249 }
02250 
02251 
02252 int CTurnCoordinator::Read (SStream *stream, Tag tag)
02253 {
02254   int rc = TAG_IGNORED;
02255 
02256   switch (tag) {
02257   case 'tilt':
02258     // Tilt ??
02259     ReadFloat (&tilt, stream);
02260     rc = TAG_READ;
02261     break;
02262   }
02263 
02264   if (rc != TAG_READ) {
02265     // See if the tag can be processed by the parent class type
02266     rc = CDependent::Read (stream, tag);
02267   }
02268 
02269   if (rc != TAG_READ) {
02270     // Tag could not be processed
02271     char s[16];
02272     TagToString (s, tag);
02273     globals->logWarning->Write ("CTurnCoordinator::Read : Unrecognized tag <%s>", s);
02274   }
02275 
02276   return rc;
02277 }
02278 
02279 
02280 //
02281 // CMagneticCompass
02282 //
02283 CMagneticCompass::CMagneticCompass (void)
02284 {
02285   TypeIs (SUBSYSTEM_MAGNETIC_COMPASS);
02286 }
02287 
02288 
02289 //
02290 // CNavigation
02291 //
02292 CNavigation::CNavigation (void)
02293 {
02294   TypeIs (SUBSYSTEM_NAVIGATION);
02295 }
02296 
02297 
02298 //
02299 // CDigitalClockOAT
02300 //
02301 CDigitalClockOAT::CDigitalClockOAT (void)
02302 {
02303   TypeIs (SUBSYSTEM_DIGITAL_CLOCK_OAT);
02304 }
02305 
02306 
02307 //
02308 // CBKKAP140Panel
02309 //
02310 CBKKAP140Panel::CBKKAP140Panel (void)
02311 {
02312   TypeIs (SUBSYSTEM_KAP140_PANEL);
02313 
02314   memset (&gyro, 0, sizeof(SMessage));
02315   memset (&nav1, 0, sizeof(SMessage));
02316 }
02317 
02318 int CBKKAP140Panel::Read (SStream *stream, Tag tag)
02319 {
02320   int rc = TAG_IGNORED;
02321 
02322   switch (tag) {
02323   case 'atop':
02324     // Autopilot specification
02325     SkipObject (stream);
02326     rc = TAG_READ;
02327     break;
02328 
02329   case 'mDG_':
02330     // Directional gyro (heading) message
02331     ReadMessage (&gyro, stream);
02332     rc = TAG_READ;
02333     break;
02334 
02335   case 'nav1':
02336     // NAV radio message
02337     ReadMessage (&nav1, stream);
02338     rc = TAG_READ;
02339     break;
02340   }
02341 
02342   if (rc != TAG_READ) {
02343     // See if the tag can be processed by the parent class type
02344     rc = CDependent::Read (stream, tag);
02345   }
02346 
02347   if (rc != TAG_READ) {
02348     // Tag could not be processed
02349     char s[16];
02350     TagToString (s, tag);
02351     globals->logWarning->Write ("CBKKAP140Radio::Read : Unrecognized tag <%s>", s);
02352   }
02353 
02354   return rc;
02355 }
02356 
02357 
02358 //
02359 // CMarkerPanel
02360 //
02361 CMarkerPanel::CMarkerPanel (void)
02362 {
02363   TypeIs (SUBSYSTEM_MARKER_PANEL);
02364 }
02365 
02366 
02367 //
02368 // CAmmeter
02369 //
02370 CAmmeter::CAmmeter (void)
02371 {
02372   TypeIs (SUBSYSTEM_AMMETER);
02373 
02374   chrg = false;
02375   memset (&mMon, 0, sizeof(SMessage));
02376 }
02377 
02378 
02379 int CAmmeter::Read (SStream *stream, Tag tag)
02380 {
02381   int rc = TAG_IGNORED;
02382 
02383   switch (tag) {
02384   case 'chrg':
02385     // Charge meter
02386     chrg = true;
02387     rc = TAG_READ;
02388     break;
02389 
02390   case 'mMon':
02391     // Monitor message
02392     ReadMessage (&mMon, stream);
02393     rc = TAG_READ;
02394     break;
02395   }
02396 
02397   if (rc != TAG_READ) {
02398     // See if the tag can be processed by the parent class type
02399     rc = CDependent::Read (stream, tag);
02400   }
02401 
02402   if (rc != TAG_READ) {
02403     // Tag could not be processed
02404     char s[16];
02405     TagToString (s, tag);
02406     globals->logWarning->Write ("CAmmeter::Read : Unrecognized tag <%s>", s);
02407   }
02408 
02409   return rc;
02410 }
02411 
02412 
02413 // *
02414 // * Engine gauge subsystems
02415 // *
02416 
02417 //
02418 // CEngineSubsystem
02419 //
02420 CEngineSubsystem::CEngineSubsystem (void)
02421 {
02422   TypeIs (SUBSYSTEM_ENGINE_SUBSYSTEM);
02423 
02424   eNum = 1;
02425 }
02426 
02427 
02428 int CEngineSubsystem::Read (SStream *stream, Tag tag)
02429 {
02430   int rc = TAG_IGNORED;
02431 
02432   switch (tag) {
02433   case 'eNum':
02434     // Engine number
02435     ReadUInt (&eNum, stream);
02436     rc = TAG_READ;
02437     break;
02438   }
02439 
02440   if (rc != TAG_READ) {
02441     // See if the tag can be processed by the parent class type
02442     rc = CDependent::Read (stream, tag);
02443   }
02444 
02445   if (rc != TAG_READ) {
02446     // Tag could not be processed
02447     char s[16];
02448     TagToString (s, tag);
02449     globals->logWarning->Write ("CEngineSubsystem::Read : Unrecognized tag <%s>", s);
02450   }
02451 
02452   return rc;
02453 }
02454 
02455 
02456 //
02457 // CTachometer
02458 //
02459 CTachometer::CTachometer (void)
02460 {
02461   TypeIs (SUBSYSTEM_TACHOMETER);
02462   Alias ('indn', 'rpmn');
02463 }
02464 
02465 
02466 //
02467 // COilTemperature
02468 //
02469 COilTemperature::COilTemperature (void)
02470 {
02471   TypeIs (SUBSYSTEM_OIL_TEMPERATURE);
02472   Alias ('indn', 'oilT');
02473 }
02474 
02475 
02476 //
02477 // COilPressure
02478 //
02479 COilPressure::COilPressure (void)
02480 {
02481   TypeIs (SUBSYSTEM_OIL_PRESSURE);
02482   Alias ('indn', 'oilP');
02483 
02484   lowP = 0;
02485 }
02486 
02487 
02488 int COilPressure::Read (SStream *stream, Tag tag)
02489 {
02490   int rc = TAG_IGNORED;
02491 
02492   switch (tag) {
02493   case 'lowP':
02494     // Low pressure threshold
02495     ReadFloat (&lowP, stream);
02496     rc = TAG_READ;
02497     break;
02498   }
02499 
02500   if (rc != TAG_READ) {
02501     // See if the tag can be processed by the parent class type
02502     rc = CEngineSubsystem::Read (stream, tag);
02503   }
02504 
02505   if (rc != TAG_READ) {
02506     // Tag could not be processed
02507     char s[16];
02508     TagToString (s, tag);
02509     globals->logWarning->Write ("COilPressure::Read : Unrecognized tag <%s>", s);
02510   }
02511 
02512   return rc;
02513 }
02514 
02515 
02516 //
02517 // CExhaustGasTemperature
02518 //
02519 CExhaustGasTemperature::CExhaustGasTemperature (void)
02520 {
02521   TypeIs (SUBSYSTEM_EXHAUST_GAS_TEMPERATURE);
02522 }
02523 
02524 
02525 //
02526 // CManifoldPressure
02527 //
02528 CManifoldPressure::CManifoldPressure (void)
02529 {
02530   TypeIs (SUBSYSTEM_MANIFOLD_PRESSURE);
02531 }
02532 
02533 
02534 //
02535 // CHobbsMeter
02536 //
02537 CHobbsMeter::CHobbsMeter (void)
02538 {
02539   TypeIs (SUBSYSTEM_HOBBS_METER);
02540 }
02541 
02542 
02543 //
02544 // CTachometerTimer
02545 //
02546 CTachometerTimer::CTachometerTimer (void)
02547 {
02548   TypeIs (SUBSYSTEM_TACHOMETER_TIMER);
02549 }
02550 
02551 
02552 // *
02553 // * Aircraft control subsystems
02554 // *
02555 
02556 //
02557 // CSteeringControl
02558 //
02559 CSteeringControl::CSteeringControl (void)
02560 {
02561   TypeIs (SUBSYSTEM_STEERING_CONTROL);
02562 }
02563 
02564 //
02565 // CBaseControl
02566 //
02567 CBaseControl::CBaseControl (void)
02568 {
02569   TypeIs (SUBSYSTEM_BASE_CONTROL);
02570 
02571   scal = 1.0f;
02572   step = 0.01f;
02573   bend = 0.0f;
02574   posn = 0.0f;
02575 
02576   indn = 0.0f;
02577 }
02578 
02579 int CBaseControl::Read (SStream *stream, Tag tag)
02580 {
02581   int rc = TAG_IGNORED;
02582 
02583   switch (tag) {
02584   case 'scal':
02585     // Scaling factor
02586     ReadFloat (&scal, stream);
02587     rc = TAG_READ;
02588     break;
02589 
02590   case 'step':
02591     // Control increment step
02592     ReadFloat (&step, stream);
02593     rc = TAG_READ;
02594     break;
02595 
02596   case 'bend':
02597     // Exponential
02598     ReadFloat (&bend, stream);
02599     rc = TAG_READ;
02600     break;
02601 
02602   case 'posn':
02603     // Default position
02604     ReadFloat (&posn, stream);
02605     rc = TAG_READ;
02606     break;
02607   }
02608 
02609   if (rc != TAG_READ) {
02610     // See if the tag can be processed by the parent class type
02611     rc = CDependent::Read (stream, tag);
02612   }
02613 
02614   if (rc != TAG_READ) {
02615     // Tag could not be processed
02616     char s[16];
02617     TagToString (s, tag);
02618     globals->logWarning->Write ("CBaseControl::Read : Unrecognized tag <%s>", s);
02619   }
02620 
02621   return rc;
02622 }
02623 
02624 
02625 //
02626 // Increment the control by the step value
02627 //
02628 void CBaseControl::Incr (void)
02629 {
02630   indn += step;
02631 
02632   DrawNoticeToUser ("Control increment", 1);
02633 }
02634 
02635 
02636 //
02637 // Decrement the control by the step value
02638 //
02639 void CBaseControl::Decr (void)
02640 {
02641   indn -= step;
02642 
02643   DrawNoticeToUser ("Control decrement", 1);
02644 }
02645 
02646 
02647 //
02648 // CThrottleControl
02649 //
02650 CThrottleControl::CThrottleControl (void)
02651 {
02652   TypeIs (SUBSYSTEM_THROTTLE_CONTROL);
02653   Alias ('indn', 'thro');
02654 }
02655 
02656 
02657 //
02658 // CMixtureControl
02659 //
02660 CMixtureControl::CMixtureControl (void)
02661 {
02662   TypeIs (SUBSYSTEM_MIXTURE_CONTROL);
02663   Alias ('indn', 'mixt');
02664 
02665   autoControl = false;
02666   injd = false;
02667   prmr = 1.0f;
02668   prff = 0.0f;
02669   plim = 0.0f;
02670 }
02671 
02672 int CMixtureControl::Read (SStream *stream, Tag tag)
02673 {
02674   int rc = TAG_IGNORED;
02675 
02676   switch (tag) {
02677   case 'auto':
02678     // Control is capable of automatic control
02679     autoControl = true;
02680     rc = TAG_READ;
02681     break;
02682 
02683   case 'injd':
02684     // Engine is fuel injected (no carbeurator)
02685     injd = true;
02686     rc = TAG_READ;
02687     break;
02688 
02689   case 'prmr':
02690     // Priming rate
02691     ReadFloat (&prmr, stream);
02692     rc = TAG_READ;
02693     break;
02694 
02695   case 'prff':
02696     // Priming fuel flow (pph)
02697     ReadFloat (&prff, stream);
02698     rc = TAG_READ;
02699     break;
02700 
02701   case 'plim':
02702     // Priming pump limit
02703     ReadFloat (&plim, stream);
02704     rc = TAG_READ;
02705     break;
02706   }
02707 
02708   if (rc != TAG_READ) {
02709     // See if the tag can be processed by the parent class type
02710     rc = CBaseControl::Read (stream, tag);
02711   }
02712 
02713   if (rc != TAG_READ) {
02714     // Tag could not be processed
02715     char s[16];
02716     TagToString (s, tag);
02717     globals->logWarning->Write ("CMixtureControl::Read : Unrecognized tag <%s>", s);
02718   }
02719 
02720   return rc;
02721 }
02722 
02723 
02724 //
02725 // CFlapControl
02726 //
02727 CFlapControl::CFlapControl (void)
02728 {
02729   TypeIs (SUBSYSTEM_FLAP_CONTROL);
02730 
02731   pos = NULL;
02732   speed = NULL;
02733 }
02734 
02735 CFlapControl::~CFlapControl (void)
02736 {
02737   delete[] pos;
02738   delete[] speed;
02739 }
02740 
02741 int CFlapControl::Read (SStream *stream, Tag tag)
02742 {
02743   int rc = TAG_IGNORED;
02744 
02745   switch (tag) {
02746   case 'flpP':
02747     {
02748       // Flap position array
02749       ReadInt (&nPos, stream);
02750       pos = new float[nPos];
02751       for (int i=0; i < nPos; i++) {
02752         ReadFloat (&pos[i], stream);
02753       }
02754     }
02755     rc = TAG_READ;
02756     break;
02757 
02758   case 'flpS':
02759     {
02760       // Flap speed array
02761       ReadInt (&nSpeed, stream);
02762       speed = new float[nSpeed];
02763       for (int i=0; i < nSpeed; i++) {
02764         ReadFloat (&speed[i], stream);
02765       }
02766     }
02767     rc = TAG_READ;
02768     break;
02769   }
02770 
02771   if (rc != TAG_READ) {
02772     // See if the tag can be processed by the parent class type
02773     rc = CBaseControl::Read (stream, tag);
02774   }
02775 
02776   if (rc != TAG_READ) {
02777     // Tag could not be processed
02778     char s[16];
02779     TagToString (s, tag);
02780     globals->logWarning->Write ("CFlapControl::Read : Unrecognized tag <%s>", s);
02781   }
02782 
02783   return rc;
02784 }
02785 
02786 
02787 //
02788 // CElevatorControl
02789 //
02790 CElevatorControl::CElevatorControl (void)
02791 {
02792   TypeIs (SUBSYSTEM_ELEVATOR_CONTROL);
02793 }
02794 
02795 
02796 //
02797 // CAileronControl
02798 //
02799 CAileronControl::CAileronControl (void)
02800 {
02801   TypeIs (SUBSYSTEM_AILERON_CONTROL);
02802 }
02803 
02804 
02805 //
02806 // CRudderControl
02807 //
02808 CRudderControl::CRudderControl (void)
02809 {
02810   TypeIs (SUBSYSTEM_RUDDER_CONTROL);
02811 }
02812 
02813 
02814 //
02815 // CElevatorTrimControl
02816 //
02817 CElevatorTrimControl::CElevatorTrimControl (void)
02818 {
02819   TypeIs (SUBSYSTEM_ELEVATOR_TRIM_CONTROL);
02820 }
02821 
02822 
02823 //
02824 // CAileronTrimControl
02825 //
02826 CAileronTrimControl::CAileronTrimControl (void)
02827 {
02828   TypeIs (SUBSYSTEM_AILERON_TRIM_CONTROL);
02829 }
02830 
02831 
02832 //
02833 // CRudderTrimControl
02834 //
02835 CRudderTrimControl::CRudderTrimControl (void)
02836 {
02837   TypeIs (SUBSYSTEM_RUDDER_TRIM_CONTROL);
02838 }
02839 
02840 
02841 //
02842 // CBrakeControl
02843 //
02844 CBrakeControl::CBrakeControl (void)
02845 {
02846   TypeIs (SUBSYSTEM_BRAKE_CONTROL);
02847 }
02848 
02849 
02850 // *
02851 // *  Radio subsystems
02852 // *
02853 
02854 //
02855 // CRadio
02856 //
02857 CRadio::CRadio (void)
02858 {
02859   TypeIs (SUBSYSTEM_RADIO);
02860 
02861   tune = lfrq = hfrq = sinc = 0;
02862   test = false;
02863 }
02864 
02865 int CRadio::Read (SStream *stream, Tag tag)
02866 {
02867   int rc = TAG_IGNORED;
02868 
02869   switch (tag) {
02870   case 'tune':
02871     ReadFloat (&tune, stream);
02872     rc = TAG_READ;
02873     break;
02874   case 'lowf':
02875     ReadFloat (&lfrq, stream);
02876     rc = TAG_READ;
02877     break;
02878   case 'high':
02879     ReadFloat (&hfrq, stream);
02880     rc = TAG_READ;
02881     break;
02882   case 'seek':
02883     ReadFloat (&sinc, stream);
02884     rc = TAG_READ;
02885     break;
02886   }
02887 
02888   if (rc != TAG_READ) {
02889     // See if the tag can be processed by the parent class type
02890     rc = CDependent::Read (stream, tag);
02891   }
02892 
02893   if (rc != TAG_READ) {
02894     // Tag could not be processed
02895     char s[16];
02896     TagToString (s, tag);
02897     globals->logWarning->Write ("CRadio::Read : Unrecognized tag <%s>", s);
02898   }
02899 
02900   return rc;
02901 }
02902 
02903 EMessageResult CRadio::ReceiveMessage (SMessage *msg)
02904 {
02905   EMessageResult rc = MSG_IGNORED;
02906 
02907   if (MsgForMe (msg)) {
02908     switch (msg->id) {
02909     case MSG_GETDATA:
02910       switch (msg->user.u.datatag) {
02911       case 'tune':
02912         msg->dataType = TYPE_REAL;
02913         msg->realData = tune;
02914         msg->result = rc = MSG_PROCESSED;
02915         break;
02916       case 'hfrq':
02917         msg->dataType = TYPE_REAL;
02918         msg->realData = hfrq;
02919         msg->result = rc = MSG_PROCESSED;
02920         break;
02921       case 'lfrq':
02922         msg->dataType = TYPE_REAL;
02923         msg->realData = lfrq;
02924         msg->result = rc = MSG_PROCESSED;
02925         break;
02926       case 'sinc':
02927         msg->dataType = TYPE_REAL;
02928         msg->realData = sinc;
02929         msg->result = rc = MSG_PROCESSED;
02930         break;
02931       case 'test':
02932         msg->dataType = TYPE_INT;
02933         msg->realData = test ? 1 : 0;
02934         msg->result = rc = MSG_PROCESSED;
02935         break;
02936       }
02937       break;
02938 
02939     case MSG_SETDATA:
02940       switch (msg->user.u.datatag) {
02941       case 'tune':
02942         tune = msg->realData;
02943         msg->result = rc = MSG_PROCESSED;
02944         break;
02945       case 'hfrq':
02946         hfrq = msg->realData;
02947         msg->result = rc = MSG_PROCESSED;
02948         break;
02949       case 'lfrq':
02950         lfrq = msg->realData;
02951         msg->result = rc = MSG_PROCESSED;
02952         break;
02953       case 'sinc':
02954         sinc = msg->realData;
02955         msg->result = rc = MSG_PROCESSED;
02956         break;
02957       case 'test':
02958         test = true;
02959         msg->result = rc = MSG_PROCESSED;
02960         break;
02961       }
02962     }
02963 
02964     if (rc == MSG_IGNORED) {
02965       // See if the message can be processed by the parent class
02966       rc = CDependent::ReceiveMessage (msg);
02967     }
02968   }
02969 
02970   return rc;
02971 }
02972 
02973 
02974 //
02975 // CNavRadio
02976 //
02977 CNavRadio::CNavRadio (void)
02978 {
02979   TypeIs (SUBSYSTEM_NAV_RADIO);
02980 
02981   tune = 108.000;
02982   lfrq = 108.000;
02983   hfrq = 117.950;
02984   sinc =   0.050;
02985   test = false;
02986 
02987   stby = 108.000;
02988 
02989   navaidList = NULL;
02990   navaidTimer = 0;
02991   navaidTuned = NULL;
02992   navaidFilter = NAVAID_TYPE_VOR;
02993 
02994   // Initialize exponential tracking for navaid pointer
02995   navdTarget = 0;
02996   navd = 0;
02997   navdTimK = 0.5f;
02998   navdRatK = 0.5f;
02999 }
03000 
03001 CNavRadio::~CNavRadio (void)
03002 {
03003   if (navaidList != NULL) {
03004     FreeNavaid (navaidList);
03005   }
03006 }
03007 
03008 int CNavRadio::Read (SStream *stream, Tag tag)
03009 {
03010   int rc = TAG_IGNORED;
03011 
03012   switch (tag) {
03013   case 'stby':
03014     ReadFloat (&stby, stream);
03015     rc = TAG_READ;
03016     break;
03017   }
03018 
03019   if (rc != TAG_READ) {
03020     // See if the tag can be processed by the parent class type
03021     rc = CRadio::Read (stream, tag);
03022   }
03023 
03024   if (rc != TAG_READ) {
03025     // Tag could not be processed
03026     char s[16];
03027     TagToString (s, tag);
03028     globals->logWarning->Write ("CNavRadio::Read : Unrecognized tag <%s>", s);
03029   }
03030 
03031   return rc;
03032 }
03033 
03034 EMessageResult CNavRadio::ReceiveMessage (SMessage *msg)
03035 {
03036   EMessageResult rc = MSG_IGNORED;
03037 
03038   if (MsgForMe (msg)) {
03039     switch (msg->id) {
03040     case MSG_GETDATA:
03041       switch (msg->user.u.datatag) {
03042       case 'stby':
03043         msg->dataType = TYPE_REAL;
03044         msg->realData = stby;
03045         msg->result = rc = MSG_PROCESSED;
03046         break;
03047       case '50Kz':
03048         msg->dataType = TYPE_INT;
03049         msg->intData = (sinc == 0.050f);
03050         msg->result = rc = MSG_PROCESSED;
03051         break;
03052       case '25Kz':
03053         msg->dataType = TYPE_INT;
03054         msg->intData = (sinc == 0.025f);
03055         msg->result = rc = MSG_PROCESSED;
03056         break;
03057       case 'navd':
03058         msg->dataType = TYPE_REAL;
03059         msg->realData = navd;
03060         msg->result = rc = MSG_PROCESSED;
03061         break;
03062       }
03063       break;
03064 
03065     case MSG_SETDATA:
03066       switch (msg->user.u.datatag) {
03067       case 'stby':
03068         stby = msg->realData;
03069         msg->result = rc = MSG_PROCESSED;
03070         break;
03071       case '50Kz':
03072         // Set step increment to 50 KHz
03073         sinc = 0.050f;
03074         msg->result = rc = MSG_PROCESSED;
03075         break;
03076       case '25Kz':
03077         // Set step increment to 25 KHz
03078         sinc = 0.025f;
03079         msg->result = rc = MSG_PROCESSED;
03080         break;
03081       }
03082     }
03083 
03084     if (rc == MSG_IGNORED) {
03085       // See if the message can be processed by the parent class
03086       rc = CRadio::ReceiveMessage (msg);
03087     }
03088   }
03089 
03090   return rc;
03091 }
03092 
03093 void CNavRadio::RescanNavaids (void)
03094 {
03095   if (navaidList != NULL) {
03097     int count = 0;
03098     SNavaid *next = navaidList;
03099     while (next != NULL) {
03100       count++;
03101       next = next->next;
03102     }
03103     FreeNavaid (navaidList);
03104     navaidList = NULL;
03105   }
03106   GetLocalNavaids (&navaidList);
03107 
03108   // Search for tuned navaid
03109   navaidTuned = NULL;
03110   SNavaid *next = navaidList;
03111   while (next != NULL) {
03112     if ((next->freq == tune) && (next->type & navaidFilter)) {
03113       // Got a match
03115       navaidTuned = next;
03116       break;
03117     }
03118     next = next->next;
03119   }
03120 }
03121 
03122 void CNavRadio::TimeSlice (float dT)
03123 {
03124   // Call parent TimeSlice method
03125   CRadio::TimeSlice (dT);
03126 
03127   if (active) {
03128     // Get list of local navaids periodically
03129     navaidTimer += dT;
03130     if (navaidTimer > 1.0f) {
03131       navaidTimer -= 1.0f;
03132       RescanNavaids ();
03133     }
03134 
03135     // Find tuned navaid
03136     if (navaidTuned != NULL) {
03137       SPosition pos = globals->sit->user->GetPosition();
03138       SVector v = GreatCirclePolar(&pos, &(navaidTuned->pos));
03139       navdTarget = Wrap360(v.h);
03140 
03141 //      char debug[80];
03142 //      sprintf (debug, "hdg=%f range=%f", v.h, FeetToNm(v.r));
03143 //      DrawNoticeToUser (debug, 1);
03144 
03145     } else {
03146       // No navaid tuned, set pointer to 0
03147       navdTarget = 0;
03148     }
03149   } else {
03150     // Set navaid pointer to zero
03151     navdTarget = 0;
03152   }
03153 
03154   // Update navaid pointer to track target
03155   float delta = Wrap180(navdTarget - navd);
03156   // Exponential response
03157 //  navd += delta * (1.0f - exp(-dT / navdTimK));
03158   // Linear response
03159   navd = Wrap360(navd + (delta * (dT / navdRatK)));
03160 }
03161 
03162 
03163 //
03164 // CRnavRadio
03165 //
03166 CRnavRadio::CRnavRadio (void)
03167 {
03168   TypeIs (SUBSYSTEM_RNAV_RADIO);
03169 }
03170 
03171 
03172 //
03173 // CCommRadio
03174 //
03175 CCommRadio::CCommRadio (void)
03176 {
03177   TypeIs (SUBSYSTEM_COMM_RADIO);
03178 
03179   tune = 118.000;
03180   lfrq = 118.000;
03181   hfrq = 137.975;
03182   sinc =   0.025;
03183 
03184   stby = 118.000;
03185 }
03186 
03187 
03188 //
03189 // CRadio
03190 //
03191 CHFCommRadio::CHFCommRadio (void)
03192 {
03193   TypeIs (SUBSYSTEM_HF_COMM_RADIO);
03194 }
03195 
03196 
03197 //
03198 // CADFRadio
03199 //
03200 CADFRadio::CADFRadio (void)
03201 {
03202   TypeIs (SUBSYSTEM_ADF_RADIO);
03203 
03204   // Initialize CNavRadio data
03205   tune = 200.0f;
03206   lfrq = 200.0f;
03207   hfrq = 2000.0f;
03208   sinc = 1.0f;
03209   test = false;
03210 
03211   stby = 200.0f;
03212   navd = 0;
03213 
03214   // Initialize ADF specific data
03215   adf = true;
03216   flt = true;
03217   bfo = frq = et = etst = false;
03218   ftime = 0;
03219   etime = 0;
03220   tone = false;
03221   volu = 1.0;
03222 
03223   navaidFilter = NAVAID_TYPE_NDB;
03224 }
03225 
03226 int CADFRadio::Read (SStream *stream, Tag tag)
03227 {
03228   int rc = TAG_IGNORED;
03229 
03230   switch (tag) {
03231   case 'adf_':
03232     adf = true;
03233     rc = TAG_READ;
03234     break;
03235   case 'bfo_':
03236     bfo = true;
03237     rc = TAG_READ;
03238     break;
03239   case 'flt':
03240     flt = true;
03241     rc = TAG_READ;
03242     break;
03243   case 'et__':
03244     et = true;
03245     rc = TAG_READ;
03246     break;
03247   case 'etst':
03248     etst = true;
03249     rc = TAG_READ;
03250     break;
03251   case 'ftim':
03252     {
03253       int temp;
03254       ReadInt (&temp, stream);
03255       ftime = (float)temp;
03256       rc = TAG_READ;
03257     }
03258     break;
03259   case 'etim':
03260     {
03261       int temp;
03262       ReadInt (&temp, stream);
03263       etime = (float)temp;
03264       rc = TAG_READ;
03265     }
03266     rc = TAG_READ;
03267     break;
03268   case 'tone':
03269     tone = true;
03270     rc = TAG_READ;
03271     break;
03272   }
03273 
03274   if (rc != TAG_READ) {
03275     // See if the tag can be processed by the parent class type
03276     rc = CNavRadio::Read (stream, tag);
03277   }
03278 
03279   if (rc != TAG_READ) {
03280     // Tag could not be processed
03281     char s[16];
03282     TagToString (s, tag);
03283     globals->logWarning->Write ("CADFRadio::Read : Unrecognized tag <%s>", s);
03284   }
03285 
03286   return rc;
03287 }
03288 
03289 void CADFRadio::ChangeADFFrequency (float &freq, int digit, int change)
03290 {
03291   // Bounds check on digit to change
03292   if ((digit < 1) || (digit > 4)) return;
03293 
03294   // Convert frequency to integer
03295   int iFreq = (int)(floorf (freq + 0.5));
03296 
03297   // Subtract value that is being changed
03298   static const int pow10[4] = {1000, 100, 10, 1};
03299   int pow = pow10[digit-1];
03300 
03301   // Subtract value being changed out of frequency, adjust and add back in
03302   int value = (iFreq / pow) % 10;
03303   iFreq -= value * pow;
03304   value = (value + change);
03305   if (value < 0) value += 10;
03306   value %= 10;
03307   iFreq += value * pow;
03308 
03309   // Range check against valid ADF HF frequency band 200 - 1799 KHz
03310   if (iFreq < 200) iFreq = 200;
03311   if (iFreq > 1799) iFreq = 1799;
03312 
03313   // Convert back to float frequency
03314   freq = (float)iFreq;
03315 }
03316 
03317 EMessageResult CADFRadio::ReceiveMessage (SMessage *msg)
03318 {
03319   EMessageResult rc = MSG_IGNORED;
03320 
03321   if (MsgForMe (msg)) {
03322     switch (msg->id) {
03323     case MSG_SETDATA:
03324       switch (msg->user.u.datatag) {
03325       case 'volu':
03326         // Set volume
03327         volu = msg->realData;
03328         msg->result = rc = MSG_PROCESSED;
03329         break;
03330       case 'ad1+':
03331         // Increment active frequency digit 1
03332         ChangeADFFrequency (tune, 1, 1);
03333         msg->result = rc = MSG_PROCESSED;
03334         break;
03335       case 'ad1-':
03336         // Decrement active frequency digit 1
03337         ChangeADFFrequency (tune, 1, -1);
03338         msg->result = rc = MSG_PROCESSED;
03339         break;
03340       case 'ad2+':
03341         // Increment active frequency digit 2
03342         ChangeADFFrequency (tune, 2, 1);
03343         msg->result = rc = MSG_PROCESSED;
03344         break;
03345       case 'ad2-':
03346         // Decrement active frequency digit 2
03347         ChangeADFFrequency (tune, 2, -1);
03348         msg->result = rc = MSG_PROCESSED;
03349         break;
03350       case 'ad3+':
03351         // Increment active frequency digit 3
03352         ChangeADFFrequency (tune, 3, 1);
03353         msg->result = rc = MSG_PROCESSED;
03354         break;
03355       case 'ad3-':
03356         // Decrement active frequency digit 3
03357         ChangeADFFrequency (tune, 3, -1);
03358         msg->result = rc = MSG_PROCESSED;
03359         break;
03360       case 'ad4+':
03361         // Increment active frequency digit 4
03362         ChangeADFFrequency (tune, 4, 1);
03363         msg->result = rc = MSG_PROCESSED;
03364         break;
03365       case 'ad4-':
03366         // Decrement active frequency digit 4
03367         ChangeADFFrequency (tune, 4, -1);
03368         msg->result = rc = MSG_PROCESSED;
03369         break;
03370       case 'sd1+':
03371         // Increment standby frequency digit 1
03372         ChangeADFFrequency (stby, 1, 1);
03373         msg->result = rc = MSG_PROCESSED;
03374         break;
03375       case 'sd1-':
03376         // Decrement standby frequency digit 1
03377         ChangeADFFrequency (stby, 1, -1);
03378         msg->result = rc = MSG_PROCESSED;
03379         break;
03380       case 'sd2+':
03381         // Increment standby frequency digit 2
03382         ChangeADFFrequency (stby, 2, 1);
03383         msg->result = rc = MSG_PROCESSED;
03384         break;
03385       case 'sd2-':
03386         // Decrement standby frequency digit 2
03387         ChangeADFFrequency (stby, 2, -1);
03388         msg->result = rc = MSG_PROCESSED;
03389         break;
03390       case 'sd3+':
03391         // Increment standby frequency digit 3
03392         ChangeADFFrequency (stby, 3, 1);
03393         msg->result = rc = MSG_PROCESSED;
03394         break;
03395       case 'sd3-':
03396         // Decrement standby frequency digit 3
03397         ChangeADFFrequency (stby, 3, -1);
03398         msg->result = rc = MSG_PROCESSED;
03399         break;
03400       case 'sd4+':
03401         // Increment standby frequency digit 4
03402         ChangeADFFrequency (stby, 4, 1);
03403         msg->result = rc = MSG_PROCESSED;
03404         break;
03405       case 'sd4-':
03406         // Decrement standby frequency digit 4
03407         ChangeADFFrequency (stby, 4, -1);
03408         msg->result = rc = MSG_PROCESSED;
03409         break;
03410       case 'adf ':
03411         // Set ADF state
03412         adf = (msg->intData != 0);
03413         msg->result = rc = MSG_PROCESSED;
03414         break;
03415       case 'adf_':
03416         // ADF button press toggles ADF state
03417         adf = !adf;
03418         msg->result = rc = MSG_PROCESSED;
03419         break;
03420       case 'bfo ':
03421         // Set BFO state
03422         bfo = (msg->intData != 0);
03423         msg->result = rc = MSG_PROCESSED;
03424         break;
03425       case 'bfo_':
03426         // BFO button press toggles BFO state
03427         bfo = !bfo;
03428         msg->result = rc = MSG_PROCESSED;
03429         break;
03430       case 'freq':
03431         // FRQ button press
03432         if (frq) {
03433           // Transfer standby and active
03434           float temp = tune;
03435           tune = stby;
03436           stby = temp;
03437         } else {
03438           // Transition back to FRQ mode
03439           frq = true;
03440           fltStored = flt;
03441           etStored = et;
03442           flt = et = false;
03443         }
03444         msg->result = rc = MSG_PROCESSED;
03445         break;
03446       case 'flt ':
03447         // Set FLT state
03448         flt = (msg->intData != 0);
03449         msg->result = rc = MSG_PROCESSED;
03450         break;
03451       case 'flt_':
03452         // FLT button press
03453         if (frq) {
03454           // FRQ mode was active; restore previous timer state
03455           flt = fltStored;
03456           et = etStored;
03457           frq = false;
03458         } else {
03459           // Toggle displayed timer
03460           if (flt) {
03461             flt = false;
03462             et = true;
03463           } else {
03464             flt = true;
03465             et = false;
03466           }
03467         }
03468         msg->result = rc = MSG_PROCESSED;
03469         break;
03470       case 'rset':
03471         // RESET button press
03472         etime = 0;
03473         msg->result = rc = MSG_PROCESSED;
03474         break;
03475       }
03476     case MSG_GETDATA:
03477       switch (msg->user.u.datatag) {
03478       case 'volu':
03479         // Volume
03480         msg->dataType = TYPE_REAL;
03481         msg->realData = volu;
03482         msg->result = rc = MSG_PROCESSED;
03483         break;
03484       case 'adf ':
03485       case 'iADF':
03486         // Get ADF flag
03487         msg->dataType = TYPE_INT;
03488         msg->intData = adf ? 1 : 0;
03489         msg->result = rc = MSG_PROCESSED;
03490         break;
03491       case 'bfo ':
03492       case 'iBFO':
03493         // Get BFO flag
03494         msg->dataType = TYPE_INT;
03495         msg->intData = bfo ? 1 : 0;
03496         msg->result = rc = MSG_PROCESSED;
03497         break;
03498       case 'frq ':
03499       case 'iFRQ':
03500         // Set FRQ flag
03501         msg->dataType = TYPE_INT;
03502         msg->intData = frq ? 1 : 0;
03503         msg->result = rc = MSG_PROCESSED;
03504         break;
03505       case 'flt ':
03506       case 'iFLT':
03507         // Set FLT flag
03508         msg->dataType = TYPE_INT;
03509         msg->intData = flt ? 1 : 0;
03510         msg->result = rc = MSG_PROCESSED;
03511         break;
03512       case 'iET_':
03513         // Set ET flag
03514         msg->dataType = TYPE_INT;
03515         msg->intData = et ? 1 : 0;
03516         msg->result = rc = MSG_PROCESSED;
03517         break;
03518       case 'ftim':
03519         // Return flight time
03520         msg->dataType = TYPE_INT;
03521         msg->intData = (int)(floorf(ftime));
03522         msg->result = rc = MSG_PROCESSED;
03523         break;
03524       case 'etim':
03525         // Return elapsed time
03526         msg->dataType = TYPE_INT;
03527         msg->intData = (int)(floorf(etime));
03528         msg->result = rc = MSG_PROCESSED;
03529         break;
03530       }
03531       break;
03532     }
03533 
03534     if (rc == MSG_IGNORED) {
03535       // See if the message can be processed by the parent class
03536       rc = CNavRadio::ReceiveMessage (msg);
03537     }
03538   }
03539 
03540   return rc;
03541 }
03542 
03543 void CADFRadio::TimeSlice (float dT)
03544 {
03545   // Call parent TimeSlice method
03546   CNavRadio::TimeSlice (dT);
03547 
03548   if (active) {
03549     // Update elapsed and flight timers, wrap around after 100 hours
03550     float wrap = 6000.0f;     // seconds in 100 hours
03551     ftime += dT;
03552     if (ftime >= wrap) ftime -= wrap;
03553     etime += dT;
03554     if (etime >= wrap) etime -= wrap;
03555   } else {
03556     // Radio is off, ensure timers are reset
03557     ftime = 0;
03558     etime = 0;
03559   }
03560 }
03561 
03562 
03563 //
03564 // CBKKX155Radio
03565 //
03566 CBKKX155Radio::CBKKX155Radio (void)
03567 {
03568   TypeIs (SUBSYSTEM_KX155_RADIO);
03569 
03570   // Initialize radio frequencies
03571   comA = 118.000;
03572   comS = 118.000;
03573   navA = 108.000;
03574   navS = 108.000;
03575 
03576   // Initialize OBS and navaid pointers
03577   obs = 0;
03578   navd = 0;
03579 
03580   navaidList = NULL;
03581   navaidTimer = 0;
03582   navaidTuned = NULL;
03583 
03584   // Initialize frequency step value
03585   comfractstep = .025;
03586 
03587   // Mode control
03588   comMode = COM_MODE_NORMAL;
03589   navMode = NAV_MODE_STANDBY;
03590 }
03591 
03592 CBKKX155Radio::~CBKKX155Radio (void)
03593 {
03594   if (navaidList != NULL) {
03595     FreeNavaid (navaidList);
03596   }
03597 }
03598 
03599 static float StepComFreq (float freq, float step)
03600 {
03601   // Convert frequency and step to MHz/KHz
03602   int freqMHz = (int)(floorf (freq));
03603   int freqKHz = (int)(floorf (fmodf (freq, 1.0f) * 1000 + 0.5));
03604 
03605   // Step may be negative, take into account with floating point functions
03606   int stepMHz, stepKHz;
03607   if (step > 0) {
03608     stepMHz = (int)(floorf (step));
03609     stepKHz = (int)(floorf (fmodf (step, 1.0f) * 1000 + 0.5));
03610   } else {
03611     stepMHz = (int)(ceilf (step));
03612     stepKHz = -(int)(floorf (fmodf (fabs(step), 1.0f) * 1000 + 0.5));
03613   }
03614 
03615   // Add step to MHz and wrap to standard COM frequency band
03616   freqMHz += stepMHz;
03617   if (freqMHz < 118) freqMHz += 19;
03618   if (freqMHz >= 137) freqMHz -= 19;
03619 
03620   // Add step to KHz
03621   freqKHz += stepKHz;
03622   if (freqKHz < 0) freqKHz += 1000;
03623   if (freqKHz >= 1000) freqKHz -= 1000;
03624 
03625   // Recombine new frequency into float for return value
03626   return (float)freqMHz + (float)freqKHz / 1000.0f;
03627 }
03628 
03629 static float StepNavFreq (float freq, float step)
03630 {
03631   // Convert frequency and step to MHz/KHz
03632   int freqMHz = (int)(floorf (freq));
03633   int freqKHz = (int)(floorf (fmodf (freq, 1.0f) * 1000 + 0.5));
03634 
03635   // Step may be negative, take into account with floating point functions
03636   int stepMHz, stepKHz;
03637   if (step > 0) {
03638     stepMHz = (int)(floorf (step));
03639     stepKHz = (int)(floorf (fmodf (step, 1.0f) * 1000 + 0.5));
03640   } else {
03641     stepMHz = (int)(ceilf (step));
03642     stepKHz = -(int)(floorf (fmodf (fabs(step), 1.0f) * 1000 + 0.5));
03643   }
03644 
03645   // Add step to MHz and wrap to standard COM frequency band
03646   freqMHz += stepMHz;
03647   if (freqMHz < 108) freqMHz += 10;
03648   if (freqMHz >= 118) freqMHz -= 10;
03649 
03650   // Add step to KHz
03651   freqKHz += stepKHz;
03652   if (freqKHz < 0) freqKHz += 1000;
03653   if (freqKHz >= 1000) freqKHz -= 1000;
03654 
03655   // Recombine new frequency into float for return value
03656   return (float)freqMHz + (float)freqKHz / 1000.0f;
03657 }
03658 
03659 EMessageResult CBKKX155Radio::ReceiveMessage (SMessage *msg)
03660 {
03661   EMessageResult rc = MSG_IGNORED;
03662 
03663   if (MsgForMe (msg)) {
03664     switch (msg->id) {
03665     case MSG_GETDATA:
03666       switch (msg->user.u.datatag) {
03667       case 'cmod':
03668         // COM mode
03669         msg->dataType = TYPE_INT;
03670         msg->intData = comMode;
03671         msg->result = rc = MSG_PROCESSED;
03672         break;
03673       case 'comA':
03674         msg->dataType = TYPE_REAL;
03675         msg->realData = comA;
03676         msg->result = rc = MSG_PROCESSED;
03677         break;
03678       case 'comS':
03679         msg->dataType = TYPE_REAL;
03680         msg->realData = comS;
03681         msg->result = rc = MSG_PROCESSED;
03682         break;
03683       case 'navA':
03684         msg->dataType = TYPE_REAL;
03685         msg->realData = navA;
03686         msg->result = rc = MSG_PROCESSED;
03687         break;
03688       case 'navS':
03689         msg->dataType = TYPE_REAL;
03690         msg->realData = navS;
03691         msg->result = rc = MSG_PROCESSED;
03692         break;
03693       case 'obs_':
03694         msg->dataType = TYPE_REAL;
03695         msg->realData = obs;
03696         msg->result = rc = MSG_PROCESSED;
03697         break;
03698       case 'navd':
03699         if (navaidTuned == NULL) {
03700           // No navaid tuned, set data type to VOID
03701           msg->dataType = TYPE_VOID;
03702         } else {
03703           msg->dataType = TYPE_REAL;
03704           msg->realData = navd;
03705         }
03706         msg->result = rc = MSG_PROCESSED;
03707         break;
03708       }
03709       break;
03710 
03711     case MSG_SETDATA:
03712       switch (msg->user.u.datatag) {
03713       case 'cmod':
03714         // COM mode
03715         switch (comMode) {
03716         case COM_MODE_NORMAL:
03717           comMode = COM_MODE_SELECT;
03718           break;
03719         case COM_MODE_SELECT:
03720         case COM_MODE_PROGRAM:
03721           comMode = COM_MODE_NORMAL;
03722           break;
03723         }
03724         msg->result = rc = MSG_PROCESSED;
03725         break;
03726       case 'incr':
03727         // Increment OBS setting
03728         obs = Wrap360 (obs + 1);
03729         msg->result = rc = MSG_PROCESSED;
03730         break;
03731       case 'decr':
03732         // Decrement OBS setting
03733         obs = Wrap360 (obs - 1);
03734         msg->result = rc = MSG_PROCESSED;
03735         break;
03736       case 'comA':
03737         // Set COM active frequency
03738         comA = msg->realData;
03739         msg->result = rc = MSG_PROCESSED;
03740         break;
03741       case 'comS':
03742         // Set COM standby frequency
03743         comS = msg->realData;
03744         msg->result = rc = MSG_PROCESSED;
03745         break;
03746       case 'navA':
03747         // Set NAV active frequency
03748         navA = msg->realData;
03749         msg->result = rc = MSG_PROCESSED;
03750         break;
03751       case 'navS':
03752         // Set NAV standby frequency
03753         navS = msg->realData;
03754         msg->result = rc = MSG_PROCESSED;
03755         break;
03756       case '25Kz':
03757         // Set COM fractional frequency step to 25 KHz
03758         comfractstep = .025;
03759         msg->result = rc = MSG_PROCESSED;
03760         break;
03761       case '50Kz':
03762         // Set COM fractional frequency step to 50 KHz
03763         comfractstep = .050;
03764         msg->result = rc = MSG_PROCESSED;
03765         break;
03766       case 'caw+':
03767         // Increment COM active frequency whole MHz
03768         comA = StepComFreq (comA, 1.0f);
03769         msg->result = rc = MSG_PROCESSED;
03770         break;
03771       case 'caw-':
03772         // Decrement COM active frequency whole MHz
03773         comA = StepComFreq (comA, -1.0f);
03774         msg->result = rc = MSG_PROCESSED;
03775         break;
03776       case 'caf+':
03777         // Increment COM active frequency fraction MHz
03778         comA = StepComFreq (comA, comfractstep);
03779         msg->result = rc = MSG_PROCESSED;
03780         break;
03781       case 'caf-':
03782         // Decrement COM active frequency fraction MHz
03783         comA = StepComFreq (comA, -comfractstep);
03784         msg->result = rc = MSG_PROCESSED;
03785         break;
03786       case 'naw+':
03787         // Increment NAV active frequency whole MHz
03788         navA = StepNavFreq (navA, 1.0f);
03789         msg->result = rc = MSG_PROCESSED;
03790         break;
03791       case 'naw-':
03792         // Decrement NAV active frequency whole MHz
03793         navA = StepNavFreq (navA, -1.0f);
03794         msg->result = rc = MSG_PROCESSED;
03795         break;
03796       case 'naf+':
03797         // Increment NAV active frequency fraction MHz
03798         navA = StepNavFreq (navA, 0.050f);
03799         msg->result = rc = MSG_PROCESSED;
03800         break;
03801       case 'naf-':
03802         // Decrement NAV active frequency fraction MHz
03803         navA = StepNavFreq (navA, -0.050f);
03804         msg->result = rc = MSG_PROCESSED;
03805         break;
03806       case 'csw+':
03807         // Increment COM standby frequency whole MHz
03808         comS = StepComFreq (comS, 1.0f);
03809         msg->result = rc = MSG_PROCESSED;
03810         break;
03811       case 'csw-':
03812         // Decrement COM standby frequency whole MHz
03813         comS = StepComFreq (comS, -1.0f);
03814         msg->result = rc = MSG_PROCESSED;
03815         break;
03816       case 'csf+':
03817         // Increment COM standby frequency fraction MHz
03818         comS = StepComFreq (comS, comfractstep);
03819         msg->result = rc = MSG_PROCESSED;
03820         break;
03821       case 'csf-':
03822         // Decrement COM standby frequency fraction MHz
03823         comS = StepComFreq (comS, -comfractstep);
03824         msg->result = rc = MSG_PROCESSED;
03825         break;
03826       case 'nsw+':
03827         // Increment NAV standby frequency whole MHz
03828         navS = StepNavFreq (navS, 1.0f);
03829         msg->result = rc = MSG_PROCESSED;
03830         break;
03831       case 'nsw-':
03832         // Decrement NAV standby frequency whole MHz
03833         navS = StepNavFreq (navS, -1.0f);
03834         msg->result = rc = MSG_PROCESSED;
03835         break;
03836       case 'nsf+':
03837         // Increment NAV standby frequency fraction MHz
03838         navS = StepNavFreq (navS, 0.050);
03839         msg->result = rc = MSG_PROCESSED;
03840         break;
03841       case 'nsf-':
03842         // Decrement NAV standby frequency fraction MHz
03843         navS = StepNavFreq (navS, -0.050);
03844         msg->result = rc = MSG_PROCESSED;
03845         break;
03846       case 'obs_':
03847         // Sets OBS value
03848         switch (msg->dataType) {
03849         case TYPE_REAL:
03850           // Set OBS to the supplied float value
03851           obs = msg->realData;
03852           msg->result = rc = MSG_PROCESSED;
03853           break;
03854         case TYPE_INT:
03855           // Set OBS to the supplied integer value
03856           obs = (float)(msg->intData);
03857           msg->result = rc = MSG_PROCESSED;
03858           break;
03859         default:
03860           // Invalid message data type
03861           gtfo ("CBKKX155Radio : Invalid data type for datatag 'obs_' : %d",
03862             msg->dataType);
03863         }
03864         break;
03865       }
03866     }
03867 
03868     if (rc == MSG_IGNORED) {
03869       // See if the message can be processed by the parent class
03870       rc = CRadio::ReceiveMessage (msg);
03871     }
03872   }
03873 
03874   return rc;
03875 }
03876 
03877 void CBKKX155Radio::RescanNavaids (void)
03878 {
03879   if (navaidList != NULL) {
03880     FreeNavaid (navaidList);
03881     navaidList = NULL;
03882   }
03883   GetLocalNavaids (&navaidList);
03884 
03885   // Search for tuned navaid
03886   navaidTuned = NULL;
03887   SNavaid *next = navaidList;
03888   while (next != NULL) {
03889     if ((next->freq == navA) && (next->type & NAVAID_TYPE_VOR)) {
03890       // Got a match
03892       navaidTuned = next;
03893       break;
03894     }
03895     next = next->next;
03896   }
03897 }
03898 
03899 void CBKKX155Radio::TimeSlice (float dT)
03900 {
03901   // Call parent TimeSlice method
03902   CRadio::TimeSlice (dT);
03903 
03904   if (active) {
03905     // Get list of local navaids periodically
03906     navaidTimer += dT;
03907     if (navaidTimer > 1.0f) {
03908       navaidTimer -= 1.0f;
03909       RescanNavaids ();
03910     }
03911 
03912     // Find tuned navaid
03913     if (navaidTuned != NULL) {
03914       SPosition pos = globals->sit->user->GetPosition();
03915       SVector v = GreatCirclePolar(&pos, &(navaidTuned->pos));
03916       navd = Wrap360(v.h);
03917 
03918 //      char debug[80];
03919 //      sprintf (debug, "hdg=%f range=%f", v.h, FeetToNm(v.r));
03920 //      DrawNoticeToUser (debug, 1);
03921 
03922     } else {
03923       // No navaid tuned, set pointer to 0
03924       navd = 0;
03925     }
03926   } else {
03927     // Set navaid pointer to zero
03928     navd = 0;
03929   }
03930 }
03931 
03932 
03933 //
03934 // CTransponderRadio
03935 //
03936 CTransponderRadio::CTransponderRadio (void)
03937 {
03938   TypeIs (SUBSYSTEM_TRANSPONDER_RADIO);
03939 
03940   mode = XPDR_STANDBY;
03941   smod = XPDR_SWITCH_STANDBY;
03942   prevActive = false;
03943   reply = false;
03944   replyTimer = 0;
03945 
03946   code = 1200;
03947 
03948   strcpy (airc, "");
03949   lspd = uspd = 0;
03950   memset (&mAlt, 0, sizeof(SMessage));
03951 }
03952 
03953 int CTransponderRadio::Read (SStream *stream, Tag tag)
03954 {
03955   int rc = TAG_IGNORED;
03956 
03957   switch (tag) {
03958   case 'mode':
03959     {
03960       int m = XPDR_OFF;
03961       ReadInt (&m, stream);
03962       mode = (ETransponderMode) m;
03963     }
03964     rc = TAG_READ;
03965     break;
03966   case 'smod':
03967     {
03968       int m = XPDR_SWITCH_OFF;
03969       ReadInt (&m, stream);
03970       smod = (ETransponderSwitchMode) m;
03971     }
03972     rc = TAG_READ;
03973     break;
03974   case 'airc':
03975     ReadString (airc, 16, stream);
03976     rc = TAG_READ;
03977     break;
03978   case 'lspd':
03979     // Lower airspeed limit
03980     ReadInt (&lspd, stream);
03981     rc = TAG_READ;
03982     break;
03983   case 'uspd':
03984     // Upper airspeed limit
03985     ReadInt (&uspd, stream);
03986     rc = TAG_READ;
03987     break;
03988   case 'mAlt':
03989     // Altitude message
03990     ReadMessage (&mAlt, stream);
03991     rc = TAG_READ;
03992     break;
03993   }
03994 
03995   if (rc != TAG_READ) {
03996     // See if the tag can be processed by the parent class type
03997     rc = CRadio::Read (stream, tag);
03998   }
03999 
04000   if (rc != TAG_READ) {
04001     // Tag could not be processed
04002     char s[16];
04003     TagToString (s, tag);
04004     globals->logWarning->Write ("CTransponderRadio::Read : Unrecognized tag <%s>", s);
04005   }
04006 
04007   return rc;
04008 }
04009 
04010 
04011 EMessageResult CTransponderRadio::ReceiveMessage (SMessage *msg)
04012 {
04013   EMessageResult rc = MSG_IGNORED;
04014 
04015   if (MsgForMe (msg)) {
04016     switch (msg->id) {
04017     case MSG_SETDATA:
04018       switch (msg->user.u.datatag) {
04019       case 'i11+':
04020         // Increment transponder code digit 1
04021         msg->result = rc = MSG_PROCESSED;
04022         break;
04023       case 'i11-':
04024         // Decrement transponder code digit 1
04025         msg->result = rc = MSG_PROCESSED;
04026         break;
04027       case 'i12+':
04028         // Increment transponder code digit 2
04029         msg->result = rc = MSG_PROCESSED;
04030         break;
04031       case 'i12-':
04032         // Decrement transponder code digit 2
04033         msg->result = rc = MSG_PROCESSED;
04034         break;
04035       case 'i13+':
04036         // Increment transponder code digit 3
04037         msg->result = rc = MSG_PROCESSED;
04038         break;
04039       case 'i13-':
04040         // Decrement transponder code digit 3
04041         msg->result = rc = MSG_PROCESSED;
04042         break;
04043       case 'i14+':
04044         // Increment transponder code digit 4
04045         msg->result = rc = MSG_PROCESSED;
04046         break;
04047       case 'i14-':
04048         // Decrement transponder code digit 4
04049         msg->result = rc = MSG_PROCESSED;
04050         break;
04051       case 'idt_':
04052         // Ident button
04053         msg->result = rc = MSG_PROCESSED;
04054         reply = true;
04055         replyTimer = 0;
04056         break;
04057       case 'mods':
04058         // Mode switch
04059         msg->result = rc = MSG_PROCESSED;
04060         break;
04061       case 'mode':
04062         // Operational mode
04063         msg->result = rc = MSG_PROCESSED;
04064         break;
04065       case 'mod+':
04066         // Increment operational mode
04067         msg->result = rc = MSG_PROCESSED;
04068         break;
04069       case 'mod-':
04070         // Decrement operational mode
04071         msg->result = rc = MSG_PROCESSED;
04072         break;
04073       case 'tune':
04074         // Set active frequency
04075         msg->result = rc = MSG_PROCESSED;
04076         break;
04077       case 'stby':
04078         // Set standby frequency
04079         msg->result = rc = MSG_PROCESSED;
04080         break;
04081       }
04082     case MSG_GETDATA:
04083       switch (msg->user.u.datatag) {
04084       case 'smod':
04085         // Mode switch state
04086         msg->dataType = TYPE_INT;
04087         msg->intData = smod;
04088         msg->result = rc = MSG_PROCESSED;
04089         break;
04090       case 'mode':
04091         // Get operational mode
04092         msg->dataType = TYPE_INT;
04093         msg->intData = mode;
04094         msg->result = rc = MSG_PROCESSED;
04095         break;
04096       case 'tune':
04097         // Get active transponder code
04098         msg->dataType = TYPE_INT;
04099         msg->intData = code;
04100         msg->result = rc = MSG_PROCESSED;
04101         break;
04102       case 'alti':
04103         // Get altitude
04104         msg->dataType = TYPE_INT;
04105         msg->intData = 0;
04106         msg->result = rc = MSG_PROCESSED;
04107         break;
04108       case 'on__':
04109         // Get On indicator status
04110         msg->dataType = TYPE_INT;
04111         msg->intData = (mode == XPDR_ON) || (mode == XPDR_TEST);
04112         msg->result = rc = MSG_PROCESSED;
04113         break;
04114       case 'sby_':
04115         // Get Standby indicator status
04116         msg->dataType = TYPE_INT;
04117         msg->intData = (mode == XPDR_STANDBY) || (mode == XPDR_TEST);
04118         msg->result = rc = MSG_PROCESSED;
04119         break;
04120       case 'rply':
04121         // Get Reply indicator status
04122         msg->dataType = TYPE_INT;
04123         msg->intData = reply || (mode == XPDR_TEST);
04124         msg->result = rc = MSG_PROCESSED;
04125         break;
04126       case 'alt_':
04127         // Get Altitude 
04128         msg->dataType = TYPE_INT;
04129         msg->intData = (mode == XPDR_ALT) || (mode == XPDR_TEST);
04130         msg->result = rc = MSG_PROCESSED;
04131         break;
04132       case 'fl__':
04133         // Get Flight Level indicator status
04134         msg->dataType = TYPE_INT;
04135         msg->intData = (mode == XPDR_ALT) || (mode == XPDR_TEST);
04136         msg->result = rc = MSG_PROCESSED;
04137         break;
04138       }
04139       break;
04140     }
04141 
04142     if (rc == MSG_IGNORED) {
04143       // See if the message can be processed by the parent class
04144       rc = CRadio::ReceiveMessage (msg);
04145     }
04146   }
04147 
04148   return rc;
04149 }
04150 
04151 void CTransponderRadio::TimeSlice (float dT)
04152 {
04153   // Call parent TimeSlice method
04154   CRadio::TimeSlice (dT);
04155 
04156   // Active status is dependent on operating mode not being OFF
04157   active &= (mode != XPDR_OFF);
04158 
04159   // Handle transitions from off, through startup modes
04160   if (active) {
04161     if (!prevActive) {
04162       // Power-on transition.  Initialize mode to A1, start timer
04163       mode = XPDR_STARTUPA1;
04164       startupTimer = 0;
04165       reply = true;
04166       replyTimer = 0;
04167     } else {
04168       // Not a power-on transition.  Check for transition through startup states
04169       startupTimer += dT;
04170       switch (mode) {
04171       case XPDR_STARTUPA1:
04172         // Check for transition to mode A2
04173         if (startupTimer > 4.0f) {
04174           mode = XPDR_STARTUPA2;
04175         }
04176         break;
04177       case XPDR_STARTUPA2:
04178         // Check for transition to selected switch mode
04179         if (startupTimer > 8.0f) {
04180           mode = (ETransponderMode) smod;
04181           reply = false;
04182         }
04183         break;
04184 
04185       default:
04186         // No timer-related operation required
04187         ;
04188       }
04189     }
04190 
04191     // Cancel reply timer after 18 seconds
04192     if (reply) {
04193       replyTimer += dT;
04194       if (replyTimer > 18.0f) {
04195         reply = false;
04196       }
04197     }
04198   }
04199 
04200   prevActive = active;
04201 }
04202 
04203 
04204 //
04205 // CBKKT76Radio
04206 //
04207 CBKKT76Radio::CBKKT76Radio (void)
04208 {
04209   TypeIs (SUBSYSTEM_KT76_RADIO);
04210 
04211   entryMode = false;
04212   strcpy (tempCode, "    ");
04213 }
04214 
04215 
04216 int CBKKT76Radio::Read (SStream *stream, Tag tag)
04217 {
04218   int rc = TAG_IGNORED;
04219 
04220   if (rc != TAG_READ) {
04221     // See if the tag can be processed by the parent class type
04222     rc = CTransponderRadio::Read (stream, tag);
04223   }
04224 
04225   if (rc != TAG_READ) {
04226     // Tag could not be processed
04227     char s[16];
04228     TagToString (s, tag);
04229     globals->logWarning->Write ("CBKKT76Radio::Read : Unrecognized tag <%s>", s);
04230   }
04231 
04232   return rc;
04233 }
04234 
04235 EMessageResult CBKKT76Radio::ReceiveMessage (SMessage *msg)
04236 {
04237   EMessageResult rc = MSG_IGNORED;
04238 
04239   if (MsgForMe (msg)) {
04240     int digit = '0';
04241     bool digitPressed = false;
04242 
04243     switch (msg->id) {
04244     case MSG_SETDATA:
04245       switch (msg->user.u.datatag) {
04246       case '___0':
04247         // Zero button
04248         digit = '0';
04249         digitPressed = true;
04250         msg->result = rc = MSG_PROCESSED;
04251         break;
04252       case '___1':
04253         // One button
04254         digit = '1';
04255         digitPressed = true;
04256         msg->result = rc = MSG_PROCESSED;
04257         break;
04258       case '___2':
04259         // Two button
04260         digit = '2';
04261         digitPressed = true;
04262         msg->result = rc = MSG_PROCESSED;
04263         break;
04264       case '___3':
04265         // Three button
04266         digit = '3';
04267         digitPressed = true;
04268         msg->result = rc = MSG_PROCESSED;
04269         break;
04270       case '___4':
04271         // Four button
04272         digit = '4';
04273         digitPressed = true;
04274         msg->result = rc = MSG_PROCESSED;
04275         break;
04276       case '___5':
04277         // Five button
04278         digit = '5';
04279         digitPressed = true;
04280         msg->result = rc = MSG_PROCESSED;
04281         break;
04282       case '___6':
04283         // Six button
04284         digit = '6';
04285         digitPressed = true;
04286         msg->result = rc = MSG_PROCESSED;
04287         break;
04288       case '___7':
04289         // Seven button
04290         digit = '7';
04291         digitPressed = true;
04292         msg->result = rc = MSG_PROCESSED;
04293         break;
04294       case 'clr_':
04295         // Clear button
04296         if (entryMode) {
04297           entryDigit--;
04298           tempCode[entryDigit] = ' ';
04299           if (entryDigit == 0) entryMode = false;
04300         }
04301         digitPressed = false;
04302         msg->result = rc = MSG_PROCESSED;
04303         break;
04304       case 'vfr_':
04305         // VFR button
04306         code = 1200;
04307         entryMode = false;
04308         digitPressed = false;
04309         msg->result = rc = MSG_PROCESSED;
04310         break;
04311       }
04312 
04313       if (digitPressed) {
04314         if (!entryMode) {
04315           // Transition to entry mode
04316           entryMode = true;
04317           entryDigit = 0;
04318           strcpy (tempCode, "    ");
04319         }
04320 
04321         // Check if entire code has been entered
04322         if (entryDigit == 3) {
04323           // Code entry complete
04324           int d0 = digit - '0';
04325           int d1 = tempCode[2] - '0';
04326           int d2 = tempCode[1] - '0';
04327           int d3 = tempCode[0] - '0';
04328           code = (d3 * 1000) + (d2 * 100) + (d1 * 10) + d0;
04329           entryMode = false;
04330         } else {
04331           // Store digit in temporary code storage
04332           tempCode[entryDigit] = digit;
04333           entryDigit++;
04334         }
04335         
04336         // Reset entry mode timer on every keypress
04337         entryTimer = 0;
04338       }
04339       break;
04340 
04341     case MSG_GETDATA:
04342       // Override getdata message for 'tune' to send code or partial code
04343       switch (msg->user.u.datatag) {
04344       case 'tune':
04345         if (entryMode) {
04346           // Return partially entered code as CHAR* data
04347           msg->dataType = TYPE_CHARPTR;
04348           msg->charPtrData = tempCode;
04349           msg->result = rc = MSG_PROCESSED;
04350         } else {
04351           // Return active transponder code as INT data
04352           msg->dataType = TYPE_INT;
04353           msg->intData = code;
04354           msg->result = rc = MSG_PROCESSED;
04355         }
04356         break;
04357       }
04358     }
04359 
04360     if (rc == MSG_IGNORED) {
04361       // See if the message can be processed by the parent class
04362       rc = CTransponderRadio::ReceiveMessage (msg);
04363     }
04364   }
04365 
04366   return rc;
04367 }
04368 
04369 void CBKKT76Radio::TimeSlice (float dT)
04370 {
04371   // Call parent class timeslice
04372   CTransponderRadio::TimeSlice (dT);
04373 
04374   // Transition back to idle state if four seconds have elapsed without keypress
04375   if (entryMode) {
04376     entryTimer += dT;
04377     if (entryTimer >= 4.0f) {
04378       entryMode = false;
04379     }
04380   }
04381 }
04382 
04383 //
04384 // CBKKLN89GPSRadio
04385 //
04386 CBKKLN89GPSRadio::CBKKLN89GPSRadio (void)
04387 {
04388   TypeIs (SUBSYSTEM_KLN89_GPS_RADIO);
04389 
04390   memset (&mFMS, 0, sizeof(SMessage));
04391   memset (&mSpd, 0, sizeof(SMessage));
04392 }
04393 
04394 
04395 int CBKKLN89GPSRadio::Read (SStream *stream, Tag tag)
04396 {
04397   int rc = TAG_IGNORED;
04398 
04399   switch (tag) {
04400   case 'mFMS':
04401     // FMS message
04402     ReadMessage (&mFMS, stream);
04403     rc = TAG_READ;
04404     break;
04405 
04406   case 'mSpd':
04407     // Airspeed message
04408     ReadMessage (&mSpd, stream);
04409     rc = TAG_READ;
04410     break;
04411   }
04412 
04413   if (rc != TAG_READ) {
04414     // See if the tag can be processed by the parent class type
04415     rc = CDependent::Read (stream, tag);
04416   }
04417 
04418   if (rc != TAG_READ) {
04419     // Tag could not be processed
04420     char s[16];
04421     TagToString (s, tag);
04422     globals->logWarning->Write ("CBKKLN89GPSRadio::Read : Unrecognized tag <%s>", s);
04423   }
04424 
04425   return rc;
04426 }
04427 
04428 
04429 void CBKKLN89GPSRadio::ReadFinished (void)
04430 {
04431   // Fill in common message fields
04432   mFMS.id = MSG_GETDATA;
04433   mSpd.id = MSG_GETDATA;
04434 
04435   CDependent::ReadFinished ();
04436 }
04437 
04438 
04439 //
04440 // CAudioPanelRadio
04441 //
04442 CAudioPanelRadio::CAudioPanelRadio (void)
04443 {
04444   TypeIs (SUBSYSTEM_AUDIO_PANEL_RADIO);
04445 }
04446 
04447 
04448 //
04449 // CBKKAP140Radio
04450 //
04451 CBKKAP140Radio::CBKKAP140Radio (void)
04452 {
04453   TypeIs (SUBSYSTEM_KAP140_RADIO);
04454 }
04455 
04456 
04457 // *
04458 // * Fuel subsystems defined in GAS file
04459 // *
04460 
04461 //
04462 // CFuelSubsystem
04463 //
04464 CFuelSubsystem::CFuelSubsystem (void)
04465 {
04466   TypeIs (SUBSYSTEM_FUEL_SUBSYSTEM);
04467 
04468   strcpy (name, "");
04469 }
04470 
04471 CFuelSubsystem::~CFuelSubsystem (void)
04472 {
04473 }
04474 
04475 int CFuelSubsystem::Read (SStream *stream, Tag tag)
04476 {
04477   int rc = TAG_IGNORED;
04478 
04479   switch (tag) {
04480   case 'name':
04481     // UI descriptive name
04482     ReadString (name, 64, stream);
04483     rc = TAG_READ;
04484     break;
04485 
04486   case 'pipe':
04487     // Fuel dependency tag
04488     {
04489       Tag t = 0;
04490       ReadTag (&t, stream);
04491       pipe.push_back (t);
04492     }
04493     rc = TAG_READ;
04494     break;
04495   }
04496 
04497   // If tag has not been processed, pass it to the parent
04498   if (rc != TAG_READ) {
04499     // See if the tag can be processed by the parent class type
04500     rc = CDependent::Read (stream, tag);
04501   }
04502 
04503   if (rc != TAG_READ) {
04504     // Tag was not processed by this object, it is unrecognized
04505     char s[16];
04506     TagToString (s, tag);
04507     globals->logWarning->Write ("CFuelSubsystem::Read : Unrecognized tag <%s>", s);
04508   }
04509 
04510   return rc;
04511 }
04512 
04513 
04514 //
04515 // CFuelTap
04516 //
04517 
04518 CFuelTap::CFuelTap (void)
04519 {
04520   TypeIs (SUBSYSTEM_FUEL_TAP);
04521 
04522   stff = 0;
04523   eNum = 1;
04524   gph = 0;
04525 }
04526 
04527 
04528 int CFuelTap::Read (SStream *stream, Tag tag)
04529 {
04530   int rc = TAG_IGNORED;
04531 
04532   switch (tag) {
04533   case 'stFF':
04534     // Initial fuel flow (gph)
04535     ReadFloat (&stff, stream);
04536     rc = TAG_READ;
04537     break;
04538 
04539   case 'eNum':
04540     // Engine number
04541     ReadUInt (&eNum, stream);
04542     rc = TAG_READ;
04543     break;
04544   }
04545 
04546   // If tag has not been processed, pass it to the parent
04547   if (rc != TAG_READ) {
04548     // See if the tag can be processed by the parent class type
04549     rc = CFuelSubsystem::Read (stream, tag);
04550   }
04551 
04552   if (rc != TAG_READ) {
04553     // Tag was not processed by this object, it is unrecognized
04554     char s[16];
04555     TagToString (s, tag);
04556     globals->logWarning->Write ("CFuelTap::Read : Unrecognized tag <%s>", s);
04557   }
04558 
04559   return rc;
04560 }
04561 
04562 void CFuelTap::ReadFinished (void)
04563 {
04564   gph = stff;
04565 }
04566 
04567 
04568 EMessageResult CFuelTap::ReceiveMessage (SMessage *msg)
04569 {
04570   EMessageResult rc = MSG_IGNORED;
04571 
04572   if (MsgForMe (msg)) {
04573     switch (msg->id) {
04574     case MSG_GETDATA:
04575       switch (msg->user.u.datatag) {
04576       case 'gph_':
04577         msg->dataType = TYPE_REAL;
04578         msg->realData = gph;
04579         msg->result = rc = MSG_PROCESSED;
04580         break;
04581       }
04582       break;
04583     }
04584 
04585     if (rc == MSG_IGNORED) {
04586       // See if the message can be processed by the parent class
04587       rc = CFuelSubsystem::ReceiveMessage (msg);
04588     }
04589   }
04590 
04591   return rc;
04592 }
04593 
04594 
04595 //
04596 // CFuelCell
04597 //
04598 CFuelCell::CFuelCell (void)
04599 {
04600   TypeIs (SUBSYSTEM_FUEL_CELL);
04601 
04602   qty = 0;
04603   cap = 0;
04604   bPos.x = bPos.y = bPos.z = 0;
04605   basP = 0;
04606   gals = 0;
04607 }
04608 
04609 int CFuelCell::Read (SStream *stream, Tag tag)
04610 {
04611   int rc = TAG_IGNORED;
04612 
04613   switch (tag) {
04614   case 'cap_':
04615     // Capacity (gallons)
04616     ReadFloat (&cap, stream);
04617     rc = TAG_READ;
04618     break;
04619 
04620   case 'qty_':
04621     // Default quantity
04622     ReadFloat (&qty, stream);
04623     rc = TAG_READ;
04624     break;
04625 
04626   case 'bPos':
04627     // Position relative to model center of gravity
04628     ReadVector (&bPos, stream);
04629     rc = TAG_READ;
04630     break;
04631 
04632   case 'basP':
04633     // Base pressure
04634     ReadFloat (&basP, stream);
04635     rc = TAG_READ;
04636     break;
04637   }
04638 
04639   // If tag has not been processed, pass it to the parent
04640   if (rc != TAG_READ) {
04641     // See if the tag can be processed by the parent class type
04642     rc = CFuelSubsystem::Read (stream, tag);
04643   }
04644 
04645   if (rc != TAG_READ) {
04646     // Tag was not processed by this object, it is unrecognized
04647     char s[16];
04648     TagToString (s, tag);
04649     globals->logWarning->Write ("CFuelCell::Read : Unrecognized tag <%s>", s);
04650   }
04651 
04652   return rc;
04653 }
04654 
04655 
04656 void CFuelCell::ReadFinished (void)
04657 {
04658   // Initialize fuel quantity to specified default
04659   gals = qty;
04660 
04661   CFuelSubsystem::ReadFinished ();
04662 }
04663 
04664 EMessageResult CFuelCell::ReceiveMessage (SMessage *msg)
04665 {
04666   EMessageResult rc = MSG_IGNORED;
04667 
04668   if (MsgForMe (msg)) {
04669     switch (msg->id) {
04670     case MSG_GETDATA:
04671       switch (msg->user.u.datatag) {
04672       case 'gals':
04673       case 'fqty':
04674         // Return fuel quantity in gallons
04675         msg->dataType = TYPE_REAL;
04676         msg->realData = gals;
04677         msg->result = rc = MSG_PROCESSED;
04678         break;
04679       }
04680       break;
04681 
04682     case MSG_SETDATA:
04683       switch (msg->user.u.datatag) {
04684       case 'gals':
04685       case 'fqty':
04686         // Set fuel quantity in gallons
04687         if (msg->dataType == TYPE_REAL) {
04688           gals = msg->realData;
04689           msg->result = rc = MSG_PROCESSED;
04690         }
04691         break;
04692       }
04693       break;
04694     }
04695 
04696     if (rc == MSG_IGNORED) {
04697       // See if the message can be processed by the parent class
04698       rc = CFuelSubsystem::ReceiveMessage (msg);
04699     }
04700   }
04701 
04702   return rc;
04703 }
04704 
04705 
04706 //
04707 // CFuelHeater
04708 //
04709 
04710 CFuelHeater::CFuelHeater (void)
04711 {
04712   TypeIs (SUBSYSTEM_FUEL_HEATER);
04713 }
04714 
04715 
04716 int CFuelHeater::Read (SStream *stream, Tag tag)
04717 {
04718   int rc = TAG_IGNORED;
04719 
04720   // If tag has not been processed, pass it to the parent
04721   if (rc != TAG_READ) {
04722     // See if the tag can be processed by the parent class type
04723     rc = CFuelSubsystem::Read (stream, tag);
04724   }
04725 
04726   if (rc != TAG_READ) {
04727     // Tag was not processed by this object, it is unrecognized
04728     char s[16];
04729     TagToString (s, tag);
04730     globals->logWarning->Write ("CFuelHeater::Read : Unrecognized tag <%s>", s);
04731   }
04732 
04733   return rc;
04734 }
04735 
04736 
04737 //
04738 // CFuelMath
04739 //
04740 
04741 CFuelMath::CFuelMath (void)
04742 {
04743   TypeIs (SUBSYSTEM_FUEL_MATH);
04744 }
04745 
04746 
04747 int CFuelMath::Read (SStream *stream, Tag tag)
04748 {
04749   int rc = TAG_IGNORED;
04750 
04751   // If tag has not been processed, pass it to the parent
04752   if (rc != TAG_READ) {
04753     // See if the tag can be processed by the parent class type
04754     rc = CFuelSubsystem::Read (stream, tag);
04755   }
04756 
04757   if (rc != TAG_READ) {
04758     // Tag was not processed by this object, it is unrecognized
04759     char s[16];
04760     TagToString (s, tag);
04761     globals->logWarning->Write ("CFuelMath::Read : Unrecognized tag <%s>", s);
04762   }
04763 
04764   return rc;
04765 }
04766 
04767 
04768 //
04769 // CFuelPump
04770 //
04771 
04772 CFuelPump::CFuelPump (void)
04773 {
04774   TypeIs (SUBSYSTEM_FUEL_PUMP);
04775 
04776   setP = 0;
04777   pass = false;
04778 }
04779 
04780 
04781 int CFuelPump::Read (SStream *stream, Tag tag)
04782 {
04783   int rc = TAG_IGNORED;
04784 
04785   switch (tag) {
04786   case 'setP':
04787     // Pump pressure
04788     ReadFloat (&setP, stream);
04789     rc = TAG_READ;
04790     break;
04791 
04792   case 'pass':
04793     // Passthrough allowed when system is off
04794     pass = true;
04795     rc = TAG_READ;
04796     break;
04797   }
04798 
04799   // If tag has not been processed, pass it to the parent
04800   if (rc != TAG_READ) {
04801     // See if the tag can be processed by the parent class type
04802     rc = CFuelSubsystem::Read (stream, tag);
04803   }
04804 
04805   if (rc != TAG_READ) {
04806     // Tag was not processed by this object, it is unrecognized
04807     char s[16];
04808     TagToString (s, tag);
04809     globals->logWarning->Write ("CFuelPumper::Read : Unrecognized tag <%s>", s);
04810   }
04811 
04812   return rc;
04813 }
04814 
04815 
04816 //
04817 // CFuelSource
04818 //
04819 
04820 CFuelSource::CFuelSource (void)
04821 {
04822   TypeIs (SUBSYSTEM_FUEL_SOURCE);
04823 }
04824 
04825 
04826 int CFuelSource::Read (SStream *stream, Tag tag)
04827 {
04828   int rc = TAG_IGNORED;
04829 
04830   // If tag has not been processed, pass it to the parent
04831   if (rc != TAG_READ) {
04832     // See if the tag can be processed by the parent class type
04833     rc = CFuelSubsystem::Read (stream, tag);
04834   }
04835 
04836   if (rc != TAG_READ) {
04837     // Tag was not processed by this object, it is unrecognized
04838     char s[16];
04839     TagToString (s, tag);
04840     globals->logWarning->Write ("CFuelSource::Read : Unrecognized tag <%s>", s);
04841   }
04842 
04843   return rc;
04844 }
04845 
04846 
04847 //
04848 // CFuelTank
04849 //
04850 
04851 CFuelTank::CFuelTank (void)
04852 {
04853   TypeIs (SUBSYSTEM_FUEL_TANK);
04854 }
04855 
04856 
04857 int CFuelTank::Read (SStream *stream, Tag tag)
04858 {
04859   int rc = TAG_IGNORED;
04860 
04861   // If tag has not been processed, pass it to the parent
04862   if (rc != TAG_READ) {
04863     // See if the tag can be processed by the parent class type
04864     rc = CFuelSubsystem::Read (stream, tag);
04865   }
04866 
04867   if (rc != TAG_READ) {
04868     // Tag was not processed by this object, it is unrecognized
04869     char s[16];
04870     TagToString (s, tag);
04871     globals->logWarning->Write ("CFuelTank::Read : Unrecognized tag <%s>", s);
04872   }
04873 
04874   return rc;
04875 }
04876 
04877 
04878 //
04879 // CEngineFuelPump
04880 //
04881 
04882 CEngineFuelPump::CEngineFuelPump (void)
04883 {
04884   TypeIs (SUBSYSTEM_ENGINE_FUEL_PUMP);
04885 }
04886 
04887 
04888 int CEngineFuelPump::Read (SStream *stream, Tag tag)
04889 {
04890   int rc = TAG_IGNORED;
04891 
04892   // If tag has not been processed, pass it to the parent
04893   if (rc != TAG_READ) {
04894     // See if the tag can be processed by the parent class type
04895     rc = CFuelSubsystem::Read (stream, tag);
04896   }
04897 
04898   if (rc != TAG_READ) {
04899     // Tag was not processed by this object, it is unrecognized
04900     char s[16];
04901     TagToString (s, tag);
04902     globals->logWarning->Write ("CEngineFuelPump::Read : Unrecognized tag <%s>", s);
04903   }
04904 
04905   return rc;
04906 }
04907 
04908 
04909 //
04910 // CFuelManagement
04911 //
04912 
04913 CFuelManagement::CFuelManagement (void)
04914 {
04915   TypeIs (SUBSYSTEM_FUEL_MANAGEMENT);
04916 }
04917 
04918 
04919 int CFuelManagement::Read (SStream *stream, Tag tag)
04920 {
04921   int rc = TAG_IGNORED;
04922 
04923   // If tag has not been processed, pass it to the parent
04924   if (rc != TAG_READ) {
04925     // See if the tag can be processed by the parent class type
04926     rc = CFuelSubsystem::Read (stream, tag);
04927   }
04928 
04929   if (rc != TAG_READ) {
04930     // Tag was not processed by this object, it is unrecognized
04931     char s[16];
04932     TagToString (s, tag);
04933     globals->logWarning->Write ("CFuelMnagement::Read : Unrecognized tag <%s>", s);
04934   }
04935 
04936   return rc;
04937 }
04938 
04939 
04940 //
04941 // CAPUFuelSource
04942 //
04943 
04944 CAPUFuelSource::CAPUFuelSource (void)
04945 {
04946   TypeIs (SUBSYSTEM_APU_FUEL_SOURCE);
04947 }
04948 
04949 
04950 int CAPUFuelSource::Read (SStream *stream, Tag tag)
04951 {
04952   int rc = TAG_IGNORED;
04953 
04954   // If tag has not been processed, pass it to the parent
04955   if (rc != TAG_READ) {
04956     // See if the tag can be processed by the parent class type
04957     rc = CFuelSubsystem::Read (stream, tag);
04958   }
04959 
04960   if (rc != TAG_READ) {
04961     // Tag was not processed by this object, it is unrecognized
04962     char s[16];
04963     TagToString (s, tag);
04964     globals->logWarning->Write ("CAPUFuelSource::Read : Unrecognized tag <%s>", s);
04965   }
04966 
04967   return rc;
04968 }
04969 
04970 
04971 
04972 // ***
04973 // *** End of actively developed subsystems
04974 // ***
04975 
04976 
04977 /*
04978 
04979 
04980 
04981 //
04982 // COnGroundMonitor
04983 //
04984 
04985 COnGroundMonitor::COnGroundMonitor (void)
04986 {
04987   type = SUBSYSTEM_ON_GROUND_MONITOR;
04988   TagToString (type_string, type);
04989 }
04990 
04991 
04992 
04993 //
04994 // CAltitudeMonitor
04995 //
04996 
04997 CAltitudeMonitor::CAltitudeMonitor (void)
04998 {
04999 }
05000 
05001 
05002 int CAltitudeMonitor::Read (SStream *stream, Tag tag)
05003 {
05004   int rc = TAG_IGNORED;
05005 
05006   if (rc != TAG_READ) {
05007     // See if the tag can be processed by the parent class type
05008     rc = CSubsystem::Read (stream, tag);
05009   }
05010 
05011   if (rc != TAG_READ) {
05012     // Tag could not be processed
05013     char s[16];
05014     TagToString (s, tag);
05015     globals->logWarning->Write ("CAltitudeMonitor::Read : Unrecognized tag <%s>", s);
05016   }
05017 
05018   return rc;
05019 }
05020 
05021 
05022 void CAltitudeMonitor::ReadFinished (void)
05023 {
05024 
05025 }
05026 
05027 
05028 void CAltitudeMonitor::Write (SStream *stream)
05029 {
05030 
05031 }
05032 
05033 
05034 //
05035 // CSpeedMonitor
05036 //
05037 
05038 CSpeedMonitor::CSpeedMonitor (void)
05039 {
05040 }
05041 
05042 
05043 int CSpeedMonitor::Read (SStream *stream, Tag tag)
05044 {
05045   int rc = TAG_IGNORED;
05046 
05047   if (rc != TAG_READ) {
05048     // See if the tag can be processed by the parent class type
05049     rc = CSubsystem::Read (stream, tag);
05050   }
05051 
05052   if (rc != TAG_READ) {
05053     // Tag could not be processed
05054     char s[16];
05055     TagToString (s, tag);
05056     globals->logWarning->Write ("CSpeedMonitor::Read : Unrecognized tag <%s>", s);
05057   }
05058 
05059   return rc;
05060 }
05061 
05062 
05063 void CSpeedMonitor::ReadFinished (void)
05064 {
05065 
05066 }
05067 
05068 
05069 void CSpeedMonitor::Write (SStream *stream)
05070 {
05071 
05072 }
05073 
05074 
05075 //
05076 // CEngineStatus
05077 //
05078 
05079 CEngineStatus::CEngineStatus (void)
05080 {
05081 }
05082 
05083 
05084 int CEngineStatus::Read (SStream *stream, Tag tag)
05085 {
05086   int rc = TAG_IGNORED;
05087 
05088   if (rc != TAG_READ) {
05089     // See if the tag can be processed by the parent class type
05090     rc = CSubsystem::Read (stream, tag);
05091   }
05092 
05093   if (rc != TAG_READ) {
05094     // Tag could not be processed
05095     char s[16];
05096     TagToString (s, tag);
05097     globals->logWarning->Write ("CEngineStatus::Read : Unrecognized tag <%s>", s);
05098   }
05099 
05100   return rc;
05101 }
05102 
05103 
05104 void CEngineStatus::ReadFinished (void)
05105 {
05106 
05107 }
05108 
05109 
05110 void CEngineStatus::Write (SStream *stream)
05111 {
05112 
05113 }
05114 
05115 
05116 //
05117 // CTimeDelay
05118 //
05119 
05120 CTimeDelay::CTimeDelay (void)
05121 {
05122 }
05123 
05124 
05125 int CTimeDelay::Read (SStream *stream, Tag tag)
05126 {
05127   int rc = TAG_IGNORED;
05128 
05129   if (rc != TAG_READ) {
05130     // See if the tag can be processed by the parent class type
05131     rc = CSubsystem::Read (stream, tag);
05132   }
05133 
05134   if (rc != TAG_READ) {
05135     // Tag could not be processed
05136     char s[16];
05137     TagToString (s, tag);
05138     globals->logWarning->Write ("CTimeDelay::Read : Unrecognized tag <%s>", s);
05139   }
05140 
05141   return rc;
05142 }
05143 
05144 
05145 void CTimeDelay::ReadFinished (void)
05146 {
05147 
05148 }
05149 
05150 
05151 void CTimeDelay::Write (SStream *stream)
05152 {
05153 
05154 }
05155 
05156 
05157 //
05158 // CKeyedSystem
05159 //
05160 
05161 CKeyedSystem::CKeyedSystem (void)
05162 {
05163 }
05164 
05165 
05166 int CKeyedSystem::Read (SStream *stream, Tag tag)
05167 {
05168   int rc = TAG_IGNORED;
05169 
05170   if (rc != TAG_READ) {
05171     // See if the tag can be processed by the parent class type
05172     rc = CSubsystem::Read (stream, tag);
05173   }
05174 
05175   if (rc != TAG_READ) {
05176     // Tag could not be processed
05177     char s[16];
05178     TagToString (s, tag);
05179     globals->logWarning->Write ("CKeyedSystem::Read : Unrecognized tag <%s>", s);
05180   }
05181 
05182   return rc;
05183 }
05184 
05185 
05186 void CKeyedSystem::ReadFinished (void)
05187 {
05188 
05189 }
05190 
05191 
05192 void CKeyedSystem::Write (SStream *stream)
05193 {
05194 
05195 }
05196 
05197 
05198 //
05199 // CEngineSubsystem
05200 //
05201 
05202 CEngineSubsystem::CEngineSubsystem (void)
05203 {
05204 }
05205 
05206 int CEngineSubsystem::Read (SStream *stream, Tag tag)
05207 {
05208   int rc = TAG_IGNORED;
05209 
05210   if (rc != TAG_READ) {
05211     // See if the tag can be processed by the parent class type
05212     rc = CSubsystem::Read (stream, tag);
05213   }
05214 
05215   if (rc != TAG_READ) {
05216     // Tag could not be processed
05217     char s[16];
05218     TagToString (s, tag);
05219     globals->logWarning->Write ("CEngineSubystem::Read : Unrecognized tag <%s>", s);
05220   }
05221 
05222   return rc;
05223 }
05224 
05225 void CEngineSubsystem::ReadFinished (void)
05226 {
05227 
05228 }
05229 
05230 void CEngineSubsystem::Write (SStream *stream)
05231 {
05232 
05233 }
05234 
05235 
05236 //
05237 // CTachometerBase
05238 //
05239 
05240 CTachometerBase::CTachometerBase (void)
05241 {
05242 }
05243 
05244 int CTachometerBase::Read (SStream *stream, Tag tag)
05245 {
05246   int rc = TAG_IGNORED;
05247 
05248   if (rc != TAG_READ) {
05249     // See if the tag can be processed by the parent class type
05250     rc = CSubsystem::Read (stream, tag);
05251   }
05252 
05253   if (rc != TAG_READ) {
05254     // Tag could not be processed
05255     char s[16];
05256     TagToString (s, tag);
05257     globals->logWarning->Write ("CTachometerBase::Read : Unrecognized tag <%s>", s);
05258   }
05259 
05260   return rc;
05261 }
05262 
05263 void CTachometerBase::ReadFinished (void)
05264 {
05265 
05266 }
05267 
05268 void CTachometerBase::Write (SStream *stream)
05269 {
05270 
05271 }
05272 
05273 
05274 //
05275 // CTachometerV1
05276 //
05277 
05278 CTachometerV1::CTachometerV1 (void)
05279 {
05280 }
05281 
05282 
05283 int CTachometerV1::Read (SStream *stream, Tag tag)
05284 {
05285   int rc = TAG_IGNORED;
05286 
05287   if (rc != TAG_READ) {
05288     // See if the tag can be processed by the parent class type
05289     rc = CSubsystem::Read (stream, tag);
05290   }
05291 
05292   if (rc != TAG_READ) {
05293     // Tag could not be processed
05294     char s[16];
05295     TagToString (s, tag);
05296     globals->logWarning->Write ("CTachometerV1::Read : Unrecognized tag <%s>", s);
05297   }
05298 
05299   return rc;
05300 }
05301 
05302 
05303 void CTachometerV1::ReadFinished (void)
05304 {
05305 
05306 }
05307 
05308 
05309 void CTachometerV1::Write (SStream *stream)
05310 {
05311 
05312 }
05313 
05314 
05315 //
05316 // CEngineControl
05317 //
05318 
05319 CEngineControl::CEngineControl (void)
05320 {
05321 }
05322 
05323 int CEngineControl::Read (SStream *stream, Tag tag)
05324 {
05325   int rc = TAG_IGNORED;
05326 
05327   if (rc != TAG_READ) {
05328     // See if the tag can be processed by the parent class type
05329     rc = CSubsystem::Read (stream, tag);
05330   }
05331 
05332   if (rc != TAG_READ) {
05333     // Tag could not be processed
05334     char s[16];
05335     TagToString (s, tag);
05336     globals->logWarning->Write ("CEngineControl::Read : Unrecognized tag <%s>", s);
05337   }
05338 
05339   return rc;
05340 }
05341 
05342 void CEngineControl::ReadFinished (void)
05343 {
05344 
05345 }
05346 
05347 void CEngineControl::Write (SStream *stream)
05348 {
05349 
05350 }
05351 
05352 
05353 //
05354 // CThrottleControlV1
05355 //
05356 
05357 CThrottleControlV1::CThrottleControlV1 (void)
05358 {
05359 }
05360 
05361 
05362 int CThrottleControlV1::Read (SStream *stream, Tag tag)
05363 {
05364   int rc = TAG_IGNORED;
05365 
05366   if (rc != TAG_READ) {
05367     // See if the tag can be processed by the parent class type
05368     rc = CSubsystem::Read (stream, tag);
05369   }
05370 
05371   if (rc != TAG_READ) {
05372     // Tag could not be processed
05373     char s[16];
05374     TagToString (s, tag);
05375     globals->logWarning->Write ("CThrottleControlV1::Read : Unrecognized tag <%s>", s);
05376   }
05377 
05378   return rc;
05379 }
05380 
05381 
05382 void CThrottleControlV1::ReadFinished (void)
05383 {
05384 
05385 }
05386 
05387 
05388 void CThrottleControlV1::Write (SStream *stream)
05389 {
05390 
05391 }
05392 
05393 
05394 //
05395 // CMixtureControlBase
05396 //
05397 
05398 CMixtureControlBase::CMixtureControlBase (void)
05399 {
05400 }
05401 
05402 int CMixtureControlBase::Read (SStream *stream, Tag tag)
05403 {
05404   int rc = TAG_IGNORED;
05405 
05406   if (rc != TAG_READ) {
05407     // See if the tag can be processed by the parent class type
05408     rc = CSubsystem::Read (stream, tag);
05409   }
05410 
05411   if (rc != TAG_READ) {
05412     // Tag could not be processed
05413     char s[16];
05414     TagToString (s, tag);
05415     globals->logWarning->Write ("CMixtureControlBase::Read : Unrecognized tag <%s>", s);
05416   }
05417 
05418   return rc;
05419 }
05420 
05421 void CMixtureControlBase::ReadFinished (void)
05422 {
05423 
05424 }
05425 
05426 void CMixtureControlBase::Write (SStream *stream)
05427 {
05428 
05429 }
05430 
05431 
05432 //
05433 // CMixtureControlV1
05434 //
05435 
05436 CMixtureControlV1::CMixtureControlV1 (void)
05437 {
05438 }
05439 
05440 
05441 int CMixtureControlV1::Read (SStream *stream, Tag tag)
05442 {
05443   int rc = TAG_IGNORED;
05444 
05445   if (rc != TAG_READ) {
05446     // See if the tag can be processed by the parent class type
05447     rc = CSubsystem::Read (stream, tag);
05448   }
05449 
05450   if (rc != TAG_READ) {
05451     // Tag could not be processed
05452     char s[16];
05453     TagToString (s, tag);
05454     globals->logWarning->Write ("CMixtureControlV1::Read : Unrecognized tag <%s>", s);
05455   }
05456 
05457   return rc;
05458 }
05459 
05460 
05461 void CMixtureControlV1::ReadFinished (void)
05462 {
05463 
05464 }
05465 
05466 
05467 void CMixtureControlV1::Write (SStream *stream)
05468 {
05469 
05470 }
05471 
05472 
05473 //
05474 // CPropellerControlV1
05475 //
05476 
05477 CPropellerControlV1::CPropellerControlV1 (void)
05478 {
05479 }
05480 
05481 
05482 int CPropellerControlV1::Read (SStream *stream, Tag tag)
05483 {
05484   int rc = TAG_IGNORED;
05485 
05486   if (rc != TAG_READ) {
05487     // See if the tag can be processed by the parent class type
05488     rc = CSubsystem::Read (stream, tag);
05489   }
05490 
05491   if (rc != TAG_READ) {
05492     // Tag could not be processed
05493     char s[16];
05494     TagToString (s, tag);
05495     globals->logWarning->Write ("CPropellerControlV1::Read : Unrecognized tag <%s>", s);
05496   }
05497 
05498   return rc;
05499 }
05500 
05501 
05502 void CPropellerControlV1::ReadFinished (void)
05503 {
05504 
05505 }
05506 
05507 
05508 void CPropellerControlV1::Write (SStream *stream)
05509 {
05510 
05511 }
05512 
05513 
05514 //
05515 // CPrimeControlV1
05516 //
05517 
05518 CPrimeControlV1::CPrimeControlV1 (void)
05519 {
05520 }
05521 
05522 
05523 int CPrimeControlV1::Read (SStream *stream, Tag tag)
05524 {
05525   int rc = TAG_IGNORED;
05526 
05527   if (rc != TAG_READ) {
05528     // See if the tag can be processed by the parent class type
05529     rc = CSubsystem::Read (stream, tag);
05530   }
05531 
05532   if (rc != TAG_READ) {
05533     // Tag could not be processed
05534     char s[16];
05535     TagToString (s, tag);
05536     globals->logWarning->Write ("CPrimeControlV1::Read : Unrecognized tag <%s>", s);
05537   }
05538 
05539   return rc;
05540 }
05541 
05542 
05543 void CPrimeControlV1::ReadFinished (void)
05544 {
05545 
05546 }
05547 
05548 
05549 void CPrimeControlV1::Write (SStream *stream)
05550 {
05551 
05552 }
05553 
05554 
05555 */
05556 
05557 
05558 //
05559 // CPitotStaticPort
05560 //
05561 
05562 
05563 CPitotStaticPort::CPitotStaticPort (void)
05564 {
05565   // Initialize
05566   type = PORT_STATIC;
05567   bPos.x = 0;   bPos.y = 0;   bPos.z = 0;
05568   grup = 1;
05569   face = PORT_LEFT;
05570   inie = false;
05571   wont = false;
05572 }
05573 
05574 int CPitotStaticPort::Read (SStream *stream, Tag tag)
05575 {
05576   int rc = TAG_IGNORED;
05577 
05578   switch (tag) {
05579   case 'type':
05580     {
05581       // Type of port, PITOT or STATIC
05582       char sType[64];
05583       ReadString (sType, 64, stream);
05584       if (stricmp (sType, "PITOT") == 0) {
05585         type = PORT_PITOT;
05586       } else if (stricmp (sType, "STATIC") == 0) {
05587         type = PORT_STATIC;
05588       }
05589       rc = TAG_READ;
05590     }
05591     break;
05592 
05593   case 'bPos':
05594     {
05595       // Port position relative to aircraft external model center
05596       ReadVector (&bPos, stream);
05597       rc = TAG_READ;
05598     }
05599     break;
05600 
05601   case 'grup':
05602     {
05603       // Group number
05604       ReadInt (&grup, stream);
05605       rc = TAG_READ;
05606     }
05607     break;
05608 
05609   case 'face':
05610     {
05611       // Which side of aircraft the port is on, LEFT or RIGHT
05612       char sFace[64];
05613       ReadString (sFace, 64, stream);
05614       if (stricmp (sFace, "LEFT") == 0) {
05615         face = PORT_LEFT;
05616       } else if (stricmp (sFace, "RIGHT") == 0) {
05617         face = PORT_RIGHT;
05618       }
05619       rc = TAG_READ;
05620     }
05621     break;
05622 
05623   case 'inie':
05624     // No arguments, if this tag is present then the port is interior
05625     inie = true;
05626     rc = TAG_READ;
05627     break;
05628 
05629   case 'wont':
05630     // No arguments, if this tag is present then the port will not ice
05631     wont = true;
05632     rc = TAG_READ;
05633     break;
05634   }
05635 
05636   // If tag has not been processed, pass it to the parent
05637   if (rc != TAG_READ) {
05638     // See if the tag can be processed by the parent class type
05639     rc = CDependent::Read (stream, tag);
05640   }
05641 
05642   if (rc != TAG_READ) {
05643     // Tag was not processed by this object, it is unrecognized
05644     char s[16];
05645     TagToString (s, tag);
05646     globals->logWarning->Write ("CPitotStaticPort::Read : Unrecognized tag <%s>", s);
05647   }
05648 
05649   return rc;
05650 }
05651 
05652 
05653 void CPitotStaticPort::ReadFinished (void)
05654 {
05655   CDependent::ReadFinished ();
05656 }
05657 
05658 
05659 void CPitotStaticPort::Write (SStream *stream)
05660 {
05661 
05662 }
05663 
05664 
SourceForge.net Logo Documentation generated by doxygen