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