aboutsummaryrefslogtreecommitdiff
path: root/site/udo/wiimote.udo
blob: 474d2babb55e1a56103fef3668bc94ca08fef69e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
#ifndef UDO_WIIMOTE
#define UDO_WIIMOTE ##
/*
	Wiimote interface

	This file is part of the SONICS UDO collection by Richard Knight 2022
		License: GPL-2.0-or-later
		http://1bpm.net
*/

#include "interop.udo"

; button bit masks
#define WII_1 #2#
#define WII_2 #1#
#define WII_A #8#
#define WII_B #4#
#define WII_HOME #128#
#define WII_MINUS #16#
#define WII_PLUS #4096#
#define WII_LEFT #256#
#define WII_RIGHT #512#
#define WII_UP #2048#
#define WII_DOWN #1024#


; everything goes to globals when connected
gkwii_pitch init 0
gkwii_roll init 0
gkwii_accelX init 0
gkwii_accelY init 0
gkwii_accelZ init 0
gkwii_buttons init 0


#ifdef USE_WIIMOTE_NUNCHUCK
#define WII_Z #-33#
#define WII_C #-34#

gkwii_ncang init 0
gkwii_ncmag init 0
gkwii_ncpitch init 0
gkwii_ncroll init 0
#end


/*
	Get the state of a wiimote button

	kstate wii_button ibutton
	
	kstate		1 if pressed/held or 0 if not
	ibutton 	the bit mask of the button; use the macros defined
*/
opcode wii_button, k, i
	ibutton xin
	if (ibutton < 0) then ; nunchuck buttons not captured by wiidata(0)
		ibutton abs ibutton
		kvalue = wiidata(ibutton)
	else
		kvalue = (gkwii_buttons & ibutton == ibutton) ? 1 : 0
	endif
	xout kvalue
endop



/*
	Keep an instrument on for as long as a wiimote button is held

	wii_buttonhold ibutton, Sinstrument 

	ibutton 		the bit mask of the button; use the macros defined
	Sinstrument		instrument name to start/stop accordingly
*/
opcode wii_buttonhold, 0, iS
	ibutton, Sinstrument xin
	kbut = wii_button(ibutton)
	if (changed:k(kbut) == 1) then
		if (kbut == 1) then
			schedulek(Sinstrument, 0, 999999) ; longnum here as -1 not good for p3
		else
			turnoff2(Sinstrument, 0, 1)
		endif
	endif
endop


opcode wii_buttonhold, 0, iSi
	ibutton, Sinstrument, ip4 xin
	kbut = wii_button(ibutton)
	if (changed:k(kbut) == 1) then
		if (kbut == 1) then
			schedulek(Sinstrument, 0, -1, ip4)
		else
			turnoff2(Sinstrument, 0, 1)
		endif
	endif
endop

/*
	Use the wiimote minus and plus buttons to scroll through item indexes

	kitem wii_pager imaxitems [, iteminitial=0, ksetindex=-1]

	kitem			the selected item/page
	imaxindex		maximum number of items
	initialindex	initial value
	ksetindex		set the item index directly with this
*/
opcode wii_pager, k, ioJ
	imaxindex, initialindex, ksetindex xin
	kcurrentitem init initialindex

	kplus = wii_button($WII_PLUS)
	kminus = wii_button($WII_MINUS)
	if (kminus == 1 && changed:k(kminus) == 1) then
		if (kcurrentitem == 0) then
			kcurrentitem = imaxindex
		else
			kcurrentitem -= 1
		endif
	elseif (kplus == 1 && changed:k(kplus) == 1) then
		if (kcurrentitem == imaxindex) then
			kcurrentitem = 0
		else
			kcurrentitem += 1
		endif
	elseif (changed:k(ksetindex) == 1) then
		if (ksetindex >= 0 && ksetindex <= imaxindex) then
			kcurrentitem = ksetindex
		endif
	endif
	xout kcurrentitem
endop


instr wii_reset
	gkwii_pitch = 0
	gkwii_roll = 0
	gkwii_accelX = 0
	gkwii_accelY = 0
	gkwii_accelZ = 0
	gkwii_buttons = 0
#ifdef USE_WIIMOTE_NUNCHUCK
	gkwii_ncang init 0
	gkwii_ncmag init 0
	gkwii_ncpitch init 0
	gkwii_ncroll init 0
#end
	turnoff
endin

instr _wii_handler_watchdog
	icbid = p4
	SonFail = p5
	kmetro metro 0.5
	if (kmetro == 1) then
		if (active:k("wii_handler") == 0) then
			schedulek(SonFail, 0, -1, icbid)
			turnoff
		endif
	endif
endin


instr _wii_handler_default_fail
	icbid = p4
	schedule("wii_reset", 0, 1)
	io_sendstring("callback", sprintf("{\"cbid\": %d, \"success\": false}", icbid))
	turnoff
endin

/*
	Connect wiimote and set global variables from it
*/
instr wii_handler
	icbid = p4
	SonComplete = strget(p5)
	SonFailWatchdog = strget(p6)
	iconnecttimeout = (p7 == 0) ? 1 : p7

	if (strcmp(SonFailWatchdog, "") == 0) then
		SonFailWatchdog = "_wii_handler_default_fail"
	endif
	schedule("_wii_handler_watchdog", 0, p3, icbid, SonFailWatchdog)

	iwiisuccess wiiconnect iconnecttimeout, 1
	
	if (icbid > 0) then
		io_sendstring("callback", sprintf("{\"cbid\": %d, \"success\": %s}", icbid, (iwiisuccess == 1) ? "true" : "false"))
	endif
	
	if (iwiisuccess == 0) then
		turnoff
	endif

	if (strcmp(SonComplete, "") != 0) then
		schedule(SonComplete, 0, -1)
	endif

	;gkwii_battery = wiidata(27)
	;printk2 gkwii_battery

	; set range of pitch and roll as 0 to 1
	wiirange 20, 0, 1
	wiirange 21, 0, 1

	gkwii_accelX = wiidata(23) ;/ 5 ;abs:k(wiidata(23)) / 5
	gkwii_accelY = wiidata(24) / 5 ;abs:k(wiidata(24)) / 5
	gkwii_accelZ = wiidata(25) / 5 ;abs:k(wiidata(25)) / 5
	gkwii_pitch = wiidata(20)
	gkwii_roll = wiidata(21)
	gkwii_buttons = wiidata(0) ; bit pattern

#ifdef USE_WIIMOTE_NUNCHUCK
	wiirange 30, 0, 1
	wiirange 31, 0, 1
	gkwii_ncang = wiidata(28) / 360
	gkwii_ncmag = wiidata(29) / 1.2
	gkwii_ncpitch = wiidata(30)
	gkwii_ncroll = wiidata(31)
#end

endin

#end