using System; using Microsoft.SPOT; using Microsoft.SPOT.Hardware; using System.Text; using System.IO.Ports; using GHI.Premium.System; namespace miniCPF { class uBloxGPS { private static bool stopGPS = false; private static byte[] portReadBytes = new byte[10240]; private static byte[] portInByteArray = new byte[256]; private static int portInByteArrayIndex = 0; private static int portBytesToRead = 0; private static byte[] latByteArray = new byte[16]; private static byte[] lonByteArray = new byte[16]; private static int latCopyStartIndex; private static int latCopyLength; private static int lonCopyStartIndex; private static int lonCopyLength; private static byte[] RMCMessage = new byte[256]; private static int tokenCounter = 0; private static int index = 0; private static int hour = 1; private static int minute = 0; private static int second = 0; private static int year = 0; private static int month = 0; private static int day = 0; private static SerialPort GPSPort = new SerialPort("COM3", 9600, Parity.None); private static object uBloxLock = new object(); private static StringBuilder sb = new StringBuilder(256); public static void start() { GPSPort.Open(); GPSPort.DiscardInBuffer(); GPSPort.DiscardOutBuffer(); GPSPort.DataReceived += new SerialDataReceivedEventHandler(GPSPortDataReceived); } public static void stop() { stopGPS = true; } public static void close() { GPSPort.Close(); } private static void GPSPortDataReceived(object sender, SerialDataReceivedEventArgs e) { portBytesToRead = GPSPort.BytesToRead; try { GPSPort.Read(portReadBytes, 0, portBytesToRead); } catch { Debug.Print("GPS Read Exception"); //TODO do something smarter here } for (int i = 0; i < portBytesToRead; i++) { portInByteArray[portInByteArrayIndex] = portReadBytes[i]; if (portInByteArrayIndex == 0) //Check to make sure first character is = $ (NMEA standard start of string) { if (portInByteArray[0] == 36) //only move on to byte index 1 after we get a $ { portInByteArrayIndex = portInByteArrayIndex + 1; } } else { if (portInByteArray[portInByteArrayIndex] == 10) { parseNMEA(portInByteArray); portInByteArrayIndex = 0; Array.Clear(portInByteArray, 0, portInByteArray.Length); } else { portInByteArrayIndex = portInByteArrayIndex + 1; } } } if (stopGPS) { GPSPort.DiscardInBuffer(); //TODO This doesn't seem to work 100% of the time, still get exceptions once in a while GPSPort.Close(); } } private static void parseNMEA(byte[] NMEAByteArray) { if (!Program.timeSynched) { if ((NMEAByteArray[1] == (byte)'G') && (NMEAByteArray[2] == (byte)'P') && (NMEAByteArray[3] == (byte)'R') && //TODO Probably need a more robust way to do this (NMEAByteArray[4] == (byte)'M') && (NMEAByteArray[5] == (byte)'C')) { uBloxGPS.parseRMC(NMEAByteArray); } } } private static void parseRMC(byte[] RMCByteArray) { tokenCounter = 0; for (int i = 0; i < 80; i++) { if (RMCByteArray[i] == 44) //The NMEA separator is a comma (',') = ASCII 44 { tokenCounter = tokenCounter + 1; //Time is the first field after $GPRMC hhmmss.sss if (tokenCounter == 1) { hour = (RMCByteArray[i + 1] - 48) * 10 + (RMCByteArray[i + 2] - 48); minute = (RMCByteArray[i + 3] - 48) * 10 + (RMCByteArray[i + 4] - 48); second = (RMCByteArray[i + 5] - 48) * 10 + (RMCByteArray[i + 6] - 48); } if (tokenCounter == 3) { latCopyStartIndex = i + 1; } if (tokenCounter == 5) { latCopyLength = i - latCopyStartIndex; lonCopyStartIndex = i + 1; } if (tokenCounter == 7) { lonCopyLength = i - lonCopyStartIndex; Array.Clear(latByteArray, 0, latByteArray.Length); Array.Copy(RMCByteArray, latCopyStartIndex, latByteArray, 0, latCopyLength); Array.Clear(lonByteArray, 0, lonByteArray.Length); Array.Copy(RMCByteArray, lonCopyStartIndex, lonByteArray, 0, lonCopyLength); } if (tokenCounter == 9) //Date is the 9th field ddmmyy { day = (RMCByteArray[i + 1] - 48) * 10 + (RMCByteArray[i + 2] - 48); month = (RMCByteArray[i + 3] - 48) * 10 + (RMCByteArray[i + 4] - 48); year = 2000 + (RMCByteArray[i + 5] - 48) * 10 + (RMCByteArray[i + 6] - 48); CPFUtilities.synchTime(year, month, day, hour, minute, second); } } } //CPFUtilities.tick(); buildRMCLogMessage(); //CPFUtilities.tock(); } //TODO Decide if we really need this method private static byte[] buildRMCLogMessage() { Array.Clear(RMCMessage, 0, RMCMessage.Length); //RMCMessage = Logger.getNewLogArrayHeader(UTF8Encoding.UTF8.GetBytes("RMC message for Time Synch")); sb.Clear(); sb.Append(UTF8Encoding.UTF8.GetChars(RMCMessage)); Debug.Print(sb.ToString()); tokenCounter = 0; index = Array.IndexOf(RMCMessage, 0); for (int i = 0; i < (int)Logger.ColumnNums.lastColumn; i++) { // RMCMessage[index] = Logger.token; index = index + 1; if (tokenCounter == (int)Logger.ColumnNums.lat) { Array.Copy(latByteArray, 0, RMCMessage, index, (Array.IndexOf(latByteArray, 0) + 1)); sb.Clear(); sb.Append(UTF8Encoding.UTF8.GetChars(RMCMessage)); Debug.Print(sb.ToString()); index = index + Array.IndexOf(latByteArray, 0); } if (tokenCounter == (int)Logger.ColumnNums.lon) { Array.Copy(lonByteArray, 0, RMCMessage, index, (Array.IndexOf(lonByteArray, 0) + 1)); sb.Clear(); sb.Append(UTF8Encoding.UTF8.GetChars(RMCMessage)); Debug.Print(sb.ToString()); index = index = Array.IndexOf(lonByteArray, 0); } tokenCounter = tokenCounter + 1; } return RMCMessage; } } }