Merge branch 'easymotor-v3'
authorKeith Packard <keithp@keithp.com>
Fri, 28 Oct 2022 02:16:39 +0000 (19:16 -0700)
committerKeith Packard <keithp@keithp.com>
Fri, 28 Oct 2022 02:16:39 +0000 (19:16 -0700)
42 files changed:
Makefile.am
Releasing
altoslib/AltosConvert.java
altoslib/AltosEepromRecordMotor.java
altosui/Makefile.am
altosui/altos-windows.nsi.in
ao-bringup/turnon_easymega_v1.0
ao-tools/ao-eeprom/ao-eeprom.c
ao-tools/ao-elftohex/ao-elftohex.1
ao-tools/ao-elftohex/ao-elftohex.c
ao-tools/lib/ao-eeprom-read.h
configure.ac
doc/Makefile.am
doc/RELNOTES
doc/altusmetrum-theme.yml
doc/altusmetrum.txt
doc/config-device.inc
doc/dedication.inc
doc/easymini-release-notes.inc
doc/easymini.txt
doc/header.inc
doc/micropeak.txt
doc/pyro-examples.inc [new file with mode: 0644]
doc/release-notes-1.9.11.inc [new file with mode: 0644]
doc/release-notes.inc
doc/telegps-dedication.inc
doc/telegps-release-notes.inc
doc/telegps.txt
doc/telelaunch-acknowledgements.inc
src/Makefile
src/aes/ao_aes.c
src/easymini-v1.0/Makefile
src/easymini-v3.0/.gitignore [new file with mode: 0644]
src/easymini-v3.0/Makefile [new file with mode: 0644]
src/easymini-v3.0/ao_easymini.c [new file with mode: 0644]
src/easymini-v3.0/ao_pins.h [new file with mode: 0644]
src/easymini-v3.0/flash-loader/Makefile [new file with mode: 0644]
src/easymini-v3.0/flash-loader/ao_pins.h [new file with mode: 0644]
src/kernel/ao_log.h
src/kernel/ao_telemetry.c
src/lpc/ao_adc_lpc.c
src/lpc/ao_beep_lpc.c

index 6918c578cf98d7541754e1938424d7c2b86cc172..f20a532a9132febfd7eb556261c330c9e6ac7479 100644 (file)
@@ -53,6 +53,8 @@ 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/easymini-v2.0/easymini-v2.0-$(VERSION).ihx \
+       src/easymini-v3.0/easymini-v3.0-$(VERSION).ihx \
        src/easymotor-v2/easymotor-v2-$(VERSION).ihx \
        src/easytimer-v1/easytimer-v1-$(VERSION).ihx \
        src/telebt-v3.0/telebt-v3.0-$(VERSION).ihx \
index 408b180519aa19a986629d7fe236eb7f82b75165..00695f8ce3e740eea5be931917de2b11690fefef 100644 (file)
--- a/Releasing
+++ b/Releasing
@@ -109,7 +109,7 @@ These are Bdale's notes on how to do a release.
 
        cp src/chaoskey-v1.0/{*.elf,*.ihx,*.bin,*.map} \
           src/easymega-v[1-2].0/{*.elf,*.ihx,*.map} \
-          src/easymini-v[1-2].0/{*.elf,*.ihx,*.map} \
+          src/easymini-v[1-3].0/{*.elf,*.ihx,*.map} \
           src/easymotor-v2/{*.elf,*.ihx,*.map} \
           src/easytimer-v1/{*.elf,*.ihx,*.map} \
           src/telebt-v[3-4].0/{*.elf,*.ihx,*.map} \
index 099ea04859337bb14e0799df62d607eabc97f9d8..3e1796b2c194bfbeb212a9adbe675a0917642201 100644 (file)
@@ -323,6 +323,16 @@ public class AltosConvert {
                return (voltage - base) / (max - base) * full_scale_pressure;
        }
 
+       static double easy_motor_3_adc(double raw) {
+               return raw / 32767.0;
+       }
+
+       static double easy_motor_3_voltage(int sensor) {
+               double  supply = 3.3;
+
+               return easy_motor_3_adc(sensor) * supply * 15.6 / 10.0;
+       }
+
        static double easy_motor_2_motor_pressure(int sensor, double ground_sensor) {
                double  supply = 3.3;
                double  ground_voltage = easy_mini_2_adc(ground_sensor) * supply * 15.6 / 10.0;
@@ -331,6 +341,14 @@ public class AltosConvert {
                return motor_pressure(voltage) - motor_pressure(ground_voltage);
        }
 
+       static double easy_motor_3_motor_pressure(int sensor, double ground_sensor) {
+               double  supply = 3.3;
+               double  ground_voltage = easy_motor_3_adc(ground_sensor) * supply * 15.6 / 10.0;
+               double  voltage = easy_motor_3_adc(sensor) * supply * 15.6 / 10.0;
+
+               return motor_pressure(voltage) - motor_pressure(ground_voltage);
+       }
+
        public static double radio_to_frequency(int freq, int setting, int cal, int channel) {
                double  f;
 
index a8f35db476c58f0a214f038c2f007dcdecde03c3..d5068b08d3f9d10b2222ff7b4137c42f9c0e3ff2 100644 (file)
@@ -68,8 +68,8 @@ public class AltosEepromRecordMotor extends AltosEepromRecord {
                case AltosLib.AO_LOG_SENSOR:
                        AltosConfigData config_data = eeprom.config_data();
 
-                       listener.set_battery_voltage(AltosConvert.easy_mini_2_voltage(v_batt()));
-                       double pa = AltosConvert.easy_motor_2_motor_pressure(motor_pres(), cal_data.ground_motor_pressure);
+                       listener.set_battery_voltage(AltosConvert.easy_motor_3_voltage(v_batt()));
+                       double pa = AltosConvert.easy_motor_3_motor_pressure(motor_pres(), cal_data.ground_motor_pressure);
                        listener.set_motor_pressure(pa);
 
                        int     accel_along = accel_along();
index fde718d3abe0de246b82254e99fbea9dd0a6da87..aeadd974f49847f0190ca2b308f38bf8225eb6ce 100644 (file)
@@ -141,7 +141,8 @@ FIRMWARE_TMEGA=$(FIRMWARE_TMEGA_1_0) $(FIRMWARE_TMEGA_2_0) $(FIRMWARE_TMEGA_3_0)
 
 FIRMWARE_EMINI_1_0=$(top_srcdir)/src/easymini-v1.0/easymini-v1.0-$(VERSION).ihx
 FIRMWARE_EMINI_2_0=$(top_srcdir)/src/easymini-v2.0/easymini-v2.0-$(VERSION).ihx
-FIRMWARE_EMINI=$(FIRMWARE_EMINI_1_0) $(FIRMWARE_EMINI_2_0)
+FIRMWARE_EMINI_3_0=$(top_srcdir)/src/easymini-v3.0/easymini-v3.0-$(VERSION).ihx
+FIRMWARE_EMINI=$(FIRMWARE_EMINI_1_0) $(FIRMWARE_EMINI_2_0) $(FIRMWARE_EMINI_3_0)
 
 FIRMWARE_EMEGA_1_0=$(top_srcdir)/src/easymega-v1.0/easymega-v1.0-$(VERSION).ihx
 FIRMWARE_EMEGA_2_0=$(top_srcdir)/src/easymega-v2.0/easymega-v2.0-$(VERSION).ihx
index 6e8b1cca8b0362ed491d38fd8ad6f153ed7931fc..f1d58d6e945bd186230bfd22bb731647c6c93ed3 100644 (file)
@@ -135,6 +135,7 @@ Section "Firmware"
        File "../src/telemega-v5.0/telemega-v5.0-${VERSION}.ihx"
        File "../src/easymini-v1.0/easymini-v1.0-${VERSION}.ihx"
        File "../src/easymini-v2.0/easymini-v2.0-${VERSION}.ihx"
+       File "../src/easymini-v3.0/easymini-v3.0-${VERSION}.ihx"
        File "../src/easymega-v1.0/easymega-v1.0-${VERSION}.ihx"
        File "../src/easymega-v2.0/easymega-v2.0-${VERSION}.ihx"
        File "../src/easymotor-v2/easymotor-v2-${VERSION}.ihx"
index b14ed2ab9895c835d20f3de84bdb2775753db31b..2a3309844efa516aba4d850fe5f05a59ba2e573a 100755 (executable)
@@ -71,6 +71,6 @@ echo 'E 0' > $dev
 
 echo 'E 1' > $dev
 
-./test-easymega
+./test-easymega-v1.0
 
 exit $?
index 780badbed3d0d4a9ee56176690aba18777751303..1f367d9332265be4f4f9941afbe4b3e76ee87def 100644 (file)
@@ -148,7 +148,7 @@ ao_thrust(int16_t value, int16_t max_adc, double ref, double r1, double r2)
 }
 
 static void
-ao_pressure(int16_t value, int16_t max_adc, double ref, double r1, double r2)
+ao_pressure(int16_t value, int16_t max_adc, double ref, double r1, double r2, double sensor_range)
 {
        printf(" pressure %5d", value);
        if (r1 && r2 && ref) {
@@ -156,7 +156,7 @@ ao_pressure(int16_t value, int16_t max_adc, double ref, double r1, double r2)
                if (volts < 0.5) volts = 0.5;
                if (volts > 4.5) volts = 4.5;
 
-               double psi = (volts - 0.5) / 4.0 * 2500.0;
+               double psi = (volts - 0.5) / 4.0 * sensor_range;
                double pa = psi_to_pa(psi);
                printf(" %9.3f kPa", pa / 1000.0);
        }
@@ -261,6 +261,7 @@ main (int argc, char **argv)
                double  sense_r1 = 0.0, sense_r2 = 0.0;
                double  batt_r1 = 0.0, batt_r2 = 0.0;
                double  adc_ref = 0.0;
+               double  pressure_sensor = 0.0;
                int16_t max_adc = 0;
 
                switch (eeprom->log_format) {
@@ -315,6 +316,7 @@ main (int argc, char **argv)
                        break;
                case AO_LOG_FORMAT_TELEFIRETWO:
                        len = 32;
+                       pressure_sensor = 2500.0;
                        max_adc = 4095;
                        adc_ref = 3.3;
                        sense_r1 = batt_r1 = 5600;
@@ -364,6 +366,7 @@ main (int argc, char **argv)
                        len = 16;
                        max_adc = 32767;
                        adc_ref = 3.3;
+                       pressure_sensor = 1600.0;
                        batt_r1 = 5600;
                        batt_r2 = 10000;
                        sense_r1 = 5600;
@@ -421,11 +424,14 @@ main (int argc, char **argv)
                                        log_mega = (struct ao_log_mega *) &eeprom->data[pos];
                                        switch (log_mega->type) {
                                        case AO_LOG_FLIGHT:
-                                               printf(" serial %5u flight %5u ground_accel %6d ground_pres %9u",
+                                               printf(" serial %5u flight %5u ground_accel %6d ground_pres %9u kPa  %7.1f  %7.1f m",
                                                       eeprom->serial_number,
                                                       log_mega->u.flight.flight,
                                                       log_mega->u.flight.ground_accel,
-                                                      log_mega->u.flight.ground_pres);
+                                                      log_mega->u.flight.ground_pres,
+                                                      log_mega->u.flight.ground_pres / 1000.0,
+                                                      ao_pressure_to_altitude(log_mega->u.flight.ground_pres));
+
                                                printf(" along %6d aross %6d through %6d",
                                                       log_mega->u.flight.ground_accel_along,
                                                       log_mega->u.flight.ground_accel_across,
@@ -522,10 +528,12 @@ main (int argc, char **argv)
                                        log_mini = (struct ao_log_mini *) &eeprom->data[pos];
                                        switch (log_mini->type) {
                                        case AO_LOG_FLIGHT:
-                                               printf(" serial %5u flight %5u ground_pres %9u",
+                                               printf(" serial %5u flight %5u ground_pres %9u kPa  %7.1f  %7.1f m",
                                                       eeprom->serial_number,
                                                       log_mini->u.flight.flight,
-                                                      log_mini->u.flight.ground_pres);
+                                                      log_mini->u.flight.ground_pres,
+                                                      log_mini->u.flight.ground_pres / 1000.0,
+                                                      ao_pressure_to_altitude(log_mini->u.flight.ground_pres));
                                                break;
                                        case AO_LOG_STATE:
                                                ao_state(log_mini->u.state.state,
@@ -551,11 +559,13 @@ main (int argc, char **argv)
                                        log_metrum = (struct ao_log_metrum *) &eeprom->data[pos];
                                        switch (log_metrum->type) {
                                        case AO_LOG_FLIGHT:
-                                               printf(" serial %5u flight %5u ground_accel %6d ground_pres %9u ground_temp %9u",
+                                               printf(" serial %5u flight %5u ground_accel %6d ground_pres %9u kPa  %7.1f  %7.1f m ground_temp %9u",
                                                       eeprom->serial_number,
                                                       log_metrum->u.flight.flight,
                                                       log_metrum->u.flight.ground_accel,
                                                       log_metrum->u.flight.ground_pres,
+                                                      log_metrum->u.flight.ground_pres / 1000.0,
+                                                      ao_pressure_to_altitude(log_metrum->u.flight.ground_pres),
                                                       log_metrum->u.flight.ground_temp);
                                                break;
                                        case AO_LOG_SENSOR:
@@ -628,7 +638,8 @@ main (int argc, char **argv)
                                        case AO_LOG_SENSOR:
                                                ao_pressure(log_firetwo->u.sensor.pressure,
                                                            max_adc, adc_ref,
-                                                           sense_r1, sense_r2);
+                                                           sense_r1, sense_r2,
+                                                           pressure_sensor);
                                                ao_thrust(log_firetwo->u.sensor.thrust,
                                                          max_adc, adc_ref,
                                                          sense_r1, sense_r2);
@@ -724,6 +735,31 @@ main (int argc, char **argv)
                                        break;
                                case AO_LOG_FORMAT_DETHERM:
                                        break;
+                               case AO_LOG_FORMAT_EASYMOTOR:
+                                       log_motor = (struct ao_log_motor *) &eeprom->data[pos];
+                                       switch (log_motor->type) {
+                                       case AO_LOG_FLIGHT:
+                                               printf(" serial %5u flight %5u",
+                                                      eeprom->serial_number,
+                                                      log_motor->u.flight.flight);
+                                               break;
+                                       case AO_LOG_STATE:
+                                               ao_state(log_motor->u.state.state,
+                                                        log_motor->u.state.reason);
+                                               break;
+                                       case AO_LOG_SENSOR:
+                                               ao_pressure(log_motor->u.sensor.pressure,
+                                                           max_adc, adc_ref,
+                                                           sense_r1, sense_r2,
+                                                           pressure_sensor);
+                                               ao_volts("v_batt",
+                                                        log_motor->u.sensor.v_batt,
+                                                        max_adc,
+                                                        adc_ref,
+                                                        batt_r1, batt_r2);
+                                               break;
+                                       }
+                                       break;
                                }
                        }
                        printf("\n");
index e52e6f5a5625ac1fc7b39e0129d484f2b06ebbc7..859d26785fe06215d790af361462b009d974563b 100644 (file)
 .\"
 .TH AO-LOAD 1 "ao-elftohex" ""
 .SH NAME
-ao-elftohex \- convert a program to IHX format
+ao-elftohex \- convert programs to IHX format
 .SH SYNOPSIS
 .B "ao-elftohex"
 [\--output-\fIoutput.ihx\fP]
 [\--verbose]
-\fIinput.elf\fP
+\fIinput.elf ...\fP
 .SH DESCRIPTION
 .I ao-elftohex
-reads the specified .elf file and writes out a .ihx version.
+reads the specified .elf files and writes out a .ihx version.
 .SH OPTIONS
 .TP
 \--output=\fIoutput.ihx\fP
@@ -34,5 +34,10 @@ This specifies the output file (default is stdout)
 .TP
 \--verbose
 Dumps some debug information.
+.TP
+\--nosym
+Excluded symbol table information from the resulting file. This
+information is a non-standard extension supported by the Altus Metrum
+tools.
 .SH AUTHOR
 Keith Packard
index f3ab0c38ca4a1fdeff140e14a553979b1aeecff6..a31f9656f6cd80a88d11f6eded1d9b4f008eef68 100644 (file)
@@ -27,6 +27,7 @@
 static const struct option options[] = {
        { .name = "verbose", .has_arg = 1, .val = 'v' },
        { .name = "output", .has_arg = 1, .val = 'o' },
+       { .name = "nosym", .has_arg = 0, .val = 'n' },
        { 0, 0, 0, 0},
 };
 
@@ -52,13 +53,15 @@ main (int argc, char **argv)
 {
        char                    *input = NULL;
        char                    *output = NULL;
-       struct ao_hex_image     *image;
-       struct ao_sym           *file_symbols;
+       struct ao_hex_image     *full_image = NULL;
+       struct ao_sym           *file_symbols = NULL;
        int                     num_file_symbols;
        FILE                    *file;
        int                     c;
+       int                     i;
+       int                     nosym = 0;
 
-       while ((c = getopt_long(argc, argv, "v:o:", options, NULL)) != -1) {
+       while ((c = getopt_long(argc, argv, "nv:o:", options, NULL)) != -1) {
                switch (c) {
                case 'o':
                        output = optarg;
@@ -66,23 +69,50 @@ main (int argc, char **argv)
                case 'v':
                        ao_verbose = (int) strtol(optarg, NULL, 0);
                        break;
+               case 'n':
+                       nosym = 1;
+                       break;
                default:
                        usage(argv[0]);
                        break;
                }
        }
 
-       input = argv[optind];
-       if (input == NULL)
+       if (optind >= argc)
                usage(argv[0]);
 
-       if (ends_with (input, ".ihx"))
-               image = ao_hex_load(input, &file_symbols, &num_file_symbols);
-       else
-               image = ao_load_elf(input, &file_symbols, &num_file_symbols);
+       for (i = optind; i < argc; i++) {
+               struct ao_hex_image *image;
 
-       if (!image)
-               usage(argv[0]);
+               input = argv[i];
+
+               free(file_symbols);
+               num_file_symbols = 0;
+               if (ends_with (input, ".ihx"))
+                       image = ao_hex_load(input, &file_symbols, &num_file_symbols);
+               else
+                       image = ao_load_elf(input, &file_symbols, &num_file_symbols);
+
+               if (!image) {
+                       fprintf(stderr, "Failed to load %s\n", input);
+                       usage(argv[0]);
+               }
+
+               if (nosym) {
+                       free(file_symbols);
+                       file_symbols = NULL;
+                       num_file_symbols = 0;
+               }
+
+               if (full_image) {
+                       full_image = ao_hex_image_cat(full_image, image);
+                       if (!full_image) {
+                               fprintf(stderr, "Can't merge image %s\n", input);
+                               usage(argv[0]);
+                       }
+               } else
+                       full_image = image;
+       }
 
        if (!output)
                file = stdout;
@@ -94,7 +124,7 @@ main (int argc, char **argv)
                }
        }
 
-       if (!ao_hex_save(file, image, file_symbols, num_file_symbols)) {
+       if (!ao_hex_save(file, full_image, file_symbols, num_file_symbols)) {
                fprintf(stderr, "%s: failed to write hex file\n", output ? output : "<stdout>");
                if (output)
                        unlink(output);
index aaf6d3d68032de922e5f20e6fccb509af71eed08..9e60a5af9acdd0750b30e9934a190d47f1ab071d 100644 (file)
@@ -45,7 +45,7 @@
 #define AO_LOG_FORMAT_TELESTATIC       17      /* 32 byte typed telestatic records */
 #define AO_LOG_FORMAT_MICROPEAK2       18      /* 2-byte baro values with header */
 #define AO_LOG_FORMAT_TELEMEGA_4       19      /* 32 byte typed telemega records with 32 bit gyro cal and Bmx160 */
-#define AO_LOG_FORMAT_EASYMOTOR                20      /* 16 byte typed easymotor records */
+#define AO_LOG_FORMAT_EASYMOTOR                20      /* 16 byte typed easymotor records with pressure sensor and adxl375 */
 #define AO_LOG_FORMAT_NONE             127     /* No log at all */
 
 enum ao_pyro_flag {
@@ -547,6 +547,37 @@ struct ao_log_gps {
        } u;
 };
 
+struct ao_log_motor {
+       char                    type;                   /* 0 */
+       uint8_t                 csum;                   /* 1 */
+       uint16_t                tick;                   /* 2 */
+       union {                                         /* 4 */
+               /* AO_LOG_FLIGHT */
+               struct {
+                       uint16_t        flight;                 /* 4 */
+                       int16_t         ground_accel;           /* 6 */
+                       int16_t         ground_accel_along;     /* 8 */
+                       int16_t         ground_accel_across;    /* 10 */
+                       int16_t         ground_accel_through;   /* 12 */
+                       int16_t         ground_motor_pressure;  /* 14 */
+               } flight;                                       /* 16 */
+               /* AO_LOG_STATE */
+               struct {
+                       uint16_t        state;                  /* 4 */
+                       uint16_t        reason;                 /* 6 */
+               } state;
+               /* AO_LOG_SENSOR */
+               struct {
+                       uint16_t        pressure;               /* 4 */
+                       uint16_t        v_batt;                 /* 6 */
+                       int16_t         accel;                  /* 8 */
+                       int16_t         accel_across;           /* 10 */
+                       int16_t         accel_along;            /* 12 */
+                       int16_t         accel_through;          /* 14 */
+               } sensor;                                       /* 16 */
+       } u;
+};
+
 struct ao_eeprom {
        struct ao_config        config;
        struct ao_ms5607_prom   ms5607_prom;
index 442fafd34fc83d4766d86a7a0b746c368beb06d2..d4164741f882d5a759bb4700d0edf707ea214855 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.10.4)
-ANDROID_VERSION=34
+AC_INIT([altos], 1.9.11)
+ANDROID_VERSION=35
 AC_CONFIG_SRCDIR([src/kernel/ao.h])
 AM_INIT_AUTOMAKE([foreign dist-bzip2])
 AM_MAINTAINER_MODE
 
-RELEASE_DATE=2022-02-21
+RELEASE_DATE=2022-05-29
 AC_SUBST(RELEASE_DATE)
 
 DOC_DATE=`LC_ALL=C date -d $RELEASE_DATE +'%d %b %Y'`
index 5ca6137991c54e9cbd7fc2b3d4988bd807e88185..35e696cb6b3ffeff20c2302dd1eca78b4feacb34 100644 (file)
@@ -17,6 +17,7 @@ FAKETIME=TZ=UTC faketime -f '$(RELEASE_DATE) 00:00:00 i0'
 endif
 
 RELNOTES_INC=\
+       release-notes-1.9.11.inc \
        release-notes-1.9.10.inc \
        release-notes-1.9.9.inc \
        release-notes-1.9.8.inc \
@@ -137,6 +138,7 @@ COMMON_INC_FILES=\
        config-ui.inc \
        load-maps.inc \
        aprs-operation.inc \
+       pyro-examples.inc \
        handling.inc \
        release-head.inc
 
index 7541b844408aaea79d8a03c5b54e0bd9ab239d97..ad659f103526cdad0b907c3335c19e9db9bbd427 100644 (file)
@@ -6,6 +6,8 @@ Creating documentation for a new release of AltOS
 
 * Make sure doc/altusmetrum-theme.yml has the right copyright year
 
+* Make sure header.inc has the right copyright year
+
 * Add references to that as appropriate from each of the documents:
 
        release-notes.inc
index bed7c141fdb116a17a3520abb3c06d49ca787140..c4f6f96bdf5368588330d7f0d34d448b8ba78cda 100644 (file)
@@ -51,7 +51,7 @@ footer:
     left:
       content: '{page-number}'
     right:
-      content: '© 2021 Bdale Garbee and Keith Packard. Creative Commons ShareAlike 3.0 License'
+      content: '© 2022 Bdale Garbee and Keith Packard. Creative Commons ShareAlike 3.0 License'
   verso:
     left:
       content: $footer_recto_right_content
index 41e79a2b6886840e62430162ad31701f4278f460..b655c0b23a166e0ff480f2b5ec7cc4d68fe1584f 100644 (file)
@@ -5,7 +5,7 @@ Keith Packard <keithp@keithp.com>; Bdale Garbee <bdale@gag.com>; Bob Finch; Anth
 :revdate: 1 Jan 1970
 :icons:
 :icontype: svg
-:copyright: Bdale Garbee and Keith Packard 2021
+:copyright: Bdale Garbee and Keith Packard 2022
 :doctype: book
 :numbered:
 :stylesheet: am.css
@@ -59,6 +59,8 @@ Keith Packard <keithp@keithp.com>; Bdale Garbee <bdale@gag.com>; Bob Finch; Anth
 
        include::system-operation.adoc[]
 
+       include::pyro-examples.adoc[]
+
        include::handling.adoc[]
 
        include::updating-firmware.adoc[]
index a533ca82213debb5455671d278192640ac3d4bed..71ee1c4f573eecba61665ea6cd815649d54b9b1c 100644 (file)
@@ -71,6 +71,11 @@ ifdef::radio[]
                flight. When disabled, the radio will not
                transmit anything during flight at all.
 
+       ==== Limit transmit to 10mW
+
+               Reduces transmit power to no more than 10mW. This is
+               useful when operating under some UK radio regulations.
+
        ==== Telemetry baud rate
 
                This sets the modulation bit rate for data
index 6fac8e450d03083724bbf489e714ee92f3654f11..b7d2b510c41ab98fbba88dcee720ea30fe90fb3c 100644 (file)
@@ -22,5 +22,5 @@
        NAR #87103, TRA #12201
 
        [verse]
-       Keith Packard, KD7SQG
+       Keith Packard, K7WQ
        NAR #88757, TRA #12200
index 34e6471a2e138b5d2e6f97a8e9b934ca09615484..ed98d5b78d7418856c15d1cdab27f61f49ba01da 100644 (file)
@@ -1,5 +1,9 @@
 [appendix]
 == Release Notes
+       :leveloffset: 2
+       include::release-notes-1.9.11.adoc[]
+
+       <<<<
        :leveloffset: 2
        include::release-notes-1.9.10.adoc[]
 
index d18b3ee5219955f43b279067d561635db6b318d3..6a4b1e4abedc9e17b442e34866d1182329ed3afc 100644 (file)
@@ -3,7 +3,7 @@ Keith Packard <keithp@keithp.com>; Bdale Garbee <bdale@gag.com>
 :title-logo-image: image:../themes/background.png[]
 :revnumber: v{version}
 :revdate: 01 Jan 1970
-:copyright: Bdale Garbee and Keith Packard 2021
+:copyright: Bdale Garbee and Keith Packard 2022
 :doctype: book
 :numbered:
 :toc:
index cb80360bf7c6bd0eb2a1419e4e1f999f8fe22d26..a33b4b9d2524b8d5a607bda1079ade4a1fade152 100644 (file)
@@ -7,7 +7,7 @@ endif::[]
 [license]
 == License
 
-Copyright © 2021 Bdale Garbee and Keith Packard
+Copyright © 2022 Bdale Garbee and Keith Packard
 
 This document is released under the terms of the link:http://creativecommons.org/licenses/by-sa/3.0/[Creative Commons ShareAlike 3.0 License]
 
index afb935d750b9ad2f69164da91f9323b8a06cde01..c02c613a8287c14a145254545c75d674044c1fdd 100644 (file)
@@ -28,7 +28,7 @@ Keith Packard <keithp@keithp.com>; Bdale Garbee <bdale@gag.com>
        NAR #87103, TRA #12201
 
        [verse]
-       Keith Packard, KD7SQG
+       Keith Packard, K7WQ
        NAR #88757, TRA #12200
 
 == Using MicroPeak
diff --git a/doc/pyro-examples.inc b/doc/pyro-examples.inc
new file mode 100644 (file)
index 0000000..051f005
--- /dev/null
@@ -0,0 +1,210 @@
+[appendix]
+== Example Pyro Channel Configurations
+
+       Programming configurable pyro channels on Altus Metrum products that 
+       include them isn't difficult, but in an attempt to aid understanding
+       of the configuration interface and help "keep simple things simple",
+       we offer the following examples of the simplest configurations for
+       common situations, along with some hints on avoiding unexpected
+       results.
+
+       The rich set of conditions provided can be used to configure almost
+       any pyro event you can imagine, for a wide variety of objectives.  
+       But don't be fooled!  Typical events need only one or a few simple
+       conditions to be configured for success.  A key thing to remember is 
+       that *all* configured conditions must be true to allow a pyro channel 
+       to fire.  Trying to include too many conditions often results in 
+       conflicting rules that never allow a channel to fire.  The most 
+       important advice we can offer is, therefore, to try and find the 
+       simplest set of conditions that will do what you need for a given 
+       project.
+
+       === Two-Stage Flights
+
+               Successful completion of a two-stage flight often involves
+               programming of two events.  The first is firing a separation
+               charge, the second is igniting the sustainer's (primary)
+               motor.
+
+               Separation charges are best fired as soon as possible after
+               the previous stage has completed providing acceleration, to
+               minimize drag of the sustainer's coast phase before ignition.
+               Recovery, whether the remainder of the flight is nominal or
+               not, usually works best when the states are separated.  So,
+               the "best" way to configure a pyro channel for a separation
+               charge is to just set "after motor number".  For a 2-stage
+               project, set this to "1".  This will cause the pyro channel
+               to fire as soon as the firmware's flight state machine
+               determines the first motor has burned out.
+
+               Safe ignition of a sustainer (primary) motor requires that
+               it happen after the previous stage burns out, while the 
+               airframe remains mostly vertical, and typically after the
+               sustainer has coasted away from the booster a bit.  A good
+               starting point is thus "after motor number" set the same as
+               the separation charge, which is "1" for a 2-stage rocket.
+               Then "angle from vertical less than" set to some
+               reasonably vertical amount, perhaps 20 degrees.  Then "delay
+               after other conditions" set for the desired duration of coast.
+               Use simulations to figure out what a reasonable value here is,
+               but for typical high power rocketry sport flights that aren't 
+               trying to set records, something like 2 seconds is usually a 
+               good place to start.
+       
+       === Triggered Clusters and Air Starts
+
+               When an airframe has a cluster of motors, one of which is 
+               "primary" and centered, surrounding by a ring of "secondary"
+               motors, you may want to use the launch control system to                        fire the primary motor and use onboard electronics to light
+               the rest of the cluster as soon as launch is detected.  This
+               is particularly true if the primary motor is significantly
+               different in geometry and may take longer to come up to 
+               pressure than the secondary motors.  In this case, a simple
+               configuration to light secondary motors is is "time since
+               boost greater than" enabled and set to "0".  There's
+               really no point in setting an angle limit since no time has
+               transpired for the airframe to change orientation.
+
+               Air starts can use the same simple configuration, but with 
+               the time set to a non-zero value.  However, if air starts
+               are going to light after the airframe leaves the launch rail
+               or tower, add an "angle from vertical less than"
+               condition just you would for a 2-stage sustainer to stay safe.
+
+       === Redundant Apogee
+
+               When flying a board like TeleMega or EasyMega, it's easy to
+               configure a programmable channel to fire a redundant apogee
+               charge.  This is of course not *fully* redundant, since it's
+               always possible that the board itself or its battery could
+               the the failure source, but far more often, pyro events fail
+               due to broken wires, bad connectors, or bad e-matches... so
+               firing two charges from one board can add useful redundancy.
+
+               The simplest configuration for redundant apogee is "flight
+               state after" set to "drogue", and then "delay after other 
+               conditions" set to a second or two.
+
+       === Redundant Main
+
+               Similarly to apogee, configuring a redundant main charge can
+               provide useful redundancy.  What we want is to configure an
+               altitude for deployment lower than the primary main deploy
+               altitude, and then ensure we only trigger on that condition
+               while descending.
+
+               The simplest configuration for redundant main is "flight
+               state after" set to "drogue", which will ensure we're in to
+               the descent phase, then "height less than" set to a number
+               lower than you've chosen for the primary main channel 
+               deployment height.
+
+       === Apogee Above Baro Sensor Limit
+
+               A question we've seen increasingly often is "How does the 
+               Telemega/Easymega detect apogee for flights above 100,000
+               feet?"  Flights above that height are a bit outside
+               our original design envelope, but can be made to work...
+               This is *not* a simple flight, and the configuration for it
+               is also not simple, but we think including this information
+               is important for anyone contemplating such a project with our
+               electronics!
+
+               Our flight computers use a Kalman sensor-fusing filter to 
+               estimate the flight state, which consists of three values:
+
+                       1. Height above ground
+                       2. Vertical speed
+                       3. Vertical acceleration
+
+               Apogee is assumed to be where vertical speed crosses zero.
+
+               Below 30km altitude (about 100k'), we use both the barometer 
+               and the accelerometer to update the flight state, along with 
+               a basic Newtonian model of motion. That works well, pegging 
+               apogee within a few sensor samples essentially every time.
+
+               Above 30km, the barometric sensor doesn't provide useful data, 
+               so we can't use it to update the flight state. Instead, the 
+               Kalman filter falls back to a single sensor mode, using only 
+               the accelerometer.
+
+               At all altitudes, we de-sense the barometric data when we 
+               estimate the speed is near or above mach as the sensor is 
+               often subjected to significant transients, which would 
+               otherwise push the flight state estimates too fast and could 
+               trigger a false apogee event.
+
+               That means the filter is no longer getting the benefit of two 
+               sensors, and relies on just the accelerometer. The trouble 
+               with accelerometers is they're measuring the derivative of 
+               speed, so you have to integrate their values to compute speed. 
+               Any offset error in acceleration measurement gets constantly 
+               added to that speed.
+
+               In addition, we assume the axial acceleration is actually 
+               vertical acceleration; our tilt measurements have enough 
+               integration error during coast that we can't usefully use 
+               that to get vertical acceleration. Because we don't live in 
+               an inertial frame, that means we're mis-computing the total 
+               acceleration acting on the airframe as we have to add gravity 
+               into the mix, and simply adding that to the axial acceleration 
+               value doesn't generate the right value.
+
+               The effect of this is to under-estimate apogee when you base 
+               the computation purely on acceleration as the rocket flies a 
+               parabolic path.
+
+               For flights *near* 100k', all of this works pretty well - 
+               you've got the flight state estimates adjusted using the 
+               barometric sensor up to 30km, then you're flying on inertial 
+               data to apogee.
+
+               For flights well above 100k', it's not great; you're usually 
+               going fast enough through 100k' that the baro sensor is still 
+               de-sensed through the end of its useful range, so the flight 
+               state estimates are not as close. After that, as you're flying 
+               purely on accelerometer data, there's no way to re-correct the 
+               state, so the apogee estimates can be off by quite a bit.
+
+               In the worst cases we have seen, the baro sensor data was 
+               wildly incorrect above mach due to poor static port design, 
+               leaving the state estimate of speed across the 30km boundary 
+               way off and causing the apogee detection to happen far from 
+               the correct time.
+
+               The good news is that correctly determining apogee is not 
+               really all that important at high altitudes; there's so little 
+               density that a drogue will have almost no drag anyways.  Data
+               from customer flights shows a very parabolic path down to 
+               about 50-60k feet, even with a recovery system deployed.
+
+               So, what we recommend is to set up two apogee plans:
+
+                       1. Use the built-in apogee detection, but add a 
+                          significant delay (as much as 30 seconds). This 
+                          will probably fire near enough to apogee to not 
+                          have a significant impact on the maximum height 
+                          achieved.
+
+                       2. Add a back-up apogee which fires after apogee 
+                          *when the height is below about 20-25km*. This 
+                          way, if the flight isn't nominal, and the sustainer 
+                          ends up reaching apogee in dense air, you aren't 
+                          hoping the chutes come out before it gets going 
+                          too fast. And, you get a second pyro channel firing 
+                          at that altitude even if it reached a higher 
+                          altitude before.
+
+               You can wire these two pyro channels to the same pyro device; 
+               you just need to make sure they're wired + to + and - to - 
+               (the manual shows which screw terminals are which).
+
+               The bottom line is that flights to altitudes modestly above
+               the range of the baro sensor with Altus Metrum products can
+               be accomplished safely, but flying "way high" (like 300k') 
+               demands a deployment mechanism which doesn't solely rely on 
+               altimeters (like ours) which are designed for modest altitude 
+               rocketry.  Flights to those altitudes also probably need 
+               active stabilization to make sure they follow the prescribed 
+               trajectory and stay inside their waiver.
diff --git a/doc/release-notes-1.9.11.inc b/doc/release-notes-1.9.11.inc
new file mode 100644 (file)
index 0000000..a473a51
--- /dev/null
@@ -0,0 +1,24 @@
+= Release Notes for Version 1.9.11
+include::release-head.adoc[]
+:doctype: article
+
+       Version 1.9.11
+
+       == AltOS
+
+       * Make Apogee Delay work again.
+
+       * Allow TX power to be limited to 10mW for compliance with
+          some uses under UK regulations.
+
+       * Fix numerous minor issues with 16- vs 32- bit time values.
+
+       == AltosUI
+
+       * Support M1-based Macs, follow AdoptOpenJDK to Adoptium
+
+       == AltosDroid
+
+       * Handle Bluetooth permissions reliably.
+
+       * Fix some screen rotation bugs.
index f492981abf3c4f9be7d623c5cb69743c3f40c3a7..53bba419425d287c1569ba0f0128b8e633c85583 100644 (file)
@@ -1,5 +1,9 @@
 [appendix]
 == Release Notes
+       :leveloffset: 2
+       include::release-notes-1.9.11.adoc[]
+
+       <<<<
        :leveloffset: 2
        include::release-notes-1.9.10.adoc[]
 
index 719c309c6bc0c4b636fe2db35c851c9f123d67b1..0b7d54d089470c730b08f6bbfe14dff2525783d9 100644 (file)
@@ -15,5 +15,5 @@
        NAR #87103, TRA #12201
 
        [verse]
-       Keith Packard, KD7SQG
+       Keith Packard, K7WQ
        NAR #88757, TRA #12200
index dedc6d4a773b6591bf9924a490a37eeb19c90168..b1e884a5c5fe11b025f83ca765d324af90211e35 100644 (file)
@@ -1,5 +1,9 @@
 [appendix]
 == Release Notes
+       :leveloffset: 2
+       include::release-notes-1.9.11.adoc[]
+
+       <<<<
        :leveloffset: 2
        include::release-notes-1.9.10.adoc[]
 
index 6db284768df230cc75e36e00c27b2d425dceef92..608a6db363c110737cce7b143c4069789cb17ec5 100644 (file)
@@ -3,7 +3,7 @@ Keith Packard <keithp@keithp.com>; Bdale Garbee <bdale@gag.com>
 :title-logo-image: image:../themes/background.png[]
 :revnumber: v{version}
 :revdate: 01 Jan 1970
-:copyright: Bdale Garbee and Keith Packard 2021
+:copyright: Bdale Garbee and Keith Packard 2022
 :stylesheet: am.css
 :linkcss:
 :toc:
index 3296624f8e96119a0acc2dbdd8709587a93e6c16..4a0f06ab9d35f09b7aba1a2c707acd511d783677 100644 (file)
@@ -22,5 +22,5 @@
        NAR #87103, TRA #12201
 
        [verse]
-       Keith Packard, KD7SQG
+       Keith Packard, K7WQ
        NAR #88757, TRA #12200
index 31671e031819cbe11c1576465d0e7e2b33d69b98..5215ca70aadecc8fb47a96d4c5b8ab562006e35b 100644 (file)
@@ -52,6 +52,7 @@ ARMM0DIRS=\
        chaoskey-v1.0 chaoskey-v1.0/flash-loader \
        telemini-v3.0 telemini-v3.0/flash-loader \
        easymini-v2.0 easymini-v2.0/flash-loader \
+       easymini-v3.0 easymini-v3.0/flash-loader \
        micropeak-v2.0
 
 AVRDIRS=\
index 0bc8188e3d2ae68c7eca2b78a214b473ce34b712..ce87e3a80bf491c09cd6f11bd760e30988c99dd2 100644 (file)
@@ -362,7 +362,7 @@ uint8_t ao_aes_mutex;
 static word32 key[16/4];
 static roundkey        rkk;
 
-static word32 iv[16/4];
+static word32 iv[32/4];
 
 void
 ao_aes_set_mode(enum ao_aes_mode mode)
index e146f54a46fd954224bc95ae8bb1cbe3c9b98ca8..755de1f06ea72779a7f140ad88c654b2d10746e4 100644 (file)
@@ -56,15 +56,25 @@ CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS)
 PROGNAME=easymini-v1.0
 PROG=$(PROGNAME)-$(VERSION).elf
 HEX=$(PROGNAME)-$(VERSION).ihx
+FLASH_PROG=flash-loader/$(PROGNAME)-altos-flash-$(VERSION).elf
+BOTH_HEX=$(PROGNAME)-combined-$(VERSION).ihx
 
 SRC=$(ALTOS_SRC) ao_easymini.c
 OBJ=$(SRC:.c=.o)
 
-all: $(PROG) $(HEX)
+all: $(PROG) $(HEX) $(BOTH_HEX)
 
 $(PROG): Makefile $(OBJ) altos.ld
        $(call quiet,CC) $(LDFLAGS) -o $(PROG) $(OBJ) $(LIBS)
 
+$(BOTH_HEX): $(PROG) $(FLASH_PROG)
+       ../../ao-tools/ao-elftohex/ao-elftohex -n --output=$@ $(FLASH_PROG) $(PROG)
+
+$(FLASH_PROG): FRC
+       +cd flash-loader && make
+
+FRC:
+
 $(OBJ): $(INC)
 
 load: $(PROG)
diff --git a/src/easymini-v3.0/.gitignore b/src/easymini-v3.0/.gitignore
new file mode 100644 (file)
index 0000000..e5f7d58
--- /dev/null
@@ -0,0 +1,2 @@
+ao_product.h
+*.elf
diff --git a/src/easymini-v3.0/Makefile b/src/easymini-v3.0/Makefile
new file mode 100644 (file)
index 0000000..81be85f
--- /dev/null
@@ -0,0 +1,91 @@
+#
+# AltOS build
+#
+#
+
+include ../lpc/Makefile.defs
+
+INC = \
+       ao.h \
+       ao_arch.h \
+       ao_arch_funcs.h \
+       ao_pins.h \
+       ao_product.h \
+       lpc.h
+
+#
+# Common AltOS sources
+#
+ALTOS_SRC = \
+       ao_interrupt.c \
+       ao_boot_chain.c \
+       ao_romconfig.c \
+       ao_product.c \
+       ao_mutex.c \
+       ao_panic.c \
+       ao_stdio.c \
+       ao_storage.c \
+       ao_report.c \
+       ao_ignite.c \
+       ao_flight.c \
+       ao_kalman.c \
+       ao_sample.c \
+       ao_data.c \
+       ao_convert_pa.c \
+       ao_convert_volt.c \
+       ao_task.c \
+       ao_log.c \
+       ao_log_mini.c \
+       ao_cmd.c \
+       ao_config.c \
+       ao_timer_lpc.c \
+       ao_exti_lpc.c \
+       ao_usb_lpc.c \
+       ao_spi_lpc.c \
+       ao_adc_lpc.c \
+       ao_beep_lpc.c \
+       ao_m25.c \
+       ao_ms5607.c
+
+PRODUCT=EasyMini-v3.0
+PRODUCT_DEF=-DEASYMINI_V_3_0
+IDPRODUCT=0x0026
+
+CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS)
+
+PROGNAME=easymini-v3.0
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+FLASH_PROG=flash-loader/$(PROGNAME)-altos-flash-$(VERSION).elf
+BOTH_HEX=$(PROGNAME)-combined-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_easymini.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX) $(BOTH_HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+       $(call quiet,CC) $(LDFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+$(BOTH_HEX): $(PROG) $(FLASH_PROG)
+       ../../ao-tools/ao-elftohex/ao-elftohex -n --output=$@ $(FLASH_PROG) $(PROG)
+
+$(FLASH_PROG): FRC
+       +cd flash-loader && make
+
+$(OBJ): $(INC)
+
+load: $(PROG)
+       lpc-load $(PROG)
+
+distclean:     clean
+
+clean:
+       rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx $(PROGNAME)-*.map
+       rm -f ao_product.h
+
+install:
+
+uninstall:
+
+FRC:
diff --git a/src/easymini-v3.0/ao_easymini.c b/src/easymini-v3.0/ao_easymini.c
new file mode 100644 (file)
index 0000000..05b2951
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_exti.h>
+
+int
+main(void)
+{
+       ao_clock_init();
+       ao_task_init();
+       ao_timer_init();
+       ao_exti_init();
+
+       ao_beep_init();
+
+       ao_adc_init();
+       ao_spi_init();
+       ao_storage_init();
+
+       ao_usb_init();
+
+       ao_cmd_init();
+       ao_flight_init();
+       ao_ms5607_init();
+       ao_log_init();
+       ao_report_init();
+       ao_igniter_init();
+       ao_config_init();
+
+       ao_start_scheduler();
+}
diff --git a/src/easymini-v3.0/ao_pins.h b/src/easymini-v3.0/ao_pins.h
new file mode 100644 (file)
index 0000000..6dbd7af
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#define HAS_BEEP               1
+#define HAS_BATTERY_REPORT     1
+
+#define AO_STACK_SIZE          352
+#define SLEEP_HASH_SIZE                3
+#define AO_NUM_TASKS           6
+
+#define IS_FLASH_LOADER        0
+
+/* Crystal on the board */
+#define AO_LPC_CLKIN   12000000
+
+/* Main clock frequency. 48MHz for USB so we don't use the USB PLL */
+#define AO_LPC_CLKOUT  48000000
+
+/* System clock frequency */
+#define AO_LPC_SYSCLK  24000000
+
+#define HAS_USB                1
+
+#define HAS_USB_CONNECT        0
+#define HAS_USB_VBUS   0
+#define HAS_USB_PULLUP 1
+#define AO_USB_PULLUP_PORT     1
+#define AO_USB_PULLUP_PIN      23
+
+#define PACKET_HAS_SLAVE       0
+
+#define AO_LOG_FORMAT          AO_LOG_FORMAT_EASYMINI1
+
+/* Beeper */
+#define AO_LPC_BEEP_TIMER      0
+#define AO_LPC_BEEP_CHANNEL    3
+#define AO_LPC_BEEP_PORT       1
+#define AO_LPC_BEEP_PIN                27
+
+/* USART */
+
+#define HAS_SERIAL             0
+#define USE_SERIAL_0_STDIN     1
+#define SERIAL_0_18_19         1
+#define SERIAL_0_14_15         0
+#define SERIAL_0_17_18         0
+#define SERIAL_0_26_27         0
+
+/* SPI */
+
+#define HAS_SPI_0              1
+#define SPI_SCK0_P0_6          1
+#define HAS_SPI_1              1
+#define SPI_SCK1_P1_20         1
+#define SPI_MISO1_P0_22                1
+#define SPI_MOSI1_P1_22                1
+
+/* M25 */
+
+#define M25_MAX_CHIPS          1
+#define AO_M25_SPI_CS_PORT     0
+#define AO_M25_SPI_CS_MASK     (1 << 23)
+#define AO_M25_SPI_BUS         1
+
+/* MS5607 */
+
+#define HAS_MS5607             1
+#define HAS_MS5611             0
+#define AO_MS5607_PRIVATE_PINS 0
+#define AO_MS5607_CS_PORT      1
+#define AO_MS5607_CS_PIN       5
+#define AO_MS5607_CS_MASK      (1 << AO_MS5607_CS_PIN)
+#define AO_MS5607_MISO_PORT    0
+#define AO_MS5607_MISO_PIN     8
+#define AO_MS5607_MISO_MASK    (1 << AO_MS5607_MISO_PIN)
+#define AO_MS5607_SPI_INDEX    0
+
+#define HAS_ACCEL              0
+#define HAS_GPS                        0
+#define HAS_RADIO              0
+#define HAS_FLIGHT             1
+#define HAS_EEPROM             1
+#define HAS_TELEMETRY          0
+#define HAS_APRS               0
+#define HAS_LOG                        1
+#define USE_INTERNAL_FLASH     0
+#define HAS_IGNITE             1
+#define HAS_IGNITE_REPORT      1
+#define SLEEP_HASH_SIZE                3
+
+#define AO_DATA_RING           16
+
+/*
+ * ADC
+ */
+
+#define HAS_ADC                        1
+
+#define AO_NUM_ADC             3
+
+#define AO_ADC_0               1
+#define AO_ADC_2               1
+#define AO_ADC_5               1
+
+struct ao_adc {
+       int16_t         sense_a;
+       int16_t         sense_m;
+       int16_t         v_batt;
+};
+
+/*
+ * Igniter
+ */
+
+#define AO_IGNITER_CLOSED      400
+#define AO_IGNITER_OPEN                60
+
+#define AO_IGNITER_DROGUE_PORT 1
+#define AO_IGNITER_DROGUE_PIN  25
+
+#define AO_IGNITER_MAIN_PORT   0
+#define AO_IGNITER_MAIN_PIN    2
+
+#define AO_SENSE_DROGUE(p)     ((p)->adc.sense_a)
+#define AO_SENSE_MAIN(p)       ((p)->adc.sense_m)
+
+#define AO_ADC_DUMP(p) \
+       printf("tick: %5lu apogee: %5d main: %5d batt: %5d\n", \
+              (p)->tick, (p)->adc.sense_a, (p)->adc.sense_m, (p)->adc.v_batt)
+
+/*
+ * 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
diff --git a/src/easymini-v3.0/flash-loader/Makefile b/src/easymini-v3.0/flash-loader/Makefile
new file mode 100644 (file)
index 0000000..96d920e
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=easymini-v3.0
+include $(TOPDIR)/lpc/Makefile-flash.defs
diff --git a/src/easymini-v3.0/flash-loader/ao_pins.h b/src/easymini-v3.0/flash-loader/ao_pins.h
new file mode 100644 (file)
index 0000000..cf827c2
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#include <ao_flash_lpc_pins.h>
+
+#define AO_BOOT_PIN            1
+#define AO_BOOT_APPLICATION_GPIO       1
+#define AO_BOOT_APPLICATION_PIN                13
+#define AO_BOOT_APPLICATION_VALUE      1
+#define AO_BOOT_APPLICATION_MODE       AO_EXTI_MODE_PULL_UP
+
+#define HAS_USB_PULLUP 1
+#define AO_USB_PULLUP_PORT     1
+#define AO_USB_PULLUP_PIN      23
+
+#endif /* _AO_PINS_H_ */
index 837fc31eed8ea6a3ecdadf274374e967e2701ce1..1faea957639ce667ad44895b60dd22bf52b893d7 100644 (file)
@@ -59,7 +59,7 @@ extern enum ao_flight_state ao_log_state;
 #define AO_LOG_FORMAT_TELESTATIC       17      /* 32 byte typed telestatic records */
 #define AO_LOG_FORMAT_MICROPEAK2       18      /* 2-byte baro values with header */
 #define AO_LOG_FORMAT_TELEMEGA_4       19      /* 32 byte typed telemega records with 32 bit gyro cal and Bmx160 */
-#define AO_LOG_FORMAT_EASYMOTOR                20      /* ? byte typed easymotor records with pressure sensor and adxl375 */
+#define AO_LOG_FORMAT_EASYMOTOR                20      /* 16 byte typed easymotor records with pressure sensor and adxl375 */
 #define AO_LOG_FORMAT_TELEMEGA_5       21      /* 32 byte typed telemega records with 32 bit gyro cal, mpu6000 and mmc5983 */
 #define AO_LOG_FORMAT_NONE             127     /* No log at all */
 
index d567f9c2a3604c0a3a073432b869bd7204d8f92e..1fd4037f540b8d0d01618b6a22672cd613bb187b 100644 (file)
@@ -636,45 +636,47 @@ ao_telemetry_set_interval(uint16_t interval)
                interval = min_interval[ao_config.radio_rate];
 #endif
        ao_telemetry_interval = interval;
+       if (interval) {
 #if AO_SEND_MEGA
-       if (interval > 1)
-               ao_telemetry_mega_data_max = 1;
-       else
-               ao_telemetry_mega_data_max = 2;
-       if (ao_telemetry_mega_data_max > cur)
-               cur++;
-       ao_telemetry_mega_data_cur = cur;
+               if (interval > 1)
+                       ao_telemetry_mega_data_max = 1;
+               else
+                       ao_telemetry_mega_data_max = 2;
+               if (ao_telemetry_mega_data_max > cur)
+                       cur++;
+               ao_telemetry_mega_data_cur = cur;
 #endif
 #if AO_SEND_METRUM
-       ao_telemetry_metrum_data_max = (int16_t) (AO_SEC_TO_TICKS(1) / interval);
-       if (ao_telemetry_metrum_data_max > cur)
-               cur++;
-       ao_telemetry_metrum_data_cur = cur;
+               ao_telemetry_metrum_data_max = (int16_t) (AO_SEC_TO_TICKS(1) / interval);
+               if (ao_telemetry_metrum_data_max > cur)
+                       cur++;
+               ao_telemetry_metrum_data_cur = cur;
 #endif
 
 #if HAS_COMPANION
-       if (!ao_companion_setup.update_period)
-               ao_companion_setup.update_period = AO_SEC_TO_TICKS(1);
-       ao_telemetry_companion_max = (int16_t) (ao_companion_setup.update_period / interval);
-       if (ao_telemetry_companion_max > cur)
-               cur++;
-       ao_telemetry_companion_cur = cur;
+               if (!ao_companion_setup.update_period)
+                       ao_companion_setup.update_period = AO_SEC_TO_TICKS(1);
+               ao_telemetry_companion_max = (int16_t) (ao_companion_setup.update_period / interval);
+               if (ao_telemetry_companion_max > cur)
+                       cur++;
+               ao_telemetry_companion_cur = cur;
 #endif
 
 #if HAS_GPS
-       ao_telemetry_gps_max = (int16_t) (AO_SEC_TO_TICKS(1) / interval);
-       if (ao_telemetry_gps_max > cur)
-               cur++;
-       ao_telemetry_loc_cur = cur;
-       if (ao_telemetry_gps_max > cur)
-               cur++;
-       ao_telemetry_sat_cur = cur;
-#endif
-
-       ao_telemetry_config_max = (int16_t) (AO_SEC_TO_TICKS(5) / interval);
-       if (ao_telemetry_config_max > cur)
-               cur++;
-       ao_telemetry_config_cur = cur;
+               ao_telemetry_gps_max = (int16_t) (AO_SEC_TO_TICKS(1) / interval);
+               if (ao_telemetry_gps_max > cur)
+                       cur++;
+               ao_telemetry_loc_cur = cur;
+               if (ao_telemetry_gps_max > cur)
+                       cur++;
+               ao_telemetry_sat_cur = cur;
+#endif
+
+               ao_telemetry_config_max = (int16_t) (AO_SEC_TO_TICKS(5) / interval);
+               if (ao_telemetry_config_max > cur)
+                       cur++;
+               ao_telemetry_config_cur = cur;
+       }
 
 #ifndef SIMPLIFY
        ao_telemetry_time = 
index c5a703c23da26fd19cb4c747534c95b6f7849fec..29d3668cedb1fdff4824dfa5ba2494610604ab81 100644 (file)
@@ -79,7 +79,7 @@ static const uint8_t  ao_adc_mask_seq[AO_ADC_NUM] = {
        1 << 4,
 #endif
 #if AO_ADC_5
-       1 << 6,
+       1 << 5,
 #endif
 #if AO_ADC_6
        1 << 6,
index ae5caa26d88b76fee2f566f2d489776b12a6d4c1..32e108cd8a974a730f0c8a3c102abafe1b872b91 100644 (file)
 
 #include "ao.h"
 
-#define _cat(a,b) a##b
-#define cat(a,b) _cat(a,b)
+#define _cat2(a,b) a##b
+#define cat2(a,b) _cat2(a,b)
 #define _cat4(a,b,c,d) a##b##c##d
 #define cat4(a,b,c,d) _cat4(a,b,c,d)
 #define _cat8(a,b,c,d,e,f,g,h) a##b##c##d##e##f##g##h
 #define cat8(a,b,c,d,e,f,g,h) _cat8(a,b,c,d,e,f,g,h)
 
-#define AO_TIMER_CLKCTRL       cat(LPC_SCB_SYSAHBCLKCTRL_CT32B, BEEPER_TIMER)
-#define AO_TIMER               cat(lpc_ct32b, BEEPER_TIMER)
-#define AO_TIMER_EMC           cat(LPC_CT32B_EMR_EMC, BEEPER_OUTPUT)
-#define AO_TIMER_PIO           cat4(pio, BEEPER_PORT, _, BEEPER_PIN)
-/* LPC_IOCONF_FUNC_PIO0_14_CT32B1_MAT1 */
-#define AO_TIMER_FUNC          cat8(LPC_IOCONF_FUNC_PIO, BEEPER_PORT, _, BEEPER_PIN, _CT32B, BEEPER_TIMER, _MAT, BEEPER_OUTPUT)
-#define AO_TIMER_PWM           cat(LPC_CT32B_PWMC_PWMEN, BEEPER_OUTPUT)
+#ifndef AO_LPC_BEEP_TIMER
+#define AO_LPC_BEEP_TIMER 1
+#define AO_LPC_BEEP_CHANNEL 1
+#define AO_LPC_BEEP_PORT       0
+#define AO_LPC_BEEP_PIN                14
+#endif
+
+#define AO_LPC_CT_BEEP                 cat2(lpc_ct32b, AO_LPC_BEEP_TIMER)
+#define AO_LPC_CT_BEEP_CLKCTRL cat2(LPC_SCB_SYSAHBCLKCTRL_CT32B, AO_LPC_BEEP_TIMER)
+#define AO_LPC_CT_BEEP_EMR     cat2(LPC_CT32B_EMR_EMC, AO_LPC_BEEP_CHANNEL)
+#define AO_LPC_CT_BEEP_MR      AO_LPC_BEEP_CHANNEL
+#define AO_LPC_CT_BEEP_PWMC    cat2(LPC_CT32B_PWMC_PWMEN, AO_LPC_BEEP_CHANNEL)
+#define AO_LPC_CT_BEEP_IOCONF  cat4(pio,AO_LPC_BEEP_PORT,_,AO_LPC_BEEP_PIN)
+#define AO_LPC_CT_BEEP_FUNC    cat8(LPC_IOCONF_FUNC_PIO,AO_LPC_BEEP_PORT,_,AO_LPC_BEEP_PIN,_CT32B,AO_LPC_BEEP_TIMER,_MAT,AO_LPC_BEEP_CHANNEL)
 
 void
 ao_beep(uint8_t beep)
 {
        if (beep == 0) {
-               AO_TIMER.tcr = ((0 << LPC_CT32B_TCR_CEN) |
+               AO_LPC_CT_BEEP.tcr = ((0 << LPC_CT32B_TCR_CEN) |
                                  (1 << LPC_CT32B_TCR_CRST));
-               lpc_scb.sysahbclkctrl &= ~(1UL << AO_TIMER_CLKCTRL);
+               lpc_scb.sysahbclkctrl &= ~(1UL << AO_LPC_CT_BEEP_CLKCTRL);
        } else {
-               lpc_scb.sysahbclkctrl |= (1 << AO_TIMER_CLKCTRL);
+               lpc_scb.sysahbclkctrl |= (1UL << AO_LPC_CT_BEEP_CLKCTRL);
 
                /* Set prescaler to match cc1111 clocks
                 */
-               AO_TIMER.pr = AO_LPC_SYSCLK / 750000 - 1;
+               AO_LPC_CT_BEEP.pr = AO_LPC_SYSCLK / 750000 - 1;
 
                /* Write the desired data in the match registers */
 
                /* Reset after two time units */
-               AO_TIMER.mr[0] = beep << 1;
+               AO_LPC_CT_BEEP.mr[0] = beep << 1;
 
                /* PWM width is half of that */
-               AO_TIMER.mr[BEEPER_OUTPUT] = beep;
+               AO_LPC_CT_BEEP.mr[AO_LPC_CT_BEEP_MR] = beep;
 
                /* Flip output on PWM match */
-               AO_TIMER.emr = (LPC_CT32B_EMR_EMC_TOGGLE << AO_TIMER_EMC);
+               AO_LPC_CT_BEEP.emr = (LPC_CT32B_EMR_EMC_TOGGLE << AO_LPC_CT_BEEP_EMR);
 
                /* Reset on match 0 */
-               AO_TIMER.mcr = (1 << LPC_CT32B_MCR_MR0R);
+               AO_LPC_CT_BEEP.mcr = (1 << LPC_CT32B_MCR_MR0R);
 
                /* PWM on match */
-               AO_TIMER.pwmc = (1 << AO_TIMER_PWM);
+               AO_LPC_CT_BEEP.pwmc = (1 << AO_LPC_CT_BEEP_PWMC);
 
                /* timer mode */
-               AO_TIMER.ctcr = 0;
+               AO_LPC_CT_BEEP.ctcr = 0;
 
                /* And turn the timer on */
-               AO_TIMER.tcr = ((1 << LPC_CT32B_TCR_CEN) |
+               AO_LPC_CT_BEEP.tcr = ((1 << LPC_CT32B_TCR_CEN) |
                                  (0 << LPC_CT32B_TCR_CRST));
        }
 }
@@ -84,10 +91,20 @@ ao_beep_for(uint8_t beep, AO_TICK_TYPE ticks)
 void
 ao_beep_init(void)
 {
-       lpc_ioconf.AO_TIMER_PIO = ((AO_TIMER_FUNC << LPC_IOCONF_FUNC) |
+       /* Our beeper is on c32b1_mat1
+        * which is on pin pio0_14
+        */
+
+       lpc_ioconf.AO_LPC_CT_BEEP_IOCONF = ((AO_LPC_CT_BEEP_FUNC << LPC_IOCONF_FUNC) |
                              (LPC_IOCONF_MODE_INACTIVE << LPC_IOCONF_MODE) |
                              (0 << LPC_IOCONF_HYS) |
                              (0 << LPC_IOCONF_INV) |
                              (1 << LPC_IOCONF_ADMODE) |
                              (0 << LPC_IOCONF_OD));
+
+       lpc_scb.sysahbclkctrl |= (1 << AO_LPC_CT_BEEP_CLKCTRL);
+
+       /* Disable the counter and reset the value */
+       AO_LPC_CT_BEEP.tcr = ((0 << LPC_CT32B_TCR_CEN) |
+                         (1 << LPC_CT32B_TCR_CRST));
 }