E9d3f1a9ded6d6b118dd84467f2278df

This is my first C program.
Please DRY it if you can.
Thanks

/*
 * 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 !

F1e3ab214a976a39cfd713bc93deb10f

Tj Holowaychuk

November 18, 2009, November 18, 2009 16:39, permalink

No rating. Login to rate!

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

E9d3f1a9ded6d6b118dd84467f2278df

taro

November 19, 2009, November 19, 2009 11:10, permalink

No rating. Login to rate!

Hi, Tj Holowaychuk

I agree. Thanks

F9a9ba6663645458aa8630157ed5e71e

Ants

November 19, 2009, November 19, 2009 19:52, permalink

No rating. Login to rate!

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?

E9d3f1a9ded6d6b118dd84467f2278df

taro

November 19, 2009, November 19, 2009 20:25, permalink

No rating. Login to rate!

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

F9a9ba6663645458aa8630157ed5e71e

Ants

November 20, 2009, November 20, 2009 10:07, permalink

No rating. Login to rate!

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;
}
220a1ce7a99b513ece2aca0f6d4688c7

zetafish

November 23, 2009, November 23, 2009 14:53, permalink

1 rating. Login to rate!

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

Your refactoring





Format Copy from initial code

or Cancel