Merge branch 'new-packet-format' of ssh://git.gag.com/scm/git/fw/altos into new-packa...
authorBdale Garbee <bdale@gag.com>
Fri, 27 Aug 2010 09:08:53 +0000 (03:08 -0600)
committerBdale Garbee <bdale@gag.com>
Fri, 27 Aug 2010 09:08:53 +0000 (03:08 -0600)
34 files changed:
ao-tools/altosui/Altos.java
ao-tools/altosui/AltosCSV.java
ao-tools/altosui/AltosCSVUI.java [new file with mode: 0644]
ao-tools/altosui/AltosDebug.java
ao-tools/altosui/AltosEepromReader.java
ao-tools/altosui/AltosFlash.java
ao-tools/altosui/AltosFlashUI.java
ao-tools/altosui/AltosGPS.java
ao-tools/altosui/AltosGreatCircle.java
ao-tools/altosui/AltosLogfileChooser.java [new file with mode: 0644]
ao-tools/altosui/AltosParse.java
ao-tools/altosui/AltosReader.java
ao-tools/altosui/AltosRomconfig.java
ao-tools/altosui/AltosRomconfigUI.java
ao-tools/altosui/AltosSerial.java
ao-tools/altosui/AltosState.java
ao-tools/altosui/AltosTelemetry.java
ao-tools/altosui/AltosTelemetryReader.java
ao-tools/altosui/AltosUI.java
ao-tools/altosui/Makefile
src/Makefile.proto
src/ao.h
src/ao_adc.c
src/ao_cmd.c
src/ao_dma.c
src/ao_gps_report.c
src/ao_gps_skytraq.c
src/ao_log.c
src/ao_product.c
src/ao_radio.c
src/ao_serial.c
src/ao_timer.c
src/ao_usb.c
src/cc1111.h

index 53359e23715dd0c0e584cac77ccd1b16bdbe4a45..07bd01ae2fb5bb5e4d342ac171514be0d7885d25 100644 (file)
@@ -114,4 +114,90 @@ public class Altos {
        static final int AO_GPS_DATE_VALID = (1 << 6);
        static final int AO_GPS_NUM_SAT_SHIFT = 0;
        static final int AO_GPS_NUM_SAT_MASK = 0xf;
+
+       static boolean isspace(int c) {
+               switch (c) {
+               case ' ':
+               case '\t':
+                       return true;
+               }
+               return false;
+       }
+
+       static boolean ishex(int c) {
+               if ('0' <= c && c <= '9')
+                       return true;
+               if ('a' <= c && c <= 'f')
+                       return true;
+               if ('A' <= c && c <= 'F')
+                       return true;
+               return false;
+       }
+
+       static boolean ishex(String s) {
+               for (int i = 0; i < s.length(); i++)
+                       if (!ishex(s.charAt(i)))
+                               return false;
+               return true;
+       }
+
+       static int fromhex(int c) {
+               if ('0' <= c && c <= '9')
+                       return c - '0';
+               if ('a' <= c && c <= 'f')
+                       return c - 'a' + 10;
+               if ('A' <= c && c <= 'F')
+                       return c - 'A' + 10;
+               return -1;
+       }
+
+       static int fromhex(String s) throws NumberFormatException {
+               int c, v = 0;
+               for (int i = 0; i < s.length(); i++) {
+                       c = s.charAt(i);
+                       if (!ishex(c)) {
+                               if (i == 0)
+                                       throw new NumberFormatException(String.format("invalid hex \"%s\"", s));
+                               return v;
+                       }
+                       v = v * 16 + fromhex(c);
+               }
+               return v;
+       }
+
+       static boolean isdec(int c) {
+               if ('0' <= c && c <= '9')
+                       return true;
+               return false;
+       }
+
+       static boolean isdec(String s) {
+               for (int i = 0; i < s.length(); i++)
+                       if (!isdec(s.charAt(i)))
+                               return false;
+               return true;
+       }
+
+       static int fromdec(int c) {
+               if ('0' <= c && c <= '9')
+                       return c - '0';
+               return -1;
+       }
+
+       static int fromdec(String s) throws NumberFormatException {
+               int c, v = 0;
+               int sign = 1;
+               for (int i = 0; i < s.length(); i++) {
+                       c = s.charAt(i);
+                       if (i == 0 && c == '-') {
+                               sign = -1;
+                       } else if (!isdec(c)) {
+                               if (i == 0)
+                                       throw new NumberFormatException(String.format("invalid number \"%s\"", s));
+                               return v;
+                       } else
+                               v = v * 10 + fromdec(c);
+               }
+               return v * sign;
+       }
 }
index 2493675849624d359db390ddb442253ed5df065e..db50e7a2e7c4a5339e7e303e70db1244b8a158b9 100644 (file)
@@ -19,12 +19,20 @@ package altosui;
 
 import java.lang.*;
 import java.io.*;
+import java.text.*;
+import java.util.*;
+
 import altosui.AltosRecord;
+import altosui.AltosReader;
 
 public class AltosCSV {
-       File            name;
-       PrintStream     out;
-       boolean         header_written;
+       File                    name;
+       PrintStream             out;
+       boolean                 header_written;
+       boolean                 seen_boost;
+       int                     boost_tick;
+       LinkedList<AltosRecord> pad_records;
+       AltosState              state;
 
        static final int ALTOS_CSV_VERSION = 1;
 
@@ -36,6 +44,7 @@ public class AltosCSV {
         *      flight number
         *      callsign
         *      time (seconds since boost)
+        *      rssi
         *
         * Flight status
         *      state
@@ -45,6 +54,7 @@ public class AltosCSV {
         *      acceleration (m/s²)
         *      pressure (mBar)
         *      altitude (m)
+        *      height (m)
         *      accelerometer speed (m/s)
         *      barometer speed (m/s)
         *      temp (°C)
@@ -65,6 +75,8 @@ public class AltosCSV {
         *      hour (0-23)
         *      minute (0-59)
         *      second (0-59)
+        *      from_pad_dist (m)
+        *      from_pad_dir (deg true)
         *
         * GPS Sat data
         *      hdop
@@ -72,12 +84,14 @@ public class AltosCSV {
         */
 
        void write_general_header() {
-               out.printf("version serial flight call time");
+               out.printf("version serial flight call time rssi");
        }
 
        void write_general(AltosRecord record) {
-               out.printf("%s,%d,%d,%s,%d",
-                          record.version, record.serial, record.flight, record.callsign, record.tick);
+               out.printf("%s,%d,%d,%s,%8.2f,%4d",
+                          record.version, record.serial, record.flight, record.callsign,
+                          (double) record.time,
+                          record.rssi);
        }
 
        void write_flight_header() {
@@ -85,31 +99,135 @@ public class AltosCSV {
        }
 
        void write_flight(AltosRecord record) {
-               out.printf("%d,%s", record.state, record.state());
+               out.printf("%d,%8s", record.state, record.state());
+       }
+
+       void write_basic_header() {
+               out.printf("acceleration pressure altitude height accel_speed baro_speed temperature battery_voltage drogue_voltage main_voltage");
+       }
+
+       void write_basic(AltosRecord record) {
+               out.printf("%8.2f,%10.2f,%8.2f,%8.2f,%8.2f,%8.2f,%5.1f,%5.2f,%5.2f,%5.2f",
+                          record.acceleration(),
+                          record.pressure(),
+                          record.altitude(),
+                          record.height(),
+                          record.accel_speed(),
+                          state.baro_speed,
+                          record.temperature(),
+                          record.battery_voltage(),
+                          record.drogue_voltage(),
+                          record.main_voltage());
+       }
+
+       void write_gps_header() {
+               out.printf("connected locked nsat latitude longitude altitude year month day hour minute second pad_dist pad_dir");
+       }
+
+       void write_gps(AltosRecord record) {
+               AltosGPS        gps = record.gps;
+               if (gps == null)
+                       gps = new AltosGPS();
+
+               AltosGreatCircle from_pad = state.from_pad;
+               if (from_pad == null)
+                       from_pad = new AltosGreatCircle();
+
+               out.printf("%2d,%2d,%3d,%12.7f,%12.7f,%6d,%5d,%3d,%3d,%3d,%3d,%3d,%9.0f,%4.0f",
+                          gps.connected?1:0,
+                          gps.locked?1:0,
+                          gps.nsat,
+                          gps.lat,
+                          gps.lon,
+                          gps.alt,
+                          gps.year,
+                          gps.month,
+                          gps.day,
+                          gps.hour,
+                          gps.minute,
+                          gps.second,
+                          from_pad.distance,
+                          from_pad.bearing);
        }
 
        void write_header() {
                out.printf("# "); write_general_header();
                out.printf(" "); write_flight_header();
+               out.printf(" "); write_basic_header();
+               out.printf(" "); write_gps_header();
+               out.printf ("\n");
+       }
+
+       void write_one(AltosRecord record) {
+               state = new AltosState(record, state);
+               write_general(record); out.printf(",");
+               write_flight(record); out.printf(",");
+               write_basic(record); out.printf(",");
+               write_gps(record);
                out.printf ("\n");
        }
 
+       void flush_pad() {
+               while (!pad_records.isEmpty()) {
+                       write_one (pad_records.remove());
+               }
+       }
+
        public void write(AltosRecord record) {
                if (!header_written) {
                        write_header();
                        header_written = true;
                }
-               write_general(record); out.printf(",");
-               write_flight(record);
-               out.printf ("\n");
+               if (!seen_boost) {
+                       if (record.state >= Altos.ao_flight_boost) {
+                               seen_boost = true;
+                               boost_tick = record.tick;
+                               flush_pad();
+                       }
+               }
+               if (seen_boost)
+                       write_one(record);
+               else
+                       pad_records.add(record);
        }
 
        public PrintStream out() {
                return out;
        }
 
+       public void close() {
+               if (!pad_records.isEmpty()) {
+                       boost_tick = pad_records.element().tick;
+                       flush_pad();
+               }
+               out.close();
+       }
+
+       public void write(AltosReader reader) {
+               AltosRecord     record;
+
+               reader.write_comments(out());
+               try {
+                       for (;;) {
+                               record = reader.read();
+                               if (record == null)
+                                       break;
+                               write(record);
+                       }
+               } catch (IOException ie) {
+                       System.out.printf("IOException\n");
+               } catch (ParseException pe) {
+                       System.out.printf("ParseException %s\n", pe.getMessage());
+               }
+       }
+
        public AltosCSV(File in_name) throws FileNotFoundException {
                name = in_name;
                out = new PrintStream(name);
+               pad_records = new LinkedList<AltosRecord>();
+       }
+
+       public AltosCSV(String in_string) throws FileNotFoundException {
+               this(new File(in_string));
        }
 }
diff --git a/ao-tools/altosui/AltosCSVUI.java b/ao-tools/altosui/AltosCSVUI.java
new file mode 100644 (file)
index 0000000..2d81236
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * 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.AltosLogfileChooser;
+import altosui.AltosCSV;
+
+public class AltosCSVUI
+       extends JDialog
+       implements Runnable, ActionListener
+{
+       JFrame          frame;
+       Thread          thread;
+       AltosReader     reader;
+       AltosCSV        writer;
+
+       public void run() {
+               AltosLogfileChooser     chooser;
+
+               chooser = new AltosLogfileChooser(frame);
+               reader = chooser.runDialog();
+               if (reader == null)
+                       return;
+               JFileChooser    csv_chooser;
+
+               File file = chooser.file();
+               String path = file.getPath();
+               int dot = path.lastIndexOf(".");
+               if (dot >= 0)
+                       path = path.substring(0,dot);
+               path = path.concat(".csv");
+               csv_chooser = new JFileChooser(path);
+               int ret = csv_chooser.showSaveDialog(frame);
+               if (ret == JFileChooser.APPROVE_OPTION) {
+                       try {
+                               writer = new AltosCSV(csv_chooser.getSelectedFile());
+                       } catch (FileNotFoundException ee) {
+                               JOptionPane.showMessageDialog(frame,
+                                                             file.getName(),
+                                                             "Cannot open file",
+                                                             JOptionPane.ERROR_MESSAGE);
+                       }
+                       writer.write(reader);
+                       reader.close();
+                       writer.close();
+               }
+       }
+
+       public void actionPerformed(ActionEvent e) {
+       }
+
+       public AltosCSVUI(JFrame in_frame) {
+               frame = in_frame;
+               thread = new Thread(this);
+               thread.start();
+       }
+}
index 83ea5bcbf9f0c9abc1068fbfb317187f1eaaa2d7..ca2e5a9046625465130c0f4dd1ec55f9c10cba48 100644 (file)
@@ -58,46 +58,12 @@ public class AltosDebug extends AltosSerial {
        public static final byte GET_CHIP_ID =          0x68;
 
 
-       static boolean ishex(int c) {
-               if ('0' <= c && c <= '9')
-                       return true;
-               if ('a' <= c && c <= 'f')
-                       return true;
-               if ('A' <= c && c <= 'F')
-                       return true;
-               return false;
-       }
-
-       static boolean ishex(String s) {
-               for (int i = 0; i < s.length(); i++)
-                       if (!ishex(s.charAt(i)))
-                               return false;
-               return true;
-       }
-       static boolean isspace(int c) {
-               switch (c) {
-               case ' ':
-               case '\t':
-                       return true;
-               }
-               return false;
-       }
-
-       static int fromhex(int c) {
-               if ('0' <= c && c <= '9')
-                       return c - '0';
-               if ('a' <= c && c <= 'f')
-                       return c - 'a' + 10;
-               if ('A' <= c && c <= 'F')
-                       return c - 'A' + 10;
-               return -1;
-       }
-
        boolean debug_mode;
 
        void ensure_debug_mode() {
                if (!debug_mode) {
-                       printf("D\n");
+                       printf("m 0\nD\n");
+                       flush_reply();
                        debug_mode = true;
                }
        }
@@ -144,14 +110,14 @@ public class AltosDebug extends AltosSerial {
                int start = 0;
                while (i < length) {
                        String  line = get_reply().trim();
-                       if (!ishex(line) || line.length() % 2 != 0)
+                       if (!Altos.ishex(line) || line.length() % 2 != 0)
                                throw new IOException(
                                        String.format
                                        ("Invalid reply \"%s\"", line));
                        int this_time = line.length() / 2;
                        for (int j = 0; j < this_time; j++)
-                               data[start + j] = (byte) ((fromhex(line.charAt(j*2)) << 4) +
-                                                 fromhex(line.charAt(j*2+1)));
+                               data[start + j] = (byte) ((Altos.fromhex(line.charAt(j*2)) << 4) +
+                                                 Altos.fromhex(line.charAt(j*2+1)));
                        start += this_time;
                        i += this_time;
                }
@@ -198,7 +164,7 @@ public class AltosDebug extends AltosSerial {
                        String line = get_reply().trim();
                        String tokens[] = line.split("\\s+");
                        for (int j = 0; j < tokens.length; j++) {
-                               if (!ishex(tokens[j]) ||
+                               if (!Altos.ishex(tokens[j]) ||
                                    tokens[j].length() != 2)
                                        throw new IOException(
                                                String.format
index c29fd90b12391105d6ed76bfb5841d6c7c9e0e1e..3f2d4c625671877e047b1d5d903a8c02b4415b3a 100644 (file)
@@ -133,8 +133,6 @@ public class AltosEepromReader extends AltosReader {
                                        ground_pres += state.pres;
                                        state.ground_pres = (int) (ground_pres / n_pad_samples);
                                        state.flight_pres = state.ground_pres;
-                                       System.out.printf("ground pressure %d altitude %f\n",
-                                                         record.b, state.altitude());
                                        ground_accel += state.accel;
                                        state.ground_accel = (int) (ground_accel / n_pad_samples);
                                        state.flight_accel = state.ground_accel;
@@ -156,7 +154,6 @@ public class AltosEepromReader extends AltosReader {
                                seen |= seen_deploy;
                                break;
                        case Altos.AO_LOG_STATE:
-                               System.out.printf("state %d\n", record.a);
                                state.state = record.a;
                                break;
                        case Altos.AO_LOG_GPS_TIME:
@@ -218,6 +215,7 @@ public class AltosEepromReader extends AltosReader {
                        case Altos.AO_LOG_PRODUCT:
                                break;
                        case Altos.AO_LOG_SERIAL_NUMBER:
+                               state.serial = record.a;
                                break;
                        case Altos.AO_LOG_SOFTWARE_VERSION:
                                break;
@@ -228,6 +226,7 @@ public class AltosEepromReader extends AltosReader {
 
        public void write_comments(PrintStream out) {
                Iterator<AltosOrderedRecord>    iterator = records.iterator();
+               out.printf("# Comments\n");
                while (iterator.hasNext()) {
                        AltosOrderedRecord      record = iterator.next();
                        switch (record.cmd) {
@@ -250,7 +249,7 @@ public class AltosEepromReader extends AltosReader {
                                out.printf ("# Accel cal: %d %d\n", record.a, record.b);
                                break;
                        case Altos.AO_LOG_RADIO_CAL:
-                               out.printf ("# Radio cal: %d %d\n", record.a);
+                               out.printf ("# Radio cal: %d\n", record.a);
                                break;
                        case Altos.AO_LOG_MANUFACTURER:
                                out.printf ("# Manufacturer: %s\n", record.data);
@@ -296,10 +295,10 @@ public class AltosEepromReader extends AltosReader {
                                        break;
                                tick = record.tick;
                                if (!saw_boost && record.cmd == Altos.AO_LOG_STATE &&
-                                   record.a == Altos.ao_flight_boost)
+                                   record.a >= Altos.ao_flight_boost)
                                {
                                        saw_boost = true;
-                                       boost_tick = state.tick;
+                                       boost_tick = tick;
                                }
                                records.add(record);
                        }
index 0f92d6e7bf2ffb82d27fa31aa0fde7cb240e73d5..b70185558f974a6fe9fb94b7ebf10db4c1dd5258 100644 (file)
@@ -247,6 +247,7 @@ public class AltosFlash {
                int flash_addr = image.address;
                int image_start = 0;
 
+               action("start", 0);
                action(0, image.data.length);
                while (remain > 0 && !aborted) {
                        int this_time = remain;
@@ -314,6 +315,8 @@ public class AltosFlash {
        }
 
        public AltosRomconfig romconfig() {
+               if (!check_rom_config())
+                       return null;
                return rom_config;
        }
 
index 0c2041e3cf338f9a8fbdf7adf3125549aaef13aa..73a97a6b9177d29c073153bd32a4d37333a88607 100644 (file)
@@ -57,8 +57,10 @@ public class AltosFlashUI
                } else {
                        String  cmd = e.getActionCommand();
                        if (cmd.equals("done"))
-                               dispose();
-                       else {
+                               ;
+                       else if (cmd.equals("start")) {
+                               setVisible(true);
+                       } else {
                                pbar.setValue(e.getID());
                                pbar.setString(cmd);
                        }
@@ -70,14 +72,15 @@ public class AltosFlashUI
                flash.addActionListener(this);
                try {
                        flash.open();
-                       if (!flash.check_rom_config()) {
-                               AltosRomconfigUI romconfig_ui = new AltosRomconfigUI (frame);
-                               romconfig_ui.showDialog();
-                               AltosRomconfig romconfig = romconfig_ui.romconfig();
-                               if (romconfig == null)
-                                       return;
-                               flash.set_romconfig(romconfig);
-                       }
+                       AltosRomconfigUI romconfig_ui = new AltosRomconfigUI (frame);
+
+                       romconfig_ui.set(flash.romconfig());
+                       romconfig_ui.showDialog();
+
+                       AltosRomconfig romconfig = romconfig_ui.romconfig();
+                       if (romconfig == null || !romconfig.valid())
+                               return;
+                       flash.set_romconfig(romconfig);
                        serial_value.setText(String.format("%d",
                                                           flash.romconfig().serial_number));
                        file_value.setText(file.toString());
@@ -88,15 +91,14 @@ public class AltosFlashUI
                                                      "Cannot open image",
                                                      file.toString(),
                                                      JOptionPane.ERROR_MESSAGE);
-                       return;
                } catch (IOException e) {
                        JOptionPane.showMessageDialog(frame,
                                                      e.getMessage(),
                                                      file.toString(),
                                                      JOptionPane.ERROR_MESSAGE);
-                       return;
                } catch (InterruptedException ie) {
                }
+               dispose();
        }
 
        public void abort() {
index b3ee67e8369186dabbf392efc6a33ae06fa9ec75..acb6fb2c8bbbdcb4c211022951ea13fb1427c2d2 100644 (file)
@@ -52,14 +52,16 @@ public class AltosGPS {
 
        AltosGPSSat[] cc_gps_sat;       /* tracking data */
 
-       void ParseGPSTime(String date, String time) throws ParseException {
+       void ParseGPSDate(String date) throws ParseException {
                String[] ymd = date.split("-");
                if (ymd.length != 3)
                        throw new ParseException("error parsing GPS date " + date + " got " + ymd.length, 0);
                year = AltosParse.parse_int(ymd[0]);
                month = AltosParse.parse_int(ymd[1]);
                day = AltosParse.parse_int(ymd[2]);
+       }
 
+       void ParseGPSTime(String time) throws ParseException {
                String[] hms = time.split(":");
                if (hms.length != 3)
                        throw new ParseException("Error parsing GPS time " + time + " got " + hms.length, 0);
@@ -73,7 +75,7 @@ public class AltosGPS {
                hour = minute = second = 0;
        }
 
-       public AltosGPS(String[] words, int i) throws ParseException {
+       public AltosGPS(String[] words, int i, int version) throws ParseException {
                AltosParse.word(words[i++], "GPS");
                nsat = AltosParse.parse_int(words[i++]);
                AltosParse.word(words[i++], "sat");
@@ -92,32 +94,44 @@ public class AltosGPS {
                        locked = true;
                        connected = true;
 
-                       ParseGPSTime(words[i], words[i+1]); i += 2;
+                       if (version > 1)
+                               ParseGPSDate(words[i++]);
+                       else
+                               year = month = day = 0;
+                       ParseGPSTime(words[i++]);
                        lat = AltosParse.parse_coord(words[i++]);
                        lon = AltosParse.parse_coord(words[i++]);
-                       alt = AltosParse.parse_int(AltosParse.strip_suffix(words[i++], "m"));
-                       ground_speed = AltosParse.parse_double(AltosParse.strip_suffix(words[i++], "m/s(H)"));
-                       course = AltosParse.parse_int(AltosParse.strip_suffix(words[i++], "°"));
-                       climb_rate = AltosParse.parse_double(AltosParse.strip_suffix(words[i++], "m/s(V)"));
-                       hdop = AltosParse.parse_double(AltosParse.strip_suffix(words[i++], "(hdop)"));
-                       h_error = AltosParse.parse_int(AltosParse.strip_suffix(words[i++], "(herr)"));
-                       v_error = AltosParse.parse_int(AltosParse.strip_suffix(words[i++], "(verr)"));
+                       alt = AltosParse.parse_int(words[i++]);
+                       if (version > 1 || (i < words.length && !words[i].equals("SAT"))) {
+                               ground_speed = AltosParse.parse_double(AltosParse.strip_suffix(words[i++], "m/s(H)"));
+                               course = AltosParse.parse_int(words[i++]);
+                               climb_rate = AltosParse.parse_double(AltosParse.strip_suffix(words[i++], "m/s(V)"));
+                               hdop = AltosParse.parse_double(AltosParse.strip_suffix(words[i++], "(hdop)"));
+                               h_error = AltosParse.parse_int(words[i++]);
+                               v_error = AltosParse.parse_int(words[i++]);
+                       }
                } else {
                        i++;
                }
-               AltosParse.word(words[i++], "SAT");
-               int tracking_channels = 0;
-               if (words[i].equals("not-connected"))
-                       tracking_channels = 0;
-               else
-                       tracking_channels = AltosParse.parse_int(words[i]);
-               i++;
-               cc_gps_sat = new AltosGPS.AltosGPSSat[tracking_channels];
-               for (int chan = 0; chan < tracking_channels; chan++) {
-                       cc_gps_sat[chan] = new AltosGPS.AltosGPSSat();
-                       cc_gps_sat[chan].svid = AltosParse.parse_int(words[i++]);
-                       cc_gps_sat[chan].c_n0 = AltosParse.parse_int(words[i++]);
-               }
+               if (i < words.length) {
+                       AltosParse.word(words[i++], "SAT");
+                       int tracking_channels = 0;
+                       if (words[i].equals("not-connected"))
+                               tracking_channels = 0;
+                       else
+                               tracking_channels = AltosParse.parse_int(words[i]);
+                       i++;
+                       cc_gps_sat = new AltosGPS.AltosGPSSat[tracking_channels];
+                       for (int chan = 0; chan < tracking_channels; chan++) {
+                               cc_gps_sat[chan] = new AltosGPS.AltosGPSSat();
+                               cc_gps_sat[chan].svid = AltosParse.parse_int(words[i++]);
+                               /* Older versions included SiRF status bits */
+                               if (version < 2)
+                                       i++;
+                               cc_gps_sat[chan].c_n0 = AltosParse.parse_int(words[i++]);
+                       }
+               } else
+                       cc_gps_sat = new AltosGPS.AltosGPSSat[0];
        }
 
        public void set_latitude(int in_lat) {
@@ -172,6 +186,7 @@ public class AltosGPS {
                nsat = old.nsat;
                locked = old.locked;
                connected = old.connected;
+               date_valid = old.date_valid;
                lat = old.lat;          /* degrees (+N -S) */
                lon = old.lon;          /* degrees (+E -W) */
                alt = old.alt;          /* m */
index 878da03e2b6a7ad2ade1e87fc97a19fa80055315..07c02c16c34c17d665335ff3c657482a289a4a62 100644 (file)
@@ -17,6 +17,8 @@
 
 package altosui;
 
+import altosui.AltosGPS;
+
 import java.lang.Math;
 
 public class AltosGreatCircle {
@@ -28,8 +30,8 @@ public class AltosGreatCircle {
        static final double rad = Math.PI / 180;
        static final double earth_radius = 6371.2 * 1000;       /* in meters */
 
-       AltosGreatCircle (double start_lat, double start_lon,
-                         double end_lat, double end_lon)
+       public AltosGreatCircle (double start_lat, double start_lon,
+                                double end_lat, double end_lon)
        {
                double lat1 = rad * start_lat;
                double lon1 = rad * -start_lon;
@@ -63,4 +65,13 @@ public class AltosGreatCircle {
                distance = d * earth_radius;
                bearing = course * 180/Math.PI;
        }
+
+       public AltosGreatCircle(AltosGPS start, AltosGPS end) {
+               this(start.lat, start.lon, end.lat, end.lon);
+       }
+
+       public AltosGreatCircle() {
+               distance = 0;
+               bearing = 0;
+       }
 }
diff --git a/ao-tools/altosui/AltosLogfileChooser.java b/ao-tools/altosui/AltosLogfileChooser.java
new file mode 100644 (file)
index 0000000..36b51de
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * 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 altosui.AltosPreferences;
+import altosui.AltosReader;
+import altosui.AltosEepromReader;
+import altosui.AltosTelemetryReader;
+
+public class AltosLogfileChooser extends JFileChooser {
+       JFrame  frame;
+       String  filename;
+       File    file;
+
+       public String filename() {
+               return filename;
+       }
+
+       public File file() {
+               return file;
+       }
+
+       public AltosReader runDialog() {
+               int     ret;
+
+               ret = showOpenDialog(frame);
+               if (ret == APPROVE_OPTION) {
+                       file = getSelectedFile();
+                       if (file == null)
+                               return null;
+                       filename = file.getName();
+                       try {
+                               FileInputStream in;
+
+                               in = new FileInputStream(file);
+                               if (filename.endsWith("eeprom"))
+                                       return new AltosEepromReader(in);
+                               else
+                                       return new AltosTelemetryReader(in);
+                       } catch (FileNotFoundException fe) {
+                               JOptionPane.showMessageDialog(frame,
+                                                             filename,
+                                                             "Cannot open file",
+                                                             JOptionPane.ERROR_MESSAGE);
+                       }
+               }
+               return null;
+       }
+
+       public AltosLogfileChooser(JFrame in_frame) {
+               frame = in_frame;
+               setDialogTitle("Select Flight Record File");
+               setFileFilter(new FileNameExtensionFilter("Flight data file",
+                                                         "eeprom",
+                                                         "telem"));
+               setCurrentDirectory(AltosPreferences.logdir());
+       }
+}
\ No newline at end of file
index a60dc69434a67aa454519979041fee7f7a4d47a3..4d82de7816ef2d625d3ef3ec386116c2bae527d7 100644 (file)
@@ -20,10 +20,16 @@ package altosui;
 import java.text.*;
 import java.lang.*;
 
+import altosui.Altos;
+
 public class AltosParse {
+       static boolean isdigit(char c) {
+               return '0' <= c && c <= '9';
+       }
+
        static int parse_int(String v) throws ParseException {
                try {
-                       return Integer.parseInt(v);
+                       return Altos.fromdec(v);
                } catch (NumberFormatException e) {
                        throw new ParseException("error parsing int " + v, 0);
                }
@@ -31,7 +37,7 @@ public class AltosParse {
 
        static int parse_hex(String v) throws ParseException {
                try {
-                       return Integer.parseInt(v, 16);
+                       return Altos.fromhex(v);
                } catch (NumberFormatException e) {
                        throw new ParseException("error parsing hex " + v, 0);
                }
index 81779e2bff5bd75675c4abcdb6422d1658bdbc4e..5be8795dc7e2a774f2dd21e1c25ddf3797f657b6 100644 (file)
@@ -25,4 +25,6 @@ import altosui.AltosRecord;
 
 public class AltosReader {
        public AltosRecord read() throws IOException, ParseException { return null; }
+       public void close() { }
+       public void write_comments(PrintStream out) { }
 }
index 844da7c4b7aad021b969453a01616b2ed86fb0f1..8c9cb27aa1207971ee21218ce058c9b02bc02652 100644 (file)
@@ -47,14 +47,57 @@ public class AltosRomconfig {
                }
        }
 
+       static void put_string(String value, byte[] bytes, int start) {
+               for (int i = 0; i < value.length(); i++)
+                       bytes[start + i] = (byte) value.charAt(i);
+       }
+
+       static final int AO_USB_DESC_STRING     = 3;
+
+       static void put_usb_serial(int value, byte[] bytes, int start) {
+               int offset = start + 0xa;
+               int string_num = 0;
+               System.out.printf("Put usb serial %d\n", value);
+
+               while (offset < bytes.length && bytes[offset] != 0) {
+                       if (bytes[offset + 1] == AO_USB_DESC_STRING) {
+                               ++string_num;
+                               if (string_num == 4)
+                                       break;
+                       }
+                       offset += ((int) bytes[offset]) & 0xff;
+               }
+               System.out.printf("offset %d content %d\n",
+                                 offset, bytes[offset]);
+               if (offset >= bytes.length || bytes[offset] == 0)
+                       return;
+               int len = ((((int) bytes[offset]) & 0xff) - 2) / 2;
+               String fmt = String.format("%%0%dd", len);
+               System.out.printf("existing serial length %d format %s\n", len, fmt);
+
+               String s = String.format(fmt, value);
+               if (s.length() != len) {
+                       System.out.printf("weird usb length issue %s isn't %d\n",
+                                         s, len);
+                       return;
+               }
+               for (int i = 0; i < len; i++) {
+                       bytes[offset + 2 + i*2] = (byte) s.charAt(i);
+                       bytes[offset + 2 + i*2+1] = 0;
+               }
+       }
+
        public AltosRomconfig(byte[] bytes, int offset) {
                version = get_int(bytes, offset + 0, 2);
                check = get_int(bytes, offset + 2, 2);
+               System.out.printf("version %d check %d\n", version, check);
                if (check == (~version & 0xffff)) {
                        switch (version) {
+                       case 2:
                        case 1:
                                serial_number = get_int(bytes, offset + 4, 2);
                                radio_calibration = get_int(bytes, offset + 6, 4);
+                               System.out.printf("serial %d cal %d\n", serial_number, radio_calibration);
                                valid = true;
                                break;
                        }
@@ -77,6 +120,8 @@ public class AltosRomconfig {
                        throw new IOException("image does not contain existing rom config");
 
                switch (existing.version) {
+               case 2:
+                       put_usb_serial(serial_number, bytes, offset);
                case 1:
                        put_int(serial_number, bytes, offset + 4, 2);
                        put_int(radio_calibration, bytes, offset + 6, 4);
@@ -86,7 +131,9 @@ public class AltosRomconfig {
 
        public void write (AltosHexfile hexfile) throws IOException {
                write(hexfile.data, 0xa0 - hexfile.address);
-               new AltosRomconfig(hexfile);
+               AltosRomconfig check = new AltosRomconfig(hexfile);
+               if (!check.valid())
+                       throw new IOException("writing new rom config failed\n");
        }
 
        public AltosRomconfig(int in_serial_number, int in_radio_calibration) {
index 21c34ef442546bd2bea560c593e87c55ce1d1a62..bc511865a552c48c261ed2be2996cbc70b09993e 100644 (file)
@@ -143,12 +143,31 @@ public class AltosRomconfigUI
                return Integer.parseInt(serial_value.getText());
        }
 
+       void set_serial(int serial) {
+               serial_value.setText(String.format("%d", serial));
+       }
+
        int radio_calibration() {
                return Integer.parseInt(radio_calibration_value.getText());
        }
 
+       void set_radio_calibration(int calibration) {
+               radio_calibration_value.setText(String.format("%d", calibration));
+       }
+
+       public void set(AltosRomconfig config) {
+               if (config != null && config.valid()) {
+                       set_serial(config.serial_number);
+                       set_radio_calibration(config.radio_calibration);
+               }
+       }
+
        public AltosRomconfig romconfig() {
-               return new AltosRomconfig(serial(), radio_calibration());
+               try {
+                       return new AltosRomconfig(serial(), radio_calibration());
+               } catch (NumberFormatException ne) {
+                       return null;
+               }
        }
 
        public AltosRomconfig showDialog() {
index d02e25a965e7a9344b9ac0f6ab45b084a7953b40..5b47960f79a28f8d7e4bd92977147b6eaad30587 100644 (file)
@@ -45,6 +45,8 @@ public class AltosSerial implements Runnable {
        LinkedBlockingQueue<String> reply_queue;
        Thread input_thread;
        String line;
+       byte[] line_bytes;
+       int line_count;
 
        public void run () {
                int c;
@@ -60,18 +62,36 @@ public class AltosSerial implements Runnable {
                                        continue;
                                synchronized(this) {
                                        if (c == '\n') {
-                                               if (line != "") {
+                                               if (line_count != 0) {
+                                                       try {
+                                                               line = new String(line_bytes, 0, line_count, "UTF-8");
+                                                       } catch (UnsupportedEncodingException ue) {
+                                                               line = "";
+                                                               for (int i = 0; i < line_count; i++)
+                                                                       line = line + line_bytes[i];
+                                                       }
                                                        if (line.startsWith("VERSION")) {
                                                                for (int e = 0; e < monitors.size(); e++) {
                                                                        LinkedBlockingQueue<String> q = monitors.get(e);
                                                                        q.put(line);
                                                                }
-                                                       } else
+                                                       } else {
+//                                                             System.out.printf("GOT: %s\n", line);
                                                                reply_queue.put(line);
+                                                       }
+                                                       line_count = 0;
                                                        line = "";
                                                }
                                        } else {
-                                               line = line + (char) c;
+                                               if (line_bytes == null) {
+                                                       line_bytes = new byte[256];
+                                               } else if (line_count == line_bytes.length) {
+                                                       byte[] new_line_bytes = new byte[line_count * 2];
+                                                       System.arraycopy(line_bytes, 0, new_line_bytes, 0, line_count);
+                                                       line_bytes = new_line_bytes;
+                                               }
+                                               line_bytes[line_count] = (byte) c;
+                                               line_count++;
                                        }
                                }
                        }
@@ -80,6 +100,11 @@ public class AltosSerial implements Runnable {
        }
 
        public void flush_reply() {
+               libaltos.altos_flush(altos);
+               try {
+                       Thread.sleep(100);
+               } catch (InterruptedException ie) {
+               }
                reply_queue.clear();
        }
 
@@ -132,6 +157,7 @@ public class AltosSerial implements Runnable {
        }
 
        public void print(String data) {
+//h            System.out.printf("\"%s\" ", data);
                for (int i = 0; i < data.length(); i++)
                        putc(data.charAt(i));
        }
index deeb4c771dcec9fb825d918bea922f75c3ff4024..c13dfe68451adb303530d1619474568486c267f7 100644 (file)
@@ -124,11 +124,6 @@ public class AltosState {
                }
 
                if (state == Altos.ao_flight_pad) {
-                       if (data.gps == null)
-                               System.out.printf("on pad, gps null\n");
-                       else
-                               System.out.printf ("on pad gps lat %f lon %f locked %d nsat %d\n",
-                                                  data.gps.lat, data.gps.lon, data.gps.locked ? 1 : 0, data.gps.nsat);
                        if (data.gps != null && data.gps.locked && data.gps.nsat >= 4) {
                                npad++;
                                if (npad > 1) {
index af29b8c04ef5e940e25dd1ca3e796e9dc895fbeb..bc62690b262874b4006ff723f208ae2a8daebfd2 100644 (file)
@@ -57,8 +57,12 @@ public class AltosTelemetry extends AltosRecord {
                String[] words = line.split("\\s+");
                int     i = 0;
 
-               AltosParse.word (words[i++], "VERSION");
-               version = AltosParse.parse_int(words[i++]);
+               if (words[i].equals("CALL")) {
+                       version = 0;
+               } else {
+                       AltosParse.word (words[i++], "VERSION");
+                       version = AltosParse.parse_int(words[i++]);
+               }
 
                AltosParse.word (words[i++], "CALL");
                callsign = words[i++];
@@ -66,12 +70,19 @@ public class AltosTelemetry extends AltosRecord {
                AltosParse.word (words[i++], "SERIAL");
                serial = AltosParse.parse_int(words[i++]);
 
-               AltosParse.word (words[i++], "FLIGHT");
-               flight = AltosParse.parse_int(words[i++]);
+               if (version >= 2) {
+                       AltosParse.word (words[i++], "FLIGHT");
+                       flight = AltosParse.parse_int(words[i++]);
+               } else
+                       flight = 0;
 
                AltosParse.word(words[i++], "RSSI");
                rssi = AltosParse.parse_int(words[i++]);
 
+               /* Older telemetry data had mis-computed RSSI value */
+               if (version <= 2)
+                       rssi = (rssi + 74) / 2 - 74;
+
                AltosParse.word(words[i++], "STATUS");
                status = AltosParse.parse_hex(words[i++]);
 
@@ -113,12 +124,17 @@ public class AltosTelemetry extends AltosRecord {
                AltosParse.word(words[i++], "gp:");
                ground_pres = AltosParse.parse_int(words[i++]);
 
-               AltosParse.word(words[i++], "a+:");
-               accel_plus_g = AltosParse.parse_int(words[i++]);
+               if (version >= 1) {
+                       AltosParse.word(words[i++], "a+:");
+                       accel_plus_g = AltosParse.parse_int(words[i++]);
 
-               AltosParse.word(words[i++], "a-:");
-               accel_minus_g = AltosParse.parse_int(words[i++]);
+                       AltosParse.word(words[i++], "a-:");
+                       accel_minus_g = AltosParse.parse_int(words[i++]);
+               } else {
+                       accel_plus_g = ground_accel;
+                       accel_minus_g = ground_accel + 530;
+               }
 
-               gps = new AltosGPS(words, i);
+               gps = new AltosGPS(words, i, version);
        }
 }
index f1f6788c0afbc17973574a0b98c5459647d153a8..a3402f9c8b85a1756809ed2f879009fcb37b4294 100644 (file)
@@ -47,20 +47,25 @@ public class AltosTelemetryReader extends AltosReader {
                try {
                        for (;;) {
                                String line = AltosRecord.gets(input);
-                               if (line == null)
+                               if (line == null) {
                                        break;
-                               AltosTelemetry record = new AltosTelemetry(line);
-                               if (record == null)
-                                       break;
-                               if (!saw_boost && record.state >= Altos.ao_flight_boost)
-                               {
-                                       saw_boost = true;
-                                       boost_tick = record.tick;
                                }
-                               records.add(record);
+                               try {
+                                       AltosTelemetry record = new AltosTelemetry(line);
+                                       if (record == null)
+                                               break;
+                                       if (!saw_boost && record.state >= Altos.ao_flight_boost)
+                                       {
+                                               saw_boost = true;
+                                               boost_tick = record.tick;
+                                       }
+                                       records.add(record);
+                               } catch (ParseException pe) {
+                                       System.out.printf("parse exception %s\n", pe.getMessage());
+                               }
                        }
                } catch (IOException io) {
-               } catch (ParseException pe) {
+                       System.out.printf("io exception\n");
                }
                record_iterator = records.iterator();
                try {
index 9fd47ea7ae149a3fc688cb0e824f2d934e2dec1a..4f3b5ddeb1c1c2fa68ab8d639135a0c32e18232e 100644 (file)
@@ -42,6 +42,8 @@ import altosui.AltosFlightStatusTableModel;
 import altosui.AltosFlightInfoTableModel;
 import altosui.AltosChannelMenu;
 import altosui.AltosFlashUI;
+import altosui.AltosLogfileChooser;
+import altosui.AltosCSVUI;
 
 import libaltosJNI.*;
 
@@ -529,33 +531,12 @@ public class AltosUI extends JFrame {
         * Replay a flight from telemetry data
         */
        private void Replay() {
-               JFileChooser    logfile_chooser = new JFileChooser();
-
-               logfile_chooser.setDialogTitle("Select Flight Record File");
-               logfile_chooser.setFileFilter(new FileNameExtensionFilter("Flight data file", "eeprom", "telem"));
-               logfile_chooser.setCurrentDirectory(AltosPreferences.logdir());
-               int returnVal = logfile_chooser.showOpenDialog(AltosUI.this);
-
-               if (returnVal == JFileChooser.APPROVE_OPTION) {
-                       File file = logfile_chooser.getSelectedFile();
-                       if (file == null)
-                               System.out.println("No file selected?");
-                       String  filename = file.getName();
-                       try {
-                               FileInputStream replay = new FileInputStream(file);
-                               DisplayThread   thread;
-                               if (filename.endsWith("eeprom"))
-                                   thread = new ReplayEepromThread(replay, filename);
-                               else
-                                   thread = new ReplayTelemetryThread(replay, filename);
-                               run_display(thread);
-                       } catch (FileNotFoundException ee) {
-                               JOptionPane.showMessageDialog(AltosUI.this,
-                                                             filename,
-                                                             "Cannot open telemetry file",
-                                                             JOptionPane.ERROR_MESSAGE);
-                       }
-               }
+               AltosLogfileChooser chooser = new AltosLogfileChooser(
+                       AltosUI.this);
+               AltosReader reader = chooser.runDialog();
+               if (reader != null)
+                       run_display(new ReplayThread(reader,
+                                                    chooser.filename()));
        }
 
        /* Connect to TeleMetrum, either directly or through
@@ -565,6 +546,14 @@ public class AltosUI extends JFrame {
                new AltosEepromDownload(AltosUI.this);
        }
 
+       /* Load a flight log file and write out a CSV file containing
+        * all of the data in standard units
+        */
+
+       private void ExportData() {
+               new AltosCSVUI(AltosUI.this);
+       }
+
        /* Create the AltosUI menus
         */
        private void createMenu() {
@@ -603,6 +592,14 @@ public class AltosUI extends JFrame {
                                });
                        menu.add(item);
 
+                       item = new JMenuItem("Export Data",KeyEvent.VK_F);
+                       item.addActionListener(new ActionListener() {
+                                       public void actionPerformed(ActionEvent e) {
+                                               ExportData();
+                                       }
+                               });
+                       menu.add(item);
+
                        item = new JMenuItem("Quit",KeyEvent.VK_Q);
                        item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q,
                                                                   ActionEvent.CTRL_MASK));
@@ -722,8 +719,67 @@ public class AltosUI extends JFrame {
                this.setJMenuBar(menubar);
 
        }
+
+       static String replace_extension(String input, String extension) {
+               int dot = input.lastIndexOf(".");
+               if (dot > 0)
+                       input = input.substring(0,dot);
+               return input.concat(extension);
+       }
+
+       static AltosReader open_logfile(String filename) {
+               File file = new File (filename);
+               try {
+                       FileInputStream in;
+
+                       in = new FileInputStream(file);
+                       if (filename.endsWith("eeprom"))
+                               return new AltosEepromReader(in);
+                       else
+                               return new AltosTelemetryReader(in);
+               } catch (FileNotFoundException fe) {
+                       System.out.printf("Cannot open '%s'\n", filename);
+                       return null;
+               }
+       }
+
+       static AltosCSV open_csv(String filename) {
+               File file = new File (filename);
+               try {
+                       return new AltosCSV(file);
+               } catch (FileNotFoundException fe) {
+                       System.out.printf("Cannot open '%s'\n", filename);
+                       return null;
+               }
+       }
+
+       static void process_file(String input) {
+               String output = replace_extension(input,".csv");
+               if (input.equals(output)) {
+                       System.out.printf("Not processing '%s'\n", input);
+                       return;
+               }
+               System.out.printf("Processing \"%s\" to \"%s\"\n", input, output);
+               AltosReader reader = open_logfile(input);
+               if (reader == null)
+                       return;
+               AltosCSV writer = open_csv(output);
+               if (writer == null)
+                       return;
+               writer.write(reader);
+               reader.close();
+               writer.close();
+       }
+
        public static void main(final String[] args) {
-               AltosUI altosui = new AltosUI();
-               altosui.setVisible(true);
+
+               /* Handle batch-mode */
+               if (args.length > 0) {
+                       for (int i = 0; i < args.length; i++)
+                               process_file(args[i]);
+               } else {
+                       AltosUI altosui = new AltosUI();
+                       altosui.setVisible(true);
+               }
        }
 }
\ No newline at end of file
index d4d3ee7ab4f66c2acc7fcffd60c8fed6123c18c3..d3ecb889d909b3f83afd2df15d6a8ba1c15d2641 100644 (file)
@@ -8,6 +8,7 @@ CLASSFILES=\
        AltosConfigUI.class \
        AltosConvert.class \
        AltosCSV.class \
+       AltosCSVUI.class \
        AltosDebug.class \
        AltosEepromDownload.class \
        AltosEepromMonitor.class \
@@ -22,6 +23,7 @@ CLASSFILES=\
        AltosGreatCircle.class \
        AltosHexfile.class \
        AltosLog.class \
+       AltosLogfileChooser.class \
        AltosParse.class \
        AltosPreferences.class \
        AltosRecord.class \
index 8bc8b0e174fc2008f5ac36e4e49bff26a0041dba..59a3b8a616d7969a80f0ba24f12f85703aa6b6a3 100644 (file)
@@ -214,9 +214,11 @@ all: ../$(PROG)
 ../altitude.h: make-altitude
        nickle $< > $@
 
-ao_product.h: ao-make-product.5c
+ao_product.h: ao-make-product.5c always
        $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
 
+always:
+
 ao_product.rel: ao_product.c ao_product.h
        $(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $<
 
index 9c418db2e804298f04335062dd6e14d9f150be71..cd4e4814e07a8a27611f9a56c06db47bcc25941f 100644 (file)
--- a/src/ao.h
+++ b/src/ao.h
@@ -79,7 +79,7 @@ ao_alarm(uint16_t delay);
 
 /* Yield the processor to another task */
 void
-ao_yield(void) _naked;
+ao_yield(void) __naked;
 
 /* Add a task to the run queue */
 void
@@ -139,7 +139,7 @@ ao_timer_set_adc_interval(uint8_t interval) __critical;
 
 /* Timer interrupt */
 void
-ao_timer_isr(void) interrupt 9;
+ao_timer_isr(void) __interrupt 9;
 
 /* Initialize the timer */
 void
@@ -198,7 +198,7 @@ ao_adc_get(__xdata struct ao_adc *packet);
 /* The A/D interrupt handler */
 
 void
-ao_adc_isr(void) interrupt 1;
+ao_adc_isr(void) __interrupt 1;
 
 /* Initialize the A/D converter */
 void
@@ -293,12 +293,13 @@ ao_led_init(uint8_t enable);
  * ao_romconfig.c
  */
 
-#define AO_ROMCONFIG_VERSION   1
+#define AO_ROMCONFIG_VERSION   2
 
 extern __code __at (0x00a0) uint16_t ao_romconfig_version;
 extern __code __at (0x00a2) uint16_t ao_romconfig_check;
 extern __code __at (0x00a4) uint16_t ao_serial_number;
 extern __code __at (0x00a6) uint32_t ao_radio_cal;
+extern __code __at (0x00aa) uint8_t ao_usb_descriptors [];
 
 /*
  * ao_usb.c
@@ -324,7 +325,7 @@ ao_usb_flush(void);
 
 /* USB interrupt handler */
 void
-ao_usb_isr(void) interrupt 6;
+ao_usb_isr(void) __interrupt 6;
 
 /* Enable the USB controller */
 void
@@ -424,7 +425,7 @@ ao_dma_abort(uint8_t id);
 
 /* DMA interrupt routine */
 void
-ao_dma_isr(void) interrupt 8;
+ao_dma_isr(void) __interrupt 8;
 
 /*
  * ao_mutex.c
@@ -563,6 +564,7 @@ struct ao_log_record {
                        uint8_t         year;
                        uint8_t         month;
                        uint8_t         day;
+                       uint8_t         extra;
                } gps_date;
                struct {
                        uint16_t        d0;
@@ -572,7 +574,7 @@ struct ao_log_record {
 };
 
 /* Write a record to the eeprom log */
-void
+uint8_t
 ao_log_data(__xdata struct ao_log_record *log) __reentrant;
 
 /* Flush the log */
@@ -720,10 +722,10 @@ ao_dbg_init(void);
 
 #if HAS_SERIAL_1
 void
-ao_serial_rx1_isr(void) interrupt 3;
+ao_serial_rx1_isr(void) __interrupt 3;
 
 void
-ao_serial_tx1_isr(void) interrupt 14;
+ao_serial_tx1_isr(void) __interrupt 14;
 
 char
 ao_serial_getchar(void) __critical;
@@ -859,7 +861,7 @@ extern __xdata uint8_t ao_radio_done;
 extern __xdata uint8_t ao_radio_mutex;
 
 void
-ao_radio_general_isr(void) interrupt 16;
+ao_radio_general_isr(void) __interrupt 16;
 
 void
 ao_radio_get(void);
@@ -1008,7 +1010,7 @@ ao_rssi_init(uint8_t rssi_led);
  * each instance of a product
  */
 
-extern const uint8_t ao_usb_descriptors [];
+extern __code __at(0x00aa) uint8_t ao_usb_descriptors [];
 extern const char ao_version[];
 extern const char ao_manufacturer[];
 extern const char ao_product[];
index 50f968488ab2ebf6b06257de3d2ab408967e99b7..49d2519e209d5c4f2faf594c5afb08da9da42af6 100644 (file)
@@ -41,7 +41,7 @@ ao_adc_get(__xdata struct ao_adc *packet)
 }
 
 void
-ao_adc_isr(void) interrupt 1
+ao_adc_isr(void) __interrupt 1
 {
        uint8_t sequence;
        uint8_t __xdata *a;
index 4a68fba49d56110b252a2896bc8041478c111171..a54a2316f006fb4a20909d430389413ac66922c1 100644 (file)
@@ -263,13 +263,12 @@ ao_cmd_register(__code struct ao_cmds *cmds)
 }
 
 void
-ao_cmd(void *parameters)
+ao_cmd(void)
 {
        __xdata char    c;
        __xdata uint8_t cmd, cmds;
        __code struct ao_cmds * __xdata cs;
        void (*__xdata func)(void);
-       (void) parameters;
 
        lex_echo = 1;
        for (;;) {
index 110138b56a42d5cfd50f19c3b3df673bff32d1da..946666abc6ff9993410fa7c155479c43c6a1e511 100644 (file)
@@ -112,7 +112,7 @@ ao_dma_abort(uint8_t id)
 }
 
 void
-ao_dma_isr(void) interrupt 8
+ao_dma_isr(void) __interrupt 8
 {
        uint8_t id, mask;
 
index cceb79ffeb82be0b03e72b73f53b3ca2cdb2db5c..7abc93f5d8e868cda3c5542a75b06a9e73846f4e 100644 (file)
@@ -51,12 +51,12 @@ ao_gps_report(void)
                gps_log.u.gps_altitude.unused = 0xffff;
                ao_log_data(&gps_log);
                if (!date_reported && (gps_data.flags & AO_GPS_DATE_VALID)) {
-                       date_reported = 1;
                        gps_log.type = AO_LOG_GPS_DATE;
                        gps_log.u.gps_date.year = gps_data.year;
                        gps_log.u.gps_date.month = gps_data.month;
                        gps_log.u.gps_date.day = gps_data.day;
-                       ao_log_data(&gps_log);
+                       gps_log.u.gps_date.extra = 0;
+                       date_reported = ao_log_data(&gps_log);
                }
        }
 }
index ae8c7ef7cafb1980d5cb08ffd541eac66d2f596c..c822f7fab57bf2125922f3fac5263369d74dcaf2 100644 (file)
@@ -422,6 +422,7 @@ gps_dump(void) __reentrant
        printf ("Time: %02d:%02d:%02d\n", ao_gps_data.hour, ao_gps_data.minute, ao_gps_data.second);
        printf ("Lat/Lon: %ld %ld\n", ao_gps_data.latitude, ao_gps_data.longitude);
        printf ("Alt: %d\n", ao_gps_data.altitude);
+       printf ("Flags: 0x%x\n", ao_gps_data.flags);
        ao_mutex_put(&ao_gps_mutex);
 }
 
index d550d40850cde2a8eef8b71c8d4828f7ea49306c..18bdb8c8d4f63cdca7b370d6c40cf0445322ffa7 100644 (file)
@@ -33,14 +33,16 @@ ao_log_csum(__xdata uint8_t *b) __reentrant
        return -sum;
 }
 
-void
+uint8_t
 ao_log_data(__xdata struct ao_log_record *log) __reentrant
 {
+       uint8_t wrote = 0;
        /* set checksum */
        log->csum = 0;
        log->csum = ao_log_csum((__xdata uint8_t *) log);
        ao_mutex_get(&ao_log_mutex); {
                if (ao_log_running) {
+                       wrote = 1;
                        ao_ee_write(ao_log_current_pos,
                                    (uint8_t *) log,
                                    sizeof (struct ao_log_record));
@@ -51,6 +53,7 @@ ao_log_data(__xdata struct ao_log_record *log) __reentrant
                                ao_log_running = 0;
                }
        } ao_mutex_put(&ao_log_mutex);
+       return wrote;
 }
 
 void
index f0eb4c07afc0e2286ced7324836d90da70d15060..82d6298f2dbe4751b6de6bd496ea6412f1c9a2d8 100644 (file)
@@ -28,7 +28,7 @@ const char ao_product[] = AO_iProduct_STRING;
 #define LE_WORD(x)    ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8))
 
 /* USB descriptors in one giant block of bytes */
-const uint8_t ao_usb_descriptors [] =
+__code __at(0x00aa) uint8_t ao_usb_descriptors [] =
 {
        /* Device descriptor */
        0x12,
index 0849349edb1d10a59208aebad7929c523da414f4..f4a9d3b265edb1a82ea37ee95cac9568022da9c6 100644 (file)
@@ -275,7 +275,7 @@ __xdata uint8_t ao_radio_done;
 __xdata uint8_t ao_radio_mutex;
 
 void
-ao_radio_general_isr(void) interrupt 16
+ao_radio_general_isr(void) __interrupt 16
 {
        S1CON &= ~0x03;
        if (RFIF & RFIF_IM_TIMEOUT) {
index 3f10376658cb10d02d627a9eed6c5b42be24b1c7..a48734c2f22793a957fb9575f6f5d0d2e0d21c26 100644 (file)
@@ -21,7 +21,7 @@ volatile __xdata struct ao_fifo       ao_usart1_rx_fifo;
 volatile __xdata struct ao_fifo        ao_usart1_tx_fifo;
 
 void
-ao_serial_rx1_isr(void) interrupt 3
+ao_serial_rx1_isr(void) __interrupt 3
 {
        if (!ao_fifo_full(ao_usart1_rx_fifo))
                ao_fifo_insert(ao_usart1_rx_fifo, U1DBUF);
@@ -42,7 +42,7 @@ ao_serial_tx1_start(void)
 }
 
 void
-ao_serial_tx1_isr(void) interrupt 14
+ao_serial_tx1_isr(void) __interrupt 14
 {
        UTX1IF = 0;
        ao_serial_tx1_started = 0;
index d1731475c226eee9992ae00315c333b1877f2285..c977fbc8b85a2f997c38e48df05f857306bac658 100644 (file)
@@ -41,7 +41,7 @@ volatile __data uint8_t       ao_adc_interval = 1;
 volatile __data uint8_t        ao_adc_count;
 #endif
 
-void ao_timer_isr(void) interrupt 9
+void ao_timer_isr(void) __interrupt 9
 {
        ++ao_tick_count;
 #if HAS_ADC
index f6e0fcf91b54e83e643b46eeec599f5dacce06db..b55130f2b73366dff311d0130133eb5b5b05ddc3 100644 (file)
@@ -43,7 +43,7 @@ ao_usb_set_interrupts(void)
  * so when we hook that up, fix this
  */
 void
-ao_usb_isr(void) interrupt 6
+ao_usb_isr(void) __interrupt 6
 {
        USBIF = 0;
        ao_usb_iif |= USBIIF;
index e8302df240736848d8800d84f111c77eba15170c..20ed052a1d5cf600dd1eabd7c6078b9542cc0781 100644 (file)
 #include <cc1110.h>
 #include <stdint.h>
 
-sfr at 0xA8 IEN0;              /* Interrupt Enable 0 Register */
+sfr __at 0xA8 IEN0;            /* Interrupt Enable 0 Register */
 
-sbit at 0xA8 RFTXRXIE;         /* RF TX/RX done interrupt enable */
-sbit at 0xA9 ADCIE;            /* ADC interrupt enable */
-sbit at 0xAA URX0IE;           /* USART0 RX interrupt enable */
-sbit at 0xAB URX1IE;           /* USART1 RX interrupt enable (shared with I2S RX) */
-sbit at 0xAB I2SRXIE;          /* I2S RX interrupt enable (shared with USART1 RX) */
-sbit at 0xAC ENCIE;            /* AES encryption/decryption interrupt enable */
-sbit at 0xAD STIE;             /* Sleep Timer interrupt enable */
-sbit at 0xAF EA;               /* Enable All */
+sbit __at 0xA8 RFTXRXIE;       /* RF TX/RX done interrupt enable */
+sbit __at 0xA9 ADCIE;          /* ADC interrupt enable */
+sbit __at 0xAA URX0IE;         /* USART0 RX interrupt enable */
+sbit __at 0xAB URX1IE;         /* USART1 RX interrupt enable (shared with I2S RX) */
+sbit __at 0xAB I2SRXIE;                /* I2S RX interrupt enable (shared with USART1 RX) */
+sbit __at 0xAC ENCIE;          /* AES encryption/decryption interrupt enable */
+sbit __at 0xAD STIE;           /* Sleep Timer interrupt enable */
+sbit __at 0xAF EA;             /* Enable All */
 
 #define IEN0_EA                        (1 << 7)
 #define IEN0_STIE              (1 << 5)
@@ -60,7 +60,7 @@ sbit at 0xAF EA;              /* Enable All */
 #define IEN0_ADCIE             (1 << 1)
 #define IEN0_RFTXRXIE          (1 << 0)
 
-sfr at 0xB8 IEN1;              /* Interrupt Enable 1 Register */
+sfr __at 0xB8 IEN1;            /* Interrupt Enable 1 Register */
 
 #define IEN1_P0IE              (1 << 5)        /* Port 0 interrupt enable */
 #define IEN1_T4IE              (1 << 4)        /* Timer 4 interrupt enable */
@@ -70,7 +70,7 @@ sfr at 0xB8 IEN1;             /* Interrupt Enable 1 Register */
 #define IEN1_DMAIE             (1 << 0)        /* DMA transfer interrupt enable */
 
 /* IEN2 */
-sfr at 0x9A IEN2;              /* Interrupt Enable 2 Register */
+sfr __at 0x9A IEN2;            /* Interrupt Enable 2 Register */
 
 #define IEN2_WDTIE             (1 << 5)        /* Watchdog timer interrupt enable */
 #define IEN2_P1IE              (1 << 4)        /* Port 1 interrupt enable */
@@ -82,7 +82,7 @@ sfr at 0x9A IEN2;             /* Interrupt Enable 2 Register */
 #define IEN2_RFIE              (1 << 0)        /* RF general interrupt enable */
 
 /* CLKCON 0xC6 */
-sfr at 0xC6 CLKCON;            /* Clock Control */
+sfr __at 0xC6 CLKCON;          /* Clock Control */
 
 #define CLKCON_OSC32K_RC       (1 << 7)
 #define CLKCON_OSC32K_XTAL     (0 << 7)
@@ -126,20 +126,20 @@ sfr at 0xC6 CLKCON;               /* Clock Control */
 #define SLEEP_MODE_MASK                (3 << 0)
 
 /* PCON 0x87 */
-sfr at 0x87 PCON;              /* Power Mode Control Register */
+sfr __at 0x87 PCON;            /* Power Mode Control Register */
 
 #define PCON_IDLE              (1 << 0)
 
 /*
  * TCON
  */
-sfr at 0x88 TCON;      /* CPU Interrupt Flag 1 */
+sfr __at 0x88 TCON;            /* CPU Interrupt Flag 1 */
 
-sbit at 0x8F URX1IF;   /* USART1 RX interrupt flag. Automatically cleared */
-sbit at 0x8F I2SRXIF;  /* I2S RX interrupt flag. Automatically cleared */
-sbit at 0x8D ADCIF;    /* ADC interrupt flag. Automatically cleared */
-sbit at 0x8B URX0IF;   /* USART0 RX interrupt flag. Automatically cleared */
-sbit at 0x89 RFTXRXIF; /* RF TX/RX complete interrupt flag. Automatically cleared */
+sbit __at 0x8F URX1IF;         /* USART1 RX interrupt flag. Automatically cleared */
+sbit __at 0x8F I2SRXIF;                /* I2S RX interrupt flag. Automatically cleared */
+sbit __at 0x8D ADCIF;          /* ADC interrupt flag. Automatically cleared */
+sbit __at 0x8B URX0IF;         /* USART0 RX interrupt flag. Automatically cleared */
+sbit __at 0x89 RFTXRXIF;       /* RF TX/RX complete interrupt flag. Automatically cleared */
 
 #define TCON_URX1IF    (1 << 7)
 #define TCON_I2SRXIF   (1 << 7)
@@ -150,10 +150,10 @@ sbit at 0x89 RFTXRXIF;    /* RF TX/RX complete interrupt flag. Automatically cleare
 /*
  * S0CON
  */
-sfr at 0x98 S0CON;     /* CPU Interrupt Flag 2 */
+sfr __at 0x98 S0CON;   /* CPU Interrupt Flag 2 */
 
-sbit at 0x98 ENCIF_0;  /* AES interrupt 0. */
-sbit at 0x99 ENCIF_1;  /* AES interrupt 1. */
+sbit __at 0x98 ENCIF_0;        /* AES interrupt 0. */
+sbit __at 0x99 ENCIF_1;        /* AES interrupt 1. */
 
 #define S0CON_ENCIF_1  (1 << 1)
 #define S0CON_ENCIF_0  (1 << 0)
@@ -161,7 +161,7 @@ sbit at 0x99 ENCIF_1;       /* AES interrupt 1. */
 /*
  * S1CON
  */
-sfr at 0x9B S1CON;     /* CPU Interrupt Flag 3 */
+sfr __at 0x9B S1CON;   /* CPU Interrupt Flag 3 */
 
 #define S1CON_RFIF_1   (1 << 1)
 #define S1CON_RFIF_0   (1 << 0)
@@ -169,15 +169,15 @@ sfr at 0x9B S1CON;        /* CPU Interrupt Flag 3 */
 /*
  * IRCON
  */
-sfr at 0xC0 IRCON;     /* CPU Interrupt Flag 4 */
+sfr __at 0xC0 IRCON;   /* CPU Interrupt Flag 4 */
 
-sbit at 0xC0 DMAIF;    /* DMA complete interrupt flag */
-sbit at 0xC1 T1IF;     /* Timer 1 interrupt flag. Automatically cleared */
-sbit at 0xC2 T2IF;     /* Timer 2 interrupt flag. Automatically cleared */
-sbit at 0xC3 T3IF;     /* Timer 3 interrupt flag. Automatically cleared */
-sbit at 0xC4 T4IF;     /* Timer 4 interrupt flag. Automatically cleared */
-sbit at 0xC5 P0IF;     /* Port0 interrupt flag */
-sbit at 0xC7 STIF;     /* Sleep Timer interrupt flag */
+sbit __at 0xC0 DMAIF;  /* DMA complete interrupt flag */
+sbit __at 0xC1 T1IF;   /* Timer 1 interrupt flag. Automatically cleared */
+sbit __at 0xC2 T2IF;   /* Timer 2 interrupt flag. Automatically cleared */
+sbit __at 0xC3 T3IF;   /* Timer 3 interrupt flag. Automatically cleared */
+sbit __at 0xC4 T4IF;   /* Timer 4 interrupt flag. Automatically cleared */
+sbit __at 0xC5 P0IF;   /* Port0 interrupt flag */
+sbit __at 0xC7 STIF;   /* Sleep Timer interrupt flag */
 
 #define IRCON_DMAIF    (1 << 0)        /* DMA complete interrupt flag */
 #define IRCON_T1IF     (1 << 1)        /* Timer 1 interrupt flag. Automatically cleared */
@@ -190,15 +190,15 @@ sbit at 0xC7 STIF;        /* Sleep Timer interrupt flag */
 /*
  * IRCON2
  */
-sfr at 0xE8 IRCON2;    /* CPU Interrupt Flag 5 */
+sfr __at 0xE8 IRCON2;  /* CPU Interrupt Flag 5 */
 
-sbit at 0xE8 USBIF;    /* USB interrupt flag (shared with Port2) */
-sbit at 0xE8 P2IF;     /* Port2 interrupt flag (shared with USB) */
-sbit at 0xE9 UTX0IF;   /* USART0 TX interrupt flag */
-sbit at 0xEA UTX1IF;   /* USART1 TX interrupt flag (shared with I2S TX) */
-sbit at 0xEA I2STXIF;  /* I2S TX interrupt flag (shared with USART1 TX) */
-sbit at 0xEB P1IF;     /* Port1 interrupt flag */
-sbit at 0xEC WDTIF;    /* Watchdog timer interrupt flag */
+sbit __at 0xE8 USBIF;  /* USB interrupt flag (shared with Port2) */
+sbit __at 0xE8 P2IF;   /* Port2 interrupt flag (shared with USB) */
+sbit __at 0xE9 UTX0IF; /* USART0 TX interrupt flag */
+sbit __at 0xEA UTX1IF; /* USART1 TX interrupt flag (shared with I2S TX) */
+sbit __at 0xEA I2STXIF;        /* I2S TX interrupt flag (shared with USART1 TX) */
+sbit __at 0xEB P1IF;   /* Port1 interrupt flag */
+sbit __at 0xEC WDTIF;  /* Watchdog timer interrupt flag */
 
 #define IRCON2_USBIF   (1 << 0)        /* USB interrupt flag (shared with Port2) */
 #define IRCON2_P2IF    (1 << 0)        /* Port2 interrupt flag (shared with USB) */
@@ -225,8 +225,8 @@ sbit at 0xEC WDTIF; /* Watchdog timer interrupt flag */
  * Priority = (IP1 << 1) | IP0. Higher priority interrupts served first
  */
 
-sfr at 0xB9 IP1;       /* Interrupt Priority 1 */
-sfr at 0xA9 IP0;       /* Interrupt Priority 0 */
+sfr __at 0xB9 IP1;     /* Interrupt Priority 1 */
+sfr __at 0xA9 IP0;     /* Interrupt Priority 0 */
 
 #define IP1_IPG5       (1 << 5)
 #define IP1_IPG4       (1 << 4)
@@ -286,13 +286,13 @@ sfr at 0xA9 IP0;  /* Interrupt Priority 0 */
  */
 
 /* Timer count */
-sfr at 0xCA T3CNT;
-sfr at 0xEA T4CNT;
+sfr __at 0xCA T3CNT;
+sfr __at 0xEA T4CNT;
 
 /* Timer control */
 
-sfr at 0xCB T3CTL;
-sfr at 0xEB T4CTL;
+sfr __at 0xCB T3CTL;
+sfr __at 0xEB T4CTL;
 
 #define TxCTL_DIV_1            (0 << 5)
 #define TxCTL_DIV_2            (1 << 5)
@@ -312,10 +312,10 @@ sfr at 0xEB T4CTL;
 
 /* Timer 4 channel 0 compare control */
 
-sfr at 0xCC T3CCTL0;
-sfr at 0xCE T3CCTL1;
-sfr at 0xEC T4CCTL0;
-sfr at 0xEE T4CCTL1;
+sfr __at 0xCC T3CCTL0;
+sfr __at 0xCE T3CCTL1;
+sfr __at 0xEC T4CCTL0;
+sfr __at 0xEE T4CCTL1;
 
 #define TxCCTLy_IM                     (1 << 6)
 #define TxCCTLy_CMP_SET                        (0 << 3)
@@ -328,16 +328,16 @@ sfr at 0xEE T4CCTL1;
 #define TxCCTLy_CMP_MODE_ENABLE                (1 << 2)
 
 /* Timer compare value */
-sfr at 0xCD T3CC0;
-sfr at 0xCF T3CC1;
-sfr at 0xED T4CC0;
-sfr at 0xEF T4CC1;
+sfr __at 0xCD T3CC0;
+sfr __at 0xCF T3CC1;
+sfr __at 0xED T4CC0;
+sfr __at 0xEF T4CC1;
 
 /*
  * Peripheral control
  */
 
-sfr at 0xf1 PERCFG;
+sfr __at 0xf1 PERCFG;
 #define PERCFG_T1CFG_ALT_1      (0 << 6)
 #define PERCFG_T1CFG_ALT_2      (1 << 6)
 #define PERCFG_T1CFG_ALT_MASK   (1 << 6)