sirf/nmea protocol switch

categories: blog

For my touchbook i recently bought a Navilock USB GPS-Modul NL-302U SIRF III containing a SiRF III chip that are known for their excellent quality.

This is how the baby looks on the inside:

navilock gps

And this is how it looks when attaching it to my linux box:

[40538.052593] pl2303 2-1.2.1:1.0: pl2303 converter detected
[40538.054396] usb 2-1.2.1: pl2303 converter now attached to ttyUSB0

Bus 002 Device 009: ID 067b:2303 Prolific Technology, Inc. PL2303 Serial Port

Unfortunately instead of the widely understood ASCII based NMEA 0183 protocol those chips are using the proprietary, binary SiRF protocol. Luckily the gpsd guys are hosting a pdf documentation of that protocol. Reading that documentation one can also find out that it is possible to switch between NMEA and SiRF modes.

Reading and displaying data from a serial port is most convenient with:

apt-get install python-serial
/usr/share/doc/python-serial/examples/miniterm.py /dev/ttyUSB0 9600

And writing to serial is quickest with:

from serial import Serial
tty = Serial("/dev/ttyUSB0", 9600)
tty.write(message)

or

python -c "from serial import Serial; Serial("/dev/ttyUSB0", 9600).write(message)"

According to section 1.2.3 of the documentation the following message needs to be written to switch from NMEA to SiRF binary mode at 9600 baud:

message = "$PSRF100,0,9600,8,1,0*0C\r\n"

Switching from the default SiRF binary mode to NMEA is more involved but described in section 2.2.2.

Numbers are 7 bit and in big endian notation:

pack = lambda x: chr(x>>8)+chr(x&0xff)

Every message has a start and end sequence

start = "\xa0\xa2"
end = "\xb0\xb3"

The payload is assembled with help from the documentation (only GGA, GSA and GSV messages enabled, 9600 baud)

payload = "\x81\x02\x01\x01\x00\x01\x05\x01\x05\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x25\x80"

Calculate 15 bit checksum:

checksum = sum(map(ord, list(payload))) & 0x7fff

Calculate the length of the payload

length = len(payload)

Assemble message:

message = start + pack(length) + payload + pack(checksum) + end

And after sending it as explained above the device will gladly output NMEA data.

View Comments
blog comments powered by Disqus