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
-------------------------------------------------------------
/* file: lp.c */
/* Author: Norbert Math, math(a)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