An implementation of the Sirf Binary and NMEA Protocol for gps devices using the SiRFstarIII chipset

Files at this revision

API Documentation at this revision

Comitter:
p3p
Date:
Thu Jun 28 21:17:29 2012 +0000
Commit message:
update to baud selection

Changed in this revision

BinaryPackets.h Show annotated file Show diff for this revision Revisions of this file
GpsInterface.cpp Show annotated file Show diff for this revision Revisions of this file
GpsInterface.h Show annotated file Show diff for this revision Revisions of this file
NmeaPackets.h Show annotated file Show diff for this revision Revisions of this file
sIRFstarIII.cpp Show annotated file Show diff for this revision Revisions of this file
sIRFstarIII.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 43da35949666 BinaryPackets.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BinaryPackets.h	Thu Jun 28 21:17:29 2012 +0000
@@ -0,0 +1,268 @@
+#ifndef SIRF_PROTOCOL_BINARY_PACKETS
+#define SIRF_PROTOCOL_BINARY_PACKETS
+
+namespace SirfStarIII {
+
+namespace BinaryPacket {
+
+enum PacketNames {
+    //inbound
+    ID_MeasuredTrackingData = 4,
+    ID_DGPSStatus = 27,
+    ID_GeodeticNavigationData = 41,
+    //outbound
+    ID_ConfigureNMEA = 129,
+    ID_SetBinarySerialPort = 134,
+    ID_SetProtocol = 135
+};
+
+class SetProtocol : public SimpleSerialProtocol::Packet {
+public:
+    SetProtocol(uint8_t _protocol) {
+        interface.protocol = _protocol;
+    }
+
+#pragma pack(push, 1)
+    struct Interface {
+        Interface() {
+            message_id = ID_SetProtocol;
+        }
+        uint8_t message_id;
+        uint8_t protocol;
+    } interface;
+#pragma pack(pop)
+
+};
+
+class SetBinarySerialPort :  public SimpleSerialProtocol::Packet {
+public:
+    SetBinarySerialPort(uint32_t _bitrate) {
+        interface.bitrate = swapEndian(_bitrate);
+    }
+#pragma pack(push, 1)
+    struct Interface {
+        Interface() {
+            message_id = ID_SetBinarySerialPort;
+            data_bits = 8;
+            stop_bit = 1;
+            parity = 0;
+        }
+        uint8_t message_id;
+        uint32_t bitrate;
+        uint8_t data_bits;
+        uint8_t stop_bit;
+        uint8_t parity;
+        uint8_t padding;
+    } interface;
+#pragma pack(pop)
+};
+
+class ConfigureNMEA :  public SimpleSerialProtocol::Packet {
+public:
+    ConfigureNMEA(uint16_t _bitrate) {
+        interface.bitrate = swapEndian(_bitrate);;
+    }
+
+#pragma pack(push, 1)
+    struct Interface {
+        Interface() {
+            message_id = ID_ConfigureNMEA;
+            mode = 2;
+            gga_message = 0;
+            gga_checksum = 1;
+            gll_message = 0;
+            gll_checksum = 1;
+            gsa_message = 0;
+            gsa_checksum = 1;
+            gsv_message = 0;
+            gsv_checksum = 1;
+            rmc_message = 1;
+            rmc_checksum = 1;
+            vtg_message = 0;
+            vtg_checksum = 1;
+            mss_message = 0;
+            mss_checksum = 1;
+            epe_message = 0;
+            epe_checksum = 0;
+            zda_message = 0;
+            zda_checksum = 1;
+            padding = 0;
+        }
+        uint8_t message_id;
+        uint8_t mode;
+        uint8_t gga_message;
+        uint8_t gga_checksum;
+        uint8_t gll_message;
+        uint8_t gll_checksum;
+        uint8_t gsa_message;
+        uint8_t gsa_checksum;
+        uint8_t gsv_message;
+        uint8_t gsv_checksum;
+        uint8_t rmc_message;
+        uint8_t rmc_checksum;
+        uint8_t vtg_message;
+        uint8_t vtg_checksum;
+        uint8_t mss_message;
+        uint8_t mss_checksum;
+        uint8_t epe_message;
+        uint8_t epe_checksum;
+        uint8_t zda_message;
+        uint8_t zda_checksum;
+        uint16_t padding;
+        uint16_t bitrate;
+    } interface;
+#pragma pack(pop)
+
+};
+
+class MeasuredTrackingData : public SimpleSerialProtocol::Packet {
+public:
+    MeasuredTrackingData() {}
+
+#pragma pack(push, 1)
+    struct Interface {
+        uint8_t message_id;
+        int16_t gps_week;
+        uint32_t gps_time_of_week;
+        uint8_t channels;
+        struct {
+            uint8_t svid;
+            uint8_t azimuth;
+            uint8_t elevation;
+            uint16_t state;
+            uint8_t c_no_1;
+            uint8_t c_no_2;
+            uint8_t c_no_3;
+            uint8_t c_no_4;
+            uint8_t c_no_5;
+            uint8_t c_no_6;
+            uint8_t c_no_7;
+            uint8_t c_no_8;
+            uint8_t c_no_9;
+            uint8_t c_no_10;
+        } channel_data[12];
+    };
+#pragma pack(pop)
+
+    static void swapByteOrder(Interface* interface) {
+        interface->gps_week = swapEndian(interface->gps_week);
+        interface->gps_time_of_week = swapEndian(interface->gps_time_of_week);
+        for (int i = 0; i < 12; i++) {
+            interface->channel_data[i].state = swapEndian(interface->channel_data[i].state);
+        }
+    }
+};
+
+class DGPSStatus : public SimpleSerialProtocol::Packet {
+public:
+#pragma pack(push, 1)
+    struct Interface {
+        uint8_t message_id;
+        uint8_t dgps_source;
+        union {
+            struct {
+                int32_t beacon_frequency;
+                uint8_t beacon_bitrate;
+                uint8_t status;
+                int32_t signal_magnitude;
+                int16_t signal_strength;
+                int16_t signal_noise_ratio;
+            };
+            struct {
+                uint8_t correction_age[12];
+                uint16_t reserved;
+            };
+        };
+        struct {
+            uint8_t satalite_prn_code;
+            int16_t dgps_correction;
+        } satalite_corrections[12];
+    };
+#pragma pack(pop)
+
+    static void swapByteOrder(Interface* interface) {
+        for (int i = 0; i < 12; i++) {
+            interface->satalite_corrections[i].dgps_correction = swapEndian(interface->satalite_corrections[i].dgps_correction);
+        }
+    }
+};
+
+class GeodeticNavigationData : public SimpleSerialProtocol::Packet {
+public:
+#pragma pack(push, 1)
+    struct Interface {
+        uint8_t message_id;
+        uint16_t nav_valid;
+        uint16_t nav_type;
+        uint16_t week_number;
+        uint32_t time_of_week;
+        uint16_t year;
+        uint8_t month;
+        uint8_t day;
+        uint8_t hour;
+        uint8_t minute;
+        uint16_t second;
+        uint32_t satalite_id_list;
+        int32_t latitude;
+        int32_t longitude;
+        int32_t altitude_elipsoid;
+        int32_t altitude_MSL;
+        int8_t map_datum;
+        uint16_t speed_over_ground;
+        uint16_t course_over_ground;
+        int16_t magnetic_variation;
+        int16_t climb_rate;
+        int16_t heading_rate;
+        uint32_t est_h_position_error;
+        uint32_t est_v_position_error;
+        uint32_t est_time_error;
+        uint16_t est_h_velocity_error;
+        int32_t clock_bias;
+        uint32_t clock_bias_error;
+        int32_t clock_drift;
+        uint32_t clock_drift_error;
+        uint32_t distance;
+        uint16_t distance_error;
+        uint16_t heading_error;
+        uint8_t satalites_in_fix;
+        uint8_t horizontal_dilution_of_presision;
+        uint8_t additional_mode_info;
+    };
+#pragma pack(pop)
+
+    static void swapByteOrder(Interface* interface) {
+        interface->nav_valid = swapEndian(interface->nav_valid);
+        interface->nav_type = swapEndian(interface->nav_type);
+        interface->week_number = swapEndian(interface->week_number);
+        interface->time_of_week = swapEndian(interface->time_of_week);
+        interface->year = swapEndian(interface->year);
+        interface->second = swapEndian(interface->second);
+        interface->satalite_id_list = swapEndian(interface->satalite_id_list);
+        interface->latitude = swapEndian(interface->latitude);
+        interface->longitude = swapEndian(interface->longitude);
+        interface->altitude_elipsoid = swapEndian(interface->altitude_elipsoid);
+        interface->altitude_MSL = swapEndian(interface->altitude_MSL);
+        interface->speed_over_ground = swapEndian(interface->speed_over_ground);
+        interface->course_over_ground = swapEndian(interface->course_over_ground);
+        interface->magnetic_variation = swapEndian(interface->magnetic_variation);
+        interface->climb_rate = swapEndian(interface->climb_rate);
+        interface->heading_rate = swapEndian(interface->heading_rate);
+        interface->est_h_position_error = swapEndian(interface->est_h_position_error);
+        interface->est_v_position_error = swapEndian(interface->est_v_position_error);
+        interface->est_time_error = swapEndian(interface->est_time_error);
+        interface->est_h_velocity_error = swapEndian(interface->est_h_velocity_error);
+        interface->clock_bias = swapEndian(interface->clock_bias);
+        interface->clock_bias_error = swapEndian(interface->clock_bias_error);
+        interface->clock_drift = swapEndian(interface->clock_drift);
+        interface->clock_drift_error = swapEndian(interface->clock_drift_error);
+        interface->distance = swapEndian(interface->distance);
+        interface->distance_error = swapEndian(interface->distance_error);
+        interface->heading_error = swapEndian(interface->heading_error);
+    }
+};
+
+}
+
+}
+
+#endif
\ No newline at end of file
diff -r 000000000000 -r 43da35949666 GpsInterface.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GpsInterface.cpp	Thu Jun 28 21:17:29 2012 +0000
@@ -0,0 +1,88 @@
+#include "GpsInterface.h"
+
+namespace SirfStarIII {
+
+GpsInterface::GpsInterface(PinName tx, PinName rx) : SirfStarIII(tx, rx) {
+    receiveCallback(BinaryPacket::ID_GeodeticNavigationData, this,  &GpsInterface::onReceiveGeodeticNavigationData);
+    receiveCallback(BinaryPacket::ID_MeasuredTrackingData, this,  &GpsInterface::onReceiveMeasuredTrackingData);
+    receiveCallback(BinaryPacket::ID_DGPSStatus, this,  &GpsInterface::onReceiveDGPSStatus);
+    receiveCallback(NMEAPacket::ID_RMC, this,  &GpsInterface::onReceiveRMC);
+}
+
+void GpsInterface::onReceiveGeodeticNavigationData(SimpleSerialProtocol::Packet* packet) {
+    if(!packet)return;
+    
+    if (packet->_valid) {
+        BinaryPacket::GeodeticNavigationData::Interface* interface = packet->interpretData<BinaryPacket::GeodeticNavigationData::Interface>();
+        if (interface) {
+            BinaryPacket::GeodeticNavigationData::swapByteOrder(interface);
+            _fix.sats =  interface->satalites_in_fix;
+            _position.longitude = (((float)interface->longitude)/10000000);
+            _position.latitude = (((float)interface->latitude)/10000000);
+
+            _time.year = interface->year;
+            _time.month = interface->month;
+            _time.day = interface->day;
+            _time.hours = interface->hour;
+            _time.minutes = interface->minute;
+            _time.seconds = interface->second/1000;
+        }
+    }
+    return;
+}
+
+void GpsInterface::onReceiveMeasuredTrackingData(SimpleSerialProtocol::Packet* packet) {
+    if(!packet)return;
+    
+    if (packet->_valid) {
+        BinaryPacket::MeasuredTrackingData::Interface* interface = packet->interpretData<BinaryPacket::MeasuredTrackingData::Interface>();
+        if (interface) {
+
+        }
+    }
+    return;
+}
+
+void GpsInterface::onReceiveDGPSStatus(SimpleSerialProtocol::Packet* packet) {
+    if(!packet)return;
+    
+    if (packet->_valid) {
+        BinaryPacket::DGPSStatus::Interface* interface = packet->interpretData<BinaryPacket::DGPSStatus::Interface>();
+        if (interface) {
+
+        }
+    }
+    return;
+}
+
+void GpsInterface::onReceiveRMC(SimpleSerialProtocol::Packet* packet) {
+    if(!packet)return;
+    
+    NMEAPacket::NMEAPacket nmeaPacket;
+    if (packet->_valid) {
+        nmeaPacket.interpretData(packet);
+        float time = atof(nmeaPacket._fields[1].c_str());
+        _time.seconds = (int)time % 100;
+        _time.minutes = (int)(time / 100)%100;
+        _time.hours =  (int)(time / 10000);
+
+        //   2 Time Status
+        _position.latitude.set(atof(nmeaPacket._fields[3].c_str()), (char)nmeaPacket._fields[4].c_str()[0]);
+        _position.longitude.set(atof(nmeaPacket._fields[5].c_str()), (char)nmeaPacket._fields[6].c_str()[0]);
+        _position.speed = atof(nmeaPacket._fields[7].c_str());
+        _position.course = atof(nmeaPacket._fields[8].c_str());
+
+        uint32_t date = atoi(nmeaPacket._fields[9].c_str());
+        _time.year = 2000 + (date % 100);
+        date /= 100;
+        _time.month = date % 100;
+        _time.day = date / 100;
+
+        // 10   magnetic variation
+        // 11   mode
+    }
+
+    return;
+}
+
+}
\ No newline at end of file
diff -r 000000000000 -r 43da35949666 GpsInterface.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GpsInterface.h	Thu Jun 28 21:17:29 2012 +0000
@@ -0,0 +1,95 @@
+#ifndef SIRF_PROTOCOL_GPS_INTERFACE
+#define SIRF_PROTOCOL_GPS_INTERFACE
+
+#include "sIRFstarIII.h"
+
+namespace SirfStarIII {
+
+class GpsInterface : public SirfStarIII {
+public:
+    GpsInterface(PinName tx, PinName rx);
+    virtual ~GpsInterface() {}
+
+    void onReceiveGeodeticNavigationData(SimpleSerialProtocol::Packet* packet);
+    void onReceiveMeasuredTrackingData(SimpleSerialProtocol::Packet* packet);
+    void onReceiveDGPSStatus(SimpleSerialProtocol::Packet* packet);
+    void onReceiveRMC(SimpleSerialProtocol::Packet* packet);
+    
+    class Coordinate {
+    public:
+        Coordinate() {
+            _gps_format = 0;
+            _dec_degrees = 0;
+            _degrees = 0;
+            _minutes = 0;
+            _seconds = 0;
+        }
+        ~Coordinate() {}
+        float _gps_format;
+        char _indicator;
+        float _dec_degrees;
+        uint16_t _degrees;
+        uint16_t _minutes;
+        float _seconds;
+
+        void set(float raw, char indicator) {
+            if(indicator == '0')return;
+            if (raw < 10000) {
+                raw = raw / 100;
+            } else {
+                raw = raw / 1000;
+            }
+            _gps_format = raw;
+            _degrees = static_cast<uint16_t>(raw);
+            raw = (raw - _degrees)*100;
+            _minutes = static_cast<uint16_t>(raw);
+            _seconds = 60 * (raw - _minutes);
+            _dec_degrees = _degrees + (float)((float)_minutes/60) + (float)(_seconds/3600);
+            _indicator = indicator;
+            if(indicator == 'S' || indicator == 'W') _dec_degrees *= -1;
+        }
+
+        void operator= (float param) {
+           _dec_degrees = param;
+        }
+        
+    };
+
+    struct FixData {
+        enum Type {
+            NoFix,
+            Fixed,
+            DifFix,
+            Reserved1,
+            Reserved2,
+            Reserved3,
+            DeadReckFix
+        };
+        uint8_t valid;
+        uint8_t fix_type;
+        uint8_t sats;
+    } _fix;
+
+    struct Position {
+        Coordinate longitude;
+        Coordinate latitude;
+        float altitude;
+        float speed;
+        float course;
+        uint8_t fix_type;
+    } _position;
+
+    struct Time {
+        uint16_t year;
+        uint8_t month;
+        uint8_t day;
+        uint8_t hours;
+        uint8_t minutes;
+        uint8_t seconds;
+    } _time;
+
+};
+
+}
+
+#endif
\ No newline at end of file
diff -r 000000000000 -r 43da35949666 NmeaPackets.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NmeaPackets.h	Thu Jun 28 21:17:29 2012 +0000
@@ -0,0 +1,52 @@
+#ifndef SIRF_PROTOCOL_NMEA_PACKETS
+#define SIRF_PROTOCOL_NMEA_PACKETS
+
+#include <string>
+#include <vector>
+#include <map>
+
+namespace SirfStarIII {
+
+namespace NMEAPacket {
+
+enum PacketNames{
+    ID_GGA, //Time, position and fix type data.
+    ID_GLL, //Latitude, longitude, UTC time of position fix and status.
+    ID_GSA, //GPS receiver operating mode, satellites used in the position solution, and DOP values.
+    ID_GSV, //The number of GPS satellites in view satellite ID numbers, elevation, azimuth, and SNR values.
+    ID_MSS, //Signal-to-noise ratio, signal strength, frequency, and bit rate from a radio-beacon receiver.
+    ID_RMC, //Time, date, position, course and speed data.
+    ID_VTG, //Course and speed information relative to the ground.
+    ID_ZDA, //PPS timing message (synchronized to PPS).
+    ID_150 //OK to send message.
+};
+
+class NMEAPacket {
+public:
+    NMEAPacket() {}
+    virtual ~NMEAPacket() {}
+
+    std::vector<std::string> _fields;
+    
+    void interpretData(SimpleSerialProtocol::Packet* packet) {
+        std::string raw_data( (char *) packet->_data);
+        std::string  temp;
+        while (raw_data.find(",", 0) != std::string::npos) {
+            size_t  pos = raw_data.find(",", 0);
+            temp = raw_data.substr(0, pos);
+            raw_data.erase(0, pos + 1);
+            if (temp.size() == 0) {
+                temp = "0";
+            }
+            _fields.push_back(temp);
+        }
+        _fields.push_back(raw_data);
+    }
+
+};
+
+}
+
+}
+
+#endif
\ No newline at end of file
diff -r 000000000000 -r 43da35949666 sIRFstarIII.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sIRFstarIII.cpp	Thu Jun 28 21:17:29 2012 +0000
@@ -0,0 +1,373 @@
+#include "sIRFstarIII.h"
+
+extern Serial debug;
+
+namespace SirfStarIII {
+
+SirfStarIII::SirfStarIII(PinName tx, PinName rx) : SimpleSerialProtocol::Protocol(tx, rx, LED1) {
+    _mode = BINARY;
+}
+
+SirfStarIII::~SirfStarIII() {
+
+}
+
+void SirfStarIII::initialise() {
+    //find the device
+    selectMode(_mode, 57600, true);
+    _receive_timeout.start();
+}
+
+void SirfStarIII::initialise(ProtocolMode mode, uint32_t baud_rate) {
+    selectMode(mode, baud_rate, true);
+    _receive_timeout.start();
+}
+
+void SirfStarIII::receive() {
+    if (_mode == BINARY) {
+        receiveBinary();
+    } else if (_mode == NMEA) {
+        receiveNMEA();
+    }
+}
+
+void SirfStarIII::sendPacket(SimpleSerialProtocol::Packet* packet) {
+    if (_mode == BINARY) {
+        sendBinaryPacket(packet);
+    } else if (_mode == NMEA) {
+        sendNMEAPacket(packet);
+    }
+}
+
+void SirfStarIII::receiveBinary() {
+    uint8_t new_byte = 0;
+    uint16_t cs = 0;
+    _receive_timeout.reset();
+    while ( MODSERIAL::rxBufferGetCount() > 0 &&  _receive_timeout.read_us() < 50 ) {
+        switch (_state) {
+            case PACKET_START:
+                new_byte = MODSERIAL::getc();
+                if (_last_byte == 0xA0 && new_byte == 0xA2) {
+                    _state = HEADER_RECEIVE;
+                }
+                _last_byte = new_byte;
+                break;
+
+            case HEADER_RECEIVE:
+                _header[_header_read++] = MODSERIAL::getc();
+                if (_header_read == 2) {
+                    _state = HEADER_DECODE;
+                }
+                break;
+
+            case HEADER_DECODE:
+                _packet._size = *(uint16_t*) _header;
+                _packet._size = _packet.swapEndian(_packet._size);
+                if (_packet._size < 512) {
+                    _state = DATA_RECEIVE;
+                } else {
+                    _state = PACKET_RESET;
+                }
+                break;
+
+            case DATA_RECEIVE:
+                if (_data_read < _packet._size) {
+                    _packet._data[_data_read++] = MODSERIAL::getc();
+                    if (_data_read == _packet._size) {
+                        _state = FOOTER_RECEIVE;
+                    }
+                }
+                break;
+
+            case FOOTER_RECEIVE:
+                if (_footer_read < 4) {
+                    _footer[_footer_read++] =  MODSERIAL::getc();
+                } else {
+                    _state = DATA_VALIDATE;
+                }
+                break;
+
+            case DATA_VALIDATE:
+                if (_footer[2] == 0xB0 && _footer[3] == 0xB3) {
+
+                    _packet._checksum =  *(uint16_t*) _footer;
+                    _packet._checksum = _packet.swapEndian(_packet._checksum);
+
+                    cs = checksumBinary(_packet._data, _packet._size);
+
+                    if (cs == _packet._checksum) {
+                        _packet._type = _packet._data[0];
+                        _state = PACKET_VALID;
+                        _packet._valid = true;
+                    } else {
+                        _state = PACKET_RESET;
+                    }
+                } else {
+                    _state = PACKET_RESET;
+                }
+                break;
+
+            case PACKET_VALID:
+                if (!_packet._valid) {
+                    _state = PACKET_RESET;
+                } else {
+                    return;
+                }
+                return;
+
+            default:
+                _state = PACKET_START;
+                _header_read = 0;
+                _data_read = 0;
+                _footer_read = 0;
+                break;
+        }
+    }
+}
+
+void SirfStarIII::sendBinaryPacket(SimpleSerialProtocol::Packet* packet) {
+    if (packet!=0) {
+        send(0xA0);
+        send(0xA2);
+
+        //size (reversed 2 byte value)
+        uint8_t* size_array = reinterpret_cast<uint8_t *>(&packet->_size);
+        send( size_array[1] );
+        send( size_array[0] );
+
+        //packet data
+        for (int i = 0; i < packet->_size; i++) {
+            send(packet->_data[i]);
+        }
+
+        //checksum (reversed 2 byte value)
+        uint16_t check_value = checksumBinary(packet->_data,  packet->_size);
+        uint8_t* check_array = reinterpret_cast<uint8_t *>( &check_value );
+        send( check_array[1] );
+        send( check_array[0] );
+
+        //end bytes
+        send(0xB0);
+        send(0xB3);
+               
+    }
+}
+
+uint16_t SirfStarIII::checksumBinary(uint8_t* packet, uint16_t packet_size) {
+    uint16_t cs = 0;
+    for (int i = 0; i < packet_size; i++) {
+        cs += packet[i];
+        cs &= 32767;
+    }
+    return cs;
+}
+
+void SirfStarIII::receiveNMEA() {
+    uint8_t new_byte = 0;
+    uint16_t cs = 0;
+    char checksum_array[2];
+
+    _receive_timeout.reset();
+    while (MODSERIAL::rxBufferGetCount() > 0 &&  _receive_timeout.read_us() < 50) {
+
+        switch (_state) {
+            case PACKET_START:
+                new_byte = MODSERIAL::getc();
+                if (new_byte == '$') {
+                    _state = DATA_RECEIVE;
+                }
+                break;
+
+            case DATA_RECEIVE:
+                new_byte = MODSERIAL::getc();
+                if (new_byte != '\r') {
+                    _packet._data[_data_read++] = new_byte;
+                } else {
+                    _packet._size = _data_read - 3; //checksum is last 3 bytes
+                    _state = FOOTER_RECEIVE;
+                }
+                break;
+
+            case FOOTER_RECEIVE:
+                //discard '\n"
+                new_byte = MODSERIAL::getc();
+                _state = DATA_VALIDATE;
+                break;
+
+            case DATA_VALIDATE:
+                _packet._data[_packet._size] = 0;
+                checksum_array[0] = _packet._data[_packet._size + 1];
+                checksum_array[1] = _packet._data[_packet._size + 2];
+                cs = (uint16_t)strtoul(checksum_array, 0, 16);
+
+                if (cs == checksumNMEA((const char *)_packet._data)) {
+                    _state = PACKET_VALID;
+                    _packet._valid = true;
+                    std::string raw_data( (char *) _packet._data);
+                    size_t pos = raw_data.find(",", 0);
+                    std::string temp = raw_data.substr(0, pos);
+
+                    if (!temp.compare("GPGGA")) {
+                        _packet._type = NMEAPacket::ID_GGA;
+                    } else if (!temp.compare("GPGLL")) {
+                        _packet._type = NMEAPacket::ID_GLL;
+                    } else if (!temp.compare("GPGSA")) {
+                        _packet._type = NMEAPacket::ID_GSA;
+                    } else if (!temp.compare("GPGSV")) {
+                        _packet._type = NMEAPacket::ID_GSV;
+                    } else if (!temp.compare("GPMSS")) { 
+                        _packet._type = NMEAPacket::ID_MSS;
+                    } else if (!temp.compare("GPRMC")) {
+                        _packet._type = NMEAPacket::ID_RMC;
+                    } else if (!temp.compare("GPVTG")) {
+                        _packet._type = NMEAPacket::ID_VTG;
+                    } else if (!temp.compare("GPZDA")) {
+                        _packet._type = NMEAPacket::ID_ZDA;
+                    } else if (!temp.compare("PSRF150")) {
+                        _packet._type = NMEAPacket::ID_150;
+                    } else {
+                        _packet._type = 255;
+                    }
+                } else {
+                    _state = PACKET_RESET;
+                }
+                break;
+
+            case PACKET_VALID:
+                if (!_packet._valid) {
+                    _state = PACKET_RESET;
+                } else {
+                    return;
+                }
+
+            default:
+                _state = PACKET_START;
+                _data_read = 0;
+                break;
+        }
+    }
+}
+
+void SirfStarIII::sendNMEAPacket(SimpleSerialProtocol::Packet* packet) {
+
+}
+
+uint8_t SirfStarIII::checksumNMEA(const char * command) {
+    uint8_t i = 1;
+    uint8_t command_checksum = command[0];
+    while (command[i] != 0) {
+        command_checksum = command_checksum ^ command[i];
+        i++;
+    }
+    return command_checksum;
+}
+
+void  SirfStarIII::selectMode(ProtocolMode mode, uint32_t baud_rate, bool find_baud) {
+    int default_baud_rate[6];
+    default_baud_rate[0] = 4800;
+    default_baud_rate[1] = 9600;
+    default_baud_rate[2] = 14400;
+    default_baud_rate[3] = 19200;
+    default_baud_rate[4] = 38400;
+    default_baud_rate[5] = 57600;
+
+    _mode = mode;
+/*
+    if (find_baud) {
+        char command[] = "PSRF100,0,%d,8,1,0\0";
+        char buffer[sizeof(command) + 10];
+        snprintf(buffer, sizeof(buffer), command, baud_rate );
+        
+        uint8_t c_checksum = checksumNMEA(buffer);
+        //send NMEA command at all baud rates to switch to BINARY @ 57600
+        for (int i = 0; i < 6; ++i) {
+            Protocol::baud(default_baud_rate[i]);
+            wait_ms(100);
+            Protocol::printf("$%s*%02X\r\n", buffer, c_checksum);
+            blockUntilTxEmpty();
+        }
+
+        //send Binary command at all baud rates to switch to 57600
+        for (int i = 0; i < 6; ++i) {
+            Protocol::baud(default_baud_rate[i]);
+            wait_ms(100);
+            BinaryPacket::SetBinarySerialPort binary_config(baud_rate);
+            binary_config.buildData<BinaryPacket::SetBinarySerialPort::Interface>(&binary_config.interface);
+            sendBinaryPacket(&binary_config);
+            blockUntilTxEmpty();
+            
+            BinaryPacket::ConfigureNMEA nmea_config(baud_rate);
+            nmea_config.buildData<BinaryPacket::ConfigureNMEA::Interface>(&nmea_config.interface);
+            sendBinaryPacket(&nmea_config);
+            blockUntilTxEmpty();
+        }
+
+        //should be binary @ baud now
+    }
+    wait_ms(50);
+    */
+    if (mode == BINARY) {
+        baud(4800);
+        wait_ms(100);
+        //Build the NMEA packet
+        char command[] = "PSRF100,0,%d,8,1,0\0";
+        char buffer[sizeof(command) + 10];
+        snprintf(buffer, sizeof(buffer), command, baud_rate );
+        uint8_t c_checksum = checksumNMEA(buffer);
+        Serial::printf("$%s*%02X\r\n", buffer, c_checksum);
+        wait_ms(10);
+        Serial::printf("$%s*%02X\r\n", buffer, c_checksum);
+        wait_ms(10);
+        Serial::printf("$%s*%02X\r\n", buffer, c_checksum);
+        wait_ms(10);
+        Serial::printf("$%s*%02X\r\n", buffer, c_checksum);
+        wait_ms(10);
+        Serial::printf("$%s*%02X\r\n", buffer, c_checksum);
+        wait_ms(10);
+        Serial::printf("$%s*%02X\r\n", buffer, c_checksum);
+        blockUntilTxEmpty();
+    }
+/*
+    if (mode == NMEA) {
+        Protocol::baud(4800);
+
+        NMEAChangeBaud(baud_rate);
+        wait_ms(10);
+
+        BinaryPacket::ConfigureNMEA nmea_config(baud_rate);
+        nmea_config.buildData<BinaryPacket::ConfigureNMEA::Interface>(&nmea_config.interface);
+        sendBinaryPacket(&nmea_config);
+        
+        BinaryPacket::SetProtocol protocol_select(2);
+        protocol_select.buildData<BinaryPacket::SetProtocol::Interface>(&protocol_select.interface);
+        sendBinaryPacket(&protocol_select);
+        
+        BinaryPacket::SetBinarySerialPort binary_config(baud_rate);
+        binary_config.buildData<BinaryPacket::SetBinarySerialPort::Interface>(&binary_config.interface);
+        sendBinaryPacket(&binary_config);
+        
+       blockUntilTxEmpty();*/
+       baud(baud_rate);
+  //  }
+}
+
+void SirfStarIII::NMEAChangeBaud(uint32_t baud_rate){
+    //Build the NMEA packet
+    char command[] = "PSRF100,1,%d,8,1,0";
+    char buffer[sizeof(command) + 10];
+    snprintf(buffer, sizeof(buffer), command, baud_rate );
+    uint8_t c_checksum = checksumNMEA(buffer);
+    
+    Protocol::printf("$%s*%02X\r\n", buffer, c_checksum);
+    baud(9600);
+}
+
+void SirfStarIII::BinaryChangeBaud(uint32_t baud_rate){
+    BinaryPacket::SetBinarySerialPort binary_config(baud_rate);
+    binary_config.buildData<BinaryPacket::SetBinarySerialPort::Interface>(&binary_config.interface);
+    sendBinaryPacket(&binary_config);
+    blockUntilTxEmpty();
+    baud(baud_rate);
+}
+
+}
\ No newline at end of file
diff -r 000000000000 -r 43da35949666 sIRFstarIII.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sIRFstarIII.h	Thu Jun 28 21:17:29 2012 +0000
@@ -0,0 +1,46 @@
+#ifndef SIRF_PROTOCOL
+#define SIRF_PROTOCOL
+
+#include "mbed.h"
+#include "MODSERIAL.h"
+#include "Protocol.h"
+#include "BinaryPackets.h"
+#include "NmeaPackets.h"
+
+namespace SirfStarIII {
+
+enum ProtocolMode {
+    BINARY,
+    NMEA    
+};
+
+class SirfStarIII : public SimpleSerialProtocol::Protocol {
+public:
+    SirfStarIII(PinName tx, PinName rx);
+    virtual ~SirfStarIII();
+    
+    virtual void initialise();
+    virtual void initialise(ProtocolMode mode, uint32_t baud_rate);
+    virtual void receive();
+    virtual void sendPacket(SimpleSerialProtocol::Packet* packet);
+    
+    void receiveBinary();
+    uint16_t checksumBinary(uint8_t* packet, uint16_t packet_size);
+    void sendBinaryPacket(SimpleSerialProtocol::Packet* packet);
+    
+    void receiveNMEA();
+    uint8_t checksumNMEA(const char * command);
+    void sendNMEAPacket(SimpleSerialProtocol::Packet* packet);
+    
+    void selectMode(ProtocolMode mode, uint32_t baud, bool find_baud = false);
+    void selectBaud(uint32_t baud);
+    
+    void NMEAChangeBaud(uint32_t baud_rate);
+    void BinaryChangeBaud(uint32_t baud_rate);
+        
+    ProtocolMode _mode;
+};
+
+}
+
+#endif
\ No newline at end of file