Merge branch 'master' into branch-1.9
authorBdale Garbee <bdale@gag.com>
Tue, 16 Jun 2020 02:26:35 +0000 (20:26 -0600)
committerBdale Garbee <bdale@gag.com>
Tue, 16 Jun 2020 02:26:35 +0000 (20:26 -0600)
148 files changed:
Makefile.am
Releasing
altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosUsb.java
altoslib/AltosConfigData.java
altoslib/AltosConfigValues.java
altoslib/AltosConvert.java
altoslib/AltosEepromList.java
altoslib/AltosIMU.java
altoslib/AltosIdleFetch.java
altoslib/AltosJson.java
altoslib/AltosLib.java
altoslib/AltosMma655x.java
altoslib/AltosRotation.java
altoslib/AltosSensorEasyTimer1.java [new file with mode: 0644]
altoslib/AltosState.java
altoslib/Makefile.am
altosui/AltosConfigFC.java
altosui/AltosConfigFCUI.java
altosui/AltosPad.java
altosui/Makefile.am
altosui/altos-windows.nsi.in
altosuilib/AltosEepromDelete.java
altosuilib/AltosFlashUI.java
altosuilib/AltosInfoTable.java
altosuilib/AltosUSBDevice.java
ao-bringup/turnon_telemetrum_v2.0
ao-tools/ao-usbload/ao-usbload.1
ao-tools/lib/ao-editaltos.c
ao-tools/lib/ao-verbose.h
configure.ac
doc/Makefile.am
doc/altosui.inc
doc/altusmetrum.txt
doc/aprs-operation.inc
doc/config-device.inc
doc/configure-altimeter.png
doc/easymega.inc
doc/easymini-device.inc
doc/easymini-release-notes.inc
doc/easytimer.inc [new file with mode: 0644]
doc/easytimer.jpg [new file with mode: 0644]
doc/getting-started.inc
doc/pyro-channels.inc
doc/release-notes-1.9.3.inc [new file with mode: 0644]
doc/release-notes.inc
doc/specs.inc
doc/system-operation.inc
doc/telegps-configure.png
doc/telegps-release-notes.inc
doc/telemega.inc
doc/telemetrum.inc
doc/telemini.inc
doc/updating-firmware.inc
doc/usage.inc
doc/using-am-products.inc
map-server/altos-mapd/.gitignore
map-server/altos-mapd/Makefile.am
map-server/altos-mapd/Manifest.txt [deleted file]
map-server/altos-mapj/.gitignore
map-server/altos-mapj/Makefile.am
map-server/altos-mapj/Manifest.txt [deleted file]
src/.gitignore
src/Makedefs.in
src/Makefile
src/Makefile.defs
src/drivers/ao_adxl375.c
src/drivers/ao_aprs.c
src/drivers/ao_bmx160.h
src/drivers/ao_gps_ublox.c
src/drivers/ao_lco.c
src/drivers/ao_lco.h
src/drivers/ao_lco_bits.c
src/drivers/ao_lco_two.c
src/drivers/ao_m25.c
src/drivers/ao_mma655x.c
src/drivers/ao_mpu9250.c
src/drivers/ao_pad.c
src/drivers/ao_quadrature.c
src/easytimer-v1/.gitignore [new file with mode: 0644]
src/easytimer-v1/Makefile [new file with mode: 0644]
src/easytimer-v1/ao_easytimer.c [new file with mode: 0644]
src/easytimer-v1/ao_pins.h [new file with mode: 0644]
src/easytimer-v1/flash-loader/Makefile [new file with mode: 0644]
src/easytimer-v1/flash-loader/ao_pins.h [new file with mode: 0644]
src/kernel/ao_cmd.c
src/kernel/ao_config.c
src/kernel/ao_config.h
src/kernel/ao_data.c
src/kernel/ao_data.h
src/kernel/ao_eeprom.h
src/kernel/ao_flight.c
src/kernel/ao_ignite.c
src/kernel/ao_kalman.c
src/kernel/ao_log.c
src/kernel/ao_log.h
src/kernel/ao_log_gps.c
src/kernel/ao_log_telestatic.c
src/kernel/ao_product.c
src/kernel/ao_report.c
src/kernel/ao_sample.c
src/kernel/ao_storage.c
src/kernel/ao_storage.h
src/kernel/ao_telemetry.c
src/kernel/ao_tracker.c
src/lpc/Makefile-flash.defs
src/lpc/Makefile-lpc.defs
src/lpc/Makefile.defs
src/lpc/altos-loader.ld
src/lpc/altos.ld
src/lpc/ao_arch.h
src/lpc/ao_boot_chain.c
src/lpc/ao_interrupt.c
src/lpc/ao_usb_lpc.c
src/lpc/lpc.h
src/micropeak-v2.0/Makefile
src/micropeak-v2.0/ao_micropeak.c
src/micropeak-v2.0/micropeak.ld
src/pnpservo-v1/lambda.ld
src/stm/Makefile-flash.defs
src/stm/Makefile-stm.defs
src/stm/Makefile.defs
src/stm/altos-loader.ld
src/stm/altos.ld
src/stm/ao_arch.h
src/stm/ao_boot_chain.c
src/stm/ao_eeprom_stm.c
src/stm/ao_flash_stm.c
src/stm/ao_interrupt.c
src/stm32f4/altos-loader.ld
src/stmf0/Makefile-flash.defs
src/stmf0/Makefile-stmf0.defs
src/stmf0/Makefile.defs
src/stmf0/altos-loader.ld
src/stmf0/altos.ld
src/stmf0/ao_arch.h
src/stmf0/ao_boot_chain.c
src/stmf0/ao_flash_stm.c
src/stmf0/ao_interrupt.c
src/stmf0/ao_storage_stm.c
src/telefireone-v2.0/Makefile
src/telegps-v1.0/Makefile
src/telegps-v2.0/Makefile
src/telelco-v2.0/ao_lco_v2.c
src/telemetrum-v2.0/Makefile
src/telestatic-v3.0/Makefile
src/telestatic-v3.0/ao_telestatic.c
src/test/.gitignore
telegps/TeleGPSConfigUI.java

index a62d539a53651eecb03b7cfbf24bb23d57af7359..fcf2652c131f4d70213382c6643d5ba831f3424c 100644 (file)
@@ -53,6 +53,7 @@ fat_altos = \
        src/easymega-v1.0/easymega-v1.0-$(VERSION).ihx \
        src/easymega-v2.0/easymega-v2.0-$(VERSION).ihx \
        src/easymini-v1.0/easymini-v1.0-$(VERSION).ihx \
+       src/easytimer-v1/easytimer-v1-$(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 \
index 4f649b6e79f2ea70bfe64a5b1dccb6dbb668efa5..223a14d3c902407478c3f6627deb3865e09a18ae 100644 (file)
--- a/Releasing
+++ b/Releasing
@@ -106,6 +106,7 @@ These are Bdale's notes on how to do a release.
           src/easymega-v2.0/{*.elf,*.ihx} \
           src/easymini-v1.0/{*.elf,*.ihx} \
           src/easymini-v2.0/{*.elf,*.ihx} \
+          src/easytimer-v1/{*.elf,*.ihx} \
           src/telebt-v3.0/{*.elf,*.ihx} \
           src/telebt-v4.0/{*.elf,*.ihx} \
           src/teledongle-v3.0/{*.elf,*.ihx} \
@@ -124,6 +125,7 @@ These are Bdale's notes on how to do a release.
           src/easymega-v2.0/flash-loader/*.elf \
           src/easymini-v1.0/flash-loader/*.elf \
           src/easymini-v2.0/flash-loader/{*.elf,*.bin} \
+          src/easytimer-v1/flash-loader/{*.elf,*.bin} \
           src/telebt-v3.0/flash-loader/*.elf \
           src/telebt-v4.0/flash-loader/{*.elf,*.bin} \
           src/teledongle-v3.0/flash-loader/*.elf \
index c2ef8a700ce026fddbf37a68dd498ba01cc059f4..35514483f026af968a6a31c13bc55f734b4a250b 100644 (file)
@@ -134,7 +134,6 @@ public class AltosUsb extends AltosDroidLink {
 
                if (want_product == AltosLib.product_basestation)
                        return have_product == AltosLib.product_teledongle ||
-                               have_product == AltosLib.product_teleterra ||
                                have_product == AltosLib.product_telebt ||
                                have_product == AltosLib.product_megadongle;
 
@@ -144,7 +143,8 @@ public class AltosUsb extends AltosDroidLink {
                                have_product == AltosLib.product_easymega ||
                                have_product == AltosLib.product_telegps ||
                                have_product == AltosLib.product_easymini ||
-                               have_product == AltosLib.product_telemini;
+                               have_product == AltosLib.product_telemini ||
+                               have_product == AltosLib.product_easytimer;
 
                if (have_product == AltosLib.product_altusmetrum)       /* old devices match any request */
                        return true;
index 474af359a5fc926103d4a9794431275e4a49f449..5d58566ecb3dc0b9836e1bd676a5857f04a1cde1 100644 (file)
@@ -78,6 +78,7 @@ public class AltosConfigData {
        public int              aprs_interval;
        public int              aprs_ssid;
        public int              aprs_format;
+       public int              aprs_offset;
 
        /* HAS_BEEP */
        public int              beep;
@@ -88,6 +89,7 @@ public class AltosConfigData {
 
        /* Log listing replies */
        public int      stored_flight;
+       public AltosEepromFlight[] flights;
 
        /* HAS_TRACKER */
        public int      tracker_motion;
@@ -161,7 +163,7 @@ public class AltosConfigData {
        public int log_available() {
                switch (log_format) {
                case AltosLib.AO_LOG_FORMAT_TINY:
-                       if (stored_flight == 0)
+                       if (flights == null)
                                return 1;
                        return 0;
                case AltosLib.AO_LOG_FORMAT_TELEMETRY:
@@ -174,10 +176,10 @@ public class AltosConfigData {
                        int     log_space = log_space();
                        int     log_used;
 
-                       if (stored_flight <= 0)
+                       if (flights == null)
                                log_used = 0;
                        else
-                               log_used = stored_flight * log_max;
+                               log_used = flights.length * log_max;
                        int     log_avail;
 
                        if (log_used >= log_space)
@@ -296,6 +298,7 @@ public class AltosConfigData {
                aprs_interval = AltosLib.MISSING;
                aprs_ssid = AltosLib.MISSING;
                aprs_format = AltosLib.MISSING;
+               aprs_offset = AltosLib.MISSING;
 
                beep = AltosLib.MISSING;
 
@@ -304,7 +307,8 @@ public class AltosConfigData {
 
                storage_size = AltosLib.MISSING;
                storage_erase_unit = AltosLib.MISSING;
-               stored_flight = AltosLib.MISSING;
+               stored_flight = 0;
+               flights = null;
 
                accel_zero_along = AltosLib.MISSING;
                accel_zero_across = AltosLib.MISSING;
@@ -316,8 +320,12 @@ public class AltosConfigData {
                adjust_accel_cal();
                switch (pad_orientation) {
                case AltosLib.AO_PAD_ORIENTATION_ANTENNA_UP:
+               case AltosLib.AO_PAD_ORIENTATION_WORDS_UPRIGHT:
+               case AltosLib.AO_PAD_ORIENTATION_BIG_PARTS_UP:
                        return accel_cal_plus_cooked;
                case AltosLib.AO_PAD_ORIENTATION_ANTENNA_DOWN:
+               case AltosLib.AO_PAD_ORIENTATION_WORDS_UPSIDEDOWN:
+               case AltosLib.AO_PAD_ORIENTATION_BIG_PARTS_DOWN:
                        return invert_accel_value(accel_cal_minus_cooked);
                default:
                        return AltosLib.MISSING;
@@ -329,8 +337,12 @@ public class AltosConfigData {
                adjust_accel_cal();
                switch (pad_orientation) {
                case AltosLib.AO_PAD_ORIENTATION_ANTENNA_UP:
+               case AltosLib.AO_PAD_ORIENTATION_WORDS_UPRIGHT:
+               case AltosLib.AO_PAD_ORIENTATION_BIG_PARTS_UP:
                        return accel_cal_minus_cooked;
                case AltosLib.AO_PAD_ORIENTATION_ANTENNA_DOWN:
+               case AltosLib.AO_PAD_ORIENTATION_WORDS_UPSIDEDOWN:
+               case AltosLib.AO_PAD_ORIENTATION_BIG_PARTS_DOWN:
                        return invert_accel_value(accel_cal_plus_cooked);
                default:
                        return AltosLib.MISSING;
@@ -349,11 +361,15 @@ public class AltosConfigData {
                {
                        switch (pad_orientation) {
                        case AltosLib.AO_PAD_ORIENTATION_ANTENNA_UP:
+                       case AltosLib.AO_PAD_ORIENTATION_WORDS_UPRIGHT:
+                       case AltosLib.AO_PAD_ORIENTATION_BIG_PARTS_UP:
                                accel_cal_plus_cooked = accel_cal_plus;
                                accel_cal_minus_cooked = accel_cal_minus;
                                accel_cal_adjusted = true;
                                break;
                        case AltosLib.AO_PAD_ORIENTATION_ANTENNA_DOWN:
+                       case AltosLib.AO_PAD_ORIENTATION_WORDS_UPSIDEDOWN:
+                       case AltosLib.AO_PAD_ORIENTATION_BIG_PARTS_DOWN:
                                accel_cal_plus_cooked = invert_accel_value(accel_cal_minus);
                                accel_cal_minus_cooked = invert_accel_value(accel_cal_plus);
                                accel_cal_adjusted = true;
@@ -465,6 +481,7 @@ public class AltosConfigData {
                try { aprs_interval = get_int(line, "APRS interval:"); } catch (Exception e) {}
                try { aprs_ssid = get_int(line, "APRS SSID:"); } catch (Exception e) {}
                try { aprs_format = get_int(line, "APRS format:"); } catch (Exception e) {}
+               try { aprs_offset = get_int(line, "APRS offset:"); } catch (Exception e) {}
 
                /* HAS_BEEP */
                try { beep = get_int(line, "Beeper setting:"); } catch (Exception e) {}
@@ -481,7 +498,32 @@ public class AltosConfigData {
                try { storage_erase_unit = get_int(line, "Storage erase unit:"); } catch (Exception e) {}
 
                /* Log listing replies */
-               try { get_int(line, "flight"); stored_flight++; }  catch (Exception e) {}
+               try {
+                       int flight = get_int(line, "flight");
+                       String[] tokens = line.split("\\s+");
+                       if (tokens.length >= 6) {
+                               int     start = -1, end = -1;
+                               try {
+                                       if (tokens[2].equals("start"))
+                                               start = AltosParse.parse_hex(tokens[3]);
+                                       if (tokens[4].equals("end"))
+                                               end = AltosParse.parse_hex(tokens[5]);
+                                       if (flight != 0 && start >= 0 && end > 0) {
+                                               int len;
+                                               if (flights == null)
+                                                       len = 0;
+                                               else
+                                                       len = flights.length;
+                                               AltosEepromFlight [] new_flights = new AltosEepromFlight[len + 1];
+                                               for (int i = 0; i < len; i++)
+                                                       new_flights[i] = flights[i];
+                                               new_flights[len] = new AltosEepromFlight(flight, start, end);
+                                               flights = new_flights;
+                                               stored_flight = flights.length;
+                                       }
+                               } catch (ParseException pe) { System.out.printf("Parse error %s\n", pe.toString()); }
+                       }
+               }  catch (Exception e) {}
 
                /* HAS_GYRO */
                try {
@@ -661,6 +703,8 @@ public class AltosConfigData {
                        aprs_ssid = source.aprs_ssid();
                if (aprs_format != AltosLib.MISSING)
                        aprs_format = source.aprs_format();
+               if (aprs_offset != AltosLib.MISSING)
+                       aprs_offset = source.aprs_offset();
 
                /* HAS_BEEP */
                if (beep != AltosLib.MISSING)
@@ -696,14 +740,14 @@ public class AltosConfigData {
                        max_enabled = false;
                        break;
                default:
-                       if (stored_flight != AltosLib.MISSING)
+                       if (flights != null)
                                max_enabled = false;
                        break;
                }
 
                dest.set_flight_log_max_enabled(max_enabled);
                dest.set_radio_enable(radio_enable);
-               dest.set_flight_log_max_limit(log_space() / 1024);
+               dest.set_flight_log_max_limit(log_space() >> 10, storage_erase_unit >> 10);
                dest.set_flight_log_max(flight_log_max);
                dest.set_ignite_mode(ignite_mode);
                dest.set_pad_orientation(pad_orientation);
@@ -718,6 +762,7 @@ public class AltosConfigData {
                dest.set_aprs_interval(aprs_interval);
                dest.set_aprs_ssid(aprs_ssid);
                dest.set_aprs_format(aprs_format);
+               dest.set_aprs_offset(aprs_offset);
                dest.set_beep(beep);
                dest.set_tracker_motion(tracker_motion);
                dest.set_tracker_interval(tracker_interval);
@@ -795,7 +840,7 @@ public class AltosConfigData {
                        link.printf("c a %d %d\n", plus, minus);
 
                /* HAS_LOG */
-               if (flight_log_max != 0)
+               if (flight_log_max != 0 && flight_log_max != AltosLib.MISSING)
                        link.printf("c l %d\n", flight_log_max);
 
                /* HAS_IGNITE */
@@ -822,6 +867,8 @@ public class AltosConfigData {
                        link.printf("c S %d\n", aprs_ssid);
                if (aprs_format != AltosLib.MISSING)
                        link.printf("c C %d\n", aprs_format);
+               if (aprs_offset != AltosLib.MISSING)
+                       link.printf("c O %d\n", aprs_offset);
 
                /* HAS_BEEP */
                if (beep != AltosLib.MISSING)
index b12a610ceeaabc36e16b2e49c6b1664c6ad3eb9a..8fa3fa41b697056ee271f76b1db6dddf1b2e2b0a 100644 (file)
@@ -64,7 +64,7 @@ public interface AltosConfigValues {
 
        public abstract int flight_log_max() throws AltosConfigDataException;
 
-       public abstract void set_flight_log_max_limit(int flight_log_max_limit);
+       public abstract void set_flight_log_max_limit(int flight_log_max_limit, int storage_erase_unit);
 
        public abstract void set_ignite_mode(int new_ignite_mode);
 
@@ -104,6 +104,10 @@ public interface AltosConfigValues {
 
        public abstract void set_aprs_format(int new_aprs_format);
 
+       public abstract int aprs_offset() throws AltosConfigDataException;
+
+       public abstract void set_aprs_offset(int new_aprs_offset);
+
        public abstract int beep() throws AltosConfigDataException;
 
        public abstract void set_beep(int new_beep);
index 63cdfa6092db2e30b2f70bb00491cde2c4ff47b5..83299632a3d3e5f38b094d3a8b18c9f264793e8f 100644 (file)
@@ -276,6 +276,10 @@ public class AltosConvert {
                return 3.3 * mega_adc(raw) * (5.1 + 10.0) / 10.0;
        }
 
+       static double easy_timer_voltage(int sensor) {
+               return 3.3 * mega_adc(sensor) * (100.0 + 27.0) / 27.0;
+       }
+
        static double easy_mini_2_adc(int raw) {
                return raw / 4095.0;
        }
index 1abc638b8290f681a88991cf29e2a69f1ace16f4..0d15fa5a9e32a2ef22fb03444d4eecb6ef65728a 100644 (file)
@@ -39,6 +39,12 @@ class AltosEepromFlight {
                start = in_start;
                end = in_end;
        }
+
+       public AltosEepromFlight() {
+               flight = 0;
+               start = 0;
+               end = 0;
+       }
 }
 
 /*
@@ -55,59 +61,17 @@ public class AltosEepromList extends ArrayList<AltosEepromLog> {
                        if (remote)
                                link.start_remote();
                        config_data = new AltosConfigData (link);
-//                     if (config_data.serial == 0)
-//                             throw new IOException("no serial number found");
-
-                       ArrayList<AltosEepromFlight> flights = new ArrayList<AltosEepromFlight>();
-
-                       if (config_data.flight_log_max != 0 || config_data.log_format != 0) {
-
-                               /* Devices with newer firmware will support the 'l'
-                                * command which will list the region of storage
-                                * occupied by each available flight
-                                */
-                               link.printf("l\n");
-                               for (;;) {
-                                       String line = link.get_reply(5000);
-                                       if (line == null)
-                                               throw new TimeoutException();
-                                       if (line.contains("done"))
-                                               break;
-                                       if (line.contains("Syntax"))
-                                               continue;
-                                       String[] tokens = line.split("\\s+");
-                                       if (tokens.length < 6)
-                                               break;
-
-                                       int     flight = -1, start = -1, end = -1;
-                                       try {
-                                               if (tokens[0].equals("flight"))
-                                                       flight = AltosParse.parse_int(tokens[1]);
-                                               if (tokens[2].equals("start"))
-                                                       start = AltosParse.parse_hex(tokens[3]);
-                                               if (tokens[4].equals("end"))
-                                                       end = AltosParse.parse_hex(tokens[5]);
-                                               if (flight != 0 && start >= 0 && end > 0)
-                                                       flights.add(new AltosEepromFlight(flight, start, end));
-                                       } catch (ParseException pe) { System.out.printf("Parse error %s\n", pe.toString()); }
-                               }
-                       } else {
-
-                               /* Older devices will hold only a single
-                                * flight. This also assumes that any older
-                                * device will have a 1MB flash device
-                                */
-                               flights.add(new AltosEepromFlight(0, 0, 0xfff));
-                       }
 
                        /* With the list of flights collected, collect more complete
                         * information on them by reading the first block or two of
                         * data. This will add GPS coordinates and a date. For older
                         * firmware, this will also extract the flight number.
                         */
-                       for (AltosEepromFlight flight : flights) {
-                               add(new AltosEepromLog(config_data, link,
-                                                      flight.flight, flight.start, flight.end));
+                       if (config_data.flights != null) {
+                               for (AltosEepromFlight flight : config_data.flights) {
+                                       add(new AltosEepromLog(config_data, link,
+                                                              flight.flight, flight.start, flight.end));
+                               }
                        }
                } finally {
                        if (remote)
index 87b9f08bedb58360decd8fa2c44ea14ca85da5be..7f8be40328faa7d848965d233727a08c90dcc05b 100644 (file)
@@ -45,6 +45,7 @@ public class AltosIMU implements Cloneable {
                case imu_type_easymega_v2:
                        return counts_per_g_mpu;
                case  imu_type_telemega_v4:
+               case imu_type_easytimer_v1:
                        return counts_per_g_bmx;
                default:
                        return AltosLib.MISSING;
@@ -69,7 +70,8 @@ public class AltosIMU implements Cloneable {
                case imu_type_easymega_v1:
                case imu_type_easymega_v2:
                        return counts_per_degree_mpu;
-               case  imu_type_telemega_v4:
+               case imu_type_telemega_v4:
+               case imu_type_easytimer_v1:
                        return counts_per_degree_bmx;
                default:
                        return AltosLib.MISSING;
@@ -99,6 +101,7 @@ public class AltosIMU implements Cloneable {
                case imu_type_easymega_v2:
                        return counts_per_gauss_mpu;
                case imu_type_telemega_v4:
+               case imu_type_easytimer_v1:
                        return 100.0;
                default:
                        return AltosLib.MISSING;
@@ -156,6 +159,8 @@ public class AltosIMU implements Cloneable {
        public static final int imu_type_easymega_v1 = 3;       /* MPU6000 */
        public static final int imu_type_easymega_v2 = 4;       /* MPU9250 */
 
+       public static final int imu_type_easytimer_v1 = 5;      /* BMX160 */
+
        private int accel_across(int imu_type) {
                switch (imu_type) {
                case imu_type_telemega_v1_v2:
@@ -164,7 +169,8 @@ public class AltosIMU implements Cloneable {
                        return accel_x;
                case imu_type_easymega_v2:
                        return -accel_y;
-               case  imu_type_telemega_v4:
+               case imu_type_telemega_v4:
+               case imu_type_easytimer_v1:
                        return -accel_y;
                default:
                        return AltosLib.MISSING;
@@ -179,6 +185,7 @@ public class AltosIMU implements Cloneable {
                        return accel_y;
                case imu_type_easymega_v2:
                case imu_type_telemega_v4:
+               case imu_type_easytimer_v1:
                        return accel_x;
                default:
                        return AltosLib.MISSING;
@@ -197,6 +204,7 @@ public class AltosIMU implements Cloneable {
                        return gyro_y;
                case imu_type_easymega_v2:
                case imu_type_telemega_v4:
+               case imu_type_easytimer_v1:
                        return gyro_x;
                default:
                        return AltosLib.MISSING;
@@ -212,6 +220,7 @@ public class AltosIMU implements Cloneable {
                case imu_type_easymega_v2:
                        return -gyro_y;
                case imu_type_telemega_v4:
+               case imu_type_easytimer_v1:
                        return -gyro_y;
                default:
                        return AltosLib.MISSING;
@@ -228,8 +237,9 @@ public class AltosIMU implements Cloneable {
                case imu_type_telemega_v3:
                case imu_type_easymega_v1:
                        return imu_axis_x;
-               case imu_type_telemega_v4:
                case imu_type_easymega_v2:
+               case imu_type_telemega_v4:
+               case imu_type_easytimer_v1:
                        return imu_axis_y;
                default:
                        return AltosLib.MISSING;
@@ -245,6 +255,7 @@ public class AltosIMU implements Cloneable {
                case imu_type_easymega_v2:
                        return -mag_y;
                case imu_type_telemega_v4:
+               case imu_type_easytimer_v1:
                        return mag_y;
                default:
                        return AltosLib.MISSING;
@@ -259,6 +270,7 @@ public class AltosIMU implements Cloneable {
                        return imu_axis_y;
                case imu_type_easymega_v2:
                case imu_type_telemega_v4:
+               case imu_type_easytimer_v1:
                        return imu_axis_x;
                default:
                        return AltosLib.MISSING;
@@ -273,6 +285,7 @@ public class AltosIMU implements Cloneable {
                        return mag_y;
                case imu_type_easymega_v2:
                case imu_type_telemega_v4:
+               case imu_type_easytimer_v1:
                        return mag_x;
                default:
                        return AltosLib.MISSING;
index 2a36983f93b4cec07c3783f49cc34182da6b653e..ca3e33eb244ffc91d47a4a035a8ffad5a9e5e668 100644 (file)
@@ -33,20 +33,22 @@ class AltosIdler {
        static final int        idle_imu_tm_v4 = 3;
        static final int        idle_imu_em_v1 = 4;
        static final int        idle_imu_em_v2 = 5;
-       static final int        idle_mag = 6;
-       static final int        idle_mma655x = 7;
-       static final int        idle_ms5607 = 8;
-       static final int        idle_adxl375 = 9;
-
-       static final int        idle_sensor_tm = 10;
-       static final int        idle_sensor_metrum = 11;
-       static final int        idle_sensor_mega = 12;
-       static final int        idle_sensor_emini1 = 13;
-       static final int        idle_sensor_emini2 = 14;
-       static final int        idle_sensor_tmini2 = 15;
-       static final int        idle_sensor_tgps1 = 16;
-       static final int        idle_sensor_tgps2 = 17;
-       static final int        idle_sensor_tmini3 = 18;
+       static final int        idle_imu_et_v1 = 6;
+       static final int        idle_mag = 7;
+       static final int        idle_mma655x = 8;
+       static final int        idle_ms5607 = 9;
+       static final int        idle_adxl375 = 10;
+
+       static final int        idle_sensor_tm = 100;
+       static final int        idle_sensor_metrum = 101;
+       static final int        idle_sensor_mega = 102;
+       static final int        idle_sensor_emini1 = 103;
+       static final int        idle_sensor_emini2 = 104;
+       static final int        idle_sensor_tmini2 = 105;
+       static final int        idle_sensor_tgps1 = 106;
+       static final int        idle_sensor_tgps2 = 107;
+       static final int        idle_sensor_tmini3 = 108;
+       static final int        idle_sensor_easytimer1 = 109;
 
        public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException, TimeoutException, AltosUnknownProduct {
                for (int idler : idlers) {
@@ -69,6 +71,9 @@ class AltosIdler {
                        case idle_imu_em_v2:
                                AltosIMU.provide_data(listener, link, AltosIMU.imu_type_easymega_v2);
                                break;
+                       case idle_imu_et_v1:
+                               AltosIMU.provide_data(listener, link, AltosIMU.imu_type_easytimer_v1);
+                               break;
                        case idle_mag:
                                AltosMag.provide_data(listener, link);
                                break;
@@ -108,6 +113,9 @@ class AltosIdler {
                        case idle_sensor_tmini3:
                                AltosSensorTMini3.provide_data(listener, link);
                                break;
+                       case idle_sensor_easytimer1:
+                               AltosSensorEasyTimer1.provide_data(listener, link);
+                               break;
                        }
                }
        }
@@ -208,6 +216,9 @@ public class AltosIdleFetch implements AltosDataProvider {
                new AltosIdler("TeleGPS-v2",
                               AltosIdler.idle_gps,
                               AltosIdler.idle_sensor_tgps2),
+               new AltosIdler("EasyTimer-v1",
+                              AltosIdler.idle_imu_et_v1,
+                              AltosIdler.idle_sensor_easytimer1),
        };
 
        AltosLink               link;
index cbeeee8785ba26319f60fc439af0b6a142987a37..1c3a342df12504130095def04323323e59877253 100644 (file)
@@ -1218,6 +1218,10 @@ public class AltosJson extends JsonUtil {
                } else if (object instanceof String) {
                        type = type_string;
                        string = (String) object;
+               } else if (object == null) {
+                       System.out.printf("unexpected null object\n");
+               } else if (object.getClass() == null) {
+                       System.out.printf("unexpected null object class\n");
                } else if (object.getClass().isArray()) {
                        assert_array(true);
 
index 14cec543eb5f9d9dc374250b4a034be338ea2aa1..a7f27830cd053a99484a70b793084f5cc6b39507 100644 (file)
@@ -117,7 +117,7 @@ public class AltosLib {
        public final static int product_altusmetrum = 0x000a;
        public final static int product_telemetrum = 0x000b;
        public final static int product_teledongle = 0x000c;
-       public final static int product_teleterra = 0x000d;
+       public final static int product_easytimer = 0x000d;
        public final static int product_telebt = 0x000e;
        public final static int product_telelaunch = 0x000f;
        public final static int product_telelco = 0x0010;
@@ -153,7 +153,7 @@ public class AltosLib {
                new Product("telemetrum", product_telemetrum),
                new Product("teleballoon", product_telemetrum),
                new Product("teledongle", product_teledongle),
-               new Product("teleterra", product_teledongle),
+               new Product("easytimer", product_easytimer),
                new Product("telebt", product_telebt),
                new Product("telelaunch", product_telelaunch),
                new Product("telelco", product_telelco),
@@ -357,6 +357,10 @@ public class AltosLib {
 
        public static final int AO_PAD_ORIENTATION_ANTENNA_UP = 0;
        public static final int AO_PAD_ORIENTATION_ANTENNA_DOWN = 1;
+       public static final int AO_PAD_ORIENTATION_WORDS_UPRIGHT = 2;
+       public static final int AO_PAD_ORIENTATION_WORDS_UPSIDEDOWN = 3;
+       public static final int AO_PAD_ORIENTATION_BIG_PARTS_UP = 4;
+       public static final int AO_PAD_ORIENTATION_BIG_PARTS_DOWN = 5;
 
        public static final int AO_LOG_FORMAT_UNKNOWN = 0;
        public static final int AO_LOG_FORMAT_FULL = 1;
@@ -586,7 +590,7 @@ public class AltosLib {
                case product_altusmetrum: return "AltusMetrum";
                case product_telemetrum: return "TeleMetrum";
                case product_teledongle: return "TeleDongle";
-               case product_teleterra: return "TeleTerra";
+               case product_easytimer: return "EasyTimer";
                case product_telebt: return "TeleBT";
                case product_telelaunch: return "TeleLaunch";
                case product_telelco: return "TeleLco";
index c009b8209b97e82dcda1430d0e98f789f915b621..1a730c11780bd0de5533c6de8d5619f87f949977 100644 (file)
@@ -55,7 +55,7 @@ public class AltosMma655x implements Cloneable {
                                int accel = mma655x.accel;
                                if (cal_data.mma655x_inverted)
                                        accel = 4095 - accel;
-                               if (cal_data.pad_orientation == 1)
+                               if (cal_data.pad_orientation == AltosLib.AO_PAD_ORIENTATION_ANTENNA_DOWN)
                                        accel = 4095 - accel;
                                listener.set_acceleration(cal_data.acceleration(accel));
                        }
index 7bcea4874095e4d8c83610ffc23c71b07e4dfc5e..85e213b25f5a0ef0700c3151b6723ee8ff34b925 100644 (file)
@@ -97,7 +97,7 @@ public class AltosRotation extends AltosQuaternion {
                             double z,
                             int pad_orientation) {
                AltosQuaternion orient = AltosQuaternion.vector(x, y, z).normalize();
-               double sky = pad_orientation == 0 ? 1 : -1;
+               double sky = (pad_orientation & 1) == 0 ? 1 : -1;
                AltosQuaternion up = new AltosQuaternion(0, 0, 0, sky);
                rotation = up.vectors_to_rotation(orient);
        }
diff --git a/altoslib/AltosSensorEasyTimer1.java b/altoslib/AltosSensorEasyTimer1.java
new file mode 100644 (file)
index 0000000..dcf7692
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright © 2020 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;
+
+class AltosSensorEasyTimer1 {
+       int             tick;
+       int[]           sense;
+       int             v_batt;
+       int             v_pbatt;
+       int             temp;
+
+       public AltosSensorEasyTimer1() {
+               sense = new int[2];
+       }
+
+       public AltosSensorEasyTimer1(AltosLink link) throws InterruptedException, TimeoutException {
+               this();
+               String[] items = link.adc();
+               for (int i = 0; i < items.length;) {
+                       if (items[i].equals("tick:")) {
+                               tick = Integer.parseInt(items[i+1]);
+                               i += 2;
+                               continue;
+                       }
+                       if (items[i].equals("A:")) {
+                               sense[0] = Integer.parseInt(items[i+1]);
+                               i += 2;
+                               continue;
+                       }
+                       if (items[i].equals("B:")) {
+                               sense[1] = Integer.parseInt(items[i+1]);
+                               i += 2;
+                               continue;
+                       }
+                       if (items[i].equals("batt:")) {
+                               v_batt = Integer.parseInt(items[i+1]);
+                               i += 2;
+                               continue;
+                       }
+                       i++;
+               }
+       }
+
+       static public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException {
+               try {
+                       AltosSensorEasyTimer1   sensor_easytimer1 = new AltosSensorEasyTimer1(link);
+
+                       listener.set_battery_voltage(AltosConvert.easy_timer_voltage(sensor_easytimer1.v_batt));
+
+                       double[]        igniter_voltage = new double[2];
+                       for (int i = 0; i < 2; i++)
+                               igniter_voltage[i] = AltosConvert.easy_timer_voltage(sensor_easytimer1.sense[i]);
+                       listener.set_igniter_voltage(igniter_voltage);
+
+               } catch (TimeoutException te) {
+               }
+       }
+}
+
index e3ea0524e90b8bd3d873aeb50d7ba722e6a80340..fc9727481201162bf636e6c4324b2d3140458310 100644 (file)
@@ -307,13 +307,12 @@ public class AltosState extends AltosDataListener {
        class AltosGpsGroundAltitude extends AltosValue {
                void set(double a, double t) {
                        super.set(a, t);
-                       pad_alt = value();
+
                        gps_altitude.set_gps_height();
                }
 
                void set_filtered(double a, double t) {
                        super.set_filtered(a, t);
-                       pad_alt = value();
                        gps_altitude.set_gps_height();
                }
 
@@ -693,7 +692,7 @@ public class AltosState extends AltosDataListener {
 
        public double   gps_height;
 
-       public double pad_lat, pad_lon, pad_alt;
+       public double pad_lat, pad_lon;
 
        public int      speak_tick;
        public double   speak_altitude;
@@ -775,7 +774,6 @@ public class AltosState extends AltosDataListener {
 
                pad_lat = AltosLib.MISSING;
                pad_lon = AltosLib.MISSING;
-               pad_alt = AltosLib.MISSING;
 
                gps_altitude = new AltosGpsAltitude();
                gps_ground_altitude = new AltosGpsGroundAltitude();
index b7d30051f87d351da8c061e129a6b6a9a9e4e2d4..0c9392d18a667110fc50b33aee01adfa6907816a 100644 (file)
@@ -105,6 +105,7 @@ altoslib_JAVA = \
        AltosUsbId.java \
        AltosSensorMM.java \
        AltosSensorEMini.java \
+       AltosSensorEasyTimer1.java \
        AltosSensorTM.java \
        AltosSensorTMini2.java \
        AltosSensorTMini3.java \
index 66afd8a0d3521f89d01ddd1e9aa4ea8fbc1aab1c..20ca311e30d1ce7b9e4e67d6f8f38c27606b0ea3 100644 (file)
@@ -232,7 +232,9 @@ public class AltosConfigFC implements ActionListener {
 
                try {
                        /* bounds check stuff */
-                       if (config_ui.flight_log_max() > data.log_space() / 1024) {
+                       if (config_ui.flight_log_max() != AltosLib.MISSING &&
+                           config_ui.flight_log_max() > data.log_space() / 1024)
+                       {
                                JOptionPane.showMessageDialog(owner,
                                                              String.format("Requested flight log, %dk, is larger than the available space, %dk.\n",
                                                                            config_ui.flight_log_max(),
index 624c7246d91cdcca18e44266127c171872c2b34a..8df3c022a398c3067a7222768befb981ad5ff0d0 100644 (file)
@@ -46,6 +46,7 @@ public class AltosConfigFCUI
        JLabel                  aprs_interval_label;
        JLabel                  aprs_ssid_label;
        JLabel                  aprs_format_label;
+       JLabel                  aprs_offset_label;
        JLabel                  flight_log_max_label;
        JLabel                  ignite_mode_label;
        JLabel                  pad_orientation_label;
@@ -72,6 +73,7 @@ public class AltosConfigFCUI
        JComboBox<String>       aprs_interval_value;
        JComboBox<Integer>      aprs_ssid_value;
        JComboBox<String>       aprs_format_value;
+       JComboBox<Integer>      aprs_offset_value;
        JComboBox<String>       flight_log_max_value;
        JComboBox<String>       ignite_mode_value;
        JComboBox<String>       pad_orientation_value;
@@ -130,17 +132,28 @@ public class AltosConfigFCUI
                0, 1, 2 ,3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
        };
 
+       static Integer[]        aprs_offset_values = {
+               0, 2, 4, 6, 8, 10, 12, 14, 16, 18
+       };
+
        static String[]         beep_values = {
                "3750",
                "4000",
                "4250",
        };
 
-       static String[]         pad_orientation_values = {
+       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 = {
                "2",
                "5",
@@ -197,6 +210,25 @@ public class AltosConfigFCUI
                return product != null && product.startsWith("TeleMetrum");
        }
 
+       boolean is_telemega() {
+               String  product = product_value.getText();
+               return product != null && product.startsWith("TeleMega");
+       }
+
+       boolean is_easymega() {
+               String  product = product_value.getText();
+               return product != null && product.startsWith("EasyMega");
+       }
+
+       boolean is_easytimer() {
+               String  product = product_value.getText();
+               return product != null && product.startsWith("EasyTimer");
+       }
+
+       boolean has_radio() {
+               return is_telemega() || is_telemetrum() || is_telemini();
+       }
+
        void set_radio_enable_tool_tip() {
                if (radio_enable_value.isVisible())
                        radio_enable_value.setToolTipText("Enable/Disable telemetry and RDF transmissions");
@@ -236,6 +268,15 @@ public class AltosConfigFCUI
                        aprs_format_value.setToolTipText("Hardware doesn't support APRS");
        }
 
+       void set_aprs_offset_tool_tip() {
+               if (aprs_offset_value.isVisible())
+                       aprs_offset_value.setToolTipText("Set the APRS offset from top of minute");
+               else if (aprs_offset_value.isVisible())
+                       aprs_offset_value.setToolTipText("Software version doesn't support setting the APRS offset");
+               else
+                       aprs_offset_value.setToolTipText("Hardware doesn't support APRS");
+       }
+
        void set_flight_log_max_tool_tip() {
                if (flight_log_max_value.isVisible())
                        flight_log_max_value.setToolTipText("Size reserved for each flight log (in kB)");
@@ -262,6 +303,8 @@ public class AltosConfigFCUI
                                pad_orientation_value.setToolTipText("Older TeleMetrum firmware must fly antenna forward");
                        else if (is_telemini() || is_easymini())
                                pad_orientation_value.setToolTipText("TeleMini and EasyMini don't care how they are mounted");
+                       else if (is_easytimer())
+                               pad_orientation_value.setToolTipText("EasyTimer can be mounted in any of six orientations");
                        else
                                pad_orientation_value.setToolTipText("Can't select orientation");
                }
@@ -621,6 +664,33 @@ public class AltosConfigFCUI
                set_aprs_format_tool_tip();
                row++;
 
+               /* APRS offset */
+               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;
+               aprs_offset_label = new JLabel("APRS offset:");
+               pane.add(aprs_offset_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;
+               aprs_offset_value = new JComboBox<Integer>(aprs_offset_values);
+               aprs_offset_value.setEditable(false);
+               aprs_offset_value.addItemListener(this);
+               aprs_offset_value.setMaximumRowCount(aprs_offset_values.length);
+               pane.add(aprs_offset_value, c);
+               set_aprs_offset_tool_tip();
+               row++;
+
                /* Callsign */
                c = new GridBagConstraints();
                c.gridx = 0; c.gridy = row;
@@ -717,6 +787,11 @@ public class AltosConfigFCUI
                c.anchor = GridBagConstraints.LINE_START;
                c.insets = ir;
                c.ipady = 5;
+               if (has_radio())
+                       pad_orientation_values = pad_orientation_values_radio;
+               else
+                       pad_orientation_values = pad_orientation_values_no_radio;
+
                pad_orientation_value = new JComboBox<String>(pad_orientation_values);
                pad_orientation_value.setEditable(false);
                pad_orientation_value.addItemListener(this);
@@ -1229,16 +1304,18 @@ public class AltosConfigFCUI
                return AltosLib.MISSING;
        }
 
-       public void set_flight_log_max_limit(int new_flight_log_max_limit) {
+       public void set_flight_log_max_limit(int new_flight_log_max_limit, int new_storage_erase_unit) {
                flight_log_max_limit = new_flight_log_max_limit;
                if (new_flight_log_max_limit != AltosLib.MISSING) {
                        flight_log_max_value.removeAllItems();
                        for (int i = 8; i >= 1; i--) {
                                int     size = flight_log_max_limit / i;
+                               if (new_storage_erase_unit != 0)
+                                       size &= ~(new_storage_erase_unit - 1);
                                flight_log_max_value.addItem(String.format("%d (%d flights)", size, i));
                        }
                }
-               if (flight_log_max != 0)
+               if (flight_log_max != 0 && flight_log_max != AltosLib.MISSING)
                        set_flight_log_max(flight_log_max);
        }
 
@@ -1482,4 +1559,20 @@ public class AltosConfigFCUI
                        return aprs_format_value.getSelectedIndex();
                return AltosLib.MISSING;
        }
+
+       public void set_aprs_offset(int new_aprs_offset) {
+               if (new_aprs_offset != AltosLib.MISSING)
+                       aprs_offset_value.setSelectedItem(new_aprs_offset);
+               aprs_offset_value.setVisible(new_aprs_offset != AltosLib.MISSING);
+               aprs_offset_label.setVisible(new_aprs_offset != AltosLib.MISSING);
+               set_aprs_offset_tool_tip();
+       }
+
+       public int aprs_offset() throws AltosConfigDataException {
+               if (aprs_offset_value.isVisible()) {
+                       Integer i = (Integer) aprs_offset_value.getSelectedItem();
+                       return i;
+               }
+               return AltosLib.MISSING;
+       }
 }
index 004bd5344619f30702c9db30a6c6f731d228abc4..e9bb4e41c2802f1003f50ab0c6570c0ce64d2fe3 100644 (file)
@@ -214,9 +214,13 @@ public class AltosPad extends AltosUIFlightTab {
        class PadAlt extends AltosUIUnitsIndicator {
 
                public double value(AltosState state, int i) {
-                       if (report_pad(state))
-                               return state.pad_alt;
-                       else if (state.gps != null)
+                       if (report_pad(state)) {
+                               double alt = state.gps_ground_altitude();
+                               if (alt == AltosLib.MISSING)
+                                       alt = state.ground_altitude();
+                               return alt;
+                       }
+                       else if (state.gps != null && state.gps.alt != AltosLib.MISSING)
                                return state.gps.alt;
                        else
                                return state.altitude();
index 4bf3db120cf380bded3c04e6fd19a863e05b88b2..b172b0227603f235f3d11b9188ba82a4ce18e152 100644 (file)
@@ -146,11 +146,14 @@ 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_ETIMER_1=$(top_srcdir)/src/easytimer-v1/easytimer-v1-$(VERSION).ihx
+FIRMWARE_ETIMER=$(FIRMWARE_ETIMER_1)
+
 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=$(FIRMWARE_TGPS_1_0) $(FIRMWARE_TGPS_2_0)
 
-FIRMWARE=$(FIRMWARE_TM) $(FIRMWARE_TELEMINI) $(FIRMWARE_TD) $(FIRMWARE_TBT) $(FIRMWARE_TMEGA) $(FIRMWARE_EMINI) $(FIRMWARE_TGPS) $(FIRMWARE_EMEGA)
+FIRMWARE=$(FIRMWARE_TM) $(FIRMWARE_TELEMINI) $(FIRMWARE_TD) $(FIRMWARE_TBT) $(FIRMWARE_TMEGA) $(FIRMWARE_EMINI) $(FIRMWARE_TGPS) $(FIRMWARE_EMEGA) $(FIRMWARE_ETIMER)
 
 ALTUSMETRUM_DOC=$(top_srcdir)/doc/altusmetrum.pdf
 ALTOS_DOC=$(top_srcdir)/doc/altos.pdf
index 9fbc845c44014714d5f2b6a900e7b8a904b12a6a..fa803c5fc566a5851f262aff271a5a2dd785d74d 100644 (file)
@@ -136,6 +136,7 @@ Section "Firmware"
        File "../src/easymini-v2.0/easymini-v2.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/easytimer-v1/easytimer-v1-${VERSION}.ihx"
 
 SectionEnd
 
index ff1b15c85719c319a616ddd2fb763b5ab1ce96b3..214ae530fafc92bd3e1196676efad5c134494698 100644 (file)
@@ -45,11 +45,13 @@ public class AltosEepromDelete implements Runnable {
                        serial_line.printf("d %d\n", log.flight);
                        for (;;) {
                                /* It can take a while to erase the flash... */
-                               String line = serial_line.get_reply(20000);
+                               String line = serial_line.get_reply(200000);
                                if (line == null)
                                        throw new TimeoutException();
                                if (line.equals("Erased"))
                                        break;
+                               if (line.equals("Failed to erase"))
+                                       throw new IOException(line);
                                if (line.startsWith("No such"))
                                        throw new IOException(line);
                        }
index e61b397337c8b35828e7397746496fabe2764109..fd84f921c5d75a5fb0249133321ad0ffd98af247 100644 (file)
@@ -64,8 +64,7 @@ public class AltosFlashUI
                "telemetrum-v1",
                "telemini-v1",
                "telenano",
-               "teleshield",
-               "teleterra"
+               "teleshield"
        };
 
        private static final String[] pair_programmed_devices = {
@@ -78,8 +77,7 @@ public class AltosFlashUI
                "TeleMetrum-v1",
                "TeleMini-v1",
                "TeleNano",
-               "TeleShield",
-               "TeleTerra"
+               "TeleShield"
        };
 
        private boolean is_pair_programmed() {
index e20a516c573e278de42696b0cfdba7fb4e84a2c6..226f112f9542dff7c328b91514704bb4931a9bb8 100644 (file)
@@ -242,7 +242,7 @@ public class AltosInfoTable extends JTable implements AltosFlightDisplay, Hierar
                                        }
                                        info_add_deg(1, "Pad latitude", state.pad_lat, 'N', 'S');
                                        info_add_deg(1, "Pad longitude", state.pad_lon, 'E', 'W');
-                                       info_add_row(1, "Pad GPS alt", "%6.0f m", state.pad_alt);
+                                       info_add_row(1, "Pad GPS alt", "%6.0f m", state.gps_ground_altitude());
                                }
                                if (state.gps.year != AltosLib.MISSING)
                                        info_add_row(2, "GPS date", "%04d-%02d-%02d",
index 349cd3ce2f1a51b16833144817e162153061f8e9..50ec4c03bc843399d380df97b6645926d9c6fd83 100644 (file)
@@ -74,13 +74,13 @@ public class AltosUSBDevice  extends altos_device implements AltosDevice {
 
                if (want_product == AltosUILib.product_basestation)
                        return have_product == AltosUILib.product_teledongle ||
-                               have_product == AltosUILib.product_teleterra ||
                                have_product == AltosUILib.product_telebt ||
                                have_product == AltosUILib.product_megadongle;
 
                if (want_product == AltosUILib.product_altimeter)
                        return have_product == AltosUILib.product_telemetrum ||
                                have_product == AltosUILib.product_telemega ||
+                               have_product == AltosUILib.product_easytimer ||
                                have_product == AltosUILib.product_easymega ||
                                have_product == AltosUILib.product_telegps ||
                                have_product == AltosUILib.product_easymini ||
index dd30378a01a649eeead9db44e6d9e8c39571326a..e2d2f532a58ba2f4b62563647fa6af8d6e71a79c 100755 (executable)
@@ -76,6 +76,6 @@ done
 
 echo 'E 1' > $dev
 
-./test-telemetrum
+./test-telemetrum-v2.0
 
 exit $?
index 48165921d27dcb9fff311570981c4324f0f35cc1..aa11bea57b607b51e766efaa655916500e0a8e14 100644 (file)
@@ -26,7 +26,10 @@ ao-usbload \- flash a program to an ARM-based AltOS device
 [\-D \fIaltos-device\fP]
 [\--device \fIaltos-device\fP]
 [\--cal \fIradio-calibration\fP]
-[\--serial \fserial-number\fP]
+[\--serial \fIserial-number\fP]
+[\--raw]
+[\--verbose=\fIverbose\fP]
+[\--wait\\
 \fIfile.elf\fP or \fIfile.ihx\fP
 .SH DESCRIPTION
 .I ao-usbload
index a51b7dbe8a129b2635bf26085edcb5cd1ca19dd6..602390e3d324d7e0cb736d39f25b5b169d63b39d 100644 (file)
@@ -56,7 +56,7 @@ rewrite(struct ao_hex_image *load, unsigned address, uint8_t *data, int length)
        if (address < load->address || load->address + load->length < address + length)
                return false;
 
-       memcpy(load->data + address - load->address, data, length);
+       memcpy(&load->data[address - load->address], data, length);
        return true;
 }
 
index d23e720cc8de1e73479579556f4afa1e696c73f8..79fbb0d953ae8e5d461483ef82a1f6c9926f512a 100644 (file)
@@ -22,7 +22,7 @@
 #include <stdint.h>
 #include <stdarg.h>
 
-uint32_t       ao_verbose;
+extern uint32_t        ao_verbose;
 
 #define AO_VERBOSE_EXE 1
 #define AO_VERBOSE_SELF        2
index 74a96a40aae1266dee98d5f3f3965bdf8fffe05c..ca5262b53b84c48ace9f50c3f426a3f0050bb688 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.2)
+AC_INIT([altos], 1.9.3)
 ANDROID_VERSION=27
 AC_CONFIG_SRCDIR([src/kernel/ao.h])
 AM_INIT_AUTOMAKE([foreign dist-bzip2])
 AM_MAINTAINER_MODE
 
-RELEASE_DATE=2020-02-26
+RELEASE_DATE=2020-06-15
 AC_SUBST(RELEASE_DATE)
 
 DOC_DATE=`LC_ALL=C date -d $RELEASE_DATE +'%d %b %Y'`
@@ -262,18 +262,18 @@ if test "x$HAVE_ARM_CC" = "xyes"; then
        save_LIBS="$LIBS"
        CC="$ARM_CC"
        CFLAGS="-mthumb -mcpu=cortex-m0"
-       LIBS="-ffreestanding -nostdlib"
+       LIBS="--specs=picolibc.specs"
        AC_LANG_PUSH([C])
 
        AC_MSG_CHECKING([if ]$ARM_CC[ supports cortex-m0])
-       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int i;])],
+       AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
                          [HAVE_ARM_M0_CC=yes],
                          [HAVE_ARM_M0_CC=no])
         AC_MSG_RESULT([$HAVE_ARM_M0_CC])
 
        CFLAGS="-mthumb -mcpu=cortex-m3"
        AC_MSG_CHECKING([if ]$ARM_CC[ supports cortex-m3])
-       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int i;])],
+       AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
                          [HAVE_ARM_M3_CC=yes],
                          [HAVE_ARM_M3_CC=no])
         AC_MSG_RESULT([$HAVE_ARM_M3_CC])
@@ -294,39 +294,10 @@ if test "x$HAVE_ARM_M3_CC" = "xno"; then
 fi
 
 if test "x$HAVE_ARM_M0_CC" = "xno"; then
-       AC_MSG_WARN([No cortex-m0 arm compiler found, LPC11U14 binaries will not be built])
-fi
-
-AC_ARG_WITH([newlib-nano],
-           [AS_HELP_STRING([--with-newlib-nano],
-                           [Root of newlib nano install])],
-           [],
-           [with_newlib_nano=auto])
-
-HAVE_NEWLIB_NANO=no
-if test "x$with_newlib_nano" != "xno"; then
-       if test "x$with_newlib_nano" = "xauto"; then
-               for d in /usr/local/lib/newlib-nano /usr/lib/newlib-nano; do
-                       if test "x$with_newlib_nano" = "xauto" -a -d "$d"; then
-                               with_newlib_nano="$d"
-                               HAVE_NEWLIB_NANO=yes
-                       fi
-               done
-       else
-               HAVE_NEWLIB_NANO=yes
-       fi
+       AC_MSG_WARN([No cortex-m0 arm compiler found, LPC11U14 and STM32F0 binaries will not be built])
 fi
 
-if test "x$HAVE_NEWLIB_NANO" = "xno"; then
-       AC_MSG_WARN([No newlib-nano library found, ARM binaries will not be built])
-       HAVE_ARM_M3_CC=no
-       HAVE_ARM_M0_CC=no
-else
-       NEWLIB_NANO="$with_newlib_nano"
-fi
 
-AC_SUBST(HAVE_NEWLIB_NANO)
-AC_SUBST(NEWLIB_NANO)
 
 #
 # Configure AVR compiler
@@ -604,7 +575,6 @@ echo "    AVR support.................: ${HAVE_AVR_CC}"
 echo "    Android support.............: ${HAVE_ANDROID_SDK}"
 echo "    Android release support.....: ${ANDROID_RELEASE}"
 echo "    STlink support..............: ${HAVE_STLINK}"
-echo "    Newlib-nano support.........: ${NEWLIB_NANO}"
 echo "    i386 and amd64 libaltos.....: ${MULTI_ARCH}"
 echo "    install shared mime info....: ${INSTALL_SHARED_MIME_INFO}"
 echo "    Strip jar timestamps........: ${STRIP_NONDETERMINISM}"
index 464cd988bef3ca242e3f0034cbb68c96721a0cb2..acb223ca2b88e9d2e65514990fc53badd6965686 100644 (file)
@@ -17,6 +17,7 @@ FAKETIME=TZ=UTC faketime -f '$(RELEASE_DATE) 00:00:00 i0'
 endif
 
 RELNOTES_INC=\
+       release-notes-1.9.3.inc \
        release-notes-1.9.2.inc \
        release-notes-1.9.1.inc \
        release-notes-1.9.inc \
@@ -67,6 +68,7 @@ IMAGES=\
        easymega-v1.0-top.jpg \
        easymini.svg \
        easymini-top.jpg \
+       easytimer.jpg \
        fire-igniter.png \
        graph-configure.png \
        graph-map.png \
@@ -142,6 +144,7 @@ INC_FILES=\
        easymini-device.inc \
        telemega.inc \
        easymega.inc \
+       easytimer.inc \
        installation.inc \
        using-am-products.inc \
        updating-firmware.inc \
index d497ad2fc9ec42f064459d233e20d57805980899..a0aab0bd5edac392a25312fda90e1d5834f213be 100644 (file)
                        similar unit as a programming dongle (pair
                        programming).
                endif::telemetrum,telemini[]
-               ifdef::telemega,easymega,telemetrum[]
+               ifdef::telemega,easymega,easytimer,telemetrum[]
                        TeleMega, EasyMega, TeleMetrum v2 or newer,
-                       EasyMini, TeleBT v3 or newer and TeleDongle v3
+                       EasyMini, EasyTimer, TeleBT v3 or newer and TeleDongle v3
                        or newer are all
-               endif::telemega,easymega,telemetrum[]
-               ifndef::telemega,easymega,telemetrum[]
+               endif::telemega,easymega,easytimer,telemetrum[]
+               ifndef::telemega,easymega,easytimer,telemetrum[]
                        EasyMini is
-               endif::telemega,easymega,telemetrum[]
+               endif::telemega,easymega,easytimer,telemetrum[]
                programmed directly
                over USB (self programming). Please read
                the directions for flashing devices in
index 6016388871fa15edad57373825addaa82bb599ad..c2492b0f40e282e96d68f50274b8e8402100deb7 100644 (file)
@@ -20,6 +20,7 @@ Keith Packard <keithp@keithp.com>; Bdale Garbee <bdale@gag.com>; Bob Finch; Anth
 :telemega: 1
 :easymega: 1
 :telegps: 1
+:easytimer: 1
 :application: AltosUI
 :pdf-stylesdir: .
 :pdf-style: altusmetrum
@@ -45,6 +46,8 @@ Keith Packard <keithp@keithp.com>; Bdale Garbee <bdale@gag.com>; Bob Finch; Anth
 
        include::easymega.adoc[]
 
+       include::easytimer.adoc[]
+
        include::installation.adoc[]
 
        include::using-am-products.adoc[]
index 09f929d088588f13da9e7ae1c87ce3e487bb5ef9..d0e382665eadccda1ef517737d7eb4430aed11ce 100644 (file)
@@ -1,12 +1,19 @@
        === APRS
 
                {aprsdevices} can send APRS if desired, and the
-               interval between APRS packets can be configured. As each APRS
-               packet takes a full second to transmit, we recommend an
-               interval of at least 5 seconds to avoid consuming too much
-               battery power or radio channel bandwidth. You can configure
-               the APRS interval using {application}; that process is described in
-               <<{configure_section}>>.
+               interval between APRS packets can be configured. As
+               each APRS packet takes a full second to transmit, we
+               recommend an interval of at least 5 seconds to avoid
+               consuming too much battery power or radio channel
+               bandwidth. You can configure the time within each
+               minute that APRS transmits by changing the APRS offset
+               value. When the GPS signal is locked and knows the
+               current time, the APRS offset selects the time with
+               each minute for the first APRS transmission;
+               subsequent transmissions occur each APRS interval
+               seconds thereafter.  You can configure the APRS
+               interval and APRS offset using {application}; that
+               process is described in <<{configure_section}>>.
 
                AltOS supports both compressed and uncompressed APRS
                position report data formats. The compressed format
index 5e3bdbf0b561b79bbbd704afbde1c47ab50566d4..15f9129e4d0dd55cbc5a459909aae2030de38e4a 100644 (file)
@@ -118,6 +118,16 @@ ifdef::radio[]
                altitude with Compressed format. Test before
                you fly to see which to use.
 
+       ==== APRS Offset
+       
+               The delay from the top of the minute before sending
+               the first APRS packet of the minute. Coordinating
+               values for this parameter between multiple devices can
+               allow a single receiver to reliably receive APRS
+               packets from multiple devices. Note that this offset only
+               takes effect while the GPS signal is locked so that the
+               transmitting device knows the current time.
+               
        ==== Callsign
 
                This sets the call sign included in each
@@ -161,7 +171,7 @@ ifdef::altusmetrum[]
                is fired first, followed after a two second
                delay by the 'main' channel.
 
-       ifdef::telemetrum,telemega,easymega[]
+       ifdef::telemetrum,telemega,easymega,easytimer[]
        ==== Pad Orientation
 
                Because they include accelerometers,
@@ -173,15 +183,16 @@ ifdef::altusmetrum[]
                with the antenna pointing aft instead.
 
                Antenna Up::
-               In this mode, the antenna end of the flight
-               computer must point forward, in line with the
-               expected flight path.
+               In this mode, the antenna (or beeper, for devices
+               without an antenna) of the flight computer must point
+               forward, in line with the expected flight path.
 
                Antenna Down::
-               In this mode, the antenna end of the flight
-               computer must point aft, in line with the
-               expected flight path.
-       endif::telemetrum,telemega,easymega[]
+
+               In this mode, the antenna (or beeper, for devices
+               without an antenna) end of the flight computer must
+               point aft, in line with the expected flight path.
+               endif::telemetrum,telemega,easymega,easytimer[]
 
        ==== Beeper Frequency
 
@@ -212,7 +223,7 @@ ifdef::telegps[]
                in the log.
 endif::telegps[]
 
-ifdef::telemega,easymega,telemetrum[]
+ifdef::telemega,easymega,easytimer,telemetrum[]
 
        ==== Calibrate Accelerometer
 
@@ -226,9 +237,9 @@ ifdef::telemega,easymega,telemetrum[]
                Configure Altimeter window and save the new
                calibration values.
 
-endif::telemega,easymega,telemetrum[]
+endif::telemega,easymega,easytimer,telemetrum[]
 
-ifdef::telemega,easymega[]
+ifdef::telemega,easymega,easytimer[]
 
        ==== Configure Pyro Channels
 
@@ -236,8 +247,8 @@ ifdef::telemega,easymega[]
                image::configure-pyro.png[width=400]
 
                This opens a separate window to configure the
-               additional pyro channels available on TeleMega
-               and EasyMega.  One column is presented for
+               additional pyro channels available on TeleMega,
+               EasyMega and EasyTimer.  One column is presented for
                each channel. Each row represents a single
                parameter, if enabled the parameter must meet
                the specified test for the pyro channel to be
@@ -264,4 +275,4 @@ ifdef::telemega,easymega[]
 
                include::pyro-channels.adoc[]
 
-endif::telemega,easymega[]
+endif::telemega,easymega,easytimer[]
index 09a83d16fa725574bc53dd9824939a5976ceb249..73c3dc33fc06ef6493220b6b7628b83c8de89c4a 100644 (file)
Binary files a/doc/configure-altimeter.png and b/doc/configure-altimeter.png differ
index 506f4c5f2fea3dc0c9d9fa2d3c1b23c02ab18cc8..e7351c07d5aa045e2ec4c6ae3438b25d7322b1f8 100644 (file)
@@ -1,7 +1,7 @@
 == EasyMega
 
        .EasyMega Board
-       image::easymega-v1.0-top.jpg[width=430]
+       image::easymega-v1.0-top.jpg[width=400]
 
        EasyMega is a 1¼ inch by 2¼ inch circuit board. It was
        designed to easily fit in a 38mm coupler. Like TeleMetrum,
                |Main pyro channel connection to pyro circuit
 
                |Top 5
-               |Main +
-               |Main pyro channel common connection to battery +
+               |Main +++
+               |Main pyro channel common connection to battery +++
 
                |Top 6
                |Apogee -
                |Apogee pyro channel connection to pyro circuit
 
                |Top 7
-               |Apogee +
-               |Apogee pyro channel common connection to battery +
+               |Apogee +++
+               |Apogee pyro channel common connection to battery +++
 
                |Top 8
                |D -
                |D pyro channel connection to pyro circuit
 
                |Top 9
-               |D +
-               |D pyro channel common connection to battery +
+               |D +++
+               |D pyro channel common connection to battery +++
 
                |Bottom 1
                |GND
                |A pyro channel connection to pyro circuit
 
                |Bottom 5
-               |A +
-               |A pyro channel common connection to battery +
+               |A +++
+               |A pyro channel common connection to battery +++
 
                |Bottom 6
                |B -
                |B pyro channel connection to pyro circuit
 
                |Bottom 7
-               |B +
-               |B pyro channel common connection to battery +
+               |B +++
+               |B pyro channel common connection to battery +++
 
                |Bottom 8
                |C -
                |C pyro channel connection to pyro circuit
 
                |Bottom 9
-               |C +
-               |C pyro channel common connection to battery +
+               |C +++
+               |C pyro channel common connection to battery +++
                |====
 
        === Using a Separate Pyro Battery with EasyMega
index d82a26075b17ac0d7320f9cd18bf6847124b2969..841f7a3ee6a7966a58ddba1ee8bb63104478f68b 100644 (file)
                |Main pyro channel connection to pyro circuit
              
                |Top 2
-               |Main +
-               |Main pyro channel common connection to battery +
+               |Main +++
+               |Main pyro channel common connection to battery +++
              
                |Top 3
-               |Battery +
+               |Battery +++
                |Positive external battery terminal
              
                |Top 4
@@ -47,8 +47,8 @@
                |Apogee pyro channel connection to pyro circuit
              
                |Bottom 2
-               |Apogee +
-               |Apogee pyro channel common connection to battery +
+               |Apogee +++
+               |Apogee pyro channel common connection to battery +++
              
                |Bottom 3
                |Switch Output
index 6fc6f035ef727d698eb51d8fcc388b16364c2fa3..53af859713d62b25b75c223c8a8a4fc72180e6dc 100644 (file)
@@ -1,5 +1,9 @@
 [appendix]
 == Release Notes
+       :leveloffset: 2
+       include::release-notes-1.9.3.adoc[]
+
+       <<<<
        :leveloffset: 2
        include::release-notes-1.9.1.adoc[]
 
diff --git a/doc/easytimer.inc b/doc/easytimer.inc
new file mode 100644 (file)
index 0000000..82689d2
--- /dev/null
@@ -0,0 +1,120 @@
+== EasyTimer
+
+       .EasyTimer Board
+       image::easytimer.jpg[width=400]
+
+       EasyTimer is built on a 0.8 inch by 1½ inch circuit board. It's
+       designed to fit in a 24mm coupler tube.
+
+       EasyTimer is designed to control events during ascent. It has
+       an accelerometer and gyroscope that can measure acceleration
+       and rotation and compute speed and tilt angle. EasyTimer has
+       two pyro channels which can be configured to fire at various
+       points during flight. Because EasyTimer has no barometric
+       sensor, it cannot be used to fire recovery charges at apogee
+       or during descent. EasyTimer is configured using the AltosUI
+       application which is available for Linux, Mac OS X and Windows.
+
+       === EasyTimer Screw Terminals
+       
+               EasyTimer has two sets of four screw terminals near
+               one end of the board. Using the picture above, the top
+               four have connections for pyro channel B and an
+               external battery and the bottom four have connections
+               for pyro circuit A and the power switch. Counting from
+               the left, the connections are as follows:
+
+               .EasyTimer Screw Terminals
+               [options="header",grid="all",cols="2,3,10"]
+               |====
+               |Terminal #|Terminal Name|Description
+               |Top 1
+               |B -
+               |Pyro channel B connection to pyro circuit
+             
+               |Top 2
+               |B +++
+               |Pyro channel B common connection to battery +++
+             
+               |Top 3
+               |Battery +++
+               |Positive external battery terminal
+             
+               |Top 4
+               |Battery -
+               |Negative external battery terminal
+             
+               |Bottom 1
+               |A -
+               |Pyro channel A connection to pyro circuit
+             
+               |Bottom 2
+               |A +++
+               |Pyro channel A common connection to battery +++
+             
+               |Bottom 3
+               |Switch Output
+               |Switch connection to flight computer
+             
+               |Bottom 4
+               |Switch Input
+               |Switch connection to positive battery terminal
+               |====
+
+       === Connecting A Battery To EasyTimer
+
+               There are two possible battery connections on
+               EasyTimer. You can use either method; both feed
+               through the power switch terminals.
+
+               One battery connection is the standard Altus Metrum
+               white JST plug. This mates with single-cell Lithium
+               Polymer batteries sold by Altus Metrum.
+
+               The other is a pair of screw terminals marked 'Battery
+               +' and 'Battery -'. Connect a battery from 4 to 12
+               volts to these terminals, being careful to match polarity.
+
+       === Charging Lithium Batteries
+
+               Because EasyTimer allows for batteries other than the
+               standard Altus Metrum Lithium Polymer cells, it cannot
+               incorporate a battery charger circuit. Therefore, when
+               using a Litium Polymer cell, you'll need an external
+               charger. These are available from Altus Metrum, or
+               from Spark Fun.
+
+       === Using a Separate Pyro Battery with EasyTimer
+       
+               As described above, using an external pyro battery involves
+               connecting the negative battery terminal to the flight
+               computer ground, connecting the positive battery terminal to
+               one of the igniter leads and connecting the other igniter
+               lead to the per-channel pyro circuit connection.
+
+               To connect the negative pyro battery terminal to EasyTimer
+               ground, connect it to the negative external battery
+               connection, top terminal 4.
+
+               Connecting the switched positive battery terminal to the pyro
+               charges must be done separate from EasyTimer, by soldering
+               them together or using some other connector.  Note that for
+               safety, you must put a switch between the pyro battery and
+               the rest of the circuit!
+
+               The other lead from each pyro charge is then inserted into
+               the appropriate per-pyro channel screw terminal (top
+               terminal 1 for pyro channel A charge, bottom terminal 1 for
+               pyro channel B charge).
+
+       === Using an Active Switch with EasyTimer
+       
+               As explained above, an external active switch requires three
+               connections, one to the positive battery terminal, one to
+               the flight computer positive input and one to ground. Use
+               the negative external battery connection, top terminal 4 for
+               ground.
+
+               The positive battery terminal is available on bottom
+               terminal 4, the positive flight computer input is on the
+               bottom terminal 3.
diff --git a/doc/easytimer.jpg b/doc/easytimer.jpg
new file mode 100644 (file)
index 0000000..703e9a1
Binary files /dev/null and b/doc/easytimer.jpg differ
index 5e60986ad1e6baecc1e8005348790f39711be4ff..bf6cbda84ccc86be8399cc6a10d3bc82e5772bbb 100644 (file)
@@ -14,6 +14,7 @@
                charging circuitry.
                endif::telemetrum,telemega,easymega[]
                The Lithium Polymer
+               ifdef::easytimer[EasyTimer, ]
                ifdef::telemini[TeleMini and]
                EasyMini battery can be charged by disconnecting it
                from the board and plugging it into a standalone
@@ -22,6 +23,7 @@
                USB power source.
 
                You can also choose to use another battery with
+               ifdef::easytimer[EasyTimer and]
                EasyMini, anything supplying between 4 and 12 volts should
                work fine (like a standard 9V battery), but if you are planning
                to fire pyro charges, ground testing is required to verify that
index ab5baef0e37cc68d7bca8c24e59a22c28d9bd0a1..1daf2f6e9b9b7bb8257b8da97b311c96c46ac3d7 100644 (file)
@@ -13,12 +13,14 @@ rate during descent is a bit noisy and so be careful when using it
 during these phases of the flight.
 
 Height above pad:: Select a value, and then choose whether the height
-above the launch pad should be above or below that value.
-
-Orientation:: TeleMega and EasyMega contain a 3-axis gyroscope and
-accelerometer which is used to compute the orientation of the
-rocket. A record of orientations over the last 0.64 seconds is kept
-and the largest value within this period is compared with the
+above the launch pad should be above or below that value. Note that
+because EasyTimer has only a low-range accelerometer and no barometer,
+this value will not be very reliable on that device.
+
+Orientation:: TeleMega, EasyMega and EasyTimer contain a 3-axis
+gyroscope and accelerometer which is used to compute the orientation
+of the rocket. A record of orientations over the last 0.64 seconds is
+kept and the largest value within this period is compared with the
 specified value. Note that the tilt angle is not the change in angle
 from the launch pad, but rather absolute relative to gravity—the
 3-axis accelerometer is used to compute the angle of the rocket on the
@@ -89,14 +91,14 @@ through a sequence of states:
    than 200m/s. Ascent rate will greater than zero. Vertical
    acceleration will be less than zero.
 
- * Drogue. The rocket has reached apogee and
-   is heading back down, but is above the
-   configured Main altitude. Ascent rate will be less than zero during
-   this state. Vertical acceleration will be negative until the rocket
-   reaches a terminal descent rate, at which point Vertical
-   acceleration will be zero. Both Ascent rate and Vertical
+ * Drogue. The rocket has reached apogee and is heading back down, but
+   is above the configured Main altitude. Ascent rate will be less
+   than zero during this state. Vertical acceleration will be negative
+   until the rocket reaches a terminal descent rate, at which point
+   Vertical acceleration will be zero. Both Ascent rate and Vertical
    acceleration are very noisy in this state, so be careful when
-   trying to use them to control pyro channels.
+   trying to use them to control pyro channels. This state selection
+   is not available on EasyTimer.
 
  * Main. The rocket is still descending, and
    is below the Main altitude. Ascent rate will be less than zero
@@ -105,7 +107,7 @@ through a sequence of states:
    it will settle down to a zero value once the rocket has reached the
    terminal velocity under the main chute. Ascent rate and Vertical
    acceleration should be much less noisy once the main chute has
-   deployed.
+   deployed. This state selection is not available on EasyTimer.
 
  * Landed. The rocket is no longer moving.
 
diff --git a/doc/release-notes-1.9.3.inc b/doc/release-notes-1.9.3.inc
new file mode 100644 (file)
index 0000000..3ae9102
--- /dev/null
@@ -0,0 +1,27 @@
+= Release Notes for Version 1.9.3
+include::release-head.adoc[]
+:doctype: article
+
+       Version 1.9.3
+
+       == AltOS
+
+       * Add APRS offset. Allows multiple APRS transmitters to coordinate when
+         transmission occurs to allow them to share a frequency.
+
+       * Fix max log size. Flight computer storage is erased in 64kB chunks. Adjust max
+         log size to be a multiple of this size.
+
+       * Check flight erasing more carefully. Handle interrupting erasing in the
+         middle.
+
+       * Add EasyTimer support.
+
+       == AltosUI, TeleGPS, MicroPeak
+
+       * Add configuration support for APRS offset.
+
+       * Adjust flight log sizes to be a multiple of the flight
+          computer erase block size.
+
+       * Report barometric pad altitude in Pad tab for TeleMini.
index dc3df120ed9c361995771ca841721e5ea573ca9c..042059bc6f163a8784b1a259e654ba0fd6eb6e05 100644 (file)
@@ -1,5 +1,9 @@
 [appendix]
 == Release Notes
+       :leveloffset: 2
+       include::release-notes-1.9.3.adoc[]
+
+       <<<<
        :leveloffset: 2
        include::release-notes-1.9.2.adoc[]
 
index b69d52ee63a78ce2a8efa44632bdfae9d7eb94a0..5c2c83cc626e5eccaf68b77b8883d931cdc52693 100644 (file)
        |3.7V
        endif::easymega[]
 
+       ifdef::easytimer[]
+       |EasyTimer v1.0
+       |-
+       |16g
+       |-
+       |BMX160
+       |-
+       |-
+       |3.7-12V
+       endif::easytimer[]
+       
+       
        |===
 
        <<<<
        |38mm coupler
        endif::easymega[]
 
+       ifdef::easytimer[]
+       |EasyMini
+       |Debug USB Battery
+       |Pyro A Pyro B Battery
+       |0.8 inch (2.03cm)
+       |1½ inch (3.81cm)
+       |24mm coupler
+       endif::easytimer[]
+
        |===
index 6cc9986b150556a283289369c22a5466bf4f3aa2..888e3891c6479941bba2276c6719e1cba5d6016a 100644 (file)
@@ -7,9 +7,9 @@
                fundamental modes, “idle” and “flight”.  Which of these modes
                the firmware operates in is determined at start up
                time.
-               ifdef::telemetrum,telemega,easymega[]
+               ifdef::telemetrum,telemega,easymega,easytimer[]
                For
-               TeleMetrum, TeleMega and EasyMega, which have accelerometers, the mode is
+               TeleMetrum, TeleMega, EasyMega and EasyTimer, which have accelerometers, the mode is
                controlled by the orientation of the
                rocket (well, actually the board, of course...) at the time
                power is switched on.  If the rocket is “nose up”, then
@@ -17,7 +17,7 @@
                launch, so the firmware chooses flight mode.  However, if the
                rocket is more or less horizontal, the firmware instead enters
                idle mode.
-               endif::telemetrum,telemega,easymega[]
+               endif::telemetrum,telemega,easymega,easytimer[]
                Since
                EasyMini doesn't
                have an
index 56cb20311b00e63250d5085aa2d12f1381913766..4bc052f3589e4fdf474a0d09560e963aba8e6592 100644 (file)
Binary files a/doc/telegps-configure.png and b/doc/telegps-configure.png differ
index af6317024455f2853f66fe8c3803a2e77c4088a8..c0a258f154b2b126770dff2ee6ec12f0e39d07f5 100644 (file)
@@ -1,6 +1,11 @@
 [appendix]
 == Release Notes
 
+       :leveloffset: 2
+       include::release-notes-1.9.3.adoc[]
+
+       <<<<
+
        :leveloffset: 2
        include::release-notes-1.9.1.adoc[]
 
index 092077e00da73e04923c77167f9e783d965e8283..ef701e46ce5b02406df9c596749e808c254e654f 100644 (file)
                |Main pyro channel connection to pyro circuit
 
                |Top 5
-               |Main +
-               |Main pyro channel common connection to battery +
+               |Main +++
+               |Main pyro channel common connection to battery +++
 
                |Top 6
                |Apogee -
                |Apogee pyro channel connection to pyro circuit
 
                |Top 7
-               |Apogee +
-               |Apogee pyro channel common connection to battery +
+               |Apogee +++
+               |Apogee pyro channel common connection to battery +++
 
                |Top 8
                |D -
                |D pyro channel connection to pyro circuit
 
                |Top 9
-               |D +
-               |D pyro channel common connection to battery +
+               |D +++
+               |D pyro channel common connection to battery +++
 
                |Bottom 1
                |GND
                |A pyro channel connection to pyro circuit
 
                |Bottom 5
-               |A +
-               |A pyro channel common connection to battery +
+               |A +++
+               |A pyro channel common connection to battery +++
 
                |Bottom 6
                |B -
                |B pyro channel connection to pyro circuit
 
                |Bottom 7
-               |B +
-               |B pyro channel common connection to battery +
+               |B +++
+               |B pyro channel common connection to battery +++
 
                |Bottom 8
                |C -
                |C pyro channel connection to pyro circuit
 
                |Bottom 9
-               |C +
-               |C pyro channel common connection to battery +
+               |C +++
+               |C pyro channel common connection to battery +++
                |====
 
        === Using a Separate Pyro Battery with TeleMega
index 7ef9876f6439eeff0dc91b5d011df7a2d1a9fa31..fdb961d7c061923ba84979cccce60d8694d25495 100644 (file)
@@ -43,9 +43,9 @@
                |Terminal #|Terminal Name|Description
                |1      |Switch Output  |Switch connection to flight computer
                |2      |Switch Input   |Switch connection to positive battery terminal
-               |3      |Main +         |Main pyro channel common connection to battery +
+               |3      |Main +++       |Main pyro channel common connection to battery +++
                |4      |Main -         |Main pyro channel connection to pyro circuit
-               |5      |Apogee +       |Apogee pyro channel common connection to battery +
+               |5      |Apogee +++     |Apogee pyro channel common connection to battery +++
                |6      |Apogee -       |Apogee pyro channel connection to pyro circuit
                |===
 
index 03732b2af2ac4ee03d7dfed70845d42aeabc6b47..7dd04bf099d887abc6349d0f217a12c0ab09321a 100644 (file)
                |Apogee pyro channel connection to pyro circuit
 
                |2
-               |Apogee +
-               |Apogee pyro channel common connection to battery +
+               |Apogee +++
+               |Apogee pyro channel common connection to battery +++
 
                |3
                |Main -
                |Main pyro channel connection to pyro circuit
 
                |4
-               |Main +
-               |Main pyro channel common connection to battery +
+               |Main +++
+               |Main pyro channel common connection to battery +++
 
                |Left
                |Switch Output
index b1047ffa645db07bb20ce7536905f82d6207b6b4..1999a9c77e6a2557458fc97aa07a5888d18d664b 100644 (file)
                        the board.
                        endif::easymega[]
 
+                       ifdef::easytimer[]
+                       EasyTimer::
+
+                       Connect pin 5 and pin 1 of the debug connector, which
+                       is the six holes next to the beeper. Pin 1 can be
+                       identified by the square pad around it, and then the
+                       pins could sequentially across the board, making Pin 5
+                       the one on the other end of the row.
+                       endif::easytimer[]
+
                        ifdef::telemetrum[]
                        TeleMetrum v2 and newer::
 
index 68d08bad8690a821f8b5649f70d788e187383156..4e40240b4df70c1de78b7b38b9bed2011bf0d87e 100644 (file)
                 signals, but no record of the flight will be
                 stored in on-board flash.
 
-               ifdef::easymega,telemega[]
+               ifdef::easymega,telemega,easytimer[]
                |Additional Igniters
                |four very short beeps
-               |Continuity indication for the four additional pyro
-                channels on TeleMega and EasyMega. One high tone for
-                no continuity, one low tone for continuity. These are
+               |Continuity indication for the additional pyro
+                channels on TeleMega, EasyMega and EasyTimer. One high tone for
+                no continuity, one low tone for continuity. On TeleMega and EasyMegay, these are
                 produced after the continuity indicators for the two
                 primary igniter channels.
-               endif::easymega,telemega[]
+               endif::easymega,telemega,easytimer[]
 
                |====
 
                the current state. See below for how to get the flight
                computer to come up in Idle mode at power on.
 
-               ifdef::telemetrum,easymega,telemega[]
+               ifdef::telemetrum,easymega,telemega,easytimer[]
                For flight computers with accelerometers (TeleMetrum,
-               EasyMega and TeleMega), the mode is selected by the
+               EasyMega, TeleMega and EasyTimer), the mode is selected by the
                orientation of the board during the self test
                interval. If the board is pointing upwards as if ready
                to fly, it will enter Flight/Pad mode. Otherwise, it will
                enter Idle mode.
-               endif::telemetrum,easymega,telemega[]
+               endif::telemetrum,easymega,telemega,easytimer[]
 
                ifdef::easymini[]
                For EasyMini, if the USB cable is connected to a
        === Using a Different Kind of Battery
 
                EasyMini
-               ifdef::telemini[and TeleMini v2 are]
-               ifndef::telemini[is]
+               ifdef::easytimer[and EasyTimer are]
+               ifndef::easytimer[is]
                designed to use either a
                lithium polymer battery or any other battery producing
                between 4 and 12 volts, such as a rectangular 9V
                battery.
 
-               ifdef::telemega,easymega,telemetrum[]
+               ifdef::telemega,easymega,telemetrum,telemini[]
                [WARNING]
+               ifdef::telemini[TeleMini, ]
                TeleMega, EasyMega and TeleMetrum are only designed to
                operate off a single-cell Lithium Polymer battery and
                cannot be used with any other kind. Connecting a
                different kind of battery to any of these will destroy
                the board.
-               endif::telemega,easymega,telemetrum[]
+               endif::telemega,easymega,telemetrum,telemini[]
 
        === Using Packet Link Mode
 
index 1c1ff10eccbbd08a7f76a3026af01c12343d5830..6048ee0ef5dca61a5bde88036a59ba78536263cf 100644 (file)
                In the rocket itself, you just need a flight computer
                and a single-cell, 3.7 volt nominal Li-Po rechargeable
                battery.
-               ifdef::telemetrum,telemega,easymega[]
+               ifdef::telemetrum,telemega,easymega,easytimer[]
                An 850mAh battery weighs less than a 9V
-               alkaline battery, and will run a TeleMetrum, TeleMega
-               or EasyMega for hours.
-               endif::telemetrum,telemega,easymega[]
+               alkaline battery, and will run a TeleMetrum, TeleMega,
+               EasyMega or EasyTimer for hours.
+               endif::telemetrum,telemega,easymega,easytimer[]
                A 110mAh battery weighs less
                than a triple A battery and is a good choice for use
                with
index 5f5ce0ae4599a66c055d6879558734403b04bca9..723964ba083af0ec5d99d07e39635c5be82ef750 100644 (file)
@@ -4,3 +4,4 @@ altos-mapd
 altos-mapd-jdb
 altos-mapd-test
 classes
+Manifest.txt
index bb20dd845886ec795c4234006890f2351748b41a..f92c3e5ac917538778e00d6fbf6d8953453e4f3e 100644 (file)
@@ -60,6 +60,10 @@ altos-mapd: Makefile
        echo 'exec java -Djava.library.path="$(altoslibdir)" -jar "$(altosmapddir)/altosmapd.jar" "$$@"' >> $@
        chmod +x $@
 
+Manifest.txt: Makefile
+       echo 'Main-Class: altosmapd.AltosMapd' > $@
+       echo "Class-Path: $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS)" >> $@
+
 altos-mapd-test: Makefile
        echo '#!/bin/sh' > $@
        echo 'dir="$$(dirname $$0)"' >> $@
@@ -77,3 +81,6 @@ $(ALTOSLIB_CLASS):
        -rm -f "$@"
        $(LN_S) ../../altoslib/"$@" .
 
+
+clean::
+       rm -f Manifest.txt
diff --git a/map-server/altos-mapd/Manifest.txt b/map-server/altos-mapd/Manifest.txt
deleted file mode 100644 (file)
index 42c0313..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-Main-Class: altosmapd.AltosMapd
-Class-Path: altoslib_13.jar
index c5d593e6b7fdc32d4232a3424115d43dfaf85dc8..b223755f0bce7598a9453f020873ba52b80eaaa4 100644 (file)
@@ -4,3 +4,5 @@ altos-mapj-test
 *.jar
 *.stamp
 classes
+Manifest.txt
+Manifest-fat.txt
index a8dfffecc55a37a924ec469fe2ebe21e7a1893ae..0c823d035c8073078141b96b44a4617f14a3f861 100644 (file)
@@ -19,6 +19,8 @@ FATJAR=altosmap-fat.jar
 
 all-local: classes/altosmap $(JAR) altos-mapj altos-mapj-test altos-mapj-jdb
 
+fat: $(FATJAR)
+
 install-altosmapJAVA: altosmap.jar
        @$(NORMAL_INSTALL)
        test -z "$(altosmapdir)" || $(MKDIR_P) "$(DESTDIR)$(altosmapdir)"
@@ -49,6 +51,14 @@ altos-mapj: Makefile
        echo 'exec java -Djava.library.path="$(altoslibdir)" -jar "$(altosmapdir)/altosmap.jar" "$$@"' >> $@
        chmod +x $@
 
+Manifest.txt: Makefile
+       echo 'Main-Class: altosmap.AltosMap' > $@
+       echo "Class-Path: $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS)" >> $@
+
+Manifest-fat.txt: Makefile
+       echo 'Main-Class: altosmap.AltosMap' > $@
+       echo "Class-Path: $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS)" >> $@
+
 altos-mapj-test: Makefile
        echo '#!/bin/sh' > $@
        echo 'dir="$$(dirname $$0)"' >> $@
@@ -66,3 +76,5 @@ $(ALTOSLIB_CLASS):
        -rm -f "$@"
        $(LN_S) ../../altoslib/"$@" .
 
+clean::
+       rm -f Manifest.txt Manifest-fat.txt
diff --git a/map-server/altos-mapj/Manifest.txt b/map-server/altos-mapj/Manifest.txt
deleted file mode 100644 (file)
index 1a285b4..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-Main-Class: altosmap.AltosMap
-Class-Path: altoslib_13.jar
index aad18d4cfe10ca70efafbb7d43edc1baea9df8d4..d1308eaeacfd728cdbafec6668c5e4fcf0592ec7 100644 (file)
@@ -3,3 +3,4 @@ altitude.h
 altitude-pa.h
 altitude-pa-small.h
 ao_whiten.h
+*.map
index b5639f7329aef479774b4f7dea4e2051e6c66c55..9543e32961c0d30d0d3703a9b58ef90221ee173c 100644 (file)
@@ -1,8 +1,6 @@
 ARM_CC=@ARM_CC@
 HAVE_ARM_M3_CC=@HAVE_ARM_M3_CC@
 HAVE_ARM_M0_CC=@HAVE_ARM_M0_CC@
-NEWLIB_NANO=@NEWLIB_NANO@
-HAVE_NEWLIB_NANO=@HAVE_NEWLIB_NANO@
 
 AVR_CC=@AVR_CC@
 AVR_OBJCOPY=@AVR_OBJCOPY@
index 3f5c19735ed1ad88fb17fcc2d2be2aff39a55fd5..7d683d8c6d9c5879bb4050ad07d6f9c6d5ecf633 100644 (file)
@@ -19,6 +19,7 @@ include Makedefs
 ARMM3DIRS=\
        easymega-v1.0 easymega-v1.0/flash-loader \
        easymega-v2.0 easymega-v2.0/flash-loader \
+       easytimer-v1 easytimer-v1/flash-loader \
        telemega-v0.1 telemega-v0.1/flash-loader \
        telemega-v1.0 telemega-v1.0/flash-loader \
        telemega-v2.0 telemega-v2.0/flash-loader \
index d52cc7061616fd31d9ccec38339bd5e1e67db91a..897f7ac1b35ade9d2574b45c6e1f1208f6923a6a 100644 (file)
@@ -18,14 +18,11 @@ WARN_FLAGS=-Wall -Wextra -Werror -Wcast-align \
        -Wshadow \
        -Warray-bounds=2
 
-OPT=-Os
+OPT=-Os -Wl,-Map=$(PROGNAME)-$(VERSION).map
 
-NEWLIB_PRINTF_CFLAGS =         -DNEWLIB_INTEGER_PRINTF_SCANF
-
-NEWLIB_CFLAGS= \
-       -ffreestanding -nostdlib \
-       -isystem $(NEWLIB_NANO)/arm-none-eabi/include \
-       $(NEWLIB_PRINTF_CFLAGS)
+PICOLIBC_CFLAGS= \
+       -specs=picolibc.specs \
+       $(PICOLIBC_PRINTF_CFLAGS)
 
 AO_CFLAGS=\
        -std=gnu99 \
index 4f6b816948709632e5462e1d8d0460a0f3911b49..dca2213b1ba94cb3b111a19ed81301c6e1cf8450 100644 (file)
@@ -235,13 +235,13 @@ static struct ao_task ao_adxl375_task;
 static void
 ao_adxl375_dump(void)
 {
-       printf ("ADXL375 value %d %d %d self test %d min %d max %d\n",
+       printf ("ADXL375 value %d %d %d self test %ld min %ld max %ld\n",
                ao_adxl375_current.x,
                ao_adxl375_current.y,
                ao_adxl375_current.z,
-               self_test_value,
-               MIN_SELF_TEST,
-               MAX_SELF_TEST);
+               (long) self_test_value,
+               (long) MIN_SELF_TEST,
+               (long) MAX_SELF_TEST);
 }
 
 const struct ao_cmds ao_adxl375_cmds[] = {
index bc5c29dfc85634d9f5a4905ead05b55308583293..826985c6e06e2f0b004a05c36a2b6976cd6a49ba 100644 (file)
@@ -234,7 +234,7 @@ static void timeInit()
 #define TNC_TX_DELAY 45
 
 /// The size of the TNC output buffer.
-#define TNC_BUFFER_SIZE 40
+#define TNC_BUFFER_SIZE 48
 
 /// States that define the current mode of the 1200 bps (A-FSK) state machine.
 typedef enum
index 9fc3334177b1208ad82f9e256f801fdf87177b32..c5bf0aff634fcd2ccf9453ba0757448517b81f21 100644 (file)
@@ -306,4 +306,6 @@ ao_bmx160_accel(int16_t sensor) {
        return (float) sensor * ((float) (BMX160_ACCEL_FULLSCALE * GRAVITY / 32767.0));
 }
 
+#define ao_bmx_accel_to_sample(accel) ((accel_t) (accel) * (32767.0f / (BMX160_ACCEL_FULLSCALE * GRAVITY)))
+
 #endif /* _BMX160_H_ */
index a6d930835baed49a70d619073b84349242b0a806..89b1c4d2c2da20374b30e4bdc3a34f58db0c6af3 100644 (file)
@@ -615,6 +615,8 @@ ao_gps(void)
        uint8_t                 class, id;
        struct ao_ublox_cksum   cksum;
        uint8_t                 i;
+       AO_TICK_TYPE            packet_start_tick;
+       AO_TICK_TYPE            solution_tick = 0;
 
        ao_gps_setup();
 
@@ -645,6 +647,8 @@ ao_gps(void)
                /* Locate the begining of the next record */
                while (ao_ublox_byte() != (uint8_t) 0xb5)
                        ;
+               packet_start_tick = ao_tick_count;
+
                if (ao_ublox_byte() != (uint8_t) 0x62)
                        continue;
 
@@ -657,7 +661,7 @@ ao_gps(void)
                ao_ublox_len = header_byte();
                ao_ublox_len |= header_byte() << 8;
 
-               ao_gps_dbg(DBG_PROTO, "class %02x id %02x len %d\n", class, id, ao_ublox_len);
+               ao_gps_dbg(DBG_PROTO, "%6u class %02x id %02x len %d\n", packet_start_tick, class, id, ao_ublox_len);
 
                if (ao_ublox_len > 1023)
                        continue;
@@ -679,6 +683,7 @@ ao_gps(void)
                                if (ao_ublox_len != 52)
                                        break;
                                ao_ublox_parse_nav_sol();
+                               solution_tick = packet_start_tick;
                                break;
                        case UBLOX_NAV_SVINFO:
                                if (ao_ublox_len < 8)
@@ -715,7 +720,7 @@ ao_gps(void)
                        switch (id) {
                        case UBLOX_NAV_TIMEUTC:
                                ao_mutex_get(&ao_gps_mutex);
-                               ao_gps_tick = ao_time();
+                               ao_gps_tick = solution_tick;
 
                                ao_gps_data.flags = 0;
                                ao_gps_data.flags |= AO_GPS_RUNNING;
index 0d7e4cba2debfca344168ccad24065cb4a94cbb1..2cb885cfc336996f7b5a3e56e4686ed48ed26c8a 100644 (file)
@@ -163,8 +163,8 @@ ao_lco_drag_monitor(void)
 
        ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200));
        for (;;) {
-               PRINTD("Drag monitor count %d active %d delay %d\n",
-                      ao_lco_drag_beep_count, ao_lco_drag_active, delay);
+               PRINTD("Drag monitor count %d active %d delay %lu\n",
+                      ao_lco_drag_beep_count, ao_lco_drag_active, (unsigned long) delay);
                if (delay == (AO_TICK_TYPE) ~0)
                        ao_sleep(&ao_lco_drag_beep_count);
                else
@@ -217,8 +217,8 @@ ao_lco_input(void)
 
        for (;;) {
                ao_event_get(&event);
-               PRINTD("event type %d unit %d value %d\n",
-                      event.type, event.unit, event.value);
+               PRINTD("event type %d unit %d value %ld\n",
+                      event.type, event.unit, (long) event.value);
                switch (event.type) {
                case AO_EVENT_QUADRATURE:
                        switch (event.unit) {
index 3b123793d7ff4d8327e4d837e2ee8dddc7df1867..452092a092df80a4aa940e27f3b623977b5a1020 100644 (file)
@@ -29,7 +29,7 @@
 
 #if DEBUG
 extern uint8_t ao_lco_debug;
-#define PRINTD(...) do { if (!ao_lco_debug) break; printf ("\r%5u %s: ", ao_tick_count, __func__); printf(__VA_ARGS__); flush(); } while(0)
+#define PRINTD(...) do { if (!ao_lco_debug) break; printf ("\r%5lu %s: ", (unsigned long) ao_tick_count, __func__); printf(__VA_ARGS__); flush(); } while(0)
 #else
 #define PRINTD(...) 
 #endif
index bc54dc22b8ab9992d4b8b2a0419fc9774a62e228..b97662a0b29fd1eda6423eb5d1092b7b5300a8d3 100644 (file)
@@ -394,9 +394,9 @@ ao_lco_toggle_drag(void)
 AO_TICK_TYPE
 ao_lco_drag_beep_check(AO_TICK_TYPE now, AO_TICK_TYPE delay)
 {
-       PRINTD("beep check count %d delta %d\n",
+       PRINTD("beep check count %d delta %ld\n",
               ao_lco_drag_beep_count,
-              (AO_TICK_SIGNED) (now - ao_lco_drag_beep_time));
+              (long) (AO_TICK_SIGNED) (now - ao_lco_drag_beep_time));
        if (ao_lco_drag_beep_count) {
                if ((AO_TICK_SIGNED) (now - ao_lco_drag_beep_time) >= 0) {
                        if (ao_lco_drag_beep_on) {
index cfef2a631c488a12e86d130d2680dd3444593447..8d4476efdbe08c1c4f6ff6185ff2e5f8b591be5b 100644 (file)
@@ -79,8 +79,8 @@ ao_lco_input(void)
                        ao_event_get(&event);
                }
                ao_lco_wakeup();
-               PRINTD("event type %d unit %d value %d\n",
-                      event.type, event.unit, event.value);
+               PRINTD("event type %d unit %d value %ld\n",
+                      event.type, event.unit, (long) event.value);
                switch (event.type) {
                case AO_EVENT_BUTTON:
                        switch (event.unit) {
index 72617cc4504f24f18966e1a80f1be4699d2a1fc9..ca0615e7c5b75e30c8e1eb0b50f98d741977f2e7 100644 (file)
@@ -239,7 +239,7 @@ ao_m25_scan(void)
  * Erase the specified sector
  */
 uint8_t
-ao_storage_erase(uint32_t pos) 
+ao_storage_device_erase(uint32_t pos)
 {
        ao_port_t       cs;
 
index b0217368692fb7939ce391663aa815f4aa46132b..4c24e98b71c1e432883f32703a90e2f569d16ce8 100644 (file)
@@ -25,7 +25,7 @@
 #define DEBUG_LOW      1
 #define DEBUG_HIGH     2
 #if 1
-#define PRINTD(l, ...) do { if (DEBUG & (l)) { printf ("\r%5u %s: ", ao_tick_count, __func__); printf(__VA_ARGS__); flush(); } } while(0)
+#define PRINTD(l, ...) do { if (DEBUG & (l)) { printf ("\r%5lu %s: ", (unsigned long) ao_tick_count, __func__); printf(__VA_ARGS__); flush(); } } while(0)
 #else
 #define PRINTD(l,...) 
 #endif
index 1b31edf4611754fe1b8c8d8fe52562b161e8579e..0597a81c57fbc8677bc64d93002db7d0d0ca88b5 100644 (file)
@@ -34,7 +34,11 @@ static uint8_t       ao_mpu9250_configured;
 
 #if AO_MPU9250_SPI
 
-#define ao_mpu9250_spi_get()   ao_spi_get(AO_MPU9250_SPI_BUS, AO_SPI_SPEED_1MHz)
+#ifndef AO_MPU9250_SPI_SPEED
+#define AO_MPU9250_SPI_SPEED   AO_SPI_SPEED_1MHz
+#endif
+
+#define ao_mpu9250_spi_get()   ao_spi_get(AO_MPU9250_SPI_BUS, AO_MPU9250_SPI_SPEED)
 #define ao_mpu9250_spi_put()   ao_spi_put(AO_MPU9250_SPI_BUS)
 
 #define ao_mpu9250_spi_start()         ao_spi_set_cs(AO_MPU9250_SPI_CS_PORT,   \
@@ -559,7 +563,7 @@ ao_mpu9250_init(void)
         */
 
        ao_cur_task = &ao_mpu9250_task;
-       ao_spi_get(AO_MPU9250_SPI_BUS, AO_SPI_SPEED_1MHz);
+       ao_mpu9250_spi_get();
        ao_cur_task = NULL;
 #endif
        ao_cmd_register(&ao_mpu9250_cmds[0]);
index 07c49afc6b890a4094a842360223eddc52eef715..f5c51c8b874a6ac30dd14fdc0861996562d6536f 100644 (file)
@@ -440,8 +440,8 @@ ao_pad(void)
                                break;
                        }
                        if ((AO_TICK_SIGNED) (ao_time() - ao_pad_arm_time) > AO_SEC_TO_TICKS(20)) {
-                               PRINTD ("late pad arm_time %d time %d\n",
-                                       ao_pad_arm_time, ao_time());
+                               PRINTD ("late pad arm_time %ld time %ld\n",
+                                       (long) ao_pad_arm_time, ao_time());
                                break;
                        }
                        PRINTD ("ignite\n");
@@ -458,8 +458,8 @@ ao_pad(void)
                        if (!ao_log_running) ao_log_start();
 #endif
                        if ((AO_TICK_SIGNED) (ao_time() - ao_pad_arm_time) > AO_SEC_TO_TICKS(20)) {
-                               PRINTD ("late pad arm_time %d time %d\n",
-                                       ao_pad_arm_time, ao_time());
+                               PRINTD ("late pad arm_time %ld time %ld\n",
+                                       (long) ao_pad_arm_time, (long) ao_time());
                                break;
                        }
                        PRINTD ("ignite\n");
index a5fbd1daaa43e30340a066373a8221cdb6d19b34..97e67aa07bfd72f5cf934fbb33516afd363a509b 100644 (file)
@@ -191,7 +191,7 @@ ao_quadrature_test(void)
                        t = ao_quadrature_step[q];
                        printf("step %3d ", t);
 #endif
-                       printf ("count %3d state %2x\n", c, s);
+                       printf ("count %3ld state %2x\n", (long) c, s);
                        flush();
                }
        }
diff --git a/src/easytimer-v1/.gitignore b/src/easytimer-v1/.gitignore
new file mode 100644 (file)
index 0000000..2e32c6f
--- /dev/null
@@ -0,0 +1,2 @@
+ao_product.h
+easytimer-*.elf
diff --git a/src/easytimer-v1/Makefile b/src/easytimer-v1/Makefile
new file mode 100644 (file)
index 0000000..b0cd15c
--- /dev/null
@@ -0,0 +1,99 @@
+#
+# 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_profile.h \
+       ao_task.h \
+       ao_whiten.h \
+       ao_sample_profile.h \
+       ao_mpu.h \
+       stm32l.h \
+       Makefile
+
+#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_stdio.c \
+       ao_panic.c \
+       ao_timer.c \
+       ao_mutex.c \
+       ao_freq.c \
+       ao_dma_stm.c \
+       ao_spi_stm.c \
+       ao_data.c \
+       ao_bmx160.c \
+       ao_adc_stm.c \
+       ao_beep_stm.c \
+       ao_usb_stm.c \
+       ao_exti_stm.c \
+       ao_eeprom_stm.c \
+       ao_convert_volt.c \
+       ao_report.c \
+       ao_sample.c \
+       ao_kalman.c \
+       ao_pyro.c \
+       ao_flight.c \
+       ao_ignite.c \
+       $(PROFILE) \
+       $(SAMPLE_PROFILE) \
+       $(STACK_GUARD)
+
+PRODUCT=EasyTimer-v1
+PRODUCT_DEF=-DEASYTIMER_V_1
+IDPRODUCT=0x000d
+
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF)
+
+PROGNAME=easytimer-v1
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_easytimer.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
+       rm -f ao_product.h
+
+install:
+
+uninstall:
diff --git a/src/easytimer-v1/ao_easytimer.c b/src/easytimer-v1/ao_easytimer.c
new file mode 100644 (file)
index 0000000..8224ee0
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * 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>
+#include <ao_profile.h>
+#if HAS_SAMPLE_PROFILE
+#include <ao_sample_profile.h>
+#endif
+#if HAS_STACK_GUARD
+#include <ao_mpu.h>
+#endif
+
+int
+main(void)
+{
+       ao_clock_init();
+
+#if HAS_STACK_GUARD
+       ao_mpu_init();
+#endif
+
+       ao_task_init();
+       ao_timer_init();
+
+       ao_spi_init();
+       ao_dma_init();
+       ao_exti_init();
+
+       ao_adc_init();
+       ao_beep_init();
+       ao_cmd_init();
+
+       ao_eeprom_init();
+
+//     ao_storage_init();
+
+       ao_bmx160_init();
+
+       ao_flight_init();
+       // ao_log_init();
+       ao_report_init();
+
+       ao_usb_init();
+       ao_pyro_init();
+       ao_igniter_init();
+
+       ao_config_init();
+#if AO_PROFILE
+       ao_profile_init();
+#endif
+#if HAS_SAMPLE_PROFILE
+       ao_sample_profile_init();
+#endif
+
+       ao_start_scheduler();
+       return 0;
+}
diff --git a/src/easytimer-v1/ao_pins.h b/src/easytimer-v1/ao_pins.h
new file mode 100644 (file)
index 0000000..3ceb49f
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ * Copyright © 2012 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 HAS_TASK_QUEUE         1
+
+/* 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           0
+#define USE_SERIAL_2_STDIN     0
+#define SERIAL_2_PA2_PA3       0
+#define SERIAL_2_PD5_PD6       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_CONFIG_MAX_SIZE     1024
+
+#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 HAS_BATTERY_REPORT     1
+#define BEEPER_CHANNEL         1
+#define BEEPER_TIMER           4
+#define BEEPER_PORT            (&stm_gpiob)
+#define BEEPER_PIN             6
+#define HAS_RADIO              0
+#define HAS_TELEMETRY          0
+#define HAS_APRS               0
+#define HAS_COMPANION          0
+
+#define HAS_SPI_1              1
+#define SPI_1_PA5_PA6_PA7      0       
+#define SPI_1_PB3_PB4_PB5      1       /* IMU */
+#define SPI_1_PE13_PE14_PE15   0
+#define SPI_1_OSPEEDR          STM_OSPEEDR_10MHz
+
+#define HAS_SPI_2              0
+#define SPI_2_PB13_PB14_PB15   0       /* Flash, Companion, Radio */
+#define SPI_2_PD1_PD3_PD4      0
+#define SPI_2_OSPEEDR          STM_OSPEEDR_10MHz
+
+#define SPI_2_PORT             (&stm_gpiob)
+#define SPI_2_SCK_PIN          13
+#define SPI_2_MISO_PIN         14
+#define SPI_2_MOSI_PIN         15
+
+#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      0
+
+#define LOW_LEVEL_DEBUG                0
+
+#define LEDS_AVAILABLE         0
+
+#define HAS_GPS                        0
+#define HAS_FLIGHT             1
+#define HAS_ADC                        1
+#define HAS_ADC_TEMP           1
+#define HAS_LOG                        0
+
+/*
+ * Igniter
+ */
+
+#define HAS_IGNITE             0
+#define HAS_IGNITE_REPORT      1
+#define AO_PYRO_NUM            2
+
+#define AO_SENSE_PYRO(p,n)     ((p)->adc.sense[n])
+#define AO_IGNITER_CLOSED      400
+#define AO_IGNITER_OPEN                60
+
+/* Pyro A */
+#define AO_PYRO_PORT_0  (&stm_gpiob)
+#define AO_PYRO_PIN_0   0
+
+#define AO_ADC_SENSE_A          1
+#define AO_ADC_SENSE_A_PORT     (&stm_gpioa)
+#define AO_ADC_SENSE_A_PIN      1
+
+/* Pyro B */
+#define AO_PYRO_PORT_1  (&stm_gpiob)
+#define AO_PYRO_PIN_1   11
+
+#define AO_ADC_SENSE_B          0
+#define AO_ADC_SENSE_B_PORT     (&stm_gpioa)
+#define AO_ADC_SENSE_B_PIN      0
+
+
+/*
+ * ADC
+ */
+#define AO_DATA_RING           32
+#define AO_ADC_NUM_SENSE       2
+
+struct ao_adc {
+       int16_t                 sense[AO_ADC_NUM_SENSE];
+       int16_t                 v_batt;
+       int16_t                 temp;
+};
+
+#define AO_ADC_DUMP(p) \
+       printf("tick: %5u A: %5d B: %5d batt: %5d\n", \
+              (p)->tick, \
+               (p)->adc.sense[0], (p)->adc.sense[1], \
+              (p)->adc.v_batt);
+
+#define AO_ADC_V_BATT          2
+#define AO_ADC_V_BATT_PORT     (&stm_gpioa)
+#define AO_ADC_V_BATT_PIN      2
+
+#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 + 1)
+
+#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_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_SQ1              AO_ADC_SENSE_A
+#define AO_ADC_SQ2              AO_ADC_SENSE_B
+#define AO_ADC_SQ3             AO_ADC_V_BATT
+#define AO_ADC_SQ4             AO_ADC_TEMP
+
+/*
+ * Voltage divider on ADC battery sampler
+ */
+#define AO_BATTERY_DIV_PLUS    100     /* 100k */
+#define AO_BATTERY_DIV_MINUS   27      /* 27k */
+
+/*
+ * 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
+
+/*
+ * bmx160
+ */
+
+#define HAS_BMX160              1
+#define AO_BMX160_INT_PORT      (&stm_gpioc)
+#define AO_BMX160_INT_PIN       13
+#define AO_BMX160_SPI_BUS       (AO_SPI_1_PB3_PB4_PB5 | AO_SPI_MODE_0)
+#define AO_BMX160_SPI_CS_PORT   (&stm_gpioa)
+#define AO_BMX160_SPI_CS_PIN    15
+#define HAS_IMU                 1
+
+#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_accel_cook(packet)             (-ao_data_along(packet))
+
+/*
+ * Monitor
+ */
+
+#define HAS_MONITOR            0
+#define LEGACY_MONITOR         0
+#define HAS_MONITOR_PUT                1
+#define AO_MONITOR_LED         0
+#define HAS_RSSI               0
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/easytimer-v1/flash-loader/Makefile b/src/easytimer-v1/flash-loader/Makefile
new file mode 100644 (file)
index 0000000..a161364
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=easytimer-v1
+include $(TOPDIR)/stm/Makefile-flash.defs
diff --git a/src/easytimer-v1/flash-loader/ao_pins.h b/src/easytimer-v1/flash-loader/ao_pins.h
new file mode 100644 (file)
index 0000000..16aeec2
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright © 2020 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_gpioc
+#define AO_BOOT_APPLICATION_PIN                15
+#define AO_BOOT_APPLICATION_VALUE      1
+#define AO_BOOT_APPLICATION_MODE       AO_EXTI_MODE_PULL_UP
+
+#endif /* _AO_PINS_H_ */
index d1c049ac78aaf5b03905dc13542905f74cb01d71..9bc19038d6c6c82e65c4251d8ddf44ca8499cc06 100644 (file)
@@ -269,7 +269,7 @@ version(void)
        printf("manufacturer     %s\n"
               "product          %s\n"
               "serial-number    %u\n"
-#if HAS_FLIGHT || HAS_TRACKER
+#if HAS_LOG && (HAS_FLIGHT || HAS_TRACKER)
               "current-flight   %u\n"
 #endif
 #if HAS_LOG
@@ -287,7 +287,7 @@ version(void)
               , ao_manufacturer
               , ao_product
               , ao_serial_number
-#if HAS_FLIGHT || HAS_TRACKER
+#if HAS_LOG && (HAS_FLIGHT || HAS_TRACKER)
               , ao_flight_number
 #endif
 #if HAS_LOG
index 9f329f17554b57e1271e94f788b51ccc3761c2f5..217b0ab1a8cd5145dbc6470f2c95bede280144f1 100644 (file)
@@ -86,7 +86,7 @@ _ao_config_put(void)
        ao_config_setup();
        ao_config_erase();
        ao_config_write(0, &ao_config, sizeof (ao_config));
-#if HAS_FLIGHT
+#if HAS_FLIGHT && HAS_LOG
        ao_log_write_erase(0);
 #endif
        ao_config_flush();
@@ -238,6 +238,10 @@ _ao_config_get(void)
                        ao_config.pad_box = 1;
                if (minor < 23)
                        ao_config.pad_idle = 120;
+#endif
+#if HAS_APRS
+               if (minor < 24)
+                       ao_config.aprs_offset = 0;
 #endif
                ao_config.minor = AO_CONFIG_MINOR;
                ao_config_dirty = 1;
@@ -363,6 +367,8 @@ ao_config_send_frequency_set(void)
 
 #if HAS_FLIGHT
 
+#if HAS_BARO
+
 static void
 ao_config_main_deploy_show(void) 
 {
@@ -381,6 +387,8 @@ ao_config_main_deploy_set(void)
        _ao_config_edit_finish();
 }
 
+#endif
+
 #if HAS_ACCEL
 static void
 ao_config_accel_calibrate_show(void) 
@@ -498,6 +506,7 @@ ao_config_accel_calibrate_set(void)
 }
 #endif /* HAS_ACCEL */
 
+#if HAS_BARO
 static void
 ao_config_apogee_delay_show(void) 
 {
@@ -533,6 +542,7 @@ ao_config_apogee_lockout_set(void)
        ao_config.apogee_lockout = r;
        _ao_config_edit_finish();
 }
+#endif
 
 #endif /* HAS_FLIGHT */
 
@@ -619,26 +629,26 @@ static void
 ao_config_log_set(void) 
 {
 #if FLIGHT_LOG_APPEND
-       printf("Flight log fixed size %d kB\n", ao_storage_log_max >> 10);
+       printf("Flight log fixed size %u kB\n", (unsigned) (ao_storage_log_max >> 10));
 #else
-       uint16_t        block = (uint16_t) (ao_storage_block >> 10);
-       uint16_t        log_max = (uint16_t) (ao_storage_log_max >> 10);
        uint32_t        r;
 
        r = ao_cmd_decimal();
        if (ao_cmd_status != ao_cmd_success)
                return;
-       if (ao_log_present())
-               printf("Storage must be empty before changing log size\n");
-       else if (block > 1024 && (r & (block - 1)))
-               printf("Flight log size must be multiple of %d kB\n", block);
-       else if (r > log_max)
-               printf("Flight log max %d kB\n", log_max);
-       else {
-               _ao_config_edit_start();
-               ao_config.flight_log_max = r << 10;
-               _ao_config_edit_finish();
+       r = r << 10;
+       if (ao_log_present()) {
+               if (r != ao_config.flight_log_max)
+                       printf("Storage must be empty before changing log size\n");
+               return;
+       }
+       if (r > ao_storage_log_max) {
+               printf("Flight log max %u kB\n", (unsigned) (ao_storage_log_max >> 10));
+               return;
        }
+       _ao_config_edit_start();
+       ao_config.flight_log_max = r & ~(ao_storage_block - 1);
+       _ao_config_edit_finish();
 #endif
 }
 #endif /* HAS_LOG */
@@ -760,6 +770,24 @@ ao_config_aprs_set(void)
        ao_telemetry_reset_interval();
 }
 
+static void
+ao_config_aprs_offset_show(void)
+{
+       printf ("APRS offset: %d\n", ao_config.aprs_offset);
+}
+
+static void
+ao_config_aprs_offset_set(void)
+{
+       uint16_t r = ao_cmd_decimal();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       _ao_config_edit_start();
+       ao_config.aprs_offset = r;
+       _ao_config_edit_finish();
+       ao_telemetry_reset_interval();
+}
+
 #endif /* HAS_APRS */
 
 #if HAS_RADIO_AMP
@@ -966,7 +994,7 @@ ao_config_save(void);
 #endif
 
 const struct ao_config_var ao_config_vars[] = {
-#if HAS_FLIGHT
+#if HAS_FLIGHT && HAS_BARO
        { "m <meters>\0Main deploy (m)",
          ao_config_main_deploy_set,    ao_config_main_deploy_show, },
        { "d <delay>\0Apogee delay (s)",
@@ -1041,6 +1069,8 @@ const struct ao_config_var ao_config_vars[] = {
          ao_config_aprs_ssid_set, ao_config_aprs_ssid_show },
        { "C <0 compressed, 1 uncompressed>\0APRS format",
          ao_config_aprs_format_set, ao_config_aprs_format_show },
+       { "O <aprs-offset>\0APRS Offset from top of minute",
+         ao_config_aprs_offset_set, ao_config_aprs_offset_show },
 #endif
 #if HAS_FIXED_PAD_BOX
        { "B <box>\0Set pad box (1-99)",
index 41aafcca8cb5ae4151920bf7aeec34f6b514de0e..87509dff8df1e94d8b8b15866a5845d021c264c0 100644 (file)
@@ -38,7 +38,7 @@
 #include <ao_storage.h>
 
 #define ao_config_setup()              ao_storage_setup()
-#define ao_config_erase()              ao_storage_erase(ao_storage_config)
+#define ao_config_erase()              ao_storage_erase(ao_storage_config, ao_storage_block)
 #define ao_config_write(pos,bytes, len)        ao_storage_write(ao_storage_config+(pos), bytes, len)
 #define ao_config_read(pos,bytes, len) ao_storage_read(ao_storage_config+(pos), bytes, len)
 #define ao_config_flush()              ao_storage_flush()
@@ -58,7 +58,7 @@
 #endif
 
 #define AO_CONFIG_MAJOR        1
-#define AO_CONFIG_MINOR        23
+#define AO_CONFIG_MINOR        24
 
 #define AO_AES_LEN 16
 
@@ -123,6 +123,9 @@ struct ao_config {
        uint8_t         pad_box;                /* minor version 22 */
        uint8_t         pad_idle;               /* minor version 23 */
 #endif
+#if HAS_APRS
+       uint8_t         aprs_offset;            /* minor version 24 */
+#endif
 };
 
 #define AO_APRS_FORMAT_COMPRESSED      0
index 536ffa2bb295556686a64fc534dccdc9bda27fc3..77cd98e40cdc577bbfd7d998cdfb9f21b1fb5887 100644 (file)
@@ -27,11 +27,18 @@ volatile uint8_t            ao_data_present;
 void
 ao_data_get(struct ao_data *packet)
 {
-#if HAS_FLIGHT
-       uint8_t i = ao_data_ring_prev(ao_sample_data);
-#else
        uint8_t i = ao_data_ring_prev(ao_data_head);
-#endif
        memcpy(packet, (void *) &ao_data_ring[i], sizeof (struct ao_data));
 }
 #endif
+
+#if HAS_ACCEL
+accel_t
+ao_data_accel(volatile struct ao_data *packet) {
+       accel_t raw;
+       raw = ao_data_accel_raw(packet);
+       if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP)
+               raw = ao_data_accel_invert(raw);
+       return raw;
+}
+#endif
index 988ac4897ecafbb8798ce1e1b5ceb2bf09368144..b43a1cd498dd636a65c0c59c55bcf7af83090bbb 100644 (file)
@@ -114,6 +114,9 @@ struct ao_data {
 #endif
 #if HAS_MPU9250
        struct ao_mpu9250_sample        mpu9250;
+#if !HAS_MMA655X
+       int16_t                         z_accel;
+#endif
 #endif
 #if HAS_HMC5883
        struct ao_hmc5883_sample        hmc5883;
@@ -132,6 +135,9 @@ struct ao_data {
 #endif
 #if HAS_BMX160
        struct ao_bmx160_sample         bmx160;
+#if !HAS_ADXL375
+       int16_t z_accel;
+#endif
 #endif
 };
 
@@ -188,26 +194,10 @@ typedef AO_ALT_TYPE       alt_t;
 
 #endif
 
-#if !HAS_BARO && HAS_ADC
-
-#define HAS_BARO       1
-
-typedef int16_t pres_t;
-typedef int16_t alt_t;
-
-#define ao_data_pres(packet)   ((packet)->adc.pres)
-#define ao_data_temp(packet)   ((packet)->adc.temp)
-#define pres_to_altitude(p)    ao_pres_to_altitude(p)
-#define ao_data_pres_cook(p)
-
-#endif
-
 /*
  * Need a few macros to pull data from the sensors:
  *
- * ao_data_accel_sample        - pull raw sensor and convert to normalized values
- * ao_data_accel       - pull normalized value (lives in the same memory)
- * ao_data_set_accel   - store normalized value back in the sensor location
+ * ao_data_accel_raw   - pull raw sensor
  * ao_data_accel_invert        - flip rocket ends for positive acceleration
  */
 
@@ -219,8 +209,7 @@ typedef int16_t alt_t;
  */
 
 typedef int16_t accel_t;
-#define ao_data_accel(packet)                  ((packet)->adc.accel)
-#define ao_data_set_accel(packet, a)           ((packet)->adc.accel = (a))
+#define ao_data_accel_raw(packet)              ((packet)->adc.accel)
 #define ao_data_accel_invert(a)                        (0x7fff -(a))
 
 /*
@@ -306,12 +295,12 @@ typedef int16_t accel_t;
 
 #if HAS_ACCEL_REF
 
-#define ao_data_accel_cook(packet) \
+#define ao_data_accel_raw(packet) \
        ((uint16_t) ((((uint32_t) (packet)->adc.accel << 16) / ((packet)->adc.accel_ref << 1))) >> 1)
 
 #else
 
-#define ao_data_accel_cook(packet) ((packet)->adc.accel)
+#define ao_data_accel_raw(packet) ((packet)->adc.accel)
 
 #endif /* HAS_ACCEL_REF */
 
@@ -331,13 +320,11 @@ typedef int16_t accel_t;
 #error AO_MMA655X_INVERT not defined
 #endif
 
-#define ao_data_accel(packet)                  ((packet)->mma655x)
 #if AO_MMA655X_INVERT
-#define ao_data_accel_cook(packet)             (AO_ACCEL_INVERT - (packet)->mma655x)
+#define ao_data_accel_raw(packet)              (AO_ACCEL_INVERT - (packet)->mma655x)
 #else
-#define ao_data_accel_cook(packet)             ((packet)->mma655x)
+#define ao_data_accel_raw(packet)              ((packet)->mma655x)
 #endif
-#define ao_data_set_accel(packet, accel)       ((packet)->mma655x = (accel))
 #define ao_data_accel_invert(accel)            (AO_ACCEL_INVERT - (accel))
 
 #endif
@@ -352,13 +339,11 @@ typedef int16_t   accel_t;
 #error AO_ADXL375_INVERT not defined
 #endif
 
-#define ao_data_accel(packet)                  ((packet)->adxl375.AO_ADXL375_AXIS)
 #if AO_ADXL375_INVERT
-#define ao_data_accel_cook(packet)             (-ao_data_accel(packet))
+#define ao_data_accel_raw(packet)              (-(packet)->adxl375.AO_ADXL375_AXIS)
 #else
-#define ao_data_accel_cook(packet)             ao_data_accel(packet)
+#define ao_data_accel_raw(packet)              ((packet)->adxl375.AO_ADXL375_AXIS)
 #endif
-#define ao_data_set_accel(packet, accel)       (ao_data_accel(packet) = (accel))
 #define ao_data_accel_invert(accel)            (-(accel))
 
 #endif /* HAS_ADXL375 */
@@ -370,9 +355,7 @@ typedef int16_t     accel_t;
 typedef int16_t accel_t;
 
 /* MPU6000 is hooked up so that positive y is positive acceleration */
-#define ao_data_accel(packet)                  ((packet)->z_accel)
-#define ao_data_accel_cook(packet)             (-(packet)->mpu6000.accel_y)
-#define ao_data_set_accel(packet, accel)       ((packet)->z_accel = (accel))
+#define ao_data_accel_raw(packet)              (-(packet)->mpu6000.accel_y)
 #define ao_data_accel_invert(a)                        (-(a))
 
 #endif
@@ -408,6 +391,18 @@ static inline float ao_convert_accel(int16_t sensor)
 
 #endif
 
+#if !HAS_ACCEL && HAS_MPU9250
+
+#define HAS_ACCEL      1
+
+typedef int16_t accel_t;
+
+/* MPU9250 is hooked up so that positive y is positive acceleration */
+#define ao_data_accel_raw(packet)              (-(packet)->mpu9250.accel_y)
+#define ao_data_accel_invert(a)                        (-(a))
+
+#endif
+
 #if !HAS_GYRO && HAS_MPU9250
 
 #define HAS_GYRO       1
@@ -441,6 +436,18 @@ static inline float ao_convert_accel(int16_t sensor)
 
 #endif
 
+#if !HAS_ACCEL && HAS_BMX160
+
+#define HAS_ACCEL      1
+
+typedef int16_t accel_t;
+
+#define ao_data_accel_raw(packet)              -ao_data_along(packet)
+#define ao_data_accel_invert(a)                        (-(a))
+#define ao_data_accel_to_sample(accel)         ao_bmx_accel_to_sample(accel)
+
+#endif
+
 #if !HAS_GYRO && HAS_BMX160
 
 #define HAS_GYRO       1
@@ -535,4 +542,9 @@ ao_data_fill(int head) {
 
 #endif
 
+#if HAS_ACCEL
+accel_t
+ao_data_accel(volatile struct ao_data *packet);
+#endif
+
 #endif /* _AO_DATA_H_ */
index f258c48c0fa4fc20b48885c5cb5b77c30657a52e..5f6adb0e542599465b4de08c6a17d1f0cf5eb96f 100644 (file)
@@ -19,8 +19,6 @@
 #ifndef _AO_EEPROM_H_
 #define _AO_EEPROM_H_
 
-extern const ao_pos_t  ao_eeprom_total;
-
 /*
  * Write to eeprom
  */
index 5a5d5b72b0adfb887f238d6512c5b91b68b8a016..c5069158a61cc603914566a4917608a54a300be3 100644 (file)
@@ -21,6 +21,8 @@
 #include <ao_log.h>
 #endif
 
+#include <ao_flight.h>
+
 #if HAS_MPU6000 || HAS_MPU9250
 #include <ao_quaternion.h>
 #endif
@@ -62,12 +64,29 @@ uint8_t                     ao_sensor_errors;
  * resting
  */
 static uint16_t                ao_interval_end;
+#ifdef HAS_BARO
 static ao_v_t          ao_interval_min_height;
 static ao_v_t          ao_interval_max_height;
+#else
+static accel_t         ao_interval_min_accel_along, ao_interval_max_accel_along;
+static accel_t         ao_interval_min_accel_across, ao_interval_max_accel_across;
+static accel_t         ao_interval_min_accel_through, ao_interval_max_accel_through;
+#endif
 #if HAS_ACCEL
 static ao_v_t          ao_coast_avg_accel;
 #endif
 
+#define init_bounds(_cur, _min, _max) do {                             \
+               _min = _max = _cur;                                     \
+       } while (0)
+
+#define check_bounds(_cur, _min, _max) do {    \
+               if (_cur < _min)                \
+                       _min = _cur;            \
+               if (_cur > _max)                \
+                       _max = _cur;            \
+       } while(0)
+
 uint8_t                        ao_flight_force_idle;
 
 /* We also have a clock, which can be used to sanity check things in
@@ -109,9 +128,12 @@ ao_flight(void)
                        if (ao_config.accel_plus_g == 0 ||
                            ao_config.accel_minus_g == 0 ||
                            ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP ||
-                           ao_ground_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP ||
-                           ao_ground_height < -1000 ||
-                           ao_ground_height > 7000)
+                           ao_ground_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP
+#if HAS_BARO
+                           || ao_ground_height < -1000 ||
+                           ao_ground_height > 7000
+#endif
+                               )
                        {
                                /* Detected an accel value outside -1.5g to 1.5g
                                 * (or uncalibrated values), so we go into invalid mode
@@ -203,7 +225,9 @@ ao_flight(void)
                                ao_launch_tick = ao_boost_tick = ao_sample_tick;
 
                                /* start logging data */
+#if HAS_LOG
                                ao_log_start();
+#endif
 
 #if HAS_TELEMETRY
                                /* Increase telemetry rate */
@@ -238,7 +262,18 @@ ao_flight(void)
                            (int16_t) (ao_sample_tick - ao_boost_tick) > BOOST_TICKS_MAX)
                        {
 #if HAS_ACCEL
+#if HAS_BARO
                                ao_flight_state = ao_flight_fast;
+#else
+                               ao_flight_state = ao_flight_coast;
+
+                               /* Initialize landing detection interval values */
+                               ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS;
+
+                               init_bounds(ao_sample_accel_along, ao_interval_min_accel_along, ao_interval_max_accel_along);
+                               init_bounds(ao_sample_accel_across, ao_interval_min_accel_across, ao_interval_max_accel_across);
+                               init_bounds(ao_sample_accel_through, ao_interval_min_accel_through, ao_interval_max_accel_through);
+#endif
                                ao_coast_avg_accel = ao_accel;
 #else
                                ao_flight_state = ao_flight_coast;
@@ -247,7 +282,7 @@ ao_flight(void)
                                ao_wakeup(&ao_flight_state);
                        }
                        break;
-#if HAS_ACCEL
+#if HAS_ACCEL && HAS_BARO
                case ao_flight_fast:
                        /*
                         * This is essentially the same as coast,
@@ -264,6 +299,7 @@ ao_flight(void)
 #endif
                case ao_flight_coast:
 
+#if HAS_BARO
                        /*
                         * By customer request - allow the user
                         * to lock out apogee detection for a specified
@@ -308,9 +344,45 @@ ao_flight(void)
                                ao_flight_state = ao_flight_drogue;
                                ao_wakeup(&ao_flight_state);
                        }
+                       else
+#else /* not HAS_BARO */
+                       /* coast to land:
+                        *
+                        * accel: values stable
+                        */
+                       check_bounds(ao_sample_accel_along, ao_interval_min_accel_along, ao_interval_max_accel_along);
+                       check_bounds(ao_sample_accel_across, ao_interval_min_accel_across, ao_interval_max_accel_across);
+                       check_bounds(ao_sample_accel_through, ao_interval_min_accel_through, ao_interval_max_accel_through);
+
+#define MAX_QUIET_ACCEL        2
+
+                       if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) {
+                               if (ao_interval_max_accel_along - ao_interval_min_accel_along <= ao_data_accel_to_sample(MAX_QUIET_ACCEL) &&
+                                   ao_interval_max_accel_across - ao_interval_min_accel_across <= ao_data_accel_to_sample(MAX_QUIET_ACCEL) &&
+                                   ao_interval_max_accel_through - ao_interval_min_accel_through <= ao_data_accel_to_sample(MAX_QUIET_ACCEL))
+                               {
+                                       ao_flight_state = ao_flight_landed;
+#if HAS_ADC
+                                       /* turn off the ADC capture */
+                                       ao_timer_set_adc_interval(0);
+#endif
+
+                                       ao_wakeup(&ao_flight_state);
+                               }
+
+                               /* Reset interval values */
+                               ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS;
+
+                               init_bounds(ao_sample_accel_along, ao_interval_min_accel_along, ao_interval_max_accel_along);
+                               init_bounds(ao_sample_accel_across, ao_interval_min_accel_across, ao_interval_max_accel_across);
+                               init_bounds(ao_sample_accel_through, ao_interval_min_accel_through, ao_interval_max_accel_through);
+                       }
+#endif
 #if HAS_ACCEL
-                       else {
+                       {
+#if HAS_BARO
                        check_re_boost:
+#endif
                                ao_coast_avg_accel = ao_coast_avg_accel + ((ao_accel - ao_coast_avg_accel) >> 5);
                                if (ao_coast_avg_accel > AO_MSS_TO_ACCEL(20)) {
                                        ao_boost_tick = ao_sample_tick;
@@ -321,6 +393,7 @@ ao_flight(void)
 #endif
 
                        break;
+#if HAS_BARO
                case ao_flight_drogue:
 
                        /* drogue to main deploy:
@@ -363,7 +436,6 @@ ao_flight(void)
                         *
                         * barometer: altitude stable
                         */
-
                        if (ao_avg_height < ao_interval_min_height)
                                ao_interval_min_height = ao_avg_height;
                        if (ao_avg_height > ao_interval_max_height)
@@ -385,6 +457,7 @@ ao_flight(void)
                                ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS;
                        }
                        break;
+#endif /* HAS_BARO */
 #if HAS_FLIGHT_DEBUG
                case ao_flight_test:
 #if HAS_GYRO
@@ -418,20 +491,27 @@ ao_flight_dump(void)
 
        printf ("sample:\n");
        printf ("  tick        %d\n", ao_sample_tick);
+#if HAS_BARO
        printf ("  raw pres    %d\n", ao_sample_pres);
+#endif
 #if HAS_ACCEL
        printf ("  raw accel   %d\n", ao_sample_accel);
 #endif
+#if HAS_BARO
        printf ("  ground pres %d\n", ao_ground_pres);
        printf ("  ground alt  %d\n", ao_ground_height);
+#endif
 #if HAS_ACCEL
        printf ("  raw accel   %d\n", ao_sample_accel);
        printf ("  groundaccel %d\n", ao_ground_accel);
        printf ("  accel_2g    %d\n", ao_accel_2g);
 #endif
 
+#if HAS_BARO
        printf ("  alt         %d\n", ao_sample_alt);
        printf ("  height      %d\n", ao_sample_height);
+#endif
+
 #if HAS_ACCEL
        printf ("  accel       %d.%02d\n", int_part(accel), frac_part(accel));
 #endif
index e9d04dcce4ba848641e73d9fbfa06f5bac3d04e5..71c99a614352d928aaa34d5e4d9dd863c18e66b8 100644 (file)
@@ -236,5 +236,7 @@ ao_igniter_init(void)
        ao_ignite_set_pins();
        ao_add_task(&ao_igniter_task, ao_igniter, "igniter");
 #endif
+#if HAS_IGNITE || AO_PYRO_NUM
        ao_cmd_register(&ao_ignite_cmds[0]);
+#endif
 }
index 4f4ffe8f1b6a813b532cd4fe751ed6d684f34b6b..aaf0595f01ab7d5e345ab5997983386f78bd4c1e 100644 (file)
@@ -86,6 +86,7 @@ ao_kalman_predict(void)
        ao_k_speed += (ao_k_t) ao_accel * AO_K_STEP_100;
 }
 
+#if HAS_BARO
 static void
 ao_kalman_err_height(void)
 {
@@ -140,7 +141,9 @@ ao_kalman_err_height(void)
 #endif
        }
 }
+#endif
 
+#if HAS_BARO
 static void
 ao_kalman_correct_baro(void)
 {
@@ -163,6 +166,7 @@ ao_kalman_correct_baro(void)
        ao_k_speed  += (ao_k_t) AO_BARO_K1_100 * ao_error_h;
        ao_k_accel  += (ao_k_t) AO_BARO_K2_100 * ao_error_h;
 }
+#endif
 
 #if HAS_ACCEL
 
@@ -177,7 +181,7 @@ ao_kalman_err_accel(void)
        ao_error_a = (accel - ao_k_accel) >> 16;
 }
 
-#ifndef FORCE_ACCEL
+#if !defined(FORCE_ACCEL) && HAS_BARO
 static void
 ao_kalman_correct_both(void)
 {
@@ -255,12 +259,14 @@ ao_kalman_correct_accel(void)
 {
        ao_kalman_err_accel();
 
+#ifdef AO_FLIGHT_TEST
        if ((int16_t) (ao_sample_tick - ao_sample_prev_tick) > 5) {
                ao_k_height +=(ao_k_t) AO_ACCEL_K0_10 * ao_error_a;
                ao_k_speed  += (ao_k_t) AO_ACCEL_K1_10 * ao_error_a;
                ao_k_accel  += (ao_k_t) AO_ACCEL_K2_10 * ao_error_a;
                return;
        }
+#endif
        ao_k_height += (ao_k_t) AO_ACCEL_K0_100 * ao_error_a;
        ao_k_speed  += (ao_k_t) AO_ACCEL_K1_100 * ao_error_a;
        ao_k_accel  += (ao_k_t) AO_ACCEL_K2_100 * ao_error_a;
@@ -273,6 +279,7 @@ void
 ao_kalman(void)
 {
        ao_kalman_predict();
+#if HAS_BARO
 #if HAS_ACCEL
        if (ao_flight_state <= ao_flight_coast) {
 #ifdef FORCE_ACCEL
@@ -283,12 +290,21 @@ ao_kalman(void)
        } else
 #endif
                ao_kalman_correct_baro();
+#else
+#if HAS_ACCEL
+       ao_kalman_correct_accel();
+#endif
+#endif
        ao_height = from_fix(ao_k_height);
        ao_speed = from_fix(ao_k_speed);
        ao_accel = from_fix(ao_k_accel);
        if (ao_height > ao_max_height)
                ao_max_height = ao_height;
+#if HAS_BARO
        ao_avg_height_scaled = ao_avg_height_scaled - ao_avg_height + ao_sample_height;
+#else
+       ao_avg_height_scaled = ao_avg_height_scaled - ao_avg_height + ao_height;
+#endif
 #ifdef AO_FLIGHT_TEST
        if ((int16_t) (ao_sample_tick - ao_sample_prev_tick) > 50)
                ao_avg_height = (ao_avg_height_scaled + 1) >> 1;
index c0a42b295938586cd9f968af2cdb2445ae28e373..f0816aeeeb07365836c29627ccd84ed10c275660 100644 (file)
@@ -111,6 +111,27 @@ ao_log_erase_mark(void)
        ao_config_put();
 }
 
+/* Position of first flight record in slot */
+static uint32_t
+ao_log_pos(uint8_t slot)
+{
+       return ((slot) * ao_config.flight_log_max);
+}
+
+/* Start of erase block containing first flight record */
+static uint32_t
+ao_log_pos_block_start(uint8_t slot)
+{
+       return ao_log_pos(slot) & ~(ao_storage_block - 1);
+}
+
+/* End of erase block containing last flight record */
+static uint32_t
+ao_log_pos_block_end(uint8_t slot)
+{
+       return ao_log_pos_block_start(slot + 1);
+}
+
 #ifndef AO_LOG_UNCOMMON
 /*
  * Common logging functions which depend on the type of the log data
@@ -159,30 +180,17 @@ ao_log_check_data(void)
        return 1;
 }
 
-uint8_t
-ao_log_check_clear(void)
-{
-       uint8_t *b = (uint8_t *) &ao_log_data;
-       uint8_t i;
-
-       for (i = 0; i < sizeof (ao_log_type); i++) {
-               if (*b++ != 0xff)
-                       return 0;
-       }
-       return 1;
-}
-
 int16_t
 ao_log_flight(uint8_t slot)
 {
+       if (ao_storage_is_erased(ao_log_pos_block_start(slot)))
+               return 0;
+
        if (!ao_storage_read(ao_log_pos(slot),
                             &ao_log_data,
                             sizeof (ao_log_type)))
                return -(int16_t) (slot + 1);
 
-       if (ao_log_check_clear())
-               return 0;
-
        if (!ao_log_check_data() || ao_log_data.type != AO_LOG_FLIGHT)
                return -(int16_t) (slot + 1);
 
@@ -196,12 +204,6 @@ ao_log_slots(void)
        return (uint8_t) (ao_storage_log_max / ao_config.flight_log_max);
 }
 
-uint32_t
-ao_log_pos(uint8_t slot)
-{
-       return ((slot) * ao_config.flight_log_max);
-}
-
 static int16_t
 ao_log_max_flight(void)
 {
@@ -222,33 +224,16 @@ ao_log_max_flight(void)
        return max_flight;
 }
 
-static void
+static uint8_t
 ao_log_erase(uint8_t slot) 
 {
-       uint32_t log_current_pos, log_end_pos;
+       uint32_t start_pos;
+       uint32_t end_pos;
 
        ao_log_erase_mark();
-       log_current_pos = ao_log_pos(slot);
-       log_end_pos = log_current_pos + ao_config.flight_log_max;
-       while (log_current_pos < log_end_pos) {
-               uint8_t i;
-               static uint8_t b;
-
-               /*
-                * Check to see if we've reached the end of
-                * the used memory to avoid re-erasing the same
-                * memory over and over again
-                */
-               for (i = 0; i < 16; i++) {
-                       if (ao_storage_read(log_current_pos + i, &b, 1))
-                               if (b != 0xff)
-                                       break;
-               }
-               if (i == 16)
-                       break;
-               ao_storage_erase(log_current_pos);
-               log_current_pos += ao_storage_block;
-       }
+       start_pos = ao_log_pos_block_start(slot);
+       end_pos = ao_log_pos_block_end(slot);
+       return ao_storage_erase(start_pos, end_pos - start_pos);
 }
 
 static void
@@ -298,12 +283,13 @@ ao_log_scan(void)
                log_slots = ao_log_slots();
                for (log_slot = 1; log_slot < log_slots; log_slot++) {
                        if (ao_log_flight(log_slot) != 0)
-                               ao_log_erase(log_slot);
+                               if (!ao_log_erase(log_slot))
+                                       printf("erase %d failed\n", log_slot);
                }
                ao_config_log_fix_append();
        }
        ao_log_current_pos = ao_log_pos(0);
-       ao_log_end_pos = ao_log_current_pos + ao_storage_log_max;
+       ao_log_end_pos = ao_log_pos_block_end(0);
 
        if (ao_flight_number) {
                uint32_t        full = ao_log_current_pos;
@@ -359,7 +345,7 @@ ao_log_scan(void)
        do {
                if (ao_log_flight(log_slot) == 0) {
                        ao_log_current_pos = ao_log_pos(log_slot);
-                       ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max;
+                       ao_log_end_pos = ao_log_pos_block_end(log_slot);
                        break;
                }
                if (++log_slot >= log_slots)
@@ -420,7 +406,12 @@ ao_log_list(void)
                        printf ("flight %d start %x end %x\n",
                                flight,
                                (uint16_t) (ao_log_pos(slot) >> 8),
-                               (uint16_t) (ao_log_pos(slot+1) >> 8));
+                               (uint16_t) (ao_log_pos_block_end(slot) >> 8));
+               else
+                       printf ("slot %d  start %x end %x\n",
+                               slot,
+                               (uint16_t) (ao_log_pos(slot) >> 8),
+                               (uint16_t) (ao_log_pos_block_end(slot) >> 8));
        }
        printf ("done\n");
 }
@@ -449,11 +440,13 @@ ao_log_delete(void)
 #if HAS_TRACKER
                                ao_tracker_erase_start(cmd_flight);
 #endif
-                               ao_log_erase(slot);
+                               if (ao_log_erase(slot))
+                                       puts("Erased");
+                               else
+                                       puts("Failed to erase");
 #if HAS_TRACKER
                                ao_tracker_erase_end();
 #endif
-                               puts("Erased");
                                return;
                        }
                }
index 1c0ba4e3cf8c766049e42b44aa2478b8160c6e35..8fe8b701c291a54af52c8e4864e824994d259ced 100644 (file)
@@ -96,10 +96,6 @@ ao_log(void);
 uint8_t
 ao_log_scan(void);
 
-/* Return the position of the start of the given log slot */
-uint32_t
-ao_log_pos(uint8_t slot);
-
 /* Start logging to eeprom */
 void
 ao_log_start(void);
index 7284932cf6f2c98d2558931ff3895964258179d2..bf326c1a7fb972b7e0d601adfaab767b806586a0 100644 (file)
@@ -84,14 +84,14 @@ ao_log_gps_tracking(uint16_t tick, struct ao_telemetry_satellite *gps_tracking_d
 int8_t
 ao_log_check(uint32_t pos)
 {
+       if (ao_storage_is_erased(pos & ~(ao_storage_block - 1)))
+               return 0;
+
        if (!ao_storage_read(pos,
                             &ao_log_data,
                             sizeof (struct ao_log_gps)))
                return AO_LOG_INVALID;
 
-       if (ao_log_check_clear())
-               return AO_LOG_EMPTY;
-
        if (!ao_log_check_data())
                return AO_LOG_INVALID;
        return AO_LOG_VALID;
index fdf8da43fe9b1d3ecaa3a936f0c5c737de7c915d..0829bcbb2286df78e60efbc5f5e3a5019253b374 100644 (file)
@@ -21,7 +21,7 @@
 #include <ao_data.h>
 #include <ao_flight.h>
 
-static struct ao_log_telestatic log;
+static struct ao_log_telestatic log_data;
 
 const uint8_t ao_log_format = AO_LOG_FORMAT_TELESTATIC;
 
@@ -41,15 +41,15 @@ ao_log_telestatic(void)
 {
        uint8_t wrote = 0;
        /* set checksum */
-       log.csum = 0;
-       log.csum = ao_log_csum((uint8_t *) &log);
+       log_data.csum = 0;
+       log_data.csum = ao_log_csum((uint8_t *) &log_data);
        ao_mutex_get(&ao_log_mutex); {
                if (ao_log_current_pos >= ao_log_end_pos && ao_log_running)
                        ao_log_stop();
                if (ao_log_running) {
                        wrote = 1;
                        ao_storage_write(ao_log_current_pos,
-                                        &log,
+                                        &log_data,
                                         sizeof (struct ao_log_telestatic));
                        ao_log_current_pos += sizeof (struct ao_log_telestatic);
                }
@@ -75,9 +75,9 @@ ao_log(void)
                while (!ao_log_running)
                        ao_sleep(&ao_log_running);
        
-               log.type = AO_LOG_FLIGHT;
-               log.tick = ao_time();
-               log.u.flight.flight = ao_flight_number;
+               log_data.type = AO_LOG_FLIGHT;
+               log_data.tick = ao_time();
+               log_data.u.flight.flight = ao_flight_number;
                ao_log_telestatic();
 
                /* Write the whole contents of the ring to the log
@@ -87,18 +87,18 @@ ao_log(void)
                for (;;) {
                        /* Write samples to EEPROM */
                        while (ao_log_data_pos != ao_data_head) {
-                               log.tick = ao_data_ring[ao_log_data_pos].tick;
-                               log.type = AO_LOG_SENSOR;
+                               log_data.tick = ao_data_ring[ao_log_data_pos].tick;
+                               log_data.type = AO_LOG_SENSOR;
 #if HAS_ADS131A0X
-                               log.u.sensor.pressure = ao_data_ring[ao_log_data_pos].ads131a0x.ain[0];
-                               log.u.sensor.pressure2 = ao_data_ring[ao_log_data_pos].ads131a0x.ain[1];
-                               log.u.sensor.thrust = ao_data_ring[ao_log_data_pos].ads131a0x.ain[2];
-                               log.u.sensor.mass = ao_data_ring[ao_log_data_pos].ads131a0x.ain[3];
+                               log_data.u.sensor.pressure = ao_data_ring[ao_log_data_pos].ads131a0x.ain[0];
+                               log_data.u.sensor.pressure2 = ao_data_ring[ao_log_data_pos].ads131a0x.ain[1];
+                               log_data.u.sensor.thrust = ao_data_ring[ao_log_data_pos].ads131a0x.ain[2];
+                               log_data.u.sensor.mass = ao_data_ring[ao_log_data_pos].ads131a0x.ain[3];
 #endif
-                               log.u.sensor.t_low = ao_data_ring[ao_log_data_pos].max6691.sensor[0].t_low;
+                               log_data.u.sensor.t_low = ao_data_ring[ao_log_data_pos].max6691.sensor[0].t_low;
                                int i;
                                for (i = 0; i < 4; i++)
-                                       log.u.sensor.t_high[i] = ao_data_ring[ao_log_data_pos].max6691.sensor[i].t_high;
+                                       log_data.u.sensor.t_high[i] = ao_data_ring[ao_log_data_pos].max6691.sensor[i].t_high;
                                ao_log_telestatic();
                                ao_log_data_pos = ao_data_ring_next(ao_log_data_pos);
                        }
index 7248865427b725a60d6544f3e4fbec90bca59511..eaa6c78b8626d3b0070d0d8e811ca9d70aa59352 100644 (file)
@@ -60,8 +60,12 @@ const char ao_product[] = AO_iProduct_STRING;
 #define TOTAL_LENGTH           (HEADER_LEN + AO_USB_HAS_INT * CONTROL_CLASS_LEN + DATA_LEN)
 #define NUM_INTERFACES         (AO_USB_HAS_INT + 1)
 
+#ifndef AO_USBCONFIG_SYMBOL
+#define AO_USBCONFIG_SYMBOL AO_ROMCONFIG_SYMBOL
+#endif
+
 /* USB descriptors in one giant block of bytes */
-AO_ROMCONFIG_SYMBOL uint8_t ao_usb_descriptors [] =
+AO_USBCONFIG_SYMBOL uint8_t ao_usb_descriptors [] =
 {
        /* Device descriptor */
        0x12,
index 12c3a1e90acabb589114ed786edb08caf9a7c0fb..26604d1ad4d784a96318dae4e8115327fe702cbc 100644 (file)
@@ -40,6 +40,8 @@ static const uint8_t flight_reports[] = {
        MORSE4(1,0,0,1),        /* invalid 'X' */
 };
 
+static enum ao_flight_state ao_report_state;
+
 #if HAS_BEEP
 #define low(time)      ao_beep_for(AO_BEEP_LOW, time)
 #define mid(time)      ao_beep_for(AO_BEEP_MID, time)
@@ -58,8 +60,6 @@ static const uint8_t flight_reports[] = {
 #endif
 #define pause(time)    ao_delay(time)
 
-static enum ao_flight_state ao_report_state;
-
 /*
  * Farnsworth spacing
  *
@@ -115,7 +115,7 @@ static enum ao_flight_state ao_report_state;
  */
 
 static void
-ao_report_beep(void) 
+ao_report_flight_state(void) 
 {
        uint8_t r = flight_reports[ao_flight_state];
        uint8_t l = r & 7;
@@ -190,6 +190,7 @@ ao_report_battery(void)
 #endif
 
 #if HAS_IGNITE_REPORT
+#if HAS_IGNITE
 static uint8_t
 ao_report_igniter_ready(enum ao_igniter igniter)
 {
@@ -202,16 +203,13 @@ ao_report_igniter(void)
        return (ao_report_igniter_ready(ao_igniter_drogue) |
                     (ao_report_igniter_ready(ao_igniter_main) << 1));
 }
+#endif
 
 static void
 ao_report_continuity(void) 
 {
-       uint8_t c;
-
-#if !HAS_IGNITE
-       if (!ao_igniter_present)
-               return;
-#endif
+       uint8_t c;
+#if HAS_IGNITE
        c = ao_report_igniter();
        if (c) {
                while (c--) {
@@ -225,8 +223,11 @@ ao_report_continuity(void)
                        low(AO_MS_TO_TICKS(20));
                }
        }
+#endif
 #if AO_PYRO_NUM
+#if HAS_IGNITE
        pause(AO_MS_TO_TICKS(250));
+#endif
        for(c = 0; c < AO_PYRO_NUM; c++) {
                enum ao_igniter_status  status = ao_pyro_status(c);
                if (status == ao_igniter_ready)
@@ -261,7 +262,7 @@ ao_report(void)
                        ao_report_battery();
                else
 #endif
-                       ao_report_beep();
+                       ao_report_flight_state();
 #if HAS_SENSOR_ERRORS
                if (ao_report_state == ao_flight_invalid && ao_sensor_errors)
                        ao_report_number(ao_sensor_errors);
index 9cba36c1004b37ec31717e7c4431e08ede4bf615..67f20aff9093b5941a3ccee9ffc5e6e752f96479 100644 (file)
 #endif
 
 uint16_t       ao_sample_tick;         /* time of last data */
+#if HAS_BARO
 pres_t         ao_sample_pres;
 alt_t          ao_sample_alt;
 alt_t          ao_sample_height;
+#endif
 #if HAS_ACCEL
 accel_t                ao_sample_accel;
 #endif
@@ -60,8 +62,10 @@ uint8_t              ao_sample_data;
  * Sensor calibration values
  */
 
+#if HAS_BARO
 pres_t         ao_ground_pres;         /* startup pressure */
 alt_t          ao_ground_height;       /* MSL of ao_ground_pres */
+#endif
 
 #if HAS_ACCEL
 accel_t                ao_ground_accel;        /* startup acceleration */
@@ -81,7 +85,9 @@ int32_t               ao_ground_roll;
 static uint8_t ao_preflight;           /* in preflight mode */
 
 static uint16_t        nsamples;
+#if HAS_BARO
 int32_t ao_sample_pres_sum;
+#endif
 #if HAS_ACCEL
 int32_t ao_sample_accel_sum;
 #endif
@@ -105,7 +111,9 @@ ao_sample_preflight_add(void)
 #if HAS_ACCEL
        ao_sample_accel_sum += ao_sample_accel;
 #endif
+#if HAS_BARO
        ao_sample_pres_sum += ao_sample_pres;
+#endif
 #if HAS_GYRO
        ao_sample_accel_along_sum += ao_sample_accel_along;
        ao_sample_accel_across_sum += ao_sample_accel_across;
@@ -171,9 +179,11 @@ ao_sample_preflight_set(void)
        ao_ground_accel = ao_sample_accel_sum >> 9;
        ao_sample_accel_sum = 0;
 #endif
+#if HAS_BARO
        ao_ground_pres = ao_sample_pres_sum >> 9;
        ao_ground_height = pres_to_altitude(ao_ground_pres);
        ao_sample_pres_sum = 0;
+#endif
 #if HAS_GYRO
        ao_ground_accel_along = ao_sample_accel_along_sum >> 9;
        ao_ground_accel_across = ao_sample_accel_across_sum >> 9;
@@ -215,7 +225,10 @@ ao_sample_preflight_set(void)
        ao_quaternion_vectors_to_rotation(&ao_rotation, &up, &orient);
 #if HAS_FLIGHT_DEBUG
        if (ao_orient_test)
-               printf("\n\treset\n");
+               printf("\n\treset across %d through %d along %d\n",
+                      (ao_ground_accel_across - ao_config.accel_zero_across),
+                      (ao_ground_accel_through - ao_config.accel_zero_through),
+                      (ao_ground_accel_along - ao_config.accel_zero_along));
 #endif 
 
        ao_sample_compute_orient();
@@ -338,10 +351,7 @@ ao_sample(void)
 #endif
 
 #if HAS_ACCEL
-               ao_sample_accel = ao_data_accel_cook(ao_data);
-               if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP)
-                       ao_sample_accel = ao_data_accel_invert(ao_sample_accel);
-               ao_data_set_accel(ao_data, ao_sample_accel);
+               ao_sample_accel = ao_data_accel(ao_data);
 #endif
 #if HAS_GYRO
                ao_sample_accel_along = ao_data_along(ao_data);
@@ -375,8 +385,10 @@ ao_sample_init(void)
 {
        ao_config_get();
        nsamples = 0;
+#if HAS_BARO
        ao_sample_pres_sum = 0;
        ao_sample_pres = 0;
+#endif
 #if HAS_ACCEL
        ao_sample_accel_sum = 0;
        ao_sample_accel = 0;
index cfd116f9791bc536ae2e5709ddc066a3d84f3d8e..73b31c6420005cc7ee75d65a19c5e1b0e6302842 100644 (file)
 #include <ao.h>
 #include <ao_storage.h>
 
+#define AO_STORAGE_DATA_SIZE   256
+
+static uint8_t storage_data[AO_STORAGE_DATA_SIZE];
+
 uint8_t
-ao_storage_read(ao_pos_t pos, void *v_buf, uint16_t len) 
+ao_storage_read(ao_pos_t pos, void *v_buf, uint16_t len)
 {
        uint8_t *buf = v_buf;
        uint16_t this_len;
@@ -81,7 +85,60 @@ ao_storage_write(ao_pos_t pos, void *v_buf, uint16_t len)
        return 1;
 }
 
-static uint8_t storage_data[128];
+uint8_t
+ao_storage_is_erased(uint32_t pos)
+{
+       uint32_t        read_pos;
+       uint32_t        read_len;
+       uint32_t        i;
+
+       read_pos = pos;
+       read_len = ao_storage_block;
+       while (read_len) {
+               uint32_t this_time = AO_STORAGE_DATA_SIZE;
+               if (this_time > read_len)
+                       this_time = read_len;
+               if (!ao_storage_read(read_pos, storage_data, this_time))
+                       return 0;
+               for (i = 0; i < this_time; i++)
+                       if (storage_data[i] != 0xff)
+                               return 0;
+               read_pos += this_time;
+               read_len -= this_time;
+       }
+       return 1;
+}
+
+uint8_t
+ao_storage_erase(uint32_t start_pos, uint32_t len)
+{
+       /* Round 'len' up to ao_storage_block units */
+       len = ((len + ao_storage_block - 1) / ao_storage_block) * ao_storage_block;
+
+       /*
+        * Start at the end of the area to erase so that the
+        * last block cleared is the first block; this will ensure
+        * that partially erased flight logs still appear in the list
+        * and can be re-erased.
+        */
+       uint32_t pos = start_pos + len - ao_storage_block;
+       while (len) {
+               int tries;
+
+#define MAX_TRIES      4       /* needs to be at least 2 */
+               for (tries = 0; tries < MAX_TRIES; tries++) {
+                       if (ao_storage_is_erased(pos))
+                               break;
+                       if (!ao_storage_device_erase(pos))
+                               return 0;
+               }
+               if (tries == MAX_TRIES)
+                       return 0;
+               pos -= ao_storage_block;
+               len -= ao_storage_block;
+       }
+       return 1;
+}
 
 static void
 ao_storage_dump(void) 
@@ -143,19 +200,16 @@ ao_storage_zap(void)
        uint32_t v = ao_cmd_hex();
        if (ao_cmd_status != ao_cmd_success)
                return;
-       ao_storage_erase((uint32_t) v << 8);
+       ao_storage_erase((uint32_t) v << 8, ao_storage_block);
 }
 
 static void
 ao_storage_zapall(void) 
 {
-       uint32_t        pos;
-
        ao_cmd_white();
        if (!ao_match_word("DoIt"))
                return;
-       for (pos = 0; pos < ao_storage_log_max; pos += ao_storage_block)
-               ao_storage_erase(pos);
+       ao_storage_erase(0, ao_storage_log_max);
 }
 
 #if AO_STORAGE_TEST
@@ -265,26 +319,26 @@ ao_storage_incr_check_block(uint32_t pos)
 static uint8_t
 ao_storage_test_block(uint32_t pos) 
 {
-       ao_storage_erase(pos);
+       ao_storage_erase(pos, ao_storage_block);
        printf(" erase"); flush();
        if (!ao_storage_check_block(pos, 0xff))
                return 0;
        printf(" zero"); flush();
        if (!ao_storage_fill_check_block(pos, 0x00))
                return 0;
-       ao_storage_erase(pos);
+       ao_storage_erase(pos, ao_storage_block);
        printf(" 0xaa"); flush();
        if (!ao_storage_fill_check_block(pos, 0xaa))
                return 0;
-       ao_storage_erase(pos);
+       ao_storage_erase(pos, ao_storage_block);
        printf(" 0x55"); flush();
        if (!ao_storage_fill_check_block(pos, 0x55))
                return 0;
-       ao_storage_erase(pos);
+       ao_storage_erase(pos, ao_storage_block);
        printf(" increment"); flush();
        if (!ao_storage_incr_check_block(pos))
                return 0;
-       ao_storage_erase(pos);
+       ao_storage_erase(pos, ao_storage_block);
        printf(" pass\n"); flush();
        return 1;
 }
@@ -304,6 +358,27 @@ ao_storage_test(void)
        }
        printf("Test complete\n");
 }
+
+static void
+ao_storage_fill(void)
+{
+       uint32_t        pos;
+
+       ao_cmd_white();
+       if (!ao_match_word("DoIt"))
+               return;
+       printf("erase "); flush();
+       ao_storage_erase(0, ao_storage_log_max);
+       for (pos = 0; pos < sizeof (storage_data); pos++)
+               storage_data[pos] = (uint8_t) pos;
+       for (pos = 0; pos < ao_storage_log_max; pos += sizeof (storage_data)) {
+               if ((pos & 0xffff) == 0) {
+                       printf("Fill 0x%x\n", pos); flush();
+               }
+               ao_storage_write(pos, storage_data, sizeof (storage_data));
+       }
+       printf("Fill complete\n");
+}
 #endif /* AO_STORAGE_TEST */
 
 static void
@@ -325,6 +400,7 @@ const struct ao_cmds ao_storage_cmds[] = {
        { ao_storage_zapall,"Z <key>\0Erase all. <key> is doit with D&I" },
 #if AO_STORAGE_TEST
        { ao_storage_test, "V <key>\0Validate flash (destructive). <key> is doit with D&I" },
+       { ao_storage_fill, "F <key>\0Fill flash with data. <key> is doit with D&I" },
 #endif
        { 0, NULL },
 };
index cf37a824db0a1c986603fd0b267d9cce59bcaaf4..1c5867e09eed3e9dc78f79a9a00490d488c3d9a4 100644 (file)
@@ -66,7 +66,13 @@ ao_storage_read(ao_pos_t pos, void *buf, uint16_t len);
 
 /* Erase a block of storage. This always clears ao_storage_block bytes */
 uint8_t
-ao_storage_erase(ao_pos_t pos);
+ao_storage_erase(ao_pos_t pos, uint32_t len);
+
+/* Check storage starting at pos to see if the chunk there
+ * is erased
+ */
+uint8_t
+ao_storage_is_erased(uint32_t pos);
 
 /* Flush any pending writes to stable storage */
 void
@@ -88,6 +94,10 @@ ao_storage_device_read(ao_pos_t pos, void *buf, uint16_t len);
 uint8_t
 ao_storage_device_write(ao_pos_t pos, void *buf, uint16_t len);
 
+/* Erase device from pos through pos + ao_storage_block */
+uint8_t
+ao_storage_device_erase(uint32_t pos);
+
 /* Initialize low-level device bits */
 void
 ao_storage_device_init(void);
index 2092c84f403cd65606eeb78078a3d64d7f689ab6..c2b2eb5a1bad0569d909481c21caf20773269457 100644 (file)
@@ -443,6 +443,28 @@ ao_send_companion(void)
 }
 #endif
 
+#if HAS_APRS
+static void
+ao_set_aprs_time(void)
+{
+       uint16_t interval = ao_config.aprs_interval;
+
+       if ((ao_gps_data.flags & AO_GPS_DATE_VALID) && interval != 0) {
+               int second = (ao_gps_data.second / interval + 1) * interval + ao_config.aprs_offset;
+               int delta;
+               if (second >= 60) {
+                       second = ao_config.aprs_offset;
+                       delta = second + 60 - ao_gps_data.second;
+               } else {
+                       delta = second - ao_gps_data.second;
+               }
+               ao_aprs_time = ao_gps_tick + AO_SEC_TO_TICKS(delta);
+       } else {
+               ao_aprs_time += AO_SEC_TO_TICKS(ao_config.aprs_interval);
+       }
+}
+#endif
+
 static void
 ao_telemetry(void)
 {
@@ -471,6 +493,7 @@ ao_telemetry(void)
 #endif
 #if HAS_APRS
                ao_aprs_time = time;
+               ao_set_aprs_time();
 #endif
                while (ao_telemetry_interval) {
                        time = ao_time() + AO_SEC_TO_TICKS(100);
@@ -539,7 +562,7 @@ ao_telemetry(void)
 #if HAS_APRS
                        if (ao_config.aprs_interval != 0) {
                                if ((int16_t) (ao_time() - ao_aprs_time) >= 0) {
-                                       ao_aprs_time = ao_time() + AO_SEC_TO_TICKS(ao_config.aprs_interval);
+                                       ao_set_aprs_time();
                                        ao_aprs_send();
                                }
                                if ((int16_t) (time - ao_aprs_time) > 0)
index 1454c17c31815aadd08c9d060f10a81cacf78711..0f2491031e8e2d0de8774e2ba1ab96f4d70e9b47 100644 (file)
@@ -134,7 +134,7 @@ ao_tracker(void)
                                                height = -height;
 
                                        if (ao_tracker_force_telem > 1)
-                                               printf("head %d ring %d ground_distance %d height %d\n", gps_head, ring, ground_distance, height);
+                                               printf("head %d ring %d ground_distance %ld height %d\n", gps_head, ring, (long) ground_distance, height);
                                        if (ground_distance > ao_config.tracker_motion ||
                                            height > (ao_config.tracker_motion << 1))
                                        {
index 44b43bfe94d5f627f6f5bfc3b9f26d7a702eab22..1ae94c1548bef0c9261a25dde823fce1bb18ca6f 100644 (file)
@@ -35,7 +35,7 @@ IDPRODUCT=0x000a
 
 CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS)
 
-LDFLAGS=$(CFLAGS) -L$(TOPDIR)/lpc -Wl,-Taltos-loader.ld
+LDFLAGS=-nostartfiles $(CFLAGS) -L$(TOPDIR)/lpc -Taltos-loader.ld
 
 PROGNAME=altos-flash
 PROG=$(HARDWARE)-$(PROGNAME)-$(VERSION).elf
index 8b2973512ba9d58b2e045631bfb22d90b91c9070..48153da30d47f916410efb3b695559ba1692f5d7 100644 (file)
@@ -2,13 +2,17 @@ ifndef TOPDIR
 TOPDIR=..
 endif
 
+# Disable floating-point support in printf to save space
+
+PICOLIBC_PRINTF_CFLAGS = -DPICOLIBC_INTEGER_PRINTF_SCANF
+
 include $(TOPDIR)/Makefile.defs
 
 vpath % $(TOPDIR)/lpc:$(AO_VPATH)
 
 CC=$(ARM_CC)
 
-LIBS=-L$(NEWLIB_NANO)/arm-none-eabi/lib/thumb/v6-m -lc -lm -lgcc
+LIBS=-lm
 
 LPC_CFLAGS=-mlittle-endian -mcpu=cortex-m0 -mthumb\
-        -I$(TOPDIR)/lpc $(AO_CFLAGS) $(NEWLIB_CFLAGS)
+        -I$(TOPDIR)/lpc $(AO_CFLAGS) $(PICOLIBC_CFLAGS)
index 7fdcf0dc4770a0050e6fbd6c35eb65967a7d7f5a..7ea76e1c85b3bb838bddc2fcc402d61676f239fb 100644 (file)
@@ -4,7 +4,7 @@ endif
 
 include $(TOPDIR)/lpc/Makefile-lpc.defs
 
-LDFLAGS=$(CFLAGS) -L$(TOPDIR)/lpc -Wl,-Taltos.ld -n
+LDFLAGS=-nostartfiles $(CFLAGS) -L$(TOPDIR)/lpc -Taltos.ld -n
 
 ao_serial_lpc.h: $(TOPDIR)/lpc/baud_rate ao_pins.h
        nickle $(TOPDIR)/lpc/baud_rate `awk '/AO_LPC_CLKOUT/{print $$3}' ao_pins.h` > $@
index be4f115d50e76b666307c7efa15baf139138f7c3..75b527fb24bf9fc79a3d9addc5f53d179e44ad66 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-MEMORY {
-       rom : ORIGIN = 0x00000000, LENGTH = 4K
-       ram : ORIGIN = 0x10000000, LENGTH = 4k - 128 - 32
-       usb (!x) : ORIGIN = 0x20004000 + 2K - 256, LENGTH = 256
-       stack (!w) : ORIGIN = 0x10000000 + 4K - 128 - 32, LENGTH = 128
-}
+__flash = 0x0;
+__flash_size = 4K;
+__ram = 0x10000000;
+__ram_size = 4k;
+__stack_size = 128;
 
 INCLUDE registers.ld
-
-EXTERN (lpc_interrupt_vector)
-
-SECTIONS {
-       /*
-        * Rom contents
-        */
-
-       .interrupt : {
-               __text_start__ = .;
-               *(.interrupt)   /* Interrupt vectors */
-
-       } > rom
-
-       .text ORIGIN(rom) + 0x100 : {
-               ao_romconfig.o(.romconfig*)
-               ao_product.o(.romconfig*)
-
-               *(.text*)       /* Executable code */
-               *(.ARM.exidx* .gnu.linkonce.armexidx.*)
-               *(.rodata*)     /* Constants */
-               __text_end__ = .;
-       } > rom
-
-       /* Boot data which must live at the start of ram so that
-        * the application and bootloader share the same addresses.
-        * This must be all uninitialized data
-        */
-       .boot ORIGIN(ram) + SIZEOF(.interrupt) (NOLOAD) : {
-               __boot_start__ = .;
-               *(.boot*)
-               __boot_end__ = .;
-       } >ram
-
-       /* Data -- relocated to RAM, but written to ROM
-        */
-       .data : {
-               _start__ = .;
-               *(.data*)       /* initialized data */
-               _end__ = .;
-       } >ram AT>rom
-
-
-       .bss : {
-               __bss_start__ = .;
-               *(.bss*)
-               *(COMMON*)
-               __bss_end__ = .;
-       } >ram
-
-       PROVIDE(__stack__ = ORIGIN(ram) + LENGTH(ram));
-       PROVIDE(end = .);
-}
-
-ENTRY(start);
+INCLUDE picolibc.ld
index 028ad775d28ef579a3f44e99c9d25422f4874001..3e0157300fb2d4c86a0ac2d0631b7738d7318403 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-MEMORY {
-       rom (rx) : ORIGIN = 0x00001000, LENGTH = 28K
-       ram (!w) : ORIGIN = 0x10000000, LENGTH = 4K - 128
-       usb (!x) : ORIGIN = 0x20004000 + 2K - 256, LENGTH = 256
-       stack (!w) : ORIGIN = 0x10000000 + 4K - 128, LENGTH = 128
-}
+__flash = 0x1000;
+__flash_size = 28K;
+__ram = 0x10000000;
+__ram_size = 4k;
+__stack_size = 128;
 
 INCLUDE registers.ld
-
-EXTERN (lpc_interrupt_vector)
-
-SECTIONS {
-       /*
-        * Rom contents
-        */
-
-       .interrupt ORIGIN(ram) : AT (ORIGIN(rom)) {
-               __interrupt_start__ = .;
-               __interrupt_rom__ = ORIGIN(rom);
-               *(.interrupt)   /* Interrupt vectors */
-               __interrupt_end__ = .;
-       } > ram
-
-       .text ORIGIN(rom) + 0x100 : {
-               __text_start__ = .;
-
-               ao_romconfig.o(.romconfig*)
-               ao_product.o(.romconfig*)
-
-               *(.text*)       /* Executable code */
-               *(.rodata*)     /* Constants */
-
-       } > rom
-
-       .ARM.exidx : {
-               *(.ARM.exidx* .gnu.linkonce.armexidx.*)
-               __text_end__ = .;
-       } > rom
-
-       /* Boot data which must live at the start of ram so that
-        * the application and bootloader share the same addresses.
-        * This must be all uninitialized data
-        */
-       .boot : {
-               __boot_start__ = .;
-               *(.boot)
-               . = ALIGN(4);
-               __boot_end__ = .;
-       } >ram
-
-       /* Data -- relocated to RAM, but written to ROM
-        */
-       .data : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) {
-               _start__ = .;
-               *(.data)        /* initialized data */
-               _end__ = .;
-               __bss_start__ = .;
-       } >ram
-
-       .bss : {
-               __bss_start__ = .;
-               *(.bss)
-               *(COMMON)
-               __bss_end__ = .;
-       } >ram
-       PROVIDE(end = .);
-
-       PROVIDE(__stack__ = ORIGIN(stack) + LENGTH(stack));
-}
-
-ENTRY(start);
-
-
+INCLUDE picolibc.ld
index 93676b860ff6c9edfb79804805307f288fd67c75..c638aa22b9658846a0a4319daec94b377706b6d4 100644 (file)
@@ -53,7 +53,8 @@
  * ao_romconfig.c
  */
 
-#define AO_ROMCONFIG_SYMBOL __attribute__((section(".romconfig"))) const
+#define AO_ROMCONFIG_SYMBOL __attribute__((section(".init.1"))) const
+#define AO_USBCONFIG_SYMBOL __attribute__((section(".init.2"))) const
 
 #define ao_arch_block_interrupts()     asm("cpsid i")
 #define ao_arch_release_interrupts()   asm("cpsie i")
index 0d0bb91c75f3c5f05bff78cc4025780ebca4c054..0cb92a5299565d90026cdde42688a921af192e6d 100644 (file)
@@ -43,7 +43,7 @@ struct ao_boot {
        uint32_t        check;
 };
 
-static struct ao_boot __attribute__ ((section(".boot"))) ao_boot;
+struct ao_boot ao_boot __attribute__((section(".preserve.2")));
 
 int
 ao_boot_check_chain(void)
index a479ec6d59585835c508e6e2cff7ce8db47e0c13..bc2848c3bffa364ba6298d3a32c9439a817dc57c 100644 (file)
 #define RELOCATE_INTERRUPT     1
 #endif
 
-extern void main(void);
-extern char __stack__;
-extern char __text_start__, __text_end__;
-extern char _start__, _end__;
-extern char __bss_start__, __bss_end__;
-#if RELOCATE_INTERRUPT
-extern char __interrupt_rom__, __interrupt_start__, __interrupt_end__;
-#endif
-
 /* Interrupt functions */
 
 void lpc_halt_isr(void)
@@ -49,26 +40,6 @@ void lpc_ignore_isr(void)
 {
 }
 
-void start(void) {
-#ifdef AO_BOOT_CHAIN
-       if (ao_boot_check_chain()) {
-#ifdef AO_BOOT_PIN
-               if (ao_boot_check_pin())
-#endif
-               {
-                       ao_boot_chain(AO_BOOT_APPLICATION_BASE);
-               }
-       }
-#endif
-#if RELOCATE_INTERRUPT
-       memcpy(&__interrupt_start__, &__interrupt_rom__, &__interrupt_end__ - &__interrupt_start__);
-       lpc_scb.sysmemremap = LPC_SCB_SYSMEMREMAP_MAP_RAM << LPC_SCB_SYSMEMREMAP_MAP;
-#endif
-       memcpy(&_start__, &__text_end__, &_end__ - &_start__);
-       memset(&__bss_start__, '\0', &__bss_end__ - &__bss_start__);
-       main();
-}
-
 #define STRINGIFY(x) #x
 
 #define isr(name) \
@@ -122,10 +93,13 @@ isr(usb_wakeup)
 #define i(addr,name)   [(addr)/4] = lpc_ ## name ## _isr
 #define c(addr,value)  [(addr)/4] = (value)
 
-__attribute__ ((section(".interrupt")))
-const void *lpc_interrupt_vector[] = {
-       [0] = &__stack__,
-       [1] = start,
+extern char __stack[];
+void _start(void) __attribute__((__noreturn__));
+
+__attribute__ ((section(".init")))
+const void *const __interrupt_vector[0x30] = {
+       [0] = __stack,
+       [1] = _start,
        i(0x08, nmi),
        i(0x0c, hardfault),
        c(0x10, 0),
@@ -178,3 +152,43 @@ const void *lpc_interrupt_vector[] = {
        i(0xb8, usb_wakeup),
        i(0xbc, hardfault),
 };
+
+/*
+ * Previous versions of this code had a 256 byte interupt vector. Add
+ * some padding to make sure the other low ROM variables land at the
+ * same address
+ */
+
+__attribute__ ((section(".init.0")))
+const void *const __interrupt_pad[0x10];
+
+void main(void) __attribute__((__noreturn__));
+
+void *__interrupt_ram[sizeof(__interrupt_vector)/sizeof(__interrupt_vector[0])] __attribute((section(".preserve.1")));
+
+extern char __data_source[];
+extern char __data_start[];
+extern char __data_size[];
+extern char __bss_start[];
+extern char __bss_size[];
+
+void _start(void) {
+       memcpy(__data_start, __data_source, (uintptr_t) __data_size);
+       memset(__bss_start, '\0', (uintptr_t) __bss_size);
+
+#ifdef AO_BOOT_CHAIN
+       if (ao_boot_check_chain()) {
+#ifdef AO_BOOT_PIN
+               if (ao_boot_check_pin())
+#endif
+               {
+                       ao_boot_chain(AO_BOOT_APPLICATION_BASE);
+               }
+       }
+#endif
+#if RELOCATE_INTERRUPT
+       memcpy(__interrupt_ram, __interrupt_vector, sizeof(__interrupt_ram));
+       lpc_scb.sysmemremap = LPC_SCB_SYSMEMREMAP_MAP_RAM << LPC_SCB_SYSMEMREMAP_MAP;
+#endif
+       main();
+}
index d6763c298bc08e458f4d1e9c17f5b4b954b21d42..9e94de12b1db05e8d3c4927eb6700a65103e028c 100644 (file)
@@ -89,8 +89,6 @@ static uint8_t        *ao_usb_out_rx_buffer[2];
 static uint8_t ao_usb_out_rx_cur;
 static uint8_t ao_usb_rx_count, ao_usb_rx_pos;
 
-extern struct lpc_usb_endpoint lpc_usb_endpoint;
-
 /* Marks when we don't need to send an IN packet.
  * This happens only when the last IN packet is not full,
  * otherwise the host will expect to keep seeing packets.
index 56b852300e4dc758a76d3d6626b3cab28431bf38..82f456522c2c0482c8fb62e44a3f4227b2fb1ebc 100644 (file)
@@ -99,6 +99,7 @@ struct lpc_ioconf {
 };
 
 extern struct lpc_ioconf lpc_ioconf;
+#define lpc_ioconf (*(struct lpc_ioconf *) 0x40044000)
 
 #define LPC_IOCONF_FUNC                0
 
@@ -486,6 +487,7 @@ struct lpc_scb {
 };
 
 extern struct lpc_scb lpc_scb;
+#define lpc_scb (*(struct lpc_scb *) 0x40048000)
 
 #define LPC_SCB_SYSMEMREMAP_MAP                0
 # define LPC_SCB_SYSMEMREMAP_MAP_BOOT_LOADER   0
@@ -645,6 +647,7 @@ struct lpc_flash {
 };
 
 extern struct lpc_flash lpc_flash;
+#define lpc_flash (*(struct lpc_flash *) 0x4003c000)
 
 struct lpc_gpio_pin {
        vuint32_t       isel;           /* 0x00 */
@@ -662,6 +665,7 @@ struct lpc_gpio_pin {
 };
 
 extern struct lpc_gpio_pin lpc_gpio_pin;
+#define lpc_gpio_pin (*(struct lpc_gpio_pin *) 0x4004c000)
 
 struct lpc_gpio_group0 {
 };
@@ -706,6 +710,7 @@ struct lpc_gpio {
 };
 
 extern struct lpc_gpio lpc_gpio;
+#define lpc_gpio (*(struct lpc_gpio *) 0x50000000)
 
 struct lpc_systick {
        uint8_t         r0000[0x10];    /* 0x0000 */
@@ -717,6 +722,7 @@ struct lpc_systick {
 };
 
 extern struct lpc_systick lpc_systick;
+#define lpc_systick (*(struct lpc_systick *) 0xe000e000)
 
 #define LPC_SYSTICK_CSR_ENABLE         0
 #define LPC_SYSTICK_CSR_TICKINT                1
@@ -755,6 +761,7 @@ struct lpc_usart {
 };
 
 extern struct lpc_usart lpc_usart;
+#define lpc_usart (*(struct lpc_usart *) 0x40008000)
 
 #define LPC_USART_IER_RBRINTEN 0
 #define LPC_USART_IER_THREINTEN        1
@@ -864,6 +871,7 @@ struct lpc_usb {
 } lpc_usb;
 
 extern struct lpc_usb lpc_usb;
+#define lpc_usb (*(struct lpc_usb *) 0x40080000)
 
 #define LPC_USB_DEVCMDSTAT_DEV_ADDR    0
 #define LPC_USB_DEVCMDSTAT_DEV_ADDR_MASK       0x7f
@@ -953,12 +961,14 @@ struct lpc_usb_endpoint {
        vuint32_t               reserved_0c;
        struct lpc_usb_epn      epn[4];
 };
+#define lpc_usb_endpoint       (*(struct lpc_usb_endpoint *) 0x20004700)
 
 /* Assigned in registers.ld to point at the base
  * of USB ram
  */
 
 extern uint8_t lpc_usb_sram[];
+#define lpc_usb_sram           ((uint8_t*) 0x20004000)
 
 #define LPC_USB_EP_ACTIVE              31
 #define LPC_USB_EP_DISABLED            30
@@ -1017,6 +1027,7 @@ struct lpc_nvic {
 };
 
 extern struct lpc_nvic lpc_nvic;
+#define lpc_nvic (*(struct lpc_nvic *) 0xe000e100)
 
 static inline void
 lpc_nvic_set_enable(int irq) {
@@ -1084,6 +1095,7 @@ struct arm_scb {
 };
 
 extern struct arm_scb arm_scb;
+#define arm_scb (*(struct arm_scb *) 0xe000ed00)
 
 struct lpc_ssp {
        vuint32_t       cr0;    /* 0x00 */
@@ -1100,6 +1112,8 @@ struct lpc_ssp {
 };
 
 extern struct lpc_ssp lpc_ssp0, lpc_ssp1;
+#define lpc_ssp0 (*(struct lpc_ssp *) 0x40040000)
+#define lpc_ssp1 (*(struct lpc_ssp *) 0x40058000)
 
 #define LPC_NUM_SPI            2
 
@@ -1174,6 +1188,7 @@ struct lpc_adc {
 };
 
 extern struct lpc_adc lpc_adc;
+#define lpc_adc (*(struct lpc_adc *) 0x4001c000)
 
 #define LPC_ADC_CR_SEL         0
 #define LPC_ADC_CR_CLKDIV      8
@@ -1226,7 +1241,6 @@ struct lpc_ct16b {
 };
 
 extern struct lpc_ct16b        lpc_ct16b0, lpc_ct16b1;
-
 #define lpc_ct16b0     (*(struct lpc_ct16b *) 0x4000c000)
 #define lpc_ct16b1     (*(struct lpc_ct16b *) 0x40010000)
 
@@ -1326,6 +1340,8 @@ struct lpc_ct32b {
 };
 
 extern struct lpc_ct32b lpc_ct32b0, lpc_ct32b1;
+#define lpc_ct32b0 (*(struct lpc_ct32b *) 0x40014000)
+#define lpc_ct32b1 (*(struct lpc_ct32b *) 0x40018000)
 
 #define LPC_CT32B_TCR_CEN      0
 #define LPC_CT32B_TCR_CRST     1
index f1f57440a89c30f8ad42409c1fdaaac04fa1b096..5949ec0963f63324a5c87f6d97bd3c931ff874e6 100644 (file)
@@ -71,10 +71,10 @@ OBJ=$(SRC:.c=.o)
 
 all: $(PROG) $(HEX)
 
-LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stmf0 -Wl,-Tmicropeak.ld -n
+LDFLAGS=-nostartfiles $(CFLAGS) -L$(TOPDIR)/stmf0 -Tmicropeak.ld -n
 
 $(PROG): Makefile $(OBJ) micropeak.ld
-       $(call quiet,CC) $(LDFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+       $(call quiet,CC) $(LDFLAGS) -o $(PROG) $(OBJ) $(LIBS) -Wl,-Map=$(PROGNAME)-$(VERSION).map
 
 distclean:     clean
 
index f3fbc9f42ca016041026086b88b0e562e84574a0..a4de48543a70d2cbf24dbad2f184fd73f2cc4870 100644 (file)
@@ -167,9 +167,7 @@ ao_battery_voltage(void)
 static void
 ao_log_erase(void)
 {
-       uint32_t        pos;
-       for (pos = 0; pos < ao_storage_log_max; pos += ao_storage_block)
-               ao_storage_erase(pos);
+       ao_storage_erase(0, ao_storage_log_max);
 }
 
 uint8_t        ao_on_battery;
@@ -227,7 +225,7 @@ ao_log_list(void)
        if (ao_log_present())
                printf ("flight %d start %x end %x\n",
                        1,
-                       0, MAX_LOG_OFFSET >> 8);
+                       0, (unsigned) (MAX_LOG_OFFSET >> 8));
        printf ("done\n");
 }
 
index a73d4c1d3dbff1b1607550e964c985908583fa0c..b4e06a877708bd7cbdbe446b4262a5b1d5265856 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-MEMORY {
-       rom (rx) :   ORIGIN = 0x08001000, LENGTH = 20K
-       flash(rx) :  ORIGIN = 0x08006000, LENGTH = 8K
-       ram (!w) :   ORIGIN = 0x20000000, LENGTH = 6k - 512
-       stack (!w) : ORIGIN = 0x20000000 + 6k - 512, LENGTH = 512
-}
+__flash = 0x08001000;
+__flash_size = 22K;
+__flash__ = __flash + __flash_size;
+__flash_end__ = __flash__ + 6K;
+__ram = 0x20000000;
+__ram_size = 6K;
+__stack_size = 512;
 
 INCLUDE registers.ld
-
-EXTERN (stm_interrupt_vector)
-
-SECTIONS {
-       /*
-        * Rom contents
-        */
-
-       .interrupt ORIGIN(ram) : AT (ORIGIN(rom)) {
-               __interrupt_start__ = .;
-               __interrupt_rom__ = ORIGIN(rom);
-               *(.interrupt)   /* Interrupt vectors */
-               __interrupt_end__ = .;
-       } > ram
-
-       .text ORIGIN(rom) + 0x100 : {
-               __text_start__ = .;
-
-               /* Ick. What I want is to specify the
-                * addresses of some global constants so
-                * that I can find them across versions
-                * of the application. I can't figure out
-                * how to make gnu ld do that, so instead
-                * we just load the two files that include
-                * these defines in the right order here and
-                * expect things to 'just work'. Don't change
-                * the contents of those files, ok?
-                */
-               ao_romconfig.o(.romconfig*)
-               ao_product.o(.romconfig*)
-
-               *(.text*)       /* Executable code */
-       } > rom
-
-       .ARM.exidx : {
-               *(.ARM.exidx* .gnu.linkonce.armexidx.*)
-       } > rom
-
-       .rodata : {
-               *(.rodata*)     /* Constants */
-       } > rom
-
-       __text_end__ = .;
-
-       /* Boot data which must live at the start of ram so that
-        * the application and bootloader share the same addresses.
-        * This must be all uninitialized data
-        */
-       .boot (NOLOAD) : {
-               __boot_start__ = .;
-               *(.boot)
-               . = ALIGN(4);
-               __boot_end__ = .;
-       } >ram
-
-       /* Functions placed in RAM (required for flashing)
-        *
-        * Align to 8 bytes as that's what the ARM likes text
-        * segment alignments to be, and if we don't, then
-        * we end up with a mismatch between the location in
-        * ROM and the desired location in RAM. I don't
-        * entirely understand this, but at least this appears
-        * to work...
-        */
-
-       .textram BLOCK(8): {
-               _start__ = .;
-               *(.ramtext)
-       } >ram AT>rom
-
-       /* Data -- relocated to RAM, but written to ROM,
-        * also aligned to 8 bytes to agree with textram
-        */
-       .data BLOCK(8): {
-               *(.data)        /* initialized data */
-               _end__ = .;
-       } >ram AT>rom
-
-       .bss : {
-               __bss_start__ = .;
-               *(.bss)
-               *(COMMON)
-               . = ALIGN(4);
-               __bss_end__ = .;
-       } >ram
-
-       PROVIDE(end = .);
-
-       PROVIDE(__flash__ = ORIGIN(flash));
-       PROVIDE(__flash_end__ = ORIGIN(flash) + LENGTH(flash));
-
-       PROVIDE(__stack__ = ORIGIN(stack) + LENGTH(stack));
-}
-
-ENTRY(start);
-
-
+INCLUDE picolibc.ld
index d3edbe9fb2168ed9eefd93ace5795bdd439382b6..20b3ace79be0df292ec4e771f6bc39abab6b9443 100644 (file)
@@ -87,7 +87,7 @@ SECTIONS {
        .textram BLOCK(8): {
                _start__ = .;
                __text_ram_start__ = .;
-               *(.ramtext)
+               *(.srodata)
                __text_ram_end = .;
        } >ram AT>rom
 
index 08a4b1773e00be742ac16856a883402d7e4f16b3..4a3864318eb342c85d849fd17dd9b991f385f15e 100644 (file)
@@ -35,13 +35,13 @@ IDPRODUCT=0x000a
 
 CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS)
 
-LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stm -Wl,-Taltos-loader.ld -n
+LDFLAGS=-nostartfiles $(CFLAGS) -L$(TOPDIR)/stm -Taltos-loader.ld -n
 
 PROGNAME=altos-flash
 PROG=$(HARDWARE)-$(PROGNAME)-$(VERSION).elf
 
 $(PROG): Makefile $(OBJ) altos-loader.ld
-       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+       $(call quiet,CC) $(LDFLAGS) -o $(PROG) $(OBJ) $(LIBS)
 
 $(OBJ): $(INC)
 
index cce28f009f86f648d907489ff483e3ffe522206a..f3fd9de65ee1f8916b56e3b346bd48540b6aef0a 100644 (file)
@@ -7,7 +7,7 @@ include $(TOPDIR)/Makefile.defs
 vpath % $(TOPDIR)/stm:$(AO_VPATH)
 
 CC=$(ARM_CC)
-LIBS=-L$(NEWLIB_NANO)/arm-none-eabi/lib/thumb/v7-m -lm -lc -lgcc
+LIBS=-lm
 
 STM_CFLAGS=-mlittle-endian -mcpu=cortex-m3 -mthumb \
-       -I$(TOPDIR)/stm $(AO_CFLAGS) $(NEWLIB_CFLAGS)
+       -I$(TOPDIR)/stm $(AO_CFLAGS) $(PICOLIBC_CFLAGS)
index 26ba582404fa4cd99b74701e71487970f99788ea..d6cbe4d4921a3be1d6257146860a16e63206e3be 100644 (file)
@@ -4,4 +4,4 @@ endif
 
 include $(TOPDIR)/stm/Makefile-stm.defs
 
-LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stm -Wl,-Taltos.ld -n
+LDFLAGS=-nostartfiles $(CFLAGS) -L$(TOPDIR)/stm -Taltos.ld -n
index 1ebbc7a2afcb15b30d2c24fe692547edec4e1073..5ef09cd237140791cb9407a3db9d3190956781cc 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-MEMORY {
-       rom : ORIGIN = 0x08000000, LENGTH = 4K
-       ram : ORIGIN = 0x20000000, LENGTH = 16K
-}
+__flash = 0x08000000;
+__flash_size = 4K;
+__ram =   0x20000000;
+__ram_size = 16K;
+__stack_size = 512;
 
 INCLUDE registers.ld
-
-EXTERN (stm_interrupt_vector)
-
-SECTIONS {
-       /*
-        * Rom contents
-        */
-
-       .text : {
-               __text_start__ = .;
-               *(.interrupt)   /* Interrupt vectors */
-
-               . = ORIGIN(rom) + 0x100;
-
-               ao_romconfig.o(.romconfig*)
-               ao_product.o(.romconfig*)
-               *(.text*)       /* Executable code */
-               *(.ARM.exidx* .gnu.linkonce.armexidx.*)
-               *(.rodata*)     /* Constants */
-       } > rom
-       __text_end__ = .;
-
-       /* Boot data which must live at the start of ram so that
-        * the application and bootloader share the same addresses.
-        * This must be all uninitialized data
-        */
-       .boot (NOLOAD) : {
-               __boot_start__ = .;
-               *(.boot)
-               __boot_end__ = .;
-       } >ram
-
-       /* Functions placed in RAM (required for flashing)
-        *
-        * Align to 8 bytes as that's what the ARM likes text
-        * segment alignments to be, and if we don't, then
-        * we end up with a mismatch between the location in
-        * ROM and the desired location in RAM. I don't
-        * entirely understand this, but at least this appears
-        * to work...
-        */
-
-       .textram BLOCK(8): {
-               _start__ = .;
-               __text_ram_start__ = .;
-               *(.ramtext)
-               __text_ram_end = .;
-       } >ram AT>rom
-
-       /* Data -- relocated to RAM, but written to ROM
-        * Also aligned to 8 bytes to agree with textram
-        */
-       .data BLOCK(8): {
-               *(.data)        /* initialized data */
-               _end__ = .;
-       } >ram AT>rom
-
-
-       .bss : {
-               __bss_start__ = .;
-               *(.bss)
-               *(COMMON)
-               __bss_end__ = .;
-       } >ram
-
-       PROVIDE(__stack__ = ORIGIN(ram) + LENGTH(ram));
-       PROVIDE(end = .);
-}
-
-ENTRY(start);
-
-
+INCLUDE picolibc.ld
index e352ed36601d85409801dc8c605a8a49a07536e7..9638bb6724cd5f00ee62ab79a65ab38008119026 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-MEMORY {
-       rom (rx) : ORIGIN = 0x08001000, LENGTH = 124K
-       ram (!w) : ORIGIN = 0x20000000, LENGTH = 15872
-       stack (!w) : ORIGIN = 0x20003e00, LENGTH = 512
-}
+__flash = 0x08001000;
+__flash_size = 124K;
+__ram = 0x20000000;
+__ram_size = 16k;
+__stack_size = 512;
 
 INCLUDE registers.ld
-
-EXTERN (stm_interrupt_vector)
-
-SECTIONS {
-       /*
-        * Rom contents
-        */
-
-       .text ORIGIN(rom) : {
-               __text_start__ = .;
-               *(.interrupt)   /* Interrupt vectors */
-
-               . = ORIGIN(rom) + 0x100;
-
-
-               /* Ick. What I want is to specify the
-                * addresses of some global constants so
-                * that I can find them across versions
-                * of the application. I can't figure out
-                * how to make gnu ld do that, so instead
-                * we just load the two files that include
-                * these defines in the right order here and
-                * expect things to 'just work'. Don't change
-                * the contents of those files, ok?
-                */
-               ao_romconfig.o(.romconfig*)
-               ao_product.o(.romconfig*)
-               *(.text*)       /* Executable code */
-               *(.rodata*)     /* Constants */
-
-       } > rom
-
-       .ARM.exidx : {
-               *(.ARM.exidx* .gnu.linkonce.armexidx.*)
-       } > rom
-       __text_end__ = .;
-
-       /* Boot data which must live at the start of ram so that
-        * the application and bootloader share the same addresses.
-        * This must be all uninitialized data
-        */
-       .boot (NOLOAD) : {
-               __boot_start__ = .;
-               *(.boot)
-               . = ALIGN(4);
-               __boot_end__ = .;
-       } >ram
-
-       /* Data -- relocated to RAM, but written to ROM
-        */
-       .data : {
-               _start__ = .;
-               *(.data)        /* initialized data */
-               . = ALIGN(4);
-               _end__ = .;
-       } >ram AT>rom
-
-       .bss : {
-               __bss_start__ = .;
-               *(.bss)
-               *(COMMON)
-               . = ALIGN(4);
-               __bss_end__ = .;
-       } >ram
-
-       PROVIDE(end = .);
-
-       PROVIDE(__stack__ = ORIGIN(stack) + LENGTH(stack));
-}
-
-ENTRY(start);
-
-
+INCLUDE picolibc.ld
index e83b6bd2cfbf3e1dac4a7c2816703fcf1214ba08..e3094c6abec04fdcc4a700d5d216639995beb7b2 100644 (file)
@@ -51,7 +51,8 @@
  * ao_romconfig.c
  */
 
-#define AO_ROMCONFIG_SYMBOL __attribute__((section(".romconfig"))) const
+#define AO_ROMCONFIG_SYMBOL __attribute__((section(".init.1"))) const
+#define AO_USBCONFIG_SYMBOL __attribute__((section(".init.2"))) const
 
 /*
  * For now, we're running at a weird frequency
index 488af1e1b8dffc2261e303aa3b3981b3a69f29f7..d91afdabc7fcbfb949ac007d72d0b8e330339fdf 100644 (file)
@@ -43,8 +43,8 @@ struct ao_boot {
        uint32_t        check;
 };
 
-static struct ao_boot __attribute__ ((section(".boot"))) ao_boot;
-       
+struct ao_boot ao_boot __attribute__((section(".preserve.2")));
+
 int
 ao_boot_check_chain(void)
 {
index d3e3338d9c94d7e1e961b29d7606b64193659a79..db4d6a49f0b5801b08ea1cb8f555cbe7c1960d3e 100644 (file)
@@ -20,7 +20,7 @@
 #include <ao_eeprom.h>
 
 /* Total bytes of available storage */
-const ao_pos_t ao_eeprom_total = 4096;
+#define ao_eeprom_total 4096
 
 /* Location of eeprom in address space */
 #define stm_eeprom     ((uint8_t *) 0x08080000)
index 38618bbe53165f64138c0a3a39fa81c2740cbf20..77296c322d2f11906c2f02ae966da7e153b0a54c 100644 (file)
@@ -70,7 +70,7 @@ ao_flash_wait_bsy(void)
                ;
 }
 
-static void __attribute__ ((section(".ramtext"),noinline))
+static void __attribute__ ((section(".sdata2.flash"), noinline))
 _ao_flash_erase_page(uint32_t *page)
 {
        stm_flash.pecr |= (1 << STM_FLASH_PECR_ERASE) | (1 << STM_FLASH_PECR_PROG);
@@ -93,7 +93,7 @@ ao_flash_erase_page(uint32_t *page)
        ao_arch_release_interrupts();
 }
 
-static void __attribute__ ((section(".ramtext"), noinline))
+static void __attribute__ ((section(".sdata2.flash"), noinline))
 _ao_flash_half_page(uint32_t *dst, uint32_t *src)
 {
        uint8_t         i;
index 1d563532b755cf7f1144400803ef0a034536febb..9a0591876348892e85dfddb6efcac07b8e68dc01 100644 (file)
 #include <ao_boot.h>
 
 extern void main(void);
-extern char __stack__;
-extern char __text_start__, __text_end__;
-extern char _start__, _end__;
-extern char __bss_start__, __bss_end__;
 
 /* Interrupt functions */
 
@@ -38,8 +34,6 @@ void stm_ignore_isr(void)
 {
 }
 
-const void *stm_interrupt_vector[];
-
 uint32_t
 stm_flash_size(void) {
        uint16_t        dev_id = stm_dev_id();
@@ -72,25 +66,6 @@ stm_flash_size(void) {
        return (uint32_t) kbytes * 1024;
 }
 
-void start(void)
-{
-#ifdef AO_BOOT_CHAIN
-       if (ao_boot_check_chain()) {
-#ifdef AO_BOOT_PIN
-               if (ao_boot_check_pin())
-#endif
-               {
-                       ao_boot_chain(AO_BOOT_APPLICATION_BASE);
-               }
-       }
-#endif
-       /* Set interrupt vector table offset */
-       stm_nvic.vto = (uint32_t) &stm_interrupt_vector;
-       memcpy(&_start__, &__text_end__, &_end__ - &_start__);
-       memset(&__bss_start__, '\0', &__bss_end__ - &__bss_start__);
-       main();
-}
-
 #define STRINGIFY(x) #x
 
 #define isr(name) \
@@ -158,10 +133,18 @@ isr(tim7)
 
 #define i(addr,name)   [(addr)/4] = stm_ ## name ## _isr
 
-__attribute__ ((section(".interrupt")))
-const void *stm_interrupt_vector[] = {
-       [0] = &__stack__,
-       [1] = start,
+extern char __stack[];
+void _start(void) __attribute__((__noreturn__));
+void main(void) __attribute__((__noreturn__));
+
+/* This must be exactly 256 bytes long so that the configuration data
+ * gets loaded at the right place
+ */
+
+__attribute__ ((section(".init")))
+const void * const __interrupt_vector[64] = {
+       [0] = &__stack,
+       [1] = _start,
        i(0x08, nmi),
        i(0x0c, hardfault),
        i(0x10, memmanage),
@@ -217,3 +200,28 @@ const void *stm_interrupt_vector[] = {
        i(0xec, tim6),
        i(0xf0, tim7),
 };
+
+extern char __data_source[];
+extern char __data_start[];
+extern char __data_size[];
+extern char __bss_start[];
+extern char __bss_size[];
+
+void _start(void) {
+       memcpy(__data_start, __data_source, (uintptr_t) __data_size);
+       memset(__bss_start, '\0', (uintptr_t) __bss_size);
+
+#ifdef AO_BOOT_CHAIN
+       if (ao_boot_check_chain()) {
+#ifdef AO_BOOT_PIN
+               if (ao_boot_check_pin())
+#endif
+               {
+                       ao_boot_chain(AO_BOOT_APPLICATION_BASE);
+               }
+       }
+#endif
+       /* Set interrupt vector table offset */
+       stm_nvic.vto = (uint32_t) &__interrupt_vector;
+       main();
+}
index 5d6e1f4b14006ff037e2c988f564681c05cf4ab1..9a46987fa33969bb1b2ab3cc7bac742e02581da2 100644 (file)
@@ -68,7 +68,7 @@ SECTIONS {
        .textram BLOCK(8): {
                _start__ = .;
                __text_ram_start__ = .;
-               *(.ramtext)
+               *(.srodata)
                __text_ram_end = .;
        } >ram AT>rom
 
index b6e44990b5a0f1fbd88ff98934d10855a48cb39b..bbb04e77c1292669b8210b6297b903321dcf6998 100644 (file)
@@ -35,7 +35,7 @@ IDPRODUCT=0x000a
 
 CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS)
 
-LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stmf0 -Wl,-Taltos-loader.ld
+LDFLAGS=-nostartfiles $(CFLAGS) -L$(TOPDIR)/stmf0 -Taltos-loader.ld
 
 PROGNAME=altos-flash
 PROG=$(HARDWARE)-$(PROGNAME)-$(VERSION).elf
@@ -47,7 +47,7 @@ FLASH_ADDR=0x08000000
 all: $(PROG) $(BIN)
 
 $(PROG): Makefile $(OBJ) altos-loader.ld
-       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+       $(call quiet,CC) $(LDFLAGS) -o $(PROG) $(OBJ) $(LIBS)
 
 $(BIN): $(PROG)
        $(MAKEBIN) --output=$@ --base=$(FLASH_ADDR) $(PROG)
index 5a883adf1345bdd72593ca23f50321ba5068f4b8..536605603e2f403a131238ff54c51acba2c4f168 100644 (file)
@@ -2,6 +2,10 @@ ifndef TOPDIR
 TOPDIR=..
 endif
 
+# Disable floating-point support in printf to save space
+
+PICOLIBC_PRINTF_CFLAGS = -DPICOLIBC_INTEGER_PRINTF_SCANF
+
 include $(TOPDIR)/Makefile.defs
 
 vpath % $(TOPDIR)/stmf0:$(AO_VPATH)
@@ -9,6 +13,6 @@ vpath % $(TOPDIR)/stmf0:$(AO_VPATH)
 CC=$(ARM_CC)
 
 STMF0_CFLAGS=-mlittle-endian -mcpu=cortex-m0 -mthumb\
-       -I$(TOPDIR)/stmf0 $(AO_CFLAGS) $(NEWLIB_CFLAGS)
+       -I$(TOPDIR)/stmf0 $(AO_CFLAGS) $(PICOLIBC_CFLAGS)
 
-LIBS=-L$(NEWLIB_NANO)/arm-none-eabi/lib/thumb/v6-m -lc -lm -lgcc
+LIBS=-lm
index 2baba4f2b3536360cb03933929fd825c62c9d425..fb62f095e6e63d99eaba4c37296dc79ef12363b9 100644 (file)
@@ -4,7 +4,7 @@ endif
 
 include $(TOPDIR)/stmf0/Makefile-stmf0.defs
 
-LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stmf0 -Wl,-Taltos.ld -n
+LDFLAGS=-nostartfiles $(CFLAGS) -L$(TOPDIR)/stmf0 -Taltos.ld -n
 
 LOADER=flash-loader/$(PROGNAME)-altos-flash-$(VERSION).elf
 MAKEBIN=$(TOPDIR)/../ao-tools/ao-makebin/ao-makebin
index 4d9b81ae0ad16d0121b8d79ee75638c994b6b618..4ce0b7043e1d34304917c7a5cc4433cbedeb7b85 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-MEMORY {
-       rom : ORIGIN = 0x08000000, LENGTH = 4K
-       ram : ORIGIN = 0x20000000, LENGTH = 6K
-}
+__flash = 0x08000000;
+__flash_size = 4K;
+__ram = 0x20000000;
+__ram_size = 6k;
+__stack_size = 128;
 
 INCLUDE registers.ld
-
-EXTERN (stm_interrupt_vector)
-
-SECTIONS {
-       /*
-        * Rom contents
-        */
-
-       .interrupt : {
-               __text_start__ = .;
-               *(.interrupt)   /* Interrupt vectors */
-       } > rom
-
-       .text ORIGIN(rom) + 0x100 : {
-               ao_romconfig.o(.romconfig*)
-               ao_product.o(.romconfig*)
-
-               *(.text*)       /* Executable code */
-               *(.ARM.exidx* .gnu.linkonce.armexidx.*)
-               *(.rodata*)     /* Constants */
-       } > rom
-       __text_end__ = .;
-
-       /* Boot data which must live at the start of ram so that
-        * the application and bootloader share the same addresses.
-        * This must be all uninitialized data
-        */
-       .boot ORIGIN(ram) + SIZEOF(.interrupt) (NOLOAD) : {
-               __boot_start__ = .;
-               *(.boot)
-               __boot_end__ = .;
-       } >ram
-
-       /* Functions placed in RAM (required for flashing)
-        *
-        * Align to 8 bytes as that's what the ARM likes text
-        * segment alignments to be, and if we don't, then
-        * we end up with a mismatch between the location in
-        * ROM and the desired location in RAM. I don't
-        * entirely understand this, but at least this appears
-        * to work...
-        */
-
-       .textram BLOCK(8): {
-               _start__ = .;
-               __text_ram_start__ = .;
-               *(.ramtext)
-               __text_ram_end = .;
-       } >ram AT>rom
-
-       /* Data -- relocated to RAM, but written to ROM.
-        * also aligned to 8 bytes in case textram is empty
-        */
-       .data BLOCK(8): {
-               *(.data)        /* initialized data */
-               _end__ = .;
-       } >ram AT>rom
-
-
-       .bss : {
-               __bss_start__ = .;
-               *(.bss)
-               *(COMMON)
-               __bss_end__ = .;
-       } >ram
-
-       PROVIDE(__stack__ = ORIGIN(ram) + LENGTH(ram));
-       PROVIDE(end = .);
-}
-
-ENTRY(start);
-
-
+INCLUDE picolibc.ld
index 64e1d00cf0ab5b1aadebebdd389914a1d8d63c5e..019565cf9f82016b4ec0c7991b712bf32f38557a 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-MEMORY {
-       rom (rx) :   ORIGIN = 0x08001000, LENGTH = 28K
-       ram (!w) :   ORIGIN = 0x20000000, LENGTH = 6k - 128
-       stack (!w) : ORIGIN = 0x20000000 + 6k - 128, LENGTH = 128
-}
+__flash = 0x08001000;
+__flash_size = 28K;
+__ram = 0x20000000;
+__ram_size = 6k;
+__stack_size = 128;
 
 INCLUDE registers.ld
-
-EXTERN (stm_interrupt_vector)
-
-SECTIONS {
-       /*
-        * Rom contents
-        */
-
-       .interrupt ORIGIN(ram) : AT (ORIGIN(rom)) {
-               __interrupt_start__ = .;
-               __interrupt_rom__ = ORIGIN(rom);
-               *(.interrupt)   /* Interrupt vectors */
-               __interrupt_end__ = .;
-       } > ram
-
-       .text ORIGIN(rom) + 0x100 : {
-               __text_start__ = .;
-
-               /* Ick. What I want is to specify the
-                * addresses of some global constants so
-                * that I can find them across versions
-                * of the application. I can't figure out
-                * how to make gnu ld do that, so instead
-                * we just load the two files that include
-                * these defines in the right order here and
-                * expect things to 'just work'. Don't change
-                * the contents of those files, ok?
-                */
-               ao_romconfig.o(.romconfig*)
-               ao_product.o(.romconfig*)
-
-               *(.text*)       /* Executable code */
-       } > rom
-
-       .ARM.exidx : {
-               *(.ARM.exidx* .gnu.linkonce.armexidx.*)
-       } > rom
-
-       .rodata : {
-               *(.rodata*)     /* Constants */
-       } > rom
-
-       __text_end__ = .;
-
-       /* Boot data which must live at the start of ram so that
-        * the application and bootloader share the same addresses.
-        * This must be all uninitialized data
-        */
-       .boot (NOLOAD) : {
-               __boot_start__ = .;
-               *(.boot)
-               . = ALIGN(4);
-               __boot_end__ = .;
-       } >ram
-
-       /* Data -- relocated to RAM, but written to ROM
-        */
-       .data : {
-               _start__ = .;
-               *(.data)        /* initialized data */
-               . = ALIGN(4);
-               _end__ = .;
-       } >ram AT>rom
-
-       .bss : {
-               __bss_start__ = .;
-               *(.bss)
-               *(COMMON)
-               . = ALIGN(4);
-               __bss_end__ = .;
-       } >ram
-
-       PROVIDE(end = .);
-
-       PROVIDE(__stack__ = ORIGIN(stack) + LENGTH(stack));
-}
-
-ENTRY(start);
-
-
+INCLUDE picolibc.ld
index d70a9110e91fa02ac481ced1e928fa1868b0ca6d..47ac72787aa1801bbd3f56dc891efa0c8402ce44 100644 (file)
@@ -53,7 +53,8 @@
  * ao_romconfig.c
  */
 
-#define AO_ROMCONFIG_SYMBOL __attribute__((section(".romconfig"))) const
+#define AO_ROMCONFIG_SYMBOL __attribute__((section(".init.1"))) const
+#define AO_USBCONFIG_SYMBOL __attribute__((section(".init.2"))) const
 
 extern const uint16_t ao_romconfig_version;
 extern const uint16_t ao_romconfig_check;
index 8f850a0a6d98d7ee1b0484f746dd8f6453e19d43..d91afdabc7fcbfb949ac007d72d0b8e330339fdf 100644 (file)
@@ -43,7 +43,7 @@ struct ao_boot {
        uint32_t        check;
 };
 
-static struct ao_boot __attribute__ ((section(".boot"))) ao_boot;
+struct ao_boot ao_boot __attribute__((section(".preserve.2")));
 
 int
 ao_boot_check_chain(void)
index 2d57eea72701eefeae6e61ad0a6fc0395cf2dac7..896d536ba0c1612e7fe341b4a4da0d399aa445ba 100644 (file)
@@ -52,7 +52,7 @@ ao_flash_lock(void)
 
 #define ao_flash_wait_bsy() do { while (stm_flash.sr & (1 << STM_FLASH_SR_BSY)); } while (0)
 
-static void __attribute__ ((section(".ramtext"),noinline))
+static void __attribute__ ((section(".sdata2.flash"), noinline))
 _ao_flash_erase_page(uint32_t *page)
 {
        stm_flash.cr |= (1 << STM_FLASH_CR_PER);
@@ -103,7 +103,7 @@ ao_flash_erase_page(uint32_t *page)
        ao_arch_release_interrupts();
 }
 
-static void __attribute__ ((section(".ramtext"), noinline))
+static void __attribute__ ((section(".sdata2.flash"), noinline))
 _ao_flash_page(uint16_t *dst, uint16_t *src)
 {
        uint8_t         i;
index 1ee6e720091be2e277fca3b26536fd559caea35d..3d7dc7a82c653e2eff6be3327b4edd252ae6ad88 100644 (file)
 #endif
 #endif
 
-extern void main(void);
-extern char __stack__;
-extern char __text_start__, __text_end__;
-extern char _start__, _end__;
-extern char __bss_start__, __bss_end__;
-#if RELOCATE_INTERRUPT
-extern char __interrupt_rom__, __interrupt_start__, __interrupt_end__;
-#endif
-
 /* Interrupt functions */
 
 void stm_halt_isr(void)
@@ -52,8 +43,6 @@ void stm_ignore_isr(void)
 {
 }
 
-const void *stm_interrupt_vector[];
-
 uint32_t
 stm_flash_size(void) {
        uint16_t        dev_id = stm_dev_id();
@@ -67,35 +56,6 @@ stm_flash_size(void) {
        return (uint32_t) kbytes * 1024;
 }
 
-void start(void)
-{
-#if AO_BOOT_CHAIN
-       if (ao_boot_check_chain()) {
-#if AO_BOOT_PIN
-               if (ao_boot_check_pin())
-#endif
-               {
-                       ao_boot_chain(AO_BOOT_APPLICATION_BASE);
-               }
-       }
-#endif
-       /* Turn on syscfg */
-       stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SYSCFGCOMPEN);
-
-#if RELOCATE_INTERRUPT
-       memcpy(&__interrupt_start__, &__interrupt_rom__, &__interrupt_end__ - &__interrupt_start__);
-       stm_syscfg.cfgr1 = (stm_syscfg.cfgr1 & ~(STM_SYSCFG_CFGR1_MEM_MODE_MASK << STM_SYSCFG_CFGR1_MEM_MODE)) |
-               (STM_SYSCFG_CFGR1_MEM_MODE_SRAM << STM_SYSCFG_CFGR1_MEM_MODE);
-#else
-       /* Switch to Main Flash mode (DFU loader leaves us in System mode) */
-       stm_syscfg.cfgr1 = (stm_syscfg.cfgr1 & ~(STM_SYSCFG_CFGR1_MEM_MODE_MASK << STM_SYSCFG_CFGR1_MEM_MODE)) |
-               (STM_SYSCFG_CFGR1_MEM_MODE_MAIN_FLASH << STM_SYSCFG_CFGR1_MEM_MODE);
-#endif
-       memcpy(&_start__, &__text_end__, &_end__ - &_start__);
-       memset(&__bss_start__, '\0', &__bss_end__ - &__bss_start__);
-       main();
-}
-
 #define STRINGIFY(x) #x
 
 #define isr(name) \
@@ -153,10 +113,14 @@ isr(usb)
 
 #define i(addr,name)   [(addr)/4] = stm_ ## name ## _isr
 
-__attribute__ ((section(".interrupt")))
-const void *stm_interrupt_vector[] = {
-       [0] = &__stack__,
-       [1] = start,
+extern char __stack[];
+void _start(void) __attribute__((__noreturn__));
+void main(void) __attribute__((__noreturn__));
+
+__attribute__ ((section(".init")))
+const void * const __interrupt_vector[0x30] = {
+       [0] = __stack,
+       [1] = _start,
        i(0x08, nmi),
        i(0x0c, hardfault),
        i(0x2c, svc),
@@ -196,3 +160,47 @@ const void *stm_interrupt_vector[] = {
        i(0xb8, cec_can),
        i(0xbc, usb),
 };
+
+/*
+ * Previous versions of this code had a 256 byte interupt vector. Add
+ * some padding to make sure the other low ROM variables land at the
+ * same address
+ */
+
+__attribute__ ((section(".init.0")))
+const void *const __interrupt_pad[0x10];
+
+void *__interrupt_ram[sizeof(__interrupt_vector)/sizeof(__interrupt_vector[0])] __attribute__((section(".preserve.1")));
+
+extern char __data_source[];
+extern char __data_start[];
+extern char __data_size[];
+extern char __bss_start[];
+extern char __bss_size[];
+
+void _start(void)
+{
+       memcpy(__data_start, __data_source, (uintptr_t) __data_size);
+       memset(__bss_start, '\0', (uintptr_t) __bss_size);
+
+#if AO_BOOT_CHAIN
+       if (ao_boot_check_chain()) {
+#if AO_BOOT_PIN
+               ao_boot_check_pin();
+#endif
+       }
+#endif
+       /* Turn on syscfg */
+       stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SYSCFGCOMPEN);
+
+#if RELOCATE_INTERRUPT
+       memcpy(__interrupt_ram, __interrupt_vector, sizeof(__interrupt_ram));
+       stm_syscfg.cfgr1 = (stm_syscfg.cfgr1 & ~(STM_SYSCFG_CFGR1_MEM_MODE_MASK << STM_SYSCFG_CFGR1_MEM_MODE)) |
+               (STM_SYSCFG_CFGR1_MEM_MODE_SRAM << STM_SYSCFG_CFGR1_MEM_MODE);
+#else
+       /* Switch to Main Flash mode (DFU loader leaves us in System mode) */
+       stm_syscfg.cfgr1 = (stm_syscfg.cfgr1 & ~(STM_SYSCFG_CFGR1_MEM_MODE_MASK << STM_SYSCFG_CFGR1_MEM_MODE)) |
+               (STM_SYSCFG_CFGR1_MEM_MODE_MAIN_FLASH << STM_SYSCFG_CFGR1_MEM_MODE);
+#endif
+       main();
+}
index c6f1defe8e67b3f8efe97a3424804e9eac470126..4f5a12ef01d757a12c4e290bcb52c522c20d8438 100644 (file)
@@ -70,7 +70,7 @@ stm_flash_page_size(void)
 
 #define ao_flash_wait_bsy() do { while (stm_flash.sr & (1 << STM_FLASH_SR_BSY)); } while (0)
 
-static void __attribute__ ((section(".ramtext"),noinline))
+static void __attribute__ ((section(".sdata2.flash"), noinline))
 _ao_flash_erase_page(uint16_t *page)
 {
        stm_flash.cr |= (1 << STM_FLASH_CR_PER);
@@ -86,7 +86,8 @@ _ao_flash_erase_page(uint16_t *page)
 
 #define _ao_flash_addr(pos)    ((uint16_t *) (void *) ((uint8_t *) __flash__ + (pos)))
 
-static void __attribute ((section(".ramtext"), noinline)) _ao_flash_byte(uint32_t pos, uint8_t b)
+static void __attribute__ ((section(".sdata2.flash"), noinline))
+_ao_flash_byte(uint32_t pos, uint8_t b)
 {
        uint16_t        v;
        uint16_t        *a = _ao_flash_addr(pos & ~1);
@@ -99,7 +100,7 @@ static void __attribute ((section(".ramtext"), noinline)) _ao_flash_byte(uint32_
        ao_flash_wait_bsy();
 }
 
-static void __attribute__ ((section(".ramtext"), noinline))
+static void __attribute__ ((section(".sdata2.flash"), noinline))
 _ao_flash_write(uint32_t pos, void *sv, uint16_t len)
 {
        uint8_t         *s = sv;
@@ -127,24 +128,9 @@ _ao_flash_write(uint32_t pos, void *sv, uint16_t len)
        stm_flash.cr &= ~(1 << STM_FLASH_CR_PG);
 }
 
-static bool
-ao_storage_is_erased(uint32_t pos)
-{
-       uint16_t *flash = _ao_flash_addr(pos);
-       uint32_t i = ao_storage_block >> 1;
-
-       while (i--)
-               if (*flash++ != 0xffff)
-                       return false;
-       return true;
-}
-
 uint8_t
-ao_storage_erase(uint32_t pos)
+ao_storage_device_erase(uint32_t pos)
 {
-       if (ao_storage_is_erased(pos))
-               return 1;
-
        ao_arch_block_interrupts();
        ao_flash_unlock();
 
@@ -196,8 +182,8 @@ ao_storage_setup(void)
 void
 ao_storage_device_info(void) 
 {
-       printf ("Using internal flash, page %d bytes, total %d bytes\n",
-               ao_storage_block, ao_storage_total);
+       printf ("Using internal flash, page %ld bytes, total %ld bytes\n",
+               (long) ao_storage_block, (long) ao_storage_total);
 }
 
 void
index af273a5d8046907e05219b9a4a355b200bec2fdc..85f06de46a92ca8ad638b91ad8701b54f67e6b78 100644 (file)
@@ -65,10 +65,6 @@ PRODUCT=TeleFireOne-v2.0
 PRODUCT_DEF=-DTELEFIREONE_V_2_0
 IDPRODUCT=0x000f
 
-# Include floating-point enabled printf
-
-NEWLIB_PRINTF_CFLAGS = 
-
 CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF)
 
 PROGNAME = telefireone-v2.0
index fc1b1f28c8de9396a72e1fd38ea69bd9bb95b23b..aa644298a2f11cca28c35d339e9492b87ce64c3a 100644 (file)
@@ -71,7 +71,7 @@ OBJ=$(SRC:.c=.o)
 all: $(PROG) $(HEX)
 
 $(PROG): Makefile $(OBJ) altos.ld
-       $(call quiet,CC) $(LDFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+       $(call quiet,CC) $(LDFLAGS) -o $(PROG) $(OBJ) $(LIBS) -Wl,-Map=$(PROGNAME)-$(VERSION).map
 
 $(OBJ): $(INC)
 
index 7ce2847154b4483e433f4c26504af8dcad00af3d..24410e0d375403c771b8b43c321b61404d133494 100644 (file)
@@ -73,7 +73,7 @@ OBJ=$(SRC:.c=.o)
 all: $(PROG) $(HEX)
 
 $(PROG): Makefile $(OBJ) altos.ld
-       $(call quiet,CC) $(LDFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+       $(call quiet,CC) $(LDFLAGS) -o $(PROG) $(OBJ) $(LIBS) -Wl,-Map=$(PROGNAME)-$(VERSION).map
 
 $(OBJ): $(INC)
 
index 1238d72f01dae3316ab352d00d47ad558fe12fce..a04ceb9fc89efdd936cf059ea2d72972ee3c40c2 100644 (file)
@@ -156,7 +156,7 @@ ao_lco_drag_monitor(void)
 
        ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200));
        for (;;) {
-               PRINTD("Drag monitor count %d delay %d\n", ao_lco_drag_beep_count, delay);
+               PRINTD("Drag monitor count %d delay %lu\n", ao_lco_drag_beep_count, (unsigned long) delay);
                if (delay == (AO_TICK_TYPE) ~0)
                        ao_sleep(&ao_lco_drag_beep_count);
                else
@@ -176,8 +176,8 @@ ao_lco_input(void)
 
        for (;;) {
                ao_event_get(&event);
-               PRINTD("event type %d unit %d value %d\n",
-                      event.type, event.unit, event.value);
+               PRINTD("event type %d unit %d value %ld\n",
+                      event.type, event.unit, (long) event.value);
                switch (event.type) {
                case AO_EVENT_QUADRATURE:
                        switch (event.unit) {
index c1e220e3df54ca7a10edab50cc5c25a5c794c974..9b66c5180407eb08a921d4a4f06b5d8750222699 100644 (file)
@@ -105,7 +105,7 @@ OBJ=$(SRC:.c=.o)
 all: $(PROG) $(HEX)
 
 $(PROG): Makefile $(OBJ) altos.ld
-       $(call quiet,CC) $(LDFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+       $(call quiet,CC) $(LDFLAGS) -o $(PROG) $(OBJ) $(LIBS) -Wl,-Map=$(PROGNAME)-$(VERSION).map
 
 $(OBJ): $(INC)
 
index 124b47fb87dccab2416c84c9de132af88ed3ff36..5bc8d56a3a79896e354650c8265e4218d867c55c 100644 (file)
@@ -64,10 +64,6 @@ PRODUCT=TeleStatic-v3.0
 PRODUCT_DEF=-DTELESTATIC_V_3_0
 IDPRODUCT=0x000f
 
-# Include floating-point enabled printf
-
-NEWLIB_PRINTF_CFLAGS = 
-
 CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF)
 
 PROGNAME = telestatic-v3.0
index 7e9cd3535e1ccc529a0e73548889386eb0a750e1..721d776c3df4fee682f45f55324c1c5fce9778c1 100644 (file)
@@ -36,7 +36,7 @@ const struct ao_cmds ao_firetwo_cmds[] = {
         { 0,    NULL },
 };
 
-void
+int
 main(void)
 {
        ao_clock_init();
index 56f532efa6ad6fe6e32d243d718d7d09339c413f..e3af02f655b8479f4a6591040febe3dfe833d881 100644 (file)
@@ -16,6 +16,7 @@ ao_fec_test
 ao_flight_test_mm
 ao_flight_test_noisy_accel
 ao_flight_test_metrum
+ao_flight_test_mini
 ao_micropeak_test
 ao_aes_test
 ao_lisp_test
index dc982dea911dca866d093c2ae14dfec7c433be0d..7c5d186e9864728f5b959b69e594e21c69314768 100644 (file)
@@ -43,6 +43,7 @@ public class TeleGPSConfigUI
        JLabel                  aprs_interval_label;
        JLabel                  aprs_ssid_label;
        JLabel                  aprs_format_label;
+       JLabel                  aprs_offset_label;
        JLabel                  flight_log_max_label;
        JLabel                  callsign_label;
        JLabel                  tracker_motion_label;
@@ -61,6 +62,7 @@ public class TeleGPSConfigUI
        JComboBox<String>       aprs_interval_value;
        JComboBox<Integer>      aprs_ssid_value;
        JComboBox<String>       aprs_format_value;
+       JComboBox<Integer>      aprs_offset_value;
        JComboBox<String>       flight_log_max_value;
        JTextField              callsign_value;
        JComboBox<String>       tracker_motion_value;
@@ -84,6 +86,10 @@ public class TeleGPSConfigUI
                0, 1, 2 ,3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
        };
 
+       static Integer[]        aprs_offset_values = {
+               0, 2, 4, 6, 8, 10, 12, 14, 16, 18
+       };
+
        static String[]         tracker_motion_values_m = {
                "2",
                "5",
@@ -178,6 +184,15 @@ public class TeleGPSConfigUI
                        aprs_format_value.setToolTipText("Hardware doesn't support APRS");
        }
 
+       void set_aprs_offset_tool_tip() {
+               if (aprs_offset_value.isVisible())
+                       aprs_offset_value.setToolTipText("Set the APRS offset from top of minute");
+               else if (aprs_offset_value.isVisible())
+                       aprs_offset_value.setToolTipText("Software version doesn't support setting the APRS offset");
+               else
+                       aprs_offset_value.setToolTipText("Hardware doesn't support APRS");
+       }
+
        void set_flight_log_max_tool_tip() {
                if (flight_log_max_value.isVisible())
                        flight_log_max_value.setToolTipText("Size reserved for each flight log (in kB)");
@@ -444,6 +459,33 @@ public class TeleGPSConfigUI
                set_aprs_format_tool_tip();
                row++;
 
+               /* APRS offset */
+               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;
+               aprs_offset_label = new JLabel("APRS offset:");
+               pane.add(aprs_offset_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;
+               aprs_offset_value = new JComboBox<Integer>(aprs_offset_values);
+               aprs_offset_value.setEditable(false);
+               aprs_offset_value.addItemListener(this);
+               aprs_offset_value.setMaximumRowCount(aprs_offset_values.length);
+               pane.add(aprs_offset_value, c);
+               set_aprs_offset_tool_tip();
+               row++;
+
                /* Callsign */
                c = new GridBagConstraints();
                c.gridx = 0; c.gridy = row;
@@ -832,14 +874,18 @@ public class TeleGPSConfigUI
                return parse_int("flight log max", flight_log_max_value.getSelectedItem().toString(), true);
        }
 
-       public void set_flight_log_max_limit(int new_flight_log_max_limit) {
+       public void set_flight_log_max_limit(int new_flight_log_max_limit, int new_storage_erase_unit) {
                flight_log_max_limit = new_flight_log_max_limit;
-               flight_log_max_value.removeAllItems();
-               for (int i = 8; i >= 1; i--) {
-                       int     size = flight_log_max_limit / i;
-                       flight_log_max_value.addItem(String.format("%d (%d flights)", size, i));
+               if (new_flight_log_max_limit != AltosLib.MISSING) {
+                       flight_log_max_value.removeAllItems();
+                       for (int i = 8; i >= 1; i--) {
+                               int     size = flight_log_max_limit / i;
+                               if (new_storage_erase_unit != 0)
+                                       size &= ~(new_storage_erase_unit - 1);
+                               flight_log_max_value.addItem(String.format("%d (%d flights)", size, i));
+                       }
                }
-               if (flight_log_max != 0)
+               if (flight_log_max != 0 && flight_log_max != AltosLib.MISSING)
                        set_flight_log_max(flight_log_max);
        }
 
@@ -963,4 +1009,19 @@ public class TeleGPSConfigUI
                        return aprs_format_value.getSelectedIndex();
                return AltosLib.MISSING;
        }
+       public void set_aprs_offset(int new_aprs_offset) {
+               if (new_aprs_offset != AltosLib.MISSING)
+                       aprs_offset_value.setSelectedItem(new_aprs_offset);
+               aprs_offset_value.setVisible(new_aprs_offset != AltosLib.MISSING);
+               aprs_offset_label.setVisible(new_aprs_offset != AltosLib.MISSING);
+               set_aprs_offset_tool_tip();
+       }
+
+       public int aprs_offset() throws AltosConfigDataException {
+               if (aprs_offset_value.isVisible()) {
+                       Integer i = (Integer) aprs_offset_value.getSelectedItem();
+                       return i;
+               }
+               return AltosLib.MISSING;
+       }
 }