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