From 19c42c4d97151f2dc38e59cff4d0638694fcd27d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 28 Mar 2024 09:45:38 -0700 Subject: [PATCH 01/15] altos/test: Adjust CRC error rate after FEC fix The number of CRC failures during FEC testing is lower now that the packet length bug has been fixed in the FEC encode bits. Signed-off-by: Keith Packard --- src/test/ao_fec_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ao_fec_test.c b/src/test/ao_fec_test.c index cbced6ae..5f234285 100644 --- a/src/test/ao_fec_test.c +++ b/src/test/ao_fec_test.c @@ -304,7 +304,7 @@ ao_real_packet(void) } #define EXPECT_DECODE_FAIL 0 -#define EXPECT_CRC_MISMATCH 6386 +#define EXPECT_CRC_MISMATCH 6304 #define EXPECT_DATA_MISMATCH 0 #define NOISE_AMOUNT 0x50 -- 2.30.2 From 2bd6698fb9d403931568ddc80266d1bb61c09a8b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 19 Apr 2024 14:07:50 -0700 Subject: [PATCH 02/15] altos/test: Add FEC test for simple 'hello' message This just tests the FEC code using a slightly different data source that makes sure odd lengths work correctly. Signed-off-by: Keith Packard --- src/test/ao_fec_test.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/test/ao_fec_test.c b/src/test/ao_fec_test.c index 5f234285..7c4e6f0e 100644 --- a/src/test/ao_fec_test.c +++ b/src/test/ao_fec_test.c @@ -303,6 +303,29 @@ ao_real_packet(void) return ok; } +int +ao_hello_packet(void) +{ + uint8_t message[5] = "hello"; + uint8_t encode[ENCODE_LEN(sizeof(message))]; + int encode_len; + uint8_t transmit[EXPAND_LEN(sizeof(message))]; + uint8_t decode[DECODE_LEN(sizeof(message))]; + int transmit_len; + int decode_ok; + + printf("Hello packet test:\n"); + ao_fec_dump_bytes(message, sizeof(message), "Message"); + encode_len = ao_fec_encode(message, sizeof(message), encode); + ao_fec_dump_bytes(encode, encode_len, "Encode"); + transmit_len = ao_expand(encode, encode_len, transmit); + ao_fec_dump_bytes(transmit, transmit_len, "Transmit"); + decode_ok = ao_fec_decode(transmit, transmit_len, decode, sizeof(message) + 2, NULL); + ao_fec_dump_bytes(decode, sizeof(message) + 2, "Receive"); + printf("Hello result: %s\n", decode_ok ? "success" : "fail"); + return decode_ok; +} + #define EXPECT_DECODE_FAIL 0 #define EXPECT_CRC_MISMATCH 6304 #define EXPECT_DATA_MISMATCH 0 @@ -336,6 +359,9 @@ main(int argc, char **argv) if (!ao_real_packet()) errors++; + if (!ao_hello_packet()) + errors++; + srandom(0); for (trial = 0; trial < 100000; trial++) { -- 2.30.2 From 5c815c673fa7e82419299d87ffde939fbd842333 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 3 Jan 2024 12:24:08 -0800 Subject: [PATCH 03/15] altosui: Set the beeper to 0 to disable Don't force the beeper to the default value when the frequency is set to 0. Signed-off-by: Keith Packard --- altoslib/AltosConvert.java | 2 +- altosui/AltosConfigFCUI.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/altoslib/AltosConvert.java b/altoslib/AltosConvert.java index ded4b365..84f7e23d 100644 --- a/altoslib/AltosConvert.java +++ b/altoslib/AltosConvert.java @@ -559,7 +559,7 @@ public class AltosConvert { public static int beep_freq_to_value(double freq) { if (freq == 0) - return 94; + return 0; return (int) Math.floor (1.0/2.0 * (24.0e6/32.0) / freq + 0.5); } diff --git a/altosui/AltosConfigFCUI.java b/altosui/AltosConfigFCUI.java index bc082a4e..a238c7df 100644 --- a/altosui/AltosConfigFCUI.java +++ b/altosui/AltosConfigFCUI.java @@ -353,7 +353,7 @@ public class AltosConfigFCUI void set_beep_tool_tip() { if (beep_value.isVisible()) - beep_value.setToolTipText("What frequency the beeper will sound at"); + beep_value.setToolTipText("What frequency the beeper will sound at (0 for off)"); else beep_value.setToolTipText("Older firmware could not select beeper frequency"); } -- 2.30.2 From 278f686f014e74962721e47aeeb60b59afafb37d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 3 Jan 2024 12:31:54 -0800 Subject: [PATCH 04/15] altosui: Support gps receiver setting Create a combo box listing the available receiver models and allow the user to select which one to use, including the builtin one. Signed-off-by: Keith Packard --- altoslib/AltosConfigData.java | 16 ++++++++- altoslib/AltosConfigValues.java | 6 +++- altoslib/AltosLib.java | 7 ++++ altosui/AltosConfigFCUI.java | 61 +++++++++++++++++++++++++++++++++ telegps/TeleGPSConfigUI.java | 61 +++++++++++++++++++++++++++++++++ 5 files changed, 149 insertions(+), 2 deletions(-) diff --git a/altoslib/AltosConfigData.java b/altoslib/AltosConfigData.java index 005ef571..6b980be6 100644 --- a/altoslib/AltosConfigData.java +++ b/altoslib/AltosConfigData.java @@ -88,6 +88,9 @@ public class AltosConfigData { public int report_feet; + /* HAS_GPS_MOSAIC */ + public int gps_receiver; + /* Storage info replies */ public int storage_size; public int storage_erase_unit; @@ -331,6 +334,8 @@ public class AltosConfigData { report_feet = AltosLib.MISSING; + gps_receiver = AltosLib.MISSING; + tracker_motion = AltosLib.MISSING; tracker_interval = AltosLib.MISSING; @@ -526,6 +531,8 @@ public class AltosConfigData { try { report_feet = get_int(line, "Report in feet:"); } catch (Exception e) {} + try { gps_receiver = get_int(line, "GPS receiver:"); } catch (Exception e) {} + /* HAS_TRACKER */ try { int[] values = get_values(line, "Tracker setting:"); @@ -777,6 +784,9 @@ public class AltosConfigData { if (report_feet != AltosLib.MISSING) report_feet = source.report_feet(); + if (gps_receiver != AltosLib.MISSING) + gps_receiver = source.gps_receiver(); + /* HAS_TRACKER */ if (tracker_motion != AltosLib.MISSING) tracker_motion = source.tracker_motion(); @@ -834,6 +844,7 @@ public class AltosConfigData { dest.set_beep(beep); dest.set_radio_10mw(radio_10mw); dest.set_report_feet(report_feet); + dest.set_gps_receiver(gps_receiver); dest.set_tracker_motion(tracker_motion); dest.set_tracker_interval(tracker_interval); } @@ -957,10 +968,13 @@ public class AltosConfigData { if (radio_10mw != AltosLib.MISSING) link.printf("c p %d\n", radio_10mw); - /* HAS_RADIO_10MW */ if (report_feet != AltosLib.MISSING) link.printf("c u %d\n", report_feet); + /* HAS_GPS_MOSAIC */ + if (gps_receiver != AltosLib.MISSING) + link.printf("c g %d\n", gps_receiver); + /* HAS_TRACKER */ if (tracker_motion != AltosLib.MISSING && tracker_interval != AltosLib.MISSING) link.printf("c t %d %d\n", tracker_motion, tracker_interval); diff --git a/altoslib/AltosConfigValues.java b/altoslib/AltosConfigValues.java index 6823e0f9..1de180d3 100644 --- a/altoslib/AltosConfigValues.java +++ b/altoslib/AltosConfigValues.java @@ -128,5 +128,9 @@ public interface AltosConfigValues { public abstract int report_feet() throws AltosConfigDataException; - public abstract void set_report_feet(int radio_10mw); + public abstract void set_report_feet(int report_feet); + + public abstract int gps_receiver() throws AltosConfigDataException; + + public abstract void set_gps_receiver(int gps_receiver); } diff --git a/altoslib/AltosLib.java b/altoslib/AltosLib.java index 82b5881a..fbbfd63c 100644 --- a/altoslib/AltosLib.java +++ b/altoslib/AltosLib.java @@ -140,6 +140,13 @@ public class AltosLib { public final static int product_basestation = 0x10000 + 1; public final static int product_altimeter = 0x10000 + 2; + public final static int gps_builtin = 0; + public final static int gps_mosaic = 1; + + public final static String[] gps_receiver_names = { + "Builtin", "Mosaic-X5" + }; + private static class Product { final String name; final int product; diff --git a/altosui/AltosConfigFCUI.java b/altosui/AltosConfigFCUI.java index a238c7df..3e5bede5 100644 --- a/altosui/AltosConfigFCUI.java +++ b/altosui/AltosConfigFCUI.java @@ -44,6 +44,7 @@ public class AltosConfigFCUI JLabel radio_enable_label; JLabel radio_10mw_label; JLabel report_feet_label; + JLabel gps_receiver_label; JLabel rate_label; JLabel aprs_interval_label; JLabel aprs_ssid_label; @@ -73,6 +74,7 @@ public class AltosConfigFCUI JRadioButton radio_enable_value; JRadioButton radio_10mw_value; JComboBox report_feet_value; + JComboBox gps_receiver_value; AltosUIRateList rate_value; JComboBox aprs_interval_value; JComboBox aprs_ssid_value; @@ -372,6 +374,13 @@ public class AltosConfigFCUI report_feet_value.setToolTipText("Older firmware always beeps max height in meters"); } + void set_gps_receiver_tool_tip() { + if (gps_receiver_value.isVisible()) + gps_receiver_value.setToolTipText("GPS receiver selection"); + else + gps_receiver_value.setToolTipText("Only TeleMega with new firmware supports alternate GPS receivers"); + } + /* Build the UI using a grid bag */ public AltosConfigFCUI(JFrame in_owner, boolean remote) { super (in_owner, title, false); @@ -656,6 +665,32 @@ public class AltosConfigFCUI set_report_feet_tool_tip(); row++; + /* GPS Receiver */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = row; + c.gridwidth = 4; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + c.ipady = 5; + gps_receiver_label = new JLabel("GPS Receiver:"); + pane.add(gps_receiver_label, c); + + c = new GridBagConstraints(); + c.gridx = 4; c.gridy = row; + c.gridwidth = 4; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + c.ipady = 5; + gps_receiver_value = new JComboBox(AltosLib.gps_receiver_names); + gps_receiver_value.setEditable(false); + gps_receiver_value.addItemListener(this); + pane.add(gps_receiver_value, c); + set_gps_receiver_tool_tip(); + row++; + /* Telemetry Rate */ c = new GridBagConstraints(); c.gridx = 0; c.gridy = row; @@ -1553,6 +1588,32 @@ public class AltosConfigFCUI return AltosLib.MISSING; } + public void set_gps_receiver(int new_gps_receiver) { + System.out.printf("set_gps_receiver %d\n", new_gps_receiver); + if (new_gps_receiver != AltosLib.MISSING) { + if (new_gps_receiver >= AltosLib.gps_receiver_names.length) + new_gps_receiver = 0; + if (new_gps_receiver < 0) { + gps_receiver_value.setEnabled(false); + new_gps_receiver = 0; + } else { + gps_receiver_value.setEnabled(true); + } + gps_receiver_value.setSelectedIndex(new_gps_receiver); + } + gps_receiver_value.setVisible(new_gps_receiver != AltosLib.MISSING); + gps_receiver_label.setVisible(new_gps_receiver != AltosLib.MISSING); + + set_gps_receiver_tool_tip(); + } + + public int gps_receiver() { + if (gps_receiver_value.isVisible()) + return gps_receiver_value.getSelectedIndex(); + else + return AltosLib.MISSING; + } + String[] tracker_motion_values() { if (AltosConvert.imperial_units) return tracker_motion_values_ft; diff --git a/telegps/TeleGPSConfigUI.java b/telegps/TeleGPSConfigUI.java index b348f702..a4a60b6f 100644 --- a/telegps/TeleGPSConfigUI.java +++ b/telegps/TeleGPSConfigUI.java @@ -41,6 +41,7 @@ public class TeleGPSConfigUI JLabel radio_enable_label; JLabel radio_10mw_label; JLabel report_feet_label; + JLabel gps_receiver_label; JLabel rate_label; JLabel aprs_interval_label; JLabel aprs_ssid_label; @@ -62,6 +63,7 @@ public class TeleGPSConfigUI JRadioButton radio_enable_value; JRadioButton radio_10mw_value; JComboBox report_feet_value; + JComboBox gps_receiver_value; AltosUIRateList rate_value; JComboBox aprs_interval_value; JComboBox aprs_ssid_value; @@ -200,6 +202,39 @@ public class TeleGPSConfigUI return AltosLib.MISSING; } + void set_gps_receiver_tool_tip() { + if (gps_receiver_value.isVisible()) + gps_receiver_value.setToolTipText("GPS receiver selection"); + else + gps_receiver_value.setToolTipText("Only TeleMega with new firmware supports alternate GPS receivers"); + } + + public void set_gps_receiver(int new_gps_receiver) { + System.out.printf("set_gps_receiver %d\n", new_gps_receiver); + if (new_gps_receiver != AltosLib.MISSING) { + if (new_gps_receiver >= AltosLib.gps_receiver_names.length) + new_gps_receiver = 0; + if (new_gps_receiver < 0) { + gps_receiver_value.setEnabled(false); + new_gps_receiver = 0; + } else { + gps_receiver_value.setEnabled(true); + } + gps_receiver_value.setSelectedIndex(new_gps_receiver); + } + gps_receiver_value.setVisible(new_gps_receiver != AltosLib.MISSING); + gps_receiver_label.setVisible(new_gps_receiver != AltosLib.MISSING); + + set_gps_receiver_tool_tip(); + } + + public int gps_receiver() { + if (gps_receiver_value.isVisible()) + return gps_receiver_value.getSelectedIndex(); + else + return AltosLib.MISSING; + } + void set_rate_tool_tip() { if (rate_value.isVisible()) rate_value.setToolTipText("Select telemetry baud rate"); @@ -430,6 +465,32 @@ public class TeleGPSConfigUI set_report_feet_tool_tip(); row++; + /* GPS Receiver */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = row; + c.gridwidth = 4; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + c.ipady = 5; + gps_receiver_label = new JLabel("GPS Receiver:"); + pane.add(gps_receiver_label, c); + + c = new GridBagConstraints(); + c.gridx = 4; c.gridy = row; + c.gridwidth = 4; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + c.ipady = 5; + gps_receiver_value = new JComboBox(AltosLib.gps_receiver_names); + gps_receiver_value.setEditable(false); + gps_receiver_value.addItemListener(this); + pane.add(gps_receiver_value, c); + set_gps_receiver_tool_tip(); + row++; + /* Radio 10mW limit */ c = new GridBagConstraints(); c.gridx = 0; c.gridy = row; -- 2.30.2 From f8d943c54b1518e77c884b6dc77ee42dc88aaeab Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Apr 2024 15:33:30 -0700 Subject: [PATCH 05/15] Add EasyTimer v2 firmware Signed-off-by: Keith Packard --- Makefile.am | 1 + Releasing | 2 ++ altosui/Makefile.am | 3 ++- altosui/altos-windows.nsi.in | 1 + 4 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 08765810..6f3ead74 100644 --- a/Makefile.am +++ b/Makefile.am @@ -57,6 +57,7 @@ fat_altos = \ src/easymini-v3.0/easymini-v3.0-$(VERSION).ihx \ src/easymotor-v3/easymotor-v3-$(VERSION).ihx \ src/easytimer-v1/easytimer-v1-$(VERSION).ihx \ + src/easytimer-v2/easytimer-v2-$(VERSION).ihx \ src/telebt-v3.0/telebt-v3.0-$(VERSION).ihx \ src/telebt-v4.0/telebt-v4.0-$(VERSION).ihx \ src/teledongle-v3.0/teledongle-v3.0-$(VERSION).ihx \ diff --git a/Releasing b/Releasing index 9750a4eb..4e0e2829 100644 --- a/Releasing +++ b/Releasing @@ -118,6 +118,7 @@ These are Bdale's notes on how to do a release. src/easymini-v[1-3].0/{*.elf,*.ihx,*.map} \ src/easymotor-v3/{*.elf,*.ihx,*.map} \ src/easytimer-v1/{*.elf,*.ihx,*.map} \ + src/easytimer-v2/{*.elf,*.ihx,*.map} \ src/telebt-v[3-4].0/{*.elf,*.ihx,*.map} \ src/teledongle-v3.0/{*.elf,*.ihx,*.map} \ src/telegps-v[1-3].0/{*.elf,*.ihx,*.map} \ @@ -132,6 +133,7 @@ These are Bdale's notes on how to do a release. src/easymini-v[1-3].0/flash-loader/*.elf \ src/easymotor-v3/flash-loader/*.elf \ src/easytimer-v1/flash-loader/*.elf \ + src/easytimer-v2/flash-loader/*.elf \ src/telebt-v[3-4].0/flash-loader/{*.elf,*.bin,*.map} \ src/teledongle-v3.0/flash-loader/*.elf \ src/telegps-v[1-3].0/flash-loader/{*.elf,*.bin,*.map} \ diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 1da6408c..bfea1810 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -155,7 +155,8 @@ FIRMWARE_EMOTOR_3=$(top_srcdir)/src/easymotor-v3/easymotor-v3-$(VERSION).ihx FIRMWARE_EMOTOR=$(FIRMWARE_EMOTOR_3) FIRMWARE_ETIMER_1=$(top_srcdir)/src/easytimer-v1/easytimer-v1-$(VERSION).ihx -FIRMWARE_ETIMER=$(FIRMWARE_ETIMER_1) +FIRMWARE_ETIMER_2=$(top_srcdir)/src/easytimer-v2/easytimer-v2-$(VERSION).ihx +FIRMWARE_ETIMER=$(FIRMWARE_ETIMER_1) $(FIRMWARE_ETIMER_2) FIRMWARE_TGPS_1_0=$(top_srcdir)/src/telegps-v1.0/telegps-v1.0-$(VERSION).ihx FIRMWARE_TGPS_2_0=$(top_srcdir)/src/telegps-v2.0/telegps-v2.0-$(VERSION).ihx diff --git a/altosui/altos-windows.nsi.in b/altosui/altos-windows.nsi.in index ee8251bb..fbed399e 100644 --- a/altosui/altos-windows.nsi.in +++ b/altosui/altos-windows.nsi.in @@ -143,6 +143,7 @@ Section "Firmware" File "../src/easymega-v2.0/easymega-v2.0-${VERSION}.ihx" File "../src/easymotor-v3/easymotor-v3-${VERSION}.ihx" File "../src/easytimer-v1/easytimer-v1-${VERSION}.ihx" + File "../src/easytimer-v2/easytimer-v2-${VERSION}.ihx" File "../src/telelco-v2.0/telelco-v2.0-${VERSION}.ihx" File "../src/telefireeight-v1.0/telefireeight-v1.0-${VERSION}.ihx" File "../src/telefireeight-v2.0/telefireeight-v2.0-${VERSION}.ihx" -- 2.30.2 From f89bfb0e1a14c9809d35f60fff448a1b3a2f2b68 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Apr 2024 15:49:29 -0700 Subject: [PATCH 06/15] Fix up fat build target Depend on all-recursive so everything gets built before we attempt to build the fat bits. Signed-off-by: Keith Packard --- Makefile.am | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Makefile.am b/Makefile.am index 6f3ead74..8bb1830a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -19,12 +19,9 @@ fat-install: fat cd micropeak && $(MAKE) fat-install endif -fat: - cd src && $(MAKE) all - cd doc && $(MAKE) all +fat: all-recursive cd libaltos && $(MAKE) fat cd altoslib && $(MAKE) all - cd altosuilib && $(MAKE) all cd icon && $(MAKE) fat cd altosui && $(MAKE) fat cd micropeak && $(MAKE) fat -- 2.30.2 From ae69294526369f251b221ee1f8ca2cb58b63bd7a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Apr 2024 18:34:30 -0700 Subject: [PATCH 07/15] altos/draw: Add 'install' target Needed for building packages; install is a no-op in this directory. Signed-off-by: Keith Packard --- src/draw/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/draw/Makefile b/src/draw/Makefile index 6b986b42..746178a0 100644 --- a/src/draw/Makefile +++ b/src/draw/Makefile @@ -151,3 +151,5 @@ $(LINE_TEST_OBJS): $(HEADERS) clean: rm -f $(LCO_TEST_OBJS) ao_font.h ao_logo.h $(FONT_SRCS) + +install: -- 2.30.2 From b834c989cbddf8db9848af03bb040da1a6a0f651 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 27 Apr 2024 22:30:29 -0700 Subject: [PATCH 08/15] doc: Add 1.9.18 release notes Signed-off-by: Keith Packard --- doc/Makefile.am | 1 + doc/altusmetrum-theme.yml | 2 +- doc/altusmetrum.txt | 2 +- doc/easymini-release-notes.inc | 8 ++++++++ doc/header.inc | 2 +- doc/release-notes-1.9.18.inc | 18 ++++++++++++++++++ doc/release-notes.inc | 4 ++++ doc/specs.inc | 9 +++++++++ doc/telegps-release-notes.inc | 8 ++++++++ 9 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 doc/release-notes-1.9.18.inc diff --git a/doc/Makefile.am b/doc/Makefile.am index f0d8cfb6..2ddfec48 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.18.inc \ release-notes-1.9.17.inc \ release-notes-1.9.16.inc \ release-notes-1.9.15.inc \ diff --git a/doc/altusmetrum-theme.yml b/doc/altusmetrum-theme.yml index 14e5634b..c838a524 100644 --- a/doc/altusmetrum-theme.yml +++ b/doc/altusmetrum-theme.yml @@ -54,7 +54,7 @@ footer: left: content: '{page-number}' right: - content: '© 2023 Bdale Garbee and Keith Packard. Creative Commons ShareAlike 3.0 License' + content: '© 2024 Bdale Garbee and Keith Packard. Creative Commons ShareAlike 3.0 License' verso: left: content: $footer_recto_right_content diff --git a/doc/altusmetrum.txt b/doc/altusmetrum.txt index cb9ef4e2..5a33d754 100644 --- a/doc/altusmetrum.txt +++ b/doc/altusmetrum.txt @@ -5,7 +5,7 @@ Keith Packard ; Bdale Garbee ; Bob Finch; Anth :revdate: 1 Jan 1970 :icons: :icontype: svg -:copyright: Bdale Garbee and Keith Packard 2023 +:copyright: Bdale Garbee and Keith Packard 2024 :doctype: book :numbered: :stylesheet: am.css diff --git a/doc/easymini-release-notes.inc b/doc/easymini-release-notes.inc index fca8e9a0..3871d338 100644 --- a/doc/easymini-release-notes.inc +++ b/doc/easymini-release-notes.inc @@ -1,5 +1,13 @@ [appendix] == Release Notes + :leveloffset: 2 + include::release-notes-1.9.18.adoc[] + + <<<< + :leveloffset: 2 + include::release-notes-1.9.17.adoc[] + + <<<< :leveloffset: 2 include::release-notes-1.9.16.adoc[] diff --git a/doc/header.inc b/doc/header.inc index 3cacba86..a91f5908 100644 --- a/doc/header.inc +++ b/doc/header.inc @@ -7,7 +7,7 @@ endif::[] [license] == License -Copyright © 2023 Bdale Garbee and Keith Packard +Copyright © 2024 Bdale Garbee and Keith Packard This document is released under the terms of the link:http://creativecommons.org/licenses/by-sa/3.0/[Creative Commons ShareAlike 3.0 License] diff --git a/doc/release-notes-1.9.18.inc b/doc/release-notes-1.9.18.inc new file mode 100644 index 00000000..3e1544d7 --- /dev/null +++ b/doc/release-notes-1.9.18.inc @@ -0,0 +1,18 @@ += Release Notes for Version 1.9.18 +include::release-head.adoc[] +:doctype: article + + Version 1.9.18 + + == AltOS + + * Add support for EasyTimer V2. The new version of this + product has on-board storage to log data during flight. + + == AltosUI & TeleGPS application + + * Add support for EasyTimer V2. This includes support for + analyizing flight data from the on-board logs. + + * Allow on-board beepers to be disabled by setting the + frequency to 0. diff --git a/doc/release-notes.inc b/doc/release-notes.inc index 786f29e3..7b98ceaf 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.18.adoc[] + + <<<< :leveloffset: 2 include::release-notes-1.9.17.adoc[] diff --git a/doc/specs.inc b/doc/specs.inc index c00e1b3a..3e02e5e3 100644 --- a/doc/specs.inc +++ b/doc/specs.inc @@ -181,6 +181,15 @@ |- |- |3.7-12V + + |EasyTimer v2.0 + |- + |24g + |- + |BMI088 + |1MB + |- + |3.7-12V endif::easytimer[] ifdef::easymotor[] diff --git a/doc/telegps-release-notes.inc b/doc/telegps-release-notes.inc index 3ef5f9bf..f6c75e24 100644 --- a/doc/telegps-release-notes.inc +++ b/doc/telegps-release-notes.inc @@ -1,5 +1,13 @@ [appendix] == Release Notes + :leveloffset: 2 + include::release-notes-1.9.18.adoc[] + + <<<< + :leveloffset: 2 + include::release-notes-1.9.17.adoc[] + + <<<< :leveloffset: 2 include::release-notes-1.9.16.adoc[] -- 2.30.2 From dce00ba450e686e0fef4bd1d6a8b292eca8bfc25 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Apr 2024 15:34:13 -0700 Subject: [PATCH 09/15] Version 1.9.18 Signed-off-by: Keith Packard --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 9e3db494..998cda30 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.17) +AC_INIT([altos], 1.9.18) ANDROID_VERSION=37 AC_CONFIG_SRCDIR([src/kernel/ao.h]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE -RELEASE_DATE=2023-08-30 +RELEASE_DATE=2024-04-28 AC_SUBST(RELEASE_DATE) DOC_DATE=`LC_ALL=C date -d $RELEASE_DATE +'%d %b %Y'` -- 2.30.2 From 673d326fd861672feaee7c903486e54e8de9471d Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sun, 28 Apr 2024 20:44:55 -0600 Subject: [PATCH 10/15] capture things learned during 1.9.18 release --- Releasing | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Releasing b/Releasing index 4e0e2829..081ece27 100644 --- a/Releasing +++ b/Releasing @@ -44,7 +44,7 @@ These are Bdale's notes on how to do a release. installers for Windows and Mac OS X sudo apt update - sudo apt install genisoimage nsis \ + sudo apt install genisoimage nsis gcc-avr avr-libc \ gcc-i686-linux-gnu gcc-aarch64-linux-gnu \ gcc-arm-linux-gnueabi gcc-arm-linux-gnueabihf \ gcc-mingw-w64-i686-posix gcc-mingw-w64-x86-64-win32 @@ -117,8 +117,7 @@ These are Bdale's notes on how to do a release. src/easymega-v[1-2].0/{*.elf,*.ihx,*.map} \ src/easymini-v[1-3].0/{*.elf,*.ihx,*.map} \ src/easymotor-v3/{*.elf,*.ihx,*.map} \ - src/easytimer-v1/{*.elf,*.ihx,*.map} \ - src/easytimer-v2/{*.elf,*.ihx,*.map} \ + src/easytimer-v[1-2]/{*.elf,*.ihx,*.map} \ src/telebt-v[3-4].0/{*.elf,*.ihx,*.map} \ src/teledongle-v3.0/{*.elf,*.ihx,*.map} \ src/telegps-v[1-3].0/{*.elf,*.ihx,*.map} \ @@ -132,8 +131,7 @@ These are Bdale's notes on how to do a release. src/easymega-v[1-2].0/flash-loader/*.elf \ src/easymini-v[1-3].0/flash-loader/*.elf \ src/easymotor-v3/flash-loader/*.elf \ - src/easytimer-v1/flash-loader/*.elf \ - src/easytimer-v2/flash-loader/*.elf \ + src/easytimer-v[1-2]/flash-loader/*.elf \ src/telebt-v[3-4].0/flash-loader/{*.elf,*.bin,*.map} \ src/teledongle-v3.0/flash-loader/*.elf \ src/telegps-v[1-3].0/flash-loader/{*.elf,*.bin,*.map} \ -- 2.30.2 From 5de98063f8e638e18ea0f05f09e31e435dfd7d0a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Apr 2024 21:19:58 -0700 Subject: [PATCH 11/15] altos/easymini-v2.0: Remove combined .dfu file This is delivered to seeed for testing the hardware. Signed-off-by: Keith Packard --- src/easymini-v2.0/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/src/easymini-v2.0/Makefile b/src/easymini-v2.0/Makefile index a045e126..ac4f9c4b 100644 --- a/src/easymini-v2.0/Makefile +++ b/src/easymini-v2.0/Makefile @@ -83,6 +83,7 @@ distclean: clean clean: rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx $(PROGNAME)-*.map + rm -f $(PROGNAME)-*.dfu rm -f ao_product.h install: -- 2.30.2 From 0d8c2354e7c4f7d2671e6c0a0d088fd94de75c46 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 29 Apr 2024 11:20:53 -0600 Subject: [PATCH 12/15] remove garbage line from easymotor turnon script --- ao-bringup/turnon_easymotor | 1 - 1 file changed, 1 deletion(-) diff --git a/ao-bringup/turnon_easymotor b/ao-bringup/turnon_easymotor index 4678430d..8528a7e7 100755 --- a/ao-bringup/turnon_easymotor +++ b/ao-bringup/turnon_easymotor @@ -46,7 +46,6 @@ case $# in exit 1; ;; esac -otootor # # Use released versions of everything # -- 2.30.2 From db58d8c58fd6dcb4d153d85e3fd37d59956c84db Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 29 Apr 2024 11:41:48 -0600 Subject: [PATCH 13/15] first cut at turnon scripts for EasyTimer v2 --- ao-bringup/cal-freq | 25 ------ .../{test-easytimer => test-easytimer-v1} | 0 ao-bringup/test-easytimer-v2 | 51 ++++++++++++ ao-bringup/turnon_easytimer | 21 ++--- ao-bringup/turnon_easytimer_v1 | 78 +++++++++++++++++++ 5 files changed, 134 insertions(+), 41 deletions(-) delete mode 100755 ao-bringup/cal-freq rename ao-bringup/{test-easytimer => test-easytimer-v1} (100%) create mode 100755 ao-bringup/test-easytimer-v2 create mode 100755 ao-bringup/turnon_easytimer_v1 diff --git a/ao-bringup/cal-freq b/ao-bringup/cal-freq deleted file mode 100755 index 40c25ce8..00000000 --- a/ao-bringup/cal-freq +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/sh - -case $# in -1) - dev="$1" - ;; -*) - echo "Usage: $0 " - exit 1; - ;; -esac - -../ao-tools/ao-cal-freq/ao-cal-freq --tty=$dev -case $? in - 0) - calline=`./get-radio-cal $dev` - CAL_VALUE=`echo $calline | awk '{print $2}'` - CURRENT_FREQ=`echo $calline | awk '{print $4}'` - echo $SERIAL","$CAL_VALUE >> cal_values - exit 0 - ;; - *) - exit 1 - ;; -esac diff --git a/ao-bringup/test-easytimer b/ao-bringup/test-easytimer-v1 similarity index 100% rename from ao-bringup/test-easytimer rename to ao-bringup/test-easytimer-v1 diff --git a/ao-bringup/test-easytimer-v2 b/ao-bringup/test-easytimer-v2 new file mode 100755 index 00000000..023f27bc --- /dev/null +++ b/ao-bringup/test-easytimer-v2 @@ -0,0 +1,51 @@ +#!/bin/sh + +VERSION=2 +PRODUCT=EasyTimer +BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'` + +echo "$PRODUCT-v$VERSION Test Program" +echo "Copyright 2024 by Bdale Garbee. Released under GPL v3" +echo +echo "Expectations:" +echo "\t$PRODUCT v$VERSION powered from USB" +echo + +ret=1 +ao-list | while read product serial dev; do + case "$product" in + "$PRODUCT-v$VERSION") + + echo "Testing $product $serial $dev" + + ./test-igniters $dev 0 1 + echo"" + + case $? in + 0) + ;; + *) + echo "failed" + exit 1 + esac + echo"" + + + FLASHSIZE=1048576 + + echo "Testing flash" + ../ao-tools/ao-test-flash/ao-test-flash --tty="$dev" "$FLASHSIZE" + + if [ $? -ne 0 ]; then + echo -e '\e[31m'"$PRODUCT-$VERSION serial $serial failed"'\e[39m' + exit 1 + fi + echo "" + + + echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship + echo "\007" + ret=0 + ;; + esac +done diff --git a/ao-bringup/turnon_easytimer b/ao-bringup/turnon_easytimer index 8953f900..da78cbb6 100755 --- a/ao-bringup/turnon_easytimer +++ b/ao-bringup/turnon_easytimer @@ -1,11 +1,7 @@ #!/bin/sh -if [ -x /usr/bin/ao-flash-stm ]; then - FLASH_STM=/usr/bin/ao-flash-stm -else - echo "Can't find ao-flash-stm! Aborting." - exit 1 -fi +# EasyTimer v2 all arrive from the assembler with +# the bootloader already flashed. if [ -x /usr/bin/ao-usbload ]; then USBLOAD=/usr/bin/ao-usbload @@ -14,16 +10,15 @@ else exit 1 fi -VERSION=1 +VERSION=2 REPO=~/altusmetrumllc/Binaries PRODUCT=EasyTimer echo "$PRODUCT v$VERSION Turn-On and Calibration Program" -echo "Copyright 2020 by Bdale Garbee. Released under GPL v3" +echo "Copyright 2024 by Bdale Garbee. Released under GPL v3" echo echo "Expectations:" echo "\t$PRODUCT v$VERSION powered from USB" -echo "\t\twith ST-Link-V2 cabled to debug header" echo case $# in @@ -41,12 +36,6 @@ case $# in ;; esac -echo $FLASH_STM - -$FLASH_STM $REPO/loaders/easytimer-v$VERSION*.elf - -sleep 3 - $USBLOAD --serial=$SERIAL --force $REPO/easytimer-v$VERSION*.elf || exit 1 sleep 5 @@ -73,6 +62,6 @@ done echo 'E 1' > $dev -./test-easytimer +./test-easytimer-v2 exit $? diff --git a/ao-bringup/turnon_easytimer_v1 b/ao-bringup/turnon_easytimer_v1 new file mode 100755 index 00000000..8953f900 --- /dev/null +++ b/ao-bringup/turnon_easytimer_v1 @@ -0,0 +1,78 @@ +#!/bin/sh + +if [ -x /usr/bin/ao-flash-stm ]; then + FLASH_STM=/usr/bin/ao-flash-stm +else + echo "Can't find ao-flash-stm! Aborting." + exit 1 +fi + +if [ -x /usr/bin/ao-usbload ]; then + USBLOAD=/usr/bin/ao-usbload +else + echo "Can't find ao-usbload! Aborting." + exit 1 +fi + +VERSION=1 +REPO=~/altusmetrumllc/Binaries +PRODUCT=EasyTimer + +echo "$PRODUCT v$VERSION Turn-On and Calibration Program" +echo "Copyright 2020 by Bdale Garbee. Released under GPL v3" +echo +echo "Expectations:" +echo "\t$PRODUCT v$VERSION powered from USB" +echo "\t\twith ST-Link-V2 cabled to debug header" +echo + +case $# in + 1) + SERIAL="$1" + echo "$PRODUCT-$VERSION serial number: $SERIAL" + ;; + 0) + echo -n "$PRODUCT-$VERSION serial number: " + read SERIAL + ;; + *) + echo "Usage: $0 " 1>&2 + exit 1; + ;; +esac + +echo $FLASH_STM + +$FLASH_STM $REPO/loaders/easytimer-v$VERSION*.elf + +sleep 3 + +$USBLOAD --serial=$SERIAL --force $REPO/easytimer-v$VERSION*.elf || exit 1 + +sleep 5 + +dev=`ao-list | awk '/EasyTimer-v'"$VERSION"'/ { print $3; exit(0); }'` + +case "$dev" in +/dev/tty*) + echo "EasyTimer found on $dev" + ;; +*) + echo 'No EasyTimer-v'"$VERSION"' found' + exit 1 + ;; +esac + +echo 'E 0' > $dev + +failed=1 +while [ $failed = 1 ]; do + ../ao-tools/ao-cal-accel/ao-cal-accel $dev + failed=$? +done + +echo 'E 1' > $dev + +./test-easytimer + +exit $? -- 2.30.2 From 407086a6b36032f0c780d3b3e94101fa96a1c900 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 11 May 2024 17:52:20 -0700 Subject: [PATCH 14/15] altos/test: Get the flight software test code working again This had gotten very stale; much hacking was required. I know the TeleMega v4 code works, other things "might". At least it seems to build without errors? Signed-off-by: Keith Packard --- src/Makefile | 2 +- src/kernel/ao_config.h | 2 + src/kernel/ao_convert_pa_test.c | 1 + src/kernel/ao_convert_test.c | 1 + src/kernel/ao_host.h | 8 ++ src/test/Makefile | 12 +- src/test/ao_fat_test.c | 4 +- src/test/ao_flight_test.c | 229 +++++++++++++++++++++++++++++--- src/test/ao_gps_test.c | 1 + src/test/ao_gps_test_skytraq.c | 4 + src/test/ao_gps_test_ublox.c | 3 + src/test/ao_micropeak_test.c | 1 + src/test/plotmm | 14 +- 13 files changed, 248 insertions(+), 34 deletions(-) diff --git a/src/Makefile b/src/Makefile index c89ac0e0..b3a3066c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -63,7 +63,7 @@ ARMM0DIRS=\ AVRDIRS=\ micropeak microkite microsplash -SUBDIRS=draw +SUBDIRS=draw test ifeq ($(strip $(HAVE_ARM_M3_CC)),yes) SUBDIRS+=$(ARMM3DIRS) diff --git a/src/kernel/ao_config.h b/src/kernel/ao_config.h index a8541775..6896eaa9 100644 --- a/src/kernel/ao_config.h +++ b/src/kernel/ao_config.h @@ -19,7 +19,9 @@ #ifndef _AO_CONFIG_H_ #define _AO_CONFIG_H_ +#ifndef AO_FLIGHT_TEST #include +#endif #if AO_PYRO_NUM #include diff --git a/src/kernel/ao_convert_pa_test.c b/src/kernel/ao_convert_pa_test.c index e0ee2928..e1ca0bf7 100644 --- a/src/kernel/ao_convert_pa_test.c +++ b/src/kernel/ao_convert_pa_test.c @@ -18,6 +18,7 @@ #include #define AO_CONVERT_TEST +#define AO_TICK_TYPE uint32_t typedef int32_t alt_t; typedef int32_t pres_t; #include "ao_host.h" diff --git a/src/kernel/ao_convert_test.c b/src/kernel/ao_convert_test.c index c8debbc5..f3eb0178 100644 --- a/src/kernel/ao_convert_test.c +++ b/src/kernel/ao_convert_test.c @@ -17,6 +17,7 @@ */ #include +#define AO_TICK_TYPE uint32_t #define AO_CONVERT_TEST #define AO_NEED_ALTITUDE_TO_PRES 1 #include "ao_host.h" diff --git a/src/kernel/ao_host.h b/src/kernel/ao_host.h index c974a9fe..30df8edc 100644 --- a/src/kernel/ao_host.h +++ b/src/kernel/ao_host.h @@ -81,12 +81,20 @@ struct ao_task { int dummy; }; +enum ao_igniter_status { + ao_igniter_unknown, /* unknown status (ambiguous voltage) */ + ao_igniter_ready, /* continuity detected */ + ao_igniter_active, /* igniter firing */ + ao_igniter_open, /* open circuit detected */ +}; + #define ao_add_task(t,f,n) #define ao_log_start() #define ao_log_stop() #define AO_MS_TO_TICKS(ms) ((ms) / 10) +#define AO_NS_TO_TICKS(ns) ((ns) / (10000000L)) #define AO_SEC_TO_TICKS(s) ((s) * 100) #define AO_FLIGHT_TEST diff --git a/src/test/Makefile b/src/test/Makefile index 55a3fbeb..2c74780d 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -3,11 +3,12 @@ vpath %.c ..:../kernel:../drivers:../util:../micropeak:../aes:../product vpath %.h ..:../kernel:../drivers:../util:../micropeak:../aes:../product vpath make-kalman ..:../kernel:../drivers:../util:../micropeak:../aes:../product -PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_flight_test_mm \ +PROGS=ao_flight_test_mm \ ao_flight_test_metrum ao_flight_test_mini \ ao_gps_test ao_gps_test_skytraq ao_gps_test_ublox ao_convert_test ao_convert_pa_test ao_fec_test \ ao_aprs_test ao_micropeak_test ao_fat_test ao_aes_test ao_int64_test \ - ao_ms5607_convert_test ao_quaternion_test + ao_ms5607_convert_test ao_quaternion_test \ + ao_flight_test_tmega4 INCS=ao_kalman.h ao_ms5607.h ao_log.h ao_data.h altitude-pa.h altitude.h ao_quaternion.h ao_eeprom_read.h TEST_SRC=ao_flight_test.c @@ -16,7 +17,7 @@ TEST_LIB=-ljson-c KALMAN=make-kalman -CFLAGS=-I.. -I. -I../kernel -I../drivers -I../micropeak -I../product -I../lisp -O0 -g -Wall -DAO_LISP_TEST -no-pie +CFLAGS=-I.. -I. -I../kernel -I../drivers -I../product -I../lisp -O0 -g -Wall -DAO_LISP_TEST -no-pie all: $(PROGS) ao_aprs_data.wav @@ -40,6 +41,9 @@ ao_flight_test_accel: $(TEST_SRC_ALL) ao_host.h ao_flight.c ao_sample.c ao_kalm ao_flight_test_mm: $(TEST_SRC_ALL) ao_host.h ao_flight.c ao_sample.c ao_kalman.c ao_pyro.c ao_pyro.h $(INCS) cc -DTELEMEGA=1 $(CFLAGS) -o $@ $(TEST_SRC) $(TEST_LIB) -lm +ao_flight_test_tmega4: $(TEST_SRC_ALL) ao_host.h ao_flight.c ao_sample.c ao_kalman.c ao_pyro.c ao_pyro.h $(INCS) + cc -DTELEMEGA_V4=1 $(CFLAGS) -o $@ $(TEST_SRC) $(TEST_LIB) -lm + ao_flight_test_metrum: $(TEST_SRC_ALL) ao_host.h ao_flight.c ao_sample.c ao_kalman.c ao_pyro.c ao_pyro.h $(INCS) cc -DTELEMETRUM_V2=1 $(CFLAGS) -o $@ $(TEST_SRC) $(TEST_LIB) -lm @@ -86,7 +90,7 @@ ao_micropeak_test: ao_micropeak_test.c ao_microflight.c ao_kalman.h cc $(CFLAGS) -o $@ ao_micropeak_test.c -lm ao_fat_test: ao_fat_test.c ao_fat.c ao_bufio.c - cc $(CFLAGS) -o $@ ao_fat_test.c -lssl -lcrypto + cc $(CFLAGS) -o $@ ao_fat_test.c -Wno-deprecated-declarations -lssl -lcrypto ao_aes_test: ao_aes_test.c ao_aes.c ao_aes_tables.c cc $(CFLAGS) -o $@ ao_aes_test.c diff --git a/src/test/ao_fat_test.c b/src/test/ao_fat_test.c index 63be71c6..dc6337fc 100644 --- a/src/test/ao_fat_test.c +++ b/src/test/ao_fat_test.c @@ -485,7 +485,7 @@ long_test_fs(void) } } - printf ("\n **** Write IO: read %llu write %llu data sectors %llu\n", total_reads, total_writes, (total_file_size + 511) / 512); + printf ("\n **** Write IO: read %lu write %lu data sectors %lu\n", total_reads, total_writes, (total_file_size + 511) / 512); check_bufio("all files created"); printf (" **** All done creating files\n"); @@ -518,7 +518,7 @@ long_test_fs(void) check_bufio("file shown"); } } - printf ("\n **** Read IO: read %llu write %llu\n", total_reads, total_writes); + printf ("\n **** Read IO: read %lu write %lu\n", total_reads, total_writes); } char *params[] = { diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index fc1dfa8f..e49035b5 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -28,6 +28,20 @@ #include #define log ao_log_data +#define AO_TICK_TYPE uint32_t +#define AO_TICK_SIGNED int32_t + +typedef int32_t pres_t; +#define pres_to_altitude(p) ao_pa_to_altitude(p) +#define ao_data_pres_cook(packet) ao_ms5607_convert(&packet->ms5607_raw, &packet->ms5607_cooked) +#define ao_data_pres(packet) ((packet)->ms5607_cooked.pres) +#define AO_ADC_MAX 4095 +#define AO_PYRO_BATTERY_DIV_PLUS 100 +#define AO_PYRO_BATTERY_DIV_MINUS 27 +#define AO_IGNITE_DIV_PLUS 100 +#define AO_IGNITE_DIV_MINUS 27 +#define AO_ADC_REFERENCE_DV 33 + #define GRAVITY 9.80665 #define AO_HERTZ 100 @@ -48,7 +62,7 @@ int ao_gps_new; -#if !defined(TELEMEGA) && !defined(TELEMETRUM_V2) && !defined(EASYMINI) && !defined(EASYMOTOR_V_2) +#if !defined(TELEMEGA) && !defined(TELEMETRUM_V2) && !defined(EASYMINI) && !defined(EASYMOTOR_V_2) && !defined(TELEMEGA_V4) #define TELEMETRUM_V1 1 #endif @@ -71,6 +85,49 @@ struct ao_adc { }; #endif +#if TELEMEGA_V4 +#define AO_ADC_NUM_SENSE 6 +#define HAS_MS5607 1 +#define HAS_BMX160 1 +#define HAS_ADXL375 1 +#define AO_ADXL375_INVERT 1 +#define AO_ADXL375_AXIS x +#define HAS_BEEP 1 +#define HAS_BARO 1 +#define AO_CONFIG_MAX_SIZE 1024 + +struct ao_adc { + int16_t sense[AO_ADC_NUM_SENSE]; + int16_t v_batt; + int16_t v_pbatt; + int16_t temp; +}; + +#define ao_data_along(packet) ((packet)->bmx160.acc_x) +#define ao_data_across(packet) (-(packet)->bmx160.acc_y) +#define ao_data_through(packet) ((packet)->bmx160.acc_z) + +#define ao_data_roll(packet) ((packet)->bmx160.gyr_x) +#define ao_data_pitch(packet) (-(packet)->bmx160.gyr_y) +#define ao_data_yaw(packet) ((packet)->bmx160.gyr_z) + +#define ao_data_mag_along(packet) ((packet)->bmx160.mag_x) +#define ao_data_mag_across(packet) ((packet)->bmx160.mag_y) +#define ao_data_mag_through(packet) ((packet)->bmx160.mag_z) + +#define ao_data_set_along(packet,v) ((packet)->bmx160.acc_x = (v)) +#define ao_data_set_across(packet,v) ((packet)->bmx160.acc_y = -(v)) +#define ao_data_set_through(packet,v) ((packet)->bmx160.acc_z = (v)) + +#define ao_data_set_roll(packet,v) ((packet)->bmx160.gyr_x = (v)) +#define ao_data_set_pitch(packet,v) ((packet)->bmx160.gyr_y = -(v)) +#define ao_data_set_yaw(packet,v) ((packet)->bmx160.gyr_z = (v)) + +#define ao_data_set_mag_along(packet,v) ((packet)->bmx160.mag_x = (v)) +#define ao_data_set_mag_across(packet,v) ((packet)->bmx160.mag_y = (v)) +#define ao_data_set_mag_through(packet,v) ((packet)->bmx160.mag_z = (v)) +#endif + #if TELEMETRUM_V2 #define AO_ADC_NUM_SENSE 2 #define HAS_MS5607 1 @@ -149,7 +206,7 @@ struct ao_adc { #define HAS_USB 1 #define HAS_GPS 1 -int16_t +AO_TICK_TYPE ao_time(void); void @@ -158,12 +215,19 @@ ao_dump_state(void); #define ao_tick_count (ao_time()) #define ao_wakeup(wchan) ao_dump_state() +enum ao_igniter_status { + ao_igniter_unknown, /* unknown status (ambiguous voltage) */ + ao_igniter_ready, /* continuity detected */ + ao_igniter_active, /* igniter firing */ + ao_igniter_open, /* open circuit detected */ +}; + #include #include #include #include -#if TELEMEGA +#if TELEMEGA || TELEMEGA_V4 int ao_gps_count; struct ao_telemetry_location ao_gps_first; struct ao_telemetry_location ao_gps_prev; @@ -289,12 +353,12 @@ double drogue_time; int main_height; double main_time; -int tick_offset; +uint32_t tick_offset; static ao_k_t ao_k_height; static double simple_speed; -int16_t +AO_TICK_TYPE ao_time(void) { return ao_data_static.tick; @@ -360,12 +424,12 @@ struct ao_cmds { }; #define AO_NEED_ALTITUDE_TO_PRES 1 -#if TELEMEGA || TELEMETRUM_V2 || EASYMINI +#if TELEMEGA || TELEMETRUM_V2 || EASYMINI || TELEMEGA_V4 #include "ao_convert_pa.c" #include struct ao_ms5607_prom ao_ms5607_prom; #include "ao_ms5607_convert.c" -#if TELEMEGA +#if TELEMEGA || TELEMEGA_V4 #define AO_PYRO_NUM 4 #include #endif @@ -388,7 +452,7 @@ extern int16_t ao_accel_2g; typedef int16_t accel_t; uint16_t ao_serial_number; -int16_t ao_flight_number; +uint16_t ao_flight_number; extern AO_TICK_TYPE ao_sample_tick; @@ -406,6 +470,7 @@ double ao_sample_qangle; AO_TICK_TYPE ao_sample_prev_tick; AO_TICK_TYPE prev_tick; +AO_TICK_TYPE start_tick; #include "ao_kalman.c" @@ -413,7 +478,7 @@ AO_TICK_TYPE prev_tick; #include "ao_sample.c" #include "ao_flight.c" #include "ao_data.c" -#if TELEMEGA +#if TELEMEGA || TELEMEGA_V4 #define AO_PYRO_NUM 4 #define AO_PYRO_0 0 @@ -426,7 +491,6 @@ AO_TICK_TYPE prev_tick; static void ao_pyro_pin_set(uint8_t pin, uint8_t value) { - printf ("set pyro %d %d\n", pin, value); } #include "ao_pyro.c" @@ -459,6 +523,9 @@ static uint16_t pyros_fired; #if HAS_MPU6000 static struct ao_mpu6000_sample ao_ground_mpu6000; #endif +#if HAS_BMX160 +static struct ao_bmx160_sample ao_ground_bmx160; +#endif void ao_test_exit(void) @@ -497,7 +564,7 @@ ao_test_exit(void) exit(0); } -#ifdef TELEMEGA +#if TELEMEGA || TELEMEGA_V4 struct ao_azel { int az; int el; @@ -529,9 +596,9 @@ ao_insert(void) #endif (void) accel; - if (!tick_offset) - tick_offset = -ao_data_static.tick; - if ((prev_tick - ao_data_static.tick) > 0x400) + if (!start_tick) + start_tick = ao_data_static.tick; + if ((AO_TICK_SIGNED) (prev_tick - ao_data_static.tick) > 0x400) tick_offset += 65536; if (prev_tick) { int ticks = ao_data_static.tick - prev_tick; @@ -540,11 +607,11 @@ ao_insert(void) simple_speed += accel * ticks / 100.0; } prev_tick = ao_data_static.tick; - time = (double) (ao_data_static.tick + tick_offset) / 100; + time = (double) (ao_data_static.tick + tick_offset - start_tick) / 100; double height = 0; #if HAS_BARO -#if TELEMEGA || TELEMETRUM_V2 || EASYMINI +#if TELEMEGA || TELEMETRUM_V2 || EASYMINI || TELEMEGA_V4 ao_ms5607_convert(&ao_data_static.ms5607_raw, &ao_data_static.ms5607_cooked); height = ao_pa_to_altitude(ao_data_static.ms5607_cooked.pres) - ao_ground_height; @@ -589,7 +656,7 @@ ao_insert(void) } if (!ao_summary) { -#if TELEMEGA +#if TELEMEGA || TELEMEGA_V4 static struct ao_quaternion ao_ground_mag; static int ao_ground_mag_set; @@ -680,10 +747,10 @@ ao_insert(void) #if 1 printf("%7.2f height %8.2f accel %8.3f accel_speed %8.3f " "state %d k_height %8.2f k_speed %8.3f k_accel %8.3f avg_height %5d drogue %4d main %4d error %5d" -#if TELEMEGA +#if TELEMEGA || TELEMEGA_V4 " angle %5d " "accel_x %8.3f accel_y %8.3f accel_z %8.3f gyro_x %8.3f gyro_y %8.3f gyro_z %8.3f mag_x %8d mag_y %8d, mag_z %8d mag_angle %4d " - "avg_accel %8.3f " + "avg_accel %8.3f pyro %d inhibited %d" #endif "\n", time, @@ -711,7 +778,26 @@ ao_insert(void) ao_data_static.hmc5883.y, ao_data_static.hmc5883.z, ao_mag_angle, - ao_coast_avg_accel / 16.0 + ao_coast_avg_accel / 16.0, + ao_pyro_fired * 10, + ao_pyro_inhibited * 10 +#endif +#if TELEMEGA_V4 + , ao_sample_orient, + + ao_bmx160_accel(ao_data_static.bmx160.acc_x), + ao_bmx160_accel(ao_data_static.bmx160.acc_y), + ao_bmx160_accel(ao_data_static.bmx160.acc_z), + ao_bmx160_gyro(ao_data_static.bmx160.gyr_x - ao_ground_bmx160.gyr_x), + ao_bmx160_gyro(ao_data_static.bmx160.gyr_y - ao_ground_bmx160.gyr_y), + ao_bmx160_gyro(ao_data_static.bmx160.gyr_z - ao_ground_bmx160.gyr_z), + ao_data_static.bmx160.mag_x, + ao_data_static.bmx160.mag_y, + ao_data_static.bmx160.mag_z, + ao_mag_angle, + ao_coast_avg_accel / 16.0, + ao_pyro_fired * 10, + ao_pyro_inhibited * 10 #endif ); #endif @@ -769,7 +855,7 @@ void ao_sleep(void *wchan) { if (wchan == &ao_data_head) { -#if TELEMEGA +#if TELEMEGA || TELEMEGA_V4 if (ao_flight_state >= ao_flight_boost && ao_flight_state < ao_flight_landed) ao_pyro_check(); #endif @@ -780,6 +866,9 @@ ao_sleep(void *wchan) #if TELEMEGA ao_data_static.mpu6000 = ao_ground_mpu6000; #endif +#if TELEMEGA_V4 + ao_data_static.bmx160 = ao_ground_bmx160; +#endif #if TELEMETRUM_V1 ao_data_static.adc.accel = ao_flight_ground_accel; #endif @@ -792,7 +881,7 @@ ao_sleep(void *wchan) } if (eeprom) { -#if TELEMEGA || EASYMOTOR_V_2 +#if TELEMEGA || EASYMOTOR_V_2 || TELEMEGA_V4 struct ao_log_mega *log_mega; #endif #if EASYMOTOR_V_2 @@ -892,6 +981,102 @@ ao_sleep(void *wchan) } break; #endif +#if TELEMEGA_V4 + case AO_LOG_FORMAT_TELEMEGA_4: + log_mega = (struct ao_log_mega *) &eeprom->data[eeprom_offset]; + eeprom_offset += sizeof (*log_mega); + switch (log_mega->type) { + case AO_LOG_FLIGHT: + ao_flight_number = log_mega->u.flight.flight; + ao_flight_ground_accel = log_mega->u.flight.ground_accel; + ao_flight_started = 1; + ao_ground_pres = log_mega->u.flight.ground_pres; + ao_ground_height = ao_pa_to_altitude(ao_ground_pres); + ao_ground_accel_along = log_mega->u.flight.ground_accel_along; + ao_ground_accel_across = log_mega->u.flight.ground_accel_across; + ao_ground_accel_through = log_mega->u.flight.ground_accel_through; + ao_ground_roll = log_mega->u.flight.ground_roll; + ao_ground_pitch = log_mega->u.flight.ground_pitch; + ao_ground_yaw = log_mega->u.flight.ground_yaw; + ao_ground_bmx160.acc_x = ao_ground_accel_along; + ao_ground_bmx160.acc_y = -ao_ground_accel_across; + ao_ground_bmx160.acc_z = ao_ground_accel_through; + ao_ground_bmx160.gyr_x = ao_ground_roll >> 9; + ao_ground_bmx160.gyr_y = -(ao_ground_pitch >> 9); + ao_ground_bmx160.gyr_z = ao_ground_yaw >> 9; + break; + case AO_LOG_STATE: + break; + case AO_LOG_SENSOR: + ao_data_static.tick = log_mega->tick; + ao_data_static.ms5607_raw.pres = log_mega->u.sensor.pres; + ao_data_static.ms5607_raw.temp = log_mega->u.sensor.temp; + ao_data_set_along(&ao_data_static, log_mega->u.sensor.accel_along); + ao_data_set_across(&ao_data_static, log_mega->u.sensor.accel_across); + ao_data_set_through(&ao_data_static, log_mega->u.sensor.accel_through); + ao_data_set_roll(&ao_data_static, log_mega->u.sensor.gyro_roll); + ao_data_set_pitch(&ao_data_static, log_mega->u.sensor.gyro_pitch); + ao_data_set_yaw(&ao_data_static, log_mega->u.sensor.gyro_yaw); + ao_data_set_mag_along(&ao_data_static, log_mega->u.sensor.mag_along); + ao_data_set_mag_across(&ao_data_static, log_mega->u.sensor.mag_across); + ao_data_set_mag_through(&ao_data_static, log_mega->u.sensor.mag_through); +#if AO_ADXL375_INVERT + ao_data_static.adxl375.AO_ADXL375_AXIS = ao_data_accel_invert(log_mega->u.sensor.accel); +#else + ao_data_static.adxl375.AO_ADXL375_AXIS = log_mega->u.sensor.accel; +#endif + if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP) + ao_data_static.adxl375.AO_ADXL375_AXIS = ao_data_accel_invert(ao_data_static.adxl375.AO_ADXL375_AXIS); + ao_records_read++; + ao_insert(); + return; + case AO_LOG_TEMP_VOLT: + if (pyros_fired != log_mega->u.volt.pyro) { + printf("pyro changed %x -> %x\n", pyros_fired, log_mega->u.volt.pyro); + pyros_fired = log_mega->u.volt.pyro; + } + break; + case AO_LOG_GPS_TIME: + ao_gps_prev = ao_gps_static; + ao_gps_static.tick = log_mega->tick; + ao_gps_static.latitude = log_mega->u.gps.latitude; + ao_gps_static.longitude = log_mega->u.gps.longitude; + { + int16_t altitude_low = log_mega->u.gps.altitude_low; + int16_t altitude_high = log_mega->u.gps.altitude_high; + int32_t altitude = altitude_low | ((int32_t) altitude_high << 16); + + AO_TELEMETRY_LOCATION_SET_ALTITUDE(&ao_gps_static, altitude); + } + ao_gps_static.flags = log_mega->u.gps.flags; + if (!ao_gps_count) + ao_gps_first = ao_gps_static; + ao_gps_count++; + break; + case AO_LOG_GPS_SAT: + break; + } + break; +#endif +#ifdef foo_TELEMEGA_V4 + case AO_LOG_FORMAT_TELEMEGA_4: + log_mega = (struct ao_log_mega *) &eeprom->data[eeprom_offset]; + eeprom_offset += sizeof (*log_mega); + switch (log_mega->type) { + case AO_LOG_FLIGHT: + ao_flight_number = log_mega->u.flight.flight; + ao_flight_ground_accel = log_mega->u.flight.ground_accel; + ao_flight_started = 1; + break; + case AO_LOG_SENSOR: + ao_data_static.tick = log_mega->tick; + ao_data_static.adxl375.AO_ADXL375_AXIS = log_mega->u.sensor.accel; + ao_records_read++; + ao_insert(); + return; + } + break; +#endif #if TELEMETRUM_V2 case AO_LOG_FORMAT_TELEMETRUM: log_metrum = (struct ao_log_metrum *) &eeprom->data[eeprom_offset]; diff --git a/src/test/ao_gps_test.c b/src/test/ao_gps_test.c index 7c1ecc15..1e7847e5 100644 --- a/src/test/ao_gps_test.c +++ b/src/test/ao_gps_test.c @@ -17,6 +17,7 @@ */ #define AO_GPS_TEST +#define AO_TICK_TYPE uint32_t #include "ao_host.h" #include #include diff --git a/src/test/ao_gps_test_skytraq.c b/src/test/ao_gps_test_skytraq.c index 11c54601..bd8998b7 100644 --- a/src/test/ao_gps_test_skytraq.c +++ b/src/test/ao_gps_test_skytraq.c @@ -17,7 +17,9 @@ */ #define AO_GPS_TEST +#define AO_TICK_TYPE uint32_t #define HAS_GPS 1 +#define tick_count 0 #include "ao_host.h" #include #include @@ -49,6 +51,8 @@ struct ao_gps_orig { int16_t altitude; /* m */ uint16_t ground_speed; /* cm/s */ uint8_t course; /* degrees / 2 */ + uint8_t pdop; /* unused */ + uint8_t vdop; /* unused */ uint8_t hdop; /* * 5 */ int16_t climb_rate; /* cm/s */ uint16_t h_error; /* m */ diff --git a/src/test/ao_gps_test_ublox.c b/src/test/ao_gps_test_ublox.c index 0833e4f6..6cccf0e5 100644 --- a/src/test/ao_gps_test_ublox.c +++ b/src/test/ao_gps_test_ublox.c @@ -17,12 +17,15 @@ */ #define AO_GPS_TEST +#define AO_TICK_TYPE uint32_t #define HAS_GPS 1 +#define ao_tick_count 0 #include "ao_host.h" #include #include #include #include +#include #include #include #define AO_GPS_NUM_SAT_MASK (0xf << 0) diff --git a/src/test/ao_micropeak_test.c b/src/test/ao_micropeak_test.c index 952460d0..ac4a69bd 100644 --- a/src/test/ao_micropeak_test.c +++ b/src/test/ao_micropeak_test.c @@ -17,6 +17,7 @@ */ #define _GNU_SOURCE +#define AO_TICK_TYPE uint32_t #include #include diff --git a/src/test/plotmm b/src/test/plotmm index 27f8ddcd..87f34cd9 100755 --- a/src/test/plotmm +++ b/src/test/plotmm @@ -14,7 +14,7 @@ case $# in exit 1 esac -gnuplot -persist << EOF +cat - /dev/tty < Date: Sat, 11 May 2024 19:03:51 -0700 Subject: [PATCH 15/15] altosui: Add config and pyro tabs to graph widget Show the flight computer configuration in the graph when available. Signed-off-by: Keith Packard --- altoslib/AltosConfigData.java | 4 + altoslib/AltosDataListener.java | 4 + altoslib/AltosLib.java | 24 ++++ altoslib/AltosRecordSet.java | 1 + altoslib/AltosTelemetryFile.java | 4 + altosui/AltosConfigFCUI.java | 29 +--- altosui/AltosGraphUI.java | 20 ++- altosuilib/AltosFlightConfigTable.java | 189 +++++++++++++++++++++++++ altosuilib/AltosFlightPyroTable.java | 184 ++++++++++++++++++++++++ altosuilib/Makefile.am | 2 + 10 files changed, 435 insertions(+), 26 deletions(-) create mode 100644 altosuilib/AltosFlightConfigTable.java create mode 100644 altosuilib/AltosFlightPyroTable.java diff --git a/altoslib/AltosConfigData.java b/altoslib/AltosConfigData.java index 6b980be6..b076357d 100644 --- a/altoslib/AltosConfigData.java +++ b/altoslib/AltosConfigData.java @@ -245,6 +245,10 @@ public class AltosConfigData { return false; } + public boolean has_radio() { + return product.startsWith("Tele"); + } + int[] parse_version(String v) { String[] parts = v.split("\\."); int r[] = new int[parts.length]; diff --git a/altoslib/AltosDataListener.java b/altoslib/AltosDataListener.java index b19cbedb..18ffd988 100644 --- a/altoslib/AltosDataListener.java +++ b/altoslib/AltosDataListener.java @@ -39,6 +39,10 @@ public abstract class AltosDataListener { return cal_data; } + public AltosConfigData config_data() { + return null; + } + public void set_time(double time) { if (time != AltosLib.MISSING) this.time = time; diff --git a/altoslib/AltosLib.java b/altoslib/AltosLib.java index fbbfd63c..dd2a4bae 100644 --- a/altoslib/AltosLib.java +++ b/altoslib/AltosLib.java @@ -235,6 +235,30 @@ public class AltosLib { "Compressed", "Uncompressed" }; + public static final String[] ignite_mode_values = { + "Dual Deploy", + "Redundant Apogee", + "Redundant Main", + "Separation & Apogee", + }; + + public static final String[] pad_orientation_values_radio = { + "Antenna Up", + "Antenna Down", + }; + + public static final String[] pad_orientation_values_no_radio = { + "Beeper Up", + "Beeper Down", + }; + + public static String[] pad_orientation_values(boolean radio) { + if (radio) + return pad_orientation_values_radio; + else + return pad_orientation_values_no_radio; + } + public static final String launch_sites_url = "https://maps.altusmetrum.org/launch-sites.txt"; public static final String launch_sites_env = "LAUNCH_SITES"; // public static final String launch_sites_url = "file:///home/keithp/misc/text/altusmetrum/AltOS/launch-sites.txt"; diff --git a/altoslib/AltosRecordSet.java b/altoslib/AltosRecordSet.java index c889cdab..b6be02a5 100644 --- a/altoslib/AltosRecordSet.java +++ b/altoslib/AltosRecordSet.java @@ -18,6 +18,7 @@ import java.util.*; public interface AltosRecordSet { public AltosCalData cal_data(); + public AltosConfigData config_data(); public void capture_series(AltosDataListener listener); public boolean valid(); } diff --git a/altoslib/AltosTelemetryFile.java b/altoslib/AltosTelemetryFile.java index 6f01f51c..5ba32518 100644 --- a/altoslib/AltosTelemetryFile.java +++ b/altoslib/AltosTelemetryFile.java @@ -138,6 +138,10 @@ public class AltosTelemetryFile implements AltosRecordSet { listener.finish(); } + public AltosConfigData config_data() { + return null; + } + public AltosTelemetryFile(FileInputStream input) throws IOException { telems = new AltosTelemetryIterable(input); } diff --git a/altosui/AltosConfigFCUI.java b/altosui/AltosConfigFCUI.java index 3e5bede5..9d39cda1 100644 --- a/altosui/AltosConfigFCUI.java +++ b/altosui/AltosConfigFCUI.java @@ -123,13 +123,6 @@ public class AltosConfigFCUI "0", "5", "10", "15", "20" }; - static String[] ignite_mode_values = { - "Dual Deploy", - "Redundant Apogee", - "Redundant Main", - "Separation & Apogee", - }; - static String[] aprs_interval_values = { "Disabled", "2", @@ -154,16 +147,6 @@ public class AltosConfigFCUI "4250", }; - static String[] pad_orientation_values_radio = { - "Antenna Up", - "Antenna Down", - }; - - static String[] pad_orientation_values_no_radio = { - "Beeper Up", - "Beeper Down", - }; - String[] pad_orientation_values; static String[] tracker_motion_values_m = { @@ -328,11 +311,7 @@ public class AltosConfigFCUI } void set_pad_orientation_values() { - String [] new_values; - if (has_radio()) - new_values = pad_orientation_values_radio; - else - new_values = pad_orientation_values_no_radio; + String [] new_values = AltosLib.pad_orientation_values(has_radio()); if (new_values != pad_orientation_values) { int id = pad_orientation_value.getSelectedIndex(); pad_orientation_value.removeAllItems(); @@ -893,7 +872,7 @@ public class AltosConfigFCUI c.anchor = GridBagConstraints.LINE_START; c.insets = ir; c.ipady = 5; - ignite_mode_value = new JComboBox(ignite_mode_values); + ignite_mode_value = new JComboBox(AltosLib.ignite_mode_values); ignite_mode_value.setEditable(false); ignite_mode_value.addItemListener(this); pane.add(ignite_mode_value, c); @@ -919,7 +898,7 @@ public class AltosConfigFCUI c.anchor = GridBagConstraints.LINE_START; c.insets = ir; c.ipady = 5; - pad_orientation_values = pad_orientation_values_no_radio; + pad_orientation_values = AltosLib.pad_orientation_values(false); pad_orientation_value = new JComboBox(pad_orientation_values); pad_orientation_value.setEditable(false); @@ -1453,7 +1432,7 @@ public class AltosConfigFCUI public void set_ignite_mode(int new_ignite_mode) { if (new_ignite_mode != AltosLib.MISSING) { - if (new_ignite_mode >= ignite_mode_values.length) + if (new_ignite_mode >= AltosLib.ignite_mode_values.length) new_ignite_mode = 0; if (new_ignite_mode < 0) { ignite_mode_value.setEnabled(false); diff --git a/altosui/AltosGraphUI.java b/altosui/AltosGraphUI.java index 127a5beb..8f52728b 100644 --- a/altosui/AltosGraphUI.java +++ b/altosui/AltosGraphUI.java @@ -39,6 +39,8 @@ public class AltosGraphUI extends AltosUIFrame implements AltosFontListener, Alt AltosUIMap map; AltosFlightStats stats; AltosFlightStatsTable statsTable; + AltosFlightConfigTable configTable; + AltosFlightPyroTable pyroTable; AltosGPS gps; boolean has_gps; @@ -77,6 +79,10 @@ public class AltosGraphUI extends AltosUIFrame implements AltosFontListener, Alt map.font_size_changed(font_size); if (statsTable != null) statsTable.font_size_changed(font_size); + if (configTable != null) + configTable.font_size_changed(font_size); + if (pyroTable != null) + pyroTable.font_size_changed(font_size); } public void units_changed(boolean imperial_units) { @@ -84,6 +90,10 @@ public class AltosGraphUI extends AltosUIFrame implements AltosFontListener, Alt map.units_changed(imperial_units); if (enable != null) enable.units_changed(imperial_units); + if (configTable != null) + configTable.units_changed(imperial_units); + if (pyroTable != null) + pyroTable.units_changed(imperial_units); } AltosUIFlightSeries flight_series; @@ -106,7 +116,7 @@ public class AltosGraphUI extends AltosUIFrame implements AltosFontListener, Alt AltosGraphUI(AltosRecordSet set, File file) throws InterruptedException, IOException { super(file.getName()); AltosCalData cal_data = set.cal_data(); - + AltosConfigData config_data = set.config_data(); pane = new JTabbedPane(); @@ -127,6 +137,14 @@ public class AltosGraphUI extends AltosUIFrame implements AltosFontListener, Alt pane.add("Flight Graph", graph.panel); pane.add("Configure Graph", enable); pane.add("Flight Statistics", statsTable); + if (config_data != null) { + configTable = new AltosFlightConfigTable(config_data); + pane.add("Configuration", configTable); + if (config_data.npyro > 0) { + pyroTable = new AltosFlightPyroTable(config_data.pyros, config_data.npyro); + pane.add("Pyros", pyroTable); + } + } has_gps = false; fill_map(flight_series); diff --git a/altosuilib/AltosFlightConfigTable.java b/altosuilib/AltosFlightConfigTable.java new file mode 100644 index 00000000..4f9714f6 --- /dev/null +++ b/altosuilib/AltosFlightConfigTable.java @@ -0,0 +1,189 @@ +/* + * Copyright © 2024 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.altosuilib_14; + +import java.awt.*; +import javax.swing.*; +import java.util.*; +import org.altusmetrum.altoslib_14.*; + +public class AltosFlightConfigTable extends JComponent + implements AltosFontListener, AltosUnitsListener +{ + GridBagLayout layout; + + FlightConfig[] flight_configs; + AltosConfigData config_data; + + class FlightConfig implements AltosFontListener { + JLabel label; + JLabel[] value; + + public void font_size_changed(int font_size) { + label.setFont(AltosUILib.label_font); + for (int i = 0; i < value.length; i++) + value[i].setFont(AltosUILib.value_font); + } + + public void set(String l, String[] values) { + label.setText(l); + for (int j = 0; j < values.length; j++) + value[j].setText(values[j]); + } + + public FlightConfig(GridBagLayout layout, int y, String label_text, String ... values) { + GridBagConstraints c = new GridBagConstraints(); + c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad); + c.weighty = 1; + + label = new JLabel(label_text); + label.setFont(AltosUILib.label_font); + label.setHorizontalAlignment(SwingConstants.LEFT); + c.gridx = 0; c.gridy = y; + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; + layout.setConstraints(label, c); + add(label); + + value = new JLabel[values.length]; + for (int j = 0; j < values.length; j++) { + value[j] = new JLabel(values[j]); + value[j].setFont(AltosUILib.value_font); + c.gridx = j+1; c.gridy = y; + c.anchor = GridBagConstraints.CENTER; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + layout.setConstraints(value[j], c); + add(value[j]); + } + flight_configs[y] = this; + } + + } + + private FlightConfig set_config(int y, String label, String ... values) { + if (flight_configs[y] == null) + flight_configs[y] = new FlightConfig(layout, y, label, values); + else + flight_configs[y].set(label, values); + return flight_configs[y]; + } + + public void font_size_changed(int font_size) { + for (int y = 0; flight_configs[y] != null; y++) + flight_configs[y].font_size_changed(font_size); + } + + private String main_deploy_label() { + return String.format("Main Deploy Altitude(%s)", AltosConvert.height.parse_units()); + } + + private String main_deploy_value() { + return String.format("%-6.1f", AltosConvert.height.value(config_data.main_deploy, AltosConvert.imperial_units)); + } + + public void set_config() { + int y = 0; + if (config_data.serial != AltosLib.MISSING) { + if (config_data.product != null && config_data.version != null) + set_config(y++, "Device", + config_data.product, + String.format("version %s", config_data.version), + String.format("serial %d", config_data.serial)); + else + set_config(y++, "Serial", String.format("%d", config_data.serial)); + } + if (config_data.flight != AltosLib.MISSING) + set_config(y++, "Flight", String.format("%d", config_data.flight)); + if (config_data.main_deploy != AltosLib.MISSING) + set_config(y++, main_deploy_label(), main_deploy_value()); + if (config_data.apogee_delay != AltosLib.MISSING) + set_config(y++, "Apogee Delay(s)", String.format("%d", config_data.apogee_delay)); + if (config_data.apogee_lockout != AltosLib.MISSING) + set_config(y++, "Apogee Lockout(s)", String.format("%d", config_data.apogee_lockout)); + if (config_data.radio_frequency != AltosLib.MISSING) + set_config(y++, "Radio Frequency (MHz)", String.format("%-7.3f", config_data.radio_frequency / 1000.0)); + if (config_data.radio_calibration != AltosLib.MISSING) + set_config(y++, "Radio Calibration", String.format("%d", config_data.radio_calibration)); + if (config_data.radio_enable != AltosLib.MISSING) + set_config(y++, "Radio Enable", String.format("%b", config_data.radio_enable != 0)); + if (config_data.radio_10mw != AltosLib.MISSING) + set_config(y++, "Limit transmit to 10mW", String.format("%b", config_data.radio_10mw != 0)); + if (config_data.report_feet != AltosLib.MISSING) + set_config(y++, "Beep max height in", config_data.report_feet == 0 ? "Meters" : "Feet"); + if (config_data.gps_receiver != AltosLib.MISSING) + set_config(y++, "GPS Receiver", AltosLib.gps_receiver_names[config_data.gps_receiver]); + if (config_data.telemetry_rate != AltosLib.MISSING) + set_config(y++, "Telemetry baud rate", String.format("%d", AltosLib.ao_telemetry_rate_values[config_data.telemetry_rate])); + if (config_data.aprs_interval != AltosLib.MISSING) + set_config(y++, "APRS Interval(s)", String.format("%d", config_data.aprs_interval)); + if (config_data.aprs_ssid != AltosLib.MISSING) + set_config(y++, "APRS SSID", String.format("%d", config_data.aprs_ssid)); + if (config_data.aprs_format != AltosLib.MISSING) + set_config(y++, "APRS Format", AltosLib.ao_aprs_format_name[config_data.aprs_format]); + if (config_data.callsign != null) + set_config(y++, "Callsign", config_data.callsign); + if (config_data.flight_log_max != AltosLib.MISSING) + set_config(y++, "Maximum Flight Log Size(kB)", String.format("%d", config_data.flight_log_max)); + if (config_data.ignite_mode != AltosLib.MISSING) + set_config(y++, "Igniter Firing Mode", AltosLib.ignite_mode_values[config_data.ignite_mode]); + if (config_data.pad_orientation != AltosLib.MISSING) + set_config(y++, "Pad Orientation", AltosLib.pad_orientation_values(config_data.has_radio())[config_data.pad_orientation]); + if (config_data.accel_cal_plus != AltosLib.MISSING) + set_config(y++, "Accel Calibration", + String.format("Plus %d", config_data.accel_cal_plus), + String.format("Minus %d", config_data.accel_cal_minus)); + if (config_data.beep != AltosLib.MISSING) + set_config(y++, "Beeper(Hz)", + config_data.beep == 0 ? "Disabled" : + String.format("%-7.1f", AltosConvert.beep_value_to_freq(config_data.beep))); + if (config_data.tracker_motion != AltosLib.MISSING) + set_config(y++, + String.format("Logging Trigger Motion (%s):", AltosConvert.height.parse_units()), + String.format("%-6.1f", + AltosConvert.height.value(config_data.tracker_motion, AltosConvert.imperial_units))); + if (config_data.tracker_interval != AltosLib.MISSING) + set_config(y++, "Position Reporting Interval(s)", + String.format("%d", config_data.tracker_interval)); + } + + public void units_changed(boolean imperial_units) { + set_config(); + } + + public void tell_closing() { + AltosUIPreferences.unregister_font_listener(this); + } + + public AltosFlightConfigTable() { + layout = new GridBagLayout(); + + setLayout(layout); + + AltosUIPreferences.register_font_listener(this); + } + + public AltosFlightConfigTable(AltosConfigData config_data) { + this(); + this.config_data = config_data; + flight_configs = new FlightConfig[30]; + set_config(); + } +} diff --git a/altosuilib/AltosFlightPyroTable.java b/altosuilib/AltosFlightPyroTable.java new file mode 100644 index 00000000..5e27a2f8 --- /dev/null +++ b/altosuilib/AltosFlightPyroTable.java @@ -0,0 +1,184 @@ +/* + * Copyright © 2024 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.altosuilib_14; + +import java.awt.*; +import javax.swing.*; +import java.util.*; +import org.altusmetrum.altoslib_14.*; + +public class AltosFlightPyroTable extends JComponent + implements AltosFontListener, AltosUnitsListener +{ + GridBagLayout layout; + AltosPyro[] pyros; + int npyro; + FlightPyro[] flight_pyros; + + class FlightPyro implements AltosFontListener { + JLabel label; + JTextField[] text_fields; + + public void font_size_changed(int font_size) { + label.setFont(AltosUILib.label_font); + for (int i = 0; i < text_fields.length; i++) + text_fields[i].setFont(AltosUILib.value_font); + } + + public void set_value(int y, int p, String value) { + GridBagConstraints c = new GridBagConstraints(); + c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad); + c.weighty = 1; + JTextField text_field; + + if (text_fields[p] == null) { + text_field = new JTextField(value); + text_field.setEditable(false); + text_field.setFont(AltosUILib.value_font); + text_field.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = p+1; c.gridy = y; + c.anchor = GridBagConstraints.EAST; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + layout.setConstraints(text_field, c); + add(text_field); + text_fields[p] = text_field; + } else { + text_fields[p].setText(value); + } + } + + public void set_label(String text) { + label.setText(text); + } + + public FlightPyro(GridBagLayout layout, int y, String label_text, int npyro) { + GridBagConstraints c = new GridBagConstraints(); + c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad); + c.weighty = 1; + + if (label_text != null) { + label = new JLabel(label_text); + label.setFont(AltosUILib.label_font); + label.setHorizontalAlignment(SwingConstants.LEFT); + c.gridx = 0; c.gridy = y; + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; + layout.setConstraints(label, c); + add(label); + } + + text_fields = new JTextField[npyro]; + } + } + + public void font_size_changed(int font_size) { + for (int i = 0; i < flight_pyros.length; i++) + flight_pyros[i].font_size_changed(font_size); + } + + public void set_pyros() { + int nrow = 1; + for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1) { + if ((AltosPyro.pyro_all_useful & flag) != 0) { + for (int p = 0; p < npyro; p++) { + if ((pyros[p].flags & flag) != 0) { + String text; + double value = pyros[p].get_value(flag); + if ((flag & AltosPyro.pyro_state_value) != 0) { + text = AltosLib.state_name_capital((int) value); + } else { + double scale = AltosPyro.pyro_to_scale(flag); + double unit_value = value; + AltosUnits units = AltosPyro.pyro_to_units(flag); + if (units != null) + unit_value = units.parse_value(value); + String format; + if (scale >= 100) + format = "%6.2f"; + else if (scale >= 10) + format = "%6.1f"; + else + format = "%6.0f"; + text = String.format(format, unit_value); + } + flight_pyros[nrow].set_value(nrow, p, text); + } + } + nrow++; + } + } + } + + public void units_changed(boolean imperial_units) { + System.out.printf("units changed\n"); + int nrow = 1; + for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1) { + if ((AltosPyro.pyro_all_useful & flag) != 0) { + String name = AltosPyro.pyro_to_name(flag); + flight_pyros[nrow].set_label(name); + } + } + set_pyros(); + } + + public void tell_closing() { + AltosUIPreferences.unregister_font_listener(this); + } + + public AltosFlightPyroTable(AltosPyro[] pyros, int npyro) { + layout = new GridBagLayout(); + + int nrow = 0; + + for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1) { + if ((AltosPyro.pyro_all_useful & flag) != 0) { + nrow++; + } + } + + flight_pyros = new FlightPyro[nrow + 1]; + + nrow = 0; + + flight_pyros[0] = new FlightPyro(layout, 0, null, npyro); + + for (int p = 0; p < npyro; p++) { + flight_pyros[0].set_value(0, p, String.format("Channel %c", 'A' + p)); + } + nrow++; + for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1) { + if ((AltosPyro.pyro_all_useful & flag) != 0) { + String name = AltosPyro.pyro_to_name(flag); + flight_pyros[nrow] = new FlightPyro(layout, nrow, name, npyro); + nrow++; + } + } + + + this.pyros = pyros; + this.npyro = npyro; + + set_pyros(); + + setLayout(layout); + AltosUIPreferences.register_font_listener(this); + } +} diff --git a/altosuilib/Makefile.am b/altosuilib/Makefile.am index 10a5b494..12bdaaa7 100644 --- a/altosuilib/Makefile.am +++ b/altosuilib/Makefile.am @@ -51,7 +51,9 @@ altosuilib_JAVA = \ AltosFlashUI.java \ AltosRomconfigUI.java \ AltosInfoTable.java \ + AltosFlightConfigTable.java \ AltosFlightInfoTableModel.java \ + AltosFlightPyroTable.java \ AltosFlightStatsTable.java \ AltosBTDevice.java \ AltosBTDeviceIterator.java \ -- 2.30.2