fixed heinous bug in switchbox routing
[slipway.git] / src / com / atmel / fpslic / FpslicBoot.java
1 package com.atmel.fpslic;
2
3 import com.ftdi.usb.*;
4 import java.io.*;
5
6 /**
7  * Bitstream level access to the bootstrap interface (protocol wrapper around FpslicPins)
8  */
9 public class FpslicBoot {
10
11     private FpslicBootPins pins;
12
13     public FpslicBoot(FpslicBootPins pins) throws IOException {
14         this.pins = pins;
15         reset();
16     }
17
18     public void reset() throws IOException {
19
20         pins.avrrstPin(false);
21         pins.configDataPin(false);
22         pins.resetPin(false);
23         pins.cclkPin(false);
24         
25         pins.conPin(false);
26         pins.flush();
27
28         pins.resetPin(false);
29         try { Thread.sleep(500); } catch (Exception e) { }
30         if (pins.initPin()) throw new RuntimeException("INIT was still high after pulling RESET low");
31
32         pins.resetPin(true);
33         try { Thread.sleep(500); } catch (Exception e) { }
34         if (!pins.initPin()) throw new RuntimeException("INIT was still low after releasing RESET");
35
36         sendConfigBits(0,2);
37         pins.flush();
38     }
39
40     public OutputStream getConfigStream() throws IOException {
41         reset();
42         return new OutputStream() {
43                 int bytes = 0;
44                 int bits = 0;
45                 public void write(int in) throws IOException {
46                     for(int i=7; i>=0; i--) {
47                         bits++;
48                         sendConfigBits((((in & 0xff) & (1<<i))!=0)?1:0, 1);
49                     }
50                 }
51                 public void write(byte[] b, int off, int len) throws IOException {
52                     for(int i=off; i<off+len; i++)
53                         write(b[i]);
54                 }
55                 public void flush() throws IOException {
56                     pins.flush();
57                 }
58                 public void close() throws IOException {
59
60                     pins.flush();
61
62                     // turn off the CON pin we've been pulling low...
63                     pins.releaseConPin();
64
65                     if (!pins.initPin())
66                         throw new RuntimeException("initialization failed at " + bytes);
67                     for(int i=0; i<100; i++) {
68                         pins.flush();
69                         if (!pins.initPin())
70                             throw new RuntimeException("initialization failed at " + bytes);
71                         try { Thread.sleep(20); } catch (Exception e) { }
72                         sendConfigBits(0,1);
73                     }
74
75                     pins.close();
76                 }
77             };
78     }
79
80     public OutputStream getOutputStream() throws IOException { return pins.getUartOutputStream(); }
81     public InputStream  getInputStream() throws IOException { return pins.getUartInputStream(); }
82     public void purge() throws IOException { pins.purge(); }
83
84     public void selfTest() throws Exception {
85         boolean pin;
86         System.out.print("smoke check: ");
87
88         // correct preamble
89         getConfigStream();
90         sendConfigBits(Integer.parseInt("00000000", 2), 8);
91         sendConfigBits(Integer.parseInt("10110111", 2), 8);
92         sendConfigBits(0,1);
93         pins.flush();
94         try { Thread.sleep(100); } catch (Exception e) { }
95         pin = pins.initPin();
96         System.out.print((pin ? green(" [pass]") : red(" [FAIL]")));
97
98         // preamble shifted one bit earlier than it should be
99         getConfigStream();
100         sendConfigBits(Integer.parseInt("0000000",  2), 7);
101         sendConfigBits(Integer.parseInt("10110111", 2), 8);
102         sendConfigBits(0, 2);
103         pins.flush();
104         try { Thread.sleep(100); } catch (Exception e) { }
105         pin = pins.initPin();
106         System.out.print((pin ? red(" [FAIL]") : green(" [pass]")));
107
108         // preamble shifted one bit later than it should be
109         getConfigStream();
110         sendConfigBits(Integer.parseInt("000000000", 2), 9);
111         sendConfigBits(Integer.parseInt("10110111",  2), 8);
112         //sendConfigBits(0, 1);
113         pins.flush();
114         try { Thread.sleep(100); } catch (Exception e) { }
115         pin = pins.initPin();
116         System.out.print((pin ? red(" [FAIL]") : green(" [pass]")));
117
118         // plain 'ol bogus preamble
119         getConfigStream();
120         sendConfigBits(Integer.parseInt("00000000", 2), 8);
121         sendConfigBits(Integer.parseInt("11110111", 2), 8);
122         sendConfigBits(0, 1);
123         pins.flush();
124         try { Thread.sleep(100); } catch (Exception e) { }
125         pin = pins.initPin();
126         System.out.print((pin ? red(" [FAIL]") : green(" [pass]")));
127
128         System.out.println();
129     }
130
131     // Private //////////////////////////////////////////////////////////////////////////////
132
133     private void sendConfigBits(int dat, int numbits) throws IOException {
134         for(int i=(numbits-1); i>=0; i--) {
135             boolean bit = (dat & (1<<i)) != 0;
136             pins.configDataPin(bit);
137             pins.cclkPin(true);
138             pins.cclkPin(false);
139             //dbits &= ~(1<<6);  // let the clock fall with the next data bit, whenever it goes out
140         }
141     }
142
143     private static String red(Object o) { return "\033[31m"+o+"\033[0m"; }
144     private static String green(Object o) { return "\033[32m"+o+"\033[0m"; }
145
146 }