As I posted yesterday, Antonio Scarfone made a NXC code that managed to read a Bluetooth GPS textual (NMEA-0183 format) readout. I’ve tried the same thing long ago, but for the reasons listed below dropped this project thinking it is impossible…
Why did I think so? Well, the Bluetooth SDK describes in the end of Appendix 1 (Communication protocol) the structure of the “expected” ‘data packet’ - 2 byte packet size, command type byte, command byte and data. This is very different with NMEA format which starts with e.g. $GPGGA and ends with *XX\LF\CR (XX is a 2 char hex checksum, \LF\CR are line feed and cartridge return chars). For me, and many other AFOLs this inconsistent format seemed impossible to overcome with the standard LEGO firmware. Other firmware like pbLua (and soon RobotC) have BT ’stream-mode’ where program can deal with the BT port like simple serial port. GPS communication with pbLua was reported a while ago, and Steve Hassenplug recently converted his Green Monster to use GPS with RobotC. But using GPS with NXC or NXT-G? I thought it will never happen.
All this was true till Antonio’s code came about. I’ve spent several hours looking at the code and going over the firmware source files trying to understand how this works. Here’re my preliminary conclusions.
1. The BT communication is done by the ‘Comm’ module. The firmware consists of several modules, each is invoked in a round robin loop every 1 millisecond.
2. When paired with a GPS, the NXT is the BT master. Thus, it does not expect data over the BT port until the running NXT program checks for data (this is done with the NXTMessageRead syscall, or the ‘ReceiveRemoteString’ in Antonio’s code).
3. After the NXT sends a data packet to the slave (i.e. GPS) checking if ‘messages’ are waiting - a packet ignored by the GPS since the format is not NMEA, the NXT waits and checks if new BT data has arrived.
3. The first two bytes of the data (’$G’ typically) are treated as the packet size - which fools the NXT to think a packet of >128 bytes (size of BT buffer) awaits him. It reads whatever is in the serial buffer (i.e. rest of NMEA data) but as the usual NMEA data is smaller then 128 bytes it waits for another message to complete 128 bytes.
4. The first message data, excluding the first two bytes, are put into the ‘BT Input Buffer’ which is in the IOMap of the comm port starting at offset 1157.
5. When a second packet arrives, the NXT fills all 128 bytes and tries to parse the new “Command”. It expects a Command Type byte of 0×00, 0×01, 0×02, x80 or 0×81 but finds something else - an ASCII char from the NMEA message. Note however, that ‘P’ and ‘Q’ chars (ASCII 0×80 and 0×81) might made the NXT go on parsing the command as either Direct command or System command with possible unexpected outcomes…
6. Since the command is unrecognized - the NXT firmware ignores it, but KEEPS the message (w/o the first 2 bytes, and with second char (index 1) turned into 0×00) in the buffer. Also, in offset 1285 in the IOMap it stores 128 as the size of the packet.
7. Now, a new NXTMessageRead call is needed for the NXT to check again the incoming BT data.
What’s next? I’ve been doing tests with NMEA messages using my PC as the slave BT device, and LabView code that waits for the NXTMessageRead packet and sends NMEA constant back. Works as described above. Another LabView code ran on the NXT, waiting for the IOMap value at 1285 to change from 0, then read all 128 bytes and convert to string. Indeed, I managed to get the text pass from the PC to the NXT, except three characters (first 2 removed as firmware thought this is the size of packet, then another char converted to 0×00 by the firmware). My guess at this stage is that some *asynchronous* loop would allow reading full NMEA strings every few cycles. Once this occurs, i.e. a string starting with $ and ending with * is found in the buffer, then NMEA parsing can be done. Furthermore, as NMEA messages have a checksum (a value which tells if the message was corrupted) it may be possible to verify integrity within the NXT program. Still some work to do till an NXT-G block is out, but most of the mystery is solved…
Question/comments - use this forum topic.