sirf/nmea protocol switch
Mon, 18 Apr 2011 20:26 categories: blogFor 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:
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.