Merge branch 'master' of git://git.gag.com/fw/altos
authorAnthony Towns <aj@erisian.com.au>
Tue, 28 Sep 2010 02:55:47 +0000 (12:55 +1000)
committerAnthony Towns <aj@erisian.com.au>
Tue, 28 Sep 2010 02:55:47 +0000 (12:55 +1000)
1  2 
ao-tools/altosui/AltosUI.java
ao-tools/altosui/Makefile.am

index e130de58d703470f61845d3852ccc9b89389370b,29eda2ece4566f793bbe1cb386a3849d00e28596..de0673a209e396630fb3b166a2e1586bf2b7f7bb
@@@ -46,6 -46,7 +46,7 @@@ import altosui.AltosCSVUI
  import altosui.AltosLine;
  import altosui.AltosStatusTable;
  import altosui.AltosInfoTable;
+ import altosui.AltosDisplayThread;
  
  import libaltosJNI.*;
  
@@@ -119,222 -120,7 +120,7 @@@ public class AltosUI extends JFrame 
                voice.speak("Rocket flight monitor ready.");
        }
  
-       void show(AltosState state, int crc_errors) {
-               if (state != null) {
-                       flightStatus.set(state);
-                       flightInfo.show(state, crc_errors);
-               }
-       }
-       class IdleThread extends Thread {
-               boolean started;
-               private AltosState state;
-               int     reported_landing;
-               int     report_interval;
-               long    report_time;
-               public synchronized void report(boolean last) {
-                       if (state == null)
-                               return;
-                       /* reset the landing count once we hear about a new flight */
-                       if (state.state < Altos.ao_flight_drogue)
-                               reported_landing = 0;
-                       /* Shut up once the rocket is on the ground */
-                       if (reported_landing > 2) {
-                               return;
-                       }
-                       /* If the rocket isn't on the pad, then report height */
-                       if (Altos.ao_flight_drogue <= state.state &&
-                           state.state < Altos.ao_flight_landed &&
-                           state.range >= 0)
-                       {
-                               voice.speak("Height %d, bearing %d, elevation %d, range %d.\n",
-                                           (int) (state.height + 0.5),
-                                           (int) (state.from_pad.bearing + 0.5),
-                                           (int) (state.elevation + 0.5),
-                                           (int) (state.range + 0.5));
-                       } else if (state.state > Altos.ao_flight_pad) {
-                               voice.speak("%d meters", (int) (state.height + 0.5));
-                       } else {
-                               reported_landing = 0;
-                       }
-                       /* If the rocket is coming down, check to see if it has landed;
-                        * either we've got a landed report or we haven't heard from it in
-                        * a long time
-                        */
-                       if (state.state >= Altos.ao_flight_drogue &&
-                           (last ||
-                            System.currentTimeMillis() - state.report_time >= 15000 ||
-                            state.state == Altos.ao_flight_landed))
-                       {
-                               if (Math.abs(state.baro_speed) < 20 && state.height < 100)
-                                       voice.speak("rocket landed safely");
-                               else
-                                       voice.speak("rocket may have crashed");
-                               if (state.from_pad != null)
-                                       voice.speak("Bearing %d degrees, range %d meters.",
-                                                   (int) (state.from_pad.bearing + 0.5),
-                                                   (int) (state.from_pad.distance + 0.5));
-                               ++reported_landing;
-                       }
-               }
-               long now () {
-                       return System.currentTimeMillis();
-               }
-               void set_report_time() {
-                       report_time = now() + report_interval;
-               }
-               public void run () {
-                       reported_landing = 0;
-                       state = null;
-                       report_interval = 10000;
-                       try {
-                               for (;;) {
-                                       set_report_time();
-                                       for (;;) {
-                                               voice.drain();
-                                               synchronized (this) {
-                                                       long    sleep_time = report_time - now();
-                                                       if (sleep_time <= 0)
-                                                               break;
-                                                       wait(sleep_time);
-                                               }
-                                       }
-                                       report(false);
-                               }
-                       } catch (InterruptedException ie) {
-                               try {
-                                       voice.drain();
-                               } catch (InterruptedException iie) { }
-                       }
-               }
-               public synchronized void notice(AltosState new_state, boolean spoken) {
-                       AltosState old_state = state;
-                       state = new_state;
-                       if (!started && state.state > Altos.ao_flight_pad) {
-                               started = true;
-                               start();
-                       }
-                       if (state.state < Altos.ao_flight_drogue)
-                               report_interval = 10000;
-                       else
-                               report_interval = 20000;
-                       if (old_state != null && old_state.state != state.state) {
-                               report_time = now();
-                               this.notify();
-                       } else if (spoken)
-                               set_report_time();
-               }
-       }
-       private boolean tell(AltosState state, AltosState old_state) {
-               boolean ret = false;
-               if (old_state == null || old_state.state != state.state) {
-                       voice.speak(state.data.state());
-                       if ((old_state == null || old_state.state <= Altos.ao_flight_boost) &&
-                           state.state > Altos.ao_flight_boost) {
-                               voice.speak("max speed: %d meters per second.",
-                                           (int) (state.max_speed + 0.5));
-                               ret = true;
-                       } else if ((old_state == null || old_state.state < Altos.ao_flight_drogue) &&
-                                  state.state >= Altos.ao_flight_drogue) {
-                               voice.speak("max height: %d meters.",
-                                           (int) (state.max_height + 0.5));
-                               ret = true;
-                       }
-               }
-               if (old_state == null || old_state.gps_ready != state.gps_ready) {
-                       if (state.gps_ready) {
-                               voice.speak("GPS ready");
-                               ret = true;
-                       }
-                       else if (old_state != null) {
-                               voice.speak("GPS lost");
-                               ret = true;
-                       }
-               }
-               old_state = state;
-               return ret;
-       }
-       class DisplayThread extends Thread {
-               IdleThread      idle_thread;
-               String          name;
-               int             crc_errors;
-               void init() { }
-               AltosRecord read() throws InterruptedException, ParseException, AltosCRCException, IOException { return null; }
-               void close(boolean interrupted) { }
-               void update(AltosState state) throws InterruptedException { }
-               public void run() {
-                       boolean         interrupted = false;
-                       String          line;
-                       AltosState      state = null;
-                       AltosState      old_state = null;
-                       boolean         told;
-                       idle_thread = new IdleThread();
-                       flightInfo.clear();
-                       try {
-                               for (;;) {
-                                       try {
-                                               AltosRecord record = read();
-                                               if (record == null)
-                                                       break;
-                                               old_state = state;
-                                               state = new AltosState(record, state);
-                                               update(state);
-                                               show(state, crc_errors);
-                                               told = tell(state, old_state);
-                                               idle_thread.notice(state, told);
-                                       } catch (ParseException pp) {
-                                               System.out.printf("Parse error: %d \"%s\"\n", pp.getErrorOffset(), pp.getMessage());
-                                       } catch (AltosCRCException ce) {
-                                               ++crc_errors;
-                                               show(state, crc_errors);
-                                       }
-                               }
-                       } catch (InterruptedException ee) {
-                               interrupted = true;
-                       } catch (IOException ie) {
-                               JOptionPane.showMessageDialog(AltosUI.this,
-                                                             String.format("Error reading from \"%s\"", name),
-                                                             "Telemetry Read Error",
-                                                             JOptionPane.ERROR_MESSAGE);
-                       } finally {
-                               close(interrupted);
-                               idle_thread.interrupt();
-                               try {
-                                       idle_thread.join();
-                               } catch (InterruptedException ie) {}
-                       }
-               }
-               public void report() {
-                       if (idle_thread != null)
-                               idle_thread.report(true);
-               }
-       }
-       class DeviceThread extends DisplayThread {
+       class DeviceThread extends AltosDisplayThread {
                AltosSerial     serial;
                LinkedBlockingQueue<AltosLine> telem;
  
                        serial.remove_monitor(telem);
                }
  
-               public DeviceThread(AltosSerial s, String in_name) {
+               public DeviceThread(AltosSerial s, String in_name, AltosVoice voice, AltosStatusTable status, AltosInfoTable info) {
+                       super(AltosUI.this, voice, status, info);
                        serial = s;
                        telem = new LinkedBlockingQueue<AltosLine>();
                        serial.add_monitor(telem);
                        try {
                                stop_display();
                                serial_line.open(device);
-                               DeviceThread thread = new DeviceThread(serial_line, device.getPath());
+                               DeviceThread thread = new DeviceThread(serial_line, device.getPath(), voice, flightStatus, flightInfo);
                                serial_line.set_channel(AltosPreferences.channel());
                                serial_line.set_callsign(AltosPreferences.callsign());
                                run_display(thread);
                new AltosFlashUI(AltosUI.this);
        }
  
-       /*
-        * Open an existing telemetry file and replay it in realtime
-        */
-       class ReplayThread extends DisplayThread {
-               AltosReader     reader;
-               String          name;
-               public AltosRecord read() {
-                       try {
-                               return reader.read();
-                       } catch (IOException ie) {
-                               JOptionPane.showMessageDialog(AltosUI.this,
-                                                             name,
-                                                             "error reading",
-                                                             JOptionPane.ERROR_MESSAGE);
-                       } catch (ParseException pe) {
-                       }
-                       return null;
-               }
-               public void close (boolean interrupted) {
-                       if (!interrupted)
-                               report();
-               }
-               public ReplayThread(AltosReader in_reader, String in_name) {
-                       reader = in_reader;
-               }
-               void update(AltosState state) throws InterruptedException {
-                       /* Make it run in realtime after the rocket leaves the pad */
-                       if (state.state > Altos.ao_flight_pad)
-                               Thread.sleep((int) (Math.min(state.time_change,10) * 1000));
-               }
-       }
  
        Thread          display_thread;
  
        private void Replay() {
                AltosLogfileChooser chooser = new AltosLogfileChooser(
                        AltosUI.this);
-               AltosReader reader = chooser.runDialog();
-               if (reader != null)
-                       run_display(new ReplayThread(reader,
-                                                    chooser.filename()));
+               AltosRecordIterable iterable = chooser.runDialog();
+               if (iterable != null)
+                       run_display(new AltosReplayThread(this, iterable.iterator(),
+                                                         chooser.filename(),
+                                                         voice,
+                                                         flightStatus,
+                                                         flightInfo));
        }
  
        /* Connect to TeleMetrum, either directly or through
                new AltosCSVUI(AltosUI.this);
        }
  
 +      /* Load a flight log CSV file and display a pretty graph.
 +       */
 +
 +      private void GraphData() {
 +              new AltosGraphUI(AltosUI.this);
 +      }
 +
        /* Create the AltosUI menus
         */
        private void createMenu() {
                                });
                        menu.add(item);
  
 +                      item = new JMenuItem("Graph Data",KeyEvent.VK_F);
 +                      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));
                return input.concat(extension);
        }
  
-       static AltosReader open_logfile(String filename) {
+       static AltosRecordIterable open_logfile(String filename) {
                File file = new File (filename);
                try {
                        FileInputStream in;
  
                        in = new FileInputStream(file);
                        if (filename.endsWith("eeprom"))
-                               return new AltosEepromReader(in);
+                               return new AltosEepromIterable(in);
                        else
-                               return new AltosTelemetryReader(in);
+                               return new AltosTelemetryIterable(in);
                } catch (FileNotFoundException fe) {
                        System.out.printf("Cannot open '%s'\n", filename);
                        return null;
                        return;
                }
                System.out.printf("Processing \"%s\" to \"%s\"\n", input, output);
-               AltosReader reader = open_logfile(input);
-               if (reader == null)
+               AltosRecordIterable iterable = open_logfile(input);
+               if (iterable == null)
                        return;
                AltosCSV writer = open_csv(output);
                if (writer == null)
                        return;
-               writer.write(reader);
-               reader.close();
+               writer.write(iterable);
                writer.close();
        }
  
                        altosui.setVisible(true);
                }
        }
 -}
 +}
index 35a1b99035665f21d3de454270a89cb5f8f7ebd1,7070af22e7fda87a0786a7e5d818b08a793f266a..ab8ca7d4a80163b4ed385a64ac65c12702a136b8
@@@ -5,7 -5,7 +5,7 @@@ man_MANS=altosui.
  
  altoslibdir=$(libdir)/altos
  
 -CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=".:classes:../libaltos:$(FREETTS)/*:/usr/share/java/*"
 +CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=".:classes:../libaltos:$(JFREECHART)/*:$(FREETTS)/*:/usr/share/java/*"
  
  bin_SCRIPTS=altosui
  
@@@ -20,9 -20,10 +20,10 @@@ altosui_JAVA = 
        AltosDebug.java \
        AltosDeviceDialog.java \
        AltosDevice.java \
+       AltosDisplayThread.java \
        AltosEepromDownload.java \
        AltosEepromMonitor.java \
-       AltosEepromReader.java \
+       AltosEepromIterable.java \
        AltosEepromRecord.java \
        AltosFile.java \
        AltosFlash.java \
@@@ -41,6 -42,8 +42,8 @@@
        AltosPreferences.java \
        AltosReader.java \
        AltosRecord.java \
+       AltosRecordIterable.java \
+       AltosReplayThread.java \
        AltosRomconfig.java \
        AltosRomconfigUI.java \
        AltosSerial.java \
        AltosState.java \
        AltosStatusTable.java \
        AltosTelemetry.java \
-       AltosTelemetryReader.java \
+       AltosTelemetryIterable.java \
        AltosUI.java \
 +    AltosCsvReader.java \
 +    AltosDataPoint.java \
 +    AltosGraph.java \
 +    AltosGraphTime.java \
 +    AltosGraphUI.java \
 +    AltosGraphDataChooser.java \
        AltosVoice.java
  
 +JFREECHART_CLASS= \
 +    jfreechart.jar \
 +    jcommon.jar \
 +    csv.jar
 +
  FREETTS_CLASS= \
        cmudict04.jar \
        cmulex.jar \
@@@ -95,7 -87,7 +98,7 @@@ LINUX_DIST=Altos-Linux-$(VERSION).tar.b
  MACOSX_DIST=Altos-Mac-$(VERSION).zip
  WINDOWS_DIST=Altos-Windows-$(VERSION_DASH).exe
  
 -FAT_FILES=$(FATJAR) $(FREETTS_CLASS)
 +FAT_FILES=$(FATJAR) $(FREETTS_CLASS) $(JFREECHART_CLASS)
  
  LINUX_FILES=$(FAT_FILES) libaltos.so $(FIRMWARE)
  LINUX_EXTRA=altosui-fat
@@@ -110,7 -102,7 +113,7 @@@ all-local: classes/altosui $(JAR) altos
  clean-local:
        -rm -rf classes $(JAR) $(FATJAR) \
                $(LINUX_DIST) $(MACOSX_DIST) windows $(WINDOWS_DIST) $(FREETTS_CLASS) \
 -              $(LIBALTOS) Manifest.txt Manifest-fat.txt altos-windows.log \
 +              $(JFREECHART_CLASS) $(LIBALTOS) Manifest.txt Manifest-fat.txt altos-windows.log \
                altosui altosui-test macosx linux
  
  if FATINSTALL
@@@ -157,7 -149,7 +160,7 @@@ $(JAR): classaltosui.stamp Manifest.tx
                -C classes altosui \
                -C ../libaltos libaltosJNI
  
 -$(FATJAR): classaltosui.stamp Manifest-fat.txt $(FREETTS_CLASS) $(LIBALTOS) $(JAVA_ICON)
 +$(FATJAR): classaltosui.stamp Manifest-fat.txt $(FREETTS_CLASS) $(JFREECHART_CLASS) $(LIBALTOS) $(JAVA_ICON)
        jar cfm $@ Manifest-fat.txt \
                -C $(top_srcdir)/icon altus-metrum-16x16.jpg \
                -C classes altosui \
  
  Manifest.txt: Makefile
        echo 'Main-Class: altosui.AltosUI' > $@
 -      echo "Class-Path: $(FREETTS)/freetts.jar" >> $@
 +      echo "Class-Path: $(FREETTS)/freetts.jar $(JFREECHART)/jfreechart.jar $(JFREECHAR)/jcommon.jar $(JFREECHART)/csv.jar" >> $@
  
  Manifest-fat.txt:
        echo 'Main-Class: altosui.AltosUI' > $@
 -      echo "Class-Path: freetts.jar" >> $@
 +      echo "Class-Path: freetts.jar jfreechart.jar jcommon.jar csv.jar" >> $@
  
  altosui: Makefile
        echo "#!/bin/sh" > $@