/// <summary> /// This event is called whenever new data is available on our /// serial port. This method is responsible for managing the input /// buffer and turning the bytes into strings that downstream methods /// can parse. /// </summary> /// <param name="ignored1">not used</param> /// <param name="ignored2">not used</param> private void serialPort_DataReceived(object ignored1, SerialDataReceivedEventArgs ignored2) { lock (this) { // if the buffer was all scanned and not useful then dump it if (m_bufferUsed == m_buffer.Length) { m_bufferUsed = 0; } // assume that all of the existing buffer was already scanned // for newlines. We will scan what we just received. int lastScanIndex = this.m_bufferUsed; // this hack backs up our scan by one byte if we saw the CR, // but didn't find the LF because it's in the next byte if (this.m_bufferUsed > 0 && this.m_buffer[this.m_bufferUsed - 1] == '\r') { lastScanIndex--; } // read all of the data that is avaiable int toRead = System.Math.Min(this.m_serialPort.BytesToRead, (this.m_buffer.Length - this.m_bufferUsed)); int bytesRead = this.m_serialPort.Read(this.m_buffer, this.m_bufferUsed, toRead); // publish the debug event if one is registered if (this.RawDataDebugEvent != null) { byte[] rawDataBuffer = new byte[bytesRead]; Array.Copy(m_buffer, m_bufferUsed, rawDataBuffer, 0, bytesRead); var rawData = new NmeaInputDebugEventArgs(rawDataBuffer); RawDataDebugEvent(this, rawData); } this.m_startProcessing = DateTime.Now.Ticks; this.m_bufferUsed += bytesRead; // loop looking for newlines bool foundNewline = true; while (foundNewline) { // scan the buffer for a new line from the last point scanned int nextNewline = 0; int pastNewline = 0; int i; for (i = lastScanIndex; i < this.m_bufferUsed; i++) { // check for a \r\n line ending. if ((this.m_bufferUsed - i) >= 2 && (this.m_buffer[i] == (byte)'\r' && this.m_buffer[i + 1] == (byte)'\n')) { nextNewline = i; pastNewline = i + 2; break; } // check for a \n line ending else if (this.m_buffer[i] == (byte)'\n') { nextNewline = i; pastNewline = i + 1; break; } } // we found a line ending if (nextNewline > 0) { char[] chars = System.Text.Encoding.UTF8.GetChars(this.m_buffer, 0, nextNewline); string line = new string(chars); if (line != null) { ParseNmeaSentence(line); m_startProcessing = DateTime.Now.Ticks; } // shuffle the buffer. not very efficient, we really should use a circular array int toCopy = this.m_bufferUsed - pastNewline; if (toCopy == 0) { // we used the whole buffer, just reset what we've got this.m_bufferUsed = 0; } else { var newBuffer = new byte[this.m_buffer.Length]; Array.Copy(this.m_buffer, pastNewline, newBuffer, 0, this.m_buffer.Length - pastNewline); this.m_bufferUsed = toCopy + 1; this.m_buffer = newBuffer; } } else { foundNewline = false; } } } }
void m_nmeaInputPort_RawDataDebugEvent(object sender, NmeaInputDebugEventArgs args) { char[] chars = System.Text.Encoding.UTF8.GetChars(args.RawData, 0, args.RawData.Length); m_oled.DrawStringAndScroll(m_debugFont, 0, 63, new string(chars)); }