This is the latest working repository used in our demo video for the Maxim to display temperature readings on Bluetooth
hspguisourcev301/HspGuiSourceV301/HSPGui/MedicalChartHelper.cs@5:bc128a16232f, 2021-05-02 (annotated)
- Committer:
- darienf
- Date:
- Sun May 02 23:09:04 2021 +0000
- Revision:
- 5:bc128a16232f
- Parent:
- 3:36de8b9e4b1a
This is the program that was last used, that has the working temperature and some comments
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
darienf | 3:36de8b9e4b1a | 1 | //using System; |
darienf | 3:36de8b9e4b1a | 2 | //using System.Collections; |
darienf | 3:36de8b9e4b1a | 3 | //using System.Collections.Generic; |
darienf | 3:36de8b9e4b1a | 4 | //using System.ComponentModel; |
darienf | 3:36de8b9e4b1a | 5 | //using System.Linq; |
darienf | 3:36de8b9e4b1a | 6 | //using System.Text; |
darienf | 3:36de8b9e4b1a | 7 | //using System.Windows.Forms; |
darienf | 3:36de8b9e4b1a | 8 | //using Microsoft.Win32.SafeHandles; |
darienf | 3:36de8b9e4b1a | 9 | |
darienf | 3:36de8b9e4b1a | 10 | namespace Maxim.MAX30101 |
darienf | 3:36de8b9e4b1a | 11 | { |
darienf | 3:36de8b9e4b1a | 12 | #pragma warning disable 1574 |
darienf | 3:36de8b9e4b1a | 13 | /// <summary> |
darienf | 3:36de8b9e4b1a | 14 | /// MedicalChartHelper class, an invisible "helper" class, |
darienf | 3:36de8b9e4b1a | 15 | /// helps manage an existing standard chart object. |
darienf | 3:36de8b9e4b1a | 16 | /// |
darienf | 3:36de8b9e4b1a | 17 | /// Initializes the standard |
darienf | 3:36de8b9e4b1a | 18 | /// System.Windows.Forms.DataVisualization.Charting.Chart chart |
darienf | 3:36de8b9e4b1a | 19 | /// with a maximum of 3 chart areas vertically aligned with each other. |
darienf | 3:36de8b9e4b1a | 20 | /// |
darienf | 3:36de8b9e4b1a | 21 | /// When data is appended to the chart, the chart series data |
darienf | 3:36de8b9e4b1a | 22 | /// is initially aligned with the left. Once the X axis reaches the |
darienf | 3:36de8b9e4b1a | 23 | /// right side of the screen, the chart begins scrolling so that |
darienf | 3:36de8b9e4b1a | 24 | /// newest data is aligned to the right edge. |
darienf | 3:36de8b9e4b1a | 25 | /// |
darienf | 3:36de8b9e4b1a | 26 | /// </summary> |
darienf | 3:36de8b9e4b1a | 27 | #pragma warning restore 1574 |
darienf | 3:36de8b9e4b1a | 28 | public class MedicalChartHelper |
darienf | 3:36de8b9e4b1a | 29 | { |
darienf | 3:36de8b9e4b1a | 30 | private System.Windows.Forms.DataVisualization.Charting.Chart _chart; |
darienf | 3:36de8b9e4b1a | 31 | private string _chartArea1Name; |
darienf | 3:36de8b9e4b1a | 32 | private string _chartArea2Name; |
darienf | 3:36de8b9e4b1a | 33 | private string _chartArea3Name; |
darienf | 3:36de8b9e4b1a | 34 | private string _series1Name; |
darienf | 3:36de8b9e4b1a | 35 | private string _series2Name; |
darienf | 3:36de8b9e4b1a | 36 | private string _series3Name; |
darienf | 3:36de8b9e4b1a | 37 | private string _chartArea1AxisYTitle; |
darienf | 3:36de8b9e4b1a | 38 | private string _chartArea2AxisYTitle; |
darienf | 3:36de8b9e4b1a | 39 | private string _chartArea3AxisYTitle; |
darienf | 3:36de8b9e4b1a | 40 | |
darienf | 3:36de8b9e4b1a | 41 | /// <summary> |
darienf | 3:36de8b9e4b1a | 42 | /// Constructor |
darienf | 3:36de8b9e4b1a | 43 | /// </summary> |
darienf | 3:36de8b9e4b1a | 44 | /// <param name="chart"></param> |
darienf | 3:36de8b9e4b1a | 45 | /// <param name="chartArea1Name"></param> |
darienf | 3:36de8b9e4b1a | 46 | /// <param name="series1Name"></param> |
darienf | 3:36de8b9e4b1a | 47 | /// <param name="chartArea1AxisYTitle"></param> |
darienf | 3:36de8b9e4b1a | 48 | /// <param name="chartArea2Name"></param> |
darienf | 3:36de8b9e4b1a | 49 | /// <param name="series2Name"></param> |
darienf | 3:36de8b9e4b1a | 50 | /// <param name="chartArea2AxisYTitle"></param> |
darienf | 3:36de8b9e4b1a | 51 | /// <param name="chartArea3Name"></param> |
darienf | 3:36de8b9e4b1a | 52 | /// <param name="series3Name"></param> |
darienf | 3:36de8b9e4b1a | 53 | /// <param name="chartArea3AxisYTitle"></param> |
darienf | 3:36de8b9e4b1a | 54 | public MedicalChartHelper(System.Windows.Forms.DataVisualization.Charting.Chart chart, |
darienf | 3:36de8b9e4b1a | 55 | string chartArea1Name = "ChartArea1Red", string series1Name = "SeriesRed", string chartArea1AxisYTitle = "Red ADC Code", |
darienf | 3:36de8b9e4b1a | 56 | string chartArea2Name = "ChartArea2IR", string series2Name = "SeriesIR", string chartArea2AxisYTitle = "IR ADC Code", |
darienf | 3:36de8b9e4b1a | 57 | string chartArea3Name = "ChartArea3Green", string series3Name = "SeriesGreen", string chartArea3AxisYTitle = "Green ADC Code", |
darienf | 3:36de8b9e4b1a | 58 | DataFormats dataFormat = DataFormats.FormatUnsigned |
darienf | 3:36de8b9e4b1a | 59 | ) |
darienf | 3:36de8b9e4b1a | 60 | { |
darienf | 3:36de8b9e4b1a | 61 | // implementation: see InitCharting() |
darienf | 3:36de8b9e4b1a | 62 | // default X axis length should be 10 seconds of data |
darienf | 3:36de8b9e4b1a | 63 | _chart = chart; |
darienf | 3:36de8b9e4b1a | 64 | _chartArea1Name = chartArea1Name; |
darienf | 3:36de8b9e4b1a | 65 | _chartArea2Name = chartArea2Name; |
darienf | 3:36de8b9e4b1a | 66 | _chartArea3Name = chartArea3Name; |
darienf | 3:36de8b9e4b1a | 67 | _series1Name = series1Name; |
darienf | 3:36de8b9e4b1a | 68 | _series2Name = series2Name; |
darienf | 3:36de8b9e4b1a | 69 | _series3Name = series3Name; |
darienf | 3:36de8b9e4b1a | 70 | _chartArea1AxisYTitle = chartArea1AxisYTitle; |
darienf | 3:36de8b9e4b1a | 71 | _chartArea2AxisYTitle = chartArea2AxisYTitle; |
darienf | 3:36de8b9e4b1a | 72 | _chartArea3AxisYTitle = chartArea3AxisYTitle; |
darienf | 3:36de8b9e4b1a | 73 | |
darienf | 3:36de8b9e4b1a | 74 | DataFormat = dataFormat; |
darienf | 3:36de8b9e4b1a | 75 | |
darienf | 3:36de8b9e4b1a | 76 | // VERIFY: OS24EVK-75 replace _xCount with _xCount1, _xCount2, _xCount3 |
darienf | 3:36de8b9e4b1a | 77 | //_xCount = 0; |
darienf | 3:36de8b9e4b1a | 78 | _xCount1 = 0; |
darienf | 3:36de8b9e4b1a | 79 | _xCount2 = 0; |
darienf | 3:36de8b9e4b1a | 80 | _xCount3 = 0; |
darienf | 3:36de8b9e4b1a | 81 | |
darienf | 3:36de8b9e4b1a | 82 | _chart.Titles[0].Visible = false; |
darienf | 3:36de8b9e4b1a | 83 | |
darienf | 3:36de8b9e4b1a | 84 | _chart.ChartAreas[_chartArea2Name].AlignWithChartArea = _chartArea1Name; |
darienf | 3:36de8b9e4b1a | 85 | _chart.ChartAreas[_chartArea3Name].AlignWithChartArea = _chartArea1Name; |
darienf | 3:36de8b9e4b1a | 86 | |
darienf | 3:36de8b9e4b1a | 87 | _chart.ChartAreas[_chartArea1Name].AxisY.Title = chartArea1AxisYTitle; |
darienf | 3:36de8b9e4b1a | 88 | _chart.ChartAreas[_chartArea2Name].AxisY.Title = chartArea2AxisYTitle; |
darienf | 3:36de8b9e4b1a | 89 | _chart.ChartAreas[_chartArea3Name].AxisY.Title = chartArea3AxisYTitle; |
darienf | 3:36de8b9e4b1a | 90 | |
darienf | 3:36de8b9e4b1a | 91 | //_chart.ChartAreas[_chartArea1Name].AxisX.LabelStyle.Enabled = !_plotXAxisNoLabels; |
darienf | 3:36de8b9e4b1a | 92 | //_chart.ChartAreas[_chartArea2Name].AxisX.LabelStyle.Enabled = !_plotXAxisNoLabels; |
darienf | 3:36de8b9e4b1a | 93 | //_chart.ChartAreas[_chartArea3Name].AxisX.LabelStyle.Enabled = !_plotXAxisNoLabels; |
darienf | 3:36de8b9e4b1a | 94 | |
darienf | 3:36de8b9e4b1a | 95 | _chart.ChartAreas[_chartArea1Name].Visible = true; // valid_Red; |
darienf | 3:36de8b9e4b1a | 96 | _chart.ChartAreas[_chartArea2Name].Visible = true; // valid_IR; |
darienf | 3:36de8b9e4b1a | 97 | _chart.ChartAreas[_chartArea3Name].Visible = true; // valid_Green; |
darienf | 3:36de8b9e4b1a | 98 | |
darienf | 3:36de8b9e4b1a | 99 | _chart.Series[_series1Name].MarkerSize = 1; // Charting.Series.MarkerSize=0 makes no points visible |
darienf | 3:36de8b9e4b1a | 100 | _chart.Series[_series1Name].BorderWidth = 1; // Charting.Series.BorderWidth is actually the line thickness |
darienf | 3:36de8b9e4b1a | 101 | _chart.Series[_series1Name].XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.UInt32; |
darienf | 3:36de8b9e4b1a | 102 | _chart.Series[_series1Name].YValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Int32; |
darienf | 3:36de8b9e4b1a | 103 | |
darienf | 3:36de8b9e4b1a | 104 | _chart.Series[_series2Name].MarkerSize = 1; // Charting.Series.MarkerSize=0 makes no points visible |
darienf | 3:36de8b9e4b1a | 105 | _chart.Series[_series2Name].BorderWidth = 1; // Charting.Series.BorderWidth is actually the line thickness |
darienf | 3:36de8b9e4b1a | 106 | _chart.Series[_series2Name].XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.UInt32; |
darienf | 3:36de8b9e4b1a | 107 | _chart.Series[_series2Name].YValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Int32; |
darienf | 3:36de8b9e4b1a | 108 | |
darienf | 3:36de8b9e4b1a | 109 | _chart.Series[_series3Name].MarkerSize = 1; // Charting.Series.MarkerSize=0 makes no points visible |
darienf | 3:36de8b9e4b1a | 110 | _chart.Series[_series3Name].BorderWidth = 1; // Charting.Series.BorderWidth is actually the line thickness |
darienf | 3:36de8b9e4b1a | 111 | _chart.Series[_series3Name].XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.UInt32; |
darienf | 3:36de8b9e4b1a | 112 | _chart.Series[_series3Name].YValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Int32; |
darienf | 3:36de8b9e4b1a | 113 | } |
darienf | 3:36de8b9e4b1a | 114 | |
darienf | 3:36de8b9e4b1a | 115 | /// <summary> |
darienf | 3:36de8b9e4b1a | 116 | /// Clear chart data, reset _xCount, reset _plotPointsToSkip |
darienf | 3:36de8b9e4b1a | 117 | /// </summary> |
darienf | 3:36de8b9e4b1a | 118 | public void Clear() |
darienf | 3:36de8b9e4b1a | 119 | { |
darienf | 3:36de8b9e4b1a | 120 | _chart.Series[_series1Name].Points.Clear(); |
darienf | 3:36de8b9e4b1a | 121 | _chart.Series[_series2Name].Points.Clear(); |
darienf | 3:36de8b9e4b1a | 122 | _chart.Series[_series3Name].Points.Clear(); |
darienf | 3:36de8b9e4b1a | 123 | // VERIFY: OS24EVK-75 replace _xCount with _xCount1, _xCount2, _xCount3 |
darienf | 3:36de8b9e4b1a | 124 | //_xCount = 0; |
darienf | 3:36de8b9e4b1a | 125 | _xCount1 = 0; |
darienf | 3:36de8b9e4b1a | 126 | _xCount2 = 0; |
darienf | 3:36de8b9e4b1a | 127 | _xCount3 = 0; |
darienf | 3:36de8b9e4b1a | 128 | _plotPointsToSkip = 0; |
darienf | 3:36de8b9e4b1a | 129 | // https://jira.maxim-ic.com/browse/OS24EVK-32 replace numPlotTime with menu item Options | Plot Time |
darienf | 3:36de8b9e4b1a | 130 | _plotPoints = (int)_plotWindowTime * _SampleRate_Hz / SampleAverage_n; |
darienf | 3:36de8b9e4b1a | 131 | if (_plotPoints > _maxPlotPoints) |
darienf | 3:36de8b9e4b1a | 132 | { |
darienf | 3:36de8b9e4b1a | 133 | _plotPointsToSkip = _plotPoints / _maxPlotPoints - 1; |
darienf | 3:36de8b9e4b1a | 134 | _plotPoints = _maxPlotPoints; |
darienf | 3:36de8b9e4b1a | 135 | } |
darienf | 3:36de8b9e4b1a | 136 | } |
darienf | 3:36de8b9e4b1a | 137 | |
darienf | 3:36de8b9e4b1a | 138 | /// <summary> |
darienf | 3:36de8b9e4b1a | 139 | /// Replacement for plotXAxisNoLabelsToolStripMenuItem.Checked |
darienf | 3:36de8b9e4b1a | 140 | /// </summary> |
darienf | 3:36de8b9e4b1a | 141 | public bool plotXAxisNoLabels { |
darienf | 3:36de8b9e4b1a | 142 | get { return _plotXAxisNoLabels; } |
darienf | 3:36de8b9e4b1a | 143 | set |
darienf | 3:36de8b9e4b1a | 144 | { |
darienf | 3:36de8b9e4b1a | 145 | _plotXAxisNoLabels = value; |
darienf | 3:36de8b9e4b1a | 146 | _chart.ChartAreas[_chartArea1Name].AxisX.LabelStyle.Enabled = !_plotXAxisNoLabels; |
darienf | 3:36de8b9e4b1a | 147 | _chart.ChartAreas[_chartArea2Name].AxisX.LabelStyle.Enabled = !_plotXAxisNoLabels; |
darienf | 3:36de8b9e4b1a | 148 | _chart.ChartAreas[_chartArea3Name].AxisX.LabelStyle.Enabled = !_plotXAxisNoLabels; |
darienf | 3:36de8b9e4b1a | 149 | } |
darienf | 3:36de8b9e4b1a | 150 | } |
darienf | 3:36de8b9e4b1a | 151 | private bool _plotXAxisNoLabels = true; // VERIFY: default plotXAxisNoLabelsToolStripMenuItem.Checked |
darienf | 3:36de8b9e4b1a | 152 | |
darienf | 3:36de8b9e4b1a | 153 | /// <summary> |
darienf | 3:36de8b9e4b1a | 154 | /// Replacement for plotXAxisTimeToolStripMenuItem.Checked |
darienf | 3:36de8b9e4b1a | 155 | /// </summary> |
darienf | 3:36de8b9e4b1a | 156 | public bool plotXAxisTime |
darienf | 3:36de8b9e4b1a | 157 | { |
darienf | 3:36de8b9e4b1a | 158 | get { return _plotXAxisTime; } |
darienf | 3:36de8b9e4b1a | 159 | set |
darienf | 3:36de8b9e4b1a | 160 | { |
darienf | 3:36de8b9e4b1a | 161 | _plotXAxisTime = value; |
darienf | 3:36de8b9e4b1a | 162 | } |
darienf | 3:36de8b9e4b1a | 163 | } |
darienf | 3:36de8b9e4b1a | 164 | private bool _plotXAxisTime = true; // VERIFY: default plotXAxisTimeToolStripMenuItem.Checked |
darienf | 3:36de8b9e4b1a | 165 | |
darienf | 3:36de8b9e4b1a | 166 | private int _SampleRate_Hz = 100; |
darienf | 3:36de8b9e4b1a | 167 | /// <summary> |
darienf | 3:36de8b9e4b1a | 168 | /// Sample rate. Replacement for int.Parse(cboSampleRate.Text) |
darienf | 3:36de8b9e4b1a | 169 | /// </summary> |
darienf | 3:36de8b9e4b1a | 170 | public int SampleRate_Hz |
darienf | 3:36de8b9e4b1a | 171 | { |
darienf | 3:36de8b9e4b1a | 172 | get { return _SampleRate_Hz; } |
darienf | 3:36de8b9e4b1a | 173 | set |
darienf | 3:36de8b9e4b1a | 174 | { |
darienf | 3:36de8b9e4b1a | 175 | _SampleRate_Hz = value; |
darienf | 3:36de8b9e4b1a | 176 | |
darienf | 3:36de8b9e4b1a | 177 | //_AutoScaleEveryNSamples = 4 * _SampleRate_Hz; // 4 seconds assuming sample rate int.Parse(cboSampleRate.Text) == 100 samples per second |
darienf | 3:36de8b9e4b1a | 178 | |
darienf | 3:36de8b9e4b1a | 179 | // VERIFY: OS24EVK-73 Sample Avg 2 breaks chart scrolling |
darienf | 3:36de8b9e4b1a | 180 | // update _plotPoints which depends on myMAX30101.SampleAverage_n |
darienf | 3:36de8b9e4b1a | 181 | _plotPoints = (int)_plotWindowTime * _SampleRate_Hz / SampleAverage_n; |
darienf | 3:36de8b9e4b1a | 182 | if (_plotPoints > _maxPlotPoints) |
darienf | 3:36de8b9e4b1a | 183 | { |
darienf | 3:36de8b9e4b1a | 184 | _plotPointsToSkip = _plotPoints / _maxPlotPoints - 1; |
darienf | 3:36de8b9e4b1a | 185 | _plotPoints = _maxPlotPoints; |
darienf | 3:36de8b9e4b1a | 186 | } |
darienf | 3:36de8b9e4b1a | 187 | } |
darienf | 3:36de8b9e4b1a | 188 | } |
darienf | 3:36de8b9e4b1a | 189 | |
darienf | 3:36de8b9e4b1a | 190 | private int _SampleAverage_n = 1; |
darienf | 3:36de8b9e4b1a | 191 | /// <summary> |
darienf | 3:36de8b9e4b1a | 192 | /// Replacement for myMAX30101.SampleAverage_n |
darienf | 3:36de8b9e4b1a | 193 | /// </summary> |
darienf | 3:36de8b9e4b1a | 194 | public int SampleAverage_n |
darienf | 3:36de8b9e4b1a | 195 | { |
darienf | 3:36de8b9e4b1a | 196 | get { return _SampleAverage_n; } |
darienf | 3:36de8b9e4b1a | 197 | set |
darienf | 3:36de8b9e4b1a | 198 | { |
darienf | 3:36de8b9e4b1a | 199 | _SampleAverage_n = value; |
darienf | 3:36de8b9e4b1a | 200 | // VERIFY: OS24EVK-73 Sample Avg 2 breaks chart scrolling |
darienf | 3:36de8b9e4b1a | 201 | // update _plotPoints which depends on myMAX30101.SampleAverage_n |
darienf | 3:36de8b9e4b1a | 202 | _plotPoints = (int)_plotWindowTime * _SampleRate_Hz / SampleAverage_n; |
darienf | 3:36de8b9e4b1a | 203 | if (_plotPoints > _maxPlotPoints) |
darienf | 3:36de8b9e4b1a | 204 | { |
darienf | 3:36de8b9e4b1a | 205 | _plotPointsToSkip = _plotPoints / _maxPlotPoints - 1; |
darienf | 3:36de8b9e4b1a | 206 | _plotPoints = _maxPlotPoints; |
darienf | 3:36de8b9e4b1a | 207 | } |
darienf | 3:36de8b9e4b1a | 208 | } |
darienf | 3:36de8b9e4b1a | 209 | } |
darienf | 3:36de8b9e4b1a | 210 | |
darienf | 3:36de8b9e4b1a | 211 | // VERIFY: IMPLEMENT OS24EVK-70 Maxim.MAX30101.MedicalChartHelper._xCount int instead of double? |
darienf | 3:36de8b9e4b1a | 212 | // VERIFY: OS24EVK-75 replace _xCount with _xCount1, _xCount2, _xCount3 |
darienf | 3:36de8b9e4b1a | 213 | //public double _xCount = 0; |
darienf | 3:36de8b9e4b1a | 214 | public int _xCount1 = 0; |
darienf | 3:36de8b9e4b1a | 215 | public int _xCount2 = 0; |
darienf | 3:36de8b9e4b1a | 216 | public int _xCount3 = 0; |
darienf | 3:36de8b9e4b1a | 217 | |
darienf | 3:36de8b9e4b1a | 218 | /// <summary> |
darienf | 3:36de8b9e4b1a | 219 | /// The actual number of points on the plot (<= _maxPlotPoints). The actual number of points may be less than _maxPlotPoints in order to maintain ~numPlotTime.Value of plotted data |
darienf | 3:36de8b9e4b1a | 220 | /// </summary> |
darienf | 3:36de8b9e4b1a | 221 | public int _plotPoints = 500; |
darienf | 3:36de8b9e4b1a | 222 | |
darienf | 3:36de8b9e4b1a | 223 | private int _plotWindowTime = 5; // plot window in seconds |
darienf | 3:36de8b9e4b1a | 224 | public int plotWindowTime |
darienf | 3:36de8b9e4b1a | 225 | { |
darienf | 3:36de8b9e4b1a | 226 | get |
darienf | 3:36de8b9e4b1a | 227 | { |
darienf | 3:36de8b9e4b1a | 228 | return _plotWindowTime; |
darienf | 3:36de8b9e4b1a | 229 | } |
darienf | 3:36de8b9e4b1a | 230 | set |
darienf | 3:36de8b9e4b1a | 231 | { |
darienf | 3:36de8b9e4b1a | 232 | _plotWindowTime = value; |
darienf | 3:36de8b9e4b1a | 233 | _plotPoints = (int)_plotWindowTime * _SampleRate_Hz / SampleAverage_n; |
darienf | 3:36de8b9e4b1a | 234 | if (_plotPoints > _maxPlotPoints) |
darienf | 3:36de8b9e4b1a | 235 | { |
darienf | 3:36de8b9e4b1a | 236 | _plotPointsToSkip = _plotPoints / _maxPlotPoints - 1; |
darienf | 3:36de8b9e4b1a | 237 | _plotPoints = _maxPlotPoints; |
darienf | 3:36de8b9e4b1a | 238 | } |
darienf | 3:36de8b9e4b1a | 239 | } |
darienf | 3:36de8b9e4b1a | 240 | } |
darienf | 3:36de8b9e4b1a | 241 | |
darienf | 3:36de8b9e4b1a | 242 | private int _maxPlotPoints = 2000; // maximum allowed number of points that can be plotted per series. Higher Fs will have more than 500 pts for a given numPlotTime.Value, so the number of samples per point will need to be increased accordingly to give maximum _maxPlotPoints |
darienf | 3:36de8b9e4b1a | 243 | |
darienf | 3:36de8b9e4b1a | 244 | public int _plotPointsToSkip = 0; |
darienf | 3:36de8b9e4b1a | 245 | |
darienf | 3:36de8b9e4b1a | 246 | // https://jira.maxim-ic.com/browse/OS24EVK-34 Autoscale tuning parameters |
darienf | 3:36de8b9e4b1a | 247 | // https://jira.maxim-ic.com/browse/OS24EVK-34 Change _AutoScaleTimeInterval to _AutoScaleEveryNSamples and use sampleNumber to measure time |
darienf | 3:36de8b9e4b1a | 248 | // https://jira.maxim-ic.com/browse/OS24EVK-42 Autoscale tuning (Larry 2014-11-24) _AutoScaleEveryNSamples |
darienf | 3:36de8b9e4b1a | 249 | // - Slow the Autoscale update rate every 4 seconds |
darienf | 3:36de8b9e4b1a | 250 | //private int _AutoScaleEveryNSamples = 400; // 4 seconds assuming sample rate int.Parse(cboSampleRate.Text) == 100 samples per second |
darienf | 3:36de8b9e4b1a | 251 | |
darienf | 3:36de8b9e4b1a | 252 | // private double _AutoScaleMarginXLeft; // ignore old data at left of graph |
darienf | 3:36de8b9e4b1a | 253 | // private double _AutoScaleMarginXRight; // ignore new data at right of graph? probably 0 by default |
darienf | 3:36de8b9e4b1a | 254 | |
darienf | 3:36de8b9e4b1a | 255 | /// <summary> |
darienf | 3:36de8b9e4b1a | 256 | /// chartMax empty area above dataMax |
darienf | 3:36de8b9e4b1a | 257 | /// </summary> |
darienf | 3:36de8b9e4b1a | 258 | private static double _AutoScaleMarginYTop = 0.125; |
darienf | 3:36de8b9e4b1a | 259 | |
darienf | 3:36de8b9e4b1a | 260 | /// <summary> |
darienf | 3:36de8b9e4b1a | 261 | /// chartMin empty area below dataMin |
darienf | 3:36de8b9e4b1a | 262 | /// </summary> |
darienf | 3:36de8b9e4b1a | 263 | private static double _AutoScaleMarginYBottom = 0.125; |
darienf | 3:36de8b9e4b1a | 264 | |
darienf | 3:36de8b9e4b1a | 265 | /// <summary> |
darienf | 3:36de8b9e4b1a | 266 | /// Minimum Y span: allow up to 10 counts per division (i.e. 50 LSBs) |
darienf | 3:36de8b9e4b1a | 267 | /// |
darienf | 3:36de8b9e4b1a | 268 | /// (5 * _AutoScaleYmultiples) minimum allowed span of chartMax-chartMin, |
darienf | 3:36de8b9e4b1a | 269 | /// to avoid focusing on LSB noise |
darienf | 3:36de8b9e4b1a | 270 | /// </summary> |
darienf | 3:36de8b9e4b1a | 271 | private static double _AutoScaleMinSpanY = 500; |
darienf | 3:36de8b9e4b1a | 272 | |
darienf | 3:36de8b9e4b1a | 273 | /// <summary> |
darienf | 3:36de8b9e4b1a | 274 | /// Y axis: No decimals. Round to nearest multiple of 100. |
darienf | 3:36de8b9e4b1a | 275 | /// </summary> |
darienf | 3:36de8b9e4b1a | 276 | private static double _AutoScaleYmultiples = 100; |
darienf | 3:36de8b9e4b1a | 277 | |
darienf | 3:36de8b9e4b1a | 278 | // Calculated initial default chart limits _AutoscaleInitialChartMaxY .. _AutoscaleInitialChartMinY |
darienf | 3:36de8b9e4b1a | 279 | int _AutoscaleInitialChartMaxY = |
darienf | 3:36de8b9e4b1a | 280 | ( |
darienf | 3:36de8b9e4b1a | 281 | (int) |
darienf | 3:36de8b9e4b1a | 282 | ((_AutoScaleMinSpanY * (1.0 + _AutoScaleMarginYTop + _AutoScaleMarginYBottom)) / _AutoScaleYmultiples) |
darienf | 3:36de8b9e4b1a | 283 | ) |
darienf | 3:36de8b9e4b1a | 284 | * (int)(_AutoScaleYmultiples); |
darienf | 3:36de8b9e4b1a | 285 | int _AutoscaleInitialChartMinY = 0; |
darienf | 3:36de8b9e4b1a | 286 | |
darienf | 3:36de8b9e4b1a | 287 | /// <summary> |
darienf | 3:36de8b9e4b1a | 288 | /// Append data to chart area 1 series 1 (Optical: Red. Accelerometer: X) |
darienf | 3:36de8b9e4b1a | 289 | /// |
darienf | 3:36de8b9e4b1a | 290 | /// @post _xCount1 is updated |
darienf | 3:36de8b9e4b1a | 291 | /// </summary> |
darienf | 3:36de8b9e4b1a | 292 | /// <param name="rawIntArrayYData"></param> |
darienf | 3:36de8b9e4b1a | 293 | /// <param name="firstNewXIndex"></param> |
darienf | 3:36de8b9e4b1a | 294 | /// <param name="lastXIndex"></param> |
darienf | 3:36de8b9e4b1a | 295 | public void AppendDataChartArea1(int[] rawIntArrayYData, int firstNewXIndex, int lastXIndex) |
darienf | 3:36de8b9e4b1a | 296 | { |
darienf | 3:36de8b9e4b1a | 297 | // AppendDataChartArea(_chartArea1Name, _series1Name, rawIntArrayYData, firstNewXIndex, lastXIndex); |
darienf | 3:36de8b9e4b1a | 298 | string chartAreaName = _chartArea1Name; |
darienf | 3:36de8b9e4b1a | 299 | string seriesName = _series1Name; |
darienf | 3:36de8b9e4b1a | 300 | |
darienf | 3:36de8b9e4b1a | 301 | for (int index = firstNewXIndex; index <= lastXIndex; index++) |
darienf | 3:36de8b9e4b1a | 302 | { |
darienf | 3:36de8b9e4b1a | 303 | int yData = rawIntArrayYData[index]; |
darienf | 3:36de8b9e4b1a | 304 | // VERIFY: OS24EVK-75 replace AutoScaleEvaluate dataFormatIs16bit2sComplement with if (DataFormat == DataFormats.Format16bit2sComplement) |
darienf | 3:36de8b9e4b1a | 305 | if (DataFormat == DataFormats.Format16bit2sComplement) |
darienf | 3:36de8b9e4b1a | 306 | { |
darienf | 3:36de8b9e4b1a | 307 | // VERIFY: OS24EVK-57 interpret rawX rawY rawZ as 16-bit 2's complement |
darienf | 3:36de8b9e4b1a | 308 | if (yData > 0x8000) |
darienf | 3:36de8b9e4b1a | 309 | { |
darienf | 3:36de8b9e4b1a | 310 | yData = yData - 0x10000; |
darienf | 3:36de8b9e4b1a | 311 | } |
darienf | 3:36de8b9e4b1a | 312 | } |
darienf | 3:36de8b9e4b1a | 313 | int count = _chart.Series[seriesName].Points.Count; |
darienf | 3:36de8b9e4b1a | 314 | // VERIFY: OS24EVK-75 replace _xCount with _xCount1, _xCount2, _xCount3 |
darienf | 3:36de8b9e4b1a | 315 | double xCoord = _xCount1 * (_plotPointsToSkip + 1) * SampleAverage_n / (plotXAxisTime ? SampleRate_Hz : 1); |
darienf | 3:36de8b9e4b1a | 316 | |
darienf | 3:36de8b9e4b1a | 317 | //_chart.Series[seriesName].Points.AddXY(xCoord, yData); |
darienf | 3:36de8b9e4b1a | 318 | _chart.Series[seriesName].Points.AddY(yData); |
darienf | 3:36de8b9e4b1a | 319 | _chart.ResetAutoValues(); |
darienf | 3:36de8b9e4b1a | 320 | |
darienf | 3:36de8b9e4b1a | 321 | while (count > _plotPoints) |
darienf | 3:36de8b9e4b1a | 322 | { |
darienf | 3:36de8b9e4b1a | 323 | _chart.Series[seriesName].Points.RemoveAt(0); |
darienf | 3:36de8b9e4b1a | 324 | count = _chart.Series[seriesName].Points.Count; |
darienf | 3:36de8b9e4b1a | 325 | } |
darienf | 3:36de8b9e4b1a | 326 | // VERIFY: OS24EVK-75 replace _xCount with _xCount1, _xCount2, _xCount3 |
darienf | 3:36de8b9e4b1a | 327 | _xCount1++; |
darienf | 3:36de8b9e4b1a | 328 | } |
darienf | 3:36de8b9e4b1a | 329 | //AutoScaleEvaluate(e.rawRedData, e.sampleNumberOffset, numSamples - 1, _chart, chartAreaName); |
darienf | 3:36de8b9e4b1a | 330 | } |
darienf | 3:36de8b9e4b1a | 331 | |
darienf | 3:36de8b9e4b1a | 332 | /// <summary> |
darienf | 3:36de8b9e4b1a | 333 | /// Append data to chart area 2 series 2 (Optical: IR. Accelerometer: Y) |
darienf | 3:36de8b9e4b1a | 334 | /// |
darienf | 3:36de8b9e4b1a | 335 | /// @post _xCount2 is updated |
darienf | 3:36de8b9e4b1a | 336 | /// </summary> |
darienf | 3:36de8b9e4b1a | 337 | /// <param name="rawIntArrayYData"></param> |
darienf | 3:36de8b9e4b1a | 338 | /// <param name="firstNewXIndex"></param> |
darienf | 3:36de8b9e4b1a | 339 | /// <param name="lastXIndex"></param> |
darienf | 3:36de8b9e4b1a | 340 | public void AppendDataChartArea2(int[] rawIntArrayYData, int firstNewXIndex, int lastXIndex) |
darienf | 3:36de8b9e4b1a | 341 | { |
darienf | 3:36de8b9e4b1a | 342 | // AppendDataChartArea(_chartArea2Name, _series2Name, rawIntArrayYData, firstNewXIndex, lastXIndex); |
darienf | 3:36de8b9e4b1a | 343 | string chartAreaName = _chartArea2Name; |
darienf | 3:36de8b9e4b1a | 344 | string seriesName = _series2Name; |
darienf | 3:36de8b9e4b1a | 345 | |
darienf | 3:36de8b9e4b1a | 346 | for (int index = firstNewXIndex; index <= lastXIndex; index++) |
darienf | 3:36de8b9e4b1a | 347 | { |
darienf | 3:36de8b9e4b1a | 348 | int yData = rawIntArrayYData[index]; |
darienf | 3:36de8b9e4b1a | 349 | // VERIFY: OS24EVK-75 replace AutoScaleEvaluate dataFormatIs16bit2sComplement with if (DataFormat == DataFormats.Format16bit2sComplement) |
darienf | 3:36de8b9e4b1a | 350 | if (DataFormat == DataFormats.Format16bit2sComplement) |
darienf | 3:36de8b9e4b1a | 351 | { |
darienf | 3:36de8b9e4b1a | 352 | // VERIFY: OS24EVK-57 interpret rawX rawY rawZ as 16-bit 2's complement |
darienf | 3:36de8b9e4b1a | 353 | if (yData > 0x8000) |
darienf | 3:36de8b9e4b1a | 354 | { |
darienf | 3:36de8b9e4b1a | 355 | yData = yData - 0x10000; |
darienf | 3:36de8b9e4b1a | 356 | } |
darienf | 3:36de8b9e4b1a | 357 | } |
darienf | 3:36de8b9e4b1a | 358 | int count = _chart.Series[seriesName].Points.Count; |
darienf | 3:36de8b9e4b1a | 359 | // VERIFY: OS24EVK-75 replace _xCount with _xCount1, _xCount2, _xCount3 |
darienf | 3:36de8b9e4b1a | 360 | double xCoord = _xCount2 * (_plotPointsToSkip + 1) * SampleAverage_n / (plotXAxisTime ? SampleRate_Hz : 1); |
darienf | 3:36de8b9e4b1a | 361 | |
darienf | 3:36de8b9e4b1a | 362 | _chart.Series[seriesName].Points.AddXY(xCoord, yData); |
darienf | 3:36de8b9e4b1a | 363 | _chart.ResetAutoValues(); |
darienf | 3:36de8b9e4b1a | 364 | |
darienf | 3:36de8b9e4b1a | 365 | while (count > _plotPoints) |
darienf | 3:36de8b9e4b1a | 366 | { |
darienf | 3:36de8b9e4b1a | 367 | _chart.Series[seriesName].Points.RemoveAt(0); |
darienf | 3:36de8b9e4b1a | 368 | count = _chart.Series[seriesName].Points.Count; |
darienf | 3:36de8b9e4b1a | 369 | } |
darienf | 3:36de8b9e4b1a | 370 | // VERIFY: OS24EVK-75 replace _xCount with _xCount1, _xCount2, _xCount3 |
darienf | 3:36de8b9e4b1a | 371 | _xCount2++; |
darienf | 3:36de8b9e4b1a | 372 | } |
darienf | 3:36de8b9e4b1a | 373 | //AutoScaleEvaluate(e.rawRedData, e.sampleNumberOffset, numSamples - 1, _chart, chartAreaName); |
darienf | 3:36de8b9e4b1a | 374 | } |
darienf | 3:36de8b9e4b1a | 375 | |
darienf | 3:36de8b9e4b1a | 376 | /// <summary> |
darienf | 3:36de8b9e4b1a | 377 | /// Append data to chart area 3 series 3 (Optical: Green. Accelerometer: Z) |
darienf | 3:36de8b9e4b1a | 378 | /// |
darienf | 3:36de8b9e4b1a | 379 | /// @post _xCount3 is updated |
darienf | 3:36de8b9e4b1a | 380 | /// </summary> |
darienf | 3:36de8b9e4b1a | 381 | /// <param name="rawIntArrayYData"></param> |
darienf | 3:36de8b9e4b1a | 382 | /// <param name="firstNewXIndex"></param> |
darienf | 3:36de8b9e4b1a | 383 | /// <param name="lastXIndex"></param> |
darienf | 3:36de8b9e4b1a | 384 | public void AppendDataChartArea3(int[] rawIntArrayYData, int firstNewXIndex, int lastXIndex) |
darienf | 3:36de8b9e4b1a | 385 | { |
darienf | 3:36de8b9e4b1a | 386 | // AppendDataChartArea(_chartArea3Name, _series3Name, rawIntArrayYData, firstNewXIndex, lastXIndex); |
darienf | 3:36de8b9e4b1a | 387 | string chartAreaName = _chartArea3Name; |
darienf | 3:36de8b9e4b1a | 388 | string seriesName = _series3Name; |
darienf | 3:36de8b9e4b1a | 389 | |
darienf | 3:36de8b9e4b1a | 390 | for (int index = firstNewXIndex; index <= lastXIndex; index++) |
darienf | 3:36de8b9e4b1a | 391 | { |
darienf | 3:36de8b9e4b1a | 392 | int yData = rawIntArrayYData[index]; |
darienf | 3:36de8b9e4b1a | 393 | // VERIFY: OS24EVK-75 replace AutoScaleEvaluate dataFormatIs16bit2sComplement with if (DataFormat == DataFormats.Format16bit2sComplement) |
darienf | 3:36de8b9e4b1a | 394 | if (DataFormat == DataFormats.Format16bit2sComplement) |
darienf | 3:36de8b9e4b1a | 395 | { |
darienf | 3:36de8b9e4b1a | 396 | // VERIFY: OS24EVK-57 interpret rawX rawY rawZ as 16-bit 2's complement |
darienf | 3:36de8b9e4b1a | 397 | if (yData > 0x8000) |
darienf | 3:36de8b9e4b1a | 398 | { |
darienf | 3:36de8b9e4b1a | 399 | yData = yData - 0x10000; |
darienf | 3:36de8b9e4b1a | 400 | } |
darienf | 3:36de8b9e4b1a | 401 | } |
darienf | 3:36de8b9e4b1a | 402 | int count = _chart.Series[seriesName].Points.Count; |
darienf | 3:36de8b9e4b1a | 403 | // VERIFY: OS24EVK-75 replace _xCount with _xCount1, _xCount2, _xCount3 |
darienf | 3:36de8b9e4b1a | 404 | double xCoord = _xCount3 * (_plotPointsToSkip + 1) * SampleAverage_n / (plotXAxisTime ? SampleRate_Hz : 1); |
darienf | 3:36de8b9e4b1a | 405 | |
darienf | 3:36de8b9e4b1a | 406 | _chart.Series[seriesName].Points.AddXY(xCoord, yData); |
darienf | 3:36de8b9e4b1a | 407 | _chart.ResetAutoValues(); |
darienf | 3:36de8b9e4b1a | 408 | |
darienf | 3:36de8b9e4b1a | 409 | while (count > _plotPoints) |
darienf | 3:36de8b9e4b1a | 410 | { |
darienf | 3:36de8b9e4b1a | 411 | _chart.Series[seriesName].Points.RemoveAt(0); |
darienf | 3:36de8b9e4b1a | 412 | count = _chart.Series[seriesName].Points.Count; |
darienf | 3:36de8b9e4b1a | 413 | } |
darienf | 3:36de8b9e4b1a | 414 | // VERIFY: OS24EVK-75 replace _xCount with _xCount1, _xCount2, _xCount3 |
darienf | 3:36de8b9e4b1a | 415 | _xCount3++; |
darienf | 3:36de8b9e4b1a | 416 | } |
darienf | 3:36de8b9e4b1a | 417 | //AutoScaleEvaluate(e.rawRedData, e.sampleNumberOffset, numSamples - 1, _chart, chartAreaName); |
darienf | 3:36de8b9e4b1a | 418 | } |
darienf | 3:36de8b9e4b1a | 419 | |
darienf | 3:36de8b9e4b1a | 420 | #if PROFILER |
darienf | 3:36de8b9e4b1a | 421 | //// TODO1: OS24EVK-54 profiling: capture max interval, number of intervals, cumulative interval |
darienf | 3:36de8b9e4b1a | 422 | System.Diagnostics.Stopwatch _profilingStopwatchAutoScaleEvaluate = new System.Diagnostics.Stopwatch(); // cumulative timing |
darienf | 3:36de8b9e4b1a | 423 | int _profilingStopwatchAutoScaleEvaluate_NumIntervals; |
darienf | 3:36de8b9e4b1a | 424 | #endif // PROFILER |
darienf | 3:36de8b9e4b1a | 425 | |
darienf | 3:36de8b9e4b1a | 426 | public void AutoScaleEvaluate1(int[] rawIntArrayYData, int firstNewXIndex, int lastXIndex) |
darienf | 3:36de8b9e4b1a | 427 | { |
darienf | 3:36de8b9e4b1a | 428 | AutoScaleEvaluate(rawIntArrayYData, firstNewXIndex, lastXIndex, _chartArea1Name); |
darienf | 3:36de8b9e4b1a | 429 | } |
darienf | 3:36de8b9e4b1a | 430 | |
darienf | 3:36de8b9e4b1a | 431 | public void AutoScaleEvaluate2(int[] rawIntArrayYData, int firstNewXIndex, int lastXIndex) |
darienf | 3:36de8b9e4b1a | 432 | { |
darienf | 3:36de8b9e4b1a | 433 | AutoScaleEvaluate(rawIntArrayYData, firstNewXIndex, lastXIndex, _chartArea2Name); |
darienf | 3:36de8b9e4b1a | 434 | } |
darienf | 3:36de8b9e4b1a | 435 | |
darienf | 3:36de8b9e4b1a | 436 | public void AutoScaleEvaluate3(int[] rawIntArrayYData, int firstNewXIndex, int lastXIndex) |
darienf | 3:36de8b9e4b1a | 437 | { |
darienf | 3:36de8b9e4b1a | 438 | AutoScaleEvaluate(rawIntArrayYData, firstNewXIndex, lastXIndex, _chartArea3Name); |
darienf | 3:36de8b9e4b1a | 439 | } |
darienf | 3:36de8b9e4b1a | 440 | |
darienf | 3:36de8b9e4b1a | 441 | // TODO1: OS24EVK-57 OS24EVK-54 AutoScaleEvaluate(int[] rawIntArrayYData,...) Calculate autoscale min/max/SampleVariance from the raw integer data. This should be much faster as it doesn't involve arbitrarily converting into floating-point numbers or excessive indexing. |
darienf | 3:36de8b9e4b1a | 442 | public void AutoScaleEvaluate(int[] rawIntArrayYData, |
darienf | 3:36de8b9e4b1a | 443 | int firstNewXIndex, |
darienf | 3:36de8b9e4b1a | 444 | int lastXIndex, |
darienf | 3:36de8b9e4b1a | 445 | /*Chart chart,*/ string chartAreaName |
darienf | 3:36de8b9e4b1a | 446 | // TODO1: OS24EVK-75 replace AutoScaleEvaluate dataFormatIs16bit2sComplement with if (DataFormat == DataFormats.Format16bit2sComplement) |
darienf | 3:36de8b9e4b1a | 447 | //bool dataFormatIs16bit2sComplement = false |
darienf | 3:36de8b9e4b1a | 448 | //string seriesName, |
darienf | 3:36de8b9e4b1a | 449 | //int sampleNumber, |
darienf | 3:36de8b9e4b1a | 450 | //ref int sampleNumberPreviousAutoscale |
darienf | 3:36de8b9e4b1a | 451 | ) |
darienf | 3:36de8b9e4b1a | 452 | { |
darienf | 3:36de8b9e4b1a | 453 | #if PROFILER |
darienf | 3:36de8b9e4b1a | 454 | // TODO1: OS24EVK-54 profiling: capture max interval, number of intervals, cumulative interval |
darienf | 3:36de8b9e4b1a | 455 | _profilingStopwatchAutoScaleEvaluate.Start(); |
darienf | 3:36de8b9e4b1a | 456 | _profilingStopwatchAutoScaleEvaluate_NumIntervals = _profilingStopwatchAutoScaleEvaluate_NumIntervals + 1; |
darienf | 3:36de8b9e4b1a | 457 | #endif // PROFILER |
darienf | 3:36de8b9e4b1a | 458 | |
darienf | 3:36de8b9e4b1a | 459 | // TODO1: OS24EVK-57 OS24EVK-54 Calculate autoscale min/max/SampleVariance from the raw integer data. This should be much faster as it doesn't involve arbitrarily converting into floating-point numbers or excessive indexing. |
darienf | 3:36de8b9e4b1a | 460 | |
darienf | 3:36de8b9e4b1a | 461 | // https://jira.maxim-ic.com/browse/OS24EVK-34 AutoScaleEvaluate() use _AutoScaleMarginXLeft; // ignore old data at left of graph |
darienf | 3:36de8b9e4b1a | 462 | // https://jira.maxim-ic.com/browse/OS24EVK-34 AutoScaleEvaluate() use _AutoScaleMarginXRight; // ignore new data at right of graph? probably 0 by default |
darienf | 3:36de8b9e4b1a | 463 | //const int firstPointIndex = 0; |
darienf | 3:36de8b9e4b1a | 464 | // advance the left and right X limits |
darienf | 3:36de8b9e4b1a | 465 | // https://jira.maxim-ic.com/browse/OS24EVK-48 Graph X axis - Replace hidden chkPlotTime with a menu option plotXAxisTimeToolStripMenuItem.Checked |
darienf | 3:36de8b9e4b1a | 466 | // https://jira.maxim-ic.com/browse/OS24EVK-47 Graph scrolling needs to be smooth progression like a paper tape chart even when (plotXAxisTimeToolStripMenuItem.Checked is true) |
darienf | 3:36de8b9e4b1a | 467 | // per Larry Skrenes 2014-11-24: graph scrolling needs to be smooth progression like a paper tape chart. |
darienf | 3:36de8b9e4b1a | 468 | // When (plotXAxisTimeToolStripMenuItem.Checked is false) graph scrolling is already smooth. |
darienf | 3:36de8b9e4b1a | 469 | // When (plotXAxisTimeToolStripMenuItem.Checked is true) graph scrolling moves in staccato 1-second steps. Larry hates this. |
darienf | 3:36de8b9e4b1a | 470 | int xWidth = _plotPoints * (_plotPointsToSkip + 1) * SampleAverage_n / (plotXAxisTime ? SampleRate_Hz : 1); |
darienf | 3:36de8b9e4b1a | 471 | // VERIFY: OS24EVK-73 Sample Avg 2 breaks chart scrolling -- xLastXIndex = lastXIndex * myMAX30101.SampleAverage_n |
darienf | 3:36de8b9e4b1a | 472 | int xLastXIndex = lastXIndex * SampleAverage_n / (plotXAxisTime ? SampleRate_Hz : 1); |
darienf | 3:36de8b9e4b1a | 473 | //int xWidth = _plotPoints * (_plotPointsToSkip + 1) * _cboSampleAvg / (false ? int.Parse(cboSampleRate.Text) : 1); |
darienf | 3:36de8b9e4b1a | 474 | //int xWidth = _plotPoints * (_plotPointsToSkip + 1) * _cboSampleAvg / (1); |
darienf | 3:36de8b9e4b1a | 475 | //int xWidth = _plotPoints * (_plotPointsToSkip + 1) * _cboSampleAvg; |
darienf | 3:36de8b9e4b1a | 476 | // https://jira.maxim-ic.com/browse/OS24EVK-15 Fix plot X axis jumping around (_plotWindowTime) |
darienf | 3:36de8b9e4b1a | 477 | // 0.0 --> 0 1 2 3 4 5 |
darienf | 3:36de8b9e4b1a | 478 | // 0.0 --> 0_ 1 2 3 4 5 |
darienf | 3:36de8b9e4b1a | 479 | // 0.0 --> 0__1 2 3 4 5 |
darienf | 3:36de8b9e4b1a | 480 | // 0.0 --> 0__1_ 2 3 4 5 |
darienf | 3:36de8b9e4b1a | 481 | // 0.0 --> 0__1__2 3 4 5 |
darienf | 3:36de8b9e4b1a | 482 | // 0.0 --> 0__1__2_ 3 4 5 |
darienf | 3:36de8b9e4b1a | 483 | // 0.0 --> 0__1__2__3 4 5 |
darienf | 3:36de8b9e4b1a | 484 | // 0.0 --> 0__1__2__3_ 4 5 |
darienf | 3:36de8b9e4b1a | 485 | // 0.0 --> 0__1__2__3__4 5 |
darienf | 3:36de8b9e4b1a | 486 | // 0.0 --> 0__1__2__3__4_ 5 |
darienf | 3:36de8b9e4b1a | 487 | // 0.0 --> 0__1__2__3__4__5 |
darienf | 3:36de8b9e4b1a | 488 | // 0.5 --> 1__2__3__4__5_ 6 |
darienf | 3:36de8b9e4b1a | 489 | // 1.0 --> 1__2__3__4__5__6 |
darienf | 3:36de8b9e4b1a | 490 | // 1.5 --> 2__3__4__5__6_ 7 |
darienf | 3:36de8b9e4b1a | 491 | // 2.0 --> 2__3__4__5__6__7 |
darienf | 3:36de8b9e4b1a | 492 | // https://jira.maxim-ic.com/browse/OS24EVK-47 Graph scrolling needs to be smooth progression like a paper tape chart even when (plotXAxisTimeToolStripMenuItem.Checked is true) |
darienf | 3:36de8b9e4b1a | 493 | // per Larry Skrenes 2014-11-24: graph scrolling needs to be smooth progression like a paper tape chart. |
darienf | 3:36de8b9e4b1a | 494 | // When (plotXAxisTimeToolStripMenuItem.Checked is false) graph scrolling is already smooth. |
darienf | 3:36de8b9e4b1a | 495 | // When (plotXAxisTimeToolStripMenuItem.Checked is true) graph scrolling moves in staccato 1-second steps. Larry hates this. |
darienf | 3:36de8b9e4b1a | 496 | // VERIFY: OS24EVK-76 Autoscale delay time is affected by Sample Average - firstVisiblePointIndex |
darienf | 3:36de8b9e4b1a | 497 | //int firstVisiblePointIndex = lastXIndex - (_plotPoints * (_plotPointsToSkip + 1) * SampleAverage_n); |
darienf | 3:36de8b9e4b1a | 498 | int firstVisiblePointIndex = lastXIndex - (_plotPoints * (_plotPointsToSkip + 1)); |
darienf | 3:36de8b9e4b1a | 499 | if (firstVisiblePointIndex < 0) { firstVisiblePointIndex = 0; } |
darienf | 3:36de8b9e4b1a | 500 | // |
darienf | 3:36de8b9e4b1a | 501 | // VERIFY: OS24EVK-73 Sample Avg 2 breaks chart scrolling -- xLastXIndex instead of lastXIndex |
darienf | 3:36de8b9e4b1a | 502 | int firstVisiblePointX = xLastXIndex - xWidth; // (int)chart.Series[0].Points[firstPointIndex].XValue; |
darienf | 3:36de8b9e4b1a | 503 | if (firstVisiblePointX < 0) { firstVisiblePointX = 0; } |
darienf | 3:36de8b9e4b1a | 504 | //int firstPointX = (int)System.Math.Ceiling(chart.Series[seriesName].Points[firstPointIndex].XValue); |
darienf | 3:36de8b9e4b1a | 505 | //if ((chart.Series[seriesName].Points[firstPointIndex].XValue) < 0.1) |
darienf | 3:36de8b9e4b1a | 506 | //{ |
darienf | 3:36de8b9e4b1a | 507 | // firstPointX = (int)System.Math.Floor(chart.Series[seriesName].Points[firstPointIndex].XValue); |
darienf | 3:36de8b9e4b1a | 508 | //} |
darienf | 3:36de8b9e4b1a | 509 | _chart.ChartAreas[chartAreaName].AxisX.Minimum = firstVisiblePointX; |
darienf | 3:36de8b9e4b1a | 510 | // https://jira.maxim-ic.com/browse/OS24EVK-47 Graph scrolling needs to be smooth progression like a paper tape chart even when (plotXAxisTimeToolStripMenuItem.Checked is true) |
darienf | 3:36de8b9e4b1a | 511 | //chart.ChartAreas[0].AxisX.Maximum = (int)System.Math.Ceiling((double)firstPointX + xWidth); |
darienf | 3:36de8b9e4b1a | 512 | _chart.ChartAreas[chartAreaName].AxisX.Maximum = firstVisiblePointX + xWidth; |
darienf | 3:36de8b9e4b1a | 513 | |
darienf | 3:36de8b9e4b1a | 514 | if (lastXIndex /* chart.Series[seriesName].Points.Count */ < 1) |
darienf | 3:36de8b9e4b1a | 515 | { |
darienf | 3:36de8b9e4b1a | 516 | //int iMaxY_chart_default = (_AutoScaleMinSpanY * (1.0 + _AutoScaleMarginYTop + _AutoScaleMarginYBottom)) / _AutoScaleYmultiples; |
darienf | 3:36de8b9e4b1a | 517 | //int _AutoscaleInitialChartMaxY = iMaxY_chart_default * _AutoScaleYmultiples; |
darienf | 3:36de8b9e4b1a | 518 | //int _AutoscaleInitialChartMaxY = |
darienf | 3:36de8b9e4b1a | 519 | // ( |
darienf | 3:36de8b9e4b1a | 520 | // (int) |
darienf | 3:36de8b9e4b1a | 521 | // ((_AutoScaleMinSpanY * (1.0 + _AutoScaleMarginYTop + _AutoScaleMarginYBottom)) / _AutoScaleYmultiples) |
darienf | 3:36de8b9e4b1a | 522 | // ) |
darienf | 3:36de8b9e4b1a | 523 | // * (int)(_AutoScaleYmultiples); |
darienf | 3:36de8b9e4b1a | 524 | //int _AutoscaleInitialChartMinY = 0; |
darienf | 3:36de8b9e4b1a | 525 | _chart.ChartAreas[chartAreaName].AxisY.Maximum = _AutoscaleInitialChartMaxY; |
darienf | 3:36de8b9e4b1a | 526 | _chart.ChartAreas[chartAreaName].AxisY.Minimum = _AutoscaleInitialChartMinY; |
darienf | 3:36de8b9e4b1a | 527 | #if PROFILER |
darienf | 3:36de8b9e4b1a | 528 | // TODO1: OS24EVK-54 profiling: capture max interval, number of intervals, cumulative interval |
darienf | 3:36de8b9e4b1a | 529 | _profilingStopwatchAutoScaleEvaluate.Stop(); |
darienf | 3:36de8b9e4b1a | 530 | #endif // PROFILER |
darienf | 3:36de8b9e4b1a | 531 | return; |
darienf | 3:36de8b9e4b1a | 532 | } |
darienf | 3:36de8b9e4b1a | 533 | |
darienf | 3:36de8b9e4b1a | 534 | // // TODO1: OS24EVK-57 OS24EVK-54 scan new data rawIntArrayYData[firstNewIndex .. lastIndex]. As is this code only triggers if the last point is extreme. |
darienf | 3:36de8b9e4b1a | 535 | // int newestPointIndex = lastXIndex; // chart.Series[seriesName].Points.Count - 1; |
darienf | 3:36de8b9e4b1a | 536 | // int newestPointY = rawIntArrayYData[lastXIndex]; // (int)chart.Series[seriesName].Points[newestPointIndex].YValues[0]; |
darienf | 3:36de8b9e4b1a | 537 | // if ((newestPointY < chart.ChartAreas[chartAreaName].AxisY.Maximum) |
darienf | 3:36de8b9e4b1a | 538 | // && (newestPointY > chart.ChartAreas[chartAreaName].AxisY.Minimum) |
darienf | 3:36de8b9e4b1a | 539 | // ) |
darienf | 3:36de8b9e4b1a | 540 | // { |
darienf | 3:36de8b9e4b1a | 541 | // // https://jira.maxim-ic.com/browse/OS24EVK-34 always re-evaluate chart when new data exceeds Minimum or Maximum |
darienf | 3:36de8b9e4b1a | 542 | // // But if we just return at this point, then autoscale will never contract to fit smaller data series. |
darienf | 3:36de8b9e4b1a | 543 | // // |
darienf | 3:36de8b9e4b1a | 544 | // // https://jira.maxim-ic.com/browse/OS24EVK-34 Change _AutoScaleTimeInterval to _AutoScaleEveryNSamples and use sampleNumber to measure time |
darienf | 3:36de8b9e4b1a | 545 | // // https://jira.maxim-ic.com/browse/OS24EVK-34 AutoScaleEvaluate() after every _AutoScaleEveryNSamples, re-scan data and fit chart to data |
darienf | 3:36de8b9e4b1a | 546 | // // if ( interval has been less than _AutoScaleEveryNSamples ) { return; } |
darienf | 3:36de8b9e4b1a | 547 | // if ((sampleNumber - sampleNumberPreviousAutoscale) < _AutoScaleEveryNSamples) |
darienf | 3:36de8b9e4b1a | 548 | // { |
darienf | 3:36de8b9e4b1a | 549 | //#if PROFILER |
darienf | 3:36de8b9e4b1a | 550 | // // TODO1: OS24EVK-54 profiling: capture max interval, number of intervals, cumulative interval |
darienf | 3:36de8b9e4b1a | 551 | // _profilingStopwatchAutoScaleEvaluate.Stop(); |
darienf | 3:36de8b9e4b1a | 552 | //#endif // PROFILER |
darienf | 3:36de8b9e4b1a | 553 | // return; |
darienf | 3:36de8b9e4b1a | 554 | // } |
darienf | 3:36de8b9e4b1a | 555 | // } |
darienf | 3:36de8b9e4b1a | 556 | |
darienf | 3:36de8b9e4b1a | 557 | int chartMinYValue = (int)_chart.ChartAreas[chartAreaName].AxisY.Minimum; // rawIntArrayYData[firstVisiblePointX] - 1; |
darienf | 3:36de8b9e4b1a | 558 | int chartMaxYValue = (int)_chart.ChartAreas[chartAreaName].AxisY.Maximum; // rawIntArrayYData[firstVisiblePointX] + 1; |
darienf | 3:36de8b9e4b1a | 559 | // VERIFY: OS24EVK-73 Sample Avg 2 breaks chart scrolling - firstVisiblePointIndex instead of firstVisiblePointX |
darienf | 3:36de8b9e4b1a | 560 | int dataMinYValue = rawIntArrayYData[firstVisiblePointIndex] - 1; |
darienf | 3:36de8b9e4b1a | 561 | int dataMaxYValue = rawIntArrayYData[firstVisiblePointIndex] + 1; |
darienf | 3:36de8b9e4b1a | 562 | for (int index = firstVisiblePointIndex; index <= lastXIndex; index++) |
darienf | 3:36de8b9e4b1a | 563 | { |
darienf | 3:36de8b9e4b1a | 564 | int Y = rawIntArrayYData[index]; |
darienf | 3:36de8b9e4b1a | 565 | // VERIFY: OS24EVK-57 OS24EVK-54 improve chart throughput: AutoScaleEvaluate() dataFormatIs16bit2sComplement=true for Accelerometer X Y Z data |
darienf | 3:36de8b9e4b1a | 566 | // VERIFY: OS24EVK-75 replace AutoScaleEvaluate dataFormatIs16bit2sComplement with if (DataFormat == DataFormats.Format16bit2sComplement) |
darienf | 3:36de8b9e4b1a | 567 | if (DataFormat == DataFormats.Format16bit2sComplement) |
darienf | 3:36de8b9e4b1a | 568 | { |
darienf | 3:36de8b9e4b1a | 569 | // VERIFY: OS24EVK-57 interpret rawX rawY rawZ as 16-bit 2's complement |
darienf | 3:36de8b9e4b1a | 570 | if (Y > 0x8000) |
darienf | 3:36de8b9e4b1a | 571 | { |
darienf | 3:36de8b9e4b1a | 572 | Y = Y - 0x10000; |
darienf | 3:36de8b9e4b1a | 573 | } |
darienf | 3:36de8b9e4b1a | 574 | } |
darienf | 3:36de8b9e4b1a | 575 | //else |
darienf | 3:36de8b9e4b1a | 576 | //{ |
darienf | 3:36de8b9e4b1a | 577 | // Y = Y + 0; // debug breakpoint for code path verification |
darienf | 3:36de8b9e4b1a | 578 | //} |
darienf | 3:36de8b9e4b1a | 579 | if (dataMinYValue > Y) |
darienf | 3:36de8b9e4b1a | 580 | { |
darienf | 3:36de8b9e4b1a | 581 | dataMinYValue = Y; |
darienf | 3:36de8b9e4b1a | 582 | } |
darienf | 3:36de8b9e4b1a | 583 | if (dataMaxYValue < Y) |
darienf | 3:36de8b9e4b1a | 584 | { |
darienf | 3:36de8b9e4b1a | 585 | dataMaxYValue = Y; |
darienf | 3:36de8b9e4b1a | 586 | } |
darienf | 3:36de8b9e4b1a | 587 | } |
darienf | 3:36de8b9e4b1a | 588 | // rawIntArrayYData[firstIndex..lastIndex] spans the range from dataMinYValue .. dataMaxYValue |
darienf | 3:36de8b9e4b1a | 589 | double dataSpanY = (dataMaxYValue - dataMinYValue); |
darienf | 3:36de8b9e4b1a | 590 | double dataCenterY = (dataMaxYValue + dataMinYValue) / 2; |
darienf | 3:36de8b9e4b1a | 591 | |
darienf | 3:36de8b9e4b1a | 592 | bool isAllDataVisible = ( |
darienf | 3:36de8b9e4b1a | 593 | (chartMinYValue < dataMaxYValue) && (dataMaxYValue < chartMaxYValue) |
darienf | 3:36de8b9e4b1a | 594 | && |
darienf | 3:36de8b9e4b1a | 595 | (chartMinYValue < dataMinYValue) && (dataMinYValue < chartMaxYValue) |
darienf | 3:36de8b9e4b1a | 596 | ); |
darienf | 3:36de8b9e4b1a | 597 | if (isAllDataVisible) |
darienf | 3:36de8b9e4b1a | 598 | { |
darienf | 3:36de8b9e4b1a | 599 | // all data is within the chart limits, but is the chart sufficiently zoomed in? |
darienf | 3:36de8b9e4b1a | 600 | double relativeDataSpan = (double)dataSpanY / (chartMaxYValue - chartMinYValue); |
darienf | 3:36de8b9e4b1a | 601 | if (relativeDataSpan > 0.65) |
darienf | 3:36de8b9e4b1a | 602 | { |
darienf | 3:36de8b9e4b1a | 603 | // the current chart scale is good enough, do not update |
darienf | 3:36de8b9e4b1a | 604 | #if PROFILER |
darienf | 3:36de8b9e4b1a | 605 | // TODO1: OS24EVK-54 profiling: capture max interval, number of intervals, cumulative interval |
darienf | 3:36de8b9e4b1a | 606 | _profilingStopwatchAutoScaleEvaluate.Stop(); |
darienf | 3:36de8b9e4b1a | 607 | #endif // PROFILER |
darienf | 3:36de8b9e4b1a | 608 | return; |
darienf | 3:36de8b9e4b1a | 609 | } |
darienf | 3:36de8b9e4b1a | 610 | } |
darienf | 3:36de8b9e4b1a | 611 | // https://jira.maxim-ic.com/browse/OS24EVK-34 AutoScaleEvaluate() use _AutoScaleMinSpanY; // minimum allowed span of chartMax-chartMin, to avoid focusing on LSB noise |
darienf | 3:36de8b9e4b1a | 612 | if (dataSpanY < _AutoScaleMinSpanY) |
darienf | 3:36de8b9e4b1a | 613 | { |
darienf | 3:36de8b9e4b1a | 614 | // https://jira.maxim-ic.com/browse/OS24EVK-34 Autoscale - Minimum span (in case dataMax-dataMin is too small) to avoid focusing on LSB noise |
darienf | 3:36de8b9e4b1a | 615 | dataSpanY = _AutoScaleMinSpanY; |
darienf | 3:36de8b9e4b1a | 616 | } |
darienf | 3:36de8b9e4b1a | 617 | else |
darienf | 3:36de8b9e4b1a | 618 | { |
darienf | 3:36de8b9e4b1a | 619 | // https://jira.maxim-ic.com/browse/OS24EVK-34 Autoscale - Apply a Top margin - Bottom margin = 12% .. 88% when mapping Chart max-min to Data max-min |
darienf | 3:36de8b9e4b1a | 620 | // https://jira.maxim-ic.com/browse/OS24EVK-34 AutoScaleEvaluate() use _AutoScaleMarginYTop; // chartMax empty area above dataMax |
darienf | 3:36de8b9e4b1a | 621 | // https://jira.maxim-ic.com/browse/OS24EVK-34 AutoScaleEvaluate() use _AutoScaleMarginYBottom; // chartMin empty area below dataMin |
darienf | 3:36de8b9e4b1a | 622 | // dataSpanY = dataSpanY * 1.25; |
darienf | 3:36de8b9e4b1a | 623 | // dataSpanY = dataSpanY * (1.0 + 0.125 + 0.125); |
darienf | 3:36de8b9e4b1a | 624 | dataSpanY = dataSpanY * (1.0 + _AutoScaleMarginYTop + _AutoScaleMarginYBottom); |
darienf | 3:36de8b9e4b1a | 625 | |
darienf | 3:36de8b9e4b1a | 626 | // https://jira.maxim-ic.com/browse/OS24EVK-42 Autoscale tuning (Larry 2014-11-24) Round to nearest multiple of 100. |
darienf | 3:36de8b9e4b1a | 627 | // - Y axis: No decimals. Round to nearest multiple of 100. |
darienf | 3:36de8b9e4b1a | 628 | // private double _AutoScaleYmultiples = 100; |
darienf | 3:36de8b9e4b1a | 629 | //int tempdataSpanY = (int)(dataSpanY / _AutoScaleYmultiples); |
darienf | 3:36de8b9e4b1a | 630 | //dataSpanY = tempdataSpanY * _AutoScaleYmultiples; |
darienf | 3:36de8b9e4b1a | 631 | //dataSpanY = (double)((int)dataSpanY / _AutoScaleYmultiples) * _AutoScaleYmultiples; |
darienf | 3:36de8b9e4b1a | 632 | //dataCenterY = (double)((int)dataCenterY / _AutoScaleYmultiples) * _AutoScaleYmultiples; |
darienf | 3:36de8b9e4b1a | 633 | } |
darienf | 3:36de8b9e4b1a | 634 | // https://jira.maxim-ic.com/browse/OS24EVK-34 Autoscale - There are 5 vertical divisions; keep the minor axis tick values integer |
darienf | 3:36de8b9e4b1a | 635 | //int YaxisDivisions = (int)System.Math.Ceiling(dataSpanY / 6.0); |
darienf | 3:36de8b9e4b1a | 636 | //dataSpanY = YaxisDivisions * 6; |
darienf | 3:36de8b9e4b1a | 637 | // https://jira.maxim-ic.com/browse/OS24EVK-42 Autoscale tuning (Larry 2014-11-24) Round to nearest multiple of 100. |
darienf | 3:36de8b9e4b1a | 638 | // - Y axis: No decimals. Round to nearest multiple of 100. |
darienf | 3:36de8b9e4b1a | 639 | // private double _AutoScaleYmultiples = 100; |
darienf | 3:36de8b9e4b1a | 640 | //int tempdataCenterY = (int)(dataCenterY / (_AutoScaleYmultiples*2)); |
darienf | 3:36de8b9e4b1a | 641 | //dataCenterY = tempdataCenterY * (_AutoScaleYmultiples*2); |
darienf | 3:36de8b9e4b1a | 642 | |
darienf | 3:36de8b9e4b1a | 643 | // chart.ChartAreas[0].AxisY.Maximum = dataMaxYValue; |
darienf | 3:36de8b9e4b1a | 644 | // chart.ChartAreas[0].AxisY.Minimum = dataMinYValue; |
darienf | 3:36de8b9e4b1a | 645 | //chart.ChartAreas[0].AxisY.Maximum = System.Math.Ceiling(dataCenterY + (dataSpanY / 2)); // dataMaxYValue; |
darienf | 3:36de8b9e4b1a | 646 | //chart.ChartAreas[0].AxisY.Minimum = System.Math.Floor(dataCenterY - (dataSpanY / 2)); // dataMinYValue; |
darienf | 3:36de8b9e4b1a | 647 | // https://jira.maxim-ic.com/browse/OS24EVK-42 Autoscale tuning (Larry 2014-11-24) Round to nearest multiple of 100. |
darienf | 3:36de8b9e4b1a | 648 | // - Y axis: No decimals. Round to nearest multiple of 100. |
darienf | 3:36de8b9e4b1a | 649 | // private double _AutoScaleYmultiples = 100; |
darienf | 3:36de8b9e4b1a | 650 | int iMaxY_target = (int)((dataCenterY + (dataSpanY / 2)) / _AutoScaleYmultiples); |
darienf | 3:36de8b9e4b1a | 651 | int iMinY_target = (int)((dataCenterY - (dataSpanY / 2)) / _AutoScaleYmultiples); |
darienf | 3:36de8b9e4b1a | 652 | |
darienf | 3:36de8b9e4b1a | 653 | double dampingConstantK = 0.2; |
darienf | 3:36de8b9e4b1a | 654 | int iMaxY_damped = iMaxY_target; |
darienf | 3:36de8b9e4b1a | 655 | int iMinY_damped = iMinY_target; |
darienf | 3:36de8b9e4b1a | 656 | if (double.IsNaN(_chart.ChartAreas[chartAreaName].AxisY.Maximum) == false) |
darienf | 3:36de8b9e4b1a | 657 | { |
darienf | 3:36de8b9e4b1a | 658 | int iMaxY_chart = (int)(_chart.ChartAreas[chartAreaName].AxisY.Maximum / _AutoScaleYmultiples); |
darienf | 3:36de8b9e4b1a | 659 | int iMinY_chart = (int)(_chart.ChartAreas[chartAreaName].AxisY.Minimum / _AutoScaleYmultiples); |
darienf | 3:36de8b9e4b1a | 660 | iMaxY_damped = (int)((dampingConstantK * (double)iMaxY_target) + ((1 - dampingConstantK) * (double)iMaxY_chart) + 0.5); |
darienf | 3:36de8b9e4b1a | 661 | iMinY_damped = (int)((dampingConstantK * (double)iMinY_target) + ((1 - dampingConstantK) * (double)iMinY_chart)); |
darienf | 3:36de8b9e4b1a | 662 | } |
darienf | 3:36de8b9e4b1a | 663 | double maxY = iMaxY_target * _AutoScaleYmultiples; |
darienf | 3:36de8b9e4b1a | 664 | double minY = iMinY_target * _AutoScaleYmultiples; |
darienf | 3:36de8b9e4b1a | 665 | _chart.ChartAreas[chartAreaName].AxisY.Maximum = maxY; |
darienf | 3:36de8b9e4b1a | 666 | _chart.ChartAreas[chartAreaName].AxisY.Minimum = minY; |
darienf | 3:36de8b9e4b1a | 667 | // if chart.ChartAreas[chartAreaName].AxisY.Maximum is NaN then just assign maxY |
darienf | 3:36de8b9e4b1a | 668 | //if (double.IsNaN(chart.ChartAreas[chartAreaName].AxisY.Maximum)) |
darienf | 3:36de8b9e4b1a | 669 | //{ |
darienf | 3:36de8b9e4b1a | 670 | // chart.ChartAreas[chartAreaName].AxisY.Maximum = maxY; |
darienf | 3:36de8b9e4b1a | 671 | // chart.ChartAreas[chartAreaName].AxisY.Minimum = minY; |
darienf | 3:36de8b9e4b1a | 672 | //} |
darienf | 3:36de8b9e4b1a | 673 | //else |
darienf | 3:36de8b9e4b1a | 674 | //{ |
darienf | 3:36de8b9e4b1a | 675 | // chart.ChartAreas[chartAreaName].AxisY.Maximum = (dampingConstantK * maxY) + ((1 - dampingConstantK) * chart.ChartAreas[chartAreaName].AxisY.Maximum); |
darienf | 3:36de8b9e4b1a | 676 | // chart.ChartAreas[chartAreaName].AxisY.Minimum = (dampingConstantK * minY) + ((1 - dampingConstantK) * chart.ChartAreas[chartAreaName].AxisY.Minimum); |
darienf | 3:36de8b9e4b1a | 677 | //} |
darienf | 3:36de8b9e4b1a | 678 | |
darienf | 3:36de8b9e4b1a | 679 | #if PROFILER |
darienf | 3:36de8b9e4b1a | 680 | // TODO1: OS24EVK-54 profiling: capture max interval, number of intervals, cumulative interval |
darienf | 3:36de8b9e4b1a | 681 | _profilingStopwatchAutoScaleEvaluate.Stop(); |
darienf | 3:36de8b9e4b1a | 682 | #endif // PROFILER |
darienf | 3:36de8b9e4b1a | 683 | } |
darienf | 3:36de8b9e4b1a | 684 | |
darienf | 3:36de8b9e4b1a | 685 | /// <summary> |
darienf | 3:36de8b9e4b1a | 686 | /// Raw data format |
darienf | 3:36de8b9e4b1a | 687 | /// </summary> |
darienf | 3:36de8b9e4b1a | 688 | public DataFormats DataFormat = DataFormats.FormatUnsigned; |
darienf | 3:36de8b9e4b1a | 689 | |
darienf | 3:36de8b9e4b1a | 690 | public enum DataFormats |
darienf | 3:36de8b9e4b1a | 691 | { |
darienf | 3:36de8b9e4b1a | 692 | /// <summary> |
darienf | 3:36de8b9e4b1a | 693 | /// Interpret raw data as unsigned values |
darienf | 3:36de8b9e4b1a | 694 | /// </summary> |
darienf | 3:36de8b9e4b1a | 695 | FormatUnsigned, |
darienf | 3:36de8b9e4b1a | 696 | |
darienf | 3:36de8b9e4b1a | 697 | /// <summary> |
darienf | 3:36de8b9e4b1a | 698 | /// Interpret raw data as 16-bit, signed 2's complement values |
darienf | 3:36de8b9e4b1a | 699 | /// </summary> |
darienf | 3:36de8b9e4b1a | 700 | Format16bit2sComplement, |
darienf | 3:36de8b9e4b1a | 701 | } |
darienf | 3:36de8b9e4b1a | 702 | |
darienf | 3:36de8b9e4b1a | 703 | } // public class MedicalChartHelper |
darienf | 3:36de8b9e4b1a | 704 | |
darienf | 3:36de8b9e4b1a | 705 | } // namespace Maxim.MAX30101 |