#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# $Id: FormatNotes,v 1.1.4.7 2007/07/18 17:40:58 swift Exp $
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# RCS Log:
#
# $Log: FormatNotes,v $
# Revision 1.1.4.7  2007/07/18 17:40:58  swift
# Added the Sbe43i serial number to test message 2.
#
# Revision 1.1.4.6  2007/07/06 20:56:03  swift
# Minor change to facilitate automatic management of FormatNotes.
#
# Revision 1.1.4.5  2005/08/31 17:45:23  swift
# Added status-indicator and log-entries for shallow water traps.
#
# Revision 1.1.4.4  2005/05/01 21:45:48  swift
# Add format specs for pressure activation mode.
#
# Revision 1.1.4.3  2005/01/20 19:12:18  swift
# Reformatted test messages to include all mission programming as well as
# SBE41 biographical data.
#
# Revision 1.1.4.2  2004/04/20 20:48:19  swift
# Eliminated the revision specifier.
#
# Revision 1.1.4.1  2003/11/21 02:45:36  swift
# Documented SBE41 status bits.  Also documented the encoding and format for
# oxygen data.
#
# Revision 1.1  2003/11/12 23:05:54  swift
# Initial revision
#
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


Format specification for APF9 firmware revision: Apf9aSbe41Ido-071807 
===================================================================================


Test Message Format:
--------------------

Test Message #1:

Byte(s)  Pneumonic    Description
------------------------------------------------------------------------------
      0        CRC    Message CRC computed with BathySystem's CRC generator.
      1        MSG    Message id.  Test message blocks are allowed to span
                      more than one message so a message id is required.
      2        BLK    Message block id.  The block id increments with each
                      transmitted message block with overflow at 0xff.
      3        MON    Firmware revision: month. 
      4        DAY    Firmware revision: day. 
      5         YR    Firmware revision: year. 
    6,7        FLT    Float id. 
    8,9        SEC    The time [seconds] since the start of the mission
                      prelude.
  10,11     STATUS    This word records the state of 16 status bits.  Individual
                      bits can be accessed with an appropriate bit-mask.
  12,13          P    Pressure [centibars] measured once each test-message block.   
     14        VAC    Vacuum [counts] measured during self-test.
     15        ABP    Air bladder pressure [counts] measured once each
                      test-message block. 
     16        BAT    Quiescent battery voltage [counts] measured once each
                      test-message block.  
     17         UP    Mission configuration: up-time [TQuantum] modulo-256.
  18,19       DOWN    Mission configuration: down-time [TQuantum] modulo-65536.
  20,21       PRKP    Mission configuration: park pressure [decibars].
     22        PPP    Mission configuration: park piston position [counts].
     23      NUDGE    Mission configuration: buoyancy nudge for ascent
                      maintenance [counts] (aka., depth correction factor).
     24         OK    Mission configuration: internal vacuum threshold
                      [counts] for mission abortion. (aka., OK-vacuum count).
     25     ASCEND    Mission configuration: ascent time-out period
                      [TQuantum] modulo-256.
     26        TBP    Mission configuration: maximum air bladder pressure [counts]. 
  27,28         TP    Mission configuration: target profile pressure [decibars].
     29        TPP    Mission configuration: target profile piston position [counts].
     30          N    Mission configuration: park & profile cycle length.
     31               Not used - exists only when 20-bit argos ids are used.


Test Message #2:

Byte(s)  Pneumonic    Description
------------------------------------------------------------------------------
      0        CRC    Message CRC computed with BathySystem's CRC generator.
      1        MSG    Message id.  Test message blocks are allowed to span
                      more than one message so a message id is required.
      2        BLK    Message block id.  The block id increments with each
                      transmitted message block with overflow at 0xff.
      3        MON    Firmware revision: month. 
      4        DAY    Firmware revision: day. 
      5         YR    Firmware revision: year. 
      6       FEXT    Piston count at full extension. (counts)
      7       FRET    Piston count at full retraction. (counts)
      8        IBN    Initial buoyancy nudge. (counts)
      9       DPDP    Deep-profile descent period. (hours)
     10        PDP    Park descent period. (hours)
     11        PRE    Mission prelude period. (hours)
     12        REP    Argos repetition period. (seconds)
  13,14      SBESN    Serial number of the SBE41 sensor module.
  15,16      SBEFW    Firmware revision of the SBE41 sensor module.
  17,18      IDOSN    Serial number for the Sbe43i oxygen sensor.
  19-22      EPOCH    The current UNIX epoch (GMT) of the Apf9a RTC (little 
                      endian order).
  23,24        TOD    The number of minutes past midnight when the down-time
                      will expire.  If ToD feature disabled then these bytes 
                      will be set to 0xfffe.
  25,26      DEBUG    The debugging verbosity used for generating
                      engineering log entries.  
  27-31               Not used yet (filled with 0xff's).

The SBE41 biographical data transmitted in this firmware revision is the
SBE41's serial number (2 bytes) and the SBE41's firmware revision (2 bytes).
The serial number is encoded as a hex integer.  For example, serial number
1500 would be encoded and transmitted as 0x05DC.  The firmware revision is
multiplied by 100 before being encoded as a hex integer.  For example, FwRev
2.6 will be multiplied by 100 to get 260 before being encoded as 0x0104.



Data Message Format:
--------------------

Message #1
----------

Byte(s)  Pneumonic    Description
------------------------------------------------------------------------------
      0        CRC    Message CRC computed with BathySystem's CRC generator.
      1        MSG    Message id.  Test message blocks are allowed to span
                      more than one message so a message id is required.
      2        BLK    Message block id.  The block id increments with each
                      transmitted message block with overflow at 0xff.
    3,4        FLT    Float id. 
      5        PRF    Profile id modulo-256.
      6        LEN    Number of TSP samples in this message block.
    7,8     STATUS    This word records the state of 16 status bits.  Individual
                      bits can be accessed with an appropriate bit-mask.
   9,10         SP    The surface pressure [centibars] as recorded just
                      prior to the descent to the park depth.
     11        VAC    The internal vacuum [counts] recorded when the park
                      phase of the mission cycle terminated. 
     12        ABP    The air bladder pressure [counts] recorded just after
                      each argos transmission.
     13        SPP    The piston position [counts] recorded when the
                      surface-detection algorithm terminated. 
     14       PPP2    The piston position [counts] recorded at time that
                      the park phase of the mission cycle terminated.
     15        PPP    The piston position [counts] recorded at the time
                      that the last deep-descent phase terminated.
  16,17      SBE41    This word records the state of 16 status bits
                      specifically related to the SBE41.  Individual bits
                      can be accessed with an appropriate bit-mask.
  18,19        PMT    The total length of time [seconds] that the pump motor
                      ran during the current profile cycle.        
     20         VQ    The quiescent battery voltage [counts] measured when
                      the park phase of the profile cycle terminated.
     21         IQ    The quiescent battery current [counts] measured when
                      the park phase of the profile cycle terminated.
     22       VSBE    The battery voltage [counts] measured when the SBE41
                      sampled after the park phase of the profile cycle
                      terminated. 
     23       ISBE    The battery current [counts] measured when the SBE41
                      sampled after the park phase of the profile cycle
                      terminated. 
     24       VHPP    The battery voltage [counts] measured just prior to
                      then end of the initial extension of the buoyancy pump
                      at the start of the profile phase of the profile cycle.
     25       IHPP    The battery current [counts] measured just prior to
                      then end of the initial extension of the buoyancy pump
                      at the start of the profile phase of the profile cycle.
     26        VAP    The battery voltage [counts] measured during the most
                      recent period when the air pump was activated.
     27        IAP    The battery current [counts] measured during the most
                      recent period when the air pump was activated.
     28        PAP    The number of 6-second pulses of the air pump required
                      to inflate the air bladder.
  29,30       VSAP    The integrated measure (Volt-Sec) of the volume of air
                      pumped during the telemetry cycle.
     31         NA    Not used (0xff).  Present only if a 20-bit argos id is
                      used. 


/* definition of the 'STATUS' bits in the engineering data above  */
DeepPrf          0x0001  The current profile is a deep profile.
ShallowWaterTrap 0x0002  Shallow water trap detected
Obs25Min         0x0004  Sample time-out (25 min) expired.
PistonFullExt    0x0008  Piston fully extended before surface-detection algorithm terminated.
AscentTimeOut    0x0010  Ascent time-out expired.
TestMsg          0x0020  Current argos message is a test message.
PreludeMsg       0x0040  Current argos message transmitted during mission prelude.
PActMsg          0x0080  Current argos message is a pressure-activation test message.
BadSeqPnt        0x0100  Invalid sequence point detected.
Sbe41PFail       0x0200  Sbe41(P) exception. 
Sbe41PtFail      0x0400  Sbe41(PT) exception. 
Sbe41PtsFail     0x0800  Sbe41(PTS) exception.
Sbe41PUnreliable 0x1000  Sbe41(P) unreliable.
AirSysBypass     0x2000  Air inflation system by-passed; excessive energy consumption.
WatchDogAlarm    0x4000  Wake-up by watchdog alarm.
PrfIdOverflow    0x8000  The 8-bit profile counter overflowed.

/* definition of the 'SBE41' status bits in the engineering data above  */
Sbe41PedanticExceptn 0x0001 An exception was detected while parsing the p-only pedantic regex.
Sbe41PedanticFail    0x0002 The SBE41 response to p-only measurement failed the pedantic regex.
Sbe41RegexFail       0x0004 The SBE41 response to p-only measurement failed the nonpedantic regex.
Sbe41NullArg         0x0008 NULL argument detected during p-only measurement.
Sbe41RegExceptn      0x0010 An exception was detected while parsing the p-only  nonpedantic regex.
Sbe41NoResponse      0x0020 No response detected from SBE41 for p-only request.
                     0x0040 Not used yet.
                     0x0080 Not used yet.
Sbe41PedanticExceptn 0x0100 An exception was detected while parsing the pts pedantic regex.
Sbe41PedanticFail    0x0200 The SBE41 response to pts measurement failed the pedantic regex.
Sbe41RegexFail       0x0400 The SBE41 response to pts measurement failed the nonpedantic regex.
Sbe41NullArg         0x0800 NULL argument detected during  pts measurement.
Sbe41RegExceptn      0x1000 An exception was detected while parsing the pts nonpedantic regex.
Sbe41NoResponse      0x2000 No response detected from SBE41 for pts request.
                     0x4000 Not used yet.
                     0x8000 Not used yet.

Messages 2-N:
-------------

Message 2 continues with miscellaneous engineering data:

Byte(s)  Pneumonic    Description
------------------------------------------------------------------------------
      0        CRC    Message CRC computed with BathySystem's CRC generator.
      1        MSG    Message id.  
    2-5      EPOCH    UNIX epoch when the down-time expired (Ap9a RTC).
                      Signed 4-byte integer written in little-endian order. 
    6,7      TINIT    Time (ie., minutes) when telemetry phase was initiated
                      relative to EPOCH.  Signed integer in 2's-complement
                      form. 
      8       NADJ    Number of active-ballast adjustments made during the
                      park phase.

Next, the hydrographic data are transmitted in messages 2-N in the order
that they were collected.  The sample taken at the end of the park phase
will be transmitted first (in bytes 9-16 of message 2) followed by the
samples collected during the profile phase.  Each sample consists of 8 bytes
in order of T (2 bytes), S (2 bytes), P (2 bytes), O (2 bytes).  The
hydrographic data are encoded as shown in the C-source code below.


Message N: Auxiliary Engineering data
-------------------------------------

The last message is filled out with auxiliary engineering data.  This is
engineering data that is of a lower priority that the engineering data
transmitted in message 1.  The amount of engineering data will be variable
and only enough to complete the last message (at most).  The auxiliary
engineering data will never cause an additional message to be generated.  If
the auxiliary engineering data are not sufficient to complete the last
message then the remaining unused bytes will be set to 0xff.  Auxiliary
engineering data are included in the order presented below:

Time of profile initiation: The time difference (ie., minutes) between the
start of the profile and the end of the down-time.  This is a 2-byte signed
integer (expressed in 2's-complement form) where positive values indicate
profile initiation after the down-time expired and negative values indicate
profile initiation before the down-time expired.

Descent pressure marks: During the park-descent phase, the pressure is
measured just after the piston has been retracted; this is the first descent
mark.  In addition, at hourly intervals after initiation of the park-descent
phase, the pressure is measured.  These measurements mark the descent and
can be used to determine the descent rate as a function of time.

The first byte beyond the end of the hydrographic data is the count of the
number of descent pressure marks.  This byte is followed by 1-byte pressures
(bars) marking the descent phase.  

/*------------------------------------------------------------------------*/
/* function to encode pressure as a 2-byte unsigned integer               */
/*------------------------------------------------------------------------*/
/**
   This function implements the hex-encoding of IEEE-formattted floating
   point pressure data into 16-bit unsigned integers with 2's complement
   representation.  The encoding formula accounts for the full range of
   32-bit IEEE floating point values but only values in the open range:
   -3276.7<p<3276.7 are representable.  This encoding makes full use of all
   16-bits.

      \begin{verbatim}
      input:
         p ... The pressure (decibars) expressed as a floating point value.

      output:
         1) Nonfinite values (Inf, -Inf, NaN) are mapped to the sentinel hex
            value: 0x8000.

         2) Pressure values less than -3276.7 are mapped to the sentinel hex
            value: 0x8001.

         3) Pressure values greater than 32767.7 are mapped to the sentinel
            hex value: 0x7fff.

         4) Pressures in the range -0.15<p<=-0.05 would ordinarily map to
            0xffff but since this value has other special purposes,
            pressures in the range -0.15<p<=-0.05 map to 0xfffe.

         5) All other values are expressed in centibars rounded to the
            nearest integer and expressed as a 16-bit signed integer in
            2's-complement form.
      \end{verbatim}

   Important Note: This function is not portable to C-implementations for
   which unsigned integers do not have exactly two bytes.  For the APF9
   controller, this function has been fully tested over the full range of
   pressure.
*/
static unsigned int EncodeP(float p)
{
   /* initialize with the mapping for a nonfinite pressure */
   unsigned int P = 0x8000;

   /* make sure that unsigned integers have exactly two bytes */
   assert(sizeof(unsigned int)==2);
   
   if (finite(p))
   {
      /* assign out-of-range values to sentinel values */
      if (p>=3276.7) P=0x7fff; else if (p<=-3276.7) P=0x8001;

      /* encode the pressure as the number of centibars (rounded) */
      else P = (unsigned int)(10*(p + ((p<0) ? -0.05 : 0.05)));
      
      /* -0.15<p<=-0.05 maps to 0xffff; 0xffff is special so remap to 0xfffe */
      if (P==0xffff) P=0xfffe;
   }
   
   return P;
}

/*------------------------------------------------------------------------*/
/* function to encode salinity as a 2-byte unsigned integer               */
/*------------------------------------------------------------------------*/
/**
   This function implements the hex-encoding of IEEE-formattted floating
   point salinity data into 16-bit unsigned integers with 2's complement
   representation.  The encoding formula accounts for the full range of
   32-bit IEEE floating point values but only values in the open range:
   -4.095<s<61.439 are representable.  This encoding makes full use of all
   16-bits.

      \begin{verbatim}
      input:
         s ... The salinity (PSU) expressed as a floating point value.

      output:
         1) Nonfinite values (Inf, -Inf, NaN) are mapped to the sentinel hex
            value: 0xf000.

         2) Salinity values less than -4.095 are mapped to the sentinel hex
            value: 0xf001.

         3) Salinity values greater than 61.439 are mapped to the sentinel
            hex value: 0xefff.

         4) Salinities in the range -0.0015<s<=-0.0005 would ordinarily map
            to 0xffff but since this value has other special purposes,
            salinitys in the range -0.0015<s<=-0.0005 to 0xfffe.

         5) All other values are expressed in parts-per-million (PPM)
            rounded to the nearest integer and expressed as a 16-bit
            signed integer in 2's-complement form.
      \end{verbatim}

   Important Note: This function is not portable to C-implementations for
   which unsigned integers do not have exactly two bytes.  For the APF9
   controller, this function has been fully tested over the full range of
   salinity.
*/
static unsigned int EncodeS(float s)
{
   /* initialize with the mapping for a nonfinite salinity */
   unsigned int S = 0xf000;

   /* make sure that unsigned integers have exactly two bytes */
   assert(sizeof(unsigned int)==2);

   if (finite(s))
   {
      /* assign out-of-range values to sentinel values */
      if (s>=61.439) S=0xefff; else if (s<=-4.095) S=0xf001;

      /* encode the salinity as the number of PPM (rounded) */
      else S = (unsigned int)(1000*(s + ((s<0) ? -0.0005 : 0.0005)));

      /* -0.0015<s<=-0.0005 maps to 0xffff; 0xffff is special so remap to 0xfffe */
      if (S==0xffff) S=0xfffe;
   }
   
   return S;
}

/*------------------------------------------------------------------------*/
/* function to encode temperature as a 2-byte unsigned integer            */
/*------------------------------------------------------------------------*/
/**
   This function implements the hex-encoding of IEEE-formattted floating
   point temperature data into 16-bit unsigned integers with 2's complement
   representation.  The encoding formula accounts for the full range of
   32-bit IEEE floating point values but only values in the open range:
   -4.095<t<61.439 are representable.  This encoding makes full use of all
   16-bits.

      \begin{verbatim}
      input:
         t ... The temperature (C) expressed as a floating point value.

      output:
         1) Nonfinite values (Inf, -Inf, NaN) are mapped to the sentinel hex
            value: 0xf000.

         2) Temperatures values less than -4.095 are mapped to the sentinel
            hex value: 0xf001.

         3) Temperatures values greater than 61.439 are mapped to the
            sentinel hex value: 0xefff.

         4) Temperatures in the range -0.0015<t<=-0.0005 would ordinarily
            map to 0xffff but since this value has other special purposes,
            temperatures in the range -0.0015<t<=-0.0005 to 0xfffe.

         5) All other values are expressed in milldegrees Celsius rounded to
            the nearest integer and expressed as a 16-bit signed integer in
            2's-complement form.
      \end{verbatim}

   Important Note: This function is not portable to C-implementations for
   which unsigned integers do not have exactly two bytes.  For the APF9
   controller, this function has been fully tested over the full range of
   temperature.
*/
static unsigned int EncodeT(float t)
{
   /* initialize with the mapping for a nonfinite temperature */
   unsigned int T = 0xf000;

   /* make sure that unsigned integers have exactly two bytes */
   assert(sizeof(unsigned int)==2);

   if (finite(t))
   {
      /* assign out-of-range values to sentinel values */
      if (t>=61.439) T=0xefff; else if (t<=-4.095) T=0xf001;

      /* encode the temperature as the number of millidegrees (rounded) */
      else T = (unsigned int)(1000*(t + ((t<0) ? -0.0005 : 0.0005)));

      /* -0.0015<t<=-0.0005 maps to 0xffff; 0xffff is special so remap to 0xfffe */
      if (T==0xffff) T=0xfffe;
   }
   
   return T;
}

/*------------------------------------------------------------------------*/
/* function to encode oxygen as a 2-byte unsigned integer                 */
/*------------------------------------------------------------------------*/
/**
   This function implements the hex-encoding of IEEE-formattted floating
   point oxygen data into 16-bit unsigned integers with 2's-complement
   representation.  The encoding formula accounts for the full range of
   32-bit IEEE floating point values but only values in the open range:
   -4095<o2<61439 are representable.  This encoding makes full use of all
   16-bits.

      \begin{verbatim}
      input:
         o2 ... The oxygen (o2-freq) expressed as a floating point value.

      output:
         1) Nonfinite values (Inf, -Inf, NaN) are mapped to the sentinel hex
            value: 0xf000.

         2) Oxygen frequency values less than -4095 are mapped to the
            sentinel hex value: 0xf001.

         3) Oxygen frequency values greater than 61439 are mapped to the
            sentinel hex value: 0xefff.

         4) Oxygen frequencies in the range -1.5<o2<=-0.5 would ordinarily
            map to 0xffff but since this value has other special purposes,
            oxygens frequencies in the range -1.5<o2<=-0.5 to 0xfffe.

         5) All other values are to the nearest integer and expressed as a
            16-bit signed integer in 2's-complement form.
      \end{verbatim}

   Important Note: This function is not portable to C-implementations for
   which unsigned integers do not have exactly two bytes.  For the APF9
   controller, this function has been fully tested over the full range of
   oxygen.
*/
static unsigned int EncodeO2(float o2)
{
   /* initialize with the mapping for a nonfinite oxygen */
   unsigned int O2 = 0xf000;

   /* make sure that unsigned integers have exactly two bytes */
   assert(sizeof(unsigned int)==2);

   if (finite(o2))
   {
      /* assign out-of-range values to sentinel values */
      if (o2>=61439) O2=0xefff; else if (o2<=-4095) O2=0xf001;

      /* encode the oxygen as the number of PPM (rounded) */
      else O2 = (unsigned int)(o2 + ((o2<0) ? -0.5 : 0.5));

      /* -1.5<s<=-0.5 maps to 0xffff; 0xffff is special so remap to 0xfffe */
      if (O2==0xffff) O2=0xfffe;
   }
   
   return O2;
}
