Use RXTX for serial comm. Add logdir preference saving
[fw/altos] / ao-tools / altosui / AltosSerial.java
1 /*
2  * Copyright © 2010 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; version 2 of the License.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
16  */
17
18 /*
19  * Deal with TeleDongle on a serial port
20  */
21
22 package altosui;
23
24 import java.lang.*;
25 import java.io.*;
26 import java.util.concurrent.LinkedBlockingQueue;
27 import java.util.LinkedList;
28 import java.util.Iterator;
29 import gnu.io.*;
30 import altosui.AltosSerialMonitor;
31
32 /*
33  * This class reads from the serial port and places each received
34  * line in a queue. Dealing with that queue is left up to other
35  * threads.
36  */
37 class AltosSerialReader implements Runnable {
38         InputStream     serial_in;
39         LinkedBlockingQueue<String> monitor_queue;
40         LinkedBlockingQueue<String> reply_queue;
41         Thread input_thread;
42         String line;
43
44         public void run () {
45                 int c;
46
47                 try {
48                         while ((c = serial_in.read()) != -1) {
49                                 if (c == '\r')
50                                         continue;
51                                 synchronized(this) {
52                                         if (c == '\n') {
53                                                 if (line != "") {
54                                                         if (line.startsWith("VERSION"))
55                                                                 monitor_queue.put(line);
56                                                         else
57                                                                 reply_queue.put(line);
58                                                         line = "";
59                                                 }
60                                         } else {
61                                                 line = line + (char) c;
62                                         }
63                                 }
64                         }
65                 } catch (IOException e) {
66                 } catch (InterruptedException e) {
67                 }
68         }
69
70         public String get_telem() throws InterruptedException {
71                 return monitor_queue.take();
72         }
73
74         public String get_reply() throws InterruptedException {
75                 return reply_queue.take();
76         }
77
78         public void flush () {
79                 synchronized(this) {
80                         if (!"VERSION".startsWith(line) && !line.startsWith("VERSION"))
81                                 line = "";
82                         reply_queue.clear();
83                 }
84         }
85
86         public boolean opened() {
87                 return serial_in != null;
88         }
89
90         public void close() {
91                 if (serial_in != null) {
92                         try {
93                                 serial_in.close();
94                         } catch (IOException e) {
95                         }
96                         serial_in = null;
97                 }
98                 if (input_thread != null) {
99                         try {
100                                 input_thread.join();
101                         } catch (InterruptedException e) {
102                         }
103                         input_thread = null;
104                 }
105         }
106
107         public void open(File name) throws FileNotFoundException {
108                 close();
109                 serial_in = new FileInputStream(name);
110                 input_thread = new Thread(this);
111                 input_thread.start();
112         }
113         public void open(CommPort c) throws IOException {
114                 close();
115                 serial_in = c.getInputStream();
116                 input_thread = new Thread(this);
117                 input_thread.start();
118         }
119         public AltosSerialReader () {
120                 serial_in = null;
121                 input_thread = null;
122                 line = "";
123                 monitor_queue = new LinkedBlockingQueue<String> ();
124                 reply_queue = new LinkedBlockingQueue<String> ();
125         }
126
127 }
128
129 public class AltosSerial implements Runnable {
130         OutputStream serial_out = null;
131         Thread monitor_thread = null;
132         AltosSerialReader reader = null;
133         LinkedList<AltosSerialMonitor> callbacks;
134
135         public void run() {
136                 try {
137                         for (;;) {
138                                 String s = reader.get_telem();
139                                 synchronized(callbacks) {
140                                         Iterator<AltosSerialMonitor> i = callbacks.iterator();
141                                         while (i.hasNext()) {
142                                                 i.next().data(s);
143                                         }
144                                 }
145                         }
146                 } catch (InterruptedException e) {
147                 }
148         }
149
150         boolean need_monitor() {
151                 return reader.opened() && !callbacks.isEmpty();
152         }
153
154         void maybe_stop_monitor() {
155                 if (!need_monitor() && monitor_thread != null) {
156                         monitor_thread.interrupt();
157                         try {
158                                 monitor_thread.join();
159                         } catch (InterruptedException e) {
160                         } finally {
161                                 monitor_thread = null;
162                         }
163                 }
164         }
165
166         void maybe_start_monitor() {
167                 if (need_monitor() && monitor_thread == null) {
168                         monitor_thread = new Thread(this);
169                         monitor_thread.start();
170                 }
171         }
172
173         public void monitor(AltosSerialMonitor monitor) {
174                 synchronized(callbacks) {
175                         callbacks.add(monitor);
176                         maybe_start_monitor();
177                 }
178         }
179
180
181         public void unmonitor(AltosSerialMonitor monitor) {
182                 synchronized(callbacks) {
183                         callbacks.remove(monitor);
184                         maybe_stop_monitor();
185                 }
186         }
187
188         public void close() {
189                 synchronized(callbacks) {
190                         reader.close();
191                         maybe_stop_monitor();
192                 }
193         }
194
195         public void open(File serial_name) throws FileNotFoundException {
196                 reader.open(serial_name);
197                 serial_out = new FileOutputStream(serial_name);
198         }
199
200         public void open(CommPort comm_port) throws IOException {
201                 reader.open(comm_port);
202                 serial_out = comm_port.getOutputStream();
203         }
204
205         public void connect(String port_name) throws IOException, NoSuchPortException, PortInUseException {
206                 System.out.printf("Opening serial port %s\n", port_name);
207                 CommPort comm_port = new RXTXPort(port_name);
208 //              CommPortIdentifier port_identifier = CommPortIdentifier.getPortIdentifier(port_name);
209 //              CommPort comm_port = port_identifier.open("Altos", 1000);
210                 open(comm_port);
211         }
212
213         void init() {
214                 reader = new AltosSerialReader();
215                 callbacks = new LinkedList<AltosSerialMonitor>();
216         }
217
218         public AltosSerial() {
219                 init();
220         }
221
222         public AltosSerial(File serial_name) throws FileNotFoundException {
223                 init();
224                 open(serial_name);
225         }
226
227         public AltosSerial(CommPort comm_port) throws IOException {
228                 init();
229                 open(comm_port);
230         }
231 }