2 * Copyright © 2017 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
15 package org.altusmetrum.altoslib_11;
20 public class AltosEepromNew {
22 private AltosJson config;
24 private AltosConfigData config_data;
27 * Public accessor APIs
29 public int data8(int offset) {
30 return ((int) data.get(offset)) & 0xff;
33 public int data16(int offset) {
34 return data8(offset) | (data8(offset+1) << 8);
37 public int data24(int offset) {
38 return (data8(offset) |
39 (data8(offset+1) << 8) |
40 (data8(offset+2) << 16));
43 public int data32(int offset) {
44 return (data8(offset) |
45 (data8(offset+1) << 8) |
46 (data8(offset+2) << 16) |
47 (data8(offset+3) << 24));
54 public AltosConfigData config_data() {
55 if (config_data == null) {
56 config_data = (AltosConfigData) config.make(AltosConfigData.class);
57 if (config_data == null)
58 config_data = new AltosConfigData();
60 if (config_data.log_format == AltosLib.AO_LOG_FORMAT_UNKNOWN) {
61 config_data.log_format = AltosLib.AO_LOG_FORMAT_FULL;
62 if (config_data.product != null) {
63 if (config_data.product.startsWith("TeleMetrum"))
64 config_data.log_format = AltosLib.AO_LOG_FORMAT_FULL;
65 else if (config_data.product.startsWith("TeleMini"))
66 config_data.log_format = AltosLib.AO_LOG_FORMAT_TINY;
73 public void reset_config_data() {
77 private void write_config(Writer w) throws IOException {
78 config.write(w, 0, true);
85 private void write_data(Writer w) throws IOException {
86 PrintWriter pw = new PrintWriter(w);
88 for (int i = 0; i < data.size(); i++) {
95 pw.printf("%02x", data.get(i));
100 private boolean read_config(Reader r) throws IOException {
101 config = AltosJson.fromReader(r);
107 private boolean read_data(Reader r) throws IOException {
108 BufferedReader br = new BufferedReader(r);
111 data = new ArrayList<Byte>();
112 while ((s = br.readLine()) != null) {
114 String[] tokens = s.split("\\s+");
116 for (int i = 0; i < tokens.length; i++) {
117 if (tokens[i].length() > 0) {
119 data.add((byte) AltosLib.fromhex(tokens[i]));
120 } catch (NumberFormatException e) {
121 throw new IOException(e.toString());
129 private boolean read_old_config(BufferedReader r) throws IOException {
130 AltosConfigData cfg = new AltosConfigData();
132 boolean done = false;
134 /* The data starts with an upper case F character followed by a space */
136 int first = r.read();
138 int second = r.read();
146 String line = r.readLine();
149 cfg.parse_line(line);
151 config = new AltosJson(cfg);
155 private boolean read_old_data(BufferedReader r) throws IOException {
158 data = new ArrayList<Byte>();
159 while ((line = r.readLine()) != null) {
160 String[] tokens = line.split("\\s+");
162 /* Make sure there's at least a type and time */
163 if (tokens.length < 2)
167 if (tokens[0].length() != 1)
169 int start = data.size();
171 if (config_data().log_format != AltosLib.AO_LOG_FORMAT_TINY) {
172 data.add((byte) tokens[0].codePointAt(0));
174 int time = AltosLib.fromhex(tokens[1]);
177 data.add((byte) (time & 0xff));
178 data.add((byte) (time >> 8));
180 if (tokens.length == 4) {
181 /* Handle ancient log files */
182 if (config_data().log_format == AltosLib.AO_LOG_FORMAT_TINY) {
184 * Ancient TeleMini log files stored "extra" data to pretend
185 * that it was a TeleMetrum device. Throw that away and
186 * just save the actual log data.
188 int a = AltosLib.fromhex(tokens[2]);
189 int b = AltosLib.fromhex(tokens[3]);
192 data.add((byte) (b & 0xff));
193 data.add((byte) ((b >> 8)));
195 for (int i = 2; i < tokens.length; i++) {
196 int v = AltosLib.fromhex(tokens[i]);
197 data.add((byte) (v & 0xff));
198 data.add((byte) ((v >> 8)));
200 /* Re-compute the checksum byte */
201 data.set(start + 1, (byte) (256 - AltosConvert.checksum(data, start, data.size() - start)));
204 for (int i = 2; i < tokens.length; i++)
205 data.add((byte) AltosLib.fromhex(tokens[i]));
206 /* Re-compute the checksum byte */
207 data.set(start + 1, (byte) (256 - AltosConvert.checksum(data, start, data.size() - start)));
213 private void read(Reader r) throws IOException {
214 BufferedReader br = new BufferedReader(r);
221 if (!read_config(br))
222 throw new IOException("failed to read config");
224 throw new IOException("failed to read data");
226 if (!read_old_config(br))
227 throw new IOException("failed to read old config");
228 if (!read_old_data(br))
229 throw new IOException("failed to read old data");
234 * Public APIs for I/O
236 public void write(Writer w) throws IOException {
241 public String toString() {
243 Writer w = new StringWriter();
247 } catch (Exception e) {
252 public void print() throws IOException {
253 System.out.printf("%s", toString());
259 public AltosEepromNew(Reader r) throws IOException {
263 public AltosEepromNew(String s) throws IOException {
264 read(new StringReader(s));
267 public AltosEepromNew(AltosJson config, ArrayList<Byte> data) {
268 this.config = config;
272 public AltosEepromNew(AltosConfigData config_data, ArrayList<Byte> data) {
273 this.config = new AltosJson(config_data);
277 public AltosEepromNew() {