checkpoint
[slipway.git] / src / edu / berkeley / obits / AtmelSerial.java
1 package edu.berkeley.obits;
2
3 import static edu.berkeley.obits.device.atmel.AtmelDevice.Constants.*;
4 import static edu.berkeley.obits.device.atmel.AtmelDevice.Util.*;
5 import edu.berkeley.obits.device.atmel.*;
6 import java.awt.*;
7 import java.awt.event.*;
8 import java.awt.color.*;
9 import org.ibex.util.*;
10 import java.io.*;
11 import java.util.*;
12 import gnu.io.*;
13
14 public class AtmelSerial {
15
16     //public static boolean mullers = false;
17     public static boolean mullers = true;
18     public static int masterx = 1;
19     public static SerialPort detectObitsPort() throws Exception {
20         Enumeration e = CommPortIdentifier.getPortIdentifiers();
21         while(e.hasMoreElements()) {
22             CommPortIdentifier cpi = (CommPortIdentifier)e.nextElement();
23             Log.info(AtmelSerial.class, "trying " + cpi.getName());
24             if (cpi.getName().startsWith("/dev/cu.usbserial-")) return new RXTXPort(cpi.getName());
25             if (cpi.getName().startsWith("/dev/ttyS0")) return new RXTXPort(cpi.getName());
26         }
27         Log.info(AtmelSerial.class, "returning null...");
28         return null;
29     }
30     public static int PIPELEN=20;
31     public static void main(String[] s) throws Exception {
32         AvrDrone device = new AvrDrone(detectObitsPort());
33         At40k at40k = new At40k.At40k10(device);
34         int count = 0;
35         try {
36             long begin = System.currentTimeMillis();
37             BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
38             for(String str = br.readLine(); str != null; str = br.readLine()) {
39                 long foo = Long.parseLong(str, 16);
40                 device.mode4((int)(foo >> 24), (int)(foo >> 16), (int)(foo >>  8), (int)(foo >>  0));
41                 count++;
42                 if (count % 100 == 0) Log.info(AtmelSerial.class, "wrote " + count + " configuration octets");
43             }
44             device.flush();
45             long end = System.currentTimeMillis();
46             Log.info(AtmelSerial.class, "finished in " + ((end-begin)/1000) + "s");
47             Thread.sleep(1000);
48             Log.info(AtmelSerial.class, "issuing command");
49
50             //at40k.iob_top(2, true).oe(false);
51             //at40k.iob_top(2, false).oe(false);
52             //at40k.iob_top(1, true).oe(false);
53
54             // this command confirmed to turn *on* led0
55             //at40k.iob_top(1, false).output(0);
56             /*
57             for(int i=0; i<20; i++) {
58                 at40k.iob_bot(i, false).output(0);
59                 at40k.iob_bot(i, true).output(0);
60             }
61             */
62
63             //System.out.println("tick");
64                 //Thread.sleep(3000);
65                 //System.out.println("tick");
66                 //at40k.cell(0x01, 0x17).xlut((byte)0x);
67
68             /*
69             System.out.println(Integer.toString(0xff & at40k.cell(0x01, 0x17).xlut(), 16));
70             System.out.println(Integer.toString(0xff & at40k.cell(0x01, 0x17).ylut(), 16));
71             at40k.cell(0x01, 0x17).ylut((byte)0xff);
72             */
73
74             //at40k.cell(0x01, 0x17).wi(L1);
75             /*
76             System.out.println("a: " + at40k.new SectorWire(true, 0, 4, 0x17).driverRight());
77             System.out.println("b: " + at40k.new SectorWire(true, 1, 4, 0x17).driverRight());
78             At40k.SectorWire h0p0 = at40k.new SectorWire(true, 0, 0, 0x17);
79             At40k.SectorWire h0p1 = at40k.new SectorWire(true, 1, 0, 0x17);
80             At40k.SectorWire h0p2 = at40k.new SectorWire(true, 2, 0, 0x17);
81             At40k.SectorWire h4p0 = at40k.new SectorWire(true, 0, 4, 0x17);
82             At40k.SectorWire h4p1 = at40k.new SectorWire(true, 1, 4, 0x17);
83             At40k.SectorWire h4p2 = at40k.new SectorWire(true, 2, 4, 0x17);
84
85             //h4p1.drives(h0p1, false);
86             //at40k.cell(0x04, 0x17).out(L1, false);
87             //at40k.cell(0x04, 0x17).h(L0, false);
88
89             for(int plane=0; plane<5; plane++) {
90                 at40k.new SectorWire(true, plane,     4, 0x17).drives(at40k.new SectorWire(true, plane,     0, 0x17), false);
91                 at40k.cell(0x04, 0x17).out(plane, false);
92                 at40k.cell(0x04, 0x17).h(plane, false);
93                 at40k.cell(0x01, 0x17).h(plane, false);
94             }
95             try { Thread.sleep(2000); } catch (Exception e) { }
96
97             int plane=0;
98             at40k.new SectorWire(true, plane, 4, 0x17).drives(at40k.new SectorWire(true, plane, 0, 0x17), true);
99             at40k.cell(0x04, 0x17).out(plane, true);
100             at40k.cell(0x04, 0x17).h(plane, true);
101             at40k.cell(0x01, 0x17).h(plane, true);
102             at40k.cell(0x01, 0x17).wi(plane);
103
104             */
105
106             /*
107             System.out.println("xlut is " + hex(at40k.cell(0x04, 0x17).xlut()));
108             System.out.println("ylut is " + hex(at40k.cell(0x04, 0x17).ylut()));
109             At40k.Cell cell = at40k.cell(0x04, 0x17);
110             //cell.xlut(0xff);
111             //cell.f(false);
112             System.out.println(cell.c());
113             cell.c(YLUT);
114             cell.ylut(0x4D);
115             cell.xlut(0x00);
116
117             cell.b(false);
118             cell.f(false);
119             //cell.t(false, false, true);
120             cell.t(false, true, false);
121             cell.out(L3, true);
122             cell.wi(L3);
123
124             cell.yo(false);
125             cell.h(L0, false);
126             cell.h(L1, false);
127             cell.h(L2, false);
128             cell.h(L3, false);
129             cell.h(L4, false);
130
131             for(int i=3; i>=1; i--) {
132                 at40k.cell(i, 0x17).yi(EAST);
133                 at40k.cell(i, 0x17).ylut(0x55);
134                 at40k.cell(i, 0x17).yo(false);
135             }
136             */
137
138             //System.out.println("reading port status: " + Integer.toString(device.readBus() & 0xff, 16));
139
140
141             // blank these out
142             /*
143             at40k.cell(23, 8).ylut(0xff);
144             at40k.cell(23, 11).ylut(0xff);
145             at40k.iob_right(8, true).enableOutput();
146             at40k.iob_right(11, true).enableOutput();
147             */
148             //for(int x=4;  x<=22; x++) swap(at40k.cell(x, 22), NW, NORTH);
149
150
151             // entry cell: just copy X->X Y->Y
152             //at40k.cell(4,23).b(false);
153             //at40k.cell(4,23).yo(false);
154             //at40k.cell(4,23).ylut(at40k.cell(4,23).xlut());
155             //at40k.cell(4,23).xo(false);
156             /*
157             at40k.cell(4,23).xlut(0x55);
158             at40k.cell(4,23).ylut(0x55);
159             */
160             /*
161             at40k.cell(4,23).xlut(0x71);
162             at40k.cell(4,23).ylut(0x44);
163             at40k.cell(4,23).c(YLUT);
164             at40k.cell(4,23).f(false);
165             at40k.cell(4,23).t(false, false, true);
166             */
167
168             //for(int x=6;  x<=23; x++) copy(at40k.cell(x, 23), NW, WEST);  // top row copies to the right
169             /*
170             copy(at40k.cell(5, 22), NW, NORTH);
171             for(int x=6;  x<=22; x++) copy(at40k.cell(x, 22), NW, WEST);  // second top row copies to the right
172             //for(int y=22; y>=10; y--) copy(at40k.cell(23, y), NW, NORTH); // right edge copies down
173             for(int y=21; y>=9;  y--) copy(at40k.cell(22, y), NW, NORTH); // second right edge copies down
174             copy(at40k.cell(23, 9), NW, WEST);                            // second output
175             */
176             /*
177             handshaker(at40k.cell(4,23));
178             at40k.cell(4,23).xi(NW);
179             at40k.cell(4,23).yi(SOUTH);
180
181             //handshaker(at40k.cell(5,23));
182             //at40k.cell(5,23).yi(NORTH);
183
184             at40k.cell(5,23).yi(NORTH);
185             at40k.cell(5,23).xlut(0x55);
186             at40k.cell(5,23).xi(SW);
187             at40k.cell(5,23).ylut(0x55);
188             at40k.cell(5,22).yi(NORTH);
189             at40k.cell(5,22).xlut(0x55);
190
191             bounce(at40k.cell(4,22));
192
193             // cell southeast of entry cell
194             at40k.cell(3,22).xi(NE);      // NW->xin
195             at40k.cell(3,22).ylut(0x33);  // xin->y
196             at40k.cell(3,22).yo(false);   // y->yout
197             copy(at40k.cell(3, 21), NW, NORTH);  // second top row copies to the right
198             copy(at40k.cell(4, 21), NW, EAST);  // second top row copies to the right
199             copy(at40k.cell(5, 21), NW, EAST);  // second top row copies to the right
200             copy(at40k.cell(6, 21), NW, EAST);  // second top row copies to the right
201             copy(at40k.cell(6, 22), NW, SOUTH);  // second top row copies to the right
202             */
203             /*
204             at40k.cell(05,22).xlut(0xff);
205             at40k.cell(05,22).ylut(0xff);
206             at40k.cell(05,22).c(XLUT);
207             at40k.cell(05,22).f(false);
208             at40k.cell(05,22).b(false);
209             at40k.cell(05,22).oe(NONE);
210             at40k.cell(05,22).v(L3, true);
211             at40k.cell(05,22).out(L3, true);
212             */
213             /*
214             at40k.cell(4,23).ylut(~0xCC);
215             at40k.cell(4,23).xlut(~0xAA);
216             at40k.cell(5,23).ylut(~0xAA);
217             at40k.cell(5,23).xlut(~0xAA);
218             for(int i=6; i<PIPELEN+2; i++) {
219                 at40k.cell(i, 23).ylut(0xAA);
220                 at40k.cell(i, 23).xlut(0xCC);
221                 at40k.cell(i, 23).yi(WEST);
222             }
223             */
224
225             /* LAST
226             System.out.println("doit");
227             if (mullers) doitx(at40k, device);
228             //System.out.println("counter");
229             //counter(at40k, device);
230
231             at40k.cell(21,15).yi(WEST);
232             at40k.cell(21,15).ylut(0xAA);
233
234             at40k.cell(22,15).yi(WEST);
235             at40k.cell(22,15).ylut(0xAA);
236             */
237             at40k.cell(23,15).h(3, true);
238             at40k.cell(23,15).yi(L3);
239             at40k.cell(23,15).ylut(0xAA);
240             at40k.iob_right(15, true).enableOutput(WEST);
241
242
243             At40k.Cell c = at40k.cell(10,10);
244             c.ylut(~LUT_SELF);
245             c.xlut(LUT_Z);
246             c.yi(WEST);
247             c.c(YLUT);
248             c.f(false);
249             c.t(TMUX_FB);
250             copy(c.west(), EAST, NW);
251             copy(c.west().north().west(), SE, SE);
252
253             c = c.east();
254             c.ylut(~LUT_SELF);
255             c.xlut(LUT_Z);
256             c.yi(EAST);
257             c.c(YLUT);
258             c.f(false);
259             c.t(TMUX_FB);
260             copy(c.east(), WEST, SE);
261             copy(c.east().south().east(), NW, NW);
262
263             c = c.north();
264             copy(c.north(), SOUTH, SOUTH);
265             c.xlut((LUT_SELF & ~LUT_OTHER) | LUT_Z);
266             c.ylut(LUT_Z);
267             c.yi(SOUTH);
268             c.c(XLUT);
269             c.xi(SW);
270             c.wi(L4);
271             c.f(false);
272             c.t(TMUX_W_AND_FB);
273             c.v(L4, false);
274             c.h(L4, true);
275             c.v(L2, false);
276             c.h(L2, true);
277
278             c = c.west();
279             copy(c.north(), SOUTH, SOUTH);
280             c.xlut((LUT_SELF & ~LUT_OTHER) | LUT_Z);
281             c.ylut(~LUT_Z);
282             c.yi(SOUTH);
283             c.xi(SE);
284             c.c(XLUT);
285             c.wi(L4);
286             c.f(false);
287             c.t(TMUX_W_AND_FB);
288             c.v(L4, false);
289             c.h(L4, true);
290             c.v(L2, false);
291             c.h(L2, true);
292
293             c = c.west();
294             c.v(L4, false);
295             c.h(L4, true);
296             c.out(L4, true);
297             c.f(false);
298             c.b(false);
299             c.oe(NONE);
300             c.c(YLUT);
301             c.hwire(L4).west().drives(c.hwire(L4), false);
302             c.hwire(L4).east().drives(c.hwire(L4), false);
303
304             c = c.south();
305             c = c.south();
306             c.v(L4, false);
307             c.h(L4, true);
308             c.out(L4, true);
309             c.f(false);
310             c.b(false);
311             c.oe(NONE);
312             c.c(YLUT);
313             c.hwire(L4).west().drives(c.hwire(L4), false);
314             c.hwire(L4).east().drives(c.hwire(L4), false);
315
316             c = c.east();
317             c = c.east();
318             copy(c.south(), NORTH, NORTH);
319             c.xlut(((~LUT_SELF) & (~LUT_OTHER)) | LUT_Z);
320             c.ylut(LUT_Z);
321             c.yi(NORTH);
322             c.c(XLUT);
323             c.xi(NW);
324             c.wi(L4);
325             c.f(false);
326             c.t(TMUX_W_AND_FB);
327             c.v(L4, false);
328             c.h(L4, true);
329             c.v(L2, false);
330             c.h(L2, true);
331
332             c = c.west();
333             copy(c.south(), NORTH, NORTH);
334             c.xlut((LUT_SELF & LUT_OTHER) | LUT_Z);
335             c.ylut(LUT_Z);
336             c.yi(NORTH);
337             c.xi(NE);
338             c.c(XLUT);
339             c.wi(L4);
340             c.f(false);
341             c.t(TMUX_W_AND_FB);
342             c.v(L4, false);
343             c.h(L4, true);
344             c.v(L2, false);
345             c.h(L2, true);
346
347
348
349             // catch a rising transition
350             /*
351             c = c.west();
352             c.v(L2, false);
353             c.h(L2, true);
354             c.out(L2, true);
355             c.f(false);
356             c.b(false);
357             c.oe(NONE);
358             c.c(YLUT);
359             */
360             c.hwire(L2).west().drives(c.hwire(L2), false);
361             c.hwire(L2).east().drives(c.hwire(L2), false);
362
363             //for(int x=5; x<PIPELEN; x++) {
364             //at40k.cell(x,23).hwire(L0).drives(at40k.cell(x,23).hwire(L0).east());
365             //}
366
367             /*
368             at40k.cell(22,11).ylut(0xff);
369             at40k.cell(23,11).yi(L3);
370             //at40k.cell(23,11).yi(WEST);
371             //at40k.cell(23,11).xi(L1);
372             at40k.cell(23,11).ylut(0xAA);
373             at40k.iob_right(11, true).enableOutput(WEST);
374             at40k.cell(23,11).v(L3, true);
375             at40k.cell(23,11).yo(false);
376             //at40k.flush();
377             */
378             int vx=04;
379             int vv=23;
380             /*
381             System.out.println("correct: " + at40k.cell(19,15).hwire(L3) + " drives " + at40k.cell(20,15).hwire(L3));
382             System.out.println("correct: " + at40k.cell(15,15).hwire(L3) + " drives " + at40k.cell(19,15).hwire(L3));
383             System.out.println("correct: " + at40k.cell(11,15).hwire(L3) + " drives " + at40k.cell(15,15).hwire(L3));
384             System.out.println("correct: " + at40k.cell(07,15).hwire(L3) + " drives " + at40k.cell(11,15).hwire(L3));
385
386             at40k.cell(19,15).hwire(L3).drives(at40k.cell(20,15).hwire(L3), true);
387             at40k.cell(15,15).hwire(L3).drives(at40k.cell(19,15).hwire(L3), true);
388             at40k.cell(11,15).hwire(L3).drives(at40k.cell(15,15).hwire(L3), true);
389             at40k.cell(07,15).hwire(L3).drives(at40k.cell(11,15).hwire(L3), true);
390             */
391             //at40k.cell(05,vv).xlut(0xff);
392             //at40k.cell(05,vv).ylut(0xff);
393             /*
394             at40k.cell(vx,vv).c(YLUT);
395             at40k.cell(vx,vv).f(false);
396             at40k.cell(vx,vv).b(false);
397             at40k.cell(vx,vv).oe(NONE);
398             at40k.cell(vx,vv).v(L3, true);
399             at40k.cell(vx,vv).out(L3, true);
400             */
401             /*
402             at40k.cell(vx,15).v(L3, true);
403             at40k.cell(vx,15).h(L3, true);
404             at40k.cell(vx,19).vwire(L3).drives(at40k.cell(vx,15).vwire(L3), true);
405             at40k.cell(vx,23).vwire(L3).drives(at40k.cell(vx,19).vwire(L3), true);
406             */
407
408             //at40k.cell(5,23).ylut(0x00);
409             //at40k.cell(6,22).ylut(0xff);
410             //at40k.cell(22,11).ylut(0xff);
411             /*
412             At40k.Cell cell = at40k.cell(4, 16);
413             cell.xlut(0xff);
414             cell.ylut(0xff);
415             cell.b(false);
416             cell.f(false);
417             cell.c(XLUT);
418             cell.h(L3, true);
419             cell.v(L3, true);
420             cell.out(L3, true);
421             cell.oe(NONE);
422             */
423             //scan(at40k, cell, YLUT, true);
424             //scan(at40k, cell, YLUT, false);
425
426             //device.scanFPGA(true);
427             Visualizer v = new Visualizer(at40k, device);
428             v.show();
429             v.setSize(1380, 1080);
430             At40k.Cell cell = at40k.cell(4, 23);
431             Image img = v.createImage(v.getWidth(), v.getHeight());
432             /*
433             int x = 1;
434             int y = 14;
435             cell = at40k.cell(x,y);
436             scan(at40k, cell, YLUT, true);
437             cell.c(YLUT);
438             cell.b(false);
439             cell.f(false);
440             cell.oe(NONE);
441             cell.ylut(0xff);
442             */
443             //int x = 5;
444             //int y = 11;
445
446             //selfTest(device, at40k, v);
447             System.out.println("save: " + AvrDrone.save + " of " + (AvrDrone.saveof*5));
448
449             at40k.iob_top(0, true).enableInput();
450             copy(at40k.cell(0, 23), NORTH, NORTH);
451             at40k.iob_bot(0, true).enableOutput(NORTH);
452
453             for(int i=0; i<10000; i++) {
454                 v.refresh();
455                 try { Thread.sleep(100); } catch (Exception e) { }
456             }
457             //cell.ylut(0x09);
458
459             //at40k.cell(0x01, 0x17).h(0, false);
460             //at40k.cell(0x01, 0x17).xi(NE);
461             //at40k.cell(0x01, 0x17).ylut((byte)0x55);
462
463             //at40k.cell(0x04, 0x17).xlut((byte)0x10);
464             //at40k.cell(0x04, 0x17).ylut((byte)0x10);
465             //at40k.cell(0x04, 0x17).yo(false);
466             //at40k.cell(0x04, 0x17).xo();
467
468             /*
469             at40k.cell(0x01, 0x17).xi(L0);
470             at40k.cell(0x01, 0x17).h(L0, true);
471             */
472             /*
473             at40k.cell(0x03, 0x17).xlut((byte)0x55);
474             at40k.cell(0x03, 0x17).ylut((byte)0x55);
475             at40k.cell(0x03, 0x17).yi(EAST);
476             at40k.cell(0x03, 0x17).ylut((byte)0x55);
477             at40k.cell(0x03, 0x17).yo(true);
478
479             at40k.cell(0x03, 0x17).f(false);
480             at40k.cell(0x03, 0x17).c(XLUT);
481             at40k.cell(0x03, 0x17).oe(NONE);
482             at40k.cell(0x03, 0x17).out(L0, true);
483
484             at40k.cell(0x02, 0x17).yi(EAST);
485             at40k.cell(0x02, 0x17).ylut((byte)0x55);
486             at40k.cell(0x02, 0x17).yo(false);
487
488             at40k.cell(0x01, 0x17).yi(EAST);
489             at40k.cell(0x01, 0x17).ylut((byte)0x55);
490             at40k.cell(0x01, 0x17).yo(false);
491
492             at40k.cell(0x01, 0x17).h(L0, true);
493             at40k.cell(0x01, 0x17).v(L0, false);
494             */
495             //at40k.cell(0x01, 0x17).yi(L0);
496             //at40k.cell(0x01, 0x17).xi(L0);
497             //at40k.cell(0x01, 0x17).ylut((byte)0x33);
498
499             /*
500             at40k.cell(0x03, 0x17).h(L0, true);
501             at40k.cell(0x03, 0x17).out(L0, true);
502             at40k.cell(0x03, 0x17).c(XLUT);
503             at40k.cell(0x03, 0x17).f(false);
504             */
505             /*
506             at40k.cell(0x01, 0x17).xin(4);
507             at40k.cell(0x01, 0x17).yin(4);
508             at40k.cell(0x01, 0x16).ylut((byte)0x00);
509             device.mode4(2, 0x17, 0x01, 0);
510
511             for(int i=0; i<10; i++) {
512                 Thread.sleep(3000);
513                 System.out.println("tick");
514                 //at40k.cell(0x01, 0x17).xlut((byte)0xFF);
515                 at40k.cell(0x00, 0x17).ylut((byte)0x00);
516                 device.flush();
517                 Thread.sleep(3000);
518                 System.out.println("tick");
519                 //at40k.cell(0x01, 0x17).xlut((byte)0x00);
520                 at40k.cell(0x00, 0x17).ylut((byte)0xFF);
521                 device.flush();
522             }
523             */
524
525
526             /*
527             at40k.iob_top(0, true).output(0);
528             at40k.iob_top(0, true).oe(false);
529             at40k.iob_top(0, true).pullup();
530             device.flush();
531             Thread.sleep(3000);
532
533             Log.info(AtmelSerial.class, "issuing command");
534             at40k.iob_top(1, true).pulldown();
535             device.flush();
536             */
537             Log.info(AtmelSerial.class, "done");
538             System.exit(0);
539         } catch (Exception e) { e.printStackTrace(); }
540     }
541
542     public static void scan(At40k dev, At40k.Cell cell, int source, boolean setup) {
543         if (setup) {
544             if (source != NONE) cell.c(source);
545             if (cell.b()) cell.b(false);
546             if (cell.f()) cell.f(false);
547             if (!cell.out(L3)) cell.out(L3, true);
548         }
549         if (cell.vx(L3)!=setup) cell.v(L3, setup);
550
551         At40k.SectorWire sw = cell.vwire(L3);
552         //System.out.println("wire is: " + sw);
553
554         if (sw.row > (12 & ~0x3) && sw.north()!=null && sw.north().drives(sw))
555             sw.north().drives(sw, false);
556         while(sw.row > (12 & ~0x3) && sw.south() != null) {
557             //System.out.println(sw + " -> " + sw.south());
558             if (sw.drives(sw.south())!=setup) sw.drives(sw.south(), setup);
559             sw = sw.south();
560         }
561         if (sw.row < (12 & ~0x3) && sw.south() != null && sw.south().drives(sw))
562             sw.north().drives(sw, false);
563         while(sw.row < (12 & ~0x3) && sw.north() != null) {
564             //System.out.println(sw + " -> " + sw.north());
565             if (sw.drives(sw.north())!=setup) sw.drives(sw.north(), setup);
566             sw = sw.north();
567         }
568
569         //cell = dev.cell(19, 15);
570         cell = dev.cell(cell.col, 15);
571         /*
572         System.out.println("cell is " + cell);
573         cell.xlut(0xff);
574         cell.ylut(0xff);
575         cell.b(false);
576         cell.f(false);
577         cell.c(XLUT);
578         cell.out(L3, true);
579         cell.oe(NONE);
580         */
581         if (cell.hx(L3) != setup) cell.h(L3, setup);
582         if (cell.vx(L3) != setup) cell.v(L3, setup);
583         sw = cell.hwire(L3);
584
585         if (sw.west()!=null && sw.west().drives(sw)) { sw.west().drives(sw, false); }
586         while(sw.east() != null) {
587             //System.out.println(sw + " -> " + sw.east());
588             if (sw.drives(sw.east())!=setup) sw.drives(sw.east(), setup);
589             sw = sw.east();
590         }
591
592     }
593
594     public static void copy(At40k.Cell c, int xdir, int ydir) {
595         switch(xdir) {
596             case NW: case NE: case SW: case SE: {
597                 c.xi(xdir);
598                 c.xlut(LUT_SELF);
599                 break;
600             }
601             case NORTH: case SOUTH: case EAST: case WEST: {
602                 c.yi(xdir);
603                 c.xlut(LUT_OTHER);
604                 break;
605             }
606             case NONE: break;
607             default: throw new Error();
608         }
609         switch(ydir) {
610             case NW: case NE: case SW: case SE: {
611                 c.xi(ydir);
612                 c.ylut(LUT_OTHER);
613                 break;
614             }
615             case NORTH: case SOUTH: case EAST: case WEST: {
616                 c.yi(ydir);
617                 c.ylut(LUT_SELF);
618                 break;
619             }
620             case NONE: break;
621             default: throw new Error();
622         }
623         c.xo(false);
624         c.yo(false);
625     }
626     public static String hex(int x) {
627         return Long.toString(x & 0xffffffffL, 16);
628     }
629
630     public static void handshaker(At40k.Cell cell) {
631         cell.xlut(0x22);
632         cell.ylut(0x71);
633         cell.c(XLUT);
634         cell.f(false);
635         cell.t(false, false, true);
636     }
637
638     public static class Visualizer extends Frame implements KeyListener, MouseMotionListener, MouseListener {
639         public static final int WIDTH = 40;
640         public static final int HEIGHT = 40;
641         public static final int LW = 15;
642         public static final int LH = 15;
643         public static final Color RED  = new Color(0xaa, 0x55, 0x55);
644         public static final Color BLUE = new Color(0x55, 0x55, 0xaa);
645         private final At40k dev;
646         private final AvrDrone drone;
647         int selx = -1;
648         int sely = -1;
649         public Visualizer(final At40k dev, final AvrDrone drone) {
650             this.dev = dev;
651             this.drone = drone;
652             show();
653             addMouseMotionListener(this);
654             addMouseListener(this);
655             addKeyListener(this);
656             new Thread() {
657                 public void run() {
658                     try {
659                         while(true) {
660                             Thread.sleep(500);
661                             if (!enabled) continue;
662                             /*
663                             At40k.Cell cell = dev.cell(21, 22);
664                             cell.xlut(0xff);
665                             cell.ylut(0xff);
666                             */
667                             keyPressed(null);
668                             /*
669                             cell.xlut(0x00);
670                             cell.ylut(0x00);
671                             */
672                         }
673                     } catch (Exception e) {
674                         e.printStackTrace();
675                     }
676                 }
677             }.start();
678         }
679         public boolean enabled = false;
680         public void mouseClicked(MouseEvent e) { }
681         public void mouseEntered(MouseEvent e) { }
682         public void mouseExited(MouseEvent e) { }
683         public void mouseReleased(MouseEvent e) {
684         }
685         public void keyTyped(KeyEvent k) {
686         }
687         public void keyReleased(KeyEvent k) {
688         }
689         public void keyPressed(KeyEvent keyevent) {
690             boolean scan = false;
691             switch(keyevent==null ? '_' : keyevent.getKeyChar()) {
692                 case '1': {
693                     if (selx==-1 || sely==-1) break;
694                     At40k.Cell cell = dev.cell(selx, sely);
695                     cell.xlut(0xff);
696                     cell.ylut(0xff);
697                     drawCell(getGraphics(), selx, sely);
698                     break;
699                 }
700                 case 'i': {
701                     System.out.println("interrupt_count: " + drone.readCount());
702                     break;
703                 }
704                 case 'x': {
705                     masterx+=2;
706                     if (mullers) {
707                         if (masterx <= 22) {
708                             int mx = masterx;
709                             System.out.println("low => " + mx);
710                             copy(dev.cell(mx, yofs-2), NORTH, NORTH);
711                             copy(dev.cell(mx, yofs-3), NORTH, NORTH);
712                             //dev.cell(mx, yofs-3).ylut(~dev.cell(mx, yofs-3).ylut());
713                             //dev.cell(mx, yofs-3).xlut(~dev.cell(mx, yofs-3).xlut());
714                         } else {
715                             int mx = 23-(masterx-23);
716                             System.out.println("high => " + mx);
717                             copy(dev.cell(mx, yofs), NW, NW);//NORTH, NORTH);
718                             copy(dev.cell(mx, yofs-1), NORTH, NORTH);
719                             //for(int x=mx-1; x>=1; x--)
720                             //copy(dev.cell(x, yofs), EAST, EAST);
721                             for(int y=yofs+1; y<=23; y++)
722                                 copy(dev.cell(1, y), SOUTH, SOUTH);
723                             //dev.cell(mx, yofs-1).ylut(~dev.cell(mx, yofs-1).ylut());
724                             //dev.cell(mx, yofs-1).xlut(~dev.cell(mx, yofs-1).xlut());
725                         }
726                     } else {
727                         if (masterx <= 22) {
728                             int mx = masterx;
729                             System.out.println("low => " + mx);
730                             copy(dev.cell(mx, yofs-2), SOUTH, SOUTH);
731                             copy(dev.cell(mx, yofs-3), NORTH, NORTH);
732                             dev.cell(mx, yofs-3).ylut(~dev.cell(mx, yofs-3).ylut());
733                             dev.cell(mx, yofs-3).xlut(~dev.cell(mx, yofs-3).xlut());
734                         } else {
735                             int mx = 23-(masterx-23);
736                             System.out.println("high => " + mx);
737                             copy(dev.cell(mx, yofs), SOUTH, SOUTH);
738                             /*
739                             copy(dev.cell(mx, yofs-1), NORTH, NORTH);
740                             */
741                             copy(dev.cell(mx, yofs-1), NORTH, SW);
742                             boolean left = true;
743                             At40k.Cell lc = null;
744                             for(int k=0; k<10; k++) {
745                                 int y = yofs-2-(k*2);
746                                 copy(dev.cell(left?(mx-1):mx, y),        SOUTH, left?NE:NW);
747                                 copy(lc = dev.cell(left?(mx-1):mx, y-1), NORTH, left?SE:SW); 
748                                 left = !left;
749                             }
750                             copy(lc, NORTH, NORTH);
751
752                             //for(int x=mx-1; x>=1; x--)
753                             //copy(dev.cell(x, yofs), EAST, EAST);
754                             //for(int y=yofs+1; y<=23; y++)
755                             //copy(dev.cell(1, y), SOUTH, SOUTH);
756
757                             if (mx<21) {
758                                 dev.cell(mx+2, yofs).ylut(0x00);
759                                 dev.cell(mx+2, yofs).xlut(0x00);
760                             }
761
762                             /*
763                             dev.cell(mx, yofs-1).ylut(~LUT_Z);
764                             dev.cell(mx, yofs-1).xlut(LUT_Z);
765                             loopback(dev.cell(mx, yofs-1), YLUT);
766                             */
767                             dev.cell(mx, yofs).ylut(~LUT_SELF);
768                             dev.cell(mx, yofs).xlut(~LUT_OTHER);
769                         }
770                     }
771                     break;
772                 }
773                 case ' ': {
774                     //enabled = !enabled;
775                     scan = true;
776                     break;
777                 }
778                 case '4': {
779                     //enabled = !enabled;
780                     try {
781                         for(int cap=0; cap<15; cap++) {
782                             drain(dev, drone);
783                             try { Thread.sleep(100); } catch (Exception e) { }
784                             //showit(dev, drone, this);
785                             fill(dev, drone, cap);
786                             drone.readCount();
787                             long now = System.currentTimeMillis();
788                             try { Thread.sleep(4000); } catch (Exception e) { }
789                             int count = drone.readCount();
790                             long now2 = System.currentTimeMillis();
791                             System.out.println(cap + " ,  " + (((float)count * (2*2*2*2*2*2*2*2*2*1000))/(now2-now)));
792                         }
793                     } catch (Exception e) { e.printStackTrace(); }
794                     break;
795                 }
796                 case 'C': {
797                     if (selx==-1 || sely==-1) break;
798                     At40k.Cell cell = dev.cell(selx, sely);
799                     cell.ylut(0xB2);
800                     drawCell(getGraphics(), selx, sely);
801                     break;
802                 }
803                 case '0': {
804                     if (selx==-1 || sely==-1) break;
805                     At40k.Cell cell = dev.cell(selx, sely);
806                     cell.xlut(0x00);
807                     cell.ylut(0x00);
808                     drawCell(getGraphics(), selx, sely);
809                     break;
810                 }
811             } 
812             if (!scan) return;
813             showit(dev, drone, this);
814         }
815         public void mousePressed(MouseEvent e) {
816             final At40k.Cell cell = dev.cell(selx, sely);
817             if (cell==null) return;
818             final int old = cell.c();
819             AvrDrone.ByteCallback bc = new AvrDrone.ByteCallback() {
820                     public void call(byte b) throws Exception {
821                         boolean y = (b & 0x80) != 0;
822                         //cell.c(old);
823                         Graphics g = getGraphics();
824                         g.setFont(new Font("sansserif", Font.BOLD, 14));
825                         g.setColor(Color.white);
826                         //g.drawString("X=0", left(cell) + 10, top(cell) + 20);
827                         //g.drawString("X=1", left(cell) + 10, top(cell) + 20);
828                         //g.setColor(Color.white);
829                         //g.drawString("Y=0", left(cell) + 8, top(cell) + 35);
830                         //g.drawString("Y=1", left(cell) + 8, top(cell) + 35);
831                         //g.setColor(RED);
832                         //g.drawString("X="+(x?"1":"0"), left(cell) + 10, top(cell) + 20);
833                         String v = (cell.c()==YLUT ? "Y" : cell.c()==XLUT ? "X" : "C");
834                         g.drawString(v+"="+(y?"0":"1"), left(cell) + 8, top(cell) + 35);
835                         g.setColor(BLUE);
836                         g.drawString(v+"="+(y?"1":"0"), left(cell) + 8, top(cell) + 35);
837                     } };
838             scan(dev, cell, NONE, true);
839             drone.readBus(bc);
840             //scan(dev, cell, XLUT, true);
841             //boolean x = (drone.readBus() & 0x80) != 0;
842             scan(dev, cell, NONE, false);
843         }
844
845         public void mouseMoved(MouseEvent e) {
846             int x = e.getX();
847             int y = e.getY();
848             if (selx >= 0 && selx < 24 && sely >= 0 && sely < 24) {
849                 int cx = selx;
850                 int cy = sely;
851                 At40k.Cell cell = dev.cell(cx, cy);
852                 selx = -1;
853                 sely = -1;
854                 /*
855                 drawCell(getGraphics(), cx, cy);
856                 drawSector(getGraphics(), dev.cell(cx, cy).sector());
857                 */
858             }
859             selx = (x-20)/(WIDTH+2);
860             sely = (23 - (y-20)/(HEIGHT+2))+1;
861             /*
862             At40k.Cell cell = dev.cell(selx, sely);
863             if (selx >= 0 && selx < 24 && sely >= 0 && sely < 24) {
864                 drawCell(getGraphics(), selx, sely);
865                 drawSector(getGraphics(), dev.cell(selx, sely).sector());
866             }
867             */
868         }
869         public void mouseDragged(MouseEvent e) { mousePressed(e); }
870         public void paint(Graphics g) {
871             System.out.println("paintall");
872             g.setColor(Color.white);
873             g.fillRect(0, 0, getWidth(), getHeight());
874             g.setFont(new Font("sansserif", Font.BOLD, 24));
875             for(int x=0; x<24; x++)
876                 for(int y=0; y<24; y++)
877                     drawCell(g,x,y);
878             for(int x=0; x<=23; x+=4)
879                 for(int y=23; y>=0; y-=4) 
880                     drawSector(g, dev.cell(x, y).sector());
881             /*
882             g.setColor(BLUE);
883             g.drawString("Ready", (5*(WIDTH+2))+20, 40);
884             g.setColor(RED);
885             g.drawString("Send",  (3*(WIDTH+2))+20, 40);
886             g.setColor(BLUE);
887             */
888             refresh();
889         }
890         public void refresh() {
891             Graphics g = getGraphics();
892             /*
893             int data = drone.readBus() & 0xff;
894             for(int i=0; i<8; i++) {
895                 g.setColor((data & (1<<i))==0 ? Color.black : Color.green);
896                 g.drawString("D"+i,  (24*(WIDTH+2))+20, ((23-(i+7))*(HEIGHT+2))+60-HEIGHT/2);
897             }
898             */
899         }
900         public static int left(At40k.Cell cell) { return (cell.col)   *(WIDTH+2)+20; }
901         public static int top(At40k.Cell cell)  { return (23-cell.row)*(HEIGHT+2)+60; }
902         public void drawSector(Graphics g, At40k.Sector sector) {
903             g.setColor(Color.gray);
904             ((Graphics2D)g).setStroke(new BasicStroke(1));
905             int px = ((sector.col)*(WIDTH+2))+20-1;
906             int py = ((23-(sector.row+3))*(HEIGHT+2))+60-1;
907             g.drawRect(px, py, (WIDTH+2)*4+2, (HEIGHT+2)*4+2);
908             /*
909             for(int dir=0; dir<2; dir++) {
910                 boolean h = dir==0;
911                 for(int y=h?sector.row:sector.col; y<(h?sector.row+4:sector.col+4); y++)
912                     for(int plane=0; plane<=4; plane++) {
913                         At40k.Cell cell      = h ? dev.cell(sector.col,   y) : dev.cell(y, sector.row);
914                         At40k.Cell cell_east = h ? dev.cell(sector.col-1, y) : dev.cell(y, sector.row-1);
915                         At40k.Cell cell_west = h ? dev.cell(sector.col+4, y) : dev.cell(y, sector.row+4);
916                         boolean draw = false;
917                         if (h) {
918                             if (cell_east!=null &&
919                                 (cell_east.hwire(plane).drives(cell.hwire(plane)) ||
920                                  cell_east.hwire(plane).drives(cell.hwire(plane))))
921                                 draw = true;
922                             if (cell_west!=null &&
923                                 (cell_west.hwire(plane).drives(cell.hwire(plane)) ||
924                                  cell_west.hwire(plane).drives(cell.hwire(plane))))
925                                 draw = true;
926                         } else {
927                             if (cell_east!=null &&
928                                 (cell_east.vwire(plane).drives(cell.vwire(plane)) ||
929                                  cell_east.vwire(plane).drives(cell.vwire(plane))))
930                                 draw = true;
931                             if (cell_west!=null &&
932                                 (cell_west.vwire(plane).drives(cell.vwire(plane)) ||
933                                  cell_west.vwire(plane).drives(cell.vwire(plane))))
934                                 draw = true;
935                         }
936                         if (!draw)
937                             for(int x=h?sector.col:sector.row; x<(h?sector.col+4:sector.row+4); x++)
938                                 if (((h ? dev.cell(x,y).hx(plane) : dev.cell(y,x).vx(plane))) ||
939                                     (h?dev.cell(x,y).out(plane):dev.cell(y,x).out(plane)))
940                                     draw = true;
941                         if (draw) {
942                             g.setColor(new Color(0xff, 0x00, 0xff));
943                             if (h) {
944                                 g.drawLine(left(cell),
945                                            top(cell)+3,
946                                            left(cell) + 4*(WIDTH+2),
947                                            top(cell)+3
948                                            );
949                             } else {
950                                 g.drawLine(left(cell)+3,
951                                            top(cell) + (HEIGHT+2),
952                                            left(cell)+3,
953                                            top(cell) - 3*(HEIGHT+2)
954                                            );
955                             }
956                         }
957                     }
958             }
959             */
960         }
961         public void drawCell(Graphics g, int cx, int cy) {
962             int x = (cx*(WIDTH+2))+20;
963             int y = ((23-cy)*(HEIGHT+2))+60;
964             if (g.getClipBounds() != null && !g.getClipBounds().intersects(new Rectangle(x, y, x+WIDTH, y+HEIGHT))) return;
965             drawCell(g, cx, cy, Color.white);
966         }
967         public void drawCell(Graphics g, int cx, int cy, Color bg) {
968             int x = (cx*(WIDTH+2))+20;
969             int y = ((23-cy)*(HEIGHT+2))+60;
970
971             //System.out.println("drawcell " + cx + "," + cy);
972             At40k.Cell cell = dev.cell(cx, cy);
973             g.setColor(bg);
974             g.fillRect(x, y, WIDTH, HEIGHT);
975
976             g.setColor((selx==cx && sely==cy) ? Color.red : Color.black);
977             g.drawRect(x, y, WIDTH, HEIGHT);
978
979             //g.setColor((selx==cx && sely==cy) ? Color.red : Color.gray);
980             //g.drawRect(x+(WIDTH-(LW*2))/2-1,    y+(HEIGHT-LW)/2-1, LW*2+1, LH+1);
981
982             //g.setColor(RED);
983             //g.fillRect(x+(WIDTH-(LW*2))/2,    y+(HEIGHT-LW)/2, LW,   LH);
984             //g.setColor(Color.white);
985             //g.drawString("1", x+(WIDTH-(LW*2))/2,    y+(HEIGHT-LW)/2);
986
987             //g.setColor(BLUE);
988             //g.fillRect(x+(WIDTH-(LW*2))/2+LW, y+(HEIGHT-LW)/2, LW,   LH);
989             //g.setColor(Color.white);
990             //g.drawString("0", x+(WIDTH-(LW*2))/2+LW,    y+(HEIGHT-LW)/2);
991
992             /*
993               g.setColor(BLUE);
994             ((Graphics2D)g).setStroke(new BasicStroke((float)1));
995             switch(cell.yi()) {
996                 case NORTH: g.drawLine(x+WIDTH/2+5,  y-10,        x+WIDTH/2+5, y+HEIGHT/2); break;
997                 case SOUTH: g.drawLine(x+WIDTH/2-5,  y+HEIGHT+10, x+WIDTH/2-5, y+HEIGHT/2); break;
998                 case EAST:  g.drawLine(x+WIDTH+10, y+HEIGHT/2+5,  x+WIDTH/2, y+HEIGHT/2+5); break;
999                 case WEST:  g.drawLine(x-10,       y+HEIGHT/2-5,  x+WIDTH/2, y+HEIGHT/2-5); break;
1000                 case NONE:  break;
1001             }
1002             g.setColor(RED);
1003             ((Graphics2D)g).setStroke(new BasicStroke((float)1));
1004             switch(cell.xi()) {
1005                 case NW: g.drawLine(x-10+3,       y-10,        x+WIDTH/2+3, y+HEIGHT/2); break;
1006                 case SW: g.drawLine(x-10-3,       y+HEIGHT+10, x+WIDTH/2-3, y+HEIGHT/2); break;
1007                 case NE: g.drawLine(x+WIDTH+10+3, y-10,        x+WIDTH/2+3, y+HEIGHT/2); break;
1008                 case SE: g.drawLine(x+WIDTH+10-3, y+HEIGHT+10, x+WIDTH/2-3, y+HEIGHT/2); break;
1009                 case NONE:  break;
1010             }
1011             ((Graphics2D)g).setStroke(new BasicStroke(1));
1012             */
1013             /*
1014             if (selx==cx && sely==cy) {
1015                 int xp = 23 * (WIDTH+2) + 100;
1016                 int yp = 100;
1017                 g.setColor(Color.white);
1018                 g.fillRect(xp, yp, 300, 1000);
1019                 g.setColor(Color.black);
1020                 g.drawString("Cell " + cx + "," + cy,       xp, (yp+=15));
1021                 //g.drawString("X-Lut: " + bin8(cell.xlut()), xp, (yp+=15));
1022                 g.drawString("X-Lut: " + cell.printXLut(), xp, (yp+=15));
1023                 //g.drawString("Y-Lut: " + bin8(cell.ylut()), xp, (yp+=15));
1024                 g.drawString("Y-Lut: " + cell.printYLutX(), xp, (yp+=15));
1025             }
1026             */
1027             if ((cell.ylut()&0xff)==0xff && (cell.xlut()&0xff)==0xff) {
1028                 g.setColor(new Color(0x00, 0x00, 0xff));
1029                 g.drawString("1", left(cell) + 12, top(cell) + 30);
1030             }
1031             if ((cell.ylut()&0xff)==0x00 && (cell.xlut()&0xff)==0x00) {
1032                 g.setColor(new Color(0x00, 0x00, 0xff));
1033                 g.drawString("0", left(cell) + 12, top(cell) + 30);
1034             }
1035             if ((cell.ylut()&0xff)==0xB2) {
1036                 //System.out.println("muller @ " + cell);
1037                 //g.setColor(RED);
1038                 //g.drawString("X="+(x?"1":"0"), left(cell) + 10, top(cell) + 20);
1039                 g.setColor(new Color(0x00, 0xaa, 0x00));
1040                 g.drawString("C", left(cell) + 12, top(cell) + 30);
1041             }
1042
1043         }
1044     }
1045
1046     private static String pad(int i, String s) { if (s.length()>i) return s; return "0"+pad((i-1),s); }
1047     private static String bin8(byte b) {
1048         int n = b & 0xff;
1049         String ret = "";
1050         for(int i=7; i>=0; i--)
1051             ret += (n & (1<<i))==0 ? "0" : "1";
1052         return ret;
1053     }
1054
1055     public static void selfTest(AvrDrone device, At40k at40k, Visualizer v) {
1056         /*
1057             int fail = 0;
1058             long now = System.currentTimeMillis();
1059             for(int x=0; x<24; x++)
1060                 for(int y=0; y<24; y++) {
1061                     At40k.Cell cell = at40k.cell(x,y);
1062                     scan(at40k, cell, YLUT, true);
1063                     //v.paint(img.getGraphics());
1064                     //v.getGraphics().drawImage(img, 0, 0, null);
1065                     cell.ylut(0xff);
1066                     boolean a = (device.readBus() & 0x80)!=0;
1067                     cell.ylut(0x00);
1068                     boolean b = (device.readBus() & 0x80)!=0;
1069                     if (a & !b) {
1070                         //System.out.println("pass " + x+","+y);
1071                         Graphics g = v.getGraphics();
1072                         g.setColor(Color.green);
1073                         g.drawString("pass", v.left(cell) + 10, v.top(cell) + 20);
1074                     } else {
1075                         System.out.println("FAIL!!!! " + x+","+y+" => " + a + " " + b);
1076                         fail++;
1077                         Graphics g = v.getGraphics();
1078                         g.setColor(Color.red);
1079                         g.drawString("FAIL", v.left(cell) + 10, v.top(cell) + 20);
1080                     }
1081                     scan(at40k, cell, YLUT, false);
1082                 }
1083
1084             System.out.println("failures: " + fail);
1085             System.out.println("scan time: " + (System.currentTimeMillis()-now) + "ms");
1086         */
1087     }
1088     
1089     public static void bounce(At40k.Cell cell, int xi, int yi) {
1090         cell.xlut((byte)0xCC);
1091         cell.ylut((byte)0xCC);
1092         cell.xi(xi);
1093         cell.yi(yi);
1094         cell.xo(false);
1095         cell.yo(false);
1096     }
1097     public static void muller(At40k.Cell cell, int xi, int yi) {
1098         cell.ylut(0xB2);
1099         cell.c(YLUT);
1100         cell.f(false);
1101         cell.t(false, false, true);
1102         cell.xi(xi);
1103         cell.yi(yi);
1104         cell.yo(false);
1105         cell.xo(false);
1106     }
1107
1108     /** watches for a rising/falling edge on Yin, emits a pulse on Xout */
1109     public static void pulse_detect(At40k.Cell c, int in, boolean falling) {
1110         c.ylut(0x00);
1111         c.xlut(0x00);
1112         switch(in) {
1113             case NW: case NE: case SW: case SE: {
1114                 c.xi(in);
1115                 loopback(c, XLUT);
1116                 if (!falling) c.ylut(lutSwap(0x0C)); /* x & !z */
1117                 else          c.ylut(lutSwap(0x30)); /* !x & z */
1118                 c.xlut(LUT_SELF);
1119                 break;
1120             }
1121             case NORTH: case SOUTH: case EAST: case WEST: {
1122                 c.yi(in);
1123                 loopback(c, YLUT);
1124                 if (!falling) c.xlut(0x0C); /* y & !z */
1125                 else          c.xlut(0x30); /* !y & z */
1126                 c.ylut(LUT_SELF);
1127                 break;
1128             }
1129             default: throw new Error();
1130         }
1131     }
1132
1133     /** watches for a pulse on Xin, copies value of Yin */
1134     public static void pulse_copy(At40k.Cell cell, int xi, int yi, boolean invert) {
1135         loopback(cell, YLUT);
1136         if (!invert) cell.ylut(0xB8);   /* yo = x ?  yi : z => 1011 1000 */
1137         else         cell.ylut(0x74);   /* yo = x ? !yi : z => 0111 0100 */
1138         if (!invert) cell.xlut(lutSwap(0xB8));   /* yo = x ?  yi : z => 1011 1000 */
1139         else         cell.xlut(lutSwap(0x74));   /* yo = x ? !yi : z => 0111 0100 */
1140         cell.xi(xi);
1141         cell.yi(yi);
1142     }
1143
1144     public static void loopback(At40k.Cell cell, int cin) {
1145         cell.f(false);
1146         cell.b(false);
1147         cell.t(false, false, true);
1148         cell.yo(false);
1149         cell.xo(false);
1150         cell.c(cin);
1151     }
1152     public static void doit(At40k at40k, AvrDrone device) throws Exception {
1153
1154         At40k.Cell led = at40k.cell(1, 23);
1155         led.v(L2, true);
1156         led.h(L2, false);
1157         led.yi(L2);
1158         led.ylut(~LUT_SELF);
1159         led.xlut(LUT_SELF);
1160         led.yo(false);
1161
1162         At40k.Cell c = at40k.cell(1, 22);
1163         c.out(L1, true);
1164         c.out(L0, true);
1165         c.oe(V4);
1166         c.ylut(0xff);
1167         c.h(L1, true);
1168         c.h(L0, false);
1169
1170         c.v(L0, /*false*/true);
1171
1172         c.v(L1, true);
1173         c.f(false);
1174         c.b(false);
1175         c.c(YLUT);
1176
1177         for(int i=0; i<4; i++) at40k.cell(i, 20).h(L0, false);
1178         At40k.Cell z = at40k.cell(1, 20);
1179         z.out(L0, true);
1180         z.xlut(0xff);
1181         z.c(XLUT);
1182         z.yi(L0);
1183         z.ylut(~LUT_SELF);
1184         z.v(L0, true);
1185         //z.h(L0, true);
1186         z.h(L0, false);
1187         z.f(false);
1188         z.b(false);
1189         z.hwire(L0).east().drives(z.hwire(L0), false);
1190         z.hwire(L1).east().drives(z.hwire(L1), false);
1191         z.vwire(L0).south().drives(z.vwire(L0), false);
1192         z.vwire(L1).south().drives(z.vwire(L1), false);
1193         z.oe(H4);
1194
1195         z = at40k.cell(0, 20);
1196         z.oe(NONE);
1197         z.out(L0, true);
1198         z.out(L1, true);
1199         z.out(L2, true);
1200         //z.out(L3, true);
1201         z.out(L4, true);
1202         z.h(L0, true);
1203         z.h(L1, true);
1204         z.h(L2, true);
1205         //z.h(L3, true);
1206         z.h(L4, true);
1207         z.f(false);
1208         z.b(false);
1209         z.yi(EAST);
1210         z.ylut(LUT_SELF);
1211         z.c(YLUT);
1212
1213         for(int y=20; y<=22; y++)
1214             for(int x=2; x<=5; x++) {
1215                 c = at40k.cell(x, y);
1216                 copy(c, NW, WEST);
1217             }
1218
1219         //c = at40k.cell(2, 22);
1220         //c.h(L0, true);
1221         //c.yi(L0);
1222
1223         c = at40k.cell(1, 21);
1224         c.v(L0, true);
1225         c.v(L2, true);
1226         c.yi(L0);
1227         c.out(L2, true);
1228         c.ylut(LUT_SELF);
1229         c.c(YLUT);
1230         c.b(false);
1231         c.f(false);
1232         c.oe(NONE);
1233         c.yo(false);
1234
1235         
1236
1237         c = at40k.cell(13, 22);
1238         c.xlut(LUT_OTHER | 0xF0);
1239         c.c(XLUT);
1240         c.t(false, false, true);
1241         c.b(false);
1242         c.f(false);
1243         c.ylut(0xF0);
1244         c.yi(EAST);
1245         c.yo(false);
1246         /*
1247         // this gate detects a rising edge on its Xin (delayed copy on Yin); when viewed, it inverts its state
1248         c = at40k.cell(14, 22);
1249         c.ylut(0x00);
1250         c.c(XLUT);
1251         c.f(false);
1252         c.b(false);
1253         c.t(false, false, true);
1254         c.xi(SE);
1255         c.yi(SOUTH);
1256         c.yo(false);
1257         c.xo(false);
1258         c.ylut(0xA6); // (x & !z) ? ~y : y
1259         c.xlut(LUT_SELF); 
1260
1261         c = at40k.cell(14, 20);
1262         c.ylut(LUT_OTHER);
1263         c.xi(NE);
1264         c = at40k.cell(14, 21);
1265         c.ylut(LUT_SELF);
1266         c.xi(SOUTH);
1267
1268         c = at40k.cell(13, 22);
1269         c.xlut(0x00);
1270         c.xlut(LUT_OTHER);// | 0xF0);
1271 */
1272         //c = at40k.cell(13, 22);
1273         //copy(c, NW, EAST);
1274         /*
1275         c.ylut(0x00);
1276         c.c(YLUT);
1277         c.f(false);
1278         c.b(false);
1279         c.t(false, false, true);
1280         c.xi(SE);
1281         c.yi(NORTH);
1282         c.yo(false);
1283         c.xo(false);
1284         c.ylut(0x54);  // (x || z) & !y
1285         */
1286
1287         /*        
1288         c = at40k.cell(2, 21);
1289         c.ylut(0x00);
1290         c.c(YLUT);
1291         c.f(false);
1292         c.b(false);
1293         c.t(false, false, true);
1294         c.xi(SE);
1295         c.yi(WEST);
1296         c.yo(false);
1297         c.xo(false);
1298         c.ylut(0xE8);
1299  
1300        //at40k.cell(2, 21).xlut(0xF0);
1301
1302         at40k.cell(3, 22).ylut(LUT_OTHER);
1303         at40k.cell(3, 22).xi(SW);
1304         */
1305         //at40k.iob_top(5, true).enableOutput(SOUTH);
1306         //at40k.iob_top(5, false).enableOutput(SE);
1307     }
1308
1309     public static int yofs = mullers ? 19 : 22;
1310     public static void counter(At40k at40k, AvrDrone device) throws Exception {
1311         // watch for rising edge from south, emit pulse on Xout (to NE)
1312         //copy(at40k.cell(16,23), SW, WEST);
1313         
1314         for(int x=22; x>=1; x-=2) {
1315             pulse_detect(at40k.cell(x, yofs), SE,      false);
1316             pulse_detect(at40k.cell(x, yofs-1), EAST,    true);
1317             pulse_copy(at40k.cell(x-1, yofs), SE, SOUTH, false);
1318             pulse_copy(at40k.cell(x-1, yofs-1), NE, NORTH, true);
1319
1320             //pulse_detect(at40k.cell(15, 22), NORTH, false);
1321             //pulse_detect(at40k.cell(16, 22), NW,    true);
1322             //pulse_copy(at40k.cell(16, 21), NW, WEST, false);
1323             //pulse_copy(at40k.cell(15, 21), NE, EAST, true);
1324         }
1325         for(int x=23; x>1; x-=2) {
1326             pulse_detect(at40k.cell(x-1, yofs-2), SW,    false);
1327             pulse_detect(at40k.cell(x-1, yofs-3), WEST,  true);
1328             pulse_copy(at40k.cell(x, yofs-2), SW, SOUTH, false);
1329             pulse_copy(at40k.cell(x, yofs-3), NW, NORTH, true);
1330
1331             //pulse_detect(at40k.cell(15, 22), NORTH, false);
1332             //pulse_detect(at40k.cell(16, 22), NW,    true);
1333             //pulse_copy(at40k.cell(16, 21), NW, WEST, false);
1334             //pulse_copy(at40k.cell(15, 21), NE, EAST, true);
1335         }
1336         copy(at40k.cell(1, yofs-2), SOUTH, SOUTH);
1337         copy(at40k.cell(1, yofs-3), NORTH, NORTH);
1338         at40k.cell(1, yofs-3).ylut(~at40k.cell(1, yofs-3).ylut());
1339         at40k.cell(1, yofs-3).xlut(~at40k.cell(1, yofs-3).xlut());
1340
1341         copy(at40k.cell(23, yofs), SOUTH, SOUTH);
1342         copy(at40k.cell(23, yofs-1), SOUTH, SOUTH);
1343
1344         for(int i=23; i>yofs; i--) copy(at40k.cell(1, i), SOUTH, SOUTH);
1345
1346         //at40k.iob_top(1, true).slew(SLOW);
1347         //at40k.iob_top(1, false).slew(SLOW);
1348
1349     }
1350     public static void fill(At40k at40k, AvrDrone device, int num) throws Exception {
1351         //muller(at40k.cell(PIPELEN,22), NE, WEST);
1352         At40k.Cell a = at40k.cell(10,22);
1353         At40k.Cell b = at40k.cell(11,22);
1354         a.ylut(0x00);
1355         for(int i=0; i<num; i++) {
1356             //System.out.println(i);
1357             b.lut(0xff, 0xff);
1358             device.flush();
1359             try { Thread.sleep(1); } catch (Exception e) { }
1360             b.lut(0x00, 0x00);
1361             device.flush();
1362             try { Thread.sleep(1); } catch (Exception e) { }
1363         }
1364         b.ylut(0xB2);
1365         a.ylut(0xB2);
1366     }
1367     public static void showit(At40k dev, AvrDrone drone, final Visualizer vis) {
1368         final long then = System.currentTimeMillis();
1369         final Graphics g = vis.getGraphics();
1370         g.setFont(new Font("sansserif", Font.BOLD, 24));
1371         final Color red = new Color(0xff, 0x99, 0x99);
1372         final Color green = new Color(0x99, 0xff, 0x99);
1373         for(int xx=0; xx<=22; xx++) {
1374             for(int yy=23; yy>=0; yy--) {
1375                 //for(int xx=5; xx<=PIPELEN-1; xx++) {
1376                 //for(int yy=21; yy<=22; yy++) {
1377                 final int x = xx;
1378                 final int y = yy;
1379                 final At40k.Cell cell = dev.cell(x, y);
1380                 if ((cell.ylut()&0xff)!=0xB2) continue;
1381                 AvrDrone.ByteCallback bc = new AvrDrone.ByteCallback() {
1382                         public void call(byte b) throws Exception {
1383                             boolean v = (b & 0x80) != 0;
1384                             vis.drawCell(g, x, y, v?red:green);
1385                             //if (x==PIPELEN-1 && y==22) System.out.println("time: " + (System.currentTimeMillis()-then));
1386                         }
1387                     };
1388                 scan(dev, cell, NONE, true);
1389                 drone.readBus(bc);
1390                 //scan(dev, cell, YLUT, false);
1391                 cell.v(L3, false);
1392                 dev.cell(x, 15).h(L3, false);
1393                 dev.cell(x, 15).v(L3, false);
1394             }
1395         }
1396     }
1397     public static void drain(At40k at40k, AvrDrone device) throws Exception {
1398         At40k.Cell a = at40k.cell(10,22);
1399         At40k.Cell b = at40k.cell(11,22);
1400         a.lut(0x00, 0x00);
1401         b.lut(0x00, 0x00);
1402         for(int i=0; i<30; i++) {
1403             //System.out.println(i);
1404             a.lut(0xff, 0xff);
1405             device.flush();
1406             try { Thread.sleep(1); } catch (Exception e) { }
1407             a.lut(0x00, 0x00);
1408             device.flush();
1409             try { Thread.sleep(1); } catch (Exception e) { }
1410         }
1411         b.ylut(0xB2);
1412         a.ylut(0xB2);
1413     }
1414     public static void doitx(At40k at40k, AvrDrone device) throws Exception {
1415         for(int i=5; i<PIPELEN+1; i++) bounce(at40k.cell(i, 23), SE,                     SOUTH);
1416         for(int x=5; x<PIPELEN;   x++) muller(at40k.cell(x, 22), x==PIPELEN-1 ? SE : NE, WEST);
1417         
1418         bounce(at40k.cell(PIPELEN,  21), NW, WEST);
1419         
1420         for(int x=5; x<PIPELEN;   x++) muller(at40k.cell(x, 21), SW,                     x==PIPELEN-1 ? NORTH : EAST);
1421         for(int x=4; x<PIPELEN+1; x++) bounce(at40k.cell(x, 20), NW,                     NORTH);
1422         
1423         bounce(at40k.cell(4, 22), SE, EAST);
1424         //muller(at40k.cell(4PIPELEN-1,21), SW, NORTH);
1425         
1426         //muller(at40k.cell(4,22), NE, WEST);
1427         //at40k.cell(4,22).ylut(0xEE);
1428         muller(at40k.cell(5, 22), NE, SOUTH);
1429         muller(at40k.cell(5, 21), NW, EAST);
1430         /*
1431         for(int x=4; x>=0; x--) {
1432             at40k.cell(x, 21).ylut(0xAA);
1433             at40k.cell(x, 21).yi(EAST);
1434             at40k.cell(x, 21).yo(false);
1435         }
1436
1437         at40k.cell(0, 22).ylut(0xAA);
1438         at40k.cell(0, 22).yi(SOUTH);
1439         at40k.cell(0, 22).yo(false);
1440
1441         at40k.cell(0, 23).ylut(~0xAA);
1442         at40k.cell(0, 23).xlut(~0xcc);
1443         at40k.cell(0, 23).yi(SOUTH);
1444         at40k.cell(0, 23).yo(false);
1445         */
1446         for(int x=3; x<=23; x+=2) {
1447             pulse_detect(at40k.cell(x-1, 19), SW,    false);
1448             pulse_detect(at40k.cell(x-1, 18), WEST,  true);
1449             pulse_copy(at40k.cell(x, 19), SW, SOUTH, false);
1450             pulse_copy(at40k.cell(x, 18), NW, NORTH, true);
1451
1452             if (x<17) {
1453                 pulse_detect(at40k.cell(x-1, 16), SW,    false);
1454                 pulse_detect(at40k.cell(x-1, 15), WEST,  true);
1455                 pulse_copy(at40k.cell(x, 16), SW, SOUTH, false);
1456                 pulse_copy(at40k.cell(x, 15), NW, NORTH, true);
1457             }
1458             //pulse_detect(at40k.cell(15, 22), NORTH, false);
1459             //pulse_detect(at40k.cell(16, 22), NW,    true);
1460             //pulse_copy(at40k.cell(16, 21), NW, WEST, false);
1461             //pulse_copy(at40k.cell(15, 21), NE, EAST, true);
1462         }
1463         for(int x=14; x>=1; x--)
1464             copy(at40k.cell(x, 17), EAST, EAST);
1465         for(int x=4; x>=0; x--)
1466             copy(at40k.cell(x, 21), EAST, EAST);
1467         copy(at40k.cell(13, 17), SOUTH, SOUTH);
1468
1469         copy(at40k.cell(0, 20), NORTH, NORTH);
1470         copy(at40k.cell(0, 19), NORTH, NORTH);
1471         copy(at40k.cell(0, 18), NORTH, NORTH);
1472         copy(at40k.cell(0, 17), NORTH, NORTH);
1473         copy(at40k.cell(0, 16), NORTH, NORTH);
1474         copy(at40k.cell(1, 16), WEST, WEST);
1475         copy(at40k.cell(1, 15), NORTH, NORTH);
1476
1477         copy(at40k.cell(1, 20), SOUTH, SOUTH);
1478         copy(at40k.cell(1, 19), SOUTH, SOUTH);
1479         copy(at40k.cell(1, 18), SOUTH, SOUTH);
1480
1481         for(int y=20; y<=23; y++)
1482             copy(at40k.cell(23, y), SOUTH, SOUTH);
1483
1484
1485         //for(int x=19; x<=23; x++)
1486         //copy(at40k.cell(x, 0), WEST, WEST);
1487         //copy(at40k.cell(18, 19), NW, NW);
1488         //at40k.iob_top(5, true).enableOutput(SOUTH);
1489         //at40k.iob_top(5, false).enableOutput(SOUTH);
1490     }
1491 }