parallal port object

Norbert Math math at iem.kug.ac.at
Sun Oct 29 13:50:12 CET 2000


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 at 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                         



More information about the Pd-list mailing list