// not avilable on ThunderBolt-E or early ThunderBolts
 private void osc_sense(TsipPacket tp)
 {
     Debug.Print("Packet 8F.A1 (10 MHz sense):");
     unit_osc_polarity = (tp.GetNextByte() != 0);
 }
 private void pps_timing_mode(TsipPacket tp)
 {
     Debug.Print("Packet 8F.A2 (Timing mode):");
     unit_pps_mode = tp.GetNextByte();
 }
 private void get_alm_health(TsipPacket tp)
 {
     Debug.Print(":0x49   (Almanac Health Page Report)");
     for (int i = 0; i < 32; i++)
         Satellites[i].IsHealthy = (tp.GetNextByte() == 0);
 }
        private void last_fix_info(TsipPacket tp)
        {
            Debug.Print("Packet 57 (last fix info):");

            byte source_of_fix = tp.GetNextByte();
            byte tracking_mode = tp.GetNextByte();
            Single time_of_fix = tp.GetNextSingle();
            UInt16 week_of_fix = tp.GetNextWord();
        }
        // Thunderbolt E Version Information
        private void ebolt_version(TsipPacket tp)
        {
            byte rev_month;
            byte rev_day;
            UInt16 rev_year;

            byte subcode = tp.GetNextByte();
            if (subcode == 0x81) // firmware version
            {
                Debug.Print(":0x1C.0x81 (Firmware Version)");
                byte reserved8 = tp.GetNextByte();
                byte major = tp.GetNextByte(); // major version number
                byte minor = tp.GetNextByte(); // minor version number
                byte build = tp.GetNextByte(); // build number
                rev_month = tp.GetNextByte();  // build month
                rev_day = tp.GetNextByte();    // build day
                rev_year = tp.GetNextWord();   // build year
                unit_firmware.VersionString = tp.GetNextString(); // product name string
                try
                {
                    unit_firmware.Date = new DateTime(rev_year, rev_month, rev_day, 0, 0, 0);
                }
                catch (Exception e)
                {
                    unit_firmware.Date = new DateTime(0L);   // bad date
                    Debug.Print("Date Conversion Exception: " + e.Message);
                }
                unit_firmware.Code = 0;
                if (FirmwareVersionInfoReceived != null)
                    FirmwareVersionInfoReceived(this, new VersionInfoEventArgs(unit_firmware));
            }
            else if (subcode == 0x83) // hardware version
            {
                Debug.Print(":0x1C.0x83 (Hardware Version)");
                UInt32 serno = tp.GetNextDWord();    // board serial number
                rev_day = tp.GetNextByte();          // board build day
                rev_month = tp.GetNextByte();        // board build month
                rev_year = tp.GetNextWord();         // board build year
                byte rev_hour = tp.GetNextByte();    // board build hour

                unit_hardware.Code = tp.GetNextWord(); // hardware code associated with hardware ID
                unit_hardware.VersionString = tp.GetNextString(); // Hardware ID
                unit_hardware.SerialNumber = "SN:" + serno.ToString();

                try
                {
                    unit_hardware.Date = new DateTime(rev_year, rev_month, rev_day, rev_hour, 0, 0);
                }
                catch (Exception e)
                {
                    unit_hardware.Date = new DateTime(0L);  // bad date
                    Debug.Print("Date Conversion Exception: " + e.Message);
                }
                if (HardwareVersionInfoReceived != null)
                    HardwareVersionInfoReceived(this, new VersionInfoEventArgs(unit_hardware));
            }
            else
                unknown_msg(tp);
        }
        private void eph_status(TsipPacket tp)
        {
            Debug.Print("Packet 5B (Sat ephemeris status):");

            byte prn = tp.GetNextByte();
            prn--;
            if (prn > 31)
            {
                unknown_msg(tp);
                return;
            }

            Satellites[prn].CollectionTime = tp.GetNextSingle();
            Satellites[prn].EphemerisHealth = tp.GetNextByte();
            Satellites[prn].IODE = tp.GetNextByte();
            Satellites[prn].Toe = tp.GetNextSingle();
            Satellites[prn].FitIntervalFlag = tp.GetNextByte();
            Satellites[prn].UserRangeAccuracy = tp.GetNextSingle();
        }
        /// <summary>
        /// Satellite Health Report
        /// 
        /// op = 0x03:
        /// The 32 single-byte flags (byte 1-32) identify the Enable/Disable attribute
        /// status for the 32 satellites. Disabled satellites are not used, even when
        /// the satellite is in good health. The flags identify any satellites which are
        /// manually disabled by user. The factory default setting is to enable all
        /// satellites for inclusion in position solution computations if they are in
        /// good health and conform with the mask values for elevation angle,
        /// signal level, PDOP, and PDOP Switch
        ///
        /// op = 0x06:
        /// The 32 single-byte flags (byte 1-32) identify the Heed/Ignore Health
        /// attribute status for the 32 satellites. Flags with the Ignore attribute set
        /// indicate that the satellite can be used in the position solution, regardless
        /// of whether the satellite is in good or bad health. The factory default
        /// setting is to heed satellite health when choosing the satellites included
        /// in a position solution computation
        /// </summary>
        private void sat_health(TsipPacket tp)
        {
            Debug.Print(":0x59 (Satellite Attribute Database Status Report)");

            byte op = tp.GetNextByte();
            if (op == 3)        // enable / disable
            {
                for (int i = 0; i < 32; i++)
                    Satellites[i].Disabled = (tp.GetNextByte() == 1);
            }
            else if (op == 6) // heed / ignore
            {
                for (int i = 0; i < 32; i++)
                    Satellites[i].ForcedHealthy = (tp.GetNextByte() == 1);
            }
            else
                unknown_msg(tp);
        }
 private void ebolt_health1(TsipPacket tp)
 {
     Debug.Print(":0x46 (E Receiver Health 1st Packet):");
     receiver_status = (ReceiverStatus)tp.GetNextByte();
     //byte sv_fix = tsip_byte();
     byte antenna_fault = tp.GetNextByte();
 }
        private void rcvr_config(TsipPacket tp)
        {
            Debug.Print("0xBB (Receiver config)");

            byte subcode = tp.GetNextByte();
            byte rcvr_mode = tp.GetNextByte();
            byte rsvd1 = tp.GetNextByte();
            byte dynamics_code = tp.GetNextByte();
            byte rsvd2 = tp.GetNextByte();
            Single el_mask = tp.GetNextSingle();
            Single amu_mask = tp.GetNextSingle();
            Single pdop_mask = tp.GetNextSingle();
            Single pdop_switch = tp.GetNextSingle();
            byte rsvd3 = tp.GetNextByte();
            byte foliage_mode = tp.GetNextByte();
        }
        private void receive_sig_levels(TsipPacket tp)
        {
            Debug.Print(":0x47    (Signal Levels for All Tracked Satellites Report)");

            byte count = tp.GetNextByte();
            for (int i = 0; i < count; i++)
            {
                byte prn = tp.GetNextByte();
                Single sig_level = tp.GetNextSingle();
                prn--;          // zero offset adjust
                if (prn > 31)
                    continue;   // disregard bogus data

                Satellites[prn].SignalLevel = sig_level;
                Satellites[prn].Tracked = true;
            }
        }
        private void raw_data(TsipPacket tp)
        {
            byte prn = tp.GetNextByte();
            prn--;
            if (prn > 31)
            {
                unknown_msg(tp);
                return;
            }

            //Debug.Print(":0x5A    (Raw Measurement Data prn = {0} )", prn);

            Satellites[prn].SampleLength = tp.GetNextSingle();
            Satellites[prn].SignalLevel = tp.GetNextSingle();
            Satellites[prn].CodePhase = tp.GetNextSingle();
            Satellites[prn].Doppler = tp.GetNextSingle();
            Satellites[prn].RawTime = tp.GetNextDouble();
            Satellites[prn].Tracked = true;
        }
        private void prodn_params(TsipPacket tp)
        {
            Debug.Print("Packet 8F.42 (Production Params):");

            byte prodn_options = tp.GetNextByte();
            byte prodn_number = tp.GetNextByte();
            UInt16 case_prefix = tp.GetNextWord();
            UInt32 case_sn = tp.GetNextDWord();
            UInt32 prodn_num = tp.GetNextDWord();
            UInt16 rsvd1 = tp.GetNextWord();
            UInt16 machine_id = tp.GetNextWord();
            UInt16 rsvd2 = tp.GetNextWord();
        }
        private void primary_timing(TsipPacket tp)
        {
            Debug.Print(":0x8F.AB (Primary Timing)");

            UInt32 pri_tow = tp.GetNextDWord();
            UInt16 pri_gps_week = tp.GetNextWord();
            Int16 pri_utc_offset = (short)tp.GetNextWord();
            byte time_flags = tp.GetNextByte();
            byte pri_seconds = tp.GetNextByte();
            byte pri_minutes = tp.GetNextByte();
            byte pri_hours = tp.GetNextByte();
            byte pri_day = tp.GetNextByte();
            byte pri_month = tp.GetNextByte();
            UInt16 pri_year = tp.GetNextWord();
            try
            {
                // if this fires an execption, just skip the bad packet
                current_time = new DateTime(pri_year, pri_month, pri_day, pri_hours, pri_minutes, pri_seconds);

                tow = pri_tow;
                utc_offset = pri_utc_offset;
                gps_week = pri_gps_week;

                if ((time_flags & 0x04) == 0x04)
                    time_value = TimeType.NoTimeAvailable;
                else if ((time_flags & 0x08) == 0x08)
                    time_value = TimeType.NoUTCOffset;
                else if ((time_flags & 0x10) == 0x10)
                    time_value = TimeType.UserSetTime;
                else if ((time_flags & 0x01) == 0x01)
                    time_value = TimeType.UTCTimeOk;
                else
                    time_value = TimeType.GPSTimeOk;

                // Set the time on the netduino to the current time on the Thunderbolt.
                Microsoft.SPOT.Hardware.Utility.SetLocalTime(current_time);

                if ((last_current_time != current_time) && (TimeChanged != null))
                    TimeChanged(this, new EventArgs());

                last_current_time = current_time;
            }
            catch (Exception e)
            {
                current_time = last_current_time;
                Debug.Print("Exception:" + e.Message);
            }
        }
        private void dac_values(TsipPacket tp)
        {
            Debug.Print("Packet 8F.A0 (DAC values):");

            UInt32 dac_value = tp.GetNextDWord();
            Single dac_voltage = tp.GetNextSingle();
            Byte dac_res = tp.GetNextByte();
            Byte dac_format = tp.GetNextByte();
            Single dac_min = tp.GetNextSingle();
            Single dac_max = tp.GetNextSingle();
        }
        /// <summary>
        /// This packet provides a list of satellites used for position or time-only fixes by the GPS
        /// receiver. The packet also provides the dilution of precision values PDOP, HDOP, VDOP and TDOP 
        /// of that set and provides the current mode (automatic or manual, 3-D or 2-D, Over-Determined Clock
        /// mode, etc.). This packet has variable length equal to (17 + nsvs) where "nsvs" is the
        /// number of satellites used in the solution. If an SV is rejected for use by the T-RAIM
        /// algorithm then the SV PRN value will be negative.
        /// 
        /// PDOP = positional DOP
        /// HDOP = horizontal DOP
        /// VDOP = vertical DOP
        /// TDOP = temporal DOP
        /// 
        /// Note: The GPS receiver sends this packet in response to packet 0x24 or automatically. 
        /// </summary>
        private void sat_list(TsipPacket tp)
        {
            byte mode, count, dimension;

            dimension = mode = count = tp.GetNextByte();
            dimension &= 0x07;  // fix dimension is in first 3 bits
            mode &= 0x08;       // mode is in bit 3
            mode >>= 3;
            count >>= 4;        // tracked sat count in upper 4 bits

            //Debug.Print(":0x6D    (Satellite List count = {0})", count);

            positional_dop = Helpers.FloatToFixPrecision(tp.GetNextSingle());
            horizontal_dop = Helpers.FloatToFixPrecision(tp.GetNextSingle());
            vertical_dop = Helpers.FloatToFixPrecision(tp.GetNextSingle());
            temporal_dop = Helpers.FloatToFixPrecision(tp.GetNextSingle());
            fix_dimension = Helpers.ByteToFixDimension(dimension);
            fix_mode = Helpers.ByteToFixMode(mode);

            for (int i = 0; i < 32; i++)    // clear current tracking flags
                Satellites[i].UsedInFix = false;

            for (int i = 0; i < count; i++)
            {
                bool used = true;
                byte prn = tp.GetNextByte();
                if ((prn & 0x80) == 0x80)   // satellite is tracked but is not used in fix
                {
                    used = false;
                    prn &= 0x7F;
                }
                prn--;
                if (prn > 31)
                    continue;               // disregard bogus data

                Satellites[prn].Tracked = true;
                Satellites[prn].UsedInFix = used;
            }
        }
        private void discipline_params(TsipPacket tp)
        {
            Debug.Print("Packet 8F.A8 (Discipline params):");

            byte type = tp.GetNextByte();

            if (type == 0)
            {
                unit_time_constant = tp.GetNextSingle();
                unit_damping_factor = tp.GetNextSingle();
            }
            else if (type == 1)
            {
                unit_osc_gain = tp.GetNextSingle();
                unit_min_volts = tp.GetNextSingle();
                unit_max_volts = tp.GetNextSingle();
            }
            else if (type == 2)
            {
                unit_jam_sync = tp.GetNextSingle();
                unit_max_freq_offset = tp.GetNextSingle();
            }
            else if (type == 3)
            {
                unit_initial_voltage = tp.GetNextSingle();
            }
        }
        //not available on ThunderBolt-E
        /// <summary>
        /// This broadcast packet provides individual satellite solutions as well as the combined
        /// timing solutions. Two formats of this packet are supported: a floating-point form and an
        /// integer form. This packet is broadcast once per second if enabled with the 0x8E-A5 packet
        /// mask command. Packet 0x8E-A5 allows the user to select which format will be broadcast.
        /// 
        /// notes:
        /// If both formats are selected the ThunderBolt will send format 0 (floating point) only.
        /// 
        /// For clock bias numbers, a positive sign indicates that the ThunderBolt PPS occurs after the
        /// GPS PPS. 
        /// 
        /// For clock bias rate numbers, a positive sign indicates that the ThunderBolt
        /// 10MHz frequency output is running slow relative to GPS.
        /// 
        /// 8 sets of satellite ID and data are sent with n=1, 2, . . . 8
        /// </summary>
        private void sat_solutions(TsipPacket tp)
        {
            Debug.Print(":0x8F.A7 (Satellite Solutions)");

            byte format = tp.GetNextByte();
            UInt32 time_of_week = tp.GetNextDWord();

            Single clock_bias;
            Single clock_bias_rate;

            if (format == 0)
            {   // floating point
                clock_bias = tp.GetNextSingle();
                clock_bias_rate = tp.GetNextSingle();
            }
            else if (format == 1)
            {   // integer values
                clock_bias = (float)(int)tp.GetNextWord();
                clock_bias *= 100.0e-12F;
                clock_bias_rate = (float)(int)tp.GetNextWord();
                clock_bias_rate *= 1.0e-12F;
            }
            else
            {
                unknown_msg(tp);
                return;
            }

            for (int i = 0; i < 32; i++)    // reset current bias flags
                Satellites[i].HasBiasInfo = false;

            for (int i = 0; i < 8; i++)     // get bias info from all visible satellites
            {
                byte prn = tp.GetNextByte();
                prn--;
                if (prn > 31)               // ignore bogus data
                    continue;

                if (format == 0)
                    Satellites[prn].SatBias = tp.GetNextSingle();
                else
                {
                    Satellites[prn].SatBias = (float)(int)tp.GetNextWord();
                    Satellites[prn].SatBias *= 100.0e-12F;
                }

                Satellites[prn].TimeOfFix = (float)time_of_week;
                Satellites[prn].HasBiasInfo = true;
            }
        }
 private void ebolt_health2(TsipPacket tp)
 {
     Debug.Print(":0x4B (E Receiver Health 2nd Packet):");
     byte id = tp.GetNextByte();
     byte rtc = tp.GetNextByte();
     byte superpackets = tp.GetNextByte();
 }
        private void sat_tracking(TsipPacket tp)
        {
            Debug.Print(":0x5C    (Satellite Tracking)");

            byte prn = tp.GetNextByte();
            prn--;
            if (prn > 31)
            {
                unknown_msg(tp);
                return;
            }

            Satellites[prn].Slot = Satellites[prn].Channel = tp.GetNextByte();
            Satellites[prn].Slot &= 0x07;
            Satellites[prn].Channel >>= 3;
            Satellites[prn].AcquisitionFlag = tp.GetNextByte();
            Satellites[prn].EphemerisFlag = tp.GetNextByte();
            Satellites[prn].SignalLevel = tp.GetNextSingle();
            Satellites[prn].TimeOfWeek = tp.GetNextSingle();
            Satellites[prn].Elevation = tp.GetNextSingle();
            Satellites[prn].Azimuth = tp.GetNextSingle();
            Satellites[prn].Age = tp.GetNextByte();
            Satellites[prn].MsecStatus = tp.GetNextByte();
            Satellites[prn].BadDataFlag = tp.GetNextByte();
            Satellites[prn].CollectingData = tp.GetNextByte();
        }
        private void eeprom_status(TsipPacket tp)
        {
            Debug.Print("Packet 5F (EEPROM status):");

            byte flag = tp.GetNextByte();
            if (flag == 0x11)
            {
                UInt16 ee_status = tp.GetNextWord();
            }
        }
        private void secondary_timing(TsipPacket tp)
        {
            Debug.Print(":0x8F.AC (Secondary Timing)");

            byte spare;
            try
            {
                receiver_mode = (ReceiverMode)tp.GetNextByte();
            }
            catch
            {
                receiver_mode = ReceiverMode.Unknown;
            }
            try
            {
                discipline_mode = (DiscipliningMode)tp.GetNextByte();
            }
            catch
            {
                discipline_mode = DiscipliningMode.Unknown;
            }
            survey_progress = tp.GetNextByte(); // 0-100%

            holdover = tp.GetNextDWord(); // seconds

            critical_alarms = tp.GetNextWord();
            minor_alarms = tp.GetNextWord();
            try
            {
                gps_status = (ReceiverStatus)tp.GetNextByte();
            }
            catch
            {
                gps_status = ReceiverStatus.Unknown;
            }

            try
            {
                discipline = (DiscipliningActivity)tp.GetNextByte();
            }
            catch
            {
                discipline = DiscipliningActivity.Unknown;
            }

            spare = tp.GetNextByte();
            spare = tp.GetNextByte();

            pps_offset = tp.GetNextSingle();  // in nano seconds (ns)

            osc_offset = tp.GetNextSingle();  // in parts per billion (ppb)

            dac_value = tp.GetNextDWord();
            dac_voltage = tp.GetNextSingle(); // in V
            temperature = tp.GetNextSingle(); // in C

            position.Latitude = tp.GetNextDouble();
            position.Longitude = tp.GetNextDouble();
            position.Altitude = tp.GetNextDouble();

            if (SecondaryTimingChanged != null)
                SecondaryTimingChanged(this, null);

            raise_position_change();

            clear_sat_tracking(); //??
        }
        private void filter_config(TsipPacket tp)
        {
            Debug.Print("Packet 70 (Filter config):");

            pv_filter = tp.GetNextByte();
            static_filter = tp.GetNextByte();
            altitude_filter = tp.GetNextByte();
            kalman_filter = tp.GetNextByte();
        }
 private void survey_params(TsipPacket tp)
 {
     Debug.Print("Packet 8F.A9 (Survey params):");
     byte survey_flag = tp.GetNextByte();
     unit_survey_save = tp.GetNextByte();
     unit_survey_length = tp.GetNextDWord();
     UInt32 rsvd = tp.GetNextDWord();
 }
        private void io_options(TsipPacket tp)
        {
            Debug.Print("Packet 55 (I/O options):");

            byte posn = tp.GetNextByte();
            byte vel = tp.GetNextByte();
            byte timing = tp.GetNextByte();
            byte aux = tp.GetNextByte();
            level_type = ((aux & 0x08) == 0x08) ? "dB" : "AMU";
        }
        private void timing_msg(TsipPacket tp)
        {
            byte subcode = tp.GetNextByte();

            if (subcode == 0x15)
                datums(tp);
            else if (subcode == 0x41)
                manuf_params(tp);
            else if (subcode == 0x42)
                prodn_params(tp);
            else if (subcode == 0x4A)
                pps_settings(tp);
            else if (subcode == 0xA0)
                dac_values(tp);
            else if (subcode == 0xA1)
                osc_sense(tp);
            else if (subcode == 0xA2)
                pps_timing_mode(tp);
            else if (subcode == 0xA5)
                packet_mask(tp);
            else if (subcode == 0xA7)
                sat_solutions(tp);   // not on ThunderBolt-E
            else if (subcode == 0xA8)
                discipline_params(tp);
            else if (subcode == 0xA9)
                survey_params(tp);
            else if (subcode == 0xAB)
                primary_timing(tp);
            else if (subcode == 0xAC)
                secondary_timing(tp);
            else
                unknown_msg(tp);
        }
        private void manuf_params(TsipPacket tp)
        {
            Debug.Print("Packet 8F.41 (Manufacturing Params):");

            UInt16 sn_prefix = tp.GetNextWord();
            UInt32 serial_num = tp.GetNextDWord();
            byte build_year = tp.GetNextByte();
            byte build_month = tp.GetNextByte();
            byte build_day = tp.GetNextByte();
            byte build_hour = tp.GetNextByte();
            Single osc_offset = tp.GetNextSingle();
            UInt16 test_code = tp.GetNextWord();

            unit_build.Date = new DateTime(build_year + 2000, build_month, build_day, build_hour, 0, 0);
            unit_build.SerialNumber = sn_prefix.ToString() + "-" + serial_num.ToString();
        }
        private void version_info(TsipPacket tp)
        {
            Debug.Print(":0x45 (Software Version Info Received)");

            byte ap_major = tp.GetNextByte();  // Application firmware
            byte ap_minor = tp.GetNextByte();
            byte ap_month = tp.GetNextByte();
            byte ap_day = tp.GetNextByte();
            UInt16 ap_year = (ushort)(tp.GetNextByte() + 2000); // docs say 1900 based!

            byte core_major = tp.GetNextByte(); // GPS firmware
            byte core_minor = tp.GetNextByte();
            byte core_month = tp.GetNextByte();
            byte core_day = tp.GetNextByte();
            UInt16 core_year = (ushort)(tp.GetNextByte() + 2000); // docs say 1900 based!

            try
            {
                unit_firmware.Major = ap_month;
                unit_firmware.Minor = ap_minor;
                unit_firmware.Date = new DateTime(ap_year, ap_month, ap_day);

                unit_hardware.Major = core_major;
                unit_hardware.Minor = core_minor;
                unit_hardware.Date = new DateTime(core_year, core_month, core_day);

                if (SoftwareVersionInfoReceived != null)
                    SoftwareVersionInfoReceived(this, new VersionInfoEventArgs(unit_firmware));

                if (HardwareVersionInfoReceived != null)
                    HardwareVersionInfoReceived(this, new VersionInfoEventArgs(unit_hardware));
            }
            catch (Exception e)
            {
                Debug.Print("Exception:" + e.Message);
            }
        }
        private void packet_58(TsipPacket tp)
        {
            Debug.Print("Packet 58 (GPS system data):");

            byte op = tp.GetNextByte();
            byte type = tp.GetNextByte();
            byte prn = tp.GetNextByte();
            byte len = tp.GetNextByte();
        }
        private void pps_settings(TsipPacket tp)
        {
            Debug.Print("Packet 8F.4A (PPS settings):");

            byte pps_enabled = tp.GetNextByte();
            byte pps_rsvd = tp.GetNextByte();
            byte pps_polarity = tp.GetNextByte();
            Double cable_delay = tp.GetNextDouble();
            Single bias_threshold = tp.GetNextSingle();

            unit_pps = (pps_enabled != 0);
            unit_cable_delay = (cable_delay / 1.0E-9);
        }