forum wrote:
hi all
has anybody done a parallel object already ?
need to write to the par-port (no reading)
norbert, i think you've done this, can I have the code ?
mfg.dsa.rwe iohannes
hi iohannes & list,
sorry this is goin a bit long - skip it if you are not interested, and sorry too, the code is linux only.
Here is the code for an external which opens a file/character-device and writes characters to it. I used it to drive old pinwirters from pd.
BEWARE - this is very dangerous!! It might allow you to open an important file and hack into it. Better check carefully which file/device you open and, of course, never run this external as root.
/* file: lp.c */ /* Author: Norbert Math, math@alien.mur.at */ /* DISCLAIMER: I do not take any responsability for this code!!*/ /* code for line printer pd class */ /* Can also be used for writing into files and other caracter devices */
#include "m_pd.h" #include <stdio.h>
typedef struct lp { t_object t_ob; t_symbol *x_sym; t_symbol* filename; FILE* x_file; } t_lp;
void lp_ft1 (t_lp *x, t_floatarg g) { }
static void lp_print(t_lp *x,t_symbol* lpstring) { if (lpstring != &s_) x->x_sym = lpstring; fprintf (x->x_file, "%s\n", *x->x_sym); post("lp: %s", *x->x_sym); fflush(x->x_file); }
void lp_open(t_lp *x,t_symbol* filename) { x->filename = filename; post("lp: opening %s",x->filename->s_name); if ((x->x_file = fopen(x->filename->s_name, "w")) == NULL) { post("lp: Can't open %s", *x->filename); } setbuf(x->x_file, NULL); }
void lp_close(t_lp *x,t_symbol* filename) { x->filename = filename; post("lp: closing %s",x->filename->s_name); if ((x->x_file) == NULL) { post("lp: No file to close"); return; } if (fclose(x->x_file) !=0) { post("lp: Error closing %s", *x->filename); } }
void lp_free() { post("lp_free"); }
t_class *lp_class;
void *lp_new() { t_lp *x = (t_lp *)pd_new(lp_class); inlet_new(&x->t_ob, &x->t_ob.ob_pd, gensym("lp_in"), gensym("ft1")); post("lp_new"); return (void *)x; }
void lp_setup() { post("lp_setup"); lp_class = class_new(gensym("lp"), lp_new, 0, sizeof(t_lp), 0, 0); class_addmethod(lp_class, (t_method)lp_print, gensym("print"),A_DEFSYM,0); class_addmethod(lp_class, (t_method)lp_open, gensym("open"),A_DEFSYM,0); class_addmethod(lp_class, (t_method)lp_close, gensym("close"),A_DEFSYM,0); }
file: lp.pd This is an example of how to use lp.pd-linux first click on a "open" message, then on a "print" message, finally on a "close" message.
#N canvas 246 -6 600 484 8; #X obj 102 253 lp; #X msg 70 81 open /dev/lp0; #X msg 82 104 close /dev/lp0; #X msg 102 130 open foofile; #X msg 126 165 close foofile; #X msg 236 195 print hoi; #X msg 235 170 print ++++++++++++++++++++++++++++++++++; #X msg 237 219 print .; #X msg 235 115 0; #X msg 262 115 1; #X obj 235 145 metro 200; #X floatatom 296 116; #X connect 1 0 0 0; #X connect 2 0 0 0; #X connect 3 0 0 0; #X connect 4 0 0 0; #X connect 5 0 0 0; #X connect 6 0 0 0; #X connect 7 0 0 0; #X connect 8 0 10 0; #X connect 9 0 10 0; #X connect 10 0 6 0; #X connect 11 0 10 1;
If you need to access the parallel port directly, ie. you do not want to print out characters but you want to use it for controlling external hardware/relays you need to write the external yourself. Here are some, i hope useful, hints :
#include <unistd.h>
First, use ioperm to grant access to the I/O-Port (only root can call iopoerm!):
if(ioperm(0x378,1,1)) { fprintf(stderr,"ioperm error.\n"); exit(1); }
Check the bios if your par.port actually uses the address 0x378.
Then define this little assembler function:
static inline void port_out( unsigned short int port, unsigned char val ) { __asm__ volatile ( "outb %0,%1\n" : : "a" (val), "d" (port) ); }
Now, a call to port_out() sets the bits on the par.port.
port_out(0x378, 000);
sets all bits to 0.
Finally, just wrap foo1.c around it and your external is ready ;-)
Useful literature: The coffee mini-HOWTO describes how to control a coffe machine over the parallel port - when will we be able to make coffee with pd??
mfg
norbert