checkpoint
[slipway.git] / src / com / ftdi / usb / FtdiUart.java
1 package com.ftdi.usb;
2 import java.io.*;
3
4 /**
5  *  A Java wrapper around libftdi.
6  *
7  *  Note: blocking reads are currently implemented by busy-waiting.
8  *  This is really ugly.  Check the linux kernel source to see how to
9  *  get libftdi to do it properly.
10  *
11  *  Flow control is also not properly supported.
12  */
13 public class FtdiUart {
14
15     private SWIGTYPE_p_ftdi_context context = example.new_ftdi_context();
16
17     public OutputStream getOutputStream() { return out; }
18     public InputStream  getInputStream() { return in; }
19
20     public FtdiUart(int vendor, int product, int baud) {
21         example.ftdi_init(context);
22         example.ftdi_usb_open(context, vendor, product);
23         example.ftdi_usb_reset(context);
24         example.ftdi_set_baudrate(context, baud);
25         example.ftdi_set_line_property(context, 8, 0, 0);
26         purge();
27     }
28
29     /**
30      *  Switch to uart mode, with read/write access to four CBUS lines.
31      *  This function is used to write to the CBUS lines (re-invoke it to change their state).
32      *  I think readPins() is used to read from them, but I'm not sure.
33      *
34      *  @param cbus_mask a four-bit mask; set bit=1 to write to a CBUS line, bit=0 to read from it
35      *  @param cbus_bits a four-bit mask; the bits to assert on the write-enabled CBUS lines
36      */
37     public synchronized void uart_and_cbus_mode(int cbus_mask, int cbus_bits) {
38         example.ftdi_set_bitmode(context, (short)((cbus_mask << 4) | cbus_bits), (short)0x20);
39     }
40
41     /**
42      *  Switch to dbus mode; CBUS lines will be released (ie they will float).
43      *  Use getInputStream()/getOutputStream() to read/write the eight DBUS lines.
44      * 
45      *  @param dbus_mask an eight-bit mask; set bit=1 to write to a DBUS line, bit=0 to read from it
46      */
47     public synchronized void dbus_mode(int dbus_mask) {
48         example.ftdi_set_bitmode(context, (short)dbus_mask, (short)0x01);
49     }
50
51     /** returns the instantaneous value present on the DBUS pins */
52     public synchronized int readPins() {
53         try {
54             getOutputStream().flush();
55         } catch (IOException e) {
56             throw new RuntimeException(e);
57         }
58         byte[] b = new byte[1];
59         example.ftdi_read_pins(context, b);
60         return b[0];
61     }
62
63     /** purge the on-chip buffers */
64     public synchronized void purge() {
65         example.ftdi_usb_purge_buffers(context);
66     }
67
68     private final InputStream in = new InputStream() {
69             public int available() throws IOException {
70                 // FIXME
71                 return 0;
72             }
73             public int read() throws IOException {
74                 byte[] b = new byte[1];
75                 int result = 0;
76                 while(result==0) result = read(b, 0, 1);
77                 return b[0] & 0xff;
78             }
79             public int read(byte[] b, int off, int len) throws IOException {
80                 // FIXME: blocking reads?
81                 int result = 0;
82                 while(true) {
83                     if (len==0) return 0;
84                     byte[] b0 = new byte[len];
85                     synchronized(FtdiUart.this) {
86                         result = example.ftdi_read_data(context, b0, len);
87                     }
88                     if (result>0) {
89                         System.arraycopy(b0, 0, b, off, result);
90                         return result;
91                     }
92                     try { Thread.sleep(50); } catch (Exception e) { e.printStackTrace(); } 
93                 }
94             }
95         };
96
97     private final OutputStream out = new BufferedOutputStream(new OutputStream() {
98             public void write(int b) throws IOException {
99                 byte[] d = new byte[1];
100                 d[0] = (byte)b;
101                 write(d, 0, 1);
102             }
103             public void write(byte[] b, int off, int len) throws IOException {
104                 byte[] b2 = new byte[64];
105                 while(len > 0) {
106                     System.arraycopy(b, off, b2, 0, Math.min(b2.length, len));
107                     int result;
108                     synchronized(FtdiUart.this) {
109                         result = example.ftdi_write_data(context, b2, Math.min(b2.length, len));
110                     }
111                     off += result;
112                     len -= result;
113                 }
114             }
115         });
116 }