altos: Shuffle LCO functions around, add telelco first cut
[fw/altos] / altoslib / AltosIdleRecordTM.java
1 /*
2  * Copyright © 2012 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 package org.altusmetrum.AltosLib;
19
20 import java.io.*;
21 import java.util.*;
22 import java.text.*;
23 import java.util.prefs.*;
24 import java.util.concurrent.*;
25
26 class AltosADCTM {
27         int     tick;
28         int     accel;
29         int     pres;
30         int     temp;
31         int     batt;
32         int     drogue;
33         int     main;
34
35         public AltosADCTM(AltosLink link) throws InterruptedException, TimeoutException {
36                 link.printf("a\n");
37                 for (;;) {
38                         String line = link.get_reply_no_dialog(5000);
39                         if (line == null) {
40                                 throw new TimeoutException();
41                         }
42                         if (!line.startsWith("tick:"))
43                                 continue;
44                         String[] items = line.split("\\s+");
45                         for (int i = 0; i < items.length;) {
46                                 if (items[i].equals("tick:")) {
47                                         tick = Integer.parseInt(items[i+1]);
48                                         i += 2;
49                                         continue;
50                                 }
51                                 if (items[i].equals("accel:")) {
52                                         accel = Integer.parseInt(items[i+1]);
53                                         i += 2;
54                                         continue;
55                                 }
56                                 if (items[i].equals("pres:")) {
57                                         pres = Integer.parseInt(items[i+1]);
58                                         i += 2;
59                                         continue;
60                                 }
61                                 if (items[i].equals("temp:")) {
62                                         temp = Integer.parseInt(items[i+1]);
63                                         i += 2;
64                                         continue;
65                                 }
66                                 if (items[i].equals("batt:")) {
67                                         batt = Integer.parseInt(items[i+1]);
68                                         i += 2;
69                                         continue;
70                                 }
71                                 if (items[i].equals("drogue:")) {
72                                         drogue = Integer.parseInt(items[i+1]);
73                                         i += 2;
74                                         continue;
75                                 }
76                                 if (items[i].equals("main:")) {
77                                         main = Integer.parseInt(items[i+1]);
78                                         i += 2;
79                                         continue;
80                                 }
81                                 i++;
82                         }
83                         break;
84                 }
85         }
86 }
87
88 class AltosGPSQuery extends AltosGPS {
89         public AltosGPSQuery (AltosLink link, AltosConfigData config_data)
90                 throws TimeoutException, InterruptedException {
91                 boolean says_done = config_data.compare_version("1.0") >= 0;
92                 link.printf("g\n");
93                 for (;;) {
94                         String line = link.get_reply_no_dialog(5000);
95                         if (line == null)
96                                 throw new TimeoutException();
97                         String[] bits = line.split("\\s+");
98                         if (bits.length == 0)
99                                 continue;
100                         if (line.startsWith("Date:")) {
101                                 if (bits.length < 2)
102                                         continue;
103                                 String[] d = bits[1].split(":");
104                                 if (d.length < 3)
105                                         continue;
106                                 year = Integer.parseInt(d[0]) + 2000;
107                                 month = Integer.parseInt(d[1]);
108                                 day = Integer.parseInt(d[2]);
109                                 continue;
110                         }
111                         if (line.startsWith("Time:")) {
112                                 if (bits.length < 2)
113                                         continue;
114                                 String[] d = bits[1].split("/");
115                                 if (d.length < 3)
116                                         continue;
117                                 hour = Integer.parseInt(d[0]);
118                                 minute = Integer.parseInt(d[1]);
119                                 second = Integer.parseInt(d[2]);
120                                 continue;
121                         }
122                         if (line.startsWith("Lat/Lon:")) {
123                                 if (bits.length < 3)
124                                         continue;
125                                 lat = Integer.parseInt(bits[1]) * 1.0e-7;
126                                 lon = Integer.parseInt(bits[2]) * 1.0e-7;
127                                 continue;
128                         }
129                         if (line.startsWith("Alt:")) {
130                                 if (bits.length < 2)
131                                         continue;
132                                 alt = Integer.parseInt(bits[1]);
133                                 continue;
134                         }
135                         if (line.startsWith("Flags:")) {
136                                 if (bits.length < 2)
137                                         continue;
138                                 int status = Integer.decode(bits[1]);
139                                 connected = (status & AltosLib.AO_GPS_RUNNING) != 0;
140                                 locked = (status & AltosLib.AO_GPS_VALID) != 0;
141                                 if (!says_done)
142                                         break;
143                                 continue;
144                         }
145                         if (line.startsWith("Sats:")) {
146                                 if (bits.length < 2)
147                                         continue;
148                                 nsat = Integer.parseInt(bits[1]);
149                                 cc_gps_sat = new AltosGPSSat[nsat];
150                                 for (int i = 0; i < nsat; i++) {
151                                         int     svid = Integer.parseInt(bits[2+i*2]);
152                                         int     cc_n0 = Integer.parseInt(bits[3+i*2]);
153                                         cc_gps_sat[i] = new AltosGPSSat(svid, cc_n0);
154                                 }
155                         }
156                         if (line.startsWith("done"))
157                                 break;
158                         if (line.startsWith("Syntax error"))
159                                 break;
160                 }
161         }
162 }
163
164 public class AltosIdleMonitor extends Thread {
165         AltosLink               link;
166         AltosIdleMonitorListener        listener;
167         AltosState              state;
168         boolean                 remote;
169         double                  frequency;
170         AltosState              previous_state;
171         AltosConfigData         config_data;
172         AltosADC                adc;
173         AltosGPS                gps;
174
175         int AltosRSSI() throws TimeoutException, InterruptedException {
176                 link.printf("s\n");
177                 String line = link.get_reply_no_dialog(5000);
178                 if (line == null)
179                         throw new TimeoutException();
180                 String[] items = line.split("\\s+");
181                 if (items.length < 2)
182                         return 0;
183                 if (!items[0].equals("RSSI:"))
184                         return 0;
185                 int rssi = Integer.parseInt(items[1]);
186                 return rssi;
187         }
188
189         void update_state() throws InterruptedException, TimeoutException {
190                 AltosRecordTM   record = new AltosRecordTM();
191                 int             rssi;
192
193                 try {
194                         if (remote) {
195                                 link.set_radio_frequency(frequency);
196                                 link.start_remote();
197                         } else
198                                 link.flush_input();
199                         config_data = new AltosConfigData(link);
200                         adc = new AltosADC(link);
201                         gps = new AltosGPSQuery(link, config_data);
202                 } finally {
203                         if (remote) {
204                                 link.stop_remote();
205                                 rssi = AltosRSSI();
206                         } else
207                                 rssi = 0;
208                 }
209
210                 record.version = 0;
211                 record.callsign = config_data.callsign;
212                 record.serial = config_data.serial;
213                 record.flight = config_data.log_available() > 0 ? 255 : 0;
214                 record.rssi = rssi;
215                 record.status = 0;
216                 record.state = AltosLib.ao_flight_idle;
217
218                 record.tick = adc.tick;
219
220                 record.accel = adc.accel;
221                 record.pres = adc.pres;
222                 record.batt = adc.batt;
223                 record.temp = adc.temp;
224                 record.drogue = adc.drogue;
225                 record.main = adc.main;
226
227                 record.ground_accel = record.accel;
228                 record.ground_pres = record.pres;
229                 record.accel_plus_g = config_data.accel_cal_plus;
230                 record.accel_minus_g = config_data.accel_cal_minus;
231                 record.acceleration = 0;
232                 record.speed = 0;
233                 record.height = 0;
234                 record.gps = gps;
235                 state = new AltosState (record, state);
236         }
237
238         public void set_frequency(double in_frequency) {
239                 frequency = in_frequency;
240         }
241
242         public void post_state() {
243                 listener.update(state);
244         }
245
246         public void run() {
247                 try {
248                         for (;;) {
249                                 try {
250                                         update_state();
251                                         post_state();
252                                 } catch (TimeoutException te) {
253                                 }
254                                 Thread.sleep(1000);
255                         }
256                 } catch (InterruptedException ie) {
257                         link.close();
258                 }
259         }
260
261         public AltosIdleMonitor(AltosIdleMonitorListener in_listener, AltosLink in_link, boolean in_remote)
262                 throws FileNotFoundException, InterruptedException, TimeoutException {
263                 listener = in_listener;
264                 link = in_link;
265                 remote = in_remote;
266                 state = null;
267         }
268 }