From: Bdale Garbee Date: Tue, 16 Jun 2020 02:26:35 +0000 (-0600) Subject: Merge branch 'master' into branch-1.9 X-Git-Tag: 1.9.3~1 X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=f31d842d0e07a1893441cb89fb287b31b86d28c1;hp=0fd503fb65d513f54dade10256545043725d83e3;p=fw%2Faltos Merge branch 'master' into branch-1.9 --- diff --git a/Makefile.am b/Makefile.am index a62d539a..fcf2652c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 \ diff --git a/Releasing b/Releasing index 4f649b6e..223a14d3 100644 --- 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 \ diff --git a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosUsb.java b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosUsb.java index c2ef8a70..35514483 100644 --- a/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosUsb.java +++ b/altosdroid/app/src/main/java/org/altusmetrum/AltosDroid/AltosUsb.java @@ -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; diff --git a/altoslib/AltosConfigData.java b/altoslib/AltosConfigData.java index 474af359..5d58566e 100644 --- a/altoslib/AltosConfigData.java +++ b/altoslib/AltosConfigData.java @@ -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) diff --git a/altoslib/AltosConfigValues.java b/altoslib/AltosConfigValues.java index b12a610c..8fa3fa41 100644 --- a/altoslib/AltosConfigValues.java +++ b/altoslib/AltosConfigValues.java @@ -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); diff --git a/altoslib/AltosConvert.java b/altoslib/AltosConvert.java index 63cdfa60..83299632 100644 --- a/altoslib/AltosConvert.java +++ b/altoslib/AltosConvert.java @@ -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; } diff --git a/altoslib/AltosEepromList.java b/altoslib/AltosEepromList.java index 1abc638b..0d15fa5a 100644 --- a/altoslib/AltosEepromList.java +++ b/altoslib/AltosEepromList.java @@ -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 { if (remote) link.start_remote(); config_data = new AltosConfigData (link); -// if (config_data.serial == 0) -// throw new IOException("no serial number found"); - - ArrayList flights = new ArrayList(); - - 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) diff --git a/altoslib/AltosIMU.java b/altoslib/AltosIMU.java index 87b9f08b..7f8be403 100644 --- a/altoslib/AltosIMU.java +++ b/altoslib/AltosIMU.java @@ -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; diff --git a/altoslib/AltosIdleFetch.java b/altoslib/AltosIdleFetch.java index 2a36983f..ca3e33eb 100644 --- a/altoslib/AltosIdleFetch.java +++ b/altoslib/AltosIdleFetch.java @@ -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; diff --git a/altoslib/AltosJson.java b/altoslib/AltosJson.java index cbeeee87..1c3a342d 100644 --- a/altoslib/AltosJson.java +++ b/altoslib/AltosJson.java @@ -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); diff --git a/altoslib/AltosLib.java b/altoslib/AltosLib.java index 14cec543..a7f27830 100644 --- a/altoslib/AltosLib.java +++ b/altoslib/AltosLib.java @@ -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"; diff --git a/altoslib/AltosMma655x.java b/altoslib/AltosMma655x.java index c009b820..1a730c11 100644 --- a/altoslib/AltosMma655x.java +++ b/altoslib/AltosMma655x.java @@ -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)); } diff --git a/altoslib/AltosRotation.java b/altoslib/AltosRotation.java index 7bcea487..85e213b2 100644 --- a/altoslib/AltosRotation.java +++ b/altoslib/AltosRotation.java @@ -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 index 00000000..dcf76928 --- /dev/null +++ b/altoslib/AltosSensorEasyTimer1.java @@ -0,0 +1,77 @@ +/* + * Copyright © 2020 Keith Packard + * + * 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) { + } + } +} + diff --git a/altoslib/AltosState.java b/altoslib/AltosState.java index e3ea0524..fc972748 100644 --- a/altoslib/AltosState.java +++ b/altoslib/AltosState.java @@ -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(); diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am index b7d30051..0c9392d1 100644 --- a/altoslib/Makefile.am +++ b/altoslib/Makefile.am @@ -105,6 +105,7 @@ altoslib_JAVA = \ AltosUsbId.java \ AltosSensorMM.java \ AltosSensorEMini.java \ + AltosSensorEasyTimer1.java \ AltosSensorTM.java \ AltosSensorTMini2.java \ AltosSensorTMini3.java \ diff --git a/altosui/AltosConfigFC.java b/altosui/AltosConfigFC.java index 66afd8a0..20ca311e 100644 --- a/altosui/AltosConfigFC.java +++ b/altosui/AltosConfigFC.java @@ -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(), diff --git a/altosui/AltosConfigFCUI.java b/altosui/AltosConfigFCUI.java index 624c7246..8df3c022 100644 --- a/altosui/AltosConfigFCUI.java +++ b/altosui/AltosConfigFCUI.java @@ -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 aprs_interval_value; JComboBox aprs_ssid_value; JComboBox aprs_format_value; + JComboBox aprs_offset_value; JComboBox flight_log_max_value; JComboBox ignite_mode_value; JComboBox 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(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(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; + } } diff --git a/altosui/AltosPad.java b/altosui/AltosPad.java index 004bd534..e9bb4e41 100644 --- a/altosui/AltosPad.java +++ b/altosui/AltosPad.java @@ -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(); diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 4bf3db12..b172b022 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -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 diff --git a/altosui/altos-windows.nsi.in b/altosui/altos-windows.nsi.in index 9fbc845c..fa803c5f 100644 --- a/altosui/altos-windows.nsi.in +++ b/altosui/altos-windows.nsi.in @@ -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 diff --git a/altosuilib/AltosEepromDelete.java b/altosuilib/AltosEepromDelete.java index ff1b15c8..214ae530 100644 --- a/altosuilib/AltosEepromDelete.java +++ b/altosuilib/AltosEepromDelete.java @@ -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); } diff --git a/altosuilib/AltosFlashUI.java b/altosuilib/AltosFlashUI.java index e61b3973..fd84f921 100644 --- a/altosuilib/AltosFlashUI.java +++ b/altosuilib/AltosFlashUI.java @@ -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() { diff --git a/altosuilib/AltosInfoTable.java b/altosuilib/AltosInfoTable.java index e20a516c..226f112f 100644 --- a/altosuilib/AltosInfoTable.java +++ b/altosuilib/AltosInfoTable.java @@ -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", diff --git a/altosuilib/AltosUSBDevice.java b/altosuilib/AltosUSBDevice.java index 349cd3ce..50ec4c03 100644 --- a/altosuilib/AltosUSBDevice.java +++ b/altosuilib/AltosUSBDevice.java @@ -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 || diff --git a/ao-bringup/turnon_telemetrum_v2.0 b/ao-bringup/turnon_telemetrum_v2.0 index dd30378a..e2d2f532 100755 --- a/ao-bringup/turnon_telemetrum_v2.0 +++ b/ao-bringup/turnon_telemetrum_v2.0 @@ -76,6 +76,6 @@ done echo 'E 1' > $dev -./test-telemetrum +./test-telemetrum-v2.0 exit $? diff --git a/ao-tools/ao-usbload/ao-usbload.1 b/ao-tools/ao-usbload/ao-usbload.1 index 48165921..aa11bea5 100644 --- a/ao-tools/ao-usbload/ao-usbload.1 +++ b/ao-tools/ao-usbload/ao-usbload.1 @@ -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 diff --git a/ao-tools/lib/ao-editaltos.c b/ao-tools/lib/ao-editaltos.c index a51b7dbe..602390e3 100644 --- a/ao-tools/lib/ao-editaltos.c +++ b/ao-tools/lib/ao-editaltos.c @@ -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; } diff --git a/ao-tools/lib/ao-verbose.h b/ao-tools/lib/ao-verbose.h index d23e720c..79fbb0d9 100644 --- a/ao-tools/lib/ao-verbose.h +++ b/ao-tools/lib/ao-verbose.h @@ -22,7 +22,7 @@ #include #include -uint32_t ao_verbose; +extern uint32_t ao_verbose; #define AO_VERBOSE_EXE 1 #define AO_VERBOSE_SELF 2 diff --git a/configure.ac b/configure.ac index 74a96a40..ca5262b5 100644 --- a/configure.ac +++ b/configure.ac @@ -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}" diff --git a/doc/Makefile.am b/doc/Makefile.am index 464cd988..acb223ca 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -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 \ diff --git a/doc/altosui.inc b/doc/altosui.inc index d497ad2f..a0aab0bd 100644 --- a/doc/altosui.inc +++ b/doc/altosui.inc @@ -633,14 +633,14 @@ 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 diff --git a/doc/altusmetrum.txt b/doc/altusmetrum.txt index 60163888..c2492b0f 100644 --- a/doc/altusmetrum.txt +++ b/doc/altusmetrum.txt @@ -20,6 +20,7 @@ Keith Packard ; Bdale Garbee ; Bob Finch; Anth :telemega: 1 :easymega: 1 :telegps: 1 +:easytimer: 1 :application: AltosUI :pdf-stylesdir: . :pdf-style: altusmetrum @@ -45,6 +46,8 @@ Keith Packard ; Bdale Garbee ; Bob Finch; Anth include::easymega.adoc[] + include::easytimer.adoc[] + include::installation.adoc[] include::using-am-products.adoc[] diff --git a/doc/aprs-operation.inc b/doc/aprs-operation.inc index 09f929d0..d0e38266 100644 --- a/doc/aprs-operation.inc +++ b/doc/aprs-operation.inc @@ -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 diff --git a/doc/config-device.inc b/doc/config-device.inc index 5e3bdbf0..15f9129e 100644 --- a/doc/config-device.inc +++ b/doc/config-device.inc @@ -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[] diff --git a/doc/configure-altimeter.png b/doc/configure-altimeter.png index 09a83d16..73c3dc33 100644 Binary files a/doc/configure-altimeter.png and b/doc/configure-altimeter.png differ diff --git a/doc/easymega.inc b/doc/easymega.inc index 506f4c5f..e7351c07 100644 --- a/doc/easymega.inc +++ b/doc/easymega.inc @@ -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, @@ -36,24 +36,24 @@ |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 @@ -72,24 +72,24 @@ |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 diff --git a/doc/easymini-device.inc b/doc/easymini-device.inc index d82a2607..841f7a3e 100644 --- a/doc/easymini-device.inc +++ b/doc/easymini-device.inc @@ -31,11 +31,11 @@ |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 diff --git a/doc/easymini-release-notes.inc b/doc/easymini-release-notes.inc index 6fc6f035..53af8597 100644 --- a/doc/easymini-release-notes.inc +++ b/doc/easymini-release-notes.inc @@ -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 index 00000000..82689d20 --- /dev/null +++ b/doc/easytimer.inc @@ -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 index 00000000..703e9a14 Binary files /dev/null and b/doc/easytimer.jpg differ diff --git a/doc/getting-started.inc b/doc/getting-started.inc index 5e60986a..bf6cbda8 100644 --- a/doc/getting-started.inc +++ b/doc/getting-started.inc @@ -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 diff --git a/doc/pyro-channels.inc b/doc/pyro-channels.inc index ab5baef0..1daf2f6e 100644 --- a/doc/pyro-channels.inc +++ b/doc/pyro-channels.inc @@ -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 index 00000000..3ae9102d --- /dev/null +++ b/doc/release-notes-1.9.3.inc @@ -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. diff --git a/doc/release-notes.inc b/doc/release-notes.inc index dc3df120..042059bc 100644 --- a/doc/release-notes.inc +++ b/doc/release-notes.inc @@ -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[] diff --git a/doc/specs.inc b/doc/specs.inc index b69d52ee..5c2c83cc 100644 --- a/doc/specs.inc +++ b/doc/specs.inc @@ -154,6 +154,18 @@ |3.7V endif::easymega[] + ifdef::easytimer[] + |EasyTimer v1.0 + |- + |16g + |- + |BMX160 + |- + |- + |3.7-12V + endif::easytimer[] + + |=== <<<< @@ -214,4 +226,13 @@ |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[] + |=== diff --git a/doc/system-operation.inc b/doc/system-operation.inc index 6cc9986b..888e3891 100644 --- a/doc/system-operation.inc +++ b/doc/system-operation.inc @@ -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 diff --git a/doc/telegps-configure.png b/doc/telegps-configure.png index 56cb2031..4bc052f3 100644 Binary files a/doc/telegps-configure.png and b/doc/telegps-configure.png differ diff --git a/doc/telegps-release-notes.inc b/doc/telegps-release-notes.inc index af631702..c0a258f1 100644 --- a/doc/telegps-release-notes.inc +++ b/doc/telegps-release-notes.inc @@ -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[] diff --git a/doc/telemega.inc b/doc/telemega.inc index 092077e0..ef701e46 100644 --- a/doc/telemega.inc +++ b/doc/telemega.inc @@ -48,24 +48,24 @@ |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 @@ -84,24 +84,24 @@ |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 diff --git a/doc/telemetrum.inc b/doc/telemetrum.inc index 7ef9876f..fdb961d7 100644 --- a/doc/telemetrum.inc +++ b/doc/telemetrum.inc @@ -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 |=== diff --git a/doc/telemini.inc b/doc/telemini.inc index 03732b2a..7dd04bf0 100644 --- a/doc/telemini.inc +++ b/doc/telemini.inc @@ -38,16 +38,16 @@ |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 diff --git a/doc/updating-firmware.inc b/doc/updating-firmware.inc index b1047ffa..1999a9c7 100644 --- a/doc/updating-firmware.inc +++ b/doc/updating-firmware.inc @@ -105,6 +105,16 @@ 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:: diff --git a/doc/usage.inc b/doc/usage.inc index 68d08bad..4e40240b 100644 --- a/doc/usage.inc +++ b/doc/usage.inc @@ -167,15 +167,15 @@ 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[] |==== @@ -249,14 +249,14 @@ 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 @@ -315,21 +315,22 @@ === 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 diff --git a/doc/using-am-products.inc b/doc/using-am-products.inc index 1c1ff10e..6048ee0e 100644 --- a/doc/using-am-products.inc +++ b/doc/using-am-products.inc @@ -17,11 +17,11 @@ 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 diff --git a/map-server/altos-mapd/.gitignore b/map-server/altos-mapd/.gitignore index 5f5ce0ae..723964ba 100644 --- a/map-server/altos-mapd/.gitignore +++ b/map-server/altos-mapd/.gitignore @@ -4,3 +4,4 @@ altos-mapd altos-mapd-jdb altos-mapd-test classes +Manifest.txt diff --git a/map-server/altos-mapd/Makefile.am b/map-server/altos-mapd/Makefile.am index bb20dd84..f92c3e5a 100644 --- a/map-server/altos-mapd/Makefile.am +++ b/map-server/altos-mapd/Makefile.am @@ -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 index 42c0313b..00000000 --- a/map-server/altos-mapd/Manifest.txt +++ /dev/null @@ -1,2 +0,0 @@ -Main-Class: altosmapd.AltosMapd -Class-Path: altoslib_13.jar diff --git a/map-server/altos-mapj/.gitignore b/map-server/altos-mapj/.gitignore index c5d593e6..b223755f 100644 --- a/map-server/altos-mapj/.gitignore +++ b/map-server/altos-mapj/.gitignore @@ -4,3 +4,5 @@ altos-mapj-test *.jar *.stamp classes +Manifest.txt +Manifest-fat.txt diff --git a/map-server/altos-mapj/Makefile.am b/map-server/altos-mapj/Makefile.am index a8dfffec..0c823d03 100644 --- a/map-server/altos-mapj/Makefile.am +++ b/map-server/altos-mapj/Makefile.am @@ -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 index 1a285b40..00000000 --- a/map-server/altos-mapj/Manifest.txt +++ /dev/null @@ -1,2 +0,0 @@ -Main-Class: altosmap.AltosMap -Class-Path: altoslib_13.jar diff --git a/src/.gitignore b/src/.gitignore index aad18d4c..d1308eae 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -3,3 +3,4 @@ altitude.h altitude-pa.h altitude-pa-small.h ao_whiten.h +*.map diff --git a/src/Makedefs.in b/src/Makedefs.in index b5639f73..9543e329 100644 --- a/src/Makedefs.in +++ b/src/Makedefs.in @@ -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@ diff --git a/src/Makefile b/src/Makefile index 3f5c1973..7d683d8c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -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 \ diff --git a/src/Makefile.defs b/src/Makefile.defs index d52cc706..897f7ac1 100644 --- a/src/Makefile.defs +++ b/src/Makefile.defs @@ -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 \ diff --git a/src/drivers/ao_adxl375.c b/src/drivers/ao_adxl375.c index 4f6b8169..dca2213b 100644 --- a/src/drivers/ao_adxl375.c +++ b/src/drivers/ao_adxl375.c @@ -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[] = { diff --git a/src/drivers/ao_aprs.c b/src/drivers/ao_aprs.c index bc5c29df..826985c6 100644 --- a/src/drivers/ao_aprs.c +++ b/src/drivers/ao_aprs.c @@ -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 diff --git a/src/drivers/ao_bmx160.h b/src/drivers/ao_bmx160.h index 9fc33341..c5bf0aff 100644 --- a/src/drivers/ao_bmx160.h +++ b/src/drivers/ao_bmx160.h @@ -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_ */ diff --git a/src/drivers/ao_gps_ublox.c b/src/drivers/ao_gps_ublox.c index a6d93083..89b1c4d2 100644 --- a/src/drivers/ao_gps_ublox.c +++ b/src/drivers/ao_gps_ublox.c @@ -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; diff --git a/src/drivers/ao_lco.c b/src/drivers/ao_lco.c index 0d7e4cba..2cb885cf 100644 --- a/src/drivers/ao_lco.c +++ b/src/drivers/ao_lco.c @@ -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) { diff --git a/src/drivers/ao_lco.h b/src/drivers/ao_lco.h index 3b123793..452092a0 100644 --- a/src/drivers/ao_lco.h +++ b/src/drivers/ao_lco.h @@ -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 diff --git a/src/drivers/ao_lco_bits.c b/src/drivers/ao_lco_bits.c index bc54dc22..b97662a0 100644 --- a/src/drivers/ao_lco_bits.c +++ b/src/drivers/ao_lco_bits.c @@ -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) { diff --git a/src/drivers/ao_lco_two.c b/src/drivers/ao_lco_two.c index cfef2a63..8d4476ef 100644 --- a/src/drivers/ao_lco_two.c +++ b/src/drivers/ao_lco_two.c @@ -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) { diff --git a/src/drivers/ao_m25.c b/src/drivers/ao_m25.c index 72617cc4..ca0615e7 100644 --- a/src/drivers/ao_m25.c +++ b/src/drivers/ao_m25.c @@ -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; diff --git a/src/drivers/ao_mma655x.c b/src/drivers/ao_mma655x.c index b0217368..4c24e98b 100644 --- a/src/drivers/ao_mma655x.c +++ b/src/drivers/ao_mma655x.c @@ -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 diff --git a/src/drivers/ao_mpu9250.c b/src/drivers/ao_mpu9250.c index 1b31edf4..0597a81c 100644 --- a/src/drivers/ao_mpu9250.c +++ b/src/drivers/ao_mpu9250.c @@ -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]); diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c index 07c49afc..f5c51c8b 100644 --- a/src/drivers/ao_pad.c +++ b/src/drivers/ao_pad.c @@ -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"); diff --git a/src/drivers/ao_quadrature.c b/src/drivers/ao_quadrature.c index a5fbd1da..97e67aa0 100644 --- a/src/drivers/ao_quadrature.c +++ b/src/drivers/ao_quadrature.c @@ -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 index 00000000..2e32c6ff --- /dev/null +++ b/src/easytimer-v1/.gitignore @@ -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 index 00000000..b0cd15c2 --- /dev/null +++ b/src/easytimer-v1/Makefile @@ -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 index 00000000..8224ee06 --- /dev/null +++ b/src/easytimer-v1/ao_easytimer.c @@ -0,0 +1,79 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#if HAS_SAMPLE_PROFILE +#include +#endif +#if HAS_STACK_GUARD +#include +#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 index 00000000..3ceb49f3 --- /dev/null +++ b/src/easytimer-v1/ao_pins.h @@ -0,0 +1,242 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 index 00000000..a1613645 --- /dev/null +++ b/src/easytimer-v1/flash-loader/Makefile @@ -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 index 00000000..16aeec29 --- /dev/null +++ b/src/easytimer-v1/flash-loader/ao_pins.h @@ -0,0 +1,35 @@ +/* + * Copyright © 2020 Keith Packard + * + * 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 + +/* 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_ */ diff --git a/src/kernel/ao_cmd.c b/src/kernel/ao_cmd.c index d1c049ac..9bc19038 100644 --- a/src/kernel/ao_cmd.c +++ b/src/kernel/ao_cmd.c @@ -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 diff --git a/src/kernel/ao_config.c b/src/kernel/ao_config.c index 9f329f17..217b0ab1 100644 --- a/src/kernel/ao_config.c +++ b/src/kernel/ao_config.c @@ -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 \0Main deploy (m)", ao_config_main_deploy_set, ao_config_main_deploy_show, }, { "d \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 \0APRS Offset from top of minute", + ao_config_aprs_offset_set, ao_config_aprs_offset_show }, #endif #if HAS_FIXED_PAD_BOX { "B \0Set pad box (1-99)", diff --git a/src/kernel/ao_config.h b/src/kernel/ao_config.h index 41aafcca..87509dff 100644 --- a/src/kernel/ao_config.h +++ b/src/kernel/ao_config.h @@ -38,7 +38,7 @@ #include #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 diff --git a/src/kernel/ao_data.c b/src/kernel/ao_data.c index 536ffa2b..77cd98e4 100644 --- a/src/kernel/ao_data.c +++ b/src/kernel/ao_data.c @@ -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 diff --git a/src/kernel/ao_data.h b/src/kernel/ao_data.h index 988ac489..b43a1cd4 100644 --- a/src/kernel/ao_data.h +++ b/src/kernel/ao_data.h @@ -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_ */ diff --git a/src/kernel/ao_eeprom.h b/src/kernel/ao_eeprom.h index f258c48c..5f6adb0e 100644 --- a/src/kernel/ao_eeprom.h +++ b/src/kernel/ao_eeprom.h @@ -19,8 +19,6 @@ #ifndef _AO_EEPROM_H_ #define _AO_EEPROM_H_ -extern const ao_pos_t ao_eeprom_total; - /* * Write to eeprom */ diff --git a/src/kernel/ao_flight.c b/src/kernel/ao_flight.c index 5a5d5b72..c5069158 100644 --- a/src/kernel/ao_flight.c +++ b/src/kernel/ao_flight.c @@ -21,6 +21,8 @@ #include #endif +#include + #if HAS_MPU6000 || HAS_MPU9250 #include #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 diff --git a/src/kernel/ao_ignite.c b/src/kernel/ao_ignite.c index e9d04dcc..71c99a61 100644 --- a/src/kernel/ao_ignite.c +++ b/src/kernel/ao_ignite.c @@ -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 } diff --git a/src/kernel/ao_kalman.c b/src/kernel/ao_kalman.c index 4f4ffe8f..aaf0595f 100644 --- a/src/kernel/ao_kalman.c +++ b/src/kernel/ao_kalman.c @@ -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; diff --git a/src/kernel/ao_log.c b/src/kernel/ao_log.c index c0a42b29..f0816aee 100644 --- a/src/kernel/ao_log.c +++ b/src/kernel/ao_log.c @@ -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; } } diff --git a/src/kernel/ao_log.h b/src/kernel/ao_log.h index 1c0ba4e3..8fe8b701 100644 --- a/src/kernel/ao_log.h +++ b/src/kernel/ao_log.h @@ -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); diff --git a/src/kernel/ao_log_gps.c b/src/kernel/ao_log_gps.c index 7284932c..bf326c1a 100644 --- a/src/kernel/ao_log_gps.c +++ b/src/kernel/ao_log_gps.c @@ -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; diff --git a/src/kernel/ao_log_telestatic.c b/src/kernel/ao_log_telestatic.c index fdf8da43..0829bcbb 100644 --- a/src/kernel/ao_log_telestatic.c +++ b/src/kernel/ao_log_telestatic.c @@ -21,7 +21,7 @@ #include #include -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); } diff --git a/src/kernel/ao_product.c b/src/kernel/ao_product.c index 72488654..eaa6c78b 100644 --- a/src/kernel/ao_product.c +++ b/src/kernel/ao_product.c @@ -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, diff --git a/src/kernel/ao_report.c b/src/kernel/ao_report.c index 12c3a1e9..26604d1a 100644 --- a/src/kernel/ao_report.c +++ b/src/kernel/ao_report.c @@ -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); diff --git a/src/kernel/ao_sample.c b/src/kernel/ao_sample.c index 9cba36c1..67f20aff 100644 --- a/src/kernel/ao_sample.c +++ b/src/kernel/ao_sample.c @@ -36,9 +36,11 @@ #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; diff --git a/src/kernel/ao_storage.c b/src/kernel/ao_storage.c index cfd116f9..73b31c64 100644 --- a/src/kernel/ao_storage.c +++ b/src/kernel/ao_storage.c @@ -19,8 +19,12 @@ #include #include +#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 \0Erase all. is doit with D&I" }, #if AO_STORAGE_TEST { ao_storage_test, "V \0Validate flash (destructive). is doit with D&I" }, + { ao_storage_fill, "F \0Fill flash with data. is doit with D&I" }, #endif { 0, NULL }, }; diff --git a/src/kernel/ao_storage.h b/src/kernel/ao_storage.h index cf37a824..1c5867e0 100644 --- a/src/kernel/ao_storage.h +++ b/src/kernel/ao_storage.h @@ -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); diff --git a/src/kernel/ao_telemetry.c b/src/kernel/ao_telemetry.c index 2092c84f..c2b2eb5a 100644 --- a/src/kernel/ao_telemetry.c +++ b/src/kernel/ao_telemetry.c @@ -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) diff --git a/src/kernel/ao_tracker.c b/src/kernel/ao_tracker.c index 1454c17c..0f249103 100644 --- a/src/kernel/ao_tracker.c +++ b/src/kernel/ao_tracker.c @@ -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)) { diff --git a/src/lpc/Makefile-flash.defs b/src/lpc/Makefile-flash.defs index 44b43bfe..1ae94c15 100644 --- a/src/lpc/Makefile-flash.defs +++ b/src/lpc/Makefile-flash.defs @@ -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 diff --git a/src/lpc/Makefile-lpc.defs b/src/lpc/Makefile-lpc.defs index 8b297351..48153da3 100644 --- a/src/lpc/Makefile-lpc.defs +++ b/src/lpc/Makefile-lpc.defs @@ -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) diff --git a/src/lpc/Makefile.defs b/src/lpc/Makefile.defs index 7fdcf0dc..7ea76e1c 100644 --- a/src/lpc/Makefile.defs +++ b/src/lpc/Makefile.defs @@ -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` > $@ diff --git a/src/lpc/altos-loader.ld b/src/lpc/altos-loader.ld index be4f115d..75b527fb 100644 --- a/src/lpc/altos-loader.ld +++ b/src/lpc/altos-loader.ld @@ -16,66 +16,11 @@ * 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 diff --git a/src/lpc/altos.ld b/src/lpc/altos.ld index 028ad775..3e015730 100644 --- a/src/lpc/altos.ld +++ b/src/lpc/altos.ld @@ -16,76 +16,11 @@ * 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 diff --git a/src/lpc/ao_arch.h b/src/lpc/ao_arch.h index 93676b86..c638aa22 100644 --- a/src/lpc/ao_arch.h +++ b/src/lpc/ao_arch.h @@ -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") diff --git a/src/lpc/ao_boot_chain.c b/src/lpc/ao_boot_chain.c index 0d0bb91c..0cb92a52 100644 --- a/src/lpc/ao_boot_chain.c +++ b/src/lpc/ao_boot_chain.c @@ -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) diff --git a/src/lpc/ao_interrupt.c b/src/lpc/ao_interrupt.c index a479ec6d..bc2848c3 100644 --- a/src/lpc/ao_interrupt.c +++ b/src/lpc/ao_interrupt.c @@ -29,15 +29,6 @@ #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(); +} diff --git a/src/lpc/ao_usb_lpc.c b/src/lpc/ao_usb_lpc.c index d6763c29..9e94de12 100644 --- a/src/lpc/ao_usb_lpc.c +++ b/src/lpc/ao_usb_lpc.c @@ -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. diff --git a/src/lpc/lpc.h b/src/lpc/lpc.h index 56b85230..82f45652 100644 --- a/src/lpc/lpc.h +++ b/src/lpc/lpc.h @@ -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 diff --git a/src/micropeak-v2.0/Makefile b/src/micropeak-v2.0/Makefile index f1f57440..5949ec09 100644 --- a/src/micropeak-v2.0/Makefile +++ b/src/micropeak-v2.0/Makefile @@ -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 diff --git a/src/micropeak-v2.0/ao_micropeak.c b/src/micropeak-v2.0/ao_micropeak.c index f3fbc9f4..a4de4854 100644 --- a/src/micropeak-v2.0/ao_micropeak.c +++ b/src/micropeak-v2.0/ao_micropeak.c @@ -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"); } diff --git a/src/micropeak-v2.0/micropeak.ld b/src/micropeak-v2.0/micropeak.ld index a73d4c1d..b4e06a87 100644 --- a/src/micropeak-v2.0/micropeak.ld +++ b/src/micropeak-v2.0/micropeak.ld @@ -16,108 +16,13 @@ * 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 diff --git a/src/pnpservo-v1/lambda.ld b/src/pnpservo-v1/lambda.ld index d3edbe9f..20b3ace7 100644 --- a/src/pnpservo-v1/lambda.ld +++ b/src/pnpservo-v1/lambda.ld @@ -87,7 +87,7 @@ SECTIONS { .textram BLOCK(8): { _start__ = .; __text_ram_start__ = .; - *(.ramtext) + *(.srodata) __text_ram_end = .; } >ram AT>rom diff --git a/src/stm/Makefile-flash.defs b/src/stm/Makefile-flash.defs index 08a4b177..4a386431 100644 --- a/src/stm/Makefile-flash.defs +++ b/src/stm/Makefile-flash.defs @@ -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) diff --git a/src/stm/Makefile-stm.defs b/src/stm/Makefile-stm.defs index cce28f00..f3fd9de6 100644 --- a/src/stm/Makefile-stm.defs +++ b/src/stm/Makefile-stm.defs @@ -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) diff --git a/src/stm/Makefile.defs b/src/stm/Makefile.defs index 26ba5824..d6cbe4d4 100644 --- a/src/stm/Makefile.defs +++ b/src/stm/Makefile.defs @@ -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 diff --git a/src/stm/altos-loader.ld b/src/stm/altos-loader.ld index 1ebbc7a2..5ef09cd2 100644 --- a/src/stm/altos-loader.ld +++ b/src/stm/altos-loader.ld @@ -16,81 +16,11 @@ * 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 diff --git a/src/stm/altos.ld b/src/stm/altos.ld index e352ed36..9638bb67 100644 --- a/src/stm/altos.ld +++ b/src/stm/altos.ld @@ -16,83 +16,11 @@ * 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 diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index e83b6bd2..e3094c6a 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -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 diff --git a/src/stm/ao_boot_chain.c b/src/stm/ao_boot_chain.c index 488af1e1..d91afdab 100644 --- a/src/stm/ao_boot_chain.c +++ b/src/stm/ao_boot_chain.c @@ -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) { diff --git a/src/stm/ao_eeprom_stm.c b/src/stm/ao_eeprom_stm.c index d3e3338d..db4d6a49 100644 --- a/src/stm/ao_eeprom_stm.c +++ b/src/stm/ao_eeprom_stm.c @@ -20,7 +20,7 @@ #include /* 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) diff --git a/src/stm/ao_flash_stm.c b/src/stm/ao_flash_stm.c index 38618bbe..77296c32 100644 --- a/src/stm/ao_flash_stm.c +++ b/src/stm/ao_flash_stm.c @@ -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; diff --git a/src/stm/ao_interrupt.c b/src/stm/ao_interrupt.c index 1d563532..9a059187 100644 --- a/src/stm/ao_interrupt.c +++ b/src/stm/ao_interrupt.c @@ -22,10 +22,6 @@ #include 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(); +} diff --git a/src/stm32f4/altos-loader.ld b/src/stm32f4/altos-loader.ld index 5d6e1f4b..9a46987f 100644 --- a/src/stm32f4/altos-loader.ld +++ b/src/stm32f4/altos-loader.ld @@ -68,7 +68,7 @@ SECTIONS { .textram BLOCK(8): { _start__ = .; __text_ram_start__ = .; - *(.ramtext) + *(.srodata) __text_ram_end = .; } >ram AT>rom diff --git a/src/stmf0/Makefile-flash.defs b/src/stmf0/Makefile-flash.defs index b6e44990..bbb04e77 100644 --- a/src/stmf0/Makefile-flash.defs +++ b/src/stmf0/Makefile-flash.defs @@ -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) diff --git a/src/stmf0/Makefile-stmf0.defs b/src/stmf0/Makefile-stmf0.defs index 5a883adf..53660560 100644 --- a/src/stmf0/Makefile-stmf0.defs +++ b/src/stmf0/Makefile-stmf0.defs @@ -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 diff --git a/src/stmf0/Makefile.defs b/src/stmf0/Makefile.defs index 2baba4f2..fb62f095 100644 --- a/src/stmf0/Makefile.defs +++ b/src/stmf0/Makefile.defs @@ -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 diff --git a/src/stmf0/altos-loader.ld b/src/stmf0/altos-loader.ld index 4d9b81ae..4ce0b704 100644 --- a/src/stmf0/altos-loader.ld +++ b/src/stmf0/altos-loader.ld @@ -16,82 +16,11 @@ * 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 diff --git a/src/stmf0/altos.ld b/src/stmf0/altos.ld index 64e1d00c..019565cf 100644 --- a/src/stmf0/altos.ld +++ b/src/stmf0/altos.ld @@ -16,90 +16,11 @@ * 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 diff --git a/src/stmf0/ao_arch.h b/src/stmf0/ao_arch.h index d70a9110..47ac7278 100644 --- a/src/stmf0/ao_arch.h +++ b/src/stmf0/ao_arch.h @@ -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; diff --git a/src/stmf0/ao_boot_chain.c b/src/stmf0/ao_boot_chain.c index 8f850a0a..d91afdab 100644 --- a/src/stmf0/ao_boot_chain.c +++ b/src/stmf0/ao_boot_chain.c @@ -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) diff --git a/src/stmf0/ao_flash_stm.c b/src/stmf0/ao_flash_stm.c index 2d57eea7..896d536b 100644 --- a/src/stmf0/ao_flash_stm.c +++ b/src/stmf0/ao_flash_stm.c @@ -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; diff --git a/src/stmf0/ao_interrupt.c b/src/stmf0/ao_interrupt.c index 1ee6e720..3d7dc7a8 100644 --- a/src/stmf0/ao_interrupt.c +++ b/src/stmf0/ao_interrupt.c @@ -32,15 +32,6 @@ #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(); +} diff --git a/src/stmf0/ao_storage_stm.c b/src/stmf0/ao_storage_stm.c index c6f1defe..4f5a12ef 100644 --- a/src/stmf0/ao_storage_stm.c +++ b/src/stmf0/ao_storage_stm.c @@ -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 diff --git a/src/telefireone-v2.0/Makefile b/src/telefireone-v2.0/Makefile index af273a5d..85f06de4 100644 --- a/src/telefireone-v2.0/Makefile +++ b/src/telefireone-v2.0/Makefile @@ -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 diff --git a/src/telegps-v1.0/Makefile b/src/telegps-v1.0/Makefile index fc1b1f28..aa644298 100644 --- a/src/telegps-v1.0/Makefile +++ b/src/telegps-v1.0/Makefile @@ -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) diff --git a/src/telegps-v2.0/Makefile b/src/telegps-v2.0/Makefile index 7ce28471..24410e0d 100644 --- a/src/telegps-v2.0/Makefile +++ b/src/telegps-v2.0/Makefile @@ -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) diff --git a/src/telelco-v2.0/ao_lco_v2.c b/src/telelco-v2.0/ao_lco_v2.c index 1238d72f..a04ceb9f 100644 --- a/src/telelco-v2.0/ao_lco_v2.c +++ b/src/telelco-v2.0/ao_lco_v2.c @@ -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) { diff --git a/src/telemetrum-v2.0/Makefile b/src/telemetrum-v2.0/Makefile index c1e220e3..9b66c518 100644 --- a/src/telemetrum-v2.0/Makefile +++ b/src/telemetrum-v2.0/Makefile @@ -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) diff --git a/src/telestatic-v3.0/Makefile b/src/telestatic-v3.0/Makefile index 124b47fb..5bc8d56a 100644 --- a/src/telestatic-v3.0/Makefile +++ b/src/telestatic-v3.0/Makefile @@ -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 diff --git a/src/telestatic-v3.0/ao_telestatic.c b/src/telestatic-v3.0/ao_telestatic.c index 7e9cd353..721d776c 100644 --- a/src/telestatic-v3.0/ao_telestatic.c +++ b/src/telestatic-v3.0/ao_telestatic.c @@ -36,7 +36,7 @@ const struct ao_cmds ao_firetwo_cmds[] = { { 0, NULL }, }; -void +int main(void) { ao_clock_init(); diff --git a/src/test/.gitignore b/src/test/.gitignore index 56f532ef..e3af02f6 100644 --- a/src/test/.gitignore +++ b/src/test/.gitignore @@ -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 diff --git a/telegps/TeleGPSConfigUI.java b/telegps/TeleGPSConfigUI.java index dc982dea..7c5d186e 100644 --- a/telegps/TeleGPSConfigUI.java +++ b/telegps/TeleGPSConfigUI.java @@ -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 aprs_interval_value; JComboBox aprs_ssid_value; JComboBox aprs_format_value; + JComboBox aprs_offset_value; JComboBox flight_log_max_value; JTextField callsign_value; JComboBox 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(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; + } }