From: Bdale Garbee Date: Tue, 23 Oct 2012 15:38:36 +0000 (-0600) Subject: Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos X-Git-Tag: 1.1.9.2~32 X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=commitdiff_plain;h=055f3232decc07e064d596469b81cf9869411c2d;hp=8ca58e20208495ce63b8256a8ffa43932867e8d5 Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos --- diff --git a/altosdroid/.externalToolBuilders/Generate BuildInfo.java.launch b/altosdroid/.externalToolBuilders/Generate BuildInfo.java.launch new file mode 100644 index 00000000..3b8eff45 --- /dev/null +++ b/altosdroid/.externalToolBuilders/Generate BuildInfo.java.launch @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/altosdroid/.gitignore b/altosdroid/.gitignore index c0bb8dd4..e3acba40 100644 --- a/altosdroid/.gitignore +++ b/altosdroid/.gitignore @@ -1,3 +1,4 @@ local.properties bin gen +src/org/altusmetrum/AltosDroid/BuildInfo.java diff --git a/altosdroid/.project b/altosdroid/.project index 7b56596a..ebe4a4bb 100644 --- a/altosdroid/.project +++ b/altosdroid/.project @@ -5,6 +5,16 @@ + + org.eclipse.ui.externaltools.ExternalToolBuilder + auto,full,incremental, + + + LaunchConfigHandle + <project>/.externalToolBuilders/Generate BuildInfo.java.launch + + + com.android.ide.eclipse.adt.ResourceManagerBuilder diff --git a/altosdroid/Makefile.am b/altosdroid/Makefile.am index 96831b72..3860e110 100644 --- a/altosdroid/Makefile.am +++ b/altosdroid/Makefile.am @@ -30,6 +30,7 @@ SRC=\ $(SRC_DIR)/TelemetryLogger.java \ $(SRC_DIR)/AltosBluetooth.java \ $(SRC_DIR)/DeviceListActivity.java \ + $(SRC_DIR)/BuildInfo.java \ $(SRC_DIR)/Dumper.java all: $(all_target) @@ -38,6 +39,9 @@ $(ALTOSLIB): $(ALTOSLIB_SRCDIR)/$(ALTOSLIB_JAR) mkdir -p $(EXT_LIBDIR) cd $(EXT_LIBDIR) && ln -s $(shell echo $(EXT_LIBDIR) | sed 's|[^/]\+|..|g')/$(ALTOSLIB_SRCDIR)/$(ALTOSLIB_JAR) . +$(SRC_DIR)/BuildInfo.java: + ./buildinfo.sh + if ANDROID install-release: bin/AltosDroid-release.apk $(ADB) install -r bin/AltosDroid-release.apk @@ -55,3 +59,4 @@ endif clean: $(clean_command) +.PHONY: $(SRC_DIR)/BuildInfo.java diff --git a/altosdroid/buildinfo.sh b/altosdroid/buildinfo.sh new file mode 100755 index 00000000..f620c4a0 --- /dev/null +++ b/altosdroid/buildinfo.sh @@ -0,0 +1,31 @@ +#!/bin/sh +# + +describe=$(git describe --always 2>/dev/null || echo '') +if [ -n "$describe" ]; then + version=$(echo $describe | cut -d- -f1) + commitnum=$(echo $describe | cut -d- -f2) + commithash=$(echo $describe | cut -d- -f3) +else + . ../src/Version + version=$VERSION + commitnum='' + commithash='' +fi + +builddate=$(date "+%Y-%m-%d") +buildtime=$(date "+%H:%M") + + +infile=src/org/altusmetrum/AltosDroid/BuildInfo.java.in +outfile=src/org/altusmetrum/AltosDroid/BuildInfo.java + +echo "Version $describe, built on $builddate, $buildtime" + +sed -e "s/@DESCRIBE@/$describe/" \ + -e "s/@VERSION@/$version/" \ + -e "s/@COMMITNUM@/$commitnum/" \ + -e "s/@COMMITHASH@/$commithash/" \ + -e "s/@BUILDDATE@/$builddate/" \ + -e "s/@BUILDTIME@/$buildtime/" \ + $infile > $outfile diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java index 3396f77e..b1fc8d30 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java @@ -189,10 +189,7 @@ public class AltosDroid extends Activity { mSerialView.setText(String.format("%d", state.data.serial)); mFlightView.setText(String.format("%d", state.data.flight)); mStateView.setText(state.data.state()); - double speed = state.speed; - if (!state.ascent) - speed = state.baro_speed; - mSpeedView.setText(String.format("%6.0f m/s", speed)); + mSpeedView.setText(String.format("%6.0f m/s", state.speed())); mAccelView.setText(String.format("%6.0f m/s²", state.acceleration)); mRangeView.setText(String.format("%6.0f m", state.range)); mHeightView.setText(String.format("%6.0f m", state.height)); diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java index 3382d551..264e35c6 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java @@ -67,7 +67,7 @@ public class AltosVoice { speak(state.data.state()); if ((old_state == null || old_state.state <= AltosLib.ao_flight_boost) && state.state > AltosLib.ao_flight_boost) { - speak(String.format("max speed: %d meters per second.", (int) (state.max_speed + 0.5))); + speak(String.format("max speed: %d meters per second.", (int) (state.max_speed() + 0.5))); spoke = true; } else if ((old_state == null || old_state.state < AltosLib.ao_flight_drogue) && state.state >= AltosLib.ao_flight_drogue) { diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/BuildInfo.java.in b/altosdroid/src/org/altusmetrum/AltosDroid/BuildInfo.java.in new file mode 100644 index 00000000..763f814e --- /dev/null +++ b/altosdroid/src/org/altusmetrum/AltosDroid/BuildInfo.java.in @@ -0,0 +1,28 @@ +/* + * Copyright © 2012 Mike Beattie + * + * 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; version 2 of the License. + * + * 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.AltosDroid; + +public class BuildInfo { + public static final String git_describe = "@DESCRIBE@"; + public static final String version = "@VERSION@"; + public static final String commitnum = "@COMMITNUM@"; + public static final String commithash = "@COMMITHASH@"; + public static final String builddate = "@BUILDDATE@"; + public static final String buildtime = "@BUILDTIME@"; +} + diff --git a/altoslib/AltosConfigData.java b/altoslib/AltosConfigData.java index a962b105..45a88783 100644 --- a/altoslib/AltosConfigData.java +++ b/altoslib/AltosConfigData.java @@ -50,6 +50,8 @@ public class AltosConfigData implements Iterable { public int storage_size; public int storage_erase_unit; + public AltosPyro[] pyros; + public static String get_string(String line, String label) throws ParseException { if (line.startsWith(label)) { String quoted = line.substring(label.length()).trim(); @@ -135,6 +137,10 @@ public class AltosConfigData implements Iterable { radio_frequency = 0; stored_flight = 0; serial = -1; + pyros = null; + + int npyro = 0; + int pyro = 0; for (;;) { String line = link.get_reply(); if (line == null) @@ -142,6 +148,16 @@ public class AltosConfigData implements Iterable { if (line.contains("Syntax error")) continue; lines.add(line); + if (pyro < npyro - 1) { + if (pyros == null) + pyros = new AltosPyro[npyro]; + try { + pyros[pyro] = new AltosPyro(pyro, line); + } catch (ParseException e) { + } + ++pyro; + continue; + } try { serial = get_int(line, "serial-number"); } catch (Exception e) {} try { log_format = get_int(line, "log-format"); } catch (Exception e) {} try { main_deploy = get_int(line, "Main deploy:"); } catch (Exception e) {} @@ -173,6 +189,7 @@ public class AltosConfigData implements Iterable { try { get_int(line, "flight"); stored_flight++; } catch (Exception e) {} try { storage_size = get_int(line, "Storage size:"); } catch (Exception e) {} try { storage_erase_unit = get_int(line, "Storage erase unit"); } catch (Exception e) {} + try { npyro = get_int(line, "Pyro-count:"); pyro = 0; } catch (Exception e) {} /* signals the end of the version info */ if (line.startsWith("software-version")) diff --git a/altoslib/AltosEepromMega.java b/altoslib/AltosEepromMega.java index 26bacf8d..af4f8aca 100644 --- a/altoslib/AltosEepromMega.java +++ b/altoslib/AltosEepromMega.java @@ -24,7 +24,7 @@ public class AltosEepromMega { public int tick; public boolean valid; public String data; - public int a, b; + public int config_a, config_b; public int data8[]; @@ -66,12 +66,7 @@ public class AltosEepromMega { public int mag_x() { return data16(20); } public int mag_y() { return data16(22); } public int mag_z() { return data16(24); } - public int accel() { - int a = data16(26); - if (a != 0xffff) - return a; - return accel_y(); - } + public int accel() { return data16(26); } /* AO_LOG_VOLT elements */ public int v_batt() { return data16(0); } @@ -79,6 +74,22 @@ public class AltosEepromMega { public int nsense() { return data16(4); } public int sense(int i) { return data16(6 + i * 2); } + /* AO_LOG_GPS_TIME elements */ + public int latitude() { return data32(0); } + public int longitude() { return data32(4); } + public int altitude() { return data16(8); } + public int hour() { return data8(10); } + public int minute() { return data8(11); } + public int second() { return data8(12); } + public int flags() { return data8(13); } + public int year() { return data8(14); } + public int month() { return data8(15); } + public int day() { return data8(16); } + + /* AO_LOG_GPS_SAT elements */ + public int nsat() { return data16(0); } + public int svid(int n) { return data8(2 + n * 2); } + public int c_n(int n) { return data8(2 + n * 2 + 1); } public AltosEepromMega (AltosEepromChunk chunk, int start) throws ParseException { cmd = chunk.data(start); @@ -126,26 +137,26 @@ public class AltosEepromMega { data = tokens[2]; } else if (tokens[0].equals("Main") && tokens[1].equals("deploy:")) { cmd = AltosLib.AO_LOG_MAIN_DEPLOY; - a = Integer.parseInt(tokens[2]); + config_a = Integer.parseInt(tokens[2]); } else if (tokens[0].equals("Apogee") && tokens[1].equals("delay:")) { cmd = AltosLib.AO_LOG_APOGEE_DELAY; - a = Integer.parseInt(tokens[2]); + config_a = Integer.parseInt(tokens[2]); } else if (tokens[0].equals("Radio") && tokens[1].equals("channel:")) { cmd = AltosLib.AO_LOG_RADIO_CHANNEL; - a = Integer.parseInt(tokens[2]); + config_a = Integer.parseInt(tokens[2]); } else if (tokens[0].equals("Callsign:")) { cmd = AltosLib.AO_LOG_CALLSIGN; data = tokens[1].replaceAll("\"",""); } else if (tokens[0].equals("Accel") && tokens[1].equals("cal")) { cmd = AltosLib.AO_LOG_ACCEL_CAL; - a = Integer.parseInt(tokens[3]); - b = Integer.parseInt(tokens[5]); + config_a = Integer.parseInt(tokens[3]); + config_b = Integer.parseInt(tokens[5]); } else if (tokens[0].equals("Radio") && tokens[1].equals("cal:")) { cmd = AltosLib.AO_LOG_RADIO_CAL; - a = Integer.parseInt(tokens[2]); + config_a = Integer.parseInt(tokens[2]); } else if (tokens[0].equals("Max") && tokens[1].equals("flight") && tokens[2].equals("log:")) { cmd = AltosLib.AO_LOG_MAX_FLIGHT_LOG; - a = Integer.parseInt(tokens[3]); + config_a = Integer.parseInt(tokens[3]); } else if (tokens[0].equals("manufacturer")) { cmd = AltosLib.AO_LOG_MANUFACTURER; data = tokens[1]; @@ -154,38 +165,38 @@ public class AltosEepromMega { data = tokens[1]; } else if (tokens[0].equals("serial-number")) { cmd = AltosLib.AO_LOG_SERIAL_NUMBER; - a = Integer.parseInt(tokens[1]); + config_a = Integer.parseInt(tokens[1]); } else if (tokens[0].equals("log-format")) { cmd = AltosLib.AO_LOG_LOG_FORMAT; - a = Integer.parseInt(tokens[1]); + config_a = Integer.parseInt(tokens[1]); } else if (tokens[0].equals("software-version")) { cmd = AltosLib.AO_LOG_SOFTWARE_VERSION; data = tokens[1]; } else if (tokens[0].equals("ms5607")) { if (tokens[1].equals("reserved:")) { cmd = AltosLib.AO_LOG_BARO_RESERVED; - a = Integer.parseInt(tokens[2]); + config_a = Integer.parseInt(tokens[2]); } else if (tokens[1].equals("sens:")) { cmd = AltosLib.AO_LOG_BARO_SENS; - a = Integer.parseInt(tokens[2]); + config_a = Integer.parseInt(tokens[2]); } else if (tokens[1].equals("off:")) { cmd = AltosLib.AO_LOG_BARO_OFF; - a = Integer.parseInt(tokens[2]); + config_a = Integer.parseInt(tokens[2]); } else if (tokens[1].equals("tcs:")) { cmd = AltosLib.AO_LOG_BARO_TCS; - a = Integer.parseInt(tokens[2]); + config_a = Integer.parseInt(tokens[2]); } else if (tokens[1].equals("tco:")) { cmd = AltosLib.AO_LOG_BARO_TCO; - a = Integer.parseInt(tokens[2]); + config_a = Integer.parseInt(tokens[2]); } else if (tokens[1].equals("tref:")) { cmd = AltosLib.AO_LOG_BARO_TREF; - a = Integer.parseInt(tokens[2]); + config_a = Integer.parseInt(tokens[2]); } else if (tokens[1].equals("tempsens:")) { cmd = AltosLib.AO_LOG_BARO_TEMPSENS; - a = Integer.parseInt(tokens[2]); + config_a = Integer.parseInt(tokens[2]); } else if (tokens[1].equals("crc:")) { cmd = AltosLib.AO_LOG_BARO_CRC; - a = Integer.parseInt(tokens[2]); + config_a = Integer.parseInt(tokens[2]); } else { cmd = AltosLib.AO_LOG_INVALID; data = line; diff --git a/altoslib/AltosEepromMegaIterable.java b/altoslib/AltosEepromMegaIterable.java index 1ab2fcc8..16809089 100644 --- a/altoslib/AltosEepromMegaIterable.java +++ b/altoslib/AltosEepromMegaIterable.java @@ -106,80 +106,47 @@ public class AltosEepromMegaIterable extends AltosRecordIterable { eeprom.sensor_tick = record.tick; has_accel = true; break; - case AltosLib.AO_LOG_PRESSURE: - state.pres = record.b; - state.flight_pres = state.pres; - if (eeprom.n_pad_samples == 0) { - eeprom.n_pad_samples++; - state.ground_pres = state.pres; - } - eeprom.seen |= seen_sensor; - break; case AltosLib.AO_LOG_TEMP_VOLT: state.v_batt = record.v_batt(); state.v_pyro = record.v_pbatt(); - for (int i = 0; i < AltosRecordMM.num_sense; i++) + for (int i = 0; i < record.nsense(); i++) state.sense[i] = record.sense(i); eeprom.seen |= seen_temp_volt; break; -// -// case AltosLib.AO_LOG_DEPLOY: -// state.drogue = record.a; -// state.main = record.b; -// eeprom.seen |= seen_deploy; -// has_ignite = true; -// break; - case AltosLib.AO_LOG_STATE: state.state = record.state(); break; case AltosLib.AO_LOG_GPS_TIME: eeprom.gps_tick = state.tick; - AltosGPS old = state.gps; state.gps = new AltosGPS(); - /* GPS date doesn't get repeated through the file */ - if (old != null) { - state.gps.year = old.year; - state.gps.month = old.month; - state.gps.day = old.day; - } - state.gps.hour = (record.a & 0xff); - state.gps.minute = (record.a >> 8); - state.gps.second = (record.b & 0xff); + state.gps.lat = record.latitude() / 1e7; + state.gps.lon = record.longitude() / 1e7; + state.gps.alt = record.altitude(); + state.gps.year = record.year() + 2000; + state.gps.month = record.month(); + state.gps.day = record.day(); + + state.gps.hour = record.hour(); + state.gps.minute = record.minute(); + state.gps.second = record.second(); - int flags = (record.b >> 8); + int flags = record.flags(); state.gps.connected = (flags & AltosLib.AO_GPS_RUNNING) != 0; state.gps.locked = (flags & AltosLib.AO_GPS_VALID) != 0; state.gps.nsat = (flags & AltosLib.AO_GPS_NUM_SAT_MASK) >> AltosLib.AO_GPS_NUM_SAT_SHIFT; state.new_gps = true; has_gps = true; - break; - case AltosLib.AO_LOG_GPS_LAT: - int lat32 = record.a | (record.b << 16); - state.gps.lat = (double) lat32 / 1e7; - break; - case AltosLib.AO_LOG_GPS_LON: - int lon32 = record.a | (record.b << 16); - state.gps.lon = (double) lon32 / 1e7; - break; - case AltosLib.AO_LOG_GPS_ALT: - state.gps.alt = record.a; + eeprom.seen |= seen_gps_time | seen_gps_lat | seen_gps_lon; break; case AltosLib.AO_LOG_GPS_SAT: if (state.tick == eeprom.gps_tick) { - int svid = record.a; - int c_n0 = record.b >> 8; - state.gps.add_sat(svid, c_n0); + int nsat = record.nsat(); + for (int i = 0; i < nsat; i++) + state.gps.add_sat(record.svid(i), record.c_n(i)); } break; - case AltosLib.AO_LOG_GPS_DATE: - state.gps.year = (record.a & 0xff) + 2000; - state.gps.month = record.a >> 8; - state.gps.day = record.b & 0xff; - break; - case AltosLib.AO_LOG_CONFIG_VERSION: break; case AltosLib.AO_LOG_MAIN_DEPLOY: @@ -192,8 +159,8 @@ public class AltosEepromMegaIterable extends AltosRecordIterable { state.callsign = record.data; break; case AltosLib.AO_LOG_ACCEL_CAL: - state.accel_plus_g = record.a; - state.accel_minus_g = record.b; + state.accel_plus_g = record.config_a; + state.accel_minus_g = record.config_b; break; case AltosLib.AO_LOG_RADIO_CAL: break; @@ -202,33 +169,33 @@ public class AltosEepromMegaIterable extends AltosRecordIterable { case AltosLib.AO_LOG_PRODUCT: break; case AltosLib.AO_LOG_SERIAL_NUMBER: - state.serial = record.a; + state.serial = record.config_a; break; case AltosLib.AO_LOG_SOFTWARE_VERSION: break; case AltosLib.AO_LOG_BARO_RESERVED: - baro.reserved = record.a; + baro.reserved = record.config_a; break; case AltosLib.AO_LOG_BARO_SENS: - baro.sens =record.a; + baro.sens =record.config_a; break; case AltosLib.AO_LOG_BARO_OFF: - baro.off =record.a; + baro.off =record.config_a; break; case AltosLib.AO_LOG_BARO_TCS: - baro.tcs =record.a; + baro.tcs =record.config_a; break; case AltosLib.AO_LOG_BARO_TCO: - baro.tco =record.a; + baro.tco =record.config_a; break; case AltosLib.AO_LOG_BARO_TREF: - baro.tref =record.a; + baro.tref =record.config_a; break; case AltosLib.AO_LOG_BARO_TEMPSENS: - baro.tempsens =record.a; + baro.tempsens =record.config_a; break; case AltosLib.AO_LOG_BARO_CRC: - baro.crc =record.a; + baro.crc =record.config_a; break; } state.seen |= eeprom.seen; @@ -287,25 +254,25 @@ public class AltosEepromMegaIterable extends AltosRecordIterable { out.printf("# Config version: %s\n", record.data); break; case AltosLib.AO_LOG_MAIN_DEPLOY: - out.printf("# Main deploy: %s\n", record.a); + out.printf("# Main deploy: %s\n", record.config_a); break; case AltosLib.AO_LOG_APOGEE_DELAY: - out.printf("# Apogee delay: %s\n", record.a); + out.printf("# Apogee delay: %s\n", record.config_a); break; case AltosLib.AO_LOG_RADIO_CHANNEL: - out.printf("# Radio channel: %s\n", record.a); + out.printf("# Radio channel: %s\n", record.config_a); break; case AltosLib.AO_LOG_CALLSIGN: out.printf("# Callsign: %s\n", record.data); break; case AltosLib.AO_LOG_ACCEL_CAL: - out.printf ("# Accel cal: %d %d\n", record.a, record.b); + out.printf ("# Accel cal: %d %d\n", record.config_a, record.config_b); break; case AltosLib.AO_LOG_RADIO_CAL: - out.printf ("# Radio cal: %d\n", record.a); + out.printf ("# Radio cal: %d\n", record.config_a); break; case AltosLib.AO_LOG_MAX_FLIGHT_LOG: - out.printf ("# Max flight log: %d\n", record.a); + out.printf ("# Max flight log: %d\n", record.config_a); break; case AltosLib.AO_LOG_MANUFACTURER: out.printf ("# Manufacturer: %s\n", record.data); @@ -314,73 +281,39 @@ public class AltosEepromMegaIterable extends AltosRecordIterable { out.printf ("# Product: %s\n", record.data); break; case AltosLib.AO_LOG_SERIAL_NUMBER: - out.printf ("# Serial number: %d\n", record.a); + out.printf ("# Serial number: %d\n", record.config_a); break; case AltosLib.AO_LOG_SOFTWARE_VERSION: out.printf ("# Software version: %s\n", record.data); break; case AltosLib.AO_LOG_BARO_RESERVED: - out.printf ("# Baro reserved: %d\n", record.a); + out.printf ("# Baro reserved: %d\n", record.config_a); break; case AltosLib.AO_LOG_BARO_SENS: - out.printf ("# Baro sens: %d\n", record.a); + out.printf ("# Baro sens: %d\n", record.config_a); break; case AltosLib.AO_LOG_BARO_OFF: - out.printf ("# Baro off: %d\n", record.a); + out.printf ("# Baro off: %d\n", record.config_a); break; case AltosLib.AO_LOG_BARO_TCS: - out.printf ("# Baro tcs: %d\n", record.a); + out.printf ("# Baro tcs: %d\n", record.config_a); break; case AltosLib.AO_LOG_BARO_TCO: - out.printf ("# Baro tco: %d\n", record.a); + out.printf ("# Baro tco: %d\n", record.config_a); break; case AltosLib.AO_LOG_BARO_TREF: - out.printf ("# Baro tref: %d\n", record.a); + out.printf ("# Baro tref: %d\n", record.config_a); break; case AltosLib.AO_LOG_BARO_TEMPSENS: - out.printf ("# Baro tempsens: %d\n", record.a); + out.printf ("# Baro tempsens: %d\n", record.config_a); break; case AltosLib.AO_LOG_BARO_CRC: - out.printf ("# Baro crc: %d\n", record.a); + out.printf ("# Baro crc: %d\n", record.config_a); break; } } } - /* - * Given an AO_LOG_GPS_TIME record with correct time, and one - * missing time, rewrite the missing time values with the good - * ones, assuming that the difference between them is 'diff' seconds - */ - void update_time(AltosOrderedMegaRecord good, AltosOrderedMegaRecord bad) { - - int diff = (bad.tick - good.tick + 50) / 100; - - int hour = (good.a & 0xff); - int minute = (good.a >> 8); - int second = (good.b & 0xff); - int flags = (good.b >> 8); - int seconds = hour * 3600 + minute * 60 + second; - - /* Make sure this looks like a good GPS value */ - if ((flags & AltosLib.AO_GPS_NUM_SAT_MASK) >> AltosLib.AO_GPS_NUM_SAT_SHIFT < 4) - flags = (flags & ~AltosLib.AO_GPS_NUM_SAT_MASK) | (4 << AltosLib.AO_GPS_NUM_SAT_SHIFT); - flags |= AltosLib.AO_GPS_RUNNING; - flags |= AltosLib.AO_GPS_VALID; - - int new_seconds = seconds + diff; - if (new_seconds < 0) - new_seconds += 24 * 3600; - int new_second = (new_seconds % 60); - int new_minutes = (new_seconds / 60); - int new_minute = (new_minutes % 60); - int new_hours = (new_minutes / 60); - int new_hour = (new_hours % 24); - - bad.a = new_hour + (new_minute << 8); - bad.b = new_second + (flags << 8); - } - /* * Read the whole file, dumping records into a RB tree so * we can enumerate them in time order -- the eeprom data @@ -416,53 +349,11 @@ public class AltosEepromMegaIterable extends AltosRecordIterable { continue; } - /* Two firmware bugs caused the loss of some GPS data. - * The flight date would never be recorded, and often - * the flight time would get overwritten by another - * record. Detect the loss of the GPS date and fix up the - * missing time records - */ - if (record.cmd == AltosLib.AO_LOG_GPS_DATE) { - gps_date_record = record; - continue; - } - - /* go back and fix up any missing time values */ - if (record.cmd == AltosLib.AO_LOG_GPS_TIME) { - last_gps_time = record; - if (missing_time) { - Iterator iterator = records.iterator(); - while (iterator.hasNext()) { - AltosOrderedMegaRecord old = iterator.next(); - if (old.cmd == AltosLib.AO_LOG_GPS_TIME && - old.a == -1 && old.b == -1) - { - update_time(record, old); - } - } - missing_time = false; - } - } - - if (record.cmd == AltosLib.AO_LOG_GPS_LAT) { - if (last_gps_time == null || last_gps_time.tick != record.tick) { - AltosOrderedMegaRecord add_gps_time = new AltosOrderedMegaRecord(AltosLib.AO_LOG_GPS_TIME, - record.tick, - -1, -1, index-1); - if (last_gps_time != null) - update_time(last_gps_time, add_gps_time); - else - missing_time = true; - - records.add(add_gps_time); - record.index = index++; - } - } records.add(record); /* Bail after reading the 'landed' record; we're all done */ if (record.cmd == AltosLib.AO_LOG_STATE && - record.a == AltosLib.ao_flight_landed) + record.state() == AltosLib.ao_flight_landed) break; } } catch (IOException io) { diff --git a/altoslib/AltosIdleMonitor.java b/altoslib/AltosIdleMonitor.java index 2c4965ff..07d8930d 100644 --- a/altoslib/AltosIdleMonitor.java +++ b/altoslib/AltosIdleMonitor.java @@ -97,7 +97,7 @@ public class AltosIdleMonitor extends Thread { else if (has_sensor_mm(config_data)) record = sensor_mm(config_data); else - record = new AltosRecord(); + record = new AltosRecordNone(); if (has_gps(config_data)) gps = new AltosGPSQuery(link, config_data); diff --git a/altoslib/AltosLib.java b/altoslib/AltosLib.java index 192c445e..07516aeb 100644 --- a/altoslib/AltosLib.java +++ b/altoslib/AltosLib.java @@ -199,7 +199,7 @@ public class AltosLib { public static String state_name_capital(int state) { if (state < 0 || state_to_string.length <= state) - return "invalid"; + return "Invalid"; return state_to_string_capital[state]; } diff --git a/altoslib/AltosOrderedMegaRecord.java b/altoslib/AltosOrderedMegaRecord.java index 05423dd9..3aaf7b5b 100644 --- a/altoslib/AltosOrderedMegaRecord.java +++ b/altoslib/AltosOrderedMegaRecord.java @@ -43,18 +43,6 @@ class AltosOrderedMegaRecord extends AltosEepromMega implements Comparable + * + * 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; version 2 of the License. + * + * 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; + +import java.util.*; +import java.text.*; +import java.util.concurrent.*; + +public class AltosPyro { + public static final int pyro_none = 0x00000000; + + public static final int pyro_accel_less = 0x00000001; + public static final int pyro_accel_greater = 0x00000002; + public static final String pyro_accel_less_string = "a<"; + public static final String pyro_accel_greater_string = "a>"; + public static final String pyro_accel_less_name = "Acceleration less than (m/s²)"; + public static final String pyro_accel_greater_name = "Acceleration greater than (m/s²)"; + public static final double pyro_accel_scale = 16.0; + + public static final int pyro_speed_less = 0x00000004; + public static final int pyro_speed_greater = 0x00000008; + public static final String pyro_speed_less_string = "s<"; + public static final String pyro_speed_greater_string = "s>"; + public static final String pyro_speed_less_name = "Speed less than (m/s)"; + public static final String pyro_speed_greater_name = "Speed greater than (m/s)"; + public static final double pyro_speed_scale = 16.0; + + public static final int pyro_height_less = 0x00000010; + public static final int pyro_height_greater = 0x00000020; + public static final String pyro_height_less_string = "h<"; + public static final String pyro_height_greater_string = "h>"; + public static final String pyro_height_less_name = "Height less than (m)"; + public static final String pyro_height_greater_name = "Height greater than (m)"; + public static final double pyro_height_scale = 1.0; + + public static final int pyro_orient_less = 0x00000040; + public static final int pyro_orient_greater = 0x00000080; + public static final String pyro_orient_less_string = "o<"; + public static final String pyro_orient_greater_string = "o>"; + public static final String pyro_orient_less_name = "Angle from vertical less than (degrees)"; + public static final String pyro_orient_greater_name = "Angle from vertical greater than (degrees)"; + public static final double pyro_orient_scale = 1.0; + + public static final int pyro_time_less = 0x00000100; + public static final int pyro_time_greater = 0x00000200; + public static final String pyro_time_less_string = "t<"; + public static final String pyro_time_greater_string = "t>"; + public static final String pyro_time_less_name = "Time since boost less than (s)"; + public static final String pyro_time_greater_name = "Time since boost greater than (s)"; + public static final double pyro_time_scale = 100.0; + + public static final int pyro_ascending = 0x00000400; + public static final int pyro_descending = 0x00000800; + public static final String pyro_ascending_string = "A"; + public static final String pyro_descending_string = "D"; + public static final String pyro_ascending_name = "Ascending"; + public static final String pyro_descending_name = "Descending"; + + public static final int pyro_after_motor = 0x00001000; + public static final String pyro_after_motor_string = "m"; + public static final String pyro_after_motor_name = "After motor number"; + public static final double pyro_after_motor_scale = 1.0; + + public static final int pyro_delay = 0x00002000; + public static final String pyro_delay_string = "d"; + public static final String pyro_delay_name = "Delay after other conditions (s)"; + public static final double pyro_delay_scale = 100.0; + + public static final int pyro_state_less = 0x00004000; + public static final int pyro_state_greater_or_equal = 0x00008000; + public static final String pyro_state_less_string = "f<"; + public static final String pyro_state_greater_or_equal_string = "f>="; + public static final String pyro_state_less_name = "Flight state before"; + public static final String pyro_state_greater_or_equal_name = "Flight state after"; + public static final double pyro_state_scale = 1.0; + + public static final int pyro_all = 0x0000ffff; + + public static final int pyro_no_value = (pyro_ascending | + pyro_descending); + + public static final int pyro_state_value = pyro_state_less | pyro_state_greater_or_equal; + + private static HashMap string_to_pyro = new HashMap(); + + private static HashMap pyro_to_string = new HashMap(); + + private static HashMap pyro_to_name = new HashMap(); + + private static HashMap pyro_to_scale = new HashMap(); + + private static void insert_map(int flag, String string, String name, double scale) { + string_to_pyro.put(string, flag); + pyro_to_string.put(flag, string); + pyro_to_name.put(flag, name); + pyro_to_scale.put(flag, scale); + } + + public static int string_to_pyro(String name) { + if (string_to_pyro.containsKey(name)) + return string_to_pyro.get(name); + return pyro_none; + } + + public static String pyro_to_string(int flag) { + if (pyro_to_string.containsKey(flag)) + return pyro_to_string.get(flag); + return null; + } + + public static String pyro_to_name(int flag) { + if (pyro_to_name.containsKey(flag)) + return pyro_to_name.get(flag); + return null; + } + + public static double pyro_to_scale(int flag) { + if (pyro_to_scale.containsKey(flag)) + return pyro_to_scale.get(flag); + return 1.0; + } + + private static void initialize_maps() { + insert_map(pyro_accel_less, pyro_accel_less_string, pyro_accel_less_name, pyro_accel_scale); + insert_map(pyro_accel_greater, pyro_accel_greater_string, pyro_accel_greater_name, pyro_accel_scale); + + insert_map(pyro_speed_less, pyro_speed_less_string, pyro_speed_less_name, pyro_speed_scale); + insert_map(pyro_speed_greater, pyro_speed_greater_string, pyro_speed_greater_name, pyro_speed_scale); + + insert_map(pyro_height_less, pyro_height_less_string, pyro_height_less_name, pyro_height_scale); + insert_map(pyro_height_greater, pyro_height_greater_string, pyro_height_greater_name, pyro_height_scale); + + insert_map(pyro_orient_less, pyro_orient_less_string, pyro_orient_less_name, pyro_orient_scale); + insert_map(pyro_orient_greater, pyro_orient_greater_string, pyro_orient_greater_name, pyro_orient_scale); + + insert_map(pyro_time_less, pyro_time_less_string, pyro_time_less_name, pyro_time_scale); + insert_map(pyro_time_greater, pyro_time_greater_string, pyro_time_greater_name, pyro_time_scale); + + insert_map(pyro_ascending, pyro_ascending_string, pyro_ascending_name, 1.0); + insert_map(pyro_descending, pyro_descending_string, pyro_descending_name, 1.0); + + insert_map(pyro_after_motor, pyro_after_motor_string, pyro_after_motor_name, 1.0); + insert_map(pyro_delay, pyro_delay_string, pyro_delay_name, pyro_delay_scale); + + insert_map(pyro_state_less, pyro_state_less_string, pyro_state_less_name, 1.0); + insert_map(pyro_state_greater_or_equal, pyro_state_greater_or_equal_string, pyro_state_greater_or_equal_name, 1.0); + } + + { + initialize_maps(); + } + + public int channel; + public int flags; + public int accel_less, accel_greater; + public int speed_less, speed_greater; + public int height_less, height_greater; + public int orient_less, orient_greater; + public int time_less, time_greater; + public int delay; + public int state_less, state_greater_or_equal; + public int motor; + + public AltosPyro(int in_channel) { + channel = in_channel; + flags = 0; + } + + private boolean set_ivalue(int flag, int value) { + switch (flag) { + case pyro_accel_less: accel_less = value; break; + case pyro_accel_greater: accel_greater = value; break; + case pyro_speed_less: speed_less = value; break; + case pyro_speed_greater: speed_greater = value; break; + case pyro_height_less: height_less = value; break; + case pyro_height_greater: height_greater = value; break; + case pyro_orient_less: orient_less = value; break; + case pyro_orient_greater: orient_greater = value; break; + case pyro_time_less: time_less = value; break; + case pyro_time_greater: time_greater = value; break; + case pyro_after_motor: motor = value; break; + case pyro_delay: delay = value; break; + case pyro_state_less: state_less = value; break; + case pyro_state_greater_or_equal: state_greater_or_equal = value; break; + default: + return false; + } + return true; + } + + public boolean set_value(int flag, double dvalue) { + return set_ivalue(flag, (int) (dvalue * pyro_to_scale(flag))); + } + + private int get_ivalue (int flag) { + int value; + + switch (flag) { + case pyro_accel_less: value = accel_less; break; + case pyro_accel_greater: value = accel_greater; break; + case pyro_speed_less: value = speed_less; break; + case pyro_speed_greater: value = speed_greater; break; + case pyro_height_less: value = height_less; break; + case pyro_height_greater: value = height_greater; break; + case pyro_orient_less: value = orient_less; break; + case pyro_orient_greater: value = orient_greater; break; + case pyro_time_less: value = time_less; break; + case pyro_time_greater: value = time_greater; break; + case pyro_after_motor: value = motor; break; + case pyro_delay: value = delay; break; + case pyro_state_less: value = state_less; break; + case pyro_state_greater_or_equal: value = state_greater_or_equal; break; + default: value = 0; break; + } + return value; + } + + public double get_value(int flag) { + return get_ivalue(flag) / pyro_to_scale(flag); + } + + public AltosPyro(int in_channel, String line) throws ParseException { + String[] tokens = line.split("\\s+"); + + channel = in_channel; + flags = 0; + + int i = 0; + if (tokens[i].equals("Pyro")) + i += 2; + + for (; i < tokens.length; i++) { + + if (tokens[i].equals("")) + break; + + int flag = string_to_pyro(tokens[i]); + if (flag == pyro_none) + throw new ParseException(String.format("Invalid pyro token \"%s\"", + tokens[i]), i); + flags |= flag; + + if ((flag & pyro_no_value) == 0) { + int value = 0; + ++i; + try { + value = AltosLib.fromdec(tokens[i]); + } catch (NumberFormatException n) { + throw new ParseException(String.format("Invalid pyro value \"%s\"", + tokens[i]), i); + } + if (!set_ivalue(flag, value)) + throw new ParseException(String.format("Internal parser error \"%s\" \"%s\"", + tokens[i-1], tokens[i]), i-1); + } + } + } + + public String toString() { + String ret = String.format("%d", channel); + + for (int flag = 1; flag <= flags; flag <<= 1) { + if ((flags & flag) != 0) { + String add; + if ((flag & pyro_no_value) == 0) { + add = String.format(" %s %d", + pyro_to_string.get(flag), + get_ivalue(flag)); + } else { + add = String.format(" %s", + pyro_to_string.get(flag)); + } + ret = ret.concat(add); + } + } + return ret; + } +} diff --git a/altoslib/AltosRecord.java b/altoslib/AltosRecord.java index 8bab1d0c..09169515 100644 --- a/altoslib/AltosRecord.java +++ b/altoslib/AltosRecord.java @@ -17,7 +17,7 @@ package org.altusmetrum.AltosLib; -public class AltosRecord implements Comparable , Cloneable { +public abstract class AltosRecord implements Comparable , Cloneable { public static final int seen_flight = 1; public static final int seen_sensor = 2; @@ -43,11 +43,6 @@ public class AltosRecord implements Comparable , Cloneable { public int state; public int tick; - /* Current flight dynamic state */ - public double acceleration; /* m/s² */ - public double speed; /* m/s */ - public double height; /* m */ - public AltosGPS gps; public boolean new_gps; @@ -63,6 +58,11 @@ public class AltosRecord implements Comparable , Cloneable { public AltosRecordCompanion companion; + /* Telemetry sources have these values recorded from the flight computer */ + public double kalman_height; + public double kalman_speed; + public double kalman_acceleration; + /* * Abstract methods that convert record data * to standard units: @@ -75,76 +75,48 @@ public class AltosRecord implements Comparable , Cloneable { * temperature: °C */ - public double raw_pressure() { return MISSING; } - - public double filtered_pressure() { return MISSING; } - - public double ground_pressure() { return MISSING; } - - public double battery_voltage() { return MISSING; } + abstract public double pressure(); + abstract public double ground_pressure(); + abstract public double acceleration(); - public double main_voltage() { return MISSING; } + public double altitude() { + double p = pressure(); - public double drogue_voltage() { return MISSING; } - - public double temperature() { return MISSING; } - - public double acceleration() { return MISSING; } - - public double accel_speed() { return MISSING; } - - public AltosIMU imu() { return null; } - - public AltosMag mag() { return null; } - - /* - * Convert various pressure values to altitude - */ - - public double raw_altitude() { - double p = raw_pressure(); if (p == MISSING) return MISSING; return AltosConvert.pressure_to_altitude(p); } public double ground_altitude() { - double p = ground_pressure(); + double p = ground_pressure(); + if (p == MISSING) return MISSING; return AltosConvert.pressure_to_altitude(p); } - public double filtered_altitude() { - double ga = ground_altitude(); - if (height != MISSING && ga != MISSING) - return height + ga; + public double height() { + double g = ground_altitude(); + double a = altitude(); - double p = filtered_pressure(); - if (p == MISSING) - return raw_altitude(); - return AltosConvert.pressure_to_altitude(p); + if (g == MISSING) + return MISSING; + if (a == MISSING) + return MISSING; + return a - g; } - public double filtered_height() { - if (height != MISSING) - return height; + public double battery_voltage() { return MISSING; } - double f = filtered_altitude(); - double g = ground_altitude(); - if (f == MISSING || g == MISSING) - return MISSING; - return f - g; - } + public double main_voltage() { return MISSING; } - public double raw_height() { - double r = raw_altitude(); - double g = ground_altitude(); + public double drogue_voltage() { return MISSING; } - if (r == MISSING || g == MISSING) - return height; - return r - g; - } + public double temperature() { return MISSING; } + + public AltosIMU imu() { return null; } + + public AltosMag mag() { return null; } public String state() { return AltosLib.state_name(state); @@ -164,12 +136,12 @@ public class AltosRecord implements Comparable , Cloneable { status = old.status; state = old.state; tick = old.tick; - acceleration = old.acceleration; - speed = old.speed; - height = old.height; gps = new AltosGPS(old.gps); new_gps = old.new_gps; companion = old.companion; + kalman_acceleration = old.kalman_acceleration; + kalman_speed = old.kalman_speed; + kalman_height = old.kalman_height; } public AltosRecord clone() { @@ -192,11 +164,12 @@ public class AltosRecord implements Comparable , Cloneable { status = 0; state = AltosLib.ao_flight_startup; tick = 0; - acceleration = MISSING; - speed = MISSING; - height = MISSING; gps = new AltosGPS(); new_gps = false; companion = null; + + kalman_acceleration = MISSING; + kalman_speed = MISSING; + kalman_height = MISSING; } } diff --git a/altoslib/AltosRecordMM.java b/altoslib/AltosRecordMM.java index 5f952f7a..9f529234 100644 --- a/altoslib/AltosRecordMM.java +++ b/altoslib/AltosRecordMM.java @@ -19,6 +19,7 @@ package org.altusmetrum.AltosLib; public class AltosRecordMM extends AltosRecord { + /* Sensor values */ public int accel; public int pres; public int temp; @@ -45,16 +46,12 @@ public class AltosRecordMM extends AltosRecord { return raw / 4095.0; } - public double raw_pressure() { + public double pressure() { if (pres != MISSING) return pres; return MISSING; } - public double filtered_pressure() { - return raw_pressure(); - } - public double ground_pressure() { if (ground_pres != MISSING) return ground_pres; @@ -98,9 +95,6 @@ public class AltosRecordMM extends AltosRecord { } public double acceleration() { - if (acceleration != MISSING) - return acceleration; - if (ground_accel == MISSING || accel == MISSING) return MISSING; @@ -110,10 +104,6 @@ public class AltosRecordMM extends AltosRecord { return (ground_accel - accel) / accel_counts_per_mss(); } - public double accel_speed() { - return speed; - } - public void copy (AltosRecordMM old) { super.copy(old); diff --git a/altoslib/AltosRecordNone.java b/altoslib/AltosRecordNone.java new file mode 100644 index 00000000..ca0a5fe3 --- /dev/null +++ b/altoslib/AltosRecordNone.java @@ -0,0 +1,34 @@ +/* + * 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; version 2 of the License. + * + * 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; + +public class AltosRecordNone extends AltosRecord { + + public double pressure() { return MISSING; } + public double ground_pressure() { return MISSING; } + public double temperature() { return MISSING; } + public double acceleration() { return MISSING; } + + public AltosRecordNone(AltosRecord old) { + super.copy(old); + } + + public AltosRecordNone() { + super(); + } +} diff --git a/altoslib/AltosRecordTM.java b/altoslib/AltosRecordTM.java index 37accef6..9530be31 100644 --- a/altoslib/AltosRecordTM.java +++ b/altoslib/AltosRecordTM.java @@ -18,6 +18,8 @@ package org.altusmetrum.AltosLib; public class AltosRecordTM extends AltosRecord { + + /* Sensor values */ public int accel; public int pres; public int temp; @@ -57,18 +59,12 @@ public class AltosRecordTM extends AltosRecord { return ((count / 16.0) / 2047.0 + 0.095) / 0.009 * 1000.0; } - public double raw_pressure() { + public double pressure() { if (pres == MISSING) return MISSING; return barometer_to_pressure(pres); } - public double filtered_pressure() { - if (flight_pres == MISSING) - return MISSING; - return barometer_to_pressure(flight_pres); - } - public double ground_pressure() { if (ground_pres == MISSING) return MISSING; @@ -121,22 +117,11 @@ public class AltosRecordTM extends AltosRecord { } public double acceleration() { - if (acceleration != MISSING) - return acceleration; - if (ground_accel == MISSING || accel == MISSING) return MISSING; return (ground_accel - accel) / accel_counts_per_mss(); } - public double accel_speed() { - if (speed != MISSING) - return speed; - if (flight_vel == MISSING) - return MISSING; - return flight_vel / (accel_counts_per_mss() * 100.0); - } - public void copy(AltosRecordTM old) { super.copy(old); diff --git a/altoslib/AltosState.java b/altoslib/AltosState.java index 2e4d8870..f28dd1c6 100644 --- a/altoslib/AltosState.java +++ b/altoslib/AltosState.java @@ -40,17 +40,17 @@ public class AltosState { public double ground_altitude; public double altitude; public double height; - public double speed; public double acceleration; public double battery; public double temperature; public double main_sense; public double drogue_sense; + public double accel_speed; public double baro_speed; public double max_height; public double max_acceleration; - public double max_speed; + public double max_accel_speed; public double max_baro_speed; public AltosGPS gps; @@ -76,20 +76,39 @@ public class AltosState { public int speak_tick; public double speak_altitude; - public void init (AltosRecord cur, AltosState prev_state) { - //int i; - //AltosRecord prev; + public double speed() { + if (ascent) + return accel_speed; + else + return baro_speed; + } + + public double max_speed() { + if (max_accel_speed != 0) + return max_accel_speed; + return max_baro_speed; + } + public void init (AltosRecord cur, AltosState prev_state) { data = cur; ground_altitude = data.ground_altitude(); - altitude = data.raw_altitude(); - height = data.filtered_height(); + + altitude = data.altitude(); + + if (data.kalman_height != AltosRecord.MISSING) + height = data.kalman_height; + else { + if (prev_state != null) + height = (prev_state.height * 15 + altitude - ground_altitude) / 16.0; + } report_time = System.currentTimeMillis(); - acceleration = data.acceleration(); - speed = data.accel_speed(); + if (data.kalman_acceleration != AltosRecord.MISSING) + acceleration = data.kalman_acceleration; + else + acceleration = data.acceleration(); temperature = data.temperature(); drogue_sense = data.drogue_voltage(); main_sense = data.main_voltage(); @@ -108,7 +127,7 @@ public class AltosState { pad_alt = prev_state.pad_alt; max_height = prev_state.max_height; max_acceleration = prev_state.max_acceleration; - max_speed = prev_state.max_speed; + max_accel_speed = prev_state.max_accel_speed; max_baro_speed = prev_state.max_baro_speed; imu = prev_state.imu; mag = prev_state.mag; @@ -119,23 +138,39 @@ public class AltosState { time_change = (tick - prev_state.tick) / 100.0; - /* compute barometric speed */ + if (data.kalman_speed != AltosRecord.MISSING) { + baro_speed = accel_speed = data.kalman_speed; + } else { + /* compute barometric speed */ - double height_change = height - prev_state.height; - if (data.speed != AltosRecord.MISSING) - baro_speed = data.speed; - else { + double height_change = height - prev_state.height; if (time_change > 0) baro_speed = (prev_state.baro_speed * 3 + (height_change / time_change)) / 4.0; else baro_speed = prev_state.baro_speed; + + if (acceleration == AltosRecord.MISSING) { + /* Fill in mising acceleration value */ + accel_speed = baro_speed; + if (time_change > 0) + acceleration = (accel_speed - prev_state.accel_speed) / time_change; + else + acceleration = prev_state.acceleration; + } else { + /* compute accelerometer speed */ + accel_speed = prev_state.accel_speed + acceleration * time_change; + } } + } else { npad = 0; ngps = 0; gps = null; baro_speed = 0; + accel_speed = 0; time_change = 0; + if (acceleration == AltosRecord.MISSING) + acceleration = 0; } time = tick / 100.0; @@ -180,8 +215,8 @@ public class AltosState { /* Only look at accelerometer data under boost */ if (boost && acceleration > max_acceleration && acceleration != AltosRecord.MISSING) max_acceleration = acceleration; - if (boost && speed > max_speed && speed != AltosRecord.MISSING) - max_speed = speed; + if (boost && accel_speed > max_accel_speed && accel_speed != AltosRecord.MISSING) + max_accel_speed = accel_speed; if (boost && baro_speed > max_baro_speed && baro_speed != AltosRecord.MISSING) max_baro_speed = baro_speed; diff --git a/altoslib/AltosTelemetryRecordLegacy.java b/altoslib/AltosTelemetryRecordLegacy.java index 21176069..43189794 100644 --- a/altoslib/AltosTelemetryRecordLegacy.java +++ b/altoslib/AltosTelemetryRecordLegacy.java @@ -257,9 +257,9 @@ public class AltosTelemetryRecordLegacy extends AltosTelemetryRecord { record.accel_minus_g = map.get_int(AO_TELEM_CAL_ACCEL_MINUS, AltosRecord.MISSING); /* flight computer values */ - record.acceleration = map.get_double(AO_TELEM_KALMAN_ACCEL, AltosRecord.MISSING, 1/16.0); - record.speed = map.get_double(AO_TELEM_KALMAN_SPEED, AltosRecord.MISSING, 1/16.0); - record.height = map.get_int(AO_TELEM_KALMAN_HEIGHT, AltosRecord.MISSING); + record.kalman_acceleration = map.get_double(AO_TELEM_KALMAN_ACCEL, AltosRecord.MISSING, 1/16.0); + record.kalman_speed = map.get_double(AO_TELEM_KALMAN_SPEED, AltosRecord.MISSING, 1/16.0); + record.kalman_height = map.get_int(AO_TELEM_KALMAN_HEIGHT, AltosRecord.MISSING); record.flight_accel = map.get_int(AO_TELEM_ADHOC_ACCEL, AltosRecord.MISSING); record.flight_vel = map.get_int(AO_TELEM_ADHOC_SPEED, AltosRecord.MISSING); @@ -334,9 +334,9 @@ public class AltosTelemetryRecordLegacy extends AltosTelemetryRecord { /* Old TeleDongle code with kalman-reporting TeleMetrum code */ if ((record.flight_vel & 0xffff0000) == 0x80000000) { - record.speed = ((short) record.flight_vel) / 16.0; - record.acceleration = record.flight_accel / 16.0; - record.height = record.flight_pres; + record.kalman_speed = ((short) record.flight_vel) / 16.0; + record.kalman_acceleration = record.flight_accel / 16.0; + record.kalman_height = record.flight_pres; record.flight_vel = AltosRecord.MISSING; record.flight_pres = AltosRecord.MISSING; record.flight_accel = AltosRecord.MISSING; @@ -455,9 +455,9 @@ public class AltosTelemetryRecordLegacy extends AltosTelemetryRecord { record.accel_minus_g = int16(19); if (uint16(11) == 0x8000) { - record.acceleration = int16(5); - record.speed = int16(9); - record.height = int16(13); + record.kalman_acceleration = int16(5); + record.kalman_speed = int16(9); + record.kalman_height = int16(13); record.flight_accel = AltosRecord.MISSING; record.flight_vel = AltosRecord.MISSING; record.flight_pres = AltosRecord.MISSING; @@ -465,9 +465,9 @@ public class AltosTelemetryRecordLegacy extends AltosTelemetryRecord { record.flight_accel = int16(5); record.flight_vel = uint32(9); record.flight_pres = int16(13); - record.acceleration = AltosRecord.MISSING; - record.speed = AltosRecord.MISSING; - record.height = AltosRecord.MISSING; + record.kalman_acceleration = AltosRecord.MISSING; + record.kalman_speed = AltosRecord.MISSING; + record.kalman_height = AltosRecord.MISSING; } record.gps = null; diff --git a/altoslib/AltosTelemetryRecordMegaData.java b/altoslib/AltosTelemetryRecordMegaData.java index 8f55d238..16a7b80c 100644 --- a/altoslib/AltosTelemetryRecordMegaData.java +++ b/altoslib/AltosTelemetryRecordMegaData.java @@ -83,9 +83,9 @@ public class AltosTelemetryRecordMegaData extends AltosTelemetryRecordRaw { next.accel_plus_g = accel_plus_g; next.accel_minus_g = accel_minus_g; - next.acceleration = acceleration / 16.0; - next.speed = speed / 16.0; - next.height = height; + next.kalman_acceleration = acceleration / 16.0; + next.kalman_speed = speed / 16.0; + next.kalman_height = height; next.seen |= AltosRecord.seen_flight | AltosRecord.seen_temp_volt; diff --git a/altoslib/AltosTelemetryRecordRaw.java b/altoslib/AltosTelemetryRecordRaw.java index fbb373d5..c21da6fc 100644 --- a/altoslib/AltosTelemetryRecordRaw.java +++ b/altoslib/AltosTelemetryRecordRaw.java @@ -65,7 +65,7 @@ public class AltosTelemetryRecordRaw extends AltosTelemetryRecord { if (previous != null) next = previous.clone(); else - next = new AltosRecord(); + next = new AltosRecordNone(); next.serial = serial; next.tick = tick; return next; diff --git a/altoslib/AltosTelemetryRecordSensor.java b/altoslib/AltosTelemetryRecordSensor.java index 319a91b3..f1fc156c 100644 --- a/altoslib/AltosTelemetryRecordSensor.java +++ b/altoslib/AltosTelemetryRecordSensor.java @@ -86,9 +86,9 @@ public class AltosTelemetryRecordSensor extends AltosTelemetryRecordRaw { next.main = AltosRecord.MISSING; } - next.acceleration = acceleration / 16.0; - next.speed = speed / 16.0; - next.height = height; + next.kalman_acceleration = acceleration / 16.0; + next.kalman_speed = speed / 16.0; + next.kalman_height = height; next.ground_pres = ground_pres; if (type == packet_type_TM_sensor) { diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am index b56d8af1..2579a650 100644 --- a/altoslib/Makefile.am +++ b/altoslib/Makefile.am @@ -46,6 +46,7 @@ AltosLib_JAVA = \ $(SRC)/AltosRecordCompanion.java \ $(SRC)/AltosRecordIterable.java \ $(SRC)/AltosRecord.java \ + $(SRC)/AltosRecordNone.java \ $(SRC)/AltosRecordTM.java \ $(SRC)/AltosRecordMM.java \ $(SRC)/AltosReplayReader.java \ @@ -74,7 +75,8 @@ AltosLib_JAVA = \ $(SRC)/AltosDistance.java \ $(SRC)/AltosHeight.java \ $(SRC)/AltosSpeed.java \ - $(SRC)/AltosAccel.java + $(SRC)/AltosAccel.java \ + $(SRC)/AltosPyro.java JAR=AltosLib.jar diff --git a/altosui/AltosAscent.java b/altosui/AltosAscent.java index 007c74ec..a05c4404 100644 --- a/altosui/AltosAscent.java +++ b/altosui/AltosAscent.java @@ -251,7 +251,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { class Speed extends AscentValueHold { void show (AltosState state, int crc_errors) { - double speed = state.speed; + double speed = state.accel_speed; if (!state.ascent) speed = state.baro_speed; show(AltosConvert.speed, speed); diff --git a/altosui/AltosCSV.java b/altosui/AltosCSV.java index f8cc1ed6..1c929a7c 100644 --- a/altosui/AltosCSV.java +++ b/altosui/AltosCSV.java @@ -128,10 +128,10 @@ public class AltosCSV implements AltosWriter { void write_basic(AltosRecord record) { out.printf("%8.2f,%10.2f,%8.2f,%8.2f,%8.2f,%8.2f,%5.1f,%5.2f,%5.2f,%5.2f", record.acceleration(), - record.raw_pressure(), - record.raw_altitude(), - record.raw_height(), - record.accel_speed(), + record.pressure(), + record.altitude(), + record.height(), + state.accel_speed, state.baro_speed, record.temperature(), record.battery_voltage(), diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index 44e5a3fa..44c6239a 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -22,6 +22,7 @@ import javax.swing.*; import java.io.*; import java.util.concurrent.*; import org.altusmetrum.AltosLib.*; +import java.text.*; public class AltosConfig implements ActionListener { @@ -78,6 +79,8 @@ public class AltosConfig implements ActionListener { string_ref version; string_ref product; string_ref callsign; + int_ref npyro; + AltosPyro[] pyros; AltosConfigUI config_ui; boolean serial_started; boolean made_visible; @@ -162,6 +165,8 @@ public class AltosConfig implements ActionListener { config_ui.set_ignite_mode(ignite_mode.get()); config_ui.set_pad_orientation(pad_orientation.get()); config_ui.set_callsign(callsign.get()); + config_ui.set_pyros(pyros); + config_ui.set_has_pyro(npyro.get() > 0); config_ui.set_clean(); if (!made_visible) { made_visible = true; @@ -169,6 +174,8 @@ public class AltosConfig implements ActionListener { } } + int pyro; + void process_line(String line) { if (line == null) { abort(); @@ -179,6 +186,18 @@ public class AltosConfig implements ActionListener { update_ui(); return; } + if (pyro < npyro.get()) { + if (pyros == null) + pyros = new AltosPyro[npyro.get()]; + + try { + pyros[pyro] = new AltosPyro(pyro, line); + } catch (ParseException e) { + System.out.printf ("pyro parse failed %s\n", line); + } + ++pyro; + return; + } get_int(line, "serial-number", serial); get_int(line, "log-format", log_format); get_int(line, "Main deploy:", main_deploy); @@ -200,6 +219,7 @@ public class AltosConfig implements ActionListener { get_string(line, "Callsign:", callsign); get_string(line,"software-version", version); get_string(line,"product", product); + get_int(line, "Pyro-count:", npyro); } final static int serial_mode_read = 0; @@ -243,6 +263,8 @@ public class AltosConfig implements ActionListener { callsign.set("N0CALL"); version.set("unknown"); product.set("unknown"); + pyro = 0; + npyro.set(0); } void get_data() { @@ -304,6 +326,12 @@ public class AltosConfig implements ActionListener { serial_line.printf("c i %d\n", ignite_mode.get()); if (pad_orientation.get() >= 0) serial_line.printf("c o %d\n", pad_orientation.get()); + if (pyros.length > 0) { + for (int p = 0; p < pyros.length; p++) { + serial_line.printf("c P %s\n", + pyros[p].toString()); + } + } serial_line.printf("c w\n"); } catch (InterruptedException ie) { } catch (TimeoutException te) { @@ -431,6 +459,9 @@ public class AltosConfig implements ActionListener { if (pad_orientation.get() >= 0) pad_orientation.set(config_ui.pad_orientation()); callsign.set(config_ui.callsign()); + if (npyro.get() > 0) { + pyros = config_ui.pyros(); + } run_serial_thread(serial_mode_save); } @@ -477,13 +508,14 @@ public class AltosConfig implements ActionListener { callsign = new string_ref("N0CALL"); version = new string_ref("unknown"); product = new string_ref("unknown"); + npyro = new int_ref(0); device = AltosDeviceDialog.show(owner, Altos.product_any); if (device != null) { try { serial_line = new AltosSerial(device); try { - if (!device.matchProduct(Altos.product_altimeter)) + if (device.matchProduct(Altos.product_basestation)) remote = true; init_ui(); } catch (InterruptedException ie) { diff --git a/altosui/AltosConfigPyroUI.java b/altosui/AltosConfigPyroUI.java new file mode 100644 index 00000000..17adb15f --- /dev/null +++ b/altosui/AltosConfigPyroUI.java @@ -0,0 +1,288 @@ +/* + * 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; version 2 of the License. + * + * 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 altosui; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.event.*; +import org.altusmetrum.AltosLib.*; + +public class AltosConfigPyroUI + extends AltosDialog + implements ItemListener, DocumentListener +{ + AltosConfigUI owner; + Container pane; + + static Insets il = new Insets(4,4,4,4); + static Insets ir = new Insets(4,4,4,4); + + static String[] state_names; + + static void make_state_names() { + if (state_names == null) { + + state_names = new String[AltosLib.ao_flight_landed - AltosLib.ao_flight_boost + 1]; + for (int state = AltosLib.ao_flight_boost; state <= AltosLib.ao_flight_landed; state++) + state_names[state - AltosLib.ao_flight_boost] = AltosLib.state_name_capital(state); + } + } + + class PyroItem implements ItemListener, DocumentListener + { + public int flag; + public JRadioButton enable; + public JTextField value; + public JComboBox combo; + AltosConfigPyroUI ui; + + public void set_enable(boolean enable) { + if (value != null) + value.setEnabled(enable); + if (combo != null) + combo.setEnabled(enable); + } + + public void itemStateChanged(ItemEvent e) { + set_enable(enable.isSelected()); + ui.set_dirty(); + } + + public void changedUpdate(DocumentEvent e) { + ui.set_dirty(); + } + + public void insertUpdate(DocumentEvent e) { + ui.set_dirty(); + } + + public void removeUpdate(DocumentEvent e) { + ui.set_dirty(); + } + + public void set(boolean new_enable, double new_value) { + enable.setSelected(new_enable); + set_enable(new_enable); + if (value != null) { + double scale = AltosPyro.pyro_to_scale(flag); + String format = "%6.0f"; + if (scale >= 10) + format = "%6.1f"; + else if (scale >= 100) + format = "%6.2f"; + value.setText(String.format(format, new_value)); + } + if (combo != null) + if (new_value >= AltosLib.ao_flight_boost && new_value <= AltosLib.ao_flight_landed) + combo.setSelectedIndex((int) new_value - AltosLib.ao_flight_boost); + } + + public boolean enabled() { + return enable.isSelected(); + } + + public double value() { + if (value != null) + return Double.parseDouble(value.getText()); + if (combo != null) + return combo.getSelectedIndex() + AltosLib.ao_flight_boost; + return 0; + } + + public PyroItem(AltosConfigPyroUI in_ui, int in_flag, int x, int y) { + + ui = in_ui; + flag = in_flag; + + GridBagConstraints c; + c = new GridBagConstraints(); + c.gridx = x; c.gridy = y; + c.gridwidth = 1; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + enable = new JRadioButton(); + enable.addItemListener(this); + pane.add(enable, c); + + if ((flag & AltosPyro.pyro_no_value) == 0) { + c = new GridBagConstraints(); + c.gridx = x+1; c.gridy = y; + c.gridwidth = 1; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + if ((flag & AltosPyro.pyro_state_value) != 0) { + make_state_names(); + combo = new JComboBox(state_names); + combo.addItemListener(this); + pane.add(combo, c); + } else { + value = new JTextField(10); + value.getDocument().addDocumentListener(this); + pane.add(value, c); + } + } + } + } + + class PyroColumn { + public PyroItem[] items; + public JLabel label; + int channel; + + public void set(AltosPyro pyro) { + int row = 0; + for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1) { + if ((AltosPyro.pyro_all & flag) != 0) { + items[row].set((pyro.flags & flag) != 0, + pyro.get_value(flag)); + row++; + } + } + } + + public AltosPyro get() { + AltosPyro p = new AltosPyro(channel); + + int row = 0; + for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1) { + if ((AltosPyro.pyro_all & flag) != 0) { + if (items[row].enabled()) { + System.out.printf ("Flag %x enabled\n", flag); + p.flags |= flag; + p.set_value(flag, items[row].value()); + } + row++; + } + } + System.out.printf ("Pyro %x %s\n", p.flags, p.toString()); + return p; + } + + public PyroColumn(AltosConfigPyroUI ui, int x, int y, int in_channel) { + + channel = in_channel; + + int nrow = 0; + for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1) + if ((flag & AltosPyro.pyro_all) != 0) + nrow++; + + items = new PyroItem[nrow]; + int row = 0; + + GridBagConstraints c; + c = new GridBagConstraints(); + c.gridx = x; c.gridy = y; + c.gridwidth = 2; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = il; + label = new JLabel(String.format("Pyro Channel %d", channel)); + pane.add(label, c); + y++; + + for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1) + if ((flag & AltosPyro.pyro_all) != 0) { + items[row] = new PyroItem(ui, flag, x, y + row); + row++; + } + } + } + + PyroColumn[] columns; + + public void set_pyros(AltosPyro[] pyros) { + for (int i = 0; i < pyros.length; i++) { + if (pyros[i].channel < columns.length) + columns[pyros[i].channel].set(pyros[i]); + } + } + + public AltosPyro[] get_pyros() { + AltosPyro[] pyros = new AltosPyro[columns.length]; + for (int c = 0; c < columns.length; c++) + pyros[c] = columns[c].get(); + return pyros; + } + + public void set_dirty() { + owner.set_dirty(); + } + + public void itemStateChanged(ItemEvent e) { + owner.set_dirty(); + } + + public void changedUpdate(DocumentEvent e) { + owner.set_dirty(); + } + + public void insertUpdate(DocumentEvent e) { + owner.set_dirty(); + } + + public void removeUpdate(DocumentEvent e) { + owner.set_dirty(); + } + + public AltosConfigPyroUI(AltosConfigUI in_owner, AltosPyro[] pyros) { + + super(in_owner, "Configure Pyro Channels", false); + + owner = in_owner; + + GridBagConstraints c; + + pane = getContentPane(); + pane.setLayout(new GridBagLayout()); + + int row = 1; + + for (int flag = 1; flag <= AltosPyro.pyro_all; flag <<= 1) { + String n; + + n = AltosPyro.pyro_to_name(flag); + if (n != null) { + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = row; + c.gridwidth = 1; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + JLabel label = new JLabel(n); + pane.add(label, c); + row++; + } + } + + columns = new PyroColumn[pyros.length]; + + for (int i = 0; i < pyros.length; i++) { + columns[i] = new PyroColumn(this, i*2 + 1, 0, i); + columns[i].set(pyros[i]); + } + } + + public void make_visible() { + pack(); + setVisible(true); + } +} diff --git a/altosui/AltosConfigUI.java b/altosui/AltosConfigUI.java index dd34a9cf..feac053b 100644 --- a/altosui/AltosConfigUI.java +++ b/altosui/AltosConfigUI.java @@ -29,7 +29,6 @@ public class AltosConfigUI { Container pane; - Box box; JLabel product_label; JLabel version_label; JLabel serial_label; @@ -62,11 +61,15 @@ public class AltosConfigUI JComboBox pad_orientation_value; JTextField callsign_value; + JButton pyro; + JButton save; JButton reset; JButton reboot; JButton close; + AltosPyro[] pyros; + ActionListener listener; static String[] main_deploy_values = { @@ -510,6 +513,20 @@ public class AltosConfigUI set_pad_orientation_tool_tip(); row++; + /* Pyro channels */ + c = new GridBagConstraints(); + c.gridx = 4; c.gridy = row; + c.gridwidth = 4; + c.fill = GridBagConstraints.HORIZONTAL; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + c.ipady = 5; + pyro = new JButton("Configure Pyro Channels"); + pane.add(pyro, c); + pyro.addActionListener(this); + pyro.setActionCommand("Pyro"); + row++; + /* Buttons */ c = new GridBagConstraints(); c.gridx = 0; c.gridy = row; @@ -582,10 +599,30 @@ public class AltosConfigUI return true; } + void set_dirty() { + dirty = true; + save.setEnabled(true); + } + + public void set_clean() { + dirty = false; + save.setEnabled(false); + } + + AltosConfigPyroUI pyro_ui; + /* Listen for events from our buttons */ public void actionPerformed(ActionEvent e) { String cmd = e.getActionCommand(); + if (cmd.equals("Pyro")) { + if (pyro_ui == null && pyros != null) { + pyro_ui = new AltosConfigPyroUI(this, pyros); + pyro_ui.make_visible(); + } + return; + } + if (cmd.equals("Close") || cmd.equals("Reboot")) if (!check_dirty(cmd)) return; @@ -594,25 +631,25 @@ public class AltosConfigUI setVisible(false); dispose(); } - dirty = false; + set_clean(); } /* ItemListener interface method */ public void itemStateChanged(ItemEvent e) { - dirty = true; + set_dirty(); } /* DocumentListener interface methods */ public void changedUpdate(DocumentEvent e) { - dirty = true; + set_dirty(); } public void insertUpdate(DocumentEvent e) { - dirty = true; + set_dirty(); } public void removeUpdate(DocumentEvent e) { - dirty = true; + set_dirty(); } /* Let the config code hook on a listener */ @@ -725,8 +762,7 @@ public class AltosConfigUI } public void set_flight_log_max(int new_flight_log_max) { - if (new_flight_log_max == 0) - flight_log_max_value.setEnabled(false); + flight_log_max_value.setEnabled(new_flight_log_max > 0); flight_log_max_value.setSelectedItem(Integer.toString(new_flight_log_max)); set_flight_log_max_tool_tip(); } @@ -793,7 +829,19 @@ public class AltosConfigUI return -1; } - public void set_clean() { - dirty = false; + public void set_has_pyro(boolean has_pyro) { + pyro.setEnabled(has_pyro); + } + + public void set_pyros(AltosPyro[] new_pyros) { + pyros = new_pyros; + if (pyro_ui != null) + pyro_ui.set_pyros(pyros); + } + + public AltosPyro[] pyros() { + if (pyro_ui != null) + pyros = pyro_ui.get_pyros(); + return pyros; } } diff --git a/altosui/AltosDataChooser.java b/altosui/AltosDataChooser.java index 4d2f321e..a8a2ca49 100644 --- a/altosui/AltosDataChooser.java +++ b/altosui/AltosDataChooser.java @@ -70,6 +70,12 @@ public class AltosDataChooser extends JFileChooser { public AltosDataChooser(JFrame in_frame) { frame = in_frame; setDialogTitle("Select Flight Record File"); + setFileFilter(new FileNameExtensionFilter("TeleMetrum eeprom file", + "eeprom")); + setFileFilter(new FileNameExtensionFilter("Telemetry file", + "telem")); + setFileFilter(new FileNameExtensionFilter("MegaMetrum eeprom file", + "mega")); setFileFilter(new FileNameExtensionFilter("Flight data file", "telem", "eeprom", "mega")); setCurrentDirectory(AltosUIPreferences.logdir()); diff --git a/altosui/AltosDataPoint.java b/altosui/AltosDataPoint.java index 5e077320..4956e9f3 100644 --- a/altosui/AltosDataPoint.java +++ b/altosui/AltosDataPoint.java @@ -16,11 +16,8 @@ interface AltosDataPoint { String state_name(); double acceleration(); - double pressure(); - double altitude(); double height(); - double accel_speed(); - double baro_speed(); + double speed(); double temperature(); double battery_voltage(); double drogue_voltage(); diff --git a/altosui/AltosDataPointReader.java b/altosui/AltosDataPointReader.java index 2316cf97..88df081f 100644 --- a/altosui/AltosDataPointReader.java +++ b/altosui/AltosDataPointReader.java @@ -12,7 +12,6 @@ import org.altusmetrum.AltosLib.*; class AltosDataPointReader implements Iterable { Iterator iter; AltosState state; - AltosRecord record; boolean has_gps; boolean has_accel; boolean has_ignite; @@ -22,7 +21,7 @@ class AltosDataPointReader implements Iterable { public AltosDataPointReader(AltosRecordIterable reader) { this.iter = reader.iterator(); this.state = null; - has_accel = reader.has_accel(); + has_accel = true; has_gps = reader.has_gps(); has_ignite = reader.has_ignite(); } @@ -30,35 +29,31 @@ class AltosDataPointReader implements Iterable { private void read_next_record() throws NoSuchElementException { - record = iter.next(); - state = new AltosState(record, state); + state = new AltosState(iter.next(), state); } private AltosDataPoint current_dp() { - assert this.record != null; + assert this.state != null; return new AltosDataPoint() { - public int version() { return record.version; } - public int serial() { return record.serial; } - public int flight() { return record.flight; } - public String callsign() { return record.callsign; } - public double time() { return record.time; } - public double rssi() { return record.rssi; } + public int version() { return state.data.version; } + public int serial() { return state.data.serial; } + public int flight() { return state.data.flight; } + public String callsign() { return state.data.callsign; } + public double time() { return state.data.time; } + public double rssi() { return state.data.rssi; } - public int state() { return record.state; } - public String state_name() { return record.state(); } + public int state() { return state.state; } + public String state_name() { return state.data.state(); } - public double acceleration() { return record.acceleration(); } - public double pressure() { return record.raw_pressure(); } - public double altitude() { return record.raw_altitude(); } - public double height() { return record.raw_height(); } - public double accel_speed() { return record.accel_speed(); } - public double baro_speed() { return state.baro_speed; } - public double temperature() { return record.temperature(); } - public double battery_voltage() { return record.battery_voltage(); } - public double drogue_voltage() { return record.drogue_voltage(); } - public double main_voltage() { return record.main_voltage(); } - public boolean has_accel() { return has_accel; } + public double acceleration() { return state.acceleration; } + public double height() { return state.height; } + public double speed() { return state.speed(); } + public double temperature() { return state.temperature; } + public double battery_voltage() { return state.battery; } + public double drogue_voltage() { return state.drogue_sense; } + public double main_voltage() { return state.main_sense; } + public boolean has_accel() { return true; } // return state.acceleration != AltosRecord.MISSING; } }; } @@ -68,14 +63,14 @@ class AltosDataPointReader implements Iterable { throw new UnsupportedOperationException(); } public boolean hasNext() { - if (record != null && record.state == Altos.ao_flight_landed) + if (state != null && state.state == Altos.ao_flight_landed) return false; return iter.hasNext(); } public AltosDataPoint next() { do { read_next_record(); - } while (record.time < -1.0 && hasNext()); + } while (state.data.time < -1.0 && hasNext()); return current_dp(); } }; diff --git a/altosui/AltosDescent.java b/altosui/AltosDescent.java index a71cdc10..2ea7cbfa 100644 --- a/altosui/AltosDescent.java +++ b/altosui/AltosDescent.java @@ -256,7 +256,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { class Speed extends DescentValue { void show (AltosState state, int crc_errors) { - double speed = state.speed; + double speed = state.accel_speed; if (!state.ascent) speed = state.baro_speed; show(AltosConvert.speed, speed); diff --git a/altosui/AltosDialog.java b/altosui/AltosDialog.java index eac371aa..c2a9d6e6 100644 --- a/altosui/AltosDialog.java +++ b/altosui/AltosDialog.java @@ -45,6 +45,12 @@ public class AltosDialog extends JDialog implements AltosUIListener { addWindowListener(new AltosDialogListener()); } + public AltosDialog(Dialog dialog, String label, boolean modal) { + super(dialog, label, modal); + AltosUIPreferences.register_ui_listener(this); + addWindowListener(new AltosDialogListener()); + } + public AltosDialog(Frame frame, boolean modal) { super(frame, modal); AltosUIPreferences.register_ui_listener(this); diff --git a/altosui/AltosDisplayThread.java b/altosui/AltosDisplayThread.java index f7a1d03e..1ba70c7e 100644 --- a/altosui/AltosDisplayThread.java +++ b/altosui/AltosDisplayThread.java @@ -197,7 +197,7 @@ public class AltosDisplayThread extends Thread { if ((old_state == null || old_state.state <= Altos.ao_flight_boost) && state.state > Altos.ao_flight_boost) { voice.speak("max speed: %s.", - AltosConvert.speed.say_units(state.max_speed + 0.5)); + AltosConvert.speed.say_units(state.max_accel_speed + 0.5)); ret = true; } else if ((old_state == null || old_state.state < Altos.ao_flight_drogue) && state.state >= Altos.ao_flight_drogue) { diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index a5e99749..21b46740 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -283,7 +283,7 @@ public class AltosEepromDownload implements Runnable { if (r.cmd == Altos.AO_LOG_GPS_TIME) { year = 2000 + r.data8(14); month = r.data8(15); - day = r.data8(14); + day = r.data8(16); want_file = true; } diff --git a/altosui/AltosFlightStats.java b/altosui/AltosFlightStats.java index e48cb608..1653ca57 100644 --- a/altosui/AltosFlightStats.java +++ b/altosui/AltosFlightStats.java @@ -24,7 +24,7 @@ public class AltosFlightStats { double max_height; double max_speed; double max_acceleration; - double[] state_speed = new double[Altos.ao_flight_invalid + 1]; + double[] state_accel_speed = new double[Altos.ao_flight_invalid + 1]; double[] state_baro_speed = new double[Altos.ao_flight_invalid + 1]; double[] state_accel = new double[Altos.ao_flight_invalid + 1]; int[] state_count = new int[Altos.ao_flight_invalid + 1]; @@ -123,7 +123,7 @@ public class AltosFlightStats { } } state_accel[state.state] += state.acceleration; - state_speed[state.state] += state.speed; + state_accel_speed[state.state] += state.accel_speed; state_baro_speed[state.state] += state.baro_speed; state_count[state.state]++; if (state_start[state.state] == 0.0) @@ -131,8 +131,8 @@ public class AltosFlightStats { if (state_end[state.state] < state.time) state_end[state.state] = state.time; max_height = state.max_height; - if (state.max_speed != 0) - max_speed = state.max_speed; + if (state.max_accel_speed != 0) + max_speed = state.max_accel_speed; else max_speed = state.max_baro_speed; max_acceleration = state.max_acceleration; @@ -140,7 +140,7 @@ public class AltosFlightStats { } for (int s = Altos.ao_flight_startup; s <= Altos.ao_flight_landed; s++) { if (state_count[s] > 0) { - state_speed[s] /= state_count[s]; + state_accel_speed[s] /= state_count[s]; state_baro_speed[s] /= state_count[s]; state_accel[s] /= state_count[s]; } diff --git a/altosui/AltosGraphUI.java b/altosui/AltosGraphUI.java index cb8e3d20..f59f70ba 100644 --- a/altosui/AltosGraphUI.java +++ b/altosui/AltosGraphUI.java @@ -40,12 +40,7 @@ public class AltosGraphUI extends AltosFrame AltosGraphTime.Element speed = new AltosGraphTime.TimeSeries(String.format("Speed (%s)", AltosConvert.speed.show_units()), "Vertical Speed", green) { public void gotTimeData(double time, AltosDataPoint d) { - double speed; - if (d.state() < Altos.ao_flight_drogue && d.has_accel()) { - speed = d.accel_speed(); - } else { - speed = d.baro_speed(); - } + double speed = d.speed(); if (speed != AltosRecord.MISSING) series.add(time, AltosConvert.speed.value(speed)); } diff --git a/altosui/AltosInfoTable.java b/altosui/AltosInfoTable.java index 86e02ab1..11d1b0c1 100644 --- a/altosui/AltosInfoTable.java +++ b/altosui/AltosInfoTable.java @@ -114,8 +114,8 @@ public class AltosInfoTable extends JTable { info_add_row(0, "Max height", "%6.0f m", state.max_height); info_add_row(0, "Acceleration", "%8.1f m/s²", state.acceleration); info_add_row(0, "Max acceleration", "%8.1f m/s²", state.max_acceleration); - info_add_row(0, "Speed", "%8.1f m/s", state.ascent ? state.speed : state.baro_speed); - info_add_row(0, "Max Speed", "%8.1f m/s", state.max_speed); + info_add_row(0, "Speed", "%8.1f m/s", state.speed()); + info_add_row(0, "Max Speed", "%8.1f m/s", state.max_accel_speed); info_add_row(0, "Temperature", "%9.2f °C", state.temperature); info_add_row(0, "Battery", "%9.2f V", state.battery); if (state.drogue_sense != AltosRecord.MISSING) diff --git a/altosui/AltosKML.java b/altosui/AltosKML.java index 57339b19..281638bf 100644 --- a/altosui/AltosKML.java +++ b/altosui/AltosKML.java @@ -109,7 +109,7 @@ public class AltosKML implements AltosWriter { AltosGPS gps = record.gps; out.printf(kml_coord_fmt, gps.lon, gps.lat, - record.filtered_altitude(), (double) gps.alt, + record.altitude(), (double) gps.alt, record.time, gps.nsat); } diff --git a/altosui/AltosLanded.java b/altosui/AltosLanded.java index 57c2d476..5e073f7d 100644 --- a/altosui/AltosLanded.java +++ b/altosui/AltosLanded.java @@ -173,7 +173,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio class Speed extends LandedValue { void show (AltosState state, int crc_errors) { - show(AltosConvert.speed, state.max_speed); + show(AltosConvert.speed, state.max_speed()); } public Speed (GridBagLayout layout, int y) { super (layout, y, "Maximum Speed"); @@ -250,6 +250,9 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio } else if (filename.endsWith("telem")) { FileInputStream in = new FileInputStream(file); records = new AltosTelemetryIterable(in); + } else if (filename.endsWith("mega")) { + FileInputStream in = new FileInputStream(file); + records = new AltosEepromMegaIterable(in); } else { throw new FileNotFoundException(filename); } diff --git a/altosui/Makefile.am b/altosui/Makefile.am index de7a86c0..306a396e 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -24,6 +24,7 @@ altosui_JAVA = \ AltosConfig.java \ AltosConfigFreqUI.java \ AltosConfigUI.java \ + AltosConfigPyroUI.java \ AltosConfigureUI.java \ AltosConfigTD.java \ AltosConfigTDUI.java \ diff --git a/src/Makefile b/src/Makefile index b8828d46..1949e554 100644 --- a/src/Makefile +++ b/src/Makefile @@ -27,7 +27,7 @@ ifneq ($(shell which sdcc),) endif ifneq ($(shell which avr-gcc),) - SUBDIRS += telescience-v0.1 telepyro-v0.1 + SUBDIRS += telescience-v0.1 telescience-pwm telepyro-v0.1 endif ifneq ($(shell which arm-none-eabi-gcc),) diff --git a/src/avr/ao_adc_avr.c b/src/avr/ao_adc_avr.c index 3a262977..231512b2 100644 --- a/src/avr/ao_adc_avr.c +++ b/src/avr/ao_adc_avr.c @@ -16,6 +16,7 @@ */ #include "ao.h" +#include "ao_pwmin.h" volatile __xdata struct ao_data ao_data_ring[AO_DATA_RING]; volatile __data uint8_t ao_data_head; @@ -93,9 +94,13 @@ ISR(ADC_vect) value = ADCL; value |= (ADCH << 8); ao_data_ring[ao_data_head].adc.adc[ao_adc_channel] = value; - if (++ao_adc_channel < NUM_ADC) + if (++ao_adc_channel < NUM_ADC - HAS_ICP3_COUNT) ao_adc_start(); else { +#if HAS_ICP3_COUNT + /* steal last adc channel for pwm input */ + ao_data_ring[ao_data_head].adc.adc[ao_adc_channel] = ao_icp3_count; +#endif ADCSRA = ADCSRA_INIT; ao_data_ring[ao_data_head].tick = ao_time(); ao_data_head = ao_data_ring_next(ao_data_head); diff --git a/src/avr/ao_arch.h b/src/avr/ao_arch.h index a14d0ade..96659aaf 100644 --- a/src/avr/ao_arch.h +++ b/src/avr/ao_arch.h @@ -37,7 +37,9 @@ * AVR definitions and code fragments for AltOS */ +#ifndef AO_STACK_SIZE #define AO_STACK_SIZE 116 +#endif /* Various definitions to make GCC look more like SDCC */ diff --git a/src/avr/ao_pins.h b/src/avr/ao_pins.h index bc423ff7..a08e87fa 100644 --- a/src/avr/ao_pins.h +++ b/src/avr/ao_pins.h @@ -32,7 +32,7 @@ #define HAS_BEEP 0 #endif -#ifdef TELESCIENCE +#if defined(TELESCIENCE) || defined(TELESCIENCE_PWM) #define LEDS_AVAILABLE 0 #define HAS_USB 1 #define HAS_LOG 1 @@ -47,6 +47,11 @@ #define AVR_VCC_5V 0 #define AVR_VCC_3V3 1 #define AVR_CLOCK 8000000UL +#ifdef TELESCIENCE_PWM + #define HAS_ICP3_COUNT 1 +#else + #define HAS_ICP3_COUNT 0 +#endif #define SPI_CS_PORT PORTE #define SPI_CS_DIR DDRE @@ -64,6 +69,7 @@ #endif #ifdef TELEPYRO + #define AO_STACK_SIZE 104 #define LEDS_AVAILABLE 0 #define HAS_USB 1 #define HAS_LOG 0 @@ -81,6 +87,7 @@ #define IS_COMPANION 1 #define HAS_ORIENT 0 #define ao_storage_pos_t uint16_t + #define HAS_ICP3_COUNT 0 #define AVR_VCC_5V 0 #define AVR_VCC_3V3 1 diff --git a/src/avr/ao_pwmin.c b/src/avr/ao_pwmin.c new file mode 100644 index 00000000..84397357 --- /dev/null +++ b/src/avr/ao_pwmin.c @@ -0,0 +1,90 @@ +/* + * Copyright © 2012 Robert D. Garbee + * + * 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; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_pwmin.h" + +/* + * This code implements a PWM input using ICP3. + * + * The initial use is to measure wind speed in the ULA/Ball summer intern + * project payload developed at Challenger Middle School. + */ + +volatile __data uint16_t ao_icp3_count = 0; +volatile __data uint16_t ao_icp3_last = 0; + +uint16_t ao_icp3(void) +{ + uint16_t v; + ao_arch_critical( + v = ao_icp3_count; + ); + return v; +} + +static void +ao_pwmin_display(void) __reentrant +{ + /* display the most recent value */ + printf("icp 3: %5u\n", ao_icp3()); + +} + + +ISR(TIMER3_CAPT_vect) +{ + + uint8_t lo = ICR3L; + uint8_t hi = ICR3H; + uint16_t ao_icp3_this = (hi <<8) | lo; + + /* handling counter rollovers */ + if (ao_icp3_this >= ao_icp3_last) + ao_icp3_count = ao_icp3_this - ao_icp3_last; + else + ao_icp3_count = ao_icp3_this + (65536 - ao_icp3_last); + ao_icp3_last = ao_icp3_this; +} + +__code struct ao_cmds ao_pwmin_cmds[] = { + { ao_pwmin_display, "p\0PWM input" }, + { 0, NULL }, +}; + +void +ao_pwmin_init(void) +{ + /* do hardware setup here */ + TCCR3A = ((0 << WGM31) | /* normal mode, OCR3A */ + (0 << WGM30)); /* normal mode, OCR3A */ + TCCR3B = ((1 << ICNC3) | /* input capture noise canceler on */ + (0 << ICES3) | /* input capture on falling edge (don't care) */ + (0 << WGM33) | /* normal mode, OCR3A */ + (0 << WGM32) | /* normal mode, OCR3A */ + (3 << CS30)); /* clk/64 from prescaler */ + + + + TIMSK3 = (1 << ICIE3); /* Interrupt on input compare */ + + /* set the spike filter bit in the TCCR3B register */ + + ao_cmd_register(&ao_pwmin_cmds[0]); +} + + diff --git a/src/avr/ao_pwmin.h b/src/avr/ao_pwmin.h new file mode 100644 index 00000000..8097d399 --- /dev/null +++ b/src/avr/ao_pwmin.h @@ -0,0 +1,20 @@ +/* + * Copyright © 2012 Robert D. Garbee + * + * 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; version 2 of the License. + * + * 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. + */ + +void ao_pwmin_init(void); + +extern volatile __data uint16_t ao_icp3_count; diff --git a/src/core/ao_log.h b/src/core/ao_log.h index eaaca444..4eaed420 100644 --- a/src/core/ao_log.h +++ b/src/core/ao_log.h @@ -197,15 +197,18 @@ struct ao_log_mega { uint8_t csum; /* 1 */ uint16_t tick; /* 2 */ union { /* 4 */ + /* AO_LOG_FLIGHT */ struct { uint16_t flight; /* 4 */ int16_t ground_accel; /* 6 */ uint32_t ground_pres; /* 8 */ } flight; /* 12 */ + /* AO_LOG_STATE */ struct { uint16_t state; uint16_t reason; } state; + /* AO_LOG_SENSOR */ struct { uint32_t pres; /* 4 */ uint32_t temp; /* 8 */ @@ -220,12 +223,14 @@ struct ao_log_mega { int16_t mag_z; /* 28 */ int16_t accel; /* 30 */ } sensor; /* 32 */ + /* AO_LOG_TEMP_VOLT */ struct { int16_t v_batt; /* 4 */ int16_t v_pbatt; /* 6 */ int16_t n_sense; /* 8 */ int16_t sense[10]; /* 10 */ } volt; /* 30 */ + /* AO_LOG_GPS_TIME */ struct { int32_t latitude; /* 4 */ int32_t longitude; /* 8 */ @@ -239,6 +244,7 @@ struct ao_log_mega { uint8_t day; /* 20 */ uint8_t pad; /* 21 */ } gps; /* 22 */ + /* AO_LOG_GPS_SAT */ struct { uint16_t channels; /* 4 */ struct { diff --git a/src/core/ao_pyro.c b/src/core/ao_pyro.c index 4f37e979..aac8fda5 100644 --- a/src/core/ao_pyro.c +++ b/src/core/ao_pyro.c @@ -113,6 +113,15 @@ ao_pyro_ready(struct ao_pyro *pyro) /* handled separately */ continue; + case ao_pyro_state_less: + if (ao_flight_state < pyro->state_less) + continue; + break; + case ao_pyro_state_greater_or_equal: + if (ao_flight_state >= pyro->state_greater_or_equal) + continue; + break; + default: continue; } @@ -166,7 +175,7 @@ uint8_t ao_pyro_wakeup; static void ao_pyro(void) { - uint8_t p; + uint8_t p, any_waiting; struct ao_pyro *pyro; ao_config_get(); @@ -177,6 +186,7 @@ ao_pyro(void) ao_alarm(AO_MS_TO_TICKS(100)); ao_sleep(&ao_pyro_wakeup); ao_clear_alarm(); + any_waiting = 0; for (p = 0; p < AO_PYRO_NUM; p++) { pyro = &ao_config.pyro[p]; @@ -190,6 +200,7 @@ ao_pyro(void) if (!pyro->flags) continue; + any_waiting = 1; /* Check pyro state to see if it shoule fire */ if (!pyro->delay_done) { @@ -213,7 +224,10 @@ ao_pyro(void) ao_pyro_fire(p); } + if (!any_waiting) + break; } + ao_exit(); } __xdata struct ao_task ao_pyro_task; @@ -257,6 +271,9 @@ const struct { { "t<", ao_pyro_time_less, offsetof(struct ao_pyro, time_less), HELP("time less (s * 100)") }, { "t>", ao_pyro_time_greater, offsetof(struct ao_pyro, time_greater), HELP("time greater (s * 100)") }, + { "f<", ao_pyro_state_less, offsetof(struct ao_pyro, state_less), HELP("state less") }, + { "f>=",ao_pyro_state_greater_or_equal, offsetof(struct ao_pyro, state_greater_or_equal), HELP("state greater or equal") }, + { "A", ao_pyro_ascending, NO_VALUE, HELP("ascending") }, { "D", ao_pyro_descending, NO_VALUE, HELP("descending") }, diff --git a/src/core/ao_pyro.h b/src/core/ao_pyro.h index 5deb69d0..cde850ad 100644 --- a/src/core/ao_pyro.h +++ b/src/core/ao_pyro.h @@ -42,6 +42,9 @@ enum ao_pyro_flag { ao_pyro_after_motor = 0x00001000, ao_pyro_delay = 0x00002000, + + ao_pyro_state_less = 0x00004000, + ao_pyro_state_greater_or_equal = 0x00008000, }; struct ao_pyro { @@ -52,6 +55,7 @@ struct ao_pyro { int16_t orient_less, orient_greater; int16_t time_less, time_greater; int16_t delay; + uint8_t state_less, state_greater_or_equal; int16_t motor; uint16_t delay_done; uint8_t fired; diff --git a/src/product/ao_telescience.c b/src/product/ao_telescience.c index 45b6d40e..d448d318 100644 --- a/src/product/ao_telescience.c +++ b/src/product/ao_telescience.c @@ -16,6 +16,9 @@ */ #include "ao.h" +#if HAS_ICP3_COUNT +#include "ao_pwmin.h" +#endif int main(void) @@ -34,6 +37,9 @@ main(void) ao_usb_init(); ao_adc_init(); ao_log_single_init(); +#if HAS_ICP3_COUNT + ao_pwmin_init(); +#endif ao_start_scheduler(); return 0; } diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index 1132f748..f3011d3f 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -266,6 +266,7 @@ ao_clock_init(void) stm_rcc.csr |= (1 << STM_RCC_CSR_RMVF); +#if DEBUG_THE_CLOCK /* Output SYSCLK on PA8 for measurments */ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); @@ -276,4 +277,5 @@ ao_clock_init(void) stm_rcc.cfgr |= (STM_RCC_CFGR_MCOPRE_DIV_1 << STM_RCC_CFGR_MCOPRE); stm_rcc.cfgr |= (STM_RCC_CFGR_MCOSEL_HSE << STM_RCC_CFGR_MCOSEL); +#endif } diff --git a/src/telepyro-v0.1/Makefile b/src/telepyro-v0.1/Makefile index 2ccd565f..6743ba66 100644 --- a/src/telepyro-v0.1/Makefile +++ b/src/telepyro-v0.1/Makefile @@ -96,7 +96,7 @@ ao_product.o: ao_product.c ao_product.h distclean: clean clean: - rm -f $(OBJ) + rm -f $(OBJ) $(PROG) $(PROG).hex rm -f ao_product.h install: diff --git a/src/telescience-pwm/.gitignore b/src/telescience-pwm/.gitignore new file mode 100644 index 00000000..dfccadf8 --- /dev/null +++ b/src/telescience-pwm/.gitignore @@ -0,0 +1,2 @@ +telescience-v0.1* +ao_product.h diff --git a/src/telescience-pwm/Makefile b/src/telescience-pwm/Makefile new file mode 100644 index 00000000..43d77e2e --- /dev/null +++ b/src/telescience-pwm/Makefile @@ -0,0 +1,116 @@ +# +# AltOS build +# +# +vpath % ..:../core:../product:../drivers:../avr +vpath ao-make-product.5c ../util + +MCU=atmega32u4 +DUDECPUTYPE=m32u4 +#PROGRAMMER=stk500v2 -P usb +PROGRAMMER=usbtiny +LOADCMD=avrdude +LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: +CC=avr-gcc +OBJCOPY=avr-objcopy + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_arch.h \ + ao_usb.h \ + ao_pins.h \ + ao_product.h + +# +# Common AltOS sources +# +TELESCIENCE_STORAGE= \ + ao_m25.c \ + ao_spi_usart.c \ + ao_storage.c + +TELESCIENCE_LOG= \ + ao_log_single.c \ + ao_log_telescience.c + +ALTOS_SRC = \ + ao_clock.c \ + ao_cmd.c \ + ao_mutex.c \ + ao_panic.c \ + ao_product.c \ + ao_stdio.c \ + ao_task.c \ + ao_timer.c \ + ao_led.c \ + ao_avr_stdio.c \ + ao_romconfig.c \ + ao_usb_avr.c \ + ao_adc_avr.c \ + ao_science_slave.c \ + ao_spi_slave.c \ + ao_pwmin.c \ + $(TELESCIENCE_STORAGE)\ + $(TELESCIENCE_LOG) + +PRODUCT=TeleScience-PWM +MCU=atmega32u4 +PRODUCT_DEF=-DTELESCIENCE -DTELESCIENCE_PWM +IDPRODUCT=0x0011 +CFLAGS = $(PRODUCT_DEF) -I. -I../avr -I../core -I.. +CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O3 -mcall-prologues -DAVR + +NICKLE=nickle + +PROG=telescience-pwm + +SRC=$(ALTOS_SRC) ao_telescience.c +OBJ=$(SRC:.c=.o) + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: $(PROG) + +CHECK=sh ../util/check-avr-mem + +$(PROG): Makefile $(OBJ) + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) + $(call quiet,CHECK) $(PROG) || ($(RM) -f $(PROG); exit 1) + +$(PROG).hex: $(PROG) + avr-size $(PROG) + $(OBJCOPY) -R .eeprom -O ihex $(PROG) $@ + + +load: $(PROG).hex + $(LOADCMD) $(LOADARG)$(PROG).hex + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +ao_product.o: ao_product.c ao_product.h + +%.o : %.c $(INC) + $(call quiet,CC) -c $(CFLAGS) $< + +distclean: clean + +clean: + rm -f *.o $(PROG) $(PROG).hex + rm -f ao_product.h + +install: + +uninstall: + +$(OBJ): ao_product.h $(INC) diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index 0df9a5d7..7180f02d 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -39,7 +39,7 @@ #define AO_ADC_NUM_SENSE 6 #define HAS_MS5607 1 #define HAS_MPU6000 1 -#define HAS_MMA655X 0 +#define HAS_MMA655X 1 struct ao_adc { int16_t sense[AO_ADC_NUM_SENSE]; @@ -622,6 +622,9 @@ ao_sleep(void *wchan) ao_data_static.mpu6000.gyro_x = int16(bytes, 14); ao_data_static.mpu6000.gyro_y = -int16(bytes, 16); ao_data_static.mpu6000.gyro_z = int16(bytes, 18); +#if HAS_MMA655X + ao_data_static.mma655x = int16(bytes, 26); +#endif if (ao_records_read == 0) ao_ground_mpu6000 = ao_data_static.mpu6000; else if (ao_records_read < 10) { diff --git a/src/test/run-mm b/src/test/run-mm new file mode 100755 index 00000000..6f3d97a2 --- /dev/null +++ b/src/test/run-mm @@ -0,0 +1,41 @@ +#!/bin/sh + +DIR=~/misc/rockets/flights + +for i in "$@"; do +case "$i" in + */*) + file="$i" + ;; + *) + file="$DIR/$i" + ;; +esac +./ao_flight_test_mm "$file" > run-out.mm + +#./ao_flight_test_accel "$file" > run-out.accel +#"run-out.accel" using 1:9 with lines lt 4 axes x1y1 title "accel height",\ +#"run-out.accel" using 1:11 with lines lt 4 axes x1y2 title "accel speed",\ +#"run-out.accel" using 1:13 with lines lt 4 axes x1y2 title "accel accel",\ +#"run-out.accel" using 1:15 with lines lt 4 axes x1y1 title "accel drogue",\ +#"run-out.accel" using 1:17 with lines lt 4 axes x1y1 title "accel main",\ +# + +gnuplot << EOF +set ylabel "altitude (m)" +set y2label "velocity (m/s), acceleration(m/s²)" +set xlabel "time (s)" +set xtics border out nomirror +set ytics border out nomirror +set y2tics border out nomirror +set title "$i" +plot "run-out.mm" using 1:3 with lines lw 2 lt 1 axes x1y1 title "raw height",\ +"run-out.mm" using 1:5 with lines lw 2 lt 1 axes x1y2 title "raw accel",\ +"run-out.mm" using 1:21 with lines lt 2 axes x1y1 title "mm height",\ +"run-out.mm" using 1:23 with lines lt 2 axes x1y2 title "mm speed",\ +"run-out.mm" using 1:25 with lines lt 2 axes x1y2 title "mm accel",\ +"run-out.mm" using 1:29 with lines lt 2 axes x1y1 title "mm drogue",\ +"run-out.mm" using 1:31 with lines lt 2 axes x1y1 title "mm main" +pause mouse close +EOF +done \ No newline at end of file diff --git a/src/util/check-avr-mem b/src/util/check-avr-mem old mode 100644 new mode 100755