@ -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 > 1 0 0 )
Lines . RemoveAt ( 0 ) ;
OnPropertyChanged ( "ConsoleText" ) ;
}
public double SampleDelay { get { return 0.000026 ; } }
public int MaxSequenceSize { get { return 2 0 4 8 ; } }
private class Sequence
{
public ulong StartTime { get ; set ; }
@ -46,7 +51,11 @@ namespace SerialMonitor
}
}
}
double ValueToHeight ( byte value ) { return ( double ) value + 1 0 ; }
double ValueToHeight ( double time , byte value )
{
//value = (byte)(Math.Sin(time * 100.0) * 127.0 + 128.0);
return 2 5 6.0 - ( double ) value + 1 0 ;
}
private SortedSet < Sequence > Sequences = new SortedSet < Sequence > ( new Sequence . Comparer ( ) ) ;
public IEnumerable < Line > 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 / 1 0 0 0 0 0 0.0 ;
if ( seqStartTime + ( double ) sequence . Data . Length * SampleDelay > ViewportStartTime & & seqStartTime < ViewportStartTime + ViewportTimeWidth )
{
foreach ( var line in ConvertToLines ( sequence ) )
yield return line ;
}
}
}
}
private IEnumerable < Line > ConvertToLines ( Sequence sequence , ulong displayStartTime )
private IEnumerable < Line > ConvertToLines ( Sequence sequence )
{
double sampleDelay = 0.000936 ; // in seconds
double scale = 1 0 ; // in pixels per second
double viewportWidth = OscilloscopeCanvas . ActualWidth ;
double scale = viewportWidth / ViewportTimeWidth ; // in pixels per second
double pos = ( sequence . StartTime - displayStartTime ) / 1 0 0 0 0 0 0.0 * scale ;
ulong displayStartTime = ( ulong ) ( viewportStartTime_ * 1 0 0 0 0 0 0.0 ) ;
double pos = ( ( double ) sequence . StartTime - ( double ) displayStartTime ) / 1 0 0 0 0 0 0.0 * scale ;
if ( pos > 1 0 0 0 )
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 / 1 0 0 0 0 0 0.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 / 1 0 0 0 0 0 0.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 / 1 0 0 0 0 0 0.0 : 0.0 ; } }
public double MaxTime { get { return Sequences . Any ( ) ? Math . Max ( MinTime + 0.1 , ( double ) Sequences . Last ( ) . StartTime / 1 0 0 0 0 0 0.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 ) ) ;
PropertyC hange d( this , new PropertyChangedEventArgs ( name ) ) ;
}
}
}