6787e0c82de78026566159eda85a1c51e513c770
[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
30 import libaltosJNI.*;
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
38 public class AltosSerial implements Runnable {
39
40         SWIGTYPE_p_altos_file altos;
41         LinkedList<LinkedBlockingQueue<AltosLine>> monitors;
42         LinkedBlockingQueue<AltosLine> reply_queue;
43         Thread input_thread;
44         String line;
45         byte[] line_bytes;
46         int line_count;
47         boolean monitor_mode;
48
49         public void run () {
50                 int c;
51
52                 try {
53                         for (;;) {
54                                 c = libaltos.altos_getchar(altos, 0);
55                                 if (Thread.interrupted())
56                                         break;
57                                 if (c == libaltosConstants.LIBALTOS_ERROR) {
58                                         for (int e = 0; e < monitors.size(); e++) {
59                                                 LinkedBlockingQueue<AltosLine> q = monitors.get(e);
60                                                 q.put(new AltosLine());
61                                         }
62                                         reply_queue.put (new AltosLine());
63                                         break;
64                                 }
65                                 if (c == libaltosConstants.LIBALTOS_TIMEOUT)
66                                         continue;
67                                 if (c == '\r')
68                                         continue;
69                                 synchronized(this) {
70                                         if (c == '\n') {
71                                                 if (line_count != 0) {
72                                                         try {
73                                                                 line = new String(line_bytes, 0, line_count, "UTF-8");
74                                                         } catch (UnsupportedEncodingException ue) {
75                                                                 line = "";
76                                                                 for (int i = 0; i < line_count; i++)
77                                                                         line = line + line_bytes[i];
78                                                         }
79                                                         if (line.startsWith("VERSION") || line.startsWith("CRC")) {
80                                                                 for (int e = 0; e < monitors.size(); e++) {
81                                                                         LinkedBlockingQueue<AltosLine> q = monitors.get(e);
82                                                                         q.put(new AltosLine (line));
83                                                                 }
84                                                         } else {
85 //                                                              System.out.printf("GOT: %s\n", line);
86                                                                 reply_queue.put(new AltosLine (line));
87                                                         }
88                                                         line_count = 0;
89                                                         line = "";
90                                                 }
91                                         } else {
92                                                 if (line_bytes == null) {
93                                                         line_bytes = new byte[256];
94                                                 } else if (line_count == line_bytes.length) {
95                                                         byte[] new_line_bytes = new byte[line_count * 2];
96                                                         System.arraycopy(line_bytes, 0, new_line_bytes, 0, line_count);
97                                                         line_bytes = new_line_bytes;
98                                                 }
99                                                 line_bytes[line_count] = (byte) c;
100                                                 line_count++;
101                                         }
102                                 }
103                         }
104                 } catch (InterruptedException e) {
105                 }
106         }
107
108         public void flush_output() {
109                 if (altos != null)
110                         libaltos.altos_flush(altos);
111         }
112
113         public void flush_input() {
114                 flush_output();
115                 try {
116                         Thread.sleep(200);
117                 } catch (InterruptedException ie) {
118                 }
119                 synchronized(this) {
120                         if (!"VERSION".startsWith(line) &&
121                             !line.startsWith("VERSION"))
122                                 line = "";
123                         reply_queue.clear();
124                 }
125         }
126
127         public String get_reply() throws InterruptedException {
128                 flush_output();
129                 AltosLine line = reply_queue.take();
130                 return line.line;
131         }
132
133         public void add_monitor(LinkedBlockingQueue<AltosLine> q) {
134                 set_monitor(true);
135                 monitors.add(q);
136         }
137
138         public void remove_monitor(LinkedBlockingQueue<AltosLine> q) {
139                 monitors.remove(q);
140                 if (monitors.isEmpty())
141                         set_monitor(false);
142         }
143
144         public boolean opened() {
145                 return altos != null;
146         }
147
148         public void close() {
149                 if (altos != null) {
150                         libaltos.altos_close(altos);
151                 }
152                 if (input_thread != null) {
153                         try {
154                                 input_thread.interrupt();
155                                 input_thread.join();
156                         } catch (InterruptedException e) {
157                         }
158                         input_thread = null;
159                 }
160                 if (altos != null) {
161                         libaltos.altos_free(altos);
162                         altos = null;
163                 }
164         }
165
166         public void putc(char c) {
167                 if (altos != null)
168                         libaltos.altos_putchar(altos, c);
169         }
170
171         public void print(String data) {
172 //              System.out.printf("\"%s\" ", data);
173                 for (int i = 0; i < data.length(); i++)
174                         putc(data.charAt(i));
175         }
176
177         public void printf(String format, Object ... arguments) {
178                 print(String.format(format, arguments));
179         }
180
181         public void open(altos_device device) throws FileNotFoundException {
182                 close();
183                 altos = libaltos.altos_open(device);
184                 if (altos == null)
185                         throw new FileNotFoundException(device.getPath());
186                 input_thread = new Thread(this);
187                 input_thread.start();
188                 print("~\nE 0\n");
189                 flush_output();
190                 set_monitor(monitor_mode);
191                 set_channel(AltosPreferences.channel(device.getSerial()));
192                 set_callsign(AltosPreferences.callsign());
193         }
194
195         public void set_channel(int channel) {
196                 if (altos != null) {
197                         if (monitor_mode)
198                                 printf("m 0\nc r %d\nm 1\n", channel);
199                         else
200                                 printf("c r %d\n", channel);
201                         flush_output();
202                 }
203         }
204
205         void set_monitor(boolean monitor) {
206                 monitor_mode = monitor;
207                 if (altos != null) {
208                         if (monitor)
209                                 printf("m 1\n");
210                         else
211                                 printf("m 0\n");
212                         flush_output();
213                 }
214         }
215
216         public void set_callsign(String callsign) {
217                 if (altos != null) {
218                         printf ("c c %s\n", callsign);
219                         flush_output();
220                 }
221         }
222
223         public AltosSerial() {
224                 altos = null;
225                 input_thread = null;
226                 line = "";
227                 monitor_mode = false;
228                 monitors = new LinkedList<LinkedBlockingQueue<AltosLine>> ();
229                 reply_queue = new LinkedBlockingQueue<AltosLine> ();
230         }
231 }