/* LoadMeter.c
Stewart, January 10, 1984 8:48 PM, created
Stewart, January 11, 1984 11:52 AM, add logic
*/
#include "LoadMeter.h"
int pSwitch; /* packets per second switch */
int bSwitch; /* bits per second switch */
int tSwitch; /* time constant switch */
int oldpSw;
int oldbSw;
int oldtSw;
int oldSwitch; /* last switch poll value */
/* in memory storage of PIO state */
int pAutob; /* packets/second autoranging: BOOL */
int bAutob; /* bits/second autoranging: BOOL */
int bMode; /* bits/second mode, see LoadMeter.h */
int pMode; /* packets/second mode, see LoadMeter.h */
int tMode; /* averaging time mode, see LoadMeter.h */
/* the following three tables describe the connection
between the various modes and particular LEDs
*/
int pLedCV[4];
int bLedCV[4];
int tLedCV[4];
/* timers */
int tenths;
InitMeter()
{
InitLM();
STimer(500, &tenths);
};
DoMeter()
{
CheckWDT();
CheckSwitches();
UpdateLEDs();
DataCollect();
};
InitLM()
{
InitLMIO();
InitTables();
pSwitch = 0;
bSwitch = 0;
tSwitch = 0;
oldpSw = 2;
oldbSw = 2;
oldtSw = 2;
oldSwitch = 0x00A8;
pAutob = 0;
bAutob = 0;
pMode = ModeP30;
bMode = ModeB3;
tMode = ModeT03;
CycleTMode();
CycleBMode();
CyclePMode();
};
InitTables()
{
pLedCV[ModeP30] = LedP30;
pLedCV[ModeP100] = LedP100;
pLedCV[ModeP300] = LedP300;
pLedCV[ModeP1000] = LedP1000;
bLedCV[ModeB3] = LedB3;
bLedCV[ModeB10] = LedB10;
bLedCV[ModeB30] = LedB30;
bLedCV[ModeB100] = LedB100;
tLedCV[ModeT03] = LedT03;
tLedCV[ModeT1] = LedT1;
tLedCV[ModeT3] = LedT3;
tLedCV[ModeT10] = LedT10;
};
CheckSwitches()
{
int sw;
sw = InByte(lmpiob);
SwitchLogic(&oldpSw, sw >> switchPPS, &pSwitch);
SwitchLogic(&oldbSw, sw >> switchBPS, &bSwitch);
SwitchLogic(&oldtSw, sw >> switchTC, &tSwitch);
};
/* pOld is a pointer to an integer holding the "old"
value of the switch input bits
new is the new value of the input bits
pBool is a pointer to a boolean that is set on
up transitions of the switch
a down switch shows 1, an up switch shows 2, others
should be ignored
*/
SwitchLogic(pOld, new, pBool)
int *pOld, new, *pBool;
{
new &= 3;
if (*pOld == 2 && new == 1) { /* down transition */
*pOld = 1;
return;
};
if (*pOld == 1 && new == 2) { /* up transition */
*pOld = 2;
*pBool = true;
return;
};
};
UpdateLEDs()
{
if (pSwitch) {
CyclePMode();
pSwitch = false;
};
if (bSwitch) {
CycleBMode();
bSwitch = false;
};
if (tSwitch) {
CycleTMode();
tSwitch = false;
};
};
CycleTMode()
{
tMode = ModN(tMode, 4);
InitData();
SetLeds(tLedCV, tMode);
};
CyclePMode()
{
CycleFive(&pMode, &pAutob);
Bit(LedPAuto, pAutob);
SetLeds(pLedCV, pMode);
};
CycleBMode()
{
CycleFive(&bMode, &bAutob);
Bit(LedBAuto, bAutob);
SetLeds(bLedCV, bMode);
};
/* data handling sections for the Ethernet */
int bps[100];
int pps[100];
int now;
int limit;
int oldPPS;
int oldBPS;
int avgPPS;
/* double precision */
int avgBPS[2];
InitData()
{
int i;
now = 0;
switch (tMode) {
case ModeT03: limit = 3; break;
case ModeT1: limit = 10; break;
case ModeT3: limit = 30; break;
case ModeT10: limit = 100; break;
};
for (i = 0; i < limit; i += 1) bps[i] = pps[i] = 0;
};
DataCollect()
{
int i;
if (!Expired(&tenths)) return;
AddTimer(500, &tenths);
PollCounters();
avgPPS = 0;
avgBPS[0] = avgBPS[1] = 0;
for (i = 0; i < limit; i += 1) {
avgPPS += pps[i];
DoubleIncrement(avgBPS, bps[i]);
};
SetMeters();
};
/* call this every tenth of a second */
PollCounters()
{
int newBPS, newPPS;
newPPS = GetPPS();
pps[now] = UpdateModFK(oldPPS, newPPS);
oldPPS = newPPS;
newBPS = GetBPS();
bps[now] = UpdateModFK(oldBPS, newBPS);
oldBPS = newBPS;
now = ModN(now, limit);
};
SetMeters()
{
int bpsMeter, ppsMeter;
bpsMeter = 0;
ppsMeter = 0;
/* scale the bits per second numbers to 50000 / second */
/* scale the pps numbers to 1 second *10 and limit them */
switch (tMode) {
case ModeT03: {
/* the number in avgBPS can't be larger than 1500, so
we can use single prec. arith
*/
bpsMeter = (avgBPS[0] * 10) / 3; /* ls word */
ppsMeter = (UMin(avgPPS, MaxP03) * 100) / 3;
break;
};
case ModeT1: {
bpsMeter = avgBPS[0]; /* ls word */
ppsMeter = UMin(avgPPS, MaxP1) * 10;
break;
};
case ModeT3: {
bpsMeter = DoubleUDiv(avgBPS, 3);
ppsMeter = (UMin(avgPPS, MaxP3) * 10) / 3;
break;
};
case ModeT10: {
bpsMeter = DoubleUDiv(avgBPS, 10);
ppsMeter = UMin(avgPPS, MaxP10);
break;
};
};
/* limit to eventual full scale */
/* scale bits per second to full scale */
switch (bMode) {
case ModeB3: {
bpsMeter = (UMin(bpsMeter, 1500) / 3) * 100;
break;
};
case ModeB10: {
bpsMeter = UMin(bpsMeter, 5000) * 10;
break;
};
case ModeB30: {
bpsMeter = (UMin(bpsMeter, 15000) / 3) * 10;
break;
};
case ModeB100: {
bpsMeter = UMin(bpsMeter, 50000);
break;
};
};
/* now map 50000 to 1000 meter FS */
bpsMeter /= 50;
/* limit reading to eventual full scale */
/* scale packets per second to full scale */
switch (pMode) {
case ModeP30: {
ppsMeter = UMin(ppsMeter, 300) * 10 / 3;
break;
};
case ModeP100: {
ppsMeter = UMin(ppsMeter, 1000);
break;
};
case ModeP300: {
ppsMeter = UMin(ppsMeter, 3000) / 3;
break;
};
case ModeP1000: {
ppsMeter = UMin(ppsMeter, 10000) / 10;
break;
};
};
bpsMeter = Clip(0, bpsMeter, 1000);
ppsMeter = Clip(0, ppsMeter, 1000);
SetMeter(1, bpsMeter);
SetMeter(2, ppsMeter);
};