View Javadoc

1   /*
2    * Copyright 2007-2008 Volker Fritzsch
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License. 
15   */
16  package motejx.extensions.nunchuk;
17  
18  import java.awt.Point;
19  
20  import javax.swing.event.EventListenerList;
21  
22  import motej.AbstractExtension;
23  import motej.Mote;
24  import motej.event.AccelerometerEvent;
25  import motej.event.AccelerometerListener;
26  import motej.event.DataEvent;
27  import motej.event.DataListener;
28  
29  import org.slf4j.Logger;
30  import org.slf4j.LoggerFactory;
31  
32  /**
33   * 
34   * <p>
35   * 
36   * @author <a href="mailto:vfritzsch@users.sourceforge.net">Volker Fritzsch</a>
37   */
38  public class Nunchuk extends AbstractExtension implements DataListener {
39  
40  	private EventListenerList listenerList = new EventListenerList();
41  
42  	private Mote mote;
43  
44  	private Logger log = LoggerFactory.getLogger(Nunchuk.class);
45  
46  	private NunchukCalibrationData calibrationData;
47  
48  	/**
49  	 * @param listener
50  	 */
51  	public void addAccelerometerListener(AccelerometerListener<Nunchuk> listener) {
52  		listenerList.add(AccelerometerListener.class, listener);
53  	}
54  
55  	/**
56  	 * @param listener
57  	 */
58  	public void addAnalogStickListener(AnalogStickListener listener) {
59  		listenerList.add(AnalogStickListener.class, listener);
60  	}
61  
62  	/**
63  	 * @param listener
64  	 */
65  	public void addNunchukButtonListener(NunchukButtonListener listener) {
66  		listenerList.add(NunchukButtonListener.class, listener);
67  	}
68  
69  	/*
70  	 * (non-Javadoc)
71  	 * 
72  	 * @see motej.event.DataListener#dataRead(motej.event.DataEvent)
73  	 */
74  	public void dataRead(DataEvent evt) {
75  		if (calibrationData == null && evt.getError() == 0
76  				&& evt.getAddress()[0] == 0x00
77  				&& (evt.getAddress()[1] & 0xff) == 0x30
78  				&& evt.getPayload().length == 0x0f) {
79  
80  			log.debug("Calibration Data received.");
81  
82  			byte[] payload = evt.getPayload();
83  
84  			calibrationData = new NunchukCalibrationData();
85  			calibrationData.setZeroForceX(payload[0] & 0xff);
86  			calibrationData.setZeroForceY(payload[1] & 0xff);
87  			calibrationData.setZeroForceZ(payload[2] & 0xff);
88  			calibrationData.setGravityForceX(payload[4] & 0xff);
89  			calibrationData.setGravityForceY(payload[5] & 0xff);
90  			calibrationData.setGravityForceZ(payload[6] & 0xff);
91  			calibrationData.setMinimumAnalogPoint(new Point(payload[9] & 0xff,
92  					payload[12] & 0xff));
93  			calibrationData.setMaximumAnalogPoint(new Point(payload[8] & 0xff,
94  					payload[11] & 0xff));
95  			calibrationData.setCenterAnalogPoint(new Point(payload[10] & 0xff,
96  					payload[13] & 0xff));
97  		}
98  	}
99  
100 	/**
101 	 * @param data
102 	 */
103 	@SuppressWarnings("unchecked")
104 	protected void fireAccelerometerEvent(byte[] data) {
105 		AccelerometerListener<Nunchuk>[] listeners = listenerList
106 				.getListeners(AccelerometerListener.class);
107 		if (listeners.length == 0) {
108 			return;
109 		}
110 
111 		// remark: I am currently ignoring the LSB as I do with the LSB of the
112 		// calibration data.
113 		// if someone comes up with reliable data, we'll add it, i promise.
114 		int ax = ((data[2] & 0xff)); // << 2) ^ (data[5] & 0x0c);
115 		int ay = ((data[3] & 0xff)); // << 2) ^ (data[5] & 0x30);
116 		int az = ((data[4] & 0xff)); // << 2) ^ (data[5] & 0xc0);
117 		AccelerometerEvent<Nunchuk> evt = new AccelerometerEvent<Nunchuk>(this,
118 				ax, ay, az);
119 		for (AccelerometerListener<Nunchuk> l : listeners) {
120 			l.accelerometerChanged(evt);
121 		}
122 	}
123 
124 	protected void fireAnalogStickEvent(byte[] data) {
125 		AnalogStickListener[] listeners = listenerList
126 				.getListeners(AnalogStickListener.class);
127 		if (listeners.length == 0) {
128 			return;
129 		}
130 
131 		int sx = data[0] & 0xff;
132 		int sy = data[1] & 0xff;
133 		AnalogStickEvent evt = new AnalogStickEvent(this, new Point(sx & 0xff,
134 				sy & 0xff));
135 		for (AnalogStickListener l : listeners) {
136 			l.analogStickChanged(evt);
137 		}
138 	}
139 
140 	protected void fireButtonEvent(byte[] data) {
141 		NunchukButtonListener[] listeners = listenerList
142 				.getListeners(NunchukButtonListener.class);
143 		if (listeners.length == 0) {
144 			return;
145 		}
146 
147 		// we invert the original data as the wiimote returns
148 		// button pressed as nil and thats not that useable.
149 		int modifiers = (data[5] & 0x03) ^ 0x03;
150 
151 		NunchukButtonEvent evt = new NunchukButtonEvent(this, modifiers);
152 		for (NunchukButtonListener l : listeners) {
153 			l.buttonPressed(evt);
154 		}
155 	}
156 
157 	/**
158 	 * @return
159 	 */
160 	public NunchukCalibrationData getCalibrationData() {
161 		return calibrationData;
162 	}
163 
164 	/**
165 	 * @return
166 	 */
167 	public Mote getMote() {
168 		return mote;
169 	}
170 
171 	/*
172 	 * (non-Javadoc)
173 	 * 
174 	 * @see motej.Extension#initialize()
175 	 */
176 	public void initialize() {
177 		mote.addDataListener(this);
178 		
179 		// initialize
180 		mote.writeRegisters(new byte[] { (byte) 0xa4, 0x00, 0x40}, new byte[] { 0x00 });
181 		
182 		// request calibration data
183 		mote.readRegisters(new byte[] { (byte) 0xa4, 0x00, 0x30 }, new byte[] {
184 				0x00, 0x0f });
185 	}
186 
187 	/*
188 	 * (non-Javadoc)
189 	 * 
190 	 * @see motej.Extension#parseExtensionData(byte[])
191 	 */
192 	public void parseExtensionData(byte[] extensionData) {
193 		decrypt(extensionData);
194 		fireAnalogStickEvent(extensionData);
195 		fireAccelerometerEvent(extensionData);
196 		fireButtonEvent(extensionData);
197 	}
198 
199 	/**
200 	 * @param listener
201 	 */
202 	public void removeAccelerometerListener(
203 			AccelerometerListener<Nunchuk> listener) {
204 		listenerList.remove(AccelerometerListener.class, listener);
205 	}
206 
207 	/**
208 	 * @param listener
209 	 */
210 	public void removeAnalogStickListener(AnalogStickListener listener) {
211 		listenerList.remove(AnalogStickListener.class, listener);
212 	}
213 
214 	/**
215 	 * @param listener
216 	 */
217 	public void removeNunchukButtonListener(NunchukButtonListener listener) {
218 		listenerList.remove(NunchukButtonListener.class, listener);
219 	}
220 
221 	/*
222 	 * (non-Javadoc)
223 	 * 
224 	 * @see motej.Extension#setMote(motej.Mote)
225 	 */
226 	public void setMote(Mote mote) {
227 		this.mote = mote;
228 	}
229 
230 	/*
231 	 * (non-Javadoc)
232 	 * 
233 	 * @see java.lang.Object#toString()
234 	 */
235 	@Override
236 	public String toString() {
237 		return "Nunchuk";
238 	}
239 }