diff options
| author | Bdale Garbee <bdale@gag.com> | 2013-05-16 00:36:23 -0600 |
|---|---|---|
| committer | Bdale Garbee <bdale@gag.com> | 2013-05-16 00:36:23 -0600 |
| commit | 02d111b1b53ef01fc6e9ab6c4bc60b8af1be0067 (patch) | |
| tree | 8356f4a019969ee99a45e264c87d38555cf316cc /altoslib | |
| parent | 7a2e1f05adad990a6b161865267abf07ffec7a7e (diff) | |
| parent | 7699a55aed3a9a7daeb4c6a5a9a280f43edf455f (diff) | |
Merge branch 'branch-1.2' into debian
Diffstat (limited to 'altoslib')
76 files changed, 2919 insertions, 876 deletions
diff --git a/altoslib/.gitignore b/altoslib/.gitignore index a71d076c..ff0fd710 100644 --- a/altoslib/.gitignore +++ b/altoslib/.gitignore @@ -1,3 +1,3 @@ bin -classAltosLib.stamp -AltosLib.jar +classaltoslib.stamp +altoslib*.jar diff --git a/altoslib/AltosAccel.java b/altoslib/AltosAccel.java index d14764a2..d02b3238 100644 --- a/altoslib/AltosAccel.java +++ b/altoslib/AltosAccel.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; public class AltosAccel extends AltosUnits { @@ -37,7 +37,7 @@ public class AltosAccel extends AltosUnits { return "meters per second squared"; } - int show_fraction(int width) { + public int show_fraction(int width) { return width / 9; } }
\ No newline at end of file diff --git a/altoslib/AltosCRCException.java b/altoslib/AltosCRCException.java index 101c5363..76e79add 100644 --- a/altoslib/AltosCRCException.java +++ b/altoslib/AltosCRCException.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; public class AltosCRCException extends Exception { public int rssi; diff --git a/altoslib/AltosConfigData.java b/altoslib/AltosConfigData.java index 6f343639..2ca5a7a5 100644 --- a/altoslib/AltosConfigData.java +++ b/altoslib/AltosConfigData.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; import java.util.*; import java.text.*; @@ -26,30 +26,57 @@ public class AltosConfigData implements Iterable<String> { /* Version information */ public String manufacturer; public String product; - public String version; - public int log_format; public int serial; + public int flight; + public int log_format; + public String version; /* Strings returned */ public LinkedList<String> lines; /* Config information */ - public int config_major; - public int config_minor; + /* HAS_FLIGHT*/ public int main_deploy; public int apogee_delay; - public int radio_channel; - public int radio_setting; + public int apogee_lockout; + + /* HAS_RADIO */ public int radio_frequency; public String callsign; - public int accel_cal_plus, accel_cal_minus; + public int radio_enable; public int radio_calibration; + /* Old HAS_RADIO values */ + public int radio_channel; + public int radio_setting; + + /* HAS_ACCEL */ + public int accel_cal_plus, accel_cal_minus; + public int pad_orientation; + + /* HAS_LOG */ public int flight_log_max; + + /* HAS_IGNITE */ public int ignite_mode; - public int stored_flight; + + /* HAS_AES */ + public String aes_key; + + /* AO_PYRO_NUM */ + public AltosPyro[] pyros; + public int npyro; + public int pyro; + + /* HAS_APRS */ + public int aprs_interval; + + /* Storage info replies */ public int storage_size; public int storage_erase_unit; + /* Log listing replies */ + public int stored_flight; + public static String get_string(String line, String label) throws ParseException { if (line.startsWith(label)) { String quoted = line.substring(label.length()).trim(); @@ -83,18 +110,37 @@ public class AltosConfigData implements Iterable<String> { if (stored_flight == 0) return 1; return 0; + case AltosLib.AO_LOG_FORMAT_TELEMETRY: + case AltosLib.AO_LOG_FORMAT_TELESCIENCE: + return 1; default: if (flight_log_max <= 0) return 1; + int log_max = flight_log_max * 1024; int log_space = storage_size - storage_erase_unit; - int log_used = stored_flight * flight_log_max; + int log_used; + + if (stored_flight <= 0) + log_used = 0; + else + log_used = stored_flight * log_max; + int log_avail; if (log_used >= log_space) - return 0; - return (log_space - log_used) / flight_log_max; + log_avail = 0; + else + log_avail = (log_space - log_used) / log_max; + + return log_avail; } } + public boolean has_monitor_battery() { + if (product.startsWith("TeleBT")) + return true; + return false; + } + int[] parse_version(String v) { String[] parts = v.split("\\."); int r[] = new int[parts.length]; @@ -109,7 +155,7 @@ public class AltosConfigData implements Iterable<String> { return r; } - + public int compare_version(String other) { int[] me = parse_version(version); int[] them = parse_version(other); @@ -128,55 +174,342 @@ public class AltosConfigData implements Iterable<String> { return 0; } - public AltosConfigData(AltosLink link) throws InterruptedException, TimeoutException { - link.printf("c s\nf\nl\nv\n"); + public void reset() { lines = new LinkedList<String>(); - radio_setting = 0; - radio_frequency = 0; + + manufacturer = "unknown"; + product = "unknown"; + serial = 0; + flight = 0; + log_format = AltosLib.AO_LOG_FORMAT_UNKNOWN; + version = "unknown"; + + main_deploy = -1; + apogee_delay = -1; + apogee_lockout = -1; + + radio_frequency = -1; + callsign = null; + radio_enable = -1; + radio_calibration = -1; + radio_channel = -1; + radio_setting = -1; + + accel_cal_plus = -1; + accel_cal_minus = -1; + pad_orientation = -1; + + flight_log_max = -1; + ignite_mode = -1; + + aes_key = ""; + + pyro = 0; + npyro = 0; + pyros = null; + + aprs_interval = -1; + + storage_size = -1; + storage_erase_unit = -1; stored_flight = 0; + } + + public void parse_line(String line) { + lines.add(line); + /* Version replies */ + try { manufacturer = get_string(line, "manufacturer"); } catch (Exception e) {} + try { product = get_string(line, "product"); } catch (Exception e) {} + try { serial = get_int(line, "serial-number"); } catch (Exception e) {} + try { flight = get_int(line, "current-flight"); } catch (Exception e) {} + try { log_format = get_int(line, "log-format"); } catch (Exception e) {} + try { version = get_string(line, "software-version"); } catch (Exception e) {} + + /* Version also contains MS5607 info, which we ignore here */ + + /* Config show replies */ + + /* HAS_FLIGHT */ + try { main_deploy = get_int(line, "Main deploy:"); } catch (Exception e) {} + try { apogee_delay = get_int(line, "Apogee delay:"); } catch (Exception e) {} + try { apogee_lockout = get_int(line, "Apogee lockout:"); } catch (Exception e) {} + + /* HAS_RADIO */ + try { + radio_frequency = get_int(line, "Frequency:"); + if (radio_frequency < 0) + radio_frequency = 434550; + } catch (Exception e) {} + try { callsign = get_string(line, "Callsign:"); } catch (Exception e) {} + try { radio_enable = get_int(line, "Radio enable:"); } catch (Exception e) {} + try { radio_calibration = get_int(line, "Radio cal:"); } catch (Exception e) {} + + /* Old HAS_RADIO values */ + try { radio_channel = get_int(line, "Radio channel:"); } catch (Exception e) {} + try { radio_setting = get_int(line, "Radio setting:"); } catch (Exception e) {} + + /* HAS_ACCEL */ + try { + if (line.startsWith("Accel cal")) { + String[] bits = line.split("\\s+"); + if (bits.length >= 6) { + accel_cal_plus = Integer.parseInt(bits[3]); + accel_cal_minus = Integer.parseInt(bits[5]); + } + } + } catch (Exception e) {} + try { pad_orientation = get_int(line, "Pad orientation:"); } catch (Exception e) {} + + /* HAS_LOG */ + try { flight_log_max = get_int(line, "Max flight log:"); } catch (Exception e) {} + + /* HAS_IGNITE */ + try { ignite_mode = get_int(line, "Ignite mode:"); } catch (Exception e) {} + + /* HAS_AES */ + try { aes_key = get_string(line, "AES key:"); } catch (Exception e) {} + + /* AO_PYRO_NUM */ + try { + npyro = get_int(line, "Pyro-count:"); + pyros = new AltosPyro[npyro]; + pyro = 0; + } catch (Exception e) {} + if (npyro > 0) { + try { + AltosPyro p = new AltosPyro(pyro, line); + if (pyro < npyro) + pyros[pyro++] = p; + } catch (Exception e) {} + } + + /* HAS_APRS */ + try { aprs_interval = get_int(line, "APRS interval:"); } catch (Exception e) {} + + /* Storage info replies */ + try { storage_size = get_int(line, "Storage size:"); } catch (Exception e) {} + try { storage_erase_unit = get_int(line, "Storage erase unit:"); } catch (Exception e) {} + + /* Log listing replies */ + try { get_int(line, "flight"); stored_flight++; } catch (Exception e) {} + } + + public AltosConfigData() { + reset(); + } + + private void read_link(AltosLink link, String finished) throws InterruptedException, TimeoutException { for (;;) { String line = link.get_reply(); if (line == null) throw new TimeoutException(); if (line.contains("Syntax error")) continue; - lines.add(line); - 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) {} - try { apogee_delay = get_int(line, "Apogee delay:"); } catch (Exception e) {} - try { radio_channel = get_int(line, "Radio channel:"); } catch (Exception e) {} - try { radio_setting = get_int(line, "Radio setting:"); } catch (Exception e) {} - try { - radio_frequency = get_int(line, "Frequency:"); - if (radio_frequency < 0) - radio_frequency = 434550; - } catch (Exception e) {} - try { - if (line.startsWith("Accel cal")) { - String[] bits = line.split("\\s+"); - if (bits.length >= 6) { - accel_cal_plus = Integer.parseInt(bits[3]); - accel_cal_minus = Integer.parseInt(bits[5]); - } - } - } catch (Exception e) {} - try { radio_calibration = get_int(line, "Radio cal:"); } catch (Exception e) {} - try { flight_log_max = get_int(line, "Max flight log:"); } catch (Exception e) {} - try { ignite_mode = get_int(line, "Ignite mode:"); } catch (Exception e) {} - try { callsign = get_string(line, "Callsign:"); } catch (Exception e) {} - try { version = get_string(line,"software-version"); } catch (Exception e) {} - try { product = get_string(line,"product"); } catch (Exception e) {} - try { manufacturer = get_string(line,"manufacturer"); } catch (Exception e) {} - - 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) {} + this.parse_line(line); /* signals the end of the version info */ - if (line.startsWith("software-version")) + if (line.startsWith(finished)) break; } } -}
\ No newline at end of file + public boolean has_frequency() { + return radio_frequency >= 0 || radio_setting >= 0 || radio_channel >= 0; + } + + public void set_frequency(double freq) { + int frequency = radio_frequency; + int setting = radio_setting; + + if (frequency > 0) { + radio_frequency = (int) Math.floor (freq * 1000 + 0.5); + radio_channel = -1; + } else if (setting > 0) { + radio_setting =AltosConvert.radio_frequency_to_setting(freq, + radio_calibration); + radio_channel = -1; + } else { + radio_channel = AltosConvert.radio_frequency_to_channel(freq); + } + } + + public double frequency() { + int channel = radio_channel; + int setting = radio_setting; + if (channel < 0) + channel = 0; + if (setting < 0) + setting = 0; + + return AltosConvert.radio_to_frequency(radio_frequency, + setting, + radio_calibration, + channel); + } + + public int log_limit() { + if (storage_size > 0 && storage_erase_unit > 0) { + int log_limit = storage_size - storage_erase_unit; + if (log_limit > 0) + return log_limit / 1024; + } + return 1024; + } + + public void get_values(AltosConfigValues source) { + + /* HAS_FLIGHT */ + if (main_deploy >= 0) + main_deploy = source.main_deploy(); + if (apogee_delay >= 0) + apogee_delay = source.apogee_delay(); + if (apogee_lockout >= 0) + apogee_lockout = source.apogee_lockout(); + + /* HAS_RADIO */ + if (has_frequency()) + set_frequency(source.radio_frequency()); + if (radio_enable >= 0) + radio_enable = source.radio_enable(); + if (callsign != null) + callsign = source.callsign(); + if (radio_calibration >= 0) + radio_calibration = source.radio_calibration(); + + /* HAS_ACCEL */ + if (pad_orientation >= 0) + pad_orientation = source.pad_orientation(); + + /* HAS_LOG */ + if (flight_log_max >= 0) + flight_log_max = source.flight_log_max(); + + /* HAS_IGNITE */ + if (ignite_mode >= 0) + ignite_mode = source.ignite_mode(); + + /* AO_PYRO_NUM */ + if (npyro > 0) + pyros = source.pyros(); + + if (aprs_interval >= 0) + aprs_interval = source.aprs_interval(); + } + + public void set_values(AltosConfigValues dest) { + dest.set_serial(serial); + dest.set_product(product); + dest.set_version(version); + dest.set_main_deploy(main_deploy); + dest.set_apogee_delay(apogee_delay); + dest.set_apogee_lockout(apogee_lockout); + dest.set_radio_calibration(radio_calibration); + dest.set_radio_frequency(frequency()); + boolean max_enabled = true; + switch (log_format) { + case AltosLib.AO_LOG_FORMAT_TINY: + max_enabled = false; + break; + default: + if (stored_flight >= 0) + max_enabled = false; + break; + } + dest.set_flight_log_max_enabled(max_enabled); + dest.set_radio_enable(radio_enable); + dest.set_flight_log_max_limit(log_limit()); + dest.set_flight_log_max(flight_log_max); + dest.set_ignite_mode(ignite_mode); + dest.set_pad_orientation(pad_orientation); + dest.set_callsign(callsign); + if (npyro > 0) + dest.set_pyros(pyros); + else + dest.set_pyros(null); + dest.set_aprs_interval(aprs_interval); + } + + public void save(AltosLink link, boolean remote) throws InterruptedException, TimeoutException { + + /* HAS_FLIGHT */ + if (main_deploy >= 0) + link.printf("c m %d\n", main_deploy); + if (apogee_delay >= 0) + link.printf("c d %d\n", apogee_delay); + if (apogee_lockout >= 0) + link.printf("c L %d\n", apogee_lockout); + + /* Don't mess with radio calibration when remote */ + if (radio_calibration > 0 && !remote) + link.printf("c f %d\n", radio_calibration); + + /* HAS_RADIO */ + if (has_frequency()) { + boolean has_frequency = radio_frequency >= 0; + boolean has_setting = radio_setting > 0; + double frequency = frequency(); + link.set_radio_frequency(frequency, + has_frequency, + has_setting, + radio_calibration); + /* When remote, reset the dongle frequency at the same time */ + if (remote) { + link.stop_remote(); + link.set_radio_frequency(frequency); + link.start_remote(); + } + } + + if (callsign != null) + link.printf("c c %s\n", callsign); + if (radio_enable >= 0) + link.printf("c e %d\n", radio_enable); + + /* HAS_ACCEL */ + /* UI doesn't support accel cal */ + if (pad_orientation >= 0) + link.printf("c o %d\n", pad_orientation); + + /* HAS_LOG */ + if (flight_log_max != 0) + link.printf("c l %d\n", flight_log_max); + + /* HAS_IGNITE */ + if (ignite_mode >= 0) + link.printf("c i %d\n", ignite_mode); + + /* HAS_AES */ + /* UI doesn't support AES key config */ + + /* AO_PYRO_NUM */ + if (npyro > 0) { + for (int p = 0; p < pyros.length; p++) { + link.printf("c P %s\n", + pyros[p].toString()); + } + } + + /* HAS_APRS */ + if (aprs_interval >= 0) + link.printf("c A %d\n", aprs_interval); + + link.printf("c w\n"); + link.flush_output(); + } + + public AltosConfigData(AltosLink link) throws InterruptedException, TimeoutException { + reset(); + link.printf("c s\nf\nv\n"); + read_link(link, "software-version"); + switch (log_format) { + case AltosLib.AO_LOG_FORMAT_FULL: + case AltosLib.AO_LOG_FORMAT_TINY: + case AltosLib.AO_LOG_FORMAT_TELEMEGA: + link.printf("l\n"); + read_link(link, "done"); + default: + break; + } + } + +} diff --git a/altoslib/AltosConfigValues.java b/altoslib/AltosConfigValues.java new file mode 100644 index 00000000..027d10f4 --- /dev/null +++ b/altoslib/AltosConfigValues.java @@ -0,0 +1,79 @@ +/* + * Copyright © 2012 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; 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_1; + +public interface AltosConfigValues { + /* set and get all of the dialog values */ + public abstract void set_product(String product); + + public abstract void set_version(String version); + + public abstract void set_serial(int serial); + + public abstract void set_main_deploy(int new_main_deploy); + + public abstract int main_deploy(); + + public abstract void set_apogee_delay(int new_apogee_delay); + + public abstract int apogee_delay(); + + public abstract void set_apogee_lockout(int new_apogee_lockout); + + public abstract int apogee_lockout(); + + public abstract void set_radio_frequency(double new_radio_frequency); + + public abstract double radio_frequency(); + + public abstract void set_radio_calibration(int new_radio_calibration); + + public abstract int radio_calibration(); + + public abstract void set_radio_enable(int new_radio_enable); + + public abstract int radio_enable(); + + public abstract void set_callsign(String new_callsign); + + public abstract String callsign(); + + public abstract void set_flight_log_max(int new_flight_log_max); + + public abstract void set_flight_log_max_enabled(boolean enable); + + public abstract int flight_log_max(); + + public abstract void set_flight_log_max_limit(int flight_log_max_limit); + + public abstract void set_ignite_mode(int new_ignite_mode); + + public abstract int ignite_mode(); + + public abstract void set_pad_orientation(int new_pad_orientation); + + public abstract int pad_orientation(); + + public abstract void set_pyros(AltosPyro[] new_pyros); + + public abstract AltosPyro[] pyros(); + + public abstract int aprs_interval(); + + public abstract void set_aprs_interval(int new_aprs_interval); +} diff --git a/altoslib/AltosConvert.java b/altoslib/AltosConvert.java index acd6c5f4..a42b36c4 100644 --- a/altoslib/AltosConvert.java +++ b/altoslib/AltosConvert.java @@ -18,7 +18,7 @@ /* * Sensor data conversion functions */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; public class AltosConvert { /* @@ -258,6 +258,10 @@ public class AltosConvert { return meters / 9.80665; } + public static double c_to_f(double c) { + return c * 9/5 + 32; + } + public static boolean imperial_units = false; public static AltosDistance distance = new AltosDistance(); @@ -268,6 +272,8 @@ public class AltosConvert { public static AltosAccel accel = new AltosAccel(); + public static AltosTemperature temperature = new AltosTemperature(); + public static String show_gs(String format, double a) { a = meters_to_g(a); format = format.concat(" g"); diff --git a/altoslib/AltosDebug.java b/altoslib/AltosDebug.java new file mode 100644 index 00000000..4d8e3ae7 --- /dev/null +++ b/altoslib/AltosDebug.java @@ -0,0 +1,280 @@ +/* + * Copyright © 2010 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; 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_1; + +import java.io.*; + +public class AltosDebug { + + public static final byte WR_CONFIG = 0x1d; + public static final byte RD_CONFIG = 0x24; + public static final byte CONFIG_TIMERS_OFF = (1 << 3); + public static final byte CONFIG_DMA_PAUSE = (1 << 2); + public static final byte CONFIG_TIMER_SUSPEND = (1 << 1); + public static final byte SET_FLASH_INFO_PAGE = (1 << 0); + + public static final byte GET_PC = 0x28; + public static final byte READ_STATUS = 0x34; + public static final byte STATUS_CHIP_ERASE_DONE = (byte) (1 << 7); + public static final byte STATUS_PCON_IDLE = (1 << 6); + public static final byte STATUS_CPU_HALTED = (1 << 5); + public static final byte STATUS_POWER_MODE_0 = (1 << 4); + public static final byte STATUS_HALT_STATUS = (1 << 3); + public static final byte STATUS_DEBUG_LOCKED = (1 << 2); + public static final byte STATUS_OSCILLATOR_STABLE = (1 << 1); + public static final byte STATUS_STACK_OVERFLOW = (1 << 0); + + public static final byte SET_HW_BRKPNT = 0x3b; + public static byte HW_BRKPNT_N(byte n) { return (byte) ((n) << 3); } + public static final byte HW_BRKPNT_N_MASK = (0x3 << 3); + public static final byte HW_BRKPNT_ENABLE = (1 << 2); + + public static final byte HALT = 0x44; + public static final byte RESUME = 0x4c; + public static byte DEBUG_INSTR(byte n) { return (byte) (0x54|(n)); } + public static final byte STEP_INSTR = 0x5c; + public static byte STEP_REPLACE(byte n) { return (byte) (0x64|(n)); } + public static final byte GET_CHIP_ID = 0x68; + + + AltosLink link; + + boolean debug_mode; + + void ensure_debug_mode() { + if (!debug_mode) { + link.printf("D\n"); + try { + link.flush_input(); + } catch (InterruptedException ie) { + } + debug_mode = true; + } + } + + void dump_memory(String header, int address, byte[] bytes, int start, int len) { + System.out.printf("%s\n", header); + for (int j = 0; j < len; j++) { + if ((j & 15) == 0) { + if (j != 0) + System.out.printf("\n"); + System.out.printf ("%04x:", address + j); + } + System.out.printf(" %02x", bytes[start + j]); + } + System.out.printf("\n"); + } + + public void close() { + link.close(); + } + + /* + * Write target memory + */ + public void write_memory(int address, byte[] bytes, int start, int len) { + ensure_debug_mode(); +// dump_memory("write_memory", address, bytes, start, len); + link.printf("O %x %x\n", len, address); + for (int i = 0; i < len; i++) + link.printf("%02x", bytes[start + i]); + } + + public void write_memory(int address, byte[] bytes) { + write_memory(address, bytes, 0, bytes.length); + } + + /* + * Read target memory + */ + public byte[] read_memory(int address, int length) + throws IOException, InterruptedException { + byte[] data = new byte[length]; + + link.flush_input(); + ensure_debug_mode(); + link.printf("I %x %x\n", length, address); + int i = 0; + int start = 0; + while (i < length) { + String line = link.get_reply().trim(); + if (!AltosLib.ishex(line) || line.length() % 2 != 0) + throw new IOException( + String.format + ("Invalid reply \"%s\"", line)); + int this_time = line.length() / 2; + for (int j = 0; j < this_time; j++) + data[start + j] = (byte) ((AltosLib.fromhex(line.charAt(j*2)) << 4) + + AltosLib.fromhex(line.charAt(j*2+1))); + start += this_time; + i += this_time; + } +// dump_memory("read_memory", address, data, 0, length); + + return data; + } + + /* + * Write raw bytes to the debug link using the 'P' command + */ + public void write_bytes(byte[] bytes) throws IOException { + int i = 0; + ensure_debug_mode(); + while (i < bytes.length) { + int this_time = bytes.length - i; + if (this_time > 8) + this_time = 0; + link.printf("P"); + for (int j = 0; j < this_time; j++) + link.printf(" %02x", bytes[i+j]); + link.printf("\n"); + i += this_time; + } + } + + public void write_byte(byte b) throws IOException { + byte[] bytes = { b }; + write_bytes(bytes); + } + + /* + * Read raw bytes from the debug link using the 'G' command + */ + public byte[] read_bytes(int length) + throws IOException, InterruptedException { + + link.flush_input(); + ensure_debug_mode(); + link.printf("G %x\n", length); + int i = 0; + byte[] data = new byte[length]; + while (i < length) { + String line = link.get_reply(); + + if (line == null) + throw new IOException("Timeout in read_bytes"); + line = line.trim(); + String tokens[] = line.split("\\s+"); + for (int j = 0; j < tokens.length; j++) { + if (!AltosLib.ishex(tokens[j]) || + tokens[j].length() != 2) + throw new IOException( + String.format + ("Invalid read_bytes reply \"%s\"", line)); + try { + if (i + j >= length) + throw new IOException( + String.format + ("Invalid read_bytes reply \"%s\"", line)); + else + data[i + j] = (byte) Integer.parseInt(tokens[j], 16); + } catch (NumberFormatException ne) { + throw new IOException( + String.format + ("Invalid read_bytes reply \"%s\"", line)); + } + } + i += tokens.length; + } + return data; + } + + public byte read_byte() throws IOException, InterruptedException { + return read_bytes(1)[0]; + } + + public byte debug_instr(byte[] instruction) throws IOException, InterruptedException { + byte[] command = new byte[1 + instruction.length]; + command[0] = DEBUG_INSTR((byte) instruction.length); + for (int i = 0; i < instruction.length; i++) + command[i+1] = instruction[i]; + write_bytes(command); + return read_byte(); + } + + public byte resume() throws IOException, InterruptedException { + write_byte(RESUME); + return read_byte(); + } + + public int read_uint16() throws IOException, InterruptedException { + byte[] d = read_bytes(2); + return ((int) (d[0] & 0xff) << 8) | (d[1] & 0xff); + } + + public int read_uint8() throws IOException, InterruptedException { + byte[] d = read_bytes(1); + return (int) (d[0] & 0xff); + } + + public int get_chip_id() throws IOException, InterruptedException { + write_byte(GET_CHIP_ID); + return read_uint16(); + } + + public int get_pc() throws IOException, InterruptedException { + write_byte(GET_PC); + return read_uint16(); + } + + public byte read_status() throws IOException, InterruptedException { + write_byte(READ_STATUS); + return read_byte(); + } + + static final byte LJMP = 0x02; + + public void set_pc(int pc) throws IOException, InterruptedException { + byte high = (byte) (pc >> 8); + byte low = (byte) pc; + byte[] jump_mem = { LJMP, high, low }; + debug_instr(jump_mem); + } + + public boolean check_connection() throws IOException, InterruptedException { + byte reply = read_status(); + if ((reply & STATUS_CHIP_ERASE_DONE) == 0) + return false; + if ((reply & STATUS_PCON_IDLE) != 0) + return false; + if ((reply & STATUS_POWER_MODE_0) == 0) + return false; + return true; + } + + public AltosRomconfig romconfig() { + try { + byte[] bytes = read_memory(0xa0, 10); + return new AltosRomconfig(bytes, 0); + } catch (IOException ie) { + } catch (InterruptedException ie) { + } + return new AltosRomconfig(); + } + + /* + * Reset target + */ + public void reset() { + link.printf ("R\n"); + } + + public AltosDebug (AltosLink link) { + this.link = link; + } +}
\ No newline at end of file diff --git a/altoslib/AltosDistance.java b/altoslib/AltosDistance.java index a6026d4a..25028ac7 100644 --- a/altoslib/AltosDistance.java +++ b/altoslib/AltosDistance.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; public class AltosDistance extends AltosUnits { @@ -37,13 +37,13 @@ public class AltosDistance extends AltosUnits { return "meters"; } - int show_fraction(int width) { + public int show_fraction(int width) { if (AltosConvert.imperial_units) return width / 3; return width / 9; } - int say_fraction() { + public int say_fraction() { if (AltosConvert.imperial_units) return 1; return 0; diff --git a/altoslib/AltosEepromChunk.java b/altoslib/AltosEepromChunk.java index 77b22fe2..b1bba3bb 100644 --- a/altoslib/AltosEepromChunk.java +++ b/altoslib/AltosEepromChunk.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; import java.text.*; import java.util.concurrent.*; diff --git a/altoslib/AltosEepromIterable.java b/altoslib/AltosEepromIterable.java index 986b7a2c..b84574ef 100644 --- a/altoslib/AltosEepromIterable.java +++ b/altoslib/AltosEepromIterable.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; import java.io.*; import java.util.*; @@ -125,30 +125,40 @@ public class AltosEepromIterable extends AltosRecordIterable { 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; + state.gps_sequence++; has_gps = true; break; case AltosLib.AO_LOG_GPS_LAT: eeprom.seen |= AltosRecord.seen_gps_lat; int lat32 = record.a | (record.b << 16); + if (state.gps == null) + state.gps = new AltosGPS(); state.gps.lat = (double) lat32 / 1e7; break; case AltosLib.AO_LOG_GPS_LON: eeprom.seen |= AltosRecord.seen_gps_lon; int lon32 = record.a | (record.b << 16); + if (state.gps == null) + state.gps = new AltosGPS(); state.gps.lon = (double) lon32 / 1e7; break; case AltosLib.AO_LOG_GPS_ALT: + if (state.gps == null) + state.gps = new AltosGPS(); state.gps.alt = record.a; break; case AltosLib.AO_LOG_GPS_SAT: if (state.tick == eeprom.gps_tick) { int svid = record.a; int c_n0 = record.b >> 8; + if (state.gps == null) + state.gps = new AltosGPS(); state.gps.add_sat(svid, c_n0); } break; case AltosLib.AO_LOG_GPS_DATE: + if (state.gps == null) + state.gps = new AltosGPS(); state.gps.year = (record.a & 0xff) + 2000; state.gps.month = record.a >> 8; state.gps.day = record.b & 0xff; diff --git a/altoslib/AltosEepromLog.java b/altoslib/AltosEepromLog.java index 211fd706..20026c6d 100644 --- a/altoslib/AltosEepromLog.java +++ b/altoslib/AltosEepromLog.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; import java.text.*; import java.util.concurrent.*; diff --git a/altoslib/AltosEepromMega.java b/altoslib/AltosEepromMega.java index 26bacf8d..b077e26c 100644 --- a/altoslib/AltosEepromMega.java +++ b/altoslib/AltosEepromMega.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; import java.text.*; @@ -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..5736f937 100644 --- a/altoslib/AltosEepromMegaIterable.java +++ b/altoslib/AltosEepromMegaIterable.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; import java.io.*; import java.util.*; @@ -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; + state.gps_sequence++; 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,74 +281,40 @@ 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 * are sometimes out of order with GPS data getting timestamps @@ -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<AltosOrderedMegaRecord> 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/AltosEepromRecord.java b/altoslib/AltosEepromRecord.java index c7ced6a3..70ac1113 100644 --- a/altoslib/AltosEepromRecord.java +++ b/altoslib/AltosEepromRecord.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; import java.text.*; diff --git a/altoslib/AltosEepromTeleScience.java b/altoslib/AltosEepromTeleScience.java index 02ce4553..2a828cf3 100644 --- a/altoslib/AltosEepromTeleScience.java +++ b/altoslib/AltosEepromTeleScience.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; import java.text.*; diff --git a/altoslib/AltosFile.java b/altoslib/AltosFile.java index 1ab00b38..90dbc6db 100644 --- a/altoslib/AltosFile.java +++ b/altoslib/AltosFile.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; import java.io.File; import java.util.*; diff --git a/altoslib/AltosFlash.java b/altoslib/AltosFlash.java new file mode 100644 index 00000000..010274b9 --- /dev/null +++ b/altoslib/AltosFlash.java @@ -0,0 +1,353 @@ +/* + * Copyright © 2010 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; 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_1; + +import java.io.*; + +public class AltosFlash { + File file; + FileInputStream input; + AltosHexfile image; + AltosLink link; + AltosDebug debug; + AltosRomconfig rom_config; + boolean aborted; + AltosFlashListener listener; + + static final byte MOV_direct_data = (byte) 0x75; + static final byte MOV_DPTR_data16 = (byte) 0x90; + static final byte MOV_A_data = (byte) 0x74; + static final byte MOVX_atDPTR_A = (byte) 0xf0; + static final byte MOVX_A_atDPTR = (byte) 0xe0; + static final byte INC_DPTR = (byte) 0xa3; + static final byte TRAP = (byte) 0xa5; + + static final byte JB = (byte) 0x20; + + static final byte MOV_A_direct = (byte) 0xe5; + static final byte MOV_direct1_direct2 = (byte) 0x85; + static final byte MOV_direct_A = (byte) 0xf5; + static final byte MOV_R0_data = (byte) (0x78 | 0); + static final byte MOV_R1_data = (byte) (0x78 | 1); + static final byte MOV_R2_data = (byte) (0x78 | 2); + static final byte MOV_R3_data = (byte) (0x78 | 3); + static final byte MOV_R4_data = (byte) (0x78 | 4); + static final byte MOV_R5_data = (byte) (0x78 | 5); + static final byte MOV_R6_data = (byte) (0x78 | 6); + static final byte MOV_R7_data = (byte) (0x78 | 7); + static final byte DJNZ_R0_rel = (byte) (0xd8 | 0); + static final byte DJNZ_R1_rel = (byte) (0xd8 | 1); + static final byte DJNZ_R2_rel = (byte) (0xd8 | 2); + static final byte DJNZ_R3_rel = (byte) (0xd8 | 3); + static final byte DJNZ_R4_rel = (byte) (0xd8 | 4); + static final byte DJNZ_R5_rel = (byte) (0xd8 | 5); + static final byte DJNZ_R6_rel = (byte) (0xd8 | 6); + static final byte DJNZ_R7_rel = (byte) (0xd8 | 7); + + static final byte P1DIR = (byte) 0xFE; + static final byte P1 = (byte) 0x90; + + /* flash controller */ + static final byte FWT = (byte) 0xAB; + static final byte FADDRL = (byte) 0xAC; + static final byte FADDRH = (byte) 0xAD; + static final byte FCTL = (byte) 0xAE; + static final byte FCTL_BUSY = (byte) 0x80; + static final byte FCTL_BUSY_BIT = (byte) 7; + static final byte FCTL_SWBSY = (byte) 0x40; + static final byte FCTL_SWBSY_BIT = (byte) 6; + static final byte FCTL_CONTRD = (byte) 0x10; + static final byte FCTL_WRITE = (byte) 0x02; + static final byte FCTL_ERASE = (byte) 0x01; + static final byte FWDATA = (byte) 0xAF; + + static final byte ACC = (byte) 0xE0; + + /* offsets within the flash_page program */ + static final int FLASH_ADDR_HIGH = 8; + static final int FLASH_ADDR_LOW = 11; + static final int RAM_ADDR_HIGH = 13; + static final int RAM_ADDR_LOW = 14; + static final int FLASH_WORDS_HIGH = 16; + static final int FLASH_WORDS_LOW = 18; + static final int FLASH_TIMING = 21; + + /* sleep mode control */ + static final int SLEEP = (byte) 0xbe; + static final int SLEEP_USB_EN = (byte) 0x80; + static final int SLEEP_XOSC_STB = (byte) 0x40; + static final int SLEEP_HFRC_STB = (byte) 0x20; + static final int SLEEP_RST_MASK = (byte) 0x18; + static final int SLEEP_RST_POWERON = (byte) 0x00; + static final int SLEEP_RST_EXTERNAL = (byte) 0x10; + static final int SLEEP_RST_WATCHDOG = (byte) 0x08; + static final int SLEEP_OSC_PD = (byte) 0x04; + static final int SLEEP_MODE_MASK = (byte) 0x03; + static final int SLEEP_MODE_PM0 = (byte) 0x00; + static final int SLEEP_MODE_PM1 = (byte) 0x01; + static final int SLEEP_MODE_PM2 = (byte) 0x02; + static final int SLEEP_MODE_PM3 = (byte) 0x03; + + /* clock controller */ + static final byte CLKCON = (byte) 0xC6; + static final byte CLKCON_OSC32K = (byte) 0x80; + static final byte CLKCON_OSC = (byte) 0x40; + static final byte CLKCON_TICKSPD = (byte) 0x38; + static final byte CLKCON_CLKSPD = (byte) 0x07; + + static final byte[] flash_page_proto = { + + MOV_direct_data, P1DIR, (byte) 0x02, + MOV_direct_data, P1, (byte) 0xFF, + + MOV_direct_data, FADDRH, 0, /* FLASH_ADDR_HIGH */ + + MOV_direct_data, FADDRL, 0, /* FLASH_ADDR_LOW */ + + MOV_DPTR_data16, 0, 0, /* RAM_ADDR_HIGH, RAM_ADDR_LOW */ + + MOV_R7_data, 0, /* FLASH_WORDS_HIGH */ + + MOV_R6_data, 0, /* FLASH_WORDS_LOW */ + + + MOV_direct_data, FWT, 0x20, /* FLASH_TIMING */ + + MOV_direct_data, FCTL, FCTL_ERASE, +/* eraseWaitLoop: */ + MOV_A_direct, FCTL, + JB, ACC|FCTL_BUSY_BIT, (byte) 0xfb, + + MOV_direct_data, P1, (byte) 0xfd, + + MOV_direct_data, FCTL, FCTL_WRITE, +/* writeLoop: */ + MOV_R5_data, 2, +/* writeWordLoop: */ + MOVX_A_atDPTR, + INC_DPTR, + MOV_direct_A, FWDATA, + DJNZ_R5_rel, (byte) 0xfa, /* writeWordLoop */ +/* writeWaitLoop: */ + MOV_A_direct, FCTL, + JB, ACC|FCTL_SWBSY_BIT, (byte) 0xfb, /* writeWaitLoop */ + DJNZ_R6_rel, (byte) 0xf1, /* writeLoop */ + DJNZ_R7_rel, (byte) 0xef, /* writeLoop */ + + MOV_direct_data, P1DIR, (byte) 0x00, + MOV_direct_data, P1, (byte) 0xFF, + TRAP, + }; + + public byte[] make_flash_page(int flash_addr, int ram_addr, int byte_count) { + int flash_word_addr = flash_addr >> 1; + int flash_word_count = ((byte_count + 1) >> 1); + + byte[] flash_page = new byte[flash_page_proto.length]; + for (int i = 0; i < flash_page.length; i++) + flash_page[i] = flash_page_proto[i]; + + flash_page[FLASH_ADDR_HIGH] = (byte) (flash_word_addr >> 8); + flash_page[FLASH_ADDR_LOW] = (byte) (flash_word_addr); + flash_page[RAM_ADDR_HIGH] = (byte) (ram_addr >> 8); + flash_page[RAM_ADDR_LOW] = (byte) (ram_addr); + + byte flash_words_low = (byte) (flash_word_count); + byte flash_words_high = (byte) (flash_word_count >> 8); + /* the flashing code has a minor 'bug' */ + if (flash_words_low != 0) + flash_words_high++; + + flash_page[FLASH_WORDS_HIGH] = (byte) flash_words_high; + flash_page[FLASH_WORDS_LOW] = (byte) flash_words_low; + return flash_page; + } + + static byte[] set_clkcon_fast = { + MOV_direct_data, CLKCON, 0x00 + }; + + static byte[] get_sleep = { + MOV_A_direct, SLEEP + }; + + public void clock_init() throws IOException, InterruptedException { + if (debug != null) { + debug.debug_instr(set_clkcon_fast); + + byte status; + for (int times = 0; times < 20; times++) { + Thread.sleep(1); + status = debug.debug_instr(get_sleep); + if ((status & SLEEP_XOSC_STB) != 0) + return; + } + throw new IOException("Failed to initialize target clock"); + } + } + + void action(String s, int percent) { + if (listener != null && !aborted) + listener.position(s, percent); + } + + void action(int part, int total) { + int percent = 100 * part / total; + action(String.format("%d/%d (%d%%)", + part, total, percent), + percent); + } + + void altos_run(int pc) throws IOException, InterruptedException { + debug.set_pc(pc); + int set_pc = debug.get_pc(); + if (pc != set_pc) + throw new IOException("Failed to set target program counter"); + debug.resume(); + + for (int times = 0; times < 20; times++) { + byte status = debug.read_status(); + if ((status & AltosDebug.STATUS_CPU_HALTED) != 0) + return; + } + + throw new IOException("Failed to execute program on target"); + } + + public void flash() { + try { + if (!check_rom_config()) + throw new IOException("Invalid rom config settings"); + if (image.address + image.data.length > 0x8000) + throw new IOException(String.format("Flash image too long %d", + image.address + + image.data.length)); + if ((image.address & 0x3ff) != 0) + throw new IOException(String.format("Flash image must start on page boundary (is 0x%x)", + image.address)); + int ram_address = 0xf000; + int flash_prog = 0xf400; + + /* + * Store desired config values into image + */ + rom_config.write(image); + /* + * Bring up the clock + */ + clock_init(); + + int remain = image.data.length; + int flash_addr = image.address; + int image_start = 0; + + action("start", 0); + action(0, image.data.length); + while (remain > 0 && !aborted) { + int this_time = remain; + if (this_time > 0x400) + this_time = 0x400; + + if (debug != null) { + /* write the data */ + debug.write_memory(ram_address, image.data, + image_start, this_time); + + /* write the flash program */ + byte[] flash_page = make_flash_page(flash_addr, + ram_address, + this_time); + debug.write_memory(flash_prog, flash_page); + + altos_run(flash_prog); + byte[] check = debug.read_memory(flash_addr, this_time); + for (int i = 0; i < this_time; i++) + if (check[i] != image.data[image_start + i]) + throw new IOException(String.format("Flash write failed at 0x%x (%02x != %02x)", + image.address + image_start + i, + check[i], image.data[image_start + i])); + } else { + Thread.sleep(100); + } + + remain -= this_time; + flash_addr += this_time; + image_start += this_time; + + action(image.data.length - remain, image.data.length); + } + if (!aborted) { + action("done", 100); + if (debug != null) { + debug.set_pc(image.address); + debug.resume(); + } + } + if (debug != null) + debug.close(); + } catch (IOException ie) { + action(ie.getMessage(), -1); + abort(); + } catch (InterruptedException ie) { + abort(); + } + } + + public void close() { + if (debug != null) + debug.close(); + } + + synchronized public void abort() { + aborted = true; + close(); + } + + public boolean check_rom_config() { + if (debug == null) + return true; + if (rom_config == null) + rom_config = debug.romconfig(); + return rom_config != null && rom_config.valid(); + } + + public void set_romconfig (AltosRomconfig romconfig) { + rom_config = romconfig; + } + + public AltosRomconfig romconfig() { + if (!check_rom_config()) + return null; + return rom_config; + } + + public AltosFlash(File file, AltosLink link, AltosFlashListener listener) + throws IOException, FileNotFoundException, InterruptedException { + this.file = file; + this.link = link; + this.listener = listener; + if (link != null) + debug = new AltosDebug(link); + input = new FileInputStream(file); + image = new AltosHexfile(input); + if (debug != null && !debug.check_connection()) { + debug.close(); + throw new IOException("Debug port not connected"); + } + } +}
\ No newline at end of file diff --git a/altoslib/AltosFlashListener.java b/altoslib/AltosFlashListener.java new file mode 100644 index 00000000..ab50b74a --- /dev/null +++ b/altoslib/AltosFlashListener.java @@ -0,0 +1,22 @@ +/* + * Copyright © 2013 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; 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_1; + +public interface AltosFlashListener { + public void position(String label, int percent); +} diff --git a/altoslib/AltosFlightReader.java b/altoslib/AltosFlightReader.java index cbd64153..34526658 100644 --- a/altoslib/AltosFlightReader.java +++ b/altoslib/AltosFlightReader.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; import java.text.*; import java.io.*; @@ -45,4 +45,8 @@ public class AltosFlightReader { public boolean supports_telemetry(int telemetry) { return false; } public File backing_file() { return null; } + + public boolean has_monitor_battery() { return false; } + + public double monitor_battery() { return AltosRecord.MISSING; } } diff --git a/altoslib/AltosFrequency.java b/altoslib/AltosFrequency.java index e20f03b7..484a2fd9 100644 --- a/altoslib/AltosFrequency.java +++ b/altoslib/AltosFrequency.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; public class AltosFrequency { public double frequency; diff --git a/altoslib/AltosGPS.java b/altoslib/AltosGPS.java index ea0949ec..f23842f3 100644 --- a/altoslib/AltosGPS.java +++ b/altoslib/AltosGPS.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; import java.text.*; @@ -217,33 +217,38 @@ public class AltosGPS { } public AltosGPS(AltosGPS old) { - nsat = old.nsat; - locked = old.locked; - connected = old.connected; - lat = old.lat; /* degrees (+N -S) */ - lon = old.lon; /* degrees (+E -W) */ - alt = old.alt; /* m */ - year = old.year; - month = old.month; - day = old.day; - hour = old.hour; - minute = old.minute; - second = old.second; - - ground_speed = old.ground_speed; /* m/s */ - course = old.course; /* degrees */ - climb_rate = old.climb_rate; /* m/s */ - hdop = old.hdop; /* unitless? */ - h_error = old.h_error; /* m */ - v_error = old.v_error; /* m */ - - if (old.cc_gps_sat != null) { - cc_gps_sat = new AltosGPSSat[old.cc_gps_sat.length]; - for (int i = 0; i < old.cc_gps_sat.length; i++) { - cc_gps_sat[i] = new AltosGPSSat(); - cc_gps_sat[i].svid = old.cc_gps_sat[i].svid; - cc_gps_sat[i].c_n0 = old.cc_gps_sat[i].c_n0; + if (old != null) { + nsat = old.nsat; + locked = old.locked; + connected = old.connected; + lat = old.lat; /* degrees (+N -S) */ + lon = old.lon; /* degrees (+E -W) */ + alt = old.alt; /* m */ + year = old.year; + month = old.month; + day = old.day; + hour = old.hour; + minute = old.minute; + second = old.second; + + ground_speed = old.ground_speed; /* m/s */ + course = old.course; /* degrees */ + climb_rate = old.climb_rate; /* m/s */ + hdop = old.hdop; /* unitless? */ + h_error = old.h_error; /* m */ + v_error = old.v_error; /* m */ + + if (old.cc_gps_sat != null) { + cc_gps_sat = new AltosGPSSat[old.cc_gps_sat.length]; + for (int i = 0; i < old.cc_gps_sat.length; i++) { + cc_gps_sat[i] = new AltosGPSSat(); + cc_gps_sat[i].svid = old.cc_gps_sat[i].svid; + cc_gps_sat[i].c_n0 = old.cc_gps_sat[i].c_n0; + } } + } else { + ClearGPSTime(); + cc_gps_sat = null; } } } diff --git a/altoslib/AltosGPSQuery.java b/altoslib/AltosGPSQuery.java index e93af259..deb9d201 100644 --- a/altoslib/AltosGPSQuery.java +++ b/altoslib/AltosGPSQuery.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; import java.util.concurrent.*; diff --git a/altoslib/AltosGPSSat.java b/altoslib/AltosGPSSat.java index faa1ec8d..8714dd8a 100644 --- a/altoslib/AltosGPSSat.java +++ b/altoslib/AltosGPSSat.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; public class AltosGPSSat { public int svid; diff --git a/altoslib/AltosGreatCircle.java b/altoslib/AltosGreatCircle.java index 76b71859..f1cf0ae9 100644 --- a/altoslib/AltosGreatCircle.java +++ b/altoslib/AltosGreatCircle.java @@ -15,13 +15,15 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; import java.lang.Math; public class AltosGreatCircle { public double distance; public double bearing; + public double range; + public double elevation; double sqr(double a) { return a * a; } @@ -54,9 +56,8 @@ public class AltosGreatCircle { return bearing_string[length][(int)((bearing / 90 * 8 + 1) / 2)%16]; } - public AltosGreatCircle (double start_lat, double start_lon, - double end_lat, double end_lon) - { + public AltosGreatCircle (double start_lat, double start_lon, double start_alt, + double end_lat, double end_lon, double end_alt) { double lat1 = rad * start_lat; double lon1 = rad * -start_lon; double lat2 = rad * end_lat; @@ -88,14 +89,25 @@ public class AltosGreatCircle { } distance = d * earth_radius; bearing = course * 180/Math.PI; + + double height_diff = end_alt - start_alt; + range = Math.sqrt(distance * distance + height_diff * height_diff); + elevation = Math.atan2(height_diff, distance) * 180 / Math.PI; + } + + public AltosGreatCircle (double start_lat, double start_lon, + double end_lat, double end_lon) { + this(start_lat, start_lon, 0, end_lat, end_lon, 0); } public AltosGreatCircle(AltosGPS start, AltosGPS end) { - this(start.lat, start.lon, end.lat, end.lon); + this(start.lat, start.lon, start.alt, end.lat, end.lon, end.alt); } public AltosGreatCircle() { distance = 0; bearing = 0; + range = 0; + elevation = 0; } } diff --git a/altoslib/AltosHeight.java b/altoslib/AltosHeight.java index da7ffdae..ed590812 100644 --- a/altoslib/AltosHeight.java +++ b/altoslib/AltosHeight.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; public class AltosHeight extends AltosUnits { @@ -37,7 +37,7 @@ public class AltosHeight extends AltosUnits { return "meters"; } - int show_fraction(int width) { + public int show_fraction(int width) { return width / 9; } }
\ No newline at end of file diff --git a/altoslib/AltosHexfile.java b/altoslib/AltosHexfile.java new file mode 100644 index 00000000..2140228a --- /dev/null +++ b/altoslib/AltosHexfile.java @@ -0,0 +1,300 @@ +/* + * Copyright © 2010 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; 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_1; + +import java.io.*; +import java.util.LinkedList; +import java.util.Arrays; + +class HexFileInputStream extends PushbackInputStream { + public int line; + + public HexFileInputStream(FileInputStream o) { + super(new BufferedInputStream(o)); + line = 1; + } + + public int read() throws IOException { + int c = super.read(); + if (c == '\n') + line++; + return c; + } + + public void unread(int c) throws IOException { + if (c == '\n') + line--; + if (c != -1) + super.unread(c); + } +} + +class HexRecord implements Comparable<Object> { + public int address; + public int type; + public byte checksum; + public byte[] data; + + static final int NORMAL = 0; + static final int EOF = 1; + static final int EXTENDED_ADDRESS = 2; + + enum read_state { + marker, + length, + address, + type, + data, + checksum, + newline, + white, + done, + } + + boolean ishex(int c) { + if ('0' <= c && c <= '9') + return true; + if ('a' <= c && c <= 'f') + return true; + if ('A' <= c && c <= 'F') + return true; + return false; + } + + boolean isspace(int c) { + switch (c) { + case ' ': + case '\t': + return true; + } + return false; + } + + int fromhex(int c) { + if ('0' <= c && c <= '9') + return c - '0'; + if ('a' <= c && c <= 'f') + return c - 'a' + 10; + if ('A' <= c && c <= 'F') + return c - 'A' + 10; + return -1; + } + + public byte checksum() { + byte got = 0; + + got += data.length; + got += (address >> 8) & 0xff; + got += (address ) & 0xff; + got += type; + for (int i = 0; i < data.length; i++) + got += data[i]; + return (byte) (-got); + } + + public int compareTo(Object other) { + HexRecord o = (HexRecord) other; + return address - o.address; + } + + public String toString() { + return String.format("%04x: %02x (%d)", address, type, data.length); + } + + public HexRecord(HexFileInputStream input) throws IOException { + read_state state = read_state.marker; + int nhexbytes = 0; + int hex = 0; + int ndata = 0; + byte got_checksum; + + while (state != read_state.done) { + int c = input.read(); + if (c < 0 && state != read_state.white) + throw new IOException(String.format("%d: Unexpected EOF", input.line)); + if (c == ' ') + continue; + switch (state) { + case marker: + if (c != ':') + throw new IOException("Missing ':'"); + state = read_state.length; + nhexbytes = 2; + hex = 0; + break; + case length: + case address: + case type: + case data: + case checksum: + if(!ishex(c)) + throw new IOException(String.format("Non-hex char '%c'", c)); + hex = hex << 4 | fromhex(c); + --nhexbytes; + if (nhexbytes != 0) + break; + + switch (state) { + case length: + data = new byte[hex]; + state = read_state.address; + nhexbytes = 4; + break; + case address: + address = hex; + state = read_state.type; + nhexbytes = 2; + break; + case type: + type = hex; + if (data.length > 0) + state = read_state.data; + else + state = read_state.checksum; + nhexbytes = 2; + ndata = 0; + break; + case data: + data[ndata] = (byte) hex; + ndata++; + nhexbytes = 2; + if (ndata == data.length) + state = read_state.checksum; + break; + case checksum: + checksum = (byte) hex; + state = read_state.newline; + break; + default: + break; + } + hex = 0; + break; + case newline: + if (c != '\n' && c != '\r') + throw new IOException("Missing newline"); + state = read_state.white; + break; + case white: + if (!isspace(c)) { + input.unread(c); + state = read_state.done; + } + break; + case done: + break; + } + } + got_checksum = checksum(); + if (got_checksum != checksum) + throw new IOException(String.format("Invalid checksum (read 0x%02x computed 0x%02x)\n", + checksum, got_checksum)); + } +} + +public class AltosHexfile { + public int address; + public byte[] data; + + public byte get_byte(int a) { + return data[a - address]; + } + + public AltosHexfile(FileInputStream file) throws IOException { + HexFileInputStream input = new HexFileInputStream(file); + LinkedList<HexRecord> record_list = new LinkedList<HexRecord>(); + boolean done = false; + + while (!done) { + HexRecord record = new HexRecord(input); + + if (record.type == HexRecord.EOF) + done = true; + else + record_list.add(record); + } + + long extended_addr = 0; + long base = 0; + long bound = 0; + boolean set = false; + for (HexRecord record : record_list) { + switch (record.type) { + case 0: + long addr = extended_addr + record.address; + long r_bound = addr + record.data.length; + if (!set || addr < base) + base = addr; + if (!set || r_bound > bound) + bound = r_bound; + set = true; + break; + case 1: + break; + case 2: + if (record.data.length != 2) + throw new IOException("invalid extended segment address record"); + extended_addr = ((record.data[0] << 8) + (record.data[1])) << 4; + break; + case 4: + if (record.data.length != 2) + throw new IOException("invalid extended segment address record"); + extended_addr = ((record.data[0] << 8) + (record.data[1])) << 16; + break; + default: + throw new IOException ("invalid hex record type"); + } + } + + if (!set || base >= bound) + throw new IOException("invalid hex file"); + + if (bound - base > 4 * 1024 * 1024) + throw new IOException("hex file too large"); + + data = new byte[(int) (bound - base)]; + address = (int) base; + Arrays.fill(data, (byte) 0xff); + + /* Paint the records into the new array */ + for (HexRecord record : record_list) { + switch (record.type) { + case 0: + long addr = extended_addr + record.address; + long r_bound = addr + record.data.length; + for (int j = 0; j < record.data.length; j++) + data[(int) (addr - base) + j] = record.data[j]; + break; + case 1: + break; + case 2: + if (record.data.length != 2) + throw new IOException("invalid extended segment address record"); + extended_addr = ((record.data[0] << 8) + (record.data[1])) << 4; + break; + case 4: + if (record.data.length != 2) + throw new IOException("invalid extended segment address record"); + extended_addr = ((record.data[0] << 8) + (record.data[1])) << 16; + break; + default: + throw new IOException ("invalid hex record type"); + } + } + } +}
\ No newline at end of file diff --git a/altoslib/AltosIMU.java b/altoslib/AltosIMU.java index c0eaf139..8f6731fa 100644 --- a/altoslib/AltosIMU.java +++ b/altoslib/AltosIMU.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; public class AltosIMU { public int accel_x; diff --git a/altoslib/AltosIMUQuery.java b/altoslib/AltosIMUQuery.java index 0965fa39..4ea5d963 100644 --- a/altoslib/AltosIMUQuery.java +++ b/altoslib/AltosIMUQuery.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; import java.util.concurrent.TimeoutException; diff --git a/altoslib/AltosIdleMonitor.java b/altoslib/AltosIdleMonitor.java index 2c4965ff..b3ce5b20 100644 --- a/altoslib/AltosIdleMonitor.java +++ b/altoslib/AltosIdleMonitor.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; import java.io.*; import java.util.concurrent.*; @@ -27,7 +27,9 @@ public class AltosIdleMonitor extends Thread { AltosState state; boolean remote; double frequency; + String callsign; AltosState previous_state; + AltosListenerState listener_state; AltosConfigData config_data; AltosGPS gps; @@ -50,11 +52,11 @@ public class AltosIdleMonitor extends Thread { } boolean has_sensor_mm(AltosConfigData config_data) { - return config_data.product.startsWith("MegaMetrum"); + return config_data.product.startsWith("TeleMega"); } boolean has_gps(AltosConfigData config_data) { - return config_data.product.startsWith("TeleMetrum") || config_data.product.startsWith("MegaMetrum"); + return config_data.product.startsWith("TeleMetrum") || config_data.product.startsWith("TeleMega"); } AltosRecord sensor_mm(AltosConfigData config_data) throws InterruptedException, TimeoutException { @@ -87,6 +89,7 @@ public class AltosIdleMonitor extends Thread { try { if (remote) { link.set_radio_frequency(frequency); + link.set_callsign(callsign); link.start_remote(); } else link.flush_input(); @@ -97,7 +100,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); @@ -109,13 +112,15 @@ public class AltosIdleMonitor extends Thread { record.status = 0; record.state = AltosLib.ao_flight_idle; record.gps = gps; - record.new_gps = true; + record.gps_sequence++; state = new AltosState (record, state); } finally { if (remote) { link.stop_remote(); - if (record != null) - record.rssi = AltosRSSI(); + if (record != null) { + record.rssi = link.rssi(); + listener_state.battery = link.monitor_battery(); + } } else { if (record != null) record.rssi = 0; @@ -126,10 +131,27 @@ public class AltosIdleMonitor extends Thread { public void set_frequency(double in_frequency) { frequency = in_frequency; + link.abort_reply(); + } + + public void set_callsign(String in_callsign) { + callsign = in_callsign; + link.abort_reply(); } public void post_state() { - listener.update(state); + listener.update(state, listener_state); + } + + public void abort() { + if (isAlive()) { + interrupt(); + link.abort_reply(); + try { + join(); + } catch (InterruptedException ie) { + } + } } public void run() { @@ -153,5 +175,6 @@ public class AltosIdleMonitor extends Thread { link = in_link; remote = in_remote; state = null; + listener_state = new AltosListenerState(); } } diff --git a/altoslib/AltosIdleMonitorListener.java b/altoslib/AltosIdleMonitorListener.java index 9f9ababf..27e36dea 100644 --- a/altoslib/AltosIdleMonitorListener.java +++ b/altoslib/AltosIdleMonitorListener.java @@ -15,8 +15,8 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; public interface AltosIdleMonitorListener { - public void update(AltosState state); + public void update(AltosState state, AltosListenerState listener_state); }
\ No newline at end of file diff --git a/altoslib/AltosIgnite.java b/altoslib/AltosIgnite.java index a48d0b69..85905900 100644 --- a/altoslib/AltosIgnite.java +++ b/altoslib/AltosIgnite.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; import java.io.*; import java.util.concurrent.*; diff --git a/altoslib/AltosLib.java b/altoslib/AltosLib.java index 192c445e..25d17e72 100644 --- a/altoslib/AltosLib.java +++ b/altoslib/AltosLib.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; import java.util.*; import java.io.*; @@ -50,7 +50,7 @@ public class AltosLib { public static final int AO_LOG_SERIAL_NUMBER = 2002; public static final int AO_LOG_LOG_FORMAT = 2003; - /* Added for header fields in megametrum files */ + /* Added for header fields in telemega files */ public static final int AO_LOG_BARO_RESERVED = 3000; public static final int AO_LOG_BARO_SENS = 3001; public static final int AO_LOG_BARO_OFF = 3002; @@ -89,10 +89,11 @@ public class AltosLib { public final static int product_telelco = 0x0010; public final static int product_telescience = 0x0011; public final static int product_telepyro =0x0012; - public final static int product_megametrum = 0x0023; + public final static int product_telemega = 0x0023; public final static int product_megadongle = 0x0024; + public final static int product_telegps = 0x0025; public final static int product_altusmetrum_min = 0x000a; - public final static int product_altusmetrum_max = 0x0024; + public final static int product_altusmetrum_max = 0x0025; public final static int product_any = 0x10000; public final static int product_basestation = 0x10000 + 1; @@ -199,7 +200,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]; } @@ -214,7 +215,7 @@ public class AltosLib { public static final int AO_LOG_FORMAT_TINY = 2; public static final int AO_LOG_FORMAT_TELEMETRY = 3; public static final int AO_LOG_FORMAT_TELESCIENCE = 4; - public static final int AO_LOG_FORMAT_MEGAMETRUM = 5; + public static final int AO_LOG_FORMAT_TELEMEGA = 5; public static final int AO_LOG_FORMAT_NONE = 127; public static boolean isspace(int c) { @@ -405,4 +406,8 @@ public class AltosLib { input = input.substring(0,dot); return input.concat(extension); } + + public static File replace_extension(File input, String extension) { + return new File(replace_extension(input.getPath(), extension)); + } } diff --git a/altoslib/AltosLine.java b/altoslib/AltosLine.java index 5627795a..b3bd20f9 100644 --- a/altoslib/AltosLine.java +++ b/altoslib/AltosLine.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; public class AltosLine { public String line; diff --git a/altoslib/AltosLink.java b/altoslib/AltosLink.java index 6d510563..159ebfe1 100644 --- a/altoslib/AltosLink.java +++ b/altoslib/AltosLink.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; import java.io.*; import java.util.concurrent.*; @@ -249,6 +249,7 @@ public abstract class AltosLink implements Runnable { public boolean monitor_mode = false; public int telemetry = AltosLib.ao_telemetry_standard; public double frequency; + public String callsign; AltosConfigData config_data; private int telemetry_len() { @@ -284,8 +285,8 @@ public abstract class AltosLink implements Runnable { frequency = in_frequency; config_data(); set_radio_frequency(frequency, - config_data.radio_frequency != 0, - config_data.radio_setting != 0, + config_data.radio_frequency > 0, + config_data.radio_setting > 0, config_data.radio_calibration); } @@ -330,6 +331,7 @@ public abstract class AltosLink implements Runnable { } public void set_callsign(String callsign) { + this.callsign = callsign; printf ("c c %s\n", callsign); flush_output(); } @@ -339,10 +341,10 @@ public abstract class AltosLink implements Runnable { public String name; public void start_remote() throws TimeoutException, InterruptedException { - if (debug) - System.out.printf("start remote %7.3f\n", frequency); if (frequency == 0.0) frequency = AltosPreferences.frequency(serial); + if (debug) + System.out.printf("start remote %7.3f\n", frequency); set_radio_frequency(frequency); set_callsign(AltosPreferences.callsign()); printf("p\nE 0\n"); @@ -362,6 +364,64 @@ public abstract class AltosLink implements Runnable { remote = false; } + public int rssi() throws TimeoutException, InterruptedException { + if (remote) + return 0; + printf("s\n"); + String line = get_reply_no_dialog(5000); + if (line == null) + throw new TimeoutException(); + String[] items = line.split("\\s+"); + if (items.length < 2) + return 0; + if (!items[0].equals("RSSI:")) + return 0; + int rssi = Integer.parseInt(items[1]); + return rssi; + } + + public String[] adc() throws TimeoutException, InterruptedException { + printf("a\n"); + for (;;) { + String line = get_reply_no_dialog(5000); + if (line == null) { + throw new TimeoutException(); + } + if (!line.startsWith("tick:")) + continue; + String[] items = line.split("\\s+"); + return items; + } + } + + public boolean has_monitor_battery() { + return config_data.has_monitor_battery(); + } + + public double monitor_battery() { + int monitor_batt = AltosRecord.MISSING; + + if (config_data.has_monitor_battery()) { + try { + String[] items = adc(); + for (int i = 0; i < items.length;) { + if (items[i].equals("batt")) { + monitor_batt = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + i++; + } + } catch (InterruptedException ie) { + } catch (TimeoutException te) { + } + } + if (monitor_batt == AltosRecord.MISSING) + return AltosRecord.MISSING; + return AltosConvert.cc_battery_to_voltage(monitor_batt); + } + public AltosLink() { + callsign = ""; } } diff --git a/altoslib/AltosListenerState.java b/altoslib/AltosListenerState.java new file mode 100644 index 00000000..2fb4673e --- /dev/null +++ b/altoslib/AltosListenerState.java @@ -0,0 +1,28 @@ +/* + * Copyright © 2013 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; 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_1; + +public class AltosListenerState { + public int crc_errors; + public double battery; + + public AltosListenerState() { + crc_errors = 0; + battery = AltosRecord.MISSING; + } +} diff --git a/altoslib/AltosLog.java b/altoslib/AltosLog.java index 3c124700..974c9f0f 100644 --- a/altoslib/AltosLog.java +++ b/altoslib/AltosLog.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; import java.io.*; import java.text.ParseException; @@ -25,7 +25,7 @@ import java.util.concurrent.LinkedBlockingQueue; * This creates a thread to capture telemetry data and write it to * a log file */ -class AltosLog implements Runnable { +public class AltosLog implements Runnable { LinkedBlockingQueue<AltosLine> input_queue; LinkedBlockingQueue<String> pending_queue; @@ -45,7 +45,7 @@ class AltosLog implements Runnable { } } - void close() { + public void close() { close_log_file(); if (log_thread != null) { log_thread.interrupt(); @@ -53,7 +53,7 @@ class AltosLog implements Runnable { } } - File file() { + public File file() { return file; } @@ -85,7 +85,7 @@ class AltosLog implements Runnable { continue; try { AltosRecord telem = AltosTelemetry.parse(line.line, previous); - if (telem.serial != 0 && telem.flight != 0 && + if ((telem.seen & AltosRecord.seen_flight) != 0 && (telem.serial != serial || telem.flight != flight || log_file == null)) { close_log_file(); diff --git a/altoslib/AltosMag.java b/altoslib/AltosMag.java index 0f8399ab..b3bbd92f 100644 --- a/altoslib/AltosMag.java +++ b/altoslib/AltosMag.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; public class AltosMag { public int x; diff --git a/altoslib/AltosMs5607.java b/altoslib/AltosMs5607.java index 268e89f6..606916b7 100644 --- a/altoslib/AltosMs5607.java +++ b/altoslib/AltosMs5607.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; public class AltosMs5607 { public int reserved; @@ -32,6 +32,8 @@ public class AltosMs5607 { public int pa; public int cc; + static final boolean ms5611 = false; + void convert() { int dT; int TEMP; @@ -41,20 +43,26 @@ public class AltosMs5607 { dT = raw_temp - ((int) tref << 8); - TEMP = (int) (2000 + (((long) dT * tempsens) >> 23)); + TEMP = (int) (2000 + (((long) dT * (long) tempsens) >> 23)); + + if (ms5611) { + OFF = ((long) off << 16) + (((long) tco * (long) dT) >> 7); - OFF = ((long) off << 17) + (((long) tco * dT) >> 6); + SENS = ((long) sens << 15) + (((long) tcs * (long) dT) >> 8); + } else { + OFF = ((long) off << 17) + (((long) tco * (long) dT) >> 6); - SENS = ((long) sens << 16) + (((long) tcs * dT) >> 7); + SENS = ((long) sens << 16) + (((long) tcs * (long) dT) >> 7); + } if (TEMP < 2000) { int T2 = (int) (((long) dT * (long) dT) >> 31); int TEMPM = TEMP - 2000; - long OFF2 = (61 * (long) TEMPM * (long) TEMPM) >> 4; - long SENS2 = 2 * (long) TEMPM * (long) TEMPM; + long OFF2 = ((long) 61 * (long) TEMPM * (long) TEMPM) >> 4; + long SENS2 = (long) 2 * (long) TEMPM * (long) TEMPM; if (TEMP < 1500) { int TEMPP = TEMP + 1500; - long TEMPP2 = TEMPP * TEMPP; + long TEMPP2 = (long) TEMPP * (long) TEMPP; OFF2 = OFF2 + 15 * TEMPP2; SENS2 = SENS2 + 8 * TEMPP2; } @@ -74,6 +82,43 @@ public class AltosMs5607 { return pa; } + public boolean parse_line(String line) { + String[] items = line.split("\\s+"); + if (line.startsWith("Pressure:")) { + if (items.length >= 2) + raw_pres = Integer.parseInt(items[1]); + } else if (line.startsWith("Temperature:")) { + if (items.length >= 2) + raw_temp = Integer.parseInt(items[1]); + } else if (line.startsWith("ms5607 reserved:")) { + if (items.length >= 3) + reserved = Integer.parseInt(items[2]); + } else if (line.startsWith("ms5607 sens:")) { + if (items.length >= 3) + sens = Integer.parseInt(items[2]); + } else if (line.startsWith("ms5607 off:")) { + if (items.length >= 3) + off = Integer.parseInt(items[2]); + } else if (line.startsWith("ms5607 tcs:")) { + if (items.length >= 3) + tcs = Integer.parseInt(items[2]); + } else if (line.startsWith("ms5607 tco:")) { + if (items.length >= 3) + tco = Integer.parseInt(items[2]); + } else if (line.startsWith("ms5607 tref:")) { + if (items.length >= 3) + tref = Integer.parseInt(items[2]); + } else if (line.startsWith("ms5607 tempsens:")) { + if (items.length >= 3) + tempsens = Integer.parseInt(items[2]); + } else if (line.startsWith("ms5607 crc:")) { + if (items.length >= 3) + crc = Integer.parseInt(items[2]); + } else if (line.startsWith("Altitude")) + return false; + return true; + } + public AltosMs5607() { raw_pres = AltosRecord.MISSING; raw_temp = AltosRecord.MISSING; diff --git a/altoslib/AltosMs5607Query.java b/altoslib/AltosMs5607Query.java index 3c746795..d39dbf26 100644 --- a/altoslib/AltosMs5607Query.java +++ b/altoslib/AltosMs5607Query.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; import java.util.concurrent.TimeoutException; @@ -27,38 +27,7 @@ class AltosMs5607Query extends AltosMs5607 { if (line == null) { throw new TimeoutException(); } - String[] items = line.split("\\s+"); - if (line.startsWith("Pressure:")) { - if (items.length >= 2) - raw_pres = Integer.parseInt(items[1]); - } else if (line.startsWith("Temperature:")) { - if (items.length >= 2) - raw_temp = Integer.parseInt(items[1]); - } else if (line.startsWith("ms5607 reserved:")) { - if (items.length >= 3) - reserved = Integer.parseInt(items[2]); - } else if (line.startsWith("ms5607 sens:")) { - if (items.length >= 3) - sens = Integer.parseInt(items[2]); - } else if (line.startsWith("ms5607 off:")) { - if (items.length >= 3) - off = Integer.parseInt(items[2]); - } else if (line.startsWith("ms5607 tcs:")) { - if (items.length >= 3) - tcs = Integer.parseInt(items[2]); - } else if (line.startsWith("ms5607 tco:")) { - if (items.length >= 3) - tco = Integer.parseInt(items[2]); - } else if (line.startsWith("ms5607 tref:")) { - if (items.length >= 3) - tref = Integer.parseInt(items[2]); - } else if (line.startsWith("ms5607 tempsens:")) { - if (items.length >= 3) - tempsens = Integer.parseInt(items[2]); - } else if (line.startsWith("ms5607 crc:")) { - if (items.length >= 3) - crc = Integer.parseInt(items[2]); - } else if (line.startsWith("Altitude")) + if (!parse_line(line)) break; } convert(); diff --git a/altoslib/AltosOrderedMegaRecord.java b/altoslib/AltosOrderedMegaRecord.java index 05423dd9..b20a5bbd 100644 --- a/altoslib/AltosOrderedMegaRecord.java +++ b/altoslib/AltosOrderedMegaRecord.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; import java.text.ParseException; @@ -43,18 +43,6 @@ class AltosOrderedMegaRecord extends AltosEepromMega implements Comparable<Altos index = in_index; } - public AltosOrderedMegaRecord(int in_cmd, int in_tick, int in_a, int in_b, int in_index) { - super(in_cmd, in_tick); - a = in_a; - b = in_b; - index = in_index; - } - - public String toString() { - return String.format("%d.%d %04x %04x %04x", - cmd, index, tick, a, b); - } - public int compareTo(AltosOrderedMegaRecord o) { int tick_diff = tick - o.tick; if (tick_diff != 0) diff --git a/altoslib/AltosOrderedRecord.java b/altoslib/AltosOrderedRecord.java index b4cfd8f2..63507d39 100644 --- a/altoslib/AltosOrderedRecord.java +++ b/altoslib/AltosOrderedRecord.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; import java.text.ParseException; diff --git a/altoslib/AltosParse.java b/altoslib/AltosParse.java index e938a177..66bbeed5 100644 --- a/altoslib/AltosParse.java +++ b/altoslib/AltosParse.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; import java.text.*; diff --git a/altoslib/AltosPreferences.java b/altoslib/AltosPreferences.java index 0e7b2bd3..088ca3d7 100644 --- a/altoslib/AltosPreferences.java +++ b/altoslib/AltosPreferences.java @@ -15,15 +15,13 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; import java.io.*; import java.util.*; -import java.util.prefs.*; -import javax.swing.filechooser.FileSystemView; public class AltosPreferences { - public static Preferences preferences; + public static AltosPreferencesBackend backend = null; /* logdir preference name */ public final static String logdirPreference = "LOGDIR"; @@ -64,6 +62,9 @@ public class AltosPreferences { /* Log directory */ public static File logdir; + /* Last log directory - use this next time we open or save something */ + public static File last_logdir; + /* Map directory -- hangs of logdir */ public static File mapdir; @@ -100,13 +101,10 @@ public class AltosPreferences { public static AltosFrequency[] load_common_frequencies() { AltosFrequency[] frequencies = null; boolean existing = false; - try { - existing = preferences.nodeExists(common_frequencies_node_name); - } catch (BackingStoreException be) { - existing = false; - } + existing = backend.nodeExists(common_frequencies_node_name); + if (existing) { - Preferences node = preferences.node(common_frequencies_node_name); + AltosPreferencesBackend node = backend.node(common_frequencies_node_name); int count = node.getInt(frequency_count, 0); frequencies = new AltosFrequency[count]; @@ -115,7 +113,7 @@ public class AltosPreferences { String description; frequency = node.getDouble(String.format(frequency_format, i), 0.0); - description = node.get(String.format(description_format, i), null); + description = node.getString(String.format(description_format, i), null); frequencies[i] = new AltosFrequency(frequency, description); } } else { @@ -129,28 +127,27 @@ public class AltosPreferences { } public static void save_common_frequencies(AltosFrequency[] frequencies) { - Preferences node = preferences.node(common_frequencies_node_name); + AltosPreferencesBackend node = backend.node(common_frequencies_node_name); node.putInt(frequency_count, frequencies.length); for (int i = 0; i < frequencies.length; i++) { node.putDouble(String.format(frequency_format, i), frequencies[i].frequency); - node.put(String.format(description_format, i), frequencies[i].description); + node.putString(String.format(description_format, i), frequencies[i].description); } } public static int launcher_serial; public static int launcher_channel; - public static void init() { - preferences = Preferences.userRoot().node("/org/altusmetrum/altosui"); + public static void init(AltosPreferencesBackend in_backend) { + backend = in_backend; /* Initialize logdir from preferences */ - String logdir_string = preferences.get(logdirPreference, null); + String logdir_string = backend.getString(logdirPreference, null); if (logdir_string != null) logdir = new File(logdir_string); else { - /* Use the file system view default directory */ - logdir = new File(FileSystemView.getFileSystemView().getDefaultDirectory(), logdirName); + logdir = new File(backend.homeDirectory(), logdirName); if (!logdir.exists()) logdir.mkdirs(); } @@ -162,17 +159,17 @@ public class AltosPreferences { telemetries = new Hashtable<Integer,Integer>(); - voice = preferences.getBoolean(voicePreference, true); + voice = backend.getBoolean(voicePreference, true); - callsign = preferences.get(callsignPreference,"N0CALL"); + callsign = backend.getString(callsignPreference,"N0CALL"); - scanning_telemetry = preferences.getInt(scanningTelemetryPreference,(1 << AltosLib.ao_telemetry_standard)); + scanning_telemetry = backend.getInt(scanningTelemetryPreference,(1 << AltosLib.ao_telemetry_standard)); - launcher_serial = preferences.getInt(launcherSerialPreference, 0); + launcher_serial = backend.getInt(launcherSerialPreference, 0); - launcher_channel = preferences.getInt(launcherChannelPreference, 0); + launcher_channel = backend.getInt(launcherChannelPreference, 0); - String firmwaredir_string = preferences.get(firmwaredirPreference, null); + String firmwaredir_string = backend.getString(firmwaredirPreference, null); if (firmwaredir_string != null) firmwaredir = new File(firmwaredir_string); else @@ -180,65 +177,69 @@ public class AltosPreferences { common_frequencies = load_common_frequencies(); - AltosConvert.imperial_units = preferences.getBoolean(unitsPreference, false); + AltosConvert.imperial_units = backend.getBoolean(unitsPreference, false); } - static { init(); } - public static void flush_preferences() { - try { - preferences.flush(); - } catch (BackingStoreException ee) { -/* - if (component != null) - JOptionPane.showMessageDialog(component, - preferences.absolutePath(), - "Cannot save prefernces", - JOptionPane.ERROR_MESSAGE); - else -*/ - System.err.printf("Cannot save preferences\n"); - } + backend.flush(); } public static void set_logdir(File new_logdir) { - synchronized (preferences) { + synchronized (backend) { logdir = new_logdir; mapdir = new File(logdir, "maps"); if (!mapdir.exists()) mapdir.mkdirs(); - preferences.put(logdirPreference, logdir.getPath()); + backend.putString(logdirPreference, logdir.getPath()); flush_preferences(); } } public static File logdir() { - synchronized (preferences) { + synchronized (backend) { return logdir; } } + public static File last_logdir() { + synchronized (backend) { + if (last_logdir == null) + last_logdir = logdir; + return last_logdir; + } + } + + public static void set_last_logdir(File file) { + synchronized(backend) { + if (file != null && !file.isDirectory()) + file = file.getParentFile(); + if (file == null) + file = new File("."); + last_logdir = file; + } + } + public static File mapdir() { - synchronized (preferences) { + synchronized (backend) { return mapdir; } } public static void set_frequency(int serial, double new_frequency) { - synchronized (preferences) { + synchronized (backend) { frequencies.put(serial, new_frequency); - preferences.putDouble(String.format(frequencyPreferenceFormat, serial), new_frequency); + backend.putDouble(String.format(frequencyPreferenceFormat, serial), new_frequency); flush_preferences(); } } public static double frequency(int serial) { - synchronized (preferences) { + synchronized (backend) { if (frequencies.containsKey(serial)) return frequencies.get(serial); - double frequency = preferences.getDouble(String.format(frequencyPreferenceFormat, serial), 0); + double frequency = backend.getDouble(String.format(frequencyPreferenceFormat, serial), 0); if (frequency == 0.0) { - int channel = preferences.getInt(String.format(channelPreferenceFormat, serial), 0); + int channel = backend.getInt(String.format(channelPreferenceFormat, serial), 0); frequency = AltosConvert.radio_channel_to_frequency(channel); } frequencies.put(serial, frequency); @@ -247,122 +248,122 @@ public class AltosPreferences { } public static void set_telemetry(int serial, int new_telemetry) { - synchronized (preferences) { + synchronized (backend) { telemetries.put(serial, new_telemetry); - preferences.putInt(String.format(telemetryPreferenceFormat, serial), new_telemetry); + backend.putInt(String.format(telemetryPreferenceFormat, serial), new_telemetry); flush_preferences(); } } public static int telemetry(int serial) { - synchronized (preferences) { + synchronized (backend) { if (telemetries.containsKey(serial)) return telemetries.get(serial); - int telemetry = preferences.getInt(String.format(telemetryPreferenceFormat, serial), - AltosLib.ao_telemetry_standard); + int telemetry = backend.getInt(String.format(telemetryPreferenceFormat, serial), + AltosLib.ao_telemetry_standard); telemetries.put(serial, telemetry); return telemetry; } } public static void set_scanning_telemetry(int new_scanning_telemetry) { - synchronized (preferences) { + synchronized (backend) { scanning_telemetry = new_scanning_telemetry; - preferences.putInt(scanningTelemetryPreference, scanning_telemetry); + backend.putInt(scanningTelemetryPreference, scanning_telemetry); flush_preferences(); } } public static int scanning_telemetry() { - synchronized (preferences) { + synchronized (backend) { return scanning_telemetry; } } public static void set_voice(boolean new_voice) { - synchronized (preferences) { + synchronized (backend) { voice = new_voice; - preferences.putBoolean(voicePreference, voice); + backend.putBoolean(voicePreference, voice); flush_preferences(); } } public static boolean voice() { - synchronized (preferences) { + synchronized (backend) { return voice; } } public static void set_callsign(String new_callsign) { - synchronized(preferences) { + synchronized(backend) { callsign = new_callsign; - preferences.put(callsignPreference, callsign); + backend.putString(callsignPreference, callsign); flush_preferences(); } } public static String callsign() { - synchronized(preferences) { + synchronized(backend) { return callsign; } } public static void set_firmwaredir(File new_firmwaredir) { - synchronized (preferences) { + synchronized (backend) { firmwaredir = new_firmwaredir; - preferences.put(firmwaredirPreference, firmwaredir.getPath()); + backend.putString(firmwaredirPreference, firmwaredir.getPath()); flush_preferences(); } } public static File firmwaredir() { - synchronized (preferences) { + synchronized (backend) { return firmwaredir; } } public static void set_launcher_serial(int new_launcher_serial) { - synchronized (preferences) { + synchronized (backend) { launcher_serial = new_launcher_serial; - preferences.putInt(launcherSerialPreference, launcher_serial); + backend.putInt(launcherSerialPreference, launcher_serial); flush_preferences(); } } public static int launcher_serial() { - synchronized (preferences) { + synchronized (backend) { return launcher_serial; } } public static void set_launcher_channel(int new_launcher_channel) { - synchronized (preferences) { + synchronized (backend) { launcher_channel = new_launcher_channel; - preferences.putInt(launcherChannelPreference, launcher_channel); + backend.putInt(launcherChannelPreference, launcher_channel); flush_preferences(); } } public static int launcher_channel() { - synchronized (preferences) { + synchronized (backend) { return launcher_channel; } } - public static Preferences bt_devices() { - synchronized (preferences) { - return preferences.node("bt_devices"); + public static AltosPreferencesBackend bt_devices() { + synchronized (backend) { + return backend.node("bt_devices"); } } public static AltosFrequency[] common_frequencies() { - synchronized (preferences) { + synchronized (backend) { return common_frequencies; } } public static void set_common_frequencies(AltosFrequency[] frequencies) { - synchronized(preferences) { + synchronized(backend) { common_frequencies = frequencies; save_common_frequencies(frequencies); flush_preferences(); @@ -387,17 +388,38 @@ public class AltosPreferences { set_common_frequencies(new_frequencies); } + static LinkedList<AltosUnitsListener> units_listeners; + public static boolean imperial_units() { - synchronized(preferences) { + synchronized(backend) { return AltosConvert.imperial_units; } } public static void set_imperial_units(boolean imperial_units) { - synchronized (preferences) { + synchronized (backend) { AltosConvert.imperial_units = imperial_units; - preferences.putBoolean(unitsPreference, imperial_units); + backend.putBoolean(unitsPreference, imperial_units); flush_preferences(); } + if (units_listeners != null) { + for (AltosUnitsListener l : units_listeners) { + l.units_changed(imperial_units); + } + } + } + + public static void register_units_listener(AltosUnitsListener l) { + synchronized(backend) { + if (units_listeners == null) + units_listeners = new LinkedList<AltosUnitsListener>(); + units_listeners.add(l); + } + } + + public static void unregister_units_listener(AltosUnitsListener l) { + synchronized(backend) { + units_listeners.remove(l); + } } } diff --git a/altoslib/AltosPreferencesBackend.java b/altoslib/AltosPreferencesBackend.java new file mode 100644 index 00000000..fb8a235a --- /dev/null +++ b/altoslib/AltosPreferencesBackend.java @@ -0,0 +1,45 @@ +/* + * Copyright © 2010 Mike Beattie <mike@ethernal.org> + * + * 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_1; + +import java.io.File; + +public interface AltosPreferencesBackend { + + public String getString(String key, String def); + public void putString(String key, String value); + + public int getInt(String key, int def); + public void putInt(String key, int value); + + public double getDouble(String key, double def); + public void putDouble(String key, double value); + + public boolean getBoolean(String key, boolean def); + public void putBoolean(String key, boolean value); + + public boolean nodeExists(String key); + public AltosPreferencesBackend node(String key); + + public String[] keys(); + public void remove(String key); + + public void flush(); + + public File homeDirectory(); +} diff --git a/altoslib/AltosPyro.java b/altoslib/AltosPyro.java new file mode 100644 index 00000000..4dbb4223 --- /dev/null +++ b/altoslib/AltosPyro.java @@ -0,0 +1,293 @@ +/* + * Copyright © 2012 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; 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_1; + +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,Integer> string_to_pyro = new HashMap<String,Integer>(); + + private static HashMap<Integer,String> pyro_to_string = new HashMap<Integer,String>(); + + private static HashMap<Integer,String> pyro_to_name = new HashMap<Integer,String>(); + + private static HashMap<Integer,Double> pyro_to_scale = new HashMap<Integer,Double>(); + + 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("<disabled>")) + 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..5e4ed927 100644 --- a/altoslib/AltosRecord.java +++ b/altoslib/AltosRecord.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; public class AltosRecord implements Comparable <AltosRecord>, Cloneable { @@ -43,13 +43,8 @@ public class AltosRecord implements Comparable <AltosRecord>, 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; + public int gps_sequence; public double time; /* seconds since boost */ @@ -63,6 +58,11 @@ public class AltosRecord implements Comparable <AltosRecord>, 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 <AltosRecord>, Cloneable { * temperature: °C */ - public double raw_pressure() { return MISSING; } - - public double filtered_pressure() { return MISSING; } - + public double pressure() { return MISSING; } public double ground_pressure() { return MISSING; } - - public double battery_voltage() { return MISSING; } - - public double main_voltage() { return MISSING; } - - 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; } + public double altitude() { + double p = pressure(); - /* - * 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); @@ -154,6 +126,12 @@ public class AltosRecord implements Comparable <AltosRecord>, Cloneable { return tick - o.tick; } + public AltosRecord clone() { + AltosRecord n = new AltosRecord(); + n.copy(this); + return n; + } + public void copy(AltosRecord old) { seen = old.seen; version = old.version; @@ -164,39 +142,30 @@ public class AltosRecord implements Comparable <AltosRecord>, 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; + gps_sequence = old.gps_sequence; companion = old.companion; - } - - public AltosRecord clone() { - try { - AltosRecord n = (AltosRecord) super.clone(); - n.copy(this); - return n; - } catch (CloneNotSupportedException e) { - return null; - } + kalman_acceleration = old.kalman_acceleration; + kalman_speed = old.kalman_speed; + kalman_height = old.kalman_height; } public AltosRecord() { seen = 0; version = 0; callsign = "N0CALL"; - serial = 0; - flight = 0; + serial = MISSING; + flight = MISSING; rssi = 0; status = 0; state = AltosLib.ao_flight_startup; tick = 0; - acceleration = MISSING; - speed = MISSING; - height = MISSING; - gps = new AltosGPS(); - new_gps = false; + gps = null; + gps_sequence = 0; companion = null; + + kalman_acceleration = MISSING; + kalman_speed = MISSING; + kalman_height = MISSING; } } diff --git a/altoslib/AltosRecordCompanion.java b/altoslib/AltosRecordCompanion.java index c8cc6cac..b153fb5b 100644 --- a/altoslib/AltosRecordCompanion.java +++ b/altoslib/AltosRecordCompanion.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; public class AltosRecordCompanion { public final static int board_id_telescience = 0x0a; diff --git a/altoslib/AltosRecordIterable.java b/altoslib/AltosRecordIterable.java index ed1787ed..62dbdfe3 100644 --- a/altoslib/AltosRecordIterable.java +++ b/altoslib/AltosRecordIterable.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; import java.io.*; import java.util.*; diff --git a/altoslib/AltosRecordMM.java b/altoslib/AltosRecordMM.java index 5f952f7a..bf64192c 100644 --- a/altoslib/AltosRecordMM.java +++ b/altoslib/AltosRecordMM.java @@ -15,10 +15,11 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; 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); @@ -141,10 +131,10 @@ public class AltosRecordMM extends AltosRecord { mag = old.mag; } + + public AltosRecordMM clone() { - AltosRecordMM n = (AltosRecordMM) super.clone(); - n.copy(this); - return n; + return new AltosRecordMM(this); } void make_missing() { @@ -177,6 +167,10 @@ public class AltosRecordMM extends AltosRecord { make_missing(); } + public AltosRecordMM(AltosRecordMM old) { + copy(old); + } + public AltosRecordMM() { super(); make_missing(); diff --git a/altoslib/AltosRecordNone.java b/altoslib/AltosRecordNone.java new file mode 100644 index 00000000..a95b6a9c --- /dev/null +++ b/altoslib/AltosRecordNone.java @@ -0,0 +1,38 @@ +/* + * Copyright © 2012 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; 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_1; + +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 clone() { + return new AltosRecordNone(this); + } + + public AltosRecordNone() { + super(); + } +} diff --git a/altoslib/AltosRecordTM.java b/altoslib/AltosRecordTM.java index 37accef6..c6cf3646 100644 --- a/altoslib/AltosRecordTM.java +++ b/altoslib/AltosRecordTM.java @@ -15,9 +15,11 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; 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); @@ -164,9 +149,7 @@ public class AltosRecordTM extends AltosRecord { } public AltosRecordTM clone() { - AltosRecordTM n = (AltosRecordTM) super.clone(); - n.copy(this); - return n; + return new AltosRecordTM(this); } void make_missing() { @@ -192,6 +175,10 @@ public class AltosRecordTM extends AltosRecord { make_missing(); } + public AltosRecordTM(AltosRecordTM old) { + copy(old); + } + public AltosRecordTM() { super(); make_missing(); diff --git a/altoslib/AltosReplayReader.java b/altoslib/AltosReplayReader.java index 50bef07a..a7e30370 100644 --- a/altoslib/AltosReplayReader.java +++ b/altoslib/AltosReplayReader.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; import java.io.*; import java.util.*; diff --git a/altoslib/AltosRomconfig.java b/altoslib/AltosRomconfig.java new file mode 100644 index 00000000..0800a2c4 --- /dev/null +++ b/altoslib/AltosRomconfig.java @@ -0,0 +1,148 @@ +/* + * Copyright © 2010 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; 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_1; + +import java.io.*; + +public class AltosRomconfig { + public boolean valid; + public int version; + public int check; + public int serial_number; + public int radio_calibration; + + static int get_int(byte[] bytes, int start, int len) { + int v = 0; + int o = 0; + while (len > 0) { + v = v | ((((int) bytes[start]) & 0xff) << o); + start++; + len--; + o += 8; + } + return v; + } + + static void put_int(int value, byte[] bytes, int start, int len) { + while (len > 0) { + bytes[start] = (byte) (value & 0xff); + start++; + len--; + value >>= 8; + } + } + + static void put_string(String value, byte[] bytes, int start) { + for (int i = 0; i < value.length(); i++) + bytes[start + i] = (byte) value.charAt(i); + } + + static final int AO_USB_DESC_STRING = 3; + + static void put_usb_serial(int value, byte[] bytes, int start) { + int offset = start + 0xa; + int string_num = 0; + + while (offset < bytes.length && bytes[offset] != 0) { + if (bytes[offset + 1] == AO_USB_DESC_STRING) { + ++string_num; + if (string_num == 4) + break; + } + offset += ((int) bytes[offset]) & 0xff; + } + if (offset >= bytes.length || bytes[offset] == 0) + return; + int len = ((((int) bytes[offset]) & 0xff) - 2) / 2; + String fmt = String.format("%%0%dd", len); + + String s = String.format(fmt, value); + if (s.length() != len) { + System.out.printf("weird usb length issue %s isn't %d\n", + s, len); + return; + } + for (int i = 0; i < len; i++) { + bytes[offset + 2 + i*2] = (byte) s.charAt(i); + bytes[offset + 2 + i*2+1] = 0; + } + } + + public AltosRomconfig(byte[] bytes, int offset) { + version = get_int(bytes, offset + 0, 2); + check = get_int(bytes, offset + 2, 2); + if (check == (~version & 0xffff)) { + switch (version) { + case 2: + case 1: + serial_number = get_int(bytes, offset + 4, 2); + radio_calibration = get_int(bytes, offset + 6, 4); + valid = true; + break; + } + } + } + + public AltosRomconfig(AltosHexfile hexfile) { + this(hexfile.data, 0xa0 - hexfile.address); + } + + public void write(byte[] bytes, int offset) throws IOException { + if (!valid) + throw new IOException("rom configuration invalid"); + + if (offset < 0 || bytes.length < offset + 10) + throw new IOException("image cannot contain rom config"); + + AltosRomconfig existing = new AltosRomconfig(bytes, offset); + if (!existing.valid) + throw new IOException("image does not contain existing rom config"); + + switch (existing.version) { + case 2: + put_usb_serial(serial_number, bytes, offset); + case 1: + put_int(serial_number, bytes, offset + 4, 2); + put_int(radio_calibration, bytes, offset + 6, 4); + break; + } + } + + public void write (AltosHexfile hexfile) throws IOException { + write(hexfile.data, 0xa0 - hexfile.address); + AltosRomconfig check = new AltosRomconfig(hexfile); + if (!check.valid()) + throw new IOException("writing new rom config failed\n"); + } + + public AltosRomconfig(int in_serial_number, int in_radio_calibration) { + valid = true; + version = 1; + check = (~version & 0xffff); + serial_number = in_serial_number; + radio_calibration = in_radio_calibration; + } + + public boolean valid() { + return valid && serial_number != 0; + } + + public AltosRomconfig() { + valid = false; + } +} diff --git a/altoslib/AltosSensorMM.java b/altoslib/AltosSensorMM.java index b6f21ef0..6d1b61c0 100644 --- a/altoslib/AltosSensorMM.java +++ b/altoslib/AltosSensorMM.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; import java.util.concurrent.TimeoutException; @@ -28,75 +28,65 @@ class AltosSensorMM { int accel_ref; public AltosSensorMM(AltosLink link) throws InterruptedException, TimeoutException { - link.printf("a\n"); - for (;;) { - String line = link.get_reply_no_dialog(5000); - if (line == null) { - throw new TimeoutException(); + String[] items = link.adc(); + sense = new int[6]; + for (int i = 0; i < items.length;) { + if (items[i].equals("tick:")) { + tick = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("0:")) { + sense[0] = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("1:")) { + sense[1] = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("2:")) { + sense[2] = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("3:")) { + sense[3] = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("4:")) { + sense[4] = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("5:")) { + sense[5] = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("6:")) { + v_batt = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("7:")) { + v_pyro = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("8:")) { + accel = Integer.parseInt(items[i+1]); + i += 2; + continue; } - if (!line.startsWith("tick:")) + if (items[i].equals("9:")) { + accel_ref = Integer.parseInt(items[i+1]); + i += 2; continue; - String[] items = line.split("\\s+"); - sense = new int[6]; - for (int i = 0; i < items.length;) { - if (items[i].equals("tick:")) { - tick = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("0:")) { - sense[0] = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("1:")) { - sense[1] = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("2:")) { - sense[2] = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("3:")) { - sense[3] = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("4:")) { - sense[4] = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("5:")) { - sense[5] = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("6:")) { - v_batt = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("7:")) { - v_pyro = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("8:")) { - accel = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("9:")) { - accel_ref = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - i++; } - break; + i++; } } } diff --git a/altoslib/AltosSensorTM.java b/altoslib/AltosSensorTM.java index 75158cbf..754dc5bb 100644 --- a/altoslib/AltosSensorTM.java +++ b/altoslib/AltosSensorTM.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; import java.util.concurrent.TimeoutException; @@ -23,54 +23,44 @@ class AltosSensorTM extends AltosRecordTM { public AltosSensorTM(AltosLink link, AltosConfigData config_data) throws InterruptedException, TimeoutException { super(); - link.printf("a\n"); - for (;;) { - String line = link.get_reply_no_dialog(5000); - if (line == null) { - throw new TimeoutException(); + String[] items = link.adc(); + for (int i = 0; i < items.length;) { + if (items[i].equals("tick:")) { + tick = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("accel:")) { + accel = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("pres:")) { + pres = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("temp:")) { + temp = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("batt:")) { + batt = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("drogue:")) { + drogue = Integer.parseInt(items[i+1]); + i += 2; + continue; } - if (!line.startsWith("tick:")) + if (items[i].equals("main:")) { + main = Integer.parseInt(items[i+1]); + i += 2; continue; - String[] items = line.split("\\s+"); - for (int i = 0; i < items.length;) { - if (items[i].equals("tick:")) { - tick = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("accel:")) { - accel = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("pres:")) { - pres = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("temp:")) { - temp = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("batt:")) { - batt = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("drogue:")) { - drogue = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("main:")) { - main = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - i++; } - break; + i++; } ground_accel = config_data.accel_cal_plus; ground_pres = pres; diff --git a/altoslib/AltosSpeed.java b/altoslib/AltosSpeed.java index af63ed17..6fb624fb 100644 --- a/altoslib/AltosSpeed.java +++ b/altoslib/AltosSpeed.java @@ -15,29 +15,29 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; public class AltosSpeed extends AltosUnits { public double value(double v) { if (AltosConvert.imperial_units) - return AltosConvert.meters_to_feet(v); + return AltosConvert.meters_to_mph(v); return v; } public String show_units() { if (AltosConvert.imperial_units) - return "ft/s"; + return "mph"; return "m/s"; } public String say_units() { if (AltosConvert.imperial_units) - return "feet per second"; + return "miles per hour"; return "meters per second"; } - int show_fraction(int width) { + public int show_fraction(int width) { return width / 9; } }
\ No newline at end of file diff --git a/altoslib/AltosState.java b/altoslib/AltosState.java index 2e4d8870..825306be 100644 --- a/altoslib/AltosState.java +++ b/altoslib/AltosState.java @@ -19,7 +19,7 @@ * Track flight state from telemetry or eeprom data stream */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; public class AltosState { public AltosRecord data; @@ -40,20 +40,21 @@ 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; + public int gps_sequence; public AltosIMU imu; public AltosMag mag; @@ -76,20 +77,50 @@ 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; + /* Discard previous state if it was for a different board */ + if (prev_state != null && prev_state.data.serial != data.serial) + prev_state = null; ground_altitude = data.ground_altitude(); - altitude = data.raw_altitude(); - height = data.filtered_height(); + + altitude = data.altitude(); + if (altitude == AltosRecord.MISSING && data.gps != null) + altitude = data.gps.alt; + + height = AltosRecord.MISSING; + if (data.kalman_height != AltosRecord.MISSING) + height = data.kalman_height; + else { + if (altitude != AltosRecord.MISSING && ground_altitude != AltosRecord.MISSING) { + double cur_height = altitude - ground_altitude; + if (prev_state == null || prev_state.height == AltosRecord.MISSING) + height = cur_height; + else + height = (prev_state.height * 15 + cur_height) / 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(); @@ -103,12 +134,13 @@ public class AltosState { npad = prev_state.npad; ngps = prev_state.ngps; gps = prev_state.gps; + gps_sequence = prev_state.gps_sequence; pad_lat = prev_state.pad_lat; pad_lon = prev_state.pad_lon; 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,28 +151,58 @@ 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; + + double prev_baro_speed = prev_state.baro_speed; + if (prev_baro_speed == AltosRecord.MISSING) + prev_baro_speed = 0; - double height_change = height - prev_state.height; - if (data.speed != AltosRecord.MISSING) - baro_speed = data.speed; - else { if (time_change > 0) - baro_speed = (prev_state.baro_speed * 3 + (height_change / time_change)) / 4.0; + baro_speed = (prev_baro_speed * 3 + (height_change / time_change)) / 4.0; else baro_speed = prev_state.baro_speed; + + double prev_accel_speed = prev_state.accel_speed; + + if (prev_accel_speed == AltosRecord.MISSING) + prev_accel_speed = 0; + + if (acceleration == AltosRecord.MISSING) { + /* Fill in mising acceleration value */ + accel_speed = baro_speed; + + if (time_change > 0 && accel_speed != AltosRecord.MISSING) + acceleration = (accel_speed - prev_accel_speed) / time_change; + else + acceleration = prev_state.acceleration; + } else { + /* compute accelerometer speed */ + accel_speed = prev_accel_speed + acceleration * time_change; + } } } else { npad = 0; ngps = 0; gps = null; - baro_speed = 0; + gps_sequence = 0; + baro_speed = AltosRecord.MISSING; + accel_speed = AltosRecord.MISSING; + pad_alt = AltosRecord.MISSING; + max_baro_speed = 0; + max_accel_speed = 0; + max_height = 0; + max_acceleration = 0; time_change = 0; } time = tick / 100.0; - if (cur.new_gps && (state == AltosLib.ao_flight_pad || state == AltosLib.ao_flight_idle)) { + if (data.gps != null && data.gps_sequence != gps_sequence && (state < AltosLib.ao_flight_boost)) { /* Track consecutive 'good' gps reports, waiting for 10 of them */ if (data.gps != null && data.gps.locked && data.gps.nsat >= 4) @@ -150,7 +212,7 @@ public class AltosState { /* Average GPS data while on the pad */ if (data.gps != null && data.gps.locked && data.gps.nsat >= 4) { - if (ngps > 1) { + if (ngps > 1 && state == AltosLib.ao_flight_pad) { /* filter pad position */ pad_lat = (pad_lat * 31.0 + data.gps.lat) / 32.0; pad_lon = (pad_lon * 31.0 + data.gps.lon) / 32.0; @@ -162,10 +224,12 @@ public class AltosState { } ngps++; } - } else - pad_alt = ground_altitude; + } else { + if (ngps == 0 && ground_altitude != AltosRecord.MISSING) + pad_alt = ground_altitude; + } - data.new_gps = false; + gps_sequence = data.gps_sequence; gps_waiting = MIN_PAD_SAMPLES - npad; if (gps_waiting < 0) @@ -178,32 +242,29 @@ public class AltosState { boost = (AltosLib.ao_flight_boost == state); /* Only look at accelerometer data under boost */ - if (boost && acceleration > max_acceleration && acceleration != AltosRecord.MISSING) + if (boost && acceleration != AltosRecord.MISSING && (max_acceleration == AltosRecord.MISSING || acceleration > max_acceleration)) max_acceleration = acceleration; - if (boost && speed > max_speed && speed != AltosRecord.MISSING) - max_speed = speed; - if (boost && baro_speed > max_baro_speed && baro_speed != AltosRecord.MISSING) + if (boost && accel_speed != AltosRecord.MISSING && accel_speed > max_accel_speed) + max_accel_speed = accel_speed; + if (boost && baro_speed != AltosRecord.MISSING && baro_speed > max_baro_speed) max_baro_speed = baro_speed; - if (height > max_height && height != AltosRecord.MISSING) + if (height != AltosRecord.MISSING && height > max_height) max_height = height; - if (data.gps != null) { - if (gps == null || !gps.locked || data.gps.locked) - gps = data.gps; - if (ngps > 0 && gps.locked) { - from_pad = new AltosGreatCircle(pad_lat, pad_lon, gps.lat, gps.lon); - } - } elevation = 0; range = -1; - if (ngps > 0) { - gps_height = gps.alt - pad_alt; - if (from_pad != null) { - elevation = Math.atan2(height, from_pad.distance) * 180 / Math.PI; - range = Math.sqrt(height * height + from_pad.distance * from_pad.distance); + gps_height = 0; + if (data.gps != null) { + gps = data.gps; + if (ngps > 0 && gps.locked) { + double h = height; + + if (h == AltosRecord.MISSING) h = 0; + from_pad = new AltosGreatCircle(pad_lat, pad_lon, 0, gps.lat, gps.lon, h); + elevation = from_pad.elevation; + range = from_pad.range; + gps_height = gps.alt - pad_alt; } - } else { - gps_height = 0; } } diff --git a/altoslib/AltosTelemetry.java b/altoslib/AltosTelemetry.java index 15534158..e7322349 100644 --- a/altoslib/AltosTelemetry.java +++ b/altoslib/AltosTelemetry.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; import java.text.*; diff --git a/altoslib/AltosTelemetryIterable.java b/altoslib/AltosTelemetryIterable.java index e95c15e0..57033638 100644 --- a/altoslib/AltosTelemetryIterable.java +++ b/altoslib/AltosTelemetryIterable.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; import java.io.*; import java.util.*; diff --git a/altoslib/AltosTelemetryMap.java b/altoslib/AltosTelemetryMap.java index bc1486d8..7cca98b0 100644 --- a/altoslib/AltosTelemetryMap.java +++ b/altoslib/AltosTelemetryMap.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; import java.text.*; import java.util.HashMap; diff --git a/altoslib/AltosTelemetryReader.java b/altoslib/AltosTelemetryReader.java index 94fa560b..b4293c73 100644 --- a/altoslib/AltosTelemetryReader.java +++ b/altoslib/AltosTelemetryReader.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; import java.text.*; import java.io.*; @@ -107,6 +107,14 @@ public class AltosTelemetryReader extends AltosFlightReader { return log.file(); } + public boolean has_monitor_battery() { + return link.has_monitor_battery(); + } + + public double monitor_battery() { + return link.monitor_battery(); + } + public AltosTelemetryReader (AltosLink in_link) throws IOException, InterruptedException, TimeoutException { link = in_link; diff --git a/altoslib/AltosTelemetryRecord.java b/altoslib/AltosTelemetryRecord.java index 6a8cfd35..fdc3c88e 100644 --- a/altoslib/AltosTelemetryRecord.java +++ b/altoslib/AltosTelemetryRecord.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; import java.text.*; public abstract class AltosTelemetryRecord { @@ -80,25 +80,25 @@ public abstract class AltosTelemetryRecord { r = new AltosTelemetryRecordSensor(bytes, rssi); break; case packet_type_configuration: - r = new AltosTelemetryRecordConfiguration(bytes); + r = new AltosTelemetryRecordConfiguration(bytes, rssi); break; case packet_type_location: - r = new AltosTelemetryRecordLocation(bytes); + r = new AltosTelemetryRecordLocation(bytes, rssi); break; case packet_type_satellite: - r = new AltosTelemetryRecordSatellite(bytes); + r = new AltosTelemetryRecordSatellite(bytes, rssi); break; case packet_type_companion: - r = new AltosTelemetryRecordCompanion(bytes); + r = new AltosTelemetryRecordCompanion(bytes, rssi); break; case packet_type_MM_sensor: r = new AltosTelemetryRecordMegaSensor(bytes, rssi); break; case packet_type_MM_data: - r = new AltosTelemetryRecordMegaData(bytes); + r = new AltosTelemetryRecordMegaData(bytes, rssi); break; default: - r = new AltosTelemetryRecordRaw(bytes); + r = new AltosTelemetryRecordRaw(bytes, rssi); break; } break; diff --git a/altoslib/AltosTelemetryRecordCompanion.java b/altoslib/AltosTelemetryRecordCompanion.java index 6ad17244..2231df13 100644 --- a/altoslib/AltosTelemetryRecordCompanion.java +++ b/altoslib/AltosTelemetryRecordCompanion.java @@ -15,14 +15,14 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; public class AltosTelemetryRecordCompanion extends AltosTelemetryRecordRaw { AltosRecordCompanion companion; - public AltosTelemetryRecordCompanion(int[] in_bytes) { - super(in_bytes); + public AltosTelemetryRecordCompanion(int[] in_bytes, int rssi) { + super(in_bytes, rssi); int off = 0; if (uint8(6) == 0) diff --git a/altoslib/AltosTelemetryRecordConfiguration.java b/altoslib/AltosTelemetryRecordConfiguration.java index 25242edc..47fc3488 100644 --- a/altoslib/AltosTelemetryRecordConfiguration.java +++ b/altoslib/AltosTelemetryRecordConfiguration.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; public class AltosTelemetryRecordConfiguration extends AltosTelemetryRecordRaw { @@ -29,8 +29,8 @@ public class AltosTelemetryRecordConfiguration extends AltosTelemetryRecordRaw { String callsign; String version; - public AltosTelemetryRecordConfiguration(int[] in_bytes) { - super(in_bytes); + public AltosTelemetryRecordConfiguration(int[] in_bytes, int rssi) { + super(in_bytes, rssi); device_type = uint8(5); flight = uint16(6); diff --git a/altoslib/AltosTelemetryRecordGeneral.java b/altoslib/AltosTelemetryRecordGeneral.java index a53280cf..08cd6065 100644 --- a/altoslib/AltosTelemetryRecordGeneral.java +++ b/altoslib/AltosTelemetryRecordGeneral.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; import java.text.*; diff --git a/altoslib/AltosTelemetryRecordLegacy.java b/altoslib/AltosTelemetryRecordLegacy.java index 21176069..f2d3f868 100644 --- a/altoslib/AltosTelemetryRecordLegacy.java +++ b/altoslib/AltosTelemetryRecordLegacy.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; import java.text.*; @@ -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); @@ -267,7 +267,7 @@ public class AltosTelemetryRecordLegacy extends AltosTelemetryRecord { if (map.has(AO_TELEM_GPS_STATE)) { record.gps = new AltosGPS(map); - record.new_gps = true; + record.gps_sequence++; } else record.gps = null; @@ -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; @@ -357,7 +357,7 @@ public class AltosTelemetryRecordLegacy extends AltosTelemetryRecord { } record.gps = new AltosGPS(words, i, record.version); - record.new_gps = true; + record.gps_sequence++; } public AltosTelemetryRecordLegacy(String line) throws ParseException, AltosCRCException { @@ -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; @@ -476,7 +476,7 @@ public class AltosTelemetryRecordLegacy extends AltosTelemetryRecord { if ((gps_flags & (AO_GPS_VALID|AO_GPS_RUNNING)) != 0) { record.gps = new AltosGPS(); - record.new_gps = true; + record.gps_sequence++; record.seen |= AltosRecord.seen_gps_time | AltosRecord.seen_gps_lat | AltosRecord.seen_gps_lon; record.gps.nsat = (gps_flags & AO_GPS_NUM_SAT_MASK); diff --git a/altoslib/AltosTelemetryRecordLocation.java b/altoslib/AltosTelemetryRecordLocation.java index cddb773d..0236d291 100644 --- a/altoslib/AltosTelemetryRecordLocation.java +++ b/altoslib/AltosTelemetryRecordLocation.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; public class AltosTelemetryRecordLocation extends AltosTelemetryRecordRaw { @@ -37,8 +37,8 @@ public class AltosTelemetryRecordLocation extends AltosTelemetryRecordRaw { int climb_rate; int course; - public AltosTelemetryRecordLocation(int[] in_bytes) { - super(in_bytes); + public AltosTelemetryRecordLocation(int[] in_bytes, int rssi) { + super(in_bytes, rssi); flags = uint8(5); altitude = int16(6); @@ -85,7 +85,7 @@ public class AltosTelemetryRecordLocation extends AltosTelemetryRecordRaw { next.gps.hdop = hdop; next.gps.vdop = vdop; next.seen |= AltosRecord.seen_gps_time | AltosRecord.seen_gps_lat | AltosRecord.seen_gps_lon; - next.new_gps = true; + next.gps_sequence++; } return next; diff --git a/altoslib/AltosTelemetryRecordMegaData.java b/altoslib/AltosTelemetryRecordMegaData.java index 8f55d238..a484ef4e 100644 --- a/altoslib/AltosTelemetryRecordMegaData.java +++ b/altoslib/AltosTelemetryRecordMegaData.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; public class AltosTelemetryRecordMegaData extends AltosTelemetryRecordRaw { @@ -35,8 +35,8 @@ public class AltosTelemetryRecordMegaData extends AltosTelemetryRecordRaw { int speed; int height; - public AltosTelemetryRecordMegaData(int[] in_bytes) { - super(in_bytes); + public AltosTelemetryRecordMegaData(int[] in_bytes, int rssi) { + super(in_bytes, rssi); state = int8(5); @@ -83,11 +83,11 @@ 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; + next.seen |= AltosRecord.seen_sensor | AltosRecord.seen_temp_volt; return next; } diff --git a/altoslib/AltosTelemetryRecordMegaSensor.java b/altoslib/AltosTelemetryRecordMegaSensor.java index 93c001de..2a4b17a4 100644 --- a/altoslib/AltosTelemetryRecordMegaSensor.java +++ b/altoslib/AltosTelemetryRecordMegaSensor.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; public class AltosTelemetryRecordMegaSensor extends AltosTelemetryRecordRaw { @@ -35,10 +35,8 @@ public class AltosTelemetryRecordMegaSensor extends AltosTelemetryRecordRaw { int mag_y; int mag_z; - int rssi; - - public AltosTelemetryRecordMegaSensor(int[] in_bytes, int in_rssi) { - super(in_bytes); + public AltosTelemetryRecordMegaSensor(int[] in_bytes, int rssi) { + super(in_bytes, rssi); accel = int16(6); pres = int32(8); @@ -55,8 +53,6 @@ public class AltosTelemetryRecordMegaSensor extends AltosTelemetryRecordRaw { mag_x = int16(26); mag_y = int16(28); mag_z = int16(30); - - rssi = in_rssi; } public AltosRecord update_state(AltosRecord previous) { @@ -85,8 +81,6 @@ public class AltosTelemetryRecordMegaSensor extends AltosTelemetryRecordRaw { next.mag.y = mag_y; next.mag.z = mag_z; - next.rssi = rssi; - next.seen |= AltosRecord.seen_sensor; return next; diff --git a/altoslib/AltosTelemetryRecordRaw.java b/altoslib/AltosTelemetryRecordRaw.java index fbb373d5..f94789bb 100644 --- a/altoslib/AltosTelemetryRecordRaw.java +++ b/altoslib/AltosTelemetryRecordRaw.java @@ -15,13 +15,14 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; public class AltosTelemetryRecordRaw extends AltosTelemetryRecord { int[] bytes; int serial; int tick; int type; + int rssi; long received_time; @@ -53,21 +54,24 @@ public class AltosTelemetryRecordRaw extends AltosTelemetryRecord { return AltosLib.string(bytes, off + 1, l); } - public AltosTelemetryRecordRaw(int[] in_bytes) { + public AltosTelemetryRecordRaw(int[] in_bytes, int in_rssi) { bytes = in_bytes; serial = uint16(0); tick = uint16(2); type = uint8(4); + rssi = in_rssi; } public AltosRecord update_state(AltosRecord previous) { AltosRecord next; - if (previous != null) + + if (previous != null && previous.serial == serial) next = previous.clone(); else - next = new AltosRecord(); + next = new AltosRecordNone(); next.serial = serial; next.tick = tick; + next.rssi = rssi; return next; } diff --git a/altoslib/AltosTelemetryRecordSatellite.java b/altoslib/AltosTelemetryRecordSatellite.java index 2526afb6..9835389b 100644 --- a/altoslib/AltosTelemetryRecordSatellite.java +++ b/altoslib/AltosTelemetryRecordSatellite.java @@ -15,14 +15,14 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; public class AltosTelemetryRecordSatellite extends AltosTelemetryRecordRaw { int channels; AltosGPSSat[] sats; - public AltosTelemetryRecordSatellite(int[] in_bytes) { - super(in_bytes); + public AltosTelemetryRecordSatellite(int[] in_bytes, int rssi) { + super(in_bytes, rssi); channels = uint8(5); if (channels > 12) diff --git a/altoslib/AltosTelemetryRecordSensor.java b/altoslib/AltosTelemetryRecordSensor.java index 319a91b3..e0e92c13 100644 --- a/altoslib/AltosTelemetryRecordSensor.java +++ b/altoslib/AltosTelemetryRecordSensor.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; public class AltosTelemetryRecordSensor extends AltosTelemetryRecordRaw { @@ -36,10 +36,8 @@ public class AltosTelemetryRecordSensor extends AltosTelemetryRecordRaw { int accel_plus_g; int accel_minus_g; - int rssi; - - public AltosTelemetryRecordSensor(int[] in_bytes, int in_rssi) { - super(in_bytes); + public AltosTelemetryRecordSensor(int[] in_bytes, int rssi) { + super(in_bytes, rssi); state = uint8(5); accel = int16(6); @@ -57,8 +55,6 @@ public class AltosTelemetryRecordSensor extends AltosTelemetryRecordRaw { ground_accel = int16(26); accel_plus_g = int16(28); accel_minus_g = int16(30); - - rssi = in_rssi; } public AltosRecord update_state(AltosRecord prev) { @@ -86,9 +82,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) { @@ -101,8 +97,6 @@ public class AltosTelemetryRecordSensor extends AltosTelemetryRecordRaw { next.accel_minus_g = AltosRecord.MISSING; } - next.rssi = rssi; - next.seen |= AltosRecord.seen_sensor | AltosRecord.seen_temp_volt; return next; diff --git a/altoslib/AltosTemperature.java b/altoslib/AltosTemperature.java new file mode 100644 index 00000000..2749eac0 --- /dev/null +++ b/altoslib/AltosTemperature.java @@ -0,0 +1,43 @@ +/* + * Copyright © 2012 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; 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_1; + +public class AltosTemperature extends AltosUnits { + + public double value(double v) { + if (AltosConvert.imperial_units) + return AltosConvert.c_to_f(v); + return v; + } + + public String show_units() { + if (AltosConvert.imperial_units) + return "°F"; + return "°C"; + } + + public String say_units() { + if (AltosConvert.imperial_units) + return "degrees farenheit"; + return "degrees celsius"; + } + + public int show_fraction(int width) { + return width / 3; + } +} diff --git a/altoslib/AltosUnits.java b/altoslib/AltosUnits.java index 47540c61..b8b3254c 100644 --- a/altoslib/AltosUnits.java +++ b/altoslib/AltosUnits.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package org.altusmetrum.altoslib_1; public abstract class AltosUnits { @@ -25,7 +25,7 @@ public abstract class AltosUnits { public abstract String say_units(); - abstract int show_fraction(int width); + public abstract int show_fraction(int width); int say_fraction() { return 0; @@ -43,6 +43,10 @@ public abstract class AltosUnits { return String.format("%%1.%df %s", say_fraction(), say_units()); } + public String graph_format(int width) { + return String.format(String.format("%%%d.%df", width, show_fraction(width)), 0.0); + } + public String show(int width, double v) { return String.format(show_format(width), value(v)); } diff --git a/altoslib/AltosUnitsListener.java b/altoslib/AltosUnitsListener.java new file mode 100644 index 00000000..61a181a4 --- /dev/null +++ b/altoslib/AltosUnitsListener.java @@ -0,0 +1,22 @@ +/* + * Copyright © 2012 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; 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_1; + +public interface AltosUnitsListener { + public void units_changed(boolean imperial_units); +} diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am index a9f810f9..18b028d6 100644 --- a/altoslib/Makefile.am +++ b/altoslib/Makefile.am @@ -2,94 +2,107 @@ AM_JAVACFLAGS=-encoding UTF-8 -Xlint:deprecation JAVAROOT=bin +VERSION=1 + CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH="bin:$(FREETTS)/*:/usr/share/java/*" SRC=. -BIN=bin/org/altusmetrum/AltosLib -AltosLibdir = $(datadir)/java +altoslibdir = $(datadir)/java -AltosLib_JAVA = \ - $(SRC)/AltosLib.java \ - $(SRC)/AltosConfigData.java \ - $(SRC)/AltosConvert.java \ - $(SRC)/AltosCRCException.java \ - $(SRC)/AltosEepromChunk.java \ - $(SRC)/AltosEepromIterable.java \ - $(SRC)/AltosEepromLog.java \ - $(SRC)/AltosEepromMega.java \ - $(SRC)/AltosEepromMegaIterable.java \ - $(SRC)/AltosEepromRecord.java \ - $(SRC)/AltosEepromTeleScience.java \ - $(SRC)/AltosFile.java \ - $(SRC)/AltosFlightReader.java \ - $(SRC)/AltosFrequency.java \ - $(SRC)/AltosGPS.java \ - $(SRC)/AltosGPSQuery.java \ - $(SRC)/AltosGPSSat.java \ - $(SRC)/AltosGreatCircle.java \ - $(SRC)/AltosIdleMonitor.java \ - $(SRC)/AltosIdleMonitorListener.java \ - $(SRC)/AltosIgnite.java \ - $(SRC)/AltosIMU.java \ - $(SRC)/AltosIMUQuery.java \ - $(SRC)/AltosLine.java \ - $(SRC)/AltosLink.java \ - $(SRC)/AltosLog.java \ - $(SRC)/AltosMs5607.java \ - $(SRC)/AltosMs5607Query.java \ - $(SRC)/AltosOrderedRecord.java \ - $(SRC)/AltosOrderedMegaRecord.java \ - $(SRC)/AltosParse.java \ - $(SRC)/AltosPreferences.java \ - $(SRC)/AltosRecordCompanion.java \ - $(SRC)/AltosRecordIterable.java \ - $(SRC)/AltosRecord.java \ - $(SRC)/AltosRecordTM.java \ - $(SRC)/AltosRecordMM.java \ - $(SRC)/AltosReplayReader.java \ - $(SRC)/AltosSensorMM.java \ - $(SRC)/AltosSensorTM.java \ - $(SRC)/AltosState.java \ - $(SRC)/AltosTelemetry.java \ - $(SRC)/AltosTelemetryIterable.java \ - $(SRC)/AltosTelemetryMap.java \ - $(SRC)/AltosTelemetryReader.java \ - $(SRC)/AltosTelemetryRecordCompanion.java \ - $(SRC)/AltosTelemetryRecordConfiguration.java \ - $(SRC)/AltosTelemetryRecordGeneral.java \ - $(SRC)/AltosTelemetryRecord.java \ - $(SRC)/AltosTelemetryRecordLegacy.java \ - $(SRC)/AltosTelemetryRecordLocation.java \ - $(SRC)/AltosTelemetryRecordRaw.java \ - $(SRC)/AltosTelemetryRecordSatellite.java \ - $(SRC)/AltosTelemetryRecordSensor.java \ - $(SRC)/AltosTelemetryRecordMegaSensor.java \ - $(SRC)/AltosTelemetryRecordMegaData.java \ - $(SRC)/AltosMs5607.java \ - $(SRC)/AltosIMU.java \ - $(SRC)/AltosMag.java \ - $(SRC)/AltosUnits.java \ - $(SRC)/AltosDistance.java \ - $(SRC)/AltosHeight.java \ - $(SRC)/AltosSpeed.java \ - $(SRC)/AltosAccel.java +altoslib_JAVA = \ + AltosLib.java \ + AltosConfigData.java \ + AltosConfigValues.java \ + AltosConvert.java \ + AltosCRCException.java \ + AltosDebug.java \ + AltosEepromChunk.java \ + AltosEepromIterable.java \ + AltosEepromLog.java \ + AltosEepromMega.java \ + AltosEepromMegaIterable.java \ + AltosEepromRecord.java \ + AltosEepromTeleScience.java \ + AltosFile.java \ + AltosFlash.java \ + AltosFlashListener.java \ + AltosFlightReader.java \ + AltosFrequency.java \ + AltosGPS.java \ + AltosGPSQuery.java \ + AltosGPSSat.java \ + AltosGreatCircle.java \ + AltosHexfile.java \ + AltosIdleMonitor.java \ + AltosIdleMonitorListener.java \ + AltosIgnite.java \ + AltosIMU.java \ + AltosIMUQuery.java \ + AltosLine.java \ + AltosLink.java \ + AltosListenerState.java \ + AltosLog.java \ + AltosMs5607.java \ + AltosMs5607Query.java \ + AltosOrderedRecord.java \ + AltosOrderedMegaRecord.java \ + AltosParse.java \ + AltosPreferences.java \ + AltosPreferencesBackend.java \ + AltosRecordCompanion.java \ + AltosRecordIterable.java \ + AltosRecord.java \ + AltosRecordNone.java \ + AltosRecordTM.java \ + AltosRecordMM.java \ + AltosReplayReader.java \ + AltosRomconfig.java \ + AltosSensorMM.java \ + AltosSensorTM.java \ + AltosState.java \ + AltosTelemetry.java \ + AltosTelemetryIterable.java \ + AltosTelemetryMap.java \ + AltosTelemetryReader.java \ + AltosTelemetryRecordCompanion.java \ + AltosTelemetryRecordConfiguration.java \ + AltosTelemetryRecordGeneral.java \ + AltosTelemetryRecord.java \ + AltosTelemetryRecordLegacy.java \ + AltosTelemetryRecordLocation.java \ + AltosTelemetryRecordRaw.java \ + AltosTelemetryRecordSatellite.java \ + AltosTelemetryRecordSensor.java \ + AltosTelemetryRecordMegaSensor.java \ + AltosTelemetryRecordMegaData.java \ + AltosUnitsListener.java \ + AltosMs5607.java \ + AltosIMU.java \ + AltosMag.java \ + AltosUnits.java \ + AltosDistance.java \ + AltosHeight.java \ + AltosSpeed.java \ + AltosTemperature.java \ + AltosAccel.java \ + AltosPyro.java -JAR=AltosLib.jar +JAR=altoslib_$(ALTOSLIB_VERSION).jar all-local: $(JAR) clean-local: -rm -rf bin $(JAR) -install-AltosLibJAVA: $(JAR) +install-altoslibJAVA: $(JAR) @$(NORMAL_INSTALL) - test -z "$(AltosLibdir)" || $(MKDIR_P) "$(DESTDIR)$(AltosLibdir)" - echo " $(INSTALL_DATA)" "$<" "'$(DESTDIR)$(AltosLibdir)/$(JAR)"; \ - $(INSTALL_DATA) "$<" "$(DESTDIR)$(AltosLibdir)" + test -z "$(altoslibdir)" || $(MKDIR_P) "$(DESTDIR)$(altoslibdir)" + echo " $(INSTALL_DATA)" "$<" "'$(DESTDIR)$(altoslibdir)/$(JAR)"; \ + $(INSTALL_DATA) "$<" "$(DESTDIR)$(altoslibdir)" bin: mkdir -p bin -$(JAR): classAltosLib.stamp +$(JAR): classaltoslib.stamp jar cf $@ -C bin org |
