static boolean map_initialized = false;
+ static final int tab_elt_pad = 5;
+
+ static final Font label_font = new Font("Dialog", Font.PLAIN, 22);
+ static final Font value_font = new Font("Monospaced", Font.PLAIN, 22);
+ static final Font status_font = new Font("SansSerif", Font.BOLD, 24);
+
static void initialize_map()
{
string_to_state.put("startup", ao_flight_startup);
public class AltosAscent extends JComponent implements AltosFlightDisplay {
GridBagLayout layout;
- Font label_font;
- Font value_font;
+
+ public class AscentStatus {
+ JLabel label;
+ JTextField value;
+ AltosLights lights;
+
+ void show(AltosState state, int crc_errors) {}
+ void reset() {
+ value.setText("");
+ lights.set(false);
+ }
+
+ public AscentStatus (GridBagLayout layout, int y, String text) {
+ GridBagConstraints c = new GridBagConstraints();
+ c.weighty = 1;
+
+ lights = new AltosLights();
+ c.gridx = 0; c.gridy = y;
+ c.anchor = GridBagConstraints.CENTER;
+ c.fill = GridBagConstraints.VERTICAL;
+ c.weightx = 0;
+ layout.setConstraints(lights, c);
+ add(lights);
+
+ label = new JLabel(text);
+ label.setFont(Altos.label_font);
+ label.setHorizontalAlignment(SwingConstants.LEFT);
+ c.gridx = 1; c.gridy = y;
+ c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
+ c.anchor = GridBagConstraints.WEST;
+ c.fill = GridBagConstraints.VERTICAL;
+ c.weightx = 0;
+ layout.setConstraints(label, c);
+ add(label);
+
+ value = new JTextField(15);
+ value.setFont(Altos.value_font);
+ value.setHorizontalAlignment(SwingConstants.RIGHT);
+ c.gridx = 2; c.gridy = y;
+ c.anchor = GridBagConstraints.WEST;
+ c.fill = GridBagConstraints.BOTH;
+ c.weightx = 1;
+ layout.setConstraints(value, c);
+ add(value);
+
+ }
+ }
public class AscentValue {
JLabel label;
}
public AscentValue (GridBagLayout layout, int y, String text) {
GridBagConstraints c = new GridBagConstraints();
+ c.weighty = 1;
label = new JLabel(text);
- label.setFont(label_font);
+ label.setFont(Altos.label_font);
label.setHorizontalAlignment(SwingConstants.LEFT);
c.gridx = 0; c.gridy = y;
- c.insets = new Insets(10, 10, 10, 10);
+ c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
c.anchor = GridBagConstraints.WEST;
+ c.fill = GridBagConstraints.VERTICAL;
+ c.weightx = 0;
layout.setConstraints(label, c);
add(label);
value = new JTextField(30);
- value.setFont(value_font);
+ value.setFont(Altos.value_font);
value.setHorizontalAlignment(SwingConstants.RIGHT);
c.gridx = 1; c.gridy = y;
c.anchor = GridBagConstraints.WEST;
- c.fill = GridBagConstraints.HORIZONTAL;
+ c.fill = GridBagConstraints.BOTH;
c.gridwidth = 2;
+ c.weightx = 1;
layout.setConstraints(value, c);
add(value);
}
}
public AscentValueHold (GridBagLayout layout, int y, String text) {
GridBagConstraints c = new GridBagConstraints();
+ c.weighty = 1;
label = new JLabel(text);
- label.setFont(label_font);
+ label.setFont(Altos.label_font);
label.setHorizontalAlignment(SwingConstants.LEFT);
c.gridx = 0; c.gridy = y;
- c.insets = new Insets(10, 10, 10, 10);
+ c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
c.anchor = GridBagConstraints.WEST;
+ c.fill = GridBagConstraints.VERTICAL;
+ c.weightx = 0;
layout.setConstraints(label, c);
add(label);
value = new JTextField(15);
- value.setFont(value_font);
+ value.setFont(Altos.value_font);
value.setHorizontalAlignment(SwingConstants.RIGHT);
c.gridx = 1; c.gridy = y;
c.anchor = GridBagConstraints.EAST;
+ c.fill = GridBagConstraints.BOTH;
+ c.weightx = 1;
layout.setConstraints(value, c);
add(value);
max_value = new JTextField(15);
- max_value.setFont(value_font);
+ max_value.setFont(Altos.value_font);
max_value.setHorizontalAlignment(SwingConstants.RIGHT);
c.gridx = 2; c.gridy = y;
c.anchor = GridBagConstraints.EAST;
+ c.fill = GridBagConstraints.BOTH;
+ c.weightx = 1;
layout.setConstraints(max_value, c);
add(max_value);
}
return String.format("%s %4d° %9.6f", h, deg, min);
}
+ class Apogee extends AscentStatus {
+ void show (AltosState state, int crc_errors) {
+ value.setText(String.format("%4.2f V", state.drogue_sense));
+ lights.set(state.drogue_sense > 3.2);
+ }
+ public Apogee (GridBagLayout layout, int y) {
+ super(layout, y, "Apogee Igniter Voltage");
+ }
+ }
+
+ Apogee apogee;
+
+ class Main extends AscentStatus {
+ void show (AltosState state, int crc_errors) {
+ value.setText(String.format("%4.2f V", state.main_sense));
+ lights.set(state.main_sense > 3.2);
+ }
+ public Main (GridBagLayout layout, int y) {
+ super(layout, y, "Main Igniter Voltage");
+ }
+ }
+
+ Main main;
+
class Lat extends AscentValue {
void show (AltosState state, int crc_errors) {
if (state.gps != null)
public void reset() {
lat.reset();
lon.reset();
+ main.reset();
+ apogee.reset();
height.reset();
speed.reset();
accel.reset();
lat.show(state, crc_errors);
lon.show(state, crc_errors);
height.show(state, crc_errors);
+ main.show(state, crc_errors);
+ apogee.show(state, crc_errors);
speed.show(state, crc_errors);
accel.show(state, crc_errors);
}
JLabel cur, max;
cur = new JLabel("Current");
- cur.setFont(label_font);
+ cur.setFont(Altos.label_font);
c = new GridBagConstraints();
c.gridx = 1; c.gridy = y;
- c.insets = new Insets(10, 10, 10, 10);
+ c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
layout.setConstraints(cur, c);
add(cur);
max = new JLabel("Maximum");
- max.setFont(label_font);
+ max.setFont(Altos.label_font);
c.gridx = 2; c.gridy = y;
layout.setConstraints(max, c);
add(max);
public AltosAscent() {
layout = new GridBagLayout();
- label_font = new Font("Dialog", Font.PLAIN, 24);
- value_font = new Font("Monospaced", Font.PLAIN, 24);
setLayout(layout);
/* Elements in ascent display:
accel = new Accel(layout, 3);
lat = new Lat(layout, 4);
lon = new Lon(layout, 5);
+ apogee = new Apogee(layout, 6);
+ main = new Main(layout, 7);
}
}
import java.util.prefs.*;
import java.util.concurrent.LinkedBlockingQueue;
-import altosui.AltosLogfileChooser;
-import altosui.AltosCSV;
-
public class AltosCSVUI
extends JDialog
implements Runnable, ActionListener
import java.util.prefs.*;
import java.util.concurrent.LinkedBlockingQueue;
-import altosui.Altos;
-import altosui.AltosSerial;
-import altosui.AltosSerialMonitor;
-import altosui.AltosRecord;
-import altosui.AltosTelemetry;
-import altosui.AltosState;
-import altosui.AltosDeviceDialog;
-import altosui.AltosPreferences;
-import altosui.AltosLog;
-import altosui.AltosVoice;
-import altosui.AltosFlightStatusTableModel;
-import altosui.AltosFlightInfoTableModel;
-import altosui.AltosConfigUI;
-
import libaltosJNI.*;
public class AltosConfig implements Runnable, ActionListener {
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
- if (cmd.equals("save")) {
+ if (cmd.equals("Save")) {
save_data();
set_ui();
- } else if (cmd.equals("reset")) {
+ } else if (cmd.equals("Reset")) {
set_ui();
- } else if (cmd.equals("close")) {
+ } else if (cmd.equals("Reboot")) {
+ if (serial_line != null) {
+ try {
+ start_serial();
+ serial_line.printf("r eboot\n");
+ } catch (InterruptedException ie) {
+ } finally {
+ try {
+ stop_serial();
+ } catch (InterruptedException ie) {
+ }
+ }
+ serial_line.close();
+ }
+ } else if (cmd.equals("Close")) {
if (serial_line != null)
serial_line.close();
}
product = new string_ref("unknown");
device = AltosDeviceDialog.show(owner, AltosDevice.product_any);
- serial_line = new AltosSerial();
if (device != null) {
try {
- serial_line.open(device);
+ serial_line = new AltosSerial(device);
if (!device.matchProduct(AltosDevice.product_telemetrum))
remote = true;
config_thread = new Thread(this);
device.getPath()),
"Cannot open target device",
JOptionPane.ERROR_MESSAGE);
+ } catch (AltosSerialInUseException si) {
+ JOptionPane.showMessageDialog(owner,
+ String.format("Device \"%s\" already in use",
+ device.getPath()),
+ "Device in use",
+ JOptionPane.ERROR_MESSAGE);
} catch (IOException ee) {
JOptionPane.showMessageDialog(owner,
device.getPath(),
import java.util.prefs.*;
import java.util.concurrent.LinkedBlockingQueue;
-import altosui.Altos;
-import altosui.AltosSerial;
-import altosui.AltosSerialMonitor;
-import altosui.AltosRecord;
-import altosui.AltosTelemetry;
-import altosui.AltosState;
-import altosui.AltosDeviceDialog;
-import altosui.AltosPreferences;
-import altosui.AltosLog;
-import altosui.AltosVoice;
-import altosui.AltosFlightStatusTableModel;
-import altosui.AltosFlightInfoTableModel;
-
import libaltosJNI.*;
public class AltosConfigUI
JButton save;
JButton reset;
+ JButton reboot;
JButton close;
ActionListener listener;
public void windowClosing(WindowEvent e) {
ui.actionPerformed(new ActionEvent(e.getSource(),
ActionEvent.ACTION_PERFORMED,
- "close"));
+ "Close"));
}
}
/* Product */
c = new GridBagConstraints();
c.gridx = 0; c.gridy = 0;
- c.gridwidth = 3;
+ c.gridwidth = 4;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.LINE_START;
c.insets = il;
pane.add(product_label, c);
c = new GridBagConstraints();
- c.gridx = 3; c.gridy = 0;
- c.gridwidth = 3;
+ c.gridx = 4; c.gridy = 0;
+ c.gridwidth = 4;
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1;
c.anchor = GridBagConstraints.LINE_START;
/* Version */
c = new GridBagConstraints();
c.gridx = 0; c.gridy = 1;
- c.gridwidth = 3;
+ c.gridwidth = 4;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.LINE_START;
c.insets = il;
pane.add(version_label, c);
c = new GridBagConstraints();
- c.gridx = 3; c.gridy = 1;
- c.gridwidth = 3;
+ c.gridx = 4; c.gridy = 1;
+ c.gridwidth = 4;
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1;
c.anchor = GridBagConstraints.LINE_START;
/* Serial */
c = new GridBagConstraints();
c.gridx = 0; c.gridy = 2;
- c.gridwidth = 3;
+ c.gridwidth = 4;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.LINE_START;
c.insets = il;
pane.add(serial_label, c);
c = new GridBagConstraints();
- c.gridx = 3; c.gridy = 2;
- c.gridwidth = 3;
+ c.gridx = 4; c.gridy = 2;
+ c.gridwidth = 4;
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1;
c.anchor = GridBagConstraints.LINE_START;
/* Main deploy */
c = new GridBagConstraints();
c.gridx = 0; c.gridy = 3;
- c.gridwidth = 3;
+ c.gridwidth = 4;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.LINE_START;
c.insets = il;
pane.add(main_deploy_label, c);
c = new GridBagConstraints();
- c.gridx = 3; c.gridy = 3;
- c.gridwidth = 3;
+ c.gridx = 4; c.gridy = 3;
+ c.gridwidth = 4;
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1;
c.anchor = GridBagConstraints.LINE_START;
/* Apogee delay */
c = new GridBagConstraints();
c.gridx = 0; c.gridy = 4;
- c.gridwidth = 3;
+ c.gridwidth = 4;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.LINE_START;
c.insets = il;
pane.add(apogee_delay_label, c);
c = new GridBagConstraints();
- c.gridx = 3; c.gridy = 4;
- c.gridwidth = 3;
+ c.gridx = 4; c.gridy = 4;
+ c.gridwidth = 4;
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1;
c.anchor = GridBagConstraints.LINE_START;
/* Radio channel */
c = new GridBagConstraints();
c.gridx = 0; c.gridy = 5;
- c.gridwidth = 3;
+ c.gridwidth = 4;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.LINE_START;
c.insets = il;
pane.add(radio_channel_label, c);
c = new GridBagConstraints();
- c.gridx = 3; c.gridy = 5;
- c.gridwidth = 3;
+ c.gridx = 4; c.gridy = 5;
+ c.gridwidth = 4;
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1;
c.anchor = GridBagConstraints.LINE_START;
/* Radio Calibration */
c = new GridBagConstraints();
c.gridx = 0; c.gridy = 6;
- c.gridwidth = 3;
+ c.gridwidth = 4;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.LINE_START;
c.insets = il;
pane.add(radio_calibration_label, c);
c = new GridBagConstraints();
- c.gridx = 3; c.gridy = 6;
- c.gridwidth = 3;
+ c.gridx = 4; c.gridy = 6;
+ c.gridwidth = 4;
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1;
c.anchor = GridBagConstraints.LINE_START;
/* Callsign */
c = new GridBagConstraints();
c.gridx = 0; c.gridy = 7;
- c.gridwidth = 3;
+ c.gridwidth = 4;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.LINE_START;
c.insets = il;
pane.add(callsign_label, c);
c = new GridBagConstraints();
- c.gridx = 3; c.gridy = 7;
- c.gridwidth = 3;
+ c.gridx = 4; c.gridy = 7;
+ c.gridwidth = 4;
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1;
c.anchor = GridBagConstraints.LINE_START;
c.insets = ir;
c.ipady = 5;
- callsign_value = new JTextField("N0CALL");
+ callsign_value = new JTextField(AltosPreferences.callsign());
callsign_value.getDocument().addDocumentListener(this);
pane.add(callsign_value, c);
/* Buttons */
c = new GridBagConstraints();
c.gridx = 0; c.gridy = 8;
- c.gridwidth = 6;
+ c.gridwidth = 2;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.LINE_START;
c.insets = il;
save = new JButton("Save");
pane.add(save, c);
save.addActionListener(this);
- save.setActionCommand("save");
+ save.setActionCommand("Save");
c = new GridBagConstraints();
- c.gridx = 0; c.gridy = 8;
- c.gridwidth = 6;
+ c.gridx = 2; c.gridy = 8;
+ c.gridwidth = 2;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.CENTER;
c.insets = il;
reset = new JButton("Reset");
pane.add(reset, c);
reset.addActionListener(this);
- reset.setActionCommand("reset");
+ reset.setActionCommand("Reset");
c = new GridBagConstraints();
- c.gridx = 0; c.gridy = 8;
- c.gridwidth = 6;
+ c.gridx = 4; c.gridy = 8;
+ c.gridwidth = 2;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.CENTER;
+ c.insets = il;
+ reboot = new JButton("Reboot");
+ pane.add(reboot, c);
+ reboot.addActionListener(this);
+ reboot.setActionCommand("Reboot");
+
+ c = new GridBagConstraints();
+ c.gridx = 6; c.gridy = 8;
+ c.gridwidth = 2;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.LINE_END;
c.insets = il;
close = new JButton("Close");
pane.add(close, c);
close.addActionListener(this);
- close.setActionCommand("close");
+ close.setActionCommand("Close");
addWindowListener(new ConfigListener(this));
}
}
/* If any values have been changed, confirm before closing */
- public boolean check_dirty() {
+ public boolean check_dirty(String operation) {
if (dirty) {
- Object[] options = { "Close anyway", "Keep editing" };
+ Object[] options = { String.format("%s anyway", operation), "Keep editing" };
int i;
i = JOptionPane.showOptionDialog(this,
- "Configuration modified, close anyway?",
+ String.format("Configuration modified. %s anyway?", operation),
"Configuration Modified",
JOptionPane.DEFAULT_OPTION,
JOptionPane.WARNING_MESSAGE,
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
- if (cmd.equals("close"))
- if (!check_dirty())
+ if (cmd.equals("Close") || cmd.equals("Reboot"))
+ if (!check_dirty(cmd))
return;
listener.actionPerformed(e);
- if (cmd.equals("close")) {
+ if (cmd.equals("Close") || cmd.equals("Reboot")) {
setVisible(false);
dispose();
}
--- /dev/null
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package altosui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.filechooser.FileNameExtensionFilter;
+import javax.swing.table.*;
+import javax.swing.event.*;
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import java.util.prefs.*;
+import java.util.concurrent.LinkedBlockingQueue;
+
+public class AltosConfigureUI
+ extends JDialog
+ implements DocumentListener
+{
+ JFrame owner;
+ AltosVoice voice;
+ Container pane;
+
+ JRadioButton enable_voice;
+ JButton test_voice;
+ JButton close;
+
+ JButton configure_log;
+ JTextField log_directory;
+
+ JLabel callsign_label;
+ JTextField callsign_value;
+
+ /* DocumentListener interface methods */
+ public void changedUpdate(DocumentEvent e) {
+ AltosPreferences.set_callsign(callsign_value.getText());
+ }
+
+ public void insertUpdate(DocumentEvent e) {
+ changedUpdate(e);
+ }
+
+ public void removeUpdate(DocumentEvent e) {
+ changedUpdate(e);
+ }
+
+ public AltosConfigureUI(JFrame in_owner, AltosVoice in_voice) {
+ super(in_owner, "Configure AltosUI", false);
+
+ GridBagConstraints c;
+
+ Insets insets = new Insets(4, 4, 4, 4);
+
+ owner = in_owner;
+ voice = in_voice;
+ pane = getContentPane();
+ pane.setLayout(new GridBagLayout());
+
+ c = new GridBagConstraints();
+ c.insets = insets;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.CENTER;
+
+ /* Enable Voice */
+ c.gridx = 0;
+ c.gridy = 0;
+ enable_voice = new JRadioButton("Enable Voice", AltosPreferences.voice());
+ enable_voice.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ JRadioButton item = (JRadioButton) e.getSource();
+ boolean enabled = item.isSelected();
+ AltosPreferences.set_voice(enabled);
+ if (enabled)
+ voice.speak_always("Enable voice.");
+ else
+ voice.speak_always("Disable voice.");
+ }
+ });
+ pane.add(enable_voice, c);
+ c.gridx = 1;
+ c.gridy = 0;
+ test_voice = new JButton("Test Voice");
+ test_voice.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ voice.speak("That's one small step for man; one giant leap for mankind.");
+ }
+ });
+ pane.add(test_voice, c);
+
+ configure_log = new JButton("Configure Log");
+ configure_log.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ AltosPreferences.ConfigureLog();
+ log_directory.setText(AltosPreferences.logdir().getPath());
+ }
+ });
+ c.gridwidth = 1;
+
+ c.gridx = 0;
+ c.gridy = 2;
+ pane.add(configure_log, c);
+
+ log_directory = new JTextField(AltosPreferences.logdir().getPath());
+ c.gridx = 1;
+ c.gridy = 2;
+ c.fill = GridBagConstraints.BOTH;
+ pane.add(log_directory, c);
+
+ callsign_label = new JLabel("Callsign");
+ c.gridx = 0;
+ c.gridy = 3;
+ pane.add(callsign_label, c);
+
+ callsign_value = new JTextField(AltosPreferences.callsign());
+ callsign_value.getDocument().addDocumentListener(this);
+ c.gridx = 1;
+ c.gridy = 3;
+ pane.add(callsign_value, c);
+
+ close = new JButton("Close");
+ close.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ setVisible(false);
+ }
+ });
+ c.gridx = 0;
+ c.gridy = 4;
+ c.gridwidth = 2;
+ c.fill = GridBagConstraints.NONE;
+ pane.add(close, c);
+
+ pack();
+ setLocationRelativeTo(owner);
+ setVisible(true);
+ }
+}
import java.util.NoSuchElementException;
import java.util.Iterator;
-import altosui.AltosDataPoint;
-import altosui.AltosRecordIterable;
-import altosui.AltosRecord;
-import altosui.AltosState;
-
class AltosDataPointReader implements Iterable<AltosDataPoint> {
Iterator<AltosRecord> iter;
AltosState state;
import java.lang.*;
import java.io.*;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.LinkedList;
-import java.util.Iterator;
-import altosui.AltosSerial;
-import altosui.AltosRomconfig;
+import java.util.concurrent.*;
+import java.util.*;
+
+import libaltosJNI.*;
public class AltosDebug extends AltosSerial {
public void reset() {
printf ("R\n");
}
+
+ public AltosDebug (altos_device in_device) throws FileNotFoundException, AltosSerialInUseException {
+ super(in_device);
+ }
}
\ No newline at end of file
public class AltosDescent extends JComponent implements AltosFlightDisplay {
GridBagLayout layout;
- Font label_font;
- Font value_font;
+ public class DescentStatus {
+ JLabel label;
+ JTextField value;
+ AltosLights lights;
+
+ void show(AltosState state, int crc_errors) {}
+ void reset() {
+ value.setText("");
+ lights.set(false);
+ }
+
+ public DescentStatus (GridBagLayout layout, int y, String text) {
+ GridBagConstraints c = new GridBagConstraints();
+ c.weighty = 1;
+
+ lights = new AltosLights();
+ c.gridx = 0; c.gridy = y;
+ c.anchor = GridBagConstraints.CENTER;
+ c.fill = GridBagConstraints.VERTICAL;
+ c.weightx = 0;
+ layout.setConstraints(lights, c);
+ add(lights);
+
+ label = new JLabel(text);
+ label.setFont(Altos.label_font);
+ label.setHorizontalAlignment(SwingConstants.LEFT);
+ c.gridx = 1; c.gridy = y;
+ c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
+ c.anchor = GridBagConstraints.WEST;
+ c.fill = GridBagConstraints.VERTICAL;
+ c.weightx = 0;
+ layout.setConstraints(label, c);
+ add(label);
+
+ value = new JTextField(15);
+ value.setFont(Altos.value_font);
+ value.setHorizontalAlignment(SwingConstants.RIGHT);
+ c.gridx = 2; c.gridy = y;
+ c.anchor = GridBagConstraints.WEST;
+ c.fill = GridBagConstraints.BOTH;
+ c.weightx = 1;
+ layout.setConstraints(value, c);
+ add(value);
+
+ }
+ }
public class DescentValue {
JLabel label;
JTextField value;
value.setText(String.format(format, v));
}
- public DescentValue (GridBagLayout layout, int y, String text) {
+ public DescentValue (GridBagLayout layout, int x, int y, String text) {
GridBagConstraints c = new GridBagConstraints();
+ c.weighty = 1;
label = new JLabel(text);
- label.setFont(label_font);
+ label.setFont(Altos.label_font);
label.setHorizontalAlignment(SwingConstants.LEFT);
- c.gridx = 0; c.gridy = y;
- c.insets = new Insets(10, 10, 10, 10);
+ c.gridx = x + 0; c.gridy = y;
+ c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
c.anchor = GridBagConstraints.WEST;
+ c.fill = GridBagConstraints.VERTICAL;
+ c.weightx = 0;
layout.setConstraints(label, c);
add(label);
- value = new JTextField(30);
- value.setFont(value_font);
+ value = new JTextField(17);
+ value.setFont(Altos.value_font);
value.setHorizontalAlignment(SwingConstants.RIGHT);
- c.gridx = 1; c.gridy = y;
- c.gridwidth = 2;
+ c.gridx = x + 1; c.gridy = y;
c.anchor = GridBagConstraints.WEST;
- c.fill = GridBagConstraints.HORIZONTAL;
+ c.fill = GridBagConstraints.BOTH;
+ c.weightx = 1;
layout.setConstraints(value, c);
add(value);
}
void show (AltosState state, int crc_errors) {
show("%6.0f m", state.height);
}
- public Height (GridBagLayout layout, int y) {
- super (layout, y, "Height");
+ public Height (GridBagLayout layout, int x, int y) {
+ super (layout, x, y, "Height");
}
}
speed = state.baro_speed;
show("%6.0f m/s", speed);
}
- public Speed (GridBagLayout layout, int y) {
- super (layout, y, "Speed");
+ public Speed (GridBagLayout layout, int x, int y) {
+ super (layout, x, y, "Speed");
}
}
else
value.setText("???");
}
- public Lat (GridBagLayout layout, int y) {
- super (layout, y, "Latitude");
+ public Lat (GridBagLayout layout, int x, int y) {
+ super (layout, x, y, "Latitude");
}
}
else
value.setText("???");
}
- public Lon (GridBagLayout layout, int y) {
- super (layout, y, "Longitude");
+ public Lon (GridBagLayout layout, int x, int y) {
+ super (layout, x, y, "Longitude");
}
}
Lon lon;
+ class Apogee extends DescentStatus {
+ void show (AltosState state, int crc_errors) {
+ value.setText(String.format("%4.2f V", state.drogue_sense));
+ lights.set(state.drogue_sense > 3.2);
+ }
+ public Apogee (GridBagLayout layout, int y) {
+ super(layout, y, "Apogee Igniter Voltage");
+ }
+ }
+
+ Apogee apogee;
+
+ class Main extends DescentStatus {
+ void show (AltosState state, int crc_errors) {
+ value.setText(String.format("%4.2f V", state.main_sense));
+ lights.set(state.main_sense > 3.2);
+ }
+ public Main (GridBagLayout layout, int y) {
+ super(layout, y, "Main Igniter Voltage");
+ }
+ }
+
+ Main main;
+
class Bearing {
JLabel label;
JTextField value;
JTextField value_deg;
- void reset () {
+ void reset () {
value.setText("");
value_deg.setText("");
- }
+ }
void show (AltosState state, int crc_errors) {
if (state.from_pad != null) {
- value.setText(state.from_pad.bearing_words(
- AltosGreatCircle.BEARING_LONG));
+ value.setText(state.from_pad.bearing_words(
+ AltosGreatCircle.BEARING_LONG));
value_deg.setText(String.format("%3.0f°", state.from_pad.bearing));
} else {
value.setText("???");
value_deg.setText("???");
- }
- }
- public Bearing (GridBagLayout layout, int y) {
- GridBagConstraints c = new GridBagConstraints();
-
- label = new JLabel("Bearing");
- label.setFont(label_font);
- label.setHorizontalAlignment(SwingConstants.LEFT);
- c.gridx = 0; c.gridy = y;
- c.insets = new Insets(10, 10, 10, 10);
- c.anchor = GridBagConstraints.WEST;
- layout.setConstraints(label, c);
- add(label);
-
- value = new JTextField(30);
- value.setFont(value_font);
- value.setHorizontalAlignment(SwingConstants.RIGHT);
- c.gridx = 1; c.gridy = y;
- c.anchor = GridBagConstraints.EAST;
- c.fill = GridBagConstraints.HORIZONTAL;
- layout.setConstraints(value, c);
- add(value);
-
- value_deg = new JTextField(5);
- value_deg.setFont(value_font);
- value_deg.setHorizontalAlignment(SwingConstants.RIGHT);
- c.gridx = 2; c.gridy = y;
- c.anchor = GridBagConstraints.EAST;
- c.fill = GridBagConstraints.HORIZONTAL;
-
- layout.setConstraints(value_deg, c);
- add(value_deg);
+ }
+ }
+ public Bearing (GridBagLayout layout, int x, int y) {
+ GridBagConstraints c = new GridBagConstraints();
+ c.weighty = 1;
+
+ label = new JLabel("Bearing");
+ label.setFont(Altos.label_font);
+ label.setHorizontalAlignment(SwingConstants.LEFT);
+ c.gridx = x + 0; c.gridy = y;
+ c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
+ c.anchor = GridBagConstraints.WEST;
+ c.weightx = 0;
+ c.fill = GridBagConstraints.VERTICAL;
+ layout.setConstraints(label, c);
+ add(label);
+
+ value = new JTextField(30);
+ value.setFont(Altos.value_font);
+ value.setHorizontalAlignment(SwingConstants.RIGHT);
+ c.gridx = x + 1; c.gridy = y;
+ c.anchor = GridBagConstraints.EAST;
+ c.weightx = 1;
+ c.gridwidth = 2;
+ c.fill = GridBagConstraints.BOTH;
+ layout.setConstraints(value, c);
+ add(value);
+
+ value_deg = new JTextField(5);
+ value_deg.setFont(Altos.value_font);
+ value_deg.setHorizontalAlignment(SwingConstants.RIGHT);
+ c.gridx = x + 3; c.gridy = y;
+ c.anchor = GridBagConstraints.EAST;
+ c.weightx = 1;
+ c.fill = GridBagConstraints.BOTH;
+ layout.setConstraints(value_deg, c);
+ add(value_deg);
}
}
else
value.setText("???");
}
- public Elevation (GridBagLayout layout, int y) {
- super (layout, y, "Elevation");
+ public Elevation (GridBagLayout layout, int x, int y) {
+ super (layout, x, y, "Elevation");
}
}
void show (AltosState state, int crc_errors) {
show("%6.0f m", state.range);
}
- public Range (GridBagLayout layout, int y) {
- super (layout, y, "Range");
+ public Range (GridBagLayout layout, int x, int y) {
+ super (layout, x, y, "Range");
}
}
bearing.reset();
elevation.reset();
range.reset();
+ main.reset();
+ apogee.reset();
}
public void show(AltosState state, int crc_errors) {
range.show(state, crc_errors);
lat.show(state, crc_errors);
lon.show(state, crc_errors);
+ main.show(state, crc_errors);
+ apogee.show(state, crc_errors);
}
public AltosDescent() {
layout = new GridBagLayout();
- label_font = new Font("Dialog", Font.PLAIN, 24);
- value_font = new Font("Monospaced", Font.PLAIN, 24);
setLayout(layout);
/* Elements in descent display */
- speed = new Speed(layout, 0);
- height = new Height(layout, 1);
- bearing = new Bearing(layout, 2);
- elevation = new Elevation(layout, 3);
- range = new Range(layout, 4);
- lat = new Lat(layout, 5);
- lon = new Lon(layout, 6);
+ speed = new Speed(layout, 0, 0); height = new Height(layout, 2, 0);
+ elevation = new Elevation(layout, 0, 1); range = new Range(layout, 2, 1);
+ bearing = new Bearing(layout, 0, 2);
+ lat = new Lat(layout, 0, 3);
+ lon = new Lon(layout, 0, 4);
+ apogee = new Apogee(layout, 5);
+ main = new Main(layout, 6);
}
}
import libaltosJNI.altos_device;
import libaltosJNI.SWIGTYPE_p_altos_file;
import libaltosJNI.SWIGTYPE_p_altos_list;
-import altosui.AltosDevice;
public class AltosDeviceDialog extends JDialog implements ActionListener {
import java.util.prefs.*;
import java.util.concurrent.LinkedBlockingQueue;
-import altosui.Altos;
-import altosui.AltosSerial;
-import altosui.AltosSerialMonitor;
-import altosui.AltosRecord;
-import altosui.AltosTelemetry;
-import altosui.AltosState;
-import altosui.AltosDeviceDialog;
-import altosui.AltosPreferences;
-import altosui.AltosLog;
-import altosui.AltosVoice;
-import altosui.AltosEepromMonitor;
-
import libaltosJNI.*;
public class AltosEepromDownload implements Runnable {
frame = given_frame;
device = AltosDeviceDialog.show(frame, AltosDevice.product_any);
- serial_line = new AltosSerial();
remote = false;
if (device != null) {
try {
- serial_line.open(device);
+ serial_line = new AltosSerial(device);
if (!device.matchProduct(AltosDevice.product_telemetrum))
remote = true;
eeprom_thread = new Thread(this);
device.getPath()),
"Cannot open target device",
JOptionPane.ERROR_MESSAGE);
+ } catch (AltosSerialInUseException si) {
+ JOptionPane.showMessageDialog(frame,
+ String.format("Device \"%s\" already in use",
+ device.getPath()),
+ "Device in use",
+ JOptionPane.ERROR_MESSAGE);
} catch (IOException ee) {
JOptionPane.showMessageDialog(frame,
device.getPath(),
import java.util.prefs.*;
import java.util.concurrent.LinkedBlockingQueue;
-import altosui.AltosRecord;
-import altosui.AltosState;
-import altosui.AltosDeviceDialog;
-import altosui.AltosPreferences;
-import altosui.AltosLog;
-import altosui.AltosVoice;
-import altosui.AltosEepromMonitor;
-
/*
* AltosRecords with an index field so they can be sorted by tick while preserving
* the original ordering for elements with matching ticks
import java.util.prefs.*;
import java.util.concurrent.LinkedBlockingQueue;
-import altosui.AltosSerial;
-import altosui.AltosSerialMonitor;
-import altosui.AltosRecord;
-import altosui.AltosTelemetry;
-import altosui.AltosState;
-import altosui.AltosDeviceDialog;
-import altosui.AltosPreferences;
-import altosui.AltosLog;
-import altosui.AltosVoice;
-
public class AltosEepromMonitor extends JDialog {
Container pane;
import java.util.prefs.*;
import java.util.concurrent.LinkedBlockingQueue;
-import altosui.AltosSerial;
-import altosui.AltosSerialMonitor;
-import altosui.AltosRecord;
-import altosui.AltosTelemetry;
-import altosui.AltosState;
-import altosui.AltosDeviceDialog;
-import altosui.AltosPreferences;
-import altosui.AltosLog;
-import altosui.AltosVoice;
-import altosui.AltosEepromMonitor;
-
public class AltosEepromRecord {
public int cmd;
public int tick;
import java.lang.*;
import java.io.File;
import java.util.*;
-import altosui.AltosTelemetry;
-import altosui.AltosPreferences;
class AltosFile extends File {
import java.util.prefs.*;
import java.util.concurrent.LinkedBlockingQueue;
-import altosui.AltosHexfile;
-
public class AltosFlash {
File file;
FileInputStream input;
return rom_config;
}
- public void open() throws IOException, FileNotFoundException, InterruptedException {
+ public AltosFlash(File in_file, AltosDevice in_debug_dongle)
+ throws IOException, FileNotFoundException, AltosSerialInUseException, InterruptedException {
+ file = in_file;
+ debug_dongle = in_debug_dongle;
+ debug = new AltosDebug(in_debug_dongle);
input = new FileInputStream(file);
image = new AltosHexfile(input);
- debug.open(debug_dongle);
if (!debug.check_connection())
throw new IOException("Debug port not connected");
}
-
- public AltosFlash(File in_file, AltosDevice in_debug_dongle) {
- file = in_file;
- debug_dongle = in_debug_dongle;
- debug = new AltosDebug();
- }
}
\ No newline at end of file
import java.util.prefs.*;
import java.util.concurrent.LinkedBlockingQueue;
-import altosui.AltosHexfile;
-import altosui.AltosFlash;
-
public class AltosFlashUI
extends JDialog
implements Runnable, ActionListener
}
public void run() {
- flash = new AltosFlash(file, debug_dongle);
- flash.addActionListener(this);
try {
- flash.open();
+ flash = new AltosFlash(file, debug_dongle);
+ flash.addActionListener(this);
AltosRomconfigUI romconfig_ui = new AltosRomconfigUI (frame);
romconfig_ui.set(flash.romconfig());
"Cannot open image",
file.toString(),
JOptionPane.ERROR_MESSAGE);
+ } catch (AltosSerialInUseException si) {
+ JOptionPane.showMessageDialog(frame,
+ String.format("Device \"%s\" already in use",
+ debug_dongle.getPath()),
+ "Device in use",
+ JOptionPane.ERROR_MESSAGE);
} catch (IOException e) {
JOptionPane.showMessageDialog(frame,
e.getMessage(),
public int getColumnCount() { return columnNames.length; }
public String getColumnName(int col) { return columnNames[col]; }
- public int getRowCount() { return 20; }
+ public int getRowCount() { return 17; }
int current_row = 0;
int prev_num_rows = 0;
--- /dev/null
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package altosui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.filechooser.FileNameExtensionFilter;
+import javax.swing.table.*;
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import java.util.prefs.*;
+import java.util.concurrent.LinkedBlockingQueue;
+
+public class AltosFlightStatus extends JComponent implements AltosFlightDisplay {
+ GridBagLayout layout;
+
+ public class FlightValue {
+ JLabel label;
+ JTextField value;
+
+ void show(AltosState state, int crc_errors) {}
+
+ void reset() {
+ value.setText("");
+ }
+ public FlightValue (GridBagLayout layout, int x, String text) {
+ GridBagConstraints c = new GridBagConstraints();
+ c.insets = new Insets(5, 5, 5, 5);
+ c.anchor = GridBagConstraints.CENTER;
+ c.fill = GridBagConstraints.BOTH;
+ c.weightx = 1;
+ c.weighty = 1;
+
+ label = new JLabel(text);
+ label.setFont(Altos.status_font);
+ label.setHorizontalAlignment(SwingConstants.CENTER);
+ c.gridx = x; c.gridy = 0;
+ layout.setConstraints(label, c);
+ add(label);
+
+ value = new JTextField("");
+ value.setFont(Altos.status_font);
+ value.setHorizontalAlignment(SwingConstants.CENTER);
+ c.gridx = x; c.gridy = 1;
+ layout.setConstraints(value, c);
+ add(value);
+ }
+ }
+
+ class Call extends FlightValue {
+ void show(AltosState state, int crc_errors) {
+ value.setText(state.data.callsign);
+ }
+ public Call (GridBagLayout layout, int x) {
+ super (layout, x, "Callsign");
+ }
+ }
+
+ Call call;
+
+ class Serial extends FlightValue {
+ void show(AltosState state, int crc_errors) {
+ value.setText(String.format("%d", state.data.serial));
+ }
+ public Serial (GridBagLayout layout, int x) {
+ super (layout, x, "Serial");
+ }
+ }
+
+ Serial serial;
+
+ class Flight extends FlightValue {
+ void show(AltosState state, int crc_errors) {
+ value.setText(String.format("%d", state.data.flight));
+ }
+ public Flight (GridBagLayout layout, int x) {
+ super (layout, x, "Flight");
+ }
+ }
+
+ Flight flight;
+
+ class FlightState extends FlightValue {
+ void show(AltosState state, int crc_errors) {
+ value.setText(state.data.state());
+ }
+ public FlightState (GridBagLayout layout, int x) {
+ super (layout, x, "State");
+ }
+ }
+
+ FlightState flight_state;
+
+ class RSSI extends FlightValue {
+ void show(AltosState state, int crc_errors) {
+ value.setText(String.format("%d", state.data.rssi));
+ }
+ public RSSI (GridBagLayout layout, int x) {
+ super (layout, x, "RSSI (dBm)");
+ }
+ }
+
+ RSSI rssi;
+
+ public void reset () {
+ call.reset();
+ serial.reset();
+ flight.reset();
+ flight_state.reset();
+ rssi.reset();
+ }
+
+ public void show (AltosState state, int crc_errors) {
+ call.show(state, crc_errors);
+ serial.show(state, crc_errors);
+ flight.show(state, crc_errors);
+ flight_state.show(state, crc_errors);
+ rssi.show(state, crc_errors);
+ }
+
+ public int height() {
+ Dimension d = layout.preferredLayoutSize(this);
+ return d.height;
+ }
+
+ public AltosFlightStatus() {
+ layout = new GridBagLayout();
+
+ setLayout(layout);
+
+ call = new Call(layout, 0);
+ serial = new Serial(layout, 1);
+ flight = new Flight(layout, 2);
+ flight_state = new FlightState(layout, 3);
+ rssi = new RSSI(layout, 4);
+ }
+}
AltosLanded landed;
AltosSiteMap sitemap;
- private AltosStatusTable flightStatus;
+ private AltosFlightStatus flightStatus;
+ private JScrollPane flightInfoPane;
private AltosInfoTable flightInfo;
static final int tab_pad = 1;
int cur_tab = 0;
+ boolean exit_on_close = false;
+
int which_tab(AltosState state) {
if (state.state < Altos.ao_flight_boost)
return tab_pad;
}
cur_tab = tab;
}
- flightStatus.set(state);
+ flightStatus.show(state, crc_errors);
flightInfo.show(state, crc_errors);
sitemap.show(state, crc_errors);
}
+ public void set_exit_on_close() {
+ exit_on_close = true;
+ }
+
public AltosFlightUI(AltosVoice in_voice, AltosFlightReader in_reader, final int serial) {
- AltosPreferences.init(this);
+ AltosPreferences.init(this);
voice = in_voice;
reader = in_reader;
setTitle(String.format("AltOS %s", reader.name));
- flightStatus = new AltosStatusTable();
+ flightStatus = new AltosFlightStatus();
vbox = new Box (BoxLayout.Y_AXIS);
vbox.add(flightStatus);
pane.add("Landed", landed);
flightInfo = new AltosInfoTable();
- pane.add("Table", new JScrollPane(flightInfo.box()));
+ flightInfoPane = new JScrollPane(flightInfo.box());
+ pane.add("Table", flightInfoPane);
sitemap = new AltosSiteMap();
pane.add("Site Map", sitemap);
this.setJMenuBar(menubar);
}
- this.setSize(new Dimension (width(), height()));
+ this.setSize(this.getPreferredSize());
this.validate();
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
disconnect();
setVisible(false);
dispose();
+ if (exit_on_close)
+ System.exit(0);
}
});
import java.lang.*;
import java.text.*;
-import altosui.AltosParse;
-
public class AltosGPS {
public class AltosGPSSat {
import org.jfree.chart.JFreeChart;
import org.jfree.chart.ChartUtilities;
-import altosui.AltosDataPoint;
-
abstract class AltosGraph {
public String filename;
public abstract void addData(AltosDataPoint d);
import java.text.*;
import java.util.prefs.*;
-import altosui.AltosPreferences;
-import altosui.AltosDataPointReader;
-import altosui.AltosEepromIterable;
-import altosui.AltosTelemetryIterable;
-
public class AltosGraphDataChooser extends JFileChooser {
JFrame frame;
String filename;
import org.jfree.ui.RectangleAnchor;
import org.jfree.ui.TextAnchor;
-import altosui.AltosDataPoint;
-import altosui.AltosGraph;
-
class AltosGraphTime extends AltosGraph {
static interface Element {
void attachGraph(AltosGraphTime g);
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;
-import altosui.AltosDataPoint;
-import altosui.AltosGraphTime;
-
public class AltosGraphUI extends JFrame
{
static final private Color red = new Color(194,31,31);
package altosui;
-import altosui.AltosGPS;
-
import java.lang.Math;
public class AltosGreatCircle {
import java.util.prefs.*;
import java.util.concurrent.LinkedBlockingQueue;
-import altosui.AltosFlightInfoTableModel;
-import altosui.AltosState;
-
public class AltosInfoTable {
private Box box;
private JTable table[];
public LandedValue (GridBagLayout layout, int y, String text) {
GridBagConstraints c = new GridBagConstraints();
+ c.weighty = 1;
label = new JLabel(text);
label.setFont(label_font);
c.gridx = 0; c.gridy = y;
c.insets = new Insets(10, 10, 10, 10);
c.anchor = GridBagConstraints.WEST;
+ c.weightx = 0;
+ c.fill = GridBagConstraints.VERTICAL;
layout.setConstraints(label, c);
add(label);
value.setHorizontalAlignment(SwingConstants.RIGHT);
c.gridx = 1; c.gridy = y;
c.anchor = GridBagConstraints.WEST;
- c.fill = GridBagConstraints.HORIZONTAL;
+ c.weightx = 1;
+ c.fill = GridBagConstraints.BOTH;
layout.setConstraints(value, c);
add(value);
}
public AltosLanded() {
layout = new GridBagLayout();
- label_font = new Font("Dialog", Font.PLAIN, 24);
- value_font = new Font("Monospaced", Font.PLAIN, 24);
+ label_font = new Font("Dialog", Font.PLAIN, 22);
+ value_font = new Font("Monospaced", Font.PLAIN, 22);
setLayout(layout);
/* Elements in descent display */
import java.util.*;
import java.text.ParseException;
import java.util.concurrent.LinkedBlockingQueue;
-import altosui.AltosSerial;
-import altosui.AltosFile;
-import altosui.AltosLine;
/*
* This creates a thread to capture telemetry data and write it to
public class AltosPad extends JComponent implements AltosFlightDisplay {
GridBagLayout layout;
- Font label_font;
- Font value_font;
public class LaunchStatus {
JLabel label;
public LaunchStatus (GridBagLayout layout, int y, String text) {
GridBagConstraints c = new GridBagConstraints();
+ c.weighty = 1;
lights = new AltosLights();
c.gridx = 0; c.gridy = y;
c.anchor = GridBagConstraints.CENTER;
- c.fill = GridBagConstraints.CENTER;
+ c.fill = GridBagConstraints.VERTICAL;
+ c.weightx = 0;
layout.setConstraints(lights, c);
add(lights);
label = new JLabel(text);
- label.setFont(label_font);
+ label.setFont(Altos.label_font);
label.setHorizontalAlignment(SwingConstants.LEFT);
c.gridx = 1; c.gridy = y;
- c.insets = new Insets(10, 10, 10, 10);
+ c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
c.anchor = GridBagConstraints.WEST;
- c.fill = GridBagConstraints.WEST;
+ c.fill = GridBagConstraints.VERTICAL;
+ c.weightx = 0;
layout.setConstraints(label, c);
add(label);
value = new JTextField(15);
- value.setFont(value_font);
+ value.setFont(Altos.value_font);
value.setHorizontalAlignment(SwingConstants.RIGHT);
c.gridx = 2; c.gridy = y;
c.anchor = GridBagConstraints.WEST;
+ c.fill = GridBagConstraints.BOTH;
+ c.weightx = 1;
layout.setConstraints(value, c);
add(value);
}
public LaunchValue (GridBagLayout layout, int y, String text) {
GridBagConstraints c = new GridBagConstraints();
+ c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
+ c.weighty = 1;
label = new JLabel(text);
- label.setFont(label_font);
+ label.setFont(Altos.label_font);
label.setHorizontalAlignment(SwingConstants.LEFT);
c.gridx = 1; c.gridy = y;
- c.insets = new Insets(10, 10, 10, 10);
c.anchor = GridBagConstraints.WEST;
+ c.fill = GridBagConstraints.VERTICAL;
+ c.weightx = 0;
layout.setConstraints(label, c);
add(label);
value = new JTextField(30);
- value.setFont(value_font);
+ value.setFont(Altos.value_font);
value.setHorizontalAlignment(SwingConstants.RIGHT);
c.gridx = 2; c.gridy = y;
c.anchor = GridBagConstraints.EAST;
- c.fill = GridBagConstraints.HORIZONTAL;
+ c.fill = GridBagConstraints.BOTH;
+ c.weightx = 1;
layout.setConstraints(value, c);
add(value);
}
Main main;
- class GPS extends LaunchStatus {
+ class GPSLocked extends LaunchStatus {
void show (AltosState state, int crc_errors) {
value.setText(String.format("%4d sats", state.gps.nsat));
+ lights.set(state.gps.locked);
+ }
+ public GPSLocked (GridBagLayout layout, int y) {
+ super (layout, y, "GPS Locked");
+ }
+ }
+
+ GPSLocked gps_locked;
+
+ class GPSReady extends LaunchStatus {
+ void show (AltosState state, int crc_errors) {
+ if (state.gps_ready)
+ value.setText("Ready");
+ else
+ value.setText(String.format("Waiting %d", state.gps_waiting));
lights.set(state.gps_ready);
}
- public GPS (GridBagLayout layout, int y) {
- super (layout, y, "GPS Status");
+ public GPSReady (GridBagLayout layout, int y) {
+ super (layout, y, "GPS Ready");
}
}
- GPS gps;
+ GPSReady gps_ready;
String pos(double p, String pos, String neg) {
String h = pos;
battery.reset();
apogee.reset();
main.reset();
- gps.reset();
+ gps_locked.reset();
+ gps_ready.reset();
pad_lat.reset();
pad_lon.reset();
pad_alt.reset();
battery.show(state, crc_errors);
apogee.show(state, crc_errors);
main.show(state, crc_errors);
- gps.show(state, crc_errors);
+ gps_locked.show(state, crc_errors);
+ gps_ready.show(state, crc_errors);
pad_lat.show(state, crc_errors);
pad_lon.show(state, crc_errors);
pad_alt.show(state, crc_errors);
public AltosPad() {
layout = new GridBagLayout();
- GridBagConstraints c;
-
- label_font = new Font("Dialog", Font.PLAIN, 24);
- value_font = new Font("Monospaced", Font.PLAIN, 24);
setLayout(layout);
- c = new GridBagConstraints();
/* Elements in pad display:
*
* Battery voltage
* Igniter continuity
- * GPS lock status and location
+ * GPS lock status
+ * GPS ready status
+ * GPS location
* Pad altitude
* RSSI
*/
battery = new Battery(layout, 0);
apogee = new Apogee(layout, 1);
main = new Main(layout, 2);
- gps = new GPS(layout, 3);
- pad_lat = new PadLat(layout, 4);
- pad_lon = new PadLon(layout, 5);
- pad_alt = new PadAlt(layout, 6);
+ gps_locked = new GPSLocked(layout, 3);
+ gps_ready = new GPSReady(layout, 4);
+ pad_lat = new PadLat(layout, 5);
+ pad_lon = new PadLon(layout, 6);
+ pad_alt = new PadAlt(layout, 7);
}
}
import java.text.*;
import java.lang.*;
-import altosui.Altos;
-
public class AltosParse {
static boolean isdigit(char c) {
return '0' <= c && c <= '9';
import java.util.*;
import java.text.*;
-import altosui.AltosRecord;
-
public class AltosReader {
public AltosRecord read() throws IOException, ParseException { return null; }
public void close() { }
import java.text.*;
import java.util.HashMap;
import java.io.*;
-import altosui.AltosConvert;
-import altosui.AltosGPS;
public class AltosRecord {
int version;
import java.util.prefs.*;
import java.util.concurrent.LinkedBlockingQueue;
-import altosui.AltosRecord;
-import altosui.AltosState;
-import altosui.AltosDeviceDialog;
-import altosui.AltosPreferences;
-import altosui.AltosLog;
-import altosui.AltosVoice;
-import altosui.AltosEepromMonitor;
-
public abstract class AltosRecordIterable implements Iterable<AltosRecord> {
public abstract Iterator<AltosRecord> iterator();
public void write_comments(PrintStream out) { }
package altosui;
import java.io.*;
-import altosui.AltosHexfile;
public class AltosRomconfig {
public boolean valid;
import java.text.*;
import java.util.prefs.*;
-import altosui.AltosRomconfig;
-
public class AltosRomconfigUI
extends JDialog
implements ActionListener
import java.lang.*;
import java.io.*;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.LinkedList;
-import java.util.Iterator;
-import altosui.AltosSerialMonitor;
-import altosui.AltosLine;
-import libaltosJNI.libaltos;
-import libaltosJNI.altos_device;
-import libaltosJNI.SWIGTYPE_p_altos_file;
-import libaltosJNI.SWIGTYPE_p_altos_list;
-import libaltosJNI.libaltosConstants;
+import java.util.concurrent.*;
+import java.util.*;
+
+import libaltosJNI.*;
/*
* This class reads from the serial port and places each received
public class AltosSerial implements Runnable {
+ static List<String> devices_opened = Collections.synchronizedList(new LinkedList<String>());
+
+ altos_device device;
SWIGTYPE_p_altos_file altos;
LinkedList<LinkedBlockingQueue<AltosLine>> monitors;
LinkedBlockingQueue<AltosLine> reply_queue;
set_monitor(false);
}
- public boolean opened() {
- return altos != null;
- }
-
public void close() {
if (altos != null) {
libaltos.altos_close(altos);
libaltos.altos_free(altos);
altos = null;
}
+ synchronized (devices_opened) {
+ devices_opened.remove(device.getPath());
+ }
}
public void putc(char c) {
print(String.format(format, arguments));
}
- public void open(altos_device device) throws FileNotFoundException {
+ private void open() throws FileNotFoundException, AltosSerialInUseException {
+ synchronized (devices_opened) {
+ if (devices_opened.contains(device.getPath()))
+ throw new AltosSerialInUseException(device);
+ devices_opened.add(device.getPath());
+ }
close();
altos = libaltos.altos_open(device);
if (altos == null)
}
}
- public AltosSerial() {
- altos = null;
- input_thread = null;
+ public AltosSerial(altos_device in_device) throws FileNotFoundException, AltosSerialInUseException {
+ device = in_device;
line = "";
monitor_mode = false;
monitors = new LinkedList<LinkedBlockingQueue<AltosLine>> ();
reply_queue = new LinkedBlockingQueue<AltosLine> ();
+ open();
}
}
--- /dev/null
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package altosui;
+
+import libaltosJNI.*;
+
+public class AltosSerialInUseException extends Exception {
+ public altos_device device;
+
+ public AltosSerialInUseException (altos_device in_device) {
+ device = in_device;
+ }
+}
package altosui;
-import altosui.AltosRecord;
-import altosui.AltosGPS;
-
public class AltosState {
AltosRecord data;
+++ /dev/null
-/*
- * Copyright © 2010 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-package altosui;
-
-import java.awt.*;
-import java.awt.event.*;
-import javax.swing.*;
-import javax.swing.filechooser.FileNameExtensionFilter;
-import javax.swing.table.*;
-import java.io.*;
-import java.util.*;
-import java.text.*;
-import java.util.prefs.*;
-import java.util.concurrent.LinkedBlockingQueue;
-
-import altosui.AltosFlightStatusTableModel;
-import altosui.AltosFlightInfoTableModel;
-
-public class AltosStatusTable extends JTable {
- private AltosFlightStatusTableModel flightStatusModel;
-
- private Font statusFont = new Font("SansSerif", Font.BOLD, 24);
-
- public AltosStatusTable() {
- super((TableModel) new AltosFlightStatusTableModel());
- flightStatusModel = (AltosFlightStatusTableModel) getModel();
-
- setFont(statusFont);
-
- TableColumnModel tcm = getColumnModel();
-
- for (int i = 0; i < flightStatusModel.getColumnCount(); i++) {
- DefaultTableCellRenderer r = new DefaultTableCellRenderer();
- r.setFont(statusFont);
- r.setHorizontalAlignment(SwingConstants.CENTER);
- tcm.getColumn(i).setCellRenderer(r);
- }
-
- setRowHeight(rowHeight());
- setShowGrid(false);
- }
-
- public int rowHeight() {
- FontMetrics statusMetrics = getFontMetrics(statusFont);
- return (statusMetrics.getHeight() + statusMetrics.getLeading()) * 15 / 10;
- }
-
- public int height() {
- return rowHeight * 4;
- }
-
- public void set(AltosState state) {
- flightStatusModel.set(state);
- }
-}
import java.lang.*;
import java.text.*;
import java.util.HashMap;
-import altosui.AltosConvert;
-import altosui.AltosRecord;
-import altosui.AltosGPS;
-import altosui.AltosCRCException;
/*
* Telemetry data contents
import java.io.*;
import java.util.*;
import java.text.*;
-import altosui.AltosTelemetry;
public class AltosTelemetryIterable extends AltosRecordIterable {
LinkedList<AltosRecord> records;
serial.set_callsign(callsign);
}
- public AltosTelemetryReader (AltosDevice in_device) throws FileNotFoundException, IOException {
+ public AltosTelemetryReader (AltosDevice in_device)
+ throws FileNotFoundException, AltosSerialInUseException, IOException {
device = in_device;
- serial = new AltosSerial();
+ serial = new AltosSerial(device);
log = new AltosLog(serial);
name = device.getPath();
telem = new LinkedBlockingQueue<AltosLine>();
serial.add_monitor(telem);
- serial.open(device);
}
}
import java.util.prefs.*;
import java.util.concurrent.LinkedBlockingQueue;
-import altosui.Altos;
-import altosui.AltosSerial;
-import altosui.AltosSerialMonitor;
-import altosui.AltosRecord;
-import altosui.AltosTelemetry;
-import altosui.AltosState;
-import altosui.AltosDeviceDialog;
-import altosui.AltosPreferences;
-import altosui.AltosLog;
-import altosui.AltosVoice;
-import altosui.AltosFlightInfoTableModel;
-import altosui.AltosFlashUI;
-import altosui.AltosLogfileChooser;
-import altosui.AltosCSVUI;
-import altosui.AltosLine;
-import altosui.AltosStatusTable;
-import altosui.AltosInfoTable;
-import altosui.AltosDisplayThread;
-
import libaltosJNI.*;
public class AltosUI extends JFrame {
device.getPath()),
"Cannot open target device",
JOptionPane.ERROR_MESSAGE);
+ } catch (AltosSerialInUseException si) {
+ JOptionPane.showMessageDialog(AltosUI.this,
+ String.format("Device \"%s\" already in use",
+ device.getPath()),
+ "Device in use",
+ JOptionPane.ERROR_MESSAGE);
} catch (IOException ee) {
JOptionPane.showMessageDialog(AltosUI.this,
device.getPath(),
}
});
- setTitle("AltOS");
+ b = addButton(0, 2, "Configure AltosUI");
+ b.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ ConfigureAltosUI();
+ }
+ });
+
+ b = addButton(1, 2, "Flash Image");
+ b.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ FlashImage();
+ }
+ });
- createMenu();
+ b = addButton(2, 2, "Quit");
+ b.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ System.exit(0);
+ }
+ });
+
+ setTitle("AltOS");
pane.doLayout();
pane.validate();
new AltosGraphUI(AltosUI.this);
}
- /* Create the AltosUI menus
- */
- private void createMenu() {
- JMenuBar menubar = new JMenuBar();
- JMenu menu;
- JMenuItem item;
- JRadioButtonMenuItem radioitem;
-
- // File menu
- {
- menu = new JMenu("File");
- menu.setMnemonic(KeyEvent.VK_F);
- menubar.add(menu);
-
- item = new JMenuItem("Flash Image",KeyEvent.VK_I);
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- FlashImage();
- }
- });
- menu.add(item);
-
- item = new JMenuItem("Export Data",KeyEvent.VK_E);
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- ExportData();
- }
- });
- menu.add(item);
-
- item = new JMenuItem("Graph Data",KeyEvent.VK_G);
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- GraphData();
- }
- });
- menu.add(item);
-
- item = new JMenuItem("Quit",KeyEvent.VK_Q);
- item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q,
- ActionEvent.CTRL_MASK));
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- System.out.printf("exiting\n");
- System.exit(0);
- }
- });
- menu.add(item);
- }
-
- // Device menu
- if (false) {
- menu = new JMenu("Device");
- menu.setMnemonic(KeyEvent.VK_D);
- menubar.add(menu);
-
- item = new JMenuItem("Connect to Device",KeyEvent.VK_C);
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- ConnectToDevice();
- }
- });
- menu.add(item);
-
- menu.addSeparator();
-
- item = new JMenuItem("Set Callsign",KeyEvent.VK_S);
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- ConfigureCallsign();
- }
- });
-
- menu.add(item);
-
- item = new JMenuItem("Configure TeleMetrum device",KeyEvent.VK_T);
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- ConfigureTeleMetrum();
- }
- });
-
- menu.add(item);
- }
- // Log menu
- {
- menu = new JMenu("Log");
- menu.setMnemonic(KeyEvent.VK_L);
- menubar.add(menu);
-
- item = new JMenuItem("New Log",KeyEvent.VK_N);
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- }
- });
- menu.add(item);
-
- item = new JMenuItem("Configure Log",KeyEvent.VK_C);
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- AltosPreferences.ConfigureLog();
- }
- });
- menu.add(item);
- }
- // Voice menu
- {
- menu = new JMenu("Voice", true);
- menu.setMnemonic(KeyEvent.VK_V);
- menubar.add(menu);
-
- radioitem = new JRadioButtonMenuItem("Enable Voice", AltosPreferences.voice());
- radioitem.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- JRadioButtonMenuItem item = (JRadioButtonMenuItem) e.getSource();
- boolean enabled = item.isSelected();
- AltosPreferences.set_voice(enabled);
- if (enabled)
- voice.speak_always("Enable voice.");
- else
- voice.speak_always("Disable voice.");
- }
- });
- menu.add(radioitem);
- item = new JMenuItem("Test Voice",KeyEvent.VK_T);
- item.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- voice.speak("That's one small step for man; one giant leap for mankind.");
- }
- });
- menu.add(item);
- }
- this.setJMenuBar(menubar);
+ private void ConfigureAltosUI() {
+ new AltosConfigureUI(AltosUI.this, voice);
}
static AltosRecordIterable open_logfile(String filename) {
public static void main(final String[] args) {
int process = 0;
/* Handle batch-mode */
- if (args.length == 2 && args[0].equals("--replay")) {
- String filename = args[1];
- FileInputStream in;
- try {
- in = new FileInputStream(filename);
- } catch (Exception e) {
- System.out.printf("Failed to open file '%s'\n", filename);
- return;
- }
- AltosRecordIterable recs;
- AltosReplayReader reader;
- if (filename.endsWith("eeprom")) {
- recs = new AltosEepromIterable(in);
- } else {
- recs = new AltosTelemetryIterable(in);
- }
- reader = new AltosReplayReader(recs.iterator(), filename);
- new AltosFlightUI(new AltosVoice(), reader);
- return;
- } else if (args.length > 0) {
+ if (args.length == 2 && args[0].equals("--replay")) {
+ String filename = args[1];
+ FileInputStream in;
+ try {
+ in = new FileInputStream(filename);
+ } catch (Exception e) {
+ System.out.printf("Failed to open file '%s'\n", filename);
+ return;
+ }
+ AltosRecordIterable recs;
+ AltosReplayReader reader;
+ if (filename.endsWith("eeprom")) {
+ recs = new AltosEepromIterable(in);
+ } else {
+ recs = new AltosTelemetryIterable(in);
+ }
+ reader = new AltosReplayReader(recs.iterator(), filename);
+ AltosFlightUI flight_ui = new AltosFlightUI(new AltosVoice(), reader);
+ flight_ui.set_exit_on_close();
+ return;
+ } else if (args.length > 0) {
for (int i = 0; i < args.length; i++) {
if (args[i].equals("--kml"))
process |= process_kml;
AltosChannelMenu.java \
AltosConfig.java \
AltosConfigUI.java \
+ AltosConfigureUI.java \
AltosConvert.java \
AltosCRCException.java \
AltosCSV.java \
AltosFlightDisplay.java \
AltosFlightInfoTableModel.java \
AltosFlightReader.java \
- AltosFlightStatusTableModel.java \
+ AltosFlightStatus.java \
AltosFlightUI.java \
AltosGPS.java \
AltosGreatCircle.java \
AltosRomconfig.java \
AltosRomconfigUI.java \
AltosSerial.java \
+ AltosSerialInUseException.java \
AltosSerialMonitor.java \
AltosSiteMap.java \
AltosState.java \
- AltosStatusTable.java \
AltosTelemetry.java \
AltosTelemetryIterable.java \
AltosUI.java \