Subversion Repositories svnkaklik

Rev

Details | Last modification | View Log

Rev Author Line No. Line
157 kaklik 1
/*
2
    AVRcamVIEW: A PC application to test out the functionallity of the
3
     AVRcam real-time image processing engine.
4
    Copyright (C) 2004    Brent A. Taylor
5
 
6
    This program is free software; you can redistribute it and/or
7
    modify it under the terms of the GNU General Public
8
    License as published by the Free Software Foundation; either
9
    version 2 of the License, or (at your option) any later version.
10
 
11
    This program is distributed in the hope that it will be useful,
12
    but WITHOUT ANY WARRANTY; without even the implied warranty of
13
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
    General Public License for more details.
15
 
16
    You should have received a copy of the GNU General Public
17
    License along with this program; if not, write to the Free Software
18
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 
20
   For more information on the AVRcamVIEW, please contact:
21
 
22
   taylorba@comcast.net
23
 
24
   or go to www.jrobot.net for more details regarding the system.
25
*/
26
 
27
package avr.device;
28
 
29
import java.io.*;
30
import java.nio.*;
31
import java.util.*;
32
import javax.comm.*;
33
 
34
import java.awt.*;
35
 
36
import avr.connection.*;
37
import avr.connection.event.*;
38
import avr.device.event.*;
39
import avr.io.*;
40
import avr.lang.*;
41
 
42
public class Device implements ConnectionListener {
43
 
44
   public static void main(String[] args) throws Exception {
45
      Device device = new Device();
46
 
47
      SerialParams params = new SerialParams();
48
 
49
      device.setConnection(new SerialConnection("COM1", params));
50
 
51
      device.connect();
52
      device.sendPing();
53
      device.sendDumpFrame();
54
      device.sendGetVersion();
55
      device.sendSetRegisters(new HashMap());
56
      device.sendReset();
57
      device.sendEnableTracking();
58
      device.sendDisableTracking();
59
      device.sendSetColorMap(null, null, null);
60
 
61
      try {
62
         System.in.read();
63
      } catch(IOException ioe) {
64
         ioe.printStackTrace();
65
      }
66
      device.disconnect();
67
 
68
   }
69
 
70
   private static final String ACK = "ACK";
71
   private static final String NCK = "NCK";
72
   private static final String VERSION = "AVR";
73
 
74
   private static final String COLOR_MAP_KEY = "avr.color.map";
75
 
76
   // timeout after 3 seconds
77
   private static final int RESPONSE_TIMEOUT = 3000;
78
 
79
   private java.util.List connectionListeners;
80
   private java.util.List dataListeners;
81
   private AbstractConnection con;
82
 
83
   private InputStream in;
84
   private OutputStream out;
85
 
86
   private int[][] colorMap;
87
   private Color[] mapColors;
88
 
89
   private Timer responseTimer;
90
   private TimerTask responseTask;
91
 
92
   public Device() {
93
      connectionListeners = new ArrayList(3);
94
      dataListeners = new ArrayList(3);
95
      loadMap();
96
 
97
      responseTimer = new Timer();
98
   }
99
 
100
   public Color[] getMapColors() {
101
      return mapColors;
102
   }
103
 
104
   public int[][] getColorMap() {
105
      return colorMap;
106
   }
107
 
108
   public void setColorMap(int[][] colorMap) {
109
      this.colorMap = colorMap;
110
      setMapColors();
111
      saveMap();
112
   }
113
 
114
   public void saveMap() {
115
      try {
116
         ByteArrayOutputStream bOut = new ByteArrayOutputStream();
117
         DataOutputStream dOut = new DataOutputStream(bOut);
118
 
119
         dOut.writeInt(colorMap.length);
120
         for(int i = 0; i < colorMap.length; i++) {
121
            dOut.writeInt(colorMap[i].length);
122
            for(int j = 0; j < colorMap[i].length; j++) {
123
               dOut.writeInt(colorMap[i][j]);
124
            }
125
         }
126
 
127
         dOut.close();
128
 
129
         AVRSystem.PREFS.putByteArray(COLOR_MAP_KEY, bOut.toByteArray());
130
 
131
      } catch(Exception e) {
132
         e.printStackTrace();
133
      }
134
   }
135
 
136
   public void loadMap() {
137
      try {
138
         byte[] data = AVRSystem.PREFS.getByteArray(COLOR_MAP_KEY, null);
139
         if(data != null) {
140
            ByteArrayInputStream bIn = new ByteArrayInputStream(data);
141
            DataInputStream dIn = new DataInputStream(bIn);
142
 
143
            int width = dIn.readInt();
144
            colorMap = new int[width][];
145
            for(int i = 0; i < colorMap.length; i++) {
146
               colorMap[i] = new int[dIn.readInt()];
147
               for(int j = 0; j < colorMap[i].length; j++) {
148
                  colorMap[i][j] = dIn.readInt();
149
               }
150
            }
151
 
152
            dIn.close();
153
         } else {
154
            colorMap = new int[3][AVRSystem.NUM_INTENSITIES];
155
         }
156
 
157
         setMapColors();
158
 
159
      } catch(Exception e) {
160
         e.printStackTrace();
161
      }
162
 
163
   }
164
 
165
   private void setMapColors() {
166
      mapColors = new Color[8];
167
 
168
      for(int col = 0; col < mapColors.length; col++) {
169
         int value = 0;
170
 
171
         int red = 0;
172
         int green = 0;
173
         int blue = 0;
174
 
175
         int numRed = 0;
176
         int numGreen = 0;
177
         int numBlue = 0;
178
 
179
 
180
         for(int i = 0; i < AVRSystem.NUM_INTENSITIES; i++) {
181
 
182
            if((colorMap[0][i] & (0x01 << (7 - col))) != 0) {
183
               red += i << 4;
184
               numRed++;
185
            }
186
 
187
            if((colorMap[1][i] & (0x01 << (7 - col))) != 0) {
188
               green += i << 4;
189
               numGreen++;
190
            }
191
 
192
            if((colorMap[2][i] & (0x01 << (7 - col))) != 0) {
193
               blue += i << 4;
194
               numBlue++;
195
            }
196
 
197
         }
198
 
199
         if(numRed > 0) {
200
            red /= numRed;
201
         }
202
 
203
         if(numGreen > 0) {
204
            green /= numGreen;
205
         }
206
 
207
         if(numBlue > 0) {
208
            blue /= numBlue;
209
         }
210
 
211
         value = (red << 16) | (green << 8) | blue;
212
 
213
         mapColors[col] = new Color(value);
214
      }
215
 
216
   }
217
 
218
   public AbstractConnection getConnection() {
219
      return con;
220
   }
221
 
222
   public void setConnection(AbstractConnection con) {
223
      this.con = con;
224
   }
225
 
226
   public boolean isConnected() {
227
      return con != null && con.isConnected();
228
   }
229
 
230
   public void addConnectionListener(ConnectionListener listener) {
231
      AVRSystem.LOG.finest("Added Connection Listener: " + listener);
232
      connectionListeners.add(listener);
233
   }
234
 
235
   public void removeConnectionListener(ConnectionListener listener) {
236
      AVRSystem.LOG.finest("Removed Connection Listener: " + listener);
237
      connectionListeners.remove(listener);
238
   }
239
 
240
   public void connected(ConnectionEvent event) {
241
      ConnectionListener[] listeners = (ConnectionListener[])connectionListeners.toArray(new ConnectionListener[connectionListeners.size()]);
242
      for(int i = 0; i < listeners.length; i++) {
243
         ((ConnectionListener)listeners[i]).connected(event);
244
      }
245
   }
246
 
247
   public void disconnected(ConnectionEvent event) {
248
      ConnectionListener[] listeners = (ConnectionListener[])connectionListeners.toArray(new ConnectionListener[connectionListeners.size()]);
249
      for(int i = 0; i < listeners.length; i++) {
250
         ((ConnectionListener)listeners[i]).disconnected(event);
251
      }
252
   }
253
 
254
   public void connect() throws Exception {
255
 
256
      if(!isConnected()) {
257
         con.connect();
258
 
259
         if(con instanceof SerialConnection) {
260
            SerialPort serialPort = (SerialPort)con.getConnectionObject();
261
            serialPort.notifyOnDataAvailable(true);
262
            try {
263
               serialPort.addEventListener(new SerialEventHandler(this));
264
            } catch(TooManyListenersException tmle) {
265
               AVRSystem.LOG.severe(tmle.getMessage());
266
            }
267
         }
268
 
269
         in = new AVRInputStream(con.getInputStream());
270
         out = con.getOutputStream();
271
 
272
         AVRSystem.LOG.config("Device connected to " + con.toString());
273
 
274
         connected(new ConnectionEvent(con));
275
 
276
      }
277
   }
278
 
279
   public void disconnect() {
280
 
281
      if(isConnected()) {
282
         try {
283
            con.disconnect();
284
            AVRSystem.LOG.config("Device Disconnected");
285
            disconnected(new ConnectionEvent(con));
286
            con = null;
287
         } catch(IOException ioe) {
288
            AVRSystem.LOG.severe(ioe.getMessage());
289
         }
290
      }
291
   }
292
 
293
   public InputStream getInputStream() {
294
      return in;
295
   }
296
 
297
   public void addDataListener(DataListener dl) {
298
      if(dataListeners.add(dl)) {
299
         AVRSystem.LOG.finest("Added Data Listener: " + dl);
300
      }
301
   }
302
 
303
   public void removeDataListener(DataListener dl) {
304
      if(dataListeners.remove(dl)) {
305
         AVRSystem.LOG.finest("Removed Data Listener: " + dl);
306
      }
307
   }
308
 
309
   protected void handleString(String data) {
310
      if(data.equals(ACK)) {
311
         fireACKReceived();
312
      } else if(data.equals(NCK)) {
313
         fireNCKReceived();
314
      } else if(data.startsWith(VERSION)) {
315
         fireVERSIONReceived(data);
316
      } else {
317
         StringBuffer builder = new StringBuffer("UNKNOWN PACKET: (");
318
         ByteBuffer bytes = ByteBuffer.wrap(data.getBytes());
319
         builder.append(bytes.remaining()).append(") ");
320
         while(bytes.hasRemaining()) {
321
            builder.append(Integer.toHexString(bytes.get() & 0xFF)).append(' ');
322
         }
323
         AVRSystem.LOG.warning(builder.toString());
324
      }
325
   }
326
 
327
   protected void handleData(ByteBuffer data) {
328
      if(data.hasRemaining()) {
329
         byte dataType = data.get();
330
         if(dataType == 0x0B) {
331
            fireFrameDataReceived(data);
332
         } else if(dataType == 0x0A) {
333
            fireTrackingDataReceived(data);
334
         } else {
335
            handleString(new String(data.array(), 0, data.limit()));
336
         }
337
      }
338
   }
339
 
340
   protected void fireACKReceived() {
341
      if(responseTask != null) {
342
         responseTask.cancel();
343
      }
344
      AVRSystem.LOG.info("Received: ACK");
345
      DataListener[] listeners = (DataListener[])dataListeners.toArray(new DataListener[dataListeners.size()]);
346
      for(int i = 0; i < listeners.length; i++) {
347
         ((DataListener)listeners[i]).ack();
348
      }
349
   }
350
 
351
   private void fireResponseTimerExpired() {
352
      AVRSystem.LOG.severe("Response Timer Expired");
353
      DataListener[] listeners = (DataListener[])dataListeners.toArray(new DataListener[dataListeners.size()]);
354
      for(int i = 0; i < listeners.length; i++) {
355
         ((DataListener)listeners[i]).responseTimerExpired();
356
      }
357
   }
358
 
359
   protected void fireNCKReceived() {
360
      if(responseTask != null) {
361
         responseTask.cancel();
362
      }
363
      AVRSystem.LOG.info("Received: NCK");
364
      DataListener[] listeners = (DataListener[])dataListeners.toArray(new DataListener[dataListeners.size()]);
365
      for(int i = 0; i < listeners.length; i++) {
366
         ((DataListener)listeners[i]).nck();
367
      }
368
   }
369
 
370
   protected void fireVERSIONReceived(String version) {
371
      if(responseTask != null) {
372
         responseTask.cancel();
373
      }
374
      AVRSystem.LOG.info("Received: " + version);
375
      DataListener[] listeners = (DataListener[])dataListeners.toArray(new DataListener[dataListeners.size()]);
376
      for(int i = 0; i < listeners.length; i++) {
377
         ((DataListener)listeners[i]).version(version);
378
      }
379
   }
380
 
381
   protected void fireFrameDataReceived(ByteBuffer data) {
382
 
383
      int position = data.position();
384
      StringBuffer buf = new StringBuffer("Received: Frame Dump (" + (data.get(position) & 0xFF) + ")");
385
 
386
      data.position(0);
387
 
388
      while(data.hasRemaining()) {
389
         int b = data.get() & 0xFF;
390
         buf.append(' ').append(((b & 0xF0) == 0) ? "0" : "").append(Integer.toHexString(b).toUpperCase());
391
      }
392
 
393
      data.position(position);
394
 
395
      AVRSystem.LOG.info(buf.toString());
396
//      AVRSystem.LOG.info("Received: Frame Dump (" + (data.get(data.position()) & 0xFF) + ")");
397
      DataListener[] listeners = (DataListener[])dataListeners.toArray(new DataListener[dataListeners.size()]);
398
      for(int i = 0; i < listeners.length; i++) {
399
         data.mark();
400
         ((DataListener)listeners[i]).frameData(data);
401
         data.reset();
402
      }
403
   }
404
 
405
   protected void fireTrackingDataReceived(ByteBuffer data) {
406
 
407
      int position = data.position();
408
      StringBuffer buf = new StringBuffer("Received: Tracking Info (" + (data.get(position) & 0xFF) + ")");
409
 
410
      data.position(0);
411
 
412
      while(data.hasRemaining()) {
413
         int b = data.get() & 0xFF;
414
         buf.append(' ').append(((b & 0xF0) == 0) ? "0" : "").append(Integer.toHexString(b).toUpperCase());
415
      }
416
 
417
      data.position(position);
418
 
419
      AVRSystem.LOG.info(buf.toString());
420
      DataListener[] listeners = (DataListener[])dataListeners.toArray(new DataListener[dataListeners.size()]);
421
      for(int i = 0; i < listeners.length; i++) {
422
         data.mark();
423
         ((DataListener)listeners[i]).trackingData(data);
424
         data.reset();
425
      }
426
   }
427
 
428
   private void sendRequest(byte[] data) throws IOException {
429
      sendRequest(data, 0, data.length);
430
   }
431
 
432
   private void sendRequest(byte[] data, int off, int len) throws IOException {
433
 
434
      responseTask = new ResponseTask();
435
      responseTimer.schedule(responseTask, RESPONSE_TIMEOUT);
436
 
437
      if(isConnected()) {
438
 
439
         out.write(data, off, len);
440
         out.write((byte)'\n');
441
         out.flush();
442
 
443
         StringBuffer builder = new StringBuffer("Sending: ");
444
         for(int i = off; i < len; i++) {
445
            builder.append((char)data[i]);
446
         }
447
         AVRSystem.LOG.info(builder.toString());
448
      } else {
449
         AVRSystem.LOG.warning("AVRcam not connected.");
450
      }
451
   }
452
 
453
   public void sendSetRegisters(Map registers) throws IOException {
454
      ByteBuffer buffer = ByteBuffer.allocate(60);
455
      buffer.put((byte)'C')
456
            .put((byte)'R');
457
 
458
     Set entries = registers.entrySet();
459
     for(Iterator i = entries.iterator(); i.hasNext();) {
460
        Map.Entry entry = (Map.Entry)i.next();
461
        buffer.put((byte)' ').put(entry.getKey().toString().getBytes())
462
              .put((byte)' ').put(entry.getValue().toString().getBytes());
463
     }
464
 
465
      buffer.put((byte)'\r');
466
      buffer.flip();
467
      sendRequest(buffer.array(), 0, buffer.remaining());
468
   }
469
 
470
   public void sendDisableTracking() throws IOException {
471
      sendRequest(new byte[] { (byte)'D', (byte)'T', (byte)'\r'} );
472
   }
473
 
474
   public void sendDumpFrame() throws IOException {
475
      sendRequest(new byte[] { (byte)'D', (byte)'F', (byte)'\r'} );
476
   }
477
 
478
   public void sendEnableTracking() throws IOException {
479
      sendRequest(new byte[] { (byte)'E', (byte)'T', (byte)'\r'} );
480
   }
481
 
482
   public void sendGetVersion() throws IOException {
483
      sendRequest(new byte[] { (byte)'G', (byte)'V', (byte)'\r'} );
484
   }
485
 
486
   public void sendPing() throws IOException {
487
      sendRequest(new byte[] { (byte)'P', (byte)'G', (byte)'\r'} );
488
   }
489
 
490
   public void sendReset() throws IOException {
491
      sendRequest(new byte[] { (byte)'R', (byte)'S', (byte)'\r'} );
492
   }
493
 
494
   public void sendSetColorMap(int[] red, int[] green, int[] blue) throws IOException {
495
      ByteBuffer buffer = ByteBuffer.allocate(2 + 4 * red.length * 3 + 1);
496
      buffer.put("SM".getBytes());
497
      for(int i = 0; i < red.length; i++) {
498
         buffer.put((" " + red[i] + "").getBytes());
499
      }
500
      for(int i = 0; i < green.length; i++) {
501
         buffer.put((" " + green[i] + "").getBytes());
502
      }
503
      for(int i = 0; i < blue.length; i++) {
504
         buffer.put((" " + blue[i] + "").getBytes());
505
      }
506
      buffer.put("\r".getBytes());
507
      buffer.flip();
508
      sendRequest(buffer.array(), 0, buffer.remaining());
509
   }
510
 
511
   public void sendCameraData(ByteBuffer data) throws IOException {
512
 
513
      out.write((byte)0x0A);
514
      out.write(data.array(), 0, data.remaining());
515
      out.write((byte)0xFF);
516
 
517
      out.flush();
518
 
519
   }
520
 
521
   private final static class SerialEventHandler implements SerialPortEventListener {
522
 
523
      private Device device;
524
 
525
      public SerialEventHandler(Device device) {
526
         this.device = device;
527
      }
528
 
529
      public void serialEvent(SerialPortEvent spe) {
530
         if(spe.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
531
 
532
            try {
533
 
534
               do {
535
 
536
                  byte[] data = new byte[1024];
537
 
538
                  int bytesRead = device.getInputStream().read(data);
539
                  if(bytesRead > 0) {
540
                     // take only bytesRead - 1 to remove the
541
                     // terminating character '\r' or 0xFF
542
                     EventQueue.invokeLater(new GUITask(device, ByteBuffer.wrap(data, 0, bytesRead - 1)));
543
                  }
544
 
545
               } while(device.getInputStream().available() > 0);
546
 
547
            } catch(IOException ioe) {
548
               AVRSystem.LOG.severe(ioe.getMessage());
549
               device.disconnect();
550
            }
551
 
552
         }
553
      }
554
 
555
   }
556
 
557
   private final static class GUITask implements Runnable {
558
      private ByteBuffer data;
559
      private Device device;
560
 
561
      public GUITask(Device device, ByteBuffer data) {
562
         this.device = device;
563
         this.data = data;
564
      }
565
 
566
      public void run() {
567
         device.handleData(data);
568
      }
569
 
570
   }
571
 
572
   private final class ResponseTask extends TimerTask {
573
 
574
      public void run() {
575
         // make sure we fire the timer expired event
576
         // using the Event Dispatch Thread.  If not,
577
         // queue this TimerTask in the Event Queue.
578
         if(EventQueue.isDispatchThread()) {
579
            fireResponseTimerExpired();
580
         } else {
581
            EventQueue.invokeLater(this);
582
         }
583
      }
584
 
585
   }
586
 
587
   /**
588
    * Only used for debugging purposes, this will simulate an ACK coming from the device.
589
    */
590
   public void simulateACK() {
591
      fireACKReceived();
592
   }
593
 
594
   /**
595
    * Only used for debugging purposes, this will simulate an NCK coming from the device.
596
    */
597
   public void simulateNCK() {
598
      fireNCKReceived();
599
   }
600
 
601
}