/*
* 0x378 - 0x37F are data pins
* 0x383 - 0x387 are status pins
* 0x388 - 0x38B are control pins
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <machine/cpufunc.h>
#include <signal.h>
#define DELAY 200000
#define PORT 0x378
short int i;
void openPort()
{
if(i386_set_ioperm(PORT, 1, 1))
{
fprintf(stderr, "error opening lpt");
exit(1);
}
}
void closePort()
{
if(i386_set_ioperm(PORT, 1, 0))
{
fprintf(stderr, "error closing lpt");
exit(1);
}
}
void throwOff()
{
outb(PORT, 0);
}
void countNumbers()
{
for(i = 255; i > -1; i--)
{
outb(PORT, i);
usleep(DELAY);
}
}
void serialToggle(short int mask)
{
for(i = 1; i < 256; i *= 2)
{
outb(PORT, i ^ mask);
usleep(DELAY);
}
}
void serialToggleReverse(short int mask)
{
for(i = 128; i > 0; i /= 2)
{
outb(PORT, i ^ mask);
usleep(DELAY);
}
}
void serialLoop(short int mask)
{
serialToggle(mask);
throwOff();
serialToggleReverse(mask);
}
void serialRiseUp(short int mask)
{
for(i = 1; i <= 256; i *= 2)
{
outb(PORT, i - 1 ^ mask);
usleep(DELAY);
}
}
void serialRiseDown(short int mask)
{
for(i = 256; i >= 1; i /= 2)
{
outb(PORT, i - 1 ^ mask);
usleep(DELAY);
}
}
void serialRise(short int mask)
{
serialRiseUp(mask);
serialRiseDown(mask);
}
void serialRiseReverse(short int mask)
{
serialRiseUp(mask);
serialRiseDown(~mask);
}
void centerLoopIn(short int mask)
{
for(i = 1; i < 9; i *= 2)
{
outb(PORT, (i + 128/i) ^ mask);
usleep(DELAY);
}
}
void centerLoopOut(short int mask)
{
for(i = 8; i > 0; i /= 2)
{
outb(PORT, (i + 128/i) ^ mask);
usleep(DELAY);
}
}
void centerLoop(short int mask)
{
centerLoopIn(mask);
throwOff();
centerLoopOut(mask);
}
void centerWalkIn(short int mask)
{
for(i = 1; i < 9; i *= 2)
{
outb(PORT, i ^ mask);
usleep(DELAY);
outb(PORT, 128/i ^ mask);
usleep(DELAY);
}
}
void centerWalkOut(short int mask)
{
for(i = 8; i > 0; i /= 2)
{
outb(PORT, i ^ mask);
usleep(DELAY);
outb(PORT, 128/i ^ mask);
usleep(DELAY);
}
}
void centerWalk(short int mask)
{
centerWalkIn(mask);
throwOff();
centerWalkOut(mask);
}
void sigIntHandler(int sigNo)
{
throwOff();
closePort();
exit(0);
}
int main()
{
signal(SIGINT, sigIntHandler);
openPort();
printf("Press key a-z for performance or ^C to quit\n");
short int c;
c=getchar();
while (1)
{
switch(c)
{
case 'a':
serialLoop(0);
break;
case 'b':
serialLoop(255);
break;
case 'c':
countNumbers();
break;
case 'd':
serialToggle(0);
break;
case 'e':
serialToggle(255);
break;
case 'f':
serialToggleReverse(0);
break;
case 'g':
serialToggleReverse(255);
break;
case 'h':
centerLoopIn(0);
break;
case 'i':
centerLoopIn(255);
break;
case 'j':
centerLoopOut(0);
break;
case 'k':
centerLoopOut(255);
break;
case 'l':
centerLoop(0);
break;
case 'm':
centerLoop(255);
break;
case 'n':
centerWalkIn(0);
break;
case 'o':
centerWalkIn(255);
break;
case 'p':
centerWalkOut(0);
break;
case 'q':
centerWalkOut(255);
break;
case 'r':
centerWalk(0);
break;
case 's':
centerWalk(255);
break;
case 't':
serialRiseUp(0);
break;
case 'u':
serialRiseUp(255);
break;
case 'v':
serialRiseDown(0);
break;
case 'w':
serialRiseDown(255);
break;
case 'x':
serialRise(0);
break;
case 'y':
serialRise(255);
break;
case 'z':
serialRiseReverse(255);
break;
}
}
return 0;
}
Refactorings
No refactoring yet !
Tj Holowaychuk
November 18, 2009, November 18, 2009 16:39, permalink
SIGINT interrupts normally no? why handle it and say it cant be handled lol id probably just leave it out completely if thats all your doing
Ants
November 19, 2009, November 19, 2009 19:52, permalink
What's the difference between serialRise() and serialRiseReverse()? The function bodies look the same.
In main(), is it intentional, that you only pick up the input character once and then loop infinitely?
taro
November 19, 2009, November 19, 2009 20:25, permalink
Hello, Ants
Actually, bodies of serialRise() and serialRiseReverse() have only one character difference.
No, it is not intentional, but can not do it in other way. If you can help improving this, please.
Thanks
Ants
November 20, 2009, November 20, 2009 10:07, permalink
Sorry, only just slightly clearer...
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <machine/cpufunc.h>
#include <signal.h>
#include <ctype.h>
/*
* 0x378 - 0x37F are data pins
* 0x383 - 0x387 are status pins
* 0x388 - 0x38B are control pins
*/
#define PORT 0x378
#define DELAY 200000
#define ZERO_BITS (0)
#define ALL_BITS (~ZERO_BITS)
#define CountOf(_rg) (sizeof(_rg)/sizeof(_rg[0]))
#define OutputEachBitUp(_max, _op) for(int i = 1; i <= (_max); i *= 2) { _op; }
#define OutputEachBitDown(_max, _op) for(int i = (_max); i > 0; i /= 2) { _op; }
#define OutputEachByteBit(_dir, _op) OutputEachBit##_dir(128, _op)
#define OutputEachNibbleBit(_dir, _op) OutputEachBit##_dir(8, _op)
#define OutputEachByteBitPattern(_dir, _x) OutputEachBit##_dir(128, OutputByteWithMask(_x, mask))
#define OutputEachNibbleBitPattern(_dir, _x) OutputEachBit##_dir(8, OutputByteWithMask(_x, mask))
#define OutputEachNibblePairBitPattern(_dir, _x) OutputEachBit##_dir(8, OutputNibblePairWithMask(_x, mask))
typedef short int BYTE;
typedef struct _functioncall
{
void (*func)(BYTE);
short int mask;
} FUNCTIONCALL;
void openPort()
{
if(i386_set_ioperm(PORT, 1, 1))
{
fprintf(stderr, "error opening lpt");
exit(1);
}
}
void closePort()
{
if(i386_set_ioperm(PORT, 1, 0))
{
fprintf(stderr, "error closing lpt");
exit(1);
}
}
void throwOff()
{
outb(PORT, 0);
}
void sigIntHandler(int sigNo)
{
throwOff();
closePort();
exit(0);
}
void OutputByteWithMask(BYTE b, BYTE mask)
{
outb(PORT, b ^ mask);
usleep(DELAY);
}
void countNumbers(BYTE unused)
{
for(int i = 255; i > -1; i--)
OutputByteWithMask(i, ZERO_BITS);
}
void serialToggle(BYTE mask)
{
OutputEachByteBitPattern(Up, i);
}
void serialToggleReverse(BYTE mask)
{
OutputEachByteBitPattern(Down, i);
}
void serialLoop(BYTE mask)
{
serialToggle(mask);
throwOff();
serialToggleReverse(mask);
}
void serialRiseUp(BYTE mask)
{
OutputEachByteBitPattern(Up, i - 1);
}
void serialRiseDown(BYTE mask)
{
OutputEachByteBitPattern(Down, i - 1);
}
void serialRise(BYTE mask)
{
serialRiseUp(mask);
serialRiseDown(mask);
}
void serialRiseReverse(BYTE mask)
{
serialRiseUp(mask);
serialRiseDown(~mask);
}
void centerLoopIn(BYTE mask)
{
OutputEachNibbleBitPattern(Up, i + 128 / i);
}
void centerLoopOut(BYTE mask)
{
OutputEachNibbleBitPattern(Down, i + 128 / i);
}
void centerLoop(BYTE mask)
{
centerLoopIn(mask);
throwOff();
centerLoopOut(mask);
}
void OutputNibblePairWithMask(BYTE nibble, BYTE mask)
{
OutputByteWithMask(nibble, mask);
OutputByteWithMask(128 / nibble, mask);
}
void centerWalkIn(BYTE mask)
{
OutputEachNibblePairBitPattern(Up, i);
}
void centerWalkOut(BYTE mask)
{
OutputEachNibblePairBitPattern(Down, i);
}
void centerWalk(BYTE mask)
{
centerWalkIn(mask);
throwOff();
centerWalkOut(mask);
}
FUNCTIONCALL g_rgfunctioncall[] =
{
{ serialLoop, ZERO_BITS }, // a
{ serialLoop, ALL_BITS }, // b
{ countNumbers, ZERO_BITS }, // c
{ serialToggle, ZERO_BITS }, // d
{ serialToggle, ALL_BITS }, // e
{ serialToggleReverse, ZERO_BITS }, // f
{ serialToggleReverse, ALL_BITS }, // g
{ centerLoopIn, ZERO_BITS }, // h
{ centerLoopIn, ALL_BITS }, // i
{ centerLoopOut, ZERO_BITS }, // j
{ centerLoopOut, ALL_BITS }, // k
{ centerLoop, ZERO_BITS }, // l
{ centerLoop, ALL_BITS }, // m
{ centerWalkIn, ZERO_BITS }, // n
{ centerWalkIn, ALL_BITS }, // o
{ centerWalkOut, ZERO_BITS }, // p
{ centerWalkOut, ALL_BITS }, // q
{ centerWalk, ZERO_BITS }, // r
{ centerWalk, ALL_BITS }, // s
{ serialRiseUp, ZERO_BITS }, // t
{ serialRiseUp, ALL_BITS }, // u
{ serialRiseDown, ZERO_BITS }, // v
{ serialRiseDown, ALL_BITS }, // w
{ serialRise, ZERO_BITS }, // x
{ serialRise, ALL_BITS }, // y
{ serialRiseReverse, ALL_BITS }, // z
};
FUNCTIONCALL * GetFunctionCall(char ch)
{
int i = toupper(ch) - 'A';
if (0 <= i && i < CountOf(g_rgfunctioncall))
return &g_rgfunctioncall[i];
return NULL;
}
void InvokeFunctionCall(FUNCTIONCALL * pfunctioncall)
{
if (pfunctioncall)
pfunctioncall->func(pfunctioncall->mask);
}
int main()
{
int ch;
signal(SIGINT, sigIntHandler);
printf("Press key a-z for performance, or ^Z or ^C to quit\n");
openPort();
while ((ch = getchar()) != EOF)
InvokeFunctionCall(GetFunctionCall(ch));
throwOff();
closePort();
return 0;
}
zetafish
November 23, 2009, November 23, 2009 14:53, permalink
The methods with the single loop basically run up or run down powers of 2. Iteration can be put in a seperate function. Only difference between the functions is how to get to the bits. The functions that combine in/out up/down also have similar pattern. Variation is to do a throwOff and to use the ~mask on the out/down pass.
typedef short int (* BITFUN)(short int, short int);
short int toggle(short int i, short int mask) { return i ^ mask ;}
short int rise(short int i, short int mask) { return i - (1 ^ mask); }
short int loop(short int i, short int mask) { return (i + 128/i) ^ mask; }
short int walk1(short int i, short int mask) { return i ^ mask; }
short int walk2(short int i, short int mask) { return 128/i ^ mask; }
typedef struct comdef {
int bits;
BITFUN bitfun[];
} COMDEF;
COMDEF TOGGLE = { 8, { toggle, NULL } };
COMDEF RISE = { 9, { rise, NULL } };
COMDEF LOOP = { 4, { loop, NULL } };
COMDEF WALK = { 4, { walk1, walk2, NULL } };
#define WITH_THROW 1
#define WITH_REVERSE 1
void emit(BITFUN* f, short int i, short int mask) {
while (f) {
short int bits = (**f)(i, mask);
outb(PORT, bits);
usleep(DELAY);
}
}
void up(COMDEF* def, short int mask) {
for (i = 0 ; i < def->bits ; ++i) {
emit(def->bitfun, 1 << i, mask);
}
}
void down(COMDEF* def, short int mask) {
for (i = def->bits - 1 ; i >= 0 ; --i) {
emit(def->bitfun, 1 << i, mask);
}
}
void combine(COMDEF* def, short int with, short int mask) {
up(def, mask);
if (WITH_THROW & with) {
throwOff();
}
down(def, WITH_REVERSE & with ? ~mask : mask);
}
void serialToggle(short int mask) { up( &TOGGLE, mask ); }
void serialToggleReverse(short int mask) { down( &TOGGLE, mask ); }
void serialRiseUp(short int mask) { up( &RISE, mask ); }
void serialRiseDown(short int mask) { down( &RISE, mask ); }
void centerLoopIn(short int mask) { up( &LOOP, mask ); }
void centerLoopOut(short int mask) { down( &LOOP, mask ); }
void centerWalkIn(short int mask) { up( &WALK, mask ); }
void centerWalkOut(short int mask) { down( &WALK, mask ); }
void serialLoop(short int mask) { combine( &TOGGLE, WITH_THROW, mask ); }
void serialRise(short int mask) { combine( &RISE, 0, mask ); }
void serialRiseReverse(short int mask) { combine( &RISE, WITH_REVERSE, mask ); }
void centerLoop(short int mask) { combine( &LOOP, WITH_THROW, mask ); }
void centerWalk(short int mask) { combine( &WALK, WITH_THROW, mask ); }
This is my first C program.
Please DRY it if you can.
Thanks