X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=blobdiff_plain;f=altosui%2FAltosSerial.java;h=4cf306d051e478706294010c90c35c6ce7aae104;hp=6dce6f3d284c3b2326f6990a561dbe80c153a217;hb=31e3255b6cbfaf95c0e97e2d1ec8de72f845994c;hpb=440d52e34364fdeeddc76a2d744cc6d1c934364f diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index 6dce6f3d..4cf306d0 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -25,6 +25,12 @@ import java.lang.*; import java.io.*; import java.util.concurrent.*; import java.util.*; +import java.text.*; +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; +import javax.swing.table.*; import libaltosJNI.*; @@ -36,7 +42,7 @@ import libaltosJNI.*; public class AltosSerial implements Runnable { - static List devices_opened = Collections.synchronizedList(new LinkedList()); + static java.util.List devices_opened = Collections.synchronizedList(new LinkedList()); AltosDevice device; SWIGTYPE_p_altos_file altos; @@ -47,6 +53,17 @@ public class AltosSerial implements Runnable { byte[] line_bytes; int line_count; boolean monitor_mode; + int telemetry; + double frequency; + static boolean debug; + boolean remote; + LinkedList pending_output = new LinkedList(); + Frame frame; + AltosConfigData config_data; + + static void set_debug(boolean new_debug) { + debug = new_debug; + } public void run () { int c; @@ -78,13 +95,14 @@ public class AltosSerial implements Runnable { for (int i = 0; i < line_count; i++) line = line + line_bytes[i]; } - if (line.startsWith("VERSION") || line.startsWith("CRC")) { + if (debug) + System.out.printf("\t\t\t\t\t%s\n", line); + if (line.startsWith("TELEM") || line.startsWith("VERSION") || line.startsWith("CRC")) { for (int e = 0; e < monitors.size(); e++) { LinkedBlockingQueue q = monitors.get(e); q.put(new AltosLine (line)); } } else { -// System.out.printf("GOT: %s\n", line); reply_queue.put(new AltosLine (line)); } line_count = 0; @@ -108,18 +126,76 @@ public class AltosSerial implements Runnable { } public void flush_output() { - if (altos != null) + if (altos != null) { + for (String s : pending_output) + System.out.print(s); + pending_output.clear(); libaltos.altos_flush(altos); + } + } + + boolean abort; + JDialog timeout_dialog; + boolean timeout_started = false; + + private void stop_timeout_dialog() { + if (timeout_started) { + timeout_started = false; + Runnable r = new Runnable() { + public void run() { + timeout_dialog.setVisible(false); + } + }; + SwingUtilities.invokeLater(r); + } + } + + private void start_timeout_dialog_internal() { + + Object[] options = { "Cancel" }; + + JOptionPane pane = new JOptionPane(); + pane.setMessage(String.format("Connecting to %s, %7.3f MHz", device.toShortString(), frequency)); + pane.setOptions(options); + pane.setInitialValue(null); + + timeout_dialog = pane.createDialog(frame, "Connecting..."); + + timeout_dialog.setVisible(true); + + Object o = pane.getValue(); + if (o == null) + return; + if (options[0].equals(o)) + abort = true; + timeout_dialog.dispose(); + timeout_dialog = null; + } + + private boolean check_timeout() { + if (!timeout_started && frame != null) { + if (!SwingUtilities.isEventDispatchThread()) { + timeout_started = true; + Runnable r = new Runnable() { + public void run() { + start_timeout_dialog_internal(); + } + }; + SwingUtilities.invokeLater(r); + } + } + return abort; } - public void flush_input() { + public void flush_input() throws InterruptedException { flush_output(); boolean got_some; + + int timeout = 100; + if (remote) + timeout = 500; do { - try { - Thread.sleep(100); - } catch (InterruptedException ie) { - } + Thread.sleep(timeout); got_some = !reply_queue.isEmpty(); synchronized(this) { if (!"VERSION".startsWith(line) && @@ -130,18 +206,54 @@ public class AltosSerial implements Runnable { } while (got_some); } + int in_reply; + + public String get_reply(int timeout) throws InterruptedException { + boolean can_cancel = true; + String reply = null; + + try { + ++in_reply; + + if (SwingUtilities.isEventDispatchThread()) { + can_cancel = false; + if (remote) + System.out.printf("Uh-oh, reading remote serial device from swing thread\n"); + } + flush_output(); + if (remote && can_cancel) { + timeout = 500; + } + abort = false; + timeout_started = false; + for (;;) { + AltosLine line = reply_queue.poll(timeout, TimeUnit.MILLISECONDS); + if (line != null) { + stop_timeout_dialog(); + reply = line.line; + break; + } + if (!remote || !can_cancel || check_timeout()) { + reply = null; + break; + } + } + } finally { + --in_reply; + } + return reply; + } + public String get_reply() throws InterruptedException { - flush_output(); - AltosLine line = reply_queue.take(); - return line.line; + return get_reply(5000); } - public String get_reply(int timeout) throws InterruptedException { + public String get_reply_no_dialog(int timeout) throws InterruptedException, TimeoutException { flush_output(); AltosLine line = reply_queue.poll(timeout, TimeUnit.MILLISECONDS); - if (line == null) - return null; - return line.line; + if (line != null) + return line.line; + return null; } public void add_monitor(LinkedBlockingQueue q) { @@ -156,6 +268,15 @@ public class AltosSerial implements Runnable { } public void close() { + if (remote) { + try { + stop_remote(); + } catch (InterruptedException ie) { + } + } + if (in_reply != 0) + System.out.printf("Uh-oh. Closing active serial device\n"); + if (altos != null) { libaltos.altos_close(altos); } @@ -174,15 +295,18 @@ public class AltosSerial implements Runnable { synchronized (devices_opened) { devices_opened.remove(device.getPath()); } + if (debug) + System.out.printf("Closing %s\n", device.getPath()); } - public void putc(char c) { + private void putc(char c) { if (altos != null) libaltos.altos_putchar(altos, c); } public void print(String data) { -// System.out.printf("\"%s\" ", data); + if (debug) + pending_output.add(data); for (int i = 0; i < data.length(); i++) putc(data.charAt(i)); } @@ -197,11 +321,15 @@ public class AltosSerial implements Runnable { throw new AltosSerialInUseException(device); devices_opened.add(device.getPath()); } - altos = libaltos.altos_open(device); + altos = device.open(); if (altos == null) { + final String message = device.getErrorString(); close(); - throw new FileNotFoundException(device.toShortString()); + throw new FileNotFoundException(String.format("%s (%s)", + device.toShortString(), message)); } + if (debug) + System.out.printf("Open %s\n", device.getPath()); input_thread = new Thread(this); input_thread.start(); print("~\nE 0\n"); @@ -209,26 +337,65 @@ public class AltosSerial implements Runnable { flush_output(); } - public void set_radio() { - set_channel(AltosPreferences.channel(device.getSerial())); - set_callsign(AltosPreferences.callsign()); + private int telemetry_len() { + return Altos.telemetry_len(telemetry); } - public void set_channel(int channel) { + private void set_channel(int channel) { if (altos != null) { if (monitor_mode) - printf("m 0\nc r %d\nm 1\n", channel); + printf("m 0\nc r %d\nm %x\n", + channel, telemetry_len()); else printf("c r %d\n", channel); flush_output(); } } + private void set_radio_setting(int setting) { + if (altos != null) { + if (monitor_mode) + printf("m 0\nc R %d\nm %x\n", + setting, telemetry_len()); + else + printf("c R %d\n", setting); + flush_output(); + } + } + + public void set_radio_frequency(double frequency, + boolean has_setting, + int cal) { + if (debug) + System.out.printf("set_radio_frequency %7.3f %b %d\n", frequency, has_setting, cal); + if (has_setting) + set_radio_setting(AltosConvert.radio_frequency_to_setting(frequency, cal)); + else + set_channel(AltosConvert.radio_frequency_to_channel(frequency)); + } + + public void set_radio_frequency(double in_frequency) throws InterruptedException, TimeoutException { + frequency = in_frequency; + config_data(); + set_radio_frequency(frequency, + config_data.radio_setting != 0, + config_data.radio_calibration); + } + + public void set_telemetry(int in_telemetry) { + telemetry = in_telemetry; + if (altos != null) { + if (monitor_mode) + printf("m 0\nm %x\n", telemetry_len()); + flush_output(); + } + } + void set_monitor(boolean monitor) { monitor_mode = monitor; if (altos != null) { if (monitor) - printf("m 1\n"); + printf("m %x\n", telemetry_len()); else printf("m 0\n"); flush_output(); @@ -242,20 +409,46 @@ public class AltosSerial implements Runnable { } } - public void start_remote() { - set_radio(); + public AltosConfigData config_data() throws InterruptedException, TimeoutException { + if (config_data == null) + config_data = new AltosConfigData(this); + return config_data; + } + + public void start_remote() throws TimeoutException, InterruptedException { + if (debug) + System.out.printf("start remote %7.3f\n", frequency); + if (frequency == 0.0) + frequency = AltosPreferences.frequency(device.getSerial()); + set_radio_frequency(frequency); + set_callsign(AltosPreferences.callsign()); printf("p\nE 0\n"); flush_input(); + remote = true; + } + + public void stop_remote() throws InterruptedException { + if (debug) + System.out.printf("stop remote\n"); + try { + flush_input(); + } finally { + printf ("~\n"); + flush_output(); + } + remote = false; } - public void stop_remote() { - printf ("~"); + public void set_frame(Frame in_frame) { + frame = in_frame; } public AltosSerial(AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException { device = in_device; line = ""; monitor_mode = false; + frame = null; + telemetry = Altos.ao_telemetry_standard; monitors = new LinkedList> (); reply_queue = new LinkedBlockingQueue (); open();