diff --git a/ThunderboltTimeSync.sln b/ThunderboltTimeSync.sln index c1ad819..bbe2b29 100644 --- a/ThunderboltTimeSync.sln +++ b/ThunderboltTimeSync.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.25123.0 +VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThunderboltTimeSync", "ThunderboltTimeSync\ThunderboltTimeSync.csproj", "{7D970120-F57C-4541-BD54-2602C59EB8BA}" EndProject diff --git a/ThunderboltTimeSync/FormMain.cs b/ThunderboltTimeSync/FormMain.cs index 9d6b913..012bffd 100644 --- a/ThunderboltTimeSync/FormMain.cs +++ b/ThunderboltTimeSync/FormMain.cs @@ -1,5 +1,7 @@ -using System; +using System.Collections.Generic; using System.Diagnostics; +using System.IO.Ports; +using System.Linq; using System.Windows.Forms; namespace ThunderboltTimeSync { @@ -18,16 +20,19 @@ namespace ThunderboltTimeSync { InitializeComponent(); - Debug.WriteLine(SystemTimeUtils.GetSystemTime().ToString("yyyy-MM-ddTHH:mm:ssK.ffff")); - try { - SystemTimeUtils.SetSystemTime(new DateTime( - 2000, 1, 1, - 10, 0, 0, 0 - )); - } catch (SystemTimeUtils.SystemTimeException stEx) { - Debug.WriteLine(string.Format("Setting system time failed: \"{0}\"", stEx.Message)); - } - Debug.WriteLine(SystemTimeUtils.GetSystemTime().ToString("yyyy-MM-ddTHH:mm:ssK.ffff")); + ThunderboltSerialPort tbsp = new ThunderboltSerialPort(new SerialPort("COM3")); + + tbsp.PacketReceived += (List packetBuffer) => { + List byteStrings = packetBuffer.Select(x => string.Format("{0:X2}", x)).ToList(); + Debug.WriteLine( + string.Format( + "Packet received: {0}", + string.Join(" ", byteStrings) + ) + ); + }; + + tbsp.Open(); } } } diff --git a/ThunderboltTimeSync/ThunderboltSerialPort.cs b/ThunderboltTimeSync/ThunderboltSerialPort.cs new file mode 100644 index 0000000..15a91da --- /dev/null +++ b/ThunderboltTimeSync/ThunderboltSerialPort.cs @@ -0,0 +1,88 @@ +using System.Collections.Generic; +using System.IO.Ports; + +namespace ThunderboltTimeSync { + public class ThunderboltSerialPort { + private static readonly byte CHAR_DLE = 0x10; + private static readonly byte CHAR_ETX = 0x03; + + private List packetBuffer; + private bool inPacket; + + private SerialPort serialPort; + + /// + /// A delegate which is called when a full packet is received over the serial port. + /// The byte buffer passed in contains the initial [DLE], and final [DLE][ETX]. The buffer is completely unparsed and remains stuffed. + /// + /// A byte buffer which contains the packet. + public delegate void PacketReceivedEventHandler(List packetBuffer); + + /// + /// An event which is called when a full packet is received over the serial port. + /// Refer to for more information. + /// + public event PacketReceivedEventHandler PacketReceived; + + /// + /// Creates an instance of the ThunderboltSerialPort class, which processes serial data from a Thunderbolt and + /// The serial port passed into the function must not be opened, or have a delegate already attached to the DataReceived event. + /// + /// The serial port on which to communicate with the Thunderbolt. + public ThunderboltSerialPort(SerialPort serialPort) { + packetBuffer = new List(); + inPacket = false; + + this.serialPort = serialPort; + serialPort.DataReceived += DataReceived; + } + + /// + /// Begins processing serial data. + /// + public void Open() { + serialPort.Open(); + } + + private void DataReceived(object sender, SerialDataReceivedEventArgs e) { + int possibleCurrentByte; + + while ((possibleCurrentByte = serialPort.ReadByte()) != -1) { + // Once we're sure the byte that was read wasn't -1 (which signifies the end of the read), we're safe to cast to a byte + byte currentByte = (byte) possibleCurrentByte; + + if (inPacket) { + packetBuffer.Add(currentByte); + + // Check buffer length to ensure we've reached a plausible end of packet. + // 5 bytes is [DLE]<1 byte of data>[DLE][ETX] + if (currentByte == CHAR_ETX && packetBuffer.Count >= 5) { + int numberOfPrecedingDLEs = 0; + + // Count number of DLEs, excluding the first two bytes (initial DLE and id) + for (int i = 2; i < packetBuffer.Count; ++i) { + if (packetBuffer[i] == CHAR_DLE) { + ++numberOfPrecedingDLEs; + } + } + + // Odd number of DLEs means the ETX does in fact signify the end of the packet + if (numberOfPrecedingDLEs % 2 == 1) { + PacketReceived?.Invoke(packetBuffer); + + packetBuffer.Clear(); + inPacket = false; + } + } + } else { + // A DLE received when not currently in a packet signifies the beginning of a packet + if (currentByte == CHAR_DLE) { + packetBuffer.Add(currentByte); + + inPacket = true; + } + } + } + } + } +} \ No newline at end of file diff --git a/ThunderboltTimeSync/ThunderboltTimeSync.csproj b/ThunderboltTimeSync/ThunderboltTimeSync.csproj index e76789c..8016cf0 100644 --- a/ThunderboltTimeSync/ThunderboltTimeSync.csproj +++ b/ThunderboltTimeSync/ThunderboltTimeSync.csproj @@ -55,6 +55,7 @@ + FormMain.cs