aboutsummaryrefslogtreecommitdiffstats
path: root/Java/com/phidgets/MotorControlPhidget.java
blob: 8539b9876ea08e5105e6c80466289290880ca620 (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
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
/*
 * Copyright 2011 Phidgets Inc.  All rights reserved.
 */

package com.phidgets;
import java.util.Iterator;
import java.util.LinkedList;
import com.phidgets.event.*;
/**
 * This class represents a Phidget Motor Controller. All Methods
 * to to control a motor controller and read back motor data are implemented in this class.
 <p>
 The Motor Control Phidget is able to control 1 or more DC motors. 
 Both speed and acceleration are controllable. Speed is controlled via PWM. The size of the motors
 that can be driven depends on the motor controller. See your hardware documentation for more information.
 <p>
 The motor Controller boards also has 0 or more digital inputs.
 * 
 * @author Phidgets Inc.
 */
public final class MotorControlPhidget extends Phidget
{
	public MotorControlPhidget () throws PhidgetException
	{
		super (create ());
	}
	private static native long create () throws PhidgetException;

	/**
	 * Returns the number of motors supported by this Phidget. This does not neccesarily correspond
	 to the number of motors actually attached to the board.
	 * @return number of supported motors
	 * @throws PhidgetException If this Phidget is not opened and attached. 
	 * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
	 */
	public native int getMotorCount () throws PhidgetException;
	/**
	 * Returns the number of digital inputs. Not all Motor Controllers have digital inputs.
	 * @return number of digital inputs
	 * @throws PhidgetException If this Phidget is not opened and attached. 
	 * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
	 */
	public native int getInputCount () throws PhidgetException;
	/**
	 * Returns the number of encoders. Not all Motor Controllers have encoders.
	 * @return number of encoders
	 * @throws PhidgetException If this Phidget is not opened and attached. 
	 * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
	 */
	public native int getEncoderCount () throws PhidgetException;
	/**
	 * Returns the number of analog inputs. Not all Motor Controllers have analog inputs.
	 * @return number of analog inputs
	 * @throws PhidgetException If this Phidget is not opened and attached. 
	 * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
	 */
	public native int getSensorCount () throws PhidgetException;
	/**
	 * Returns the state of a digital input. True means that the input is activated, and False indicates the default state.
	 * @param index index of the input
	 * @return state of the input
	 * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid. 
	 * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
	 */
	public native boolean getInputState (int index) throws PhidgetException;
	/**
	 * Returns the position of an encoder. This is an absolute position as calcutated since the encoder was plugged in.
	 This value can be reset to anything using {@link #setEncoderPosition(int, int) setEncoderPosition}.  Not all Motor Controllers have encoders.

	 * @param index index of the encoder
	 * @return position of the encoder
	 * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range. 
	 * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
	 */
	public native int getEncoderPosition (int index) throws PhidgetException;
	/**
	 * Sets the position of a specific encoder. This resets the internal position count for an encoder. This call in no way actually 
	 sends information to the device, as an absolute position is maintained only in the library. After this call, position changes
	 from the encoder will use the new value to calculate absolute position as reported by {@link #getEncoderPosition}. Not all Motor Controllers have encoders.
	 * @param index index of the encoder
	 * @param position new position for a encoder.
	 * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range. 
	 * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
	 */
	public native void setEncoderPosition (int index, int position) throws PhidgetException;
	/**
	 * Returns the value of a sensor. Not all Motor Controllers have analog sensors.
	 * @param index index of the sensor
	 * @return sensor value of the sensor. Range is 0-1000.
	 * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range. 
	 * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
	 */
	public native int getSensorValue (int index) throws PhidgetException;
	/**
	 * Returns the raw value of a sensor(12-bit). Not all Motor Controllers have analog sensors.
	 * @param index index of the sensor
	 * @return sensor raw value of the sensor. Range is 0-4096.
	 * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range. 
	 * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
	 */
	public native int getSensorRawValue (int index) throws PhidgetException;
	/**
	 * Returns the ratiometric state of a sensor. Not all Motor Controllers have analog sensors.
	 * @return ratiometric state of sensors
	 * @throws PhidgetException If this Phidget is not opened and attached.
	 * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
	 */
	public native boolean getRatiometric () throws PhidgetException;
	/**
	 * Sets the ratiometric state. This controls the voltage reference used for sampling the analog sensors. 
	 * @param ratiometric new ratiometric state of the sensors
	 * @throws PhidgetException If this Phidget is not opened and attached.
	 * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
	 */
	public native void setRatiometric (boolean ratiometric) throws PhidgetException;
	/**
	 * Returns a motor's acceleration. The valid range is between {@link #getAccelerationMin getAccelerationMin} and {@link #getAccelerationMax getAccelerationMax}, and refers to how fast the Motor Controller
	 will change the speed of a motor.
	 * @param index Index of motor
	 * @return acceleration of motor
	 * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid. 
	 * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
	 */
	public native double getAcceleration (int index) throws PhidgetException;
	/**
	 * Sets a motor's acceleration. 
	 * The valid range is between {@link #getAccelerationMin getAccelerationMin} and {@link #getAccelerationMax getAccelerationMax}. This controls how fast the motor changes speed.
	 * @param index index of the motor
	 * @param acceleration requested acceleration for that motor
	 * @throws PhidgetException If this Phidget is not opened and attached, or if the index or acceleration value are invalid. 
	 * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
	 */
	public native void setAcceleration (int index, double acceleration) throws PhidgetException;
	/**
	 * Returns the maximum acceleration that a motor will accept, or return.
	 * @param index Index of the motor
	 * @return Maximum acceleration
	 * @throws PhidgetException If this Phidget is not opened and attached.
	 * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
	 */
	public native double getAccelerationMax (int index) throws PhidgetException;
	/**
	 * Returns the minimum acceleration that a motor will accept, or return.
	 * @param index Index of the motor
	 * @return Minimum acceleration
	 * @throws PhidgetException If this Phidget is not opened and attached.
	 * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
	 */
	public native double getAccelerationMin (int index) throws PhidgetException;
	/**
	 * Returns a motor's velocity. The valid range is -100 - 100, with 0 being stopped.
	 * @param index index of the motor
	 * @return current velocity of the motor
	 * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid. 
	 * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
	 */
	public native double getVelocity (int index) throws PhidgetException;
	/**
	 * @deprecated  Replaced by
	 *              {@link #getVelocity}
	 */
	public native double getSpeed (int index) throws PhidgetException;
	/**
	 * Sets a motor's velocity.
	 * The valid range is from -100 to 100, with 0 being stopped. -100 and 100 both correspond to full voltage,
	 with the value in between corresponding to different widths of PWM.
	 * @param index index of the motor
	 * @param velocity requested velocity for the motor
	 * @throws PhidgetException If this Phidget is not opened and attached, or if the index or speed value are invalid. 
	 * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
	 */
	public native void setVelocity (int index, double velocity) throws PhidgetException;
	/**
	 * @deprecated  Replaced by
	 *              {@link #setVelocity}
	 */
	public native void setSpeed (int index, double speed) throws PhidgetException;
	/**
	 * Returns a motor's current usage. The valid range is 0 - 255. Note that this is not supported on all motor controllers.
	 * @param index index of the motor
	 * @return current usage of the motor
	 * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid. 
	 * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
	 */
	public native double getCurrent (int index) throws PhidgetException;
	/**
	 * Returns the Back EMF sensing state for a specific motor. Note that this is not supported on all motor controllers.
	 * @param index Index of the motor
	 * @return Back EMF Sensing state for the motor
	 * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid. 
	 * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
	 */
	public native boolean getBackEMFSensingState (int index) throws PhidgetException;
	/**
	 * Sets the Back EMF sensing state for a specific motor. Note that this is not supported on all motor controllers.
	 * @param index Index of the motor
	 * @param bEMFState new Back EMF Sensing State
	 * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid. 
	 * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
	 */
	public native void setBackEMFSensingState (int index, boolean bEMFState) throws PhidgetException;
	/**
	 * Sets the Back EMF voltage for a specific motor. Note that this is not supported on all motor controllers.
	 * @param index Index of the motor
	 * @return Back EMF voltage of the motor
	 * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid. 
	 * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
	 */
	public native double getBackEMF (int index) throws PhidgetException;
	/**
	 * Sets the supply voltage for the motors. This could be  higher than the actual voltage. Note that this is not supported on all motor controllers.
	 * @return Supply voltage of the motor, in volts
	 * @throws PhidgetException If this Phidget is not opened and attached, the index is invalid, or if {@link #setBackEMFSensingState setBackEMFSensingState} is not set.
	 * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
	 */
	public native double getSupplyVoltage () throws PhidgetException;
	/**
	 * Returns the braking value for a specific motor. Note that this is not supported on all motor controllers.
	 * @param index index of the motor
	 * @return Braking value for the motor
	 * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid. 
	 * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
	 */
	public native double getBraking (int index) throws PhidgetException;
	/**
	 * Sets the braking value for a specific motor. This is applied when velocity is 0. Default is 0%. Note that this is not supported on all motor controllers. Range is 0-100.
	 * @param index index of the motor
	 * @param braking new braking value for a specific motor
	 * @throws PhidgetException If this Phidget is not opened and attached, the index is invalid, or the brake value is invalid 
	 * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
	 */
	public native void setBraking (int index, double braking) throws PhidgetException;

	private final void enableDeviceSpecificEvents (boolean b)
	{
		enableMotorVelocityChangeEvents (b && motorVelocityChangeListeners.size () > 0);
		enableCurrentChangeEvents (b && currentChangeListeners.size () > 0);
		enableCurrentUpdateEvents (b && currentUpdateListeners.size () > 0);
		enableInputChangeEvents (b && inputChangeListeners.size () > 0);
		enableEncoderPositionChangeEvents (b && encoderPositionChangeListeners.size () > 0);
		enableEncoderPositionUpdateEvents (b && encoderPositionUpdateListeners.size () > 0);
		enableBackEMFUpdateEvents (b && backEMFUpdateListeners.size () > 0);
		enableSensorUpdateEvents (b && sensorUpdateListeners.size () > 0);
	}
	/**
	 * Adds a velocity change listener. The velocity change handler is a method that will be called when the velocity
	 of a motor changes. These velocity changes are reported back from the Motor Controller and so correspond to actual motor speeds
	 over time.
	 * <p>
	 * There is no limit on the number of velocity change handlers that can be registered for a particular Phidget.
	 * 
	 * @param l An implemetation of the {@link com.phidgets.event.MotorVelocityChangeListener MotorVelocityChangeListener} interface
	 */
	public final void addMotorVelocityChangeListener (MotorVelocityChangeListener l)
	{
		synchronized (motorVelocityChangeListeners)
		{
			motorVelocityChangeListeners.add (l);
			enableMotorVelocityChangeEvents (true);
	}} private LinkedList motorVelocityChangeListeners = new LinkedList ();
	private long nativeMotorVelocityChangeHandler = 0;
	public final void removeMotorVelocityChangeListener (MotorVelocityChangeListener l)
	{
		synchronized (motorVelocityChangeListeners)
		{
			motorVelocityChangeListeners.remove (l);
			enableMotorVelocityChangeEvents (motorVelocityChangeListeners.size () > 0);
	}} private void fireMotorVelocityChange (MotorVelocityChangeEvent e)
	{
		synchronized (motorVelocityChangeListeners)
		{
			for (Iterator it = motorVelocityChangeListeners.iterator (); it.hasNext ();)
				((MotorVelocityChangeListener) it.next ()).motorVelocityChanged (e);
		}
	}
	private native void enableMotorVelocityChangeEvents (boolean b);
	/**
	 * Adds a current change listener. The current change handler is a method that will be called when the current
	 consumed by a motor changes. Note that this event is not supported with the current motor controller, but
	 will be supported in the future
	 * <p>
	 * There is no limit on the number of current change handlers that can be registered for a particular Phidget.
	 * 
	 * @param l An implemetation of the {@link com.phidgets.event.CurrentChangeListener CurrentChangeListener} interface
	 */
	public final void addCurrentChangeListener (CurrentChangeListener l)
	{
		synchronized (currentChangeListeners)
		{
			currentChangeListeners.add (l);
			enableCurrentChangeEvents (true);
	}} private LinkedList currentChangeListeners = new LinkedList ();
	private long nativeCurrentChangeHandler = 0;
	public final void removeCurrentChangeListener (CurrentChangeListener l)
	{
		synchronized (currentChangeListeners)
		{
			currentChangeListeners.remove (l);
			enableCurrentChangeEvents (currentChangeListeners.size () > 0);
	}} private void fireCurrentChange (CurrentChangeEvent e)
	{
		synchronized (currentChangeListeners)
		{
			for (Iterator it = currentChangeListeners.iterator (); it.hasNext ();)
				((CurrentChangeListener) it.next ()).currentChanged (e);
		}
	}
	private native void enableCurrentChangeEvents (boolean b);
	/**
	 * Adds a current update listener. The current change handler is a method that will be called every 8ms, regardless whether the current
	 consumed by a motor changes. Note that this event is not supported with all motor controllers
	 * <p>
	 * There is no limit on the number of current update handlers that can be registered for a particular Phidget.
	 * 
	 * @param l An implemetation of the {@link com.phidgets.event.CurrentUpdateListener CurrentUpdateListener} interface
	 */
	public final void addCurrentUpdateListener (CurrentUpdateListener l)
	{
		synchronized (currentUpdateListeners)
		{
			currentUpdateListeners.add (l);
			enableCurrentUpdateEvents (true);
	}} private LinkedList currentUpdateListeners = new LinkedList ();
	private long nativeCurrentUpdateHandler = 0;
	public final void removeCurrentUpdateListener (CurrentUpdateListener l)
	{
		synchronized (currentUpdateListeners)
		{
			currentUpdateListeners.remove (l);
			enableCurrentUpdateEvents (currentUpdateListeners.size () > 0);
	}} private void fireCurrentUpdate (CurrentUpdateEvent e)
	{
		synchronized (currentUpdateListeners)
		{
			for (Iterator it = currentUpdateListeners.iterator (); it.hasNext ();)
				((CurrentUpdateListener) it.next ()).currentUpdated (e);
		}
	}
	private native void enableCurrentUpdateEvents (boolean b);
	/**
	 * Adds an input change listener. The input change handler is a method that will be called when an input on this
	 * Motor Controller board has changed.
	 * <p>
	 * There is no limit on the number of input change handlers that can be registered for a particular Phidget.
	 * 
	 * @param l An implemetation of the {@link com.phidgets.event.InputChangeListener InputChangeListener} interface
	 */
	public final void addInputChangeListener (InputChangeListener l)
	{
		synchronized (inputChangeListeners)
		{
			inputChangeListeners.add (l);
			enableInputChangeEvents (true);
	}} private LinkedList inputChangeListeners = new LinkedList ();
	private long nativeInputChangeHandler = 0;
	public final void removeInputChangeListener (InputChangeListener l)
	{
		synchronized (inputChangeListeners)
		{
			inputChangeListeners.remove (l);
			enableInputChangeEvents (inputChangeListeners.size () > 0);
	}} private void fireInputChange (InputChangeEvent e)
	{
		synchronized (inputChangeListeners)
		{
			for (Iterator it = inputChangeListeners.iterator (); it.hasNext ();)
				((InputChangeListener) it.next ()).inputChanged (e);
		}
	}
	private native void enableInputChangeEvents (boolean b);
	/**
	 * Adds a position change listener. The position change handler is a method that will be called when the position of an 
	 encoder changes. The position change event provides data about how many ticks have occured, and how much time has
	 passed since the last position change event, but does not contain an absolute position. This can be obtained from
	 {@link #getEncoderPosition}.
	 * <p>
	 * There is no limit on the number of encoder position change handlers that can be registered for a particular Phidget.
	 * 
	 * @param l An implemetation of the {@link com.phidgets.event.EncoderPositionChangeListener EncoderPositionChangeListener} interface
	 */
	public final void addEncoderPositionChangeListener (EncoderPositionChangeListener l)
	{
		synchronized (encoderPositionChangeListeners)
		{
			encoderPositionChangeListeners.add (l);
			enableEncoderPositionChangeEvents (true);
	}} private LinkedList encoderPositionChangeListeners = new LinkedList ();
	private long nativeEncoderPositionChangeHandler = 0;
	public final void removeEncoderPositionChangeListener (EncoderPositionChangeListener l)
	{
		synchronized (encoderPositionChangeListeners)
		{
			encoderPositionChangeListeners.remove (l);
			enableEncoderPositionChangeEvents (encoderPositionChangeListeners.size () > 0);
	}} private void fireEncoderPositionChange (EncoderPositionChangeEvent e)
	{
		synchronized (encoderPositionChangeListeners)
		{
			for (Iterator it = encoderPositionChangeListeners.iterator (); it.hasNext ();)
				((EncoderPositionChangeListener) it.next ()).encoderPositionChanged (e);
		}
	}
	private native void enableEncoderPositionChangeEvents (boolean b);
	/**
	 * Adds a position update listener. The position update handler is a method that will be called at a constant rate; every 8ms, whether the encoder position has changed or not. 
	 * The position update event provides data about how many ticks have occured since the last position update event, but does not contain an absolute position. This can be obtained from
	 *{@link #getEncoderPosition}.
	 * <p>
	 * There is no limit on the number of encoder position update handlers that can be registered for a particular Phidget.
	 * 
	 * @param l An implemetation of the {@link com.phidgets.event.EncoderPositionUpdateListener EncoderPositionUpdateListener} interface
	 */
	public final void addEncoderPositionUpdateListener (EncoderPositionUpdateListener l)
	{
		synchronized (encoderPositionUpdateListeners)
		{
			encoderPositionUpdateListeners.add (l);
			enableEncoderPositionUpdateEvents (true);
	}} private LinkedList encoderPositionUpdateListeners = new LinkedList ();
	private long nativeEncoderPositionUpdateHandler = 0;
	public final void removeEncoderPositionUpdateListener (EncoderPositionUpdateListener l)
	{
		synchronized (encoderPositionUpdateListeners)
		{
			encoderPositionUpdateListeners.remove (l);
			enableEncoderPositionUpdateEvents (encoderPositionUpdateListeners.size () > 0);
	}} private void fireEncoderPositionUpdate (EncoderPositionUpdateEvent e)
	{
		synchronized (encoderPositionUpdateListeners)
		{
			for (Iterator it = encoderPositionUpdateListeners.iterator (); it.hasNext ();)
				((EncoderPositionUpdateListener) it.next ()).encoderPositionUpdated (e);
		}
	}
	private native void enableEncoderPositionUpdateEvents (boolean b);
	/**
	 * Adds a Back EMF update listener. The Back EMF update handler is a method that will be called at a constant rate; every 8ms, whether the Back EMF value has changed or not. 
	 * <p>
	 * There is no limit on the number of Back EMF update handlers that can be registered for a particular Phidget.
	 * 
	 * @param l An implemetation of the {@link com.phidgets.event.BackEMFUpdateListener BackEMFUpdateListener} interface
	 */
	public final void addBackEMFUpdateListener (BackEMFUpdateListener l)
	{
		synchronized (backEMFUpdateListeners)
		{
			backEMFUpdateListeners.add (l);
			enableBackEMFUpdateEvents (true);
	}} private LinkedList backEMFUpdateListeners = new LinkedList ();
	private long nativeBackEMFUpdateHandler = 0;
	public final void removeBackEMFUpdateListener (BackEMFUpdateListener l)
	{
		synchronized (backEMFUpdateListeners)
		{
			backEMFUpdateListeners.remove (l);
			enableBackEMFUpdateEvents (backEMFUpdateListeners.size () > 0);
	}} private void fireBackEMFUpdate (BackEMFUpdateEvent e)
	{
		synchronized (backEMFUpdateListeners)
		{
			for (Iterator it = backEMFUpdateListeners.iterator (); it.hasNext ();)
				((BackEMFUpdateListener) it.next ()).backEMFUpdated (e);
		}
	}
	private native void enableBackEMFUpdateEvents (boolean b);
	/**
	 * Adds a sensor update listener. The sensor update handler is a method that will be called at a constant rate; every 8ms, whether the sensor value has changed or not. 
	 * <p>
	 * There is no limit on the number of sensor update handlers that can be registered for a particular Phidget.
	 * 
	 * @param l An implemetation of the {@link com.phidgets.event.SensorUpdateListener SensorUpdateListener} interface
	 */
	public final void addSensorUpdateListener (SensorUpdateListener l)
	{
		synchronized (sensorUpdateListeners)
		{
			sensorUpdateListeners.add (l);
			enableSensorUpdateEvents (true);
	}} private LinkedList sensorUpdateListeners = new LinkedList ();
	private long nativeSensorUpdateHandler = 0;
	public final void removeSensorUpdateListener (SensorUpdateListener l)
	{
		synchronized (sensorUpdateListeners)
		{
			sensorUpdateListeners.remove (l);
			enableSensorUpdateEvents (sensorUpdateListeners.size () > 0);
	}} private void fireSensorUpdate (SensorUpdateEvent e)
	{
		synchronized (sensorUpdateListeners)
		{
			for (Iterator it = sensorUpdateListeners.iterator (); it.hasNext ();)
				((SensorUpdateListener) it.next ()).sensorUpdated (e);
		}
	}
	private native void enableSensorUpdateEvents (boolean b);
}