From: Bdale Garbee Date: Fri, 27 Aug 2010 09:08:53 +0000 (-0600) Subject: Merge branch 'new-packet-format' of ssh://git.gag.com/scm/git/fw/altos into new-packa... X-Git-Tag: debian/0.6+373+gcf65c6b~1^2~10 X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=commitdiff_plain;h=c443f43f8dee6e0fcbcecf9d09e948fd928b7af4;hp=295043112ccde35092945c286596f9045ee6fa05 Merge branch 'new-packet-format' of ssh://git.gag.com/scm/git/fw/altos into new-package-format --- diff --git a/ao-tools/altosui/Altos.java b/ao-tools/altosui/Altos.java index 53359e23..07bd01ae 100644 --- a/ao-tools/altosui/Altos.java +++ b/ao-tools/altosui/Altos.java @@ -114,4 +114,90 @@ public class Altos { static final int AO_GPS_DATE_VALID = (1 << 6); static final int AO_GPS_NUM_SAT_SHIFT = 0; static final int AO_GPS_NUM_SAT_MASK = 0xf; + + static boolean isspace(int c) { + switch (c) { + case ' ': + case '\t': + return true; + } + return false; + } + + static 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; + } + + static boolean ishex(String s) { + for (int i = 0; i < s.length(); i++) + if (!ishex(s.charAt(i))) + return false; + return true; + } + + static 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; + } + + static int fromhex(String s) throws NumberFormatException { + int c, v = 0; + for (int i = 0; i < s.length(); i++) { + c = s.charAt(i); + if (!ishex(c)) { + if (i == 0) + throw new NumberFormatException(String.format("invalid hex \"%s\"", s)); + return v; + } + v = v * 16 + fromhex(c); + } + return v; + } + + static boolean isdec(int c) { + if ('0' <= c && c <= '9') + return true; + return false; + } + + static boolean isdec(String s) { + for (int i = 0; i < s.length(); i++) + if (!isdec(s.charAt(i))) + return false; + return true; + } + + static int fromdec(int c) { + if ('0' <= c && c <= '9') + return c - '0'; + return -1; + } + + static int fromdec(String s) throws NumberFormatException { + int c, v = 0; + int sign = 1; + for (int i = 0; i < s.length(); i++) { + c = s.charAt(i); + if (i == 0 && c == '-') { + sign = -1; + } else if (!isdec(c)) { + if (i == 0) + throw new NumberFormatException(String.format("invalid number \"%s\"", s)); + return v; + } else + v = v * 10 + fromdec(c); + } + return v * sign; + } } diff --git a/ao-tools/altosui/AltosCSV.java b/ao-tools/altosui/AltosCSV.java index 24936758..db50e7a2 100644 --- a/ao-tools/altosui/AltosCSV.java +++ b/ao-tools/altosui/AltosCSV.java @@ -19,12 +19,20 @@ package altosui; import java.lang.*; import java.io.*; +import java.text.*; +import java.util.*; + import altosui.AltosRecord; +import altosui.AltosReader; public class AltosCSV { - File name; - PrintStream out; - boolean header_written; + File name; + PrintStream out; + boolean header_written; + boolean seen_boost; + int boost_tick; + LinkedList pad_records; + AltosState state; static final int ALTOS_CSV_VERSION = 1; @@ -36,6 +44,7 @@ public class AltosCSV { * flight number * callsign * time (seconds since boost) + * rssi * * Flight status * state @@ -45,6 +54,7 @@ public class AltosCSV { * acceleration (m/s²) * pressure (mBar) * altitude (m) + * height (m) * accelerometer speed (m/s) * barometer speed (m/s) * temp (°C) @@ -65,6 +75,8 @@ public class AltosCSV { * hour (0-23) * minute (0-59) * second (0-59) + * from_pad_dist (m) + * from_pad_dir (deg true) * * GPS Sat data * hdop @@ -72,12 +84,14 @@ public class AltosCSV { */ void write_general_header() { - out.printf("version serial flight call time"); + out.printf("version serial flight call time rssi"); } void write_general(AltosRecord record) { - out.printf("%s,%d,%d,%s,%d", - record.version, record.serial, record.flight, record.callsign, record.tick); + out.printf("%s,%d,%d,%s,%8.2f,%4d", + record.version, record.serial, record.flight, record.callsign, + (double) record.time, + record.rssi); } void write_flight_header() { @@ -85,31 +99,135 @@ public class AltosCSV { } void write_flight(AltosRecord record) { - out.printf("%d,%s", record.state, record.state()); + out.printf("%d,%8s", record.state, record.state()); + } + + void write_basic_header() { + out.printf("acceleration pressure altitude height accel_speed baro_speed temperature battery_voltage drogue_voltage main_voltage"); + } + + void write_basic(AltosRecord record) { + out.printf("%8.2f,%10.2f,%8.2f,%8.2f,%8.2f,%8.2f,%5.1f,%5.2f,%5.2f,%5.2f", + record.acceleration(), + record.pressure(), + record.altitude(), + record.height(), + record.accel_speed(), + state.baro_speed, + record.temperature(), + record.battery_voltage(), + record.drogue_voltage(), + record.main_voltage()); + } + + void write_gps_header() { + out.printf("connected locked nsat latitude longitude altitude year month day hour minute second pad_dist pad_dir"); + } + + void write_gps(AltosRecord record) { + AltosGPS gps = record.gps; + if (gps == null) + gps = new AltosGPS(); + + AltosGreatCircle from_pad = state.from_pad; + if (from_pad == null) + from_pad = new AltosGreatCircle(); + + out.printf("%2d,%2d,%3d,%12.7f,%12.7f,%6d,%5d,%3d,%3d,%3d,%3d,%3d,%9.0f,%4.0f", + gps.connected?1:0, + gps.locked?1:0, + gps.nsat, + gps.lat, + gps.lon, + gps.alt, + gps.year, + gps.month, + gps.day, + gps.hour, + gps.minute, + gps.second, + from_pad.distance, + from_pad.bearing); } void write_header() { out.printf("# "); write_general_header(); out.printf(" "); write_flight_header(); + out.printf(" "); write_basic_header(); + out.printf(" "); write_gps_header(); + out.printf ("\n"); + } + + void write_one(AltosRecord record) { + state = new AltosState(record, state); + write_general(record); out.printf(","); + write_flight(record); out.printf(","); + write_basic(record); out.printf(","); + write_gps(record); out.printf ("\n"); } + void flush_pad() { + while (!pad_records.isEmpty()) { + write_one (pad_records.remove()); + } + } + public void write(AltosRecord record) { if (!header_written) { write_header(); header_written = true; } - write_general(record); out.printf(","); - write_flight(record); - out.printf ("\n"); + if (!seen_boost) { + if (record.state >= Altos.ao_flight_boost) { + seen_boost = true; + boost_tick = record.tick; + flush_pad(); + } + } + if (seen_boost) + write_one(record); + else + pad_records.add(record); } public PrintStream out() { return out; } + public void close() { + if (!pad_records.isEmpty()) { + boost_tick = pad_records.element().tick; + flush_pad(); + } + out.close(); + } + + public void write(AltosReader reader) { + AltosRecord record; + + reader.write_comments(out()); + try { + for (;;) { + record = reader.read(); + if (record == null) + break; + write(record); + } + } catch (IOException ie) { + System.out.printf("IOException\n"); + } catch (ParseException pe) { + System.out.printf("ParseException %s\n", pe.getMessage()); + } + } + public AltosCSV(File in_name) throws FileNotFoundException { name = in_name; out = new PrintStream(name); + pad_records = new LinkedList(); + } + + public AltosCSV(String in_string) throws FileNotFoundException { + this(new File(in_string)); } } diff --git a/ao-tools/altosui/AltosCSVUI.java b/ao-tools/altosui/AltosCSVUI.java new file mode 100644 index 00000000..2d812361 --- /dev/null +++ b/ao-tools/altosui/AltosCSVUI.java @@ -0,0 +1,83 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package altosui; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; +import javax.swing.table.*; +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.util.concurrent.LinkedBlockingQueue; + +import altosui.AltosLogfileChooser; +import altosui.AltosCSV; + +public class AltosCSVUI + extends JDialog + implements Runnable, ActionListener +{ + JFrame frame; + Thread thread; + AltosReader reader; + AltosCSV writer; + + public void run() { + AltosLogfileChooser chooser; + + chooser = new AltosLogfileChooser(frame); + reader = chooser.runDialog(); + if (reader == null) + return; + JFileChooser csv_chooser; + + File file = chooser.file(); + String path = file.getPath(); + int dot = path.lastIndexOf("."); + if (dot >= 0) + path = path.substring(0,dot); + path = path.concat(".csv"); + csv_chooser = new JFileChooser(path); + int ret = csv_chooser.showSaveDialog(frame); + if (ret == JFileChooser.APPROVE_OPTION) { + try { + writer = new AltosCSV(csv_chooser.getSelectedFile()); + } catch (FileNotFoundException ee) { + JOptionPane.showMessageDialog(frame, + file.getName(), + "Cannot open file", + JOptionPane.ERROR_MESSAGE); + } + writer.write(reader); + reader.close(); + writer.close(); + } + } + + public void actionPerformed(ActionEvent e) { + } + + public AltosCSVUI(JFrame in_frame) { + frame = in_frame; + thread = new Thread(this); + thread.start(); + } +} diff --git a/ao-tools/altosui/AltosDebug.java b/ao-tools/altosui/AltosDebug.java index 83ea5bcb..ca2e5a90 100644 --- a/ao-tools/altosui/AltosDebug.java +++ b/ao-tools/altosui/AltosDebug.java @@ -58,46 +58,12 @@ public class AltosDebug extends AltosSerial { public static final byte GET_CHIP_ID = 0x68; - static 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; - } - - static boolean ishex(String s) { - for (int i = 0; i < s.length(); i++) - if (!ishex(s.charAt(i))) - return false; - return true; - } - static boolean isspace(int c) { - switch (c) { - case ' ': - case '\t': - return true; - } - return false; - } - - static 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; - } - boolean debug_mode; void ensure_debug_mode() { if (!debug_mode) { - printf("D\n"); + printf("m 0\nD\n"); + flush_reply(); debug_mode = true; } } @@ -144,14 +110,14 @@ public class AltosDebug extends AltosSerial { int start = 0; while (i < length) { String line = get_reply().trim(); - if (!ishex(line) || line.length() % 2 != 0) + if (!Altos.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) ((fromhex(line.charAt(j*2)) << 4) + - fromhex(line.charAt(j*2+1))); + data[start + j] = (byte) ((Altos.fromhex(line.charAt(j*2)) << 4) + + Altos.fromhex(line.charAt(j*2+1))); start += this_time; i += this_time; } @@ -198,7 +164,7 @@ public class AltosDebug extends AltosSerial { String line = get_reply().trim(); String tokens[] = line.split("\\s+"); for (int j = 0; j < tokens.length; j++) { - if (!ishex(tokens[j]) || + if (!Altos.ishex(tokens[j]) || tokens[j].length() != 2) throw new IOException( String.format diff --git a/ao-tools/altosui/AltosEepromReader.java b/ao-tools/altosui/AltosEepromReader.java index c29fd90b..3f2d4c62 100644 --- a/ao-tools/altosui/AltosEepromReader.java +++ b/ao-tools/altosui/AltosEepromReader.java @@ -133,8 +133,6 @@ public class AltosEepromReader extends AltosReader { ground_pres += state.pres; state.ground_pres = (int) (ground_pres / n_pad_samples); state.flight_pres = state.ground_pres; - System.out.printf("ground pressure %d altitude %f\n", - record.b, state.altitude()); ground_accel += state.accel; state.ground_accel = (int) (ground_accel / n_pad_samples); state.flight_accel = state.ground_accel; @@ -156,7 +154,6 @@ public class AltosEepromReader extends AltosReader { seen |= seen_deploy; break; case Altos.AO_LOG_STATE: - System.out.printf("state %d\n", record.a); state.state = record.a; break; case Altos.AO_LOG_GPS_TIME: @@ -218,6 +215,7 @@ public class AltosEepromReader extends AltosReader { case Altos.AO_LOG_PRODUCT: break; case Altos.AO_LOG_SERIAL_NUMBER: + state.serial = record.a; break; case Altos.AO_LOG_SOFTWARE_VERSION: break; @@ -228,6 +226,7 @@ public class AltosEepromReader extends AltosReader { public void write_comments(PrintStream out) { Iterator iterator = records.iterator(); + out.printf("# Comments\n"); while (iterator.hasNext()) { AltosOrderedRecord record = iterator.next(); switch (record.cmd) { @@ -250,7 +249,7 @@ public class AltosEepromReader extends AltosReader { out.printf ("# Accel cal: %d %d\n", record.a, record.b); break; case Altos.AO_LOG_RADIO_CAL: - out.printf ("# Radio cal: %d %d\n", record.a); + out.printf ("# Radio cal: %d\n", record.a); break; case Altos.AO_LOG_MANUFACTURER: out.printf ("# Manufacturer: %s\n", record.data); @@ -296,10 +295,10 @@ public class AltosEepromReader extends AltosReader { break; tick = record.tick; if (!saw_boost && record.cmd == Altos.AO_LOG_STATE && - record.a == Altos.ao_flight_boost) + record.a >= Altos.ao_flight_boost) { saw_boost = true; - boost_tick = state.tick; + boost_tick = tick; } records.add(record); } diff --git a/ao-tools/altosui/AltosFlash.java b/ao-tools/altosui/AltosFlash.java index 0f92d6e7..b7018555 100644 --- a/ao-tools/altosui/AltosFlash.java +++ b/ao-tools/altosui/AltosFlash.java @@ -247,6 +247,7 @@ public class AltosFlash { 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; @@ -314,6 +315,8 @@ public class AltosFlash { } public AltosRomconfig romconfig() { + if (!check_rom_config()) + return null; return rom_config; } diff --git a/ao-tools/altosui/AltosFlashUI.java b/ao-tools/altosui/AltosFlashUI.java index 0c2041e3..73a97a6b 100644 --- a/ao-tools/altosui/AltosFlashUI.java +++ b/ao-tools/altosui/AltosFlashUI.java @@ -57,8 +57,10 @@ public class AltosFlashUI } else { String cmd = e.getActionCommand(); if (cmd.equals("done")) - dispose(); - else { + ; + else if (cmd.equals("start")) { + setVisible(true); + } else { pbar.setValue(e.getID()); pbar.setString(cmd); } @@ -70,14 +72,15 @@ public class AltosFlashUI flash.addActionListener(this); try { flash.open(); - if (!flash.check_rom_config()) { - AltosRomconfigUI romconfig_ui = new AltosRomconfigUI (frame); - romconfig_ui.showDialog(); - AltosRomconfig romconfig = romconfig_ui.romconfig(); - if (romconfig == null) - return; - flash.set_romconfig(romconfig); - } + AltosRomconfigUI romconfig_ui = new AltosRomconfigUI (frame); + + romconfig_ui.set(flash.romconfig()); + romconfig_ui.showDialog(); + + AltosRomconfig romconfig = romconfig_ui.romconfig(); + if (romconfig == null || !romconfig.valid()) + return; + flash.set_romconfig(romconfig); serial_value.setText(String.format("%d", flash.romconfig().serial_number)); file_value.setText(file.toString()); @@ -88,15 +91,14 @@ public class AltosFlashUI "Cannot open image", file.toString(), JOptionPane.ERROR_MESSAGE); - return; } catch (IOException e) { JOptionPane.showMessageDialog(frame, e.getMessage(), file.toString(), JOptionPane.ERROR_MESSAGE); - return; } catch (InterruptedException ie) { } + dispose(); } public void abort() { diff --git a/ao-tools/altosui/AltosGPS.java b/ao-tools/altosui/AltosGPS.java index b3ee67e8..acb6fb2c 100644 --- a/ao-tools/altosui/AltosGPS.java +++ b/ao-tools/altosui/AltosGPS.java @@ -52,14 +52,16 @@ public class AltosGPS { AltosGPSSat[] cc_gps_sat; /* tracking data */ - void ParseGPSTime(String date, String time) throws ParseException { + void ParseGPSDate(String date) throws ParseException { String[] ymd = date.split("-"); if (ymd.length != 3) throw new ParseException("error parsing GPS date " + date + " got " + ymd.length, 0); year = AltosParse.parse_int(ymd[0]); month = AltosParse.parse_int(ymd[1]); day = AltosParse.parse_int(ymd[2]); + } + void ParseGPSTime(String time) throws ParseException { String[] hms = time.split(":"); if (hms.length != 3) throw new ParseException("Error parsing GPS time " + time + " got " + hms.length, 0); @@ -73,7 +75,7 @@ public class AltosGPS { hour = minute = second = 0; } - public AltosGPS(String[] words, int i) throws ParseException { + public AltosGPS(String[] words, int i, int version) throws ParseException { AltosParse.word(words[i++], "GPS"); nsat = AltosParse.parse_int(words[i++]); AltosParse.word(words[i++], "sat"); @@ -92,32 +94,44 @@ public class AltosGPS { locked = true; connected = true; - ParseGPSTime(words[i], words[i+1]); i += 2; + if (version > 1) + ParseGPSDate(words[i++]); + else + year = month = day = 0; + ParseGPSTime(words[i++]); lat = AltosParse.parse_coord(words[i++]); lon = AltosParse.parse_coord(words[i++]); - alt = AltosParse.parse_int(AltosParse.strip_suffix(words[i++], "m")); - ground_speed = AltosParse.parse_double(AltosParse.strip_suffix(words[i++], "m/s(H)")); - course = AltosParse.parse_int(AltosParse.strip_suffix(words[i++], "°")); - climb_rate = AltosParse.parse_double(AltosParse.strip_suffix(words[i++], "m/s(V)")); - hdop = AltosParse.parse_double(AltosParse.strip_suffix(words[i++], "(hdop)")); - h_error = AltosParse.parse_int(AltosParse.strip_suffix(words[i++], "(herr)")); - v_error = AltosParse.parse_int(AltosParse.strip_suffix(words[i++], "(verr)")); + alt = AltosParse.parse_int(words[i++]); + if (version > 1 || (i < words.length && !words[i].equals("SAT"))) { + ground_speed = AltosParse.parse_double(AltosParse.strip_suffix(words[i++], "m/s(H)")); + course = AltosParse.parse_int(words[i++]); + climb_rate = AltosParse.parse_double(AltosParse.strip_suffix(words[i++], "m/s(V)")); + hdop = AltosParse.parse_double(AltosParse.strip_suffix(words[i++], "(hdop)")); + h_error = AltosParse.parse_int(words[i++]); + v_error = AltosParse.parse_int(words[i++]); + } } else { i++; } - AltosParse.word(words[i++], "SAT"); - int tracking_channels = 0; - if (words[i].equals("not-connected")) - tracking_channels = 0; - else - tracking_channels = AltosParse.parse_int(words[i]); - i++; - cc_gps_sat = new AltosGPS.AltosGPSSat[tracking_channels]; - for (int chan = 0; chan < tracking_channels; chan++) { - cc_gps_sat[chan] = new AltosGPS.AltosGPSSat(); - cc_gps_sat[chan].svid = AltosParse.parse_int(words[i++]); - cc_gps_sat[chan].c_n0 = AltosParse.parse_int(words[i++]); - } + if (i < words.length) { + AltosParse.word(words[i++], "SAT"); + int tracking_channels = 0; + if (words[i].equals("not-connected")) + tracking_channels = 0; + else + tracking_channels = AltosParse.parse_int(words[i]); + i++; + cc_gps_sat = new AltosGPS.AltosGPSSat[tracking_channels]; + for (int chan = 0; chan < tracking_channels; chan++) { + cc_gps_sat[chan] = new AltosGPS.AltosGPSSat(); + cc_gps_sat[chan].svid = AltosParse.parse_int(words[i++]); + /* Older versions included SiRF status bits */ + if (version < 2) + i++; + cc_gps_sat[chan].c_n0 = AltosParse.parse_int(words[i++]); + } + } else + cc_gps_sat = new AltosGPS.AltosGPSSat[0]; } public void set_latitude(int in_lat) { @@ -172,6 +186,7 @@ public class AltosGPS { nsat = old.nsat; locked = old.locked; connected = old.connected; + date_valid = old.date_valid; lat = old.lat; /* degrees (+N -S) */ lon = old.lon; /* degrees (+E -W) */ alt = old.alt; /* m */ diff --git a/ao-tools/altosui/AltosGreatCircle.java b/ao-tools/altosui/AltosGreatCircle.java index 878da03e..07c02c16 100644 --- a/ao-tools/altosui/AltosGreatCircle.java +++ b/ao-tools/altosui/AltosGreatCircle.java @@ -17,6 +17,8 @@ package altosui; +import altosui.AltosGPS; + import java.lang.Math; public class AltosGreatCircle { @@ -28,8 +30,8 @@ public class AltosGreatCircle { static final double rad = Math.PI / 180; static final double earth_radius = 6371.2 * 1000; /* in meters */ - AltosGreatCircle (double start_lat, double start_lon, - double end_lat, double end_lon) + public AltosGreatCircle (double start_lat, double start_lon, + double end_lat, double end_lon) { double lat1 = rad * start_lat; double lon1 = rad * -start_lon; @@ -63,4 +65,13 @@ public class AltosGreatCircle { distance = d * earth_radius; bearing = course * 180/Math.PI; } + + public AltosGreatCircle(AltosGPS start, AltosGPS end) { + this(start.lat, start.lon, end.lat, end.lon); + } + + public AltosGreatCircle() { + distance = 0; + bearing = 0; + } } diff --git a/ao-tools/altosui/AltosLogfileChooser.java b/ao-tools/altosui/AltosLogfileChooser.java new file mode 100644 index 00000000..36b51de6 --- /dev/null +++ b/ao-tools/altosui/AltosLogfileChooser.java @@ -0,0 +1,83 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package altosui; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; +import javax.swing.table.*; +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; + +import altosui.AltosPreferences; +import altosui.AltosReader; +import altosui.AltosEepromReader; +import altosui.AltosTelemetryReader; + +public class AltosLogfileChooser extends JFileChooser { + JFrame frame; + String filename; + File file; + + public String filename() { + return filename; + } + + public File file() { + return file; + } + + public AltosReader runDialog() { + int ret; + + ret = showOpenDialog(frame); + if (ret == APPROVE_OPTION) { + file = getSelectedFile(); + if (file == null) + return null; + filename = file.getName(); + try { + FileInputStream in; + + in = new FileInputStream(file); + if (filename.endsWith("eeprom")) + return new AltosEepromReader(in); + else + return new AltosTelemetryReader(in); + } catch (FileNotFoundException fe) { + JOptionPane.showMessageDialog(frame, + filename, + "Cannot open file", + JOptionPane.ERROR_MESSAGE); + } + } + return null; + } + + public AltosLogfileChooser(JFrame in_frame) { + frame = in_frame; + setDialogTitle("Select Flight Record File"); + setFileFilter(new FileNameExtensionFilter("Flight data file", + "eeprom", + "telem")); + setCurrentDirectory(AltosPreferences.logdir()); + } +} \ No newline at end of file diff --git a/ao-tools/altosui/AltosParse.java b/ao-tools/altosui/AltosParse.java index a60dc694..4d82de78 100644 --- a/ao-tools/altosui/AltosParse.java +++ b/ao-tools/altosui/AltosParse.java @@ -20,10 +20,16 @@ package altosui; import java.text.*; import java.lang.*; +import altosui.Altos; + public class AltosParse { + static boolean isdigit(char c) { + return '0' <= c && c <= '9'; + } + static int parse_int(String v) throws ParseException { try { - return Integer.parseInt(v); + return Altos.fromdec(v); } catch (NumberFormatException e) { throw new ParseException("error parsing int " + v, 0); } @@ -31,7 +37,7 @@ public class AltosParse { static int parse_hex(String v) throws ParseException { try { - return Integer.parseInt(v, 16); + return Altos.fromhex(v); } catch (NumberFormatException e) { throw new ParseException("error parsing hex " + v, 0); } diff --git a/ao-tools/altosui/AltosReader.java b/ao-tools/altosui/AltosReader.java index 81779e2b..5be8795d 100644 --- a/ao-tools/altosui/AltosReader.java +++ b/ao-tools/altosui/AltosReader.java @@ -25,4 +25,6 @@ import altosui.AltosRecord; public class AltosReader { public AltosRecord read() throws IOException, ParseException { return null; } + public void close() { } + public void write_comments(PrintStream out) { } } diff --git a/ao-tools/altosui/AltosRomconfig.java b/ao-tools/altosui/AltosRomconfig.java index 844da7c4..8c9cb27a 100644 --- a/ao-tools/altosui/AltosRomconfig.java +++ b/ao-tools/altosui/AltosRomconfig.java @@ -47,14 +47,57 @@ public class AltosRomconfig { } } + 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; + System.out.printf("Put usb serial %d\n", value); + + 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; + } + System.out.printf("offset %d content %d\n", + offset, bytes[offset]); + if (offset >= bytes.length || bytes[offset] == 0) + return; + int len = ((((int) bytes[offset]) & 0xff) - 2) / 2; + String fmt = String.format("%%0%dd", len); + System.out.printf("existing serial length %d format %s\n", len, fmt); + + 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); + System.out.printf("version %d check %d\n", version, check); 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); + System.out.printf("serial %d cal %d\n", serial_number, radio_calibration); valid = true; break; } @@ -77,6 +120,8 @@ public class AltosRomconfig { 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); @@ -86,7 +131,9 @@ public class AltosRomconfig { public void write (AltosHexfile hexfile) throws IOException { write(hexfile.data, 0xa0 - hexfile.address); - new AltosRomconfig(hexfile); + 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) { diff --git a/ao-tools/altosui/AltosRomconfigUI.java b/ao-tools/altosui/AltosRomconfigUI.java index 21c34ef4..bc511865 100644 --- a/ao-tools/altosui/AltosRomconfigUI.java +++ b/ao-tools/altosui/AltosRomconfigUI.java @@ -143,12 +143,31 @@ public class AltosRomconfigUI return Integer.parseInt(serial_value.getText()); } + void set_serial(int serial) { + serial_value.setText(String.format("%d", serial)); + } + int radio_calibration() { return Integer.parseInt(radio_calibration_value.getText()); } + void set_radio_calibration(int calibration) { + radio_calibration_value.setText(String.format("%d", calibration)); + } + + public void set(AltosRomconfig config) { + if (config != null && config.valid()) { + set_serial(config.serial_number); + set_radio_calibration(config.radio_calibration); + } + } + public AltosRomconfig romconfig() { - return new AltosRomconfig(serial(), radio_calibration()); + try { + return new AltosRomconfig(serial(), radio_calibration()); + } catch (NumberFormatException ne) { + return null; + } } public AltosRomconfig showDialog() { diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java index d02e25a9..5b47960f 100644 --- a/ao-tools/altosui/AltosSerial.java +++ b/ao-tools/altosui/AltosSerial.java @@ -45,6 +45,8 @@ public class AltosSerial implements Runnable { LinkedBlockingQueue reply_queue; Thread input_thread; String line; + byte[] line_bytes; + int line_count; public void run () { int c; @@ -60,18 +62,36 @@ public class AltosSerial implements Runnable { continue; synchronized(this) { if (c == '\n') { - if (line != "") { + if (line_count != 0) { + try { + line = new String(line_bytes, 0, line_count, "UTF-8"); + } catch (UnsupportedEncodingException ue) { + line = ""; + for (int i = 0; i < line_count; i++) + line = line + line_bytes[i]; + } if (line.startsWith("VERSION")) { for (int e = 0; e < monitors.size(); e++) { LinkedBlockingQueue q = monitors.get(e); q.put(line); } - } else + } else { +// System.out.printf("GOT: %s\n", line); reply_queue.put(line); + } + line_count = 0; line = ""; } } else { - line = line + (char) c; + if (line_bytes == null) { + line_bytes = new byte[256]; + } else if (line_count == line_bytes.length) { + byte[] new_line_bytes = new byte[line_count * 2]; + System.arraycopy(line_bytes, 0, new_line_bytes, 0, line_count); + line_bytes = new_line_bytes; + } + line_bytes[line_count] = (byte) c; + line_count++; } } } @@ -80,6 +100,11 @@ public class AltosSerial implements Runnable { } public void flush_reply() { + libaltos.altos_flush(altos); + try { + Thread.sleep(100); + } catch (InterruptedException ie) { + } reply_queue.clear(); } @@ -132,6 +157,7 @@ public class AltosSerial implements Runnable { } public void print(String data) { +//h System.out.printf("\"%s\" ", data); for (int i = 0; i < data.length(); i++) putc(data.charAt(i)); } diff --git a/ao-tools/altosui/AltosState.java b/ao-tools/altosui/AltosState.java index deeb4c77..c13dfe68 100644 --- a/ao-tools/altosui/AltosState.java +++ b/ao-tools/altosui/AltosState.java @@ -124,11 +124,6 @@ public class AltosState { } if (state == Altos.ao_flight_pad) { - if (data.gps == null) - System.out.printf("on pad, gps null\n"); - else - System.out.printf ("on pad gps lat %f lon %f locked %d nsat %d\n", - data.gps.lat, data.gps.lon, data.gps.locked ? 1 : 0, data.gps.nsat); if (data.gps != null && data.gps.locked && data.gps.nsat >= 4) { npad++; if (npad > 1) { diff --git a/ao-tools/altosui/AltosTelemetry.java b/ao-tools/altosui/AltosTelemetry.java index af29b8c0..bc62690b 100644 --- a/ao-tools/altosui/AltosTelemetry.java +++ b/ao-tools/altosui/AltosTelemetry.java @@ -57,8 +57,12 @@ public class AltosTelemetry extends AltosRecord { String[] words = line.split("\\s+"); int i = 0; - AltosParse.word (words[i++], "VERSION"); - version = AltosParse.parse_int(words[i++]); + if (words[i].equals("CALL")) { + version = 0; + } else { + AltosParse.word (words[i++], "VERSION"); + version = AltosParse.parse_int(words[i++]); + } AltosParse.word (words[i++], "CALL"); callsign = words[i++]; @@ -66,12 +70,19 @@ public class AltosTelemetry extends AltosRecord { AltosParse.word (words[i++], "SERIAL"); serial = AltosParse.parse_int(words[i++]); - AltosParse.word (words[i++], "FLIGHT"); - flight = AltosParse.parse_int(words[i++]); + if (version >= 2) { + AltosParse.word (words[i++], "FLIGHT"); + flight = AltosParse.parse_int(words[i++]); + } else + flight = 0; AltosParse.word(words[i++], "RSSI"); rssi = AltosParse.parse_int(words[i++]); + /* Older telemetry data had mis-computed RSSI value */ + if (version <= 2) + rssi = (rssi + 74) / 2 - 74; + AltosParse.word(words[i++], "STATUS"); status = AltosParse.parse_hex(words[i++]); @@ -113,12 +124,17 @@ public class AltosTelemetry extends AltosRecord { AltosParse.word(words[i++], "gp:"); ground_pres = AltosParse.parse_int(words[i++]); - AltosParse.word(words[i++], "a+:"); - accel_plus_g = AltosParse.parse_int(words[i++]); + if (version >= 1) { + AltosParse.word(words[i++], "a+:"); + accel_plus_g = AltosParse.parse_int(words[i++]); - AltosParse.word(words[i++], "a-:"); - accel_minus_g = AltosParse.parse_int(words[i++]); + AltosParse.word(words[i++], "a-:"); + accel_minus_g = AltosParse.parse_int(words[i++]); + } else { + accel_plus_g = ground_accel; + accel_minus_g = ground_accel + 530; + } - gps = new AltosGPS(words, i); + gps = new AltosGPS(words, i, version); } } diff --git a/ao-tools/altosui/AltosTelemetryReader.java b/ao-tools/altosui/AltosTelemetryReader.java index f1f6788c..a3402f9c 100644 --- a/ao-tools/altosui/AltosTelemetryReader.java +++ b/ao-tools/altosui/AltosTelemetryReader.java @@ -47,20 +47,25 @@ public class AltosTelemetryReader extends AltosReader { try { for (;;) { String line = AltosRecord.gets(input); - if (line == null) + if (line == null) { break; - AltosTelemetry record = new AltosTelemetry(line); - if (record == null) - break; - if (!saw_boost && record.state >= Altos.ao_flight_boost) - { - saw_boost = true; - boost_tick = record.tick; } - records.add(record); + try { + AltosTelemetry record = new AltosTelemetry(line); + if (record == null) + break; + if (!saw_boost && record.state >= Altos.ao_flight_boost) + { + saw_boost = true; + boost_tick = record.tick; + } + records.add(record); + } catch (ParseException pe) { + System.out.printf("parse exception %s\n", pe.getMessage()); + } } } catch (IOException io) { - } catch (ParseException pe) { + System.out.printf("io exception\n"); } record_iterator = records.iterator(); try { diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 9fd47ea7..4f3b5dde 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -42,6 +42,8 @@ import altosui.AltosFlightStatusTableModel; import altosui.AltosFlightInfoTableModel; import altosui.AltosChannelMenu; import altosui.AltosFlashUI; +import altosui.AltosLogfileChooser; +import altosui.AltosCSVUI; import libaltosJNI.*; @@ -529,33 +531,12 @@ public class AltosUI extends JFrame { * Replay a flight from telemetry data */ private void Replay() { - JFileChooser logfile_chooser = new JFileChooser(); - - logfile_chooser.setDialogTitle("Select Flight Record File"); - logfile_chooser.setFileFilter(new FileNameExtensionFilter("Flight data file", "eeprom", "telem")); - logfile_chooser.setCurrentDirectory(AltosPreferences.logdir()); - int returnVal = logfile_chooser.showOpenDialog(AltosUI.this); - - if (returnVal == JFileChooser.APPROVE_OPTION) { - File file = logfile_chooser.getSelectedFile(); - if (file == null) - System.out.println("No file selected?"); - String filename = file.getName(); - try { - FileInputStream replay = new FileInputStream(file); - DisplayThread thread; - if (filename.endsWith("eeprom")) - thread = new ReplayEepromThread(replay, filename); - else - thread = new ReplayTelemetryThread(replay, filename); - run_display(thread); - } catch (FileNotFoundException ee) { - JOptionPane.showMessageDialog(AltosUI.this, - filename, - "Cannot open telemetry file", - JOptionPane.ERROR_MESSAGE); - } - } + AltosLogfileChooser chooser = new AltosLogfileChooser( + AltosUI.this); + AltosReader reader = chooser.runDialog(); + if (reader != null) + run_display(new ReplayThread(reader, + chooser.filename())); } /* Connect to TeleMetrum, either directly or through @@ -565,6 +546,14 @@ public class AltosUI extends JFrame { new AltosEepromDownload(AltosUI.this); } + /* Load a flight log file and write out a CSV file containing + * all of the data in standard units + */ + + private void ExportData() { + new AltosCSVUI(AltosUI.this); + } + /* Create the AltosUI menus */ private void createMenu() { @@ -603,6 +592,14 @@ public class AltosUI extends JFrame { }); menu.add(item); + item = new JMenuItem("Export Data",KeyEvent.VK_F); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + ExportData(); + } + }); + menu.add(item); + item = new JMenuItem("Quit",KeyEvent.VK_Q); item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, ActionEvent.CTRL_MASK)); @@ -722,8 +719,67 @@ public class AltosUI extends JFrame { this.setJMenuBar(menubar); } + + static String replace_extension(String input, String extension) { + int dot = input.lastIndexOf("."); + if (dot > 0) + input = input.substring(0,dot); + return input.concat(extension); + } + + static AltosReader open_logfile(String filename) { + File file = new File (filename); + try { + FileInputStream in; + + in = new FileInputStream(file); + if (filename.endsWith("eeprom")) + return new AltosEepromReader(in); + else + return new AltosTelemetryReader(in); + } catch (FileNotFoundException fe) { + System.out.printf("Cannot open '%s'\n", filename); + return null; + } + } + + static AltosCSV open_csv(String filename) { + File file = new File (filename); + try { + return new AltosCSV(file); + } catch (FileNotFoundException fe) { + System.out.printf("Cannot open '%s'\n", filename); + return null; + } + } + + static void process_file(String input) { + String output = replace_extension(input,".csv"); + if (input.equals(output)) { + System.out.printf("Not processing '%s'\n", input); + return; + } + System.out.printf("Processing \"%s\" to \"%s\"\n", input, output); + AltosReader reader = open_logfile(input); + if (reader == null) + return; + AltosCSV writer = open_csv(output); + if (writer == null) + return; + writer.write(reader); + reader.close(); + writer.close(); + } + public static void main(final String[] args) { - AltosUI altosui = new AltosUI(); - altosui.setVisible(true); + + /* Handle batch-mode */ + if (args.length > 0) { + for (int i = 0; i < args.length; i++) + process_file(args[i]); + } else { + AltosUI altosui = new AltosUI(); + altosui.setVisible(true); + } } } \ No newline at end of file diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index d4d3ee7a..d3ecb889 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -8,6 +8,7 @@ CLASSFILES=\ AltosConfigUI.class \ AltosConvert.class \ AltosCSV.class \ + AltosCSVUI.class \ AltosDebug.class \ AltosEepromDownload.class \ AltosEepromMonitor.class \ @@ -22,6 +23,7 @@ CLASSFILES=\ AltosGreatCircle.class \ AltosHexfile.class \ AltosLog.class \ + AltosLogfileChooser.class \ AltosParse.class \ AltosPreferences.class \ AltosRecord.class \ diff --git a/src/Makefile.proto b/src/Makefile.proto index 8bc8b0e1..59a3b8a6 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -214,9 +214,11 @@ all: ../$(PROG) ../altitude.h: make-altitude nickle $< > $@ -ao_product.h: ao-make-product.5c +ao_product.h: ao-make-product.5c always $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ +always: + ao_product.rel: ao_product.c ao_product.h $(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< diff --git a/src/ao.h b/src/ao.h index 9c418db2..cd4e4814 100644 --- a/src/ao.h +++ b/src/ao.h @@ -79,7 +79,7 @@ ao_alarm(uint16_t delay); /* Yield the processor to another task */ void -ao_yield(void) _naked; +ao_yield(void) __naked; /* Add a task to the run queue */ void @@ -139,7 +139,7 @@ ao_timer_set_adc_interval(uint8_t interval) __critical; /* Timer interrupt */ void -ao_timer_isr(void) interrupt 9; +ao_timer_isr(void) __interrupt 9; /* Initialize the timer */ void @@ -198,7 +198,7 @@ ao_adc_get(__xdata struct ao_adc *packet); /* The A/D interrupt handler */ void -ao_adc_isr(void) interrupt 1; +ao_adc_isr(void) __interrupt 1; /* Initialize the A/D converter */ void @@ -293,12 +293,13 @@ ao_led_init(uint8_t enable); * ao_romconfig.c */ -#define AO_ROMCONFIG_VERSION 1 +#define AO_ROMCONFIG_VERSION 2 extern __code __at (0x00a0) uint16_t ao_romconfig_version; extern __code __at (0x00a2) uint16_t ao_romconfig_check; extern __code __at (0x00a4) uint16_t ao_serial_number; extern __code __at (0x00a6) uint32_t ao_radio_cal; +extern __code __at (0x00aa) uint8_t ao_usb_descriptors []; /* * ao_usb.c @@ -324,7 +325,7 @@ ao_usb_flush(void); /* USB interrupt handler */ void -ao_usb_isr(void) interrupt 6; +ao_usb_isr(void) __interrupt 6; /* Enable the USB controller */ void @@ -424,7 +425,7 @@ ao_dma_abort(uint8_t id); /* DMA interrupt routine */ void -ao_dma_isr(void) interrupt 8; +ao_dma_isr(void) __interrupt 8; /* * ao_mutex.c @@ -563,6 +564,7 @@ struct ao_log_record { uint8_t year; uint8_t month; uint8_t day; + uint8_t extra; } gps_date; struct { uint16_t d0; @@ -572,7 +574,7 @@ struct ao_log_record { }; /* Write a record to the eeprom log */ -void +uint8_t ao_log_data(__xdata struct ao_log_record *log) __reentrant; /* Flush the log */ @@ -720,10 +722,10 @@ ao_dbg_init(void); #if HAS_SERIAL_1 void -ao_serial_rx1_isr(void) interrupt 3; +ao_serial_rx1_isr(void) __interrupt 3; void -ao_serial_tx1_isr(void) interrupt 14; +ao_serial_tx1_isr(void) __interrupt 14; char ao_serial_getchar(void) __critical; @@ -859,7 +861,7 @@ extern __xdata uint8_t ao_radio_done; extern __xdata uint8_t ao_radio_mutex; void -ao_radio_general_isr(void) interrupt 16; +ao_radio_general_isr(void) __interrupt 16; void ao_radio_get(void); @@ -1008,7 +1010,7 @@ ao_rssi_init(uint8_t rssi_led); * each instance of a product */ -extern const uint8_t ao_usb_descriptors []; +extern __code __at(0x00aa) uint8_t ao_usb_descriptors []; extern const char ao_version[]; extern const char ao_manufacturer[]; extern const char ao_product[]; diff --git a/src/ao_adc.c b/src/ao_adc.c index 50f96848..49d2519e 100644 --- a/src/ao_adc.c +++ b/src/ao_adc.c @@ -41,7 +41,7 @@ ao_adc_get(__xdata struct ao_adc *packet) } void -ao_adc_isr(void) interrupt 1 +ao_adc_isr(void) __interrupt 1 { uint8_t sequence; uint8_t __xdata *a; diff --git a/src/ao_cmd.c b/src/ao_cmd.c index 4a68fba4..a54a2316 100644 --- a/src/ao_cmd.c +++ b/src/ao_cmd.c @@ -263,13 +263,12 @@ ao_cmd_register(__code struct ao_cmds *cmds) } void -ao_cmd(void *parameters) +ao_cmd(void) { __xdata char c; __xdata uint8_t cmd, cmds; __code struct ao_cmds * __xdata cs; void (*__xdata func)(void); - (void) parameters; lex_echo = 1; for (;;) { diff --git a/src/ao_dma.c b/src/ao_dma.c index 110138b5..946666ab 100644 --- a/src/ao_dma.c +++ b/src/ao_dma.c @@ -112,7 +112,7 @@ ao_dma_abort(uint8_t id) } void -ao_dma_isr(void) interrupt 8 +ao_dma_isr(void) __interrupt 8 { uint8_t id, mask; diff --git a/src/ao_gps_report.c b/src/ao_gps_report.c index cceb79ff..7abc93f5 100644 --- a/src/ao_gps_report.c +++ b/src/ao_gps_report.c @@ -51,12 +51,12 @@ ao_gps_report(void) gps_log.u.gps_altitude.unused = 0xffff; ao_log_data(&gps_log); if (!date_reported && (gps_data.flags & AO_GPS_DATE_VALID)) { - date_reported = 1; gps_log.type = AO_LOG_GPS_DATE; gps_log.u.gps_date.year = gps_data.year; gps_log.u.gps_date.month = gps_data.month; gps_log.u.gps_date.day = gps_data.day; - ao_log_data(&gps_log); + gps_log.u.gps_date.extra = 0; + date_reported = ao_log_data(&gps_log); } } } diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index ae8c7ef7..c822f7fa 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -422,6 +422,7 @@ gps_dump(void) __reentrant printf ("Time: %02d:%02d:%02d\n", ao_gps_data.hour, ao_gps_data.minute, ao_gps_data.second); printf ("Lat/Lon: %ld %ld\n", ao_gps_data.latitude, ao_gps_data.longitude); printf ("Alt: %d\n", ao_gps_data.altitude); + printf ("Flags: 0x%x\n", ao_gps_data.flags); ao_mutex_put(&ao_gps_mutex); } diff --git a/src/ao_log.c b/src/ao_log.c index d550d408..18bdb8c8 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -33,14 +33,16 @@ ao_log_csum(__xdata uint8_t *b) __reentrant return -sum; } -void +uint8_t ao_log_data(__xdata struct ao_log_record *log) __reentrant { + uint8_t wrote = 0; /* set checksum */ log->csum = 0; log->csum = ao_log_csum((__xdata uint8_t *) log); ao_mutex_get(&ao_log_mutex); { if (ao_log_running) { + wrote = 1; ao_ee_write(ao_log_current_pos, (uint8_t *) log, sizeof (struct ao_log_record)); @@ -51,6 +53,7 @@ ao_log_data(__xdata struct ao_log_record *log) __reentrant ao_log_running = 0; } } ao_mutex_put(&ao_log_mutex); + return wrote; } void diff --git a/src/ao_product.c b/src/ao_product.c index f0eb4c07..82d6298f 100644 --- a/src/ao_product.c +++ b/src/ao_product.c @@ -28,7 +28,7 @@ const char ao_product[] = AO_iProduct_STRING; #define LE_WORD(x) ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8)) /* USB descriptors in one giant block of bytes */ -const uint8_t ao_usb_descriptors [] = +__code __at(0x00aa) uint8_t ao_usb_descriptors [] = { /* Device descriptor */ 0x12, diff --git a/src/ao_radio.c b/src/ao_radio.c index 0849349e..f4a9d3b2 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -275,7 +275,7 @@ __xdata uint8_t ao_radio_done; __xdata uint8_t ao_radio_mutex; void -ao_radio_general_isr(void) interrupt 16 +ao_radio_general_isr(void) __interrupt 16 { S1CON &= ~0x03; if (RFIF & RFIF_IM_TIMEOUT) { diff --git a/src/ao_serial.c b/src/ao_serial.c index 3f103766..a48734c2 100644 --- a/src/ao_serial.c +++ b/src/ao_serial.c @@ -21,7 +21,7 @@ volatile __xdata struct ao_fifo ao_usart1_rx_fifo; volatile __xdata struct ao_fifo ao_usart1_tx_fifo; void -ao_serial_rx1_isr(void) interrupt 3 +ao_serial_rx1_isr(void) __interrupt 3 { if (!ao_fifo_full(ao_usart1_rx_fifo)) ao_fifo_insert(ao_usart1_rx_fifo, U1DBUF); @@ -42,7 +42,7 @@ ao_serial_tx1_start(void) } void -ao_serial_tx1_isr(void) interrupt 14 +ao_serial_tx1_isr(void) __interrupt 14 { UTX1IF = 0; ao_serial_tx1_started = 0; diff --git a/src/ao_timer.c b/src/ao_timer.c index d1731475..c977fbc8 100644 --- a/src/ao_timer.c +++ b/src/ao_timer.c @@ -41,7 +41,7 @@ volatile __data uint8_t ao_adc_interval = 1; volatile __data uint8_t ao_adc_count; #endif -void ao_timer_isr(void) interrupt 9 +void ao_timer_isr(void) __interrupt 9 { ++ao_tick_count; #if HAS_ADC diff --git a/src/ao_usb.c b/src/ao_usb.c index f6e0fcf9..b55130f2 100644 --- a/src/ao_usb.c +++ b/src/ao_usb.c @@ -43,7 +43,7 @@ ao_usb_set_interrupts(void) * so when we hook that up, fix this */ void -ao_usb_isr(void) interrupt 6 +ao_usb_isr(void) __interrupt 6 { USBIF = 0; ao_usb_iif |= USBIIF; diff --git a/src/cc1111.h b/src/cc1111.h index e8302df2..20ed052a 100644 --- a/src/cc1111.h +++ b/src/cc1111.h @@ -40,16 +40,16 @@ #include #include -sfr at 0xA8 IEN0; /* Interrupt Enable 0 Register */ +sfr __at 0xA8 IEN0; /* Interrupt Enable 0 Register */ -sbit at 0xA8 RFTXRXIE; /* RF TX/RX done interrupt enable */ -sbit at 0xA9 ADCIE; /* ADC interrupt enable */ -sbit at 0xAA URX0IE; /* USART0 RX interrupt enable */ -sbit at 0xAB URX1IE; /* USART1 RX interrupt enable (shared with I2S RX) */ -sbit at 0xAB I2SRXIE; /* I2S RX interrupt enable (shared with USART1 RX) */ -sbit at 0xAC ENCIE; /* AES encryption/decryption interrupt enable */ -sbit at 0xAD STIE; /* Sleep Timer interrupt enable */ -sbit at 0xAF EA; /* Enable All */ +sbit __at 0xA8 RFTXRXIE; /* RF TX/RX done interrupt enable */ +sbit __at 0xA9 ADCIE; /* ADC interrupt enable */ +sbit __at 0xAA URX0IE; /* USART0 RX interrupt enable */ +sbit __at 0xAB URX1IE; /* USART1 RX interrupt enable (shared with I2S RX) */ +sbit __at 0xAB I2SRXIE; /* I2S RX interrupt enable (shared with USART1 RX) */ +sbit __at 0xAC ENCIE; /* AES encryption/decryption interrupt enable */ +sbit __at 0xAD STIE; /* Sleep Timer interrupt enable */ +sbit __at 0xAF EA; /* Enable All */ #define IEN0_EA (1 << 7) #define IEN0_STIE (1 << 5) @@ -60,7 +60,7 @@ sbit at 0xAF EA; /* Enable All */ #define IEN0_ADCIE (1 << 1) #define IEN0_RFTXRXIE (1 << 0) -sfr at 0xB8 IEN1; /* Interrupt Enable 1 Register */ +sfr __at 0xB8 IEN1; /* Interrupt Enable 1 Register */ #define IEN1_P0IE (1 << 5) /* Port 0 interrupt enable */ #define IEN1_T4IE (1 << 4) /* Timer 4 interrupt enable */ @@ -70,7 +70,7 @@ sfr at 0xB8 IEN1; /* Interrupt Enable 1 Register */ #define IEN1_DMAIE (1 << 0) /* DMA transfer interrupt enable */ /* IEN2 */ -sfr at 0x9A IEN2; /* Interrupt Enable 2 Register */ +sfr __at 0x9A IEN2; /* Interrupt Enable 2 Register */ #define IEN2_WDTIE (1 << 5) /* Watchdog timer interrupt enable */ #define IEN2_P1IE (1 << 4) /* Port 1 interrupt enable */ @@ -82,7 +82,7 @@ sfr at 0x9A IEN2; /* Interrupt Enable 2 Register */ #define IEN2_RFIE (1 << 0) /* RF general interrupt enable */ /* CLKCON 0xC6 */ -sfr at 0xC6 CLKCON; /* Clock Control */ +sfr __at 0xC6 CLKCON; /* Clock Control */ #define CLKCON_OSC32K_RC (1 << 7) #define CLKCON_OSC32K_XTAL (0 << 7) @@ -126,20 +126,20 @@ sfr at 0xC6 CLKCON; /* Clock Control */ #define SLEEP_MODE_MASK (3 << 0) /* PCON 0x87 */ -sfr at 0x87 PCON; /* Power Mode Control Register */ +sfr __at 0x87 PCON; /* Power Mode Control Register */ #define PCON_IDLE (1 << 0) /* * TCON */ -sfr at 0x88 TCON; /* CPU Interrupt Flag 1 */ +sfr __at 0x88 TCON; /* CPU Interrupt Flag 1 */ -sbit at 0x8F URX1IF; /* USART1 RX interrupt flag. Automatically cleared */ -sbit at 0x8F I2SRXIF; /* I2S RX interrupt flag. Automatically cleared */ -sbit at 0x8D ADCIF; /* ADC interrupt flag. Automatically cleared */ -sbit at 0x8B URX0IF; /* USART0 RX interrupt flag. Automatically cleared */ -sbit at 0x89 RFTXRXIF; /* RF TX/RX complete interrupt flag. Automatically cleared */ +sbit __at 0x8F URX1IF; /* USART1 RX interrupt flag. Automatically cleared */ +sbit __at 0x8F I2SRXIF; /* I2S RX interrupt flag. Automatically cleared */ +sbit __at 0x8D ADCIF; /* ADC interrupt flag. Automatically cleared */ +sbit __at 0x8B URX0IF; /* USART0 RX interrupt flag. Automatically cleared */ +sbit __at 0x89 RFTXRXIF; /* RF TX/RX complete interrupt flag. Automatically cleared */ #define TCON_URX1IF (1 << 7) #define TCON_I2SRXIF (1 << 7) @@ -150,10 +150,10 @@ sbit at 0x89 RFTXRXIF; /* RF TX/RX complete interrupt flag. Automatically cleare /* * S0CON */ -sfr at 0x98 S0CON; /* CPU Interrupt Flag 2 */ +sfr __at 0x98 S0CON; /* CPU Interrupt Flag 2 */ -sbit at 0x98 ENCIF_0; /* AES interrupt 0. */ -sbit at 0x99 ENCIF_1; /* AES interrupt 1. */ +sbit __at 0x98 ENCIF_0; /* AES interrupt 0. */ +sbit __at 0x99 ENCIF_1; /* AES interrupt 1. */ #define S0CON_ENCIF_1 (1 << 1) #define S0CON_ENCIF_0 (1 << 0) @@ -161,7 +161,7 @@ sbit at 0x99 ENCIF_1; /* AES interrupt 1. */ /* * S1CON */ -sfr at 0x9B S1CON; /* CPU Interrupt Flag 3 */ +sfr __at 0x9B S1CON; /* CPU Interrupt Flag 3 */ #define S1CON_RFIF_1 (1 << 1) #define S1CON_RFIF_0 (1 << 0) @@ -169,15 +169,15 @@ sfr at 0x9B S1CON; /* CPU Interrupt Flag 3 */ /* * IRCON */ -sfr at 0xC0 IRCON; /* CPU Interrupt Flag 4 */ +sfr __at 0xC0 IRCON; /* CPU Interrupt Flag 4 */ -sbit at 0xC0 DMAIF; /* DMA complete interrupt flag */ -sbit at 0xC1 T1IF; /* Timer 1 interrupt flag. Automatically cleared */ -sbit at 0xC2 T2IF; /* Timer 2 interrupt flag. Automatically cleared */ -sbit at 0xC3 T3IF; /* Timer 3 interrupt flag. Automatically cleared */ -sbit at 0xC4 T4IF; /* Timer 4 interrupt flag. Automatically cleared */ -sbit at 0xC5 P0IF; /* Port0 interrupt flag */ -sbit at 0xC7 STIF; /* Sleep Timer interrupt flag */ +sbit __at 0xC0 DMAIF; /* DMA complete interrupt flag */ +sbit __at 0xC1 T1IF; /* Timer 1 interrupt flag. Automatically cleared */ +sbit __at 0xC2 T2IF; /* Timer 2 interrupt flag. Automatically cleared */ +sbit __at 0xC3 T3IF; /* Timer 3 interrupt flag. Automatically cleared */ +sbit __at 0xC4 T4IF; /* Timer 4 interrupt flag. Automatically cleared */ +sbit __at 0xC5 P0IF; /* Port0 interrupt flag */ +sbit __at 0xC7 STIF; /* Sleep Timer interrupt flag */ #define IRCON_DMAIF (1 << 0) /* DMA complete interrupt flag */ #define IRCON_T1IF (1 << 1) /* Timer 1 interrupt flag. Automatically cleared */ @@ -190,15 +190,15 @@ sbit at 0xC7 STIF; /* Sleep Timer interrupt flag */ /* * IRCON2 */ -sfr at 0xE8 IRCON2; /* CPU Interrupt Flag 5 */ +sfr __at 0xE8 IRCON2; /* CPU Interrupt Flag 5 */ -sbit at 0xE8 USBIF; /* USB interrupt flag (shared with Port2) */ -sbit at 0xE8 P2IF; /* Port2 interrupt flag (shared with USB) */ -sbit at 0xE9 UTX0IF; /* USART0 TX interrupt flag */ -sbit at 0xEA UTX1IF; /* USART1 TX interrupt flag (shared with I2S TX) */ -sbit at 0xEA I2STXIF; /* I2S TX interrupt flag (shared with USART1 TX) */ -sbit at 0xEB P1IF; /* Port1 interrupt flag */ -sbit at 0xEC WDTIF; /* Watchdog timer interrupt flag */ +sbit __at 0xE8 USBIF; /* USB interrupt flag (shared with Port2) */ +sbit __at 0xE8 P2IF; /* Port2 interrupt flag (shared with USB) */ +sbit __at 0xE9 UTX0IF; /* USART0 TX interrupt flag */ +sbit __at 0xEA UTX1IF; /* USART1 TX interrupt flag (shared with I2S TX) */ +sbit __at 0xEA I2STXIF; /* I2S TX interrupt flag (shared with USART1 TX) */ +sbit __at 0xEB P1IF; /* Port1 interrupt flag */ +sbit __at 0xEC WDTIF; /* Watchdog timer interrupt flag */ #define IRCON2_USBIF (1 << 0) /* USB interrupt flag (shared with Port2) */ #define IRCON2_P2IF (1 << 0) /* Port2 interrupt flag (shared with USB) */ @@ -225,8 +225,8 @@ sbit at 0xEC WDTIF; /* Watchdog timer interrupt flag */ * Priority = (IP1 << 1) | IP0. Higher priority interrupts served first */ -sfr at 0xB9 IP1; /* Interrupt Priority 1 */ -sfr at 0xA9 IP0; /* Interrupt Priority 0 */ +sfr __at 0xB9 IP1; /* Interrupt Priority 1 */ +sfr __at 0xA9 IP0; /* Interrupt Priority 0 */ #define IP1_IPG5 (1 << 5) #define IP1_IPG4 (1 << 4) @@ -286,13 +286,13 @@ sfr at 0xA9 IP0; /* Interrupt Priority 0 */ */ /* Timer count */ -sfr at 0xCA T3CNT; -sfr at 0xEA T4CNT; +sfr __at 0xCA T3CNT; +sfr __at 0xEA T4CNT; /* Timer control */ -sfr at 0xCB T3CTL; -sfr at 0xEB T4CTL; +sfr __at 0xCB T3CTL; +sfr __at 0xEB T4CTL; #define TxCTL_DIV_1 (0 << 5) #define TxCTL_DIV_2 (1 << 5) @@ -312,10 +312,10 @@ sfr at 0xEB T4CTL; /* Timer 4 channel 0 compare control */ -sfr at 0xCC T3CCTL0; -sfr at 0xCE T3CCTL1; -sfr at 0xEC T4CCTL0; -sfr at 0xEE T4CCTL1; +sfr __at 0xCC T3CCTL0; +sfr __at 0xCE T3CCTL1; +sfr __at 0xEC T4CCTL0; +sfr __at 0xEE T4CCTL1; #define TxCCTLy_IM (1 << 6) #define TxCCTLy_CMP_SET (0 << 3) @@ -328,16 +328,16 @@ sfr at 0xEE T4CCTL1; #define TxCCTLy_CMP_MODE_ENABLE (1 << 2) /* Timer compare value */ -sfr at 0xCD T3CC0; -sfr at 0xCF T3CC1; -sfr at 0xED T4CC0; -sfr at 0xEF T4CC1; +sfr __at 0xCD T3CC0; +sfr __at 0xCF T3CC1; +sfr __at 0xED T4CC0; +sfr __at 0xEF T4CC1; /* * Peripheral control */ -sfr at 0xf1 PERCFG; +sfr __at 0xf1 PERCFG; #define PERCFG_T1CFG_ALT_1 (0 << 6) #define PERCFG_T1CFG_ALT_2 (1 << 6) #define PERCFG_T1CFG_ALT_MASK (1 << 6)