From b728db1e262bdaa64b031c95f35d76d151459352 Mon Sep 17 00:00:00 2001 From: Youen Toupin Date: Sun, 12 Apr 2015 12:16:54 +0200 Subject: [PATCH] first version of debug messages display in Serial Monitor console --- OneWireIO.ino | 13 +-- SerialChannel.cpp | 69 ++++++++++++--- SerialChannel.h | 19 +++-- SerialMonitor/SerialMonitor/App.xaml | 12 ++- SerialMonitor/SerialMonitor/App.xaml.cs | 83 +++++++++++++++++++ SerialMonitor/SerialMonitor/MainWindow.xaml | 7 +- .../SerialMonitor/MainWindow.xaml.cs | 3 + .../SerialMonitor/MainWindowContext.cs | 40 +++++++++ SerialMonitor/SerialMonitor/SerialMessage.cs | 26 ++++++ .../SerialMonitor/SerialMonitor.csproj | 3 + .../SerialMonitor/SerialPortExtensions.cs | 44 ++++++++++ 11 files changed, 287 insertions(+), 32 deletions(-) create mode 100644 SerialMonitor/SerialMonitor/MainWindowContext.cs create mode 100644 SerialMonitor/SerialMonitor/SerialMessage.cs create mode 100644 SerialMonitor/SerialMonitor/SerialPortExtensions.cs diff --git a/OneWireIO.ino b/OneWireIO.ino index fa2253e..9bdce34 100644 --- a/OneWireIO.ino +++ b/OneWireIO.ino @@ -14,8 +14,8 @@ byte backBufferPos = 0; byte samplesSkipped = SkipSamples; unsigned long backBufferStartTime = micros(); -SerialChannel oscilloscope; -SerialChannel debug; +SerialChannel oscilloscope("oscilloscope"); +SerialChannel debug("debug"); void setup() { @@ -45,8 +45,6 @@ void setup() sei();//enable interrupts Serial.begin(9600); - oscilloscope.init("oscilloscope"); - debug.init("debug"); } void loop() @@ -60,15 +58,10 @@ void loop() backBufferStartTime = micros(); sei();//enable interrupts - unsigned long now = micros(); - debug.write((byte*)&now, 4); debug.write("Starting buffer transmission"); - oscilloscope.write((byte*)¤tBufferStartTime, 4); - oscilloscope.write(currentBuffer, currentBufferSize); + oscilloscope.write(currentBuffer, currentBufferSize, currentBufferStartTime); - now = micros(); - debug.write((byte*)&now, 4); debug.write("Buffer transmitted"); } diff --git a/SerialChannel.cpp b/SerialChannel.cpp index 64b57f5..51c716e 100644 --- a/SerialChannel.cpp +++ b/SerialChannel.cpp @@ -1,29 +1,72 @@ #include "Arduino.h" #include "SerialChannel.h" -short SerialChannel::nextId = 0; +byte SerialChannel::nextId = 1; +SerialChannel* SerialChannel::first = 0; -SerialChannel::SerialChannel() +SerialChannel::SerialChannel(const char* name_) + : next(0) + , id((byte)-1) + , name(name_) { + if(first == 0) + first = this; + else + { + SerialChannel* c = first; + while(c->next != 0) c = c->next; + c->next = this; + } + + id = nextId++; } -void SerialChannel::init(const char* name) +void SerialChannel::write(byte* data, short byteCount, unsigned long time) { - id = nextId++; - Serial.write((short)0); + if (time == (unsigned long)-1) + time = micros(); + + handleConnection(); + + Serial.write("START"); Serial.write(id); - Serial.write(strlen(name)); - Serial.write(name); + writeULong(time); + writeShort(byteCount); + Serial.write(data, byteCount); } -void SerialChannel::write(byte* data, short byteCount) +void SerialChannel::write(const char* text, unsigned long time) { - Serial.write(byteCount); - Serial.write(id); - Serial.write(data, byteCount); + write((byte*)text, strlen(text), time); } -void SerialChannel::write(const char* text) +void SerialChannel::writeShort(short num) { - Serial.write((byte*)text, strlen(text)); + Serial.write((byte*)&num, 2); } + +void SerialChannel::writeULong(unsigned long num) +{ + Serial.write((byte*)&num, 4); +} + +void SerialChannel::handleConnection() +{ + int b = Serial.read(); + if(b == (int)'C') + { + Serial.write("CONNECTION"); + SerialChannel* c = first; + while(c) + { + Serial.write("START"); + Serial.write(0); + Serial.write("ChannelInit"); + Serial.write(c->id); + writeShort(strlen(c->name)); + Serial.write(c->name); + c = c->next; + } + } +} + diff --git a/SerialChannel.h b/SerialChannel.h index 3c66d7d..7a2d5f8 100644 --- a/SerialChannel.h +++ b/SerialChannel.h @@ -4,17 +4,24 @@ class SerialChannel { private: - static short nextId; - short id; + static SerialChannel* first; + SerialChannel* next; + + static byte nextId; + byte id; + const char* name; public: - SerialChannel(); + SerialChannel(const char* name_); - void init(const char* name); + void write(byte* data, short byteCount, unsigned long time = (unsigned long)-1); - void write(byte* data, short byteCount); + void write(const char* text, unsigned long time = (unsigned long)-1); - void write(const char* text); +private: + void handleConnection(); + void writeShort(short num); + void writeULong(unsigned long num); }; #endif diff --git a/SerialMonitor/SerialMonitor/App.xaml b/SerialMonitor/SerialMonitor/App.xaml index cc3b030..a998b86 100644 --- a/SerialMonitor/SerialMonitor/App.xaml +++ b/SerialMonitor/SerialMonitor/App.xaml @@ -3,6 +3,16 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" StartupUri="MainWindow.xaml"> - + + + + diff --git a/SerialMonitor/SerialMonitor/App.xaml.cs b/SerialMonitor/SerialMonitor/App.xaml.cs index 0ea20d1..24feecc 100644 --- a/SerialMonitor/SerialMonitor/App.xaml.cs +++ b/SerialMonitor/SerialMonitor/App.xaml.cs @@ -2,9 +2,14 @@ using System.Collections.Generic; using System.Configuration; using System.Data; +using System.Diagnostics; +using System.IO.Ports; using System.Linq; +using System.Text; using System.Threading.Tasks; using System.Windows; +using System.Windows.Shapes; +using System.Windows.Threading; namespace SerialMonitor { @@ -13,5 +18,83 @@ namespace SerialMonitor /// public partial class App : Application { + private SerialPort Serial; + private IDictionary Channels = new Dictionary(); + private bool Connected = false; + + protected override void OnStartup(StartupEventArgs e) + { + base.OnStartup(e); + + Serial = new SerialPort(); + Serial.PortName = "COM4"; + Serial.BaudRate = 9600; + + Serial.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(OnDataReceived); + + Serial.Open(); + } + + private void OnDataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) + { + if (!Connected) + { + Serial.Write("C"); + Serial.ReadTo("CONNECTION"); + Connected = true; + } + + // channel declaration message: byte 0 ; string "ChannelInit" ; byte ; short ; byte[length] + // regular message: byte ; short ; byte[length] + + SerialMessage message = null; + + Serial.ReadTo("START"); + + int id = Serial.ReadByte(); + if (id == 0) + { + string check = Encoding.UTF8.GetString(Serial.ReadBytes(11)); + if (check != "ChannelInit") + throw new Exception("Incorrect data check for channel initialization"); + id = Serial.ReadByte(); + int length = Serial.ReadShort(); + string name = Encoding.UTF8.GetString(Serial.ReadBytes(length)); + Channels[id] = name; + message = new SerialMessage { ChannelName = "debug", StringData = "Channel " + name + " opened", SendTime = 0 }; + } + else + { + ulong sendTime = Serial.ReadULong(); + int length = Serial.ReadShort(); + byte[] data = Serial.ReadBytes(length); + message = new SerialMessage { ChannelName = Channels[id], Data = data, SendTime = sendTime }; + } + + if(message != null) + Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => OnMessageReceived(message))); + } + + private void OnMessageReceived(SerialMessage message) + { + switch (message.ChannelName) + { + case "debug": + string text = ((float)message.SendTime / 1000000).ToString("0.000") + "s " + message.StringData; + //Debug.WriteLine(text); + MainWindowContext.Get.WriteLine(text); + break; + case "oscilloscope": + /*float visibleDuration = 10.0f; + float sampleDelay = 0.000936f; + float startOffset = (float)message.SendTime / 1000000; + for (int i = 1; i < message.Data.Length; ++i ) + { + var line = new Line(); + canvas.Children.Add(line); + }*/ + break; + } + } } } diff --git a/SerialMonitor/SerialMonitor/MainWindow.xaml b/SerialMonitor/SerialMonitor/MainWindow.xaml index 51b1a8f..765f627 100644 --- a/SerialMonitor/SerialMonitor/MainWindow.xaml +++ b/SerialMonitor/SerialMonitor/MainWindow.xaml @@ -1,8 +1,11 @@  + Title="Serial Monitor" Height="396" Width="629"> - + + + + diff --git a/SerialMonitor/SerialMonitor/MainWindow.xaml.cs b/SerialMonitor/SerialMonitor/MainWindow.xaml.cs index 11f2c90..d0f0a1d 100644 --- a/SerialMonitor/SerialMonitor/MainWindow.xaml.cs +++ b/SerialMonitor/SerialMonitor/MainWindow.xaml.cs @@ -23,6 +23,9 @@ namespace SerialMonitor public MainWindow() { InitializeComponent(); + var context = new MainWindowContext(); + context.WriteLine("Connecting..."); + this.DataContext = context; } } } diff --git a/SerialMonitor/SerialMonitor/MainWindowContext.cs b/SerialMonitor/SerialMonitor/MainWindowContext.cs new file mode 100644 index 0000000..b16f54f --- /dev/null +++ b/SerialMonitor/SerialMonitor/MainWindowContext.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SerialMonitor +{ + public class MainWindowContext : INotifyPropertyChanged + { + public MainWindowContext() + { + Get = this; + } + + public static MainWindowContext Get { get; private set; } + + private List Lines = new List(); + public string ConsoleText { get { return String.Join("\n", Lines); } } + + public void WriteLine(string line) + { + Lines.Add(line); + if (Lines.Count > 9) + Lines.RemoveAt(0); + OnPropertyChanged("ConsoleText"); + } + + public event PropertyChangedEventHandler PropertyChanged; + protected void OnPropertyChanged(string name) + { + PropertyChangedEventHandler handler = PropertyChanged; + if (handler != null) + { + handler(this, new PropertyChangedEventArgs(name)); + } + } + } +} diff --git a/SerialMonitor/SerialMonitor/SerialMessage.cs b/SerialMonitor/SerialMonitor/SerialMessage.cs new file mode 100644 index 0000000..4e4ed5a --- /dev/null +++ b/SerialMonitor/SerialMonitor/SerialMessage.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SerialMonitor +{ + public class SerialMessage + { + public string ChannelName { get; set; } + + /// + /// Time at which the message was sent, in microseconds since the start of the remote executable + /// + public ulong SendTime { get; set; } + + public byte[] Data { get; set; } + + public string StringData + { + get { return Encoding.UTF8.GetString(Data); } + set { Data = Encoding.UTF8.GetBytes(value); } + } + } +} diff --git a/SerialMonitor/SerialMonitor/SerialMonitor.csproj b/SerialMonitor/SerialMonitor/SerialMonitor.csproj index 6cb916e..1638f28 100644 --- a/SerialMonitor/SerialMonitor/SerialMonitor.csproj +++ b/SerialMonitor/SerialMonitor/SerialMonitor.csproj @@ -53,6 +53,9 @@ MSBuild:Compile Designer + + + MSBuild:Compile Designer diff --git a/SerialMonitor/SerialMonitor/SerialPortExtensions.cs b/SerialMonitor/SerialMonitor/SerialPortExtensions.cs new file mode 100644 index 0000000..91e98bc --- /dev/null +++ b/SerialMonitor/SerialMonitor/SerialPortExtensions.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.IO.Ports; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SerialMonitor +{ + public static class SerialPortExtensions + { + public static int ReadShort(this SerialPort port) + { + int b1 = port.ReadByte(); + int b2 = port.ReadByte(); + return b2 * 256 + b1; + } + + public static ulong ReadULong(this SerialPort port) + { + ulong b1 = (ulong)port.ReadByte(); + ulong b2 = (ulong)port.ReadByte(); + ulong b3 = (ulong)port.ReadByte(); + ulong b4 = (ulong)port.ReadByte(); + return b4 * 256 * 256 * 256 + b3 * 256 * 256 + b2 * 256 + b1; + } + + public static byte[] ReadBytes(this SerialPort port, int numBytes) + { + var bytes = new byte[numBytes]; + int remaining = numBytes; + int pos = 0; + while (remaining > 0) + { + int read = port.Read(bytes, pos, remaining); + if (read < 0) + throw new Exception("Connection closed"); + remaining -= read; + pos += read; + } + return bytes; + } + } +}