enum StripChartOrientation {Vertical, Horizontal};
class StripChartField : public IOField
{
UINT *DataBuf;
PixelLoc *PixelBuf;
UINT PixelCount;
UINT NumPoints;
UINT DataHead;
UINT DataTail;
StripChartOrientation Orientation;
BOOL Changed;
public:
StripChartField(LCDDisplay *d, UINT x, UINT y, UINT w,
UINT h, StripChartOrientation o);
void NewPoint(UINT val);
virtual void Paint();
};
StripChartField::StripChartField(LCDDisplay *d, UINT x,
UINT y, UINT w, UINT h, StripChartOrientation o)
: (d, x, y, w, h)
{
Orientation = o;
DataHead = 0;
DataTail = 0;
PixelCount = 0;
Changed = FALSE;
/* I omit, for space, the initialization of the Data and Pixel
buffers */
}
void StripChartField::NewPoint(UINT val)
{
// add the point to the queue
DataHead = (DataHead + 1) % NumPoints;
if (DataHead == DataTail)
DataTail = (DataTail + 1) % NumPoints;
DataBuf[DataHead] = val;
Changed = TRUE;
}
void StripChartField::Paint()
{
if (Changed == FALSE) return;
Changed = FALSE;
// Erase all the old points on the screen
UINT t = 0;
while (t != PixelCount)
{
Display->Plot(PixelBuf[t].X, PixelBuf[t].Y, White);
t += 1;
}
// Set coordinates of pixels to draw
PixelCount = 0;
t = DataTail;
while (t != DataHead)
{
// scale the value so it fits in the graph
// only need to set the value of one coordinate now, other
// coordinate was set in the constructor as it will not
// change further
if (Orientation == Horizontal)
PixelBuf[PixelCount].Y =
(Y+H-1) - ((ULONG) DataBuf[t] *
(ULONG) (H-1)) / ((ULONG) USHRT_MAX + 1);
else
PixelBuf[PixelCount].X =
(X+W-1) - ((ULONG) DataBuf[t] *
(ULONG) (W-1)) / ((ULONG) USHRT_MAX + 1);
t = (t + 1) % NumPoints;
PixelCount+=1;
}
// Draw the points in PixelBuf
for (short i = 0; i < PixelCount; i++)
Display->Plot(PixelBuf[i].X, PixelBuf[i].Y, Black);
}
class ParmSelectField : public TextOutputIOField
{
protected:
PRM *PRM; // all system parameters of interest are PRM
objects
public:
ParmSelectField(LCDDisplay *d, UINT x, UINT y, UINT w,
UINT h);
PRM *GetParm(); // returns currently selected system parameter
virtual void GotFocus();
virtual void LostFocus();
virtual void DialMovedTo(UINT Position);
};
ParmSelectField::ParmSelectField(LCDDisplay *d, UINT x,
UINT y, UINT w, UINT h) : (d, x, y, w, h)
{
PRM = LastPRMAddedToList;
FontToUse = _8x8;
TColor = BlackOnWhite;
sprintf(buf, "%-10.10s %-4.4s", PRM->GetName(),
PRM->GetDisplayUnits());
Changed = TRUE;
}
PRM *ParmSelectField::GetParm()
{
return PRM;
}
void ParmSelectField::GotFocus()
{
// Highlight the field when it has the input focus
TColor = WhiteOnBlack;
Changed = TRUE;
}
void ParmSelectField::LostFocus()
{
// Unhighlight the field when it loses the input focus
TColor = BlackOnWhite;
Changed = TRUE;
}
void ParmSelectField::DialMovedTo(UINT Position)
{
/* I omit, for space, the mechanism by which a system
parameter is selected for display. The PRM is
beyond the scope of this article. */
// Output is the name of the system parameter and its units
PRM = p;
sprintf(buf, "%-10.10s %-4.4s", PRM->GetName(),
PRM->GetDisplayUnits());
Changed = TRUE;
}
class StripChartProcess : public IOProcess
{
DWORD Parm1Sample;
DWORD Parm2Sample;
StripChartField *Parm1Graph;
StripChartField *Parm2Graph;
ParmSelectField *Parm1Select;
ParmSelectField *Parm2Select;
TextOutputIOField *Parm1Numeric;
TextOutputIOField *Parm2Numeric;
PRM *LastPRM1;
PRM *LastPRM2;
DWORD LastS1;
DWORD LastS2;
void GetSamples();
protected:
virtual void Paint();
public:
StripChartProcess();
} StripChartDisplay;
StripChartProcess::StripChartProcess()
{
// instantiate the fields that are to be shown on the LCD
Parm1Select = new ParmSelectField(&Display, 120, 0, 120, 8);
Parm2Select = new ParmSelectField(&Display, 120, 32, 120, 8);
Parm1Graph =
new StripChartProcess(&Display, 0, 0, 120, 32,
Horizontal);
Parm2Graph =
new StripChartProcess(&Display, 0, 32, 120, 32,
Horizontal);
Parm1Numeric =
new TextOutputIOField(&Display, 120, 8, 120, 8);
Parm2Numeric =
new TextOutputIOField(&Display, 120, 40, 120, 8);
// Z order is not important, but set tab stops of the two
// input fields
RegisterField(Parm1Select, 0, 1);
RegisterField(Parm2Select, 0, 2);
RegisterField(Parm1Graph);
RegisterField(Parm2Graph);
RegisterField(Parm1Numeric);
RegisterField(Parm2Numeric);
LastPRM1 = NULL;
LastPRM2 = NULL;
LastS1 = 2340; // unusual value, not likely to
LastS2 = 2340; // come up the first time
// in a tenth of a second, grab the first set of samples
AlarmClock.WakeMeIn(ATENTHOFASECOND,
&StripChartProcess::GetSamples, this);
}
void StripChartProcess::Paint()
{
char buf[32];
DWORD s;
PRM *p; // a pointer to a system parameter
// reset the text fields showing parameter values if changed
p = Parm1Select->GetParm(); // first system parameter to view
s = p->GetSample();
if ((s != LastS1) || (p != LastPRM1))
{
p->GetDisplayValue(s, buf);
Parm1Numeric->SetText(_8x8, BlackOnWhite, buf);
LastPRM1 = p;
LastS1 = s;
}
p = Parm2Select->GetParm(); // second system parameter to view
s = p->GetSample();
if ((s != LastS2) || (p != LastPRM2))
{
p->GetDisplayValue(s, buf);
Parm2Numeric->SetText(_8x8, BlackOnWhite, buf);
LastPRM2 = p;
LastS2 = s;
}
// Call the base class Paint() function so strip chart,
// parameter select fields get updated
IOProcess::Paint();
}
//End of File