From: Keith Packard Date: Mon, 23 Aug 2010 18:53:19 +0000 (-0700) Subject: altosui: Add .ihx file reading code and stub out flashing UI X-Git-Tag: debian/0.6+373+gcf65c6b~37 X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=commitdiff_plain;h=7f8d7978606abe544b1b9b6065c5480ed813b8ec altosui: Add .ihx file reading code and stub out flashing UI Signed-off-by: Keith Packard --- diff --git a/ao-tools/altosui/AltosFlash.java b/ao-tools/altosui/AltosFlash.java new file mode 100644 index 00000000..ac9e81df --- /dev/null +++ b/ao-tools/altosui/AltosFlash.java @@ -0,0 +1,78 @@ +/* + * 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.AltosHexfile; + +public class AltosFlash implements Runnable { + File file; + FileInputStream input; + Thread thread; + AltosHexfile image; + JFrame frame; + + public void run() { + try { + image = new AltosHexfile(input); + System.out.printf("read file start %d length %d\n", + image.address, image.data.length); + } catch (IOException e) { + JOptionPane.showMessageDialog(frame, + file, + e.getMessage(), + JOptionPane.ERROR_MESSAGE); + } + } + + public AltosFlash(JFrame in_frame) { + frame = in_frame; + + JFileChooser hexfile_chooser = new JFileChooser(); + + hexfile_chooser.setDialogTitle("Select Flash Image"); + hexfile_chooser.setFileFilter(new FileNameExtensionFilter("Flash Image", "ihx")); + int returnVal = hexfile_chooser.showOpenDialog(frame); + + if (returnVal == JFileChooser.APPROVE_OPTION) { + file = hexfile_chooser.getSelectedFile(); + if (file != null) { + try { + input = new FileInputStream(file); + thread = new Thread(this); + thread.start(); + } catch (FileNotFoundException ee) { + JOptionPane.showMessageDialog(frame, + file, + "Cannot open flash file", + JOptionPane.ERROR_MESSAGE); + } + } + } + } +} \ No newline at end of file diff --git a/ao-tools/altosui/AltosHexfile.java b/ao-tools/altosui/AltosHexfile.java new file mode 100644 index 00000000..c7078877 --- /dev/null +++ b/ao-tools/altosui/AltosHexfile.java @@ -0,0 +1,248 @@ +/* + * 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.lang.*; +import java.io.*; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.LinkedList; +import java.util.Iterator; +import java.util.Arrays; + +class HexFileInputStream extends PushbackInputStream { + public int line; + + public HexFileInputStream(FileInputStream o) { + super(new BufferedInputStream(o)); + line = 1; + } + + public int read() throws IOException { + int c = super.read(); + if (c == '\n') + line++; + return c; + } + + public void unread(int c) throws IOException { + if (c == '\n') + line--; + if (c != -1) + super.unread(c); + } +} + +class HexRecord implements Comparable { + public int address; + public int type; + public byte checksum; + public byte[] data; + + static final int NORMAL = 0; + static final int EOF = 1; + static final int EXTENDED_ADDRESS = 2; + + enum read_state { + marker, + length, + address, + type, + data, + checksum, + newline, + white, + done, + } + + boolean ishex(int c) { + if ('0' <= c && c <= '9') + return true; + if ('a' <= c && c <= 'f') + return true; + if ('A' <= c && c <= 'F') + return true; + return false; + } + + boolean isspace(int c) { + switch (c) { + case ' ': + case '\t': + return true; + } + return false; + } + + int fromhex(int c) { + if ('0' <= c && c <= '9') + return c - '0'; + if ('a' <= c && c <= 'f') + return c - 'a' + 10; + if ('A' <= c && c <= 'F') + return c - 'A' + 10; + return -1; + } + + public byte checksum() { + byte got = 0; + + got += data.length; + got += (address >> 8) & 0xff; + got += (address ) & 0xff; + got += type; + for (int i = 0; i < data.length; i++) + got += data[i]; + return (byte) (-got); + } + + public int compareTo(Object other) { + HexRecord o = (HexRecord) other; + return address - o.address; + } + + public String toString() { + return String.format("%04x: %02x (%d)", address, type, data.length); + } + + public HexRecord(HexFileInputStream input) throws IOException { + read_state state = read_state.marker; + int nhexbytes = 0; + int hex = 0; + int ndata = 0; + byte got_checksum; + + while (state != read_state.done) { + int c = input.read(); + if (c < 0 && state != read_state.white) + throw new IOException(String.format("%d: Unexpected EOF", input.line)); + if (c == ' ') + continue; + switch (state) { + case marker: + if (c != ':') + throw new IOException("Missing ':'"); + state = read_state.length; + nhexbytes = 2; + hex = 0; + break; + case length: + case address: + case type: + case data: + case checksum: + if(!ishex(c)) + throw new IOException(String.format("Non-hex char '%c'", c)); + hex = hex << 4 | fromhex(c); + --nhexbytes; + if (nhexbytes != 0) + break; + + switch (state) { + case length: + data = new byte[hex]; + state = read_state.address; + nhexbytes = 4; + break; + case address: + address = hex; + state = read_state.type; + nhexbytes = 2; + break; + case type: + type = hex; + if (data.length > 0) + state = read_state.data; + else + state = read_state.checksum; + nhexbytes = 2; + ndata = 0; + break; + case data: + data[ndata] = (byte) hex; + ndata++; + nhexbytes = 2; + if (ndata == data.length) + state = read_state.checksum; + break; + case checksum: + checksum = (byte) hex; + state = read_state.newline; + break; + default: + break; + } + hex = 0; + break; + case newline: + if (c != '\n' && c != '\r') + throw new IOException("Missing newline"); + state = read_state.white; + break; + case white: + if (!isspace(c)) { + input.unread(c); + state = read_state.done; + } + break; + case done: + break; + } + } + got_checksum = checksum(); + if (got_checksum != checksum) + throw new IOException(String.format("Invalid checksum (read 0x%02x computed 0x%02x)\n", + checksum, got_checksum)); + } +} + +public class AltosHexfile { + public int address; + public byte[] data; + + public AltosHexfile(FileInputStream file) throws IOException { + HexFileInputStream input = new HexFileInputStream(file); + LinkedList record_list = new LinkedList(); + boolean done = false; + + while (!done) { + HexRecord record = new HexRecord(input); + + if (record.type == HexRecord.EOF) + done = true; + else + record_list.add(record); + } + HexRecord[] records = record_list.toArray(new HexRecord[0]); + Arrays.sort(records); + if (records.length > 0) { + int base = records[0].address; + int bound = records[records.length-1].address + + records[records.length-1].data.length; + + data = new byte[bound - base]; + address = base; + Arrays.fill(data, (byte) 0xff); + + /* Paint the records into the new array */ + for (int i = 0; i < records.length; i++) { + for (int j = 0; j < records[i].data.length; j++) + data[records[i].address - base + j] = records[i].data[j]; + } + } + } +} \ No newline at end of file diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 49d1f11a..565866ea 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -41,6 +41,7 @@ import altosui.AltosVoice; import altosui.AltosFlightStatusTableModel; import altosui.AltosFlightInfoTableModel; import altosui.AltosChannelMenu; +import altosui.AltosFlash; import libaltosJNI.*; @@ -457,6 +458,11 @@ public class AltosUI extends JFrame { void ConfigureTeleMetrum() { new AltosConfig(AltosUI.this); } + + void FlashImage() { + new AltosFlash(AltosUI.this); + } + /* * Open an existing telemetry file and replay it in realtime */ @@ -589,6 +595,14 @@ public class AltosUI extends JFrame { }); menu.add(item); + item = new JMenuItem("Flash Image",KeyEvent.VK_F); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + FlashImage(); + } + }); + menu.add(item); + item = new JMenuItem("Quit",KeyEvent.VK_Q); item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, ActionEvent.CTRL_MASK)); diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index 541b89e3..ebe59644 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -13,10 +13,12 @@ CLASSFILES=\ AltosEepromReader.class \ AltosEepromRecord.class \ AltosFile.class \ + AltosFlash.class \ AltosFlightInfoTableModel.class \ AltosFlightStatusTableModel.class \ AltosGPS.class \ AltosGreatCircle.class \ + AltosHexfile.class \ AltosLog.class \ AltosParse.class \ AltosPreferences.class \