diff --git a/OneWireIO.ino b/OneWireIO.ino
index 925f199..c6bf7b7 100644
--- a/OneWireIO.ino
+++ b/OneWireIO.ino
@@ -5,12 +5,14 @@
#define OWPin 2
#define InterruptNumber 0 // Must correspond to the OWPin to correctly detect state changes. On Arduino Uno, interrupt 0 is for digital pin 2
-const int SkipSamples = 8; // how many samples we want to skip between two samples we keep (can be used to lower the sampling frequency)
-const int BufferSize = 128;
+// how many samples we want to skip between two samples we keep (can be used to lower the sampling frequency)
+#define SkipSamples 0
+
+const int BufferSize = 512;
byte buffer1[BufferSize];
byte buffer2[BufferSize];
byte* backBuffer = buffer1;
-volatile byte backBufferPos = 0;
+volatile short backBufferPos = 0;
byte samplesSkipped = SkipSamples;
unsigned long backBufferStartTime = micros();
@@ -24,7 +26,7 @@ void setup()
digitalWrite(LEDPin, LOW);
- attachInterrupt(InterruptNumber,onewireInterrupt,CHANGE);
+ //attachInterrupt(InterruptNumber,onewireInterrupt,CHANGE);
cli();//disable interrupts
@@ -36,7 +38,7 @@ void setup()
ADMUX |= (1 << REFS0); //set reference voltage
ADMUX |= (1 << ADLAR); //left align the ADC value- so we can read highest 8 bits from ADCH register only
- ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); //set ADC clock with 128 prescaler- 16mHz/128=125kHz ; 13 cycles for a conversion which means 9600 samples per second
+ ADCSRA |= (1 << ADPS2) | (0 << ADPS1) | (1 << ADPS0); //set ADC clock with 32 prescaler- 16mHz/32=500KHz ; 13 cycles for a conversion which means 38000 samples per second
ADCSRA |= (1 << ADATE); //enabble auto trigger
ADCSRA |= (1 << ADIE); //enable interrupts when measurement complete
ADCSRA |= (1 << ADEN); //enable ADC
@@ -44,7 +46,7 @@ void setup()
sei();//enable interrupts
- Serial.begin(200000);
+ Serial.begin(400000);
}
void loop()
@@ -52,27 +54,32 @@ void loop()
while(backBufferPos < BufferSize / 2) ;
cli();//disable interrupts
byte* currentBuffer = backBuffer;
- unsigned long currentBufferStartTime = backBufferStartTime;
- byte currentBufferSize = backBufferPos;
+ short currentBufferSize = backBufferPos;
backBuffer = (backBuffer == buffer1 ? buffer2 : buffer1);
backBufferPos = 0;
- backBufferStartTime = micros();
sei();//enable interrupts
+ unsigned long currentBufferStartTime = backBufferStartTime;
+ backBufferStartTime = micros();
+ digitalWrite(LEDPin, LOW);
+ //Serial.write(currentBuffer, currentBufferSize);
oscilloscope.write(currentBuffer, currentBufferSize, currentBufferStartTime);
}
ISR(ADC_vect) {//when new ADC value ready
byte sample = ADCH; //store 8 bit value from analog pin 0
-
+
+ #if SkipSamples > 0
if(samplesSkipped++ < SkipSamples)
return;
samplesSkipped = 0;
+ #endif
backBuffer[backBufferPos++] = sample;
if(backBufferPos >= BufferSize)
{
// overflow of back buffer, we loose the current sample
+ digitalWrite(LEDPin, HIGH);
backBufferPos = BufferSize - 1;
}
}
diff --git a/SerialMonitor/SerialMonitor/App.xaml.cs b/SerialMonitor/SerialMonitor/App.xaml.cs
index ac44671..74db570 100644
--- a/SerialMonitor/SerialMonitor/App.xaml.cs
+++ b/SerialMonitor/SerialMonitor/App.xaml.cs
@@ -28,7 +28,7 @@ namespace SerialMonitor
Serial = new SerialPort();
Serial.PortName = "COM4";
- Serial.BaudRate = 200000;
+ Serial.BaudRate = 400000;
Serial.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(OnDataReceived);
diff --git a/SerialMonitor/SerialMonitor/MainWindow.xaml b/SerialMonitor/SerialMonitor/MainWindow.xaml
index 98617aa..7cb7936 100644
--- a/SerialMonitor/SerialMonitor/MainWindow.xaml
+++ b/SerialMonitor/SerialMonitor/MainWindow.xaml
@@ -1,11 +1,18 @@
+ Title="Serial Monitor" Height="490.75" Width="923">
-
-
-
+
+
+
+
+
+
+
+
+
+
diff --git a/SerialMonitor/SerialMonitor/MainWindow.xaml.cs b/SerialMonitor/SerialMonitor/MainWindow.xaml.cs
index 9a6318d..82c9d9f 100644
--- a/SerialMonitor/SerialMonitor/MainWindow.xaml.cs
+++ b/SerialMonitor/SerialMonitor/MainWindow.xaml.cs
@@ -26,6 +26,37 @@ namespace SerialMonitor
var context = new MainWindowContext(this);
context.WriteLine("Connecting...");
this.DataContext = context;
+
+ this.MouseWheel += OnMouseWheel;
+ }
+
+ private void OnMouseWheel(object sender, MouseWheelEventArgs e)
+ {
+ MainWindowContext context = (MainWindowContext)this.DataContext;
+ Point cursorPos = e.GetPosition(context.OscilloscopeCanvas);
+ if (cursorPos.X < 0 || cursorPos.X > context.OscilloscopeCanvas.ActualWidth || cursorPos.Y < 0 || cursorPos.Y > context.OscilloscopeCanvas.ActualHeight)
+ return;
+
+ double cursorPosRatio = cursorPos.X / context.OscilloscopeCanvas.ActualWidth;
+ double cursorTime = context.ViewportStartTime + cursorPosRatio * context.ViewportTimeWidth;
+
+ double newTimeWidth = context.ViewportTimeWidth;
+ if (e.Delta > 0)
+ newTimeWidth /= e.Delta * 0.01;
+ else if (e.Delta < 0)
+ newTimeWidth *= -e.Delta * 0.01;
+
+ double totalTimeWidth = Math.Max(0.1, context.MaxTime - context.MinTime);
+ if (newTimeWidth > totalTimeWidth)
+ newTimeWidth = totalTimeWidth;
+
+ double newStartTime = cursorTime - cursorPosRatio * newTimeWidth;
+ if (newStartTime < context.MinTime)
+ newStartTime = context.MinTime;
+ if (newStartTime + newTimeWidth > context.MaxTime)
+ newStartTime = context.MaxTime - newTimeWidth;
+
+ context.SetViewport(newStartTime, newTimeWidth);
}
}
}
diff --git a/SerialMonitor/SerialMonitor/MainWindowContext.cs b/SerialMonitor/SerialMonitor/MainWindowContext.cs
index e329a90..33d40ec 100644
--- a/SerialMonitor/SerialMonitor/MainWindowContext.cs
+++ b/SerialMonitor/SerialMonitor/MainWindowContext.cs
@@ -1,11 +1,13 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
+using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
+using System.Windows.Input;
using System.Windows.Shapes;
namespace SerialMonitor
@@ -28,11 +30,14 @@ namespace SerialMonitor
public void WriteLine(string line)
{
Lines.Add(line);
- if (Lines.Count > 9)
+ if (Lines.Count > 100)
Lines.RemoveAt(0);
OnPropertyChanged("ConsoleText");
}
+ public double SampleDelay { get { return 0.000026; } }
+ public int MaxSequenceSize { get { return 2048; } }
+
private class Sequence
{
public ulong StartTime { get; set; }
@@ -46,7 +51,11 @@ namespace SerialMonitor
}
}
}
- double ValueToHeight(byte value) { return (double)value + 10; }
+ double ValueToHeight(double time, byte value)
+ {
+ //value = (byte)(Math.Sin(time * 100.0) * 127.0 + 128.0);
+ return 256.0 - (double)value + 10;
+ }
private SortedSet Sequences = new SortedSet(new Sequence.Comparer());
public IEnumerable Oscilloscope
{
@@ -54,64 +63,147 @@ namespace SerialMonitor
{
if(!Sequences.Any())
yield break;
-
- ulong startTime = Sequences.ElementAt(0).StartTime;
foreach (var sequence in Sequences)
{
- foreach (var line in ConvertToLines(sequence, startTime))
- yield return line;
+ double seqStartTime = (double)sequence.StartTime/1000000.0;
+ if (seqStartTime + (double)sequence.Data.Length * SampleDelay > ViewportStartTime && seqStartTime < ViewportStartTime + ViewportTimeWidth)
+ {
+ foreach (var line in ConvertToLines(sequence))
+ yield return line;
+ }
}
}
}
- private IEnumerable ConvertToLines(Sequence sequence, ulong displayStartTime)
+ private IEnumerable ConvertToLines(Sequence sequence)
{
- double sampleDelay = 0.000936; // in seconds
- double scale = 10; // in pixels per second
+ double viewportWidth = OscilloscopeCanvas.ActualWidth;
+ double scale = viewportWidth / ViewportTimeWidth; // in pixels per second
- double pos = (sequence.StartTime - displayStartTime) / 1000000.0 * scale;
+ ulong displayStartTime = (ulong)(viewportStartTime_ * 1000000.0);
+
+ double pos = ((double)sequence.StartTime - (double)displayStartTime) / 1000000.0 * scale;
if (pos > 1000)
yield break;
- double prevHeight = ValueToHeight(sequence.Data[0]);
+ double prevPos = pos;
+ byte minValue = sequence.Data[0];
+ byte maxValue = minValue;
+ int prevIdx = 0;
+ double prevHeight = ValueToHeight(sequence.StartTime / 1000000.0, minValue);
for (int idx = 1; idx < sequence.Data.Length; ++idx)
{
byte value = sequence.Data[idx];
- var line = new Line();
- line.Stroke = System.Windows.Media.Brushes.LightSteelBlue;
- line.X1 = pos;
- pos += sampleDelay * scale;
- line.X2 = pos;
- line.Y1 = prevHeight;
- prevHeight = ValueToHeight(value);
- line.Y2 = prevHeight;
- line.HorizontalAlignment = HorizontalAlignment.Left;
- line.VerticalAlignment = VerticalAlignment.Center;
- line.StrokeThickness = 1;
- yield return line;
+ pos += SampleDelay * scale;
+ if (value > maxValue) maxValue = value;
+ if (value < minValue) minValue = value;
+
+ if (pos > 0 && pos < viewportWidth && pos - prevPos >= 5 || idx == sequence.Data.Length - 1)
+ {
+ var line = new Line();
+ line.Stroke = System.Windows.Media.Brushes.LightSteelBlue;
+ line.HorizontalAlignment = HorizontalAlignment.Left;
+ line.VerticalAlignment = VerticalAlignment.Center;
+ line.StrokeThickness = 1;
+
+ line.X1 = prevPos;
+ prevPos = pos;
+ line.X2 = pos;
+
+ double time = (double)sequence.StartTime / 1000000.0 + (double)idx * SampleDelay;
+ double lastHeight = ValueToHeight(time, value);
+
+ if (idx == prevIdx + 1)
+ {
+ line.Y1 = prevHeight;
+ line.Y2 = lastHeight;
+ }
+ else
+ {
+ if (value - minValue > maxValue - value)
+ {
+ line.Y1 = ValueToHeight(time, minValue);
+ line.Y2 = ValueToHeight(time, maxValue);
+ }
+ else
+ {
+ line.Y1 = ValueToHeight(time, maxValue);
+ line.Y2 = ValueToHeight(time, minValue);
+ }
+ }
+
+ prevHeight = lastHeight;
+ minValue = value;
+ maxValue = value;
+ prevIdx = idx;
+
+ yield return line;
+ }
}
}
public void AddSequence(ulong startTime, byte[] data)
{
+ // TODO: merge sequences if total size is lower than MaxSequenceSize
var sequence = new Sequence { StartTime = startTime, Data = data };
Sequences.Add(sequence);
OnPropertyChanged("Oscilloscope");
- var canvas = (Canvas)Window.FindName("Oscilloscope");
- /*canvas.Children.Clear();
+ OnPropertyChanged("MinTime");
+ OnPropertyChanged("MaxTime");
+ if (Sequences.Count == 1)
+ {
+ ViewportStartTime = MinTime;
+ }
+
+ var canvas = OscilloscopeCanvas;
+ foreach (var line in ConvertToLines(sequence))
+ canvas.Children.Add(line);
+ }
+
+ void RefreshOscilloscope()
+ {
+ var canvas = OscilloscopeCanvas;
+ canvas.Children.Clear();
foreach (var line in Oscilloscope)
- canvas.Children.Add(line);*/
- foreach (var line in ConvertToLines(sequence, Sequences.ElementAt(0).StartTime))
canvas.Children.Add(line);
}
+ private Canvas oscilloscopeCanvas_;
+ public Canvas OscilloscopeCanvas { get { if (oscilloscopeCanvas_ == null) oscilloscopeCanvas_ = (Canvas)Window.FindName("Oscilloscope"); return oscilloscopeCanvas_; } }
+
+ public double MinTime { get { return Sequences.Any() ? (double)Sequences.First().StartTime / 1000000.0 : 0.0; } }
+ public double MaxTime { get { return Sequences.Any() ? Math.Max(MinTime + 0.1, (double)Sequences.Last().StartTime / 1000000.0) : 0.1; } }
+ private double viewportTimeWidth_ = 0.1;
+ public double ViewportTimeWidth
+ {
+ get { return viewportTimeWidth_; }
+ set { viewportTimeWidth_ = value; OnPropertyChanged("ViewportTimeWidth"); RefreshOscilloscope(); }
+ }
+
+ private double viewportStartTime_ = 0;
+ public double ViewportStartTime
+ {
+ get { return viewportStartTime_; }
+ set { viewportStartTime_ = value; OnPropertyChanged("ViewportStartTime"); RefreshOscilloscope(); }
+ }
+ public double ScrollValue
+ {
+ get { return MathEx.Unproject(MathEx.Project(ViewportStartTime, MinTime, MaxTime - ViewportTimeWidth), MinTime, MaxTime); }
+ set { ViewportStartTime = MathEx.Unproject(MathEx.Project(value, MinTime, MaxTime), MinTime, MaxTime - ViewportTimeWidth); }
+ }
+
+ public void SetViewport(double startTime, double timeWidth)
+ {
+ viewportStartTime_ = startTime;
+ ViewportTimeWidth = timeWidth;
+ }
+
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
- PropertyChangedEventHandler handler = PropertyChanged;
- if (handler != null)
+ if (PropertyChanged != null)
{
- handler(this, new PropertyChangedEventArgs(name));
+ PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
}
diff --git a/SerialMonitor/SerialMonitor/MathEx.cs b/SerialMonitor/SerialMonitor/MathEx.cs
new file mode 100644
index 0000000..4d6e1e6
--- /dev/null
+++ b/SerialMonitor/SerialMonitor/MathEx.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace SerialMonitor
+{
+ public static class MathEx
+ {
+ public static double Project(double value, double rangeMin, double rangeMax)
+ {
+ return (value - rangeMin) / (rangeMax - rangeMin);
+ }
+
+ public static double Unproject(double ratio, double rangeMin, double rangeMax)
+ {
+ return rangeMin + ratio * (rangeMax - rangeMin);
+ }
+ }
+}
diff --git a/SerialMonitor/SerialMonitor/SerialMonitor.csproj b/SerialMonitor/SerialMonitor/SerialMonitor.csproj
index 1638f28..6f58ec6 100644
--- a/SerialMonitor/SerialMonitor/SerialMonitor.csproj
+++ b/SerialMonitor/SerialMonitor/SerialMonitor.csproj
@@ -54,6 +54,7 @@
Designer
+