/*
* Copyright 2007-2008 Volker Fritzsch
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package motejx.extensions.nunchuk;
import java.awt.Point;
import javax.swing.event.EventListenerList;
import motej.AbstractExtension;
import motej.Mote;
import motej.event.AccelerometerEvent;
import motej.event.AccelerometerListener;
import motej.event.DataEvent;
import motej.event.DataListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* <p>
*
* @author <a href="mailto:vfritzsch@users.sourceforge.net">Volker Fritzsch</a>
*/
public class Nunchuk extends AbstractExtension implements DataListener {
private EventListenerList listenerList = new EventListenerList();
private Mote mote;
private Logger log = LoggerFactory.getLogger(Nunchuk.class);
private NunchukCalibrationData calibrationData;
/**
* @param listener
*/
public void addAccelerometerListener(AccelerometerListener<Nunchuk> listener) {
listenerList.add(AccelerometerListener.class, listener);
}
/**
* @param listener
*/
public void addAnalogStickListener(AnalogStickListener listener) {
listenerList.add(AnalogStickListener.class, listener);
}
/**
* @param listener
*/
public void addNunchukButtonListener(NunchukButtonListener listener) {
listenerList.add(NunchukButtonListener.class, listener);
}
/*
* (non-Javadoc)
*
* @see motej.event.DataListener#dataRead(motej.event.DataEvent)
*/
public void dataRead(DataEvent evt) {
if (calibrationData == null && evt.getError() == 0
&& evt.getAddress()[0] == 0x00
&& (evt.getAddress()[1] & 0xff) == 0x30
&& evt.getPayload().length == 0x0f) {
log.debug("Calibration Data received.");
byte[] payload = evt.getPayload();
calibrationData = new NunchukCalibrationData();
calibrationData.setZeroForceX(payload[0] & 0xff);
calibrationData.setZeroForceY(payload[1] & 0xff);
calibrationData.setZeroForceZ(payload[2] & 0xff);
calibrationData.setGravityForceX(payload[4] & 0xff);
calibrationData.setGravityForceY(payload[5] & 0xff);
calibrationData.setGravityForceZ(payload[6] & 0xff);
calibrationData.setMinimumAnalogPoint(new Point(payload[9] & 0xff,
payload[12] & 0xff));
calibrationData.setMaximumAnalogPoint(new Point(payload[8] & 0xff,
payload[11] & 0xff));
calibrationData.setCenterAnalogPoint(new Point(payload[10] & 0xff,
payload[13] & 0xff));
}
}
/**
* @param data
*/
@SuppressWarnings("unchecked")
protected void fireAccelerometerEvent(byte[] data) {
AccelerometerListener<Nunchuk>[] listeners = listenerList
.getListeners(AccelerometerListener.class);
if (listeners.length == 0) {
return;
}
// remark: I am currently ignoring the LSB as I do with the LSB of the
// calibration data.
// if someone comes up with reliable data, we'll add it, i promise.
int ax = ((data[2] & 0xff)); // << 2) ^ (data[5] & 0x0c);
int ay = ((data[3] & 0xff)); // << 2) ^ (data[5] & 0x30);
int az = ((data[4] & 0xff)); // << 2) ^ (data[5] & 0xc0);
AccelerometerEvent<Nunchuk> evt = new AccelerometerEvent<Nunchuk>(this,
ax, ay, az);
for (AccelerometerListener<Nunchuk> l : listeners) {
l.accelerometerChanged(evt);
}
}
protected void fireAnalogStickEvent(byte[] data) {
AnalogStickListener[] listeners = listenerList
.getListeners(AnalogStickListener.class);
if (listeners.length == 0) {
return;
}
int sx = data[0] & 0xff;
int sy = data[1] & 0xff;
AnalogStickEvent evt = new AnalogStickEvent(this, new Point(sx & 0xff,
sy & 0xff));
for (AnalogStickListener l : listeners) {
l.analogStickChanged(evt);
}
}
protected void fireButtonEvent(byte[] data) {
NunchukButtonListener[] listeners = listenerList
.getListeners(NunchukButtonListener.class);
if (listeners.length == 0) {
return;
}
// we invert the original data as the wiimote returns
// button pressed as nil and thats not that useable.
int modifiers = (data[5] & 0x03) ^ 0x03;
NunchukButtonEvent evt = new NunchukButtonEvent(this, modifiers);
for (NunchukButtonListener l : listeners) {
l.buttonPressed(evt);
}
}
/**
* @return
*/
public NunchukCalibrationData getCalibrationData() {
return calibrationData;
}
/**
* @return
*/
public Mote getMote() {
return mote;
}
/*
* (non-Javadoc)
*
* @see motej.Extension#initialize()
*/
public void initialize() {
mote.addDataListener(this);
// initialize
mote.writeRegisters(new byte[] { (byte) 0xa4, 0x00, 0x40}, new byte[] { 0x00 });
// request calibration data
mote.readRegisters(new byte[] { (byte) 0xa4, 0x00, 0x30 }, new byte[] {
0x00, 0x0f });
}
/*
* (non-Javadoc)
*
* @see motej.Extension#parseExtensionData(byte[])
*/
public void parseExtensionData(byte[] extensionData) {
decrypt(extensionData);
fireAnalogStickEvent(extensionData);
fireAccelerometerEvent(extensionData);
fireButtonEvent(extensionData);
}
/**
* @param listener
*/
public void removeAccelerometerListener(
AccelerometerListener<Nunchuk> listener) {
listenerList.remove(AccelerometerListener.class, listener);
}
/**
* @param listener
*/
public void removeAnalogStickListener(AnalogStickListener listener) {
listenerList.remove(AnalogStickListener.class, listener);
}
/**
* @param listener
*/
public void removeNunchukButtonListener(NunchukButtonListener listener) {
listenerList.remove(NunchukButtonListener.class, listener);
}
/*
* (non-Javadoc)
*
* @see motej.Extension#setMote(motej.Mote)
*/
public void setMote(Mote mote) {
this.mote = mote;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "Nunchuk";
}
}