=3);
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 frequency (rounded) */
else O2 = (unsigned int)(o2 + ((o2<0) ? -0.5 : 0.5));
/* express in 16-bit 2's-complement form */
if (O2<0) O2+=0x10000L;
}
return O2;
}
/*------------------------------------------------------------------------*/
/* function to encode pressure as a 2-byte unsigned integer */
/*------------------------------------------------------------------------*/
/**
This function implements the hex-encoding of IEEE-formattted floating
point pressure data into 2-byte signed 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=3);
if (finite(p))
{
/* assign out-of-range values to sentinel values */
if (p>=3276.7) P=0x7fffL; else if (p<=-3276.7) P=0x8001L;
/* encode the pressure as the number of centibars (rounded) */
else P = (long int)(10*(p + ((p<0) ? -0.05 : 0.05)));
/* express in 16-bit 2's-complement form */
if (P<0) P+=0x10000L;
}
return P;
}
/*------------------------------------------------------------------------*/
/* function to encode salinity as a 2-byte unsigned long 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~~=3);
if (finite(s))
{
/* assign out-of-range values to sentinel values */
if (s>=61.439) S=0xefffL; else if (s<=-4.095) S=0xf001L;
/* encode the salinity as the number of parts-per-ten-million (rounded) */
else S = (long int)(1000*(s + ((s<0) ? -0.0005 : 0.0005)));
/* express in 16-bit 2's-complement form */
if (S<0) S+=0x10000L;
}
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=3);
if (finite(t))
{
/* assign out-of-range values to sentinel values */
if (t>=61.439) T=0xefffL; else if (t<=-4.095) T=0xf001L;
/* encode the temperature as the number of tenths of millidegrees (rounded) */
else T = (long int)(1000*(t + ((t<0) ? -0.0005 : 0.0005)));
/* express in 16-bit 2's-complement form */
if (T<0) T+=0x10000L;
}
return T;
}
/*------------------------------------------------------------------------*/
/* function to decode an 8-byte FLBB encoding string */
/*------------------------------------------------------------------------*/
/**
This function inverts the hex-encoding scheme implemented in
FlbbEncode(). For detailed information about the encoding scheme and how
to invert it, see the comment sections of FlbbEncode() and FlbbDecodeTSig().
\begin{verbatim}
input:
encode....the FLBB encoding string as computed by FlbbEncode().
output:
This function decodes the FLBB encoding string and returns a
pointer to the FlbbData object that contains the decoded data. If
the function argument 'flbbdata' is non-NULL then the decoded data
are stored there. Otherwise the decoded data are stored in a
static local FlbbData object which is potentially overwritten on
each call to this function. If the encoding string is NULL then
the flbbdata object will be initialized with missing-data
indicators.
\end{verbatim}
*/
struct FlbbData *FlbbDecode(struct FlbbData *flbbdata,FlbbArray *encode)
{
/* define a static local FlbbData object */
static struct FlbbData _flbbdata;
/* initialize the return value */
struct FlbbData *D=(flbbdata) ? flbbdata : &_flbbdata;
/* initialize a pointer to the FlbbArray object */
unsigned char *E=*encode;
/* validate the 4-byte encoding string */
if (E)
{
/* initialize the fluorescence wavelenrgth */
D->FWaveLen=-1;
/* unpack the fluorescence signal */
D->FSig=E[0]; D->FSig<<=4; D->FSig |= ((E[1]>>4)&0xf);
/* initialize the scattering wavelength */
D->BbWaveLen=-1;
/* unpack the Bb signal */
D->BbSig=E[1]&0xf; D->BbSig<<=8; D->BbSig |= E[2];
/* unpack and decode the temperature signal */
D->TSig=FlbbDecodeTSig(E[3]);
/* initialize the timestamp as missing */
D->timestamp=(time_t)(-1);
}
/* initialize the FlbbData object with missing-data indicators */
else *D = FlbbInit;
return D;
}
/*------------------------------------------------------------------------*/
/* function to encode temperature signal as a 1-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.0950x80)?(T-0x100):T; TSig+=0x200;}
return TSig;
}
/*------------------------------------------------------------------------*/
/* function to encode a FlbbData object containing a FLBB sensor sample */
/*------------------------------------------------------------------------*/
/**
This function encodes a FlbbData object and packs it into an 4-byte hex
array. Each of the two optical signal channels are encoded as a 12-bit
unsigned integer and the temperature signal is encoded as an 8-bit
unsigned integer. These 32-bits of encoded data are then packed into an
4-byte array in order of fluorescence signal (12 bits), bb signal (12
bits), and thermistor signal(8 bits).
\begin{verbatim}
input:
flbbdata.....The data returned by the FLBB sensor.
output:
encode...The 4-byte array of packed, encoded data. Refer to
FlbbEncodeTSig() and FlbbEncode12Bit() for encoding
details.
If 'encode' is non-NULL then it is used to store the encoding
string. Otherwise, a local static encoding string is used. This
function returns a pointer to the encoding string.
\end{verbatim}
*/
unsigned char *FlbbEncode(const struct FlbbData *flbbdata, FlbbArray *encode)
{
/* define a local static encoding string */
static FlbbArray _encode;
/* initialize the function's return value */
unsigned char *E=(encode) ? *encode : _encode;
/* validate the data source */
if (flbbdata)
{
/* encode the fluorescence and backscatter signals */
unsigned int FSig=FlbbEncode12Bit(flbbdata->FSig),
BbSig=FlbbEncode12Bit(flbbdata->BbSig);
/* pack 12-bit encoded Flbb signals in first 3 bytes of encoding array */
E[0]=(FSig>>4)&0xff; E[1]=(((FSig<<4)&0xf0) | ((BbSig>>8)&0x0f)); E[2]=BbSig&0xff;
/* pack the encoded thermistor signal in last byte */
E[3]=FlbbEncodeTSig(flbbdata->TSig);
}
/* initialize the encoding array to missing data indicators (0xff) */
else memset((void *)E,0xff,sizeof(FlbbArray));
return E;
}
/*------------------------------------------------------------------------*/
/* function to encode a value as a 2-byte unsigned integer */
/*------------------------------------------------------------------------*/
/**
This function implements the hex-encoding of 16-bit signed
integers into 12-bit unsigned integers. The encoding formula
accounts for the full range of 16-bit integers but only values
in the semi-open range: 0<=v<4093 are representable. This
encoding makes full use of all 12-bits.
\begin{verbatim}
input:
v ... The value to be encoded.
output:
1) The sentinel hex value 0xfff is reserved as a missing-data
indicator.
2) The maximum 16-bit signed integer value 0x7fff plays
the same role as NaN plays for floating point values
and is mapped to the sentinel hex value: 0xffe.
3) Values greater than or equal to 4093.0 are mapped to the sentinel
hex value: 0xffd.
4) Values less than or equal to zero are mapped to the sentinel
hex value: 0x000.
5) All other values are rounded to the nearest integer and
expressed as a 12-bit unsigned integer.
\end{verbatim}
Important Note: This function is not portable to C-implementations for
which unsigned integers do not have at least two bytes. For the APF9
controller, this function has been fully tested over the full range of
values.
*/
static unsigned int FlbbEncode12Bit(int v)
{
/* initialize with the mapping for a nonfinite 12-bit value */
unsigned int V = 0xffe;
/* make sure that unsigned integers have at least two bytes */
assert(sizeof(unsigned int)>=2);
if (v!=0x7fff)
{
/* assign out-of-range values to sentinel values */
if (v>=0xffd) V=0xffd; else if (v<=0) V=0x000;
/* encode the 12-bit value as is */
else V = v;
}
return V;
}
/*------------------------------------------------------------------------*/
/* function to encode temperature signal as a 1-byte unsigned integer */
/*------------------------------------------------------------------------*/
/**
This function implements the hex-encoding of the 12-bit FLBB
thermistor channel into an 8-bit unsigned integer with 2's
complement representation. The encoding formula accounts for
the full range of 12-bit integers but only values in the open
range: 385=639) T=0x7f; else if (TSig<=385) T=0x81;
/* encode the temperature signal as an offset */
else T = (unsigned char)(TSig-512);
/* TSig=511 maps to 0xff; 0xff is special so remap to 0xfe */
if (T==0xff) T=0xfe;
}
return T;
}
4) GPS fix format.
------------------
Each telemetry cycle begins with the float attempting to acquire a GPS
fix. The fix includes the amount of time required to acquire the fix,
the longitude and latitude (degrees), the date & time of the fix, and the
number of satellites used to determine the fix. For example:
# GPS fix obtained in 98 seconds.
# lon lat mm/dd/yyyy hhmmss nsat
Fix: -152.945 22.544 09/01/2005 104710 8
Positive values of longitude, latitude represent east, north hemispheres,
respectively. Negative values of longitude, latitude represent west,
south hemispheres, respectively. The date is given in month-day-year
format and the time is given in hours-minutes-seconds format.
If no fix was acquired then the following note is entered into the
iridium message:
# Attempt to get GPS fix failed after 600 seconds.
5) Biographical & engineering data.
-----------------------------------
These data have the format, "key"="value", as shown in the following
examples:
ActiveBallastAdjustments=5
AirBladderPressure=119
AirPumpAmps=91
AirPumpVolts=192
BuoyancyPumpOnTime=1539
Interpretation of these data requires detailed knowledge of firmware
implementations.
~~