Created
February 13, 2015 16:46
-
-
Save adamgreig/84e1f4dffc1924d7d94d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*///------------------------------------------------------ | |
LPTMon - monitor CPU activity and new mail/RSS, display | | |
this on a series of LEDs connected to parallel | | |
port one (0x378). If there's a button on input | | |
one of LPT (pin 10), pressing that clears the | | |
new email/RSS status. | | |
To configure your mail/RSS reader, have it | | |
execute this program with either "newrss" or | | |
"newemail" as the first argument, to indicate | | |
a new item, or "norss" / "noemail" to indicate | | |
no new items. The argument "nonew" will clear | | |
both things (as though the button had been | | |
pressed). Note that you must start the program | | |
with no arguments to begin watching for new | | |
items and to show the CPU status. | | |
For instance, have this program autostart, and | | |
run it with relavant arguments when you get a | | |
new item. | | |
Technically, it uses LEDs on pins 2 and 3 for | | |
new email, pins 4 to 7 for CPU (each represents | | |
25%), and pins 8 and 9 for new RSS. | | |
This program uses three files - two to indicate | | |
new items, and one to indicate if the main | | |
process is currently running. They are called | | |
.newrss, .newemail and .lptmon and are stored in | | |
/tmp. | | |
(c) Adam Greig, 2006 | | |
[email protected] | | |
Licensing info: | | |
You may use and modify this as much as you want | | |
for personal use, and you may redistribute it | | |
so long as you give credit to the original | | |
author. You may not sell this software. | | |
NB: if compiler cannot find sys/io.h, use | | |
unistd.h AND asm/io.h (and get rid of sys/io.h) | | |
NB2: The instance of this program run without | | |
arguments MUST be run as root, otherwise it will | | |
not get permissions to access the parallel port. | | |
(ie, unless you run with -nolpt you need root.) | | |
*///------------------------------------------------------- | |
//standard output and file work | |
#include <iostream> | |
#include <cstdio> | |
#include <fstream> | |
#include <strings.h> | |
//include for writing to ports | |
#include <sys/io.h> | |
//include for handling signals | |
#include <signal.h> | |
using namespace std; | |
//define filenames and port bases | |
char CURRENTLYRUNNING[20]="/tmp/.lptmon"; | |
char NEWRSS[20]="/tmp/.newrss"; | |
char NEWEMAIL[20]="/tmp/.newemail"; | |
int LPTDATA=0x378; | |
int LPTSTATUS=0x379; | |
//define these as global | |
bool useLPT = true; | |
bool useGraphics = true; | |
bool doDaemon = false; | |
bool RSSOnOne = false; | |
bool EmailOnOne = false; | |
//define a parallel port class | |
class ParallelPort { | |
public: | |
//define the base while constructing | |
ParallelPort( int newBase ) : base(newBase) { } | |
//member function to write to the port | |
void Write(int value) { | |
if (value >= 0 && value <= 255) { | |
if (useLPT) { outb(value, base); } | |
//now to figure out the ASCII... :X | |
if (useGraphics) { | |
cout << "["; | |
if ((value&1) == 1) { cout << "(x)"; } else { cout << "( )"; } | |
if ((value&2) == 2) { cout << "(x)"; } else { cout << "( )"; } | |
if ((value&4) == 4) { cout << "(x)"; } else { cout << "( )"; } | |
if ((value&8) == 8) { cout << "(x)"; } else { cout << "( )"; } | |
if ((value&16) == 16) { cout << "(x)"; } else { cout << "( )"; } | |
if ((value&32) == 32) { cout << "(x)"; } else { cout << "( )"; } | |
if ((value&64) == 64) { cout << "(x)"; } else { cout << "( )"; } | |
if ((value&128) == 128) { cout << "(x)"; } else { cout << "( )"; } | |
cout << "]" << "\r" << flush; | |
} | |
currentValue = value; | |
} else { | |
cout << "Error: value not in range" << endl; | |
} | |
} | |
//member function to read from the port | |
int Read() { | |
return inb(base); | |
} | |
int currentValue; | |
protected: | |
const int base; | |
}; | |
//define a class for file access (check if already running, set running, | |
// check for new RSS and email, clear RSS, clear email). | |
class FileAccess { | |
public: | |
bool check(char szItem[10]) { | |
ifstream sNewItem(szItem); | |
int iNewItem = 0; | |
(sNewItem) >> iNewItem; | |
return iNewItem; | |
} | |
void set(char szItem[10], int nStatus) { | |
ofstream sSetItem(szItem); | |
sSetItem << nStatus << endl; | |
return; | |
} | |
}; | |
//make a global instance of the class | |
FileAccess fa; | |
//define a function to get CPU usage %.. eeep | |
int CPUUsage() { | |
int u1, n1, s1, i1; //first, define ints for the data read in from /proc/stat | |
int u2, n2, s2, i2; //next, ints to hold a second set of said data | |
int totalUse, totalTotal; //then, some ints for use in calculations | |
int totalPercent; //an int to return home | |
char cpu[31]; //useless char array to hold first piece of read data | |
FILE * fProcStat1; //new file | |
fProcStat1 = fopen ("/proc/stat","r"); //open the file | |
fscanf(fProcStat1, "%s %d %d %d %d", &cpu, &u1, &n1, &s1, &i1); //read the data into the ints | |
fclose (fProcStat1); //close file | |
sleep(1); //wait one second | |
FILE * fProcStat2; //second new file | |
fProcStat2 = fopen ("/proc/stat","r"); //open the file | |
fscanf(fProcStat2, "%s %d %d %d %d", &cpu, &u2, &n2, &s2, &i2); //read data into 2nd ints | |
fclose (fProcStat2); //close file | |
totalUse = (u2-u1) + (n2-n1) + (s2-s1); //first get total usage time | |
totalTotal = totalUse + (i2-i1); //next get total overall time | |
totalPercent = (100*totalUse)/totalTotal; //work out percentage from the two | |
return totalPercent; //return the percentage | |
} //there, that wasn't too bad, was it? | |
//thanks to JmSchanck from http://ubuntuforums.org/showpost.php?p=852594&postcount=2 | |
//for help with this, along with the source code for kcpuload ;P | |
//define a function to output a CPU usage number of LEDs to light | |
int outputCPU(int cpuPercent) { | |
if (cpuPercent >= 0 && cpuPercent <=24) { | |
return 1; | |
} else if (cpuPercent >= 25 && cpuPercent <= 49) { | |
return 2; | |
} else if (cpuPercent >= 50 && cpuPercent <= 74) { | |
return 3; | |
} else if (cpuPercent >= 75 && cpuPercent <= 100) { | |
return 4; | |
} | |
return 1; | |
} | |
//define a function to output usage for the program | |
void Usage() { | |
cout << "lptMon, Adam Greig, 2006. Version 1. \nSee source for details & copyright.\n"; | |
cout << "This program must be started once as a daemon, and then can be called again\n"; | |
cout << "with arguments. Possible arguments are:\n\n"; | |
cout << "No mode:\n-h\tOutput this help.\n\n"; | |
cout << "Daemon mode:\n-nolpt \tdo not actually access LTP (will not need root)\n"; | |
cout << "-nographics\tdo not draw to the console, just write to LTP\n"; | |
cout << "(no arguments)\twrite graphics and to LPT, needs root\n\n"; | |
cout << "Non-Daemon mode (normally run by a mail/rss reader):\nnewrss\tindicate that there are new RSS messages\n"; | |
cout << "newemail\tindicate that there are new email messages\n"; | |
cout << "norss\tindicate that there are no new RSS messages\n"; | |
cout << "nomail\tindicate that there are no new email messages\n"; | |
cout << "nonew\tclear all new items\n\n"; | |
cout << "Check the source code for more verbose instructions." << endl; | |
} | |
//function to exit gracefully | |
void graceful_exit(int nSignal) { | |
fa.set(CURRENTLYRUNNING, 0); | |
cout << endl; | |
exit(0); | |
} //thanks to ylixir on http://ubuntuforums.org/showpost.php?p=1332270&postcount=2 | |
// for help with this one | |
int main(int argc, char* argv[]) { | |
//setup signal handling | |
signal(SIGINT, graceful_exit); | |
if (argc == 2) { | |
if (!strcmp(argv[1], "-h")) { | |
Usage(); | |
} else if (!strcmp(argv[1], "-nolpt")) { | |
useLPT = false; | |
doDaemon = true; | |
} else if (!strcmp(argv[1], "-nographics")) { | |
useGraphics = false; | |
doDaemon = true; | |
} else if (!strcmp(argv[1], "newemail")) { | |
fa.set(NEWEMAIL, 1); | |
exit(0); | |
} else if (!strcmp(argv[1], "newrss")) { | |
fa.set(NEWRSS, 1); | |
exit(0); | |
} else if (!strcmp(argv[1], "noemail")) { | |
fa.set(NEWEMAIL, 0); | |
exit(0); | |
} else if (!strcmp(argv[1], "norss")) { | |
fa.set(NEWRSS, 0); | |
exit(0); | |
} else if (!strcmp(argv[1], "nonew")) { | |
fa.set(NEWRSS, 0); | |
fa.set(NEWEMAIL, 0); | |
exit(0); | |
} else { | |
Usage(); | |
} | |
} | |
if (argc == 1 || doDaemon) { | |
//if we're to run as a daemon | |
//check if we're running | |
if (fa.check(CURRENTLYRUNNING)) { | |
cerr << "Error: This program appears to already be running. \nIf you're" | |
<< " sure it is not, delete the file /tmp/.lptmon and try again." | |
<< endl; | |
exit(1); | |
} | |
//set ourselves as running | |
fa.set(CURRENTLYRUNNING, 1); | |
//open up the port | |
if (useLPT) { | |
if (ioperm(LPTDATA,2,1)) { | |
fprintf(stderr, "Could not access LPT, failing! Are you running this as root?\n"); | |
fa.set(CURRENTLYRUNNING,0); | |
exit(1); | |
} | |
} | |
//create two parallel ports | |
ParallelPort lptData(LPTDATA); | |
ParallelPort lptStatus(LPTSTATUS); | |
//setup an int to hold CPU usage | |
int cpuUsage; | |
int cpuLEDs; | |
//and some ints to hold RSS/email status | |
bool newRSS; | |
bool newEmail; | |
//and an int to hold LPT input status | |
int lptInput; | |
//and finally show a key if we're using console graphics | |
if (useGraphics) { | |
cout << " RSS CPU EMAIL" << endl; | |
} | |
// START MAIN PROGRAM LOOP HERE | |
// ---------------------------- | |
while (true) { //main program loop | |
//Get CPU usage, display it | |
//------------------------------------------- | |
cpuUsage = CPUUsage(); | |
cpuLEDs = outputCPU(cpuUsage); | |
switch (cpuLEDs) { | |
case 1: | |
lptData.Write(4); | |
break; | |
case 2: | |
lptData.Write(12); | |
break; | |
case 3: | |
lptData.Write(28); | |
break; | |
case 4: | |
lptData.Write(60); | |
break; | |
} | |
//------------------------------------------- | |
//Check for new RSS/email | |
//------------------------------------------- | |
newRSS = fa.check(NEWRSS); | |
newEmail = fa.check(NEWEMAIL); | |
//------------------------------------------- | |
//Check for input on LPT | |
//------------------------------------------- | |
if (useLPT) { | |
lptInput = lptStatus.Read(); | |
if (lptInput == 127) { lptInput = 0; } else | |
if (lptInput == 63) { lptInput = 1; } | |
if (lptInput == 1) { | |
fa.set(NEWRSS, 0); | |
fa.set(NEWEMAIL, 0); | |
newRSS = 0; | |
newEmail = 0; | |
} | |
} | |
//------------------------------------------- | |
//Process new RSS/email | |
//------------------------------------------- | |
if (newRSS) { | |
if (RSSOnOne) { | |
lptData.Write((lptData.currentValue) + 2); | |
RSSOnOne = false; | |
} else { | |
lptData.Write((lptData.currentValue) + 1); | |
RSSOnOne = true; | |
} | |
} | |
if (newEmail) { | |
if (EmailOnOne) { | |
lptData.Write((lptData.currentValue) + 128); | |
EmailOnOne = false; | |
} else { | |
lptData.Write((lptData.currentValue) + 64); | |
EmailOnOne = true; | |
} | |
} | |
//------------------------------------------- | |
} | |
// ---------------------------- | |
// END MAIN PROGRAM LOOP HERE | |
fa.set(CURRENTLYRUNNING,0); | |
} else if (argc > 2) { | |
Usage(); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment