aboutsummaryrefslogtreecommitdiff
path: root/sixaxis
diff options
context:
space:
mode:
Diffstat (limited to 'sixaxis')
-rw-r--r--sixaxis/Makefile242
-rw-r--r--sixaxis/sixaxis-help.pd127
-rw-r--r--sixaxis/sixaxis.c412
3 files changed, 781 insertions, 0 deletions
diff --git a/sixaxis/Makefile b/sixaxis/Makefile
new file mode 100644
index 0000000..51c9331
--- /dev/null
+++ b/sixaxis/Makefile
@@ -0,0 +1,242 @@
+# To use this Makefile for your project, first put the name of your library in
+# LIBRARY_NAME variable. The folder for your project should have the same name
+# as your library.
+LIBRARY_NAME = sixaxis
+LIBRARY_VERSION = 0.1
+
+# Next, add your .c source files to the SOURCES variable. The help files will
+# be included automatically
+SOURCES =
+
+# For objects that only build on certain platforms, add those to the SOURCES
+# line for the right platforms.
+SOURCES_android =
+SOURCES_cygwin =
+SOURCES_macosx =
+SOURCES_iphoneos =
+SOURCES_linux = sixaxis.c
+SOURCES_windows =
+
+# list all pd objects (i.e. myobject.pd) files here, and their helpfiles will
+# be included automatically
+PDOBJECTS =
+
+# if you want to include any other files in the source and binary tarballs,
+# list them here. This can be anything from header files, READMEs, example
+# patches, documentation, etc.
+EXTRA_DIST =
+
+
+#------------------------------------------------------------------------------#
+#
+# you shouldn't need to edit anything below here, if we did it right :)
+#
+#------------------------------------------------------------------------------#
+
+# where Pd lives
+PD_PATH = ../../../pd
+# where to install the library
+prefix = /usr/local
+libdir = $(prefix)/lib
+pkglibdir = $(libdir)/pd-externals
+objectsdir = $(pkglibdir)
+
+
+INSTALL = install
+INSTALL_FILE = $(INSTALL) -p -m 644
+INSTALL_DIR = $(INSTALL) -p -m 755 -d
+
+CFLAGS = -DPD -I$(PD_PATH)/src -Wall -W -g
+LDFLAGS =
+LIBS =
+ALLSOURCES := $(SOURCES) $(SOURCES_android) $(SOURCES_cygwin) $(SOURCES_macosx) \
+ $(SOURCES_iphoneos) $(SOURCES_linux) $(SOURCES_windows)
+
+UNAME := $(shell uname -s)
+ifeq ($(UNAME),Darwin)
+ CPU := $(shell uname -p)
+ ifeq ($(CPU),arm) # iPhone/iPod Touch
+ SOURCES += $(SOURCES_macosx)
+ EXTENSION = pd_darwin
+ OS = iphoneos
+ IPHONE_BASE=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin
+ CC=$(IPHONE_BASE)/gcc
+ CPP=$(IPHONE_BASE)/cpp
+ CXX=$(IPHONE_BASE)/g++
+ ISYSROOT = -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk
+ IPHONE_CFLAGS = -miphoneos-version-min=3.0 $(ISYSROOT) -arch armv6
+ OPT_CFLAGS = -fast -funroll-loops -fomit-frame-pointer
+ CFLAGS := $(IPHONE_CFLAGS) $(OPT_CFLAGS) $(CFLAGS) \
+ -I/Applications/Pd-extended.app/Contents/Resources/include
+ LDFLAGS += -arch armv6 -bundle -undefined dynamic_lookup $(ISYSROOT)
+ LIBS += -lc
+ STRIP = strip -x
+ DISTDIR=$(LIBRARY_NAME)-$(LIBRARY_VERSION)
+ DISTBINDIR=$(DISTDIR)-$(OS)
+ else # Mac OS X
+ SOURCES += $(SOURCES_macosx)
+ EXTENSION = pd_darwin
+ OS = macosx
+ OPT_CFLAGS = -ftree-vectorize -ftree-vectorizer-verbose=2 -fast
+ FAT_FLAGS = -arch i386 -arch ppc -mmacosx-version-min=10.4
+ CFLAGS += $(FAT_FLAGS) -fPIC -I/sw/include \
+ -I/Applications/Pd-extended.app/Contents/Resources/include
+ LDFLAGS += $(FAT_FLAGS) -bundle -undefined dynamic_lookup -L/sw/lib
+ # if the 'pd' binary exists, check the linking against it to aid with stripping
+ LDFLAGS += $(shell test -e $(PD_PATH)/bin/pd && echo -bundle_loader $(PD_PATH)/bin/pd)
+ LIBS += -lc
+ STRIP = strip -x
+ DISTDIR=$(LIBRARY_NAME)-$(LIBRARY_VERSION)
+ DISTBINDIR=$(DISTDIR)-$(OS)
+ endif
+endif
+ifeq ($(UNAME),Linux)
+ SOURCES += $(SOURCES_linux)
+ EXTENSION = pd_linux
+ OS = linux
+ OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer
+ CFLAGS += -fPIC
+ LDFLAGS += -Wl,--export-dynamic -shared -fPIC
+ LIBS += -lc
+ STRIP = strip --strip-unneeded -R .note -R .comment
+ DISTDIR=$(LIBRARY_NAME)-$(LIBRARY_VERSION)
+ DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m)
+endif
+ifeq (CYGWIN,$(findstring CYGWIN,$(UNAME)))
+ SOURCES += $(SOURCES_cygwin)
+ EXTENSION = dll
+ OS = cygwin
+ OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer
+ CFLAGS +=
+ LDFLAGS += -Wl,--export-dynamic -shared -L$(PD_PATH)/src
+ LIBS += -lc -lpd
+ STRIP = strip --strip-unneeded -R .note -R .comment
+ DISTDIR=$(LIBRARY_NAME)-$(LIBRARY_VERSION)
+ DISTBINDIR=$(DISTDIR)-$(OS)
+endif
+ifeq (MINGW,$(findstring MINGW,$(UNAME)))
+ SOURCES += $(SOURCES_windows)
+ EXTENSION = dll
+ OS = windows
+ OPT_CFLAGS = -O3 -funroll-loops -fomit-frame-pointer
+ WINDOWS_HACKS = -D'O_NONBLOCK=1'
+ CFLAGS += -mms-bitfields $(WINDOWS_HACKS)
+ LDFLAGS += -s -shared -Wl,--enable-auto-import
+ LIBS += -L$(PD_PATH)/src -L$(PD_PATH)/bin -L$(PD_PATH)/obj -lpd -lwsock32 -lkernel32 -luser32 -lgdi32
+ STRIP = strip --strip-unneeded -R .note -R .comment
+ DISTDIR=$(LIBRARY_NAME)-$(LIBRARY_VERSION)
+ DISTBINDIR=$(DISTDIR)-$(OS)
+endif
+
+CFLAGS += $(OPT_CFLAGS)
+
+
+.PHONY = install libdir_install single_install install-doc install-exec install-examples clean dist etags
+
+all: $(SOURCES:.c=.$(EXTENSION))
+
+%.o: %.c
+ $(CC) $(CFLAGS) -o "$*.o" -c "$*.c"
+
+%.$(EXTENSION): %.o
+ $(CC) $(LDFLAGS) -o "$*.$(EXTENSION)" "$*.o" $(LIBS)
+ chmod a-x "$*.$(EXTENSION)"
+
+# this links everything into a single binary file
+$(LIBRARY_NAME): $(SOURCES:.c=.o) $(LIBRARY_NAME).o
+ $(CC) $(LDFLAGS) -o $(LIBRARY_NAME).$(EXTENSION) $(SOURCES:.c=.o) $(LIBRARY_NAME).o $(LIBS)
+ chmod a-x $(LIBRARY_NAME).$(EXTENSION)
+
+
+install: libdir_install
+
+# The meta and help files are explicitly installed to make sure they are
+# actually there. Those files are not optional, then need to be there.
+libdir_install: $(SOURCES:.c=.$(EXTENSION)) install-doc install-examples
+ $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
+ $(INSTALL_FILE) $(LIBRARY_NAME)-meta.pd \
+ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
+ test -z "$(strip $(SOURCES))" || (\
+ $(INSTALL_FILE) $(SOURCES:.c=.$(EXTENSION)) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) && \
+ $(STRIP) $(addprefix $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/,$(SOURCES:.c=.$(EXTENSION))))
+ test -z "$(strip $(PDOBJECTS))" || \
+ $(INSTALL_FILE) $(PDOBJECTS) \
+ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
+
+# install library linked as single binary
+single_install: $(LIBRARY_NAME) install-doc install-exec
+ $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
+ $(INSTALL_FILE) $(LIBRARY_NAME).$(EXTENSION) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
+ $(STRIP) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/$(LIBRARY_NAME).$(EXTENSION)
+
+install-doc:
+ $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
+ test -z "$(strip $(SOURCES))" || \
+ $(INSTALL_FILE) $(SOURCES:.c=-help.pd) \
+ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
+ test -z "$(strip $(PDOBJECTS))" || \
+ $(INSTALL_FILE) $(PDOBJECTS:.pd=-help.pd) \
+ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
+# this is the only bit not really handled well...
+ $(INSTALL_FILE) README.txt $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/
+
+install-examples:
+ test ! -d examples || (\
+ $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/examples && \
+ $(INSTALL_FILE) examples/*.* $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/examples)
+
+
+clean:
+ -rm -f -- $(SOURCES:.c=.o)
+ -rm -f -- $(SOURCES:.c=.$(EXTENSION))
+ -rm -f -- $(LIBRARY_NAME).$(EXTENSION)
+
+distclean: clean
+ -rm -f -- $(DISTBINDIR).tar.gz
+ -rm -rf -- $(DISTBINDIR)
+ -rm -f -- $(DISTDIR).tar.gz
+ -rm -rf -- $(DISTDIR)
+
+
+$(DISTBINDIR):
+ $(INSTALL_DIR) $(DISTBINDIR)
+
+libdir: all $(DISTBINDIR)
+ $(INSTALL_FILE) $(LIBRARY_NAME)-meta.pd $(DISTBINDIR)
+ $(INSTALL_FILE) $(SOURCES) $(DISTBINDIR)
+ $(INSTALL_FILE) $(SOURCES:.c=-help.pd) $(DISTBINDIR)
+ test -z "$(strip $(EXTRA_DIST))" || \
+ $(INSTALL_FILE) $(EXTRA_DIST) $(DISTBINDIR)
+# tar --exclude-vcs -czpf $(DISTBINDIR).tar.gz $(DISTBINDIR)
+
+$(DISTDIR):
+ $(INSTALL_DIR) $(DISTDIR)
+
+dist: $(DISTDIR)
+ $(INSTALL_FILE) Makefile $(DISTDIR)
+ $(INSTALL_FILE) $(LIBRARY_NAME)-meta.pd $(DISTDIR)
+ test -z "$(strip $(ALLSOURCES))" || \
+ $(INSTALL_FILE) $(ALLSOURCES) $(DISTDIR)
+ test -z "$(strip $(ALLSOURCES))" || \
+ $(INSTALL_FILE) $(ALLSOURCES:.c=-help.pd) $(DISTDIR)
+ test -z "$(strip $(PDOBJECTS))" || \
+ $(INSTALL_FILE) $(PDOBJECTS) $(DISTDIR)
+ test -z "$(strip $(PDOBJECTS))" || \
+ $(INSTALL_FILE) $(PDOBJECTS:.pd=-help.pd) $(DISTDIR)
+ test -z "$(strip $(EXTRA_DIST))" || \
+ $(INSTALL_FILE) $(EXTRA_DIST) $(DISTDIR)
+ tar --exclude-vcs -czpf $(DISTDIR).tar.gz $(DISTDIR)
+
+
+etags:
+ etags *.h $(SOURCES) ../../pd/src/*.[ch] /usr/include/*.h /usr/include/*/*.h
+
+showpaths:
+ @echo "PD_PATH: $(PD_PATH)"
+ @echo "objectsdir: $(objectsdir)"
+ @echo "LIBRARY_NAME: $(LIBRARY_NAME)"
+ @echo "SOURCES: $(SOURCES)"
+ @echo "ALLSOURCES: $(ALLSOURCES)"
+ @echo "UNAME: $(UNAME)"
+ @echo "CPU: $(CPU)"
+
diff --git a/sixaxis/sixaxis-help.pd b/sixaxis/sixaxis-help.pd
new file mode 100644
index 0000000..b5fae4f
--- /dev/null
+++ b/sixaxis/sixaxis-help.pd
@@ -0,0 +1,127 @@
+#N canvas 197 95 565 482 10;
+#X obj -71 5 cnv 15 550 25 empty empty sixaxis 20 12 1 16 -228992 -66577
+0;
+#N canvas 746 51 411 235 see 0;
+#N canvas 108 318 543 264 route 0;
+#X obj 27 14 inlet;
+#X obj 72 226 outlet;
+#X obj 19 226 outlet;
+#X obj 172 226 outlet;
+#X obj 222 204 symbol;
+#X obj 222 226 outlet;
+#X obj 272 204 symbol;
+#X obj 272 226 outlet;
+#X obj 322 204 symbol;
+#X obj 322 226 outlet;
+#X obj 372 204 symbol;
+#X obj 372 226 outlet;
+#X obj 122 225 outlet;
+#X obj 422 204 symbol;
+#X obj 422 226 outlet;
+#X obj 472 204 symbol;
+#X obj 472 226 outlet;
+#X obj 26 63 route open device poll total product manufacturer transport
+type vendorID productID;
+#X connect 0 0 17 0;
+#X connect 4 0 5 0;
+#X connect 6 0 7 0;
+#X connect 8 0 9 0;
+#X connect 10 0 11 0;
+#X connect 13 0 14 0;
+#X connect 15 0 16 0;
+#X connect 17 0 2 0;
+#X connect 17 1 1 0;
+#X connect 17 2 12 0;
+#X connect 17 3 3 0;
+#X connect 17 4 4 0;
+#X connect 17 5 6 0;
+#X connect 17 6 8 0;
+#X connect 17 7 10 0;
+#X connect 17 8 13 0;
+#X connect 17 9 15 0;
+#X restore 117 70 pd route info;
+#X obj 221 96 tgl 15 0 empty empty open 0 -6 0 8 -262144 -1 -1 1 1
+;
+#X obj 110 22 inlet;
+#X obj 123 43 print info;
+#X floatatom 156 140 5 0 0 0 device - -;
+#X floatatom 156 162 5 0 0 0 poll - -;
+#X floatatom 156 182 5 0 0 0 total - -;
+#X connect 0 0 1 0;
+#X connect 0 1 4 0;
+#X connect 0 2 5 0;
+#X connect 0 3 6 0;
+#X connect 2 0 0 0;
+#X connect 2 0 3 0;
+#X restore 82 239 pd see device info;
+#X obj -7 181 tgl 30 0 empty empty empty 17 7 0 10 -4034 -1 -1 0 1
+;
+#X msg 89 188 info;
+#X msg 48 171 close;
+#X obj -20 406 hsl 128 15 0 1 0 0 empty empty empty -2 -8 0 10 -262144
+-1 -1 5904 1;
+#X obj 120 406 hsl 128 15 0 1 0 0 empty empty empty -2 -8 0 10 -262144
+-1 -1 8699 1;
+#X obj 260 406 hsl 128 15 0 1 0 0 empty empty empty -2 -8 0 10 -262144
+-1 -1 5152 1;
+#X obj 43 276 route accelerometer;
+#X obj 43 308 route x y z;
+#X msg 43 151 open 4;
+#N canvas 162 133 570 420 serin 0;
+#X obj 286 61 cnv 15 30 15 empty \$0-open-canvas 4 4 8 0 14 -233017
+-1 0;
+#X obj 60 61 hradio 15 1 1 15 empty empty empty 0 -6 0 8 -225271 -1
+-1 4;
+#X obj 60 13 inlet;
+#X msg 200 202 label \$1;
+#X obj 200 180 makefilename %d;
+#X obj 59 108 int;
+#X obj 59 337 outlet;
+#X msg 201 306 set \$1 \$2;
+#X obj 59 266 trigger bang anything;
+#X obj 201 286 list;
+#X msg 60 210 open \$1;
+#X obj 200 225 send \$0-open-canvas;
+#X connect 1 0 5 0;
+#X connect 2 0 1 0;
+#X connect 3 0 11 0;
+#X connect 4 0 3 0;
+#X connect 5 0 4 0;
+#X connect 5 0 10 0;
+#X connect 7 0 6 0;
+#X connect 8 0 6 0;
+#X connect 8 1 9 0;
+#X connect 9 0 7 0;
+#X connect 10 0 8 0;
+#X coords 0 -1 1 1 257 17 1 60 60;
+#X restore 43 129 pd serin;
+#X obj 257 375 mapping/autoscale;
+#X obj 117 375 mapping/autoscale;
+#X obj -23 375 mapping/autoscale;
+#X obj 43 216 sixaxis;
+#N canvas 6 77 450 300 more 0;
+#X text -17 56 By default \, [sixaxis] uses /dev/hidraw? for the device
+name to get data from. You can override it using the [devname( message
+\, like this:;
+#X msg 30 154 devname /dev/my/strange/custom/hidraw;
+#X restore -15 444 pd more on device names;
+#X text -63 44 This objectclass supports getting accelerometer data
+from the Sony SIXAXIS controller. Use this in conjuction with [hid]
+to get all of the data from the SIXAXIS;
+#X obj -59 83 pddp/pddplink http://www.pabr.org/sixlinux/sixlinux.en.html
+-text Using the PlayStation 3 controller in Bluetooth mode with Linux
+;
+#X connect 2 0 15 0;
+#X connect 3 0 15 0;
+#X connect 4 0 15 0;
+#X connect 8 0 9 0;
+#X connect 9 0 14 0;
+#X connect 9 1 13 0;
+#X connect 9 2 12 0;
+#X connect 10 0 15 0;
+#X connect 11 0 10 0;
+#X connect 12 0 7 0;
+#X connect 13 0 6 0;
+#X connect 14 0 5 0;
+#X connect 15 0 8 0;
+#X connect 15 1 1 0;
diff --git a/sixaxis/sixaxis.c b/sixaxis/sixaxis.c
new file mode 100644
index 0000000..d110c71
--- /dev/null
+++ b/sixaxis/sixaxis.c
@@ -0,0 +1,412 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "m_pd.h"
+
+//#define DEBUG(x)
+#define DEBUG(x) x
+
+#define DEFAULT_DELAY 10
+#define SIXAXIS_DEVNAME "/dev/hidraw"
+
+static char *version = "$Revision: 1.1 $";
+
+/*------------------------------------------------------------------------------
+ * GLOBAL DECLARATIONS
+ */
+
+/* hidraw data format */
+struct sixaxis_state {
+ double time;
+ int ax, ay, az; // Raw accelerometer data
+ double ddx, ddy, ddz; // Acceleration
+ double dx, dy, dz; // Speed
+ double x, y, z; // Position
+};
+
+/* pre-generated symbols */
+static t_symbol *ps_open, *ps_device, *ps_poll, *ps_total, *ps_range, *ps_devname;
+static t_symbol *ps_x, *ps_y, *ps_z;
+static t_symbol *ps_accelerometer, *ps_acceleration, *ps_speed, *ps_position;
+
+/* mostly for status querying */
+static unsigned short device_count;
+
+/* previous state for calculating position, speed, acceleration */
+//static struct sixaxis_state prev;
+
+/*------------------------------------------------------------------------------
+ * CLASS DEF
+ */
+static t_class *sixaxis_class;
+
+typedef struct _sixaxis {
+ t_object x_obj;
+ t_int x_fd;
+ t_clock *x_clock;
+ short x_device_number;
+ short x_instance;
+ t_int x_device_open;
+ int x_read_ok;
+ int x_started;
+ int x_delay;
+ unsigned char buf[128];
+ struct sixaxis_state x_sixaxis_state;
+ t_atom x_output_atoms[3];
+ t_outlet *x_data_outlet;
+ t_outlet *x_status_outlet;
+} t_sixaxis;
+
+
+
+/*------------------------------------------------------------------------------
+ * SUPPORT FUNCTIONS
+ */
+
+static void output_status(t_sixaxis *x, t_symbol *selector, t_float output_value)
+{
+ t_atom *output_atom = (t_atom *)getbytes(sizeof(t_atom));
+ SETFLOAT(output_atom, output_value);
+ outlet_anything( x->x_status_outlet, selector, 1, output_atom);
+ freebytes(output_atom,sizeof(t_atom));
+}
+
+static void output_open_status(t_sixaxis *x)
+{
+ output_status(x, ps_open, x->x_device_open);
+}
+
+static void output_device_number(t_sixaxis *x)
+{
+ output_status(x, ps_device, x->x_device_number);
+}
+
+static void output_poll_time(t_sixaxis *x)
+{
+ output_status(x, ps_poll, x->x_delay);
+}
+
+static void output_device_count(t_sixaxis *x)
+{
+ output_status(x, ps_total, device_count);
+}
+
+static short get_device_number_from_arguments(int argc, t_atom *argv)
+{
+ short device_number = -1;
+ t_symbol *first_argument;
+
+ if(argc == 1)
+ {
+ first_argument = atom_getsymbolarg(0,argc,argv);
+ if(first_argument == &s_)
+ { // single float arg means device #
+ device_number = (short) atom_getfloatarg(0,argc,argv);
+ }
+ }
+ return device_number;
+}
+/*------------------------------------------------------------------------------
+ * CLASS METHODS
+ */
+
+void sixaxis_stop(t_sixaxis* x)
+{
+ DEBUG(post("sixaxis_stop"););
+
+ if (x->x_fd >= 0 && x->x_started) {
+ clock_unset(x->x_clock);
+ post("sixaxis: polling stopped");
+ x->x_started = 0;
+ }
+}
+
+static void sixaxis_close(t_sixaxis *x)
+{
+ DEBUG(post("sixaxis_close"););
+
+/* just to be safe, stop it first */
+ sixaxis_stop(x);
+
+ if(x->x_fd < 0)
+ return;
+ close(x->x_fd);
+ post("[sixaxis] closed %s%d", SIXAXIS_DEVNAME, x->x_device_number);
+ x->x_device_open = 0;
+ output_open_status(x);
+}
+
+static t_int sixaxis_open_device(t_sixaxis *x, short device_number)
+{
+ DEBUG(post("sixaxis_open_device"););
+
+ char block_device[FILENAME_MAX];
+
+ x->x_fd = -1;
+
+ if(device_number < 0)
+ {
+ pd_error(x,"[sixaxis] invalid device number: %d (must be 0 or greater)"
+ , device_number);
+ return EXIT_FAILURE;
+ }
+
+ x->x_device_number = device_number;
+ snprintf(block_device, FILENAME_MAX, "%s%d", SIXAXIS_DEVNAME, x->x_device_number);
+
+ /* open the device read-only, non-exclusive */
+ x->x_fd = open(block_device, O_RDONLY | O_NONBLOCK);
+ /* test if device open */
+ if(x->x_fd < 0 )
+ {
+ pd_error(x,"[sixaxis] open %s failed",block_device);
+ x->x_fd = -1;
+ return EXIT_FAILURE;
+ }
+ post ("[sixaxis] opened device %d (%s)", x->x_device_number, block_device);
+
+ return EXIT_SUCCESS;
+}
+
+/* sixaxis_open behavoir
+ * current state action
+ * ---------------------------------------
+ * closed / same device open
+ * open / same device no action
+ * closed / different device open
+ * open / different device close, open
+ */
+static void sixaxis_open(t_sixaxis *x, t_symbol *s, int argc, t_atom *argv)
+{
+ DEBUG(post("sixaxis_open"););
+ short new_device_number = get_device_number_from_arguments(argc, argv);
+// t_int started = x->x_started; // store state to restore after device is opened
+
+ if (new_device_number < 0)
+ {
+ pd_error(x,"[sixaxis] invalid device number: %d (must be 0 or greater)",
+ new_device_number);
+ return;
+ }
+ /* check whether we have to close previous device */
+ if (x->x_device_open && new_device_number != x->x_device_number)
+ {
+ sixaxis_close(x);
+ }
+ /* no device open, so open one now */
+ if (!x->x_device_open)
+ {
+ if(sixaxis_open_device(x, new_device_number) == EXIT_SUCCESS)
+ {
+ x->x_device_open = 1;
+ x->x_device_number = new_device_number;
+ /* restore the polling state so that when I [tgl] is used to
+ * start/stop [sixaxis], the [tgl]'s state will continue to
+ * accurately reflect [sixaxis]'s state */
+ post("[sixaxis] set device# to %d",new_device_number);
+ output_device_number(x);
+ }
+ else
+ {
+ x->x_device_number = -1;
+ pd_error(x, "[sixaxis] can not open device %d",new_device_number);
+ }
+ }
+
+ /* always output open result so you can test for success in Pd space */
+ output_open_status(x);
+}
+
+static void sixaxis_read(t_sixaxis *x)
+{
+ if(x->x_fd < 0)
+ return;
+ if(read(x->x_fd, &(x->buf), sizeof(x->buf)) > -1) {
+// if ( nr < 0 ) { perror("read(stdin)"); exit(1); }
+// if ( nr != 48 ) { fprintf(stderr, "Unsupported report\n"); exit(1); }
+
+/* struct timeval tv; */
+/* if ( gettimeofday(&tv, NULL) ) { */
+/* perror("gettimeofday"); */
+/* return; */
+/* } */
+/* x->x_sixaxis_state.time = tv.tv_sec + tv.tv_usec*1e-6; */
+/* x->x_sixaxis_state.ax = x->buf[40]<<8 | x->buf[41]; */
+/* x->x_sixaxis_state.ay = x->buf[42]<<8 | x->buf[43]; */
+/* x->x_sixaxis_state.az = x->buf[44]<<8 | x->buf[45]; */
+/* if ( ! prev.time ) { */
+/* prev.time = x->x_sixaxis_state.time; */
+/* prev.ax = x->x_sixaxis_state.ax; */
+/* prev.ay = x->x_sixaxis_state.ay; */
+/* prev.az = x->x_sixaxis_state.az; */
+/* } */
+/* double dt = x->x_sixaxis_state.time - prev.time; */
+/* double rc_dd = 2.0; // Time constant for highpass filter on acceleration */
+/* double alpha_dd = rc_dd / (rc_dd+dt); */
+/* x->x_sixaxis_state.ddx = alpha_dd*(prev.ddx + (x->x_sixaxis_state.ax-prev.ax)*0.01); */
+/* x->x_sixaxis_state.ddy = alpha_dd*(prev.ddy + (x->x_sixaxis_state.ay-prev.ay)*0.01); */
+/* x->x_sixaxis_state.ddz = alpha_dd*(prev.ddz - (x->x_sixaxis_state.az-prev.az)*0.01); */
+/* double rc_d = 2.0; // Time constant for highpass filter on speed */
+/* double alpha_d = rc_d / (rc_d+dt); */
+/* x->x_sixaxis_state.dx = alpha_d*(prev.dx + x->x_sixaxis_state.ddx*dt); */
+/* x->x_sixaxis_state.dy = alpha_d*(prev.dy + x->x_sixaxis_state.ddy*dt); */
+/* x->x_sixaxis_state.dz = alpha_d*(prev.dz + x->x_sixaxis_state.ddz*dt); */
+/* double rc = 1.0; // Time constant for highpass filter on position */
+/* double alpha = rc / (rc+dt); */
+/* x->x_sixaxis_state.x = alpha*(prev.x + x->x_sixaxis_state.dx*dt); */
+/* x->x_sixaxis_state.y = alpha*(prev.y + x->x_sixaxis_state.dy*dt); */
+/* x->x_sixaxis_state.z = alpha*(prev.z + x->x_sixaxis_state.dz*dt); */
+ /* raw accelerometer data */
+ SETSYMBOL(x->x_output_atoms, ps_x);
+ SETFLOAT(x->x_output_atoms + 1, x->buf[40]<<8 | x->buf[41]);
+ outlet_anything(x->x_data_outlet, ps_accelerometer, 2, x->x_output_atoms);
+ SETSYMBOL(x->x_output_atoms, ps_y);
+ SETFLOAT(x->x_output_atoms + 1, x->buf[42]<<8 | x->buf[43]);
+ outlet_anything(x->x_data_outlet, ps_accelerometer, 2, x->x_output_atoms);
+ SETSYMBOL(x->x_output_atoms, ps_z);
+ SETFLOAT(x->x_output_atoms + 1, x->buf[44]<<8 | x->buf[45]);
+ outlet_anything(x->x_data_outlet, ps_accelerometer, 2, x->x_output_atoms);
+/* SETFLOAT(x->x_output_atoms, x->x_sixaxis_state.ax); */
+/* SETFLOAT(x->x_output_atoms + 1, x->x_sixaxis_state.ay); */
+/* SETFLOAT(x->x_output_atoms + 2, x->x_sixaxis_state.az); */
+/* outlet_anything(x->x_data_outlet, ps_accelerometer, 3, x->x_output_atoms); */
+/* /\* acceleration data *\/ */
+/* SETFLOAT(x->x_output_atoms, x->x_sixaxis_state.ddx); */
+/* SETFLOAT(x->x_output_atoms + 1, x->x_sixaxis_state.ddy); */
+/* SETFLOAT(x->x_output_atoms + 2, x->x_sixaxis_state.ddz); */
+/* outlet_anything(x->x_data_outlet, ps_acceleration, 3, x->x_output_atoms); */
+/* /\* speed data *\/ */
+/* SETFLOAT(x->x_output_atoms, x->x_sixaxis_state.dx); */
+/* SETFLOAT(x->x_output_atoms + 1, x->x_sixaxis_state.dy); */
+/* SETFLOAT(x->x_output_atoms + 2, x->x_sixaxis_state.dz); */
+/* outlet_anything(x->x_data_outlet, ps_speed, 3, x->x_output_atoms); */
+/* /\* position data *\/ */
+/* SETFLOAT(x->x_output_atoms, x->x_sixaxis_state.x); */
+/* SETFLOAT(x->x_output_atoms + 1, x->x_sixaxis_state.y); */
+/* SETFLOAT(x->x_output_atoms + 2, x->x_sixaxis_state.z); */
+/* outlet_anything(x->x_data_outlet, ps_position, 3, x->x_output_atoms); */
+ }
+ if(x->x_started) {
+ clock_delay(x->x_clock, x->x_delay);
+ }
+}
+// double ddx, ddy, ddz; // Acceleration
+// double dx, dy, dz; // Speed
+// double x, y, z; // Position
+
+/* Actions */
+
+static void sixaxis_info(t_sixaxis *x)
+{
+ output_open_status(x);
+ output_device_number(x);
+ output_device_count(x);
+ output_poll_time(x);
+// TODO output ranges for sixaxis
+// output_element_ranges(x);
+}
+
+void sixaxis_start(t_sixaxis* x)
+{
+ DEBUG(post("sixaxis_start"););
+
+ if(!x->x_device_open) {
+ sixaxis_open_device(x, x->x_device_number);
+ }
+ if (x->x_fd > -1 && !x->x_started) {
+ clock_delay(x->x_clock, DEFAULT_DELAY);
+ post("sixaxis: polling started");
+ x->x_started = 1;
+ }
+}
+
+static void sixaxis_float(t_sixaxis* x, t_floatarg f)
+{
+ DEBUG(post("sixaxis_float"););
+
+ if (f > 0)
+ sixaxis_start(x);
+ else
+ sixaxis_stop(x);
+}
+
+/* setup functions */
+static void sixaxis_free(t_sixaxis* x)
+{
+ DEBUG(post("sixaxis_free"););
+
+ if (x->x_fd < 0) return;
+
+ sixaxis_stop(x);
+ clock_free(x->x_clock);
+ close(x->x_fd);
+}
+
+static void *sixaxis_new(t_symbol *s, int argc, t_atom *argv)
+{
+ t_sixaxis *x = (t_sixaxis *)pd_new(sixaxis_class);
+
+ DEBUG(post("sixaxis_new"););
+
+ post("[sixaxis] %s, written by Hans-Christoph Steiner <hans@eds.org>",version);
+
+ /* init vars */
+ x->x_fd = -1;
+ x->x_read_ok = 1;
+ x->x_started = 0;
+ x->x_delay = DEFAULT_DELAY;
+ if(argc > 0)
+ x->x_device_number = get_device_number_from_arguments(argc, argv);
+ else
+ x->x_device_number = 0;
+
+ x->x_clock = clock_new(x, (t_method)sixaxis_read);
+
+ /* create standard "io"-style outlets */
+ x->x_data_outlet = outlet_new(&x->x_obj, 0);
+ x->x_status_outlet = outlet_new(&x->x_obj, 0);
+
+ return (x);
+}
+
+void sixaxis_setup(void)
+{
+ DEBUG(post("sixaxis_setup"););
+ sixaxis_class = class_new(gensym("sixaxis"),
+ (t_newmethod)sixaxis_new,
+ (t_method)sixaxis_free,
+ sizeof(t_sixaxis), 0, A_GIMME, 0);
+
+ /* add inlet datatype methods */
+ class_addfloat(sixaxis_class,(t_method) sixaxis_float);
+ class_addbang(sixaxis_class,(t_method) sixaxis_read);
+
+ /* add inlet message methods */
+ class_addmethod(sixaxis_class,(t_method) sixaxis_open,gensym("open"),A_GIMME,0);
+ class_addmethod(sixaxis_class,(t_method) sixaxis_close,gensym("close"),0);
+ class_addmethod(sixaxis_class,(t_method) sixaxis_info,gensym("info"),0);
+
+ /* pre-generate often used symbols */
+ ps_open = gensym("open");
+ ps_device = gensym("device");
+ ps_poll = gensym("poll");
+ ps_total = gensym("total");
+ ps_range = gensym("range");
+ ps_devname = gensym("devname");
+
+ ps_accelerometer = gensym("accelerometer");
+ ps_x = gensym("x");
+ ps_y = gensym("y");
+ ps_z = gensym("z");
+
+ ps_acceleration = gensym("acceleration");
+ ps_speed = gensym("speed");
+ ps_position = gensym("position");
+}
+