[chronojump] runEncoder capture and minimal gui done!



commit d3a0254700e0ea2122a0d8bf7a84f468877b43d4
Author: Xavier de Blas <xaviblas gmail com>
Date:   Fri May 18 09:41:56 2018 +0200

    runEncoder capture and minimal gui done!

 glade/app1.glade             |  149 +++++++++++--
 src/Makefile.am              |    2 +
 src/chronojump.cs            |    5 +-
 src/chronopicRegister.cs     |    4 +-
 src/constants.cs             |    2 +-
 src/forceSensor.cs           |    2 +-
 src/gui/chronojump.cs        |   88 ++++++++
 src/gui/chronopicRegister.cs |    3 +-
 src/gui/forceSensor.cs       |    2 +-
 src/gui/runEncoder.cs        |  492 ++++++++++++++++++++++++++++++++++++++++++
 src/util.cs                  |   38 ++++
 src/utilEncoder.cs           |   13 +-
 12 files changed, 771 insertions(+), 29 deletions(-)
---
diff --git a/glade/app1.glade b/glade/app1.glade
index f2a8541..d0dfec5 100644
--- a/glade/app1.glade
+++ b/glade/app1.glade
@@ -422,6 +422,17 @@
                       </widget>
                     </child>
                     <child>
+                      <widget class="GtkRadioMenuItem" id="radio_menuitem_mode_runs_encoder">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="label">Encoder races</property>
+                        <property name="use_underline">True</property>
+                        <property name="draw_as_radio">True</property>
+                        <property name="group">radio_menuitem_mode_jumps_simple</property>
+                        <signal name="activate" handler="on_radio_menuitem_mode_activate" swapped="no"/>
+                      </widget>
+                    </child>
+                    <child>
                       <widget class="GtkSeparatorMenuItem" id="menuitem5">
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
@@ -1727,6 +1738,9 @@
                                                             <placeholder/>
                                                             </child>
                                                             <child>
+                                                            <placeholder/>
+                                                            </child>
+                                                            <child>
                                                             <widget class="GtkLabel" 
id="label_start_selector_jumps">
                                                             <property name="visible">True</property>
                                                             <property name="can_focus">False</property>
@@ -5595,6 +5609,39 @@ EncoderInertialCapture</property>
                                                             <property name="type">tab</property>
                                                           </packing>
                                                         </child>
+                                                        <child>
+                                                          <widget class="GtkHBox" id="hbox286">
+                                                            <property name="visible">True</property>
+                                                            <property name="can_focus">False</property>
+                                                            <child>
+                                                            <widget class="GtkLabel" id="label368">
+                                                            <property name="visible">True</property>
+                                                            <property name="can_focus">False</property>
+                                                            <property name="label">race encoder 
stuff</property>
+                                                            </widget>
+                                                            <packing>
+                                                            <property name="expand">False</property>
+                                                            <property name="fill">False</property>
+                                                            <property name="position">0</property>
+                                                            </packing>
+                                                            </child>
+                                                          </widget>
+                                                          <packing>
+                                                            <property name="position">8</property>
+                                                          </packing>
+                                                        </child>
+                                                        <child>
+                                                          <widget class="GtkLabel" id="label367">
+                                                            <property name="visible">True</property>
+                                                            <property name="can_focus">False</property>
+                                                            <property name="label">runs encoder</property>
+                                                          </widget>
+                                                          <packing>
+                                                            <property name="position">8</property>
+                                                            <property name="tab_fill">False</property>
+                                                            <property name="type">tab</property>
+                                                          </packing>
+                                                        </child>
                                                       </widget>
                                                       <packing>
                                                         <property name="expand">False</property>
@@ -8308,6 +8355,39 @@ EncoderInertialCapture</property>
                                                             <property name="type">tab</property>
                                                             </packing>
                                                             </child>
+                                                            <child>
+                                                            <widget class="GtkHBox" id="hbox288">
+                                                            <property name="visible">True</property>
+                                                            <property name="can_focus">False</property>
+                                                            <child>
+                                                            <widget class="GtkLabel" id="label370">
+                                                            <property name="visible">True</property>
+                                                            <property name="can_focus">False</property>
+                                                            <property name="label">race encoder 
stuff</property>
+                                                            </widget>
+                                                            <packing>
+                                                            <property name="expand">False</property>
+                                                            <property name="fill">False</property>
+                                                            <property name="position">0</property>
+                                                            </packing>
+                                                            </child>
+                                                            </widget>
+                                                            <packing>
+                                                            <property name="position">8</property>
+                                                            </packing>
+                                                            </child>
+                                                            <child>
+                                                            <widget class="GtkLabel" id="label369">
+                                                            <property name="visible">True</property>
+                                                            <property name="can_focus">False</property>
+                                                            <property name="label" translatable="yes">runs 
encoder</property>
+                                                            </widget>
+                                                            <packing>
+                                                            <property name="position">8</property>
+                                                            <property name="tab_fill">False</property>
+                                                            <property name="type">tab</property>
+                                                            </packing>
+                                                            </child>
                                                             </widget>
                                                             <packing>
                                                             <property name="expand">True</property>
@@ -12774,6 +12854,51 @@ EncoderInertialCapture</property>
                                                             <property name="type">tab</property>
                                                             </packing>
                                                             </child>
+                                                            <child>
+                                                            <widget class="GtkVBox" id="vbox132">
+                                                            <property name="visible">True</property>
+                                                            <property name="can_focus">False</property>
+                                                            <property name="border_width">8</property>
+                                                            <child>
+                                                            <widget class="GtkHBox" id="hbox290">
+                                                            <property name="visible">True</property>
+                                                            <property name="can_focus">False</property>
+                                                            <child>
+                                                            <widget class="GtkLabel" id="label372">
+                                                            <property name="visible">True</property>
+                                                            <property name="can_focus">False</property>
+                                                            <property name="label">race encoder 
stuff</property>
+                                                            </widget>
+                                                            <packing>
+                                                            <property name="expand">False</property>
+                                                            <property name="fill">False</property>
+                                                            <property name="position">0</property>
+                                                            </packing>
+                                                            </child>
+                                                            </widget>
+                                                            <packing>
+                                                            <property name="expand">False</property>
+                                                            <property name="fill">False</property>
+                                                            <property name="position">0</property>
+                                                            </packing>
+                                                            </child>
+                                                            </widget>
+                                                            <packing>
+                                                            <property name="position">8</property>
+                                                            </packing>
+                                                            </child>
+                                                            <child>
+                                                            <widget class="GtkLabel" id="label371">
+                                                            <property name="visible">True</property>
+                                                            <property name="can_focus">False</property>
+                                                            <property name="label" translatable="yes">runs 
encoder</property>
+                                                            </widget>
+                                                            <packing>
+                                                            <property name="position">8</property>
+                                                            <property name="tab_fill">False</property>
+                                                            <property name="type">tab</property>
+                                                            </packing>
+                                                            </child>
                                                             </widget>
                                                             <packing>
                                                             <property name="position">1</property>
@@ -19220,27 +19345,6 @@ Concentric</property>
                                                             <placeholder/>
                                                             </child>
                                                             <child>
-                                                            <placeholder/>
-                                                            </child>
-                                                            <child>
-                                                            <placeholder/>
-                                                            </child>
-                                                            <child>
-                                                            <placeholder/>
-                                                            </child>
-                                                            <child>
-                                                            <placeholder/>
-                                                            </child>
-                                                            <child>
-                                                            <placeholder/>
-                                                            </child>
-                                                            <child>
-                                                            <placeholder/>
-                                                            </child>
-                                                            <child>
-                                                            <placeholder/>
-                                                            </child>
-                                                            <child>
                                                             <widget class="GtkLabel" 
id="label_force_sensor_ai_rfd_a">
                                                             <property name="visible">True</property>
                                                             <property name="can_focus">False</property>
@@ -27620,6 +27724,9 @@ then click this button.</property>
                                                             <child>
                                                             <placeholder/>
                                                             </child>
+                                                            <child>
+                                                            <placeholder/>
+                                                            </child>
                                                             </widget>
                                                             <packing>
                                                             <property name="expand">False</property>
diff --git a/src/Makefile.am b/src/Makefile.am
index bd43bfa..a423bd9 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -30,6 +30,7 @@ SOURCES = \
        gui/jumpType.cs\
        gui/restTime.cs\
        gui/run.cs\
+       gui/runEncoder.cs\
        gui/runType.cs\
        gui/reactionTime.cs\
        gui/pulse.cs\
@@ -268,6 +269,7 @@ RESOURCES = \
        ../images/board-encoder.png,board-encoder.png \
        ../images/board-arduino-rfid.png,board-arduino-rfid.png \
        ../images/board-arduino-force.png,board-arduino-force.png \
+       ../images/board-arduino-run-encoder.png,board-arduino-run-encoder.png \
        ../images/chronojump-jumps-small.png,chronojump-jumps-small.png \
        ../images/chronojump-runs-small.png,chronojump-runs-small.png \
        ../images/chronojump-encoder-small.png,chronojump-encoder-small.png \
diff --git a/src/chronojump.cs b/src/chronojump.cs
index a96ceae..1c972ea 100644
--- a/src/chronojump.cs
+++ b/src/chronojump.cs
@@ -268,10 +268,11 @@ public class ChronoJump
 
                //to store user videos and photos
                Util.CreateMultimediaDirsIfNeeded();
-               //to store encoder data and graphs
+
+               //to store (encoder, force sensor, run encoder) data and graphs
                UtilEncoder.CreateEncoderDirIfNeeded();
-               //to store force sensor data and graphs
                Util.CreateForceSensorDirIfNeeded();
+               Util.CreateRunEncoderDirIfNeeded();
 
 //TODO: when a session is deleted, encoder data has to be deleted, also multimedia videos, I suppose. Show 
message to user warning about it
 //TODO: encoder weight auto written depending on person loaded, and changes if it changes person or weight
diff --git a/src/chronopicRegister.cs b/src/chronopicRegister.cs
index 131ac08..45198a6 100644
--- a/src/chronopicRegister.cs
+++ b/src/chronopicRegister.cs
@@ -34,7 +34,7 @@ public class ChronopicRegisterPort
        public string Port;
        public bool FTDI;
        public string SerialNumber;
-       public enum Types { UNKNOWN, CONTACTS, ENCODER, ARDUINO_RFID, ARDUINO_FORCE }
+       public enum Types { UNKNOWN, CONTACTS, ENCODER, ARDUINO_RFID, ARDUINO_FORCE, ARDUINO_RUN_ENCODER }
        public Types Type;
 
        public bool ConnectedReal;      //if connexion has been done by ChronopicInit.Do
@@ -76,6 +76,8 @@ public class ChronopicRegisterPort
                        return "RFID";
                else if(typeStatic == Types.ARDUINO_FORCE)
                        return Catalog.GetString("Force sensor");
+               else if(typeStatic == Types.ARDUINO_RUN_ENCODER)
+                       return "Run encoder (experimental)";
 
                return Catalog.GetString("Unknown");
        }
diff --git a/src/constants.cs b/src/constants.cs
index 0e383b2..67ec848 100644
--- a/src/constants.cs
+++ b/src/constants.cs
@@ -744,7 +744,7 @@ public class Constants
        public enum Menuitem_modes {
                UNDEFINED,
                JUMPSSIMPLE, JUMPSREACTIVE,
-               RUNSSIMPLE, RUNSINTERVALLIC,
+               RUNSSIMPLE, RUNSINTERVALLIC, RUNSENCODER,
                POWERGRAVITATORY, POWERINERTIAL,
                FORCESENSOR, RT, OTHER } //OTHER can be: Multichronopic, Pulse
 
diff --git a/src/forceSensor.cs b/src/forceSensor.cs
index 45301e6..c177449 100644
--- a/src/forceSensor.cs
+++ b/src/forceSensor.cs
@@ -570,7 +570,7 @@ public class ForceSensorGraph
                scriptOptions +=
                        "\n#testLength\n" +             testLength.ToString() + "\n" +
                        "#title\n" +                    title + "\n" +
-                       "#scriptsPath\n" +              UtilEncoder.GetmifPath() + "\n";
+                       "#scriptsPath\n" +              UtilEncoder.GetScriptsPath() + "\n";
 
                TextWriter writer = File.CreateText(Path.GetTempPath() + "Roptions.txt");
                writer.Write(scriptOptions);
diff --git a/src/gui/chronojump.cs b/src/gui/chronojump.cs
index 05e346c..48dad27 100644
--- a/src/gui/chronojump.cs
+++ b/src/gui/chronojump.cs
@@ -54,6 +54,7 @@ public partial class ChronoJumpWindow
        [Widget] Gtk.RadioMenuItem radio_menuitem_mode_jumps_reactive;
        [Widget] Gtk.RadioMenuItem radio_menuitem_mode_runs_simple;
        [Widget] Gtk.RadioMenuItem radio_menuitem_mode_runs_intervallic;
+       [Widget] Gtk.RadioMenuItem radio_menuitem_mode_runs_encoder;
        [Widget] Gtk.RadioMenuItem radio_menuitem_mode_power_gravitatory;
        [Widget] Gtk.RadioMenuItem radio_menuitem_mode_power_inertial;
        [Widget] Gtk.RadioMenuItem radio_menuitem_mode_force_sensor;
@@ -501,6 +502,8 @@ public partial class ChronoJumpWindow
                        myType = currentRunType;
                else if(current_menuitem_mode == Constants.Menuitem_modes.RUNSINTERVALLIC)
                        myType = currentRunIntervalType;
+               //else if(current_menuitem_mode == Constants.Menuitem_modes.RUNSENCODER)
+               //      myType = currentRunIntervalType;
                //else if(current_menuitem_mode == Constants.Menuitem_modes.FORCESENSOR
                //      myType = currentForceType;
                else if(current_menuitem_mode == Constants.Menuitem_modes.RT)
@@ -802,6 +805,8 @@ public partial class ChronoJumpWindow
                        "   " + ((Label) radio_menuitem_mode_runs_simple.Child).Text;
                ((Label) radio_menuitem_mode_runs_intervallic.Child).Text =
                        "   " + ((Label) radio_menuitem_mode_runs_intervallic.Child).Text;
+               ((Label) radio_menuitem_mode_runs_encoder.Child).Text =
+                       "   " + ((Label) radio_menuitem_mode_runs_encoder.Child).Text;
 
                ((Label) radio_menuitem_mode_power_gravitatory.Child).Text =
                        "   " + ((Label) radio_menuitem_mode_power_gravitatory.Child).Text;
@@ -1090,6 +1095,9 @@ public partial class ChronoJumpWindow
                                label_sprint_person_name.Text = string.Format(Catalog.GetString("Sprints of 
{0}"), currentPerson.Name);
                        createTreeView_runs_interval_sprint (treeview_runs_interval_sprint);
                }
+               //else if(current_menuitem_mode == Constants.Menuitem_modes.RUNSENCODER)
+               //{
+               //}
                else if(current_menuitem_mode == Constants.Menuitem_modes.RT)
                        updateGraphReactionTimes();
 
@@ -2222,6 +2230,15 @@ public partial class ChronoJumpWindow
                if(portFSOpened)
                        portFS.Close();
 
+               //cancel runEncoder capture process
+               if(capturingRunEncoder == runEncoderStatus.STARTING || capturingRunEncoder == 
runEncoderStatus.CAPTURING)
+               {
+                       LogB.Information("cancelling runEncoder capture");
+                       runEncoderProcessCancel = true;
+               }
+               if(portREOpened)
+                       portRE.Close();
+
                LogB.Information("Bye3!");
                
                Log.End();
@@ -2259,6 +2276,9 @@ public partial class ChronoJumpWindow
                                modePrint = Catalog.GetString("Races simple");
                        else if(mode == Constants.Menuitem_modes.RUNSINTERVALLIC)
                                modePrint = Catalog.GetString("Races intervallic");
+                       else if(mode == Constants.Menuitem_modes.RUNSENCODER)
+                               //modePrint = Catalog.GetString("Races with encoder");
+                               modePrint = "Races with encoder";
                        else if(mode == Constants.Menuitem_modes.POWERGRAVITATORY)
                                modePrint = Catalog.GetString("Encoder (gravitatory)");
                        else if(mode == Constants.Menuitem_modes.POWERINERTIAL)
@@ -3145,6 +3165,7 @@ public partial class ChronoJumpWindow
                        notebook_sup.CurrentPage = 0;
                        //notebook_capture_analyze.ShowTabs = true;
                        hbox_contacts_sup_capture_analyze_two_buttons.Visible = true;
+                       button_threshold.Visible = true;
                        if(m == Constants.Menuitem_modes.JUMPSSIMPLE) 
                        {
                                notebooks_change(m);
@@ -3173,6 +3194,7 @@ public partial class ChronoJumpWindow
                        notebook_sup.CurrentPage = 0;
                        //notebook_capture_analyze.ShowTabs = true;
                        hbox_contacts_sup_capture_analyze_two_buttons.Visible = true;
+                       button_threshold.Visible = true;
                        button_inspect_last_test.Visible = true;
 
                        if(m == Constants.Menuitem_modes.RUNSSIMPLE) 
@@ -3311,12 +3333,32 @@ public partial class ChronoJumpWindow
 
                        //notebook_capture_analyze.ShowTabs = false; //only capture tab is shown (only valid 
for "OTHER" tests)
                        hbox_contacts_sup_capture_analyze_two_buttons.Visible = true;
+                       button_threshold.Visible = false;
+                       //notebook_capture_analyze.GetNthPage(2).Hide(); //hide jumpsProfile on other tests
+                       hbox_results_legend.Visible = false;
+
+                       //on force sensor only show table
+                       notebook_capture_graph_table.CurrentPage = 1; //"Show table"
+                       notebook_capture_graph_table.ShowTabs = false;
+               }
+               else if(m == Constants.Menuitem_modes.RUNSENCODER)
+               {
+                       notebook_sup.CurrentPage = 0;
+                       radio_menuitem_mode_runs_encoder.Active = true;
+                       notebooks_change(m);
+//                     on_extra_window_reaction_times_test_changed(new object(), new EventArgs());
+
+                       //notebook_capture_analyze.ShowTabs = false; //only capture tab is shown (only valid 
for "OTHER" tests)
+                       hbox_contacts_sup_capture_analyze_two_buttons.Visible = false;
+                       button_threshold.Visible = false;
                        //notebook_capture_analyze.GetNthPage(2).Hide(); //hide jumpsProfile on other tests
                        hbox_results_legend.Visible = false;
 
+                       /*
                        //on force sensor only show table
                        notebook_capture_graph_table.CurrentPage = 1; //"Show table"
                        notebook_capture_graph_table.ShowTabs = false;
+                       */
                }
                else if(m == Constants.Menuitem_modes.RT)
                {
@@ -3328,6 +3370,7 @@ public partial class ChronoJumpWindow
                        notebook_capture_analyze.CurrentPage = 0;
                        //notebook_capture_analyze.ShowTabs = false; //only capture tab is shown (only valid 
for "OTHER" tests)
                        hbox_contacts_sup_capture_analyze_two_buttons.Visible = false;
+                       button_threshold.Visible = true;
                        //notebook_capture_analyze.GetNthPage(2).Hide(); //hide jumpsProfile on other tests
                }
                else {  //m == Constants.Menuitem_modes.OTHER (contacts / other)
@@ -3339,6 +3382,7 @@ public partial class ChronoJumpWindow
                        notebook_capture_analyze.CurrentPage = 0;
                        //notebook_capture_analyze.ShowTabs = false; //only capture tab is shown (only valid 
for "OTHER" tests)
                        hbox_contacts_sup_capture_analyze_two_buttons.Visible = false;
+                       button_threshold.Visible = true;
                        //notebook_capture_analyze.GetNthPage(2).Hide(); //hide jumpsProfile on other tests
                }
 
@@ -3521,6 +3565,8 @@ public partial class ChronoJumpWindow
                        return Constants.Menuitem_modes.RUNSSIMPLE;
                else if(radio_menuitem_mode_runs_intervallic.Active)
                        return Constants.Menuitem_modes.RUNSINTERVALLIC;
+               else if(radio_menuitem_mode_runs_encoder.Active)
+                       return Constants.Menuitem_modes.RUNSENCODER;
                else if(radio_menuitem_mode_power_gravitatory.Active)
                        return Constants.Menuitem_modes.POWERGRAVITATORY;
                else if(radio_menuitem_mode_power_inertial.Active)
@@ -3584,6 +3630,13 @@ public partial class ChronoJumpWindow
                else
                        radio_menuitem_mode_runs_intervallic.Active = true;
        }
+       private void on_button_selector_start_runs_encoder_clicked(object o, EventArgs args)
+       {
+               if(radio_menuitem_mode_runs_encoder.Active)
+                       select_menuitem_mode_toggled(Constants.Menuitem_modes.RUNSENCODER);
+               else
+                       radio_menuitem_mode_runs_encoder.Active = true;
+       }
        
        private void on_button_selector_start_encoder_clicked(object o, EventArgs args) 
        {
@@ -3812,6 +3865,12 @@ public partial class ChronoJumpWindow
                        forceProcessCancel = true;
                        return;
                }
+               if(capturingRunEncoder == runEncoderStatus.STARTING || capturingRunEncoder == 
runEncoderStatus.CAPTURING)
+               {
+                       LogB.Information("cancel clicked on runEncoder");
+                       runEncoderProcessCancel = true;
+                       return;
+               }
 
                LogB.Information("cancel clicked one");
 
@@ -3848,6 +3907,13 @@ public partial class ChronoJumpWindow
                        forceProcessFinish = true;
                        return;
                }
+               if(capturingRunEncoder == runEncoderStatus.STARTING || capturingRunEncoder == 
runEncoderStatus.CAPTURING)
+               {
+                       LogB.Information("finish clicked on runEncoder");
+                       runEncoderProcessFinish = true;
+                       return;
+               }
+
 
                LogB.Information("finish clicked one");
 
@@ -3910,6 +3976,16 @@ public partial class ChronoJumpWindow
                        on_buttons_force_sensor_clicked(button_execute_test, new EventArgs ());
                        return;
                }
+               if(current_menuitem_mode == Constants.Menuitem_modes.RUNSENCODER)
+               {
+                       LogB.Debug("radio_mode_runs_encoder");
+                       /*
+                        * runs encoder is not FTDI
+                        */
+
+                       on_runs_encoder_capture_clicked ();
+                       return;
+               }
 
                // stop capturing inertial on the background if we start capturing a contacts test
                if(encoderThreadBG != null && encoderThreadBG.IsAlive)
@@ -4053,6 +4129,11 @@ public partial class ChronoJumpWindow
                                pixbuf = new Pixbuf (null, Util.GetImagePath(true) + 
Constants.FileNameForceSensor);
                                button_image_test_zoom.Hide();
                        break;
+                       case "RUNSENCODER":
+                               //pixbuf = new Pixbuf (null, Util.GetImagePath(true) + 
Constants.FileNameRunEncoder);
+                               pixbuf = new Pixbuf (null, Util.GetImagePath(true) + "no_image.png");
+                               button_image_test_zoom.Hide();
+                       break;
                        case "":
                                pixbuf = new Pixbuf (null, Util.GetImagePath(true) + "no_image.png");
                                button_image_test_zoom.Hide();
@@ -6660,6 +6741,13 @@ LogB.Debug("X");
                        notebook_results.CurrentPage = 3;
                        changeTestImage(EventType.Types.RUN.ToString(), 
                                        currentRunIntervalType.Name, currentRunIntervalType.ImageFileName);
+               } else if(mode == Constants.Menuitem_modes.RUNSENCODER)
+               {
+                       notebook_execute.CurrentPage = 8;
+                       notebook_options_top.CurrentPage = 8;
+                       notebook_results.CurrentPage = 8;
+                       changeTestImage("", "", "RUNSENCODER");
+                       event_execute_button_finish.Sensitive = false;
                } else if(mode == Constants.Menuitem_modes.FORCESENSOR)
                {
                        notebook_execute.CurrentPage = 4;
diff --git a/src/gui/chronopicRegister.cs b/src/gui/chronopicRegister.cs
index d66385d..bce77c6 100644
--- a/src/gui/chronopicRegister.cs
+++ b/src/gui/chronopicRegister.cs
@@ -27,7 +27,7 @@ using Mono.Unix;
 
 public class TypePix
 {
-       public ChronopicRegisterPort.Types Type; //public enum Types { UNKNOWN, CONTACTS, ENCODER, 
ARDUINO_FORCE, ARDUINO_RFID }
+       public ChronopicRegisterPort.Types Type; //public enum Types { UNKNOWN, CONTACTS, ENCODER, 
ARDUINO_FORCE, ARDUINO_RFID, ARDUINO_RUN_ENCODER_ }
        public Pixbuf Pix;
 
        public TypePix(ChronopicRegisterPort.Types type, Pixbuf pix)
@@ -51,6 +51,7 @@ public static class TypePixList
                l.Add(new TypePix(ChronopicRegisterPort.Types.ENCODER, new Pixbuf (null, 
Util.GetImagePath(false) + "board-encoder.png")));
                l.Add(new TypePix(ChronopicRegisterPort.Types.ARDUINO_FORCE, new Pixbuf (null, 
Util.GetImagePath(false) + "board-arduino-force.png")));
                l.Add(new TypePix(ChronopicRegisterPort.Types.ARDUINO_RFID, new Pixbuf (null, 
Util.GetImagePath(false) + "board-arduino-rfid.png")));
+               l.Add(new TypePix(ChronopicRegisterPort.Types.ARDUINO_RUN_ENCODER, new Pixbuf (null, 
Util.GetImagePath(false) + "board-arduino-run-encoder.png")));
        }
 
        public static Pixbuf GetPix(ChronopicRegisterPort.Types type)
diff --git a/src/gui/forceSensor.cs b/src/gui/forceSensor.cs
index 7d36db9..b33e1c8 100644
--- a/src/gui/forceSensor.cs
+++ b/src/gui/forceSensor.cs
@@ -1349,7 +1349,7 @@ LogB.Information(" fc R ");
                button_image_test_zoom.Visible = ! modeForceSensor;
                notebook_options_top.Visible = ! modeForceSensor;
 
-               button_threshold.Visible = ! modeForceSensor;
+               //button_threshold.Visible = ! modeForceSensor;
 
                menuitem_force_sensor_open_folder.Visible = modeForceSensor;
                menuitem_force_sensor_check_version.Visible = modeForceSensor;
diff --git a/src/gui/runEncoder.cs b/src/gui/runEncoder.cs
new file mode 100644
index 0000000..ca658fc
--- /dev/null
+++ b/src/gui/runEncoder.cs
@@ -0,0 +1,492 @@
+/*
+ * This file is part of ChronoJump
+ *
+ * ChronoJump is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or   
+ *    (at your option) any later version.
+ *    
+ * ChronoJump is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+ *    GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Copyright (C) 2018   Xavier de Blas <xaviblas gmail com>
+ */
+
+using System;
+using System.IO;
+using System.IO.Ports;
+using System.Threading;
+using Gtk;
+using Gdk;
+using Glade;
+using System.Text; //StringBuilder
+using System.Collections.Generic; //List<T>
+using Mono.Unix;
+
+
+public partial class ChronoJumpWindow 
+{
+       Thread runEncoderCaptureThread;
+       static bool runEncoderProcessFinish;
+       static bool runEncoderProcessCancel;
+       static bool runEncoderProcessError;
+       
+       static string lastRunEncoderFile = "";
+       static string lastRunEncoderFullPath = "";
+
+       //int usbDisconnectedCount;
+       //int usbDisconnectedLastTime;
+       /*
+        * runEncoderStatus:
+        * STOP is when is not used
+        * STARTING is while is waiting run encoder sensor to start capturing
+        * CAPTURING is when data is arriving
+        * COPIED_TO_TMP means data is on tmp and graph can be called
+        */
+       enum runEncoderStatus { STOP, STARTING, CAPTURING, COPIED_TO_TMP }
+       static runEncoderStatus capturingRunEncoder = runEncoderStatus.STOP;
+       /*
+       static bool redoingPoints; //don't draw while redoing points (adjusting screen)
+
+       static bool forceCaptureStartMark;      //Just needed to display "Capturing message"
+       static ForceSensorValues forceSensorValues;
+
+       */
+       string runEncoderPortName;
+       SerialPort portRE; //Attention!! Don't reopen port because arduino makes reset
+       bool portREOpened;
+
+       string runEncoderNotConnectedString =
+               //Catalog.GetString("Run encoder sensor is not detected!") + " " +
+               "Run encoder sensor is not detected!" + " " +
+               Catalog.GetString("Plug cable and click on 'device' button.");
+
+
+       //this can use GTK (forceSensor not because it's managed by non-gtk thread)
+       private bool runEncoderConnect()
+       {
+               LogB.Information(" RE connect 0 ");
+               if(chronopicRegister.ConnectedOfType(ChronopicRegisterPort.Types.ARDUINO_RUN_ENCODER) == null)
+               {
+                       event_execute_label_message.Text = runEncoderNotConnectedString;
+                       return false;
+               }
+
+               LogB.Information(" RE connect 1 ");
+               runEncoderPortName = 
chronopicRegister.ConnectedOfType(ChronopicRegisterPort.Types.ARDUINO_RUN_ENCODER).Port;
+               LogB.Information(" RE connect 2 ");
+               if(runEncoderPortName == null || runEncoderPortName == "")
+               {
+                       event_execute_label_message.Text = "Please, select port!";
+                       return false;
+               }
+               LogB.Information(" RE connect 3 ");
+               event_execute_label_message.Text = "Connecting ...";
+
+               portRE = new SerialPort(runEncoderPortName, 115200); //runEncoder
+               LogB.Information(" RE connect 4: opening port...");
+
+               try {
+                       portRE.Open();
+               }
+               catch (System.IO.IOException)
+               {
+                       event_execute_label_message.Text = runEncoderNotConnectedString;
+                       return false;
+               }
+
+               LogB.Information(" RE connect 5: let arduino start");
+
+               Thread.Sleep(3000); //sleep to let arduino start reading serial event
+
+               LogB.Information(" RE connect 6: get version");
+
+               /*
+               string version = runEncoderCheckVersionDo();
+               LogB.Information("Version found: [" + version + "]");
+
+               if(version == "0.1")
+               {
+                       LogB.Information(" RE connect 6b, version 0.1: adjusting parameters...");
+               }
+               */
+
+               portREOpened = true;
+               event_execute_label_message.Text = "Connected!";
+               LogB.Information(" RE connect 7: connected and adjusted!");
+               return true;
+       }
+       private void runEncoderDisconnect()
+       {
+               portRE.Close();
+               portREOpened = false;
+               event_execute_label_message.Text = "Disconnected!";
+       }
+
+       //Attention: no GTK here!!
+       private bool runEncoderSendCommand(string command, string displayMessage, string errorMessage)
+       {
+               //forceSensorOtherMessage = displayMessage;
+
+               try {
+                       LogB.Information("Run Encoder command |" + command + "|");
+                       portRE.WriteLine(command);
+               }
+               catch (Exception ex)
+               {
+                       if(ex is System.IO.IOException || ex is System.TimeoutException)
+                       {
+                               LogB.Information(errorMessage);
+                               portREOpened = false;
+                               return false;
+                       }
+                       //throw;
+               }
+
+               return true;
+       }
+
+       private void on_runs_encoder_capture_clicked ()
+       {
+               runEncoderButtonsSensitive(false);
+               bool connected = runEncoderCapturePre();
+               if(! connected)
+                       runEncoderButtonsSensitive(true);
+       }
+
+       //TODO: do all this with an "other" thread like in force sensor to allow connecting messages to be 
displayed
+       private bool runEncoderCapturePre()
+       {
+               if(! portREOpened)
+                       if(! runEncoderConnect())
+                               return false;
+
+               event_execute_label_message.Text = "Please, wait ...";
+               capturingRunEncoder = runEncoderStatus.STARTING;
+
+               button_execute_test.Sensitive = false;
+               event_execute_button_finish.Sensitive = true;
+               event_execute_button_cancel.Sensitive = true;
+               
+               //forceCaptureStartMark = false;
+
+               runEncoderProcessFinish = false;
+               runEncoderProcessCancel = false;
+               runEncoderProcessError = false;
+
+               //To know if USB has been disconnected
+               usbDisconnectedCount = 0;
+               usbDisconnectedLastTime = 0;
+
+               /*
+               //initialize
+               forceSensorValues = new ForceSensorValues();
+               */
+
+               event_execute_ButtonFinish.Clicked -= new EventHandler(on_finish_clicked);
+               event_execute_ButtonFinish.Clicked += new EventHandler(on_finish_clicked);
+               
+               event_execute_ButtonCancel.Clicked -= new EventHandler(on_cancel_clicked);
+               event_execute_ButtonCancel.Clicked += new EventHandler(on_cancel_clicked);
+
+               event_execute_label_message.Text = "Capturing ...";
+
+               runEncoderCaptureThread = new Thread(new ThreadStart(runEncoderCaptureDo));
+               GLib.Idle.Add (new GLib.IdleHandler (pulseGTKRunEncoderCapture));
+
+               LogB.ThreadStart();
+               runEncoderCaptureThread.Start();
+               return true;
+       }
+
+       //non GTK on this method
+       private void runEncoderCaptureDo()
+       {
+               LogB.Information("runEncoderCaptureDo 0");
+               lastChangedTime = 0;
+
+               if(! runEncoderSendCommand("start_capture:", "", "Catched run encoder capturing"))
+               {
+                       runEncoderProcessError = true;
+                       return;
+               }
+
+               string str = "";
+               LogB.Information("runEncoderCaptureDo 1");
+               do {
+                       Thread.Sleep(100); //sleep to let arduino start reading
+                       try {
+                               str = portRE.ReadLine();
+                       } catch {
+                               runEncoderProcessError = true;
+                               return;
+                       }
+
+                       LogB.Information("init string: " + str);
+               }
+               while(! str.Contains("Starting capture"));
+
+               //forceCaptureStartMark = true;
+               capturingRunEncoder = runEncoderStatus.CAPTURING;
+
+               Util.CreateRunEncoderSessionDirIfNeeded (currentSession.UniqueID);
+
+               string nameDate = currentPerson.Name + "_" + UtilDate.ToFile(DateTime.Now);
+
+               //fileName to save the csv
+               string fileName = Util.GetRunEncoderSessionDir(currentSession.UniqueID) + 
Path.DirectorySeparatorChar + nameDate + ".csv";
+
+               //lastRunEncoderFile to save the images
+               lastRunEncoderFile = nameDate;
+
+
+               TextWriter writer = File.CreateText(fileName);
+               writer.WriteLine("Pulses;Time(useconds)");
+               str = "";
+               int firstTime = 0;
+
+               while(! runEncoderProcessFinish && ! runEncoderProcessCancel && ! runEncoderProcessError)
+               {
+                       //LogB.Information(string.Format("finish conditions: {0}-{1}-{2}",
+                       //                      runEncoderProcessFinish, runEncoderProcessCancel, 
runEncoderProcessError));
+
+                       /*
+                        * The difference between forceSensor and runEncoder is:
+                        * runEncoder is not always returning data
+                        * if user press "finish" button, and they don't move the encoder,
+                        * this will never end:
+                        * //str = portRE.ReadLine();
+                        * so use the following method that allows to return a "" when there no data
+                        * and then the while above will end with the runEncoderProcessFinish condition
+                        */
+                       str = readFromRunEncoderIfDataArrived();
+                       //LogB.Information("str: " + str); //TODO: remove this log
+                       if(str == "")
+                               continue;
+
+                       //check if there is one and only one ';'
+                       if( ! (str.Contains(";") && str.IndexOf(";") == str.LastIndexOf(";")) )
+                               continue;
+
+                       string [] strFull = str.Split(new char[] {';'});
+                       //LogB.Information("str: " + str);
+
+                       LogB.Information("pulses: " + strFull[0]);
+                       if(! Util.IsNumber(strFull[0], false))
+                               continue;
+
+                       LogB.Information("time microseconds: " + strFull[1]);
+                       if(! Util.IsNumber(strFull[1], false))
+                               continue;
+
+                       /*
+                       int time = Convert.ToInt32(strFull[0]);
+
+                       //measurement does not start at 0 time. When we start receiving data, mark this as 
firstTime
+                       if(firstTime == 0)
+                               firstTime = time;
+
+                       //use this to have time starting at 0
+                       time -= firstTime;
+
+                       double force = Convert.ToDouble(Util.ChangeDecimalSeparator(strFull[1]));
+                       */
+                       int pulse = Convert.ToInt32(strFull[0]);
+                       int time = Convert.ToInt32(strFull[1]);
+                       writer.WriteLine(pulse.ToString() + ";" + time.ToString());
+               }
+               LogB.Information(string.Format("FINISHED WITH conditions: {0}-{1}-{2}",
+                                               runEncoderProcessFinish, runEncoderProcessCancel, 
runEncoderProcessError));
+               LogB.Information("Calling end_capture");
+               if(! runEncoderSendCommand("end_capture:", "Ending capture ...", "Catched ending capture"))
+               {
+                       runEncoderProcessError = true;
+                       capturingRunEncoder = runEncoderStatus.STOP;
+                       Util.FileDelete(fileName);
+                       return;
+               }
+
+               LogB.Information("Waiting end_capture");
+               do {
+                       Thread.Sleep(10);
+                       try {
+                               str = portRE.ReadLine();
+                       } catch {
+                               LogB.Information("Catched waiting end_capture feedback");
+                       }
+                       LogB.Information("waiting \"Capture ended\" string: " + str);
+               }
+               while(! str.Contains("Capture ended"));
+               LogB.Information("Success: received end_capture");
+
+               writer.Flush();
+               writer.Close();
+               ((IDisposable)writer).Dispose();
+               capturingRunEncoder = runEncoderStatus.STOP;
+
+               //port.Close();
+
+               if(runEncoderProcessCancel || runEncoderProcessError)
+                       Util.FileDelete(fileName);
+               else {
+                       //call graph
+                       File.Copy(fileName, UtilEncoder.GetRunEncoderCSVFileName(), true); //can be 
overwritten
+                       lastRunEncoderFullPath = fileName;
+                       capturingRunEncoder = runEncoderStatus.COPIED_TO_TMP;
+               }
+       }
+                       
+       private string readFromRunEncoderIfDataArrived()
+       {
+               string str = "";
+               if (portRE.BytesToRead > 0)
+                       str = portRE.ReadLine();
+                       //LogB.Information("PRE_get_calibrationfactor bytes: " + portFS.ReadExisting());
+
+               return str;
+       }
+
+       private bool pulseGTKRunEncoderCapture ()
+       {
+LogB.Information(" fc A ");
+               if(runEncoderCaptureThread == null)
+               {
+                       Thread.Sleep (25);
+                       return true;
+               }
+
+LogB.Information(" fc B ");
+               //LogB.Information(capturingRunEncoder.ToString())
+               if(! runEncoderCaptureThread.IsAlive || runEncoderProcessFinish || runEncoderProcessCancel || 
runEncoderProcessError)
+               {
+LogB.Information(" fc C ");
+                       if(runEncoderProcessFinish)
+                       {
+LogB.Information(" fc C finish");
+/*
+                               if(capturingRunEncoder != runEncoderStatus.COPIED_TO_TMP)
+                               {
+                                       Thread.Sleep (25); //Wait file is copied
+                                       return true;
+                               }
+                               else
+                               {
+*/
+                                       event_execute_label_message.Text = "Saved.";
+                                       Thread.Sleep (250); //Wait a bit to ensure is copied
+
+                                       /*
+                                       fscPoints.InitRealWidthHeight();
+                                       forceSensorDoSignalGraphPlot();
+                                       forceSensorDoRFDGraph();
+
+                                       //if drawingarea has still not shown, don't paint graph because GC 
screen is not defined
+                                       if(force_sensor_ai_drawingareaShown)
+                                               forceSensorDoGraphAI();
+                                       */
+//                             }
+LogB.Information(" fc C finish 2");
+                       } else if(runEncoderProcessCancel || runEncoderProcessError)
+                       {
+LogB.Information(" fc C cancel ");
+                               if(runEncoderProcessCancel)
+                                       event_execute_label_message.Text = "Cancelled.";
+                               else
+                                       event_execute_label_message.Text = runEncoderNotConnectedString;
+LogB.Information(" fc C cancel 2");
+                       }
+                       else
+                               event_execute_label_message.Text = "";
+
+                       LogB.ThreadEnding();
+
+                       /*
+                        * ensure runEncoderCaptureThread is ended:
+                        * called: portRE.WriteLine("end_capture:");
+                        * and received feedback from device
+                        */
+                       while(runEncoderCaptureThread.IsAlive)
+                               Thread.Sleep (250);
+LogB.Information(" fc D ");
+
+                       LogB.ThreadEnded(); 
+
+                       runEncoderButtonsSensitive(true);
+                       /*
+                       button_force_sensor_image_save_signal.Sensitive = true;
+                       button_force_sensor_analyze_recalculate.Sensitive = true;
+                       */
+
+                       //finish, cancel: sensitive = false
+                       hideButtons();
+
+                       restTime.AddOrModify(currentPerson.UniqueID, currentPerson.Name, true);
+                       updateRestTimes();
+
+                       return false;
+               }
+
+LogB.Information(" fc E ");
+/*
+               if(forceCaptureStartMark)
+               {
+                       event_execute_label_message.Text = "Capturing ...";
+                       forceCaptureStartMark = false;
+               }
+               */
+LogB.Information(" fc F ");
+
+               if(capturingRunEncoder == runEncoderStatus.CAPTURING)
+               {
+LogB.Information(" fc G ");
+
+
+LogB.Information(" fc H2 ");
+/*
+                       if(usbDisconnectedLastTime == forceSensorValues.TimeLast)
+                       {
+                               usbDisconnectedCount ++;
+                               if(usbDisconnectedCount >= 20)
+                               {
+                                       event_execute_label_message.Text = "Disconnected!";
+                                       runEncoderProcessError = true;
+                                       return true;
+                               }
+                       }
+                       else
+                       {
+                               usbDisconnectedLastTime = forceSensorValues.TimeLast;
+                               usbDisconnectedCount = 0;
+                       }
+                       */
+
+LogB.Information(" fc I ");
+
+LogB.Information(" fc Q ");
+               }
+LogB.Information(" fc R ");
+
+               Thread.Sleep (25);
+               //LogB.Information(" RunEncoder:"+ runEncoderCaptureThread.ThreadState.ToString());
+               return true;
+       }
+
+       void runEncoderButtonsSensitive(bool sensitive)
+       {
+               button_execute_test.Sensitive = sensitive;
+
+               //other gui buttons
+               main_menu.Sensitive = sensitive;
+               hbox_contacts_sup_capture_analyze_two_buttons.Sensitive = sensitive;
+               frame_persons.Sensitive = sensitive;
+               hbox_top_person.Sensitive = sensitive;
+               hbox_chronopics_and_more.Sensitive = sensitive;
+       }
+
+}
diff --git a/src/util.cs b/src/util.cs
index c37c7d2..42cccb7 100644
--- a/src/util.cs
+++ b/src/util.cs
@@ -975,6 +975,44 @@ public class Util
         * <--------------- end of force sensor suff
         */
 
+       /*
+        * run encoder suff ------------------>
+        */
+
+       //to store run encoder data and graphs
+       public static string GetRunEncoderDir()
+       {
+               return Path.Combine(
+                               Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
+                               "Chronojump" + Path.DirectorySeparatorChar + "runEncoder");
+       }
+       public static void CreateRunEncoderDirIfNeeded ()
+       {
+               string dir = GetRunEncoderDir();
+               if( ! Directory.Exists(dir)) {
+                       Directory.CreateDirectory (dir);
+                       LogB.Information ("created dir:", dir);
+               }
+       }
+
+       //runEncoder organized by sessions.
+       public static string GetRunEncoderSessionDir (int sessionID)
+       {
+               return GetRunEncoderDir() + Path.DirectorySeparatorChar + sessionID.ToString();
+       }
+       public static void CreateRunEncoderSessionDirIfNeeded (int sessionID)
+       {
+               string dir = GetRunEncoderSessionDir(sessionID);
+               if( ! Directory.Exists(dir)) {
+                       Directory.CreateDirectory (dir);
+                       LogB.Information ("created dir:", dir);
+               }
+       }
+
+       /*
+        * <--------------- end of force sensor suff
+        */
+
 
        //videos ar organized by sessions. Photos no.   
        public static string GetVideoSessionDir (int sessionID) {
diff --git a/src/utilEncoder.cs b/src/utilEncoder.cs
index 4cc9455..61aaa90 100644
--- a/src/utilEncoder.cs
+++ b/src/utilEncoder.cs
@@ -247,9 +247,20 @@ public class UtilEncoder
                return System.IO.Path.Combine(Path.GetTempPath(), "sprintGraph.png");
        }
 
-       public static string GetmifPath() {
+       public static string GetScriptsPath() {
                return System.IO.Path.Combine(Util.GetDataDir(), "r-scripts");
        }
+
+       public static string GetRunEncoderScript() {
+               return System.IO.Path.Combine(GetSprintPath(), "sprintEncoder.R");
+       }
+       public static string GetRunEncoderCSVFileName() {
+               return Path.Combine(Path.GetTempPath(), "cj_run_encoder_data.csv");
+       }
+       public static string GetRunEncoderTempFileName() {
+               return Path.Combine(Path.GetTempPath(), "cj_run_encoder_graph.png");
+       }
+
        public static string GetmifScript() {
                return System.IO.Path.Combine(GetSprintPath(), "maximumIsometricForce.R");
        }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]