2 * Copyright © 2010 Keith Packard <keithp@keithp.com>
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; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
22 import java.awt.event.*;
24 import javax.swing.event.*;
26 import org.altusmetrum.altoslib_14.*;
27 import org.altusmetrum.altosuilib_14.*;
29 public class AltosConfigFCUI
31 implements ActionListener, ItemListener, DocumentListener, AltosConfigValues, AltosUnitsListener
38 JLabel main_deploy_label;
39 JLabel apogee_delay_label;
40 JLabel apogee_lockout_label;
41 JLabel frequency_label;
42 JLabel radio_calibration_label;
43 JLabel radio_frequency_label;
44 JLabel radio_enable_label;
46 JLabel aprs_interval_label;
47 JLabel aprs_ssid_label;
48 JLabel aprs_format_label;
49 JLabel aprs_offset_label;
50 JLabel flight_log_max_label;
51 JLabel ignite_mode_label;
52 JLabel pad_orientation_label;
53 JLabel accel_plus_label;
54 JLabel accel_minus_label;
55 JLabel callsign_label;
57 JLabel tracker_motion_label;
58 JLabel tracker_interval_label;
66 JComboBox<String> main_deploy_value;
67 JComboBox<String> apogee_delay_value;
68 JComboBox<String> apogee_lockout_value;
69 AltosUIFreqList radio_frequency_value;
70 JLabel radio_calibration_value;
71 JRadioButton radio_enable_value;
72 AltosUIRateList rate_value;
73 JComboBox<String> aprs_interval_value;
74 JComboBox<Integer> aprs_ssid_value;
75 JComboBox<String> aprs_format_value;
76 JComboBox<Integer> aprs_offset_value;
77 JComboBox<String> flight_log_max_value;
78 JComboBox<String> ignite_mode_value;
79 JComboBox<String> pad_orientation_value;
80 JTextField accel_plus_value;
81 JTextField accel_minus_value;
82 JTextField callsign_value;
83 JComboBox<String> beep_value;
84 JComboBox<String> tracker_motion_value;
85 JComboBox<String> tracker_interval_value;
96 double pyro_firing_time;
98 ActionListener listener;
100 static String[] main_deploy_values_m = {
101 "100", "150", "200", "250", "300", "350",
105 static String[] main_deploy_values_ft = {
106 "250", "500", "750", "1000", "1250", "1500",
110 static String[] apogee_delay_values = {
111 "0", "1", "2", "3", "4", "5"
114 static String[] apogee_lockout_values = {
115 "0", "5", "10", "15", "20"
118 static String[] ignite_mode_values = {
124 static String[] aprs_interval_values = {
131 static Integer[] aprs_ssid_values = {
132 0, 1, 2 ,3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
135 static Integer[] aprs_offset_values = {
136 0, 2, 4, 6, 8, 10, 12, 14, 16, 18
139 static String[] beep_values = {
145 static String[] pad_orientation_values_none = {
148 static String[] pad_orientation_values_radio = {
153 static String[] pad_orientation_values_no_radio = {
158 static String[] pad_orientation_values_six_axis = {
167 String[] pad_orientation_values;
169 static String[] tracker_motion_values_m = {
176 static String[] tracker_motion_values_ft = {
183 static String[] tracker_interval_values = {
190 /* A window listener to catch closing events and tell the config code */
191 class ConfigListener extends WindowAdapter {
194 public ConfigListener(AltosConfigFCUI this_ui) {
198 public void windowClosing(WindowEvent e) {
199 ui.actionPerformed(new ActionEvent(e.getSource(),
200 ActionEvent.ACTION_PERFORMED,
205 boolean is_telemini_v1() {
206 String product = product_value.getText();
207 return product != null && product.startsWith("TeleMini-v1");
210 boolean is_telemini() {
211 String product = product_value.getText();
212 return product != null && product.startsWith("TeleMini");
215 boolean is_easymini() {
216 String product = product_value.getText();
217 return product != null && product.startsWith("EasyMini");
220 boolean is_telemetrum() {
221 String product = product_value.getText();
222 return product != null && product.startsWith("TeleMetrum");
225 boolean is_telemega() {
226 String product = product_value.getText();
227 return product != null && product.startsWith("TeleMega");
230 boolean is_easymega() {
231 String product = product_value.getText();
232 return product != null && product.startsWith("EasyMega");
235 boolean is_easytimer() {
236 String product = product_value.getText();
237 return product != null && product.startsWith("EasyTimer");
240 boolean has_radio() {
241 return is_telemega() || is_telemetrum() || is_telemini();
244 void set_radio_enable_tool_tip() {
245 if (radio_enable_value.isVisible())
246 radio_enable_value.setToolTipText("Enable/Disable telemetry and RDF transmissions");
248 radio_enable_value.setToolTipText("Firmware version does not support disabling radio");
251 void set_rate_tool_tip() {
252 if (rate_value.isVisible())
253 rate_value.setToolTipText("Select telemetry baud rate");
255 rate_value.setToolTipText("Firmware version does not support variable telemetry rates");
258 void set_aprs_interval_tool_tip() {
259 if (aprs_interval_value.isVisible())
260 aprs_interval_value.setToolTipText("Enable APRS and set the interval between APRS reports");
262 aprs_interval_value.setToolTipText("Hardware doesn't support APRS");
265 void set_aprs_ssid_tool_tip() {
266 if (aprs_ssid_value.isVisible())
267 aprs_ssid_value.setToolTipText("Set the APRS SSID (secondary station identifier)");
268 else if (aprs_ssid_value.isVisible())
269 aprs_ssid_value.setToolTipText("Software version doesn't support setting the APRS SSID");
271 aprs_ssid_value.setToolTipText("Hardware doesn't support APRS");
274 void set_aprs_format_tool_tip() {
275 if (aprs_format_value.isVisible())
276 aprs_format_value.setToolTipText("Set the APRS format (compressed/uncompressed)");
277 else if (aprs_format_value.isVisible())
278 aprs_format_value.setToolTipText("Software version doesn't support setting the APRS format");
280 aprs_format_value.setToolTipText("Hardware doesn't support APRS");
283 void set_aprs_offset_tool_tip() {
284 if (aprs_offset_value.isVisible())
285 aprs_offset_value.setToolTipText("Set the APRS offset from top of minute");
286 else if (aprs_offset_value.isVisible())
287 aprs_offset_value.setToolTipText("Software version doesn't support setting the APRS offset");
289 aprs_offset_value.setToolTipText("Hardware doesn't support APRS");
292 void set_flight_log_max_tool_tip() {
293 if (flight_log_max_value.isVisible())
294 flight_log_max_value.setToolTipText("Size reserved for each flight log (in kB)");
296 if (is_telemini_v1())
297 flight_log_max_value.setToolTipText("TeleMini-v1 stores only one flight");
299 flight_log_max_value.setToolTipText("Cannot set max value with flight logs in memory");
303 void set_ignite_mode_tool_tip() {
304 if (ignite_mode_value.isVisible())
305 ignite_mode_value.setToolTipText("Select when igniters will be fired");
307 ignite_mode_value.setToolTipText("Older firmware could not select ignite mode");
310 void set_pad_orientation_tool_tip() {
311 if (pad_orientation_value.isVisible()) {
312 pad_orientation_value.setToolTipText("How will the computer be mounted in the airframe");
315 pad_orientation_value.setToolTipText("Older TeleMetrum firmware must fly antenna forward");
316 else if (is_telemini() || is_easymini())
317 pad_orientation_value.setToolTipText("TeleMini and EasyMini don't care how they are mounted");
318 else if (is_easytimer())
319 pad_orientation_value.setToolTipText("EasyTimer can be mounted in any of six orientations");
321 pad_orientation_value.setToolTipText("Can't select orientation");
325 void set_accel_tool_tips() {
326 if (accel_plus_value.isVisible()) {
327 accel_plus_value.setToolTipText("Pad acceleration value in flight orientation");
328 accel_minus_value.setToolTipText("Upside-down acceleration value");
330 accel_plus_value.setToolTipText("No accelerometer");
331 accel_minus_value.setToolTipText("No accelerometer");
335 void set_beep_tool_tip() {
336 if (beep_value.isVisible())
337 beep_value.setToolTipText("What frequency the beeper will sound at");
339 beep_value.setToolTipText("Older firmware could not select beeper frequency");
342 /* Build the UI using a grid bag */
343 public AltosConfigFCUI(JFrame in_owner, boolean remote) {
344 super (in_owner, "Configure Flight Computer", false);
347 GridBagConstraints c;
350 Insets il = new Insets(4,4,4,4);
351 Insets ir = new Insets(4,4,4,4);
353 pane = getContentPane();
354 pane.setLayout(new GridBagLayout());
357 c = new GridBagConstraints();
358 c.gridx = 0; c.gridy = row;
360 c.fill = GridBagConstraints.NONE;
361 c.anchor = GridBagConstraints.LINE_START;
363 product_label = new JLabel("Product:");
364 pane.add(product_label, c);
366 c = new GridBagConstraints();
367 c.gridx = 4; c.gridy = row;
369 c.fill = GridBagConstraints.HORIZONTAL;
371 c.anchor = GridBagConstraints.LINE_START;
373 product_value = new JLabel("");
374 pane.add(product_value, c);
378 c = new GridBagConstraints();
379 c.gridx = 0; c.gridy = row;
381 c.fill = GridBagConstraints.NONE;
382 c.anchor = GridBagConstraints.LINE_START;
385 version_label = new JLabel("Software version:");
386 pane.add(version_label, c);
388 c = new GridBagConstraints();
389 c.gridx = 4; c.gridy = row;
391 c.fill = GridBagConstraints.HORIZONTAL;
393 c.anchor = GridBagConstraints.LINE_START;
396 version_value = new JLabel("");
397 pane.add(version_value, c);
401 c = new GridBagConstraints();
402 c.gridx = 0; c.gridy = row;
404 c.fill = GridBagConstraints.NONE;
405 c.anchor = GridBagConstraints.LINE_START;
408 serial_label = new JLabel("Serial:");
409 pane.add(serial_label, c);
411 c = new GridBagConstraints();
412 c.gridx = 4; c.gridy = row;
414 c.fill = GridBagConstraints.HORIZONTAL;
416 c.anchor = GridBagConstraints.LINE_START;
419 serial_value = new JLabel("");
420 pane.add(serial_value, c);
424 c = new GridBagConstraints();
425 c.gridx = 0; c.gridy = row;
427 c.fill = GridBagConstraints.NONE;
428 c.anchor = GridBagConstraints.LINE_START;
431 main_deploy_label = new JLabel(get_main_deploy_label());
432 pane.add(main_deploy_label, c);
434 c = new GridBagConstraints();
435 c.gridx = 4; c.gridy = row;
437 c.fill = GridBagConstraints.HORIZONTAL;
439 c.anchor = GridBagConstraints.LINE_START;
442 main_deploy_value = new JComboBox<String>(main_deploy_values());
443 main_deploy_value.setEditable(true);
444 main_deploy_value.addItemListener(this);
445 pane.add(main_deploy_value, c);
446 main_deploy_value.setToolTipText("Height above pad altitude to fire main charge");
450 c = new GridBagConstraints();
451 c.gridx = 0; c.gridy = row;
453 c.fill = GridBagConstraints.NONE;
454 c.anchor = GridBagConstraints.LINE_START;
457 apogee_delay_label = new JLabel("Apogee Delay(s):");
458 pane.add(apogee_delay_label, c);
460 c = new GridBagConstraints();
461 c.gridx = 4; c.gridy = row;
463 c.fill = GridBagConstraints.HORIZONTAL;
465 c.anchor = GridBagConstraints.LINE_START;
468 apogee_delay_value = new JComboBox<String>(apogee_delay_values);
469 apogee_delay_value.setEditable(true);
470 apogee_delay_value.addItemListener(this);
471 pane.add(apogee_delay_value, c);
472 apogee_delay_value.setToolTipText("Delay after apogee before charge fires");
476 c = new GridBagConstraints();
477 c.gridx = 0; c.gridy = row;
479 c.fill = GridBagConstraints.NONE;
480 c.anchor = GridBagConstraints.LINE_START;
483 apogee_lockout_label = new JLabel("Apogee Lockout(s):");
484 pane.add(apogee_lockout_label, c);
486 c = new GridBagConstraints();
487 c.gridx = 4; c.gridy = row;
489 c.fill = GridBagConstraints.HORIZONTAL;
491 c.anchor = GridBagConstraints.LINE_START;
494 apogee_lockout_value = new JComboBox<String>(apogee_lockout_values);
495 apogee_lockout_value.setEditable(true);
496 apogee_lockout_value.addItemListener(this);
497 pane.add(apogee_lockout_value, c);
498 apogee_lockout_value.setToolTipText("Time after launch while apogee detection is locked out");
502 c = new GridBagConstraints();
503 c.gridx = 0; c.gridy = row;
505 c.fill = GridBagConstraints.NONE;
506 c.anchor = GridBagConstraints.LINE_START;
509 radio_frequency_label = new JLabel("Frequency:");
510 pane.add(radio_frequency_label, c);
512 c = new GridBagConstraints();
513 c.gridx = 4; c.gridy = row;
515 c.fill = GridBagConstraints.HORIZONTAL;
517 c.anchor = GridBagConstraints.LINE_START;
520 radio_frequency_value = new AltosUIFreqList();
521 radio_frequency_value.addItemListener(this);
522 pane.add(radio_frequency_value, c);
523 radio_frequency_value.setToolTipText("Telemetry, RDF and packet frequency");
526 /* Radio Calibration */
527 c = new GridBagConstraints();
528 c.gridx = 0; c.gridy = row;
530 c.fill = GridBagConstraints.NONE;
531 c.anchor = GridBagConstraints.LINE_START;
534 radio_calibration_label = new JLabel("RF Calibration:");
535 pane.add(radio_calibration_label, c);
537 c = new GridBagConstraints();
538 c.gridx = 4; c.gridy = row;
540 c.fill = GridBagConstraints.HORIZONTAL;
542 c.anchor = GridBagConstraints.LINE_START;
545 radio_calibration_value = new JLabel(String.format("%d", 1186611));
546 pane.add(radio_calibration_value, c);
550 c = new GridBagConstraints();
551 c.gridx = 0; c.gridy = row;
553 c.fill = GridBagConstraints.NONE;
554 c.anchor = GridBagConstraints.LINE_START;
557 radio_enable_label = new JLabel("Telemetry/RDF/APRS Enable:");
558 pane.add(radio_enable_label, c);
560 c = new GridBagConstraints();
561 c.gridx = 4; c.gridy = row;
563 c.fill = GridBagConstraints.HORIZONTAL;
565 c.anchor = GridBagConstraints.LINE_START;
568 radio_enable_value = new JRadioButton("Enabled");
569 radio_enable_value.addItemListener(this);
570 pane.add(radio_enable_value, c);
571 set_radio_enable_tool_tip();
575 c = new GridBagConstraints();
576 c.gridx = 0; c.gridy = row;
578 c.fill = GridBagConstraints.NONE;
579 c.anchor = GridBagConstraints.LINE_START;
582 rate_label = new JLabel("Telemetry baud rate:");
583 pane.add(rate_label, c);
585 c = new GridBagConstraints();
586 c.gridx = 4; c.gridy = row;
588 c.fill = GridBagConstraints.HORIZONTAL;
590 c.anchor = GridBagConstraints.LINE_START;
593 rate_value = new AltosUIRateList();
594 rate_value.addItemListener(this);
595 pane.add(rate_value, c);
600 c = new GridBagConstraints();
601 c.gridx = 0; c.gridy = row;
603 c.fill = GridBagConstraints.NONE;
604 c.anchor = GridBagConstraints.LINE_START;
607 aprs_interval_label = new JLabel("APRS Interval(s):");
608 pane.add(aprs_interval_label, c);
610 c = new GridBagConstraints();
611 c.gridx = 4; c.gridy = row;
613 c.fill = GridBagConstraints.HORIZONTAL;
615 c.anchor = GridBagConstraints.LINE_START;
618 aprs_interval_value = new JComboBox<String>(aprs_interval_values);
619 aprs_interval_value.setEditable(true);
620 aprs_interval_value.addItemListener(this);
621 pane.add(aprs_interval_value, c);
622 set_aprs_interval_tool_tip();
626 c = new GridBagConstraints();
627 c.gridx = 0; c.gridy = row;
629 c.fill = GridBagConstraints.NONE;
630 c.anchor = GridBagConstraints.LINE_START;
633 aprs_ssid_label = new JLabel("APRS SSID:");
634 pane.add(aprs_ssid_label, c);
636 c = new GridBagConstraints();
637 c.gridx = 4; c.gridy = row;
639 c.fill = GridBagConstraints.HORIZONTAL;
641 c.anchor = GridBagConstraints.LINE_START;
644 aprs_ssid_value = new JComboBox<Integer>(aprs_ssid_values);
645 aprs_ssid_value.setEditable(false);
646 aprs_ssid_value.addItemListener(this);
647 aprs_ssid_value.setMaximumRowCount(aprs_ssid_values.length);
648 pane.add(aprs_ssid_value, c);
649 set_aprs_ssid_tool_tip();
653 c = new GridBagConstraints();
654 c.gridx = 0; c.gridy = row;
656 c.fill = GridBagConstraints.NONE;
657 c.anchor = GridBagConstraints.LINE_START;
660 aprs_format_label = new JLabel("APRS format:");
661 pane.add(aprs_format_label, c);
663 c = new GridBagConstraints();
664 c.gridx = 4; c.gridy = row;
666 c.fill = GridBagConstraints.HORIZONTAL;
668 c.anchor = GridBagConstraints.LINE_START;
671 aprs_format_value = new JComboBox<String>(AltosLib.ao_aprs_format_name);
672 aprs_format_value.setEditable(false);
673 aprs_format_value.addItemListener(this);
674 aprs_format_value.setMaximumRowCount(AltosLib.ao_aprs_format_name.length);
675 pane.add(aprs_format_value, c);
676 set_aprs_format_tool_tip();
680 c = new GridBagConstraints();
681 c.gridx = 0; c.gridy = row;
683 c.fill = GridBagConstraints.NONE;
684 c.anchor = GridBagConstraints.LINE_START;
687 aprs_offset_label = new JLabel("APRS offset:");
688 pane.add(aprs_offset_label, c);
690 c = new GridBagConstraints();
691 c.gridx = 4; c.gridy = row;
693 c.fill = GridBagConstraints.HORIZONTAL;
695 c.anchor = GridBagConstraints.LINE_START;
698 aprs_offset_value = new JComboBox<Integer>(aprs_offset_values);
699 aprs_offset_value.setEditable(false);
700 aprs_offset_value.addItemListener(this);
701 aprs_offset_value.setMaximumRowCount(aprs_offset_values.length);
702 pane.add(aprs_offset_value, c);
703 set_aprs_offset_tool_tip();
707 c = new GridBagConstraints();
708 c.gridx = 0; c.gridy = row;
710 c.fill = GridBagConstraints.NONE;
711 c.anchor = GridBagConstraints.LINE_START;
714 callsign_label = new JLabel("Callsign:");
715 pane.add(callsign_label, c);
717 c = new GridBagConstraints();
718 c.gridx = 4; c.gridy = row;
720 c.fill = GridBagConstraints.HORIZONTAL;
722 c.anchor = GridBagConstraints.LINE_START;
725 callsign_value = new JTextField(AltosUIPreferences.callsign());
726 callsign_value.getDocument().addDocumentListener(this);
727 pane.add(callsign_value, c);
728 callsign_value.setToolTipText("Callsign reported in telemetry data");
732 c = new GridBagConstraints();
733 c.gridx = 0; c.gridy = row;
735 c.fill = GridBagConstraints.NONE;
736 c.anchor = GridBagConstraints.LINE_START;
739 flight_log_max_label = new JLabel("Maximum Flight Log Size (kB):");
740 pane.add(flight_log_max_label, c);
742 c = new GridBagConstraints();
743 c.gridx = 4; c.gridy = row;
745 c.fill = GridBagConstraints.HORIZONTAL;
747 c.anchor = GridBagConstraints.LINE_START;
750 flight_log_max_value = new JComboBox<String>();
751 flight_log_max_value.setEditable(true);
752 flight_log_max_value.addItemListener(this);
753 pane.add(flight_log_max_value, c);
754 set_flight_log_max_tool_tip();
758 c = new GridBagConstraints();
759 c.gridx = 0; c.gridy = row;
761 c.fill = GridBagConstraints.NONE;
762 c.anchor = GridBagConstraints.LINE_START;
765 ignite_mode_label = new JLabel("Igniter Firing Mode:");
766 pane.add(ignite_mode_label, c);
768 c = new GridBagConstraints();
769 c.gridx = 4; c.gridy = row;
771 c.fill = GridBagConstraints.HORIZONTAL;
773 c.anchor = GridBagConstraints.LINE_START;
776 ignite_mode_value = new JComboBox<String>(ignite_mode_values);
777 ignite_mode_value.setEditable(false);
778 ignite_mode_value.addItemListener(this);
779 pane.add(ignite_mode_value, c);
780 set_ignite_mode_tool_tip();
783 /* Pad orientation */
784 c = new GridBagConstraints();
785 c.gridx = 0; c.gridy = row;
787 c.fill = GridBagConstraints.NONE;
788 c.anchor = GridBagConstraints.LINE_START;
791 pad_orientation_label = new JLabel("Pad Orientation:");
792 pane.add(pad_orientation_label, c);
794 c = new GridBagConstraints();
795 c.gridx = 4; c.gridy = row;
797 c.fill = GridBagConstraints.HORIZONTAL;
799 c.anchor = GridBagConstraints.LINE_START;
803 pad_orientation_value = new JComboBox<String>();
804 pad_orientation_value.setEditable(false);
805 pad_orientation_value.addItemListener(this);
806 pane.add(pad_orientation_value, c);
807 set_pad_orientation_tool_tip();
811 c = new GridBagConstraints();
812 c.gridx = 0; c.gridy = row;
814 c.fill = GridBagConstraints.NONE;
815 c.anchor = GridBagConstraints.LINE_START;
818 accel_plus_label = new JLabel("Accel Plus:");
819 pane.add(accel_plus_label, c);
821 c = new GridBagConstraints();
822 c.gridx = 4; c.gridy = row;
824 c.fill = GridBagConstraints.HORIZONTAL;
826 c.anchor = GridBagConstraints.LINE_START;
829 accel_plus_value = new JTextField(10);
830 accel_plus_value.setEditable(true);
831 accel_plus_value.getDocument().addDocumentListener(this);
832 pane.add(accel_plus_value, c);
836 c = new GridBagConstraints();
837 c.gridx = 0; c.gridy = row;
839 c.fill = GridBagConstraints.NONE;
840 c.anchor = GridBagConstraints.LINE_START;
843 accel_minus_label = new JLabel("Accel Minus:");
844 pane.add(accel_minus_label, c);
846 c = new GridBagConstraints();
847 c.gridx = 4; c.gridy = row;
849 c.fill = GridBagConstraints.HORIZONTAL;
851 c.anchor = GridBagConstraints.LINE_START;
854 accel_minus_value = new JTextField(10);
855 accel_minus_value.setEditable(true);
856 accel_minus_value.getDocument().addDocumentListener(this);
857 pane.add(accel_minus_value, c);
859 set_accel_tool_tips();
862 c = new GridBagConstraints();
863 c.gridx = 0; c.gridy = row;
865 c.fill = GridBagConstraints.NONE;
866 c.anchor = GridBagConstraints.LINE_START;
869 beep_label = new JLabel("Beeper Frequency:");
870 pane.add(beep_label, c);
872 c = new GridBagConstraints();
873 c.gridx = 4; c.gridy = row;
875 c.fill = GridBagConstraints.HORIZONTAL;
877 c.anchor = GridBagConstraints.LINE_START;
880 beep_value = new JComboBox<String>(beep_values);
881 beep_value.setEditable(true);
882 beep_value.addItemListener(this);
883 pane.add(beep_value, c);
887 /* Tracker triger horiz distances */
888 c = new GridBagConstraints();
889 c.gridx = 0; c.gridy = row;
891 c.fill = GridBagConstraints.NONE;
892 c.anchor = GridBagConstraints.LINE_START;
895 tracker_motion_label = new JLabel(get_tracker_motion_label());
896 pane.add(tracker_motion_label, c);
898 c = new GridBagConstraints();
899 c.gridx = 4; c.gridy = row;
901 c.fill = GridBagConstraints.HORIZONTAL;
903 c.anchor = GridBagConstraints.LINE_START;
906 tracker_motion_value = new JComboBox<String>(tracker_motion_values());
907 tracker_motion_value.setEditable(true);
908 tracker_motion_value.addItemListener(this);
909 pane.add(tracker_motion_value, c);
912 /* Tracker triger vert distances */
913 c = new GridBagConstraints();
914 c.gridx = 0; c.gridy = row;
916 c.fill = GridBagConstraints.NONE;
917 c.anchor = GridBagConstraints.LINE_START;
920 tracker_interval_label = new JLabel("Position Reporting Interval(s):");
921 pane.add(tracker_interval_label, c);
923 c = new GridBagConstraints();
924 c.gridx = 4; c.gridy = row;
926 c.fill = GridBagConstraints.HORIZONTAL;
928 c.anchor = GridBagConstraints.LINE_START;
931 tracker_interval_value = new JComboBox<String>(tracker_interval_values);
932 tracker_interval_value.setEditable(true);
933 tracker_interval_value.addItemListener(this);
934 pane.add(tracker_interval_value, c);
935 set_tracker_tool_tip();
939 c = new GridBagConstraints();
940 c.gridx = 4; c.gridy = row;
942 c.fill = GridBagConstraints.HORIZONTAL;
943 c.anchor = GridBagConstraints.LINE_START;
946 pyro = new JButton("Configure Pyro Channels");
948 pyro.addActionListener(this);
949 pyro.setActionCommand("Pyro");
953 c = new GridBagConstraints();
954 c.gridx = 5; c.gridy = row;
956 c.fill = GridBagConstraints.HORIZONTAL;
957 c.anchor = GridBagConstraints.LINE_START;
960 accel_cal = new JButton("Calibrate Accelerometer");
961 pane.add(accel_cal, c);
962 accel_cal.addActionListener(this);
963 accel_cal.setActionCommand("Accel");
967 c = new GridBagConstraints();
968 c.gridx = 0; c.gridy = row;
970 c.fill = GridBagConstraints.NONE;
971 c.anchor = GridBagConstraints.LINE_START;
973 save = new JButton("Save");
975 save.addActionListener(this);
976 save.setActionCommand("Save");
978 c = new GridBagConstraints();
979 c.gridx = 2; c.gridy = row;
981 c.fill = GridBagConstraints.NONE;
982 c.anchor = GridBagConstraints.CENTER;
984 reset = new JButton("Reset");
986 reset.addActionListener(this);
987 reset.setActionCommand("Reset");
989 c = new GridBagConstraints();
990 c.gridx = 4; c.gridy = row;
992 c.fill = GridBagConstraints.NONE;
993 c.anchor = GridBagConstraints.CENTER;
995 reboot = new JButton("Reboot");
997 reboot.addActionListener(this);
998 reboot.setActionCommand("Reboot");
1000 c = new GridBagConstraints();
1001 c.gridx = 6; c.gridy = row;
1003 c.fill = GridBagConstraints.NONE;
1004 c.anchor = GridBagConstraints.LINE_END;
1006 close = new JButton("Close");
1008 close.addActionListener(this);
1009 close.setActionCommand("Close");
1011 addWindowListener(new ConfigListener(this));
1012 AltosPreferences.register_units_listener(this);
1015 /* Once the initial values are set, the config code will show the dialog */
1016 public void make_visible() {
1018 setLocationRelativeTo(owner);
1022 /* If any values have been changed, confirm before closing */
1023 public boolean check_dirty(String operation) {
1025 Object[] options = { String.format("%s anyway", operation), "Keep editing" };
1027 i = JOptionPane.showOptionDialog(this,
1028 String.format("Configuration modified. %s anyway?", operation),
1029 "Configuration Modified",
1030 JOptionPane.DEFAULT_OPTION,
1031 JOptionPane.WARNING_MESSAGE,
1032 null, options, options[1]);
1039 public void set_dirty() {
1041 save.setEnabled(true);
1044 public void set_clean() {
1046 save.setEnabled(false);
1049 AltosConfigPyroUI pyro_ui;
1051 public void dispose() {
1052 if (pyro_ui != null)
1054 AltosPreferences.unregister_units_listener(this);
1058 /* Listen for events from our buttons */
1059 public void actionPerformed(ActionEvent e) {
1060 String cmd = e.getActionCommand();
1062 if (cmd.equals("Pyro")) {
1063 if (pyro_ui == null && pyros != null)
1064 pyro_ui = new AltosConfigPyroUI(this, pyros, pyro_firing_time);
1065 if (pyro_ui != null)
1066 pyro_ui.make_visible();
1070 if (cmd.equals("Close") || cmd.equals("Reboot"))
1071 if (!check_dirty(cmd))
1073 listener.actionPerformed(e);
1074 if (cmd.equals("Close") || cmd.equals("Reboot")) {
1078 if (cmd.equals("Save") || cmd.equals("Reset"))
1082 /* ItemListener interface method */
1083 public void itemStateChanged(ItemEvent e) {
1087 /* DocumentListener interface methods */
1088 public void changedUpdate(DocumentEvent e) {
1092 public void insertUpdate(DocumentEvent e) {
1096 public void removeUpdate(DocumentEvent e) {
1100 /* Let the config code hook on a listener */
1101 public void addActionListener(ActionListener l) {
1105 void set_pad_orientation_values()
1108 pad_orientation_values = pad_orientation_values_radio;
1109 else if (is_easytimer())
1110 pad_orientation_values = pad_orientation_values_six_axis;
1112 pad_orientation_values = pad_orientation_values_no_radio;
1113 pad_orientation_value.removeAllItems();
1114 for (String s : pad_orientation_values)
1115 pad_orientation_value.addItem(s);
1116 set_pad_orientation_tool_tip();
1119 /* set and get all of the dialog values */
1120 public void set_product(String product) {
1121 radio_frequency_value.set_product(product);
1122 product_value.setText(product);
1123 set_accel_tool_tips();
1124 set_flight_log_max_tool_tip();
1125 set_pad_orientation_values();
1128 public void set_version(String version) {
1129 version_value.setText(version);
1132 public void set_serial(int serial) {
1133 radio_frequency_value.set_serial(serial);
1134 serial_value.setText(String.format("%d", serial));
1137 public void set_altitude_32(int altitude_32) {
1140 public void set_main_deploy(int new_main_deploy) {
1141 if (new_main_deploy != AltosLib.MISSING)
1142 main_deploy_value.setSelectedItem(AltosConvert.height.say(new_main_deploy));
1143 main_deploy_value.setVisible(new_main_deploy != AltosLib.MISSING);
1144 main_deploy_label.setVisible(new_main_deploy != AltosLib.MISSING);
1147 public int main_deploy() throws AltosConfigDataException {
1148 String str = main_deploy_value.getSelectedItem().toString();
1150 return (int) (AltosConvert.height.parse_locale(str) + 0.5);
1151 } catch (ParseException pe) {
1152 throw new AltosConfigDataException("invalid main deploy height %s", str);
1156 String get_main_deploy_label() {
1157 return String.format("Main Deploy Altitude(%s):", AltosConvert.height.parse_units());
1160 String[] main_deploy_values() {
1161 if (AltosConvert.imperial_units)
1162 return main_deploy_values_ft;
1164 return main_deploy_values_m;
1167 void set_main_deploy_values() {
1168 String[] v = main_deploy_values();
1169 while (main_deploy_value.getItemCount() > 0)
1170 main_deploy_value.removeItemAt(0);
1171 for (int i = 0; i < v.length; i++)
1172 main_deploy_value.addItem(v[i]);
1173 main_deploy_value.setMaximumRowCount(v.length);
1176 public void units_changed(boolean imperial_units) {
1177 boolean was_dirty = dirty;
1179 String v = main_deploy_value.getSelectedItem().toString();
1180 main_deploy_label.setText(get_main_deploy_label());
1181 set_main_deploy_values();
1183 int m = (int) (AltosConvert.height.parse_locale(v, !imperial_units) + 0.5);
1185 } catch (ParseException pe) {
1188 if (tracker_motion_value.isVisible()) {
1189 String motion = tracker_motion_value.getSelectedItem().toString();
1190 tracker_motion_label.setText(get_tracker_motion_label());
1191 set_tracker_motion_values();
1193 int m = (int) (AltosConvert.height.parse_locale(motion, !imperial_units) + 0.5);
1194 set_tracker_motion(m);
1195 } catch (ParseException pe) {
1203 public void set_apogee_delay(int new_apogee_delay) {
1204 if (new_apogee_delay != AltosLib.MISSING)
1205 apogee_delay_value.setSelectedItem(Integer.toString(new_apogee_delay));
1206 apogee_delay_value.setVisible(new_apogee_delay != AltosLib.MISSING);
1207 apogee_delay_label.setVisible(new_apogee_delay != AltosLib.MISSING);
1210 private int parse_int(String name, String s, boolean split) throws AltosConfigDataException {
1213 v = s.split("\\s+")[0];
1215 return Integer.parseInt(v);
1216 } catch (NumberFormatException ne) {
1217 throw new AltosConfigDataException("Invalid %s \"%s\"", name, s);
1221 public int apogee_delay() throws AltosConfigDataException {
1222 return parse_int("apogee delay", apogee_delay_value.getSelectedItem().toString(), false);
1225 public void set_apogee_lockout(int new_apogee_lockout) {
1226 if (new_apogee_lockout != AltosLib.MISSING)
1227 apogee_lockout_value.setSelectedItem(Integer.toString(new_apogee_lockout));
1229 apogee_lockout_value.setVisible(new_apogee_lockout != AltosLib.MISSING);
1230 apogee_lockout_label.setVisible(new_apogee_lockout != AltosLib.MISSING);
1233 public int apogee_lockout() throws AltosConfigDataException {
1234 return parse_int("apogee lockout", apogee_lockout_value.getSelectedItem().toString(), false);
1237 public void set_radio_frequency(double new_radio_frequency) {
1238 if (new_radio_frequency != AltosLib.MISSING)
1239 radio_frequency_value.set_frequency(new_radio_frequency);
1240 radio_frequency_label.setVisible(new_radio_frequency != AltosLib.MISSING);
1241 radio_frequency_value.setVisible(new_radio_frequency != AltosLib.MISSING);
1244 public double radio_frequency() {
1245 return radio_frequency_value.frequency();
1248 public void set_radio_calibration(int new_radio_calibration) {
1249 if (new_radio_calibration != AltosLib.MISSING)
1250 radio_calibration_value.setText(String.format("%d", new_radio_calibration));
1251 radio_calibration_value.setVisible(new_radio_calibration != AltosLib.MISSING);
1252 radio_calibration_label.setVisible(new_radio_calibration != AltosLib.MISSING);
1255 public void set_radio_enable(int new_radio_enable) {
1256 if (new_radio_enable != AltosLib.MISSING)
1257 radio_enable_value.setSelected(new_radio_enable != 0);
1258 radio_enable_label.setVisible(new_radio_enable != AltosLib.MISSING);
1259 radio_enable_value.setVisible(new_radio_enable != AltosLib.MISSING);
1260 set_radio_enable_tool_tip();
1263 public int radio_enable() {
1264 if (radio_enable_value.isVisible())
1265 return radio_enable_value.isSelected() ? 1 : 0;
1267 return AltosLib.MISSING;
1270 public void set_telemetry_rate(int new_rate) {
1271 if (new_rate != AltosLib.MISSING)
1272 rate_value.set_rate(new_rate);
1273 rate_label.setVisible(new_rate != AltosLib.MISSING);
1274 rate_value.setVisible(new_rate != AltosLib.MISSING);
1275 set_rate_tool_tip();
1278 public int telemetry_rate() {
1279 return rate_value.rate();
1282 public void set_callsign(String new_callsign) {
1283 if (new_callsign != null)
1284 callsign_value.setText(new_callsign);
1285 callsign_value.setVisible(new_callsign != null);
1286 callsign_label.setVisible(new_callsign != null);
1289 public String callsign() {
1290 if (callsign_value.isVisible())
1291 return callsign_value.getText();
1295 int flight_log_max_limit;
1298 public String flight_log_max_label(int flight_log_max) {
1299 if (flight_log_max_limit != 0) {
1300 int nflight = flight_log_max_limit / flight_log_max;
1301 String plural = nflight > 1 ? "s" : "";
1303 return String.format("%d (%d flight%s)", flight_log_max, nflight, plural);
1305 return String.format("%d", flight_log_max);
1308 public void set_flight_log_max(int new_flight_log_max) {
1309 if (new_flight_log_max != AltosLib.MISSING) {
1310 flight_log_max_value.setSelectedItem(flight_log_max_label(new_flight_log_max));
1311 flight_log_max = new_flight_log_max;
1313 flight_log_max_value.setVisible(new_flight_log_max != AltosLib.MISSING);
1314 flight_log_max_label.setVisible(new_flight_log_max != AltosLib.MISSING);
1315 set_flight_log_max_tool_tip();
1318 public void set_flight_log_max_enabled(boolean enable) {
1319 flight_log_max_value.setEnabled(enable);
1320 set_flight_log_max_tool_tip();
1323 public int flight_log_max() throws AltosConfigDataException {
1324 if (flight_log_max_value.isVisible())
1325 return parse_int("flight log max", flight_log_max_value.getSelectedItem().toString(), true);
1326 return AltosLib.MISSING;
1329 public void set_flight_log_max_limit(int new_flight_log_max_limit, int new_storage_erase_unit) {
1330 flight_log_max_limit = new_flight_log_max_limit;
1331 if (new_flight_log_max_limit != AltosLib.MISSING) {
1332 flight_log_max_value.removeAllItems();
1333 for (int i = 8; i >= 1; i--) {
1334 int size = flight_log_max_limit / i;
1335 if (new_storage_erase_unit != 0)
1336 size &= ~(new_storage_erase_unit - 1);
1337 flight_log_max_value.addItem(String.format("%d (%d flights)", size, i));
1340 if (flight_log_max != 0 && flight_log_max != AltosLib.MISSING)
1341 set_flight_log_max(flight_log_max);
1344 public void set_ignite_mode(int new_ignite_mode) {
1345 if (new_ignite_mode != AltosLib.MISSING) {
1346 if (new_ignite_mode >= ignite_mode_values.length)
1347 new_ignite_mode = 0;
1348 if (new_ignite_mode < 0) {
1349 ignite_mode_value.setEnabled(false);
1350 new_ignite_mode = 0;
1352 ignite_mode_value.setEnabled(true);
1354 ignite_mode_value.setSelectedIndex(new_ignite_mode);
1356 ignite_mode_value.setVisible(new_ignite_mode != AltosLib.MISSING);
1357 ignite_mode_label.setVisible(new_ignite_mode != AltosLib.MISSING);
1359 set_ignite_mode_tool_tip();
1362 public int ignite_mode() {
1363 if (ignite_mode_value.isVisible())
1364 return ignite_mode_value.getSelectedIndex();
1366 return AltosLib.MISSING;
1370 public void set_pad_orientation(int new_pad_orientation) {
1371 if (new_pad_orientation != AltosLib.MISSING) {
1372 if (new_pad_orientation >= pad_orientation_values.length)
1373 new_pad_orientation = 0;
1374 if (new_pad_orientation < 0)
1375 new_pad_orientation = 0;
1376 pad_orientation_value.setSelectedIndex(new_pad_orientation);
1378 pad_orientation_value.setVisible(new_pad_orientation != AltosLib.MISSING);
1379 pad_orientation_label.setVisible(new_pad_orientation != AltosLib.MISSING);
1380 accel_cal.setVisible(new_pad_orientation != AltosLib.MISSING);
1382 set_pad_orientation_tool_tip();
1385 public int pad_orientation() {
1386 if (pad_orientation_value.isVisible())
1387 return pad_orientation_value.getSelectedIndex();
1389 return AltosLib.MISSING;
1392 public void set_accel_cal(int accel_plus, int accel_minus) {
1393 if (accel_plus != AltosLib.MISSING) {
1394 accel_plus_value.setText(String.format("%d", accel_plus));
1395 accel_minus_value.setText(String.format("%d", accel_minus));
1397 accel_plus_value.setVisible(accel_plus != AltosLib.MISSING);
1398 accel_plus_label.setVisible(accel_plus != AltosLib.MISSING);
1399 accel_minus_value.setVisible(accel_minus != AltosLib.MISSING);
1400 accel_minus_label.setVisible(accel_minus != AltosLib.MISSING);
1402 set_accel_tool_tips();
1405 public int accel_cal_plus() {
1406 if (accel_plus_value.isVisible())
1407 return Integer.parseInt(accel_plus_value.getText());
1408 return AltosLib.MISSING;
1411 public int accel_cal_minus() {
1412 if (accel_minus_value.isVisible())
1413 return Integer.parseInt(accel_minus_value.getText());
1414 return AltosLib.MISSING;
1417 public void set_beep(int new_beep) {
1418 if (new_beep != AltosLib.MISSING) {
1419 int new_freq = (int) Math.floor (AltosConvert.beep_value_to_freq(new_beep) + 0.5);
1420 for (int i = 0; i < beep_values.length; i++)
1421 if (new_beep == AltosConvert.beep_freq_to_value(Integer.parseInt(beep_values[i]))) {
1422 beep_value.setSelectedIndex(i);
1423 set_beep_tool_tip();
1426 beep_value.setSelectedItem(String.format("%d", new_freq));
1428 beep_value.setVisible(new_beep != AltosLib.MISSING);
1429 beep_label.setVisible(new_beep != AltosLib.MISSING);
1430 set_beep_tool_tip();
1434 if (beep_value.isVisible())
1435 return AltosConvert.beep_freq_to_value(Integer.parseInt(beep_value.getSelectedItem().toString()));
1437 return AltosLib.MISSING;
1440 String[] tracker_motion_values() {
1441 if (AltosConvert.imperial_units)
1442 return tracker_motion_values_ft;
1444 return tracker_motion_values_m;
1447 void set_tracker_motion_values() {
1448 String[] v = tracker_motion_values();
1449 while (tracker_motion_value.getItemCount() > 0)
1450 tracker_motion_value.removeItemAt(0);
1451 for (int i = 0; i < v.length; i++)
1452 tracker_motion_value.addItem(v[i]);
1453 tracker_motion_value.setMaximumRowCount(v.length);
1456 String get_tracker_motion_label() {
1457 return String.format("Logging Trigger Motion (%s):", AltosConvert.height.parse_units());
1460 void set_tracker_tool_tip() {
1461 if (tracker_motion_value.isVisible())
1462 tracker_motion_value.setToolTipText("How far the device must move before logging");
1464 tracker_motion_value.setToolTipText("This device doesn't disable logging when stationary");
1465 if (tracker_interval_value.isVisible())
1466 tracker_interval_value.setToolTipText("How often to report GPS position");
1468 tracker_interval_value.setToolTipText("This device can't configure interval");
1471 public void set_tracker_motion(int tracker_motion) {
1472 if (tracker_motion != AltosLib.MISSING)
1473 tracker_motion_value.setSelectedItem(AltosConvert.height.say(tracker_motion));
1474 tracker_motion_label.setVisible(tracker_motion != AltosLib.MISSING);
1475 tracker_motion_value.setVisible(tracker_motion != AltosLib.MISSING);
1478 public int tracker_motion() throws AltosConfigDataException {
1479 if (tracker_motion_value.isVisible()) {
1480 String str = tracker_motion_value.getSelectedItem().toString();
1482 return (int) (AltosConvert.height.parse_locale(str) + 0.5);
1483 } catch (ParseException pe) {
1484 throw new AltosConfigDataException("invalid tracker motion %s", str);
1487 return AltosLib.MISSING;
1490 public void set_tracker_interval(int tracker_interval) {
1491 if (tracker_interval != AltosLib.MISSING)
1492 tracker_interval_value.setSelectedItem(String.format("%d", tracker_interval));
1493 tracker_interval_label.setVisible(tracker_interval != AltosLib.MISSING);
1494 tracker_interval_value.setVisible(tracker_interval != AltosLib.MISSING);
1497 public int tracker_interval() throws AltosConfigDataException {
1498 if (tracker_interval_value.isVisible())
1499 return parse_int ("tracker interval", tracker_interval_value.getSelectedItem().toString(), false);
1500 return AltosLib.MISSING;
1503 public void set_pyros(AltosPyro[] new_pyros) {
1505 if (pyros != null && pyro_ui != null)
1506 pyro_ui.set_pyros(pyros);
1507 pyro.setVisible(pyros != null);
1510 public AltosPyro[] pyros() throws AltosConfigDataException {
1511 if (pyro_ui != null)
1512 pyros = pyro_ui.get_pyros();
1516 public void set_pyro_firing_time(double new_pyro_firing_time) {
1517 pyro_firing_time = new_pyro_firing_time;
1518 if (pyro_firing_time != AltosLib.MISSING && pyro_ui != null)
1519 pyro_ui.set_pyro_firing_time(pyro_firing_time);
1520 pyro.setVisible(pyro_firing_time != AltosLib.MISSING);
1523 public double pyro_firing_time() throws AltosConfigDataException {
1524 if (pyro_ui != null)
1525 pyro_firing_time = pyro_ui.get_pyro_firing_time();
1526 return pyro_firing_time;
1529 private String aprs_interval_string(int interval) {
1532 return Integer.toString(interval);
1535 private int aprs_interval_value(String interval) throws AltosConfigDataException {
1536 if (interval.equalsIgnoreCase("Disabled"))
1538 return parse_int("aprs interval", interval, false);
1541 public void set_aprs_interval(int new_aprs_interval) {
1542 if (new_aprs_interval != AltosLib.MISSING)
1543 aprs_interval_value.setSelectedItem(aprs_interval_string(new_aprs_interval));
1544 aprs_interval_value.setVisible(new_aprs_interval != AltosLib.MISSING);
1545 aprs_interval_label.setVisible(new_aprs_interval != AltosLib.MISSING);
1546 set_aprs_interval_tool_tip();
1549 public int aprs_interval() throws AltosConfigDataException {
1550 if (aprs_interval_value.isVisible())
1551 return aprs_interval_value(aprs_interval_value.getSelectedItem().toString());
1552 return AltosLib.MISSING;
1555 public void set_aprs_ssid(int new_aprs_ssid) {
1556 if (new_aprs_ssid != AltosLib.MISSING)
1557 aprs_ssid_value.setSelectedItem(new_aprs_ssid);
1558 aprs_ssid_value.setVisible(new_aprs_ssid != AltosLib.MISSING);
1559 aprs_ssid_label.setVisible(new_aprs_ssid != AltosLib.MISSING);
1560 set_aprs_ssid_tool_tip();
1563 public int aprs_ssid() throws AltosConfigDataException {
1564 if (aprs_ssid_value.isVisible()) {
1565 Integer i = (Integer) aprs_ssid_value.getSelectedItem();
1568 return AltosLib.MISSING;
1571 public void set_aprs_format(int new_aprs_format) {
1572 if (new_aprs_format != AltosLib.MISSING)
1573 aprs_format_value.setSelectedIndex(new_aprs_format);
1574 aprs_format_value.setVisible(new_aprs_format != AltosLib.MISSING);
1575 aprs_format_label.setVisible(new_aprs_format != AltosLib.MISSING);
1576 set_aprs_format_tool_tip();
1579 public int aprs_format() throws AltosConfigDataException {
1580 if (aprs_format_value.isVisible())
1581 return aprs_format_value.getSelectedIndex();
1582 return AltosLib.MISSING;
1585 public void set_aprs_offset(int new_aprs_offset) {
1586 if (new_aprs_offset != AltosLib.MISSING)
1587 aprs_offset_value.setSelectedItem(new_aprs_offset);
1588 aprs_offset_value.setVisible(new_aprs_offset != AltosLib.MISSING);
1589 aprs_offset_label.setVisible(new_aprs_offset != AltosLib.MISSING);
1590 set_aprs_offset_tool_tip();
1593 public int aprs_offset() throws AltosConfigDataException {
1594 if (aprs_offset_value.isVisible()) {
1595 Integer i = (Integer) aprs_offset_value.getSelectedItem();
1598 return AltosLib.MISSING;