From da3f6b1d47080e0162944834d18017c9a691c0b1 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Mon, 10 Mar 2008 21:50:43 +0000 Subject: moved wiiremote to aka.wiiremote to reflect the name of the Max/MSP object. This is a direct port, so it makes sense to have the same name. svn path=/trunk/externals/io/; revision=9551 --- aka.wiiremote/COPYRIGHT.txt | 13 + aka.wiiremote/HISTORY.txt | 54 ++ aka.wiiremote/Makefile | 33 ++ aka.wiiremote/README.txt | 6 + aka.wiiremote/TODO | 7 + aka.wiiremote/aka.wiiremote.c | 642 +++++++++++++++++++++++ aka.wiiremote/wiiremote-help.pd | 80 +++ aka.wiiremote/wiiremote.c | 1087 +++++++++++++++++++++++++++++++++++++++ aka.wiiremote/wiiremote.h | 175 +++++++ 9 files changed, 2097 insertions(+) create mode 100644 aka.wiiremote/COPYRIGHT.txt create mode 100644 aka.wiiremote/HISTORY.txt create mode 100644 aka.wiiremote/Makefile create mode 100644 aka.wiiremote/README.txt create mode 100644 aka.wiiremote/TODO create mode 100644 aka.wiiremote/aka.wiiremote.c create mode 100644 aka.wiiremote/wiiremote-help.pd create mode 100644 aka.wiiremote/wiiremote.c create mode 100644 aka.wiiremote/wiiremote.h (limited to 'aka.wiiremote') diff --git a/aka.wiiremote/COPYRIGHT.txt b/aka.wiiremote/COPYRIGHT.txt new file mode 100644 index 0000000..b33233c --- /dev/null +++ b/aka.wiiremote/COPYRIGHT.txt @@ -0,0 +1,13 @@ +Max porting by Masayuki Akamatsu +Copyright (c) 2006, Masayuki Akamatsu +Based on "DarwiinRemote" by Hiroaki Kimura +Copyright (c) 2006, Hiroaki Kimura +All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +3. Neither the name of this project nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/aka.wiiremote/HISTORY.txt b/aka.wiiremote/HISTORY.txt new file mode 100644 index 0000000..a0687b1 --- /dev/null +++ b/aka.wiiremote/HISTORY.txt @@ -0,0 +1,54 @@ +aka.wiiremote Version History + +1.0B6 : 2007.04.24 + +- The Classic Controller is supported. +- The help patch is updated. +- The URLs in [info] subpatch are updated. + +- 'expansion' message enables to use the expansion controller(Nunchuk or Classic Controller). +- 'nunchuk' message is obsolete. + You should use 'expansion' instead of it even though you can use it for the backward compatibility only. + +- The IR sensor and the expansion controller (ex. Nunchuk) can be used together. + +- The stability on PPC-Mac is a little improved. + You have to do the following steps every time you use the Wii Remote on PPC-Mac. + (You would set up only once on Intel-Mac.) +1: Delete "Nintendo RVL-CNT-01" on "Device" tab in "Bluetooth" System Preference. +2: Do the setup for Wii Remote. See http://max.iamas.ac.jp/2061/articles/121.html +3: Open "aka.wiiremote.help" and connect it. + + +1.0B5 : 2007.02.03 + +- Nunchuk is supported. +( Classic Controller is NOT supported.) +- device address is supported. +- outlets and output messages are changed. +- some input messages are simplified. +- help patch is expanded for Nunchuk. + + +1.0B4 : 2006.12.24 + +- multiple Wii remotes are supported. + + +1.0B3 : 2006.12.20 + +- data acquisition is improved. +- unusual vibration sound is resolved. + + +1.0B2 : 2006.12.15 + +- connection/disconnection is improved. +- IR sensor is supported. +- status report is supported +- help patch is rewritten. + + +1.0B1 : 2006.12.12 + +- first release \ No newline at end of file diff --git a/aka.wiiremote/Makefile b/aka.wiiremote/Makefile new file mode 100644 index 0000000..e222c9b --- /dev/null +++ b/aka.wiiremote/Makefile @@ -0,0 +1,33 @@ +TARGET := $(shell pwd | sed 's|.*/\(.*\)$$|\1|') +EXTERNALS_ROOT := $(shell pwd | sed 's|^\(/.*externals\).*|\1|') + +default: + make -C $(EXTERNALS_ROOT) $(TARGET) + +install: + make -C $(EXTERNALS_ROOT) $(TARGET)_install + +clean: + make -C $(EXTERNALS_ROOT) $(TARGET)_clean + +test_locations: + make -C $(EXTERNALS_ROOT) test_locations + +# for emacs +etags: + etags ../../../pd/src/*.h *.[ch] + make etags_`uname -s` + +etags_Darwin: + etags -a \ + /System/Library/Frameworks/ForceFeedback.framework/Headers/*.h \ + /System/Library/Frameworks/CoreFoundation.framework/Headers/*.h \ + /System/Library/Frameworks/Carbon.framework/Headers/*.h \ + /System/Library/Frameworks/IOBluetooth.framework/Headers/*.[ch] + +etags_Linux: + etags -a /usr/include/*.h linux/input.h /usr/include/sys/*.h + +etags_MINGW: + etags -a /usr/include/*.h /usr/include/sys/*.h \ + /usr/local/include/*.h /usr/local/include/sys/*.h diff --git a/aka.wiiremote/README.txt b/aka.wiiremote/README.txt new file mode 100644 index 0000000..bdaf778 --- /dev/null +++ b/aka.wiiremote/README.txt @@ -0,0 +1,6 @@ + +This is a port of the Max class aka.wiiremote by Masayuki Akamatsu. Its +available here: + +http://www.iamas.ac.jp/~aka/max/#aka_wiiremote + diff --git a/aka.wiiremote/TODO b/aka.wiiremote/TODO new file mode 100644 index 0000000..a8da43d --- /dev/null +++ b/aka.wiiremote/TODO @@ -0,0 +1,7 @@ + + + - try out IOBluetoothLocalDeviceAvailable(wiiremote->inquiry); to see if that will set up the event loops (http://lists.apple.com/archives/bluetooth-dev/2006/Dec/msg00001.html) + + +- try CFRunLoopRun(); then CFRunLoopStop(CFRunLoopGetCurrent()); in akawiiremote_clock() and akawiiremote_bang() + diff --git a/aka.wiiremote/aka.wiiremote.c b/aka.wiiremote/aka.wiiremote.c new file mode 100644 index 0000000..767d737 --- /dev/null +++ b/aka.wiiremote/aka.wiiremote.c @@ -0,0 +1,642 @@ +// aka.wiiremote.c +// Copyright by Masayuki Akamatsu +// Code for PD by Hans-Christoph Steiner +// 1.0B1 : 2006.12.12 +// 1.0B2 : 2006.12.15 +// 1.0B3 : 2006.12.20 +// 1.0B4 : 2006.12.24 +// 1.0B5 : 2007.02.03 +// 1.0B6 : 2007.04.24 + +#ifdef PD +#include "m_pd.h" +#define SETSYM SETSYMBOL +#define SETLONG SETFLOAT +#define method t_method +//#define addbang(x) class_addbang(wiiremote_class, (x)) +//#define addmess(x) class_addmessage(class_wiiremote, (x)) +static t_class *wiiremote_class; +#else /* Max */ +#include "ext.h" +#endif /* PD */ + +#include "wiiremote.h" +#include +#include + +#define kInterval 100 +#define kMaxTrial 100 + +typedef struct _akawiiremote +{ +#ifdef PD + t_object x_obj; +#else /* Max */ + struct object obj; +#endif + + WiiRemoteRef wiiremote; + char address[32]; + + void *clock; + Boolean connected; + + void *statusOut; + void *dataOut; +} t_akawiiremote; + +void *akawiiremote_class; // the number of instance of this object + +void akawiiremote_bang(t_akawiiremote *x); +void akawiiremote_address(t_akawiiremote *x, t_symbol *s); +void akawiiremote_connect(t_akawiiremote *x); +void akawiiremote_disconnect(t_akawiiremote *x); +void akawiiremote_motionsensor(t_akawiiremote *x, long enable); +void akawiiremote_irsensor(t_akawiiremote *x, long enable); +void akawiiremote_vibration(t_akawiiremote *x, long enable); +void akawiiremote_led(t_akawiiremote *x, long enable1, long enable2, long enable3, long enable4); +void akawiiremote_expansion(t_akawiiremote *x, long enable); +void akawiiremote_extraoutput(t_akawiiremote *x, long enable); + +void akawiiremote_getbattery(t_akawiiremote *x); +void akawiiremote_getexpansion(t_akawiiremote *x); +void akawiiremote_getled(t_akawiiremote *x); +void akawiiremote_getaddress(t_akawiiremote *x); +void akawiiremote_getcalibration(t_akawiiremote *x); + +void akawiiremote_assist(t_akawiiremote *x, void *b, long m, long a, char *s); +void akawiiremote_clock(t_akawiiremote *x); +void *akawiiremote_new(t_symbol *s, short ac, t_atom *av); +void akawiiremote_free(t_akawiiremote *x); + +char remoteStr[] = "remote"; +char nunchukStr[] = "nunchuk"; +char classicStr[] = "classic"; + +#ifdef PD +void wiiremote_setup() +#else /* Max */ +void main() +#endif /* PD */ +{ + NumVersion outSoftwareVersion; + BluetoothHCIVersionInfo outHardwareVersion; + + post("aka.wiiremote 1.0B7-UB by Masayuki Akamatsu"); + + if (IOBluetoothGetVersion(&outSoftwareVersion, &outHardwareVersion)==kIOReturnSuccess) // B7 + { + if (outSoftwareVersion.majorRev < 1 && outSoftwareVersion.minorAndBugRev < 0x63) + { + error("requires Blutooth version 1.6.3 or later."); + return; + } + } + else + { + error("can't get Bluetooth version."); + return; + } + +#ifdef PD + post("\tPd port by Hans-Christoph Steiner"); + + wiiremote_class = class_new(gensym("wiiremote"), + (t_newmethod)akawiiremote_new, + (t_method)akawiiremote_free, + sizeof(t_akawiiremote), + CLASS_DEFAULT, + A_GIMME,0); + + class_addbang(wiiremote_class,(t_method)akawiiremote_bang); + class_addmethod(wiiremote_class,(t_method)akawiiremote_address,gensym("address"),A_DEFSYMBOL, 0); + class_addmethod(wiiremote_class,(t_method)akawiiremote_connect,gensym("connect"),0); + class_addmethod(wiiremote_class,(t_method)akawiiremote_disconnect,gensym("disconnect"),0); + class_addmethod(wiiremote_class,(t_method)akawiiremote_motionsensor,gensym("motion"), A_DEFFLOAT, 0); + class_addmethod(wiiremote_class,(t_method)akawiiremote_irsensor,gensym("ir"), A_DEFFLOAT, 0); + class_addmethod(wiiremote_class,(t_method)akawiiremote_vibration,gensym("vibration"), A_DEFFLOAT, 0); + class_addmethod(wiiremote_class,(t_method)akawiiremote_led,gensym("led"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addmethod(wiiremote_class,(t_method)akawiiremote_expansion,gensym("expansion"), A_DEFFLOAT, 0); + class_addmethod(wiiremote_class,(t_method)akawiiremote_expansion,gensym("nunchuk"), A_DEFFLOAT, 0); + class_addmethod(wiiremote_class,(t_method)akawiiremote_extraoutput,gensym("extraoutput"), A_DEFFLOAT, 0); // B7 + + class_addmethod(wiiremote_class,(t_method)akawiiremote_getbattery,gensym("getbattery"),0); + class_addmethod(wiiremote_class,(t_method)akawiiremote_getexpansion,gensym("getexpansion"),0); + class_addmethod(wiiremote_class,(t_method)akawiiremote_getled,gensym("getled"),0); + class_addmethod(wiiremote_class,(t_method)akawiiremote_getaddress,gensym("getaddress"),0); + class_addmethod(wiiremote_class,(t_method)akawiiremote_getcalibration,gensym("getcalibration"), 0); +#else /* Max */ + setup((t_messlist **)&akawiiremote_class, (method)akawiiremote_new, (method)akawiiremote_free, (short)sizeof(t_akawiiremote), 0L, A_GIMME, 0); + + addbang((method)akawiiremote_bang); + addmess((method)akawiiremote_address,"address",A_DEFSYM, 0); + addmess((method)akawiiremote_connect,"connect", 0); + addmess((method)akawiiremote_disconnect,"disconnect",0); + addmess((method)akawiiremote_motionsensor,"motion", A_DEFLONG, 0); + addmess((method)akawiiremote_irsensor,"ir", A_DEFLONG, 0); + addmess((method)akawiiremote_vibration,"vibration", A_DEFLONG, 0); + addmess((method)akawiiremote_led,"led", A_DEFLONG, A_DEFLONG, A_DEFLONG, A_DEFLONG, 0); + addmess((method)akawiiremote_expansion,"expansion", A_DEFLONG, 0); + addmess((method)akawiiremote_expansion,"nunchuk", A_DEFLONG, 0); + addmess((method)akawiiremote_extraoutput,"extraoutput", A_DEFLONG, 0); // B7 + + addmess((method)akawiiremote_getbattery,"getbattery",0); + addmess((method)akawiiremote_getexpansion,"getexpansion",0); + addmess((method)akawiiremote_getled,"getled",0); + addmess((method)akawiiremote_getaddress,"getaddress",0); + addmess((method)akawiiremote_getcalibration,"getcalibration", 0); + + addmess((method)akawiiremote_assist,"assist",A_CANT,0); +#endif /* PD */ +} + +//-------------------------------------------------------------------------------------------- + +void akawiiremote_bang(t_akawiiremote *x) +{ + t_atom av[7]; + + if (x->wiiremote->device == nil) + return; // do nothing + + if (x->wiiremote->isExpansionPortAttached && x->wiiremote->isExpansionPortEnabled) + { + // Classic Controller + if (x->wiiremote->expType == WiiClassicController) + { + // Buttons + SETSYM(av, gensym("buttons")); + SETLONG(av + 1, x->wiiremote->cButtonData); + outlet_anything(x->dataOut, gensym(classicStr), 2, av); + + // Joystick 1 + SETSYM(av, gensym("stick1")); + SETLONG(av + 1, x->wiiremote->cStickX1); + SETLONG(av + 2, x->wiiremote->cStickY1); + outlet_anything(x->dataOut, gensym(classicStr), 3, av); + + // Joystick 2 + SETSYM(av, gensym("stick2")); + SETLONG(av + 1, x->wiiremote->cStickX2); + SETLONG(av + 2, x->wiiremote->cStickY2); + outlet_anything(x->dataOut, gensym(classicStr), 3, av); + + // Analog + SETSYM(av, gensym("analog")); + SETLONG(av + 1, x->wiiremote->cAnalogL); + SETLONG(av + 2, x->wiiremote->cAnalogR); + outlet_anything(x->dataOut, gensym(classicStr), 3, av); + } + + // Nunchuk + if (x->wiiremote->expType == WiiNunchuk) + { + // Buttons + SETSYM(av, gensym("buttons")); + SETLONG(av + 1, x->wiiremote->nButtonData); + outlet_anything(x->dataOut, gensym(nunchukStr), 2, av); + + // Joystick + SETSYM(av, gensym("stick")); + SETLONG(av + 1, x->wiiremote->nStickX); + SETLONG(av + 2, x->wiiremote->nStickY); + outlet_anything(x->dataOut, gensym(nunchukStr), 3, av); + + if (x->wiiremote->isExtraOutputEnabled) + { + SETSYM(av, gensym("stick_calibration")); + SETLONG(av + 1, x->wiiremote->nunchukJoyStickCalibData.x_min); + SETLONG(av + 2, x->wiiremote->nunchukJoyStickCalibData.x_max); + SETLONG(av + 3, x->wiiremote->nunchukJoyStickCalibData.x_center); + SETLONG(av + 4, x->wiiremote->nunchukJoyStickCalibData.y_min); + SETLONG(av + 5, x->wiiremote->nunchukJoyStickCalibData.y_max); + SETLONG(av + 6, x->wiiremote->nunchukJoyStickCalibData.y_center); + outlet_anything(x->dataOut, gensym(nunchukStr), 7, av); + } + + // Motion Sensor + if (x->wiiremote->isMotionSensorEnabled) + { + SETSYM(av, gensym("motion")); + SETLONG(av + 1, x->wiiremote->nAccX); + SETLONG(av + 2, x->wiiremote->nAccY); + SETLONG(av + 3, x->wiiremote->nAccZ); + SETLONG(av + 4, x->wiiremote->nOrientation); + outlet_anything(x->dataOut, gensym(nunchukStr), 5, av); + + if (x->wiiremote->isExtraOutputEnabled) + { + SETSYM(av, gensym("motion_calibration")); + SETLONG(av + 1, x->wiiremote->nunchukCalibData.accX_zero); + SETLONG(av + 2, x->wiiremote->nunchukCalibData.accY_zero); + SETLONG(av + 3, x->wiiremote->nunchukCalibData.accZ_zero); + SETLONG(av + 4, x->wiiremote->nunchukCalibData.accX_1g); + SETLONG(av + 5, x->wiiremote->nunchukCalibData.accY_1g); + SETLONG(av + 6, x->wiiremote->nunchukCalibData.accZ_1g); + outlet_anything(x->dataOut, gensym(nunchukStr), 7, av); + } + } + } + } + + // Wii Remote + + // Buttons + SETSYM(av, gensym("buttons")); + SETLONG(av + 1, x->wiiremote->buttonData); + outlet_anything(x->dataOut, gensym(remoteStr), 2, av); + + // IR Sensor + if (x->wiiremote->isIRSensorEnabled) + { + SETSYM(av, gensym("ir")); + SETFLOAT(av + 1, x->wiiremote->posX); // posX and posY are "float"???? + SETFLOAT(av + 2, x->wiiremote->posY); + SETFLOAT(av + 3, x->wiiremote->angle); + SETLONG (av + 4, x->wiiremote->tracking); + outlet_anything(x->dataOut, gensym(remoteStr), 5, av); + + if (x->wiiremote->isExtraOutputEnabled) // B7 + { + SETSYM(av, gensym("irraw")); + SETLONG(av + 1, 0); + SETLONG(av + 2, x->wiiremote->irData[0].x); + SETLONG(av + 3, x->wiiremote->irData[0].y); + SETLONG(av + 4, x->wiiremote->irData[0].s); + outlet_anything(x->dataOut, gensym(remoteStr), 5, av); + SETLONG(av + 1, 1); + SETLONG(av + 2, x->wiiremote->irData[1].x); + SETLONG(av + 3, x->wiiremote->irData[1].y); + SETLONG(av + 4, x->wiiremote->irData[1].s); + outlet_anything(x->dataOut, gensym(remoteStr), 5, av); + SETLONG(av + 1, 2); + SETLONG(av + 2, x->wiiremote->irData[2].x); + SETLONG(av + 3, x->wiiremote->irData[2].y); + SETLONG(av + 4, x->wiiremote->irData[2].s); + outlet_anything(x->dataOut, gensym(remoteStr), 5, av); + SETLONG(av + 1, 3); + SETLONG(av + 2, x->wiiremote->irData[3].x); + SETLONG(av + 3, x->wiiremote->irData[3].y); + SETLONG(av + 4, x->wiiremote->irData[3].s); + outlet_anything(x->dataOut, gensym(remoteStr), 5, av); + } + } + + // Motion Sensor + if (x->wiiremote->isMotionSensorEnabled) + { + SETSYM(av, gensym("motion")); + SETLONG(av + 1, x->wiiremote->accX); + SETLONG(av + 2, x->wiiremote->accY); + SETLONG(av + 3, x->wiiremote->accZ); + SETLONG(av + 4, x->wiiremote->orientation); + outlet_anything(x->dataOut, gensym(remoteStr), 5, av); + + if (x->wiiremote->isExtraOutputEnabled) // B7 + { + SETSYM(av, gensym("motion_calibration")); + SETLONG(av + 1, x->wiiremote->wiiCalibData.accX_zero); + SETLONG(av + 2, x->wiiremote->wiiCalibData.accY_zero); + SETLONG(av + 3, x->wiiremote->wiiCalibData.accZ_zero); + SETLONG(av + 4, x->wiiremote->wiiCalibData.accX_1g); + SETLONG(av + 5, x->wiiremote->wiiCalibData.accY_1g); + SETLONG(av + 6, x->wiiremote->wiiCalibData.accZ_1g); + outlet_anything(x->dataOut, gensym(remoteStr), 7, av); + } + } +} + +//-------------------------------------------------------------------------------------------- + +void akawiiremote_address(t_akawiiremote *x, t_symbol *s) +{ + if (*(s->s_name) == 0) // if null string + *(x->address) = 0; + else + strcpy(x->address, s->s_name); +} + +//-------------------------------------------------------------------------------------------- + +void akawiiremote_connect(t_akawiiremote *x) +{ + post("akawiiremote_connect"); + t_atom status; + Boolean result; + + if (wiiremote_isconnected(x->wiiremote)) + { + SETLONG(&status, -1); + outlet_anything(x->statusOut, gensym("connect"), 1, &status); + } + else + { + result = wiiremote_search(x->wiiremote, x->address); // start searching the device + x->connected = false; + clock_unset(x->clock); // stop clock + clock_delay(x->clock, 0); // start clock to check the device found + } +} + +void akawiiremote_foundFunc(t_akawiiremote *x) +{ +} + +void akawiiremote_disconnect(t_akawiiremote *x) +{ + post("akawiiremote_disconnect"); + + Boolean result; + t_atom status; + + clock_unset(x->clock); // stop clock + wiiremote_stopsearch(x->wiiremote); + + result = wiiremote_disconnect(x->wiiremote); + SETLONG(&status, result); + outlet_anything(x->statusOut, gensym("disconnect"), 1, &status); + + x->connected = !result; +} + +//-------------------------------------------------------------------------------------------- + +void akawiiremote_motionsensor(t_akawiiremote *x, long enable) +{ + Boolean result; + + result = wiiremote_motionsensor(x->wiiremote, enable); + //SETLONG(&status, result); + //outlet_anything(x->statusOut, gensym("motion"), 1, &status); +} + +void akawiiremote_irsensor(t_akawiiremote *x, long enable) +{ + Boolean result; + + result = wiiremote_irsensor(x->wiiremote, enable); + //SETLONG(&status, result); + //outlet_anything(x->statusOut, gensym("ir"), 1, &status); +} + +void akawiiremote_extraoutput(t_akawiiremote *x, long enable) // B7 +{ + x->wiiremote->isExtraOutputEnabled = enable; +} + +void akawiiremote_expansion(t_akawiiremote *x, long enable) +{ + Boolean result; + + result = wiiremote_expansion(x->wiiremote, enable); + //SETLONG(&status, result); + //outlet_anything(x->statusOut, gensym("nunchuk"), 1, &status); +} + +void akawiiremote_vibration(t_akawiiremote *x, long enable) +{ + Boolean result; + + result = wiiremote_vibration(x->wiiremote, enable); + //SETLONG(&status, result); + //outlet_anything(x->statusOut, gensym("vibration"), 1, &status); +} + +void akawiiremote_led(t_akawiiremote *x, long enable1, long enable2, long enable3, long enable4) +{ + Boolean result; + + result = wiiremote_led(x->wiiremote, enable1, enable2, enable3, enable4); + //SETLONG(&status, result); + //outlet_anything(x->statusOut, gensym("led"), 1, &status); +} + +//-------------------------------------------------------------------------------------------- + +void akawiiremote_getbattery(t_akawiiremote *x) +{ + if (x->wiiremote->device == nil) + { + outlet_anything(x->statusOut, gensym("battery"), 0, nil); + } + else + { + t_atom status; + + SETFLOAT(&status, x->wiiremote->batteryLevel); + outlet_anything(x->statusOut, gensym("battery"), 1, &status); + } +} + +void akawiiremote_getexpansion(t_akawiiremote *x) +{ + if (x->wiiremote->device == nil) + { + outlet_anything(x->statusOut, gensym("expansion"), 0, nil); + } + else + { + t_atom status; + if (x->wiiremote->isExpansionPortAttached) + SETLONG(&status, x->wiiremote->expType); + else + SETLONG(&status, 0); + outlet_anything(x->statusOut, gensym("expansion"), 1, &status); + } +} + +void akawiiremote_getled(t_akawiiremote *x) +{ + if (x->wiiremote->device == nil) + { + outlet_anything(x->statusOut, gensym("led"), 0, nil); + } + else + { + t_atom list[4]; + + SETLONG(list, x->wiiremote->isLED1Illuminated); + SETLONG(list + 1, x->wiiremote->isLED2Illuminated); + SETLONG(list + 2, x->wiiremote->isLED3Illuminated); + SETLONG(list + 3, x->wiiremote->isLED4Illuminated); + outlet_anything(x->statusOut, gensym("led"), 4, list); + } +} + +void akawiiremote_getcalibration(t_akawiiremote *x) +{ + if (x->wiiremote->device == nil) + { + outlet_anything(x->statusOut, gensym("calibration"), 0, nil); + } + else + { + t_atom list[8]; + + if (x->wiiremote->isExpansionPortAttached) + { + SETSYM(list, gensym(nunchukStr)); + SETSYM(list + 1, gensym("stick")); + SETLONG(list + 2, x->wiiremote->nunchukJoyStickCalibData.x_max); + SETLONG(list + 3, x->wiiremote->nunchukJoyStickCalibData.x_min); + SETLONG(list + 4, x->wiiremote->nunchukJoyStickCalibData.x_center); + SETLONG(list + 5, x->wiiremote->nunchukJoyStickCalibData.y_max); + SETLONG(list + 6, x->wiiremote->nunchukJoyStickCalibData.y_min); + SETLONG(list + 7, x->wiiremote->nunchukJoyStickCalibData.y_center); + outlet_anything(x->statusOut, gensym("calibration"), 8, list); + + SETSYM(list + 1, gensym("motion")); + SETLONG(list + 2, x->wiiremote->nunchukCalibData.accX_zero); + SETLONG(list + 3, x->wiiremote->nunchukCalibData.accY_zero); + SETLONG(list + 4, x->wiiremote->nunchukCalibData.accZ_zero); + SETLONG(list + 5, x->wiiremote->nunchukCalibData.accX_1g); + SETLONG(list + 6, x->wiiremote->nunchukCalibData.accY_1g); + SETLONG(list + 7, x->wiiremote->nunchukCalibData.accZ_1g); + outlet_anything(x->statusOut, gensym("calibration"), 8, list); + } + + SETSYM(list, gensym(remoteStr)); + SETSYM(list + 1, gensym("motion")); + SETLONG(list + 2, x->wiiremote->wiiCalibData.accX_zero); + SETLONG(list + 3, x->wiiremote->wiiCalibData.accY_zero); + SETLONG(list + 4, x->wiiremote->wiiCalibData.accZ_zero); + SETLONG(list + 5, x->wiiremote->wiiCalibData.accX_1g); + SETLONG(list + 6, x->wiiremote->wiiCalibData.accY_1g); + SETLONG(list + 7, x->wiiremote->wiiCalibData.accZ_1g); + outlet_anything(x->statusOut, gensym("calibration"), 8, list); + } +} + +//-------------------------------------------------------------------------------------------- + +void akawiiremote_getaddress(t_akawiiremote *x) +{ + if (x->wiiremote->device == nil) + { + outlet_anything(x->statusOut, gensym("address"), 0, nil); + } + else + { + char str[32]; + t_atom address; + + wiiremote_getaddress(x->wiiremote, str); + SETSYM(&address, gensym(str)); + outlet_anything(x->statusOut, gensym("address"), 1, &address); + } +} + +//-------------------------------------------------------------------------------------------- + +void akawiiremote_clock(t_akawiiremote *x) +{ + Boolean connection; + t_atom status; + + connection = wiiremote_isconnected(x->wiiremote); + + if (x->connected == false && connection == true) // if the device is connected... + { + wiiremote_getstatus(x->wiiremote); + x->connected = true; + SETLONG(&status, 1); + outlet_anything(x->statusOut, gensym("connect"), 1, &status); + } + + if (x->connected == true && connection == false) + { + x->connected = false; + SETLONG(&status, 0); + outlet_anything(x->statusOut, gensym("connect"), 1, &status); + } + + clock_delay(x->clock, kInterval); // restart clock +} + +//-------------------------------------------------------------------------------------------- + +void akawiiremote_assist(t_akawiiremote *x, void *b, long m, long a, char *s) +{ +#ifndef PD /* Max */ + if (m==ASSIST_INLET) + { + sprintf(s,"connect, bang, disconnect...."); + } + else +#endif /* NOT PD */ + { + switch(a) + { + case 0: sprintf(s,"data messages"); break; + case 2: sprintf(s,"status messages"); break; + } + } +} + +//-------------------------------------------------------------------------------------------- + +void *akawiiremote_new(t_symbol *s, short ac, t_atom *av) +{ +#ifdef PD + t_akawiiremote *x = (t_akawiiremote *)pd_new(wiiremote_class); + t_symbol *first_argument; + + x->statusOut = outlet_new(&x->x_obj, 0); + x->dataOut = outlet_new(&x->x_obj, &s_list); + +/* this sets the device name from the object arguments */ + first_argument = atom_getsymbolarg(0, ac, av); + if(first_argument != &s_) + atom_string(av, x->address, MAXPDSTRING-1); +#else /* Max */ + t_akawiiremote *x; + + x = (t_akawiiremote *)newobject(akawiiremote_class); + + x->statusOut = outlet_new(x, 0); + x->dataOut = outlet_new(x, 0); + + if (ac>0 && av[0].a_type == A_SYM) + strcpy(x->address, av[0].a_w.w_sym->s_name); +#endif /* PD */ + + x->wiiremote = (WiiRemoteRef)getbytes(sizeof(WiiRemoteRec)); + if (x->wiiremote != nil) + { + wiiremote_init(x->wiiremote); + x->wiiremote->isMotionSensorEnabled = true; + x->wiiremote->isIRSensorEnabled = false; + x->wiiremote->isVibrationEnabled = false; + x->wiiremote->isExpansionPortEnabled = false; + x->wiiremote->isLED1Illuminated = false; + x->wiiremote->isLED2Illuminated = false; + x->wiiremote->isLED3Illuminated = false; + x->wiiremote->isLED4Illuminated = false; + x->wiiremote->isExtraOutputEnabled = false; + } + + x->clock = clock_new(x, (method)akawiiremote_clock); + + x->connected = false; + + return x; +} + +void akawiiremote_free(t_akawiiremote *x) +{ + if (x->wiiremote != nil) + { + if (wiiremote_isconnected(x->wiiremote)) + wiiremote_disconnect(x->wiiremote); + freebytes(x->wiiremote, sizeof(WiiRemoteRec)); + x->wiiremote = nil; + } + + clock_unset(x->clock); +#ifdef PD + clock_free(x->clock); +#else /* Max */ + freeobject((t_object *)x->clock); +#endif /* PD */ +} + diff --git a/aka.wiiremote/wiiremote-help.pd b/aka.wiiremote/wiiremote-help.pd new file mode 100644 index 0000000..5c8f610 --- /dev/null +++ b/aka.wiiremote/wiiremote-help.pd @@ -0,0 +1,80 @@ +#N canvas 287 96 744 626 10; +#X msg 128 207 connect; +#X msg 141 228 disconnect; +#X obj 218 203 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X obj 294 202 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X obj 127 285 metro 100; +#X obj 127 264 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X msg 89 283 bang; +#X text 49 49 - Use the Bluetooth Setup Assistant to setup the WiiRemote +with your computer (only required for the first use).; +#X text 49 79 - Press the "Sync" button on the WiiRemote \, four LEDs +will start blinking.; +#X text 49 109 - Click on the [connect( message \, the LEDs will stop +blinking once its connected; +#X text 49 139 - Start the [metro] to get updates from [wiiremote] +; +#X obj 399 526 pddp/print; +#X obj 354 556 pddp/print; +#X obj 354 410 route remote; +#X msg 503 290 getbattery; +#X msg 503 310 getled; +#X msg 503 330 getexpansion; +#X obj 489 431 print RIGHT; +#X obj 253 430 print LEFT; +#X obj 354 476 route motion buttons ir; +#X obj 444 497 pddp/print; +#X msg 294 224 ir \$1; +#X msg 218 225 motion \$1; +#X obj 344 202 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X msg 344 224 vibration \$1; +#X obj 434 202 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X msg 434 224 expansion \$1; +#X obj 524 202 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X msg 524 223 extraoutput \$1; +#N canvas 254 342 450 300 address 0; +#X obj 176 252 outlet; +#X msg 206 126 getaddress; +#X msg 176 72 address 00-1e-35-4c-e6-f1; +#X connect 1 0 0 0; +#X connect 2 0 0 0; +#X restore 25 462 pd address; +#X msg 503 352 getaddress; +#X obj 631 536 dac~; +#X obj 632 408 pddp/dsp; +#X obj 640 500 osc~ 100; +#X obj 303 388 wiiremote 00-1e-35-4c-e6-f1; +#X connect 0 0 34 0; +#X connect 1 0 34 0; +#X connect 2 0 22 0; +#X connect 3 0 21 0; +#X connect 4 0 34 0; +#X connect 5 0 4 0; +#X connect 6 0 34 0; +#X connect 13 0 19 0; +#X connect 13 1 17 0; +#X connect 14 0 34 0; +#X connect 15 0 34 0; +#X connect 16 0 34 0; +#X connect 19 0 12 0; +#X connect 19 1 11 0; +#X connect 19 2 20 0; +#X connect 21 0 34 0; +#X connect 22 0 34 0; +#X connect 23 0 24 0; +#X connect 24 0 34 0; +#X connect 25 0 26 0; +#X connect 26 0 34 0; +#X connect 27 0 28 0; +#X connect 28 0 34 0; +#X connect 30 0 34 0; +#X connect 33 0 31 0; +#X connect 33 0 31 1; +#X connect 34 0 18 0; +#X connect 34 1 13 0; diff --git a/aka.wiiremote/wiiremote.c b/aka.wiiremote/wiiremote.c new file mode 100644 index 0000000..481085e --- /dev/null +++ b/aka.wiiremote/wiiremote.c @@ -0,0 +1,1087 @@ +// wiiremote.c +// Copyright by Masayuki Akamatsu +// Based on "DarwiinRemote" by Hiroaki Kimura + +#include "wiiremote.h" +#include + +// this type is used a lot (data array): +typedef unsigned char darr[]; + +#define kTrial 10 +#define kWait 10000 +// the unit of kWait is microseconds, thus 10000 means 10ms + +#define kWiiIRPixelsWidth 1024.0 +#define kWiiIRPixelsHeight 768.0 + + +Boolean requestUpdates(WiiRemoteRef wiiremote); +void myEventListener(IOBluetoothL2CAPChannelRef channel, void *refCon, IOBluetoothL2CAPChannelEvent *event); + + +//-------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------- + +void wiiremote_init(WiiRemoteRef wiiremote) +{ + wiiremote->inquiry = nil; + wiiremote->device = nil; + wiiremote->ichan = nil; + wiiremote->cchan = nil; + + wiiremote->address = nil; + + wiiremote->accX = 0x10; + wiiremote->accY = 0x10; + wiiremote->accZ = 0x10; + wiiremote->buttonData = 0; + + wiiremote->lowZ = 0; + wiiremote->lowX = 0; + wiiremote->leftPoint = -1; + wiiremote->tracking = false; + + wiiremote->batteryLevel = 0; + + wiiremote->readingRegister = false; + wiiremote->isMotionSensorEnabled = false; + wiiremote->isVibrationEnabled = false; + wiiremote->isIRSensorEnabled = false; + wiiremote->wiiIRMode = kWiiIRModeExtended; + wiiremote->isExpansionPortEnabled = false; + wiiremote->isExpansionPortAttached = false; + wiiremote->expType = WiiExpNotAttached; + + wiiremote->isLED1Illuminated = false; + wiiremote->isLED2Illuminated = false; + wiiremote->isLED3Illuminated = false; + wiiremote->isLED4Illuminated = false; + + wiiremote->nAccX = 0x10; + wiiremote->nAccY = 0x10; + wiiremote->nAccZ = 0x10; + wiiremote->nButtonData = 0; + + wiiremote->nLowZ = 0; + wiiremote->nLowX = 0; + +} + +//-------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------- + +Boolean openCChan(WiiRemoteRef wiiremote) +{ + short i; + IOReturn ret; + + // open L2CAPChannel : BluetoothL2CAPPSM = 17 + for (i=0; idevice, &(wiiremote->cchan), 17, myEventListener, (void *)wiiremote); + if ( ret == kIOReturnSuccess) + break; + usleep(kWait); // wait 10ms + } + if (i==kTrial) + { + wiiremote->cchan = nil; + IOBluetoothDeviceCloseConnection(wiiremote->device); + return false; + } + IOBluetoothObjectRetain(wiiremote->cchan); + + return (ret==kIOReturnSuccess); +} + +Boolean openIChan(WiiRemoteRef wiiremote) +{ + short i; + IOReturn ret; + + // open L2CAPChannel : BluetoothL2CAPPSM = 19 + for (i=0; idevice, &(wiiremote->ichan), 19, myEventListener, (void *)wiiremote); + if ( ret == kIOReturnSuccess) + break; + usleep(kWait); // wait 10ms + } + if (i==kTrial) + { + wiiremote->ichan = nil; + IOBluetoothL2CAPChannelCloseChannel(wiiremote->cchan); + IOBluetoothObjectRelease(wiiremote->cchan); + IOBluetoothDeviceCloseConnection(wiiremote->device); + return false; + } + IOBluetoothObjectRetain(wiiremote->ichan); + + return (ret==kIOReturnSuccess); +} + +//-------------------------------------------------------------------------------------------- + +Boolean sendCommand(WiiRemoteRef wiiremote, unsigned char *data, unsigned short length) +{ + unsigned char buf[40]; + IOReturn ret; + int i; + + memset(buf,0,40); + buf[0] = 0x52; + memcpy(buf+1, data, length); + if (buf[1] == 0x16) + length=23; + else + length++; + + usleep(kWait); // wait 10ms // Done to make sure commands don't happen too fast. + + for (i = 0; icchan, buf, length); + if (ret == kIOReturnSuccess) + break; + usleep(kWait); + } + + if (ret != kIOReturnSuccess) + wiiremote_disconnect(wiiremote); + + return (ret==kIOReturnSuccess); +} + +Boolean writeData(WiiRemoteRef wiiremote, const unsigned char *data, unsigned long address, unsigned short length) +{ + unsigned char cmd[22]; + int i; + unsigned long addr = address; + + + for(i=0 ; i>24) & 0xFF; + cmd[2] = (addr>>16) & 0xFF; + cmd[3] = (addr>> 8) & 0xFF; + cmd[4] = (addr>> 0) & 0xFF; + cmd[5] = length; + + // and of course the vibration flag, as usual + if (wiiremote->isVibrationEnabled) cmd[1] |= 0x01; + + data = cmd; + + return sendCommand(wiiremote, cmd, 22); +} + +Boolean readData(WiiRemoteRef wiiremote, unsigned long address, unsigned short length) +{ + + unsigned char cmd[7]; + unsigned long addr = address; + unsigned short len = length; + + cmd[0] = 0x17; + cmd[1] = (addr>>24)&0xFF; + cmd[2] = (addr>>16)&0xFF; + cmd[3] = (addr>> 8)&0xFF; + cmd[4] = (addr>> 0)&0xFF; + + cmd[5] = (len >> 8)&0xFF; + cmd[6] = (len >> 0)&0xFF; + + if (wiiremote->isVibrationEnabled) cmd[1] |= 0x01; + if (cmd[1] & 0x02) wiiremote->readingRegister = true; + + return sendCommand(wiiremote, cmd, 7); +} + +//-------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------- + +void checkDevice(WiiRemoteRef wiiremote, IOBluetoothDeviceRef device) +{ + post("checkDevice"); + CFStringRef name; + CFStringRef address; + + if (wiiremote_isconnected(wiiremote)) + return; + + name = IOBluetoothDeviceGetName(device); + address = IOBluetoothDeviceGetAddressString(device); + if (name != nil && address != nil) + { + if (CFStringCompare(name, CFSTR("Nintendo RVL-CNT-01"), 0) == kCFCompareEqualTo) + { + if ( CFStringGetLength(wiiremote->address) == 0 + || CFStringCompare(address, wiiremote->address, kCFCompareCaseInsensitive) == kCFCompareEqualTo) + { + wiiremote->device = IOBluetoothObjectRetain(device); + if ( wiiremote_connect(wiiremote) == false ) + wiiremote_disconnect(wiiremote); + } + } + } +} + +void myFoundFunc(void *refCon, IOBluetoothDeviceInquiryRef inquiry, IOBluetoothDeviceRef device) +{ + post("myFoundFunc"); + checkDevice((WiiRemoteRef)refCon, device); +} + +void myUpdatedFunc(void *refCon, IOBluetoothDeviceInquiryRef inquiry, IOBluetoothDeviceRef device, uint32_t devicesRemaining) +{ + post("myUpdatedFunc"); + + checkDevice((WiiRemoteRef)refCon, device); +} + +void myCompleteFunc(void *refCon, IOBluetoothDeviceInquiryRef inquiry, IOReturn error, Boolean aborted) +{ + post("myCompleteFunc"); + + if (aborted) return; // called by stop ;) + + if (error != kIOReturnSuccess) + { + wiiremote_stopsearch((WiiRemoteRef)refCon); + return; + } +#ifdef PD + // PD doesn't use the Carbon loop, so we have to manually control it + CFRunLoopStop( CFRunLoopGetCurrent() ); +#endif +} + +//-------------------------------------------------------------------------------------------- + +Boolean wiiremote_isconnected(WiiRemoteRef wiiremote) +{ + Boolean result; + + result = wiiremote->device != nil && IOBluetoothDeviceIsConnected(wiiremote->device); + return result; +} + +Boolean wiiremote_search(WiiRemoteRef wiiremote, char *address) +{ + post("wiiremote_search"); + IOReturn ret; + + if (wiiremote->inquiry != nil) + return true; + + wiiremote->inquiry = IOBluetoothDeviceInquiryCreateWithCallbackRefCon((void *)wiiremote); + IOBluetoothDeviceInquirySetDeviceFoundCallback(wiiremote->inquiry, myFoundFunc); + IOBluetoothDeviceInquirySetDeviceNameUpdatedCallback(wiiremote->inquiry, myUpdatedFunc); + IOBluetoothDeviceInquirySetCompleteCallback(wiiremote->inquiry, myCompleteFunc); + + if (wiiremote->address != nil) + CFRelease(wiiremote->address); + wiiremote->address = CFStringCreateWithCString(nil, address, kCFStringEncodingMacRoman); + + ret = IOBluetoothDeviceInquiryStart(wiiremote->inquiry); + if (ret != kIOReturnSuccess) + { + IOBluetoothDeviceInquiryDelete(wiiremote->inquiry); + wiiremote->inquiry = nil; + return false; + } +#ifdef PD + CFRunLoopRun(); // PD doesn't use the Carbon loop, so we have to manually control it +#endif + return true; +} + +Boolean wiiremote_stopsearch(WiiRemoteRef wiiremote) +{ + post("wiiremote_stopsearch"); + IOReturn ret; + + if (wiiremote->inquiry == nil) + { + return true; // already stopped + } + + ret = IOBluetoothDeviceInquiryStop(wiiremote->inquiry); + + if (ret != kIOReturnSuccess && ret != kIOReturnNotPermitted) + { + // kIOReturnNotPermitted is if it's already stopped + } + + IOBluetoothDeviceInquiryDelete(wiiremote->inquiry); + wiiremote->inquiry = nil; + + return (ret==kIOReturnSuccess); +} + +//-------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------- + +unsigned char decrypt(unsigned char data) +{ + return (data ^ 0x17) + 0x17; +} + +//-------------------------------------------------------------------------------------------- + +/** +* Handle report 0x21 (Read Data) from wiimote. + * dp[0] = Bluetooth header + * dp[1] = (0x21) Report/Channel ID + * dp[2] = Wiimote Buttons + * dp[3] = Wiimote Buttons + * dp[4] = High 4 bits = payload size; Low 4 bits = Error flag (0 = all good) + * dp[5] = Offset of memory read + * dp[6] = Offset of memory read + * dp[7+] = the Data. + **/ + +void handleRAMData(WiiRemoteRef wiiremote, unsigned char *dp, size_t dataLength) +{ + // specify attached expasion device + if ((dp[5] == 0x00) && (dp[6] == 0xF0)) + { + if (decrypt(dp[21]) == 0x00) + { + wiiremote->expType = WiiNunchuk; + } + else + if (decrypt(dp[21]) == 0x01) + { + wiiremote->expType = WiiClassicController; + } + else + { + wiiremote->expType = WiiExpNotAttached; + } + // initExpPort = NO; + return; + } + + // wiimote calibration data + if (!wiiremote->readingRegister && dp[5] == 0x00 && dp[6] == 0x20) + { + wiiremote->wiiCalibData.accX_zero = dp[7]; + wiiremote->wiiCalibData.accY_zero = dp[8]; + wiiremote->wiiCalibData.accZ_zero = dp[9]; + + //dp[10] - unknown/unused + + wiiremote->wiiCalibData.accX_1g = dp[11]; + wiiremote->wiiCalibData.accY_1g = dp[12]; + wiiremote->wiiCalibData.accZ_1g = dp[13]; + return; + } + + // expansion device calibration data. + if (wiiremote->readingRegister && dp[5] == 0x00 && dp[6] == 0x20) + { + if (wiiremote->expType == WiiNunchuk) + { + //nunchuk calibration data + wiiremote->nunchukCalibData.accX_zero = decrypt(dp[7]); + wiiremote->nunchukCalibData.accY_zero = decrypt(dp[8]); + wiiremote->nunchukCalibData.accZ_zero = decrypt(dp[9]); + + wiiremote->nunchukCalibData.accX_1g = decrypt(dp[11]); + wiiremote->nunchukCalibData.accY_1g = decrypt(dp[12]); + wiiremote->nunchukCalibData.accZ_1g = decrypt(dp[13]); + + wiiremote->nunchukJoyStickCalibData.x_max = decrypt(dp[15]); + wiiremote->nunchukJoyStickCalibData.x_min = decrypt(dp[16]); + wiiremote->nunchukJoyStickCalibData.x_center = decrypt(dp[17]); + + wiiremote->nunchukJoyStickCalibData.y_max = decrypt(dp[18]); + wiiremote->nunchukJoyStickCalibData.y_min = decrypt(dp[19]); + wiiremote->nunchukJoyStickCalibData.y_center = decrypt(dp[20]); + + return; + } + else + if (wiiremote->expType == WiiClassicController) + { + //classic controller calibration data (probably) + } + } + + // wii remote buttons + wiiremote->buttonData = ((short)dp[2] << 8) + dp[3]; +} + +void handleStatusReport(WiiRemoteRef wiiremote, unsigned char *dp, size_t dataLength) +{ + wiiremote->batteryLevel = (double)dp[7]; + wiiremote->batteryLevel /= (double)0xC0; // C0 = fully charged. + + if ((dp[4] & 0x02)) //some device attached to Wiimote + { + wiiremote->isExpansionPortAttached = true; + // initExpPort = YES; + + Boolean ret = writeData(wiiremote, (darr){0x00}, 0x04A40040, 1); // Initialize the device + + if (ret == false) + { + wiiremote->isExpansionPortAttached = false; + return; + } + + usleep(kWait); // Give the write a chance to be processed. + + ret = readData(wiiremote, 0x04A400F0, 16); // read expansion device type + if (ret == false) + { + wiiremote->isExpansionPortAttached = false; + } + } + else + { // unplugged + wiiremote->isExpansionPortAttached = false; + wiiremote->expType = WiiExpNotAttached; + } + + if (dp[4] & 0x10) + wiiremote->isLED1Illuminated = true; + else + wiiremote->isLED1Illuminated = false; + + if (dp[4] & 0x20) + wiiremote->isLED2Illuminated = true; + else + wiiremote->isLED2Illuminated = false; + + if (dp[4] & 0x40) + wiiremote->isLED3Illuminated = true; + else + wiiremote->isLED3Illuminated = false; + + if (dp[4] & 0x80) + wiiremote->isLED4Illuminated = true; + else + wiiremote->isLED4Illuminated = false; +} + +void handleExtensionData(WiiRemoteRef wiiremote, unsigned char *dp, size_t dataLength) +{ + unsigned char startByte; + + switch (dp[1]) { + case 0x34 : + startByte = 4; + break; + case 0x35 : + startByte = 7; + break; + case 0x36 : + startByte = 14; + break; + case 0x37 : + startByte = 17; + break; + default: + return; // This shouldn't ever happen. + break; + } + + if (wiiremote->expType == WiiNunchuk) + { + wiiremote->nStickX = decrypt(dp[startByte]); + wiiremote->nStickY = decrypt(dp[startByte +1]); + wiiremote->nAccX = decrypt(dp[startByte +2]); + wiiremote->nAccY = decrypt(dp[startByte +3]); + wiiremote->nAccZ = decrypt(dp[startByte +4]); + wiiremote->nButtonData = decrypt(dp[startByte +5]); + + wiiremote->nLowZ = wiiremote->nLowZ * .9 + wiiremote->nAccZ * .1; + wiiremote->nLowX = wiiremote->nLowX * .9 + wiiremote->nAccX * .1; + + float absx = abs(wiiremote->nLowX - 128); + float absz = abs(wiiremote->nLowZ - 128); + + if (wiiremote->nOrientation == 0 || wiiremote->nOrientation == 2) absx -= 5; + if (wiiremote->nOrientation == 1 || wiiremote->nOrientation == 3) absz -= 5; + + if (absz >= absx) + { + if (absz > 5) + wiiremote->nOrientation = (wiiremote->nLowZ > 128) ? 0 : 2; + } + else + { + if (absx > 5) + wiiremote->nOrientation = (wiiremote->nLowX > 128) ? 3 : 1; + } + } + else + if (wiiremote->expType == WiiClassicController) + { + wiiremote->cButtonData = (unsigned short)(decrypt(dp[startByte + 4]) << 8) + decrypt(dp[startByte + 5]); + wiiremote->cButtonData = ~wiiremote->cButtonData; // bit reverse + + wiiremote->cStickX1 = decrypt(dp[startByte]) & 0x3F; + wiiremote->cStickY1 = decrypt(dp[startByte + 1]) & 0x3F; + + wiiremote->cStickX2 = (((decrypt(dp[startByte +0]) & 0xC0) >> 3) | + ((decrypt(dp[startByte +1]) & 0xC0) >> 5) | + ((decrypt(dp[startByte +2]) & 0x80) >> 7)) & 0x1F; + wiiremote->cStickY2 = decrypt(dp[startByte + 2]) & 0x1F; + + wiiremote->cAnalogL = (((decrypt(dp[startByte +2]) & 0x60) >> 2) | + ((decrypt(dp[startByte +3]) & 0xE0) >> 5)) & 0x1F; + wiiremote->cAnalogR = decrypt(dp[startByte + 3]) & 0x1F; + } +} + +void handleIRData(WiiRemoteRef wiiremote, unsigned char *dp, size_t dataLength) +{ + int i; + + if (dp[1] == 0x33) + { // 12 IR bytes + int startByte = 0; + for(i=0 ; i < 4 ; i++) + { + startByte = 7 + 3 * i; + wiiremote->irData[i].x = (dp[startByte +0] | ((dp[startByte +2] & 0x30) << 4)) & 0x3FF; + wiiremote->irData[i].y = (dp[startByte +1] | ((dp[startByte +2] & 0xC0) << 2)) & 0x3FF; + wiiremote->irData[i].s = dp[startByte +2] & 0x0F; + } + } + else + { // 10 IR bytes + int shift = (dp[1] == 0x36) ? 4 : 7; + int startByte = 0; + for (i=0; i < 2; i++) { + startByte = shift + 5 * i; + wiiremote->irData[2*i].x = (dp[startByte +0] | ((dp[startByte +2] & 0x30) << 4)) & 0x3FF; + wiiremote->irData[2*i].y = (dp[startByte +1] | ((dp[startByte +2] & 0xC0) << 2)) & 0x3FF; + wiiremote->irData[2*i].s = ((wiiremote->irData[2*i].x == wiiremote->irData[2*i].y) && (wiiremote->irData[2*i].x == 0x3FF)) ? 0x0F : 0x05; // No size is given in 10 byte report. + + wiiremote->irData[(2*i)+1].x = (dp[startByte +3] | ((dp[startByte +2] & 0x03) << 8)) & 0x3FF; + wiiremote->irData[(2*i)+1].y = (dp[startByte +4] | ((dp[startByte +2] & 0x0C) << 6)) & 0x3FF; + wiiremote->irData[(2*i)+1].s = ((wiiremote->irData[(2*i)+1].x == wiiremote->irData[(2*i)+1].y) && (wiiremote->irData[(2*i)+1].x == 0x3FF)) ? 0x0F : 0x05; // No size is given in 10 byte report. + } + } + + int p1 = -1; + int p2 = -1; + // we should modify this loop to take the points with the lowest s (the brightest ones) + for (i=0 ; i<4 ; i++) { + if (p1 == -1) { + if (wiiremote->irData [i].s < 0x0F) + p1 = i; + } else { + if (wiiremote->irData [i].s < 0x0F) { + p2 = i; + break; + } + } + } + + double ox, oy; + if ((p1 > -1) && (p2 > -1)) + { + int l = wiiremote->leftPoint; + if (wiiremote->leftPoint == -1) + { + switch (wiiremote->orientation) + { + case 0: l = (wiiremote->irData[p1].x < wiiremote->irData[p2].x) ? 0 : 1; break; + case 1: l = (wiiremote->irData[p1].y > wiiremote->irData[p2].y) ? 0 : 1; break; + case 2: l = (wiiremote->irData[p1].x > wiiremote->irData[p2].x) ? 0 : 1; break; + case 3: l = (wiiremote->irData[p1].y < wiiremote->irData[p2].y) ? 0 : 1; break; + } + + wiiremote->leftPoint = l; + } + + int r = 1-l; + + double dx = wiiremote->irData[r].x - wiiremote->irData[l].x; + double dy = wiiremote->irData[r].y - wiiremote->irData[l].y; + double d = hypot (dx, dy); + + dx /= d; + dy /= d; + + double cx = (wiiremote->irData[l].x + wiiremote->irData[r].x)/kWiiIRPixelsWidth - 1; + double cy = (wiiremote->irData[l].y + wiiremote->irData[r].y)/kWiiIRPixelsHeight - 1; + + ox = -dy*cy-dx*cx; + oy = -dx*cy+dy*cx; + + // cam: + // Compensate for distance. There must be fewer than 0.75*768 pixels between the spots for this to work. + // In other words, you have to be far enough away from the sensor bar for the two spots to have enough + // space on the image sensor to travel without one of the points going off the image. + // note: it is working very well ... + double gain = 4; + if (d < (0.75 * kWiiIRPixelsHeight)) + gain = 1 / (1 - d/kWiiIRPixelsHeight); + + ox *= gain; + oy *= gain; + + wiiremote->angle = atan2(dy, dx); + wiiremote->tracking = true; + } + else + { + ox = oy = -100; + wiiremote->leftPoint = -1; // not tracking + wiiremote->angle = -100; + wiiremote->tracking = false; + } + + wiiremote->posX = ox; + wiiremote->posY = oy; +} + +void handleButtonReport(WiiRemoteRef wiiremote, unsigned char *dp, size_t dataLength) +{ + // wiimote buttons + wiiremote->buttonData = ((short)dp[2] << 8) + dp[3]; + + // report contains extension data + switch (dp[1]) + { + case 0x34 : + case 0x35 : + case 0x36 : + case 0x37 : + handleExtensionData(wiiremote, dp, dataLength); + break; + } + + // report contains IR data + if (dp[1] & 0x02) + { + handleIRData(wiiremote, dp, dataLength); + } + + // report contains motion sensor data + if (dp[1] & 0x01) + { + wiiremote->accX = dp[4]; + wiiremote->accY = dp[5]; + wiiremote->accZ = dp[6]; + + wiiremote->lowZ = wiiremote->lowZ * 0.9 + wiiremote->accZ * 0.1; + wiiremote->lowX = wiiremote->lowX * 0.9 + wiiremote->accX * 0.1; + + float absx = abs(wiiremote->lowX-128); + float absz = abs(wiiremote->lowZ-128); + + if (wiiremote->orientation == 0 || wiiremote->orientation == 2) absx -= 5; + if (wiiremote->orientation == 1 || wiiremote->orientation == 3) absz -= 5; + + if (absz >= absx) + { + if (absz > 5) + wiiremote->orientation = (wiiremote->lowZ > 128)?0:2; + } + else + { + if (absx > 5) + wiiremote->orientation = (wiiremote->lowX > 128)?3:1; + } + } +} + +//-------------------------------------------------------------------------------------------- + + void myDataListener(IOBluetoothL2CAPChannelRef channel, void *dataPointer, UInt16 dataLength, void *refCon) +{ + WiiRemoteRef wiiremote = (WiiRemoteRef)refCon; + unsigned char* dp = (unsigned char*)dataPointer; + + if (!wiiremote->device) + return; + + //controller status (expansion port and battery level data) - received when report 0x15 sent to Wiimote (getCurrentStatus:) or status of expansion port changes. + if (dp[1] == 0x20 && dataLength >= 8) + { + handleStatusReport(wiiremote, dp, dataLength); + requestUpdates(wiiremote); // Make sure we keep getting state change reports. + return; + } + + if (dp[1] == 0x21) + { + handleRAMData(wiiremote, dp, dataLength); + return; + } + + if (dp[1] == 0x22) + { // Write data response + //NSLog(@"Write data response: %00x %00x %00x %00x", dp[2], dp[3], dp[4], dp[5]); + return; + } + + // report contains button info + if ((dp[1] & 0xF0) == 0x30) + { + handleButtonReport(wiiremote, dp, dataLength); + } +} + +void myEventListener(IOBluetoothL2CAPChannelRef channel, void *refCon, IOBluetoothL2CAPChannelEvent *event) +{ + if (event->eventType == kIOBluetoothL2CAPChannelEventTypeData) + { + // In thise case: + // event->u.newData.dataPtr is a pointer to the block of data received. + // event->u.newData.dataSize is the size of the block of data. + myDataListener(channel, event->u.data.dataPtr, event->u.data.dataSize, refCon); + } + else + if (event->eventType == kIOBluetoothL2CAPChannelEventTypeClosed) + { + // In this case: + // event->u.terminatedChannel is the channel that was terminated. It can be converted in an IOBluetoothL2CAPChannel + // object with [IOBluetoothL2CAPChannel withL2CAPChannelRef:]. (see below). + } +} + +void myDisconnectedFunc(void * refCon, IOBluetoothUserNotificationRef inRef, IOBluetoothObjectRef objectRef) +{ + CFStringRef itsAddress, myAddress; + + itsAddress = IOBluetoothDeviceGetAddressString(objectRef); + if (itsAddress != nil) + { + myAddress = IOBluetoothDeviceGetAddressString(((WiiRemoteRef)refCon)->device); + if (myAddress != nil) + { + if (CFStringCompare(itsAddress, myAddress, 0) == kCFCompareEqualTo) + { + wiiremote_disconnect((WiiRemoteRef)refCon); + } + CFRelease(myAddress); + } + CFRelease(itsAddress); + } +} + +//-------------------------------------------------------------------------------------------- + +void wiiremote_getaddress(WiiRemoteRef wiiremote, char *address) +{ + CFStringRef cfstring; + + cfstring = IOBluetoothDeviceGetAddressString(wiiremote->device); + CFStringGetCString(cfstring, address, 32, kCFStringEncodingMacRoman); + CFRelease(cfstring); + +} + +//-------------------------------------------------------------------------------------------- + +Boolean wiiremote_connect(WiiRemoteRef wiiremote) +{ + IOReturn ret; + Boolean result; + short i; + + if (wiiremote->device == nil) + return false; + + // connect the device + for (i=0; idevice, nil, nil); + if ( ret == kIOReturnSuccess) + break; + usleep(kWait); // wait 10ms + } + if (i==kTrial) + return false; + + wiiremote->disconnectNotification = IOBluetoothDeviceRegisterForDisconnectNotification(wiiremote->device, myDisconnectedFunc, (void *)wiiremote); + + // performs an SDP query + for (i=0; idevice, nil, nil); + if ( ret == kIOReturnSuccess) + break; + usleep(kWait); // wait 10ms + } + if (i==kTrial) + return false; + + result = openCChan(wiiremote); + result = openIChan(wiiremote); + + if (result) + { + result = wiiremote_led(wiiremote, wiiremote->isLED1Illuminated, wiiremote->isLED2Illuminated, wiiremote->isLED3Illuminated, wiiremote->isLED4Illuminated); + } + + if (result == false) + { + wiiremote_disconnect(wiiremote); + return result; + } + + wiiremote_getstatus(wiiremote); + requestUpdates(wiiremote); + + readData(wiiremote, 0x0020, 7); // Get Accelerometer callibration data + + return true; +} + + +Boolean wiiremote_disconnect(WiiRemoteRef wiiremote) +{ + short i = 0; + + if (wiiremote->cchan) + { + if (IOBluetoothDeviceIsConnected(wiiremote->device)) + { + for (i=0; icchan) == kIOReturnSuccess) + break; + usleep(kWait); // wait 10ms + } + } + if (i==kTrial) return false; + IOBluetoothObjectRelease(wiiremote->cchan); + wiiremote->cchan = nil; + } + + if (wiiremote->ichan) + { + if (IOBluetoothDeviceIsConnected(wiiremote->device)) + { + for (i=0; iichan) == kIOReturnSuccess) + break; + } + } + if (i==kTrial) return false; + IOBluetoothObjectRelease(wiiremote->ichan); + wiiremote->ichan = nil; + } + + if (wiiremote->device) + { + if (IOBluetoothDeviceIsConnected(wiiremote->device)) + { + for (i=0; idevice) == kIOReturnSuccess) + break; + } + } + if (i==kTrial) return false; + IOBluetoothObjectRelease(wiiremote->device); + wiiremote->device = nil; + } + + if (wiiremote->disconnectNotification != nil) + { + IOBluetoothUserNotificationUnregister(wiiremote->disconnectNotification); + wiiremote->disconnectNotification = nil; + } + + return true; +} + +//-------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------- + +Boolean requestUpdates(WiiRemoteRef wiiremote) +{ + Boolean result; + + // Set the report type the Wiimote should send. + unsigned char cmd[] = {0x12, 0x02, 0x30}; // Just buttons. + + if (wiiremote->isVibrationEnabled) cmd[1] |= 0x01; + + /* + There are numerous status report types that can be requested. + The IR reports must be matched with the data format set when initializing the IR camera: + 0x36, 0x37 - 10 IR bytes go with Basic mode + 0x33 - 12 IR bytes go with Extended mode + 0x3e/0x3f - 36 IR bytes go with Full mode + + The Nunchuk and Classic controller use 6 bytes to report their state, so the reports that + give more extension bytes don't provide any more info. + + Buttons | Accelerometer | IR | Extension + --------------------+-------------------+-----------+------------- + 0x30: Core Buttons | | | + 0x31: Core Buttons | Accelerometer | | + 0x32: Core Buttons | | | 8 bytes + 0x33: Core Buttons | Accelerometer | 12 bytes | + 0x34: Core Buttons | | | 19 bytes + 0x35: Core Buttons | Accelerometer | | 16 bytes + 0x36: Core Buttons | | 10 bytes | 9 bytes + 0x37: Core Buttons | Accelerometer | 10 bytes | 6 bytes + ?? 0x38: Core Buttons and Accelerometer with 16 IR bytes ?? + 0x3d: | | | 21 bytes + + 0x3e / 0x3f: Interleaved Core Buttons and Accelerometer with 16/36 IR bytes + + */ + + if (wiiremote->isIRSensorEnabled) + { + if (wiiremote->isExpansionPortEnabled) + { + cmd[2] = 0x36; // Buttons, 10 IR Bytes, 9 Extension Bytes + wiiremote->wiiIRMode = kWiiIRModeBasic; + } + else + { + cmd[2] = 0x33; // Buttons, Accelerometer, and 12 IR Bytes. + wiiremote->wiiIRMode = kWiiIRModeExtended; + } + + // Set IR Mode + writeData(wiiremote, (darr){ wiiremote->wiiIRMode }, 0x04B00033, 1); + usleep(kWait); // wait 10ms + } + else + { + if (wiiremote->isExpansionPortEnabled) + { + cmd[2] = 0x34; // Buttons, 19 Extension Bytes + } + else + { + cmd[2] = 0x30; // Buttons + } + } + + if (wiiremote->isMotionSensorEnabled) cmd[2] |= 0x01; // Add Accelerometer + + usleep(kWait); // wait 10ms + result = sendCommand(wiiremote, cmd, 3); + + return(result); +} + +//-------------------------------------------------------------------------------------------- + +Boolean wiiremote_motionsensor(WiiRemoteRef wiiremote, Boolean enabled) +{ + wiiremote->isMotionSensorEnabled = enabled; + return requestUpdates(wiiremote); +} + +Boolean wiiremote_vibration(WiiRemoteRef wiiremote, Boolean enabled) +{ + + wiiremote->isVibrationEnabled = enabled; + return requestUpdates(wiiremote); +} + +Boolean wiiremote_led(WiiRemoteRef wiiremote, Boolean enabled1, Boolean enabled2, Boolean enabled3, Boolean enabled4) +{ + unsigned char cmd[] = {0x11, 0x00}; + if (wiiremote->isVibrationEnabled) cmd[1] |= 0x01; + if (enabled1) cmd[1] |= 0x10; + if (enabled2) cmd[1] |= 0x20; + if (enabled3) cmd[1] |= 0x40; + if (enabled4) cmd[1] |= 0x80; + + wiiremote->isLED1Illuminated = enabled1; + wiiremote->isLED2Illuminated = enabled2; + wiiremote->isLED3Illuminated = enabled3; + wiiremote->isLED4Illuminated = enabled4; + + return sendCommand(wiiremote, cmd, 2); +} + +Boolean wiiremote_expansion(WiiRemoteRef wiiremote, Boolean enabled) +{ + wiiremote->isExpansionPortEnabled = enabled; + if (wiiremote->isExpansionPortAttached == false) + { + wiiremote->isExpansionPortEnabled = false; + } + else + { + readData(wiiremote, 0x04A40020, 16); //get calbdata + } + + return requestUpdates(wiiremote); +} + +Boolean wiiremote_irsensor(WiiRemoteRef wiiremote, Boolean enabled) +{ + Boolean ret; + + wiiremote->isIRSensorEnabled = enabled; + + // ir enable 1 + unsigned char cmd[] = {0x13, 0x00}; + if (wiiremote->isVibrationEnabled) cmd[1] |= 0x01; + if (wiiremote->isIRSensorEnabled) cmd[1] |= 0x04; + if ((ret = sendCommand(wiiremote, cmd, 2)) == false) + return ret; + usleep(kWait); + + // set register 0x1a (ir enable 2) + unsigned char cmd2[] = {0x1a, 0x00}; + if (enabled) cmd2[1] |= 0x04; + if ((ret = sendCommand(wiiremote, cmd2, 2)) == false) + return ret; + usleep(kWait); + + if(enabled) + { + // based on marcan's method, found on wiili wiki: + // tweaked to include some aspects of cliff's setup procedure in the hopes + // of it actually turning on 100% of the time (was seeing 30-40% failure rate before) + // the sleeps help it it seems + usleep(kWait); + if ((ret = writeData(wiiremote, (darr){0x01}, 0x04B00030, 1)) == false) return ret; + usleep(kWait); + if ((ret = writeData(wiiremote, (darr){0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0xC0}, 0x04B00000, 9)) == false) return ret; + usleep(kWait); + if ((ret = writeData(wiiremote, (darr){0x40, 0x00}, 0x04B0001A, 2)) == false) return ret; + usleep(kWait); + if ((ret = writeData(wiiremote, (darr){0x08}, 0x04B00030, 1)) == false) return ret; + usleep(kWait); + + requestUpdates(wiiremote); + } + else + { + // probably should do some writes to power down the camera, save battery + // but don't know how yet. + + ret = wiiremote_motionsensor(wiiremote, wiiremote->isMotionSensorEnabled); + ret = wiiremote_vibration(wiiremote, wiiremote->isVibrationEnabled); + ret = wiiremote_expansion(wiiremote, wiiremote->isExpansionPortEnabled); + } + + return ret; +} + +Boolean wiiremote_getstatus(WiiRemoteRef wiiremote) +{ + unsigned char cmd[] = {0x15, 0x00}; + return sendCommand(wiiremote, cmd, 2); +} + + diff --git a/aka.wiiremote/wiiremote.h b/aka.wiiremote/wiiremote.h new file mode 100644 index 0000000..4a03f09 --- /dev/null +++ b/aka.wiiremote/wiiremote.h @@ -0,0 +1,175 @@ +// wiiremote.h +// Copyright by Masayuki Akamatsu +// Based on "DarwiinRemote" by Hiroaki Kimura + +#include +#include +#include +#include +#include + +// Macros for PD for compability with Max macros +#ifdef PD +#define SETSYM SETSYMBOL +#define SETLONG SETFLOAT +#endif + +typedef unsigned char WiiIRModeType; +enum { + kWiiIRModeBasic = 0x01, + kWiiIRModeExtended = 0x03, + kWiiIRModeFull = 0x05 +}; + +typedef struct { + int x, y, s; +} IRData; + +typedef struct { + unsigned char accX_zero, accY_zero, accZ_zero, accX_1g, accY_1g, accZ_1g; +} WiiAccCalibData; + +typedef struct { + unsigned char x_min, x_max, x_center, y_min, y_max, y_center; +} WiiJoyStickCalibData; + +typedef UInt16 WiiButtonType; +enum { + WiiRemoteAButton, + WiiRemoteBButton, + WiiRemoteOneButton, + WiiRemoteTwoButton, + WiiRemoteMinusButton, + WiiRemoteHomeButton, + WiiRemotePlusButton, + WiiRemoteUpButton, + WiiRemoteDownButton, + WiiRemoteLeftButton, + WiiRemoteRightButton, + + WiiNunchukZButton, + WiiNunchukCButton, + + WiiClassicControllerXButton, + WiiClassicControllerYButton, + WiiClassicControllerAButton, + WiiClassicControllerBButton, + WiiClassicControllerLButton, + WiiClassicControllerRButton, + WiiClassicControllerZLButton, + WiiClassicControllerZRButton, + WiiClassicControllerUpButton, + WiiClassicControllerDownButton, + WiiClassicControllerLeftButton, + WiiClassicControllerRightButton, + WiiClassicControllerMinusButton, + WiiClassicControllerHomeButton, + WiiClassicControllerPlusButton +}; + +typedef UInt16 WiiExpansionPortType; +enum{ + WiiExpNotAttached, + WiiNunchuk, + WiiClassicController +}; + +typedef UInt16 WiiAccelerationSensorType; +enum{ + WiiRemoteAccelerationSensor, + WiiNunchukAccelerationSensor +}; + + +typedef UInt16 WiiJoyStickType; +enum{ + WiiNunchukJoyStick, + WiiClassicControllerLeftJoyStick, + WiiClassicControllerRightJoyStick +}; + + +typedef struct _WiiRemoteRec +{ + IOBluetoothDeviceInquiryRef inquiry; + IOBluetoothDeviceRef device; + IOBluetoothL2CAPChannelRef ichan; + IOBluetoothL2CAPChannelRef cchan; + + CFStringRef address; + + unsigned char accX; + unsigned char accY; + unsigned char accZ; + unsigned short buttonData; + + float lowZ; + float lowX; + int orientation; + int leftPoint; // is point 0 or 1 on the left. -1 when not tracking. + + float posX; + float posY; + float angle; + Boolean tracking; + + WiiExpansionPortType expType; + WiiAccCalibData wiiCalibData, nunchukCalibData; + WiiJoyStickCalibData nunchukJoyStickCalibData; + WiiIRModeType wiiIRMode; + IRData irData[4]; + double batteryLevel; + + Boolean readingRegister; + Boolean isMotionSensorEnabled; + Boolean isIRSensorEnabled; + Boolean isVibrationEnabled; + Boolean isExpansionPortEnabled; + Boolean initExpPort; + Boolean isLED1Illuminated; + Boolean isLED2Illuminated; + Boolean isLED3Illuminated; + Boolean isLED4Illuminated; + Boolean isExtraOutputEnabled; + + Boolean isExpansionPortAttached; + + IOBluetoothUserNotificationRef disconnectNotification; + + //nunchuk + unsigned char nStickX; + unsigned char nStickY; + unsigned char nAccX; + unsigned char nAccY; + unsigned char nAccZ; + unsigned char nButtonData; + + float nLowZ; + float nLowX; + int nOrientation; + + //classic controller + unsigned short cButtonData; + unsigned char cStickX1; + unsigned char cStickY1; + unsigned char cStickX2; + unsigned char cStickY2; + unsigned char cAnalogL; + unsigned char cAnalogR; + +} WiiRemoteRec, *WiiRemoteRef; + +void wiiremote_init(WiiRemoteRef wiiremote); +Boolean wiiremote_isconnected(WiiRemoteRef wiiremote); +Boolean wiiremote_search(WiiRemoteRef wiiremote, char *address); +Boolean wiiremote_stopsearch(WiiRemoteRef wiiremote); +Boolean wiiremote_connect(WiiRemoteRef wiiremote); +Boolean wiiremote_disconnect(WiiRemoteRef wiiremote); +void wiiremote_getaddress(WiiRemoteRef wiiremote, char *address); +Boolean wiiremote_motionsensor(WiiRemoteRef wiiremote, Boolean enabled); +Boolean wiiremote_irsensor(WiiRemoteRef wiiremote, Boolean enabled); +Boolean wiiremote_vibration(WiiRemoteRef wiiremote, Boolean enabled); +Boolean wiiremote_led(WiiRemoteRef wiiremote, Boolean enabled1, Boolean enabled2, Boolean enabled3, Boolean enabled4); +Boolean wiiremote_expansion(WiiRemoteRef wiiremote, Boolean enabled); +Boolean wiiremote_getstatus(WiiRemoteRef wiiremote); + -- cgit v1.2.1 From b68834346483649aee638c4cf749d124097d6361 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Mon, 10 Mar 2008 21:51:41 +0000 Subject: moved wiiremote to aka.wiiremote to reflect the name of the Max/MSP object. This is a direct port, so it makes sense to have the same name. svn path=/trunk/externals/io/; revision=9552 --- aka.wiiremote/aka.wiiremote-help.pd | 80 +++++++++++++++++++++++++++++++++++++ aka.wiiremote/wiiremote-help.pd | 80 ------------------------------------- 2 files changed, 80 insertions(+), 80 deletions(-) create mode 100644 aka.wiiremote/aka.wiiremote-help.pd delete mode 100644 aka.wiiremote/wiiremote-help.pd (limited to 'aka.wiiremote') diff --git a/aka.wiiremote/aka.wiiremote-help.pd b/aka.wiiremote/aka.wiiremote-help.pd new file mode 100644 index 0000000..5c8f610 --- /dev/null +++ b/aka.wiiremote/aka.wiiremote-help.pd @@ -0,0 +1,80 @@ +#N canvas 287 96 744 626 10; +#X msg 128 207 connect; +#X msg 141 228 disconnect; +#X obj 218 203 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X obj 294 202 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X obj 127 285 metro 100; +#X obj 127 264 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X msg 89 283 bang; +#X text 49 49 - Use the Bluetooth Setup Assistant to setup the WiiRemote +with your computer (only required for the first use).; +#X text 49 79 - Press the "Sync" button on the WiiRemote \, four LEDs +will start blinking.; +#X text 49 109 - Click on the [connect( message \, the LEDs will stop +blinking once its connected; +#X text 49 139 - Start the [metro] to get updates from [wiiremote] +; +#X obj 399 526 pddp/print; +#X obj 354 556 pddp/print; +#X obj 354 410 route remote; +#X msg 503 290 getbattery; +#X msg 503 310 getled; +#X msg 503 330 getexpansion; +#X obj 489 431 print RIGHT; +#X obj 253 430 print LEFT; +#X obj 354 476 route motion buttons ir; +#X obj 444 497 pddp/print; +#X msg 294 224 ir \$1; +#X msg 218 225 motion \$1; +#X obj 344 202 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X msg 344 224 vibration \$1; +#X obj 434 202 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X msg 434 224 expansion \$1; +#X obj 524 202 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X msg 524 223 extraoutput \$1; +#N canvas 254 342 450 300 address 0; +#X obj 176 252 outlet; +#X msg 206 126 getaddress; +#X msg 176 72 address 00-1e-35-4c-e6-f1; +#X connect 1 0 0 0; +#X connect 2 0 0 0; +#X restore 25 462 pd address; +#X msg 503 352 getaddress; +#X obj 631 536 dac~; +#X obj 632 408 pddp/dsp; +#X obj 640 500 osc~ 100; +#X obj 303 388 wiiremote 00-1e-35-4c-e6-f1; +#X connect 0 0 34 0; +#X connect 1 0 34 0; +#X connect 2 0 22 0; +#X connect 3 0 21 0; +#X connect 4 0 34 0; +#X connect 5 0 4 0; +#X connect 6 0 34 0; +#X connect 13 0 19 0; +#X connect 13 1 17 0; +#X connect 14 0 34 0; +#X connect 15 0 34 0; +#X connect 16 0 34 0; +#X connect 19 0 12 0; +#X connect 19 1 11 0; +#X connect 19 2 20 0; +#X connect 21 0 34 0; +#X connect 22 0 34 0; +#X connect 23 0 24 0; +#X connect 24 0 34 0; +#X connect 25 0 26 0; +#X connect 26 0 34 0; +#X connect 27 0 28 0; +#X connect 28 0 34 0; +#X connect 30 0 34 0; +#X connect 33 0 31 0; +#X connect 33 0 31 1; +#X connect 34 0 18 0; +#X connect 34 1 13 0; diff --git a/aka.wiiremote/wiiremote-help.pd b/aka.wiiremote/wiiremote-help.pd deleted file mode 100644 index 5c8f610..0000000 --- a/aka.wiiremote/wiiremote-help.pd +++ /dev/null @@ -1,80 +0,0 @@ -#N canvas 287 96 744 626 10; -#X msg 128 207 connect; -#X msg 141 228 disconnect; -#X obj 218 203 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 -1; -#X obj 294 202 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 -1; -#X obj 127 285 metro 100; -#X obj 127 264 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 -1; -#X msg 89 283 bang; -#X text 49 49 - Use the Bluetooth Setup Assistant to setup the WiiRemote -with your computer (only required for the first use).; -#X text 49 79 - Press the "Sync" button on the WiiRemote \, four LEDs -will start blinking.; -#X text 49 109 - Click on the [connect( message \, the LEDs will stop -blinking once its connected; -#X text 49 139 - Start the [metro] to get updates from [wiiremote] -; -#X obj 399 526 pddp/print; -#X obj 354 556 pddp/print; -#X obj 354 410 route remote; -#X msg 503 290 getbattery; -#X msg 503 310 getled; -#X msg 503 330 getexpansion; -#X obj 489 431 print RIGHT; -#X obj 253 430 print LEFT; -#X obj 354 476 route motion buttons ir; -#X obj 444 497 pddp/print; -#X msg 294 224 ir \$1; -#X msg 218 225 motion \$1; -#X obj 344 202 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 -1; -#X msg 344 224 vibration \$1; -#X obj 434 202 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 -1; -#X msg 434 224 expansion \$1; -#X obj 524 202 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 -1; -#X msg 524 223 extraoutput \$1; -#N canvas 254 342 450 300 address 0; -#X obj 176 252 outlet; -#X msg 206 126 getaddress; -#X msg 176 72 address 00-1e-35-4c-e6-f1; -#X connect 1 0 0 0; -#X connect 2 0 0 0; -#X restore 25 462 pd address; -#X msg 503 352 getaddress; -#X obj 631 536 dac~; -#X obj 632 408 pddp/dsp; -#X obj 640 500 osc~ 100; -#X obj 303 388 wiiremote 00-1e-35-4c-e6-f1; -#X connect 0 0 34 0; -#X connect 1 0 34 0; -#X connect 2 0 22 0; -#X connect 3 0 21 0; -#X connect 4 0 34 0; -#X connect 5 0 4 0; -#X connect 6 0 34 0; -#X connect 13 0 19 0; -#X connect 13 1 17 0; -#X connect 14 0 34 0; -#X connect 15 0 34 0; -#X connect 16 0 34 0; -#X connect 19 0 12 0; -#X connect 19 1 11 0; -#X connect 19 2 20 0; -#X connect 21 0 34 0; -#X connect 22 0 34 0; -#X connect 23 0 24 0; -#X connect 24 0 34 0; -#X connect 25 0 26 0; -#X connect 26 0 34 0; -#X connect 27 0 28 0; -#X connect 28 0 34 0; -#X connect 30 0 34 0; -#X connect 33 0 31 0; -#X connect 33 0 31 1; -#X connect 34 0 18 0; -#X connect 34 1 13 0; -- cgit v1.2.1 From eb95f74725288feef6a214fe754a966bcbf7311e Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Mon, 10 Mar 2008 21:52:30 +0000 Subject: changed object names to reflect name change svn path=/trunk/externals/io/; revision=9553 --- aka.wiiremote/aka.wiiremote-help.pd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'aka.wiiremote') diff --git a/aka.wiiremote/aka.wiiremote-help.pd b/aka.wiiremote/aka.wiiremote-help.pd index 5c8f610..4c32d94 100644 --- a/aka.wiiremote/aka.wiiremote-help.pd +++ b/aka.wiiremote/aka.wiiremote-help.pd @@ -15,7 +15,7 @@ with your computer (only required for the first use).; will start blinking.; #X text 49 109 - Click on the [connect( message \, the LEDs will stop blinking once its connected; -#X text 49 139 - Start the [metro] to get updates from [wiiremote] +#X text 49 139 - Start the [metro] to get updates from [aka.wiiremote] ; #X obj 399 526 pddp/print; #X obj 354 556 pddp/print; @@ -49,7 +49,7 @@ blinking once its connected; #X obj 631 536 dac~; #X obj 632 408 pddp/dsp; #X obj 640 500 osc~ 100; -#X obj 303 388 wiiremote 00-1e-35-4c-e6-f1; +#X obj 303 388 aka.wiiremote 00-1e-35-4c-e6-f1; #X connect 0 0 34 0; #X connect 1 0 34 0; #X connect 2 0 22 0; -- cgit v1.2.1 From 430e10e0813bc4a39f155640fdf70a76a03fb191 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 27 May 2008 19:10:02 +0000 Subject: first attempt at adding a CFRunLoop in order to get the events svn path=/trunk/externals/io/; revision=9929 --- aka.wiiremote/aka.wiiremote-help.pd | 33 +++++++++--------- aka.wiiremote/aka.wiiremote.c | 69 +++++++++++++++++++++++++------------ 2 files changed, 64 insertions(+), 38 deletions(-) (limited to 'aka.wiiremote') diff --git a/aka.wiiremote/aka.wiiremote-help.pd b/aka.wiiremote/aka.wiiremote-help.pd index 4c32d94..83def15 100644 --- a/aka.wiiremote/aka.wiiremote-help.pd +++ b/aka.wiiremote/aka.wiiremote-help.pd @@ -49,32 +49,33 @@ blinking once its connected; #X obj 631 536 dac~; #X obj 632 408 pddp/dsp; #X obj 640 500 osc~ 100; -#X obj 303 388 aka.wiiremote 00-1e-35-4c-e6-f1; -#X connect 0 0 34 0; -#X connect 1 0 34 0; +#X obj 154 513 aka.wiiremote; +#X obj 303 388 aka.wiiremote; +#X connect 0 0 35 0; +#X connect 1 0 35 0; #X connect 2 0 22 0; #X connect 3 0 21 0; -#X connect 4 0 34 0; +#X connect 4 0 35 0; #X connect 5 0 4 0; -#X connect 6 0 34 0; +#X connect 6 0 35 0; #X connect 13 0 19 0; #X connect 13 1 17 0; -#X connect 14 0 34 0; -#X connect 15 0 34 0; -#X connect 16 0 34 0; +#X connect 14 0 35 0; +#X connect 15 0 35 0; +#X connect 16 0 35 0; #X connect 19 0 12 0; #X connect 19 1 11 0; #X connect 19 2 20 0; -#X connect 21 0 34 0; -#X connect 22 0 34 0; +#X connect 21 0 35 0; +#X connect 22 0 35 0; #X connect 23 0 24 0; -#X connect 24 0 34 0; +#X connect 24 0 35 0; #X connect 25 0 26 0; -#X connect 26 0 34 0; +#X connect 26 0 35 0; #X connect 27 0 28 0; -#X connect 28 0 34 0; -#X connect 30 0 34 0; +#X connect 28 0 35 0; +#X connect 30 0 35 0; #X connect 33 0 31 0; #X connect 33 0 31 1; -#X connect 34 0 18 0; -#X connect 34 1 13 0; +#X connect 35 0 18 0; +#X connect 35 1 13 0; diff --git a/aka.wiiremote/aka.wiiremote.c b/aka.wiiremote/aka.wiiremote.c index 767d737..d8b12cb 100644 --- a/aka.wiiremote/aka.wiiremote.c +++ b/aka.wiiremote/aka.wiiremote.c @@ -15,9 +15,12 @@ #define method t_method //#define addbang(x) class_addbang(wiiremote_class, (x)) //#define addmess(x) class_addmessage(class_wiiremote, (x)) -static t_class *wiiremote_class; +// a CFRunLoop is needed for Pd since the 'pd' process is not a Carbon app +static t_class *akawiiremote_class; #else /* Max */ #include "ext.h" + +void *akawiiremote_class; // the number of instance of this object #endif /* PD */ #include "wiiremote.h" @@ -45,7 +48,11 @@ typedef struct _akawiiremote void *dataOut; } t_akawiiremote; -void *akawiiremote_class; // the number of instance of this object +#ifdef PD +static IONotificationPortRef gNotifyPort; +static io_iterator_t gAddedIter; +static CFRunLoopRef gRunLoop; +#endif void akawiiremote_bang(t_akawiiremote *x); void akawiiremote_address(t_akawiiremote *x, t_symbol *s); @@ -74,7 +81,7 @@ char nunchukStr[] = "nunchuk"; char classicStr[] = "classic"; #ifdef PD -void wiiremote_setup() +void setup_aka0x2ewiiremote() #else /* Max */ void main() #endif /* PD */ @@ -101,30 +108,30 @@ void main() #ifdef PD post("\tPd port by Hans-Christoph Steiner"); - wiiremote_class = class_new(gensym("wiiremote"), + akawiiremote_class = class_new(gensym("aka.wiiremote"), (t_newmethod)akawiiremote_new, (t_method)akawiiremote_free, sizeof(t_akawiiremote), CLASS_DEFAULT, A_GIMME,0); - class_addbang(wiiremote_class,(t_method)akawiiremote_bang); - class_addmethod(wiiremote_class,(t_method)akawiiremote_address,gensym("address"),A_DEFSYMBOL, 0); - class_addmethod(wiiremote_class,(t_method)akawiiremote_connect,gensym("connect"),0); - class_addmethod(wiiremote_class,(t_method)akawiiremote_disconnect,gensym("disconnect"),0); - class_addmethod(wiiremote_class,(t_method)akawiiremote_motionsensor,gensym("motion"), A_DEFFLOAT, 0); - class_addmethod(wiiremote_class,(t_method)akawiiremote_irsensor,gensym("ir"), A_DEFFLOAT, 0); - class_addmethod(wiiremote_class,(t_method)akawiiremote_vibration,gensym("vibration"), A_DEFFLOAT, 0); - class_addmethod(wiiremote_class,(t_method)akawiiremote_led,gensym("led"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); - class_addmethod(wiiremote_class,(t_method)akawiiremote_expansion,gensym("expansion"), A_DEFFLOAT, 0); - class_addmethod(wiiremote_class,(t_method)akawiiremote_expansion,gensym("nunchuk"), A_DEFFLOAT, 0); - class_addmethod(wiiremote_class,(t_method)akawiiremote_extraoutput,gensym("extraoutput"), A_DEFFLOAT, 0); // B7 - - class_addmethod(wiiremote_class,(t_method)akawiiremote_getbattery,gensym("getbattery"),0); - class_addmethod(wiiremote_class,(t_method)akawiiremote_getexpansion,gensym("getexpansion"),0); - class_addmethod(wiiremote_class,(t_method)akawiiremote_getled,gensym("getled"),0); - class_addmethod(wiiremote_class,(t_method)akawiiremote_getaddress,gensym("getaddress"),0); - class_addmethod(wiiremote_class,(t_method)akawiiremote_getcalibration,gensym("getcalibration"), 0); + class_addbang(akawiiremote_class,(t_method)akawiiremote_bang); + class_addmethod(akawiiremote_class,(t_method)akawiiremote_address,gensym("address"),A_DEFSYMBOL, 0); + class_addmethod(akawiiremote_class,(t_method)akawiiremote_connect,gensym("connect"),0); + class_addmethod(akawiiremote_class,(t_method)akawiiremote_disconnect,gensym("disconnect"),0); + class_addmethod(akawiiremote_class,(t_method)akawiiremote_motionsensor,gensym("motion"), A_DEFFLOAT, 0); + class_addmethod(akawiiremote_class,(t_method)akawiiremote_irsensor,gensym("ir"), A_DEFFLOAT, 0); + class_addmethod(akawiiremote_class,(t_method)akawiiremote_vibration,gensym("vibration"), A_DEFFLOAT, 0); + class_addmethod(akawiiremote_class,(t_method)akawiiremote_led,gensym("led"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addmethod(akawiiremote_class,(t_method)akawiiremote_expansion,gensym("expansion"), A_DEFFLOAT, 0); + class_addmethod(akawiiremote_class,(t_method)akawiiremote_expansion,gensym("nunchuk"), A_DEFFLOAT, 0); + class_addmethod(akawiiremote_class,(t_method)akawiiremote_extraoutput,gensym("extraoutput"), A_DEFFLOAT, 0); // B7 + + class_addmethod(akawiiremote_class,(t_method)akawiiremote_getbattery,gensym("getbattery"),0); + class_addmethod(akawiiremote_class,(t_method)akawiiremote_getexpansion,gensym("getexpansion"),0); + class_addmethod(akawiiremote_class,(t_method)akawiiremote_getled,gensym("getled"),0); + class_addmethod(akawiiremote_class,(t_method)akawiiremote_getaddress,gensym("getaddress"),0); + class_addmethod(akawiiremote_class,(t_method)akawiiremote_getcalibration,gensym("getcalibration"), 0); #else /* Max */ setup((t_messlist **)&akawiiremote_class, (method)akawiiremote_new, (method)akawiiremote_free, (short)sizeof(t_akawiiremote), 0L, A_GIMME, 0); @@ -578,7 +585,7 @@ void akawiiremote_assist(t_akawiiremote *x, void *b, long m, long a, char *s) void *akawiiremote_new(t_symbol *s, short ac, t_atom *av) { #ifdef PD - t_akawiiremote *x = (t_akawiiremote *)pd_new(wiiremote_class); + t_akawiiremote *x = (t_akawiiremote *)pd_new(akawiiremote_class); t_symbol *first_argument; x->statusOut = outlet_new(&x->x_obj, 0); @@ -588,6 +595,24 @@ void *akawiiremote_new(t_symbol *s, short ac, t_atom *av) first_argument = atom_getsymbolarg(0, ac, av); if(first_argument != &s_) atom_string(av, x->address, MAXPDSTRING-1); + + IOReturn result = kIOReturnSuccess; + mach_port_t masterPort = NULL; + result = IOMasterPort (bootstrap_port, &masterPort); + if (kIOReturnSuccess != result) + pd_error("IOMasterPort error with bootstrap_port, error %d", result); + else + { + // Create a notification port and add its run loop event source to our run loop + // This is how async notifications get set up. + CFRunLoopSourceRef runLoopSource; + + gNotifyPort = IONotificationPortCreate(masterPort); + runLoopSource = IONotificationPortGetRunLoopSource(gNotifyPort); + + gRunLoop = CFRunLoopGetCurrent(); + CFRunLoopAddSource(gRunLoop, runLoopSource, kCFRunLoopDefaultMode); + } #else /* Max */ t_akawiiremote *x; -- cgit v1.2.1 From dc185c66b8b0648fe068fdbeaedabc0e24cb4e4b Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Wed, 28 May 2008 10:49:34 +0000 Subject: changed classname to akawiiremote so that I don't have to deal with the hexloader svn path=/trunk/externals/io/; revision=9931 --- aka.wiiremote/aka.wiiremote-help.pd | 33 ++++++++++++++++----------------- aka.wiiremote/aka.wiiremote.c | 8 ++++---- 2 files changed, 20 insertions(+), 21 deletions(-) (limited to 'aka.wiiremote') diff --git a/aka.wiiremote/aka.wiiremote-help.pd b/aka.wiiremote/aka.wiiremote-help.pd index 83def15..c3ae89a 100644 --- a/aka.wiiremote/aka.wiiremote-help.pd +++ b/aka.wiiremote/aka.wiiremote-help.pd @@ -49,33 +49,32 @@ blinking once its connected; #X obj 631 536 dac~; #X obj 632 408 pddp/dsp; #X obj 640 500 osc~ 100; -#X obj 154 513 aka.wiiremote; -#X obj 303 388 aka.wiiremote; -#X connect 0 0 35 0; -#X connect 1 0 35 0; +#X obj 303 388 akawiiremote; +#X connect 0 0 34 0; +#X connect 1 0 34 0; #X connect 2 0 22 0; #X connect 3 0 21 0; -#X connect 4 0 35 0; +#X connect 4 0 34 0; #X connect 5 0 4 0; -#X connect 6 0 35 0; +#X connect 6 0 34 0; #X connect 13 0 19 0; #X connect 13 1 17 0; -#X connect 14 0 35 0; -#X connect 15 0 35 0; -#X connect 16 0 35 0; +#X connect 14 0 34 0; +#X connect 15 0 34 0; +#X connect 16 0 34 0; #X connect 19 0 12 0; #X connect 19 1 11 0; #X connect 19 2 20 0; -#X connect 21 0 35 0; -#X connect 22 0 35 0; +#X connect 21 0 34 0; +#X connect 22 0 34 0; #X connect 23 0 24 0; -#X connect 24 0 35 0; +#X connect 24 0 34 0; #X connect 25 0 26 0; -#X connect 26 0 35 0; +#X connect 26 0 34 0; #X connect 27 0 28 0; -#X connect 28 0 35 0; -#X connect 30 0 35 0; +#X connect 28 0 34 0; +#X connect 30 0 34 0; #X connect 33 0 31 0; #X connect 33 0 31 1; -#X connect 35 0 18 0; -#X connect 35 1 13 0; +#X connect 34 0 18 0; +#X connect 34 1 13 0; diff --git a/aka.wiiremote/aka.wiiremote.c b/aka.wiiremote/aka.wiiremote.c index d8b12cb..0831f44 100644 --- a/aka.wiiremote/aka.wiiremote.c +++ b/aka.wiiremote/aka.wiiremote.c @@ -81,7 +81,7 @@ char nunchukStr[] = "nunchuk"; char classicStr[] = "classic"; #ifdef PD -void setup_aka0x2ewiiremote() +void akawiiremote_setup() #else /* Max */ void main() #endif /* PD */ @@ -108,7 +108,7 @@ void main() #ifdef PD post("\tPd port by Hans-Christoph Steiner"); - akawiiremote_class = class_new(gensym("aka.wiiremote"), + akawiiremote_class = class_new(gensym("akawiiremote"), (t_newmethod)akawiiremote_new, (t_method)akawiiremote_free, sizeof(t_akawiiremote), @@ -597,10 +597,10 @@ void *akawiiremote_new(t_symbol *s, short ac, t_atom *av) atom_string(av, x->address, MAXPDSTRING-1); IOReturn result = kIOReturnSuccess; - mach_port_t masterPort = NULL; + mach_port_t masterPort = (mach_port_t) NULL; result = IOMasterPort (bootstrap_port, &masterPort); if (kIOReturnSuccess != result) - pd_error("IOMasterPort error with bootstrap_port, error %d", result); + pd_error(x, "[akawiiremote] IOMasterPort error with bootstrap_port, error %d", result); else { // Create a notification port and add its run loop event source to our run loop -- cgit v1.2.1 From 7acd17222423c5ac84f3ad21a2ece9a2ef331c5d Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Wed, 28 May 2008 10:54:53 +0000 Subject: moved files to reflect name change to [akawiiremote] svn path=/trunk/externals/io/; revision=9932 --- aka.wiiremote/aka.wiiremote-help.pd | 80 ------------------------------------- aka.wiiremote/akawiiremote-help.pd | 80 +++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 80 deletions(-) delete mode 100644 aka.wiiremote/aka.wiiremote-help.pd create mode 100644 aka.wiiremote/akawiiremote-help.pd (limited to 'aka.wiiremote') diff --git a/aka.wiiremote/aka.wiiremote-help.pd b/aka.wiiremote/aka.wiiremote-help.pd deleted file mode 100644 index c3ae89a..0000000 --- a/aka.wiiremote/aka.wiiremote-help.pd +++ /dev/null @@ -1,80 +0,0 @@ -#N canvas 287 96 744 626 10; -#X msg 128 207 connect; -#X msg 141 228 disconnect; -#X obj 218 203 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 -1; -#X obj 294 202 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 -1; -#X obj 127 285 metro 100; -#X obj 127 264 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 -1; -#X msg 89 283 bang; -#X text 49 49 - Use the Bluetooth Setup Assistant to setup the WiiRemote -with your computer (only required for the first use).; -#X text 49 79 - Press the "Sync" button on the WiiRemote \, four LEDs -will start blinking.; -#X text 49 109 - Click on the [connect( message \, the LEDs will stop -blinking once its connected; -#X text 49 139 - Start the [metro] to get updates from [aka.wiiremote] -; -#X obj 399 526 pddp/print; -#X obj 354 556 pddp/print; -#X obj 354 410 route remote; -#X msg 503 290 getbattery; -#X msg 503 310 getled; -#X msg 503 330 getexpansion; -#X obj 489 431 print RIGHT; -#X obj 253 430 print LEFT; -#X obj 354 476 route motion buttons ir; -#X obj 444 497 pddp/print; -#X msg 294 224 ir \$1; -#X msg 218 225 motion \$1; -#X obj 344 202 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 -1; -#X msg 344 224 vibration \$1; -#X obj 434 202 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 -1; -#X msg 434 224 expansion \$1; -#X obj 524 202 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 -1; -#X msg 524 223 extraoutput \$1; -#N canvas 254 342 450 300 address 0; -#X obj 176 252 outlet; -#X msg 206 126 getaddress; -#X msg 176 72 address 00-1e-35-4c-e6-f1; -#X connect 1 0 0 0; -#X connect 2 0 0 0; -#X restore 25 462 pd address; -#X msg 503 352 getaddress; -#X obj 631 536 dac~; -#X obj 632 408 pddp/dsp; -#X obj 640 500 osc~ 100; -#X obj 303 388 akawiiremote; -#X connect 0 0 34 0; -#X connect 1 0 34 0; -#X connect 2 0 22 0; -#X connect 3 0 21 0; -#X connect 4 0 34 0; -#X connect 5 0 4 0; -#X connect 6 0 34 0; -#X connect 13 0 19 0; -#X connect 13 1 17 0; -#X connect 14 0 34 0; -#X connect 15 0 34 0; -#X connect 16 0 34 0; -#X connect 19 0 12 0; -#X connect 19 1 11 0; -#X connect 19 2 20 0; -#X connect 21 0 34 0; -#X connect 22 0 34 0; -#X connect 23 0 24 0; -#X connect 24 0 34 0; -#X connect 25 0 26 0; -#X connect 26 0 34 0; -#X connect 27 0 28 0; -#X connect 28 0 34 0; -#X connect 30 0 34 0; -#X connect 33 0 31 0; -#X connect 33 0 31 1; -#X connect 34 0 18 0; -#X connect 34 1 13 0; diff --git a/aka.wiiremote/akawiiremote-help.pd b/aka.wiiremote/akawiiremote-help.pd new file mode 100644 index 0000000..c3ae89a --- /dev/null +++ b/aka.wiiremote/akawiiremote-help.pd @@ -0,0 +1,80 @@ +#N canvas 287 96 744 626 10; +#X msg 128 207 connect; +#X msg 141 228 disconnect; +#X obj 218 203 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X obj 294 202 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X obj 127 285 metro 100; +#X obj 127 264 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X msg 89 283 bang; +#X text 49 49 - Use the Bluetooth Setup Assistant to setup the WiiRemote +with your computer (only required for the first use).; +#X text 49 79 - Press the "Sync" button on the WiiRemote \, four LEDs +will start blinking.; +#X text 49 109 - Click on the [connect( message \, the LEDs will stop +blinking once its connected; +#X text 49 139 - Start the [metro] to get updates from [aka.wiiremote] +; +#X obj 399 526 pddp/print; +#X obj 354 556 pddp/print; +#X obj 354 410 route remote; +#X msg 503 290 getbattery; +#X msg 503 310 getled; +#X msg 503 330 getexpansion; +#X obj 489 431 print RIGHT; +#X obj 253 430 print LEFT; +#X obj 354 476 route motion buttons ir; +#X obj 444 497 pddp/print; +#X msg 294 224 ir \$1; +#X msg 218 225 motion \$1; +#X obj 344 202 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X msg 344 224 vibration \$1; +#X obj 434 202 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X msg 434 224 expansion \$1; +#X obj 524 202 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X msg 524 223 extraoutput \$1; +#N canvas 254 342 450 300 address 0; +#X obj 176 252 outlet; +#X msg 206 126 getaddress; +#X msg 176 72 address 00-1e-35-4c-e6-f1; +#X connect 1 0 0 0; +#X connect 2 0 0 0; +#X restore 25 462 pd address; +#X msg 503 352 getaddress; +#X obj 631 536 dac~; +#X obj 632 408 pddp/dsp; +#X obj 640 500 osc~ 100; +#X obj 303 388 akawiiremote; +#X connect 0 0 34 0; +#X connect 1 0 34 0; +#X connect 2 0 22 0; +#X connect 3 0 21 0; +#X connect 4 0 34 0; +#X connect 5 0 4 0; +#X connect 6 0 34 0; +#X connect 13 0 19 0; +#X connect 13 1 17 0; +#X connect 14 0 34 0; +#X connect 15 0 34 0; +#X connect 16 0 34 0; +#X connect 19 0 12 0; +#X connect 19 1 11 0; +#X connect 19 2 20 0; +#X connect 21 0 34 0; +#X connect 22 0 34 0; +#X connect 23 0 24 0; +#X connect 24 0 34 0; +#X connect 25 0 26 0; +#X connect 26 0 34 0; +#X connect 27 0 28 0; +#X connect 28 0 34 0; +#X connect 30 0 34 0; +#X connect 33 0 31 0; +#X connect 33 0 31 1; +#X connect 34 0 18 0; +#X connect 34 1 13 0; -- cgit v1.2.1 From 590fa42a7ca536666dd4c76a7398b011bbd886e0 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 22 Jul 2008 15:04:33 +0000 Subject: added #define BLUETOOTH_VERSION_USE_CURRENT to get rid of "deprecated" warnings based on this bluetooth-dev post: http://lists.apple.com/archives/Bluetooth-dev/2007/Mar/msg00024.html svn path=/trunk/externals/io/; revision=10205 --- aka.wiiremote/wiiremote.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'aka.wiiremote') diff --git a/aka.wiiremote/wiiremote.h b/aka.wiiremote/wiiremote.h index 4a03f09..560e401 100644 --- a/aka.wiiremote/wiiremote.h +++ b/aka.wiiremote/wiiremote.h @@ -2,6 +2,8 @@ // Copyright by Masayuki Akamatsu // Based on "DarwiinRemote" by Hiroaki Kimura +#define BLUETOOTH_VERSION_USE_CURRENT // gets rid of deprecated warnings + #include #include #include -- cgit v1.2.1 From 25dcbfc009a7fbf95a4e2e8788a5cf68d2cdd7b1 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 22 Jul 2008 15:23:12 +0000 Subject: first working version, bangs now get udpated data properly, but the various other messages don't work, like [motion $1(, [ir $1(, etc. To get it working, I used CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true), which runs the CFRunLoop until just one event has been processed. svn path=/trunk/externals/io/; revision=10206 --- aka.wiiremote/aka.wiiremote.c | 32 +++++++------------------------- aka.wiiremote/akawiiremote-help.pd | 2 ++ aka.wiiremote/wiiremote.c | 31 ++++++++++++++++++++++--------- 3 files changed, 31 insertions(+), 34 deletions(-) (limited to 'aka.wiiremote') diff --git a/aka.wiiremote/aka.wiiremote.c b/aka.wiiremote/aka.wiiremote.c index 0831f44..5834b63 100644 --- a/aka.wiiremote/aka.wiiremote.c +++ b/aka.wiiremote/aka.wiiremote.c @@ -10,6 +10,7 @@ #ifdef PD #include "m_pd.h" +#include "m_imp.h" #define SETSYM SETSYMBOL #define SETLONG SETFLOAT #define method t_method @@ -48,12 +49,6 @@ typedef struct _akawiiremote void *dataOut; } t_akawiiremote; -#ifdef PD -static IONotificationPortRef gNotifyPort; -static io_iterator_t gAddedIter; -static CFRunLoopRef gRunLoop; -#endif - void akawiiremote_bang(t_akawiiremote *x); void akawiiremote_address(t_akawiiremote *x, t_symbol *s); void akawiiremote_connect(t_akawiiremote *x); @@ -165,7 +160,9 @@ void akawiiremote_bang(t_akawiiremote *x) if (x->wiiremote->device == nil) return; // do nothing - +#ifdef PD + CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true); +#endif if (x->wiiremote->isExpansionPortAttached && x->wiiremote->isExpansionPortEnabled) { // Classic Controller @@ -544,6 +541,9 @@ void akawiiremote_clock(t_akawiiremote *x) if (x->connected == false && connection == true) // if the device is connected... { +#ifdef PD + CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true); +#endif wiiremote_getstatus(x->wiiremote); x->connected = true; SETLONG(&status, 1); @@ -595,24 +595,6 @@ void *akawiiremote_new(t_symbol *s, short ac, t_atom *av) first_argument = atom_getsymbolarg(0, ac, av); if(first_argument != &s_) atom_string(av, x->address, MAXPDSTRING-1); - - IOReturn result = kIOReturnSuccess; - mach_port_t masterPort = (mach_port_t) NULL; - result = IOMasterPort (bootstrap_port, &masterPort); - if (kIOReturnSuccess != result) - pd_error(x, "[akawiiremote] IOMasterPort error with bootstrap_port, error %d", result); - else - { - // Create a notification port and add its run loop event source to our run loop - // This is how async notifications get set up. - CFRunLoopSourceRef runLoopSource; - - gNotifyPort = IONotificationPortCreate(masterPort); - runLoopSource = IONotificationPortGetRunLoopSource(gNotifyPort); - - gRunLoop = CFRunLoopGetCurrent(); - CFRunLoopAddSource(gRunLoop, runLoopSource, kCFRunLoopDefaultMode); - } #else /* Max */ t_akawiiremote *x; diff --git a/aka.wiiremote/akawiiremote-help.pd b/aka.wiiremote/akawiiremote-help.pd index c3ae89a..b2e85ed 100644 --- a/aka.wiiremote/akawiiremote-help.pd +++ b/aka.wiiremote/akawiiremote-help.pd @@ -50,6 +50,7 @@ blinking once its connected; #X obj 632 408 pddp/dsp; #X obj 640 500 osc~ 100; #X obj 303 388 akawiiremote; +#X obj 334 589 print; #X connect 0 0 34 0; #X connect 1 0 34 0; #X connect 2 0 22 0; @@ -63,6 +64,7 @@ blinking once its connected; #X connect 15 0 34 0; #X connect 16 0 34 0; #X connect 19 0 12 0; +#X connect 19 0 35 0; #X connect 19 1 11 0; #X connect 19 2 20 0; #X connect 21 0 34 0; diff --git a/aka.wiiremote/wiiremote.c b/aka.wiiremote/wiiremote.c index 481085e..92efeb0 100644 --- a/aka.wiiremote/wiiremote.c +++ b/aka.wiiremote/wiiremote.c @@ -19,6 +19,7 @@ typedef unsigned char darr[]; Boolean requestUpdates(WiiRemoteRef wiiremote); void myEventListener(IOBluetoothL2CAPChannelRef channel, void *refCon, IOBluetoothL2CAPChannelEvent *event); +#define DEBUG(x) //-------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------- @@ -73,6 +74,7 @@ void wiiremote_init(WiiRemoteRef wiiremote) Boolean openCChan(WiiRemoteRef wiiremote) { + DEBUG(post("openCChan");); short i; IOReturn ret; @@ -97,6 +99,7 @@ Boolean openCChan(WiiRemoteRef wiiremote) Boolean openIChan(WiiRemoteRef wiiremote) { + DEBUG(post("openCChan");); short i; IOReturn ret; @@ -208,7 +211,7 @@ Boolean readData(WiiRemoteRef wiiremote, unsigned long address, unsigned short l void checkDevice(WiiRemoteRef wiiremote, IOBluetoothDeviceRef device) { - post("checkDevice"); + DEBUG(post("checkDevice");); CFStringRef name; CFStringRef address; @@ -234,20 +237,21 @@ void checkDevice(WiiRemoteRef wiiremote, IOBluetoothDeviceRef device) void myFoundFunc(void *refCon, IOBluetoothDeviceInquiryRef inquiry, IOBluetoothDeviceRef device) { - post("myFoundFunc"); + DEBUG(post("myFoundFunc");); checkDevice((WiiRemoteRef)refCon, device); } void myUpdatedFunc(void *refCon, IOBluetoothDeviceInquiryRef inquiry, IOBluetoothDeviceRef device, uint32_t devicesRemaining) { - post("myUpdatedFunc"); + DEBUG(post("myUpdatedFunc");); checkDevice((WiiRemoteRef)refCon, device); } void myCompleteFunc(void *refCon, IOBluetoothDeviceInquiryRef inquiry, IOReturn error, Boolean aborted) { - post("myCompleteFunc"); + IOReturn ret; + DEBUG(post("myCompleteFunc");); if (aborted) return; // called by stop ;) @@ -256,8 +260,15 @@ void myCompleteFunc(void *refCon, IOBluetoothDeviceInquiryRef inquiry, IOReturn wiiremote_stopsearch((WiiRemoteRef)refCon); return; } +/* + ret = IOBluetoothDeviceInquiryStart(((WiiRemoteRef)refCon)->inquiry); + if (ret != kIOReturnSuccess) + { + wiiremote_stopsearch((WiiRemoteRef)refCon); + } +*/ #ifdef PD - // PD doesn't use the Carbon loop, so we have to manually control it + // PD doesn't use a CFRunLoop, so we have to manually control it CFRunLoopStop( CFRunLoopGetCurrent() ); #endif } @@ -274,7 +285,7 @@ Boolean wiiremote_isconnected(WiiRemoteRef wiiremote) Boolean wiiremote_search(WiiRemoteRef wiiremote, char *address) { - post("wiiremote_search"); + DEBUG(post("wiiremote_search");); IOReturn ret; if (wiiremote->inquiry != nil) @@ -297,14 +308,14 @@ Boolean wiiremote_search(WiiRemoteRef wiiremote, char *address) return false; } #ifdef PD - CFRunLoopRun(); // PD doesn't use the Carbon loop, so we have to manually control it + // PD doesn't use a CFRunLoop, so we have to manually control it + CFRunLoopRun(); #endif return true; } Boolean wiiremote_stopsearch(WiiRemoteRef wiiremote) { - post("wiiremote_stopsearch"); IOReturn ret; if (wiiremote->inquiry == nil) @@ -703,6 +714,7 @@ void handleButtonReport(WiiRemoteRef wiiremote, unsigned char *dp, size_t dataLe void myDataListener(IOBluetoothL2CAPChannelRef channel, void *dataPointer, UInt16 dataLength, void *refCon) { + DEBUG(post("myDataListener");); WiiRemoteRef wiiremote = (WiiRemoteRef)refCon; unsigned char* dp = (unsigned char*)dataPointer; @@ -738,6 +750,7 @@ void handleButtonReport(WiiRemoteRef wiiremote, unsigned char *dp, size_t dataLe void myEventListener(IOBluetoothL2CAPChannelRef channel, void *refCon, IOBluetoothL2CAPChannelEvent *event) { + DEBUG(post("myEventListener");); if (event->eventType == kIOBluetoothL2CAPChannelEventTypeData) { // In thise case: @@ -846,7 +859,7 @@ Boolean wiiremote_connect(WiiRemoteRef wiiremote) Boolean wiiremote_disconnect(WiiRemoteRef wiiremote) { - short i = 0; + short i; if (wiiremote->cchan) { -- cgit v1.2.1 From ef417b58265bc400d687783c341f84c87b5daa09 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 22 Jul 2008 15:30:52 +0000 Subject: removed CFRunLoopRunInMode() in clock function since it doesn't seem to do anything there svn path=/trunk/externals/io/; revision=10207 --- aka.wiiremote/aka.wiiremote.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'aka.wiiremote') diff --git a/aka.wiiremote/aka.wiiremote.c b/aka.wiiremote/aka.wiiremote.c index 5834b63..7a113b6 100644 --- a/aka.wiiremote/aka.wiiremote.c +++ b/aka.wiiremote/aka.wiiremote.c @@ -538,12 +538,9 @@ void akawiiremote_clock(t_akawiiremote *x) t_atom status; connection = wiiremote_isconnected(x->wiiremote); - + if (x->connected == false && connection == true) // if the device is connected... { -#ifdef PD - CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true); -#endif wiiremote_getstatus(x->wiiremote); x->connected = true; SETLONG(&status, 1); -- cgit v1.2.1