diff options
author | IOhannes m zmölnig <zmoelnig@users.sourceforge.net> | 2009-10-05 16:03:46 +0000 |
---|---|---|
committer | IOhannes m zmölnig <zmoelnig@users.sourceforge.net> | 2009-10-05 16:03:46 +0000 |
commit | 61412df161175b6cc5537e959afeb8cb231ef5c5 (patch) | |
tree | c451a8c30cdac9177990e338dc63f113e88097bd | |
parent | 8013e5e7a0574db98e391139988a3eb16b8e475b (diff) |
breaking API of [wiimote]: all data is sent through a single outlet that has to be routed
svn path=/trunk/externals/hardware/wiimote/; revision=12528
-rw-r--r-- | wiimote-help.pd | 44 | ||||
-rw-r--r-- | wiimote.c | 757 | ||||
-rw-r--r-- | wiimote.pd | 41 | ||||
-rw-r--r-- | wiiremote.c | 805 |
4 files changed, 501 insertions, 1146 deletions
diff --git a/wiimote-help.pd b/wiimote-help.pd index 3beb620..43eae98 100644 --- a/wiimote-help.pd +++ b/wiimote-help.pd @@ -72,7 +72,7 @@ case. The total acceleration is given by:; #X connect 24 0 2 0; #X connect 24 1 2 1; #X connect 24 2 2 2; -#X restore 130 475 pd \$0-accelerometer-stuff; +#X restore 134 485 pd \$0-accelerometer-stuff; #N canvas 0 0 652 563 \$0-IR-stuff 0; #X obj 134 18 inlet; #X obj 122 510 pointer; @@ -125,7 +125,7 @@ case. The total acceleration is given by:; #X connect 21 1 22 1; #X connect 23 0 24 0; #X connect 24 0 20 0; -#X restore 139 453 pd \$0-IR-stuff; +#X restore 146 463 pd \$0-IR-stuff; #X msg 408 356 setLED \$1; #X obj 408 307 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; @@ -226,7 +226,7 @@ You must specifically enable each reporting mode:; #X connect 9 1 11 0; #X connect 9 2 10 0; #X connect 15 0 1 0; -#X restore 148 430 pd \$0-nunchuck-stuff; +#X restore 158 444 pd \$0-nunchuck-stuff; #X obj 579 406 cnv 15 275 230 empty empty Nunchuk: 10 15 0 14 -228992 -355 0; #X floatatom 756 470 7 0 0 1 _X #0-nc-accX-set #0-nc-accX; @@ -291,7 +291,7 @@ empty -2 -8 0 10 -225280 -1 -1 0 1; #X connect 0 0 1 0; #X connect 1 0 2 0; #X connect 1 1 3 0; -#X restore 122 497 pd \$0-button-stuff; +#X restore 122 507 pd \$0-button-stuff; #X text 783 5 Buttons:; #N canvas 185 133 481 416 NC-data 0; #X scalar NC-stick 130 133 \;; @@ -299,15 +299,33 @@ empty -2 -8 0 10 -225280 -1 -1 0 1; #X restore 681 534 pd NC-data; #X obj 161 615 print; #X msg 36 69 connect 00:1E:35:1D:0E:15; +#N canvas 0 0 970 429 router 0; +#X obj 104 38 inlet; +#X obj 104 207 outlet button; +#X obj 232 277 outlet IR; +#X obj 378 267 outlet nunchuck-buttons; +#X obj 449 287 outlet nunchuck-acceleration; +#X obj 520 307 outlet nunchuck-stick; +#X obj 168 247 outlet acceleration; +#X obj 104 169 route button acceleration ir; +#X obj 378 245 route button acceleration stick; +#X obj 378 204 route nunchuck motionplus; +#X text 392 161 extensions; +#X text 168 138 core; +#X connect 0 0 7 0; +#X connect 7 0 1 0; +#X connect 7 1 6 0; +#X connect 7 2 2 0; +#X connect 7 3 9 0; +#X connect 8 0 3 0; +#X connect 8 1 4 0; +#X connect 8 2 5 0; +#X connect 9 0 8 0; +#X restore 122 423 pd router; #X connect 0 0 3 0; #X connect 1 0 4 0; #X connect 2 0 3 0; -#X connect 3 0 57 0; -#X connect 3 1 9 0; -#X connect 3 2 10 0; -#X connect 3 3 27 0; -#X connect 3 4 27 1; -#X connect 3 5 27 2; +#X connect 3 0 62 0; #X connect 4 0 3 0; #X connect 5 0 7 0; #X connect 6 0 8 0; @@ -323,3 +341,9 @@ empty -2 -8 0 10 -225280 -1 -1 0 1; #X connect 22 0 26 0; #X connect 26 0 3 0; #X connect 61 0 3 0; +#X connect 62 0 57 0; +#X connect 62 1 9 0; +#X connect 62 2 10 0; +#X connect 62 3 27 0; +#X connect 62 4 27 1; +#X connect 62 5 27 2; @@ -1,5 +1,5 @@ // =================================================================== -// Wiimote external for Puredata +// Wiiremote external for Puredata // Written by Mike Wozniewki (Feb 2007), www.mikewoz.com // // Requires the CWiid library (version 0.6.00) by L. Donnie Smith @@ -22,7 +22,7 @@ // ChangeLog: // 2008-04-14 Florian Krebs -// * adapt wiimote external for the actual version of cwiid (0.6.00) +// * adapt wiiremote external for the actual version of cwiid (0.6.00) // 2009-09-14 IOhannes m zmölnig // * made it compile without private cwiid-headers @@ -43,80 +43,61 @@ struct acc { unsigned char z; }; -/* Wiimote Callback */ -cwiid_mesg_callback_t cwiid_callback; - -// class and struct declarations for wiimote pd external: -static t_class *cwiid_class; -typedef struct _wiimote +// class and struct declarations for wiiremote pd external: +static t_class *wiiremote_class; +typedef struct _wiiremote { t_object x_obj; // standard pd object (must be first in struct) - cwiid_wiimote_t *wiimote; // individual wiimote handle per pd object, represented in libcwiid + cwiid_wiimote_t *wiiremote; // individual wiiremote handle per pd object, represented in libcwiid t_float connected; - int wiimoteID; - - t_float toggle_acc, toggle_ir, toggle_nc; - - struct acc acc_zero, acc_one; // acceleration - struct acc nc_acc_zero, nc_acc_one; // nunchuck acceleration - - // We store atom list for each data type so we don't waste time - // allocating memory at every callback: - t_atom btn_atoms[2]; - t_atom acc_atoms[3]; - t_atom ir_atoms[4]; - t_atom nc_btn_atoms[2]; - t_atom nc_acc_atoms[3]; - t_atom nc_stick_atoms[2]; - - // outlets: - t_outlet *outlet_btn; - t_outlet *outlet_acc; - t_outlet *outlet_ir; - t_outlet *outlet_nc_btn; - t_outlet *outlet_nc_acc; - t_outlet *outlet_nc_stick; - -} t_wiimote; + int wiiremoteID; + int reportMode; + struct acc_cal acc_cal; /* calibration for built-in accelerometer */ + struct acc_cal nc_acc_cal; /* calibration for nunchuk accelerometer */ -// For now, we make one global t_wiimote pointer that we can refer to + // outlets: + t_outlet *outlet_data; +} t_wiiremote; + + +// For now, we make one global t_wiiremote pointer that we can refer to // in the cwiid_callback. This means we can support maximum of ONE -// wiimote. ARGH. We'll have to figure out how to have access to the +// wiiremote. ARGH. We'll have to figure out how to have access to the // pd object from the callback (without modifying the CWiid code): -#define MAX_WIIMOTES 14 +#define MAX_WIIREMOTES 14 -typedef struct _wiimoteList { - t_wiimote*x; +typedef struct _wiiremoteList { + t_wiiremote*x; int id; - struct _wiimoteList*next; -} t_wiimoteList; + struct _wiiremoteList*next; +} t_wiiremoteList; -t_wiimoteList*g_wiimoteList=NULL; +t_wiiremoteList*g_wiiremoteList=NULL; -int addWiimoteObject(t_wiimote*x, int id) { - t_wiimoteList*wl=g_wiimoteList; - t_wiimoteList*newentry=NULL; +static int addWiiremoteObject(t_wiiremote*x, int id) { + t_wiiremoteList*wl=g_wiiremoteList; + t_wiiremoteList*newentry=NULL; if(NULL!=wl) { while(wl->next) { if(wl->x == x) { - pd_error(x, "[wiimote]: already bound to Wii%02d", wl->id); + pd_error(x, "[wiiremote]: already bound to Wii%02d", wl->id); return 0; } if(wl->id == id) { - pd_error(x, "[wiimote]: another object is already bound to Wii%02d", wl->id); + pd_error(x, "[wiiremote]: another object is already bound to Wii%02d", wl->id); return 0; } wl=wl->next; } } - newentry=(t_wiimoteList*)getbytes(sizeof(t_wiimoteList)); + newentry=(t_wiiremoteList*)getbytes(sizeof(t_wiiremoteList)); newentry->next=NULL; newentry->x=x; newentry->id=id; @@ -124,13 +105,13 @@ int addWiimoteObject(t_wiimote*x, int id) { if(wl) wl->next=newentry; else - g_wiimoteList=newentry; + g_wiiremoteList=newentry; return 1; } -t_wiimote*getWiimoteObject(const int id) { - t_wiimoteList*wl=g_wiimoteList; +static t_wiiremote*getWiiremoteObject(const int id) { + t_wiiremoteList*wl=g_wiiremoteList; if(NULL==wl) return NULL; @@ -143,9 +124,9 @@ t_wiimote*getWiimoteObject(const int id) { return NULL; } -void removeWiimoteObject(const t_wiimote*x) { - t_wiimoteList*wl=g_wiimoteList; - t_wiimoteList*last=NULL; +static void removeWiiremoteObject(const t_wiiremote*x) { + t_wiiremoteList*wl=g_wiiremoteList; + t_wiiremoteList*last=NULL; if(NULL==wl) return; @@ -154,12 +135,12 @@ void removeWiimoteObject(const t_wiimote*x) { if(last) { last->next=wl->next; } else { - g_wiimoteList=wl->next; + g_wiiremoteList=wl->next; } wl->x=NULL; wl->id=0; wl->next=NULL; - freebytes(wl, sizeof(t_wiimoteList)); + freebytes(wl, sizeof(t_wiiremoteList)); return; } @@ -171,102 +152,101 @@ void removeWiimoteObject(const t_wiimote*x) { // ============================================================== -void cwiid_debug(t_wiimote *x) +static void wiiremote_debug(t_wiiremote *x) { post("\n======================"); - if (x->connected) post("Wiimote (id: %d) is connected.", x->wiimoteID); - else post("Wiimote (id: %d) is NOT connected.", x->wiimoteID); - post("acceleration: %s", (x->toggle_acc)?"ON":"OFF"); - post("IR: %s", (x->toggle_ir)?"ON":"OFF"); - post("nunchuck: %s", (x->toggle_nc)?"ON":"OFF"); + if (x->connected) post("Wiiremote (id: %d) is connected.", x->wiiremoteID); + else post("Wiiremote (id: %d) is NOT connected.", x->wiiremoteID); + post("acceleration: %s", (x->reportMode & CWIID_RPT_ACC)?"ON":"OFF"); + post("IR: %s", (x->reportMode & CWIID_RPT_IR)?"ON":"OFF"); + post("extensions: %s", (x->reportMode & CWIID_RPT_EXT)?"ON":"OFF"); post(""); - post("Accelerometer calibration: zero=(%d,%d,%d) one=(%d,%d,%d)",x->acc_zero.x,x->acc_zero.y,x->acc_zero.z,x->acc_one.x,x->acc_one.y,x->acc_one.z); - post("Nunchuck calibration: zero=(%d,%d,%d) one=(%d,%d,%d)",x->nc_acc_zero.x,x->nc_acc_zero.y,x->nc_acc_zero.z,x->nc_acc_one.x,x->nc_acc_one.y,x->nc_acc_one.z); + post("Accelerometer calibration: zero=(%d,%d,%d) one=(%d,%d,%d)", + x->acc_cal.zero[CWIID_X], x->acc_cal.zero[CWIID_Y], x->acc_cal.zero[CWIID_Z], + x->acc_cal.one [CWIID_X], x->acc_cal.one [CWIID_Y], x->acc_cal.one [CWIID_Z]); + post("Nunchuk calibration: zero=(%d,%d,%d) one=(%d,%d,%d)", + x->nc_acc_cal.zero[CWIID_X], x->nc_acc_cal.zero[CWIID_Y], x->nc_acc_cal.zero[CWIID_Z], + x->nc_acc_cal.one [CWIID_X], x->nc_acc_cal.one [CWIID_Y], x->nc_acc_cal.one [CWIID_Z]); + } // ============================================================== +static void wiiremote_cwiid_battery(t_wiiremote *x, int battery) +{ + t_atom ap[1]; + t_float bat=(1.f*battery) / CWIID_BATTERY_MAX; + + SETFLOAT(ap+0, bat); + + verbose(1, "Battery: %d%%", (int) (100*bat)); + + outlet_anything(x->outlet_data, gensym("battery"), 1, ap); +} + // Button handler: -void cwiid_btn(t_wiimote *x, struct cwiid_btn_mesg *mesg) +static void wiiremote_cwiid_btn(t_wiiremote *x, struct cwiid_btn_mesg *mesg) { - SETFLOAT(x->btn_atoms+0, (mesg->buttons & 0xFF00)>>8); - SETFLOAT(x->btn_atoms+1, mesg->buttons & 0x00FF); - outlet_anything(x->outlet_btn, &s_list, 2, x->btn_atoms); -/* - if (mesg->buttons & CWIID_BTN_UP) {} - if (mesg->buttons & CWIID_BTN_DOWN) {} - if (mesg->buttons & CWIID_BTN_LEFT) {} - if (mesg->buttons & CWIID_BTN_RIGHT) {} - if (mesg->buttons & CWIID_BTN_A) {} - if (mesg->buttons & CWIID_BTN_B) {} - if (mesg->buttons & CWIID_BTN_MINUS) {} - if (mesg->buttons & CWIID_BTN_PLUS) {} - if (mesg->buttons & CWIID_BTN_HOME) {} - if (mesg->buttons & CWIID_BTN_1) {} - if (mesg->buttons & CWIID_BTN_2) {} -*/ - + t_atom ap[2]; + SETFLOAT(ap+0, (mesg->buttons & 0xFF00)>>8); + SETFLOAT(ap+1, mesg->buttons & 0x00FF); + outlet_anything(x->outlet_data, gensym("button"), 2, ap); } -void cwiid_acc(t_wiimote *x, struct cwiid_acc_mesg *mesg) +static void wiiremote_cwiid_acc(t_wiiremote *x, struct cwiid_acc_mesg *mesg) { - if (x->toggle_acc) - { - double a_x, a_y, a_z; + double a_x, a_y, a_z; + t_atom ap[3]; - a_x = ((double)mesg->acc[CWIID_X] - x->acc_zero.x) / (x->acc_one.x - x->acc_zero.x); - a_y = ((double)mesg->acc[CWIID_Y] - x->acc_zero.y) / (x->acc_one.y - x->acc_zero.y); - a_z = ((double)mesg->acc[CWIID_Z] - x->acc_zero.z) / (x->acc_one.z - x->acc_zero.z); + a_x = ((double)mesg->acc[CWIID_X] - x->acc_cal.zero[CWIID_X]) / (x->acc_cal.one[CWIID_X] - x->acc_cal.zero[CWIID_X]); + a_y = ((double)mesg->acc[CWIID_Y] - x->acc_cal.zero[CWIID_Y]) / (x->acc_cal.one[CWIID_Y] - x->acc_cal.zero[CWIID_Y]); + a_z = ((double)mesg->acc[CWIID_Z] - x->acc_cal.zero[CWIID_Z]) / (x->acc_cal.one[CWIID_Z] - x->acc_cal.zero[CWIID_Z]); - /* + /* double a, roll, pitch; a = sqrt(pow(a_x,2)+pow(a_y,2)+pow(a_z,2)); roll = atan(a_x/a_z); if (a_z <= 0.0) roll += PI * ((a_x > 0.0) ? 1 : -1); roll *= -1; pitch = atan(a_y/a_z*cos(roll)); - */ + */ + - SETFLOAT(x->acc_atoms+0, a_x); - SETFLOAT(x->acc_atoms+1, a_y); - SETFLOAT(x->acc_atoms+2, a_z); - outlet_anything(x->outlet_acc, &s_list, 3, x->acc_atoms); - } + SETFLOAT(ap+0, a_x); + SETFLOAT(ap+1, a_y); + SETFLOAT(ap+2, a_z); + outlet_anything(x->outlet_data, gensym("acceleration"), 3, ap); } -void cwiid_ir(t_wiimote *x, struct cwiid_ir_mesg *mesg) +static void wiiremote_cwiid_ir(t_wiiremote *x, struct cwiid_ir_mesg *mesg) { unsigned int i; - if (x->toggle_ir) - { - //post("IR (valid,x,y,size) #%d: %d %d %d %d", i, data->ir_data.ir_src[i].valid, data->ir_data.ir_src[i].x, data->ir_data.ir_src[i].y, data->ir_data.ir_src[i].size); - for (i=0; i<CWIID_IR_SRC_COUNT; i++) - { - if (mesg->src[i].valid) - { - SETFLOAT(x->ir_atoms+0, i); - SETFLOAT(x->ir_atoms+1, mesg->src[i].pos[CWIID_X]); - SETFLOAT(x->ir_atoms+2, mesg->src[i].pos[CWIID_Y]); - SETFLOAT(x->ir_atoms+3, mesg->src[i].size); - outlet_anything(x->outlet_ir, &s_list, 4, x->ir_atoms); - } + //post("IR (valid,x,y,size) #%d: %d %d %d %d", i, data->ir_data.ir_src[i].valid, data->ir_data.ir_src[i].x, data->ir_data.ir_src[i].y, data->ir_data.ir_src[i].size); + for (i=0; i<CWIID_IR_SRC_COUNT; i++){ + if (mesg->src[i].valid) { + t_atom ap[4]; + SETFLOAT(ap+0, i); + SETFLOAT(ap+1, mesg->src[i].pos[CWIID_X]); + SETFLOAT(ap+2, mesg->src[i].pos[CWIID_Y]); + SETFLOAT(ap+3, mesg->src[i].size); + outlet_anything(x->outlet_data, gensym("ir"), 4, ap); } } } - -void cwiid_nunchuk(t_wiimote *x, struct cwiid_nunchuk_mesg *mesg) +static void wiiremote_cwiid_nunchuk(t_wiiremote *x, struct cwiid_nunchuk_mesg *mesg) { + t_atom ap[4]; double a_x, a_y, a_z; - a_x = ((double)mesg->acc[CWIID_X] - x->nc_acc_zero.x) / (x->nc_acc_one.x - x->nc_acc_zero.x); - a_y = ((double)mesg->acc[CWIID_Y] - x->nc_acc_zero.y) / (x->nc_acc_one.y - x->nc_acc_zero.y); - a_z = ((double)mesg->acc[CWIID_Z] - x->nc_acc_zero.z) / (x->nc_acc_one.z - x->nc_acc_zero.z); + a_x = ((double)mesg->acc[CWIID_X] - x->nc_acc_cal.zero[CWIID_X]) / (x->nc_acc_cal.one[CWIID_X] - x->nc_acc_cal.zero[CWIID_X]); + a_y = ((double)mesg->acc[CWIID_Y] - x->nc_acc_cal.zero[CWIID_Y]) / (x->nc_acc_cal.one[CWIID_Y] - x->nc_acc_cal.zero[CWIID_Y]); + a_z = ((double)mesg->acc[CWIID_Z] - x->nc_acc_cal.zero[CWIID_Z]) / (x->nc_acc_cal.one[CWIID_Z] - x->nc_acc_cal.zero[CWIID_Z]); /* double a, roll, pitch; @@ -279,153 +259,350 @@ void cwiid_nunchuk(t_wiimote *x, struct cwiid_nunchuk_mesg *mesg) if (mesg->buttons & CWIID_NUNCHUK_BTN_C) {} if (mesg->buttons & CWIID_NUNCHUK_BTN_Z) {} - outlet_float(x->outlet_nc_btn, mesg->buttons); - - SETFLOAT(x->nc_acc_atoms+0, a_x); - SETFLOAT(x->nc_acc_atoms+1, a_y); - SETFLOAT(x->nc_acc_atoms+2, a_z); - outlet_anything(x->outlet_nc_acc, &s_list, 3, x->nc_acc_atoms); + /* nunchuk button */ + SETSYMBOL(ap+0, gensym("button")); + SETFLOAT (ap+1, (t_float)mesg->buttons); + outlet_anything(x->outlet_data, gensym("nunchuk"), 2, ap); - SETFLOAT(x->nc_stick_atoms+0, mesg->stick[CWIID_X]); - SETFLOAT(x->nc_stick_atoms+1, mesg->stick[CWIID_Y]); - outlet_anything(x->outlet_nc_stick, &s_list, 2, x->nc_stick_atoms); + + /* nunchuk button */ + SETSYMBOL(ap+0, gensym("acceleration")); + SETFLOAT (ap+1, a_x); + SETFLOAT (ap+2, a_y); + SETFLOAT (ap+3, a_z); + outlet_anything(x->outlet_data, gensym("nunchuk"), 4, ap); + /* nunchuk button */ + SETSYMBOL(ap+0, gensym("stick")); + SETFLOAT (ap+1, mesg->stick[CWIID_X]); + SETFLOAT (ap+2, mesg->stick[CWIID_Y]); + outlet_anything(x->outlet_data, gensym("nunchuk"), 3, ap); +} + +#ifdef CWIID_RPT_CLASSIC +static void wiiremote_cwiid_classic(t_wiiremote *x, struct cwiid_classic_mesg *mesg) +{ + t_atom ap[3]; + + // t_float scale = 1.f / ((uint16_t)0xFFFF); + + SETSYMBOL(ap+0, gensym("left_stick")); + SETFLOAT (ap+1, mesg->l_stick[CWIID_X]); + SETFLOAT (ap+2, mesg->l_stick[CWIID_Y]); + outlet_anything(x->outlet_data, gensym("classic"), 3, ap); + + SETSYMBOL(ap+0, gensym("right_stick")); + SETFLOAT (ap+1, mesg->r_stick[CWIID_X]); + SETFLOAT (ap+2, mesg->r_stick[CWIID_Y]); + outlet_anything(x->outlet_data, gensym("classic"), 3, ap); + + + SETSYMBOL(ap+0, gensym("left")); + SETFLOAT (ap+1, mesg->l); + outlet_anything(x->outlet_data, gensym("classic"), 2, ap); + + SETSYMBOL(ap+0, gensym("right")); + SETFLOAT (ap+1, mesg->r); + outlet_anything(x->outlet_data, gensym("classic"), 2, ap); + + + SETSYMBOL(ap+0, gensym("button")); + SETFLOAT(ap+1, (mesg->buttons & 0xFF00)>>8); + SETFLOAT(ap+2, mesg->buttons & 0x00FF); + + outlet_anything(x->outlet_data, gensym("classic"), 3, ap); + + +} +#endif + +#ifdef CWIID_RPT_BALANCE +#warning Balance ignores calibration data +static void wiiremote_cwiid_balance_output(t_wiiremote *x, t_symbol*s, uint16_t value[3], t_float scale) +{ + t_atom ap[4]; + t_float a = scale*value[CWIID_X]; + t_float b = scale*value[CWIID_Y]; + t_float c = scale*value[CWIID_Z]; + + SETSYMBOL(ap+0, s); + SETFLOAT (ap+1, a); + SETFLOAT (ap+2, b); + SETFLOAT (ap+3, c); + outlet_anything(x->outlet_data, gensym("balance"), 4, ap); +} + +static void wiiremote_cwiid_balance(t_wiiremote *x, struct cwiid_balance_mesg *mesg) +{ + t_float scale = 1.f / ((uint16_t)0xFFFF); + wiiremote_cwiid_balance_output(x, gensym("right_top"), &mesg->right_top, scale); + wiiremote_cwiid_balance_output(x, gensym("right_bottom"), &mesg->right_bottom, scale); + wiiremote_cwiid_balance_output(x, gensym("left_top"), &mesg->left_top, scale); + wiiremote_cwiid_balance_output(x, gensym("left_bottom"), &mesg->left_bottom, scale); +} +#endif + +#ifdef CWIID_RPT_MOTIONPLUS +static void wiiremote_cwiid_motionplus(t_wiiremote *x, struct cwiid_motionplus_mesg *mesg) +{ + t_atom ap[4]; + t_float scale = 1.f;// / ((uint16_t)0xFFFF); + + t_float phi = scale*mesg->angle_rate[CWIID_PHI]; + t_float theta= scale*mesg->angle_rate[CWIID_THETA]; + t_float psi = scale*mesg->angle_rate[CWIID_PSI]; + + t_float phi_speed = 1.; + t_float theta_speed = 1.; + t_float psi_speed = 1.; + + + SETSYMBOL(ap+0, gensym("low_speed")); +#ifdef HAVE_CWIID_MOTIONPLUS_LOWSPEED + phi_speed = mesg->low_speed[CWIID_PHI]; + theta_speed= mesg->low_speed[CWIID_THETA]; + psi_speed = mesg->low_speed[CWIID_PSI]; +#endif + SETFLOAT (ap+1, phi_speed); + SETFLOAT (ap+2, theta_speed); + SETFLOAT (ap+3, psi_speed); + outlet_anything(x->outlet_data, gensym("motionplus"), 4, ap); + + + SETSYMBOL(ap+0, gensym("angle_rate")); + SETFLOAT (ap+1, phi); + SETFLOAT (ap+2, theta); + SETFLOAT (ap+3, psi); + outlet_anything(x->outlet_data, gensym("motionplus"), 4, ap); } +#endif + + + +static void wiiremote_cwiid_message(t_wiiremote *x, union cwiid_mesg mesg) { + switch (mesg.type) { + case CWIID_MESG_STATUS: + wiiremote_cwiid_battery(x, mesg.status_mesg.battery); + switch (mesg.status_mesg.ext_type) { + case CWIID_EXT_NONE: + post("No extension attached"); + break; + case CWIID_EXT_NUNCHUK: + post("Nunchuk extension attached"); + if(cwiid_get_acc_cal(x->wiiremote, CWIID_EXT_NUNCHUK, &x->nc_acc_cal)) { + post("Unable to retrieve nunchuk calibration"); + } else { + post("Retrieved nunchuk calibration: zero=(%02d,%02d,%02d) one=(%02d,%02d,%02d)", + x->nc_acc_cal.zero[CWIID_X], + x->nc_acc_cal.zero[CWIID_Y], + x->nc_acc_cal.zero[CWIID_Z], + x->nc_acc_cal.one [CWIID_X], + x->nc_acc_cal.one [CWIID_Y], + x->nc_acc_cal.one [CWIID_Z]); + } + break; + case CWIID_EXT_CLASSIC: + post("Classic controller attached. There is no support for this yet."); + break; + case CWIID_EXT_BALANCE: + post("Balance controller attached. There is no support for this yet."); + break; + case CWIID_EXT_MOTIONPLUS: + post("MotionPlus controller attached."); + /* no calibration needed for MotionPlus */ + break; + case CWIID_EXT_UNKNOWN: + post("Unknown extension attached"); + break; + default: + post("ext mesg %d unknown", mesg.status_mesg.ext_type); + break; + } + break; + case CWIID_MESG_BTN: + wiiremote_cwiid_btn(x, &mesg.btn_mesg); + break; + case CWIID_MESG_ACC: + wiiremote_cwiid_acc(x, &mesg.acc_mesg); + break; + case CWIID_MESG_IR: + wiiremote_cwiid_ir(x, &mesg.ir_mesg); + break; +#ifdef CWIID_RPT_NUNCHUK + case CWIID_MESG_NUNCHUK: + wiiremote_cwiid_nunchuk(x, &mesg.nunchuk_mesg); + break; +#endif +#ifdef CWIID_RPT_CLASSIC + case CWIID_MESG_CLASSIC: + wiiremote_cwiid_classic(x, &mesg.classic_mesg); + // todo + break; +#endif +#ifdef CWIID_RPT_MOTIONPLUS + case CWIID_MESG_MOTIONPLUS: + wiiremote_cwiid_motionplus(x, &mesg.motionplus_mesg); + break; +#endif +#ifdef CWIID_RPT_BALANCE + case CWIID_MESG_BALANCE: + wiiremote_cwiid_balance(x, &mesg.balance_mesg); + break; +#endif + default: + post("mesg %d unknown", (mesg.type)); + break; + } +} + + +static void print_timestamp(struct timespec*timestamp, struct timespec*reference) { + double t0=timestamp->tv_sec*1000. + (timestamp->tv_nsec) / 1000000.; + double t1=0; + double t=0; + if(reference) { + t1=reference->tv_sec*1000. + (reference->tv_nsec) / 1000000.; + } + + t=t0-t1; + + post("timestamp: %f", (t)); + +} + // The CWiid library invokes a callback function whenever events are -// generated by the wiimote. This function is specified when connecting -// to the wiimote (in the cwiid_open function). +// generated by the wiiremote. This function is specified when connecting +// to the wiiremote (in the cwiid_open function). // Unfortunately, the mesg struct passed as an argument to the -// callback does not have a pointer to the wiimote instance, and it -// is thus impossible to know which wiimote has invoked the callback. +// callback does not have a pointer to the wiiremote instance, and it +// is thus impossible to know which wiiremote-object has invoked the callback. // For this case we provide a hard-coded set of wrapper callbacks to -// indicate which Pd wiimote instance to control. +// indicate which Pd wiiremote instance to control. -// So far I have only checked with one wiimote +// So far I have only checked with one wiiremote -/*void cwiid_callback(cwiid_wiimote_t *wiimt, int mesg_count, union cwiid_mesg *mesg[], struct timespec *timestamp) +/*void cwiid_callback(cwiid_wiiremote_t *wiimt, int mesg_count, union cwiid_mesg *mesg[], struct timespec *timestamp) */ -void cwiid_callback(cwiid_wiimote_t *wiimote, int mesg_count, +static void cwiid_callback(cwiid_wiimote_t *wiiremote, int mesg_count, union cwiid_mesg mesg_array[], struct timespec *timestamp) { - unsigned char buf[7]; int i; - t_wiimote *x=NULL; + t_wiiremote *x=NULL; + + static struct timespec*ts=NULL; + if(NULL==ts) { + ts=(struct timespec*)getbytes(sizeof(struct timespec)); + ts->tv_sec =timestamp->tv_sec; + ts->tv_nsec =timestamp->tv_nsec; + } - if(g_wiimoteList==NULL||wiimote==NULL) { + if(g_wiiremoteList==NULL||wiiremote==NULL) { post("no wii's known"); return; } - x=getWiimoteObject(cwiid_get_id(wiimote)); + x=getWiiremoteObject(cwiid_get_id(wiiremote)); if(NULL==x) { - post("no wiimote loaded: %d%",cwiid_get_id(wiimote)); + post("no wiiremote loaded: %d%",cwiid_get_id(wiiremote)); return; } - - for (i=0; i < mesg_count; i++) - { - switch (mesg_array[i].type) { - case CWIID_MESG_STATUS: - post("Battery: %d%", (int) (100.0 * mesg_array[i].status_mesg.battery / CWIID_BATTERY_MAX)); - switch (mesg_array[i].status_mesg.ext_type) { - case CWIID_EXT_NONE: - post("No nunchuck attached"); - break; - case CWIID_EXT_NUNCHUK: - post("Nunchuck extension attached"); - - if (cwiid_read(x->wiimote, CWIID_RW_REG | CWIID_RW_DECODE, 0xA40020, 7, buf)) { - post("Unable to retrieve Nunchuk calibration"); - } - else { - x->nc_acc_zero.x = buf[0]; - x->nc_acc_zero.y = buf[1]; - x->nc_acc_zero.z = buf[2]; - x->nc_acc_one.x = buf[4]; - x->nc_acc_one.y = buf[5]; - x->nc_acc_one.z = buf[6]; - } - break; - case CWIID_EXT_CLASSIC: - post("Classic controller attached. There is no support for this yet."); - break; - case CWIID_EXT_UNKNOWN: - post("Unknown extension attached"); - break; - } - break; - case CWIID_MESG_BTN: - cwiid_btn(x, &mesg_array[i].btn_mesg); - break; - case CWIID_MESG_ACC: - cwiid_acc(x, &mesg_array[i].acc_mesg); - break; - case CWIID_MESG_IR: - cwiid_ir(x, &mesg_array[i].ir_mesg); - break; - case CWIID_MESG_NUNCHUK: - cwiid_nunchuk(x, &mesg_array[i].nunchuk_mesg); - break; - case CWIID_MESG_CLASSIC: - // todo - break; - default: - break; - } - } + + //print_timestamp(timestamp, ts); + for (i=0; i < mesg_count; i++) { + wiiremote_cwiid_message(x, mesg_array[i]); + } } // ============================================================== +static void wiiremote_status(t_wiiremote *x) +{ + if(x->connected) { + if (cwiid_request_status(x->wiiremote)) { + pd_error(x, "error requesting status message"); + } + } +} -void cwiid_setReportMode(t_wiimote *x, t_floatarg r) +static void wiiremote_resetReportMode(t_wiiremote *x) { - unsigned char rpt_mode; + if (x->connected) { + verbose(1, "changing report mode for Wii%02d to %d", x->wiiremoteID, x->reportMode); + if (cwiid_command(x->wiiremote, CWIID_CMD_RPT_MODE, x->reportMode)) { + post("wiiremote error: problem setting report mode."); + } + } +} - if (r >= 0) rpt_mode = (unsigned char) r; - else { - rpt_mode = CWIID_RPT_STATUS | CWIID_RPT_BTN; - if (x->toggle_ir) rpt_mode |= CWIID_RPT_IR; - if (x->toggle_acc) rpt_mode |= CWIID_RPT_ACC; - if (x->toggle_nc) rpt_mode |= CWIID_RPT_EXT; + +static void wiiremote_setReportMode(t_wiiremote *x, t_floatarg r) +{ + if (r >= 0) { + x->reportMode = (int) r; + wiiremote_resetReportMode(x); + } else { + return; } - if (x->connected) - { - verbose(1, "changing report mode for Wii%02d to %d", x->wiimoteID, rpt_mode); - if (cwiid_command(x->wiimote, CWIID_CMD_RPT_MODE, rpt_mode)) { - post("wiimote error: problem setting report mode."); - } +} + + +static void wiiremote_report(t_wiiremote*x, int flag, int onoff) +{ + if(onoff) { + x->reportMode |= flag; + } else { + x->reportMode &= ~flag; } + wiiremote_resetReportMode(x); } -void cwiid_reportAcceleration(t_wiimote *x, t_floatarg f) +static void wiiremote_reportAcceleration(t_wiiremote *x, t_floatarg f) { - x->toggle_acc = f; - cwiid_setReportMode(x, -1); + wiiremote_report(x, CWIID_RPT_ACC, f); } -void cwiid_reportIR(t_wiimote *x, t_floatarg f) +static void wiiremote_reportIR(t_wiiremote *x, t_floatarg f) { - x->toggle_ir = f; - cwiid_setReportMode(x, -1); + wiiremote_report(x, CWIID_RPT_IR, f); } -void cwiid_reportNunchuck(t_wiimote *x, t_floatarg f) +static void wiiremote_reportNunchuk(t_wiiremote *x, t_floatarg f) { - x->toggle_nc = f; - cwiid_setReportMode(x, -1); + wiiremote_report(x, CWIID_RPT_EXT, f); } -void cwiid_setRumble(t_wiimote *x, t_floatarg f) + +static void wiiremote_reportMotionplus(t_wiiremote *x, t_floatarg f) +{ +#ifdef CWIID_RPT_MOTIONPLUS + int flag=f; + if (x->connected) { + verbose(1, "changing motionplus report mode for Wii%02d to %d", x->wiiremoteID, flag); + int err=0; + if(flag) { + err=cwiid_enable(x->wiiremote, CWIID_FLAG_MOTIONPLUS); + } else { + err=cwiid_disable(x->wiiremote, CWIID_FLAG_MOTIONPLUS); + } + if(err) { + pd_error(x, "turning %s motionplus returned %d", (flag?"on":"off"), err); + } else { + wiiremote_report(x, CWIID_RPT_MOTIONPLUS, f); + } + } +#endif +} + +static void wiiremote_setRumble(t_wiiremote *x, t_floatarg f) { if (x->connected) { - if (cwiid_command(x->wiimote, CWIID_CMD_RUMBLE, f)) post("wiiremote error: problem setting rumble."); + if (cwiid_command(x->wiiremote, CWIID_CMD_RUMBLE, f)) post("wiiremote error: problem setting rumble."); } } -void cwiid_setLED(t_wiimote *x, t_floatarg f) +static void wiiremote_setLED(t_wiiremote *x, t_floatarg f) { // some possible values: // CWIID_LED0_ON 0x01 @@ -434,7 +611,7 @@ void cwiid_setLED(t_wiimote *x, t_floatarg f) // CWIID_LED3_ON 0x08 if (x->connected) { - if (cwiid_command(x->wiimote, CWIID_CMD_LED, f)) post("wiiremote error: problem setting LED."); + if (cwiid_command(x->wiiremote, CWIID_CMD_LED, f)) post("wiiremote error: problem setting LED."); } } @@ -443,17 +620,16 @@ void cwiid_setLED(t_wiimote *x, t_floatarg f) // ============================================================== -// The following function attempts to connect to a wiimote at a +// The following function attempts to connect to a wiiremote at a // specific address, provided as an argument. eg, 00:19:1D:70:CE:72 // This address can be discovered by running the following command // in a console: // hcitool scan | grep Nintendo -void cwiid_doConnect(t_wiimote *x, t_symbol *addr, t_symbol *dongaddr) +static void wiiremote_doConnect(t_wiiremote *x, t_symbol *addr, t_symbol *dongaddr) { - unsigned char buf[7]; - int i; bdaddr_t bdaddr; + unsigned int flags = CWIID_FLAG_MESG_IFC; bdaddr_t dong_bdaddr; bdaddr_t* dong_bdaddr_ptr=&dong_bdaddr; @@ -478,76 +654,81 @@ void cwiid_doConnect(t_wiimote *x, t_symbol *addr, t_symbol *dongaddr) str2ba(dongaddr->s_name, &dong_bdaddr); } // connect: - + + #if 0 -#warning florian, you cannot just change the cwiid_open() function - x->wiimote = cwiid_open(&bdaddr, dong_bdaddr_ptr, CWIID_FLAG_MESG_IFC); + x->wiiremote = cwiid_open(&bdaddr, dong_bdaddr_ptr, flags); #else - x->wiimote = cwiid_open(&bdaddr, CWIID_FLAG_MESG_IFC); +#warning multi-dongle support... + x->wiiremote = cwiid_open(&bdaddr, flags); #endif - if(NULL==x->wiimote) { - post("wiimote error: unable to connect"); + if(NULL==x->wiiremote) { + post("wiiremote error: unable to connect"); return; } - if(!addWiimoteObject(x, cwiid_get_id(x->wiimote))) { - cwiid_close(x->wiimote); - x->wiimote==NULL; + if(!addWiiremoteObject(x, cwiid_get_id(x->wiiremote))) { + cwiid_close(x->wiiremote); + x->wiiremote=NULL; return; } - x->wiimoteID= cwiid_get_id(x->wiimote); + x->wiiremoteID= cwiid_get_id(x->wiiremote); - post("wiimote %i is successfully connected", x->wiimoteID); - if (cwiid_read(x->wiimote, CWIID_RW_EEPROM, 0x16, 7, buf)) { + post("wiiremote %i is successfully connected", x->wiiremoteID); + + if(cwiid_get_acc_cal(x->wiiremote, CWIID_EXT_NONE, &x->acc_cal)) { post("Unable to retrieve accelerometer calibration"); } else { - x->acc_zero.x = buf[0]; - x->acc_zero.y = buf[1]; - x->acc_zero.z = buf[2]; - x->acc_one.x = buf[4]; - x->acc_one.y = buf[5]; - x->acc_one.z = buf[6]; - //post("Retrieved wiimote calibration: zero=(%.1f,%.1f,%.1f) one=(%.1f,%.1f,%.1f)",buf[0],buf[2],buf[3],buf[4],buf[5],buf[6]); + post("Retrieved wiiremote calibration: zero=(%02d,%02d,%02d) one=(%02d,%02d,%02d)", + x->acc_cal.zero[CWIID_X], + x->acc_cal.zero[CWIID_Y], + x->acc_cal.zero[CWIID_Z], + x->acc_cal.one [CWIID_X], + x->acc_cal.one [CWIID_Y], + x->acc_cal.one [CWIID_Z]); } x->connected = 1; - cwiid_setReportMode(x,-1); - if (cwiid_set_mesg_callback(x->wiimote, &cwiid_callback)) { + x->reportMode |= CWIID_RPT_STATUS; + x->reportMode |= CWIID_RPT_BTN; + wiiremote_resetReportMode(x); + + if (cwiid_set_mesg_callback(x->wiiremote, &cwiid_callback)) { pd_error(x, "Unable to set message callback"); } } -// The following function attempts to discover a wiimote. It requires -// that the user puts the wiimote into 'discoverable' mode before being +// The following function attempts to discover a wiiremote. It requires +// that the user puts the wiiremote into 'discoverable' mode before being // called. This is done by pressing the red button under the battery // cover, or by pressing buttons 1 and 2 simultaneously. // TODO: Without pressing the buttons, I get a segmentation error. So far, I don't know why. -void cwiid_discover(t_wiimote *x) +static void wiiremote_discover(t_wiiremote *x) { - post("Put the wiimote into discover mode by pressing buttons 1 and 2 simultaneously."); + post("Put the wiiremote into discover mode by pressing buttons 1 and 2 simultaneously."); - cwiid_doConnect(x, NULL, gensym("NULL")); + wiiremote_doConnect(x, NULL, gensym("NULL")); if (!(x->connected)) { - post("Error: could not find any wiimotes. Please ensure that bluetooth is enabled, and that the 'hcitool scan' command lists your Nintendo device."); + post("Error: could not find any wiiremotes. Please ensure that bluetooth is enabled, and that the 'hcitool scan' command lists your Nintendo device."); } } -void cwiid_doDisconnect(t_wiimote *x) +static void wiiremote_doDisconnect(t_wiiremote *x) { if (x->connected) { - if (cwiid_close(x->wiimote)) { - post("wiimote error: problems when disconnecting."); + if (cwiid_close(x->wiiremote)) { + post("wiiremote error: problems when disconnecting."); } else { post("disconnect successfull, resetting values"); - removeWiimoteObject(x); + removeWiiremoteObject(x); x->connected = 0; } } @@ -559,70 +740,66 @@ void cwiid_doDisconnect(t_wiimote *x) // ============================================================== // ============================================================== -static void *cwiid_new(t_symbol* s, int argc, t_atom *argv) +static void *wiiremote_new(t_symbol*s, int argc, t_atom *argv) { - bdaddr_t bdaddr; // wiimote bdaddr - t_wiimote *x = (t_wiimote *)pd_new(cwiid_class); + t_wiiremote *x = (t_wiiremote *)pd_new(wiiremote_class); // create outlets: - x->outlet_btn = outlet_new(&x->x_obj, &s_list); - x->outlet_acc = outlet_new(&x->x_obj, &s_list); - x->outlet_ir = outlet_new(&x->x_obj, &s_list); - x->outlet_nc_btn = outlet_new(&x->x_obj, &s_float); - x->outlet_nc_acc = outlet_new(&x->x_obj, &s_list); - x->outlet_nc_stick = outlet_new(&x->x_obj, &s_list); + x->outlet_data = outlet_new(&x->x_obj, NULL); // initialize toggles: - x->toggle_acc = 0; - x->toggle_ir = 0; - x->toggle_nc = 0; - x->connected = 0; - x->wiimoteID = -1; + x->wiiremoteID = -1; // connect if user provided an address as an argument: if (argc==2) { - post("conecting to provided address..."); + post("[%s] connecting to provided address...", s->s_name); if (argv->a_type == A_SYMBOL) { - cwiid_doConnect(x, NULL, atom_getsymbol(argv)); + wiiremote_doConnect(x, NULL, atom_getsymbol(argv)); } else { - error("[wiimote] expects either no argument, or a bluetooth address as an argument. eg, 00:19:1D:70:CE:72"); + error("[wiiremote] expects either no argument, or a bluetooth address as an argument. eg, 00:19:1D:70:CE:72"); return NULL; } } - - - - - - return (x); } -static void cwiid_free(t_wiimote* x) +static void wiiremote_free(t_wiiremote* x) { - cwiid_doDisconnect(x); + wiiremote_doDisconnect(x); } -void wiimote_setup(void) +void wiiremote_setup(void) { - int i; - - cwiid_class = class_new(gensym("wiimote"), (t_newmethod)cwiid_new, (t_method)cwiid_free, sizeof(t_wiimote), CLASS_DEFAULT, A_GIMME, 0); - class_addmethod(cwiid_class, (t_method) cwiid_debug, gensym("debug"), 0); - class_addmethod(cwiid_class, (t_method) cwiid_doConnect, gensym("connect"), A_SYMBOL, A_SYMBOL, 0); - class_addmethod(cwiid_class, (t_method) cwiid_doDisconnect, gensym("disconnect"), 0); - class_addmethod(cwiid_class, (t_method) cwiid_discover, gensym("discover"), 0); - class_addmethod(cwiid_class, (t_method) cwiid_setReportMode, gensym("setReportMode"), A_DEFFLOAT, 0); - class_addmethod(cwiid_class, (t_method) cwiid_reportAcceleration, gensym("reportAcceleration"), A_DEFFLOAT, 0); - class_addmethod(cwiid_class, (t_method) cwiid_reportNunchuck, gensym("reportNunchuck"), A_DEFFLOAT, 0); - class_addmethod(cwiid_class, (t_method) cwiid_reportIR, gensym("reportIR"), A_DEFFLOAT, 0); - class_addmethod(cwiid_class, (t_method) cwiid_setRumble, gensym("setRumble"), A_DEFFLOAT, 0); - class_addmethod(cwiid_class, (t_method) cwiid_setLED, gensym("setLED"), A_DEFFLOAT, 0); + wiiremote_class = class_new(gensym("wiiremote"), (t_newmethod)wiiremote_new, (t_method)wiiremote_free, sizeof(t_wiiremote), CLASS_DEFAULT, A_GIMME, 0); + + class_addmethod(wiiremote_class, (t_method) wiiremote_debug, gensym("debug"), 0); + class_addmethod(wiiremote_class, (t_method) wiiremote_status, gensym("status"), 0); + + + /* connection settings */ + class_addmethod(wiiremote_class, (t_method) wiiremote_doConnect, gensym("connect"), A_DEFSYMBOL, A_DEFSYMBOL, 0); + class_addmethod(wiiremote_class, (t_method) wiiremote_doDisconnect, gensym("disconnect"), 0); + class_addmethod(wiiremote_class, (t_method) wiiremote_discover, gensym("discover"), 0); + + + /* query data */ + class_addmethod(wiiremote_class, (t_method) wiiremote_setReportMode, gensym("setReportMode"), A_DEFFLOAT, 0); + class_addmethod(wiiremote_class, (t_method) wiiremote_reportAcceleration, gensym("reportAcceleration"), A_DEFFLOAT, 0); + class_addmethod(wiiremote_class, (t_method) wiiremote_reportIR, gensym("reportIR"), A_DEFFLOAT, 0); + + class_addmethod(wiiremote_class, (t_method) wiiremote_reportNunchuk, gensym("reportNunchuck"), A_DEFFLOAT, 0); + class_addmethod(wiiremote_class, (t_method) wiiremote_reportNunchuk, gensym("reportNunchuk"), A_DEFFLOAT, 0); + class_addmethod(wiiremote_class, (t_method) wiiremote_reportMotionplus, gensym("reportMotionplus"), A_DEFFLOAT, 0); + + + /* set things on the wiimote */ + class_addmethod(wiiremote_class, (t_method) wiiremote_setRumble, gensym("setRumble"), A_DEFFLOAT, 0); + class_addmethod(wiiremote_class, (t_method) wiiremote_setLED, gensym("setLED"), A_DEFFLOAT, 0); } diff --git a/wiimote.pd b/wiimote.pd deleted file mode 100644 index db5455c..0000000 --- a/wiimote.pd +++ /dev/null @@ -1,41 +0,0 @@ -#N canvas 236 633 922 423 10; -#X obj 104 111 wiiremote; -#X obj 104 38 inlet; -#X obj 104 207 outlet button; -#X obj 232 277 outlet IR; -#X obj 378 267 outlet nunchuck-buttons; -#X obj 449 287 outlet nunchuck-acceleration; -#X obj 520 307 outlet nunchuck-stick; -#X obj 168 247 outlet acceleration; -#X obj 104 169 route button acceleration ir; -#X obj 378 245 route button acceleration stick; -#X obj 378 204 route nunchuck motionplus; -#X obj 588 162 print motionplus; -#X msg 280 87 setReportMode \$1; -#X floatatom 282 44 5 0 0 0 - - -; -#X obj 476 70 pow; -#X msg 476 44 2 \$1; -#X obj 478 26 hradio 15 1 0 8 empty empty empty 0 -8 0 10 -262144 -1 --1 0; -#X text 628 32 5==accelera; -#X text 762 134 0x80=; -#X symbolatom 505 138 10 0 0 0 - - -; -#X obj 502 112 makefilename 0x%x; -#X connect 0 0 8 0; -#X connect 1 0 0 0; -#X connect 8 0 2 0; -#X connect 8 1 7 0; -#X connect 8 2 3 0; -#X connect 8 3 10 0; -#X connect 9 0 4 0; -#X connect 9 1 5 0; -#X connect 9 2 6 0; -#X connect 10 0 9 0; -#X connect 10 1 11 0; -#X connect 12 0 0 0; -#X connect 13 0 12 0; -#X connect 14 0 13 0; -#X connect 14 0 20 0; -#X connect 15 0 14 0; -#X connect 16 0 15 0; -#X connect 20 0 19 0; diff --git a/wiiremote.c b/wiiremote.c deleted file mode 100644 index 99af4fb..0000000 --- a/wiiremote.c +++ /dev/null @@ -1,805 +0,0 @@ -// =================================================================== -// Wiiremote external for Puredata -// Written by Mike Wozniewki (Feb 2007), www.mikewoz.com -// -// Requires the CWiid library (version 0.6.00) by L. Donnie Smith -// -// =================================================================== -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// =================================================================== - -// ChangeLog: -// 2008-04-14 Florian Krebs -// * adapt wiiremote external for the actual version of cwiid (0.6.00) -// 2009-09-14 IOhannes m zmölnig -// * made it compile without private cwiid-headers - - -#include <stdio.h> -#include <unistd.h> -#include <sys/select.h> -#include <bluetooth/bluetooth.h> -#include <m_pd.h> -#include <math.h> -#include <cwiid.h> - -#define PI 3.14159265358979323 - -struct acc { - unsigned char x; - unsigned char y; - unsigned char z; -}; - -// class and struct declarations for wiiremote pd external: -static t_class *wiiremote_class; -typedef struct _wiiremote -{ - t_object x_obj; // standard pd object (must be first in struct) - - cwiid_wiimote_t *wiiremote; // individual wiiremote handle per pd object, represented in libcwiid - - t_float connected; - int wiiremoteID; - - - int reportMode; - - struct acc_cal acc_cal; /* calibration for built-in accelerometer */ - struct acc_cal nc_acc_cal; /* calibration for nunchuk accelerometer */ - - // outlets: - t_outlet *outlet_data; -} t_wiiremote; - - -// For now, we make one global t_wiiremote pointer that we can refer to -// in the cwiid_callback. This means we can support maximum of ONE -// wiiremote. ARGH. We'll have to figure out how to have access to the -// pd object from the callback (without modifying the CWiid code): -#define MAX_WIIREMOTES 14 - -typedef struct _wiiremoteList { - t_wiiremote*x; - int id; - struct _wiiremoteList*next; -} t_wiiremoteList; - -t_wiiremoteList*g_wiiremoteList=NULL; - -static int addWiiremoteObject(t_wiiremote*x, int id) { - t_wiiremoteList*wl=g_wiiremoteList; - t_wiiremoteList*newentry=NULL; - if(NULL!=wl) { - while(wl->next) { - - if(wl->x == x) { - pd_error(x, "[wiiremote]: already bound to Wii%02d", wl->id); - return 0; - } - if(wl->id == id) { - pd_error(x, "[wiiremote]: another object is already bound to Wii%02d", wl->id); - return 0; - } - wl=wl->next; - } - } - - newentry=(t_wiiremoteList*)getbytes(sizeof(t_wiiremoteList)); - newentry->next=NULL; - newentry->x=x; - newentry->id=id; - - if(wl) - wl->next=newentry; - else - g_wiiremoteList=newentry; - - return 1; -} - -static t_wiiremote*getWiiremoteObject(const int id) { - t_wiiremoteList*wl=g_wiiremoteList; - if(NULL==wl) - return NULL; - - while(wl) { - if(id == wl->id) { - return wl->x; - } - wl=wl->next; - } - return NULL; -} - -static void removeWiiremoteObject(const t_wiiremote*x) { - t_wiiremoteList*wl=g_wiiremoteList; - t_wiiremoteList*last=NULL; - if(NULL==wl) - return; - - while(wl) { - if(x == wl->x) { - if(last) { - last->next=wl->next; - } else { - g_wiiremoteList=wl->next; - } - wl->x=NULL; - wl->id=0; - wl->next=NULL; - freebytes(wl, sizeof(t_wiiremoteList)); - - return; - } - last=wl; - wl=wl->next; - } -} - - - -// ============================================================== -static void wiiremote_debug(t_wiiremote *x) -{ - post("\n======================"); - if (x->connected) post("Wiiremote (id: %d) is connected.", x->wiiremoteID); - else post("Wiiremote (id: %d) is NOT connected.", x->wiiremoteID); - post("acceleration: %s", (x->reportMode & CWIID_RPT_ACC)?"ON":"OFF"); - post("IR: %s", (x->reportMode & CWIID_RPT_IR)?"ON":"OFF"); - post("extensions: %s", (x->reportMode & CWIID_RPT_EXT)?"ON":"OFF"); - post(""); - post("Accelerometer calibration: zero=(%d,%d,%d) one=(%d,%d,%d)", - x->acc_cal.zero[CWIID_X], x->acc_cal.zero[CWIID_Y], x->acc_cal.zero[CWIID_Z], - x->acc_cal.one [CWIID_X], x->acc_cal.one [CWIID_Y], x->acc_cal.one [CWIID_Z]); - post("Nunchuk calibration: zero=(%d,%d,%d) one=(%d,%d,%d)", - x->nc_acc_cal.zero[CWIID_X], x->nc_acc_cal.zero[CWIID_Y], x->nc_acc_cal.zero[CWIID_Z], - x->nc_acc_cal.one [CWIID_X], x->nc_acc_cal.one [CWIID_Y], x->nc_acc_cal.one [CWIID_Z]); - - - -} - -// ============================================================== - -static void wiiremote_cwiid_battery(t_wiiremote *x, int battery) -{ - t_atom ap[1]; - t_float bat=(1.f*battery) / CWIID_BATTERY_MAX; - - SETFLOAT(ap+0, bat); - - verbose(1, "Battery: %d%%", (int) (100*bat)); - - outlet_anything(x->outlet_data, gensym("battery"), 1, ap); -} - -// Button handler: -static void wiiremote_cwiid_btn(t_wiiremote *x, struct cwiid_btn_mesg *mesg) -{ - t_atom ap[2]; - SETFLOAT(ap+0, (mesg->buttons & 0xFF00)>>8); - SETFLOAT(ap+1, mesg->buttons & 0x00FF); - outlet_anything(x->outlet_data, gensym("button"), 2, ap); -} - - -static void wiiremote_cwiid_acc(t_wiiremote *x, struct cwiid_acc_mesg *mesg) -{ - double a_x, a_y, a_z; - t_atom ap[3]; - - a_x = ((double)mesg->acc[CWIID_X] - x->acc_cal.zero[CWIID_X]) / (x->acc_cal.one[CWIID_X] - x->acc_cal.zero[CWIID_X]); - a_y = ((double)mesg->acc[CWIID_Y] - x->acc_cal.zero[CWIID_Y]) / (x->acc_cal.one[CWIID_Y] - x->acc_cal.zero[CWIID_Y]); - a_z = ((double)mesg->acc[CWIID_Z] - x->acc_cal.zero[CWIID_Z]) / (x->acc_cal.one[CWIID_Z] - x->acc_cal.zero[CWIID_Z]); - - /* - double a, roll, pitch; - a = sqrt(pow(a_x,2)+pow(a_y,2)+pow(a_z,2)); - roll = atan(a_x/a_z); - if (a_z <= 0.0) roll += PI * ((a_x > 0.0) ? 1 : -1); - roll *= -1; - pitch = atan(a_y/a_z*cos(roll)); - */ - - - SETFLOAT(ap+0, a_x); - SETFLOAT(ap+1, a_y); - SETFLOAT(ap+2, a_z); - outlet_anything(x->outlet_data, gensym("acceleration"), 3, ap); - -} - -static void wiiremote_cwiid_ir(t_wiiremote *x, struct cwiid_ir_mesg *mesg) -{ - unsigned int i; - - //post("IR (valid,x,y,size) #%d: %d %d %d %d", i, data->ir_data.ir_src[i].valid, data->ir_data.ir_src[i].x, data->ir_data.ir_src[i].y, data->ir_data.ir_src[i].size); - for (i=0; i<CWIID_IR_SRC_COUNT; i++){ - if (mesg->src[i].valid) { - t_atom ap[4]; - SETFLOAT(ap+0, i); - SETFLOAT(ap+1, mesg->src[i].pos[CWIID_X]); - SETFLOAT(ap+2, mesg->src[i].pos[CWIID_Y]); - SETFLOAT(ap+3, mesg->src[i].size); - outlet_anything(x->outlet_data, gensym("ir"), 4, ap); - } - } -} - -static void wiiremote_cwiid_nunchuk(t_wiiremote *x, struct cwiid_nunchuk_mesg *mesg) -{ - t_atom ap[4]; - double a_x, a_y, a_z; - - a_x = ((double)mesg->acc[CWIID_X] - x->nc_acc_cal.zero[CWIID_X]) / (x->nc_acc_cal.one[CWIID_X] - x->nc_acc_cal.zero[CWIID_X]); - a_y = ((double)mesg->acc[CWIID_Y] - x->nc_acc_cal.zero[CWIID_Y]) / (x->nc_acc_cal.one[CWIID_Y] - x->nc_acc_cal.zero[CWIID_Y]); - a_z = ((double)mesg->acc[CWIID_Z] - x->nc_acc_cal.zero[CWIID_Z]) / (x->nc_acc_cal.one[CWIID_Z] - x->nc_acc_cal.zero[CWIID_Z]); - - /* - double a, roll, pitch; - a = sqrt(pow(a_x,2)+pow(a_y,2)+pow(a_z,2)); - roll = atan(a_x/a_z); - if (a_z <= 0.0) roll += PI * ((a_x > 0.0) ? 1 : -1); - roll *= -1; - pitch = atan(a_y/a_z*cos(roll)); - */ - - if (mesg->buttons & CWIID_NUNCHUK_BTN_C) {} - if (mesg->buttons & CWIID_NUNCHUK_BTN_Z) {} - /* nunchuk button */ - SETSYMBOL(ap+0, gensym("button")); - SETFLOAT (ap+1, (t_float)mesg->buttons); - outlet_anything(x->outlet_data, gensym("nunchuk"), 2, ap); - - - /* nunchuk button */ - SETSYMBOL(ap+0, gensym("acceleration")); - SETFLOAT (ap+1, a_x); - SETFLOAT (ap+2, a_y); - SETFLOAT (ap+3, a_z); - outlet_anything(x->outlet_data, gensym("nunchuk"), 4, ap); - - /* nunchuk button */ - SETSYMBOL(ap+0, gensym("stick")); - SETFLOAT (ap+1, mesg->stick[CWIID_X]); - SETFLOAT (ap+2, mesg->stick[CWIID_Y]); - outlet_anything(x->outlet_data, gensym("nunchuk"), 3, ap); -} - -#ifdef CWIID_RPT_CLASSIC -static void wiiremote_cwiid_classic(t_wiiremote *x, struct cwiid_classic_mesg *mesg) -{ - t_atom ap[3]; - - // t_float scale = 1.f / ((uint16_t)0xFFFF); - - SETSYMBOL(ap+0, gensym("left_stick")); - SETFLOAT (ap+1, mesg->l_stick[CWIID_X]); - SETFLOAT (ap+2, mesg->l_stick[CWIID_Y]); - outlet_anything(x->outlet_data, gensym("classic"), 3, ap); - - SETSYMBOL(ap+0, gensym("right_stick")); - SETFLOAT (ap+1, mesg->r_stick[CWIID_X]); - SETFLOAT (ap+2, mesg->r_stick[CWIID_Y]); - outlet_anything(x->outlet_data, gensym("classic"), 3, ap); - - - SETSYMBOL(ap+0, gensym("left")); - SETFLOAT (ap+1, mesg->l); - outlet_anything(x->outlet_data, gensym("classic"), 2, ap); - - SETSYMBOL(ap+0, gensym("right")); - SETFLOAT (ap+1, mesg->r); - outlet_anything(x->outlet_data, gensym("classic"), 2, ap); - - - SETSYMBOL(ap+0, gensym("button")); - SETFLOAT(ap+1, (mesg->buttons & 0xFF00)>>8); - SETFLOAT(ap+2, mesg->buttons & 0x00FF); - - outlet_anything(x->outlet_data, gensym("classic"), 3, ap); - - -} -#endif - -#ifdef CWIID_RPT_BALANCE -#warning Balance ignores calibration data -static void wiiremote_cwiid_balance_output(t_wiiremote *x, t_symbol*s, uint16_t value[3], t_float scale) -{ - t_atom ap[4]; - t_float a = scale*value[CWIID_X]; - t_float b = scale*value[CWIID_Y]; - t_float c = scale*value[CWIID_Z]; - - SETSYMBOL(ap+0, s); - SETFLOAT (ap+1, a); - SETFLOAT (ap+2, b); - SETFLOAT (ap+3, c); - outlet_anything(x->outlet_data, gensym("balance"), 4, ap); -} - -static void wiiremote_cwiid_balance(t_wiiremote *x, struct cwiid_balance_mesg *mesg) -{ - t_float scale = 1.f / ((uint16_t)0xFFFF); - wiiremote_cwiid_balance_output(x, gensym("right_top"), &mesg->right_top, scale); - wiiremote_cwiid_balance_output(x, gensym("right_bottom"), &mesg->right_bottom, scale); - wiiremote_cwiid_balance_output(x, gensym("left_top"), &mesg->left_top, scale); - wiiremote_cwiid_balance_output(x, gensym("left_bottom"), &mesg->left_bottom, scale); -} -#endif - -#ifdef CWIID_RPT_MOTIONPLUS -static void wiiremote_cwiid_motionplus(t_wiiremote *x, struct cwiid_motionplus_mesg *mesg) -{ - t_atom ap[4]; - t_float scale = 1.f;// / ((uint16_t)0xFFFF); - - t_float phi = scale*mesg->angle_rate[CWIID_PHI]; - t_float theta= scale*mesg->angle_rate[CWIID_THETA]; - t_float psi = scale*mesg->angle_rate[CWIID_PSI]; - - t_float phi_speed = 1.; - t_float theta_speed = 1.; - t_float psi_speed = 1.; - - - SETSYMBOL(ap+0, gensym("low_speed")); -#ifdef HAVE_CWIID_MOTIONPLUS_LOWSPEED - phi_speed = mesg->low_speed[CWIID_PHI]; - theta_speed= mesg->low_speed[CWIID_THETA]; - psi_speed = mesg->low_speed[CWIID_PSI]; -#endif - SETFLOAT (ap+1, phi_speed); - SETFLOAT (ap+2, theta_speed); - SETFLOAT (ap+3, psi_speed); - outlet_anything(x->outlet_data, gensym("motionplus"), 4, ap); - - - SETSYMBOL(ap+0, gensym("angle_rate")); - SETFLOAT (ap+1, phi); - SETFLOAT (ap+2, theta); - SETFLOAT (ap+3, psi); - outlet_anything(x->outlet_data, gensym("motionplus"), 4, ap); -} -#endif - - - -static void wiiremote_cwiid_message(t_wiiremote *x, union cwiid_mesg mesg) { - switch (mesg.type) { - case CWIID_MESG_STATUS: - wiiremote_cwiid_battery(x, mesg.status_mesg.battery); - switch (mesg.status_mesg.ext_type) { - case CWIID_EXT_NONE: - post("No extension attached"); - break; - case CWIID_EXT_NUNCHUK: - post("Nunchuk extension attached"); - if(cwiid_get_acc_cal(x->wiiremote, CWIID_EXT_NUNCHUK, &x->nc_acc_cal)) { - post("Unable to retrieve nunchuk calibration"); - } else { - post("Retrieved nunchuk calibration: zero=(%02d,%02d,%02d) one=(%02d,%02d,%02d)", - x->nc_acc_cal.zero[CWIID_X], - x->nc_acc_cal.zero[CWIID_Y], - x->nc_acc_cal.zero[CWIID_Z], - x->nc_acc_cal.one [CWIID_X], - x->nc_acc_cal.one [CWIID_Y], - x->nc_acc_cal.one [CWIID_Z]); - } - break; - case CWIID_EXT_CLASSIC: - post("Classic controller attached. There is no support for this yet."); - break; - case CWIID_EXT_BALANCE: - post("Balance controller attached. There is no support for this yet."); - break; - case CWIID_EXT_MOTIONPLUS: - post("MotionPlus controller attached."); - /* no calibration needed for MotionPlus */ - break; - case CWIID_EXT_UNKNOWN: - post("Unknown extension attached"); - break; - default: - post("ext mesg %d unknown", mesg.status_mesg.ext_type); - break; - } - break; - case CWIID_MESG_BTN: - wiiremote_cwiid_btn(x, &mesg.btn_mesg); - break; - case CWIID_MESG_ACC: - wiiremote_cwiid_acc(x, &mesg.acc_mesg); - break; - case CWIID_MESG_IR: - wiiremote_cwiid_ir(x, &mesg.ir_mesg); - break; -#ifdef CWIID_RPT_NUNCHUK - case CWIID_MESG_NUNCHUK: - wiiremote_cwiid_nunchuk(x, &mesg.nunchuk_mesg); - break; -#endif -#ifdef CWIID_RPT_CLASSIC - case CWIID_MESG_CLASSIC: - wiiremote_cwiid_classic(x, &mesg.classic_mesg); - // todo - break; -#endif -#ifdef CWIID_RPT_MOTIONPLUS - case CWIID_MESG_MOTIONPLUS: - wiiremote_cwiid_motionplus(x, &mesg.motionplus_mesg); - break; -#endif -#ifdef CWIID_RPT_BALANCE - case CWIID_MESG_BALANCE: - wiiremote_cwiid_balance(x, &mesg.balance_mesg); - break; -#endif - default: - post("mesg %d unknown", (mesg.type)); - break; - } -} - - -static void print_timestamp(struct timespec*timestamp, struct timespec*reference) { - double t0=timestamp->tv_sec*1000. + (timestamp->tv_nsec) / 1000000.; - double t1=0; - double t=0; - if(reference) { - t1=reference->tv_sec*1000. + (reference->tv_nsec) / 1000000.; - } - - t=t0-t1; - - post("timestamp: %f", (t)); - -} - - -// The CWiid library invokes a callback function whenever events are -// generated by the wiiremote. This function is specified when connecting -// to the wiiremote (in the cwiid_open function). - -// Unfortunately, the mesg struct passed as an argument to the -// callback does not have a pointer to the wiiremote instance, and it -// is thus impossible to know which wiiremote-object has invoked the callback. -// For this case we provide a hard-coded set of wrapper callbacks to -// indicate which Pd wiiremote instance to control. - -// So far I have only checked with one wiiremote - -/*void cwiid_callback(cwiid_wiiremote_t *wiimt, int mesg_count, union cwiid_mesg *mesg[], struct timespec *timestamp) -*/ -static void cwiid_callback(cwiid_wiimote_t *wiiremote, int mesg_count, - union cwiid_mesg mesg_array[], struct timespec *timestamp) -{ - int i; - t_wiiremote *x=NULL; - - static struct timespec*ts=NULL; - if(NULL==ts) { - ts=(struct timespec*)getbytes(sizeof(struct timespec)); - ts->tv_sec =timestamp->tv_sec; - ts->tv_nsec =timestamp->tv_nsec; - } - - if(g_wiiremoteList==NULL||wiiremote==NULL) { - post("no wii's known"); - return; - } - x=getWiiremoteObject(cwiid_get_id(wiiremote)); - if(NULL==x) { - post("no wiiremote loaded: %d%",cwiid_get_id(wiiremote)); - return; - } - - //print_timestamp(timestamp, ts); - for (i=0; i < mesg_count; i++) { - wiiremote_cwiid_message(x, mesg_array[i]); - } -} - -// ============================================================== - -static void wiiremote_status(t_wiiremote *x) -{ - if(x->connected) { - if (cwiid_request_status(x->wiiremote)) { - pd_error(x, "error requesting status message"); - } - } -} - - -static void wiiremote_resetReportMode(t_wiiremote *x) -{ - if (x->connected) { - verbose(1, "changing report mode for Wii%02d to %d", x->wiiremoteID, x->reportMode); - if (cwiid_command(x->wiiremote, CWIID_CMD_RPT_MODE, x->reportMode)) { - post("wiiremote error: problem setting report mode."); - } - } -} - - -static void wiiremote_setReportMode(t_wiiremote *x, t_floatarg r) -{ - if (r >= 0) { - x->reportMode = (int) r; - wiiremote_resetReportMode(x); - } else { - return; - } -} - - -static void wiiremote_report(t_wiiremote*x, int flag, int onoff) -{ - if(onoff) { - x->reportMode |= flag; - } else { - x->reportMode &= ~flag; - } - wiiremote_resetReportMode(x); -} - -static void wiiremote_reportAcceleration(t_wiiremote *x, t_floatarg f) -{ - wiiremote_report(x, CWIID_RPT_ACC, f); -} - -static void wiiremote_reportIR(t_wiiremote *x, t_floatarg f) -{ - wiiremote_report(x, CWIID_RPT_IR, f); -} - -static void wiiremote_reportNunchuk(t_wiiremote *x, t_floatarg f) -{ - wiiremote_report(x, CWIID_RPT_EXT, f); -} - -static void wiiremote_reportMotionplus(t_wiiremote *x, t_floatarg f) -{ -#ifdef CWIID_RPT_MOTIONPLUS - int flag=f; - if (x->connected) { - verbose(1, "changing motionplus report mode for Wii%02d to %d", x->wiiremoteID, flag); - int err=0; - if(flag) { - err=cwiid_enable(x->wiiremote, CWIID_FLAG_MOTIONPLUS); - } else { - err=cwiid_disable(x->wiiremote, CWIID_FLAG_MOTIONPLUS); - } - if(err) { - pd_error(x, "turning %s motionplus returned %d", (flag?"on":"off"), err); - } else { - wiiremote_report(x, CWIID_RPT_MOTIONPLUS, f); - } - } -#endif -} - -static void wiiremote_setRumble(t_wiiremote *x, t_floatarg f) -{ - if (x->connected) - { - if (cwiid_command(x->wiiremote, CWIID_CMD_RUMBLE, f)) post("wiiremote error: problem setting rumble."); - } -} - -static void wiiremote_setLED(t_wiiremote *x, t_floatarg f) -{ - // some possible values: - // CWIID_LED0_ON 0x01 - // CWIID_LED1_ON 0x02 - // CWIID_LED2_ON 0x04 - // CWIID_LED3_ON 0x08 - if (x->connected) - { - if (cwiid_command(x->wiiremote, CWIID_CMD_LED, f)) post("wiiremote error: problem setting LED."); - } -} - - - -// ============================================================== - - -// The following function attempts to connect to a wiiremote at a -// specific address, provided as an argument. eg, 00:19:1D:70:CE:72 -// This address can be discovered by running the following command -// in a console: -// hcitool scan | grep Nintendo - -static void wiiremote_doConnect(t_wiiremote *x, t_symbol *addr, t_symbol *dongaddr) -{ - bdaddr_t bdaddr; - unsigned int flags = CWIID_FLAG_MESG_IFC; - - bdaddr_t dong_bdaddr; - bdaddr_t* dong_bdaddr_ptr=&dong_bdaddr; - - // determine address: - if (NULL==addr || addr==gensym("")) { - post("Searching automatically..."); - bdaddr = *BDADDR_ANY; - } - else { - str2ba(addr->s_name, &bdaddr); - post("Connecting to given address..."); - post("Press buttons 1 and 2 simultaneously."); - } - - // determine dongleaddress: - if (NULL==dongaddr || dongaddr==gensym("")) { - post("Binding automatically..."); - dong_bdaddr_ptr = NULL; - } - else { - str2ba(dongaddr->s_name, &dong_bdaddr); - } - // connect: - - -#if 0 - x->wiiremote = cwiid_open(&bdaddr, dong_bdaddr_ptr, flags); -#else -#warning multi-dongle support... - x->wiiremote = cwiid_open(&bdaddr, flags); -#endif - - if(NULL==x->wiiremote) { - post("wiiremote error: unable to connect"); - return; - } - - if(!addWiiremoteObject(x, cwiid_get_id(x->wiiremote))) { - cwiid_close(x->wiiremote); - x->wiiremote=NULL; - return; - } - - x->wiiremoteID= cwiid_get_id(x->wiiremote); - - post("wiiremote %i is successfully connected", x->wiiremoteID); - - if(cwiid_get_acc_cal(x->wiiremote, CWIID_EXT_NONE, &x->acc_cal)) { - post("Unable to retrieve accelerometer calibration"); - } else { - post("Retrieved wiiremote calibration: zero=(%02d,%02d,%02d) one=(%02d,%02d,%02d)", - x->acc_cal.zero[CWIID_X], - x->acc_cal.zero[CWIID_Y], - x->acc_cal.zero[CWIID_Z], - x->acc_cal.one [CWIID_X], - x->acc_cal.one [CWIID_Y], - x->acc_cal.one [CWIID_Z]); - } - - x->connected = 1; - - x->reportMode |= CWIID_RPT_STATUS; - x->reportMode |= CWIID_RPT_BTN; - wiiremote_resetReportMode(x); - - if (cwiid_set_mesg_callback(x->wiiremote, &cwiid_callback)) { - pd_error(x, "Unable to set message callback"); - } -} - -// The following function attempts to discover a wiiremote. It requires -// that the user puts the wiiremote into 'discoverable' mode before being -// called. This is done by pressing the red button under the battery -// cover, or by pressing buttons 1 and 2 simultaneously. -// TODO: Without pressing the buttons, I get a segmentation error. So far, I don't know why. - -static void wiiremote_discover(t_wiiremote *x) -{ - post("Put the wiiremote into discover mode by pressing buttons 1 and 2 simultaneously."); - - wiiremote_doConnect(x, NULL, gensym("NULL")); - if (!(x->connected)) - { - post("Error: could not find any wiiremotes. Please ensure that bluetooth is enabled, and that the 'hcitool scan' command lists your Nintendo device."); - } -} - -static void wiiremote_doDisconnect(t_wiiremote *x) -{ - - if (x->connected) - { - if (cwiid_close(x->wiiremote)) { - post("wiiremote error: problems when disconnecting."); - } - else { - post("disconnect successfull, resetting values"); - removeWiiremoteObject(x); - x->connected = 0; - } - } - else post("device is not connected"); - -} - - -// ============================================================== -// ============================================================== - -static void *wiiremote_new(t_symbol*s, int argc, t_atom *argv) -{ - t_wiiremote *x = (t_wiiremote *)pd_new(wiiremote_class); - - // create outlets: - x->outlet_data = outlet_new(&x->x_obj, NULL); - - // initialize toggles: - x->connected = 0; - x->wiiremoteID = -1; - - // connect if user provided an address as an argument: - - if (argc==2) - { - post("[%s] connecting to provided address...", s->s_name); - if (argv->a_type == A_SYMBOL) - { - wiiremote_doConnect(x, NULL, atom_getsymbol(argv)); - } else { - error("[wiiremote] expects either no argument, or a bluetooth address as an argument. eg, 00:19:1D:70:CE:72"); - return NULL; - } - } - return (x); -} - - -static void wiiremote_free(t_wiiremote* x) -{ - wiiremote_doDisconnect(x); -} - -void wiiremote_setup(void) -{ - wiiremote_class = class_new(gensym("wiiremote"), (t_newmethod)wiiremote_new, (t_method)wiiremote_free, sizeof(t_wiiremote), CLASS_DEFAULT, A_GIMME, 0); - - class_addmethod(wiiremote_class, (t_method) wiiremote_debug, gensym("debug"), 0); - class_addmethod(wiiremote_class, (t_method) wiiremote_status, gensym("status"), 0); - - - /* connection settings */ - class_addmethod(wiiremote_class, (t_method) wiiremote_doConnect, gensym("connect"), A_DEFSYMBOL, A_DEFSYMBOL, 0); - class_addmethod(wiiremote_class, (t_method) wiiremote_doDisconnect, gensym("disconnect"), 0); - class_addmethod(wiiremote_class, (t_method) wiiremote_discover, gensym("discover"), 0); - - - /* query data */ - class_addmethod(wiiremote_class, (t_method) wiiremote_setReportMode, gensym("setReportMode"), A_DEFFLOAT, 0); - class_addmethod(wiiremote_class, (t_method) wiiremote_reportAcceleration, gensym("reportAcceleration"), A_DEFFLOAT, 0); - class_addmethod(wiiremote_class, (t_method) wiiremote_reportIR, gensym("reportIR"), A_DEFFLOAT, 0); - - class_addmethod(wiiremote_class, (t_method) wiiremote_reportNunchuk, gensym("reportNunchuck"), A_DEFFLOAT, 0); - class_addmethod(wiiremote_class, (t_method) wiiremote_reportNunchuk, gensym("reportNunchuk"), A_DEFFLOAT, 0); - class_addmethod(wiiremote_class, (t_method) wiiremote_reportMotionplus, gensym("reportMotionplus"), A_DEFFLOAT, 0); - - - /* set things on the wiimote */ - class_addmethod(wiiremote_class, (t_method) wiiremote_setRumble, gensym("setRumble"), A_DEFFLOAT, 0); - class_addmethod(wiiremote_class, (t_method) wiiremote_setLED, gensym("setLED"), A_DEFFLOAT, 0); -} - - |