checkpoint
[slipway.git] / src / edu / berkeley / obits / device / atmel / AvrDrone.java
1 package edu.berkeley.obits.device.atmel;
2
3 import edu.berkeley.obits.*;
4 import org.ibex.util.Log;
5 import java.io.*;
6 import java.util.*;
7 import gnu.io.*;
8
9 /** the "host" side of the AVR Drone; see AvrDrone.c for the other side */
10 public class AvrDrone extends AtmelDevice {
11
12     final DataInputStream in;
13
14     final DataOutputStream out;
15
16     final SerialPort sp;
17
18     public AvrDrone(SerialPort sp) throws IOException, UnsupportedCommOperationException, InterruptedException, DeviceException {
19         this.sp = sp;
20         //sp.setSerialPortParams(115200, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
21         sp.setSerialPortParams(38400, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
22         sp.setFlowControlMode(sp.FLOWCONTROL_RTSCTS_OUT);
23         sp.setInputBufferSize(1024);
24         //sp.setFlowControlMode(sp.FLOWCONTROL_NONE);
25         this.out = new DataOutputStream(sp.getOutputStream());
26         this.in = new DataInputStream(sp.getInputStream());
27         Log.debug(this, "consuming any leftover data on the serial port");
28         while(in.available() > 0) in.read();
29         reset();
30         Log.debug(this, "waiting for device to identify itself");
31         if (in.readByte() != (byte)'O')  throw new RuntimeException("didn't get the proper signature");
32         if (in.readByte() != (byte)'B')  throw new RuntimeException("didn't get the proper signature");
33         if (in.readByte() != (byte)'I')  throw new RuntimeException("didn't get the proper signature");
34         if (in.readByte() != (byte)'T')  throw new RuntimeException("didn't get the proper signature");
35         if (in.readByte() != (byte)'S')  throw new RuntimeException("didn't get the proper signature");
36         if (in.readByte() != (byte)'\n') throw new RuntimeException("didn't get the proper signature");
37         Log.info(this, "device correctly identified itself; ready for operation");
38     }
39
40     public synchronized void scanFPGA(boolean on) throws DeviceException {
41         try {
42             if (on) {
43                 out.writeByte(3);
44                 out.flush();
45             } else {
46                 // FIXME
47             }
48         } catch (IOException e) { throw new DeviceException(e); }
49     }
50     // fixme!
51     public static int retval = 0;
52     public synchronized int readCount() throws DeviceException {
53         try {
54             if (reader != null) {
55                 reader.start();
56                 reader = null;
57             }
58             ByteCallback bc = new ByteCallback() {
59                     public synchronized void call(byte b) throws Exception {
60                         retval =
61                             ((b & 0xff) << 24) |
62                             ((in.read() & 0xff) << 16) |
63                             ((in.read() & 0xff) << 8) |
64                             ((in.read() & 0xff) << 0);
65                         this.notify();
66                     }
67                 };
68             synchronized(bc) {
69                 callbacks.add(bc);
70                 out.writeByte(6);
71                 out.flush();
72                 bc.wait();
73             }
74             return retval;
75         } catch (Exception e) { throw new DeviceException(e); }
76     }
77
78     public static interface ByteCallback {
79         public void call(byte b) throws Exception;
80     }
81
82     private Vector callbacks = new Vector();
83
84     private Thread reader = new Thread() {
85             public void run() {
86                 while(true) {
87                     try {
88                         byte b = in.readByte();
89                         ByteCallback bc = (ByteCallback)callbacks.remove(0);
90                         bc.call(b);
91                     } catch (Exception e) {
92                         e.printStackTrace();
93                     }
94                 }
95             }
96         };
97
98     public synchronized void readBus(ByteCallback bc) throws DeviceException {
99         try {
100             callbacks.add(bc);
101             out.writeByte(2);
102             out.flush();
103             if (reader != null) {
104                 reader.start();
105                 reader = null;
106             }
107         } catch (IOException e) { throw new DeviceException(e); }
108     }
109
110     public synchronized void readInterrupts(ByteCallback bc) throws DeviceException {
111         try {
112             callbacks.add(bc);
113             out.writeByte(6);
114             out.flush();
115             if (reader != null) {
116                 reader.start();
117                 reader = null;
118             }
119         } catch (IOException e) { throw new DeviceException(e); }
120     }
121
122     public synchronized void reset() throws DeviceException {
123         try {
124             Log.info(this, "resetting device");
125             sp.setDTR(true);
126             sp.setRTS(true);
127             Thread.sleep(500);
128             Log.info(this, "deasserting reset signal");
129             sp.setDTR(false);
130             sp.setRTS(false);
131             Thread.sleep(100);
132         } catch (InterruptedException e) { throw new DeviceException(e); }
133     }
134
135     private byte[][][] cache = new byte[24][][];
136     public synchronized byte mode4(int z, int y, int x) throws DeviceException {
137         if (cache[x]==null) return 0;
138         if (cache[x][y]==null) return 0;
139         return cache[x][y][z];
140     }
141
142     int lastz = 0;
143     int lastx = 0;
144     int lasty = 0;
145     public static int save = 0;
146     public static int saveof = 0;
147     public synchronized void mode4(int z, int y, int x, int d) throws DeviceException {
148         try {
149             /*
150             Log.info(this, "writing configuration frame [zyxd]: " +
151                       pad(1, Integer.toString(z&0xff, 16)) + " " +
152                       pad(1, Integer.toString(y&0xff, 16)) + " " +
153                       pad(1, Integer.toString(x&0xff, 16)) + " " +
154                       pad(1, Integer.toString(d&0xff, 16))
155                       );
156             */
157             boolean zchange = z!=lastz;
158             boolean ychange = y!=lasty;
159             boolean xchange = x!=lastx;
160             boolean zinc    = z==lastz+1;
161             boolean yinc    = y==lasty+1;
162             boolean xinc    = x==lastx+1;
163             boolean zdec    = z==lastz-1;
164             boolean ydec    = y==lasty-1;
165             boolean xdec    = x==lastx-1;
166             
167             //System.out.println(zchange + " " + ychange + " " + xchange);
168             out.writeByte(0x80
169                           | (zinc?0x40:zdec?0x04:zchange?0x44:0x00)
170                           | (yinc?0x20:ydec?0x02:ychange?0x22:0x00)
171                           | (xinc?0x10:xdec?0x01:xchange?0x11:0x00));
172             if (!zinc && !zdec && zchange) out.writeByte(z); else save++;
173             if (!yinc && !ydec && ychange) out.writeByte(y); else save++;
174             if (!xinc && !xdec && xchange) out.writeByte(x); else save++;
175             saveof++;
176             lastz = z;
177             lastx = x;
178             lasty = y;
179             out.writeByte(d);
180             if (cache[x & 0xff]==null) cache[x & 0xff] = new byte[24][];
181             if (cache[x & 0xff][y & 0xff]==null) cache[x & 0xff][y & 0xff] = new byte[256];
182             cache[x & 0xff][y & 0xff][z & 0xff] = (byte)(d & 0xff);
183         } catch (IOException e) { throw new DeviceException(e); }
184     }
185
186     public synchronized void flush() throws DeviceException {
187         try {
188             out.flush();
189         } catch (IOException e) { throw new DeviceException(e); }
190     }
191
192     private String pad(int i, String s) { if (s.length()>i) return s; return "0"+pad((i-1),s); }
193
194 }