src/teledongle-v0.2/teledongle-v0.2-$(VERSION).ihx \
src/teledongle-v3.0/teledongle-v3.0-$(VERSION).ihx \
src/telegps-v1.0/telegps-v1.0-$(VERSION).ihx \
+ src/telegps-v2.0/telegps-v2.0-$(VERSION).ihx \
src/telemega-v1.0/telemega-v1.0-$(VERSION).ihx \
src/telemega-v2.0/telemega-v2.0-$(VERSION).ihx \
src/telemetrum-v1.0/telemetrum-v1.0-$(VERSION).ihx \
--with-fat-dir=/home/bdale/web/altusmetrum/
make && make fat
- this pushes packages for each platform and application
- to web site, including auto-generated mdwn files and
- release notes in html format.
+ - store a stable copy of ARM binaries for production use
- # store a stable copy of ARM binaries for production use
cp src/chaoskey-v1.0/{*.elf,*.ihx} \
src/easymega-v1.0/{*.elf,*.ihx} \
src/easymini-v1.0/{*.elf,*.ihx} \
src/telebt-v4.0/{*.elf,*.ihx} \
src/teledongle-v3.0/{*.elf,*.ihx} \
src/telegps-v1.0/{*.elf,*.ihx} \
+ src/telegps-v2.0/{*.elf,*.ihx} \
src/telemega-v1.0/{*.elf,*.ihx} \
src/telemega-v2.0/{*.elf,*.ihx} \
src/telemetrum-v2.0/{*.elf,*.ihx} \
src/easymini-v1.0/flash-loader/*.elf \
src/easymini-v2.0/flash-loader/{*.elf,*.bin} \
src/telebt-v3.0/flash-loader/*.elf \
- src/telebt-v4.0/flash-loader/*.elf \
+ src/telebt-v4.0/flash-loader/{*.elf,*.bin} \
src/teledongle-v3.0/flash-loader/*.elf \
src/telegps-v1.0/flash-loader/*.elf \
+ src/telegps-v2.0/flash-loader/*.elf \
src/telemega-v1.0/flash-loader/*.elf \
src/telemega-v2.0/flash-loader/*.elf \
src/telemetrum-v2.0/flash-loader/*.elf \
(cd ~/altusmetrumllc ; git add Binaries ; git commit -a)
(cd ~/altusmetrumllc ; git push)
- - copy the relevant release notes .html file from doc/ to
- /home/bdale/web/altusmetrum/AltOS/releases/<rev>
-
- Push new release to web site
make fat-install
(cd doc ; make publish)
- (cd ~/web/altusmetrum/ && git add AltOS/releases
- TeleGPS/releases MicroPeak/releases && git commit -m'Release
- <rev>' && git push origin master)
+ (cd ~/web/altusmetrum/ && \
+ git add */releases && git commit -m'Release <rev>' && \
+ git push origin master)
+
+ - upload the Debian package
- this pushes fresh documents to the web site
+ - clean up
sudo debian/rules clean
git push origin master branch-<version> debian pristine-tar
git push --tags
- push commits and leave the build tree in an uncluttered state
-
Testing before a release
To verify that a build works, the following need to be checked
}
}
+class Tracker implements CharSequence, Comparable {
+ int serial;
+ String call;
+ double frequency;
+
+ String display;
+
+ public Tracker(int serial, String call, double frequency) {
+ if (call == null)
+ call = "none";
+
+ this.serial = serial;
+ this.call = call;
+ this.frequency = frequency;
+ if (frequency == 0.0)
+ display = "Auto";
+ else if (frequency == AltosLib.MISSING) {
+ display = String.format("%-8.8s %6d", call, serial);
+ } else {
+ display = String.format("%-8.8s %7.3f %6d", call, frequency, serial);
+ }
+ }
+
+ public Tracker(AltosState s) {
+ this(s == null ? 0 : s.cal_data().serial,
+ s == null ? null : s.cal_data().callsign,
+ s == null ? 0.0 : s.frequency);
+ }
+
+ /* CharSequence */
+ public char charAt(int index) {
+ return display.charAt(index);
+ }
+
+ public int length() {
+ return display.length();
+ }
+
+ public CharSequence subSequence(int start, int end) throws IndexOutOfBoundsException {
+ return display.subSequence(start, end);
+ }
+
+ public String toString() {
+ return display.toString();
+ }
+
+ /* Comparable */
+ public int compareTo (Object other) {
+ Tracker o = (Tracker) other;
+ if (frequency == 0.0) {
+ if (o.frequency == 0.0)
+ return 0;
+ return -1;
+ }
+ if (o.frequency == 0.0)
+ return 1;
+
+ int a = serial - o.serial;
+ int b = call.compareTo(o.call);
+ int c = (int) Math.signum(frequency - o.frequency);
+
+ if (b != 0)
+ return b;
+ if (c != 0)
+ return c;
+ return a;
+ }
+}
+
public class AltosDroid extends FragmentActivity implements AltosUnitsListener, LocationListener {
// Actions sent to the telemetry server at startup time
private Timer timer;
TelemetryState telemetry_state;
- Integer[] serials;
+ Tracker[] trackers;
+
UsbDevice pending_usb_device;
boolean start_with_usb;
AltosPreferences.register_units_listener(this);
}
- serials = telemetry_state.states.keySet().toArray(new Integer[0]);
- Arrays.sort(serials);
+ int num_trackers = 0;
+ for (AltosState s : telemetry_state.states.values()) {
+ num_trackers++;
+ }
+
+ trackers = new Tracker[num_trackers + 1];
+
+ int n = 0;
+ trackers[n++] = new Tracker(0, "auto", 0.0);
+
+ for (AltosState s : telemetry_state.states.values())
+ trackers[n++] = new Tracker(s);
+
+ Arrays.sort(trackers);
update_title(telemetry_state);
}
if (serial != 0) {
- for (i = 0; i < serials.length; i++)
- if (serials[i] == serial)
+ for (i = 0; i < trackers.length; i++)
+ if (trackers[i].serial == serial)
break;
- if (i == serials.length) {
+ if (i == trackers.length) {
AltosDebug.debug("attempt to select unknown tracker %d\n", serial);
return;
}
void touch_trackers(Integer[] serials) {
AlertDialog.Builder builder_tracker = new AlertDialog.Builder(this);
builder_tracker.setTitle("Select Tracker");
- final String[] trackers = new String[serials.length + 1];
- trackers[0] = "Auto";
- for (int i = 0; i < serials.length; i++)
- trackers[i+1] = String.format("%d", serials[i]);
- builder_tracker.setItems(trackers,
+
+ final Tracker[] my_trackers = new Tracker[serials.length + 1];
+
+ my_trackers[0] = new Tracker(null);
+
+ for (int i = 0; i < serials.length; i++) {
+ AltosState s = telemetry_state.states.get(serials[i]);
+ my_trackers[i+1] = new Tracker(s);
+ }
+ builder_tracker.setItems(my_trackers,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
if (item == 0)
select_tracker(0);
else
- select_tracker(Integer.parseInt(trackers[item]));
+ select_tracker(my_trackers[item].serial);
}
});
AlertDialog alert_tracker = builder_tracker.create();
alert_freq.show();
return true;
case R.id.select_tracker:
- if (serials != null) {
- String[] trackers = new String[serials.length+1];
- trackers[0] = "Auto";
- for (int i = 0; i < serials.length; i++)
- trackers[i+1] = String.format("%d", serials[i]);
+ if (trackers != null) {
AlertDialog.Builder builder_serial = new AlertDialog.Builder(this);
builder_serial.setTitle("Select a tracker");
builder_serial.setItems(trackers,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
+ System.out.printf("select item %d %s\n", item, trackers[item].display);
if (item == 0)
select_tracker(0);
else
- select_tracker(serials[item-1]);
+ select_tracker(trackers[item].serial);
}
});
AlertDialog alert_serial = builder_serial.create();
}
return true;
case R.id.delete_track:
- if (serials != null) {
- String[] trackers = new String[serials.length];
- for (int i = 0; i < serials.length; i++)
- trackers[i] = String.format("%d", serials[i]);
+ if (trackers != null) {
AlertDialog.Builder builder_serial = new AlertDialog.Builder(this);
builder_serial.setTitle("Delete a track");
- builder_serial.setItems(trackers,
+ final Tracker[] my_trackers = new Tracker[trackers.length - 1];
+ for (int i = 0; i < trackers.length - 1; i++)
+ my_trackers[i] = trackers[i+1];
+ builder_serial.setItems(my_trackers,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
- delete_track(serials[item]);
+ delete_track(my_trackers[item].serial);
}
});
AlertDialog alert_serial = builder_serial.create();
while (telemQueue != null) {
try {
AltosTelemetry telem = read();
+ telem.set_frequency(link.frequency);
handler.obtainMessage(TelemetryService.MSG_TELEMETRY, telem).sendToTarget();
} catch (ParseException pp) {
AltosDebug.error("Parse error: %d \"%s\"", pp.getErrorOffset(), pp.getMessage());
--- /dev/null
+/*
+ * Copyright © 2017 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.altusmetrum.altoslib_12;
+
+import java.io.*;
+import java.util.concurrent.*;
+
+public class AltosAccelCal implements Runnable {
+
+ AltosLink link;
+ AltosAccelCalListener listener;
+
+ boolean remote;
+ boolean close_on_exit;
+ double frequency;
+ String callsign;
+
+ Thread accel_thread;
+
+ AltosConfigData config_data;
+
+ public static final int phase_antenna_up = 0;
+ public static final int phase_antenna_down = 1;
+
+ void start_link() throws InterruptedException, TimeoutException {
+ if (remote) {
+ link.set_radio_frequency(frequency);
+ link.set_callsign(callsign);
+ link.start_remote();
+ } else
+ link.flush_input();
+ }
+
+ boolean stop_link() throws InterruptedException, TimeoutException {
+ if (remote)
+ link.stop_remote();
+ return link.reply_abort;
+ }
+
+ 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 abort() throws InterruptedException {
+ while (accel_thread.isAlive()) {
+ accel_thread.interrupt();
+ link.abort_reply();
+ Thread.sleep(100);
+ }
+ accel_thread.join();
+ }
+
+ static private final String press_msg = "press a key...";
+
+ private Semaphore ui_signal_semaphore;
+ private boolean ui_signal_reply;
+
+ public void signal(boolean reply) {
+ System.out.printf("Signal cal semaphore %b\n", reply);
+ ui_signal_reply = reply;
+ ui_signal_semaphore.release();
+ }
+
+ private boolean wait_signal() throws InterruptedException {
+ System.out.printf("\twait for cal signal...\n");
+ ui_signal_semaphore.acquire();
+ System.out.printf("\tgot cal signal %b\n", ui_signal_reply);
+ return ui_signal_reply;
+ }
+
+ private boolean wait_press(int timeout) throws InterruptedException {
+ for (;;) {
+ String line = link.get_reply(timeout);
+ if (line == null) {
+ System.out.printf("get_reply timeout\n");
+ return false;
+ }
+ System.out.printf("got line %s\n", line);
+ if (line.contains(press_msg))
+ return true;
+ if (line.contains("Invalid"))
+ return false;
+ if (line.contains("Syntax"))
+ return false;
+ if (line.contains("Calibrating"))
+ listener.message(this, line);
+ }
+ }
+
+ static final int cal_timeout = 20 * 1000;
+
+ public void run() {
+ System.out.printf("start accel cal procedure\n");
+ try {
+ AltosConfigData new_config = null;
+
+ try {
+ start_link();
+ config_data = link.config_data();
+
+ /* set back to antenna up for calibration */
+ if (config_data.pad_orientation != 0)
+ link.printf("c o 0\n");
+
+ /* Start calibration */
+ try {
+ System.out.printf("*** start cal\n");
+ link.set_match(press_msg);
+ link.printf("c a 0\n");
+ System.out.printf("*** wait press\n");
+ if (!wait_press(cal_timeout))
+ throw new TimeoutException("timeout");
+ System.out.printf("*** set_phase antenna_up\n");
+ listener.set_phase(this, phase_antenna_up);
+ System.out.printf("*** wait_signal\n");
+ if (!wait_signal())
+ throw new InterruptedException("aborted");
+ link.set_match(press_msg);
+ System.out.printf("*** send newline\n");
+ link.printf("\n");
+ System.out.printf("*** wait press\n");
+ if (!wait_press(cal_timeout))
+ throw new TimeoutException("timeout");
+ System.out.printf("***set_phase antenna_down\n");
+ listener.set_phase(this, phase_antenna_down);
+ System.out.printf("*** wait_signal\n");
+ if (!wait_signal())
+ throw new InterruptedException("aborted");
+ System.out.printf("*** send newline and version command\n");
+ link.printf("\nv\n");
+ } catch (TimeoutException e) {
+ throw e;
+ } catch (InterruptedException e) {
+ throw e;
+ }
+ link.set_match(null);
+
+ boolean worked = true;
+ for (;;) {
+ String line = link.get_reply(cal_timeout);
+ if (line == null)
+ throw new TimeoutException();
+ System.out.printf("*** waiting for finish: %s\n", line);
+ if (line.contains("Invalid"))
+ worked = false;
+ if (line.contains("software-version"))
+ break;
+ if (line.contains("Calibrating"))
+ listener.message(this, line);
+ }
+ System.out.printf("*** worked: %b\n", worked);
+ if (worked)
+ new_config = new AltosConfigData(link);
+ } finally {
+ System.out.printf("Restore orientation %d +g %d -g %d\n",
+ config_data.pad_orientation,
+ config_data.accel_cal_plus,
+ config_data.accel_cal_minus);
+ if (config_data.pad_orientation != AltosLib.MISSING && config_data.pad_orientation != 0)
+ link.printf("c o %d\n", config_data.pad_orientation);
+ if (config_data.accel_cal_plus != AltosLib.MISSING && config_data.accel_cal_minus != AltosLib.MISSING)
+ link.printf("c a %d %d\n",
+ config_data.accel_cal_plus, config_data.accel_cal_minus);
+ stop_link();
+ }
+ if (new_config != null) {
+ System.out.printf("*** +1g %d -1g %d\n",
+ new_config.accel_cal_plus,
+ new_config.accel_cal_minus);
+ listener.cal_done(this, new_config.accel_cal_plus, new_config.accel_cal_minus);
+ if (!wait_signal())
+ throw new InterruptedException("aborted");
+ } else
+ listener.error(this, "Calibration failed");
+ } catch (TimeoutException te) {
+ System.out.printf("timeout");
+ listener.error(this, "timeout");
+ } catch (InterruptedException ie) {
+ System.out.printf("interrupted\n");
+ listener.error(this, "interrupted");
+ }
+ }
+
+ public void start() {
+ accel_thread = new Thread(this);
+ listener.set_thread(this, accel_thread);
+ accel_thread.start();
+ }
+
+ public AltosAccelCal(AltosLink link, AltosAccelCalListener listener) {
+ this.link = link;
+ this.listener = listener;
+ ui_signal_semaphore = new Semaphore(0);
+ }
+}
--- /dev/null
+/*
+ * Copyright © 2017 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.altusmetrum.altoslib_12;
+
+import java.io.*;
+import java.util.concurrent.*;
+
+public interface AltosAccelCalListener {
+ public void set_thread(AltosAccelCal cal, Thread thread);
+
+ public void set_phase(AltosAccelCal cal, int phase);
+
+ public void cal_done(AltosAccelCal cal, int plus, int minus);
+
+ public void error(AltosAccelCal cal, String msg);
+
+ public void message(AltosAccelCal cal, String msg);
+}
/* HAS_GYRO */
try {
- if (line.startsWith("IMU call along")) {
+ if (line.startsWith("IMU cal along")) {
String[] bits = line.split("\\s+");
if (bits.length >= 8) {
accel_zero_along = Integer.parseInt(bits[3]);
if (pad_orientation != AltosLib.MISSING)
pad_orientation = source.pad_orientation();
+ if (accel_cal_plus != AltosLib.MISSING)
+ accel_cal_plus = source.accel_cal_plus();
+
+ if (accel_cal_minus != AltosLib.MISSING)
+ accel_cal_minus = source.accel_cal_minus();
+
/* HAS_LOG */
if (flight_log_max != AltosLib.MISSING)
flight_log_max = source.flight_log_max();
dest.set_flight_log_max(flight_log_max);
dest.set_ignite_mode(ignite_mode);
dest.set_pad_orientation(pad_orientation);
+ dest.set_accel_cal(accel_cal_plus, accel_cal_minus);
dest.set_callsign(callsign);
if (npyro != AltosLib.MISSING)
dest.set_pyros(pyros);
link.printf("c e %d\n", radio_enable);
/* HAS_ACCEL */
- /* UI doesn't support accel cal */
if (pad_orientation != AltosLib.MISSING)
link.printf("c o %d\n", pad_orientation);
+ if (accel_cal_plus != AltosLib.MISSING && accel_cal_minus != AltosLib.MISSING)
+ link.printf("c a %d %d\n", accel_cal_plus, accel_cal_minus);
/* HAS_LOG */
if (flight_log_max != 0)
public abstract int pad_orientation();
+ public abstract void set_accel_cal(int accel_cal_plus, int accel_cal_minus);
+
+ public abstract int accel_cal_plus();
+
+ public abstract int accel_cal_minus();
+
+ public abstract void set_dirty();
+
+ public abstract void set_clean();
+
public abstract void set_pyros(AltosPyro[] new_pyros);
public abstract AltosPyro[] pyros() throws AltosConfigDataException;
public double time = AltosLib.MISSING;
public int state = AltosLib.MISSING;
+ public double frequency = AltosLib.MISSING;
public void set_tick(int tick) {
cal_data.set_tick(tick);
cal_data().set_flight(flight);
}
+ public void set_frequency(double frequency) {
+ this.frequency = frequency;
+ }
+
/* Called after all records are captured */
public void finish() {
}
add_times(series, (int) prev.value, prev.time, state.time);
prev = state;
}
- if (prev != null)
- add_times(series, (int) prev.value, prev.time, series.accel_series.last().time);
+ if (prev != null) {
+ AltosTimeValue last_accel = series.accel_series.last();
+ if (last_accel != null)
+ add_times(series, (int) prev.value, prev.time, last_accel.time);
+ }
}
for (int s = 0; s <= AltosLib.ao_flight_invalid; s++) {
has_gps = true;
lat = pad_lat = gps.lat;
lon = pad_lon = gps.lon;
- for (AltosGPSTimeValue gtv : series.gps_series) {
- gps = gtv.gps;
- if (gps.locked && gps.nsat >= 4) {
- lat = gps.lat;
- lon = gps.lon;
+ if (series.gps_series != null) {
+ for (AltosGPSTimeValue gtv : series.gps_series) {
+ gps = gtv.gps;
+ if (gps.locked && gps.nsat >= 4) {
+ lat = gps.lat;
+ lon = gps.lon;
+ }
}
}
-
}
max_height = AltosLib.MISSING;
public LinkedBlockingQueue<AltosLine> reply_queue = new LinkedBlockingQueue<AltosLine>();
public LinkedBlockingQueue<byte[]> binary_queue = new LinkedBlockingQueue<byte[]>();
+ private String match_string = null;
+
public synchronized void add_monitor(LinkedBlockingQueue<AltosLine> q) {
set_monitor(true);
monitors.add(q);
private int len_read = 0;
+ private boolean match_bytes(byte[] bytes, int byte_count, String match) {
+ if (byte_count < match.length())
+ return false;
+ String line = new String(bytes, 0, byte_count, AltosLib.unicode_set);
+ if (line == null)
+ return false;
+ return line.indexOf(match) >= 0;
+ }
+
public void run () {
int c;
byte[] line_bytes = null;
line_count = 0;
len_read = 0;
}
+ if (match_string != null && match_bytes(line_bytes, line_count, match_string)) {
+ match_string = null;
+ add_bytes(line_bytes, line_count);
+ line_count = 0;
+ }
}
}
}
}
}
+ public void set_match(String match) {
+ match_string = match;
+ }
public String get_reply(int timeout) throws InterruptedException {
boolean can_cancel = can_cancel_reply();
}
public AltosState() {
- Thread.dumpStack();
init();
}
/* Mark when we received the packet */
long received_time;
+ /* Mark frequency packet was received on */
+ public double frequency = AltosLib.MISSING;
+
static boolean cksum(int[] bytes) {
int sum = 0x5a;
for (int i = 1; i < bytes.length - 1; i++)
listener.set_serial(serial());
if (listener.state == AltosLib.ao_flight_invalid)
listener.set_state(AltosLib.ao_flight_startup);
+ if (frequency != AltosLib.MISSING)
+ listener.set_frequency(frequency);
listener.set_tick(tick());
listener.set_rssi(rssi(), status());
listener.set_received_time(received_time);
return telem;
}
+ public void set_frequency(double frequency) {
+ this.frequency = frequency;
+ }
+
public AltosTelemetry() {
this.received_time = System.currentTimeMillis();
}
}
public AltosTimeValue first() {
- return values.get(0);
+ if (values.size() > 0)
+ return values.get(0);
+ return null;
}
public AltosTimeValue last() {
- return values.get(values.size() - 1);
+ if (values.size() > 0)
+ return values.get(values.size() - 1);
+ return null;
}
public double average() {
altoslib_JAVA = \
AltosLib.java \
+ AltosAccelCal.java \
+ AltosAccelCalListener.java \
AltosCalData.java \
AltosCompanion.java \
AltosConfigData.java \
if (serial_line != null)
serial_line.close();
}
+ else if (cmd.equals("Accel")) {
+ if (data.pad_orientation != AltosLib.MISSING) {
+ AltosUIAccelCal accel_ui = new AltosUIAccelCal(owner, serial_line, config_ui);
+ if (accel_ui != null)
+ accel_ui.doit();
+ }
+ }
} catch (InterruptedException ie) {
abort();
} catch (TimeoutException te) {
JLabel flight_log_max_label;
JLabel ignite_mode_label;
JLabel pad_orientation_label;
+ JLabel accel_plus_label;
+ JLabel accel_minus_label;
JLabel callsign_label;
JLabel beep_label;
JLabel tracker_motion_label;
JComboBox<String> flight_log_max_value;
JComboBox<String> ignite_mode_value;
JComboBox<String> pad_orientation_value;
+ JTextField accel_plus_value;
+ JTextField accel_minus_value;
JTextField callsign_value;
JComboBox<String> beep_value;
JComboBox<String> tracker_motion_value;
JComboBox<String> tracker_interval_value;
JButton pyro;
+ JButton accel_cal;
JButton save;
JButton reset;
}
void set_pad_orientation_tool_tip() {
- if (pad_orientation_value.isVisible())
+ if (pad_orientation_value.isVisible()) {
pad_orientation_value.setToolTipText("How will the computer be mounted in the airframe");
- else {
+ } else {
if (is_telemetrum())
pad_orientation_value.setToolTipText("Older TeleMetrum firmware must fly antenna forward");
else if (is_telemini() || is_easymini())
}
}
+ void set_accel_tool_tips() {
+ if (accel_plus_value.isVisible()) {
+ accel_plus_value.setToolTipText("Pad acceleration value in flight orientation");
+ accel_minus_value.setToolTipText("Upside-down acceleration value");
+ } else {
+ accel_plus_value.setToolTipText("No accelerometer");
+ accel_minus_value.setToolTipText("No accelerometer");
+ }
+ }
+
void set_beep_tool_tip() {
if (beep_value.isVisible())
beep_value.setToolTipText("What frequency the beeper will sound at");
set_pad_orientation_tool_tip();
row++;
+ /* Accel plus */
+ c = new GridBagConstraints();
+ c.gridx = 0; c.gridy = row;
+ c.gridwidth = 4;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = il;
+ c.ipady = 5;
+ accel_plus_label = new JLabel("Accel Plus:");
+ pane.add(accel_plus_label, c);
+
+ c = new GridBagConstraints();
+ c.gridx = 4; c.gridy = row;
+ c.gridwidth = 4;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.weightx = 1;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = ir;
+ c.ipady = 5;
+ accel_plus_value = new JTextField(10);
+ accel_plus_value.setEditable(true);
+ accel_plus_value.getDocument().addDocumentListener(this);
+ pane.add(accel_plus_value, c);
+ row++;
+
+ /* Accel minus */
+ c = new GridBagConstraints();
+ c.gridx = 0; c.gridy = row;
+ c.gridwidth = 4;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = il;
+ c.ipady = 5;
+ accel_minus_label = new JLabel("Accel Minus:");
+ pane.add(accel_minus_label, c);
+
+ c = new GridBagConstraints();
+ c.gridx = 4; c.gridy = row;
+ c.gridwidth = 4;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.weightx = 1;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = ir;
+ c.ipady = 5;
+ accel_minus_value = new JTextField(10);
+ accel_minus_value.setEditable(true);
+ accel_minus_value.getDocument().addDocumentListener(this);
+ pane.add(accel_minus_value, c);
+ row++;
+ set_accel_tool_tips();
+
/* Beeper */
c = new GridBagConstraints();
c.gridx = 0; c.gridy = row;
pyro.setActionCommand("Pyro");
row++;
+ /* Accel cal */
+ c = new GridBagConstraints();
+ c.gridx = 5; c.gridy = row;
+ c.gridwidth = 5;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = il;
+ c.ipady = 5;
+ accel_cal = new JButton("Calibrate Accelerometer");
+ pane.add(accel_cal, c);
+ accel_cal.addActionListener(this);
+ accel_cal.setActionCommand("Accel");
+ row++;
+
/* Buttons */
c = new GridBagConstraints();
c.gridx = 0; c.gridy = row;
return true;
}
- void set_dirty() {
+ public void set_dirty() {
dirty = true;
save.setEnabled(true);
}
setVisible(false);
dispose();
}
- set_clean();
+ if (cmd.equals("Save") || cmd.equals("Reset"))
+ set_clean();
}
/* ItemListener interface method */
radio_frequency_value.set_product(product);
product_value.setText(product);
set_pad_orientation_tool_tip();
+ set_accel_tool_tips();
set_flight_log_max_tool_tip();
}
}
pad_orientation_value.setVisible(new_pad_orientation != AltosLib.MISSING);
pad_orientation_label.setVisible(new_pad_orientation != AltosLib.MISSING);
+ accel_cal.setVisible(new_pad_orientation != AltosLib.MISSING);
set_pad_orientation_tool_tip();
}
return AltosLib.MISSING;
}
+ public void set_accel_cal(int accel_plus, int accel_minus) {
+ if (accel_plus != AltosLib.MISSING) {
+ accel_plus_value.setText(String.format("%d", accel_plus));
+ accel_minus_value.setText(String.format("%d", accel_minus));
+ }
+ accel_plus_value.setVisible(accel_plus != AltosLib.MISSING);
+ accel_plus_label.setVisible(accel_plus != AltosLib.MISSING);
+ accel_minus_value.setVisible(accel_minus != AltosLib.MISSING);
+ accel_minus_label.setVisible(accel_minus != AltosLib.MISSING);
+
+ set_accel_tool_tips();
+ }
+
+ public int accel_cal_plus() {
+ if (accel_plus_value.isVisible())
+ return Integer.parseInt(accel_plus_value.getText());
+ return AltosLib.MISSING;
+ }
+
+ public int accel_cal_minus() {
+ if (accel_minus_value.isVisible())
+ return Integer.parseInt(accel_minus_value.getText());
+ return AltosLib.MISSING;
+ }
+
public void set_beep(int new_beep) {
if (new_beep != AltosLib.MISSING) {
int new_freq = (int) Math.floor (AltosConvert.beep_value_to_freq(new_beep) + 0.5);
if (flight_series.gps_series != null) {
for (AltosGPSTimeValue gtv : flight_series.gps_series) {
- gtv_last = gtv;
AltosGPS gps = gtv.gps;
if (gps != null &&
gps.locked &&
map = new AltosUIMap();
map.show(gps, (int) flight_series.value_before(AltosFlightSeries.state_name, gtv.time));
this.gps = gps;
+ gtv_last = gtv;
has_gps = true;
}
}
--- /dev/null
+/*
+ * Copyright © 2017 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.altusmetrum.altosuilib_12;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.beans.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import org.altusmetrum.altoslib_12.*;
+
+public class AltosUIAccelCal
+ extends AltosUIDialog
+ implements AltosAccelCalListener, ActionListener
+{
+ Frame owner;
+ AltosLink link;
+ AltosAccelCal cal;
+ AltosConfigValues config_values;
+ Thread thread;
+ Container pane;
+ JTextField message;
+ JButton antenna_up;
+ JButton antenna_down;
+ JButton ok;
+ JButton cancel;
+ boolean success;
+ int accel_plus, accel_minus;
+
+ private void make_visible() {
+ pack();
+ cal.start();
+ setVisible(true);
+ }
+
+ public boolean doit() {
+ success = false;
+ make_visible();
+ return success;
+ }
+
+ public int accel_cal_plus() {
+ if (success)
+ return accel_plus;
+ return AltosLib.MISSING;
+ }
+
+ public int accel_cal_minus() {
+ if (success)
+ return accel_minus;
+ return AltosLib.MISSING;
+ }
+
+ private void setDefaultButton(JButton button) {
+ this.getRootPane().setDefaultButton(button);
+ }
+
+ /* AltosAccelCalListener interface */
+ public void set_thread(AltosAccelCal cal, Thread thread) {
+ this.thread = thread;
+ }
+
+ public void set_phase(AltosAccelCal cal, final int phase) {
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ switch (phase) {
+ case AltosAccelCal.phase_antenna_up:
+ message.setText("Orient antenna upwards and click on Antenna Up");
+ antenna_up.setEnabled(true);
+ setDefaultButton(antenna_up);
+ antenna_down.setEnabled(false);
+ ok.setEnabled(false);
+ break;
+ case AltosAccelCal.phase_antenna_down:
+ message.setText("Orient antenna downwards and click on Antenna Down");
+ antenna_up.setEnabled(false);
+ antenna_down.setEnabled(true);
+ setDefaultButton(antenna_down);
+ ok.setEnabled(false);
+ break;
+ }
+ }
+ });
+ }
+
+ public void cal_done(AltosAccelCal cal, int plus, int minus) {
+ accel_plus = plus;
+ accel_minus = minus;
+ success = true;
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ message.setText(String.format("Calibration succeeded, plus %d minus %d, press OK to continue", accel_plus, accel_minus));
+ antenna_up.setEnabled(false);
+ antenna_down.setEnabled(false);
+ ok.setEnabled(true);
+ setDefaultButton(ok);
+ }
+ });
+ }
+
+ public void message(AltosAccelCal cal, final String msg) {
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ message.setText(msg);
+ }
+ });
+ }
+
+ public void error(AltosAccelCal cal, String msg) {
+ message(cal, msg);
+ }
+
+ /* ActionListener interface */
+ public void actionPerformed(ActionEvent e) {
+ String cmd = e.getActionCommand();
+
+ if ("up".equals(cmd)) {
+ cal.signal(true);
+ antenna_up.setEnabled(false);
+ } else if ("down".equals(cmd)) {
+ cal.signal(true);
+ antenna_down.setEnabled(false);
+ this.setDefaultButton(antenna_down);
+ } else if ("ok".equals(cmd)) {
+ cal.signal(true);
+ this.setVisible(false);
+ if (success) {
+ config_values.set_accel_cal(accel_plus, accel_minus);
+ config_values.set_dirty();
+ }
+ try {
+ cal.abort();
+ } catch (InterruptedException ie) {
+ }
+ } else if ("cancel".equals(cmd)) {
+ cal.signal(false);
+ this.setVisible(false);
+ try {
+ cal.abort();
+ } catch (InterruptedException ie) {
+ }
+ }
+ }
+ public AltosUIAccelCal(Frame owner, AltosLink link, AltosConfigValues config_values) {
+ super(owner, "Calibrate Accelerometer", true);
+
+ this.owner = owner;
+ this.link = link;
+ this.config_values = config_values;
+
+ pane = getContentPane();
+ pane.setLayout(new GridBagLayout());
+
+ GridBagConstraints c = new GridBagConstraints();
+ c.insets = new Insets(4,4,4,4);
+
+ int x = 0;
+ int y = 0;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.anchor = GridBagConstraints.WEST;
+ c.gridx = x;
+ c.gridy = y;
+ c.gridwidth = 4;
+ c.gridheight = 1;
+ c.weightx = 0;
+ c.weighty = 0;
+ message = new JTextField(64);
+ pane.add(message, c);
+
+ y++; x = 0;
+
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.WEST;
+ c.gridx = x;
+ c.gridy = y;
+ c.gridwidth = 1;
+ c.gridheight = 1;
+ c.weightx = 0;
+ c.weighty = 0;
+ antenna_up = new JButton("Antenna Up");
+ antenna_up.setActionCommand("up");
+ antenna_up.setEnabled(false);
+ antenna_up.addActionListener(this);
+ pane.add(antenna_up, c);
+
+ x++;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.WEST;
+ c.gridx = x;
+ c.gridy = y;
+ c.gridwidth = 1;
+ c.gridheight = 1;
+ c.weightx = 0;
+ c.weighty = 0;
+ antenna_down = new JButton("Antenna Down");
+ antenna_down.setActionCommand("down");
+ antenna_down.setEnabled(false);
+ antenna_down.addActionListener(this);
+ pane.add(antenna_down, c);
+
+ x++;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.WEST;
+ c.gridx = x;
+ c.gridy = y;
+ c.gridwidth = 1;
+ c.gridheight = 1;
+ c.weightx = 0;
+ c.weighty = 0;
+ ok = new JButton("OK");
+ ok.setActionCommand("ok");
+ ok.setEnabled(false);
+ ok.addActionListener(this);
+ pane.add(ok, c);
+
+ x++;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.WEST;
+ c.gridx = x;
+ c.gridy = y;
+ c.gridwidth = 1;
+ c.gridheight = 1;
+ c.weightx = 0;
+ c.weighty = 0;
+ cancel = new JButton("Cancel");
+ cancel.setActionCommand("cancel");
+ cancel.setEnabled(true);
+ cancel.addActionListener(this);
+ pane.add(cancel, c);
+
+ cal = new AltosAccelCal(this.link, this);
+ }
+}
AltosDevice.java \
AltosDeviceDialog.java \
AltosPositionListener.java \
+ AltosUIAccelCal.java \
AltosUIConfigure.java \
AltosUIAxis.java \
AltosUIDataMissing.java \
+++ /dev/null
-#!/bin/sh
-
-VERSION=1.0
-PRODUCT=TeleGPS
-BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
-
-echo "$PRODUCT-v$VERSION Test Program"
-echo "Copyright 2014 by Bdale Garbee. Released under GPL v2"
-echo
-echo "Expectations:"
-echo "\t$PRODUCT v$VERSION powered from USB"
-echo
-
-ret=1
-ao-list | while read product serial dev; do
- case "$product" in
- "$PRODUCT-v$VERSION")
-
- echo "Testing $product $serial $dev"
-
- FLASHSIZE=2097152
-
- echo "Testing flash"
- ../ao-tools/ao-test-flash/ao-test-flash --tty="$dev" "$FLASHSIZE"
-
- case $? in
- 0)
- ;;
- *)
- echo "failed"
- exit 1
- esac
-
- echo "Testing GPS"
- ../ao-tools/ao-test-gps/ao-test-gps --tty="$dev"
-
- case $? in
- 0)
- ;;
- *)
- echo "failed"
- exit 1
- esac
-
- echo "$PRODUCT-v$VERSION" serial "$serial" passed functional tests
- ret=0
- ;;
- *)
- echo "Skipping $product $serial $dev"
- ;;
- esac
-done
--- /dev/null
+#!/bin/sh
+
+VERSION=1.0
+PRODUCT=TeleGPS
+BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+
+echo "$PRODUCT-v$VERSION Test Program"
+echo "Copyright 2014 by Bdale Garbee. Released under GPL v2"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION powered from USB"
+echo
+
+ret=1
+ao-list | while read product serial dev; do
+ case "$product" in
+ "$PRODUCT-v$VERSION")
+
+ echo "Testing $product $serial $dev"
+
+ FLASHSIZE=2097152
+
+ echo "Testing flash"
+ ../ao-tools/ao-test-flash/ao-test-flash --tty="$dev" "$FLASHSIZE"
+
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "failed"
+ exit 1
+ esac
+
+ echo "Testing GPS"
+ ../ao-tools/ao-test-gps/ao-test-gps --tty="$dev"
+
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "failed"
+ exit 1
+ esac
+
+ echo "$PRODUCT-v$VERSION" serial "$serial" passed functional tests
+ ret=0
+ ;;
+ *)
+ echo "Skipping $product $serial $dev"
+ ;;
+ esac
+done
--- /dev/null
+#!/bin/sh
+
+VERSION=2.0
+PRODUCT=TeleGPS
+BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+
+echo "$PRODUCT-v$VERSION Test Program"
+echo "Copyright 2014 by Bdale Garbee. Released under GPL v2"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION powered from USB"
+echo
+
+ret=1
+ao-list | while read product serial dev; do
+ case "$product" in
+ "$PRODUCT-v$VERSION")
+
+ echo "Testing $product $serial $dev"
+
+ FLASHSIZE=2097152
+
+ echo "Testing flash"
+ ../ao-tools/ao-test-flash/ao-test-flash --tty="$dev" "$FLASHSIZE"
+
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "failed"
+ exit 1
+ esac
+
+ echo "Testing GPS"
+ ../ao-tools/ao-test-gps/ao-test-gps --tty="$dev"
+
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "failed"
+ exit 1
+ esac
+
+ echo "$PRODUCT-v$VERSION" serial "$serial" passed functional tests
+ ret=0
+ ;;
+ *)
+ echo "Skipping $product $serial $dev"
+ ;;
+ esac
+done
fi
echo -n "checking BTLE functionality... "
-btdev=`sudo timeout -s SIGINT 5s hcitool lescan | awk -F \- '/TeleBT/ { print $2 }'`
+btdev=`sudo timeout -s SIGINT 5s hcitool lescan | awk -F \- '/TeleBT/ { print $2 }' | head -n 1`
if [ "$btdev" = "$SERIAL" ]; then
echo "working!"
else
#!/bin/sh
-if [ -x ../ao-tools/ao-flash/ao-flash-lpc ]; then
- FLASH_LPC=../ao-tools/ao-flash/ao-flash-lpc
-elif [ -x /usr/bin/ao-flash-lpc ]; then
- FLASH_LPC=/usr/bin/ao-flash-lpc
+if [ -x /usr/bin/dfu-util ]; then
+ DFU_UTIL=/usr/bin/dfu-util
else
- echo "Can't find ao-flash-lpc! Aborting."
- exit 1
+ echo "Can't find dfu-util! Aborting."
+ exit 1
fi
if [ -x /usr/bin/ao-usbload ]; then
fi
PRODUCT=TeleGPS
-VERSION=1.0
-BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
-echo $FILE
+VERSION=2.0
+REPO=~/altusmetrumllc/Binaries
+
+#BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+#echo $FILE
echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
-echo "Copyright 2014 by Bdale Garbee. Released under GPL v2"
+echo "Copyright 2017 by Bdale Garbee. Released under GPL v3+"
echo
echo "Expectations:"
-echo "\t$PRODUCT v$VERSION powered from USB"
-echo "\t\twith ST-Link-V2 cabled to debug header"
+echo "\t$PRODUCT v$VERSION powered from / attached to USB on this computer"
echo
case $# in
#
# Use released versions of everything
#
-FLASH_FILE=~/altusmetrumllc/Binaries/loaders/telegps-v1.0-altos-flash-*.elf
-ALTOS_FILE=~/altusmetrumllc/Binaries/telegps-v1.0-*.elf
-
-echo $FLASH_LPC $FLASH_FILE
+FLASH_FILE=$REPO/loaders/telegps-v2.0-altos-flash-*.bin
+ALTOS_FILE=$REPO/telegps-v2.0-*.elf
-$FLASH_LPC $FLASH_FILE || exit 1
+$DFU_UTIL -a 0 -s 0x08000000:leave -D $FLASH_FILE || exit 1
sleep 2
-echo $USBLOAD $ALTOS_FILE
-
$USBLOAD --serial=$SERIAL $ALTOS_FILE || exit 1
-sleep 2
+sleep 3
-dev=`ao-list | awk '/TeleGPS-v'"$VERSION"'/ { print $3; exit(0); }'`
+dev=`ao-list | awk '/'"$PRODUCT"'-v'"$VERSION"'/ { print $3; exit(0); }'`
case "$dev" in
/dev/tty*)
- echo "TeleGPS found on $dev"
+ echo "$PRODUCT found on $dev"
;;
*)
- echo 'No TeleGPS-v'"$VERSION"' found'
+ echo 'No '"$PRODUCT"'-v'"$VERSION"' found'
exit 1
;;
esac
SERIAL=$SERIAL ./cal-freq $dev
-./test-telegps
+./test-telegps-v2
exit $?
--- /dev/null
+#!/bin/sh
+
+if [ -x ../ao-tools/ao-flash/ao-flash-lpc ]; then
+ FLASH_LPC=../ao-tools/ao-flash/ao-flash-lpc
+elif [ -x /usr/bin/ao-flash-lpc ]; then
+ FLASH_LPC=/usr/bin/ao-flash-lpc
+else
+ echo "Can't find ao-flash-lpc! Aborting."
+ exit 1
+fi
+
+if [ -x /usr/bin/ao-usbload ]; then
+ USBLOAD=/usr/bin/ao-usbload
+else
+ echo "Can't find ao-usbload! Aborting."
+ exit 1
+fi
+
+PRODUCT=TeleGPS
+VERSION=1.0
+BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+echo $FILE
+
+echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2014 by Bdale Garbee. Released under GPL v2"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION powered from USB"
+echo "\t\twith ST-Link-V2 cabled to debug header"
+echo
+
+case $# in
+ 1)
+ SERIAL="$1"
+ echo "$PRODUCT-$VERSION serial number: $SERIAL"
+ ;;
+ 0)
+ echo -n "$PRODUCT-$VERSION serial number: "
+ read SERIAL
+ ;;
+ *)
+ echo "Usage: $0 <serial-number>" 1>&2
+ exit 1;
+ ;;
+esac
+
+#
+# Use released versions of everything
+#
+FLASH_FILE=~/altusmetrumllc/Binaries/loaders/telegps-v1.0-altos-flash-*.elf
+ALTOS_FILE=~/altusmetrumllc/Binaries/telegps-v1.0-*.elf
+
+echo $FLASH_LPC $FLASH_FILE
+
+$FLASH_LPC $FLASH_FILE || exit 1
+
+sleep 2
+
+echo $USBLOAD $ALTOS_FILE
+
+$USBLOAD --serial=$SERIAL $ALTOS_FILE || exit 1
+
+sleep 2
+
+dev=`ao-list | awk '/TeleGPS-v'"$VERSION"'/ { print $3; exit(0); }'`
+
+case "$dev" in
+/dev/tty*)
+ echo "TeleGPS found on $dev"
+ ;;
+*)
+ echo 'No TeleGPS-v'"$VERSION"' found'
+ exit 1
+ ;;
+esac
+
+SERIAL=$SERIAL ./cal-freq $dev
+
+./test-telegps-v1
+
+exit $?
bin_PROGRAMS=ao-chaosread
-AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+AM_CFLAGS=$(LIBUSB_CFLAGS) -Wall -Wextra
ao_chaosread_LDADD=$(LIBUSB_LIBS)
goto out;
}
- ret = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, device_serial, match_len + 1);
+ ret = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, (unsigned char *) device_serial, match_len + 1);
if (ret < 0) {
fprintf(stderr, "failed to get serial number: %s\n", libusb_strerror(ret));
int ret;
ssize_t num;
libusb_device **list;
- libusb_device *device = NULL;
int d;
ck = calloc(sizeof (struct chaoskey), 1);
free(ck);
}
-void
-chaoskey_transfer_callback(struct libusb_transfer *transfer)
-{
- struct chaoskey *ck = transfer->user_data;
-}
-
#define ENDPOINT 0x86
int
}
len -= transferred;
buf += transferred;
+ total += transferred;
}
+ return total;
}
static const struct option options[] = {
int i;
for (i = 0; i < got / 2; i++)
putchar((buf[i] >> 1 & 0xff));
- } else
- write(1, buf, got);
+ } else {
+ int i;
+ int ret;
+ for (i = 0; i < got; i += ret) {
+ ret = write(1, ((char *) buf) + i, got - i);
+ if (ret <= 0) {
+ perror("write");
+ exit(1);
+ }
+ }
+ }
length -= got;
}
exit(0);
dnl Process this file with autoconf to create configure.
AC_PREREQ(2.57)
-AC_INIT([altos], 1.8.1)
-ANDROID_VERSION=15
+AC_INIT([altos], 1.8.2)
+ANDROID_VERSION=16
AC_CONFIG_SRCDIR([src/kernel/ao.h])
AM_INIT_AUTOMAKE([foreign dist-bzip2])
AM_MAINTAINER_MODE
-RELEASE_DATE=2017-08-27
+RELEASE_DATE=2017-09-18
AC_SUBST(RELEASE_DATE)
VERSION_DASH=`echo $VERSION | sed 's/\./-/g'`
#
RELNOTES_INC=\
+ release-notes-1.8.2.inc \
release-notes-1.8.1.inc \
release-notes-1.8.inc \
release-notes-1.7.inc \
</legalnotice>
<revhistory>
<?dbhtml filename="altusmetrum-revhistory.html"?>
+ <revision>
+ <revnumber>1.8.2</revnumber>
+ <date>18 Sep 2017</date>
+ <revremark>
+ Support TeleGPS v2.0 hardware. Add accelerometer recalibration
+ UI.
+ </revremark>
+ </revision>
<revision>
<revnumber>1.8.1</revnumber>
<date>27 Aug 2017</date>
in the log.
endif::telegps[]
+ifdef::telemega,easymega,telemetrum[]
+
+ ==== Calibrate Accelerometer
+
+ This opens a separate window to recalibrate the
+ accelerometers. Follow the instructions, orienting the
+ flight computer with the antenna end, or end opposite
+ the screw terminals, in the case of EasyMega, first up
+ and then down.
+
+ When the calibration is complete, return to the
+ Configure Altimeter window and save the new
+ calibration values.
+
+endif::telemega,easymega,telemetrum[]
+
ifdef::telemega,easymega[]
==== Configure Pyro Channels
--- /dev/null
+= Release Notes for Version 1.8.2
+:toc!:
+:doctype: article
+
+ Version 1.8.2 includes support for TeleGPS version 2.0 along
+ with accelerometer recalibration support in AltosUI.
+
+ 1.8.2 also contains a couple of minor fixes for AltosUI when
+ analyzing saved data files.
+
+ == AltOS
+
+ AltOS New Features
+
+ * Support for TeleGPS version 2.0 hardware.
+
+ == AltosUI and TeleGPS Applications
+
+ AltosUI and TeleGPS New Features
+
+ * Support for TeleGPS version 2.0.
+
+ * Accelerometer re-calibration user interface.
+
+ AltosUI and TeleGPS Bug Fixes
+
+ * Prevent some crashes when reading older saved flight data
+ for graphing or KML export.
[appendix]
== Release Notes
+ :leveloffset: 2
+ include::release-notes-1.8.2.raw[]
+
+ <<<<
:leveloffset: 2
include::release-notes-1.8.1.raw[]
ifdef::radio[disabled, and the radio goes into transmit-only mode.]
ifndef::radio[disabled.]
The only way to get out of this
- mode is to power the flight computer down.
+ mode is to power the flight computer down. See below for how to get the flight
+ computer to come up in Flight/Pad mode at power on.
Idle::
The flight computer is ready to communicate over USB
ifdef::radio[and in packet mode over the radio.]
You can configure
the flight computer, download data or display
- the current state.
+ the current state. See below for how to get the flight
+ computer to come up in Idle mode at power on.
ifdef::telemetrum,easymega,telemega[]
For flight computers with accelerometers (TeleMetrum,
megadongle-v0.1 megadongle-v0.1/flash-loader \
telegps-v0.3 telegps-v0.3/flash-loader \
telegps-v1.0 telegps-v1.0/flash-loader \
+ telegps-v2.0 telegps-v2.0/flash-loader \
telelco-v0.2 telelco-v0.2/flash-loader \
telelco-v0.3 telelco-v0.3/flash-loader \
telescience-v0.2 telescience-v0.2/flash-loader \
ao_crc_reset();
- ao_delay(TRNG_ENABLE_DELAY);
-
for (s = 0; s < AO_TRNG_START_WAIT; s++) {
- if (ao_trng_get_cooked(buffer[0]))
+ int i;
+ uint16_t min, max;
+ uint16_t buf[AO_USB_IN_SIZE>>1];
+
+ ao_trng_get_raw(buf);
+ min = max = buf[0];
+ for (i = 1; i < (AO_USB_IN_SIZE>>1); i++) {
+ uint16_t v = buf[i];
+ if (v < min) min = v;
+ if (v > max) max = v;
+ }
+ /* Wait for at least 10 bits of range */
+ if ((uint16_t) (max - min) >= 1024)
break;
ao_delay(AO_MS_TO_TICKS(10));
}
case ao_pyro_state_greater_or_equal:
if (ao_flight_state >= pyro->state_greater_or_equal)
continue;
- DBG("state %d >= %d\n", ao_flight_state, pyro->state_less);
+ DBG("state %d < %d\n", ao_flight_state, pyro->state_greater_or_equal);
break;
default:
#define IS_FLASH_LOADER 0
#define HAS_BEEP 0
-#define AO_HSE 32000000
+#define AO_HSE 16000000
#define AO_RCC_CFGR_PLLMUL STM_RCC_CFGR_PLLMUL_3
-#define AO_RCC_CFGR2_PLLDIV STM_RCC_CFGR2_PREDIV_2
+#define AO_RCC_CFGR2_PLLDIV STM_RCC_CFGR2_PREDIV_1
#define AO_PLLMUL 3
-#define AO_PLLDIV 2
+#define AO_PLLDIV 1
/* HCLK = 48MHz */
#define AO_AHB_PRESCALER 1
#define HAS_USB 1
#define AO_USB_DIRECTIO 0
#define AO_PA11_PA12_RMP 1
+#define HAS_USB_CONNECT 1
+#define AO_USB_CONNECT_PORT (&stm_gpiob)
+#define AO_USB_CONNECT_PIN 3
#define IS_FLASH_LOADER 0
#define HAS_SERIAL_2 1
#define SERIAL_2_PA2_PA3 1
#define USE_SERIAL_2_STDIN 0
+#define USE_SERIAL_2_FLOW 0
+#define USE_SERIAL_2_SW_FLOW 0
#define ao_gps_getchar ao_serial2_getchar
#define ao_gps_putchar ao_serial2_putchar
ao_aprs_test ao_micropeak_test ao_fat_test ao_aes_test ao_int64_test \
ao_ms5607_convert_test ao_quaternion_test ao_lisp_test
-INCS=ao_kalman.h ao_ms5607.h ao_log.h ao_data.h altitude-pa.h altitude.h ao_quaternion.h
+INCS=ao_kalman.h ao_ms5607.h ao_log.h ao_data.h altitude-pa.h altitude.h ao_quaternion.h ao_eeprom_read.h
+TEST_SRC=ao_flight_test.c
+TEST_SRC_ALL=ao_flight_test.c ao_eeprom_read.c ao_eeprom_read_old.c
+TEST_LIB=-ljson-c
KALMAN=make-kalman
install:
-ao_flight_test: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h $(INCS)
- cc $(CFLAGS) -o $@ $<
+ao_flight_test: $(TEST_SRC_ALL) ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h $(INCS)
+ cc $(CFLAGS) -o $@ $(TEST_SRC) $(TEST_LIB)
-ao_flight_test_noisy_accel: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c $(INCS)
- cc -DNOISY_ACCEL=1 $(CFLAGS) -o $@ $<
+ao_flight_test_noisy_accel: $(TEST_SRC_ALL) ao_host.h ao_flight.c ao_sample.c ao_kalman.c $(INCS)
+ cc -DNOISY_ACCEL=1 $(CFLAGS) -o $@ $(TEST_SRC) $(TEST_LIB)
-ao_flight_test_baro: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c $(INCS)
- cc $(CFLAGS) -o $@ -DHAS_ACCEL=0 ao_flight_test.c
+ao_flight_test_baro: $(TEST_SRC_ALL) ao_host.h ao_flight.c ao_sample.c ao_kalman.c $(INCS)
+ cc $(CFLAGS) -o $@ -DHAS_ACCEL=0 $(TEST_SRC) $(TEST_LIB)
-ao_flight_test_accel: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c $(INCS)
- cc $(CFLAGS) -o $@ -DFORCE_ACCEL=1 ao_flight_test.c
+ao_flight_test_accel: $(TEST_SRC_ALL) ao_host.h ao_flight.c ao_sample.c ao_kalman.c $(INCS)
+ cc $(CFLAGS) -o $@ -DFORCE_ACCEL=1 $(TEST_SRC) $(TEST_LIB)
-ao_flight_test_mm: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c ao_pyro.c ao_pyro.h $(INCS)
- cc -DTELEMEGA=1 $(CFLAGS) -o $@ $< -lm
+ao_flight_test_mm: $(TEST_SRC_ALL) ao_host.h ao_flight.c ao_sample.c ao_kalman.c ao_pyro.c ao_pyro.h $(INCS)
+ cc -DTELEMEGA=1 $(CFLAGS) -o $@ $(TEST_SRC) $(TEST_LIB) -lm
-ao_flight_test_metrum: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c ao_pyro.c ao_pyro.h $(INCS)
- cc -DTELEMETRUM_V2=1 $(CFLAGS) -o $@ $< -lm
+ao_flight_test_metrum: $(TEST_SRC_ALL) ao_host.h ao_flight.c ao_sample.c ao_kalman.c ao_pyro.c ao_pyro.h $(INCS)
+ cc -DTELEMETRUM_V2=1 $(CFLAGS) -o $@ $(TEST_SRC) $(TEST_LIB) -lm
-ao_flight_test_mini: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c ao_pyro.c ao_pyro.h $(INCS)
- cc -DEASYMINI=1 -DHAS_ACCEL=0 $(CFLAGS) -o $@ $< -lm
+ao_flight_test_mini: $(TEST_SRC_ALL) ao_host.h ao_flight.c ao_sample.c ao_kalman.c ao_pyro.c ao_pyro.h $(INCS)
+ cc -DEASYMINI=1 -DHAS_ACCEL=0 $(CFLAGS) -o $@ $(TEST_SRC) $(TEST_LIB) -lm
ao_gps_test: ao_gps_test.c ao_gps_sirf.c ao_gps_print.c ao_host.h
cc $(CFLAGS) -o $@ $<
--- /dev/null
+/*
+ * Copyright © 2017 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include "ao_eeprom_read.h"
+#include <json-c/json.h>
+#include <string.h>
+#include <errno.h>
+
+static struct json_object *
+ao_eeprom_read_config(FILE *file)
+{
+ char line[1024];
+ struct json_tokener *tok;
+ struct json_object *obj = NULL;
+ enum json_tokener_error err;
+
+ tok = json_tokener_new();
+ if (!tok)
+ goto fail_tok;
+
+ for (;;) {
+ if (fgets(line, sizeof(line), file) == NULL)
+ goto fail_read;
+ obj = json_tokener_parse_ex(tok, line, strlen(line));
+ err = json_tokener_get_error(tok);
+ if (err == json_tokener_success)
+ break;
+ if (err != json_tokener_continue)
+ goto fail_read;
+ }
+ json_tokener_free(tok);
+ return obj;
+fail_read:
+ json_tokener_free(tok);
+fail_tok:
+ return NULL;
+}
+
+static int
+ao_eeprom_read_byte(FILE *file)
+{
+ int byte;
+ if (fscanf(file, "%x", &byte) != 1)
+ return EOF;
+ return byte;
+}
+
+static int
+ao_eeprom_read_data(FILE *file, struct ao_eeprom *eeprom)
+{
+ uint8_t *data = NULL, *ndata;
+ int len = 0;
+ int size = 0;
+ int byte;
+
+ data = malloc(size = 64);
+ if (!data)
+ goto fail_alloc;
+ while ((byte = ao_eeprom_read_byte(file)) != EOF) {
+ if (len == size) {
+ ndata = realloc(data, size *= 2);
+ if (!ndata)
+ goto fail_realloc;
+ data = ndata;
+ }
+ data[len++] = (uint8_t) byte;
+ }
+ eeprom->data = data;
+ eeprom->len = len;
+ return 1;
+fail_realloc:
+ free(data);
+fail_alloc:
+ return 0;
+}
+
+static int
+ao_json_get_int(struct json_object *obj, const char *key, int def)
+{
+ struct json_object *value;
+ int i;
+
+ if (!json_object_object_get_ex(obj, key, &value))
+ return def;
+ errno = 0;
+ i = (int) json_object_get_int(value);
+ if (errno != 0)
+ return def;
+ return i;
+}
+
+static const char *
+ao_json_get_string(struct json_object *obj, const char *key, const char *def)
+{
+ struct json_object *value;
+ const char *str;
+
+ if (!json_object_object_get_ex(obj, key, &value))
+ return def;
+ errno = 0;
+ str = json_object_get_string(value);
+ if (errno)
+ return def;
+ if (!str)
+ return def;
+ return str;
+}
+
+#if AO_PYRO_NUM
+static int
+ao_eeprom_get_pyro(struct ao_config *config, struct json_object *obj)
+{
+ struct json_object *pyros;
+ struct json_object *pyro;
+ int i, p;
+
+ if (!json_object_object_get_ex(obj, "pyros", &pyros))
+ return 1;
+
+ if (json_object_get_type(pyros) != json_type_array)
+ return 0;
+
+ for (i = 0; i < json_object_array_length(pyros); i++) {
+ pyro = json_object_array_get_idx(pyros, i);
+ if (pyro) {
+ p = ao_json_get_int(pyro, "channel", -1);
+ if (0 <= p && p < AO_PYRO_NUM) {
+ config->pyro[p].flags = ao_json_get_int(pyro, "flags", 0);
+ config->pyro[p].accel_less = ao_json_get_int(pyro, "accel_less", 0);
+ config->pyro[p].accel_greater = ao_json_get_int(pyro, "accel_greater", 0);
+ config->pyro[p].speed_less = ao_json_get_int(pyro, "speed_less", 0);
+ config->pyro[p].speed_greater = ao_json_get_int(pyro, "speed_greater", 0);
+ config->pyro[p].height_less = ao_json_get_int(pyro, "height_less", 0);
+ config->pyro[p].height_greater = ao_json_get_int(pyro, "height_greater", 0);
+ config->pyro[p].orient_less = ao_json_get_int(pyro, "orient_less", 0);
+ config->pyro[p].orient_greater = ao_json_get_int(pyro, "orient_greater", 0);
+ config->pyro[p].time_less = ao_json_get_int(pyro, "time_less", 0);
+ config->pyro[p].time_greater = ao_json_get_int(pyro, "time_greater", 0);
+ config->pyro[p].delay = ao_json_get_int(pyro, "delay", 0);
+ config->pyro[p].state_less = ao_json_get_int(pyro, "state_less", 0);
+ config->pyro[p].state_greater_or_equal = ao_json_get_int(pyro, "state_greater_or_equal", 0);
+ config->pyro[p].motor = ao_json_get_int(pyro, "motor", 0);
+ }
+ }
+ }
+ return 1;
+}
+#endif
+
+static int
+ao_eeprom_get_ms5607(struct ao_ms5607_prom *ms5607_prom, struct json_object *obj)
+{
+ struct json_object *ms5607;
+
+ if (!json_object_object_get_ex(obj, "ms5607", &ms5607))
+ return 1;
+
+ if (json_object_get_type(ms5607) != json_type_object)
+ return 0;
+
+ ms5607_prom->reserved = ao_json_get_int(ms5607, "reserved", 0);
+ ms5607_prom->sens = ao_json_get_int(ms5607, "sens", 0);
+ ms5607_prom->off = ao_json_get_int(ms5607, "off", 0);
+ ms5607_prom->tcs = ao_json_get_int(ms5607, "tcs", 0);
+ ms5607_prom->tco = ao_json_get_int(ms5607, "tco", 0);
+ ms5607_prom->tref = ao_json_get_int(ms5607, "tref", 0);
+ ms5607_prom->tempsens = ao_json_get_int(ms5607, "tempsens", 0);
+ ms5607_prom->crc = ao_json_get_int(ms5607, "crc", 0);
+ return 1;
+}
+
+static int
+ao_eeprom_get_config(struct ao_eeprom *ao_eeprom, struct json_object *obj)
+{
+ struct ao_config *config = &ao_eeprom->config;
+ const char *s;
+
+ if (json_object_get_type(obj) != json_type_object)
+ return 0;
+
+ ao_eeprom->log_format = ao_json_get_int(obj, "log_format", 0);
+ ao_eeprom->serial_number = ao_json_get_int(obj, "serial", 0);
+
+ config->major = ao_json_get_int(obj, "config_major", 0);
+ config->minor = ao_json_get_int(obj, "config_minor", 0);
+ if (config->major == 0 || config->minor == 0)
+ return 0;
+
+ config->main_deploy = ao_json_get_int(obj, "main_deploy", 250);
+ config->accel_plus_g = ao_json_get_int(obj, "accel_cal_plus", 0);
+
+ s = ao_json_get_string(obj, "callsign", "N0CALL");
+ strncpy(config->callsign, s, sizeof(config->callsign));
+
+ config->apogee_delay = ao_json_get_int(obj, "apogee_delay", 0);
+ config->accel_minus_g = ao_json_get_int(obj, "accel_cal_minus", 0);
+ config->radio_cal = ao_json_get_int(obj, "radio_calibration", 0);
+ config->flight_log_max = ao_json_get_int(obj, "flight_log_max", 0);
+ config->ignite_mode = ao_json_get_int(obj, "ignite_mode", 0);
+ config->pad_orientation = ao_json_get_int(obj, "pad_orientation", 0);
+ config->radio_setting = ao_json_get_int(obj, "radio_setting", 0);
+ config->radio_enable = ao_json_get_int(obj, "radio_enable", 1);
+ config->frequency = ao_json_get_int(obj, "frequency", 434550);
+ config->apogee_lockout = ao_json_get_int(obj, "apogee_lockout", 0);
+#if AO_PYRO_NUM
+ if (!ao_eeprom_get_pyro(config, obj))
+ return 0;
+#endif
+ config->ignite_mode = ao_json_get_int(obj, "ignite_mode", 0);
+ config->ignite_mode = ao_json_get_int(obj, "ignite_mode", 0);
+ config->ignite_mode = ao_json_get_int(obj, "ignite_mode", 0);
+ config->ignite_mode = ao_json_get_int(obj, "ignite_mode", 0);
+ config->ignite_mode = ao_json_get_int(obj, "ignite_mode", 0);
+ config->ignite_mode = ao_json_get_int(obj, "ignite_mode", 0);
+
+ if (!ao_eeprom_get_ms5607(&ao_eeprom->ms5607_prom, obj))
+ return 0;
+
+ return 1;
+}
+
+struct ao_eeprom *
+ao_eeprom_read(FILE *file)
+{
+ struct ao_eeprom *ao_eeprom;
+ struct json_object *obj;
+ int ret;
+
+ ao_eeprom = calloc(1, sizeof (struct ao_eeprom));
+ if (!ao_eeprom)
+ goto fail_ao_eeprom;
+
+ obj = ao_eeprom_read_config(file);
+ if (!obj)
+ goto fail_config;
+
+ ret = ao_eeprom_get_config(ao_eeprom, obj);
+ json_object_put(obj);
+ if (!ret)
+ goto fail_config;
+
+ if (!ao_eeprom_read_data(file, ao_eeprom))
+ goto fail_data;
+
+ return ao_eeprom;
+fail_data:
+fail_config:
+ free(ao_eeprom);
+fail_ao_eeprom:
+ return NULL;
+}
--- /dev/null
+/*
+ * Copyright © 2017 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef _AO_EEPROM_READ_H_
+#define _AO_EEPROM_READ_H_
+
+#define __pdata
+#define __data
+#define __xdata
+#define __code
+#define __reentrant
+
+#include <stdint.h>
+#include <stdio.h>
+#include <ao_telemetry.h>
+#include <ao_config.h>
+#include <ao_ms5607.h>
+#include <ao_log.h>
+
+struct ao_eeprom {
+ struct ao_config config;
+ struct ao_ms5607_prom ms5607_prom;
+ int log_format;
+ uint16_t serial_number;
+ uint8_t *data;
+ uint32_t len;
+ uint32_t size;
+};
+
+struct ao_eeprom *ao_eeprom_read(FILE *file);
+
+struct ao_eeprom *ao_eeprom_read_old(FILE *file);
+
+void ao_eeprom_free_data(struct ao_eeprom *ao_eeprom);
+
+#endif /* _AO_EEPROM_READ_H_ */
--- /dev/null
+/*
+ * Copyright © 2017 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.
+ */
+
+#include "ao_eeprom_read.h"
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+static int
+ao_eeprom_add_u8(struct ao_eeprom *ao_eeprom, uint8_t byte)
+{
+ if (ao_eeprom->len == ao_eeprom->size) {
+ uint32_t nsize = ao_eeprom->size * 2;
+ uint8_t *ndata = realloc(ao_eeprom->data, nsize);
+ if (!ndata)
+ return 0;
+ ao_eeprom->data = ndata;
+ ao_eeprom->size = nsize;
+ }
+ ao_eeprom->data[ao_eeprom->len++] = byte;
+ return 1;
+}
+
+static int
+ao_eeprom_add_u16(struct ao_eeprom *ao_eeprom, uint16_t u16)
+{
+ if (!ao_eeprom_add_u8(ao_eeprom, u16 & 0xff))
+ return 0;
+
+ return ao_eeprom_add_u8(ao_eeprom, u16 >> 8);
+}
+
+struct ao_eeprom *
+ao_eeprom_read_old(FILE *file)
+{
+ struct ao_eeprom *ao_eeprom;
+ char line[1024];
+ char *l;
+
+ ao_eeprom = calloc(1, sizeof (struct ao_eeprom));
+ if (!ao_eeprom)
+ return NULL;
+
+ ao_eeprom->log_format = -1;
+ ao_eeprom->size = 64;
+ ao_eeprom->data = malloc(ao_eeprom->size);
+ if (!ao_eeprom->data) {
+ free(ao_eeprom);
+ return NULL;
+ }
+ while (fgets(line, sizeof(line), file) != NULL) {
+ int nword;
+ char *words[64];
+ char *saveptr;
+ l = line;
+ for (nword = 0; nword < 64; nword++) {
+ words[nword] = strtok_r(l, " \t\n", &saveptr);
+ l = NULL;
+ if (words[nword] == NULL)
+ break;
+ }
+ if (((ao_eeprom->log_format == AO_LOG_FORMAT_TELEMEGA_OLD || ao_eeprom->log_format == AO_LOG_FORMAT_TELEMEGA) && nword == 30 && strlen(words[0]) == 1) ||
+ ((ao_eeprom->log_format == AO_LOG_FORMAT_EASYMINI1 || ao_eeprom->log_format == AO_LOG_FORMAT_EASYMINI2) && nword == 14 && strlen(words[0]) == 1) ||
+ (ao_eeprom->log_format == AO_LOG_FORMAT_TELEMETRUM && nword == 14 && strlen(words[0]) == 1))
+ {
+ int i;
+ uint8_t type;
+ uint16_t tick;
+
+ type = words[0][0];
+ tick = strtoul(words[1], NULL, 16);
+ ao_eeprom_add_u8(ao_eeprom, type);
+ ao_eeprom_add_u8(ao_eeprom, 0); /* checksum */
+ ao_eeprom_add_u16(ao_eeprom, tick);
+ for (i = 2; i < nword; i++)
+ ao_eeprom_add_u8(ao_eeprom, strtoul(words[i], NULL, 16));
+ }
+ else if (nword == 4 && strlen(words[0]) == 1) {
+ uint8_t type;
+ uint16_t tick, a, b;
+ type = words[0][0];
+ tick = strtoul(words[1], NULL, 16);
+ a = strtoul(words[2], NULL, 16);
+ b = strtoul(words[3], NULL, 16);
+ if (type == 'P')
+ type = 'A';
+ ao_eeprom_add_u8(ao_eeprom, type);
+ ao_eeprom_add_u8(ao_eeprom, 0); /* checksum */
+ ao_eeprom_add_u16(ao_eeprom, tick);
+ ao_eeprom_add_u16(ao_eeprom, a);
+ ao_eeprom_add_u16(ao_eeprom, b);
+ }
+ else if (nword == 3 && strcmp(words[0], "ms5607") == 0) {
+ if (strcmp(words[1], "reserved:") == 0)
+ ao_eeprom->ms5607_prom.reserved = strtoul(words[2], NULL, 10);
+ else if (strcmp(words[1], "sens:") == 0)
+ ao_eeprom->ms5607_prom.sens = strtoul(words[2], NULL, 10);
+ else if (strcmp(words[1], "off:") == 0)
+ ao_eeprom->ms5607_prom.off = strtoul(words[2], NULL, 10);
+ else if (strcmp(words[1], "tcs:") == 0)
+ ao_eeprom->ms5607_prom.tcs = strtoul(words[2], NULL, 10);
+ else if (strcmp(words[1], "tco:") == 0)
+ ao_eeprom->ms5607_prom.tco = strtoul(words[2], NULL, 10);
+ else if (strcmp(words[1], "tref:") == 0)
+ ao_eeprom->ms5607_prom.tref = strtoul(words[2], NULL, 10);
+ else if (strcmp(words[1], "tempsens:") == 0)
+ ao_eeprom->ms5607_prom.tempsens = strtoul(words[2], NULL, 10);
+ else if (strcmp(words[1], "crc:") == 0)
+ ao_eeprom->ms5607_prom.crc = strtoul(words[2], NULL, 10);
+ continue;
+ }
+#if AO_NUM_PYRO
+ else if (nword >= 3 && strcmp(words[0], "Pyro") == 0) {
+ int p = strtoul(words[1], NULL, 10);
+ int i, j;
+ struct ao_pyro *pyro = &ao_eeprom->config.pyro[p];
+
+ for (i = 2; i < nword; i++) {
+ for (j = 0; j < NUM_PYRO_VALUES; j++)
+ if (!strcmp (words[i], ao_pyro_values[j].name))
+ break;
+ if (j == NUM_PYRO_VALUES)
+ continue;
+ pyro->flags |= ao_pyro_values[j].flag;
+ if (ao_pyro_values[j].offset != NO_VALUE && i + 1 < nword) {
+ int16_t val = strtoul(words[++i], NULL, 10);
+ printf("pyro %d condition %s value %d\n", p, words[i-1], val);
+ *((int16_t *) ((char *) pyro + ao_pyro_values[j].offset)) = val;
+ }
+ }
+ }
+#endif
+ else if (nword == 2 && strcmp(words[0], "log-format") == 0) {
+ ao_eeprom->log_format = strtoul(words[1], NULL, 10);
+ } else if (nword == 2 && strcmp(words[0], "serial-number") == 0) {
+ ao_eeprom->serial_number = strtoul(words[1], NULL, 10);
+ } else if (nword >= 6 && strcmp(words[0], "Accel") == 0) {
+ ao_eeprom->config.accel_plus_g = atoi(words[3]);
+ ao_eeprom->config.accel_minus_g = atoi(words[5]);
+#if HAS_GYRO
+ } else if (nword >= 8 && strcmp(words[0], "IMU") == 0) {
+ ao_eeprom->config.accel_zero_along = atoi(words[3]);
+ ao_eeprom->config.accel_zero_across = atoi(words[5]);
+ ao_eeprom->config.accel_zero_through = atoi(words[7]);
+#endif
+ } else if (nword >= 4 && strcmp(words[0], "Main") == 0) {
+ ao_eeprom->config.main_deploy = atoi(words[2]);
+ } else if (nword >= 3 && strcmp(words[0], "Apogee") == 0 &&
+ strcmp(words[1], "lockout:") == 0) {
+ ao_eeprom->config.apogee_lockout = atoi(words[2]);
+ } else if (nword >= 3 && strcmp(words[0], "Pad") == 0 &&
+ strcmp(words[1], "orientation:") == 0) {
+ ao_eeprom->config.pad_orientation = atoi(words[2]);
+ }
+ }
+ return ao_eeprom;
+}
+
double dist, bearing;
if (!ao_gps_count)
return 0;
-
+
cc_great_circle(ao_gps_first.latitude / 1e7,
ao_gps_first.longitude / 1e7,
ao_gps_static.latitude / 1e7,
int ao_flight_debug;
+struct ao_eeprom *eeprom;
+uint32_t eeprom_offset;
+
FILE *emulator_in;
char *emulator_app;
char *emulator_name;
#include <ao_ms5607.h>
struct ao_ms5607_prom ao_ms5607_prom;
#include "ao_ms5607_convert.c"
+#if TELEMEGA
#define AO_PYRO_NUM 4
#include <ao_pyro.h>
+#endif
#else
#include "ao_convert.c"
#endif
#include <ao_config.h>
#include <ao_fake_flight.h>
+#include <ao_eeprom_read.h>
+#include <ao_log.h>
#define ao_config_get()
#include "ao_pyro.c"
#endif
+#include "ao_eeprom_read.c"
+#include "ao_eeprom_read_old.c"
#define to_double(f) ((f) / 65536.0)
static int ao_records_read = 0;
static int ao_eof_read = 0;
+#if !EASYMINI
static int ao_flight_ground_accel;
+#endif
static int ao_flight_started = 0;
static int ao_test_max_height;
static double ao_test_max_height_time;
static int landed_set;
static double landed_time;
static double landed_height;
+#if AO_PYRO_NUM
+static uint16_t pyros_fired;
+#endif
#if HAS_MPU6000
static struct ao_mpu6000_sample ao_ground_mpu6000;
#endif
+#if HAS_ACCEL
+int ao_error_h_sq_avg;
+#endif
+
void
ao_test_exit(void)
{
ao_quaternion_normalize(&ao_mag, &ao_mag);
ao_quaternion_rotate(&ao_mag_rot, &ao_mag, &ao_rotation);
-
+
float ao_dot;
int ao_mag_angle;
ao_sleep(void *wchan)
{
if (wchan == &ao_data_head) {
- char type = 0;
- uint16_t tick = 0;
- uint16_t a = 0, b = 0;
- uint8_t bytes[1024];
- union ao_telemetry_all telem;
- char line[1024];
- char *saveptr;
- char *l;
- char *words[64];
- int nword;
-
#if TELEMEGA
if (ao_flight_state >= ao_flight_boost && ao_flight_state < ao_flight_landed)
ao_pyro_check();
return;
}
- if (!fgets(line, sizeof (line), emulator_in)) {
- if (++ao_eof_read >= 1000) {
- if (!ao_summary)
- printf ("no more data, exiting simulation\n");
- ao_test_exit();
- }
- ao_data_static.tick += 10;
- ao_insert();
- return;
- }
- l = line;
- for (nword = 0; nword < 64; nword++) {
- words[nword] = strtok_r(l, " \t\n", &saveptr);
- l = NULL;
- if (words[nword] == NULL)
- break;
- }
+ if (eeprom) {
#if TELEMEGA
- if ((log_format == AO_LOG_FORMAT_TELEMEGA_OLD || log_format == AO_LOG_FORMAT_TELEMEGA) && nword == 30 && strlen(words[0]) == 1) {
- int i;
- struct ao_ms5607_value value;
-
- type = words[0][0];
- tick = strtoul(words[1], NULL, 16);
-// printf ("%c %04x", type, tick);
- for (i = 2; i < nword; i++) {
- bytes[i - 2] = strtoul(words[i], NULL, 16);
-// printf(" %02x", bytes[i-2]);
- }
-// printf ("\n");
- switch (type) {
- case 'F':
- ao_flight_number = uint16(bytes, 0);
- ao_flight_ground_accel = int16(bytes, 2);
- ao_flight_started = 1;
- ao_ground_pres = int32(bytes, 4);
- ao_ground_height = ao_pa_to_altitude(ao_ground_pres);
- ao_ground_accel_along = int16(bytes, 8);
- ao_ground_accel_across = int16(bytes, 10);
- ao_ground_accel_through = int16(bytes, 12);
- ao_ground_roll = int16(bytes, 14);
- ao_ground_pitch = int16(bytes, 16);
- ao_ground_yaw = int16(bytes, 18);
- ao_ground_mpu6000.accel_x = ao_ground_accel_across;
- ao_ground_mpu6000.accel_y = ao_ground_accel_along;
- ao_ground_mpu6000.accel_z = ao_ground_accel_through;
- ao_ground_mpu6000.gyro_x = ao_ground_pitch >> 9;
- ao_ground_mpu6000.gyro_y = ao_ground_roll >> 9;
- ao_ground_mpu6000.gyro_z = ao_ground_yaw >> 9;
- break;
- case 'A':
- ao_data_static.tick = tick;
- ao_data_static.ms5607_raw.pres = int32(bytes, 0);
- ao_data_static.ms5607_raw.temp = int32(bytes, 4);
- ao_ms5607_convert(&ao_data_static.ms5607_raw, &value);
- ao_data_static.mpu6000.accel_x = int16(bytes, 8);
- ao_data_static.mpu6000.accel_y = int16(bytes, 10);
- ao_data_static.mpu6000.accel_z = int16(bytes, 12);
- ao_data_static.mpu6000.gyro_x = int16(bytes, 14);
- ao_data_static.mpu6000.gyro_y = int16(bytes, 16);
- ao_data_static.mpu6000.gyro_z = int16(bytes, 18);
- ao_data_static.hmc5883.x = int16(bytes, 20);
- ao_data_static.hmc5883.y = int16(bytes, 22);
- ao_data_static.hmc5883.z = int16(bytes, 24);
-#if HAS_MMA655X
- ao_data_static.mma655x = int16(bytes, 26);
- if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP)
- ao_data_static.mma655x = ao_data_accel_invert(ao_data_static.mma655x);
+ struct ao_log_mega *log_mega;
#endif
- ao_records_read++;
- ao_insert();
- return;
- case 'G':
- ao_gps_prev = ao_gps_static;
- ao_gps_static.tick = tick;
- ao_gps_static.latitude = int32(bytes, 0);
- ao_gps_static.longitude = int32(bytes, 4);
- {
- int32_t altitude = int32(bytes, 8);
- AO_TELEMETRY_LOCATION_SET_ALTITUDE(&ao_gps_static, altitude);
- }
- ao_gps_static.flags = bytes[13];
- if (!ao_gps_count)
- ao_gps_first = ao_gps_static;
- ao_gps_count++;
- break;
- }
- continue;
- } else if (nword == 3 && strcmp(words[0], "ms5607") == 0) {
- if (strcmp(words[1], "reserved:") == 0)
- ao_ms5607_prom.reserved = strtoul(words[2], NULL, 10);
- else if (strcmp(words[1], "sens:") == 0)
- ao_ms5607_prom.sens = strtoul(words[2], NULL, 10);
- else if (strcmp(words[1], "off:") == 0)
- ao_ms5607_prom.off = strtoul(words[2], NULL, 10);
- else if (strcmp(words[1], "tcs:") == 0)
- ao_ms5607_prom.tcs = strtoul(words[2], NULL, 10);
- else if (strcmp(words[1], "tco:") == 0)
- ao_ms5607_prom.tco = strtoul(words[2], NULL, 10);
- else if (strcmp(words[1], "tref:") == 0)
- ao_ms5607_prom.tref = strtoul(words[2], NULL, 10);
- else if (strcmp(words[1], "tempsens:") == 0)
- ao_ms5607_prom.tempsens = strtoul(words[2], NULL, 10);
- else if (strcmp(words[1], "crc:") == 0)
- ao_ms5607_prom.crc = strtoul(words[2], NULL, 10);
- continue;
- } else if (nword >= 3 && strcmp(words[0], "Pyro") == 0) {
- int p = strtoul(words[1], NULL, 10);
- int i, j;
- struct ao_pyro *pyro = &ao_config.pyro[p];
-
- for (i = 2; i < nword; i++) {
- for (j = 0; j < NUM_PYRO_VALUES; j++)
- if (!strcmp (words[i], ao_pyro_values[j].name))
- break;
- if (j == NUM_PYRO_VALUES)
- continue;
- pyro->flags |= ao_pyro_values[j].flag;
- if (ao_pyro_values[j].offset != NO_VALUE && i + 1 < nword) {
- int16_t val = strtoul(words[++i], NULL, 10);
- printf("pyro %d condition %s value %d\n", p, words[i-1], val);
- *((int16_t *) ((char *) pyro + ao_pyro_values[j].offset)) = val;
- }
- }
- }
+#if TELEMETRUM_V2
+ struct ao_log_metrum *log_metrum;
#endif
#if EASYMINI
- if ((log_format == AO_LOG_FORMAT_EASYMINI1 || log_format == AO_LOG_FORMAT_EASYMINI2) && nword == 14 && strlen(words[0]) == 1) {
- int i;
- struct ao_ms5607_value value;
-
- type = words[0][0];
- tick = strtoul(words[1], NULL, 16);
-// printf ("%c %04x", type, tick);
- for (i = 2; i < nword; i++) {
- bytes[i - 2] = strtoul(words[i], NULL, 16);
-// printf(" %02x", bytes[i-2]);
- }
-// printf ("\n");
- switch (type) {
- case 'F':
- ao_flight_started = 1;
- ao_flight_number = uint16(bytes, 0);
- ao_ground_pres = uint32(bytes, 4);
- ao_ground_height = ao_pa_to_altitude(ao_ground_pres);
-#if 0
- printf("ground pres %d height %d\n", ao_ground_pres, ao_ground_height);
- printf("sens %d off %d tcs %d tco %d tref %d tempsens %d crc %d\n",
- ao_ms5607_prom.sens,
- ao_ms5607_prom.off,
- ao_ms5607_prom.tcs,
- ao_ms5607_prom.tco,
- ao_ms5607_prom.tref,
- ao_ms5607_prom.tempsens,
- ao_ms5607_prom.crc);
+ struct ao_log_mini *log_mini;
#endif
- break;
- case 'A':
- ao_data_static.tick = tick;
- ao_data_static.ms5607_raw.pres = int24(bytes, 0);
- ao_data_static.ms5607_raw.temp = int24(bytes, 3);
-#if 0
- printf("raw pres %d temp %d\n",
- ao_data_static.ms5607_raw.pres,
- ao_data_static.ms5607_raw.temp);
+#if TELEMETRUM_V1
+ struct ao_log_record *log_record;
#endif
- ao_ms5607_convert(&ao_data_static.ms5607_raw, &value);
-// printf("pres %d height %d\n", value.pres, ao_pa_to_altitude(value.pres));
- ao_records_read++;
+
+ if (eeprom_offset >= eeprom->len) {
+ if (++ao_eof_read >= 1000)
+ if (!ao_summary)
+ printf ("no more data, exiting simulation\n");
+ ao_test_exit();
+ ao_data_static.tick += 10;
ao_insert();
return;
}
- continue;
- } else if (nword == 3 && strcmp(words[0], "ms5607") == 0) {
- if (strcmp(words[1], "reserved:") == 0)
- ao_ms5607_prom.reserved = strtoul(words[2], NULL, 10);
- else if (strcmp(words[1], "sens:") == 0)
- ao_ms5607_prom.sens = strtoul(words[2], NULL, 10);
- else if (strcmp(words[1], "off:") == 0)
- ao_ms5607_prom.off = strtoul(words[2], NULL, 10);
- else if (strcmp(words[1], "tcs:") == 0)
- ao_ms5607_prom.tcs = strtoul(words[2], NULL, 10);
- else if (strcmp(words[1], "tco:") == 0)
- ao_ms5607_prom.tco = strtoul(words[2], NULL, 10);
- else if (strcmp(words[1], "tref:") == 0)
- ao_ms5607_prom.tref = strtoul(words[2], NULL, 10);
- else if (strcmp(words[1], "tempsens:") == 0)
- ao_ms5607_prom.tempsens = strtoul(words[2], NULL, 10);
- else if (strcmp(words[1], "crc:") == 0)
- ao_ms5607_prom.crc = strtoul(words[2], NULL, 10);
- continue;
- }
+ switch (eeprom->log_format) {
+#if TELEMEGA
+ case AO_LOG_FORMAT_TELEMEGA_OLD:
+ case AO_LOG_FORMAT_TELEMEGA:
+ log_mega = (struct ao_log_mega *) &eeprom->data[eeprom_offset];
+ eeprom_offset += sizeof (*log_mega);
+ switch (log_mega->type) {
+ case AO_LOG_FLIGHT:
+ ao_flight_number = log_mega->u.flight.flight;
+ ao_flight_ground_accel = log_mega->u.flight.ground_accel;
+ ao_flight_started = 1;
+ ao_ground_pres = log_mega->u.flight.ground_pres;
+ ao_ground_height = ao_pa_to_altitude(ao_ground_pres);
+ ao_ground_accel_along = log_mega->u.flight.ground_accel_along;
+ ao_ground_accel_across = log_mega->u.flight.ground_accel_across;
+ ao_ground_accel_through = log_mega->u.flight.ground_accel_through;
+ ao_ground_roll = log_mega->u.flight.ground_roll;
+ ao_ground_pitch = log_mega->u.flight.ground_pitch;
+ ao_ground_yaw = log_mega->u.flight.ground_yaw;
+ ao_ground_mpu6000.accel_x = ao_ground_accel_across;
+ ao_ground_mpu6000.accel_y = ao_ground_accel_along;
+ ao_ground_mpu6000.accel_z = ao_ground_accel_through;
+ ao_ground_mpu6000.gyro_x = ao_ground_pitch >> 9;
+ ao_ground_mpu6000.gyro_y = ao_ground_roll >> 9;
+ ao_ground_mpu6000.gyro_z = ao_ground_yaw >> 9;
+ break;
+ case AO_LOG_STATE:
+ break;
+ case AO_LOG_SENSOR:
+ ao_data_static.tick = log_mega->tick;
+ ao_data_static.ms5607_raw.pres = log_mega->u.sensor.pres;
+ ao_data_static.ms5607_raw.temp = log_mega->u.sensor.temp;
+ ao_data_static.mpu6000.accel_x = log_mega->u.sensor.accel_x;
+ ao_data_static.mpu6000.accel_y = log_mega->u.sensor.accel_y;
+ ao_data_static.mpu6000.accel_z = log_mega->u.sensor.accel_z;
+ ao_data_static.mpu6000.gyro_x = log_mega->u.sensor.gyro_x;
+ ao_data_static.mpu6000.gyro_y = log_mega->u.sensor.gyro_y;
+ ao_data_static.mpu6000.gyro_z = log_mega->u.sensor.gyro_z;
+ ao_data_static.hmc5883.x = log_mega->u.sensor.mag_x;
+ ao_data_static.hmc5883.y = log_mega->u.sensor.mag_y;
+ ao_data_static.hmc5883.z = log_mega->u.sensor.mag_z;
+ ao_data_static.mma655x = log_mega->u.sensor.accel;
+ if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP)
+ ao_data_static.mma655x = ao_data_accel_invert(ao_data_static.mma655x);
+ ao_records_read++;
+ ao_insert();
+ return;
+ case AO_LOG_TEMP_VOLT:
+ if (pyros_fired != log_mega->u.volt.pyro) {
+ printf("pyro changed %x -> %x\n", pyros_fired, log_mega->u.volt.pyro);
+ pyros_fired = log_mega->u.volt.pyro;
+ }
+ break;
+ case AO_LOG_GPS_TIME:
+ ao_gps_prev = ao_gps_static;
+ ao_gps_static.tick = log_mega->tick;
+ ao_gps_static.latitude = log_mega->u.gps.latitude;
+ ao_gps_static.longitude = log_mega->u.gps.longitude;
+ {
+ int16_t altitude_low = log_mega->u.gps.altitude_low;
+ int16_t altitude_high = log_mega->u.gps.altitude_high;
+ int32_t altitude = altitude_low | ((int32_t) altitude_high << 16);
+
+ AO_TELEMETRY_LOCATION_SET_ALTITUDE(&ao_gps_static, altitude);
+ }
+ ao_gps_static.flags = log_mega->u.gps.flags;
+ if (!ao_gps_count)
+ ao_gps_first = ao_gps_static;
+ ao_gps_count++;
+ break;
+ case AO_LOG_GPS_SAT:
+ break;
+ }
+ break;
#endif
#if TELEMETRUM_V2
- if (log_format == AO_LOG_FORMAT_TELEMETRUM && nword == 14 && strlen(words[0]) == 1) {
- int i;
- struct ao_ms5607_value value;
-
- type = words[0][0];
- tick = strtoul(words[1], NULL, 16);
-// printf ("%c %04x", type, tick);
- for (i = 2; i < nword; i++) {
- bytes[i - 2] = strtoul(words[i], NULL, 16);
-// printf(" %02x", bytes[i-2]);
- }
-// printf ("\n");
- switch (type) {
- case 'F':
- ao_flight_number = uint16(bytes, 0);
- ao_flight_ground_accel = int16(bytes, 2);
- ao_flight_started = 1;
- ao_ground_pres = int32(bytes, 4);
- ao_ground_height = ao_pa_to_altitude(ao_ground_pres);
+ case AO_LOG_FORMAT_TELEMETRUM:
+ log_metrum = (struct ao_log_metrum *) &eeprom->data[eeprom_offset];
+ eeprom_offset += sizeof (*log_metrum);
+ switch (log_metrum->type) {
+ case AO_LOG_FLIGHT:
+ ao_flight_started = 1;
+ ao_flight_number = log_metrum->u.flight.flight;
+ ao_flight_ground_accel = log_metrum->u.flight.ground_accel;
+ ao_ground_pres = log_metrum->u.flight.ground_pres;
+ ao_ground_height = ao_pa_to_altitude(ao_ground_pres);
+ break;
+ case AO_LOG_SENSOR:
+ ao_data_static.tick = log_metrum->tick;
+ ao_data_static.ms5607_raw.pres = log_metrum->u.sensor.pres;
+ ao_data_static.ms5607_raw.temp = log_metrum->u.sensor.temp;
+ ao_data_static.mma655x = log_metrum->u.sensor.accel;
+ ao_records_read++;
+ ao_insert();
+ return;
+ }
break;
- case 'A':
- ao_data_static.tick = tick;
- ao_data_static.ms5607_raw.pres = int32(bytes, 0);
- ao_data_static.ms5607_raw.temp = int32(bytes, 4);
- ao_ms5607_convert(&ao_data_static.ms5607_raw, &value);
- ao_data_static.mma655x = int16(bytes, 8);
- ao_records_read++;
- ao_insert();
- return;
- }
- continue;
- } else if (nword == 3 && strcmp(words[0], "ms5607") == 0) {
- if (strcmp(words[1], "reserved:") == 0)
- ao_ms5607_prom.reserved = strtoul(words[2], NULL, 10);
- else if (strcmp(words[1], "sens:") == 0)
- ao_ms5607_prom.sens = strtoul(words[2], NULL, 10);
- else if (strcmp(words[1], "off:") == 0)
- ao_ms5607_prom.off = strtoul(words[2], NULL, 10);
- else if (strcmp(words[1], "tcs:") == 0)
- ao_ms5607_prom.tcs = strtoul(words[2], NULL, 10);
- else if (strcmp(words[1], "tco:") == 0)
- ao_ms5607_prom.tco = strtoul(words[2], NULL, 10);
- else if (strcmp(words[1], "tref:") == 0)
- ao_ms5607_prom.tref = strtoul(words[2], NULL, 10);
- else if (strcmp(words[1], "tempsens:") == 0)
- ao_ms5607_prom.tempsens = strtoul(words[2], NULL, 10);
- else if (strcmp(words[1], "crc:") == 0)
- ao_ms5607_prom.crc = strtoul(words[2], NULL, 10);
- continue;
- }
#endif
-#if TELEMETRUM_V1
- if (nword == 4 && log_format != AO_LOG_FORMAT_TELEMEGA) {
- type = words[0][0];
- tick = strtoul(words[1], NULL, 16);
- a = strtoul(words[2], NULL, 16);
- b = strtoul(words[3], NULL, 16);
- if (type == 'P')
- type = 'A';
- }
-#endif
- else if (nword == 2 && strcmp(words[0], "log-format") == 0) {
- log_format = strtoul(words[1], NULL, 10);
- } else if (nword == 2 && strcmp(words[0], "serial-number") == 0) {
- ao_serial_number = strtoul(words[1], NULL, 10);
- } else if (nword >= 6 && strcmp(words[0], "Accel") == 0) {
- ao_config.accel_plus_g = atoi(words[3]);
- ao_config.accel_minus_g = atoi(words[5]);
-#ifdef TELEMEGA
- } else if (nword >= 8 && strcmp(words[0], "IMU") == 0) {
- ao_config.accel_zero_along = atoi(words[3]);
- ao_config.accel_zero_across = atoi(words[5]);
- ao_config.accel_zero_through = atoi(words[7]);
+#if EASYMINI
+ case AO_LOG_FORMAT_EASYMINI1:
+ case AO_LOG_FORMAT_EASYMINI2:
+ case AO_LOG_FORMAT_TELEMINI3:
+ log_mini = (struct ao_log_mini *) &eeprom->data[eeprom_offset];
+ eeprom_offset += sizeof (*log_mini);
+ switch (log_mini->type) {
+ case AO_LOG_FLIGHT:
+ ao_flight_started = 1;
+ ao_flight_number = log_mini->u.flight.flight;
+ ao_ground_pres = log_mini->u.flight.ground_pres;
+ ao_ground_height = ao_pa_to_altitude(ao_ground_pres);
+ break;
+ case AO_LOG_SENSOR:
+ ao_data_static.tick = log_mini->tick;
+ ao_data_static.ms5607_raw.pres = int24(log_mini->u.sensor.pres, 0);
+ ao_data_static.ms5607_raw.temp = int24(log_mini->u.sensor.temp, 0);
+ ao_records_read++;
+ ao_insert();
+ return;
+ }
+ break;
#endif
- } else if (nword >= 4 && strcmp(words[0], "Main") == 0) {
- ao_config.main_deploy = atoi(words[2]);
- } else if (nword >= 3 && strcmp(words[0], "Apogee") == 0 &&
- strcmp(words[1], "lockout:") == 0) {
- ao_config.apogee_lockout = atoi(words[2]);
- } else if (nword >= 3 && strcmp(words[0], "Pad") == 0 &&
- strcmp(words[1], "orientation:") == 0) {
- ao_config.pad_orientation = atoi(words[2]);
- } else if (nword >= 36 && strcmp(words[0], "CALL") == 0) {
- tick = atoi(words[10]);
- if (!ao_flight_started) {
- type = 'F';
- a = atoi(words[26]);
- ao_flight_started = 1;
- } else {
- type = 'A';
- a = atoi(words[12]);
- b = atoi(words[14]);
- }
- } else if (nword == 3 && strcmp(words[0], "BARO") == 0) {
- tick = strtol(words[1], NULL, 16);
- a = 16384 - 328;
- b = strtol(words[2], NULL, 10);
- type = 'A';
- if (!ao_flight_started) {
- ao_flight_ground_accel = 16384 - 328;
- ao_config.accel_plus_g = 16384 - 328;
- ao_config.accel_minus_g = 16384 + 328;
- ao_flight_started = 1;
- }
- } else if (nword == 2 && strcmp(words[0], "TELEM") == 0) {
- __xdata char *hex = words[1];
- char elt[3];
- int i, len;
- uint8_t sum;
-
- len = strlen(hex);
- if (len > sizeof (bytes) * 2) {
- len = sizeof (bytes)*2;
- hex[len] = '\0';
- }
- for (i = 0; i < len; i += 2) {
- elt[0] = hex[i];
- elt[1] = hex[i+1];
- elt[2] = '\0';
- bytes[i/2] = (uint8_t) strtol(elt, NULL, 16);
- }
- len = i/2;
- if (bytes[0] != len - 2) {
- printf ("bad length %d != %d\n", bytes[0], len - 2);
- continue;
- }
- sum = 0x5a;
- for (i = 1; i < len-1; i++)
- sum += bytes[i];
- if (sum != bytes[len-1]) {
- printf ("bad checksum\n");
- continue;
- }
- if ((bytes[len-2] & 0x80) == 0) {
- continue;
- }
- if (len == 36) {
- ao_xmemcpy(&telem, bytes + 1, 32);
- tick = telem.generic.tick;
- switch (telem.generic.type) {
- case AO_TELEMETRY_SENSOR_TELEMETRUM:
- case AO_TELEMETRY_SENSOR_TELEMINI:
- case AO_TELEMETRY_SENSOR_TELENANO:
- if (!ao_flight_started) {
- ao_flight_ground_accel = telem.sensor.ground_accel;
- ao_config.accel_plus_g = telem.sensor.accel_plus_g;
- ao_config.accel_minus_g = telem.sensor.accel_minus_g;
- ao_flight_started = 1;
- }
- type = 'A';
- a = telem.sensor.accel;
- b = telem.sensor.pres;
+#if TELEMETRUM_V1
+ case AO_LOG_FORMAT_FULL:
+ case AO_LOG_FORMAT_TINY:
+ log_record = (struct ao_log_record *) &eeprom->data[eeprom_offset];
+ eeprom_offset += sizeof (*log_record);
+ switch (log_record->type) {
+ case AO_LOG_FLIGHT:
+ ao_flight_started = 1;
+ ao_flight_ground_accel = log_record->u.flight.ground_accel;
+ ao_flight_number = log_record->u.flight.flight;
+ break;
+ case AO_LOG_SENSOR:
+ case 'P': /* ancient telemini */
+ ao_data_static.tick = log_record->tick;
+ ao_data_static.adc.accel = log_record->u.sensor.accel;
+ ao_data_static.adc.pres_real = log_record->u.sensor.pres;
+ ao_data_static.adc.pres = log_record->u.sensor.pres;
+ ao_records_read++;
+ ao_insert();
+ return;
+ case AO_LOG_TEMP_VOLT:
+ ao_data_static.tick = log_record->tick;;
+ ao_data_static.adc.temp = log_record->u.temp_volt.temp;
+ ao_data_static.adc.v_batt = log_record->u.temp_volt.v_batt;
break;
}
- } else if (len == 99) {
- ao_flight_started = 1;
- tick = uint16(bytes+1, 21);
- ao_flight_ground_accel = int16(bytes+1, 7);
- ao_config.accel_plus_g = int16(bytes+1, 17);
- ao_config.accel_minus_g = int16(bytes+1, 19);
- type = 'A';
- a = int16(bytes+1, 23);
- b = int16(bytes+1, 25);
- } else if (len == 98) {
- ao_flight_started = 1;
- tick = uint16(bytes+1, 20);
- ao_flight_ground_accel = int16(bytes+1, 6);
- ao_config.accel_plus_g = int16(bytes+1, 16);
- ao_config.accel_minus_g = int16(bytes+1, 18);
- type = 'A';
- a = int16(bytes+1, 22);
- b = int16(bytes+1, 24);
- } else {
- printf("unknown len %d\n", len);
- continue;
- }
- }
- if (type != 'F' && !ao_flight_started)
- continue;
-
-#if TELEMEGA || TELEMETRUM_V2 || EASYMINI
- (void) a;
- (void) b;
-#else
- switch (type) {
- case 'F':
- ao_flight_ground_accel = a;
- ao_flight_number = b;
- if (ao_config.accel_plus_g == 0) {
- ao_config.accel_plus_g = a;
- ao_config.accel_minus_g = a + 530;
+ break;
+#endif
+ default:
+ printf ("invalid log format %d\n", log_format);
+ ao_test_exit();
}
- if (ao_config.main_deploy == 0)
- ao_config.main_deploy = 250;
- ao_flight_started = 1;
- break;
- case 'S':
- break;
- case 'A':
- ao_data_static.tick = tick;
- ao_data_static.adc.accel = a;
- ao_data_static.adc.pres_real = b;
- ao_data_static.adc.pres = b;
- ao_records_read++;
- ao_insert();
- return;
- case 'T':
- ao_data_static.tick = tick;
- ao_data_static.adc.temp = a;
- ao_data_static.adc.v_batt = b;
- break;
- case 'D':
- case 'G':
- case 'N':
- case 'W':
- case 'H':
- break;
}
-#endif
}
}
emulator_info = info;
ao_summary = summary;
+ if (strstr(name, ".eeprom") != NULL) {
+ char c;
+
+ c = getc(f);
+ ungetc(c, f);
+ if (c == '{')
+ eeprom = ao_eeprom_read(f);
+ else
+ eeprom = ao_eeprom_read_old(f);
+
+ if (eeprom) {
+#if HAS_MS5607
+ ao_ms5607_prom = eeprom->ms5607_prom;
+#endif
+ ao_config = eeprom->config;
+ ao_serial_number = eeprom->serial_number;
+ log_format = eeprom->log_format;
+ }
+ }
+
ao_flight_init();
ao_flight();
}
return true;
}
- void set_dirty() {
+ public void set_dirty() {
dirty = true;
save.setEnabled(true);
}
super.dispose();
}
+ public int accel_cal_plus() {
+ return AltosLib.MISSING;
+ }
+
+ public int accel_cal_minus() {
+ return AltosLib.MISSING;
+ }
+
+ public void set_accel_cal(int accel_plus, int accel_minus) {
+ }
+
/* Listen for events from our buttons */
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();