/* 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); };