checkpoint
authoradam <adam@megacz.com>
Tue, 21 Mar 2006 15:56:05 +0000 (16:56 +0100)
committeradam <adam@megacz.com>
Tue, 21 Mar 2006 15:56:05 +0000 (16:56 +0100)
src/edu/berkeley/obits/AtmelSerial.java
src/edu/berkeley/obits/device/atmel/At40k.java
src/edu/berkeley/obits/device/atmel/AtmelDevice.java
src/edu/berkeley/obits/device/atmel/AvrDrone.c
src/edu/berkeley/obits/device/atmel/AvrDrone.java

index a7a4dec..3216a3a 100644 (file)
@@ -1,6 +1,10 @@
 package edu.berkeley.obits;
 
+import static edu.berkeley.obits.device.atmel.AtmelDevice.Constants.*;
 import edu.berkeley.obits.device.atmel.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.color.*;
 import org.ibex.util.*;
 import java.io.*;
 import java.util.*;
@@ -36,7 +40,7 @@ public class AtmelSerial {
             device.flush();
             long end = System.currentTimeMillis();
             Log.info(AtmelSerial.class, "finished in " + ((end-begin)/1000) + "s");
-            Thread.sleep(3000);
+            Thread.sleep(1000);
             Log.info(AtmelSerial.class, "issuing command");
 
             //at40k.iob_top(2, true).oe(false);
@@ -57,11 +61,308 @@ public class AtmelSerial {
                 //System.out.println("tick");
                 //at40k.cell(0x01, 0x17).xlut((byte)0x);
 
-            at40k.cell(0x04, 0x17).xlut((byte)~0x10);
-            at40k.cell(0x04, 0x17).ylut((byte)0x10);
-            at40k.cell(0x04, 0x17).xo(true);
+            /*
+            System.out.println(Integer.toString(0xff & at40k.cell(0x01, 0x17).xlut(), 16));
+            System.out.println(Integer.toString(0xff & at40k.cell(0x01, 0x17).ylut(), 16));
+            at40k.cell(0x01, 0x17).ylut((byte)0xff);
+            */
+
+            //at40k.cell(0x01, 0x17).wi(L1);
+            /*
+            System.out.println("a: " + at40k.new SectorWire(true, 0, 4, 0x17).driverRight());
+            System.out.println("b: " + at40k.new SectorWire(true, 1, 4, 0x17).driverRight());
+            At40k.SectorWire h0p0 = at40k.new SectorWire(true, 0, 0, 0x17);
+            At40k.SectorWire h0p1 = at40k.new SectorWire(true, 1, 0, 0x17);
+            At40k.SectorWire h0p2 = at40k.new SectorWire(true, 2, 0, 0x17);
+            At40k.SectorWire h4p0 = at40k.new SectorWire(true, 0, 4, 0x17);
+            At40k.SectorWire h4p1 = at40k.new SectorWire(true, 1, 4, 0x17);
+            At40k.SectorWire h4p2 = at40k.new SectorWire(true, 2, 4, 0x17);
+
+            //h4p1.drives(h0p1, false);
+            //at40k.cell(0x04, 0x17).out(L1, false);
+            //at40k.cell(0x04, 0x17).h(L0, false);
+
+            for(int plane=0; plane<5; plane++) {
+                at40k.new SectorWire(true, plane,     4, 0x17).drives(at40k.new SectorWire(true, plane,     0, 0x17), false);
+                at40k.cell(0x04, 0x17).out(plane, false);
+                at40k.cell(0x04, 0x17).h(plane, false);
+                at40k.cell(0x01, 0x17).h(plane, false);
+            }
+            try { Thread.sleep(2000); } catch (Exception e) { }
+
+            int plane=0;
+            at40k.new SectorWire(true, plane, 4, 0x17).drives(at40k.new SectorWire(true, plane, 0, 0x17), true);
+            at40k.cell(0x04, 0x17).out(plane, true);
+            at40k.cell(0x04, 0x17).h(plane, true);
+            at40k.cell(0x01, 0x17).h(plane, true);
+            at40k.cell(0x01, 0x17).wi(plane);
+
+            */
+
+            /*
+            System.out.println("xlut is " + hex(at40k.cell(0x04, 0x17).xlut()));
+            System.out.println("ylut is " + hex(at40k.cell(0x04, 0x17).ylut()));
+            At40k.Cell cell = at40k.cell(0x04, 0x17);
+            //cell.xlut(0xff);
+            //cell.f(false);
+            System.out.println(cell.c());
+            cell.c(YLUT);
+            cell.ylut(0x4D);
+            cell.xlut(0x00);
+
+            cell.b(false);
+            cell.f(false);
+            //cell.t(false, false, true);
+            cell.t(false, true, false);
+            cell.out(L3, true);
+            cell.wi(L3);
+
+            cell.yo(false);
+            cell.h(L0, false);
+            cell.h(L1, false);
+            cell.h(L2, false);
+            cell.h(L3, false);
+            cell.h(L4, false);
+
+            for(int i=3; i>=1; i--) {
+                at40k.cell(i, 0x17).yi(EAST);
+                at40k.cell(i, 0x17).ylut(0x55);
+                at40k.cell(i, 0x17).yo(false);
+            }
+            */
+
+            //System.out.println("reading port status: " + Integer.toString(device.readBus() & 0xff, 16));
+
+
+            // blank these out
+            /*
+            at40k.cell(23, 8).ylut(0xff);
+            at40k.cell(23, 11).ylut(0xff);
+            at40k.iob_right(8, true).enableOutput();
+            at40k.iob_right(11, true).enableOutput();
+            */
+            //for(int x=4;  x<=22; x++) swap(at40k.cell(x, 22), NW, NORTH);
+
+
+            // entry cell: just copy X->X Y->Y
+            //at40k.cell(4,23).b(false);
+            //at40k.cell(4,23).yo(false);
+            //at40k.cell(4,23).ylut(at40k.cell(4,23).xlut());
+            //at40k.cell(4,23).xo(false);
+            /*
+            at40k.cell(4,23).xlut(0x55);
+            at40k.cell(4,23).ylut(0x55);
+            */
+            /*
+            at40k.cell(4,23).xlut(0x71);
+            at40k.cell(4,23).ylut(0x44);
+            at40k.cell(4,23).c(YLUT);
+            at40k.cell(4,23).f(false);
+            at40k.cell(4,23).t(false, false, true);
+            */
+
+            //for(int x=6;  x<=23; x++) copy(at40k.cell(x, 23), NW, WEST);  // top row copies to the right
+            /*
+            copy(at40k.cell(5, 22), NW, NORTH);
+            for(int x=6;  x<=22; x++) copy(at40k.cell(x, 22), NW, WEST);  // second top row copies to the right
+            //for(int y=22; y>=10; y--) copy(at40k.cell(23, y), NW, NORTH); // right edge copies down
+            for(int y=21; y>=9;  y--) copy(at40k.cell(22, y), NW, NORTH); // second right edge copies down
+            copy(at40k.cell(23, 9), NW, WEST);                            // second output
+            */
+            /*
+            handshaker(at40k.cell(4,23));
+            at40k.cell(4,23).xi(NW);
+            at40k.cell(4,23).yi(SOUTH);
+
+            //handshaker(at40k.cell(5,23));
+            //at40k.cell(5,23).yi(NORTH);
 
+            at40k.cell(5,23).yi(NORTH);
+            at40k.cell(5,23).xlut(0x55);
+            at40k.cell(5,23).xi(SW);
+            at40k.cell(5,23).ylut(0x55);
+            at40k.cell(5,22).yi(NORTH);
+            at40k.cell(5,22).xlut(0x55);
 
+            bounce(at40k.cell(4,22));
+
+            // cell southeast of entry cell
+            at40k.cell(3,22).xi(NE);      // NW->xin
+            at40k.cell(3,22).ylut(0x33);  // xin->y
+            at40k.cell(3,22).yo(false);   // y->yout
+            copy(at40k.cell(3, 21), NW, NORTH);  // second top row copies to the right
+            copy(at40k.cell(4, 21), NW, EAST);  // second top row copies to the right
+            copy(at40k.cell(5, 21), NW, EAST);  // second top row copies to the right
+            copy(at40k.cell(6, 21), NW, EAST);  // second top row copies to the right
+            copy(at40k.cell(6, 22), NW, SOUTH);  // second top row copies to the right
+            */
+            /*
+            at40k.cell(05,22).xlut(0xff);
+            at40k.cell(05,22).ylut(0xff);
+            at40k.cell(05,22).c(XLUT);
+            at40k.cell(05,22).f(false);
+            at40k.cell(05,22).b(false);
+            at40k.cell(05,22).oe(NONE);
+            at40k.cell(05,22).v(L3, true);
+            at40k.cell(05,22).out(L3, true);
+            */
+            at40k.cell(21,15).yi(WEST);
+            at40k.cell(21,15).ylut(0xAA);
+            at40k.cell(22,15).yi(WEST);
+            at40k.cell(22,15).ylut(0xAA);
+            at40k.cell(23,15).h(3, true);
+            at40k.cell(23,15).yi(L3);
+            at40k.cell(23,15).ylut(0xAA);
+            at40k.iob_right(15, true).enableOutput(WEST);
+            /*
+            at40k.cell(22,11).ylut(0xff);
+            at40k.cell(23,11).yi(L3);
+            //at40k.cell(23,11).yi(WEST);
+            //at40k.cell(23,11).xi(L1);
+            at40k.cell(23,11).ylut(0xAA);
+            at40k.iob_right(11, true).enableOutput(WEST);
+            at40k.cell(23,11).v(L3, true);
+            at40k.cell(23,11).yo(false);
+            //at40k.flush();
+            */
+            int vx=04;
+            int vv=23;
+            /*
+            System.out.println("correct: " + at40k.cell(19,15).hwire(L3) + " drives " + at40k.cell(20,15).hwire(L3));
+            System.out.println("correct: " + at40k.cell(15,15).hwire(L3) + " drives " + at40k.cell(19,15).hwire(L3));
+            System.out.println("correct: " + at40k.cell(11,15).hwire(L3) + " drives " + at40k.cell(15,15).hwire(L3));
+            System.out.println("correct: " + at40k.cell(07,15).hwire(L3) + " drives " + at40k.cell(11,15).hwire(L3));
+
+            at40k.cell(19,15).hwire(L3).drives(at40k.cell(20,15).hwire(L3), true);
+            at40k.cell(15,15).hwire(L3).drives(at40k.cell(19,15).hwire(L3), true);
+            at40k.cell(11,15).hwire(L3).drives(at40k.cell(15,15).hwire(L3), true);
+            at40k.cell(07,15).hwire(L3).drives(at40k.cell(11,15).hwire(L3), true);
+            */
+            //at40k.cell(05,vv).xlut(0xff);
+            //at40k.cell(05,vv).ylut(0xff);
+            /*
+            at40k.cell(vx,vv).c(YLUT);
+            at40k.cell(vx,vv).f(false);
+            at40k.cell(vx,vv).b(false);
+            at40k.cell(vx,vv).oe(NONE);
+            at40k.cell(vx,vv).v(L3, true);
+            at40k.cell(vx,vv).out(L3, true);
+            */
+            /*
+            at40k.cell(vx,15).v(L3, true);
+            at40k.cell(vx,15).h(L3, true);
+            at40k.cell(vx,19).vwire(L3).drives(at40k.cell(vx,15).vwire(L3), true);
+            at40k.cell(vx,23).vwire(L3).drives(at40k.cell(vx,19).vwire(L3), true);
+            */
+
+            //at40k.cell(5,23).ylut(0x00);
+            //at40k.cell(6,22).ylut(0xff);
+            //at40k.cell(22,11).ylut(0xff);
+            /*
+            At40k.Cell cell = at40k.cell(4, 16);
+            cell.xlut(0xff);
+            cell.ylut(0xff);
+            cell.b(false);
+            cell.f(false);
+            cell.c(XLUT);
+            cell.h(L3, true);
+            cell.v(L3, true);
+            cell.out(L3, true);
+            cell.oe(NONE);
+            */
+            //scan(at40k, cell, YLUT, true);
+            //scan(at40k, cell, YLUT, false);
+
+            device.scanFPGA();
+            Visualizer v = new Visualizer(at40k, device);
+            v.show();
+            v.setSize(1380, 1080);
+            At40k.Cell cell = at40k.cell(4, 23);
+            Image img = v.createImage(v.getWidth(), v.getHeight());
+            /*
+            int x = 1;
+            int y = 14;
+            cell = at40k.cell(x,y);
+            scan(at40k, cell, YLUT, true);
+            cell.c(YLUT);
+            cell.b(false);
+            cell.f(false);
+            cell.oe(NONE);
+            cell.ylut(0xff);
+            */
+            for(int x=0; x<10; x++)
+                for(int y=20; y<23; y++) {
+                    scan(at40k, cell, YLUT, true);
+                    //v.paint(img.getGraphics());
+                    //v.getGraphics().drawImage(img, 0, 0, null);
+                    cell.ylut(0xff);
+                    cell.c(YLUT);
+                    cell.b(false);
+                    cell.f(false);
+                    cell.ylut(0xff);
+                    cell.ylut(0xff);
+                    cell.ylut(0xff);
+                    cell.ylut(0xff);
+                    //try { Thread.sleep(1000); } catch (Exception e) { }
+                    int a = device.readBus();
+                    cell.ylut(0x00);
+                    int b = device.readBus();
+                    scan(at40k, cell, YLUT, false);
+                    System.out.println("scan " + x+","+y+" => " + a + " " + b);
+                }
+
+            for(int i=0; i<10000; i++) {
+                v.refresh();
+                try { Thread.sleep(100); } catch (Exception e) { }
+            }
+            //cell.ylut(0x09);
+
+            //at40k.cell(0x01, 0x17).h(0, false);
+            //at40k.cell(0x01, 0x17).xi(NE);
+            //at40k.cell(0x01, 0x17).ylut((byte)0x55);
+
+            //at40k.cell(0x04, 0x17).xlut((byte)0x10);
+            //at40k.cell(0x04, 0x17).ylut((byte)0x10);
+            //at40k.cell(0x04, 0x17).yo(false);
+            //at40k.cell(0x04, 0x17).xo();
+
+            /*
+            at40k.cell(0x01, 0x17).xi(L0);
+            at40k.cell(0x01, 0x17).h(L0, true);
+            */
+            /*
+            at40k.cell(0x03, 0x17).xlut((byte)0x55);
+            at40k.cell(0x03, 0x17).ylut((byte)0x55);
+            at40k.cell(0x03, 0x17).yi(EAST);
+            at40k.cell(0x03, 0x17).ylut((byte)0x55);
+            at40k.cell(0x03, 0x17).yo(true);
+
+            at40k.cell(0x03, 0x17).f(false);
+            at40k.cell(0x03, 0x17).c(XLUT);
+            at40k.cell(0x03, 0x17).oe(NONE);
+            at40k.cell(0x03, 0x17).out(L0, true);
+
+            at40k.cell(0x02, 0x17).yi(EAST);
+            at40k.cell(0x02, 0x17).ylut((byte)0x55);
+            at40k.cell(0x02, 0x17).yo(false);
+
+            at40k.cell(0x01, 0x17).yi(EAST);
+            at40k.cell(0x01, 0x17).ylut((byte)0x55);
+            at40k.cell(0x01, 0x17).yo(false);
+
+            at40k.cell(0x01, 0x17).h(L0, true);
+            at40k.cell(0x01, 0x17).v(L0, false);
+            */
+            //at40k.cell(0x01, 0x17).yi(L0);
+            //at40k.cell(0x01, 0x17).xi(L0);
+            //at40k.cell(0x01, 0x17).ylut((byte)0x33);
+
+            /*
+            at40k.cell(0x03, 0x17).h(L0, true);
+            at40k.cell(0x03, 0x17).out(L0, true);
+            at40k.cell(0x03, 0x17).c(XLUT);
+            at40k.cell(0x03, 0x17).f(false);
+            */
             /*
             at40k.cell(0x01, 0x17).xin(4);
             at40k.cell(0x01, 0x17).yin(4);
@@ -99,4 +400,264 @@ public class AtmelSerial {
         } catch (Exception e) { e.printStackTrace(); }
     }
 
+    public static void scan(At40k dev, At40k.Cell cell, int source, boolean setup) {
+        if (setup) {
+            cell.c(source);
+            cell.b(false);
+            cell.f(false);
+        }
+        cell.v(L3, setup);
+        cell.out(L3, setup);
+
+        At40k.SectorWire sw = cell.vwire(L3);
+        //System.out.println("wire is: " + sw);
+        while(sw.row > (12 & ~0x3) && sw.south() != null) {
+            //System.out.println(sw + " -> " + sw.south());
+            sw.drives(sw.south(), setup);
+            sw = sw.south();
+        }
+        while(sw.row < (12 & ~0x3) && sw.north() != null) {
+            //System.out.println(sw + " -> " + sw.north());
+            sw.drives(sw.north(), setup);
+            sw = sw.north();
+        }
+        //cell = dev.cell(19, 15);
+        cell = dev.cell(cell.col, 15);
+        /*
+        System.out.println("cell is " + cell);
+        cell.xlut(0xff);
+        cell.ylut(0xff);
+        cell.b(false);
+        cell.f(false);
+        cell.c(XLUT);
+        cell.out(L3, true);
+        cell.oe(NONE);
+        */
+        cell.h(L3, setup);
+        cell.v(L3, setup);
+        sw = cell.hwire(L3);
+        while(sw.east() != null) {
+            //System.out.println(sw + " -> " + sw.east());
+            sw.drives(sw.east(), setup);
+            sw = sw.east();
+        }
+    }
+
+    public static void copy(At40k.Cell cell, int xdir, int ydir) {
+        cell.xlut((byte)0x33);
+        cell.ylut((byte)0x55);
+        cell.xi(xdir);
+        cell.yi(ydir);
+        cell.xo(false);
+        cell.yo(false);
+    }
+    public static String hex(int x) {
+        return Long.toString(x & 0xffffffffL, 16);
+    }
+
+    public static void bounce(At40k.Cell cell) {
+        cell.xlut((byte)0x33);
+        cell.ylut((byte)0x55);
+        cell.xi(NE);
+        cell.yi(NORTH);
+        cell.xo(false);
+        cell.yo(false);
+    }
+    public static void handshaker(At40k.Cell cell) {
+        cell.xlut(0x22);
+        cell.ylut(0x71);
+        cell.c(XLUT);
+        cell.f(false);
+        cell.t(false, false, true);
+    }
+
+    public static class Visualizer extends Frame implements MouseMotionListener {
+        public static final int WIDTH = 40;
+        public static final int HEIGHT = 40;
+        public static final int LW = 15;
+        public static final int LH = 15;
+        public static final Color RED  = new Color(0xaa, 0x55, 0x55);
+        public static final Color BLUE = new Color(0x55, 0x55, 0xaa);
+        private final At40k dev;
+        private final AvrDrone drone;
+        int selx = -1;
+        int sely = -1;
+        public Visualizer(At40k dev, AvrDrone drone) {
+            this.dev = dev;
+            this.drone = drone;
+            show();
+            addMouseMotionListener(this);
+        }
+        public void mouseMoved(MouseEvent e) {
+            int x = e.getX();
+            int y = e.getY();
+            if (selx >= 0 && selx < 24 && sely >= 0 && sely < 24) {
+                int cx = selx;
+                int cy = sely;
+                selx = -1;
+                sely = -1;
+                drawCell(getGraphics(), cx, cy);
+                drawSector(getGraphics(), dev.cell(cx, cy).sector());
+            }
+            selx = (x-20)/(WIDTH+2);
+            sely = (23 - (y-20)/(HEIGHT+2))+1;
+            if (selx >= 0 && selx < 24 && sely >= 0 && sely < 24) {
+                drawCell(getGraphics(), selx, sely);
+                drawSector(getGraphics(), dev.cell(selx, sely).sector());
+            }
+        }
+        public void mouseDragged(MouseEvent e) {
+        }
+        public void paint(Graphics g) {
+            g.setColor(Color.white);
+            g.fillRect(0, 0, getWidth(), getHeight());
+            for(int x=0; x<24; x++)
+                for(int y=0; y<24; y++)
+                    drawCell(g,x,y);
+            for(int x=0; x<=23; x+=4)
+                for(int y=23; y>=0; y-=4) 
+                    drawSector(g, dev.cell(x, y).sector());
+            g.setColor(BLUE);
+            g.drawString("Ready", (5*(WIDTH+2))+20, 40);
+            g.setColor(RED);
+            g.drawString("Send",  (3*(WIDTH+2))+20, 40);
+            g.setColor(BLUE);
+            refresh();
+        }
+        public void refresh() {
+            Graphics g = getGraphics();
+            int data = drone.readBus() & 0xff;
+            for(int i=0; i<8; i++) {
+                g.setColor((data & (1<<i))==0 ? Color.black : Color.green);
+                g.drawString("D"+i,  (24*(WIDTH+2))+20, ((23-(i+7))*(HEIGHT+2))+60-HEIGHT/2);
+            }
+        }
+        public int left(At40k.Cell cell) { return (cell.col)   *(WIDTH+2)+20; }
+        public int top(At40k.Cell cell)  { return (23-cell.row)*(HEIGHT+2)+60; }
+        public void drawSector(Graphics g, At40k.Sector sector) {
+            g.setColor(Color.gray);
+            ((Graphics2D)g).setStroke(new BasicStroke(1));
+            int px = ((sector.col)*(WIDTH+2))+20-1;
+            int py = ((23-(sector.row+3))*(HEIGHT+2))+60-1;
+            g.drawRect(px, py, (WIDTH+2)*4+2, (HEIGHT+2)*4+2);
+            for(int dir=0; dir<2; dir++) {
+                boolean h = dir==0;
+                for(int y=h?sector.row:sector.col; y<(h?sector.row+4:sector.col+4); y++)
+                    for(int plane=0; plane<=4; plane++) {
+                        At40k.Cell cell      = h ? dev.cell(sector.col,   y) : dev.cell(y, sector.row);
+                        At40k.Cell cell_east = h ? dev.cell(sector.col-1, y) : dev.cell(y, sector.row-1);
+                        At40k.Cell cell_west = h ? dev.cell(sector.col+4, y) : dev.cell(y, sector.row+4);
+                        boolean draw = false;
+                        if (h) {
+                            if (cell_east!=null &&
+                                (cell_east.hwire(plane).drives(cell.hwire(plane)) ||
+                                 cell_east.hwire(plane).drives(cell.hwire(plane))))
+                                draw = true;
+                            if (cell_west!=null &&
+                                (cell_west.hwire(plane).drives(cell.hwire(plane)) ||
+                                 cell_west.hwire(plane).drives(cell.hwire(plane))))
+                                draw = true;
+                        } else {
+                            if (cell_east!=null &&
+                                (cell_east.vwire(plane).drives(cell.vwire(plane)) ||
+                                 cell_east.vwire(plane).drives(cell.vwire(plane))))
+                                draw = true;
+                            if (cell_west!=null &&
+                                (cell_west.vwire(plane).drives(cell.vwire(plane)) ||
+                                 cell_west.vwire(plane).drives(cell.vwire(plane))))
+                                draw = true;
+                        }
+                        if (!draw)
+                            for(int x=h?sector.col:sector.row; x<(h?sector.col+4:sector.row+4); x++)
+                                if (((h ? dev.cell(x,y).hx(plane) : dev.cell(y,x).vx(plane))) ||
+                                    (h?dev.cell(x,y).out(plane):dev.cell(y,x).out(plane)))
+                                    draw = true;
+                        if (draw) {
+                            g.setColor(new Color(0xff, 0x00, 0xff));
+                            if (h) {
+                                g.drawLine(left(cell),
+                                           top(cell)+3,
+                                           left(cell) + 4*(WIDTH+2),
+                                           top(cell)+3
+                                           );
+                            } else {
+                                g.drawLine(left(cell)+3,
+                                           top(cell) + (HEIGHT+2),
+                                           left(cell)+3,
+                                           top(cell) - 3*(HEIGHT+2)
+                                           );
+                            }
+                        }
+                    }
+            }
+        }
+        public void drawCell(Graphics g, int cx, int cy) {
+            int x = (cx*(WIDTH+2))+20;
+            int y = ((23-cy)*(HEIGHT+2))+60;
+            if (g.getClipBounds() != null && !g.getClipBounds().intersects(new Rectangle(x, y, x+WIDTH, y+HEIGHT))) return;
+
+            At40k.Cell cell = dev.cell(cx, cy);
+            g.setColor(Color.white);
+            g.fillRect(x, y, WIDTH, HEIGHT);
+
+            g.setColor((selx==cx && sely==cy) ? Color.red : Color.black);
+            g.drawRect(x, y, WIDTH, HEIGHT);
+
+            g.setColor((selx==cx && sely==cy) ? Color.red : Color.gray);
+            g.drawRect(x+(WIDTH-(LW*2))/2-1,    y+(HEIGHT-LW)/2-1, LW*2+1, LH+1);
+
+            g.setColor(RED);
+            //g.fillRect(x+(WIDTH-(LW*2))/2,    y+(HEIGHT-LW)/2, LW,   LH);
+            g.setColor(Color.white);
+            //g.drawString("1", x+(WIDTH-(LW*2))/2,    y+(HEIGHT-LW)/2);
+
+            g.setColor(BLUE);
+            //g.fillRect(x+(WIDTH-(LW*2))/2+LW, y+(HEIGHT-LW)/2, LW,   LH);
+            g.setColor(Color.white);
+            //g.drawString("0", x+(WIDTH-(LW*2))/2+LW,    y+(HEIGHT-LW)/2);
+
+            g.setColor(BLUE);
+            ((Graphics2D)g).setStroke(new BasicStroke((float)1.5));
+            switch(cell.yi()) {
+                case NORTH: g.drawLine(x+WIDTH/2+5,  y-10,        x+WIDTH/2+5, y+HEIGHT/2); break;
+                case SOUTH: g.drawLine(x+WIDTH/2-5,  y+HEIGHT+10, x+WIDTH/2-5, y+HEIGHT/2); break;
+                case EAST:  g.drawLine(x+WIDTH+10, y+HEIGHT/2+5,  x+WIDTH/2, y+HEIGHT/2+5); break;
+                case WEST:  g.drawLine(x-10,       y+HEIGHT/2-5,  x+WIDTH/2, y+HEIGHT/2-5); break;
+                case NONE:  break;
+            }
+            g.setColor(RED);
+            ((Graphics2D)g).setStroke(new BasicStroke((float)1.5));
+            switch(cell.xi()) {
+                case NW: g.drawLine(x-10+3,       y-10,        x+WIDTH/2+3, y+HEIGHT/2); break;
+                case SW: g.drawLine(x-10-3,       y+HEIGHT+10, x+WIDTH/2-3, y+HEIGHT/2); break;
+                case NE: g.drawLine(x+WIDTH+10+3, y-10,        x+WIDTH/2+3, y+HEIGHT/2); break;
+                case SE: g.drawLine(x+WIDTH+10-3, y+HEIGHT+10, x+WIDTH/2-3, y+HEIGHT/2); break;
+                case NONE:  break;
+            }
+            ((Graphics2D)g).setStroke(new BasicStroke(1));
+
+            if (selx==cx && sely==cy) {
+                int xp = 23 * (WIDTH+2) + 100;
+                int yp = 100;
+                g.setColor(Color.white);
+                g.fillRect(xp, yp, 300, 1000);
+                g.setColor(Color.black);
+                g.drawString("Cell " + cx + "," + cy,       xp, (yp+=15));
+                //g.drawString("X-Lut: " + bin8(cell.xlut()), xp, (yp+=15));
+                g.drawString("X-Lut: " + cell.printXLut(), xp, (yp+=15));
+                //g.drawString("Y-Lut: " + bin8(cell.ylut()), xp, (yp+=15));
+                g.drawString("Y-Lut: " + cell.printYLutX(), xp, (yp+=15));
+            }
+        }
+    }
+
+    private static String pad(int i, String s) { if (s.length()>i) return s; return "0"+pad((i-1),s); }
+    private static String bin8(byte b) {
+        int n = b & 0xff;
+        String ret = "";
+        for(int i=7; i>=0; i--)
+            ret += (n & (1<<i))==0 ? "0" : "1";
+        return ret;
+    }
+
 }
index 3d43d75..6a98c5d 100644 (file)
@@ -2,10 +2,12 @@ package edu.berkeley.obits.device.atmel;
 import static edu.berkeley.obits.device.atmel.AtmelDevice.Constants.*;
 import edu.berkeley.obits.*;
 import org.ibex.util.*;
+import java.util.*;
+import java.io.*;
 
 public class At40k {
 
-    private final AtmelDevice dev;
+    /*private*/public final AtmelDevice dev;
     private final int width;
     private final int height;
 
@@ -19,33 +21,166 @@ public class At40k {
         public At40k10(AtmelDevice dev) { super(dev, 24, 24); }
     }
 
-    public Sector sector(int col, int row) { return new Sector(col, row); }
     public final class Sector {
         public final int col;
         public final int row;
-        public Sector(int col, int row) {
+        public Sector(Cell c) { this((c.col/4)*4, (c.row/4)*4); }
+        private Sector(int col, int row) {
             if (row % 4 != 0) throw new Error("Sector must be created with a multiple-of-4 row");
             if (col % 4 != 0) throw new Error("Sector must be created with a multiple-of-4 col");
             this.row = row;
             this.col = col;
         }
+        public Sector north() { return row+4>=height ? null : new Sector(col, row+4); }
+        public Sector south() { return row==0 ?        null : new Sector(col, row-4); }
+        public Sector east()  { return col+4>=width ?  null : new Sector(col+4, row); }
+        public Sector west()  { return col==0 ?        null : new Sector(col-4, row); }
+        public Cell cell() { return At40k.this.cell(col, row); }
+    }
+
+    public final class SectorWire {
+        public final boolean global;
+        public final boolean horizontal;
+        public final int     plane;
+        public final int     row;
+        public final int     col;
+        public SectorWire(boolean horizontal, int plane, int col, int row) {
+            this.horizontal=horizontal;
+            this.global = false;
+            this.plane=plane;
+            this.col= horizontal ? (col & ~0x3) : col;
+            this.row=!horizontal ? (row & ~0x3) : row;
+        }
+        private int z(int z)       { return (horizontal ? 0x30 : 0x20) | z; }
+        public int code(boolean left) {
+            switch(plane) {
+                case 0: return z(6)+(left?0:1);
+                case 1: return z(8)+(left?0:1);
+                case 2: return z(2*(4-plane))+(left?0:1);
+                case 3: return z(2*(4-plane))+(left?0:1);
+                case 4: return z(2*(4-plane))+(left?0:1);
+            }
+            throw new Error();
+        }
+
+        private final int fine()   { return horizontal ? row : col; }
+        public  final int coarse() { return horizontal ? col : row; }
+        private int _row()  { return horizontal ? row          : ((row)>>2); }
+        private int _col()  { return horizontal ? ((col)>>2) : col;          }
+
+        public SectorWire west()  { return !horizontal ? null : col-4<0       ? null : new SectorWire(horizontal, plane, col-4, row); }
+        public SectorWire east()  { return !horizontal ? null : col+4>=width  ? null : new SectorWire(horizontal, plane, col+4, row); }
+        public SectorWire north() { return  horizontal ? null : row+4>=height ? null : new SectorWire(horizontal, plane, col,   row+4); }
+        public SectorWire south() { return  horizontal ? null : row-4<0       ? null : new SectorWire(horizontal, plane, col,   row-4); }
+
+        public String toString() {
+            return
+                (horizontal?(col+":"+(col+3)):(""+col))+","+
+                (horizontal?(row+"")         :(row+":"+(row+3)))+
+                "x"+plane;
+        }
+
+        /** returns the ZYX0 coordinate of the byte controlling the switchbox that bridges this wire to <tt>w</tt> */
+        public int switchbox(SectorWire w) {
+            if (w.horizontal==horizontal) {
+                if (w.plane!=plane) throw new Error();
+                if (Math.abs(w.coarse()-coarse())!=4) throw new Error(w.coarse() + " -- " + coarse());
+                if (w.coarse() < coarse()) return w.switchbox(this);
+                boolean topleft = w.coarse() < coarse();
+                int col = _col() + (( horizontal && !topleft) ? 1 : 0);
+                int row = _row() + ((!horizontal && !topleft) ? 1 : 0);
+                return (code(topleft) << 24) | (row<<16) | (col<<8);
+            }
+            throw new Error("not implemented");
+        }
+
+        public void drives(SectorWire w, boolean enable) {
+            dev.mode4zyx(switchbox(w), enable?0x02:0x00, 0x07);
+        }
+
+        public boolean drives(SectorWire w) {
+            int connect = (dev.mode4zyx(switchbox(w)) >> (global?3:0)) & 0x7;
+            return (connect & 0x2)!=0;
+        }
+        public SectorWire driverRight() {
+            System.out.println("checking " + Integer.toString(code(true), 16) + " " + Integer.toString(_row(), 16) + " " + Integer.toString(_col(), 16));
+            int ret = dev.mode4(z(code(true)), _row(), _col());
+            ret = (ret >> (global?3:0)) & 0x7;
+            switch(ret) {
+                case 0: return null;
+                case 1: return null;  /* global wire on same side */
+                case 2: return new SectorWire(horizontal, plane, horizontal?(col+4):col, horizontal?row:(row+4));
+                case 4: return null;  /* global wire on other side */
+                default: throw new Error("multiple drivers on " + this + "!");
+            }
+        }
+    }
+    /*    
+    public final class SwitchBox {
+        public final boolean h;
+        public final int col;
+        public final int row;
+        public final int plane;
+        public SwitchBox(boolean h, int col, int row, int plane) { this.h = h; this.col = col; this.row = row; this.plane = plane; }
+        public SectorWire west(boolean global)  { return !h ? null : global ? null : new SectorWire(h, col-4, row,   plane); }
+        public SectorWire east(boolean global)  { return !h ? null : global ? null : new SectorWire(h, col+4, row,   plane); }
+        public SectorWire north(boolean global) { return !h ? null : global ? null : new SectorWire(h, col,   row-4, plane); }
+        public SectorWire south(boolean global) { return !h ? null : global ? null : new SectorWire(h, col,   row+4, plane); }
+    }
+    */
+
+    public Cell cell(int col, int row) {
+        if (col<0) return null;
+        if (row<0) return null;
+        if (col>=width) return null;
+        if (row>=height) return null;
+        return new Cell(col, row);
     }
 
-    public Cell cell(int col, int row) { return new Cell(col, row); }
     public final class Cell {
         public final int col;
         public final int row;
-        public Sector getSector() { return sector(col - (col % 4), row - (row % 4)); }
+
+        public SectorWire hwire(int plane)  { return new SectorWire(true, plane, col, row); }
+        public SectorWire vwire(int plane)  { return new SectorWire(false, plane, col, row); }
+
+        public Sector sector() { return new Sector(this); }
         public Cell(int col, int row) {
             this.row = row;
             this.col = col;
         }
 
-        /* bit positions mean:  [MSB] ___ __y _x_ _xy z__ z_y zx_ zxy [LSB] */
-        public void ylut(byte table)   { dev.mode4(6, row, col, ~table); }
+        /* bit positions mean:  [MSB] zxy z_y zx_ z__ _xy __y _x_ ___ [LSB] */
+        public void xlut(int table)    { dev.mode4(7, row, col, (byte)(table & 0xff)); }
+        public byte xlut()             { return (byte)(dev.mode4(7, row, col) & 0xff); }
+        public String printXLut()      { return printLut(xlut(), "y", "x", "t"); }
+        public String printXLutX()     { return printLut(xlut(), str(yi(), "y"), str(xi(), "x"), str(ti(), "t")); }
+
+        public String str(int x, String def) {
+            switch(x) {
+                case NORTH: return "n";
+                case SOUTH: return "s";
+                case EAST:  return "e";
+                case WEST:  return "w";
+                case NW:    return "nw";
+                case SE:    return "se";
+                case NE:    return "ne";
+                case SW:    return "sw";
+                case FB:    return "fb";
+                case L0:    return (hx(0)&&vx(0))?"HV0":hx(0)?"H0":vx(0)?"V0":"L0";
+                case L1:    return (hx(1)&&vx(1))?"HV1":hx(1)?"H1":vx(1)?"V1":"L1";
+                case L2:    return (hx(2)&&vx(2))?"HV2":hx(2)?"H2":vx(2)?"V2":"L2";
+                case L3:    return (hx(3)&&vx(3))?"HV3":hx(3)?"H3":vx(3)?"V3":"L3";
+                case L4:    return (hx(4)&&vx(4))?"HV4":hx(4)?"H4":vx(4)?"V4":"L4";
+                default: return def;
+            }
+        }
 
-        /* bit positions mean:  [MSB] ___ __y _x_ _xy z__ z_y zx_ zxy [LSB] */
-        public void xlut(byte table)   { dev.mode4(7, row, col, ~table); }
+        /* bit positions mean:  [MSB] zxy zx_ z_y z__ _xy _x_ __y ___ [LSB] */
+        public void ylut(int table)    { dev.mode4(6, row, col, (byte)(table & 0xff)); }
+        public byte ylut()             { return (byte)(dev.mode4(6, row, col) & 0xff); }
+        public String printYLut()      { return printLut(ylut(), "y", "x", "t"); }
+        public String printYLutX()     { return printLut(ylut(), str(yi(), "y"), str(xi(), "x"), str(ti(), "t")); }
 
         public void ff_reset_value(boolean value) {
             //dev.mode4( /* FIXME WRONG!!! */, row, col, 3, !value); return;
@@ -53,19 +188,30 @@ public class At40k {
 
         public void out(int plane, boolean enable) {
             switch(plane) {
-                case 0: dev.mode4(0x00, row, col, 2, enable); return;
-                case 1: dev.mode4(0x00, row, col, 3, enable); return;
-                case 2: dev.mode4(0x00, row, col, 5, enable); return;
-                case 3: dev.mode4(0x00, row, col, 4, enable); return;
-                case 4: dev.mode4(0x00, row, col, 1, enable); return;
+                case L0: dev.mode4(0x00, row, col, 3, enable); return;
+                case L1: dev.mode4(0x00, row, col, 2, enable); return;
+                case L2: dev.mode4(0x00, row, col, 5, enable); return;
+                case L3: dev.mode4(0x00, row, col, 4, enable); return;
+                case L4: dev.mode4(0x00, row, col, 1, enable); return;
+                default: throw new RuntimeException("invalid argument");
+            }
+        }
+
+        public boolean out(int plane) {
+            switch(plane) {
+                case L0: return (dev.mode4(0x00, row, col) & (1<<3)) != 0;
+                case L1: return (dev.mode4(0x00, row, col) & (1<<2)) != 0;
+                case L2: return (dev.mode4(0x00, row, col) & (1<<5)) != 0;
+                case L3: return (dev.mode4(0x00, row, col) & (1<<4)) != 0;
+                case L4: return (dev.mode4(0x00, row, col) & (1<<1)) != 0;
                 default: throw new RuntimeException("invalid argument");
             }
         }
 
         public void h(int plane, boolean enable) {
             switch(plane) {
-                case 0: dev.mode4(0x08, row, col, 0, enable); return;
-                case 1: dev.mode4(0x08, row, col, 2, enable); return;
+                case 0: dev.mode4(0x08, row, col, 2, enable); return;
+                case 1: dev.mode4(0x08, row, col, 0, enable); return;
                 case 2: dev.mode4(0x08, row, col, 5, enable); return;
                 case 3: dev.mode4(0x08, row, col, 6, enable); return;
                 case 4: dev.mode4(0x00, row, col, 6, enable); return;
@@ -73,6 +219,17 @@ public class At40k {
             }
         }
         
+        public boolean hx(int plane) {
+            switch(plane) {
+                case 0: return (dev.mode4(0x08, row, col) & (1<<2)) != 0;
+                case 1: return (dev.mode4(0x08, row, col) & (1<<0)) != 0;
+                case 2: return (dev.mode4(0x08, row, col) & (1<<5)) != 0;
+                case 3: return (dev.mode4(0x08, row, col) & (1<<6)) != 0;
+                case 4: return (dev.mode4(0x00, row, col) & (1<<6)) != 0;
+                default: throw new RuntimeException("invalid argument");
+            }
+        }
+        
         public void v(int plane, boolean enable) {
             switch(plane) {
                 case 0: dev.mode4(0x08, row, col, 1, enable); return;
@@ -84,9 +241,28 @@ public class At40k {
             }
         }
         
+        public boolean vx(int plane) {
+            switch(plane) {
+                case 0: return (dev.mode4(0x08, row, col) & (1<<1)) != 0;
+                case 1: return (dev.mode4(0x08, row, col) & (1<<3)) != 0;
+                case 2: return (dev.mode4(0x08, row, col) & (1<<4)) != 0;
+                case 3: return (dev.mode4(0x08, row, col) & (1<<7)) != 0;
+                case 4: return (dev.mode4(0x00, row, col) & (1<<7)) != 0;
+                default: throw new RuntimeException("invalid argument");
+            }
+        }
+        
+        public int ti() {
+            switch(dev.mode4(1, row, col) & 0x30) {
+                case 0x20: return zi();
+                case 0x10: return FB;
+                case 0x00: return wi();
+                default: throw new Error("ack!");
+            }
+        }
         public void t(boolean z, boolean w, boolean fb) {
             // still not totally satisfied...
-            //     how to we distinguish between z&w vs z or w&fb vs fb?
+            //     how to we distinguish between z&w vs z or w&fb vs fb? ==> you can't!  this is a false connection in my diagram
             //     what does it mean for both bits (0x30) to be set to 1?
             if (fb && z) throw new RuntimeException("invalid combination");
             int result = 0;
@@ -103,12 +279,22 @@ public class At40k {
                 default:   throw new RuntimeException("Invalid Argument");
             }
         }
-
+        public int c() {
+            switch (dev.mode4(1, row, col) >> 6) {
+                case 0x00: return XLUT;
+                case 0x01: return YLUT;
+                case 0x02: return ZMUX;
+            }
+            throw new Error();
+        }
         public void b(boolean registered) { dev.mode4(1, row, col, 3, !registered); }
         public void f(boolean registered) { dev.mode4(1, row, col, 2, !registered); }
-
         public void xo(boolean center)    { dev.mode4(1, row, col, 1, center); }
         public void yo(boolean center)    { dev.mode4(1, row, col, 0, center); }
+        public boolean b() { return (dev.mode4(1, row, col) >> 3)!=1; }
+        public boolean f() { return (dev.mode4(1, row, col) >> 2)!=1; }
+        public boolean x() { return (dev.mode4(1, row, col) >> 1)==1; }
+        public boolean y() { return (dev.mode4(1, row, col) >> 0)==1; }
 
         public void oe(int source) {
             switch(source) {
@@ -119,38 +305,70 @@ public class At40k {
             }
         }
 
-        public void xin(int source) {
+        public int xi() {
+            // FIXME: can be multiple
+            if ((dev.mode4(0x03, row, col) & (1<<4))!=0) return L3;
+            switch(dev.mode4(0x05, row, col) & 0xff) {
+                case 0x80: return SW;
+                case (1<<6): return NE;
+                case (1<<5): return SE;
+                case (1<<4): return NW;
+                case (1<<3): return L3;
+                case (1<<2): return L2;
+                case (1<<1): return L1;
+                case (1<<0): return L0;
+                case 0: return NONE;
+                default: throw new Error();
+            }
+        }
+
+        public void xi(int source) {
             switch(source) {
                 case SW: dev.mode4(0x03, row, col, 4, false); dev.mode4(0x05, row, col, 1<<7); break;
                 case NE: dev.mode4(0x03, row, col, 4, false); dev.mode4(0x05, row, col, 1<<6); break;
                 case SE: dev.mode4(0x03, row, col, 4, false); dev.mode4(0x05, row, col, 1<<5); break;
                 case NW: dev.mode4(0x03, row, col, 4, false); dev.mode4(0x05, row, col, 1<<4); break;
                 case L4: dev.mode4(0x03, row, col, 4, true);  dev.mode4(0x05, row, col,    0); break;
-                case L3: dev.mode4(0x03, row, col, 4, false); dev.mode4(0x05, row, col, 1<<3); break;
-                case L2: dev.mode4(0x03, row, col, 4, false); dev.mode4(0x05, row, col, 1<<2); break;
-                case L1: dev.mode4(0x03, row, col, 4, false); dev.mode4(0x05, row, col, 1<<1); break;
-                case L0: dev.mode4(0x03, row, col, 4, false); dev.mode4(0x05, row, col, 1<<0); break;
+                case L3: dev.mode4(0x03, row, col, 4, false); dev.mode4(0x05, row, col, 1<<0); break;
+                case L2: dev.mode4(0x03, row, col, 4, false); dev.mode4(0x05, row, col, 1<<1); break;
+                case L1: dev.mode4(0x03, row, col, 4, false); dev.mode4(0x05, row, col, 1<<2); break;
+                case L0: dev.mode4(0x03, row, col, 4, false); dev.mode4(0x05, row, col, 1<<3); break;
                 default: throw new RuntimeException("invalid argument");
             }
         }
 
-        // FIXME: cancel out the others
-        public void yin(int source) {
+        public int yi() {
+            if ((dev.mode4(0x02, row, col) & (1<<6))!=0) return L4;
+            switch(dev.mode4(0x04, row, col) & 0xff) {
+                case 0x80: return NORTH;
+                case (1<<5): return SOUTH;
+                case (1<<6): return WEST;
+                case (1<<4): return EAST;
+                case (1<<3): return L3;
+                case (1<<2): return L2;
+                case (1<<1): return L1;
+                case (1<<0): return L0;
+                case 0: return NONE;
+                default: throw new Error();
+            }
+        }
+
+        public void yi(int source) {
             switch(source) {
                 case NORTH: dev.mode4(0x02, row, col, 6, false); dev.mode4(0x04, row, col, 1<<7); break;
-                case SOUTH: dev.mode4(0x02, row, col, 6, false); dev.mode4(0x04, row, col, 1<<6); break;
-                case WEST:  dev.mode4(0x02, row, col, 6, false); dev.mode4(0x04, row, col, 1<<5); break;
+                case SOUTH: dev.mode4(0x02, row, col, 6, false); dev.mode4(0x04, row, col, 1<<5); break;
+                case WEST:  dev.mode4(0x02, row, col, 6, false); dev.mode4(0x04, row, col, 1<<6); break;
                 case EAST:  dev.mode4(0x02, row, col, 6, false); dev.mode4(0x04, row, col, 1<<4); break;
                 case L4:    dev.mode4(0x02, row, col, 6, true);  dev.mode4(0x04, row, col,    0); break;
-                case L3:    dev.mode4(0x02, row, col, 6, false); dev.mode4(0x04, row, col, 1<<3); break;
-                case L2:    dev.mode4(0x02, row, col, 6, false); dev.mode4(0x04, row, col, 1<<2); break;
-                case L1:    dev.mode4(0x02, row, col, 6, false); dev.mode4(0x04, row, col, 1<<1); break;
-                case L0:    dev.mode4(0x02, row, col, 6, false); dev.mode4(0x04, row, col, 1<<0); break;
+                case L3:    dev.mode4(0x02, row, col, 6, false); dev.mode4(0x04, row, col, 1<<0); break;
+                case L2:    dev.mode4(0x02, row, col, 6, false); dev.mode4(0x04, row, col, 1<<1); break;
+                case L1:    dev.mode4(0x02, row, col, 6, false); dev.mode4(0x04, row, col, 1<<2); break;
+                case L0:    dev.mode4(0x02, row, col, 6, false); dev.mode4(0x04, row, col, 1<<3); break;
                 default: throw new RuntimeException("invalid argument");
             }
         }
 
-        public void win(int source) {
+        public void wi(int source) {
             switch(source) {
                 case L4:    dev.mode4(0x03, row, col, 1<<5, 0xEC); break;
                 case L3:    dev.mode4(0x03, row, col, 1<<6, 0xEC); break;
@@ -161,7 +379,19 @@ public class At40k {
             }
         }
 
-        public void zin(int source) {
+        public int wi() {
+            switch(dev.mode4(0x03, row, col) & 0xff) {
+                case (1<<5): return L4;
+                case (1<<6): return L3;
+                case (1<<7): return L2;
+                case (1<<3): return L1;
+                case (1<<2): return L0;
+                case (0):    return NONE;
+                default: throw new RuntimeException("invalid argument");
+            }
+        }
+
+        public void zi(int source) {
             switch(source) {
                 case L4:    dev.mode4(0x02, row, col, 1<<7, 0xDB); break;
                 case L3:    dev.mode4(0x02, row, col, 1<<5, 0xDB); break;
@@ -172,12 +402,24 @@ public class At40k {
             }
         }
 
+        public int zi() {
+            switch(dev.mode4(0x02, row, col) & 0xff) {
+                case (1<<7): return L4;
+                case (1<<5): return L3;
+                case (1<<4): return L2;
+                case (1<<3): return L1;
+                case (1<<2): return L0;
+                case 0:      return NONE;
+                default: throw new RuntimeException("invalid argument");
+            }
+        }
+
     }
 
-    public IOB iob_top(int col, boolean primary)   { return new IOB(col, 0, primary); }
-    public IOB iob_bot(int col, boolean primary)   { return new IOB(col, 1, primary); }
-    public IOB iob_left(int row, boolean primary)  { return new IOB(1, row, primary); }
-    public IOB iob_right(int row, boolean primary) { return new IOB(2, row, primary); }
+    public IOB iob_top(int col, boolean primary)   { return new IOB(col, 0, primary, true); }
+    public IOB iob_bot(int col, boolean primary)   { return new IOB(col, 1, primary, true); }
+    public IOB iob_left(int row, boolean primary)  { return new IOB(0, row, primary, false); }
+    public IOB iob_right(int row, boolean primary) { return new IOB(1, row, primary, false); }
     /*
     public IOB fromPin(int pin) {
         if (pin >=  4 && pin <= 11) return io(pin-3);
@@ -230,28 +472,140 @@ public class At40k {
         public final int col;
         public final int row;
         public final boolean primary;
-        public IOB(int col, int row, boolean primary) { this.col = col; this.row = row; this.primary = primary; }
+        public final boolean northsouth;
+        public IOB(int col, int row, boolean primary, boolean northsouth) {
+            this.col = col;
+            this.row = row;
+            this.northsouth = northsouth;
+            this.primary = primary;
+        }
+        /*
+        public String dump() {
+            System.out.println("[ "+
+                               (schmitt()?"schmitt ":"")+
+                               (slew()==3?"fast ":slew()==2?"med ":slew()==1?"slow ":"slew-unknown ")+
+                               (cr()?"cr ":"")+
+                               (reg()?"reg ":"")+
+                               
+        }
+        */
+        public void enableOutput(int direction) {
+            useoem(true);
+            output(direction);
+            pullnone();
+            useoem(true);
+            oem(ALWAYS_ON);
+            oe(true);
+            // note: east-side IOBs should have slew=med, others slew=fast
+            slew((!northsouth && col==1) ? MEDIUM : FAST);
+        }
+        public void enableInput() {
+            schmitt(true);
+            pullnone();
+        }
+
+        public void    useoem(boolean use)  { dev.mode4(z(3), row, col, 6, use); }
+        public boolean useoem()             { return (dev.mode4(z(3), row, col) & (1<<6))!=0; }
+        public void    schmitt(boolean use) { dev.mode4(z(0), row, col, 7, use); }
+        public boolean schmitt()            { return (dev.mode4(z(0), row, col) & (1<<7))!=0; }
+
+        public void    slew(int slew) {
+            switch(slew) {
+                case FAST:   dev.mode4(z(0), row, col, 3<<5, 0x60); return;
+                case MEDIUM: dev.mode4(z(0), row, col, 2<<5, 0x60); return;
+                case SLOW:   dev.mode4(z(0), row, col, 1<<5, 0x60); return;
+                default: throw new Error();
+            }
+        }
 
-        private int z(int code) { return 0x60 | (primary ? 0x08 : 0x10) | code; }
-        public void pullup()   { dev.mode4(z(0), row, col, (dev.mode4(z(0), row, col) & (~0x6)) | 0x00); }
-        public void pulldown() { dev.mode4(z(0), row, col, (dev.mode4(z(0), row, col) & (~0x6)) | 0x03); }
-        public void pullnone() { dev.mode4(z(0), row, col, (dev.mode4(z(0), row, col) & (~0x6)) | 0x01); }
+        public void    oem(int source) {
+            switch(source) {
+                case ALWAYS_ON:  dev.mode4(z(3), row, col, 1<<5, 0x3f); return;
+                case ALWAYS_OFF: dev.mode4(z(3), row, col,    0, 0x3f); return;
+                default: throw new Error();
+            }
+        }
+
+        private int z(int code) { return (northsouth ? 0x70 : 0x60) | (primary ? 0x00 : 0x04) | (code & 0x7); }
+        public void pullup()   { dev.mode4(z(0), row, col, 0x00<<1, 0x06); }
+        public void pulldown() { dev.mode4(z(0), row, col, 0x03<<1, 0x06); }
+        public void pullnone() { dev.mode4(z(0), row, col, 0x01<<1, 0x06); }
         public void oe(boolean oe) {
             int old =  dev.mode4(z(1), row, col) & (~(1<<5));
             old     |= oe ? 0 : (1<<5);
             dev.mode4(z(1), row, col, old & 0xff);
         }
+
         public void output(int which) {
-            if (which < 0 || which > 6) throw new RuntimeException("oem(x) only valid for 0<=x<=5");
-            int d = dev.mode4(z(1), row, col) & 0x80;
-            if (which>0) { d |= 1 << (which==6 ? 6 : which==0 ? 5 : (which-1)); }
-            Log.warn("z", Integer.toString(z(1),16));
-            Log.warn("y", Integer.toString(row,16));
-            Log.warn("x", Integer.toString(col,16));
-            Log.warn("d", Integer.toString(d,16));
-            dev.mode4(z(1), row, col, d);
+            switch(which) {
+                case NONE:
+                    dev.mode4(z(1), row, col, 0, 0x1f); return;
+                case WEST: case EAST: case NORTH: case SOUTH:
+                    dev.mode4(z(1), row, col, 1<<0, 0x1f); return;
+                case NW: case SW: case NE: case SE:
+                    dev.mode4(z(1), row, col, 1<<1, 0x1f); return;
+                default: throw new Error();
+            }
         }
-        
+
+    }
+
+    public static void main(String[] s) throws Exception {
+        System.out.println(printLut(0x39, "se", "n", "L0"));
     }
+    public static synchronized String printLut(int lut, String xn, String yn, String zn) {
+        try {
+            File f = File.createTempFile("mvsis", ".mvs");
+            f.deleteOnExit();
 
+            FileOutputStream fos = new FileOutputStream(f);
+            PrintWriter pw = new PrintWriter(new OutputStreamWriter(fos));
+            pw.println(".model clb");
+            pw.println(".inputs "+xn+" "+yn+" "+zn);
+            pw.println(".outputs O");
+            pw.println(".table "+xn+" "+yn+" "+zn+/*("X_xor_Y X_xor_Z Y_xor_Z")+*/ " -> O");
+            for(int i=8; i>=0; i--) {
+                int x = ((i & 0x01)!=0 ? 1 : 0);
+                int y = ((i & 0x02)!=0 ? 1 : 0);
+                int z = ((i & 0x04)!=0 ? 1 : 0);
+                pw.print(" "+x+" ");
+                pw.print(" "+y+" ");
+                pw.print(" "+z+" ");
+                //pw.print(" "+(x ^ y)+" ");
+                //pw.print(" "+(y ^ z)+" ");
+                //pw.print(" "+(z ^ y)+" ");
+                pw.print((lut & (1<<i))==0 ? 0 : 1);
+                pw.println();
+            }
+            pw.println(".end");
+            pw.flush();
+            pw.close();
+            Process p = Runtime.getRuntime().exec(new String[] { "mvsis", "-c", "simplify;print_factor", f.getAbsolutePath() });
+            new Gobble("mvsis: ", p.getErrorStream()).start();
+            //new Gobble("mvsis: ", p.getInputStream()).start();
+            BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
+            String ret = br.readLine();
+            //f.delete();
+            return ret.trim();
+        } catch (Exception e) {
+            e.printStackTrace();
+            return "*mvsis_error*";
+        }
+    }
+
+    public static class Gobble extends Thread {
+        private final String header;
+        private final BufferedReader br;
+        public Gobble(String header, BufferedReader br) { this.br = br; this.header = header; }
+        public Gobble(String header, Reader r)          { this(header, new BufferedReader(r)); }
+        public Gobble(String header, InputStream is)    { this(header, new InputStreamReader(is)); }
+        public void run() {
+            try {
+                for(String s = br.readLine(); s!=null; s=br.readLine())
+                    System.err.println(header + s);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
 }
index 484d76f..e37c22a 100644 (file)
@@ -30,20 +30,32 @@ public abstract class AtmelDevice extends Bits implements Device {
         public static final int SW    = 21;
         public static final int NE    = 22;
         public static final int SE    = 23;
+
+        public static final int SLOW   = 24;
+        public static final int MEDIUM = 25;
+        public static final int FAST   = 26;
+
+        public static final int ALWAYS_ON  = 27;
+        public static final int ALWAYS_OFF = 28;
+
+        public static final int FB    = 29;
     }
 
     /** issue a command to the device in Mode4 format; see Gosset's documentation for further details */
     public abstract void mode4(int z, int y, int x, int d) throws DeviceException;
     public abstract byte mode4(int z, int y, int x);
+    public          byte mode4zyx(int zyx) { return mode4(zyx>>24, (zyx>>16)&0xff, (zyx>>8)&0xff); }
+    public          void mode4zyx(int zyx, int d, int invmask) { mode4(zyx>>24, (zyx>>16)&0xff, (zyx>>8)&0xff, d, invmask); }
     public          void mode4(int z, int y, int x, int d, int invmask) {
         int old = mode4(z, y, x);
         old &= ~invmask;
         old |= d;
         mode4(z, y, x, old);
     }
+    public          void mode4zyx(int zyx, int bit, boolean set) { mode4(zyx>>24, (zyx>>16)&0xff, (zyx>>8)&0xff, bit, set); }
     public          void mode4(int z, int y, int x, int bit, boolean set) {
         int old = mode4(z, y, x);
-        old &= 1 << bit;
+        old &= ~(1 << bit);
         old |= set ? (1 << bit) : 0;
         mode4(z, y, x, old);
     }
index b50eaab..06253ad 100644 (file)
@@ -85,6 +85,8 @@ void init() {
   sei();\r
 }\r
 \r
+\r
+\r
 void conf(int z, int y, int x, int d) {\r
   FPGAX = x;\r
   FPGAY = y;\r
@@ -109,6 +111,19 @@ void doreset() {
   while(1) { }\r
 }\r
 \r
+#define TIMERVAL 100\r
+ISR(SIG_OVERFLOW0) { \r
+  PORTD = ~FISUA;\r
+  TCNT0 = TIMERVAL;           // load the nearest-to-one-second value  into the timer0\r
+  TIMSK |= (1<<TOIE0);        //enable the compare match1 interrupt and the timer/counter0 overflow interrupt\r
+  sei();\r
+} \r
+void init_timer()  { \r
+  TCCR0 |= (1<<CS00);         // set the timer0 prescaler to CK\r
+  TCNT0 = TIMERVAL;           // load the nearest-to-one-second value  into the timer0\r
+  TIMSK |= (1<<TOIE0);        //enable the compare match1 interrupt and the timer/counter0 overflow interrupt\r
+} \r
+\r
 ISR(SIG_INTERRUPT1) {   // use interrupt1 since interrupt0 is sent by the watchdog (I think)\r
   doreset();\r
 }\r
@@ -155,6 +170,14 @@ int main() {
         conf(z, y, x, d);\r
         portd(1,0);\r
         break;\r
+      case 2:\r
+        portd(1,1);\r
+        send(FISUA);\r
+        portd(1,0);\r
+        break;\r
+      case 3:\r
+        init_timer();\r
+        break;\r
       default: die();\r
     }\r
   }\r
index f00f794..a4b7b3c 100644 (file)
@@ -35,7 +35,21 @@ public class AvrDrone extends AtmelDevice {
         Log.info(this, "device correctly identified itself; ready for operation");
     }
 
-    public void reset() throws DeviceException {
+    public synchronized void scanFPGA() throws DeviceException {
+        try {
+            out.writeByte(3);
+            out.flush();
+        } catch (IOException e) { throw new DeviceException(e); }
+    }
+    public synchronized byte readBus() throws DeviceException {
+        try {
+            out.writeByte(2);
+            out.flush();
+            return in.readByte();
+        } catch (IOException e) { throw new DeviceException(e); }
+    }
+
+    public synchronized void reset() throws DeviceException {
         try {
             Log.info(this, "resetting device");
             sp.setDTR(true);
@@ -49,19 +63,21 @@ public class AvrDrone extends AtmelDevice {
     }
 
     private byte[][][] cache = new byte[24][][];
-    public byte mode4(int z, int y, int x) throws DeviceException {
+    public synchronized byte mode4(int z, int y, int x) throws DeviceException {
         if (cache[x]==null) return 0;
         if (cache[x][y]==null) return 0;
         return cache[x][y][z];
     }
-    public void mode4(int z, int y, int x, int d) throws DeviceException {
+    public synchronized void mode4(int z, int y, int x, int d) throws DeviceException {
         try {
-            Log.debug(this, "writing configuration frame [zyxd]: " +
-                      pad(2, Integer.toString(z, 16)) + " " +
-                      pad(2, Integer.toString(y, 16)) + " " +
-                      pad(2, Integer.toString(x, 16)) + " " +
-                      pad(2, Integer.toString(d, 16))
+            /*
+            Log.info(this, "writing configuration frame [zyxd]: " +
+                      pad(1, Integer.toString(z&0xff, 16)) + " " +
+                      pad(1, Integer.toString(y&0xff, 16)) + " " +
+                      pad(1, Integer.toString(x&0xff, 16)) + " " +
+                      pad(1, Integer.toString(d&0xff, 16))
                       );
+            */
             out.writeByte(1);
             out.writeByte(z);
             out.writeByte(y);
@@ -73,7 +89,7 @@ public class AvrDrone extends AtmelDevice {
         } catch (IOException e) { throw new DeviceException(e); }
     }
 
-    public void flush() throws DeviceException {
+    public synchronized void flush() throws DeviceException {
         try {
             out.flush();
         } catch (IOException e) { throw new DeviceException(e); }