From 6399a803763f0f42fb19ec5088ab6b779d9c4b7a Mon Sep 17 00:00:00 2001 From: Lars Gardien Date: Mon, 28 Dec 2015 17:01:51 +0100 Subject: [PATCH 1/3] Implemented a sligthly more dynamic version of the queuethread, also made it singleton to avoid conflicts. This is usefull when the Sensor event will be implemented. --- MonoBrickFirmware/Tools/QueueThread.cs | 124 ++++++++++++-------- MonoBrickFirmware/UserInput/ButtonEvents.cs | 2 +- 2 files changed, 76 insertions(+), 50 deletions(-) diff --git a/MonoBrickFirmware/Tools/QueueThread.cs b/MonoBrickFirmware/Tools/QueueThread.cs index 90f544a..e35e04a 100644 --- a/MonoBrickFirmware/Tools/QueueThread.cs +++ b/MonoBrickFirmware/Tools/QueueThread.cs @@ -1,57 +1,83 @@ using System; using System.Collections.Generic; using System.Threading; +using MonoBrickFirmware.Display; namespace MonoBrickFirmware.Tools { - public class QueueThread : IDisposable - { - public QueueThread () - { - Thread t = new Thread(ThreadFunc); - t.IsBackground = true; - t.Start(); - } - private Queue queue = new Queue(); - private EventWaitHandle stop = new EventWaitHandle(false, EventResetMode.ManualReset); - private void ThreadFunc() - { - while (!stop.WaitOne(0)) - { - Action action = null; - lock (queue) - { - if (queue.Count > 0) - { - action = queue.Dequeue(); - } - else - { - Monitor.Wait(queue); - } - } - if (action != null) - action(); - } - } - - public void Enqueue(Action a) - { - lock (queue) - { - queue.Enqueue(a); - Monitor.Pulse(queue); - } - } - - public void Dispose() - { - lock (queue) - { - stop.Set(); - Monitor.Pulse(queue); - } - } - } + public class QueueThread : IDisposable + { + private QueueThread() + { + Thread t = new Thread(ThreadFunc); + t.IsBackground = true; + t.Start(); + } + + public static QueueThread Instance + { + get { return Nested.instance; } + } + + private class Nested + { + static Nested() { } + internal static readonly QueueThread instance = new QueueThread(); + } + + private Queue queue = new Queue(); + private EventWaitHandle stop = new EventWaitHandle(false, EventResetMode.ManualReset); + private void ThreadFunc() + { + while (!stop.WaitOne(0)) + { + EventNode nodeToRaise = null; + lock (queue) + { + if (queue.Count > 0) + { + nodeToRaise = queue.Dequeue(); + } + else + { + Monitor.Wait(queue); + } + } + if ((nodeToRaise != null) && (nodeToRaise.eventToRaise != null)) + { + Delegate eventToRaise = nodeToRaise.eventToRaise; + object[] parameters = nodeToRaise.parameters; + + try + { + eventToRaise.DynamicInvoke(parameters); + } + catch (Exception ex) + { + LcdConsole.WriteLine(ex.ToString()); + } + } + } + } + + public void Enqueue(Delegate eventToEnqueue, params Object[] paramaters) + { + lock (queue) + { + EventNode node = new EventNode(eventToEnqueue, paramaters); + queue.Enqueue(node); + Monitor.Pulse(queue); + } + } + + public void Dispose() + { + lock (queue) + { + stop.Set(); + Monitor.Pulse(queue); + } + } + } } diff --git a/MonoBrickFirmware/UserInput/ButtonEvents.cs b/MonoBrickFirmware/UserInput/ButtonEvents.cs index ebed80a..7936183 100644 --- a/MonoBrickFirmware/UserInput/ButtonEvents.cs +++ b/MonoBrickFirmware/UserInput/ButtonEvents.cs @@ -9,7 +9,7 @@ public class ButtonEvents : IDisposable { EventWaitHandle stopPolling = new ManualResetEvent (false); private int pollTime = 50; - QueueThread queue = new QueueThread (); + QueueThread queue = QueueThread.Instance; Thread pollThread = null; public ButtonEvents (int pollInterval = 50) From 2f1b7d4d2f6a403789f47404df8ba04b62528324 Mon Sep 17 00:00:00 2001 From: Lars Gardien Date: Mon, 28 Dec 2015 17:10:32 +0100 Subject: [PATCH 2/3] Added the EventNode, forgot it the previous commit --- MonoBrickFirmware/MonoBrickFirmware.csproj | 9 ++------ MonoBrickFirmware/Tools/EventNode.cs | 26 ++++++++++++++++++++++ 2 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 MonoBrickFirmware/Tools/EventNode.cs diff --git a/MonoBrickFirmware/MonoBrickFirmware.csproj b/MonoBrickFirmware/MonoBrickFirmware.csproj index 298ba77..dff10ad 100644 --- a/MonoBrickFirmware/MonoBrickFirmware.csproj +++ b/MonoBrickFirmware/MonoBrickFirmware.csproj @@ -35,6 +35,7 @@ + @@ -172,11 +173,5 @@ font.profont_7 - - - - - - - + \ No newline at end of file diff --git a/MonoBrickFirmware/Tools/EventNode.cs b/MonoBrickFirmware/Tools/EventNode.cs new file mode 100644 index 0000000..599b2b4 --- /dev/null +++ b/MonoBrickFirmware/Tools/EventNode.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace MonoBrickFirmware.Tools +{ + public class EventNode + { + private Delegate EventToRaise; + private Object[] Parameters; + + public EventNode(Delegate Event, Object[] Parameters) + { + this.EventToRaise = Event; + this.Parameters = Parameters; + } + + public Delegate eventToRaise { + get { return this.EventToRaise; } + } + public Object[] parameters { + get { return this.Parameters; } + } + } +} From 95945d09b02d7ceb4571ee61bbdcb8de8b8bcf67 Mon Sep 17 00:00:00 2001 From: Lars Gardien Date: Tue, 29 Dec 2015 21:02:22 +0100 Subject: [PATCH 3/3] Sensor Polling Implemented the polling on the UartSensor class. Off course this should eventually be in the ISensor class so all sensors can profit from it, but I didn't need it, so didn't implement it. One can now subscribe to a sensor's event and the queuethread will decide when an event gets raised. --- .vs/config/applicationhost.config | 1038 +++++++++++++++++ MonoBrickFirmware/Sensors/EV3ColorSensor.cs | 51 +- MonoBrickFirmware/Sensors/EV3GyroSensor.cs | 49 +- MonoBrickFirmware/Sensors/EV3IRSensor.cs | 41 +- .../Sensors/EV3UltraSonicSensor.cs | 47 +- MonoBrickFirmware/Sensors/SensorFactory.cs | 5 + MonoBrickFirmware/Sensors/UARTSensor.cs | 63 +- 7 files changed, 1187 insertions(+), 107 deletions(-) create mode 100644 .vs/config/applicationhost.config diff --git a/.vs/config/applicationhost.config b/.vs/config/applicationhost.config new file mode 100644 index 0000000..936d45d --- /dev/null +++ b/.vs/config/applicationhost.config @@ -0,0 +1,1038 @@ + + + + + + + + +
+
+
+
+
+
+
+
+ + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+ +
+
+
+ +
+
+ +
+
+ +
+
+
+ + +
+
+
+
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MonoBrickFirmware/Sensors/EV3ColorSensor.cs b/MonoBrickFirmware/Sensors/EV3ColorSensor.cs index 5e1b515..21bc423 100644 --- a/MonoBrickFirmware/Sensors/EV3ColorSensor.cs +++ b/MonoBrickFirmware/Sensors/EV3ColorSensor.cs @@ -5,31 +5,30 @@ namespace MonoBrickFirmware.Sensors { public class EV3ColorSensor : UartSensor{ - - /// - /// Initializes a new instance of the NXTColorSensor class in color mode - /// - public EV3ColorSensor (SensorPort port) : this(port, ColorMode.Color) - { - - } - - /// - /// Initializes a new instance of the NXTColorSensor class. - /// - /// Mode. - public EV3ColorSensor (SensorPort port, ColorMode mode) : base(port) - { - base.Initialise(base.uartMode); - Mode = mode; - - } - - /// - /// Gets or sets the color mode. - /// - /// The color mode. - public ColorMode Mode { + /// + /// Initializes a new instance of the EV3ColorSensor class in color mode + /// + /// refresh rate for pollThread + public EV3ColorSensor(SensorPort port, int pollInterval = 50) : this(port, ColorMode.Color, pollInterval) + { + } + + /// + /// Initializes a new instance of the EV3ColorSensor class. + /// + /// Mode. + /// refresh rate for pollThread + public EV3ColorSensor(SensorPort port, ColorMode mode, int pollInterval = 50) : base(port, pollInterval) + { + base.Initialise(base.uartMode); + Mode = mode; + } + + /// + /// Gets or sets the color mode. + /// + /// The color mode. + public ColorMode Mode { get{return SensorModeToColorMode(base.uartMode);} set{ base.SetMode(ColorModeToSensorMode(value)); @@ -80,7 +79,7 @@ public int ReadRaw () /// /// Read the intensity of the reflected or ambient light in percent. In color mode the color index is returned /// - public int Read() + public override int Read() { int value = 0; switch (Mode) diff --git a/MonoBrickFirmware/Sensors/EV3GyroSensor.cs b/MonoBrickFirmware/Sensors/EV3GyroSensor.cs index 83f7f87..b757687 100644 --- a/MonoBrickFirmware/Sensors/EV3GyroSensor.cs +++ b/MonoBrickFirmware/Sensors/EV3GyroSensor.cs @@ -25,30 +25,29 @@ public enum GyroMode { /// Class for the EV3 Gyro sensor /// public class EV3GyroSensor :UartSensor{ - - /// - /// Initializes a new instance of the Gyro sensor. - /// - public EV3GyroSensor (SensorPort port) : this(port, GyroMode.Angle) - { - - } - - /// - /// Initializes a new instance of the Gyro sensor. - /// - /// Mode. - public EV3GyroSensor (SensorPort port, GyroMode mode) : base(port) - { - base.Initialise(base.uartMode); - Mode = mode; - } - - /// - /// Gets or sets the Gyro mode. - /// - /// The mode. - public GyroMode Mode { + + /// + /// Initializes a new instance of the Gyro sensor. + /// + public EV3GyroSensor(SensorPort port, int pollInterval = 50) : this(port, GyroMode.Angle, pollInterval) + { + } + + /// + /// Initializes a new instance of the Gyro sensor. + /// + /// Mode. + public EV3GyroSensor(SensorPort port, GyroMode mode, int pollInterval = 50) : base(port, pollInterval) + { + base.Initialise(base.uartMode); + Mode = mode; + } + + /// + /// Gets or sets the Gyro mode. + /// + /// The mode. + public GyroMode Mode { get{return (GyroMode) base.uartMode;} set{SetMode((UARTMode) value);} } @@ -106,7 +105,7 @@ public int RotationCount () /// /// Read the gyro sensor value. The returned value depends on the mode. /// - public int Read () + public override int Read () { if (Mode == GyroMode.Angle) { return BitConverter.ToInt16(ReadBytes(2),0)%360; diff --git a/MonoBrickFirmware/Sensors/EV3IRSensor.cs b/MonoBrickFirmware/Sensors/EV3IRSensor.cs index 377a220..06cc5f1 100644 --- a/MonoBrickFirmware/Sensors/EV3IRSensor.cs +++ b/MonoBrickFirmware/Sensors/EV3IRSensor.cs @@ -68,26 +68,25 @@ public class BeaconLocation{ /// public class EV3IRSensor : UartSensor{ - /// - /// Initializes a new instance of the class. - /// - /// Port. - public EV3IRSensor (SensorPort port) : this(port, IRMode.Proximity) - { - - } - - /// - /// Initializes a new instance of the class. - /// - /// Senosr port. - /// IR Mode. - public EV3IRSensor (SensorPort port, IRMode mode) : base(port) - { - base.Initialise(base.uartMode); - Mode = mode; - Channel = IRChannel.One; - } + /// + /// Initializes a new instance of the class. + /// + /// Port. + public EV3IRSensor(SensorPort port, int pollInterval = 50) : this(port, IRMode.Proximity, pollInterval) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// Senosr port. + /// IR Mode. + public EV3IRSensor(SensorPort port, IRMode mode, int pollInterval = 50) : base(port, pollInterval) + { + base.Initialise(base.uartMode); + Mode = mode; + Channel = IRChannel.One; + } /// /// Gets or sets the IR mode. @@ -125,7 +124,7 @@ public override string ReadAsString () /// Read the sensor value. The returned value depends on the mode. Distance in proximity mode. /// Remote command number in remote mode. Beacon location in seek mode. /// - public int Read(){ + public override int Read(){ int value = 0; switch ((IRMode)base.uartMode) { diff --git a/MonoBrickFirmware/Sensors/EV3UltraSonicSensor.cs b/MonoBrickFirmware/Sensors/EV3UltraSonicSensor.cs index 420b0b8..46d06dd 100644 --- a/MonoBrickFirmware/Sensors/EV3UltraSonicSensor.cs +++ b/MonoBrickFirmware/Sensors/EV3UltraSonicSensor.cs @@ -7,29 +7,28 @@ namespace MonoBrickFirmware.Sensors /// Class for the EV3 ultrasonic sensor /// public class EV3UltrasonicSensor : UartSensor{ - /// - /// Initializes a new instance of the EV3 Ultrasonic Sensor. - /// - public EV3UltrasonicSensor (SensorPort port) : this(port, UltraSonicMode.Centimeter) - { - - } - - /// - /// Initializes a new instance of the EV3 Ultrasonic Sensor. - /// - /// Mode. - public EV3UltrasonicSensor (SensorPort port, UltraSonicMode mode) : base(port) - { - base.Initialise(base.uartMode); - Mode = mode; - } - - /// - /// Gets or sets the Gyro mode. - /// - /// The mode. - public UltraSonicMode Mode { + /// + /// Initializes a new instance of the EV3 Ultrasonic Sensor. + /// + public EV3UltrasonicSensor(SensorPort port, int pollInterval = 50) : this(port, UltraSonicMode.Centimeter, pollInterval) + { + } + + /// + /// Initializes a new instance of the EV3 Ultrasonic Sensor. + /// + /// Mode. + public EV3UltrasonicSensor(SensorPort port, UltraSonicMode mode, int pollInterval = 50) : base(port, pollInterval) + { + base.Initialise(base.uartMode); + Mode = mode; + } + + /// + /// Gets or sets the Gyro mode. + /// + /// The mode. + public UltraSonicMode Mode { get{return (UltraSonicMode) base.uartMode;} set{SetMode((UARTMode) value);} } @@ -59,7 +58,7 @@ public override string ReadAsString () /// /// Read the sensor value. Result depends on the mode /// - public int Read () + public override int Read () { if (Mode == UltraSonicMode.Listen) { diff --git a/MonoBrickFirmware/Sensors/SensorFactory.cs b/MonoBrickFirmware/Sensors/SensorFactory.cs index d2a9f82..b649ee8 100644 --- a/MonoBrickFirmware/Sensors/SensorFactory.cs +++ b/MonoBrickFirmware/Sensors/SensorFactory.cs @@ -158,6 +158,11 @@ public override string ReadAsString () { return ""; } + + public override int Read() + { + return 0; + } /// /// Gets the name of the sensor. diff --git a/MonoBrickFirmware/Sensors/UARTSensor.cs b/MonoBrickFirmware/Sensors/UARTSensor.cs index e824d87..dd123b7 100644 --- a/MonoBrickFirmware/Sensors/UARTSensor.cs +++ b/MonoBrickFirmware/Sensors/UARTSensor.cs @@ -3,6 +3,8 @@ using System.Collections.Generic; using MonoBrickFirmware.Native; using MonoBrickFirmware.Tools; +using System.Threading; +using System.ComponentModel; namespace MonoBrickFirmware.Sensors { @@ -51,17 +53,56 @@ public abstract class UartSensor:ISensor protected const int NumberOfSensorPorts = SensorManager.NumberOfSensorPorts; protected SensorPort port; protected UARTMode uartMode{get; private set;} - - public UartSensor (SensorPort port) - { - this.port = port; - uartMemory = SensorManager.Instance.UartMemory; - UartDevice = SensorManager.Instance.UartDevice; - } - - public abstract string ReadAsString (); - - public abstract void SelectNextMode(); + + private int pollTime = 50; + private EventWaitHandle stopPolling = new ManualResetEvent(false); + private QueueThread queue = QueueThread.Instance; + private Thread pollThread = null; + public UartSensor(SensorPort port, int pollTime = 50) + { + this.port = port; + this.pollTime = pollTime; + uartMemory = SensorManager.Instance.UartMemory; + UartDevice = SensorManager.Instance.UartDevice; + pollThread = new Thread(sensorPollThread); + pollThread.Start(); + } + + /// + /// Stop polling this instance + /// + public void Kill() + { + stopPolling.Set(); + pollThread.Join(); + } + + + /// + /// thread that checks the sensor' state, and raises the propertyChanged event in queue when it is changed. + /// + private void sensorPollThread() + { + Thread.CurrentThread.IsBackground = true; + int lastState = Read(); + while (!stopPolling.WaitOne(pollTime)) + { + int currenState = Read(); + if (currenState != lastState) + { + queue.Enqueue(propertyChangedEvent, this, new PropertyChangedEventArgs(GetSensorName())); + lastState = currenState; + } + } + } + + public event PropertyChangedEventHandler propertyChangedEvent; + + public abstract string ReadAsString(); + + public abstract int Read(); + + public abstract void SelectNextMode(); public abstract string GetSensorName();