Merge branch 'branch-1.8' into debian
authorBdale Garbee <bdale@gag.com>
Tue, 19 Sep 2017 02:46:47 +0000 (20:46 -0600)
committerBdale Garbee <bdale@gag.com>
Tue, 19 Sep 2017 02:46:47 +0000 (20:46 -0600)
50 files changed:
.gitignore
ChangeLog
Makefile.am
Releasing
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java
altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java
altoslib/AltosAccelCal.java [new file with mode: 0644]
altoslib/AltosAccelCalListener.java [new file with mode: 0644]
altoslib/AltosConfigData.java
altoslib/AltosConfigValues.java
altoslib/AltosDataListener.java
altoslib/AltosFlightStats.java
altoslib/AltosLink.java
altoslib/AltosState.java
altoslib/AltosTelemetry.java
altoslib/AltosTimeSeries.java
altoslib/Makefile.am
altosui/AltosConfigFC.java
altosui/AltosConfigFCUI.java
altosui/AltosGraphUI.java
altosui/Makefile.am
altosuilib/AltosUIAccelCal.java [new file with mode: 0644]
altosuilib/Makefile.am
ao-bringup/test-telegps [deleted file]
ao-bringup/test-telegps-v1 [new file with mode: 0755]
ao-bringup/test-telegps-v2 [new file with mode: 0755]
ao-bringup/turnon_telebt
ao-bringup/turnon_telegps
ao-bringup/turnon_telegps_v1 [new file with mode: 0755]
ao-tools/ao-chaosread/Makefile.am
ao-tools/ao-chaosread/ao-chaosread.c
configure.ac
doc/Makefile
doc/altusmetrum-docinfo.xml
doc/config-device.inc
doc/release-notes-1.8.2.inc [new file with mode: 0644]
doc/release-notes.inc
doc/usage.inc
micropeak/Makefile.am
src/Makefile
src/drivers/ao_trng_send.c
src/kernel/ao_pyro.c
src/telegps-v2.0/ao_pins.h
src/test/Makefile
src/test/ao_eeprom_read.c [new file with mode: 0644]
src/test/ao_eeprom_read.h [new file with mode: 0644]
src/test/ao_eeprom_read_old.c [new file with mode: 0644]
src/test/ao_flight_test.c
telegps/Makefile.am
telegps/TeleGPSConfigUI.java

index 7b424a8da182e2fcb86140abe0581d3a62cdc319..18d642daaa8ff5de713a068df9d2334fa3289fa3 100644 (file)
@@ -7,6 +7,7 @@
 *.lnk
 *.lst
 *.map
+*.mdwn
 *.mem
 *.o
 *.rel
index 94cb587509ff8a4274079c4f1ec8265bf4dcc521..9c73f88d6ea572ba53fbee2d0ccfa20d7b0e2d62 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,258 @@
+commit 1ece6e6fd3faaae3f6c6d434497eb04235939dc3
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Mon Sep 18 20:43:14 2017 -0600
+
+    be more aggressive about removing and ignoring .mdwn files
+
+commit b12e982259817328e348f1aaa91c5c824891e7b9
+Merge: b1cf0dab e87d56b6
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Mon Sep 18 20:35:00 2017 -0600
+
+    Merge branch 'master' into branch-1.8
+
+commit e87d56b665ca30a3e5920c23cd60c99b84341aa2
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Sep 18 18:51:51 2017 -0700
+
+    Update release version and date
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a54b3330574dd130540e482a06a3f8d7ca652b6c
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Sep 18 18:43:00 2017 -0700
+
+    Update docs for 1.8.2 release
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d0c1ebc43a9c5bb0a3503d33978a5e7bc87057fe
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Sep 18 18:51:18 2017 -0700
+
+    Add short section on accelerometer calibration
+
+commit 60cadbc85949adf464be16a5cf8ce2c24d67bedf
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Sep 18 14:40:37 2017 -0700
+
+    altos/telegps-v2.0: Enable USB connect monitoring
+    
+    Disable radios when plugged in to USB to save power and avoid being
+    noisy.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6e4c104c28952f2010c7b1cbc9ce59e148ab2d8f
+Merge: 63eeaada 4f2cbe0c
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Mon Sep 18 16:01:43 2017 -0600
+
+    Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos
+
+commit 63eeaada85cb9ddccb0fa9b2d751cc8f46399d9c
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Mon Sep 18 16:01:21 2017 -0600
+
+    production TeleGPS v2.0 use a 16Mhz crystal for the SOC
+
+commit 4f2cbe0c537c9f417aae310cc3b89f84e0915103
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Sep 18 09:57:41 2017 -0700
+
+    altoslib: Avoid crashing when computing stats for empty flight logs
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b9a00856aa4cf55ae4a143288058094ef8061134
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Sep 18 09:57:06 2017 -0700
+
+    telegps: Fix up TeleGPS UI bits after accel cal changes
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 95952059bbb50b5f22460418df003a87c8bd3271
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Sep 12 15:47:43 2017 -0700
+
+    test/ao_flight_test: Show recorded pyro firing
+    
+    Can compare with computed values.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 28a2db68e4806383cfaa7075d454c35cade9633a
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Sun Sep 17 12:41:50 2017 -0600
+
+    publish support for TeleGPS v2.0
+
+commit ad61e277069217d98400e884d3c173357d2343ed
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Thu Sep 14 10:51:18 2017 -0600
+
+    deal with cheap BT dongle that shows multiple copies of unit in lescan output
+
+commit 5666a3c9427324ad8f92e21c5f9017436b36a82a
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Sep 12 14:02:11 2017 -0700
+
+    altosuilib: Make steps in accel cal default button
+    
+    This way you can just hit return through the process.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 441056b01abcf9287f61f425cf29fc4b1603c619
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Sep 12 13:43:06 2017 -0700
+
+    altos/test: Handle new eeprom file format. Give up on telem files.
+    
+    Parse eeprom config using libjson-c, then read the hex values into a
+    giant blob.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit be44d33f5e94b8c4180adb275ec83cc70852db48
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Sep 12 13:41:11 2017 -0700
+
+    altos: Fix debug printf in ao_pyro for state >=
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 10d14146ef84fbe4670454bc0996854a4066cfea
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Sep 12 13:40:06 2017 -0700
+
+    chaoskey: Wait for input data to stabilize before using it
+    
+    The ADC data takes a while to start working after power on; wait for
+    the range of input values to look reasonable before using the data.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8284ba8bf78aade8f9d8f711cfefe2010ce81066
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Sep 12 13:38:36 2017 -0700
+
+    doc: Add forward reference from 'idle' description to idle entry steps.
+    
+    This provides a reminder that entering idle mode takes specific steps
+    which differ between models.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8960cb525ef43c2262c7854b9a6f08237b3ea05b
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Sep 12 13:37:24 2017 -0700
+
+    altosui: Handle missing GPS when graphing mega/metrum data
+    
+    These have GPS, but if we never get a valid packet, then there won't
+    be any final position to display.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a4dfaf25954134dbdc7229e2de39d4a4c049f285
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Sep 12 13:37:06 2017 -0700
+
+    altosui: Remove debug printfs in FC config UI
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit bc1cc0db1251e351d862dffbf618d0ce926c389d
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Sep 12 13:36:24 2017 -0700
+
+    altosdroid: Display serial, call, freq in tracker list
+    
+    This makes the list a lot easier to find entries in when it gets long.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4151c30e1294c0dda3aa02e7ac23b9616f25a4d0
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Sep 12 13:35:25 2017 -0700
+
+    altoslib: Make receive frequency available in telem data
+    
+    This lets AltosDroid record which frequency each station was heard on.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d84f5e576e83a2b965d0e9752a9bbef100954815
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Sep 12 13:34:23 2017 -0700
+
+    altoslib: Remove debug stack dump from AltosState
+    
+    An empty AltosState is allocated when parsing JSON data; it's not a
+    mistake.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b48966c3121e1b5d4a659bebcad595d6f1ec5ee5
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Sep 12 13:33:13 2017 -0700
+
+    altoslib: Correctly parse IMU cal data
+    
+    Was trying to match 'IMU call along' instead of 'IMU cal along',
+    causing the line to not match and losing the IMU accel cal values.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f607a882a50aa6cd9e8e3e74cbaa5bcc1b5fa4a4
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Sep 6 08:37:12 2017 -0600
+
+    ao-tools/ao-chaosread: Add -Wall -Wextra, clean up results
+
+commit 558a143315f0345b79cc4f22aa4b643fedcded9c
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Aug 11 23:42:53 2017 -0400
+
+    altosui: Accel calibration UI
+    
+    Provides a GUI for re-calibrating accelerometers
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c9a742db2497d07079f3d4bf383c6246cf80507c
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Aug 31 20:32:05 2017 -0700
+
+    Bump to version 1.8.1.1/android 16 for altosdroid
+    
+    AltosDroid 1.8.1 got released before the latest fix for not storing
+    frequency preferences was made. Make a 1.8.1.1 with a new android
+    release number for that.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6e85a8244389bffab0744be8dfa90b706f829083
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Mon Aug 28 15:09:14 2017 -0600
+
+    need to capture .bin file for telebt-v4.0 loader
+
+commit ccf7ad5a31604e98b34bf16e3da6afb264ad1291
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Mon Aug 28 14:01:54 2017 -0600
+
+    a few tweaks to the Releasing document based on experience with 1.8.1
+
+commit b1cf0dab1e28433e06ab02cec033951ea0149ea3
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Mon Aug 28 12:05:17 2017 -0600
+
+    releasing 1.8.1
+
 commit b68c0482d4fae8eb54cde1df0e4bcf4c5d272bad
 Author: Keith Packard <keithp@keithp.com>
 Date:   Sun Aug 27 22:49:09 2017 -0700
index cac02c62763333c4dda23d4e249b1f614665c24a..4f47417eccf00c9bc5846d97a4847339ab366664 100644 (file)
@@ -64,6 +64,7 @@ fat_altos = \
        src/teledongle-v0.2/teledongle-v0.2-$(VERSION).ihx \
        src/teledongle-v3.0/teledongle-v3.0-$(VERSION).ihx \
        src/telegps-v1.0/telegps-v1.0-$(VERSION).ihx \
+       src/telegps-v2.0/telegps-v2.0-$(VERSION).ihx \
        src/telemega-v1.0/telemega-v1.0-$(VERSION).ihx \
        src/telemega-v2.0/telemega-v2.0-$(VERSION).ihx \
        src/telemetrum-v1.0/telemetrum-v1.0-$(VERSION).ihx \
index 5780f3ce2778ce4e9318d58259cf083df3b548d8..8af50a1e7b385637261c86a40baf3d010284698c 100644 (file)
--- a/Releasing
+++ b/Releasing
@@ -95,11 +95,8 @@ These are Bdale's notes on how to do a release.
                --with-fat-dir=/home/bdale/web/altusmetrum/
        make && make fat
 
-               this pushes packages for each platform and application
-               to web site, including auto-generated mdwn files and
-               release notes in html format.
+       - store a stable copy of ARM binaries for production use
 
-       # store a stable copy of ARM binaries for production use
        cp src/chaoskey-v1.0/{*.elf,*.ihx} \
           src/easymega-v1.0/{*.elf,*.ihx} \
           src/easymini-v1.0/{*.elf,*.ihx} \
@@ -108,6 +105,7 @@ These are Bdale's notes on how to do a release.
           src/telebt-v4.0/{*.elf,*.ihx} \
           src/teledongle-v3.0/{*.elf,*.ihx} \
           src/telegps-v1.0/{*.elf,*.ihx} \
+          src/telegps-v2.0/{*.elf,*.ihx} \
           src/telemega-v1.0/{*.elf,*.ihx} \
           src/telemega-v2.0/{*.elf,*.ihx} \
           src/telemetrum-v2.0/{*.elf,*.ihx} \
@@ -118,9 +116,10 @@ These are Bdale's notes on how to do a release.
           src/easymini-v1.0/flash-loader/*.elf \
           src/easymini-v2.0/flash-loader/{*.elf,*.bin} \
           src/telebt-v3.0/flash-loader/*.elf \
-          src/telebt-v4.0/flash-loader/*.elf \
+          src/telebt-v4.0/flash-loader/{*.elf,*.bin} \
           src/teledongle-v3.0/flash-loader/*.elf \
           src/telegps-v1.0/flash-loader/*.elf \
+          src/telegps-v2.0/flash-loader/*.elf \
           src/telemega-v1.0/flash-loader/*.elf \
           src/telemega-v2.0/flash-loader/*.elf \
           src/telemetrum-v2.0/flash-loader/*.elf \
@@ -129,26 +128,23 @@ These are Bdale's notes on how to do a release.
        (cd ~/altusmetrumllc ; git add Binaries ; git commit -a) 
        (cd ~/altusmetrumllc ; git push) 
 
-       - copy the relevant release notes .html file from doc/ to 
-           /home/bdale/web/altusmetrum/AltOS/releases/<rev>
-
        - Push new release to web site
 
        make fat-install
        (cd doc ; make publish)
 
-       (cd ~/web/altusmetrum/ && git add AltOS/releases
-       TeleGPS/releases MicroPeak/releases && git commit -m'Release
-       <rev>' && git push origin master)
+       (cd ~/web/altusmetrum/ && \
+               git add */releases && git commit -m'Release <rev>' && \
+               git push origin master)
+
+       - upload the Debian package 
 
-               this pushes fresh documents to the web site
+       - clean up
 
        sudo debian/rules clean
        git push origin master branch-<version> debian pristine-tar
        git push --tags
 
-               push commits and leave the build tree in an uncluttered state
-
 Testing before a release
 
        To verify that a build works, the following need to be checked
index 924ab4c9350a4564bdcb532b04e47777ead16bef..0776fa0027fb382270e06107657341e20935f3ed 100644 (file)
@@ -77,6 +77,75 @@ class SavedState {
        }
 }
 
+class Tracker implements CharSequence, Comparable {
+       int     serial;
+       String  call;
+       double  frequency;
+
+       String  display;
+
+       public Tracker(int serial, String call, double frequency) {
+               if (call == null)
+                       call = "none";
+
+               this.serial = serial;
+               this.call = call;
+               this.frequency = frequency;
+               if (frequency == 0.0)
+                       display = "Auto";
+               else if (frequency == AltosLib.MISSING) {
+                       display = String.format("%-8.8s  %6d", call, serial);
+               } else {
+                       display = String.format("%-8.8s %7.3f %6d", call, frequency, serial);
+               }
+       }
+
+       public Tracker(AltosState s) {
+               this(s == null ? 0 : s.cal_data().serial,
+                    s == null ? null : s.cal_data().callsign,
+                    s == null ? 0.0 : s.frequency);
+       }
+
+       /* CharSequence */
+       public char charAt(int index) {
+               return display.charAt(index);
+       }
+
+       public int length() {
+               return display.length();
+       }
+
+       public CharSequence subSequence(int start, int end) throws IndexOutOfBoundsException {
+               return display.subSequence(start, end);
+       }
+
+       public String toString() {
+               return display.toString();
+       }
+
+       /* Comparable */
+       public int compareTo (Object other) {
+               Tracker o = (Tracker) other;
+               if (frequency == 0.0) {
+                       if (o.frequency == 0.0)
+                               return 0;
+                       return -1;
+               }
+               if (o.frequency == 0.0)
+                       return 1;
+
+               int     a = serial - o.serial;
+               int     b = call.compareTo(o.call);
+               int     c = (int) Math.signum(frequency - o.frequency);
+
+               if (b != 0)
+                       return b;
+               if (c != 0)
+                       return c;
+               return a;
+       }
+}
+
 public class AltosDroid extends FragmentActivity implements AltosUnitsListener, LocationListener {
 
        // Actions sent to the telemetry server at startup time
@@ -151,7 +220,8 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,
        private Timer timer;
 
        TelemetryState  telemetry_state;
-       Integer[]       serials;
+       Tracker[]       trackers;
+
 
        UsbDevice       pending_usb_device;
        boolean         start_with_usb;
@@ -323,8 +393,20 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,
                        AltosPreferences.register_units_listener(this);
                }
 
-               serials = telemetry_state.states.keySet().toArray(new Integer[0]);
-               Arrays.sort(serials);
+               int     num_trackers = 0;
+               for (AltosState s : telemetry_state.states.values()) {
+                       num_trackers++;
+               }
+
+               trackers = new Tracker[num_trackers + 1];
+
+               int n = 0;
+               trackers[n++] = new Tracker(0, "auto", 0.0);
+
+               for (AltosState s : telemetry_state.states.values())
+                       trackers[n++] = new Tracker(s);
+
+               Arrays.sort(trackers);
 
                update_title(telemetry_state);
 
@@ -955,11 +1037,11 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,
                }
 
                if (serial != 0) {
-                       for (i = 0; i < serials.length; i++)
-                               if (serials[i] == serial)
+                       for (i = 0; i < trackers.length; i++)
+                               if (trackers[i].serial == serial)
                                        break;
 
-                       if (i == serials.length) {
+                       if (i == trackers.length) {
                                AltosDebug.debug("attempt to select unknown tracker %d\n", serial);
                                return;
                        }
@@ -972,17 +1054,22 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,
        void touch_trackers(Integer[] serials) {
                AlertDialog.Builder builder_tracker = new AlertDialog.Builder(this);
                builder_tracker.setTitle("Select Tracker");
-               final String[] trackers = new String[serials.length + 1];
-               trackers[0] = "Auto";
-               for (int i = 0; i < serials.length; i++)
-                       trackers[i+1] = String.format("%d", serials[i]);
-               builder_tracker.setItems(trackers,
+
+               final Tracker[] my_trackers = new Tracker[serials.length + 1];
+
+               my_trackers[0] = new Tracker(null);
+
+               for (int i = 0; i < serials.length; i++) {
+                       AltosState      s = telemetry_state.states.get(serials[i]);
+                       my_trackers[i+1] = new Tracker(s);
+               }
+               builder_tracker.setItems(my_trackers,
                                         new DialogInterface.OnClickListener() {
                                                 public void onClick(DialogInterface dialog, int item) {
                                                         if (item == 0)
                                                                 select_tracker(0);
                                                         else
-                                                                select_tracker(Integer.parseInt(trackers[item]));
+                                                                select_tracker(my_trackers[item].serial);
                                                 }
                                         });
                AlertDialog alert_tracker = builder_tracker.create();
@@ -1040,20 +1127,17 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,
                        alert_freq.show();
                        return true;
                case R.id.select_tracker:
-                       if (serials != null) {
-                               String[] trackers = new String[serials.length+1];
-                               trackers[0] = "Auto";
-                               for (int i = 0; i < serials.length; i++)
-                                       trackers[i+1] = String.format("%d", serials[i]);
+                       if (trackers != null) {
                                AlertDialog.Builder builder_serial = new AlertDialog.Builder(this);
                                builder_serial.setTitle("Select a tracker");
                                builder_serial.setItems(trackers,
                                                        new DialogInterface.OnClickListener() {
                                                                public void onClick(DialogInterface dialog, int item) {
+                                                                       System.out.printf("select item %d %s\n", item, trackers[item].display);
                                                                        if (item == 0)
                                                                                select_tracker(0);
                                                                        else
-                                                                               select_tracker(serials[item-1]);
+                                                                               select_tracker(trackers[item].serial);
                                                                }
                                                        });
                                AlertDialog alert_serial = builder_serial.create();
@@ -1062,16 +1146,16 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,
                        }
                        return true;
                case R.id.delete_track:
-                       if (serials != null) {
-                               String[] trackers = new String[serials.length];
-                               for (int i = 0; i < serials.length; i++)
-                                       trackers[i] = String.format("%d", serials[i]);
+                       if (trackers != null) {
                                AlertDialog.Builder builder_serial = new AlertDialog.Builder(this);
                                builder_serial.setTitle("Delete a track");
-                               builder_serial.setItems(trackers,
+                               final Tracker[] my_trackers = new Tracker[trackers.length - 1];
+                               for (int i = 0; i < trackers.length - 1; i++)
+                                       my_trackers[i] = trackers[i+1];
+                               builder_serial.setItems(my_trackers,
                                                        new DialogInterface.OnClickListener() {
                                                                public void onClick(DialogInterface dialog, int item) {
-                                                                       delete_track(serials[item]);
+                                                                       delete_track(my_trackers[item].serial);
                                                                }
                                                        });
                                AlertDialog alert_serial = builder_serial.create();
index d097a550953760958751d33b159161562af7eada..69685dc7a843010f994ceff365877dd8801f991c 100644 (file)
@@ -60,6 +60,7 @@ public class TelemetryReader extends Thread {
                        while (telemQueue != null) {
                                try {
                                        AltosTelemetry  telem = read();
+                                       telem.set_frequency(link.frequency);
                                        handler.obtainMessage(TelemetryService.MSG_TELEMETRY, telem).sendToTarget();
                                } catch (ParseException pp) {
                                        AltosDebug.error("Parse error: %d \"%s\"", pp.getErrorOffset(), pp.getMessage());
diff --git a/altoslib/AltosAccelCal.java b/altoslib/AltosAccelCal.java
new file mode 100644 (file)
index 0000000..03d9fbf
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ * Copyright Â© 2017 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.altusmetrum.altoslib_12;
+
+import java.io.*;
+import java.util.concurrent.*;
+
+public class AltosAccelCal implements Runnable {
+
+       AltosLink               link;
+       AltosAccelCalListener   listener;
+
+       boolean                 remote;
+       boolean                 close_on_exit;
+       double                  frequency;
+       String                  callsign;
+
+       Thread                  accel_thread;
+
+       AltosConfigData         config_data;
+
+       public static final int phase_antenna_up = 0;
+       public static final int phase_antenna_down = 1;
+
+       void start_link() throws InterruptedException, TimeoutException {
+               if (remote) {
+                       link.set_radio_frequency(frequency);
+                       link.set_callsign(callsign);
+                       link.start_remote();
+               } else
+                       link.flush_input();
+       }
+
+       boolean stop_link() throws InterruptedException, TimeoutException {
+               if (remote)
+                       link.stop_remote();
+               return link.reply_abort;
+       }
+
+       public void set_frequency(double in_frequency) {
+               frequency = in_frequency;
+               link.abort_reply();
+       }
+
+       public void set_callsign(String in_callsign) {
+               callsign = in_callsign;
+               link.abort_reply();
+       }
+
+       public void abort() throws InterruptedException {
+               while (accel_thread.isAlive()) {
+                       accel_thread.interrupt();
+                       link.abort_reply();
+                       Thread.sleep(100);
+               }
+               accel_thread.join();
+       }
+
+       static private final String press_msg = "press a key...";
+
+       private Semaphore ui_signal_semaphore;
+       private boolean ui_signal_reply;
+
+       public void signal(boolean reply) {
+               System.out.printf("Signal cal semaphore %b\n", reply);
+               ui_signal_reply = reply;
+               ui_signal_semaphore.release();
+       }
+
+       private boolean wait_signal() throws InterruptedException {
+               System.out.printf("\twait for cal signal...\n");
+               ui_signal_semaphore.acquire();
+               System.out.printf("\tgot cal signal %b\n", ui_signal_reply);
+               return ui_signal_reply;
+       }
+
+       private boolean wait_press(int timeout) throws InterruptedException {
+               for (;;) {
+                       String line = link.get_reply(timeout);
+                       if (line == null) {
+                               System.out.printf("get_reply timeout\n");
+                               return false;
+                       }
+                       System.out.printf("got line %s\n", line);
+                       if (line.contains(press_msg))
+                               return true;
+                       if (line.contains("Invalid"))
+                               return false;
+                       if (line.contains("Syntax"))
+                               return false;
+                       if (line.contains("Calibrating"))
+                               listener.message(this, line);
+               }
+       }
+
+       static final int cal_timeout = 20 * 1000;
+
+       public void run() {
+               System.out.printf("start accel cal procedure\n");
+               try {
+                       AltosConfigData new_config = null;
+
+                       try {
+                               start_link();
+                               config_data = link.config_data();
+
+                               /* set back to antenna up for calibration */
+                               if (config_data.pad_orientation != 0)
+                                       link.printf("c o 0\n");
+
+                               /* Start calibration */
+                               try {
+                                       System.out.printf("*** start cal\n");
+                                       link.set_match(press_msg);
+                                       link.printf("c a 0\n");
+                                       System.out.printf("*** wait press\n");
+                                       if (!wait_press(cal_timeout))
+                                               throw new TimeoutException("timeout");
+                                       System.out.printf("*** set_phase antenna_up\n");
+                                       listener.set_phase(this, phase_antenna_up);
+                                       System.out.printf("*** wait_signal\n");
+                                       if (!wait_signal())
+                                               throw new InterruptedException("aborted");
+                                       link.set_match(press_msg);
+                                       System.out.printf("*** send newline\n");
+                                       link.printf("\n");
+                                       System.out.printf("*** wait press\n");
+                                       if (!wait_press(cal_timeout))
+                                               throw new TimeoutException("timeout");
+                                       System.out.printf("***set_phase antenna_down\n");
+                                       listener.set_phase(this, phase_antenna_down);
+                                       System.out.printf("*** wait_signal\n");
+                                       if (!wait_signal())
+                                               throw new InterruptedException("aborted");
+                                       System.out.printf("*** send newline and version command\n");
+                                       link.printf("\nv\n");
+                               } catch (TimeoutException e) {
+                                       throw e;
+                               } catch (InterruptedException e) {
+                                       throw e;
+                               }
+                               link.set_match(null);
+
+                               boolean worked = true;
+                               for (;;) {
+                                       String line = link.get_reply(cal_timeout);
+                                       if (line == null)
+                                               throw new TimeoutException();
+                                       System.out.printf("*** waiting for finish: %s\n", line);
+                                       if (line.contains("Invalid"))
+                                               worked = false;
+                                       if (line.contains("software-version"))
+                                               break;
+                                       if (line.contains("Calibrating"))
+                                               listener.message(this, line);
+                               }
+                               System.out.printf("*** worked: %b\n", worked);
+                               if (worked)
+                                       new_config = new AltosConfigData(link);
+                       } finally {
+                               System.out.printf("Restore orientation %d +g %d -g %d\n",
+                                                 config_data.pad_orientation,
+                                                 config_data.accel_cal_plus,
+                                                 config_data.accel_cal_minus);
+                               if (config_data.pad_orientation != AltosLib.MISSING && config_data.pad_orientation != 0)
+                                       link.printf("c o %d\n", config_data.pad_orientation);
+                               if (config_data.accel_cal_plus != AltosLib.MISSING && config_data.accel_cal_minus != AltosLib.MISSING)
+                                       link.printf("c a %d %d\n",
+                                                   config_data.accel_cal_plus, config_data.accel_cal_minus);
+                               stop_link();
+                       }
+                       if (new_config != null) {
+                               System.out.printf("*** +1g %d -1g %d\n",
+                                                 new_config.accel_cal_plus,
+                                                 new_config.accel_cal_minus);
+                               listener.cal_done(this, new_config.accel_cal_plus, new_config.accel_cal_minus);
+                               if (!wait_signal())
+                                       throw new InterruptedException("aborted");
+                       } else
+                               listener.error(this, "Calibration failed");
+               } catch (TimeoutException te) {
+                       System.out.printf("timeout");
+                       listener.error(this, "timeout");
+               } catch (InterruptedException ie) {
+                       System.out.printf("interrupted\n");
+                       listener.error(this, "interrupted");
+               }
+       }
+
+       public void start() {
+               accel_thread = new Thread(this);
+               listener.set_thread(this, accel_thread);
+               accel_thread.start();
+       }
+
+       public AltosAccelCal(AltosLink link, AltosAccelCalListener listener) {
+               this.link = link;
+               this.listener = listener;
+               ui_signal_semaphore = new Semaphore(0);
+       }
+}
diff --git a/altoslib/AltosAccelCalListener.java b/altoslib/AltosAccelCalListener.java
new file mode 100644 (file)
index 0000000..1735924
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright Â© 2017 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.altusmetrum.altoslib_12;
+
+import java.io.*;
+import java.util.concurrent.*;
+
+public interface AltosAccelCalListener {
+       public void set_thread(AltosAccelCal cal, Thread thread);
+
+       public void set_phase(AltosAccelCal cal, int phase);
+
+       public void cal_done(AltosAccelCal cal, int plus, int minus);
+
+       public void error(AltosAccelCal cal, String msg);
+
+       public void message(AltosAccelCal cal, String msg);
+}
index 63c34310f6d12458338d08b2e3a46b8b4cffed06..dc036867047cf278432aa99b7b35be0ccb244d6f 100644 (file)
@@ -405,7 +405,7 @@ public class AltosConfigData {
 
                /* HAS_GYRO */
                try {
-                       if (line.startsWith("IMU call along")) {
+                       if (line.startsWith("IMU cal along")) {
                                String[] bits = line.split("\\s+");
                                if (bits.length >= 8) {
                                        accel_zero_along = Integer.parseInt(bits[3]);
@@ -525,6 +525,12 @@ public class AltosConfigData {
                if (pad_orientation != AltosLib.MISSING)
                        pad_orientation = source.pad_orientation();
 
+               if (accel_cal_plus != AltosLib.MISSING)
+                       accel_cal_plus = source.accel_cal_plus();
+
+               if (accel_cal_minus != AltosLib.MISSING)
+                       accel_cal_minus = source.accel_cal_minus();
+
                /* HAS_LOG */
                if (flight_log_max != AltosLib.MISSING)
                        flight_log_max = source.flight_log_max();
@@ -592,6 +598,7 @@ public class AltosConfigData {
                dest.set_flight_log_max(flight_log_max);
                dest.set_ignite_mode(ignite_mode);
                dest.set_pad_orientation(pad_orientation);
+               dest.set_accel_cal(accel_cal_plus, accel_cal_minus);
                dest.set_callsign(callsign);
                if (npyro != AltosLib.MISSING)
                        dest.set_pyros(pyros);
@@ -669,9 +676,10 @@ public class AltosConfigData {
                        link.printf("c e %d\n", radio_enable);
 
                /* HAS_ACCEL */
-               /* UI doesn't support accel cal */
                if (pad_orientation != AltosLib.MISSING)
                        link.printf("c o %d\n", pad_orientation);
+               if (accel_cal_plus != AltosLib.MISSING && accel_cal_minus != AltosLib.MISSING)
+                       link.printf("c a %d %d\n", accel_cal_plus, accel_cal_minus);
 
                /* HAS_LOG */
                if (flight_log_max != 0)
index 170b1112ea096048d06d61a893ad16444825973f..10478fd4f96313dff8684792356f2cc0be3e44c5 100644 (file)
@@ -74,6 +74,16 @@ public interface AltosConfigValues {
 
        public abstract int pad_orientation();
 
+       public abstract void set_accel_cal(int accel_cal_plus, int accel_cal_minus);
+
+       public abstract int accel_cal_plus();
+
+       public abstract int accel_cal_minus();
+
+       public abstract void set_dirty();
+
+       public abstract void set_clean();
+
        public abstract void set_pyros(AltosPyro[] new_pyros);
 
        public abstract AltosPyro[] pyros() throws AltosConfigDataException;
index 5f89b3e4b5adae46772f47387ea0e5da37107f19..be6d840f0091e9b20d21589634ff63099272f5eb 100644 (file)
@@ -20,6 +20,7 @@ public abstract class AltosDataListener {
 
        public double           time = AltosLib.MISSING;
        public int              state = AltosLib.MISSING;
+       public double           frequency = AltosLib.MISSING;
 
        public void set_tick(int tick) {
                cal_data.set_tick(tick);
@@ -55,6 +56,10 @@ public abstract class AltosDataListener {
                cal_data().set_flight(flight);
        }
 
+       public void set_frequency(double frequency) {
+               this.frequency = frequency;
+       }
+
        /* Called after all records are captured */
        public void finish() {
        }
index c2e4e2a36bb8a72fc9b023bdebfffc7eb2c47b3a..ea1a9675aba8c818c814481bb45e6e545568cae0 100644 (file)
@@ -212,8 +212,11 @@ public class AltosFlightStats {
                                        add_times(series, (int) prev.value, prev.time, state.time);
                                prev = state;
                        }
-                       if (prev != null)
-                               add_times(series, (int) prev.value, prev.time, series.accel_series.last().time);
+                       if (prev != null) {
+                               AltosTimeValue last_accel = series.accel_series.last();
+                               if (last_accel != null)
+                                       add_times(series, (int) prev.value, prev.time, last_accel.time);
+                       }
                }
 
                for (int s = 0; s <= AltosLib.ao_flight_invalid; s++) {
@@ -245,14 +248,15 @@ public class AltosFlightStats {
                        has_gps = true;
                        lat = pad_lat = gps.lat;
                        lon = pad_lon = gps.lon;
-                       for (AltosGPSTimeValue gtv : series.gps_series) {
-                               gps = gtv.gps;
-                               if (gps.locked && gps.nsat >= 4) {
-                                       lat = gps.lat;
-                                       lon = gps.lon;
+                       if (series.gps_series != null) {
+                               for (AltosGPSTimeValue gtv : series.gps_series) {
+                                       gps = gtv.gps;
+                                       if (gps.locked && gps.nsat >= 4) {
+                                               lat = gps.lat;
+                                               lon = gps.lon;
+                                       }
                                }
                        }
-
                }
 
                max_height = AltosLib.MISSING;
index 5a802ef180230bdfb969d01212a0197781bb366d..5413de9dea7740fcaf56dcc2a19450d416c54f41 100644 (file)
@@ -43,6 +43,8 @@ public abstract class AltosLink implements Runnable {
        public LinkedBlockingQueue<AltosLine> reply_queue = new LinkedBlockingQueue<AltosLine>();
        public LinkedBlockingQueue<byte[]> binary_queue = new LinkedBlockingQueue<byte[]>();
 
+       private String match_string = null;
+
        public synchronized void add_monitor(LinkedBlockingQueue<AltosLine> q) {
                set_monitor(true);
                monitors.add(q);
@@ -112,6 +114,15 @@ public abstract class AltosLink implements Runnable {
 
        private int     len_read = 0;
 
+       private boolean match_bytes(byte[] bytes, int byte_count, String match) {
+               if (byte_count < match.length())
+                       return false;
+               String  line = new String(bytes, 0, byte_count, AltosLib.unicode_set);
+               if (line == null)
+                       return false;
+               return line.indexOf(match) >= 0;
+       }
+
        public void run () {
                int c;
                byte[] line_bytes = null;
@@ -159,6 +170,11 @@ public abstract class AltosLink implements Runnable {
                                                        line_count = 0;
                                                        len_read = 0;
                                                }
+                                               if (match_string != null && match_bytes(line_bytes, line_count, match_string)) {
+                                                       match_string = null;
+                                                       add_bytes(line_bytes, line_count);
+                                                       line_count = 0;
+                                               }
                                        }
                                }
                        }
@@ -166,6 +182,9 @@ public abstract class AltosLink implements Runnable {
                }
        }
 
+       public void set_match(String match) {
+               match_string = match;
+       }
 
        public String get_reply(int timeout) throws InterruptedException {
                boolean can_cancel = can_cancel_reply();
index 9ee3d57ddf814fe340ef53df61fa2e31758d5cae..39ab10da14c9c78bafee2156b7b3097b6ac80a71 100644 (file)
@@ -1060,7 +1060,6 @@ public class AltosState extends AltosDataListener {
        }
 
        public AltosState() {
-               Thread.dumpStack();
                init();
        }
 
index 7d576942c22f6348cd2b804c9855d751f1745f69..f17e11717c391410fd222148b4e6733165c45ed0 100644 (file)
@@ -38,6 +38,9 @@ public abstract class AltosTelemetry implements AltosDataProvider {
        /* Mark when we received the packet */
        long            received_time;
 
+       /* Mark frequency packet was received on */
+       public double           frequency = AltosLib.MISSING;
+
        static boolean cksum(int[] bytes) {
                int     sum = 0x5a;
                for (int i = 1; i < bytes.length - 1; i++)
@@ -50,6 +53,8 @@ public abstract class AltosTelemetry implements AltosDataProvider {
                listener.set_serial(serial());
                if (listener.state == AltosLib.ao_flight_invalid)
                        listener.set_state(AltosLib.ao_flight_startup);
+               if (frequency != AltosLib.MISSING)
+                       listener.set_frequency(frequency);
                listener.set_tick(tick());
                listener.set_rssi(rssi(), status());
                listener.set_received_time(received_time);
@@ -108,6 +113,10 @@ public abstract class AltosTelemetry implements AltosDataProvider {
                return telem;
        }
 
+       public void set_frequency(double frequency) {
+               this.frequency = frequency;
+       }
+
        public AltosTelemetry() {
                this.received_time = System.currentTimeMillis();
        }
index b3c432fcf565e1b481d63e0025024334a8d90061..9f3b4d807ef26bb36ae9a358515ac41c17f3bad5 100644 (file)
@@ -151,11 +151,15 @@ public class AltosTimeSeries implements Iterable<AltosTimeValue>, Comparable<Alt
        }
 
        public AltosTimeValue first() {
-               return values.get(0);
+               if (values.size() > 0)
+                       return values.get(0);
+               return null;
        }
 
        public AltosTimeValue last() {
-               return values.get(values.size() - 1);
+               if (values.size() > 0)
+                       return values.get(values.size() - 1);
+               return null;
        }
 
        public double average() {
index 11b5d562ee643ae1f7e061bc9a885702c6d22a86..08af9496e00199f32226024da1f35049142cef25 100644 (file)
@@ -26,6 +26,8 @@ record_files = \
 
 altoslib_JAVA = \
        AltosLib.java \
+       AltosAccelCal.java \
+       AltosAccelCalListener.java \
        AltosCalData.java \
        AltosCompanion.java \
        AltosConfigData.java \
index beff71b7279db119e094f10f8cae37688dfcae14..5e2aa7f4ef405470c0106a3255fb9a7bf8399e55 100644 (file)
@@ -268,6 +268,13 @@ public class AltosConfigFC implements ActionListener {
                                if (serial_line != null)
                                        serial_line.close();
                        }
+                       else if (cmd.equals("Accel")) {
+                               if (data.pad_orientation != AltosLib.MISSING) {
+                                       AltosUIAccelCal accel_ui = new AltosUIAccelCal(owner, serial_line, config_ui);
+                                       if (accel_ui != null)
+                                               accel_ui.doit();
+                               }
+                       }
                } catch (InterruptedException ie) {
                        abort();
                } catch (TimeoutException te) {
index c0c37254673188fad2026a90cba7d591a062a2b9..1e875dec1aa9b490622fd0d2d371f306b43f0936 100644 (file)
@@ -49,6 +49,8 @@ public class AltosConfigFCUI
        JLabel                  flight_log_max_label;
        JLabel                  ignite_mode_label;
        JLabel                  pad_orientation_label;
+       JLabel                  accel_plus_label;
+       JLabel                  accel_minus_label;
        JLabel                  callsign_label;
        JLabel                  beep_label;
        JLabel                  tracker_motion_label;
@@ -73,12 +75,15 @@ public class AltosConfigFCUI
        JComboBox<String>       flight_log_max_value;
        JComboBox<String>       ignite_mode_value;
        JComboBox<String>       pad_orientation_value;
+       JTextField              accel_plus_value;
+       JTextField              accel_minus_value;
        JTextField              callsign_value;
        JComboBox<String>       beep_value;
        JComboBox<String>       tracker_motion_value;
        JComboBox<String>       tracker_interval_value;
 
        JButton                 pyro;
+       JButton                 accel_cal;
 
        JButton                 save;
        JButton                 reset;
@@ -250,9 +255,9 @@ public class AltosConfigFCUI
        }
 
        void set_pad_orientation_tool_tip() {
-               if (pad_orientation_value.isVisible())
+               if (pad_orientation_value.isVisible()) {
                        pad_orientation_value.setToolTipText("How will the computer be mounted in the airframe");
-               else {
+               else {
                        if (is_telemetrum())
                                pad_orientation_value.setToolTipText("Older TeleMetrum firmware must fly antenna forward");
                        else if (is_telemini() || is_easymini())
@@ -262,6 +267,16 @@ public class AltosConfigFCUI
                }
        }
 
+       void set_accel_tool_tips() {
+               if (accel_plus_value.isVisible()) {
+                       accel_plus_value.setToolTipText("Pad acceleration value in flight orientation");
+                       accel_minus_value.setToolTipText("Upside-down acceleration value");
+               } else {
+                       accel_plus_value.setToolTipText("No accelerometer");
+                       accel_minus_value.setToolTipText("No accelerometer");
+               }
+       }
+
        void set_beep_tool_tip() {
                if (beep_value.isVisible())
                        beep_value.setToolTipText("What frequency the beeper will sound at");
@@ -709,6 +724,57 @@ public class AltosConfigFCUI
                set_pad_orientation_tool_tip();
                row++;
 
+               /* Accel plus */
+               c = new GridBagConstraints();
+               c.gridx = 0; c.gridy = row;
+               c.gridwidth = 4;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = il;
+               c.ipady = 5;
+               accel_plus_label = new JLabel("Accel Plus:");
+               pane.add(accel_plus_label, c);
+
+               c = new GridBagConstraints();
+               c.gridx = 4; c.gridy = row;
+               c.gridwidth = 4;
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.weightx = 1;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = ir;
+               c.ipady = 5;
+               accel_plus_value = new JTextField(10);
+               accel_plus_value.setEditable(true);
+               accel_plus_value.getDocument().addDocumentListener(this);
+               pane.add(accel_plus_value, c);
+               row++;
+
+               /* Accel minus */
+               c = new GridBagConstraints();
+               c.gridx = 0; c.gridy = row;
+               c.gridwidth = 4;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = il;
+               c.ipady = 5;
+               accel_minus_label = new JLabel("Accel Minus:");
+               pane.add(accel_minus_label, c);
+
+               c = new GridBagConstraints();
+               c.gridx = 4; c.gridy = row;
+               c.gridwidth = 4;
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.weightx = 1;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = ir;
+               c.ipady = 5;
+               accel_minus_value = new JTextField(10);
+               accel_minus_value.setEditable(true);
+               accel_minus_value.getDocument().addDocumentListener(this);
+               pane.add(accel_minus_value, c);
+               row++;
+               set_accel_tool_tips();
+
                /* Beeper */
                c = new GridBagConstraints();
                c.gridx = 0; c.gridy = row;
@@ -800,6 +866,20 @@ public class AltosConfigFCUI
                pyro.setActionCommand("Pyro");
                row++;
 
+               /* Accel cal */
+               c = new GridBagConstraints();
+               c.gridx = 5; c.gridy = row;
+               c.gridwidth = 5;
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = il;
+               c.ipady = 5;
+               accel_cal = new JButton("Calibrate Accelerometer");
+               pane.add(accel_cal, c);
+               accel_cal.addActionListener(this);
+               accel_cal.setActionCommand("Accel");
+               row++;
+
                /* Buttons */
                c = new GridBagConstraints();
                c.gridx = 0; c.gridy = row;
@@ -873,7 +953,7 @@ public class AltosConfigFCUI
                return true;
        }
 
-       void set_dirty() {
+       public void set_dirty() {
                dirty = true;
                save.setEnabled(true);
        }
@@ -912,7 +992,8 @@ public class AltosConfigFCUI
                        setVisible(false);
                        dispose();
                }
-               set_clean();
+               if (cmd.equals("Save") || cmd.equals("Reset"))
+                       set_clean();
        }
 
        /* ItemListener interface method */
@@ -943,6 +1024,7 @@ public class AltosConfigFCUI
                radio_frequency_value.set_product(product);
                product_value.setText(product);
                set_pad_orientation_tool_tip();
+               set_accel_tool_tips();
                set_flight_log_max_tool_tip();
        }
 
@@ -1196,6 +1278,7 @@ public class AltosConfigFCUI
                }
                pad_orientation_value.setVisible(new_pad_orientation != AltosLib.MISSING);
                pad_orientation_label.setVisible(new_pad_orientation != AltosLib.MISSING);
+               accel_cal.setVisible(new_pad_orientation != AltosLib.MISSING);
 
                set_pad_orientation_tool_tip();
        }
@@ -1207,6 +1290,31 @@ public class AltosConfigFCUI
                        return AltosLib.MISSING;
        }
 
+       public void set_accel_cal(int accel_plus, int accel_minus) {
+               if (accel_plus != AltosLib.MISSING) {
+                       accel_plus_value.setText(String.format("%d", accel_plus));
+                       accel_minus_value.setText(String.format("%d", accel_minus));
+               }
+               accel_plus_value.setVisible(accel_plus != AltosLib.MISSING);
+               accel_plus_label.setVisible(accel_plus != AltosLib.MISSING);
+               accel_minus_value.setVisible(accel_minus != AltosLib.MISSING);
+               accel_minus_label.setVisible(accel_minus != AltosLib.MISSING);
+
+               set_accel_tool_tips();
+       }
+
+       public int accel_cal_plus() {
+               if (accel_plus_value.isVisible())
+                       return Integer.parseInt(accel_plus_value.getText());
+               return AltosLib.MISSING;
+       }
+
+       public int accel_cal_minus() {
+               if (accel_minus_value.isVisible())
+                       return Integer.parseInt(accel_minus_value.getText());
+               return AltosLib.MISSING;
+       }
+
        public void set_beep(int new_beep) {
                if (new_beep != AltosLib.MISSING) {
                        int new_freq = (int) Math.floor (AltosConvert.beep_value_to_freq(new_beep) + 0.5);
index f6c906c64fa78a1a14802b20d47914efcbbe7dab..042f9277c2cf40e8335d9b46d9f5bda727b7c9e1 100644 (file)
@@ -48,7 +48,6 @@ public class AltosGraphUI extends AltosUIFrame implements AltosFontListener, Alt
 
                if (flight_series.gps_series != null) {
                        for (AltosGPSTimeValue gtv : flight_series.gps_series) {
-                               gtv_last = gtv;
                                AltosGPS gps = gtv.gps;
                                if (gps != null &&
                                    gps.locked &&
@@ -57,6 +56,7 @@ public class AltosGraphUI extends AltosUIFrame implements AltosFontListener, Alt
                                                map = new AltosUIMap();
                                        map.show(gps, (int) flight_series.value_before(AltosFlightSeries.state_name, gtv.time));
                                        this.gps = gps;
+                                       gtv_last = gtv;
                                        has_gps = true;
                                }
                        }
index 53762aec728bd9740ef8b999227f40be78d8247e..6f206c3d362a9c54a7b53bd8a2acd0a7a80e9921 100644 (file)
@@ -194,7 +194,7 @@ clean-local:
                Altos-Linux-*.tar.bz2 Altos-Linux-*.sh Altos-Mac-*.dmg Altos-Windows-*.exe \
                windows altoslib_*.jar altosuilib_*.jar $(FREETTS_CLASS) \
                $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(LIBALTOS) Manifest.txt Manifest-fat.txt altos-windows.log altos-windows.nsi \
-               altosui altosui-test altosui-jdb macosx linux *.desktop $(MDWN)
+               altosui altosui-test altosui-jdb macosx linux *.desktop *.mdwn
 
 EXTRA_DIST = $(desktop_file).in
 
diff --git a/altosuilib/AltosUIAccelCal.java b/altosuilib/AltosUIAccelCal.java
new file mode 100644 (file)
index 0000000..af72a21
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ * Copyright Â© 2017 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.altusmetrum.altosuilib_12;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.beans.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import org.altusmetrum.altoslib_12.*;
+
+public class AltosUIAccelCal
+       extends AltosUIDialog
+       implements AltosAccelCalListener, ActionListener
+{
+       Frame owner;
+       AltosLink link;
+       AltosAccelCal cal;
+       AltosConfigValues       config_values;
+       Thread thread;
+       Container pane;
+       JTextField message;
+       JButton antenna_up;
+       JButton antenna_down;
+       JButton ok;
+       JButton cancel;
+       boolean success;
+       int accel_plus, accel_minus;
+
+       private void make_visible() {
+               pack();
+               cal.start();
+               setVisible(true);
+       }
+
+       public boolean doit() {
+               success = false;
+               make_visible();
+               return success;
+       }
+
+       public int accel_cal_plus() {
+               if (success)
+                       return accel_plus;
+               return AltosLib.MISSING;
+       }
+
+       public int accel_cal_minus() {
+               if (success)
+                       return accel_minus;
+               return AltosLib.MISSING;
+       }
+
+       private void setDefaultButton(JButton button) {
+               this.getRootPane().setDefaultButton(button);
+       }
+
+       /* AltosAccelCalListener interface */
+       public void set_thread(AltosAccelCal cal, Thread thread) {
+               this.thread = thread;
+       }
+
+       public void set_phase(AltosAccelCal cal, final int phase) {
+               SwingUtilities.invokeLater(new Runnable() {
+                               public void run() {
+                                       switch (phase) {
+                                       case AltosAccelCal.phase_antenna_up:
+                                               message.setText("Orient antenna upwards and click on Antenna Up");
+                                               antenna_up.setEnabled(true);
+                                               setDefaultButton(antenna_up);
+                                               antenna_down.setEnabled(false);
+                                               ok.setEnabled(false);
+                                               break;
+                                       case AltosAccelCal.phase_antenna_down:
+                                               message.setText("Orient antenna downwards and click on Antenna Down");
+                                               antenna_up.setEnabled(false);
+                                               antenna_down.setEnabled(true);
+                                               setDefaultButton(antenna_down);
+                                               ok.setEnabled(false);
+                                               break;
+                                       }
+                               }
+                       });
+       }
+
+       public void cal_done(AltosAccelCal cal, int plus, int minus) {
+               accel_plus = plus;
+               accel_minus = minus;
+               success = true;
+               SwingUtilities.invokeLater(new Runnable() {
+                               public void run() {
+                                       message.setText(String.format("Calibration succeeded, plus %d minus %d, press OK to continue", accel_plus, accel_minus));
+                                       antenna_up.setEnabled(false);
+                                       antenna_down.setEnabled(false);
+                                       ok.setEnabled(true);
+                                       setDefaultButton(ok);
+                               }
+                       });
+       }
+
+       public void message(AltosAccelCal cal, final String msg) {
+               SwingUtilities.invokeLater(new Runnable() {
+                               public void run() {
+                                       message.setText(msg);
+                               }
+                       });
+       }
+
+       public void error(AltosAccelCal cal, String msg) {
+               message(cal, msg);
+       }
+
+       /* ActionListener interface */
+       public void actionPerformed(ActionEvent e) {
+               String  cmd = e.getActionCommand();
+
+               if ("up".equals(cmd)) {
+                       cal.signal(true);
+                       antenna_up.setEnabled(false);
+               } else if ("down".equals(cmd)) {
+                       cal.signal(true);
+                       antenna_down.setEnabled(false);
+                       this.setDefaultButton(antenna_down);
+               } else if ("ok".equals(cmd)) {
+                       cal.signal(true);
+                       this.setVisible(false);
+                       if (success) {
+                               config_values.set_accel_cal(accel_plus, accel_minus);
+                               config_values.set_dirty();
+                       }
+                       try {
+                               cal.abort();
+                       } catch (InterruptedException ie) {
+                       }
+               } else if ("cancel".equals(cmd)) {
+                       cal.signal(false);
+                       this.setVisible(false);
+                       try {
+                               cal.abort();
+                       } catch (InterruptedException ie) {
+                       }
+               }
+       }
+       public AltosUIAccelCal(Frame owner, AltosLink link, AltosConfigValues config_values) {
+               super(owner, "Calibrate Accelerometer", true);
+
+               this.owner = owner;
+               this.link = link;
+               this.config_values = config_values;
+
+               pane = getContentPane();
+               pane.setLayout(new GridBagLayout());
+
+               GridBagConstraints c = new GridBagConstraints();
+               c.insets = new Insets(4,4,4,4);
+
+               int x = 0;
+               int y = 0;
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.anchor = GridBagConstraints.WEST;
+               c.gridx = x;
+               c.gridy = y;
+               c.gridwidth = 4;
+               c.gridheight = 1;
+               c.weightx = 0;
+               c.weighty = 0;
+               message = new JTextField(64);
+               pane.add(message, c);
+
+               y++; x = 0;
+
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.WEST;
+               c.gridx = x;
+               c.gridy = y;
+               c.gridwidth = 1;
+               c.gridheight = 1;
+               c.weightx = 0;
+               c.weighty = 0;
+               antenna_up = new JButton("Antenna Up");
+               antenna_up.setActionCommand("up");
+               antenna_up.setEnabled(false);
+               antenna_up.addActionListener(this);
+               pane.add(antenna_up, c);
+
+               x++;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.WEST;
+               c.gridx = x;
+               c.gridy = y;
+               c.gridwidth = 1;
+               c.gridheight = 1;
+               c.weightx = 0;
+               c.weighty = 0;
+               antenna_down = new JButton("Antenna Down");
+               antenna_down.setActionCommand("down");
+               antenna_down.setEnabled(false);
+               antenna_down.addActionListener(this);
+               pane.add(antenna_down, c);
+
+               x++;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.WEST;
+               c.gridx = x;
+               c.gridy = y;
+               c.gridwidth = 1;
+               c.gridheight = 1;
+               c.weightx = 0;
+               c.weighty = 0;
+               ok = new JButton("OK");
+               ok.setActionCommand("ok");
+               ok.setEnabled(false);
+               ok.addActionListener(this);
+               pane.add(ok, c);
+
+               x++;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.WEST;
+               c.gridx = x;
+               c.gridy = y;
+               c.gridwidth = 1;
+               c.gridheight = 1;
+               c.weightx = 0;
+               c.weighty = 0;
+               cancel = new JButton("Cancel");
+               cancel.setActionCommand("cancel");
+               cancel.setEnabled(true);
+               cancel.addActionListener(this);
+               pane.add(cancel, c);
+
+               cal = new AltosAccelCal(this.link, this);
+       }
+}
index 4b5eb524c09824995393bb4a25d856f0f682dd6e..ce86d21e3a1405a4665cd86a04bb7b58f26a8774 100644 (file)
@@ -13,6 +13,7 @@ altosuilib_JAVA = \
        AltosDevice.java \
        AltosDeviceDialog.java \
        AltosPositionListener.java \
+       AltosUIAccelCal.java \
        AltosUIConfigure.java \
        AltosUIAxis.java \
        AltosUIDataMissing.java \
diff --git a/ao-bringup/test-telegps b/ao-bringup/test-telegps
deleted file mode 100755 (executable)
index 0b27580..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/bin/sh
-
-VERSION=1.0
-PRODUCT=TeleGPS
-BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
-
-echo "$PRODUCT-v$VERSION Test Program"
-echo "Copyright 2014 by Bdale Garbee.  Released under GPL v2"
-echo
-echo "Expectations:"
-echo "\t$PRODUCT v$VERSION powered from USB"
-echo
-
-ret=1
-ao-list | while read product serial dev; do
-    case "$product" in
-       "$PRODUCT-v$VERSION")
-
-           echo "Testing $product $serial $dev"
-
-           FLASHSIZE=2097152
-
-           echo "Testing flash"
-           ../ao-tools/ao-test-flash/ao-test-flash --tty="$dev" "$FLASHSIZE"
-
-           case $? in
-               0)
-                   ;;
-               *)
-                   echo "failed"
-                   exit 1
-           esac
-
-           echo "Testing GPS"
-           ../ao-tools/ao-test-gps/ao-test-gps --tty="$dev"
-
-           case $? in
-               0)
-                   ;;
-               *)
-                   echo "failed"
-                   exit 1
-           esac
-
-           echo "$PRODUCT-v$VERSION" serial "$serial" passed functional tests
-           ret=0
-           ;;
-       *)
-           echo "Skipping $product $serial $dev"
-           ;;
-    esac
-done
diff --git a/ao-bringup/test-telegps-v1 b/ao-bringup/test-telegps-v1
new file mode 100755 (executable)
index 0000000..0b27580
--- /dev/null
@@ -0,0 +1,52 @@
+#!/bin/sh
+
+VERSION=1.0
+PRODUCT=TeleGPS
+BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+
+echo "$PRODUCT-v$VERSION Test Program"
+echo "Copyright 2014 by Bdale Garbee.  Released under GPL v2"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION powered from USB"
+echo
+
+ret=1
+ao-list | while read product serial dev; do
+    case "$product" in
+       "$PRODUCT-v$VERSION")
+
+           echo "Testing $product $serial $dev"
+
+           FLASHSIZE=2097152
+
+           echo "Testing flash"
+           ../ao-tools/ao-test-flash/ao-test-flash --tty="$dev" "$FLASHSIZE"
+
+           case $? in
+               0)
+                   ;;
+               *)
+                   echo "failed"
+                   exit 1
+           esac
+
+           echo "Testing GPS"
+           ../ao-tools/ao-test-gps/ao-test-gps --tty="$dev"
+
+           case $? in
+               0)
+                   ;;
+               *)
+                   echo "failed"
+                   exit 1
+           esac
+
+           echo "$PRODUCT-v$VERSION" serial "$serial" passed functional tests
+           ret=0
+           ;;
+       *)
+           echo "Skipping $product $serial $dev"
+           ;;
+    esac
+done
diff --git a/ao-bringup/test-telegps-v2 b/ao-bringup/test-telegps-v2
new file mode 100755 (executable)
index 0000000..b103aed
--- /dev/null
@@ -0,0 +1,52 @@
+#!/bin/sh
+
+VERSION=2.0
+PRODUCT=TeleGPS
+BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+
+echo "$PRODUCT-v$VERSION Test Program"
+echo "Copyright 2014 by Bdale Garbee.  Released under GPL v2"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION powered from USB"
+echo
+
+ret=1
+ao-list | while read product serial dev; do
+    case "$product" in
+       "$PRODUCT-v$VERSION")
+
+           echo "Testing $product $serial $dev"
+
+           FLASHSIZE=2097152
+
+           echo "Testing flash"
+           ../ao-tools/ao-test-flash/ao-test-flash --tty="$dev" "$FLASHSIZE"
+
+           case $? in
+               0)
+                   ;;
+               *)
+                   echo "failed"
+                   exit 1
+           esac
+
+           echo "Testing GPS"
+           ../ao-tools/ao-test-gps/ao-test-gps --tty="$dev"
+
+           case $? in
+               0)
+                   ;;
+               *)
+                   echo "failed"
+                   exit 1
+           esac
+
+           echo "$PRODUCT-v$VERSION" serial "$serial" passed functional tests
+           ret=0
+           ;;
+       *)
+           echo "Skipping $product $serial $dev"
+           ;;
+    esac
+done
index 912ba459657d01bdb5a889d00d4eba2f4613d7f2..fb8318b311c83d7ac28aa9adfbe392cf866ef1af 100755 (executable)
@@ -80,7 +80,7 @@ else
 fi
 
 echo -n "checking BTLE functionality... "
-btdev=`sudo timeout -s SIGINT 5s hcitool lescan | awk -F \- '/TeleBT/ { print $2 }'`
+btdev=`sudo timeout -s SIGINT 5s hcitool lescan | awk -F \- '/TeleBT/ { print $2 }' | head -n 1`
 if [ "$btdev" = "$SERIAL" ]; then
        echo "working!"
 else
index b6da2898bbaece3545bce832e5f32bda8f4e1017..fd879abdb175532ef84ea61328376a1fcd539e7d 100755 (executable)
@@ -1,12 +1,10 @@
 #!/bin/sh
 
-if [ -x ../ao-tools/ao-flash/ao-flash-lpc ]; then
-        FLASH_LPC=../ao-tools/ao-flash/ao-flash-lpc
-elif [ -x /usr/bin/ao-flash-lpc ]; then
-        FLASH_LPC=/usr/bin/ao-flash-lpc
+if [ -x /usr/bin/dfu-util ]; then
+    DFU_UTIL=/usr/bin/dfu-util
 else
-        echo "Can't find ao-flash-lpc!  Aborting."
-        exit 1
+    echo "Can't find dfu-util! Aborting."
+    exit 1
 fi
 
 if [ -x /usr/bin/ao-usbload ]; then
@@ -17,16 +15,17 @@ else
 fi
 
 PRODUCT=TeleGPS
-VERSION=1.0
-BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
-echo $FILE
+VERSION=2.0
+REPO=~/altusmetrumllc/Binaries
+
+#BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+#echo $FILE
 
 echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
-echo "Copyright 2014 by Bdale Garbee.  Released under GPL v2"
+echo "Copyright 2017 by Bdale Garbee.  Released under GPL v3+"
 echo
 echo "Expectations:"
-echo "\t$PRODUCT v$VERSION powered from USB"
-echo "\t\twith ST-Link-V2 cabled to debug header"
+echo "\t$PRODUCT v$VERSION powered from / attached to USB on this computer"
 echo
 
 case $# in
@@ -47,35 +46,31 @@ esac
 #
 # Use released versions of everything
 #
-FLASH_FILE=~/altusmetrumllc/Binaries/loaders/telegps-v1.0-altos-flash-*.elf
-ALTOS_FILE=~/altusmetrumllc/Binaries/telegps-v1.0-*.elf
-
-echo $FLASH_LPC $FLASH_FILE
+FLASH_FILE=$REPO/loaders/telegps-v2.0-altos-flash-*.bin
+ALTOS_FILE=$REPO/telegps-v2.0-*.elf
 
-$FLASH_LPC $FLASH_FILE || exit 1
+$DFU_UTIL -a 0 -s 0x08000000:leave -D $FLASH_FILE || exit 1
 
 sleep 2
 
-echo $USBLOAD $ALTOS_FILE
-
 $USBLOAD --serial=$SERIAL $ALTOS_FILE || exit 1
 
-sleep 2
+sleep 3
 
-dev=`ao-list | awk '/TeleGPS-v'"$VERSION"'/ { print $3; exit(0); }'`
+dev=`ao-list | awk '/'"$PRODUCT"'-v'"$VERSION"'/ { print $3; exit(0); }'`
 
 case "$dev" in
 /dev/tty*)
-        echo "TeleGPS found on $dev"
+        echo "$PRODUCT found on $dev"
         ;;
 *)
-        echo 'No TeleGPS-v'"$VERSION"' found'
+        echo 'No '"$PRODUCT"'-v'"$VERSION"' found'
         exit 1
         ;;
 esac
 
 SERIAL=$SERIAL ./cal-freq $dev
 
-./test-telegps
+./test-telegps-v2
 
 exit $?
diff --git a/ao-bringup/turnon_telegps_v1 b/ao-bringup/turnon_telegps_v1
new file mode 100755 (executable)
index 0000000..5341acc
--- /dev/null
@@ -0,0 +1,81 @@
+#!/bin/sh
+
+if [ -x ../ao-tools/ao-flash/ao-flash-lpc ]; then
+        FLASH_LPC=../ao-tools/ao-flash/ao-flash-lpc
+elif [ -x /usr/bin/ao-flash-lpc ]; then
+        FLASH_LPC=/usr/bin/ao-flash-lpc
+else
+        echo "Can't find ao-flash-lpc!  Aborting."
+        exit 1
+fi
+
+if [ -x /usr/bin/ao-usbload ]; then
+       USBLOAD=/usr/bin/ao-usbload
+else
+       echo "Can't find ao-usbload!  Aborting."
+       exit 1
+fi
+
+PRODUCT=TeleGPS
+VERSION=1.0
+BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+echo $FILE
+
+echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2014 by Bdale Garbee.  Released under GPL v2"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION powered from USB"
+echo "\t\twith ST-Link-V2 cabled to debug header"
+echo
+
+case $# in
+    1)
+       SERIAL="$1"
+       echo "$PRODUCT-$VERSION serial number: $SERIAL" 
+       ;;
+    0)
+       echo -n "$PRODUCT-$VERSION serial number: "
+       read SERIAL
+       ;;
+    *)
+       echo "Usage: $0 <serial-number>" 1>&2
+       exit 1;
+       ;;
+esac
+
+#
+# Use released versions of everything
+#
+FLASH_FILE=~/altusmetrumllc/Binaries/loaders/telegps-v1.0-altos-flash-*.elf
+ALTOS_FILE=~/altusmetrumllc/Binaries/telegps-v1.0-*.elf
+
+echo $FLASH_LPC $FLASH_FILE
+
+$FLASH_LPC $FLASH_FILE || exit 1
+
+sleep 2
+
+echo $USBLOAD $ALTOS_FILE
+
+$USBLOAD --serial=$SERIAL $ALTOS_FILE || exit 1
+
+sleep 2
+
+dev=`ao-list | awk '/TeleGPS-v'"$VERSION"'/ { print $3; exit(0); }'`
+
+case "$dev" in
+/dev/tty*)
+        echo "TeleGPS found on $dev"
+        ;;
+*)
+        echo 'No TeleGPS-v'"$VERSION"' found'
+        exit 1
+        ;;
+esac
+
+SERIAL=$SERIAL ./cal-freq $dev
+
+./test-telegps-v1
+
+exit $?
index 581eb2d22bc45b5e4ff9b98e0190836869727b1f..6ba8885ce12dd1ebb5f3c113b842cc42f5e1e1d8 100644 (file)
@@ -1,6 +1,6 @@
 bin_PROGRAMS=ao-chaosread
 
-AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+AM_CFLAGS=$(LIBUSB_CFLAGS) -Wall -Wextra
 
 ao_chaosread_LDADD=$(LIBUSB_LIBS)
 
index 7808f6c91d5cdad2689219951ac117ff96bc6392..6d860139f71487a59dbd3f9d8e6433532fa018b4 100644 (file)
@@ -74,7 +74,7 @@ chaoskey_match(libusb_device *dev, char *match_serial)
                goto out;
        }
 
-       ret = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, device_serial, match_len + 1);
+       ret = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, (unsigned char *) device_serial, match_len + 1);
 
        if (ret < 0) {
                fprintf(stderr, "failed to get serial number: %s\n", libusb_strerror(ret));
@@ -103,7 +103,6 @@ chaoskey_open(char *serial)
        int             ret;
        ssize_t         num;
        libusb_device   **list;
-       libusb_device   *device = NULL;
        int             d;
 
        ck = calloc(sizeof (struct chaoskey), 1);
@@ -173,12 +172,6 @@ chaoskey_close(struct chaoskey *ck)
        free(ck);
 }
 
-void
-chaoskey_transfer_callback(struct libusb_transfer *transfer)
-{
-       struct chaoskey *ck = transfer->user_data;
-}
-
 #define ENDPOINT       0x86
 
 int
@@ -202,7 +195,9 @@ chaoskey_read(struct chaoskey *ck, void *buffer, int len)
                }
                len -= transferred;
                buf += transferred;
+               total += transferred;
        }
+       return total;
 }
 
 static const struct option options[] = {
@@ -283,8 +278,17 @@ main (int argc, char **argv)
                        int i;
                        for (i = 0; i < got / 2; i++)
                                putchar((buf[i] >> 1 & 0xff));
-               } else
-                       write(1, buf, got);
+               } else {
+                       int i;
+                       int ret;
+                       for (i = 0; i < got; i += ret) {
+                               ret = write(1, ((char *) buf) + i, got - i);
+                               if (ret <= 0) {
+                                       perror("write");
+                                       exit(1);
+                               }
+                       }
+               }
                length -= got;
        }
        exit(0);
index dc80f6e3939a188a77796830f4b1dd1fa24eed74..2bf6c7e330de9840b2f907ad4ca224cc9a691f3b 100644 (file)
@@ -18,13 +18,13 @@ dnl
 dnl Process this file with autoconf to create configure.
 
 AC_PREREQ(2.57)
-AC_INIT([altos], 1.8.1)
-ANDROID_VERSION=15
+AC_INIT([altos], 1.8.2)
+ANDROID_VERSION=16
 AC_CONFIG_SRCDIR([src/kernel/ao.h])
 AM_INIT_AUTOMAKE([foreign dist-bzip2])
 AM_MAINTAINER_MODE
 
-RELEASE_DATE=2017-08-27
+RELEASE_DATE=2017-09-18
 AC_SUBST(RELEASE_DATE)
 
 VERSION_DASH=`echo $VERSION | sed 's/\./-/g'`
index 5b264e02f8ac88b1f972c0e4ece5f3ebbd5378f2..b1bff8482d94a99a2924821aa119dd1656089f6d 100644 (file)
@@ -3,6 +3,7 @@
 #
 
 RELNOTES_INC=\
+       release-notes-1.8.2.inc \
        release-notes-1.8.1.inc \
        release-notes-1.8.inc \
        release-notes-1.7.inc \
index 595422f1b34eb878ab9b8aab12742cc5f2756886..c2bc14d19055d79276cc076272fdd0a70fec43ad 100644 (file)
 </legalnotice>
 <revhistory>
   <?dbhtml filename="altusmetrum-revhistory.html"?>
+  <revision>
+    <revnumber>1.8.2</revnumber>
+    <date>18 Sep 2017</date>
+    <revremark>
+      Support TeleGPS v2.0 hardware. Add accelerometer recalibration
+      UI.
+    </revremark>
+  </revision>
   <revision>
     <revnumber>1.8.1</revnumber>
     <date>27 Aug 2017</date>
index 35848882b32bff54542ff87cc78661af4fcb904e..99d5c008861fd4e48abfe589c0641448b87e4fa1 100644 (file)
@@ -206,6 +206,22 @@ ifdef::telegps[]
                in the log.
 endif::telegps[]
 
+ifdef::telemega,easymega,telemetrum[]
+
+       ==== Calibrate Accelerometer
+
+               This opens a separate window to recalibrate the
+               accelerometers. Follow the instructions, orienting the
+               flight computer with the antenna end, or end opposite
+               the screw terminals, in the case of EasyMega, first up
+               and then down.
+
+               When the calibration is complete, return to the
+               Configure Altimeter window and save the new
+               calibration values.
+
+endif::telemega,easymega,telemetrum[]
+
 ifdef::telemega,easymega[]
 
        ==== Configure Pyro Channels
diff --git a/doc/release-notes-1.8.2.inc b/doc/release-notes-1.8.2.inc
new file mode 100644 (file)
index 0000000..2923ec1
--- /dev/null
@@ -0,0 +1,28 @@
+= Release Notes for Version 1.8.2
+:toc!:
+:doctype: article
+
+       Version 1.8.2 includes support for TeleGPS version 2.0 along
+       with accelerometer recalibration support in AltosUI.
+
+       1.8.2 also contains a couple of minor fixes for AltosUI when
+       analyzing saved data files.
+
+       == AltOS
+
+       AltOS New Features
+
+       * Support for TeleGPS version 2.0 hardware.
+
+       == AltosUI and TeleGPS Applications
+
+       AltosUI and TeleGPS New Features
+
+       * Support for TeleGPS version 2.0.
+
+       * Accelerometer re-calibration user interface.
+
+       AltosUI and TeleGPS Bug Fixes
+
+       * Prevent some crashes when reading older saved flight data
+          for graphing or KML export.
index adcf57ed99cb6d918faf9ff66cdc0ea60a026a2b..a102b2dc060c97a78fa76ff4c5198e2c651d81da 100644 (file)
@@ -1,6 +1,10 @@
 [appendix]
 == Release Notes
 
+       :leveloffset: 2
+       include::release-notes-1.8.2.raw[]
+
+       <<<<
        :leveloffset: 2
        include::release-notes-1.8.1.raw[]
 
index 29587b7e7e4f4afc3d16f3af307a8bddbdd849d2..d010f398e76d926559dc5eb398217f074b0b88f3 100644 (file)
                ifdef::radio[disabled, and the radio goes into transmit-only mode.]
                ifndef::radio[disabled.]
                The only way to get out of this
-               mode is to power the flight computer down.
+               mode is to power the flight computer down. See below for how to get the flight
+               computer to come up in Flight/Pad mode at power on.
 
                Idle::
                The flight computer is ready to communicate over USB
                ifdef::radio[and in packet mode over the radio.]
                You can configure
                the flight computer, download data or display
-               the current state.
+               the current state. See below for how to get the flight
+               computer to come up in Idle mode at power on.
 
                ifdef::telemetrum,easymega,telemega[]
                For flight computers with accelerometers (TeleMetrum,
index 6f674b19fd952aa8e7db451bccf0f1eb315ea117..5e153b82af85cdc6a4085f6f00dd53adfe5f3ff4 100644 (file)
@@ -103,7 +103,7 @@ clean-local:
                altoslib_*.jar altosuilib_*.jar \
                $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(LIBALTOS) Manifest.txt Manifest-fat.txt \
                micropeak micropeak-test micropeak-jdb macosx linux windows micropeak-windows.log \
-               micropeak-windows.nsi *.desktop $(MDWN)
+               micropeak-windows.nsi *.desktop *.mdwn
 
 EXTRA_DIST = $(desktop_file).in
 
index 25e43a0eb5757d8e75b7f99c456542c02bb339ee..661fd33301d4f8207e5e7d1a933dedceef9b462d 100644 (file)
@@ -35,6 +35,7 @@ ARMM3DIRS=\
        megadongle-v0.1 megadongle-v0.1/flash-loader \
        telegps-v0.3 telegps-v0.3/flash-loader \
        telegps-v1.0 telegps-v1.0/flash-loader \
+       telegps-v2.0 telegps-v2.0/flash-loader \
        telelco-v0.2 telelco-v0.2/flash-loader \
        telelco-v0.3 telelco-v0.3/flash-loader \
        telescience-v0.2 telescience-v0.2/flash-loader \
index b1227aaab8dba5a0213e50c4fd9b30ac7d1cdef9..7cda053d3ff2263d9bb7c89b55d6947a786b52d1 100644 (file)
@@ -153,10 +153,20 @@ ao_trng_send(void)
 
        ao_crc_reset();
 
-       ao_delay(TRNG_ENABLE_DELAY);
-
        for (s = 0; s < AO_TRNG_START_WAIT; s++) {
-               if (ao_trng_get_cooked(buffer[0]))
+               int i;
+               uint16_t        min, max;
+               uint16_t        buf[AO_USB_IN_SIZE>>1];
+
+               ao_trng_get_raw(buf);
+               min = max = buf[0];
+               for (i = 1; i < (AO_USB_IN_SIZE>>1); i++) {
+                       uint16_t v = buf[i];
+                       if (v < min) min = v;
+                       if (v > max) max = v;
+               }
+               /* Wait for at least 10 bits of range */
+               if ((uint16_t) (max - min) >= 1024)
                        break;
                ao_delay(AO_MS_TO_TICKS(10));
        }
index a0881f9e3a8262fce6ec2b925363c5fcbb75ac32..9543b3ef20cd60f8a9d85f9442ea3ea5dd3d98cd 100644 (file)
@@ -181,7 +181,7 @@ ao_pyro_ready(struct ao_pyro *pyro)
                case ao_pyro_state_greater_or_equal:
                        if (ao_flight_state >= pyro->state_greater_or_equal)
                                continue;
-                       DBG("state %d >= %d\n", ao_flight_state, pyro->state_less);
+                       DBG("state %d < %d\n", ao_flight_state, pyro->state_greater_or_equal);
                        break;
 
                default:
index f92564d6c86d0cdb2d9f31c2a7e0a49d26ba2a36..fa175371b28f8835f462b9cb04ac17abf9bb3e07 100644 (file)
 #define IS_FLASH_LOADER                0
 #define HAS_BEEP              0
 
-#define AO_HSE                  32000000
+#define AO_HSE                  16000000
 #define AO_RCC_CFGR_PLLMUL      STM_RCC_CFGR_PLLMUL_3
-#define AO_RCC_CFGR2_PLLDIV    STM_RCC_CFGR2_PREDIV_2
+#define AO_RCC_CFGR2_PLLDIV    STM_RCC_CFGR2_PREDIV_1
 #define AO_PLLMUL               3
-#define AO_PLLDIV               2
+#define AO_PLLDIV               1
 
 /* HCLK = 48MHz */
 #define AO_AHB_PRESCALER        1
@@ -50,6 +50,9 @@
 #define HAS_USB                         1
 #define AO_USB_DIRECTIO                 0
 #define AO_PA11_PA12_RMP                1
+#define HAS_USB_CONNECT                        1
+#define AO_USB_CONNECT_PORT            (&stm_gpiob)
+#define AO_USB_CONNECT_PIN             3
 
 #define IS_FLASH_LOADER 0
 
@@ -110,6 +113,8 @@ struct ao_adc {
 #define HAS_SERIAL_2           1
 #define SERIAL_2_PA2_PA3       1
 #define USE_SERIAL_2_STDIN     0
+#define USE_SERIAL_2_FLOW       0
+#define USE_SERIAL_2_SW_FLOW    0
 
 #define ao_gps_getchar         ao_serial2_getchar
 #define ao_gps_putchar         ao_serial2_putchar
index a0c2d5feea7658a07e7dc4eb5784135e0d275e5d..088084303edc74cea9d6ff108e12a803aa63daa8 100644 (file)
@@ -6,7 +6,10 @@ PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noi
        ao_aprs_test ao_micropeak_test ao_fat_test ao_aes_test ao_int64_test \
        ao_ms5607_convert_test ao_quaternion_test ao_lisp_test
 
-INCS=ao_kalman.h ao_ms5607.h ao_log.h ao_data.h altitude-pa.h altitude.h ao_quaternion.h
+INCS=ao_kalman.h ao_ms5607.h ao_log.h ao_data.h altitude-pa.h altitude.h ao_quaternion.h ao_eeprom_read.h
+TEST_SRC=ao_flight_test.c
+TEST_SRC_ALL=ao_flight_test.c ao_eeprom_read.c ao_eeprom_read_old.c
+TEST_LIB=-ljson-c
 
 KALMAN=make-kalman 
 
@@ -19,26 +22,26 @@ clean:
 
 install:
 
-ao_flight_test: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h $(INCS)
-       cc $(CFLAGS) -o $@ $<
+ao_flight_test: $(TEST_SRC_ALL) ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h $(INCS)
+       cc $(CFLAGS) -o $@ $(TEST_SRC) $(TEST_LIB)
 
-ao_flight_test_noisy_accel: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c $(INCS)
-       cc -DNOISY_ACCEL=1 $(CFLAGS) -o $@ $<
+ao_flight_test_noisy_accel: $(TEST_SRC_ALL) ao_host.h ao_flight.c ao_sample.c ao_kalman.c $(INCS)
+       cc -DNOISY_ACCEL=1 $(CFLAGS) -o $@ $(TEST_SRC) $(TEST_LIB)
 
-ao_flight_test_baro: ao_flight_test.c ao_host.h ao_flight.c  ao_sample.c ao_kalman.c $(INCS)
-       cc $(CFLAGS) -o $@ -DHAS_ACCEL=0 ao_flight_test.c
+ao_flight_test_baro: $(TEST_SRC_ALL) ao_host.h ao_flight.c  ao_sample.c ao_kalman.c $(INCS)
+       cc $(CFLAGS) -o $@ -DHAS_ACCEL=0 $(TEST_SRC) $(TEST_LIB)
 
-ao_flight_test_accel: ao_flight_test.c ao_host.h ao_flight.c  ao_sample.c ao_kalman.c $(INCS)
-       cc $(CFLAGS) -o $@ -DFORCE_ACCEL=1 ao_flight_test.c
+ao_flight_test_accel: $(TEST_SRC_ALL) ao_host.h ao_flight.c  ao_sample.c ao_kalman.c $(INCS)
+       cc $(CFLAGS) -o $@ -DFORCE_ACCEL=1 $(TEST_SRC) $(TEST_LIB)
 
-ao_flight_test_mm: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c ao_pyro.c ao_pyro.h $(INCS)
-       cc -DTELEMEGA=1 $(CFLAGS) -o $@ $< -lm
+ao_flight_test_mm: $(TEST_SRC_ALL) ao_host.h ao_flight.c ao_sample.c ao_kalman.c ao_pyro.c ao_pyro.h $(INCS)
+       cc -DTELEMEGA=1 $(CFLAGS) -o $@ $(TEST_SRC)  $(TEST_LIB) -lm
 
-ao_flight_test_metrum: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c ao_pyro.c ao_pyro.h $(INCS)
-       cc -DTELEMETRUM_V2=1 $(CFLAGS) -o $@ $< -lm
+ao_flight_test_metrum: $(TEST_SRC_ALL) ao_host.h ao_flight.c ao_sample.c ao_kalman.c ao_pyro.c ao_pyro.h $(INCS)
+       cc -DTELEMETRUM_V2=1 $(CFLAGS) -o $@ $(TEST_SRC)  $(TEST_LIB) -lm
 
-ao_flight_test_mini: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c ao_pyro.c ao_pyro.h $(INCS)
-       cc -DEASYMINI=1 -DHAS_ACCEL=0 $(CFLAGS) -o $@ $< -lm
+ao_flight_test_mini: $(TEST_SRC_ALL) ao_host.h ao_flight.c ao_sample.c ao_kalman.c ao_pyro.c ao_pyro.h $(INCS)
+       cc -DEASYMINI=1 -DHAS_ACCEL=0 $(CFLAGS) -o $@ $(TEST_SRC)  $(TEST_LIB) -lm
 
 ao_gps_test: ao_gps_test.c ao_gps_sirf.c ao_gps_print.c ao_host.h
        cc $(CFLAGS) -o $@ $<
diff --git a/src/test/ao_eeprom_read.c b/src/test/ao_eeprom_read.c
new file mode 100644 (file)
index 0000000..803ef36
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * Copyright Â© 2017 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, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ */
+
+#include "ao_eeprom_read.h"
+#include <json-c/json.h>
+#include <string.h>
+#include <errno.h>
+
+static struct json_object *
+ao_eeprom_read_config(FILE *file)
+{
+       char                    line[1024];
+       struct json_tokener     *tok;
+       struct json_object      *obj = NULL;
+       enum json_tokener_error err;
+
+       tok = json_tokener_new();
+       if (!tok)
+               goto fail_tok;
+
+       for (;;) {
+               if (fgets(line, sizeof(line), file) == NULL)
+                       goto fail_read;
+               obj = json_tokener_parse_ex(tok, line, strlen(line));
+               err = json_tokener_get_error(tok);
+               if (err == json_tokener_success)
+                       break;
+               if (err != json_tokener_continue)
+                       goto fail_read;
+       }
+       json_tokener_free(tok);
+       return obj;
+fail_read:
+       json_tokener_free(tok);
+fail_tok:
+       return NULL;
+}
+
+static int
+ao_eeprom_read_byte(FILE *file)
+{
+       int     byte;
+       if (fscanf(file, "%x", &byte) != 1)
+               return EOF;
+       return byte;
+}
+
+static int
+ao_eeprom_read_data(FILE *file, struct ao_eeprom *eeprom)
+{
+       uint8_t *data = NULL, *ndata;
+       int     len = 0;
+       int     size = 0;
+       int     byte;
+
+       data = malloc(size = 64);
+       if (!data)
+               goto fail_alloc;
+       while ((byte = ao_eeprom_read_byte(file)) != EOF) {
+               if (len == size) {
+                       ndata = realloc(data, size *= 2);
+                       if (!ndata)
+                               goto fail_realloc;
+                       data = ndata;
+               }
+               data[len++] = (uint8_t) byte;
+       }
+       eeprom->data = data;
+       eeprom->len = len;
+       return 1;
+fail_realloc:
+       free(data);
+fail_alloc:
+       return 0;
+}
+
+static int
+ao_json_get_int(struct json_object *obj, const char *key, int def)
+{
+       struct json_object *value;
+       int i;
+
+       if (!json_object_object_get_ex(obj, key, &value))
+               return def;
+       errno = 0;
+       i = (int) json_object_get_int(value);
+       if (errno != 0)
+               return def;
+       return i;
+}
+
+static const char *
+ao_json_get_string(struct json_object *obj, const char *key, const char *def)
+{
+       struct json_object *value;
+       const char *str;
+
+       if (!json_object_object_get_ex(obj, key, &value))
+               return def;
+       errno = 0;
+       str = json_object_get_string(value);
+       if (errno)
+               return def;
+       if (!str)
+               return def;
+       return str;
+}
+
+#if AO_PYRO_NUM
+static int
+ao_eeprom_get_pyro(struct ao_config *config, struct json_object *obj)
+{
+       struct json_object      *pyros;
+       struct json_object      *pyro;
+       int                     i, p;
+
+       if (!json_object_object_get_ex(obj, "pyros", &pyros))
+               return 1;
+
+       if (json_object_get_type(pyros) != json_type_array)
+               return 0;
+
+       for (i = 0; i < json_object_array_length(pyros); i++) {
+               pyro = json_object_array_get_idx(pyros, i);
+               if (pyro) {
+                       p = ao_json_get_int(pyro, "channel", -1);
+                       if (0 <= p && p < AO_PYRO_NUM) {
+                               config->pyro[p].flags           = ao_json_get_int(pyro, "flags", 0);
+                               config->pyro[p].accel_less      = ao_json_get_int(pyro, "accel_less", 0);
+                               config->pyro[p].accel_greater   = ao_json_get_int(pyro, "accel_greater", 0);
+                               config->pyro[p].speed_less      = ao_json_get_int(pyro, "speed_less", 0);
+                               config->pyro[p].speed_greater   = ao_json_get_int(pyro, "speed_greater", 0);
+                               config->pyro[p].height_less     = ao_json_get_int(pyro, "height_less", 0);
+                               config->pyro[p].height_greater  = ao_json_get_int(pyro, "height_greater", 0);
+                               config->pyro[p].orient_less     = ao_json_get_int(pyro, "orient_less", 0);
+                               config->pyro[p].orient_greater  = ao_json_get_int(pyro, "orient_greater", 0);
+                               config->pyro[p].time_less       = ao_json_get_int(pyro, "time_less", 0);
+                               config->pyro[p].time_greater    = ao_json_get_int(pyro, "time_greater", 0);
+                               config->pyro[p].delay           = ao_json_get_int(pyro, "delay", 0);
+                               config->pyro[p].state_less      = ao_json_get_int(pyro, "state_less", 0);
+                               config->pyro[p].state_greater_or_equal  = ao_json_get_int(pyro, "state_greater_or_equal", 0);
+                               config->pyro[p].motor           = ao_json_get_int(pyro, "motor", 0);
+                       }
+               }
+       }
+       return 1;
+}
+#endif
+
+static int
+ao_eeprom_get_ms5607(struct ao_ms5607_prom *ms5607_prom, struct json_object *obj)
+{
+       struct json_object      *ms5607;
+
+       if (!json_object_object_get_ex(obj, "ms5607", &ms5607))
+               return 1;
+
+       if (json_object_get_type(ms5607) != json_type_object)
+               return 0;
+
+       ms5607_prom->reserved = ao_json_get_int(ms5607, "reserved", 0);
+       ms5607_prom->sens =     ao_json_get_int(ms5607, "sens", 0);
+       ms5607_prom->off =      ao_json_get_int(ms5607, "off", 0);
+       ms5607_prom->tcs =      ao_json_get_int(ms5607, "tcs", 0);
+       ms5607_prom->tco =      ao_json_get_int(ms5607, "tco", 0);
+       ms5607_prom->tref =     ao_json_get_int(ms5607, "tref", 0);
+       ms5607_prom->tempsens = ao_json_get_int(ms5607, "tempsens", 0);
+       ms5607_prom->crc =      ao_json_get_int(ms5607, "crc", 0);
+       return 1;
+}
+
+static int
+ao_eeprom_get_config(struct ao_eeprom *ao_eeprom, struct json_object *obj)
+{
+       struct ao_config        *config = &ao_eeprom->config;
+       const char              *s;
+
+       if (json_object_get_type(obj) != json_type_object)
+               return 0;
+
+       ao_eeprom->log_format =         ao_json_get_int(obj, "log_format", 0);
+       ao_eeprom->serial_number =      ao_json_get_int(obj, "serial", 0);
+
+       config->major =                 ao_json_get_int(obj, "config_major", 0);
+       config->minor =                 ao_json_get_int(obj, "config_minor", 0);
+       if (config->major == 0 || config->minor == 0)
+               return 0;
+
+       config->main_deploy =           ao_json_get_int(obj, "main_deploy", 250);
+       config->accel_plus_g =          ao_json_get_int(obj, "accel_cal_plus", 0);
+
+       s = ao_json_get_string(obj, "callsign", "N0CALL");
+       strncpy(config->callsign, s, sizeof(config->callsign));
+
+       config->apogee_delay =          ao_json_get_int(obj, "apogee_delay", 0);
+       config->accel_minus_g =         ao_json_get_int(obj, "accel_cal_minus", 0);
+       config->radio_cal =             ao_json_get_int(obj, "radio_calibration", 0);
+       config->flight_log_max =        ao_json_get_int(obj, "flight_log_max", 0);
+       config->ignite_mode =           ao_json_get_int(obj, "ignite_mode", 0);
+       config->pad_orientation =       ao_json_get_int(obj, "pad_orientation", 0);
+       config->radio_setting =         ao_json_get_int(obj, "radio_setting", 0);
+       config->radio_enable =          ao_json_get_int(obj, "radio_enable", 1);
+       config->frequency =             ao_json_get_int(obj, "frequency", 434550);
+       config->apogee_lockout =        ao_json_get_int(obj, "apogee_lockout", 0);
+#if AO_PYRO_NUM
+       if (!ao_eeprom_get_pyro(config, obj))
+               return 0;
+#endif
+       config->ignite_mode =           ao_json_get_int(obj, "ignite_mode", 0);
+       config->ignite_mode =           ao_json_get_int(obj, "ignite_mode", 0);
+       config->ignite_mode =           ao_json_get_int(obj, "ignite_mode", 0);
+       config->ignite_mode =           ao_json_get_int(obj, "ignite_mode", 0);
+       config->ignite_mode =           ao_json_get_int(obj, "ignite_mode", 0);
+       config->ignite_mode =           ao_json_get_int(obj, "ignite_mode", 0);
+
+       if (!ao_eeprom_get_ms5607(&ao_eeprom->ms5607_prom, obj))
+               return 0;
+
+       return 1;
+}
+
+struct ao_eeprom *
+ao_eeprom_read(FILE *file)
+{
+       struct ao_eeprom        *ao_eeprom;
+       struct json_object      *obj;
+       int                     ret;
+
+       ao_eeprom = calloc(1, sizeof (struct ao_eeprom));
+       if (!ao_eeprom)
+               goto fail_ao_eeprom;
+
+       obj = ao_eeprom_read_config(file);
+       if (!obj)
+               goto fail_config;
+
+       ret = ao_eeprom_get_config(ao_eeprom, obj);
+       json_object_put(obj);
+       if (!ret)
+               goto fail_config;
+
+       if (!ao_eeprom_read_data(file, ao_eeprom))
+               goto fail_data;
+
+       return ao_eeprom;
+fail_data:
+fail_config:
+       free(ao_eeprom);
+fail_ao_eeprom:
+       return NULL;
+}
diff --git a/src/test/ao_eeprom_read.h b/src/test/ao_eeprom_read.h
new file mode 100644 (file)
index 0000000..03c327c
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright Â© 2017 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, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ */
+
+#ifndef _AO_EEPROM_READ_H_
+#define _AO_EEPROM_READ_H_
+
+#define __pdata
+#define __data
+#define __xdata
+#define __code
+#define __reentrant
+
+#include <stdint.h>
+#include <stdio.h>
+#include <ao_telemetry.h>
+#include <ao_config.h>
+#include <ao_ms5607.h>
+#include <ao_log.h>
+
+struct ao_eeprom {
+       struct ao_config        config;
+       struct ao_ms5607_prom   ms5607_prom;
+       int                     log_format;
+       uint16_t                serial_number;
+       uint8_t                 *data;
+       uint32_t                len;
+       uint32_t                size;
+};
+
+struct ao_eeprom *ao_eeprom_read(FILE *file);
+
+struct ao_eeprom *ao_eeprom_read_old(FILE *file);
+
+void ao_eeprom_free_data(struct ao_eeprom *ao_eeprom);
+
+#endif /* _AO_EEPROM_READ_H_ */
diff --git a/src/test/ao_eeprom_read_old.c b/src/test/ao_eeprom_read_old.c
new file mode 100644 (file)
index 0000000..c66ffae
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * Copyright Â© 2017 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.
+ */
+
+#include "ao_eeprom_read.h"
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+static int
+ao_eeprom_add_u8(struct ao_eeprom *ao_eeprom, uint8_t byte)
+{
+       if (ao_eeprom->len == ao_eeprom->size) {
+               uint32_t        nsize = ao_eeprom->size * 2;
+               uint8_t         *ndata = realloc(ao_eeprom->data, nsize);
+               if (!ndata)
+                       return 0;
+               ao_eeprom->data = ndata;
+               ao_eeprom->size = nsize;
+       }
+       ao_eeprom->data[ao_eeprom->len++] = byte;
+       return 1;
+}
+
+static int
+ao_eeprom_add_u16(struct ao_eeprom *ao_eeprom, uint16_t u16)
+{
+       if (!ao_eeprom_add_u8(ao_eeprom, u16 & 0xff))
+               return 0;
+
+       return ao_eeprom_add_u8(ao_eeprom, u16 >> 8);
+}
+
+struct ao_eeprom *
+ao_eeprom_read_old(FILE *file)
+{
+       struct ao_eeprom        *ao_eeprom;
+       char                    line[1024];
+       char                    *l;
+
+       ao_eeprom = calloc(1, sizeof (struct ao_eeprom));
+       if (!ao_eeprom)
+               return NULL;
+
+       ao_eeprom->log_format = -1;
+       ao_eeprom->size = 64;
+       ao_eeprom->data = malloc(ao_eeprom->size);
+       if (!ao_eeprom->data) {
+               free(ao_eeprom);
+               return NULL;
+       }
+       while (fgets(line, sizeof(line), file) != NULL) {
+               int nword;
+               char *words[64];
+               char *saveptr;
+               l = line;
+               for (nword = 0; nword < 64; nword++) {
+                       words[nword] = strtok_r(l, " \t\n", &saveptr);
+                       l = NULL;
+                       if (words[nword] == NULL)
+                               break;
+               }
+               if (((ao_eeprom->log_format == AO_LOG_FORMAT_TELEMEGA_OLD || ao_eeprom->log_format == AO_LOG_FORMAT_TELEMEGA) && nword == 30 && strlen(words[0]) == 1) ||
+                   ((ao_eeprom->log_format == AO_LOG_FORMAT_EASYMINI1 || ao_eeprom->log_format == AO_LOG_FORMAT_EASYMINI2) && nword == 14 && strlen(words[0]) == 1) ||
+                   (ao_eeprom->log_format == AO_LOG_FORMAT_TELEMETRUM && nword == 14 && strlen(words[0]) == 1))
+               {
+                       int             i;
+                       uint8_t         type;
+                       uint16_t        tick;
+
+                       type = words[0][0];
+                       tick = strtoul(words[1], NULL, 16);
+                       ao_eeprom_add_u8(ao_eeprom, type);
+                       ao_eeprom_add_u8(ao_eeprom, 0); /* checksum */
+                       ao_eeprom_add_u16(ao_eeprom, tick);
+                       for (i = 2; i < nword; i++)
+                               ao_eeprom_add_u8(ao_eeprom, strtoul(words[i], NULL, 16));
+               }
+               else if (nword == 4 && strlen(words[0]) == 1) {
+                       uint8_t         type;
+                       uint16_t        tick, a, b;
+                       type = words[0][0];
+                       tick = strtoul(words[1], NULL, 16);
+                       a = strtoul(words[2], NULL, 16);
+                       b = strtoul(words[3], NULL, 16);
+                       if (type == 'P')
+                               type = 'A';
+                       ao_eeprom_add_u8(ao_eeprom, type);
+                       ao_eeprom_add_u8(ao_eeprom, 0); /* checksum */
+                       ao_eeprom_add_u16(ao_eeprom, tick);
+                       ao_eeprom_add_u16(ao_eeprom, a);
+                       ao_eeprom_add_u16(ao_eeprom, b);
+               }
+               else if (nword == 3 && strcmp(words[0], "ms5607") == 0) {
+                       if (strcmp(words[1], "reserved:") == 0)
+                               ao_eeprom->ms5607_prom.reserved = strtoul(words[2], NULL, 10);
+                       else if (strcmp(words[1], "sens:") == 0)
+                               ao_eeprom->ms5607_prom.sens = strtoul(words[2], NULL, 10);
+                       else if (strcmp(words[1], "off:") == 0)
+                               ao_eeprom->ms5607_prom.off = strtoul(words[2], NULL, 10);
+                       else if (strcmp(words[1], "tcs:") == 0)
+                               ao_eeprom->ms5607_prom.tcs = strtoul(words[2], NULL, 10);
+                       else if (strcmp(words[1], "tco:") == 0)
+                               ao_eeprom->ms5607_prom.tco = strtoul(words[2], NULL, 10);
+                       else if (strcmp(words[1], "tref:") == 0)
+                               ao_eeprom->ms5607_prom.tref = strtoul(words[2], NULL, 10);
+                       else if (strcmp(words[1], "tempsens:") == 0)
+                               ao_eeprom->ms5607_prom.tempsens = strtoul(words[2], NULL, 10);
+                       else if (strcmp(words[1], "crc:") == 0)
+                               ao_eeprom->ms5607_prom.crc = strtoul(words[2], NULL, 10);
+                       continue;
+               }
+#if AO_NUM_PYRO
+               else if (nword >= 3 && strcmp(words[0], "Pyro") == 0) {
+                       int     p = strtoul(words[1], NULL, 10);
+                       int     i, j;
+                       struct ao_pyro  *pyro = &ao_eeprom->config.pyro[p];
+
+                       for (i = 2; i < nword; i++) {
+                               for (j = 0; j < NUM_PYRO_VALUES; j++)
+                                       if (!strcmp (words[i], ao_pyro_values[j].name))
+                                               break;
+                               if (j == NUM_PYRO_VALUES)
+                                       continue;
+                               pyro->flags |= ao_pyro_values[j].flag;
+                               if (ao_pyro_values[j].offset != NO_VALUE && i + 1 < nword) {
+                                       int16_t val = strtoul(words[++i], NULL, 10);
+                                       printf("pyro %d condition %s value %d\n", p, words[i-1], val);
+                                       *((int16_t *) ((char *) pyro + ao_pyro_values[j].offset)) = val;
+                               }
+                       }
+               }
+#endif
+               else if (nword == 2 && strcmp(words[0], "log-format") == 0) {
+                       ao_eeprom->log_format = strtoul(words[1], NULL, 10);
+               } else if (nword == 2 && strcmp(words[0], "serial-number") == 0) {
+                       ao_eeprom->serial_number = strtoul(words[1], NULL, 10);
+               } else if (nword >= 6 && strcmp(words[0], "Accel") == 0) {
+                       ao_eeprom->config.accel_plus_g = atoi(words[3]);
+                       ao_eeprom->config.accel_minus_g = atoi(words[5]);
+#if HAS_GYRO
+               } else if (nword >= 8 && strcmp(words[0], "IMU") == 0) {
+                       ao_eeprom->config.accel_zero_along = atoi(words[3]);
+                       ao_eeprom->config.accel_zero_across = atoi(words[5]);
+                       ao_eeprom->config.accel_zero_through = atoi(words[7]);
+#endif
+               } else if (nword >= 4 && strcmp(words[0], "Main") == 0) {
+                       ao_eeprom->config.main_deploy = atoi(words[2]);
+               } else if (nword >= 3 && strcmp(words[0], "Apogee") == 0 &&
+                          strcmp(words[1], "lockout:") == 0) {
+                       ao_eeprom->config.apogee_lockout = atoi(words[2]);
+               } else if (nword >= 3 && strcmp(words[0], "Pad") == 0 &&
+                          strcmp(words[1], "orientation:") == 0) {
+                       ao_eeprom->config.pad_orientation = atoi(words[2]);
+               }
+       }
+       return ao_eeprom;
+}
+
index 55bfe410c85f48296a85d76056b04fa3bae16c88..298848d6a46b4a7921bd8fddb9ba4605020e3e25 100644 (file)
@@ -191,7 +191,7 @@ ao_distance_from_pad(void)
        double  dist, bearing;
        if (!ao_gps_count)
                return 0;
-       
+
        cc_great_circle(ao_gps_first.latitude / 1e7,
                        ao_gps_first.longitude / 1e7,
                        ao_gps_static.latitude / 1e7,
@@ -308,6 +308,9 @@ struct ao_task {
 
 int    ao_flight_debug;
 
+struct ao_eeprom       *eeprom;
+uint32_t               eeprom_offset;
+
 FILE *emulator_in;
 char *emulator_app;
 char *emulator_name;
@@ -341,14 +344,18 @@ struct ao_cmds {
 #include <ao_ms5607.h>
 struct ao_ms5607_prom  ao_ms5607_prom;
 #include "ao_ms5607_convert.c"
+#if TELEMEGA
 #define AO_PYRO_NUM    4
 #include <ao_pyro.h>
+#endif
 #else
 #include "ao_convert.c"
 #endif
 
 #include <ao_config.h>
 #include <ao_fake_flight.h>
+#include <ao_eeprom_read.h>
+#include <ao_log.h>
 
 #define ao_config_get()
 
@@ -401,12 +408,16 @@ ao_pyro_pin_set(uint8_t pin, uint8_t value)
 
 #include "ao_pyro.c"
 #endif
+#include "ao_eeprom_read.c"
+#include "ao_eeprom_read_old.c"
 
 #define to_double(f)   ((f) / 65536.0)
 
 static int     ao_records_read = 0;
 static int     ao_eof_read = 0;
+#if !EASYMINI
 static int     ao_flight_ground_accel;
+#endif
 static int     ao_flight_started = 0;
 static int     ao_test_max_height;
 static double  ao_test_max_height_time;
@@ -418,11 +429,18 @@ static double     ao_test_landed_time;
 static int     landed_set;
 static double  landed_time;
 static double  landed_height;
+#if AO_PYRO_NUM
+static uint16_t        pyros_fired;
+#endif
 
 #if HAS_MPU6000
 static struct ao_mpu6000_sample        ao_ground_mpu6000;
 #endif
 
+#if HAS_ACCEL
+int ao_error_h_sq_avg;
+#endif
+
 void
 ao_test_exit(void)
 {
@@ -567,7 +585,7 @@ ao_insert(void)
 
                        ao_quaternion_normalize(&ao_mag, &ao_mag);
                        ao_quaternion_rotate(&ao_mag_rot, &ao_mag, &ao_rotation);
-                       
+
                        float                           ao_dot;
                        int                             ao_mag_angle;
 
@@ -722,17 +740,6 @@ void
 ao_sleep(void *wchan)
 {
        if (wchan == &ao_data_head) {
-               char            type = 0;
-               uint16_t        tick = 0;
-               uint16_t        a = 0, b = 0;
-               uint8_t         bytes[1024];
-               union ao_telemetry_all  telem;
-               char            line[1024];
-               char            *saveptr;
-               char            *l;
-               char            *words[64];
-               int             nword;
-
 #if TELEMEGA
                if (ao_flight_state >= ao_flight_boost && ao_flight_state < ao_flight_landed)
                        ao_pyro_check();
@@ -752,419 +759,183 @@ ao_sleep(void *wchan)
                                return;
                        }
 
-                       if (!fgets(line, sizeof (line), emulator_in)) {
-                               if (++ao_eof_read >= 1000) {
-                                       if (!ao_summary)
-                                               printf ("no more data, exiting simulation\n");
-                                       ao_test_exit();
-                               }
-                               ao_data_static.tick += 10;
-                               ao_insert();
-                               return;
-                       }
-                       l = line;
-                       for (nword = 0; nword < 64; nword++) {
-                               words[nword] = strtok_r(l, " \t\n", &saveptr);
-                               l = NULL;
-                               if (words[nword] == NULL)
-                                       break;
-                       }
+                       if (eeprom) {
 #if TELEMEGA
-                       if ((log_format == AO_LOG_FORMAT_TELEMEGA_OLD || log_format == AO_LOG_FORMAT_TELEMEGA) && nword == 30 && strlen(words[0]) == 1) {
-                               int     i;
-                               struct ao_ms5607_value  value;
-
-                               type = words[0][0];
-                               tick = strtoul(words[1], NULL, 16);
-//                             printf ("%c %04x", type, tick);
-                               for (i = 2; i < nword; i++) {
-                                       bytes[i - 2] = strtoul(words[i], NULL, 16);
-//                                     printf(" %02x", bytes[i-2]);
-                               }
-//                             printf ("\n");
-                               switch (type) {
-                               case 'F':
-                                       ao_flight_number = uint16(bytes, 0);
-                                       ao_flight_ground_accel = int16(bytes, 2);
-                                       ao_flight_started = 1;
-                                       ao_ground_pres = int32(bytes, 4);
-                                       ao_ground_height = ao_pa_to_altitude(ao_ground_pres);
-                                       ao_ground_accel_along = int16(bytes, 8);
-                                       ao_ground_accel_across = int16(bytes, 10);
-                                       ao_ground_accel_through = int16(bytes, 12);
-                                       ao_ground_roll = int16(bytes, 14);
-                                       ao_ground_pitch = int16(bytes, 16);
-                                       ao_ground_yaw = int16(bytes, 18);
-                                       ao_ground_mpu6000.accel_x = ao_ground_accel_across;
-                                       ao_ground_mpu6000.accel_y = ao_ground_accel_along;
-                                       ao_ground_mpu6000.accel_z = ao_ground_accel_through;
-                                       ao_ground_mpu6000.gyro_x = ao_ground_pitch >> 9;
-                                       ao_ground_mpu6000.gyro_y = ao_ground_roll >> 9;
-                                       ao_ground_mpu6000.gyro_z = ao_ground_yaw >> 9;
-                                       break;
-                               case 'A':
-                                       ao_data_static.tick = tick;
-                                       ao_data_static.ms5607_raw.pres = int32(bytes, 0);
-                                       ao_data_static.ms5607_raw.temp = int32(bytes, 4);
-                                       ao_ms5607_convert(&ao_data_static.ms5607_raw, &value);
-                                       ao_data_static.mpu6000.accel_x = int16(bytes, 8);
-                                       ao_data_static.mpu6000.accel_y = int16(bytes, 10);
-                                       ao_data_static.mpu6000.accel_z = int16(bytes, 12);
-                                       ao_data_static.mpu6000.gyro_x = int16(bytes, 14);
-                                       ao_data_static.mpu6000.gyro_y = int16(bytes, 16);
-                                       ao_data_static.mpu6000.gyro_z = int16(bytes, 18);
-                                       ao_data_static.hmc5883.x = int16(bytes, 20);
-                                       ao_data_static.hmc5883.y = int16(bytes, 22);
-                                       ao_data_static.hmc5883.z = int16(bytes, 24);
-#if HAS_MMA655X
-                                       ao_data_static.mma655x = int16(bytes, 26);
-                                       if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP)
-                                               ao_data_static.mma655x = ao_data_accel_invert(ao_data_static.mma655x);
+                               struct ao_log_mega      *log_mega;
 #endif
-                                       ao_records_read++;
-                                       ao_insert();
-                                       return;
-                               case 'G':
-                                       ao_gps_prev = ao_gps_static;
-                                       ao_gps_static.tick = tick;
-                                       ao_gps_static.latitude = int32(bytes, 0);
-                                       ao_gps_static.longitude = int32(bytes, 4);
-                                       {
-                                               int32_t altitude = int32(bytes, 8);
-                                               AO_TELEMETRY_LOCATION_SET_ALTITUDE(&ao_gps_static, altitude);
-                                       }
-                                       ao_gps_static.flags = bytes[13];
-                                       if (!ao_gps_count)
-                                               ao_gps_first = ao_gps_static;
-                                       ao_gps_count++;
-                                       break;
-                               }
-                               continue;
-                       } else if (nword == 3 && strcmp(words[0], "ms5607") == 0) {
-                               if (strcmp(words[1], "reserved:") == 0)
-                                       ao_ms5607_prom.reserved = strtoul(words[2], NULL, 10);
-                               else if (strcmp(words[1], "sens:") == 0)
-                                       ao_ms5607_prom.sens = strtoul(words[2], NULL, 10);
-                               else if (strcmp(words[1], "off:") == 0)
-                                       ao_ms5607_prom.off = strtoul(words[2], NULL, 10);
-                               else if (strcmp(words[1], "tcs:") == 0)
-                                       ao_ms5607_prom.tcs = strtoul(words[2], NULL, 10);
-                               else if (strcmp(words[1], "tco:") == 0)
-                                       ao_ms5607_prom.tco = strtoul(words[2], NULL, 10);
-                               else if (strcmp(words[1], "tref:") == 0)
-                                       ao_ms5607_prom.tref = strtoul(words[2], NULL, 10);
-                               else if (strcmp(words[1], "tempsens:") == 0)
-                                       ao_ms5607_prom.tempsens = strtoul(words[2], NULL, 10);
-                               else if (strcmp(words[1], "crc:") == 0)
-                                       ao_ms5607_prom.crc = strtoul(words[2], NULL, 10);
-                               continue;
-                       } else if (nword >= 3 && strcmp(words[0], "Pyro") == 0) {
-                               int     p = strtoul(words[1], NULL, 10);
-                               int     i, j;
-                               struct ao_pyro  *pyro = &ao_config.pyro[p];
-
-                               for (i = 2; i < nword; i++) {
-                                       for (j = 0; j < NUM_PYRO_VALUES; j++)
-                                               if (!strcmp (words[i], ao_pyro_values[j].name))
-                                                       break;
-                                       if (j == NUM_PYRO_VALUES)
-                                               continue;
-                                       pyro->flags |= ao_pyro_values[j].flag;
-                                       if (ao_pyro_values[j].offset != NO_VALUE && i + 1 < nword) {
-                                               int16_t val = strtoul(words[++i], NULL, 10);
-                                               printf("pyro %d condition %s value %d\n", p, words[i-1], val);
-                                               *((int16_t *) ((char *) pyro + ao_pyro_values[j].offset)) = val;
-                                       }
-                               }
-                       }
+#if TELEMETRUM_V2
+                               struct ao_log_metrum    *log_metrum;
 #endif
 #if EASYMINI
-                       if ((log_format == AO_LOG_FORMAT_EASYMINI1 || log_format == AO_LOG_FORMAT_EASYMINI2) && nword == 14 && strlen(words[0]) == 1) {
-                               int     i;
-                               struct ao_ms5607_value  value;
-
-                               type = words[0][0];
-                               tick = strtoul(words[1], NULL, 16);
-//                             printf ("%c %04x", type, tick);
-                               for (i = 2; i < nword; i++) {
-                                       bytes[i - 2] = strtoul(words[i], NULL, 16);
-//                                     printf(" %02x", bytes[i-2]);
-                               }
-//                             printf ("\n");
-                               switch (type) {
-                               case 'F':
-                                       ao_flight_started = 1;
-                                       ao_flight_number = uint16(bytes, 0);
-                                       ao_ground_pres = uint32(bytes, 4);
-                                       ao_ground_height = ao_pa_to_altitude(ao_ground_pres);
-#if 0
-                                       printf("ground pres %d height %d\n", ao_ground_pres, ao_ground_height);
-                                       printf("sens %d off %d tcs %d tco %d tref %d tempsens %d crc %d\n",
-                                              ao_ms5607_prom.sens,
-                                              ao_ms5607_prom.off,
-                                              ao_ms5607_prom.tcs,
-                                              ao_ms5607_prom.tco,
-                                              ao_ms5607_prom.tref,
-                                              ao_ms5607_prom.tempsens,
-                                              ao_ms5607_prom.crc);
+                               struct ao_log_mini      *log_mini;
 #endif
-                                       break;
-                               case 'A':
-                                       ao_data_static.tick = tick;
-                                       ao_data_static.ms5607_raw.pres = int24(bytes, 0);
-                                       ao_data_static.ms5607_raw.temp = int24(bytes, 3);
-#if 0
-                                       printf("raw pres %d temp %d\n",
-                                              ao_data_static.ms5607_raw.pres,
-                                              ao_data_static.ms5607_raw.temp);
+#if TELEMETRUM_V1
+                               struct ao_log_record    *log_record;
 #endif
-                                       ao_ms5607_convert(&ao_data_static.ms5607_raw, &value);
-//                                     printf("pres %d height %d\n", value.pres, ao_pa_to_altitude(value.pres));
-                                       ao_records_read++;
+
+                               if (eeprom_offset >= eeprom->len) {
+                                       if (++ao_eof_read >= 1000)
+                                               if (!ao_summary)
+                                                       printf ("no more data, exiting simulation\n");
+                                       ao_test_exit();
+                                       ao_data_static.tick += 10;
                                        ao_insert();
                                        return;
                                }
-                               continue;
-                       } else if (nword == 3 && strcmp(words[0], "ms5607") == 0) {
-                               if (strcmp(words[1], "reserved:") == 0)
-                                       ao_ms5607_prom.reserved = strtoul(words[2], NULL, 10);
-                               else if (strcmp(words[1], "sens:") == 0)
-                                       ao_ms5607_prom.sens = strtoul(words[2], NULL, 10);
-                               else if (strcmp(words[1], "off:") == 0)
-                                       ao_ms5607_prom.off = strtoul(words[2], NULL, 10);
-                               else if (strcmp(words[1], "tcs:") == 0)
-                                       ao_ms5607_prom.tcs = strtoul(words[2], NULL, 10);
-                               else if (strcmp(words[1], "tco:") == 0)
-                                       ao_ms5607_prom.tco = strtoul(words[2], NULL, 10);
-                               else if (strcmp(words[1], "tref:") == 0)
-                                       ao_ms5607_prom.tref = strtoul(words[2], NULL, 10);
-                               else if (strcmp(words[1], "tempsens:") == 0)
-                                       ao_ms5607_prom.tempsens = strtoul(words[2], NULL, 10);
-                               else if (strcmp(words[1], "crc:") == 0)
-                                       ao_ms5607_prom.crc = strtoul(words[2], NULL, 10);
-                               continue;
-                       }
+                               switch (eeprom->log_format) {
+#if TELEMEGA
+                               case AO_LOG_FORMAT_TELEMEGA_OLD:
+                               case AO_LOG_FORMAT_TELEMEGA:
+                                       log_mega = (struct ao_log_mega *) &eeprom->data[eeprom_offset];
+                                       eeprom_offset += sizeof (*log_mega);
+                                       switch (log_mega->type) {
+                                       case AO_LOG_FLIGHT:
+                                               ao_flight_number = log_mega->u.flight.flight;
+                                               ao_flight_ground_accel = log_mega->u.flight.ground_accel;
+                                               ao_flight_started = 1;
+                                               ao_ground_pres = log_mega->u.flight.ground_pres;
+                                               ao_ground_height = ao_pa_to_altitude(ao_ground_pres);
+                                               ao_ground_accel_along = log_mega->u.flight.ground_accel_along;
+                                               ao_ground_accel_across = log_mega->u.flight.ground_accel_across;
+                                               ao_ground_accel_through = log_mega->u.flight.ground_accel_through;
+                                               ao_ground_roll = log_mega->u.flight.ground_roll;
+                                               ao_ground_pitch = log_mega->u.flight.ground_pitch;
+                                               ao_ground_yaw = log_mega->u.flight.ground_yaw;
+                                               ao_ground_mpu6000.accel_x = ao_ground_accel_across;
+                                               ao_ground_mpu6000.accel_y = ao_ground_accel_along;
+                                               ao_ground_mpu6000.accel_z = ao_ground_accel_through;
+                                               ao_ground_mpu6000.gyro_x = ao_ground_pitch >> 9;
+                                               ao_ground_mpu6000.gyro_y = ao_ground_roll >> 9;
+                                               ao_ground_mpu6000.gyro_z = ao_ground_yaw >> 9;
+                                               break;
+                                       case AO_LOG_STATE:
+                                               break;
+                                       case AO_LOG_SENSOR:
+                                               ao_data_static.tick = log_mega->tick;
+                                               ao_data_static.ms5607_raw.pres = log_mega->u.sensor.pres;
+                                               ao_data_static.ms5607_raw.temp = log_mega->u.sensor.temp;
+                                               ao_data_static.mpu6000.accel_x = log_mega->u.sensor.accel_x;
+                                               ao_data_static.mpu6000.accel_y = log_mega->u.sensor.accel_y;
+                                               ao_data_static.mpu6000.accel_z = log_mega->u.sensor.accel_z;
+                                               ao_data_static.mpu6000.gyro_x = log_mega->u.sensor.gyro_x;
+                                               ao_data_static.mpu6000.gyro_y = log_mega->u.sensor.gyro_y;
+                                               ao_data_static.mpu6000.gyro_z = log_mega->u.sensor.gyro_z;
+                                               ao_data_static.hmc5883.x = log_mega->u.sensor.mag_x;
+                                               ao_data_static.hmc5883.y = log_mega->u.sensor.mag_y;
+                                               ao_data_static.hmc5883.z = log_mega->u.sensor.mag_z;
+                                               ao_data_static.mma655x = log_mega->u.sensor.accel;
+                                               if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP)
+                                                       ao_data_static.mma655x = ao_data_accel_invert(ao_data_static.mma655x);
+                                               ao_records_read++;
+                                               ao_insert();
+                                               return;
+                                       case AO_LOG_TEMP_VOLT:
+                                               if (pyros_fired != log_mega->u.volt.pyro) {
+                                                       printf("pyro changed %x -> %x\n", pyros_fired, log_mega->u.volt.pyro);
+                                                       pyros_fired = log_mega->u.volt.pyro;
+                                               }
+                                               break;
+                                       case AO_LOG_GPS_TIME:
+                                               ao_gps_prev = ao_gps_static;
+                                               ao_gps_static.tick = log_mega->tick;
+                                               ao_gps_static.latitude = log_mega->u.gps.latitude;
+                                               ao_gps_static.longitude = log_mega->u.gps.longitude;
+                                               {
+                                                       int16_t altitude_low = log_mega->u.gps.altitude_low;
+                                                       int16_t altitude_high = log_mega->u.gps.altitude_high;
+                                                       int32_t altitude = altitude_low | ((int32_t) altitude_high << 16);
+
+                                                       AO_TELEMETRY_LOCATION_SET_ALTITUDE(&ao_gps_static, altitude);
+                                               }
+                                               ao_gps_static.flags = log_mega->u.gps.flags;
+                                               if (!ao_gps_count)
+                                                       ao_gps_first = ao_gps_static;
+                                               ao_gps_count++;
+                                               break;
+                                       case AO_LOG_GPS_SAT:
+                                               break;
+                                       }
+                                       break;
 #endif
 #if TELEMETRUM_V2
-                       if (log_format == AO_LOG_FORMAT_TELEMETRUM && nword == 14 && strlen(words[0]) == 1) {
-                               int     i;
-                               struct ao_ms5607_value  value;
-
-                               type = words[0][0];
-                               tick = strtoul(words[1], NULL, 16);
-//                             printf ("%c %04x", type, tick);
-                               for (i = 2; i < nword; i++) {
-                                       bytes[i - 2] = strtoul(words[i], NULL, 16);
-//                                     printf(" %02x", bytes[i-2]);
-                               }
-//                             printf ("\n");
-                               switch (type) {
-                               case 'F':
-                                       ao_flight_number = uint16(bytes, 0);
-                                       ao_flight_ground_accel = int16(bytes, 2);
-                                       ao_flight_started = 1;
-                                       ao_ground_pres = int32(bytes, 4);
-                                       ao_ground_height = ao_pa_to_altitude(ao_ground_pres);
+                               case AO_LOG_FORMAT_TELEMETRUM:
+                                       log_metrum = (struct ao_log_metrum *) &eeprom->data[eeprom_offset];
+                                       eeprom_offset += sizeof (*log_metrum);
+                                       switch (log_metrum->type) {
+                                       case AO_LOG_FLIGHT:
+                                               ao_flight_started = 1;
+                                               ao_flight_number = log_metrum->u.flight.flight;
+                                               ao_flight_ground_accel = log_metrum->u.flight.ground_accel;
+                                               ao_ground_pres = log_metrum->u.flight.ground_pres;
+                                               ao_ground_height = ao_pa_to_altitude(ao_ground_pres);
+                                               break;
+                                       case AO_LOG_SENSOR:
+                                               ao_data_static.tick = log_metrum->tick;
+                                               ao_data_static.ms5607_raw.pres = log_metrum->u.sensor.pres;
+                                               ao_data_static.ms5607_raw.temp = log_metrum->u.sensor.temp;
+                                               ao_data_static.mma655x = log_metrum->u.sensor.accel;
+                                               ao_records_read++;
+                                               ao_insert();
+                                               return;
+                                       }
                                        break;
-                               case 'A':
-                                       ao_data_static.tick = tick;
-                                       ao_data_static.ms5607_raw.pres = int32(bytes, 0);
-                                       ao_data_static.ms5607_raw.temp = int32(bytes, 4);
-                                       ao_ms5607_convert(&ao_data_static.ms5607_raw, &value);
-                                       ao_data_static.mma655x = int16(bytes, 8);
-                                       ao_records_read++;
-                                       ao_insert();
-                                       return;
-                               }
-                               continue;
-                       } else if (nword == 3 && strcmp(words[0], "ms5607") == 0) {
-                               if (strcmp(words[1], "reserved:") == 0)
-                                       ao_ms5607_prom.reserved = strtoul(words[2], NULL, 10);
-                               else if (strcmp(words[1], "sens:") == 0)
-                                       ao_ms5607_prom.sens = strtoul(words[2], NULL, 10);
-                               else if (strcmp(words[1], "off:") == 0)
-                                       ao_ms5607_prom.off = strtoul(words[2], NULL, 10);
-                               else if (strcmp(words[1], "tcs:") == 0)
-                                       ao_ms5607_prom.tcs = strtoul(words[2], NULL, 10);
-                               else if (strcmp(words[1], "tco:") == 0)
-                                       ao_ms5607_prom.tco = strtoul(words[2], NULL, 10);
-                               else if (strcmp(words[1], "tref:") == 0)
-                                       ao_ms5607_prom.tref = strtoul(words[2], NULL, 10);
-                               else if (strcmp(words[1], "tempsens:") == 0)
-                                       ao_ms5607_prom.tempsens = strtoul(words[2], NULL, 10);
-                               else if (strcmp(words[1], "crc:") == 0)
-                                       ao_ms5607_prom.crc = strtoul(words[2], NULL, 10);
-                               continue;
-                       }
 #endif
-#if TELEMETRUM_V1
-                       if (nword == 4 && log_format != AO_LOG_FORMAT_TELEMEGA) {
-                               type = words[0][0];
-                               tick = strtoul(words[1], NULL, 16);
-                               a = strtoul(words[2], NULL, 16);
-                               b = strtoul(words[3], NULL, 16);
-                               if (type == 'P')
-                                       type = 'A';
-                       }
-#endif
-                       else if (nword == 2 && strcmp(words[0], "log-format") == 0) {
-                               log_format = strtoul(words[1], NULL, 10);
-                       } else if (nword == 2 && strcmp(words[0], "serial-number") == 0) {
-                               ao_serial_number = strtoul(words[1], NULL, 10);
-                       } else if (nword >= 6 && strcmp(words[0], "Accel") == 0) {
-                               ao_config.accel_plus_g = atoi(words[3]);
-                               ao_config.accel_minus_g = atoi(words[5]);
-#ifdef TELEMEGA
-                       } else if (nword >= 8 && strcmp(words[0], "IMU") == 0) {
-                               ao_config.accel_zero_along = atoi(words[3]);
-                               ao_config.accel_zero_across = atoi(words[5]);
-                               ao_config.accel_zero_through = atoi(words[7]);
+#if EASYMINI
+                               case AO_LOG_FORMAT_EASYMINI1:
+                               case AO_LOG_FORMAT_EASYMINI2:
+                               case AO_LOG_FORMAT_TELEMINI3:
+                                       log_mini = (struct ao_log_mini *) &eeprom->data[eeprom_offset];
+                                       eeprom_offset += sizeof (*log_mini);
+                                       switch (log_mini->type) {
+                                       case AO_LOG_FLIGHT:
+                                               ao_flight_started = 1;
+                                               ao_flight_number = log_mini->u.flight.flight;
+                                               ao_ground_pres = log_mini->u.flight.ground_pres;
+                                               ao_ground_height = ao_pa_to_altitude(ao_ground_pres);
+                                               break;
+                                       case AO_LOG_SENSOR:
+                                               ao_data_static.tick = log_mini->tick;
+                                               ao_data_static.ms5607_raw.pres = int24(log_mini->u.sensor.pres, 0);
+                                               ao_data_static.ms5607_raw.temp = int24(log_mini->u.sensor.temp, 0);
+                                               ao_records_read++;
+                                               ao_insert();
+                                               return;
+                                       }
+                                       break;
 #endif
-                       } else if (nword >= 4 && strcmp(words[0], "Main") == 0) {
-                               ao_config.main_deploy = atoi(words[2]);
-                       } else if (nword >= 3 && strcmp(words[0], "Apogee") == 0 &&
-                                  strcmp(words[1], "lockout:") == 0) {
-                               ao_config.apogee_lockout = atoi(words[2]);
-                       } else if (nword >= 3 && strcmp(words[0], "Pad") == 0 &&
-                                  strcmp(words[1], "orientation:") == 0) {
-                               ao_config.pad_orientation = atoi(words[2]);
-                       } else if (nword >= 36 && strcmp(words[0], "CALL") == 0) {
-                               tick = atoi(words[10]);
-                               if (!ao_flight_started) {
-                                       type = 'F';
-                                       a = atoi(words[26]);
-                                       ao_flight_started = 1;
-                               } else {
-                                       type = 'A';
-                                       a = atoi(words[12]);
-                                       b = atoi(words[14]);
-                               }
-                       } else if (nword == 3 && strcmp(words[0], "BARO") == 0) {
-                               tick = strtol(words[1], NULL, 16);
-                               a = 16384 - 328;
-                               b = strtol(words[2], NULL, 10);
-                               type = 'A';
-                               if (!ao_flight_started) {
-                                       ao_flight_ground_accel = 16384 - 328;
-                                       ao_config.accel_plus_g = 16384 - 328;
-                                       ao_config.accel_minus_g = 16384 + 328;
-                                       ao_flight_started = 1;
-                               }
-                       } else if (nword == 2 && strcmp(words[0], "TELEM") == 0) {
-                               __xdata char    *hex = words[1];
-                               char    elt[3];
-                               int     i, len;
-                               uint8_t sum;
-
-                               len = strlen(hex);
-                               if (len > sizeof (bytes) * 2) {
-                                       len = sizeof (bytes)*2;
-                                       hex[len] = '\0';
-                               }
-                               for (i = 0; i < len; i += 2) {
-                                       elt[0] = hex[i];
-                                       elt[1] = hex[i+1];
-                                       elt[2] = '\0';
-                                       bytes[i/2] = (uint8_t) strtol(elt, NULL, 16);
-                               }
-                               len = i/2;
-                               if (bytes[0] != len - 2) {
-                                       printf ("bad length %d != %d\n", bytes[0], len - 2);
-                                       continue;
-                               }
-                               sum = 0x5a;
-                               for (i = 1; i < len-1; i++)
-                                       sum += bytes[i];
-                               if (sum != bytes[len-1]) {
-                                       printf ("bad checksum\n");
-                                       continue;
-                               }
-                               if ((bytes[len-2] & 0x80) == 0) {
-                                       continue;
-                               }
-                               if (len == 36) {
-                                       ao_xmemcpy(&telem, bytes + 1, 32);
-                                       tick = telem.generic.tick;
-                                       switch (telem.generic.type) {
-                                       case AO_TELEMETRY_SENSOR_TELEMETRUM:
-                                       case AO_TELEMETRY_SENSOR_TELEMINI:
-                                       case AO_TELEMETRY_SENSOR_TELENANO:
-                                               if (!ao_flight_started) {
-                                                       ao_flight_ground_accel = telem.sensor.ground_accel;
-                                                       ao_config.accel_plus_g = telem.sensor.accel_plus_g;
-                                                       ao_config.accel_minus_g = telem.sensor.accel_minus_g;
-                                                       ao_flight_started = 1;
-                                               }
-                                               type = 'A';
-                                               a = telem.sensor.accel;
-                                               b = telem.sensor.pres;
+#if TELEMETRUM_V1
+                               case AO_LOG_FORMAT_FULL:
+                               case AO_LOG_FORMAT_TINY:
+                                       log_record = (struct ao_log_record *) &eeprom->data[eeprom_offset];
+                                       eeprom_offset += sizeof (*log_record);
+                                       switch (log_record->type) {
+                                       case AO_LOG_FLIGHT:
+                                               ao_flight_started = 1;
+                                               ao_flight_ground_accel = log_record->u.flight.ground_accel;
+                                               ao_flight_number = log_record->u.flight.flight;
+                                               break;
+                                       case AO_LOG_SENSOR:
+                                       case 'P':       /* ancient telemini */
+                                               ao_data_static.tick = log_record->tick;
+                                               ao_data_static.adc.accel = log_record->u.sensor.accel;
+                                               ao_data_static.adc.pres_real = log_record->u.sensor.pres;
+                                               ao_data_static.adc.pres = log_record->u.sensor.pres;
+                                               ao_records_read++;
+                                               ao_insert();
+                                               return;
+                                       case AO_LOG_TEMP_VOLT:
+                                               ao_data_static.tick = log_record->tick;;
+                                               ao_data_static.adc.temp = log_record->u.temp_volt.temp;
+                                               ao_data_static.adc.v_batt = log_record->u.temp_volt.v_batt;
                                                break;
                                        }
-                               } else if (len == 99) {
-                                       ao_flight_started = 1;
-                                       tick = uint16(bytes+1, 21);
-                                       ao_flight_ground_accel = int16(bytes+1, 7);
-                                       ao_config.accel_plus_g = int16(bytes+1, 17);
-                                       ao_config.accel_minus_g = int16(bytes+1, 19);
-                                       type = 'A';
-                                       a = int16(bytes+1, 23);
-                                       b = int16(bytes+1, 25);
-                               } else if (len == 98) {
-                                       ao_flight_started = 1;
-                                       tick = uint16(bytes+1, 20);
-                                       ao_flight_ground_accel = int16(bytes+1, 6);
-                                       ao_config.accel_plus_g = int16(bytes+1, 16);
-                                       ao_config.accel_minus_g = int16(bytes+1, 18);
-                                       type = 'A';
-                                       a = int16(bytes+1, 22);
-                                       b = int16(bytes+1, 24);
-                               } else {
-                                       printf("unknown len %d\n", len);
-                                       continue;
-                               }
-                       }
-                       if (type != 'F' && !ao_flight_started)
-                               continue;
-
-#if TELEMEGA || TELEMETRUM_V2 || EASYMINI
-                       (void) a;
-                       (void) b;
-#else
-                       switch (type) {
-                       case 'F':
-                               ao_flight_ground_accel = a;
-                               ao_flight_number = b;
-                               if (ao_config.accel_plus_g == 0) {
-                                       ao_config.accel_plus_g = a;
-                                       ao_config.accel_minus_g = a + 530;
+                                       break;
+#endif
+                               default:
+                                       printf ("invalid log format %d\n", log_format);
+                                       ao_test_exit();
                                }
-                               if (ao_config.main_deploy == 0)
-                                       ao_config.main_deploy = 250;
-                               ao_flight_started = 1;
-                               break;
-                       case 'S':
-                               break;
-                       case 'A':
-                               ao_data_static.tick = tick;
-                               ao_data_static.adc.accel = a;
-                               ao_data_static.adc.pres_real = b;
-                               ao_data_static.adc.pres = b;
-                               ao_records_read++;
-                               ao_insert();
-                               return;
-                       case 'T':
-                               ao_data_static.tick = tick;
-                               ao_data_static.adc.temp = a;
-                               ao_data_static.adc.v_batt = b;
-                               break;
-                       case 'D':
-                       case 'G':
-                       case 'N':
-                       case 'W':
-                       case 'H':
-                               break;
                        }
-#endif
                }
 
        }
@@ -1190,6 +961,26 @@ void run_flight_fixed(char *name, FILE *f, int summary, char *info)
        emulator_info = info;
        ao_summary = summary;
 
+       if (strstr(name, ".eeprom") != NULL) {
+               char    c;
+
+               c = getc(f);
+               ungetc(c, f);
+               if (c == '{')
+                       eeprom = ao_eeprom_read(f);
+               else
+                       eeprom = ao_eeprom_read_old(f);
+
+               if (eeprom) {
+#if HAS_MS5607
+                       ao_ms5607_prom = eeprom->ms5607_prom;
+#endif
+                       ao_config = eeprom->config;
+                       ao_serial_number = eeprom->serial_number;
+                       log_format = eeprom->log_format;
+               }
+       }
+
        ao_flight_init();
        ao_flight();
 }
index a1c4a0a17dd56fc48b0ba228e7dbc1a6bec39a33..9dd2ceac6429c93f7931525eac89e5d52d6989bb 100644 (file)
@@ -128,7 +128,7 @@ clean-local:
                altoslib_*.jar altosuilib_*.jar \
                $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(FREETTS_CLASS) $(LIBALTOS) Manifest.txt Manifest-fat.txt \
                telegps telegps-test telegps-jdb macosx linux windows telegps-windows.log \
-               telegps-windows.nsi *.desktop $(MDWN)
+               telegps-windows.nsi *.desktop *.mdwn
 
 EXTRA_DIST = $(desktop_file).in
 
index 88ced19248298b0c80119826de3a3040eb0d2a83..87683c2baf5b3155f7731bf2d9ebef8914e0e0c1 100644 (file)
@@ -619,7 +619,7 @@ public class TeleGPSConfigUI
                return true;
        }
 
-       void set_dirty() {
+       public void set_dirty() {
                dirty = true;
                save.setEnabled(true);
        }
@@ -634,6 +634,17 @@ public class TeleGPSConfigUI
                super.dispose();
        }
 
+       public int accel_cal_plus() {
+               return AltosLib.MISSING;
+       }
+
+       public int accel_cal_minus() {
+               return AltosLib.MISSING;
+       }
+
+       public void set_accel_cal(int accel_plus, int accel_minus) {
+       }
+
        /* Listen for events from our buttons */
        public void actionPerformed(ActionEvent e) {
                String  cmd = e.getActionCommand();