Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed MAX14720 MAX30205 USBDevice
HspGuiSourceV301/HSPGui/CustomControls/OpticalView.cs
- Committer:
- darienf
- Date:
- 2021-04-06
- Revision:
- 20:6d2af70c92ab
File content as of revision 20:6d2af70c92ab:
/*******************************************************************************
* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
*
* This software is protected by copyright laws of the United States and
* of foreign countries. This material may also be protected by patent laws
* and technology transfer regulations of the United States and of foreign
* countries. This software is furnished under a license agreement and/or a
* nondisclosure agreement and may only be used or reproduced in accordance
* with the terms of those agreements. Dissemination of this information to
* any party or parties not specified in the license agreement and/or
* nondisclosure agreement is expressly prohibited.
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of Maxim Integrated
* Products, Inc. shall not be used except as stated in the Maxim Integrated
* Products, Inc. Branding Policy.
*
* The mere transfer of this software does not imply any licenses
* of trade secrets, proprietary technology, copyrights, patents,
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all
* ownership rights.
*******************************************************************************
*/
#define USE_MEDICALCHARTHELPER
//#define CES_DEMO
using System;
using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using RPCSupport.Streaming;
using Maxim.Charting;
using System.Threading;
using HealthSensorPlatform.View;
using System.Windows.Forms.DataVisualization.Charting;
// DEBUG
using System.IO;
namespace HealthSensorPlatform.CustomControls
{
public partial class OpticalView : UserControl, IDeviceView, IOpticalAlgorithmView
{
/* Constant Fields */
static string StartString = "Start Monitor";
static string StopString = "Stop Monitor";
const int ChartTime = 4; // 4 seconds
/* Fields */
private bool connected = false;
private bool streaming = false;
private RPCSupport.RPCClient rpcClient;
//private MedicalChartHelper medicalChartLED;
//private MedicalChartHelper medicalChartAccel;
private AutoScaleCalculator fifo1Calc;
private AutoScaleCalculator fifo2Calc;
private AutoScaleCalculator fifo3Calc;
eStreamMode streamMode;
byte fifo_waterlevel_mark = 0x0f;
byte sample_avg;
byte sample_rate;
byte pulse_width;
byte red_led_current;
byte ir_led_current;
byte green_led_current;
byte slot_1;
byte slot_2;
byte slot_3;
byte slot_4;
// Heart Rate Sensor
int points; // Number of x-axis points for a plot
int sampleRate; // Human readable sample rate
int sampleAverage; // Human readable number of average points
// LIS2HD
int sampleRateAccel;
int pointsAccel;
EventHandler<PartialArrayIntAvailableEventArgs> appendChart; // Allows event to be unregistered
Dictionary<string, MedianFilter> intervalDict = new Dictionary<string, MedianFilter>();
Dictionary<string, AutoScaleCalculator> chartScaleDict = new Dictionary<string, AutoScaleCalculator>();
List<Control> streamingControls = new List<Control>();
#if CES_DEMO
// Algorithm Data
Queue red;
Queue ir;
Queue led;
// struct to run algorithms
AlgorithmMobileBU.AlgorithmConfiguration config;
AlgorithmMobileBU.AlgorithmOutput output;
int algoCounter = 0;
#endif
// DEBUG
//StreamWriter file = new StreamWriter("hsp_output_data.csv");
/* Constructors */
public OpticalView()
{
InitializeComponent();
OpticalSensorInitControls();
cboSampleRate.SelectedIndexChanged += new EventHandler(cboSRPWLed_SelectedIndexChanged);
cboPulseWidth.SelectedIndexChanged += new EventHandler(cboSRPWLed_SelectedIndexChanged);
cboRedLED.SelectedIndexChanged += new EventHandler(cboSRPWLed_SelectedIndexChanged);
cboIRLED.SelectedIndexChanged += new EventHandler(cboSRPWLed_SelectedIndexChanged);
cboGreenLED.SelectedIndexChanged += new EventHandler(cboSRPWLed_SelectedIndexChanged);
cboSampleRate.SelectedIndexChanged += new EventHandler(cboSampleRate_SelectedIndexChanged);
cboSampleAvg.SelectedIndexChanged += new EventHandler(cboSampleRate_SelectedIndexChanged);
streamingControls.AddRange(new Control[] { panel1, maximGroupBoxSettings, maximGroupBoxLEDcurrents, maximGroupBoxLEDTimingSlots, btnDefaults });
#if CES_DEMO
// Algorithm
red = new Queue();
ir = new Queue();
led = new Queue();
config = new AlgorithmMobileBU.AlgorithmConfiguration();
output = new AlgorithmMobileBU.AlgorithmOutput();
config.snrNoFingerThreshold = -9;
config.acLowPerfusionThreshold = 950;
config.isAGC = 0;
//updateAlgorithm();
lblHeartRate.Visible = true;
lblHeartRateText.Visible = true;
#endif
}
/* Delegates */
//public delegate void StreamingStartStopEventHandler(StreamingStartStopEventArgs e);
/* Events */
//public event StreamingStartStopEventHandler StreamingStartStop;
public event EventHandler<StreamingStartStopEventArgs> StreamingStartStop;
/* Enums */
public enum eStreamMode
{
eHR,
eSPO2,
eMulti
}
/* Properties */
public RPCSupport.RPCClient RPCClient
{
set
{
rpcClient = value;
appendChart = new EventHandler<PartialArrayIntAvailableEventArgs>(On_AppendChart);
rpcClient.streaming.PartialArrayIntAvailable += appendChart;
}
}
public bool Connected
{
get
{
return connected;
}
set
{
connected = value;
if (connected == false)
if (btnMonitoring.Text == StopString)
streamingStartStop();
}
}
public int AccelSampleRate
{
get
{
return sampleRateAccel;
}
}
public int OpticalSampleRate
{
get
{
return sampleRate / sampleAverage;
}
}
public eStreamMode ModeConfiguration
{
get
{
return streamMode;
}
}
/* Methods */
// Clean up streaming
public void Close()
{
rpcClient.streaming.PartialArrayIntAvailable -= appendChart; // Stop event from firing
// Disable streaming if enabled
if (btnMonitoring.Text == StopString)
streamingStartStop();
}
public void DisplayAlgorithmResult(double heartRateBPM, bool heartRateBPMValid, double heartRateBPMSignalStrength,
double spO2Percent, bool spO2PercentValid, double spO2PercentSignalStrength)
{
// 100Hz only - TODO
if (OpticalSampleRate != 100)
return;
if (heartRateBPMValid)
{
lblHeartRate.ForeColor = SystemColors.ControlText;
lblHeartRate.Text = string.Format("{0}", heartRateBPM * (sampleRate / 100.0)); // 100.0 for default sample rate
}
else
{
lblHeartRate.ForeColor = Color.Gray;
}
if (spO2PercentValid)
{
lblSpO2.ForeColor = SystemColors.ControlText;
lblSpO2.Text = string.Format("{0:0.0}", spO2Percent);
}
else
{
lblSpO2.ForeColor = Color.Gray;
}
}
public void DisplayAlgorithmReset()
{
lblHeartRate.Text = "----";
lblHeartRate.ForeColor = Color.Gray;
lblSpO2.Text = "----";
lblSpO2.ForeColor = Color.Gray;
}
System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
void InitGraphs()
{
/*
medicalChartLED = new MedicalChartHelper(chartLED,
"ChartArea1Red", "SeriesRed", "Red ADC Code",
"ChartArea2IR", "SeriesIR", "IR ADC Code",
"ChartArea3Green", "SeriesGreen", "Green ADC Code",
MedicalChartHelper.DataFormats.FormatUnsigned);
medicalChartLED._plotPoints = 200;
medicalChartAccel = new MedicalChartHelper(chartAccel,
"ChartArea4AccelX", "SeriesAccelX", "Accelerometer X",
"ChartArea5AccelY", "SeriesAccelY", "Accelerometer Y",
"ChartArea6AccelZ", "SeriesAccelZ", "Accelerometer Z",
MedicalChartHelper.DataFormats.Format16bit2sComplement);
*/
MedianFilter fifo1 = new MedianFilter(10);
MedianFilter fifo2 = new MedianFilter(10);
MedianFilter fifo3 = new MedianFilter(10);
MedianFilter accelx = new MedianFilter(10);
MedianFilter accely = new MedianFilter(10);
MedianFilter accelz = new MedianFilter(10);
intervalDict.Add("ChartArea1Red", fifo1);
intervalDict.Add("ChartArea2IR", fifo2);
intervalDict.Add("ChartArea3Green", fifo3);
intervalDict.Add("ChartArea4AccelX", accelx);
intervalDict.Add("ChartArea5AccelY", accely);
intervalDict.Add("ChartArea6AccelZ", accelz);
fifo1Calc = new AutoScaleCalculator(0, 90000);
fifo1Calc.Minimum = 0;
fifo1Calc.Maximum = Math.Pow(2, 18);
fifo1Calc.Intervals = 5;
fifo1Calc.MinimumRange = 200;
fifo1Calc.ScaleTrigger = 0.8;
fifo1Calc.RescaleTargetRange = 0.25;
chartScaleDict.Add("ChartArea1Red", fifo1Calc);
fifo2Calc = new AutoScaleCalculator(0, 90000);
fifo2Calc.Minimum = 0;
fifo2Calc.Maximum = Math.Pow(2, 18);
fifo2Calc.Intervals = 5;
fifo2Calc.MinimumRange = 200;
fifo2Calc.ScaleTrigger = 0.8;
fifo2Calc.RescaleTargetRange = 0.25;
chartScaleDict.Add("ChartArea2IR", fifo2Calc);
fifo3Calc = new AutoScaleCalculator(0, 90000);
fifo3Calc.Minimum = 0;
fifo3Calc.Maximum = Math.Pow(2, 18);
fifo3Calc.Intervals = 5;
fifo3Calc.MinimumRange = 200;
fifo3Calc.ScaleTrigger = 0.8;
fifo3Calc.RescaleTargetRange = 0.25;
chartScaleDict.Add("ChartArea3Green", fifo2Calc);
AutoScaleCalculator accelXCalc = new AutoScaleCalculator(-10000, 10000);
accelXCalc.Minimum = -32768;
accelXCalc.Maximum = 32767;
accelXCalc.Intervals = 5;
accelXCalc.MinimumRange = 500;
accelXCalc.ScaleTrigger = 0.8;
accelXCalc.RescaleTargetRange = 0.25;
chartScaleDict.Add("ChartArea4AccelX", accelXCalc);
AutoScaleCalculator accelYCalc = new AutoScaleCalculator(-10000, 10000);
accelYCalc.Minimum = -32768;
accelYCalc.Maximum = 32767;
accelYCalc.Intervals = 5;
accelYCalc.MinimumRange = 500;
accelYCalc.ScaleTrigger = 0.8;
accelYCalc.RescaleTargetRange = 0.25;
chartScaleDict.Add("ChartArea5AccelY", accelYCalc);
AutoScaleCalculator accelZCalc = new AutoScaleCalculator(-10000, 10000);
accelZCalc.Minimum = -32768;
accelZCalc.Maximum = 32767;
accelZCalc.Intervals = 5;
accelZCalc.MinimumRange = 500;
accelZCalc.ScaleTrigger = 0.8;
accelZCalc.RescaleTargetRange = 0.25;
chartScaleDict.Add("ChartArea6AccelZ", accelZCalc);
/*
Random rand = new Random();
int[] data1 = new int[10];
int[] data2 = new int[10];
int[] data3 = new int[10];
double[] data1_ = new double[10];
double[] data2_ = new double[10];
double[] data3_ = new double[10];
for (int i = 0; i < data1.Length; i++)
{
data1[i] = rand.Next(10);
data2[i] = rand.Next(10);
data3[i] = rand.Next(10);
data1_[i] = rand.NextDouble() * 10;
data2_[i] = rand.NextDouble() * 10;
data3_[i] = rand.NextDouble() * 10;
}
*/
/*
int[] dummyData = new int[] { 0 };
medicalChartLED.AppendDataChartArea1(dummyData, 0, 0);
medicalChartLED.AppendDataChartArea2(dummyData, 0, 0);
medicalChartLED.AppendDataChartArea3(dummyData, 0, 0);
//medicalChartAccel._xCount1++;
//medicalChartAccel._xCount2++;
//medicalChartAccel._xCount3++;
medicalChartAccel.AppendDataChartArea1(dummyData, 0, 0);
medicalChartAccel.AppendDataChartArea2(dummyData, 0, 0);
medicalChartAccel.AppendDataChartArea3(dummyData, 0, 0);
*/
setupGraphs();
chartLED.ChartAreas["ChartArea3Green"].Visible = false;
timer.Interval = 50;
//timer.Tick += new EventHandler(timer_Tick);
}
void setupGraphs()
{
chartLED.SuspendLayout();
chartAccel.SuspendLayout();
/* Initialize Empty Chart Grid */
chartLED.Series["SeriesRed"].Points.Clear();
chartLED.Series["SeriesIR"].Points.Clear();
chartLED.Series["SeriesGreen"].Points.Clear();
chartAccel.Series["SeriesAccelX"].Points.Clear();
chartAccel.Series["SeriesAccelY"].Points.Clear();
chartAccel.Series["SeriesAccelZ"].Points.Clear();
// Clear labels
chartLED.ChartAreas["ChartArea1Red"].AxisX.CustomLabels.Clear();
chartLED.ChartAreas["ChartArea2IR"].AxisX.CustomLabels.Clear();
chartLED.ChartAreas["ChartArea3Green"].AxisX.CustomLabels.Clear();
chartAccel.ChartAreas["ChartArea4AccelX"].AxisX.CustomLabels.Clear();
chartAccel.ChartAreas["ChartArea5AccelY"].AxisX.CustomLabels.Clear();
chartAccel.ChartAreas["ChartArea6AccelZ"].AxisX.CustomLabels.Clear();
chartLED.Series["SeriesRed"].Points.Add(0);
chartLED.Series["SeriesIR"].Points.Add(0);
chartLED.Series["SeriesGreen"].Points.Add(0);
chartAccel.Series["SeriesAccelX"].Points.Add(0);
chartAccel.Series["SeriesAccelY"].Points.Add(0);
chartAccel.Series["SeriesAccelZ"].Points.Add(0);
// Initialize Plots for OS24
chartLED.ChartAreas["ChartArea1Red"].AxisX.Interval = points / ChartTime;
chartLED.ChartAreas["ChartArea2IR"].AxisX.Interval = points / ChartTime;
chartLED.ChartAreas["ChartArea3Green"].AxisX.Interval = points / ChartTime;
chartLED.ChartAreas["ChartArea1Red"].AxisX.Maximum = points;
chartLED.ChartAreas["ChartArea2IR"].AxisX.Maximum = points;
chartLED.ChartAreas["ChartArea3Green"].AxisX.Maximum = points;
chartLED.ChartAreas["ChartArea1Red"].AxisY.Maximum = 90000;
chartLED.ChartAreas["ChartArea1Red"].AxisY.Minimum = 0;
chartLED.ChartAreas["ChartArea2IR"].AxisY.Maximum = 90000;
chartLED.ChartAreas["ChartArea2IR"].AxisY.Minimum = 0;
chartLED.ChartAreas["ChartArea3Green"].AxisY.Maximum = 90000;
chartLED.ChartAreas["ChartArea3Green"].AxisY.Minimum = 0;
// Initialize Plots for LIS2HD
sampleRateAccel = sampleRate;
//pointsAccel = (sampleRateAccel / sampleAverage) * ChartTime;
pointsAccel = (sampleRateAccel) * ChartTime;
chartAccel.ChartAreas["ChartArea4AccelX"].AxisX.Interval = pointsAccel / ChartTime;
chartAccel.ChartAreas["ChartArea5AccelY"].AxisX.Interval = pointsAccel / ChartTime;
chartAccel.ChartAreas["ChartArea6AccelZ"].AxisX.Interval = pointsAccel / ChartTime;
chartAccel.ChartAreas["ChartArea4AccelX"].AxisX.Maximum = pointsAccel;
chartAccel.ChartAreas["ChartArea5AccelY"].AxisX.Maximum = pointsAccel;
chartAccel.ChartAreas["ChartArea6AccelZ"].AxisX.Maximum = pointsAccel;
chartAccel.ChartAreas["ChartArea4AccelX"].AxisY.Minimum = -10000;
chartAccel.ChartAreas["ChartArea5AccelY"].AxisY.Minimum = -10000;
chartAccel.ChartAreas["ChartArea6AccelZ"].AxisY.Minimum = -10000;
chartAccel.ChartAreas["ChartArea4AccelX"].AxisY.Maximum = 10000;
chartAccel.ChartAreas["ChartArea5AccelY"].AxisY.Maximum = 10000;
chartAccel.ChartAreas["ChartArea6AccelZ"].AxisY.Maximum = 10000;
// Set X-axis labels in seconds
for (int i = 0; i < ChartTime + 1; i++)
{
chartLED.ChartAreas["ChartArea1Red"].AxisX.CustomLabels.Add( (sampleRate / sampleAverage) * (2 * i - 1) / 2, (sampleRate / sampleAverage) * (2 * i + 1) / 2, i.ToString());
chartLED.ChartAreas["ChartArea2IR"].AxisX.CustomLabels.Add( (sampleRate / sampleAverage) * (2 * i - 1) / 2, (sampleRate / sampleAverage) * (2 * i + 1) / 2, i.ToString());
chartLED.ChartAreas["ChartArea3Green"].AxisX.CustomLabels.Add( (sampleRate / sampleAverage) * (2 * i - 1) / 2, (sampleRate / sampleAverage) * (2 * i + 1) / 2, i.ToString());
chartAccel.ChartAreas["ChartArea4AccelX"].AxisX.CustomLabels.Add(sampleRateAccel * (2 * i - 1) / 2, sampleRateAccel * (2 * i + 1) / 2, i.ToString());
chartAccel.ChartAreas["ChartArea5AccelY"].AxisX.CustomLabels.Add(sampleRateAccel * (2 * i - 1) / 2, sampleRateAccel * (2 * i + 1) / 2, i.ToString());
chartAccel.ChartAreas["ChartArea6AccelZ"].AxisX.CustomLabels.Add(sampleRateAccel * (2 * i - 1) / 2, sampleRateAccel * (2 * i + 1) / 2, i.ToString());
}
chartLED.ResumeLayout();
chartLED.Invalidate();
chartAccel.ResumeLayout();
chartAccel.Invalidate();
}
void timer_Tick(object sender, EventArgs e)
{
/*Single tmpData = dynamicData[0].Y;
for (int i = 0; i < dynamicData.Length - 1; i++)
{
dynamicData[i].Y = dynamicData[i + 1].Y;
}
dynamicData[dynamicData.Length - 1].Y = tmpData;*/
//PointF[] newData = GenerateDynamicData(100, 5);
//UpdateLedChart("SeriesRed", newData);
//UpdateLedChart("SeriesIR", newData);
//UpdateLedChart("SeriesGreen", newData);
}
/*private void UpdateLedChart(string seriesName, PointF[] data)
{
int count;
chartLED.SuspendLayout();
//chartLED.Series[seriesName].Points.Clear();
foreach (PointF pt in data)
{
//chartLED.Series[seriesName].Points.AddXY(pt.X, pt.Y);
chartLED.Series[seriesName].Points.Add(pt.Y);
}
for (count = chartLED.Series[seriesName].Points.Count;
count > points;
count = chartLED.Series[seriesName].Points.Count)
{
chartLED.Series[seriesName].Points.RemoveAt(0);
}
chartLED.ResumeLayout();
chartLED.Invalidate();
}*/
private void UpdateXYZChart(string seriesName, int[] data)
{
int datapoint;
int count;
chartAccel.SuspendLayout();
//chartLED.Series[seriesName].Points.Clear();
foreach (int val in data)
{
//chartLED.Series[seriesName].Points.AddXY(pt.X, pt.Y);
datapoint = val;
// Two's complement conversion
if (val > 0x8000)
{
datapoint = datapoint - 0x10000;
}
chartAccel.Series[seriesName].Points.Add(datapoint);
}
for (count = chartAccel.Series[seriesName].Points.Count;
count > pointsAccel;
count = chartAccel.Series[seriesName].Points.Count)
{
chartAccel.Series[seriesName].Points.RemoveAt(0);
}
//chartAccel.ResetAutoValues();
chartAccel.ResumeLayout();
chartAccel.Invalidate();
}
private void UpdateLedChart(string seriesName, int[] data)
{
int[] dataPoints = new int[points];
int j = 0;
int count;
chartLED.SuspendLayout();
//chartLED.Series[seriesName].Points.Clear();
// Update Chart with new data
if (data.Length > points)
j = data.Length - points;
for (; j < data.Length; j++ )
{
chartLED.Series[seriesName].Points.Add(data[j]);
#if CES_DEMO
if (seriesName.CompareTo("SeriesRed") == 0)
red.Enqueue(data[j]);
else if (seriesName.CompareTo("SeriesIR") == 0)
ir.Enqueue(data[j]);
else if (seriesName.CompareTo("SeriesGreen") == 0)
led.Enqueue(data[j]);
#endif
}
for (count = chartLED.Series[seriesName].Points.Count;
count > points;
count = chartLED.Series[seriesName].Points.Count)
{
chartLED.Series[seriesName].Points.RemoveAt(0);
}
}
private void UpdateLedChartScale(string chartName, string seriesName)
{
int min = Int32.MaxValue, max = 0;
int i, j;
int[] data = new int[points];
int graphCount;
//int maxRound, minRound;
graphCount = chartLED.Series[seriesName].Points.Count;
for (j = 0; j < graphCount; j++ )
{
data[j] = (int)chartLED.Series[seriesName].Points[j].YValues[0];
}
//if (data.Length < sampleRate)
// return; // not enough data to draw graph
/*else*/
if (graphCount < (sampleRate / sampleAverage) * 2) // look back 2 seconds
{
i = 0;
}
else // look back 2 seconds
{
i = graphCount - (sampleRate / sampleAverage) * 2;
}
min = data[i];
max = data[i];
for (; i < graphCount; i++ )
{
if (data[i] < min && data[i] != 0)
min = data[i];
else if (data[i] > max)
max = data[i];
}
/*
MedianFilter filter;
intervalDict.TryGetValue(chartName, out filter);
var minMax = chartInterval(min, max, chartLED.ChartAreas[chartName].AxisY.Minimum, chartLED.ChartAreas[chartName].AxisY.Maximum, filter);
minRound = minMax.Item1;
maxRound = minMax.Item2;
// For no finger on sensor
if (max < 500)
max = 500;
*/
AutoScaleCalculator chartScale;
chartScaleDict.TryGetValue(chartName, out chartScale);
var minMax = chartScale.Interval(min, max);
// Round to nearest 100 with averaging
//chartLED.ChartAreas[chartName].AxisY.Maximum = (chartLED.ChartAreas[chartName].AxisY.Maximum + (max / 100 + 1) * 100)/2;
//chartLED.ChartAreas[chartName].AxisY.Maximum = (((int)chartLED.ChartAreas[chartName].AxisY.Maximum + max)/200 + 1) * 100;
//chartLED.ChartAreas[chartName].AxisY.Minimum = (chartLED.ChartAreas[chartName].AxisY.Minimum + (min / 100 - 1) * 100)/2;
//chartLED.ChartAreas[chartName].AxisY.Minimum = (((int)chartLED.ChartAreas[chartName].AxisY.Minimum + min)/200 - 1) * 100;
chartLED.ChartAreas[chartName].AxisY.Minimum = minMax.Item1;
chartLED.ChartAreas[chartName].AxisY.Maximum = minMax.Item2;
chartLED.ResumeLayout();
chartLED.Invalidate();
}
private void UpdateXYZChartScale(string chartName, string seriesName)
{
int min = Int32.MaxValue, max = Int32.MinValue;
int i, j;
int maxRound, minRound;
int graphCount;
int[] data = new int[pointsAccel];
graphCount = chartAccel.Series[seriesName].Points.Count;
// Save all points from plot to data[]
for (j = 0; j < graphCount; j++)
{
data[j] = (int)chartAccel.Series[seriesName].Points[j].YValues[0];
}
if (graphCount < (sampleRateAccel / sampleAverage) * 2) // look back 3 seconds
i = 0;
else
i = graphCount - (sampleRateAccel / sampleAverage) * 2;
// Find min/max
min = data[i];
max = data[i];
for (; i < graphCount; i++)
{
if (data[i] < min)
min = data[i];
else if (data[i] > max)
max = data[i];
}
/*
// Sane defaults
if (min == max)
{
min = 0;
max = 100;
}
MedianFilter filter;
intervalDict.TryGetValue(chartName, out filter);
var minMax = chartInterval(min, max, chartAccel.ChartAreas[chartName].AxisY.Minimum, chartAccel.ChartAreas[chartName].AxisY.Maximum, filter);
minRound = minMax.Item1;
maxRound = minMax.Item2;
if (maxRound > 32768)
maxRound = 33000;
if (minRound < -32768)
minRound = -33000;
*/
AutoScaleCalculator chartScale;
chartScaleDict.TryGetValue(chartName, out chartScale);
var minMax = chartScale.Interval(min, max);
minRound = (int)minMax.Item1;
maxRound = (int)minMax.Item2;
// Set the Min and Max for Y Axis
//chartAccel.ChartAreas[chartName].AxisY.Maximum = (((int)chartAccel.ChartAreas[chartName].AxisY.Maximum + max) / 200 + 1) * 100;
//chartAccel.ChartAreas[chartName].AxisY.Minimum = (((int)chartAccel.ChartAreas[chartName].AxisY.Minimum + min) / 200 - 1) * 100;
chartAccel.ChartAreas[chartName].AxisY.Maximum = maxRound;
chartAccel.ChartAreas[chartName].AxisY.Minimum = minRound;
//System.Diagnostics.Debug.Print(chartName + " count: " + graphCount + " minRound: " + minRound + " maxRound: " + maxRound + " min: " + min + " max: " + max);
chartAccel.ResumeLayout();
chartAccel.Invalidate();
}
/*private PointF[] dynamicData;
private static PointF[] GenerateDynamicData(double amplitude, int sampleCount)
{
Random rnd = new Random();
PointF[] points = new PointF[sampleCount];
points[0] = new PointF(0, (Single)(amplitude * rnd.NextDouble()));
for (int i = 1; i < sampleCount; i++)
{
points[i] = new PointF(i, (Single)(points[i - 1].Y + (amplitude / 10 * (0.5 - rnd.NextDouble()))));
if (points[i].Y > amplitude) points[i].Y = (Single)amplitude;
}
return (points);
}*/
/// <summary>
/// Calculate rounded minimum and maximum for chart data
/// </summary>
/// <param name="minimum"></param>
/// <param name="maximum"></param>
/// <param name="chartInterval"></param>
/// <returns></returns>
private static Tuple<int, int> chartInterval(int minimum, int maximum, double chartMinimum, double chartMaximum, MedianFilter chartInterval)
{
int delta, interval, roundInterval, roundCenter;
double mag, magPower, magMostSigDigit;
int center;
// 10% and 90% range
int chartRange = (int)(chartMaximum - chartMinimum);
int dataRange = maximum - minimum;
if (minimum < chartMinimum + chartRange * 0.10 || maximum > chartMaximum - chartRange * 0.10
|| dataRange > 0.9 * chartRange || dataRange < 0.1 * chartRange)
{
delta = (int)((maximum - minimum));
interval = delta * (100 / 35) / 5; // delta * 4 = 25% * 4 = 100 (full chart scale)
center = minimum + (maximum - minimum) / 2;
mag = Math.Floor(Math.Log10(interval));
magPower = Math.Pow(10, mag);
magMostSigDigit = (int)(interval / (double)magPower + 0.5);
if (magMostSigDigit >= 5.0)
magMostSigDigit = 10;
else if (magMostSigDigit >= 2.0)
magMostSigDigit = 5;
else if (magMostSigDigit >= 1.0)
magMostSigDigit = 2;
roundInterval = (int)(magMostSigDigit * magPower);
if (roundInterval < 100)
{
roundInterval = 100;
}
roundInterval = chartInterval.Filter(roundInterval);
roundCenter = ((center + 100) / 200) * 200;
int roundMin = (int)(roundCenter - roundInterval * 2.5);
int roundMax = (int)(roundCenter + roundInterval * 2.5);
if (roundInterval > 104858)
{
roundMin = 0;
roundMax = 550000;
}
/*else
{
if (roundMin < 0) // || roundMax > 524288)
{
roundMin = 0;
roundMax = roundInterval * 5;
}
}*/
return new Tuple<int, int>(roundMin, roundMax);
}
return new Tuple<int, int>((int)chartMinimum, (int)chartMaximum);
}
void OpticalSensorInitControls()
{
cboMode.Items.AddRange(new string[] { "HR","SPO2","LED" });
cboSampleRate.Items.AddRange(new string[] { "50", "100", "200", "400" });
cboSampleAvg.Items.AddRange(new string[] { "1", "2", "4", "8", "16", "32" });
cboPulseWidth.Items.AddRange(new string[] { "69", "118", "215", "411" });
cboADCFSrangenA.Items.AddRange(new string[] { "2048", "4096", "8192", "16384" });
double slopeInt = 25.0 / 128.0;
for (int index = 0; index < 256; index++)
{
string str = index < 0x0F ? (0.2 * index).ToString() : (slopeInt * index + slopeInt).ToString();
cboIRLED.Items.Add(str);
cboRedLED.Items.Add(str);
cboGreenLED.Items.Add(str);
cboPilotPA.Items.Add(str);
}
OpticalSensorDefaults();
calculateAvgCurrent();
InitGraphs();
}
public void OpticalSensorDefaults()
{
cboMode.SelectedItem = "SPO2";
cboRedLED.SelectedItem = "10.15625";
cboIRLED.SelectedItem = "10.15625";
cboGreenLED.SelectedItem = "10.15625";
cboSampleRate.SelectedItem = "100";
cboPulseWidth.SelectedItem = "411";
cboSampleAvg.SelectedItem = "1";
cboADCFSrangenA.SelectedItem = "8192";
cboLEDslot1.SelectedIndex = 1;
cboLEDslot2.SelectedIndex = 2;
cboLEDslot3.SelectedIndex = 3;
cboLEDslot4.SelectedIndex = 0;
// Used to generate the initial chart grid
sample_rate = (byte)cboSampleRate.SelectedIndex;
sample_avg = (byte)cboSampleAvg.SelectedIndex;
sampleRate = (1 << sample_rate) * 50; // (1 << sample_rate) = 2^sample_rate
sampleAverage = (1 << sample_avg); // 2^sample_avg
points = (sampleRate / sampleAverage) * ChartTime; // 4 seconds, 2^sample_av
sampleRateAccel = sampleRate;
pointsAccel = (sampleRateAccel / sampleAverage) * ChartTime;
}
private void cbo_IndexChanged(object sender, EventArgs e)
{
if ((MaximStyle.MaximComboBox)sender == cboMode)
{
bool HRmode = (cboMode.Text == "HR");
bool SPO2mode = (cboMode.Text == "SPO2");
bool multiLEDmode = (cboMode.Text == "LED");
//labelcboRedLED.Enabled = myMAX30101.valid_Red;
//cboRedLED.Enabled = myMAX30101.valid_Red;
bool valid_IR = (multiLEDmode || SPO2mode);
bool valid_Green = multiLEDmode;
bool valid_Red = multiLEDmode;
labelcboIRLED.Enabled = valid_IR;
cboIRLED.Enabled = valid_IR;
labelcboGreenLED.Enabled = valid_Green;
cboGreenLED.Enabled = valid_Green;
cboLEDslot1.Enabled = multiLEDmode;
cboLEDslot2.Enabled = multiLEDmode;
cboLEDslot3.Enabled = multiLEDmode;
cboLEDslot4.Enabled = multiLEDmode;
{
// Hide unused LED channel graphs
// | mode | ChartArea1Red | ChartArea2IR | ChartArea3Green |
// | LED | visible | visible | visible | MAX30101 only
// | SPO2 | visible | visible | hidden |
// | HR | visible | hidden | hidden | MAX30101: Red only. MAX30100: IR only.
valid_Red = true;
valid_IR = multiLEDmode || SPO2mode;
valid_Green = multiLEDmode;
chartLED.ChartAreas["ChartArea1Red"].Visible = valid_Red;
chartLED.ChartAreas["ChartArea2IR"].Visible = valid_IR;
chartLED.ChartAreas["ChartArea3Green"].Visible = valid_Green;
}
}
}
public void On_AppendChart(object sender, PartialArrayIntAvailableEventArgs e)
{
if (streaming)
{
if ((e.reportID & 0xF0) == PartialArrayIntAvailableEventArgs.PACKET_MAX30101)
{
if (e.array1.Length != 0)
{
UpdateLedChart("SeriesRed", e.array1);
UpdateLedChartScale("ChartArea1Red", "SeriesRed");
}
if (e.array2.Length != 0)
{
UpdateLedChart("SeriesIR", e.array2);
UpdateLedChartScale("ChartArea2IR", "SeriesIR");
}
if (e.array3.Length != 0)
{
UpdateLedChart("SeriesGreen", e.array3);
UpdateLedChartScale("ChartArea3Green", "SeriesGreen");
}
}
if (e.reportID == PartialArrayIntAvailableEventArgs.PACKET_LIS2DH)
{
if (e.array1.Length != 0)
{
UpdateXYZChart("SeriesAccelX", e.array1);
UpdateXYZChartScale("ChartArea4AccelX", "SeriesAccelX");
}
if (e.array2.Length != 0)
{
UpdateXYZChart("SeriesAccelY", e.array2);
UpdateXYZChartScale("ChartArea5AccelY", "SeriesAccelY");
}
if (e.array3.Length != 0)
{
UpdateXYZChart("SeriesAccelZ", e.array3);
UpdateXYZChartScale("ChartArea6AccelZ", "SeriesAccelZ");
}
#if CES_DEMO
if (sampleRate == 100)
updateAlgorithm();
#endif
}
}
}
#if CES_DEMO
private void updateAlgorithm()
{
int rtn = 0;
while (red.Count != 0 ) //&& ir.Couunt != 0 && led.Count != 0)
{
StringBuilder outputData = new StringBuilder();
int redVal = (Int32)red.Dequeue(); // Always dequeue red, checked in while loop
int irVal = ir.Count > 0 ? (Int32)ir.Dequeue() : 1;
int ledVal = led.Count > 0 ? (Int32)led.Dequeue() : 1;
switch (streamMode)
{
case eStreamMode.eSPO2:
rtn = AlgorithmMobileBU.runAlgorithm_win(irVal, redVal, 1, // ir, r, led
25, sampleRate, ++algoCounter,
0, 0, 0, ref config, ref output);
break;
case eStreamMode.eHR: // TODO: Not functioning
rtn = AlgorithmMobileBU.runAlgorithm_win(1, redVal, 1, // ir, r, led
25, sampleRate, ++algoCounter,
0, 0, 0, ref config, ref output);
break;
case eStreamMode.eMulti:
rtn = AlgorithmMobileBU.runAlgorithm_win(irVal, redVal, ledVal, // ir, r, led
25, sampleRate, ++algoCounter,
0, 0, 0, ref config, ref output);
break;
}
//outputData.Append(DateTime.Now.ToString("HH:mm:ss.ffff"));
//outputData.Append(",");
//outputData.Append(irVal);
//outputData.Append(",");
//outputData.Append(redVal);
//outputData.Append(",");
//outputData.Append(0); // Can be green
//outputData.Append(",");
//outputData.Append(0); // Ax
//outputData.Append(",");
//outputData.Append(0); // Ay
//outputData.Append(",");
//outputData.Append(0); // Az
//outputData.Append(",");
//file.WriteLine(outputData.ToString()); // Raw data output
}
lblHeartRate.Text = Math.Round(output.hr).ToString(); //redIn.ToString();
lblRespRate.Text = output.resp_rate.ToString("N");
lblSpO2.Text = output.R == 0 ? "0" : (-45.060 * output.R * output.R + 30.354 * output.R + 94.845).ToString("N");//output.spo2.ToString("N");
lblHeartRateVariation.Text = output.hrv.ToString("N");
lblPulseInterval.Text = output.pulse_interval.ToString("N");
}
#endif
private void OpticalView_Load(object sender, EventArgs e)
{
//OpticalSensorInitControls();
//OpticalSensorDefaults();
}
private void streamingStartStop()
{
if (cboMode.Text == "HR") streamMode = eStreamMode.eHR;
if (cboMode.Text == "SPO2") streamMode = eStreamMode.eSPO2;
if (cboMode.Text == "LED") streamMode = eStreamMode.eMulti;
if (Connected && btnMonitoring.Text == StartString)
{
streaming = true;
sample_rate = (byte)cboSampleRate.SelectedIndex;
sample_avg = (byte)cboSampleAvg.SelectedIndex;
pulse_width = (byte)cboPulseWidth.SelectedIndex;
red_led_current = (byte)cboRedLED.SelectedIndex;
ir_led_current = (byte)cboIRLED.SelectedIndex;
green_led_current = (byte)cboGreenLED.SelectedIndex;
slot_1 = (byte)cboLEDslot1.SelectedIndex;
slot_2 = (byte)cboLEDslot2.SelectedIndex;
slot_3 = (byte)cboLEDslot3.SelectedIndex;
slot_4 = (byte)cboLEDslot4.SelectedIndex;
sampleRate = Int32.Parse((string)cboSampleRate.SelectedItem);
sampleAverage = Int32.Parse((string)cboSampleAvg.SelectedItem);
points = (sampleRate / sampleAverage ) * ChartTime;
foreach (Control c in streamingControls)
c.Enabled = false;
#if CES_DEMO
// For Algorithm
sampleRate = (1 << sample_rate) * 50; // (1 << sample_rate) = 2^sample_rate
sampleAverage = (1 << sample_avg); // 2^sample_avg
points = (sampleRate / sampleAverage) * ChartTime; // 4 seconds, 2^sample_av
sampleRateAccel = 10; // TODO, update with real value from Jerry
pointsAccel = (sampleRateAccel / sampleAverage) * ChartTime;
// Reset algorithm counter
algoCounter = 0;
if (sampleRate == 100)
{
lblHeartRateText.Enabled = true;
lblHeartRate.Enabled = true;
lblSpO2.Enabled = true;
lblSpO2Text.Enabled = true;
}
else
{
lblHeartRateText.Enabled = false;
lblHeartRate.Enabled = false;
lblSpO2.Enabled = false;
lblSpO2Text.Enabled = false;
}
#endif
// Setup grid
setupGraphs();
switch (streamMode)
{
case eStreamMode.eHR:
rpcClient.MAX30101.HRmode_init(fifo_waterlevel_mark, sample_avg, sample_rate, pulse_width,
red_led_current, (byte)(sample_rate + 4));
break;
case eStreamMode.eMulti:
rpcClient.MAX30101.Multimode_init(fifo_waterlevel_mark, sample_avg, sample_rate, pulse_width,
red_led_current, ir_led_current, green_led_current,
slot_1, slot_2, slot_3, slot_4, (byte)(sample_rate + 4));
break;
case eStreamMode.eSPO2:
rpcClient.MAX30101.SpO2mode_init(fifo_waterlevel_mark, sample_avg, sample_rate, pulse_width,
red_led_current, ir_led_current, (byte)(sample_rate + 4));
break;
}
btnMonitoring.Text = StopString;
if (StreamingStartStop != null)
StreamingStartStop(this, new StreamingStartStopEventArgs() { state = true });
}
else if (btnMonitoring.Text == StopString)
{
streaming = false;
switch (streamMode)
{
case eStreamMode.eHR:
rpcClient.MAX30101.HRmode_stop(connected);
break;
case eStreamMode.eMulti:
rpcClient.MAX30101.Multimode_stop(connected);
break;
case eStreamMode.eSPO2:
rpcClient.MAX30101.SpO2mode_stop(connected);
break;
}
//rpcClient.MAX30101.StopStreaming();
btnMonitoring.Text = StartString;
foreach (Control c in streamingControls)
c.Enabled = true;
if (StreamingStartStop != null)
StreamingStartStop(this, new StreamingStartStopEventArgs() { state = false });
}
}
private void btnMonitoring_Click(object sender, EventArgs e)
{
//if (Connected)
streamingStartStop();
}
private void button1_Click(object sender, EventArgs e)
{
timer.Start();
}
private void button1_Click_1(object sender, EventArgs e)
{
/* Debug*/
//int count = chartLED.Series["SeriesRed"].Points.Count;
//int count2 = chartAccel.Series["SeriesAccelX"].Points.Count;
UpdateXYZChartScale("ChartArea6AccelZ", "SeriesAccelZ");
}
private void btnDefaults_Click(object sender, EventArgs e)
{
OpticalSensorDefaults();
}
private void cboSRPWLed_SelectedIndexChanged(object sender, EventArgs e)
{
calculateAvgCurrent();
}
private void calculateAvgCurrent()
{
double ratio = double.Parse(cboPulseWidth.Text) * 1e-6 * double.Parse(cboSampleRate.Text);
string _noDataString = "---";
if (ratio <= 1)
{
lblAvgIRLEDcurrent.Text = String.Format("{0:0.00}", double.Parse(cboIRLED.Text) * ratio);
lblAvgRedLEDcurrent.Text = String.Format("{0:0.00}", double.Parse(cboRedLED.Text) * ratio);
// https://jira.maxim-ic.com/browse/OS24EVK-17 Green LED: Multi-LED Mode timeslice; FIFO Read Red, IR, Green
lblAvgGreenLEDcurrent.Text = String.Format("{0:0.00}", double.Parse(cboGreenLED.Text) * ratio);
// https://jira.maxim-ic.com/browse/OS24EVK-32 update lblAvgPilotPALEDcurrent from cboPilotPA similar to lblAvgGreenLEDcurrent
//lblAvgPilotPALEDcurrent.Text = String.Format("{0:0.00}", double.Parse(cboPilotPA.Text) * ratio);
}
else
{
lblAvgIRLEDcurrent.Text = _noDataString;
lblAvgRedLEDcurrent.Text = _noDataString;
// https://jira.maxim-ic.com/browse/OS24EVK-17 Green LED: Multi-LED Mode timeslice; FIFO Read Red, IR, Green
lblAvgGreenLEDcurrent.Text = _noDataString;
// https://jira.maxim-ic.com/browse/OS24EVK-32 update lblAvgPilotPALEDcurrent from cboPilotPA similar to lblAvgGreenLEDcurrent
lblAvgPilotPALEDcurrent.Text = _noDataString;
}
}
void cboSampleRate_SelectedIndexChanged(object sender, EventArgs e)
{
if ((string)cboSampleRate.SelectedItem == "100" && (string)cboSampleAvg.SelectedItem == "1")
grpAlgorithm.Enabled = true;
else
grpAlgorithm.Enabled = false;
sampleRate = Int32.Parse((string)cboSampleRate.SelectedItem);
sampleAverage = Int32.Parse((string)cboSampleAvg.SelectedItem);
}
public string SettingsString()
{
StringBuilder strBuilder = new StringBuilder();
strBuilder.Append("% ");
strBuilder.Append("Mode = ");
strBuilder.Append(cboMode.SelectedItem);
strBuilder.Append(Environment.NewLine);
strBuilder.Append("% ");
strBuilder.Append("Sample Rate (Hz) = ");
strBuilder.Append(cboSampleRate.SelectedItem);
strBuilder.Append(" Sample Average = ");
strBuilder.Append(cboSampleAvg.SelectedItem);
strBuilder.Append(" Pulse Width (us) = ");
strBuilder.Append(cboPulseWidth.SelectedItem);
strBuilder.Append(" ADC Full Scale Range (nA) = ");
strBuilder.Append(cboADCFSrangenA.SelectedItem);
strBuilder.Append(Environment.NewLine);
strBuilder.Append("% ");
strBuilder.Append(" LED Red (mA) = ");
strBuilder.Append(cboRedLED.SelectedItem);
strBuilder.Append(" LED IR (mA) = ");
strBuilder.Append(cboIRLED.SelectedItem);
strBuilder.Append(" LED Green (mA) = ");
strBuilder.Append(cboGreenLED.SelectedItem);
strBuilder.Append(Environment.NewLine);
strBuilder.Append("% ");
strBuilder.Append("LED Slot 1 = ");
strBuilder.Append(cboLEDslot1.SelectedIndex);
strBuilder.Append(" LED Slot 2 = ");
strBuilder.Append(cboLEDslot2.SelectedIndex);
strBuilder.Append(" LED Slot 3 = ");
strBuilder.Append(cboLEDslot3.SelectedIndex);
strBuilder.Append(" LED Slot 4 = ");
strBuilder.Append(cboLEDslot4.SelectedIndex);
return strBuilder.ToString();
}
public string AccelSettingString()
{
return "% Sample Rate (Hz) = " + AccelSampleRate;
}
public InitArgs.HRModeInitStart GetHRModeArgs()
{
InitArgs.HRModeInitStart args = new InitArgs.HRModeInitStart();
args.FifoWaterlevelMark = fifo_waterlevel_mark;
args.SampleRate = (byte)cboSampleRate.SelectedIndex;
args.SampleAverage = (byte)cboSampleAvg.SelectedIndex;
args.PulseWidth = (byte)cboPulseWidth.SelectedIndex;
args.RedLedCurrent = (byte)cboRedLED.SelectedIndex;
return args;
}
public InitArgs.SpO2HRModeInitStart GetSpO2HRModeArgs()
{
InitArgs.SpO2HRModeInitStart args = new InitArgs.SpO2HRModeInitStart();
args.FifoWaterlevelMark = fifo_waterlevel_mark;
args.SampleRate = (byte)cboSampleRate.SelectedIndex;
args.SampleAverage = (byte)cboSampleAvg.SelectedIndex;
args.PulseWidth = (byte)cboPulseWidth.SelectedIndex;
args.RedLedCurrent = (byte)cboRedLED.SelectedIndex;
args.IRLedCurrent = (byte)cboIRLED.SelectedIndex;
return args;
}
public InitArgs.MultiModeInitStart GetMultiModeArgs()
{
InitArgs.MultiModeInitStart args = new InitArgs.MultiModeInitStart();
args.FifoWaterlevelMark = fifo_waterlevel_mark;
args.SampleRate = (byte)cboSampleRate.SelectedIndex;
args.SampleAverage = (byte)cboSampleAvg.SelectedIndex;
args.PulseWidth = (byte)cboPulseWidth.SelectedIndex;
args.RedLedCurrent = (byte)cboRedLED.SelectedIndex;
args.IRLedCurrent = (byte)cboIRLED.SelectedIndex;
args.GreenLedCurrent = (byte)cboGreenLED.SelectedIndex;
args.Slot1 = (byte)cboLEDslot1.SelectedIndex;
args.Slot2 = (byte)cboLEDslot2.SelectedIndex;
args.Slot3 = (byte)cboLEDslot3.SelectedIndex;
args.Slot4 = (byte)cboLEDslot4.SelectedIndex;
return args;
}
public void SetHRModeArgs(InitArgs.HRModeInitStart args)
{
cboSampleRate.SelectedIndex = args.SampleRate;
cboSampleAvg.SelectedIndex = args.SampleAverage;
cboPulseWidth.SelectedIndex = args.PulseWidth;
cboRedLED.SelectedIndex = args.RedLedCurrent;
}
public void SetSpO2HRModeArgs(InitArgs.SpO2HRModeInitStart args)
{
cboSampleRate.SelectedIndex = args.SampleRate;
cboSampleAvg.SelectedIndex = args.SampleAverage;
cboPulseWidth.SelectedIndex = args.PulseWidth;
cboRedLED.SelectedIndex = args.RedLedCurrent;
cboIRLED.SelectedIndex = args.IRLedCurrent;
}
public void SetMultiModeArgs(InitArgs.MultiModeInitStart args)
{
cboSampleRate.SelectedIndex = args.SampleRate;
cboSampleAvg.SelectedIndex = args.SampleAverage;
cboPulseWidth.SelectedIndex = args.PulseWidth;
cboRedLED.SelectedIndex = args.RedLedCurrent;
cboIRLED.SelectedIndex = args.IRLedCurrent;
cboGreenLED.SelectedIndex = args.GreenLedCurrent;
cboLEDslot1.SelectedIndex = args.Slot1;
cboLEDslot2.SelectedIndex = args.Slot2;
cboLEDslot3.SelectedIndex = args.Slot3;
cboLEDslot4.SelectedIndex = args.Slot4;
}
class MedianFilter
{
Queue<int> items;
int depth;
public MedianFilter(int depth)
{
items = new Queue<int>(depth + 1);
this.depth = depth;
}
public int Filter(int current)
{
int last;
items.Enqueue(current);
if (items.Count > depth)
{
items.Dequeue();
}
last = items.Peek();
if (items.Count < depth)
{
return current;
}
else
{
int count;
int[] arrayItems = items.ToArray();
int maxCount = 0;
int maxKey = 0;
Dictionary<int, int> valueOccurance = new Dictionary<int, int>();
for (int i = 0; i < arrayItems.Length; i++)
{
bool exists = valueOccurance.TryGetValue(arrayItems[i], out count);
if (exists)
{
count++;
valueOccurance.Remove(arrayItems[i]);
valueOccurance.Add(arrayItems[i], count);
}
else
{
valueOccurance.Add(arrayItems[i], 1);
}
}
foreach (KeyValuePair<int, int> item in valueOccurance)
{
if (item.Key > maxCount)
{
maxKey = item.Key;
}
}
return maxKey;
}
}
}
/*
public class StreamingStartStopEventArgs : EventArgs
{
public bool state { get; set; }
}*/
}
}