]> git.gag.com Git - fw/altos/commitdiff
doc: Add 1.9.22 release notes master
authorKeith Packard <keithp@keithp.com>
Fri, 27 Jun 2025 20:22:18 +0000 (13:22 -0700)
committerKeith Packard <keithp@keithp.com>
Fri, 27 Jun 2025 20:22:18 +0000 (13:22 -0700)
Signed-off-by: Keith Packard <keithp@keithp.com>
191 files changed:
Makefile.am
Releasing
altosdroid/app-debug.apk [new file with mode: 0644]
altosdroid/app-release.apk [new file with mode: 0644]
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDroid.java
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosDroidPreferencesBackend.java
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosMapOffline.java
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosMapOnline.java
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosVoice.java
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/IdleModeActivity.java
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/IgniterActivity.java
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/PreloadMapActivity.java
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/SelectTrackerActivity.java
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TabMap.java
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TabPad.java
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/TabRecover.java
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/Tracker.java
altosdroid/app/src/main/res/layout/manage_frequencies.xml
altoslib/AltosCalData.java
altoslib/AltosConfigData.java
altoslib/AltosConfigValues.java
altoslib/AltosConvert.java
altoslib/AltosDataListener.java
altoslib/AltosEepromRecordMega.java
altoslib/AltosEepromRecordMetrum.java
altoslib/AltosEepromRecordSet.java
altoslib/AltosEepromRecordTimer.java
altoslib/AltosIdleFetch.java
altoslib/AltosLib.java
altoslib/AltosMapStore.java
altoslib/AltosRecordSet.java
altoslib/AltosSensorMega.java
altoslib/AltosSensorMetrum.java
altoslib/AltosSensorTGPS4.java [new file with mode: 0644]
altoslib/AltosTelemetry.java
altoslib/AltosTelemetryFile.java
altoslib/AltosTelemetryMegaData.java
altoslib/AltosTelemetryMetrumSensor.java
altoslib/AltosTelemetryStandard.java
altoslib/Makefile.am
altosui/AltosConfigFCUI.java
altosui/AltosGraphUI.java
altosui/Makefile.am
altosui/altos-windows.nsi.in
altosuilib/AltosFlightConfigTable.java [new file with mode: 0644]
altosuilib/AltosFlightPyroTable.java [new file with mode: 0644]
altosuilib/AltosGraph.java
altosuilib/AltosUIAxis.java
altosuilib/AltosUIEnable.java
altosuilib/AltosUIFlightSeries.java
altosuilib/AltosUIGraph.java
altosuilib/AltosUIGrapher.java
altosuilib/AltosUILineStyle.java
altosuilib/AltosUIMarker.java
altosuilib/AltosUITimeSeries.java
altosuilib/Makefile.am
ao-bringup/test-easymega [deleted file]
ao-bringup/test-easymega-v2.0 [new file with mode: 0755]
ao-bringup/test-easymega-v3.0 [new file with mode: 0755]
ao-bringup/test-easymini-v2.0 [new file with mode: 0755]
ao-bringup/test-easytimer [deleted file]
ao-bringup/test-easytimer-v1 [new file with mode: 0755]
ao-bringup/test-easytimer-v2 [new file with mode: 0755]
ao-bringup/test-telegps-v4 [new file with mode: 0755]
ao-bringup/test-telemega-v7.0 [new file with mode: 0755]
ao-bringup/turnon_easymega [changed from file to symlink]
ao-bringup/turnon_easymega_v2.0 [new file with mode: 0755]
ao-bringup/turnon_easymega_v3.0 [new file with mode: 0755]
ao-bringup/turnon_easymini [changed from file to symlink]
ao-bringup/turnon_easymini_v2.0 [new file with mode: 0755]
ao-bringup/turnon_easymini_v3.0 [new file with mode: 0755]
ao-bringup/turnon_easymotor
ao-bringup/turnon_easytimer
ao-bringup/turnon_easytimer_v1 [new file with mode: 0755]
ao-bringup/turnon_telebt [changed from file to symlink]
ao-bringup/turnon_telebt_v4 [new file with mode: 0755]
ao-bringup/turnon_telebt_v4d [new file with mode: 0755]
ao-bringup/turnon_telegps [changed from file to symlink]
ao-bringup/turnon_telegps_v3 [new file with mode: 0755]
ao-bringup/turnon_telegps_v4 [new file with mode: 0755]
ao-bringup/turnon_telelco [changed from file to symlink]
ao-bringup/turnon_telelco_v2 [new file with mode: 0755]
ao-bringup/turnon_telelco_v3 [new file with mode: 0755]
ao-bringup/turnon_telemega [changed from file to symlink]
ao-bringup/turnon_telemega_v6.0 [new file with mode: 0755]
ao-bringup/turnon_telemega_v7.0 [new file with mode: 0755]
ao-tools/ao-cal-accel/ao-cal-accel.c
configure.ac
doc/Makefile.am
doc/altusmetrum-theme.yml
doc/altusmetrum.txt
doc/easymini-release-notes.inc
doc/header.inc
doc/intro.inc
doc/micropeak-outline.txt [new file with mode: 0644]
doc/micropeak.svg [new file with mode: 0644]
doc/motortest-intro.inc
doc/motortest-operation.inc
doc/release-notes-1.9.18.inc [new file with mode: 0644]
doc/release-notes-1.9.19.inc [new file with mode: 0644]
doc/release-notes-1.9.20.inc [new file with mode: 0644]
doc/release-notes-1.9.21.inc [new file with mode: 0644]
doc/release-notes-1.9.22.inc [new file with mode: 0644]
doc/release-notes.inc
doc/specs.inc
doc/system-operation.inc
doc/telegps-release-notes.inc
doc/telelaunch-acknowledgements.inc
doc/telelaunch-intro.inc
doc/telemetry.txt
map-server/altos-map/altos-map-fake
src/Makefile
src/draw/Makefile
src/drivers/ao_adxl375.c
src/drivers/ao_cc1200.c
src/drivers/ao_lco.h
src/drivers/ao_lco_bits.c
src/drivers/ao_rn4678.c
src/easymega-v3.0/Makefile
src/easymini-v2.0/Makefile
src/kernel/ao.h
src/kernel/ao_config.c
src/kernel/ao_config.h
src/kernel/ao_convert_pa_test.c
src/kernel/ao_convert_test.c
src/kernel/ao_host.h
src/kernel/ao_log.h
src/kernel/ao_radio_cmac.c
src/kernel/ao_radio_cmac.h
src/kernel/ao_stdio.c
src/kernel/ao_telemetry.c
src/kernel/ao_telemetry.h
src/mpusb-v3.0/ao_mpusb.c
src/product/ao_micropeak.c
src/stm/Makefile-flash.defs
src/telebt-v4.0-seeed/.gitignore [new file with mode: 0644]
src/telebt-v4.0-seeed/Makefile [new file with mode: 0644]
src/telebt-v4.0-seeed/ao_pins.h [new file with mode: 0644]
src/telebt-v4.0-seeed/ao_telebt_seeed.c [new file with mode: 0644]
src/telebt-v4.0-seeed/flash-loader/Makefile [new file with mode: 0644]
src/telebt-v4.0-seeed/flash-loader/ao_pins.h [new file with mode: 0644]
src/telegps-v4.0-seeed/ao_pins.h [new file with mode: 0644]
src/telegps-v4.0-seeed/ao_telegps_seeed.c [new file with mode: 0644]
src/telegps-v4.0-seeed/flash-loader/.gitignore [new file with mode: 0644]
src/telegps-v4.0-seeed/flash-loader/ao_pins.h [new file with mode: 0644]
src/telegps-v4.0/Makefile [new file with mode: 0644]
src/telegps-v4.0/ao_pins.h [new file with mode: 0644]
src/telegps-v4.0/ao_telegps.c [new file with mode: 0644]
src/telegps-v4.0/flash-loader/.gitignore [new file with mode: 0644]
src/telegps-v4.0/flash-loader/Makefile [new file with mode: 0644]
src/telegps-v4.0/flash-loader/ao_pins.h [new file with mode: 0644]
src/telelco-v3.0/Makefile
src/telelco-v3.0/ao_lco_v3.c
src/telelco-v3.0/ao_pins.h
src/telelco-v3.0/ao_telelco.c
src/telemega-v0.1/ao_pins.h
src/telemega-v1.0/ao_pins.h
src/telemega-v2.0/ao_pins.h
src/telemega-v3.0/ao_pins.h
src/telemega-v4.0/ao_pins.h
src/telemega-v5.0/ao_pins.h
src/telemega-v6.0/ao_pins.h
src/telemega-v7.0-seeed/.gitignore [new file with mode: 0644]
src/telemega-v7.0-seeed/ao_pins.h [new file with mode: 0644]
src/telemega-v7.0-seeed/ao_telemega_seeed.c [new file with mode: 0644]
src/telemega-v7.0-seeed/flash-loader/ao_pins.h [new file with mode: 0644]
src/telemega-v7.0/.gitignore [new file with mode: 0644]
src/telemega-v7.0/Makefile [new file with mode: 0644]
src/telemega-v7.0/ao_pins.h [new file with mode: 0644]
src/telemega-v7.0/ao_telemega.c [new file with mode: 0644]
src/telemega-v7.0/flash-loader/Makefile [new file with mode: 0644]
src/telemega-v7.0/flash-loader/ao_pins.h [new file with mode: 0644]
src/telemetrum-v4.0-seeed/.gitignore [new file with mode: 0644]
src/telemetrum-v4.0-seeed/Makefile [new file with mode: 0644]
src/telemetrum-v4.0-seeed/ao_pins.h [new file with mode: 0644]
src/telemetrum-v4.0-seeed/ao_telemetrum_seeed.c [new file with mode: 0644]
src/telemetrum-v4.0-seeed/flash-loader/Makefile [new file with mode: 0644]
src/telemetrum-v4.0-seeed/flash-loader/ao_pins.h [new file with mode: 0644]
src/test/Makefile
src/test/ao_fat_test.c
src/test/ao_fec_test.c
src/test/ao_flight_test.c
src/test/ao_gps_test.c
src/test/ao_gps_test_skytraq.c
src/test/ao_gps_test_ublox.c
src/test/ao_micropeak_test.c
src/test/plotmm
telegps/Makefile.am
telegps/TeleGPSConfigUI.java
telegps/TeleGPSGraphUI.java
telegps/telegps-windows.nsi.in

index 08765810d76c14d6fd0564f390140b42e07bd912..55805bbc10e8505167b5b2fd38627fa066b3333f 100644 (file)
@@ -19,12 +19,9 @@ fat-install: fat
        cd micropeak && $(MAKE) fat-install
 endif
 
-fat:
-       cd src && $(MAKE) all
-       cd doc && $(MAKE) all
+fat: all-recursive
        cd libaltos && $(MAKE) fat
        cd altoslib && $(MAKE) all
-       cd altosuilib && $(MAKE) all
        cd icon && $(MAKE) fat
        cd altosui && $(MAKE) fat
        cd micropeak && $(MAKE) fat
@@ -52,22 +49,27 @@ fat_android = \
 fat_altos = \
        src/easymega-v1.0/easymega-v1.0-$(VERSION).ihx \
        src/easymega-v2.0/easymega-v2.0-$(VERSION).ihx \
+       src/easymega-v3.0/easymega-v3.0-$(VERSION).ihx \
        src/easymini-v1.0/easymini-v1.0-$(VERSION).ihx \
        src/easymini-v2.0/easymini-v2.0-$(VERSION).ihx \
        src/easymini-v3.0/easymini-v3.0-$(VERSION).ihx \
        src/easymotor-v3/easymotor-v3-$(VERSION).ihx \
        src/easytimer-v1/easytimer-v1-$(VERSION).ihx \
+       src/easytimer-v2/easytimer-v2-$(VERSION).ihx \
        src/telebt-v3.0/telebt-v3.0-$(VERSION).ihx \
        src/telebt-v4.0/telebt-v4.0-$(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/telegps-v3.0/telegps-v3.0-$(VERSION).ihx \
+       src/telegps-v4.0/telegps-v4.0-$(VERSION).ihx \
        src/telemega-v1.0/telemega-v1.0-$(VERSION).ihx \
        src/telemega-v2.0/telemega-v2.0-$(VERSION).ihx \
        src/telemega-v3.0/telemega-v3.0-$(VERSION).ihx \
        src/telemega-v4.0/telemega-v4.0-$(VERSION).ihx \
        src/telemega-v5.0/telemega-v5.0-$(VERSION).ihx \
        src/telemega-v6.0/telemega-v6.0-$(VERSION).ihx \
+       src/telemega-v7.0/telemega-v7.0-$(VERSION).ihx \
        src/telemetrum-v2.0/telemetrum-v2.0-$(VERSION).ihx \
        src/telemetrum-v3.0/telemetrum-v3.0-$(VERSION).ihx \
        src/telemetrum-v4.0/telemetrum-v4.0-$(VERSION).ihx \
index 9750a4eb3a32b9cc19ee6f23491169985ed2f756..85a6ca57b315434ccf22c1122a60dd2b19f760d0 100644 (file)
--- a/Releasing
+++ b/Releasing
@@ -15,6 +15,8 @@ Adding a product to the release
 
        Add the firmware to Releasing
 
+       Add new product specs to doc/specs.inc
+
 These are Keith's notes on how to do a release
 
        - update the version and date in configure.ac if Bdale hasn't already
@@ -44,7 +46,7 @@ These are Bdale's notes on how to do a release.
          installers for Windows and Mac OS X
 
                sudo apt update
-               sudo apt install genisoimage nsis \
+               sudo apt install genisoimage nsis gcc-avr avr-libc \
                        gcc-i686-linux-gnu gcc-aarch64-linux-gnu \
                        gcc-arm-linux-gnueabi gcc-arm-linux-gnueabihf \
                        gcc-mingw-w64-i686-posix gcc-mingw-w64-x86-64-win32
@@ -90,6 +92,9 @@ These are Bdale's notes on how to do a release.
 
         git commit -n debian/changelog -m "update changelog for Debian build"
 
+       - review debian/patches, all should be obsoleted by a new release, so
+         take care of any that are there and commit the changes
+
        - if this is a -1 release, then
                gbp buildpackage --git-no-pristine-tar \
                        --git-upstream-branch=branch-<version> \ # eg 1.3
@@ -114,31 +119,31 @@ These are Bdale's notes on how to do a release.
        - store a stable copy of ARM binaries for production use
 
        cp src/chaoskey-v1.0/{*.elf,*.ihx,*.bin,*.map} \
-          src/easymega-v[1-2].0/{*.elf,*.ihx,*.map} \
+          src/easymega-v[1-3].0/{*.elf,*.ihx,*.map} \
           src/easymini-v[1-3].0/{*.elf,*.ihx,*.map} \
           src/easymotor-v3/{*.elf,*.ihx,*.map} \
-          src/easytimer-v1/{*.elf,*.ihx,*.map} \
+          src/easytimer-v[1-2]/{*.elf,*.ihx,*.map} \
           src/telebt-v[3-4].0/{*.elf,*.ihx,*.map} \
           src/teledongle-v3.0/{*.elf,*.ihx,*.map} \
-          src/telegps-v[1-3].0/{*.elf,*.ihx,*.map} \
-          src/telemega-v[1-6].0/{*.elf,*.ihx,*.map} \
+          src/telegps-v[1-4].0/{*.elf,*.ihx,*.map} \
+          src/telemega-v[1-7].0/{*.elf,*.ihx,*.map} \
           src/telemetrum-v[2-4].0/{*.elf,*.ihx,*.map} \
           src/telemini-v3.0/{*.elf,*.ihx,*.map} \
-          src/telelco-v2.0/{*.elf,*.ihx,*.map} \
+          src/telelco-v[2-3].0/{*.elf,*.ihx,*.map} \
           src/telefireeight-v[1-2].0/{*.elf,*.ihx,*.map} \
           ~/altusmetrumllc/Binaries/
        cp src/chaoskey-v1.0/flash-loader/{*.elf,*.bin,*.map} \
-          src/easymega-v[1-2].0/flash-loader/*.elf \
+          src/easymega-v[1-3].0/flash-loader/*.elf \
           src/easymini-v[1-3].0/flash-loader/*.elf \
           src/easymotor-v3/flash-loader/*.elf \
-          src/easytimer-v1/flash-loader/*.elf \
+          src/easytimer-v[1-2]/flash-loader/*.elf \
           src/telebt-v[3-4].0/flash-loader/{*.elf,*.bin,*.map} \
           src/teledongle-v3.0/flash-loader/*.elf \
-          src/telegps-v[1-3].0/flash-loader/{*.elf,*.bin,*.map} \
-          src/telemega-v[1-6].0/flash-loader/*.elf \
+          src/telegps-v[1-4].0/flash-loader/{*.elf,*.bin,*.map} \
+          src/telemega-v[1-7].0/flash-loader/*.elf \
           src/telemetrum-v[2-4].0/flash-loader/*.elf \
           src/telemini-v3.0/flash-loader/{*.elf,*.bin,*.map} \
-          src/telelco-v2.0/flash-loader/*.elf \
+          src/telelco-v[2-3].0/flash-loader/*.elf \
           src/telefireeight-v[1-2].0/flash-loader/*.elf \
           ~/altusmetrumllc/Binaries/loaders/
        (cd ~/altusmetrumllc ; git add Binaries ; git commit -a) 
diff --git a/altosdroid/app-debug.apk b/altosdroid/app-debug.apk
new file mode 100644 (file)
index 0000000..6d3ca36
Binary files /dev/null and b/altosdroid/app-debug.apk differ
diff --git a/altosdroid/app-release.apk b/altosdroid/app-release.apk
new file mode 100644 (file)
index 0000000..80ad354
Binary files /dev/null and b/altosdroid/app-release.apk differ
index 6d70872123954b1a88ba3fc3b897529e9b4da9f8..fd16197072ec30d2a46a45ff6f742ca8824b73f7 100644 (file)
@@ -276,10 +276,10 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,
                switch (telemetry_state.connect) {
                case TelemetryState.CONNECT_CONNECTED:
                        if (telemetry_state.config != null) {
-                               String str = String.format("S/N %d %6.3f MHz%s", telemetry_state.config.serial,
+                               String str = String.format(Locale.getDefault(), "S/N %d %6.3f MHz%s", telemetry_state.config.serial,
                                                           telemetry_state.frequency, telemetry_state.idle_mode ? " (idle)" : "");
                                if (telemetry_state.telemetry_rate != AltosLib.ao_telemetry_rate_38400)
-                                       str = str.concat(String.format(" %d bps",
+                                       str = str.concat(String.format(Locale.getDefault(), " %d bps",
                                                                       AltosLib.ao_telemetry_rate_values[telemetry_state.telemetry_rate]));
                                setTitle(str);
                        } else {
@@ -288,7 +288,7 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,
                        break;
                case TelemetryState.CONNECT_CONNECTING:
                        if (telemetry_state.address != null)
-                               setTitle(String.format("Connecting to %s...", telemetry_state.address.name));
+                               setTitle(String.format(Locale.getDefault(), "Connecting to %s...", telemetry_state.address.name));
                        else
                                setTitle("Connecting to something...");
                        break;
@@ -423,13 +423,13 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,
        static String age_string(int age) {
                String  text;
                if (age < 60)
-                       text = String.format("%ds", age);
+                       text = String.format(Locale.getDefault(), "%ds", age);
                else if (age < 60 * 60)
-                       text = String.format("%dm", age / 60);
+                       text = String.format(Locale.getDefault(), "%dm", age / 60);
                else if (age < 60 * 60 * 24)
-                       text = String.format("%dh", age / (60 * 60));
+                       text = String.format(Locale.getDefault(), "%dh", age / (60 * 60));
                else
-                       text = String.format("%dd", age / (24 * 60 * 60));
+                       text = String.format(Locale.getDefault(), "%dd", age / (24 * 60 * 60));
                return text;
        }
 
@@ -522,13 +522,13 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,
                                if (state.cal_data().serial == AltosLib.MISSING)
                                        mSerialView.setText("");
                                else
-                                       mSerialView.setText(String.format("%d", state.cal_data().serial));
+                                       mSerialView.setText(String.format(Locale.getDefault(), "%d", state.cal_data().serial));
                        }
                        if (saved_state == null || state.cal_data().flight != saved_state.flight) {
                                if (state.cal_data().flight == AltosLib.MISSING)
                                        mFlightView.setText("");
                                else
-                                       mFlightView.setText(String.format("%d", state.cal_data().flight));
+                                       mFlightView.setText(String.format(Locale.getDefault(), "%d", state.cal_data().flight));
                        }
                        if (saved_state == null || state.state() != saved_state.state) {
                                if (state.state() == AltosLib.ao_flight_stateless) {
@@ -542,7 +542,7 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,
                                if (state.rssi == AltosLib.MISSING)
                                        mRSSIView.setText("");
                                else
-                                       mRSSIView.setText(String.format("%d", state.rssi));
+                                       mRSSIView.setText(String.format(Locale.getDefault(), "%d", state.rssi));
                        }
                        saved_state = new SavedState(state);
                }
@@ -575,19 +575,19 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,
                }
                int deg = (int) Math.floor(p);
                double min = (p - Math.floor(p)) * 60.0;
-               return String.format("%d° %7.4f\" %s", deg, min, h);
+               return String.format(Locale.getDefault(), "%d° %7.4f\" %s", deg, min, h);
        }
 
        static String number(String format, double value) {
                if (value == AltosLib.MISSING)
                        return "";
-               return String.format(format, value);
+               return String.format(Locale.getDefault(), format, value);
        }
 
        static String integer(String format, int value) {
                if (value == AltosLib.MISSING)
                        return "";
-               return String.format(format, value);
+               return String.format(Locale.getDefault(), format, value);
        }
 
        private View create_tab_view(String label) {
@@ -779,7 +779,7 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,
                        try {
                                locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, this);
                                location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
-                       } catch (Exception e) {
+                       } catch (SecurityException e) {
                                locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000, 1, this);
                                location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                        }
@@ -1328,9 +1328,9 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,
                else if (iheading < -179 || 179 < iheading)
                        return "backwards";
                else if (iheading < 0)
-                       return String.format("left %d°", -iheading);
+                       return String.format(Locale.getDefault(), "left %d°", -iheading);
                else
-                       return String.format("right %d°", iheading);
+                       return String.format(Locale.getDefault(), "right %d°", iheading);
        }
 
        public void onLocationChanged(Location location) {
index 170353ab4838098035f6e1dc37768bb0ee41f9f4..024ca1b9a923148ec8fbce9c23348b48a112cc6f 100644 (file)
@@ -31,7 +31,6 @@ public class AltosDroidPreferencesBackend extends AltosPreferencesBackend {
        public final static String        NAME    = "org.altusmetrum.AltosDroid";
        private Context                   context = null;
        private SharedPreferences         prefs   = null;
-       private SharedPreferences.Editor  editor  = null;
 
        public AltosDroidPreferencesBackend(Context in_context) {
                this(in_context, NAME);
@@ -40,7 +39,6 @@ public class AltosDroidPreferencesBackend extends AltosPreferencesBackend {
        public AltosDroidPreferencesBackend(Context in_context, String in_prefs) {
                context = in_context;
                prefs   = context.getSharedPreferences(in_prefs, 0);
-               editor  = prefs.edit();
        }
 
        public String[] keys() {
@@ -104,37 +102,48 @@ public class AltosDroidPreferencesBackend extends AltosPreferencesBackend {
        }
 
        public void putBoolean(String key, boolean value) {
+               SharedPreferences.Editor editor = prefs.edit();
                editor.putBoolean(key, value);
+               editor.apply();
        }
 
        public void putDouble(String key, double value) {
+               SharedPreferences.Editor editor = prefs.edit();
                editor.putFloat(key, (float)value);
+               editor.apply();
        }
 
        public void putInt(String key, int value) {
+               SharedPreferences.Editor editor = prefs.edit();
                editor.putInt(key, value);
+               editor.apply();
        }
 
        public void putString(String key, String value) {
+               SharedPreferences.Editor editor = prefs.edit();
 //             AltosDebug.debug("AltosDroidPreferencesBackend put string %s:\n", key);
 //             String[] lines = value.split("\n");
 //             for (String l : lines)
 //                     AltosDebug.debug("        %s\n", l);
                editor.putString(key, value);
+               editor.apply();
        }
 
        public void putBytes(String key, byte[] bytes) {
+               SharedPreferences.Editor editor = prefs.edit();
                String save = Base64.encodeToString(bytes, Base64.DEFAULT);
                editor.putString(key, save);
+               editor.apply();
        }
 
        public void remove(String key) {
+               SharedPreferences.Editor editor = prefs.edit();
                AltosDebug.debug("remove preference %s\n", key);
                editor.remove(key);
+               editor.apply();
        }
 
        public void flush() {
-               editor.apply();
        }
 
        public File homeDirectory() {
index 7bd57a4ca39ebfcd19e44a130c91ef20c15db2a8..ab841b10ee9c6e952e60340b92fc67b40f823a4b 100644 (file)
@@ -70,7 +70,7 @@ class Rocket implements Comparable {
 
        Rocket(int serial, AltosMapOffline map_offline) {
                this.serial = serial;
-               this.name = String.format("%d", serial);
+               this.name = String.format(Locale.ROOT, "%d", serial);
                this.map_offline = map_offline;
        }
 }
index 76cd990be7f5b474f38fbddea13f3c8653db1341..70fb5c65a1d7ad5395aa9a4cc90dedbe49dc0103 100644 (file)
@@ -90,7 +90,7 @@ class RocketOnline implements Comparable {
 
        RocketOnline(Context context, int serial, GoogleMap map, double lat, double lon, long last_packet) {
                this.serial = serial;
-               String name = String.format("%d", serial);
+               String name = String.format(Locale.ROOT, "%d", serial);
                this.marker = map.addMarker(new MarkerOptions()
                                            .icon(BitmapDescriptorFactory.fromBitmap(rocket_bitmap(context, name)))
                                            .position(new LatLng(lat, lon))
@@ -207,8 +207,12 @@ public class AltosMapOnline implements AltosDroidMapInterface, GoogleMap.OnMarke
 
        void
        position_permission() {
-               if (mMap != null)
-                       mMap.setMyLocationEnabled(true);
+               if (mMap != null) {
+                       try {
+                               mMap.setMyLocationEnabled(true);
+                       } catch (SecurityException e) {
+                       }
+               }
        }
 
        @Override
@@ -218,7 +222,7 @@ public class AltosMapOnline implements AltosDroidMapInterface, GoogleMap.OnMarke
                if (mMap != null) {
                        map_type_changed(map_type);
                        if (altos_droid.have_location_permission)
-                               mMap.setMyLocationEnabled(true);
+                               position_permission();
                        else
                                altos_droid.tell_map_permission(this);
                        mMap.getUiSettings().setTiltGesturesEnabled(false);
index 2049c79654b958c645846d298423912605ddabed..f86f60cb3d3ec39cf36ffc9466d510955f2bb803 100644 (file)
@@ -19,6 +19,7 @@
 
 package org.altusmetrum.AltosDroid;
 
+import java.util.*;
 import android.speech.tts.TextToSpeech;
 import android.speech.tts.TextToSpeech.OnInitListener;
 import android.location.Location;
@@ -90,7 +91,7 @@ public class AltosVoice {
        }
 
        public synchronized void speak(String format, Object ... arguments) {
-               speak(String.format(format, arguments));
+               speak(String.format(Locale.getDefault(), format, arguments));
        }
 
        public synchronized boolean is_speaking() {
@@ -269,7 +270,7 @@ public class AltosVoice {
 
                String direction = AltosDroid.direction(from_receiver, receiver);
                if (direction == null)
-                       direction = String.format("Bearing %d", (int) (from_receiver.bearing + 0.5));
+                       direction = String.format(Locale.getDefault(), "Bearing %d", (int) (from_receiver.bearing + 0.5));
 
                speak("%s, distance %s.", direction,
                      AltosConvert.distance.say_units(from_receiver.distance));
index 9b9095bdefc28979a9ff66786d2f2ed57dc54227..2e77530d11560559ed49a60dd4b4631d44048899 100644 (file)
@@ -18,6 +18,7 @@
 
 package org.altusmetrum.AltosDroid;
 
+import java.util.*;
 import android.app.Activity;
 import android.content.Intent;
 import android.os.Bundle;
@@ -87,7 +88,7 @@ public class IdleModeActivity extends Activity {
 
                frequency = getIntent().getDoubleExtra(AltosDroid.EXTRA_FREQUENCY, 0.0);
                frequencyView = (TextView) findViewById(R.id.frequency);
-               frequencyView.setText(String.format("Frequency: %7.3f MHz", frequency));
+               frequencyView.setText(String.format(Locale.getDefault(), "Frequency: %7.3f MHz", frequency));
 
                connect = (Button) findViewById(R.id.connect_idle);
                connect.setOnClickListener(new OnClickListener() {
index 752558206accf3f89d3880d9c95d3cf1fbb68a48..f75961c377d909f9ce026030f689e7c72803fcac 100644 (file)
@@ -275,8 +275,8 @@ public class IgniterActivity extends Activity {
                set_igniter(status, "drogue", "Apogee");
                set_igniter(status, "main", "Main");
                for (int extra = 0;; extra++) {
-                       String  name = String.format("%d", extra);
-                       String  pretty = String.format("%c", 'A' + extra);
+                       String  name = String.format(Locale.getDefault(), "%d", extra);
+                       String  pretty = String.format(Locale.getDefault(), "%c", 'A' + extra);
                        if (!set_igniter(status, name, pretty))
                                break;
                }
@@ -291,7 +291,7 @@ public class IgniterActivity extends Activity {
        }
 
        private void arm_set_text() {
-               String  text = String.format("Armed %d", arm_remaining);
+               String  text = String.format(Locale.getDefault(), "Armed %d", arm_remaining);
 
                if (arm.isChecked())
                        arm.setText(text);
index eb1230116c7cf4406486a7490d89432a95e9e09f..cd0ce70b0e1c8e2ea34d6dad8729c7993c4bcbee 100644 (file)
@@ -134,8 +134,8 @@ public class PreloadMapActivity extends Activity implements AltosLaunchSiteListe
                        if (selected_item != null)
                                known_sites_spinner.setSelection(known_sites_adapter.getPosition(selected_item));
                        else {
-                               latitude.setText(new StringBuffer(String.format("%12.6f", current_location_site.latitude)));
-                               longitude.setText(new StringBuffer(String.format("%12.6f", current_location_site.longitude)));
+                               latitude.setText(new StringBuffer(String.format(Locale.getDefault(), "%12.6f", current_location_site.latitude)));
+                               longitude.setText(new StringBuffer(String.format(Locale.getDefault(), "%12.6f", current_location_site.longitude)));
                        }
                } else {
                        current_location_site.latitude = location.getLatitude();
@@ -279,8 +279,8 @@ public class PreloadMapActivity extends Activity implements AltosLaunchSiteListe
        class SiteListListener implements OnItemSelectedListener {
                public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
                        AltosLaunchSite site = (AltosLaunchSite) parent.getItemAtPosition(pos);
-                       latitude.setText(new StringBuffer(String.format("%12.6f", site.latitude)));
-                       longitude.setText(new StringBuffer(String.format("%12.6f", site.longitude)));
+                       latitude.setText(new StringBuffer(String.format(Locale.getDefault(), "%12.6f", site.latitude)));
+                       longitude.setText(new StringBuffer(String.format(Locale.getDefault(), "%12.6f", site.longitude)));
                }
                public void onNothingSelected(AdapterView<?> parent) {
                }
@@ -358,8 +358,11 @@ public class PreloadMapActivity extends Activity implements AltosLaunchSiteListe
                LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
                try {
                        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, this);
-               } catch (Exception e) {
-                       locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000, 1, this);
+               } catch (SecurityException e) {
+                       try {
+                               locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000, 1, this);
+                       } catch (SecurityException se) {
+                       }
                }
 
                new AltosLaunchSites(this);
index 1815331ef2e29aeb22875b8d858e215d084e7543..36e2898031a98f0d966662dac0f4f98e65972f1f 100644 (file)
@@ -195,13 +195,13 @@ public class SelectTrackerActivity extends Activity implements OnTouchListener {
                if (tracker.serial == 0)
                        ((TextView) row.findViewById(R.id.serial_view)).setText("");
                else
-                       ((TextView) row.findViewById(R.id.serial_view)).setText(String.format("%d", tracker.serial));
+                       ((TextView) row.findViewById(R.id.serial_view)).setText(String.format(Locale.getDefault(), "%d", tracker.serial));
                if (tracker.frequency == 0.0)
                        ((TextView) row.findViewById(R.id.frequency_view)).setText("");
                else if (tracker.frequency == AltosLib.MISSING)
                        ((TextView) row.findViewById(R.id.frequency_view)).setText("");
                else
-                       ((TextView) row.findViewById(R.id.frequency_view)).setText(String.format("%7.3f", tracker.frequency));
+                       ((TextView) row.findViewById(R.id.frequency_view)).setText(String.format(Locale.getDefault(), "%7.3f", tracker.frequency));
                if (tracker.received_time != 0) {
                        int age = (int) ((start_time - tracker.received_time + 500) / 1000);
                        ((TextView) row.findViewById(R.id.age_view)).setText(AltosDroid.age_string(age));
index 55acd5d68a88201b3b6bfb64372b9c1c2af5f2bd..8e8fd7743d87462d6d5cd26f500a6bcb0a70f037 100644 (file)
@@ -18,6 +18,8 @@
 
 package org.altusmetrum.AltosDroid;
 
+import java.util.*;
+
 import org.altusmetrum.altoslib_14.*;
 
 import android.app.Activity;
@@ -95,7 +97,7 @@ public class TabMap extends AltosDroidTab implements AltosDroidMapSourceListener
                                mBearingView.setText(direction);
                        } else {
                                mBearingLabel.setText("Bearing");
-                               mBearingView.setText(String.format("%3.0f°", from_receiver.bearing));
+                               mBearingView.setText(String.format(Locale.getDefault(), "%3.0f°", from_receiver.bearing));
                        }
                        set_value(mDistanceView, AltosConvert.distance, 6, from_receiver.distance);
                } else {
index fd997612725530357ab9a593b802835d729c632d..558be4f87f5cd3135f7ba602be782d8cceaadba2 100644 (file)
@@ -18,6 +18,8 @@
 
 package org.altusmetrum.AltosDroid;
 
+import java.util.*;
+
 import org.altusmetrum.altoslib_14.*;
 
 import android.os.Bundle;
@@ -213,7 +215,7 @@ public class TabPad extends AltosDroidTab {
                        if (state.gps != null) {
                                int soln = state.gps.nsat;
                                int nsat = state.gps.cc_gps_sat != null ? state.gps.cc_gps_sat.length : 0;
-                               gps_locked_view.setText(String.format("%d in soln, %d in view", soln, nsat));
+                               gps_locked_view.setText(String.format(Locale.getDefault(), "%d in soln, %d in view", soln, nsat));
                                gps_locked_lights.set(state.gps.locked && state.gps.nsat >= 4, false);
                                if (state.gps_ready)
                                        gps_ready_view.setText("Ready");
index df1ee8fa36202a14c5acd12ea654ca07664c27cb..93a645c20e549799c573a5b8f65b53e1247f8cb9 100644 (file)
@@ -18,6 +18,7 @@
 
 package org.altusmetrum.AltosDroid;
 
+import java.util.*;
 import org.altusmetrum.altoslib_14.*;
 
 import android.os.Bundle;
@@ -61,7 +62,7 @@ public class TabRecover extends AltosDroidTab {
 
        public void show(TelemetryState telem_state, AltosState state, AltosGreatCircle from_receiver, Location receiver) {
                if (from_receiver != null) {
-                       mBearingView.setText(String.format("%1.0f°", from_receiver.bearing));
+                       mBearingView.setText(String.format(Locale.getDefault(), "%1.0f°", from_receiver.bearing));
                        set_value(mDistanceView, AltosConvert.distance, 1, from_receiver.distance);
                        String direction = AltosDroid.direction(from_receiver, receiver);
                        if (direction == null)
index 614b4c2cfd5a03becf2a6263c0ae8dd145827fa4..3992395fcf246aa65191f988ef85c0310719f2ec 100644 (file)
@@ -62,9 +62,9 @@ public class Tracker implements CharSequence, Comparable, Parcelable {
                if (frequency == 0.0)
                        display = "Auto";
                else if (frequency == AltosLib.MISSING) {
-                       display = String.format("%-8.8s  %6d", call, serial);
+                       display = String.format(Locale.getDefault(), "%-8.8s  %6d", call, serial);
                } else {
-                       display = String.format("%-8.8s %7.3f %6d", call, frequency, serial);
+                       display = String.format(Locale.getDefault(), "%-8.8s %7.3f %6d", call, frequency, serial);
                }
        }
 
index afb3310fbfccdb6e77681caaa7bd3192db7fecc3..86afc695cfef440a2b7b3e0dc84860cbf5ec9bc1 100644 (file)
@@ -39,7 +39,6 @@
          android:layout_weight="1"
          android:hint="@string/frequency"
          android:inputType="number|numberDecimal"/>
-      />
       <TextView
          android:id="@+id/mhz"
          android:layout_width="wrap_content"
index c90534a924e4159ea62cc0a1db5575e8493a67d0..53e3b8fb6c4bbb271db9c6af215e3e9ddbaca48b 100644 (file)
@@ -202,9 +202,12 @@ public class AltosCalData {
        public void set_tick(int tick) {
                if (tick != AltosLib.MISSING) {
                        if (prev_tick != AltosLib.MISSING) {
-                               while (tick < prev_tick - 1000) {
+                               while (tick < prev_tick - 32767) {
                                        tick += 65536;
                                }
+                               while (tick > prev_tick + 32767) {
+                                       tick -= 65536;
+                               }
                        }
                        if (first_tick == AltosLib.MISSING)
                                first_tick = tick;
index 005ef57156a4da31eb7187ce43df9167446a696b..90730ce31a667adbe08a0c3212bb8771e2b81618 100644 (file)
@@ -88,6 +88,9 @@ public class AltosConfigData {
 
        public int              report_feet;
 
+       /* HAS_GPS_MOSAIC */
+       public int              gps_receiver;
+
        /* Storage info replies */
        public int      storage_size;
        public int      storage_erase_unit;
@@ -219,6 +222,7 @@ public class AltosConfigData {
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_4:
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_5:
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_6:
+               case AltosLib.AO_LOG_FORMAT_TELEMEGA_7:
                case AltosLib.AO_LOG_FORMAT_EASYMEGA_2:
                case AltosLib.AO_LOG_FORMAT_EASYMEGA_3:
                case AltosLib.AO_LOG_FORMAT_EASYMOTOR:
@@ -242,6 +246,10 @@ public class AltosConfigData {
                return false;
        }
 
+       public boolean has_radio() {
+               return product.startsWith("Tele");
+       }
+
        int[] parse_version(String v) {
                String[] parts = v.split("\\.");
                int r[] = new int[parts.length];
@@ -331,6 +339,8 @@ public class AltosConfigData {
 
                report_feet = AltosLib.MISSING;
 
+               gps_receiver = AltosLib.MISSING;
+
                tracker_motion = AltosLib.MISSING;
                tracker_interval = AltosLib.MISSING;
 
@@ -526,6 +536,8 @@ public class AltosConfigData {
 
                try { report_feet = get_int(line, "Report in feet:"); } catch (Exception e) {}
 
+               try { gps_receiver = get_int(line, "GPS receiver:"); } catch (Exception e) {}
+
                /* HAS_TRACKER */
                try {
                        int[] values = get_values(line, "Tracker setting:");
@@ -681,6 +693,8 @@ public class AltosConfigData {
                                return true;
                        if (product.startsWith("TeleMega-v6"))
                                return true;
+                       if (product.startsWith("TeleMega-v7"))
+                               return true;
                        if (product.startsWith("EasyMotor-v2"))
                                return true;
                        if (product.startsWith("EasyMotor-v3"))
@@ -703,6 +717,8 @@ public class AltosConfigData {
                                return AltosAdxl375.X_AXIS;
                        if (product.startsWith("TeleMega-v6"))
                                return AltosAdxl375.X_AXIS;
+                       if (product.startsWith("TeleMega-v7"))
+                               return AltosAdxl375.X_AXIS;
                        if (product.startsWith("EasyMotor-v2"))
                                return AltosAdxl375.X_AXIS;
                        if (product.startsWith("EasyMotor-v3"))
@@ -777,6 +793,9 @@ public class AltosConfigData {
                if (report_feet != AltosLib.MISSING)
                        report_feet = source.report_feet();
 
+               if (gps_receiver != AltosLib.MISSING)
+                       gps_receiver = source.gps_receiver();
+
                /* HAS_TRACKER */
                if (tracker_motion != AltosLib.MISSING)
                        tracker_motion = source.tracker_motion();
@@ -834,6 +853,7 @@ public class AltosConfigData {
                dest.set_beep(beep);
                dest.set_radio_10mw(radio_10mw);
                dest.set_report_feet(report_feet);
+               dest.set_gps_receiver(gps_receiver);
                dest.set_tracker_motion(tracker_motion);
                dest.set_tracker_interval(tracker_interval);
        }
@@ -957,10 +977,13 @@ public class AltosConfigData {
                if (radio_10mw != AltosLib.MISSING)
                        link.printf("c p %d\n", radio_10mw);
 
-               /* HAS_RADIO_10MW */
                if (report_feet != AltosLib.MISSING)
                        link.printf("c u %d\n", report_feet);
 
+               /* HAS_GPS_MOSAIC */
+               if (gps_receiver != AltosLib.MISSING)
+                       link.printf("c g %d\n", gps_receiver);
+
                /* HAS_TRACKER */
                if (tracker_motion != AltosLib.MISSING && tracker_interval != AltosLib.MISSING)
                        link.printf("c t %d %d\n", tracker_motion, tracker_interval);
index 6823e0f99c9b1dc24f122dacd695af99aa60a68e..1de180d30ae3485303e6f705ee4aeb68ea6a10bb 100644 (file)
@@ -128,5 +128,9 @@ public interface AltosConfigValues {
 
        public abstract int report_feet() throws AltosConfigDataException;
 
-       public abstract void set_report_feet(int radio_10mw);
+       public abstract void set_report_feet(int report_feet);
+
+       public abstract int gps_receiver() throws AltosConfigDataException;
+
+       public abstract void set_gps_receiver(int gps_receiver);
 }
index ded4b36527cbfc92e6ba7beefbadcc9a31a3cbb1..a478881ea585d3031ee2372a6a88e5268e0d8b9b 100644 (file)
@@ -49,21 +49,21 @@ public class AltosConvert {
 
        private static final double GRAVITATIONAL_ACCELERATION = -gravity;
        private static final double AIR_GAS_CONSTANT            = 287.053;
-       private static final double NUMBER_OF_LAYERS            = 7;
-       private static final double MAXIMUM_ALTITUDE            = 84852.0;
-       private static final double MINIMUM_PRESSURE            = 0.3734;
+       private static final double MAXIMUM_ALTITUDE            = 100000.0;
+       private static final double MINIMUM_PRESSURE            = 0.023439;
        private static final double LAYER0_BASE_TEMPERATURE     = 288.15;
        private static final double LAYER0_BASE_PRESSURE        = 101325;
 
        /* lapse rate and base altitude for each layer in the atmosphere */
        private static final double[] lapse_rate = {
-               -0.0065, 0.0, 0.001, 0.0028, 0.0, -0.0028, -0.002
+               -0.0065, 0.0, 0.001, 0.0028, 0.0, -0.0028, -0.002, 0,
        };
 
-       private static final int[] base_altitude = {
-               0, 11000, 20000, 32000, 47000, 51000, 71000
+       private static final double[] base_altitude = {
+               0, 11000, 20000, 32000, 47000, 51000, 71000, 84852,
        };
 
+       private static final int NUMBER_OF_LAYERS               = base_altitude.length;
        /* outputs atmospheric pressure associated with the given altitude.
         * altitudes are measured with respect to the mean sea level
         */
@@ -128,25 +128,21 @@ public class AltosConvert {
                double next_base_pressure = LAYER0_BASE_PRESSURE;
 
                double altitude;
-               double base_pressure;
-               double base_temperature;
+               double base_pressure = 0;
+               double base_temperature = 0;
                double base; /* base for function to determine base pressure of next layer */
                double exponent; /* exponent for function to determine base pressure
                                    of next layer */
                double coefficient;
                int layer_number; /* identifies layer in the atmosphere */
-               int delta_z; /* difference between two altitudes */
+               double delta_z; /* difference between two altitudes */
 
-               if (pressure < 0)  /* illegal pressure */
-                       return -1;
                if (pressure < MINIMUM_PRESSURE) /* FIX ME: use sensor data to improve model */
-                       return MAXIMUM_ALTITUDE;
+                       pressure = MINIMUM_PRESSURE;
 
                /* calculate the base temperature and pressure for the atmospheric layer
                   associated with the inputted pressure. */
-               layer_number = -1;
-               do {
-                       layer_number++;
+               for (layer_number = 0; layer_number < NUMBER_OF_LAYERS - 1; layer_number++) {
                        base_pressure = next_base_pressure;
                        base_temperature = next_base_temperature;
                        delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number];
@@ -162,8 +158,9 @@ public class AltosConvert {
                                next_base_pressure *= Math.pow(base, exponent);
                        }
                        next_base_temperature += delta_z * lapse_rate[layer_number];
+                       if (pressure >= next_base_pressure)
+                               break;
                }
-               while(layer_number < NUMBER_OF_LAYERS - 1 && pressure < next_base_pressure);
 
                /* calculate the altitude associated with the inputted pressure */
                if (lapse_rate[layer_number] == 0.0) {
@@ -181,6 +178,9 @@ public class AltosConvert {
                                + coefficient * (Math.pow(base, exponent) - 1);
                }
 
+               if (altitude > MAXIMUM_ALTITUDE)
+                       altitude = MAXIMUM_ALTITUDE;
+
                return altitude;
        }
 
@@ -224,15 +224,49 @@ public class AltosConvert {
                return raw / 4095.0;
        }
 
+       static double stm_adc(int raw) {
+               return raw / 4095.0;
+       }
+
+       static public double easy_timer_battery_voltage(int v_batt) {
+               if (v_batt != AltosLib.MISSING)
+                       return 3.3 * stm_adc(v_batt) * (5.6 + 10.0) / 10.0;
+               return AltosLib.MISSING;
+       }
+
+       static double easy_timer_pyro_voltage_15v(int raw) {
+               if (raw != AltosLib.MISSING)
+                       return 3.3 * stm_adc(raw) * (100.0 + 27.0) / 27.0;
+               return AltosLib.MISSING;
+       }
+
+       static public double metrum_battery_voltage(int v_batt) {
+               if (v_batt != AltosLib.MISSING)
+                       return 3.3 * stm_adc(v_batt) * (5.6 + 10.0) / 10.0;
+               return AltosLib.MISSING;
+       }
+
+       static double metrum_pyro_voltage(int raw) {
+               if (raw != AltosLib.MISSING)
+                       return 3.3 * stm_adc(raw) * (100.0 + 27.0) / 27.0;
+               return AltosLib.MISSING;
+       }
+
        static public double mega_battery_voltage(int v_batt) {
                if (v_batt != AltosLib.MISSING)
-                       return 3.3 * mega_adc(v_batt) * (5.6 + 10.0) / 10.0;
+                       return 3.3 * stm_adc(v_batt) * (5.6 + 10.0) / 10.0;
                return AltosLib.MISSING;
        }
 
-       static double mega_pyro_voltage(int raw) {
+       static double mega_pyro_voltage_15v(int raw) {
                if (raw != AltosLib.MISSING)
-                       return 3.3 * mega_adc(raw) * (100.0 + 27.0) / 27.0;
+                       return 3.3 * stm_adc(raw) * (100.0 + 27.0) / 27.0;
+               return AltosLib.MISSING;
+       }
+
+       static double mega_pyro_voltage_30v(int raw) {
+               if (raw != AltosLib.MISSING)
+                       return 3.3 * stm_adc(raw) * (100.0 + 12.0) / 12.0;
                return AltosLib.MISSING;
        }
 
@@ -276,6 +310,13 @@ public class AltosConvert {
                return sensor / 32767.0 * supply * (5.6 + 10.0) / 10.0;
        }
 
+       /* STM32F042 */
+       static double tele_gps_4_voltage(int sensor) {
+               double  supply = 3.3;
+
+               return sensor / 4095.0 * supply * (5.6 + 10.0) / 10.0;
+       }
+
        static double tele_bt_3_battery(int raw) {
                if (raw == AltosLib.MISSING)
                        return AltosLib.MISSING;
@@ -559,7 +600,7 @@ public class AltosConvert {
 
        public static int beep_freq_to_value(double freq) {
                if (freq == 0)
-                       return 94;
+                       return 0;
                return (int) Math.floor (1.0/2.0 * (24.0e6/32.0) / freq + 0.5);
        }
 
index b19cbedbbdb513b914a6edf1bbe55cf58af2608f..18ffd988299a63cb2821d1c0eae5df6221f016dd 100644 (file)
@@ -39,6 +39,10 @@ public abstract class AltosDataListener {
                return cal_data;
        }
 
+       public AltosConfigData config_data() {
+               return null;
+       }
+
        public void set_time(double time) {
                if (time != AltosLib.MISSING)
                        this.time = time;
index bf94b676c4bf795738effd637d54350f93375223..b9dcea583b943522840391338494a5923e3c0245 100644 (file)
@@ -36,6 +36,7 @@ public class AltosEepromRecordMega extends AltosEepromRecord {
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_4:
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_5:
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_6:
+               case AltosLib.AO_LOG_FORMAT_TELEMEGA_7:
                        return data32(16);
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
                        return data16(14);
@@ -51,6 +52,7 @@ public class AltosEepromRecordMega extends AltosEepromRecord {
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_4:
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_5:
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_6:
+               case AltosLib.AO_LOG_FORMAT_TELEMEGA_7:
                        return data32(20);
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
                        return data16(16);
@@ -66,6 +68,7 @@ public class AltosEepromRecordMega extends AltosEepromRecord {
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_4:
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_5:
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_6:
+               case AltosLib.AO_LOG_FORMAT_TELEMEGA_7:
                        return data32(24);
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
                        return data16(18);
@@ -123,6 +126,7 @@ public class AltosEepromRecordMega extends AltosEepromRecord {
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_5:
                        return AltosLib.model_mpu6000;
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_6:
+               case AltosLib.AO_LOG_FORMAT_TELEMEGA_7:
                        return AltosLib.model_bmi088;
                }
                return AltosLib.MISSING;
@@ -132,6 +136,7 @@ public class AltosEepromRecordMega extends AltosEepromRecord {
                switch (log_format) {
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_5:
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_6:
+               case AltosLib.AO_LOG_FORMAT_TELEMEGA_7:
                        return true;
                }
                return false;
@@ -141,6 +146,7 @@ public class AltosEepromRecordMega extends AltosEepromRecord {
                switch (log_format) {
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_5:
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_6:
+               case AltosLib.AO_LOG_FORMAT_TELEMEGA_7:
                        return AltosLib.model_mmc5983;
                }
                return AltosLib.MISSING;
@@ -290,6 +296,15 @@ public class AltosEepromRecordMega extends AltosEepromRecord {
        private int sense(int i) { return data16(6 + i * 2); }
        private int pyro() { return data16(26); }
 
+       private double pyro_voltage(int sense) {
+               switch (log_format) {
+               case AltosLib.AO_LOG_FORMAT_TELEMEGA_7:
+                       return AltosConvert.mega_pyro_voltage_30v(sense);
+               default:
+                       return AltosConvert.mega_pyro_voltage_15v(sense);
+               }
+       }
+
        /* AO_LOG_GPS_TIME elements */
        private int latitude() { return data32(0); }
        private int longitude() { return data32(4); }
@@ -374,16 +389,16 @@ public class AltosEepromRecordMega extends AltosEepromRecord {
                        break;
                case AltosLib.AO_LOG_TEMP_VOLT:
                        listener.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt()));
-                       listener.set_pyro_voltage(AltosConvert.mega_pyro_voltage(v_pbatt()));
+                       listener.set_pyro_voltage(pyro_voltage(v_pbatt()));
 
                        int nsense = nsense();
 
-                       listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense(nsense-2)));
-                       listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sense(nsense-1)));
+                       listener.set_apogee_voltage(pyro_voltage(sense(nsense-2)));
+                       listener.set_main_voltage(pyro_voltage(sense(nsense-1)));
 
                        double voltages[] = new double[nsense-2];
                        for (int i = 0; i < nsense-2; i++)
-                               voltages[i] = AltosConvert.mega_pyro_voltage(sense(i));
+                               voltages[i] = pyro_voltage(sense(i));
 
                        listener.set_igniter_voltage(voltages);
                        listener.set_pyro_fired(pyro());
index 848f4fb16eecd682d530ec20a976a7efa9bf2ba8..13cc6982eea64aa306b95fefae82c7264eefc3ce 100644 (file)
@@ -86,9 +86,9 @@ public class AltosEepromRecordMetrum extends AltosEepromRecord {
                        listener.set_acceleration(cal_data.acceleration(accel()));
                        break;
                case AltosLib.AO_LOG_TEMP_VOLT:
-                       listener.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt()));
-                       listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense_a()));
-                       listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sense_m()));
+                       listener.set_battery_voltage(AltosConvert.metrum_battery_voltage(v_batt()));
+                       listener.set_apogee_voltage(AltosConvert.metrum_pyro_voltage(sense_a()));
+                       listener.set_main_voltage(AltosConvert.metrum_pyro_voltage(sense_m()));
                        break;
                case AltosLib.AO_LOG_GPS_POS:
                        gps = listener.make_temp_gps(false);
index 8f3fa4590e43bcecd060b1d287bf09490a7a23db..842675c96f16bcd970220dc1156fb60df67f7fed 100644 (file)
@@ -89,6 +89,7 @@ public class AltosEepromRecordSet implements AltosRecordSet {
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_5:
                case AltosLib.AO_LOG_FORMAT_TELEMEGA_6:
                case AltosLib.AO_LOG_FORMAT_EASYMEGA_3:
+               case AltosLib.AO_LOG_FORMAT_TELEMEGA_7:
                        record = new AltosEepromRecordMega(eeprom);
                        break;
                case AltosLib.AO_LOG_FORMAT_TELEMETRUM:
@@ -138,6 +139,8 @@ public class AltosEepromRecordSet implements AltosRecordSet {
                        } else {
                                while (t < tick - 32767)
                                        t += 65536;
+                               while (t > tick + 32767)
+                                       t -= 65536;
                                tick = t;
                        }
                        record.wide_tick = tick;
index 91dcb6a3346bcb2df40db7820024dc28cab3646c..1d3f733ae86eda570f9074412a293eb97f81328b 100644 (file)
@@ -135,17 +135,17 @@ public class AltosEepromRecordTimer extends AltosEepromRecord {
 
                        listener.set_acceleration(cal_data.acceleration(accel()));
 
-                       listener.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt()));
-                       listener.set_pyro_voltage(AltosConvert.mega_pyro_voltage(v_pbatt()));
+                       listener.set_battery_voltage(AltosConvert.easy_timer_battery_voltage(v_batt()));
+                       listener.set_pyro_voltage(AltosConvert.easy_timer_pyro_voltage_15v(v_pbatt()));
 
                        int nsense = nsense();
 
-                       listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense(nsense-2)));
-                       listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sense(nsense-1)));
+                       listener.set_apogee_voltage(AltosConvert.easy_timer_pyro_voltage_15v(sense(nsense-2)));
+                       listener.set_main_voltage(AltosConvert.easy_timer_pyro_voltage_15v(sense(nsense-1)));
 
                        double voltages[] = new double[nsense-2];
                        for (int i = 0; i < nsense-2; i++)
-                               voltages[i] = AltosConvert.mega_pyro_voltage(sense(i));
+                               voltages[i] = AltosConvert.easy_timer_pyro_voltage_15v(sense(i));
 
                        listener.set_igniter_voltage(voltages);
                        listener.set_pyro_fired(pyro());
index b64ba0a4c9ee0828d876e80709229b51f5e877e8..65b329d4e821d8fba7bcbb090def1f2c60bcb9c2 100644 (file)
@@ -58,6 +58,7 @@ class AltosIdler {
        static final int        idle_sensor_emini3 = 112;
        static final int        idle_sensor_etimer2 = 113;
        static final int        idle_sensor_emega3 = 114;
+       static final int        idle_sensor_tgps4 = 115;
 
        public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException, TimeoutException, AltosUnknownProduct {
                for (int idler : idlers) {
@@ -134,6 +135,9 @@ class AltosIdler {
                        case idle_sensor_tgps3:
                                AltosSensorTGPS3.provide_data(listener, link);
                                break;
+                       case idle_sensor_tgps4:
+                               AltosSensorTGPS4.provide_data(listener, link);
+                               break;
                        case idle_sensor_tmini3:
                                AltosSensorTMini3.provide_data(listener, link);
                                break;
@@ -249,6 +253,12 @@ public class AltosIdleFetch implements AltosDataProvider {
                               AltosIdler.idle_ms5607,
                               AltosIdler.idle_imu, AltosIdler.idle_mag,
                               AltosIdler.idle_sensor_mega),
+               new AltosIdler("TeleMega-v7",
+                              AltosIdler.idle_gps,
+                              AltosIdler.idle_adxl375,
+                              AltosIdler.idle_ms5607,
+                              AltosIdler.idle_imu, AltosIdler.idle_mag,
+                              AltosIdler.idle_sensor_mega),
                new AltosIdler("EasyMega-v1",
                               AltosIdler.idle_mma655x,
                               AltosIdler.idle_ms5607,
@@ -274,6 +284,9 @@ public class AltosIdleFetch implements AltosDataProvider {
                new AltosIdler("TeleGPS-v3",
                               AltosIdler.idle_gps,
                               AltosIdler.idle_sensor_tgps3),
+               new AltosIdler("TeleGPS-v4",
+                              AltosIdler.idle_gps,
+                              AltosIdler.idle_sensor_tgps4),
                new AltosIdler("EasyTimer-v1",
                               AltosIdler.idle_imu_et_v1,
                               AltosIdler.idle_sensor_easytimer1),
index 82b5881ae49dc4389328460a859cada80acbfbe1..48fa9b04248da526c5169d056a1f757fc4f903cb 100644 (file)
@@ -140,6 +140,13 @@ public class AltosLib {
        public final static int product_basestation = 0x10000 + 1;
        public final static int product_altimeter = 0x10000 + 2;
 
+       public final static int gps_builtin = 0;
+       public final static int gps_mosaic = 1;
+
+       public final static String[] gps_receiver_names = {
+               "Builtin", "Mosaic-X5"
+       };
+
        private static class Product {
                final String    name;
                final int       product;
@@ -228,6 +235,30 @@ public class AltosLib {
                "Compressed", "Uncompressed"
        };
 
+       public static final String[] ignite_mode_values = {
+               "Dual Deploy",
+               "Redundant Apogee",
+               "Redundant Main",
+               "Separation & Apogee",
+       };
+
+       public static final String[]    pad_orientation_values_radio = {
+               "Antenna Up",
+               "Antenna Down",
+       };
+
+       public static final String[]    pad_orientation_values_no_radio = {
+               "Beeper Up",
+               "Beeper Down",
+       };
+
+       public static String[] pad_orientation_values(boolean radio) {
+               if (radio)
+                       return pad_orientation_values_radio;
+               else
+                       return pad_orientation_values_no_radio;
+       }
+
        public static final String launch_sites_url = "https://maps.altusmetrum.org/launch-sites.txt";
        public static final String launch_sites_env = "LAUNCH_SITES";
 //     public static final String launch_sites_url = "file:///home/keithp/misc/text/altusmetrum/AltOS/launch-sites.txt";
@@ -389,6 +420,7 @@ public class AltosLib {
        public static final int AO_LOG_FORMAT_TELEMEGA_6 = 22;
        public static final int AO_LOG_FORMAT_EASYTIMER_2 = 23;
        public static final int AO_LOG_FORMAT_EASYMEGA_3 = 24;
+       public static final int AO_LOG_FORMAT_TELEMEGA_7 = 25;
        public static final int AO_LOG_FORMAT_NONE = 127;
 
        public static final int model_mpu6000 = 0;
@@ -671,6 +703,8 @@ public class AltosLib {
                        return product_telemega;
                case AO_LOG_FORMAT_TELEMEGA_6:
                        return product_telemega;
+               case AO_LOG_FORMAT_TELEMEGA_7:
+                       return product_telemega;
                case AO_LOG_FORMAT_NONE:
                        return product_altusmetrum;
                default:
index f852f5604993be0f974d77dd17e2f954132b541d..a2221ac4a2945d88d7ad395d005e2a422b6da494 100644 (file)
@@ -131,20 +131,15 @@ public class AltosMapStore {
                                }
                                InputStream in = new BufferedInputStream(uc.getInputStream());
                                int bytesRead = 0;
-                               int offset = 0;
-                               data = new byte[contentLength];
-                               while (offset < contentLength) {
-                                       bytesRead = in.read(data, offset, data.length - offset);
-                                       if (bytesRead == -1)
-                                               break;
-                                       offset += bytesRead;
+                               byte[] buffer = new byte[4096];
+                               ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                               while ((bytesRead = in.read(buffer)) != -1) {
+                                       baos.write(buffer, 0, bytesRead);
                                }
                                in.close();
+                               data = baos.toByteArray();
 
-                               if (offset == contentLength)
-                                       status = AltosMapTile.fetched;
-                               else
-                                       status = AltosMapTile.failed;
+                               status = AltosMapTile.fetched;
 
                        } catch (IOException e) {
                                status = AltosMapTile.failed;
index c889cdab0619acf33be7748579f08e18465a91ba..b6be02a58c787595e55220409d274553f97a6276 100644 (file)
@@ -18,6 +18,7 @@ import java.util.*;
 
 public interface AltosRecordSet {
        public AltosCalData cal_data();
+       public AltosConfigData config_data();
        public void capture_series(AltosDataListener listener);
        public boolean valid();
 }
index 076acc6252dec7b97c93fac5215954ee5af874c9..e42117814a07ff5016061d25c254b3e0a176929c 100644 (file)
@@ -21,6 +21,7 @@ package org.altusmetrum.altoslib_14;
 import java.util.concurrent.TimeoutException;
 
 class AltosSensorMega {
+       int             log_format;
        int             tick;
        int[]           sense;
        int             v_batt;
@@ -33,6 +34,7 @@ class AltosSensorMega {
 
        public AltosSensorMega(AltosLink link) throws InterruptedException, TimeoutException {
                this();
+               log_format = link.config_data().log_format;
                String[] items = link.adc();
                for (int i = 0; i < items.length;) {
                        if (items[i].equals("tick:")) {
@@ -89,17 +91,30 @@ class AltosSensorMega {
                }
        }
 
+       double pyro_voltage(int sense) {
+               switch (log_format) {
+               case AltosLib.AO_LOG_FORMAT_TELEMEGA_7:
+                       return AltosConvert.mega_pyro_voltage_30v(sense);
+               default:
+                       return AltosConvert.mega_pyro_voltage_15v(sense);
+               }
+       }
+
+       double battery_voltage(int sense) {
+               return AltosConvert.mega_battery_voltage(sense);
+       }
+
        static public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException {
                try {
                        AltosSensorMega sensor_mega = new AltosSensorMega(link);
 
-                       listener.set_battery_voltage(AltosConvert.mega_battery_voltage(sensor_mega.v_batt));
-                       listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sensor_mega.sense[4]));
-                       listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sensor_mega.sense[5]));
+                       listener.set_battery_voltage(sensor_mega.battery_voltage(sensor_mega.v_batt));
+                       listener.set_apogee_voltage(sensor_mega.pyro_voltage(sensor_mega.sense[4]));
+                       listener.set_main_voltage(sensor_mega.pyro_voltage(sensor_mega.sense[5]));
 
                        double[]        igniter_voltage = new double[4];
                        for (int i = 0; i < 4; i++)
-                               igniter_voltage[i] = AltosConvert.mega_pyro_voltage(sensor_mega.sense[i]);
+                               igniter_voltage[i] = sensor_mega.pyro_voltage(sensor_mega.sense[i]);
                        listener.set_igniter_voltage(igniter_voltage);
 
                } catch (TimeoutException te) {
index 591be15bebb289cafce2b26c4d4cf503e888e333..420e51b8cfa8e2ad5fb548b5dea6a113b7781553 100644 (file)
@@ -56,9 +56,9 @@ class AltosSensorMetrum {
        static public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException {
                try {
                        AltosSensorMetrum       sensor_metrum = new AltosSensorMetrum(link);
-                       listener.set_battery_voltage(AltosConvert.mega_battery_voltage(sensor_metrum.v_batt));
-                       listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sensor_metrum.sense_a));
-                       listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sensor_metrum.sense_m));
+                       listener.set_battery_voltage(AltosConvert.metrum_battery_voltage(sensor_metrum.v_batt));
+                       listener.set_apogee_voltage(AltosConvert.metrum_pyro_voltage(sensor_metrum.sense_a));
+                       listener.set_main_voltage(AltosConvert.metrum_pyro_voltage(sensor_metrum.sense_m));
                } catch (TimeoutException te) {
                }
        }
diff --git a/altoslib/AltosSensorTGPS4.java b/altoslib/AltosSensorTGPS4.java
new file mode 100644 (file)
index 0000000..2e62f19
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright © 2015 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.altoslib_14;
+
+import java.util.concurrent.TimeoutException;
+
+public class AltosSensorTGPS4 {
+       public int      tick;
+       public int      batt;
+
+       static public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException {
+               try {
+                       AltosSensorTGPS4        sensor_tgps = new AltosSensorTGPS4(link);
+
+                       if (sensor_tgps == null)
+                               return;
+                       listener.set_battery_voltage(AltosConvert.tele_gps_4_voltage(sensor_tgps.batt));
+
+               } catch (TimeoutException te) {
+               }
+       }
+
+       public AltosSensorTGPS4(AltosLink link) throws InterruptedException, TimeoutException {
+               String[] items = link.adc();
+               for (int i = 0; i < items.length - 1;) {
+                       if (items[i].equals("tick:")) {
+                               tick = Integer.parseInt(items[i+1]);
+                               i += 2;
+                               continue;
+                       }
+                       if (items[i].equals("batt:")) {
+                               batt = Integer.parseInt(items[i+1]);
+                               i += 2;
+                               continue;
+                       }
+                       i++;
+               }
+       }
+}
+
index 5fa5fc3bbb9955676dfa96c3391ace005bccd808..8dbb939c56dffd84e2fc0af9842ab4fd52236cc1 100644 (file)
@@ -75,7 +75,7 @@ public abstract class AltosTelemetry implements AltosDataProvider {
        final static int packet_type_satellite = 0x06;
        final static int packet_type_companion = 0x07;
        final static int packet_type_mega_sensor_mpu = 0x08;
-       final static int packet_type_mega_data = 0x09;
+       final static int packet_type_mega_data_15v = 0x09;
        final static int packet_type_metrum_sensor = 0x0a;
        final static int packet_type_metrum_data = 0x0b;
        final static int packet_type_mini2 = 0x10;
@@ -83,6 +83,7 @@ public abstract class AltosTelemetry implements AltosDataProvider {
        final static int packet_type_mega_sensor_bmx160 = 0x12;
        final static int packet_type_mega_norm_mpu6000_mmc5983 = 0x13;
        final static int packet_type_mega_norm_bmi088_mmc5983 = 0x14;
+       final static int packet_type_mega_data_30v = 0x15;
 
        static AltosTelemetry parse_hex(String hex)  throws ParseException, AltosCRCException {
                AltosTelemetry  telem = null;
index 6f01f51c180be81d53f54471401a14c328ef23bc..5ba32518a3fff5fb1dedef4e757578f550574660 100644 (file)
@@ -138,6 +138,10 @@ public class AltosTelemetryFile implements AltosRecordSet {
                listener.finish();
        }
 
+       public AltosConfigData config_data() {
+               return null;
+       }
+
        public AltosTelemetryFile(FileInputStream input) throws IOException {
                telems = new AltosTelemetryIterable(input);
        }
index 3e1e3c95d1fff00cb8958088803a204e79b61bc6..33ca648e3bc867e048a5697662b95f1eb0d68c82 100644 (file)
@@ -41,20 +41,29 @@ public class AltosTelemetryMegaData extends AltosTelemetryStandard {
                super(bytes);
        }
 
+       double pyro_voltage(int sense) {
+               switch (type()) {
+               case AltosTelemetry.packet_type_mega_data_30v:
+                       return AltosConvert.mega_pyro_voltage_30v(sense);
+               default:
+                       return AltosConvert.mega_pyro_voltage_15v(sense);
+               }
+       }
+
        public void provide_data(AltosDataListener listener) {
                super.provide_data(listener);
 
                listener.set_state(state());
 
                listener.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt()));
-               listener.set_pyro_voltage(AltosConvert.mega_pyro_voltage(v_pyro()));
+               listener.set_pyro_voltage(pyro_voltage(v_pyro()));
 
-               listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense(4)));
-               listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sense(5)));
+               listener.set_apogee_voltage(pyro_voltage(sense(4)));
+               listener.set_main_voltage(pyro_voltage(sense(5)));
 
                double voltages[] = new double[4];
                for (int i = 0; i < 4; i++)
-                       voltages[i] = AltosConvert.mega_pyro_voltage(sense(i));
+                       voltages[i] = pyro_voltage(sense(i));
 
                listener.set_igniter_voltage(voltages);
 
index b26bff64e2f842365e8f35c056fa2e906a20089f..d1abd6dba260332efdb4d78bbf2c3994d4aec31a 100644 (file)
@@ -49,9 +49,9 @@ public class AltosTelemetryMetrumSensor extends AltosTelemetryStandard {
 
                listener.set_kalman(height_16(), speed()/16.0, acceleration()/16.0);
 
-               listener.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt()));
+               listener.set_battery_voltage(AltosConvert.metrum_battery_voltage(v_batt()));
 
-               listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense_a()));
-               listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sense_m()));
+               listener.set_apogee_voltage(AltosConvert.metrum_pyro_voltage(sense_a()));
+               listener.set_main_voltage(AltosConvert.metrum_pyro_voltage(sense_m()));
        }
 }
index bea217c82dcbe10ad00497df323018a226ec5536..0cb0066b9bf28520142dfd907aa65e4c5f1e3b50 100644 (file)
@@ -81,7 +81,8 @@ public abstract class AltosTelemetryStandard extends AltosTelemetry {
                case packet_type_mega_sensor_bmx160:
                        telem = new AltosTelemetryMegaSensor(bytes, AltosIMU.imu_type_telemega_v4);
                        break;
-               case packet_type_mega_data:
+               case packet_type_mega_data_15v:
+               case packet_type_mega_data_30v:
                        telem = new AltosTelemetryMegaData(bytes);
                        break;
                case packet_type_metrum_sensor:
index 7cb2ef6fbc82ca0dc2c07dd09411a34a1563a80c..ed69e9abde9dda8c0d8e42f6cf2a918348831af1 100644 (file)
@@ -118,6 +118,7 @@ altoslib_JAVA = \
        AltosSensorTGPS1.java \
        AltosSensorTGPS2.java \
        AltosSensorTGPS3.java \
+       AltosSensorTGPS4.java \
        AltosSensorEasyMotor2.java \
        AltosState.java \
        AltosStateName.java \
index bc082a4ee6fbda228ccf58de5fc124e3f5ba5f66..9d39cda1bf820e0c898b8a3b1d5633881c57b5f2 100644 (file)
@@ -44,6 +44,7 @@ public class AltosConfigFCUI
        JLabel                  radio_enable_label;
        JLabel                  radio_10mw_label;
        JLabel                  report_feet_label;
+       JLabel                  gps_receiver_label;
        JLabel                  rate_label;
        JLabel                  aprs_interval_label;
        JLabel                  aprs_ssid_label;
@@ -73,6 +74,7 @@ public class AltosConfigFCUI
        JRadioButton            radio_enable_value;
        JRadioButton            radio_10mw_value;
        JComboBox<String>       report_feet_value;
+       JComboBox<String>       gps_receiver_value;
        AltosUIRateList         rate_value;
        JComboBox<String>       aprs_interval_value;
        JComboBox<Integer>      aprs_ssid_value;
@@ -121,13 +123,6 @@ public class AltosConfigFCUI
                "0", "5", "10", "15", "20"
        };
 
-       static String[]         ignite_mode_values = {
-               "Dual Deploy",
-               "Redundant Apogee",
-               "Redundant Main",
-               "Separation & Apogee",
-       };
-
        static String[]         aprs_interval_values = {
                "Disabled",
                "2",
@@ -152,16 +147,6 @@ public class AltosConfigFCUI
                "4250",
        };
 
-       static String[]         pad_orientation_values_radio = {
-               "Antenna Up",
-               "Antenna Down",
-       };
-
-       static String[]         pad_orientation_values_no_radio = {
-               "Beeper Up",
-               "Beeper Down",
-       };
-
        String[] pad_orientation_values;
 
        static String[]         tracker_motion_values_m = {
@@ -326,11 +311,7 @@ public class AltosConfigFCUI
        }
 
        void set_pad_orientation_values() {
-               String [] new_values;
-               if (has_radio())
-                       new_values = pad_orientation_values_radio;
-               else
-                       new_values = pad_orientation_values_no_radio;
+               String [] new_values = AltosLib.pad_orientation_values(has_radio());
                if (new_values != pad_orientation_values) {
                        int id = pad_orientation_value.getSelectedIndex();
                        pad_orientation_value.removeAllItems();
@@ -353,7 +334,7 @@ public class AltosConfigFCUI
 
        void set_beep_tool_tip() {
                if (beep_value.isVisible())
-                       beep_value.setToolTipText("What frequency the beeper will sound at");
+                       beep_value.setToolTipText("What frequency the beeper will sound at (0 for off)");
                else
                        beep_value.setToolTipText("Older firmware could not select beeper frequency");
        }
@@ -372,6 +353,13 @@ public class AltosConfigFCUI
                        report_feet_value.setToolTipText("Older firmware always beeps max height in meters");
        }
 
+       void set_gps_receiver_tool_tip() {
+               if (gps_receiver_value.isVisible())
+                       gps_receiver_value.setToolTipText("GPS receiver selection");
+               else
+                       gps_receiver_value.setToolTipText("Only TeleMega with new firmware supports alternate GPS receivers");
+       }
+
        /* Build the UI using a grid bag */
        public AltosConfigFCUI(JFrame in_owner, boolean remote) {
                super (in_owner, title, false);
@@ -656,6 +644,32 @@ public class AltosConfigFCUI
                set_report_feet_tool_tip();
                row++;
 
+               /* GPS Receiver */
+               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;
+               gps_receiver_label = new JLabel("GPS Receiver:");
+               pane.add(gps_receiver_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;
+               gps_receiver_value = new JComboBox<String>(AltosLib.gps_receiver_names);
+               gps_receiver_value.setEditable(false);
+               gps_receiver_value.addItemListener(this);
+               pane.add(gps_receiver_value, c);
+               set_gps_receiver_tool_tip();
+               row++;
+
                /* Telemetry Rate */
                c = new GridBagConstraints();
                c.gridx = 0; c.gridy = row;
@@ -858,7 +872,7 @@ public class AltosConfigFCUI
                c.anchor = GridBagConstraints.LINE_START;
                c.insets = ir;
                c.ipady = 5;
-               ignite_mode_value = new JComboBox<String>(ignite_mode_values);
+               ignite_mode_value = new JComboBox<String>(AltosLib.ignite_mode_values);
                ignite_mode_value.setEditable(false);
                ignite_mode_value.addItemListener(this);
                pane.add(ignite_mode_value, c);
@@ -884,7 +898,7 @@ public class AltosConfigFCUI
                c.anchor = GridBagConstraints.LINE_START;
                c.insets = ir;
                c.ipady = 5;
-               pad_orientation_values = pad_orientation_values_no_radio;
+               pad_orientation_values = AltosLib.pad_orientation_values(false);
 
                pad_orientation_value = new JComboBox<String>(pad_orientation_values);
                pad_orientation_value.setEditable(false);
@@ -1418,7 +1432,7 @@ public class AltosConfigFCUI
 
        public void set_ignite_mode(int new_ignite_mode) {
                if (new_ignite_mode != AltosLib.MISSING) {
-                       if (new_ignite_mode >= ignite_mode_values.length)
+                       if (new_ignite_mode >= AltosLib.ignite_mode_values.length)
                                new_ignite_mode = 0;
                        if (new_ignite_mode < 0) {
                                ignite_mode_value.setEnabled(false);
@@ -1553,6 +1567,32 @@ public class AltosConfigFCUI
                        return AltosLib.MISSING;
        }
 
+       public void set_gps_receiver(int new_gps_receiver) {
+               System.out.printf("set_gps_receiver %d\n", new_gps_receiver);
+               if (new_gps_receiver != AltosLib.MISSING) {
+                       if (new_gps_receiver >= AltosLib.gps_receiver_names.length)
+                               new_gps_receiver = 0;
+                       if (new_gps_receiver < 0) {
+                               gps_receiver_value.setEnabled(false);
+                               new_gps_receiver = 0;
+                       } else {
+                               gps_receiver_value.setEnabled(true);
+                       }
+                       gps_receiver_value.setSelectedIndex(new_gps_receiver);
+               }
+               gps_receiver_value.setVisible(new_gps_receiver != AltosLib.MISSING);
+               gps_receiver_label.setVisible(new_gps_receiver != AltosLib.MISSING);
+
+               set_gps_receiver_tool_tip();
+       }
+
+       public int gps_receiver() {
+               if (gps_receiver_value.isVisible())
+                       return gps_receiver_value.getSelectedIndex();
+               else
+                       return AltosLib.MISSING;
+       }
+
        String[] tracker_motion_values() {
                if (AltosConvert.imperial_units)
                        return tracker_motion_values_ft;
index 127a5beb0fd1566dc8ca28ca56a25b68ca892f15..777b6855d6b2cb2427542268d47d53ab60993062 100644 (file)
@@ -29,7 +29,7 @@ import org.altusmetrum.altosuilib_14.*;
 
 import org.jfree.chart.ChartPanel;
 import org.jfree.chart.JFreeChart;
-import org.jfree.ui.RefineryUtilities;
+import org.jfree.chart.ui.UIUtils;
 
 public class AltosGraphUI extends AltosUIFrame implements AltosFontListener, AltosUnitsListener, AltosFilterListener
 {
@@ -39,6 +39,8 @@ public class AltosGraphUI extends AltosUIFrame implements AltosFontListener, Alt
        AltosUIMap              map;
        AltosFlightStats        stats;
        AltosFlightStatsTable   statsTable;
+       AltosFlightConfigTable  configTable;
+       AltosFlightPyroTable    pyroTable;
        AltosGPS                gps;
        boolean                 has_gps;
 
@@ -77,6 +79,10 @@ public class AltosGraphUI extends AltosUIFrame implements AltosFontListener, Alt
                        map.font_size_changed(font_size);
                if (statsTable != null)
                        statsTable.font_size_changed(font_size);
+               if (configTable != null)
+                       configTable.font_size_changed(font_size);
+               if (pyroTable != null)
+                       pyroTable.font_size_changed(font_size);
        }
 
        public void units_changed(boolean imperial_units) {
@@ -84,6 +90,10 @@ public class AltosGraphUI extends AltosUIFrame implements AltosFontListener, Alt
                        map.units_changed(imperial_units);
                if (enable != null)
                        enable.units_changed(imperial_units);
+               if (configTable != null)
+                       configTable.units_changed(imperial_units);
+               if (pyroTable != null)
+                       pyroTable.units_changed(imperial_units);
        }
 
        AltosUIFlightSeries flight_series;
@@ -106,7 +116,7 @@ public class AltosGraphUI extends AltosUIFrame implements AltosFontListener, Alt
        AltosGraphUI(AltosRecordSet set, File file) throws InterruptedException, IOException {
                super(file.getName());
                AltosCalData    cal_data = set.cal_data();
-
+               AltosConfigData config_data = set.config_data();
 
                pane = new JTabbedPane();
 
@@ -127,6 +137,14 @@ public class AltosGraphUI extends AltosUIFrame implements AltosFontListener, Alt
                pane.add("Flight Graph", graph.panel);
                pane.add("Configure Graph", enable);
                pane.add("Flight Statistics", statsTable);
+               if (config_data != null) {
+                       configTable = new AltosFlightConfigTable(config_data);
+                       pane.add("Configuration", configTable);
+                       if (config_data.npyro > 0 && config_data.npyro != AltosLib.MISSING) {
+                               pyroTable = new AltosFlightPyroTable(config_data.pyros, config_data.npyro);
+                               pane.add("Pyros", pyroTable);
+                       }
+               }
 
                has_gps = false;
                fill_map(flight_series);
index 1da6408c18fe0f1e6fb03fe91c4397cc0d1b58c6..38dd29dff5febf72554737d2e7f5b9ba9badfa75 100644 (file)
@@ -140,7 +140,8 @@ FIRMWARE_TMEGA_3_0=$(top_srcdir)/src/telemega-v3.0/telemega-v3.0-$(VERSION).ihx
 FIRMWARE_TMEGA_4_0=$(top_srcdir)/src/telemega-v4.0/telemega-v4.0-$(VERSION).ihx
 FIRMWARE_TMEGA_5_0=$(top_srcdir)/src/telemega-v5.0/telemega-v5.0-$(VERSION).ihx
 FIRMWARE_TMEGA_6_0=$(top_srcdir)/src/telemega-v6.0/telemega-v6.0-$(VERSION).ihx
-FIRMWARE_TMEGA=$(FIRMWARE_TMEGA_1_0) $(FIRMWARE_TMEGA_2_0) $(FIRMWARE_TMEGA_3_0) $(FIRMWARE_TMEGA_4_0) $(FIRMWARE_TMEGA_5_0) $(FIRMWARE_TMEGA_6_0)
+FIRMWARE_TMEGA_7_0=$(top_srcdir)/src/telemega-v7.0/telemega-v7.0-$(VERSION).ihx
+FIRMWARE_TMEGA=$(FIRMWARE_TMEGA_1_0) $(FIRMWARE_TMEGA_2_0) $(FIRMWARE_TMEGA_3_0) $(FIRMWARE_TMEGA_4_0) $(FIRMWARE_TMEGA_5_0) $(FIRMWARE_TMEGA_6_0) $(FIRMWARE_TMEGA_7_0)
 
 FIRMWARE_EMINI_1_0=$(top_srcdir)/src/easymini-v1.0/easymini-v1.0-$(VERSION).ihx
 FIRMWARE_EMINI_2_0=$(top_srcdir)/src/easymini-v2.0/easymini-v2.0-$(VERSION).ihx
@@ -149,18 +150,21 @@ FIRMWARE_EMINI=$(FIRMWARE_EMINI_1_0) $(FIRMWARE_EMINI_2_0) $(FIRMWARE_EMINI_3_0)
 
 FIRMWARE_EMEGA_1_0=$(top_srcdir)/src/easymega-v1.0/easymega-v1.0-$(VERSION).ihx
 FIRMWARE_EMEGA_2_0=$(top_srcdir)/src/easymega-v2.0/easymega-v2.0-$(VERSION).ihx
-FIRMWARE_EMEGA=$(FIRMWARE_EMEGA_1_0) $(FIRMWARE_EMEGA_2_0)
+FIRMWARE_EMEGA_3_0=$(top_srcdir)/src/easymega-v3.0/easymega-v3.0-$(VERSION).ihx
+FIRMWARE_EMEGA=$(FIRMWARE_EMEGA_1_0) $(FIRMWARE_EMEGA_2_0) $(FIRMWARE_EMEGA_3_0)
 
 FIRMWARE_EMOTOR_3=$(top_srcdir)/src/easymotor-v3/easymotor-v3-$(VERSION).ihx
 FIRMWARE_EMOTOR=$(FIRMWARE_EMOTOR_3)
 
 FIRMWARE_ETIMER_1=$(top_srcdir)/src/easytimer-v1/easytimer-v1-$(VERSION).ihx
-FIRMWARE_ETIMER=$(FIRMWARE_ETIMER_1)
+FIRMWARE_ETIMER_2=$(top_srcdir)/src/easytimer-v2/easytimer-v2-$(VERSION).ihx
+FIRMWARE_ETIMER=$(FIRMWARE_ETIMER_1) $(FIRMWARE_ETIMER_2)
 
 FIRMWARE_TGPS_1_0=$(top_srcdir)/src/telegps-v1.0/telegps-v1.0-$(VERSION).ihx
 FIRMWARE_TGPS_2_0=$(top_srcdir)/src/telegps-v2.0/telegps-v2.0-$(VERSION).ihx
 FIRMWARE_TGPS_3_0=$(top_srcdir)/src/telegps-v3.0/telegps-v3.0-$(VERSION).ihx
-FIRMWARE_TGPS=$(FIRMWARE_TGPS_1_0) $(FIRMWARE_TGPS_2_0) $(FIRMWARE_TGPS_3_0)
+FIRMWARE_TGPS_4_0=$(top_srcdir)/src/telegps-v4.0/telegps-v4.0-$(VERSION).ihx
+FIRMWARE_TGPS=$(FIRMWARE_TGPS_1_0) $(FIRMWARE_TGPS_2_0) $(FIRMWARE_TGPS_3_0) $(FIRMWARE_TGPS_4_0)
 
 FIRMWARE_TLCO_2_0=$(top_srcdir)/src/telelco-v2.0/telelco-v2.0-$(VERSION).ihx
 FIRMWARE_TLCO=$(FIRMWARE_TLCO_2_0)
index ee8251bbe14f3c8404413460e86efef4179309db..d11c5fd951d57773d27f6d9ec14283a2205e7239 100644 (file)
@@ -127,6 +127,7 @@ Section "Firmware"
        File "../src/telegps-v1.0/telegps-v1.0-${VERSION}.ihx"
        File "../src/telegps-v2.0/telegps-v2.0-${VERSION}.ihx"
        File "../src/telegps-v3.0/telegps-v3.0-${VERSION}.ihx"
+       File "../src/telegps-v4.0/telegps-v4.0-${VERSION}.ihx"
        File "../src/teledongle-v3.0/teledongle-v3.0-${VERSION}.ihx"
        File "../src/telebt-v3.0/telebt-v3.0-${VERSION}.ihx"
        File "../src/telebt-v4.0/telebt-v4.0-${VERSION}.ihx"
@@ -136,13 +137,16 @@ Section "Firmware"
        File "../src/telemega-v4.0/telemega-v4.0-${VERSION}.ihx"
        File "../src/telemega-v5.0/telemega-v5.0-${VERSION}.ihx"
        File "../src/telemega-v6.0/telemega-v6.0-${VERSION}.ihx"
+       File "../src/telemega-v7.0/telemega-v7.0-${VERSION}.ihx"
        File "../src/easymini-v1.0/easymini-v1.0-${VERSION}.ihx"
        File "../src/easymini-v2.0/easymini-v2.0-${VERSION}.ihx"
        File "../src/easymini-v3.0/easymini-v3.0-${VERSION}.ihx"
        File "../src/easymega-v1.0/easymega-v1.0-${VERSION}.ihx"
        File "../src/easymega-v2.0/easymega-v2.0-${VERSION}.ihx"
+       File "../src/easymega-v3.0/easymega-v3.0-${VERSION}.ihx"
        File "../src/easymotor-v3/easymotor-v3-${VERSION}.ihx"
        File "../src/easytimer-v1/easytimer-v1-${VERSION}.ihx"
+       File "../src/easytimer-v2/easytimer-v2-${VERSION}.ihx"
        File "../src/telelco-v2.0/telelco-v2.0-${VERSION}.ihx"
        File "../src/telefireeight-v1.0/telefireeight-v1.0-${VERSION}.ihx"
        File "../src/telefireeight-v2.0/telefireeight-v2.0-${VERSION}.ihx"
diff --git a/altosuilib/AltosFlightConfigTable.java b/altosuilib/AltosFlightConfigTable.java
new file mode 100644 (file)
index 0000000..4f9714f
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * Copyright © 2024 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.altosuilib_14;
+
+import java.awt.*;
+import javax.swing.*;
+import java.util.*;
+import org.altusmetrum.altoslib_14.*;
+
+public class AltosFlightConfigTable extends JComponent
+       implements AltosFontListener, AltosUnitsListener
+{
+       GridBagLayout   layout;
+
+       FlightConfig[] flight_configs;
+       AltosConfigData config_data;
+
+       class FlightConfig implements AltosFontListener {
+               JLabel          label;
+               JLabel[]        value;
+
+               public void font_size_changed(int font_size) {
+                       label.setFont(AltosUILib.label_font);
+                       for (int i = 0; i < value.length; i++)
+                               value[i].setFont(AltosUILib.value_font);
+               }
+
+               public void set(String l, String[] values) {
+                       label.setText(l);
+                       for (int j = 0; j < values.length; j++)
+                               value[j].setText(values[j]);
+               }
+
+               public FlightConfig(GridBagLayout layout, int y, String label_text, String ... values) {
+                       GridBagConstraints      c = new GridBagConstraints();
+                       c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad);
+                       c.weighty = 1;
+
+                       label = new JLabel(label_text);
+                       label.setFont(AltosUILib.label_font);
+                       label.setHorizontalAlignment(SwingConstants.LEFT);
+                       c.gridx = 0; c.gridy = y;
+                       c.anchor = GridBagConstraints.WEST;
+                       c.fill = GridBagConstraints.VERTICAL;
+                       c.weightx = 0;
+                       layout.setConstraints(label, c);
+                       add(label);
+
+                       value = new JLabel[values.length];
+                       for (int j = 0; j < values.length; j++) {
+                               value[j] = new JLabel(values[j]);
+                               value[j].setFont(AltosUILib.value_font);
+                               c.gridx = j+1; c.gridy = y;
+                               c.anchor = GridBagConstraints.CENTER;
+                               c.fill = GridBagConstraints.BOTH;
+                               c.weightx = 1;
+                               layout.setConstraints(value[j], c);
+                               add(value[j]);
+                       }
+                       flight_configs[y] = this;
+               }
+
+       }
+
+       private FlightConfig set_config(int y, String label, String ... values) {
+               if (flight_configs[y] == null)
+                       flight_configs[y] = new FlightConfig(layout, y, label, values);
+               else
+                       flight_configs[y].set(label, values);
+               return flight_configs[y];
+       }
+
+       public void font_size_changed(int font_size) {
+               for (int y = 0; flight_configs[y] != null; y++)
+                       flight_configs[y].font_size_changed(font_size);
+       }
+
+       private String main_deploy_label() {
+               return String.format("Main Deploy Altitude(%s)", AltosConvert.height.parse_units());
+       }
+
+       private String main_deploy_value() {
+               return String.format("%-6.1f", AltosConvert.height.value(config_data.main_deploy, AltosConvert.imperial_units));
+       }
+
+       public void set_config() {
+               int y = 0;
+               if (config_data.serial != AltosLib.MISSING) {
+                       if (config_data.product != null && config_data.version != null)
+                               set_config(y++, "Device",
+                                          config_data.product,
+                                          String.format("version %s", config_data.version),
+                                          String.format("serial %d", config_data.serial));
+                       else
+                               set_config(y++, "Serial", String.format("%d", config_data.serial));
+               }
+               if (config_data.flight != AltosLib.MISSING)
+                       set_config(y++, "Flight", String.format("%d", config_data.flight));
+               if (config_data.main_deploy != AltosLib.MISSING)
+                       set_config(y++, main_deploy_label(), main_deploy_value());
+               if (config_data.apogee_delay != AltosLib.MISSING)
+                       set_config(y++, "Apogee Delay(s)", String.format("%d", config_data.apogee_delay));
+               if (config_data.apogee_lockout != AltosLib.MISSING)
+                       set_config(y++, "Apogee Lockout(s)", String.format("%d", config_data.apogee_lockout));
+               if (config_data.radio_frequency != AltosLib.MISSING)
+                       set_config(y++, "Radio Frequency (MHz)", String.format("%-7.3f", config_data.radio_frequency / 1000.0));
+               if (config_data.radio_calibration != AltosLib.MISSING)
+                       set_config(y++, "Radio Calibration", String.format("%d", config_data.radio_calibration));
+               if (config_data.radio_enable != AltosLib.MISSING)
+                       set_config(y++, "Radio Enable", String.format("%b", config_data.radio_enable != 0));
+               if (config_data.radio_10mw != AltosLib.MISSING)
+                       set_config(y++, "Limit transmit to 10mW", String.format("%b", config_data.radio_10mw != 0));
+               if (config_data.report_feet != AltosLib.MISSING)
+                       set_config(y++, "Beep max height in", config_data.report_feet == 0 ? "Meters" : "Feet");
+               if (config_data.gps_receiver != AltosLib.MISSING)
+                       set_config(y++, "GPS Receiver", AltosLib.gps_receiver_names[config_data.gps_receiver]);
+               if (config_data.telemetry_rate != AltosLib.MISSING)
+                       set_config(y++, "Telemetry baud rate", String.format("%d", AltosLib.ao_telemetry_rate_values[config_data.telemetry_rate]));
+               if (config_data.aprs_interval != AltosLib.MISSING)
+                       set_config(y++, "APRS Interval(s)", String.format("%d", config_data.aprs_interval));
+               if (config_data.aprs_ssid != AltosLib.MISSING)
+                       set_config(y++, "APRS SSID", String.format("%d", config_data.aprs_ssid));
+               if (config_data.aprs_format != AltosLib.MISSING)
+                       set_config(y++, "APRS Format", AltosLib.ao_aprs_format_name[config_data.aprs_format]);
+               if (config_data.callsign != null)
+                       set_config(y++, "Callsign", config_data.callsign);
+               if (config_data.flight_log_max != AltosLib.MISSING)
+                       set_config(y++, "Maximum Flight Log Size(kB)", String.format("%d", config_data.flight_log_max));
+               if (config_data.ignite_mode != AltosLib.MISSING)
+                       set_config(y++, "Igniter Firing Mode", AltosLib.ignite_mode_values[config_data.ignite_mode]);
+               if (config_data.pad_orientation != AltosLib.MISSING)
+                       set_config(y++, "Pad Orientation", AltosLib.pad_orientation_values(config_data.has_radio())[config_data.pad_orientation]);
+               if (config_data.accel_cal_plus != AltosLib.MISSING)
+                       set_config(y++, "Accel Calibration",
+                                  String.format("Plus %d", config_data.accel_cal_plus),
+                                  String.format("Minus %d", config_data.accel_cal_minus));
+               if (config_data.beep != AltosLib.MISSING)
+                       set_config(y++, "Beeper(Hz)",
+                                  config_data.beep == 0 ? "Disabled" :
+                                  String.format("%-7.1f", AltosConvert.beep_value_to_freq(config_data.beep)));
+               if (config_data.tracker_motion != AltosLib.MISSING)
+                       set_config(y++,
+                                  String.format("Logging Trigger Motion (%s):", AltosConvert.height.parse_units()),
+                                  String.format("%-6.1f",
+                                                AltosConvert.height.value(config_data.tracker_motion, AltosConvert.imperial_units)));
+               if (config_data.tracker_interval != AltosLib.MISSING)
+                       set_config(y++, "Position Reporting Interval(s)",
+                                  String.format("%d", config_data.tracker_interval));
+       }
+
+       public void units_changed(boolean imperial_units) {
+               set_config();
+       }
+
+       public void tell_closing() {
+               AltosUIPreferences.unregister_font_listener(this);
+       }
+
+       public AltosFlightConfigTable() {
+               layout = new GridBagLayout();
+
+               setLayout(layout);
+
+               AltosUIPreferences.register_font_listener(this);
+       }
+
+       public AltosFlightConfigTable(AltosConfigData config_data) {
+               this();
+               this.config_data = config_data;
+               flight_configs = new FlightConfig[30];
+               set_config();
+       }
+}
diff --git a/altosuilib/AltosFlightPyroTable.java b/altosuilib/AltosFlightPyroTable.java
new file mode 100644 (file)
index 0000000..5e27a2f
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * Copyright © 2024 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.altosuilib_14;
+
+import java.awt.*;
+import javax.swing.*;
+import java.util.*;
+import org.altusmetrum.altoslib_14.*;
+
+public class AltosFlightPyroTable extends JComponent
+       implements AltosFontListener, AltosUnitsListener
+{
+       GridBagLayout   layout;
+       AltosPyro[]     pyros;
+       int             npyro;
+       FlightPyro[]    flight_pyros;
+
+       class FlightPyro implements AltosFontListener {
+               JLabel          label;
+               JTextField[]    text_fields;
+
+               public void font_size_changed(int font_size) {
+                       label.setFont(AltosUILib.label_font);
+                       for (int i = 0; i < text_fields.length; i++)
+                               text_fields[i].setFont(AltosUILib.value_font);
+               }
+
+               public void set_value(int y, int p, String value) {
+                       GridBagConstraints      c = new GridBagConstraints();
+                       c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad);
+                       c.weighty = 1;
+                       JTextField      text_field;
+
+                       if (text_fields[p] == null) {
+                               text_field = new JTextField(value);
+                               text_field.setEditable(false);
+                               text_field.setFont(AltosUILib.value_font);
+                               text_field.setHorizontalAlignment(SwingConstants.RIGHT);
+                               c.gridx = p+1; c.gridy = y;
+                               c.anchor = GridBagConstraints.EAST;
+                               c.fill = GridBagConstraints.BOTH;
+                               c.weightx = 1;
+                               layout.setConstraints(text_field, c);
+                               add(text_field);
+                               text_fields[p] = text_field;
+                       } else {
+                               text_fields[p].setText(value);
+                       }
+               }
+
+               public void set_label(String text) {
+                       label.setText(text);
+               }
+
+               public FlightPyro(GridBagLayout layout, int y, String label_text, int npyro) {
+                       GridBagConstraints      c = new GridBagConstraints();
+                       c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad);
+                       c.weighty = 1;
+
+                       if (label_text != null) {
+                               label = new JLabel(label_text);
+                               label.setFont(AltosUILib.label_font);
+                               label.setHorizontalAlignment(SwingConstants.LEFT);
+                               c.gridx = 0; c.gridy = y;
+                               c.anchor = GridBagConstraints.WEST;
+                               c.fill = GridBagConstraints.VERTICAL;
+                               c.weightx = 0;
+                               layout.setConstraints(label, c);
+                               add(label);
+                       }
+
+                       text_fields = new JTextField[npyro];
+               }
+       }
+
+       public void font_size_changed(int font_size) {
+               for (int i = 0; i < flight_pyros.length; i++)
+                       flight_pyros[i].font_size_changed(font_size);
+       }
+
+       public void set_pyros() {
+               int nrow = 1;
+               for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1) {
+                       if ((AltosPyro.pyro_all_useful & flag) != 0) {
+                               for (int p = 0; p < npyro; p++) {
+                                       if ((pyros[p].flags & flag) != 0) {
+                                               String text;
+                                               double  value = pyros[p].get_value(flag);
+                                               if ((flag & AltosPyro.pyro_state_value) != 0) {
+                                                       text = AltosLib.state_name_capital((int) value);
+                                               } else {
+                                                       double  scale = AltosPyro.pyro_to_scale(flag);
+                                                       double  unit_value = value;
+                                                       AltosUnits units = AltosPyro.pyro_to_units(flag);
+                                                       if (units != null)
+                                                               unit_value = units.parse_value(value);
+                                                       String  format;
+                                                       if (scale >= 100)
+                                                               format = "%6.2f";
+                                                       else if (scale >= 10)
+                                                               format = "%6.1f";
+                                                       else
+                                                               format = "%6.0f";
+                                                       text = String.format(format, unit_value);
+                                               }
+                                               flight_pyros[nrow].set_value(nrow, p, text);
+                                       }
+                               }
+                               nrow++;
+                       }
+               }
+       }
+
+       public void units_changed(boolean imperial_units) {
+               System.out.printf("units changed\n");
+               int nrow = 1;
+               for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1) {
+                       if ((AltosPyro.pyro_all_useful & flag) != 0) {
+                               String name = AltosPyro.pyro_to_name(flag);
+                               flight_pyros[nrow].set_label(name);
+                       }
+               }
+               set_pyros();
+       }
+
+       public void tell_closing() {
+               AltosUIPreferences.unregister_font_listener(this);
+       }
+
+       public AltosFlightPyroTable(AltosPyro[] pyros, int npyro) {
+               layout = new GridBagLayout();
+
+               int nrow = 0;
+
+               for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1) {
+                       if ((AltosPyro.pyro_all_useful & flag) != 0) {
+                               nrow++;
+                       }
+               }
+
+               flight_pyros = new FlightPyro[nrow + 1];
+
+               nrow = 0;
+
+               flight_pyros[0] = new FlightPyro(layout, 0, null, npyro);
+
+               for (int p = 0; p < npyro; p++) {
+                       flight_pyros[0].set_value(0, p, String.format("Channel %c", 'A' + p));
+               }
+               nrow++;
+               for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1) {
+                       if ((AltosPyro.pyro_all_useful & flag) != 0) {
+                               String name = AltosPyro.pyro_to_name(flag);
+                               flight_pyros[nrow] = new FlightPyro(layout, nrow, name, npyro);
+                               nrow++;
+                       }
+               }
+
+
+               this.pyros = pyros;
+               this.npyro = npyro;
+
+               set_pyros();
+
+               setLayout(layout);
+               AltosUIPreferences.register_font_listener(this);
+       }
+}
index 46dc80f36e02b56defd2fa5a99d0e430c8a04bfe..393c8cc6bb965c3cdd7f3a6e019e5e236a78ebe6 100644 (file)
@@ -25,7 +25,7 @@ import java.awt.*;
 import javax.swing.*;
 import org.altusmetrum.altoslib_14.*;
 
-import org.jfree.ui.*;
+import org.jfree.chart.ui.*;
 import org.jfree.chart.*;
 import org.jfree.chart.plot.*;
 import org.jfree.chart.axis.*;
index 75722d12bea000c34de25414e356ac91e7feb3e7..a31af5a2891df2fa3f613742dcdfe6bb0c0f744d 100644 (file)
@@ -25,7 +25,7 @@ import java.awt.*;
 import javax.swing.*;
 import org.altusmetrum.altoslib_14.*;
 
-import org.jfree.ui.*;
+import org.jfree.chart.ui.*;
 import org.jfree.chart.*;
 import org.jfree.chart.plot.*;
 import org.jfree.chart.axis.*;
index 3806930171b7513a2221059576043448cc97717f..973117f36430fab03349e41d73bb064e42cbdf83 100644 (file)
@@ -27,7 +27,7 @@ import java.util.concurrent.*;
 import java.util.*;
 import org.altusmetrum.altoslib_14.*;
 
-import org.jfree.ui.*;
+import org.jfree.chart.ui.*;
 import org.jfree.chart.*;
 import org.jfree.chart.plot.*;
 import org.jfree.chart.axis.*;
index 7e64cc2e2a26230428fbb2838a942eab9f556ba7..51f9c959f961eef9d4a83620b5d4f7e6477c564d 100644 (file)
@@ -19,7 +19,7 @@ import java.awt.*;
 import javax.swing.*;
 import org.altusmetrum.altoslib_14.*;
 
-import org.jfree.ui.*;
+import org.jfree.chart.ui.*;
 import org.jfree.chart.*;
 import org.jfree.chart.plot.*;
 import org.jfree.chart.axis.*;
index 12176070f50ac441dd967d0126bd76fb355a09de..ca60e1a04477a37aeba9dfb8aab6dc35a72f99ca 100644 (file)
@@ -26,7 +26,7 @@ import java.awt.*;
 import javax.swing.*;
 import org.altusmetrum.altoslib_14.*;
 
-import org.jfree.ui.*;
+import org.jfree.chart.ui.*;
 import org.jfree.chart.*;
 import org.jfree.chart.plot.*;
 import org.jfree.chart.axis.*;
@@ -155,7 +155,7 @@ public class AltosUIGraph implements AltosUnitsListener, AltosShapeListener {
                chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT,
                                       plot, true);
 
-               ChartUtilities.applyCurrentTheme(chart);
+               ChartUtils.applyCurrentTheme(chart);
 
                plot.setDomainGridlinePaint(gridline_color);
                plot.setRangeGridlinePaint(gridline_color);
index 9f5cd3f16bbc0771ed0eb34d76e59fcedfbd3c02..8310b1df68de4a93804a35185bf3028c71fa703e 100644 (file)
@@ -25,7 +25,7 @@ import java.awt.*;
 import javax.swing.*;
 import org.altusmetrum.altoslib_14.*;
 
-import org.jfree.ui.*;
+import org.jfree.chart.ui.*;
 import org.jfree.chart.*;
 import org.jfree.chart.plot.*;
 import org.jfree.chart.axis.*;
index 5b0238becf26b6f5d5abecfa4cf9c6a41ef1fca0..a7bdbf45ca0995cd5947f7ac571f02af08246881 100644 (file)
@@ -21,7 +21,7 @@ import java.awt.*;
 import javax.swing.*;
 import org.altusmetrum.altoslib_14.*;
 
-import org.jfree.ui.*;
+import org.jfree.chart.ui.*;
 import org.jfree.chart.*;
 import org.jfree.chart.plot.*;
 import org.jfree.chart.axis.*;
index 37ae2e85c93bb31d8062f1025613f286c2b59fe0..3f112faed3d085f8f0d5399fe9063a8ee9f3494b 100644 (file)
@@ -25,7 +25,7 @@ import java.awt.*;
 import javax.swing.*;
 import org.altusmetrum.altoslib_14.*;
 
-import org.jfree.ui.*;
+import org.jfree.chart.ui.*;
 import org.jfree.chart.*;
 import org.jfree.chart.plot.*;
 import org.jfree.chart.axis.*;
index 63d5c0574c5a9e1aa940f8ae43ab9ce5580906b5..80669c2685dda410f042117b240c81318fc70b06 100644 (file)
@@ -25,7 +25,7 @@ import java.awt.*;
 import javax.swing.*;
 import org.altusmetrum.altoslib_14.*;
 
-import org.jfree.ui.*;
+import org.jfree.chart.ui.*;
 import org.jfree.chart.*;
 import org.jfree.chart.plot.*;
 import org.jfree.chart.axis.*;
@@ -141,7 +141,7 @@ public class AltosUITimeSeries extends AltosTimeSeries implements AltosUIGrapher
                                                                           units.graph_units()),
                                                             new java.text.DecimalFormat(time_example),
                                                             new java.text.DecimalFormat(example));
-                       renderer.setBaseToolTipGenerator(ttg);
+                       renderer.setSeriesToolTipGenerator(0, ttg);
                }
                set_data();
        }
index 10a5b494d3883477f3030aaeeaaebab22cb491d8..12bdaaa778ea7c9ae1169e12ff6cc987f1e5e510 100644 (file)
@@ -51,7 +51,9 @@ altosuilib_JAVA = \
        AltosFlashUI.java \
        AltosRomconfigUI.java \
        AltosInfoTable.java \
+       AltosFlightConfigTable.java \
        AltosFlightInfoTableModel.java \
+       AltosFlightPyroTable.java \
        AltosFlightStatsTable.java \
        AltosBTDevice.java \
        AltosBTDeviceIterator.java \
diff --git a/ao-bringup/test-easymega b/ao-bringup/test-easymega
deleted file mode 100755 (executable)
index 04dfb44..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-#!/bin/sh
-
-VERSION=2.0
-PRODUCT=EasyMega
-BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
-
-echo "$PRODUCT-v$VERSION Test Program"
-echo "Copyright 2018 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"
-           echo ""
-
-           ./test-igniters $dev --rplus=100 --rminus=27 --adcmax=4095 main drogue 3 0 1 2
-           echo""
-
-           echo "Testing baro sensor"
-           ../ao-tools/ao-test-baro/ao-test-baro --tty="$dev"
-
-           case $? in
-               0)
-                   ;;
-               *)
-                   echo "failed"
-                   exit 1
-           esac
-           echo""
-
-           FLASHSIZE=8388608
-
-           echo "Testing flash"
-           ../ao-tools/ao-test-flash/ao-test-flash --tty="$dev" "$FLASHSIZE"
-
-           case $? in
-               0)
-                   ;;
-               *)
-                   echo "failed"
-                   exit 1
-           esac
-           echo""
-
-           echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
-           ret=0
-           ;;
-    esac
-done
diff --git a/ao-bringup/test-easymega-v2.0 b/ao-bringup/test-easymega-v2.0
new file mode 100755 (executable)
index 0000000..04dfb44
--- /dev/null
@@ -0,0 +1,55 @@
+#!/bin/sh
+
+VERSION=2.0
+PRODUCT=EasyMega
+BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+
+echo "$PRODUCT-v$VERSION Test Program"
+echo "Copyright 2018 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"
+           echo ""
+
+           ./test-igniters $dev --rplus=100 --rminus=27 --adcmax=4095 main drogue 3 0 1 2
+           echo""
+
+           echo "Testing baro sensor"
+           ../ao-tools/ao-test-baro/ao-test-baro --tty="$dev"
+
+           case $? in
+               0)
+                   ;;
+               *)
+                   echo "failed"
+                   exit 1
+           esac
+           echo""
+
+           FLASHSIZE=8388608
+
+           echo "Testing flash"
+           ../ao-tools/ao-test-flash/ao-test-flash --tty="$dev" "$FLASHSIZE"
+
+           case $? in
+               0)
+                   ;;
+               *)
+                   echo "failed"
+                   exit 1
+           esac
+           echo""
+
+           echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
+           ret=0
+           ;;
+    esac
+done
diff --git a/ao-bringup/test-easymega-v3.0 b/ao-bringup/test-easymega-v3.0
new file mode 100755 (executable)
index 0000000..1d000bf
--- /dev/null
@@ -0,0 +1,55 @@
+#!/bin/sh
+
+VERSION=3.0
+PRODUCT=EasyMega
+BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+
+echo "$PRODUCT-v$VERSION Test Program"
+echo "Copyright 2024 by Bdale Garbee.  Released under GPL v3"
+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"
+           echo ""
+
+           ./test-igniters $dev --rplus=100 --rminus=27 --adcmax=4095 main drogue 3 0 1 2
+           echo""
+
+           echo "Testing baro sensor"
+           ../ao-tools/ao-test-baro/ao-test-baro --tty="$dev"
+
+           case $? in
+               0)
+                   ;;
+               *)
+                   echo "failed"
+                   exit 1
+           esac
+           echo""
+
+           FLASHSIZE=8388608
+
+           echo "Testing flash"
+           ../ao-tools/ao-test-flash/ao-test-flash --tty="$dev" "$FLASHSIZE"
+
+           case $? in
+               0)
+                   ;;
+               *)
+                   echo "failed"
+                   exit 1
+           esac
+           echo""
+
+           echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
+           ret=0
+           ;;
+    esac
+done
diff --git a/ao-bringup/test-easymini-v2.0 b/ao-bringup/test-easymini-v2.0
new file mode 100755 (executable)
index 0000000..7850b55
--- /dev/null
@@ -0,0 +1,62 @@
+#!/bin/bash
+
+VERSION=2.0
+PRODUCT=EasyMini
+BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+
+echo "$PRODUCT-v$VERSION Test Program"
+echo "Copyright 2014 by Keith Packard.  Released under GPL v2"
+echo
+echo "Expectations:"
+echo -e "\t$PRODUCT v$VERSION powered from USB"
+echo
+
+found=0
+while [ $found -eq 0 ]; do
+    (ao-list; echo END END END END) | while read product serial dev; do
+       case "$product" in
+           "$PRODUCT-v$VERSION")
+
+               found=1
+               echo -e '\e[34m'Testing $product $serial $dev'\e[39m'
+               echo ""
+               
+               ./test-igniters "$dev" drogue main
+               echo ""
+
+               echo "Testing baro sensor"
+               ../ao-tools/ao-test-baro/ao-test-baro --tty="$dev"
+
+               if [ $? -ne 0 ]; then
+                   echo -e '\e[31m'"$PRODUCT-$VERSION serial $serial failed"'\e[39m'
+                   exit 1
+               fi
+               echo""
+
+               FLASHSIZE=1048576
+
+               echo "Testing flash"
+               ../ao-tools/ao-test-flash/ao-test-flash --tty="$dev" "$FLASHSIZE"
+
+               if [ $? -ne 0 ]; then
+                   echo -e '\e[31m'"$PRODUCT-$VERSION serial $serial failed"'\e[39m'
+                   exit 1
+               fi
+
+               echo ""
+
+               echo -e '\e[32m'"$PRODUCT-v$VERSION" serial "$serial" is ready to ship'\e[39m'
+               exit 0
+               ;;
+           END)
+               exit 2
+               ;;
+       esac
+    done
+    result=$?
+    if [ $result -ne 2 ]; then
+       exit $result
+    fi
+    echo 'No device, sleeping...'
+    sleep 1
+done
diff --git a/ao-bringup/test-easytimer b/ao-bringup/test-easytimer
deleted file mode 100755 (executable)
index f93164c..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/bin/sh
-
-VERSION=1
-PRODUCT=EasyTimer
-BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
-
-echo "$PRODUCT-v$VERSION Test Program"
-echo "Copyright 2020 by Bdale Garbee.  Released under GPL v3"
-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"
-
-           ./test-igniters $dev 0 1
-           echo""
-
-           case $? in
-               0)
-                   ;;
-               *)
-                   echo "failed"
-                   exit 1
-           esac
-           echo""
-
-           echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
-           echo "\007"
-           ret=0
-           ;;
-    esac
-done
diff --git a/ao-bringup/test-easytimer-v1 b/ao-bringup/test-easytimer-v1
new file mode 100755 (executable)
index 0000000..f93164c
--- /dev/null
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+VERSION=1
+PRODUCT=EasyTimer
+BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+
+echo "$PRODUCT-v$VERSION Test Program"
+echo "Copyright 2020 by Bdale Garbee.  Released under GPL v3"
+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"
+
+           ./test-igniters $dev 0 1
+           echo""
+
+           case $? in
+               0)
+                   ;;
+               *)
+                   echo "failed"
+                   exit 1
+           esac
+           echo""
+
+           echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
+           echo "\007"
+           ret=0
+           ;;
+    esac
+done
diff --git a/ao-bringup/test-easytimer-v2 b/ao-bringup/test-easytimer-v2
new file mode 100755 (executable)
index 0000000..023f27b
--- /dev/null
@@ -0,0 +1,51 @@
+#!/bin/sh
+
+VERSION=2
+PRODUCT=EasyTimer
+BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+
+echo "$PRODUCT-v$VERSION Test Program"
+echo "Copyright 2024 by Bdale Garbee.  Released under GPL v3"
+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"
+
+           ./test-igniters $dev 0 1
+           echo""
+
+           case $? in
+               0)
+                   ;;
+               *)
+                   echo "failed"
+                   exit 1
+           esac
+           echo""
+
+
+           FLASHSIZE=1048576
+
+           echo "Testing flash"
+           ../ao-tools/ao-test-flash/ao-test-flash --tty="$dev" "$FLASHSIZE"
+
+           if [ $? -ne 0 ]; then
+               echo -e '\e[31m'"$PRODUCT-$VERSION serial $serial failed"'\e[39m'
+               exit 1
+           fi
+           echo ""
+
+
+           echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
+           echo "\007"
+           ret=0
+           ;;
+    esac
+done
diff --git a/ao-bringup/test-telegps-v4 b/ao-bringup/test-telegps-v4
new file mode 100755 (executable)
index 0000000..808c0dd
--- /dev/null
@@ -0,0 +1,53 @@
+#!/bin/sh
+
+VERSION=4.0
+PRODUCT=TeleGPS
+BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+
+echo "$PRODUCT-v$VERSION Test Program"
+echo "Copyright 2025 by Bdale Garbee.  Released under GPL v3"
+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" is ready to ship
+            echo "\007"
+           ret=0
+           ;;
+       *)
+           echo "Skipping $product $serial $dev"
+           ;;
+    esac
+done
diff --git a/ao-bringup/test-telemega-v7.0 b/ao-bringup/test-telemega-v7.0
new file mode 100755 (executable)
index 0000000..aafcdda
--- /dev/null
@@ -0,0 +1,67 @@
+#!/bin/sh
+
+VERSION=7.0
+PRODUCT=TeleMega
+BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+
+echo "$PRODUCT-v$VERSION Test Program"
+echo "Copyright 2025 by Bdale Garbee.  Released under GPL v3"
+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"
+
+           ./test-igniters $dev --rplus=100 --rminus=12 --adcmax=4095 main drogue 3 0 1 2
+           echo""
+
+           echo "Testing baro sensor"
+           ../ao-tools/ao-test-baro/ao-test-baro --tty="$dev"
+
+           case $? in
+               0)
+                   ;;
+               *)
+                   echo "failed"
+                   exit 1
+           esac
+           echo""
+
+           FLASHSIZE=8388608
+
+           echo "Testing flash"
+           ../ao-tools/ao-test-flash/ao-test-flash --tty="$dev" "$FLASHSIZE"
+
+           case $? in
+               0)
+                   ;;
+               *)
+                   echo "failed"
+                   exit 1
+           esac
+           echo""
+
+           echo "Testing GPS"
+           ../ao-tools/ao-test-gps/ao-test-gps --tty="$dev"
+
+           case $? in
+               0)
+                   ;;
+               *)
+                   echo "failed"
+                   exit 1
+           esac
+           echo""
+
+           echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
+           echo "\007"
+           ret=0
+           ;;
+    esac
+done
deleted file mode 100755 (executable)
index 64180bd3b9a3976fd41649c294f02a5063fb2bd9..0000000000000000000000000000000000000000
+++ /dev/null
@@ -1,79 +0,0 @@
-#!/bin/sh
-
-PRODUCT=EasyMega
-VERSION=2.0
-REPO=~/altusmetrumllc/Binaries
-
-if [ -x /usr/bin/ao-flash-stm ]; then
-       FLASH_STM=/usr/bin/ao-flash-stm
-else
-       echo "Can't find ao-flash-stm!  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
-
-echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
-echo "Copyright 2018 by Bdale Garbee.  Released under GPL v2"
-echo
-echo "Expectations:"
-echo "\t$PRODUCT v$VERSION"
-echo "\t\twith USB cable attached"
-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
-
-echo $FLASH_STM
-
-$FLASH_STM $REPO/loaders/easymega-v$VERSION*.elf
-
-sleep 3
-
-$USBLOAD --serial=$SERIAL $REPO/easymega-v$VERSION*.elf || exit 1
-
-sleep 5
-
-dev=`ao-list | awk '/'"$PRODUCT"'-v'"$VERSION"'/ { print $3; exit(0); }'`
-
-case "$dev" in
-/dev/tty*)
-       echo "$PRODUCT found on $dev"
-       ;;
-*)
-       echo 'No '"$PRODUCT"'-v'"$VERSION"' found'
-       exit 1
-       ;;
-esac
-
-echo 'E 0' > $dev
-
-failed=1
-while [ $failed =  1 ]; do
-    ../ao-tools/ao-cal-accel/ao-cal-accel $dev
-    failed=$?
-done
-
-echo 'E 1' > $dev
-
-./test-easymega
-
-exit $?
new file mode 120000 (symlink)
index 0000000000000000000000000000000000000000..b4661b042dd92758c69ed50d6d52a7671bb31c5d
--- /dev/null
@@ -0,0 +1 @@
+turnon_easymega_v3.0
\ No newline at end of file
diff --git a/ao-bringup/turnon_easymega_v2.0 b/ao-bringup/turnon_easymega_v2.0
new file mode 100755 (executable)
index 0000000..95b843b
--- /dev/null
@@ -0,0 +1,79 @@
+#!/bin/sh
+
+PRODUCT=EasyMega
+VERSION=2.0
+REPO=~/altusmetrumllc/Binaries
+
+if [ -x /usr/bin/ao-flash-stm ]; then
+       FLASH_STM=/usr/bin/ao-flash-stm
+else
+       echo "Can't find ao-flash-stm!  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
+
+echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2018 by Bdale Garbee.  Released under GPL v2"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION"
+echo "\t\twith USB cable attached"
+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
+
+echo $FLASH_STM
+
+$FLASH_STM $REPO/loaders/easymega-v$VERSION*.elf
+
+sleep 3
+
+$USBLOAD --serial=$SERIAL $REPO/easymega-v$VERSION*.elf || exit 1
+
+sleep 5
+
+dev=`ao-list | awk '/'"$PRODUCT"'-v'"$VERSION"'/ { print $3; exit(0); }'`
+
+case "$dev" in
+/dev/tty*)
+       echo "$PRODUCT found on $dev"
+       ;;
+*)
+       echo 'No '"$PRODUCT"'-v'"$VERSION"' found'
+       exit 1
+       ;;
+esac
+
+echo 'E 0' > $dev
+
+failed=1
+while [ $failed =  1 ]; do
+    ../ao-tools/ao-cal-accel/ao-cal-accel $dev
+    failed=$?
+done
+
+echo 'E 1' > $dev
+
+./test-easymega-v2.0
+
+exit $?
diff --git a/ao-bringup/turnon_easymega_v3.0 b/ao-bringup/turnon_easymega_v3.0
new file mode 100755 (executable)
index 0000000..59d06ba
--- /dev/null
@@ -0,0 +1,65 @@
+#!/bin/sh
+
+PRODUCT=EasyMega
+VERSION=3.0
+REPO=~/altusmetrumllc/Binaries
+
+if [ -x /usr/bin/ao-usbload ]; then
+       USBLOAD=/usr/bin/ao-usbload
+else
+       echo "Can't find ao-usbload!  Aborting."
+       exit 1
+fi
+
+echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2024 by Bdale Garbee.  Released under GPL v3"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION"
+echo "\t\twith USB cable attached"
+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
+
+$USBLOAD --serial=$SERIAL $REPO/easymega-v$VERSION*.elf || exit 1
+
+sleep 5
+
+dev=`ao-list | awk '/'"$PRODUCT"'-v'"$VERSION"'/ { print $3; exit(0); }'`
+
+case "$dev" in
+/dev/tty*)
+       echo "$PRODUCT found on $dev"
+       ;;
+*)
+       echo 'No '"$PRODUCT"'-v'"$VERSION"' found'
+       exit 1
+       ;;
+esac
+
+echo 'E 0' > $dev
+
+failed=1
+while [ $failed =  1 ]; do
+    ../ao-tools/ao-cal-accel/ao-cal-accel $dev
+    failed=$?
+done
+
+echo 'E 1' > $dev
+
+./test-easymega-v3.0
+
+exit $?
deleted file mode 100755 (executable)
index 1960c4d679d314529b58a8bcaf6b7524a46409b0..0000000000000000000000000000000000000000
+++ /dev/null
@@ -1,69 +0,0 @@
-#!/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 ../ao-tools/ao-usbload/ao-usbload ]; then
-       USBLOAD=../ao-tools/ao-usbload/ao-usbload
-elif [ -x /usr/bin/ao-usbload ]; then
-       USBLOAD=/usr/bin/ao-usbload
-else
-       echo "Can't find ao-usbload!  Aborting."
-       exit 1
-fi
-
-VERSION=3.0
-PRODUCT=EasyMini
-BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
-echo $FILE
-
-echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
-echo "Copyright 2022 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
-
-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/easymini-v3.0-altos-flash-*.elf
-ALTOS_FILE=~/altusmetrumllc/Binaries/easymini-v3.0-*.elf
-
-echo $FLASH_LPC $FLASH_FILE
-
-$FLASH_LPC $FLASH_FILE || exit 1
-
-sleep 1
-
-echo $USBLOAD $ALTOS_FILE
-
-$USBLOAD --serial=$SERIAL $ALTOS_FILE || exit 1
-
-sleep 1
-
-./test-easymini-v3.0
-
-exit $?
new file mode 120000 (symlink)
index 0000000000000000000000000000000000000000..e817720c21dde6abb7a3f35509ace07e291ad8cc
--- /dev/null
@@ -0,0 +1 @@
+turnon_easymini_v2.0
\ No newline at end of file
diff --git a/ao-bringup/turnon_easymini_v2.0 b/ao-bringup/turnon_easymini_v2.0
new file mode 100755 (executable)
index 0000000..3d883b3
--- /dev/null
@@ -0,0 +1,69 @@
+#!/bin/sh
+
+#if [ -x /usr/bin/dfu-util ]; then
+#    DFU_UTIL=/usr/bin/dfu-util
+#else
+#    echo "Can't find dfu-util! Aborting."
+#    exit 1
+#fi
+
+if [ -x ../ao-tools/ao-usbload/ao-usbload ]; then
+       USBLOAD=../ao-tools/ao-usbload/ao-usbload
+elif [ -x /usr/bin/ao-usbload ]; then
+       USBLOAD=/usr/bin/ao-usbload
+else
+       echo "Can't find ao-usbload!  Aborting."
+       exit 1
+fi
+
+VERSION=2.0
+PRODUCT=EasyMini
+BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+echo $FILE
+
+echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2024 by Bdale Garbee.  Released under GPL v2+"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION powered and connected to USB"
+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/easymini-v2.0-altos-flash-*.bin
+ALTOS_FILE=~/altusmetrumllc/Binaries/easymini-v2.0-*.elf
+
+#FLASH_FILE=../src/$BASE-v$VERSION/flash-loader/$BASE-v$VERSION-altos-flash-*.elf
+#ALTOS_FILE=../src/$BASE-v$VERSION/*.ihx
+
+#echo $DFU_UTIL -a 0 -s 0x08000000:leave -D $FLASH_FILE
+
+#$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 1
+
+./test-easymini-v2.0
+
+exit $?
diff --git a/ao-bringup/turnon_easymini_v3.0 b/ao-bringup/turnon_easymini_v3.0
new file mode 100755 (executable)
index 0000000..1960c4d
--- /dev/null
@@ -0,0 +1,69 @@
+#!/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 ../ao-tools/ao-usbload/ao-usbload ]; then
+       USBLOAD=../ao-tools/ao-usbload/ao-usbload
+elif [ -x /usr/bin/ao-usbload ]; then
+       USBLOAD=/usr/bin/ao-usbload
+else
+       echo "Can't find ao-usbload!  Aborting."
+       exit 1
+fi
+
+VERSION=3.0
+PRODUCT=EasyMini
+BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+echo $FILE
+
+echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2022 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
+
+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/easymini-v3.0-altos-flash-*.elf
+ALTOS_FILE=~/altusmetrumllc/Binaries/easymini-v3.0-*.elf
+
+echo $FLASH_LPC $FLASH_FILE
+
+$FLASH_LPC $FLASH_FILE || exit 1
+
+sleep 1
+
+echo $USBLOAD $ALTOS_FILE
+
+$USBLOAD --serial=$SERIAL $ALTOS_FILE || exit 1
+
+sleep 1
+
+./test-easymini-v3.0
+
+exit $?
index 4678430d1498fcdff9b22afd54b64b0c5dfdea02..8528a7e726096f894e796def7e795074874984d8 100755 (executable)
@@ -46,7 +46,6 @@ case $# in
        exit 1;
        ;;
 esac
-otootor
 #
 # Use released versions of everything
 #
index 8953f90045f02017b4063af8922b89f14385d92d..da78cbb6190e59cba34198b28110834eaccffddf 100755 (executable)
@@ -1,11 +1,7 @@
 #!/bin/sh
 
-if [ -x /usr/bin/ao-flash-stm ]; then
-       FLASH_STM=/usr/bin/ao-flash-stm
-else
-       echo "Can't find ao-flash-stm!  Aborting."
-       exit 1
-fi
+# EasyTimer v2 all arrive from the assembler with 
+# the bootloader already flashed. 
 
 if [ -x /usr/bin/ao-usbload ]; then
        USBLOAD=/usr/bin/ao-usbload
@@ -14,16 +10,15 @@ else
        exit 1
 fi
 
-VERSION=1
+VERSION=2
 REPO=~/altusmetrumllc/Binaries
 PRODUCT=EasyTimer
 
 echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
-echo "Copyright 2020 by Bdale Garbee.  Released under GPL v3"
+echo "Copyright 2024 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
 
 case $# in
@@ -41,12 +36,6 @@ case $# in
        ;;
 esac
 
-echo $FLASH_STM
-
-$FLASH_STM $REPO/loaders/easytimer-v$VERSION*.elf 
-
-sleep 3
-
 $USBLOAD --serial=$SERIAL --force $REPO/easytimer-v$VERSION*.elf || exit 1
 
 sleep 5
@@ -73,6 +62,6 @@ done
 
 echo 'E 1' > $dev
 
-./test-easytimer
+./test-easytimer-v2
 
 exit $?
diff --git a/ao-bringup/turnon_easytimer_v1 b/ao-bringup/turnon_easytimer_v1
new file mode 100755 (executable)
index 0000000..8953f90
--- /dev/null
@@ -0,0 +1,78 @@
+#!/bin/sh
+
+if [ -x /usr/bin/ao-flash-stm ]; then
+       FLASH_STM=/usr/bin/ao-flash-stm
+else
+       echo "Can't find ao-flash-stm!  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
+
+VERSION=1
+REPO=~/altusmetrumllc/Binaries
+PRODUCT=EasyTimer
+
+echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2020 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
+
+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
+
+echo $FLASH_STM
+
+$FLASH_STM $REPO/loaders/easytimer-v$VERSION*.elf 
+
+sleep 3
+
+$USBLOAD --serial=$SERIAL --force $REPO/easytimer-v$VERSION*.elf || exit 1
+
+sleep 5
+
+dev=`ao-list | awk '/EasyTimer-v'"$VERSION"'/ { print $3; exit(0); }'`
+
+case "$dev" in
+/dev/tty*)
+       echo "EasyTimer found on $dev"
+       ;;
+*)
+       echo 'No EasyTimer-v'"$VERSION"' found'
+       exit 1
+       ;;
+esac
+
+echo 'E 0' > $dev
+
+failed=1
+while [ $failed = 1 ]; do
+    ../ao-tools/ao-cal-accel/ao-cal-accel $dev
+    failed=$?
+done
+
+echo 'E 1' > $dev
+
+./test-easytimer
+
+exit $?
deleted file mode 100755 (executable)
index af72bab869575ed650f26a74ec633356c9bcaf2b..0000000000000000000000000000000000000000
+++ /dev/null
@@ -1,96 +0,0 @@
-#!/bin/sh
-
-if [ -x /usr/bin/dfu-util ]; then
-    DFU_UTIL=/usr/bin/dfu-util
-else
-    echo "Can't find dfu-util! 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
-
-VERSION=4.0
-REPO=~/altusmetrumllc/Binaries
-PRODUCT=TeleBT
-
-echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
-echo "Copyright 2017 by Bdale Garbee.  Released under GPL v3+"
-echo
-echo "Expectations:"
-echo "\t$PRODUCT v$VERSION attached by USB"
-echo "\t\twith coax from UHF to frequency counter"
-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
-
-FLASH_FILE=$REPO/loaders/telebt-v$VERSION-altos-flash-*.bin
-ALTOS_FILE=$REPO/telebt-v$VERSION-*.elf
-
-$DFU_UTIL -a 0 -s 0x08000000:leave -D $FLASH_FILE
-
-sleep 2
-
-$USBLOAD --serial=$SERIAL $ALTOS_FILE || exit 1
-
-sleep 3
-
-dev=`ao-list | awk '/'"$PRODUCT"'-v'"$VERSION"'/ { print $3; exit(0); }'`
-
-case "$dev" in
-/dev/tty*)
-       echo "$PRODUCT found on $dev"
-       ;;
-*)
-       echo 'No '"$PRODUCT"'-v'"$VERSION"' found'
-       exit 1
-       ;;
-esac
-
-CALFILE=cal-$SERIAL.txt
-
-../ao-tools/ao-cal-freq/ao-cal-freq --nosave --output=$CALFILE --tty=$dev
-
-CAL_VALUE=`cat $CALFILE`
-echo $SERIAL","$CAL_VALUE >> cal_values
-echo "Reflashing with calibration: $CAL_VALUE"
-$USBLOAD --cal=$CAL_VALUE --tty=$dev $ALTOS_FILE || exit 1
-
-echo -n "checking BlueTooth functionality... "
-btdev=`hcitool scan | awk -F \- '/TeleBT/ { print $2 }'`
-if [ "$btdev" = "$SERIAL" ]; then
-       echo "working!"
-else
-       echo "device not found"
-       exit 1
-fi
-
-echo -n "checking BTLE functionality... "
-btdev=`sudo timeout -s SIGINT 5s hcitool lescan | awk -F \- '/TeleBT/ { print $2 }' | head -n 1`
-if [ "$btdev" = "$SERIAL" ]; then
-       echo "working!"
-else
-       echo "device not found"
-       exit 1
-fi
-
-echo "$PRODUCT-v$VERSION $SERIAL is ready to ship"
-
-exit $?
new file mode 120000 (symlink)
index 0000000000000000000000000000000000000000..b5409df9f728e8faeb091d177b2db3d6a4d8cfe2
--- /dev/null
@@ -0,0 +1 @@
+turnon_telebt_v4d
\ No newline at end of file
diff --git a/ao-bringup/turnon_telebt_v4 b/ao-bringup/turnon_telebt_v4
new file mode 100755 (executable)
index 0000000..af72bab
--- /dev/null
@@ -0,0 +1,96 @@
+#!/bin/sh
+
+if [ -x /usr/bin/dfu-util ]; then
+    DFU_UTIL=/usr/bin/dfu-util
+else
+    echo "Can't find dfu-util! 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
+
+VERSION=4.0
+REPO=~/altusmetrumllc/Binaries
+PRODUCT=TeleBT
+
+echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2017 by Bdale Garbee.  Released under GPL v3+"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION attached by USB"
+echo "\t\twith coax from UHF to frequency counter"
+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
+
+FLASH_FILE=$REPO/loaders/telebt-v$VERSION-altos-flash-*.bin
+ALTOS_FILE=$REPO/telebt-v$VERSION-*.elf
+
+$DFU_UTIL -a 0 -s 0x08000000:leave -D $FLASH_FILE
+
+sleep 2
+
+$USBLOAD --serial=$SERIAL $ALTOS_FILE || exit 1
+
+sleep 3
+
+dev=`ao-list | awk '/'"$PRODUCT"'-v'"$VERSION"'/ { print $3; exit(0); }'`
+
+case "$dev" in
+/dev/tty*)
+       echo "$PRODUCT found on $dev"
+       ;;
+*)
+       echo 'No '"$PRODUCT"'-v'"$VERSION"' found'
+       exit 1
+       ;;
+esac
+
+CALFILE=cal-$SERIAL.txt
+
+../ao-tools/ao-cal-freq/ao-cal-freq --nosave --output=$CALFILE --tty=$dev
+
+CAL_VALUE=`cat $CALFILE`
+echo $SERIAL","$CAL_VALUE >> cal_values
+echo "Reflashing with calibration: $CAL_VALUE"
+$USBLOAD --cal=$CAL_VALUE --tty=$dev $ALTOS_FILE || exit 1
+
+echo -n "checking BlueTooth functionality... "
+btdev=`hcitool scan | awk -F \- '/TeleBT/ { print $2 }'`
+if [ "$btdev" = "$SERIAL" ]; then
+       echo "working!"
+else
+       echo "device not found"
+       exit 1
+fi
+
+echo -n "checking BTLE functionality... "
+btdev=`sudo timeout -s SIGINT 5s hcitool lescan | awk -F \- '/TeleBT/ { print $2 }' | head -n 1`
+if [ "$btdev" = "$SERIAL" ]; then
+       echo "working!"
+else
+       echo "device not found"
+       exit 1
+fi
+
+echo "$PRODUCT-v$VERSION $SERIAL is ready to ship"
+
+exit $?
diff --git a/ao-bringup/turnon_telebt_v4d b/ao-bringup/turnon_telebt_v4d
new file mode 100755 (executable)
index 0000000..7f09b57
--- /dev/null
@@ -0,0 +1,87 @@
+#!/bin/sh
+#
+# the difference with v4.0d is that the bootloader should already
+# have been flashed at Seeed, so don't try to re-flash that part
+
+if [ -x /usr/bin/ao-usbload ]; then
+       USBLOAD=/usr/bin/ao-usbload
+else
+       echo "Can't find ao-usbload!  Aborting."
+       exit 1
+fi
+
+VERSION=4.0
+REPO=~/altusmetrumllc/Binaries
+PRODUCT=TeleBT
+
+echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2025 by Bdale Garbee.  Released under GPL v3"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION attached by USB"
+echo "\t\twith coax from UHF to frequency counter"
+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
+
+ALTOS_FILE=$REPO/telebt-v$VERSION-*.elf
+
+$USBLOAD --serial=$SERIAL $ALTOS_FILE || exit 1
+
+sleep 3
+
+dev=`ao-list | awk '/'"$PRODUCT"'-v'"$VERSION"'/ { print $3; exit(0); }'`
+
+case "$dev" in
+/dev/tty*)
+       echo "$PRODUCT found on $dev"
+       ;;
+*)
+       echo 'No '"$PRODUCT"'-v'"$VERSION"' found'
+       exit 1
+       ;;
+esac
+
+CALFILE=cal-$SERIAL.txt
+
+../ao-tools/ao-cal-freq/ao-cal-freq --nosave --output=$CALFILE --tty=$dev
+
+CAL_VALUE=`cat $CALFILE`
+echo $SERIAL","$CAL_VALUE >> cal_values
+echo "Reflashing with calibration: $CAL_VALUE"
+$USBLOAD --cal=$CAL_VALUE --tty=$dev $ALTOS_FILE || exit 1
+
+echo -n "checking BlueTooth functionality... "
+btdev=`hcitool scan | awk -F \- '/TeleBT/ { print $2 }'`
+if [ "$btdev" = "$SERIAL" ]; then
+       echo "working!"
+else
+       echo "device not found"
+       exit 1
+fi
+
+echo -n "checking BTLE functionality... "
+btdev=`sudo timeout -s SIGINT 5s hcitool lescan | awk -F \- '/TeleBT/ { print $2 }' | head -n 1`
+if [ "$btdev" = "$SERIAL" ]; then
+       echo "working!"
+else
+       echo "device not found"
+       exit 1
+fi
+
+echo "$PRODUCT-v$VERSION $SERIAL is ready to ship"
+
+exit $?
deleted file mode 100755 (executable)
index 45f8fcf5a847d14842120198cb8cf0c651edb555..0000000000000000000000000000000000000000
+++ /dev/null
@@ -1,84 +0,0 @@
-#!/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=3.0
-BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
-echo $FILE
-
-echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
-echo "Copyright 2023 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
-
-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-v3.0-altos-flash-*.elf
-ALTOS_FILE=~/altusmetrumllc/Binaries/telegps-v3.0-*.elf
-
-echo $FLASH_LPC $FLASH_FILE
-
-$FLASH_LPC $FLASH_FILE || exit 1
-
-sleep 1
-
-echo $USBLOAD $ALTOS_FILE
-
-$USBLOAD --serial=$SERIAL $ALTOS_FILE || exit 1
-
-sleep 1
-
-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
-
-CALFILE=cal-$SERIAL.txt
-../ao-tools/ao-cal-freq/ao-cal-freq --output=$CALFILE --tty=$dev
-CAL_VALUE=`cat $CALFILE`
-echo $SERIAL","$CAL_VALUE >> cal_values
-
-./test-telegps-v3
-
-exit $?
new file mode 120000 (symlink)
index 0000000000000000000000000000000000000000..ff02e210985f54230ca93cfe1b0b4680543715ef
--- /dev/null
@@ -0,0 +1 @@
+turnon_telegps_v4
\ No newline at end of file
diff --git a/ao-bringup/turnon_telegps_v3 b/ao-bringup/turnon_telegps_v3
new file mode 100755 (executable)
index 0000000..45f8fcf
--- /dev/null
@@ -0,0 +1,84 @@
+#!/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=3.0
+BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+echo $FILE
+
+echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2023 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
+
+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-v3.0-altos-flash-*.elf
+ALTOS_FILE=~/altusmetrumllc/Binaries/telegps-v3.0-*.elf
+
+echo $FLASH_LPC $FLASH_FILE
+
+$FLASH_LPC $FLASH_FILE || exit 1
+
+sleep 1
+
+echo $USBLOAD $ALTOS_FILE
+
+$USBLOAD --serial=$SERIAL $ALTOS_FILE || exit 1
+
+sleep 1
+
+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
+
+CALFILE=cal-$SERIAL.txt
+../ao-tools/ao-cal-freq/ao-cal-freq --output=$CALFILE --tty=$dev
+CAL_VALUE=`cat $CALFILE`
+echo $SERIAL","$CAL_VALUE >> cal_values
+
+./test-telegps-v3
+
+exit $?
diff --git a/ao-bringup/turnon_telegps_v4 b/ao-bringup/turnon_telegps_v4
new file mode 100755 (executable)
index 0000000..87ea145
--- /dev/null
@@ -0,0 +1,67 @@
+#!/bin/sh
+
+if [ -x /usr/bin/ao-usbload ]; then
+       USBLOAD=/usr/bin/ao-usbload
+else
+       echo "Can't find ao-usbload!  Aborting."
+       exit 1
+fi
+
+VERSION=4.0
+REPO=~/altusmetrumllc/Binaries
+PRODUCT=TeleGPS
+
+echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2025 by Bdale Garbee.  Released under GPL v3"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION powered from USB"
+echo "\t\twith coax from UHF to frequency counter"
+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
+#
+ALTOS_FILE=$REPO/telegps-v$VERSION-*.elf
+
+echo $USBLOAD $ALTOS_FILE
+
+$USBLOAD --serial=$SERIAL $ALTOS_FILE || exit 1
+
+sleep 1
+
+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
+
+CALFILE=cal-$SERIAL.txt
+../ao-tools/ao-cal-freq/ao-cal-freq --output=$CALFILE --tty=$dev
+CAL_VALUE=`cat $CALFILE`
+echo $SERIAL","$CAL_VALUE >> cal_values
+
+./test-telegps-v4
+
+exit $?
deleted file mode 100755 (executable)
index dafa2131a64aa0b6d36820d1b66ab1c22e5ab180..0000000000000000000000000000000000000000
+++ /dev/null
@@ -1,76 +0,0 @@
-#!/bin/sh
-
-if [ -x /usr/bin/ao-flash-stm ]; then
-       FLASH_STM=/usr/bin/ao-flash-stm
-else
-       echo "Can't find ao-flash-stm!  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
-
-VERSION=2.0
-REPO=~/altusmetrumllc/Binaries
-PRODUCT=TeleLCO
-
-echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
-echo "Copyright 2018 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\twith coax from UHF to frequency counter"
-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
-
-echo $FLASH_STM
-
-$FLASH_STM $REPO/loaders/telelco-v$VERSION*.elf 
-
-sleep 3
-
-$USBLOAD --serial=$SERIAL --force $REPO/telelco-v$VERSION*.elf || exit 1
-
-sleep 5
-
-dev=`ao-list | awk '/'"$PRODUCT-v$VERSION"'/ { print $3; exit(0); }'`
-
-case "$dev" in
-/dev/tty*)
-       echo "$PRODUCT"' found on $dev'
-       ;;
-*)
-       echo 'No '"$PRODUCT-v$VERSION"' found'
-       exit 1
-       ;;
-esac
-
-echo 'E 0' > $dev
-
-SERIAL=$SERIAL ./cal-freq $dev
-
-echo 'E 1' > $dev
-
-echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
-echo "\007"
-
-exit $?
new file mode 120000 (symlink)
index 0000000000000000000000000000000000000000..b5c4ae5615b12f41cf11ec23a79d0d1927e14873
--- /dev/null
@@ -0,0 +1 @@
+turnon_telelco_v3
\ No newline at end of file
diff --git a/ao-bringup/turnon_telelco_v2 b/ao-bringup/turnon_telelco_v2
new file mode 100755 (executable)
index 0000000..dafa213
--- /dev/null
@@ -0,0 +1,76 @@
+#!/bin/sh
+
+if [ -x /usr/bin/ao-flash-stm ]; then
+       FLASH_STM=/usr/bin/ao-flash-stm
+else
+       echo "Can't find ao-flash-stm!  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
+
+VERSION=2.0
+REPO=~/altusmetrumllc/Binaries
+PRODUCT=TeleLCO
+
+echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2018 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\twith coax from UHF to frequency counter"
+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
+
+echo $FLASH_STM
+
+$FLASH_STM $REPO/loaders/telelco-v$VERSION*.elf 
+
+sleep 3
+
+$USBLOAD --serial=$SERIAL --force $REPO/telelco-v$VERSION*.elf || exit 1
+
+sleep 5
+
+dev=`ao-list | awk '/'"$PRODUCT-v$VERSION"'/ { print $3; exit(0); }'`
+
+case "$dev" in
+/dev/tty*)
+       echo "$PRODUCT"' found on $dev'
+       ;;
+*)
+       echo 'No '"$PRODUCT-v$VERSION"' found'
+       exit 1
+       ;;
+esac
+
+echo 'E 0' > $dev
+
+SERIAL=$SERIAL ./cal-freq $dev
+
+echo 'E 1' > $dev
+
+echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
+echo "\007"
+
+exit $?
diff --git a/ao-bringup/turnon_telelco_v3 b/ao-bringup/turnon_telelco_v3
new file mode 100755 (executable)
index 0000000..ac92061
--- /dev/null
@@ -0,0 +1,76 @@
+#!/bin/sh
+
+if [ -x /usr/bin/ao-flash-stm ]; then
+       FLASH_STM=/usr/bin/ao-flash-stm32f1
+else
+       echo "Can't find ao-flash-stm!  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
+
+VERSION=3.0
+REPO=~/altusmetrumllc/Binaries
+PRODUCT=TeleLCO
+
+echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2024 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\twith coax from UHF to frequency counter"
+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
+
+echo $FLASH_STM
+
+$FLASH_STM $REPO/loaders/telelco-v$VERSION*.elf 
+
+sleep 3
+
+$USBLOAD --serial=$SERIAL --force $REPO/telelco-v$VERSION*.elf || exit 1
+
+sleep 5
+
+dev=`ao-list | awk '/'"$PRODUCT-v$VERSION"'/ { print $3; exit(0); }'`
+
+case "$dev" in
+/dev/tty*)
+       echo "$PRODUCT"' found on $dev'
+       ;;
+*)
+       echo 'No '"$PRODUCT-v$VERSION"' found'
+       exit 1
+       ;;
+esac
+
+echo 'E 0' > $dev
+
+SERIAL=$SERIAL ./cal-freq $dev
+
+echo 'E 1' > $dev
+
+echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
+echo "\007"
+
+exit $?
deleted file mode 100755 (executable)
index b433133b6d5911842ab25e57d37c05c94f103011..0000000000000000000000000000000000000000
+++ /dev/null
@@ -1,81 +0,0 @@
-#!/bin/sh
-
-if [ -x /usr/bin/ao-flash-stm ]; then
-       FLASH_STM=/usr/bin/ao-flash-stm
-else
-       echo "Can't find ao-flash-stm!  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
-
-VERSION=6.0
-REPO=~/altusmetrumllc/Binaries
-PRODUCT=TeleMega
-
-echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
-echo "Copyright 2023 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\twith coax from UHF to frequency counter"
-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
-
-echo $FLASH_STM
-
-$FLASH_STM $REPO/loaders/telemega-v$VERSION*.elf 
-
-sleep 3
-
-$USBLOAD --serial=$SERIAL --force $REPO/telemega-v$VERSION*.elf || exit 1
-
-sleep 5
-
-dev=`ao-list | awk '/TeleMega-v'"$VERSION"'/ { print $3; exit(0); }'`
-
-case "$dev" in
-/dev/tty*)
-       echo "TeleMega found on $dev"
-       ;;
-*)
-       echo 'No TeleMega-v'"$VERSION"' found'
-       exit 1
-       ;;
-esac
-
-echo 'E 0' > $dev
-
-SERIAL=$SERIAL ./cal-freq $dev
-
-failed=1
-while [ $failed = 1 ]; do
-    ../ao-tools/ao-cal-accel/ao-cal-accel $dev
-    failed=$?
-done
-
-echo 'E 1' > $dev
-
-./test-telemega-v6.0
-
-exit $?
new file mode 120000 (symlink)
index 0000000000000000000000000000000000000000..40c58fc81cbf68dfd34335e2de5ae59a0db5dd37
--- /dev/null
@@ -0,0 +1 @@
+turnon_telemega_v7.0
\ No newline at end of file
diff --git a/ao-bringup/turnon_telemega_v6.0 b/ao-bringup/turnon_telemega_v6.0
new file mode 100755 (executable)
index 0000000..b433133
--- /dev/null
@@ -0,0 +1,81 @@
+#!/bin/sh
+
+if [ -x /usr/bin/ao-flash-stm ]; then
+       FLASH_STM=/usr/bin/ao-flash-stm
+else
+       echo "Can't find ao-flash-stm!  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
+
+VERSION=6.0
+REPO=~/altusmetrumllc/Binaries
+PRODUCT=TeleMega
+
+echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2023 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\twith coax from UHF to frequency counter"
+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
+
+echo $FLASH_STM
+
+$FLASH_STM $REPO/loaders/telemega-v$VERSION*.elf 
+
+sleep 3
+
+$USBLOAD --serial=$SERIAL --force $REPO/telemega-v$VERSION*.elf || exit 1
+
+sleep 5
+
+dev=`ao-list | awk '/TeleMega-v'"$VERSION"'/ { print $3; exit(0); }'`
+
+case "$dev" in
+/dev/tty*)
+       echo "TeleMega found on $dev"
+       ;;
+*)
+       echo 'No TeleMega-v'"$VERSION"' found'
+       exit 1
+       ;;
+esac
+
+echo 'E 0' > $dev
+
+SERIAL=$SERIAL ./cal-freq $dev
+
+failed=1
+while [ $failed = 1 ]; do
+    ../ao-tools/ao-cal-accel/ao-cal-accel $dev
+    failed=$?
+done
+
+echo 'E 1' > $dev
+
+./test-telemega-v6.0
+
+exit $?
diff --git a/ao-bringup/turnon_telemega_v7.0 b/ao-bringup/turnon_telemega_v7.0
new file mode 100755 (executable)
index 0000000..9b1dab9
--- /dev/null
@@ -0,0 +1,69 @@
+#!/bin/sh
+
+if [ -x /usr/bin/ao-usbload ]; then
+       USBLOAD=/usr/bin/ao-usbload
+else
+       echo "Can't find ao-usbload!  Aborting."
+       exit 1
+fi
+
+VERSION=7.0
+REPO=~/altusmetrumllc/Binaries
+PRODUCT=TeleMega
+
+echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2025 by Bdale Garbee.  Released under GPL v3"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION powered from USB"
+echo "\t\twith coax from UHF to frequency counter"
+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
+
+# product ships from SMT assembler with bootloader already flashed
+
+$USBLOAD --serial=$SERIAL --force $REPO/telemega-v$VERSION*.elf || exit 1
+
+sleep 5
+
+dev=`ao-list | awk '/TeleMega-v'"$VERSION"'/ { print $3; exit(0); }'`
+
+case "$dev" in
+/dev/tty*)
+       echo "TeleMega found on $dev"
+       ;;
+*)
+       echo 'No TeleMega-v'"$VERSION"' found'
+       exit 1
+       ;;
+esac
+
+echo 'E 0' > $dev
+
+SERIAL=$SERIAL ./cal-freq $dev
+
+failed=1
+while [ $failed = 1 ]; do
+    ../ao-tools/ao-cal-accel/ao-cal-accel $dev
+    failed=$?
+done
+
+echo 'E 1' > $dev
+
+./test-telemega-v7.0
+
+exit $?
index 671e4ba53925b9e6f05a9c398c45a22fe855da57..1272efecc37fea2a3528e7eb15d85cc4a24df1d1 100644 (file)
@@ -80,7 +80,7 @@ static struct flash *
 flash(struct cc_usb *usb)
 {
        struct flash    *head = NULL, **tail = &head;
-       cc_usb_printf(usb, "c s\nv\n");
+       cc_usb_printf(usb, "c s\nA\nv\n");
        for (;;) {
                char    line[512];
                struct flash    *b;
@@ -125,6 +125,7 @@ static int
 do_cal(struct cc_usb *usb) {
        struct flash    *b;
        char    **accel;
+       char    **sensor;
        char    line[1024];
        int     l = 0;
        int     running = 0;
@@ -172,6 +173,35 @@ do_cal(struct cc_usb *usb) {
        printf ("Accel cal +1g: %s -1g: %s\n",
                accel[3], accel[5]);
 
+       sensor = find_flash(b, "ADXL375");
+
+       if (sensor) {
+               char    *plus_end = NULL, *minus_end = NULL;
+               long    accel_plus = strtol(accel[3], &plus_end, 10);
+               long    accel_minus = strtol(accel[5], &minus_end, 10);
+               double  one_g;
+
+               if (plus_end == NULL || plus_end == accel[3]) {
+                       printf("can't extract plus value from %s\n", accel[3]);
+                       return 0;
+               }
+
+               if (minus_end == NULL || minus_end == accel[5]) {
+                       printf("can't extract minus value from %s\n", accel[5]);
+                       return 0;
+               }
+               one_g = (accel_minus - accel_plus) / 2.0;
+               if (one_g < 0)
+                       one_g = -one_g;
+
+               if (one_g < 18 || 23 < one_g) {
+                       printf("Device out of spec. LSB/g is %g. Should be >= 18.4 and <= 22.6\n", one_g);
+                       return 0;
+               }
+
+               printf("Device sensitivity: %g LSB/g\n", one_g);
+       }
+
        printf ("Saving..."); fflush(stdout);
        cc_usb_printf (usb, "c w\n");
        cc_usb_sync(usb);
index 9e3db4945f7ec483aab787b6db737864637048c7..55424fe988c2041f694b5d75f7fef59cabbcb0fe 100644 (file)
@@ -18,13 +18,13 @@ dnl
 dnl Process this file with autoconf to create configure.
 
 AC_PREREQ(2.57)
-AC_INIT([altos], 1.9.17)
+AC_INIT([altos], 1.9.21.1)
 ANDROID_VERSION=37
 AC_CONFIG_SRCDIR([src/kernel/ao.h])
 AM_INIT_AUTOMAKE([foreign dist-bzip2])
 AM_MAINTAINER_MODE
 
-RELEASE_DATE=2023-08-30
+RELEASE_DATE=2025-06-27
 AC_SUBST(RELEASE_DATE)
 
 DOC_DATE=`LC_ALL=C date -d $RELEASE_DATE +'%d %b %Y'`
@@ -74,7 +74,7 @@ AC_ARG_WITH(jvm, AS_HELP_STRING([--with-jvm=PATH],
 
 if test "x$JVM" = "xauto"; then
        AC_MSG_CHECKING([JVM])
-       for jvm in default-java java-6-openjdk java-7-openjdk java-8-openjdk java-9-openjdk java-10-openjdk java-11-openjdk java-12-openjdk java-13-openjdk java-6-sun java-8-openjdk-amd64; do
+       for jvm in default-java java-8-openjdk java-9-openjdk java-10-openjdk java-11-openjdk java-12-openjdk java-13-openjdk java-8-openjdk-amd64; do
                if test "x$JVM" = "xauto"; then
                        INCLUDE="/usr/lib/jvm/$jvm/include"
                        if test -f "$INCLUDE"/jni.h; then
@@ -88,9 +88,9 @@ if test "x$JVM" = "xauto"; then
        AC_MSG_RESULT([$JVM])
 fi
 
-AC_ARG_WITH(java-version, AS_HELP_STRING([--with-java-version=7],
-                                        [Set java language compatibility version (default is 7)]),
-          [JAVA_VERSION=$withval], [JAVA_VERSION=7])
+AC_ARG_WITH(java-version, AS_HELP_STRING([--with-java-version=8],
+                                        [Set java language compatibility version (default is 8)]),
+          [JAVA_VERSION=$withval], [JAVA_VERSION=8])
 
 JAVAC="$JVM"/bin/javac
 JAVA="$JVM"/bin/java
index f0d8cfb629d7ede77222bb2aea02b1ed85e6ba1c..b1fd4ceff869eb16b5c112a2f6efcec6b12ff60b 100644 (file)
@@ -17,6 +17,11 @@ FAKETIME=TZ=UTC faketime -f '$(RELEASE_DATE) 00:00:00 i0'
 endif
 
 RELNOTES_INC=\
+       release-notes-1.9.22.inc \
+       release-notes-1.9.21.inc \
+       release-notes-1.9.20.inc \
+       release-notes-1.9.19.inc \
+       release-notes-1.9.18.inc \
        release-notes-1.9.17.inc \
        release-notes-1.9.16.inc \
        release-notes-1.9.15.inc \
@@ -235,6 +240,7 @@ EASYMINI_ADOC_FILES=$(EASYMINI_TXT_FILES:.txt=.adoc) $(EASYMINI_INC_FILES:.inc=.
 OUTLINE_TXT_FILES=\
        easymega-outline.txt \
        easymini-outline.txt \
+       micropeak-outline.txt \
        telemega-outline.txt \
        telemetrum-outline.txt \
        telemini-v1-outline.txt \
@@ -251,6 +257,7 @@ SVG=\
        telemetrum.svg \
        telemini-v1.svg \
        telemini-v3.svg \
+       micropeak.svg \
        easymega.svg
 
 RELNOTES_HTML=$(RELNOTES_INC:.inc=.html)
@@ -323,7 +330,7 @@ ATTRIBUTES=--attribute="revdate=$(DOC_DATE)" --attribute="version=$(VERSION)"
        asciidoctor $(ATTRIBUTES) -b html5 $*.adoc
 
 .adoc.pdf:
-       asciidoctor-pdf $(ATTRIBUTES) -a optimize $*.adoc
+       asciidoctor-pdf $(ATTRIBUTES) --attribute="pdf-version=1.6" -a optimize $*.adoc
 
 all:   $(HTML) $(PDF)
 
@@ -345,6 +352,8 @@ telemini-v1-outline.pdf: telemini-v1-outline.txt telemini-v1.svg
 
 telemini-v3-outline.pdf: telemini-v3-outline.txt telemini-v3.svg
 
+micropeak-outline.pdf: micropeak-outline.txt micropeak.svg
+
 install:       all
 
 WEB_ROOT=/home/bdale/web/
index 14e5634bb95946ba141ade05d9f88613ea862677..031a3237b04c8fc21bfad9392affcf8981e103a9 100644 (file)
@@ -54,7 +54,7 @@ footer:
     left:
       content: '{page-number}'
     right:
-      content: '© 2023 Bdale Garbee and Keith Packard. Creative Commons ShareAlike 3.0 License'
+      content: '© 2025 Bdale Garbee and Keith Packard. Creative Commons ShareAlike 3.0 License'
   verso:
     left:
       content: $footer_recto_right_content
index cb9ef4e2f5f59aab6d248147e27f9b1bb32ef5c4..6061252308a82579d55e07c1f178be85ddfd70f5 100644 (file)
@@ -5,7 +5,7 @@ Keith Packard <keithp@keithp.com>; Bdale Garbee <bdale@gag.com>; Bob Finch; Anth
 :revdate: 1 Jan 1970
 :icons:
 :icontype: svg
-:copyright: Bdale Garbee and Keith Packard 2023
+:copyright: Bdale Garbee and Keith Packard 2025
 :doctype: book
 :numbered:
 :stylesheet: am.css
index fca8e9a06da59ea0b9bf9036f01f6c260dcaa3c1..1aadccb5d1837b62e1d3ac17e354b22813092af0 100644 (file)
@@ -1,5 +1,29 @@
 [appendix]
 == Release Notes
+       :leveloffset: 2
+       include::release-notes-1.9.22.adoc[]
+
+       <<<<
+       :leveloffset: 2
+       include::release-notes-1.9.21.adoc[]
+
+       <<<<
+       :leveloffset: 2
+       include::release-notes-1.9.20.adoc[]
+
+       <<<<
+       :leveloffset: 2
+       include::release-notes-1.9.19.adoc[]
+
+       <<<<
+       :leveloffset: 2
+       include::release-notes-1.9.18.adoc[]
+
+       <<<<
+       :leveloffset: 2
+       include::release-notes-1.9.17.adoc[]
+
+       <<<<
        :leveloffset: 2
        include::release-notes-1.9.16.adoc[]
 
index 3cacba86e292d6387a2f8972014fe1b1f3244721..029b827b1465ed1fb0af44253681e7afccbc2c5b 100644 (file)
@@ -7,7 +7,7 @@ endif::[]
 [license]
 == License
 
-Copyright © 2023 Bdale Garbee and Keith Packard
+Copyright © 2025 Bdale Garbee and Keith Packard
 
 This document is released under the terms of the link:http://creativecommons.org/licenses/by-sa/3.0/[Creative Commons ShareAlike 3.0 License]
 
index a95247a2ff81c1723ec1170e086418329770e3dc..12615cdc7ab89cdd19573b5cef21e2e6a553e5c9 100644 (file)
@@ -14,7 +14,7 @@
        aren't answered in this manual, or just need a little help figuring
        things out, we strongly suggest joining the Altus Metrum user email
        list, which you can do by visiting 
-       https://lists.gag.com/mailman/listinfo/altusmetrum.  There's a lot
+       https://groups.io/g/altusmetrum.  There's a lot
        of useful information in the mailing list archives!
 
        The first device created for our community was TeleMetrum, a dual
diff --git a/doc/micropeak-outline.txt b/doc/micropeak-outline.txt
new file mode 100644 (file)
index 0000000..4f18180
--- /dev/null
@@ -0,0 +1,14 @@
+:notitle:
+:doctype: article
+
+== MicroPeak Outline and Hole Pattern
+
+       This image, when printed, provides a precise template for the
+       mounting holes in MicroPeak. MicroPeak has overall dimensions
+       of 0.700 x 0.560 inches (17.78mm x 14.224mm), and the 0.098
+       inch (2.5mm) mounting holes are 0.075 inches (1.905mm) from
+       the board edges.  That means they are in a rectangle measuring
+       0.550 x 0.410 inches (13.97mm x 10.414mm), sized for use with
+       2-56 or M2.5 screws.
+
+       image::micropeak.svg[align="center"]
diff --git a/doc/micropeak.svg b/doc/micropeak.svg
new file mode 100644 (file)
index 0000000..00507c8
--- /dev/null
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   width="1.25in"
+   height="1in"
+   viewBox="0 0 120 106"
+   preserveaspectratio="none"
+   id="svg2"
+   version="1.1"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <defs
+     id="defs27" />
+  <g
+     transform="translate(25,25)"
+     style="fill:none;stroke:#000000;stroke-width:1;stroke-linejoin:miter;font-size:24"
+     id="g22">
+    <!-- outline -->
+    <rect
+       width="70"
+       height="56"
+       x="0"
+       y="0"
+       id="rect2" />
+    <!-- holes -->
+    <path
+       d="M7.5,7.5 m-4.9,0 a4.9,4.9,0,1,0,9.8,0 a4.9,4.9,0,1,0,-9.8,0 l9.8,0 m-4.9,-4.9 l0,9.8"
+       id="path4" />
+    <path
+       d="M62.5,7.5 m-4.9,0 a4.9,4.9,0,1,0,9.8,0 a4.9,4.9,0,1,0,-9.8,0 l9.8,0 m-4.9,-4.9 l0,9.8"
+       id="path6" />
+    <path
+       d="M7.5,48.5 m-4.9,0 a4.9,4.9,0,1,0,9.8,0 a4.9,4.9,0,1,0,-9.8,0 l9.8,0 m-4.9,-4.9 l0,9.8"
+       id="path8" />
+    <path
+       d="M62.5,48.5 m-4.9,0 a4.9,4.9,0,1,0,9.8,0 a4.9,4.9,0,1,0,-9.8,0 l9.8,0 m-4.9,-4.9 l0,9.8"
+       id="path10" />
+    <!-- width -->
+    <path
+       d="M0,-5 l0,-10 M70,-5 l0,-10"
+       id="path11" />
+    <text
+       x="35"
+       y="-7"
+       style="fill:#000000;stroke:none;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:10px;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-anchor:middle"
+       text-anchor="middle"
+       id="text16"><tspan
+         id="tspan310">0.700</tspan>
+    </text>
+    <!-- height -->
+    <path
+       d="M-5,0 l-10,0 M-5,56 l-10,0"
+       id="path11" />
+    <text
+       x="28"
+       y="14"
+       transform="rotate(90)"
+       style="fill:#000000;stroke:none;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:10px;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-anchor:middle"
+       text-anchor="middle"
+       id="text16"><tspan
+         id="tspan310">0.560</tspan>
+    </text>
+    <!-- hole H dist -->
+    <path
+       d="M7.5,61 l0,10 M62.5,60 l0,10"
+       id="path11" />
+    <text
+       x="35"
+       y="70"
+       style="fill:#000000;stroke:none;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:10px;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-anchor:middle"
+       text-anchor="middle"
+       id="text16"><tspan
+         id="tspan310">0.550</tspan>
+    </text>
+    <!-- hole V dist -->
+    <path
+       d="M75,7.5 l10,0 M75,48.5 l10,0"
+       id="path11" />
+    <text
+       x="28"
+       y="-77"
+       transform="rotate(90)"
+       style="fill:#000000;stroke:none;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:10px;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-anchor:middle"
+       text-anchor="middle"
+       id="text16"><tspan
+         id="tspan310">0.410</tspan>
+    </text>
+    <!-- label -->
+    <text
+       x="35"
+       y="31"
+       style="fill:#000000;stroke:none;font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:10px;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-anchor:middle"
+       text-anchor="middle"
+       id="text16"><tspan
+         id="tspan310">MicroPeak</tspan></text>
+  </g>
+</svg>
index 85776a25463544baa5f7ee9390b71229678d0276..51408b444d82cd59318dc6ea23fafa503239d1d7 100644 (file)
@@ -23,5 +23,5 @@ Because documentation is just as prone as software to contain “bugs”, and
 can always be improved… If you have questions that aren't answered in this 
 manual, or just need a little help figuring things out, we strongly suggest 
 joining the Altus Metrum user email list, which you can do by visiting 
-https://lists.gag.com/mailman3.
+https://groups.io/g/altusmetrum.
 
index 6371ae04c49301f62ad1d72824e25aadb1032a2f..958a0cad66a668782a09b74b901c24639bc5b193 100644 (file)
@@ -5,12 +5,16 @@
        checklist after the rocket is installed on a launch rail.
 
        The board will beep out a Morse code “P” every few seconds
-       indicating that it's in pad mode and ready to detect launch.
-       Once launch is detected, the board logs pressure and acceleration
-       data 100 times per second throughout the flight.
+       indicating that it's in pad mode and ready to detect the start of
+       the motor burn.  Recording starts when chamber pressure rises by
+       at least 50psi, then the board logs pressure and acceleration
+       data 100 times per second until chamber pressure goes low again and
+       remains stable for at least 10 seconds.
 
-       After flight, AltosUI can be used to download the flight data,
-       view a quick graph of acceleration and pressure with pan and
+       After flight, attach a USB data cable to the board before powering
+       it on so that it goes in to 'idle mode'.  Then AltosUI can be used 
+       to download the flight data, view a quick graph of acceleration and 
+       pressure with pan and
        zoom capabilities, then export it to a comma separated values 
        (CSV) file. Such a file can easily be loaded into a spreadsheet 
-       for analysis.
+       for analysis. 
diff --git a/doc/release-notes-1.9.18.inc b/doc/release-notes-1.9.18.inc
new file mode 100644 (file)
index 0000000..3e1544d
--- /dev/null
@@ -0,0 +1,18 @@
+= Release Notes for Version 1.9.18
+include::release-head.adoc[]
+:doctype: article
+
+       Version 1.9.18
+
+       == AltOS
+       
+       * Add support for EasyTimer V2. The new version of this
+          product has on-board storage to log data during flight.
+
+       == AltosUI & TeleGPS application
+
+       * Add support for EasyTimer V2. This includes support for
+          analyizing flight data from the on-board logs.
+
+       * Allow on-board beepers to be disabled by setting the
+         frequency to 0.
diff --git a/doc/release-notes-1.9.19.inc b/doc/release-notes-1.9.19.inc
new file mode 100644 (file)
index 0000000..f346f60
--- /dev/null
@@ -0,0 +1,14 @@
+= Release Notes for Version 1.9.19
+include::release-head.adoc[]
+:doctype: article
+
+       Version 1.9.19
+
+       == AltOS
+       
+       * Finish support for EasyMega V3.
+
+       == AltosUI & TeleGPS application
+
+       * Show device configuration information when graphing a
+          flight.
diff --git a/doc/release-notes-1.9.20.inc b/doc/release-notes-1.9.20.inc
new file mode 100644 (file)
index 0000000..fd356aa
--- /dev/null
@@ -0,0 +1,15 @@
+= Release Notes for Version 1.9.20
+include::release-head.adoc[]
+:doctype: article
+
+       Version 1.9.20
+
+       == AltOS
+       
+       * Add support for TeleGPS v4.0 and TeleMega v7.0
+
+       == AltosUI & TeleGPS application
+
+       * Add support for TeleGPS v4.0 and TeleMega v7.0
+
+       * Add support for 30V pyro voltage range
diff --git a/doc/release-notes-1.9.21.inc b/doc/release-notes-1.9.21.inc
new file mode 100644 (file)
index 0000000..f2d45e7
--- /dev/null
@@ -0,0 +1,15 @@
+= Release Notes for Version 1.9.21
+include::release-head.adoc[]
+:doctype: article
+
+       Version 1.9.21
+
+       == AltOS
+       
+       * Add support for TeleBT v4.0 factory test.
+
+       * Support Picolibc 1.8.10
+
+       == AltosUI & TeleGPS application
+
+       * Support pressure values below sensor range.
diff --git a/doc/release-notes-1.9.22.inc b/doc/release-notes-1.9.22.inc
new file mode 100644 (file)
index 0000000..9010ea5
--- /dev/null
@@ -0,0 +1,9 @@
+= Release Notes for Version 1.9.22
+include::release-head.adoc[]
+:doctype: article
+
+       Version 1.9.22
+
+       == AltosUI & TeleGPS application
+
+       * Support TeleMega v7 .eeprom files
index 786f29e3e3a229774482a6ddf63fc380f37f408d..4344879a05d91fd89f5e96ca419f3435ac133170 100644 (file)
@@ -1,5 +1,25 @@
 [appendix]
 == Release Notes
+       :leveloffset: 2
+       include::release-notes-1.9.22.adoc[]
+
+       <<<<
+       :leveloffset: 2
+       include::release-notes-1.9.21.adoc[]
+
+       <<<<
+       :leveloffset: 2
+       include::release-notes-1.9.20.adoc[]
+
+       <<<<
+       :leveloffset: 2
+       include::release-notes-1.9.19.adoc[]
+
+       <<<<
+       :leveloffset: 2
+       include::release-notes-1.9.18.adoc[]
+
+       <<<<
        :leveloffset: 2
        include::release-notes-1.9.17.adoc[]
 
index c00e1b3a235455b71eca0d9ea690392a72c1576f..b6acbed82c2a841caec4b23efa8a4a45e5b28173 100644 (file)
        |40mW
        |3.7V
 
+       |TeleMega v7.0
+       |MS5607 30km (100k')
+       |ADXL375 200g
+       |uBlox Max-10S
+       |BMI088 MMC5983
+       |8MB
+       |40mW
+       |3.7V
+
        endif::telemega[]
        ifdef::easymega[]
        |EasyMega v1.0
        |8MB
        |-
        |3.7V
+
+       |EasyMega v3.0
+       |MS5607 30km (100k')
+       |ADXL375 200g
+       |-
+       |BMI088 MMC5983A
+       |8MB
+       |-
+       |3.7V
        endif::easymega[]
 
        ifdef::easytimer[]
        |-
        |-
        |3.7-12V
+
+       |EasyTimer v2.0
+       |-
+       |24g
+       |-
+       |BMI088 MMC5983
+       |1MB
+       |-
+       |3.7-12V
        endif::easytimer[]
        
        ifdef::easymotor[]
        |-
        |8MB
        |-
-       |6.5-15V
+       |3.7V
        endif::easymotor[]
        
        
index 888e3891c6479941bba2276c6719e1cba5d6016a..656ed8e42a756a1bbfab56699a8e026821fe765e 100644 (file)
                have an
                accelerometer we can use to determine orientation, “idle” mode
                is selected if the board is connected via USB to a computer,
-               otherwise the board enters “flight” mode.
+               otherwise the board enters “flight” mode.  This is also how
+               EasyMotor works, since even though it has an accelerometer,
+               it detects the motor burn it is meant to record by detecting\ e\ 1          a rise in chamber pressure, and board orientation doesn't 
+               matter.
                ifdef::telemini[]
                TeleMini
                selects “idle” mode if it receives a command packet
index 3ef5f9bf6a9231064f99631e3c4e5b288d86c64b..e10f62adeb56987ecd74aa48b013bf84043cc999 100644 (file)
@@ -1,5 +1,29 @@
 [appendix]
 == Release Notes
+       :leveloffset: 2
+       include::release-notes-1.9.22.adoc[]
+
+       <<<<
+       :leveloffset: 2
+       include::release-notes-1.9.21.adoc[]
+
+       <<<<
+       :leveloffset: 2
+       include::release-notes-1.9.20.adoc[]
+
+       <<<<
+       :leveloffset: 2
+       include::release-notes-1.9.19.adoc[]
+
+       <<<<
+       :leveloffset: 2
+       include::release-notes-1.9.18.adoc[]
+
+       <<<<
+       :leveloffset: 2
+       include::release-notes-1.9.17.adoc[]
+
+       <<<<
        :leveloffset: 2
        include::release-notes-1.9.16.adoc[]
 
index 4a0f06ab9d35f09b7aba1a2c707acd511d783677..d4bd897a2cba7107ac5181b557a05dc5f6d91294 100644 (file)
@@ -1,7 +1,8 @@
 [dedication]
 == Acknowledgments
 
-       Our profound thanks to Terry Lee for major contributions to making 
+       Our profound thanks to Terry Lee (TRA #10206, NAR #3284) for major
+        contributions to making
        the TeleLaunch system something we could actually package and sell!
 
        Tripoli Colorado, Oregon Rocketry, New River Valley Rocketry, and 
index bfd67a49da0479ff69e7bfd876d70be1bae7a334..c93c19f32085b2ebd63ba8e327c6edfc82bacae5 100644 (file)
@@ -23,5 +23,5 @@ Because documentation is just as prone as software to contain "bugs", and
 can always be improved...  If you have questions that aren't answered in this 
 manual, or just need a little help figuring things out, we strongly suggest 
 joining the Altus Metrum user email list, which you can do by visiting 
-https://lists.gag.com/mailman/listinfo/altusmetrum.
+https://groups.io/g/altusmetrum.
 
index c867c6cdac0e5eb0dc65c11c4ef51b78937cc8a5..7ee0ab3c831abb6a302c1748622ec3de01649075 100644 (file)
@@ -48,7 +48,7 @@ Keith Packard <keithp@keithp.com>; Bdale Garbee <bdale@gag.com>
                |0      |uint16_t       |serial |Device serial Number
                |2      |uint16_t       |tick   |Device time in 100ths of a second
                |4      |uint8_t        |type   |Packet type
-               |5
+               |5      |       |       |
                |====
 
                Each packet starts with these five bytes which serve to identify
@@ -93,7 +93,7 @@ Keith Packard <keithp@keithp.com>; Bdale Garbee <bdale@gag.com>
                |26     |int16_t        |ground_accel   |TM
                |28     |int16_t        |accel_plus_g   |TM
                |30     |int16_t        |accel_minus_g  |TM
-               |32
+               |32     |       |       |
                |====
 
        === TeleMega Sensor Data
@@ -152,7 +152,7 @@ Keith Packard <keithp@keithp.com>; Bdale Garbee <bdale@gag.com>
                |26     |int16_t        |mag_x          |X field strength (across)
                |28     |int16_t        |mag_y          |Y field strength (along)
                |30     |int16_t        |mag_z          |Z field strength (through)
-               |32
+               |32     |       |       |
                |====
 
                .TeleMega Kalman and Voltage Data Packet Contents
@@ -170,7 +170,7 @@ Keith Packard <keithp@keithp.com>; Bdale Garbee <bdale@gag.com>
                |26     |int16_t        |acceleration   |m/s² * 16
                |28     |int16_t        |speed          |m/s * 16
                |30     |int16_t        |height         |m
-               |32
+               |32     |       |       |
                |====
 
        === TeleMetrum v2 and newer Sensor Data
@@ -208,7 +208,7 @@ Keith Packard <keithp@keithp.com>; Bdale Garbee <bdale@gag.com>
                |22     |int16_t        |sense_d        |drogue continuity sense
                |24     |int16_t        |sense_m        |main continuity sense
                |26     |pad[6]         |pad bytes      |
-               |32
+               |32     |       |       |
                |====
 
                .TeleMetrum v2 and newer Calibration Data Packet Contents
@@ -221,7 +221,7 @@ Keith Packard <keithp@keithp.com>; Bdale Garbee <bdale@gag.com>
                |14     |int16_t        |accel_plus_g   |Accel calibration at +1g
                |16     |int16_t        |accel_minus_g  |Accel calibration at -1g
                |18     |pad[14]        |pad bytes      |
-               |32
+               |32     |       |       |
                |====
 
        === TeleMini v3.0 Sensor Data
@@ -255,7 +255,7 @@ Keith Packard <keithp@keithp.com>; Bdale Garbee <bdale@gag.com>
                |22     |int16_t        |height         |m
                |24     |int16_t        |ground_pres    |Average barometer reading on ground
                |28     |pad[4]         |pad bytes      |
-               |32
+               |32     |       |       |
                |====
 
 
@@ -287,7 +287,7 @@ Keith Packard <keithp@keithp.com>; Bdale Garbee <bdale@gag.com>
                |14     |uint16_t       |flight_log_max |Maximum flight log size (kB)
                |16     |char           |callsign[8]    |Radio operator identifier
                |24     |char           |version[8]     |Software version identifier
-               |32
+               |32     |       |       |
                |====
 
        === GPS Location
@@ -328,7 +328,7 @@ Keith Packard <keithp@keithp.com>; Bdale Garbee <bdale@gag.com>
                |28     |int16_t        |climb_rate     |cm/s
                |30     |uint8_t        |course         |/ 2
                |31     |uint8_t        |unused[1]      |
-               |32
+               |32     |       |       |
                |====
 
                Packed into a one byte field are status flags and the
@@ -405,7 +405,7 @@ Keith Packard <keithp@keithp.com>; Bdale Garbee <bdale@gag.com>
                |5      |uint8_t        |channels       |Number of reported satellite information
                |6      |sat_info_t     |sats[12]       |See Per-Satellite data table below
                |30     |uint8_t        |unused[2]      |
-               |32
+               |32     |       |       |
                |====
 
                .GPS Per-Satellite data (sat_info_t)
@@ -414,7 +414,7 @@ Keith Packard <keithp@keithp.com>; Bdale Garbee <bdale@gag.com>
                |Offset |Data Type      |Name           |Description
                |0      |uint8_t        |svid           |Space Vehicle Identifier
                |1      |uint8_t        |c_n_1          |C/N1 signal quality indicator
-               |2
+               |2      |       |       |
                |====
 
        === Companion Data
@@ -444,7 +444,7 @@ Keith Packard <keithp@keithp.com>; Bdale Garbee <bdale@gag.com>
                |6      |uint8_t        |update_period  |How often telemetry is sent, in 1/100ths of a second
                |7      |uint8_t        |channels       |Number of data channels supplied
                |8      |uint16_t[12]   |companion_data |Up to 12 channels of 16-bit companion data
-               |32
+               |32     |       |       |
                |====
 
 == Data Transmission
index 1bf5f8e278eb771f44b6c87ac1f369e80ca574fb..e9cf19668d501ac43a14da83679f8df5cb882984 100755 (executable)
@@ -1,5 +1,5 @@
 #!/bin/sh
 # map-N43.799102,W120.586281-hybrid-20.jpg
-export QUERY_STRING="lat=43.799102&lon=-120.586281&zoom=20"
+export QUERY_STRING="lat=43.799102&lon=-120.586281&zoom=17"
 export REMOTE_ADDR="127.0.0.1"
 ./altos-map
index c89ac0e0b52ea36094529a9c04fe10881eb21370..5b70157322222d9b9e7b6abd8b2d2ee10bc944a5 100644 (file)
@@ -29,12 +29,14 @@ ARMM3DIRS=\
        telemega-v4.0 telemega-v4.0/flash-loader \
        telemega-v5.0 telemega-v5.0/flash-loader \
        telemega-v6.0 telemega-v6.0/flash-loader \
+       telemega-v7.0 telemega-v7.0/flash-loader \
        telemetrum-v2.0 telemetrum-v2.0/flash-loader \
        telemetrum-v3.0 telemetrum-v3.0/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 \
        telegps-v3.0 telegps-v3.0/flash-loader \
+       telegps-v4.0 telegps-v4.0/flash-loader \
        telelco-v0.2 telelco-v0.2/flash-loader \
        telelco-v0.2-cc1200 telelco-v0.2-cc1200/flash-loader \
        telelco-v0.3 telelco-v0.3/flash-loader \
@@ -63,7 +65,7 @@ ARMM0DIRS=\
 AVRDIRS=\
        micropeak microkite microsplash
 
-SUBDIRS=draw
+SUBDIRS=draw test
 
 ifeq ($(strip $(HAVE_ARM_M3_CC)),yes)
 SUBDIRS+=$(ARMM3DIRS)
index 6b986b4223e0631eb334d2651db3427da853a198..746178a044e82c133854536925d862636cf4f0f3 100644 (file)
@@ -151,3 +151,5 @@ $(LINE_TEST_OBJS): $(HEADERS)
 
 clean:
        rm -f $(LCO_TEST_OBJS) ao_font.h ao_logo.h $(FONT_SRCS)
+
+install:
index 70bf92a5f1fb72e6a44d0f711de58623a711a222..4366e302fa0e9802cf2519623fb17e1beaec3128 100644 (file)
@@ -102,11 +102,14 @@ struct ao_adxl375_total {
 
 #define AO_ADXL375_SELF_TEST_SAMPLES   10
 #define AO_ADXL375_SELF_TEST_SETTLE    4
+#define AO_ADXL375_SELF_TEST_DELAY     AO_MS_TO_TICKS(10)
 
 #define MIN_LSB_G      18.4
 #define MAX_LSB_G      22.6
-#define SELF_TEST_MIN_G        5.0
-#define SELF_TEST_MAX_G        6.8
+
+/* The self test value can vary within a rather wide range */
+#define SELF_TEST_MIN_G        4.0
+#define SELF_TEST_MAX_G        12.0
 
 #define MIN_SELF_TEST  ((int32_t) (MIN_LSB_G * SELF_TEST_MIN_G * AO_ADXL375_SELF_TEST_SAMPLES + 0.5))
 #define MAX_SELF_TEST  ((int32_t) (MAX_LSB_G * SELF_TEST_MAX_G * AO_ADXL375_SELF_TEST_SAMPLES + 0.5))
@@ -122,7 +125,7 @@ ao_adxl375_total_value(struct ao_adxl375_total *total, int samples)
                total->x += value.x;
                total->y += value.y;
                total->z += value.z;
-               ao_delay(AO_MS_TO_TICKS(10));
+               ao_delay(AO_ADXL375_SELF_TEST_DELAY);
        }
 }
 
@@ -174,6 +177,11 @@ ao_adxl375_setup(void)
                             (0 << AO_ADXL375_POWER_CTL_SLEEP) |
                             (AO_ADXL375_POWER_CTL_WAKEUP_8 << AO_ADXL375_POWER_CTL_WAKEUP));
 
+       /* Set to normal mode */
+
+       ao_adxl375_reg_write(AO_ADXL375_DATA_FORMAT,
+                            AO_ADXL375_DATA_FORMAT_SETTINGS(0));
+
        /* Perform self-test */
 
        struct ao_adxl375_total self_test_off, self_test_on;
@@ -208,13 +216,9 @@ ao_adxl375_setup(void)
        if (z_change < MIN_SELF_TEST)
                AO_SENSOR_ERROR(AO_DATA_ADXL375);
 
-       /* This check is commented out as maximum self test is unreliable
-
-          if (z_change > MAX_SELF_TEST)
+       if (z_change > MAX_SELF_TEST)
                AO_SENSOR_ERROR(AO_DATA_ADXL375);
 
-       */
-
        /* Discard some samples to let it settle down */
        ao_adxl375_total_value(&self_test_off, AO_ADXL375_SELF_TEST_SETTLE);
 }
index ed1d298e1b4a8c100950da114c7ab45ed8abbce0..b3a1e57551556054a5f9a6cd31a98f6ab36c0484 100644 (file)
@@ -1456,6 +1456,22 @@ static const struct ao_cmds ao_radio_cmds[] = {
        { 0, NULL }
 };
 
+/* Make sure the radio is alive */
+bool
+ao_radio_post(void)
+{
+       uint8_t partnum;
+
+       partnum = ao_radio_reg_read(CC1200_PARTNUMBER);
+       switch (partnum) {
+       case CC1200_PARTNUMBER_CC1200:
+       case CC1200_PARTNUMBER_CC1201:
+               return true;
+       default:
+               return false;
+       }
+}
+
 void
 ao_radio_init(void)
 {
index 176f83837898e48366f28ce19f66e18f2af7880b..47d587bb046f9076564ac57186a374a1bc7cb378 100644 (file)
@@ -47,35 +47,45 @@ extern uint8_t      ao_lco_firing;          /* fire button pressed */
 extern struct ao_pad_query     ao_pad_query;   /* Last received QUERY from pad */
 
 #ifdef AO_LCO_DRAG_RACE_BOX
-#define AO_LCO_BOX_DRAG                0               /* Box number to enable drag race mode (old LCO bits) */
-#define AO_LCO_BOX_FIRST       AO_LCO_BOX_DRAG
+# define AO_LCO_BOX_DRAG       0               /* Box number to enable drag race mode (old LCO bits) */
+# define AO_LCO_BOX_FIRST      AO_LCO_BOX_DRAG
 #else
-# define AO_LCO_LCO_VOLTAGE    0               /* Box number to show LCO voltage */
-# ifdef AO_LCO_HAS_INFO
-#  define AO_LCO_INFO          -3
+# ifdef AO_LCO_HAS_CONTRAST
+#  define AO_LCO_CONTRAST      -2
 #  ifndef AO_LCO_BOX_FIRST
-#   define AO_LCO_BOX_FIRST AO_LCO_INFO
+#   define AO_LCO_BOX_FIRST    AO_LCO_CONTRAST
 #  endif
 # endif
-# ifdef AO_LCO_HAS_BACKLIGHT
-#   define AO_LCO_BACKLIGHT    -2
-#   ifndef AO_LCO_BOX_FIRST
-#    define AO_LCO_BOX_FIRST AO_LCO_BACKLIGHT
-#   endif
+# ifdef AO_LCO_HAS_BACKLIGHT_UI
+#  define AO_LCO_BACKLIGHT     -1
+#  ifndef AO_LCO_BOX_FIRST
+#   define AO_LCO_BOX_FIRST    AO_LCO_BACKLIGHT
+#  endif
 # endif
-# ifdef AO_LCO_HAS_CONTRAST
-#  define AO_LCO_CONTRAST      -1
+# if AO_LCO_HAS_LCO_INFO
+#  define AO_LCO_LCO_INFO      0               /* Box number to show LCO info */
 #  ifndef AO_LCO_BOX_FIRST
-#   define AO_LCO_BOX_FIRST    AO_LCO_CONTRAST
+#   define AO_LCO_BOX_FIRST    AO_LCO_LCO_INFO
+#  endif
+# else
+#  define AO_LCO_LCO_VOLTAGE   -1
+#  ifndef AO_LCO_BOX_FIRST
+#   define AO_LCO_BOX_FIRST    AO_LCO_LCO_VOLTAGE
 #  endif
 # endif
 # ifndef AO_LCO_BOX_FIRST
-#  define AO_LCO_BOX_FIRST     AO_LCO_LCO_VOLTAGE
+#  define AO_LCO_BOX_FIRST     1
 # endif
 #endif
-#define AO_LCO_PAD_VOLTAGE     0               /* Pad number to show box voltage */
-#define AO_LCO_PAD_RSSI                -1              /* Pad number to show box RSSI */
-#define AO_LCO_PAD_FIRST       AO_LCO_PAD_RSSI
+
+#ifdef AO_LCO_HAS_PAD_INFO
+# define AO_LCO_PAD_INFO       0               /* Pad number to show box info */
+# define AO_LCO_PAD_FIRST      AO_LCO_PAD_INFO
+#else
+# define AO_LCO_PAD_VOLTAGE    0               /* Pad number to show box voltage */
+# define AO_LCO_PAD_RSSI       -1              /* Pad number to show box RSSI */
+# define AO_LCO_PAD_FIRST      AO_LCO_PAD_RSSI
+#endif
 
 static inline bool
 ao_lco_box_pseudo(int16_t box)
@@ -97,8 +107,8 @@ ao_lco_box_pseudo(int16_t box)
        case AO_LCO_BACKLIGHT:
                return true;
 #endif
-#ifdef AO_LCO_INFO
-       case AO_LCO_INFO:
+#ifdef AO_LCO_LCO_INFO
+       case AO_LCO_LCO_INFO:
                return true;
 #endif
        default:
@@ -110,10 +120,18 @@ static inline bool
 ao_lco_pad_pseudo(int8_t pad)
 {
        switch (pad) {
+#ifdef AO_LCO_PAD_VOLTAGE
        case AO_LCO_PAD_VOLTAGE:
                return true;
+#endif
+#ifdef AO_LCO_PAD_RSSI
        case AO_LCO_PAD_RSSI:
                return true;
+#endif
+#ifdef AO_LCO_PAD_INFO
+       case AO_LCO_PAD_INFO:
+               return true;
+#endif
        default:
                return false;
        }
index ebe3d0cb2989b12ca59ca15fefd4ab2081a9dea7..0d922d6e85d340339ca3f5c9da1f1a24b37e2403 100644 (file)
@@ -38,6 +38,8 @@ static uint8_t                ao_lco_channels[AO_PAD_MAX_BOXES];      /* pad channels available on
 static uint16_t                ao_lco_tick_offset[AO_PAD_MAX_BOXES];   /* 16 bit offset from local to remote tick count */
 static uint8_t         ao_lco_selected[AO_PAD_MAX_BOXES];      /* pads selected to fire */
 
+static uint32_t                ao_lco_query_good, ao_lco_query_bad;
+
 uint8_t                ao_lco_valid[AO_PAD_MAX_BOXES];         /* AO_LCO_VALID bits per box */
 
 static const AO_LED_TYPE       continuity_led[AO_LED_CONTINUITY_NUM] = {
@@ -171,9 +173,14 @@ ao_lco_get_channels(int16_t box, struct ao_pad_query *query)
        if (r == AO_RADIO_CMAC_OK) {
                ao_lco_channels[box] = query->channels;
                ao_lco_valid[box] = AO_LCO_VALID_LAST | AO_LCO_VALID_EVER;
-       } else
+               ++ao_lco_query_good;
+       } else {
                ao_lco_valid[box] &= (uint8_t) ~AO_LCO_VALID_LAST;
-       PRINTD("ao_lco_get_channels(%d) rssi %d valid %d ret %d offset %d\n", box, ao_radio_cmac_rssi, ao_lco_valid[box], r, ao_lco_tick_offset[box]);
+               ++ao_lco_query_bad;
+       }
+       PRINTD("ao_lco_get_channels(%d) rssi %d valid %d ret %d offset %d good %"PRIu32" bad %"PRIu32"\n",
+              box, ao_radio_cmac_rssi, ao_lco_valid[box], r, ao_lco_tick_offset[box],
+              ao_lco_query_good, ao_lco_query_bad);
        ao_wakeup(&ao_pad_query);
        return ao_lco_valid[box];
 }
@@ -193,9 +200,9 @@ ao_lco_update(void)
                        if (!ao_lco_pad_pseudo(ao_lco_pad))
                                ao_lco_set_pad(ao_lco_pad_first(ao_lco_box));
                }
-               if (ao_lco_pad_pseudo(ao_lco_pad))
-                       ao_lco_show();
        }
+       if (ao_lco_pad_pseudo(ao_lco_pad))
+               ao_lco_show();
 }
 
 uint8_t        ao_lco_box_mask[AO_LCO_MASK_SIZE(AO_PAD_MAX_BOXES)];
@@ -266,7 +273,7 @@ ao_lco_step_pad(int8_t dir)
                break;
        }
 #endif
-#ifdef AO_LCO_HAS_BACKLIGHT
+#ifdef AO_LCO_HAS_BACKLIGHT_UI
        case AO_LCO_BACKLIGHT: {
                int32_t backlight = ao_lco_get_backlight();
 
@@ -282,8 +289,8 @@ ao_lco_step_pad(int8_t dir)
                break;
        }
 #endif
-#ifdef AO_LCO_HAS_INFO
-       case AO_LCO_INFO: {
+#if AO_LCO_HAS_LCO_INFO
+       case AO_LCO_LCO_INFO: {
 #if AO_LCO_MIN_INFO_PAGE < AO_LCO_MAX_INFO_PAGE
                int32_t info_page = ao_lco_get_info_page();
 
index 3c07e7216cc34b3c084bffeee28ce12eed5aa44d..f3c05e82469e25a8fb186459fb8780592260f93e 100644 (file)
@@ -308,19 +308,10 @@ ao_rn_wait_status(void)
 }
 
 static int
-ao_rn_set_name(void)
+ao_rn_set_name(char *name)
 {
-       char    sn[8];
-       char    *s = sn + 8;
-       int     n;
-
 //     ao_rn_dbg("set name...\n");
-       *--s = '\0';
-       n = ao_serial_number;
-       do {
-               *--s = (uint8_t) ('0' + n % 10);
-       } while (n /= 10);
-       ao_rn_send_cmd(AO_RN_SET_NAME_CMD "TeleBT-", s);
+       ao_rn_send_cmd(AO_RN_SET_NAME_CMD, name);
        return ao_rn_wait_status();
 }
 
@@ -345,6 +336,7 @@ ao_rn_isr(void)
        ao_wakeup(&ao_rn_connected);
 }
 
+#ifndef ao_bt_panic
 static void
 ao_bt_panic(int where)
 {
@@ -361,6 +353,7 @@ ao_bt_panic(int where)
                }
        }
 }
+#endif
 
 static uint8_t ao_rn_stdio;
 
@@ -377,7 +370,7 @@ static void
 ao_rn(void)
 {
        int     status = AO_RN_ERROR;
-       char    name[17];
+       char    have_name[17], want_name[17];
        int     i;
 
        ao_rn_dbg("ao_rn top\n");
@@ -416,15 +409,16 @@ ao_rn(void)
                /* Check to see if the name is already set and assume
                 * that the device is ready to go
                 */
-               status = ao_rn_get_name(name, sizeof (name));
+               status = ao_rn_get_name(have_name, sizeof (have_name));
                if (status != AO_RN_OK) {
                        ao_rn_dbg("get name failed\n");
-                       status = ao_rn_get_name(name, sizeof (name));
+                       status = ao_rn_get_name(have_name, sizeof (have_name));
                        if (status != AO_RN_OK)
                                continue;
                }
+               snprintf(want_name, sizeof(want_name), "TeleBT-%u", ao_serial_number);
 
-               if (strncmp(name, "TeleBT-", 7) == 0) {
+               if (strcmp(have_name, want_name) == 0) {
                        ao_rn_dbg("name is set\n");
                        status = AO_RN_OK;
                        break;
@@ -453,7 +447,7 @@ ao_rn(void)
                /* Finally, set the name. Doing this last makes it possible to check
                 * if the whole sequence has been done
                 */
-               if (ao_rn_set_name() != AO_RN_OK) {
+               if (ao_rn_set_name(want_name) != AO_RN_OK) {
                        ao_rn_dbg("set name failed\n");
                        continue;
                }
index c145b83b2a8557990416a6e64393e4c0fde40a56..f745e45ed1d16c6794d8bef703bfb19e3018a60d 100644 (file)
@@ -84,17 +84,33 @@ CFLAGS = $(PRODUCT_DEF) $(STM32F1_CFLAGS)
 PROGNAME=easymega-v3.0
 PROG=$(PROGNAME)-$(VERSION).elf
 HEX=$(PROGNAME)-$(VERSION).ihx
+FLASH_PROG=flash-loader/$(PROGNAME)-altos-flash-$(VERSION).elf
+BOTH_DFU=$(PROGNAME)-combined-$(VERSION).dfu
+BOTH_HEX=$(PROGNAME)-combined-$(VERSION).ihx
+ELFTOHEX=$(TOPDIR)/../ao-tools/ao-elftohex/ao-elftohex
+MAKEBIN=$(TOPDIR)/../ao-tools/ao-makebin/ao-makebin
 
 SRC=$(ALTOS_SRC) ao_easymega.c
 OBJ=$(SRC:.c=.o)
 
-all: $(PROG) $(HEX)
+all: $(PROG) $(HEX) $(BOTH_DFU) $(BOTH_HEX)
 
 $(PROG): Makefile $(OBJ) altos.ld
        $(call quiet,CC) $(LDFLAGS) -o $(PROG) $(OBJ) $(LIBS)
 
+$(BOTH_DFU): $(PROG) $(FLASH_PROG)
+       $(MAKEBIN) --dfu --output=$@ --base=$(FLASH_ADDR) $(FLASH_PROG) $(PROG)
+
+$(BOTH_HEX): $(PROG) $(FLASH_PROG)
+       $(ELFTOHEX) --nosym --output=$@ $(FLASH_PROG) $(PROG)
+
+$(FLASH_PROG): FRC
+       +cd flash-loader && make
+
 $(OBJ): $(INC)
 
+FRC:
+
 distclean:     clean
 
 clean:
index a045e126672d553b60ced4b0f4753803d0d83770..ac4f9c4bb7043eb908af3a64d70874d3a59e0466 100644 (file)
@@ -83,6 +83,7 @@ distclean:    clean
 
 clean:
        rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx $(PROGNAME)-*.map
+       rm -f $(PROGNAME)-*.dfu
        rm -f ao_product.h
 
 install:
index b3f780f5c7609797c15c895e90b0fa965dcf1a44..1cfe29e9f55652c2b448cde57858cc3317f3957b 100644 (file)
 #ifndef _AO_H_
 #define _AO_H_
 
-#include <stdint.h>
+#include <inttypes.h>
 #include <stdio.h>
 #include <string.h>
 #include <stddef.h>
+#include <stdarg.h>
 #include <stdbool.h>
 #include <ao_pins.h>
 #include <ao_arch.h>
@@ -666,6 +667,9 @@ ao_radio_test_on(void);
 void
 ao_radio_test_off(void);
 
+bool
+ao_radio_post(void);
+
 void
 ao_radio_init(void);
 
index 565ac61e450e6d6a567975761e0b4fcb02bf2b4d..4883e7cfa9821d4ef590698f391b6c956054b815 100644 (file)
@@ -56,6 +56,10 @@ uint8_t ao_force_freq;
 #define AO_CONFIG_DEFAULT_PYRO_TIME    AO_MS_TO_TICKS(50)
 #define AO_CONFIG_DEFAULT_RADIO_10MW   0
 #define AO_CONFIG_DEFAULT_REPORT_FEET  0
+#ifndef AO_CONFIG_DEFAULT_ACCEL_PLUS_G
+#define AO_CONFIG_DEFAULT_ACCEL_PLUS_G 0
+#define AO_CONFIG_DEFAULT_ACCEL_MINUS_G        0
+#endif
 #if HAS_CONFIG_SAVE
 #ifndef USE_INTERNAL_FLASH
 #error Please define USE_INTERNAL_FLASH
@@ -155,8 +159,8 @@ _ao_config_get(void)
                        ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY;
                /* Fixups for minor version 2 */
                if (minor < 2) {
-                       ao_config.accel_plus_g = 0;
-                       ao_config.accel_minus_g = 0;
+                       ao_config.accel_plus_g = AO_CONFIG_DEFAULT_ACCEL_PLUS_G;
+                       ao_config.accel_minus_g = AO_CONFIG_DEFAULT_ACCEL_MINUS_G;
                }
                /* Fixups for minor version 3 */
 #if HAS_RADIO
index a8541775ae807272947dbd66b357c05ec2e2ef61..6896eaa973161375adf553c519369eac03ee8e45 100644 (file)
@@ -19,7 +19,9 @@
 #ifndef _AO_CONFIG_H_
 #define _AO_CONFIG_H_
 
+#ifndef AO_FLIGHT_TEST
 #include <ao.h>
+#endif
 
 #if AO_PYRO_NUM
 #include <ao_pyro.h>
index e0ee2928cfa8fd569e260fc05d46161b1d6eefba..e1ca0bf7bb01ee123ec146c2b03aaf9855a525fb 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <stdint.h>
 #define AO_CONVERT_TEST
+#define AO_TICK_TYPE uint32_t
 typedef int32_t alt_t;
 typedef int32_t pres_t;
 #include "ao_host.h"
index c8debbc57d2df707a3fb1989842bc589d082387d..f3eb0178d1bbe0e9fa882872afcab823a66c959f 100644 (file)
@@ -17,6 +17,7 @@
  */
 
 #include <stdint.h>
+#define AO_TICK_TYPE uint32_t
 #define AO_CONVERT_TEST
 #define AO_NEED_ALTITUDE_TO_PRES 1
 #include "ao_host.h"
index c974a9fe5f1e37c89261245bfa3ab945d1b8bdbf..30df8edc0e66ffc7cc7f610adc57103edbfd881c 100644 (file)
@@ -81,12 +81,20 @@ struct ao_task {
        int dummy;
 };
 
+enum ao_igniter_status {
+       ao_igniter_unknown,     /* unknown status (ambiguous voltage) */
+       ao_igniter_ready,       /* continuity detected */
+       ao_igniter_active,      /* igniter firing */
+       ao_igniter_open,        /* open circuit detected */
+};
+
 #define ao_add_task(t,f,n)
 
 #define ao_log_start()
 #define ao_log_stop()
 
 #define AO_MS_TO_TICKS(ms)     ((ms) / 10)
+#define AO_NS_TO_TICKS(ns)     ((ns) / (10000000L))
 #define AO_SEC_TO_TICKS(s)     ((s) * 100)
 
 #define AO_FLIGHT_TEST
index b8aa6a8c589541759f50a34885cff2edf53897e5..f905f62a0996158bbce23d2c8746b173b775c6ec 100644 (file)
@@ -64,6 +64,7 @@ extern enum ao_flight_state ao_log_state;
 #define AO_LOG_FORMAT_TELEMEGA_6       22      /* 32 byte typed telemega records with 32 bit gyro cal, bmi088 and mmc5983 */
 #define AO_LOG_FORMAT_EASYTIMER_2      23      /* 32 byte typed easytimer records with 32 bit gyro cal, bmi088 and mmc5983 */
 #define AO_LOG_FORMAT_EASYMEGA_3       24      /* 32 byte typed telemega records with 32 bit gyro cal, bmi088 and mmc5983 */
+#define AO_LOG_FORMAT_TELEMEGA_7       25      /* 32 byte typed telemega records with 32 bit gyro cal, bmi088 and mmc5983, 30V max pyro */
 #define AO_LOG_FORMAT_NONE             127     /* No log at all */
 
 /* Return the flight number from the given log slot, 0 if none, -slot on failure */
@@ -593,7 +594,7 @@ struct ao_log_timer {
        } u;
 };
 
-#if AO_LOG_FORMAT == AO_LOG_FOMAT_TELEMEGA_OLD || AO_LOG_FORMAT == AO_LOG_FORMAT_TELEMEGA || AO_LOG_FORMAT == AO_LOG_FORMAT_TELEMEGA_3 || AO_LOG_FORMAT == AO_LOG_FORMAT_EASYMEGA_2 || AO_LOG_FORMAT == AO_LOG_FORMAT_TELEMEGA_4 || AO_LOG_FORMAT == AO_LOG_FORMAT_TELEMEGA_5 || AO_LOG_FORMAT == AO_LOG_FORMAT_TELEMEGA_6 || AO_LOG_FORMAT == AO_LOG_FORMAT_EASYMEGA_3
+#if AO_LOG_FORMAT == AO_LOG_FOMAT_TELEMEGA_OLD || AO_LOG_FORMAT == AO_LOG_FORMAT_TELEMEGA || AO_LOG_FORMAT == AO_LOG_FORMAT_TELEMEGA_3 || AO_LOG_FORMAT == AO_LOG_FORMAT_EASYMEGA_2 || AO_LOG_FORMAT == AO_LOG_FORMAT_TELEMEGA_4 || AO_LOG_FORMAT == AO_LOG_FORMAT_TELEMEGA_5 || AO_LOG_FORMAT == AO_LOG_FORMAT_TELEMEGA_6 || AO_LOG_FORMAT == AO_LOG_FORMAT_EASYMEGA_3 || AO_LOG_FORMAT == AO_LOG_FORMAT_TELEMEGA_7
 typedef struct ao_log_mega ao_log_type;
 #endif
 
index 5f09344af8915dd273b4ab044ca95fdc5a1df49d..b7aceef6792cc4646eb069917c1f348752c1ead0 100644 (file)
@@ -76,6 +76,8 @@ radio_cmac_send(uint8_t len)
  * Receive and validate an incoming packet
  */
 
+int8_t ao_radio_cmac_last_rssi;
+
 static int8_t
 radio_cmac_recv(uint8_t len, AO_TICK_TYPE timeout) 
 {
@@ -92,6 +94,8 @@ radio_cmac_recv(uint8_t len, AO_TICK_TYPE timeout)
                return AO_RADIO_CMAC_TIMEOUT;
        }
 
+       ao_radio_cmac_last_rssi = ao_radio_rssi;
+
        if (!(cmac_data[len + AO_CMAC_KEY_LEN +1] & AO_RADIO_STATUS_CRC_OK))
                return AO_RADIO_CMAC_CRC_ERROR;
 
index 2977cd3e69960076b5fef9e5eac53891bae586f5..1bea8a03479e71f0a10ce1ae53a9608d30633696 100644 (file)
@@ -24,7 +24,7 @@
 #define AO_CMAC_KEY_LEN                AO_AES_LEN
 #define AO_CMAC_MAX_LEN                (128 - AO_CMAC_KEY_LEN)
 
-extern int8_t ao_radio_cmac_rssi;
+extern int8_t ao_radio_cmac_rssi, ao_radio_cmac_last_rssi;
 
 int8_t
 ao_radio_cmac_send(void *packet, uint8_t len);
index 7f74f81194bcca5b1782c111c1d63b711b130e29..a7c5e252ac461a8b1cad48394535151edc237b45 100644 (file)
@@ -188,8 +188,6 @@ ao_flushc(FILE *ignore)
 
 static FILE __stdio = FDEV_SETUP_STREAM(ao_putc, ao_getc, ao_flushc, _FDEV_SETUP_RW);
 
-#ifdef PICOLIBC_STDIO_GLOBALS
-
 #ifdef __strong_reference
 #define STDIO_ALIAS(x) __strong_reference(stdin, x);
 #else
@@ -199,9 +197,3 @@ static FILE __stdio = FDEV_SETUP_STREAM(ao_putc, ao_getc, ao_flushc, _FDEV_SETUP
 FILE *const stdin = &__stdio;
 STDIO_ALIAS(stdout);
 STDIO_ALIAS(stderr);
-
-#else
-
-FILE *const __iob[3] = { &__stdio, &__stdio, &__stdio };
-
-#endif
index 8586efd548f59cce09f4aa4b0de43a439471ba5b..1e0828334fd467c3ae29cb640b75f8d82b0a814c 100644 (file)
@@ -142,7 +142,7 @@ ao_send_mega_sensor(void)
 #if AO_LOG_NORMALIZED
 #if AO_LOG_FORMAT == AO_LOG_FORMAT_TELEMEGA_5
        telemetry.generic.type = AO_TELEMETRY_MEGA_NORM_MPU6000_MMC5983;
-#elif AO_LOG_FORMAT == AO_LOG_FORMAT_TELEMEGA_6
+#elif AO_LOG_FORMAT == AO_LOG_FORMAT_TELEMEGA_6 || AO_LOG_FORMAT == AO_LOG_FORMAT_TELEMEGA_7
        telemetry.generic.type = AO_TELEMETRY_MEGA_NORM_BMI088_MMC5983;
 #else
 #error unknown normalized log type
index 983a99b8fd1cba7ef4adf0b4d41a047f9bb5f1e8..3f5f270b523d7df4759d1854c601ce90575ca649 100644 (file)
@@ -204,7 +204,8 @@ struct ao_telemetry_mega_sensor {
        /* 32 */
 };
 
-#define AO_TELEMETRY_MEGA_DATA         0x09
+#define AO_TELEMETRY_MEGA_DATA_15V             0x09    /* 100k / 27k */
+#define AO_TELEMETRY_MEGA_DATA_30V             0x15    /* 100k / 12k */
 
 struct ao_telemetry_mega_data {
        uint16_t        serial;         /*  0 */
index dc30e19702fa1f8b467c540e4409d1e9c94630fd..610fa63120a5a37082eff8a2e8b596c3adaf6e97 100644 (file)
@@ -33,7 +33,7 @@ ao_report(void)
                        flush();
                        c = ao_up_getchar();
                }
-               putchar(c);
+               putchar((char) c);
        }
 }
 
index 22559aaff085d0df5405f7e9c445d701b4a5055d..b9ab97e7cd0333db208ebd88140ab67a02e3787d 100644 (file)
@@ -85,6 +85,7 @@ main(void)
        for (;;) {
                cli();
 #pragma GCC diagnostic ignored "-Wconversion"
+#pragma GCC diagnostic ignored "-Wsign-conversion"
                set_sleep_mode((uint8_t) SLEEP_MODE_PWR_DOWN);
                sleep_mode();
        }
index 776811586fdfb467f91078289ee2bb88991248e9..3b0f0bad048576b513e01389bc8e8280105ce87f 100644 (file)
@@ -35,7 +35,7 @@ IDPRODUCT=0x000a
 
 CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS)
 
-LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stm -Taltos-loader.ld -n
+LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stm -Taltos-loader.ld -n --crt0=minimal
 
 PROGNAME=$(HARDWARE)-altos-flash
 PROG=$(PROGNAME)-$(VERSION).elf
diff --git a/src/telebt-v4.0-seeed/.gitignore b/src/telebt-v4.0-seeed/.gitignore
new file mode 100644 (file)
index 0000000..d1cf232
--- /dev/null
@@ -0,0 +1,4 @@
+ao_product.h
+*.bin
+*.ihx
+*.elf
diff --git a/src/telebt-v4.0-seeed/Makefile b/src/telebt-v4.0-seeed/Makefile
new file mode 100644 (file)
index 0000000..16f2e1d
--- /dev/null
@@ -0,0 +1,88 @@
+#
+# AltOS build
+#
+#
+
+include ../stmf0/Makefile.defs
+
+INC = \
+       ao.h \
+       ao_arch.h \
+       ao_arch_funcs.h \
+       ao_boot.h \
+       ao_pins.h \
+       ao_product.h \
+       ao_cc1200_CC1200.h \
+       ao_task.h \
+       ao_rn4678.h \
+       stm32f0.h \
+       Makefile
+
+ALTOS_SRC = \
+       ao_boot_chain.c \
+       ao_interrupt.c \
+       ao_product.c \
+       ao_romconfig.c \
+       ao_cmd.c \
+       ao_config.c \
+       ao_data.c \
+       ao_task.c \
+       ao_led_stmf0.c \
+       ao_stdio.c \
+       ao_panic.c \
+       ao_timer.c \
+       ao_mutex.c \
+       ao_serial_stm.c \
+       ao_rn4678.c \
+       ao_freq.c \
+       ao_dma_stm.c \
+       ao_spi_stm.c \
+       ao_cc1200.c \
+       ao_adc_stm.c \
+       ao_usb_stm.c \
+       ao_exti_stm.c \
+       ao_convert_volt.c \
+       ao_packet_master.c \
+       ao_packet.c \
+       ao_monitor.c \
+       ao_send_packet.c
+
+PRODUCT=TeleBT-v4.0
+PRODUCT_DEF=-DTELEBT_V_4_0
+IDPRODUCT=0x000e
+
+CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS)
+
+PROGNAME=telebt-v4.0-seeed
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+FLASH_PROG=flash-loader/$(PROGNAME)-altos-flash-$(VERSION).elf
+BOTH_HEX=$(PROGNAME)-combined-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_telebt_seeed.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX) $(BOTH_HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+       $(call quiet,CC) $(LDFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+$(BOTH_HEX): $(PROG) $(FLASH_PROG)
+       ../../ao-tools/ao-elftohex/ao-elftohex -n --output=$@ $(FLASH_PROG) $(PROG)
+
+$(FLASH_PROG): FRC
+       +cd flash-loader && make
+
+$(OBJ): $(INC)
+
+distclean:     clean
+
+clean:
+       rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx $(PROGNAME)-*.map
+       rm -f ao_product.h
+
+install:
+
+uninstall:
+
+FRC:
diff --git a/src/telebt-v4.0-seeed/ao_pins.h b/src/telebt-v4.0-seeed/ao_pins.h
new file mode 100644 (file)
index 0000000..312864d
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * Copyright © 2017 Bdale Garbee <bdale@gag.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.
+ *
+ * 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.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define AO_STACK_SIZE          504
+
+#define AO_HSE                  32000000
+#define AO_RCC_CFGR_PLLMUL     STM_RCC_CFGR_PLLMUL_3
+#define AO_RCC_CFGR2_PLLDIV    STM_RCC_CFGR2_PREDIV_2
+#define AO_PLLMUL              3
+#define AO_PLLDIV              2
+
+/* HCLK = 48MHz */
+#define AO_AHB_PRESCALER        1
+#define AO_RCC_CFGR_HPRE_DIV    STM_RCC_CFGR_HPRE_DIV_1
+
+/* APB = 48MHz */
+#define AO_APB_PRESCALER        1
+#define AO_RCC_CFGR_PPRE_DIV    STM_RCC_CFGR_PPRE_DIV_1
+
+#define HAS_USB                        1
+#define AO_USB_DIRECTIO                0
+#define AO_PA11_PA12_RMP       0
+
+#define IS_FLASH_LOADER        0
+
+/*
+ * Serial ports
+ */
+#define HAS_SERIAL_1           0
+#define USE_SERIAL_1_STDIN     0
+#define SERIAL_1_PB6_PB7       0
+#define SERIAL_1_PA9_PA10      0
+
+#define HAS_SERIAL_2           1
+#define USE_SERIAL_2_STDIN     1
+#define DELAY_SERIAL_2_STDIN   1
+#define USE_SERIAL_2_FLOW      1
+#define USE_SERIAL_2_SW_FLOW   0
+#define SERIAL_2_PA2_PA3       1
+#define SERIAL_2_PD5_PD6       0
+#define SERIAL_2_PORT_RTS      (&stm_gpioa)
+#define SERIAL_2_PIN_RTS       1
+#define SERIAL_2_PORT_CTS      (&stm_gpioa)
+#define SERIAL_2_PIN_CTS       0
+
+#define AO_CONFIG_MAX_SIZE     1024
+
+#define HAS_EEPROM             0
+#define USE_INTERNAL_FLASH     0
+#define USE_EEPROM_CONFIG      0
+#define USE_STORAGE_CONFIG     0
+#define HAS_BEEP               0
+#define HAS_BATTERY_REPORT     0
+#define HAS_RADIO              1
+#define HAS_TELEMETRY          0
+#define HAS_APRS               0
+#define HAS_ACCEL              0
+#define HAS_AES                        0
+
+#define HAS_SPI_1              1
+#define SPI_1_PA5_PA6_PA7      1       /* CC1200 */
+#define SPI_1_PB3_PB4_PB5      0
+#define SPI_1_PE13_PE14_PE15   0
+#define SPI_1_OSPEEDR          STM_OSPEEDR_HIGH
+
+#define HAS_SPI_2              0
+#define SPI_2_PB13_PB14_PB15   0
+#define SPI_2_PD1_PD3_PD4      0
+#define SPI_2_OSPEEDR          STM_OSPEEDR_HIGH
+
+#define HAS_I2C_1              0
+#define I2C_1_PB8_PB9          0
+
+#define HAS_I2C_2              0
+#define I2C_2_PB10_PB11                0
+
+#define PACKET_HAS_SLAVE       0
+#define PACKET_HAS_MASTER      1
+
+#define LOW_LEVEL_DEBUG                0
+
+#define LED_PORT_0_ENABLE      STM_RCC_AHBENR_IOPBEN
+#define LED_PORT_1_ENABLE      STM_RCC_AHBENR_IOPCEN
+#define LED_PORT_0             (&stm_gpiob)
+#define LED_PORT_1             (&stm_gpioc)
+#define LED_PORT_0_SHIFT       0
+#define LED_PORT_1_SHIFT       0
+#define LED_PIN_RED            (0 + LED_PORT_0_SHIFT)
+#define LED_PIN_BLUE           (15 + LED_PORT_1_SHIFT)
+#define AO_LED_RED             (1 << LED_PIN_RED)
+#define AO_LED_BLUE            (1 << LED_PIN_BLUE)
+#define LED_PORT_0_MASK                (AO_LED_RED)
+#define LED_PORT_1_MASK                (AO_LED_BLUE)
+#define AO_BT_LED              AO_LED_BLUE
+
+#define AO_FAIL_ADC    1
+#define AO_FAIL_RADIO  2
+#define AO_FAIL_BT     3
+
+#define ao_bt_panic(x) ao_panic(AO_FAIL_BT)
+
+#define LEDS_AVAILABLE         (AO_LED_RED | AO_LED_BLUE)
+
+#define HAS_GPS                        0
+#define HAS_FLIGHT             0
+#define HAS_ADC                        1
+#define HAS_ADC_TEMP           0
+#define HAS_LOG                        0
+#undef HAS_BATTERY_REPORT
+#define HAS_BATTERY_REPORT     1
+
+/*
+ * ADC
+ */
+#define AO_DATA_RING           32
+#define AO_ADC_NUM_SENSE       2
+
+struct ao_adc {
+       int16_t                 v_batt;
+};
+
+#define AO_ADC_DUMP(p) \
+       printf("tick: %5lu batt %5d\n", \
+              (p)->tick, \
+              (p)->adc.v_batt);
+
+#define AO_ADC_V_BATT          4
+#define AO_ADC_V_BATT_PORT     (&stm_gpioa)
+#define AO_ADC_V_BATT_PIN      4
+
+#define AO_ADC_RCC_AHBENR      ((1 << STM_RCC_AHBENR_IOPAEN))
+
+#define AO_NUM_ADC_PIN         1
+
+#define AO_ADC_PIN0_PORT       AO_ADC_V_BATT_PORT
+#define AO_ADC_PIN0_PIN                AO_ADC_V_BATT_PIN
+#define AO_ADC_PIN0_CH         AO_ADC_V_BATT_PIN
+
+#define AO_NUM_ADC             (AO_NUM_ADC_PIN)
+
+#define AO_ADC_SQ1             AO_ADC_V_BATT
+
+/*
+ * Voltage divider on ADC battery sampler
+ */
+#define AO_BATTERY_DIV_PLUS    51      /* 5.1k */
+#define AO_BATTERY_DIV_MINUS   100     /* 10k */
+
+/*
+ * ADC reference in decivolts
+ */
+#define AO_ADC_REFERENCE_DV    33
+
+/*
+ * RN4678
+ */
+#define HAS_RN                 1
+
+#define ao_serial_rn_getchar   ao_serial2_getchar
+#define ao_serial_rn_putchar   ao_serial2_putchar
+#define _ao_serial_rn_pollchar _ao_serial2_pollchar
+#define _ao_serial_rn_sleep_for        _ao_serial2_sleep_for
+#define ao_serial_rn_set_speed ao_serial2_set_speed
+#define ao_serial_rn_drain     ao_serial2_drain
+#define ao_serial_rn_rx_fifo   (ao_stm_usart2.rx_fifo)
+
+/* Pin 5. BM70 P2_2 */
+#define AO_RN_SW_BTN_PORT      (&stm_gpioc)
+#define AO_RN_SW_BTN_PIN       14
+
+/* Pin 12. BM70 P1_5. Status indication along with P0_4 */
+#define AO_RN_P1_5_PORT                (&stm_gpiob)
+#define AO_RN_P1_5_PIN         6
+
+/* Pin 21. BM70 RST_N. */
+#define AO_RN_RST_N_PORT       (&stm_gpioa)
+#define AO_RN_RST_N_PIN                15
+
+/* Pin 22. BM70 RXD. */
+#define AO_RN_RXD_PORT         (&stm_gpioa)
+#define AO_RN_RXD_PIN          2
+
+/* Pin 23. BM70 TXD. */
+#define AO_RN_TXD_PORT         (&stm_gpioa)
+#define AO_RN_TXD_PIN          3
+
+/* Pin 24. BM70 P3_1/RSSI_IND. */
+#define AO_RN_P3_1_PORT                (&stm_gpiob)
+#define AO_RN_P3_1_PIN         2
+
+/* Pin 29. BM70 P0_7. */
+#define AO_RN_P3_7_PORT                (&stm_gpiob)
+#define AO_RN_P3_7_PIN         12
+
+/*
+ * Radio (cc1200)
+ */
+
+/* gets pretty close to 434.550 */
+
+#define AO_RADIO_CAL_DEFAULT   5695485
+
+#define AO_FEC_DEBUG           0
+#define AO_CC1200_SPI_CS_PORT  (&stm_gpiob)
+#define AO_CC1200_SPI_CS_PIN   11
+#define AO_CC1200_SPI_BUS      AO_SPI_1_PA5_PA6_PA7
+#define AO_CC1200_SPI          stm_spi1
+
+#define AO_CC1200_INT_PORT             (&stm_gpiob)
+#define AO_CC1200_INT_PIN              (10)
+
+#define AO_CC1200_INT_GPIO     2
+#define AO_CC1200_INT_GPIO_IOCFG       CC1200_IOCFG2
+
+#define HAS_BOOT_RADIO         0
+
+/* Monitor bits */
+#define HAS_MONITOR            1
+#define LEGACY_MONITOR         0
+#define AO_MONITOR_LED         AO_LED_RED
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/telebt-v4.0-seeed/ao_telebt_seeed.c b/src/telebt-v4.0-seeed/ao_telebt_seeed.c
new file mode 100644 (file)
index 0000000..8e27ded
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright © 2015 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.
+ *
+ * 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.h>
+#include <ao_exti.h>
+#include <ao_packet.h>
+#include <ao_send_packet.h>
+#include <ao_usb.h>
+#include <ao_rn4678.h>
+
+static void
+ao_validate(void)
+{
+       uint8_t data;
+       int16_t decivolt;
+       int i;
+
+       ao_config_get();
+
+       /* Check the battery voltage */
+       for (i = 0; i < 10; i++) {
+               data = ao_data_head;
+               do {
+                       ao_sleep((void *) &ao_data_head);
+               } while (ao_data_head == data);
+       }
+       decivolt = ao_battery_decivolt(ao_data_ring[data].adc.v_batt);
+       if (decivolt < 35 || 55 < decivolt)
+               ao_panic(AO_FAIL_ADC);
+
+       if (!ao_radio_post())
+               ao_panic(AO_FAIL_RADIO);
+
+       /*
+        * Wait for BT module to come online. That will panic if it
+        * doesn't work
+        */
+       for (;;) {
+               if (ao_num_stdios == 2)
+                       break;
+               ao_delay(AO_SEC_TO_TICKS(1));
+       }
+
+       ao_led_on(AO_LED_BLUE);
+
+       ao_exit();
+}
+
+struct ao_task ao_validate_task;
+
+int
+main(void)
+{
+       ao_clock_init();
+
+       ao_task_init();
+       ao_led_init();
+       ao_led_off(LEDS_AVAILABLE);
+       ao_timer_init();
+
+       ao_spi_init();
+       ao_dma_init();
+       ao_exti_init();
+
+       ao_adc_init();
+       ao_cmd_init();
+//     ao_send_packet_init();
+
+       ao_usb_init();
+       ao_serial_init();
+
+       ao_radio_init();
+//     ao_packet_master_init();
+//     ao_monitor_init();
+       ao_rn4678_init();
+
+       ao_config_init();
+
+       ao_add_task(&ao_validate_task, ao_validate, "validate");
+
+       ao_start_scheduler();
+       return 0;
+}
diff --git a/src/telebt-v4.0-seeed/flash-loader/Makefile b/src/telebt-v4.0-seeed/flash-loader/Makefile
new file mode 100644 (file)
index 0000000..e44f379
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=telebt-v4.0-seeed
+include $(TOPDIR)/stmf0/Makefile-flash.defs
diff --git a/src/telebt-v4.0-seeed/flash-loader/ao_pins.h b/src/telebt-v4.0-seeed/flash-loader/ao_pins.h
new file mode 100644 (file)
index 0000000..8f4d6f8
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright © 2013 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.
+ *
+ * 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.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#include <ao_flash_stm_pins.h>
+
+/* ground U7 pin 30 to force bootload */
+
+#define AO_BOOT_PIN                    1
+#define AO_BOOT_APPLICATION_GPIO       stm_gpioa
+#define AO_BOOT_APPLICATION_PIN                9
+#define AO_BOOT_APPLICATION_VALUE      1
+#define AO_BOOT_APPLICATION_MODE       AO_EXTI_MODE_PULL_UP
+
+/* USB */
+#define HAS_USB                        1
+#define AO_USB_DIRECTIO                0
+#define AO_PA11_PA12_RMP       0
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/telegps-v4.0-seeed/ao_pins.h b/src/telegps-v4.0-seeed/ao_pins.h
new file mode 100644 (file)
index 0000000..a5ea6ea
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * Copyright © 2024 Bdale Garbee <bdale@gag.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.
+ *
+ * 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.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define LED_PORT_ENABLE STM_RCC_AHBENR_IOPBEN
+#define LED_PORT        (&stm_gpiob)
+#define LED_PIN_GREEN   5
+#define AO_LED_GREEN    (1 << LED_PIN_GREEN)
+#define AO_LED_PANIC   AO_LED_GREEN
+#define AO_LED_GPS_LOCK        AO_LED_GREEN
+
+#define LEDS_AVAILABLE  (AO_LED_GREEN)
+
+#define AO_STACK_SIZE          512
+
+#define IS_FLASH_LOADER                0
+#define HAS_BEEP              0
+
+#define AO_HSE                  16000000
+#define AO_RCC_CFGR_PLLMUL      STM_RCC_CFGR_PLLMUL_3
+#define AO_RCC_CFGR2_PLLDIV    STM_RCC_CFGR2_PREDIV_1
+#define AO_PLLMUL               3
+#define AO_PLLDIV               1
+
+/* HCLK = 48MHz */
+#define AO_AHB_PRESCALER        1
+#define AO_RCC_CFGR_HPRE_DIV    STM_RCC_CFGR_HPRE_DIV_1
+
+/* APB = 48MHz */
+#define AO_APB_PRESCALER        1
+#define AO_RCC_CFGR_PPRE_DIV    STM_RCC_CFGR_PPRE_DIV_1
+
+#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
+
+/* ADC */
+
+#define HAS_ADC                        1
+#define AO_ADC_PIN0_PORT        (&stm_gpiob)
+#define AO_ADC_PIN0_PIN         1
+#define AO_ADC_PIN0_CH          9
+
+#define AO_ADC_RCC_AHBENR       ((1 << STM_RCC_AHBENR_IOPBEN))
+
+#define ao_telemetry_battery_convert(a)        ((a) << 3)
+
+#define AO_NUM_ADC              1
+
+#define AO_DATA_RING           4
+
+/*
+ * Voltage divider on ADC battery sampler
+ */
+#define AO_BATTERY_DIV_PLUS    56      /* 5.6k */
+#define AO_BATTERY_DIV_MINUS   100     /* 10k */
+
+/*
+ * ADC reference in decivolts
+ */
+#define AO_ADC_REFERENCE_DV    33
+
+struct ao_adc {
+        int16_t                 v_batt;
+};
+
+#define AO_ADC_DUMP(p) \
+        printf("tick: %5lu batt: %5d\n", \
+               (p)->tick, \
+               (p)->adc.v_batt)
+
+/* SPI */
+#define HAS_SPI_1               1
+#define HAS_SPI_2               0
+#define SPI_1_PA5_PA6_PA7       1
+#define SPI_1_PB3_PB4_PB5       0
+#define SPI_1_OSPEEDR           STM_OSPEEDR_HIGH
+
+/* Flash */
+
+#define M25_MAX_CHIPS           1
+#define AO_M25_SPI_CS_PORT      (&stm_gpiob)
+#define AO_M25_SPI_CS_MASK      (1 << 0)
+#define AO_M25_SPI_BUS          AO_SPI_1_PA5_PA6_PA7
+
+/* Serial */
+#define HAS_SERIAL_1           0
+#define SERIAL_1_PB6_PB7       1
+#define USE_SERIAL_1_STDIN     0
+
+#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
+#define ao_gps_set_speed       ao_serial2_set_speed
+
+#define HAS_EEPROM             1
+#define USE_INTERNAL_FLASH     0
+#define HAS_RADIO              1
+#define HAS_TELEMETRY          1
+#define HAS_RDF                        1
+#define HAS_APRS               1
+
+#define HAS_GPS                        1
+#define HAS_FLIGHT             0
+#define HAS_LOG                        1
+#define FLIGHT_LOG_APPEND      1
+#define HAS_TRACKER            1
+#define LOG_ADC                        0
+
+#define AO_CONFIG_DEFAULT_APRS_INTERVAL                0
+#define AO_CONFIG_DEFAULT_RADIO_POWER          0xc0
+#define AO_LOG_FORMAT                          AO_LOG_FORMAT_TELEGPS
+
+/*
+ * GPS
+ */
+
+#define AO_SERIAL_SPEED_UBLOX  AO_SERIAL_SPEED_9600
+#define AO_UBLOX_VERSION       10
+
+/*
+ * Radio (cc1200)
+ */
+
+/* gets pretty close to 434.550 */
+
+#define AO_RADIO_CAL_DEFAULT    5695733
+
+#define AO_FEC_DEBUG            0
+#define AO_CC1200_SPI_CS_PORT   (&stm_gpioa)
+#define AO_CC1200_SPI_CS_PIN    1
+#define AO_CC1200_SPI_BUS       AO_SPI_1_PA5_PA6_PA7
+#define AO_CC1200_SPI           stm_spi1
+
+#define AO_CC1200_INT_PORT              (&stm_gpioa)
+#define AO_CC1200_INT_PIN               4
+
+#define AO_CC1200_INT_GPIO      2
+#define AO_CC1200_INT_GPIO_IOCFG        CC1200_IOCFG2
+
+#define HAS_BOOT_RADIO          0
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/telegps-v4.0-seeed/ao_telegps_seeed.c b/src/telegps-v4.0-seeed/ao_telegps_seeed.c
new file mode 100644 (file)
index 0000000..b9cc818
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright © 2013 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.
+ *
+ * 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.h>
+#include <ao_log.h>
+#include <ao_exti.h>
+#include <ao_tracker.h>
+
+#define AO_FAIL_FLASH  1
+#define AO_FAIL_ADC    2
+#define AO_FAIL_GPS    3
+#define AO_FAIL_RADIO  4
+
+static void
+ao_validate(void)
+{
+       static struct ao_telemetry_location     gps_data;
+       static struct ao_telemetry_satellite    gps_tracking_data;
+       uint8_t new;
+       uint8_t data;
+       int16_t decivolt;
+       AO_TICK_TYPE    gps_start;
+
+       /* Check the flash part */
+       ao_storage_setup();
+       if (ao_storage_total != 2 * 1024 * 1024)
+               ao_panic(AO_FAIL_FLASH);
+
+       /* Check the battery voltage */
+       data = ao_data_head;
+       do {
+               ao_sleep((void *) &ao_data_head);
+       } while (ao_data_head == data);
+       decivolt = ao_battery_decivolt(ao_data_ring[data].adc.v_batt);
+       if (decivolt < 35 && 55 < decivolt)
+               ao_panic(AO_FAIL_ADC);
+
+       /* Check to make sure GPS data is being received */
+       gps_start = ao_time();
+       for (;;) {
+               while ((new = ao_gps_new) == 0)
+                       ao_sleep_for(&ao_gps_new, AO_SEC_TO_TICKS(1));
+               ao_mutex_get(&ao_gps_mutex);
+               if (new & AO_GPS_NEW_DATA)
+                       memcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data));
+               if (new & AO_GPS_NEW_TRACKING)
+                       memcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data));
+               ao_gps_new = 0;
+               ao_mutex_put(&ao_gps_mutex);
+
+               if (new & AO_GPS_NEW_DATA) {
+                       if (gps_data.flags & AO_GPS_RUNNING)
+                               break;
+               }
+               if ((AO_TICK_SIGNED) (ao_time() - gps_start) > (AO_TICK_SIGNED) AO_SEC_TO_TICKS(10))
+                       ao_panic(AO_FAIL_GPS);
+       }
+
+       if (!ao_radio_post())
+               ao_panic(AO_FAIL_RADIO);
+
+       ao_led_on(LEDS_AVAILABLE);
+       ao_exit();
+}
+
+struct ao_task ao_validate_task;
+
+int
+main(void)
+{
+       ao_clock_init();
+       ao_task_init();
+       ao_cmd_init();
+       ao_config_init();
+
+       ao_led_init();
+       ao_led_off(LEDS_AVAILABLE);
+
+       /* internal systems */
+       ao_timer_init();
+       ao_dma_init();
+       ao_exti_init();
+
+       /* SoC hardware */
+       ao_adc_init();
+       ao_serial_init();
+       ao_spi_init();
+       ao_usb_init();
+
+       /* External hardware */
+       ao_storage_init();
+       ao_radio_init();
+       ao_gps_init();
+
+
+       ao_add_task(&ao_validate_task, ao_validate, "validate");
+
+       ao_start_scheduler();
+}
diff --git a/src/telegps-v4.0-seeed/flash-loader/.gitignore b/src/telegps-v4.0-seeed/flash-loader/.gitignore
new file mode 100644 (file)
index 0000000..7bbed04
--- /dev/null
@@ -0,0 +1,2 @@
+*.elf
+*.bin
diff --git a/src/telegps-v4.0-seeed/flash-loader/ao_pins.h b/src/telegps-v4.0-seeed/flash-loader/ao_pins.h
new file mode 100644 (file)
index 0000000..c7bf4e7
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright © 2024 Bdale Garbee <bdale@gag.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.
+ *
+ * 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.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#include <ao_flash_stm_pins.h>
+
+/* Pin 5 on debug connector */
+
+#define AO_BOOT_PIN            1
+#define AO_BOOT_APPLICATION_GPIO       stm_gpiob
+#define AO_BOOT_APPLICATION_PIN                6
+#define AO_BOOT_APPLICATION_VALUE      1
+#define AO_BOOT_APPLICATION_MODE       AO_EXTI_MODE_PULL_UP
+
+#define HAS_USB                        1
+#define AO_USB_DIRECTIO                0
+#define AO_PA11_PA12_RMP       1
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/telegps-v4.0/Makefile b/src/telegps-v4.0/Makefile
new file mode 100644 (file)
index 0000000..0b1535c
--- /dev/null
@@ -0,0 +1,88 @@
+#
+# AltOS build
+#
+#
+
+TOPDIR=..
+
+include $(TOPDIR)/stmf0/Makefile.defs
+
+INC = \
+       ao.h \
+       ao_arch.h \
+       ao_arch_funcs.h \
+       ao_pins.h \
+       ao_product.h \
+       ao_tracker.h \
+       ao_task.h \
+       ao_cc1200.h \
+       ao_fec.h \
+       stm32f0.h \
+       Makefile
+
+
+ALTOS_SRC = \
+       ao_adc_stm.c \
+       ao_led_stmf0.c \
+       ao_interrupt.c \
+       ao_boot_chain.c \
+       ao_product.c \
+       ao_romconfig.c \
+       ao_cmd.c \
+       ao_config.c \
+       ao_task.c \
+       ao_stdio.c \
+       ao_panic.c \
+       ao_timer.c \
+       ao_mutex.c \
+       ao_freq.c \
+       ao_dma_stm.c \
+       ao_spi_stm.c \
+       ao_usb_stm.c \
+       ao_exti_stm.c \
+       ao_serial_stm.c \
+       ao_gps_ublox.c \
+       ao_gps_show.c \
+       ao_cc1200.c \
+       ao_aprs.c \
+       ao_tracker.c \
+       ao_telemetry.c \
+       ao_storage.c \
+       ao_m25.c \
+       ao_log.c \
+       ao_log_gps.c \
+       ao_distance.c \
+       ao_sqrt.c \
+       ao_data.c \
+       ao_convert_volt.c \
+       $(SAMPLE_PROFILE)
+
+PRODUCT=TeleGPS-v4.0
+PRODUCT_DEF=-DTELEGPS
+IDPRODUCT=0x0025
+
+CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) $(PROFILE_DEF)
+
+PROGNAME=telegps-v4.0
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_telegps.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+       $(call quiet,CC) $(LDFLAGS) -o $(PROG) $(OBJ) $(LIBS) -Wl,-Map=$(PROGNAME)-$(VERSION).map
+
+$(OBJ): $(INC)
+
+distclean:     clean
+
+clean:
+       rm -f *.o ao_serial_stm.h $(PROGNAME)-*.elf $(PROGNAME)-*.ihx $(PROGNAME)-*.map
+       rm -f ao_product.h
+
+install:
+
+uninstall:
diff --git a/src/telegps-v4.0/ao_pins.h b/src/telegps-v4.0/ao_pins.h
new file mode 100644 (file)
index 0000000..a5ea6ea
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * Copyright © 2024 Bdale Garbee <bdale@gag.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.
+ *
+ * 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.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define LED_PORT_ENABLE STM_RCC_AHBENR_IOPBEN
+#define LED_PORT        (&stm_gpiob)
+#define LED_PIN_GREEN   5
+#define AO_LED_GREEN    (1 << LED_PIN_GREEN)
+#define AO_LED_PANIC   AO_LED_GREEN
+#define AO_LED_GPS_LOCK        AO_LED_GREEN
+
+#define LEDS_AVAILABLE  (AO_LED_GREEN)
+
+#define AO_STACK_SIZE          512
+
+#define IS_FLASH_LOADER                0
+#define HAS_BEEP              0
+
+#define AO_HSE                  16000000
+#define AO_RCC_CFGR_PLLMUL      STM_RCC_CFGR_PLLMUL_3
+#define AO_RCC_CFGR2_PLLDIV    STM_RCC_CFGR2_PREDIV_1
+#define AO_PLLMUL               3
+#define AO_PLLDIV               1
+
+/* HCLK = 48MHz */
+#define AO_AHB_PRESCALER        1
+#define AO_RCC_CFGR_HPRE_DIV    STM_RCC_CFGR_HPRE_DIV_1
+
+/* APB = 48MHz */
+#define AO_APB_PRESCALER        1
+#define AO_RCC_CFGR_PPRE_DIV    STM_RCC_CFGR_PPRE_DIV_1
+
+#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
+
+/* ADC */
+
+#define HAS_ADC                        1
+#define AO_ADC_PIN0_PORT        (&stm_gpiob)
+#define AO_ADC_PIN0_PIN         1
+#define AO_ADC_PIN0_CH          9
+
+#define AO_ADC_RCC_AHBENR       ((1 << STM_RCC_AHBENR_IOPBEN))
+
+#define ao_telemetry_battery_convert(a)        ((a) << 3)
+
+#define AO_NUM_ADC              1
+
+#define AO_DATA_RING           4
+
+/*
+ * Voltage divider on ADC battery sampler
+ */
+#define AO_BATTERY_DIV_PLUS    56      /* 5.6k */
+#define AO_BATTERY_DIV_MINUS   100     /* 10k */
+
+/*
+ * ADC reference in decivolts
+ */
+#define AO_ADC_REFERENCE_DV    33
+
+struct ao_adc {
+        int16_t                 v_batt;
+};
+
+#define AO_ADC_DUMP(p) \
+        printf("tick: %5lu batt: %5d\n", \
+               (p)->tick, \
+               (p)->adc.v_batt)
+
+/* SPI */
+#define HAS_SPI_1               1
+#define HAS_SPI_2               0
+#define SPI_1_PA5_PA6_PA7       1
+#define SPI_1_PB3_PB4_PB5       0
+#define SPI_1_OSPEEDR           STM_OSPEEDR_HIGH
+
+/* Flash */
+
+#define M25_MAX_CHIPS           1
+#define AO_M25_SPI_CS_PORT      (&stm_gpiob)
+#define AO_M25_SPI_CS_MASK      (1 << 0)
+#define AO_M25_SPI_BUS          AO_SPI_1_PA5_PA6_PA7
+
+/* Serial */
+#define HAS_SERIAL_1           0
+#define SERIAL_1_PB6_PB7       1
+#define USE_SERIAL_1_STDIN     0
+
+#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
+#define ao_gps_set_speed       ao_serial2_set_speed
+
+#define HAS_EEPROM             1
+#define USE_INTERNAL_FLASH     0
+#define HAS_RADIO              1
+#define HAS_TELEMETRY          1
+#define HAS_RDF                        1
+#define HAS_APRS               1
+
+#define HAS_GPS                        1
+#define HAS_FLIGHT             0
+#define HAS_LOG                        1
+#define FLIGHT_LOG_APPEND      1
+#define HAS_TRACKER            1
+#define LOG_ADC                        0
+
+#define AO_CONFIG_DEFAULT_APRS_INTERVAL                0
+#define AO_CONFIG_DEFAULT_RADIO_POWER          0xc0
+#define AO_LOG_FORMAT                          AO_LOG_FORMAT_TELEGPS
+
+/*
+ * GPS
+ */
+
+#define AO_SERIAL_SPEED_UBLOX  AO_SERIAL_SPEED_9600
+#define AO_UBLOX_VERSION       10
+
+/*
+ * Radio (cc1200)
+ */
+
+/* gets pretty close to 434.550 */
+
+#define AO_RADIO_CAL_DEFAULT    5695733
+
+#define AO_FEC_DEBUG            0
+#define AO_CC1200_SPI_CS_PORT   (&stm_gpioa)
+#define AO_CC1200_SPI_CS_PIN    1
+#define AO_CC1200_SPI_BUS       AO_SPI_1_PA5_PA6_PA7
+#define AO_CC1200_SPI           stm_spi1
+
+#define AO_CC1200_INT_PORT              (&stm_gpioa)
+#define AO_CC1200_INT_PIN               4
+
+#define AO_CC1200_INT_GPIO      2
+#define AO_CC1200_INT_GPIO_IOCFG        CC1200_IOCFG2
+
+#define HAS_BOOT_RADIO          0
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/telegps-v4.0/ao_telegps.c b/src/telegps-v4.0/ao_telegps.c
new file mode 100644 (file)
index 0000000..1ba67f6
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright © 2013 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.
+ *
+ * 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.h>
+#include <ao_log.h>
+#include <ao_exti.h>
+#include <ao_tracker.h>
+
+int
+main(void)
+{
+       ao_clock_init();
+       ao_task_init();
+       ao_cmd_init();
+       ao_config_init();
+
+       ao_led_init();
+       ao_led_on(LEDS_AVAILABLE);
+
+       /* internal systems */
+       ao_timer_init();
+       ao_dma_init();
+       ao_exti_init();
+
+       /* SoC hardware */
+       ao_adc_init();
+       ao_serial_init();
+       ao_spi_init();
+       ao_usb_init();
+
+       /* External hardware */
+       ao_storage_init();
+       ao_radio_init();
+       ao_gps_init();
+
+       /* Services */
+       ao_log_init();
+       ao_telemetry_init();
+       ao_tracker_init();
+
+       ao_led_off(LEDS_AVAILABLE);
+
+       ao_start_scheduler();
+}
diff --git a/src/telegps-v4.0/flash-loader/.gitignore b/src/telegps-v4.0/flash-loader/.gitignore
new file mode 100644 (file)
index 0000000..7bbed04
--- /dev/null
@@ -0,0 +1,2 @@
+*.elf
+*.bin
diff --git a/src/telegps-v4.0/flash-loader/Makefile b/src/telegps-v4.0/flash-loader/Makefile
new file mode 100644 (file)
index 0000000..499d976
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=telegps-v4.0
+include $(TOPDIR)/stmf0/Makefile-flash.defs
diff --git a/src/telegps-v4.0/flash-loader/ao_pins.h b/src/telegps-v4.0/flash-loader/ao_pins.h
new file mode 100644 (file)
index 0000000..c7bf4e7
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright © 2024 Bdale Garbee <bdale@gag.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.
+ *
+ * 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.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#include <ao_flash_stm_pins.h>
+
+/* Pin 5 on debug connector */
+
+#define AO_BOOT_PIN            1
+#define AO_BOOT_APPLICATION_GPIO       stm_gpiob
+#define AO_BOOT_APPLICATION_PIN                6
+#define AO_BOOT_APPLICATION_VALUE      1
+#define AO_BOOT_APPLICATION_MODE       AO_EXTI_MODE_PULL_UP
+
+#define HAS_USB                        1
+#define AO_USB_DIRECTIO                0
+#define AO_PA11_PA12_RMP       1
+
+#endif /* _AO_PINS_H_ */
index cc17a2219b723f5245f80e66cd3789dc3991b838..fae076adfe5ccffc3ed1d0b2e50e2f2acb419df4 100644 (file)
@@ -48,7 +48,8 @@ ALTOS_SRC = \
        ao_timer.c \
        ao_mutex.c \
        ao_freq.c \
-       ao_adc_single_stm.c \
+       ao_adc_stm.c \
+       ao_data.c \
        ao_dma_stm.c \
        ao_spi_stm.c \
        ao_beep_stm.c \
@@ -77,7 +78,7 @@ ALTOS_SRC = \
        BitstreamVeraSans-Roman-24.c \
        BitstreamVeraSans-Roman-10.c \
        BitstreamVeraSans-Roman-12.c \
-       BenguiatGothicStd-Bold-26.c \
+       BenguiatGothicStd-Bold-24.c \
        ao_quadrature.c \
        ao_button.c \
        ao_event.c \
@@ -122,7 +123,7 @@ BitstreamVeraSans-Roman-58.c: ao_font.h
 BitstreamVeraSans-Roman-24.c: ao_font.h
 BitstreamVeraSans-Roman-10.c: ao_font.h
 BitstreamVeraSans-Roman-12.c: ao_font.h
-BenguiatGothicStd-Bold-26.c: ao_font.h
+BenguiatGothicStd-Bold-24.c: ao_font.h
 
 install:
 
index dc6b030edd471561f973fae0902dc6beb15edcf2..2f4c1dbed26830dd27ab9a4a67c09092fd01db6c 100644 (file)
@@ -24,6 +24,7 @@
 #include <ao_st7565.h>
 #include <ao_adc_single.h>
 #include <ao_pwm.h>
+#include <limits.h>
 
 #define WIDTH  AO_ST7565_WIDTH
 #define HEIGHT AO_ST7565_HEIGHT
@@ -40,8 +41,8 @@ static struct ao_bitmap fb = {
 };
 
 static const struct ao_transform logo_transform = {
-       .x_scale = 48, .x_off = 2,
-       .y_scale = 48, .y_off = 0,
+       .x_scale = 40, .x_off = 8,
+       .y_scale = 40, .y_off = 0,
 };
 
 static const struct ao_transform show_transform = {
@@ -53,7 +54,7 @@ static const struct ao_transform show_transform = {
 #define VOLT_FONT BitstreamVeraSans_Roman_58_font
 #define SMALL_FONT BitstreamVeraSans_Roman_12_font
 #define TINY_FONT BitstreamVeraSans_Roman_10_font
-#define LOGO_FONT BenguiatGothicStd_Bold_26_font
+#define LOGO_FONT BenguiatGothicStd_Bold_24_font
 
 #define LABEL_Y                (int16_t) (SMALL_FONT.ascent)
 #define VALUE_Y                (int16_t) (LABEL_Y + 5 + BIG_FONT.ascent)
@@ -70,6 +71,8 @@ static const struct ao_transform show_transform = {
 #define SCAN_X         (WIDTH - 100) / 2
 #define SCAN_Y         50
 #define SCAN_HEIGHT    3
+#define SCANNING_X     (WIDTH / 2)
+#define SCANNING_Y     (SCAN_Y - 2)
 #define FOUND_Y                63
 #define FOUND_X                3
 #define FOUND_WIDTH    (WIDTH - 6)
@@ -87,8 +90,9 @@ static const struct ao_transform show_transform = {
 #define BACKLIGHT_HEIGHT       20
 #define BACKLIGHT_VALUE_X      64
 #define BACKLIGHT_VALUE_Y      (BACKLIGHT_Y + BACKLIGHT_HEIGHT + SMALL_FONT.ascent + 3)
-#define INFO_START_Y   ((int16_t) (SMALL_FONT.ascent + 2))
-#define INFO_STEP_Y    ((int16_t) (SMALL_FONT.ascent + 3))
+#define INFO_FONT      TINY_FONT
+#define INFO_START_Y   ((int16_t) (INFO_FONT.ascent + 2))
+#define INFO_STEP_Y    ((int16_t) (INFO_FONT.ascent + 2))
 
 #define AO_LCO_DRAG_RACE_START_TIME    AO_SEC_TO_TICKS(5)
 #define AO_LCO_DRAG_RACE_STOP_TIME     AO_SEC_TO_TICKS(2)
@@ -103,6 +107,9 @@ static uint8_t      ao_lco_event_debug;
 
 static uint8_t ao_lco_display_mutex;
 
+static uint8_t         ao_sample_data;
+static struct ao_data  ao_data_cur;
+
 static void
 _ao_center_text(int16_t x, int16_t y, const struct ao_font *font, const char *str)
 {
@@ -131,28 +138,12 @@ _ao_lco_show_box(int16_t box)
 }
 
 static void
-_ao_lco_show_voltage(uint16_t decivolts, const char *label)
+_ao_format_voltage(char *str, size_t size, uint16_t decivolts)
 {
-       char    str[7];
-
-       PRINTD("voltage %d\n", decivolts);
-       _ao_center_text(WIDTH/2, LABEL_Y, &SMALL_FONT, label);
-       snprintf(str, sizeof(str), "%d.%d", decivolts / 10, decivolts % 10);
-       _ao_center_text(WIDTH/2, VALUE_Y, &BIG_FONT, str);
-}
-
-static void
-_ao_lco_batt_voltage(void)
-{
-       struct ao_adc   packet;
-       int16_t         decivolt;
-
-       ao_adc_single_get(&packet);
-       decivolt = ao_battery_decivolt(packet.v_batt);
-       _ao_lco_show_voltage((uint16_t) decivolt, "LCO Battery");
-       ao_st7565_update(&fb);
+       snprintf(str, size, "%d.%d", decivolts / 10, decivolts % 10);
 }
 
+#if AO_LCO_HAS_CONTRAST
 static void
 _ao_lco_show_contrast(void)
 {
@@ -165,7 +156,9 @@ _ao_lco_show_contrast(void)
        snprintf(buf, sizeof(buf), "%d %%", brightness * 100 / AO_LCO_MAX_CONTRAST);
        _ao_center_text(WIDTH/2, CONTRAST_VALUE_Y, &SMALL_FONT, buf);
 }
+#endif
 
+#if AO_LCO_HAS_BACKLIGHT_UI
 static void
 _ao_lco_show_backlight(void)
 {
@@ -178,6 +171,7 @@ _ao_lco_show_backlight(void)
        snprintf(buf, sizeof(buf), "%ld %%", backlight * 100 / AO_LCO_MAX_BACKLIGHT);
        _ao_center_text(WIDTH/2, BACKLIGHT_VALUE_Y, &SMALL_FONT, buf);
 }
+#endif
 
 static int16_t info_y;
 
@@ -189,46 +183,141 @@ _ao_lco_info(const char *format, ...)
        va_start(a, format);
        vsnprintf(buf, sizeof(buf), format, a);
        va_end(a);
-       ao_text(&fb, &SMALL_FONT, 0, info_y, buf, AO_BLACK, AO_COPY);
+       ao_text(&fb, &INFO_FONT, 0, info_y, buf, AO_BLACK, AO_COPY);
        info_y += INFO_STEP_Y;
 }
 
 static void
-_ao_lco_show_info(void)
+_ao_lco_show_lco_info(void)
 {
-       info_y = INFO_START_Y;
+       char            battery[7];
+       int16_t         decivolt;
+
        ao_logo_poly(&fb, &show_transform, AO_BLACK, AO_COPY);
+
+       decivolt = ao_battery_decivolt(ao_data_cur.adc.v_batt);
+       _ao_format_voltage(battery, sizeof(battery), (uint16_t) decivolt);
+
+       info_y = INFO_START_Y;
        _ao_lco_info("%s", ao_product);
-       _ao_lco_info("Version: %s", ao_version);
        _ao_lco_info("Serial: %d", ao_serial_number);
+       _ao_lco_info("Battery: %sV", battery);
+       _ao_lco_info("Version: %s", ao_version);
        _ao_lco_info("Callsign: %s", ao_config.callsign);
        _ao_lco_info("Frequency: %ld.%03d",
                     ao_config.frequency / 1000,
                     (int) (ao_config.frequency % 1000));
 }
 
+static uint8_t
+popcount(uint32_t value)
+{
+       uint8_t count = 0;
+       while(value != 0) {
+               count += value & 1;
+               value >>= 1;
+       }
+       return count;
+}
+
+static void
+_ao_lco_show_pad_info(void)
+{
+       char    pad_battery[7];
+
+       ao_logo_poly(&fb, &show_transform, AO_BLACK, AO_COPY);
+       info_y = INFO_START_Y;
+       _ao_lco_info("Bank: %d", ao_lco_box);
+       if (!(ao_lco_valid[ao_lco_box] & AO_LCO_VALID_LAST)) {
+               _ao_lco_info("Contact lost");
+               _ao_lco_info("Last RSSI: %ddBm", ao_radio_cmac_last_rssi);
+       } else {
+               _ao_lco_info("Total pads: %d", popcount(ao_pad_query.channels));
+               _ao_lco_info("RSSI: %ddBm", ao_radio_cmac_rssi);
+               _ao_format_voltage(pad_battery, sizeof(pad_battery), ao_pad_query.battery);
+               _ao_lco_info("Battery: %sV", pad_battery);
+               _ao_lco_info("Arming switch: %s", ao_pad_query.arm_status ? "On" : "Off");
+       }
+}
+
+#define AO_LCO_DIM_BACKLIGHT   (AO_LCO_MIN_BACKLIGHT + 3 * AO_LCO_BACKLIGHT_STEP)
+#define AO_AUTO_BACKLIGHT_RANGE        (AO_LCO_MAX_BACKLIGHT - AO_LCO_DIM_BACKLIGHT)
+#define AO_AUTO_BACKLIGHT_GAP  AO_ADC_MAX / 6
+
+static struct {
+       int16_t v_als;
+       int32_t backlight;
+} ao_lco_backlight_map[] = {
+       { .v_als = AO_ADC_MAX / 6, .backlight = AO_LCO_DIM_BACKLIGHT },
+       { .v_als = AO_ADC_MAX / 3, .backlight = (AO_LCO_MAX_BACKLIGHT - AO_LCO_MIN_BACKLIGHT) / 2 },
+       { .v_als = AO_ADC_MAX / 2, .backlight = AO_LCO_MAX_BACKLIGHT },
+       { .v_als = AO_ADC_MAX * 3 / 4,  .backlight = 0 },
+};
+
+#define NUM_BACKLIGHT_MAP sizeof(ao_lco_backlight_map)/sizeof(ao_lco_backlight_map[0])
+
+static unsigned ao_backlight_prev = NUM_BACKLIGHT_MAP - 1;
+
 static void
-_ao_lco_show_rssi(void)
+ao_auto_backlight(int16_t als_min, int16_t als_max)
 {
-       char label[20];
-       int16_t width;
-       snprintf(label, sizeof(label), "Bank %d RSSI", ao_lco_box);
-       width = ao_text_width(&SMALL_FONT, label);
-       ao_text(&fb, &SMALL_FONT, VALUE_LABEL_X - width / 2, LABEL_Y, label, AO_BLACK, AO_COPY);
-       if (!(ao_lco_valid[ao_lco_box] & AO_LCO_VALID_LAST))
-               strcpy(label, "---");
-       else
-               snprintf(label, sizeof(label), "%d", ao_radio_cmac_rssi);
-       width = ao_text_width(&VOLT_FONT, label);
-       ao_text(&fb, &VOLT_FONT, VALUE_LABEL_X - width / 2, VALUE_Y, label, AO_BLACK, AO_COPY);
+       unsigned ao_backlight;
+
+       PRINTD("ao_auto_backlight min %d max %d\n", als_min, als_max);
+       ao_backlight = ao_backlight_prev;
+       while (als_min > ao_lco_backlight_map[ao_backlight].v_als + AO_AUTO_BACKLIGHT_GAP) {
+               if (ao_backlight == NUM_BACKLIGHT_MAP - 1)
+                       break;
+               ao_backlight++;
+       }
+       while (als_max < ao_lco_backlight_map[ao_backlight].v_als - AO_AUTO_BACKLIGHT_GAP) {
+               if (ao_backlight == 0)
+                       return;
+               ao_backlight--;
+       }
+       if (ao_backlight != ao_backlight_prev)
+       {
+               PRINTD("   set backlight to %ld\n", ao_lco_backlight_map[ao_backlight].backlight);
+               ao_lco_set_backlight(ao_lco_backlight_map[ao_backlight].backlight);
+               ao_backlight_prev = ao_backlight;
+       }
 }
 
+#define AO_LCO_BACKLIGHT_INTERVAL      AO_SEC_TO_TICKS(2)
+
 static void
-_ao_lco_show_pad_battery(void)
+ao_lco_data(void)
 {
-       char label[20];
-       snprintf(label, sizeof(label), "Bank %d Battery", ao_lco_box);
-       _ao_lco_show_voltage(ao_pad_query.battery, label);
+       AO_TICK_TYPE    backlight_tick = ao_time() + AO_LCO_BACKLIGHT_INTERVAL;
+       AO_TICK_TYPE    now;
+       int16_t         als_min = INT16_MAX;
+       int16_t         als_max = INT16_MIN;
+
+       ao_timer_set_adc_interval(AO_MS_TO_TICKS(100));
+       for (;;) {
+               ao_sleep((void *) &ao_data_head);
+
+               while (ao_sample_data != ao_data_head) {
+                       struct ao_data *ao_data;
+
+                       /* Capture a sample */
+                       ao_data = (struct ao_data *) &ao_data_ring[ao_sample_data];
+
+                       ao_data_cur = *ao_data;
+                       if (ao_data_cur.adc.v_als < als_min)
+                               als_min = ao_data_cur.adc.v_als;
+                       if (ao_data_cur.adc.v_als > als_max)
+                               als_max = ao_data_cur.adc.v_als;
+                       ao_sample_data = ao_data_ring_next(ao_sample_data);
+               }
+               now = ao_time();
+               if ((AO_TICK_SIGNED) (backlight_tick - now) < 0) {
+                       backlight_tick = now + AO_LCO_BACKLIGHT_INTERVAL;
+                       ao_auto_backlight(als_min, als_max);
+                       als_min = INT16_MAX;
+                       als_max = INT16_MIN;
+               }
+       }
 }
 
 void
@@ -237,25 +326,23 @@ ao_lco_show(void)
        ao_mutex_get(&ao_lco_display_mutex);
        ao_rect(&fb, 0, 0, WIDTH, HEIGHT, AO_WHITE, AO_COPY);
        switch (ao_lco_box) {
-       case AO_LCO_LCO_VOLTAGE:
-               _ao_lco_batt_voltage();
-               break;
+#if AO_LCO_HAS_CONTRAST
        case AO_LCO_CONTRAST:
                _ao_lco_show_contrast();
                break;
+#endif
+#if AO_LCO_HAS_BACKLIGHT_UI
        case AO_LCO_BACKLIGHT:
                _ao_lco_show_backlight();
                break;
-       case AO_LCO_INFO:
-               _ao_lco_show_info();
+#endif
+       case AO_LCO_LCO_INFO:
+               _ao_lco_show_lco_info();
                break;
        default:
                switch (ao_lco_pad) {
-               case AO_LCO_PAD_RSSI:
-                       _ao_lco_show_rssi();
-                       break;
-               case AO_LCO_PAD_VOLTAGE:
-                       _ao_lco_show_pad_battery();
+               case AO_LCO_PAD_INFO:
+                       _ao_lco_show_pad_info();
                        break;
                default:
                        _ao_lco_show_pad(ao_lco_pad);
@@ -291,6 +378,7 @@ ao_lco_set_select(void)
 }
 
 
+#if AO_LCO_HAS_CONTRAST
 void
 ao_lco_set_contrast(int32_t contrast)
 {
@@ -302,7 +390,9 @@ ao_lco_get_contrast(void)
 {
        return (int32_t) ao_st7565_get_brightness();
 }
+#endif
 
+#if AO_LCO_HAS_BACKLIGHT
 static uint16_t ao_backlight;
 
 void
@@ -317,6 +407,7 @@ ao_lco_get_backlight(void)
 {
        return (int32_t) ao_backlight;
 }
+#endif
 
 static struct ao_task  ao_lco_drag_task;
 
@@ -413,12 +504,13 @@ ao_lco_display_test(void)
        ao_led_on(AO_LEDS_AVAILABLE);
        ao_rect(&fb, 0, 0, WIDTH, HEIGHT, AO_BLACK, AO_COPY);
        ao_st7565_update(&fb);
-       ao_delay(AO_MS_TO_TICKS(250));
+       ao_delay(AO_MS_TO_TICKS(1000));
        ao_led_off(AO_LEDS_AVAILABLE);
 }
 
 static struct ao_task ao_lco_input_task;
 static struct ao_task ao_lco_monitor_task;
+static struct ao_task ao_lco_data_task;
 static struct ao_task ao_lco_arm_warn_task;
 static struct ao_task ao_lco_igniter_status_task;
 
@@ -432,6 +524,7 @@ ao_lco_search_start(void)
 {
        ao_rect(&fb, 0, 0, WIDTH, HEIGHT, AO_WHITE, AO_COPY);
        ao_logo(&fb, &logo_transform, &LOGO_FONT, AO_BLACK, AO_COPY);
+       _ao_center_text(SCANNING_X, SCANNING_Y, &TINY_FONT, "Scanning...");
        found_width = 0;
        nfound = 0;
 }
@@ -515,6 +608,7 @@ void
 ao_lco_init(void)
 {
        ao_add_task(&ao_lco_monitor_task, ao_lco_main, "lco monitor");
+       ao_add_task(&ao_lco_data_task, ao_lco_data, "lco data");
 #if DEBUG
        ao_cmd_register(&ao_lco_cmds[0]);
 #endif
index e286cae6eceacc97c1ad571441faeb64ae0637af..b1af364fca3b9ee219fc23110e38b9be007b7718 100644 (file)
 #define AO_BUTTON_0            1
 
 #define AO_BUTTON_DRAG_SELECT  1
-#define AO_BUTTON_1_PORT       &stm_gpioc
-#define AO_BUTTON_1            0
+#define AO_BUTTON_1_PORT       &stm_gpiod
+#define AO_BUTTON_1            2
 
 #define AO_BUTTON_SPARE1               2
 #define AO_BUTTON_2_PORT       &stm_gpiob
 
 /* ADC */
 
-struct ao_adc {
-       int16_t         v_batt;
-};
-
-#define AO_ADC_DUMP(p) \
-       printf("batt: %5d\n", (p)->v_batt)
+#define AO_DATA_RING           8
 
-#define HAS_ADC_SINGLE         1
+#define HAS_ADC                        1
 #define HAS_ADC_TEMP           0
 #define HAS_BATTERY_REPORT     1
 
@@ -277,12 +272,33 @@ struct ao_adc {
 #define AO_ADC_V_BATT_PORT     (&stm_gpioa)
 #define AO_ADC_V_BATT_PIN      2
 
+#define AO_ADC_V_ALS           10
+#define AO_ADC_V_ALS_PORT      (&stm_gpioc)
+#define AO_ADC_V_ALS_PIN       0
+
 #define AO_ADC_PIN0_PORT       AO_ADC_V_BATT_PORT
 #define AO_ADC_PIN0_PIN                AO_ADC_V_BATT_PIN
 
+#define AO_ADC_PIN1_PORT       AO_ADC_V_ALS_PORT
+#define AO_ADC_PIN1_PIN                AO_ADC_V_ALS_PIN
+
 #define AO_ADC_SQ1             AO_ADC_V_BATT
+#define AO_ADC_SQ2             AO_ADC_V_ALS
 
-#define AO_NUM_ADC             1
+#define AO_NUM_ADC             2
+
+struct ao_adc {
+       union {
+               struct {
+                       int16_t         v_batt;
+                       int16_t         v_als;
+               };
+               int16_t v_vals[AO_NUM_ADC];
+       };
+};
+
+#define AO_ADC_DUMP(p) \
+       printf("batt: %5d als %5d\n", (p)->adc.v_batt, (p)->adc.v_als)
 
 /*
  * Voltage divider on ADC battery sampler
@@ -296,20 +312,23 @@ struct ao_adc {
 #define AO_ADC_REFERENCE_DV    33
 
 #define AO_LCO_SEARCH_API
-#define AO_LCO_HAS_CONTRAST    1
-#define AO_LCO_MIN_CONTRAST    0
-#define AO_LCO_MAX_CONTRAST    63
-#define AO_LCO_CONTRAST_STEP   1
+
+//#define AO_LCO_HAS_CONTRAST  1
+//#define AO_LCO_MIN_CONTRAST  0
+//#define AO_LCO_MAX_CONTRAST  63
+//#define AO_LCO_CONTRAST_STEP 1
 
 #define AO_LCO_HAS_BACKLIGHT   1
 #define AO_LCO_MIN_BACKLIGHT   0
 #define AO_LCO_MAX_BACKLIGHT   65535
 #define AO_LCO_BACKLIGHT_STEP  771
 
-#define AO_LCO_HAS_INFO                1
+#define AO_LCO_HAS_LCO_INFO    1
 #define AO_LCO_MIN_INFO_PAGE   0
 #define AO_LCO_MAX_INFO_PAGE   0
 
+#define AO_LCO_HAS_PAD_INFO    1
+
 /*
  * LCD Backlight via PWM.
  *
index faba96b0e0f5c28b930af0ad4a5d492b2d8af188..6293edd3878bdcc1bd807c8642f63b6bd96d7dd2 100644 (file)
 #include <ao_st7565.h>
 #include <ao_pwm.h>
 
-#define WIDTH  AO_ST7565_WIDTH
-#define HEIGHT AO_ST7565_HEIGHT
-#define STRIDE AO_BITMAP_STRIDE(WIDTH)
-
-static uint32_t        image[STRIDE * HEIGHT];
-
-static struct ao_bitmap fb = {
-       .base = image,
-       .stride = STRIDE,
-       .width = WIDTH,
-       .height = HEIGHT,
-       .damage = AO_BOX_INIT,
-};
-
-static void
-ao_st7565_test(void)
-{
-       ao_rect(&fb, 0, 0, WIDTH, HEIGHT, AO_WHITE, AO_COPY);
-       ao_st7565_update(&fb);
-       ao_text(&fb, &BitstreamVeraSans_Roman_24_font,
-               0, 20, "hello world", AO_BLACK, AO_COPY);
-       ao_st7565_update(&fb);
-}
-
-static int16_t x1 = 32, _y1 = 10, x2 = 32, y2 = 40;
-static int16_t dx1 = 2, dy1 = 2, dx2 = -2, dy2 = -1;
-
-#define bounds(v,m,M,d)        \
-               if (v < m) {                    \
-                       v = m + m - v;          \
-                       d = -d;                 \
-               } else if (v > M) {             \
-                       v = M - (v - M);        \
-                       d = -d;                 \
-               }
-
-static void
-ao_st7565_line(void)
-{
-       int     i;
-
-       for (i = 0; i < 100; i++) {
-               ao_rect(&fb, 0, 0, WIDTH, HEIGHT, AO_WHITE, AO_COPY);
-               ao_line(&fb, x1, _y1, x2, y2, AO_BLACK, AO_COPY);
-               ao_st7565_update(&fb);
-               x1 += dx1;
-               _y1 += dy1;
-               x2 += dx2;
-               y2 += dy2;
-               printf("%d,%d - %d,%d\n", x1, _y1, x2, y2);
-               fflush(stdout);
-               bounds(x1, 0, WIDTH, dx1);
-               bounds(x2, 0, WIDTH, dx2);
-               bounds(_y1, 0, HEIGHT, dy1);
-               bounds(y2, 0, HEIGHT, dy2);
-               ao_delay(AO_MS_TO_TICKS(200));
-       }
-}
-
-static const float pad_volts = 12.3f;
-static const float lco_volts = 4.1f;
-static const int rssi = -30;
-
-static int     boxes[] = { 1, 2, 3, 5, 8, 11, 13, 17, 19, 23, 29, 31, 37, 62, 97 };
-
-//static int   max_box = 97;
-
-#define ARRAYSIZE(a)   (sizeof(a) / sizeof((a)[0]))
-
-static bool
-valid_box(int box)
-{
-       size_t i;
-       if (box == 0)
-               return true;
-       for (i = 0; i < ARRAYSIZE(boxes); i++)
-               if (boxes[i] == box)
-                       return true;
-       return false;
-}
-
-#if 0
-static void
-next_box(void)
-{
-       for (int n = box_number + 1; n <= max_box; n++)
-               if (valid_box(n)) {
-                       box_number = n;
-                       return;
-               }
-       box_number = 0;
-}
-
-static void
-prev_box(void)
-{
-       for (int n = box_number - 1; n >= 0; n--)
-               if (valid_box(n)) {
-                       box_number = n;
-                       return;
-               }
-       box_number = max_box;
-}
-#endif
-
-static const struct ao_transform logo_transform = {
-       .x_scale = 48, .x_off = 2,
-       .y_scale = 48, .y_off = 0,
-};
-
-#define BIG_FONT BitstreamVeraSans_Roman_58_font
-#define VOLT_FONT BitstreamVeraSans_Roman_58_font
-#define SMALL_FONT BitstreamVeraSans_Roman_12_font
-#define TINY_FONT BitstreamVeraSans_Roman_10_font
-#define LOGO_FONT BenguiatGothicStd_Bold_26_font
-
-#define LABEL_Y                (int16_t) (SMALL_FONT.ascent)
-#define VALUE_Y                (int16_t) (LABEL_Y + BIG_FONT.ascent + 5)
-#define BOX_X          2
-#define PAD_X          90
-#define BOX_LABEL_X    30
-#define VOLT_LABEL_X   25
-#define RSSI_LABEL_X   15
-#define PAD_LABEL_X    95
-#define SEP_X          (PAD_X - 8)
-#define SCAN_X         (WIDTH - 100) / 2
-#define SCAN_Y         50
-#define SCAN_HEIGHT    3
-#define FOUND_Y                63
-#define FOUND_X                6
-#define FOUND_WIDTH    17
-#define MAX_VALID      (WIDTH / FOUND_WIDTH)
-
-static int16_t box_number = 88;
-static int16_t pad_number = 8;
-
-static void
-ao_st7565_poly(void)
-{
-       int16_t scan_number;
-       char    str[8];
-       int     i;
-       int     v;
-       int     last_box;
-       int16_t b;
-
-       for (scan_number = 0; scan_number < 100; scan_number++) {
-               ao_rect(&fb, 0, 0, WIDTH, HEIGHT, AO_WHITE, AO_COPY);
-               ao_logo(&fb, &logo_transform, &LOGO_FONT, AO_BLACK, AO_COPY);
-               if (scan_number) {
-                       ao_rect(&fb, SCAN_X, SCAN_Y, (int16_t) scan_number, SCAN_HEIGHT, AO_BLACK, AO_COPY);
-                       b = 0;
-                       v = 0;
-                       last_box = 0;
-                       for (i = scan_number; i > 1; i--) {
-                               if (valid_box(i)) {
-                                       if (!last_box)
-                                               last_box = i;
-                                       v++;
-                                       if (v == MAX_VALID)
-                                               break;
-                               }
-                       }
-                       for (; i <= scan_number; i++) {
-                               if (valid_box(i)) {
-                                       sprintf(str, "%02d%s", i, i == last_box ? "" : ",");
-                                       ao_text(&fb, &TINY_FONT, (int16_t) (FOUND_X + FOUND_WIDTH * b),
-                                               FOUND_Y, str, AO_BLACK, AO_COPY);
-                                       b++;
-                               }
-                       }
-               }
-               ao_st7565_update(&fb);
-               ao_delay(AO_MS_TO_TICKS(50));
-       }
-       ao_rect(&fb, 0, 0, WIDTH, HEIGHT, AO_WHITE, AO_COPY);
-       switch (box_number) {
-       case 0:
-               sprintf(str, "%4.1f", lco_volts);
-               ao_text(&fb, &VOLT_FONT, BOX_X, VALUE_Y, str, AO_BLACK, AO_COPY);
-               ao_text(&fb, &SMALL_FONT, VOLT_LABEL_X, LABEL_Y, "LCO Battery", AO_BLACK, AO_COPY);
-               break;
-       default:
-               switch (pad_number) {
-               case -1:
-                       sprintf(str, "%4.1f", pad_volts);
-                       ao_text(&fb, &VOLT_FONT, BOX_X, VALUE_Y, str, AO_BLACK, AO_COPY);
-                       ao_text(&fb, &SMALL_FONT, VOLT_LABEL_X, LABEL_Y, "Pad Battery", AO_BLACK, AO_COPY);
-                       break;
-               case 0:
-                       sprintf(str, "%4d", rssi);
-                       ao_text(&fb, &VOLT_FONT, BOX_X, VALUE_Y, str, AO_BLACK, AO_COPY);
-                       ao_text(&fb, &SMALL_FONT, RSSI_LABEL_X, LABEL_Y, "Signal Strength", AO_BLACK, AO_COPY);
-                       break;
-               default:
-                       sprintf(str, "%02d", box_number);
-                       ao_text(&fb, &BIG_FONT, BOX_X, VALUE_Y, str, AO_BLACK, AO_COPY);
-                       ao_text(&fb, &SMALL_FONT, BOX_LABEL_X, LABEL_Y, "Box", AO_BLACK, AO_COPY);
-
-                       sprintf(str, "%d", pad_number);
-                       ao_text(&fb, &BIG_FONT, PAD_X, VALUE_Y, str, AO_BLACK, AO_COPY);
-                       ao_text(&fb, &SMALL_FONT, PAD_LABEL_X, LABEL_Y, "Pad", AO_BLACK, AO_COPY);
-
-                       ao_rect(&fb, SEP_X, 0, 2, HEIGHT, AO_BLACK, AO_COPY);
-               }
-               break;
-       }
-       ao_st7565_update(&fb);
-}
-
-const struct ao_cmds ao_st7565_cmds[] = {
-       { ao_st7565_test, "g\0Test ST7565 display" },
-       { ao_st7565_line, "l\0Draw lines" },
-       { ao_st7565_poly, "p\0Draw polygon" },
-       { 0, NULL },
-};
-
 int
 main(void)
 {
@@ -261,7 +44,7 @@ main(void)
        ao_spi_init();
        ao_dma_init();
        ao_exti_init();
-       ao_adc_single_init();
+       ao_adc_init();
 
        ao_beep_init();
        ao_pwm_init();
@@ -281,8 +64,6 @@ main(void)
        ao_lco_init();
        ao_lco_cmd_init();
 
-//     ao_cmd_register(ao_st7565_cmds);
-
        ao_start_scheduler();
        return 0;
 }
index c16b33a03975475c34076cfa911f11bceb346c6e..f702ca18059f0b315c3b65de3c1e2be37366a389 100644 (file)
@@ -69,6 +69,7 @@
 #define LOG_ERASE_MARK                         0x55
 #define LOG_MAX_ERASE                          128
 #define AO_LOG_FORMAT                          AO_LOG_FORMAT_TELEMEGA
+#define AO_TELEMETRY_MEGA_DATA AO_TELEMETRY_MEGA_DATA_15V
 
 #define HAS_EEPROM             1
 #define USE_INTERNAL_FLASH     0
index ce258471e6ff853dc1b7d3af76f07c07135ed2d7..833fd90e6cb5504756b18cbccf8df6b1de9bdae4 100644 (file)
@@ -69,6 +69,7 @@
 #define LOG_ERASE_MARK                         0x55
 #define LOG_MAX_ERASE                          128
 #define AO_LOG_FORMAT                          AO_LOG_FORMAT_TELEMEGA
+#define AO_TELEMETRY_MEGA_DATA AO_TELEMETRY_MEGA_DATA_15V
 
 #define HAS_EEPROM             1
 #define USE_INTERNAL_FLASH     0
index c8d365c6459c7890cc86a1eb55b8de79259fc88e..6e0d1c803d2dddbc966a16a10b6a546d8eb6b03e 100644 (file)
@@ -69,6 +69,7 @@
 #define LOG_ERASE_MARK                         0x55
 #define LOG_MAX_ERASE                          128
 #define AO_LOG_FORMAT                          AO_LOG_FORMAT_TELEMEGA
+#define AO_TELEMETRY_MEGA_DATA AO_TELEMETRY_MEGA_DATA_15V
 
 #define HAS_EEPROM             1
 #define USE_INTERNAL_FLASH     0
index c68699e03bf92b2091a1f9f4b18604129cf89dfa..6d599112059e53a6ca83fd0e69cab1fb1457517f 100644 (file)
@@ -69,6 +69,7 @@
 #define LOG_ERASE_MARK                         0x55
 #define LOG_MAX_ERASE                          128
 #define AO_LOG_FORMAT                          AO_LOG_FORMAT_TELEMEGA_3
+#define AO_TELEMETRY_MEGA_DATA AO_TELEMETRY_MEGA_DATA_15V
 
 #define HAS_EEPROM             1
 #define USE_INTERNAL_FLASH     0
index 7fa6d83528f5fd3f8fa216a8aadb23d91dbd4a96..47d53f282ef5c270de37076c5d0364ff1fea5a45 100644 (file)
@@ -69,6 +69,7 @@
 #define LOG_ERASE_MARK                         0x55
 #define LOG_MAX_ERASE                          128
 #define AO_LOG_FORMAT                          AO_LOG_FORMAT_TELEMEGA_4
+#define AO_TELEMETRY_MEGA_DATA AO_TELEMETRY_MEGA_DATA_15V
 
 #define HAS_EEPROM             1
 #define USE_INTERNAL_FLASH     0
index 5901eeae272fd838b497e5470d34a42f718f4b71..a38b8b1eefdc29c72a1d1d46302fba1c8e2cc91a 100644 (file)
@@ -71,6 +71,7 @@
 #define LOG_ERASE_MARK                         0x55
 #define LOG_MAX_ERASE                          128
 #define AO_LOG_FORMAT                          AO_LOG_FORMAT_TELEMEGA_5
+#define AO_TELEMETRY_MEGA_DATA AO_TELEMETRY_MEGA_DATA_15V
 #define AO_LOG_NORMALIZED                      1
 
 #define HAS_EEPROM             1
index 8e9be45d8c5831c0e1d0727d16f49a3f49feff3b..3a95be08a2f100b64a68b62eabe8c5a2df11754d 100644 (file)
@@ -71,6 +71,7 @@
 #define LOG_ERASE_MARK                         0x55
 #define LOG_MAX_ERASE                          128
 #define AO_LOG_FORMAT                          AO_LOG_FORMAT_TELEMEGA_6
+#define AO_TELEMETRY_MEGA_DATA AO_TELEMETRY_MEGA_DATA_15V
 #define AO_LOG_NORMALIZED                      1
 
 #define HAS_EEPROM             1
diff --git a/src/telemega-v7.0-seeed/.gitignore b/src/telemega-v7.0-seeed/.gitignore
new file mode 100644 (file)
index 0000000..e67759a
--- /dev/null
@@ -0,0 +1,2 @@
+ao_product.h
+telemega-*.elf
diff --git a/src/telemega-v7.0-seeed/ao_pins.h b/src/telemega-v7.0-seeed/ao_pins.h
new file mode 100644 (file)
index 0000000..06fa08d
--- /dev/null
@@ -0,0 +1,491 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+
+/* 16MHz High speed external crystal */
+#define AO_HSE                 16000000
+
+/* PLLVCO = 96MHz (so that USB will work) */
+#define AO_PLLMUL              6
+#define AO_RCC_CFGR_PLLMUL     (STM_RCC_CFGR_PLLMUL_6)
+
+/* SYSCLK = 32MHz (no need to go faster than CPU) */
+#define AO_PLLDIV              3
+#define AO_RCC_CFGR_PLLDIV     (STM_RCC_CFGR_PLLDIV_3)
+
+/* HCLK = 32MHz (CPU clock) */
+#define AO_AHB_PRESCALER       1
+#define AO_RCC_CFGR_HPRE_DIV   STM_RCC_CFGR_HPRE_DIV_1
+
+/* Run APB1 at 16MHz (HCLK/2) */
+#define AO_APB1_PRESCALER      2
+#define AO_RCC_CFGR_PPRE1_DIV  STM_RCC_CFGR_PPRE2_DIV_2
+
+/* Run APB2 at 16MHz (HCLK/2) */
+#define AO_APB2_PRESCALER      2
+#define AO_RCC_CFGR_PPRE2_DIV  STM_RCC_CFGR_PPRE2_DIV_2
+
+#define HAS_SERIAL_1           0
+#define USE_SERIAL_1_STDIN     0
+#define SERIAL_1_PB6_PB7       0
+#define SERIAL_1_PA9_PA10      0
+
+#define HAS_SERIAL_2           1
+#define USE_SERIAL_2_STDIN     0
+#define SERIAL_2_PA2_PA3       1
+#define SERIAL_2_PD5_PD6       0
+#define USE_SERIAL_2_FLOW      0
+#define USE_SERIAL_2_SW_FLOW   0
+
+#define HAS_SERIAL_3           0
+#define USE_SERIAL_3_STDIN     0
+#define SERIAL_3_PB10_PB11     0
+#define SERIAL_3_PC10_PC11     0
+#define SERIAL_3_PD8_PD9       0
+
+#define ao_gps_getchar         ao_serial2_getchar
+#define ao_gps_putchar         ao_serial2_putchar
+#define ao_gps_set_speed       ao_serial2_set_speed
+#define ao_gps_fifo            (ao_stm_usart2.rx_fifo)
+
+#define AO_UBLOX_VERSION       10
+
+#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX       (1024 * 1024)
+#define AO_CONFIG_DEFAULT_ACCEL_PLUS_G         -20
+#define AO_CONFIG_DEFAULT_ACCEL_MINUS_G                20
+#define AO_CONFIG_MAX_SIZE                     1024
+#define LOG_ERASE_MARK                         0x55
+#define LOG_MAX_ERASE                          128
+#define AO_LOG_FORMAT                          AO_LOG_FORMAT_TELEMEGA_7
+#define AO_TELEMETRY_MEGA_DATA                         AO_TELEMETRY_MEGA_DATA_30V
+#define AO_LOG_NORMALIZED                      1
+
+#define HAS_EEPROM             1
+#define USE_INTERNAL_FLASH     0
+#define USE_EEPROM_CONFIG      1
+#define USE_STORAGE_CONFIG     0
+#define HAS_USB                        1
+#define HAS_BEEP               1
+#define BEEPER_TIMER           3
+#define BEEPER_CHANNEL         2
+#define BEEPER_PORT            (&stm_gpioe)
+#define BEEPER_PIN             4
+#define HAS_BATTERY_REPORT     1
+#define HAS_RADIO              1
+#define HAS_TELEMETRY          1
+#define HAS_APRS               1
+#define HAS_COMPANION          1
+
+#define HAS_SPI_1              1
+#define SPI_1_PA5_PA6_PA7      1       /* Barometer */
+#define SPI_1_PB3_PB4_PB5      1       /* Accelerometer */
+#define SPI_1_PE13_PE14_PE15   1       /* MPU6000 */
+#define SPI_1_OSPEEDR          STM_OSPEEDR_10MHz
+
+//#define MMC5983_I2C          1
+
+#define HAS_SPI_2              1
+#define SPI_2_PB13_PB14_PB15   1       /* Flash, Companion */
+#ifndef MMC5983_I2C
+#define SPI_2_PD1_PD3_PD4      1       /* MMC5983 */
+#endif
+#define SPI_2_OSPEEDR          STM_OSPEEDR_10MHz
+
+#define HAS_I2C_1              0
+#define I2C_1_PB8_PB9          0
+
+#define HAS_I2C_2              0
+#define I2C_2_PB10_PB11                0
+
+#define PACKET_HAS_SLAVE       1
+#define PACKET_HAS_MASTER      0
+
+#define LOW_LEVEL_DEBUG                0
+
+#define LED_PORT_ENABLE                STM_RCC_AHBENR_GPIOCEN
+#define LED_PORT               (&stm_gpioc)
+#define LED_PIN_RED            8
+#define LED_PIN_GREEN          9
+#define AO_LED_RED             (1 << LED_PIN_RED)
+#define AO_LED_GREEN           (1 << LED_PIN_GREEN)
+
+#define LEDS_AVAILABLE         (AO_LED_RED | AO_LED_GREEN)
+
+#define HAS_GPS                        1
+#define HAS_FLIGHT             1
+#define HAS_ADC                        1
+#define HAS_ADC_TEMP           1
+#define HAS_LOG                        1
+
+/*
+ * Igniter
+ */
+
+#define HAS_IGNITE             1
+#define HAS_IGNITE_REPORT      1
+
+#define AO_SENSE_PYRO(p,n)     ((p)->adc.sense[n])
+#define AO_SENSE_DROGUE(p)     ((p)->adc.sense[4])
+#define AO_SENSE_MAIN(p)       ((p)->adc.sense[5])
+#define AO_IGNITER_CLOSED      400
+#define AO_IGNITER_OPEN                60
+
+/* Pyro A */
+#define AO_PYRO_PORT_0 (&stm_gpiod)
+#define AO_PYRO_PIN_0  6
+
+/* Pyro B */
+#define AO_PYRO_PORT_1 (&stm_gpiod)
+#define AO_PYRO_PIN_1  7
+
+/* Pyro C */
+#define AO_PYRO_PORT_2 (&stm_gpioe)
+#define AO_PYRO_PIN_2  3
+
+/* Pyro D */
+#define AO_PYRO_PORT_3 (&stm_gpioe)
+#define AO_PYRO_PIN_3  2
+
+/* Drogue */
+#define AO_IGNITER_DROGUE_PORT (&stm_gpioe)
+#define AO_IGNITER_DROGUE_PIN  6
+
+/* Main */
+#define AO_IGNITER_MAIN_PORT   (&stm_gpioe)
+#define AO_IGNITER_MAIN_PIN    5
+
+/* Number of general purpose pyro channels available */
+#define AO_PYRO_NUM    4
+
+/*
+ * ADC
+ */
+#define AO_DATA_RING           32
+#define AO_ADC_NUM_SENSE       6
+
+struct ao_adc {
+       int16_t                 sense[AO_ADC_NUM_SENSE];
+       int16_t                 v_batt;
+       int16_t                 v_pbatt;
+       int16_t                 temp;
+};
+
+#define AO_ADC_DUMP(p) \
+       printf("tick: %5lu A: %5d B: %5d C: %5d D: %5d drogue: %5d main: %5d batt: %5d pbatt: %5d temp: %5d\n", \
+              (p)->tick, \
+              (p)->adc.sense[0], (p)->adc.sense[1], (p)->adc.sense[2], \
+              (p)->adc.sense[3], (p)->adc.sense[4], (p)->adc.sense[5], \
+              (p)->adc.v_batt, (p)->adc.v_pbatt, (p)->adc.temp)
+
+#define AO_ADC_SENSE_A         0
+#define AO_ADC_SENSE_A_PORT    (&stm_gpioa)
+#define AO_ADC_SENSE_A_PIN     0
+
+#define AO_ADC_SENSE_B         1
+#define AO_ADC_SENSE_B_PORT    (&stm_gpioa)
+#define AO_ADC_SENSE_B_PIN     1
+
+#define AO_ADC_SENSE_C         24
+#define AO_ADC_SENSE_C_PORT    (&stm_gpioe)
+#define AO_ADC_SENSE_C_PIN     9
+
+#define AO_ADC_SENSE_D         25
+#define AO_ADC_SENSE_D_PORT    (&stm_gpioe)
+#define AO_ADC_SENSE_D_PIN     10
+
+#define AO_ADC_SENSE_DROGUE    4
+#define AO_ADC_SENSE_DROGUE_PORT       (&stm_gpioa)
+#define AO_ADC_SENSE_DROGUE_PIN        4
+
+#define AO_ADC_SENSE_MAIN      22
+#define AO_ADC_SENSE_MAIN_PORT (&stm_gpioe)
+#define AO_ADC_SENSE_MAIN_PIN  7
+
+#define AO_ADC_V_BATT          8
+#define AO_ADC_V_BATT_PORT     (&stm_gpiob)
+#define AO_ADC_V_BATT_PIN      0
+
+#define AO_ADC_V_PBATT         9
+#define AO_ADC_V_PBATT_PORT    (&stm_gpiob)
+#define AO_ADC_V_PBATT_PIN     1
+
+#define AO_ADC_TEMP            16
+
+#define AO_ADC_RCC_AHBENR      ((1 << STM_RCC_AHBENR_GPIOAEN) | \
+                                (1 << STM_RCC_AHBENR_GPIOEEN) | \
+                                (1 << STM_RCC_AHBENR_GPIOBEN))
+
+#define AO_NUM_ADC_PIN         (AO_ADC_NUM_SENSE + 2)
+
+#define AO_ADC_PIN0_PORT       AO_ADC_SENSE_A_PORT
+#define AO_ADC_PIN0_PIN                AO_ADC_SENSE_A_PIN
+#define AO_ADC_PIN1_PORT       AO_ADC_SENSE_B_PORT
+#define AO_ADC_PIN1_PIN                AO_ADC_SENSE_B_PIN
+#define AO_ADC_PIN2_PORT       AO_ADC_SENSE_C_PORT
+#define AO_ADC_PIN2_PIN                AO_ADC_SENSE_C_PIN
+#define AO_ADC_PIN3_PORT       AO_ADC_SENSE_D_PORT
+#define AO_ADC_PIN3_PIN                AO_ADC_SENSE_D_PIN
+#define AO_ADC_PIN4_PORT       AO_ADC_SENSE_DROGUE_PORT
+#define AO_ADC_PIN4_PIN                AO_ADC_SENSE_DROGUE_PIN
+#define AO_ADC_PIN5_PORT       AO_ADC_SENSE_MAIN_PORT
+#define AO_ADC_PIN5_PIN                AO_ADC_SENSE_MAIN_PIN
+#define AO_ADC_PIN6_PORT       AO_ADC_V_BATT_PORT
+#define AO_ADC_PIN6_PIN                AO_ADC_V_BATT_PIN
+#define AO_ADC_PIN7_PORT       AO_ADC_V_PBATT_PORT
+#define AO_ADC_PIN7_PIN                AO_ADC_V_PBATT_PIN
+
+#define AO_NUM_ADC             (AO_ADC_NUM_SENSE + 3)
+
+#define AO_ADC_SQ1             AO_ADC_SENSE_A
+#define AO_ADC_SQ2             AO_ADC_SENSE_B
+#define AO_ADC_SQ3             AO_ADC_SENSE_C
+#define AO_ADC_SQ4             AO_ADC_SENSE_D
+#define AO_ADC_SQ5             AO_ADC_SENSE_DROGUE
+#define AO_ADC_SQ6             AO_ADC_SENSE_MAIN
+#define AO_ADC_SQ7             AO_ADC_V_BATT
+#define AO_ADC_SQ8             AO_ADC_V_PBATT
+#define AO_ADC_SQ9             AO_ADC_TEMP
+
+/*
+ * Voltage divider on ADC battery sampler
+ */
+#define AO_BATTERY_DIV_PLUS    56      /* 5.6k */
+#define AO_BATTERY_DIV_MINUS   100     /* 10k */
+
+/*
+ * Voltage divider on ADC pyro battery sampler
+ */
+#define AO_PYRO_BATTERY_DIV_PLUS       100     /* 100k */
+#define AO_PYRO_BATTERY_DIV_MINUS      12      /* 12k */
+
+/*
+ * Voltage divider on ADC igniter samplers
+ */
+#define AO_IGNITE_DIV_PLUS     100     /* 100k */
+#define AO_IGNITE_DIV_MINUS    12      /* 12k */
+
+/*
+ * ADC reference in decivolts
+ */
+#define AO_ADC_REFERENCE_DV    33
+
+/*
+ * Pressure sensor settings
+ */
+#define HAS_MS5607             1
+#define HAS_MS5611             0
+#define AO_MS5607_PRIVATE_PINS 1
+#define AO_MS5607_CS_PORT      (&stm_gpioc)
+#define AO_MS5607_CS_PIN       4
+#define AO_MS5607_CS_MASK      (1 << AO_MS5607_CS)
+#define AO_MS5607_MISO_PORT    (&stm_gpioa)
+#define AO_MS5607_MISO_PIN     6
+#define AO_MS5607_MISO_MASK    (1 << AO_MS5607_MISO)
+#define AO_MS5607_SPI_INDEX    AO_SPI_1_PA5_PA6_PA7
+
+/*
+ * SPI Flash memory
+ */
+
+#define M25_MAX_CHIPS          1
+#define AO_M25_SPI_CS_PORT     (&stm_gpiod)
+#define AO_M25_SPI_CS_MASK     (1 << 10)
+#define AO_M25_SPI_BUS         AO_SPI_2_PB13_PB14_PB15
+
+/*
+ * Radio (cc1200)
+ */
+
+/* gets pretty close to 434.550 */
+
+#define AO_RADIO_CAL_DEFAULT   5695733
+
+#define AO_FEC_DEBUG           0
+#define AO_CC1200_SPI_CS_PORT  (&stm_gpioc)
+#define AO_CC1200_SPI_CS_PIN   5
+#define AO_CC1200_SPI_BUS      AO_SPI_2_PB13_PB14_PB15
+#define AO_CC1200_SPI          stm_spi2
+
+#define AO_CC1200_INT_PORT             (&stm_gpiob)
+#define AO_CC1200_INT_PIN              11
+
+#define AO_CC1200_INT_GPIO     2
+#define AO_CC1200_INT_GPIO_IOCFG       CC1200_IOCFG2
+
+#define AO_CC1200_MARC_GPIO    3
+#define AO_CC1200_MARC_GPIO_IOCFG      CC1200_IOCFG3
+
+#define HAS_BOOT_RADIO         0
+
+
+/*
+ *
+ * Here are the required sensor signs:
+ *
+ * +along      nose up
+ * +across     USB down
+ * +through    TH down
+ *
+ * With the board aligned to have positive accel for the relevant
+ * axis, looking down from above we have:
+ *
+ * +roll       counter clockwise (nose up)
+ * +pitch      counter clockwise (USB down)
+ * +yaw                counter clockwise (TH down)
+ */
+
+/*
+ * On TMega v6, bmi088 pin 1 (NE corner of chip) is placed towards the
+ * USB and antenna edges of the board. Relative to bmi088 specs, to
+ * get the above values, we need to flip the Y axis, assigning values
+ * as follows:
+ *
+ *     +along          +X      +roll   +X
+ *     +across         -Y      +pitch  -Y
+ *     +through        +Z      +yaw    +Z
+ */
+
+#define HAS_BMI088             1
+#define AO_BMI088_SPI_BUS      AO_SPI_1_PE13_PE14_PE15
+#define AO_BMI088_ACC_CS_PORT  (&stm_gpioc)
+#define AO_BMI088_ACC_CS_PIN   14
+#define AO_BMI088_GYR_CS_PORT  (&stm_gpioc)
+#define AO_BMI088_GYR_CS_PIN   13
+#define HAS_IMU                        1
+
+#define ao_bmi088_along(m)     ((m)->acc.x)
+#define ao_bmi088_across(m)    (-(m)->acc.y)
+#define ao_bmi088_through(m)   ((m)->acc.z)
+
+#define ao_bmi088_roll(m)      ((m)->gyr.x)
+#define ao_bmi088_pitch(m)     (-(m)->gyr.y)
+#define ao_bmi088_yaw(m)       ((m)->gyr.z)
+
+#define ao_data_along(packet)  ao_bmi088_along(&(packet)->bmi088)
+#define ao_data_across(packet) ao_bmi088_across(&(packet)->bmi088)
+#define ao_data_through(packet)        ao_bmi088_through(&(packet)->bmi088)
+
+#define ao_data_roll(packet)   ao_bmi088_roll(&(packet)->bmi088)
+#define ao_data_pitch(packet)  ao_bmi088_pitch(&(packet)->bmi088)
+#define ao_data_yaw(packet)    ao_bmi088_yaw(&(packet)->bmi088)
+
+/*
+ * MMC5983
+ *
+ *     pin 1 NE corner of chip
+ *
+ *     +along          -Y
+ *     +across         +X
+ *     +through        -Z
+ */
+
+#define HAS_MMC5983            1
+#define AO_MMC5983_INT_PORT    (&stm_gpiod)
+#define AO_MMC5983_INT_PIN     5
+#define AO_MMC5983_SPI_CLK_PORT        (&stm_gpiod)
+#define AO_MMC5983_SPI_CLK_PIN 1
+#define AO_MMC5983_SPI_MISO_PORT       (&stm_gpiod)
+#define AO_MMC5983_SPI_MISO_PIN        3
+#define AO_MMC5983_SPI_MOSI_PORT       (&stm_gpiod)
+#define AO_MMC5983_SPI_MOSI_PIN        4
+#define AO_MMC5983_SPI_INDEX   (AO_SPI_2_PD1_PD3_PD4 | AO_SPI_MODE_3)
+#define AO_MMC5983_SPI_CS_PORT (&stm_gpioa)
+#define AO_MMC5983_SPI_CS_PIN  15
+
+#define ao_mmc5983_along(m)            (-(m)->y)
+#define ao_mmc5983_across(m)           ((m)->x)
+#define ao_mmc5983_through(m)          (-(m)->z)
+
+#define ao_data_mag_along(packet)      ao_mmc5983_along(&(packet)->mmc5983)
+#define ao_data_mag_across(packet)     ao_mmc5983_across(&(packet)->mmc5983)
+#define ao_data_mag_through(packet)    ao_mmc5983_through(&(packet)->mmc5983)
+
+/*
+ * ADXL375
+ *
+ * pin 1 NW corner of chip
+ *
+ *     +along          +X
+ *     +across         +Y
+ *     +through        +Z
+ */
+
+#define HAS_ADXL375            1
+#define AO_ADXL375_SPI_INDEX   (AO_SPI_1_PB3_PB4_PB5 | AO_SPI_MODE_3)
+#define AO_ADXL375_CS_PORT     (&stm_gpioc)
+#define AO_ADXL375_CS_PIN      0
+
+#define AO_ADXL375_AXIS                x
+#define AO_ADXL375_INVERT      1
+
+#define NUM_CMDS               16
+
+/*
+ * Companion
+ */
+
+#define AO_COMPANION_CS_PORT   (&stm_gpiob)
+#define AO_COMPANION_CS_PIN_0  (6)
+#define AO_COMPANION_CS_PIN    AO_COMPANION_CS_PIN_0
+#define AO_COMPANION_CS_PIN_1  (7)
+#define AO_COMPANION_SPI_BUS   AO_SPI_2_PB13_PB14_PB15
+
+/*
+ * Monitor
+ */
+
+#define HAS_MONITOR            0
+#define LEGACY_MONITOR         0
+#define HAS_MONITOR_PUT                1
+#define AO_MONITOR_LED         0
+#define HAS_RSSI               0
+
+/*
+ * Profiling Viterbi decoding
+ */
+
+#ifndef AO_PROFILE
+#define AO_PROFILE             0
+#endif
+
+/*
+ * PWM output
+ */
+
+#define NUM_PWM                        4
+#define PWM_MAX                        20000
+#define AO_PWM_TIMER           stm_tim4
+#define AO_PWM_TIMER_ENABLE    STM_RCC_APB1ENR_TIM4EN
+#define AO_PWM_TIMER_SCALE     32
+
+#define AO_PWM_0_GPIO          (&stm_gpiod)
+#define AO_PWM_0_PIN           12
+
+#define AO_PWM_1_GPIO          (&stm_gpiod)
+#define AO_PWM_1_PIN           13
+
+#define AO_PWM_2_GPIO          (&stm_gpiod)
+#define AO_PWM_2_PIN           15
+
+#define AO_PWM_3_GPIO          (&stm_gpiod)
+#define AO_PWM_3_PIN           14
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/telemega-v7.0-seeed/ao_telemega_seeed.c b/src/telemega-v7.0-seeed/ao_telemega_seeed.c
new file mode 100644 (file)
index 0000000..b056fe5
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * Copyright © 2021 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.
+ *
+ * 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.h>
+#include <ao_bmi088.h>
+#include <ao_mmc5983.h>
+#include <ao_adxl375.h>
+#include <ao_log.h>
+#include <ao_exti.h>
+#include <ao_packet.h>
+#include <ao_companion.h>
+#include <ao_profile.h>
+#include <ao_eeprom.h>
+#include <ao_i2c_bit.h>
+#if HAS_SAMPLE_PROFILE
+#include <ao_sample_profile.h>
+#endif
+#include <ao_pyro.h>
+#if HAS_STACK_GUARD
+#include <ao_mpu.h>
+#endif
+#include <ao_pwm.h>
+
+#define AO_FAIL_FLASH  1
+#define AO_FAIL_ADC    2
+#define AO_FAIL_GPS    3
+#define AO_FAIL_RADIO  4
+#define AO_FAIL_ACCEL  5
+#define AO_FAIL_BARO   6
+#define AO_FAIL_IMU    7
+#define AO_FAIL_MAG    8
+#define AO_FAIL_RANGE  9
+
+static void
+ao_validate(void)
+{
+       static struct ao_telemetry_location     gps_data;
+       static struct ao_telemetry_satellite    gps_tracking_data;
+       uint8_t new;
+       uint8_t data;
+       int16_t decivolt;
+       AO_TICK_TYPE    gps_start;
+
+       ao_config_get();
+       /* Check the flash part */
+       ao_storage_setup();
+       if (ao_storage_total != 8 * 1024 * 1024)
+               ao_panic(AO_FAIL_FLASH);
+
+       /* Check the battery voltage */
+       data = ao_data_head;
+       do {
+               ao_sleep((void *) &ao_data_head);
+       } while (ao_data_head == data);
+       decivolt = ao_battery_decivolt(ao_data_ring[data].adc.v_batt);
+       if (decivolt < 35 || 55 < decivolt)
+               ao_panic(AO_FAIL_ADC);
+
+       /* Check to make sure GPS data is being received */
+       gps_start = ao_time();
+       for (;;) {
+               while ((new = ao_gps_new) == 0)
+                       ao_sleep_for(&ao_gps_new, AO_SEC_TO_TICKS(1));
+               ao_mutex_get(&ao_gps_mutex);
+               if (new & AO_GPS_NEW_DATA)
+                       memcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data));
+               if (new & AO_GPS_NEW_TRACKING)
+                       memcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data));
+               ao_gps_new = 0;
+               ao_mutex_put(&ao_gps_mutex);
+
+               if (new & AO_GPS_NEW_DATA) {
+                       if (gps_data.flags & AO_GPS_RUNNING)
+                               break;
+               }
+               if ((AO_TICK_SIGNED) (ao_time() - gps_start) > (AO_TICK_SIGNED) AO_SEC_TO_TICKS(10))
+                       ao_panic(AO_FAIL_GPS);
+       }
+
+       if (!ao_radio_post())
+               ao_panic(AO_FAIL_RADIO);
+
+       ao_sample_init();
+       ao_flight_state = ao_flight_startup;
+       for (;;) {
+
+               /*
+                * Process ADC samples, just looping
+                * until the sensors are calibrated.
+                */
+               if (ao_sample())
+                       break;
+       }
+
+       if (ao_sensor_errors & AO_DATA_MS5607)
+               ao_panic(AO_FAIL_BARO);
+       if (ao_sensor_errors & AO_DATA_BMI088)
+               ao_panic(AO_FAIL_IMU);
+       if (ao_sensor_errors & AO_DATA_MMC5983)
+               ao_panic(AO_FAIL_MAG);
+       if (ao_sensor_errors & AO_DATA_ADXL375)
+               ao_panic(AO_FAIL_ACCEL);
+       if (ao_sensor_errors)
+               ao_panic(AO_FAIL_RANGE);
+
+       /* Check ground accel value to make sure it's somewhat valid */
+       if (ao_ground_accel < (accel_t) AO_CONFIG_DEFAULT_ACCEL_PLUS_G - ACCEL_NOSE_UP ||
+           ao_ground_accel > (accel_t) AO_CONFIG_DEFAULT_ACCEL_MINUS_G + ACCEL_NOSE_UP) {
+               ao_panic(AO_FAIL_ACCEL);
+       }
+       if (ao_ground_height < -1000 || ao_ground_height > 7000)
+               ao_panic(AO_FAIL_BARO);
+
+       ao_led_on(AO_LED_GREEN);
+       ao_beep_for(AO_BEEP_MID_DEFAULT, AO_MS_TO_TICKS(100));
+
+       ao_exit();
+}
+
+struct ao_task ao_validate_task;
+
+int
+main(void)
+{
+       ao_clock_init();
+
+#if HAS_STACK_GUARD
+       ao_mpu_init();
+#endif
+
+       ao_task_init();
+       ao_serial_init();
+       ao_led_init();
+       ao_led_off(LEDS_AVAILABLE);
+       ao_timer_init();
+
+       ao_spi_init();
+#ifdef MMC5983_I2C
+       ao_i2c_bit_init();
+#endif
+       ao_dma_init();
+       ao_exti_init();
+
+       ao_adc_init();
+#if HAS_BEEP
+       ao_beep_init();
+#endif
+       ao_cmd_init();
+
+       ao_ms5607_init();
+       ao_bmi088_init();
+       ao_mmc5983_init();
+       ao_adxl375_init();
+
+       ao_eeprom_init();
+       ao_storage_init();
+
+       ao_usb_init();
+       ao_gps_init();
+
+       ao_radio_init();
+       ao_igniter_init();
+       ao_pyro_init();
+
+       ao_config_init();
+#if AO_PROFILE
+       ao_profile_init();
+#endif
+#if HAS_SAMPLE_PROFILE
+       ao_sample_profile_init();
+#endif
+
+       ao_pwm_init();
+
+       ao_add_task(&ao_validate_task, ao_validate, "validate");
+
+       ao_start_scheduler();
+       return 0;
+}
diff --git a/src/telemega-v7.0-seeed/flash-loader/ao_pins.h b/src/telemega-v7.0-seeed/flash-loader/ao_pins.h
new file mode 100644 (file)
index 0000000..46ba162
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright © 2021 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.
+ *
+ * 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.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+/* External crystal at 16MHz */
+#define AO_HSE         16000000
+
+#include <ao_flash_stm_pins.h>
+
+/* Companion port cs_companion0 PB6 */
+
+#define AO_BOOT_PIN                    1
+#define AO_BOOT_APPLICATION_GPIO       stm_gpiob
+#define AO_BOOT_APPLICATION_PIN                6
+#define AO_BOOT_APPLICATION_VALUE      1
+#define AO_BOOT_APPLICATION_MODE       AO_EXTI_MODE_PULL_UP
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/telemega-v7.0/.gitignore b/src/telemega-v7.0/.gitignore
new file mode 100644 (file)
index 0000000..e67759a
--- /dev/null
@@ -0,0 +1,2 @@
+ao_product.h
+telemega-*.elf
diff --git a/src/telemega-v7.0/Makefile b/src/telemega-v7.0/Makefile
new file mode 100644 (file)
index 0000000..a9e8300
--- /dev/null
@@ -0,0 +1,130 @@
+#
+# AltOS build
+#
+#
+
+include ../stm/Makefile.defs
+
+INC = \
+       ao.h \
+       ao_arch.h \
+       ao_arch_funcs.h \
+       ao_boot.h \
+       ao_companion.h \
+       ao_data.h \
+       ao_sample.h \
+       ao_pins.h \
+       altitude-pa.h \
+       ao_kalman.h \
+       ao_product.h \
+       ao_ms5607.h \
+       ao_bmi088.h \
+       ao_mmc5983.h \
+       ao_adxl375.h \
+       ao_cc1200_CC1200.h \
+       ao_profile.h \
+       ao_task.h \
+       ao_whiten.h \
+       ao_sample_profile.h \
+       ao_quaternion.h \
+       ao_mpu.h \
+       stm32l.h \
+       ao_ms5607_convert.c \
+       Makefile
+
+#
+# Common AltOS sources
+#
+
+#PROFILE=ao_profile.c
+#PROFILE_DEF=-DAO_PROFILE=1
+
+#SAMPLE_PROFILE=ao_sample_profile.c \
+#      ao_sample_profile_timer.c
+#SAMPLE_PROFILE_DEF=-DHAS_SAMPLE_PROFILE=1
+
+#STACK_GUARD=ao_mpu_stm.c
+#STACK_GUARD_DEF=-DHAS_STACK_GUARD=1
+
+ALTOS_SRC = \
+       ao_boot_chain.c \
+       ao_interrupt.c \
+       ao_product.c \
+       ao_romconfig.c \
+       ao_cmd.c \
+       ao_config.c \
+       ao_task.c \
+       ao_led_stm.c \
+       ao_stdio.c \
+       ao_panic.c \
+       ao_timer.c \
+       ao_mutex.c \
+       ao_serial_stm.c \
+       ao_gps_ublox.c \
+       ao_gps_show.c \
+       ao_gps_report_mega.c \
+       ao_ignite.c \
+       ao_freq.c \
+       ao_dma_stm.c \
+       ao_spi_stm.c \
+       ao_cc1200.c \
+       ao_data.c \
+       ao_ms5607.c \
+       ao_adxl375.c \
+       ao_adc_stm.c \
+       ao_beep_stm.c \
+       ao_eeprom_stm.c \
+       ao_storage.c \
+       ao_m25.c \
+       ao_usb_stm.c \
+       ao_exti_stm.c \
+       ao_report.c \
+       ao_bmi088.c \
+       ao_mmc5983.c \
+       ao_convert_pa.c \
+       ao_convert_volt.c \
+       ao_log.c \
+       ao_log_mega.c \
+       ao_sample.c \
+       ao_kalman.c \
+       ao_flight.c \
+       ao_telemetry.c \
+       ao_packet_slave.c \
+       ao_packet.c \
+       ao_companion.c \
+       ao_pyro.c \
+       ao_aprs.c \
+       ao_pwm_stm.c \
+       $(PROFILE) \
+       $(SAMPLE_PROFILE) \
+       $(STACK_GUARD)
+
+PRODUCT=TeleMega-v7.0
+PRODUCT_DEF=-DTELEMEGA
+IDPRODUCT=0x0023
+
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF)
+
+PROGNAME=telemega-v7.0
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_telemega.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+       $(call quiet,CC) $(LDFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+$(OBJ): $(INC)
+
+distclean:     clean
+
+clean:
+       rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx $(PROGNAME)-*.map
+       rm -f ao_product.h
+
+install:
+
+uninstall:
diff --git a/src/telemega-v7.0/ao_pins.h b/src/telemega-v7.0/ao_pins.h
new file mode 100644 (file)
index 0000000..9844261
--- /dev/null
@@ -0,0 +1,489 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+
+/* 16MHz High speed external crystal */
+#define AO_HSE                 16000000
+
+/* PLLVCO = 96MHz (so that USB will work) */
+#define AO_PLLMUL              6
+#define AO_RCC_CFGR_PLLMUL     (STM_RCC_CFGR_PLLMUL_6)
+
+/* SYSCLK = 32MHz (no need to go faster than CPU) */
+#define AO_PLLDIV              3
+#define AO_RCC_CFGR_PLLDIV     (STM_RCC_CFGR_PLLDIV_3)
+
+/* HCLK = 32MHz (CPU clock) */
+#define AO_AHB_PRESCALER       1
+#define AO_RCC_CFGR_HPRE_DIV   STM_RCC_CFGR_HPRE_DIV_1
+
+/* Run APB1 at 16MHz (HCLK/2) */
+#define AO_APB1_PRESCALER      2
+#define AO_RCC_CFGR_PPRE1_DIV  STM_RCC_CFGR_PPRE2_DIV_2
+
+/* Run APB2 at 16MHz (HCLK/2) */
+#define AO_APB2_PRESCALER      2
+#define AO_RCC_CFGR_PPRE2_DIV  STM_RCC_CFGR_PPRE2_DIV_2
+
+#define HAS_SERIAL_1           0
+#define USE_SERIAL_1_STDIN     0
+#define SERIAL_1_PB6_PB7       0
+#define SERIAL_1_PA9_PA10      0
+
+#define HAS_SERIAL_2           1
+#define USE_SERIAL_2_STDIN     0
+#define SERIAL_2_PA2_PA3       1
+#define SERIAL_2_PD5_PD6       0
+#define USE_SERIAL_2_FLOW      0
+#define USE_SERIAL_2_SW_FLOW   0
+
+#define HAS_SERIAL_3           0
+#define USE_SERIAL_3_STDIN     0
+#define SERIAL_3_PB10_PB11     0
+#define SERIAL_3_PC10_PC11     0
+#define SERIAL_3_PD8_PD9       0
+
+#define ao_gps_getchar         ao_serial2_getchar
+#define ao_gps_putchar         ao_serial2_putchar
+#define ao_gps_set_speed       ao_serial2_set_speed
+#define ao_gps_fifo            (ao_stm_usart2.rx_fifo)
+
+#define AO_UBLOX_VERSION       10
+
+#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX       (1024 * 1024)
+#define AO_CONFIG_MAX_SIZE                     1024
+#define LOG_ERASE_MARK                         0x55
+#define LOG_MAX_ERASE                          128
+#define AO_LOG_FORMAT                          AO_LOG_FORMAT_TELEMEGA_7
+#define AO_TELEMETRY_MEGA_DATA                         AO_TELEMETRY_MEGA_DATA_30V
+#define AO_LOG_NORMALIZED                      1
+
+#define HAS_EEPROM             1
+#define USE_INTERNAL_FLASH     0
+#define USE_EEPROM_CONFIG      1
+#define USE_STORAGE_CONFIG     0
+#define HAS_USB                        1
+#define HAS_BEEP               1
+#define BEEPER_TIMER           3
+#define BEEPER_CHANNEL         2
+#define BEEPER_PORT            (&stm_gpioe)
+#define BEEPER_PIN             4
+#define HAS_BATTERY_REPORT     1
+#define HAS_RADIO              1
+#define HAS_TELEMETRY          1
+#define HAS_APRS               1
+#define HAS_COMPANION          1
+
+#define HAS_SPI_1              1
+#define SPI_1_PA5_PA6_PA7      1       /* Barometer */
+#define SPI_1_PB3_PB4_PB5      1       /* Accelerometer */
+#define SPI_1_PE13_PE14_PE15   1       /* MPU6000 */
+#define SPI_1_OSPEEDR          STM_OSPEEDR_10MHz
+
+//#define MMC5983_I2C          1
+
+#define HAS_SPI_2              1
+#define SPI_2_PB13_PB14_PB15   1       /* Flash, Companion */
+#ifndef MMC5983_I2C
+#define SPI_2_PD1_PD3_PD4      1       /* MMC5983 */
+#endif
+#define SPI_2_OSPEEDR          STM_OSPEEDR_10MHz
+
+#define HAS_I2C_1              0
+#define I2C_1_PB8_PB9          0
+
+#define HAS_I2C_2              0
+#define I2C_2_PB10_PB11                0
+
+#define PACKET_HAS_SLAVE       1
+#define PACKET_HAS_MASTER      0
+
+#define LOW_LEVEL_DEBUG                0
+
+#define LED_PORT_ENABLE                STM_RCC_AHBENR_GPIOCEN
+#define LED_PORT               (&stm_gpioc)
+#define LED_PIN_RED            8
+#define LED_PIN_GREEN          9
+#define AO_LED_RED             (1 << LED_PIN_RED)
+#define AO_LED_GREEN           (1 << LED_PIN_GREEN)
+
+#define LEDS_AVAILABLE         (AO_LED_RED | AO_LED_GREEN)
+
+#define HAS_GPS                        1
+#define HAS_FLIGHT             1
+#define HAS_ADC                        1
+#define HAS_ADC_TEMP           1
+#define HAS_LOG                        1
+
+/*
+ * Igniter
+ */
+
+#define HAS_IGNITE             1
+#define HAS_IGNITE_REPORT      1
+
+#define AO_SENSE_PYRO(p,n)     ((p)->adc.sense[n])
+#define AO_SENSE_DROGUE(p)     ((p)->adc.sense[4])
+#define AO_SENSE_MAIN(p)       ((p)->adc.sense[5])
+#define AO_IGNITER_CLOSED      400
+#define AO_IGNITER_OPEN                60
+
+/* Pyro A */
+#define AO_PYRO_PORT_0 (&stm_gpiod)
+#define AO_PYRO_PIN_0  6
+
+/* Pyro B */
+#define AO_PYRO_PORT_1 (&stm_gpiod)
+#define AO_PYRO_PIN_1  7
+
+/* Pyro C */
+#define AO_PYRO_PORT_2 (&stm_gpioe)
+#define AO_PYRO_PIN_2  3
+
+/* Pyro D */
+#define AO_PYRO_PORT_3 (&stm_gpioe)
+#define AO_PYRO_PIN_3  2
+
+/* Drogue */
+#define AO_IGNITER_DROGUE_PORT (&stm_gpioe)
+#define AO_IGNITER_DROGUE_PIN  6
+
+/* Main */
+#define AO_IGNITER_MAIN_PORT   (&stm_gpioe)
+#define AO_IGNITER_MAIN_PIN    5
+
+/* Number of general purpose pyro channels available */
+#define AO_PYRO_NUM    4
+
+/*
+ * ADC
+ */
+#define AO_DATA_RING           32
+#define AO_ADC_NUM_SENSE       6
+
+struct ao_adc {
+       int16_t                 sense[AO_ADC_NUM_SENSE];
+       int16_t                 v_batt;
+       int16_t                 v_pbatt;
+       int16_t                 temp;
+};
+
+#define AO_ADC_DUMP(p) \
+       printf("tick: %5lu A: %5d B: %5d C: %5d D: %5d drogue: %5d main: %5d batt: %5d pbatt: %5d temp: %5d\n", \
+              (p)->tick, \
+              (p)->adc.sense[0], (p)->adc.sense[1], (p)->adc.sense[2], \
+              (p)->adc.sense[3], (p)->adc.sense[4], (p)->adc.sense[5], \
+              (p)->adc.v_batt, (p)->adc.v_pbatt, (p)->adc.temp)
+
+#define AO_ADC_SENSE_A         0
+#define AO_ADC_SENSE_A_PORT    (&stm_gpioa)
+#define AO_ADC_SENSE_A_PIN     0
+
+#define AO_ADC_SENSE_B         1
+#define AO_ADC_SENSE_B_PORT    (&stm_gpioa)
+#define AO_ADC_SENSE_B_PIN     1
+
+#define AO_ADC_SENSE_C         24
+#define AO_ADC_SENSE_C_PORT    (&stm_gpioe)
+#define AO_ADC_SENSE_C_PIN     9
+
+#define AO_ADC_SENSE_D         25
+#define AO_ADC_SENSE_D_PORT    (&stm_gpioe)
+#define AO_ADC_SENSE_D_PIN     10
+
+#define AO_ADC_SENSE_DROGUE    4
+#define AO_ADC_SENSE_DROGUE_PORT       (&stm_gpioa)
+#define AO_ADC_SENSE_DROGUE_PIN        4
+
+#define AO_ADC_SENSE_MAIN      22
+#define AO_ADC_SENSE_MAIN_PORT (&stm_gpioe)
+#define AO_ADC_SENSE_MAIN_PIN  7
+
+#define AO_ADC_V_BATT          8
+#define AO_ADC_V_BATT_PORT     (&stm_gpiob)
+#define AO_ADC_V_BATT_PIN      0
+
+#define AO_ADC_V_PBATT         9
+#define AO_ADC_V_PBATT_PORT    (&stm_gpiob)
+#define AO_ADC_V_PBATT_PIN     1
+
+#define AO_ADC_TEMP            16
+
+#define AO_ADC_RCC_AHBENR      ((1 << STM_RCC_AHBENR_GPIOAEN) | \
+                                (1 << STM_RCC_AHBENR_GPIOEEN) | \
+                                (1 << STM_RCC_AHBENR_GPIOBEN))
+
+#define AO_NUM_ADC_PIN         (AO_ADC_NUM_SENSE + 2)
+
+#define AO_ADC_PIN0_PORT       AO_ADC_SENSE_A_PORT
+#define AO_ADC_PIN0_PIN                AO_ADC_SENSE_A_PIN
+#define AO_ADC_PIN1_PORT       AO_ADC_SENSE_B_PORT
+#define AO_ADC_PIN1_PIN                AO_ADC_SENSE_B_PIN
+#define AO_ADC_PIN2_PORT       AO_ADC_SENSE_C_PORT
+#define AO_ADC_PIN2_PIN                AO_ADC_SENSE_C_PIN
+#define AO_ADC_PIN3_PORT       AO_ADC_SENSE_D_PORT
+#define AO_ADC_PIN3_PIN                AO_ADC_SENSE_D_PIN
+#define AO_ADC_PIN4_PORT       AO_ADC_SENSE_DROGUE_PORT
+#define AO_ADC_PIN4_PIN                AO_ADC_SENSE_DROGUE_PIN
+#define AO_ADC_PIN5_PORT       AO_ADC_SENSE_MAIN_PORT
+#define AO_ADC_PIN5_PIN                AO_ADC_SENSE_MAIN_PIN
+#define AO_ADC_PIN6_PORT       AO_ADC_V_BATT_PORT
+#define AO_ADC_PIN6_PIN                AO_ADC_V_BATT_PIN
+#define AO_ADC_PIN7_PORT       AO_ADC_V_PBATT_PORT
+#define AO_ADC_PIN7_PIN                AO_ADC_V_PBATT_PIN
+
+#define AO_NUM_ADC             (AO_ADC_NUM_SENSE + 3)
+
+#define AO_ADC_SQ1             AO_ADC_SENSE_A
+#define AO_ADC_SQ2             AO_ADC_SENSE_B
+#define AO_ADC_SQ3             AO_ADC_SENSE_C
+#define AO_ADC_SQ4             AO_ADC_SENSE_D
+#define AO_ADC_SQ5             AO_ADC_SENSE_DROGUE
+#define AO_ADC_SQ6             AO_ADC_SENSE_MAIN
+#define AO_ADC_SQ7             AO_ADC_V_BATT
+#define AO_ADC_SQ8             AO_ADC_V_PBATT
+#define AO_ADC_SQ9             AO_ADC_TEMP
+
+/*
+ * Voltage divider on ADC battery sampler
+ */
+#define AO_BATTERY_DIV_PLUS    56      /* 5.6k */
+#define AO_BATTERY_DIV_MINUS   100     /* 10k */
+
+/*
+ * Voltage divider on ADC pyro battery sampler
+ */
+#define AO_PYRO_BATTERY_DIV_PLUS       100     /* 100k */
+#define AO_PYRO_BATTERY_DIV_MINUS      12      /* 12k */
+
+/*
+ * Voltage divider on ADC igniter samplers
+ */
+#define AO_IGNITE_DIV_PLUS     100     /* 100k */
+#define AO_IGNITE_DIV_MINUS    12      /* 12k */
+
+/*
+ * ADC reference in decivolts
+ */
+#define AO_ADC_REFERENCE_DV    33
+
+/*
+ * Pressure sensor settings
+ */
+#define HAS_MS5607             1
+#define HAS_MS5611             0
+#define AO_MS5607_PRIVATE_PINS 1
+#define AO_MS5607_CS_PORT      (&stm_gpioc)
+#define AO_MS5607_CS_PIN       4
+#define AO_MS5607_CS_MASK      (1 << AO_MS5607_CS)
+#define AO_MS5607_MISO_PORT    (&stm_gpioa)
+#define AO_MS5607_MISO_PIN     6
+#define AO_MS5607_MISO_MASK    (1 << AO_MS5607_MISO)
+#define AO_MS5607_SPI_INDEX    AO_SPI_1_PA5_PA6_PA7
+
+/*
+ * SPI Flash memory
+ */
+
+#define M25_MAX_CHIPS          1
+#define AO_M25_SPI_CS_PORT     (&stm_gpiod)
+#define AO_M25_SPI_CS_MASK     (1 << 10)
+#define AO_M25_SPI_BUS         AO_SPI_2_PB13_PB14_PB15
+
+/*
+ * Radio (cc1200)
+ */
+
+/* gets pretty close to 434.550 */
+
+#define AO_RADIO_CAL_DEFAULT   5695733
+
+#define AO_FEC_DEBUG           0
+#define AO_CC1200_SPI_CS_PORT  (&stm_gpioc)
+#define AO_CC1200_SPI_CS_PIN   5
+#define AO_CC1200_SPI_BUS      AO_SPI_2_PB13_PB14_PB15
+#define AO_CC1200_SPI          stm_spi2
+
+#define AO_CC1200_INT_PORT             (&stm_gpiob)
+#define AO_CC1200_INT_PIN              11
+
+#define AO_CC1200_INT_GPIO     2
+#define AO_CC1200_INT_GPIO_IOCFG       CC1200_IOCFG2
+
+#define AO_CC1200_MARC_GPIO    3
+#define AO_CC1200_MARC_GPIO_IOCFG      CC1200_IOCFG3
+
+#define HAS_BOOT_RADIO         0
+
+
+/*
+ *
+ * Here are the required sensor signs:
+ *
+ * +along      nose up
+ * +across     USB down
+ * +through    TH down
+ *
+ * With the board aligned to have positive accel for the relevant
+ * axis, looking down from above we have:
+ *
+ * +roll       counter clockwise (nose up)
+ * +pitch      counter clockwise (USB down)
+ * +yaw                counter clockwise (TH down)
+ */
+
+/*
+ * On TMega v6, bmi088 pin 1 (NE corner of chip) is placed towards the
+ * USB and antenna edges of the board. Relative to bmi088 specs, to
+ * get the above values, we need to flip the Y axis, assigning values
+ * as follows:
+ *
+ *     +along          +X      +roll   +X
+ *     +across         -Y      +pitch  -Y
+ *     +through        +Z      +yaw    +Z
+ */
+
+#define HAS_BMI088             1
+#define AO_BMI088_SPI_BUS      AO_SPI_1_PE13_PE14_PE15
+#define AO_BMI088_ACC_CS_PORT  (&stm_gpioc)
+#define AO_BMI088_ACC_CS_PIN   14
+#define AO_BMI088_GYR_CS_PORT  (&stm_gpioc)
+#define AO_BMI088_GYR_CS_PIN   13
+#define HAS_IMU                        1
+
+#define ao_bmi088_along(m)     ((m)->acc.x)
+#define ao_bmi088_across(m)    (-(m)->acc.y)
+#define ao_bmi088_through(m)   ((m)->acc.z)
+
+#define ao_bmi088_roll(m)      ((m)->gyr.x)
+#define ao_bmi088_pitch(m)     (-(m)->gyr.y)
+#define ao_bmi088_yaw(m)       ((m)->gyr.z)
+
+#define ao_data_along(packet)  ao_bmi088_along(&(packet)->bmi088)
+#define ao_data_across(packet) ao_bmi088_across(&(packet)->bmi088)
+#define ao_data_through(packet)        ao_bmi088_through(&(packet)->bmi088)
+
+#define ao_data_roll(packet)   ao_bmi088_roll(&(packet)->bmi088)
+#define ao_data_pitch(packet)  ao_bmi088_pitch(&(packet)->bmi088)
+#define ao_data_yaw(packet)    ao_bmi088_yaw(&(packet)->bmi088)
+
+/*
+ * MMC5983
+ *
+ *     pin 1 NE corner of chip
+ *
+ *     +along          -Y
+ *     +across         +X
+ *     +through        -Z
+ */
+
+#define HAS_MMC5983            1
+#define AO_MMC5983_INT_PORT    (&stm_gpiod)
+#define AO_MMC5983_INT_PIN     5
+#define AO_MMC5983_SPI_CLK_PORT        (&stm_gpiod)
+#define AO_MMC5983_SPI_CLK_PIN 1
+#define AO_MMC5983_SPI_MISO_PORT       (&stm_gpiod)
+#define AO_MMC5983_SPI_MISO_PIN        3
+#define AO_MMC5983_SPI_MOSI_PORT       (&stm_gpiod)
+#define AO_MMC5983_SPI_MOSI_PIN        4
+#define AO_MMC5983_SPI_INDEX   (AO_SPI_2_PD1_PD3_PD4 | AO_SPI_MODE_3)
+#define AO_MMC5983_SPI_CS_PORT (&stm_gpioa)
+#define AO_MMC5983_SPI_CS_PIN  15
+
+#define ao_mmc5983_along(m)            (-(m)->y)
+#define ao_mmc5983_across(m)           ((m)->x)
+#define ao_mmc5983_through(m)          (-(m)->z)
+
+#define ao_data_mag_along(packet)      ao_mmc5983_along(&(packet)->mmc5983)
+#define ao_data_mag_across(packet)     ao_mmc5983_across(&(packet)->mmc5983)
+#define ao_data_mag_through(packet)    ao_mmc5983_through(&(packet)->mmc5983)
+
+/*
+ * ADXL375
+ *
+ * pin 1 NW corner of chip
+ *
+ *     +along          +X
+ *     +across         +Y
+ *     +through        +Z
+ */
+
+#define HAS_ADXL375            1
+#define AO_ADXL375_SPI_INDEX   (AO_SPI_1_PB3_PB4_PB5 | AO_SPI_MODE_3)
+#define AO_ADXL375_CS_PORT     (&stm_gpioc)
+#define AO_ADXL375_CS_PIN      0
+
+#define AO_ADXL375_AXIS                x
+#define AO_ADXL375_INVERT      1
+
+#define NUM_CMDS               16
+
+/*
+ * Companion
+ */
+
+#define AO_COMPANION_CS_PORT   (&stm_gpiob)
+#define AO_COMPANION_CS_PIN_0  (6)
+#define AO_COMPANION_CS_PIN    AO_COMPANION_CS_PIN_0
+#define AO_COMPANION_CS_PIN_1  (7)
+#define AO_COMPANION_SPI_BUS   AO_SPI_2_PB13_PB14_PB15
+
+/*
+ * Monitor
+ */
+
+#define HAS_MONITOR            0
+#define LEGACY_MONITOR         0
+#define HAS_MONITOR_PUT                1
+#define AO_MONITOR_LED         0
+#define HAS_RSSI               0
+
+/*
+ * Profiling Viterbi decoding
+ */
+
+#ifndef AO_PROFILE
+#define AO_PROFILE             0
+#endif
+
+/*
+ * PWM output
+ */
+
+#define NUM_PWM                        4
+#define PWM_MAX                        20000
+#define AO_PWM_TIMER           stm_tim4
+#define AO_PWM_TIMER_ENABLE    STM_RCC_APB1ENR_TIM4EN
+#define AO_PWM_TIMER_SCALE     32
+
+#define AO_PWM_0_GPIO          (&stm_gpiod)
+#define AO_PWM_0_PIN           12
+
+#define AO_PWM_1_GPIO          (&stm_gpiod)
+#define AO_PWM_1_PIN           13
+
+#define AO_PWM_2_GPIO          (&stm_gpiod)
+#define AO_PWM_2_PIN           15
+
+#define AO_PWM_3_GPIO          (&stm_gpiod)
+#define AO_PWM_3_PIN           14
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/telemega-v7.0/ao_telemega.c b/src/telemega-v7.0/ao_telemega.c
new file mode 100644 (file)
index 0000000..91526a8
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright © 2021 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.
+ *
+ * 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.h>
+#include <ao_bmi088.h>
+#include <ao_mmc5983.h>
+#include <ao_adxl375.h>
+#include <ao_log.h>
+#include <ao_exti.h>
+#include <ao_packet.h>
+#include <ao_companion.h>
+#include <ao_profile.h>
+#include <ao_eeprom.h>
+#include <ao_i2c_bit.h>
+#if HAS_SAMPLE_PROFILE
+#include <ao_sample_profile.h>
+#endif
+#include <ao_pyro.h>
+#if HAS_STACK_GUARD
+#include <ao_mpu.h>
+#endif
+#include <ao_pwm.h>
+
+int
+main(void)
+{
+       ao_clock_init();
+
+#if HAS_STACK_GUARD
+       ao_mpu_init();
+#endif
+
+       ao_task_init();
+       ao_serial_init();
+       ao_led_init();
+       ao_led_on(LEDS_AVAILABLE);
+       ao_timer_init();
+
+       ao_spi_init();
+#ifdef MMC5983_I2C
+       ao_i2c_bit_init();
+#endif
+       ao_dma_init();
+       ao_exti_init();
+
+       ao_adc_init();
+#if HAS_BEEP
+       ao_beep_init();
+#endif
+       ao_cmd_init();
+
+       ao_ms5607_init();
+       ao_bmi088_init();
+       ao_mmc5983_init();
+       ao_adxl375_init();
+
+       ao_eeprom_init();
+       ao_storage_init();
+
+       ao_flight_init();
+       ao_log_init();
+       ao_report_init();
+
+       ao_usb_init();
+       ao_gps_init();
+       ao_gps_report_mega_init();
+       ao_telemetry_init();
+       ao_radio_init();
+       ao_packet_slave_init(false);
+       ao_igniter_init();
+       ao_companion_init();
+       ao_pyro_init();
+
+       ao_config_init();
+#if AO_PROFILE
+       ao_profile_init();
+#endif
+#if HAS_SAMPLE_PROFILE
+       ao_sample_profile_init();
+#endif
+
+       ao_pwm_init();
+
+       ao_led_off(LEDS_AVAILABLE);
+
+       ao_start_scheduler();
+       return 0;
+}
diff --git a/src/telemega-v7.0/flash-loader/Makefile b/src/telemega-v7.0/flash-loader/Makefile
new file mode 100644 (file)
index 0000000..415f1d9
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=telemega-v7.0
+include $(TOPDIR)/stm/Makefile-flash.defs
diff --git a/src/telemega-v7.0/flash-loader/ao_pins.h b/src/telemega-v7.0/flash-loader/ao_pins.h
new file mode 100644 (file)
index 0000000..46ba162
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright © 2021 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.
+ *
+ * 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.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+/* External crystal at 16MHz */
+#define AO_HSE         16000000
+
+#include <ao_flash_stm_pins.h>
+
+/* Companion port cs_companion0 PB6 */
+
+#define AO_BOOT_PIN                    1
+#define AO_BOOT_APPLICATION_GPIO       stm_gpiob
+#define AO_BOOT_APPLICATION_PIN                6
+#define AO_BOOT_APPLICATION_VALUE      1
+#define AO_BOOT_APPLICATION_MODE       AO_EXTI_MODE_PULL_UP
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/telemetrum-v4.0-seeed/.gitignore b/src/telemetrum-v4.0-seeed/.gitignore
new file mode 100644 (file)
index 0000000..35ce24d
--- /dev/null
@@ -0,0 +1,2 @@
+ao_product.h
+telemetrum-*.elf
diff --git a/src/telemetrum-v4.0-seeed/Makefile b/src/telemetrum-v4.0-seeed/Makefile
new file mode 100644 (file)
index 0000000..540d023
--- /dev/null
@@ -0,0 +1,132 @@
+#
+# AltOS build
+#
+#
+
+include ../samd21/Makefile.defs
+
+INC = \
+        ao.h \
+        ao_arch.h \
+        ao_arch_funcs.h \
+        ao_boot.h \
+        ao_companion.h \
+        ao_data.h \
+        ao_sample.h \
+        ao_pins.h \
+        altitude-pa.h \
+        ao_kalman.h \
+        ao_product.h \
+        ao_ms5607.h \
+        ao_adxl375.h \
+        ao_cc1200_CC1200.h \
+        ao_task.h \
+        ao_whiten.h \
+       samd21.h \
+       Makefile
+
+# SAMD21G17D
+
+SAMD21_ROM=128
+SAMD21_RAM=16
+
+#PROFILE=ao_profile.c
+#PROFILE_DEF=-DAO_PROFILE=1
+
+#SAMPLE_PROFILE=ao_sample_profile.c \
+#       ao_sample_profile_timer.c
+#SAMPLE_PROFILE_DEF=-DHAS_SAMPLE_PROFILE=1
+
+#STACK_GUARD=ao_mpu_stm.c
+#STACK_GUARD_DEF=-DHAS_STACK_GUARD=1
+
+ALTOS_SRC = \
+       ao_boot_chain.c \
+        ao_interrupt.c \
+        ao_product.c \
+        ao_romconfig.c \
+        ao_cmd.c \
+        ao_config.c \
+        ao_task.c \
+        ao_led.c \
+        ao_stdio.c \
+        ao_panic.c \
+        ao_timer.c \
+        ao_mutex.c \
+        ao_serial_samd21.c \
+        ao_gps_ublox.c \
+        ao_gps_show.c \
+        ao_gps_report_metrum.c \
+        ao_ignite.c \
+        ao_freq.c \
+        ao_dma_samd21.c \
+        ao_spi_samd21.c \
+        ao_cc1200.c \
+        ao_data.c \
+        ao_ms5607.c \
+        ao_adxl375.c \
+        ao_adc_samd21.c \
+        ao_beep_samd21.c \
+        ao_storage.c \
+        ao_m25.c \
+       ao_usb_samd21.c \
+       ao_exti_samd21.c \
+        ao_report.c \
+        ao_convert_pa.c \
+        ao_convert_volt.c \
+        ao_log.c \
+        ao_log_metrum.c \
+        ao_sample.c \
+        ao_kalman.c \
+        ao_flight.c \
+        ao_telemetry.c \
+        ao_packet_slave.c \
+        ao_packet.c \
+        ao_companion.c \
+        ao_aprs.c \
+        $(PROFILE) \
+        $(SAMPLE_PROFILE) \
+        $(STACK_GUARD)
+
+PRODUCT=TeleMetrum-v4.0
+PRODUCT_DEF=-DTELEMETRUM_V_4_0
+IDPRODUCT=0x000b
+
+CFLAGS = $(PRODUCT_DEF) $(SAMD21_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF)
+
+PROGNAME=telemetrum-v4.0-seeed
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+FLASH_PROG=flash-loader/$(PROGNAME)-altos-flash-$(VERSION).elf
+BOTH_HEX=$(PROGNAME)-combined-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_telemetrum_seeed.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX) $(BOTH_HEX)
+
+$(PROG): Makefile $(OBJ)
+       $(call quiet,CC) $(LDFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+$(BOTH_HEX): $(PROG) $(FLASH_PROG)
+       ../../ao-tools/ao-elftohex/ao-elftohex -n --output=$@ $(FLASH_PROG) $(PROG)
+
+$(FLASH_PROG): FRC
+       +cd flash-loader && make
+
+FRC:
+
+$(OBJ): $(INC)
+
+load: $(PROG)
+       stm-load $(PROG)
+
+distclean:     clean
+
+clean:
+       rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx $(PROGNAME)-*.map
+       rm -f ao_product.h
+
+install:
+
+uninstall:
diff --git a/src/telemetrum-v4.0-seeed/ao_pins.h b/src/telemetrum-v4.0-seeed/ao_pins.h
new file mode 100644 (file)
index 0000000..164b1e5
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ * Copyright © 2022 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.
+ *
+ * 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.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define AO_XOSC                        1
+#define AO_XOSC_FREQ           16000000
+#define AO_XOSC_DIV            256
+#define AO_XOSC_MUL            768
+
+#define AO_AHB_PRESCALER       1
+#define AO_APBA_PRESCALER      1
+
+#define HAS_SERIAL_1           1
+#define USE_SERIAL_1_STDIN     0
+
+#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX       (512 * 1024)
+#define AO_CONFIG_DEFAULT_ACCEL_PLUS_G         -20
+#define AO_CONFIG_DEFAULT_ACCEL_MINUS_G                20
+#define AO_CONFIG_MAX_SIZE                     1024
+#define LOG_ERASE_MARK                         0x55
+#define LOG_MAX_ERASE                          128
+#define AO_LOG_FORMAT                          AO_LOG_FORMAT_TELEMETRUM
+
+#define HAS_EEPROM             1
+#define USE_INTERNAL_FLASH     0
+#define USE_EEPROM_CONFIG      0
+#define USE_STORAGE_CONFIG     1
+#define HAS_USB                        1
+#define USE_USB_STDIO  1
+#define HAS_BATTERY_REPORT     1
+#define BEEPER_CHANNEL         4
+#define BEEPER_TIMER           3
+#define BEEPER_PORT            (&samd21_port_a)
+#define BEEPER_PIN             16
+#define HAS_RADIO              1
+#define HAS_RADIO_10MW         1
+#define HAS_TELEMETRY          1
+#define HAS_APRS               1
+#define HAS_COMPANION          1
+
+#define HAS_SPI_0              1
+#define HAS_SPI_3              1
+#define HAS_SPI_5              1
+
+#define PACKET_HAS_SLAVE       1
+#define PACKET_HAS_MASTER      0
+
+#define LOW_LEVEL_DEBUG                0
+
+#define HAS_LED                        1
+#define LED_0_PORT             (&samd21_port_b)
+#define LED_0_PIN              10
+#define LED_1_PORT             (&samd21_port_b)
+#define LED_1_PIN              11
+#define AO_LED_RED             (1 << 0)
+#define AO_LED_GREEN           (1 << 1)
+
+#define HAS_GPS                        1
+#define HAS_FLIGHT             1
+#define HAS_ADC                        1
+#define HAS_ADC_TEMP           1
+#define HAS_LOG                        1
+
+/*
+ * Beeper
+ */
+
+#define HAS_BEEP               1
+/* Beep on PA16 function E TCC2.0 */
+
+#define AO_BEEP_TCC            (&samd21_tcc2)
+#define AO_BEEP_TCC_APBC_MASK  SAMD21_PM_APBCMASK_TCC2
+#define AO_BEEP_PORT           (&samd21_port_a)
+#define AO_BEEP_PIN            (16)
+#define AO_BEEP_FUNC           SAMD21_PORT_PMUX_FUNC_E
+
+/*
+ * Igniter
+ */
+
+#define HAS_IGNITE             1
+#define HAS_IGNITE_REPORT      1
+
+#define AO_SENSE_DROGUE(p)     ((p)->adc.sense_a)
+#define AO_SENSE_MAIN(p)       ((p)->adc.sense_m)
+#define AO_IGNITER_CLOSED      400
+#define AO_IGNITER_OPEN                60
+
+/* Drogue */
+#define AO_IGNITER_DROGUE_PORT (&samd21_port_a)
+#define AO_IGNITER_DROGUE_PIN  19
+
+/* Main */
+#define AO_IGNITER_MAIN_PORT   (&samd21_port_a)
+#define AO_IGNITER_MAIN_PIN    18
+
+/*
+ * ADC
+ */
+#define AO_DATA_RING           32
+#define AO_ADC_NUM_SENSE       2
+
+struct ao_adc {
+       int16_t                 sense_a;
+       int16_t                 sense_m;
+       int16_t                 v_batt;
+       int16_t                 temp;
+};
+
+#define AO_ADC_DUMP(p) \
+       printf("tick: %5lu drogue: %5d main: %5d batt: %5d\n", \
+              (p)->tick, \
+              (p)->adc.sense_a, (p)->adc.sense_m, \
+              (p)->adc.v_batt);
+
+#define AO_ADC_SENSE_DROGUE            18
+#define AO_ADC_SENSE_DROGUE_PORT       (&samd21_port_a)
+#define AO_ADC_SENSE_DROGUE_PIN                10
+
+#define AO_ADC_SENSE_MAIN              19
+#define AO_ADC_SENSE_MAIN_PORT         (&samd21_port_a)
+#define AO_ADC_SENSE_MAIN_PIN          11
+
+#define AO_ADC_V_BATT                  17
+#define AO_ADC_V_BATT_PORT             (&samd21_port_a)
+#define AO_ADC_V_BATT_PIN              9
+
+#define AO_ADC_TEMP                    SAMD21_ADC_INPUTCTRL_MUXPOS_TEMP
+
+#define AO_NUM_ADC_PIN                 3
+
+#define AO_ADC_PIN0_PORT       AO_ADC_SENSE_DROGUE_PORT
+#define AO_ADC_PIN0_PIN                AO_ADC_SENSE_DROGUE_PIN
+#define AO_ADC_PIN1_PORT       AO_ADC_SENSE_MAIN_PORT
+#define AO_ADC_PIN1_PIN                AO_ADC_SENSE_MAIN_PIN
+#define AO_ADC_PIN2_PORT       AO_ADC_V_BATT_PORT
+#define AO_ADC_PIN2_PIN                AO_ADC_V_BATT_PIN
+
+#define AO_NUM_ADC             (AO_NUM_ADC_PIN + 1)
+
+#define AO_ADC_SQ0             AO_ADC_SENSE_DROGUE
+#define AO_ADC_SQ1             AO_ADC_SENSE_MAIN
+#define AO_ADC_SQ2             AO_ADC_V_BATT
+#define AO_ADC_SQ3             AO_ADC_TEMP
+
+/*
+ * Voltage divider on ADC battery sampler
+ */
+#define AO_BATTERY_DIV_PLUS    56      /* 5.6k */
+#define AO_BATTERY_DIV_MINUS   100     /* 10k */
+
+/*
+ * Voltage divider on ADC igniter samplers
+ */
+#define AO_IGNITE_DIV_PLUS     100     /* 100k */
+#define AO_IGNITE_DIV_MINUS    27      /* 27k */
+
+/*
+ * ADC reference in decivolts
+ */
+#define AO_ADC_REFERENCE_DV    33
+
+/*
+ * GPS
+ */
+
+#define AO_SERIAL_SPEED_UBLOX  AO_SERIAL_SPEED_9600
+#define AO_UBLOX_VERSION       10
+
+#define HAS_SERIAL_1           1
+#define USE_SERIAL_1_STDIN     0
+#define SERIAL_1_PA00_PA01     1
+
+#define ao_gps_getchar         ao_serial1_getchar
+#define ao_gps_putchar         ao_serial1_putchar
+#define ao_gps_set_speed       ao_serial1_set_speed
+#define ao_gps_fifo            (ao_samd21_usart1.rx_fifo)
+
+/*
+ * Pressure sensor settings
+ */
+#define HAS_MS5607             1
+#define HAS_MS5611             0
+#define AO_MS5607_PRIVATE_PINS 0
+#define AO_MS5607_CS_PORT      (&samd21_port_a)
+#define AO_MS5607_CS_PIN       21
+#define AO_MS5607_MISO_PORT    (&samd21_port_a)
+#define AO_MS5607_MISO_PIN     20
+#define AO_MS5607_SPI_INDEX    AO_SPI_3_PA22_PA23_PA20
+
+/*
+ * SPI Flash memory
+ */
+
+#define M25_MAX_CHIPS          1
+#define AO_M25_SPI_CS_PORT     (&samd21_port_a)
+#define AO_M25_SPI_CS_MASK     (1 << 27)
+#define AO_M25_SPI_BUS         AO_SPI_5_PB22_PB23_PB03
+
+
+/*
+ * Radio (cc1200)
+ */
+
+/* gets pretty close to 434.550 */
+
+#define AO_RADIO_CAL_DEFAULT   5695733
+
+#define AO_CC1200_SPI_CS_PORT  (&samd21_port_a)
+#define AO_CC1200_SPI_CS_PIN   7
+#define AO_CC1200_SPI_BUS      AO_SPI_5_PB22_PB23_PB03
+
+#define AO_CC1200_INT_PORT             (&samd21_port_b)
+#define AO_CC1200_INT_PIN              (8)
+#define AO_CC1200_MCU_WAKEUP_PORT      (&samd21_port_b)
+#define AO_CC1200_MCU_WAKEUP_PIN       (9)
+
+#define AO_CC1200_INT_GPIO     2
+#define AO_CC1200_INT_GPIO_IOCFG       CC1200_IOCFG2
+
+#define AO_CC1200_MARC_GPIO    3
+#define AO_CC1200_MARC_GPIO_IOCFG      CC1200_IOCFG3
+
+#define HAS_BOOT_RADIO         0
+
+#define HAS_HIGHG_ACCEL                1
+
+/* ADXL375 */
+
+#define HAS_ADXL375            1
+#define AO_ADXL375_CS_PORT     (&samd21_port_a)
+#define AO_ADXL375_CS_PIN      8
+#define AO_ADXL375_SPI_INDEX   (AO_SPI_0_PA04_PA05_PA06 | AO_SPI_MODE_3)
+
+#define AO_ADXL375_AXIS                x
+#define AO_ADXL375_INVERT      1
+
+#define NUM_CMDS               16
+
+/*
+ * Companion
+ */
+
+#define AO_COMPANION_CS_PORT   (&samd21_port_a)
+#define AO_COMPANION_CS_PIN    (13)
+#define AO_COMPANION_SPI_BUS   AO_SPI_5_PB22_PB23_PB03
+
+/*
+ * Monitor
+ */
+
+#define HAS_MONITOR            0
+#define LEGACY_MONITOR         0
+#define HAS_MONITOR_PUT                1
+#define AO_MONITOR_LED         0
+#define HAS_RSSI               0
+
+/*
+ * Profiling Viterbi decoding
+ */
+
+#ifndef AO_PROFILE
+#define AO_PROFILE             0
+#endif
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/telemetrum-v4.0-seeed/ao_telemetrum_seeed.c b/src/telemetrum-v4.0-seeed/ao_telemetrum_seeed.c
new file mode 100644 (file)
index 0000000..b448eda
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * Copyright © 2016 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.
+ *
+ * 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.h>
+#include <ao_ms5607.h>
+#include <ao_adxl375.h>
+#include <ao_log.h>
+#include <ao_exti.h>
+#include <ao_packet.h>
+#include <ao_companion.h>
+#include <ao_eeprom.h>
+#if HAS_SAMPLE_PROFILE
+#include <ao_profile.h>
+#include <ao_sample_profile.h>
+#endif
+#if HAS_STACK_GUARD
+#include <ao_mpu.h>
+#endif
+#include <ao_dma_samd21.h>
+
+#define AO_FAIL_FLASH  1
+#define AO_FAIL_ADC    2
+#define AO_FAIL_GPS    3
+#define AO_FAIL_RADIO  4
+#define AO_FAIL_ACCEL  5
+#define AO_FAIL_BARO   6
+#define AO_FAIL_RANGE  7
+
+static void
+ao_validate(void)
+{
+       static struct ao_telemetry_location     gps_data;
+       static struct ao_telemetry_satellite    gps_tracking_data;
+       uint8_t new;
+       uint8_t data;
+       int16_t decivolt;
+       AO_TICK_TYPE    gps_start;
+
+       ao_config_get();
+       /* Check the flash part */
+       ao_storage_setup();
+       if (ao_storage_total != 8 * 1024 * 1024)
+               ao_panic(AO_FAIL_FLASH);
+
+       /* Check the battery voltage */
+       data = ao_data_head;
+       do {
+               ao_sleep((void *) &ao_data_head);
+       } while (ao_data_head == data);
+       decivolt = ao_battery_decivolt(ao_data_ring[data].adc.v_batt);
+       if (decivolt < 35 || 55 < decivolt)
+               ao_panic(AO_FAIL_ADC);
+
+       /* Check to make sure GPS data is being received */
+       gps_start = ao_time();
+       for (;;) {
+               while ((new = ao_gps_new) == 0)
+                       ao_sleep_for(&ao_gps_new, AO_SEC_TO_TICKS(1));
+               ao_mutex_get(&ao_gps_mutex);
+               if (new & AO_GPS_NEW_DATA)
+                       memcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data));
+               if (new & AO_GPS_NEW_TRACKING)
+                       memcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data));
+               ao_gps_new = 0;
+               ao_mutex_put(&ao_gps_mutex);
+
+               if (new & AO_GPS_NEW_DATA) {
+                       if (gps_data.flags & AO_GPS_RUNNING)
+                               break;
+               }
+               if ((AO_TICK_SIGNED) (ao_time() - gps_start) > (AO_TICK_SIGNED) AO_SEC_TO_TICKS(10))
+                       ao_panic(AO_FAIL_GPS);
+       }
+
+       if (!ao_radio_post())
+               ao_panic(AO_FAIL_RADIO);
+
+       ao_sample_init();
+       ao_flight_state = ao_flight_startup;
+       for (;;) {
+
+               /*
+                * Process ADC samples, just looping
+                * until the sensors are calibrated.
+                */
+               if (ao_sample())
+                       break;
+       }
+
+       if (ao_sensor_errors & AO_DATA_MS5607)
+               ao_panic(AO_FAIL_BARO);
+       if (ao_sensor_errors & AO_DATA_ADXL375)
+               ao_panic(AO_FAIL_ACCEL);
+       if (ao_sensor_errors)
+               ao_panic(AO_FAIL_RANGE);
+
+       /* Check ground accel value to make sure it's somewhat valid */
+       if (ao_ground_accel < (accel_t) AO_CONFIG_DEFAULT_ACCEL_PLUS_G - ACCEL_NOSE_UP ||
+           ao_ground_accel > (accel_t) AO_CONFIG_DEFAULT_ACCEL_MINUS_G + ACCEL_NOSE_UP) {
+               ao_panic(AO_FAIL_ACCEL);
+       }
+       if (ao_ground_height < -1000 || ao_ground_height > 7000)
+               ao_panic(AO_FAIL_BARO);
+
+       ao_led_on(AO_LED_GREEN);
+       ao_beep_for(AO_BEEP_MID_DEFAULT, AO_MS_TO_TICKS(100));
+
+       ao_exit();
+}
+
+struct ao_task ao_validate_task;
+
+int
+main(void)
+{
+       ao_clock_init();
+
+#if HAS_STACK_GUARD
+       ao_mpu_init();
+#endif
+
+       ao_task_init();
+       ao_serial_init();
+       ao_led_init();
+       ao_led_off(LEDS_AVAILABLE);
+       ao_timer_init();
+
+       ao_spi_init();
+       ao_dma_init();
+       ao_exti_init();
+
+       ao_adc_init();
+       ao_beep_init();
+       ao_cmd_init();
+
+       ao_ms5607_init();
+       ao_adxl375_init();
+
+       ao_storage_init();
+
+       ao_usb_init();
+       ao_gps_init();
+
+       ao_radio_init();
+       ao_igniter_init();
+
+       ao_config_init();
+#if AO_PROFILE
+       ao_profile_init();
+#endif
+#if HAS_SAMPLE_PROFILE
+       ao_sample_profile_init();
+#endif
+
+       ao_add_task(&ao_validate_task, ao_validate, "validate");
+
+       ao_start_scheduler();
+       return 0;
+}
diff --git a/src/telemetrum-v4.0-seeed/flash-loader/Makefile b/src/telemetrum-v4.0-seeed/flash-loader/Makefile
new file mode 100644 (file)
index 0000000..46ca8cf
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=telemetrum-v4.0-seeed
+include $(TOPDIR)/samd21/Makefile-flash.defs
diff --git a/src/telemetrum-v4.0-seeed/flash-loader/ao_pins.h b/src/telemetrum-v4.0-seeed/flash-loader/ao_pins.h
new file mode 100644 (file)
index 0000000..5653c24
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright © 2022 Bdale Garbee <bdale@gag.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.
+ *
+ * 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.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#include <ao_flash_samd21_pins.h>
+
+/* cs_comp_0 (companion port pin 6) to gnd for boot loader mode */
+
+#define AO_BOOT_PIN                    1
+#define AO_BOOT_APPLICATION_GPIO       (samd21_port_a)
+#define AO_BOOT_APPLICATION_PIN                13
+#define AO_BOOT_APPLICATION_VALUE      1
+#define AO_BOOT_APPLICATION_MODE       AO_MODE_PULL_UP
+
+/* USB */
+#define HAS_USB                        1
+
+#define AO_XOSC                        1
+#define AO_XOSC_FREQ           16000000
+#define AO_XOSC_DIV            256
+#define AO_XOSC_MUL            768
+
+#endif /* _AO_PINS_H_ */
index 55a3fbeb5abda9c98d7bffc7b7e587bd575a092e..2c74780d1fac362f6a9305ac7190196279cc1c9b 100644 (file)
@@ -3,11 +3,12 @@ vpath %.c ..:../kernel:../drivers:../util:../micropeak:../aes:../product
 vpath %.h ..:../kernel:../drivers:../util:../micropeak:../aes:../product
 vpath make-kalman ..:../kernel:../drivers:../util:../micropeak:../aes:../product
 
-PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_flight_test_mm \
+PROGS=ao_flight_test_mm \
        ao_flight_test_metrum ao_flight_test_mini \
        ao_gps_test ao_gps_test_skytraq ao_gps_test_ublox ao_convert_test ao_convert_pa_test ao_fec_test \
        ao_aprs_test ao_micropeak_test ao_fat_test ao_aes_test ao_int64_test \
-       ao_ms5607_convert_test ao_quaternion_test
+       ao_ms5607_convert_test ao_quaternion_test \
+       ao_flight_test_tmega4
 
 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
@@ -16,7 +17,7 @@ TEST_LIB=-ljson-c
 
 KALMAN=make-kalman 
 
-CFLAGS=-I.. -I. -I../kernel -I../drivers -I../micropeak -I../product -I../lisp -O0 -g -Wall -DAO_LISP_TEST -no-pie
+CFLAGS=-I.. -I. -I../kernel -I../drivers -I../product -I../lisp -O0 -g -Wall -DAO_LISP_TEST -no-pie
 
 all: $(PROGS) ao_aprs_data.wav
 
@@ -40,6 +41,9 @@ ao_flight_test_accel: $(TEST_SRC_ALL) ao_host.h ao_flight.c  ao_sample.c ao_kalm
 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_tmega4: $(TEST_SRC_ALL) ao_host.h ao_flight.c ao_sample.c ao_kalman.c ao_pyro.c ao_pyro.h $(INCS)
+       cc -DTELEMEGA_V4=1 $(CFLAGS) -o $@ $(TEST_SRC)  $(TEST_LIB) -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
 
@@ -86,7 +90,7 @@ ao_micropeak_test: ao_micropeak_test.c ao_microflight.c ao_kalman.h
        cc $(CFLAGS) -o $@ ao_micropeak_test.c -lm
 
 ao_fat_test: ao_fat_test.c ao_fat.c ao_bufio.c
-       cc $(CFLAGS) -o $@ ao_fat_test.c -lssl -lcrypto
+       cc $(CFLAGS) -o $@ ao_fat_test.c -Wno-deprecated-declarations -lssl -lcrypto
 
 ao_aes_test: ao_aes_test.c ao_aes.c ao_aes_tables.c
        cc $(CFLAGS) -o $@ ao_aes_test.c
index 63be71c6b378b6b0424bf7cc3ff708ce278a5dc4..dc6337fc29b917e4987a443297623d680523617d 100644 (file)
@@ -485,7 +485,7 @@ long_test_fs(void)
                }
        }
 
-       printf ("\n   **** Write IO: read %llu write %llu data sectors %llu\n", total_reads, total_writes, (total_file_size + 511) / 512);
+       printf ("\n   **** Write IO: read %lu write %lu data sectors %lu\n", total_reads, total_writes, (total_file_size + 511) / 512);
 
        check_bufio("all files created");
        printf ("   **** All done creating files\n");
@@ -518,7 +518,7 @@ long_test_fs(void)
                        check_bufio("file shown");
                }
        }
-       printf ("\n  **** Read IO: read %llu write %llu\n", total_reads, total_writes);
+       printf ("\n  **** Read IO: read %lu write %lu\n", total_reads, total_writes);
 }
 
 char *params[] = {
index cbced6ae31435fb870ee8c599c02d88f9d564d5a..7c4e6f0e627283ed08f8d7214d20592ad8f42704 100644 (file)
@@ -303,8 +303,31 @@ ao_real_packet(void)
        return ok;
 }
 
+int
+ao_hello_packet(void)
+{
+       uint8_t message[5] = "hello";
+       uint8_t encode[ENCODE_LEN(sizeof(message))];
+       int encode_len;
+       uint8_t transmit[EXPAND_LEN(sizeof(message))];
+       uint8_t decode[DECODE_LEN(sizeof(message))];
+       int transmit_len;
+       int decode_ok;
+
+       printf("Hello packet test:\n");
+       ao_fec_dump_bytes(message, sizeof(message), "Message");
+       encode_len = ao_fec_encode(message, sizeof(message), encode);
+       ao_fec_dump_bytes(encode, encode_len, "Encode");
+       transmit_len = ao_expand(encode, encode_len, transmit);
+       ao_fec_dump_bytes(transmit, transmit_len, "Transmit");
+       decode_ok = ao_fec_decode(transmit, transmit_len, decode, sizeof(message) + 2, NULL);
+       ao_fec_dump_bytes(decode, sizeof(message) + 2, "Receive");
+       printf("Hello result: %s\n", decode_ok ? "success" : "fail");
+       return decode_ok;
+}
+
 #define EXPECT_DECODE_FAIL     0
-#define EXPECT_CRC_MISMATCH    6386
+#define EXPECT_CRC_MISMATCH    6304
 #define EXPECT_DATA_MISMATCH   0
 #define NOISE_AMOUNT           0x50
 
@@ -336,6 +359,9 @@ main(int argc, char **argv)
        if (!ao_real_packet())
                errors++;
 
+       if (!ao_hello_packet())
+               errors++;
+
        srandom(0);
        for (trial = 0; trial < 100000; trial++) {
 
index fc1dfa8fe6b759b1def1caccc3ffdfa78429210b..e49035b52997abfaf68dfecca0ff25a5dc8b3941 100644 (file)
 #include <math.h>
 #define log ao_log_data
 
+#define AO_TICK_TYPE   uint32_t
+#define AO_TICK_SIGNED int32_t
+
+typedef int32_t pres_t;
+#define pres_to_altitude(p) ao_pa_to_altitude(p)
+#define ao_data_pres_cook(packet) ao_ms5607_convert(&packet->ms5607_raw, &packet->ms5607_cooked)
+#define ao_data_pres(packet) ((packet)->ms5607_cooked.pres)
+#define AO_ADC_MAX     4095
+#define AO_PYRO_BATTERY_DIV_PLUS       100
+#define AO_PYRO_BATTERY_DIV_MINUS      27
+#define AO_IGNITE_DIV_PLUS     100
+#define AO_IGNITE_DIV_MINUS    27
+#define AO_ADC_REFERENCE_DV    33
+
 #define GRAVITY 9.80665
 
 #define AO_HERTZ       100
@@ -48,7 +62,7 @@
 
 int ao_gps_new;
 
-#if !defined(TELEMEGA) && !defined(TELEMETRUM_V2) && !defined(EASYMINI) && !defined(EASYMOTOR_V_2)
+#if !defined(TELEMEGA) && !defined(TELEMETRUM_V2) && !defined(EASYMINI) && !defined(EASYMOTOR_V_2) && !defined(TELEMEGA_V4)
 #define TELEMETRUM_V1 1
 #endif
 
@@ -71,6 +85,49 @@ struct ao_adc {
 };
 #endif
 
+#if TELEMEGA_V4
+#define AO_ADC_NUM_SENSE       6
+#define HAS_MS5607             1
+#define HAS_BMX160             1
+#define HAS_ADXL375            1
+#define AO_ADXL375_INVERT      1
+#define AO_ADXL375_AXIS                x
+#define HAS_BEEP               1
+#define HAS_BARO               1
+#define AO_CONFIG_MAX_SIZE     1024
+
+struct ao_adc {
+       int16_t                 sense[AO_ADC_NUM_SENSE];
+       int16_t                 v_batt;
+       int16_t                 v_pbatt;
+       int16_t                 temp;
+};
+
+#define ao_data_along(packet)  ((packet)->bmx160.acc_x)
+#define ao_data_across(packet) (-(packet)->bmx160.acc_y)
+#define ao_data_through(packet)        ((packet)->bmx160.acc_z)
+
+#define ao_data_roll(packet)   ((packet)->bmx160.gyr_x)
+#define ao_data_pitch(packet)  (-(packet)->bmx160.gyr_y)
+#define ao_data_yaw(packet)    ((packet)->bmx160.gyr_z)
+
+#define ao_data_mag_along(packet)      ((packet)->bmx160.mag_x)
+#define ao_data_mag_across(packet)     ((packet)->bmx160.mag_y)
+#define ao_data_mag_through(packet)    ((packet)->bmx160.mag_z)
+
+#define ao_data_set_along(packet,v)    ((packet)->bmx160.acc_x = (v))
+#define ao_data_set_across(packet,v)   ((packet)->bmx160.acc_y = -(v))
+#define ao_data_set_through(packet,v)  ((packet)->bmx160.acc_z = (v))
+
+#define ao_data_set_roll(packet,v)     ((packet)->bmx160.gyr_x = (v))
+#define ao_data_set_pitch(packet,v)    ((packet)->bmx160.gyr_y = -(v))
+#define ao_data_set_yaw(packet,v)      ((packet)->bmx160.gyr_z = (v))
+
+#define ao_data_set_mag_along(packet,v)        ((packet)->bmx160.mag_x = (v))
+#define ao_data_set_mag_across(packet,v)       ((packet)->bmx160.mag_y = (v))
+#define ao_data_set_mag_through(packet,v)      ((packet)->bmx160.mag_z = (v))
+#endif
+
 #if TELEMETRUM_V2
 #define AO_ADC_NUM_SENSE       2
 #define HAS_MS5607             1
@@ -149,7 +206,7 @@ struct ao_adc {
 #define HAS_USB 1
 #define HAS_GPS 1
 
-int16_t
+AO_TICK_TYPE
 ao_time(void);
 
 void
@@ -158,12 +215,19 @@ ao_dump_state(void);
 #define ao_tick_count  (ao_time())
 #define ao_wakeup(wchan) ao_dump_state()
 
+enum ao_igniter_status {
+       ao_igniter_unknown,     /* unknown status (ambiguous voltage) */
+       ao_igniter_ready,       /* continuity detected */
+       ao_igniter_active,      /* igniter firing */
+       ao_igniter_open,        /* open circuit detected */
+};
+
 #include <ao_data.h>
 #include <ao_log.h>
 #include <ao_telemetry.h>
 #include <ao_sample.h>
 
-#if TELEMEGA
+#if TELEMEGA || TELEMEGA_V4
 int ao_gps_count;
 struct ao_telemetry_location ao_gps_first;
 struct ao_telemetry_location ao_gps_prev;
@@ -289,12 +353,12 @@ double    drogue_time;
 int    main_height;
 double main_time;
 
-int    tick_offset;
+uint32_t       tick_offset;
 
 static ao_k_t  ao_k_height;
 static double  simple_speed;
 
-int16_t
+AO_TICK_TYPE
 ao_time(void)
 {
        return ao_data_static.tick;
@@ -360,12 +424,12 @@ struct ao_cmds {
 };
 
 #define AO_NEED_ALTITUDE_TO_PRES 1
-#if TELEMEGA || TELEMETRUM_V2 || EASYMINI
+#if TELEMEGA || TELEMETRUM_V2 || EASYMINI || TELEMEGA_V4
 #include "ao_convert_pa.c"
 #include <ao_ms5607.h>
 struct ao_ms5607_prom  ao_ms5607_prom;
 #include "ao_ms5607_convert.c"
-#if TELEMEGA
+#if TELEMEGA || TELEMEGA_V4
 #define AO_PYRO_NUM    4
 #include <ao_pyro.h>
 #endif
@@ -388,7 +452,7 @@ extern int16_t ao_accel_2g;
 typedef int16_t        accel_t;
 
 uint16_t       ao_serial_number;
-int16_t                ao_flight_number;
+uint16_t       ao_flight_number;
 
 extern AO_TICK_TYPE    ao_sample_tick;
 
@@ -406,6 +470,7 @@ double ao_sample_qangle;
 
 AO_TICK_TYPE   ao_sample_prev_tick;
 AO_TICK_TYPE   prev_tick;
+AO_TICK_TYPE   start_tick;
 
 
 #include "ao_kalman.c"
@@ -413,7 +478,7 @@ AO_TICK_TYPE        prev_tick;
 #include "ao_sample.c"
 #include "ao_flight.c"
 #include "ao_data.c"
-#if TELEMEGA
+#if TELEMEGA || TELEMEGA_V4
 #define AO_PYRO_NUM    4
 
 #define AO_PYRO_0      0
@@ -426,7 +491,6 @@ AO_TICK_TYPE        prev_tick;
 static void
 ao_pyro_pin_set(uint8_t pin, uint8_t value)
 {
-       printf ("set pyro %d %d\n", pin, value);
 }
 
 #include "ao_pyro.c"
@@ -459,6 +523,9 @@ static uint16_t     pyros_fired;
 #if HAS_MPU6000
 static struct ao_mpu6000_sample        ao_ground_mpu6000;
 #endif
+#if HAS_BMX160
+static struct ao_bmx160_sample ao_ground_bmx160;
+#endif
 
 void
 ao_test_exit(void)
@@ -497,7 +564,7 @@ ao_test_exit(void)
        exit(0);
 }
 
-#ifdef TELEMEGA
+#if TELEMEGA || TELEMEGA_V4
 struct ao_azel {
        int     az;
        int     el;
@@ -529,9 +596,9 @@ ao_insert(void)
 #endif
 
                (void) accel;
-               if (!tick_offset)
-                       tick_offset = -ao_data_static.tick;
-               if ((prev_tick - ao_data_static.tick) > 0x400)
+               if (!start_tick)
+                       start_tick = ao_data_static.tick;
+               if ((AO_TICK_SIGNED) (prev_tick - ao_data_static.tick) > 0x400)
                        tick_offset += 65536;
                if (prev_tick) {
                        int ticks = ao_data_static.tick - prev_tick;
@@ -540,11 +607,11 @@ ao_insert(void)
                        simple_speed += accel * ticks / 100.0;
                }
                prev_tick = ao_data_static.tick;
-               time = (double) (ao_data_static.tick + tick_offset) / 100;
+               time = (double) (ao_data_static.tick + tick_offset - start_tick) / 100;
 
                double height = 0;
 #if HAS_BARO
-#if TELEMEGA || TELEMETRUM_V2 || EASYMINI
+#if TELEMEGA || TELEMETRUM_V2 || EASYMINI || TELEMEGA_V4
                ao_ms5607_convert(&ao_data_static.ms5607_raw, &ao_data_static.ms5607_cooked);
                height = ao_pa_to_altitude(ao_data_static.ms5607_cooked.pres) - ao_ground_height;
 
@@ -589,7 +656,7 @@ ao_insert(void)
                }
 
                if (!ao_summary) {
-#if TELEMEGA
+#if TELEMEGA || TELEMEGA_V4
                        static struct ao_quaternion     ao_ground_mag;
                        static int                      ao_ground_mag_set;
 
@@ -680,10 +747,10 @@ ao_insert(void)
 #if 1
                        printf("%7.2f height %8.2f accel %8.3f accel_speed %8.3f "
                               "state %d k_height %8.2f k_speed %8.3f k_accel %8.3f avg_height %5d drogue %4d main %4d error %5d"
-#if TELEMEGA
+#if TELEMEGA || TELEMEGA_V4
                               " angle %5d "
                               "accel_x %8.3f accel_y %8.3f accel_z %8.3f gyro_x %8.3f gyro_y %8.3f gyro_z %8.3f mag_x %8d mag_y %8d, mag_z %8d mag_angle %4d "
-                              "avg_accel %8.3f "
+                              "avg_accel %8.3f pyro %d inhibited %d"
 #endif
                               "\n",
                               time,
@@ -711,7 +778,26 @@ ao_insert(void)
                               ao_data_static.hmc5883.y,
                               ao_data_static.hmc5883.z,
                               ao_mag_angle,
-                              ao_coast_avg_accel / 16.0
+                              ao_coast_avg_accel / 16.0,
+                              ao_pyro_fired * 10,
+                              ao_pyro_inhibited * 10
+#endif
+#if TELEMEGA_V4
+                              , ao_sample_orient,
+
+                              ao_bmx160_accel(ao_data_static.bmx160.acc_x),
+                              ao_bmx160_accel(ao_data_static.bmx160.acc_y),
+                              ao_bmx160_accel(ao_data_static.bmx160.acc_z),
+                              ao_bmx160_gyro(ao_data_static.bmx160.gyr_x - ao_ground_bmx160.gyr_x),
+                              ao_bmx160_gyro(ao_data_static.bmx160.gyr_y - ao_ground_bmx160.gyr_y),
+                              ao_bmx160_gyro(ao_data_static.bmx160.gyr_z - ao_ground_bmx160.gyr_z),
+                              ao_data_static.bmx160.mag_x,
+                              ao_data_static.bmx160.mag_y,
+                              ao_data_static.bmx160.mag_z,
+                              ao_mag_angle,
+                              ao_coast_avg_accel / 16.0,
+                              ao_pyro_fired * 10,
+                              ao_pyro_inhibited * 10
 #endif
                                );
 #endif
@@ -769,7 +855,7 @@ void
 ao_sleep(void *wchan)
 {
        if (wchan == &ao_data_head) {
-#if TELEMEGA
+#if TELEMEGA || TELEMEGA_V4
                if (ao_flight_state >= ao_flight_boost && ao_flight_state < ao_flight_landed)
                        ao_pyro_check();
 #endif
@@ -780,6 +866,9 @@ ao_sleep(void *wchan)
 #if TELEMEGA
                                ao_data_static.mpu6000 = ao_ground_mpu6000;
 #endif
+#if TELEMEGA_V4
+                               ao_data_static.bmx160 = ao_ground_bmx160;
+#endif
 #if TELEMETRUM_V1
                                ao_data_static.adc.accel = ao_flight_ground_accel;
 #endif
@@ -792,7 +881,7 @@ ao_sleep(void *wchan)
                        }
 
                        if (eeprom) {
-#if TELEMEGA || EASYMOTOR_V_2
+#if TELEMEGA || EASYMOTOR_V_2 || TELEMEGA_V4
                                struct ao_log_mega      *log_mega;
 #endif
 #if EASYMOTOR_V_2
@@ -892,6 +981,102 @@ ao_sleep(void *wchan)
                                        }
                                        break;
 #endif
+#if TELEMEGA_V4
+                               case AO_LOG_FORMAT_TELEMEGA_4:
+                                       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_bmx160.acc_x = ao_ground_accel_along;
+                                               ao_ground_bmx160.acc_y = -ao_ground_accel_across;
+                                               ao_ground_bmx160.acc_z = ao_ground_accel_through;
+                                               ao_ground_bmx160.gyr_x = ao_ground_roll >> 9;
+                                               ao_ground_bmx160.gyr_y = -(ao_ground_pitch >> 9);
+                                               ao_ground_bmx160.gyr_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_set_along(&ao_data_static, log_mega->u.sensor.accel_along);
+                                               ao_data_set_across(&ao_data_static, log_mega->u.sensor.accel_across);
+                                               ao_data_set_through(&ao_data_static, log_mega->u.sensor.accel_through);
+                                               ao_data_set_roll(&ao_data_static, log_mega->u.sensor.gyro_roll);
+                                               ao_data_set_pitch(&ao_data_static, log_mega->u.sensor.gyro_pitch);
+                                               ao_data_set_yaw(&ao_data_static, log_mega->u.sensor.gyro_yaw);
+                                               ao_data_set_mag_along(&ao_data_static, log_mega->u.sensor.mag_along);
+                                               ao_data_set_mag_across(&ao_data_static, log_mega->u.sensor.mag_across);
+                                               ao_data_set_mag_through(&ao_data_static, log_mega->u.sensor.mag_through);
+#if AO_ADXL375_INVERT
+                                               ao_data_static.adxl375.AO_ADXL375_AXIS = ao_data_accel_invert(log_mega->u.sensor.accel);
+#else
+                                               ao_data_static.adxl375.AO_ADXL375_AXIS = log_mega->u.sensor.accel;
+#endif
+                                               if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP)
+                                                       ao_data_static.adxl375.AO_ADXL375_AXIS = ao_data_accel_invert(ao_data_static.adxl375.AO_ADXL375_AXIS);
+                                               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
+#ifdef foo_TELEMEGA_V4
+                               case AO_LOG_FORMAT_TELEMEGA_4:
+                                       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;
+                                               break;
+                                       case AO_LOG_SENSOR:
+                                               ao_data_static.tick = log_mega->tick;
+                                               ao_data_static.adxl375.AO_ADXL375_AXIS = log_mega->u.sensor.accel;
+                                               ao_records_read++;
+                                               ao_insert();
+                                               return;
+                                       }
+                                       break;
+#endif
 #if TELEMETRUM_V2
                                case AO_LOG_FORMAT_TELEMETRUM:
                                        log_metrum = (struct ao_log_metrum *) &eeprom->data[eeprom_offset];
index 7c1ecc15f50607a20ee3cbcd1d0a7c688aea8ba6..1e7847e5603995b842cfec83918b6e7f5a9bd76b 100644 (file)
@@ -17,6 +17,7 @@
  */
 
 #define AO_GPS_TEST
+#define AO_TICK_TYPE uint32_t
 #include "ao_host.h"
 #include <termios.h>
 #include <errno.h>
index 11c54601b9cee77d5a784848afb3a7f44033114b..bd8998b77e959741daff920669cc13b78d606329 100644 (file)
@@ -17,7 +17,9 @@
  */
 
 #define AO_GPS_TEST
+#define AO_TICK_TYPE uint32_t
 #define HAS_GPS 1
+#define tick_count 0
 #include "ao_host.h"
 #include <termios.h>
 #include <errno.h>
@@ -49,6 +51,8 @@ struct ao_gps_orig {
        int16_t                 altitude;       /* m */
        uint16_t                ground_speed;   /* cm/s */
        uint8_t                 course;         /* degrees / 2 */
+       uint8_t                 pdop;           /* unused */
+       uint8_t                 vdop;           /* unused */
        uint8_t                 hdop;           /* * 5 */
        int16_t                 climb_rate;     /* cm/s */
        uint16_t                h_error;        /* m */
index 0833e4f60a3c158b5dabb61768991b60893bed80..6cccf0e51b3af18e43e62a75a44bf920f56fbf02 100644 (file)
  */
 
 #define AO_GPS_TEST
+#define AO_TICK_TYPE uint32_t
 #define HAS_GPS        1
+#define ao_tick_count 0
 #include "ao_host.h"
 #include <termios.h>
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <stdbool.h>
 #include <fcntl.h>
 #include <unistd.h>
 #define AO_GPS_NUM_SAT_MASK    (0xf << 0)
index 952460d0c2831c2daf12808037ffa947ee019171..ac4a69bd4702f13a930a3c907bbe98c3f0b0d79d 100644 (file)
@@ -17,6 +17,7 @@
  */
 
 #define _GNU_SOURCE
+#define AO_TICK_TYPE uint32_t
 
 #include <stdint.h>
 #include <stdio.h>
index 27f8ddcdeedc832fab8a40574195551850c72c26..87f34cd9fee155de93d2b277efab6f327efc4ff5 100755 (executable)
@@ -14,7 +14,7 @@ case $# in
        exit 1
 esac
 
-gnuplot -persist << EOF
+cat - /dev/tty <<EOF | gnuplot
 set ylabel "distance (m)"
 set y2label "angle (d)"
 set xlabel "time (s)"
@@ -22,8 +22,12 @@ set xtics border out nomirror
 set ytics border out nomirror
 set y2tics border out nomirror
 set title "$title"
-plot "$file" using 1:5 with lines axes x1y1 title "height",\
-"$file" using 1:7 with lines axes x1y2 title "angle",\
-"$file" using 1:13 with lines axes x1y2 title "gps angle",\
-"$file" using 1:15 with lines axes x1y2 title "sats"
+plot "$file" using 1:3 with lines axes x1y1 title "height",\
+"$file" using 1:7 with lines axes x1y1 title "speed", \
+"$file" using 1:5 with lines axes x1y1 title "accel", \
+"$file" using 1:13 with lines axes x1y1 title "k_speed",\
+"$file" using 1:15 with lines axes x1y1 title "k_accel",\
+"$file" using 1:25 with lines axes x1y2 title "angle",\
+"$file" using 1:49 with lines axes x1y2 title "pyro",\
+"$file" using 1:51 with lines axes x1y2 title "inhibited"
 EOF
index 552abea76bdf5bc53f2e91eab23ed0f823f950af..f8e2cf15c3ccc97ed476237085e758cdf40b0c4e 100644 (file)
@@ -114,7 +114,8 @@ FIRMWARE_TBT=$(FIRMWARE_TBT_3_0) $(FIRMWARE_TBT_4_0)
 FIRMWARE_TGPS_1_0=$(top_srcdir)/src/telegps-v1.0/telegps-v1.0-$(VERSION).ihx
 FIRMWARE_TGPS_2_0=$(top_srcdir)/src/telegps-v2.0/telegps-v2.0-$(VERSION).ihx
 FIRMWARE_TGPS_3_0=$(top_srcdir)/src/telegps-v3.0/telegps-v3.0-$(VERSION).ihx
-FIRMWARE_TGPS=$(FIRMWARE_TGPS_1_0) $(FIRMWARE_TGPS_2_0) $(FIRMWARE_TGPS_3_0)
+FIRMWARE_TGPS_4_0=$(top_srcdir)/src/telegps-v4.0/telegps-v4.0-$(VERSION).ihx
+FIRMWARE_TGPS=$(FIRMWARE_TGPS_1_0) $(FIRMWARE_TGPS_2_0) $(FIRMWARE_TGPS_3_0) $(FIRMWARE_TGPS_4_0)
 
 FIRMWARE=$(FIRMWARE_TGPS) $(FIRMWARE_TD) $(FIRMWARE_TBT)
 
index b348f702ca707ddee5de949b6bc812152715b008..a4a60b6f267670f07591d1d5f41d5ed56d748d77 100644 (file)
@@ -41,6 +41,7 @@ public class TeleGPSConfigUI
        JLabel                  radio_enable_label;
        JLabel                  radio_10mw_label;
        JLabel                  report_feet_label;
+       JLabel                  gps_receiver_label;
        JLabel                  rate_label;
        JLabel                  aprs_interval_label;
        JLabel                  aprs_ssid_label;
@@ -62,6 +63,7 @@ public class TeleGPSConfigUI
        JRadioButton            radio_enable_value;
        JRadioButton            radio_10mw_value;
        JComboBox<String>       report_feet_value;
+       JComboBox<String>       gps_receiver_value;
        AltosUIRateList         rate_value;
        JComboBox<String>       aprs_interval_value;
        JComboBox<Integer>      aprs_ssid_value;
@@ -200,6 +202,39 @@ public class TeleGPSConfigUI
                        return AltosLib.MISSING;
        }
 
+       void set_gps_receiver_tool_tip() {
+               if (gps_receiver_value.isVisible())
+                       gps_receiver_value.setToolTipText("GPS receiver selection");
+               else
+                       gps_receiver_value.setToolTipText("Only TeleMega with new firmware supports alternate GPS receivers");
+       }
+
+       public void set_gps_receiver(int new_gps_receiver) {
+               System.out.printf("set_gps_receiver %d\n", new_gps_receiver);
+               if (new_gps_receiver != AltosLib.MISSING) {
+                       if (new_gps_receiver >= AltosLib.gps_receiver_names.length)
+                               new_gps_receiver = 0;
+                       if (new_gps_receiver < 0) {
+                               gps_receiver_value.setEnabled(false);
+                               new_gps_receiver = 0;
+                       } else {
+                               gps_receiver_value.setEnabled(true);
+                       }
+                       gps_receiver_value.setSelectedIndex(new_gps_receiver);
+               }
+               gps_receiver_value.setVisible(new_gps_receiver != AltosLib.MISSING);
+               gps_receiver_label.setVisible(new_gps_receiver != AltosLib.MISSING);
+
+               set_gps_receiver_tool_tip();
+       }
+
+       public int gps_receiver() {
+               if (gps_receiver_value.isVisible())
+                       return gps_receiver_value.getSelectedIndex();
+               else
+                       return AltosLib.MISSING;
+       }
+
        void set_rate_tool_tip() {
                if (rate_value.isVisible())
                        rate_value.setToolTipText("Select telemetry baud rate");
@@ -430,6 +465,32 @@ public class TeleGPSConfigUI
                set_report_feet_tool_tip();
                row++;
 
+               /* GPS Receiver */
+               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;
+               gps_receiver_label = new JLabel("GPS Receiver:");
+               pane.add(gps_receiver_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;
+               gps_receiver_value = new JComboBox<String>(AltosLib.gps_receiver_names);
+               gps_receiver_value.setEditable(false);
+               gps_receiver_value.addItemListener(this);
+               pane.add(gps_receiver_value, c);
+               set_gps_receiver_tool_tip();
+               row++;
+
                /* Radio 10mW limit */
                c = new GridBagConstraints();
                c.gridx = 0; c.gridy = row;
index e9fc683101b637bf4f1d3596ddf2227dfb1de91f..2b693bae741bcf151ce2da13c69b153ea52a05a7 100644 (file)
@@ -32,7 +32,7 @@ import org.altusmetrum.altosuilib_14.*;
 
 import org.jfree.chart.ChartPanel;
 import org.jfree.chart.JFreeChart;
-import org.jfree.ui.RefineryUtilities;
+import org.jfree.chart.ui.UIUtils;
 
 public class TeleGPSGraphUI extends AltosUIFrame implements AltosFontListener, AltosUnitsListener, AltosFilterListener
 {
index c7fb452c8628065be4b6b63614f550d0e6f4ba7d..4e686857fc2601cf871129e5e4d3655938c3d88c 100644 (file)
@@ -123,6 +123,7 @@ Section "TeleGPS, TeleDongle and TeleBT Firmware"
        File "../src/telegps-v1.0/telegps-v1.0-${VERSION}.ihx"
        File "../src/telegps-v2.0/telegps-v2.0-${VERSION}.ihx"
        File "../src/telegps-v3.0/telegps-v3.0-${VERSION}.ihx"
+       File "../src/telegps-v4.0/telegps-v4.0-${VERSION}.ihx"
        File "../src/teledongle-v3.0/teledongle-v3.0-${VERSION}.ihx"
        File "../src/telebt-v3.0/telebt-v3.0-${VERSION}.ihx"
        File "../src/telebt-v4.0/telebt-v4.0-${VERSION}.ihx"