Update of /cvsroot/pure-data/externals/hardware/multio In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv7896
Added Files: Makefile help-multio.pd multio.c Log Message: checking in first usable version
--- NEW FILE: help-multio.pd --- #N canvas 112 95 1011 631 12; #X obj 132 124 tgl 30 0 empty empty empty 0 -6 0 8 -62784 -1 -1 0 1 ; #X obj 506 210 unpack f f; #X floatatom 421 247 5 0 0 0 - - -; #X floatatom 499 248 5 0 0 0 - - -; #X msg 132 161 open; #X obj 132 202 multio; #X msg 132 69 readout_time 20; #X msg 132 98 readout_time 1000; #X msg 132 25 readout_time 1; #X text 185 163 <-- open the device (opened by default if possible) ; #X text 170 132 <-- start/stop readout of the device (on by default) ; #X text 290 39 <--+ | <--+-> set the time between readouts (msec) | 20 msec is the default <--+; #X obj 123 357 vsl 30 128 0 4096 0 0 empty empty empty 0 -8 0 8 -128992 -1 -1 59 1; #X obj 154 357 vsl 30 128 0 4096 0 0 empty empty empty 0 -8 0 8 -128992 -1 -1 198 1; #X obj 185 357 vsl 30 128 0 4096 0 0 empty empty empty 0 -8 0 8 -128992 -1 -1 177 1; #X obj 216 357 vsl 30 128 0 4096 0 0 empty empty empty 0 -8 0 8 -128992 -1 -1 155 1; #X obj 247 357 vsl 30 128 0 4096 0 0 empty empty empty 0 -8 0 8 -128992 -1 -1 3 1; #X obj 278 357 vsl 30 128 0 4096 0 0 empty empty empty 0 -8 0 8 -128992 -1 -1 0 1; #X obj 309 357 vsl 30 128 0 4096 0 0 empty empty empty 0 -8 0 8 -128992 -1 -1 186 1; #X obj 340 357 vsl 30 128 0 4096 0 0 empty empty empty 0 -8 0 8 -128992 -1 -1 769 1; #X obj 371 357 vsl 30 128 0 4096 0 0 empty empty empty 0 -8 0 8 -128992 -1 -1 353 1; #X obj 402 357 vsl 30 128 0 4096 0 0 empty empty empty 0 -8 0 8 -128992 -1 -1 1659 1; #X obj 433 357 vsl 30 128 0 4096 0 0 empty empty empty 0 -8 0 8 -128992 -1 -1 1380 1; #X obj 123 274 route 0 1 2 3 4 5 6 7 8 9 10; #X obj 433 311 nbx 4 16 -1e+037 1e+037 0 0 empty empty empty 0 -6 0 14 -262144 -1 -1 445 256; #X obj 402 330 nbx 4 16 -1e+037 1e+037 0 0 empty empty empty 0 -6 0 14 -262144 -1 -1 535 256; #X obj 371 311 nbx 4 16 -1e+037 1e+037 0 0 empty empty empty 0 -6 0 14 -262144 -1 -1 114 256; #X obj 340 330 nbx 4 16 -1e+037 1e+037 0 0 empty empty empty 0 -6 0 14 -262144 -1 -1 248 256; #X obj 309 311 nbx 4 16 -1e+037 1e+037 0 0 empty empty empty 0 -6 0 14 -262144 -1 -1 60 256; #X obj 278 330 nbx 4 16 -1e+037 1e+037 0 0 empty empty empty 0 -6 0 14 -262144 -1 -1 0 256; #X obj 247 311 nbx 4 16 -1e+037 1e+037 0 0 empty empty empty 0 -6 0 14 -262144 -1 -1 1 256; #X obj 216 330 nbx 4 16 -1e+037 1e+037 0 0 empty empty empty 0 -6 0 14 -262144 -1 -1 50 256; #X obj 185 311 nbx 4 16 -1e+037 1e+037 0 0 empty empty empty 0 -6 0 14 -262144 -1 -1 57 256; #X obj 154 330 nbx 4 16 -1e+037 1e+037 0 0 empty empty empty 0 -6 0 14 -262144 -1 -1 64 256; #X obj 123 311 nbx 4 16 -1e+037 1e+037 0 0 empty empty empty 0 -6 0 14 -262144 -1 -1 19 256; #X msg 130 46 readout_time 5; #X connect 0 0 5 0; #X connect 1 0 2 0; #X connect 1 1 3 0; #X connect 4 0 5 0; #X connect 5 0 23 0; #X connect 5 1 1 0; #X connect 6 0 5 0; #X connect 7 0 5 0; #X connect 8 0 5 0; #X connect 23 0 34 0; #X connect 23 1 33 0; #X connect 23 2 32 0; #X connect 23 3 31 0; #X connect 23 4 30 0; #X connect 23 5 29 0; #X connect 23 6 28 0; #X connect 23 7 27 0; #X connect 23 8 26 0; #X connect 23 9 25 0; #X connect 23 10 24 0; #X connect 24 0 22 0; #X connect 25 0 21 0; #X connect 26 0 20 0; #X connect 27 0 19 0; #X connect 28 0 18 0; #X connect 29 0 17 0; #X connect 30 0 16 0; #X connect 31 0 15 0; #X connect 32 0 14 0; #X connect 33 0 13 0; #X connect 34 0 12 0; #X connect 35 0 5 0;
--- NEW FILE: multio.c --- /* multio
connects to multIO and listens.. left outlet for analog middle for digital
output is a list of 2 floats (channel, value)
*/ #ifdef NT #include <windows.h> #endif
#include "m_pd.h" #include "usb.h" #include "pthread.h"
#define DEFDELTIME 20 // time between readouts in msec #define TIMEOUT 1000 // timeout time in usb interrupts reading and writing #define MAXBUF 1024
/* PICkit USB values */ static const int multio_vendorID=0xdead; // Microchip, Inc static const int multio_productID=0xbeef; // PICkit 1 FLASH starter kit static const int multio_configuration=2; /* 1: HID; 2: vendor specific */ static const int multio_interface=0; static const int reqLen=8; static char is_open; typedef unsigned char byte;
static t_class *multio_class;
typedef struct _multio { t_object x_obj; // myself usb_dev_handle *d; // handle to multIO t_clock *x_clock; // as in metro double x_deltime; // as in metro int x_hit; // as in metro pthread_attr_t multio_thread_attr; pthread_t x_threadid; unsigned char double_buffer[2][MAXBUF]; // a double buffer: thread writes one, cyclic read of the other one // the second parameter should be deafult 1000 but setable via // object parameters int buf_count[2]; // how many bytes are in a buffer unsigned char whichbuf; // which one to read from char old_digi[8]; // buffer of digital input, is a byte, 8 values at a time char digi_outs[8]; // buffer of digital input, is a byte, 8 values at a time int analog_buffer[64]; // buffered analog outs t_outlet *a_out, *d_out, *s_out; // outlets } t_multio;
static void *usb_read_thread(void *w) { t_multio *x = (t_multio*) w; int cnt = 0; int bytesread = 0; unsigned char mybuf = 1; unsigned char buffer[8]; while(1) // never ending { pthread_testcancel(); if(x->d) // only read if the device is opened { if(x->buf_count[x->whichbuf] <= 0) // check if the read buffer is empty { mybuf = x->whichbuf; // if so, use it for writing x->whichbuf = !(x->whichbuf &1); // and toggle the read buffer } bytesread = usb_interrupt_read(x->d, 0x81, buffer, 8, 1000); if(bytesread > 0) { if(x->buf_count[mybuf]+bytesread > MAXBUF) x->buf_count[mybuf] = 0; x->double_buffer[mybuf][x->buf_count[mybuf]++] = bytesread; // store the number of bytes for that message for(cnt = 0; cnt < bytesread; cnt++) // append the message data into the buffer { x->double_buffer[mybuf][x->buf_count[mybuf]++] = buffer[cnt]; } // post("thread read %i bytes to buffer %i (now %i bytes)",bytesread, mybuf,x->buf_count[mybuf] ); } } #ifdef NT Sleep(1); #endif } }
static void start_thread(t_multio *x) {
// create the worker thread if(pthread_attr_init(&x->multio_thread_attr) < 0) { post("multio: could not launch receive thread"); return; } if(pthread_attr_setdetachstate(&x->multio_thread_attr, PTHREAD_CREATE_DETACHED) < 0) { post("multio: could not launch receive thread"); return; } if(pthread_create(&x->x_threadid, &x->multio_thread_attr, usb_read_thread, x) < 0) { post("multio: could not launch receive thread"); return; } else { post("multio: thread %d launched", (int)x->x_threadid ); } }
// methods invoked by the inlets static void multio_analog_write(t_multio *x, t_symbol *s, int argc, t_atom *argv) { int channel; int value; unsigned char buffer[8]; int bytesread; if (argc<2) { error("multio: multio_analog_write error: i need minimum 2 values list"); return; }
if (!(x->d)) { error("multio: multI/O not initialized"); return; }
channel = atom_getfloat(argv++); value = atom_getfloat(argv);
if(channel < 0 || channel > 63) { error("multio: inconsistent dac output channel"); return; }
if (value != x->analog_buffer[channel]) { x->analog_buffer[channel] = value; buffer[0] = 97 + channel; // channel is 0 based buffer[1] = value & 0xff; buffer[2] = (value & 0xff00) >> 8; bytesread = usb_interrupt_write(x->d, 1, buffer, 3, TIMEOUT); } }
static void multio_digi_write(t_multio *x, t_symbol *s, int argc, t_atom *argv) { int channel; int value; unsigned char buffer[8]; int bytesread; char testbit = 0x01; int count; int group; int channel_in_group; char ctmp; char bitmask;
if (argc<2) { error("multio: multio_digi_write error: i need minimum 2 values list"); return; } channel = atom_getfloat(argv++); value = atom_getfloat(argv);
if(channel < 0 || channel > 63) { error("multio: inconsistent digital output channel"); return; }
group = channel / 8 ; channel_in_group = channel % 8;
bitmask = 0x01 << channel_in_group; ctmp = x->digi_outs[group] & ~bitmask; if (value) ctmp = ctmp | bitmask; if(ctmp != x->digi_outs[group]) { x->digi_outs[group] = ctmp; buffer[0] = group + 1; // + 1 is the offset for digi outs (1..9) buffer[1] = ctmp; bytesread = usb_interrupt_write(x->d, 1, buffer, 3, TIMEOUT); post("multio: writing %i to group %i", ctmp, group); }
}
static void multio_system_write(t_multio *x, t_symbol *s, int argc, t_atom *argv) {
unsigned char cmd, bvalue, smallvalue; unsigned short int value; unsigned char buffer[5];
if (argc<3) { error("multio: multio_system_write error: i need minimum 3 values list"); return; } cmd = atom_getfloat(argv++); bvalue = atom_getfloat(argv++);
buffer[0] = 161; buffer[1] = cmd; buffer[2] = bvalue;
switch(cmd) { case 0: case 1: usb_interrupt_write(x->d, 1, buffer, 3, TIMEOUT); break; case 2: case 3: case 4: value = atom_getfloat(argv); buffer[3] = value & 0x00ff; buffer[4] = value >> 8; usb_interrupt_write(x->d, 1, buffer, 5, TIMEOUT); break; case 5: case 6: case 7: case 8: buffer[3] = atom_getfloat(argv); usb_interrupt_write(x->d, 1, buffer, 4, TIMEOUT); break; case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17: usb_interrupt_write(x->d, 1, buffer, 3, TIMEOUT); break; default: error("multio: unknown system command"); break; } }
// read & process the buffer // this will be called each tick in the pd object static void process_buffer(t_multio *x) { int cnt; if(x->buf_count[x->whichbuf] > 0) { // post("process %i bytes buffer\n", x->buf_count[x->whichbuf]); for(cnt = 0; cnt < x->buf_count[x->whichbuf]; cnt++) { if(x->double_buffer[x->whichbuf][cnt] == 2) { // post("process buf: %i msglen: %i id: %i val: %i", x->whichbuf, x->double_buffer[x->whichbuf][cnt],x->double_buffer[x->whichbuf][cnt+1],x->double_buffer[x->whichbuf][cnt+2]); if (x->double_buffer[x->whichbuf][cnt+1]>=1 && x->double_buffer[x->whichbuf][cnt+1] <= 8) { // digital input //send_digi(x, first-1, buffer[1]); char testbit = 0x01; t_atom lista[2]; int count; int group = x->double_buffer[x->whichbuf][cnt+1]-1;
for(count = 0; count < 8; count++) { if((x->double_buffer[x->whichbuf][cnt+2] & testbit) != (x->old_digi[group] & testbit)) { SETFLOAT(lista, (group*8)+count); if(x->double_buffer[x->whichbuf][cnt+2] & testbit) SETFLOAT(lista+1, 1); else SETFLOAT(lista+1, 0); outlet_anything(x->d_out, gensym("list") , 2, lista); } testbit <<= 1; } x->old_digi[group] = x->double_buffer[x->whichbuf][cnt+2]; } cnt += 2; } else if(x->double_buffer[x->whichbuf][cnt] == 3) { // post("process buf: %i msglen: %i id: %i val: %i", x->whichbuf, x->double_buffer[x->whichbuf][cnt],x->double_buffer[x->whichbuf][cnt+1],x->double_buffer[x->whichbuf][cnt+2] + (x->double_buffer[x->whichbuf][cnt+3] << 8)); if (x->double_buffer[x->whichbuf][cnt+1]>=9 && x->double_buffer[x->whichbuf][cnt+1] <=96) { // analog input t_atom lista[2]; int result; int channel = x->double_buffer[x->whichbuf][cnt+1]-9;
result = x->double_buffer[x->whichbuf][cnt+2] + (x->double_buffer[x->whichbuf][cnt+3] << 8); x->analog_buffer[channel] = result;
SETFLOAT(lista, channel); SETFLOAT(lista+1, result); outlet_anything(x->a_out, gensym("list"),2 , lista); } cnt += 3; } else cnt += x->double_buffer[x->whichbuf][cnt]; } x->buf_count[x->whichbuf] = 0; } }
/* // method invoked by the timer static void multio_read(t_multio *x) { unsigned char buffer[8]; int first; int bytesread; byte retData[8]; int reads=64;
if (x->d) { } else { post("error, connection not inizialized"); return; }
while(usb_interrupt_read(x->d, 0x81, buffer, 8, 2) > 0)
{ // reads--; //if (usb_interrupt_read(x->d, 0x81, buffer, 8, TIMEOUT) > 0) //{ first = buffer[0];
if (first>=1 && first <= 8) { // digital input //send_digi(x, first-1, buffer[1]); char testbit = 0x01; t_atom lista[2]; int count; int group = first-1;
for(count = 0; count < 8; count++) { if((buffer[1] & testbit) != (x->old_digi[group] & testbit)) { SETFLOAT(lista, (group*8)+count); if(buffer[1] & testbit) SETFLOAT(lista+1, 1); else SETFLOAT(lista+1, 0); outlet_anything(x->d_out, gensym("list") , 2, lista); } testbit <<= 1; } x->old_digi[group] = buffer[1]; }
if (first>=9 && first <=96) { // analog input t_atom lista[2]; int result; int channel = first-9;
result = buffer[1] + (buffer[2] << 8); x->analog_buffer[channel] = result;
SETFLOAT(lista, channel); SETFLOAT(lista+1, result); outlet_anything(x->a_out, gensym("list"),2 , lista); }
if (first==161) { t_atom list2[2]; t_atom list3[3];
switch(buffer[1]) { case 0: case 1: SETFLOAT(list2, buffer[1]); SETFLOAT(list2+1, buffer[2]); outlet_anything(x->s_out, gensym("list"),2 , list2); break; case 2: case 3: case 4: SETFLOAT(list3, buffer[1]); SETFLOAT(list3+1, buffer[2]); SETFLOAT(list3+2, (float)(buffer[3] + (buffer[4]<<8)) ); outlet_anything(x->s_out, gensym("list"),3 , list3); break; case 5: case 6: case 7: case 8: SETFLOAT(list3, buffer[1]); SETFLOAT(list3+1, buffer[2]); SETFLOAT(list3+2, buffer[3]); outlet_anything(x->s_out, gensym("list"),3 , list3); break; case 9: SETFLOAT(list2, buffer[1] - 9); outlet_anything(x->a_out, gensym("list"),2 , list2); break; case 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17: SETFLOAT(list3, buffer[1]); SETFLOAT(list3+1, buffer[2]); SETFLOAT(list3+2, buffer[3]); outlet_anything(x->s_out, gensym("list"),3 , list3); break; default: error("unknown system command echo"); break; } // system input } } } */
static void multio_open(t_multio *x) { struct usb_device *device; struct usb_bus* bus; unsigned char buffer[8]; usb_init(); usb_find_busses(); usb_find_devices();
for (bus=usb_get_busses();bus!=NULL;bus=bus->next) { struct usb_device* usb_devices = bus->devices;
for(device=usb_devices;device;device=device->next) {
if (device->descriptor.idVendor == multio_vendorID &&device->descriptor.idProduct == multio_productID) {
post( "multio: Found mamalala multI/O as device '%s' on USB bus %s", device->filename, device->bus->dirname); x->d=usb_open(device);
if (x->d) { /* This is our device-- claim it */
if (usb_set_configuration(x->d,multio_configuration)) { post("multio: Error setting USB configuration."); usb_close(x->d); return; } else post("multio: Selecting non-HID config");
if (usb_claim_interface(x->d,multio_interface)) { post("multio: Claim failed-- the mamalala multI/O is in use by another driver.\n" "multio: Do a `dmesg` to see which kernel driver has claimed it--\n" "multio: You may need to `rmmod hid` or patch your kernel's hid driver."); usb_close(x->d); return;
} else post("multio: Claimed interface"); while(usb_interrupt_read(x->d, 0x81, buffer, 8, 10) > 0) {
} return; } } } } // if i am here then i couldn't find mutlIO! post("multio: unable to find multI/O !"); }
static void multio_tick(t_multio *x) { x->x_hit = 0; // multio_read(x); process_buffer(x); if (!x->x_hit) clock_delay(x->x_clock, x->x_deltime); }
static void multio_float(t_multio *x, t_float f) { if (f != 0) multio_tick(x); else clock_unset(x->x_clock); x->x_hit = 1; }
static void multio_start(t_multio *x) { multio_float(x, 1); }
static void multio_stop(t_multio *x) { multio_float(x, 0); }
static void multio_ft1(t_multio *x, t_floatarg g) { if (g < 1) g = 1; x->x_deltime = g; }
static void multio_free(t_multio *x) { if(is_open) { clock_free(x->x_clock); if(x->d) { while(pthread_cancel(x->x_threadid) < 0) post("multio: killing thread\n"); post("multio: thread canceled\n"); usb_close(x->d); } is_open = 0; } else post("multio: not active object"); }
static void *multio_new(t_symbol *s, int argc, t_atom *argv) { if(!is_open) { t_multio *x = (t_multio *)pd_new(multio_class); x->x_clock = clock_new(x, (t_method)multio_tick); x->x_deltime = DEFDELTIME; x->a_out = outlet_new(&x->x_obj, &s_list); x->d_out = outlet_new(&x->x_obj, &s_list); x->s_out = outlet_new(&x->x_obj, &s_list); // look for multIO
multio_open(x); if(x->d) start_thread(x); // inlets for digital and system inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("list"), gensym("digi_write")); // remap to digi_write inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("list"), gensym("system_write")); is_open = 1; multio_start(x); return (x); } else { post("multio: object already exists"); return(0); } }
void multio_setup(void) { multio_class = class_new(gensym("multio"), (t_newmethod)multio_new, (t_method)multio_free, sizeof(t_multio), CLASS_DEFAULT, A_GIMME, 0); //class_addbang(multio_class, (t_method)multio_bang); // to set the time between 2 readouts class_addmethod(multio_class, (t_method)multio_ft1, gensym("readout_time"), A_FLOAT, 0); class_addfloat(multio_class, (t_method)multio_float); // start/stop using a toggle // to stop reading class_addmethod(multio_class, (t_method)multio_stop, gensym("stop"), 0); // to start reading class_addmethod(multio_class, (t_method)multio_start, gensym("start"), 0); // open the device class_addmethod(multio_class, (t_method)multio_open, gensym("open"), 0); // write analog data using leftmost inlet class_addlist(multio_class, (t_method)multio_analog_write); class_addmethod(multio_class, (t_method)multio_digi_write, gensym("digi_write"), A_GIMME, 0); class_addmethod(multio_class, (t_method)multio_system_write, gensym("system_write"), A_GIMME, 0); is_open = 0; // welcome message post("\nmultio: a pd driver for the multI/O USB device"); post("multio: www.davidemorelli.it - multio.mamalala.de");
}
--- NEW FILE: Makefile --- NAME=multio CSYM=multio
current: pd_linux
# ----------------------- NT -----------------------
pd_nt: $(NAME).dll
.SUFFIXES: .dll
VC="C:\Programmi\Microsoft Visual Studio .NET\Vc7" PDPATH="H:\PureData\pd-0.38-3.msw\pd" LIBUSBPATH="H:\PureData\multIO\libusb-win32-device-bin-0.1.10.1" PDNTCFLAGS = /W3 /WX /DNT /DPD /nologo
PDNTINCLUDE = /I. (PDPATH)\tcl\include /I$(PDPATH)\src /I$(VC)\include /I$(LIBUSBPATH)\include
PDNTLDIR = $(VC)\lib PDNTLIB = $(PDNTLDIR)\libc.lib \ $(PDNTLDIR)\oldnames.lib \ $(PDNTLDIR)\kernel32.lib \ $(LIBUSBPATH)\lib\msvc\libusb.lib \ $(PDPATH)\bin\pd.lib \ $(PDPATH)\bin\pthreadVC.lib
.c.dll: cl $(PDNTCFLAGS) $(PDNTINCLUDE) /c $*.c link /dll /export:$(CSYM)_setup $*.obj $(PDNTLIB)
# ----------------------- LINUX i386 -----------------------
pd_linux: $(NAME).pd_linux
.SUFFIXES: .pd_linux
LINUXCFLAGS = -DPD -O2 -funroll-loops -fomit-frame-pointer -fPIC \ -Wall -W -Wshadow -Wstrict-prototypes \ -Wno-unused -Wno-parentheses -Wno-switch $(CFLAGS)
LINUXINCLUDE = -I../../src
.c.pd_linux: $(CC) $(LINUXCFLAGS) $(LINUXINCLUDE) -o $*.o -c $*.c ld -export_dynamic -shared -o $*.pd_linux $*.o -lc -lm -lusb strip --strip-unneeded $*.pd_linux rm -f $*.o
# ----------------------- Mac OSX -----------------------
pd_darwin: $(NAME).pd_darwin
.SUFFIXES: .pd_darwin
DARWINCFLAGS = -DPD -O2 -Wall -W -Wshadow -Wstrict-prototypes \ -Wno-unused -Wno-parentheses -Wno-switch
.c.pd_darwin: $(CC) $(DARWINCFLAGS) $(LINUXINCLUDE) -o $*.o -c $*.c $(CC) -bundle -undefined suppress -flat_namespace -o $*.pd_darwin $*.o rm -f $*.o
# ----------------------------------------------------------
clean: rm -f *.o *.pd_* so_locations