X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=blobdiff_plain;f=altosui%2FAltosEepromDownload.java;h=f96a3dc90527559b685d2c28b94a090a53ba9467;hp=02fc36f298cfc6922710aaace084a6fa091e1eb0;hb=011615d40b3cb1d1c0ab9fa41e139e263a6a51e7;hpb=3fbefb3eea981d34a09496cf8abf0119de2e35bf diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index 02fc36f2..f96a3dc9 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -32,254 +32,301 @@ import libaltosJNI.*; public class AltosEepromDownload implements Runnable { - static final String[] state_names = { - "startup", - "idle", - "pad", - "boost", - "fast", - "coast", - "drogue", - "main", - "landed", - "invalid", - }; - - int[] ParseHex(String line) { - String[] tokens = line.split("\\s+"); - int[] array = new int[tokens.length]; - - for (int i = 0; i < tokens.length; i++) - try { - array[i] = Integer.parseInt(tokens[i], 16); - } catch (NumberFormatException ne) { - return null; - } - return array; + JFrame frame; + AltosSerial serial_line; + boolean remote; + Thread eeprom_thread; + AltosEepromMonitor monitor; + + int flight; + int year, month, day; + boolean want_file; + FileWriter eeprom_file; + LinkedList eeprom_pending; + + AltosEepromList flights; + ActionListener listener; + boolean success; + ParseException parse_exception; + + private void FlushPending() throws IOException { + for (String s : flights.config_data) { + eeprom_file.write(s); + eeprom_file.write('\n'); + } + + for (String s : eeprom_pending) + eeprom_file.write(s); } - int checksum(int[] line) { - int csum = 0x5a; - for (int i = 1; i < line.length; i++) - csum += line[i]; - return csum & 0xff; + private void CheckFile(boolean force) throws IOException { + if (eeprom_file != null) + return; + if (force || (flight != 0 && want_file)) { + AltosFile eeprom_name; + if (year != 0 && month != 0 && day != 0) + eeprom_name = new AltosFile(year, month, day, flights.config_data.serial, flight, "eeprom"); + else + eeprom_name = new AltosFile(flights.config_data.serial, flight, "eeprom"); + + eeprom_file = new FileWriter(eeprom_name); + if (eeprom_file != null) { + monitor.set_file(eeprom_name.getName()); + FlushPending(); + eeprom_pending = null; + } + } } - void FlushPending(FileWriter file, LinkedList pending) throws IOException { - while (!pending.isEmpty()) { - file.write(pending.remove()); + void Log(AltosEepromRecord r) throws IOException { + if (r.cmd != Altos.AO_LOG_INVALID) { + String log_line = String.format("%c %4x %4x %4x\n", + r.cmd, r.tick, r.a, r.b); + if (eeprom_file != null) + eeprom_file.write(log_line); + else + eeprom_pending.add(log_line); } } - JFrame frame; - AltosDevice device; - AltosSerial serial_line; - boolean remote; - Thread eeprom_thread; - AltosEepromMonitor monitor; + static final int log_full = 1; + static final int log_tiny = 2; - void CaptureLog() throws IOException, InterruptedException, TimeoutException { - int serial = 0; - int block, state_block = 0; - int addr; - int flight = 0; - int year = 0, month = 0, day = 0; - int state = 0; - boolean done = false; - boolean want_file = false; - boolean any_valid; - FileWriter eeprom_file = null; - AltosFile eeprom_name; - LinkedList eeprom_pending = new LinkedList(); - - serial_line.printf("\nc s\nv\n"); - - /* Pull the serial number out of the version information */ - - for (;;) { - String line = serial_line.get_reply(5000); - - if (line == null) - throw new TimeoutException(); - if (line.startsWith("serial-number")) { - try { - serial = Integer.parseInt(line.substring(13).trim()); - } catch (NumberFormatException ne) { - serial = 0; - } - } + boolean done; + int state; - eeprom_pending.add(String.format("%s\n", line)); + void CaptureFull(AltosEepromChunk eechunk) throws IOException { + AltosEepromBlock eeblock = new AltosEepromBlock(eechunk); - /* signals the end of the version info */ - if (line.startsWith("software-version")) - break; + if (eeblock.has_flight) { + flight = eeblock.flight; + monitor.set_flight(flight); + } + if (eeblock.has_date) { + year = eeblock.year; + month = eeblock.month; + day = eeblock.day; + want_file = true; } - if (serial == 0) - throw new IOException("no serial number found"); - monitor.set_serial(serial); - /* Now scan the eeprom, reading blocks of data and converting to .eeprom file form */ + if (eeblock.size() == 0 || + eeblock.has_state && eeblock.state == Altos.ao_flight_landed) + done = true; - state = 0; state_block = 0; - for (block = 0; !done && block < 511; block++) { - serial_line.printf("e %x\n", block); - any_valid = false; - monitor.set_value(state_names[state], state, block - state_block); - for (addr = 0; addr < 0x100;) { - String line = serial_line.get_reply(5000); - if (line == null) - throw new TimeoutException(); - int[] values = ParseHex(line); - - if (values == null) { - System.out.printf("invalid line: %s\n", line); - continue; - } else if (values[0] != addr) { - System.out.printf("data address out of sync at 0x%x\n", - block * 256 + values[0]); - } else if (checksum(values) != 0) { - System.out.printf("invalid checksum at 0x%x\n", - block * 256 + values[0]); - } else { - any_valid = true; - int cmd = values[1]; - int tick = values[3] + (values[4] << 8); - int a = values[5] + (values[6] << 8); - int b = values[7] + (values[8] << 8); - - if (cmd == Altos.AO_LOG_FLIGHT) { - flight = b; - monitor.set_flight(flight); - } + /* Monitor state transitions to update display */ + if (eeblock.has_state) { + if (eeblock.state > Altos.ao_flight_pad) + want_file = true; + if (eeblock.state > state) + state = eeblock.state; + } - /* Monitor state transitions to update display */ - if (cmd == Altos.AO_LOG_STATE && a <= Altos.ao_flight_landed) { - if (a > Altos.ao_flight_pad) - want_file = true; - if (a > state) - state_block = block; - state = a; - } + if (parse_exception == null && eeblock.parse_exception != null) + parse_exception = eeblock.parse_exception; - if (cmd == Altos.AO_LOG_GPS_DATE) { - year = 2000 + (a & 0xff); - month = (a >> 8) & 0xff; - day = (b & 0xff); - want_file = true; - } - - if (eeprom_file == null) { - if (serial != 0 && flight != 0 && want_file) { - if (year != 0 && month != 0 && day != 0) - eeprom_name = new AltosFile(year, month, day, serial, flight, "eeprom"); - else - eeprom_name = new AltosFile(serial, flight, "eeprom"); - - monitor.set_file(eeprom_name.getName()); - eeprom_file = new FileWriter(eeprom_name); - if (eeprom_file != null) { - FlushPending(eeprom_file, eeprom_pending); - eeprom_pending = null; - } - } - } + CheckFile(false); - String log_line = String.format("%c %4x %4x %4x\n", - cmd, tick, a, b); - if (eeprom_file != null) - eeprom_file.write(log_line); - else - eeprom_pending.add(log_line); + for (int record = 0; record < eeblock.size(); record++) + Log(eeblock.get(record)); + } - if (cmd == Altos.AO_LOG_STATE && a == Altos.ao_flight_landed) { + boolean start; + int tiny_tick; + + void CaptureTiny (AltosEepromChunk eechunk) throws IOException { + boolean some_reasonable_data = false; + + for (int i = 0; i < eechunk.data.length; i += 2) { + int v = eechunk.data16(i); + + if (i == 0 && start) { + tiny_tick = 0; + start = false; + flight = v; + Log(new AltosEepromRecord(Altos.AO_LOG_FLIGHT, tiny_tick, 0, v)); + some_reasonable_data = true; + } else { + int s = v ^ 0x8000; + if (Altos.ao_flight_startup <= s && s <= Altos.ao_flight_invalid) { + Log(new AltosEepromRecord(Altos.AO_LOG_STATE, tiny_tick, s, 0)); + if (s == Altos.ao_flight_landed) { done = true; + break; } + some_reasonable_data = true; + } else { + if (v != 0xffff) + some_reasonable_data = true; + Log(new AltosEepromRecord(Altos.AO_LOG_HEIGHT, tiny_tick, v, 0)); + if (state < Altos.ao_flight_drogue) + tiny_tick += 10; + else + tiny_tick += 100; } - addr += 8; } - if (!any_valid) - done = true; } - if (eeprom_file == null) { - eeprom_name = new AltosFile(serial,flight,"eeprom"); - eeprom_file = new FileWriter(eeprom_name); - if (eeprom_file != null) { - FlushPending(eeprom_file, eeprom_pending); + CheckFile(false); + if (!some_reasonable_data) + done = true; + } + + void CaptureLog(AltosEepromLog log) throws IOException, InterruptedException, TimeoutException { + int block, state_block = 0; + int log_style = 0; + + state = 0; + done = false; + start = true; + + if (flights.config_data.serial == 0) + throw new IOException("no serial number found"); + + /* Reset per-capture variables */ + flight = 0; + year = 0; + month = 0; + day = 0; + want_file = false; + eeprom_file = null; + eeprom_pending = new LinkedList(); + + /* Set serial number in the monitor dialog window */ + monitor.set_serial(flights.config_data.serial); + /* Now scan the eeprom, reading blocks of data and converting to .eeprom file form */ + + state = 0; state_block = log.start_block; + for (block = log.start_block; !done && block < log.end_block; block++) { + monitor.set_value(Altos.state_to_string[state], state, block - state_block); + + AltosEepromChunk eechunk = new AltosEepromChunk(serial_line, block); + + /* + * Figure out what kind of data is there + */ + + if (block == log.start_block) { + if (eechunk.data(0) == Altos.AO_LOG_FLIGHT) + log_style = log_full; + else + log_style = log_tiny; + } + + switch (log_style) { + case log_full: + CaptureFull(eechunk); + break; + case log_tiny: + CaptureTiny(eechunk); + break; } } + CheckFile(true); if (eeprom_file != null) { eeprom_file.flush(); eeprom_file.close(); } } - public void run () { - if (remote) { - serial_line.set_radio(); - serial_line.printf("p\nE 0\n"); - serial_line.flush_input(); - } + private void show_message_internal(String message, String title, int message_type) { + JOptionPane.showMessageDialog(frame, + message, + title, + message_type); + } - monitor = new AltosEepromMonitor(frame, Altos.ao_flight_boost, Altos.ao_flight_landed); - monitor.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - eeprom_thread.interrupt(); + private void show_message(String in_message, String in_title, int in_message_type) { + final String message = in_message; + final String title = in_title; + final int message_type = in_message_type; + Runnable r = new Runnable() { + public void run() { + try { + show_message_internal(message, title, message_type); + } catch (Exception ex) { + } } - }); + }; + SwingUtilities.invokeLater(r); + } + + public void run () { + if (remote) + serial_line.start_remote(); + try { - CaptureLog(); + boolean failed = false; + for (AltosEepromLog log : flights) { + parse_exception = null; + if (log.download) { + monitor.reset(); + CaptureLog(log); + } + if (parse_exception != null) { + failed = true; + show_message(String.format("Flight %d download error\n%s\nValid log data saved", + log.flight, + parse_exception.getMessage()), + serial_line.device.toShortString(), + JOptionPane.WARNING_MESSAGE); + } + } + success = !failed; } catch (IOException ee) { - JOptionPane.showMessageDialog(frame, - device.toShortString(), - ee.getLocalizedMessage(), - JOptionPane.ERROR_MESSAGE); + show_message(ee.getLocalizedMessage(), + serial_line.device.toShortString(), + JOptionPane.ERROR_MESSAGE); } catch (InterruptedException ie) { } catch (TimeoutException te) { - JOptionPane.showMessageDialog(frame, - String.format("Connection to \"%s\" failed", - device.toShortString()), - "Connection Failed", - JOptionPane.ERROR_MESSAGE); + show_message(String.format("Connection to \"%s\" failed", + serial_line.device.toShortString()), + "Connection Failed", + JOptionPane.ERROR_MESSAGE); } if (remote) - serial_line.printf("~"); + serial_line.stop_remote(); monitor.done(); serial_line.flush_output(); - serial_line.close(); + if (listener != null) { + Runnable r = new Runnable() { + public void run() { + try { + listener.actionPerformed(new ActionEvent(this, + success ? 1 : 0, + "download")); + } catch (Exception ex) { + } + } + }; + SwingUtilities.invokeLater(r); + } + } + + public void start() { + eeprom_thread = new Thread(this); + eeprom_thread.start(); } - public AltosEepromDownload(JFrame given_frame) { + public void addActionListener(ActionListener l) { + listener = l; + } + + public AltosEepromDownload(JFrame given_frame, + AltosSerial given_serial_line, + boolean given_remote, + AltosEepromList given_flights) { + frame = given_frame; - device = AltosDeviceDialog.show(frame, AltosDevice.product_any); - - remote = false; - - if (device != null) { - try { - serial_line = new AltosSerial(device); - if (!device.matchProduct(AltosDevice.product_telemetrum)) - remote = true; - eeprom_thread = new Thread(this); - eeprom_thread.start(); - } catch (FileNotFoundException ee) { - JOptionPane.showMessageDialog(frame, - String.format("Cannot open device \"%s\"", - device.toShortString()), - "Cannot open target device", - JOptionPane.ERROR_MESSAGE); - } catch (AltosSerialInUseException si) { - JOptionPane.showMessageDialog(frame, - String.format("Device \"%s\" already in use", - device.toShortString()), - "Device in use", - JOptionPane.ERROR_MESSAGE); - } catch (IOException ee) { - JOptionPane.showMessageDialog(frame, - device.toShortString(), - ee.getLocalizedMessage(), - JOptionPane.ERROR_MESSAGE); - } - } + serial_line = given_serial_line; + remote = given_remote; + flights = given_flights; + success = false; + + monitor = new AltosEepromMonitor(frame, Altos.ao_flight_boost, Altos.ao_flight_landed); + monitor.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (eeprom_thread != null) + eeprom_thread.interrupt(); + } + }); } }