Skip to content

Instantly share code, notes, and snippets.

@adamgreig
Created February 13, 2015 16:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adamgreig/84e1f4dffc1924d7d94d to your computer and use it in GitHub Desktop.
Save adamgreig/84e1f4dffc1924d7d94d to your computer and use it in GitHub Desktop.
/*///------------------------------------------------------
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 |
random@randomskk.net |
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