Add telem parsing code
[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 altosui.AltosSerialMonitor;
30
31 /*
32  * This class reads from the serial port and places each received
33  * line in a queue. Dealing with that queue is left up to other
34  * threads.
35  */
36 class AltosSerialReader implements Runnable {
37         FileInputStream serial_in;
38         LinkedBlockingQueue<String> monitor_queue;
39         LinkedBlockingQueue<String> reply_queue;
40         Thread input_thread;
41         String line;
42
43         public void run () {
44                 int c;
45
46                 try {
47                         while ((c = serial_in.read()) != -1) {
48                                 if (c == '\r')
49                                         continue;
50                                 synchronized(this) {
51                                         if (c == '\n') {
52                                                 if (line != "") {
53                                                         if (line.startsWith("VERSION"))
54                                                                 monitor_queue.put(line);
55                                                         else
56                                                                 reply_queue.put(line);
57                                                         line = "";
58                                                 }
59                                         } else {
60                                                 line = line + (char) c;
61                                         }
62                                 }
63                         }
64                 } catch (IOException e) {
65                 } catch (InterruptedException e) {
66                 }
67         }
68
69         public String get_telem() throws InterruptedException {
70                 return monitor_queue.take();
71         }
72
73         public String get_reply() throws InterruptedException {
74                 return reply_queue.take();
75         }
76
77         public void flush () {
78                 synchronized(this) {
79                         if (!"VERSION".startsWith(line) && !line.startsWith("VERSION"))
80                                 line = "";
81                         reply_queue.clear();
82                 }
83         }
84
85         public boolean opened() {
86                 return serial_in != null;
87         }
88
89         public void close() {
90                 if (serial_in != null) {
91                         try {
92                                 serial_in.close();
93                         } catch (IOException e) {
94                         }
95                         serial_in = null;
96                 }
97                 if (input_thread != null) {
98                         try {
99                                 input_thread.join();
100                         } catch (InterruptedException e) {
101                         }
102                         input_thread = null;
103                 }
104         }
105
106         public void open(File name) throws FileNotFoundException {
107                 close();
108                 serial_in = new FileInputStream(name);
109                 input_thread = new Thread(this);
110                 input_thread.start();
111         }
112         public AltosSerialReader () {
113                 serial_in = null;
114                 input_thread = null;
115                 line = "";
116                 monitor_queue = new LinkedBlockingQueue<String> ();
117                 reply_queue = new LinkedBlockingQueue<String> ();
118         }
119
120 }
121
122 public class AltosSerial implements Runnable {
123         FileOutputStream serial_out = null;
124         Thread monitor_thread = null;
125         AltosSerialReader reader = null;
126         LinkedList<AltosSerialMonitor> callbacks;
127
128         public void run() {
129                 try {
130                         for (;;) {
131                                 String s = reader.get_telem();
132                                 synchronized(callbacks) {
133                                         Iterator<AltosSerialMonitor> i = callbacks.iterator();
134                                         while (i.hasNext()) {
135                                                 i.next().data(s);
136                                         }
137                                 }
138                         }
139                 } catch (InterruptedException e) {
140                 }
141         }
142
143         boolean need_monitor() {
144                 return reader.opened() && !callbacks.isEmpty();
145         }
146
147         void maybe_stop_monitor() {
148                 if (!need_monitor() && monitor_thread != null) {
149                         monitor_thread.interrupt();
150                         try {
151                                 monitor_thread.join();
152                         } catch (InterruptedException e) {
153                         } finally {
154                                 monitor_thread = null;
155                         }
156                 }
157         }
158
159         void maybe_start_monitor() {
160                 if (need_monitor() && monitor_thread == null) {
161                         monitor_thread = new Thread(this);
162                         monitor_thread.start();
163                 }
164         }
165
166         public void monitor(AltosSerialMonitor monitor) {
167                 synchronized(callbacks) {
168                         callbacks.add(monitor);
169                         maybe_start_monitor();
170                 }
171         }
172
173
174         public void unmonitor(AltosSerialMonitor monitor) {
175                 synchronized(callbacks) {
176                         callbacks.remove(monitor);
177                         maybe_stop_monitor();
178                 }
179         }
180
181         public void close() {
182                 synchronized(callbacks) {
183                         reader.close();
184                         maybe_stop_monitor();
185                 }
186         }
187
188         public void open(File serial_name) throws FileNotFoundException {
189                 reader.open(serial_name);
190                 serial_out = new FileOutputStream(serial_name);
191                 try {
192                         serial_out.write('?');
193                         serial_out.write('\r');
194                 } catch (IOException e) {
195                 }
196         }
197
198         void init() {
199                 reader = new AltosSerialReader();
200                 callbacks = new LinkedList<AltosSerialMonitor>();
201         }
202
203         public AltosSerial() {
204                 init();
205         }
206
207         public AltosSerial(File serial_name) throws FileNotFoundException {
208                 init();
209                 open(serial_name);
210         }
211 }