Index: src/mlx/acft.py
===================================================================
--- src/mlx/acft.py	(revision 317)
+++ src/mlx/acft.py	(revision 321)
@@ -83,9 +83,15 @@
 
         self._checkers.append(checks.AltimeterLogger())
+
+        self._nav1Logger = checks.NAV1Logger()
+        self._checkers.append(self._nav1Logger)
+        self._nav2Logger = checks.NAV2Logger()
+        self._checkers.append(self._nav2Logger)
+
+        self._adf1Logger = checks.ADF1Logger()
+        self._checkers.append(self._adf1Logger)
+        self._adf2Logger = checks.ADF2Logger()
+        self._checkers.append(self._adf2Logger)
         
-        self._checkers.append(checks.NAV1Logger())
-        self._checkers.append(checks.NAV2Logger())
-        self._checkers.append(checks.ADF1Logger())
-        self._checkers.append(checks.ADF2Logger())
         self._checkers.append(checks.SquawkLogger())
 
@@ -248,5 +254,8 @@
                                     (aircraftState.windDirection, 
                                      aircraftState.windSpeed))
+                self._logRadios(aircraftState)
                 self._logV1R2()
+            elif newStage==const.STAGE_DESCENT or newStage==const.STAGE_LANDING:
+                self._logRadios(aircraftState)
             elif newStage==const.STAGE_TAXIAFTERLAND:
                 flight = self._flight
@@ -427,4 +436,15 @@
         
 
+    def _logRadios(self, aircraftState):
+        """Log the radios from the given aircraft state."""
+        flight = self._flight
+        logger = flight.logger
+
+        self._nav1Logger.forceLog(flight, logger, aircraftState)
+        self._nav2Logger.forceLog(flight, logger, aircraftState)
+
+        self._adf1Logger.logState(flight, logger, aircraftState)
+        self._adf2Logger.logState(flight, logger, aircraftState)
+
 #---------------------------------------------------------------------------------------
 
Index: src/mlx/checks.py
===================================================================
--- src/mlx/checks.py	(revision 320)
+++ src/mlx/checks.py	(revision 321)
@@ -270,6 +270,6 @@
         - _changed(self, oldState, state): returns a boolean indicating if the
         value has changed or not
-        - _getMessage(self, flight, state): return a strings containing the
-        message to log with the new value
+        - _getMessage(self, flight, state, forced): return a strings containing
+        the message to log with the new value
         """
         self._logInitial = logInitial    
@@ -288,7 +288,11 @@
         
         if shouldLog:
-            message = self._getMessage(flight, state)
-            if message is not None:
-                logger.message(self._getLogTimestamp(state), message)
+            self.logState(flight, logger, state)
+
+    def logState(self, flight, logger, state, forced = False):
+        """Log the state."""
+        message = self._getMessage(flight, state, forced)
+        if message is not None:
+            logger.message(self._getLogTimestamp(state), message)
         
 #-------------------------------------------------------------------------------
@@ -340,5 +344,5 @@
             
         newValue = self._getValue(state)
-        if self._oldValue!=newValue:
+        if self._isDifferent(self._oldValue, newValue):
             if self._firstChange is None:
                 self._firstChange = state.timestamp
@@ -359,4 +363,10 @@
                self._lastChangeState is not None else state.timestamp
 
+    def _isDifferent(self, oldValue, newValue):
+        """Determine if the given values are different.
+
+        This default implementation checks for simple equality."""
+        return oldValue!=newValue
+
 #---------------------------------------------------------------------------------------
 
@@ -370,5 +380,5 @@
         self._template = template
 
-    def _getMessage(self, flight, state):
+    def _getMessage(self, flight, state, forced):
         """Get the message."""
         value = self._getValue(state)        
@@ -393,4 +403,42 @@
 #---------------------------------------------------------------------------------------
 
+class ForceableLoggerMixin(object):
+    """A mixin for loggers that can be forced to log a certain state.
+
+    The last logged state is always maintained, and when checking for a change,
+    that state is compared to the current one (which may actually be the same,
+    if a forced logging was performed for that state).
+
+    Children should implement the following functions:
+    - _hasChanged(oldState, state): the real check for a change
+    - _logState(flight, logger, state, forced): the real logging function
+    """
+    def __init__(self):
+        """Construct the mixin."""
+        self._lastLoggedState = None
+
+    def forceLog(self, flight, logger, state):
+        """Force logging the given state."""
+        self.logState(flight, logger, state, forced = True)
+
+    def logState(self, flight, logger, state, forced = False):
+        """Log the state.
+
+        It calls _logState to perform the real logging, and saves the given
+        state as the last logged one."""
+        self._logState(flight, logger, state, forced)
+        self._lastLoggedState = state
+    
+    def _changed(self, oldState, state):
+        """Check if the state has changed.
+
+        This function calls _hasChanged for the real check, and replaces
+        oldState with the stored last logged state, if any."""
+        if self._lastLoggedState is not None:
+            oldState = self._lastLoggedState
+        return self._hasChanged(oldState, state)
+
+#---------------------------------------------------------------------------------------
+
 class AltimeterLogger(StateChangeLogger, SingleValueMixin,
                       DelayedChangeMixin):
@@ -404,5 +452,5 @@
                                 DelayedChangeMixin._getLogTimestamp(self, state)
 
-    def _getMessage(self, flight, state):
+    def _getMessage(self, flight, state, forced):
         """Get the message to log on a change."""
         logState = self._lastChangeState if \
@@ -413,16 +461,37 @@
 #---------------------------------------------------------------------------------------
 
-class NAVLogger(StateChangeLogger, DelayedChangeMixin):
+class NAVLogger(StateChangeLogger, DelayedChangeMixin, ForceableLoggerMixin):
     """Logger for NAV radios.
 
     It also logs the OBS frequency set."""
+    @staticmethod
+    def getMessage(logName, frequency, obs):
+        """Get the message for the given NAV radio setting."""
+        message = u"%s frequency: %s MHz" % (logName, frequency)
+        if obs is not None: message += u" [%d\u00b0]" % (obs,)
+        return message
+    
     def __init__(self, attrName, logName):
         """Construct the NAV logger."""
         StateChangeLogger.__init__(self, logInitial = True)
         DelayedChangeMixin.__init__(self)
+        ForceableLoggerMixin.__init__(self)
+
+        self.logState = lambda flight, logger, state, forced = False: \
+            ForceableLoggerMixin.logState(self, flight, logger, state,
+                                          forced = forced)
+        self._getLogTimestamp = \
+            lambda state: DelayedChangeMixin._getLogTimestamp(self, state)
+        self._changed = lambda oldState, state: \
+            ForceableLoggerMixin._changed(self, oldState, state)
+        self._hasChanged = lambda oldState, state: \
+            DelayedChangeMixin._changed(self, oldState, state)
+        self._logState = lambda flight, logger, state, forced: \
+             StateChangeLogger.logState(self, flight, logger, state,
+                                        forced = forced)
 
         self._attrName = attrName
         self._logName = logName
-        
+
     def _getValue(self, state):
         """Get the value.
@@ -432,11 +501,19 @@
         frequency = getattr(state, self._attrName)
         obs = getattr(state, self._attrName + "_obs")
-        return None if frequency is None or obs is None else (frequency, obs)
-
-    def _getMessage(self, flight, state):
+        manual = getattr(state, self._attrName + "_manual")
+        return (frequency, obs, manual)
+
+    def _getMessage(self, flight, state, forced):
         """Get the message."""
-        value = self._getValue(state)
-        return None if value is None else \
-               (u"%s frequency: %s MHz [%d\u00b0]" % (self._logName, value[0], value[1]))
+        (frequency, obs, manual) = self._getValue(state)
+        return None if frequency is None or obs is None or \
+               (not manual and not forced) else \
+               self.getMessage(self._logName, frequency, obs)
+
+    def _isDifferent(self, oldValue, newValue):
+        """Determine if the valie has changed between the given states."""
+        (oldFrequency, oldOBS, _oldManual) = oldValue
+        (newFrequency, newOBS, _newManual) = newValue
+        return oldFrequency!=newFrequency or oldOBS!=newOBS
 
 #---------------------------------------------------------------------------------------
@@ -458,19 +535,38 @@
 #---------------------------------------------------------------------------------------
 
-class ADF1Logger(GenericStateChangeLogger):
+class ADFLogger(GenericStateChangeLogger, ForceableLoggerMixin):
+    """Base class for the ADF loggers."""
+    def __init__(self, attr, logName):
+        """Construct the ADF logger."""
+        GenericStateChangeLogger.__init__(self, attr,
+                                          "%s frequency: %%s kHz" % (logName,),
+                                          minDelay = 3.0, maxDelay = 10.0)
+        ForceableLoggerMixin.__init__(self)
+
+        self.logState = lambda flight, logger, state, forced = False: \
+            ForceableLoggerMixin.logState(self, flight, logger, state,
+                                          forced = forced)
+        self._changed = lambda oldState, state: \
+            ForceableLoggerMixin._changed(self, oldState, state)
+        self._hasChanged = lambda oldState, state: \
+            DelayedChangeMixin._changed(self, oldState, state)
+        self._logState = lambda flight, logger, state, forced: \
+             StateChangeLogger.logState(self, flight, logger, state, forced)
+
+#---------------------------------------------------------------------------------------
+
+class ADF1Logger(ADFLogger):
     """Logger for the ADF1 radio setting."""
     def __init__(self):
         """Construct the logger."""
-        super(ADF1Logger, self).__init__("adf1", "ADF1 frequency: %s kHz",
-                                         minDelay = 3.0, maxDelay = 10.0)
-
-#---------------------------------------------------------------------------------------
-
-class ADF2Logger(GenericStateChangeLogger):
+        super(ADF1Logger, self).__init__("adf1", "ADF1")
+
+#---------------------------------------------------------------------------------------
+
+class ADF2Logger(ADFLogger):
     """Logger for the ADF2 radio setting."""
     def __init__(self):
         """Construct the logger."""
-        super(ADF2Logger, self).__init__("adf2", "ADF2 frequency: %s kHz",
-                                         minDelay = 3.0, maxDelay = 10.0)
+        super(ADF2Logger, self).__init__("adf2", "ADF2")
 
 #---------------------------------------------------------------------------------------
@@ -494,5 +590,5 @@
         self._template = template
 
-    def _getMessage(self, flight, state):
+    def _getMessage(self, flight, state, forced):
         """Get the message from the given state."""
         return self._template % ("ON" if self._getValue(state) else "OFF")
@@ -539,5 +635,5 @@
         SingleValueMixin.__init__(self, "flapsSet")
 
-    def _getMessage(self, flight, state):
+    def _getMessage(self, flight, state, forced):
         """Get the message to log on a change."""
         speed = state.groundSpeed if state.groundSpeed<80.0 else state.ias
@@ -555,5 +651,5 @@
         SingleValueMixin.__init__(self, "gearControlDown")
 
-    def _getMessage(self, flight, state):
+    def _getMessage(self, flight, state, forced):
         """Get the message to log on a change."""
         return "Gears SET to %s at %.0f %s, %.0f feet" % \
Index: src/mlx/fs.py
===================================================================
--- src/mlx/fs.py	(revision 320)
+++ src/mlx/fs.py	(revision 321)
@@ -231,8 +231,10 @@
     - nav1_obs: the OBS setting of the NAV1 radio in degrees (int). Can be None, if
     the value is unreliable or meaningless.
+    - nav1_manual: a boolean indicating if the NAV1 radio is on manual control
     - nav2: the frequency of the NAV1 radio in MHz (string). Can be None, if
     the frequency is unreliable or meaningless.
     - nav2_obs: the OBS setting of the NAV2 radio in degrees (int). Can be None, if
     the value is unreliable or meaningless.
+    - nav2_manual: a boolean indicating if the NAV2 radio is on manual control
     - adf1: the frequency of the ADF1 radio in kHz (string). Can be None, if
     the frequency is unreliable or meaningless.
Index: src/mlx/fsuipc.py
===================================================================
--- src/mlx/fsuipc.py	(revision 320)
+++ src/mlx/fsuipc.py	(revision 321)
@@ -1179,5 +1179,5 @@
                       ("nav1_obs", 0x0c4e, "H"),
                       ("nav2", 0x0352, "H"),
-                      ("nav2_obs", 0x035e, "H"),
+                      ("nav2_obs", 0x0c5e, "H"),
                       ("adf1_main", 0x034c, "H"),
                       ("adf1_ext", 0x0356, "H"),
@@ -1365,6 +1365,8 @@
         state.nav1 = AircraftModel.convertFrequency(data[self._monidx_nav1])
         state.nav1_obs = data[self._monidx_nav1_obs]
+        state.nav1_manual = True
         state.nav2 = AircraftModel.convertFrequency(data[self._monidx_nav2])
         state.nav2_obs = data[self._monidx_nav2_obs]
+        state.nav2_manual = True
         state.adf1 = \
             AircraftModel.convertADFFrequency(data[self._monidx_adf1_main],
@@ -1751,5 +1753,5 @@
                                                          data)
         state.landingLightsOn = None
-        state.nav2 = None
+        state.nav2_manual = aircraft.flight.stage!=const.STAGE_CRUISE
 
         return state
Index: src/mlx/pyuipc_sim.py
===================================================================
--- src/mlx/pyuipc_sim.py	(revision 317)
+++ src/mlx/pyuipc_sim.py	(revision 321)
@@ -283,5 +283,7 @@
 
         self.nav1 = 117.3
+        self.nav1_obs = 128
         self.nav2 = 109.5
+        self.nav2_obs = 308
         self.adf1 = 382.7
         self.adf2 = 1540.6
@@ -450,4 +452,8 @@
         elif offset==0x0bec:       # Nose gear
             return int(self.noseGear * 16383.0)
+        elif offset==0x0c4e:       # NAV1 OBS
+            return self.nav1_obs
+        elif offset==0x0c5e:       # NAV2 OBS
+            return self.nav2_obs
         elif offset==0x0d0c:       # Lights
             lights = 0
@@ -684,4 +690,8 @@
         elif offset==0x0bec:       # Nose gear
             self.noseGear = value / 16383.0
+        elif offset==0x0c4e:       # NAV1 OBS
+            self.nav1_obs = value
+        elif offset==0x0c5e:       # NAV2 OBS
+            self.nav2_obs = value
         elif offset==0x0d0c:       # Lights
             self.navLightsOn = (value&0x01)!=0
@@ -1209,7 +1219,13 @@
                                        Values._writeFrequency,
                                        lambda word: Values._readFrequency(float(word)))
+        self._valueHandlers["nav1_obs"] = ([(0x0c4e, "H")],
+                                           lambda value: value,
+                                           lambda word: int(word))
         self._valueHandlers["nav2"] = ([(0x0352, "H")],
                                        Values._writeFrequency,
                                        lambda word: Values._readFrequency(float(word)))
+        self._valueHandlers["nav2_obs"] = ([(0x0c5e, "H")],
+                                           lambda value: value,
+                                           lambda word: int(word))
         self._valueHandlers["adf1"] = ([(0x034c, "H"), (0x0356, "H")],
                                        lambda values:
