Repository for import to local machine

Dependencies:   DMBasicGUI DMSupport

Committer:
jmitc91516
Date:
Mon Jul 31 15:37:57 2017 +0000
Revision:
8:26e49e6955bd
Parent:
1:a5258871b33d
Method ramp scrolling improved, and more bitmaps moved to QSPI memory

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jmitc91516 1:a5258871b33d 1 #include "GuiLibGraph.h"
jmitc91516 1:a5258871b33d 2
jmitc91516 1:a5258871b33d 3 #include <cstring>
jmitc91516 1:a5258871b33d 4
jmitc91516 1:a5258871b33d 5 #include <float.h>
jmitc91516 1:a5258871b33d 6
jmitc91516 1:a5258871b33d 7
jmitc91516 1:a5258871b33d 8 #define USE_LED_FOR_DEBUGGING
jmitc91516 1:a5258871b33d 9
jmitc91516 1:a5258871b33d 10 #ifdef USE_LED_FOR_DEBUGGING
jmitc91516 1:a5258871b33d 11
jmitc91516 1:a5258871b33d 12 #include "gpio_api.h"
jmitc91516 1:a5258871b33d 13 #include "wait_api.h"
jmitc91516 1:a5258871b33d 14 #include "toolchain.h"
jmitc91516 1:a5258871b33d 15 #include "mbed_interface.h"
jmitc91516 1:a5258871b33d 16
jmitc91516 1:a5258871b33d 17 /*
jmitc91516 1:a5258871b33d 18 Draw a part of a profile - which will be a quadrilateral, vertical at left and right, horizontal at the bottom, but a sloping straight line at the top -
jmitc91516 1:a5258871b33d 19 by calling the EasyGUI GuiLib_VLine function multiple times.
jmitc91516 1:a5258871b33d 20
jmitc91516 1:a5258871b33d 21 Args: colour of the profile to the left of the boundary
jmitc91516 1:a5258871b33d 22 colour of the profile to the right of the boundary
jmitc91516 1:a5258871b33d 23 X coords of the left and right edges of the section
jmitc91516 1:a5258871b33d 24 X coord of the colour boundary
jmitc91516 1:a5258871b33d 25 Y coord of the bottom
jmitc91516 1:a5258871b33d 26 Y coords of the top left and top right
jmitc91516 1:a5258871b33d 27
jmitc91516 1:a5258871b33d 28 Returns true if OK, false if it failed (e.g. the coords were invalid).
jmitc91516 1:a5258871b33d 29 */
jmitc91516 1:a5258871b33d 30 extern bool DrawProfileSectionUsingGuiLibVLine(GuiConst_INTCOLOR colour1, GuiConst_INTCOLOR colour2, GuiConst_INT16S xLeft, GuiConst_INT16S xRight, GuiConst_INT16S xColourBoundary,
jmitc91516 1:a5258871b33d 31 GuiConst_INT16S yBottom, GuiConst_INT16S yTopLeft, GuiConst_INT16S yTopRight);
jmitc91516 1:a5258871b33d 32
jmitc91516 1:a5258871b33d 33
jmitc91516 1:a5258871b33d 34 // Turn on LED 4 when we get an error (mismatched time/X coord) in the graph data (see below)
jmitc91516 1:a5258871b33d 35 static void SetLed4(bool turnLedOn)
jmitc91516 1:a5258871b33d 36 {
jmitc91516 1:a5258871b33d 37 gpio_t led_4; gpio_init_out(&led_4, LED4);
jmitc91516 1:a5258871b33d 38
jmitc91516 1:a5258871b33d 39 if(turnLedOn) {
jmitc91516 1:a5258871b33d 40 gpio_write(&led_4, 1); // one appears to mean "turn LED 4 on"
jmitc91516 1:a5258871b33d 41 } else {
jmitc91516 1:a5258871b33d 42 gpio_write(&led_4, 0); // zero appears to turn it off
jmitc91516 1:a5258871b33d 43 }
jmitc91516 1:a5258871b33d 44 }
jmitc91516 1:a5258871b33d 45
jmitc91516 1:a5258871b33d 46 #endif // USE_LED_FOR_DEBUGGING
jmitc91516 1:a5258871b33d 47
jmitc91516 1:a5258871b33d 48
jmitc91516 1:a5258871b33d 49 /*
jmitc91516 1:a5258871b33d 50 The GuiLibGraphDataSet class - encapsulates a GuiLib_GraphDataPoint array,
jmitc91516 1:a5258871b33d 51 making access and use of it more straightforward than if the caller
jmitc91516 1:a5258871b33d 52 had to do this directly.
jmitc91516 1:a5258871b33d 53
jmitc91516 1:a5258871b33d 54 We assume that X coordinates are time values, and Y coordinates are temperature, pressure, etc, values.
jmitc91516 1:a5258871b33d 55 ******************************************************************************************************
jmitc91516 1:a5258871b33d 56
jmitc91516 1:a5258871b33d 57 We leave it to the caller to decide what the Y coordinate units are, but we let the caller specify
jmitc91516 1:a5258871b33d 58 the time (i.e. X axis) units. If the caller changes the units, we recalculate the X coordinates to match.
jmitc91516 1:a5258871b33d 59 The options are minutes and seconds - we default to minutes.
jmitc91516 1:a5258871b33d 60
jmitc91516 1:a5258871b33d 61 Note that the coord values are integers (as in the easyGUI Graph item).
jmitc91516 1:a5258871b33d 62 */
jmitc91516 1:a5258871b33d 63
jmitc91516 1:a5258871b33d 64 /*
jmitc91516 1:a5258871b33d 65 Static member function, to provide a standard way of converting the floating point coordinates we store internally (for accuracy),
jmitc91516 1:a5258871b33d 66 to the integer values required by easyGUI graphs. We always store the time value (X coordinate) as minutes, in units of 0.1 minute,
jmitc91516 1:a5258871b33d 67 as does the GC itself. We convert to integer minutes or seconds as required by the caller.
jmitc91516 1:a5258871b33d 68
jmitc91516 1:a5258871b33d 69 We do not concern ourselves here with the units of the Y coordinate - we assume that the caller knows what they are.
jmitc91516 1:a5258871b33d 70
jmitc91516 1:a5258871b33d 71 Args: pointer to the GuiLib_GraphDataPoint object to receive the integer coordinates
jmitc91516 1:a5258871b33d 72 the floating point data to be converted
jmitc91516 1:a5258871b33d 73 the time unit (minutes or seconds) for the generated X coordinate
jmitc91516 1:a5258871b33d 74
jmitc91516 1:a5258871b33d 75 No return value (we assume the conversion will always succeed).
jmitc91516 1:a5258871b33d 76 */
jmitc91516 1:a5258871b33d 77 void GuiLibGraphDataSet::ConvertFloatingDataPointToGuiLibGraphDataPoint(GuiLib_GraphDataPoint* graphDataPoint, FloatingDataPoint floatingDataPoint, TimeUnit timeUnit)
jmitc91516 1:a5258871b33d 78 {
jmitc91516 1:a5258871b33d 79 // The 'floor' mathematical function expects a double as its argument
jmitc91516 1:a5258871b33d 80
jmitc91516 1:a5258871b33d 81 double doubleX = (double) floatingDataPoint.X;
jmitc91516 1:a5258871b33d 82 if(timeUnit == SECONDS) {
jmitc91516 1:a5258871b33d 83 doubleX *= 60.0;
jmitc91516 1:a5258871b33d 84 }
jmitc91516 1:a5258871b33d 85
jmitc91516 1:a5258871b33d 86 double doubleY = (double) floatingDataPoint.Y;
jmitc91516 1:a5258871b33d 87
jmitc91516 1:a5258871b33d 88 // Round, don't truncate
jmitc91516 1:a5258871b33d 89 graphDataPoint->X = (GuiConst_INT32S) floor(doubleX + 0.5);
jmitc91516 1:a5258871b33d 90 graphDataPoint->Y = (GuiConst_INT32S) floor(doubleY + 0.5);
jmitc91516 1:a5258871b33d 91 }
jmitc91516 1:a5258871b33d 92
jmitc91516 1:a5258871b33d 93 GuiLibGraphDataSet::GuiLibGraphDataSet()
jmitc91516 1:a5258871b33d 94 {
jmitc91516 1:a5258871b33d 95 // No data yet...
jmitc91516 1:a5258871b33d 96
jmitc91516 1:a5258871b33d 97 theGraphDataSet = NULL;
jmitc91516 1:a5258871b33d 98
jmitc91516 1:a5258871b33d 99 graphDataSetActualLength = 0;
jmitc91516 1:a5258871b33d 100 graphDataSetSizeInIncrements = 0;
jmitc91516 1:a5258871b33d 101
jmitc91516 1:a5258871b33d 102 nonRoundedTotalMethodTime = 0.0f;
jmitc91516 1:a5258871b33d 103 }
jmitc91516 1:a5258871b33d 104
jmitc91516 1:a5258871b33d 105 GuiLibGraphDataSet::~GuiLibGraphDataSet()
jmitc91516 1:a5258871b33d 106 {
jmitc91516 1:a5258871b33d 107 if(theGraphDataSet != NULL) {
jmitc91516 1:a5258871b33d 108 delete [] theGraphDataSet;
jmitc91516 1:a5258871b33d 109 }
jmitc91516 1:a5258871b33d 110 }
jmitc91516 1:a5258871b33d 111
jmitc91516 1:a5258871b33d 112
jmitc91516 1:a5258871b33d 113 /*
jmitc91516 1:a5258871b33d 114 Clears (i.e. deletes, removes) all the existing data (if any) for this dataset
jmitc91516 1:a5258871b33d 115 */
jmitc91516 1:a5258871b33d 116 void GuiLibGraphDataSet::ClearData(void)
jmitc91516 1:a5258871b33d 117 {
jmitc91516 1:a5258871b33d 118 if(theGraphDataSet != NULL) {
jmitc91516 1:a5258871b33d 119 delete [] theGraphDataSet;
jmitc91516 1:a5258871b33d 120 theGraphDataSet = NULL;
jmitc91516 1:a5258871b33d 121
jmitc91516 1:a5258871b33d 122 graphDataSetActualLength = 0;
jmitc91516 1:a5258871b33d 123 graphDataSetSizeInIncrements = 0;
jmitc91516 1:a5258871b33d 124 }
jmitc91516 1:a5258871b33d 125 }
jmitc91516 1:a5258871b33d 126
jmitc91516 1:a5258871b33d 127
jmitc91516 1:a5258871b33d 128 /*
jmitc91516 1:a5258871b33d 129 We extend the dataset array in steps of 'SIZE_INCREMENT'. This function does that,
jmitc91516 1:a5258871b33d 130 and copies the existing data to the extended array.
jmitc91516 1:a5258871b33d 131
jmitc91516 1:a5258871b33d 132 It returns true if it succeeded in extending the dataset array, false otherwise.
jmitc91516 1:a5258871b33d 133 */
jmitc91516 1:a5258871b33d 134 bool GuiLibGraphDataSet::ExtendDataSetArray(void)
jmitc91516 1:a5258871b33d 135 {
jmitc91516 1:a5258871b33d 136 bool retVal = false;
jmitc91516 1:a5258871b33d 137
jmitc91516 1:a5258871b33d 138 if(theGraphDataSet != NULL) {
jmitc91516 1:a5258871b33d 139 FloatingDataPoint* newGraphDataSet = new FloatingDataPoint[(graphDataSetSizeInIncrements + 1) * SIZE_INCREMENT];
jmitc91516 1:a5258871b33d 140
jmitc91516 1:a5258871b33d 141 if(newGraphDataSet != NULL) {
jmitc91516 1:a5258871b33d 142 std::memcpy(newGraphDataSet, theGraphDataSet, (graphDataSetSizeInIncrements * SIZE_INCREMENT * sizeof(FloatingDataPoint)));
jmitc91516 1:a5258871b33d 143
jmitc91516 1:a5258871b33d 144 delete [] theGraphDataSet;
jmitc91516 1:a5258871b33d 145
jmitc91516 1:a5258871b33d 146 theGraphDataSet = newGraphDataSet;
jmitc91516 1:a5258871b33d 147
jmitc91516 1:a5258871b33d 148 ++graphDataSetSizeInIncrements;
jmitc91516 1:a5258871b33d 149
jmitc91516 1:a5258871b33d 150 // Leave 'graphDataSetActualLength' with whatever value it currently has.
jmitc91516 1:a5258871b33d 151 // We have only extended the array, not added any data to it.
jmitc91516 1:a5258871b33d 152
jmitc91516 1:a5258871b33d 153 retVal = true; // Success
jmitc91516 1:a5258871b33d 154 }
jmitc91516 1:a5258871b33d 155
jmitc91516 1:a5258871b33d 156 } else {
jmitc91516 1:a5258871b33d 157 // This is the first 'extension'
jmitc91516 1:a5258871b33d 158 theGraphDataSet = new FloatingDataPoint[SIZE_INCREMENT];
jmitc91516 1:a5258871b33d 159
jmitc91516 1:a5258871b33d 160 if(theGraphDataSet != NULL) {
jmitc91516 1:a5258871b33d 161 graphDataSetSizeInIncrements = 1;
jmitc91516 1:a5258871b33d 162
jmitc91516 1:a5258871b33d 163 // We assume 'graphDataSetActualLength' is set to zero - leave it with this value.
jmitc91516 1:a5258871b33d 164 // We have only allocated memory for the array, not put any data in it.
jmitc91516 1:a5258871b33d 165
jmitc91516 1:a5258871b33d 166 retVal = true; // Success
jmitc91516 1:a5258871b33d 167 }
jmitc91516 1:a5258871b33d 168 }
jmitc91516 1:a5258871b33d 169
jmitc91516 1:a5258871b33d 170 return retVal;
jmitc91516 1:a5258871b33d 171 }
jmitc91516 1:a5258871b33d 172
jmitc91516 1:a5258871b33d 173
jmitc91516 1:a5258871b33d 174 /*
jmitc91516 1:a5258871b33d 175 Adds a datapoint with the specified X and Y values to the dataset array,
jmitc91516 1:a5258871b33d 176 making sure to keep the array elements in ascending order of X coordinate.
jmitc91516 1:a5258871b33d 177 Other member functions of this class rely on this.
jmitc91516 1:a5258871b33d 178 *************************************************
jmitc91516 1:a5258871b33d 179
jmitc91516 1:a5258871b33d 180 Returns true for success, false for failure.
jmitc91516 1:a5258871b33d 181
jmitc91516 1:a5258871b33d 182 Args: the X and Y values for the new datapoint
jmitc91516 1:a5258871b33d 183
jmitc91516 1:a5258871b33d 184 Note that this function takes no account of the units specified for the X (i.e. time) axis -
jmitc91516 1:a5258871b33d 185 we assume that the caller has already ensured that the X value is in those units.
jmitc91516 1:a5258871b33d 186 */
jmitc91516 1:a5258871b33d 187 bool GuiLibGraphDataSet::AddDataPoint(float X, float Y)
jmitc91516 1:a5258871b33d 188 {
jmitc91516 1:a5258871b33d 189 // Check that we do not already have a point at the same X coordinate -
jmitc91516 1:a5258871b33d 190 // if so, return false
jmitc91516 1:a5258871b33d 191 for (int i = 0; i < graphDataSetActualLength; ++i) {
jmitc91516 1:a5258871b33d 192 if(theGraphDataSet[i].X == X) {
jmitc91516 1:a5258871b33d 193 return false;
jmitc91516 1:a5258871b33d 194 }
jmitc91516 1:a5258871b33d 195
jmitc91516 1:a5258871b33d 196 if(theGraphDataSet[i].X > X) {
jmitc91516 1:a5258871b33d 197 // We have now reached a point with a greater X coord,
jmitc91516 1:a5258871b33d 198 // without finding a point with the same X coord - safe to continue
jmitc91516 1:a5258871b33d 199 break;
jmitc91516 1:a5258871b33d 200 }
jmitc91516 1:a5258871b33d 201 }
jmitc91516 1:a5258871b33d 202
jmitc91516 1:a5258871b33d 203 if((graphDataSetActualLength + 1) > (graphDataSetSizeInIncrements * SIZE_INCREMENT)) {
jmitc91516 1:a5258871b33d 204
jmitc91516 1:a5258871b33d 205 // We need to extend the array before adding the new datapoint
jmitc91516 1:a5258871b33d 206
jmitc91516 1:a5258871b33d 207 if(!ExtendDataSetArray()) {
jmitc91516 1:a5258871b33d 208 return false;
jmitc91516 1:a5258871b33d 209 }
jmitc91516 1:a5258871b33d 210 }
jmitc91516 1:a5258871b33d 211
jmitc91516 1:a5258871b33d 212 // We now have room for the new datapoint
jmitc91516 1:a5258871b33d 213 // - make sure we keep the datapoints in ascending order of X coord
jmitc91516 1:a5258871b33d 214 int positionToAdd = graphDataSetActualLength;
jmitc91516 1:a5258871b33d 215
jmitc91516 1:a5258871b33d 216 if(graphDataSetActualLength > 0) {
jmitc91516 1:a5258871b33d 217
jmitc91516 1:a5258871b33d 218 while(theGraphDataSet[positionToAdd - 1].X > X) {
jmitc91516 1:a5258871b33d 219 --positionToAdd;
jmitc91516 1:a5258871b33d 220
jmitc91516 1:a5258871b33d 221 if(positionToAdd == 0) break;
jmitc91516 1:a5258871b33d 222 }
jmitc91516 1:a5258871b33d 223
jmitc91516 1:a5258871b33d 224
jmitc91516 1:a5258871b33d 225 // Move 'up' all the array elements 'above' positionToAdd
jmitc91516 1:a5258871b33d 226
jmitc91516 1:a5258871b33d 227 for (int j = graphDataSetActualLength; j > positionToAdd; --j) {
jmitc91516 1:a5258871b33d 228 theGraphDataSet[j] = theGraphDataSet[j - 1];
jmitc91516 1:a5258871b33d 229 }
jmitc91516 1:a5258871b33d 230 }
jmitc91516 1:a5258871b33d 231
jmitc91516 1:a5258871b33d 232 // We are now ready to add the new datapoint
jmitc91516 1:a5258871b33d 233
jmitc91516 1:a5258871b33d 234 theGraphDataSet[positionToAdd].X = X;
jmitc91516 1:a5258871b33d 235 theGraphDataSet[positionToAdd].Y = Y;
jmitc91516 1:a5258871b33d 236
jmitc91516 1:a5258871b33d 237 ++graphDataSetActualLength;
jmitc91516 1:a5258871b33d 238
jmitc91516 1:a5258871b33d 239 return true;
jmitc91516 1:a5258871b33d 240 }
jmitc91516 1:a5258871b33d 241
jmitc91516 1:a5258871b33d 242 /*
jmitc91516 1:a5258871b33d 243 Returns the X and Y coordinates of the datapoint at the specified index in the dataset.
jmitc91516 1:a5258871b33d 244
jmitc91516 1:a5258871b33d 245 Returns true if we actually have a point at the index, false if not (does not set
jmitc91516 1:a5258871b33d 246 the destination variables in this case).
jmitc91516 1:a5258871b33d 247
jmitc91516 1:a5258871b33d 248 Args: the index of the point required
jmitc91516 1:a5258871b33d 249 pointers to variables to contain the X and Y values of the specified datapoint.
jmitc91516 1:a5258871b33d 250 (It is up to the caller to make sure these are valid.)
jmitc91516 1:a5258871b33d 251 */
jmitc91516 1:a5258871b33d 252 bool GuiLibGraphDataSet::GetDataPoint(int dataPointIndex, float *X, float *Y)
jmitc91516 1:a5258871b33d 253 {
jmitc91516 1:a5258871b33d 254 if((dataPointIndex >= 0) && (dataPointIndex < graphDataSetActualLength)) {
jmitc91516 1:a5258871b33d 255
jmitc91516 1:a5258871b33d 256 *X = theGraphDataSet[dataPointIndex].X;
jmitc91516 1:a5258871b33d 257 *Y = theGraphDataSet[dataPointIndex].Y;
jmitc91516 1:a5258871b33d 258
jmitc91516 1:a5258871b33d 259 return true;
jmitc91516 1:a5258871b33d 260 }
jmitc91516 1:a5258871b33d 261
jmitc91516 1:a5258871b33d 262 // 'else' index not valid
jmitc91516 1:a5258871b33d 263 return false;
jmitc91516 1:a5258871b33d 264 }
jmitc91516 1:a5258871b33d 265
jmitc91516 1:a5258871b33d 266
jmitc91516 1:a5258871b33d 267 /*
jmitc91516 1:a5258871b33d 268 Returns the Y coordinate of a point on the graph at the specified X coordinate.
jmitc91516 1:a5258871b33d 269 This will in general mean interpolating between two adjacent points - we assume
jmitc91516 1:a5258871b33d 270 a straight line in this case.
jmitc91516 1:a5258871b33d 271
jmitc91516 1:a5258871b33d 272 Note that this function relies on the array elements being in ascending order
jmitc91516 1:a5258871b33d 273 of X coordinate.
jmitc91516 1:a5258871b33d 274 */
jmitc91516 1:a5258871b33d 275 float GuiLibGraphDataSet::GetYCoordAtXCoord(float X)
jmitc91516 1:a5258871b33d 276 {
jmitc91516 1:a5258871b33d 277 if(graphDataSetActualLength > 0) {
jmitc91516 1:a5258871b33d 278
jmitc91516 1:a5258871b33d 279 if(graphDataSetActualLength > 1) {
jmitc91516 1:a5258871b33d 280
jmitc91516 1:a5258871b33d 281 // Deal with the extreme cases first
jmitc91516 1:a5258871b33d 282 if(theGraphDataSet[0].X > X) {
jmitc91516 1:a5258871b33d 283
jmitc91516 1:a5258871b33d 284 // Required point is before the start of our array
jmitc91516 1:a5258871b33d 285
jmitc91516 1:a5258871b33d 286 double X0 = (double) theGraphDataSet[0].X;
jmitc91516 1:a5258871b33d 287 double Y0 = (double) theGraphDataSet[0].Y;
jmitc91516 1:a5258871b33d 288 double X1 = (double) theGraphDataSet[1].X;
jmitc91516 1:a5258871b33d 289 double Y1 = (double) theGraphDataSet[1].Y;
jmitc91516 1:a5258871b33d 290
jmitc91516 1:a5258871b33d 291 double m = (Y1 - Y0) / (X1 - X0);
jmitc91516 1:a5258871b33d 292 double c = Y0 - (m * X0);
jmitc91516 1:a5258871b33d 293
jmitc91516 1:a5258871b33d 294 return (float)(m * (double) X) + c;
jmitc91516 1:a5258871b33d 295 }
jmitc91516 1:a5258871b33d 296
jmitc91516 1:a5258871b33d 297 // 'else' ...
jmitc91516 1:a5258871b33d 298 if(theGraphDataSet[graphDataSetActualLength - 1].X < X) {
jmitc91516 1:a5258871b33d 299
jmitc91516 1:a5258871b33d 300 // Required point is after the end of our array
jmitc91516 1:a5258871b33d 301
jmitc91516 1:a5258871b33d 302 double X0 = (double) theGraphDataSet[graphDataSetActualLength - 2].X;
jmitc91516 1:a5258871b33d 303 double Y0 = (double) theGraphDataSet[graphDataSetActualLength - 2].Y;
jmitc91516 1:a5258871b33d 304 double X1 = (double) theGraphDataSet[graphDataSetActualLength - 1].X;
jmitc91516 1:a5258871b33d 305 double Y1 = (double) theGraphDataSet[graphDataSetActualLength - 1].Y;
jmitc91516 1:a5258871b33d 306
jmitc91516 1:a5258871b33d 307 double m = (Y1 - Y0) / (X1 - X0);
jmitc91516 1:a5258871b33d 308 double c = Y0 - (m * X0);
jmitc91516 1:a5258871b33d 309
jmitc91516 1:a5258871b33d 310 return (float)(m * (double) X) + c;
jmitc91516 1:a5258871b33d 311 }
jmitc91516 1:a5258871b33d 312
jmitc91516 1:a5258871b33d 313 // 'else' - required data point must either be coincident with one of our data points,
jmitc91516 1:a5258871b33d 314 // or between two of them
jmitc91516 1:a5258871b33d 315 for (int i = 0; i < (graphDataSetActualLength - 1); ++i) {
jmitc91516 1:a5258871b33d 316
jmitc91516 1:a5258871b33d 317 if(theGraphDataSet[i].X == X) {
jmitc91516 1:a5258871b33d 318 // We already have a data point at the specified X coordinate
jmitc91516 1:a5258871b33d 319
jmitc91516 1:a5258871b33d 320 return theGraphDataSet[i].Y;
jmitc91516 1:a5258871b33d 321 }
jmitc91516 1:a5258871b33d 322
jmitc91516 1:a5258871b33d 323 // 'else'
jmitc91516 1:a5258871b33d 324 if(theGraphDataSet[i + 1].X == X) {
jmitc91516 1:a5258871b33d 325 // We already have a data point at the specified X coordinate
jmitc91516 1:a5258871b33d 326
jmitc91516 1:a5258871b33d 327 return theGraphDataSet[i + 1].Y;
jmitc91516 1:a5258871b33d 328 }
jmitc91516 1:a5258871b33d 329
jmitc91516 1:a5258871b33d 330 // 'else'
jmitc91516 1:a5258871b33d 331 if(theGraphDataSet[i + 1].X > X) {
jmitc91516 1:a5258871b33d 332
jmitc91516 1:a5258871b33d 333 // We must interpolate between two data points
jmitc91516 1:a5258871b33d 334
jmitc91516 1:a5258871b33d 335 double xValue = (double) X;
jmitc91516 1:a5258871b33d 336
jmitc91516 1:a5258871b33d 337 double X0 = (double) theGraphDataSet[i].X;
jmitc91516 1:a5258871b33d 338 double Y0 = (double) theGraphDataSet[i].Y;
jmitc91516 1:a5258871b33d 339 double X1 = (double) theGraphDataSet[i + 1].X;
jmitc91516 1:a5258871b33d 340 double Y1 = (double) theGraphDataSet[i + 1].Y;
jmitc91516 1:a5258871b33d 341
jmitc91516 1:a5258871b33d 342 double m = (Y1 - Y0) / (X1 - X0);
jmitc91516 1:a5258871b33d 343 double c = Y0 - (m * X0);
jmitc91516 1:a5258871b33d 344
jmitc91516 1:a5258871b33d 345 return (float)((m * xValue) + c);
jmitc91516 1:a5258871b33d 346 }
jmitc91516 1:a5258871b33d 347 }
jmitc91516 1:a5258871b33d 348 }
jmitc91516 1:a5258871b33d 349
jmitc91516 1:a5258871b33d 350 // 'else' we only have one datapoint - return its Y coord
jmitc91516 1:a5258871b33d 351 // (i.e. treat the 'graph' as a straight line)
jmitc91516 1:a5258871b33d 352 return theGraphDataSet[0].Y;
jmitc91516 1:a5258871b33d 353 }
jmitc91516 1:a5258871b33d 354
jmitc91516 1:a5258871b33d 355 // 'else' we have no existing data points to interpolate
jmitc91516 1:a5258871b33d 356 return 0.0f;
jmitc91516 1:a5258871b33d 357 }
jmitc91516 1:a5258871b33d 358
jmitc91516 1:a5258871b33d 359 /*
jmitc91516 1:a5258871b33d 360 Copy our current 'actual' floating point data array,
jmitc91516 1:a5258871b33d 361 to a GuiLib_GraphDataPoint array, as required by the easyGUI Graph.
jmitc91516 1:a5258871b33d 362
jmitc91516 1:a5258871b33d 363 The actual floating point data is always in minutes, but may well have a fractional part,
jmitc91516 1:a5258871b33d 364 since the GC measures time, in effect, in units of 0.1 minute. The GuiLib_GraphDataPoint
jmitc91516 1:a5258871b33d 365 structure, however, uses integers, so we copy the actual data to integer numbers
jmitc91516 1:a5258871b33d 366 either in minutes or seconds, as specified by the caller. We convert the original
jmitc91516 1:a5258871b33d 367 floating point values to integers by rounding them, using our static function
jmitc91516 1:a5258871b33d 368 'ConvertFloatingDataPointToGuiLibGraphDataPoint'.
jmitc91516 1:a5258871b33d 369
jmitc91516 1:a5258871b33d 370 If the caller wants minutes to be the time unit, we may well end up with multiple points
jmitc91516 1:a5258871b33d 371 at the same X (i.e. time) coordinate - guard against this by combining them into one point
jmitc91516 1:a5258871b33d 372 whose Y coordinate is the average of the duplicate points. If the caller wants seconds,
jmitc91516 1:a5258871b33d 373 we assume that we cannot possibly have multiple points at the same X coordinate.
jmitc91516 1:a5258871b33d 374
jmitc91516 1:a5258871b33d 375 Note that we pass a pointer to the GuiLib_GraphDataPoint array back to the caller.
jmitc91516 1:a5258871b33d 376 It is up to the caller to delete this array when it is no longer needed.
jmitc91516 1:a5258871b33d 377 ************************************************************************
jmitc91516 1:a5258871b33d 378
jmitc91516 1:a5258871b33d 379 It is also up to the caller to check that the pointer we return is not NULL before using it.
jmitc91516 1:a5258871b33d 380 ********************************************************************************************
jmitc91516 1:a5258871b33d 381
jmitc91516 1:a5258871b33d 382
jmitc91516 1:a5258871b33d 383 Args: the time unit (minutes or seconds) to be used in the copy
jmitc91516 1:a5258871b33d 384 a pointer to an unsigned integer to contain the number of points in the copied array
jmitc91516 1:a5258871b33d 385
jmitc91516 1:a5258871b33d 386 Return value: pointer to the array of GuiLib_GraphDataPoints containing the copied data
jmitc91516 1:a5258871b33d 387
jmitc91516 1:a5258871b33d 388 */
jmitc91516 1:a5258871b33d 389 GuiLib_GraphDataPoint* GuiLibGraphDataSet::GetGraphDataPointCopy(TimeUnit timeUnit, GuiConst_INT16U *countOfCopiedPoints)
jmitc91516 1:a5258871b33d 390 {
jmitc91516 1:a5258871b33d 391 // Remember that our 'native' data points are in time (i.e. X coordinate) units of 0.1 minute
jmitc91516 1:a5258871b33d 392
jmitc91516 1:a5258871b33d 393 // First, a straight copy, rounding the X coordinate to the unit specified
jmitc91516 1:a5258871b33d 394 GuiLib_GraphDataPoint* graphDataSetCopy = new GuiLib_GraphDataPoint[graphDataSetActualLength];
jmitc91516 1:a5258871b33d 395
jmitc91516 1:a5258871b33d 396 if(graphDataSetCopy == NULL) {
jmitc91516 1:a5258871b33d 397
jmitc91516 1:a5258871b33d 398 // Failed to allocate the memory we need
jmitc91516 1:a5258871b33d 399
jmitc91516 1:a5258871b33d 400 *countOfCopiedPoints = 0;
jmitc91516 1:a5258871b33d 401 return NULL;
jmitc91516 1:a5258871b33d 402 }
jmitc91516 1:a5258871b33d 403
jmitc91516 1:a5258871b33d 404 // 'else' memory allocated - continue
jmitc91516 1:a5258871b33d 405
jmitc91516 1:a5258871b33d 406 for(int index = 0; index < graphDataSetActualLength; ++index) {
jmitc91516 1:a5258871b33d 407 ConvertFloatingDataPointToGuiLibGraphDataPoint(&graphDataSetCopy[index], theGraphDataSet[index], timeUnit);
jmitc91516 1:a5258871b33d 408 }
jmitc91516 1:a5258871b33d 409
jmitc91516 1:a5258871b33d 410 if(timeUnit == SECONDS) {
jmitc91516 1:a5258871b33d 411
jmitc91516 1:a5258871b33d 412 // The simple case - since our 'native' data points are in 'units' of 0.1 minute,
jmitc91516 1:a5258871b33d 413 // we cannot have multiple points at the same number of seconds, i.e. with the same X coordinate -
jmitc91516 1:a5258871b33d 414 // so just return the duplicate array, with rounded X and Y coordinate values, that we created above
jmitc91516 1:a5258871b33d 415
jmitc91516 1:a5258871b33d 416 *countOfCopiedPoints = graphDataSetActualLength; // Tell caller how many points there are
jmitc91516 1:a5258871b33d 417 return graphDataSetCopy;
jmitc91516 1:a5258871b33d 418 }
jmitc91516 1:a5258871b33d 419
jmitc91516 1:a5258871b33d 420
jmitc91516 1:a5258871b33d 421 // 'else' must be minutes - now, we must guard against multiple points at the same X coordinate
jmitc91516 1:a5258871b33d 422 // *******************************************************************
jmitc91516 1:a5258871b33d 423
jmitc91516 1:a5258871b33d 424 // Count how many distinct points - i.e. with different X coordinate values - there are
jmitc91516 1:a5258871b33d 425 int pointIndex;
jmitc91516 1:a5258871b33d 426 GuiConst_INT32S lastXCoord = graphDataSetCopy[0].X;
jmitc91516 1:a5258871b33d 427 int countOfDistinctPoints = 1; // We have already looked at the first point
jmitc91516 1:a5258871b33d 428 for(pointIndex = 1; pointIndex < graphDataSetActualLength; ++pointIndex) {
jmitc91516 1:a5258871b33d 429 if(graphDataSetCopy[pointIndex].X > lastXCoord) {
jmitc91516 1:a5258871b33d 430 ++countOfDistinctPoints;
jmitc91516 1:a5258871b33d 431 lastXCoord = graphDataSetCopy[pointIndex].X;
jmitc91516 1:a5258871b33d 432 }
jmitc91516 1:a5258871b33d 433 // 'else' this point has the same X coordinate as the previous one
jmitc91516 1:a5258871b33d 434 }
jmitc91516 1:a5258871b33d 435
jmitc91516 1:a5258871b33d 436 // Now allocate an array to contain that number of points
jmitc91516 1:a5258871b33d 437 GuiLib_GraphDataPoint* graphDataSetMinutesCopy = new GuiLib_GraphDataPoint[countOfDistinctPoints];
jmitc91516 1:a5258871b33d 438
jmitc91516 1:a5258871b33d 439 if(graphDataSetMinutesCopy == NULL) {
jmitc91516 1:a5258871b33d 440 // Failed to allocate the memory we need
jmitc91516 1:a5258871b33d 441 delete [] graphDataSetCopy;
jmitc91516 1:a5258871b33d 442
jmitc91516 1:a5258871b33d 443 *countOfCopiedPoints = 0;
jmitc91516 1:a5258871b33d 444 return NULL;
jmitc91516 1:a5258871b33d 445 }
jmitc91516 1:a5258871b33d 446
jmitc91516 1:a5258871b33d 447 // 'else' memory allocated - continue
jmitc91516 1:a5258871b33d 448
jmitc91516 1:a5258871b33d 449 // When we find two or more points with the same X coordinate in the original dataset copy array,
jmitc91516 1:a5258871b33d 450 // we create one point in the 'minutes' array, whose Y coordinate is the average of the Y coordinates
jmitc91516 1:a5258871b33d 451 // of the original points
jmitc91516 1:a5258871b33d 452
jmitc91516 1:a5258871b33d 453 graphDataSetMinutesCopy[0] = graphDataSetCopy[0];
jmitc91516 1:a5258871b33d 454 int minutesPointIndex = 0;
jmitc91516 1:a5258871b33d 455 lastXCoord = graphDataSetCopy[0].X;
jmitc91516 1:a5258871b33d 456 int multiPointCount = 1; // Count of the number of points at the current X coordinate
jmitc91516 1:a5258871b33d 457 for(pointIndex = 1; pointIndex < graphDataSetActualLength; ++pointIndex) {
jmitc91516 1:a5258871b33d 458 if(graphDataSetCopy[pointIndex].X > lastXCoord) {
jmitc91516 1:a5258871b33d 459
jmitc91516 1:a5258871b33d 460 if(multiPointCount > 1) {
jmitc91516 1:a5258871b33d 461 // Set the minutes copy to the average of the Y values we have accumulated
jmitc91516 1:a5258871b33d 462 graphDataSetMinutesCopy[minutesPointIndex].Y /= multiPointCount;
jmitc91516 1:a5258871b33d 463 multiPointCount = 1;
jmitc91516 1:a5258871b33d 464 }
jmitc91516 1:a5258871b33d 465
jmitc91516 1:a5258871b33d 466 ++minutesPointIndex;
jmitc91516 1:a5258871b33d 467 graphDataSetMinutesCopy[minutesPointIndex] = graphDataSetCopy[pointIndex];
jmitc91516 1:a5258871b33d 468
jmitc91516 1:a5258871b33d 469 lastXCoord = graphDataSetCopy[pointIndex].X;
jmitc91516 1:a5258871b33d 470
jmitc91516 1:a5258871b33d 471 } else {
jmitc91516 1:a5258871b33d 472
jmitc91516 1:a5258871b33d 473 // This point must have the same X coordinate as the previous one -
jmitc91516 1:a5258871b33d 474 // start accumulating the Y values, ready to take the average
jmitc91516 1:a5258871b33d 475 graphDataSetMinutesCopy[minutesPointIndex].Y += graphDataSetCopy[pointIndex].Y;
jmitc91516 1:a5258871b33d 476 ++multiPointCount;
jmitc91516 1:a5258871b33d 477 }
jmitc91516 1:a5258871b33d 478 }
jmitc91516 1:a5258871b33d 479
jmitc91516 1:a5258871b33d 480 if(multiPointCount > 1) {
jmitc91516 1:a5258871b33d 481 graphDataSetMinutesCopy[minutesPointIndex].Y /= multiPointCount;
jmitc91516 1:a5258871b33d 482 }
jmitc91516 1:a5258871b33d 483
jmitc91516 1:a5258871b33d 484 delete [] graphDataSetCopy; // No longer needed
jmitc91516 1:a5258871b33d 485
jmitc91516 1:a5258871b33d 486 *countOfCopiedPoints = countOfDistinctPoints; // Tell caller how many points there are in the copied array
jmitc91516 1:a5258871b33d 487 return graphDataSetMinutesCopy; // Caller wants this array, not the original copy
jmitc91516 1:a5258871b33d 488 }
jmitc91516 1:a5258871b33d 489
jmitc91516 1:a5258871b33d 490
jmitc91516 1:a5258871b33d 491 /*
jmitc91516 1:a5258871b33d 492 Copy our current 'actual' floating point data array,
jmitc91516 1:a5258871b33d 493 to a GuiLib_GraphDataPoint array, as required by the easyGUI Graph.
jmitc91516 1:a5258871b33d 494
jmitc91516 1:a5258871b33d 495 The actual floating point data is always in minutes, but may well have a fractional part,
jmitc91516 1:a5258871b33d 496 since the GC measures time, in effect, in units of 0.1 minute - and we have time as the X axis.
jmitc91516 1:a5258871b33d 497 The GuiLib_GraphDataPoint structure, however, uses integers, so before copying the actual data
jmitc91516 1:a5258871b33d 498 to integer numbers, we multiply the X values by 10.0.
jmitc91516 1:a5258871b33d 499
jmitc91516 1:a5258871b33d 500 Note that we pass a pointer to the GuiLib_GraphDataPoint array back to the caller.
jmitc91516 1:a5258871b33d 501 It is up to the caller to delete this array when it is no longer needed.
jmitc91516 1:a5258871b33d 502 ************************************************************************
jmitc91516 1:a5258871b33d 503
jmitc91516 1:a5258871b33d 504 It is also up to the caller to check that the pointer we return is not NULL before using it.
jmitc91516 1:a5258871b33d 505 ********************************************************************************************
jmitc91516 1:a5258871b33d 506
jmitc91516 1:a5258871b33d 507
jmitc91516 1:a5258871b33d 508 Args: a pointer to an unsigned integer to contain the number of points in the copied array
jmitc91516 1:a5258871b33d 509
jmitc91516 1:a5258871b33d 510 Return value: pointer to the array of GuiLib_GraphDataPoints containing the copied data
jmitc91516 1:a5258871b33d 511
jmitc91516 1:a5258871b33d 512 */
jmitc91516 1:a5258871b33d 513 GuiLib_GraphDataPoint* GuiLibGraphDataSet::GetGraphDataPointCopyInTenthsOfMinutes(float yAxisScaleFactor, GuiConst_INT16U *countOfCopiedPoints)
jmitc91516 1:a5258871b33d 514 {
jmitc91516 1:a5258871b33d 515 GuiLib_GraphDataPoint* graphDataSetCopy = new GuiLib_GraphDataPoint[graphDataSetActualLength];
jmitc91516 1:a5258871b33d 516
jmitc91516 1:a5258871b33d 517 if(graphDataSetCopy == NULL) {
jmitc91516 1:a5258871b33d 518
jmitc91516 1:a5258871b33d 519 // Failed to allocate the memory we need
jmitc91516 1:a5258871b33d 520
jmitc91516 1:a5258871b33d 521 *countOfCopiedPoints = 0;
jmitc91516 1:a5258871b33d 522 return NULL;
jmitc91516 1:a5258871b33d 523 }
jmitc91516 1:a5258871b33d 524
jmitc91516 1:a5258871b33d 525 // 'else' memory allocated - continue...
jmitc91516 1:a5258871b33d 526
jmitc91516 1:a5258871b33d 527 // The 'floor' mathematical function expects a double as its argument
jmitc91516 1:a5258871b33d 528 double doubleX;
jmitc91516 1:a5258871b33d 529 double doubleY;
jmitc91516 1:a5258871b33d 530
jmitc91516 1:a5258871b33d 531 for(int index = 0; index < graphDataSetActualLength; ++index) {
jmitc91516 1:a5258871b33d 532
jmitc91516 1:a5258871b33d 533 // 'floor' math(s) function requires a double argument, not float
jmitc91516 1:a5258871b33d 534 doubleX = ((double)theGraphDataSet[index].X) * 10.0;
jmitc91516 1:a5258871b33d 535 doubleY = (double)(theGraphDataSet[index].Y * yAxisScaleFactor);
jmitc91516 1:a5258871b33d 536
jmitc91516 1:a5258871b33d 537 // Round, don't truncate
jmitc91516 1:a5258871b33d 538 graphDataSetCopy[index].X = (GuiConst_INT32S) floor(doubleX + 0.5);
jmitc91516 1:a5258871b33d 539 graphDataSetCopy[index].Y = (GuiConst_INT32S) floor(doubleY + 0.5);
jmitc91516 1:a5258871b33d 540 }
jmitc91516 1:a5258871b33d 541
jmitc91516 1:a5258871b33d 542 *countOfCopiedPoints = graphDataSetActualLength; // Tell caller how many points there are
jmitc91516 1:a5258871b33d 543 return graphDataSetCopy;
jmitc91516 1:a5258871b33d 544 }
jmitc91516 1:a5258871b33d 545
jmitc91516 1:a5258871b33d 546
jmitc91516 1:a5258871b33d 547 /*
jmitc91516 1:a5258871b33d 548 Sets another GuiLibGraphDataSet object to a 'partial copy' of this one.
jmitc91516 1:a5258871b33d 549 A 'partial copy' is a copy that begins at the specified X start coordinate, and ends at the specified X end coordinate.
jmitc91516 1:a5258871b33d 550 We copy all of our coordinate pairs that lie between those two X values to the destination.
jmitc91516 1:a5258871b33d 551 If we do not have a coordinate pair exactly at the specified X start coordinate, we generate one
jmitc91516 1:a5258871b33d 552 using our 'GetYCoordAtXCoord' member function. The same applies to the end X coordinate.
jmitc91516 1:a5258871b33d 553
jmitc91516 1:a5258871b33d 554 Args: the X coordinate at which to start the copy
jmitc91516 1:a5258871b33d 555 the X coordinate at which to end the copy
jmitc91516 1:a5258871b33d 556 a pointer to the GuiLibGraphDataSet object which is to be the copy destination
jmitc91516 1:a5258871b33d 557 */
jmitc91516 1:a5258871b33d 558 void GuiLibGraphDataSet::MakePartialCopy(float startXCoord, float endXCoord, GuiLibGraphDataSet* copyDestination)
jmitc91516 1:a5258871b33d 559 {
jmitc91516 1:a5258871b33d 560 // First, clear the copy destination of any existing data
jmitc91516 1:a5258871b33d 561 copyDestination->ClearData();
jmitc91516 1:a5258871b33d 562
jmitc91516 1:a5258871b33d 563
jmitc91516 1:a5258871b33d 564 // If the end coord is less than the start coord, do nothing
jmitc91516 1:a5258871b33d 565 // - leave data clear
jmitc91516 1:a5258871b33d 566 if(endXCoord < startXCoord) {
jmitc91516 1:a5258871b33d 567 return;
jmitc91516 1:a5258871b33d 568 }
jmitc91516 1:a5258871b33d 569
jmitc91516 1:a5258871b33d 570 if(graphDataSetActualLength > 0) {
jmitc91516 1:a5258871b33d 571
jmitc91516 1:a5258871b33d 572 int pointIndex;
jmitc91516 1:a5258871b33d 573 for (pointIndex = 0; pointIndex < graphDataSetActualLength; ++pointIndex) {
jmitc91516 1:a5258871b33d 574
jmitc91516 1:a5258871b33d 575 if(theGraphDataSet[pointIndex].X >= startXCoord) {
jmitc91516 1:a5258871b33d 576 break;
jmitc91516 1:a5258871b33d 577 }
jmitc91516 1:a5258871b33d 578 }
jmitc91516 1:a5258871b33d 579
jmitc91516 1:a5258871b33d 580 if(pointIndex < graphDataSetActualLength) {
jmitc91516 1:a5258871b33d 581 if (theGraphDataSet[pointIndex].X > startXCoord) {
jmitc91516 1:a5258871b33d 582
jmitc91516 1:a5258871b33d 583 // Need to add a start point at the specified start X coord
jmitc91516 1:a5258871b33d 584 copyDestination->AddDataPoint(startXCoord, GetYCoordAtXCoord(startXCoord));
jmitc91516 1:a5258871b33d 585
jmitc91516 1:a5258871b33d 586 } // 'else' the start point already has the correct X coordinate - no need to add another
jmitc91516 1:a5258871b33d 587
jmitc91516 1:a5258871b33d 588 // pointIndex already has the correct start value
jmitc91516 1:a5258871b33d 589 for (; pointIndex < graphDataSetActualLength; ++pointIndex) {
jmitc91516 1:a5258871b33d 590
jmitc91516 1:a5258871b33d 591 if(theGraphDataSet[pointIndex].X <= endXCoord) {
jmitc91516 1:a5258871b33d 592 copyDestination->AddDataPoint(theGraphDataSet[pointIndex].X, theGraphDataSet[pointIndex].Y);
jmitc91516 1:a5258871b33d 593 } else {
jmitc91516 1:a5258871b33d 594 break;
jmitc91516 1:a5258871b33d 595 }
jmitc91516 1:a5258871b33d 596 }
jmitc91516 1:a5258871b33d 597
jmitc91516 1:a5258871b33d 598 if (theGraphDataSet[pointIndex - 1].X < endXCoord) {
jmitc91516 1:a5258871b33d 599
jmitc91516 1:a5258871b33d 600 // Need to add a final point at the end X coord
jmitc91516 1:a5258871b33d 601 copyDestination->AddDataPoint(endXCoord, GetYCoordAtXCoord(endXCoord));
jmitc91516 1:a5258871b33d 602
jmitc91516 1:a5258871b33d 603 } // 'else' the final point already has the correct X coordinate - no need to add another
jmitc91516 1:a5258871b33d 604
jmitc91516 1:a5258871b33d 605 } // 'else' we have no points above the start X coordinate - nothing to copy
jmitc91516 1:a5258871b33d 606
jmitc91516 1:a5258871b33d 607 } // 'else' we have no points to copy
jmitc91516 1:a5258871b33d 608 }
jmitc91516 1:a5258871b33d 609
jmitc91516 1:a5258871b33d 610 /*
jmitc91516 1:a5258871b33d 611 Sets another GuiLibGraphDataSet object to an 'interpolated partial copy' of this one.
jmitc91516 1:a5258871b33d 612 This is a copy that starts at a specified X coordinate and finishes at another specified X coordinate,
jmitc91516 1:a5258871b33d 613 and has a specified interval between X coordinates. This will, in general, require interpolating
jmitc91516 1:a5258871b33d 614 between our existing data points.
jmitc91516 1:a5258871b33d 615
jmitc91516 1:a5258871b33d 616 Args: the X coordinate at which to start
jmitc91516 1:a5258871b33d 617 the X coordinate at which to finish
jmitc91516 1:a5258871b33d 618 the X interval - i.e. the interval between X coords
jmitc91516 1:a5258871b33d 619 a pointer to the GuiLibGraphDataSet object which is to be the copy destination
jmitc91516 1:a5258871b33d 620 */
jmitc91516 1:a5258871b33d 621 void GuiLibGraphDataSet::MakeInterpolatedPartialCopy(float startXCoord, float endXCoord, float xInterval, GuiLibGraphDataSet* copyDestination)
jmitc91516 1:a5258871b33d 622 {
jmitc91516 1:a5258871b33d 623 // First, clear the copy destination of any existing data
jmitc91516 1:a5258871b33d 624 copyDestination->ClearData();
jmitc91516 1:a5258871b33d 625
jmitc91516 1:a5258871b33d 626 // Let the for loop limits take care of whether the start and end X coordinates are in the correct order
jmitc91516 1:a5258871b33d 627
jmitc91516 1:a5258871b33d 628 // Now copy/generate the actual points
jmitc91516 1:a5258871b33d 629 float xCoord;
jmitc91516 1:a5258871b33d 630 float endLimit = endXCoord + (xInterval / 2.0f); // Should just be 'endXCoord' - but allow for floating point rounding,
jmitc91516 1:a5258871b33d 631 // otherwise we may omit the last point
jmitc91516 1:a5258871b33d 632 for (xCoord = startXCoord; xCoord <= endLimit; xCoord += xInterval) {
jmitc91516 1:a5258871b33d 633 copyDestination->AddDataPoint(xCoord, GetYCoordAtXCoord(xCoord));
jmitc91516 1:a5258871b33d 634 }
jmitc91516 1:a5258871b33d 635 }
jmitc91516 1:a5258871b33d 636
jmitc91516 1:a5258871b33d 637 /*
jmitc91516 1:a5258871b33d 638 Sets another GuiLibGraphDataSet object to an 'interpolated partial copy' of this one.
jmitc91516 1:a5258871b33d 639 This is a copy that starts at a specified X coordinate and finishes at another specified X coordinate,
jmitc91516 1:a5258871b33d 640 and has a specified interval between X coordinates. This will, in general, require interpolating
jmitc91516 1:a5258871b33d 641 between our existing data points.
jmitc91516 1:a5258871b33d 642
jmitc91516 1:a5258871b33d 643 Unlike the original 'MakeInterpolatedPartialCopy' above, this guarantees to add a final point at the end
jmitc91516 1:a5258871b33d 644 of the copy range, whether this makes an exact interval or not. This means that, in a profile where
jmitc91516 1:a5258871b33d 645 the 'interpolated partial copy' is displayed as a bar chart underneath a line (created using the
jmitc91516 1:a5258871b33d 646 'MakePartialCopy' function), we are guaranteed to have a bar at the exact end of the line -
jmitc91516 1:a5258871b33d 647 it will not overhang empty space.
jmitc91516 1:a5258871b33d 648
jmitc91516 1:a5258871b33d 649 Args: the X coordinate at which to start
jmitc91516 1:a5258871b33d 650 the X coordinate at which to finish
jmitc91516 1:a5258871b33d 651 the X interval - i.e. the interval between X coords
jmitc91516 1:a5258871b33d 652 a pointer to the GuiLibGraphDataSet object which is to be the copy destination
jmitc91516 1:a5258871b33d 653 */
jmitc91516 1:a5258871b33d 654 void GuiLibGraphDataSet::MakeInterpolatedPartialCopyWithFinalPoint(float startXCoord, float endXCoord, float xInterval, GuiLibGraphDataSet* copyDestination)
jmitc91516 1:a5258871b33d 655 {
jmitc91516 1:a5258871b33d 656 // First, clear the copy destination of any existing data
jmitc91516 1:a5258871b33d 657 copyDestination->ClearData();
jmitc91516 1:a5258871b33d 658
jmitc91516 1:a5258871b33d 659 // Let the for loop limits take care of whether the start and end X coordinates are in the correct order
jmitc91516 1:a5258871b33d 660
jmitc91516 1:a5258871b33d 661 // Now copy/generate the actual points
jmitc91516 1:a5258871b33d 662 float xCoord;
jmitc91516 1:a5258871b33d 663 bool needFinalPoint = true;
jmitc91516 1:a5258871b33d 664 for (xCoord = startXCoord; xCoord <= endXCoord; xCoord += xInterval) {
jmitc91516 1:a5258871b33d 665 copyDestination->AddDataPoint(xCoord, GetYCoordAtXCoord(xCoord));
jmitc91516 1:a5258871b33d 666
jmitc91516 1:a5258871b33d 667 if(xCoord == endXCoord) {
jmitc91516 1:a5258871b33d 668 needFinalPoint = false;
jmitc91516 1:a5258871b33d 669 }
jmitc91516 1:a5258871b33d 670 }
jmitc91516 1:a5258871b33d 671
jmitc91516 1:a5258871b33d 672 if(needFinalPoint) {
jmitc91516 1:a5258871b33d 673 // We need to add a final point at the exact end of the copy range
jmitc91516 1:a5258871b33d 674 copyDestination->AddDataPoint(endXCoord, GetYCoordAtXCoord(endXCoord));
jmitc91516 1:a5258871b33d 675 }
jmitc91516 1:a5258871b33d 676 }
jmitc91516 1:a5258871b33d 677
jmitc91516 1:a5258871b33d 678 /*
jmitc91516 1:a5258871b33d 679 Gets the current temperature for a particular component.
jmitc91516 1:a5258871b33d 680
jmitc91516 1:a5258871b33d 681 Args: the GC command to get the temperature for that component
jmitc91516 1:a5258871b33d 682 the usbDevice and usbHostGC instances corresponding to the GC
jmitc91516 1:a5258871b33d 683
jmitc91516 1:a5258871b33d 684 Returns the current temperature of the component as a floating-point value, in degrees C.
jmitc91516 1:a5258871b33d 685 */
jmitc91516 1:a5258871b33d 686 float GuiLibGraphDataSet::GetComponentTemperature(char *cmd, USBDeviceConnected* usbDevice, USBHostGC* usbHostGC)
jmitc91516 1:a5258871b33d 687 {
jmitc91516 1:a5258871b33d 688 // Guard against simultaneous calls to usbHostGC->SetDeviceReport -
jmitc91516 1:a5258871b33d 689 // it is not re-entrant (and nor is the GC)
jmitc91516 1:a5258871b33d 690 while(usbHostGC->ExecutingSetDeviceReport()) {}
jmitc91516 1:a5258871b33d 691
jmitc91516 1:a5258871b33d 692 char response[50];
jmitc91516 1:a5258871b33d 693 usbHostGC->SetDeviceReport(usbDevice, cmd, response);
jmitc91516 1:a5258871b33d 694 // We expect a response like this: "Dxxx1234" - temp in units of 1 deg c
jmitc91516 1:a5258871b33d 695
jmitc91516 1:a5258871b33d 696 float retVal;
jmitc91516 1:a5258871b33d 697
jmitc91516 1:a5258871b33d 698 // But check for "EPKT" first
jmitc91516 1:a5258871b33d 699 if(response[0] == 'E') {
jmitc91516 1:a5258871b33d 700 retVal = -1.0f; // ** Caller must check for this **
jmitc91516 1:a5258871b33d 701 } else {
jmitc91516 1:a5258871b33d 702 sscanf(&response[4], "%f", &retVal);
jmitc91516 1:a5258871b33d 703 }
jmitc91516 1:a5258871b33d 704
jmitc91516 1:a5258871b33d 705 return retVal;
jmitc91516 1:a5258871b33d 706 }
jmitc91516 1:a5258871b33d 707
jmitc91516 1:a5258871b33d 708 /*
jmitc91516 1:a5258871b33d 709 Gets, and returns, the current column temperature.
jmitc91516 1:a5258871b33d 710
jmitc91516 1:a5258871b33d 711 Returns the current column temperature as a floating-point value, in degrees C.
jmitc91516 1:a5258871b33d 712 */
jmitc91516 1:a5258871b33d 713 float GuiLibGraphDataSet::GetColumnTemperature(USBDeviceConnected* usbDevice, USBHostGC* usbHostGC)
jmitc91516 1:a5258871b33d 714 {
jmitc91516 1:a5258871b33d 715 //#define GCOL_VALUE_IN_TENTHS_OF_A_DEGREE
jmitc91516 1:a5258871b33d 716 #ifdef GCOL_VALUE_IN_TENTHS_OF_A_DEGREE
jmitc91516 1:a5258871b33d 717 // This value is actually in tenths of a degree, not whole degrees as stated above
jmitc91516 1:a5258871b33d 718 return ((GetComponentTemperature("GCOL", usbDevice, usbHostGC)) * 0.1f);
jmitc91516 1:a5258871b33d 719 #undef GCOL_VALUE_IN_TENTHS_OF_A_DEGREE
jmitc91516 1:a5258871b33d 720 #else
jmitc91516 1:a5258871b33d 721 return GetComponentTemperature("GCOL", usbDevice, usbHostGC);
jmitc91516 1:a5258871b33d 722 #endif
jmitc91516 1:a5258871b33d 723 }
jmitc91516 1:a5258871b33d 724
jmitc91516 1:a5258871b33d 725 /*
jmitc91516 1:a5258871b33d 726 Gets, and returns, the current injector temperature.
jmitc91516 1:a5258871b33d 727
jmitc91516 1:a5258871b33d 728 Returns the current injector temperature as a floating-point value, in degrees C.
jmitc91516 1:a5258871b33d 729 */
jmitc91516 1:a5258871b33d 730 float GuiLibGraphDataSet::GetInjectorTemperature(USBDeviceConnected* usbDevice, USBHostGC* usbHostGC)
jmitc91516 1:a5258871b33d 731 {
jmitc91516 1:a5258871b33d 732 //#define GINJ_VALUE_IN_TENTHS_OF_A_DEGREE
jmitc91516 1:a5258871b33d 733 #ifdef GINJ_VALUE_IN_TENTHS_OF_A_DEGREE
jmitc91516 1:a5258871b33d 734 // This value is actually in tenths of a degree, not whole degrees as stated above
jmitc91516 1:a5258871b33d 735 return ((GetComponentTemperature("GINJ", usbDevice, usbHostGC)) * 0.1f);
jmitc91516 1:a5258871b33d 736 #undef GINJ_VALUE_IN_TENTHS_OF_A_DEGREE
jmitc91516 1:a5258871b33d 737 #else
jmitc91516 1:a5258871b33d 738 return GetComponentTemperature("GINJ", usbDevice, usbHostGC);
jmitc91516 1:a5258871b33d 739 #endif
jmitc91516 1:a5258871b33d 740 }
jmitc91516 1:a5258871b33d 741
jmitc91516 1:a5258871b33d 742 /*
jmitc91516 1:a5258871b33d 743 Gets, and returns, a time value, obtained using the command passed to it.
jmitc91516 1:a5258871b33d 744 We expect that this value will be returned by the GC in units of 0.1 minute.
jmitc91516 1:a5258871b33d 745
jmitc91516 1:a5258871b33d 746 Args: a pointer to a null-terminated string containing the command to use
jmitc91516 1:a5258871b33d 747 pointers to the USBDevice and USBHost instances corresponding to the GC
jmitc91516 1:a5258871b33d 748
jmitc91516 1:a5258871b33d 749 Note that this code is intended to be as efficient as possible.
jmitc91516 1:a5258871b33d 750
jmitc91516 1:a5258871b33d 751 Returns the required time as a floating-point value, in minutes - i.e. scaled from
jmitc91516 1:a5258871b33d 752 the value returned by the GC.
jmitc91516 1:a5258871b33d 753 */
jmitc91516 1:a5258871b33d 754 float GuiLibGraphDataSet::GetTimeValue(char *cmd, USBDeviceConnected* usbDevice, USBHostGC* usbHostGC)
jmitc91516 1:a5258871b33d 755 {
jmitc91516 1:a5258871b33d 756 // Guard against simultaneous calls to usbHostGC->SetDeviceReport -
jmitc91516 1:a5258871b33d 757 // it is not re-entrant (and nor is the GC)
jmitc91516 1:a5258871b33d 758 while(usbHostGC->ExecutingSetDeviceReport()) {}
jmitc91516 1:a5258871b33d 759
jmitc91516 1:a5258871b33d 760 char buff[10];
jmitc91516 1:a5258871b33d 761 char response[50];
jmitc91516 1:a5258871b33d 762 usbHostGC->SetDeviceReport(usbDevice, cmd, response);
jmitc91516 1:a5258871b33d 763 // We expect a response like this: "Dxxx1234" - time in units of 0.1 minute
jmitc91516 1:a5258871b33d 764
jmitc91516 1:a5258871b33d 765 float retVal;
jmitc91516 1:a5258871b33d 766
jmitc91516 1:a5258871b33d 767 // But check for "EPKT" first
jmitc91516 1:a5258871b33d 768 if(response[0] == 'E') {
jmitc91516 1:a5258871b33d 769 retVal = -1.0f; // ** Caller must check for this **
jmitc91516 1:a5258871b33d 770 } else {
jmitc91516 1:a5258871b33d 771 buff[0] = response[4];
jmitc91516 1:a5258871b33d 772 buff[1] = response[5];
jmitc91516 1:a5258871b33d 773 buff[2] = response[6];
jmitc91516 1:a5258871b33d 774 buff[3] = '.';
jmitc91516 1:a5258871b33d 775 buff[4] = response[7];
jmitc91516 1:a5258871b33d 776
jmitc91516 1:a5258871b33d 777 sscanf(buff, "%f", &retVal);
jmitc91516 1:a5258871b33d 778 }
jmitc91516 1:a5258871b33d 779
jmitc91516 1:a5258871b33d 780 return retVal;
jmitc91516 1:a5258871b33d 781 }
jmitc91516 1:a5258871b33d 782
jmitc91516 1:a5258871b33d 783 /*
jmitc91516 1:a5258871b33d 784 Gets, and returns, the initial hold time.
jmitc91516 1:a5258871b33d 785
jmitc91516 1:a5258871b33d 786 Returns the initial hold time as a floating-point value, in minutes.
jmitc91516 1:a5258871b33d 787 */
jmitc91516 1:a5258871b33d 788 float GuiLibGraphDataSet::GetInitialHoldTime(USBDeviceConnected* usbDevice, USBHostGC* usbHostGC)
jmitc91516 1:a5258871b33d 789 {
jmitc91516 1:a5258871b33d 790 return GetTimeValue("GTIM", usbDevice, usbHostGC);
jmitc91516 1:a5258871b33d 791 }
jmitc91516 1:a5258871b33d 792
jmitc91516 1:a5258871b33d 793 /*
jmitc91516 1:a5258871b33d 794 Gets, and returns, the PTV/injector initial time.
jmitc91516 1:a5258871b33d 795
jmitc91516 1:a5258871b33d 796 Returns the initial time as a floating-point value, in minutes.
jmitc91516 1:a5258871b33d 797 */
jmitc91516 1:a5258871b33d 798 float GuiLibGraphDataSet::GetPTVInitialTime(USBDeviceConnected* usbDevice, USBHostGC* usbHostGC)
jmitc91516 1:a5258871b33d 799 {
jmitc91516 1:a5258871b33d 800 return GetTimeValue("GIPT", usbDevice, usbHostGC);
jmitc91516 1:a5258871b33d 801 }
jmitc91516 1:a5258871b33d 802
jmitc91516 1:a5258871b33d 803 /*
jmitc91516 1:a5258871b33d 804 Gets, and returns, the initial pressure.
jmitc91516 1:a5258871b33d 805
jmitc91516 1:a5258871b33d 806 Note that this code is intended to be as efficient as possible.
jmitc91516 1:a5258871b33d 807
jmitc91516 1:a5258871b33d 808 Returns the initial pressure as a floating-point value, in minutes.
jmitc91516 1:a5258871b33d 809 */
jmitc91516 1:a5258871b33d 810 float GuiLibGraphDataSet::GetInitialPressure(USBDeviceConnected* usbDevice, USBHostGC* usbHostGC)
jmitc91516 1:a5258871b33d 811 {
jmitc91516 1:a5258871b33d 812 // Guard against simultaneous calls to usbHostGC->SetDeviceReport -
jmitc91516 1:a5258871b33d 813 // it is not re-entrant (and nor is the GC)
jmitc91516 1:a5258871b33d 814 while(usbHostGC->ExecutingSetDeviceReport()) {}
jmitc91516 1:a5258871b33d 815
jmitc91516 1:a5258871b33d 816 char buff[10];
jmitc91516 1:a5258871b33d 817 char response[50];
jmitc91516 1:a5258871b33d 818 usbHostGC->SetDeviceReport(usbDevice, "GPRS", response);
jmitc91516 1:a5258871b33d 819 // We expect a response like this: "DPRS1234" - pressure in units of 0.1 psi
jmitc91516 1:a5258871b33d 820
jmitc91516 1:a5258871b33d 821 float retVal;
jmitc91516 1:a5258871b33d 822
jmitc91516 1:a5258871b33d 823 // But check for "EPKT" first
jmitc91516 1:a5258871b33d 824 if(response[0] == 'E') {
jmitc91516 1:a5258871b33d 825 retVal = -1.0f; // ** Caller must check for this **
jmitc91516 1:a5258871b33d 826 } else {
jmitc91516 1:a5258871b33d 827 buff[0] = response[4];
jmitc91516 1:a5258871b33d 828 buff[1] = response[5];
jmitc91516 1:a5258871b33d 829 buff[2] = response[6];
jmitc91516 1:a5258871b33d 830 buff[3] = '.';
jmitc91516 1:a5258871b33d 831 buff[4] = response[7];
jmitc91516 1:a5258871b33d 832
jmitc91516 1:a5258871b33d 833 sscanf(buff, "%f", &retVal);
jmitc91516 1:a5258871b33d 834 }
jmitc91516 1:a5258871b33d 835
jmitc91516 1:a5258871b33d 836 return retVal;
jmitc91516 1:a5258871b33d 837 }
jmitc91516 1:a5258871b33d 838
jmitc91516 1:a5258871b33d 839 /*
jmitc91516 1:a5258871b33d 840 Gets a value from the GC for a particular ramp.
jmitc91516 1:a5258871b33d 841
jmitc91516 1:a5258871b33d 842 All commands that get ramp values from the GC have the form "Gxxr", where "G" means "get",
jmitc91516 1:a5258871b33d 843 the characters "xx" are specific to the command, and "r" is the ramp index, 0 through 9.
jmitc91516 1:a5258871b33d 844 The GC's response will have the form "Dxxrnnnn", where "nnnn" is a four digit value -
jmitc91516 1:a5258871b33d 845 this is the value we want. This function converts that value to a float, and returns it in that form.
jmitc91516 1:a5258871b33d 846 It is up to the caller to convert this into the correct units for the command, including scaling it if necessary.
jmitc91516 1:a5258871b33d 847
jmitc91516 1:a5258871b33d 848 Args: the command to get the required ramp value (the three "Gxx" characters)
jmitc91516 1:a5258871b33d 849 the ramp index (0 to 9 inclusive)
jmitc91516 1:a5258871b33d 850 pointers to the USBDeviceConnected and USBHostGC instances that match the GC
jmitc91516 1:a5258871b33d 851
jmitc91516 1:a5258871b33d 852 Returns the ramp value obtained from the GC, as an (unscaled) floating point value
jmitc91516 1:a5258871b33d 853 */
jmitc91516 1:a5258871b33d 854 float GuiLibGraphDataSet::GetRampValue(char *cmd, int rampIndex, USBDeviceConnected* usbDevice, USBHostGC* usbHostGC)
jmitc91516 1:a5258871b33d 855 {
jmitc91516 1:a5258871b33d 856 // Check command length is valid
jmitc91516 1:a5258871b33d 857 if(strlen(cmd) != 3) {
jmitc91516 1:a5258871b33d 858 return 0.0f;
jmitc91516 1:a5258871b33d 859 }
jmitc91516 1:a5258871b33d 860
jmitc91516 1:a5258871b33d 861 // Now the ramp index
jmitc91516 1:a5258871b33d 862 if((rampIndex < 0) || (rampIndex > 9)) {
jmitc91516 1:a5258871b33d 863 return 0.0f;
jmitc91516 1:a5258871b33d 864 }
jmitc91516 1:a5258871b33d 865
jmitc91516 1:a5258871b33d 866
jmitc91516 1:a5258871b33d 867 char response[GC_MESSAGE_LENGTH+2];
jmitc91516 1:a5258871b33d 868
jmitc91516 1:a5258871b33d 869 // Guard against simultaneous calls to usbHostGC->SetDeviceReport -
jmitc91516 1:a5258871b33d 870 // it is not re-entrant (and nor is the GC)
jmitc91516 1:a5258871b33d 871 while(usbHostGC->ExecutingSetDeviceReport()) {}
jmitc91516 1:a5258871b33d 872
jmitc91516 1:a5258871b33d 873 char buff[100];
jmitc91516 1:a5258871b33d 874 sprintf(buff, "%s%d", cmd, rampIndex);
jmitc91516 1:a5258871b33d 875 usbHostGC->SetDeviceReport(usbDevice, buff, response);
jmitc91516 1:a5258871b33d 876
jmitc91516 1:a5258871b33d 877 float rampValue;
jmitc91516 1:a5258871b33d 878
jmitc91516 1:a5258871b33d 879 // We expect a response of the form "DXXnrrrr", where "XX" is the second and third character of the command,
jmitc91516 1:a5258871b33d 880 // 'n' is the ramp index, and "rrrr" is the required ramp value
jmitc91516 1:a5258871b33d 881
jmitc91516 1:a5258871b33d 882 // But check for "EPKT" first...
jmitc91516 1:a5258871b33d 883 if(response[0] == 'E') {
jmitc91516 1:a5258871b33d 884 rampValue = 0.0f;
jmitc91516 1:a5258871b33d 885 } else {
jmitc91516 1:a5258871b33d 886 sscanf(&response[4], "%f", &rampValue);
jmitc91516 1:a5258871b33d 887 }
jmitc91516 1:a5258871b33d 888
jmitc91516 1:a5258871b33d 889 return rampValue;
jmitc91516 1:a5258871b33d 890 }
jmitc91516 1:a5258871b33d 891
jmitc91516 1:a5258871b33d 892 /*
jmitc91516 1:a5258871b33d 893 Gets the temperature ramp rate for a particular ramp.
jmitc91516 1:a5258871b33d 894
jmitc91516 1:a5258871b33d 895 Args: the ramp index (0 to 9 inclusive)
jmitc91516 1:a5258871b33d 896 pointers to the USBDeviceConnected and USBHostGC instances that match the GC
jmitc91516 1:a5258871b33d 897
jmitc91516 1:a5258871b33d 898 Returns the temperature ramp rate obtained from the GC, in degrees C per minute.
jmitc91516 1:a5258871b33d 899 */
jmitc91516 1:a5258871b33d 900 float GuiLibGraphDataSet::GetTemperatureRampRate(int rampIndex, USBDeviceConnected* usbDevice, USBHostGC* usbHostGC)
jmitc91516 1:a5258871b33d 901 {
jmitc91516 1:a5258871b33d 902 return GetRampValue("GRP", rampIndex, usbDevice, usbHostGC);
jmitc91516 1:a5258871b33d 903 }
jmitc91516 1:a5258871b33d 904
jmitc91516 1:a5258871b33d 905 /*
jmitc91516 1:a5258871b33d 906 Gets the PTV/injector temperature ramp rate for a particular ramp.
jmitc91516 1:a5258871b33d 907
jmitc91516 1:a5258871b33d 908 Args: the ramp index (0 to 9 inclusive)
jmitc91516 1:a5258871b33d 909 pointers to the USBDeviceConnected and USBHostGC instances that match the GC
jmitc91516 1:a5258871b33d 910
jmitc91516 1:a5258871b33d 911 Returns the temperature ramp rate obtained from the GC, in degrees C per minute.
jmitc91516 1:a5258871b33d 912 */
jmitc91516 1:a5258871b33d 913 float GuiLibGraphDataSet::GetPTVTemperatureRampRate(int rampIndex, USBDeviceConnected* usbDevice, USBHostGC* usbHostGC)
jmitc91516 1:a5258871b33d 914 {
jmitc91516 1:a5258871b33d 915 return GetRampValue("GIP", rampIndex, usbDevice, usbHostGC);
jmitc91516 1:a5258871b33d 916 }
jmitc91516 1:a5258871b33d 917
jmitc91516 1:a5258871b33d 918 /*
jmitc91516 1:a5258871b33d 919 Gets the upper temperature for a particular ramp.
jmitc91516 1:a5258871b33d 920
jmitc91516 1:a5258871b33d 921 Args: the ramp index (0 to 9 inclusive)
jmitc91516 1:a5258871b33d 922 pointers to the USBDeviceConnected and USBHostGC instances that match the GC
jmitc91516 1:a5258871b33d 923
jmitc91516 1:a5258871b33d 924 Returns the upper temperature obtained from the GC, in degrees C.
jmitc91516 1:a5258871b33d 925 */
jmitc91516 1:a5258871b33d 926 float GuiLibGraphDataSet::GetRampUpperTemperature(int rampIndex, USBDeviceConnected* usbDevice, USBHostGC* usbHostGC)
jmitc91516 1:a5258871b33d 927 {
jmitc91516 1:a5258871b33d 928 //#define GRC_VALUE_IN_TENTHS_OF_A_DEGREE
jmitc91516 1:a5258871b33d 929 #ifdef GRC_VALUE_IN_TENTHS_OF_A_DEGREE
jmitc91516 1:a5258871b33d 930 // This value is actually in tenths of a degree, not whole degrees as stated above
jmitc91516 1:a5258871b33d 931 return ((GetRampValue("GRC", rampIndex, usbDevice, usbHostGC)) * 0.1f);
jmitc91516 1:a5258871b33d 932 #undef GRC_VALUE_IN_TENTHS_OF_A_DEGREE
jmitc91516 1:a5258871b33d 933 #else
jmitc91516 1:a5258871b33d 934 return GetRampValue("GRC", rampIndex, usbDevice, usbHostGC);
jmitc91516 1:a5258871b33d 935 #endif
jmitc91516 1:a5258871b33d 936 }
jmitc91516 1:a5258871b33d 937
jmitc91516 1:a5258871b33d 938 /*
jmitc91516 1:a5258871b33d 939 Gets the upper temperature for a particular PTV/injector ramp.
jmitc91516 1:a5258871b33d 940
jmitc91516 1:a5258871b33d 941 Args: the ramp index (0 to 9 inclusive)
jmitc91516 1:a5258871b33d 942 pointers to the USBDeviceConnected and USBHostGC instances that match the GC
jmitc91516 1:a5258871b33d 943
jmitc91516 1:a5258871b33d 944 Returns the upper temperature obtained from the GC, in degrees C.
jmitc91516 1:a5258871b33d 945 */
jmitc91516 1:a5258871b33d 946 float GuiLibGraphDataSet::GetPTVRampUpperTemperature(int rampIndex, USBDeviceConnected* usbDevice, USBHostGC* usbHostGC)
jmitc91516 1:a5258871b33d 947 {
jmitc91516 1:a5258871b33d 948 return GetRampValue("GIC", rampIndex, usbDevice, usbHostGC);
jmitc91516 1:a5258871b33d 949 }
jmitc91516 1:a5258871b33d 950
jmitc91516 1:a5258871b33d 951 /*
jmitc91516 1:a5258871b33d 952 Gets the ramp time for a particular ramp.
jmitc91516 1:a5258871b33d 953
jmitc91516 1:a5258871b33d 954 Args: the ramp index (0 to 9 inclusive)
jmitc91516 1:a5258871b33d 955 pointers to the USBDeviceConnected and USBHostGC instances that match the GC
jmitc91516 1:a5258871b33d 956
jmitc91516 1:a5258871b33d 957 Returns the ramp time obtained from the GC, in minutes (actually the GC returns a value in units of 0.1 minute,
jmitc91516 1:a5258871b33d 958 but this function applies that scaling to the value before returning it).
jmitc91516 1:a5258871b33d 959 */
jmitc91516 1:a5258871b33d 960 float GuiLibGraphDataSet::GetRampUpperTime(int rampIndex, USBDeviceConnected* usbDevice, USBHostGC* usbHostGC)
jmitc91516 1:a5258871b33d 961 {
jmitc91516 1:a5258871b33d 962 return ((GetRampValue("GRS", rampIndex, usbDevice, usbHostGC)) * 0.1f);
jmitc91516 1:a5258871b33d 963 }
jmitc91516 1:a5258871b33d 964
jmitc91516 1:a5258871b33d 965 /*
jmitc91516 1:a5258871b33d 966 Gets the ramp time for a particular PTV/injector ramp.
jmitc91516 1:a5258871b33d 967
jmitc91516 1:a5258871b33d 968 Args: the ramp index (0 to 9 inclusive)
jmitc91516 1:a5258871b33d 969 pointers to the USBDeviceConnected and USBHostGC instances that match the GC
jmitc91516 1:a5258871b33d 970
jmitc91516 1:a5258871b33d 971 Returns the ramp time obtained from the GC, in minutes (actually the GC returns a value in units of 0.1 minute,
jmitc91516 1:a5258871b33d 972 but this function applies that scaling to the value before returning it).
jmitc91516 1:a5258871b33d 973 */
jmitc91516 1:a5258871b33d 974 float GuiLibGraphDataSet::GetPTVRampUpperTime(int rampIndex, USBDeviceConnected* usbDevice, USBHostGC* usbHostGC)
jmitc91516 1:a5258871b33d 975 {
jmitc91516 1:a5258871b33d 976 return ((GetRampValue("GIS", rampIndex, usbDevice, usbHostGC)) * 0.1f);
jmitc91516 1:a5258871b33d 977 }
jmitc91516 1:a5258871b33d 978
jmitc91516 1:a5258871b33d 979 /*
jmitc91516 1:a5258871b33d 980 Gets the pressure ramp rate for a particular ramp.
jmitc91516 1:a5258871b33d 981
jmitc91516 1:a5258871b33d 982 Args: the ramp index (0 to 9 inclusive)
jmitc91516 1:a5258871b33d 983 pointers to the USBDeviceConnected and USBHostGC instances that match the GC
jmitc91516 1:a5258871b33d 984
jmitc91516 1:a5258871b33d 985 Returns the pressure ramp rate obtained from the GC, in psi per minute (actually the GC returns a value
jmitc91516 1:a5258871b33d 986 in units of 0.01 psi/min, but this function applies that scaling to the value before returning it).
jmitc91516 1:a5258871b33d 987 */
jmitc91516 1:a5258871b33d 988 float GuiLibGraphDataSet::GetPressureRampRate(int rampIndex, USBDeviceConnected* usbDevice, USBHostGC* usbHostGC)
jmitc91516 1:a5258871b33d 989 {
jmitc91516 1:a5258871b33d 990 return ((GetRampValue("GPR", rampIndex, usbDevice, usbHostGC)) * 0.01f);
jmitc91516 1:a5258871b33d 991 }
jmitc91516 1:a5258871b33d 992
jmitc91516 1:a5258871b33d 993 /*
jmitc91516 1:a5258871b33d 994 Gets the upper pressure for a particular ramp.
jmitc91516 1:a5258871b33d 995
jmitc91516 1:a5258871b33d 996 Args: the ramp index (0 to 9 inclusive)
jmitc91516 1:a5258871b33d 997 pointers to the USBDeviceConnected and USBHostGC instances that match the GC
jmitc91516 1:a5258871b33d 998
jmitc91516 1:a5258871b33d 999 Returns the upper pressure obtained from the GC, in psi (actually the GC returns a value
jmitc91516 1:a5258871b33d 1000 in units of 0.1 psi, but this function applies that scaling to the value before returning it).
jmitc91516 1:a5258871b33d 1001 */
jmitc91516 1:a5258871b33d 1002 float GuiLibGraphDataSet::GetRampUpperPressure(int rampIndex, USBDeviceConnected* usbDevice, USBHostGC* usbHostGC)
jmitc91516 1:a5258871b33d 1003 {
jmitc91516 1:a5258871b33d 1004 return ((GetRampValue("GPU", rampIndex, usbDevice, usbHostGC)) * 0.1f);
jmitc91516 1:a5258871b33d 1005 }
jmitc91516 1:a5258871b33d 1006
jmitc91516 1:a5258871b33d 1007 /*
jmitc91516 1:a5258871b33d 1008 Setup this dataset to match the column ramp temperature vs time values
jmitc91516 1:a5258871b33d 1009 currently set up in the GC.
jmitc91516 1:a5258871b33d 1010
jmitc91516 1:a5258871b33d 1011 Args: - pointers to the USBDeviceConnected and USBHostGC instances that match the GC
jmitc91516 1:a5258871b33d 1012
jmitc91516 1:a5258871b33d 1013 Returns the number of points in the updated dataset.
jmitc91516 1:a5258871b33d 1014 */
jmitc91516 1:a5258871b33d 1015 int GuiLibGraphDataSet::SetupFromColumnTemperatureRampValues(USBDeviceConnected* usbDevice, USBHostGC* usbHostGC)
jmitc91516 1:a5258871b33d 1016 {
jmitc91516 1:a5258871b33d 1017 // First, delete all existing data from this dataset
jmitc91516 1:a5258871b33d 1018 ClearData();
jmitc91516 1:a5258871b33d 1019
jmitc91516 1:a5258871b33d 1020
jmitc91516 1:a5258871b33d 1021 // Now let the AddDataPoint function take care of extending the dataset array, etc
jmitc91516 1:a5258871b33d 1022
jmitc91516 1:a5258871b33d 1023 // First point will be at the current temperature, time zero.
jmitc91516 1:a5258871b33d 1024 // Second point will be at the same temperature, after the initial time.
jmitc91516 1:a5258871b33d 1025
jmitc91516 1:a5258871b33d 1026 float initialTemperature = GetColumnTemperature(usbDevice, usbHostGC);
jmitc91516 1:a5258871b33d 1027 float initialHoldTime = GetInitialHoldTime(usbDevice, usbHostGC);
jmitc91516 1:a5258871b33d 1028
jmitc91516 1:a5258871b33d 1029 AddDataPoint(0, initialTemperature);
jmitc91516 1:a5258871b33d 1030 AddDataPoint(initialHoldTime, initialTemperature);
jmitc91516 1:a5258871b33d 1031 int pointCount = 2;
jmitc91516 1:a5258871b33d 1032
jmitc91516 1:a5258871b33d 1033 // These values are specific to each ramp (index 0 through 9)
jmitc91516 1:a5258871b33d 1034 float temperatureRampRate; // This is the rate at which the GC will increase the column temperature
jmitc91516 1:a5258871b33d 1035 // (if this is zero, this ramp is not used, and nor are any after it -
jmitc91516 1:a5258871b33d 1036 // i.e. the previous ramp was the final one)
jmitc91516 1:a5258871b33d 1037 float rampUpperTemperature; // This is the upper (or "target") temperature
jmitc91516 1:a5258871b33d 1038 float rampUpperTime; // Once the column reaches the upper/target temperature, the GC
jmitc91516 1:a5258871b33d 1039 // will keep it at that temperature for this length of time -
jmitc91516 1:a5258871b33d 1040 // at the end of this, the next ramp will start (unless this is the last one)
jmitc91516 1:a5258871b33d 1041 float rampingTime;
jmitc91516 1:a5258871b33d 1042
jmitc91516 1:a5258871b33d 1043 float totalMethodTime = initialHoldTime;
jmitc91516 1:a5258871b33d 1044
jmitc91516 1:a5258871b33d 1045 float previousRampUpperTemperature = initialTemperature;
jmitc91516 1:a5258871b33d 1046
jmitc91516 1:a5258871b33d 1047 // These are the coordinates we add to the graph dataset
jmitc91516 1:a5258871b33d 1048 float X1, X2;
jmitc91516 1:a5258871b33d 1049 float Y1, Y2;
jmitc91516 1:a5258871b33d 1050
jmitc91516 1:a5258871b33d 1051 #ifdef USE_VERSION_102 // This starts at ramp index 0 - older versions start at 1
jmitc91516 1:a5258871b33d 1052 for (int rampIndex = 0; rampIndex < 10; ++rampIndex) {
jmitc91516 1:a5258871b33d 1053 #else
jmitc91516 1:a5258871b33d 1054 for (int rampIndex = 1; rampIndex < 10; ++rampIndex) {
jmitc91516 1:a5258871b33d 1055 #endif
jmitc91516 1:a5258871b33d 1056 temperatureRampRate = GetTemperatureRampRate(rampIndex, usbDevice, usbHostGC);
jmitc91516 1:a5258871b33d 1057
jmitc91516 1:a5258871b33d 1058 if(temperatureRampRate <= FLT_MIN) { // Avoid rounding errors - do not test for equality with zero
jmitc91516 1:a5258871b33d 1059 // No more ramps
jmitc91516 1:a5258871b33d 1060 break;
jmitc91516 1:a5258871b33d 1061 }
jmitc91516 1:a5258871b33d 1062
jmitc91516 1:a5258871b33d 1063
jmitc91516 1:a5258871b33d 1064 rampUpperTemperature = GetRampUpperTemperature(rampIndex, usbDevice, usbHostGC);
jmitc91516 1:a5258871b33d 1065
jmitc91516 1:a5258871b33d 1066 // Sanity check
jmitc91516 1:a5258871b33d 1067 if(rampUpperTemperature < previousRampUpperTemperature) {
jmitc91516 1:a5258871b33d 1068 // This should never happen. We must have got our temperature units confused (or something) - give up
jmitc91516 1:a5258871b33d 1069 break;
jmitc91516 1:a5258871b33d 1070 }
jmitc91516 1:a5258871b33d 1071
jmitc91516 1:a5258871b33d 1072 rampingTime = (rampUpperTemperature - previousRampUpperTemperature) / temperatureRampRate;
jmitc91516 1:a5258871b33d 1073
jmitc91516 1:a5258871b33d 1074 totalMethodTime += rampingTime;
jmitc91516 1:a5258871b33d 1075
jmitc91516 1:a5258871b33d 1076 X1 = totalMethodTime;
jmitc91516 1:a5258871b33d 1077 Y1 = rampUpperTemperature;
jmitc91516 1:a5258871b33d 1078
jmitc91516 1:a5258871b33d 1079 if(AddDataPoint(X1, Y1)) {
jmitc91516 1:a5258871b33d 1080 ++pointCount;
jmitc91516 1:a5258871b33d 1081 }
jmitc91516 1:a5258871b33d 1082
jmitc91516 1:a5258871b33d 1083
jmitc91516 1:a5258871b33d 1084 rampUpperTime = GetRampUpperTime(rampIndex, usbDevice, usbHostGC);
jmitc91516 1:a5258871b33d 1085
jmitc91516 1:a5258871b33d 1086 if(rampUpperTime > FLT_MIN) { // i.e. > 0 (avoid floating point rounding errors)
jmitc91516 1:a5258871b33d 1087
jmitc91516 1:a5258871b33d 1088 totalMethodTime += rampUpperTime;
jmitc91516 1:a5258871b33d 1089
jmitc91516 1:a5258871b33d 1090 X2 = totalMethodTime;
jmitc91516 1:a5258871b33d 1091 Y2 = rampUpperTemperature;
jmitc91516 1:a5258871b33d 1092
jmitc91516 1:a5258871b33d 1093 if(AddDataPoint(X2, Y2)) {
jmitc91516 1:a5258871b33d 1094 ++pointCount;
jmitc91516 1:a5258871b33d 1095 }
jmitc91516 1:a5258871b33d 1096 }
jmitc91516 1:a5258871b33d 1097 // 'Else' the ramp upper time is zero - we are not holding here -
jmitc91516 1:a5258871b33d 1098 // so do not add a second point (AddDataPoint does not allow
jmitc91516 1:a5258871b33d 1099 // two points at the same X coordinate anyway)
jmitc91516 1:a5258871b33d 1100 // *** See comment [HOLDING INTERVAL] in SetupGasPressureProfileWithTimingsFromColumnMethod ***
jmitc91516 1:a5258871b33d 1101
jmitc91516 1:a5258871b33d 1102 previousRampUpperTemperature = rampUpperTemperature;
jmitc91516 1:a5258871b33d 1103 }
jmitc91516 1:a5258871b33d 1104
jmitc91516 1:a5258871b33d 1105 nonRoundedTotalMethodTime = totalMethodTime;
jmitc91516 1:a5258871b33d 1106
jmitc91516 1:a5258871b33d 1107 return pointCount;
jmitc91516 1:a5258871b33d 1108 }
jmitc91516 1:a5258871b33d 1109
jmitc91516 1:a5258871b33d 1110 /*
jmitc91516 1:a5258871b33d 1111 Setup this dataset to match the ramp pressure vs time values currently set up in the GC.
jmitc91516 1:a5258871b33d 1112 Compares the time values with those for a specified column method, and (assuming the time values
jmitc91516 1:a5258871b33d 1113 should match those for the column method) turns on LED 3 if they do not.
jmitc91516 1:a5258871b33d 1114
jmitc91516 1:a5258871b33d 1115 Args: - pointers to the USBDeviceConnected and USBHostGC instances that match the GC
jmitc91516 1:a5258871b33d 1116 - pointer to a GuiLibGraphDataSet object containing the matching column method
jmitc91516 1:a5258871b33d 1117
jmitc91516 1:a5258871b33d 1118 Returns the number of points in the updated dataset.
jmitc91516 1:a5258871b33d 1119 */
jmitc91516 1:a5258871b33d 1120 int GuiLibGraphDataSet::SetupFromPressureRampValues(USBDeviceConnected* usbDevice, USBHostGC* usbHostGC, GuiLibGraphDataSet* columnMethodDataSet)
jmitc91516 1:a5258871b33d 1121 {
jmitc91516 1:a5258871b33d 1122 // First, delete all existing data from this dataset
jmitc91516 1:a5258871b33d 1123 ClearData();
jmitc91516 1:a5258871b33d 1124
jmitc91516 1:a5258871b33d 1125
jmitc91516 1:a5258871b33d 1126 // Now let the AddDataPoint function take care of extending the dataset array, etc
jmitc91516 1:a5258871b33d 1127
jmitc91516 1:a5258871b33d 1128 // First point will be at the initial pressure, time zero.
jmitc91516 1:a5258871b33d 1129 // Second point will be at the same pressure, after the initial time.
jmitc91516 1:a5258871b33d 1130 float initialPressure = (double) GetInitialPressure(usbDevice, usbHostGC);
jmitc91516 1:a5258871b33d 1131 float initialHoldTime = (double) GetInitialHoldTime(usbDevice, usbHostGC);
jmitc91516 1:a5258871b33d 1132
jmitc91516 1:a5258871b33d 1133 AddDataPoint(0, initialPressure);
jmitc91516 1:a5258871b33d 1134 AddDataPoint(initialHoldTime, initialPressure);
jmitc91516 1:a5258871b33d 1135 int pointCount = 2;
jmitc91516 1:a5258871b33d 1136
jmitc91516 1:a5258871b33d 1137 // These values are specific to each ramp (index 0 through 9)
jmitc91516 1:a5258871b33d 1138 float pressureRampRate; // This is the rate at which the GC will increase the gas pressure
jmitc91516 1:a5258871b33d 1139 // (if this is zero, this ramp is not used, and nor are any after it -
jmitc91516 1:a5258871b33d 1140 // i.e. the previous ramp was the final one)
jmitc91516 1:a5258871b33d 1141 float rampUpperPressure; // This is the upper (or "target") pressure
jmitc91516 1:a5258871b33d 1142 float rampUpperTime; // Once the column reaches the upper/target pressure, the GC
jmitc91516 1:a5258871b33d 1143 // will keep it at that pressure for this length of time -
jmitc91516 1:a5258871b33d 1144 // at the end of this, the next ramp will start (unless this is the last one)
jmitc91516 1:a5258871b33d 1145 float rampingTime;
jmitc91516 1:a5258871b33d 1146
jmitc91516 1:a5258871b33d 1147 float totalMethodTime = initialHoldTime;
jmitc91516 1:a5258871b33d 1148
jmitc91516 1:a5258871b33d 1149 float previousRampUpperPressure = initialPressure;
jmitc91516 1:a5258871b33d 1150
jmitc91516 1:a5258871b33d 1151 // These are the coordinates we add to the graph dataset
jmitc91516 1:a5258871b33d 1152 float X1, X2;
jmitc91516 1:a5258871b33d 1153 float Y1, Y2;
jmitc91516 1:a5258871b33d 1154
jmitc91516 1:a5258871b33d 1155 // These are the corresponding coordinates for the column method
jmitc91516 1:a5258871b33d 1156 float columnX1, columnX2;
jmitc91516 1:a5258871b33d 1157 float columnY1, columnY2;
jmitc91516 1:a5258871b33d 1158
jmitc91516 1:a5258871b33d 1159 #ifdef USE_VERSION_102 // This starts at ramp index 0, older versions start at 1
jmitc91516 1:a5258871b33d 1160 for (int rampIndex = 0; rampIndex < 10; ++rampIndex) {
jmitc91516 1:a5258871b33d 1161 #else
jmitc91516 1:a5258871b33d 1162 for (int rampIndex = 1; rampIndex < 10; ++rampIndex) {
jmitc91516 1:a5258871b33d 1163 #endif
jmitc91516 1:a5258871b33d 1164 pressureRampRate = GetPressureRampRate(rampIndex, usbDevice, usbHostGC);
jmitc91516 1:a5258871b33d 1165
jmitc91516 1:a5258871b33d 1166 if(pressureRampRate <= FLT_MIN) { // Avoid rounding errors - do not test for equality with zero
jmitc91516 1:a5258871b33d 1167 // No more ramps
jmitc91516 1:a5258871b33d 1168 break;
jmitc91516 1:a5258871b33d 1169 }
jmitc91516 1:a5258871b33d 1170
jmitc91516 1:a5258871b33d 1171
jmitc91516 1:a5258871b33d 1172 rampUpperPressure = GetRampUpperPressure(rampIndex, usbDevice, usbHostGC);
jmitc91516 1:a5258871b33d 1173
jmitc91516 1:a5258871b33d 1174 // Sanity check
jmitc91516 1:a5258871b33d 1175 if(rampUpperPressure < previousRampUpperPressure) {
jmitc91516 1:a5258871b33d 1176 // This should never happen. We must have got our pressure units confused (or something) - give up
jmitc91516 1:a5258871b33d 1177 break;
jmitc91516 1:a5258871b33d 1178 }
jmitc91516 1:a5258871b33d 1179
jmitc91516 1:a5258871b33d 1180
jmitc91516 1:a5258871b33d 1181 rampingTime = (rampUpperPressure - previousRampUpperPressure) / pressureRampRate;
jmitc91516 1:a5258871b33d 1182
jmitc91516 1:a5258871b33d 1183 totalMethodTime += rampingTime;
jmitc91516 1:a5258871b33d 1184
jmitc91516 1:a5258871b33d 1185 // Round the floating point values to the nearest integer
jmitc91516 1:a5258871b33d 1186 X1 = totalMethodTime;
jmitc91516 1:a5258871b33d 1187 Y1 = rampUpperPressure;
jmitc91516 1:a5258871b33d 1188
jmitc91516 1:a5258871b33d 1189 if(columnMethodDataSet->GetDataPoint(pointCount, &columnX1, &columnY1)) {
jmitc91516 1:a5258871b33d 1190 if(X1 != columnX1) {
jmitc91516 1:a5258871b33d 1191 // Our time and the corresponding column method time do not match -
jmitc91516 1:a5258871b33d 1192 // indicate error by turning on LED 3, and use the column method value
jmitc91516 1:a5258871b33d 1193 // (the two methods must match)
jmitc91516 1:a5258871b33d 1194 #ifdef USE_LED_FOR_DEBUGGING
jmitc91516 1:a5258871b33d 1195 SetLed4(true);
jmitc91516 1:a5258871b33d 1196 #endif
jmitc91516 1:a5258871b33d 1197 X1 = columnX1;
jmitc91516 1:a5258871b33d 1198 }
jmitc91516 1:a5258871b33d 1199 }
jmitc91516 1:a5258871b33d 1200
jmitc91516 1:a5258871b33d 1201 if(AddDataPoint(X1, Y1)) {
jmitc91516 1:a5258871b33d 1202 ++pointCount;
jmitc91516 1:a5258871b33d 1203 }
jmitc91516 1:a5258871b33d 1204
jmitc91516 1:a5258871b33d 1205
jmitc91516 1:a5258871b33d 1206 rampUpperTime = GetRampUpperTime(rampIndex, usbDevice, usbHostGC);
jmitc91516 1:a5258871b33d 1207
jmitc91516 1:a5258871b33d 1208 totalMethodTime += rampUpperTime;
jmitc91516 1:a5258871b33d 1209
jmitc91516 1:a5258871b33d 1210 X2 = totalMethodTime;
jmitc91516 1:a5258871b33d 1211 Y2 = rampUpperPressure;
jmitc91516 1:a5258871b33d 1212
jmitc91516 1:a5258871b33d 1213 if(columnMethodDataSet->GetDataPoint(pointCount, &columnX2, &columnY2)) {
jmitc91516 1:a5258871b33d 1214 if(X2 != columnX2) {
jmitc91516 1:a5258871b33d 1215 // Our time and the corresponding column method time do not match -
jmitc91516 1:a5258871b33d 1216 // indicate error by turning on LED 3, and use the column method value
jmitc91516 1:a5258871b33d 1217 // (the two methods must match)
jmitc91516 1:a5258871b33d 1218 #ifdef USE_LED_FOR_DEBUGGING
jmitc91516 1:a5258871b33d 1219 SetLed4(true);
jmitc91516 1:a5258871b33d 1220 #endif
jmitc91516 1:a5258871b33d 1221 X2 = columnX2;
jmitc91516 1:a5258871b33d 1222 }
jmitc91516 1:a5258871b33d 1223 }
jmitc91516 1:a5258871b33d 1224
jmitc91516 1:a5258871b33d 1225 if(AddDataPoint(X2, Y2)) {
jmitc91516 1:a5258871b33d 1226 ++pointCount;
jmitc91516 1:a5258871b33d 1227 }
jmitc91516 1:a5258871b33d 1228
jmitc91516 1:a5258871b33d 1229 previousRampUpperPressure = rampUpperPressure;
jmitc91516 1:a5258871b33d 1230 }
jmitc91516 1:a5258871b33d 1231
jmitc91516 1:a5258871b33d 1232 nonRoundedTotalMethodTime = totalMethodTime;
jmitc91516 1:a5258871b33d 1233
jmitc91516 1:a5258871b33d 1234 #ifdef USE_LED_FOR_DEBUGGING
jmitc91516 1:a5258871b33d 1235 // Done with LED 4
jmitc91516 1:a5258871b33d 1236 SetLed4(false);
jmitc91516 1:a5258871b33d 1237 #endif
jmitc91516 1:a5258871b33d 1238 return pointCount;
jmitc91516 1:a5258871b33d 1239 }
jmitc91516 1:a5258871b33d 1240
jmitc91516 1:a5258871b33d 1241 /*
jmitc91516 1:a5258871b33d 1242 Setup this dataset to give a injector temperature profile that matches a column method.
jmitc91516 1:a5258871b33d 1243 This will show a constant injector temperature for the same length of time
jmitc91516 1:a5258871b33d 1244 as the specified column method.
jmitc91516 1:a5258871b33d 1245
jmitc91516 1:a5258871b33d 1246 Args: - pointers to the USBDeviceConnected and USBHostGC instances that match the GC
jmitc91516 1:a5258871b33d 1247 - pointer to a GuiLibGraphDataSet object containing the matching column method
jmitc91516 1:a5258871b33d 1248
jmitc91516 1:a5258871b33d 1249 Returns the number of points in the updated dataset (this will always be 2).
jmitc91516 1:a5258871b33d 1250 */
jmitc91516 1:a5258871b33d 1251 int GuiLibGraphDataSet::SetupInjectorTemperatureProfileToMatchColumnMethod(USBDeviceConnected* usbDevice, USBHostGC* usbHostGC, GuiLibGraphDataSet* columnMethodDataSet)
jmitc91516 1:a5258871b33d 1252 {
jmitc91516 1:a5258871b33d 1253 // First, delete all existing data from this dataset
jmitc91516 1:a5258871b33d 1254 ClearData();
jmitc91516 1:a5258871b33d 1255
jmitc91516 1:a5258871b33d 1256
jmitc91516 1:a5258871b33d 1257 nonRoundedTotalMethodTime = columnMethodDataSet->nonRoundedTotalMethodTime;
jmitc91516 1:a5258871b33d 1258
jmitc91516 1:a5258871b33d 1259 // Now let the AddDataPoint function take care of extending the dataset array, etc
jmitc91516 1:a5258871b33d 1260
jmitc91516 1:a5258871b33d 1261 // First point will be at the current injector temperature, time zero.
jmitc91516 1:a5258871b33d 1262 // Second point will be at the same temperature, at the end of the column method time.
jmitc91516 1:a5258871b33d 1263
jmitc91516 1:a5258871b33d 1264 float injectorTemperature = GetInjectorTemperature(usbDevice, usbHostGC);
jmitc91516 1:a5258871b33d 1265 float methodDuration = columnMethodDataSet->GetTotalMethodTime();
jmitc91516 1:a5258871b33d 1266
jmitc91516 1:a5258871b33d 1267 AddDataPoint(0, injectorTemperature);
jmitc91516 1:a5258871b33d 1268 AddDataPoint(methodDuration, injectorTemperature);
jmitc91516 1:a5258871b33d 1269 int pointCount = 2;
jmitc91516 1:a5258871b33d 1270
jmitc91516 1:a5258871b33d 1271 return pointCount;
jmitc91516 1:a5258871b33d 1272 }
jmitc91516 1:a5258871b33d 1273
jmitc91516 1:a5258871b33d 1274
jmitc91516 1:a5258871b33d 1275 /*
jmitc91516 1:a5258871b33d 1276 Setup this dataset to an injector temperature profile derived purely from the
jmitc91516 1:a5258871b33d 1277 injector/PTV settings in the GC, without reference to the current column method (if any).
jmitc91516 1:a5258871b33d 1278
jmitc91516 1:a5258871b33d 1279 Args: pointers to the USBDeviceConnected and USBHostGC instances that match the GC
jmitc91516 1:a5258871b33d 1280
jmitc91516 1:a5258871b33d 1281 Returns the number of points in the updated dataset.
jmitc91516 1:a5258871b33d 1282 */
jmitc91516 1:a5258871b33d 1283 int GuiLibGraphDataSet::SetupFromPTVTemperatureRampValues(USBDeviceConnected* usbDevice, USBHostGC* usbHostGC)
jmitc91516 1:a5258871b33d 1284 {
jmitc91516 1:a5258871b33d 1285 // First, delete all existing data from this dataset
jmitc91516 1:a5258871b33d 1286 ClearData();
jmitc91516 1:a5258871b33d 1287
jmitc91516 1:a5258871b33d 1288
jmitc91516 1:a5258871b33d 1289 // Now let the AddDataPoint function take care of extending the dataset array, etc
jmitc91516 1:a5258871b33d 1290
jmitc91516 1:a5258871b33d 1291 // First point will be at the current PTV temperature, time zero.
jmitc91516 1:a5258871b33d 1292 // Second point will be at the same temperature, after the initial time.
jmitc91516 1:a5258871b33d 1293 // Note that the words "injector" and "PTV" are effectively synonymous
jmitc91516 1:a5258871b33d 1294
jmitc91516 1:a5258871b33d 1295 float initialTemperature = GetInjectorTemperature(usbDevice, usbHostGC);
jmitc91516 1:a5258871b33d 1296 float initialTime = GetPTVInitialTime(usbDevice, usbHostGC);
jmitc91516 1:a5258871b33d 1297
jmitc91516 1:a5258871b33d 1298 AddDataPoint(0, initialTemperature);
jmitc91516 1:a5258871b33d 1299 AddDataPoint(initialTime, initialTemperature);
jmitc91516 1:a5258871b33d 1300 int pointCount = 2;
jmitc91516 1:a5258871b33d 1301
jmitc91516 1:a5258871b33d 1302 // These values are specific to each ramp (index 0 through 9)
jmitc91516 1:a5258871b33d 1303 float temperatureRampRate; // This is the rate at which the GC will increase the PTV temperature
jmitc91516 1:a5258871b33d 1304 // (if this is zero, this ramp is not used, and nor are any after it -
jmitc91516 1:a5258871b33d 1305 // i.e. the previous ramp was the final one)
jmitc91516 1:a5258871b33d 1306 float rampUpperTemperature; // This is the upper (or "target") temperature
jmitc91516 1:a5258871b33d 1307 float rampUpperTime; // Once the PTV reaches the upper/target temperature, the GC
jmitc91516 1:a5258871b33d 1308 // will keep it at that temperature for this length of time -
jmitc91516 1:a5258871b33d 1309 // at the end of this, the next ramp will start (unless this is the last one)
jmitc91516 1:a5258871b33d 1310 float rampingTime;
jmitc91516 1:a5258871b33d 1311
jmitc91516 1:a5258871b33d 1312 float totalMethodTime = initialTime;
jmitc91516 1:a5258871b33d 1313
jmitc91516 1:a5258871b33d 1314 float previousRampUpperTemperature = initialTemperature;
jmitc91516 1:a5258871b33d 1315
jmitc91516 1:a5258871b33d 1316 // These are the coordinates we add to the graph dataset
jmitc91516 1:a5258871b33d 1317 float X1, X2;
jmitc91516 1:a5258871b33d 1318 float Y1, Y2;
jmitc91516 1:a5258871b33d 1319
jmitc91516 1:a5258871b33d 1320 #ifdef USE_VERSION_102 // This starts at ramp index 0 - older versions start at 1
jmitc91516 1:a5258871b33d 1321 for (int rampIndex = 0; rampIndex < 10; ++rampIndex) {
jmitc91516 1:a5258871b33d 1322 #else
jmitc91516 1:a5258871b33d 1323 for (int rampIndex = 1; rampIndex < 10; ++rampIndex) {
jmitc91516 1:a5258871b33d 1324 #endif
jmitc91516 1:a5258871b33d 1325 temperatureRampRate = GetPTVTemperatureRampRate(rampIndex, usbDevice, usbHostGC);
jmitc91516 1:a5258871b33d 1326
jmitc91516 1:a5258871b33d 1327 if(temperatureRampRate <= FLT_MIN) { // Avoid rounding errors - do not test for equality with zero
jmitc91516 1:a5258871b33d 1328 // No more ramps
jmitc91516 1:a5258871b33d 1329 break;
jmitc91516 1:a5258871b33d 1330 }
jmitc91516 1:a5258871b33d 1331
jmitc91516 1:a5258871b33d 1332
jmitc91516 1:a5258871b33d 1333 rampUpperTemperature = GetPTVRampUpperTemperature(rampIndex, usbDevice, usbHostGC);
jmitc91516 1:a5258871b33d 1334
jmitc91516 1:a5258871b33d 1335 // Sanity check
jmitc91516 1:a5258871b33d 1336 if(rampUpperTemperature < previousRampUpperTemperature) {
jmitc91516 1:a5258871b33d 1337 // This should never happen. We must have got our temperature units confused (or something) - give up
jmitc91516 1:a5258871b33d 1338 break;
jmitc91516 1:a5258871b33d 1339 }
jmitc91516 1:a5258871b33d 1340
jmitc91516 1:a5258871b33d 1341 rampingTime = (rampUpperTemperature - previousRampUpperTemperature) / temperatureRampRate;
jmitc91516 1:a5258871b33d 1342
jmitc91516 1:a5258871b33d 1343 totalMethodTime += rampingTime;
jmitc91516 1:a5258871b33d 1344
jmitc91516 1:a5258871b33d 1345 X1 = totalMethodTime;
jmitc91516 1:a5258871b33d 1346 Y1 = rampUpperTemperature;
jmitc91516 1:a5258871b33d 1347
jmitc91516 1:a5258871b33d 1348 if(AddDataPoint(X1, Y1)) {
jmitc91516 1:a5258871b33d 1349 ++pointCount;
jmitc91516 1:a5258871b33d 1350 }
jmitc91516 1:a5258871b33d 1351
jmitc91516 1:a5258871b33d 1352
jmitc91516 1:a5258871b33d 1353 rampUpperTime = GetPTVRampUpperTime(rampIndex, usbDevice, usbHostGC);
jmitc91516 1:a5258871b33d 1354
jmitc91516 1:a5258871b33d 1355 if(rampUpperTime > FLT_MIN) { // i.e. > 0 (avoid floating point rounding errors)
jmitc91516 1:a5258871b33d 1356
jmitc91516 1:a5258871b33d 1357 totalMethodTime += rampUpperTime;
jmitc91516 1:a5258871b33d 1358
jmitc91516 1:a5258871b33d 1359 X2 = totalMethodTime;
jmitc91516 1:a5258871b33d 1360 Y2 = rampUpperTemperature;
jmitc91516 1:a5258871b33d 1361
jmitc91516 1:a5258871b33d 1362 if(AddDataPoint(X2, Y2)) {
jmitc91516 1:a5258871b33d 1363 ++pointCount;
jmitc91516 1:a5258871b33d 1364 }
jmitc91516 1:a5258871b33d 1365 }
jmitc91516 1:a5258871b33d 1366 // 'Else' the ramp upper time is zero - we are not holding here -
jmitc91516 1:a5258871b33d 1367 // so do not add a second point (AddDataPoint does not allow
jmitc91516 1:a5258871b33d 1368 // two points at the same X coordinate anyway)
jmitc91516 1:a5258871b33d 1369
jmitc91516 1:a5258871b33d 1370 previousRampUpperTemperature = rampUpperTemperature;
jmitc91516 1:a5258871b33d 1371 }
jmitc91516 1:a5258871b33d 1372
jmitc91516 1:a5258871b33d 1373 nonRoundedTotalMethodTime = totalMethodTime;
jmitc91516 1:a5258871b33d 1374
jmitc91516 1:a5258871b33d 1375 return pointCount;
jmitc91516 1:a5258871b33d 1376 }
jmitc91516 1:a5258871b33d 1377
jmitc91516 1:a5258871b33d 1378 /*
jmitc91516 1:a5258871b33d 1379 Setup this dataset with a gas pressure profile that matches the current column method.
jmitc91516 1:a5258871b33d 1380 The timings will be taken from the matching column method - which *must* already be set up.
jmitc91516 1:a5258871b33d 1381 In Constant Pressure mode (first gas ramp rate == 0), the same pressure
jmitc91516 1:a5258871b33d 1382 will be maintained from start to end of the method, while in Programmed Pressure mode
jmitc91516 1:a5258871b33d 1383 (first gas ramp rate > 0), the pressure ramps will each start and end at the same times
jmitc91516 1:a5258871b33d 1384 as the corresponding temperature ramps in the column method.
jmitc91516 1:a5258871b33d 1385
jmitc91516 1:a5258871b33d 1386 In both cases, the total duration will be the same as the column method.
jmitc91516 1:a5258871b33d 1387
jmitc91516 1:a5258871b33d 1388 Args: - pointers to the USBDeviceConnected and USBHostGC instances that match the GC
jmitc91516 1:a5258871b33d 1389 - pointer to a GuiLibGraphDataSet object containing the matching column method
jmitc91516 1:a5258871b33d 1390
jmitc91516 1:a5258871b33d 1391 Returns the number of points in the updated dataset.
jmitc91516 1:a5258871b33d 1392 */
jmitc91516 1:a5258871b33d 1393 int GuiLibGraphDataSet::SetupGasPressureProfileWithTimingsFromColumnMethod(USBDeviceConnected* usbDevice, USBHostGC* usbHostGC, GuiLibGraphDataSet* columnMethodDataSet)
jmitc91516 1:a5258871b33d 1394 {
jmitc91516 1:a5258871b33d 1395 // First, delete all existing data from this dataset
jmitc91516 1:a5258871b33d 1396 ClearData();
jmitc91516 1:a5258871b33d 1397
jmitc91516 1:a5258871b33d 1398 // Now let the AddDataPoint function take care of extending the dataset array, etc
jmitc91516 1:a5258871b33d 1399
jmitc91516 1:a5258871b33d 1400 int pointCount;
jmitc91516 1:a5258871b33d 1401
jmitc91516 1:a5258871b33d 1402 if(GetPressureRampRate(0, usbDevice, usbHostGC) > FLT_MIN) { // Avoid rounding errors
jmitc91516 1:a5258871b33d 1403
jmitc91516 1:a5258871b33d 1404 // Programmed Pressure mode
jmitc91516 1:a5258871b33d 1405
jmitc91516 1:a5258871b33d 1406 // First point will be at the initial pressure, time zero.
jmitc91516 1:a5258871b33d 1407 // Second point will be at the same pressure, after the initial time.
jmitc91516 1:a5258871b33d 1408 float initialPressure = (double) GetInitialPressure(usbDevice, usbHostGC);
jmitc91516 1:a5258871b33d 1409 float initialHoldTime = (double) GetInitialHoldTime(usbDevice, usbHostGC);
jmitc91516 1:a5258871b33d 1410
jmitc91516 1:a5258871b33d 1411 AddDataPoint(0, initialPressure);
jmitc91516 1:a5258871b33d 1412 AddDataPoint(initialHoldTime, initialPressure);
jmitc91516 1:a5258871b33d 1413 pointCount = 2;
jmitc91516 1:a5258871b33d 1414
jmitc91516 1:a5258871b33d 1415 // This value is specific to each ramp (index 0 through 9)
jmitc91516 1:a5258871b33d 1416 float rampUpperPressure; // This is the upper (or "target") pressure
jmitc91516 1:a5258871b33d 1417
jmitc91516 1:a5258871b33d 1418 float totalMethodTime = initialHoldTime;
jmitc91516 1:a5258871b33d 1419
jmitc91516 1:a5258871b33d 1420 // These are the coordinates we add to the graph dataset.
jmitc91516 1:a5258871b33d 1421 // X coordinates are time values, Y coordinates are temperatures
jmitc91516 1:a5258871b33d 1422 // (in the column dataset) or pressures (in this dataset).
jmitc91516 1:a5258871b33d 1423 // Note that we get our time values from the column dataset -
jmitc91516 1:a5258871b33d 1424 // we do not calculate them here - we want to make sure they match
jmitc91516 1:a5258871b33d 1425 float X1, Y1;
jmitc91516 1:a5258871b33d 1426 float X2, Y2;
jmitc91516 1:a5258871b33d 1427
jmitc91516 1:a5258871b33d 1428 #ifdef USE_VERSION_102 // This starts at ramp index 0, older versions start at 1
jmitc91516 1:a5258871b33d 1429 for (int rampIndex = 0; rampIndex < 10; ++rampIndex) {
jmitc91516 1:a5258871b33d 1430 #else
jmitc91516 1:a5258871b33d 1431 for (int rampIndex = 1; rampIndex < 10; ++rampIndex) {
jmitc91516 1:a5258871b33d 1432 #endif
jmitc91516 1:a5258871b33d 1433 rampUpperPressure = GetRampUpperPressure(rampIndex, usbDevice, usbHostGC);
jmitc91516 1:a5258871b33d 1434
jmitc91516 1:a5258871b33d 1435 if(!columnMethodDataSet->GetDataPoint(pointCount, &X1, &Y1)) {
jmitc91516 1:a5258871b33d 1436 // We have run out of points in the column method
jmitc91516 1:a5258871b33d 1437 break;
jmitc91516 1:a5258871b33d 1438 }
jmitc91516 1:a5258871b33d 1439
jmitc91516 1:a5258871b33d 1440 AddDataPoint(X1, rampUpperPressure);
jmitc91516 1:a5258871b33d 1441 totalMethodTime = X1;
jmitc91516 1:a5258871b33d 1442 ++pointCount;
jmitc91516 1:a5258871b33d 1443
jmitc91516 1:a5258871b33d 1444 if(!columnMethodDataSet->GetDataPoint(pointCount, &X2, &Y2)) {
jmitc91516 1:a5258871b33d 1445 // We have run out of points in the column method
jmitc91516 1:a5258871b33d 1446 break;
jmitc91516 1:a5258871b33d 1447 }
jmitc91516 1:a5258871b33d 1448
jmitc91516 1:a5258871b33d 1449 if(Y2 == Y1) {
jmitc91516 1:a5258871b33d 1450 // Temperatures are the same - this is a non-zero holding interval
jmitc91516 1:a5258871b33d 1451 AddDataPoint(X2, rampUpperPressure);
jmitc91516 1:a5258871b33d 1452 totalMethodTime = X2;
jmitc91516 1:a5258871b33d 1453 ++pointCount;
jmitc91516 1:a5258871b33d 1454 }
jmitc91516 1:a5258871b33d 1455 // 'else' we are not holding here - do not add a second point -
jmitc91516 1:a5258871b33d 1456 // the second point here is actually the end of the next ramp,
jmitc91516 1:a5258871b33d 1457 // so re-use it for the next ramp (don't increment pointCount,
jmitc91516 1:a5258871b33d 1458 // so we get the same data point again 'next time round')
jmitc91516 1:a5258871b33d 1459 // *** See comment [HOLDING INTERVAL] in SetupFromColumnTemperatureRampValues ***
jmitc91516 1:a5258871b33d 1460 }
jmitc91516 1:a5258871b33d 1461
jmitc91516 1:a5258871b33d 1462 nonRoundedTotalMethodTime = totalMethodTime;
jmitc91516 1:a5258871b33d 1463
jmitc91516 1:a5258871b33d 1464 } else {
jmitc91516 1:a5258871b33d 1465
jmitc91516 1:a5258871b33d 1466 // Constant pressure mode
jmitc91516 1:a5258871b33d 1467
jmitc91516 1:a5258871b33d 1468 nonRoundedTotalMethodTime = columnMethodDataSet->nonRoundedTotalMethodTime;
jmitc91516 1:a5258871b33d 1469
jmitc91516 1:a5258871b33d 1470 // First point will be at the initial gas pressure, time zero.
jmitc91516 1:a5258871b33d 1471 // Second point will be at the same pressure, at the end of the column method time.
jmitc91516 1:a5258871b33d 1472
jmitc91516 1:a5258871b33d 1473 float initialPressure = (double) GetInitialPressure(usbDevice, usbHostGC);
jmitc91516 1:a5258871b33d 1474 float methodDuration = columnMethodDataSet->GetTotalMethodTime();
jmitc91516 1:a5258871b33d 1475
jmitc91516 1:a5258871b33d 1476 AddDataPoint(0, initialPressure);
jmitc91516 1:a5258871b33d 1477 AddDataPoint(methodDuration, initialPressure);
jmitc91516 1:a5258871b33d 1478 pointCount = 2;
jmitc91516 1:a5258871b33d 1479 }
jmitc91516 1:a5258871b33d 1480
jmitc91516 1:a5258871b33d 1481 return pointCount;
jmitc91516 1:a5258871b33d 1482 }
jmitc91516 1:a5258871b33d 1483
jmitc91516 1:a5258871b33d 1484 /*
jmitc91516 1:a5258871b33d 1485 Returns the total time expected to be taken by the current method.
jmitc91516 1:a5258871b33d 1486 (This is effectively the same as the X coordinate of the final datapoint.)
jmitc91516 1:a5258871b33d 1487
jmitc91516 1:a5258871b33d 1488 Takes no arguments.
jmitc91516 1:a5258871b33d 1489 */
jmitc91516 1:a5258871b33d 1490 float GuiLibGraphDataSet::GetTotalMethodTime(void)
jmitc91516 1:a5258871b33d 1491 {
jmitc91516 1:a5258871b33d 1492 if(graphDataSetActualLength <= 0) {
jmitc91516 1:a5258871b33d 1493 return 0.0f;
jmitc91516 1:a5258871b33d 1494 }
jmitc91516 1:a5258871b33d 1495
jmitc91516 1:a5258871b33d 1496 // 'else' we have some data
jmitc91516 1:a5258871b33d 1497 float finalX;
jmitc91516 1:a5258871b33d 1498 float finalY;
jmitc91516 1:a5258871b33d 1499 if(GetDataPoint((graphDataSetActualLength - 1), &finalX, &finalY)) {
jmitc91516 1:a5258871b33d 1500 return (finalX);
jmitc91516 1:a5258871b33d 1501 }
jmitc91516 1:a5258871b33d 1502
jmitc91516 1:a5258871b33d 1503 // 'else' GetDataPoint failed for some reason
jmitc91516 1:a5258871b33d 1504 return 0.0f;
jmitc91516 1:a5258871b33d 1505 }
jmitc91516 1:a5258871b33d 1506
jmitc91516 1:a5258871b33d 1507 /*
jmitc91516 1:a5258871b33d 1508 Returns the range of X coordinate values.
jmitc91516 1:a5258871b33d 1509
jmitc91516 1:a5258871b33d 1510 Args: pointers to the variables to contain the minimum and maximum X values
jmitc91516 1:a5258871b33d 1511 (these are integers, as required for an easyGUI graph)
jmitc91516 1:a5258871b33d 1512 the time unit to be used (minutes or seconds)
jmitc91516 1:a5258871b33d 1513
jmitc91516 1:a5258871b33d 1514 No return code.
jmitc91516 1:a5258871b33d 1515 */
jmitc91516 1:a5258871b33d 1516 void GuiLibGraphDataSet::GetXAxisRange(GuiConst_INT32S *xMin, GuiConst_INT32S *xMax, TimeUnit timeUnit)
jmitc91516 1:a5258871b33d 1517 {
jmitc91516 1:a5258871b33d 1518 if(graphDataSetActualLength <= 0) {
jmitc91516 1:a5258871b33d 1519 // We have no data
jmitc91516 1:a5258871b33d 1520 *xMin = 0;
jmitc91516 1:a5258871b33d 1521 *xMax = 0;
jmitc91516 1:a5258871b33d 1522
jmitc91516 1:a5258871b33d 1523 return;
jmitc91516 1:a5258871b33d 1524 }
jmitc91516 1:a5258871b33d 1525
jmitc91516 1:a5258871b33d 1526 // 'else' we have some data
jmitc91516 1:a5258871b33d 1527 float X1;
jmitc91516 1:a5258871b33d 1528 float Y1;
jmitc91516 1:a5258871b33d 1529 float X2;
jmitc91516 1:a5258871b33d 1530 float Y2;
jmitc91516 1:a5258871b33d 1531 GetDataPoint(0, &X1, &Y1);
jmitc91516 1:a5258871b33d 1532 GetDataPoint((graphDataSetActualLength - 1), &X2, &Y2);
jmitc91516 1:a5258871b33d 1533
jmitc91516 1:a5258871b33d 1534 if(timeUnit == SECONDS) {
jmitc91516 1:a5258871b33d 1535 X1 *= 60.0f;
jmitc91516 1:a5258871b33d 1536 X2 *= 60.0f;
jmitc91516 1:a5258871b33d 1537 }
jmitc91516 1:a5258871b33d 1538
jmitc91516 1:a5258871b33d 1539 *xMin = (GuiConst_INT32S) floor((double)X1 + 0.5);
jmitc91516 1:a5258871b33d 1540 *xMax = (GuiConst_INT32S) floor((double)X2 + 0.5);
jmitc91516 1:a5258871b33d 1541 }
jmitc91516 1:a5258871b33d 1542
jmitc91516 1:a5258871b33d 1543 /*
jmitc91516 1:a5258871b33d 1544 Returns the range of X coordinate values, in units of 0.1 minute.
jmitc91516 1:a5258871b33d 1545
jmitc91516 1:a5258871b33d 1546 Args: pointers to the variables to contain the minimum and maximum X values
jmitc91516 1:a5258871b33d 1547 (these are integers, as required for an easyGUI graph)
jmitc91516 1:a5258871b33d 1548
jmitc91516 1:a5258871b33d 1549 No return code.
jmitc91516 1:a5258871b33d 1550 */
jmitc91516 1:a5258871b33d 1551 void GuiLibGraphDataSet::GetXAxisRangeInTenthsOfMinutes(GuiConst_INT32S *xMin, GuiConst_INT32S *xMax)
jmitc91516 1:a5258871b33d 1552 {
jmitc91516 1:a5258871b33d 1553 if(graphDataSetActualLength <= 0) {
jmitc91516 1:a5258871b33d 1554 // We have no data
jmitc91516 1:a5258871b33d 1555 *xMin = 0;
jmitc91516 1:a5258871b33d 1556 *xMax = 0;
jmitc91516 1:a5258871b33d 1557
jmitc91516 1:a5258871b33d 1558 return;
jmitc91516 1:a5258871b33d 1559 }
jmitc91516 1:a5258871b33d 1560
jmitc91516 1:a5258871b33d 1561 // 'else' we have some data
jmitc91516 1:a5258871b33d 1562 float X1;
jmitc91516 1:a5258871b33d 1563 float Y1;
jmitc91516 1:a5258871b33d 1564 float X2;
jmitc91516 1:a5258871b33d 1565 float Y2;
jmitc91516 1:a5258871b33d 1566 GetDataPoint(0, &X1, &Y1);
jmitc91516 1:a5258871b33d 1567 GetDataPoint((graphDataSetActualLength - 1), &X2, &Y2);
jmitc91516 1:a5258871b33d 1568
jmitc91516 1:a5258871b33d 1569 *xMin = (GuiConst_INT32S) (X1 * 10.0f);
jmitc91516 1:a5258871b33d 1570 *xMax = (GuiConst_INT32S) (X2 * 10.0f);
jmitc91516 1:a5258871b33d 1571 }
jmitc91516 1:a5258871b33d 1572
jmitc91516 1:a5258871b33d 1573 /*
jmitc91516 1:a5258871b33d 1574 Returns the range of X coordinate values - but rounded to be a whole number of 'ticks'
jmitc91516 1:a5258871b33d 1575 (i.e. the interval between marks on the X axis).
jmitc91516 1:a5258871b33d 1576
jmitc91516 1:a5258871b33d 1577 Args: pointers to the variables to contain the minimum and maximum X values
jmitc91516 1:a5258871b33d 1578 the tick size
jmitc91516 1:a5258871b33d 1579 the time unit
jmitc91516 1:a5258871b33d 1580
jmitc91516 1:a5258871b33d 1581 No return code.
jmitc91516 1:a5258871b33d 1582 */
jmitc91516 1:a5258871b33d 1583 void GuiLibGraphDataSet::GetXAxisRange(GuiConst_INT32S *xMin, GuiConst_INT32S *xMax, GuiConst_INT32S xTickSize, TimeUnit timeUnit)
jmitc91516 1:a5258871b33d 1584 {
jmitc91516 1:a5258871b33d 1585 GuiConst_INT32S rawXMin;
jmitc91516 1:a5258871b33d 1586 GuiConst_INT32S rawXMax;
jmitc91516 1:a5258871b33d 1587
jmitc91516 1:a5258871b33d 1588 GetXAxisRange(&rawXMin, &rawXMax, timeUnit);
jmitc91516 1:a5258871b33d 1589
jmitc91516 1:a5258871b33d 1590 RoundAxisRangeByTickSize(xMin, xMax, rawXMin, rawXMax, xTickSize);
jmitc91516 1:a5258871b33d 1591 }
jmitc91516 1:a5258871b33d 1592
jmitc91516 1:a5258871b33d 1593 /*
jmitc91516 1:a5258871b33d 1594 Returns the range of X coordinate values, in units of 0.1 minute - but rounded to be a whole number of 'ticks'
jmitc91516 1:a5258871b33d 1595 (i.e. the interval between marks on the X axis).
jmitc91516 1:a5258871b33d 1596
jmitc91516 1:a5258871b33d 1597 Args: pointers to the variables to contain the minimum and maximum X values
jmitc91516 1:a5258871b33d 1598 the tick size
jmitc91516 1:a5258871b33d 1599
jmitc91516 1:a5258871b33d 1600 No return code.
jmitc91516 1:a5258871b33d 1601 */
jmitc91516 1:a5258871b33d 1602 void GuiLibGraphDataSet::GetXAxisRangeInTenthsOfMinutes(GuiConst_INT32S *xMin, GuiConst_INT32S *xMax, GuiConst_INT32S xTickSize)
jmitc91516 1:a5258871b33d 1603 {
jmitc91516 1:a5258871b33d 1604 GuiConst_INT32S rawXMin;
jmitc91516 1:a5258871b33d 1605 GuiConst_INT32S rawXMax;
jmitc91516 1:a5258871b33d 1606
jmitc91516 1:a5258871b33d 1607 GetXAxisRangeInTenthsOfMinutes(&rawXMin, &rawXMax);
jmitc91516 1:a5258871b33d 1608
jmitc91516 1:a5258871b33d 1609 RoundAxisRangeByTickSize(xMin, xMax, rawXMin, rawXMax, xTickSize);
jmitc91516 1:a5258871b33d 1610 }
jmitc91516 1:a5258871b33d 1611
jmitc91516 1:a5258871b33d 1612 /*
jmitc91516 1:a5258871b33d 1613 Returns the range of Y coordinate values.
jmitc91516 1:a5258871b33d 1614
jmitc91516 1:a5258871b33d 1615 Args: pointers to the variables to contain the minimum and maximum Y values
jmitc91516 1:a5258871b33d 1616 (these are integers, as required for an easyGUI graph)
jmitc91516 1:a5258871b33d 1617
jmitc91516 1:a5258871b33d 1618 No return code.
jmitc91516 1:a5258871b33d 1619 */
jmitc91516 1:a5258871b33d 1620 void GuiLibGraphDataSet::GetYAxisRange(GuiConst_INT32S *yMin, GuiConst_INT32S *yMax)
jmitc91516 1:a5258871b33d 1621 {
jmitc91516 1:a5258871b33d 1622 if(graphDataSetActualLength <= 0) {
jmitc91516 1:a5258871b33d 1623 // We have no data
jmitc91516 1:a5258871b33d 1624 *yMin = 0;
jmitc91516 1:a5258871b33d 1625 *yMax = 0;
jmitc91516 1:a5258871b33d 1626
jmitc91516 1:a5258871b33d 1627 return;
jmitc91516 1:a5258871b33d 1628 }
jmitc91516 1:a5258871b33d 1629
jmitc91516 1:a5258871b33d 1630 // 'else' we have some data
jmitc91516 1:a5258871b33d 1631 float X;
jmitc91516 1:a5258871b33d 1632 float Y;
jmitc91516 1:a5258871b33d 1633 float minYSoFar;
jmitc91516 1:a5258871b33d 1634 float maxYSoFar;
jmitc91516 1:a5258871b33d 1635
jmitc91516 1:a5258871b33d 1636 GetDataPoint(0, &X, &Y);
jmitc91516 1:a5258871b33d 1637 minYSoFar = Y;
jmitc91516 1:a5258871b33d 1638 maxYSoFar = Y;
jmitc91516 1:a5258871b33d 1639
jmitc91516 1:a5258871b33d 1640 for (int pointIndex = 1; pointIndex < graphDataSetActualLength; ++pointIndex) {
jmitc91516 1:a5258871b33d 1641 GetDataPoint(pointIndex, &X, &Y);
jmitc91516 1:a5258871b33d 1642
jmitc91516 1:a5258871b33d 1643 if(Y < minYSoFar) { minYSoFar = Y; }
jmitc91516 1:a5258871b33d 1644 if(Y > maxYSoFar) { maxYSoFar = Y; }
jmitc91516 1:a5258871b33d 1645 }
jmitc91516 1:a5258871b33d 1646
jmitc91516 1:a5258871b33d 1647 *yMin = (GuiConst_INT32S) floor((double)minYSoFar + 0.5);
jmitc91516 1:a5258871b33d 1648 *yMax = (GuiConst_INT32S) floor((double)maxYSoFar + 0.5);
jmitc91516 1:a5258871b33d 1649 }
jmitc91516 1:a5258871b33d 1650
jmitc91516 1:a5258871b33d 1651 /*
jmitc91516 1:a5258871b33d 1652 Returns the range of Y coordinate values - but rounded to be a whole number of 'ticks'
jmitc91516 1:a5258871b33d 1653 (i.e. the interval between marks on the Y axis)
jmitc91516 1:a5258871b33d 1654
jmitc91516 1:a5258871b33d 1655 Args: pointers to the variables to contain the minimum and maximum X values
jmitc91516 1:a5258871b33d 1656 the tick size
jmitc91516 1:a5258871b33d 1657
jmitc91516 1:a5258871b33d 1658 No return code.
jmitc91516 1:a5258871b33d 1659 */
jmitc91516 1:a5258871b33d 1660 void GuiLibGraphDataSet::GetYAxisRange(GuiConst_INT32S *yMin, GuiConst_INT32S *yMax, GuiConst_INT32S yTickSize)
jmitc91516 1:a5258871b33d 1661 {
jmitc91516 1:a5258871b33d 1662 GuiConst_INT32S rawYMin;
jmitc91516 1:a5258871b33d 1663 GuiConst_INT32S rawYMax;
jmitc91516 1:a5258871b33d 1664
jmitc91516 1:a5258871b33d 1665 GetYAxisRange(&rawYMin, &rawYMax);
jmitc91516 1:a5258871b33d 1666
jmitc91516 1:a5258871b33d 1667 RoundAxisRangeByTickSize(yMin, yMax, rawYMin, rawYMax, yTickSize);
jmitc91516 1:a5258871b33d 1668 }
jmitc91516 1:a5258871b33d 1669
jmitc91516 1:a5258871b33d 1670 /*
jmitc91516 1:a5258871b33d 1671 Rounds an axis range to be a whole number of 'ticks' - i.e. the range starts at the last tick below the minimum value,
jmitc91516 1:a5258871b33d 1672 and ends at the first tick above the maximum value.
jmitc91516 1:a5258871b33d 1673
jmitc91516 1:a5258871b33d 1674 Args: pointers to the variables to contain the rounded minimum and maximum
jmitc91516 1:a5258871b33d 1675 the 'raw' minimum and maximum values
jmitc91516 1:a5258871b33d 1676 the tick size
jmitc91516 1:a5258871b33d 1677 */
jmitc91516 1:a5258871b33d 1678 void GuiLibGraphDataSet::RoundAxisRangeByTickSize(GuiConst_INT32S *axisMin, GuiConst_INT32S *axisMax, GuiConst_INT32S rawAxisMin, GuiConst_INT32S rawAxisMax, GuiConst_INT32S axisTickSize)
jmitc91516 1:a5258871b33d 1679 {
jmitc91516 1:a5258871b33d 1680 if(axisTickSize > 0) {
jmitc91516 1:a5258871b33d 1681 float fAxisTickSize = (float) axisTickSize;
jmitc91516 1:a5258871b33d 1682
jmitc91516 1:a5258871b33d 1683 float fRawAxisMin = (float) rawAxisMin;
jmitc91516 1:a5258871b33d 1684 float axisTickCountMin = fRawAxisMin / fAxisTickSize;
jmitc91516 1:a5258871b33d 1685 *axisMin = (GuiConst_INT32S) (fAxisTickSize * (floor (axisTickCountMin)));
jmitc91516 1:a5258871b33d 1686
jmitc91516 1:a5258871b33d 1687 float fRawAxisMax = (float) rawAxisMax;
jmitc91516 1:a5258871b33d 1688 float axisTickCountMax = fRawAxisMax / fAxisTickSize;
jmitc91516 1:a5258871b33d 1689 *axisMax = (GuiConst_INT32S) (fAxisTickSize * (ceil (axisTickCountMax)));
jmitc91516 1:a5258871b33d 1690 } else {
jmitc91516 1:a5258871b33d 1691 *axisMin = rawAxisMin;
jmitc91516 1:a5258871b33d 1692 *axisMax = rawAxisMax;
jmitc91516 1:a5258871b33d 1693 }
jmitc91516 1:a5258871b33d 1694 }
jmitc91516 1:a5258871b33d 1695
jmitc91516 1:a5258871b33d 1696
jmitc91516 1:a5258871b33d 1697 /*
jmitc91516 1:a5258871b33d 1698 Draws the profile directly to the display, using the GuiLib_VLine function, via the DrawProfileSectionUsingGuiLibVLine function defined in main.cpp.
jmitc91516 1:a5258871b33d 1699 In general, this will be two colours, with a boundary part way across, to represent how much of the method we have executed, and how much remains.
jmitc91516 1:a5258871b33d 1700
jmitc91516 1:a5258871b33d 1701 This is the private version of this function, which takes a boolean value stating whether or not
jmitc91516 1:a5258871b33d 1702 to record the parameter values. One public version takes explicit values, and tells this function to record them,
jmitc91516 1:a5258871b33d 1703 while the other takes no parameters, simply passing this function the previously recorded values
jmitc91516 1:a5258871b33d 1704 (this is so that the caller does not have to keep re-calculating the same values, possibly in more than one place).
jmitc91516 1:a5258871b33d 1705
jmitc91516 1:a5258871b33d 1706 Args: the display X coordinate at which to start
jmitc91516 1:a5258871b33d 1707 the display Y coordinate at which to start
jmitc91516 1:a5258871b33d 1708 the X and Y scale factors - i.e. the values you have to multiply our X and Y coordinates by, to get display coordinates
jmitc91516 1:a5258871b33d 1709 the colour of the first section
jmitc91516 1:a5258871b33d 1710 the colour of the second section
jmitc91516 1:a5258871b33d 1711 the X coordinate (internal, not display) at which the second section starts. If this is < 0, we draw the entire profile in the first colour
jmitc91516 1:a5258871b33d 1712 flag saying whether or not to record the parameters
jmitc91516 1:a5258871b33d 1713
jmitc91516 1:a5258871b33d 1714 No return code
jmitc91516 1:a5258871b33d 1715 */
jmitc91516 1:a5258871b33d 1716 void GuiLibGraphDataSet::DrawUsingGuiLibVLine(GuiConst_INT16S xLeft, GuiConst_INT16S yBottom, double xScaleFactor, double yScaleFactor,
jmitc91516 1:a5258871b33d 1717 GuiConst_INTCOLOR firstColour, GuiConst_INTCOLOR secondColour, double xColourBoundary, bool recordParameters)
jmitc91516 1:a5258871b33d 1718 {
jmitc91516 1:a5258871b33d 1719 if(theGraphDataSet != NULL) {
jmitc91516 1:a5258871b33d 1720
jmitc91516 1:a5258871b33d 1721 GuiConst_INT16S profileSectionLeft;
jmitc91516 1:a5258871b33d 1722 GuiConst_INT16S profileSectionRight;
jmitc91516 1:a5258871b33d 1723
jmitc91516 1:a5258871b33d 1724 GuiConst_INT16S profileSectionTopLeft;
jmitc91516 1:a5258871b33d 1725 GuiConst_INT16S profileSectionTopRight;
jmitc91516 1:a5258871b33d 1726
jmitc91516 1:a5258871b33d 1727 GuiConst_INT16S profileColourBoundary = xLeft + (GuiConst_INT16S)floor(xColourBoundary * xScaleFactor);
jmitc91516 1:a5258871b33d 1728
jmitc91516 1:a5258871b33d 1729 for(int graphDataSetIndex = 0; graphDataSetIndex < (graphDataSetActualLength - 1); ++graphDataSetIndex) {
jmitc91516 1:a5258871b33d 1730
jmitc91516 1:a5258871b33d 1731 profileSectionLeft = xLeft + (GuiConst_INT16S)floor(theGraphDataSet[graphDataSetIndex].X * xScaleFactor);
jmitc91516 1:a5258871b33d 1732 profileSectionRight = xLeft + (GuiConst_INT16S)floor(theGraphDataSet[graphDataSetIndex + 1].X * xScaleFactor);
jmitc91516 1:a5258871b33d 1733
jmitc91516 1:a5258871b33d 1734 profileSectionTopLeft = yBottom + (GuiConst_INT16S)floor(theGraphDataSet[graphDataSetIndex].Y * yScaleFactor);
jmitc91516 1:a5258871b33d 1735 profileSectionTopRight = yBottom + (GuiConst_INT16S)floor(theGraphDataSet[graphDataSetIndex + 1].Y * yScaleFactor);
jmitc91516 1:a5258871b33d 1736
jmitc91516 1:a5258871b33d 1737 DrawProfileSectionUsingGuiLibVLine(firstColour, secondColour, profileSectionLeft, profileSectionRight, profileColourBoundary, yBottom, profileSectionTopLeft, profileSectionTopRight);
jmitc91516 1:a5258871b33d 1738 }
jmitc91516 1:a5258871b33d 1739 }
jmitc91516 1:a5258871b33d 1740
jmitc91516 1:a5258871b33d 1741 if(recordParameters) {
jmitc91516 1:a5258871b33d 1742 DrawUsingGuiLibVLineParameters.isSet = true;
jmitc91516 1:a5258871b33d 1743 DrawUsingGuiLibVLineParameters.xLeft = xLeft;
jmitc91516 1:a5258871b33d 1744 DrawUsingGuiLibVLineParameters.yBottom = yBottom;
jmitc91516 1:a5258871b33d 1745 DrawUsingGuiLibVLineParameters.xScaleFactor = xScaleFactor;
jmitc91516 1:a5258871b33d 1746 DrawUsingGuiLibVLineParameters.yScaleFactor = yScaleFactor;
jmitc91516 1:a5258871b33d 1747 DrawUsingGuiLibVLineParameters.firstColour = firstColour;
jmitc91516 1:a5258871b33d 1748 DrawUsingGuiLibVLineParameters.secondColour = secondColour;
jmitc91516 1:a5258871b33d 1749 DrawUsingGuiLibVLineParameters.xColourBoundary = xColourBoundary;
jmitc91516 1:a5258871b33d 1750 }
jmitc91516 1:a5258871b33d 1751 //&&&&&
jmitc91516 1:a5258871b33d 1752 }
jmitc91516 1:a5258871b33d 1753
jmitc91516 1:a5258871b33d 1754 /*
jmitc91516 1:a5258871b33d 1755 Call the DrawUsingGuiLibVLine function (see above) with newly-calculated parameter values.
jmitc91516 1:a5258871b33d 1756
jmitc91516 1:a5258871b33d 1757 Args: the display X coordinate at which to start
jmitc91516 1:a5258871b33d 1758 the display Y coordinate at which to start
jmitc91516 1:a5258871b33d 1759 the X and Y scale factors - i.e. the values you have to multiply our X and Y coordinates by, to get display coordinates
jmitc91516 1:a5258871b33d 1760 the colour of the first section
jmitc91516 1:a5258871b33d 1761 the colour of the second section
jmitc91516 1:a5258871b33d 1762 the X coordinate (internal, not display) at which the second section starts. If this is < 0, we draw the entire profile in the first colour
jmitc91516 1:a5258871b33d 1763
jmitc91516 1:a5258871b33d 1764 No return code.
jmitc91516 1:a5258871b33d 1765 */
jmitc91516 1:a5258871b33d 1766 void GuiLibGraphDataSet::DrawUsingGuiLibVLine(GuiConst_INT16S xLeft, GuiConst_INT16S yBottom, double xScaleFactor, double yScaleFactor, GuiConst_INTCOLOR firstColour, GuiConst_INTCOLOR secondColour, double xColourBoundary)
jmitc91516 1:a5258871b33d 1767 {
jmitc91516 1:a5258871b33d 1768 DrawUsingGuiLibVLine(xLeft,
jmitc91516 1:a5258871b33d 1769 yBottom,
jmitc91516 1:a5258871b33d 1770 xScaleFactor,
jmitc91516 1:a5258871b33d 1771 yScaleFactor,
jmitc91516 1:a5258871b33d 1772 firstColour,
jmitc91516 1:a5258871b33d 1773 secondColour,
jmitc91516 1:a5258871b33d 1774 xColourBoundary,
jmitc91516 1:a5258871b33d 1775 true );
jmitc91516 1:a5258871b33d 1776 }
jmitc91516 1:a5258871b33d 1777
jmitc91516 1:a5258871b33d 1778 /*
jmitc91516 1:a5258871b33d 1779 Repeats the last call to the version of DrawUsingGuiLibVLine with parameters,
jmitc91516 1:a5258871b33d 1780 using the same parameter values (if available). This is so that the caller
jmitc91516 1:a5258871b33d 1781 does not have to repeatedly calculate the same values in more than one place.
jmitc91516 1:a5258871b33d 1782 */
jmitc91516 1:a5258871b33d 1783 void GuiLibGraphDataSet::DrawUsingGuiLibVLine(void)
jmitc91516 1:a5258871b33d 1784 {
jmitc91516 1:a5258871b33d 1785 if(DrawUsingGuiLibVLineParameters.isSet) {
jmitc91516 1:a5258871b33d 1786 DrawUsingGuiLibVLine(DrawUsingGuiLibVLineParameters.xLeft,
jmitc91516 1:a5258871b33d 1787 DrawUsingGuiLibVLineParameters.yBottom,
jmitc91516 1:a5258871b33d 1788 DrawUsingGuiLibVLineParameters.xScaleFactor,
jmitc91516 1:a5258871b33d 1789 DrawUsingGuiLibVLineParameters.yScaleFactor,
jmitc91516 1:a5258871b33d 1790 DrawUsingGuiLibVLineParameters.firstColour,
jmitc91516 1:a5258871b33d 1791 DrawUsingGuiLibVLineParameters.secondColour,
jmitc91516 1:a5258871b33d 1792 DrawUsingGuiLibVLineParameters.xColourBoundary,
jmitc91516 1:a5258871b33d 1793 false );
jmitc91516 1:a5258871b33d 1794 }
jmitc91516 1:a5258871b33d 1795 // else no values available - do nothing
jmitc91516 1:a5258871b33d 1796 }
jmitc91516 1:a5258871b33d 1797
jmitc91516 1:a5258871b33d 1798
jmitc91516 1:a5258871b33d 1799
jmitc91516 1:a5258871b33d 1800 /*
jmitc91516 1:a5258871b33d 1801 GuiLibGraph constructor - the graph index must be specified by the caller,
jmitc91516 1:a5258871b33d 1802 and must match the index number specified for the graph in easyGUI
jmitc91516 1:a5258871b33d 1803 ******************************************************************
jmitc91516 1:a5258871b33d 1804 */
jmitc91516 1:a5258871b33d 1805 GuiLibGraph::GuiLibGraph(GuiConst_INT8U graphIndex)
jmitc91516 1:a5258871b33d 1806 {
jmitc91516 1:a5258871b33d 1807 GuiLib_GraphIndex = graphIndex;
jmitc91516 1:a5258871b33d 1808
jmitc91516 1:a5258871b33d 1809 xAxisUnits = MINUTES;
jmitc91516 1:a5258871b33d 1810
jmitc91516 1:a5258871b33d 1811 for(int i = 0; i < DATASET_INDEX_COUNT; ++i) {
jmitc91516 1:a5258871b33d 1812 dataSetDataPtr[i] = NULL;
jmitc91516 1:a5258871b33d 1813 }
jmitc91516 1:a5258871b33d 1814
jmitc91516 1:a5258871b33d 1815 xAxisLabelData.isSet = false;
jmitc91516 1:a5258871b33d 1816 }
jmitc91516 1:a5258871b33d 1817
jmitc91516 1:a5258871b33d 1818 GuiLibGraph::~GuiLibGraph()
jmitc91516 1:a5258871b33d 1819 {
jmitc91516 1:a5258871b33d 1820 for(int i = 0; i < DATASET_INDEX_COUNT; ++i) {
jmitc91516 1:a5258871b33d 1821 if(dataSetDataPtr[i] != NULL) {
jmitc91516 1:a5258871b33d 1822 delete [] dataSetDataPtr[i];
jmitc91516 1:a5258871b33d 1823 }
jmitc91516 1:a5258871b33d 1824 }
jmitc91516 1:a5258871b33d 1825 }
jmitc91516 1:a5258871b33d 1826
jmitc91516 1:a5258871b33d 1827
jmitc91516 1:a5258871b33d 1828 void GuiLibGraph::SetXAxisUnits(TimeUnit newXAxisUnits)
jmitc91516 1:a5258871b33d 1829 {
jmitc91516 1:a5258871b33d 1830 xAxisUnits = newXAxisUnits;
jmitc91516 1:a5258871b33d 1831 }
jmitc91516 1:a5258871b33d 1832
jmitc91516 1:a5258871b33d 1833 TimeUnit GuiLibGraph::GetXAxisUnits(void)
jmitc91516 1:a5258871b33d 1834 {
jmitc91516 1:a5258871b33d 1835 return xAxisUnits;
jmitc91516 1:a5258871b33d 1836 }
jmitc91516 1:a5258871b33d 1837
jmitc91516 1:a5258871b33d 1838
jmitc91516 1:a5258871b33d 1839 /*
jmitc91516 1:a5258871b33d 1840 Draws the axes for this graph.
jmitc91516 1:a5258871b33d 1841
jmitc91516 1:a5258871b33d 1842 Encapsulates the easyGUI 'GuiLib_Graph_DrawAxes' function,
jmitc91516 1:a5258871b33d 1843 passing it the index number specified for this graph
jmitc91516 1:a5258871b33d 1844
jmitc91516 1:a5258871b33d 1845 Args: None (we already know the index number for this graph)
jmitc91516 1:a5258871b33d 1846
jmitc91516 1:a5258871b33d 1847 */
jmitc91516 1:a5258871b33d 1848 GuiConst_INT8U GuiLibGraph::DrawAxes(void)
jmitc91516 1:a5258871b33d 1849 {
jmitc91516 1:a5258871b33d 1850 if(xAxisUnits == SECONDS) {
jmitc91516 1:a5258871b33d 1851 GuiLib_Graph_HideXAxis(GuiLib_GraphIndex, MINUTES_XAXIS_INDEX);
jmitc91516 1:a5258871b33d 1852 GuiLib_Graph_ShowXAxis(GuiLib_GraphIndex, SECONDS_XAXIS_INDEX);
jmitc91516 1:a5258871b33d 1853 } else {
jmitc91516 1:a5258871b33d 1854 GuiLib_Graph_ShowXAxis(GuiLib_GraphIndex, MINUTES_XAXIS_INDEX);
jmitc91516 1:a5258871b33d 1855 GuiLib_Graph_HideXAxis(GuiLib_GraphIndex, SECONDS_XAXIS_INDEX);
jmitc91516 1:a5258871b33d 1856 }
jmitc91516 1:a5258871b33d 1857
jmitc91516 1:a5258871b33d 1858 return GuiLib_Graph_DrawAxes(GuiLib_GraphIndex);
jmitc91516 1:a5258871b33d 1859 }
jmitc91516 1:a5258871b33d 1860
jmitc91516 1:a5258871b33d 1861 /*
jmitc91516 1:a5258871b33d 1862 Since the units we are using for the time values (0.1 minute) cannot be displayed by the easyGUI graph object,
jmitc91516 1:a5258871b33d 1863 which works only in integers, we are multiplying our x coordinates by 10 before passing them to the graph.
jmitc91516 1:a5258871b33d 1864 This means that we cannot let the easyGUI graph label its own X axis, since the values will look incorrect
jmitc91516 1:a5258871b33d 1865 to the user. We must therefore draw the values ourselves - which is what this function does.
jmitc91516 1:a5258871b33d 1866
jmitc91516 1:a5258871b33d 1867 This is the private version of this function, which takes a boolean value stating whether or not
jmitc91516 1:a5258871b33d 1868 to record the parameter values. One public version takes explicit values, and tells this function to record them,
jmitc91516 1:a5258871b33d 1869 while the other takes no parameters, simply passing this function the previously recorded values
jmitc91516 1:a5258871b33d 1870 (this is so that the caller does not have to keep re-calculating the same values, possibly in more than one place).
jmitc91516 1:a5258871b33d 1871
jmitc91516 1:a5258871b33d 1872 Args: the start and end X axis values
jmitc91516 1:a5258871b33d 1873 the tick size (i.e. the interval between successive values
jmitc91516 1:a5258871b33d 1874 the X and Y coordinates of the graph
jmitc91516 1:a5258871b33d 1875 the width of the graph
jmitc91516 1:a5258871b33d 1876 boolean stating whether or not to record the parameter values
jmitc91516 1:a5258871b33d 1877 */
jmitc91516 1:a5258871b33d 1878 void GuiLibGraph::DrawXAxisLabels(GuiConst_INT32S minValue, GuiConst_INT32S maxValue, GuiConst_INT32S tickSize,
jmitc91516 1:a5258871b33d 1879 GuiConst_INT16S graphX, GuiConst_INT16S graphY, GuiConst_INT16S graphW, bool recordParameters)
jmitc91516 1:a5258871b33d 1880 {
jmitc91516 1:a5258871b33d 1881 int intervalCount = (maxValue - minValue) / tickSize;
jmitc91516 1:a5258871b33d 1882
jmitc91516 1:a5258871b33d 1883 GuiConst_INT16S xCoord = graphX + 10; // 10 is empirical - relative to the graph X coordinate, it puts the labels in the correct place
jmitc91516 1:a5258871b33d 1884 GuiConst_INT16S xCoordInterval = graphW / intervalCount;
jmitc91516 1:a5258871b33d 1885
jmitc91516 1:a5258871b33d 1886 GuiConst_INT16S yCoord = graphY + 15; // 15 is also empirical - relative to the graph Y coordinate, it puts the labels in the correct place
jmitc91516 1:a5258871b33d 1887
jmitc91516 1:a5258871b33d 1888 const GuiConst_INT16U fontNo = GuiFont_Helv20Bold;
jmitc91516 1:a5258871b33d 1889 char text[100];
jmitc91516 1:a5258871b33d 1890
jmitc91516 1:a5258871b33d 1891 for(GuiConst_INT32S xValue = minValue; xValue <= maxValue; xValue += tickSize) {
jmitc91516 1:a5258871b33d 1892 sprintf(text, "%d", xValue);
jmitc91516 1:a5258871b33d 1893
jmitc91516 1:a5258871b33d 1894 GuiLib_DrawStr(
jmitc91516 1:a5258871b33d 1895 xCoord, //GuiConst_INT16S X,
jmitc91516 1:a5258871b33d 1896 yCoord, //GuiConst_INT16S Y,
jmitc91516 1:a5258871b33d 1897 fontNo, //GuiConst_INT16U FontNo,
jmitc91516 1:a5258871b33d 1898 text, //GuiConst_TEXT PrefixLocate *String,
jmitc91516 1:a5258871b33d 1899 GuiLib_ALIGN_CENTER, //GuiConst_INT8U Alignment,
jmitc91516 1:a5258871b33d 1900 GuiLib_PS_ON, //GuiConst_INT8U PsWriting,
jmitc91516 1:a5258871b33d 1901 GuiLib_TRANSPARENT_ON, //GuiConst_INT8U Transparent,
jmitc91516 1:a5258871b33d 1902 GuiLib_UNDERLINE_OFF, //GuiConst_INT8U Underlining,
jmitc91516 1:a5258871b33d 1903 0, //GuiConst_INT16S BackBoxSizeX,
jmitc91516 1:a5258871b33d 1904 0, //GuiConst_INT16S BackBoxSizeY1,
jmitc91516 1:a5258871b33d 1905 0, //GuiConst_INT16S BackBoxSizeY2,
jmitc91516 1:a5258871b33d 1906 GuiLib_BBP_NONE, //GuiConst_INT8U BackBorderPixels,
jmitc91516 1:a5258871b33d 1907 0, //GuiConst_INTCOLOR ForeColor,
jmitc91516 1:a5258871b33d 1908 0xFFFF //GuiConst_INTCOLOR BackColor
jmitc91516 1:a5258871b33d 1909 );
jmitc91516 1:a5258871b33d 1910
jmitc91516 1:a5258871b33d 1911 xCoord += xCoordInterval;
jmitc91516 1:a5258871b33d 1912 }
jmitc91516 1:a5258871b33d 1913
jmitc91516 1:a5258871b33d 1914 if(recordParameters) {
jmitc91516 1:a5258871b33d 1915 xAxisLabelData.isSet = true;
jmitc91516 1:a5258871b33d 1916 xAxisLabelData.minValue = minValue;
jmitc91516 1:a5258871b33d 1917 xAxisLabelData.maxValue = maxValue;
jmitc91516 1:a5258871b33d 1918 xAxisLabelData.tickSize = tickSize;
jmitc91516 1:a5258871b33d 1919 xAxisLabelData.graphX = graphX;
jmitc91516 1:a5258871b33d 1920 xAxisLabelData.graphY = graphY;
jmitc91516 1:a5258871b33d 1921 xAxisLabelData.graphW = graphW;
jmitc91516 1:a5258871b33d 1922 }
jmitc91516 1:a5258871b33d 1923 }
jmitc91516 1:a5258871b33d 1924
jmitc91516 1:a5258871b33d 1925 /*
jmitc91516 1:a5258871b33d 1926 Call the DrawXAxisLabels function (see above) with newly-calculated parameter values.
jmitc91516 1:a5258871b33d 1927
jmitc91516 1:a5258871b33d 1928 Args: the start and end X axis values
jmitc91516 1:a5258871b33d 1929 the tick size (i.e. the interval between successive values
jmitc91516 1:a5258871b33d 1930 the X and Y coordinates of the graph
jmitc91516 1:a5258871b33d 1931 the width of the graph
jmitc91516 1:a5258871b33d 1932 */
jmitc91516 1:a5258871b33d 1933 void GuiLibGraph::DrawXAxisLabels(GuiConst_INT32S minValue, GuiConst_INT32S maxValue, GuiConst_INT32S tickSize,
jmitc91516 1:a5258871b33d 1934 GuiConst_INT16S graphX, GuiConst_INT16S graphY, GuiConst_INT16S graphW)
jmitc91516 1:a5258871b33d 1935 {
jmitc91516 1:a5258871b33d 1936 DrawXAxisLabels(minValue,
jmitc91516 1:a5258871b33d 1937 maxValue,
jmitc91516 1:a5258871b33d 1938 tickSize,
jmitc91516 1:a5258871b33d 1939 graphX,
jmitc91516 1:a5258871b33d 1940 graphY,
jmitc91516 1:a5258871b33d 1941 graphW,
jmitc91516 1:a5258871b33d 1942 true );
jmitc91516 1:a5258871b33d 1943 }
jmitc91516 1:a5258871b33d 1944
jmitc91516 1:a5258871b33d 1945 /*
jmitc91516 1:a5258871b33d 1946 Repeats the last call to the version of DrawXAxisLabels with parameters,
jmitc91516 1:a5258871b33d 1947 using the same parameter values (if available). This is so that the caller
jmitc91516 1:a5258871b33d 1948 does not have to repeatedly calculate the same values in more than one place.
jmitc91516 1:a5258871b33d 1949 */
jmitc91516 1:a5258871b33d 1950 void GuiLibGraph::DrawXAxisLabels(void)
jmitc91516 1:a5258871b33d 1951 {
jmitc91516 1:a5258871b33d 1952 if(xAxisLabelData.isSet) {
jmitc91516 1:a5258871b33d 1953 DrawXAxisLabels(xAxisLabelData.minValue,
jmitc91516 1:a5258871b33d 1954 xAxisLabelData.maxValue,
jmitc91516 1:a5258871b33d 1955 xAxisLabelData.tickSize,
jmitc91516 1:a5258871b33d 1956 xAxisLabelData.graphX,
jmitc91516 1:a5258871b33d 1957 xAxisLabelData.graphY,
jmitc91516 1:a5258871b33d 1958 xAxisLabelData.graphW,
jmitc91516 1:a5258871b33d 1959 false );
jmitc91516 1:a5258871b33d 1960 }
jmitc91516 1:a5258871b33d 1961 // else no values available - do nothing
jmitc91516 1:a5258871b33d 1962 }
jmitc91516 1:a5258871b33d 1963
jmitc91516 1:a5258871b33d 1964
jmitc91516 1:a5258871b33d 1965 /*
jmitc91516 1:a5258871b33d 1966 Similarly to the X axis, we deliberately pass values that are larger than the real values to the Y axis.
jmitc91516 1:a5258871b33d 1967 This is to avoid the 'stepped' appearance that the profile can have for methods with a small range of values in Y.
jmitc91516 1:a5258871b33d 1968 This means that we cannot let the easyGUI graph label its own Y axis, since the values will look incorrect
jmitc91516 1:a5258871b33d 1969 to the user. We must therefore draw the values ourselves - which is what this function does.
jmitc91516 1:a5258871b33d 1970
jmitc91516 1:a5258871b33d 1971 This is the private version of this function, which takes a boolean value stating whether or not
jmitc91516 1:a5258871b33d 1972 to record the parameter values. One public version takes explicit values, and tells this function to record them,
jmitc91516 1:a5258871b33d 1973 while the other takes no parameters, simply passing this function the previously recorded values
jmitc91516 1:a5258871b33d 1974 (this is so that the caller does not have to keep re-calculating the same values, possibly in more than one place).
jmitc91516 1:a5258871b33d 1975
jmitc91516 1:a5258871b33d 1976 Args: the start and end Y axis values
jmitc91516 1:a5258871b33d 1977 the tick size (i.e. the interval between successive values
jmitc91516 1:a5258871b33d 1978 the X and Y coordinates of the graph
jmitc91516 1:a5258871b33d 1979 the height of the graph
jmitc91516 1:a5258871b33d 1980 boolean stating whether or not to record the parameter values
jmitc91516 1:a5258871b33d 1981 */
jmitc91516 1:a5258871b33d 1982 void GuiLibGraph::DrawYAxisLabels(GuiConst_INT32S minValue, GuiConst_INT32S maxValue, GuiConst_INT32S tickSize,
jmitc91516 1:a5258871b33d 1983 GuiConst_INT16S graphX, GuiConst_INT16S graphY, GuiConst_INT16S graphH, bool recordParameters)
jmitc91516 1:a5258871b33d 1984 {
jmitc91516 1:a5258871b33d 1985 int intervalCount = (maxValue - minValue) / tickSize;
jmitc91516 1:a5258871b33d 1986
jmitc91516 1:a5258871b33d 1987 GuiConst_INT16S xCoord = graphX; // GuiLib_ALIGN_RIGHT means that the text ends at the X coordinate
jmitc91516 1:a5258871b33d 1988
jmitc91516 1:a5258871b33d 1989 GuiConst_INT16S yCoord = graphY - 2; // 2 is also empirical - relative to the graph Y coordinate, it puts the labels in the correct place
jmitc91516 1:a5258871b33d 1990 GuiConst_INT16S yCoordInterval = (graphH / intervalCount) - 2; // 2 is also empirical - otherwise, the labels get out of step with the Y axis ticks as they go up the graph
jmitc91516 1:a5258871b33d 1991
jmitc91516 1:a5258871b33d 1992 const GuiConst_INT16U fontNo = GuiFont_Helv20Bold;
jmitc91516 1:a5258871b33d 1993 char text[100];
jmitc91516 1:a5258871b33d 1994
jmitc91516 1:a5258871b33d 1995 for(GuiConst_INT32S xValue = minValue; xValue <= maxValue; xValue += tickSize) {
jmitc91516 1:a5258871b33d 1996 sprintf(text, "%d", xValue);
jmitc91516 1:a5258871b33d 1997
jmitc91516 1:a5258871b33d 1998 GuiLib_DrawStr(
jmitc91516 1:a5258871b33d 1999 xCoord, //GuiConst_INT16S X,
jmitc91516 1:a5258871b33d 2000 yCoord, //GuiConst_INT16S Y,
jmitc91516 1:a5258871b33d 2001 fontNo, //GuiConst_INT16U FontNo,
jmitc91516 1:a5258871b33d 2002 text, //GuiConst_TEXT PrefixLocate *String,
jmitc91516 1:a5258871b33d 2003 GuiLib_ALIGN_RIGHT, //GuiConst_INT8U Alignment,
jmitc91516 1:a5258871b33d 2004 GuiLib_PS_ON, //GuiConst_INT8U PsWriting,
jmitc91516 1:a5258871b33d 2005 GuiLib_TRANSPARENT_ON, //GuiConst_INT8U Transparent,
jmitc91516 1:a5258871b33d 2006 GuiLib_UNDERLINE_OFF, //GuiConst_INT8U Underlining,
jmitc91516 1:a5258871b33d 2007 0, //GuiConst_INT16S BackBoxSizeX,
jmitc91516 1:a5258871b33d 2008 0, //GuiConst_INT16S BackBoxSizeY1,
jmitc91516 1:a5258871b33d 2009 0, //GuiConst_INT16S BackBoxSizeY2,
jmitc91516 1:a5258871b33d 2010 GuiLib_BBP_NONE, //GuiConst_INT8U BackBorderPixels,
jmitc91516 1:a5258871b33d 2011 0, //GuiConst_INTCOLOR ForeColor,
jmitc91516 1:a5258871b33d 2012 0xFFFF //GuiConst_INTCOLOR BackColor
jmitc91516 1:a5258871b33d 2013 );
jmitc91516 1:a5258871b33d 2014
jmitc91516 1:a5258871b33d 2015 yCoord -= yCoordInterval;
jmitc91516 1:a5258871b33d 2016 }
jmitc91516 1:a5258871b33d 2017
jmitc91516 1:a5258871b33d 2018 if(recordParameters) {
jmitc91516 1:a5258871b33d 2019 yAxisLabelData.isSet = true;
jmitc91516 1:a5258871b33d 2020 yAxisLabelData.minValue = minValue;
jmitc91516 1:a5258871b33d 2021 yAxisLabelData.maxValue = maxValue;
jmitc91516 1:a5258871b33d 2022 yAxisLabelData.tickSize = tickSize;
jmitc91516 1:a5258871b33d 2023 yAxisLabelData.graphX = graphX;
jmitc91516 1:a5258871b33d 2024 yAxisLabelData.graphY = graphY;
jmitc91516 1:a5258871b33d 2025 yAxisLabelData.graphH = graphH;
jmitc91516 1:a5258871b33d 2026 }
jmitc91516 1:a5258871b33d 2027 }
jmitc91516 1:a5258871b33d 2028
jmitc91516 1:a5258871b33d 2029 /*
jmitc91516 1:a5258871b33d 2030 Call the DrawYAxisLabels function (see above) with newly-calculated parameter values.
jmitc91516 1:a5258871b33d 2031
jmitc91516 1:a5258871b33d 2032 Args: the start and end Y axis values
jmitc91516 1:a5258871b33d 2033 the tick size (i.e. the interval between successive values
jmitc91516 1:a5258871b33d 2034 the X and Y coordinates of the graph
jmitc91516 1:a5258871b33d 2035 the height of the graph
jmitc91516 1:a5258871b33d 2036 */
jmitc91516 1:a5258871b33d 2037 void GuiLibGraph::DrawYAxisLabels(GuiConst_INT32S minValue, GuiConst_INT32S maxValue, GuiConst_INT32S tickSize,
jmitc91516 1:a5258871b33d 2038 GuiConst_INT16S graphX, GuiConst_INT16S graphY, GuiConst_INT16S graphH)
jmitc91516 1:a5258871b33d 2039 {
jmitc91516 1:a5258871b33d 2040 DrawYAxisLabels(minValue,
jmitc91516 1:a5258871b33d 2041 maxValue,
jmitc91516 1:a5258871b33d 2042 tickSize,
jmitc91516 1:a5258871b33d 2043 graphX,
jmitc91516 1:a5258871b33d 2044 graphY,
jmitc91516 1:a5258871b33d 2045 graphH,
jmitc91516 1:a5258871b33d 2046 true );
jmitc91516 1:a5258871b33d 2047 }
jmitc91516 1:a5258871b33d 2048
jmitc91516 1:a5258871b33d 2049 /*
jmitc91516 1:a5258871b33d 2050 Repeats the last call to the version of DrawYAxisLabels with parameters,
jmitc91516 1:a5258871b33d 2051 using the same parameter values (if available). This is so that the caller
jmitc91516 1:a5258871b33d 2052 does not have to repeatedly calculate the same values in more than one place.
jmitc91516 1:a5258871b33d 2053 */
jmitc91516 1:a5258871b33d 2054 void GuiLibGraph::DrawYAxisLabels(void)
jmitc91516 1:a5258871b33d 2055 {
jmitc91516 1:a5258871b33d 2056 if(yAxisLabelData.isSet) {
jmitc91516 1:a5258871b33d 2057 DrawYAxisLabels(yAxisLabelData.minValue,
jmitc91516 1:a5258871b33d 2058 yAxisLabelData.maxValue,
jmitc91516 1:a5258871b33d 2059 yAxisLabelData.tickSize,
jmitc91516 1:a5258871b33d 2060 yAxisLabelData.graphX,
jmitc91516 1:a5258871b33d 2061 yAxisLabelData.graphY,
jmitc91516 1:a5258871b33d 2062 yAxisLabelData.graphH,
jmitc91516 1:a5258871b33d 2063 false );
jmitc91516 1:a5258871b33d 2064 }
jmitc91516 1:a5258871b33d 2065 // else no values available - do nothing
jmitc91516 1:a5258871b33d 2066 }
jmitc91516 1:a5258871b33d 2067
jmitc91516 1:a5258871b33d 2068
jmitc91516 1:a5258871b33d 2069 /*
jmitc91516 1:a5258871b33d 2070 Draws the specified data set for this graph.
jmitc91516 1:a5258871b33d 2071
jmitc91516 1:a5258871b33d 2072 Encapsulates the easyGUI 'GuiLib_Graph_DrawDataSet' function,
jmitc91516 1:a5258871b33d 2073 passing it the index number specified for this graph,
jmitc91516 1:a5258871b33d 2074 and the data set index number given by the caller.
jmitc91516 1:a5258871b33d 2075
jmitc91516 1:a5258871b33d 2076 Note that a data set with that index must already have been created
jmitc91516 1:a5258871b33d 2077 in easyGUI for this graph.
jmitc91516 1:a5258871b33d 2078
jmitc91516 1:a5258871b33d 2079 Args: index number of the data set
jmitc91516 1:a5258871b33d 2080
jmitc91516 1:a5258871b33d 2081 */
jmitc91516 1:a5258871b33d 2082 GuiConst_INT8U GuiLibGraph::DrawDataSet(GuiConst_INT8U dataSetIndex)
jmitc91516 1:a5258871b33d 2083 {
jmitc91516 1:a5258871b33d 2084 return GuiLib_Graph_DrawDataSet(GuiLib_GraphIndex, dataSetIndex);
jmitc91516 1:a5258871b33d 2085 }
jmitc91516 1:a5258871b33d 2086
jmitc91516 1:a5258871b33d 2087 /*
jmitc91516 1:a5258871b33d 2088 Draws the specified data point in the specified data set for this graph.
jmitc91516 1:a5258871b33d 2089
jmitc91516 1:a5258871b33d 2090 Encapsulates the easyGUI 'GuiLib_Graph_DrawDataPoint' function,
jmitc91516 1:a5258871b33d 2091 passing it the index number specified for this graph,
jmitc91516 1:a5258871b33d 2092 and the data set and data point index numbers given by the caller.
jmitc91516 1:a5258871b33d 2093
jmitc91516 1:a5258871b33d 2094 Note that a data set with that index must already have been created
jmitc91516 1:a5258871b33d 2095 in easyGUI for this graph.
jmitc91516 1:a5258871b33d 2096
jmitc91516 1:a5258871b33d 2097 Args: index number of the data set
jmitc91516 1:a5258871b33d 2098 index number of the data point in that set
jmitc91516 1:a5258871b33d 2099
jmitc91516 1:a5258871b33d 2100 */
jmitc91516 1:a5258871b33d 2101 GuiConst_INT8U GuiLibGraph::DrawDataPoint(GuiConst_INT8U dataSetIndex, GuiConst_INT16U dataPointIndex)
jmitc91516 1:a5258871b33d 2102 {
jmitc91516 1:a5258871b33d 2103 return GuiLib_Graph_DrawDataPoint(GuiLib_GraphIndex, dataSetIndex, dataPointIndex);
jmitc91516 1:a5258871b33d 2104 }
jmitc91516 1:a5258871b33d 2105
jmitc91516 1:a5258871b33d 2106 /*
jmitc91516 1:a5258871b33d 2107 Shows the specified data set for this graph.
jmitc91516 1:a5258871b33d 2108
jmitc91516 1:a5258871b33d 2109 Encapsulates the easyGUI 'GuiLib_Graph_ShowDataSet' function,
jmitc91516 1:a5258871b33d 2110 passing it the index number specified for this graph,
jmitc91516 1:a5258871b33d 2111 and the data set index number given by the caller.
jmitc91516 1:a5258871b33d 2112
jmitc91516 1:a5258871b33d 2113 Note that a data set with that index must already have been created
jmitc91516 1:a5258871b33d 2114 in easyGUI for this graph.
jmitc91516 1:a5258871b33d 2115
jmitc91516 1:a5258871b33d 2116 Args: index number of the data set
jmitc91516 1:a5258871b33d 2117
jmitc91516 1:a5258871b33d 2118 */
jmitc91516 1:a5258871b33d 2119 GuiConst_INT8U GuiLibGraph::ShowDataSet(GuiConst_INT8U dataSetIndex)
jmitc91516 1:a5258871b33d 2120 {
jmitc91516 1:a5258871b33d 2121 return GuiLib_Graph_ShowDataSet(GuiLib_GraphIndex, dataSetIndex);
jmitc91516 1:a5258871b33d 2122 }
jmitc91516 1:a5258871b33d 2123
jmitc91516 1:a5258871b33d 2124 /*
jmitc91516 1:a5258871b33d 2125 Hides the specified data set for this graph.
jmitc91516 1:a5258871b33d 2126
jmitc91516 1:a5258871b33d 2127 Encapsulates the easyGUI 'GuiLib_Graph_HideDataSet' function,
jmitc91516 1:a5258871b33d 2128 passing it the index number specified for this graph,
jmitc91516 1:a5258871b33d 2129 and the data set index number given by the caller.
jmitc91516 1:a5258871b33d 2130
jmitc91516 1:a5258871b33d 2131 Note that a data set with that index must already have been created
jmitc91516 1:a5258871b33d 2132 in easyGUI for this graph.
jmitc91516 1:a5258871b33d 2133
jmitc91516 1:a5258871b33d 2134 Args: index number of the data set
jmitc91516 1:a5258871b33d 2135
jmitc91516 1:a5258871b33d 2136 */
jmitc91516 1:a5258871b33d 2137 GuiConst_INT8U GuiLibGraph::HideDataSet(GuiConst_INT8U dataSetIndex)
jmitc91516 1:a5258871b33d 2138 {
jmitc91516 1:a5258871b33d 2139 return GuiLib_Graph_HideDataSet(GuiLib_GraphIndex, dataSetIndex);
jmitc91516 1:a5258871b33d 2140 }
jmitc91516 1:a5258871b33d 2141
jmitc91516 1:a5258871b33d 2142 /*
jmitc91516 1:a5258871b33d 2143 Sets the range of the X axis for this graph.
jmitc91516 1:a5258871b33d 2144
jmitc91516 1:a5258871b33d 2145 Encapsulates the easyGUI 'GuiLib_Graph_SetXAxisRange' function,
jmitc91516 1:a5258871b33d 2146 passing it the index number specified for this graph,
jmitc91516 1:a5258871b33d 2147 the X axis index number (this depends on the selected units),
jmitc91516 1:a5258871b33d 2148 and the minimum and maximum values given by the caller.
jmitc91516 1:a5258871b33d 2149
jmitc91516 1:a5258871b33d 2150 Args: minimum value for the range
jmitc91516 1:a5258871b33d 2151 maximum value for the range
jmitc91516 1:a5258871b33d 2152
jmitc91516 1:a5258871b33d 2153 */
jmitc91516 1:a5258871b33d 2154 GuiConst_INT8U GuiLibGraph::SetXAxisRange(GuiConst_INT32S minValue, GuiConst_INT32S maxValue)
jmitc91516 1:a5258871b33d 2155 {
jmitc91516 1:a5258871b33d 2156 #define BOTH_AT_ONCE
jmitc91516 1:a5258871b33d 2157 #ifdef BOTH_AT_ONCE
jmitc91516 1:a5258871b33d 2158 // The graph coordinates seem to relate to X axis zero, regardless of which one we are actually displaying -
jmitc91516 1:a5258871b33d 2159 // so set both at once
jmitc91516 1:a5258871b33d 2160 if(GuiLib_Graph_SetXAxisRange(GuiLib_GraphIndex, MINUTES_XAXIS_INDEX, minValue, maxValue) == 0) {
jmitc91516 1:a5258871b33d 2161 // Failed
jmitc91516 1:a5258871b33d 2162 return 0;
jmitc91516 1:a5258871b33d 2163 }
jmitc91516 1:a5258871b33d 2164
jmitc91516 1:a5258871b33d 2165 // 'else' OK
jmitc91516 1:a5258871b33d 2166 return GuiLib_Graph_SetXAxisRange(GuiLib_GraphIndex, SECONDS_XAXIS_INDEX, minValue, maxValue);
jmitc91516 1:a5258871b33d 2167 #else
jmitc91516 1:a5258871b33d 2168 GuiConst_INT8U xAxisIndex = (xAxisUnits == SECONDS) ? SECONDS_XAXIS_INDEX : MINUTES_XAXIS_INDEX;
jmitc91516 1:a5258871b33d 2169
jmitc91516 1:a5258871b33d 2170 return GuiLib_Graph_SetXAxisRange(GuiLib_GraphIndex, xAxisIndex, minValue, maxValue);
jmitc91516 1:a5258871b33d 2171 #endif
jmitc91516 1:a5258871b33d 2172 }
jmitc91516 1:a5258871b33d 2173
jmitc91516 1:a5258871b33d 2174 /*
jmitc91516 1:a5258871b33d 2175 Sets the range of the Y axis for this graph.
jmitc91516 1:a5258871b33d 2176
jmitc91516 1:a5258871b33d 2177 Encapsulates the easyGUI 'GuiLib_Graph_SetYAxisRange' function,
jmitc91516 1:a5258871b33d 2178 passing it the index number specified for this graph,
jmitc91516 1:a5258871b33d 2179 the Y axis index number (currently always zero),
jmitc91516 1:a5258871b33d 2180 and the minimum and maximum values for its range given by the caller.
jmitc91516 1:a5258871b33d 2181
jmitc91516 1:a5258871b33d 2182 Args: minimum value for the range
jmitc91516 1:a5258871b33d 2183 maximum value for the range
jmitc91516 1:a5258871b33d 2184
jmitc91516 1:a5258871b33d 2185 */
jmitc91516 1:a5258871b33d 2186 GuiConst_INT8U GuiLibGraph::SetYAxisRange(GuiConst_INT32S minValue, GuiConst_INT32S maxValue)
jmitc91516 1:a5258871b33d 2187 {
jmitc91516 1:a5258871b33d 2188 GuiConst_INT8U yAxisIndex = YAXIS_INDEX;
jmitc91516 1:a5258871b33d 2189
jmitc91516 1:a5258871b33d 2190 return GuiLib_Graph_SetYAxisRange(GuiLib_GraphIndex, yAxisIndex, minValue, maxValue);
jmitc91516 1:a5258871b33d 2191 }
jmitc91516 1:a5258871b33d 2192
jmitc91516 1:a5258871b33d 2193 /*
jmitc91516 1:a5258871b33d 2194 Sets the data for the specified data set.
jmitc91516 1:a5258871b33d 2195
jmitc91516 1:a5258871b33d 2196 Args: the dataset index (this must already have been created in easyGUI)
jmitc91516 1:a5258871b33d 2197 (a pointer to) a GuiLibGraphDataSet object containing the new data
jmitc91516 1:a5258871b33d 2198 the time unit (minutes or seconds) to be used
jmitc91516 1:a5258871b33d 2199
jmitc91516 1:a5258871b33d 2200 Note that we reject dataset index values outside the range 0-9
jmitc91516 1:a5258871b33d 2201 (since we need to keep a pointer to the memory used, and currently
jmitc91516 1:a5258871b33d 2202 we only allow a fixed number of them).
jmitc91516 1:a5258871b33d 2203
jmitc91516 1:a5258871b33d 2204 */
jmitc91516 1:a5258871b33d 2205 GuiConst_INT8U GuiLibGraph::SetDataForGraphDataSet(GuiConst_INT8U dataSetIndex, GuiLibGraphDataSet* dataSet, TimeUnit timeUnit)
jmitc91516 1:a5258871b33d 2206 {
jmitc91516 1:a5258871b33d 2207 /*
jmitc91516 1:a5258871b33d 2208 This is a copy of the declaration of 'GuiLib_Graph_AddDataSet' in GuiLib.h:
jmitc91516 1:a5258871b33d 2209
jmitc91516 1:a5258871b33d 2210 extern GuiConst_INT8U GuiLib_Graph_AddDataSet(
jmitc91516 1:a5258871b33d 2211 GuiConst_INT8U GraphIndex,
jmitc91516 1:a5258871b33d 2212 GuiConst_INT8U DataSetIndex,
jmitc91516 1:a5258871b33d 2213 GuiConst_INT8U XAxisIndex,
jmitc91516 1:a5258871b33d 2214 GuiConst_INT8U YAxisIndex,
jmitc91516 1:a5258871b33d 2215 GuiLib_GraphDataPoint *DataPtr,
jmitc91516 1:a5258871b33d 2216 GuiConst_INT16U DataSize,
jmitc91516 1:a5258871b33d 2217 GuiConst_INT16U DataCount,
jmitc91516 1:a5258871b33d 2218 GuiConst_INT16U DataFirst);
jmitc91516 1:a5258871b33d 2219
jmitc91516 1:a5258871b33d 2220 We supply either default values for these parameters,
jmitc91516 1:a5258871b33d 2221 or get them from the GuiLibGraphDataSet object.
jmitc91516 1:a5258871b33d 2222 */
jmitc91516 1:a5258871b33d 2223
jmitc91516 1:a5258871b33d 2224 if(dataSetIndex < DATASET_INDEX_COUNT) {
jmitc91516 1:a5258871b33d 2225 // Make sure this data set, on this graph, has only the data we are about to 'add' to it -
jmitc91516 1:a5258871b33d 2226 // get rid of any existing data
jmitc91516 1:a5258871b33d 2227 GuiLib_Graph_RemoveDataSet(GuiLib_GraphIndex, dataSetIndex);
jmitc91516 1:a5258871b33d 2228
jmitc91516 1:a5258871b33d 2229 if(dataSetDataPtr[dataSetIndex] != NULL) {
jmitc91516 1:a5258871b33d 2230 delete [] dataSetDataPtr[dataSetIndex];
jmitc91516 1:a5258871b33d 2231 }
jmitc91516 1:a5258871b33d 2232
jmitc91516 1:a5258871b33d 2233 GuiConst_INT16U dataSize;
jmitc91516 1:a5258871b33d 2234 GuiLib_GraphDataPoint* dataCopy = dataSet->GetGraphDataPointCopy(timeUnit, &dataSize);
jmitc91516 1:a5258871b33d 2235
jmitc91516 1:a5258871b33d 2236 if(dataCopy != NULL) {
jmitc91516 1:a5258871b33d 2237 // Although the data is passed to us in an array allocated by the GuiLibGraphDataSet object,
jmitc91516 1:a5258871b33d 2238 // we keep a pointer to it in our own array, so that we can delete it when it is no longer required.
jmitc91516 1:a5258871b33d 2239 dataSetDataPtr[dataSetIndex] = dataCopy;
jmitc91516 1:a5258871b33d 2240
jmitc91516 1:a5258871b33d 2241 // I think this easyGUI function has a misleading name - you cannot 'add' a dataset with this function -
jmitc91516 1:a5258871b33d 2242 // you can only specify the data for a dataset that already exists
jmitc91516 1:a5258871b33d 2243 return GuiLib_Graph_AddDataSet(GuiLib_GraphIndex, dataSetIndex, 0, 0, dataSetDataPtr[dataSetIndex], dataSize, dataSize, 0);
jmitc91516 1:a5258871b33d 2244 }
jmitc91516 1:a5258871b33d 2245 // 'else' copy failed - drop through to error return
jmitc91516 1:a5258871b33d 2246 }
jmitc91516 1:a5258871b33d 2247
jmitc91516 1:a5258871b33d 2248 // 'else' dataset index out of range, or copy failed (see above)
jmitc91516 1:a5258871b33d 2249 return 0;
jmitc91516 1:a5258871b33d 2250 }
jmitc91516 1:a5258871b33d 2251
jmitc91516 1:a5258871b33d 2252
jmitc91516 1:a5258871b33d 2253 /*
jmitc91516 1:a5258871b33d 2254 Sets the data for the specified data set, using tenths of minutes as the X axis unit
jmitc91516 1:a5258871b33d 2255
jmitc91516 1:a5258871b33d 2256 Args: the dataset index (this must already have been created in easyGUI)
jmitc91516 1:a5258871b33d 2257 (a pointer to) a GuiLibGraphDataSet object containing the new data
jmitc91516 1:a5258871b33d 2258
jmitc91516 1:a5258871b33d 2259 Note that we reject dataset index values outside the range 0-9
jmitc91516 1:a5258871b33d 2260 (since we need to keep a pointer to the memory used, and currently
jmitc91516 1:a5258871b33d 2261 we only allow a fixed number of them).
jmitc91516 1:a5258871b33d 2262
jmitc91516 1:a5258871b33d 2263 */
jmitc91516 1:a5258871b33d 2264 GuiConst_INT8U GuiLibGraph::SetDataForGraphDataSetInTenthsOfMinutes(GuiConst_INT8U dataSetIndex, float yAxisScaleFactor, GuiLibGraphDataSet* dataSet)
jmitc91516 1:a5258871b33d 2265 {
jmitc91516 1:a5258871b33d 2266 /*
jmitc91516 1:a5258871b33d 2267 This is a copy of the declaration of 'GuiLib_Graph_AddDataSet' in GuiLib.h:
jmitc91516 1:a5258871b33d 2268
jmitc91516 1:a5258871b33d 2269 extern GuiConst_INT8U GuiLib_Graph_AddDataSet(
jmitc91516 1:a5258871b33d 2270 GuiConst_INT8U GraphIndex,
jmitc91516 1:a5258871b33d 2271 GuiConst_INT8U DataSetIndex,
jmitc91516 1:a5258871b33d 2272 GuiConst_INT8U XAxisIndex,
jmitc91516 1:a5258871b33d 2273 GuiConst_INT8U YAxisIndex,
jmitc91516 1:a5258871b33d 2274 GuiLib_GraphDataPoint *DataPtr,
jmitc91516 1:a5258871b33d 2275 GuiConst_INT16U DataSize,
jmitc91516 1:a5258871b33d 2276 GuiConst_INT16U DataCount,
jmitc91516 1:a5258871b33d 2277 GuiConst_INT16U DataFirst);
jmitc91516 1:a5258871b33d 2278
jmitc91516 1:a5258871b33d 2279 We supply either default values for these parameters,
jmitc91516 1:a5258871b33d 2280 or get them from the GuiLibGraphDataSet object.
jmitc91516 1:a5258871b33d 2281 */
jmitc91516 1:a5258871b33d 2282
jmitc91516 1:a5258871b33d 2283 if(dataSetIndex < DATASET_INDEX_COUNT) {
jmitc91516 1:a5258871b33d 2284 // Make sure this data set, on this graph, has only the data we are about to 'add' to it -
jmitc91516 1:a5258871b33d 2285 // get rid of any existing data
jmitc91516 1:a5258871b33d 2286 GuiLib_Graph_RemoveDataSet(GuiLib_GraphIndex, dataSetIndex);
jmitc91516 1:a5258871b33d 2287
jmitc91516 1:a5258871b33d 2288 if(dataSetDataPtr[dataSetIndex] != NULL) {
jmitc91516 1:a5258871b33d 2289 delete [] dataSetDataPtr[dataSetIndex];
jmitc91516 1:a5258871b33d 2290 }
jmitc91516 1:a5258871b33d 2291
jmitc91516 1:a5258871b33d 2292 GuiConst_INT16U dataSize;
jmitc91516 1:a5258871b33d 2293 GuiLib_GraphDataPoint* dataCopy = dataSet->GetGraphDataPointCopyInTenthsOfMinutes(yAxisScaleFactor, &dataSize);
jmitc91516 1:a5258871b33d 2294
jmitc91516 1:a5258871b33d 2295 if(dataCopy != NULL) {
jmitc91516 1:a5258871b33d 2296 // Although the data is passed to us in an array allocated by the GuiLibGraphDataSet object,
jmitc91516 1:a5258871b33d 2297 // we keep a pointer to it in our own array, so that we can delete it when it is no longer required.
jmitc91516 1:a5258871b33d 2298 dataSetDataPtr[dataSetIndex] = dataCopy;
jmitc91516 1:a5258871b33d 2299
jmitc91516 1:a5258871b33d 2300 // I think this easyGUI function has a misleading name - you cannot 'add' a dataset with this function -
jmitc91516 1:a5258871b33d 2301 // you can only specify the data for a dataset that already exists
jmitc91516 1:a5258871b33d 2302 return GuiLib_Graph_AddDataSet(GuiLib_GraphIndex, dataSetIndex, 0, 0, dataSetDataPtr[dataSetIndex], dataSize, dataSize, 0);
jmitc91516 1:a5258871b33d 2303 }
jmitc91516 1:a5258871b33d 2304 // 'else' copy failed - drop through to error return
jmitc91516 1:a5258871b33d 2305 }
jmitc91516 1:a5258871b33d 2306
jmitc91516 1:a5258871b33d 2307 // 'else' dataset index out of range, or copy failed (see above)
jmitc91516 1:a5258871b33d 2308 return 0;
jmitc91516 1:a5258871b33d 2309 }
jmitc91516 1:a5258871b33d 2310
jmitc91516 1:a5258871b33d 2311
jmitc91516 1:a5258871b33d 2312 /*
jmitc91516 1:a5258871b33d 2313 Sets the specified data set to consist of a single point.
jmitc91516 1:a5258871b33d 2314
jmitc91516 1:a5258871b33d 2315 Args: the dataset index (this must already have been created in easyGUI)
jmitc91516 1:a5258871b33d 2316 the X coordinate of the point
jmitc91516 1:a5258871b33d 2317 the Y coordinate of the point
jmitc91516 1:a5258871b33d 2318 */
jmitc91516 1:a5258871b33d 2319 GuiConst_INT8U GuiLibGraph::SetSinglePointForGraphDataSet(GuiConst_INT8U dataSetIndex, GuiConst_INT32S X, GuiConst_INT32S Y)
jmitc91516 1:a5258871b33d 2320 {
jmitc91516 1:a5258871b33d 2321 // return GuiLib_Graph_AddDataPoint(GuiLib_GraphIndex, dataSetIndex, X, Y);
jmitc91516 1:a5258871b33d 2322
jmitc91516 1:a5258871b33d 2323 /*
jmitc91516 1:a5258871b33d 2324 This is a copy of the declaration of 'GuiLib_Graph_AddDataSet' in GuiLib.h:
jmitc91516 1:a5258871b33d 2325
jmitc91516 1:a5258871b33d 2326 extern GuiConst_INT8U GuiLib_Graph_AddDataSet(
jmitc91516 1:a5258871b33d 2327 GuiConst_INT8U GraphIndex,
jmitc91516 1:a5258871b33d 2328 GuiConst_INT8U DataSetIndex,
jmitc91516 1:a5258871b33d 2329 GuiConst_INT8U XAxisIndex,
jmitc91516 1:a5258871b33d 2330 GuiConst_INT8U YAxisIndex,
jmitc91516 1:a5258871b33d 2331 GuiLib_GraphDataPoint *DataPtr,
jmitc91516 1:a5258871b33d 2332 GuiConst_INT16U DataSize,
jmitc91516 1:a5258871b33d 2333 GuiConst_INT16U DataCount,
jmitc91516 1:a5258871b33d 2334 GuiConst_INT16U DataFirst);
jmitc91516 1:a5258871b33d 2335
jmitc91516 1:a5258871b33d 2336 We supply either default values for these parameters,
jmitc91516 1:a5258871b33d 2337 or get them from the values passed to us.
jmitc91516 1:a5258871b33d 2338 */
jmitc91516 1:a5258871b33d 2339 GuiLib_GraphDataPoint dataPoint;
jmitc91516 1:a5258871b33d 2340 dataPoint.X = X;
jmitc91516 1:a5258871b33d 2341 dataPoint.Y = Y;
jmitc91516 1:a5258871b33d 2342
jmitc91516 1:a5258871b33d 2343 // I think this easyGUI function has a misleading name - you cannot 'add' a dataset with this function -
jmitc91516 1:a5258871b33d 2344 // you can only specify the data for a dataset that already exists
jmitc91516 1:a5258871b33d 2345 return GuiLib_Graph_AddDataSet(GuiLib_GraphIndex, dataSetIndex, 0, 0, &dataPoint, 10, 1, 0);
jmitc91516 1:a5258871b33d 2346 }
jmitc91516 1:a5258871b33d 2347
jmitc91516 1:a5258871b33d 2348 /*
jmitc91516 1:a5258871b33d 2349 Redraws this graph (by calling the easyGUI GuiLib_Graph_Redraw function).
jmitc91516 1:a5258871b33d 2350 This redraws the entire graph, including background, axes and data sets.
jmitc91516 1:a5258871b33d 2351 */
jmitc91516 1:a5258871b33d 2352 GuiConst_INT8U GuiLibGraph::Redraw(void)
jmitc91516 1:a5258871b33d 2353 {
jmitc91516 1:a5258871b33d 2354 return GuiLib_Graph_Redraw(GuiLib_GraphIndex);
jmitc91516 1:a5258871b33d 2355 }