aboutsummaryrefslogtreecommitdiff
path: root/uDMX
diff options
context:
space:
mode:
authorThomas O Fredericks <mrtof@users.sourceforge.net>2009-12-18 14:34:07 +0000
committerIOhannes m zmölnig <zmoelnig@iem.at>2015-10-14 15:08:22 +0200
commite15e9a50eb5932538d92c10f49a09ad968cb0f43 (patch)
tree0b099cde681a8119d435c1991884d520de76643f /uDMX
parentf467f395ebda720ece4debd60d3531586fa432be (diff)
Added uDMX to hardware
svn path=/trunk/externals/hardware/; revision=12839
Diffstat (limited to 'uDMX')
-rw-r--r--uDMX/README2
-rw-r--r--uDMX/makefile105
-rw-r--r--uDMX/uDMX-help.pd12
-rwxr-xr-xuDMX/uDMX.c275
-rw-r--r--uDMX/uDMX_cmds.h31
5 files changed, 425 insertions, 0 deletions
diff --git a/uDMX/README b/uDMX/README
new file mode 100644
index 0000000..1d9a8a1
--- /dev/null
+++ b/uDMX/README
@@ -0,0 +1,2 @@
+Requires libusb
+More information: http://www.anyma.ch/research/udmx/
diff --git a/uDMX/makefile b/uDMX/makefile
new file mode 100644
index 0000000..f030c66
--- /dev/null
+++ b/uDMX/makefile
@@ -0,0 +1,105 @@
+current:
+ echo make pd_linux, pd_nt, pd_irix5, pd_irix6 or pd_darwin, then make install
+
+clean: ; rm -f *.pd_* *.o
+
+# ----------------------- NT -----------------------
+
+pd_nt: edubeat.dll
+
+INSTALL_PREFIX="C:\pd\extra"
+EXT=dll
+.SUFFIXES: .obj .dll
+
+PDNTCFLAGS = /W3 /WX /DNT /DPD /nologo
+VC="D:\Program Files\Microsoft Visual Studio\Vc98"
+
+PDNTINCLUDE = /I. /I\tcl\include /I..\..\src /I$(VC)\include
+
+PDNTLDIR = $(VC)\lib
+PDNTLIB = $(PDNTLDIR)\libc.lib \
+ $(PDNTLDIR)\oldnames.lib \
+ $(PDNTLDIR)\kernel32.lib \
+ ..\..\bin\pd.lib
+
+.c.dll:
+ cl $(PDNTCFLAGS) $(PDNTINCLUDE) /c $*.c
+ link /dll /export:$*_setup $*.obj $(PDNTLIB)
+
+# ----------------------- IRIX 5.x -----------------------
+
+pd_irix5: edubeat.pd_irix5
+
+INSTALL_PREFIX=/usr/local
+EXT=pd_irix5
+.SUFFIXES: .pd_irix5
+
+SGICFLAGS5 = -o32 -DPD -DUNIX -DIRIX -O2
+
+SGIINCLUDE = -I/usr/local/include
+
+.c.pd_irix5:
+ cc $(SGICFLAGS5) $(SGIINCLUDE) -o $*.o -c $*.c
+ ld -elf -shared -rdata_shared -o $*.pd_irix5 $*.o
+ rm $*.o
+
+# ----------------------- IRIX 5.x -----------------------
+
+pd_irix6: edubeat.pd_irix6
+
+INSTALL_PREFIX=/usr/local
+EXT=pd_irix6
+.SUFFIXES: .pd_irix6
+
+SGICFLAGS5 = -o32 -DPD -DUNIX -DIRIX -O2
+
+SGIINCLUDE = -I/usr/local/include
+
+.c.pd_irix6:
+ cc $(SGICFLAGS5) $(SGIINCLUDE) -o $*.o -c $*.c
+ ld -elf -shared -rdata_shared -o $*.pd_irix6 $*.o
+ rm $*.o
+
+# ----------------------- LINUX i386 -----------------------
+
+pd_linux: uDMX.pd_linux
+
+INSTALL_PREFIX=/usr
+EXT=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
+
+LINUXINCLUDE = -I/usr/include
+
+.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 $*.o
+
+# ----------------------- Mac OSX -----------------------
+
+pd_darwin: edubeat.pd_darwin
+
+INSTALL_PREFIX=/usr/local
+EXT=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
+
+# ----------------------------------------------
+
+install::
+ install -d $(INSTALL_PREFIX)/lib/pd/extra
+# install -m 644 *.$(EXT) $(INSTALL_PREFIX)/lib/pd/externs
+ -install -m 644 edubeat.$(EXT) $(INSTALL_PREFIX)/lib/pd/extra
+ install -m 644 *.pd $(INSTALL_PREFIX)/lib/pd/doc/5.reference
diff --git a/uDMX/uDMX-help.pd b/uDMX/uDMX-help.pd
new file mode 100644
index 0000000..54d08d3
--- /dev/null
+++ b/uDMX/uDMX-help.pd
@@ -0,0 +1,12 @@
+#N canvas 0 0 450 300 10;
+#X floatatom 203 74 5 0 0 0 - - -;
+#X msg 232 107 1;
+#X msg 103 57 255 255 255;
+#X obj 184 122 uDMX;
+#X msg 70 128 0 0 0;
+#X msg 101 175 127 127 127;
+#X connect 0 0 3 0;
+#X connect 1 0 3 1;
+#X connect 2 0 3 0;
+#X connect 4 0 3 0;
+#X connect 5 0 3 0;
diff --git a/uDMX/uDMX.c b/uDMX/uDMX.c
new file mode 100755
index 0000000..eadc53c
--- /dev/null
+++ b/uDMX/uDMX.c
@@ -0,0 +1,275 @@
+/*
+ uDMX.c
+
+ pd-Interface to the [ a n y m a | uDMX - Open Source USB Sensor Box ]
+
+ Authors: Michael Egger
+ Copyright: 2007 [ a n y m a ]
+ Website: www.anyma.ch
+
+ License: GNU GPL 2.0 www.gnu.org
+
+ Version: 0.2 2009-06-30
+ 0.1 2007-01-28
+ */
+
+#include "m_pd.h"
+
+#include "uDMX_cmds.h"
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <usb.h> /* this is libusb, see http://libusb.sourceforge.net/ */
+
+#define USBDEV_SHARED_VENDOR 0x16C0 /* VOTI */
+#define USBDEV_SHARED_PRODUCT 0x05DC /* Obdev's free shared PID */
+
+typedef struct _uDMX // defines our object's internal variables for each instance in a patch
+{
+ t_object p_ob; // object header - ALL objects MUST begin with this...
+ usb_dev_handle *dev_handle; // handle to the uDMX usb device
+ int debug_flag;
+ int channel; // int value - received from the right inlet and stored internally for each object instance
+} t_uDMX;
+
+void *uDMX_class; // global pointer to the object class - so max can reference the object
+
+
+
+// these are prototypes for the methods that are defined below
+void uDMX_int(t_uDMX *x, long n);
+void uDMX_setchannel(t_uDMX *x, t_floatarg f);
+void uDMX_debug(t_uDMX *x, t_symbol *s, short ac, t_atom *av);
+void uDMX_list(t_uDMX *x, t_symbol *s, short ac, t_atom *av);
+void uDMX_open(t_uDMX *x);
+void uDMX_close(t_uDMX *x);
+void *uDMX_new(long n);
+static int usbGetStringAscii(usb_dev_handle *dev, int dex, int langid, char *buf, int buflen);
+void find_device(t_uDMX *x);
+
+//--------------------------------------------------------------------------
+
+void uDMX_setup(void)
+{
+
+ uDMX_class = class_new ( gensym("uDMX"),(t_newmethod)uDMX_new, 0, sizeof(t_uDMX), CLASS_DEFAULT,0);
+
+ class_addfloat(uDMX_class, (t_method)uDMX_int); // the method for an int in the left inlet (inlet 0)
+ class_addmethod(uDMX_class, (t_method)uDMX_debug,gensym("debug"), A_GIMME, 0);
+ class_addlist(uDMX_class, (t_method)uDMX_list);
+ class_addmethod(uDMX_class, (t_method)uDMX_open, gensym("open"), 0);
+ class_addmethod(uDMX_class, (t_method)uDMX_close, gensym("close"), 0);
+ class_addmethod(uDMX_class, (t_method)uDMX_setchannel, gensym("setchannel"), A_FLOAT, 0);
+
+ post("uDMX version 0.9 - (c) 2006 [ a n y m a ]",0); // post any important info to the max window when our object is laoded
+}
+//--------------------------------------------------------------------------
+
+void uDMX_int(t_uDMX *x, long n) // x = the instance of the object; n = the int received in the left inlet
+{
+ unsigned char buffer[8];
+ int nBytes;
+
+ if (n > 255) n=255;
+ if (n < 0) n=0;
+ if (x->channel > 512) x->channel=512;
+ if (x->channel < 0) x->channel=0;
+
+ if (!(x->dev_handle)) find_device(x);
+ else {
+ nBytes = usb_control_msg(x->dev_handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT,
+ cmd_SetSingleChannel, n, x->channel, buffer, sizeof(buffer), 5000);
+ if(nBytes < 0)
+ if (x->debug_flag) error("uDMX: USB error: %s", usb_strerror());
+ }
+}
+
+void uDMX_setchannel(t_uDMX *x, t_floatarg f)
+{
+ x->channel = f;
+}
+
+//--------------------------------------------------------------------------
+
+void uDMX_list(t_uDMX *x, t_symbol *s, short ac, t_atom *av)
+{
+ int i;
+ unsigned char* buf = malloc(ac);
+ int nBytes;
+ int n;
+
+ if (x->channel > 512) x->channel=512;
+ if (x->channel < 0) x->channel=0;
+
+ if (!(x->dev_handle)) find_device(x);
+ else {
+
+ if (x->debug_flag) post("uDMX: ac: %i\n", ac);
+ for(i=0; i<ac; ++i,av++) {
+ if (av->a_type==A_FLOAT) {
+ n = (int) av->a_w.w_float;
+ if (n > 255) n=255;
+ if (n < 0) n=0;
+
+ buf[i] = n;
+ } else
+ buf[i] = 0;
+ }
+ nBytes = usb_control_msg(x->dev_handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT,
+ cmd_SetChannelRange, ac, x->channel, buf, ac, 5000);
+ if (x->debug_flag) post( "bytes returned: %i\n", nBytes);
+ if(nBytes < 0)
+ if (x->debug_flag) error("uDMX: USB error: %s\n", usb_strerror());
+ else if(nBytes > 0) if (x->debug_flag) post("uDMX: returned: %i\n", (int)(buf[0]));
+ free(buf);
+ }
+}
+
+//--------------------------------------------------------------------------
+
+void uDMX_debug(t_uDMX *x, t_symbol *s, short ac, t_atom *av) // x = the instance of the object; n = the int received in the left inlet
+{
+ x->debug_flag = 1;
+ if (ac) {
+ if (av->a_type==A_FLOAT) x->debug_flag = av->a_w.w_float;
+ }
+}
+
+
+
+//--------------------------------------------------------------------------
+
+void uDMX_free(t_uDMX *x)
+{
+ if (x->dev_handle)
+ usb_close(x->dev_handle);
+}
+
+//--------------------------------------------------------------------------
+
+void uDMX_open(t_uDMX *x)
+{
+ if (x->dev_handle) {
+ post("uDMX: There is already a connection to www.anyma.ch/uDMX",0);
+ } else find_device(x);
+}
+
+//--------------------------------------------------------------------------
+
+void uDMX_close(t_uDMX *x)
+{
+ if (x->dev_handle) {
+ usb_close(x->dev_handle);
+ x->dev_handle = NULL;
+ post("uDMX: Closed connection to www.anyma.ch/uDMX",0);
+ } else
+ post("uDMX: There was no open connection to www.anyma.ch/uDMX",0);
+}
+
+
+//--------------------------------------------------------------------------
+
+void *uDMX_new(long n) // n = int argument typed into object box (A_DEFLONG) -- defaults to 0 if no args are typed
+{
+ t_uDMX *x; // local variable (pointer to a t_uDMX data structure)
+
+ x = (t_uDMX *)pd_new(uDMX_class); // create a new instance of this object
+
+ // create a second int inlet (leftmost inlet is automatic - all objects have one inlet by default)
+ // floatinlet_new(x, x->channel); //crashes on PD .... assigns float in inlet 2 directly to channel
+ inlet_new(&x->p_ob, &x->p_ob.ob_pd, gensym("float"), gensym("setchannel"));
+
+ x->channel = 0;
+ x->debug_flag = 0;
+ x->dev_handle = NULL;
+
+ find_device(x);
+
+ return(x); // return a reference to the object instance
+}
+
+//--------------------------------------------------------------------------
+
+
+static int usbGetStringAscii(usb_dev_handle *dev, int dex, int langid, char *buf, int buflen)
+{
+char buffer[256];
+int rval, i;
+
+ if((rval = usb_control_msg(dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8) + dex, langid, buffer, sizeof(buffer), 1000)) < 0)
+ return rval;
+ if(buffer[1] != USB_DT_STRING)
+ return 0;
+ if((unsigned char)buffer[0] < rval)
+ rval = (unsigned char)buffer[0];
+ rval /= 2;
+ /* lossy conversion to ISO Latin1 */
+ for(i=1;i<rval;i++){
+ if(i > buflen) /* destination buffer overflow */
+ break;
+ buf[i-1] = buffer[2 * i];
+ if(buffer[2 * i + 1] != 0) /* outside of ISO Latin1 range */
+ buf[i-1] = '?';
+ }
+ buf[i-1] = 0;
+ return i-1;
+}
+
+//--------------------------------------------------------------------------
+
+
+void find_device(t_uDMX *x)
+{
+ usb_dev_handle *handle = NULL;
+ struct usb_bus *bus;
+ struct usb_device *dev;
+
+ usb_init();
+ usb_find_busses();
+ usb_find_devices();
+ for(bus=usb_get_busses(); bus; bus=bus->next){
+ for(dev=bus->devices; dev; dev=dev->next){
+ if(dev->descriptor.idVendor == USBDEV_SHARED_VENDOR && dev->descriptor.idProduct == USBDEV_SHARED_PRODUCT){
+ char string[256];
+ int len;
+ handle = usb_open(dev); /* we need to open the device in order to query strings */
+ if(!handle){
+ error ("Warning: cannot open USB device: %s", usb_strerror());
+ continue;
+ }
+ /* now find out whether the device actually is uDMX */
+ len = usbGetStringAscii(handle, dev->descriptor.iManufacturer, 0x0409, string, sizeof(string));
+ if(len < 0){
+ post("uDMX: warning: cannot query manufacturer for device: %s", usb_strerror());
+ goto skipDevice;
+ }
+
+ // post("uDMX: seen device from vendor ->%s<-", string);
+ if(strcmp(string, "www.anyma.ch") != 0)
+ goto skipDevice;
+ len = usbGetStringAscii(handle, dev->descriptor.iProduct, 0x0409, string, sizeof(string));
+ if(len < 0){
+ post("uDMX: warning: cannot query product for device: %s", usb_strerror());
+ goto skipDevice;
+ }
+ // post("uDMX: seen product ->%s<-", string);
+ if(strcmp(string, "uDMX") == 0)
+ break;
+skipDevice:
+ usb_close(handle);
+ handle = NULL;
+ }
+ }
+ if(handle)
+ break;
+ }
+
+ if(!handle){
+ post("uDMX: Could not find USB device www.anyma.ch/uDMX");
+ x->dev_handle = NULL;
+ } else {
+ x->dev_handle = handle;
+ post("uDMX: Found USB device www.anyma.ch/uDMX");
+ }
+}
diff --git a/uDMX/uDMX_cmds.h b/uDMX/uDMX_cmds.h
new file mode 100644
index 0000000..12a72af
--- /dev/null
+++ b/uDMX/uDMX_cmds.h
@@ -0,0 +1,31 @@
+/*
+ * usb2dmx_cmds.h
+ *
+ *
+ * Created by Max Egger on 14.02.06.
+ *
+ */
+
+#define cmd_SetSingleChannel 1
+/* usb request for cmd_SetSingleChannel:
+ bmRequestType: ignored by device, should be USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT
+ bRequest: cmd_SetSingleChannel
+ wValue: value of channel to set [0 .. 255]
+ wIndex: channel index to set [0 .. 511]
+ wLength: ignored
+*/
+#define cmd_SetChannelRange 2
+/* usb request for cmd_SetChannelRange:
+ bmRequestType: ignored by device, should be USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT
+ bRequest: cmd_SetChannelRange
+ wValue: number of channels to set [1 .. 512-wIndex]
+ wIndex: index of first channel to set [0 .. 511]
+ wLength: length of data, must be >= wValue
+*/
+
+#define cmd_StartBootloader 0xf8
+// Start Bootloader for Software updates
+
+
+#define err_BadChannel 1
+#define err_BadValue 2