/**
* Linux parallel port userspace driver (ppdev) for the
* Nixdorf 0043/44 punch card reader with
* buffer 0377.01 (8 bit encoding)
*
* Copyright (c) March 2009 Sven Koeppel
*
* This program is free software; you can redistribute
* it and/or modify it under the terms of the GNU General
* Public License as published by the Free Software
* Foundation; either version 3 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will
* be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General
* Public License along with this program; if not, see
* .
*
**/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define PARPORT_DEVICE "/dev/parport0"
int parport_fd;
typedef enum {
MAGNET_ON,
MAGNET_OFF
} magnet_status_t;
void set_magnet(magnet_status_t target_status) {
unsigned char mask = (target_status==MAGNET_OFF ? PARPORT_CONTROL_AUTOFD : 0x0);
if(ioctl(parport_fd, PPWCONTROL, &mask)) {
perror("Setting magnet status (control lines)");
exit(0);
}
}
int mtime(long long since) {
/* gibt Millisekunden zurueck seit since. since sind dabei die
Millisekunden seit der Unix-Epoche. Ein initiales since kann
per mtime(0) gefunden werden. */
struct timeval time;
gettimeofday(&time, NULL);
// Sec*10^3
return (time.tv_sec * 1000 + (long long)(time.tv_usec / 1000)) - since;
}
void print_bit(char* label, int pos, unsigned char byte) {
int value = ((byte >> pos) & 0x01)==0 ? 0 : 1;
if(label == NULL)
printf("%i=%i ", pos, value);
else
printf("%s=%i ", label, value);
}
void simple_reading_program() {
// this will never touch the magnet...
long long abs_time = mtime(0);
for(;;) {
fflush(NULL);
unsigned char data;
unsigned char status;
fd_set rfds;
FD_ZERO (&rfds);
FD_SET (parport_fd, &rfds);
//printf("Waiting for interrupt...\n");
if (!select (parport_fd + 1, &rfds, NULL, NULL, NULL)) {
/* Caught a signal? */
printf("Caught a signal...");
continue;
}
// we've got that interrupt
// fetch current register values
if(ioctl(parport_fd, PPRDATA, &data)) {
perror("Interrupt data readout");
exit(1);
}
if(ioctl(parport_fd, PPRSTATUS, &status)) {
perror("Status data readout");
exit(1);
}
// display status:
printf("%i: ",(int)mtime(abs_time));
if(status & PARPORT_STATUS_SELECT) {
printf("DATA: ");
int pos;
for(pos=0; pos<8; print_bit(NULL, pos++, data));
printf("| STATUS: ");
print_bit("ERROR", 3, status);
print_bit("SEL", 4, status);
print_bit("PE", 5, status);
print_bit("ACK", 6, status);
print_bit("BUSY", 7, status);
printf("\n");
} else {
printf("no card.\n");
}
// clear the interrupt
unsigned char irqc;
ioctl(parport_fd, PPCLRIRQ, &irqc);
if(irqc > 1)
printf("MISSED %d INTTERUPT%s!!!!!\n", irqc-1, irqc == 2 ? "S" : "");
}
} // function
void magnet_testing_program() {
printf("Looping.\n");
int x = 10;
//for(x=0; x<10; x++) {
while(x > 0) {
printf("m = Magnet, o = Magnet off, q = Quit\n> ");
fflush(NULL);
switch(getchar()) {
case '\n': break;
case 'm':
printf("Magnet is ON!\n");
set_magnet(MAGNET_ON); break;
case 'q':
printf("Quitting\n");
x = -42;
break;
case 'o':
default:
printf("Magnet is OFF!\n");
set_magnet(MAGNET_OFF);
}
}
}
int main(int arvc, char** argv) {
printf("opening device %s...\n", PARPORT_DEVICE);
parport_fd = open(PARPORT_DEVICE, O_RDWR);
if(parport_fd == -1) {
perror("opening device failed");
return 1;
}
printf("claiming port...\n");
if(ioctl(parport_fd, PPCLAIM)) {
perror("claiming port (PPCLAIM)");
return 1;
}
printf("setting compatibility mode...\n");
int mode = IEEE1284_MODE_COMPAT; //BYTE; //COMPAT;
if(ioctl(parport_fd, PPNEGOT, &mode)) {
perror("Setting compatibilty mode (PPNEGOT)");
return 1;
}
printf("Disabling data line drivers...\n");
mode = 1;
if(ioctl(parport_fd, PPDATADIR, &mode)) {
perror("Setting PPDATADIR");
return 1;
}
printf("Ready to start.\n");
printf("Setting up control mask\n");
set_magnet(MAGNET_OFF);
//magnet_testing_program();
// now fetch interrupts and give out data at these times.
// never use the magnet.
simple_reading_program();
printf("Finished. Turning magnet off and quitting.\n");
set_magnet(MAGNET_OFF);
return 0;
} // main