From d9f6e940d72990216bd872435f9ff7fbee9d4ba3 Mon Sep 17 00:00:00 2001 From: arkypita Date: Mon, 21 Aug 2017 11:16:02 +0200 Subject: [PATCH] fix for #76 Fix #76 and add emulator config ability --- LaserGRBL/GrblCore.cs | 37 +++++-- LaserGRBL/GrblEmulator/GrblEmulator.cs | 55 +++++++++- LaserGRBL/LaserGRBL.csproj | 1 + LaserGRBL/MainForm.cs | 2 +- LaserGRBL/Properties/AssemblyInfo.cs | 2 +- LaserGRBL/Tools/Cronometro.cs | 139 +++++++++++++++++++++++++ 6 files changed, 225 insertions(+), 11 deletions(-) create mode 100644 LaserGRBL/Tools/Cronometro.cs diff --git a/LaserGRBL/GrblCore.cs b/LaserGRBL/GrblCore.cs index f96ca5be8..49e6fd2fd 100644 --- a/LaserGRBL/GrblCore.cs +++ b/LaserGRBL/GrblCore.cs @@ -209,16 +209,35 @@ public void ExportConfig(string filename) try { + Tools.AutoResetTimer WaitResponseTimeout = new Tools.AutoResetTimer(TimeSpan.FromSeconds(10), true); - while (cmd.Status == GrblCommand.CommandStatus.WaitingResponse) //resta in attesa della risposta - ; + //resta in attesa dell'invio del comando e della risposta + while (cmd.Status == GrblCommand.CommandStatus.Queued || cmd.Status == GrblCommand.CommandStatus.WaitingResponse) + if (WaitResponseTimeout.Expired) + throw new TimeoutException("No response received from grbl!"); + else + System.Threading.Thread.Sleep(10); - if (cmd.Status != GrblCommand.CommandStatus.ResponseGood) - { - System.Windows.Forms.MessageBox.Show("Error exporting config!", "Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error); - } - else + if (cmd.Status == GrblCommand.CommandStatus.ResponseGood) { + //attendi la ricezione di tutti i parametri + long tStart = Tools.HiResTimer.TotalMilliseconds; + long tLast = tStart; + int counter = mSentPtr.Count; + + //finché l'ultima risposta è più recente di 1s e non sono passati più di 10s totali + while (Tools.HiResTimer.TotalMilliseconds - tLast < 1000 && Tools.HiResTimer.TotalMilliseconds - tStart < 10000) + { + if (mSentPtr.Count != counter) + { + tLast = Tools.HiResTimer.TotalMilliseconds; + counter = mSentPtr.Count; + } + else + { + System.Threading.Thread.Sleep(10); + } + } int msg = 0; foreach (IGrblRow row in mSentPtr) @@ -233,6 +252,10 @@ public void ExportConfig(string filename) sw.Close(); System.Windows.Forms.MessageBox.Show(String.Format("{0} Config exported with success!", msg), "Success", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Information); } + else + { + System.Windows.Forms.MessageBox.Show("Error exporting config!", "Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error); + } } catch (Exception ex) { diff --git a/LaserGRBL/GrblEmulator/GrblEmulator.cs b/LaserGRBL/GrblEmulator/GrblEmulator.cs index b2404f40e..b9290cc5b 100644 --- a/LaserGRBL/GrblEmulator/GrblEmulator.cs +++ b/LaserGRBL/GrblEmulator/GrblEmulator.cs @@ -93,15 +93,66 @@ protected override void OnMessage(MessageEventArgs e) else if (e.Data == "{fb:n}\n") ; else if (e.Data == "!") - {mPaused = true; SendStatus();} + { mPaused = true; SendStatus(); } else if (e.Data == "~") - { mPaused = false; SendStatus(); } + { mPaused = false; SendStatus(); } else if (e.RawData.Length == 1 && e.RawData[0] == 24) GrblReset(); + else if (e.Data == "$$\n") + SendConfig(); + else if (IsSetConf(e.Data)) + SetConfig(e.Data); else EnqueueRX(e); } + System.Text.RegularExpressions.Regex confRegEX = new System.Text.RegularExpressions.Regex(@"^[$](\d+) *= *(\d+\.?\d*)"); + private bool IsSetConf(string p) + {return confRegEX.IsMatch(p);} + + private void SetConfig(string p) + { + try + { + System.Text.RegularExpressions.MatchCollection matches = confRegEX.Matches(p); + int key = int.Parse(matches[0].Groups[1].Value); + + if (configTable.Keys.Contains(key)) + { + if (configTable[key] is int) + configTable[key] = int.Parse(matches[0].Groups[2].Value, System.Globalization.CultureInfo.InvariantCulture); + else if (configTable[key] is decimal) + configTable[key] = decimal.Parse(matches[0].Groups[2].Value, System.Globalization.CultureInfo.InvariantCulture); + else if (configTable[key] is bool) + configTable[key] = int.Parse(matches[0].Groups[2].Value) == 0 ? false : true; + + ImmediateTX("ok"); + } + else + ImmediateTX("error"); + } + catch(Exception ex) + { + ImmediateTX("error"); + } + } + + private Dictionary configTable = new Dictionary { { 0, 10 }, { 1, 25 }, { 2, 0 }, { 3, 0 }, { 4, false }, { 5, false }, { 6, false }, { 10, 1 }, { 11, 0.010m }, { 12, 0.002m }, { 13, false }, { 20, false }, { 21, false }, { 22, false }, { 23, 0 }, { 24, 25.000m }, { 25, 500.000m }, { 26, 250 }, { 27, 1.000m }, { 30, 1000.0m }, { 31, 0.0m }, { 32, false }, { 100, 250.000m }, { 101, 250.000m }, { 102, 250.000m }, { 110, 500.000m }, { 111, 500.000m }, { 112, 500.000m }, { 120, 10.000m }, { 121, 10.000m }, { 122, 10.000m }, { 130, 200.000m }, { 131, 200.000m }, { 132, 200.000m } }; + + private void SendConfig() + { + ImmediateTX("ok"); + foreach (KeyValuePair kvp in configTable) + { + if (kvp.Value is decimal) + ImmediateTX(string.Format(System.Globalization.CultureInfo.InvariantCulture, "${0}={1:0.000}", kvp.Key, kvp.Value)); + else if (kvp.Value is bool) + ImmediateTX(string.Format(System.Globalization.CultureInfo.InvariantCulture, "${0}={1}", kvp.Key, ((bool)kvp.Value) ? 1 : 0)); + else + ImmediateTX(string.Format(System.Globalization.CultureInfo.InvariantCulture, "${0}={1}", kvp.Key, kvp.Value)); + } + } + private void EnqueueRX(MessageEventArgs e) { lock (rxBuf) diff --git a/LaserGRBL/LaserGRBL.csproj b/LaserGRBL/LaserGRBL.csproj index f3fa04c7e..5acfb1e4a 100644 --- a/LaserGRBL/LaserGRBL.csproj +++ b/LaserGRBL/LaserGRBL.csproj @@ -289,6 +289,7 @@ SplashScreenForm.cs + diff --git a/LaserGRBL/MainForm.cs b/LaserGRBL/MainForm.cs index 983265fd1..94091a51d 100644 --- a/LaserGRBL/MainForm.cs +++ b/LaserGRBL/MainForm.cs @@ -170,8 +170,8 @@ void MnExportConfigClick(object sender, EventArgs e) if (filename != null) {Core.ExportConfig(filename);} - } + void MnImportConfigClick(object sender, EventArgs e) { string filename = null; diff --git a/LaserGRBL/Properties/AssemblyInfo.cs b/LaserGRBL/Properties/AssemblyInfo.cs index 14dfa2547..4de3b2269 100644 --- a/LaserGRBL/Properties/AssemblyInfo.cs +++ b/LaserGRBL/Properties/AssemblyInfo.cs @@ -31,5 +31,5 @@ // È possibile specificare tutti i valori oppure impostare valori predefiniti per i numeri relativi alla revisione e alla build // utilizzando l'asterisco (*) come descritto di seguito: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion ("2.7.4")] +[assembly: AssemblyVersion ("2.7.5")] [assembly: NeutralResourcesLanguageAttribute("en")] diff --git a/LaserGRBL/Tools/Cronometro.cs b/LaserGRBL/Tools/Cronometro.cs new file mode 100644 index 000000000..cb378d613 --- /dev/null +++ b/LaserGRBL/Tools/Cronometro.cs @@ -0,0 +1,139 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Tools +{ + public class TimingBase + { + + private static long mStartup; + + static TimingBase() + { + mStartup = HiResTimer.TotalNano; + } + + public static TimeSpan TimeFromApplicationStartup() + { + // Un singolo Tick rappresenta cento nanosecondi + return TimeSpan.FromTicks((HiResTimer.TotalNano - mStartup) / 100); + } + + } + + public class OneShootCrono + { + //necessario xè non è sufficiente usare starttime + private bool started = false; + + private TimeSpan starttime = TimeSpan.Zero; + public void Start() + { + starttime = TimingBase.TimeFromApplicationStartup(); + started = true; + } + + public TimeSpan TempoTrascorso + { + get + { + //non inizializzato + if (!started) + { + return TimeSpan.Zero; + } + else + { + return TimingBase.TimeFromApplicationStartup() - starttime; + } + } + } + + public virtual void Reset() + { + starttime = TimeSpan.Zero; + started = false; + } + + public bool Running + { + get { return started; } + } + + } + + public class Cronometro : OneShootCrono + { + + + private System.Collections.Generic.List times = new System.Collections.Generic.List(); + public void SalvaIntermedio() + { + times.Add(TempoTrascorso); + } + + public override void Reset() + { + base.Reset(); + times.Clear(); + } + + public System.Collections.Generic.List Intermedi + { + get { return times; } + } + + } + + public class AutoResetTimer + { + private TimeSpan m_period; + private OneShootCrono crono; + + private long m_periodcount; + public AutoResetTimer(TimeSpan Period, bool start = false) + { + m_period = Period; + crono = new OneShootCrono(); + + if (start) + Start(); + } + + public void Start() + { + crono.Start(); + } + + public bool Running + { + get { return crono.Running; } + } + + public TimeSpan Period + { + get { return m_period; } + } + + public bool Expired + { + get + { + bool rv = false; + long newperiod = crono.TempoTrascorso.Ticks / Period.Ticks; + rv = newperiod > m_periodcount; + m_periodcount = newperiod; + return rv; + } + } + + public long NumPeriod + { + get { return m_periodcount; } + } + + } + +}