altosui: Fix Landed tab units
[fw/altos] / altosui / AltosPad.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 package altosui;
19
20 import java.awt.*;
21 import java.awt.event.*;
22 import javax.swing.*;
23 import javax.swing.filechooser.FileNameExtensionFilter;
24 import javax.swing.table.*;
25 import java.io.*;
26 import java.util.*;
27 import java.text.*;
28 import java.util.prefs.*;
29 import java.util.concurrent.LinkedBlockingQueue;
30 import org.altusmetrum.AltosLib.*;
31
32 public class AltosPad extends JComponent implements AltosFlightDisplay {
33         GridBagLayout   layout;
34
35         public class LaunchStatus {
36                 JLabel          label;
37                 JTextField      value;
38                 AltosLights     lights;
39
40                 void show(AltosState state, int crc_errors) {}
41
42                 void reset() {
43                         value.setText("");
44                         lights.set(false);
45                 }
46
47                 public void show() {
48                         label.setVisible(true);
49                         value.setVisible(true);
50                         lights.setVisible(true);
51                 }
52
53                 void show(String s) {
54                         show();
55                         value.setText(s);
56                 }
57
58                 void show(String format, double value) {
59                         show(String.format(format, value));
60                 }
61
62                 void show(String format, int value) {
63                         show(String.format(format, value));
64                 }
65
66                 public void hide() {
67                         label.setVisible(false);
68                         value.setVisible(false);
69                         lights.setVisible(false);
70                 }
71
72                 public void set_font() {
73                         label.setFont(Altos.label_font);
74                         value.setFont(Altos.value_font);
75                 }
76
77                 public LaunchStatus (GridBagLayout layout, int y, String text) {
78                         GridBagConstraints      c = new GridBagConstraints();
79                         c.weighty = 1;
80
81                         lights = new AltosLights();
82                         c.gridx = 0; c.gridy = y;
83                         c.anchor = GridBagConstraints.CENTER;
84                         c.fill = GridBagConstraints.VERTICAL;
85                         c.weightx = 0;
86                         layout.setConstraints(lights, c);
87                         add(lights);
88
89                         label = new JLabel(text);
90                         label.setFont(Altos.label_font);
91                         label.setHorizontalAlignment(SwingConstants.LEFT);
92                         c.gridx = 1; c.gridy = y;
93                         c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
94                         c.anchor = GridBagConstraints.WEST;
95                         c.fill = GridBagConstraints.VERTICAL;
96                         c.weightx = 0;
97                         layout.setConstraints(label, c);
98                         add(label);
99
100                         value = new JTextField(Altos.text_width);
101                         value.setFont(Altos.value_font);
102                         value.setHorizontalAlignment(SwingConstants.RIGHT);
103                         c.gridx = 2; c.gridy = y;
104                         c.anchor = GridBagConstraints.WEST;
105                         c.fill = GridBagConstraints.BOTH;
106                         c.weightx = 1;
107                         layout.setConstraints(value, c);
108                         add(value);
109
110                 }
111         }
112
113         public class LaunchValue {
114                 JLabel          label;
115                 JTextField      value;
116                 void show(AltosState state, int crc_errors) {}
117
118                 void show() {
119                         label.setVisible(true);
120                         value.setVisible(true);
121                 }
122
123                 void hide() {
124                         label.setVisible(false);
125                         value.setVisible(false);
126                 }
127
128                 public void set_font() {
129                         label.setFont(Altos.label_font);
130                         value.setFont(Altos.value_font);
131                 }
132
133                 void show(String s) {
134                         show();
135                         value.setText(s);
136                 }
137
138                 void show(AltosUnits units, double v) {
139                         show(units.show(8, v));
140                 }
141
142                 void show(String format, double v) {
143                         show(String.format(format, v));
144                 }
145
146                 void reset() {
147                         value.setText("");
148                 }
149
150                 public LaunchValue (GridBagLayout layout, int y, String text) {
151                         GridBagConstraints      c = new GridBagConstraints();
152                         c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
153                         c.weighty = 1;
154
155                         label = new JLabel(text);
156                         label.setFont(Altos.label_font);
157                         label.setHorizontalAlignment(SwingConstants.LEFT);
158                         c.gridx = 1; c.gridy = y;
159                         c.anchor = GridBagConstraints.WEST;
160                         c.fill = GridBagConstraints.VERTICAL;
161                         c.weightx = 0;
162                         layout.setConstraints(label, c);
163                         add(label);
164
165                         value = new JTextField(Altos.text_width);
166                         value.setFont(Altos.value_font);
167                         value.setHorizontalAlignment(SwingConstants.RIGHT);
168                         c.gridx = 2; c.gridy = y;
169                         c.anchor = GridBagConstraints.EAST;
170                         c.fill = GridBagConstraints.BOTH;
171                         c.weightx = 1;
172                         layout.setConstraints(value, c);
173                         add(value);
174                 }
175         }
176
177         class Battery extends LaunchStatus {
178                 void show (AltosState state, int crc_errors) {
179                         show("%4.2f V", state.battery);
180                         lights.set(state.battery > 3.7);
181                 }
182                 public Battery (GridBagLayout layout, int y) {
183                         super(layout, y, "Battery Voltage");
184                 }
185         }
186
187         Battery battery;
188
189         class Apogee extends LaunchStatus {
190                 void show (AltosState state, int crc_errors) {
191                         show("%4.2f V", state.drogue_sense);
192                         lights.set(state.drogue_sense > 3.2);
193                 }
194                 public Apogee (GridBagLayout layout, int y) {
195                         super(layout, y, "Apogee Igniter Voltage");
196                 }
197         }
198
199         Apogee apogee;
200
201         class Main extends LaunchStatus {
202                 void show (AltosState state, int crc_errors) {
203                         show("%4.2f V", state.main_sense);
204                         lights.set(state.main_sense > 3.2);
205                 }
206                 public Main (GridBagLayout layout, int y) {
207                         super(layout, y, "Main Igniter Voltage");
208                 }
209         }
210
211         Main main;
212
213         class LoggingReady extends LaunchStatus {
214                 void show (AltosState state, int crc_errors) {
215                         if (state.data.flight != 0) {
216                                 if (state.data.state <= Altos.ao_flight_pad)
217                                         show("Ready to record");
218                                 else if (state.data.state < Altos.ao_flight_landed)
219                                         show("Recording data");
220                                 else
221                                         show("Recorded data");
222                         }
223                         else
224                                 show("Storage full");
225                         lights.set(state.data.flight != 0);
226                 }
227                 public LoggingReady (GridBagLayout layout, int y) {
228                         super(layout, y, "On-board Data Logging");
229                 }
230         }
231
232         LoggingReady logging_ready;
233
234         class GPSLocked extends LaunchStatus {
235                 void show (AltosState state, int crc_errors) {
236                         show("%4d sats", state.gps.nsat);
237                         lights.set(state.gps.locked && state.gps.nsat >= 4);
238                 }
239                 public GPSLocked (GridBagLayout layout, int y) {
240                         super (layout, y, "GPS Locked");
241                 }
242         }
243
244         GPSLocked gps_locked;
245
246         class GPSReady extends LaunchStatus {
247                 void show (AltosState state, int crc_errors) {
248                         if (state.gps_ready)
249                                 show("Ready");
250                         else
251                                 show("Waiting %d", state.gps_waiting);
252                         lights.set(state.gps_ready);
253                 }
254                 public GPSReady (GridBagLayout layout, int y) {
255                         super (layout, y, "GPS Ready");
256                 }
257         }
258
259         GPSReady gps_ready;
260
261         String pos(double p, String pos, String neg) {
262                 String  h = pos;
263                 if (p < 0) {
264                         h = neg;
265                         p = -p;
266                 }
267                 int deg = (int) Math.floor(p);
268                 double min = (p - Math.floor(p)) * 60.0;
269                 return String.format("%s %4d° %9.6f", h, deg, min);
270         }
271
272         class PadLat extends LaunchValue {
273                 void show (AltosState state, int crc_errors) {
274                         show(pos(state.pad_lat,"N", "S"));
275                 }
276                 public PadLat (GridBagLayout layout, int y) {
277                         super (layout, y, "Pad Latitude");
278                 }
279         }
280
281         PadLat pad_lat;
282
283         class PadLon extends LaunchValue {
284                 void show (AltosState state, int crc_errors) {
285                         show(pos(state.pad_lon,"E", "W"));
286                 }
287                 public PadLon (GridBagLayout layout, int y) {
288                         super (layout, y, "Pad Longitude");
289                 }
290         }
291
292         PadLon pad_lon;
293
294         class PadAlt extends LaunchValue {
295                 void show (AltosState state, int crc_errors) {
296                         show("%4.0f m", state.pad_alt);
297                 }
298                 public PadAlt (GridBagLayout layout, int y) {
299                         super (layout, y, "Pad Altitude");
300                 }
301         }
302
303         PadAlt pad_alt;
304
305         public void reset() {
306                 battery.reset();
307                 apogee.reset();
308                 main.reset();
309                 logging_ready.reset();
310                 gps_locked.reset();
311                 gps_ready.reset();
312                 pad_lat.reset();
313                 pad_lon.reset();
314                 pad_alt.reset();
315         }
316
317         public void set_font() {
318                 battery.set_font();
319                 apogee.set_font();
320                 main.set_font();
321                 logging_ready.set_font();
322                 gps_locked.set_font();
323                 gps_ready.set_font();
324                 pad_lat.set_font();
325                 pad_lon.set_font();
326                 pad_alt.set_font();
327         }
328         
329         public void show(AltosState state, int crc_errors) {
330                 battery.show(state, crc_errors);
331                 if (state.drogue_sense == AltosRecord.MISSING)
332                         apogee.hide();
333                 else
334                         apogee.show(state, crc_errors);
335                 if (state.main_sense == AltosRecord.MISSING)
336                         main.hide();
337                 else
338                         main.show(state, crc_errors);
339                 logging_ready.show(state, crc_errors);
340                 pad_alt.show(state, crc_errors);
341                 if (state.gps != null && state.gps.connected) {
342                         gps_locked.show(state, crc_errors);
343                         gps_ready.show(state, crc_errors);
344                         pad_lat.show(state, crc_errors);
345                         pad_lon.show(state, crc_errors);
346                 } else {
347                         gps_locked.hide();
348                         gps_ready.hide();
349                         pad_lat.hide();
350                         pad_lon.hide();
351                 }
352         }
353
354         public AltosPad() {
355                 layout = new GridBagLayout();
356
357                 setLayout(layout);
358
359                 /* Elements in pad display:
360                  *
361                  * Battery voltage
362                  * Igniter continuity
363                  * GPS lock status
364                  * GPS ready status
365                  * GPS location
366                  * Pad altitude
367                  * RSSI
368                  */
369                 battery = new Battery(layout, 0);
370                 apogee = new Apogee(layout, 1);
371                 main = new Main(layout, 2);
372                 logging_ready = new LoggingReady(layout, 3);
373                 gps_locked = new GPSLocked(layout, 4);
374                 gps_ready = new GPSReady(layout, 5);
375                 pad_lat = new PadLat(layout, 6);
376                 pad_lon = new PadLon(layout, 7);
377                 pad_alt = new PadAlt(layout, 8);
378         }
379 }